Reference documentation for deal.II version 9.0.0
mapping_q_generic.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2000 - 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/table.h>
23 #include <deal.II/base/tensor_product_polynomials.h>
24 #include <deal.II/base/memory_consumption.h>
25 #include <deal.II/base/std_cxx14/memory.h>
26 #include <deal.II/lac/full_matrix.h>
27 #include <deal.II/lac/tensor_product_matrix.h>
28 #include <deal.II/grid/tria.h>
29 #include <deal.II/grid/tria_iterator.h>
30 #include <deal.II/grid/tria_boundary.h>
31 #include <deal.II/grid/manifold_lib.h>
32 #include <deal.II/dofs/dof_accessor.h>
33 #include <deal.II/fe/fe_tools.h>
34 #include <deal.II/fe/fe.h>
35 #include <deal.II/fe/fe_values.h>
36 #include <deal.II/fe/mapping_q_generic.h>
37 #include <deal.II/fe/mapping_q1.h>
38 #include <deal.II/matrix_free/tensor_product_kernels.h>
39 #include <deal.II/matrix_free/shape_info.h>
40 #include <deal.II/matrix_free/evaluation_kernels.h>
41 #include <deal.II/matrix_free/evaluation_selector.h>
42 
43 #include <cmath>
44 #include <algorithm>
45 #include <numeric>
46 #include <array>
47 #include <memory>
48 
49 
50 DEAL_II_NAMESPACE_OPEN
51 
52 
53 namespace internal
54 {
55  namespace MappingQGenericImplementation
56  {
57  namespace
58  {
59  template <int dim>
60  std::vector<unsigned int>
61  get_dpo_vector (const unsigned int degree)
62  {
63  std::vector<unsigned int> dpo(dim+1, 1U);
64  for (unsigned int i=1; i<dpo.size(); ++i)
65  dpo[i]=dpo[i-1]*(degree-1);
66  return dpo;
67  }
68  }
69  }
70 
71  namespace MappingQ1
72  {
73  namespace
74  {
75  // These are left as templates on the spatial dimension (even though dim
76  // == spacedim must be true for them to make sense) because templates are
77  // expanded before the compiler eliminates code due to the 'if (dim ==
78  // spacedim)' statement (see the body of the general
79  // transform_real_to_unit_cell).
80  template <int spacedim>
81  Point<1>
82  transform_real_to_unit_cell
83  (const std::array<Point<spacedim>, GeometryInfo<1>::vertices_per_cell> &vertices,
84  const Point<spacedim> &p)
85  {
86  Assert(spacedim == 1, ExcInternalError());
87  return Point<1>((p[0] - vertices[0](0))/(vertices[1](0) - vertices[0](0)));
88  }
89 
90 
91 
92  template <int spacedim>
93  Point<2>
94  transform_real_to_unit_cell
95  (const std::array<Point<spacedim>, GeometryInfo<2>::vertices_per_cell> &vertices,
96  const Point<spacedim> &p)
97  {
98  Assert(spacedim == 2, ExcInternalError());
99 
100  // For accuracy reasons, we do all arithmetics in extended precision
101  // (long double). This has a noticeable effect on the hit rate for
102  // borderline cases and thus makes the algorithm more robust.
103  const long double x = p(0);
104  const long double y = p(1);
105 
106  const long double x0 = vertices[0](0);
107  const long double x1 = vertices[1](0);
108  const long double x2 = vertices[2](0);
109  const long double x3 = vertices[3](0);
110 
111  const long double y0 = vertices[0](1);
112  const long double y1 = vertices[1](1);
113  const long double y2 = vertices[2](1);
114  const long double y3 = vertices[3](1);
115 
116  const long double a = (x1 - x3)*(y0 - y2) - (x0 - x2)*(y1 - y3);
117  const long double b = -(x0 - x1 - x2 + x3)*y + (x - 2*x1 + x3)*y0 - (x - 2*x0 + x2)*y1
118  - (x - x1)*y2 + (x - x0)*y3;
119  const long double c = (x0 - x1)*y - (x - x1)*y0 + (x - x0)*y1;
120 
121  const long double discriminant = b*b - 4*a*c;
122  // exit if the point is not in the cell (this is the only case where the
123  // discriminant is negative)
124  AssertThrow (discriminant > 0.0,
126 
127  long double eta1;
128  long double eta2;
129  const long double sqrt_discriminant = std::sqrt(discriminant);
130  // special case #1: if a is near-zero to make the discriminant exactly
131  // equal b, then use the linear formula
132  if (b != 0.0 && std::abs(b) == sqrt_discriminant)
133  {
134  eta1 = -c/b;
135  eta2 = -c/b;
136  }
137  // special case #2: a is zero for parallelograms and very small for
138  // near-parallelograms:
139  else if (std::abs(a) < 1e-8*std::abs(b))
140  {
141  // if both a and c are very small then the root should be near
142  // zero: this first case will capture that
143  eta1 = 2*c / (-b - sqrt_discriminant);
144  eta2 = 2*c / (-b + sqrt_discriminant);
145  }
146  // finally, use the plain version:
147  else
148  {
149  eta1 = (-b - sqrt_discriminant) / (2*a);
150  eta2 = (-b + sqrt_discriminant) / (2*a);
151  }
152  // pick the one closer to the center of the cell.
153  const long double eta = (std::abs(eta1 - 0.5) < std::abs(eta2 - 0.5)) ? eta1 : eta2;
154 
155  /*
156  * There are two ways to compute xi from eta, but either one may have a
157  * zero denominator.
158  */
159  const long double subexpr0 = -eta*x2 + x0*(eta - 1);
160  const long double xi_denominator0 = eta*x3 - x1*(eta - 1) + subexpr0;
161  const long double max_x = std::max(std::max(std::abs(x0), std::abs(x1)),
162  std::max(std::abs(x2), std::abs(x3)));
163 
164  if (std::abs(xi_denominator0) > 1e-10*max_x)
165  {
166  const double xi = (x + subexpr0)/xi_denominator0;
167  return Point<2>(xi, eta);
168  }
169  else
170  {
171  const long double max_y = std::max(std::max(std::abs(y0), std::abs(y1)),
172  std::max(std::abs(y2), std::abs(y3)));
173  const long double subexpr1 = -eta*y2 + y0*(eta - 1);
174  const long double xi_denominator1 = eta*y3 - y1*(eta - 1) + subexpr1;
175  if (std::abs(xi_denominator1) > 1e-10*max_y)
176  {
177  const double xi = (subexpr1 + y)/xi_denominator1;
178  return Point<2>(xi, eta);
179  }
180  else // give up and try Newton iteration
181  {
182  AssertThrow (false,
184  }
185  }
186  // bogus return to placate compiler. It should not be possible to get
187  // here.
188  Assert(false, ExcInternalError());
189  return Point<2>(std::numeric_limits<double>::quiet_NaN(),
190  std::numeric_limits<double>::quiet_NaN());
191  }
192 
193 
194 
195  template <int spacedim>
196  Point<3>
197  transform_real_to_unit_cell
198  (const std::array<Point<spacedim>, GeometryInfo<3>::vertices_per_cell> &/*vertices*/,
199  const Point<spacedim> &/*p*/)
200  {
201  // It should not be possible to get here
202  Assert(false, ExcInternalError());
203  return Point<3>();
204  }
205 
206 
207 
208  template <int dim, int spacedim>
209  void compute_shape_function_values_general (const unsigned int n_shape_functions,
210  const std::vector<Point<dim> > &unit_points,
211  typename ::MappingQGeneric<dim,spacedim>::InternalData &data)
212  {
213  const unsigned int n_points=unit_points.size();
214 
215  // Construct the tensor product polynomials used as shape functions for the
216  // Qp mapping of cells at the boundary.
218  tensor_pols (Polynomials::generate_complete_Lagrange_basis(data.line_support_points.get_points()));
219  Assert (n_shape_functions==tensor_pols.n(),
220  ExcInternalError());
221 
222  // then also construct the mapping from lexicographic to the Qp shape function numbering
223  const std::vector<unsigned int>
224  renumber (FETools::
225  lexicographic_to_hierarchic_numbering
226  (FiniteElementData<dim> (internal::MappingQGenericImplementation::get_dpo_vector<dim>
227  (data.polynomial_degree), 1, data.polynomial_degree)));
228 
229  std::vector<double> values;
230  std::vector<Tensor<1,dim> > grads;
231  if (data.shape_values.size()!=0)
232  {
233  Assert(data.shape_values.size()==n_shape_functions*n_points,
234  ExcInternalError());
235  values.resize(n_shape_functions);
236  }
237  if (data.shape_derivatives.size()!=0)
238  {
239  Assert(data.shape_derivatives.size()==n_shape_functions*n_points,
240  ExcInternalError());
241  grads.resize(n_shape_functions);
242  }
243 
244  std::vector<Tensor<2,dim> > grad2;
245  if (data.shape_second_derivatives.size()!=0)
246  {
247  Assert(data.shape_second_derivatives.size()==n_shape_functions*n_points,
248  ExcInternalError());
249  grad2.resize(n_shape_functions);
250  }
251 
252  std::vector<Tensor<3,dim> > grad3;
253  if (data.shape_third_derivatives.size()!=0)
254  {
255  Assert(data.shape_third_derivatives.size()==n_shape_functions*n_points,
256  ExcInternalError());
257  grad3.resize(n_shape_functions);
258  }
259 
260  std::vector<Tensor<4,dim> > grad4;
261  if (data.shape_fourth_derivatives.size()!=0)
262  {
263  Assert(data.shape_fourth_derivatives.size()==n_shape_functions*n_points,
264  ExcInternalError());
265  grad4.resize(n_shape_functions);
266  }
267 
268 
269  if (data.shape_values.size()!=0 ||
270  data.shape_derivatives.size()!=0 ||
271  data.shape_second_derivatives.size()!=0 ||
272  data.shape_third_derivatives.size()!=0 ||
273  data.shape_fourth_derivatives.size()!=0 )
274  for (unsigned int point=0; point<n_points; ++point)
275  {
276  tensor_pols.compute(unit_points[point], values, grads, grad2, grad3, grad4);
277 
278  if (data.shape_values.size()!=0)
279  for (unsigned int i=0; i<n_shape_functions; ++i)
280  data.shape(point,renumber[i]) = values[i];
281 
282  if (data.shape_derivatives.size()!=0)
283  for (unsigned int i=0; i<n_shape_functions; ++i)
284  data.derivative(point,renumber[i]) = grads[i];
285 
286  if (data.shape_second_derivatives.size()!=0)
287  for (unsigned int i=0; i<n_shape_functions; ++i)
288  data.second_derivative(point,renumber[i]) = grad2[i];
289 
290  if (data.shape_third_derivatives.size()!=0)
291  for (unsigned int i=0; i<n_shape_functions; ++i)
292  data.third_derivative(point,renumber[i]) = grad3[i];
293 
294  if (data.shape_fourth_derivatives.size()!=0)
295  for (unsigned int i=0; i<n_shape_functions; ++i)
296  data.fourth_derivative(point,renumber[i]) = grad4[i];
297  }
298  }
299 
300 
301  void
302  compute_shape_function_values_hardcode (const unsigned int n_shape_functions,
303  const std::vector<Point<1> > &unit_points,
305  {
306  (void)n_shape_functions;
307  const unsigned int n_points=unit_points.size();
308  for (unsigned int k = 0 ; k < n_points ; ++k)
309  {
310  double x = unit_points[k](0);
311 
312  if (data.shape_values.size()!=0)
313  {
314  Assert(data.shape_values.size()==n_shape_functions*n_points,
315  ExcInternalError());
316  data.shape(k,0) = 1.-x;
317  data.shape(k,1) = x;
318  }
319  if (data.shape_derivatives.size()!=0)
320  {
321  Assert(data.shape_derivatives.size()==n_shape_functions*n_points,
322  ExcInternalError());
323  data.derivative(k,0)[0] = -1.;
324  data.derivative(k,1)[0] = 1.;
325  }
326  if (data.shape_second_derivatives.size()!=0)
327  {
328  Assert(data.shape_second_derivatives.size()==n_shape_functions*n_points,
329  ExcInternalError());
330  data.second_derivative(k,0)[0][0] = 0;
331  data.second_derivative(k,1)[0][0] = 0;
332  }
333  if (data.shape_third_derivatives.size()!=0)
334  {
335  Assert(data.shape_third_derivatives.size()==n_shape_functions*n_points,
336  ExcInternalError());
337 
338  Tensor<3,1> zero;
339  data.third_derivative(k,0) = zero;
340  data.third_derivative(k,1) = zero;
341  }
342  if (data.shape_fourth_derivatives.size()!=0)
343  {
344  Assert(data.shape_fourth_derivatives.size()==n_shape_functions*n_points,
345  ExcInternalError());
346 
347  Tensor<4,1> zero;
348  data.fourth_derivative(k,0) = zero;
349  data.fourth_derivative(k,1) = zero;
350  }
351  }
352  }
353 
354 
355  void
356  compute_shape_function_values_hardcode (const unsigned int n_shape_functions,
357  const std::vector<Point<2> > &unit_points,
359  {
360 
361  (void)n_shape_functions;
362  const unsigned int n_points=unit_points.size();
363  for (unsigned int k = 0 ; k < n_points ; ++k)
364  {
365  double x = unit_points[k](0);
366  double y = unit_points[k](1);
367 
368  if (data.shape_values.size()!=0)
369  {
370  Assert(data.shape_values.size()==n_shape_functions*n_points,
371  ExcInternalError());
372  data.shape(k,0) = (1.-x)*(1.-y);
373  data.shape(k,1) = x*(1.-y);
374  data.shape(k,2) = (1.-x)*y;
375  data.shape(k,3) = x*y;
376  }
377  if (data.shape_derivatives.size()!=0)
378  {
379  Assert(data.shape_derivatives.size()==n_shape_functions*n_points,
380  ExcInternalError());
381  data.derivative(k,0)[0] = (y-1.);
382  data.derivative(k,1)[0] = (1.-y);
383  data.derivative(k,2)[0] = -y;
384  data.derivative(k,3)[0] = y;
385  data.derivative(k,0)[1] = (x-1.);
386  data.derivative(k,1)[1] = -x;
387  data.derivative(k,2)[1] = (1.-x);
388  data.derivative(k,3)[1] = x;
389  }
390  if (data.shape_second_derivatives.size()!=0)
391  {
392  Assert(data.shape_second_derivatives.size()==n_shape_functions*n_points,
393  ExcInternalError());
394  data.second_derivative(k,0)[0][0] = 0;
395  data.second_derivative(k,1)[0][0] = 0;
396  data.second_derivative(k,2)[0][0] = 0;
397  data.second_derivative(k,3)[0][0] = 0;
398  data.second_derivative(k,0)[0][1] = 1.;
399  data.second_derivative(k,1)[0][1] = -1.;
400  data.second_derivative(k,2)[0][1] = -1.;
401  data.second_derivative(k,3)[0][1] = 1.;
402  data.second_derivative(k,0)[1][0] = 1.;
403  data.second_derivative(k,1)[1][0] = -1.;
404  data.second_derivative(k,2)[1][0] = -1.;
405  data.second_derivative(k,3)[1][0] = 1.;
406  data.second_derivative(k,0)[1][1] = 0;
407  data.second_derivative(k,1)[1][1] = 0;
408  data.second_derivative(k,2)[1][1] = 0;
409  data.second_derivative(k,3)[1][1] = 0;
410  }
411  if (data.shape_third_derivatives.size()!=0)
412  {
413  Assert(data.shape_third_derivatives.size()==n_shape_functions*n_points,
414  ExcInternalError());
415 
416  Tensor<3,2> zero;
417  for (unsigned int i=0; i<4; ++i)
418  data.third_derivative(k,i) = zero;
419  }
420  if (data.shape_fourth_derivatives.size()!=0)
421  {
422  Assert(data.shape_fourth_derivatives.size()==n_shape_functions*n_points,
423  ExcInternalError());
424  Tensor<4,2> zero;
425  for (unsigned int i=0; i<4; ++i)
426  data.fourth_derivative(k,i) = zero;
427  }
428  }
429  }
430 
431 
432 
433  void
434  compute_shape_function_values_hardcode (const unsigned int n_shape_functions,
435  const std::vector<Point<3> > &unit_points,
437  {
438  (void)n_shape_functions;
439  const unsigned int n_points=unit_points.size();
440  for (unsigned int k = 0 ; k < n_points ; ++k)
441  {
442  double x = unit_points[k](0);
443  double y = unit_points[k](1);
444  double z = unit_points[k](2);
445 
446  if (data.shape_values.size()!=0)
447  {
448  Assert(data.shape_values.size()==n_shape_functions*n_points,
449  ExcInternalError());
450  data.shape(k,0) = (1.-x)*(1.-y)*(1.-z);
451  data.shape(k,1) = x*(1.-y)*(1.-z);
452  data.shape(k,2) = (1.-x)*y*(1.-z);
453  data.shape(k,3) = x*y*(1.-z);
454  data.shape(k,4) = (1.-x)*(1.-y)*z;
455  data.shape(k,5) = x*(1.-y)*z;
456  data.shape(k,6) = (1.-x)*y*z;
457  data.shape(k,7) = x*y*z;
458  }
459  if (data.shape_derivatives.size()!=0)
460  {
461  Assert(data.shape_derivatives.size()==n_shape_functions*n_points,
462  ExcInternalError());
463  data.derivative(k,0)[0] = (y-1.)*(1.-z);
464  data.derivative(k,1)[0] = (1.-y)*(1.-z);
465  data.derivative(k,2)[0] = -y*(1.-z);
466  data.derivative(k,3)[0] = y*(1.-z);
467  data.derivative(k,4)[0] = (y-1.)*z;
468  data.derivative(k,5)[0] = (1.-y)*z;
469  data.derivative(k,6)[0] = -y*z;
470  data.derivative(k,7)[0] = y*z;
471  data.derivative(k,0)[1] = (x-1.)*(1.-z);
472  data.derivative(k,1)[1] = -x*(1.-z);
473  data.derivative(k,2)[1] = (1.-x)*(1.-z);
474  data.derivative(k,3)[1] = x*(1.-z);
475  data.derivative(k,4)[1] = (x-1.)*z;
476  data.derivative(k,5)[1] = -x*z;
477  data.derivative(k,6)[1] = (1.-x)*z;
478  data.derivative(k,7)[1] = x*z;
479  data.derivative(k,0)[2] = (x-1)*(1.-y);
480  data.derivative(k,1)[2] = x*(y-1.);
481  data.derivative(k,2)[2] = (x-1.)*y;
482  data.derivative(k,3)[2] = -x*y;
483  data.derivative(k,4)[2] = (1.-x)*(1.-y);
484  data.derivative(k,5)[2] = x*(1.-y);
485  data.derivative(k,6)[2] = (1.-x)*y;
486  data.derivative(k,7)[2] = x*y;
487  }
488  if (data.shape_second_derivatives.size()!=0)
489  {
490  Assert(data.shape_second_derivatives.size()==n_shape_functions*n_points,
491  ExcInternalError());
492  data.second_derivative(k,0)[0][0] = 0;
493  data.second_derivative(k,1)[0][0] = 0;
494  data.second_derivative(k,2)[0][0] = 0;
495  data.second_derivative(k,3)[0][0] = 0;
496  data.second_derivative(k,4)[0][0] = 0;
497  data.second_derivative(k,5)[0][0] = 0;
498  data.second_derivative(k,6)[0][0] = 0;
499  data.second_derivative(k,7)[0][0] = 0;
500  data.second_derivative(k,0)[1][1] = 0;
501  data.second_derivative(k,1)[1][1] = 0;
502  data.second_derivative(k,2)[1][1] = 0;
503  data.second_derivative(k,3)[1][1] = 0;
504  data.second_derivative(k,4)[1][1] = 0;
505  data.second_derivative(k,5)[1][1] = 0;
506  data.second_derivative(k,6)[1][1] = 0;
507  data.second_derivative(k,7)[1][1] = 0;
508  data.second_derivative(k,0)[2][2] = 0;
509  data.second_derivative(k,1)[2][2] = 0;
510  data.second_derivative(k,2)[2][2] = 0;
511  data.second_derivative(k,3)[2][2] = 0;
512  data.second_derivative(k,4)[2][2] = 0;
513  data.second_derivative(k,5)[2][2] = 0;
514  data.second_derivative(k,6)[2][2] = 0;
515  data.second_derivative(k,7)[2][2] = 0;
516 
517  data.second_derivative(k,0)[0][1] = (1.-z);
518  data.second_derivative(k,1)[0][1] = -(1.-z);
519  data.second_derivative(k,2)[0][1] = -(1.-z);
520  data.second_derivative(k,3)[0][1] = (1.-z);
521  data.second_derivative(k,4)[0][1] = z;
522  data.second_derivative(k,5)[0][1] = -z;
523  data.second_derivative(k,6)[0][1] = -z;
524  data.second_derivative(k,7)[0][1] = z;
525  data.second_derivative(k,0)[1][0] = (1.-z);
526  data.second_derivative(k,1)[1][0] = -(1.-z);
527  data.second_derivative(k,2)[1][0] = -(1.-z);
528  data.second_derivative(k,3)[1][0] = (1.-z);
529  data.second_derivative(k,4)[1][0] = z;
530  data.second_derivative(k,5)[1][0] = -z;
531  data.second_derivative(k,6)[1][0] = -z;
532  data.second_derivative(k,7)[1][0] = z;
533 
534  data.second_derivative(k,0)[0][2] = (1.-y);
535  data.second_derivative(k,1)[0][2] = -(1.-y);
536  data.second_derivative(k,2)[0][2] = y;
537  data.second_derivative(k,3)[0][2] = -y;
538  data.second_derivative(k,4)[0][2] = -(1.-y);
539  data.second_derivative(k,5)[0][2] = (1.-y);
540  data.second_derivative(k,6)[0][2] = -y;
541  data.second_derivative(k,7)[0][2] = y;
542  data.second_derivative(k,0)[2][0] = (1.-y);
543  data.second_derivative(k,1)[2][0] = -(1.-y);
544  data.second_derivative(k,2)[2][0] = y;
545  data.second_derivative(k,3)[2][0] = -y;
546  data.second_derivative(k,4)[2][0] = -(1.-y);
547  data.second_derivative(k,5)[2][0] = (1.-y);
548  data.second_derivative(k,6)[2][0] = -y;
549  data.second_derivative(k,7)[2][0] = y;
550 
551  data.second_derivative(k,0)[1][2] = (1.-x);
552  data.second_derivative(k,1)[1][2] = x;
553  data.second_derivative(k,2)[1][2] = -(1.-x);
554  data.second_derivative(k,3)[1][2] = -x;
555  data.second_derivative(k,4)[1][2] = -(1.-x);
556  data.second_derivative(k,5)[1][2] = -x;
557  data.second_derivative(k,6)[1][2] = (1.-x);
558  data.second_derivative(k,7)[1][2] = x;
559  data.second_derivative(k,0)[2][1] = (1.-x);
560  data.second_derivative(k,1)[2][1] = x;
561  data.second_derivative(k,2)[2][1] = -(1.-x);
562  data.second_derivative(k,3)[2][1] = -x;
563  data.second_derivative(k,4)[2][1] = -(1.-x);
564  data.second_derivative(k,5)[2][1] = -x;
565  data.second_derivative(k,6)[2][1] = (1.-x);
566  data.second_derivative(k,7)[2][1] = x;
567  }
568  if (data.shape_third_derivatives.size()!=0)
569  {
570  Assert(data.shape_third_derivatives.size()==n_shape_functions*n_points,
571  ExcInternalError());
572 
573  for (unsigned int i=0; i<3; ++i)
574  for (unsigned int j=0; j<3; ++j)
575  for (unsigned int l=0; l<3; ++l)
576  if ((i==j)||(j==l)||(l==i))
577  {
578  for (unsigned int m=0; m<8; ++m)
579  data.third_derivative(k,m)[i][j][l] = 0;
580  }
581  else
582  {
583  data.third_derivative(k,0)[i][j][l] = -1.;
584  data.third_derivative(k,1)[i][j][l] = 1.;
585  data.third_derivative(k,2)[i][j][l] = 1.;
586  data.third_derivative(k,3)[i][j][l] = -1.;
587  data.third_derivative(k,4)[i][j][l] = 1.;
588  data.third_derivative(k,5)[i][j][l] = -1.;
589  data.third_derivative(k,6)[i][j][l] = -1.;
590  data.third_derivative(k,7)[i][j][l] = 1.;
591  }
592 
593  }
594  if (data.shape_fourth_derivatives.size()!=0)
595  {
596  Assert(data.shape_fourth_derivatives.size()==n_shape_functions*n_points,
597  ExcInternalError());
598  Tensor<4,3> zero;
599  for (unsigned int i=0; i<8; ++i)
600  data.fourth_derivative(k,i) = zero;
601  }
602  }
603  }
604  }
605  }
606 }
607 
608 
609 
610 template <int dim, int spacedim>
611 MappingQGeneric<dim,spacedim>::InternalData::InternalData (const unsigned int polynomial_degree)
612  :
613  polynomial_degree (polynomial_degree),
614  n_shape_functions (Utilities::fixed_power<dim>(polynomial_degree+1)),
615  line_support_points(QGaussLobatto<1>(polynomial_degree+1)),
616  tensor_product_quadrature(false)
617 {}
618 
619 
620 
621 template <int dim, int spacedim>
622 std::size_t
624 {
627  MemoryConsumption::memory_consumption (shape_derivatives) +
629  MemoryConsumption::memory_consumption (contravariant) +
630  MemoryConsumption::memory_consumption (unit_tangentials) +
632  MemoryConsumption::memory_consumption (mapping_support_points) +
633  MemoryConsumption::memory_consumption (cell_of_current_support_points) +
634  MemoryConsumption::memory_consumption (volume_elements) +
636  MemoryConsumption::memory_consumption (n_shape_functions));
637 }
638 
639 
640 template <int dim, int spacedim>
641 void
643 initialize (const UpdateFlags update_flags,
644  const Quadrature<dim> &q,
645  const unsigned int n_original_q_points)
646 {
647  // store the flags in the internal data object so we can access them
648  // in fill_fe_*_values()
649  this->update_each = update_flags;
650 
651  const unsigned int n_q_points = q.size();
652 
653  // see if we need the (transformation) shape function values
654  // and/or gradients and resize the necessary arrays
655  if (this->update_each & update_quadrature_points)
656  shape_values.resize(n_shape_functions * n_q_points);
657 
658  if (this->update_each & (update_covariant_transformation
671  shape_derivatives.resize(n_shape_functions * n_q_points);
672 
673  if (this->update_each & update_covariant_transformation)
674  covariant.resize(n_original_q_points);
675 
676  if (this->update_each & update_contravariant_transformation)
677  contravariant.resize(n_original_q_points);
678 
679  if (this->update_each & update_volume_elements)
680  volume_elements.resize(n_original_q_points);
681 
682  if (this->update_each &
684  shape_second_derivatives.resize(n_shape_functions * n_q_points);
685 
686  if (this->update_each &
688  shape_third_derivatives.resize(n_shape_functions * n_q_points);
689 
690  if (this->update_each &
692  shape_fourth_derivatives.resize(n_shape_functions * n_q_points);
693 
694  const std::vector<Point<dim> > &ref_q_points = q.get_points();
695  // now also fill the various fields with their correct values
696  compute_shape_function_values (ref_q_points);
697 
698  tensor_product_quadrature = q.is_tensor_product();
699 
700  if (dim>1)
701  {
702  // find out if the one-dimensional formula is the same
703  // in all directions
704  if (tensor_product_quadrature)
705  {
706  const std::array<Quadrature<1>, dim> quad_array = q.get_tensor_basis();
707  for (unsigned int i=1; i<dim && tensor_product_quadrature; ++i)
708  {
709  if (quad_array[i-1].size() != quad_array[i].size())
710  {
711  tensor_product_quadrature = false;
712  break;
713  }
714  else
715  {
716  const std::vector<Point<1>> &points_1 = quad_array[i-1].get_points();
717  const std::vector<Point<1>> &points_2 = quad_array[i].get_points();
718  const std::vector<double> &weights_1 = quad_array[i-1].get_weights();
719  const std::vector<double> &weights_2 = quad_array[i].get_weights();
720  for (unsigned int j=0; j<quad_array[i].size(); ++j)
721  {
722  if (std::abs(points_1[j][0]-points_2[j][0])>1.e-10
723  || std::abs(weights_1[j]-weights_2[j])>1.e-10)
724  {
725  tensor_product_quadrature = false;
726  break;
727  }
728 
729  }
730  }
731  }
732 
733  if (tensor_product_quadrature)
734  {
735  const FE_Q<dim> fe(polynomial_degree);
736  shape_info.reinit(q.get_tensor_basis()[0], fe);
737 
738  const unsigned int n_shape_values = fe.n_dofs_per_cell();
739  const unsigned int max_size = std::max(n_q_points,n_shape_values);
740  const unsigned int vec_length = ::VectorizedArray<double>::n_array_elements;
741  const unsigned int n_comp = 1+ (spacedim-1)/vec_length;
742 
743  scratch.resize((dim-1)*max_size);
744  values_dofs.resize(n_comp*n_shape_values);
745  }
746  }
747  }
748 }
749 
750 
751 
752 template <int dim, int spacedim>
753 void
755 initialize_face (const UpdateFlags update_flags,
756  const Quadrature<dim> &q,
757  const unsigned int n_original_q_points)
758 {
759  initialize (update_flags, q, n_original_q_points);
760 
761  if (dim>1 && tensor_product_quadrature)
762  {
763  const unsigned int facedim = dim > 1 ? dim-1 : 1;
765  shape_info.reinit(q.get_tensor_basis()[0], fe);
766 
767  const unsigned int n_shape_values = fe.n_dofs_per_cell();
768  const unsigned int n_q_points = q.size();
769  const unsigned int max_size = std::max(n_q_points,n_shape_values);
770  const unsigned int vec_length = VectorizedArray<double>::n_array_elements;
771  const unsigned int n_comp = 1+ (spacedim-1)/vec_length;
772 
773  scratch.resize((dim-1)*max_size);
774  values_dofs.resize(n_comp*n_shape_values);
775  }
776 
777  if (dim > 1)
778  {
779  if (this->update_each & (update_boundary_forms |
784  {
785  aux.resize (dim-1, std::vector<Tensor<1,spacedim> > (n_original_q_points));
786 
787  // Compute tangentials to the unit cell.
788  for (unsigned int i=0; i<unit_tangentials.size(); ++i)
789  unit_tangentials[i].resize (n_original_q_points);
790  switch (dim)
791  {
792  case 2:
793  {
794  // ensure a counterclockwise orientation of tangentials
795  static const int tangential_orientation[4]= {-1,1,1,-1};
796  for (unsigned int i=0; i<GeometryInfo<dim>::faces_per_cell; ++i)
797  {
798  Tensor<1,dim> tang;
799  tang[1-i/2] = tangential_orientation[i];
800  std::fill (unit_tangentials[i].begin(),
801  unit_tangentials[i].end(),
802  tang);
803  }
804 
805  break;
806  }
807 
808  case 3:
809  {
810  for (unsigned int i=0; i<GeometryInfo<dim>::faces_per_cell; ++i)
811  {
812  Tensor<1,dim> tang1, tang2;
813 
814  const unsigned int nd=
816 
817  // first tangential
818  // vector in direction
819  // of the (nd+1)%3 axis
820  // and inverted in case
821  // of unit inward normal
822  tang1[(nd+1)%dim]=GeometryInfo<dim>::unit_normal_orientation[i];
823  // second tangential
824  // vector in direction
825  // of the (nd+2)%3 axis
826  tang2[(nd+2)%dim]=1.;
827 
828  // same unit tangents
829  // for all quadrature
830  // points on this face
831  std::fill (unit_tangentials[i].begin(),
832  unit_tangentials[i].end(),
833  tang1);
834  std::fill (unit_tangentials[GeometryInfo<dim>::faces_per_cell+i].begin(),
835  unit_tangentials[GeometryInfo<dim>::faces_per_cell+i].end(),
836  tang2);
837  }
838 
839  break;
840  }
841 
842  default:
843  Assert (false, ExcNotImplemented());
844  }
845  }
846  }
847 }
848 
849 
850 
851 
852 
853 template <>
854 void
856 compute_shape_function_values (const std::vector<Point<1> > &unit_points)
857 {
858  // if the polynomial degree is one, then we can simplify code a bit
859  // by using hard-coded shape functions.
860  if (polynomial_degree == 1)
861  internal::MappingQ1::compute_shape_function_values_hardcode (n_shape_functions,
862  unit_points, *this);
863  else
864  {
865  // otherwise ask an object that describes the polynomial space
866  internal::MappingQ1::compute_shape_function_values_general<1,1>(n_shape_functions,
867  unit_points,*this);
868  }
869 }
870 
871 template <>
872 void
874 compute_shape_function_values (const std::vector<Point<2> > &unit_points)
875 {
876  // if the polynomial degree is one, then we can simplify code a bit
877  // by using hard-coded shape functions.
878  if (polynomial_degree == 1)
879  internal::MappingQ1::compute_shape_function_values_hardcode (n_shape_functions,
880  unit_points, *this);
881  else
882  {
883  // otherwise ask an object that describes the polynomial space
884  internal::MappingQ1::compute_shape_function_values_general<2,2>(n_shape_functions,
885  unit_points,*this);
886  }
887 }
888 
889 template <>
890 void
892 compute_shape_function_values (const std::vector<Point<3> > &unit_points)
893 {
894  // if the polynomial degree is one, then we can simplify code a bit
895  // by using hard-coded shape functions.
896  if (polynomial_degree == 1)
897  internal::MappingQ1::compute_shape_function_values_hardcode (n_shape_functions,
898  unit_points, *this);
899  else
900  {
901  // otherwise ask an object that describes the polynomial space
902  internal::MappingQ1::compute_shape_function_values_general<3,3>(n_shape_functions,
903  unit_points,*this);
904  }
905 }
906 
907 template <int dim, int spacedim>
908 void
910 compute_shape_function_values (const std::vector<Point<dim> > &unit_points)
911 {
912  // for non-matching combinations of dim and spacedim, just run the general
913  // case
914  internal::MappingQ1::compute_shape_function_values_general<dim,spacedim>(n_shape_functions,
915  unit_points,*this);
916 }
917 
918 
919 namespace internal
920 {
921  namespace MappingQGenericImplementation
922  {
923  namespace
924  {
933  compute_support_point_weights_on_quad(const unsigned int polynomial_degree)
934  {
935  ::Table<2,double> loqvs;
936 
937  // we are asked to compute weights for interior support points, but
938  // there are no interior points if degree==1
939  if (polynomial_degree == 1)
940  return loqvs;
941 
942  const unsigned int M = polynomial_degree-1;
943  const unsigned int n_inner_2d = M*M;
944  const unsigned int n_outer_2d = 4 + 4*M;
945 
946  // set the weights of transfinite interpolation
947  loqvs.reinit(n_inner_2d, n_outer_2d);
949  for (unsigned int i=0; i<M; ++i)
950  for (unsigned int j=0; j<M; ++j)
951  {
952  const Point<2> p = gl.point((i+1)*(polynomial_degree+1)+(j+1));
953  const unsigned int index_table = i*M+j;
954  for (unsigned int v=0; v<4; ++v)
955  loqvs(index_table, v) =
957  loqvs(index_table, 4+i) = 1.-p[0];
958  loqvs(index_table, 4+i+M) = p[0];
959  loqvs(index_table, 4+j+2*M) = 1.-p[1];
960  loqvs(index_table, 4+j+3*M) = p[1];
961  }
962 
963  // the sum of weights of the points at the outer rim should be one. check
964  // this
965  for (unsigned int unit_point=0; unit_point<n_inner_2d; ++unit_point)
966  Assert(std::fabs(std::accumulate(loqvs[unit_point].begin(),
967  loqvs[unit_point].end(),0.) - 1)<1e-13*polynomial_degree,
968  ExcInternalError());
969 
970  return loqvs;
971  }
972 
973 
974 
982  compute_support_point_weights_on_hex(const unsigned int polynomial_degree)
983  {
984  ::Table<2,double> lohvs;
985 
986  // we are asked to compute weights for interior support points, but
987  // there are no interior points if degree==1
988  if (polynomial_degree == 1)
989  return lohvs;
990 
991  const unsigned int M = polynomial_degree-1;
992 
993  const unsigned int n_inner = Utilities::fixed_power<3>(M);
994  const unsigned int n_outer = 8+12*M+6*M*M;
995 
996  // set the weights of transfinite interpolation
997  lohvs.reinit(n_inner, n_outer);
999  for (unsigned int i=0; i<M; ++i)
1000  for (unsigned int j=0; j<M; ++j)
1001  for (unsigned int k=0; k<M; ++k)
1002  {
1003  const Point<3> p = gl.point((i+1)*(M+2)*(M+2)+(j+1)*(M+2)+(k+1));
1004  const unsigned int index_table = i*M*M+j*M+k;
1005 
1006  // vertices
1007  for (unsigned int v=0; v<8; ++v)
1008  lohvs(index_table, v) =
1010 
1011  // lines
1012  {
1013  constexpr std::array<unsigned int,4> line_coordinates_y
1014  ({{0, 1, 4, 5}});
1015  const Point<2> py(p[0], p[2]);
1016  for (unsigned int l=0; l<4; ++l)
1017  lohvs(index_table, 8+line_coordinates_y[l]*M+j) =
1019  }
1020 
1021  {
1022  constexpr std::array<unsigned int,4> line_coordinates_x
1023  ({{2, 3, 6, 7}});
1024  const Point<2> px(p[1], p[2]);
1025  for (unsigned int l=0; l<4; ++l)
1026  lohvs(index_table, 8+line_coordinates_x[l]*M+k) =
1028  }
1029 
1030  {
1031  constexpr std::array<unsigned int,4> line_coordinates_z
1032  ({{8, 9, 10, 11}});
1033  const Point<2> pz(p[0], p[1]);
1034  for (unsigned int l=0; l<4; ++l)
1035  lohvs(index_table, 8+line_coordinates_z[l]*M+i) =
1037  }
1038 
1039  // quads
1040  lohvs(index_table, 8+12*M+0*M*M+i*M+j) = 1.-p[0];
1041  lohvs(index_table, 8+12*M+1*M*M+i*M+j) = p[0];
1042  lohvs(index_table, 8+12*M+2*M*M+k*M+i) = 1.-p[1];
1043  lohvs(index_table, 8+12*M+3*M*M+k*M+i) = p[1];
1044  lohvs(index_table, 8+12*M+4*M*M+j*M+k) = 1.-p[2];
1045  lohvs(index_table, 8+12*M+5*M*M+j*M+k) = p[2];
1046  }
1047 
1048  // the sum of weights of the points at the outer rim should be one. check
1049  // this
1050  for (unsigned int unit_point=0; unit_point<n_inner; ++unit_point)
1051  Assert(std::fabs(std::accumulate(lohvs[unit_point].begin(),
1052  lohvs[unit_point].end(),0.) - 1)<1e-13*polynomial_degree,
1053  ExcInternalError());
1054 
1055  return lohvs;
1056  }
1057 
1058 
1059 
1064  std::vector<::Table<2,double> >
1065  compute_support_point_weights_perimeter_to_interior(const unsigned int polynomial_degree,
1066  const unsigned int dim)
1067  {
1068  Assert(dim > 0 && dim <= 3, ExcImpossibleInDim(dim));
1069  std::vector<::Table<2,double> > output(dim);
1070  if (polynomial_degree <= 1)
1071  return output;
1072 
1073  // fill the 1D interior weights
1074  QGaussLobatto<1> quadrature(polynomial_degree+1);
1076  for (unsigned int q=0; q<polynomial_degree-1; ++q)
1077  for (unsigned int i=0; i<GeometryInfo<1>::vertices_per_cell; ++i)
1078  output[0](q,i) = GeometryInfo<1>::d_linear_shape_function(quadrature.point(q+1),
1079  i);
1080 
1081  if (dim > 1)
1082  output[1] = compute_support_point_weights_on_quad(polynomial_degree);
1083 
1084  if (dim > 2)
1085  output[2] = compute_support_point_weights_on_hex(polynomial_degree);
1086 
1087  return output;
1088  }
1089 
1093  template <int dim>
1095  compute_support_point_weights_cell(const unsigned int polynomial_degree)
1096  {
1097  Assert(dim > 0 && dim <= 3, ExcImpossibleInDim(dim));
1098  if (polynomial_degree <= 1)
1099  return ::Table<2,double>();
1100 
1101  QGaussLobatto<dim> quadrature(polynomial_degree+1);
1102  std::vector<unsigned int> h2l(quadrature.size());
1103  FETools::hierarchic_to_lexicographic_numbering<dim>(polynomial_degree, h2l);
1104 
1105  ::Table<2,double> output(quadrature.size() - GeometryInfo<dim>::vertices_per_cell,
1107  for (unsigned int q=0; q<output.size(0); ++q)
1108  for (unsigned int i=0; i<GeometryInfo<dim>::vertices_per_cell; ++i)
1110  i);
1111 
1112  return output;
1113  }
1114 
1115 
1116 
1124  template <int dim, int spacedim>
1126  compute_mapped_location_of_point
1127  (const typename ::MappingQGeneric<dim,spacedim>::InternalData &data)
1128  {
1129  AssertDimension (data.shape_values.size(),
1130  data.mapping_support_points.size());
1131 
1132  // use now the InternalData to compute the point in real space.
1133  Point<spacedim> p_real;
1134  for (unsigned int i=0; i<data.mapping_support_points.size(); ++i)
1135  p_real += data.mapping_support_points[i] * data.shape(0,i);
1136 
1137  return p_real;
1138  }
1139 
1140 
1141 
1145  template <int dim>
1146  Point<dim>
1147  do_transform_real_to_unit_cell_internal
1148  (const typename ::Triangulation<dim,dim>::cell_iterator &cell,
1149  const Point<dim> &p,
1150  const Point<dim> &initial_p_unit,
1151  typename ::MappingQGeneric<dim,dim>::InternalData &mdata)
1152  {
1153  const unsigned int spacedim = dim;
1154 
1155  const unsigned int n_shapes=mdata.shape_values.size();
1156  (void)n_shapes;
1157  Assert(n_shapes!=0, ExcInternalError());
1158  AssertDimension (mdata.shape_derivatives.size(), n_shapes);
1159 
1160  std::vector<Point<spacedim> > &points=mdata.mapping_support_points;
1161  AssertDimension (points.size(), n_shapes);
1162 
1163 
1164  // Newton iteration to solve
1165  // f(x)=p(x)-p=0
1166  // where we are looking for 'x' and p(x) is the forward transformation
1167  // from unit to real cell. We solve this using a Newton iteration
1168  // x_{n+1}=x_n-[f'(x)]^{-1}f(x)
1169  // The start value is set to be the linear approximation to the cell
1170 
1171  // The shape values and derivatives of the mapping at this point are
1172  // previously computed.
1173 
1174  Point<dim> p_unit = initial_p_unit;
1175 
1176  mdata.compute_shape_function_values(std::vector<Point<dim> > (1, p_unit));
1177 
1178  Point<spacedim> p_real = compute_mapped_location_of_point<dim,spacedim>(mdata);
1179  Tensor<1,spacedim> f = p_real-p;
1180 
1181  // early out if we already have our point
1182  if (f.norm_square() < 1e-24 * cell->diameter() * cell->diameter())
1183  return p_unit;
1184 
1185  // we need to compare the position of the computed p(x) against the given
1186  // point 'p'. We will terminate the iteration and return 'x' if they are
1187  // less than eps apart. The question is how to choose eps -- or, put maybe
1188  // more generally: in which norm we want these 'p' and 'p(x)' to be eps
1189  // apart.
1190  //
1191  // the question is difficult since we may have to deal with very elongated
1192  // cells where we may achieve 1e-12*h for the distance of these two points
1193  // in the 'long' direction, but achieving this tolerance in the 'short'
1194  // direction of the cell may not be possible
1195  //
1196  // what we do instead is then to terminate iterations if
1197  // \| p(x) - p \|_A < eps
1198  // where the A-norm is somehow induced by the transformation of the cell.
1199  // in particular, we want to measure distances relative to the sizes of
1200  // the cell in its principal directions.
1201  //
1202  // to define what exactly A should be, note that to first order we have
1203  // the following (assuming that x* is the solution of the problem, i.e.,
1204  // p(x*)=p):
1205  // p(x) - p = p(x) - p(x*)
1206  // = -grad p(x) * (x*-x) + higher order terms
1207  // This suggest to measure with a norm that corresponds to
1208  // A = {[grad p(x]^T [grad p(x)]}^{-1}
1209  // because then
1210  // \| p(x) - p \|_A \approx \| x - x* \|
1211  // Consequently, we will try to enforce that
1212  // \| p(x) - p \|_A = \| f \| <= eps
1213  //
1214  // Note that using this norm is a bit dangerous since the norm changes
1215  // in every iteration (A isn't fixed by depends on xk). However, if the
1216  // cell is not too deformed (it may be stretched, but not twisted) then
1217  // the mapping is almost linear and A is indeed constant or nearly so.
1218  const double eps = 1.e-11;
1219  const unsigned int newton_iteration_limit = 20;
1220 
1221  unsigned int newton_iteration = 0;
1222  double last_f_weighted_norm;
1223  do
1224  {
1225 #ifdef DEBUG_TRANSFORM_REAL_TO_UNIT_CELL
1226  std::cout << "Newton iteration " << newton_iteration << std::endl;
1227 #endif
1228 
1229  // f'(x)
1230  Tensor<2,spacedim> df;
1231  for (unsigned int k=0; k<mdata.n_shape_functions; ++k)
1232  {
1233  const Tensor<1,dim> &grad_transform=mdata.derivative(0,k);
1234  const Point<spacedim> &point=points[k];
1235 
1236  for (unsigned int i=0; i<spacedim; ++i)
1237  for (unsigned int j=0; j<dim; ++j)
1238  df[i][j]+=point[i]*grad_transform[j];
1239  }
1240 
1241  // Solve [f'(x)]d=f(x)
1242  AssertThrow(determinant(df) > 0,
1244  Tensor<2,spacedim> df_inverse = invert(df);
1245  const Tensor<1,spacedim> delta = df_inverse * static_cast<const Tensor<1,spacedim>&>(f);
1246 
1247 #ifdef DEBUG_TRANSFORM_REAL_TO_UNIT_CELL
1248  std::cout << " delta=" << delta << std::endl;
1249 #endif
1250 
1251  // do a line search
1252  double step_length = 1;
1253  do
1254  {
1255  // update of p_unit. The spacedim-th component of transformed point
1256  // is simply ignored in codimension one case. When this component is
1257  // not zero, then we are projecting the point to the surface or
1258  // curve identified by the cell.
1259  Point<dim> p_unit_trial = p_unit;
1260  for (unsigned int i=0; i<dim; ++i)
1261  p_unit_trial[i] -= step_length * delta[i];
1262 
1263  // shape values and derivatives
1264  // at new p_unit point
1265  mdata.compute_shape_function_values(std::vector<Point<dim> > (1, p_unit_trial));
1266 
1267  // f(x)
1268  Point<spacedim> p_real_trial = internal::MappingQGenericImplementation::compute_mapped_location_of_point<dim,spacedim>(mdata);
1269  const Tensor<1,spacedim> f_trial = p_real_trial-p;
1270 
1271 #ifdef DEBUG_TRANSFORM_REAL_TO_UNIT_CELL
1272  std::cout << " step_length=" << step_length << std::endl
1273  << " ||f || =" << f.norm() << std::endl
1274  << " ||f*|| =" << f_trial.norm() << std::endl
1275  << " ||f*||_A =" << (df_inverse * f_trial).norm() << std::endl;
1276 #endif
1277 
1278  // see if we are making progress with the current step length
1279  // and if not, reduce it by a factor of two and try again
1280  //
1281  // strictly speaking, we should probably use the same norm as we use
1282  // for the outer algorithm. in practice, line search is just a
1283  // crutch to find a "reasonable" step length, and so using the l2
1284  // norm is probably just fine
1285  if (f_trial.norm() < f.norm())
1286  {
1287  p_real = p_real_trial;
1288  p_unit = p_unit_trial;
1289  f = f_trial;
1290  break;
1291  }
1292  else if (step_length > 0.05)
1293  step_length /= 2;
1294  else
1295  AssertThrow (false,
1297  }
1298  while (true);
1299 
1300  ++newton_iteration;
1301  if (newton_iteration > newton_iteration_limit)
1302  AssertThrow (false,
1304  last_f_weighted_norm = (df_inverse * f).norm();
1305  }
1306  while (last_f_weighted_norm > eps);
1307 
1308  return p_unit;
1309  }
1310 
1311 
1312 
1316  template <int dim>
1317  Point<dim>
1318  do_transform_real_to_unit_cell_internal_codim1
1319  (const typename ::Triangulation<dim,dim+1>::cell_iterator &cell,
1320  const Point<dim+1> &p,
1321  const Point<dim> &initial_p_unit,
1322  typename ::MappingQGeneric<dim,dim+1>::InternalData &mdata)
1323  {
1324  const unsigned int spacedim = dim+1;
1325 
1326  const unsigned int n_shapes=mdata.shape_values.size();
1327  (void)n_shapes;
1328  Assert(n_shapes!=0, ExcInternalError());
1329  Assert(mdata.shape_derivatives.size()==n_shapes, ExcInternalError());
1330  Assert(mdata.shape_second_derivatives.size()==n_shapes, ExcInternalError());
1331 
1332  std::vector<Point<spacedim> > &points=mdata.mapping_support_points;
1333  Assert(points.size()==n_shapes, ExcInternalError());
1334 
1335  Point<spacedim> p_minus_F;
1336 
1337  Tensor<1,spacedim> DF[dim];
1338  Tensor<1,spacedim> D2F[dim][dim];
1339 
1340  Point<dim> p_unit = initial_p_unit;
1341  Point<dim> f;
1342  Tensor<2,dim> df;
1343 
1344  // Evaluate first and second derivatives
1345  mdata.compute_shape_function_values(std::vector<Point<dim> > (1, p_unit));
1346 
1347  for (unsigned int k=0; k<mdata.n_shape_functions; ++k)
1348  {
1349  const Tensor<1,dim> &grad_phi_k = mdata.derivative(0,k);
1350  const Tensor<2,dim> &hessian_k = mdata.second_derivative(0,k);
1351  const Point<spacedim> &point_k = points[k];
1352 
1353  for (unsigned int j=0; j<dim; ++j)
1354  {
1355  DF[j] += grad_phi_k[j] * point_k;
1356  for (unsigned int l=0; l<dim; ++l)
1357  D2F[j][l] += hessian_k[j][l] * point_k;
1358  }
1359  }
1360 
1361  p_minus_F = p;
1362  p_minus_F -= compute_mapped_location_of_point<dim,spacedim>(mdata);
1363 
1364 
1365  for (unsigned int j=0; j<dim; ++j)
1366  f[j] = DF[j] * p_minus_F;
1367 
1368  for (unsigned int j=0; j<dim; ++j)
1369  {
1370  f[j] = DF[j] * p_minus_F;
1371  for (unsigned int l=0; l<dim; ++l)
1372  df[j][l] = -DF[j]*DF[l] + D2F[j][l] * p_minus_F;
1373  }
1374 
1375 
1376  const double eps = 1.e-12*cell->diameter();
1377  const unsigned int loop_limit = 10;
1378 
1379  unsigned int loop=0;
1380 
1381  while (f.norm()>eps && loop++<loop_limit)
1382  {
1383  // Solve [df(x)]d=f(x)
1384  const Tensor<1,dim> d = invert(df) * static_cast<const Tensor<1,dim>&>(f);
1385  p_unit -= d;
1386 
1387  for (unsigned int j=0; j<dim; ++j)
1388  {
1389  DF[j].clear();
1390  for (unsigned int l=0; l<dim; ++l)
1391  D2F[j][l].clear();
1392  }
1393 
1394  mdata.compute_shape_function_values(std::vector<Point<dim> > (1, p_unit));
1395 
1396  for (unsigned int k=0; k<mdata.n_shape_functions; ++k)
1397  {
1398  const Tensor<1,dim> &grad_phi_k = mdata.derivative(0,k);
1399  const Tensor<2,dim> &hessian_k = mdata.second_derivative(0,k);
1400  const Point<spacedim> &point_k = points[k];
1401 
1402  for (unsigned int j=0; j<dim; ++j)
1403  {
1404  DF[j] += grad_phi_k[j] * point_k;
1405  for (unsigned int l=0; l<dim; ++l)
1406  D2F[j][l] += hessian_k[j][l] * point_k;
1407  }
1408  }
1409 
1410  //TODO: implement a line search here in much the same way as for
1411  // the corresponding function above that does so for dim==spacedim
1412  p_minus_F = p;
1413  p_minus_F -= compute_mapped_location_of_point<dim,spacedim>(mdata);
1414 
1415  for (unsigned int j=0; j<dim; ++j)
1416  {
1417  f[j] = DF[j] * p_minus_F;
1418  for (unsigned int l=0; l<dim; ++l)
1419  df[j][l] = -DF[j]*DF[l] + D2F[j][l] * p_minus_F;
1420  }
1421 
1422  }
1423 
1424 
1425  // Here we check that in the last execution of while the first
1426  // condition was already wrong, meaning the residual was below
1427  // eps. Only if the first condition failed, loop will have been
1428  // increased and tested, and thus have reached the limit.
1430 
1431  return p_unit;
1432  }
1433 
1439  template <int dim, int spacedim>
1440  void
1441  maybe_update_q_points_Jacobians_and_grads_tensor
1442  (const CellSimilarity::Similarity cell_similarity,
1443  const typename ::MappingQGeneric<dim,spacedim>::InternalData &data,
1444  std::vector<Point<spacedim> > &quadrature_points,
1445  std::vector<DerivativeForm<2,dim,spacedim> > &jacobian_grads)
1446  {
1447  const UpdateFlags update_flags = data.update_each;
1448 
1449  const unsigned int n_shape_values = data.n_shape_functions;
1450  const unsigned int n_q_points = data.shape_info.n_q_points;
1451  const unsigned int vec_length = VectorizedArray<double>::n_array_elements;
1452  const unsigned int n_comp = 1+ (spacedim-1)/vec_length;
1453  const unsigned int n_hessians = (dim*(dim+1))/2;
1454 
1455  const bool evaluate_values = update_flags & update_quadrature_points;
1456  const bool evaluate_gradients= (cell_similarity != CellSimilarity::translation)
1457  &&(update_flags & update_contravariant_transformation);
1458  const bool evaluate_hessians = (cell_similarity != CellSimilarity::translation)
1459  &&(update_flags & update_jacobian_grads);
1460 
1461  Assert (!evaluate_values || n_q_points > 0, ExcInternalError());
1462  Assert (!evaluate_values || n_q_points == quadrature_points.size(),
1463  ExcDimensionMismatch(n_q_points, quadrature_points.size()));
1464  Assert (!evaluate_gradients || data.n_shape_functions > 0, ExcInternalError());
1465  Assert (!evaluate_gradients || n_q_points == data.contravariant.size(),
1466  ExcDimensionMismatch(n_q_points, data.contravariant.size()));
1467  Assert (!evaluate_hessians || n_q_points == jacobian_grads.size(),
1468  ExcDimensionMismatch(n_q_points, jacobian_grads.size()));
1469 
1470  // prepare arrays
1471  if (evaluate_values || evaluate_gradients || evaluate_hessians)
1472  {
1473  data.values_dofs.resize(n_comp*n_shape_values);
1474  data.values_quad.resize(n_comp*n_q_points);
1475  data.gradients_quad.resize (n_comp*n_q_points*dim);
1476 
1477  if (evaluate_hessians)
1478  data.hessians_quad.resize(n_comp*n_q_points*n_hessians);
1479 
1480  const std::vector<unsigned int> &renumber_to_lexicographic
1481  = data.shape_info.lexicographic_numbering;
1482  for (unsigned int i=0; i<n_shape_values; ++i)
1483  for (unsigned int d=0; d<spacedim; ++d)
1484  {
1485  const unsigned int in_comp = d%vec_length;
1486  const unsigned int out_comp = d/vec_length;
1487  data.values_dofs[out_comp*n_shape_values+i][in_comp]
1488  = data.mapping_support_points[renumber_to_lexicographic[i]][d];
1489  }
1490 
1491  // do the actual tensorized evaluation
1492  SelectEvaluator<dim, -1, 0, n_comp, VectorizedArray<double> >::evaluate
1493  (data.shape_info, data.values_dofs.begin(), data.values_quad.begin(),
1494  data.gradients_quad.begin(), data.hessians_quad.begin(), data.scratch.begin(),
1495  evaluate_values, evaluate_gradients, evaluate_hessians);
1496  }
1497 
1498  // do the postprocessing
1499  if (evaluate_values)
1500  {
1501  for (unsigned int out_comp=0; out_comp<n_comp; ++out_comp)
1502  for (unsigned int i=0; i<n_q_points; ++i)
1503  for (unsigned int in_comp=0;
1504  in_comp<vec_length && in_comp<spacedim-out_comp*vec_length; ++in_comp)
1505  quadrature_points[i][out_comp*vec_length+in_comp]
1506  = data.values_quad[out_comp*n_q_points+i][in_comp];
1507  }
1508 
1509  if (evaluate_gradients)
1510  {
1511  std::fill(data.contravariant.begin(), data.contravariant.end(),
1513  // We need to reinterpret the data after evaluate has been applied.
1514  for (unsigned int out_comp=0; out_comp<n_comp; ++out_comp)
1515  for (unsigned int point=0; point<n_q_points; ++point)
1516  for (unsigned int j=0; j<dim; ++j)
1517  for (unsigned int in_comp=0;
1518  in_comp<vec_length && in_comp<spacedim-out_comp*vec_length; ++in_comp)
1519  {
1520  const unsigned int total_number = point*dim+j;
1521  const unsigned int new_comp = total_number/n_q_points;
1522  const unsigned int new_point = total_number % n_q_points;
1523  data.contravariant[new_point][out_comp*vec_length+in_comp][new_comp]
1524  = data.gradients_quad[(out_comp*n_q_points+point)*dim+j][in_comp];
1525  }
1526  }
1527  if (update_flags & update_covariant_transformation)
1528  if (cell_similarity != CellSimilarity::translation)
1529  for (unsigned int point=0; point<n_q_points; ++point)
1530  data.covariant[point] = (data.contravariant[point]).covariant_form();
1531 
1532  if (update_flags & update_volume_elements)
1533  if (cell_similarity != CellSimilarity::translation)
1534  for (unsigned int point=0; point<n_q_points; ++point)
1535  data.volume_elements[point] = data.contravariant[point].determinant();
1536 
1537  if (evaluate_hessians)
1538  {
1539  constexpr int desymmetrize_3d [6][2] = {{0,0},{1,1},{2,2},{0,1},{0,2},{1,2}};
1540  constexpr int desymmetrize_2d [3][2] = {{0,0},{1,1},{0,1}};
1541 
1542  // We need to reinterpret the data after evaluate has been applied.
1543  for (unsigned int out_comp=0; out_comp<n_comp; ++out_comp)
1544  for (unsigned int point=0; point<n_q_points; ++point)
1545  for (unsigned int j=0; j<n_hessians; ++j)
1546  for (unsigned int in_comp=0;
1547  in_comp<vec_length && in_comp<spacedim-out_comp*vec_length; ++in_comp)
1548  {
1549  const unsigned int total_number = point*n_hessians+j;
1550  const unsigned int new_point = total_number % n_q_points;
1551  const unsigned int new_hessian_comp = total_number/n_q_points;
1552  const unsigned int new_hessian_comp_i = dim==2 ? desymmetrize_2d[new_hessian_comp][0]
1553  : desymmetrize_3d[new_hessian_comp][0];
1554  const unsigned int new_hessian_comp_j = dim==2 ? desymmetrize_2d[new_hessian_comp][1]
1555  : desymmetrize_3d[new_hessian_comp][1];
1556  const double value = data.hessians_quad[(out_comp*n_q_points+point)*n_hessians+j][in_comp];
1557  jacobian_grads[new_point][out_comp*vec_length+in_comp][new_hessian_comp_i][new_hessian_comp_j] = value;
1558  jacobian_grads[new_point][out_comp*vec_length+in_comp][new_hessian_comp_j][new_hessian_comp_i] = value;
1559  }
1560  }
1561  }
1562 
1563 
1570  template <int dim, int spacedim>
1571  void
1572  maybe_compute_q_points
1573  (const typename QProjector<dim>::DataSetDescriptor data_set,
1574  const typename ::MappingQGeneric<dim,spacedim>::InternalData &data,
1575  std::vector<Point<spacedim> > &quadrature_points)
1576  {
1577  const UpdateFlags update_flags = data.update_each;
1578 
1579  if (update_flags & update_quadrature_points)
1580  for (unsigned int point=0; point<quadrature_points.size(); ++point)
1581  {
1582  const double *shape = &data.shape(point+data_set,0);
1583  Point<spacedim> result = (shape[0] *
1584  data.mapping_support_points[0]);
1585  for (unsigned int k=1; k<data.n_shape_functions; ++k)
1586  for (unsigned int i=0; i<spacedim; ++i)
1587  result[i] += shape[k] * data.mapping_support_points[k][i];
1588  quadrature_points[point] = result;
1589  }
1590  }
1591 
1592 
1593 
1601  template <int dim, int spacedim>
1602  void
1603  maybe_update_Jacobians
1604  (const CellSimilarity::Similarity cell_similarity,
1605  const typename ::QProjector<dim>::DataSetDescriptor data_set,
1606  const typename ::MappingQGeneric<dim,spacedim>::InternalData &data)
1607  {
1608  const UpdateFlags update_flags = data.update_each;
1609 
1610  if (update_flags & update_contravariant_transformation)
1611  // if the current cell is just a
1612  // translation of the previous one, no
1613  // need to recompute jacobians...
1614  if (cell_similarity != CellSimilarity::translation)
1615  {
1616  const unsigned int n_q_points = data.contravariant.size();
1617 
1618  std::fill(data.contravariant.begin(), data.contravariant.end(),
1620 
1621  Assert (data.n_shape_functions > 0, ExcInternalError());
1622 
1623  const Tensor<1,spacedim> *supp_pts =
1624  &data.mapping_support_points[0];
1625 
1626  for (unsigned int point=0; point<n_q_points; ++point)
1627  {
1628  const Tensor<1,dim> *data_derv =
1629  &data.derivative(point+data_set, 0);
1630 
1631  double result [spacedim][dim];
1632 
1633  // peel away part of sum to avoid zeroing the
1634  // entries and adding for the first time
1635  for (unsigned int i=0; i<spacedim; ++i)
1636  for (unsigned int j=0; j<dim; ++j)
1637  result[i][j] = data_derv[0][j] * supp_pts[0][i];
1638  for (unsigned int k=1; k<data.n_shape_functions; ++k)
1639  for (unsigned int i=0; i<spacedim; ++i)
1640  for (unsigned int j=0; j<dim; ++j)
1641  result[i][j] += data_derv[k][j] * supp_pts[k][i];
1642 
1643  // write result into contravariant data. for
1644  // j=dim in the case dim<spacedim, there will
1645  // never be any nonzero data that arrives in
1646  // here, so it is ok anyway because it was
1647  // initialized to zero at the initialization
1648  for (unsigned int i=0; i<spacedim; ++i)
1649  for (unsigned int j=0; j<dim; ++j)
1650  data.contravariant[point][i][j] = result[i][j];
1651  }
1652  }
1653 
1654  if (update_flags & update_covariant_transformation)
1655  if (cell_similarity != CellSimilarity::translation)
1656  {
1657  const unsigned int n_q_points = data.contravariant.size();
1658  for (unsigned int point=0; point<n_q_points; ++point)
1659  {
1660  data.covariant[point] = (data.contravariant[point]).covariant_form();
1661  }
1662  }
1663 
1664  if (update_flags & update_volume_elements)
1665  if (cell_similarity != CellSimilarity::translation)
1666  {
1667  const unsigned int n_q_points = data.contravariant.size();
1668  for (unsigned int point=0; point<n_q_points; ++point)
1669  data.volume_elements[point] = data.contravariant[point].determinant();
1670  }
1671 
1672  }
1673 
1680  template <int dim, int spacedim>
1681  void
1682  maybe_update_jacobian_grads
1683  (const CellSimilarity::Similarity cell_similarity,
1684  const typename QProjector<dim>::DataSetDescriptor data_set,
1685  const typename ::MappingQGeneric<dim,spacedim>::InternalData &data,
1686  std::vector<DerivativeForm<2,dim,spacedim> > &jacobian_grads)
1687  {
1688  const UpdateFlags update_flags = data.update_each;
1689  if (update_flags & update_jacobian_grads)
1690  {
1691  const unsigned int n_q_points = jacobian_grads.size();
1692 
1693  if (cell_similarity != CellSimilarity::translation)
1694  for (unsigned int point=0; point<n_q_points; ++point)
1695  {
1696  const Tensor<2,dim> *second =
1697  &data.second_derivative(point+data_set, 0);
1698  double result [spacedim][dim][dim];
1699  for (unsigned int i=0; i<spacedim; ++i)
1700  for (unsigned int j=0; j<dim; ++j)
1701  for (unsigned int l=0; l<dim; ++l)
1702  result[i][j][l] = (second[0][j][l] *
1703  data.mapping_support_points[0][i]);
1704  for (unsigned int k=1; k<data.n_shape_functions; ++k)
1705  for (unsigned int i=0; i<spacedim; ++i)
1706  for (unsigned int j=0; j<dim; ++j)
1707  for (unsigned int l=0; l<dim; ++l)
1708  result[i][j][l]
1709  += (second[k][j][l]
1710  *
1711  data.mapping_support_points[k][i]);
1712 
1713  for (unsigned int i=0; i<spacedim; ++i)
1714  for (unsigned int j=0; j<dim; ++j)
1715  for (unsigned int l=0; l<dim; ++l)
1716  jacobian_grads[point][i][j][l] = result[i][j][l];
1717  }
1718  }
1719  }
1720 
1727  template <int dim, int spacedim>
1728  void
1729  maybe_update_jacobian_pushed_forward_grads
1730  (const CellSimilarity::Similarity cell_similarity,
1731  const typename QProjector<dim>::DataSetDescriptor data_set,
1732  const typename ::MappingQGeneric<dim,spacedim>::InternalData &data,
1733  std::vector<Tensor<3,spacedim> > &jacobian_pushed_forward_grads)
1734  {
1735  const UpdateFlags update_flags = data.update_each;
1736  if (update_flags & update_jacobian_pushed_forward_grads)
1737  {
1738  const unsigned int n_q_points = jacobian_pushed_forward_grads.size();
1739 
1740  if (cell_similarity != CellSimilarity::translation)
1741  {
1742  double tmp[spacedim][spacedim][spacedim];
1743  for (unsigned int point=0; point<n_q_points; ++point)
1744  {
1745  const Tensor<2,dim> *second =
1746  &data.second_derivative(point+data_set, 0);
1747  double result [spacedim][dim][dim];
1748  for (unsigned int i=0; i<spacedim; ++i)
1749  for (unsigned int j=0; j<dim; ++j)
1750  for (unsigned int l=0; l<dim; ++l)
1751  result[i][j][l] = (second[0][j][l] *
1752  data.mapping_support_points[0][i]);
1753  for (unsigned int k=1; k<data.n_shape_functions; ++k)
1754  for (unsigned int i=0; i<spacedim; ++i)
1755  for (unsigned int j=0; j<dim; ++j)
1756  for (unsigned int l=0; l<dim; ++l)
1757  result[i][j][l]
1758  += (second[k][j][l]
1759  *
1760  data.mapping_support_points[k][i]);
1761 
1762  // first push forward the j-components
1763  for (unsigned int i=0; i<spacedim; ++i)
1764  for (unsigned int j=0; j<spacedim; ++j)
1765  for (unsigned int l=0; l<dim; ++l)
1766  {
1767  tmp[i][j][l] = result[i][0][l] *
1768  data.covariant[point][j][0];
1769  for (unsigned int jr=1; jr<dim; ++jr)
1770  {
1771  tmp[i][j][l] += result[i][jr][l] *
1772  data.covariant[point][j][jr];
1773  }
1774  }
1775 
1776  // now, pushing forward the l-components
1777  for (unsigned int i=0; i<spacedim; ++i)
1778  for (unsigned int j=0; j<spacedim; ++j)
1779  for (unsigned int l=0; l<spacedim; ++l)
1780  {
1781  jacobian_pushed_forward_grads[point][i][j][l] = tmp[i][j][0] *
1782  data.covariant[point][l][0];
1783  for (unsigned int lr=1; lr<dim; ++lr)
1784  {
1785  jacobian_pushed_forward_grads[point][i][j][l] += tmp[i][j][lr] *
1786  data.covariant[point][l][lr];
1787  }
1788 
1789  }
1790  }
1791  }
1792  }
1793  }
1794 
1801  template <int dim, int spacedim>
1802  void
1803  maybe_update_jacobian_2nd_derivatives
1804  (const CellSimilarity::Similarity cell_similarity,
1805  const typename QProjector<dim>::DataSetDescriptor data_set,
1806  const typename ::MappingQGeneric<dim,spacedim>::InternalData &data,
1807  std::vector<DerivativeForm<3,dim,spacedim> > &jacobian_2nd_derivatives)
1808  {
1809  const UpdateFlags update_flags = data.update_each;
1810  if (update_flags & update_jacobian_2nd_derivatives)
1811  {
1812  const unsigned int n_q_points = jacobian_2nd_derivatives.size();
1813 
1814  if (cell_similarity != CellSimilarity::translation)
1815  {
1816  for (unsigned int point=0; point<n_q_points; ++point)
1817  {
1818  const Tensor<3,dim> *third =
1819  &data.third_derivative(point+data_set, 0);
1820  double result [spacedim][dim][dim][dim];
1821  for (unsigned int i=0; i<spacedim; ++i)
1822  for (unsigned int j=0; j<dim; ++j)
1823  for (unsigned int l=0; l<dim; ++l)
1824  for (unsigned int m=0; m<dim; ++m)
1825  result[i][j][l][m] = (third[0][j][l][m] *
1826  data.mapping_support_points[0][i]);
1827  for (unsigned int k=1; k<data.n_shape_functions; ++k)
1828  for (unsigned int i=0; i<spacedim; ++i)
1829  for (unsigned int j=0; j<dim; ++j)
1830  for (unsigned int l=0; l<dim; ++l)
1831  for (unsigned int m=0; m<dim; ++m)
1832  result[i][j][l][m]
1833  += (third[k][j][l][m]
1834  *
1835  data.mapping_support_points[k][i]);
1836 
1837  for (unsigned int i=0; i<spacedim; ++i)
1838  for (unsigned int j=0; j<dim; ++j)
1839  for (unsigned int l=0; l<dim; ++l)
1840  for (unsigned int m=0; m<dim; ++m)
1841  jacobian_2nd_derivatives[point][i][j][l][m] = result[i][j][l][m];
1842  }
1843  }
1844  }
1845  }
1846 
1854  template <int dim, int spacedim>
1855  void
1856  maybe_update_jacobian_pushed_forward_2nd_derivatives
1857  (const CellSimilarity::Similarity cell_similarity,
1858  const typename QProjector<dim>::DataSetDescriptor data_set,
1859  const typename ::MappingQGeneric<dim,spacedim>::InternalData &data,
1860  std::vector<Tensor<4,spacedim> > &jacobian_pushed_forward_2nd_derivatives)
1861  {
1862  const UpdateFlags update_flags = data.update_each;
1864  {
1865  const unsigned int n_q_points = jacobian_pushed_forward_2nd_derivatives.size();
1866 
1867  if (cell_similarity != CellSimilarity::translation)
1868  {
1869  double tmp[spacedim][spacedim][spacedim][spacedim];
1870  for (unsigned int point=0; point<n_q_points; ++point)
1871  {
1872  const Tensor<3,dim> *third =
1873  &data.third_derivative(point+data_set, 0);
1874  double result [spacedim][dim][dim][dim];
1875  for (unsigned int i=0; i<spacedim; ++i)
1876  for (unsigned int j=0; j<dim; ++j)
1877  for (unsigned int l=0; l<dim; ++l)
1878  for (unsigned int m=0; m<dim; ++m)
1879  result[i][j][l][m] = (third[0][j][l][m] *
1880  data.mapping_support_points[0][i]);
1881  for (unsigned int k=1; k<data.n_shape_functions; ++k)
1882  for (unsigned int i=0; i<spacedim; ++i)
1883  for (unsigned int j=0; j<dim; ++j)
1884  for (unsigned int l=0; l<dim; ++l)
1885  for (unsigned int m=0; m<dim; ++m)
1886  result[i][j][l][m]
1887  += (third[k][j][l][m]
1888  *
1889  data.mapping_support_points[k][i]);
1890 
1891  // push forward the j-coordinate
1892  for (unsigned int i=0; i<spacedim; ++i)
1893  for (unsigned int j=0; j<spacedim; ++j)
1894  for (unsigned int l=0; l<dim; ++l)
1895  for (unsigned int m=0; m<dim; ++m)
1896  {
1897  jacobian_pushed_forward_2nd_derivatives[point][i][j][l][m]
1898  = result[i][0][l][m]*
1899  data.covariant[point][j][0];
1900  for (unsigned int jr=1; jr<dim; ++jr)
1901  jacobian_pushed_forward_2nd_derivatives[point][i][j][l][m]
1902  += result[i][jr][l][m]*
1903  data.covariant[point][j][jr];
1904  }
1905 
1906  // push forward the l-coordinate
1907  for (unsigned int i=0; i<spacedim; ++i)
1908  for (unsigned int j=0; j<spacedim; ++j)
1909  for (unsigned int l=0; l<spacedim; ++l)
1910  for (unsigned int m=0; m<dim; ++m)
1911  {
1912  tmp[i][j][l][m]
1913  = jacobian_pushed_forward_2nd_derivatives[point][i][j][0][m]*
1914  data.covariant[point][l][0];
1915  for (unsigned int lr=1; lr<dim; ++lr)
1916  tmp[i][j][l][m]
1917  += jacobian_pushed_forward_2nd_derivatives[point][i][j][lr][m]*
1918  data.covariant[point][l][lr];
1919  }
1920 
1921  // push forward the m-coordinate
1922  for (unsigned int i=0; i<spacedim; ++i)
1923  for (unsigned int j=0; j<spacedim; ++j)
1924  for (unsigned int l=0; l<spacedim; ++l)
1925  for (unsigned int m=0; m<spacedim; ++m)
1926  {
1927  jacobian_pushed_forward_2nd_derivatives[point][i][j][l][m]
1928  = tmp[i][j][l][0]*
1929  data.covariant[point][m][0];
1930  for (unsigned int mr=1; mr<dim; ++mr)
1931  jacobian_pushed_forward_2nd_derivatives[point][i][j][l][m]
1932  += tmp[i][j][l][mr]*
1933  data.covariant[point][m][mr];
1934  }
1935  }
1936  }
1937  }
1938  }
1939 
1946  template <int dim, int spacedim>
1947  void
1948  maybe_update_jacobian_3rd_derivatives
1949  (const CellSimilarity::Similarity cell_similarity,
1950  const typename QProjector<dim>::DataSetDescriptor data_set,
1951  const typename ::MappingQGeneric<dim,spacedim>::InternalData &data,
1952  std::vector<DerivativeForm<4,dim,spacedim> > &jacobian_3rd_derivatives)
1953  {
1954  const UpdateFlags update_flags = data.update_each;
1955  if (update_flags & update_jacobian_3rd_derivatives)
1956  {
1957  const unsigned int n_q_points = jacobian_3rd_derivatives.size();
1958 
1959  if (cell_similarity != CellSimilarity::translation)
1960  {
1961  for (unsigned int point=0; point<n_q_points; ++point)
1962  {
1963  const Tensor<4,dim> *fourth =
1964  &data.fourth_derivative(point+data_set, 0);
1965  double result [spacedim][dim][dim][dim][dim];
1966  for (unsigned int i=0; i<spacedim; ++i)
1967  for (unsigned int j=0; j<dim; ++j)
1968  for (unsigned int l=0; l<dim; ++l)
1969  for (unsigned int m=0; m<dim; ++m)
1970  for (unsigned int n=0; n<dim; ++n)
1971  result[i][j][l][m][n] = (fourth[0][j][l][m][n] *
1972  data.mapping_support_points[0][i]);
1973  for (unsigned int k=1; k<data.n_shape_functions; ++k)
1974  for (unsigned int i=0; i<spacedim; ++i)
1975  for (unsigned int j=0; j<dim; ++j)
1976  for (unsigned int l=0; l<dim; ++l)
1977  for (unsigned int m=0; m<dim; ++m)
1978  for (unsigned int n=0; n<dim; ++n)
1979  result[i][j][l][m][n]
1980  += (fourth[k][j][l][m][n]
1981  *
1982  data.mapping_support_points[k][i]);
1983 
1984  for (unsigned int i=0; i<spacedim; ++i)
1985  for (unsigned int j=0; j<dim; ++j)
1986  for (unsigned int l=0; l<dim; ++l)
1987  for (unsigned int m=0; m<dim; ++m)
1988  for (unsigned int n=0; n<dim; ++n)
1989  jacobian_3rd_derivatives[point][i][j][l][m][n] = result[i][j][l][m][n];
1990  }
1991  }
1992  }
1993  }
1994 
2001  template <int dim, int spacedim>
2002  void
2003  maybe_update_jacobian_pushed_forward_3rd_derivatives
2004  (const CellSimilarity::Similarity cell_similarity,
2005  const typename QProjector<dim>::DataSetDescriptor data_set,
2006  const typename ::MappingQGeneric<dim,spacedim>::InternalData &data,
2007  std::vector<Tensor<5,spacedim> > &jacobian_pushed_forward_3rd_derivatives)
2008  {
2009  const UpdateFlags update_flags = data.update_each;
2011  {
2012  const unsigned int n_q_points = jacobian_pushed_forward_3rd_derivatives.size();
2013 
2014  if (cell_similarity != CellSimilarity::translation)
2015  {
2016  double tmp[spacedim][spacedim][spacedim][spacedim][spacedim];
2017  for (unsigned int point=0; point<n_q_points; ++point)
2018  {
2019  const Tensor<4,dim> *fourth =
2020  &data.fourth_derivative(point+data_set, 0);
2021  double result [spacedim][dim][dim][dim][dim];
2022  for (unsigned int i=0; i<spacedim; ++i)
2023  for (unsigned int j=0; j<dim; ++j)
2024  for (unsigned int l=0; l<dim; ++l)
2025  for (unsigned int m=0; m<dim; ++m)
2026  for (unsigned int n=0; n<dim; ++n)
2027  result[i][j][l][m][n] = (fourth[0][j][l][m][n] *
2028  data.mapping_support_points[0][i]);
2029  for (unsigned int k=1; k<data.n_shape_functions; ++k)
2030  for (unsigned int i=0; i<spacedim; ++i)
2031  for (unsigned int j=0; j<dim; ++j)
2032  for (unsigned int l=0; l<dim; ++l)
2033  for (unsigned int m=0; m<dim; ++m)
2034  for (unsigned int n=0; n<dim; ++n)
2035  result[i][j][l][m][n]
2036  += (fourth[k][j][l][m][n]
2037  *
2038  data.mapping_support_points[k][i]);
2039 
2040  // push-forward the j-coordinate
2041  for (unsigned int i=0; i<spacedim; ++i)
2042  for (unsigned int j=0; j<spacedim; ++j)
2043  for (unsigned int l=0; l<dim; ++l)
2044  for (unsigned int m=0; m<dim; ++m)
2045  for (unsigned int n=0; n<dim; ++n)
2046  {
2047  tmp[i][j][l][m][n] = result[i][0][l][m][n] *
2048  data.covariant[point][j][0];
2049  for (unsigned int jr=1; jr<dim; ++jr)
2050  tmp[i][j][l][m][n] += result[i][jr][l][m][n] *
2051  data.covariant[point][j][jr];
2052  }
2053 
2054  // push-forward the l-coordinate
2055  for (unsigned int i=0; i<spacedim; ++i)
2056  for (unsigned int j=0; j<spacedim; ++j)
2057  for (unsigned int l=0; l<spacedim; ++l)
2058  for (unsigned int m=0; m<dim; ++m)
2059  for (unsigned int n=0; n<dim; ++n)
2060  {
2061  jacobian_pushed_forward_3rd_derivatives[point][i][j][l][m][n]
2062  = tmp[i][j][0][m][n] *
2063  data.covariant[point][l][0];
2064  for (unsigned int lr=1; lr<dim; ++lr)
2065  jacobian_pushed_forward_3rd_derivatives[point][i][j][l][m][n]
2066  += tmp[i][j][lr][m][n] *
2067  data.covariant[point][l][lr];
2068  }
2069 
2070  // push-forward the m-coordinate
2071  for (unsigned int i=0; i<spacedim; ++i)
2072  for (unsigned int j=0; j<spacedim; ++j)
2073  for (unsigned int l=0; l<spacedim; ++l)
2074  for (unsigned int m=0; m<spacedim; ++m)
2075  for (unsigned int n=0; n<dim; ++n)
2076  {
2077  tmp[i][j][l][m][n]
2078  = jacobian_pushed_forward_3rd_derivatives[point][i][j][l][0][n] *
2079  data.covariant[point][m][0];
2080  for (unsigned int mr=1; mr<dim; ++mr)
2081  tmp[i][j][l][m][n]
2082  += jacobian_pushed_forward_3rd_derivatives[point][i][j][l][mr][n] *
2083  data.covariant[point][m][mr];
2084  }
2085 
2086  // push-forward the n-coordinate
2087  for (unsigned int i=0; i<spacedim; ++i)
2088  for (unsigned int j=0; j<spacedim; ++j)
2089  for (unsigned int l=0; l<spacedim; ++l)
2090  for (unsigned int m=0; m<spacedim; ++m)
2091  for (unsigned int n=0; n<spacedim; ++n)
2092  {
2093  jacobian_pushed_forward_3rd_derivatives[point][i][j][l][m][n]
2094  = tmp[i][j][l][m][0] *
2095  data.covariant[point][n][0];
2096  for (unsigned int nr=1; nr<dim; ++nr)
2097  jacobian_pushed_forward_3rd_derivatives[point][i][j][l][m][n]
2098  += tmp[i][j][l][m][nr] *
2099  data.covariant[point][n][nr];
2100  }
2101  }
2102  }
2103  }
2104  }
2105  }
2106  }
2107 }
2108 
2109 
2110 
2111 template <int dim, int spacedim>
2113  :
2114  polynomial_degree(p),
2115  line_support_points(this->polynomial_degree+1),
2116  fe_q(dim == 3 ? new FE_Q<dim>(this->polynomial_degree) : nullptr),
2117  support_point_weights_perimeter_to_interior (internal::MappingQGenericImplementation::compute_support_point_weights_perimeter_to_interior(this->polynomial_degree, dim)),
2118  support_point_weights_cell (internal::MappingQGenericImplementation::compute_support_point_weights_cell<dim>(this->polynomial_degree))
2119 {
2120  Assert (p >= 1, ExcMessage ("It only makes sense to create polynomial mappings "
2121  "with a polynomial degree greater or equal to one."));
2122 }
2123 
2124 
2125 
2126 template <int dim, int spacedim>
2128  :
2129  polynomial_degree(mapping.polynomial_degree),
2130  line_support_points(mapping.line_support_points),
2131  fe_q(dim == 3 ? new FE_Q<dim>(*mapping.fe_q) : nullptr),
2132  support_point_weights_perimeter_to_interior (mapping.support_point_weights_perimeter_to_interior),
2133  support_point_weights_cell (mapping.support_point_weights_cell)
2134 {}
2135 
2136 
2137 
2138 
2139 template <int dim, int spacedim>
2140 std::unique_ptr<Mapping<dim,spacedim> >
2142 {
2143  return std_cxx14::make_unique<MappingQGeneric<dim,spacedim>>(*this);
2144 }
2145 
2146 
2147 
2148 
2149 template <int dim, int spacedim>
2150 unsigned int
2152 {
2153  return polynomial_degree;
2154 }
2155 
2156 
2157 
2158 template <int dim, int spacedim>
2162  const Point<dim> &p) const
2163 {
2164  // set up the polynomial space
2166  tensor_pols (Polynomials::generate_complete_Lagrange_basis(line_support_points.get_points()));
2167  Assert (tensor_pols.n() == Utilities::fixed_power<dim>(polynomial_degree+1),
2168  ExcInternalError());
2169 
2170  // then also construct the mapping from lexicographic to the Qp shape function numbering
2171  const std::vector<unsigned int>
2172  renumber (FETools::
2173  lexicographic_to_hierarchic_numbering
2174  (FiniteElementData<dim> (internal::MappingQGenericImplementation::get_dpo_vector<dim>
2175  (polynomial_degree), 1, polynomial_degree)));
2176 
2177  const std::vector<Point<spacedim> > support_points
2178  = this->compute_mapping_support_points(cell);
2179 
2180  Point<spacedim> mapped_point;
2181  for (unsigned int i=0; i<tensor_pols.n(); ++i)
2182  mapped_point += support_points[renumber[i]] * tensor_pols.compute_value (i, p);
2183 
2184  return mapped_point;
2185 }
2186 
2187 
2188 // In the code below, GCC tries to instantiate MappingQGeneric<3,4> when
2189 // seeing which of the overloaded versions of
2190 // do_transform_real_to_unit_cell_internal() to call. This leads to bad
2191 // error messages and, generally, nothing very good. Avoid this by ensuring
2192 // that this class exists, but does not have an inner InternalData
2193 // type, thereby ruling out the codim-1 version of the function
2194 // below when doing overload resolution.
2195 template <>
2196 class MappingQGeneric<3,4>
2197 {};
2198 
2199 
2200 
2201 // visual studio freaks out when trying to determine if
2202 // do_transform_real_to_unit_cell_internal with dim=3 and spacedim=4 is a good
2203 // candidate. So instead of letting the compiler pick the correct overload, we
2204 // use template specialization to make sure we pick up the right function to
2205 // call:
2206 
2207 template <int dim, int spacedim>
2208 Point<dim>
2212  const Point<spacedim> &,
2213  const Point<dim> &) const
2214 {
2215  // default implementation (should never be called)
2216  Assert(false, ExcInternalError());
2217  return Point<dim>();
2218 }
2219 
2220 template <>
2221 Point<1>
2225  const Point<1> &p,
2226  const Point<1> &initial_p_unit) const
2227 {
2228  const int dim = 1;
2229  const int spacedim = 1;
2230 
2231  const Quadrature<dim> point_quadrature(initial_p_unit);
2232 
2234  if (spacedim>dim)
2235  update_flags |= update_jacobian_grads;
2236  auto mdata = Utilities::dynamic_unique_cast<InternalData>(get_data(update_flags,
2237  point_quadrature));
2238 
2239  mdata->mapping_support_points = this->compute_mapping_support_points (cell);
2240 
2241  // dispatch to the various specializations for spacedim=dim,
2242  // spacedim=dim+1, etc
2243  return internal::MappingQGenericImplementation::do_transform_real_to_unit_cell_internal<1>(cell, p, initial_p_unit, *mdata);
2244 }
2245 
2246 template <>
2247 Point<2>
2251  const Point<2> &p,
2252  const Point<2> &initial_p_unit) const
2253 {
2254  const int dim = 2;
2255  const int spacedim = 2;
2256 
2257  const Quadrature<dim> point_quadrature(initial_p_unit);
2258 
2260  if (spacedim>dim)
2261  update_flags |= update_jacobian_grads;
2262  auto mdata = Utilities::dynamic_unique_cast<InternalData>(get_data(update_flags,
2263  point_quadrature));
2264 
2265  mdata->mapping_support_points = this->compute_mapping_support_points (cell);
2266 
2267  // dispatch to the various specializations for spacedim=dim,
2268  // spacedim=dim+1, etc
2269  return internal::MappingQGenericImplementation::do_transform_real_to_unit_cell_internal<2>(cell, p, initial_p_unit, *mdata);
2270 }
2271 
2272 template <>
2273 Point<3>
2277  const Point<3> &p,
2278  const Point<3> &initial_p_unit) const
2279 {
2280  const int dim = 3;
2281  const int spacedim = 3;
2282 
2283  const Quadrature<dim> point_quadrature(initial_p_unit);
2284 
2286  if (spacedim>dim)
2287  update_flags |= update_jacobian_grads;
2288  auto mdata = Utilities::dynamic_unique_cast<InternalData>(get_data(update_flags,
2289  point_quadrature));
2290 
2291  mdata->mapping_support_points = this->compute_mapping_support_points (cell);
2292 
2293  // dispatch to the various specializations for spacedim=dim,
2294  // spacedim=dim+1, etc
2295  return internal::MappingQGenericImplementation::do_transform_real_to_unit_cell_internal<3>(cell, p, initial_p_unit, *mdata);
2296 }
2297 
2298 
2299 
2300 template <>
2301 Point<1>
2305  const Point<2> &p,
2306  const Point<1> &initial_p_unit) const
2307 {
2308  const int dim = 1;
2309  const int spacedim = 2;
2310 
2311  const Quadrature<dim> point_quadrature(initial_p_unit);
2312 
2314  if (spacedim>dim)
2315  update_flags |= update_jacobian_grads;
2316  auto mdata = Utilities::dynamic_unique_cast<InternalData>(get_data(update_flags,
2317  point_quadrature));
2318 
2319  mdata->mapping_support_points = this->compute_mapping_support_points (cell);
2320 
2321  // dispatch to the various specializations for spacedim=dim,
2322  // spacedim=dim+1, etc
2323  return internal::MappingQGenericImplementation::do_transform_real_to_unit_cell_internal_codim1<1>(cell, p, initial_p_unit, *mdata);
2324 }
2325 
2326 
2327 
2328 template <>
2329 Point<2>
2333  const Point<3> &p,
2334  const Point<2> &initial_p_unit) const
2335 {
2336  const int dim = 2;
2337  const int spacedim = 3;
2338 
2339  const Quadrature<dim> point_quadrature(initial_p_unit);
2340 
2342  if (spacedim>dim)
2343  update_flags |= update_jacobian_grads;
2344  auto mdata = Utilities::dynamic_unique_cast<InternalData>(get_data(update_flags,
2345  point_quadrature));
2346 
2347  mdata->mapping_support_points = this->compute_mapping_support_points (cell);
2348 
2349  // dispatch to the various specializations for spacedim=dim,
2350  // spacedim=dim+1, etc
2351  return internal::MappingQGenericImplementation::do_transform_real_to_unit_cell_internal_codim1<2>(cell, p, initial_p_unit, *mdata);
2352 }
2353 
2354 template <>
2355 Point<1>
2359  const Point<3> &,
2360  const Point<1> &) const
2361 {
2362  Assert (false, ExcNotImplemented());
2363  return Point<1>();
2364 }
2365 
2366 
2367 
2368 template <int dim, int spacedim>
2369 Point<dim>
2372  const Point<spacedim> &p) const
2373 {
2374  // Use an exact formula if one is available. this is only the case
2375  // for Q1 mappings in 1d, and in 2d if dim==spacedim
2376  if ((polynomial_degree == 1) &&
2377  ((dim == 1)
2378  ||
2379  ((dim == 2) && (dim == spacedim))))
2380  {
2381  // The dimension-dependent algorithms are much faster (about 25-45x in
2382  // 2D) but fail most of the time when the given point (p) is not in the
2383  // cell. The dimension-independent Newton algorithm given below is
2384  // slower, but more robust (though it still sometimes fails). Therefore
2385  // this function implements the following strategy based on the
2386  // p's dimension:
2387  //
2388  // * In 1D this mapping is linear, so the mapping is always invertible
2389  // (and the exact formula is known) as long as the cell has non-zero
2390  // length.
2391  // * In 2D the exact (quadratic) formula is called first. If either the
2392  // exact formula does not succeed (negative discriminant in the
2393  // quadratic formula) or succeeds but finds a solution outside of the
2394  // unit cell, then the Newton solver is called. The rationale for the
2395  // second choice is that the exact formula may provide two different
2396  // answers when mapping a point outside of the real cell, but the
2397  // Newton solver (if it converges) will only return one answer.
2398  // Otherwise the exact formula successfully found a point in the unit
2399  // cell and that value is returned.
2400  // * In 3D there is no (known to the authors) exact formula, so the Newton
2401  // algorithm is used.
2402  const std::array<Point<spacedim>, GeometryInfo<dim>::vertices_per_cell>
2403  vertices = this->get_vertices(cell);
2404  try
2405  {
2406  switch (dim)
2407  {
2408  case 1:
2409  {
2410  // formula not subject to any issues in 1d
2411  if (spacedim == 1)
2412  return internal::MappingQ1::transform_real_to_unit_cell(vertices, p);
2413  else
2414  break;
2415  }
2416 
2417  case 2:
2418  {
2419  const Point<dim> point
2420  = internal::MappingQ1::transform_real_to_unit_cell(vertices, p);
2421 
2422  // formula not guaranteed to work for points outside of
2423  // the cell. only take the computed point if it lies
2424  // inside the reference cell
2425  const double eps = 1e-15;
2426  if (-eps <= point(1) && point(1) <= 1 + eps &&
2427  -eps <= point(0) && point(0) <= 1 + eps)
2428  {
2429  return point;
2430  }
2431  else
2432  break;
2433  }
2434 
2435  default:
2436  {
2437  // we should get here, based on the if-condition at the top
2438  Assert(false, ExcInternalError());
2439  }
2440  }
2441  }
2443  {
2444  // simply fall through and continue on to the standard Newton code
2445  }
2446  }
2447  else
2448  {
2449  // we can't use an explicit formula,
2450  }
2451 
2452 
2453  // Find the initial value for the Newton iteration by a normal
2454  // projection to the least square plane determined by the vertices
2455  // of the cell
2456  Point<dim> initial_p_unit;
2457  if (this->preserves_vertex_locations())
2458  initial_p_unit = cell->real_to_unit_cell_affine_approximation(p);
2459  else
2460  {
2461  // for the MappingQEulerian type classes, we want to still call the cell
2462  // iterator's affine approximation. do so by creating a dummy
2463  // triangulation with just the first vertices.
2464  //
2465  // we do this by first getting all support points, then
2466  // throwing away all but the vertices, and finally calling
2467  // the same function as above
2468  std::vector<Point<spacedim> > a
2469  = this->compute_mapping_support_points (cell);
2471  std::vector<CellData<dim> > cells(1);
2472  for (unsigned int i=0; i<GeometryInfo<dim>::vertices_per_cell; ++i)
2473  cells[0].vertices[i] = i;
2475  tria.create_triangulation(a, cells, SubCellData());
2476  initial_p_unit = tria.begin_active()->real_to_unit_cell_affine_approximation(p);
2477  }
2478  // in 1d with spacedim > 1 the affine approximation is exact
2479  if (dim == 1 && polynomial_degree == 1)
2480  {
2481  return initial_p_unit;
2482  }
2483  else
2484  {
2485  // in case the function above should have given us something back that
2486  // lies outside the unit cell, then project it back into the reference
2487  // cell in hopes that this gives a better starting point to the
2488  // following iteration
2489  initial_p_unit = GeometryInfo<dim>::project_to_unit_cell(initial_p_unit);
2490 
2491  // perform the Newton iteration and return the result. note that this
2492  // statement may throw an exception, which we simply pass up to the
2493  // caller
2494  return this->transform_real_to_unit_cell_internal(cell, p, initial_p_unit);
2495  }
2496 }
2497 
2498 
2499 
2500 template <int dim, int spacedim>
2503 {
2504  // add flags if the respective quantities are necessary to compute
2505  // what we need. note that some flags appear in both the conditions
2506  // and in subsequent set operations. this leads to some circular
2507  // logic. the only way to treat this is to iterate. since there are
2508  // 5 if-clauses in the loop, it will take at most 5 iterations to
2509  // converge. do them:
2510  UpdateFlags out = in;
2511  for (unsigned int i=0; i<5; ++i)
2512  {
2513  // The following is a little incorrect:
2514  // If not applied on a face,
2515  // update_boundary_forms does not
2516  // make sense. On the other hand,
2517  // it is necessary on a
2518  // face. Currently,
2519  // update_boundary_forms is simply
2520  // ignored for the interior of a
2521  // cell.
2522  if (out & (update_JxW_values
2524  out |= update_boundary_forms;
2525 
2533 
2534  if (out & (update_inverse_jacobians
2539 
2540  // The contravariant transformation is used in the Piola
2541  // transformation, which requires the determinant of the Jacobi
2542  // matrix of the transformation. Because we have no way of
2543  // knowing here whether the finite element wants to use the
2544  // contravariant or the Piola transforms, we add the JxW values
2545  // to the list of flags to be updated for each cell.
2547  out |= update_volume_elements;
2548 
2549  // the same is true when computing normal vectors: they require
2550  // the determinant of the Jacobian
2551  if (out & update_normal_vectors)
2552  out |= update_volume_elements;
2553  }
2554 
2555  return out;
2556 }
2557 
2558 
2559 
2560 template <int dim, int spacedim>
2561 std::unique_ptr<typename Mapping<dim,spacedim>::InternalDataBase>
2563  const Quadrature<dim> &q) const
2564 {
2565  auto data = std_cxx14::make_unique<InternalData>(polynomial_degree);
2566  data->initialize (this->requires_update_flags(update_flags), q, q.size());
2567 
2568  return std::move(data);
2569 }
2570 
2571 
2572 
2573 template <int dim, int spacedim>
2574 std::unique_ptr<typename Mapping<dim,spacedim>::InternalDataBase>
2576  const Quadrature<dim-1> &quadrature) const
2577 {
2578  auto data = std_cxx14::make_unique<InternalData>(polynomial_degree);
2579  data->initialize_face (this->requires_update_flags(update_flags),
2581  quadrature.size());
2582 
2583  return std::move(data);
2584 }
2585 
2586 
2587 
2588 template <int dim, int spacedim>
2589 std::unique_ptr<typename Mapping<dim,spacedim>::InternalDataBase>
2591  const Quadrature<dim-1>& quadrature) const
2592 {
2593  auto data = std_cxx14::make_unique<InternalData>(polynomial_degree);
2594  data->initialize_face (this->requires_update_flags(update_flags),
2596  quadrature.size());
2597 
2598  return std::move(data);
2599 }
2600 
2601 
2602 
2603 template <int dim, int spacedim>
2607  const CellSimilarity::Similarity cell_similarity,
2608  const Quadrature<dim> &quadrature,
2609  const typename Mapping<dim,spacedim>::InternalDataBase &internal_data,
2611 {
2612  // ensure that the following static_cast is really correct:
2613  Assert (dynamic_cast<const InternalData *>(&internal_data) != nullptr,
2614  ExcInternalError());
2615  const InternalData &data = static_cast<const InternalData &>(internal_data);
2616 
2617  const unsigned int n_q_points=quadrature.size();
2618 
2619  // recompute the support points of the transformation of this
2620  // cell. we tried to be clever here in an earlier version of the
2621  // library by checking whether the cell is the same as the one we
2622  // had visited last, but it turns out to be difficult to determine
2623  // that because a cell for the purposes of a mapping is
2624  // characterized not just by its (triangulation, level, index)
2625  // triple, but also by the locations of its vertices, the manifold
2626  // object attached to the cell and all of its bounding faces/edges,
2627  // etc. to reliably test that the "cell" we are on is, therefore,
2628  // not easily done
2629  data.mapping_support_points = this->compute_mapping_support_points(cell);
2630  data.cell_of_current_support_points = cell;
2631 
2632  // if the order of the mapping is greater than 1, then do not reuse any cell
2633  // similarity information. This is necessary because the cell similarity
2634  // value is computed with just cell vertices and does not take into account
2635  // cell curvature.
2636  const CellSimilarity::Similarity computed_cell_similarity =
2637  (polynomial_degree == 1 ? cell_similarity : CellSimilarity::none);
2638 
2639  if (dim>1 && data.tensor_product_quadrature)
2640  {
2641  internal::MappingQGenericImplementation::maybe_update_q_points_Jacobians_and_grads_tensor<dim, spacedim>
2642  (computed_cell_similarity,
2643  data,
2644  output_data.quadrature_points,
2645  output_data.jacobian_grads);
2646  }
2647  else
2648  {
2649  internal::MappingQGenericImplementation::maybe_compute_q_points<dim,spacedim>
2651  data,
2652  output_data.quadrature_points);
2653 
2654  internal::MappingQGenericImplementation::maybe_update_Jacobians<dim,spacedim>
2655  (computed_cell_similarity,
2657  data);
2658 
2659  internal::MappingQGenericImplementation::maybe_update_jacobian_grads<dim,spacedim>
2660  (computed_cell_similarity,
2662  data,
2663  output_data.jacobian_grads);
2664  }
2665 
2666  internal::MappingQGenericImplementation::maybe_update_jacobian_pushed_forward_grads<dim,spacedim>
2667  (computed_cell_similarity,
2669  data,
2670  output_data.jacobian_pushed_forward_grads);
2671 
2672  internal::MappingQGenericImplementation::maybe_update_jacobian_2nd_derivatives<dim,spacedim>
2673  (computed_cell_similarity,
2675  data,
2676  output_data.jacobian_2nd_derivatives);
2677 
2678  internal::MappingQGenericImplementation::maybe_update_jacobian_pushed_forward_2nd_derivatives<dim,spacedim>
2679  (computed_cell_similarity,
2681  data,
2683 
2684  internal::MappingQGenericImplementation::maybe_update_jacobian_3rd_derivatives<dim,spacedim>
2685  (computed_cell_similarity,
2687  data,
2688  output_data.jacobian_3rd_derivatives);
2689 
2690  internal::MappingQGenericImplementation::maybe_update_jacobian_pushed_forward_3rd_derivatives<dim,spacedim>
2691  (computed_cell_similarity,
2693  data,
2695 
2696  const UpdateFlags update_flags = data.update_each;
2697  const std::vector<double> &weights=quadrature.get_weights();
2698 
2699  // Multiply quadrature weights by absolute value of Jacobian determinants or
2700  // the area element g=sqrt(DX^t DX) in case of codim > 0
2701 
2702  if (update_flags & (update_normal_vectors
2703  | update_JxW_values))
2704  {
2705  AssertDimension (output_data.JxW_values.size(), n_q_points);
2706 
2707  Assert( !(update_flags & update_normal_vectors ) ||
2708  (output_data.normal_vectors.size() == n_q_points),
2709  ExcDimensionMismatch(output_data.normal_vectors.size(), n_q_points));
2710 
2711 
2712  if (computed_cell_similarity != CellSimilarity::translation)
2713  for (unsigned int point=0; point<n_q_points; ++point)
2714  {
2715 
2716  if (dim == spacedim)
2717  {
2718  const double det = data.contravariant[point].determinant();
2719 
2720  // check for distorted cells.
2721 
2722  // TODO: this allows for anisotropies of up to 1e6 in 3D and
2723  // 1e12 in 2D. might want to find a finer
2724  // (dimension-independent) criterion
2725  Assert (det > 1e-12*Utilities::fixed_power<dim>(cell->diameter()/
2726  std::sqrt(double(dim))),
2727  (typename Mapping<dim,spacedim>::ExcDistortedMappedCell(cell->center(), det, point)));
2728 
2729  output_data.JxW_values[point] = weights[point] * det;
2730  }
2731  // if dim==spacedim, then there is no cell normal to
2732  // compute. since this is for FEValues (and not FEFaceValues),
2733  // there are also no face normals to compute
2734  else //codim>0 case
2735  {
2736  Tensor<1, spacedim> DX_t [dim];
2737  for (unsigned int i=0; i<spacedim; ++i)
2738  for (unsigned int j=0; j<dim; ++j)
2739  DX_t[j][i] = data.contravariant[point][i][j];
2740 
2741  Tensor<2, dim> G; //First fundamental form
2742  for (unsigned int i=0; i<dim; ++i)
2743  for (unsigned int j=0; j<dim; ++j)
2744  G[i][j] = DX_t[i] * DX_t[j];
2745 
2746  output_data.JxW_values[point]
2747  = sqrt(determinant(G)) * weights[point];
2748 
2749  if (computed_cell_similarity == CellSimilarity::inverted_translation)
2750  {
2751  // we only need to flip the normal
2752  if (update_flags & update_normal_vectors)
2753  output_data.normal_vectors[point] *= -1.;
2754  }
2755  else
2756  {
2757  if (update_flags & update_normal_vectors)
2758  {
2759  Assert(spacedim == dim+1,
2760  ExcMessage("There is no (unique) cell normal for "
2761  + Utilities::int_to_string(dim) +
2762  "-dimensional cells in "
2763  + Utilities::int_to_string(spacedim) +
2764  "-dimensional space. This only works if the "
2765  "space dimension is one greater than the "
2766  "dimensionality of the mesh cells."));
2767 
2768  if (dim==1)
2769  output_data.normal_vectors[point] =
2770  cross_product_2d(-DX_t[0]);
2771  else //dim == 2
2772  output_data.normal_vectors[point] =
2773  cross_product_3d(DX_t[0], DX_t[1]);
2774 
2775  output_data.normal_vectors[point] /= output_data.normal_vectors[point].norm();
2776 
2777  if (cell->direction_flag() == false)
2778  output_data.normal_vectors[point] *= -1.;
2779  }
2780 
2781  }
2782  } //codim>0 case
2783 
2784  }
2785  }
2786 
2787 
2788 
2789  // copy values from InternalData to vector given by reference
2790  if (update_flags & update_jacobians)
2791  {
2792  AssertDimension (output_data.jacobians.size(), n_q_points);
2793  if (computed_cell_similarity != CellSimilarity::translation)
2794  for (unsigned int point=0; point<n_q_points; ++point)
2795  output_data.jacobians[point] = data.contravariant[point];
2796  }
2797 
2798  // copy values from InternalData to vector given by reference
2799  if (update_flags & update_inverse_jacobians)
2800  {
2801  AssertDimension (output_data.inverse_jacobians.size(), n_q_points);
2802  if (computed_cell_similarity != CellSimilarity::translation)
2803  for (unsigned int point=0; point<n_q_points; ++point)
2804  output_data.inverse_jacobians[point] = data.covariant[point].transpose();
2805  }
2806 
2807  return computed_cell_similarity;
2808 }
2809 
2810 
2811 
2812 
2813 
2814 
2815 namespace internal
2816 {
2817  namespace MappingQGenericImplementation
2818  {
2819  namespace
2820  {
2830  template <int dim, int spacedim>
2831  void
2832  maybe_compute_face_data (const ::MappingQGeneric<dim,spacedim> &mapping,
2833  const typename ::Triangulation<dim,spacedim>::cell_iterator &cell,
2834  const unsigned int face_no,
2835  const unsigned int subface_no,
2836  const unsigned int n_q_points,
2837  const std::vector<double> &weights,
2838  const typename ::MappingQGeneric<dim,spacedim>::InternalData &data,
2840  {
2841  const UpdateFlags update_flags = data.update_each;
2842 
2843  if (update_flags & (update_boundary_forms |
2848  {
2849  if (update_flags & update_boundary_forms)
2850  AssertDimension (output_data.boundary_forms.size(), n_q_points);
2851  if (update_flags & update_normal_vectors)
2852  AssertDimension (output_data.normal_vectors.size(), n_q_points);
2853  if (update_flags & update_JxW_values)
2854  AssertDimension (output_data.JxW_values.size(), n_q_points);
2855 
2856  Assert (data.aux.size()+1 >= dim, ExcInternalError());
2857 
2858  // first compute some common data that is used for evaluating
2859  // all of the flags below
2860 
2861  // map the unit tangentials to the real cell. checking for d!=dim-1
2862  // eliminates compiler warnings regarding unsigned int expressions <
2863  // 0.
2864  for (unsigned int d=0; d!=dim-1; ++d)
2865  {
2867  data.unit_tangentials.size(),
2868  ExcInternalError());
2869  Assert (data.aux[d].size() <=
2870  data.unit_tangentials[face_no+GeometryInfo<dim>::faces_per_cell*d].size(),
2871  ExcInternalError());
2872 
2873  mapping.transform (make_array_view(data.unit_tangentials[face_no+GeometryInfo<dim>::faces_per_cell*d]),
2875  data,
2876  make_array_view(data.aux[d]));
2877  }
2878 
2879  if (update_flags & update_boundary_forms)
2880  {
2881  // if dim==spacedim, we can use the unit tangentials to compute the
2882  // boundary form by simply taking the cross product
2883  if (dim == spacedim)
2884  {
2885  for (unsigned int i=0; i<n_q_points; ++i)
2886  switch (dim)
2887  {
2888  case 1:
2889  // in 1d, we don't have access to any of the data.aux
2890  // fields (because it has only dim-1 components), but we
2891  // can still compute the boundary form by simply
2892  // looking at the number of the face
2893  output_data.boundary_forms[i][0] = (face_no == 0 ?
2894  -1 : +1);
2895  break;
2896  case 2:
2897  output_data.boundary_forms[i] =
2898  cross_product_2d(data.aux[0][i]);
2899  break;
2900  case 3:
2901  output_data.boundary_forms[i] =
2902  cross_product_3d(data.aux[0][i], data.aux[1][i]);
2903  break;
2904  default:
2905  Assert(false, ExcNotImplemented());
2906  }
2907  }
2908  else //(dim < spacedim)
2909  {
2910  // in the codim-one case, the boundary form results from the
2911  // cross product of all the face tangential vectors and the cell
2912  // normal vector
2913  //
2914  // to compute the cell normal, use the same method used in
2915  // fill_fe_values for cells above
2916  AssertDimension (data.contravariant.size(), n_q_points);
2917 
2918  for (unsigned int point=0; point<n_q_points; ++point)
2919  {
2920  if (dim==1)
2921  {
2922  // J is a tangent vector
2923  output_data.boundary_forms[point] = data.contravariant[point].transpose()[0];
2924  output_data.boundary_forms[point] /=
2925  (face_no == 0 ? -1. : +1.) * output_data.boundary_forms[point].norm();
2926  }
2927 
2928  if (dim==2)
2929  {
2930  const DerivativeForm<1,spacedim,dim> DX_t =
2931  data.contravariant[point].transpose();
2932 
2933  Tensor<1, spacedim> cell_normal =
2934  cross_product_3d(DX_t[0], DX_t[1]);
2935  cell_normal /= cell_normal.norm();
2936 
2937  // then compute the face normal from the face tangent
2938  // and the cell normal:
2939  output_data.boundary_forms[point] =
2940  cross_product_3d(data.aux[0][point], cell_normal);
2941  }
2942  }
2943  }
2944  }
2945 
2946  if (update_flags & update_JxW_values)
2947  for (unsigned int i=0; i<output_data.boundary_forms.size(); ++i)
2948  {
2949  output_data.JxW_values[i] = output_data.boundary_forms[i].norm() * weights[i];
2950 
2951  if (subface_no != numbers::invalid_unsigned_int)
2952  {
2953  const double area_ratio = GeometryInfo<dim>::subface_ratio(cell->subface_case(face_no),
2954  subface_no);
2955  output_data.JxW_values[i] *= area_ratio;
2956  }
2957  }
2958 
2959  if (update_flags & update_normal_vectors)
2960  for (unsigned int i=0; i<output_data.normal_vectors.size(); ++i)
2961  output_data.normal_vectors[i] = Point<spacedim>(output_data.boundary_forms[i] /
2962  output_data.boundary_forms[i].norm());
2963 
2964  if (update_flags & update_jacobians)
2965  for (unsigned int point=0; point<n_q_points; ++point)
2966  output_data.jacobians[point] = data.contravariant[point];
2967 
2968  if (update_flags & update_inverse_jacobians)
2969  for (unsigned int point=0; point<n_q_points; ++point)
2970  output_data.inverse_jacobians[point] = data.covariant[point].transpose();
2971  }
2972  }
2973 
2974 
2981  template <int dim, int spacedim>
2982  void
2983  do_fill_fe_face_values (const ::MappingQGeneric<dim,spacedim> &mapping,
2984  const typename ::Triangulation<dim,spacedim>::cell_iterator &cell,
2985  const unsigned int face_no,
2986  const unsigned int subface_no,
2987  const typename QProjector<dim>::DataSetDescriptor data_set,
2988  const Quadrature<dim-1> &quadrature,
2989  const typename ::MappingQGeneric<dim,spacedim>::InternalData &data,
2991  {
2992  if (dim>1 && data.tensor_product_quadrature)
2993  {
2994  maybe_update_q_points_Jacobians_and_grads_tensor<dim, spacedim>
2996  data,
2997  output_data.quadrature_points,
2998  output_data.jacobian_grads);
2999  }
3000  else
3001  {
3002  maybe_compute_q_points<dim,spacedim> (data_set,
3003  data,
3004  output_data.quadrature_points);
3005  maybe_update_Jacobians<dim,spacedim> (CellSimilarity::none,
3006  data_set,
3007  data);
3008  maybe_update_jacobian_grads<dim,spacedim> (CellSimilarity::none,
3009  data_set,
3010  data,
3011  output_data.jacobian_grads);
3012  }
3013  maybe_update_jacobian_pushed_forward_grads<dim,spacedim> (CellSimilarity::none,
3014  data_set,
3015  data,
3016  output_data.jacobian_pushed_forward_grads);
3017  maybe_update_jacobian_2nd_derivatives<dim,spacedim> (CellSimilarity::none,
3018  data_set,
3019  data,
3020  output_data.jacobian_2nd_derivatives);
3021  maybe_update_jacobian_pushed_forward_2nd_derivatives<dim,spacedim> (CellSimilarity::none,
3022  data_set,
3023  data,
3025  maybe_update_jacobian_3rd_derivatives<dim,spacedim> (CellSimilarity::none,
3026  data_set,
3027  data,
3028  output_data.jacobian_3rd_derivatives);
3029  maybe_update_jacobian_pushed_forward_3rd_derivatives<dim,spacedim> (CellSimilarity::none,
3030  data_set,
3031  data,
3033 
3034  maybe_compute_face_data (mapping,
3035  cell, face_no, subface_no, quadrature.size(),
3036  quadrature.get_weights(), data,
3037  output_data);
3038  }
3039  }
3040  }
3041 }
3042 
3043 
3044 
3045 template <int dim, int spacedim>
3046 void
3049  const unsigned int face_no,
3050  const Quadrature<dim-1> &quadrature,
3051  const typename Mapping<dim,spacedim>::InternalDataBase &internal_data,
3053 {
3054  // ensure that the following cast is really correct:
3055  Assert ((dynamic_cast<const InternalData *>(&internal_data) != nullptr),
3056  ExcInternalError());
3057  const InternalData &data
3058  = static_cast<const InternalData &>(internal_data);
3059 
3060  // if necessary, recompute the support points of the transformation of this cell
3061  // (note that we need to first check the triangulation pointer, since otherwise
3062  // the second test might trigger an exception if the triangulations are not the
3063  // same)
3064  if ((data.mapping_support_points.size() == 0)
3065  ||
3066  (&cell->get_triangulation() !=
3067  &data.cell_of_current_support_points->get_triangulation())
3068  ||
3069  (cell != data.cell_of_current_support_points))
3070  {
3071  data.mapping_support_points = this->compute_mapping_support_points(cell);
3072  data.cell_of_current_support_points = cell;
3073  }
3074 
3075  internal::MappingQGenericImplementation::do_fill_fe_face_values
3076  (*this,
3077  cell, face_no, numbers::invalid_unsigned_int,
3079  cell->face_orientation(face_no),
3080  cell->face_flip(face_no),
3081  cell->face_rotation(face_no),
3082  quadrature.size()),
3083  quadrature,
3084  data,
3085  output_data);
3086 }
3087 
3088 
3089 
3090 template <int dim, int spacedim>
3091 void
3094  const unsigned int face_no,
3095  const unsigned int subface_no,
3096  const Quadrature<dim-1> &quadrature,
3097  const typename Mapping<dim,spacedim>::InternalDataBase &internal_data,
3099 {
3100  // ensure that the following cast is really correct:
3101  Assert ((dynamic_cast<const InternalData *>(&internal_data) != nullptr),
3102  ExcInternalError());
3103  const InternalData &data
3104  = static_cast<const InternalData &>(internal_data);
3105 
3106  // if necessary, recompute the support points of the transformation of this cell
3107  // (note that we need to first check the triangulation pointer, since otherwise
3108  // the second test might trigger an exception if the triangulations are not the
3109  // same)
3110  if ((data.mapping_support_points.size() == 0)
3111  ||
3112  (&cell->get_triangulation() !=
3113  &data.cell_of_current_support_points->get_triangulation())
3114  ||
3115  (cell != data.cell_of_current_support_points))
3116  {
3117  data.mapping_support_points = this->compute_mapping_support_points(cell);
3118  data.cell_of_current_support_points = cell;
3119  }
3120 
3121  internal::MappingQGenericImplementation::do_fill_fe_face_values
3122  (*this,
3123  cell, face_no, subface_no,
3124  QProjector<dim>::DataSetDescriptor::subface (face_no, subface_no,
3125  cell->face_orientation(face_no),
3126  cell->face_flip(face_no),
3127  cell->face_rotation(face_no),
3128  quadrature.size(),
3129  cell->subface_case(face_no)),
3130  quadrature,
3131  data,
3132  output_data);
3133 }
3134 
3135 
3136 
3137 namespace internal
3138 {
3139  namespace MappingQGenericImplementation
3140  {
3141  namespace
3142  {
3143  template <int dim, int spacedim, int rank>
3144  void
3145  transform_fields(const ArrayView<const Tensor<rank,dim> > &input,
3146  const MappingType mapping_type,
3147  const typename Mapping<dim,spacedim>::InternalDataBase &mapping_data,
3148  const ArrayView<Tensor<rank,spacedim> > &output)
3149  {
3150  AssertDimension (input.size(), output.size());
3151  Assert ((dynamic_cast<const typename ::MappingQGeneric<dim,spacedim>::InternalData *>(&mapping_data) != nullptr),
3152  ExcInternalError());
3153  const typename ::MappingQGeneric<dim,spacedim>::InternalData
3154  &data = static_cast<const typename ::MappingQGeneric<dim,spacedim>::InternalData &>(mapping_data);
3155 
3156  switch (mapping_type)
3157  {
3158  case mapping_contravariant:
3159  {
3160  Assert (data.update_each & update_contravariant_transformation,
3161  typename FEValuesBase<dim>::ExcAccessToUninitializedField("update_contravariant_transformation"));
3162 
3163  for (unsigned int i=0; i<output.size(); ++i)
3164  output[i] = apply_transformation(data.contravariant[i], input[i]);
3165 
3166  return;
3167  }
3168 
3169  case mapping_piola:
3170  {
3171  Assert (data.update_each & update_contravariant_transformation,
3172  typename FEValuesBase<dim>::ExcAccessToUninitializedField("update_contravariant_transformation"));
3173  Assert (data.update_each & update_volume_elements,
3174  typename FEValuesBase<dim>::ExcAccessToUninitializedField("update_volume_elements"));
3175  Assert (rank==1, ExcMessage("Only for rank 1"));
3176  if (rank!=1)
3177  return;
3178 
3179  for (unsigned int i=0; i<output.size(); ++i)
3180  {
3181  output[i] = apply_transformation(data.contravariant[i], input[i]);
3182  output[i] /= data.volume_elements[i];
3183  }
3184  return;
3185  }
3186  //We still allow this operation as in the
3187  //reference cell Derivatives are Tensor
3188  //rather than DerivativeForm
3189  case mapping_covariant:
3190  {
3191  Assert (data.update_each & update_contravariant_transformation,
3192  typename FEValuesBase<dim>::ExcAccessToUninitializedField("update_covariant_transformation"));
3193 
3194  for (unsigned int i=0; i<output.size(); ++i)
3195  output[i] = apply_transformation(data.covariant[i], input[i]);
3196 
3197  return;
3198  }
3199 
3200  default:
3201  Assert(false, ExcNotImplemented());
3202  }
3203  }
3204 
3205 
3206  template <int dim, int spacedim, int rank>
3207  void
3208  transform_gradients(const ArrayView<const Tensor<rank,dim> > &input,
3209  const MappingType mapping_type,
3210  const typename Mapping<dim,spacedim>::InternalDataBase &mapping_data,
3211  const ArrayView<Tensor<rank,spacedim> > &output)
3212  {
3213  AssertDimension (input.size(), output.size());
3214  Assert ((dynamic_cast<const typename ::MappingQGeneric<dim,spacedim>::InternalData *>(&mapping_data) != nullptr),
3215  ExcInternalError());
3216  const typename ::MappingQGeneric<dim,spacedim>::InternalData
3217  &data = static_cast<const typename ::MappingQGeneric<dim,spacedim>::InternalData &>(mapping_data);
3218 
3219  switch (mapping_type)
3220  {
3222  {
3223  Assert (data.update_each & update_covariant_transformation,
3224  typename FEValuesBase<dim>::ExcAccessToUninitializedField("update_covariant_transformation"));
3225  Assert (data.update_each & update_contravariant_transformation,
3226  typename FEValuesBase<dim>::ExcAccessToUninitializedField("update_contravariant_transformation"));
3227  Assert (rank==2, ExcMessage("Only for rank 2"));
3228 
3229  for (unsigned int i=0; i<output.size(); ++i)
3230  {
3232  apply_transformation(data.contravariant[i], transpose(input[i]) );
3233  output[i] = apply_transformation(data.covariant[i], A.transpose() );
3234  }
3235 
3236  return;
3237  }
3238 
3240  {
3241  Assert (data.update_each & update_covariant_transformation,
3242  typename FEValuesBase<dim>::ExcAccessToUninitializedField("update_covariant_transformation"));
3243  Assert (rank==2, ExcMessage("Only for rank 2"));
3244 
3245  for (unsigned int i=0; i<output.size(); ++i)
3246  {
3248  apply_transformation(data.covariant[i], transpose(input[i]) );
3249  output[i] = apply_transformation(data.covariant[i], A.transpose() );
3250  }
3251 
3252  return;
3253  }
3254 
3256  {
3257  Assert (data.update_each & update_covariant_transformation,
3258  typename FEValuesBase<dim>::ExcAccessToUninitializedField("update_covariant_transformation"));
3259  Assert (data.update_each & update_contravariant_transformation,
3260  typename FEValuesBase<dim>::ExcAccessToUninitializedField("update_contravariant_transformation"));
3261  Assert (data.update_each & update_volume_elements,
3262  typename FEValuesBase<dim>::ExcAccessToUninitializedField("update_volume_elements"));
3263  Assert (rank==2, ExcMessage("Only for rank 2"));
3264 
3265  for (unsigned int i=0; i<output.size(); ++i)
3266  {
3268  apply_transformation(data.covariant[i], input[i] );
3269  Tensor<2,spacedim> T =
3270  apply_transformation(data.contravariant[i], A.transpose() );
3271 
3272  output[i] = transpose(T);
3273  output[i] /= data.volume_elements[i];
3274  }
3275 
3276  return;
3277  }
3278 
3279  default:
3280  Assert(false, ExcNotImplemented());
3281  }
3282  }
3283 
3284 
3285 
3286 
3287  template <int dim, int spacedim>
3288  void
3289  transform_hessians(const ArrayView<const Tensor<3,dim> > &input,
3290  const MappingType mapping_type,
3291  const typename Mapping<dim,spacedim>::InternalDataBase &mapping_data,
3292  const ArrayView<Tensor<3,spacedim> > &output)
3293  {
3294  AssertDimension (input.size(), output.size());
3295  Assert ((dynamic_cast<const typename ::MappingQGeneric<dim,spacedim>::InternalData *>(&mapping_data) != nullptr),
3296  ExcInternalError());
3297  const typename ::MappingQGeneric<dim,spacedim>::InternalData
3298  &data = static_cast<const typename ::MappingQGeneric<dim,spacedim>::InternalData &>(mapping_data);
3299 
3300  switch (mapping_type)
3301  {
3303  {
3304  Assert (data.update_each & update_covariant_transformation,
3305  typename FEValuesBase<dim>::ExcAccessToUninitializedField("update_covariant_transformation"));
3306  Assert (data.update_each & update_contravariant_transformation,
3307  typename FEValuesBase<dim>::ExcAccessToUninitializedField("update_contravariant_transformation"));
3308 
3309  for (unsigned int q=0; q<output.size(); ++q)
3310  for (unsigned int i=0; i<spacedim; ++i)
3311  {
3312  double tmp1[dim][dim];
3313  for (unsigned int J=0; J<dim; ++J)
3314  for (unsigned int K=0; K<dim; ++K)
3315  {
3316  tmp1[J][K] = data.contravariant[q][i][0] * input[q][0][J][K];
3317  for (unsigned int I=1; I<dim; ++I)
3318  tmp1[J][K] += data.contravariant[q][i][I] * input[q][I][J][K];
3319  }
3320  for (unsigned int j=0; j<spacedim; ++j)
3321  {
3322  double tmp2[dim];
3323  for (unsigned int K=0; K<dim; ++K)
3324  {
3325  tmp2[K] = data.covariant[q][j][0] * tmp1[0][K];
3326  for (unsigned int J=1; J<dim; ++J)
3327  tmp2[K] += data.covariant[q][j][J] * tmp1[J][K];
3328  }
3329  for (unsigned int k=0; k<spacedim; ++k)
3330  {
3331  output[q][i][j][k] = data.covariant[q][k][0] * tmp2[0];
3332  for (unsigned int K=1; K<dim; ++K)
3333  output[q][i][j][k] += data.covariant[q][k][K] * tmp2[K];
3334  }
3335  }
3336  }
3337  return;
3338  }
3339 
3341  {
3342  Assert (data.update_each & update_covariant_transformation,
3343  typename FEValuesBase<dim>::ExcAccessToUninitializedField("update_covariant_transformation"));
3344 
3345  for (unsigned int q=0; q<output.size(); ++q)
3346  for (unsigned int i=0; i<spacedim; ++i)
3347  {
3348  double tmp1[dim][dim];
3349  for (unsigned int J=0; J<dim; ++J)
3350  for (unsigned int K=0; K<dim; ++K)
3351  {
3352  tmp1[J][K] = data.covariant[q][i][0] * input[q][0][J][K];
3353  for (unsigned int I=1; I<dim; ++I)
3354  tmp1[J][K] += data.covariant[q][i][I] * input[q][I][J][K];
3355  }
3356  for (unsigned int j=0; j<spacedim; ++j)
3357  {
3358  double tmp2[dim];
3359  for (unsigned int K=0; K<dim; ++K)
3360  {
3361  tmp2[K] = data.covariant[q][j][0] * tmp1[0][K];
3362  for (unsigned int J=1; J<dim; ++J)
3363  tmp2[K] += data.covariant[q][j][J] * tmp1[J][K];
3364  }
3365  for (unsigned int k=0; k<spacedim; ++k)
3366  {
3367  output[q][i][j][k] = data.covariant[q][k][0] * tmp2[0];
3368  for (unsigned int K=1; K<dim; ++K)
3369  output[q][i][j][k] += data.covariant[q][k][K] * tmp2[K];
3370  }
3371  }
3372  }
3373 
3374  return;
3375  }
3376 
3377  case mapping_piola_hessian:
3378  {
3379  Assert (data.update_each & update_covariant_transformation,
3380  typename FEValuesBase<dim>::ExcAccessToUninitializedField("update_covariant_transformation"));
3381  Assert (data.update_each & update_contravariant_transformation,
3382  typename FEValuesBase<dim>::ExcAccessToUninitializedField("update_contravariant_transformation"));
3383  Assert (data.update_each & update_volume_elements,
3384  typename FEValuesBase<dim>::ExcAccessToUninitializedField("update_volume_elements"));
3385 
3386  for (unsigned int q=0; q<output.size(); ++q)
3387  for (unsigned int i=0; i<spacedim; ++i)
3388  {
3389  double factor[dim];
3390  for (unsigned int I=0; I<dim; ++I)
3391  factor[I] = data.contravariant[q][i][I] / data.volume_elements[q];
3392  double tmp1[dim][dim];
3393  for (unsigned int J=0; J<dim; ++J)
3394  for (unsigned int K=0; K<dim; ++K)
3395  {
3396  tmp1[J][K] = factor[0] * input[q][0][J][K];
3397  for (unsigned int I=1; I<dim; ++I)
3398  tmp1[J][K] += factor[I] * input[q][I][J][K];
3399  }
3400  for (unsigned int j=0; j<spacedim; ++j)
3401  {
3402  double tmp2[dim];
3403  for (unsigned int K=0; K<dim; ++K)
3404  {
3405  tmp2[K] = data.covariant[q][j][0] * tmp1[0][K];
3406  for (unsigned int J=1; J<dim; ++J)
3407  tmp2[K] += data.covariant[q][j][J] * tmp1[J][K];
3408  }
3409  for (unsigned int k=0; k<spacedim; ++k)
3410  {
3411  output[q][i][j][k] = data.covariant[q][k][0] * tmp2[0];
3412  for (unsigned int K=1; K<dim; ++K)
3413  output[q][i][j][k] += data.covariant[q][k][K] * tmp2[K];
3414  }
3415  }
3416  }
3417 
3418  return;
3419  }
3420 
3421  default:
3422  Assert(false, ExcNotImplemented());
3423  }
3424  }
3425 
3426 
3427 
3428 
3429  template <int dim, int spacedim, int rank>
3430  void
3431  transform_differential_forms(const ArrayView<const DerivativeForm<rank, dim,spacedim> > &input,
3432  const MappingType mapping_type,
3433  const typename Mapping<dim,spacedim>::InternalDataBase &mapping_data,
3434  const ArrayView<Tensor<rank+1, spacedim> > &output)
3435  {
3436  AssertDimension (input.size(), output.size());
3437  Assert ((dynamic_cast<const typename ::MappingQGeneric<dim,spacedim>::InternalData *>(&mapping_data) != nullptr),
3438  ExcInternalError());
3439  const typename ::MappingQGeneric<dim,spacedim>::InternalData
3440  &data = static_cast<const typename ::MappingQGeneric<dim,spacedim>::InternalData &>(mapping_data);
3441 
3442  switch (mapping_type)
3443  {
3444  case mapping_covariant:
3445  {
3446  Assert (data.update_each & update_contravariant_transformation,
3447  typename FEValuesBase<dim>::ExcAccessToUninitializedField("update_covariant_transformation"));
3448 
3449  for (unsigned int i=0; i<output.size(); ++i)
3450  output[i] = apply_transformation(data.covariant[i], input[i]);
3451 
3452  return;
3453  }
3454  default:
3455  Assert(false, ExcNotImplemented());
3456  }
3457  }
3458  }
3459  }
3460 }
3461 
3462 
3463 
3464 template <int dim, int spacedim>
3465 void
3467 transform (const ArrayView<const Tensor<1, dim> > &input,
3468  const MappingType mapping_type,
3469  const typename Mapping<dim,spacedim>::InternalDataBase &mapping_data,
3470  const ArrayView<Tensor<1, spacedim> > &output) const
3471 {
3472  internal::MappingQGenericImplementation::transform_fields(input, mapping_type, mapping_data, output);
3473 }
3474 
3475 
3476 
3477 template <int dim, int spacedim>
3478 void
3481  const MappingType mapping_type,
3482  const typename Mapping<dim,spacedim>::InternalDataBase &mapping_data,
3483  const ArrayView<Tensor<2, spacedim> > &output) const
3484 {
3485  internal::MappingQGenericImplementation::transform_differential_forms(input, mapping_type, mapping_data, output);
3486 }
3487 
3488 
3489 
3490 template <int dim, int spacedim>
3491 void
3493 transform (const ArrayView<const Tensor<2, dim> > &input,
3494  const MappingType mapping_type,
3495  const typename Mapping<dim,spacedim>::InternalDataBase &mapping_data,
3496  const ArrayView<Tensor<2, spacedim> > &output) const
3497 {
3498  switch (mapping_type)
3499  {
3500  case mapping_contravariant:
3501  internal::MappingQGenericImplementation::transform_fields(input, mapping_type, mapping_data, output);
3502  return;
3503 
3507  internal::MappingQGenericImplementation::transform_gradients(input, mapping_type, mapping_data, output);
3508  return;
3509  default:
3510  Assert(false, ExcNotImplemented());
3511  }
3512 }
3513 
3514 
3515 
3516 template <int dim, int spacedim>
3517 void
3520  const MappingType mapping_type,
3521  const typename Mapping<dim,spacedim>::InternalDataBase &mapping_data,
3522  const ArrayView<Tensor<3,spacedim> > &output) const
3523 {
3524 
3525  AssertDimension (input.size(), output.size());
3526  Assert (dynamic_cast<const InternalData *>(&mapping_data) != nullptr,
3527  ExcInternalError());
3528  const InternalData &data = static_cast<const InternalData &>(mapping_data);
3529 
3530  switch (mapping_type)
3531  {
3533  {
3535  typename FEValuesBase<dim>::ExcAccessToUninitializedField("update_covariant_transformation"));
3536 
3537  for (unsigned int q=0; q<output.size(); ++q)
3538  for (unsigned int i=0; i<spacedim; ++i)
3539  for (unsigned int j=0; j<spacedim; ++j)
3540  {
3541  double tmp[dim];
3542  for (unsigned int K=0; K<dim; ++K)
3543  {
3544  tmp[K] = data.covariant[q][j][0] * input[q][i][0][K];
3545  for (unsigned int J=1; J<dim; ++J)
3546  tmp[K] += data.covariant[q][j][J] * input[q][i][J][K];
3547  }
3548  for (unsigned int k=0; k<spacedim; ++k)
3549  {
3550  output[q][i][j][k] = data.covariant[q][k][0] * tmp[0];
3551  for (unsigned int K=1; K<dim; ++K)
3552  output[q][i][j][k] += data.covariant[q][k][K] * tmp[K];
3553  }
3554  }
3555  return;
3556  }
3557 
3558  default:
3559  Assert(false, ExcNotImplemented());
3560  }
3561 }
3562 
3563 
3564 
3565 template <int dim, int spacedim>
3566 void
3568 transform (const ArrayView<const Tensor<3,dim> > &input,
3569  const MappingType mapping_type,
3570  const typename Mapping<dim,spacedim>::InternalDataBase &mapping_data,
3571  const ArrayView<Tensor<3,spacedim> > &output) const
3572 {
3573  switch (mapping_type)
3574  {
3575  case mapping_piola_hessian:
3578  internal::MappingQGenericImplementation::transform_hessians(input, mapping_type, mapping_data, output);
3579  return;
3580  default:
3581  Assert(false, ExcNotImplemented());
3582  }
3583 }
3584 
3585 
3586 
3587 template <int dim, int spacedim>
3588 void
3591  std::vector<Point<spacedim> > &a) const
3592 {
3593  // if we only need the midpoint, then ask for it.
3594  if (this->polynomial_degree==2)
3595  {
3596  for (unsigned int line_no=0; line_no<GeometryInfo<dim>::lines_per_cell; ++line_no)
3597  {
3598  const typename Triangulation<dim,spacedim>::line_iterator line =
3599  (dim == 1 ?
3600  static_cast<typename Triangulation<dim,spacedim>::line_iterator>(cell) :
3601  cell->line(line_no));
3602 
3603  const Manifold<dim,spacedim> &manifold =
3604  ( ( line->manifold_id() == numbers::invalid_manifold_id ) &&
3605  ( dim < spacedim )
3606  ?
3607  cell->get_manifold()
3608  :
3609  line->get_manifold() );
3610  a.push_back(manifold.get_new_point_on_line(line));
3611  }
3612  }
3613  else
3614  // otherwise call the more complicated functions and ask for inner points
3615  // from the boundary description
3616  {
3617  std::vector<Point<spacedim> > tmp_points;
3618  // loop over each of the lines, and if it is at the boundary, then first
3619  // get the boundary description and second compute the points on it
3620  for (unsigned int line_no=0; line_no<GeometryInfo<dim>::lines_per_cell; ++line_no)
3621  {
3622  const typename Triangulation<dim,spacedim>::line_iterator
3623  line = (dim == 1
3624  ?
3625  static_cast<typename Triangulation<dim,spacedim>::line_iterator>(cell)
3626  :
3627  cell->line(line_no));
3628 
3629  const Manifold<dim,spacedim> &manifold =
3630  ( ( line->manifold_id() == numbers::invalid_manifold_id ) &&
3631  ( dim < spacedim )
3632  ?
3633  cell->get_manifold() :
3634  line->get_manifold() );
3635 
3636  if (const Boundary<dim,spacedim> *boundary
3637  = dynamic_cast<const Boundary<dim,spacedim> *>(&manifold))
3638  {
3639  tmp_points.resize(this->polynomial_degree-1);
3640  boundary->get_intermediate_points_on_line(line, tmp_points);
3641  if (dim != 3 || cell->line_orientation(line_no))
3642  a.insert (a.end(), tmp_points.begin(), tmp_points.end());
3643  else
3644  a.insert (a.end(), tmp_points.rbegin(), tmp_points.rend());
3645  }
3646  else
3647  {
3648  const std::array<Point<spacedim>, 2> vertices
3649  {
3650  {
3651  cell->vertex(GeometryInfo<dim>::line_to_cell_vertices(line_no, 0)),
3652  cell->vertex(GeometryInfo<dim>::line_to_cell_vertices(line_no, 1))
3653  }
3654  };
3655 
3656  const std::size_t n_rows = support_point_weights_perimeter_to_interior[0].size(0);
3657  a.resize(a.size() + n_rows);
3658  auto a_view = make_array_view(a.end() - n_rows, a.end());
3659  manifold.get_new_points(make_array_view(vertices.begin(),
3660  vertices.end()),
3661  support_point_weights_perimeter_to_interior[0],
3662  a_view);
3663  }
3664  }
3665  }
3666 }
3667 
3668 
3669 
3670 template <>
3671 void
3674  std::vector<Point<3> > &a) const
3675 {
3676  const unsigned int faces_per_cell = GeometryInfo<3>::faces_per_cell;
3677 
3678  // used if face quad at boundary or entirely in the interior of the domain
3679  std::vector<Point<3> > tmp_points;
3680 
3681  // loop over all faces and collect points on them
3682  for (unsigned int face_no=0; face_no<faces_per_cell; ++face_no)
3683  {
3684  const Triangulation<3>::face_iterator face = cell->face(face_no);
3685 
3686  // select the correct mappings for the present face
3687  const bool face_orientation = cell->face_orientation(face_no),
3688  face_flip = cell->face_flip (face_no),
3689  face_rotation = cell->face_rotation (face_no);
3690 
3691 #ifdef DEBUG
3692  const unsigned int vertices_per_face = GeometryInfo<3>::vertices_per_face,
3693  lines_per_face = GeometryInfo<3>::lines_per_face;
3694 
3695  // some sanity checks up front
3696  for (unsigned int i=0; i<vertices_per_face; ++i)
3697  Assert(face->vertex_index(i)==cell->vertex_index(
3699  face_orientation,
3700  face_flip,
3701  face_rotation)),
3702  ExcInternalError());
3703 
3704  // indices of the lines that bound a face are given by GeometryInfo<3>::
3705  // face_to_cell_lines
3706  for (unsigned int i=0; i<lines_per_face; ++i)
3707  Assert(face->line(i)==cell->line(GeometryInfo<3>::face_to_cell_lines(
3708  face_no, i, face_orientation, face_flip, face_rotation)),
3709  ExcInternalError());
3710 #endif
3711 
3712  // On a quad, we have to check whether the manifold should determine the
3713  // point distribution from all surrounding points (new manifold code) or
3714  // the old-style Boundary code should simply return the intermediate
3715  // points. The second check is to find out whether the Boundary object
3716  // is actually a StraightBoundary (the default flat manifold assigned to
3717  // the triangulation if no manifold is assigned).
3718  const Boundary<3,3> *boundary =
3719  dynamic_cast<const Boundary<3,3> *>(&face->get_manifold());
3720  if (boundary != nullptr &&
3721  std::string(typeid(*boundary).name()).find("StraightBoundary") ==
3722  std::string::npos)
3723  {
3724  // ask the boundary/manifold object to return intermediate points on it
3725  tmp_points.resize((polynomial_degree-1)*(polynomial_degree-1));
3726  boundary->get_intermediate_points_on_quad(face, tmp_points);
3727  for (unsigned int i=0; i<tmp_points.size(); ++i)
3728  a.push_back(tmp_points[fe_q->adjust_quad_dof_index_for_face_orientation(i,
3729  face_orientation,
3730  face_flip,
3731  face_rotation)]);
3732  }
3733  else
3734  {
3735  // extract the points surrounding a quad from the points
3736  // already computed. First get the 4 vertices and then the points on
3737  // the four lines
3738  boost::container::small_vector<Point<3>, 200>
3740  + GeometryInfo<2>::lines_per_cell*(polynomial_degree-1));
3741  for (unsigned int v=0; v<GeometryInfo<2>::vertices_per_cell; ++v)
3742  tmp_points[v] = a[GeometryInfo<3>::face_to_cell_vertices(face_no,v)];
3743  if (polynomial_degree > 1)
3744  for (unsigned int line=0; line<GeometryInfo<2>::lines_per_cell; ++line)
3745  for (unsigned int i=0; i<polynomial_degree-1; ++i)
3746  tmp_points[4+line*(polynomial_degree-1)+i] =
3748  (polynomial_degree-1)*
3749  GeometryInfo<3>::face_to_cell_lines(face_no,line) + i];
3750 
3751  const std::size_t n_rows = support_point_weights_perimeter_to_interior[1].size(0);
3752  a.resize(a.size() + n_rows);
3753  auto a_view = make_array_view(a.end() - n_rows, a.end());
3754  face->get_manifold().get_new_points (make_array_view(tmp_points.begin(),
3755  tmp_points.end()),
3756  support_point_weights_perimeter_to_interior[1],
3757  a_view);
3758  }
3759  }
3760 }
3761 
3762 
3763 
3764 template <>
3765 void
3768  std::vector<Point<3> > &a) const
3769 {
3770  if (const Boundary<2,3> *boundary =
3771  dynamic_cast<const Boundary<2,3> *>(&cell->get_manifold()))
3772  {
3773  std::vector<Point<3> > points((polynomial_degree-1)*(polynomial_degree-1));
3774  boundary->get_intermediate_points_on_quad(cell, points);
3775  a.insert(a.end(), points.begin(), points.end());
3776  }
3777  else
3778  {
3779  std::array<Point<3>, GeometryInfo<2>::vertices_per_cell> vertices;
3780  for (unsigned int i=0; i<GeometryInfo<2>::vertices_per_cell; ++i)
3781  vertices[i] = cell->vertex(i);
3782 
3783  Table<2,double> weights(Utilities::fixed_power<2>(polynomial_degree-1),
3785  for (unsigned int q=0, q2=0; q2<polynomial_degree-1; ++q2)
3786  for (unsigned int q1=0; q1<polynomial_degree-1; ++q1, ++q)
3787  {
3788  Point<2> point(line_support_points.point(q1+1)[0],
3789  line_support_points.point(q2+1)[0]);
3790  for (unsigned int i=0; i<GeometryInfo<2>::vertices_per_cell; ++i)
3791  weights(q,i) = GeometryInfo<2>::d_linear_shape_function(point, i);
3792  }
3793  // TODO: use all surrounding points once Boundary path is removed
3794  const std::size_t n_rows = weights.size(0);
3795  a.resize(a.size() + n_rows);
3796  auto a_view = make_array_view(a.end() - n_rows, a.end());
3797  cell->get_manifold().get_new_points(make_array_view(vertices.begin(),
3798  vertices.end()),
3799  weights,
3800  a_view);
3801  }
3802 }
3803 
3804 
3805 
3806 template <int dim, int spacedim>
3807 void
3810  std::vector<Point<spacedim> > &) const
3811 {
3812  Assert (false, ExcInternalError());
3813 }
3814 
3815 
3816 
3817 template <int dim, int spacedim>
3818 std::vector<Point<spacedim> >
3821 {
3822  // get the vertices first
3823  std::vector<Point<spacedim> > a;
3824  a.reserve(Utilities::fixed_power<dim>(polynomial_degree+1));
3825  for (unsigned int i=0; i<GeometryInfo<dim>::vertices_per_cell; ++i)
3826  a.push_back(cell->vertex(i));
3827 
3828  if (this->polynomial_degree > 1)
3829  {
3830  // check if all entities have the same manifold id which is when we can
3831  // simply ask the manifold for all points. the transfinite manifold can
3832  // do the interpolation better than this class, so if we detect that we
3833  // do not have to change anything here
3834  Assert(dim<=3, ExcImpossibleInDim(dim));
3835  bool all_manifold_ids_are_equal = (dim == spacedim);
3836  if (all_manifold_ids_are_equal &&
3837  dynamic_cast<const TransfiniteInterpolationManifold<dim,spacedim>*>(&cell->get_manifold()) == nullptr)
3838  {
3839  for (unsigned int f=0; f<GeometryInfo<dim>::faces_per_cell; ++f)
3840  if (&cell->face(f)->get_manifold() != &cell->get_manifold())
3841  all_manifold_ids_are_equal = false;
3842 
3843  if (dim == 3)
3844  for (unsigned int l=0; l<GeometryInfo<dim>::lines_per_cell; ++l)
3845  if (&cell->line(l)->get_manifold() != &cell->get_manifold())
3846  all_manifold_ids_are_equal = false;
3847  }
3848 
3849  if (all_manifold_ids_are_equal)
3850  {
3851  const std::size_t n_rows = support_point_weights_cell.size(0);
3852  a.resize(a.size() + n_rows);
3853  auto a_view = make_array_view(a.end() - n_rows, a.end());
3854  cell->get_manifold().get_new_points(make_array_view(a.begin(),
3855  a.end() - n_rows),
3856  support_point_weights_cell,
3857  a_view);
3858  }
3859  else
3860  switch (dim)
3861  {
3862  case 1:
3863  add_line_support_points(cell, a);
3864  break;
3865  case 2:
3866  // in 2d, add the points on the four bounding lines to the exterior
3867  // (outer) points
3868  add_line_support_points(cell, a);
3869 
3870  // then get the interior support points
3871  if (dim != spacedim)
3872  add_quad_support_points(cell, a);
3873  else
3874  {
3875  const std::size_t n_rows = support_point_weights_perimeter_to_interior[1].size(0);
3876  a.resize(a.size() + n_rows);
3877  auto a_view = make_array_view(a.end() - n_rows, a.end());
3878  cell->get_manifold().get_new_points(make_array_view(a.begin(),
3879  a.end() - n_rows),
3880  support_point_weights_perimeter_to_interior[1],
3881  a_view);
3882  }
3883  break;
3884 
3885  case 3:
3886  // in 3d also add the points located on the boundary faces
3887  add_line_support_points (cell, a);
3888  add_quad_support_points (cell, a);
3889 
3890  // then compute the interior points
3891  {
3892  const std::size_t n_rows = support_point_weights_perimeter_to_interior[2].size(0);
3893  a.resize(a.size() + n_rows);
3894  auto a_view = make_array_view(a.end() - n_rows, a.end());
3895  cell->get_manifold().get_new_points(make_array_view(a.begin(),
3896  a.end() - n_rows),
3897  support_point_weights_perimeter_to_interior[2],
3898  a_view);
3899  }
3900  break;
3901 
3902  default:
3903  Assert(false, ExcNotImplemented());
3904  break;
3905  }
3906  }
3907 
3908  return a;
3909 }
3910 
3911 
3912 
3913 //--------------------------- Explicit instantiations -----------------------
3914 #include "mapping_q_generic.inst"
3915 
3916 
3917 DEAL_II_NAMESPACE_CLOSE
Transformed quadrature weights.
unsigned int n() const
std::vector< DerivativeForm< 1, dim, spacedim > > covariant
std::vector< Tensor< 1, spacedim > > normal_vectors
void loop(ITERATOR begin, typename identity< ITERATOR >::type end, DOFINFO &dinfo, INFOBOX &info, const std::function< void(DOFINFO &, typename INFOBOX::CellInfo &)> &cell_worker, const std::function< void(DOFINFO &, typename INFOBOX::CellInfo &)> &boundary_worker, const std::function< void(DOFINFO &, DOFINFO &, typename INFOBOX::CellInfo &, typename INFOBOX::CellInfo &)> &face_worker, ASSEMBLER &assembler, const LoopControl &lctrl=LoopControl())
Definition: loop.h:386
Definition: tria.h:67
static const unsigned int invalid_unsigned_int
Definition: types.h:173
#define AssertDimension(dim1, dim2)
Definition: exceptions.h:1248
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
Number determinant(const SymmetricTensor< 2, dim, Number > &)
std::vector< Tensor< 2, dim > > shape_second_derivatives
const unsigned int polynomial_degree
Contravariant transformation.
std::vector< DerivativeForm< 1, dim, spacedim > > jacobians
const std::vector< Point< dim > > & get_points() const
std::vector< Tensor< 4, spacedim > > jacobian_pushed_forward_2nd_derivatives
const std::vector< double > & get_weights() const
SymmetricTensor< 2, dim, Number > e(const Tensor< 2, dim, Number > &F)
Point< spacedim > point(const gp_Pnt &p, const double &tolerance=1e-10)
Definition: utilities.cc:183
MappingType
Definition: mapping.h:51
virtual UpdateFlags requires_update_flags(const UpdateFlags update_flags) const override
std::vector< Table< 2, double > > support_point_weights_perimeter_to_interior
std::vector< Tensor< 4, dim > > shape_fourth_derivatives
virtual Point< spacedim > transform_unit_to_real_cell(const typename Triangulation< dim, spacedim >::cell_iterator &cell, const Point< dim > &p) const override
std::vector< DerivativeForm< 4, dim, spacedim > > jacobian_3rd_derivatives
Volume element.
Outer normal vector, not normalized.
std::vector< Polynomial< double > > generate_complete_Lagrange_basis(const std::vector< Point< 1 > > &points)
Definition: polynomial.cc:830
Table< 2, double > support_point_weights_cell
virtual std::unique_ptr< Mapping< dim, spacedim > > clone() const override
Determinant of the Jacobian.
active_cell_iterator begin_active(const unsigned int level=0) const
Definition: tria.cc:10508
std::conditional< dim==1, std::array< Quadrature< 1 >, dim >, const std::array< Quadrature< 1 >, dim > & >::type get_tensor_basis() const
Definition: quadrature.cc:332
Triangulation< dim, spacedim >::cell_iterator cell_of_current_support_points
Transformed quadrature points.
const Tensor< 3, dim > & third_derivative(const unsigned int qpoint, const unsigned int shape_nr) const
virtual CellSimilarity::Similarity fill_fe_values(const typename Triangulation< dim, spacedim >::cell_iterator &cell, const CellSimilarity::Similarity cell_similarity, const Quadrature< dim > &quadrature, const typename Mapping< dim, spacedim >::InternalDataBase &internal_data, ::internal::FEValuesImplementation::MappingRelatedData< dim, spacedim > &output_data) const override
MappingQGeneric(const unsigned int polynomial_degree)
#define AssertThrow(cond, exc)
Definition: exceptions.h:1221
numbers::NumberTraits< Number >::real_type norm() const
Definition: tensor.h:1273
std::vector< Tensor< 5, spacedim > > jacobian_pushed_forward_3rd_derivatives
static DataSetDescriptor cell()
Definition: qprojector.h:348
const Tensor< 4, dim > & fourth_derivative(const unsigned int qpoint, const unsigned int shape_nr) const
Definition: point.h:104
const std::unique_ptr< FE_Q< dim > > fe_q
InternalData(const unsigned int polynomial_degree)
std::unique_ptr< To > dynamic_unique_cast(std::unique_ptr< From > &&p)
Definition: utilities.h:592
std::vector< Tensor< 1, dim > > shape_derivatives
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
SymmetricTensor< 2, dim, Number > invert(const SymmetricTensor< 2, dim, Number > &)
virtual void add_quad_support_points(const typename Triangulation< dim, spacedim >::cell_iterator &cell, std::vector< Point< spacedim > > &a) const
ArrayView< typename std::remove_reference< typename std::iterator_traits< Iterator >::reference >::type > make_array_view(const Iterator begin, const Iterator end)
Definition: array_view.h:490
void compute_shape_function_values(const std::vector< Point< dim > > &unit_points)
virtual void get_intermediate_points_on_quad(const typename Triangulation< dim, spacedim >::quad_iterator &quad, std::vector< Point< spacedim > > &points) const
std::vector< DerivativeForm< 2, dim, spacedim > > jacobian_grads
Definition: tria.h:45
static ::ExceptionBase & ExcMessage(std::string arg1)
virtual Point< spacedim > get_new_point_on_line(const typename Triangulation< dim, spacedim >::line_iterator &line) const
Definition: manifold.cc:306
static ::ExceptionBase & ExcImpossibleInDim(int arg1)
void reinit(const TableIndices< N > &new_size, const bool omit_default_initialization=false)
Tensor< 1, dim, Number > cross_product_2d(const Tensor< 1, dim, Number > &src)
Definition: tensor.h:1945
#define Assert(cond, exc)
Definition: exceptions.h:1142
UpdateFlags
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
Abstract base class for mapping classes.
Definition: dof_tools.h:46
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
virtual void create_triangulation(const std::vector< Point< spacedim > > &vertices, const std::vector< CellData< dim > > &cells, const SubCellData &subcelldata)
Definition: tria.cc:9240
std::vector< Point< spacedim > > mapping_support_points
DerivativeForm< 1, spacedim, dim, Number > transpose() const
virtual std::unique_ptr< typename Mapping< dim, spacedim >::InternalDataBase > get_data(const UpdateFlags, const Quadrature< dim > &quadrature) const override
SymmetricTensor< rank_, dim, Number > transpose(const SymmetricTensor< rank_, dim, Number > &t)
void initialize(const UpdateFlags update_flags, const Quadrature< dim > &quadrature, const unsigned int n_original_q_points)
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< Tensor< 3, spacedim > > jacobian_pushed_forward_grads
unsigned int size() const
SymmetricTensor< 2, dim, Number > b(const Tensor< 2, dim, Number > &F)
Tensor< 1, dim, Number > cross_product_3d(const Tensor< 1, dim, Number > &src1, const Tensor< 1, dim, Number > &src2)
Definition: tensor.h:1971
Point< dim > transform_real_to_unit_cell_internal(const typename Triangulation< dim, spacedim >::cell_iterator &cell, const Point< spacedim > &p, const Point< dim > &initial_p_unit) const
std::vector< DerivativeForm< 3, dim, spacedim > > jacobian_2nd_derivatives
std::vector< Point< spacedim > > quadrature_points
static Point< dim > project_to_unit_cell(const Point< dim > &p)
unsigned int get_degree() const
double norm(const FEValuesBase< dim > &fe, const VectorSlice< const std::vector< std::vector< Tensor< 1, dim > > > > &Du)
Definition: divergence.h:534
virtual void get_new_points(const ArrayView< const Point< spacedim >> &surrounding_points, const Table< 2, double > &weights, ArrayView< Point< spacedim >> new_points) const
Definition: manifold.cc:114
const double & shape(const unsigned int qpoint, const unsigned int shape_nr) const
Number determinant(const SymmetricTensor< 2, dim, Number > &t)
std::vector< DerivativeForm< 1, spacedim, dim > > inverse_jacobians
VectorizedArray< Number > sqrt(const ::VectorizedArray< Number > &x)
Definition: cuda.h:31
const types::manifold_id invalid_manifold_id
Definition: types.h:229
virtual std::unique_ptr< typename Mapping< dim, spacedim >::InternalDataBase > get_face_data(const UpdateFlags flags, const Quadrature< dim-1 > &quadrature) const override
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)
unsigned int n_dofs_per_cell() const
Definition: mpi.h:53
Normal vectors.
virtual std::size_t memory_consumption() const override
virtual std::vector< Point< spacedim > > compute_mapping_support_points(const typename Triangulation< dim, spacedim >::cell_iterator &cell) const
virtual void add_line_support_points(const typename Triangulation< dim, spacedim >::cell_iterator &cell, std::vector< Point< spacedim > > &a) const
static ::ExceptionBase & ExcNotImplemented()
std::vector< Tensor< 3, dim > > shape_third_derivatives
const Tensor< 2, dim > & second_derivative(const unsigned int qpoint, const unsigned int shape_nr) const
const Tensor< 1, dim > & derivative(const unsigned int qpoint, const unsigned int shape_nr) const
void initialize_face(const UpdateFlags update_flags, const Quadrature< dim > &quadrature, const unsigned int n_original_q_points)
std::vector< Tensor< 1, spacedim > > boundary_forms
double compute_value(const unsigned int i, const Point< dim > &p) const
void clear()
Definition: tensor.h:1356
std::vector< double > shape_values
virtual Point< dim > transform_real_to_unit_cell(const typename Triangulation< dim, spacedim >::cell_iterator &cell, const Point< spacedim > &p) const override
static double subface_ratio(const internal::SubfaceCase< dim > &subface_case, const unsigned int subface_no)
bool is_tensor_product() const
const Manifold< dim, spacedim > & get_manifold(const types::manifold_id number) const
Definition: tria.cc:9083
Covariant transformation.
std::enable_if< std::is_fundamental< T >::value, std::size_t >::type memory_consumption(const T &t)
Tensor< 2, dim, Number > l(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
UpdateFlags update_each
Definition: mapping.h:562
static ::ExceptionBase & ExcInternalError()
virtual std::unique_ptr< typename Mapping< dim, spacedim >::InternalDataBase > get_subface_data(const UpdateFlags flags, const Quadrature< dim-1 > &quadrature) const override