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