Reference documentation for deal.II version 9.0.0
fe_evaluation.h
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2011 - 2018 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE at
12 // the top level of the deal.II distribution.
13 //
14 // ---------------------------------------------------------------------
15 
16 
17 #ifndef dealii_matrix_free_fe_evaluation_h
18 #define dealii_matrix_free_fe_evaluation_h
19 
20 
21 #include <deal.II/base/array_view.h>
22 #include <deal.II/base/config.h>
23 #include <deal.II/base/exceptions.h>
24 #include <deal.II/base/smartpointer.h>
26 #include <deal.II/base/template_constraints.h>
27 #include <deal.II/base/vectorization.h>
28 #include <deal.II/matrix_free/mapping_data_on_the_fly.h>
29 #include <deal.II/matrix_free/matrix_free.h>
30 #include <deal.II/matrix_free/shape_info.h>
31 #include <deal.II/matrix_free/evaluation_kernels.h>
32 #include <deal.II/matrix_free/tensor_product_kernels.h>
33 #include <deal.II/matrix_free/evaluation_selector.h>
34 
35 #include <deal.II/lac/vector_operation.h>
36 
37 DEAL_II_NAMESPACE_OPEN
38 
39 
40 
41 // forward declarations
42 namespace LinearAlgebra
43 {
44  namespace distributed
45  {
46  template <typename> class Vector;
47  }
48 }
49 namespace internal
50 {
52 }
53 
54 template <int dim, int fe_degree, int n_q_points_1d = fe_degree+1,
55  int n_components_ = 1, typename Number = double > class FEEvaluation;
56 
57 
83 template <int dim, int n_components_, typename Number, bool is_face=false>
85 {
86 public:
87  typedef Number number_type;
90  static constexpr unsigned int dimension = dim;
91  static constexpr unsigned int n_components = n_components_;
92 
101 
105  DEAL_II_DEPRECATED
106  unsigned int get_cell_data_number() const;
107 
116  unsigned int get_mapping_data_index_offset() const;
117 
125 
130  get_shape_info() const;
131 
133 
170  template <typename VectorType>
171  void read_dof_values (const VectorType &src,
172  const unsigned int first_index = 0);
173 
202  template <typename VectorType>
203  void read_dof_values_plain (const VectorType &src,
204  const unsigned int first_index = 0);
205 
229  template <typename VectorType>
230  void distribute_local_to_global (VectorType &dst,
231  const unsigned int first_index = 0) const;
232 
259  template <typename VectorType>
260  void set_dof_values (VectorType &dst,
261  const unsigned int first_index = 0) const;
262 
264 
285  value_type get_dof_value (const unsigned int dof) const;
286 
297  void submit_dof_value (const value_type val_in,
298  const unsigned int dof);
299 
311  value_type get_value (const unsigned int q_point) const;
312 
324  void submit_value (const value_type val_in,
325  const unsigned int q_point);
326 
336  gradient_type get_gradient (const unsigned int q_point) const;
337 
351  value_type get_normal_derivative (const unsigned int q_point) const;
352 
365  void submit_gradient(const gradient_type grad_in,
366  const unsigned int q_point);
367 
385  void submit_normal_derivative(const value_type grad_in,
386  const unsigned int q_point);
387 
399  get_hessian (const unsigned int q_point) const;
400 
409  gradient_type get_hessian_diagonal (const unsigned int q_point) const;
410 
421  value_type get_laplacian (const unsigned int q_point) const;
422 
423 #ifdef DOXYGEN
424  // doxygen does not anyhow mention functions coming from partial template
425  // specialization of the base class, in this case FEEvaluationAccess<dim,dim>.
426  // For now, hack-in those functions manually only to fix documentation:
427 
431  VectorizedArray<Number> get_divergence (const unsigned int q_point) const;
432 
436  SymmetricTensor<2, dim, VectorizedArray<Number> > get_symmetric_gradient (const unsigned int q_point) const;
437 
441  Tensor<1,(dim==2?1:dim), VectorizedArray<Number> > get_curl (const unsigned int q_point) const;
442 
451  void submit_divergence (const VectorizedArray<Number> div_in, const unsigned int q_point);
452 
462  void submit_symmetric_gradient (const SymmetricTensor<2, dim, VectorizedArray<Number> > grad_in, const unsigned int q_point);
463 
473  void submit_curl (const Tensor<1, dim==2?1:dim, VectorizedArray<Number> > curl_in, const unsigned int q_point);
474 
475 #endif
476 
493  value_type integrate_value () const;
494 
499  VectorizedArray<Number> JxW(const unsigned int q_index) const;
500 
504  void
506 
514  inverse_jacobian(const unsigned int q_index) const;
515 
529  get_normal_vector(const unsigned int q_point) const;
530 
539 
541 
555 
565 
576  const VectorizedArray<Number> *begin_values () const;
577 
589 
602 
615 
628  const VectorizedArray<Number> *begin_hessians () const;
629 
643 
649  const std::vector<unsigned int> &
651 
659  get_scratch_data() const;
660 
662 
663 protected:
664 
673  FEEvaluationBase (const MatrixFree<dim,Number> &matrix_free,
674  const unsigned int dof_no,
675  const unsigned int first_selected_component,
676  const unsigned int quad_no,
677  const unsigned int fe_degree,
678  const unsigned int n_q_points,
679  const bool is_interior_face);
680 
715  template <int n_components_other>
716  FEEvaluationBase (const Mapping<dim> &mapping,
717  const FiniteElement<dim> &fe,
718  const Quadrature<1> &quadrature,
719  const UpdateFlags update_flags,
720  const unsigned int first_selected_component,
722 
729  FEEvaluationBase (const FEEvaluationBase &other);
730 
738 
745  template <typename VectorType, typename VectorOperation>
746  void
747  read_write_operation (const VectorOperation &operation,
748  VectorType *vectors[],
749  const bool apply_constraints = true) const;
750 
758  template <typename VectorType, typename VectorOperation>
759  void
761  VectorType *vectors[]) const;
762 
770  template <typename VectorType, typename VectorOperation>
771  void
773  VectorType *vectors[]) const;
774 
779 
786 
800 
813 
828 
840  VectorizedArray<Number> *hessians_quad[n_components][(dim*(dim+1))/2];
841 
845  const unsigned int quad_no;
846 
851  const unsigned int n_fe_components;
852 
857  const unsigned int active_fe_index;
858 
863  const unsigned int active_quad_index;
864 
868  const unsigned int n_quadrature_points;
869 
874 
881 
888  const internal::MatrixFreeFunctions::MappingInfoStorage<(is_face?dim-1:dim),dim,Number> *mapping_data;
889 
897 
903 
911 
916 
921 
925  const Number *quadrature_weights;
926 
931  unsigned int cell;
932 
938 
944 
949  unsigned int face_no;
950 
955  unsigned int face_orientation;
956 
964  unsigned int subface_index;
965 
973 
980 
987 
994 
1001 
1008 
1015 
1020  std::shared_ptr<internal::MatrixFreeFunctions::MappingDataOnTheFly<dim,Number> > mapped_geometry;
1021 
1026  const unsigned int first_selected_component;
1027 
1032  mutable std::vector<types::global_dof_index> local_dof_indices;
1033 
1034 private:
1039  void set_data_pointers();
1040 
1044  template <int, int, typename, bool> friend class FEEvaluationBase;
1045  template <int, int, int, int, typename> friend class FEEvaluation;
1046 };
1047 
1048 
1049 
1059 template <int dim, int n_components_, typename Number, bool is_face>
1060 class FEEvaluationAccess : public FEEvaluationBase<dim,n_components_,Number, is_face>
1061 {
1062 public:
1063  typedef Number number_type;
1066  static constexpr unsigned int dimension = dim;
1067  static constexpr unsigned int n_components = n_components_;
1069 
1070 protected:
1078  FEEvaluationAccess (const MatrixFree<dim,Number> &matrix_free,
1079  const unsigned int dof_no,
1080  const unsigned int first_selected_component,
1081  const unsigned int quad_no,
1082  const unsigned int fe_degree,
1083  const unsigned int n_q_points,
1084  const bool is_interior_face = true);
1085 
1090  template <int n_components_other>
1091  FEEvaluationAccess (const Mapping<dim> &mapping,
1092  const FiniteElement<dim> &fe,
1093  const Quadrature<1> &quadrature,
1094  const UpdateFlags update_flags,
1095  const unsigned int first_selected_component,
1097 
1101  FEEvaluationAccess (const FEEvaluationAccess &other);
1102 
1107 };
1108 
1109 
1110 
1111 
1122 template <int dim, typename Number, bool is_face>
1123 class FEEvaluationAccess<dim,1,Number,is_face> : public FEEvaluationBase<dim,1,Number,is_face>
1124 {
1125 public:
1126  typedef Number number_type;
1129  static constexpr unsigned int dimension = dim;
1131 
1134  value_type get_dof_value (const unsigned int dof) const;
1135 
1138  void submit_dof_value (const value_type val_in,
1139  const unsigned int dof);
1140 
1143  value_type get_value (const unsigned int q_point) const;
1144 
1147  void submit_value (const value_type val_in,
1148  const unsigned int q_point);
1149 
1152  void submit_value (const Tensor<1,1,VectorizedArray<Number> > val_in,
1153  const unsigned int q_point);
1154 
1157  gradient_type get_gradient (const unsigned int q_point) const;
1158 
1161  value_type get_normal_derivative (const unsigned int q_point) const;
1162 
1165  void submit_gradient(const gradient_type grad_in,
1166  const unsigned int q_point);
1167 
1170  void submit_normal_derivative(const value_type grad_in,
1171  const unsigned int q_point);
1172 
1176  get_hessian (unsigned int q_point) const;
1177 
1180  gradient_type get_hessian_diagonal (const unsigned int q_point) const;
1181 
1184  value_type get_laplacian (const unsigned int q_point) const;
1185 
1188  value_type integrate_value () const;
1189 
1190 protected:
1198  FEEvaluationAccess (const MatrixFree<dim,Number> &matrix_free,
1199  const unsigned int dof_no,
1200  const unsigned int first_selected_component,
1201  const unsigned int quad_no,
1202  const unsigned int fe_degree,
1203  const unsigned int n_q_points,
1204  const bool is_interior_face = true);
1205 
1210  template <int n_components_other>
1211  FEEvaluationAccess (const Mapping<dim> &mapping,
1212  const FiniteElement<dim> &fe,
1213  const Quadrature<1> &quadrature,
1214  const UpdateFlags update_flags,
1215  const unsigned int first_selected_component,
1217 
1221  FEEvaluationAccess (const FEEvaluationAccess &other);
1222 
1227 };
1228 
1229 
1230 
1242 template <int dim, typename Number, bool is_face>
1243 class FEEvaluationAccess<dim,dim,Number,is_face> : public FEEvaluationBase<dim,dim,Number,is_face>
1244 {
1245 public:
1246  typedef Number number_type;
1249  static constexpr unsigned int dimension = dim;
1250  static constexpr unsigned int n_components = dim;
1252 
1255  gradient_type get_gradient (const unsigned int q_point) const;
1256 
1261  VectorizedArray<Number> get_divergence (const unsigned int q_point) const;
1262 
1270  get_symmetric_gradient (const unsigned int q_point) const;
1271 
1277  get_curl (const unsigned int q_point) const;
1278 
1282  get_hessian (const unsigned int q_point) const;
1283 
1286  gradient_type get_hessian_diagonal (const unsigned int q_point) const;
1287 
1290  void submit_gradient(const gradient_type grad_in,
1291  const unsigned int q_point);
1292 
1301  void submit_gradient(const Tensor<1,dim,Tensor<1,dim,VectorizedArray<Number> > > grad_in,
1302  const unsigned int q_point);
1303 
1312  void submit_divergence (const VectorizedArray<Number> div_in,
1313  const unsigned int q_point);
1314 
1324  const unsigned int q_point);
1325 
1330  void submit_curl (const Tensor<1,dim==2?1:dim,VectorizedArray<Number> > curl_in,
1331  const unsigned int q_point);
1332 
1333 protected:
1341  FEEvaluationAccess (const MatrixFree<dim,Number> &matrix_free,
1342  const unsigned int dof_no,
1343  const unsigned int first_selected_component,
1344  const unsigned int quad_no,
1345  const unsigned int dofs_per_cell,
1346  const unsigned int n_q_points,
1347  const bool is_interior_face = true);
1348 
1353  template <int n_components_other>
1354  FEEvaluationAccess (const Mapping<dim> &mapping,
1355  const FiniteElement<dim> &fe,
1356  const Quadrature<1> &quadrature,
1357  const UpdateFlags update_flags,
1358  const unsigned int first_selected_component,
1360 
1364  FEEvaluationAccess (const FEEvaluationAccess &other);
1365 
1370 };
1371 
1372 
1384 template <typename Number, bool is_face>
1385 class FEEvaluationAccess<1,1,Number,is_face> : public FEEvaluationBase<1,1,Number,is_face>
1386 {
1387 public:
1388  typedef Number number_type;
1391  static constexpr unsigned int dimension = 1;
1393 
1396  value_type get_dof_value (const unsigned int dof) const;
1397 
1400  void submit_dof_value (const value_type val_in,
1401  const unsigned int dof);
1402 
1405  value_type get_value (const unsigned int q_point) const;
1406 
1409  void submit_value (const value_type val_in,
1410  const unsigned int q_point);
1411 
1414  void submit_value (const gradient_type val_in,
1415  const unsigned int q_point);
1416 
1419  gradient_type get_gradient (const unsigned int q_point) const;
1420 
1423  value_type get_normal_derivative (const unsigned int q_point) const;
1424 
1427  void submit_gradient(const gradient_type grad_in,
1428  const unsigned int q_point);
1429 
1432  void submit_gradient(const value_type grad_in,
1433  const unsigned int q_point);
1434 
1437  void submit_normal_derivative(const value_type grad_in,
1438  const unsigned int q_point);
1439 
1442  void submit_normal_derivative(const gradient_type grad_in,
1443  const unsigned int q_point);
1444 
1448  get_hessian (unsigned int q_point) const;
1449 
1452  gradient_type get_hessian_diagonal (const unsigned int q_point) const;
1453 
1456  value_type get_laplacian (const unsigned int q_point) const;
1457 
1460  value_type integrate_value () const;
1461 
1462 protected:
1470  FEEvaluationAccess (const MatrixFree<1,Number> &matrix_free,
1471  const unsigned int dof_no,
1472  const unsigned int first_selected_component,
1473  const unsigned int quad_no,
1474  const unsigned int fe_degree,
1475  const unsigned int n_q_points,
1476  const bool is_interior_face = true);
1477 
1482  template <int n_components_other>
1483  FEEvaluationAccess (const Mapping<1> &mapping,
1484  const FiniteElement<1> &fe,
1485  const Quadrature<1> &quadrature,
1486  const UpdateFlags update_flags,
1487  const unsigned int first_selected_component,
1489 
1493  FEEvaluationAccess (const FEEvaluationAccess &other);
1494 
1499 };
1500 
1501 
1502 
2048 template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
2049  typename Number >
2050 class FEEvaluation : public FEEvaluationAccess<dim,n_components_,Number,false>
2051 {
2052 public:
2057 
2061  typedef Number number_type;
2062 
2069 
2076 
2080  static constexpr unsigned int dimension = dim;
2081 
2086  static constexpr unsigned int n_components = n_components_;
2087 
2094  static constexpr unsigned int static_n_q_points = Utilities::pow(n_q_points_1d, dim);
2095 
2103  static constexpr unsigned int static_dofs_per_component = Utilities::pow(fe_degree + 1, dim);
2104 
2113 
2122 
2148  FEEvaluation (const MatrixFree<dim,Number> &matrix_free,
2149  const unsigned int dof_no = 0,
2150  const unsigned int quad_no = 0,
2151  const unsigned int first_selected_component = 0);
2152 
2179  FEEvaluation (const Mapping<dim> &mapping,
2180  const FiniteElement<dim> &fe,
2181  const Quadrature<1> &quadrature,
2182  const UpdateFlags update_flags,
2183  const unsigned int first_selected_component = 0);
2184 
2190  FEEvaluation (const FiniteElement<dim> &fe,
2191  const Quadrature<1> &quadrature,
2192  const UpdateFlags update_flags,
2193  const unsigned int first_selected_component = 0);
2194 
2205  template <int n_components_other>
2206  FEEvaluation (const FiniteElement<dim> &fe,
2208  const unsigned int first_selected_component = 0);
2209 
2216  FEEvaluation (const FEEvaluation &other);
2217 
2224  FEEvaluation &operator= (const FEEvaluation &other);
2225 
2234  void reinit (const unsigned int cell_batch_index);
2235 
2248  template <typename DoFHandlerType, bool level_dof_access>
2250 
2261  void reinit (const typename Triangulation<dim>::cell_iterator &cell);
2262 
2272  void evaluate (const bool evaluate_values,
2273  const bool evaluate_gradients,
2274  const bool evaluate_hessians = false);
2275 
2288  void evaluate (const VectorizedArray<Number> *values_array,
2289  const bool evaluate_values,
2290  const bool evaluate_gradients,
2291  const bool evaluate_hessians = false);
2292 
2306  template <typename VectorType>
2307  void gather_evaluate (const VectorType &input_vector,
2308  const bool evaluate_values,
2309  const bool evaluate_gradients,
2310  const bool evaluate_hessians = false);
2311 
2322  void integrate (const bool integrate_values,
2323  const bool integrate_gradients);
2324 
2336  void integrate (const bool integrate_values,
2337  const bool integrate_gradients,
2338  VectorizedArray<Number> *values_array);
2339 
2353  template <typename VectorType>
2354  void integrate_scatter (const bool integrate_values,
2355  const bool integrate_gradients,
2356  VectorType &output_vector);
2357 
2363  quadrature_point (const unsigned int q_point) const;
2364 
2371  const unsigned int dofs_per_component;
2372 
2379  const unsigned int dofs_per_cell;
2380 
2388  const unsigned int n_q_points;
2389 
2390 private:
2395  void check_template_arguments(const unsigned int fe_no,
2396  const unsigned int first_selected_component);
2397 };
2398 
2399 
2400 
2432 template <int dim, int fe_degree, int n_q_points_1d = fe_degree+1,
2433  int n_components_ = 1, typename Number = double >
2434 class FEFaceEvaluation : public FEEvaluationAccess<dim,n_components_,Number,true>
2435 {
2436 public:
2441 
2445  typedef Number number_type;
2446 
2453 
2460 
2464  static constexpr unsigned int dimension = dim;
2465 
2470  static constexpr unsigned int n_components = n_components_;
2471 
2478  static constexpr unsigned int static_n_q_points = Utilities::pow(n_q_points_1d, dim-1);
2479 
2486  static constexpr unsigned int static_n_q_points_cell = Utilities::pow(n_q_points_1d, dim);
2487 
2494  static constexpr unsigned int static_dofs_per_component = Utilities::pow(fe_degree + 1, dim);
2495 
2503 
2511 
2541  FEFaceEvaluation (const MatrixFree<dim,Number> &matrix_free,
2542  const bool is_interior_face = true,
2543  const unsigned int dof_no = 0,
2544  const unsigned int quad_no = 0,
2545  const unsigned int first_selected_component = 0);
2546 
2551 
2562  void reinit (const unsigned int face_batch_number);
2563 
2571  void reinit(const unsigned int cell_batch_number,
2572  const unsigned int face_number);
2573 
2584  void evaluate (const bool evaluate_values,
2585  const bool evaluate_gradients);
2586 
2599  void evaluate (const VectorizedArray<Number> *values_array,
2600  const bool evaluate_values,
2601  const bool evaluate_gradients);
2602 
2614  template <typename VectorType>
2615  void gather_evaluate (const VectorType &input_vector,
2616  const bool evaluate_values,
2617  const bool evaluate_gradients);
2618 
2628  void integrate (const bool integrate_values,
2629  const bool integrate_gradients);
2630 
2639  void integrate (const bool integrate_values,
2640  const bool integrate_gradients,
2641  VectorizedArray<Number> *values_array);
2642 
2654  template <typename VectorType>
2655  void integrate_scatter (const bool integrate_values,
2656  const bool integrate_gradients,
2657  VectorType &output_vector);
2658 
2664  quadrature_point (const unsigned int q_point) const;
2665 
2672  const unsigned int dofs_per_component;
2673 
2680  const unsigned int dofs_per_cell;
2681 
2689  const unsigned int n_q_points;
2690 
2691 protected:
2692 
2698  void adjust_for_face_orientation(const bool integrate,
2699  const bool values,
2700  const bool gradients);
2701 };
2702 
2703 
2704 
2705 namespace internal
2706 {
2707  namespace MatrixFreeFunctions
2708  {
2709  // a helper function to compute the number of DoFs of a DGP element at compile
2710  // time, depending on the degree
2711  template <int dim, int degree>
2712  struct DGP_dofs_per_component
2713  {
2714  // this division is always without remainder
2715  static constexpr unsigned int value =
2716  (DGP_dofs_per_component<dim-1,degree>::value * (degree+dim)) / dim;
2717  };
2718 
2719  // base specialization: 1d elements have 'degree+1' degrees of freedom
2720  template <int degree>
2721  struct DGP_dofs_per_component<1,degree>
2722  {
2723  static constexpr unsigned int value = degree+1;
2724  };
2725  }
2726 }
2727 
2728 
2729 /*----------------------- Inline functions ----------------------------------*/
2730 
2731 #ifndef DOXYGEN
2732 
2733 
2734 
2735 /*----------------------- FEEvaluationBase ----------------------------------*/
2736 
2737 template <int dim, int n_components_, typename Number, bool is_face>
2738 inline
2741  const unsigned int dof_no,
2742  const unsigned int first_selected_component,
2743  const unsigned int quad_no_in,
2744  const unsigned int fe_degree,
2745  const unsigned int n_q_points,
2746  const bool is_interior_face)
2747  :
2748  scratch_data_array (data_in.acquire_scratch_data()),
2749  quad_no (quad_no_in),
2750  n_fe_components (data_in.get_dof_info(dof_no).start_components.back()),
2751  active_fe_index (fe_degree != numbers::invalid_unsigned_int ?
2752  data_in.get_dof_info(dof_no).fe_index_from_degree
2753  (first_selected_component, fe_degree)
2754  :
2755  0),
2756  active_quad_index (fe_degree != numbers::invalid_unsigned_int ?
2757  (is_face ?
2758  data_in.get_mapping_info().face_data[quad_no_in].
2759  quad_index_from_n_q_points(n_q_points)
2760  :
2761  data_in.get_mapping_info().cell_data[quad_no_in].
2762  quad_index_from_n_q_points(n_q_points))
2763  :
2764  0),
2765  n_quadrature_points(fe_degree != numbers::invalid_unsigned_int ? n_q_points :
2766  (is_face ?
2767  data_in.get_shape_info
2768  (dof_no, quad_no_in, active_fe_index, active_quad_index).n_q_points_face
2769  :
2770  data_in.get_shape_info
2771  (dof_no, quad_no_in, active_fe_index, active_quad_index).n_q_points)),
2772  matrix_info (&data_in),
2773  dof_info (&data_in.get_dof_info(dof_no)),
2774  mapping_data (internal::MatrixFreeFunctions::MappingInfoCellsOrFaces<dim,Number,is_face>::get(data_in.get_mapping_info(), quad_no)),
2775  data (&data_in.get_shape_info
2776  (dof_no, quad_no_in,
2777  dof_info->component_to_base_index[first_selected_component],
2778  active_fe_index, active_quad_index)),
2779  jacobian (nullptr),
2780  J_value (nullptr),
2781  normal_vectors (nullptr),
2782  normal_x_jacobian (nullptr),
2783  quadrature_weights (mapping_data->descriptor[active_quad_index].quadrature_weights.begin()),
2784  cell (numbers::invalid_unsigned_int),
2785  is_interior_face (is_interior_face),
2786  dof_access_index (is_face ?
2787  (is_interior_face ?
2788  internal::MatrixFreeFunctions::DoFInfo::dof_access_face_interior
2789  :
2790  internal::MatrixFreeFunctions::DoFInfo::dof_access_face_exterior)
2791  :
2792  internal::MatrixFreeFunctions::DoFInfo::dof_access_cell),
2793  cell_type (internal::MatrixFreeFunctions::general),
2794  dof_values_initialized (false),
2795  values_quad_initialized (false),
2796  gradients_quad_initialized(false),
2797  hessians_quad_initialized (false),
2798  values_quad_submitted (false),
2799  gradients_quad_submitted (false),
2800  first_selected_component (first_selected_component)
2801 {
2802  set_data_pointers();
2803  Assert (matrix_info->mapping_initialized() == true,
2804  ExcNotInitialized());
2807  AssertDimension ((is_face ? data->n_q_points_face : data->n_q_points),
2808  n_quadrature_points);
2809  AssertDimension (n_quadrature_points,
2810  mapping_data->descriptor[active_quad_index].n_q_points);
2811  Assert(dof_info->start_components.back() == 1 ||
2812  (int)n_components_ <=
2813  (int)dof_info->start_components[dof_info->component_to_base_index[first_selected_component]+1] - first_selected_component,
2814  ExcMessage("You tried to construct a vector-valued evaluator with " +
2815  Utilities::to_string(n_components) + " components. However, "
2816  "the current base element has only " +
2817  Utilities::to_string(dof_info->start_components[dof_info->component_to_base_index[first_selected_component]+1] - first_selected_component)
2818  + " components left when starting from local element index " +
2819  Utilities::to_string(first_selected_component-dof_info->start_components[dof_info->component_to_base_index[first_selected_component]])
2820  + " (global index " + Utilities::to_string(first_selected_component)
2821  + ")"));
2822 
2823  // do not check for correct dimensions of data fields here, should be done
2824  // in derived classes
2825 }
2826 
2827 
2828 
2829 template <int dim, int n_components_, typename Number, bool is_face>
2830 template <int n_components_other>
2831 inline
2833 ::FEEvaluationBase (const Mapping<dim> &mapping,
2834  const FiniteElement<dim> &fe,
2835  const Quadrature<1> &quadrature,
2836  const UpdateFlags update_flags,
2837  const unsigned int first_selected_component,
2839  :
2840  scratch_data_array (new AlignedVector<VectorizedArray<Number> >()),
2841  quad_no (numbers::invalid_unsigned_int),
2842  n_fe_components (n_components_),
2843  active_fe_index (numbers::invalid_unsigned_int),
2844  active_quad_index (numbers::invalid_unsigned_int),
2845  n_quadrature_points(Utilities::fixed_power<is_face?dim-1:dim>(quadrature.size())),
2846  matrix_info (nullptr),
2847  dof_info (nullptr),
2848  mapping_data (nullptr),
2849  // select the correct base element from the given FE component
2850  data (new internal::MatrixFreeFunctions::ShapeInfo<VectorizedArray<Number>> (quadrature, fe, fe.component_to_base_index(first_selected_component).first)),
2851  jacobian (nullptr),
2852  J_value (nullptr),
2853  normal_vectors (nullptr),
2854  normal_x_jacobian (nullptr),
2855  quadrature_weights (nullptr),
2856  cell (0),
2857  cell_type (internal::MatrixFreeFunctions::general),
2858  is_interior_face (true),
2859  dof_access_index (internal::MatrixFreeFunctions::DoFInfo::dof_access_cell),
2860  dof_values_initialized (false),
2861  values_quad_initialized (false),
2862  gradients_quad_initialized(false),
2863  hessians_quad_initialized (false),
2864  values_quad_submitted (false),
2865  gradients_quad_submitted (false),
2866  // keep the number of the selected component within the current base element
2867  // for reading dof values
2868  first_selected_component (first_selected_component)
2869 {
2870  set_data_pointers();
2871 
2872  Assert(other == nullptr || other->mapped_geometry.get() != nullptr, ExcInternalError());
2873  if (other != nullptr &&
2874  other->mapped_geometry->get_quadrature() == quadrature)
2875  mapped_geometry = other->mapped_geometry;
2876  else
2877  mapped_geometry
2879  (mapping, quadrature, update_flags);
2880  cell = 0;
2881 
2882  mapping_data = &mapped_geometry->get_data_storage();
2883  jacobian = mapped_geometry->get_data_storage().jacobians[0].begin();
2884  J_value = mapped_geometry->get_data_storage().JxW_values.begin();
2885 
2886  const unsigned int base_element_number =
2887  fe.component_to_base_index(first_selected_component).first;
2888  Assert(fe.element_multiplicity(base_element_number) == 1 ||
2889  fe.element_multiplicity(base_element_number)-first_selected_component >= n_components_,
2890  ExcMessage("The underlying element must at least contain as many "
2891  "components as requested by this class"));
2892  (void) base_element_number;
2893 }
2894 
2895 
2896 
2897 template <int dim, int n_components_, typename Number, bool is_face>
2898 inline
2901  :
2902  scratch_data_array (other.matrix_info == nullptr ?
2903  new AlignedVector<VectorizedArray<Number> >() :
2904  other.matrix_info->acquire_scratch_data()),
2905  quad_no (other.quad_no),
2906  n_fe_components (other.n_fe_components),
2907  active_fe_index (other.active_fe_index),
2908  active_quad_index (other.active_quad_index),
2909  n_quadrature_points(other.n_quadrature_points),
2910  matrix_info (other.matrix_info),
2911  dof_info (other.dof_info),
2912  mapping_data (other.mapping_data),
2913  data (other.matrix_info == nullptr ?
2914  new internal::MatrixFreeFunctions::ShapeInfo<VectorizedArray<Number>>(*other.data) :
2915  other.data),
2916  jacobian (nullptr),
2917  J_value (nullptr),
2918  normal_vectors (nullptr),
2919  normal_x_jacobian (nullptr),
2920  quadrature_weights (other.matrix_info == nullptr ? nullptr :
2921  mapping_data->descriptor[active_quad_index].quadrature_weights.begin()),
2922  cell (numbers::invalid_unsigned_int),
2923  cell_type (internal::MatrixFreeFunctions::general),
2924  is_interior_face (other.is_interior_face),
2925  dof_access_index (other.dof_access_index),
2926  dof_values_initialized (false),
2927  values_quad_initialized (false),
2928  gradients_quad_initialized(false),
2929  hessians_quad_initialized (false),
2930  values_quad_submitted (false),
2931  gradients_quad_submitted (false),
2932  first_selected_component (other.first_selected_component)
2933 {
2934  set_data_pointers();
2935 
2936  // Create deep copy of mapped geometry for use in parallel...
2937  if (other.mapped_geometry.get() != nullptr)
2938  {
2939  mapped_geometry.reset
2941  MappingDataOnTheFly<dim,Number>(other.mapped_geometry->get_fe_values().get_mapping(),
2942  other.mapped_geometry->get_quadrature(),
2943  other.mapped_geometry->get_fe_values().get_update_flags()));
2944  mapping_data = &mapped_geometry->get_data_storage();
2945  cell = 0;
2946 
2947  jacobian = mapped_geometry->get_data_storage().jacobians[0].begin();
2948  J_value = mapped_geometry->get_data_storage().JxW_values.begin();
2949  }
2950 }
2951 
2952 
2953 
2954 template <int dim, int n_components_, typename Number, bool is_face>
2955 inline
2959 {
2960  AssertDimension(quad_no, other.quad_no);
2961  AssertDimension(n_fe_components, other.n_fe_components);
2962  AssertDimension(active_fe_index, other.active_fe_index);
2963  AssertDimension(active_quad_index, other.active_quad_index);
2964  AssertDimension(first_selected_component, other.first_selected_component);
2965 
2966  // release old memory
2967  if (matrix_info == nullptr)
2968  {
2969  delete data;
2970  delete scratch_data_array;
2971  }
2972  else
2973  {
2974  matrix_info->release_scratch_data(scratch_data_array);
2975  }
2976 
2977  matrix_info = other.matrix_info;
2978  dof_info = other.dof_info;
2979  mapping_data = other.mapping_data;
2980  if (other.matrix_info == nullptr)
2981  {
2983  scratch_data_array = new AlignedVector<VectorizedArray<Number> >();
2984  }
2985  else
2986  {
2987  data = other.data;
2988  scratch_data_array = matrix_info->acquire_scratch_data();
2989  }
2990  set_data_pointers();
2991 
2992  quadrature_weights = (mapping_data != nullptr ?
2993  mapping_data->descriptor[active_quad_index].quadrature_weights.begin()
2994  :
2995  nullptr);
2998  is_interior_face = other.is_interior_face;
2999  dof_access_index = other.dof_access_index;
3000 
3001  // Create deep copy of mapped geometry for use in parallel...
3002  if (other.mapped_geometry.get() != nullptr)
3003  {
3004  mapped_geometry.reset
3006  MappingDataOnTheFly<dim,Number>(other.mapped_geometry->get_fe_values().get_mapping(),
3007  other.mapped_geometry->get_quadrature(),
3008  other.mapped_geometry->get_fe_values().get_update_flags()));
3009  cell = 0;
3010  mapping_data = &mapped_geometry->get_data_storage();
3011  jacobian = mapped_geometry->get_data_storage().jacobians[0].begin();
3012  J_value = mapped_geometry->get_data_storage().JxW_values.begin();
3013  }
3014 
3015  return *this;
3016 }
3017 
3018 
3019 
3020 template <int dim, int n_components_, typename Number, bool is_face>
3021 inline
3023 {
3024  if (matrix_info != nullptr)
3025  {
3026  try
3027  {
3028  matrix_info->release_scratch_data(scratch_data_array);
3029  }
3030  catch (...)
3031  {}
3032  }
3033  else
3034  {
3035  delete scratch_data_array;
3036  delete data;
3037  data = nullptr;
3038  }
3039  scratch_data_array = nullptr;
3040 }
3041 
3042 
3043 
3044 template <int dim, int n_components_, typename Number, bool is_face>
3045 inline
3046 void
3049 {
3050  Assert(scratch_data_array != nullptr, ExcInternalError());
3051 
3052  const unsigned int tensor_dofs_per_component =
3053  Utilities::fixed_power<dim>(this->data->fe_degree+1);
3054  const unsigned int dofs_per_component = this->data->dofs_per_component_on_cell;
3055  const unsigned int n_quadrature_points = is_face ? this->data->n_q_points_face : this->data->n_q_points;
3056 
3057  const unsigned int shift = std::max(tensor_dofs_per_component+1, dofs_per_component)*
3058  n_components_*3 + 2 * n_quadrature_points;
3059  const unsigned int allocated_size = shift + n_components_ * dofs_per_component
3060  + (n_components_*(dim*dim+2*dim+1)*n_quadrature_points);
3061  scratch_data_array->resize_fast(allocated_size);
3062 
3063  // set the pointers to the correct position in the data array
3064  for (unsigned int c=0; c<n_components_; ++c)
3065  {
3066  this->values_dofs[c] = scratch_data_array->begin() + c*dofs_per_component;
3067  this->values_quad[c] = scratch_data_array->begin() +
3068  n_components*dofs_per_component+c*n_quadrature_points;
3069  for (unsigned int d=0; d<dim; ++d)
3070  this->gradients_quad[c][d] = scratch_data_array->begin() +
3071  n_components*(dofs_per_component+n_quadrature_points) +
3072  (c*dim+d)*n_quadrature_points;
3073  for (unsigned int d=0; d<(dim*dim+dim)/2; ++d)
3074  this->hessians_quad[c][d] = scratch_data_array->begin() +
3075  n_components*((dim+1)*n_quadrature_points + dofs_per_component) +
3076  (c*(dim*dim+dim)+d)*n_quadrature_points;
3077  }
3078  scratch_data = scratch_data_array->begin() + n_components_ * dofs_per_component
3079  + (n_components_*(dim*dim+2*dim+1)*n_quadrature_points);
3080 }
3081 
3082 
3083 
3084 template <int dim, int n_components_, typename Number, bool is_face>
3085 inline
3086 unsigned int
3088 ::get_cell_data_number () const
3089 {
3090  return get_mapping_data_index_offset();
3091 }
3092 
3093 
3094 
3095 template <int dim, int n_components_, typename Number, bool is_face>
3096 inline
3097 unsigned int
3100 {
3101  if (matrix_info == 0)
3102  return 0;
3103  else
3104  {
3105  AssertIndexRange(cell, this->mapping_data->data_index_offsets.size());
3106  return this->mapping_data->data_index_offsets[cell];
3107  }
3108 }
3109 
3110 
3111 
3112 template <int dim, int n_components_, typename Number, bool is_face>
3113 inline
3116 {
3118  return cell_type;
3119 }
3120 
3121 
3122 
3123 template <int dim, int n_components_, typename Number, bool is_face>
3124 inline
3127 {
3128  Assert(data != nullptr, ExcInternalError());
3129  return *data;
3130 }
3131 
3132 
3133 
3134 template <int dim, int n_components_, typename Number, bool is_face>
3135 inline
3136 void
3139 {
3140  AssertDimension(JxW_values.size(), n_quadrature_points);
3141  Assert (J_value != nullptr, ExcNotInitialized());
3142  if (this->cell_type <= internal::MatrixFreeFunctions::affine)
3143  {
3144  VectorizedArray<Number> J = J_value[0];
3145  for (unsigned int q=0; q<this->n_quadrature_points; ++q)
3146  JxW_values[q] = J * this->quadrature_weights[q];
3147  }
3148  else
3149  for (unsigned int q=0; q<n_quadrature_points; ++q)
3150  JxW_values[q] = J_value[q];
3151 }
3152 
3153 
3154 
3155 template <int dim, int n_components_, typename Number, bool is_face>
3156 inline DEAL_II_ALWAYS_INLINE
3159 ::get_normal_vector(const unsigned int q_index) const
3160 {
3161  AssertIndexRange(q_index, n_quadrature_points);
3162  Assert(normal_vectors != nullptr, ExcMessage("Did not call reinit()!"));
3163  if (this->cell_type <= internal::MatrixFreeFunctions::flat_faces)
3164  return normal_vectors[0];
3165  else
3166  return normal_vectors[q_index];
3167 }
3168 
3169 
3170 
3171 template <int dim, int n_components_, typename Number, bool is_face>
3172 inline DEAL_II_ALWAYS_INLINE
3174 FEEvaluationBase<dim,n_components_,Number,is_face>::JxW(const unsigned int q_index) const
3175 {
3176  AssertIndexRange(q_index, n_quadrature_points);
3177  Assert (J_value != nullptr, ExcNotInitialized());
3178  if (this->cell_type <= internal::MatrixFreeFunctions::affine)
3179  {
3180  Assert (this->quadrature_weights != nullptr, ExcInternalError());
3181  return J_value[0] * this->quadrature_weights[q_index];
3182  }
3183  else
3184  return J_value[q_index];
3185 }
3186 
3187 
3188 
3189 template <int dim, int n_components_, typename Number, bool is_face>
3190 inline
3193 ::inverse_jacobian(const unsigned int q_index) const
3194 {
3195  AssertIndexRange(q_index, n_quadrature_points);
3196  Assert (this->jacobian != nullptr, ExcNotImplemented());
3197  if (this->cell_type <= internal::MatrixFreeFunctions::affine)
3198  return jacobian[0];
3199  else
3200  return jacobian[q_index];
3201 }
3202 
3203 
3204 
3205 template <int dim, int n_components_, typename Number, bool is_face>
3206 inline
3210 {
3211  Assert(matrix_info != nullptr, ExcNotImplemented());
3212  AssertDimension(array.size(), matrix_info->get_task_info().cell_partition_data.back());
3213  if (is_face)
3214  {
3215  VectorizedArray<Number> out = make_vectorized_array<Number>(Number(1.));
3216  const unsigned int *cells =
3217  is_interior_face ?
3218  &this->matrix_info->get_face_info(cell).cells_interior[0] :
3219  &this->matrix_info->get_face_info(cell).cells_exterior[0];
3220  for (unsigned int i=0; i<VectorizedArray<Number>::n_array_elements; ++i)
3221  if (cells[i] != numbers::invalid_unsigned_int)
3223  return out;
3224  }
3225  else
3226  return array[cell];
3227 }
3228 
3229 
3230 
3231 namespace internal
3232 {
3233  // access to generic vectors that have operator ().
3234  template <typename VectorType>
3235  inline
3236  typename VectorType::value_type &
3237  vector_access (VectorType &vec,
3238  const unsigned int entry)
3239  {
3240  return vec(entry);
3241  }
3242 
3243 
3244 
3245  // access to distributed MPI vectors that have a local_element(uint)
3246  // method to access data in local index space, which is what we use in
3247  // DoFInfo and hence in read_dof_values etc.
3248  template <typename Number>
3249  inline
3250  Number &
3251  vector_access (LinearAlgebra::distributed::Vector<Number> &vec,
3252  const unsigned int entry)
3253  {
3254  return vec.local_element(entry);
3255  }
3256 
3257 
3258 
3259  // this is to make sure that the parallel partitioning in the
3260  // LinearAlgebra::distributed::Vector is really the same as stored in
3261  // MatrixFree
3262  template <typename VectorType>
3263  inline
3264  void check_vector_compatibility (const VectorType &vec,
3266  {
3267  (void) vec;
3268  (void) dof_info;
3269 
3270  AssertDimension (vec.size(),
3271  dof_info.vector_partitioner->size());
3272  }
3273 
3274  template <typename Number>
3275  inline
3276  void check_vector_compatibility (const LinearAlgebra::distributed::Vector<Number> &vec,
3278  {
3279  (void) vec;
3280  (void) dof_info;
3282  ExcMessage("The parallel layout of the given vector is not "
3283  "compatible with the parallel partitioning in MatrixFree. "
3284  "Use MatrixFree::initialize_dof_vector to get a "
3285  "compatible vector."));
3286  }
3287 
3288  // A class to use the same code to read from and write to vector
3289  template <typename Number>
3290  struct VectorReader
3291  {
3292  template <typename VectorType>
3293  void process_dof (const unsigned int index,
3294  VectorType &vec,
3295  Number &res) const
3296  {
3297  res = vector_access (vec, index);
3298  }
3299 
3300  template <typename VectorType>
3301  void process_dofs_vectorized_transpose (const unsigned int dofs_per_cell,
3302  const unsigned int *dof_indices,
3303  VectorType &vec,
3304  VectorizedArray<Number> *dof_values,
3305  std::integral_constant<bool,true>) const
3306  {
3307  ::vectorized_load_and_transpose(dofs_per_cell, vec.begin(),
3308  dof_indices, dof_values);
3309  }
3310 
3311 
3312  template <typename VectorType>
3313  void process_dofs_vectorized_transpose (const unsigned int dofs_per_cell,
3314  const unsigned int *dof_indices,
3315  VectorType &vec,
3316  VectorizedArray<Number> *dof_values,
3317  std::integral_constant<bool,false>) const
3318  {
3319  for (unsigned int d=0; d<dofs_per_cell; ++d)
3320  for (unsigned int v=0; v<VectorizedArray<Number>::n_array_elements; ++v)
3321  dof_values[d][v] = vector_access(vec, dof_indices[v]+d);
3322  }
3323 
3324  // variant where VectorType::value_type is the same as Number -> can call
3325  // gather
3326  template <typename VectorType>
3327  void process_dof_gather (const unsigned int *indices,
3328  VectorType &vec,
3329  const unsigned int constant_offset,
3331  std::integral_constant<bool, true>) const
3332  {
3333  res.gather(vec.begin()+constant_offset, indices);
3334  }
3335 
3336  // variant where VectorType::value_type is not the same as Number -> must
3337  // manually load the data
3338  template <typename VectorType>
3339  void process_dof_gather (const unsigned int *indices,
3340  VectorType &vec,
3341  const unsigned int constant_offset,
3343  std::integral_constant<bool, false>) const
3344  {
3345  for (unsigned int v=0; v<VectorizedArray<Number>::n_array_elements; ++v)
3346  res[v] = vector_access(vec, indices[v]+constant_offset);
3347  }
3348 
3349  template <typename VectorType>
3350  void process_dof_global (const types::global_dof_index index,
3351  VectorType &vec,
3352  Number &res) const
3353  {
3354  res = const_cast<const VectorType &>(vec)(index);
3355  }
3356 
3357  void pre_constraints (const Number &,
3358  Number &res) const
3359  {
3360  res = Number();
3361  }
3362 
3363  template <typename VectorType>
3364  void process_constraint (const unsigned int index,
3365  const Number weight,
3366  VectorType &vec,
3367  Number &res) const
3368  {
3369  res += weight * vector_access (vec, index);
3370  }
3371 
3372  void post_constraints (const Number &sum,
3373  Number &write_pos) const
3374  {
3375  write_pos = sum;
3376  }
3377 
3378  void process_empty (VectorizedArray<Number> &res) const
3379  {
3380  res = VectorizedArray<Number>();
3381  }
3382  };
3383 
3384  // A class to use the same code to read from and write to vector
3385  template <typename Number>
3386  struct VectorDistributorLocalToGlobal
3387  {
3388  template <typename VectorType>
3389  void process_dof (const unsigned int index,
3390  VectorType &vec,
3391  Number &res) const
3392  {
3393  vector_access (vec, index) += res;
3394  }
3395 
3396  template <typename VectorType>
3397  void process_dofs_vectorized_transpose (const unsigned int dofs_per_cell,
3398  const unsigned int *dof_indices,
3399  VectorType &vec,
3400  VectorizedArray<Number> *dof_values,
3401  std::integral_constant<bool,true>) const
3402  {
3403  vectorized_transpose_and_store(true, dofs_per_cell, dof_values,
3404  dof_indices, vec.begin());
3405  }
3406 
3407  template <typename VectorType>
3408  void process_dofs_vectorized_transpose (const unsigned int dofs_per_cell,
3409  const unsigned int *dof_indices,
3410  VectorType &vec,
3411  VectorizedArray<Number> *dof_values,
3412  std::integral_constant<bool,false>) const
3413  {
3414  for (unsigned int d=0; d<dofs_per_cell; ++d)
3415  for (unsigned int v=0; v<VectorizedArray<Number>::n_array_elements; ++v)
3416  vector_access(vec, dof_indices[v]+d) += dof_values[d][v];
3417  }
3418 
3419  // variant where VectorType::value_type is the same as Number -> can call
3420  // scatter
3421  template <typename VectorType>
3422  void process_dof_gather (const unsigned int *indices,
3423  VectorType &vec,
3424  const unsigned int constant_offset,
3426  std::integral_constant<bool, true>) const
3427  {
3428 #if DEAL_II_COMPILER_VECTORIZATION_LEVEL < 3
3429  for (unsigned int v=0; v<VectorizedArray<Number>::n_array_elements; ++v)
3430  vector_access(vec, indices[v]+constant_offset) += res[v];
3431 #else
3432  // only use gather in case there is also scatter.
3434  tmp.gather(vec.begin()+constant_offset, indices);
3435  tmp += res;
3436  tmp.scatter(indices, vec.begin()+constant_offset);
3437 #endif
3438  }
3439 
3440  // variant where VectorType::value_type is not the same as Number -> must
3441  // manually append all data
3442  template <typename VectorType>
3443  void process_dof_gather (const unsigned int *indices,
3444  VectorType &vec,
3445  const unsigned int constant_offset,
3447  std::integral_constant<bool, false>) const
3448  {
3449  for (unsigned int v=0; v<VectorizedArray<Number>::n_array_elements; ++v)
3450  vector_access(vec, indices[v]+constant_offset) += res[v];
3451  }
3452 
3453  template <typename VectorType>
3454  void process_dof_global (const types::global_dof_index index,
3455  VectorType &vec,
3456  Number &res) const
3457  {
3458  vec(index) += res;
3459  }
3460 
3461  void pre_constraints (const Number &input,
3462  Number &res) const
3463  {
3464  res = input;
3465  }
3466 
3467  template <typename VectorType>
3468  void process_constraint (const unsigned int index,
3469  const Number weight,
3470  VectorType &vec,
3471  Number &res) const
3472  {
3473  vector_access (vec, index) += weight * res;
3474  }
3475 
3476  void post_constraints (const Number &,
3477  Number &) const
3478  {
3479  }
3480 
3481  void process_empty (VectorizedArray<Number> &) const
3482  {
3483  }
3484  };
3485 
3486 
3487  // A class to use the same code to read from and write to vector
3488  template <typename Number>
3489  struct VectorSetter
3490  {
3491  template <typename VectorType>
3492  void process_dof (const unsigned int index,
3493  VectorType &vec,
3494  Number &res) const
3495  {
3496  vector_access (vec, index) = res;
3497  }
3498 
3499  template <typename VectorType>
3500  void process_dofs_vectorized_transpose (const unsigned int dofs_per_cell,
3501  const unsigned int *dof_indices,
3502  VectorType &vec,
3503  VectorizedArray<Number> *dof_values,
3504  std::integral_constant<bool,true>) const
3505  {
3506  vectorized_transpose_and_store(false, dofs_per_cell, dof_values,
3507  dof_indices, vec.begin());
3508  }
3509 
3510  template <typename VectorType, bool booltype>
3511  void process_dofs_vectorized_transpose (const unsigned int dofs_per_cell,
3512  const unsigned int *dof_indices,
3513  VectorType &vec,
3514  VectorizedArray<Number> *dof_values,
3515  std::integral_constant<bool,false>) const
3516  {
3517  for (unsigned int i=0; i<dofs_per_cell; ++i)
3518  for (unsigned int v=0; v<VectorizedArray<Number>::n_array_elements; ++v)
3519  vector_access(vec, dof_indices[v]+i) = dof_values[i][v];
3520  }
3521 
3522  template <typename VectorType>
3523  void process_dof_gather (const unsigned int *indices,
3524  VectorType &vec,
3525  const unsigned int constant_offset,
3527  std::integral_constant<bool, true>) const
3528  {
3529  res.scatter(indices, vec.begin()+constant_offset);
3530  }
3531 
3532  template <typename VectorType>
3533  void process_dof_gather (const unsigned int *indices,
3534  VectorType &vec,
3535  const unsigned int constant_offset,
3537  std::integral_constant<bool, false>) const
3538  {
3539  for (unsigned int v=0; v<VectorizedArray<Number>::n_array_elements; ++v)
3540  vector_access(vec, indices[v]+constant_offset) = res[v];
3541  }
3542 
3543  template <typename VectorType>
3544  void process_dof_global (const types::global_dof_index index,
3545  VectorType &vec,
3546  Number &res) const
3547  {
3548  vec(index) = res;
3549  }
3550 
3551  void pre_constraints (const Number &,
3552  Number &) const
3553  {
3554  }
3555 
3556  template <typename VectorType>
3557  void process_constraint (const unsigned int,
3558  const Number,
3559  VectorType &,
3560  Number &) const
3561  {
3562  }
3563 
3564  void post_constraints (const Number &,
3565  Number &) const
3566  {
3567  }
3568 
3569  void process_empty (VectorizedArray<Number> &) const
3570  {
3571  }
3572  };
3573 
3574  // allows to select between block vectors and non-block vectors, which
3575  // allows to use a unified interface for extracting blocks on block vectors
3576  // and doing nothing on usual vectors
3577  template <typename VectorType, bool>
3578  struct BlockVectorSelector {};
3579 
3580  template <typename VectorType>
3581  struct BlockVectorSelector<VectorType,true>
3582  {
3583  typedef typename VectorType::BlockType BaseVectorType;
3584 
3585  static BaseVectorType *get_vector_component (VectorType &vec,
3586  const unsigned int component)
3587  {
3588  AssertIndexRange (component, vec.n_blocks());
3589  return &vec.block(component);
3590  }
3591  };
3592 
3593  template <typename VectorType>
3594  struct BlockVectorSelector<VectorType,false>
3595  {
3596  typedef VectorType BaseVectorType;
3597 
3598  static BaseVectorType *get_vector_component (VectorType &vec,
3599  const unsigned int component)
3600  {
3601  // FEEvaluation allows to combine several vectors from a scalar
3602  // FiniteElement into a "vector-valued" FEEvaluation object with
3603  // multiple components. These components can be extracted with the other
3604  // get_vector_component functions. If we do not get a vector of vectors
3605  // (std::vector<VectorType>, std::vector<VectorType*>, BlockVector), we
3606  // must make sure that we do not duplicate the components in input
3607  // and/or duplicate the resulting integrals. In such a case, we should
3608  // only get the zeroth component in the vector contained set nullptr for
3609  // the others which allows us to catch unintended use in
3610  // read_write_operation.
3611  if (component == 0)
3612  return &vec;
3613  else
3614  return nullptr;
3615  }
3616  };
3617 
3618  template <typename VectorType>
3619  struct BlockVectorSelector<std::vector<VectorType>,false>
3620  {
3621  typedef VectorType BaseVectorType;
3622 
3623  static BaseVectorType *get_vector_component (std::vector<VectorType> &vec,
3624  const unsigned int component)
3625  {
3626  AssertIndexRange (component, vec.size());
3627  return &vec[component];
3628  }
3629  };
3630 
3631  template <typename VectorType>
3632  struct BlockVectorSelector<std::vector<VectorType *>,false>
3633  {
3634  typedef VectorType BaseVectorType;
3635 
3636  static BaseVectorType *get_vector_component (std::vector<VectorType *> &vec,
3637  const unsigned int component)
3638  {
3639  AssertIndexRange (component, vec.size());
3640  return vec[component];
3641  }
3642  };
3643 }
3644 
3645 
3646 
3647 template <int dim, int n_components_, typename Number, bool is_face>
3648 template <typename VectorType, typename VectorOperation>
3649 inline
3650 void
3652 ::read_write_operation (const VectorOperation &operation,
3653  VectorType *src[],
3654  const bool apply_constraints) const
3655 {
3656  // Case 1: No MatrixFree object given, simple case because we do not need to
3657  // process constraints and need not care about vectorization -> go to
3658  // separate function
3659  if (matrix_info == nullptr)
3660  {
3661  read_write_operation_global(operation, src);
3662  return;
3663  }
3664 
3665  Assert (dof_info != nullptr, ExcNotInitialized());
3666  Assert (matrix_info->indices_initialized() == true,
3667  ExcNotInitialized());
3668  if (n_fe_components == 1)
3669  for (unsigned int comp=0; comp<n_components; ++comp)
3670  internal::check_vector_compatibility (*src[comp], *dof_info);
3671  else
3672  {
3673  internal::check_vector_compatibility (*src[0], *dof_info);
3674  }
3675 
3676  // Case 2: contiguous indices which use reduced storage of indices and can
3677  // use vectorized load/store operations -> go to separate function
3678  AssertIndexRange(cell,
3679  dof_info->index_storage_variants[dof_access_index].size());
3680  if (dof_info->index_storage_variants[is_face ? dof_access_index :
3683  {
3684  read_write_operation_contiguous(operation, src);
3685  return;
3686  }
3687 
3688  // Case 3: standard operation with one index per degree of freedom -> go on
3689  // here
3690 
3691  constexpr unsigned int n_vectorization = VectorizedArray<Number>::n_array_elements;
3692  const unsigned int dofs_per_component = this->data->dofs_per_component_on_cell;
3693  if (dof_info->index_storage_variants[is_face ? dof_access_index :
3696  {
3697  const unsigned int *dof_indices =
3698  dof_info->dof_indices_interleaved.data() +
3699  dof_info->row_starts[cell*n_fe_components*n_vectorization].first+
3700  dof_info->component_dof_indices_offset[active_fe_index][first_selected_component]*n_vectorization;
3701  if (n_components == 1 || n_fe_components == 1)
3702  for (unsigned int i=0; i<dofs_per_component; ++i, dof_indices += n_vectorization)
3703  for (unsigned int comp=0; comp<n_components; ++comp)
3704  operation.process_dof_gather (dof_indices, *src[comp], 0,
3705  values_dofs[comp][i],
3706  std::integral_constant<bool, std::is_same<typename VectorType::value_type,Number>::value>());
3707  else
3708  for (unsigned int comp=0; comp<n_components; ++comp)
3709  for (unsigned int i=0; i<dofs_per_component; ++i, dof_indices += n_vectorization)
3710  operation.process_dof_gather (dof_indices,
3711  *src[0], 0, values_dofs[comp][i],
3712  std::integral_constant<bool, std::is_same<typename VectorType::value_type,Number>::value>());
3713  return;
3714  }
3715 
3716  const unsigned int *dof_indices[n_vectorization];
3717  VectorizedArray<Number> **values_dofs =
3718  const_cast<VectorizedArray<Number> * *>(&this->values_dofs[0]);
3719 
3720  unsigned int cells_copied[n_vectorization];
3721  const unsigned int *cells;
3722  unsigned int n_vectorization_actual =
3723  dof_info->n_vectorization_lanes_filled[dof_access_index][cell];
3724  bool has_constraints = false;
3725  if (is_face)
3726  {
3728  for (unsigned int v=0; v<n_vectorization_actual; ++v)
3729  cells_copied[v] = cell*VectorizedArray<Number>::n_array_elements+v;
3730  cells =
3732  &cells_copied[0]
3733  :
3734  (is_interior_face ?
3735  &this->matrix_info->get_face_info(cell).cells_interior[0] :
3736  &this->matrix_info->get_face_info(cell).cells_exterior[0]);
3737  for (unsigned int v=0; v<n_vectorization_actual; ++v)
3738  {
3739  Assert(cells[v] < dof_info->row_starts.size()-1, ExcInternalError());
3740  has_constraints = has_constraints &&
3741  dof_info->row_starts[cells[v]*n_fe_components+first_selected_component+n_components].second !=
3742  dof_info->row_starts[cells[v]*n_fe_components+first_selected_component].second;
3743  dof_indices[v] = dof_info->dof_indices.data() +
3744  dof_info->row_starts[cells[v]*n_fe_components+first_selected_component].first;
3745  }
3746  for (unsigned int v=n_vectorization_actual; v<n_vectorization; ++v)
3747  dof_indices[v] = nullptr;
3748  }
3749  else
3750  {
3751  AssertIndexRange((cell+1)*n_vectorization*n_fe_components, dof_info->row_starts.size());
3752  const unsigned int n_components_read = n_fe_components > 1 ? n_components : 1;
3753  for (unsigned int v=0; v<n_vectorization_actual; ++v)
3754  {
3755  if (dof_info->row_starts[(cell*n_vectorization+v)*n_fe_components+first_selected_component+n_components_read].second !=
3756  dof_info->row_starts[(cell*n_vectorization+v)*n_fe_components+first_selected_component].second)
3757  has_constraints = true;
3758  Assert(dof_info->row_starts[(cell*n_vectorization+v)*n_fe_components+first_selected_component+n_components_read].first ==
3759  dof_info->row_starts[(cell*n_vectorization+v)*n_fe_components+first_selected_component].first ||
3760  dof_info->row_starts[(cell*n_vectorization+v)*n_fe_components+first_selected_component].first <
3761  dof_info->dof_indices.size(),
3762  ExcIndexRange(0, dof_info->row_starts[(cell*n_vectorization+v)*n_fe_components+first_selected_component].first,
3763  dof_info->dof_indices.size()));
3764  dof_indices[v] = dof_info->dof_indices.data() +
3765  dof_info->row_starts[(cell*n_vectorization+v)*n_fe_components+first_selected_component].first;
3766  }
3767  for (unsigned int v=n_vectorization_actual; v<n_vectorization; ++v)
3768  dof_indices[v] = nullptr;
3769  }
3770 
3771  // Case where we have no constraints throughout the whole cell: Can go
3772  // through the list of DoFs directly
3773  if (!has_constraints)
3774  {
3775  if (n_vectorization_actual < n_vectorization)
3776  for (unsigned int comp=0; comp<n_components; ++comp)
3777  for (unsigned int i=0; i<dofs_per_component; ++i)
3778  operation.process_empty(values_dofs[comp][i]);
3779  if (n_components == 1 || n_fe_components == 1)
3780  {
3781  for (unsigned int v=0; v<n_vectorization_actual; ++v)
3782  for (unsigned int i=0; i<dofs_per_component; ++i)
3783  for (unsigned int comp=0; comp<n_components; ++comp)
3784  operation.process_dof (dof_indices[v][i], *src[comp],
3785  values_dofs[comp][i][v]);
3786  }
3787  else
3788  {
3789  for (unsigned int comp=0; comp<n_components; ++comp)
3790  for (unsigned int v=0; v<n_vectorization_actual; ++v)
3791  for (unsigned int i=0; i<dofs_per_component; ++i)
3792  operation.process_dof (dof_indices[v][comp*dofs_per_component+i],
3793  *src[0], values_dofs[comp][i][v]);
3794  }
3795  return;
3796  }
3797 
3798  // In the case where there are some constraints to be resolved, loop over
3799  // all vector components that are filled and then over local dofs. ind_local
3800  // holds local number on cell, index iterates over the elements of
3801  // index_local_to_global and dof_indices points to the global indices stored
3802  // in index_local_to_global
3803  if (n_vectorization_actual < n_vectorization)
3804  for (unsigned int comp=0; comp<n_components; ++comp)
3805  for (unsigned int i=0; i<dofs_per_component; ++i)
3806  operation.process_empty(values_dofs[comp][i]);
3807  for (unsigned int v=0; v<n_vectorization_actual; ++v)
3808  {
3809  unsigned int index_indicators, next_index_indicators;
3810  const unsigned int n_components_read = n_fe_components > 1 ? n_components : 1;
3811  if (is_face)
3812  {
3813  index_indicators = dof_info->row_starts[cells[v]*n_fe_components+first_selected_component].second;
3814  next_index_indicators = dof_info->row_starts[cells[v]*n_fe_components+first_selected_component+1].second;
3815  }
3816  else
3817  {
3818  index_indicators = dof_info->row_starts[(cell*n_vectorization+v)*n_fe_components+first_selected_component].second;
3819  next_index_indicators = dof_info->row_starts[(cell*n_vectorization+v)*n_fe_components+first_selected_component+1].second;
3820  }
3821 
3822  if (apply_constraints == false &&
3823  dof_info->row_starts[(cell*n_vectorization+v)*n_fe_components+first_selected_component].second !=
3824  dof_info->row_starts[(cell*n_vectorization+v)*n_fe_components+first_selected_component+n_components_read].second)
3825  {
3826  Assert(dof_info->row_starts_plain_indices[cell*n_vectorization+v]
3828  ExcNotInitialized());
3829  dof_indices[v] = dof_info->plain_dof_indices.data() +
3830  dof_info->component_dof_indices_offset[active_fe_index][first_selected_component] +
3831  (is_face ?
3832  dof_info->row_starts_plain_indices[cells[v]]
3833  :
3834  dof_info->row_starts_plain_indices[cell*n_vectorization+v]);
3835  next_index_indicators = index_indicators;
3836  }
3837 
3838  if (n_components == 1 || n_fe_components == 1)
3839  {
3840  for (unsigned int c=0; c<n_components; ++c)
3841  Assert(src[c] != nullptr,
3842  ExcMessage("The finite element underlying this FEEvaluation "
3843  "object is scalar, but you requested " +
3844  std::to_string(n_components) +
3845  " components via the template argument in "
3846  "FEEvaluation. In that case, you must pass an "
3847  "std::vector<VectorType> or a BlockVector to " +
3848  "read_dof_values and distribute_local_to_global."));
3849 
3850  unsigned int ind_local = 0;
3851  for ( ; index_indicators != next_index_indicators; ++index_indicators)
3852  {
3853  const std::pair<unsigned short,unsigned short> indicator =
3854  dof_info->constraint_indicator[index_indicators];
3855  // run through values up to next constraint
3856  for (unsigned int j=0; j<indicator.first; ++j)
3857  for (unsigned int comp=0; comp<n_components; ++comp)
3858  operation.process_dof (dof_indices[v][j], *src[comp],
3859  values_dofs[comp][ind_local+j][v]);
3860 
3861  ind_local += indicator.first;
3862  dof_indices[v] += indicator.first;
3863 
3864  // constrained case: build the local value as a linear
3865  // combination of the global value according to constraints
3866  Number value [n_components];
3867  for (unsigned int comp=0; comp<n_components; ++comp)
3868  operation.pre_constraints (values_dofs[comp][ind_local][v],
3869  value[comp]);
3870 
3871  const Number *data_val =
3872  matrix_info->constraint_pool_begin(indicator.second);
3873  const Number *end_pool =
3874  matrix_info->constraint_pool_end(indicator.second);
3875  for ( ; data_val != end_pool; ++data_val, ++dof_indices[v])
3876  for (unsigned int comp=0; comp<n_components; ++comp)
3877  operation.process_constraint (*dof_indices[v], *data_val,
3878  *src[comp], value[comp]);
3879 
3880  for (unsigned int comp=0; comp<n_components; ++comp)
3881  operation.post_constraints (value[comp],
3882  values_dofs[comp][ind_local][v]);
3883  ind_local++;
3884  }
3885 
3886  AssertIndexRange(ind_local, dofs_per_component+1);
3887 
3888  for (; ind_local < dofs_per_component; ++dof_indices[v], ++ind_local)
3889  for (unsigned int comp=0; comp<n_components; ++comp)
3890  operation.process_dof (*dof_indices[v], *src[comp],
3891  values_dofs[comp][ind_local][v]);
3892  }
3893  else
3894  {
3895  // case with vector-valued finite elements where all components are
3896  // included in one single vector. Assumption: first come all entries
3897  // to the first component, then all entries to the second one, and
3898  // so on. This is ensured by the way MatrixFree reads out the
3899  // indices.
3900  for (unsigned int comp=0; comp<n_components; ++comp)
3901  {
3902  unsigned int ind_local = 0;
3903 
3904  // check whether there is any constraint on the current cell
3905  for ( ; index_indicators != next_index_indicators; ++index_indicators)
3906  {
3907  const std::pair<unsigned short,unsigned short> indicator =
3908  dof_info->constraint_indicator[index_indicators];
3909 
3910  // run through values up to next constraint
3911  for (unsigned int j=0; j<indicator.first; ++j)
3912  operation.process_dof (dof_indices[v][j], *src[0],
3913  values_dofs[comp][ind_local+j][v]);
3914  ind_local += indicator.first;
3915  dof_indices[v] += indicator.first;
3916 
3917  // constrained case: build the local value as a linear
3918  // combination of the global value according to constraints
3919  Number value;
3920  operation.pre_constraints (values_dofs[comp][ind_local][v], value);
3921 
3922  const Number *data_val =
3923  matrix_info->constraint_pool_begin(indicator.second);
3924  const Number *end_pool =
3925  matrix_info->constraint_pool_end(indicator.second);
3926 
3927  for ( ; data_val != end_pool; ++data_val, ++dof_indices[v])
3928  operation.process_constraint (*dof_indices[v], *data_val,
3929  *src[0], value);
3930 
3931  operation.post_constraints (value, values_dofs[comp][ind_local][v]);
3932  ind_local++;
3933  }
3934 
3935  AssertIndexRange(ind_local, dofs_per_component+1);
3936 
3937  // get the dof values past the last constraint
3938  for (; ind_local<dofs_per_component; ++dof_indices[v], ++ind_local)
3939  {
3940  AssertIndexRange(*dof_indices[v], src[0]->size());
3941  operation.process_dof (*dof_indices[v], *src[0],
3942  values_dofs[comp][ind_local][v]);
3943  }
3944 
3945  if (apply_constraints == true)
3946  {
3947  if (is_face)
3948  next_index_indicators = dof_info->row_starts[cells[v]*n_fe_components+first_selected_component+comp+2].second;
3949  else
3950  next_index_indicators = dof_info->row_starts[(cell*n_vectorization+v)*n_fe_components+first_selected_component+comp+2].second;
3951  }
3952  }
3953  }
3954  }
3955 }
3956 
3957 
3958 
3959 template <int dim, int n_components_, typename Number, bool is_face>
3960 template <typename VectorType, typename VectorOperation>
3961 inline
3962 void
3965  VectorType *src[]) const
3966 {
3967  Assert (!local_dof_indices.empty(), ExcNotInitialized());
3968 
3969  unsigned int index = first_selected_component * data->dofs_per_component_on_cell;
3970  for (unsigned int comp = 0; comp<n_components; ++comp)
3971  {
3972  for (unsigned int i=0; i<data->dofs_per_component_on_cell; ++i, ++index)
3973  {
3974  operation.process_empty(values_dofs[comp][i]);
3975  operation.process_dof_global(local_dof_indices[data->lexicographic_numbering[index]],
3976  *src[0], values_dofs[comp][i][0]);
3977  }
3978  }
3979 }
3980 
3981 
3982 
3983 template <int dim, int n_components_, typename Number, bool is_face>
3984 template <typename VectorType, typename VectorOperation>
3985 inline
3986 void
3989  VectorType *src[]) const
3990 {
3991  // This functions processes the functions read_dof_values,
3992  // distribute_local_to_global, and set_dof_values with the same code for
3993  // contiguous cell indices (DG case). The distinction between these three
3994  // cases is made by the input VectorOperation that either reads values from
3995  // a vector and puts the data into the local data field or write local data
3996  // into the vector. Certain operations are no-ops for the given use case.
3997 
3998  std::integral_constant<bool,std::is_same<typename VectorType::value_type,Number>::value>
3999  vector_selector;
4001  is_face ? dof_access_index : internal::MatrixFreeFunctions::DoFInfo::dof_access_cell;
4002 
4003  const std::vector<unsigned int> &dof_indices_cont
4004  = dof_info->dof_indices_contiguous[ind];
4005  const unsigned int vectorization_populated =
4006  dof_info->n_vectorization_lanes_filled[ind][this->cell];
4007  unsigned int dof_indices[VectorizedArray<Number>::n_array_elements];
4008  for (unsigned int v=0; v<vectorization_populated; ++v)
4009  dof_indices[v] = dof_indices_cont[cell*VectorizedArray<Number>::n_array_elements+v] +
4010  dof_info->component_dof_indices_offset[active_fe_index][first_selected_component];
4011  for (unsigned int v=vectorization_populated; v<VectorizedArray<Number>::n_array_elements; ++v)
4012  dof_indices[v] = numbers::invalid_unsigned_int;
4013 
4014  // In the case with contiguous cell indices, we know that there are no
4015  // constraints and that the indices within each element are contiguous
4016  if (vectorization_populated == VectorizedArray<Number>::n_array_elements)
4017  {
4018  if (n_components == 1 || n_fe_components == 1)
4019  for (unsigned int comp=0; comp<n_components; ++comp)
4020  operation.process_dofs_vectorized_transpose(data->dofs_per_component_on_cell,
4021  dof_indices,
4022  *src[comp], values_dofs[comp],
4023  vector_selector);
4024  else
4025  operation.process_dofs_vectorized_transpose(data->dofs_per_component_on_cell*
4026  n_components,
4027  dof_indices, *src[0],
4028  &values_dofs[0][0],
4029  vector_selector);
4030  }
4031  else
4032  for (unsigned int comp=0; comp<n_components; ++comp)
4033  {
4034  for (unsigned int i=0; i<data->dofs_per_component_on_cell; ++i)
4035  operation.process_empty(values_dofs[comp][i]);
4036  if (n_components == 1 || n_fe_components == 1)
4037  for (unsigned int v=0; v<vectorization_populated; ++v)
4038  for (unsigned int i=0; i<data->dofs_per_component_on_cell; ++i)
4039  operation.process_dof (dof_indices[v]+i, *src[comp],
4040  values_dofs[comp][i][v]);
4041  else
4042  for (unsigned int v=0; v<vectorization_populated; ++v)
4043  for (unsigned int i=0; i<data->dofs_per_component_on_cell; ++i)
4044  operation.process_dof (dof_indices[v]+i+comp*data->dofs_per_component_on_cell,
4045  *src[0], values_dofs[comp][i][v]);
4046  }
4047 }
4048 
4049 
4050 
4051 template <int dim, int n_components_, typename Number, bool is_face>
4052 template <typename VectorType>
4053 inline
4054 void
4056 ::read_dof_values (const VectorType &src,
4057  const unsigned int first_index)
4058 {
4059  // select between block vectors and non-block vectors. Note that the number
4060  // of components is checked in the internal data
4061  typename internal::BlockVectorSelector<VectorType,
4062  IsBlockVector<VectorType>::value>::BaseVectorType *src_data[n_components];
4063  for (unsigned int d=0; d<n_components; ++d)
4064  src_data[d] = internal::BlockVectorSelector<VectorType, IsBlockVector<VectorType>::value>::get_vector_component(const_cast<VectorType &>(src), d+first_index);
4065 
4066  internal::VectorReader<Number> reader;
4067  read_write_operation (reader, src_data, true);
4068 
4069 #ifdef DEBUG
4070  dof_values_initialized = true;
4071 #endif
4072 }
4073 
4074 
4075 
4076 template <int dim, int n_components_, typename Number, bool is_face>
4077 template <typename VectorType>
4078 inline
4079 void
4081 ::read_dof_values_plain (const VectorType &src,
4082  const unsigned int first_index)
4083 {
4084  // select between block vectors and non-block vectors. Note that the number
4085  // of components is checked in the internal data
4086  typename internal::BlockVectorSelector<VectorType,
4087  IsBlockVector<VectorType>::value>::BaseVectorType *src_data[n_components];
4088  for (unsigned int d=0; d<n_components; ++d)
4089  src_data[d] = internal::BlockVectorSelector<VectorType, IsBlockVector<VectorType>::value>::get_vector_component(const_cast<VectorType &>(src), d+first_index);
4090 
4091  internal::VectorReader<Number> reader;
4092  read_write_operation (reader, src_data, false);
4093 
4094 #ifdef DEBUG
4095  dof_values_initialized = true;
4096 #endif
4097 }
4098 
4099 
4100 
4101 template <int dim, int n_components_, typename Number, bool is_face>
4102 template <typename VectorType>
4103 inline
4104 void
4106 ::distribute_local_to_global (VectorType &dst,
4107  const unsigned int first_index) const
4108 {
4109  Assert (dof_values_initialized==true,
4111 
4112  // select between block vectors and non-block vectors. Note that the number
4113  // of components is checked in the internal data
4114  typename internal::BlockVectorSelector<VectorType,
4115  IsBlockVector<VectorType>::value>::BaseVectorType *dst_data[n_components];
4116  for (unsigned int d=0; d<n_components; ++d)
4117  dst_data[d] = internal::BlockVectorSelector<VectorType, IsBlockVector<VectorType>::value>::get_vector_component(dst, d+first_index);
4118 
4119  internal::VectorDistributorLocalToGlobal<Number> distributor;
4120  read_write_operation (distributor, dst_data);
4121 }
4122 
4123 
4124 
4125 template <int dim, int n_components_, typename Number, bool is_face>
4126 template <typename VectorType>
4127 inline
4128 void
4130 ::set_dof_values (VectorType &dst,
4131  const unsigned int first_index) const
4132 {
4133  Assert (dof_values_initialized==true,
4135 
4136  // select between block vectors and non-block vectors. Note that the number
4137  // of components is checked in the internal data
4138  typename internal::BlockVectorSelector<VectorType,
4139  IsBlockVector<VectorType>::value>::BaseVectorType *dst_data[n_components];
4140  for (unsigned int d=0; d<n_components; ++d)
4141  dst_data[d] = internal::BlockVectorSelector<VectorType, IsBlockVector<VectorType>::value>::get_vector_component(dst, d+first_index);
4142 
4143  internal::VectorSetter<Number> setter;
4144  read_write_operation (setter, dst_data);
4145 }
4146 
4147 
4148 
4149 
4150 /*------------------------------ access to data fields ----------------------*/
4151 
4152 template <int dim, int n_components, typename Number, bool is_face>
4153 inline
4154 const std::vector<unsigned int> &
4157 {
4158  return data->lexicographic_numbering;
4159 }
4160 
4161 
4162 
4163 template <int dim, int n_components, typename Number, bool is_face>
4164 inline
4167 get_scratch_data() const
4168 {
4169  return ArrayView<VectorizedArray<Number> >(const_cast<VectorizedArray<Number> *>(scratch_data),
4170  scratch_data_array->end()-
4171  scratch_data);
4172 }
4173 
4174 
4175 
4176 template <int dim, int n_components, typename Number, bool is_face>
4177 inline
4180 begin_dof_values () const
4181 {
4182  return &values_dofs[0][0];
4183 }
4184 
4185 
4186 
4187 template <int dim, int n_components, typename Number, bool is_face>
4188 inline
4192 {
4193 #ifdef DEBUG
4194  dof_values_initialized = true;
4195 #endif
4196  return &values_dofs[0][0];
4197 }
4198 
4199 
4200 
4201 template <int dim, int n_components, typename Number, bool is_face>
4202 inline
4205 begin_values () const
4206 {
4207  Assert (values_quad_initialized || values_quad_submitted,
4208  ExcNotInitialized());
4209  return &values_quad[0][0];
4210 }
4211 
4212 
4213 
4214 template <int dim, int n_components, typename Number, bool is_face>
4215 inline
4218 begin_values ()
4219 {
4220 #ifdef DEBUG
4221  values_quad_initialized = true;
4222  values_quad_submitted = true;
4223 #endif
4224  return &values_quad[0][0];
4225 }
4226 
4227 
4228 
4229 template <int dim, int n_components, typename Number, bool is_face>
4230 inline
4233 begin_gradients () const
4234 {
4235  Assert (gradients_quad_initialized || gradients_quad_submitted,
4236  ExcNotInitialized());
4237  return &gradients_quad[0][0][0];
4238 }
4239 
4240 
4241 
4242 template <int dim, int n_components, typename Number, bool is_face>
4243 inline
4246 begin_gradients ()
4247 {
4248 #ifdef DEBUG
4249  gradients_quad_submitted = true;
4250  gradients_quad_initialized = true;
4251 #endif
4252  return &gradients_quad[0][0][0];
4253 }
4254 
4255 
4256 
4257 template <int dim, int n_components, typename Number, bool is_face>
4258 inline
4261 begin_hessians () const
4262 {
4263  Assert (hessians_quad_initialized, ExcNotInitialized());
4264  return &hessians_quad[0][0][0];
4265 }
4266 
4267 
4268 
4269 template <int dim, int n_components, typename Number, bool is_face>
4270 inline
4273 begin_hessians ()
4274 {
4275 #ifdef DEBUG
4276  hessians_quad_initialized = true;
4277 #endif
4278  return &hessians_quad[0][0][0];
4279 }
4280 
4281 
4282 
4283 template <int dim, int n_components_, typename Number, bool is_face>
4284 inline DEAL_II_ALWAYS_INLINE
4287 ::get_dof_value (const unsigned int dof) const
4288 {
4289  AssertIndexRange (dof, this->data->dofs_per_component_on_cell);
4291  for (unsigned int comp=0; comp<n_components; comp++)
4292  return_value[comp] = this->values_dofs[comp][dof];
4293  return return_value;
4294 }
4295 
4296 
4297 
4298 template <int dim, int n_components_, typename Number, bool is_face>
4299 inline DEAL_II_ALWAYS_INLINE
4302 ::get_value (const unsigned int q_point) const
4303 {
4304  Assert (this->values_quad_initialized==true,
4306  AssertIndexRange (q_point, this->n_quadrature_points);
4308  for (unsigned int comp=0; comp<n_components; comp++)
4309  return_value[comp] = this->values_quad[comp][q_point];
4310  return return_value;
4311 }
4312 
4313 
4314 
4315 template <int dim, int n_components_, typename Number, bool is_face>
4316 inline DEAL_II_ALWAYS_INLINE
4319 ::get_gradient (const unsigned int q_point) const
4320 {
4321  Assert (this->gradients_quad_initialized==true,
4323  AssertIndexRange (q_point, this->n_quadrature_points);
4324 
4325  Assert(jacobian != nullptr, ExcNotInitialized());
4326 
4328 
4329  // Cartesian cell
4330  if (!is_face && this->cell_type == internal::MatrixFreeFunctions::cartesian)
4331  {
4332  for (unsigned int comp=0; comp<n_components; comp++)
4333  for (unsigned int d=0; d<dim; ++d)
4334  grad_out[comp][d] = (this->gradients_quad[comp][d][q_point] *
4335  jacobian[0][d][d]);
4336  }
4337  // cell with general/affine Jacobian
4338  else
4339  {
4341  jacobian[this->cell_type > internal::MatrixFreeFunctions::affine ? q_point : 0];
4342  for (unsigned int comp=0; comp<n_components; comp++)
4343  for (unsigned int d=0; d<dim; ++d)
4344  {
4345  grad_out[comp][d] = jac[d][0] *
4346  this->gradients_quad[comp][0][q_point];
4347  for (unsigned int e=1; e<dim; ++e)
4348  grad_out[comp][d] += jac[d][e] *
4349  this->gradients_quad[comp][e][q_point];
4350  }
4351  }
4352  return grad_out;
4353 }
4354 
4355 
4356 
4357 template <int dim, int n_components_, typename Number, bool is_face>
4358 inline DEAL_II_ALWAYS_INLINE
4361 ::get_normal_derivative (const unsigned int q_point) const
4362 {
4363  AssertIndexRange (q_point, this->n_quadrature_points);
4364  Assert (this->gradients_quad_initialized==true,
4366 
4367  Assert(normal_x_jacobian != nullptr, ExcNotInitialized());
4368 
4370  if (this->cell_type == internal::MatrixFreeFunctions::cartesian)
4371  for (unsigned int comp=0; comp<n_components; comp++)
4372  grad_out[comp] = this->gradients_quad[comp][dim-1][q_point] *
4373  (this->normal_x_jacobian[0][dim-1]);
4374  else
4375  {
4376  const unsigned int index =
4377  this->cell_type <= internal::MatrixFreeFunctions::affine ? 0 : q_point;
4378  for (unsigned int comp=0; comp<n_components; comp++)
4379  {
4380  grad_out[comp] = this->gradients_quad[comp][0][q_point] *
4381  this->normal_x_jacobian[index][0];
4382  for (unsigned int d=1; d<dim; ++d)
4383  grad_out[comp] += this->gradients_quad[comp][d][q_point] *
4384  this->normal_x_jacobian[index][d];
4385  }
4386  }
4387  return grad_out;
4388 }
4389 
4390 
4391 
4392 namespace internal
4393 {
4394  // compute tmp = hess_unit(u) * J^T. do this manually because we do not
4395  // store the lower diagonal because of symmetry
4396  template <typename Number>
4397  inline
4398  void
4399  hessian_unit_times_jac (const Tensor<2,1,VectorizedArray<Number> > &jac,
4400  const VectorizedArray<Number> *const hessians_quad[1],
4401  const unsigned int q_point,
4402  VectorizedArray<Number> (&tmp)[1][1])
4403  {
4404  tmp[0][0] = jac[0][0] * hessians_quad[0][q_point];
4405  }
4406 
4407  template <typename Number>
4408  inline
4409  void
4410  hessian_unit_times_jac (const Tensor<2,2,VectorizedArray<Number> > &jac,
4411  const VectorizedArray<Number> *const hessians_quad[3],
4412  const unsigned int q_point,
4413  VectorizedArray<Number> (&tmp)[2][2])
4414  {
4415  for (unsigned int d=0; d<2; ++d)
4416  {
4417  tmp[0][d] = (jac[d][0] * hessians_quad[0][q_point] +
4418  jac[d][1] * hessians_quad[2][q_point]);
4419  tmp[1][d] = (jac[d][0] * hessians_quad[2][q_point] +
4420  jac[d][1] * hessians_quad[1][q_point]);
4421  }
4422  }
4423 
4424  template <typename Number>
4425  inline
4426  void
4427  hessian_unit_times_jac (const Tensor<2,3,VectorizedArray<Number> > &jac,
4428  const VectorizedArray<Number> *const hessians_quad[6],
4429  const unsigned int q_point,
4430  VectorizedArray<Number> (&tmp)[3][3])
4431  {
4432  for (unsigned int d=0; d<3; ++d)
4433  {
4434  tmp[0][d] = (jac[d][0] * hessians_quad[0][q_point] +
4435  jac[d][1] * hessians_quad[3][q_point] +
4436  jac[d][2] * hessians_quad[4][q_point]);
4437  tmp[1][d] = (jac[d][0] * hessians_quad[3][q_point] +
4438  jac[d][1] * hessians_quad[1][q_point] +
4439  jac[d][2] * hessians_quad[5][q_point]);
4440  tmp[2][d] = (jac[d][0] * hessians_quad[4][q_point] +
4441  jac[d][1] * hessians_quad[5][q_point] +
4442  jac[d][2] * hessians_quad[2][q_point]);
4443  }
4444  }
4445 }
4446 
4447 
4448 
4449 template <int dim, int n_components_, typename Number, bool is_face>
4450 inline
4453 ::get_hessian (const unsigned int q_point) const
4454 {
4455  Assert(!is_face, ExcNotImplemented());
4456  Assert (this->hessians_quad_initialized==true,
4458  AssertIndexRange (q_point, this->n_quadrature_points);
4459 
4460  Assert(jacobian != nullptr, ExcNotImplemented());
4462  jacobian[this->cell_type <= internal::MatrixFreeFunctions::affine ? 0 : q_point];
4463 
4465 
4466  // Cartesian cell
4467  if (this->cell_type == internal::MatrixFreeFunctions::cartesian)
4468  {
4469  for (unsigned int comp=0; comp<n_components; comp++)
4470  for (unsigned int d=0; d<dim; ++d)
4471  {
4472  hessian_out[comp][d][d] = (this->hessians_quad[comp][d][q_point] *
4473  jac[d][d] * jac[d][d]);
4474  switch (dim)
4475  {
4476  case 1:
4477  break;
4478  case 2:
4479  hessian_out[comp][0][1] = (this->hessians_quad[comp][2][q_point] *
4480  jac[0][0] * jac[1][1]);
4481  break;
4482  case 3:
4483  hessian_out[comp][0][1] = (this->hessians_quad[comp][3][q_point] *
4484  jac[0][0] * jac[1][1]);
4485  hessian_out[comp][0][2] = (this->hessians_quad[comp][4][q_point] *
4486  jac[0][0] * jac[2][2]);
4487  hessian_out[comp][1][2] = (this->hessians_quad[comp][5][q_point] *
4488  jac[1][1] * jac[2][2]);
4489  break;
4490  default:
4491  Assert (false, ExcNotImplemented());
4492  }
4493  for (unsigned int e=d+1; e<dim; ++e)
4494  hessian_out[comp][e][d] = hessian_out[comp][d][e];
4495  }
4496  }
4497  // cell with general Jacobian, but constant within the cell
4498  else if (this->cell_type == internal::MatrixFreeFunctions::affine)
4499  {
4500  for (unsigned int comp=0; comp<n_components; comp++)
4501  {
4502  // compute laplacian before the gradient because it needs to access
4503  // unscaled gradient data
4504  VectorizedArray<Number> tmp[dim][dim];
4505  internal::hessian_unit_times_jac (jac, this->hessians_quad[comp],
4506  q_point, tmp);
4507 
4508  // compute first part of hessian, J * tmp = J * hess_unit(u) * J^T
4509  for (unsigned int d=0; d<dim; ++d)
4510  for (unsigned int e=d; e<dim; ++e)
4511  {
4512  hessian_out[comp][d][e] = jac[d][0] * tmp[0][e];
4513  for (unsigned int f=1; f<dim; ++f)
4514  hessian_out[comp][d][e] += jac[d][f] * tmp[f][e];
4515  }
4516 
4517  // no J' * grad(u) part here because the Jacobian is constant
4518  // throughout the cell and hence, its derivative is zero
4519 
4520  // take symmetric part
4521  for (unsigned int d=0; d<dim; ++d)
4522  for (unsigned int e=d+1; e<dim; ++e)
4523  hessian_out[comp][e][d] = hessian_out[comp][d][e];
4524  }
4525  }
4526  // cell with general Jacobian
4527  else
4528  {
4529  const Tensor<1,dim*(dim+1)/2,Tensor<1,dim,VectorizedArray<Number> > > &jac_grad =
4530  mapping_data->jacobian_gradients[1-this->is_interior_face][this->mapping_data->data_index_offsets[this->cell]+q_point];
4531  for (unsigned int comp=0; comp<n_components; comp++)
4532  {
4533  // compute laplacian before the gradient because it needs to access
4534  // unscaled gradient data
4535  VectorizedArray<Number> tmp[dim][dim];
4536  internal::hessian_unit_times_jac (jac, this->hessians_quad[comp],
4537  q_point, tmp);
4538 
4539  // compute first part of hessian, J * tmp = J * hess_unit(u) * J^T
4540  for (unsigned int d=0; d<dim; ++d)
4541  for (unsigned int e=d; e<dim; ++e)
4542  {
4543  hessian_out[comp][d][e] = jac[d][0] * tmp[0][e];
4544  for (unsigned int f=1; f<dim; ++f)
4545  hessian_out[comp][d][e] += jac[d][f] * tmp[f][e];
4546  }
4547 
4548  // add diagonal part of J' * grad(u)
4549  for (unsigned int d=0; d<dim; ++d)
4550  for (unsigned int e=0; e<dim; ++e)
4551  hessian_out[comp][d][d] += (jac_grad[d][e] *
4552  this->gradients_quad[comp][e][q_point]);
4553 
4554  // add off-diagonal part of J' * grad(u)
4555  for (unsigned int d=0, count=dim; d<dim; ++d)
4556  for (unsigned int e=d+1; e<dim; ++e, ++count)
4557  for (unsigned int f=0; f<dim; ++f)
4558  hessian_out[comp][d][e] += (jac_grad[count][f] *
4559  this->gradients_quad[comp][f][q_point]);
4560 
4561  // take symmetric part
4562  for (unsigned int d=0; d<dim; ++d)
4563  for (unsigned int e=d+1; e<dim; ++e)
4564  hessian_out[comp][e][d] = hessian_out[comp][d][e];
4565  }
4566  }
4568 }
4569 
4570 
4571 
4572 template <int dim, int n_components_, typename Number, bool is_face>
4573 inline
4576 ::get_hessian_diagonal (const unsigned int q_point) const
4577 {
4578  Assert(!is_face, ExcNotImplemented());
4579  Assert (this->hessians_quad_initialized==true,
4581  AssertIndexRange (q_point, this->n_quadrature_points);
4582 
4583  Assert(jacobian != nullptr, ExcNotImplemented());
4585  jacobian[this->cell_type <= internal::MatrixFreeFunctions::affine ? 0 : q_point];
4586 
4588 
4589  // Cartesian cell
4590  if (this->cell_type == internal::MatrixFreeFunctions::cartesian)
4591  {
4592  for (unsigned int comp=0; comp<n_components; comp++)
4593  for (unsigned int d=0; d<dim; ++d)
4594  hessian_out[comp][d] = (this->hessians_quad[comp][d][q_point] *
4595  jac[d][d] * jac[d][d]);
4596  }
4597  // cell with general Jacobian, but constant within the cell
4598  else if (this->cell_type == internal::MatrixFreeFunctions::affine)
4599  {
4600  for (unsigned int comp=0; comp<n_components; comp++)
4601  {
4602  // compute laplacian before the gradient because it needs to access
4603  // unscaled gradient data
4604  VectorizedArray<Number> tmp[dim][dim];
4605  internal::hessian_unit_times_jac (jac, this->hessians_quad[comp],
4606  q_point, tmp);
4607 
4608  // compute only the trace part of hessian, J * tmp = J *
4609  // hess_unit(u) * J^T
4610  for (unsigned int d=0; d<dim; ++d)
4611  {
4612  hessian_out[comp][d] = jac[d][0] * tmp[0][d];
4613  for (unsigned int f=1; f<dim; ++f)
4614  hessian_out[comp][d] += jac[d][f] * tmp[f][d];
4615  }
4616  }
4617  }
4618  // cell with general Jacobian
4619  else
4620  {
4621  const Tensor<1,dim*(dim+1)/2,Tensor<1,dim,VectorizedArray<Number> > > &jac_grad =
4622  mapping_data->jacobian_gradients[0][this->mapping_data->data_index_offsets[this->cell]+q_point];
4623  for (unsigned int comp=0; comp<n_components; comp++)
4624  {
4625  // compute laplacian before the gradient because it needs to access
4626  // unscaled gradient data
4627  VectorizedArray<Number> tmp[dim][dim];
4628  internal::hessian_unit_times_jac (jac, this->hessians_quad[comp],
4629  q_point, tmp);
4630 
4631  // compute only the trace part of hessian, J * tmp = J *
4632  // hess_unit(u) * J^T
4633  for (unsigned int d=0; d<dim; ++d)
4634  {
4635  hessian_out[comp][d] = jac[d][0] * tmp[0][d];
4636  for (unsigned int f=1; f<dim; ++f)
4637  hessian_out[comp][d] += jac[d][f] * tmp[f][d];
4638  }
4639 
4640  for (unsigned int d=0; d<dim; ++d)
4641  for (unsigned int e=0; e<dim; ++e)
4642  hessian_out[comp][d] += (jac_grad[d][e] *
4643  this->gradients_quad[comp][e][q_point]);
4644  }
4645  }
4646  return hessian_out;
4647 }
4648 
4649 
4650 
4651 template <int dim, int n_components_, typename Number, bool is_face>
4652 inline
4655 ::get_laplacian (const unsigned int q_point) const
4656 {
4657  Assert (is_face == false, ExcNotImplemented());
4658  Assert (this->hessians_quad_initialized==true,
4660  AssertIndexRange (q_point, this->n_quadrature_points);
4661 
4664  = get_hessian_diagonal(q_point);
4665  for (unsigned int comp=0; comp<n_components; ++comp)
4666  {
4667  laplacian_out[comp] = hess_diag[comp][0];
4668  for (unsigned int d=1; d<dim; ++d)
4669  laplacian_out[comp] += hess_diag[comp][d];
4670  }
4671  return laplacian_out;
4672 }
4673 
4674 
4675 
4676 template <int dim, int n_components_, typename Number, bool is_face>
4677 inline DEAL_II_ALWAYS_INLINE
4678 void
4680 ::submit_dof_value (const Tensor<1,n_components_,VectorizedArray<Number> > val_in,
4681  const unsigned int dof)
4682 {
4683 #ifdef DEBUG
4684  this->dof_values_initialized = true;
4685 #endif
4686  AssertIndexRange (dof, this->data->dofs_per_component_on_cell);
4687  for (unsigned int comp=0; comp<n_components; comp++)
4688  this->values_dofs[comp][dof] = val_in[comp];
4689 }
4690 
4691 
4692 
4693 template <int dim, int n_components_, typename Number, bool is_face>
4694 inline DEAL_II_ALWAYS_INLINE
4695 void
4697 ::submit_value (const Tensor<1,n_components_,VectorizedArray<Number> > val_in,
4698  const unsigned int q_point)
4699 {
4700 #ifdef DEBUG
4702  AssertIndexRange (q_point, this->n_quadrature_points);
4703  Assert (this->J_value != nullptr, ExcNotInitialized());
4704  this->values_quad_submitted = true;
4705 #endif
4706 
4707  if (this->cell_type <= internal::MatrixFreeFunctions::affine)
4708  {
4709  const VectorizedArray<Number> JxW = J_value[0] * quadrature_weights[q_point];
4710  for (unsigned int comp=0; comp<n_components; ++comp)
4711  this->values_quad[comp][q_point] = val_in[comp] * JxW;
4712  }
4713  else
4714  {
4715  const VectorizedArray<Number> JxW = J_value[q_point];
4716  for (unsigned int comp=0; comp<n_components; ++comp)
4717  this->values_quad[comp][q_point] = val_in[comp] * JxW;
4718  }
4719 }
4720 
4721 
4722 
4723 template <int dim, int n_components_, typename Number, bool is_face>
4724 inline DEAL_II_ALWAYS_INLINE
4725 void
4727 ::submit_gradient (const Tensor<1,n_components_,
4728  Tensor<1,dim,VectorizedArray<Number> > >grad_in,
4729  const unsigned int q_point)
4730 {
4731 #ifdef DEBUG
4733  AssertIndexRange (q_point, this->n_quadrature_points);
4734  this->gradients_quad_submitted = true;
4735  Assert (this->J_value != nullptr, ExcNotInitialized());
4736  Assert (this->jacobian != nullptr, ExcNotInitialized());
4737 #endif
4738 
4739  if (!is_face && this->cell_type == internal::MatrixFreeFunctions::cartesian)
4740  {
4741  const VectorizedArray<Number> JxW = J_value[0] * quadrature_weights[q_point];
4742  for (unsigned int comp=0; comp<n_components; comp++)
4743  for (unsigned int d=0; d<dim; ++d)
4744  this->gradients_quad[comp][d][q_point] = (grad_in[comp][d] *
4745  jacobian[0][d][d] * JxW);
4746  }
4747  else
4748  {
4750  this->cell_type > internal::MatrixFreeFunctions::affine ?
4751  jacobian[q_point] : jacobian[0];
4752  const VectorizedArray<Number> JxW =
4753  this->cell_type > internal::MatrixFreeFunctions::affine ?
4754  J_value[q_point] : J_value[0] * quadrature_weights[q_point];
4755  for (unsigned int comp=0; comp<n_components; ++comp)
4756  for (unsigned int d=0; d<dim; ++d)
4757  {
4758  VectorizedArray<Number> new_val = jac[0][d] * grad_in[comp][0];
4759  for (unsigned int e=1; e<dim; ++e)
4760  new_val += (jac[e][d] * grad_in[comp][e]);
4761  this->gradients_quad[comp][d][q_point] = new_val * JxW;
4762  }
4763  }
4764 }
4765 
4766 
4767 
4768 template <int dim, int n_components_, typename Number, bool is_face>
4769 inline DEAL_II_ALWAYS_INLINE
4770 void
4772 ::submit_normal_derivative (const Tensor<1,n_components_,VectorizedArray<Number> > grad_in,
4773  const unsigned int q_point)
4774 {
4775 #ifdef DEBUG
4776  AssertIndexRange (q_point, this->n_quadrature_points);
4777  this->gradients_quad_submitted = true;
4778  Assert (this->normal_x_jacobian != nullptr, ExcNotInitialized());
4779 #endif
4780 
4781  if (this->cell_type == internal::MatrixFreeFunctions::cartesian)
4782  for (unsigned int comp=0; comp<n_components; comp++)
4783  {
4784  for (unsigned int d=0; d<dim-1; ++d)
4785  this->gradients_quad[comp][d][q_point] = VectorizedArray<Number>();
4786  this->gradients_quad[comp][dim-1][q_point] =
4787  grad_in[comp] * (this->normal_x_jacobian[0][dim-1] *
4788  this->J_value[0] * this->quadrature_weights[q_point]);
4789  }
4790  else
4791  {
4792  const unsigned int index =
4793  this->cell_type <= internal::MatrixFreeFunctions::affine ? 0 : q_point;
4794  for (unsigned int comp=0; comp<n_components; comp++)
4795  {
4796  VectorizedArray<Number> factor = grad_in[comp] *
4797  this->J_value[index];
4798  if (this->cell_type <= internal::MatrixFreeFunctions::affine)
4799  factor = factor * this->quadrature_weights[q_point];
4800  for (unsigned int d=0; d<dim; ++d)
4801  this->gradients_quad[comp][d][q_point] = factor *
4802  this->normal_x_jacobian[index][d];
4803  }
4804  }
4805 }
4806 
4807 
4808 
4809 
4810 template <int dim, int n_components_, typename Number, bool is_face>
4811 inline
4814 ::integrate_value () const
4815 {
4816 #ifdef DEBUG
4818  Assert (this->values_quad_submitted == true,
4820 #endif
4822  for (unsigned int comp=0; comp<n_components; ++comp)
4823  return_value[comp] = this->values_quad[comp][0];
4824  const unsigned int n_q_points = this->n_quadrature_points;
4825  for (unsigned int q=1; q<n_q_points; ++q)
4826  for (unsigned int comp=0; comp<n_components; ++comp)
4827  return_value[comp] += this->values_quad[comp][q];
4828  return (return_value);
4829 }
4830 
4831 
4832 
4833 /*----------------------- FEEvaluationAccess --------------------------------*/
4834 
4835 
4836 template <int dim, int n_components_, typename Number, bool is_face>
4837 inline
4840  const unsigned int dof_no,
4841  const unsigned int first_selected_component,
4842  const unsigned int quad_no_in,
4843  const unsigned int fe_degree,
4844  const unsigned int n_q_points,
4845  const bool is_interior_face)
4846  :
4847  FEEvaluationBase <dim,n_components_,Number,is_face>
4848  (data_in, dof_no, first_selected_component, quad_no_in, fe_degree, n_q_points,
4849  is_interior_face)
4850 {}
4851 
4852 
4853 
4854 template <int dim, int n_components_, typename Number, bool is_face>
4855 template <int n_components_other>
4856 inline
4858 ::FEEvaluationAccess (const Mapping<dim> &mapping,
4859  const FiniteElement<dim> &fe,
4860  const Quadrature<1> &quadrature,
4861  const UpdateFlags update_flags,
4862  const unsigned int first_selected_component,
4864  :
4865  FEEvaluationBase <dim,n_components_,Number,is_face>(mapping, fe, quadrature, update_flags,
4866  first_selected_component, other)
4867 {}
4868 
4869 
4870 
4871 template <int dim, int n_components_, typename Number, bool is_face>
4872 inline
4875  :
4876  FEEvaluationBase <dim,n_components_,Number,is_face>(other)
4877 {}
4878 
4879 
4880 
4881 template <int dim, int n_components_, typename Number, bool is_face>
4882 inline
4886 {
4888  return *this;
4889 }
4890 
4891 
4892 
4893 /*-------------------- FEEvaluationAccess scalar ----------------------------*/
4894 
4895 
4896 template <int dim, typename Number, bool is_face>
4897 inline
4900  const unsigned int dof_no,
4901  const unsigned int first_selected_component,
4902  const unsigned int quad_no_in,
4903  const unsigned int fe_degree,
4904  const unsigned int n_q_points,
4905  const bool is_interior_face)
4906  :
4907  FEEvaluationBase <dim,1,Number,is_face>
4908  (data_in, dof_no, first_selected_component, quad_no_in, fe_degree, n_q_points,
4909  is_interior_face)
4910 {}
4911 
4912 
4913 
4914 template <int dim, typename Number, bool is_face>
4915 template <int n_components_other>
4916 inline
4918 ::FEEvaluationAccess (const Mapping<dim> &mapping,
4919  const FiniteElement<dim> &fe,
4920  const Quadrature<1> &quadrature,
4921  const UpdateFlags update_flags,
4922  const unsigned int first_selected_component,
4924  :
4925  FEEvaluationBase <dim,1,Number,is_face> (mapping, fe, quadrature, update_flags,
4926  first_selected_component, other)
4927 {}
4928 
4929 
4930 
4931 template <int dim, typename Number, bool is_face>
4932 inline
4935  :
4936  FEEvaluationBase <dim,1,Number,is_face>(other)
4937 {}
4938 
4939 
4940 
4941 template <int dim, typename Number, bool is_face>
4942 inline
4946 {
4948  return *this;
4949 }
4950 
4951 
4952 
4953 template <int dim, typename Number, bool is_face>
4954 inline DEAL_II_ALWAYS_INLINE
4957 ::get_dof_value (const unsigned int dof) const
4958 {
4959  AssertIndexRange (dof, this->data->dofs_per_component_on_cell);
4960  return this->values_dofs[0][dof];
4961 }
4962 
4963 
4964 
4965 template <int dim, typename Number, bool is_face>
4966 inline DEAL_II_ALWAYS_INLINE
4969 ::get_value (const unsigned int q_point) const
4970 {
4971  Assert (this->values_quad_initialized==true,
4973  AssertIndexRange (q_point, this->n_quadrature_points);
4974  return this->values_quad[0][q_point];
4975 }
4976 
4977 
4978 
4979 template <int dim, typename Number, bool is_face>
4980 inline DEAL_II_ALWAYS_INLINE
4983 ::get_normal_derivative (const unsigned int q_point) const
4984 {
4985  return BaseClass::get_normal_derivative(q_point)[0];
4986 }
4987 
4988 
4989 
4990 template <int dim, typename Number, bool is_face>
4991 inline DEAL_II_ALWAYS_INLINE
4994 ::get_gradient (const unsigned int q_point) const
4995 {
4996  // could use the base class gradient, but that involves too many expensive
4997  // initialization operations on tensors
4998 
4999  Assert (this->gradients_quad_initialized==true,
5001  AssertIndexRange (q_point, this->n_quadrature_points);
5002 
5003  Assert (this->jacobian != nullptr, ExcNotInitialized());
5004 
5006 
5007  if (!is_face && this->cell_type == internal::MatrixFreeFunctions::cartesian)
5008  {
5009  for (unsigned int d=0; d<dim; ++d)
5010  grad_out[d] = (this->gradients_quad[0][d][q_point] *
5011  this->jacobian[0][d][d]);
5012  }
5013  // cell with general/affine Jacobian
5014  else
5015  {
5017  this->jacobian[this->cell_type > internal::MatrixFreeFunctions::affine ?
5018  q_point : 0];
5019  for (unsigned int d=0; d<dim; ++d)
5020  {
5021  grad_out[d] = jac[d][0] * this->gradients_quad[0][0][q_point];
5022  for (unsigned int e=1; e<dim; ++e)
5023  grad_out[d] += jac[d][e] * this->gradients_quad[0][e][q_point];
5024  }
5025  }
5026  return grad_out;
5027 }
5028 
5029 
5030 
5031 template <int dim, typename Number, bool is_face>
5032 inline
5035 ::get_hessian (const unsigned int q_point) const
5036 {
5037  return BaseClass::get_hessian(q_point)[0];
5038 }
5039 
5040 
5041 
5042 template <int dim, typename Number, bool is_face>
5043 inline
5046 ::get_hessian_diagonal (const unsigned int q_point) const
5047 {
5048  return BaseClass::get_hessian_diagonal(q_point)[0];
5049 }
5050 
5051 
5052 
5053 template <int dim, typename Number, bool is_face>
5054 inline
5057 ::get_laplacian (const unsigned int q_point) const
5058 {
5059  return BaseClass::get_laplacian(q_point)[0];
5060 }
5061 
5062 
5063 
5064 template <int dim, typename Number, bool is_face>
5065 inline
5066 void DEAL_II_ALWAYS_INLINE
5069  const unsigned int dof)
5070 {
5071 #ifdef DEBUG
5072  this->dof_values_initialized = true;
5073  AssertIndexRange (dof, this->data->dofs_per_component_on_cell);
5074 #endif
5075  this->values_dofs[0][dof] = val_in;
5076 }
5077 
5078 
5079 
5080 template <int dim, typename Number, bool is_face>
5081 inline
5082 void DEAL_II_ALWAYS_INLINE
5085  const unsigned int q_index)
5086 {
5087 #ifdef DEBUG
5089  AssertIndexRange (q_index, this->n_quadrature_points);
5090  Assert (this->J_value != nullptr, ExcNotInitialized());
5091  this->values_quad_submitted = true;
5092 #endif
5093  if (this->cell_type <= internal::MatrixFreeFunctions::affine)
5094  {
5095  const VectorizedArray<Number> JxW = this->J_value[0] * this->quadrature_weights[q_index];
5096  this->values_quad[0][q_index] = val_in * JxW;
5097  }
5098  else //if (this->cell_type < internal::MatrixFreeFunctions::general)
5099  {
5100  this->values_quad[0][q_index] = val_in * this->J_value[q_index];
5101  }
5102 }
5103 
5104 
5105 
5106 template <int dim, typename Number, bool is_face>
5107 inline DEAL_II_ALWAYS_INLINE
5108 void
5110 ::submit_value (const Tensor<1,1,VectorizedArray<Number> > val_in,
5111  const unsigned int q_point)
5112 {
5113  submit_value(val_in[0], q_point);
5114 }
5115 
5116 
5117 
5118 template <int dim, typename Number, bool is_face>
5119 inline DEAL_II_ALWAYS_INLINE
5120 void
5123  const unsigned int q_point)
5124 {
5126  grad[0] = grad_in;
5127  BaseClass::submit_normal_derivative(grad, q_point);
5128 }
5129 
5130 
5131 
5132 template <int dim, typename Number, bool is_face>
5133 inline DEAL_II_ALWAYS_INLINE
5134 void
5136 ::submit_gradient (const Tensor<1,dim,VectorizedArray<Number> > grad_in,
5137  const unsigned int q_index)
5138 {
5139 #ifdef DEBUG
5141  AssertIndexRange (q_index, this->n_quadrature_points);
5142  this->gradients_quad_submitted = true;
5143  Assert (this->J_value != nullptr, ExcNotInitialized());
5144  Assert (this->jacobian != nullptr, ExcNotInitialized());
5145 #endif
5146 
5147  if (!is_face && this->cell_type == internal::MatrixFreeFunctions::cartesian)
5148  {
5149  const VectorizedArray<Number> JxW = this->J_value[0] *
5150  this->quadrature_weights[q_index];
5151  for (unsigned int d=0; d<dim; ++d)
5152  this->gradients_quad[0][d][q_index] = (grad_in[d] *
5153  this->jacobian[0][d][d] *
5154  JxW);
5155  }
5156  // general/affine cell type
5157  else
5158  {
5160  this->cell_type > internal::MatrixFreeFunctions::affine ?
5161  this->jacobian[q_index] : this->jacobian[0];
5162  const VectorizedArray<Number> JxW =
5163  this->cell_type > internal::MatrixFreeFunctions::affine ?
5164  this->J_value[q_index] : this->J_value[0] * this->quadrature_weights[q_index];
5165  for (unsigned int d=0; d<dim; ++d)
5166  {
5167  VectorizedArray<Number> new_val = jac[0][d] * grad_in[0];
5168  for (unsigned int e=1; e<dim; ++e)
5169  new_val += jac[e][d] * grad_in[e];
5170  this->gradients_quad[0][d][q_index] = new_val * JxW;
5171  }
5172  }
5173 }
5174 
5175 
5176 
5177 template <int dim, typename Number, bool is_face>
5178 inline
5181 ::integrate_value () const
5182 {
5183  return BaseClass::integrate_value()[0];
5184 }
5185 
5186 
5187 
5188 
5189 /*----------------- FEEvaluationAccess vector-valued ------------------------*/
5190 
5191 
5192 template <int dim, typename Number, bool is_face>
5193 inline
5196  const unsigned int dof_no,
5197  const unsigned int first_selected_component,
5198  const unsigned int quad_no_in,
5199  const unsigned int fe_degree,
5200  const unsigned int n_q_points,
5201  const bool is_interior_face)
5202  :
5203  FEEvaluationBase <dim,dim,Number,is_face>
5204  (data_in, dof_no, first_selected_component, quad_no_in, fe_degree, n_q_points,
5205  is_interior_face)
5206 {}
5207 
5208 
5209 
5210 template <int dim, typename Number, bool is_face>
5211 template <int n_components_other>
5212 inline
5214 ::FEEvaluationAccess (const Mapping<dim> &mapping,
5215  const FiniteElement<dim> &fe,
5216  const Quadrature<1> &quadrature,
5217  const UpdateFlags update_flags,
5218  const unsigned int first_selected_component,
5220  :
5221  FEEvaluationBase <dim,dim,Number,is_face> (mapping, fe, quadrature, update_flags,
5222  first_selected_component, other)
5223 {}
5224 
5225 
5226 
5227 template <int dim, typename Number, bool is_face>
5228 inline
5231  :
5232  FEEvaluationBase <dim,dim,Number,is_face>(other)
5233 {}
5234 
5235 
5236 
5237 template <int dim, typename Number, bool is_face>
5238 inline
5242 {
5244  return *this;
5245 }
5246 
5247 
5248 
5249 template <int dim, typename Number, bool is_face>
5250 inline DEAL_II_ALWAYS_INLINE
5253 ::get_gradient (const unsigned int q_point) const
5254 {
5255  return BaseClass::get_gradient (q_point);
5256 }
5257 
5258 
5259 
5260 template <int dim, typename Number, bool is_face>
5261 inline DEAL_II_ALWAYS_INLINE
5264 ::get_divergence (const unsigned int q_point) const
5265 {
5266  Assert (this->gradients_quad_initialized==true,
5268  AssertIndexRange (q_point, this->n_quadrature_points);
5269  Assert (this->jacobian != nullptr, ExcNotInitialized());
5270 
5271  VectorizedArray<Number> divergence;
5272 
5273  // Cartesian cell
5274  if (!is_face && this->cell_type == internal::MatrixFreeFunctions::cartesian)
5275  {
5276  divergence = (this->gradients_quad[0][0][q_point] *
5277  this->jacobian[0][0][0]);
5278  for (unsigned int d=1; d<dim; ++d)
5279  divergence += (this->gradients_quad[d][d][q_point] *
5280  this->jacobian[0][d][d]);
5281  }
5282  // cell with general/constant Jacobian
5283  else
5284  {
5286  this->cell_type == internal::MatrixFreeFunctions::general ?
5287  this->jacobian[q_point] : this->jacobian[0];
5288  divergence = (jac[0][0] * this->gradients_quad[0][0][q_point]);
5289  for (unsigned int e=1; e<dim; ++e)
5290  divergence += (jac[0][e] * this->gradients_quad[0][e][q_point]);
5291  for (unsigned int d=1; d<dim; ++d)
5292  for (unsigned int e=0; e<dim; ++e)
5293  divergence += (jac[d][e] * this->gradients_quad[d][e][q_point]);
5294  }
5295  return divergence;
5296 }
5297 
5298 
5299 
5300 template <int dim, typename Number, bool is_face>
5301 inline DEAL_II_ALWAYS_INLINE
5304 ::get_symmetric_gradient (const unsigned int q_point) const
5305 {
5306  // copy from generic function into dim-specialization function
5307  const Tensor<2,dim,VectorizedArray<Number> > grad = get_gradient(q_point);
5308  VectorizedArray<Number> symmetrized [(dim*dim+dim)/2];
5309  VectorizedArray<Number> half = make_vectorized_array<Number> (0.5);
5310  for (unsigned int d=0; d<dim; ++d)
5311  symmetrized[d] = grad[d][d];
5312  switch (dim)
5313  {
5314  case 1:
5315  break;
5316  case 2:
5317  symmetrized[2] = grad[0][1] + grad[1][0];
5318  symmetrized[2] *= half;
5319  break;
5320  case 3:
5321  symmetrized[3] = grad[0][1] + grad[1][0];
5322  symmetrized[3] *= half;
5323  symmetrized[4] = grad[0][2] + grad[2][0];
5324  symmetrized[4] *= half;
5325  symmetrized[5] = grad[1][2] + grad[2][1];
5326  symmetrized[5] *= half;
5327  break;
5328  default:
5329  Assert (false, ExcNotImplemented());
5330  }
5331  return SymmetricTensor<2,dim,VectorizedArray<Number> > (symmetrized);
5332 }
5333 
5334 
5335 
5336 template <int dim, typename Number, bool is_face>
5337 inline DEAL_II_ALWAYS_INLINE
5340 ::get_curl (const unsigned int q_point) const
5341 {
5342  // copy from generic function into dim-specialization function
5343  const Tensor<2,dim,VectorizedArray<Number> > grad = get_gradient(q_point);
5345  switch (dim)
5346  {
5347  case 1:
5348  Assert (false,
5349  ExcMessage("Computing the curl in 1d is not a useful operation"));
5350  break;
5351  case 2:
5352  curl[0] = grad[1][0] - grad[0][1];
5353  break;
5354  case 3:
5355  curl[0] = grad[2][1] - grad[1][2];
5356  curl[1] = grad[0][2] - grad[2][0];
5357  curl[2] = grad[1][0] - grad[0][1];
5358  break;
5359  default:
5360  Assert (false, ExcNotImplemented());
5361  }
5362  return curl;
5363 }
5364 
5365 
5366 
5367 template <int dim, typename Number, bool is_face>
5368 inline DEAL_II_ALWAYS_INLINE
5371 ::get_hessian_diagonal (const unsigned int q_point) const
5372 {
5373  return BaseClass::get_hessian_diagonal (q_point);
5374 }
5375 
5376 
5377 
5378 template <int dim, typename Number, bool is_face>
5379 inline DEAL_II_ALWAYS_INLINE
5382 ::get_hessian (const unsigned int q_point) const
5383 {
5384  Assert (this->hessians_quad_initialized==true,
5386  AssertIndexRange (q_point, this->n_quadrature_points);
5387  return BaseClass::get_hessian(q_point);
5388 }
5389 
5390 
5391 
5392 template <int dim, typename Number, bool is_face>
5393 inline DEAL_II_ALWAYS_INLINE
5394 void
5396 ::submit_gradient (const Tensor<2,dim,VectorizedArray<Number> > grad_in,
5397  const unsigned int q_point)
5398 {
5399  BaseClass::submit_gradient (grad_in, q_point);
5400 }
5401 
5402 
5403 
5404 template <int dim, typename Number, bool is_face>
5405 inline DEAL_II_ALWAYS_INLINE
5406 void
5409  grad_in,
5410  const unsigned int q_point)
5411 {
5412  BaseClass::submit_gradient(grad_in, q_point);
5413 }
5414 
5415 
5416 
5417 template <int dim, typename Number, bool is_face>
5418 inline DEAL_II_ALWAYS_INLINE
5419 void
5422  const unsigned int q_point)
5423 {
5424 #ifdef DEBUG
5426  AssertIndexRange (q_point, this->n_quadrature_points);
5427  this->gradients_quad_submitted = true;
5428  Assert (this->J_value != nullptr, ExcNotInitialized());
5429  Assert (this->jacobian != nullptr, ExcNotInitialized());
5430 #endif
5431 
5432  if (!is_face && this->cell_type == internal::MatrixFreeFunctions::cartesian)
5433  {
5434  const VectorizedArray<Number> fac = this->J_value[0] *
5435  this->quadrature_weights[q_point] * div_in;
5436  for (unsigned int d=0; d<dim; ++d)
5437  {
5438  this->gradients_quad[d][d][q_point] = (fac *
5439  this->jacobian[0][d][d]);
5440  for (unsigned int e=d+1; e<dim; ++e)
5441  {
5442  this->gradients_quad[d][e][q_point] = VectorizedArray<Number>();
5443  this->gradients_quad[e][d][q_point] = VectorizedArray<Number>();
5444  }
5445  }
5446  }
5447  else
5448  {
5450  this->cell_type == internal::MatrixFreeFunctions::general ?
5451  this->jacobian[q_point] : this->jacobian[0];
5452  const VectorizedArray<Number> fac =
5453  (this->cell_type == internal::MatrixFreeFunctions::general ?
5454  this->J_value[q_point] : this->J_value[0] *
5455  this->quadrature_weights[q_point]) * div_in;
5456  for (unsigned int d=0; d<dim; ++d)
5457  {
5458  for (unsigned int e=0; e<dim; ++e)
5459  this->gradients_quad[d][e][q_point] = jac[d][e] * fac;
5460  }
5461  }
5462 }
5463 
5464 
5465 
5466 template <int dim, typename Number, bool is_face>
5467 inline DEAL_II_ALWAYS_INLINE
5468 void
5471  sym_grad,
5472  const unsigned int q_point)
5473 {
5474  // could have used base class operator, but that involves some overhead
5475  // which is inefficient. it is nice to have the symmetric tensor because
5476  // that saves some operations
5477 #ifdef DEBUG
5479  AssertIndexRange (q_point, this->n_quadrature_points);
5480  this->gradients_quad_submitted = true;
5481  Assert (this->J_value != nullptr, ExcNotInitialized());
5482  Assert (this->jacobian != nullptr, ExcNotInitialized());
5483 #endif
5484 
5485  if (!is_face && this->cell_type == internal::MatrixFreeFunctions::cartesian)
5486  {
5487  const VectorizedArray<Number> JxW = this->J_value[0] * this->quadrature_weights[q_point];
5488  for (unsigned int d=0; d<dim; ++d)
5489  this->gradients_quad[d][d][q_point] = (sym_grad.access_raw_entry(d) *
5490  JxW *
5491  this->jacobian[0][d][d]);
5492  for (unsigned int e=0, counter=dim; e<dim; ++e)
5493  for (unsigned int d=e+1; d<dim; ++d, ++counter)
5494  {
5495  const VectorizedArray<Number> value = sym_grad.access_raw_entry(counter) * JxW;
5496  this->gradients_quad[e][d][q_point] = (value *
5497  this->jacobian[0][d][d]);
5498  this->gradients_quad[d][e][q_point] = (value *
5499  this->jacobian[0][e][e]);
5500  }
5501  }
5502  // general/affine cell type
5503  else
5504  {
5505  const VectorizedArray<Number> JxW =
5506  this->cell_type == internal::MatrixFreeFunctions::general ?
5507  this->J_value[q_point] : this->J_value[0] * this->quadrature_weights[q_point];
5509  this->cell_type == internal::MatrixFreeFunctions::general ?
5510  this->jacobian[q_point] : this->jacobian[0];
5511  VectorizedArray<Number> weighted [dim][dim];
5512  for (unsigned int i=0; i<dim; ++i)
5513  weighted[i][i] = sym_grad.access_raw_entry(i) * JxW;
5514  for (unsigned int i=0, counter=dim; i<dim; ++i)
5515  for (unsigned int j=i+1; j<dim; ++j, ++counter)
5516  {
5517  const VectorizedArray<Number> value = sym_grad.access_raw_entry(counter) * JxW;
5518  weighted[i][j] = value;
5519  weighted[j][i] = value;
5520  }
5521  for (unsigned int comp=0; comp<dim; ++comp)
5522  for (unsigned int d=0; d<dim; ++d)
5523  {
5524  VectorizedArray<Number> new_val = jac[0][d] * weighted[comp][0];
5525  for (unsigned int e=1; e<dim; ++e)
5526  new_val += jac[e][d] * weighted[comp][e];
5527  this->gradients_quad[comp][d][q_point] = new_val;
5528  }
5529  }
5530 }
5531 
5532 
5533 
5534 template <int dim, typename Number, bool is_face>
5535 inline DEAL_II_ALWAYS_INLINE
5536 void
5538 ::submit_curl (const Tensor<1,dim==2?1:dim,VectorizedArray<Number> > curl,
5539  const unsigned int q_point)
5540 {
5542  switch (dim)
5543  {
5544  case 1:
5545  Assert (false,
5546  ExcMessage("Testing by the curl in 1d is not a useful operation"));
5547  break;
5548  case 2:
5549  grad[1][0] = curl[0];
5550  grad[0][1] = -curl[0];
5551  break;
5552  case 3:
5553  grad[2][1] = curl[0];
5554  grad[1][2] = -curl[0];
5555  grad[0][2] = curl[1];
5556  grad[2][0] = -curl[1];
5557  grad[1][0] = curl[2];
5558  grad[0][1] = -curl[2];
5559  break;
5560  default:
5561  Assert (false, ExcNotImplemented());
5562  }
5563  submit_gradient (grad, q_point);
5564 }
5565 
5566 
5567 /*-------------------- FEEvaluationAccess scalar for 1d ----------------------------*/
5568 
5569 
5570 template <typename Number, bool is_face>
5571 inline
5574  const unsigned int dof_no,
5575  const unsigned int first_selected_component,
5576  const unsigned int quad_no_in,
5577  const unsigned int fe_degree,
5578  const unsigned int n_q_points,
5579  const bool is_interior_face)
5580  :
5581  FEEvaluationBase <1,1,Number,is_face>
5582  (data_in, dof_no, first_selected_component, quad_no_in, fe_degree, n_q_points,
5583  is_interior_face)
5584 {}
5585 
5586 
5587 
5588 template <typename Number, bool is_face>
5589 template <int n_components_other>
5590 inline
5592 ::FEEvaluationAccess (const Mapping<1> &mapping,
5593  const FiniteElement<1> &fe,
5594  const Quadrature<1> &quadrature,
5595  const UpdateFlags update_flags,
5596  const unsigned int first_selected_component,
5598  :
5599  FEEvaluationBase <1,1,Number,is_face> (mapping, fe, quadrature, update_flags,
5600  first_selected_component, other)
5601 {}
5602 
5603 
5604 
5605 template <typename Number, bool is_face>
5606 inline
5609  :
5610  FEEvaluationBase <1,1,Number,is_face>(other)
5611 {}
5612 
5613 
5614 
5615 template <typename Number, bool is_face>
5616 inline
5620 {
5622  return *this;
5623 }
5624 
5625 
5626 
5627 template <typename Number, bool is_face>
5628 inline DEAL_II_ALWAYS_INLINE
5631 ::get_dof_value (const unsigned int dof) const
5632 {
5633  AssertIndexRange (dof, this->data->dofs_per_component_on_cell);
5634  return this->values_dofs[0][dof];
5635 }
5636 
5637 
5638 
5639 template <typename Number, bool is_face>
5640 inline DEAL_II_ALWAYS_INLINE
5643 ::get_value (const unsigned int q_point) const
5644 {
5645  Assert (this->values_quad_initialized==true,
5647  AssertIndexRange (q_point, this->n_quadrature_points);
5648  return this->values_quad[0][q_point];
5649 }
5650 
5651 
5652 
5653 template <typename Number, bool is_face>
5654 inline DEAL_II_ALWAYS_INLINE
5657 ::get_gradient (const unsigned int q_point) const
5658 {
5659  // could use the base class gradient, but that involves too many inefficient
5660  // initialization operations on tensors
5661 
5662  Assert (this->gradients_quad_initialized==true,
5664  AssertIndexRange (q_point, this->n_quadrature_points);
5665 
5666  const Tensor<2,1,VectorizedArray<Number> > &jac =
5667  this->cell_type == internal::MatrixFreeFunctions::general ?
5668  this->jacobian[q_point] : this->jacobian[0];
5669 
5671  grad_out[0] = jac[0][0] * this->gradients_quad[0][0][q_point];
5672 
5673  return grad_out;
5674 }
5675 
5676 
5677 
5678 template <typename Number, bool is_face>
5679 inline DEAL_II_ALWAYS_INLINE
5682 ::get_normal_derivative (const unsigned int q_point) const
5683 {
5684  return BaseClass::get_normal_derivative(q_point)[0];
5685 }
5686 
5687 
5688 
5689 template <typename Number, bool is_face>
5690 inline DEAL_II_ALWAYS_INLINE
5693 ::get_hessian (const unsigned int q_point) const
5694 {
5695  return BaseClass::get_hessian(q_point)[0];
5696 }
5697 
5698 
5699 
5700 template <typename Number, bool is_face>
5701 inline DEAL_II_ALWAYS_INLINE
5704 ::get_hessian_diagonal (const unsigned int q_point) const
5705 {
5706  return BaseClass::get_hessian_diagonal(q_point)[0];
5707 }
5708 
5709 
5710 
5711 template <typename Number, bool is_face>
5712 inline DEAL_II_ALWAYS_INLINE
5715 ::get_laplacian (const unsigned int q_point) const
5716 {
5717  return BaseClass::get_laplacian(q_point)[0];
5718 }
5719 
5720 
5721 
5722 template <typename Number, bool is_face>
5723 inline DEAL_II_ALWAYS_INLINE
5724 void DEAL_II_ALWAYS_INLINE
5727  const unsigned int dof)
5728 {
5729 #ifdef DEBUG
5730  this->dof_values_initialized = true;
5731  AssertIndexRange (dof, this->data->dofs_per_component_on_cell);
5732 #endif
5733  this->values_dofs[0][dof] = val_in;
5734 }
5735 
5736 
5737 
5738 template <typename Number, bool is_face>
5739 inline DEAL_II_ALWAYS_INLINE
5740 void
5743  const unsigned int q_point)
5744 {
5745 #ifdef DEBUG
5747  AssertIndexRange (q_point, this->n_quadrature_points);
5748  this->values_quad_submitted = true;
5749 #endif
5750  if (this->cell_type == internal::MatrixFreeFunctions::general)
5751  {
5752  const VectorizedArray<Number> JxW = this->J_value[q_point];
5753  this->values_quad[0][q_point] = val_in * JxW;
5754  }
5755  else //if (this->cell_type == internal::MatrixFreeFunctions::general)
5756  {
5757  const VectorizedArray<Number> JxW = this->J_value[0] * this->quadrature_weights[q_point];
5758  this->values_quad[0][q_point] = val_in * JxW;
5759  }
5760 }
5761 
5762 
5763 
5764 template <typename Number, bool is_face>
5765 inline DEAL_II_ALWAYS_INLINE
5766 void
5768 ::submit_value (const Tensor<1,1,VectorizedArray<Number> > val_in,
5769  const unsigned int q_point)
5770 {
5771  submit_value(val_in[0], q_point);
5772 }
5773 
5774 
5775 
5776 template <typename Number, bool is_face>
5777 inline DEAL_II_ALWAYS_INLINE
5778 void
5780 ::submit_gradient (const Tensor<1,1,VectorizedArray<Number> > grad_in,
5781  const unsigned int q_point)
5782 {
5783  submit_gradient(grad_in[0], q_point);
5784 }
5785 
5786 
5787 
5788 template <typename Number, bool is_face>
5789 inline DEAL_II_ALWAYS_INLINE
5790 void
5793  const unsigned int q_point)
5794 {
5795 #ifdef DEBUG
5797  AssertIndexRange (q_point, this->n_quadrature_points);
5798  this->gradients_quad_submitted = true;
5799 #endif
5800 
5801  const Tensor<2,1,VectorizedArray<Number> > &jac =
5802  this->cell_type == internal::MatrixFreeFunctions::general ?
5803  this->jacobian[q_point] : this->jacobian[0];
5804  const VectorizedArray<Number> JxW =
5805  this->cell_type == internal::MatrixFreeFunctions::general ?
5806  this->J_value[q_point] : this->J_value[0] * this->quadrature_weights[q_point];
5807 
5808  this->gradients_quad[0][0][q_point] = jac[0][0] * grad_in * JxW;
5809 }
5810 
5811 
5812 
5813 template <typename Number, bool is_face>
5814 inline DEAL_II_ALWAYS_INLINE
5815 void
5818  const unsigned int q_point)
5819 {
5821  grad[0] = grad_in;
5822  BaseClass::submit_normal_derivative(grad, q_point);
5823 }
5824 
5825 
5826 
5827 template <typename Number, bool is_face>
5828 inline DEAL_II_ALWAYS_INLINE
5829 void
5832  const unsigned int q_point)
5833 {
5834  BaseClass::submit_normal_derivative(grad_in, q_point);
5835 }
5836 
5837 
5838 
5839 template <typename Number, bool is_face>
5840 inline
5843 ::integrate_value () const
5844 {
5845  return BaseClass::integrate_value()[0];
5846 }
5847 
5848 
5849 
5850 
5851 /*-------------------------- FEEvaluation -----------------------------------*/
5852 
5853 
5854 template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
5855  typename Number>
5856 inline
5858 ::FEEvaluation (const MatrixFree<dim,Number> &data_in,
5859  const unsigned int fe_no,
5860  const unsigned int quad_no,
5861  const unsigned int first_selected_component)
5862  :
5863  BaseClass (data_in, fe_no, first_selected_component, quad_no, fe_degree, static_n_q_points),
5864  dofs_per_component (this->data->dofs_per_component_on_cell),
5865  dofs_per_cell (this->data->dofs_per_component_on_cell *n_components_),
5866  n_q_points (this->data->n_q_points)
5867 {
5868  check_template_arguments(fe_no, 0);
5869 }
5870 
5871 
5872 
5873 template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
5874  typename Number>
5875 inline
5877 ::FEEvaluation (const Mapping<dim> &mapping,
5878  const FiniteElement<dim> &fe,
5879  const Quadrature<1> &quadrature,
5880  const UpdateFlags update_flags,
5881  const unsigned int first_selected_component)
5882  :
5883  BaseClass (mapping, fe, quadrature, update_flags,
5884  first_selected_component,
5885  static_cast<FEEvaluationBase<dim,1,Number,false>*>(nullptr)),
5886  dofs_per_component (this->data->dofs_per_component_on_cell),
5887  dofs_per_cell (this->data->dofs_per_component_on_cell *n_components_),
5888  n_q_points (this->data->n_q_points)
5889 {
5890  check_template_arguments(numbers::invalid_unsigned_int, 0);
5891 }
5892 
5893 
5894 
5895 template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
5896  typename Number>
5897 inline
5900  const Quadrature<1> &quadrature,
5901  const UpdateFlags update_flags,
5902  const unsigned int first_selected_component)
5903  :
5904  BaseClass (StaticMappingQ1<dim>::mapping, fe, quadrature, update_flags,
5905  first_selected_component,
5906  static_cast<FEEvaluationBase<dim,1,Number,false>*>(nullptr)),
5907  dofs_per_component (this->data->dofs_per_component_on_cell),
5908  dofs_per_cell (this->data->dofs_per_component_on_cell *n_components_),
5909  n_q_points (this->data->n_q_points)
5910 {
5911  check_template_arguments(numbers::invalid_unsigned_int, 0);
5912 }
5913 
5914 
5915 
5916 template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
5917  typename Number>
5918 template <int n_components_other>
5919 inline
5923  const unsigned int first_selected_component)
5924  :
5925  BaseClass (other.mapped_geometry->get_fe_values().get_mapping(),
5926  fe, other.mapped_geometry->get_quadrature(),
5927  other.mapped_geometry->get_fe_values().get_update_flags(),
5928  first_selected_component, &other),
5929  dofs_per_component (this->data->dofs_per_component_on_cell),
5930  dofs_per_cell (this->data->dofs_per_component_on_cell *n_components_),
5931  n_q_points (this->data->n_q_points)
5932 {
5933  check_template_arguments(numbers::invalid_unsigned_int, 0);
5934 }
5935 
5936 
5937 
5938 template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
5939  typename Number>
5940 inline
5942 ::FEEvaluation (const FEEvaluation &other)
5943  :
5944  BaseClass (other),
5945  dofs_per_component (this->data->dofs_per_component_on_cell),
5946  dofs_per_cell (this->data->dofs_per_component_on_cell *n_components_),
5947  n_q_points (this->data->n_q_points)
5948 {
5949  check_template_arguments(numbers::invalid_unsigned_int, 0);
5950 }
5951 
5952 
5953 
5954 template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
5955  typename Number>
5956 inline
5959 ::operator= (const FEEvaluation &other)
5960 {
5961  BaseClass::operator=(other);
5962  check_template_arguments(numbers::invalid_unsigned_int, 0);
5963  return *this;
5964 }
5965 
5966 
5967 
5968 template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
5969  typename Number>
5970 inline
5971 void
5973 ::check_template_arguments(const unsigned int dof_no,
5974  const unsigned int first_selected_component)
5975 {
5976  (void)dof_no;
5977  (void)first_selected_component;
5978 
5979 #ifdef DEBUG
5980  // print error message when the dimensions do not match. Propose a possible
5981  // fix
5982  if ((static_cast<unsigned int>(fe_degree) != numbers::invalid_unsigned_int &&
5983  static_cast<unsigned int>(fe_degree) != this->data->fe_degree)
5984  ||
5985  n_q_points != this->n_quadrature_points)
5986  {
5987  std::string message =
5988  "-------------------------------------------------------\n";
5989  message += "Illegal arguments in constructor/wrong template arguments!\n";
5990  message += " Called --> FEEvaluation<dim,";
5991  message += Utilities::int_to_string(fe_degree) + ",";
5992  message += Utilities::int_to_string(n_q_points_1d);
5993  message += "," + Utilities::int_to_string(n_components);
5994  message += ",Number>(data";
5995  if (first_selected_component != numbers::invalid_unsigned_int)
5996  {
5997  message += ", " + Utilities::int_to_string(dof_no) + ", ";
5998  message += Utilities::int_to_string(this->quad_no) + ", ";
5999  message += Utilities::int_to_string(first_selected_component);
6000  }
6001  message += ")\n";
6002 
6003  // check whether some other vector component has the correct number of
6004  // points
6005  unsigned int proposed_dof_comp = numbers::invalid_unsigned_int,
6006  proposed_fe_comp = numbers::invalid_unsigned_int,
6007  proposed_quad_comp = numbers::invalid_unsigned_int;
6008  if (dof_no != numbers::invalid_unsigned_int)
6009  {
6010  if (static_cast<unsigned int>(fe_degree) == this->data->fe_degree)
6011  {
6012  proposed_dof_comp = dof_no;
6013  proposed_fe_comp = first_selected_component;
6014  }
6015  else
6016  for (unsigned int no=0; no<this->matrix_info->n_components(); ++no)
6017  for (unsigned int nf=0; nf<this->matrix_info->n_base_elements(no); ++nf)
6018  if (this->matrix_info->get_shape_info(no,0,nf,this->active_fe_index,0).fe_degree
6019  == static_cast<unsigned int>(fe_degree))
6020  {
6021  proposed_dof_comp = no;
6022  proposed_fe_comp = nf;
6023  break;
6024  }
6025  if (n_q_points ==
6026  this->mapping_data->descriptor[this->active_quad_index].n_q_points)
6027  proposed_quad_comp = this->quad_no;
6028  else
6029  for (unsigned int no=0; no<this->matrix_info->get_mapping_info().cell_data.size(); ++no)
6030  if (this->matrix_info->get_mapping_info().cell_data[no].descriptor[this->active_quad_index].n_q_points
6031  == n_q_points)
6032  {
6033  proposed_quad_comp = no;
6034  break;
6035  }
6036  }
6037  if (proposed_dof_comp != numbers::invalid_unsigned_int &&
6038  proposed_quad_comp != numbers::invalid_unsigned_int)
6039  {
6040  if (proposed_dof_comp != first_selected_component)
6041  message += "Wrong vector component selection:\n";
6042  else
6043  message += "Wrong quadrature formula selection:\n";
6044  message += " Did you mean FEEvaluation<dim,";
6045  message += Utilities::int_to_string(fe_degree) + ",";
6046  message += Utilities::int_to_string(n_q_points_1d);
6047  message += "," + Utilities::int_to_string(n_components);
6048  message += ",Number>(data";
6049  if (dof_no != numbers::invalid_unsigned_int)
6050  {
6051  message += ", " + Utilities::int_to_string(proposed_dof_comp) + ", ";
6052  message += Utilities::int_to_string(proposed_quad_comp) + ", ";
6053  message += Utilities::int_to_string(proposed_fe_comp);
6054  }
6055  message += ")?\n";
6056  std::string correct_pos;
6057  if (proposed_dof_comp != dof_no)
6058  correct_pos = " ^ ";
6059  else
6060  correct_pos = " ";
6061  if (proposed_quad_comp != this->quad_no)
6062  correct_pos += " ^ ";
6063  else
6064  correct_pos += " ";
6065  if (proposed_fe_comp != first_selected_component)
6066  correct_pos += " ^\n";
6067  else
6068  correct_pos += " \n";
6069  message += " " + correct_pos;
6070  }
6071  // ok, did not find the numbers specified by the template arguments in
6072  // the given list. Suggest correct template arguments
6073  const unsigned int proposed_n_q_points_1d = static_cast<unsigned int>(std::pow(1.001*this->n_quadrature_points,1./dim));
6074  message += "Wrong template arguments:\n";
6075  message += " Did you mean FEEvaluation<dim,";
6076  message += Utilities::int_to_string(this->data->fe_degree) + ",";
6077  message += Utilities::int_to_string(proposed_n_q_points_1d);
6078  message += "," + Utilities::int_to_string(n_components);
6079  message += ",Number>(data";
6080  if (dof_no != numbers::invalid_unsigned_int)
6081  {
6082  message += ", " + Utilities::int_to_string(dof_no) + ", ";
6083  message += Utilities::int_to_string(this->quad_no);
6084  message += ", " + Utilities::int_to_string(first_selected_component);
6085  }
6086  message += ")?\n";
6087  std::string correct_pos;
6088  if (this->data->fe_degree != static_cast<unsigned int>(fe_degree))
6089  correct_pos = " ^";
6090  else
6091  correct_pos = " ";
6092  if (proposed_n_q_points_1d != n_q_points_1d)
6093  correct_pos += " ^\n";
6094  else
6095  correct_pos += " \n";
6096  message += " " + correct_pos;
6097 
6098  Assert (static_cast<unsigned int>(fe_degree) == this->data->fe_degree &&
6099  n_q_points == this->n_quadrature_points,
6100  ExcMessage(message));
6101  }
6102  if (dof_no != numbers::invalid_unsigned_int)
6103  AssertDimension (n_q_points,
6104  this->mapping_data->descriptor[this->active_quad_index].n_q_points);
6105 #endif
6106 }
6107 
6108 
6109 
6110 template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
6111  typename Number>
6112 inline
6113 void
6115 ::reinit (const unsigned int cell_index)
6116 {
6117  Assert (this->mapped_geometry == nullptr,
6118  ExcMessage("FEEvaluation was initialized without a matrix-free object."
6119  " Integer indexing is not possible"));
6120  if (this->mapped_geometry != nullptr)
6121  return;
6122 
6123  Assert (this->dof_info != nullptr, ExcNotInitialized());
6124  Assert (this->mapping_data != nullptr, ExcNotInitialized());
6125  this->cell = cell_index;
6126  this->cell_type = this->matrix_info->get_mapping_info().get_cell_type(cell_index);
6127 
6128  const unsigned int offsets = this->mapping_data->data_index_offsets[cell_index];
6129  this->jacobian = &this->mapping_data->jacobians[0][offsets];
6130  this->J_value = &this->mapping_data->JxW_values[offsets];
6131 
6132 #ifdef DEBUG
6133  this->dof_values_initialized = false;
6134  this->values_quad_initialized = false;
6135  this->gradients_quad_initialized = false;
6136  this->hessians_quad_initialized = false;
6137 #endif
6138 }
6139 
6140 
6141 
6142 template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
6143  typename Number>
6144 template <typename DoFHandlerType, bool level_dof_access>
6145 inline
6146 void
6149 {
6150  Assert(this->matrix_info == nullptr,
6151  ExcMessage("Cannot use initialization from cell iterator if "
6152  "initialized from MatrixFree object. Use variant for "
6153  "on the fly computation with arguments as for FEValues "
6154  "instead"));
6155  Assert(this->mapped_geometry.get() != nullptr, ExcNotInitialized());
6156  this->mapped_geometry->reinit(static_cast<typename Triangulation<dim>::cell_iterator>(cell));
6157  this->local_dof_indices.resize(cell->get_fe().dofs_per_cell);
6158  if (level_dof_access)
6159  cell->get_mg_dof_indices(this->local_dof_indices);
6160  else
6161  cell->get_dof_indices(this->local_dof_indices);
6162 }
6163 
6164 
6165 
6166 template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
6167  typename Number>
6168 inline
6169 void
6171 ::reinit (const typename Triangulation<dim>::cell_iterator &cell)
6172 {
6173  Assert(this->matrix_info == 0,
6174  ExcMessage("Cannot use initialization from cell iterator if "
6175  "initialized from MatrixFree object. Use variant for "
6176  "on the fly computation with arguments as for FEValues "
6177  "instead"));
6178  Assert(this->mapped_geometry.get() != 0, ExcNotInitialized());
6179  this->mapped_geometry->reinit(cell);
6180 }
6181 
6182 
6183 
6184 template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
6185  typename Number>
6186 inline
6189 ::quadrature_point (const unsigned int q) const
6190 {
6191  if (this->matrix_info == nullptr)
6192  {
6193  Assert ((this->mapped_geometry->get_fe_values().get_update_flags() |
6195  ExcNotInitialized());
6196  }
6197  else
6198  {
6199  Assert(this->mapping_data->quadrature_point_offsets.empty() == false,
6200  ExcNotInitialized());
6201  }
6202 
6203  AssertIndexRange (q, n_q_points);
6204 
6205  const unsigned int n_q_points_1d_actual =
6206  fe_degree == -1 ? this->data->n_q_points_1d : n_q_points_1d;
6207 
6208  // Cartesian mesh: not all quadrature points are stored, only the
6209  // diagonal. Hence, need to find the tensor product index and retrieve the
6210  // value from that
6211  const Point<dim,VectorizedArray<Number> > *quadrature_points =
6212  &this->mapping_data->quadrature_points[this->mapping_data->quadrature_point_offsets[this->cell]];
6213  if (this->cell_type == internal::MatrixFreeFunctions::cartesian)
6214  {
6216  switch (dim)
6217  {
6218  case 1:
6219  return quadrature_points[q];
6220  case 2:
6221  point[0] = quadrature_points[q%n_q_points_1d_actual][0];
6222  point[1] = quadrature_points[q/n_q_points_1d_actual][1];
6223  return point;
6224  case 3:
6225  point[0] = quadrature_points[q%n_q_points_1d_actual][0];
6226  point[1] = quadrature_points[(q/n_q_points_1d_actual)%n_q_points_1d_actual][1];
6227  point[2] = quadrature_points[q/(n_q_points_1d_actual*n_q_points_1d_actual)][2];
6228  return point;
6229  default:
6230  Assert (false, ExcNotImplemented());
6231  return point;
6232  }
6233  }
6234  // all other cases: just return the respective data as it is fully stored
6235  else
6236  return quadrature_points[q];
6237 }
6238 
6239 
6240 
6241 template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
6242  typename Number>
6243 inline
6244 void
6246 ::evaluate (const bool evaluate_values,
6247  const bool evaluate_gradients,
6248  const bool evaluate_hessians)
6249 {
6250  Assert (this->dof_values_initialized == true,
6252  evaluate(this->values_dofs[0], evaluate_values, evaluate_gradients, evaluate_hessians);
6253 }
6254 
6255 
6256 
6257 template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
6258  typename Number>
6259 inline
6260 void
6262 ::evaluate (const VectorizedArray<Number> *values_array,
6263  const bool evaluate_values,
6264  const bool evaluate_gradients,
6265  const bool evaluate_hessians)
6266 {
6268  ::evaluate (*this->data, const_cast<VectorizedArray<Number>*>(values_array),
6269  this->values_quad[0],
6270  this->gradients_quad[0][0], this->hessians_quad[0][0], this->scratch_data,
6271  evaluate_values, evaluate_gradients, evaluate_hessians);
6272 
6273 #ifdef DEBUG
6274  if (evaluate_values == true)
6275  this->values_quad_initialized = true;
6276  if (evaluate_gradients == true)
6277  this->gradients_quad_initialized = true;
6278  if (evaluate_hessians == true)
6279  this->hessians_quad_initialized = true;
6280 #endif
6281 }
6282 
6283 
6284 
6285 template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
6286  typename Number>
6287 template <typename VectorType>
6288 inline
6289 void
6291 ::gather_evaluate (const VectorType &input_vector,
6292  const bool evaluate_values,
6293  const bool evaluate_gradients,
6294  const bool evaluate_hessians)
6295 {
6296  this->read_dof_values(input_vector);
6297  evaluate(this->begin_dof_values(), evaluate_values, evaluate_gradients,
6298  evaluate_hessians);
6299 }
6300 
6301 
6302 
6303 template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
6304  typename Number>
6305 inline
6306 void
6308 ::integrate (const bool integrate_values,
6309  const bool integrate_gradients)
6310 {
6311  integrate(integrate_values, integrate_gradients, this->values_dofs[0]);
6312 
6313 #ifdef DEBUG
6314  this->dof_values_initialized = true;
6315 #endif
6316 }
6317 
6318 
6319 
6320 template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
6321  typename Number>
6322 inline
6323 void
6325 ::integrate (const bool integrate_values,
6326  const bool integrate_gradients,
6327  VectorizedArray<Number> *values_array)
6328 {
6329  if (integrate_values == true)
6330  Assert (this->values_quad_submitted == true,
6332  if (integrate_gradients == true)
6333  Assert (this->gradients_quad_submitted == true,
6335  Assert(this->matrix_info != nullptr ||
6336  this->mapped_geometry->is_initialized(), ExcNotInitialized());
6337 
6339  ::integrate (*this->data, values_array, this->values_quad[0],
6340  this->gradients_quad[0][0], this->scratch_data,
6341  integrate_values, integrate_gradients);
6342 
6343 #ifdef DEBUG
6344  this->dof_values_initialized = true;
6345 #endif
6346 }
6347 
6348 
6349 
6350 template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
6351  typename Number>
6352 template <typename VectorType>
6353 inline
6354 void
6356 ::integrate_scatter (const bool integrate_values,
6357  const bool integrate_gradients,
6358  VectorType &destination)
6359 {
6360  integrate(integrate_values, integrate_gradients, this->begin_dof_values());
6361  this->distribute_local_to_global(destination);
6362 }
6363 
6364 
6365 
6366 /*-------------------------- FEFaceEvaluation ---------------------------*/
6367 
6368 
6369 
6370 template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
6371  typename Number>
6372 inline
6374 ::FEFaceEvaluation (const MatrixFree<dim,Number> &matrix_free,
6375  const bool is_interior_face,
6376  const unsigned int dof_no,
6377  const unsigned int quad_no,
6378  const unsigned int first_selected_component)
6379  :
6380  BaseClass(matrix_free, dof_no, first_selected_component, quad_no, fe_degree,
6381  static_n_q_points, is_interior_face),
6382  dofs_per_component (this->data->dofs_per_component_on_cell),
6383  dofs_per_cell (this->data->dofs_per_component_on_cell *n_components_),
6384  n_q_points (this->data->n_q_points_face)
6385 {
6386 }
6387 
6388 
6389 
6390 template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
6391  typename Number>
6392 inline
6395 {}
6396 
6397 
6398 
6399 template <int dim, int fe_degree, int n_q_points_1d, int n_components_, typename Number>
6400 inline
6401 void
6403 ::reinit (const unsigned int face_index)
6404 {
6405  Assert (this->mapped_geometry == nullptr,
6406  ExcMessage("FEEvaluation was initialized without a matrix-free object."
6407  " Integer indexing is not possible"));
6408  if (this->mapped_geometry != nullptr)
6409  return;
6410 
6411  this->cell = face_index;
6412  this->dof_access_index = this->is_interior_face ?
6415  Assert (this->mapping_data != nullptr, ExcNotInitialized());
6416  const unsigned int n_vectors = VectorizedArray<Number>::n_array_elements;
6418  this->matrix_info->get_face_info(face_index);
6419  if (face_index >= this->matrix_info->get_task_info().face_partition_data.back() &&
6420  face_index < this->matrix_info->get_task_info().boundary_partition_data.back())
6421  Assert(this->is_interior_face, ExcMessage("Boundary faces do not have a neighbor"));
6422 
6423  this->face_no = (this->is_interior_face ? faces.interior_face_no : faces.exterior_face_no);
6424  this->subface_index = faces.subface_index;
6425  if (this->is_interior_face == true)
6426  {
6427  this->subface_index = GeometryInfo<dim>::max_children_per_cell;
6428  if (faces.face_orientation > 8)
6429  this->face_orientation = faces.face_orientation - 8;
6430  else
6431  this->face_orientation = 0;
6432  }
6433  else
6434  {
6435  if (faces.face_orientation < 8)
6436  this->face_orientation = faces.face_orientation;
6437  else
6438  this->face_orientation = 0;
6439  }
6440 
6441  this->values_quad_submitted = false;
6442 
6443  this->cell_type = this->matrix_info->get_mapping_info().face_type[face_index];
6444  const unsigned int offsets = this->mapping_data->data_index_offsets[face_index];
6445  this->J_value = &this->mapping_data->JxW_values[offsets];
6446  this->normal_vectors = &this->mapping_data->normal_vectors[offsets];
6447  this->jacobian = &this->mapping_data->jacobians[!this->is_interior_face][offsets];
6448  this->normal_x_jacobian = &this->mapping_data->normals_times_jacobians[!this->is_interior_face][offsets];
6449 
6450 #ifdef DEBUG
6451  this->dof_values_initialized = false;
6452  this->values_quad_initialized = false;
6453  this->gradients_quad_initialized = false;
6454  this->hessians_quad_initialized = false;
6455 #endif
6456 }
6457 
6458 
6459 
6460 template <int dim, int fe_degree, int n_q_points_1d, int n_components_, typename Number>
6461 inline
6462 void
6464 ::reinit (const unsigned int cell_index,
6465  const unsigned int face_number)
6466 {
6467  Assert(this->quad_no < this->matrix_info->get_mapping_info().face_data_by_cells.size(),
6468  ExcMessage("You must set MatrixFree::AdditionalData::mapping_update_flags_faces_by_cells to use the present reinit method."));
6470  AssertIndexRange(cell_index, this->matrix_info->get_mapping_info().cell_type.size());
6471  Assert (this->mapped_geometry == nullptr,
6472  ExcMessage("FEEvaluation was initialized without a matrix-free object."
6473  " Integer indexing is not possible"));
6474  Assert (this->is_interior_face==true,
6475  ExcMessage("Cell-based FEFaceEvaluation::reinit only possible for the "
6476  "interior face with second argument to constructor as true"));
6477  if (this->mapped_geometry != nullptr)
6478  return;
6479  Assert (this->matrix_info != nullptr, ExcNotInitialized());
6480 
6481  this->cell_type = this->matrix_info->get_mapping_info().cell_type[cell_index];
6482  this->cell = cell_index;
6483  this->face_orientation = 0;
6484  this->subface_index = GeometryInfo<dim>::max_children_per_cell;
6485  this->face_no = face_number;
6487 
6488  const unsigned int offsets =
6489  this->matrix_info->get_mapping_info().face_data_by_cells[this->quad_no].
6490  data_index_offsets[cell_index*GeometryInfo<dim>::faces_per_cell+face_number];
6491  AssertIndexRange(offsets, this->matrix_info->get_mapping_info().
6492  face_data_by_cells[this->quad_no].JxW_values.size());
6493  this->J_value = &this->matrix_info->get_mapping_info().
6494  face_data_by_cells[this->quad_no].JxW_values[offsets];
6495  this->normal_vectors = &this->matrix_info->get_mapping_info().
6496  face_data_by_cells[this->quad_no].normal_vectors[offsets];
6497  this->jacobian = &this->matrix_info->get_mapping_info().
6498  face_data_by_cells[this->quad_no].jacobians[0][offsets];
6499  this->normal_x_jacobian = &this->matrix_info->get_mapping_info().
6500  face_data_by_cells[this->quad_no].normals_times_jacobians[0][offsets];
6501 
6502 #ifdef DEBUG
6503  this->dof_values_initialized = false;
6504  this->values_quad_initialized = false;
6505  this->gradients_quad_initialized = false;
6506  this->hessians_quad_initialized = false;
6507 #endif
6508 }
6509 
6510 
6511 
6512 template <int dim, int fe_degree, int n_q_points_1d, int n_components,
6513  typename Number>
6514 inline
6515 void
6517 ::evaluate (const bool evaluate_values,
6518  const bool evaluate_gradients)
6519 {
6520  Assert(this->dof_values_initialized, ExcNotInitialized());
6521 
6522  evaluate(this->values_dofs[0], evaluate_values, evaluate_gradients);
6523 }
6524 
6525 
6526 
6527 template <int dim, int fe_degree, int n_q_points_1d, int n_components,
6528  typename Number>
6529 inline
6530 void
6532 ::evaluate (const VectorizedArray<Number> *values_array,
6533  const bool evaluate_values,
6534  const bool evaluate_gradients)
6535 {
6536  if (!(evaluate_values + evaluate_gradients))
6537  return;
6538 
6539  const unsigned int static_dofs_per_face = fe_degree > -1 ?
6540  Utilities::pow(fe_degree+1,dim-1) : numbers::invalid_unsigned_int;
6541  const unsigned int dofs_per_face = fe_degree > -1 ?
6542  static_dofs_per_face :
6543  Utilities::pow(this->data->fe_degree+1, dim-1);
6544 
6545  // we allocate small amounts of data on the stack to signal the compiler
6546  // that this temporary data is only needed for the calculations but the
6547  // final results can be discarded and need not be written back to
6548  // memory. For large sizes or when the dofs per face is not a compile-time
6549  // constant, however, we want to go to the heap in the `scratch_data`
6550  // variable to not risk a stack overflow.
6551  constexpr unsigned int stack_array_size_threshold = 100;
6552 
6553  VectorizedArray<Number> temp_data[static_dofs_per_face < stack_array_size_threshold ?
6554  n_components * 2 * static_dofs_per_face : 1];
6555  VectorizedArray<Number> *temp1;
6556  if (static_dofs_per_face < stack_array_size_threshold)
6557  temp1 = &temp_data[0];
6558  else
6559  temp1 = this->scratch_data;
6560 
6561  internal::FEFaceNormalEvaluationImpl<dim,fe_degree,n_components,VectorizedArray<Number> >
6562  ::template interpolate<true,false>(*this->data, values_array, temp1,
6563  evaluate_gradients, this->face_no);
6564 
6565  const unsigned int n_q_points_1d_actual = fe_degree > -1 ? n_q_points_1d : 0;
6566  if (fe_degree > -1 &&
6567  this->subface_index>=GeometryInfo<dim>::max_children_per_cell &&
6568  this->data->element_type<=internal::MatrixFreeFunctions::tensor_symmetric)
6569  internal::FEFaceEvaluationImpl<true,dim,fe_degree,n_q_points_1d_actual,n_components,VectorizedArray<Number> >
6570  ::evaluate_in_face(*this->data, temp1, this->begin_values(), this->begin_gradients(),
6571  this->scratch_data+2*n_components*dofs_per_face,
6572  evaluate_values, evaluate_gradients, this->subface_index);
6573  else
6574  internal::FEFaceEvaluationImpl<false,dim,fe_degree,n_q_points_1d_actual,n_components,VectorizedArray<Number> >
6575  ::evaluate_in_face(*this->data, temp1, this->begin_values(), this->begin_gradients(),
6576  this->scratch_data+2*n_components*dofs_per_face,
6577  evaluate_values, evaluate_gradients, this->subface_index);
6578 
6579  if (this->face_orientation)
6580  adjust_for_face_orientation(false, evaluate_values, evaluate_gradients);
6581 
6582 #ifdef DEBUG
6583  if (evaluate_values == true)
6584  this->values_quad_initialized = true;
6585  if (evaluate_gradients == true)
6586  this->gradients_quad_initialized = true;
6587 #endif
6588 }
6589 
6590 
6591 
6592 template <int dim, int fe_degree, int n_q_points_1d, int n_components,
6593  typename Number>
6594 inline
6595 void
6597 ::integrate (const bool integrate_values,
6598  const bool integrate_gradients)
6599 {
6600  integrate(integrate_values, integrate_gradients, this->values_dofs[0]);
6601 
6602 #ifdef DEBUG
6603  this->dof_values_initialized = true;
6604 #endif
6605 }
6606 
6607 
6608 
6609 template <int dim, int fe_degree, int n_q_points_1d, int n_components,
6610  typename Number>
6611 inline
6612 void
6614 ::integrate (const bool integrate_values,
6615  const bool integrate_gradients,
6616  VectorizedArray<Number> *values_array)
6617 {
6618  if (!(integrate_values + integrate_gradients))
6619  return;
6620 
6621  if (this->face_orientation)
6622  adjust_for_face_orientation(true, integrate_values, integrate_gradients);
6623 
6624  const unsigned int static_dofs_per_face = fe_degree > -1 ?
6625  Utilities::pow(fe_degree+1,dim-1) : numbers::invalid_unsigned_int;
6626  const unsigned int dofs_per_face = fe_degree > -1 ?
6627  static_dofs_per_face :
6628  Utilities::pow(this->data->fe_degree+1, dim-1);
6629 
6630  constexpr unsigned int stack_array_size_threshold = 100;
6631 
6632  VectorizedArray<Number> temp_data[static_dofs_per_face < stack_array_size_threshold ?
6633  n_components * 2 * static_dofs_per_face : 1];
6634  VectorizedArray<Number> *temp1;
6635  if (static_dofs_per_face < stack_array_size_threshold)
6636  temp1 = &temp_data[0];
6637  else
6638  temp1 = this->scratch_data;
6639 
6640  const unsigned int n_q_points_1d_actual = fe_degree > -1 ? n_q_points_1d : 0;
6641  if (fe_degree > -1 &&
6642  this->subface_index>=GeometryInfo<dim-1>::max_children_per_cell &&
6643  this->data->element_type<=internal::MatrixFreeFunctions::tensor_symmetric)
6644  internal::FEFaceEvaluationImpl<true,dim,fe_degree,n_q_points_1d_actual,n_components,VectorizedArray<Number> >
6645  ::integrate_in_face(*this->data, temp1, this->begin_values(),
6646  this->begin_gradients(),
6647  this->scratch_data+2*n_components*dofs_per_face,
6648  integrate_values, integrate_gradients, this->subface_index);
6649  else
6650  internal::FEFaceEvaluationImpl<false,dim,fe_degree,n_q_points_1d_actual,n_components,VectorizedArray<Number> >
6651  ::integrate_in_face(*this->data, temp1, this->begin_values(),
6652  this->begin_gradients(),
6653  this->scratch_data+2*n_components*dofs_per_face,
6654  integrate_values, integrate_gradients, this->subface_index);
6655 
6656  internal::FEFaceNormalEvaluationImpl<dim,fe_degree,n_components,VectorizedArray<Number> >
6657  ::template interpolate<false,false>(*this->data, temp1, values_array, integrate_gradients, this->face_no);
6658 }
6659 
6660 
6661 
6662 template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
6663  typename Number>
6664 template <typename VectorType>
6665 inline
6666 void
6668 ::gather_evaluate (const VectorType &input_vector,
6669  const bool evaluate_values,
6670  const bool evaluate_gradients)
6671 {
6672  const unsigned int side = this->face_no%2;
6673  const unsigned int dofs_per_face = fe_degree > -1 ?
6674  Utilities::pow(fe_degree+1,dim-1) :
6675  Utilities::pow(this->data->fe_degree+1, dim-1);
6676 
6677  constexpr unsigned int stack_array_size_threshold = 100;
6678 
6679  VectorizedArray<Number> temp_data[dofs_per_face < stack_array_size_threshold ?
6680  n_components_ * 2 * dofs_per_face : 1];
6681  VectorizedArray<Number> *__restrict temp1;
6682  if (dofs_per_face < stack_array_size_threshold)
6683  temp1 = &temp_data[0];
6684  else
6685  temp1 = this->scratch_data;
6686 
6687  internal::VectorReader<Number> reader;
6688 
6689  if (this->dof_info->index_storage_variants[this->dof_access_index][this->cell] ==
6691  &&
6692  this->dof_info->n_vectorization_lanes_filled[this->dof_access_index][this->cell] ==
6694  &&
6695  ((evaluate_gradients == false && this->data->nodal_at_cell_boundaries == true) ||
6696  (this->data->element_type == internal::MatrixFreeFunctions::tensor_symmetric_hermite &&
6697  fe_degree > 1)))
6698  {
6699  const unsigned int *indices = &this->dof_info->dof_indices_contiguous
6700  [this->dof_access_index][this->cell*VectorizedArray<Number>::n_array_elements];
6701  if (evaluate_gradients == true &&
6702  this->data->element_type == internal::MatrixFreeFunctions::tensor_symmetric_hermite)
6703  {
6704  // we know that the gradient weights for the Hermite case on the
6705  // right (side==1) are the negative from the value at the left
6706  // (side==0), so we only read out one of them.
6707  const VectorizedArray<Number> grad_weight0 = (side ? -1. : 1.) *
6708  this->data->shape_data_on_face[0][fe_degree+1];
6709  const VectorizedArray<Number> grad_weight1 = (side ? -1. : 1.) *
6710  this->data->shape_data_on_face[0][fe_degree+2];
6711  AssertDimension(this->data->face_to_cell_index_hermite.size(1),
6712  2*dofs_per_face);
6713 
6714  const unsigned int *index_array = &this->data->face_to_cell_index_hermite(this->face_no,0);
6715  for (unsigned int i=0; i<dofs_per_face; ++i)
6716  {
6717  const unsigned int ind1 = index_array[2*i];
6718  const unsigned int ind2 = index_array[2*i+1];
6719  for (unsigned int comp=0; comp<n_components_; ++comp)
6720  {
6721  reader.process_dof_gather(indices, input_vector,
6722  ind1+comp*static_dofs_per_component +
6723  this->dof_info->component_dof_indices_offset[this->active_fe_index][this->first_selected_component],
6724  temp1[i+2*comp*dofs_per_face],
6725  std::integral_constant<bool, std::is_same<typename VectorType::value_type,Number>::value>());
6727  reader.process_dof_gather(indices, input_vector,
6728  ind2+comp*static_dofs_per_component +
6729  this->dof_info->component_dof_indices_offset[this->active_fe_index][this->first_selected_component],
6730  grad,
6731  std::integral_constant<bool, std::is_same<typename VectorType::value_type,Number>::value>());
6732  temp1[i+dofs_per_face+2*comp*dofs_per_face] =
6733  grad_weight0 * temp1[i+2*comp*dofs_per_face] +
6734  grad_weight1 * grad;
6735  }
6736  }
6737  }
6738  else
6739  {
6740  AssertDimension(this->data->face_to_cell_index_nodal.size(1),
6741  dofs_per_face);
6742  const unsigned int *index_array = &this->data->face_to_cell_index_nodal(this->face_no,0);
6743  for (unsigned int i=0; i<dofs_per_face; ++i)
6744  for (unsigned int comp=0; comp<n_components_; ++comp)
6745  {
6746  const unsigned int ind = index_array[i];
6747  reader.process_dof_gather(indices, input_vector,
6748  ind+comp*static_dofs_per_component +
6749  this->dof_info->component_dof_indices_offset[this->active_fe_index][this->first_selected_component],
6750  temp1[i+comp*2*dofs_per_face],
6751  std::integral_constant<bool, std::is_same<typename VectorType::value_type,Number>::value>());
6752  }
6753  }
6754  }
6755  else
6756  {
6757  this->read_dof_values(input_vector);
6758  internal::FEFaceNormalEvaluationImpl<dim,fe_degree,n_components_,VectorizedArray<Number> >
6759  ::template interpolate<true,false>(*this->data, this->values_dofs[0], temp1,
6760  evaluate_gradients, this->face_no);
6761  }
6762 
6763  if (fe_degree > -1 &&
6764  this->subface_index>=GeometryInfo<dim>::max_children_per_cell &&
6765  this->data->element_type <= internal::MatrixFreeFunctions::tensor_symmetric)
6766  internal::FEFaceEvaluationImpl<true,dim,fe_degree,n_q_points_1d,n_components_,VectorizedArray<Number> >
6767  ::evaluate_in_face(*this->data, temp1, this->values_quad[0],
6768  this->gradients_quad[0][0], this->scratch_data +
6769  2*n_components_*dofs_per_face,
6770  evaluate_values, evaluate_gradients, this->subface_index);
6771  else
6772  internal::FEFaceEvaluationImpl<false,dim,fe_degree,n_q_points_1d,n_components_,VectorizedArray<Number> >
6773  ::evaluate_in_face(*this->data, temp1, this->values_quad[0],
6774  this->gradients_quad[0][0], this->scratch_data +
6775  2*n_components_*dofs_per_face,
6776  evaluate_values, evaluate_gradients, this->subface_index);
6777 
6778  if (this->face_orientation)
6779  adjust_for_face_orientation(false, evaluate_values, evaluate_gradients);
6780 
6781 #ifdef DEBUG
6782  if (evaluate_values == true)
6783  this->values_quad_initialized = true;
6784  if (evaluate_gradients == true)
6785  this->gradients_quad_initialized = true;
6786 #endif
6787 }
6788 
6789 
6790 
6791 template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
6792  typename Number>
6793 template <typename VectorType>
6794 inline
6795 void
6797 ::integrate_scatter (const bool integrate_values,
6798  const bool integrate_gradients,
6799  VectorType &destination)
6800 {
6801  const unsigned int side = this->face_no%2;
6802  const unsigned int dofs_per_face = fe_degree > -1 ?
6803  Utilities::pow(fe_degree+1,dim-1) :
6804  Utilities::pow(this->data->fe_degree+1, dim-1);
6805 
6806  constexpr unsigned int stack_array_size_threshold = 100;
6807 
6808  VectorizedArray<Number> temp_data[dofs_per_face < stack_array_size_threshold ?
6809  n_components_ * 2 * dofs_per_face : 1];
6810  VectorizedArray<Number> *__restrict temp1;
6811  if (dofs_per_face < stack_array_size_threshold)
6812  temp1 = &temp_data[0];
6813  else
6814  temp1 = this->scratch_data;
6815 
6816  if (this->face_orientation)
6817  adjust_for_face_orientation(true, integrate_values, integrate_gradients);
6818  if (fe_degree > -1 &&
6819  this->subface_index>=GeometryInfo<dim>::max_children_per_cell &&
6820  this->data->element_type <= internal::MatrixFreeFunctions::tensor_symmetric)
6821  internal::FEFaceEvaluationImpl<true,dim,fe_degree,n_q_points_1d,n_components_,VectorizedArray<Number> >
6822  ::integrate_in_face(*this->data, temp1, this->values_quad[0],
6823  this->gradients_quad[0][0], this->scratch_data +
6824  2*n_components_*dofs_per_face,
6825  integrate_values, integrate_gradients, this->subface_index);
6826  else
6827  internal::FEFaceEvaluationImpl<false,dim,fe_degree,n_q_points_1d,n_components_,VectorizedArray<Number> >
6828  ::integrate_in_face(*this->data, temp1, this->values_quad[0],
6829  this->gradients_quad[0][0], this->scratch_data +
6830  2*n_components_*dofs_per_face,
6831  integrate_values, integrate_gradients, this->subface_index);
6832 
6833 #ifdef DEBUG
6834  this->dof_values_initialized = true;
6835 #endif
6836 
6837  internal::VectorDistributorLocalToGlobal<Number> writer;
6838 
6839  if (this->dof_info->index_storage_variants[this->dof_access_index][this->cell] ==
6841  &&
6842  this->dof_info->n_vectorization_lanes_filled[this->dof_access_index][this->cell] ==
6844  &&
6845  ((integrate_gradients == false && this->data->nodal_at_cell_boundaries == true) ||
6846  (this->data->element_type == internal::MatrixFreeFunctions::tensor_symmetric_hermite &&
6847  fe_degree > 1)))
6848  {
6849  const unsigned int *indices = &this->dof_info->dof_indices_contiguous
6850  [this->dof_access_index][this->cell*VectorizedArray<Number>::n_array_elements];
6851 
6852  if (integrate_gradients == true &&
6853  this->data->element_type == internal::MatrixFreeFunctions::tensor_symmetric_hermite)
6854  {
6855  // we know that the gradient weights for the Hermite case on the
6856  // right (side==1) are the negative from the value at the left
6857  // (side==0), so we only read out one of them.
6858  const VectorizedArray<Number> grad_weight0 = (side ? -1. : 1.) * this->data->shape_data_on_face[0][fe_degree+1];
6859  const VectorizedArray<Number> grad_weight1 = (side ? -1. : 1.) * this->data->shape_data_on_face[0][fe_degree+2];
6860  AssertDimension(this->data->face_to_cell_index_hermite.size(1),
6861  2*dofs_per_face);
6862  const unsigned int *index_array = &this->data->face_to_cell_index_hermite(this->face_no,0);
6863  for (unsigned int i=0; i<dofs_per_face; ++i)
6864  {
6865  const unsigned int ind1 = index_array[2*i];
6866  const unsigned int ind2 = index_array[2*i+1];
6867  for (unsigned int comp=0; comp<n_components_; ++comp)
6868  {
6869  VectorizedArray<Number> val = temp1[i+2*comp*dofs_per_face]
6870  + grad_weight0 * temp1[i+dofs_per_face+2*comp*dofs_per_face];
6872  grad_weight1 * temp1[i+dofs_per_face+2*comp*dofs_per_face];
6873  writer.process_dof_gather(indices, destination,
6874  comp*static_dofs_per_component+ind1 +
6875  this->dof_info->component_dof_indices_offset[this->active_fe_index][this->first_selected_component],
6876  val,
6877  std::integral_constant<bool, std::is_same<typename VectorType::value_type,Number>::value>());
6878  writer.process_dof_gather(indices, destination,
6879  comp*static_dofs_per_component+ind2 +
6880  this->dof_info->component_dof_indices_offset[this->active_fe_index][this->first_selected_component],
6881  grad,
6882  std::integral_constant<bool, std::is_same<typename VectorType::value_type,Number>::value>());
6883  }
6884  }
6885  }
6886  else
6887  {
6888  AssertDimension(this->data->face_to_cell_index_nodal.size(1),
6889  dofs_per_face);
6890  const unsigned int *index_array = &this->data->face_to_cell_index_nodal(this->face_no,0);
6891  for (unsigned int i=0; i<dofs_per_face; ++i)
6892  {
6893  const unsigned int ind = index_array[i];
6894  for (unsigned int comp=0; comp<n_components_; ++comp)
6895  writer.process_dof_gather(indices, destination,
6896  comp*static_dofs_per_component+ind +
6897  this->dof_info->component_dof_indices_offset[this->active_fe_index][this->first_selected_component],
6898  temp1[i+2*comp*dofs_per_face],
6899  std::integral_constant<bool, std::is_same<typename VectorType::value_type,Number>::value>());
6900  }
6901  }
6902  }
6903  else
6904  {
6905  internal::FEFaceNormalEvaluationImpl<dim,fe_degree,n_components_,VectorizedArray<Number> >
6906  ::template interpolate<false,false>(*this->data, temp1, this->values_dofs[0],
6907  integrate_gradients, this->face_no);
6908  this->distribute_local_to_global(destination);
6909  }
6910 }
6911 
6912 
6913 
6914 template <int dim, int fe_degree, int n_q_points_1d, int n_components,
6915  typename Number>
6916 inline
6917 void
6919 ::adjust_for_face_orientation(const bool integrate,
6920  const bool values,
6921  const bool gradients)
6922 {
6923  VectorizedArray<Number> *tmp_values = this->scratch_data;
6924  const unsigned int *orientations =
6925  &this->mapping_data->descriptor[this->active_fe_index].face_orientations[this->face_orientation][0];
6926  for (unsigned int c=0; c<n_components; ++c)
6927  {
6928  if (values == true)
6929  {
6930  if (integrate)
6931  for (unsigned int q=0; q<n_q_points; ++q)
6932  tmp_values[orientations[q]] = this->values_quad[c][q];
6933  else
6934  for (unsigned int q=0; q<n_q_points; ++q)
6935  tmp_values[q] = this->values_quad[c][orientations[q]];
6936  for (unsigned int q=0; q<n_q_points; ++q)
6937  this->values_quad[c][q] = tmp_values[q];
6938  }
6939  if (gradients == true)
6940  for (unsigned int d=0; d<dim; ++d)
6941  {
6942  if (integrate)
6943  for (unsigned int q=0; q<n_q_points; ++q)
6944  tmp_values[orientations[q]] = this->gradients_quad[c][d][q];
6945  else
6946  for (unsigned int q=0; q<n_q_points; ++q)
6947  tmp_values[q] = this->gradients_quad[c][d][orientations[q]];
6948  for (unsigned int q=0; q<n_q_points; ++q)
6949  this->gradients_quad[c][d][q] = tmp_values[q];
6950  }
6951  }
6952 }
6953 
6954 
6955 
6956 template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
6957  typename Number>
6958 inline
6961 ::quadrature_point (const unsigned int q) const
6962 {
6963  AssertIndexRange (q, n_q_points);
6964  if (this->dof_access_index < 2)
6965  {
6966  Assert(this->mapping_data->quadrature_point_offsets.empty() == false,
6967  ExcNotImplemented());
6968  AssertIndexRange(this->cell, this->mapping_data->quadrature_point_offsets.size());
6969  return this->mapping_data->quadrature_points[this->mapping_data->quadrature_point_offsets[this->cell]+q];
6970  }
6971  else
6972  {
6973  Assert(this->matrix_info->get_mapping_info().face_data_by_cells
6974  [this->quad_no].quadrature_point_offsets.empty() == false,
6975  ExcNotImplemented());
6976  const unsigned int index = this->cell*GeometryInfo<dim>::faces_per_cell + this->face_no;
6977  AssertIndexRange(index, this->matrix_info->get_mapping_info().face_data_by_cells
6978  [this->quad_no].quadrature_point_offsets.size());
6979  return this->matrix_info->get_mapping_info().face_data_by_cells[this->quad_no].
6980  quadrature_points[this->matrix_info->get_mapping_info().face_data_by_cells
6981  [this->quad_no].quadrature_point_offsets[index]+q];
6982  }
6983 }
6984 
6985 
6986 
6987 /*------------------------- end FEFaceEvaluation ------------------------- */
6988 
6989 
6990 #endif // ifndef DOXYGEN
6991 
6992 
6993 DEAL_II_NAMESPACE_CLOSE
6994 
6995 #endif
gradient_type get_gradient(const unsigned int q_point) const
const unsigned int active_quad_index
std::vector< unsigned int > plain_dof_indices
Definition: dof_info.h:401
static const unsigned int invalid_unsigned_int
Definition: types.h:173
const Number * constraint_pool_begin(const unsigned int pool_index) const
void set_dof_values(VectorType &dst, const unsigned int first_index=0) const
const VectorizedArray< Number > * begin_hessians() const
#define AssertDimension(dim1, dim2)
Definition: exceptions.h:1248
const MatrixFree< dim, Number > * matrix_info
void submit_divergence(const VectorizedArray< Number > div_in, const unsigned int q_point)
bool values_quad_initialized
void check_template_arguments(const unsigned int fe_no, const unsigned int first_selected_component)
void submit_symmetric_gradient(const SymmetricTensor< 2, dim, VectorizedArray< Number > > grad_in, const unsigned int q_point)
void distribute_local_to_global(VectorType &dst, const unsigned int first_index=0) const
FEEvaluationAccess< dim, n_components_, Number, true > BaseClass
FEEvaluation & operator=(const FEEvaluation &other)
const internal::MatrixFreeFunctions::FaceToCellTopology< VectorizedArray< Number >::n_array_elements > & get_face_info(const unsigned int face_batch_number) const
internal::MatrixFreeFunctions::GeometryType get_cell_type() const
internal::MatrixFreeFunctions::GeometryType cell_type
static ::ExceptionBase & ExcAccessToUninitializedField()
std::vector< unsigned int > component_to_base_index
Definition: dof_info.h:431
const internal::MatrixFreeFunctions::TaskInfo & get_size_info() const
constexpr unsigned int pow(const unsigned int base, const unsigned int iexp)
Definition: utilities.h:354
SymmetricTensor< 2, dim, Number > e(const Tensor< 2, dim, Number > &F)
Point< spacedim > point(const gp_Pnt &p, const double &tolerance=1e-10)
Definition: utilities.cc:183
std::vector< IndexStorageVariants > index_storage_variants[3]
Definition: dof_info.h:296
Point< dim, VectorizedArray< Number > > quadrature_point(const unsigned int q_point) const
const unsigned int dofs_per_cell
BaseClass::value_type value_type
unsigned int n_components() const
void evaluate(const bool evaluate_values, const bool evaluate_gradients, const bool evaluate_hessians=false)
void integrate(const bool integrate_values, const bool integrate_gradients)
const MappingInfoStorage< dim, dim, Number > & get_data_storage() const
void submit_normal_derivative(const value_type grad_in, const unsigned int q_point)
static constexpr unsigned int static_dofs_per_cell
#define AssertIndexRange(index, range)
Definition: exceptions.h:1284
std::shared_ptr< const Utilities::MPI::Partitioner > vector_partitioner
Definition: dof_info.h:366
ArrayView< VectorizedArray< Number > > get_scratch_data() const
void submit_curl(const Tensor< 1, dim==2?1:dim, VectorizedArray< Number > > curl_in, const unsigned int q_point)
const Tensor< 2, dim, VectorizedArray< Number > > * jacobian
FEEvaluationBase & operator=(const FEEvaluationBase &other)
const unsigned int active_fe_index
std::vector< std::pair< unsigned short, unsigned short > > constraint_indicator
Definition: dof_info.h:332
const VectorizedArray< Number > * begin_dof_values() const
void integrate_scatter(const bool integrate_values, const bool integrate_gradients, VectorType &output_vector)
const internal::MatrixFreeFunctions::ShapeInfo< VectorizedArray< Number > > * data
STL namespace.
Transformed quadrature points.
static ::ExceptionBase & ExcNotInitialized()
const Tensor< 1, dim, VectorizedArray< Number > > * normal_x_jacobian
std::vector< unsigned int > cell_partition_data
Definition: task_info.h:444
void read_dof_values(const VectorType &src, const unsigned int first_index=0)
VectorizedArray< Number > read_cell_data(const AlignedVector< VectorizedArray< Number > > &array) const
static constexpr unsigned int n_components
FEEvaluationAccess & operator=(const FEEvaluationAccess &other)
AlignedVector< VectorizedArray< Number > > * scratch_data_array
static ::ExceptionBase & ExcIndexRange(int arg1, int arg2, int arg3)
void scatter(const unsigned int *offsets, Number *base_ptr) const
std::vector< unsigned int > dof_indices
Definition: dof_info.h:321
SymmetricTensor< 2, dim, VectorizedArray< Number > > get_symmetric_gradient(const unsigned int q_point) const
value_type integrate_value() const
Definition: point.h:104
std::string to_string(const number value, const unsigned int digits=numbers::invalid_unsigned_int)
Definition: utilities.cc:107
const unsigned int dofs_per_component
void fill_JxW_values(AlignedVector< VectorizedArray< Number > > &JxW_values) const
std::shared_ptr< internal::MatrixFreeFunctions::MappingDataOnTheFly< dim, Number > > mapped_geometry
value_type get_value(const unsigned int q_point) const
void read_write_operation_contiguous(const VectorOperation &operation, VectorType *vectors[]) const
void submit_value(const value_type val_in, const unsigned int q_point)
VectorizedArray< Number > JxW(const unsigned int q_index) const
std::vector< unsigned char > n_vectorization_lanes_filled[3]
Definition: dof_info.h:358
AlignedVector< VectorizedArray< Number > > * acquire_scratch_data() const
void set_data_pointers()
T fixed_power(const T t)
Definition: utilities.h:863
const Number * quadrature_weights
static constexpr unsigned int tensor_dofs_per_cell
void read_dof_values_plain(const VectorType &src, const unsigned int first_index=0)
const unsigned int dofs_per_cell
internal::MatrixFreeFunctions::DoFInfo::DoFAccessIndex dof_access_index
static ::ExceptionBase & ExcMessage(std::string arg1)
const unsigned int n_q_points
gradient_type get_hessian_diagonal(const unsigned int q_point) const
value_type get_laplacian(const unsigned int q_point) const
const internal::MatrixFreeFunctions::ShapeInfo< VectorizedArray< Number > > & get_shape_info() const
std::pair< unsigned int, unsigned int > component_to_base_index(const unsigned int component) const
Definition: fe.h:3153
T sum(const T &t, const MPI_Comm &mpi_communicator)
unsigned int global_dof_index
Definition: types.h:88
VectorizedArray< Number > get_divergence(const unsigned int q_point) const
std::vector< unsigned int > dof_indices_interleaved
Definition: dof_info.h:337
const unsigned int quad_no
VectorizedArray< Number > * scratch_data
#define Assert(cond, exc)
Definition: exceptions.h:1142
unsigned int element_multiplicity(const unsigned int index) const
Definition: fe.h:3056
UpdateFlags
const internal::MatrixFreeFunctions::DoFInfo * dof_info
const VectorizedArray< Number > * begin_values() const
unsigned int subface_index
std::vector< unsigned int > row_starts_plain_indices
Definition: dof_info.h:391
#define DeclException0(Exception0)
Definition: exceptions.h:323
std::vector< unsigned int > boundary_partition_data
Definition: task_info.h:462
const Number * constraint_pool_end(const unsigned int pool_index) const
void read_write_operation_global(const VectorOperation &operation, VectorType *vectors[]) const
std::vector< std::pair< unsigned int, unsigned int > > row_starts
Definition: dof_info.h:304
const internal::MatrixFreeFunctions::ShapeInfo< VectorizedArray< Number > > & get_shape_info(const unsigned int dof_handler_index_component=0, const unsigned int quad_index=0, const unsigned int fe_base_element=0, const unsigned int hp_active_fe_index=0, const unsigned int hp_active_quad_index=0) const
unsigned int get_mapping_data_index_offset() const
void reinit(const unsigned int face_batch_number)
unsigned int face_no
VectorizedArray< Number > * gradients_quad[n_components][dim]
VectorizedArray< Number > pow(const ::VectorizedArray< Number > &x, const Number p)
BaseClass::gradient_type gradient_type
Number number_type
static constexpr unsigned int static_dofs_per_cell
friend class FEEvaluationBase
void gather_evaluate(const VectorType &input_vector, const bool evaluate_values, const bool evaluate_gradients)
const VectorizedArray< Number > * J_value
bool mapping_initialized() const
bool hessians_quad_initialized
std::string int_to_string(const unsigned int value, const unsigned int digits=numbers::invalid_unsigned_int)
Definition: utilities.cc:98
SymmetricTensor< 2, dim, Number > d(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
void reinit(const unsigned int cell_batch_index)
void adjust_for_face_orientation(const bool integrate, const bool values, const bool gradients)
unsigned int cell
void integrate(const bool integrate_values, const bool integrate_gradients)
BaseClass::value_type value_type
static constexpr unsigned int n_components
std::vector< unsigned int > face_partition_data
Definition: task_info.h:453
static constexpr unsigned int static_n_q_points_cell
FEFaceEvaluation(const MatrixFree< dim, Number > &matrix_free, const bool is_interior_face=true, const unsigned int dof_no=0, const unsigned int quad_no=0, const unsigned int first_selected_component=0)
void release_scratch_data(const AlignedVector< VectorizedArray< Number > > *memory) const
Definition: cuda.h:31
void evaluate(const bool evaluate_values, const bool evaluate_gradients)
Tensor< 1, n_components_, Tensor< 2, dim, VectorizedArray< Number > > > get_hessian(const unsigned int q_point) const
VectorizedArray< Number > * hessians_quad[n_components][(dim *(dim+1))/2]
const internal::MatrixFreeFunctions::MappingInfoStorage<(is_face?dim-1:dim), dim, Number > * mapping_data
value_type get_dof_value(const unsigned int dof) const
Definition: mpi.h:53
static constexpr unsigned int static_n_q_points
std::vector< unsigned int > dof_indices_contiguous[3]
Definition: dof_info.h:347
const unsigned int n_q_points
std::vector< std::vector< unsigned int > > component_dof_indices_offset
Definition: dof_info.h:444
VectorizedArray< Number > * values_dofs[n_components]
const VectorizedArray< Number > * begin_gradients() const
static constexpr unsigned int tensor_dofs_per_cell
unsigned int get_cell_data_number() const
static constexpr unsigned int dimension
bool partitioners_are_compatible(const Utilities::MPI::Partitioner &part) const
Number local_element(const size_type local_index) const
unsigned int n_base_elements(const unsigned int dof_handler_index) const
static constexpr unsigned int static_dofs_per_component
const unsigned int n_quadrature_points
Tensor< 2, dim, VectorizedArray< Number > > inverse_jacobian(const unsigned int q_index) const
void gather(const Number *base_ptr, const unsigned int *offsets)
void read_write_operation(const VectorOperation &operation, VectorType *vectors[], const bool apply_constraints=true) const
const unsigned int dofs_per_component
static ::ExceptionBase & ExcNotImplemented()
Tensor< 1, dim, VectorizedArray< Number > > get_normal_vector(const unsigned int q_point) const
std::vector< types::global_dof_index > local_dof_indices
value_type get_normal_derivative(const unsigned int q_point) const
Tensor< 1,(dim==2?1:dim), VectorizedArray< Number > > get_curl(const unsigned int q_point) const
bool indices_initialized() const
static constexpr unsigned int dimension
void gather_evaluate(const VectorType &input_vector, const bool evaluate_values, const bool evaluate_gradients, const bool evaluate_hessians=false)
VectorizedArray< Number > * values_quad[n_components]
void submit_dof_value(const value_type val_in, const unsigned int dof)
bool gradients_quad_initialized
std::vector< unsigned int > start_components
Definition: dof_info.h:425
void integrate_scatter(const bool integrate_values, const bool integrate_gradients, VectorType &output_vector)
std::vector< unsigned int > lexicographic_numbering
Definition: shape_info.h:223
FEEvaluation(const MatrixFree< dim, Number > &matrix_free, const unsigned int dof_no=0, const unsigned int quad_no=0, const unsigned int first_selected_component=0)
static constexpr unsigned int static_dofs_per_component
unsigned int n_components(const DoFHandler< dim, spacedim > &dh)
FEEvaluationAccess(const MatrixFree< dim, Number > &matrix_free, const unsigned int dof_no, const unsigned int first_selected_component, const unsigned int quad_no, const unsigned int fe_degree, const unsigned int n_q_points, const bool is_interior_face=true)
unsigned int face_orientation
static constexpr unsigned int static_n_q_points
const Tensor< 1, dim, VectorizedArray< Number > > * normal_vectors
Point< dim, VectorizedArray< Number > > quadrature_point(const unsigned int q_point) const
BaseClass::gradient_type gradient_type
const std::vector< unsigned int > & get_internal_dof_numbering() const
const unsigned int n_fe_components
const internal::MatrixFreeFunctions::TaskInfo & get_task_info() const
void submit_gradient(const gradient_type grad_in, const unsigned int q_point)
const unsigned int first_selected_component
static ::ExceptionBase & ExcInternalError()
FEEvaluationAccess< dim, n_components_, Number, false > BaseClass