Reference documentation for deal.II version 9.0.0
mapping_manifold.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2016 - 2018 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE at
12 // the top level of the deal.II distribution.
13 //
14 // ---------------------------------------------------------------------
15 
16 
17 #include <deal.II/base/array_view.h>
18 #include <deal.II/base/derivative_form.h>
19 #include <deal.II/base/quadrature.h>
20 #include <deal.II/base/qprojector.h>
21 #include <deal.II/base/quadrature_lib.h>
22 #include <deal.II/base/std_cxx14/memory.h>
23 #include <deal.II/base/tensor_product_polynomials.h>
24 #include <deal.II/base/memory_consumption.h>
25 #include <deal.II/lac/full_matrix.h>
26 #include <deal.II/grid/tria.h>
27 #include <deal.II/grid/tria_iterator.h>
28 #include <deal.II/grid/tria_boundary.h>
29 #include <deal.II/dofs/dof_accessor.h>
30 #include <deal.II/grid/manifold.h>
31 #include <deal.II/fe/fe_tools.h>
32 #include <deal.II/fe/fe.h>
33 #include <deal.II/fe/fe_values.h>
34 #include <deal.II/fe/mapping_manifold.h>
35 #include <deal.II/fe/mapping_q1.h>
36 
37 #include <cmath>
38 #include <algorithm>
39 #include <numeric>
40 #include <array>
41 #include <memory>
42 
43 
44 DEAL_II_NAMESPACE_OPEN
45 
46 template <int dim, int spacedim>
47 std::size_t
49 {
62 }
63 
64 
65 template <int dim, int spacedim>
66 void
68 initialize (const UpdateFlags update_flags,
69  const Quadrature<dim> &q,
70  const unsigned int n_original_q_points)
71 {
72  // store the flags in the internal data object so we can access them
73  // in fill_fe_*_values()
74  this->update_each = update_flags;
75 
76  // Store the quadrature
77  this->quad = q;
78 
79  // Resize the weights
80  this->vertex_weights.resize(GeometryInfo<dim>::vertices_per_cell);
81 
82  // see if we need the (transformation) shape function values
83  // and/or gradients and resize the necessary arrays
85  compute_manifold_quadrature_weights(q);
86 
87  if (this->update_each & update_covariant_transformation)
88  covariant.resize(n_original_q_points);
89 
90  if (this->update_each & update_contravariant_transformation)
91  contravariant.resize(n_original_q_points);
92 
93  if (this->update_each & update_volume_elements)
94  volume_elements.resize(n_original_q_points);
95 }
96 
97 
98 template <int dim, int spacedim>
99 void
101 initialize_face (const UpdateFlags update_flags,
102  const Quadrature<dim> &q,
103  const unsigned int n_original_q_points)
104 {
105  initialize (update_flags, q, n_original_q_points);
106 
107  if (dim > 1)
108  {
109  if (this->update_each & update_boundary_forms)
110  {
111  aux.resize (dim-1, std::vector<Tensor<1,spacedim> > (n_original_q_points));
112 
113  // Compute tangentials to the unit cell.
114  for (unsigned int i=0; i<unit_tangentials.size(); ++i)
115  unit_tangentials[i].resize (n_original_q_points);
116  switch (dim)
117  {
118  case 2:
119  {
120  // ensure a counterclockwise
121  // orientation of tangentials
122  static const int tangential_orientation[4]= {-1,1,1,-1};
123  for (unsigned int i=0; i<GeometryInfo<dim>::faces_per_cell; ++i)
124  {
125  Tensor<1,dim> tang;
126  tang[1-i/2]=tangential_orientation[i];
127  std::fill (unit_tangentials[i].begin(),
128  unit_tangentials[i].end(),
129  tang);
130  }
131  break;
132  }
133  case 3:
134  {
135  for (unsigned int i=0; i<GeometryInfo<dim>::faces_per_cell; ++i)
136  {
137  Tensor<1,dim> tang1, tang2;
138 
139  const unsigned int nd=
141 
142  // first tangential
143  // vector in direction
144  // of the (nd+1)%3 axis
145  // and inverted in case
146  // of unit inward normal
147  tang1[(nd+1)%dim]=GeometryInfo<dim>::unit_normal_orientation[i];
148  // second tangential
149  // vector in direction
150  // of the (nd+2)%3 axis
151  tang2[(nd+2)%dim]=1.;
152 
153  // same unit tangents
154  // for all quadrature
155  // points on this face
156  std::fill (unit_tangentials[i].begin(),
157  unit_tangentials[i].end(), tang1);
158  std::fill (unit_tangentials[GeometryInfo<dim>::faces_per_cell+i].begin(),
159  unit_tangentials[GeometryInfo<dim>::faces_per_cell+i].end(),
160  tang2);
161  }
162  break;
163  }
164  default:
165  Assert(false,ExcNotImplemented());
166  }
167  }
168  }
169 }
170 
171 
172 
173 template <int dim, int spacedim>
175 {}
176 
177 
178 
179 template <int dim, int spacedim>
180 std::unique_ptr<Mapping<dim,spacedim> >
182 {
183  return std_cxx14::make_unique<MappingManifold<dim,spacedim>>(*this);
184 }
185 
186 
187 
188 template <int dim, int spacedim>
192  const Point<spacedim> &) const
193 {
194  Assert(false, ExcNotImplemented());
195  return Point<dim>();
196 }
197 
198 
199 
200 template <int dim, int spacedim>
204  const Point<dim> &p) const
205 {
206  std::array<Point<spacedim>, GeometryInfo<dim>::vertices_per_cell> vertices;
207  std::array<double, GeometryInfo<dim>::vertices_per_cell> weights;
208 
209  for (unsigned int v=0; v<GeometryInfo<dim>::vertices_per_cell; ++v)
210  {
211  vertices[v] = cell->vertex(v);
213  }
214  return cell->get_manifold().get_new_point(make_array_view(vertices.begin(),
215  vertices.end()),
216  make_array_view(weights.begin(),
217  weights.end()));
218 }
219 
220 
221 
222 // In the code below, GCC tries to instantiate MappingManifold<3,4> when
223 // seeing which of the overloaded versions of
224 // do_transform_real_to_unit_cell_internal() to call. This leads to bad
225 // error messages and, generally, nothing very good. Avoid this by ensuring
226 // that this class exists, but does not have an inner InternalData
227 // type, thereby ruling out the codim-1 version of the function
228 // below when doing overload resolution.
229 template <>
230 class MappingManifold<3,4>
231 {};
232 
233 
234 
235 template <int dim, int spacedim>
238 {
239  // add flags if the respective quantities are necessary to compute
240  // what we need. note that some flags appear in both the conditions
241  // and in subsequent set operations. this leads to some circular
242  // logic. the only way to treat this is to iterate. since there are
243  // 5 if-clauses in the loop, it will take at most 5 iterations to
244  // converge. do them:
245  UpdateFlags out = in;
246  for (unsigned int i=0; i<5; ++i)
247  {
248  // The following is a little incorrect:
249  // If not applied on a face,
250  // update_boundary_forms does not
251  // make sense. On the other hand,
252  // it is necessary on a
253  // face. Currently,
254  // update_boundary_forms is simply
255  // ignored for the interior of a
256  // cell.
257  if (out & (update_JxW_values
259  out |= update_boundary_forms;
260 
268 
269  if (out & (update_inverse_jacobians
274 
275  // The contravariant transformation used in the Piola
276  // transformation, which requires the determinant of the Jacobi
277  // matrix of the transformation. Because we have no way of
278  // knowing here whether the finite elements wants to use the
279  // contravariant of the Piola transforms, we add the JxW values
280  // to the list of flags to be updated for each cell.
282  out |= update_JxW_values;
283 
284  if (out & update_normal_vectors)
285  out |= update_JxW_values;
286  }
287 
288  // Now throw an exception if we stumble upon something that was not
289  // implemented yet
290  Assert(!(out & (
295  )), ExcNotImplemented());
296 
297  return out;
298 }
299 
300 
301 
302 template <int dim, int spacedim>
303 std::unique_ptr<typename Mapping<dim,spacedim>::InternalDataBase>
305  const Quadrature<dim> &q) const
306 {
307  auto data = std_cxx14::make_unique<InternalData>();
308  data->initialize (this->requires_update_flags(update_flags), q, q.size());
309 
310  return std::move(data);
311 }
312 
313 
314 
315 template <int dim, int spacedim>
316 std::unique_ptr<typename Mapping<dim,spacedim>::InternalDataBase>
318  const Quadrature<dim-1> &quadrature) const
319 {
320  auto data = std_cxx14::make_unique<InternalData>();
321  data->initialize_face (this->requires_update_flags(update_flags),
323  quadrature.size());
324 
325  return std::move(data);
326 }
327 
328 
329 
330 template <int dim, int spacedim>
331 std::unique_ptr<typename Mapping<dim,spacedim>::InternalDataBase>
333  const Quadrature<dim-1>& quadrature) const
334 {
335  auto data = std_cxx14::make_unique<InternalData>();
336  data->initialize_face (this->requires_update_flags(update_flags),
338  quadrature.size());
339 
340  return std::move(data);
341 }
342 
343 
344 
345 namespace internal
346 {
347  namespace MappingManifoldImplementation
348  {
349  namespace
350  {
357  template <int dim, int spacedim>
358  void
359  maybe_compute_q_points
360  (const typename QProjector<dim>::DataSetDescriptor data_set,
361  const typename ::MappingManifold<dim,spacedim>::InternalData &data,
362  std::vector<Point<spacedim> > &quadrature_points)
363  {
364  const UpdateFlags update_flags = data.update_each;
365 
367 
368  if (update_flags & update_quadrature_points)
369  {
370  for (unsigned int point=0; point<quadrature_points.size(); ++point)
371  {
372  quadrature_points[point] = data.manifold->get_new_point
373  (make_array_view(data.vertices),
374  make_array_view(data.cell_manifold_quadrature_weights[point+data_set]));
375  }
376  }
377  }
378 
379 
380 
386  template <int dim, int spacedim>
387  void
388  maybe_update_Jacobians
389  (const typename ::QProjector<dim>::DataSetDescriptor data_set,
390  const typename ::MappingManifold<dim,spacedim>::InternalData &data)
391  {
392  const UpdateFlags update_flags = data.update_each;
393 
394  if (update_flags & update_contravariant_transformation)
395  {
396  const unsigned int n_q_points = data.contravariant.size();
397 
398  std::fill(data.contravariant.begin(), data.contravariant.end(),
400 
402  data.vertices.size());
403  for (unsigned int point=0; point<n_q_points; ++point)
404  {
405  // Start by figuring out how to compute the direction in
406  // the reference space:
407  const Point<dim> &p = data.quad.point(point+data_set);
408 
409  // And get its image on the manifold:
410  const Point<spacedim> P = data.manifold->get_new_point
411  (make_array_view(data.vertices),
412  make_array_view(data.cell_manifold_quadrature_weights[point+data_set]));
413 
414  // To compute the Jacobian, we choose dim points aligned
415  // with the dim reference axes, which are still in the
416  // given cell, and ask for the tangent vector in these
417  // directions. Choosing the points is somewhat arbitrary,
418  // so we try to be smart and we pick points which are
419  // on the opposite quadrant w.r.t. the evaluation
420  // point.
421  for (unsigned int i=0; i<dim; ++i)
422  {
423  const Point<dim> ei = Point<dim>::unit_vector(i);
424  const double pi = p[i];
425  Assert(pi >=0 && pi <= 1.0,
426  ExcInternalError("Was expecting a quadrature point "
427  "inside the unit reference element."));
428 
429  // In the length L, we store also the direction sign,
430  // which is positive, if the coordinate is < .5,
431  const double L = pi > .5 ? -pi: 1-pi;
432 
433  const Point<dim> np(p + L*ei);
434 
435  // Get the weights to compute the np point in real space
436  for (unsigned int j=0; j<GeometryInfo<dim>::vertices_per_cell; ++j)
437  data.vertex_weights[j] = GeometryInfo<dim>::d_linear_shape_function(np, j);
438 
439  const Point<spacedim> NP=
440  data.manifold->get_new_point(make_array_view(data.vertices),
441  make_array_view(data.vertex_weights));
442 
443  const Tensor<1,spacedim> T = data.manifold->get_tangent_vector(P, NP);
444 
445  for (unsigned int d=0; d<spacedim; ++d)
446  data.contravariant[point][d][i] = T[d]/L;
447  }
448  }
449 
450  if (update_flags & update_covariant_transformation)
451  {
452  const unsigned int n_q_points = data.contravariant.size();
453  for (unsigned int point=0; point<n_q_points; ++point)
454  {
455  data.covariant[point] = (data.contravariant[point]).covariant_form();
456  }
457  }
458 
459  if (update_flags & update_volume_elements)
460  {
461  const unsigned int n_q_points = data.contravariant.size();
462  for (unsigned int point=0; point<n_q_points; ++point)
463  data.volume_elements[point] = data.contravariant[point].determinant();
464  }
465  }
466  }
467  }
468  }
469 }
470 
471 
472 
473 template <int dim, int spacedim>
477  const CellSimilarity::Similarity cell_similarity,
478  const Quadrature<dim> &quadrature,
479  const typename Mapping<dim,spacedim>::InternalDataBase &internal_data,
481 {
482  // ensure that the following static_cast is really correct:
483  Assert (dynamic_cast<const InternalData *>(&internal_data) != nullptr,
484  ExcInternalError());
485  const InternalData &data = static_cast<const InternalData &>(internal_data);
486 
487  const unsigned int n_q_points=quadrature.size();
488 
489  data.store_vertices(cell);
490  data.manifold = &(cell->get_manifold());
491 
492  internal::MappingManifoldImplementation::maybe_compute_q_points<dim,spacedim>
494  data,
495  output_data.quadrature_points);
496 
497  internal::MappingManifoldImplementation::maybe_update_Jacobians<dim,spacedim>
499  data);
500 
501  const UpdateFlags update_flags = data.update_each;
502  const std::vector<double> &weights=quadrature.get_weights();
503 
504  // Multiply quadrature weights by absolute value of Jacobian determinants or
505  // the area element g=sqrt(DX^t DX) in case of codim > 0
506 
507  if (update_flags & (update_normal_vectors
509  {
510  AssertDimension (output_data.JxW_values.size(), n_q_points);
511 
512  Assert( !(update_flags & update_normal_vectors ) ||
513  (output_data.normal_vectors.size() == n_q_points),
514  ExcDimensionMismatch(output_data.normal_vectors.size(), n_q_points));
515 
516 
517  for (unsigned int point=0; point<n_q_points; ++point)
518  {
519 
520  if (dim == spacedim)
521  {
522  const double det = data.contravariant[point].determinant();
523 
524  // check for distorted cells.
525 
526  // TODO: this allows for anisotropies of up to 1e6 in 3D and
527  // 1e12 in 2D. might want to find a finer
528  // (dimension-independent) criterion
529  Assert (det > 1e-12*Utilities::fixed_power<dim>(cell->diameter()/
530  std::sqrt(double(dim))),
531  (typename Mapping<dim,spacedim>::ExcDistortedMappedCell(cell->center(), det, point)));
532 
533  output_data.JxW_values[point] = weights[point] * det;
534  }
535  // if dim==spacedim, then there is no cell normal to
536  // compute. since this is for FEValues (and not FEFaceValues),
537  // there are also no face normals to compute
538  else //codim>0 case
539  {
540  Tensor<1, spacedim> DX_t [dim];
541  for (unsigned int i=0; i<spacedim; ++i)
542  for (unsigned int j=0; j<dim; ++j)
543  DX_t[j][i] = data.contravariant[point][i][j];
544 
545  Tensor<2, dim> G; //First fundamental form
546  for (unsigned int i=0; i<dim; ++i)
547  for (unsigned int j=0; j<dim; ++j)
548  G[i][j] = DX_t[i] * DX_t[j];
549 
550  output_data.JxW_values[point]
551  = std::sqrt(determinant(G)) * weights[point];
552 
553  if (cell_similarity == CellSimilarity::inverted_translation)
554  {
555  // we only need to flip the normal
556  if (update_flags & update_normal_vectors)
557  output_data.normal_vectors[point] *= -1.;
558  }
559  else
560  {
561  if (update_flags & update_normal_vectors)
562  {
563  Assert(spacedim == dim+1,
564  ExcMessage("There is no (unique) cell normal for "
565  + Utilities::int_to_string(dim) +
566  "-dimensional cells in "
567  + Utilities::int_to_string(spacedim) +
568  "-dimensional space. This only works if the "
569  "space dimension is one greater than the "
570  "dimensionality of the mesh cells."));
571 
572  if (dim==1)
573  output_data.normal_vectors[point] =
574  cross_product_2d(-DX_t[0]);
575  else //dim == 2
576  output_data.normal_vectors[point] =
577  cross_product_3d(DX_t[0], DX_t[1]);
578 
579  output_data.normal_vectors[point] /= output_data.normal_vectors[point].norm();
580 
581  if (cell->direction_flag() == false)
582  output_data.normal_vectors[point] *= -1.;
583  }
584 
585  }
586  } //codim>0 case
587 
588  }
589  }
590 
591 
592 
593  // copy values from InternalData to vector given by reference
594  if (update_flags & update_jacobians)
595  {
596  AssertDimension (output_data.jacobians.size(), n_q_points);
597  if (cell_similarity != CellSimilarity::translation)
598  for (unsigned int point=0; point<n_q_points; ++point)
599  output_data.jacobians[point] = data.contravariant[point];
600  }
601 
602  // copy values from InternalData to vector given by reference
603  if (update_flags & update_inverse_jacobians)
604  {
605  AssertDimension (output_data.inverse_jacobians.size(), n_q_points);
606  if (cell_similarity != CellSimilarity::translation)
607  for (unsigned int point=0; point<n_q_points; ++point)
608  output_data.inverse_jacobians[point] = data.covariant[point].transpose();
609  }
610 
611  return cell_similarity;
612 }
613 
614 
615 
616 
617 
618 
619 namespace internal
620 {
621  namespace MappingManifoldImplementation
622  {
623  namespace
624  {
634  template <int dim, int spacedim>
635  void
636  maybe_compute_face_data
637  (const ::MappingManifold<dim,spacedim> &mapping,
638  const typename ::Triangulation<dim,spacedim>::cell_iterator &cell,
639  const unsigned int face_no,
640  const unsigned int subface_no,
641  const unsigned int n_q_points,
642  const std::vector<double> &weights,
643  const typename ::MappingManifold<dim,spacedim>::InternalData &data,
645  {
646  const UpdateFlags update_flags = data.update_each;
647 
648  if (update_flags & update_boundary_forms)
649  {
650  AssertDimension (output_data.boundary_forms.size(), n_q_points);
651  if (update_flags & update_normal_vectors)
652  AssertDimension (output_data.normal_vectors.size(), n_q_points);
653  if (update_flags & update_JxW_values)
654  AssertDimension (output_data.JxW_values.size(), n_q_points);
655 
656  // map the unit tangentials to the real cell. checking for d!=dim-1
657  // eliminates compiler warnings regarding unsigned int expressions <
658  // 0.
659  for (unsigned int d=0; d!=dim-1; ++d)
660  {
662  data.unit_tangentials.size(),
663  ExcInternalError());
664  Assert (data.aux[d].size() <=
665  data.unit_tangentials[face_no+GeometryInfo<dim>::faces_per_cell*d].size(),
666  ExcInternalError());
667 
668  mapping.transform (make_array_view(data.unit_tangentials[face_no+GeometryInfo<dim>::faces_per_cell*d]),
670  data,
671  make_array_view(data.aux[d]));
672  }
673 
674  // if dim==spacedim, we can use the unit tangentials to compute the
675  // boundary form by simply taking the cross product
676  if (dim == spacedim)
677  {
678  for (unsigned int i=0; i<n_q_points; ++i)
679  switch (dim)
680  {
681  case 1:
682  // in 1d, we don't have access to any of the data.aux
683  // fields (because it has only dim-1 components), but we
684  // can still compute the boundary form by simply
685  // looking at the number of the face
686  output_data.boundary_forms[i][0] = (face_no == 0 ?
687  -1 : +1);
688  break;
689  case 2:
690  output_data.boundary_forms[i] =
691  cross_product_2d(data.aux[0][i]);
692  break;
693  case 3:
694  output_data.boundary_forms[i] =
695  cross_product_3d(data.aux[0][i], data.aux[1][i]);
696  break;
697  default:
698  Assert(false, ExcNotImplemented());
699  }
700  }
701  else //(dim < spacedim)
702  {
703  // in the codim-one case, the boundary form results from the
704  // cross product of all the face tangential vectors and the cell
705  // normal vector
706  //
707  // to compute the cell normal, use the same method used in
708  // fill_fe_values for cells above
709  AssertDimension (data.contravariant.size(), n_q_points);
710 
711  for (unsigned int point=0; point<n_q_points; ++point)
712  {
713  switch (dim)
714  {
715  case 1:
716  {
717  // J is a tangent vector
718  output_data.boundary_forms[point] = data.contravariant[point].transpose()[0];
719  output_data.boundary_forms[point] /=
720  (face_no == 0 ? -1. : +1.) * output_data.boundary_forms[point].norm();
721 
722  break;
723  }
724 
725  case 2:
726  {
727  const DerivativeForm<1,spacedim,dim> DX_t =
728  data.contravariant[point].transpose();
729 
730  Tensor<1, spacedim> cell_normal =
731  cross_product_3d(DX_t[0], DX_t[1]);
732  cell_normal /= cell_normal.norm();
733 
734  // then compute the face normal from the face tangent
735  // and the cell normal:
736  output_data.boundary_forms[point] =
737  cross_product_3d(data.aux[0][point], cell_normal);
738 
739  break;
740  }
741 
742  default:
743  Assert (false, ExcNotImplemented());
744  }
745  }
746  }
747 
748  if (update_flags & (update_normal_vectors
750  for (unsigned int i=0; i<output_data.boundary_forms.size(); ++i)
751  {
752  if (update_flags & update_JxW_values)
753  {
754  output_data.JxW_values[i] = output_data.boundary_forms[i].norm() * weights[i];
755 
756  if (subface_no!=numbers::invalid_unsigned_int)
757  {
758  const double area_ratio=GeometryInfo<dim>::subface_ratio(cell->subface_case(face_no),
759  subface_no);
760  output_data.JxW_values[i] *= area_ratio;
761  }
762  }
763 
764  if (update_flags & update_normal_vectors)
765  output_data.normal_vectors[i] = Point<spacedim>(output_data.boundary_forms[i] /
766  output_data.boundary_forms[i].norm());
767  }
768 
769  if (update_flags & update_jacobians)
770  for (unsigned int point=0; point<n_q_points; ++point)
771  output_data.jacobians[point] = data.contravariant[point];
772 
773  if (update_flags & update_inverse_jacobians)
774  for (unsigned int point=0; point<n_q_points; ++point)
775  output_data.inverse_jacobians[point] = data.covariant[point].transpose();
776  }
777  }
778 
779 
786  template <int dim, int spacedim>
787  void
788  do_fill_fe_face_values
789  (const ::MappingManifold<dim,spacedim> &mapping,
790  const typename ::Triangulation<dim,spacedim>::cell_iterator &cell,
791  const unsigned int face_no,
792  const unsigned int subface_no,
793  const typename QProjector<dim>::DataSetDescriptor data_set,
794  const Quadrature<dim-1> &quadrature,
795  const typename ::MappingManifold<dim,spacedim>::InternalData &data,
797  {
798  data.store_vertices(cell);
799 
800  data.manifold = &cell->face(face_no)->get_manifold();
801 
802  maybe_compute_q_points<dim,spacedim> (data_set,
803  data,
804  output_data.quadrature_points);
805  maybe_update_Jacobians<dim,spacedim> (data_set,
806  data);
807 
808  maybe_compute_face_data (mapping,
809  cell, face_no, subface_no, quadrature.size(),
810  quadrature.get_weights(), data,
811  output_data);
812  }
813 
814  template <int dim, int spacedim, int rank>
815  void
816  transform_fields(const ArrayView<const Tensor<rank,dim> > &input,
817  const MappingType mapping_type,
818  const typename Mapping<dim,spacedim>::InternalDataBase &mapping_data,
819  const ArrayView<Tensor<rank,spacedim> > &output)
820  {
821  AssertDimension (input.size(), output.size());
822  Assert ((dynamic_cast<const typename ::MappingManifold<dim,spacedim>::InternalData *>(&mapping_data) != nullptr),
823  ExcInternalError());
824  const typename ::MappingManifold<dim,spacedim>::InternalData
825  &data = static_cast<const typename ::MappingManifold<dim,spacedim>::InternalData &>(mapping_data);
826 
827  switch (mapping_type)
828  {
830  {
831  Assert (data.update_each & update_contravariant_transformation,
832  typename FEValuesBase<dim>::ExcAccessToUninitializedField("update_contravariant_transformation"));
833 
834  for (unsigned int i=0; i<output.size(); ++i)
835  output[i] = apply_transformation(data.contravariant[i], input[i]);
836 
837  return;
838  }
839 
840  case mapping_piola:
841  {
842  Assert (data.update_each & update_contravariant_transformation,
843  typename FEValuesBase<dim>::ExcAccessToUninitializedField("update_contravariant_transformation"));
844  Assert (data.update_each & update_volume_elements,
845  typename FEValuesBase<dim>::ExcAccessToUninitializedField("update_volume_elements"));
846  Assert (rank==1, ExcMessage("Only for rank 1"));
847  if (rank!=1)
848  return;
849 
850  for (unsigned int i=0; i<output.size(); ++i)
851  {
852  output[i] = apply_transformation(data.contravariant[i], input[i]);
853  output[i] /= data.volume_elements[i];
854  }
855  return;
856  }
857  //We still allow this operation as in the
858  //reference cell Derivatives are Tensor
859  //rather than DerivativeForm
860  case mapping_covariant:
861  {
862  Assert (data.update_each & update_contravariant_transformation,
863  typename FEValuesBase<dim>::ExcAccessToUninitializedField("update_covariant_transformation"));
864 
865  for (unsigned int i=0; i<output.size(); ++i)
866  output[i] = apply_transformation(data.covariant[i], input[i]);
867 
868  return;
869  }
870 
871  default:
872  Assert(false, ExcNotImplemented());
873  }
874  }
875 
876 
877  template <int dim, int spacedim, int rank>
878  void
879  transform_gradients(const ArrayView<const Tensor<rank,dim> > &input,
880  const MappingType mapping_type,
881  const typename Mapping<dim,spacedim>::InternalDataBase &mapping_data,
882  const ArrayView<Tensor<rank,spacedim> > &output)
883  {
884  AssertDimension (input.size(), output.size());
885  Assert ((dynamic_cast<const typename ::MappingManifold<dim,spacedim>::InternalData *>(&mapping_data) != nullptr),
886  ExcInternalError());
887  const typename ::MappingManifold<dim,spacedim>::InternalData
888  &data = static_cast<const typename ::MappingManifold<dim,spacedim>::InternalData &>(mapping_data);
889 
890  switch (mapping_type)
891  {
893  {
894  Assert (data.update_each & update_covariant_transformation,
895  typename FEValuesBase<dim>::ExcAccessToUninitializedField("update_covariant_transformation"));
896  Assert (data.update_each & update_contravariant_transformation,
897  typename FEValuesBase<dim>::ExcAccessToUninitializedField("update_contravariant_transformation"));
898  Assert (rank==2, ExcMessage("Only for rank 2"));
899 
900  for (unsigned int i=0; i<output.size(); ++i)
901  {
903  apply_transformation(data.contravariant[i], transpose(input[i]) );
904  output[i] = apply_transformation(data.covariant[i], A.transpose() );
905  }
906 
907  return;
908  }
909 
911  {
912  Assert (data.update_each & update_covariant_transformation,
913  typename FEValuesBase<dim>::ExcAccessToUninitializedField("update_covariant_transformation"));
914  Assert (rank==2, ExcMessage("Only for rank 2"));
915 
916  for (unsigned int i=0; i<output.size(); ++i)
917  {
919  apply_transformation(data.covariant[i], transpose(input[i]) );
920  output[i] = apply_transformation(data.covariant[i], A.transpose() );
921  }
922 
923  return;
924  }
925 
927  {
928  Assert (data.update_each & update_covariant_transformation,
929  typename FEValuesBase<dim>::ExcAccessToUninitializedField("update_covariant_transformation"));
930  Assert (data.update_each & update_contravariant_transformation,
931  typename FEValuesBase<dim>::ExcAccessToUninitializedField("update_contravariant_transformation"));
932  Assert (data.update_each & update_volume_elements,
933  typename FEValuesBase<dim>::ExcAccessToUninitializedField("update_volume_elements"));
934  Assert (rank==2, ExcMessage("Only for rank 2"));
935 
936  for (unsigned int i=0; i<output.size(); ++i)
937  {
939  apply_transformation(data.covariant[i], input[i] );
941  apply_transformation(data.contravariant[i], A.transpose() );
942 
943  output[i] = transpose(T);
944  output[i] /= data.volume_elements[i];
945  }
946 
947  return;
948  }
949 
950  default:
951  Assert(false, ExcNotImplemented());
952  }
953  }
954 
955 
956 
957 
958  template <int dim, int spacedim>
959  void
960  transform_hessians(const ArrayView<const Tensor<3,dim> > &input,
961  const MappingType mapping_type,
962  const typename Mapping<dim,spacedim>::InternalDataBase &mapping_data,
963  const ArrayView<Tensor<3,spacedim> > &output)
964  {
965  AssertDimension (input.size(), output.size());
966  Assert ((dynamic_cast<const typename ::MappingManifold<dim,spacedim>::InternalData *>(&mapping_data) != nullptr),
967  ExcInternalError());
968  const typename ::MappingManifold<dim,spacedim>::InternalData
969  &data = static_cast<const typename ::MappingManifold<dim,spacedim>::InternalData &>(mapping_data);
970 
971  switch (mapping_type)
972  {
974  {
975  Assert (data.update_each & update_covariant_transformation,
976  typename FEValuesBase<dim>::ExcAccessToUninitializedField("update_covariant_transformation"));
977  Assert (data.update_each & update_contravariant_transformation,
978  typename FEValuesBase<dim>::ExcAccessToUninitializedField("update_contravariant_transformation"));
979 
980  for (unsigned int q=0; q<output.size(); ++q)
981  for (unsigned int i=0; i<spacedim; ++i)
982  {
983  double tmp1[dim][dim];
984  for (unsigned int J=0; J<dim; ++J)
985  for (unsigned int K=0; K<dim; ++K)
986  {
987  tmp1[J][K] = data.contravariant[q][i][0] * input[q][0][J][K];
988  for (unsigned int I=1; I<dim; ++I)
989  tmp1[J][K] += data.contravariant[q][i][I] * input[q][I][J][K];
990  }
991  for (unsigned int j=0; j<spacedim; ++j)
992  {
993  double tmp2[dim];
994  for (unsigned int K=0; K<dim; ++K)
995  {
996  tmp2[K] = data.covariant[q][j][0] * tmp1[0][K];
997  for (unsigned int J=1; J<dim; ++J)
998  tmp2[K] += data.covariant[q][j][J] * tmp1[J][K];
999  }
1000  for (unsigned int k=0; k<spacedim; ++k)
1001  {
1002  output[q][i][j][k] = data.covariant[q][k][0] * tmp2[0];
1003  for (unsigned int K=1; K<dim; ++K)
1004  output[q][i][j][k] += data.covariant[q][k][K] * tmp2[K];
1005  }
1006  }
1007  }
1008  return;
1009  }
1010 
1012  {
1013  Assert (data.update_each & update_covariant_transformation,
1014  typename FEValuesBase<dim>::ExcAccessToUninitializedField("update_covariant_transformation"));
1015 
1016  for (unsigned int q=0; q<output.size(); ++q)
1017  for (unsigned int i=0; i<spacedim; ++i)
1018  {
1019  double tmp1[dim][dim];
1020  for (unsigned int J=0; J<dim; ++J)
1021  for (unsigned int K=0; K<dim; ++K)
1022  {
1023  tmp1[J][K] = data.covariant[q][i][0] * input[q][0][J][K];
1024  for (unsigned int I=1; I<dim; ++I)
1025  tmp1[J][K] += data.covariant[q][i][I] * input[q][I][J][K];
1026  }
1027  for (unsigned int j=0; j<spacedim; ++j)
1028  {
1029  double tmp2[dim];
1030  for (unsigned int K=0; K<dim; ++K)
1031  {
1032  tmp2[K] = data.covariant[q][j][0] * tmp1[0][K];
1033  for (unsigned int J=1; J<dim; ++J)
1034  tmp2[K] += data.covariant[q][j][J] * tmp1[J][K];
1035  }
1036  for (unsigned int k=0; k<spacedim; ++k)
1037  {
1038  output[q][i][j][k] = data.covariant[q][k][0] * tmp2[0];
1039  for (unsigned int K=1; K<dim; ++K)
1040  output[q][i][j][k] += data.covariant[q][k][K] * tmp2[K];
1041  }
1042  }
1043  }
1044 
1045  return;
1046  }
1047 
1048  case mapping_piola_hessian:
1049  {
1050  Assert (data.update_each & update_covariant_transformation,
1051  typename FEValuesBase<dim>::ExcAccessToUninitializedField("update_covariant_transformation"));
1052  Assert (data.update_each & update_contravariant_transformation,
1053  typename FEValuesBase<dim>::ExcAccessToUninitializedField("update_contravariant_transformation"));
1054  Assert (data.update_each & update_volume_elements,
1055  typename FEValuesBase<dim>::ExcAccessToUninitializedField("update_volume_elements"));
1056 
1057  for (unsigned int q=0; q<output.size(); ++q)
1058  for (unsigned int i=0; i<spacedim; ++i)
1059  {
1060  double factor[dim];
1061  for (unsigned int I=0; I<dim; ++I)
1062  factor[I] = data.contravariant[q][i][I] / data.volume_elements[q];
1063  double tmp1[dim][dim];
1064  for (unsigned int J=0; J<dim; ++J)
1065  for (unsigned int K=0; K<dim; ++K)
1066  {
1067  tmp1[J][K] = factor[0] * input[q][0][J][K];
1068  for (unsigned int I=1; I<dim; ++I)
1069  tmp1[J][K] += factor[I] * input[q][I][J][K];
1070  }
1071  for (unsigned int j=0; j<spacedim; ++j)
1072  {
1073  double tmp2[dim];
1074  for (unsigned int K=0; K<dim; ++K)
1075  {
1076  tmp2[K] = data.covariant[q][j][0] * tmp1[0][K];
1077  for (unsigned int J=1; J<dim; ++J)
1078  tmp2[K] += data.covariant[q][j][J] * tmp1[J][K];
1079  }
1080  for (unsigned int k=0; k<spacedim; ++k)
1081  {
1082  output[q][i][j][k] = data.covariant[q][k][0] * tmp2[0];
1083  for (unsigned int K=1; K<dim; ++K)
1084  output[q][i][j][k] += data.covariant[q][k][K] * tmp2[K];
1085  }
1086  }
1087  }
1088 
1089  return;
1090  }
1091 
1092  default:
1093  Assert(false, ExcNotImplemented());
1094  }
1095  }
1096 
1097 
1098 
1099 
1100  template <int dim, int spacedim, int rank>
1101  void
1102  transform_differential_forms(const ArrayView<const DerivativeForm<rank, dim,spacedim> > &input,
1103  const MappingType mapping_type,
1104  const typename Mapping<dim,spacedim>::InternalDataBase &mapping_data,
1105  const ArrayView<Tensor<rank+1, spacedim> > &output)
1106  {
1107  AssertDimension (input.size(), output.size());
1108  Assert ((dynamic_cast<const typename ::MappingManifold<dim,spacedim>::InternalData *>(&mapping_data) != nullptr),
1109  ExcInternalError());
1110  const typename ::MappingManifold<dim,spacedim>::InternalData
1111  &data = static_cast<const typename ::MappingManifold<dim,spacedim>::InternalData &>(mapping_data);
1112 
1113  switch (mapping_type)
1114  {
1115  case mapping_covariant:
1116  {
1117  Assert (data.update_each & update_contravariant_transformation,
1118  typename FEValuesBase<dim>::ExcAccessToUninitializedField("update_covariant_transformation"));
1119 
1120  for (unsigned int i=0; i<output.size(); ++i)
1121  output[i] = apply_transformation(data.covariant[i], input[i]);
1122 
1123  return;
1124  }
1125  default:
1126  Assert(false, ExcNotImplemented());
1127  }
1128  }
1129  }
1130  }
1131 }
1132 
1133 
1134 
1135 template <int dim, int spacedim>
1136 void
1139  const unsigned int face_no,
1140  const Quadrature<dim-1> &quadrature,
1141  const typename Mapping<dim,spacedim>::InternalDataBase &internal_data,
1143 {
1144  // ensure that the following cast is really correct:
1145  Assert ((dynamic_cast<const InternalData *>(&internal_data) != nullptr),
1146  ExcInternalError());
1147  const InternalData &data
1148  = static_cast<const InternalData &>(internal_data);
1149 
1150  internal::MappingManifoldImplementation::do_fill_fe_face_values
1151  (*this,
1152  cell, face_no, numbers::invalid_unsigned_int,
1154  cell->face_orientation(face_no),
1155  cell->face_flip(face_no),
1156  cell->face_rotation(face_no),
1157  quadrature.size()),
1158  quadrature,
1159  data,
1160  output_data);
1161 }
1162 
1163 
1164 
1165 template <int dim, int spacedim>
1166 void
1169  const unsigned int face_no,
1170  const unsigned int subface_no,
1171  const Quadrature<dim-1> &quadrature,
1172  const typename Mapping<dim,spacedim>::InternalDataBase &internal_data,
1174 {
1175  // ensure that the following cast is really correct:
1176  Assert ((dynamic_cast<const InternalData *>(&internal_data) != nullptr),
1177  ExcInternalError());
1178  const InternalData &data
1179  = static_cast<const InternalData &>(internal_data);
1180 
1181  internal::MappingManifoldImplementation::do_fill_fe_face_values
1182  (*this,
1183  cell, face_no, subface_no,
1184  QProjector<dim>::DataSetDescriptor::subface (face_no, subface_no,
1185  cell->face_orientation(face_no),
1186  cell->face_flip(face_no),
1187  cell->face_rotation(face_no),
1188  quadrature.size(),
1189  cell->subface_case(face_no)),
1190  quadrature,
1191  data,
1192  output_data);
1193 }
1194 
1195 
1196 
1197 template <int dim, int spacedim>
1198 void
1200 transform (const ArrayView<const Tensor<1, dim> > &input,
1201  const MappingType mapping_type,
1202  const typename Mapping<dim,spacedim>::InternalDataBase &mapping_data,
1203  const ArrayView<Tensor<1, spacedim> > &output) const
1204 {
1205  internal::MappingManifoldImplementation::transform_fields(input, mapping_type, mapping_data, output);
1206 }
1207 
1208 
1209 
1210 template <int dim, int spacedim>
1211 void
1214  const MappingType mapping_type,
1215  const typename Mapping<dim,spacedim>::InternalDataBase &mapping_data,
1216  const ArrayView<Tensor<2, spacedim> > &output) const
1217 {
1218  internal::MappingManifoldImplementation::transform_differential_forms(input, mapping_type, mapping_data, output);
1219 }
1220 
1221 
1222 
1223 template <int dim, int spacedim>
1224 void
1226 transform (const ArrayView<const Tensor<2, dim> > &input,
1227  const MappingType mapping_type,
1228  const typename Mapping<dim,spacedim>::InternalDataBase &mapping_data,
1229  const ArrayView<Tensor<2, spacedim> > &output) const
1230 {
1231  switch (mapping_type)
1232  {
1233  case mapping_contravariant:
1234  internal::MappingManifoldImplementation::transform_fields(input, mapping_type, mapping_data, output);
1235  return;
1236 
1240  internal::MappingManifoldImplementation::transform_gradients(input, mapping_type, mapping_data, output);
1241  return;
1242  default:
1243  Assert(false, ExcNotImplemented());
1244  }
1245 }
1246 
1247 
1248 
1249 template <int dim, int spacedim>
1250 void
1253  const MappingType mapping_type,
1254  const typename Mapping<dim,spacedim>::InternalDataBase &mapping_data,
1255  const ArrayView<Tensor<3,spacedim> > &output) const
1256 {
1257 
1258  AssertDimension (input.size(), output.size());
1259  Assert (dynamic_cast<const InternalData *>(&mapping_data) != nullptr,
1260  ExcInternalError());
1261  const InternalData &data = static_cast<const InternalData &>(mapping_data);
1262 
1263  switch (mapping_type)
1264  {
1266  {
1268  typename FEValuesBase<dim>::ExcAccessToUninitializedField("update_covariant_transformation"));
1269 
1270  for (unsigned int q=0; q<output.size(); ++q)
1271  for (unsigned int i=0; i<spacedim; ++i)
1272  for (unsigned int j=0; j<spacedim; ++j)
1273  {
1274  double tmp[dim];
1275  for (unsigned int K=0; K<dim; ++K)
1276  {
1277  tmp[K] = data.covariant[q][j][0] * input[q][i][0][K];
1278  for (unsigned int J=1; J<dim; ++J)
1279  tmp[K] += data.covariant[q][j][J] * input[q][i][J][K];
1280  }
1281  for (unsigned int k=0; k<spacedim; ++k)
1282  {
1283  output[q][i][j][k] = data.covariant[q][k][0] * tmp[0];
1284  for (unsigned int K=1; K<dim; ++K)
1285  output[q][i][j][k] += data.covariant[q][k][K] * tmp[K];
1286  }
1287  }
1288  return;
1289  }
1290 
1291  default:
1292  Assert(false, ExcNotImplemented());
1293  }
1294 }
1295 
1296 
1297 
1298 template <int dim, int spacedim>
1299 void
1301 transform (const ArrayView<const Tensor<3,dim> > &input,
1302  const MappingType mapping_type,
1303  const typename Mapping<dim,spacedim>::InternalDataBase &mapping_data,
1304  const ArrayView<Tensor<3,spacedim> > &output) const
1305 {
1306  switch (mapping_type)
1307  {
1308  case mapping_piola_hessian:
1311  internal::MappingManifoldImplementation::transform_hessians(input, mapping_type, mapping_data, output);
1312  return;
1313  default:
1314  Assert(false, ExcNotImplemented());
1315  }
1316 }
1317 
1318 //--------------------------- Explicit instantiations -----------------------
1319 #include "mapping_manifold.inst"
1320 
1321 
1322 DEAL_II_NAMESPACE_CLOSE
Transformed quadrature weights.
std::vector< Tensor< 1, spacedim > > normal_vectors
static const unsigned int invalid_unsigned_int
Definition: types.h:173
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
virtual std::unique_ptr< Mapping< dim, spacedim > > clone() const override
#define AssertDimension(dim1, dim2)
Definition: exceptions.h:1248
Number determinant(const SymmetricTensor< 2, dim, Number > &)
Contravariant transformation.
std::vector< DerivativeForm< 1, dim, spacedim > > jacobians
const std::vector< double > & get_weights() const
Point< spacedim > point(const gp_Pnt &p, const double &tolerance=1e-10)
Definition: utilities.cc:183
MappingType
Definition: mapping.h:51
Volume element.
std::array< std::vector< Tensor< 1, dim > >, GeometryInfo< dim >::faces_per_cell *(dim-1)> unit_tangentials
virtual void fill_fe_face_values(const typename Triangulation< dim, spacedim >::cell_iterator &cell, const unsigned int face_no, const Quadrature< dim-1 > &quadrature, const typename Mapping< dim, spacedim >::InternalDataBase &internal_data, ::internal::FEValuesImplementation::MappingRelatedData< dim, spacedim > &output_data) const override
Outer normal vector, not normalized.
Determinant of the Jacobian.
Transformed quadrature points.
void store_vertices(const typename Triangulation< dim, spacedim >::cell_iterator &cell) const
Triangulation< dim, spacedim >::cell_iterator cell
virtual std::size_t memory_consumption() const override
numbers::NumberTraits< Number >::real_type norm() const
Definition: tensor.h:1273
static DataSetDescriptor cell()
Definition: qprojector.h:348
std::vector< Point< spacedim > > vertices
virtual std::unique_ptr< typename Mapping< dim, spacedim >::InternalDataBase > get_subface_data(const UpdateFlags flags, const Quadrature< dim-1 > &quadrature) const override
virtual UpdateFlags requires_update_flags(const UpdateFlags update_flags) const override
static ::ExceptionBase & ExcMessage(std::string arg1)
std::vector< std::vector< Tensor< 1, spacedim > > > aux
#define Assert(cond, exc)
Definition: exceptions.h:1142
UpdateFlags
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
static Point< dim, Number > unit_vector(const unsigned int i)
Abstract base class for mapping classes.
Definition: dof_tools.h:46
void initialize(const UpdateFlags update_flags, const Quadrature< dim > &quadrature, const unsigned int n_original_q_points)
DerivativeForm< 1, spacedim, dim, Number > transpose() const
std::vector< DerivativeForm< 1, dim, spacedim > > covariant
SymmetricTensor< rank_, dim, Number > transpose(const SymmetricTensor< rank_, dim, Number > &t)
Gradient of volume element.
std::string int_to_string(const unsigned int value, const unsigned int digits=numbers::invalid_unsigned_int)
Definition: utilities.cc:98
SymmetricTensor< 2, dim, Number > d(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
std::vector< double > volume_elements
unsigned int size() const
std::vector< DerivativeForm< 1, dim, spacedim > > contravariant
std::vector< double > vertex_weights
std::vector< Point< spacedim > > quadrature_points
SmartPointer< const Manifold< dim, spacedim > > manifold
std::vector< DerivativeForm< 1, spacedim, dim > > inverse_jacobians
Number determinant(const Tensor< 2, dim, Number > &t)
Definition: tensor.h:2001
static double d_linear_shape_function(const Point< dim > &xi, const unsigned int i)
virtual void transform(const ArrayView< const Tensor< 1, dim > > &input, const MappingType type, const typename Mapping< dim, spacedim >::InternalDataBase &internal, const ArrayView< Tensor< 1, spacedim > > &output) const override
Normal vectors.
virtual Point< spacedim > transform_unit_to_real_cell(const typename Triangulation< dim, spacedim >::cell_iterator &cell, const Point< dim > &p) const override
static ::ExceptionBase & ExcNotImplemented()
virtual Point< dim > transform_real_to_unit_cell(const typename Triangulation< dim, spacedim >::cell_iterator &cell, const Point< spacedim > &p) const override
virtual std::unique_ptr< typename Mapping< dim, spacedim >::InternalDataBase > get_data(const UpdateFlags, const Quadrature< dim > &quadrature) const override
void initialize_face(const UpdateFlags update_flags, const Quadrature< dim > &quadrature, const unsigned int n_original_q_points)
virtual std::unique_ptr< typename Mapping< dim, spacedim >::InternalDataBase > get_face_data(const UpdateFlags flags, const Quadrature< dim-1 > &quadrature) const override
std::vector< Tensor< 1, spacedim > > boundary_forms
static double subface_ratio(const internal::SubfaceCase< dim > &subface_case, const unsigned int subface_no)
Covariant transformation.
std::vector< std::vector< double > > cell_manifold_quadrature_weights
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
std::enable_if< std::is_fundamental< T >::value, std::size_t >::type memory_consumption(const T &t)
MappingManifold()=default
UpdateFlags update_each
Definition: mapping.h:562
static ::ExceptionBase & ExcInternalError()