Reference documentation for deal.II version 8.4.2
fe_evaluation.h
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2011 - 2016 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE at
12 // the top level of the deal.II distribution.
13 //
14 // ---------------------------------------------------------------------
15 
16 
17 #ifndef dealii__matrix_free_fe_evaluation_h
18 #define dealii__matrix_free_fe_evaluation_h
19 
20 
21 #include <deal.II/base/config.h>
22 #include <deal.II/base/exceptions.h>
23 #include <deal.II/base/template_constraints.h>
24 #include <deal.II/base/symmetric_tensor.h>
25 #include <deal.II/base/vectorization.h>
26 #include <deal.II/base/smartpointer.h>
27 #include <deal.II/matrix_free/matrix_free.h>
28 #include <deal.II/matrix_free/shape_info.h>
29 #include <deal.II/matrix_free/mapping_data_on_the_fly.h>
30 
31 
32 DEAL_II_NAMESPACE_OPEN
33 
34 
35 
36 // forward declarations
37 namespace parallel
38 {
39  namespace distributed
40  {
41  template <typename> class Vector;
42  }
43 }
44 namespace internal
45 {
46  DeclException0 (ExcAccessToUninitializedField);
47 }
48 
49 template <int dim, int fe_degree, int n_q_points_1d = fe_degree+1,
50  int n_components_ = 1, typename Number = double > class FEEvaluation;
51 
52 
76 template <int dim, int n_components_, typename Number>
78 {
79 public:
80  typedef Number number_type;
83  static const unsigned int dimension = dim;
84  static const unsigned int n_components = n_components_;
85 
98  void reinit (const unsigned int cell);
99 
112  template <typename DoFHandlerType, bool level_dof_access>
114 
125  void reinit (const typename Triangulation<dim>::cell_iterator &cell);
126 
135  unsigned int get_cell_data_number() const;
136 
143  internal::MatrixFreeFunctions::CellType get_cell_type() const;
144 
149  get_shape_info() const;
150 
154  void
155  fill_JxW_values(AlignedVector<VectorizedArray<Number> > &JxW_values) const;
156 
158 
188  template <typename VectorType>
189  void read_dof_values (const VectorType &src);
190 
199  template <typename VectorType>
200  void read_dof_values (const std::vector<VectorType> &src,
201  const unsigned int first_index=0);
202 
207  template <typename VectorType>
208  void read_dof_values (const std::vector<VectorType *> &src,
209  const unsigned int first_index=0);
210 
232  template <typename VectorType>
233  void read_dof_values_plain (const VectorType &src);
234 
242  template <typename VectorType>
243  void read_dof_values_plain (const std::vector<VectorType> &src,
244  const unsigned int first_index=0);
245 
251  template <typename VectorType>
252  void read_dof_values_plain (const std::vector<VectorType *> &src,
253  const unsigned int first_index=0);
254 
271  template<typename VectorType>
272  void distribute_local_to_global (VectorType &dst) const;
273 
283  template<typename VectorType>
284  void distribute_local_to_global (std::vector<VectorType> &dst,
285  const unsigned int first_index=0) const;
286 
291  template<typename VectorType>
292  void distribute_local_to_global (std::vector<VectorType *> &dst,
293  const unsigned int first_index=0) const;
294 
311  template<typename VectorType>
312  void set_dof_values (VectorType &dst) const;
313 
323  template<typename VectorType>
324  void set_dof_values (std::vector<VectorType> &dst,
325  const unsigned int first_index=0) const;
326 
331  template<typename VectorType>
332  void set_dof_values (std::vector<VectorType *> &dst,
333  const unsigned int first_index=0) const;
334 
336 
354  value_type get_dof_value (const unsigned int dof) const;
355 
366  void submit_dof_value (const value_type val_in,
367  const unsigned int dof);
368 
380  value_type get_value (const unsigned int q_point) const;
381 
393  void submit_value (const value_type val_in,
394  const unsigned int q_point);
395 
405  gradient_type get_gradient (const unsigned int q_point) const;
406 
419  void submit_gradient(const gradient_type grad_in,
420  const unsigned int q_point);
421 
433  get_hessian (const unsigned int q_point) const;
434 
443  gradient_type get_hessian_diagonal (const unsigned int q_point) const;
444 
455  value_type get_laplacian (const unsigned int q_point) const;
456 
465  value_type integrate_value () const;
466 
468 
481  const VectorizedArray<Number> *begin_dof_values () const;
482 
491  VectorizedArray<Number> *begin_dof_values ();
492 
503  const VectorizedArray<Number> *begin_values () const;
504 
515  VectorizedArray<Number> *begin_values ();
516 
528  const VectorizedArray<Number> *begin_gradients () const;
529 
541  VectorizedArray<Number> *begin_gradients ();
542 
555  const VectorizedArray<Number> *begin_hessians () const;
556 
569  VectorizedArray<Number> *begin_hessians ();
570 
576  const std::vector<unsigned int> &
577  get_internal_dof_numbering() const;
578 
580 
581 protected:
582 
590  FEEvaluationBase (const MatrixFree<dim,Number> &matrix_free,
591  const unsigned int fe_no,
592  const unsigned int quad_no,
593  const unsigned int fe_degree,
594  const unsigned int n_q_points);
595 
630  template <int n_components_other>
631  FEEvaluationBase (const Mapping<dim> &mapping,
632  const FiniteElement<dim> &fe,
633  const Quadrature<1> &quadrature,
634  const UpdateFlags update_flags,
635  const unsigned int first_selected_component,
637 
644  FEEvaluationBase (const FEEvaluationBase &other);
645 
652  template<typename VectorType, typename VectorOperation>
653  void read_write_operation (const VectorOperation &operation,
654  VectorType *vectors[]) const;
655 
663  template<typename VectorType>
664  void read_dof_values_plain (const VectorType *src_data[]);
665 
679  VectorizedArray<Number> *values_dofs[n_components];
680 
686  VectorizedArray<Number> *values_quad[n_components];
687 
695  VectorizedArray<Number> *gradients_quad[n_components][dim];
696 
702  VectorizedArray<Number> *hessians_quad[n_components][(dim*(dim+1))/2];
703 
707  const unsigned int quad_no;
708 
713  const unsigned int n_fe_components;
714 
719  const unsigned int active_fe_index;
720 
725  const unsigned int active_quad_index;
726 
731 
737  const internal::MatrixFreeFunctions::DoFInfo *dof_info;
738 
746 
751  std_cxx11::shared_ptr<internal::MatrixFreeFunctions::ShapeInfo<Number> > stored_shape_info;
752 
760 
766 
772 
780 
785 
790 
797 
804 
809  unsigned int cell;
810 
817  internal::MatrixFreeFunctions::CellType cell_type;
818 
822  unsigned int cell_data_number;
823 
830 
837 
844 
851 
858 
865 
870  std_cxx1x::shared_ptr<internal::MatrixFreeFunctions::MappingDataOnTheFly<dim,Number> > mapped_geometry;
871 
876  std::vector<types::global_dof_index> old_style_dof_indices;
877 
882  const unsigned int first_selected_component;
883 
888  mutable std::vector<types::global_dof_index> local_dof_indices;
889 
893  template <int, int, typename> friend class FEEvaluationBase;
894  template <int, int, int, int, typename> friend class FEEvaluation;
895 };
896 
897 
898 
906 template <int dim, int n_components_, typename Number>
907 class FEEvaluationAccess : public FEEvaluationBase<dim,n_components_,Number>
908 {
909 public:
910  typedef Number number_type;
913  static const unsigned int dimension = dim;
914  static const unsigned int n_components = n_components_;
916 
917 protected:
925  FEEvaluationAccess (const MatrixFree<dim,Number> &matrix_free,
926  const unsigned int fe_no,
927  const unsigned int quad_no,
928  const unsigned int fe_degree,
929  const unsigned int n_q_points);
930 
935  template <int n_components_other>
936  FEEvaluationAccess (const Mapping<dim> &mapping,
937  const FiniteElement<dim> &fe,
938  const Quadrature<1> &quadrature,
939  const UpdateFlags update_flags,
940  const unsigned int first_selected_component,
942 
946  FEEvaluationAccess (const FEEvaluationAccess &other);
947 };
948 
949 
950 
951 
960 template <int dim, typename Number>
961 class FEEvaluationAccess<dim,1,Number> : public FEEvaluationBase<dim,1,Number>
962 {
963 public:
964  typedef Number number_type;
965  typedef VectorizedArray<Number> value_type;
967  static const unsigned int dimension = dim;
969 
979  value_type get_dof_value (const unsigned int dof) const;
980 
985  void submit_dof_value (const value_type val_in,
986  const unsigned int dof);
987 
995  value_type get_value (const unsigned int q_point) const;
996 
1004  void submit_value (const value_type val_in,
1005  const unsigned int q_point);
1006 
1012  gradient_type get_gradient (const unsigned int q_point) const;
1013 
1022  void submit_gradient(const gradient_type grad_in,
1023  const unsigned int q_point);
1024 
1032  get_hessian (unsigned int q_point) const;
1033 
1038  gradient_type get_hessian_diagonal (const unsigned int q_point) const;
1039 
1044  value_type get_laplacian (const unsigned int q_point) const;
1045 
1054  value_type integrate_value () const;
1055 
1056 protected:
1064  FEEvaluationAccess (const MatrixFree<dim,Number> &matrix_free,
1065  const unsigned int fe_no,
1066  const unsigned int quad_no,
1067  const unsigned int fe_degree,
1068  const unsigned int n_q_points);
1069 
1074  template <int n_components_other>
1075  FEEvaluationAccess (const Mapping<dim> &mapping,
1076  const FiniteElement<dim> &fe,
1077  const Quadrature<1> &quadrature,
1078  const UpdateFlags update_flags,
1079  const unsigned int first_selected_component,
1081 
1085  FEEvaluationAccess (const FEEvaluationAccess &other);
1086 };
1087 
1088 
1089 
1099 template <int dim, typename Number>
1100 class FEEvaluationAccess<dim,dim,Number> : public FEEvaluationBase<dim,dim,Number>
1101 {
1102 public:
1103  typedef Number number_type;
1106  static const unsigned int dimension = dim;
1107  static const unsigned int n_components = dim;
1109 
1114  gradient_type get_gradient (const unsigned int q_point) const;
1115 
1120  VectorizedArray<Number> get_divergence (const unsigned int q_point) const;
1121 
1129  get_symmetric_gradient (const unsigned int q_point) const;
1130 
1136  get_curl (const unsigned int q_point) const;
1137 
1145  get_hessian (const unsigned int q_point) const;
1146 
1151  gradient_type get_hessian_diagonal (const unsigned int q_point) const;
1152 
1161  void submit_gradient(const gradient_type grad_in,
1162  const unsigned int q_point);
1163 
1172  void submit_gradient(const Tensor<1,dim,Tensor<1,dim,VectorizedArray<Number> > > grad_in,
1173  const unsigned int q_point);
1174 
1183  void submit_divergence (const VectorizedArray<Number> div_in,
1184  const unsigned int q_point);
1185 
1194  void submit_symmetric_gradient(const SymmetricTensor<2,dim,VectorizedArray<Number> > grad_in,
1195  const unsigned int q_point);
1196 
1201  void submit_curl (const Tensor<1,dim==2?1:dim,VectorizedArray<Number> > curl_in,
1202  const unsigned int q_point);
1203 
1204 protected:
1212  FEEvaluationAccess (const MatrixFree<dim,Number> &matrix_free,
1213  const unsigned int fe_no,
1214  const unsigned int quad_no,
1215  const unsigned int dofs_per_cell,
1216  const unsigned int n_q_points);
1217 
1222  template <int n_components_other>
1223  FEEvaluationAccess (const Mapping<dim> &mapping,
1224  const FiniteElement<dim> &fe,
1225  const Quadrature<1> &quadrature,
1226  const UpdateFlags update_flags,
1227  const unsigned int first_selected_component,
1229 
1233  FEEvaluationAccess (const FEEvaluationAccess &other);
1234 };
1235 
1236 
1246 template <typename Number>
1247 class FEEvaluationAccess<1,1,Number> : public FEEvaluationBase<1,1,Number>
1248 {
1249 public:
1250  typedef Number number_type;
1251  typedef VectorizedArray<Number> value_type;
1253  static const unsigned int dimension = 1;
1255 
1265  value_type get_dof_value (const unsigned int dof) const;
1266 
1271  void submit_dof_value (const value_type val_in,
1272  const unsigned int dof);
1273 
1281  value_type get_value (const unsigned int q_point) const;
1282 
1290  void submit_value (const value_type val_in,
1291  const unsigned int q_point);
1292 
1298  gradient_type get_gradient (const unsigned int q_point) const;
1299 
1308  void submit_gradient(const gradient_type grad_in,
1309  const unsigned int q_point);
1310 
1318  get_hessian (unsigned int q_point) const;
1319 
1324  gradient_type get_hessian_diagonal (const unsigned int q_point) const;
1325 
1330  value_type get_laplacian (const unsigned int q_point) const;
1331 
1340  value_type integrate_value () const;
1341 
1342 protected:
1350  FEEvaluationAccess (const MatrixFree<1,Number> &matrix_free,
1351  const unsigned int fe_no,
1352  const unsigned int quad_no,
1353  const unsigned int fe_degree,
1354  const unsigned int n_q_points);
1355 
1360  template <int n_components_other>
1361  FEEvaluationAccess (const Mapping<1> &mapping,
1362  const FiniteElement<1> &fe,
1363  const Quadrature<1> &quadrature,
1364  const UpdateFlags update_flags,
1365  const unsigned int first_selected_component,
1367 
1371  FEEvaluationAccess (const FEEvaluationAccess &other);
1372 };
1373 
1374 
1375 
1528 template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
1529  typename Number >
1530 class FEEvaluation : public FEEvaluationAccess<dim,n_components_,Number>
1531 {
1532 public:
1534  typedef Number number_type;
1535  typedef typename BaseClass::value_type value_type;
1536  typedef typename BaseClass::gradient_type gradient_type;
1537  static const unsigned int dimension = dim;
1538  static const unsigned int n_components = n_components_;
1539  static const unsigned int n_q_points = Utilities::fixed_int_power<n_q_points_1d,dim>::value;
1540  static const unsigned int tensor_dofs_per_cell = Utilities::fixed_int_power<fe_degree+1,dim>::value;
1541 
1548  FEEvaluation (const MatrixFree<dim,Number> &matrix_free,
1549  const unsigned int fe_no = 0,
1550  const unsigned int quad_no = 0);
1551 
1578  FEEvaluation (const Mapping<dim> &mapping,
1579  const FiniteElement<dim> &fe,
1580  const Quadrature<1> &quadrature,
1581  const UpdateFlags update_flags,
1582  const unsigned int first_selected_component = 0);
1583 
1589  FEEvaluation (const FiniteElement<dim> &fe,
1590  const Quadrature<1> &quadrature,
1591  const UpdateFlags update_flags,
1592  const unsigned int first_selected_component = 0);
1593 
1604  template <int n_components_other>
1605  FEEvaluation (const FiniteElement<dim> &fe,
1607  const unsigned int first_selected_component = 0);
1608 
1615  FEEvaluation (const FEEvaluation &other);
1616 
1625  void evaluate (const bool evaluate_val,
1626  const bool evaluate_grad,
1627  const bool evaluate_hess = false);
1628 
1636  void integrate (const bool integrate_val,
1637  const bool integrate_grad);
1638 
1643  quadrature_point (const unsigned int q_point) const;
1644 
1650  const unsigned int dofs_per_cell;
1651 
1652 private:
1656  VectorizedArray<Number> my_data_array[n_components*(tensor_dofs_per_cell+1+(dim*dim+2*dim+1)*n_q_points)];
1657 
1662  void check_template_arguments(const unsigned int fe_no);
1663 
1667  void set_data_pointers();
1668 
1672  void (*evaluate_funct) (const internal::MatrixFreeFunctions::ShapeInfo<Number> &,
1673  VectorizedArray<Number> *values_dofs_actual[],
1674  VectorizedArray<Number> *values_quad[],
1675  VectorizedArray<Number> *gradients_quad[][dim],
1676  VectorizedArray<Number> *hessians_quad[][(dim*(dim+1))/2],
1677  const bool evaluate_val,
1678  const bool evaluate_grad,
1679  const bool evaluate_lapl);
1680 
1684  void (*integrate_funct)(const internal::MatrixFreeFunctions::ShapeInfo<Number> &,
1685  VectorizedArray<Number> *values_dofs_actual[],
1686  VectorizedArray<Number> *values_quad[],
1687  VectorizedArray<Number> *gradients_quad[][dim],
1688  const bool evaluate_val,
1689  const bool evaluate_grad);
1690 };
1691 
1692 
1693 
1694 namespace internal
1695 {
1696  namespace MatrixFreeFunctions
1697  {
1698  // a helper function to compute the number of DoFs of a DGP element at compile
1699  // time, depending on the degree
1700  template <int dim, int degree>
1701  struct DGP_dofs_per_cell
1702  {
1703  // this division is always without remainder
1704  static const unsigned int value =
1705  (DGP_dofs_per_cell<dim-1,degree>::value * (degree+dim)) / dim;
1706  };
1707 
1708  // base specialization: 1d elements have 'degree+1' degrees of freedom
1709  template <int degree>
1710  struct DGP_dofs_per_cell<1,degree>
1711  {
1712  static const unsigned int value = degree+1;
1713  };
1714  }
1715 }
1716 
1717 
1718 /*----------------------- Inline functions ----------------------------------*/
1719 
1720 #ifndef DOXYGEN
1721 
1722 
1723 
1724 /*----------------------- FEEvaluationBase ----------------------------------*/
1725 
1726 template <int dim, int n_components_, typename Number>
1727 inline
1730  const unsigned int fe_no_in,
1731  const unsigned int quad_no_in,
1732  const unsigned int fe_degree,
1733  const unsigned int n_q_points)
1734  :
1735  quad_no (quad_no_in),
1736  n_fe_components (data_in.get_dof_info(fe_no_in).n_components),
1737  active_fe_index (data_in.get_dof_info(fe_no_in).fe_index_from_degree
1738  (fe_degree)),
1739  active_quad_index (data_in.get_mapping_info().
1740  mapping_data_gen[quad_no_in].
1741  quad_index_from_n_q_points(n_q_points)),
1742  matrix_info (&data_in),
1743  dof_info (&data_in.get_dof_info(fe_no_in)),
1744  mapping_info (&data_in.get_mapping_info()),
1745  data (&data_in.get_shape_info
1746  (fe_no_in, quad_no_in, active_fe_index,
1747  active_quad_index)),
1748  cartesian_data (0),
1749  jacobian (0),
1750  J_value (0),
1751  quadrature_weights (mapping_info->mapping_data_gen[quad_no].
1752  quadrature_weights[active_quad_index].begin()),
1753  quadrature_points (0),
1754  jacobian_grad (0),
1755  jacobian_grad_upper(0),
1757  cell_type (internal::MatrixFreeFunctions::undefined),
1758  cell_data_number (0),
1759  first_selected_component (0)
1760 {
1761  for (unsigned int c=0; c<n_components_; ++c)
1762  {
1763  values_dofs[c] = 0;
1764  values_quad[c] = 0;
1765  for (unsigned int d=0; d<dim; ++d)
1766  gradients_quad[c][d] = 0;
1767  for (unsigned int d=0; d<(dim*dim+dim)/2; ++d)
1768  hessians_quad[c][d] = 0;
1769  }
1770  Assert (matrix_info->mapping_initialized() == true,
1771  ExcNotInitialized());
1772  AssertDimension (matrix_info->get_size_info().vectorization_length,
1775  dof_info->dofs_per_cell[active_fe_index]/n_fe_components);
1776  AssertDimension (data->n_q_points,
1777  mapping_info->mapping_data_gen[quad_no].n_q_points[active_quad_index]);
1778  Assert (n_fe_components == 1 ||
1779  n_components == 1 ||
1780  n_components == n_fe_components,
1781  ExcMessage ("The underlying FE is vector-valued. In this case, the "
1782  "template argument n_components must be a the same "
1783  "as the number of underlying vector components."));
1784 
1785 
1786  // do not check for correct dimensions of data fields here, should be done
1787  // in derived classes
1788 }
1789 
1790 
1791 
1792 template <int dim, int n_components_, typename Number>
1793 template <int n_components_other>
1794 inline
1796 ::FEEvaluationBase (const Mapping<dim> &mapping,
1797  const FiniteElement<dim> &fe,
1798  const Quadrature<1> &quadrature,
1799  const UpdateFlags update_flags,
1800  const unsigned int first_selected_component,
1802  :
1803  quad_no (-1),
1804  n_fe_components (n_components_),
1805  active_fe_index (-1),
1806  active_quad_index (-1),
1807  matrix_info (0),
1808  dof_info (0),
1809  mapping_info (0),
1810  // select the correct base element from the given FE component
1811  stored_shape_info (new internal::MatrixFreeFunctions::ShapeInfo<Number>(quadrature, fe, fe.component_to_base_index(first_selected_component).first)),
1812  data (stored_shape_info.get()),
1813  cartesian_data (0),
1814  jacobian (0),
1815  J_value (0),
1816  quadrature_weights (0),
1817  quadrature_points (0),
1818  jacobian_grad (0),
1819  jacobian_grad_upper(0),
1820  cell (0),
1821  cell_type (internal::MatrixFreeFunctions::general),
1822  cell_data_number (0),
1823  // keep the number of the selected component within the current base element
1824  // for reading dof values
1825  first_selected_component (fe.component_to_base_index(first_selected_component).second)
1826 {
1827  const unsigned int base_element_number =
1828  fe.component_to_base_index(first_selected_component).first;
1829  for (unsigned int c=0; c<n_components_; ++c)
1830  {
1831  values_dofs[c] = 0;
1832  values_quad[c] = 0;
1833  for (unsigned int d=0; d<dim; ++d)
1834  gradients_quad[c][d] = 0;
1835  for (unsigned int d=0; d<(dim*dim+dim)/2; ++d)
1836  hessians_quad[c][d] = 0;
1837  }
1838 
1839  Assert(other == 0 || other->mapped_geometry.get() != 0, ExcInternalError());
1840  if (other != 0 &&
1841  other->mapped_geometry->get_quadrature() == quadrature)
1842  mapped_geometry = other->mapped_geometry;
1843  else
1844  mapped_geometry.reset(new internal::MatrixFreeFunctions::
1845  MappingDataOnTheFly<dim,Number>(mapping, quadrature,
1846  update_flags));
1847  jacobian = mapped_geometry->get_inverse_jacobians().begin();
1848  J_value = mapped_geometry->get_JxW_values().begin();
1849  quadrature_points = mapped_geometry->get_quadrature_points().begin();
1850 
1851  Assert(fe.element_multiplicity(base_element_number) == 1 ||
1852  fe.element_multiplicity(base_element_number)-first_selected_component >= n_components_,
1853  ExcMessage("The underlying element must at least contain as many "
1854  "components as requested by this class"));
1855 }
1856 
1857 
1858 
1859 template <int dim, int n_components_, typename Number>
1860 inline
1863  :
1864  quad_no (other.quad_no),
1865  n_fe_components (other.n_fe_components),
1866  active_fe_index (other.active_fe_index),
1867  active_quad_index (other.active_quad_index),
1868  matrix_info (other.matrix_info),
1869  dof_info (other.dof_info),
1870  mapping_info (other.mapping_info),
1871  stored_shape_info (other.stored_shape_info),
1872  data (other.data),
1873  cartesian_data (other.cartesian_data),
1874  jacobian (other.jacobian),
1875  J_value (other.J_value),
1876  quadrature_weights (other.quadrature_weights),
1877  quadrature_points (other.quadrature_points),
1878  jacobian_grad (other.jacobian_grad),
1879  jacobian_grad_upper(other.jacobian_grad_upper),
1880  cell (other.cell),
1881  cell_type (other.cell_type),
1882  cell_data_number (other.cell_data_number),
1883  first_selected_component (other.first_selected_component)
1884 {
1885  for (unsigned int c=0; c<n_components_; ++c)
1886  {
1887  values_dofs[c] = 0;
1888  values_quad[c] = 0;
1889  for (unsigned int d=0; d<dim; ++d)
1890  gradients_quad[c][d] = 0;
1891  for (unsigned int d=0; d<(dim*dim+dim)/2; ++d)
1892  hessians_quad[c][d] = 0;
1893  }
1894 
1895  // Create deep copy of mapped geometry for use in parallel...
1896  if (other.mapped_geometry.get() != 0)
1897  {
1898  mapped_geometry.reset
1900  MappingDataOnTheFly<dim,Number>(other.mapped_geometry->get_fe_values().get_mapping(),
1901  other.mapped_geometry->get_quadrature(),
1902  other.mapped_geometry->get_fe_values().get_update_flags()));
1903  jacobian = mapped_geometry->get_inverse_jacobians().begin();
1904  J_value = mapped_geometry->get_JxW_values().begin();
1905  quadrature_points = mapped_geometry->get_quadrature_points().begin();
1906  }
1907 }
1908 
1909 
1910 
1911 template <int dim, int n_components_, typename Number>
1912 inline
1913 void
1914 FEEvaluationBase<dim,n_components_,Number>::reinit (const unsigned int cell_in)
1915 {
1916  Assert (mapped_geometry == 0,
1917  ExcMessage("FEEvaluation was initialized without a matrix-free object."
1918  " Integer indexing is not possible"));
1919  if (mapped_geometry != 0)
1920  return;
1921  Assert (dof_info != 0, ExcNotInitialized());
1922  Assert (mapping_info != 0, ExcNotInitialized());
1923  AssertIndexRange (cell_in, dof_info->row_starts.size()-1);
1924  AssertDimension (((dof_info->cell_active_fe_index.size() > 0) ?
1925  dof_info->cell_active_fe_index[cell_in] : 0),
1926  active_fe_index);
1927  cell = cell_in;
1928  cell_type = mapping_info->get_cell_type(cell);
1929  cell_data_number = mapping_info->get_cell_data_index(cell);
1930 
1931  if (mapping_info->quadrature_points_initialized == true)
1932  {
1933  AssertIndexRange (cell_data_number, mapping_info->
1934  mapping_data_gen[quad_no].rowstart_q_points.size());
1935  const unsigned int index = mapping_info->mapping_data_gen[quad_no].
1936  rowstart_q_points[cell];
1937  AssertIndexRange (index, mapping_info->mapping_data_gen[quad_no].
1938  quadrature_points.size());
1939  quadrature_points =
1940  &mapping_info->mapping_data_gen[quad_no].quadrature_points[index];
1941  }
1942 
1943  if (cell_type == internal::MatrixFreeFunctions::cartesian)
1944  {
1945  cartesian_data = &mapping_info->cartesian_data[cell_data_number].first;
1946  J_value = &mapping_info->cartesian_data[cell_data_number].second;
1947  }
1948  else if (cell_type == internal::MatrixFreeFunctions::affine)
1949  {
1950  jacobian = &mapping_info->affine_data[cell_data_number].first;
1951  J_value = &mapping_info->affine_data[cell_data_number].second;
1952  }
1953  else
1954  {
1955  const unsigned int rowstart = mapping_info->
1956  mapping_data_gen[quad_no].rowstart_jacobians[cell_data_number];
1957  AssertIndexRange (rowstart, mapping_info->
1958  mapping_data_gen[quad_no].jacobians.size());
1959  jacobian =
1960  &mapping_info->mapping_data_gen[quad_no].jacobians[rowstart];
1961  if (mapping_info->JxW_values_initialized == true)
1962  {
1963  AssertIndexRange (rowstart, mapping_info->
1964  mapping_data_gen[quad_no].JxW_values.size());
1965  J_value = &(mapping_info->mapping_data_gen[quad_no].
1966  JxW_values[rowstart]);
1967  }
1968  if (mapping_info->second_derivatives_initialized == true)
1969  {
1970  AssertIndexRange(rowstart, mapping_info->
1971  mapping_data_gen[quad_no].jacobians_grad_diag.size());
1972  jacobian_grad = &mapping_info->mapping_data_gen[quad_no].
1973  jacobians_grad_diag[rowstart];
1974  AssertIndexRange(rowstart, mapping_info->
1975  mapping_data_gen[quad_no].jacobians_grad_upper.size());
1976  jacobian_grad_upper = &mapping_info->mapping_data_gen[quad_no].
1977  jacobians_grad_upper[rowstart];
1978  }
1979  }
1980 
1981 #ifdef DEBUG
1982  dof_values_initialized = false;
1983  values_quad_initialized = false;
1984  gradients_quad_initialized = false;
1985  hessians_quad_initialized = false;
1986 #endif
1987 }
1988 
1989 
1990 
1991 template <int dim, int n_components_, typename Number>
1992 template <typename DoFHandlerType, bool level_dof_access>
1993 inline
1994 void
1997 {
1998  Assert(matrix_info == 0,
1999  ExcMessage("Cannot use initialization from cell iterator if "
2000  "initialized from MatrixFree object. Use variant for "
2001  "on the fly computation with arguments as for FEValues "
2002  "instead"));
2003  Assert(mapped_geometry.get() != 0, ExcNotInitialized());
2004  mapped_geometry->reinit(static_cast<typename Triangulation<dim>::cell_iterator>(cell));
2005  local_dof_indices.resize(cell->get_fe().dofs_per_cell);
2006  if (level_dof_access)
2007  cell->get_mg_dof_indices(local_dof_indices);
2008  else
2009  cell->get_dof_indices(local_dof_indices);
2010 }
2011 
2012 
2013 
2014 template <int dim, int n_components_, typename Number>
2015 inline
2016 void
2018 ::reinit (const typename Triangulation<dim>::cell_iterator &cell)
2019 {
2020  Assert(matrix_info == 0,
2021  ExcMessage("Cannot use initialization from cell iterator if "
2022  "initialized from MatrixFree object. Use variant for "
2023  "on the fly computation with arguments as for FEValues "
2024  "instead"));
2025  Assert(mapped_geometry.get() != 0, ExcNotInitialized());
2026  mapped_geometry->reinit(cell);
2027 }
2028 
2029 
2030 
2031 template <int dim, int n_components_, typename Number>
2032 inline
2033 unsigned int
2035 ::get_cell_data_number () const
2036 {
2037  Assert (cell != numbers::invalid_unsigned_int, ExcNotInitialized());
2038  return cell_data_number;
2039 }
2040 
2041 
2042 
2043 template <int dim, int n_components_, typename Number>
2044 inline
2045 internal::MatrixFreeFunctions::CellType
2047 {
2048  Assert (cell != numbers::invalid_unsigned_int, ExcNotInitialized());
2049  return cell_type;
2050 }
2051 
2052 
2053 
2054 template <int dim, int n_components_, typename Number>
2055 inline
2058 {
2059  Assert(data != 0, ExcInternalError());
2060  return *data;
2061 }
2062 
2063 
2064 
2065 template <int dim, int n_components_, typename Number>
2066 inline
2067 void
2070 {
2071  AssertDimension(JxW_values.size(), data->n_q_points);
2072  Assert (this->J_value != 0, ExcNotImplemented());
2073  if (this->cell_type == internal::MatrixFreeFunctions::cartesian ||
2074  this->cell_type == internal::MatrixFreeFunctions::affine)
2075  {
2076  Assert (this->mapping_info != 0, ExcNotImplemented());
2077  VectorizedArray<Number> J = this->J_value[0];
2078  for (unsigned int q=0; q<this->data->n_q_points; ++q)
2079  JxW_values[q] = J * this->quadrature_weights[q];
2080  }
2081  else
2082  for (unsigned int q=0; q<data->n_q_points; ++q)
2083  JxW_values[q] = this->J_value[q];
2084 }
2085 
2086 
2087 
2088 namespace internal
2089 {
2090  // write access to generic vectors that have operator ().
2091  template <typename VectorType>
2092  inline
2093  typename VectorType::value_type &
2094  vector_access (VectorType &vec,
2095  const unsigned int entry)
2096  {
2097  return vec(entry);
2098  }
2099 
2100 
2101 
2102  // read access to generic vectors that have operator ().
2103  template <typename VectorType>
2104  inline
2105  typename VectorType::value_type
2106  vector_access (const VectorType &vec,
2107  const unsigned int entry)
2108  {
2109  return vec(entry);
2110  }
2111 
2112 
2113 
2114  // write access to distributed MPI vectors that have a local_element(uint)
2115  // method to access data in local index space, which is what we use in
2116  // DoFInfo and hence in read_dof_values etc.
2117  template <typename Number>
2118  inline
2119  Number &
2120  vector_access (parallel::distributed::Vector<Number> &vec,
2121  const unsigned int entry)
2122  {
2123  return vec.local_element(entry);
2124  }
2125 
2126 
2127 
2128  // read access to distributed MPI vectors that have a local_element(uint)
2129  // method to access data in local index space, which is what we use in
2130  // DoFInfo and hence in read_dof_values etc.
2131  template <typename Number>
2132  inline
2133  Number
2134  vector_access (const parallel::distributed::Vector<Number> &vec,
2135  const unsigned int entry)
2136  {
2137  return vec.local_element(entry);
2138  }
2139 
2140 
2141 
2142  // this is to make sure that the parallel partitioning in the
2143  // parallel::distributed::Vector is really the same as stored in MatrixFree
2144  template <typename VectorType>
2145  inline
2146  void check_vector_compatibility (const VectorType &vec,
2147  const internal::MatrixFreeFunctions::DoFInfo &dof_info)
2148  {
2149  AssertDimension (vec.size(),
2150  dof_info.vector_partitioner->size());
2151  }
2152 
2153  template <typename Number>
2154  inline
2155  void check_vector_compatibility (const parallel::distributed::Vector<Number> &vec,
2156  const internal::MatrixFreeFunctions::DoFInfo &dof_info)
2157  {
2158  Assert (vec.partitioners_are_compatible(*dof_info.vector_partitioner),
2159  ExcMessage("The parallel layout of the given vector is not "
2160  "compatible with the parallel partitioning in MatrixFree. "
2161  "Use MatrixFree::initialize_dof_vector to get a "
2162  "compatible vector."));
2163  }
2164 
2165  // A class to use the same code to read from and write to vector
2166  template <typename Number>
2167  struct VectorReader
2168  {
2169  template <typename VectorType>
2170  void process_dof (const unsigned int index,
2171  VectorType &vec,
2172  Number &res) const
2173  {
2174  res = vector_access (const_cast<const VectorType &>(vec), index);
2175  }
2176 
2177  template <typename VectorType>
2178  void process_dof_global (const types::global_dof_index index,
2179  VectorType &vec,
2180  Number &res) const
2181  {
2182  res = const_cast<const VectorType &>(vec)(index);
2183  }
2184 
2185  void pre_constraints (const Number &,
2186  Number &res) const
2187  {
2188  res = Number();
2189  }
2190 
2191  template <typename VectorType>
2192  void process_constraint (const unsigned int index,
2193  const Number weight,
2194  VectorType &vec,
2195  Number &res) const
2196  {
2197  res += weight * vector_access (const_cast<const VectorType &>(vec), index);
2198  }
2199 
2200  void post_constraints (const Number &sum,
2201  Number &write_pos) const
2202  {
2203  write_pos = sum;
2204  }
2205 
2206  void process_empty (Number &res) const
2207  {
2208  res = Number();
2209  }
2210  };
2211 
2212  // A class to use the same code to read from and write to vector
2213  template <typename Number>
2214  struct VectorDistributorLocalToGlobal
2215  {
2216  template <typename VectorType>
2217  void process_dof (const unsigned int index,
2218  VectorType &vec,
2219  Number &res) const
2220  {
2221  vector_access (vec, index) += res;
2222  }
2223 
2224  template <typename VectorType>
2225  void process_dof_global (const types::global_dof_index index,
2226  VectorType &vec,
2227  Number &res) const
2228  {
2229  vec(index) += res;
2230  }
2231 
2232  void pre_constraints (const Number &input,
2233  Number &res) const
2234  {
2235  res = input;
2236  }
2237 
2238  template <typename VectorType>
2239  void process_constraint (const unsigned int index,
2240  const Number weight,
2241  VectorType &vec,
2242  Number &res) const
2243  {
2244  vector_access (vec, index) += weight * res;
2245  }
2246 
2247  void post_constraints (const Number &,
2248  Number &) const
2249  {
2250  }
2251 
2252  void process_empty (Number &) const
2253  {
2254  }
2255  };
2256 
2257 
2258  // A class to use the same code to read from and write to vector
2259  template <typename Number>
2260  struct VectorSetter
2261  {
2262  template <typename VectorType>
2263  void process_dof (const unsigned int index,
2264  VectorType &vec,
2265  Number &res) const
2266  {
2267  vector_access (vec, index) = res;
2268  }
2269 
2270  template <typename VectorType>
2271  void process_dof_global (const types::global_dof_index index,
2272  VectorType &vec,
2273  Number &res) const
2274  {
2275  vec(index) = res;
2276  }
2277 
2278  void pre_constraints (const Number &,
2279  Number &) const
2280  {
2281  }
2282 
2283  template <typename VectorType>
2284  void process_constraint (const unsigned int,
2285  const Number,
2286  VectorType &,
2287  Number &) const
2288  {
2289  }
2290 
2291  void post_constraints (const Number &,
2292  Number &) const
2293  {
2294  }
2295 
2296  void process_empty (Number &) const
2297  {
2298  }
2299  };
2300 
2301  // allows to select between block vectors and non-block vectors, which
2302  // allows to use a unified interface for extracting blocks on block vectors
2303  // and doing nothing on usual vectors
2304  template <typename VectorType, bool>
2305  struct BlockVectorSelector {};
2306 
2307  template <typename VectorType>
2308  struct BlockVectorSelector<VectorType,true>
2309  {
2310  typedef typename VectorType::BlockType BaseVectorType;
2311 
2312  static BaseVectorType *get_vector_component (VectorType &vec,
2313  const unsigned int component)
2314  {
2315  AssertIndexRange (component, vec.n_blocks());
2316  return &vec.block(component);
2317  }
2318  };
2319 
2320  template <typename VectorType>
2321  struct BlockVectorSelector<VectorType,false>
2322  {
2323  typedef VectorType BaseVectorType;
2324 
2325  static BaseVectorType *get_vector_component (VectorType &vec,
2326  const unsigned int)
2327  {
2328  return &vec;
2329  }
2330  };
2331 }
2332 
2333 
2334 
2335 template <int dim, int n_components_, typename Number>
2336 template<typename VectorType, typename VectorOperation>
2337 inline
2338 void
2340 ::read_write_operation (const VectorOperation &operation,
2341  VectorType *src[]) const
2342 {
2343  // This functions processes all the functions read_dof_values,
2344  // distribute_local_to_global, and set_dof_values with the same code. The
2345  // distinction between these three cases is made by the input
2346  // VectorOperation that either reads values from a vector and puts the data
2347  // into the local data field or write local data into the vector. Certain
2348  // operations are no-ops for the given use case.
2349 
2350  // Case 1: No MatrixFree object given, simple case because we do not need to
2351  // process constraints and need not care about vectorization
2352  if (matrix_info == 0)
2353  {
2354  Assert (!local_dof_indices.empty(), ExcNotInitialized());
2355 
2356  unsigned int index = first_selected_component * this->data->dofs_per_cell;
2357  for (unsigned int comp = 0; comp<n_components; ++comp)
2358  {
2359  for (unsigned int i=0; i<this->data->dofs_per_cell; ++i, ++index)
2360  {
2361  operation.process_dof_global(local_dof_indices[this->data->lexicographic_numbering[index]],
2362  *src[0], values_dofs[comp][i][0]);
2363  for (unsigned int v=1; v<VectorizedArray<Number>::n_array_elements; ++v)
2364  operation.process_empty(values_dofs[comp][i][v]);
2365  }
2366  }
2367  return;
2368  }
2369 
2370  Assert (dof_info != 0, ExcNotInitialized());
2371  Assert (matrix_info->indices_initialized() == true,
2372  ExcNotInitialized());
2373  Assert (cell != numbers::invalid_unsigned_int, ExcNotInitialized());
2374 
2375  // loop over all local dofs. ind_local holds local number on cell, index
2376  // iterates over the elements of index_local_to_global and dof_indices
2377  // points to the global indices stored in index_local_to_global
2378  const unsigned int *dof_indices = dof_info->begin_indices(cell);
2379  const std::pair<unsigned short,unsigned short> *indicators =
2380  dof_info->begin_indicators(cell);
2381  const std::pair<unsigned short,unsigned short> *indicators_end =
2382  dof_info->end_indicators(cell);
2383  unsigned int ind_local = 0;
2384  const unsigned int dofs_per_cell = this->data->dofs_per_cell;
2385 
2386  const unsigned int n_irreg_components_filled = dof_info->row_starts[cell][2];
2387  const bool at_irregular_cell = n_irreg_components_filled > 0;
2388 
2389  // scalar case (or case when all components have the same degrees of freedom
2390  // and sit on a different vector each)
2391  if (n_fe_components == 1)
2392  {
2393  const unsigned int n_local_dofs =
2395  for (unsigned int comp=0; comp<n_components; ++comp)
2396  internal::check_vector_compatibility (*src[comp], *dof_info);
2397  Number *local_data [n_components];
2398  for (unsigned int comp=0; comp<n_components; ++comp)
2399  local_data[comp] =
2400  const_cast<Number *>(&values_dofs[comp][0][0]);
2401 
2402  // standard case where there are sufficiently many cells to fill all
2403  // vectors
2404  if (at_irregular_cell == false)
2405  {
2406  // check whether there is any constraint on the current cell
2407  if (indicators != indicators_end)
2408  {
2409  for ( ; indicators != indicators_end; ++indicators)
2410  {
2411  // run through values up to next constraint
2412  for (unsigned int j=0; j<indicators->first; ++j)
2413  for (unsigned int comp=0; comp<n_components; ++comp)
2414  operation.process_dof (dof_indices[j], *src[comp],
2415  local_data[comp][ind_local+j]);
2416 
2417  ind_local += indicators->first;
2418  dof_indices += indicators->first;
2419 
2420  // constrained case: build the local value as a linear
2421  // combination of the global value according to constraints
2422  Number value [n_components];
2423  for (unsigned int comp=0; comp<n_components; ++comp)
2424  operation.pre_constraints (local_data[comp][ind_local],
2425  value[comp]);
2426 
2427  const Number *data_val =
2428  matrix_info->constraint_pool_begin(indicators->second);
2429  const Number *end_pool =
2430  matrix_info->constraint_pool_end(indicators->second);
2431  for ( ; data_val != end_pool; ++data_val, ++dof_indices)
2432  for (unsigned int comp=0; comp<n_components; ++comp)
2433  operation.process_constraint (*dof_indices, *data_val,
2434  *src[comp], value[comp]);
2435 
2436  for (unsigned int comp=0; comp<n_components; ++comp)
2437  operation.post_constraints (value[comp],
2438  local_data[comp][ind_local]);
2439 
2440  ind_local++;
2441  }
2442 
2443  // get the dof values past the last constraint
2444  for (; ind_local < n_local_dofs; ++dof_indices, ++ind_local)
2445  {
2446  for (unsigned int comp=0; comp<n_components; ++comp)
2447  operation.process_dof (*dof_indices, *src[comp],
2448  local_data[comp][ind_local]);
2449  }
2450  }
2451  else
2452  {
2453  // no constraint at all: compiler can unroll at least the
2454  // vectorization loop
2455  AssertDimension (dof_info->end_indices(cell)-dof_indices,
2456  static_cast<int>(n_local_dofs));
2457  for (unsigned int j=0; j<n_local_dofs; j+=VectorizedArray<Number>::n_array_elements)
2458  for (unsigned int v=0; v<VectorizedArray<Number>::n_array_elements; ++v)
2459  for (unsigned int comp=0; comp<n_components; ++comp)
2460  operation.process_dof (dof_indices[j+v], *src[comp],
2461  local_data[comp][j+v]);
2462  }
2463  }
2464 
2465  // non-standard case: need to fill in zeros for those components that
2466  // are not present (a bit more expensive), but there is not more than
2467  // one such cell
2468  else
2469  {
2470  Assert (n_irreg_components_filled > 0, ExcInternalError());
2471  for ( ; indicators != indicators_end; ++indicators)
2472  {
2473  for (unsigned int j=0; j<indicators->first; ++j)
2474  {
2475  // non-constrained case: copy the data from the global
2476  // vector, src, to the local one, local_src.
2477  for (unsigned int comp=0; comp<n_components; ++comp)
2478  operation.process_dof (dof_indices[j], *src[comp],
2479  local_data[comp][ind_local]);
2480 
2481  // here we jump over all the components that are artificial
2482  ++ind_local;
2484  >= n_irreg_components_filled)
2485  {
2486  for (unsigned int comp=0; comp<n_components; ++comp)
2487  operation.process_empty (local_data[comp][ind_local]);
2488  ++ind_local;
2489  }
2490  }
2491  dof_indices += indicators->first;
2492 
2493  // constrained case: build the local value as a linear
2494  // combination of the global value according to constraint
2495  Number value [n_components];
2496  for (unsigned int comp=0; comp<n_components; ++comp)
2497  operation.pre_constraints (local_data[comp][ind_local],
2498  value[comp]);
2499 
2500  const Number *data_val =
2501  matrix_info->constraint_pool_begin(indicators->second);
2502  const Number *end_pool =
2503  matrix_info->constraint_pool_end(indicators->second);
2504 
2505  for ( ; data_val != end_pool; ++data_val, ++dof_indices)
2506  for (unsigned int comp=0; comp<n_components; ++comp)
2507  operation.process_constraint (*dof_indices, *data_val,
2508  *src[comp], value[comp]);
2509 
2510  for (unsigned int comp=0; comp<n_components; ++comp)
2511  operation.post_constraints (value[comp],
2512  local_data[comp][ind_local]);
2513  ind_local++;
2515  >= n_irreg_components_filled)
2516  {
2517  for (unsigned int comp=0; comp<n_components; ++comp)
2518  operation.process_empty (local_data[comp][ind_local]);
2519  ++ind_local;
2520  }
2521  }
2522  for (; ind_local<n_local_dofs; ++dof_indices)
2523  {
2524  Assert (dof_indices != dof_info->end_indices(cell),
2525  ExcInternalError());
2526 
2527  // non-constrained case: copy the data from the global vector,
2528  // src, to the local one, local_dst.
2529  for (unsigned int comp=0; comp<n_components; ++comp)
2530  operation.process_dof (*dof_indices, *src[comp],
2531  local_data[comp][ind_local]);
2532  ++ind_local;
2534  >= n_irreg_components_filled)
2535  {
2536  for (unsigned int comp=0; comp<n_components; ++comp)
2537  operation.process_empty(local_data[comp][ind_local]);
2538  ++ind_local;
2539  }
2540  }
2541  }
2542  }
2543  else
2544  // case with vector-valued finite elements where all components are
2545  // included in one single vector. Assumption: first come all entries to
2546  // the first component, then all entries to the second one, and so
2547  // on. This is ensured by the way MatrixFree reads out the indices.
2548  {
2549  internal::check_vector_compatibility (*src[0], *dof_info);
2550  Assert (n_fe_components == n_components_, ExcNotImplemented());
2551  const unsigned int n_local_dofs =
2552  dofs_per_cell*VectorizedArray<Number>::n_array_elements * n_components;
2553  Number *local_data =
2554  const_cast<Number *>(&values_dofs[0][0][0]);
2555  if (at_irregular_cell == false)
2556  {
2557  // check whether there is any constraint on the current cell
2558  if (indicators != indicators_end)
2559  {
2560  for ( ; indicators != indicators_end; ++indicators)
2561  {
2562  // run through values up to next constraint
2563  for (unsigned int j=0; j<indicators->first; ++j)
2564  operation.process_dof (dof_indices[j], *src[0],
2565  local_data[ind_local+j]);
2566  ind_local += indicators->first;
2567  dof_indices += indicators->first;
2568 
2569  // constrained case: build the local value as a linear
2570  // combination of the global value according to constraints
2571  Number value;
2572  operation.pre_constraints (local_data[ind_local], value);
2573 
2574  const Number *data_val =
2575  matrix_info->constraint_pool_begin(indicators->second);
2576  const Number *end_pool =
2577  matrix_info->constraint_pool_end(indicators->second);
2578 
2579  for ( ; data_val != end_pool; ++data_val, ++dof_indices)
2580  operation.process_constraint (*dof_indices, *data_val,
2581  *src[0], value);
2582 
2583  operation.post_constraints (value, local_data[ind_local]);
2584  ind_local++;
2585  }
2586 
2587  // get the dof values past the last constraint
2588  for (; ind_local<n_local_dofs; ++dof_indices, ++ind_local)
2589  operation.process_dof (*dof_indices, *src[0],
2590  local_data[ind_local]);
2591  Assert (dof_indices == dof_info->end_indices(cell),
2592  ExcInternalError());
2593  }
2594  else
2595  {
2596  // no constraint at all: compiler can unroll at least the
2597  // vectorization loop
2598  AssertDimension (dof_info->end_indices(cell)-dof_indices,
2599  static_cast<int>(n_local_dofs));
2600  for (unsigned int j=0; j<n_local_dofs; j+=VectorizedArray<Number>::n_array_elements)
2601  for (unsigned int v=0; v<VectorizedArray<Number>::n_array_elements; ++v)
2602  operation.process_dof (dof_indices[j+v], *src[0],
2603  local_data[j+v]);
2604  }
2605  }
2606 
2607  // non-standard case: need to fill in zeros for those components that
2608  // are not present (a bit more expensive), but there is not more than
2609  // one such cell
2610  else
2611  {
2612  Assert (n_irreg_components_filled > 0, ExcInternalError());
2613  for ( ; indicators != indicators_end; ++indicators)
2614  {
2615  for (unsigned int j=0; j<indicators->first; ++j)
2616  {
2617  // non-constrained case: copy the data from the global
2618  // vector, src, to the local one, local_src.
2619  operation.process_dof (dof_indices[j], *src[0],
2620  local_data[ind_local]);
2621 
2622  // here we jump over all the components that are artificial
2623  ++ind_local;
2625  >= n_irreg_components_filled)
2626  {
2627  operation.process_empty (local_data[ind_local]);
2628  ++ind_local;
2629  }
2630  }
2631  dof_indices += indicators->first;
2632 
2633  // constrained case: build the local value as a linear
2634  // combination of the global value according to constraint
2635  Number value;
2636  operation.pre_constraints (local_data[ind_local], value);
2637 
2638  const Number *data_val =
2639  matrix_info->constraint_pool_begin(indicators->second);
2640  const Number *end_pool =
2641  matrix_info->constraint_pool_end(indicators->second);
2642 
2643  for ( ; data_val != end_pool; ++data_val, ++dof_indices)
2644  operation.process_constraint (*dof_indices, *data_val,
2645  *src[0], value);
2646 
2647  operation.post_constraints (value, local_data[ind_local]);
2648  ind_local++;
2650  >= n_irreg_components_filled)
2651  {
2652  operation.process_empty (local_data[ind_local]);
2653  ++ind_local;
2654  }
2655  }
2656  for (; ind_local<n_local_dofs; ++dof_indices)
2657  {
2658  Assert (dof_indices != dof_info->end_indices(cell),
2659  ExcInternalError());
2660 
2661  // non-constrained case: copy the data from the global vector,
2662  // src, to the local one, local_dst.
2663  operation.process_dof (*dof_indices, *src[0],
2664  local_data[ind_local]);
2665  ++ind_local;
2667  >= n_irreg_components_filled)
2668  {
2669  operation.process_empty (local_data[ind_local]);
2670  ++ind_local;
2671  }
2672  }
2673  }
2674  }
2675 }
2676 
2677 
2678 
2679 template <int dim, int n_components_, typename Number>
2680 template<typename VectorType>
2681 inline
2682 void
2684 ::read_dof_values (const VectorType &src)
2685 {
2686  // select between block vectors and non-block vectors. Note that the number
2687  // of components is checked in the internal data
2688  typename internal::BlockVectorSelector<VectorType,
2689  IsBlockVector<VectorType>::value>::BaseVectorType *src_data[n_components];
2690  for (unsigned int d=0; d<n_components; ++d)
2691  src_data[d] = internal::BlockVectorSelector<VectorType, IsBlockVector<VectorType>::value>::get_vector_component(const_cast<VectorType &>(src), d);
2692 
2693  internal::VectorReader<Number> reader;
2694  read_write_operation (reader, src_data);
2695 
2696 #ifdef DEBUG
2697  dof_values_initialized = true;
2698 #endif
2699 }
2700 
2701 
2702 
2703 template <int dim, int n_components_, typename Number>
2704 template<typename VectorType>
2705 inline
2706 void
2708 ::read_dof_values (const std::vector<VectorType> &src,
2709  const unsigned int first_index)
2710 {
2711  AssertIndexRange (first_index, src.size());
2712  Assert (n_fe_components == 1, ExcNotImplemented());
2713  Assert ((n_fe_components == 1 ?
2714  (first_index+n_components <= src.size()) : true),
2715  ExcIndexRange (first_index + n_components_, 0, src.size()));
2716 
2717  VectorType *src_data [n_components];
2718  for (unsigned int comp=0; comp<n_components; ++comp)
2719  src_data[comp] = const_cast<VectorType *>(&src[comp+first_index]);
2720 
2721  internal::VectorReader<Number> reader;
2722  read_write_operation (reader, src_data);
2723 
2724 #ifdef DEBUG
2725  dof_values_initialized = true;
2726 #endif
2727 }
2728 
2729 
2730 
2731 template <int dim, int n_components_, typename Number>
2732 template<typename VectorType>
2733 inline
2734 void
2736 ::read_dof_values (const std::vector<VectorType *> &src,
2737  const unsigned int first_index)
2738 {
2739  AssertIndexRange (first_index, src.size());
2740  Assert (n_fe_components == 1, ExcNotImplemented());
2741  Assert ((n_fe_components == 1 ?
2742  (first_index+n_components <= src.size()) : true),
2743  ExcIndexRange (first_index + n_components_, 0, src.size()));
2744 
2745  const VectorType *src_data [n_components];
2746  for (unsigned int comp=0; comp<n_components; ++comp)
2747  src_data[comp] = const_cast<VectorType *>(src[comp+first_index]);
2748 
2749  internal::VectorReader<Number> reader;
2750  read_write_operation (reader, src_data);
2751 
2752 #ifdef DEBUG
2753  dof_values_initialized = true;
2754 #endif
2755 }
2756 
2757 
2758 
2759 template <int dim, int n_components_, typename Number>
2760 template<typename VectorType>
2761 inline
2762 void
2764 ::read_dof_values_plain (const VectorType &src)
2765 {
2766  // select between block vectors and non-block vectors. Note that the number
2767  // of components is checked in the internal data
2768  const typename internal::BlockVectorSelector<VectorType,
2769  IsBlockVector<VectorType>::value>::BaseVectorType *src_data[n_components];
2770  for (unsigned int d=0; d<n_components; ++d)
2771  src_data[d] = internal::BlockVectorSelector<VectorType, IsBlockVector<VectorType>::value>::get_vector_component(const_cast<VectorType &>(src), d);
2772 
2773  read_dof_values_plain (src_data);
2774 }
2775 
2776 
2777 
2778 template <int dim, int n_components_, typename Number>
2779 template<typename VectorType>
2780 inline
2781 void
2783 ::read_dof_values_plain (const std::vector<VectorType> &src,
2784  const unsigned int first_index)
2785 {
2786  AssertIndexRange (first_index, src.size());
2787  Assert (n_fe_components == 1, ExcNotImplemented());
2788  Assert ((n_fe_components == 1 ?
2789  (first_index+n_components <= src.size()) : true),
2790  ExcIndexRange (first_index + n_components_, 0, src.size()));
2791  const VectorType *src_data [n_components];
2792  for (unsigned int comp=0; comp<n_components; ++comp)
2793  src_data[comp] = &src[comp+first_index];
2794  read_dof_values_plain (src_data);
2795 }
2796 
2797 
2798 
2799 template <int dim, int n_components_, typename Number>
2800 template<typename VectorType>
2801 inline
2802 void
2804 ::read_dof_values_plain (const std::vector<VectorType *> &src,
2805  const unsigned int first_index)
2806 {
2807  AssertIndexRange (first_index, src.size());
2808  Assert (n_fe_components == 1, ExcNotImplemented());
2809  Assert ((n_fe_components == 1 ?
2810  (first_index+n_components <= src.size()) : true),
2811  ExcIndexRange (first_index + n_components_, 0, src.size()));
2812  const VectorType *src_data [n_components];
2813  for (unsigned int comp=0; comp<n_components; ++comp)
2814  src_data[comp] = src[comp+first_index];
2815  read_dof_values_plain (src_data);
2816 }
2817 
2818 
2819 
2820 template <int dim, int n_components_, typename Number>
2821 template<typename VectorType>
2822 inline
2823 void
2825 ::distribute_local_to_global (VectorType &dst) const
2826 {
2827  Assert (dof_values_initialized==true,
2828  internal::ExcAccessToUninitializedField());
2829 
2830  // select between block vectors and non-block vectors. Note that the number
2831  // of components is checked in the internal data
2832  typename internal::BlockVectorSelector<VectorType,
2833  IsBlockVector<VectorType>::value>::BaseVectorType *dst_data[n_components];
2834  for (unsigned int d=0; d<n_components; ++d)
2835  dst_data[d] = internal::BlockVectorSelector<VectorType, IsBlockVector<VectorType>::value>::get_vector_component(dst, d);
2836 
2837  internal::VectorDistributorLocalToGlobal<Number> distributor;
2838  read_write_operation (distributor, dst_data);
2839 }
2840 
2841 
2842 
2843 template <int dim, int n_components_, typename Number>
2844 template<typename VectorType>
2845 inline
2846 void
2848 ::distribute_local_to_global (std::vector<VectorType> &dst,
2849  const unsigned int first_index) const
2850 {
2851  AssertIndexRange (first_index, dst.size());
2852  Assert (n_fe_components == 1, ExcNotImplemented());
2853  Assert ((n_fe_components == 1 ?
2854  (first_index+n_components <= dst.size()) : true),
2855  ExcIndexRange (first_index + n_components_, 0, dst.size()));
2856  Assert (dof_values_initialized==true,
2857  internal::ExcAccessToUninitializedField());
2858 
2859  VectorType *dst_data [n_components];
2860  for (unsigned int comp=0; comp<n_components; ++comp)
2861  dst_data[comp] = &dst[comp+first_index];
2862 
2863  internal::VectorDistributorLocalToGlobal<Number> distributor;
2864  read_write_operation (distributor, dst_data);
2865 }
2866 
2867 
2868 
2869 template <int dim, int n_components_, typename Number>
2870 template<typename VectorType>
2871 inline
2872 void
2874 ::distribute_local_to_global (std::vector<VectorType *> &dst,
2875  const unsigned int first_index) const
2876 {
2877  AssertIndexRange (first_index, dst.size());
2878  Assert (n_fe_components == 1, ExcNotImplemented());
2879  Assert ((n_fe_components == 1 ?
2880  (first_index+n_components <= dst.size()) : true),
2881  ExcIndexRange (first_index + n_components_, 0, dst.size()));
2882  Assert (dof_values_initialized==true,
2883  internal::ExcAccessToUninitializedField());
2884 
2885  VectorType *dst_data [n_components];
2886  for (unsigned int comp=0; comp<n_components; ++comp)
2887  dst_data[comp] = dst[comp+first_index];
2888 
2889  internal::VectorDistributorLocalToGlobal<Number> distributor;
2890  read_write_operation (distributor, dst_data);
2891 }
2892 
2893 
2894 
2895 template <int dim, int n_components_, typename Number>
2896 template<typename VectorType>
2897 inline
2898 void
2900 ::set_dof_values (VectorType &dst) const
2901 {
2902  Assert (dof_values_initialized==true,
2903  internal::ExcAccessToUninitializedField());
2904 
2905  // select between block vectors and non-block vectors. Note that the number
2906  // of components is checked in the internal data
2907  typename internal::BlockVectorSelector<VectorType,
2908  IsBlockVector<VectorType>::value>::BaseVectorType *dst_data[n_components];
2909  for (unsigned int d=0; d<n_components; ++d)
2910  dst_data[d] = internal::BlockVectorSelector<VectorType, IsBlockVector<VectorType>::value>::get_vector_component(dst, d);
2911 
2912  internal::VectorSetter<Number> setter;
2913  read_write_operation (setter, dst_data);
2914 }
2915 
2916 
2917 
2918 template <int dim, int n_components_, typename Number>
2919 template<typename VectorType>
2920 inline
2921 void
2923 ::set_dof_values (std::vector<VectorType> &dst,
2924  const unsigned int first_index) const
2925 {
2926  AssertIndexRange (first_index, dst.size());
2927  Assert (n_fe_components == 1, ExcNotImplemented());
2928  Assert ((n_fe_components == 1 ?
2929  (first_index+n_components <= dst.size()) : true),
2930  ExcIndexRange (first_index + n_components_, 0, dst.size()));
2931 
2932  Assert (dof_values_initialized==true,
2933  internal::ExcAccessToUninitializedField());
2934 
2935  VectorType *dst_data [n_components];
2936  for (unsigned int comp=0; comp<n_components; ++comp)
2937  dst_data[comp] = &dst[comp+first_index];
2938 
2939  internal::VectorSetter<Number> setter;
2940  read_write_operation (setter, dst_data);
2941 }
2942 
2943 
2944 
2945 template <int dim, int n_components_, typename Number>
2946 template<typename VectorType>
2947 inline
2948 void
2950 ::set_dof_values (std::vector<VectorType *> &dst,
2951  const unsigned int first_index) const
2952 {
2953  AssertIndexRange (first_index, dst.size());
2954  Assert (n_fe_components == 1, ExcNotImplemented());
2955  Assert ((n_fe_components == 1 ?
2956  (first_index+n_components <= dst.size()) : true),
2957  ExcIndexRange (first_index + n_components_, 0, dst.size()));
2958 
2959  Assert (dof_values_initialized==true,
2960  internal::ExcAccessToUninitializedField());
2961 
2962  VectorType *dst_data [n_components];
2963  for (unsigned int comp=0; comp<n_components; ++comp)
2964  dst_data[comp] = dst[comp+first_index];
2965 
2966  internal::VectorSetter<Number> setter;
2967  read_write_operation (setter, dst_data);
2968 }
2969 
2970 
2971 
2972 template <int dim, int n_components_, typename Number>
2973 template<typename VectorType>
2974 inline
2975 void
2977 ::read_dof_values_plain (const VectorType *src[])
2978 {
2979  // Case without MatrixFree initialization object
2980  if (matrix_info == 0)
2981  {
2982  internal::VectorReader<Number> reader;
2983  read_write_operation (reader, src);
2984  return;
2985  }
2986 
2987  // this is different from the other three operations because we do not use
2988  // constraints here, so this is a separate function.
2989  Assert (dof_info != 0, ExcNotInitialized());
2990  Assert (matrix_info->indices_initialized() == true,
2991  ExcNotInitialized());
2992  Assert (cell != numbers::invalid_unsigned_int, ExcNotInitialized());
2993  Assert (dof_info->store_plain_indices == true, ExcNotInitialized());
2994 
2995  // loop over all local dofs. ind_local holds local number on cell, index
2996  // iterates over the elements of index_local_to_global and dof_indices
2997  // points to the global indices stored in index_local_to_global
2998  const unsigned int *dof_indices = dof_info->begin_indices_plain(cell);
2999  const unsigned int dofs_per_cell = this->data->dofs_per_cell;
3000 
3001  const unsigned int n_irreg_components_filled = dof_info->row_starts[cell][2];
3002  const bool at_irregular_cell = n_irreg_components_filled > 0;
3003 
3004  // scalar case (or case when all components have the same degrees of freedom
3005  // and sit on a different vector each)
3006  if (n_fe_components == 1)
3007  {
3008  const unsigned int n_local_dofs =
3010  for (unsigned int comp=0; comp<n_components; ++comp)
3011  internal::check_vector_compatibility (*src[comp], *dof_info);
3012  Number *local_src_number [n_components];
3013  for (unsigned int comp=0; comp<n_components; ++comp)
3014  local_src_number[comp] = &values_dofs[comp][0][0];
3015 
3016  // standard case where there are sufficiently many cells to fill all
3017  // vectors
3018  if (at_irregular_cell == false)
3019  {
3020  for (unsigned int j=0; j<n_local_dofs; ++j)
3021  for (unsigned int comp=0; comp<n_components; ++comp)
3022  local_src_number[comp][j] =
3023  internal::vector_access (*src[comp], dof_indices[j]);
3024  }
3025 
3026  // non-standard case: need to fill in zeros for those components that
3027  // are not present (a bit more expensive), but there is not more than
3028  // one such cell
3029  else
3030  {
3031  Assert (n_irreg_components_filled > 0, ExcInternalError());
3032  for (unsigned int ind_local=0; ind_local<n_local_dofs;
3033  ++dof_indices)
3034  {
3035  // non-constrained case: copy the data from the global vector,
3036  // src, to the local one, local_dst.
3037  for (unsigned int comp=0; comp<n_components; ++comp)
3038  local_src_number[comp][ind_local] =
3039  internal::vector_access (*src[comp], *dof_indices);
3040  ++ind_local;
3041  while (ind_local % VectorizedArray<Number>::n_array_elements >= n_irreg_components_filled)
3042  {
3043  for (unsigned int comp=0; comp<n_components; ++comp)
3044  local_src_number[comp][ind_local] = 0.;
3045  ++ind_local;
3046  }
3047  }
3048  }
3049  }
3050  else
3051  // case with vector-valued finite elements where all components are
3052  // included in one single vector. Assumption: first come all entries to
3053  // the first component, then all entries to the second one, and so
3054  // on. This is ensured by the way MatrixFree reads out the indices.
3055  {
3056  internal::check_vector_compatibility (*src[0], *dof_info);
3057  Assert (n_fe_components == n_components_, ExcNotImplemented());
3058  const unsigned int n_local_dofs =
3059  dofs_per_cell * VectorizedArray<Number>::n_array_elements * n_components;
3060  Number *local_src_number = &values_dofs[0][0][0];
3061  if (at_irregular_cell == false)
3062  {
3063  for (unsigned int j=0; j<n_local_dofs; ++j)
3064  local_src_number[j] =
3065  internal::vector_access (*src[0], dof_indices[j]);
3066  }
3067 
3068  // non-standard case: need to fill in zeros for those components that
3069  // are not present (a bit more expensive), but there is not more than
3070  // one such cell
3071  else
3072  {
3073  Assert (n_irreg_components_filled > 0, ExcInternalError());
3074  for (unsigned int ind_local=0; ind_local<n_local_dofs; ++dof_indices)
3075  {
3076  // non-constrained case: copy the data from the global vector,
3077  // src, to the local one, local_dst.
3078  local_src_number[ind_local] =
3079  internal::vector_access (*src[0], *dof_indices);
3080  ++ind_local;
3081  while (ind_local % VectorizedArray<Number>::n_array_elements >= n_irreg_components_filled)
3082  {
3083  local_src_number[ind_local] = 0.;
3084  ++ind_local;
3085  }
3086  }
3087  }
3088  }
3089 
3090 #ifdef DEBUG
3091  dof_values_initialized = true;
3092 #endif
3093 }
3094 
3095 
3096 
3097 
3098 /*------------------------------ access to data fields ----------------------*/
3099 
3100 template <int dim, int n_components, typename Number>
3101 inline
3102 const std::vector<unsigned int> &
3105 {
3106  return data->lexicographic_numbering;
3107 }
3108 
3109 
3110 
3111 
3112 template <int dim, int n_components, typename Number>
3113 inline
3116 begin_dof_values () const
3117 {
3118  return &values_dofs[0][0];
3119 }
3120 
3121 
3122 
3123 template <int dim, int n_components, typename Number>
3124 inline
3128 {
3129 #ifdef DEBUG
3130  dof_values_initialized = true;
3131 #endif
3132  return &values_dofs[0][0];
3133 }
3134 
3135 
3136 
3137 template <int dim, int n_components, typename Number>
3138 inline
3141 begin_values () const
3142 {
3143  Assert (values_quad_initialized || values_quad_submitted,
3144  ExcNotInitialized());
3145  return &values_quad[0][0];
3146 }
3147 
3148 
3149 
3150 template <int dim, int n_components, typename Number>
3151 inline
3154 begin_values ()
3155 {
3156 #ifdef DEBUG
3157  values_quad_submitted = true;
3158 #endif
3159  return &values_quad[0][0];
3160 }
3161 
3162 
3163 
3164 template <int dim, int n_components, typename Number>
3165 inline
3168 begin_gradients () const
3169 {
3170  Assert (gradients_quad_initialized || gradients_quad_submitted,
3171  ExcNotInitialized());
3172  return &gradients_quad[0][0][0];
3173 }
3174 
3175 
3176 
3177 template <int dim, int n_components, typename Number>
3178 inline
3181 begin_gradients ()
3182 {
3183 #ifdef DEBUG
3184  gradients_quad_submitted = true;
3185 #endif
3186  return &gradients_quad[0][0][0];
3187 }
3188 
3189 
3190 
3191 template <int dim, int n_components, typename Number>
3192 inline
3195 begin_hessians () const
3196 {
3197  Assert (hessians_quad_initialized, ExcNotInitialized());
3198  return &hessians_quad[0][0][0];
3199 }
3200 
3201 
3202 
3203 template <int dim, int n_components, typename Number>
3204 inline
3207 begin_hessians ()
3208 {
3209  return &hessians_quad[0][0][0];
3210 }
3211 
3212 
3213 
3214 template <int dim, int n_components_, typename Number>
3215 inline
3218 ::get_dof_value (const unsigned int dof) const
3219 {
3220  AssertIndexRange (dof, this->data->dofs_per_cell);
3222  for (unsigned int comp=0; comp<n_components; comp++)
3223  return_value[comp] = this->values_dofs[comp][dof];
3224  return return_value;
3225 }
3226 
3227 
3228 
3229 template <int dim, int n_components_, typename Number>
3230 inline
3233 ::get_value (const unsigned int q_point) const
3234 {
3235  Assert (this->values_quad_initialized==true,
3236  internal::ExcAccessToUninitializedField());
3237  AssertIndexRange (q_point, this->data->n_q_points);
3239  for (unsigned int comp=0; comp<n_components; comp++)
3240  return_value[comp] = this->values_quad[comp][q_point];
3241  return return_value;
3242 }
3243 
3244 
3245 
3246 template <int dim, int n_components_, typename Number>
3247 inline
3250 ::get_gradient (const unsigned int q_point) const
3251 {
3252  Assert (this->gradients_quad_initialized==true,
3253  internal::ExcAccessToUninitializedField());
3254  AssertIndexRange (q_point, this->data->n_q_points);
3255 
3257 
3258  // Cartesian cell
3259  if (this->cell_type == internal::MatrixFreeFunctions::cartesian)
3260  {
3261  for (unsigned int comp=0; comp<n_components; comp++)
3262  for (unsigned int d=0; d<dim; ++d)
3263  grad_out[comp][d] = (this->gradients_quad[comp][d][q_point] *
3264  cartesian_data[0][d]);
3265  }
3266  // cell with general/affine Jacobian
3267  else
3268  {
3270  this->cell_type == internal::MatrixFreeFunctions::general ?
3271  jacobian[q_point] : jacobian[0];
3272  for (unsigned int comp=0; comp<n_components; comp++)
3273  {
3274  for (unsigned int d=0; d<dim; ++d)
3275  {
3276  grad_out[comp][d] = (jac[d][0] *
3277  this->gradients_quad[comp][0][q_point]);
3278  for (unsigned int e=1; e<dim; ++e)
3279  grad_out[comp][d] += (jac[d][e] *
3280  this->gradients_quad[comp][e][q_point]);
3281  }
3282  }
3283  }
3284  return grad_out;
3285 }
3286 
3287 
3288 
3289 namespace internal
3290 {
3291  // compute tmp = hess_unit(u) * J^T. do this manually because we do not
3292  // store the lower diagonal because of symmetry
3293  template <typename Number>
3294  inline
3295  void
3296  hessian_unit_times_jac (const Tensor<2,1,VectorizedArray<Number> > &jac,
3297  const VectorizedArray<Number> *const hessians_quad[1],
3298  const unsigned int q_point,
3299  VectorizedArray<Number> (&tmp)[1][1])
3300  {
3301  tmp[0][0] = jac[0][0] * hessians_quad[0][q_point];
3302  }
3303 
3304  template <typename Number>
3305  inline
3306  void
3307  hessian_unit_times_jac (const Tensor<2,2,VectorizedArray<Number> > &jac,
3308  const VectorizedArray<Number> *const hessians_quad[3],
3309  const unsigned int q_point,
3310  VectorizedArray<Number> (&tmp)[2][2])
3311  {
3312  for (unsigned int d=0; d<2; ++d)
3313  {
3314  tmp[0][d] = (jac[d][0] * hessians_quad[0][q_point] +
3315  jac[d][1] * hessians_quad[2][q_point]);
3316  tmp[1][d] = (jac[d][0] * hessians_quad[2][q_point] +
3317  jac[d][1] * hessians_quad[1][q_point]);
3318  }
3319  }
3320 
3321  template <typename Number>
3322  inline
3323  void
3324  hessian_unit_times_jac (const Tensor<2,3,VectorizedArray<Number> > &jac,
3325  const VectorizedArray<Number> *const hessians_quad[6],
3326  const unsigned int q_point,
3327  VectorizedArray<Number> (&tmp)[3][3])
3328  {
3329  for (unsigned int d=0; d<3; ++d)
3330  {
3331  tmp[0][d] = (jac[d][0] * hessians_quad[0][q_point] +
3332  jac[d][1] * hessians_quad[3][q_point] +
3333  jac[d][2] * hessians_quad[4][q_point]);
3334  tmp[1][d] = (jac[d][0] * hessians_quad[3][q_point] +
3335  jac[d][1] * hessians_quad[1][q_point] +
3336  jac[d][2] * hessians_quad[5][q_point]);
3337  tmp[2][d] = (jac[d][0] * hessians_quad[4][q_point] +
3338  jac[d][1] * hessians_quad[5][q_point] +
3339  jac[d][2] * hessians_quad[2][q_point]);
3340  }
3341  }
3342 }
3343 
3344 
3345 
3346 template <int dim, int n_components_, typename Number>
3347 inline
3350 ::get_hessian (const unsigned int q_point) const
3351 {
3352  Assert (this->hessians_quad_initialized==true,
3353  internal::ExcAccessToUninitializedField());
3354  AssertIndexRange (q_point, this->data->n_q_points);
3355 
3356  Tensor<2,dim,VectorizedArray<Number> > hessian_out [n_components];
3357 
3358  // Cartesian cell
3359  if (this->cell_type == internal::MatrixFreeFunctions::cartesian)
3360  {
3361  const Tensor<1,dim,VectorizedArray<Number> > &jac = cartesian_data[0];
3362  for (unsigned int comp=0; comp<n_components; comp++)
3363  for (unsigned int d=0; d<dim; ++d)
3364  {
3365  hessian_out[comp][d][d] = (this->hessians_quad[comp][d][q_point] *
3366  jac[d] * jac[d]);
3367  switch (dim)
3368  {
3369  case 1:
3370  break;
3371  case 2:
3372  hessian_out[comp][0][1] = (this->hessians_quad[comp][2][q_point] *
3373  jac[0] * jac[1]);
3374  break;
3375  case 3:
3376  hessian_out[comp][0][1] = (this->hessians_quad[comp][3][q_point] *
3377  jac[0] * jac[1]);
3378  hessian_out[comp][0][2] = (this->hessians_quad[comp][4][q_point] *
3379  jac[0] * jac[2]);
3380  hessian_out[comp][1][2] = (this->hessians_quad[comp][5][q_point] *
3381  jac[1] * jac[2]);
3382  break;
3383  default:
3384  Assert (false, ExcNotImplemented());
3385  }
3386  for (unsigned int e=d+1; e<dim; ++e)
3387  hessian_out[comp][e][d] = hessian_out[comp][d][e];
3388  }
3389  }
3390  // cell with general Jacobian
3391  else if (this->cell_type == internal::MatrixFreeFunctions::general)
3392  {
3393  Assert (this->mapping_info->second_derivatives_initialized == true,
3394  ExcNotInitialized());
3395  const Tensor<2,dim,VectorizedArray<Number> > &jac = jacobian[q_point];
3396  const Tensor<2,dim,VectorizedArray<Number> > &jac_grad = jacobian_grad[q_point];
3397  const Tensor<1,(dim>1?dim*(dim-1)/2:1),
3399  & jac_grad_UT = jacobian_grad_upper[q_point];
3400  for (unsigned int comp=0; comp<n_components; comp++)
3401  {
3402  // compute laplacian before the gradient because it needs to access
3403  // unscaled gradient data
3404  VectorizedArray<Number> tmp[dim][dim];
3405  internal::hessian_unit_times_jac (jac, this->hessians_quad[comp],
3406  q_point, tmp);
3407 
3408  // compute first part of hessian, J * tmp = J * hess_unit(u) * J^T
3409  for (unsigned int d=0; d<dim; ++d)
3410  for (unsigned int e=d; e<dim; ++e)
3411  {
3412  hessian_out[comp][d][e] = jac[d][0] * tmp[0][e];
3413  for (unsigned int f=1; f<dim; ++f)
3414  hessian_out[comp][d][e] += jac[d][f] * tmp[f][e];
3415  }
3416 
3417  // add diagonal part of J' * grad(u)
3418  for (unsigned int d=0; d<dim; ++d)
3419  for (unsigned int e=0; e<dim; ++e)
3420  hessian_out[comp][d][d] += (jac_grad[d][e] *
3421  this->gradients_quad[comp][e][q_point]);
3422 
3423  // add off-diagonal part of J' * grad(u)
3424  for (unsigned int d=0, count=0; d<dim; ++d)
3425  for (unsigned int e=d+1; e<dim; ++e, ++count)
3426  for (unsigned int f=0; f<dim; ++f)
3427  hessian_out[comp][d][e] += (jac_grad_UT[count][f] *
3428  this->gradients_quad[comp][f][q_point]);
3429 
3430  // take symmetric part
3431  for (unsigned int d=0; d<dim; ++d)
3432  for (unsigned int e=d+1; e<dim; ++e)
3433  hessian_out[comp][e][d] = hessian_out[comp][d][e];
3434  }
3435  }
3436  // cell with general Jacobian, but constant within the cell
3437  else // if (this->cell_type == internal::MatrixFreeFunctions::affine)
3438  {
3439  const Tensor<2,dim,VectorizedArray<Number> > &jac = jacobian[0];
3440  for (unsigned int comp=0; comp<n_components; comp++)
3441  {
3442  // compute laplacian before the gradient because it needs to access
3443  // unscaled gradient data
3444  VectorizedArray<Number> tmp[dim][dim];
3445  internal::hessian_unit_times_jac (jac, this->hessians_quad[comp],
3446  q_point, tmp);
3447 
3448  // compute first part of hessian, J * tmp = J * hess_unit(u) * J^T
3449  for (unsigned int d=0; d<dim; ++d)
3450  for (unsigned int e=d; e<dim; ++e)
3451  {
3452  hessian_out[comp][d][e] = jac[d][0] * tmp[0][e];
3453  for (unsigned int f=1; f<dim; ++f)
3454  hessian_out[comp][d][e] += jac[d][f] * tmp[f][e];
3455  }
3456 
3457  // no J' * grad(u) part here because the Jacobian is constant
3458  // throughout the cell and hence, its derivative is zero
3459 
3460  // take symmetric part
3461  for (unsigned int d=0; d<dim; ++d)
3462  for (unsigned int e=d+1; e<dim; ++e)
3463  hessian_out[comp][e][d] = hessian_out[comp][d][e];
3464  }
3465  }
3467 }
3468 
3469 
3470 
3471 template <int dim, int n_components_, typename Number>
3472 inline
3475 ::get_hessian_diagonal (const unsigned int q_point) const
3476 {
3477  Assert (this->hessians_quad_initialized==true,
3478  internal::ExcAccessToUninitializedField());
3479  AssertIndexRange (q_point, this->data->n_q_points);
3480 
3482 
3483  // Cartesian cell
3484  if (this->cell_type == internal::MatrixFreeFunctions::cartesian)
3485  {
3486  const Tensor<1,dim,VectorizedArray<Number> > &jac = cartesian_data[0];
3487  for (unsigned int comp=0; comp<n_components; comp++)
3488  for (unsigned int d=0; d<dim; ++d)
3489  hessian_out[comp][d] = (this->hessians_quad[comp][d][q_point] *
3490  jac[d] * jac[d]);
3491  }
3492  // cell with general Jacobian
3493  else if (this->cell_type == internal::MatrixFreeFunctions::general)
3494  {
3495  Assert (this->mapping_info->second_derivatives_initialized == true,
3496  ExcNotInitialized());
3497  const Tensor<2,dim,VectorizedArray<Number> > &jac = jacobian[q_point];
3498  const Tensor<2,dim,VectorizedArray<Number> > &jac_grad = jacobian_grad[q_point];
3499  for (unsigned int comp=0; comp<n_components; comp++)
3500  {
3501  // compute laplacian before the gradient because it needs to access
3502  // unscaled gradient data
3503  VectorizedArray<Number> tmp[dim][dim];
3504  internal::hessian_unit_times_jac (jac, this->hessians_quad[comp],
3505  q_point, tmp);
3506 
3507  // compute only the trace part of hessian, J * tmp = J *
3508  // hess_unit(u) * J^T
3509  for (unsigned int d=0; d<dim; ++d)
3510  {
3511  hessian_out[comp][d] = jac[d][0] * tmp[0][d];
3512  for (unsigned int f=1; f<dim; ++f)
3513  hessian_out[comp][d] += jac[d][f] * tmp[f][d];
3514  }
3515 
3516  for (unsigned int d=0; d<dim; ++d)
3517  for (unsigned int e=0; e<dim; ++e)
3518  hessian_out[comp][d] += (jac_grad[d][e] *
3519  this->gradients_quad[comp][e][q_point]);
3520  }
3521  }
3522  // cell with general Jacobian, but constant within the cell
3523  else // if (this->cell_type == internal::MatrixFreeFunctions::affine)
3524  {
3525  const Tensor<2,dim,VectorizedArray<Number> > &jac = jacobian[0];
3526  for (unsigned int comp=0; comp<n_components; comp++)
3527  {
3528  // compute laplacian before the gradient because it needs to access
3529  // unscaled gradient data
3530  VectorizedArray<Number> tmp[dim][dim];
3531  internal::hessian_unit_times_jac (jac, this->hessians_quad[comp],
3532  q_point, tmp);
3533 
3534  // compute only the trace part of hessian, J * tmp = J *
3535  // hess_unit(u) * J^T
3536  for (unsigned int d=0; d<dim; ++d)
3537  {
3538  hessian_out[comp][d] = jac[d][0] * tmp[0][d];
3539  for (unsigned int f=1; f<dim; ++f)
3540  hessian_out[comp][d] += jac[d][f] * tmp[f][d];
3541  }
3542  }
3543  }
3544  return hessian_out;
3545 }
3546 
3547 
3548 
3549 template <int dim, int n_components_, typename Number>
3550 inline
3553 ::get_laplacian (const unsigned int q_point) const
3554 {
3555  Assert (this->hessians_quad_initialized==true,
3556  internal::ExcAccessToUninitializedField());
3557  AssertIndexRange (q_point, this->data->n_q_points);
3560  = get_hessian_diagonal(q_point);
3561  for (unsigned int comp=0; comp<n_components; ++comp)
3562  {
3563  laplacian_out[comp] = hess_diag[comp][0];
3564  for (unsigned int d=1; d<dim; ++d)
3565  laplacian_out[comp] += hess_diag[comp][d];
3566  }
3567  return laplacian_out;
3568 }
3569 
3570 
3571 
3572 template <int dim, int n_components_, typename Number>
3573 inline
3574 void
3576 ::submit_dof_value (const Tensor<1,n_components_,VectorizedArray<Number> > val_in,
3577  const unsigned int dof)
3578 {
3579 #ifdef DEBUG
3580  this->dof_values_initialized = true;
3581 #endif
3582  AssertIndexRange (dof, this->data->dofs_per_cell);
3583  for (unsigned int comp=0; comp<n_components; comp++)
3584  this->values_dofs[comp][dof] = val_in[comp];
3585 }
3586 
3587 
3588 
3589 template <int dim, int n_components_, typename Number>
3590 inline
3591 void
3593 ::submit_value (const Tensor<1,n_components_,VectorizedArray<Number> > val_in,
3594  const unsigned int q_point)
3595 {
3596 #ifdef DEBUG
3597  Assert (this->cell != numbers::invalid_unsigned_int, ExcNotInitialized());
3598  AssertIndexRange (q_point, this->data->n_q_points);
3599  this->values_quad_submitted = true;
3600 #endif
3601  if (this->cell_type == internal::MatrixFreeFunctions::general)
3602  {
3603  const VectorizedArray<Number> JxW = J_value[q_point];
3604  for (unsigned int comp=0; comp<n_components; ++comp)
3605  this->values_quad[comp][q_point] = val_in[comp] * JxW;
3606  }
3607  else //if (this->cell_type < internal::MatrixFreeFunctions::general)
3608  {
3609  const VectorizedArray<Number> JxW = J_value[0] * quadrature_weights[q_point];
3610  for (unsigned int comp=0; comp<n_components; ++comp)
3611  this->values_quad[comp][q_point] = val_in[comp] * JxW;
3612  }
3613 }
3614 
3615 
3616 
3617 template <int dim, int n_components_, typename Number>
3618 inline
3619 void
3621 ::submit_gradient (const Tensor<1,n_components_,
3622  Tensor<1,dim,VectorizedArray<Number> > >grad_in,
3623  const unsigned int q_point)
3624 {
3625 #ifdef DEBUG
3626  Assert (this->cell != numbers::invalid_unsigned_int, ExcNotInitialized());
3627  AssertIndexRange (q_point, this->data->n_q_points);
3628  this->gradients_quad_submitted = true;
3629 #endif
3630  if (this->cell_type == internal::MatrixFreeFunctions::cartesian)
3631  {
3632  const VectorizedArray<Number> JxW = J_value[0] * quadrature_weights[q_point];
3633  for (unsigned int comp=0; comp<n_components; comp++)
3634  for (unsigned int d=0; d<dim; ++d)
3635  this->gradients_quad[comp][d][q_point] = (grad_in[comp][d] *
3636  cartesian_data[0][d] * JxW);
3637  }
3638  else
3639  {
3641  this->cell_type == internal::MatrixFreeFunctions::general ?
3642  jacobian[q_point] : jacobian[0];
3643  const VectorizedArray<Number> JxW =
3644  this->cell_type == internal::MatrixFreeFunctions::general ?
3645  J_value[q_point] : J_value[0] * quadrature_weights[q_point];
3646  for (unsigned int comp=0; comp<n_components; ++comp)
3647  for (unsigned int d=0; d<dim; ++d)
3648  {
3649  VectorizedArray<Number> new_val = jac[0][d] * grad_in[comp][0];
3650  for (unsigned int e=1; e<dim; ++e)
3651  new_val += (jac[e][d] * grad_in[comp][e]);
3652  this->gradients_quad[comp][d][q_point] = new_val * JxW;
3653  }
3654  }
3655 }
3656 
3657 
3658 
3659 template <int dim, int n_components_, typename Number>
3660 inline
3663 ::integrate_value () const
3664 {
3665 #ifdef DEBUG
3666  Assert (this->cell != numbers::invalid_unsigned_int, ExcNotInitialized());
3667  Assert (this->values_quad_submitted == true,
3668  internal::ExcAccessToUninitializedField());
3669 #endif
3671  for (unsigned int comp=0; comp<n_components; ++comp)
3672  return_value[comp] = this->values_quad[comp][0];
3673  const unsigned int n_q_points = this->data->n_q_points;
3674  for (unsigned int q=1; q<n_q_points; ++q)
3675  for (unsigned int comp=0; comp<n_components; ++comp)
3676  return_value[comp] += this->values_quad[comp][q];
3677  return (return_value);
3678 }
3679 
3680 
3681 
3682 /*----------------------- FEEvaluationAccess --------------------------------*/
3683 
3684 
3685 template <int dim, int n_components_, typename Number>
3686 inline
3689  const unsigned int fe_no,
3690  const unsigned int quad_no_in,
3691  const unsigned int fe_degree,
3692  const unsigned int n_q_points)
3693  :
3695  (data_in, fe_no, quad_no_in, fe_degree, n_q_points)
3696 {}
3697 
3698 
3699 
3700 template <int dim, int n_components_, typename Number>
3701 template <int n_components_other>
3702 inline
3704 ::FEEvaluationAccess (const Mapping<dim> &mapping,
3705  const FiniteElement<dim> &fe,
3706  const Quadrature<1> &quadrature,
3707  const UpdateFlags update_flags,
3708  const unsigned int first_selected_component,
3710  :
3711  FEEvaluationBase <dim,n_components_,Number>(mapping, fe, quadrature, update_flags,
3712  first_selected_component, other)
3713 {}
3714 
3715 
3716 
3717 template <int dim, int n_components_, typename Number>
3718 inline
3721  :
3723 {}
3724 
3725 
3726 
3727 
3728 /*-------------------- FEEvaluationAccess scalar ----------------------------*/
3729 
3730 
3731 template <int dim, typename Number>
3732 inline
3735  const unsigned int fe_no,
3736  const unsigned int quad_no_in,
3737  const unsigned int fe_degree,
3738  const unsigned int n_q_points)
3739  :
3741  (data_in, fe_no, quad_no_in, fe_degree, n_q_points)
3742 {}
3743 
3744 
3745 
3746 template <int dim, typename Number>
3747 template <int n_components_other>
3748 inline
3750 ::FEEvaluationAccess (const Mapping<dim> &mapping,
3751  const FiniteElement<dim> &fe,
3752  const Quadrature<1> &quadrature,
3753  const UpdateFlags update_flags,
3754  const unsigned int first_selected_component,
3756  :
3757  FEEvaluationBase <dim,1,Number> (mapping, fe, quadrature, update_flags,
3758  first_selected_component, other)
3759 {}
3760 
3761 
3762 
3763 template <int dim, typename Number>
3764 inline
3767  :
3769 {}
3770 
3771 
3772 
3773 template <int dim, typename Number>
3774 inline
3777 ::get_dof_value (const unsigned int dof) const
3778 {
3779  AssertIndexRange (dof, this->data->dofs_per_cell);
3780  return this->values_dofs[0][dof];
3781 }
3782 
3783 
3784 
3785 template <int dim, typename Number>
3786 inline
3789 ::get_value (const unsigned int q_point) const
3790 {
3791  Assert (this->values_quad_initialized==true,
3792  internal::ExcAccessToUninitializedField());
3793  AssertIndexRange (q_point, this->data->n_q_points);
3794  return this->values_quad[0][q_point];
3795 }
3796 
3797 
3798 
3799 template <int dim, typename Number>
3800 inline
3803 ::get_gradient (const unsigned int q_point) const
3804 {
3805  // could use the base class gradient, but that involves too many inefficient
3806  // initialization operations on tensors
3807 
3808  Assert (this->gradients_quad_initialized==true,
3809  internal::ExcAccessToUninitializedField());
3810  AssertIndexRange (q_point, this->data->n_q_points);
3811 
3813 
3814  // Cartesian cell
3815  if (this->cell_type == internal::MatrixFreeFunctions::cartesian)
3816  {
3817  for (unsigned int d=0; d<dim; ++d)
3818  grad_out[d] = (this->gradients_quad[0][d][q_point] *
3819  this->cartesian_data[0][d]);
3820  }
3821  // cell with general/constant Jacobian
3822  else
3823  {
3825  this->cell_type == internal::MatrixFreeFunctions::general ?
3826  this->jacobian[q_point] : this->jacobian[0];
3827  for (unsigned int d=0; d<dim; ++d)
3828  {
3829  grad_out[d] = (jac[d][0] * this->gradients_quad[0][0][q_point]);
3830  for (unsigned int e=1; e<dim; ++e)
3831  grad_out[d] += (jac[d][e] * this->gradients_quad[0][e][q_point]);
3832  }
3833  }
3834  return grad_out;
3835 }
3836 
3837 
3838 
3839 template <int dim, typename Number>
3840 inline
3843 ::get_hessian (const unsigned int q_point) const
3844 {
3845  return BaseClass::get_hessian(q_point)[0];
3846 }
3847 
3848 
3849 
3850 template <int dim, typename Number>
3851 inline
3854 ::get_hessian_diagonal (const unsigned int q_point) const
3855 {
3856  return BaseClass::get_hessian_diagonal(q_point)[0];
3857 }
3858 
3859 
3860 
3861 template <int dim, typename Number>
3862 inline
3865 ::get_laplacian (const unsigned int q_point) const
3866 {
3867  return BaseClass::get_laplacian(q_point)[0];
3868 }
3869 
3870 
3871 
3872 template <int dim, typename Number>
3873 inline
3874 void
3877  const unsigned int dof)
3878 {
3879 #ifdef DEBUG
3880  this->dof_values_initialized = true;
3881  AssertIndexRange (dof, this->data->dofs_per_cell);
3882 #endif
3883  this->values_dofs[0][dof] = val_in;
3884 }
3885 
3886 
3887 
3888 template <int dim, typename Number>
3889 inline
3890 void
3893  const unsigned int q_point)
3894 {
3895 #ifdef DEBUG
3896  Assert (this->cell != numbers::invalid_unsigned_int, ExcNotInitialized());
3897  AssertIndexRange (q_point, this->data->n_q_points);
3898  this->values_quad_submitted = true;
3899 #endif
3900  if (this->cell_type == internal::MatrixFreeFunctions::general)
3901  {
3902  const VectorizedArray<Number> JxW = this->J_value[q_point];
3903  this->values_quad[0][q_point] = val_in * JxW;
3904  }
3905  else //if (this->cell_type < internal::MatrixFreeFunctions::general)
3906  {
3907  const VectorizedArray<Number> JxW = this->J_value[0] * this->quadrature_weights[q_point];
3908  this->values_quad[0][q_point] = val_in * JxW;
3909  }
3910 }
3911 
3912 
3913 
3914 template <int dim, typename Number>
3915 inline
3916 void
3918 ::submit_gradient (const Tensor<1,dim,VectorizedArray<Number> > grad_in,
3919  const unsigned int q_point)
3920 {
3921 #ifdef DEBUG
3922  Assert (this->cell != numbers::invalid_unsigned_int, ExcNotInitialized());
3923  AssertIndexRange (q_point, this->data->n_q_points);
3924  this->gradients_quad_submitted = true;
3925 #endif
3926  if (this->cell_type == internal::MatrixFreeFunctions::cartesian)
3927  {
3928  const VectorizedArray<Number> JxW = this->J_value[0] * this->quadrature_weights[q_point];
3929  for (unsigned int d=0; d<dim; ++d)
3930  this->gradients_quad[0][d][q_point] = (grad_in[d] *
3931  this->cartesian_data[0][d] *
3932  JxW);
3933  }
3934  // general/affine cell type
3935  else
3936  {
3938  this->cell_type == internal::MatrixFreeFunctions::general ?
3939  this->jacobian[q_point] : this->jacobian[0];
3940  const VectorizedArray<Number> JxW =
3941  this->cell_type == internal::MatrixFreeFunctions::general ?
3942  this->J_value[q_point] : this->J_value[0] * this->quadrature_weights[q_point];
3943  for (unsigned int d=0; d<dim; ++d)
3944  {
3945  VectorizedArray<Number> new_val = jac[0][d] * grad_in[0];
3946  for (unsigned int e=1; e<dim; ++e)
3947  new_val += jac[e][d] * grad_in[e];
3948  this->gradients_quad[0][d][q_point] = new_val * JxW;
3949  }
3950  }
3951 }
3952 
3953 
3954 
3955 template <int dim, typename Number>
3956 inline
3959 ::integrate_value () const
3960 {
3961  return BaseClass::integrate_value()[0];
3962 }
3963 
3964 
3965 
3966 
3967 /*----------------- FEEvaluationAccess vector-valued ------------------------*/
3968 
3969 
3970 template <int dim, typename Number>
3971 inline
3974  const unsigned int fe_no,
3975  const unsigned int quad_no_in,
3976  const unsigned int fe_degree,
3977  const unsigned int n_q_points)
3978  :
3980  (data_in, fe_no, quad_no_in, fe_degree, n_q_points)
3981 {}
3982 
3983 
3984 
3985 template <int dim, typename Number>
3986 template <int n_components_other>
3987 inline
3989 ::FEEvaluationAccess (const Mapping<dim> &mapping,
3990  const FiniteElement<dim> &fe,
3991  const Quadrature<1> &quadrature,
3992  const UpdateFlags update_flags,
3993  const unsigned int first_selected_component,
3995  :
3996  FEEvaluationBase <dim,dim,Number> (mapping, fe, quadrature, update_flags,
3997  first_selected_component, other)
3998 {}
3999 
4000 
4001 
4002 template <int dim, typename Number>
4003 inline
4006  :
4008 {}
4009 
4010 
4011 
4012 template <int dim, typename Number>
4013 inline
4016 ::get_gradient (const unsigned int q_point) const
4017 {
4018  return BaseClass::get_gradient (q_point);
4019 }
4020 
4021 
4022 
4023 template <int dim, typename Number>
4024 inline
4027 ::get_divergence (const unsigned int q_point) const
4028 {
4029  Assert (this->gradients_quad_initialized==true,
4030  internal::ExcAccessToUninitializedField());
4031  AssertIndexRange (q_point, this->data->n_q_points);
4032 
4033  VectorizedArray<Number> divergence;
4034 
4035  // Cartesian cell
4036  if (this->cell_type == internal::MatrixFreeFunctions::cartesian)
4037  {
4038  divergence = (this->gradients_quad[0][0][q_point] *
4039  this->cartesian_data[0][0]);
4040  for (unsigned int d=1; d<dim; ++d)
4041  divergence += (this->gradients_quad[d][d][q_point] *
4042  this->cartesian_data[0][d]);
4043  }
4044  // cell with general/constant Jacobian
4045  else
4046  {
4048  this->cell_type == internal::MatrixFreeFunctions::general ?
4049  this->jacobian[q_point] : this->jacobian[0];
4050  divergence = (jac[0][0] * this->gradients_quad[0][0][q_point]);
4051  for (unsigned int e=1; e<dim; ++e)
4052  divergence += (jac[0][e] * this->gradients_quad[0][e][q_point]);
4053  for (unsigned int d=1; d<dim; ++d)
4054  for (unsigned int e=0; e<dim; ++e)
4055  divergence += (jac[d][e] * this->gradients_quad[d][e][q_point]);
4056  }
4057  return divergence;
4058 }
4059 
4060 
4061 
4062 template <int dim, typename Number>
4063 inline
4066 ::get_symmetric_gradient (const unsigned int q_point) const
4067 {
4068  // copy from generic function into dim-specialization function
4069  const Tensor<2,dim,VectorizedArray<Number> > grad = get_gradient(q_point);
4070  VectorizedArray<Number> symmetrized [(dim*dim+dim)/2];
4071  VectorizedArray<Number> half = make_vectorized_array (0.5);
4072  for (unsigned int d=0; d<dim; ++d)
4073  symmetrized[d] = grad[d][d];
4074  switch (dim)
4075  {
4076  case 1:
4077  break;
4078  case 2:
4079  symmetrized[2] = grad[0][1] + grad[1][0];
4080  symmetrized[2] *= half;
4081  break;
4082  case 3:
4083  symmetrized[3] = grad[0][1] + grad[1][0];
4084  symmetrized[3] *= half;
4085  symmetrized[4] = grad[0][2] + grad[2][0];
4086  symmetrized[4] *= half;
4087  symmetrized[5] = grad[1][2] + grad[2][1];
4088  symmetrized[5] *= half;
4089  break;
4090  default:
4091  Assert (false, ExcNotImplemented());
4092  }
4093  return SymmetricTensor<2,dim,VectorizedArray<Number> > (symmetrized);
4094 }
4095 
4096 
4097 
4098 template <int dim, typename Number>
4099 inline
4102 ::get_curl (const unsigned int q_point) const
4103 {
4104  // copy from generic function into dim-specialization function
4105  const Tensor<2,dim,VectorizedArray<Number> > grad = get_gradient(q_point);
4107  switch (dim)
4108  {
4109  case 1:
4110  Assert (false,
4111  ExcMessage("Computing the curl in 1d is not a useful operation"));
4112  break;
4113  case 2:
4114  curl[0] = grad[1][0] - grad[0][1];
4115  break;
4116  case 3:
4117  curl[0] = grad[2][1] - grad[1][2];
4118  curl[1] = grad[0][2] - grad[2][0];
4119  curl[2] = grad[1][0] - grad[0][1];
4120  break;
4121  default:
4122  Assert (false, ExcNotImplemented());
4123  }
4124  return curl;
4125 }
4126 
4127 
4128 
4129 template <int dim, typename Number>
4130 inline
4133 ::get_hessian_diagonal (const unsigned int q_point) const
4134 {
4135  Assert (this->hessians_quad_initialized==true,
4136  internal::ExcAccessToUninitializedField());
4137  AssertIndexRange (q_point, this->data->n_q_points);
4138 
4139  return BaseClass::get_hessian_diagonal (q_point);
4140 }
4141 
4142 
4143 
4144 template <int dim, typename Number>
4145 inline
4148 ::get_hessian (const unsigned int q_point) const
4149 {
4150  Assert (this->hessians_quad_initialized==true,
4151  internal::ExcAccessToUninitializedField());
4152  AssertIndexRange (q_point, this->data->n_q_points);
4153  return BaseClass::get_hessian(q_point);
4154 }
4155 
4156 
4157 
4158 template <int dim, typename Number>
4159 inline
4160 void
4162 ::submit_gradient (const Tensor<2,dim,VectorizedArray<Number> > grad_in,
4163  const unsigned int q_point)
4164 {
4165  BaseClass::submit_gradient (grad_in, q_point);
4166 }
4167 
4168 
4169 
4170 template <int dim, typename Number>
4171 inline
4172 void
4175  grad_in,
4176  const unsigned int q_point)
4177 {
4178  BaseClass::submit_gradient(grad_in, q_point);
4179 }
4180 
4181 
4182 
4183 template <int dim, typename Number>
4184 inline
4185 void
4188  const unsigned int q_point)
4189 {
4190 #ifdef DEBUG
4191  Assert (this->cell != numbers::invalid_unsigned_int, ExcNotInitialized());
4192  AssertIndexRange (q_point, this->data->n_q_points);
4193  this->gradients_quad_submitted = true;
4194 #endif
4195  if (this->cell_type == internal::MatrixFreeFunctions::cartesian)
4196  {
4197  const VectorizedArray<Number> fac = this->J_value[0] *
4198  this->quadrature_weights[q_point] * div_in;
4199  for (unsigned int d=0; d<dim; ++d)
4200  {
4201  this->gradients_quad[d][d][q_point] = (fac *
4202  this->cartesian_data[0][d]);
4203  for (unsigned int e=d+1; e<dim; ++e)
4204  {
4205  this->gradients_quad[d][e][q_point] = VectorizedArray<Number>();
4206  this->gradients_quad[e][d][q_point] = VectorizedArray<Number>();
4207  }
4208  }
4209  }
4210  else
4211  {
4213  this->cell_type == internal::MatrixFreeFunctions::general ?
4214  this->jacobian[q_point] : this->jacobian[0];
4215  const VectorizedArray<Number> fac =
4216  (this->cell_type == internal::MatrixFreeFunctions::general ?
4217  this->J_value[q_point] : this->J_value[0] *
4218  this->quadrature_weights[q_point]) * div_in;
4219  for (unsigned int d=0; d<dim; ++d)
4220  {
4221  for (unsigned int e=0; e<dim; ++e)
4222  this->gradients_quad[d][e][q_point] = jac[d][e] * fac;
4223  }
4224  }
4225 }
4226 
4227 
4228 
4229 template <int dim, typename Number>
4230 inline
4231 void
4234  sym_grad,
4235  const unsigned int q_point)
4236 {
4237  // could have used base class operator, but that involves some overhead
4238  // which is inefficient. it is nice to have the symmetric tensor because
4239  // that saves some operations
4240 #ifdef DEBUG
4241  Assert (this->cell != numbers::invalid_unsigned_int, ExcNotInitialized());
4242  AssertIndexRange (q_point, this->data->n_q_points);
4243  this->gradients_quad_submitted = true;
4244 #endif
4245  if (this->cell_type == internal::MatrixFreeFunctions::cartesian)
4246  {
4247  const VectorizedArray<Number> JxW = this->J_value[0] * this->quadrature_weights[q_point];
4248  for (unsigned int d=0; d<dim; ++d)
4249  this->gradients_quad[d][d][q_point] = (sym_grad.access_raw_entry(d) *
4250  JxW *
4251  this->cartesian_data[0][d]);
4252  for (unsigned int e=0, counter=dim; e<dim; ++e)
4253  for (unsigned int d=e+1; d<dim; ++d, ++counter)
4254  {
4255  const VectorizedArray<Number> value = sym_grad.access_raw_entry(counter) * JxW;
4256  this->gradients_quad[e][d][q_point] = (value *
4257  this->cartesian_data[0][d]);
4258  this->gradients_quad[d][e][q_point] = (value *
4259  this->cartesian_data[0][e]);
4260  }
4261  }
4262  // general/affine cell type
4263  else
4264  {
4265  const VectorizedArray<Number> JxW =
4266  this->cell_type == internal::MatrixFreeFunctions::general ?
4267  this->J_value[q_point] : this->J_value[0] * this->quadrature_weights[q_point];
4269  this->cell_type == internal::MatrixFreeFunctions::general ?
4270  this->jacobian[q_point] : this->jacobian[0];
4271  VectorizedArray<Number> weighted [dim][dim];
4272  for (unsigned int i=0; i<dim; ++i)
4273  weighted[i][i] = sym_grad.access_raw_entry(i) * JxW;
4274  for (unsigned int i=0, counter=dim; i<dim; ++i)
4275  for (unsigned int j=i+1; j<dim; ++j, ++counter)
4276  {
4277  const VectorizedArray<Number> value = sym_grad.access_raw_entry(counter) * JxW;
4278  weighted[i][j] = value;
4279  weighted[j][i] = value;
4280  }
4281  for (unsigned int comp=0; comp<dim; ++comp)
4282  for (unsigned int d=0; d<dim; ++d)
4283  {
4284  VectorizedArray<Number> new_val = jac[0][d] * weighted[comp][0];
4285  for (unsigned int e=1; e<dim; ++e)
4286  new_val += jac[e][d] * weighted[comp][e];
4287  this->gradients_quad[comp][d][q_point] = new_val;
4288  }
4289  }
4290 }
4291 
4292 
4293 
4294 template <int dim, typename Number>
4295 inline
4296 void
4298 ::submit_curl (const Tensor<1,dim==2?1:dim,VectorizedArray<Number> > curl,
4299  const unsigned int q_point)
4300 {
4302  switch (dim)
4303  {
4304  case 1:
4305  Assert (false,
4306  ExcMessage("Testing by the curl in 1d is not a useful operation"));
4307  break;
4308  case 2:
4309  grad[1][0] = curl[0];
4310  grad[0][1] = -curl[0];
4311  break;
4312  case 3:
4313  grad[2][1] = curl[0];
4314  grad[1][2] = -curl[0];
4315  grad[0][2] = curl[1];
4316  grad[2][0] = -curl[1];
4317  grad[1][0] = curl[2];
4318  grad[0][1] = -curl[2];
4319  break;
4320  default:
4321  Assert (false, ExcNotImplemented());
4322  }
4323  submit_gradient (grad, q_point);
4324 }
4325 
4326 
4327 /*-------------------- FEEvaluationAccess scalar for 1d ----------------------------*/
4328 
4329 
4330 template <typename Number>
4331 inline
4334  const unsigned int fe_no,
4335  const unsigned int quad_no_in,
4336  const unsigned int fe_degree,
4337  const unsigned int n_q_points)
4338  :
4340  (data_in, fe_no, quad_no_in, fe_degree, n_q_points)
4341 {}
4342 
4343 
4344 
4345 template <typename Number>
4346 template <int n_components_other>
4347 inline
4349 ::FEEvaluationAccess (const Mapping<1> &mapping,
4350  const FiniteElement<1> &fe,
4351  const Quadrature<1> &quadrature,
4352  const UpdateFlags update_flags,
4353  const unsigned int first_selected_component,
4355  :
4356  FEEvaluationBase <1,1,Number> (mapping, fe, quadrature, update_flags,
4357  first_selected_component, other)
4358 {}
4359 
4360 
4361 
4362 template <typename Number>
4363 inline
4366  :
4368 {}
4369 
4370 
4371 
4372 template <typename Number>
4373 inline
4376 ::get_dof_value (const unsigned int dof) const
4377 {
4378  AssertIndexRange (dof, this->data->dofs_per_cell);
4379  return this->values_dofs[0][dof];
4380 }
4381 
4382 
4383 
4384 template <typename Number>
4385 inline
4388 ::get_value (const unsigned int q_point) const
4389 {
4390  Assert (this->values_quad_initialized==true,
4391  internal::ExcAccessToUninitializedField());
4392  AssertIndexRange (q_point, this->data->n_q_points);
4393  return this->values_quad[0][q_point];
4394 }
4395 
4396 
4397 
4398 template <typename Number>
4399 inline
4402 ::get_gradient (const unsigned int q_point) const
4403 {
4404  // could use the base class gradient, but that involves too many inefficient
4405  // initialization operations on tensors
4406 
4407  Assert (this->gradients_quad_initialized==true,
4408  internal::ExcAccessToUninitializedField());
4409  AssertIndexRange (q_point, this->data->n_q_points);
4410 
4412 
4413  // Cartesian cell
4414  if (this->cell_type == internal::MatrixFreeFunctions::cartesian)
4415  {
4416  grad_out[0] = (this->gradients_quad[0][0][q_point] *
4417  this->cartesian_data[0][0]);
4418  }
4419  // cell with general/constant Jacobian
4420  else
4421  {
4422  const Tensor<2,1,VectorizedArray<Number> > &jac =
4423  this->cell_type == internal::MatrixFreeFunctions::general ?
4424  this->jacobian[q_point] : this->jacobian[0];
4425 
4426  grad_out[0] = (jac[0][0] * this->gradients_quad[0][0][q_point]);
4427  }
4428  return grad_out;
4429 }
4430 
4431 
4432 
4433 template <typename Number>
4434 inline
4437 ::get_hessian (const unsigned int q_point) const
4438 {
4439  return BaseClass::get_hessian(q_point)[0];
4440 }
4441 
4442 
4443 
4444 template <typename Number>
4445 inline
4448 ::get_hessian_diagonal (const unsigned int q_point) const
4449 {
4450  return BaseClass::get_hessian_diagonal(q_point)[0];
4451 }
4452 
4453 
4454 
4455 template <typename Number>
4456 inline
4459 ::get_laplacian (const unsigned int q_point) const
4460 {
4461  return BaseClass::get_laplacian(q_point)[0];
4462 }
4463 
4464 
4465 
4466 template <typename Number>
4467 inline
4468 void
4471  const unsigned int dof)
4472 {
4473 #ifdef DEBUG
4474  this->dof_values_initialized = true;
4475  AssertIndexRange (dof, this->data->dofs_per_cell);
4476 #endif
4477  this->values_dofs[0][dof] = val_in;
4478 }
4479 
4480 
4481 
4482 template <typename Number>
4483 inline
4484 void
4487  const unsigned int q_point)
4488 {
4489 #ifdef DEBUG
4490  Assert (this->cell != numbers::invalid_unsigned_int, ExcNotInitialized());
4491  AssertIndexRange (q_point, this->data->n_q_points);
4492  this->values_quad_submitted = true;
4493 #endif
4494  if (this->cell_type == internal::MatrixFreeFunctions::general)
4495  {
4496  const VectorizedArray<Number> JxW = this->J_value[q_point];
4497  this->values_quad[0][q_point] = val_in * JxW;
4498  }
4499  else //if (this->cell_type < internal::MatrixFreeFunctions::general)
4500  {
4501  const VectorizedArray<Number> JxW = this->J_value[0] * this->quadrature_weights[q_point];
4502  this->values_quad[0][q_point] = val_in * JxW;
4503  }
4504 }
4505 
4506 
4507 
4508 template <typename Number>
4509 inline
4510 void
4512 ::submit_gradient (const Tensor<1,1,VectorizedArray<Number> > grad_in,
4513  const unsigned int q_point)
4514 {
4515 #ifdef DEBUG
4516  Assert (this->cell != numbers::invalid_unsigned_int, ExcNotInitialized());
4517  AssertIndexRange (q_point, this->data->n_q_points);
4518  this->gradients_quad_submitted = true;
4519 #endif
4520  if (this->cell_type == internal::MatrixFreeFunctions::cartesian)
4521  {
4522  const VectorizedArray<Number> JxW = this->J_value[0] * this->quadrature_weights[q_point];
4523  this->gradients_quad[0][0][q_point] = (grad_in[0] *
4524  this->cartesian_data[0][0] *
4525  JxW);
4526  }
4527  // general/affine cell type
4528  else
4529  {
4530  const Tensor<2,1,VectorizedArray<Number> > &jac =
4531  this->cell_type == internal::MatrixFreeFunctions::general ?
4532  this->jacobian[q_point] : this->jacobian[0];
4533  const VectorizedArray<Number> JxW =
4534  this->cell_type == internal::MatrixFreeFunctions::general ?
4535  this->J_value[q_point] : this->J_value[0] * this->quadrature_weights[q_point];
4536 
4537  this->gradients_quad[0][0][q_point] = jac[0][0] * grad_in[0] * JxW;
4538  }
4539 }
4540 
4541 
4542 
4543 template <typename Number>
4544 inline
4547 ::integrate_value () const
4548 {
4549  return BaseClass::integrate_value()[0];
4550 }
4551 
4552 
4553 
4554 namespace internal
4555 {
4560  enum EvaluatorVariant
4561  {
4562  evaluate_general,
4563  evaluate_symmetric,
4564  evaluate_evenodd
4565  };
4566 
4570  template <EvaluatorVariant variant, int dim, int fe_degree, int n_q_points_1d,
4571  typename Number>
4572  struct EvaluatorTensorProduct
4573  {};
4574 
4579  template <int dim, int fe_degree, int n_q_points_1d, typename Number>
4580  struct EvaluatorTensorProduct<evaluate_general,dim,fe_degree,n_q_points_1d,Number>
4581  {
4582  static const unsigned int dofs_per_cell = Utilities::fixed_int_power<fe_degree+1,dim>::value;
4583  static const unsigned int n_q_points = Utilities::fixed_int_power<n_q_points_1d,dim>::value;
4584 
4589  EvaluatorTensorProduct ()
4590  :
4591  shape_values (0),
4592  shape_gradients (0),
4593  shape_hessians (0)
4594  {}
4595 
4599  EvaluatorTensorProduct (const AlignedVector<Number> &shape_values,
4600  const AlignedVector<Number> &shape_gradients,
4601  const AlignedVector<Number> &shape_hessians)
4602  :
4603  shape_values (shape_values.begin()),
4604  shape_gradients (shape_gradients.begin()),
4605  shape_hessians (shape_hessians.begin())
4606  {}
4607 
4608  template <int direction, bool dof_to_quad, bool add>
4609  void
4610  values (const Number in [],
4611  Number out[]) const
4612  {
4613  apply<direction,dof_to_quad,add>(shape_values, in, out);
4614  }
4615 
4616  template <int direction, bool dof_to_quad, bool add>
4617  void
4618  gradients (const Number in [],
4619  Number out[]) const
4620  {
4621  apply<direction,dof_to_quad,add>(shape_gradients, in, out);
4622  }
4623 
4624  template <int direction, bool dof_to_quad, bool add>
4625  void
4626  hessians (const Number in [],
4627  Number out[]) const
4628  {
4629  apply<direction,dof_to_quad,add>(shape_hessians, in, out);
4630  }
4631 
4632  template <int direction, bool dof_to_quad, bool add>
4633  static void apply (const Number *shape_data,
4634  const Number in [],
4635  Number out []);
4636 
4637  const Number *shape_values;
4638  const Number *shape_gradients;
4639  const Number *shape_hessians;
4640  };
4641 
4642  // evaluates the given shape data in 1d-3d using the tensor product
4643  // form. does not use a particular layout of entries in the matrices
4644  // like the functions below and corresponds to a usual matrix-matrix
4645  // product
4646  template <int dim, int fe_degree, int n_q_points_1d, typename Number>
4647  template <int direction, bool dof_to_quad, bool add>
4648  inline
4649  void
4650  EvaluatorTensorProduct<evaluate_general,dim,fe_degree,n_q_points_1d,Number>
4651  ::apply (const Number *shape_data,
4652  const Number in [],
4653  Number out [])
4654  {
4655  AssertIndexRange (direction, dim);
4656  const int mm = dof_to_quad ? (fe_degree+1) : n_q_points_1d,
4657  nn = dof_to_quad ? n_q_points_1d : (fe_degree+1);
4658 
4659  const int n_blocks1 = (dim > 1 ? (direction > 0 ? nn : mm) : 1);
4660  const int n_blocks2 = (dim > 2 ? (direction > 1 ? nn : mm) : 1);
4662 
4663  for (int i2=0; i2<n_blocks2; ++i2)
4664  {
4665  for (int i1=0; i1<n_blocks1; ++i1)
4666  {
4667  for (int col=0; col<nn; ++col)
4668  {
4669  Number val0;
4670  if (dof_to_quad == true)
4671  val0 = shape_data[col];
4672  else
4673  val0 = shape_data[col*n_q_points_1d];
4674  Number res0 = val0 * in[0];
4675  for (int ind=1; ind<mm; ++ind)
4676  {
4677  if (dof_to_quad == true)
4678  val0 = shape_data[ind*n_q_points_1d+col];
4679  else
4680  val0 = shape_data[col*n_q_points_1d+ind];
4681  res0 += val0 * in[stride*ind];
4682  }
4683  if (add == false)
4684  out[stride*col] = res0;
4685  else
4686  out[stride*col] += res0;
4687  }
4688 
4689  // increment: in regular case, just go to the next point in
4690  // x-direction. If we are at the end of one chunk in x-dir, need
4691  // to jump over to the next layer in z-direction
4692  switch (direction)
4693  {
4694  case 0:
4695  in += mm;
4696  out += nn;
4697  break;
4698  case 1:
4699  case 2:
4700  ++in;
4701  ++out;
4702  break;
4703  default:
4704  Assert (false, ExcNotImplemented());
4705  }
4706  }
4707  if (direction == 1)
4708  {
4709  in += nn*(mm-1);
4710  out += nn*(nn-1);
4711  }
4712  }
4713  }
4714 
4715 
4716 
4717  // This method applies the tensor product operation to produce face values
4718  // out from cell values. As opposed to the apply_tensor_product method, this
4719  // method assumes that the directions orthogonal to the face have
4720  // fe_degree+1 degrees of freedom per direction and not n_q_points_1d for
4721  // those directions lower than the one currently applied
4722  template <int dim, int fe_degree, typename Number, int face_direction,
4723  bool dof_to_quad, bool add>
4724  inline
4725  void
4726  apply_tensor_product_face (const Number *shape_data,
4727  const Number in [],
4728  Number out [])
4729  {
4730  const int n_blocks1 = dim > 1 ? (fe_degree+1) : 1;
4731  const int n_blocks2 = dim > 2 ? (fe_degree+1) : 1;
4732 
4733  AssertIndexRange (face_direction, dim);
4734  const int mm = dof_to_quad ? (fe_degree+1) : 1,
4735  nn = dof_to_quad ? 1 : (fe_degree+1);
4736 
4738 
4739  for (int i2=0; i2<n_blocks2; ++i2)
4740  {
4741  for (int i1=0; i1<n_blocks1; ++i1)
4742  {
4743  if (dof_to_quad == true)
4744  {
4745  Number res0 = shape_data[0] * in[0];
4746  for (int ind=1; ind<mm; ++ind)
4747  res0 += shape_data[ind] * in[stride*ind];
4748  if (add == false)
4749  out[0] = res0;
4750  else
4751  out[0] += res0;
4752  }
4753  else
4754  {
4755  for (int col=0; col<nn; ++col)
4756  if (add == false)
4757  out[col*stride] = shape_data[col] * in[0];
4758  else
4759  out[col*stride] += shape_data[col] * in[0];
4760  }
4761 
4762  // increment: in regular case, just go to the next point in
4763  // x-direction. If we are at the end of one chunk in x-dir, need
4764  // to jump over to the next layer in z-direction
4765  switch (face_direction)
4766  {
4767  case 0:
4768  in += mm;
4769  out += nn;
4770  break;
4771  case 1:
4772  ++in;
4773  ++out;
4774  // faces 2 and 3 in 3D use local coordinate system zx, which
4775  // is the other way around compared to the tensor
4776  // product. Need to take that into account.
4777  if (dim == 3)
4778  {
4779  if (dof_to_quad)
4780  out += fe_degree;
4781  else
4782  in += fe_degree;
4783  }
4784  break;
4785  case 2:
4786  ++in;
4787  ++out;
4788  break;
4789  default:
4790  Assert (false, ExcNotImplemented());
4791  }
4792  }
4793  if (face_direction == 1 && dim == 3)
4794  {
4795  in += mm*(mm-1);
4796  out += nn*(nn-1);
4797  // adjust for local coordinate system zx
4798  if (dof_to_quad)
4799  out -= (fe_degree+1)*(fe_degree+1)-1;
4800  else
4801  in -= (fe_degree+1)*(fe_degree+1)-1;
4802  }
4803  }
4804  }
4805 
4806 
4807 
4808  // This class specializes the general application of tensor-product based
4809  // elements for "symmetric" finite elements, i.e., when the shape functions
4810  // are symmetric about 0.5 and the quadrature points are, too.
4811  template <int dim, int fe_degree, int n_q_points_1d, typename Number>
4812  struct EvaluatorTensorProduct<evaluate_symmetric,dim,fe_degree,n_q_points_1d,Number>
4813  {
4814  static const unsigned int dofs_per_cell = Utilities::fixed_int_power<fe_degree+1,dim>::value;
4815  static const unsigned int n_q_points = Utilities::fixed_int_power<n_q_points_1d,dim>::value;
4816 
4820  EvaluatorTensorProduct (const AlignedVector<Number> &shape_values,
4821  const AlignedVector<Number> &shape_gradients,
4822  const AlignedVector<Number> &shape_hessians)
4823  :
4824  shape_values (shape_values.begin()),
4825  shape_gradients (shape_gradients.begin()),
4826  shape_hessians (shape_hessians.begin())
4827  {}
4828 
4829  template <int direction, bool dof_to_quad, bool add>
4830  void
4831  values (const Number in [],
4832  Number out[]) const;
4833 
4834  template <int direction, bool dof_to_quad, bool add>
4835  void
4836  gradients (const Number in [],
4837  Number out[]) const;
4838 
4839  template <int direction, bool dof_to_quad, bool add>
4840  void
4841  hessians (const Number in [],
4842  Number out[]) const;
4843 
4844  const Number *shape_values;
4845  const Number *shape_gradients;
4846  const Number *shape_hessians;
4847  };
4848 
4849 
4850 
4851  // In this case, the 1D shape values read (sorted lexicographically, rows
4852  // run over 1D dofs, columns over quadrature points):
4853  // Q2 --> [ 0.687 0 -0.087 ]
4854  // [ 0.4 1 0.4 ]
4855  // [-0.087 0 0.687 ]
4856  // Q3 --> [ 0.66 0.003 0.002 0.049 ]
4857  // [ 0.521 1.005 -0.01 -0.230 ]
4858  // [-0.230 -0.01 1.005 0.521 ]
4859  // [ 0.049 0.002 0.003 0.66 ]
4860  // Q4 --> [ 0.658 0.022 0 -0.007 -0.032 ]
4861  // [ 0.608 1.059 0 0.039 0.176 ]
4862  // [-0.409 -0.113 1 -0.113 -0.409 ]
4863  // [ 0.176 0.039 0 1.059 0.608 ]
4864  // [-0.032 -0.007 0 0.022 0.658 ]
4865  //
4866  // In these matrices, we want to use avoid computations involving zeros and
4867  // ones and in addition use the symmetry in entries to reduce the number of
4868  // read operations.
4869  template <int dim, int fe_degree, int n_q_points_1d, typename Number>
4870  template <int direction, bool dof_to_quad, bool add>
4871  inline
4872  void
4873  EvaluatorTensorProduct<evaluate_symmetric,dim,fe_degree,n_q_points_1d,Number>
4874  ::values (const Number in [],
4875  Number out []) const
4876  {
4877  AssertIndexRange (direction, dim);
4878  const int mm = dof_to_quad ? (fe_degree+1) : n_q_points_1d,
4879  nn = dof_to_quad ? n_q_points_1d : (fe_degree+1);
4880  const int n_cols = nn / 2;
4881  const int mid = mm / 2;
4882 
4883  const int n_blocks1 = (dim > 1 ? (direction > 0 ? nn : mm) : 1);
4884  const int n_blocks2 = (dim > 2 ? (direction > 1 ? nn : mm) : 1);
4886 
4887  for (int i2=0; i2<n_blocks2; ++i2)
4888  {
4889  for (int i1=0; i1<n_blocks1; ++i1)
4890  {
4891  for (int col=0; col<n_cols; ++col)
4892  {
4893  Number val0, val1, in0, in1, res0, res1;
4894  if (dof_to_quad == true)
4895  {
4896  val0 = shape_values[col];
4897  val1 = shape_values[nn-1-col];
4898  }
4899  else
4900  {
4901  val0 = shape_values[col*n_q_points_1d];
4902  val1 = shape_values[(col+1)*n_q_points_1d-1];
4903  }
4904  if (mid > 0)
4905  {
4906  in0 = in[0];
4907  in1 = in[stride*(mm-1)];
4908  res0 = val0 * in0;
4909  res1 = val1 * in0;
4910  res0 += val1 * in1;
4911  res1 += val0 * in1;
4912  for (int ind=1; ind<mid; ++ind)
4913  {
4914  if (dof_to_quad == true)
4915  {
4916  val0 = shape_values[ind*n_q_points_1d+col];
4917  val1 = shape_values[ind*n_q_points_1d+nn-1-col];
4918  }
4919  else
4920  {
4921  val0 = shape_values[col*n_q_points_1d+ind];
4922  val1 = shape_values[(col+1)*n_q_points_1d-1-ind];
4923  }
4924  in0 = in[stride*ind];
4925  in1 = in[stride*(mm-1-ind)];
4926  res0 += val0 * in0;
4927  res1 += val1 * in0;
4928  res0 += val1 * in1;
4929  res1 += val0 * in1;
4930  }
4931  }
4932  else
4933  res0 = res1 = Number();
4934  if (dof_to_quad == true)
4935  {
4936  if (mm % 2 == 1)
4937  {
4938  val0 = shape_values[mid*n_q_points_1d+col];
4939  val1 = val0 * in[stride*mid];
4940  res0 += val1;
4941  res1 += val1;
4942  }
4943  }
4944  else
4945  {
4946  if (mm % 2 == 1 && nn % 2 == 0)
4947  {
4948  val0 = shape_values[col*n_q_points_1d+mid];
4949  val1 = val0 * in[stride*mid];
4950  res0 += val1;
4951  res1 += val1;
4952  }
4953  }
4954  if (add == false)
4955  {
4956  out[stride*col] = res0;
4957  out[stride*(nn-1-col)] = res1;
4958  }
4959  else
4960  {
4961  out[stride*col] += res0;
4962  out[stride*(nn-1-col)] += res1;
4963  }
4964  }
4965  if ( dof_to_quad == true && nn%2==1 && mm%2==1 )
4966  {
4967  if (add==false)
4968  out[stride*n_cols] = in[stride*mid];
4969  else
4970  out[stride*n_cols] += in[stride*mid];
4971  }
4972  else if (dof_to_quad == true && nn%2==1)
4973  {
4974  Number res0;
4975  Number val0 = shape_values[n_cols];
4976  if (mid > 0)
4977  {
4978  res0 = in[0] + in[stride*(mm-1)];
4979  res0 *= val0;
4980  for (int ind=1; ind<mid; ++ind)
4981  {
4982  val0 = shape_values[ind*n_q_points_1d+n_cols];
4983  Number val1 = in[stride*ind] + in[stride*(mm-1-ind)];
4984  val1 *= val0;
4985  res0 += val1;
4986  }
4987  }
4988  else
4989  res0 = Number();
4990  if (add == false)
4991  out[stride*n_cols] = res0;
4992  else
4993  out[stride*n_cols] += res0;
4994  }
4995  else if (dof_to_quad == false && nn%2 == 1)
4996  {
4997  Number res0;
4998  if (mid > 0)
4999  {
5000  Number val0 = shape_values[n_cols*n_q_points_1d];
5001  res0 = in[0] + in[stride*(mm-1)];
5002  res0 *= val0;
5003  for (int ind=1; ind<mid; ++ind)
5004  {
5005  val0 = shape_values[n_cols*n_q_points_1d+ind];
5006  Number val1 = in[stride*ind] + in[stride*(mm-1-ind)];
5007  val1 *= val0;
5008  res0 += val1;
5009  }
5010  if (mm % 2)
5011  res0 += in[stride*mid];
5012  }
5013  else
5014  res0 = in[0];
5015  if (add == false)
5016  out[stride*n_cols] = res0;
5017  else
5018  out[stride*n_cols] += res0;
5019  }
5020 
5021  // increment: in regular case, just go to the next point in
5022  // x-direction. If we are at the end of one chunk in x-dir, need to
5023  // jump over to the next layer in z-direction
5024  switch (direction)
5025  {
5026  case 0:
5027  in += mm;
5028  out += nn;
5029  break;
5030  case 1:
5031  case 2:
5032  ++in;
5033  ++out;
5034  break;
5035  default:
5036  Assert (false, ExcNotImplemented());
5037  }
5038  }
5039  if (direction == 1)
5040  {
5041  in += nn*(mm-1);
5042  out += nn*(nn-1);
5043  }
5044  }
5045  }
5046 
5047 
5048 
5049  // For the specialized loop used for the gradient computation in
5050  // here, the 1D shape values read (sorted lexicographically, rows
5051  // run over 1D dofs, columns over quadrature points):
5052  // Q2 --> [-2.549 -1 0.549 ]
5053  // [ 3.098 0 -3.098 ]
5054  // [-0.549 1 2.549 ]
5055  // Q3 --> [-4.315 -1.03 0.5 -0.44 ]
5056  // [ 6.07 -1.44 -2.97 2.196 ]
5057  // [-2.196 2.97 1.44 -6.07 ]
5058  // [ 0.44 -0.5 1.03 4.315 ]
5059  // Q4 --> [-6.316 -1.3 0.333 -0.353 0.413 ]
5060  // [10.111 -2.76 -2.667 2.066 -2.306 ]
5061  // [-5.688 5.773 0 -5.773 5.688 ]
5062  // [ 2.306 -2.066 2.667 2.76 -10.111 ]
5063  // [-0.413 0.353 -0.333 -0.353 0.413 ]
5064  //
5065  // In these matrices, we want to use avoid computations involving
5066  // zeros and ones and in addition use the symmetry in entries to
5067  // reduce the number of read operations.
5068  template <int dim, int fe_degree, int n_q_points_1d, typename Number>
5069  template <int direction, bool dof_to_quad, bool add>
5070  inline
5071  void
5072  EvaluatorTensorProduct<evaluate_symmetric,dim,fe_degree,n_q_points_1d,Number>
5073  ::gradients (const Number in [],
5074  Number out []) const
5075  {
5076  AssertIndexRange (direction, dim);
5077  const int mm = dof_to_quad ? (fe_degree+1) : n_q_points_1d,
5078  nn = dof_to_quad ? n_q_points_1d : (fe_degree+1);
5079  const int n_cols = nn / 2;
5080  const int mid = mm / 2;
5081 
5082  const int n_blocks1 = (dim > 1 ? (direction > 0 ? nn : mm) : 1);
5083  const int n_blocks2 = (dim > 2 ? (direction > 1 ? nn : mm) : 1);
5085 
5086  for (int i2=0; i2<n_blocks2; ++i2)
5087  {
5088  for (int i1=0; i1<n_blocks1; ++i1)
5089  {
5090  for (int col=0; col<n_cols; ++col)
5091  {
5092  Number val0, val1, in0, in1, res0, res1;
5093  if (dof_to_quad == true)
5094  {
5095  val0 = shape_gradients[col];
5096  val1 = shape_gradients[nn-1-col];
5097  }
5098  else
5099  {
5100  val0 = shape_gradients[col*n_q_points_1d];
5101  val1 = shape_gradients[(nn-col-1)*n_q_points_1d];
5102  }
5103  if (mid > 0)
5104  {
5105  in0 = in[0];
5106  in1 = in[stride*(mm-1)];
5107  res0 = val0 * in0;
5108  res1 = val1 * in0;
5109  res0 -= val1 * in1;
5110  res1 -= val0 * in1;
5111  for (int ind=1; ind<mid; ++ind)
5112  {
5113  if (dof_to_quad == true)
5114  {
5115  val0 = shape_gradients[ind*n_q_points_1d+col];
5116  val1 = shape_gradients[ind*n_q_points_1d+nn-1-col];
5117  }
5118  else
5119  {
5120  val0 = shape_gradients[col*n_q_points_1d+ind];
5121  val1 = shape_gradients[(nn-col-1)*n_q_points_1d+ind];
5122  }
5123  in0 = in[stride*ind];
5124  in1 = in[stride*(mm-1-ind)];
5125  res0 += val0 * in0;
5126  res1 += val1 * in0;
5127  res0 -= val1 * in1;
5128  res1 -= val0 * in1;
5129  }
5130  }
5131  else
5132  res0 = res1 = Number();
5133  if (mm % 2 == 1)
5134  {
5135  if (dof_to_quad == true)
5136  val0 = shape_gradients[mid*n_q_points_1d+col];
5137  else
5138  val0 = shape_gradients[col*n_q_points_1d+mid];
5139  val1 = val0 * in[stride*mid];
5140  res0 += val1;
5141  res1 -= val1;
5142  }
5143  if (add == false)
5144  {
5145  out[stride*col] = res0;
5146  out[stride*(nn-1-col)] = res1;
5147  }
5148  else
5149  {
5150  out[stride*col] += res0;
5151  out[stride*(nn-1-col)] += res1;
5152  }
5153  }
5154  if ( nn%2 == 1 )
5155  {
5156  Number val0, res0;
5157  if (dof_to_quad == true)
5158  val0 = shape_gradients[n_cols];
5159  else
5160  val0 = shape_gradients[n_cols*n_q_points_1d];
5161  res0 = in[0] - in[stride*(mm-1)];
5162  res0 *= val0;
5163  for (int ind=1; ind<mid; ++ind)
5164  {
5165  if (dof_to_quad == true)
5166  val0 = shape_gradients[ind*n_q_points_1d+n_cols];
5167  else
5168  val0 = shape_gradients[n_cols*n_q_points_1d+ind];
5169  Number val1 = in[stride*ind] - in[stride*(mm-1-ind)];
5170  val1 *= val0;
5171  res0 += val1;
5172  }
5173  if (add == false)
5174  out[stride*n_cols] = res0;
5175  else
5176  out[stride*n_cols] += res0;
5177  }
5178 
5179  // increment: in regular case, just go to the next point in
5180  // x-direction. for y-part in 3D and if we are at the end of one
5181  // chunk in x-dir, need to jump over to the next layer in
5182  // z-direction
5183  switch (direction)
5184  {
5185  case 0:
5186  in += mm;
5187  out += nn;
5188  break;
5189  case 1:
5190  case 2:
5191  ++in;
5192  ++out;
5193  break;
5194  default:
5195  Assert (false, ExcNotImplemented());
5196  }
5197  }
5198 
5199  if (direction == 1)
5200  {
5201  in += nn * (mm-1);
5202  out += nn * (nn-1);
5203  }
5204  }
5205  }
5206 
5207 
5208 
5209  // evaluates the given shape data in 1d-3d using the tensor product
5210  // form assuming the symmetries of unit cell shape hessians for
5211  // finite elements in FEEvaluation
5212  template <int dim, int fe_degree, int n_q_points_1d, typename Number>
5213  template <int direction, bool dof_to_quad, bool add>
5214  inline
5215  void
5216  EvaluatorTensorProduct<evaluate_symmetric,dim,fe_degree,n_q_points_1d,Number>
5217  ::hessians (const Number in [],
5218  Number out []) const
5219  {
5220  AssertIndexRange (direction, dim);
5221  const int mm = dof_to_quad ? (fe_degree+1) : n_q_points_1d,
5222  nn = dof_to_quad ? n_q_points_1d : (fe_degree+1);
5223  const int n_cols = nn / 2;
5224  const int mid = mm / 2;
5225 
5226  const int n_blocks1 = (dim > 1 ? (direction > 0 ? nn : mm) : 1);
5227  const int n_blocks2 = (dim > 2 ? (direction > 1 ? nn : mm) : 1);
5229 
5230  for (int i2=0; i2<n_blocks2; ++i2)
5231  {
5232  for (int i1=0; i1<n_blocks1; ++i1)
5233  {
5234  for (int col=0; col<n_cols; ++col)
5235  {
5236  Number val0, val1, in0, in1, res0, res1;
5237  if (dof_to_quad == true)
5238  {
5239  val0 = shape_hessians[col];
5240  val1 = shape_hessians[nn-1-col];
5241  }
5242  else
5243  {
5244  val0 = shape_hessians[col*n_q_points_1d];
5245  val1 = shape_hessians[(col+1)*n_q_points_1d-1];
5246  }
5247  if (mid > 0)
5248  {
5249  in0 = in[0];
5250  in1 = in[stride*(mm-1)];
5251  res0 = val0 * in0;
5252  res1 = val1 * in0;
5253  res0 += val1 * in1;
5254  res1 += val0 * in1;
5255  for (int ind=1; ind<mid; ++ind)
5256  {
5257  if (dof_to_quad == true)
5258  {
5259  val0 = shape_hessians[ind*n_q_points_1d+col];
5260  val1 = shape_hessians[ind*n_q_points_1d+nn-1-col];
5261  }
5262  else
5263  {
5264  val0 = shape_hessians[col*n_q_points_1d+ind];
5265  val1 = shape_hessians[(col+1)*n_q_points_1d-1-ind];
5266  }
5267  in0 = in[stride*ind];
5268  in1 = in[stride*(mm-1-ind)];
5269  res0 += val0 * in0;
5270  res1 += val1 * in0;
5271  res0 += val1 * in1;
5272  res1 += val0 * in1;
5273  }
5274  }
5275  else
5276  res0 = res1 = Number();
5277  if (mm % 2 == 1)
5278  {
5279  if (dof_to_quad == true)
5280  val0 = shape_hessians[mid*n_q_points_1d+col];
5281  else
5282  val0 = shape_hessians[col*n_q_points_1d+mid];
5283  val1 = val0 * in[stride*mid];
5284  res0 += val1;
5285  res1 += val1;
5286  }
5287  if (add == false)
5288  {
5289  out[stride*col] = res0;
5290  out[stride*(nn-1-col)] = res1;
5291  }
5292  else
5293  {
5294  out[stride*col] += res0;
5295  out[stride*(nn-1-col)] += res1;
5296  }
5297  }
5298  if ( nn%2 == 1 )
5299  {
5300  Number val0, res0;
5301  if (dof_to_quad == true)
5302  val0 = shape_hessians[n_cols];
5303  else
5304  val0 = shape_hessians[n_cols*n_q_points_1d];
5305  if (mid > 0)
5306  {
5307  res0 = in[0] + in[stride*(mm-1)];
5308  res0 *= val0;
5309  for (int ind=1; ind<mid; ++ind)
5310  {
5311  if (dof_to_quad == true)
5312  val0 = shape_hessians[ind*n_q_points_1d+n_cols];
5313  else
5314  val0 = shape_hessians[n_cols*n_q_points_1d+ind];
5315  Number val1 = in[stride*ind] + in[stride*(mm-1-ind)];
5316  val1 *= val0;
5317  res0 += val1;
5318  }
5319  }
5320  else
5321  res0 = Number();
5322  if (mm % 2 == 1)
5323  {
5324  if (dof_to_quad == true)
5325  val0 = shape_hessians[mid*n_q_points_1d+n_cols];
5326  else
5327  val0 = shape_hessians[n_cols*n_q_points_1d+mid];
5328  res0 += val0 * in[stride*mid];
5329  }
5330  if (add == false)
5331  out[stride*n_cols] = res0;
5332  else
5333  out[stride*n_cols] += res0;
5334  }
5335 
5336  // increment: in regular case, just go to the next point in
5337  // x-direction. If we are at the end of one chunk in x-dir, need to
5338  // jump over to the next layer in z-direction
5339  switch (direction)
5340  {
5341  case 0:
5342  in += mm;
5343  out += nn;
5344  break;
5345  case 1:
5346  case 2:
5347  ++in;
5348  ++out;
5349  break;
5350  default:
5351  Assert (false, ExcNotImplemented());
5352  }
5353  }
5354  if (direction == 1)
5355  {
5356  in += nn*(mm-1);
5357  out += nn*(nn-1);
5358  }
5359  }
5360  }
5361 
5362 
5363 
5364  // This class implements a different approach to the symmetric case for
5365  // values, gradients, and Hessians also treated with the above functions: It
5366  // is possible to reduce the cost per dimension from N^2 to N^2/2, where N
5367  // is the number of 1D dofs (there are only N^2/2 different entries in the
5368  // shape matrix, so this is plausible). The approach is based on the idea of
5369  // applying the operator on the even and odd part of the input vectors
5370  // separately, given that the shape functions evaluated on quadrature points
5371  // are symmetric. This method is presented e.g. in the book "Implementing
5372  // Spectral Methods for Partial Differential Equations" by David A. Kopriva,
5373  // Springer, 2009, section 3.5.3 (Even-Odd-Decomposition). Even though the
5374  // experiments in the book say that the method is not efficient for N<20, it
5375  // is more efficient in the context where the loop bounds are compile-time
5376  // constants (templates).
5377  template <int dim, int fe_degree, int n_q_points_1d, typename Number>
5378  struct EvaluatorTensorProduct<evaluate_evenodd,dim,fe_degree,n_q_points_1d,Number>
5379  {
5380  static const unsigned int dofs_per_cell = Utilities::fixed_int_power<fe_degree+1,dim>::value;
5381  static const unsigned int n_q_points = Utilities::fixed_int_power<n_q_points_1d,dim>::value;
5382 
5387  EvaluatorTensorProduct ()
5388  :
5389  shape_values (0),
5390  shape_gradients (0),
5391  shape_hessians (0)
5392  {}
5393 
5398  EvaluatorTensorProduct (const AlignedVector<Number> &shape_values,
5399  const AlignedVector<Number> &shape_gradients,
5400  const AlignedVector<Number> &shape_hessians)
5401  :
5402  shape_values (shape_values.begin()),
5403  shape_gradients (shape_gradients.begin()),
5404  shape_hessians (shape_hessians.begin())
5405  {}
5406 
5407  template <int direction, bool dof_to_quad, bool add>
5408  void
5409  values (const Number in [],
5410  Number out[]) const
5411  {
5412  apply<direction,dof_to_quad,add,0>(shape_values, in, out);
5413  }
5414 
5415  template <int direction, bool dof_to_quad, bool add>
5416  void
5417  gradients (const Number in [],
5418  Number out[]) const
5419  {
5420  apply<direction,dof_to_quad,add,1>(shape_gradients, in, out);
5421  }
5422 
5423  template <int direction, bool dof_to_quad, bool add>
5424  void
5425  hessians (const Number in [],
5426  Number out[]) const
5427  {
5428  apply<direction,dof_to_quad,add,2>(shape_hessians, in, out);
5429  }
5430 
5431  template <int direction, bool dof_to_quad, bool add, int type>
5432  static void apply (const Number *shape_data,
5433  const Number in [],
5434  Number out []);
5435 
5436  const Number *shape_values;
5437  const Number *shape_gradients;
5438  const Number *shape_hessians;
5439  };
5440 
5441 
5442 
5443  template <int dim, int fe_degree, int n_q_points_1d, typename Number>
5444  template <int direction, bool dof_to_quad, bool add, int type>
5445  inline
5446  void
5447  EvaluatorTensorProduct<evaluate_evenodd,dim,fe_degree,n_q_points_1d,Number>
5448  ::apply (const Number *shapes,
5449  const Number in [],
5450  Number out [])
5451  {
5452  AssertIndexRange (type, 3);
5453  AssertIndexRange (direction, dim);
5454  const int mm = dof_to_quad ? (fe_degree+1) : n_q_points_1d,
5455  nn = dof_to_quad ? n_q_points_1d : (fe_degree+1);
5456  const int n_cols = nn / 2;
5457  const int mid = mm / 2;
5458 
5459  const int n_blocks1 = (dim > 1 ? (direction > 0 ? nn : mm) : 1);
5460  const int n_blocks2 = (dim > 2 ? (direction > 1 ? nn : mm) : 1);
5462 
5463  const int offset = (n_q_points_1d+1)/2;
5464 
5465  // this code may look very inefficient at first sight due to the many
5466  // different cases with if's at the innermost loop part, but all of the
5467  // conditionals can be evaluated at compile time because they are
5468  // templates, so the compiler should optimize everything away
5469  for (int i2=0; i2<n_blocks2; ++i2)
5470  {
5471  for (int i1=0; i1<n_blocks1; ++i1)
5472  {
5473  Number xp[mid>0?mid:1], xm[mid>0?mid:1];
5474  for (int i=0; i<mid; ++i)
5475  {
5476  if (dof_to_quad == true && type == 1)
5477  {
5478  xp[i] = in[stride*i] - in[stride*(mm-1-i)];
5479  xm[i] = in[stride*i] + in[stride*(mm-1-i)];
5480  }
5481  else
5482  {
5483  xp[i] = in[stride*i] + in[stride*(mm-1-i)];
5484  xm[i] = in[stride*i] - in[stride*(mm-1-i)];
5485  }
5486  }
5487  for (int col=0; col<n_cols; ++col)
5488  {
5489  Number r0, r1;
5490  if (mid > 0)
5491  {
5492  if (dof_to_quad == true)
5493  {
5494  r0 = shapes[col] * xp[0];
5495  r1 = shapes[fe_degree*offset + col] * xm[0];
5496  }
5497  else
5498  {
5499  r0 = shapes[col*offset] * xp[0];
5500  r1 = shapes[(fe_degree-col)*offset] * xm[0];
5501  }
5502  for (int ind=1; ind<mid; ++ind)
5503  {
5504  if (dof_to_quad == true)
5505  {
5506  r0 += shapes[ind*offset+col] * xp[ind];
5507  r1 += shapes[(fe_degree-ind)*offset+col] * xm[ind];
5508  }
5509  else
5510  {
5511  r0 += shapes[col*offset+ind] * xp[ind];
5512  r1 += shapes[(fe_degree-col)*offset+ind] * xm[ind];
5513  }
5514  }
5515  }
5516  else
5517  r0 = r1 = Number();
5518  if (mm % 2 == 1 && dof_to_quad == true)
5519  {
5520  if (type == 1)
5521  r1 += shapes[mid*offset+col] * in[stride*mid];
5522  else
5523  r0 += shapes[mid*offset+col] * in[stride*mid];
5524  }
5525  else if (mm % 2 == 1 && (nn % 2 == 0 || type > 0))
5526  r0 += shapes[col*offset+mid] * in[stride*mid];
5527 
5528  if (add == false)
5529  {
5530  out[stride*col] = r0 + r1;
5531  if (type == 1 && dof_to_quad == false)
5532  out[stride*(nn-1-col)] = r1 - r0;
5533  else
5534  out[stride*(nn-1-col)] = r0 - r1;
5535  }
5536  else
5537  {
5538  out[stride*col] += r0 + r1;
5539  if (type == 1 && dof_to_quad == false)
5540  out[stride*(nn-1-col)] += r1 - r0;
5541  else
5542  out[stride*(nn-1-col)] += r0 - r1;
5543  }
5544  }
5545  if ( type == 0 && dof_to_quad == true && nn%2==1 && mm%2==1 )
5546  {
5547  if (add==false)
5548  out[stride*n_cols] = in[stride*mid];
5549  else
5550  out[stride*n_cols] += in[stride*mid];
5551  }
5552  else if (dof_to_quad == true && nn%2==1)
5553  {
5554  Number r0;
5555  if (mid > 0)
5556  {
5557  r0 = shapes[n_cols] * xp[0];
5558  for (int ind=1; ind<mid; ++ind)
5559  r0 += shapes[ind*offset+n_cols] * xp[ind];
5560  }
5561  else
5562  r0 = Number();
5563  if (type != 1 && mm % 2 == 1)
5564  r0 += shapes[mid*offset+n_cols] * in[stride*mid];
5565 
5566  if (add == false)
5567  out[stride*n_cols] = r0;
5568  else
5569  out[stride*n_cols] += r0;
5570  }
5571  else if (dof_to_quad == false && nn%2 == 1)
5572  {
5573  Number r0;
5574  if (mid > 0)
5575  {
5576  if (type == 1)
5577  {
5578  r0 = shapes[n_cols*offset] * xm[0];
5579  for (int ind=1; ind<mid; ++ind)
5580  r0 += shapes[n_cols*offset+ind] * xm[ind];
5581  }
5582  else
5583  {
5584  r0 = shapes[n_cols*offset] * xp[0];
5585  for (int ind=1; ind<mid; ++ind)
5586  r0 += shapes[n_cols*offset+ind] * xp[ind];
5587  }
5588  }
5589  else
5590  r0 = Number();
5591 
5592  if (type == 0 && mm % 2 == 1)
5593  r0 += in[stride*mid];
5594  else if (type == 2 && mm % 2 == 1)
5595  r0 += shapes[n_cols*offset+mid] * in[stride*mid];
5596 
5597  if (add == false)
5598  out[stride*n_cols] = r0;
5599  else
5600  out[stride*n_cols] += r0;
5601  }
5602 
5603  // increment: in regular case, just go to the next point in
5604  // x-direction. If we are at the end of one chunk in x-dir, need to
5605  // jump over to the next layer in z-direction
5606  switch (direction)
5607  {
5608  case 0:
5609  in += mm;
5610  out += nn;
5611  break;
5612  case 1:
5613  case 2:
5614  ++in;
5615  ++out;
5616  break;
5617  default:
5618  Assert (false, ExcNotImplemented());
5619  }
5620  }
5621  if (direction == 1)
5622  {
5623  in += nn*(mm-1);
5624  out += nn*(nn-1);
5625  }
5626  }
5627  }
5628 
5629 
5630 
5631  // Select evaluator type from element shape function type
5632  template <MatrixFreeFunctions::ElementType element, bool is_long>
5633  struct EvaluatorSelector {};
5634 
5635  template <bool is_long>
5636  struct EvaluatorSelector<MatrixFreeFunctions::tensor_general,is_long>
5637  {
5638  static const EvaluatorVariant variant = evaluate_general;
5639  };
5640 
5641  template <>
5642  struct EvaluatorSelector<MatrixFreeFunctions::tensor_symmetric,false>
5643  {
5644  static const EvaluatorVariant variant = evaluate_symmetric;
5645  };
5646 
5647  template <> struct EvaluatorSelector<MatrixFreeFunctions::tensor_symmetric,true>
5648  {
5649  static const EvaluatorVariant variant = evaluate_evenodd;
5650  };
5651 
5652  template <bool is_long>
5653  struct EvaluatorSelector<MatrixFreeFunctions::truncated_tensor,is_long>
5654  {
5655  static const EvaluatorVariant variant = evaluate_general;
5656  };
5657 
5658  template <>
5659  struct EvaluatorSelector<MatrixFreeFunctions::tensor_symmetric_plus_dg0,false>
5660  {
5661  static const EvaluatorVariant variant = evaluate_symmetric;
5662  };
5663 
5664  template <>
5665  struct EvaluatorSelector<MatrixFreeFunctions::tensor_symmetric_plus_dg0,true>
5666  {
5667  static const EvaluatorVariant variant = evaluate_evenodd;
5668  };
5669 
5670  template <bool is_long>
5671  struct EvaluatorSelector<MatrixFreeFunctions::tensor_gausslobatto,is_long>
5672  {
5673  static const EvaluatorVariant variant = evaluate_evenodd;
5674  };
5675 
5676 
5677 
5678  // This struct performs the evaluation of function values, gradients and
5679  // Hessians for tensor-product finite elements. The operation is used for
5680  // both the symmetric and non-symmetric case, which use different apply
5681  // functions 'values', 'gradients' in the individual coordinate
5682  // directions. The apply functions for values are provided through one of
5683  // the template classes EvaluatorTensorProduct which in turn are selected
5684  // from the MatrixFreeFunctions::ElementType template argument.
5685  //
5686  // There is a specialization made for Gauss-Lobatto elements further down
5687  // where the 'values' operation is identity, which allows us to write
5688  // shorter code.
5689  template <MatrixFreeFunctions::ElementType type, int dim, int fe_degree,
5690  int n_q_points_1d, int n_components, typename Number>
5691  struct FEEvaluationImpl
5692  {
5693  static
5694  void evaluate (const MatrixFreeFunctions::ShapeInfo<Number> &shape_info,
5695  VectorizedArray<Number> *values_dofs_actual[],
5696  VectorizedArray<Number> *values_quad[],
5697  VectorizedArray<Number> *gradients_quad[][dim],
5698  VectorizedArray<Number> *hessians_quad[][(dim*(dim+1))/2],
5699  const bool evaluate_val,
5700  const bool evaluate_grad,
5701  const bool evaluate_lapl);
5702 
5703  static
5704  void integrate (const MatrixFreeFunctions::ShapeInfo<Number> &shape_info,
5705  VectorizedArray<Number> *values_dofs_actual[],
5706  VectorizedArray<Number> *values_quad[],
5707  VectorizedArray<Number> *gradients_quad[][dim],
5708  const bool evaluate_val,
5709  const bool evaluate_grad);
5710  };
5711 
5712 
5713  template <MatrixFreeFunctions::ElementType type, int dim, int fe_degree,
5714  int n_q_points_1d, int n_components, typename Number>
5715  inline
5716  void
5717  FEEvaluationImpl<type,dim,fe_degree,n_q_points_1d,n_components,Number>
5718  ::evaluate (const MatrixFreeFunctions::ShapeInfo<Number> &shape_info,
5719  VectorizedArray<Number> *values_dofs_actual[],
5720  VectorizedArray<Number> *values_quad[],
5721  VectorizedArray<Number> *gradients_quad[][dim],
5722  VectorizedArray<Number> *hessians_quad[][(dim*(dim+1))/2],
5723  const bool evaluate_val,
5724  const bool evaluate_grad,
5725  const bool evaluate_lapl)
5726  {
5727  if (evaluate_val == false && evaluate_grad == false && evaluate_lapl == false)
5728  return;
5729 
5730  const EvaluatorVariant variant =
5731  EvaluatorSelector<type,(fe_degree+n_q_points_1d>4)>::variant;
5732  typedef EvaluatorTensorProduct<variant, dim, fe_degree, n_q_points_1d,
5733  VectorizedArray<Number> > Eval;
5734  Eval eval (variant == evaluate_evenodd ? shape_info.shape_val_evenodd :
5735  shape_info.shape_values,
5736  variant == evaluate_evenodd ? shape_info.shape_gra_evenodd :
5737  shape_info.shape_gradients,
5738  variant == evaluate_evenodd ? shape_info.shape_hes_evenodd :
5739  shape_info.shape_hessians);
5740 
5741  const unsigned int temp_size = Eval::dofs_per_cell > Eval::n_q_points ?
5742  Eval::dofs_per_cell : Eval::n_q_points;
5743 
5744  VectorizedArray<Number> **values_dofs = values_dofs_actual;
5745  VectorizedArray<Number> data_array[type!=MatrixFreeFunctions::truncated_tensor ? 1 :
5746  n_components*Eval::dofs_per_cell];
5747  VectorizedArray<Number> *expanded_dof_values[n_components];
5748  if (type == MatrixFreeFunctions::truncated_tensor)
5749  {
5750  for (unsigned int c=0; c<n_components; ++c)
5751  expanded_dof_values[c] = &data_array[c*Eval::dofs_per_cell];
5752  values_dofs = expanded_dof_values;
5753 
5754  unsigned int count_p = 0, count_q = 0;
5755  for (unsigned int i=0; i<(dim>2?fe_degree+1:1); ++i)
5756  {
5757  for (unsigned int j=0; j<(dim>1?fe_degree+1-i:1); ++j)
5758  {
5759  for (unsigned int k=0; k<fe_degree+1-j-i; ++k, ++count_p, ++count_q)
5760  for (unsigned int c=0; c<n_components; ++c)
5761  expanded_dof_values[c][count_q] = values_dofs_actual[c][count_p];
5762  for (unsigned int k=fe_degree+1-j-i; k<fe_degree+1; ++k, ++count_q)
5763  for (unsigned int c=0; c<n_components; ++c)
5764  expanded_dof_values[c][count_q] = VectorizedArray<Number>();
5765  }
5766  for (unsigned int j=fe_degree+1-i; j<fe_degree+1; ++j)
5767  for (unsigned int k=0; k<fe_degree+1; ++k, ++count_q)
5768  for (unsigned int c=0; c<n_components; ++c)
5769  expanded_dof_values[c][count_q] = VectorizedArray<Number>();
5770  }
5771  AssertDimension(count_q, Eval::dofs_per_cell);
5772  }
5773 
5774  // These avoid compiler errors; they are only used in sensible context but
5775  // compilers typically cannot detect when we access something like
5776  // gradients_quad[2] only for dim==3.
5777  const unsigned int d1 = dim>1?1:0;
5778  const unsigned int d2 = dim>2?2:0;
5779  const unsigned int d3 = dim>2?3:0;
5780  const unsigned int d4 = dim>2?4:0;
5781  const unsigned int d5 = dim>2?5:0;
5782 
5783  switch (dim)
5784  {
5785  case 1:
5786  for (unsigned int c=0; c<n_components; c++)
5787  {
5788  if (evaluate_val == true)
5789  eval.template values<0,true,false> (values_dofs[c], values_quad[c]);
5790  if (evaluate_grad == true)
5791  eval.template gradients<0,true,false>(values_dofs[c], gradients_quad[c][0]);
5792  if (evaluate_lapl == true)
5793  eval.template hessians<0,true,false> (values_dofs[c], hessians_quad[c][0]);
5794  }
5795  break;
5796 
5797  case 2:
5798  for (unsigned int c=0; c<n_components; c++)
5799  {
5800  VectorizedArray<Number> temp1[temp_size];
5801 
5802  // grad x
5803  if (evaluate_grad == true)
5804  {
5805  eval.template gradients<0,true,false> (values_dofs[c], temp1);
5806  eval.template values<1,true,false> (temp1, gradients_quad[c][0]);
5807  }
5808  if (evaluate_lapl == true)
5809  {
5810  // grad xy
5811  if (evaluate_grad == false)
5812  eval.template gradients<0,true,false>(values_dofs[c], temp1);
5813  eval.template gradients<1,true,false> (temp1, hessians_quad[c][d1+d1]);
5814 
5815  // grad xx
5816  eval.template hessians<0,true,false>(values_dofs[c], temp1);
5817  eval.template values<1,true,false> (temp1, hessians_quad[c][0]);
5818  }
5819 
5820  // grad y
5821  eval.template values<0,true,false> (values_dofs[c], temp1);
5822  if (evaluate_grad == true)
5823  eval.template gradients<1,true,false> (temp1, gradients_quad[c][d1]);
5824 
5825  // grad yy
5826  if (evaluate_lapl == true)
5827  eval.template hessians<1,true,false> (temp1, hessians_quad[c][d1]);
5828 
5829  // val: can use values applied in x
5830  if (evaluate_val == true)
5831  eval.template values<1,true,false> (temp1, values_quad[c]);
5832  }
5833  break;
5834 
5835  case 3:
5836  for (unsigned int c=0; c<n_components; c++)
5837  {
5838  VectorizedArray<Number> temp1[temp_size];
5839  VectorizedArray<Number> temp2[temp_size];
5840 
5841  if (evaluate_grad == true)
5842  {
5843  // grad x
5844  eval.template gradients<0,true,false> (values_dofs[c], temp1);
5845  eval.template values<1,true,false> (temp1, temp2);
5846  eval.template values<2,true,false> (temp2, gradients_quad[c][0]);
5847  }
5848 
5849  if (evaluate_lapl == true)
5850  {
5851  // grad xz
5852  if (evaluate_grad == false)
5853  {
5854  eval.template gradients<0,true,false> (values_dofs[c], temp1);
5855  eval.template values<1,true,false> (temp1, temp2);
5856  }
5857  eval.template gradients<2,true,false> (temp2, hessians_quad[c][d4]);
5858 
5859  // grad xy
5860  eval.template gradients<1,true,false> (temp1, temp2);
5861  eval.template values<2,true,false> (temp2, hessians_quad[c][d3]);
5862 
5863  // grad xx
5864  eval.template hessians<0,true,false>(values_dofs[c], temp1);
5865  eval.template values<1,true,false> (temp1, temp2);
5866  eval.template values<2,true,false> (temp2, hessians_quad[c][0]);
5867  }
5868 
5869  // grad y
5870  eval.template values<0,true,false> (values_dofs[c], temp1);
5871  if (evaluate_grad == true)
5872  {
5873  eval.template gradients<1,true,false>(temp1, temp2);
5874  eval.template values<2,true,false> (temp2, gradients_quad[c][d1]);
5875  }
5876 
5877  if (evaluate_lapl == true)
5878  {
5879  // grad yz
5880  if (evaluate_grad == false)
5881  eval.template gradients<1,true,false>(temp1, temp2);
5882  eval.template gradients<2,true,false> (temp2, hessians_quad[c][d5]);
5883 
5884  // grad yy
5885  eval.template hessians<1,true,false> (temp1, temp2);
5886  eval.template values<2,true,false> (temp2, hessians_quad[c][d1]);
5887  }
5888 
5889  // grad z: can use the values applied in x direction stored in temp1
5890  eval.template values<1,true,false> (temp1, temp2);
5891  if (evaluate_grad == true)
5892  eval.template gradients<2,true,false> (temp2, gradients_quad[c][d2]);
5893 
5894  // grad zz: can use the values applied in x and y direction stored
5895  // in temp2
5896  if (evaluate_lapl == true)
5897  eval.template hessians<2,true,false>(temp2, hessians_quad[c][d2]);
5898 
5899  // val: can use the values applied in x & y direction stored in temp2
5900  if (evaluate_val == true)
5901  eval.template values<2,true,false> (temp2, values_quad[c]);
5902  }
5903  break;
5904 
5905  default:
5906  AssertThrow(false, ExcNotImplemented());
5907  }
5908 
5909  // case additional dof for FE_Q_DG0: add values; gradients and second
5910  // derivatives evaluate to zero
5911  if (type == MatrixFreeFunctions::tensor_symmetric_plus_dg0 && evaluate_val)
5912  for (unsigned int c=0; c<n_components; ++c)
5913  for (unsigned int q=0; q<Eval::n_q_points; ++q)
5914  values_quad[c][q] += values_dofs[c][Eval::dofs_per_cell];
5915  }
5916 
5917 
5918 
5919  template <MatrixFreeFunctions::ElementType type, int dim, int fe_degree,
5920  int n_q_points_1d, int n_components, typename Number>
5921  inline
5922  void
5923  FEEvaluationImpl<type,dim,fe_degree,n_q_points_1d,n_components,Number>
5924  ::integrate (const MatrixFreeFunctions::ShapeInfo<Number> &shape_info,
5925  VectorizedArray<Number> *values_dofs_actual[],
5926  VectorizedArray<Number> *values_quad[],
5927  VectorizedArray<Number> *gradients_quad[][dim],
5928  const bool integrate_val,
5929  const bool integrate_grad)
5930  {
5931  const EvaluatorVariant variant =
5932  EvaluatorSelector<type,(fe_degree+n_q_points_1d>4)>::variant;
5933  typedef EvaluatorTensorProduct<variant, dim, fe_degree, n_q_points_1d,
5934  VectorizedArray<Number> > Eval;
5935  Eval eval (variant == evaluate_evenodd ? shape_info.shape_val_evenodd :
5936  shape_info.shape_values,
5937  variant == evaluate_evenodd ? shape_info.shape_gra_evenodd :
5938  shape_info.shape_gradients,
5939  variant == evaluate_evenodd ? shape_info.shape_hes_evenodd :
5940  shape_info.shape_hessians);
5941 
5942  const unsigned int temp_size = Eval::dofs_per_cell > Eval::n_q_points ?
5943  Eval::dofs_per_cell : Eval::n_q_points;
5944  VectorizedArray<Number> temp1[temp_size];
5945  VectorizedArray<Number> temp2[temp_size];
5946 
5947  // expand dof_values to tensor product for truncated tensor products
5948  VectorizedArray<Number> **values_dofs = values_dofs_actual;
5949  VectorizedArray<Number> data_array[type!=MatrixFreeFunctions::truncated_tensor ? 1 :
5950  n_components*Eval::dofs_per_cell];
5951  VectorizedArray<Number> *expanded_dof_values[n_components];
5952  if (type == MatrixFreeFunctions::truncated_tensor)
5953  {
5954  for (unsigned int c=0; c<n_components; ++c)
5955  expanded_dof_values[c] = &data_array[c*Eval::dofs_per_cell];
5956  values_dofs = expanded_dof_values;
5957  }
5958 
5959  // These avoid compiler errors; they are only used in sensible context but
5960  // compilers typically cannot detect when we access something like
5961  // gradients_quad[2] only for dim==3.
5962  const unsigned int d1 = dim>1?1:0;
5963  const unsigned int d2 = dim>2?2:0;
5964 
5965  switch (dim)
5966  {
5967  case 1:
5968  for (unsigned int c=0; c<n_components; c++)
5969  {
5970  if (integrate_val == true)
5971  eval.template values<0,false,false> (values_quad[c], values_dofs[c]);
5972  if (integrate_grad == true)
5973  {
5974  if (integrate_val == true)
5975  eval.template gradients<0,false,true> (gradients_quad[c][0], values_dofs[c]);
5976  else
5977  eval.template gradients<0,false,false> (gradients_quad[c][0], values_dofs[c]);
5978  }
5979  }
5980  break;
5981 
5982  case 2:
5983  for (unsigned int c=0; c<n_components; c++)
5984  {
5985  if (integrate_val == true)
5986  {
5987  // val
5988  eval.template values<0,false,false> (values_quad[c], temp1);
5989  //grad x
5990  if (integrate_grad == true)
5991  eval.template gradients<0,false,true> (gradients_quad[c][0], temp1);
5992  eval.template values<1,false,false>(temp1, values_dofs[c]);
5993  }
5994  if (integrate_grad == true)
5995  {
5996  // grad y
5997  eval.template values<0,false,false> (gradients_quad[c][d1], temp1);
5998  if (integrate_val == false)
5999  {
6000  eval.template gradients<1,false,false>(temp1, values_dofs[c]);
6001  //grad x
6002  eval.template gradients<0,false,false> (gradients_quad[c][0], temp1);
6003  eval.template values<1,false,true> (temp1, values_dofs[c]);
6004  }
6005  else
6006  eval.template gradients<1,false,true>(temp1, values_dofs[c]);
6007  }
6008  }
6009  break;
6010 
6011  case 3:
6012  for (unsigned int c=0; c<n_components; c++)
6013  {
6014  if (integrate_val == true)
6015  {
6016  // val
6017  eval.template values<0,false,false> (values_quad[c], temp1);
6018  //grad x: can sum to temporary value in temp1
6019  if (integrate_grad == true)
6020  eval.template gradients<0,false,true> (gradients_quad[c][0], temp1);
6021  eval.template values<1,false,false>(temp1, temp2);
6022  if (integrate_grad == true)
6023  {
6024  eval.template values<0,false,false> (gradients_quad[c][d1], temp1);
6025  eval.template gradients<1,false,true>(temp1, temp2);
6026  }
6027  eval.template values<2,false,false> (temp2, values_dofs[c]);
6028  }
6029  else if (integrate_grad == true)
6030  {
6031  eval.template gradients<0,false,false>(gradients_quad[c][0], temp1);
6032  eval.template values<1,false,false> (temp1, temp2);
6033  eval.template values<0,false,false> (gradients_quad[c][d1], temp1);
6034  eval.template gradients<1,false,true>(temp1, temp2);
6035  eval.template values<2,false,false> (temp2, values_dofs[c]);
6036  }
6037  if (integrate_grad == true)
6038  {
6039  // grad z: can sum to temporary x and y value in output
6040  eval.template values<0,false,false> (gradients_quad[c][d2], temp1);
6041  eval.template values<1,false,false> (temp1, temp2);
6042  eval.template gradients<2,false,true> (temp2, values_dofs[c]);
6043  }
6044  }
6045  break;
6046 
6047  default:
6048  AssertThrow(false, ExcNotImplemented());
6049  }
6050 
6051  // case FE_Q_DG0: add values, gradients and second derivatives are zero
6052  if (type == MatrixFreeFunctions::tensor_symmetric_plus_dg0)
6053  {
6054  if (integrate_val)
6055  for (unsigned int c=0; c<n_components; ++c)
6056  {
6057  values_dofs[c][Eval::dofs_per_cell] = values_quad[c][0];
6058  for (unsigned int q=1; q<Eval::n_q_points; ++q)
6059  values_dofs[c][Eval::dofs_per_cell] += values_quad[c][q];
6060  }
6061  else
6062  for (unsigned int c=0; c<n_components; ++c)
6063  values_dofs[c][Eval::dofs_per_cell] = VectorizedArray<Number>();
6064  }
6065 
6066  if (type == MatrixFreeFunctions::truncated_tensor)
6067  {
6068  unsigned int count_p = 0, count_q = 0;
6069  for (unsigned int i=0; i<(dim>2?fe_degree+1:1); ++i)
6070  {
6071  for (unsigned int j=0; j<(dim>1?fe_degree+1-i:1); ++j)
6072  {
6073  for (unsigned int k=0; k<fe_degree+1-j-i; ++k, ++count_p, ++count_q)
6074  {
6075  for (unsigned int c=0; c<n_components; ++c)
6076  values_dofs_actual[c][count_p] = expanded_dof_values[c][count_q];
6077  }
6078  count_q += j+i;
6079  }
6080  count_q += i*(fe_degree+1);
6081  }
6082  AssertDimension(count_q, Eval::dofs_per_cell);
6083  }
6084  }
6085 
6086  // This a specialization for Gauss-Lobatto elements where the 'values'
6087  // operation is identity, which allows us to write shorter code.
6088  template <int dim, int fe_degree, int n_q_points_1d, int n_components, typename Number>
6089  struct FEEvaluationImpl<MatrixFreeFunctions::tensor_gausslobatto, dim,
6090  fe_degree, n_q_points_1d, n_components, Number>
6091  {
6092  static
6093  void evaluate (const MatrixFreeFunctions::ShapeInfo<Number> &shape_info,
6094  VectorizedArray<Number> *values_dofs[],
6095  VectorizedArray<Number> *values_quad[],
6096  VectorizedArray<Number> *gradients_quad[][dim],
6097  VectorizedArray<Number> *hessians_quad[][(dim*(dim+1))/2],
6098  const bool evaluate_val,
6099  const bool evaluate_grad,
6100  const bool evaluate_lapl);
6101 
6102  static
6103  void integrate (const MatrixFreeFunctions::ShapeInfo<Number> &shape_info,
6104  VectorizedArray<Number> *values_dofs[],
6105  VectorizedArray<Number> *values_quad[],
6106  VectorizedArray<Number> *gradients_quad[][dim],
6107  const bool integrate_val,
6108  const bool integrate_grad);
6109  };
6110 
6111  template <int dim, int fe_degree, int n_q_points_1d, int n_components, typename Number>
6112  inline
6113  void
6114  FEEvaluationImpl<MatrixFreeFunctions::tensor_gausslobatto, dim,
6115  fe_degree, n_q_points_1d, n_components, Number>
6116  ::evaluate (const MatrixFreeFunctions::ShapeInfo<Number> &shape_info,
6117  VectorizedArray<Number> *values_dofs[],
6118  VectorizedArray<Number> *values_quad[],
6119  VectorizedArray<Number> *gradients_quad[][dim],
6120  VectorizedArray<Number> *hessians_quad[][(dim*(dim+1))/2],
6121  const bool evaluate_val,
6122  const bool evaluate_grad,
6123  const bool evaluate_lapl)
6124  {
6125  typedef EvaluatorTensorProduct<evaluate_evenodd, dim, fe_degree, fe_degree+1,
6126  VectorizedArray<Number> > Eval;
6127  Eval eval (shape_info.shape_val_evenodd, shape_info.shape_gra_evenodd,
6128  shape_info.shape_hes_evenodd);
6129 
6130  // These avoid compiler errors; they are only used in sensible context but
6131  // compilers typically cannot detect when we access something like
6132  // gradients_quad[2] only for dim==3.
6133  const unsigned int d1 = dim>1?1:0;
6134  const unsigned int d2 = dim>2?2:0;
6135  const unsigned int d3 = dim>2?3:0;
6136  const unsigned int d4 = dim>2?4:0;
6137  const unsigned int d5 = dim>2?5:0;
6138 
6139  switch (dim)
6140  {
6141  case 1:
6142  if (evaluate_val == true)
6143  std::memcpy (values_quad[0], values_dofs[0],
6144  eval.dofs_per_cell * n_components *
6145  sizeof (values_dofs[0][0]));
6146  for (unsigned int c=0; c<n_components; c++)
6147  {
6148  if (evaluate_grad == true)
6149  eval.template gradients<0,true,false>(values_dofs[c], gradients_quad[c][0]);
6150  if (evaluate_lapl == true)
6151  eval.template hessians<0,true,false> (values_dofs[c], hessians_quad[c][0]);
6152  }
6153  break;
6154 
6155  case 2:
6156  if (evaluate_val == true)
6157  {
6158  std::memcpy (values_quad[0], values_dofs[0],
6159  Eval::dofs_per_cell * n_components *
6160  sizeof (values_dofs[0][0]));
6161  }
6162  if (evaluate_grad == true)
6163  for (unsigned int comp=0; comp<n_components; comp++)
6164  {
6165  // grad x
6166  eval.template gradients<0,true,false> (values_dofs[comp],
6167  gradients_quad[comp][0]);
6168  // grad y
6169  eval.template gradients<1,true,false> (values_dofs[comp],
6170  gradients_quad[comp][d1]);
6171  }
6172  if (evaluate_lapl == true)
6173  for (unsigned int comp=0; comp<n_components; comp++)
6174  {
6175  // hess x
6176  eval.template hessians<0,true,false> (values_dofs[comp],
6177  hessians_quad[comp][0]);
6178  // hess y
6179  eval.template hessians<1,true,false> (values_dofs[comp],
6180  hessians_quad[comp][d1]);
6181 
6182  VectorizedArray<Number> temp1[Eval::dofs_per_cell];
6183  // grad x grad y
6184  eval.template gradients<0,true,false> (values_dofs[comp], temp1);
6185  eval.template gradients<1,true,false> (temp1, hessians_quad[comp][d1+d1]);
6186  }
6187  break;
6188 
6189  case 3:
6190  if (evaluate_val == true)
6191  {
6192  std::memcpy (values_quad[0], values_dofs[0],
6193  Eval::dofs_per_cell * n_components *
6194  sizeof (values_dofs[0][0]));
6195  }
6196  if (evaluate_grad == true)
6197  for (unsigned int comp=0; comp<n_components; comp++)
6198  {
6199  // grad x
6200  eval.template gradients<0,true,false> (values_dofs[comp],
6201  gradients_quad[comp][0]);
6202  // grad y
6203  eval.template gradients<1,true,false> (values_dofs[comp],
6204  gradients_quad[comp][d1]);
6205  // grad y
6206  eval.template gradients<2,true,false> (values_dofs[comp],
6207  gradients_quad[comp][d2]);
6208  }
6209  if (evaluate_lapl == true)
6210  for (unsigned int comp=0; comp<n_components; comp++)
6211  {
6212  // grad x
6213  eval.template hessians<0,true,false> (values_dofs[comp],
6214  hessians_quad[comp][0]);
6215  // grad y
6216  eval.template hessians<1,true,false> (values_dofs[comp],
6217  hessians_quad[comp][d1]);
6218  // grad y
6219  eval.template hessians<2,true,false> (values_dofs[comp],
6220  hessians_quad[comp][d2]);
6221 
6222  VectorizedArray<Number> temp1[Eval::dofs_per_cell];
6223  // grad xy
6224  eval.template gradients<0,true,false> (values_dofs[comp], temp1);
6225  eval.template gradients<1,true,false> (temp1, hessians_quad[comp][d3]);
6226  // grad xz
6227  eval.template gradients<2,true,false> (temp1, hessians_quad[comp][d4]);
6228  // grad yz
6229  eval.template gradients<1,true,false> (values_dofs[comp], temp1);
6230  eval.template gradients<2,true,false> (temp1, hessians_quad[comp][d5]);
6231  }
6232  break;
6233  default:
6234  AssertThrow(false, ExcNotImplemented());
6235  }
6236  }
6237 
6238  template <int dim, int fe_degree, int n_q_points_1d, int n_components, typename Number>
6239  inline
6240  void
6241  FEEvaluationImpl<MatrixFreeFunctions::tensor_gausslobatto, dim,
6242  fe_degree, n_q_points_1d, n_components, Number>
6243  ::integrate (const MatrixFreeFunctions::ShapeInfo<Number> &shape_info,
6244  VectorizedArray<Number> *values_dofs[],
6245  VectorizedArray<Number> *values_quad[],
6246  VectorizedArray<Number> *gradients_quad[][dim],
6247  const bool integrate_val,
6248  const bool integrate_grad)
6249  {
6250  typedef EvaluatorTensorProduct<evaluate_evenodd, dim, fe_degree, fe_degree+1,
6251  VectorizedArray<Number> > Eval;
6252  Eval eval (shape_info.shape_val_evenodd, shape_info.shape_gra_evenodd,
6253  shape_info.shape_hes_evenodd);
6254 
6255  // These avoid compiler errors; they are only used in sensible context but
6256  // compilers typically cannot detect when we access something like
6257  // gradients_quad[2] only for dim==3.
6258  const unsigned int d1 = dim>1?1:0;
6259  const unsigned int d2 = dim>2?2:0;
6260 
6261  if (integrate_val == true)
6262  std::memcpy (values_dofs[0], values_quad[0],
6263  Eval::dofs_per_cell * n_components *
6264  sizeof (values_dofs[0][0]));
6265  switch (dim)
6266  {
6267  case 1:
6268  for (unsigned int c=0; c<n_components; c++)
6269  {
6270  if (integrate_grad == true)
6271  {
6272  if (integrate_val == true)
6273  eval.template gradients<0,false,true> (gradients_quad[c][0],
6274  values_dofs[c]);
6275  else
6276  eval.template gradients<0,false,false> (gradients_quad[c][0],
6277  values_dofs[c]);
6278  }
6279  }
6280 
6281  break;
6282  case 2:
6283  if (integrate_grad == true)
6284  for (unsigned int comp=0; comp<n_components; comp++)
6285  {
6286  // grad x: If integrate_val == true we have to add to the
6287  // previous output
6288  if (integrate_val == true)
6289  eval.template gradients<0, false, true> (gradients_quad[comp][0],
6290  values_dofs[comp]);
6291  else
6292  eval.template gradients<0, false, false> (gradients_quad[comp][0],
6293  values_dofs[comp]);
6294 
6295  // grad y
6296  eval.template gradients<1, false, true> (gradients_quad[comp][d1],
6297  values_dofs[comp]);
6298  }
6299  break;
6300 
6301  case 3:
6302  if (integrate_grad == true)
6303  for (unsigned int comp=0; comp<n_components; comp++)
6304  {
6305  // grad x: If integrate_val == true we have to add to the
6306  // previous output
6307  if (integrate_val == true)
6308  eval.template gradients<0, false, true> (gradients_quad[comp][0],
6309  values_dofs[comp]);
6310  else
6311  eval.template gradients<0, false, false> (gradients_quad[comp][0],
6312  values_dofs[comp]);
6313 
6314  // grad y
6315  eval.template gradients<1, false, true> (gradients_quad[comp][d1],
6316  values_dofs[comp]);
6317 
6318  // grad z
6319  eval.template gradients<2, false, true> (gradients_quad[comp][d2],
6320  values_dofs[comp]);
6321  }
6322  break;
6323 
6324  default:
6325  AssertThrow(false, ExcNotImplemented());
6326  }
6327  }
6328 
6329 } // end of namespace internal
6330 
6331 
6332 
6333 /*-------------------------- FEEvaluation -----------------------------------*/
6334 
6335 
6336 template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
6337  typename Number>
6338 inline
6340 ::FEEvaluation (const MatrixFree<dim,Number> &data_in,
6341  const unsigned int fe_no,
6342  const unsigned int quad_no)
6343  :
6344  BaseClass (data_in, fe_no, quad_no, fe_degree, n_q_points),
6345  dofs_per_cell (this->data->dofs_per_cell)
6346 {
6347  check_template_arguments(fe_no);
6348  set_data_pointers();
6349 }
6350 
6351 
6352 
6353 template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
6354  typename Number>
6355 inline
6357 ::FEEvaluation (const Mapping<dim> &mapping,
6358  const FiniteElement<dim> &fe,
6359  const Quadrature<1> &quadrature,
6360  const UpdateFlags update_flags,
6361  const unsigned int first_selected_component)
6362  :
6363  BaseClass (mapping, fe, quadrature, update_flags,
6364  first_selected_component,
6365  static_cast<FEEvaluationBase<dim,1,Number>*>(0)),
6366  dofs_per_cell (this->data->dofs_per_cell)
6367 {
6368  check_template_arguments(numbers::invalid_unsigned_int);
6369  set_data_pointers();
6370 }
6371 
6372 
6373 
6374 template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
6375  typename Number>
6376 inline
6379  const Quadrature<1> &quadrature,
6380  const UpdateFlags update_flags,
6381  const unsigned int first_selected_component)
6382  :
6383  BaseClass (StaticMappingQ1<dim>::mapping, fe, quadrature, update_flags,
6384  first_selected_component,
6385  static_cast<FEEvaluationBase<dim,1,Number>*>(0)),
6386  dofs_per_cell (this->data->dofs_per_cell)
6387 {
6388  check_template_arguments(numbers::invalid_unsigned_int);
6389  set_data_pointers();
6390 }
6391 
6392 
6393 
6394 template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
6395  typename Number>
6396 template <int n_components_other>
6397 inline
6401  const unsigned int first_selected_component)
6402  :
6403  BaseClass (other.mapped_geometry->get_fe_values().get_mapping(),
6404  fe, other.mapped_geometry->get_quadrature(),
6405  other.mapped_geometry->get_fe_values().get_update_flags(),
6406  first_selected_component, &other),
6407  dofs_per_cell (this->data->dofs_per_cell)
6408 {
6409  check_template_arguments(numbers::invalid_unsigned_int);
6410  set_data_pointers();
6411 }
6412 
6413 
6414 
6415 template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
6416  typename Number>
6417 inline
6419 ::FEEvaluation (const FEEvaluation &other)
6420  :
6421  BaseClass (other),
6422  dofs_per_cell (this->data->dofs_per_cell)
6423 {
6424  set_data_pointers();
6425 }
6426 
6427 
6428 
6429 template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
6430  typename Number>
6431 inline
6432 void
6435 {
6436  AssertIndexRange(this->data->dofs_per_cell, tensor_dofs_per_cell+2);
6437  const unsigned int desired_dofs_per_cell = this->data->dofs_per_cell;
6438 
6439  // set the pointers to the correct position in the data array
6440  for (unsigned int c=0; c<n_components_; ++c)
6441  {
6442  this->values_dofs[c] = &my_data_array[c*desired_dofs_per_cell];
6443  this->values_quad[c] = &my_data_array[n_components*desired_dofs_per_cell+c*n_q_points];
6444  for (unsigned int d=0; d<dim; ++d)
6445  this->gradients_quad[c][d] = &my_data_array[n_components*(desired_dofs_per_cell+
6446  n_q_points)
6447  +
6448  (c*dim+d)*n_q_points];
6449  for (unsigned int d=0; d<(dim*dim+dim)/2; ++d)
6450  this->hessians_quad[c][d] = &my_data_array[n_components*((dim+1)*n_q_points+
6451  desired_dofs_per_cell)
6452  +
6453  (c*(dim*dim+dim)+d)*n_q_points];
6454  }
6455 
6456  switch (this->data->element_type)
6457  {
6458  case internal::MatrixFreeFunctions::tensor_symmetric:
6459  evaluate_funct =
6460  internal::FEEvaluationImpl<internal::MatrixFreeFunctions::tensor_symmetric,
6461  dim, fe_degree, n_q_points_1d, n_components_,
6462  Number>::evaluate;
6463  integrate_funct =
6464  internal::FEEvaluationImpl<internal::MatrixFreeFunctions::tensor_symmetric,
6465  dim, fe_degree, n_q_points_1d, n_components_,
6466  Number>::integrate;
6467  break;
6468 
6469  case internal::MatrixFreeFunctions::tensor_symmetric_plus_dg0:
6470  evaluate_funct =
6471  internal::FEEvaluationImpl<internal::MatrixFreeFunctions::tensor_symmetric_plus_dg0,
6472  dim, fe_degree, n_q_points_1d, n_components_,
6473  Number>::evaluate;
6474  integrate_funct =
6475  internal::FEEvaluationImpl<internal::MatrixFreeFunctions::tensor_symmetric_plus_dg0,
6476  dim, fe_degree, n_q_points_1d, n_components_,
6477  Number>::integrate;
6478  break;
6479 
6480  case internal::MatrixFreeFunctions::tensor_general:
6481  evaluate_funct =
6482  internal::FEEvaluationImpl<internal::MatrixFreeFunctions::tensor_general,
6483  dim, fe_degree, n_q_points_1d, n_components_,
6484  Number>::evaluate;
6485  integrate_funct =
6486  internal::FEEvaluationImpl<internal::MatrixFreeFunctions::tensor_general,
6487  dim, fe_degree, n_q_points_1d, n_components_,
6488  Number>::integrate;
6489  break;
6490 
6491  case internal::MatrixFreeFunctions::tensor_gausslobatto:
6492  evaluate_funct =
6493  internal::FEEvaluationImpl<internal::MatrixFreeFunctions::tensor_gausslobatto,
6494  dim, fe_degree, n_q_points_1d, n_components_,
6495  Number>::evaluate;
6496  integrate_funct =
6497  internal::FEEvaluationImpl<internal::MatrixFreeFunctions::tensor_gausslobatto,
6498  dim, fe_degree, n_q_points_1d, n_components_,
6499  Number>::integrate;
6500  break;
6501 
6502  case internal::MatrixFreeFunctions::truncated_tensor:
6503  evaluate_funct =
6504  internal::FEEvaluationImpl<internal::MatrixFreeFunctions::truncated_tensor,
6505  dim, fe_degree, n_q_points_1d, n_components_,
6506  Number>::evaluate;
6507  integrate_funct =
6508  internal::FEEvaluationImpl<internal::MatrixFreeFunctions::truncated_tensor,
6509  dim, fe_degree, n_q_points_1d, n_components_,
6510  Number>::integrate;
6511  break;
6512 
6513  default:
6514  AssertThrow(false, ExcNotImplemented());
6515  }
6516 
6517 }
6518 
6519 
6520 
6521 template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
6522  typename Number>
6523 inline
6524 void
6526 ::check_template_arguments(const unsigned int fe_no)
6527 {
6528 #ifdef DEBUG
6529  // print error message when the dimensions do not match. Propose a possible
6530  // fix
6531  if (fe_degree != this->data->fe_degree
6532  ||
6533  n_q_points != this->data->n_q_points)
6534  {
6535  std::string message =
6536  "-------------------------------------------------------\n";
6537  message += "Illegal arguments in constructor/wrong template arguments!\n";
6538  message += " Called --> FEEvaluation<dim,";
6539  message += Utilities::int_to_string(fe_degree) + ",";
6540  message += Utilities::int_to_string(n_q_points_1d);
6541  message += "," + Utilities::int_to_string(n_components);
6542  message += ",Number>(data";
6543  if (fe_no != numbers::invalid_unsigned_int)
6544  {
6545  message += ", " + Utilities::int_to_string(fe_no) + ", ";
6546  message += Utilities::int_to_string(this->quad_no);
6547  }
6548  message += ")\n";
6549 
6550  // check whether some other vector component has the correct number of
6551  // points
6552  unsigned int proposed_dof_comp = numbers::invalid_unsigned_int,
6553  proposed_quad_comp = numbers::invalid_unsigned_int;
6554  if (fe_no != numbers::invalid_unsigned_int)
6555  {
6556  if (fe_degree == this->data->fe_degree)
6557  proposed_dof_comp = fe_no;
6558  else
6559  for (unsigned int no=0; no<this->matrix_info->n_components(); ++no)
6560  if (this->matrix_info->get_shape_info(no,0,this->active_fe_index,0).fe_degree
6561  == fe_degree)
6562  {
6563  proposed_dof_comp = no;
6564  break;
6565  }
6566  if (n_q_points ==
6567  this->mapping_info->mapping_data_gen[this->quad_no].n_q_points[this->active_quad_index])
6568  proposed_quad_comp = this->quad_no;
6569  else
6570  for (unsigned int no=0; no<this->mapping_info->mapping_data_gen.size(); ++no)
6571  if (this->mapping_info->mapping_data_gen[no].n_q_points[this->active_quad_index]
6572  == n_q_points)
6573  {
6574  proposed_quad_comp = no;
6575  break;
6576  }
6577  }
6578  if (proposed_dof_comp != numbers::invalid_unsigned_int &&
6579  proposed_quad_comp != numbers::invalid_unsigned_int)
6580  {
6581  if (proposed_dof_comp != fe_no)
6582  message += "Wrong vector component selection:\n";
6583  else
6584  message += "Wrong quadrature formula selection:\n";
6585  message += " Did you mean FEEvaluation<dim,";
6586  message += Utilities::int_to_string(fe_degree) + ",";
6587  message += Utilities::int_to_string(n_q_points_1d);
6588  message += "," + Utilities::int_to_string(n_components);
6589  message += ",Number>(data";
6590  if (fe_no != numbers::invalid_unsigned_int)
6591  {
6592  message += ", " + Utilities::int_to_string(proposed_dof_comp) + ", ";
6593  message += Utilities::int_to_string(proposed_quad_comp);
6594  }
6595  message += ")?\n";
6596  std::string correct_pos;
6597  if (proposed_dof_comp != fe_no)
6598  correct_pos = " ^ ";
6599  else
6600  correct_pos = " ";
6601  if (proposed_quad_comp != this->quad_no)
6602  correct_pos += " ^\n";
6603  else
6604  correct_pos += " \n";
6605  message += " " + correct_pos;
6606  }
6607  // ok, did not find the numbers specified by the template arguments in
6608  // the given list. Suggest correct template arguments
6609  const unsigned int proposed_n_q_points_1d = static_cast<unsigned int>(std::pow(1.001*this->data->n_q_points,1./dim));
6610  message += "Wrong template arguments:\n";
6611  message += " Did you mean FEEvaluation<dim,";
6612  message += Utilities::int_to_string(this->data->fe_degree) + ",";
6613  message += Utilities::int_to_string(proposed_n_q_points_1d);
6614  message += "," + Utilities::int_to_string(n_components);
6615  message += ",Number>(data";
6616  if (fe_no != numbers::invalid_unsigned_int)
6617  {
6618  message += ", " + Utilities::int_to_string(fe_no) + ", ";
6619  message += Utilities::int_to_string(this->quad_no);
6620  }
6621  message += ")?\n";
6622  std::string correct_pos;
6623  if (this->data->fe_degree != fe_degree)
6624  correct_pos = " ^";
6625  else
6626  correct_pos = " ";
6627  if (proposed_n_q_points_1d != n_q_points_1d)
6628  correct_pos += " ^\n";
6629  else
6630  correct_pos += " \n";
6631  message += " " + correct_pos;
6632 
6633  Assert (fe_degree == this->data->fe_degree &&
6634  n_q_points == this->data->n_q_points,
6635  ExcMessage(message));
6636  }
6637  if (fe_no != numbers::invalid_unsigned_int)
6638  {
6639  AssertDimension (n_q_points,
6640  this->mapping_info->mapping_data_gen[this->quad_no].
6641  n_q_points[this->active_quad_index]);
6642  AssertDimension (this->data->dofs_per_cell * this->n_fe_components,
6643  this->dof_info->dofs_per_cell[this->active_fe_index]);
6644  }
6645 #endif
6646 }
6647 
6648 
6649 
6650 template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
6651  typename Number>
6652 inline
6655 ::quadrature_point (const unsigned int q) const
6656 {
6657  Assert (this->mapping_info->quadrature_points_initialized == true,
6658  ExcNotInitialized());
6659  AssertIndexRange (q, n_q_points);
6660 
6661  // Cartesian mesh: not all quadrature points are stored, only the
6662  // diagonal. Hence, need to find the tensor product index and retrieve the
6663  // value from that
6664  if (this->cell_type == internal::MatrixFreeFunctions::cartesian)
6665  {
6667  switch (dim)
6668  {
6669  case 1:
6670  return this->quadrature_points[q];
6671  case 2:
6672  point[0] = this->quadrature_points[q%n_q_points_1d][0];
6673  point[1] = this->quadrature_points[q/n_q_points_1d][1];
6674  return point;
6675  case 3:
6676  point[0] = this->quadrature_points[q%n_q_points_1d][0];
6677  point[1] = this->quadrature_points[(q/n_q_points_1d)%n_q_points_1d][1];
6678  point[2] = this->quadrature_points[q/(n_q_points_1d*n_q_points_1d)][2];
6679  return point;
6680  default:
6681  Assert (false, ExcNotImplemented());
6682  return point;
6683  }
6684  }
6685  // all other cases: just return the respective data as it is fully stored
6686  else
6687  return this->quadrature_points[q];
6688 }
6689 
6690 
6691 
6692 template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
6693  typename Number>
6694 inline
6695 void
6697 ::evaluate (const bool evaluate_val,
6698  const bool evaluate_grad,
6699  const bool evaluate_lapl)
6700 {
6701  Assert (this->dof_values_initialized == true,
6702  internal::ExcAccessToUninitializedField());
6703  Assert(this->matrix_info != 0 ||
6704  this->mapped_geometry->is_initialized(), ExcNotInitialized());
6705 
6706  // Select algorithm matching the element type at run time (the function
6707  // pointer is easy to predict, so negligible in cost)
6708  evaluate_funct (*this->data, &this->values_dofs[0],
6709  this->values_quad, this->gradients_quad, this->hessians_quad,
6710  evaluate_val, evaluate_grad, evaluate_lapl);
6711 
6712 #ifdef DEBUG
6713  if (evaluate_val == true)
6714  this->values_quad_initialized = true;
6715  if (evaluate_grad == true)
6716  this->gradients_quad_initialized = true;
6717  if (evaluate_lapl == true)
6718  this->hessians_quad_initialized = true;
6719 #endif
6720 }
6721 
6722 
6723 
6724 template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
6725  typename Number>
6726 inline
6727 void
6729 ::integrate (bool integrate_val,bool integrate_grad)
6730 {
6731  if (integrate_val == true)
6732  Assert (this->values_quad_submitted == true,
6733  internal::ExcAccessToUninitializedField());
6734  if (integrate_grad == true)
6735  Assert (this->gradients_quad_submitted == true,
6736  internal::ExcAccessToUninitializedField());
6737  Assert(this->matrix_info != 0 ||
6738  this->mapped_geometry->is_initialized(), ExcNotInitialized());
6739 
6740  // Select algorithm matching the element type at run time (the function
6741  // pointer is easy to predict, so negligible in cost)
6742  integrate_funct (*this->data, this->values_dofs, this->values_quad,
6743  this->gradients_quad, integrate_val, integrate_grad);
6744 
6745 #ifdef DEBUG
6746  this->dof_values_initialized = true;
6747 #endif
6748 }
6749 
6750 
6751 
6752 #endif // ifndef DOXYGEN
6753 
6754 
6755 DEAL_II_NAMESPACE_CLOSE
6756 
6757 #endif
const internal::MatrixFreeFunctions::ShapeInfo< Number > & get_shape_info(const unsigned int fe_component=0, const unsigned int quad_index=0, const unsigned int hp_active_fe_index=0, const unsigned int hp_active_quad_index=0) const
void distribute_local_to_global(VectorType &dst) const
static const unsigned int invalid_unsigned_int
Definition: types.h:164
const Number * constraint_pool_begin(const unsigned int pool_index) const
#define AssertDimension(dim1, dim2)
Definition: exceptions.h:1052
AlignedVector< std::pair< Tensor< 1, dim, VectorizedArray< Number > >, VectorizedArray< Number > > > cartesian_data
Definition: mapping_info.h:146
unsigned int get_cell_data_number() const
const internal::MatrixFreeFunctions::DoFInfo & get_dof_info(const unsigned int fe_component=0) const
void integrate(const bool integrate_val, const bool integrate_grad)
Tensor< 1, n_components_, Tensor< 2, dim, VectorizedArray< Number > > > get_hessian(const unsigned int q_point) const
void set_dof_values(VectorType &dst) const
const MatrixFree< dim, Number > * matrix_info
void reinit(const unsigned int cell)
const Tensor< 1,(dim >1?dim *(dim-1)/2:1), Tensor< 1, dim, VectorizedArray< Number > > > * jacobian_grad_upper
AlignedVector< std::pair< Tensor< 2, dim, VectorizedArray< Number > >, VectorizedArray< Number > > > affine_data
Definition: mapping_info.h:161
unsigned int cell_data_number
void read_write_operation(const VectorOperation &operation, VectorType *vectors[]) const
const unsigned int first_selected_component
value_type get_laplacian(const unsigned int q_point) const
const unsigned int dofs_per_cell
unsigned int n_components() const
const unsigned int n_fe_components
bool gradients_quad_initialized
::ExceptionBase & ExcMessage(std::string arg1)
#define AssertIndexRange(index, range)
Definition: exceptions.h:1081
const VectorizedArray< Number > * begin_gradients() const
std::vector< types::global_dof_index > old_style_dof_indices
unsigned int get_cell_data_index(const unsigned int cell_chunk_no) const
Definition: mapping_info.h:369
const VectorizedArray< Number > * begin_hessians() const
const Tensor< 2, dim, VectorizedArray< Number > > * jacobian
friend class FEEvaluationBase
std::vector< MappingInfoDependent > mapping_data_gen
Definition: mapping_info.h:290
#define AssertThrow(cond, exc)
Definition: exceptions.h:358
FEEvaluationAccess(const MatrixFree< dim, Number > &matrix_free, const unsigned int fe_no, const unsigned int quad_no, const unsigned int fe_degree, const unsigned int n_q_points)
const internal::MatrixFreeFunctions::DoFInfo * dof_info
void submit_gradient(const gradient_type grad_in, const unsigned int q_point)
const VectorizedArray< Number > * begin_dof_values() const
void evaluate(const bool evaluate_val, const bool evaluate_grad, const bool evaluate_hess=false)
Definition: point.h:89
void read_dof_values(const VectorType &src)
const Tensor< 1, dim, VectorizedArray< Number > > * cartesian_data
void submit_dof_value(const value_type val_in, const unsigned int dof)
const internal::MatrixFreeFunctions::ShapeInfo< Number > * data
Number local_element(const size_type local_index) const
void fill_JxW_values(AlignedVector< VectorizedArray< Number > > &JxW_values) const
value_type get_dof_value(const unsigned int dof) const
const unsigned int active_fe_index
std::pair< unsigned int, unsigned int > component_to_base_index(const unsigned int component) const
Definition: fe.h:2862
unsigned int global_dof_index
Definition: types.h:88
const Tensor< 2, dim, VectorizedArray< Number > > * jacobian_grad
#define Assert(cond, exc)
Definition: exceptions.h:294
unsigned int element_multiplicity(const unsigned int index) const
Definition: fe.h:2766
UpdateFlags
FEEvaluation(const MatrixFree< dim, Number > &matrix_free, const unsigned int fe_no=0, const unsigned int quad_no=0)
const unsigned int active_quad_index
#define DeclException0(Exception0)
Definition: exceptions.h:522
const Number * constraint_pool_end(const unsigned int pool_index) const
const internal::MatrixFreeFunctions::MappingInfo< dim, Number > * mapping_info
std::vector< types::global_dof_index > local_dof_indices
const unsigned int quad_no
const Point< dim, VectorizedArray< Number > > * quadrature_points
bool mapping_initialized() const
std::string int_to_string(const unsigned int value, const unsigned int digits=numbers::invalid_unsigned_int)
Definition: utilities.cc:82
const VectorizedArray< Number > * quadrature_weights
gradient_type get_hessian_diagonal(const unsigned int q_point) const
bool hessians_quad_initialized
const internal::MatrixFreeFunctions::SizeInfo & get_size_info() const
unsigned int cell
value_type integrate_value() const
void submit_value(const value_type val_in, const unsigned int q_point)
internal::MatrixFreeFunctions::CellType cell_type
std_cxx11::shared_ptr< internal::MatrixFreeFunctions::ShapeInfo< Number > > stored_shape_info
void read_dof_values_plain(const VectorType &src)
gradient_type get_gradient(const unsigned int q_point) const
Definition: mpi.h:48
const VectorizedArray< Number > * begin_values() const
bool partitioners_are_compatible(const Utilities::MPI::Partitioner &part) const
iterator begin()
const internal::MatrixFreeFunctions::ShapeInfo< Number > & get_shape_info() const
bool indices_initialized() const
void check_template_arguments(const unsigned int fe_no)
std::vector< unsigned int > lexicographic_numbering
Definition: shape_info.h:190
bool values_quad_initialized
const std::vector< unsigned int > & get_internal_dof_numbering() const
value_type get_value(const unsigned int q_point) const
const VectorizedArray< Number > * J_value
CellType get_cell_type(const unsigned int cell_chunk_no) const
Definition: mapping_info.h:356
internal::MatrixFreeFunctions::CellType get_cell_type() const
void set_data_pointers()
Point< dim, VectorizedArray< Number > > quadrature_point(const unsigned int q_point) const
bool gradients_quad_submitted
std_cxx1x::shared_ptr< internal::MatrixFreeFunctions::MappingDataOnTheFly< dim, Number > > mapped_geometry