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