Reference documentation for deal.II version 9.1.0-pre
matrix_free.h
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2011 - 2018 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE.md at
12 // the top level directory of deal.II.
13 //
14 // ---------------------------------------------------------------------
15 
16 
17 #ifndef dealii_matrix_free_h
18 #define dealii_matrix_free_h
19 
20 #include <deal.II/base/aligned_vector.h>
21 #include <deal.II/base/exceptions.h>
22 #include <deal.II/base/quadrature.h>
23 #include <deal.II/base/template_constraints.h>
24 #include <deal.II/base/thread_local_storage.h>
25 #include <deal.II/base/vectorization.h>
26 
27 #include <deal.II/dofs/dof_handler.h>
28 
29 #include <deal.II/fe/fe.h>
30 #include <deal.II/fe/mapping.h>
31 #include <deal.II/fe/mapping_q1.h>
32 
33 #include <deal.II/grid/grid_tools.h>
34 
35 #include <deal.II/hp/dof_handler.h>
36 #include <deal.II/hp/q_collection.h>
37 
38 #include <deal.II/lac/affine_constraints.h>
39 #include <deal.II/lac/block_vector_base.h>
40 #include <deal.II/lac/la_parallel_vector.h>
41 #include <deal.II/lac/vector_operation.h>
42 
43 #include <deal.II/matrix_free/dof_info.h>
44 #include <deal.II/matrix_free/mapping_info.h>
45 #include <deal.II/matrix_free/shape_info.h>
46 #include <deal.II/matrix_free/task_info.h>
47 
48 #include <cstdlib>
49 #include <limits>
50 #include <list>
51 #include <memory>
52 
53 
54 DEAL_II_NAMESPACE_OPEN
55 
56 
57 
111 template <int dim, typename Number = double>
112 class MatrixFree : public Subscriptor
113 {
114 public:
119  using value_type = Number;
120 
124  static const unsigned int dimension = dim;
125 
173  {
180  {
184  none = internal::MatrixFreeFunctions::TaskInfo::none,
189  internal::MatrixFreeFunctions::TaskInfo::partition_partition,
194  internal::MatrixFreeFunctions::TaskInfo::partition_color,
199  color = internal::MatrixFreeFunctions::TaskInfo::color
200  };
201 
207  const unsigned int tasks_block_size = 0,
213  const unsigned int level_mg_handler = numbers::invalid_unsigned_int,
214  const bool store_plain_indices = true,
215  const bool initialize_indices = true,
216  const bool initialize_mapping = true,
217  const bool overlap_communication_computation = true,
218  const bool hold_all_faces_to_owned_cells = false,
219  const bool cell_vectorization_categories_strict = false)
234  {}
235 
273 
283  unsigned int tasks_block_size;
284 
297 
318 
339 
367 
376  unsigned int level_mg_handler;
377 
385 
396 
405 
419 
428 
445  std::vector<unsigned int> cell_vectorization_category;
446 
457  };
458 
466  MatrixFree();
467 
471  MatrixFree(const MatrixFree<dim, Number> &other);
472 
476  ~MatrixFree() override = default;
477 
490  template <typename DoFHandlerType, typename QuadratureType, typename number2>
491  void
492  reinit(const Mapping<dim> & mapping,
493  const DoFHandlerType & dof_handler,
494  const AffineConstraints<number2> &constraint,
495  const QuadratureType & quad,
496  const AdditionalData additional_data = AdditionalData());
497 
502  template <typename DoFHandlerType, typename QuadratureType, typename number2>
503  void
504  reinit(const DoFHandlerType & dof_handler,
505  const AffineConstraints<number2> &constraint,
506  const QuadratureType & quad,
507  const AdditionalData additional_data = AdditionalData());
508 
516  template <typename DoFHandlerType, typename QuadratureType, typename number2>
517  DEAL_II_DEPRECATED void
518  reinit(const Mapping<dim> & mapping,
519  const DoFHandlerType & dof_handler,
520  const AffineConstraints<number2> &constraint,
521  const IndexSet & locally_owned_dofs,
522  const QuadratureType & quad,
523  const AdditionalData additional_data = AdditionalData());
524 
545  template <typename DoFHandlerType, typename QuadratureType, typename number2>
546  void
547  reinit(const Mapping<dim> & mapping,
548  const std::vector<const DoFHandlerType *> & dof_handler,
549  const std::vector<const AffineConstraints<number2> *> &constraint,
550  const std::vector<QuadratureType> & quad,
551  const AdditionalData additional_data = AdditionalData());
552 
557  template <typename DoFHandlerType, typename QuadratureType, typename number2>
558  void
559  reinit(const std::vector<const DoFHandlerType *> & dof_handler,
560  const std::vector<const AffineConstraints<number2> *> &constraint,
561  const std::vector<QuadratureType> & quad,
562  const AdditionalData additional_data = AdditionalData());
563 
571  template <typename DoFHandlerType, typename QuadratureType, typename number2>
572  DEAL_II_DEPRECATED void
573  reinit(const Mapping<dim> & mapping,
574  const std::vector<const DoFHandlerType *> & dof_handler,
575  const std::vector<const AffineConstraints<number2> *> &constraint,
576  const std::vector<IndexSet> & locally_owned_set,
577  const std::vector<QuadratureType> &quad,
578  const AdditionalData additional_data = AdditionalData());
579 
587  template <typename DoFHandlerType, typename QuadratureType, typename number2>
588  void
589  reinit(const Mapping<dim> & mapping,
590  const std::vector<const DoFHandlerType *> & dof_handler,
591  const std::vector<const AffineConstraints<number2> *> &constraint,
592  const QuadratureType & quad,
593  const AdditionalData additional_data = AdditionalData());
594 
599  template <typename DoFHandlerType, typename QuadratureType, typename number2>
600  void
601  reinit(const std::vector<const DoFHandlerType *> & dof_handler,
602  const std::vector<const AffineConstraints<number2> *> &constraint,
603  const QuadratureType & quad,
604  const AdditionalData additional_data = AdditionalData());
605 
611  void
612  copy_from(const MatrixFree<dim, Number> &matrix_free_base);
613 
618  void
619  clear();
620 
622 
634  enum class DataAccessOnFaces
635  {
642  none,
643 
653  values,
654 
665  gradients,
666 
673  unspecified
674  };
675 
716  template <typename OutVector, typename InVector>
717  void
718  cell_loop(
719  const std::function<void(const MatrixFree<dim, Number> &,
720  OutVector &,
721  const InVector &,
722  const std::pair<unsigned int, unsigned int> &)>
723  & cell_operation,
724  OutVector & dst,
725  const InVector &src,
726  const bool zero_dst_vector = false) const;
727 
769  template <typename CLASS, typename OutVector, typename InVector>
770  void
771  cell_loop(void (CLASS::*cell_operation)(
772  const MatrixFree &,
773  OutVector &,
774  const InVector &,
775  const std::pair<unsigned int, unsigned int> &) const,
776  const CLASS * owning_class,
777  OutVector & dst,
778  const InVector &src,
779  const bool zero_dst_vector = false) const;
780 
784  template <typename CLASS, typename OutVector, typename InVector>
785  void
786  cell_loop(void (CLASS::*cell_operation)(
787  const MatrixFree &,
788  OutVector &,
789  const InVector &,
790  const std::pair<unsigned int, unsigned int> &),
791  CLASS * owning_class,
792  OutVector & dst,
793  const InVector &src,
794  const bool zero_dst_vector = false) const;
795 
871  template <typename OutVector, typename InVector>
872  void
873  loop(const std::function<void(const MatrixFree<dim, Number> &,
874  OutVector &,
875  const InVector &,
876  const std::pair<unsigned int, unsigned int> &)>
877  &cell_operation,
878  const std::function<void(const MatrixFree<dim, Number> &,
879  OutVector &,
880  const InVector &,
881  const std::pair<unsigned int, unsigned int> &)>
882  &face_operation,
883  const std::function<void(const MatrixFree<dim, Number> &,
884  OutVector &,
885  const InVector &,
886  const std::pair<unsigned int, unsigned int> &)>
887  & boundary_operation,
888  OutVector & dst,
889  const InVector & src,
890  const bool zero_dst_vector = false,
891  const DataAccessOnFaces dst_vector_face_access =
893  const DataAccessOnFaces src_vector_face_access =
895 
980  template <typename CLASS, typename OutVector, typename InVector>
981  void
982  loop(
983  void (CLASS::*cell_operation)(const MatrixFree &,
984  OutVector &,
985  const InVector &,
986  const std::pair<unsigned int, unsigned int> &)
987  const,
988  void (CLASS::*face_operation)(const MatrixFree &,
989  OutVector &,
990  const InVector &,
991  const std::pair<unsigned int, unsigned int> &)
992  const,
993  void (CLASS::*boundary_operation)(
994  const MatrixFree &,
995  OutVector &,
996  const InVector &,
997  const std::pair<unsigned int, unsigned int> &) const,
998  const CLASS * owning_class,
999  OutVector & dst,
1000  const InVector & src,
1001  const bool zero_dst_vector = false,
1002  const DataAccessOnFaces dst_vector_face_access =
1004  const DataAccessOnFaces src_vector_face_access =
1006 
1010  template <typename CLASS, typename OutVector, typename InVector>
1011  void
1012  loop(void (CLASS::*cell_operation)(
1013  const MatrixFree &,
1014  OutVector &,
1015  const InVector &,
1016  const std::pair<unsigned int, unsigned int> &),
1017  void (CLASS::*face_operation)(
1018  const MatrixFree &,
1019  OutVector &,
1020  const InVector &,
1021  const std::pair<unsigned int, unsigned int> &),
1022  void (CLASS::*boundary_operation)(
1023  const MatrixFree &,
1024  OutVector &,
1025  const InVector &,
1026  const std::pair<unsigned int, unsigned int> &),
1027  CLASS * owning_class,
1028  OutVector & dst,
1029  const InVector & src,
1030  const bool zero_dst_vector = false,
1031  const DataAccessOnFaces dst_vector_face_access =
1033  const DataAccessOnFaces src_vector_face_access =
1035 
1043  std::pair<unsigned int, unsigned int>
1044  create_cell_subrange_hp(const std::pair<unsigned int, unsigned int> &range,
1045  const unsigned int fe_degree,
1046  const unsigned int dof_handler_index = 0) const;
1047 
1054  std::pair<unsigned int, unsigned int>
1056  const std::pair<unsigned int, unsigned int> &range,
1057  const unsigned int fe_index,
1058  const unsigned int dof_handler_index = 0) const;
1059 
1061 
1086  template <typename VectorType>
1087  void
1088  initialize_dof_vector(VectorType & vec,
1089  const unsigned int dof_handler_index = 0) const;
1090 
1111  template <typename Number2>
1112  void
1114  const unsigned int dof_handler_index = 0) const;
1115 
1126  const std::shared_ptr<const Utilities::MPI::Partitioner> &
1127  get_vector_partitioner(const unsigned int dof_handler_index = 0) const;
1128 
1132  const IndexSet &
1133  get_locally_owned_set(const unsigned int dof_handler_index = 0) const;
1134 
1138  const IndexSet &
1139  get_ghost_set(const unsigned int dof_handler_index = 0) const;
1140 
1150  const std::vector<unsigned int> &
1151  get_constrained_dofs(const unsigned int dof_handler_index = 0) const;
1152 
1163  void
1164  renumber_dofs(std::vector<types::global_dof_index> &renumbering,
1165  const unsigned int dof_handler_index = 0);
1166 
1168 
1176  template <int spacedim>
1177  static bool
1179 
1183  unsigned int
1184  n_components() const;
1185 
1190  unsigned int
1191  n_base_elements(const unsigned int dof_handler_index) const;
1192 
1200  unsigned int
1201  n_physical_cells() const;
1202 
1212  unsigned int
1213  n_macro_cells() const;
1214 
1224  unsigned int
1225  n_cell_batches() const;
1226 
1233  unsigned int
1234  n_ghost_cell_batches() const;
1235 
1243  unsigned int
1244  n_inner_face_batches() const;
1245 
1254  unsigned int
1255  n_boundary_face_batches() const;
1256 
1261  unsigned int
1263 
1271  get_boundary_id(const unsigned int macro_face) const;
1272 
1277  std::array<types::boundary_id, VectorizedArray<Number>::n_array_elements>
1278  get_faces_by_cells_boundary_id(const unsigned int macro_cell,
1279  const unsigned int face_number) const;
1280 
1285  const DoFHandler<dim> &
1286  get_dof_handler(const unsigned int dof_handler_index = 0) const;
1287 
1299  get_cell_iterator(const unsigned int macro_cell_number,
1300  const unsigned int vector_number,
1301  const unsigned int fe_component = 0) const;
1302 
1315  get_hp_cell_iterator(const unsigned int macro_cell_number,
1316  const unsigned int vector_number,
1317  const unsigned int dof_handler_index = 0) const;
1318 
1330  bool
1331  at_irregular_cell(const unsigned int macro_cell_number) const;
1332 
1341  unsigned int
1342  n_components_filled(const unsigned int cell_batch_number) const;
1343 
1352  unsigned int
1353  n_active_entries_per_cell_batch(const unsigned int cell_batch_number) const;
1354 
1364  unsigned int
1365  n_active_entries_per_face_batch(const unsigned int face_batch_number) const;
1366 
1370  unsigned int
1371  get_dofs_per_cell(const unsigned int dof_handler_index = 0,
1372  const unsigned int hp_active_fe_index = 0) const;
1373 
1377  unsigned int
1378  get_n_q_points(const unsigned int quad_index = 0,
1379  const unsigned int hp_active_fe_index = 0) const;
1380 
1385  unsigned int
1386  get_dofs_per_face(const unsigned int fe_component = 0,
1387  const unsigned int hp_active_fe_index = 0) const;
1388 
1393  unsigned int
1394  get_n_q_points_face(const unsigned int quad_index = 0,
1395  const unsigned int hp_active_fe_index = 0) const;
1396 
1400  const Quadrature<dim> &
1401  get_quadrature(const unsigned int quad_index = 0,
1402  const unsigned int hp_active_fe_index = 0) const;
1403 
1407  const Quadrature<dim - 1> &
1408  get_face_quadrature(const unsigned int quad_index = 0,
1409  const unsigned int hp_active_fe_index = 0) const;
1410 
1417  unsigned int
1418  get_cell_category(const unsigned int macro_cell) const;
1419 
1424  std::pair<unsigned int, unsigned int>
1425  get_face_category(const unsigned int macro_face) const;
1426 
1430  bool
1431  indices_initialized() const;
1432 
1438  bool
1439  mapping_initialized() const;
1440 
1445  std::size_t
1446  memory_consumption() const;
1447 
1452  template <typename StreamType>
1453  void
1454  print_memory_consumption(StreamType &out) const;
1455 
1460  void
1461  print(std::ostream &out) const;
1462 
1464 
1474  get_task_info() const;
1475 
1479  DEAL_II_DEPRECATED
1481  get_size_info() const;
1482 
1483  /*
1484  * Return geometry-dependent information on the cells.
1485  */
1487  get_mapping_info() const;
1488 
1493  get_dof_info(const unsigned int dof_handler_index_component = 0) const;
1494 
1498  unsigned int
1499  n_constraint_pool_entries() const;
1500 
1505  const Number *
1506  constraint_pool_begin(const unsigned int pool_index) const;
1507 
1513  const Number *
1514  constraint_pool_end(const unsigned int pool_index) const;
1515 
1520  get_shape_info(const unsigned int dof_handler_index_component = 0,
1521  const unsigned int quad_index = 0,
1522  const unsigned int fe_base_element = 0,
1523  const unsigned int hp_active_fe_index = 0,
1524  const unsigned int hp_active_quad_index = 0) const;
1525 
1531  get_face_info(const unsigned int face_batch_number) const;
1532 
1547  acquire_scratch_data() const;
1548 
1552  void
1554  const AlignedVector<VectorizedArray<Number>> *memory) const;
1555 
1567 
1571  void
1573  const AlignedVector<Number> *memory) const;
1574 
1576 
1577 private:
1582  template <typename number2>
1583  void
1585  const Mapping<dim> & mapping,
1586  const std::vector<const DoFHandler<dim> *> & dof_handler,
1587  const std::vector<const AffineConstraints<number2> *> &constraint,
1588  const std::vector<IndexSet> & locally_owned_set,
1589  const std::vector<hp::QCollection<1>> & quad,
1590  const AdditionalData & additional_data);
1591 
1595  template <typename number2>
1596  void
1598  const Mapping<dim> & mapping,
1599  const std::vector<const hp::DoFHandler<dim> *> & dof_handler,
1600  const std::vector<const AffineConstraints<number2> *> &constraint,
1601  const std::vector<IndexSet> & locally_owned_set,
1602  const std::vector<hp::QCollection<1>> & quad,
1603  const AdditionalData & additional_data);
1604 
1611  template <typename number2>
1612  void
1614  const std::vector<const AffineConstraints<number2> *> &constraint,
1615  const std::vector<IndexSet> & locally_owned_set,
1616  const AdditionalData & additional_data);
1617 
1621  void
1623  const std::vector<const DoFHandler<dim> *> &dof_handlers,
1624  const AdditionalData & additional_data);
1625 
1629  void
1631  const std::vector<const hp::DoFHandler<dim> *> &dof_handlers,
1632  const AdditionalData & additional_data);
1633 
1638  void
1640 
1647  {
1648  DoFHandlers()
1649  : active_dof_handler(usual)
1650  , n_dof_handlers(0)
1652  {}
1653 
1654  std::vector<SmartPointer<const DoFHandler<dim>>> dof_handler;
1655  std::vector<SmartPointer<const hp::DoFHandler<dim>>> hp_dof_handler;
1657  {
1666  } active_dof_handler;
1667  unsigned int n_dof_handlers;
1668  unsigned int level;
1669  };
1670 
1675 
1680  std::vector<internal::MatrixFreeFunctions::DoFInfo> dof_info;
1681 
1688  std::vector<Number> constraint_pool_data;
1689 
1694  std::vector<unsigned int> constraint_pool_row_index;
1695 
1701 
1707 
1714  std::vector<std::pair<unsigned int, unsigned int>> cell_level_index;
1715 
1716 
1724 
1731 
1739 
1744 
1749 
1758  std::list<std::pair<bool, AlignedVector<VectorizedArray<Number>>>>>
1760 
1765  mutable std::list<std::pair<bool, AlignedVector<Number>>>
1767 };
1768 
1769 
1770 
1771 /*----------------------- Inline functions ----------------------------------*/
1772 
1773 #ifndef DOXYGEN
1774 
1775 
1776 
1777 template <int dim, typename Number>
1778 template <typename VectorType>
1779 inline void
1781  const unsigned int comp) const
1782 {
1783  AssertIndexRange(comp, n_components());
1784  vec.reinit(dof_info[comp].vector_partitioner->size());
1785 }
1786 
1787 
1788 
1789 template <int dim, typename Number>
1790 template <typename Number2>
1791 inline void
1794  const unsigned int comp) const
1795 {
1796  AssertIndexRange(comp, n_components());
1797  vec.reinit(dof_info[comp].vector_partitioner);
1798 }
1799 
1800 
1801 
1802 template <int dim, typename Number>
1803 inline const std::shared_ptr<const Utilities::MPI::Partitioner> &
1804 MatrixFree<dim, Number>::get_vector_partitioner(const unsigned int comp) const
1805 {
1806  AssertIndexRange(comp, n_components());
1807  return dof_info[comp].vector_partitioner;
1808 }
1809 
1810 
1811 
1812 template <int dim, typename Number>
1813 inline const std::vector<unsigned int> &
1814 MatrixFree<dim, Number>::get_constrained_dofs(const unsigned int comp) const
1815 {
1816  AssertIndexRange(comp, n_components());
1817  return dof_info[comp].constrained_dofs;
1818 }
1819 
1820 
1821 
1822 template <int dim, typename Number>
1823 inline unsigned int
1825 {
1826  AssertDimension(dof_handlers.n_dof_handlers, dof_info.size());
1827  return dof_handlers.n_dof_handlers;
1828 }
1829 
1830 
1831 
1832 template <int dim, typename Number>
1833 inline unsigned int
1834 MatrixFree<dim, Number>::n_base_elements(const unsigned int dof_no) const
1835 {
1836  AssertDimension(dof_handlers.n_dof_handlers, dof_info.size());
1837  AssertIndexRange(dof_no, dof_handlers.n_dof_handlers);
1838  return dof_handlers.dof_handler[dof_no]->get_fe().n_base_elements();
1839 }
1840 
1841 
1842 
1843 template <int dim, typename Number>
1846 {
1847  return task_info;
1848 }
1849 
1850 
1851 
1852 template <int dim, typename Number>
1855 {
1856  return task_info;
1857 }
1858 
1859 
1860 
1861 template <int dim, typename Number>
1862 inline unsigned int
1864 {
1865  return *(task_info.cell_partition_data.end() - 2);
1866 }
1867 
1868 
1869 
1870 template <int dim, typename Number>
1871 inline unsigned int
1873 {
1874  return task_info.n_active_cells;
1875 }
1876 
1877 
1878 
1879 template <int dim, typename Number>
1880 inline unsigned int
1882 {
1883  return *(task_info.cell_partition_data.end() - 2);
1884 }
1885 
1886 
1887 
1888 template <int dim, typename Number>
1889 inline unsigned int
1891 {
1892  return *(task_info.cell_partition_data.end() - 1) -
1893  *(task_info.cell_partition_data.end() - 2);
1894 }
1895 
1896 
1897 
1898 template <int dim, typename Number>
1899 inline unsigned int
1901 {
1902  if (task_info.face_partition_data.size() == 0)
1903  return 0;
1904  return task_info.face_partition_data.back();
1905 }
1906 
1907 
1908 
1909 template <int dim, typename Number>
1910 inline unsigned int
1912 {
1913  if (task_info.face_partition_data.size() == 0)
1914  return 0;
1915  return task_info.boundary_partition_data.back() -
1917 }
1918 
1919 
1920 
1921 template <int dim, typename Number>
1922 inline unsigned int
1924 {
1925  if (task_info.face_partition_data.size() == 0)
1926  return 0;
1927  return face_info.faces.size() - task_info.boundary_partition_data.back();
1928 }
1929 
1930 
1931 
1932 template <int dim, typename Number>
1933 inline types::boundary_id
1934 MatrixFree<dim, Number>::get_boundary_id(const unsigned int macro_face) const
1935 {
1936  Assert(macro_face >= task_info.boundary_partition_data[0] &&
1937  macro_face < task_info.boundary_partition_data.back(),
1938  ExcIndexRange(macro_face,
1941  return types::boundary_id(face_info.faces[macro_face].exterior_face_no);
1942 }
1943 
1944 
1945 
1946 template <int dim, typename Number>
1947 inline std::array<types::boundary_id, VectorizedArray<Number>::n_array_elements>
1949  const unsigned int macro_cell,
1950  const unsigned int face_number) const
1951 {
1952  AssertIndexRange(macro_cell, n_macro_cells());
1955  ExcNotInitialized());
1956  std::array<types::boundary_id, VectorizedArray<Number>::n_array_elements>
1957  result;
1958  result.fill(numbers::invalid_boundary_id);
1959  for (unsigned int v = 0; v < n_active_entries_per_cell_batch(macro_cell); ++v)
1960  result[v] = face_info.cell_and_face_boundary_id(macro_cell, face_number, v);
1961  return result;
1962 }
1963 
1964 
1965 
1966 template <int dim, typename Number>
1969 {
1970  return mapping_info;
1971 }
1972 
1973 
1974 
1975 template <int dim, typename Number>
1977 MatrixFree<dim, Number>::get_dof_info(const unsigned int dof_index) const
1978 {
1979  AssertIndexRange(dof_index, n_components());
1980  return dof_info[dof_index];
1981 }
1982 
1983 
1984 
1985 template <int dim, typename Number>
1986 inline unsigned int
1988 {
1989  return constraint_pool_row_index.size() - 1;
1990 }
1991 
1992 
1993 
1994 template <int dim, typename Number>
1995 inline const Number *
1996 MatrixFree<dim, Number>::constraint_pool_begin(const unsigned int row) const
1997 {
1999  return constraint_pool_data.empty() ?
2000  nullptr :
2002 }
2003 
2004 
2005 
2006 template <int dim, typename Number>
2007 inline const Number *
2008 MatrixFree<dim, Number>::constraint_pool_end(const unsigned int row) const
2009 {
2011  return constraint_pool_data.empty() ?
2012  nullptr :
2014 }
2015 
2016 
2017 
2018 template <int dim, typename Number>
2019 inline std::pair<unsigned int, unsigned int>
2021  const std::pair<unsigned int, unsigned int> &range,
2022  const unsigned int degree,
2023  const unsigned int dof_handler_component) const
2024 {
2025  if (dof_info[dof_handler_component].cell_active_fe_index.empty())
2026  {
2028  dof_info[dof_handler_component].fe_index_conversion.size(), 1);
2030  dof_info[dof_handler_component].fe_index_conversion[0].size(), 1);
2031  if (dof_info[dof_handler_component].fe_index_conversion[0][0] == degree)
2032  return range;
2033  else
2034  return std::pair<unsigned int, unsigned int>(range.second,
2035  range.second);
2036  }
2037 
2038  const unsigned int fe_index =
2039  dof_info[dof_handler_component].fe_index_from_degree(0, degree);
2040  if (fe_index >= dof_info[dof_handler_component].max_fe_index)
2041  return std::pair<unsigned int, unsigned int>(range.second, range.second);
2042  else
2043  return create_cell_subrange_hp_by_index(range,
2044  fe_index,
2045  dof_handler_component);
2046 }
2047 
2048 
2049 
2050 template <int dim, typename Number>
2051 inline bool
2052 MatrixFree<dim, Number>::at_irregular_cell(const unsigned int macro_cell) const
2053 {
2054  AssertIndexRange(macro_cell, task_info.cell_partition_data.back());
2056  cell_level_index[(macro_cell + 1) *
2058  1] ==
2059  cell_level_index[(macro_cell + 1) *
2061  2];
2062 }
2063 
2064 
2065 
2066 template <int dim, typename Number>
2067 inline unsigned int
2069  const unsigned int cell_batch_number) const
2070 {
2071  return n_active_entries_per_cell_batch(cell_batch_number);
2072 }
2073 
2074 
2075 
2076 template <int dim, typename Number>
2077 inline unsigned int
2079  const unsigned int cell_batch_number) const
2080 {
2081  AssertIndexRange(cell_batch_number, task_info.cell_partition_data.back());
2083  while (n_components > 1 &&
2084  cell_level_index[cell_batch_number *
2086  n_components - 1] ==
2087  cell_level_index[cell_batch_number *
2089  n_components - 2])
2090  --n_components;
2092  return n_components;
2093 }
2094 
2095 
2096 
2097 template <int dim, typename Number>
2098 inline unsigned int
2100  const unsigned int face_batch_number) const
2101 {
2102  AssertIndexRange(face_batch_number, face_info.faces.size());
2104  while (n_components > 1 &&
2105  face_info.faces[face_batch_number].cells_interior[n_components - 1] ==
2107  --n_components;
2109  return n_components;
2110 }
2111 
2112 
2113 
2114 template <int dim, typename Number>
2115 inline unsigned int
2117  const unsigned int dof_handler_index,
2118  const unsigned int active_fe_index) const
2119 {
2120  return dof_info[dof_handler_index].dofs_per_cell[active_fe_index];
2121 }
2122 
2123 
2124 
2125 template <int dim, typename Number>
2126 inline unsigned int
2128  const unsigned int quad_index,
2129  const unsigned int active_fe_index) const
2130 {
2131  AssertIndexRange(quad_index, mapping_info.cell_data.size());
2132  return mapping_info.cell_data[quad_index]
2133  .descriptor[active_fe_index]
2134  .n_q_points;
2135 }
2136 
2137 
2138 
2139 template <int dim, typename Number>
2140 inline unsigned int
2142  const unsigned int dof_handler_index,
2143  const unsigned int active_fe_index) const
2144 {
2145  return dof_info[dof_handler_index].dofs_per_face[active_fe_index];
2146 }
2147 
2148 
2149 
2150 template <int dim, typename Number>
2151 inline unsigned int
2153  const unsigned int quad_index,
2154  const unsigned int active_fe_index) const
2155 {
2156  AssertIndexRange(quad_index, mapping_info.face_data.size());
2157  return mapping_info.face_data[quad_index]
2158  .descriptor[active_fe_index]
2159  .n_q_points;
2160 }
2161 
2162 
2163 
2164 template <int dim, typename Number>
2165 inline const IndexSet &
2167  const unsigned int dof_handler_index) const
2168 {
2169  return dof_info[dof_handler_index].vector_partitioner->locally_owned_range();
2170 }
2171 
2172 
2173 
2174 template <int dim, typename Number>
2175 inline const IndexSet &
2177  const unsigned int dof_handler_index) const
2178 {
2179  return dof_info[dof_handler_index].vector_partitioner->ghost_indices();
2180 }
2181 
2182 
2183 
2184 template <int dim, typename Number>
2187  const unsigned int dof_handler_index,
2188  const unsigned int index_quad,
2189  const unsigned int index_fe,
2190  const unsigned int active_fe_index,
2191  const unsigned int active_quad_index) const
2192 {
2193  AssertIndexRange(dof_handler_index, dof_info.size());
2194  const unsigned int ind =
2195  dof_info[dof_handler_index].global_base_element_offset + index_fe;
2196  AssertIndexRange(ind, shape_info.size(0));
2197  AssertIndexRange(index_quad, shape_info.size(1));
2198  AssertIndexRange(active_fe_index, shape_info.size(2));
2199  AssertIndexRange(active_quad_index, shape_info.size(3));
2200  return shape_info(ind, index_quad, active_fe_index, active_quad_index);
2201 }
2202 
2203 
2204 
2205 template <int dim, typename Number>
2208 MatrixFree<dim, Number>::get_face_info(const unsigned int macro_face) const
2209 {
2210  AssertIndexRange(macro_face, face_info.faces.size());
2211  return face_info.faces[macro_face];
2212 }
2213 
2214 
2215 
2216 template <int dim, typename Number>
2217 inline const Quadrature<dim> &
2219  const unsigned int quad_index,
2220  const unsigned int active_fe_index) const
2221 {
2222  AssertIndexRange(quad_index, mapping_info.cell_data.size());
2223  return mapping_info.cell_data[quad_index]
2224  .descriptor[active_fe_index]
2225  .quadrature;
2226 }
2227 
2228 
2229 
2230 template <int dim, typename Number>
2231 inline const Quadrature<dim - 1> &
2233  const unsigned int quad_index,
2234  const unsigned int active_fe_index) const
2235 {
2236  AssertIndexRange(quad_index, mapping_info.face_data.size());
2237  return mapping_info.face_data[quad_index]
2238  .descriptor[active_fe_index]
2239  .quadrature;
2240 }
2241 
2242 
2243 
2244 template <int dim, typename Number>
2245 inline unsigned int
2246 MatrixFree<dim, Number>::get_cell_category(const unsigned int macro_cell) const
2247 {
2248  AssertIndexRange(0, dof_info.size());
2249  AssertIndexRange(macro_cell, dof_info[0].cell_active_fe_index.size());
2250  if (dof_info[0].cell_active_fe_index.empty())
2251  return 0;
2252  else
2253  return dof_info[0].cell_active_fe_index[macro_cell];
2254 }
2255 
2256 
2257 
2258 template <int dim, typename Number>
2259 inline std::pair<unsigned int, unsigned int>
2260 MatrixFree<dim, Number>::get_face_category(const unsigned int macro_face) const
2261 {
2262  AssertIndexRange(macro_face, face_info.faces.size());
2263  if (dof_info[0].cell_active_fe_index.empty())
2264  return std::make_pair(0U, 0U);
2265 
2266  std::pair<unsigned int, unsigned int> result;
2267  for (unsigned int v = 0; v < VectorizedArray<Number>::n_array_elements &&
2268  face_info.faces[macro_face].cells_interior[v] !=
2270  ++v)
2271  result.first = std::max(
2272  result.first,
2273  dof_info[0]
2274  .cell_active_fe_index[face_info.faces[macro_face].cells_interior[v]]);
2275  if (face_info.faces[macro_face].cells_exterior[0] !=
2277  for (unsigned int v = 0; v < VectorizedArray<Number>::n_array_elements &&
2278  face_info.faces[macro_face].cells_exterior[v] !=
2280  ++v)
2281  result.second = std::max(
2282  result.first,
2283  dof_info[0]
2284  .cell_active_fe_index[face_info.faces[macro_face].cells_exterior[v]]);
2285  else
2286  result.second = numbers::invalid_unsigned_int;
2287  return result;
2288 }
2289 
2290 
2291 
2292 template <int dim, typename Number>
2293 inline bool
2295 {
2296  return indices_are_initialized;
2297 }
2298 
2299 
2300 
2301 template <int dim, typename Number>
2302 inline bool
2304 {
2305  return mapping_is_initialized;
2306 }
2307 
2308 
2309 
2310 template <int dim, typename Number>
2313 {
2314  using list_type =
2315  std::list<std::pair<bool, AlignedVector<VectorizedArray<Number>>>>;
2316  list_type &data = scratch_pad.get();
2317  for (typename list_type::iterator it = data.begin(); it != data.end(); ++it)
2318  if (it->first == false)
2319  {
2320  it->first = true;
2321  return &it->second;
2322  }
2323  data.push_front(
2324  std::make_pair(true, AlignedVector<VectorizedArray<Number>>()));
2325  return &data.front().second;
2326 }
2327 
2328 
2329 
2330 template <int dim, typename Number>
2331 void
2333  const AlignedVector<VectorizedArray<Number>> *scratch) const
2334 {
2335  using list_type =
2336  std::list<std::pair<bool, AlignedVector<VectorizedArray<Number>>>>;
2337  list_type &data = scratch_pad.get();
2338  for (typename list_type::iterator it = data.begin(); it != data.end(); ++it)
2339  if (&it->second == scratch)
2340  {
2341  Assert(it->first == true, ExcInternalError());
2342  it->first = false;
2343  return;
2344  }
2345  AssertThrow(false, ExcMessage("Tried to release invalid scratch pad"));
2346 }
2347 
2348 
2349 
2350 template <int dim, typename Number>
2353 {
2354  for (typename std::list<std::pair<bool, AlignedVector<Number>>>::iterator it =
2356  it != scratch_pad_non_threadsafe.end();
2357  ++it)
2358  if (it->first == false)
2359  {
2360  it->first = true;
2361  return &it->second;
2362  }
2363  scratch_pad_non_threadsafe.push_front(
2364  std::make_pair(true, AlignedVector<Number>()));
2365  return &scratch_pad_non_threadsafe.front().second;
2366 }
2367 
2368 
2369 
2370 template <int dim, typename Number>
2371 void
2373  const AlignedVector<Number> *scratch) const
2374 {
2375  for (typename std::list<std::pair<bool, AlignedVector<Number>>>::iterator it =
2377  it != scratch_pad_non_threadsafe.end();
2378  ++it)
2379  if (&it->second == scratch)
2380  {
2381  Assert(it->first == true, ExcInternalError());
2382  it->first = false;
2383  return;
2384  }
2385  AssertThrow(false, ExcMessage("Tried to release invalid scratch pad"));
2386 }
2387 
2388 
2389 
2390 // ------------------------------ reinit functions ---------------------------
2391 
2392 namespace internal
2393 {
2394  namespace MatrixFreeImplementation
2395  {
2396  template <typename DoFHandlerType>
2397  inline std::vector<IndexSet>
2398  extract_locally_owned_index_sets(
2399  const std::vector<const DoFHandlerType *> &dofh,
2400  const unsigned int level)
2401  {
2402  std::vector<IndexSet> locally_owned_set;
2403  locally_owned_set.reserve(dofh.size());
2404  for (unsigned int j = 0; j < dofh.size(); j++)
2405  if (level == numbers::invalid_unsigned_int)
2406  locally_owned_set.push_back(dofh[j]->locally_owned_dofs());
2407  else
2408  AssertThrow(false, ExcNotImplemented());
2409  return locally_owned_set;
2410  }
2411 
2412  template <int dim, int spacedim>
2413  inline std::vector<IndexSet>
2414  extract_locally_owned_index_sets(
2415  const std::vector<const ::DoFHandler<dim, spacedim> *> &dofh,
2416  const unsigned int level)
2417  {
2418  std::vector<IndexSet> locally_owned_set;
2419  locally_owned_set.reserve(dofh.size());
2420  for (unsigned int j = 0; j < dofh.size(); j++)
2421  if (level == numbers::invalid_unsigned_int)
2422  locally_owned_set.push_back(dofh[j]->locally_owned_dofs());
2423  else
2424  locally_owned_set.push_back(dofh[j]->locally_owned_mg_dofs(level));
2425  return locally_owned_set;
2426  }
2427  } // namespace MatrixFreeImplementation
2428 } // namespace internal
2429 
2430 
2431 
2432 template <int dim, typename Number>
2433 template <typename DoFHandlerType, typename QuadratureType, typename number2>
2434 void
2436  const DoFHandlerType & dof_handler,
2437  const AffineConstraints<number2> & constraints_in,
2438  const QuadratureType & quad,
2439  const typename MatrixFree<dim, Number>::AdditionalData additional_data)
2440 {
2441  std::vector<const DoFHandlerType *> dof_handlers;
2442  std::vector<const AffineConstraints<number2> *> constraints;
2443  std::vector<QuadratureType> quads;
2444 
2445  dof_handlers.push_back(&dof_handler);
2446  constraints.push_back(&constraints_in);
2447  quads.push_back(quad);
2448 
2449  std::vector<IndexSet> locally_owned_sets =
2450  internal::MatrixFreeImplementation::extract_locally_owned_index_sets(
2451  dof_handlers, additional_data.level_mg_handler);
2452 
2453  std::vector<hp::QCollection<1>> quad_hp;
2454  quad_hp.emplace_back(quad);
2455 
2457  dof_handlers,
2458  constraints,
2459  locally_owned_sets,
2460  quad_hp,
2461  additional_data);
2462 }
2463 
2464 
2465 
2466 template <int dim, typename Number>
2467 template <typename DoFHandlerType, typename QuadratureType, typename number2>
2468 void
2470  const Mapping<dim> & mapping,
2471  const DoFHandlerType & dof_handler,
2472  const AffineConstraints<number2> & constraints_in,
2473  const QuadratureType & quad,
2474  const typename MatrixFree<dim, Number>::AdditionalData additional_data)
2475 {
2476  std::vector<const DoFHandlerType *> dof_handlers;
2477  std::vector<const AffineConstraints<number2> *> constraints;
2478 
2479  dof_handlers.push_back(&dof_handler);
2480  constraints.push_back(&constraints_in);
2481 
2482  std::vector<IndexSet> locally_owned_sets =
2483  internal::MatrixFreeImplementation::extract_locally_owned_index_sets(
2484  dof_handlers, additional_data.level_mg_handler);
2485 
2486  std::vector<hp::QCollection<1>> quad_hp;
2487  quad_hp.emplace_back(quad);
2488 
2489  internal_reinit(mapping,
2490  dof_handlers,
2491  constraints,
2492  locally_owned_sets,
2493  quad_hp,
2494  additional_data);
2495 }
2496 
2497 
2498 
2499 template <int dim, typename Number>
2500 template <typename DoFHandlerType, typename QuadratureType, typename number2>
2501 void
2503  const std::vector<const DoFHandlerType *> & dof_handler,
2504  const std::vector<const AffineConstraints<number2> *> &constraint,
2505  const std::vector<QuadratureType> & quad,
2506  const typename MatrixFree<dim, Number>::AdditionalData additional_data)
2507 {
2508  std::vector<IndexSet> locally_owned_set =
2509  internal::MatrixFreeImplementation::extract_locally_owned_index_sets(
2510  dof_handler, additional_data.level_mg_handler);
2511  std::vector<hp::QCollection<1>> quad_hp;
2512  for (unsigned int q = 0; q < quad.size(); ++q)
2513  quad_hp.emplace_back(quad[q]);
2515  dof_handler,
2516  constraint,
2517  locally_owned_set,
2518  quad_hp,
2519  additional_data);
2520 }
2521 
2522 
2523 
2524 template <int dim, typename Number>
2525 template <typename DoFHandlerType, typename QuadratureType, typename number2>
2526 void
2528  const std::vector<const DoFHandlerType *> & dof_handler,
2529  const std::vector<const AffineConstraints<number2> *> &constraint,
2530  const QuadratureType & quad,
2531  const typename MatrixFree<dim, Number>::AdditionalData additional_data)
2532 {
2533  std::vector<IndexSet> locally_owned_set =
2534  internal::MatrixFreeImplementation::extract_locally_owned_index_sets(
2535  dof_handler, additional_data.level_mg_handler);
2536  std::vector<hp::QCollection<1>> quad_hp;
2537  quad_hp.emplace_back(quad);
2539  dof_handler,
2540  constraint,
2541  locally_owned_set,
2542  quad_hp,
2543  additional_data);
2544 }
2545 
2546 
2547 
2548 template <int dim, typename Number>
2549 template <typename DoFHandlerType, typename QuadratureType, typename number2>
2550 void
2552  const Mapping<dim> & mapping,
2553  const std::vector<const DoFHandlerType *> & dof_handler,
2554  const std::vector<const AffineConstraints<number2> *> &constraint,
2555  const QuadratureType & quad,
2556  const typename MatrixFree<dim, Number>::AdditionalData additional_data)
2557 {
2558  std::vector<IndexSet> locally_owned_set =
2559  internal::MatrixFreeImplementation::extract_locally_owned_index_sets(
2560  dof_handler, additional_data.level_mg_handler);
2561  std::vector<hp::QCollection<1>> quad_hp;
2562  quad_hp.emplace_back(quad);
2563  internal_reinit(mapping,
2564  dof_handler,
2565  constraint,
2566  locally_owned_set,
2567  quad_hp,
2568  additional_data);
2569 }
2570 
2571 
2572 
2573 template <int dim, typename Number>
2574 template <typename DoFHandlerType, typename QuadratureType, typename number2>
2575 void
2577  const Mapping<dim> & mapping,
2578  const std::vector<const DoFHandlerType *> & dof_handler,
2579  const std::vector<const AffineConstraints<number2> *> &constraint,
2580  const std::vector<QuadratureType> & quad,
2581  const typename MatrixFree<dim, Number>::AdditionalData additional_data)
2582 {
2583  std::vector<IndexSet> locally_owned_set =
2584  internal::MatrixFreeImplementation::extract_locally_owned_index_sets(
2585  dof_handler, additional_data.level_mg_handler);
2586  std::vector<hp::QCollection<1>> quad_hp;
2587  for (unsigned int q = 0; q < quad.size(); ++q)
2588  quad_hp.emplace_back(quad[q]);
2589  internal_reinit(mapping,
2590  dof_handler,
2591  constraint,
2592  locally_owned_set,
2593  quad_hp,
2594  additional_data);
2595 }
2596 
2597 
2598 
2599 template <int dim, typename Number>
2600 template <typename DoFHandlerType, typename QuadratureType, typename number2>
2601 void
2603  const Mapping<dim> & mapping,
2604  const std::vector<const DoFHandlerType *> & dof_handler,
2605  const std::vector<const AffineConstraints<number2> *> &constraint,
2606  const std::vector<IndexSet> & locally_owned_set,
2607  const std::vector<QuadratureType> & quad,
2608  const typename MatrixFree<dim, Number>::AdditionalData additional_data)
2609 {
2610  // find out whether we use a hp Quadrature or a standard quadrature
2611  std::vector<hp::QCollection<1>> quad_hp;
2612  for (unsigned int q = 0; q < quad.size(); ++q)
2613  quad_hp.emplace_back(quad[q]);
2614  internal_reinit(mapping,
2615  dof_handler,
2616  constraint,
2617  locally_owned_set,
2618  quad_hp,
2619  additional_data);
2620 }
2621 
2622 
2623 
2624 // ------------------------------ implementation of loops --------------------
2625 
2626 // internal helper functions that define how to call MPI data exchange
2627 // functions: for generic vectors, do nothing at all. For distributed vectors,
2628 // call update_ghost_values_start function and so on. If we have collections
2629 // of vectors, just do the individual functions of the components. In order to
2630 // keep ghost values consistent (whether we are in read or write mode), we
2631 // also reset the values at the end. the whole situation is a bit complicated
2632 // by the fact that we need to treat block vectors differently, which use some
2633 // additional helper functions to select the blocks and template magic.
2634 namespace internal
2635 {
2636  template <int dim, typename Number>
2637  struct VectorDataExchange
2638  {
2639  // An arbitrary shift for communication to reduce the risk for accidental
2640  // interaction with other open communications that a user program might
2641  // set up
2642  static constexpr unsigned int channel_shift = 103;
2643 
2644  VectorDataExchange(
2645  const ::MatrixFree<dim, Number> &matrix_free,
2646  const typename ::MatrixFree<dim, Number>::DataAccessOnFaces
2647  vector_face_access,
2648  const unsigned int n_components)
2649  : matrix_free(matrix_free)
2650  , vector_face_access(
2651  matrix_free.get_task_info().face_partition_data.empty() ?
2653  vector_face_access)
2654  , ghosts_were_set(false)
2655 # ifdef DEAL_II_WITH_MPI
2656  , tmp_data(n_components)
2657  , requests(n_components)
2658 # endif
2659  {
2660  (void)n_components;
2661  if (this->vector_face_access !=
2663  for (unsigned int c = 0; c < matrix_free.n_components(); ++c)
2665  matrix_free.get_dof_info(c).vector_partitioner_face_variants.size(),
2666  3);
2667  }
2668 
2669  ~VectorDataExchange()
2670  {
2671 # ifdef DEAL_II_WITH_MPI
2672  for (unsigned int i = 0; i < tmp_data.size(); ++i)
2673  if (tmp_data[i] != nullptr)
2674  matrix_free.release_scratch_data_non_threadsafe(tmp_data[i]);
2675 # endif
2676  }
2677 
2678  unsigned int
2679  find_vector_in_mf(const LinearAlgebra::distributed::Vector<Number> &vec,
2680  const bool check_global_compatibility = true) const
2681  {
2682  unsigned int mf_component = numbers::invalid_unsigned_int;
2683  (void)check_global_compatibility;
2684  for (unsigned int c = 0; c < matrix_free.n_components(); ++c)
2685  if (
2686 # ifdef DEBUG
2687  check_global_compatibility ?
2688  vec.get_partitioner()->is_globally_compatible(
2689  *matrix_free.get_dof_info(c).vector_partitioner) :
2690 # endif
2691  vec.get_partitioner()->is_compatible(
2692  *matrix_free.get_dof_info(c).vector_partitioner))
2693  {
2694  mf_component = c;
2695  break;
2696  }
2697  return mf_component;
2698  }
2699 
2701  get_partitioner(const unsigned int mf_component) const
2702  {
2703  AssertDimension(matrix_free.get_dof_info(mf_component)
2704  .vector_partitioner_face_variants.size(),
2705  3);
2706  if (vector_face_access ==
2708  return *matrix_free.get_dof_info(mf_component)
2709  .vector_partitioner_face_variants[0];
2710  else if (vector_face_access ==
2712  return *matrix_free.get_dof_info(mf_component)
2713  .vector_partitioner_face_variants[1];
2714  else
2715  return *matrix_free.get_dof_info(mf_component)
2716  .vector_partitioner_face_variants[2];
2717  }
2718 
2719  void
2720  update_ghost_values_start(
2721  const unsigned int component_in_block_vector,
2723  {
2724  (void)component_in_block_vector;
2725  bool ghosts_set = vec.has_ghost_elements();
2726  if (ghosts_set)
2727  ghosts_were_set = true;
2728  if (vector_face_access ==
2730  vec.size() == 0)
2731  vec.update_ghost_values_start(component_in_block_vector +
2732  channel_shift);
2733  else
2734  {
2735 # ifdef DEAL_II_WITH_MPI
2736  const unsigned int mf_component = find_vector_in_mf(vec);
2737  if (&get_partitioner(mf_component) ==
2738  matrix_free.get_dof_info(mf_component).vector_partitioner.get())
2739  {
2740  vec.update_ghost_values_start(component_in_block_vector +
2741  channel_shift);
2742  return;
2743  }
2744 
2745  const Utilities::MPI::Partitioner &part =
2746  get_partitioner(mf_component);
2747  if (part.n_ghost_indices() == 0 && part.n_import_indices() == 0)
2748  return;
2749 
2750  tmp_data[component_in_block_vector] =
2751  matrix_free.acquire_scratch_data_non_threadsafe();
2752  tmp_data[component_in_block_vector]->resize_fast(
2753  part.n_import_indices());
2754  AssertDimension(requests.size(), tmp_data.size());
2755 
2757  component_in_block_vector + channel_shift,
2758  ArrayView<const Number>(vec.begin(), part.local_size()),
2759  ArrayView<Number>(tmp_data[component_in_block_vector]->begin(),
2760  part.n_import_indices()),
2761  ArrayView<Number>(const_cast<Number *>(vec.begin()) +
2762  vec.get_partitioner()->local_size(),
2763  vec.get_partitioner()->n_ghost_indices()),
2764  this->requests[component_in_block_vector]);
2765 # endif
2766  }
2767  }
2768 
2769  void
2770  update_ghost_values_finish(
2771  const unsigned int component_in_block_vector,
2773  {
2774  (void)component_in_block_vector;
2775  if (vector_face_access ==
2777  vec.size() == 0)
2779  else
2780  {
2781 # ifdef DEAL_II_WITH_MPI
2782 
2783  AssertIndexRange(component_in_block_vector, tmp_data.size());
2784  AssertDimension(requests.size(), tmp_data.size());
2785 
2786  const unsigned int mf_component = find_vector_in_mf(vec);
2787  const Utilities::MPI::Partitioner &part =
2788  get_partitioner(mf_component);
2789  if (&part ==
2790  matrix_free.get_dof_info(mf_component).vector_partitioner.get())
2791  {
2793  return;
2794  }
2795 
2796  if (part.n_ghost_indices() == 0 && part.n_import_indices() == 0)
2797  return;
2798 
2800  ArrayView<Number>(const_cast<Number *>(vec.begin()) +
2801  vec.get_partitioner()->local_size(),
2802  vec.get_partitioner()->n_ghost_indices()),
2803  this->requests[component_in_block_vector]);
2804 
2805  matrix_free.release_scratch_data_non_threadsafe(
2806  tmp_data[component_in_block_vector]);
2807  tmp_data[component_in_block_vector] = nullptr;
2808 # endif
2809  }
2810  }
2811 
2812  void
2813  compress_start(const unsigned int component_in_block_vector,
2815  {
2816  (void)component_in_block_vector;
2817  Assert(vec.has_ghost_elements() == false, ExcNotImplemented());
2818  if (vector_face_access ==
2820  vec.size() == 0)
2821  vec.compress_start(component_in_block_vector + channel_shift);
2822  else
2823  {
2824 # ifdef DEAL_II_WITH_MPI
2825 
2826  const unsigned int mf_component = find_vector_in_mf(vec);
2827  const Utilities::MPI::Partitioner &part =
2828  get_partitioner(mf_component);
2829  if (&part ==
2830  matrix_free.get_dof_info(mf_component).vector_partitioner.get())
2831  {
2832  vec.compress_start(component_in_block_vector + channel_shift);
2833  return;
2834  }
2835 
2836  if (part.n_ghost_indices() == 0 && part.n_import_indices() == 0)
2837  return;
2838 
2839  tmp_data[component_in_block_vector] =
2840  matrix_free.acquire_scratch_data_non_threadsafe();
2841  tmp_data[component_in_block_vector]->resize_fast(
2842  part.n_import_indices());
2843  AssertDimension(requests.size(), tmp_data.size());
2844 
2847  component_in_block_vector + channel_shift,
2848  ArrayView<Number>(vec.begin() + vec.get_partitioner()->local_size(),
2849  vec.get_partitioner()->n_ghost_indices()),
2850  ArrayView<Number>(tmp_data[component_in_block_vector]->begin(),
2851  part.n_import_indices()),
2852  this->requests[component_in_block_vector]);
2853 # endif
2854  }
2855  }
2856 
2857  void
2858  compress_finish(const unsigned int component_in_block_vector,
2860  {
2861  (void)component_in_block_vector;
2862  if (vector_face_access ==
2864  vec.size() == 0)
2866  else
2867  {
2868 # ifdef DEAL_II_WITH_MPI
2869  AssertIndexRange(component_in_block_vector, tmp_data.size());
2870  AssertDimension(requests.size(), tmp_data.size());
2871 
2872  const unsigned int mf_component = find_vector_in_mf(vec);
2873 
2874  const Utilities::MPI::Partitioner &part =
2875  get_partitioner(mf_component);
2876  if (&part ==
2877  matrix_free.get_dof_info(mf_component).vector_partitioner.get())
2878  {
2880  return;
2881  }
2882 
2883  if (part.n_ghost_indices() == 0 && part.n_import_indices() == 0)
2884  return;
2885 
2889  tmp_data[component_in_block_vector]->begin(),
2890  part.n_import_indices()),
2891  ArrayView<Number>(vec.begin(), part.local_size()),
2892  ArrayView<Number>(vec.begin() + vec.get_partitioner()->local_size(),
2893  vec.get_partitioner()->n_ghost_indices()),
2894  this->requests[component_in_block_vector]);
2895 
2896  matrix_free.release_scratch_data_non_threadsafe(
2897  tmp_data[component_in_block_vector]);
2898  tmp_data[component_in_block_vector] = nullptr;
2899 # endif
2900  }
2901  }
2902 
2903  void
2904  reset_ghost_values(
2906  {
2907  if (ghosts_were_set == true)
2908  return;
2909 
2910  if (vector_face_access ==
2912  vec.size() == 0)
2913  vec.zero_out_ghosts();
2914  else
2915  {
2916 # ifdef DEAL_II_WITH_MPI
2917  AssertDimension(requests.size(), tmp_data.size());
2918 
2919  const unsigned int mf_component = find_vector_in_mf(vec);
2920  const Utilities::MPI::Partitioner &part =
2921  get_partitioner(mf_component);
2922  if (&part ==
2923  matrix_free.get_dof_info(mf_component).vector_partitioner.get())
2924  vec.zero_out_ghosts();
2925  else if (part.n_ghost_indices() > 0)
2926  {
2927  for (std::vector<std::pair<unsigned int, unsigned int>>::
2928  const_iterator my_ghosts =
2930  my_ghosts !=
2932  ++my_ghosts)
2933  for (unsigned int j = my_ghosts->first; j < my_ghosts->second;
2934  j++)
2935  {
2937  vec)
2938  .local_element(j + part.local_size()) = 0.;
2939  }
2940  }
2941 # endif
2942  }
2943  }
2944 
2945  void
2946  zero_vector_region(const unsigned int range_index,
2948  {
2949  if (range_index == numbers::invalid_unsigned_int)
2950  vec = Number();
2951  else
2952  {
2953  const unsigned int mf_component = find_vector_in_mf(vec, false);
2955  matrix_free.get_dof_info(mf_component);
2956  Assert(dof_info.vector_zero_range_list_index.empty() == false,
2957  ExcNotInitialized());
2958 
2960  ExcInternalError());
2961  AssertIndexRange(range_index,
2962  dof_info.vector_zero_range_list_index.size() - 1);
2963  for (unsigned int id =
2964  dof_info.vector_zero_range_list_index[range_index];
2965  id != dof_info.vector_zero_range_list_index[range_index + 1];
2966  ++id)
2967  {
2968  const unsigned int start_pos =
2969  dof_info.vector_zero_range_list[id] *
2971  const unsigned int end_pos =
2972  std::min((dof_info.vector_zero_range_list[id] + 1) *
2974  chunk_size_zero_vector,
2975  dof_info.vector_partitioner->local_size() +
2976  dof_info.vector_partitioner->n_ghost_indices());
2977  std::memset(vec.begin() + start_pos,
2978  0,
2979  (end_pos - start_pos) * sizeof(Number));
2980  }
2981  }
2982  }
2983 
2984  const ::MatrixFree<dim, Number> &matrix_free;
2985  const typename ::MatrixFree<dim, Number>::DataAccessOnFaces
2986  vector_face_access;
2987  bool ghosts_were_set;
2988 # ifdef DEAL_II_WITH_MPI
2989  std::vector<AlignedVector<Number> *> tmp_data;
2990  std::vector<std::vector<MPI_Request>> requests;
2991 # endif
2992  };
2993 
2994  template <typename VectorStruct>
2995  unsigned int
2996  n_components(const VectorStruct &vec);
2997 
2998  template <typename VectorStruct>
2999  unsigned int
3000  n_components_block(const VectorStruct &vec,
3001  std::integral_constant<bool, true>)
3002  {
3003  unsigned int components = 0;
3004  for (unsigned int bl = 0; bl < vec.n_blocks(); ++bl)
3005  components += n_components(vec.block(bl));
3006  return components;
3007  }
3008 
3009  template <typename VectorStruct>
3010  unsigned int
3011  n_components_block(const VectorStruct &, std::integral_constant<bool, false>)
3012  {
3013  return 1;
3014  }
3015 
3016  template <typename VectorStruct>
3017  unsigned int
3018  n_components(const VectorStruct &vec)
3019  {
3020  return n_components_block(
3021  vec, std::integral_constant<bool, IsBlockVector<VectorStruct>::value>());
3022  }
3023 
3024  template <typename VectorStruct>
3025  inline unsigned int
3026  n_components(const std::vector<VectorStruct> &vec)
3027  {
3028  unsigned int components = 0;
3029  for (unsigned int comp = 0; comp < vec.size(); comp++)
3030  components += n_components_block(
3031  vec[comp],
3032  std::integral_constant<bool, IsBlockVector<VectorStruct>::value>());
3033  return components;
3034  }
3035 
3036  template <typename VectorStruct>
3037  inline unsigned int
3038  n_components(const std::vector<VectorStruct *> &vec)
3039  {
3040  unsigned int components = 0;
3041  for (unsigned int comp = 0; comp < vec.size(); comp++)
3042  components += n_components_block(
3043  *vec[comp],
3044  std::integral_constant<bool, IsBlockVector<VectorStruct>::value>());
3045  return components;
3046  }
3047 
3048  template <int dim, typename VectorStruct, typename Number>
3049  void
3050  update_ghost_values_start_block(const VectorStruct &vec,
3051  const unsigned int channel,
3052  std::integral_constant<bool, true>,
3053  VectorDataExchange<dim, Number> &exchanger);
3054  template <int dim, typename VectorStruct, typename Number>
3055  void
3056  reset_ghost_values_block(const VectorStruct &vec,
3057  std::integral_constant<bool, true>,
3058  VectorDataExchange<dim, Number> &exchanger);
3059  template <int dim, typename VectorStruct, typename Number>
3060  void
3061  update_ghost_values_finish_block(const VectorStruct &vec,
3062  const unsigned int channel,
3063  std::integral_constant<bool, true>,
3064  VectorDataExchange<dim, Number> &exchanger);
3065  template <int dim, typename VectorStruct, typename Number>
3066  void
3067  compress_start_block(const VectorStruct &vec,
3068  const unsigned int channel,
3069  std::integral_constant<bool, true>,
3070  VectorDataExchange<dim, Number> &exchanger);
3071  template <int dim, typename VectorStruct, typename Number>
3072  void
3073  compress_finish_block(const VectorStruct &vec,
3074  const unsigned int channel,
3075  std::integral_constant<bool, true>,
3076  VectorDataExchange<dim, Number> &exchanger);
3077  template <int dim, typename VectorStruct, typename Number>
3078  void
3079  zero_vector_region_block(const unsigned int range_index,
3080  VectorStruct &,
3081  std::integral_constant<bool, true>,
3082  VectorDataExchange<dim, Number> &);
3083 
3084  template <int dim, typename VectorStruct, typename Number>
3085  void
3086  update_ghost_values_start_block(const VectorStruct &,
3087  const unsigned int,
3088  std::integral_constant<bool, false>,
3089  VectorDataExchange<dim, Number> &)
3090  {}
3091  template <int dim, typename VectorStruct, typename Number>
3092  void
3093  reset_ghost_values_block(const VectorStruct &,
3094  std::integral_constant<bool, false>,
3095  VectorDataExchange<dim, Number> &)
3096  {}
3097  template <int dim, typename VectorStruct, typename Number>
3098  void
3099  update_ghost_values_finish_block(const VectorStruct &,
3100  const unsigned int,
3101  std::integral_constant<bool, false>,
3102  VectorDataExchange<dim, Number> &)
3103  {}
3104  template <int dim, typename VectorStruct, typename Number>
3105  void
3106  compress_start_block(const VectorStruct &,
3107  const unsigned int,
3108  std::integral_constant<bool, false>,
3109  VectorDataExchange<dim, Number> &)
3110  {}
3111  template <int dim, typename VectorStruct, typename Number>
3112  void
3113  compress_finish_block(const VectorStruct &,
3114  const unsigned int,
3115  std::integral_constant<bool, false>,
3116  VectorDataExchange<dim, Number> &)
3117  {}
3118  template <int dim, typename VectorStruct, typename Number>
3119  void
3120  zero_vector_region_block(const unsigned int range_index,
3121  VectorStruct & vec,
3122  std::integral_constant<bool, false>,
3123  VectorDataExchange<dim, Number> &)
3124  {
3125  if (range_index == 0 || range_index == numbers::invalid_unsigned_int)
3126  vec = 0;
3127  }
3128 
3129 
3130 
3131  // if the input vector did not have ghosts imported, clear them here again
3132  // in order to avoid subsequent operations e.g. in linear solvers to work
3133  // with ghosts all the time
3134  template <int dim, typename VectorStruct, typename Number>
3135  inline void
3136  reset_ghost_values(const VectorStruct & vec,
3137  VectorDataExchange<dim, Number> &exchanger)
3138  {
3139  reset_ghost_values_block(
3140  vec,
3141  std::integral_constant<bool, IsBlockVector<VectorStruct>::value>(),
3142  exchanger);
3143  }
3144 
3145 
3146 
3147  template <int dim, typename Number, typename Number2>
3148  inline void
3149  reset_ghost_values(const LinearAlgebra::distributed::Vector<Number> &vec,
3150  VectorDataExchange<dim, Number2> &exchanger)
3151  {
3152  exchanger.reset_ghost_values(vec);
3153  }
3154 
3155 
3156 
3157  template <int dim, typename VectorStruct, typename Number>
3158  inline void
3159  reset_ghost_values(const std::vector<VectorStruct> &vec,
3160  VectorDataExchange<dim, Number> &exchanger)
3161  {
3162  // return immediately if there is nothing to do.
3163  if (exchanger.ghosts_were_set == true)
3164  return;
3165 
3166  for (unsigned int comp = 0; comp < vec.size(); comp++)
3167  reset_ghost_values(vec[comp], exchanger);
3168  }
3169 
3170 
3171 
3172  template <int dim, typename VectorStruct, typename Number>
3173  inline void
3174  reset_ghost_values(const std::vector<VectorStruct *> &vec,
3175  VectorDataExchange<dim, Number> & exchanger)
3176  {
3177  // return immediately if there is nothing to do.
3178  if (exchanger.ghosts_were_set == true)
3179  return;
3180 
3181  for (unsigned int comp = 0; comp < vec.size(); comp++)
3182  reset_ghost_values(*vec[comp], exchanger);
3183  }
3184 
3185 
3186 
3187  template <int dim, typename VectorStruct, typename Number>
3188  inline void
3189  reset_ghost_values_block(const VectorStruct &vec,
3190  std::integral_constant<bool, true>,
3191  VectorDataExchange<dim, Number> &exchanger)
3192  {
3193  // return immediately if there is nothing to do.
3194  if (exchanger.ghosts_were_set == true)
3195  return;
3196 
3197  for (unsigned int i = 0; i < vec.n_blocks(); ++i)
3198  reset_ghost_values(vec.block(i), exchanger);
3199  }
3200 
3201 
3202 
3203  // A helper function to identify block vectors with many components where we
3204  // should not try to overlap computations and communcation because there
3205  // would be too many outstanding communcation requests. This is the base case
3206  // for generic vectors
3207  template <typename VectorStruct>
3208  constexpr unsigned int
3209  get_communication_block_size(const VectorStruct &)
3210  {
3212  }
3213 
3214 
3215 
3216  // Specialized case for the block vector which as the additional member
3217  // variable
3218  template <typename Number>
3219  constexpr unsigned int
3220  get_communication_block_size(
3222  {
3224  Number>::communication_block_size;
3225  }
3226 
3227 
3228 
3229  template <int dim, typename VectorStruct, typename Number>
3230  inline void
3231  update_ghost_values_start(const VectorStruct & vec,
3232  VectorDataExchange<dim, Number> &exchanger,
3233  const unsigned int channel = 0)
3234  {
3235  update_ghost_values_start_block(
3236  vec,
3237  channel,
3238  std::integral_constant<bool, IsBlockVector<VectorStruct>::value>(),
3239  exchanger);
3240  }
3241 
3242 
3243 
3244  template <int dim, typename Number, typename Number2>
3245  inline void
3246  update_ghost_values_start(
3248  VectorDataExchange<dim, Number2> & exchanger,
3249  const unsigned int channel = 0)
3250  {
3251  exchanger.update_ghost_values_start(channel, vec);
3252  }
3253 
3254 
3255 
3256  template <int dim, typename VectorStruct, typename Number>
3257  inline void
3258  update_ghost_values_start(const std::vector<VectorStruct> &vec,
3259  VectorDataExchange<dim, Number> &exchanger)
3260  {
3261  unsigned int component_index = 0;
3262  for (unsigned int comp = 0; comp < vec.size(); comp++)
3263  {
3264  update_ghost_values_start(vec[comp], exchanger, component_index);
3265  component_index += n_components(vec[comp]);
3266  }
3267  }
3268 
3269 
3270 
3271  template <int dim, typename VectorStruct, typename Number>
3272  inline void
3273  update_ghost_values_start(const std::vector<VectorStruct *> &vec,
3274  VectorDataExchange<dim, Number> & exchanger)
3275  {
3276  unsigned int component_index = 0;
3277  for (unsigned int comp = 0; comp < vec.size(); comp++)
3278  {
3279  update_ghost_values_start(*vec[comp], exchanger, component_index);
3280  component_index += n_components(*vec[comp]);
3281  }
3282  }
3283 
3284 
3285 
3286  template <int dim, typename VectorStruct, typename Number>
3287  inline void
3288  update_ghost_values_start_block(const VectorStruct &vec,
3289  const unsigned int channel,
3290  std::integral_constant<bool, true>,
3291  VectorDataExchange<dim, Number> &exchanger)
3292  {
3293  if (get_communication_block_size(vec) < vec.n_blocks())
3294  {
3295  // don't forget to set ghosts_were_set, that otherwise happens
3296  // inside VectorDataExchange::update_ghost_values_start()
3297  exchanger.ghosts_were_set = vec.has_ghost_elements();
3298  vec.update_ghost_values();
3299  }
3300  else
3301  {
3302  for (unsigned int i = 0; i < vec.n_blocks(); ++i)
3303  update_ghost_values_start(vec.block(i), exchanger, channel + i);
3304  }
3305  }
3306 
3307 
3308 
3309  template <int dim, typename VectorStruct, typename Number>
3310  inline void
3311  update_ghost_values_finish(const VectorStruct & vec,
3312  VectorDataExchange<dim, Number> &exchanger,
3313  const unsigned int channel = 0)
3314  {
3315  update_ghost_values_finish_block(
3316  vec,
3317  channel,
3318  std::integral_constant<bool, IsBlockVector<VectorStruct>::value>(),
3319  exchanger);
3320  }
3321 
3322 
3323 
3324  template <int dim, typename Number, typename Number2>
3325  inline void
3326  update_ghost_values_finish(
3328  VectorDataExchange<dim, Number2> & exchanger,
3329  const unsigned int channel = 0)
3330  {
3331  exchanger.update_ghost_values_finish(channel, vec);
3332  }
3333 
3334 
3335 
3336  template <int dim, typename VectorStruct, typename Number>
3337  inline void
3338  update_ghost_values_finish(const std::vector<VectorStruct> &vec,
3339  VectorDataExchange<dim, Number> &exchanger)
3340  {
3341  unsigned int component_index = 0;
3342  for (unsigned int comp = 0; comp < vec.size(); comp++)
3343  {
3344  update_ghost_values_finish(vec[comp], exchanger, component_index);
3345  component_index += n_components(vec[comp]);
3346  }
3347  }
3348 
3349 
3350 
3351  template <int dim, typename VectorStruct, typename Number>
3352  inline void
3353  update_ghost_values_finish(const std::vector<VectorStruct *> &vec,
3354  VectorDataExchange<dim, Number> & exchanger)
3355  {
3356  unsigned int component_index = 0;
3357  for (unsigned int comp = 0; comp < vec.size(); comp++)
3358  {
3359  update_ghost_values_finish(*vec[comp], exchanger, component_index);
3360  component_index += n_components(*vec[comp]);
3361  }
3362  }
3363 
3364 
3365 
3366  template <int dim, typename VectorStruct, typename Number>
3367  inline void
3368  update_ghost_values_finish_block(const VectorStruct &vec,
3369  const unsigned int channel,
3370  std::integral_constant<bool, true>,
3371  VectorDataExchange<dim, Number> &exchanger)
3372  {
3373  if (get_communication_block_size(vec) < vec.n_blocks())
3374  {
3375  // do nothing, everything has already been completed in the _start()
3376  // call
3377  }
3378  else
3379  for (unsigned int i = 0; i < vec.n_blocks(); ++i)
3380  update_ghost_values_finish(vec.block(i), exchanger, channel + i);
3381  }
3382 
3383 
3384 
3385  template <int dim, typename VectorStruct, typename Number>
3386  inline void
3387  compress_start(VectorStruct & vec,
3388  VectorDataExchange<dim, Number> &exchanger,
3389  const unsigned int channel = 0)
3390  {
3391  compress_start_block(
3392  vec,
3393  channel,
3394  std::integral_constant<bool, IsBlockVector<VectorStruct>::value>(),
3395  exchanger);
3396  }
3397 
3398 
3399 
3400  template <int dim, typename Number, typename Number2>
3401  inline void
3402  compress_start(LinearAlgebra::distributed::Vector<Number> &vec,
3403  VectorDataExchange<dim, Number2> & exchanger,
3404  const unsigned int channel = 0)
3405  {
3406  exchanger.compress_start(channel, vec);
3407  }
3408 
3409 
3410 
3411  template <int dim, typename VectorStruct, typename Number>
3412  inline void
3413  compress_start(std::vector<VectorStruct> & vec,
3414  VectorDataExchange<dim, Number> &exchanger)
3415  {
3416  unsigned int component_index = 0;
3417  for (unsigned int comp = 0; comp < vec.size(); comp++)
3418  {
3419  compress_start(vec[comp], exchanger, component_index);
3420  component_index += n_components(vec[comp]);
3421  }
3422  }
3423 
3424 
3425 
3426  template <int dim, typename VectorStruct, typename Number>
3427  inline void
3428  compress_start(std::vector<VectorStruct *> & vec,
3429  VectorDataExchange<dim, Number> &exchanger)
3430  {
3431  unsigned int component_index = 0;
3432  for (unsigned int comp = 0; comp < vec.size(); comp++)
3433  {
3434  compress_start(*vec[comp], exchanger, component_index);
3435  component_index += n_components(*vec[comp]);
3436  }
3437  }
3438 
3439 
3440 
3441  template <int dim, typename VectorStruct, typename Number>
3442  inline void
3443  compress_start_block(VectorStruct & vec,
3444  const unsigned int channel,
3445  std::integral_constant<bool, true>,
3446  VectorDataExchange<dim, Number> &exchanger)
3447  {
3448  if (get_communication_block_size(vec) < vec.n_blocks())
3449  vec.compress(::VectorOperation::add);
3450  else
3451  for (unsigned int i = 0; i < vec.n_blocks(); ++i)
3452  compress_start(vec.block(i), exchanger, channel + i);
3453  }
3454 
3455 
3456 
3457  template <int dim, typename VectorStruct, typename Number>
3458  inline void
3459  compress_finish(VectorStruct & vec,
3460  VectorDataExchange<dim, Number> &exchanger,
3461  const unsigned int channel = 0)
3462  {
3463  compress_finish_block(
3464  vec,
3465  channel,
3466  std::integral_constant<bool, IsBlockVector<VectorStruct>::value>(),
3467  exchanger);
3468  }
3469 
3470 
3471 
3472  template <int dim, typename Number, typename Number2>
3473  inline void
3474  compress_finish(LinearAlgebra::distributed::Vector<Number> &vec,
3475  VectorDataExchange<dim, Number2> & exchanger,
3476  const unsigned int channel = 0)
3477  {
3478  exchanger.compress_finish(channel, vec);
3479  }
3480 
3481 
3482 
3483  template <int dim, typename VectorStruct, typename Number>
3484  inline void
3485  compress_finish(std::vector<VectorStruct> & vec,
3486  VectorDataExchange<dim, Number> &exchanger)
3487  {
3488  unsigned int component_index = 0;
3489  for (unsigned int comp = 0; comp < vec.size(); comp++)
3490  {
3491  compress_finish(vec[comp], exchanger, component_index);
3492  component_index += n_components(vec[comp]);
3493  }
3494  }
3495 
3496 
3497 
3498  template <int dim, typename VectorStruct, typename Number>
3499  inline void
3500  compress_finish(std::vector<VectorStruct *> & vec,
3501  VectorDataExchange<dim, Number> &exchanger)
3502  {
3503  unsigned int component_index = 0;
3504  for (unsigned int comp = 0; comp < vec.size(); comp++)
3505  {
3506  compress_finish(*vec[comp], exchanger, component_index);
3507  component_index += n_components(*vec[comp]);
3508  }
3509  }
3510 
3511 
3512 
3513  template <int dim, typename VectorStruct, typename Number>
3514  inline void
3515  compress_finish_block(VectorStruct & vec,
3516  const unsigned int channel,
3517  std::integral_constant<bool, true>,
3518  VectorDataExchange<dim, Number> &exchanger)
3519  {
3520  if (get_communication_block_size(vec) < vec.n_blocks())
3521  {
3522  // do nothing, everything has already been completed in the _start()
3523  // call
3524  }
3525  else
3526  for (unsigned int i = 0; i < vec.n_blocks(); ++i)
3527  compress_finish(vec.block(i), exchanger, channel + i);
3528  }
3529 
3530 
3531 
3532  template <int dim, typename VectorStruct, typename Number>
3533  inline void
3534  zero_vector_region(const unsigned int range_index,
3535  VectorStruct & vec,
3536  VectorDataExchange<dim, Number> &exchanger)
3537  {
3538  zero_vector_region_block(
3539  range_index,
3540  vec,
3541  std::integral_constant<bool, IsBlockVector<VectorStruct>::value>(),
3542  exchanger);
3543  }
3544 
3545 
3546 
3547  template <int dim, typename Number, typename Number2>
3548  inline void
3549  zero_vector_region(const unsigned int range_index,
3551  VectorDataExchange<dim, Number2> & exchanger)
3552  {
3553  exchanger.zero_vector_region(range_index, vec);
3554  }
3555 
3556 
3557 
3558  template <int dim, typename VectorStruct, typename Number>
3559  inline void
3560  zero_vector_region(const unsigned int range_index,
3561  std::vector<VectorStruct> & vec,
3562  VectorDataExchange<dim, Number> &exchanger)
3563  {
3564  for (unsigned int comp = 0; comp < vec.size(); comp++)
3565  zero_vector_region(range_index, vec[comp], exchanger);
3566  }
3567 
3568 
3569 
3570  template <int dim, typename VectorStruct, typename Number>
3571  inline void
3572  zero_vector_region(const unsigned int range_index,
3573  std::vector<VectorStruct *> & vec,
3574  VectorDataExchange<dim, Number> &exchanger)
3575  {
3576  for (unsigned int comp = 0; comp < vec.size(); comp++)
3577  zero_vector_region(range_index, *vec[comp], exchanger);
3578  }
3579 
3580 
3581 
3582  template <int dim, typename VectorStruct, typename Number>
3583  inline void
3584  zero_vector_region_block(const unsigned int range_index,
3585  VectorStruct & vec,
3586  std::integral_constant<bool, true>,
3587  VectorDataExchange<dim, Number> &exchanger)
3588  {
3589  for (unsigned int i = 0; i < vec.n_blocks(); ++i)
3590  zero_vector_region(range_index, vec.block(i), exchanger);
3591  }
3592 
3593 
3594 
3595  namespace MatrixFreeFunctions
3596  {
3597  // struct to select between a const interface and a non-const interface
3598  // for MFWorker
3599  template <typename, typename, typename, typename, bool>
3600  struct InterfaceSelector
3601  {};
3602 
3603  // Version for constant functions
3604  template <typename MF,
3605  typename InVector,
3606  typename OutVector,
3607  typename Container>
3608  struct InterfaceSelector<MF, InVector, OutVector, Container, true>
3609  {
3610  using function_type = void (Container::*)(
3611  const MF &,
3612  OutVector &,
3613  const InVector &,
3614  const std::pair<unsigned int, unsigned int> &) const;
3615  };
3616 
3617  // Version for non-constant functions
3618  template <typename MF,
3619  typename InVector,
3620  typename OutVector,
3621  typename Container>
3622  struct InterfaceSelector<MF, InVector, OutVector, Container, false>
3623  {
3624  using function_type =
3625  void (Container::*)(const MF &,
3626  OutVector &,
3627  const InVector &,
3628  const std::pair<unsigned int, unsigned int> &);
3629  };
3630  } // namespace MatrixFreeFunctions
3631 
3632 
3633 
3634  // A implementation class for the worker object that runs the various
3635  // operations we want to perform during the matrix-free loop
3636  template <typename MF,
3637  typename InVector,
3638  typename OutVector,
3639  typename Container,
3640  bool is_constant>
3641  class MFWorker : public MFWorkerInterface
3642  {
3643  public:
3644  // An alias to make the arguments further down more readable
3645  using function_type = typename MatrixFreeFunctions::
3646  InterfaceSelector<MF, InVector, OutVector, Container, is_constant>::
3647  function_type;
3648 
3649  // constructor, binds all the arguments to this class
3650  MFWorker(const MF & matrix_free,
3651  const InVector & src,
3652  OutVector & dst,
3653  const bool zero_dst_vector_setting,
3654  const Container & container,
3655  function_type cell_function,
3656  function_type face_function,
3657  function_type boundary_function,
3658  const typename MF::DataAccessOnFaces src_vector_face_access =
3659  MF::DataAccessOnFaces::none,
3660  const typename MF::DataAccessOnFaces dst_vector_face_access =
3661  MF::DataAccessOnFaces::none)
3662  : matrix_free(matrix_free)
3663  , container(const_cast<Container &>(container))
3664  , cell_function(cell_function)
3665  , face_function(face_function)
3666  , boundary_function(boundary_function)
3667  , src(src)
3668  , dst(dst)
3669  , src_data_exchanger(matrix_free,
3670  src_vector_face_access,
3671  n_components(src))
3672  , dst_data_exchanger(matrix_free,
3673  dst_vector_face_access,
3674  n_components(dst))
3675  , src_and_dst_are_same(PointerComparison::equal(&src, &dst))
3676  , zero_dst_vector_setting(zero_dst_vector_setting &&
3677  !src_and_dst_are_same)
3678  {}
3679 
3680  // Runs the cell work. If no function is given, nothing is done
3681  virtual void
3682  cell(const std::pair<unsigned int, unsigned int> &cell_range) override
3683  {
3684  if (cell_function != nullptr && cell_range.second > cell_range.first)
3685  (container.*
3686  cell_function)(matrix_free, this->dst, this->src, cell_range);
3687  }
3688 
3689  // Runs the assembler on interior faces. If no function is given, nothing
3690  // is done
3691  virtual void
3692  face(const std::pair<unsigned int, unsigned int> &face_range) override
3693  {
3694  if (face_function != nullptr && face_range.second > face_range.first)
3695  (container.*
3696  face_function)(matrix_free, this->dst, this->src, face_range);
3697  }
3698 
3699  // Runs the assembler on boundary faces. If no function is given, nothing
3700  // is done
3701  virtual void
3702  boundary(const std::pair<unsigned int, unsigned int> &face_range) override
3703  {
3704  if (boundary_function != nullptr && face_range.second > face_range.first)
3705  (container.*
3706  boundary_function)(matrix_free, this->dst, this->src, face_range);
3707  }
3708 
3709  // Starts the communication for the update ghost values operation. We
3710  // cannot call this update if ghost and destination are the same because
3711  // that would introduce spurious entries in the destination (there is also
3712  // the problem that reading from a vector that we also write to is usually
3713  // not intended in case there is overlap, but this is up to the
3714  // application code to decide and we cannot catch this case here).
3715  virtual void
3716  vector_update_ghosts_start() override
3717  {
3718  if (!src_and_dst_are_same)
3719  internal::update_ghost_values_start(src, src_data_exchanger);
3720  }
3721 
3722  // Finishes the communication for the update ghost values operation
3723  virtual void
3724  vector_update_ghosts_finish() override
3725  {
3726  if (!src_and_dst_are_same)
3727  internal::update_ghost_values_finish(src, src_data_exchanger);
3728  }
3729 
3730  // Starts the communication for the vector compress operation
3731  virtual void
3732  vector_compress_start() override
3733  {
3734  internal::compress_start(dst, dst_data_exchanger);
3735  }
3736 
3737  // Finishes the communication for the vector compress operation
3738  virtual void
3739  vector_compress_finish() override
3740  {
3741  internal::compress_finish(dst, dst_data_exchanger);
3742  if (!src_and_dst_are_same)
3743  internal::reset_ghost_values(src, src_data_exchanger);
3744  }
3745 
3746  // Zeros the given input vector
3747  virtual void
3748  zero_dst_vector_range(const unsigned int range_index) override
3749  {
3750  if (zero_dst_vector_setting)
3751  internal::zero_vector_region(range_index, dst, dst_data_exchanger);
3752  }
3753 
3754  private:
3755  const MF & matrix_free;
3756  Container & container;
3757  function_type cell_function;
3758  function_type face_function;
3759  function_type boundary_function;
3760 
3761  const InVector &src;
3762  OutVector & dst;
3763  VectorDataExchange<MF::dimension, typename MF::value_type>
3764  src_data_exchanger;
3765  VectorDataExchange<MF::dimension, typename MF::value_type>
3766  dst_data_exchanger;
3767  const bool src_and_dst_are_same;
3768  const bool zero_dst_vector_setting;
3769  };
3770 
3771 
3772 
3777  template <class MF, typename InVector, typename OutVector>
3778  struct MFClassWrapper
3779  {
3780  using function_type =
3781  std::function<void(const MF &,
3782  OutVector &,
3783  const InVector &,
3784  const std::pair<unsigned int, unsigned int> &)>;
3785 
3786  MFClassWrapper(const function_type cell,
3787  const function_type face,
3788  const function_type boundary)
3789  : cell(cell)
3790  , face(face)
3791  , boundary(boundary)
3792  {}
3793 
3794  void
3795  cell_integrator(const MF & mf,
3796  OutVector & dst,
3797  const InVector & src,
3798  const std::pair<unsigned int, unsigned int> &range) const
3799  {
3800  if (cell)
3801  cell(mf, dst, src, range);
3802  }
3803 
3804  void
3805  face_integrator(const MF & mf,
3806  OutVector & dst,
3807  const InVector & src,
3808  const std::pair<unsigned int, unsigned int> &range) const
3809  {
3810  if (face)
3811  face(mf, dst, src, range);
3812  }
3813 
3814  void
3815  boundary_integrator(
3816  const MF & mf,
3817  OutVector & dst,
3818  const InVector & src,
3819  const std::pair<unsigned int, unsigned int> &range) const
3820  {
3821  if (boundary)
3822  boundary(mf, dst, src, range);
3823  }
3824 
3825  const function_type cell;
3826  const function_type face;
3827  const function_type boundary;
3828  };
3829 
3830 } // end of namespace internal
3831 
3832 
3833 
3834 template <int dim, typename Number>
3835 template <typename OutVector, typename InVector>
3836 inline void
3838  const std::function<void(const MatrixFree<dim, Number> &,
3839  OutVector &,
3840  const InVector &,
3841  const std::pair<unsigned int, unsigned int> &)>
3842  & cell_operation,
3843  OutVector & dst,
3844  const InVector &src,
3845  const bool zero_dst_vector) const
3846 {
3847  using Wrapper =
3848  internal::MFClassWrapper<MatrixFree<dim, Number>, InVector, OutVector>;
3849  Wrapper wrap(cell_operation, nullptr, nullptr);
3850  internal::
3851  MFWorker<MatrixFree<dim, Number>, InVector, OutVector, Wrapper, true>
3852  worker(*this,
3853  src,
3854  dst,
3855  zero_dst_vector,
3856  wrap,
3857  &Wrapper::cell_integrator,
3858  &Wrapper::face_integrator,
3859  &Wrapper::boundary_integrator);
3860 
3861  task_info.loop(worker);
3862 }
3863 
3864 
3865 
3866 template <int dim, typename Number>
3867 template <typename OutVector, typename InVector>
3868 inline void
3870  const std::function<void(const MatrixFree<dim, Number> &,
3871  OutVector &,
3872  const InVector &,
3873  const std::pair<unsigned int, unsigned int> &)>
3874  &cell_operation,
3875  const std::function<void(const MatrixFree<dim, Number> &,
3876  OutVector &,
3877  const InVector &,
3878  const std::pair<unsigned int, unsigned int> &)>
3879  &face_operation,
3880  const std::function<void(const MatrixFree<dim, Number> &,
3881  OutVector &,
3882  const InVector &,
3883  const std::pair<unsigned int, unsigned int> &)>
3884  & boundary_operation,
3885  OutVector & dst,
3886  const InVector & src,
3887  const bool zero_dst_vector,
3888  const DataAccessOnFaces dst_vector_face_access,
3889  const DataAccessOnFaces src_vector_face_access) const
3890 {
3891  using Wrapper =
3892  internal::MFClassWrapper<MatrixFree<dim, Number>, InVector, OutVector>;
3893  Wrapper wrap(cell_operation, face_operation, boundary_operation);
3894  internal::
3895  MFWorker<MatrixFree<dim, Number>, InVector, OutVector, Wrapper, true>
3896  worker(*this,
3897  src,
3898  dst,
3899  zero_dst_vector,
3900  wrap,
3901  &Wrapper::cell_integrator,
3902  &Wrapper::face_integrator,
3903  &Wrapper::boundary_integrator,
3904  src_vector_face_access,
3905  dst_vector_face_access);
3906 
3907  task_info.loop(worker);
3908 }
3909 
3910 
3911 
3912 template <int dim, typename Number>
3913 template <typename CLASS, typename OutVector, typename InVector>
3914 inline void
3916  void (CLASS::*function_pointer)(const MatrixFree<dim, Number> &,
3917  OutVector &,
3918  const InVector &,
3919  const std::pair<unsigned int, unsigned int> &)
3920  const,
3921  const CLASS * owning_class,
3922  OutVector & dst,
3923  const InVector &src,
3924  const bool zero_dst_vector) const
3925 {
3926  internal::MFWorker<MatrixFree<dim, Number>, InVector, OutVector, CLASS, true>
3927  worker(*this,
3928  src,
3929  dst,
3930  zero_dst_vector,
3931  *owning_class,
3932  function_pointer,
3933  nullptr,
3934  nullptr);
3935  task_info.loop(worker);
3936 }
3937 
3938 
3939 
3940 template <int dim, typename Number>
3941 template <typename CLASS, typename OutVector, typename InVector>
3942 inline void
3944  void (CLASS::*cell_operation)(const MatrixFree<dim, Number> &,
3945  OutVector &,
3946  const InVector &,
3947  const std::pair<unsigned int, unsigned int> &)
3948  const,
3949  void (CLASS::*face_operation)(const MatrixFree<dim, Number> &,
3950  OutVector &,
3951  const InVector &,
3952  const std::pair<unsigned int, unsigned int> &)
3953  const,
3954  void (CLASS::*boundary_operation)(
3955  const MatrixFree<dim, Number> &,
3956  OutVector &,
3957  const InVector &,
3958  const std::pair<unsigned int, unsigned int> &) const,
3959  const CLASS * owning_class,
3960  OutVector & dst,
3961  const InVector & src,
3962  const bool zero_dst_vector,
3963  const DataAccessOnFaces dst_vector_face_access,
3964  const DataAccessOnFaces src_vector_face_access) const
3965 {
3966  internal::MFWorker<MatrixFree<dim, Number>, InVector, OutVector, CLASS, true>
3967  worker(*this,
3968  src,
3969  dst,
3970  zero_dst_vector,
3971  *owning_class,
3972  cell_operation,
3973  face_operation,
3974  boundary_operation,
3975  src_vector_face_access,
3976  dst_vector_face_access);
3977  task_info.loop(worker);
3978 }
3979 
3980 
3981 
3982 template <int dim, typename Number>
3983 template <typename CLASS, typename OutVector, typename InVector>
3984 inline void
3986  void (CLASS::*function_pointer)(
3987  const MatrixFree<dim, Number> &,
3988  OutVector &,
3989  const InVector &,
3990  const std::pair<unsigned int, unsigned int> &),
3991  CLASS * owning_class,
3992  OutVector & dst,
3993  const InVector &src,
3994  const bool zero_dst_vector) const
3995 {
3996  internal::MFWorker<MatrixFree<dim, Number>, InVector, OutVector, CLASS, false>
3997  worker(*this,
3998  src,
3999  dst,
4000  zero_dst_vector,
4001  *owning_class,
4002  function_pointer,
4003  nullptr,
4004  nullptr);
4005  task_info.loop(worker);
4006 }
4007 
4008 
4009 
4010 template <int dim, typename Number>
4011 template <typename CLASS, typename OutVector, typename InVector>
4012 inline void
4014  void (CLASS::*cell_operation)(const MatrixFree<dim, Number> &,
4015  OutVector &,
4016  const InVector &,
4017  const std::pair<unsigned int, unsigned int> &),
4018  void (CLASS::*face_operation)(const MatrixFree<dim, Number> &,
4019  OutVector &,
4020  const InVector &,
4021  const std::pair<unsigned int, unsigned int> &),
4022  void (CLASS::*boundary_operation)(
4023  const MatrixFree<dim, Number> &,
4024  OutVector &,
4025  const InVector &,
4026  const std::pair<unsigned int, unsigned int> &),
4027  CLASS * owning_class,
4028  OutVector & dst,
4029  const InVector & src,
4030  const bool zero_dst_vector,
4031  const DataAccessOnFaces dst_vector_face_access,
4032  const DataAccessOnFaces src_vector_face_access) const
4033 {
4034  internal::MFWorker<MatrixFree<dim, Number>, InVector, OutVector, CLASS, false>
4035  worker(*this,
4036  src,
4037  dst,
4038  zero_dst_vector,
4039  *owning_class,
4040  cell_operation,
4041  face_operation,
4042  boundary_operation,
4043  src_vector_face_access,
4044  dst_vector_face_access);
4045  task_info.loop(worker);
4046 }
4047 
4048 
4049 #endif // ifndef DOXYGEN
4050 
4051 
4052 
4053 DEAL_II_NAMESPACE_CLOSE
4054 
4055 #endif
Number value_type
Definition: matrix_free.h:119
Transformed quadrature weights.
const internal::MatrixFreeFunctions::TaskInfo & get_size_info() const
UpdateFlags mapping_update_flags_inner_faces
Definition: matrix_free.h:338
void reinit(const size_type size, const bool omit_zeroing_entries=false)
const std::shared_ptr< const Utilities::MPI::Partitioner > & get_partitioner() const
unsigned int get_n_q_points_face(const unsigned int quad_index=0, const unsigned int hp_active_fe_index=0) const
unsigned int n_ghost_indices() const
internal::MatrixFreeFunctions::TaskInfo task_info
Definition: matrix_free.h:1730
bool indices_are_initialized
Definition: matrix_free.h:1743
unsigned int get_dofs_per_cell(const unsigned int dof_handler_index=0, const unsigned int hp_active_fe_index=0) const
static const unsigned int invalid_unsigned_int
Definition: types.h:173
UpdateFlags mapping_update_flags_boundary_faces
Definition: matrix_free.h:317
bool at_irregular_cell(const unsigned int macro_cell_number) const
std::vector< unsigned int > constraint_pool_row_index
Definition: matrix_free.h:1694
void loop(const std::function< void(const MatrixFree< dim, Number > &, OutVector &, const InVector &, const std::pair< unsigned int, unsigned int > &)> &cell_operation, const std::function< void(const MatrixFree< dim, Number > &, OutVector &, const InVector &, const std::pair< unsigned int, unsigned int > &)> &face_operation, const std::function< void(const MatrixFree< dim, Number > &, OutVector &, const InVector &, const std::pair< unsigned int, unsigned int > &)> &boundary_operation, OutVector &dst, const InVector &src, const bool zero_dst_vector=false, const DataAccessOnFaces dst_vector_face_access=DataAccessOnFaces::unspecified, const DataAccessOnFaces src_vector_face_access=DataAccessOnFaces::unspecified) const
#define AssertDimension(dim1, dim2)
Definition: exceptions.h:1366
A class that provides a separate storage location on each thread that accesses the object...
static const unsigned int dimension
Definition: matrix_free.h:124
std::list< std::pair< bool, AlignedVector< Number > > > scratch_pad_non_threadsafe
Definition: matrix_free.h:1766
DoFHandlers dof_handlers
Definition: matrix_free.h:1674
unsigned int get_n_q_points(const unsigned int quad_index=0, const unsigned int hp_active_fe_index=0) const
DoFHandler< dim >::cell_iterator get_cell_iterator(const unsigned int macro_cell_number, const unsigned int vector_number, const unsigned int fe_component=0) const
bool mapping_initialized() const
const std::shared_ptr< const Utilities::MPI::Partitioner > & get_vector_partitioner(const unsigned int dof_handler_index=0) const
std::vector< std::pair< unsigned int, unsigned int > > cell_level_index
Definition: matrix_free.h:1714
std::pair< unsigned int, unsigned int > get_face_category(const unsigned int macro_face) const
std::vector< Number > constraint_pool_data
Definition: matrix_free.h:1688
AlignedVector< Number > * acquire_scratch_data_non_threadsafe() const
#define AssertIndexRange(index, range)
Definition: exceptions.h:1407
std::shared_ptr< const Utilities::MPI::Partitioner > vector_partitioner
Definition: dof_info.h:386
std::vector< unsigned int > vector_zero_range_list_index
Definition: dof_info.h:512
void copy_from(const MatrixFree< dim, Number > &matrix_free_base)
void import_from_ghosted_array_start(const VectorOperation::values vector_operation, const unsigned int communication_channel, const ArrayView< Number > &ghost_array, const ArrayView< Number > &temporary_storage, std::vector< MPI_Request > &requests) const
unsigned int n_constraint_pool_entries() const
void print_memory_consumption(StreamType &out) const
void make_connectivity_graph_faces(DynamicSparsityPattern &connectivity)
void export_to_ghosted_array_start(const unsigned int communication_channel, const ArrayView< const Number > &locally_owned_array, const ArrayView< Number > &temporary_storage, const ArrayView< Number > &ghost_array, std::vector< MPI_Request > &requests) const
unsigned int n_active_entries_per_face_batch(const unsigned int face_batch_number) const
static::ExceptionBase & ExcNotInitialized()
const std::vector< unsigned int > & get_constrained_dofs(const unsigned int dof_handler_index=0) const
std::vector< unsigned int > cell_partition_data
Definition: task_info.h:471
#define AssertThrow(cond, exc)
Definition: exceptions.h:1329
const internal::MatrixFreeFunctions::DoFInfo & get_dof_info(const unsigned int dof_handler_index_component=0) const
const DoFHandler< dim > & get_dof_handler(const unsigned int dof_handler_index=0) const
const internal::MatrixFreeFunctions::ShapeInfo< VectorizedArray< Number > > & get_shape_info(const unsigned int dof_handler_index_component=0, const unsigned int quad_index=0, const unsigned int fe_base_element=0, const unsigned int hp_active_fe_index=0, const unsigned int hp_active_quad_index=0) const
static::ExceptionBase & ExcIndexRange(int arg1, int arg2, int arg3)
const std::vector< std::pair< unsigned int, unsigned int > > & ghost_indices_within_larger_ghost_set() const
const internal::MatrixFreeFunctions::TaskInfo & get_task_info() const
hp::DoFHandler< dim >::active_cell_iterator get_hp_cell_iterator(const unsigned int macro_cell_number, const unsigned int vector_number, const unsigned int dof_handler_index=0) const
const internal::MatrixFreeFunctions::FaceToCellTopology< VectorizedArray< Number >::n_array_elements > & get_face_info(const unsigned int face_batch_number) const
void compress_start(const unsigned int communication_channel=0,::VectorOperation::values operation=VectorOperation::add)
bool mapping_is_initialized
Definition: matrix_free.h:1748
~MatrixFree() override=default
unsigned int n_macro_cells() const
void import_from_ghosted_array_finish(const VectorOperation::values vector_operation, const ArrayView< const Number > &temporary_storage, const ArrayView< Number > &locally_owned_storage, const ArrayView< Number > &ghost_array, std::vector< MPI_Request > &requests) const
typename ActiveSelector::active_cell_iterator active_cell_iterator
Definition: dof_handler.h:194
void initialize_dof_handlers(const std::vector< const DoFHandler< dim > * > &dof_handlers, const AdditionalData &additional_data)
static::ExceptionBase & ExcMessage(std::string arg1)
void clear()
void renumber_dofs(std::vector< types::global_dof_index > &renumbering, const unsigned int dof_handler_index=0)
void loop(MFWorkerInterface &worker) const
Definition: task_info.cc:337
No update.
virtual size_type size() const override
size_type size(const unsigned int i) const
#define Assert(cond, exc)
Definition: exceptions.h:1227
static bool is_supported(const FiniteElement< dim, spacedim > &fe)
UpdateFlags
unsigned int n_components() const
void update_ghost_values_start(const unsigned int communication_channel=0) const
bool indices_initialized() const
const types::boundary_id invalid_boundary_id
Definition: types.h:207
std::vector< unsigned int > boundary_partition_data
Definition: task_info.h:489
void release_scratch_data(const AlignedVector< VectorizedArray< Number >> *memory) const
void release_scratch_data_non_threadsafe(const AlignedVector< Number > *memory) const
unsigned int n_components_filled(const unsigned int cell_batch_number) const
const Quadrature< dim > & get_quadrature(const unsigned int quad_index=0, const unsigned int hp_active_fe_index=0) const
AdditionalData(const TasksParallelScheme tasks_parallel_scheme=partition_partition, const unsigned int tasks_block_size=0, const UpdateFlags mapping_update_flags=update_gradients|update_JxW_values, const UpdateFlags mapping_update_flags_boundary_faces=update_default, const UpdateFlags mapping_update_flags_inner_faces=update_default, const UpdateFlags mapping_update_flags_faces_by_cells=update_default, const unsigned int level_mg_handler=numbers::invalid_unsigned_int, const bool store_plain_indices=true, const bool initialize_indices=true, const bool initialize_mapping=true, const bool overlap_communication_computation=true, const bool hold_all_faces_to_owned_cells=false, const bool cell_vectorization_categories_strict=false)
Definition: matrix_free.h:205
TasksParallelScheme tasks_parallel_scheme
Definition: matrix_free.h:272
const Quadrature< dim-1 > & get_face_quadrature(const unsigned int quad_index=0, const unsigned int hp_active_fe_index=0) const
std::array< types::boundary_id, VectorizedArray< Number >::n_array_elements > get_faces_by_cells_boundary_id(const unsigned int macro_cell, const unsigned int face_number) const
unsigned int n_inner_face_batches() const
unsigned int n_import_indices() const
Definition: hp.h:102
bool partitioners_are_compatible(const Utilities::MPI::Partitioner &part) const
std::vector< FaceToCellTopology< vectorization_width > > faces
Definition: face_info.h:154
unsigned int n_boundary_face_batches() const
internal::MatrixFreeFunctions::FaceInfo< VectorizedArray< Number >::n_array_elements > face_info
Definition: matrix_free.h:1738
Table< 4, internal::MatrixFreeFunctions::ShapeInfo< VectorizedArray< Number > > > shape_info
Definition: matrix_free.h:1706
unsigned int n_cell_batches() const
types::boundary_id get_boundary_id(const unsigned int macro_face) const
void export_to_ghosted_array_finish(const ArrayView< Number > &ghost_array, std::vector< MPI_Request > &requests) const
const Number * constraint_pool_end(const unsigned int pool_index) const
std::size_t memory_consumption() const
std::vector< unsigned int > face_partition_data
Definition: task_info.h:480
void reinit(const Mapping< dim > &mapping, const DoFHandlerType &dof_handler, const AffineConstraints< number2 > &constraint, const QuadratureType &quad, const AdditionalData additional_data=AdditionalData())
unsigned int n_base_elements(const unsigned int dof_handler_index) const
unsigned int tasks_block_size
Definition: matrix_free.h:283
::Table< 3, types::boundary_id > cell_and_face_boundary_id
Definition: face_info.h:167
void compress_finish(::VectorOperation::values operation)
unsigned int n_physical_cells() const
unsigned int get_dofs_per_face(const unsigned int fe_component=0, const unsigned int hp_active_fe_index=0) const
internal::MatrixFreeFunctions::MappingInfo< dim, Number > mapping_info
Definition: matrix_free.h:1700
unsigned int cell_level_index_end_local
Definition: matrix_free.h:1723
std::pair< unsigned int, unsigned int > create_cell_subrange_hp_by_index(const std::pair< unsigned int, unsigned int > &range, const unsigned int fe_index, const unsigned int dof_handler_index=0) const
unsigned int level_mg_handler
Definition: matrix_free.h:376
Shape function gradients.
const IndexSet & get_locally_owned_set(const unsigned int dof_handler_index=0) const
void internal_reinit(const Mapping< dim > &mapping, const std::vector< const DoFHandler< dim > * > &dof_handler, const std::vector< const AffineConstraints< number2 > * > &constraint, const std::vector< IndexSet > &locally_owned_set, const std::vector< hp::QCollection< 1 >> &quad, const AdditionalData &additional_data)
unsigned int get_cell_category(const unsigned int macro_cell) const
unsigned int n_ghost_cell_batches() const
UpdateFlags mapping_update_flags
Definition: matrix_free.h:296
static::ExceptionBase & ExcNotImplemented()
Threads::ThreadLocalStorage< std::list< std::pair< bool, AlignedVector< VectorizedArray< Number > > > > > scratch_pad
Definition: matrix_free.h:1759
std::vector< unsigned int > vector_zero_range_list
Definition: dof_info.h:517
Definition: table.h:37
const Number * constraint_pool_begin(const unsigned int pool_index) const
std::vector< internal::MatrixFreeFunctions::DoFInfo > dof_info
Definition: matrix_free.h:1680
AlignedVector< VectorizedArray< Number > > * acquire_scratch_data() const
static const unsigned int chunk_size_zero_vector
Definition: dof_info.h:78
unsigned int boundary_id
Definition: types.h:111
const IndexSet & get_ghost_set(const unsigned int dof_handler_index=0) const
void cell_loop(const std::function< void(const MatrixFree< dim, Number > &, OutVector &, const InVector &, const std::pair< unsigned int, unsigned int > &)> &cell_operation, OutVector &dst, const InVector &src, const bool zero_dst_vector=false) const
void print(std::ostream &out) const
unsigned int n_ghost_inner_face_batches() const
UpdateFlags mapping_update_flags_faces_by_cells
Definition: matrix_free.h:366
unsigned int local_size() const
unsigned int n_active_entries_per_cell_batch(const unsigned int cell_batch_number) const
static bool equal(const T *p1, const T *p2)
std::vector< unsigned int > cell_vectorization_category
Definition: matrix_free.h:445
void initialize_dof_vector(VectorType &vec, const unsigned int dof_handler_index=0) const
static::ExceptionBase & ExcInternalError()
std::pair< unsigned int, unsigned int > create_cell_subrange_hp(const std::pair< unsigned int, unsigned int > &range, const unsigned int fe_degree, const unsigned int dof_handler_index=0) const