Reference documentation for deal.II version Git e694e60270 2021-02-25 22:28:05 -0500
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
la_parallel_vector.h
Go to the documentation of this file.
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2011 - 2020 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 #ifndef dealii_la_parallel_vector_h
17 #define dealii_la_parallel_vector_h
18 
19 #include <deal.II/base/config.h>
20 
24 #include <deal.II/base/mpi.h>
25 #include <deal.II/base/numbers.h>
28 
32 
33 #include <iomanip>
34 #include <memory>
35 
37 
38 // Forward declarations
39 #ifndef DOXYGEN
40 namespace LinearAlgebra
41 {
45  namespace distributed
46  {
47  template <typename>
48  class BlockVector;
49  }
50 
51  template <typename>
52  class ReadWriteVector;
53 } // namespace LinearAlgebra
54 
55 # ifdef DEAL_II_WITH_PETSC
56 namespace PETScWrappers
57 {
58  namespace MPI
59  {
60  class Vector;
61  }
62 } // namespace PETScWrappers
63 # endif
64 
65 # ifdef DEAL_II_WITH_TRILINOS
66 namespace TrilinosWrappers
67 {
68  namespace MPI
69  {
70  class Vector;
71  }
72 } // namespace TrilinosWrappers
73 # endif
74 #endif
75 
76 namespace LinearAlgebra
77 {
78  namespace distributed
79  {
244  template <typename Number, typename MemorySpace = MemorySpace::Host>
246  public Subscriptor
247  {
248  public:
250  using value_type = Number;
251  using pointer = value_type *;
252  using const_pointer = const value_type *;
253  using iterator = value_type *;
254  using const_iterator = const value_type *;
256  using const_reference = const value_type &;
259 
260  static_assert(
261  std::is_same<MemorySpace, ::MemorySpace::Host>::value ||
262  std::is_same<MemorySpace, ::MemorySpace::CUDA>::value,
263  "MemorySpace should be Host or CUDA");
264 
272  Vector();
273 
280  Vector(const Vector<Number, MemorySpace> &in_vector);
281 
286  Vector(const size_type size);
287 
304  Vector(const IndexSet &local_range,
305  const IndexSet &ghost_indices,
306  const MPI_Comm &communicator);
307 
311  Vector(const IndexSet &local_range, const MPI_Comm &communicator);
312 
319  Vector(
320  const std::shared_ptr<const Utilities::MPI::Partitioner> &partitioner);
321 
325  virtual ~Vector() override;
326 
331  void
332  reinit(const size_type size, const bool omit_zeroing_entries = false);
333 
344  template <typename Number2>
345  void
346  reinit(const Vector<Number2, MemorySpace> &in_vector,
347  const bool omit_zeroing_entries = false);
348 
365  void
366  reinit(const IndexSet &local_range,
367  const IndexSet &ghost_indices,
368  const MPI_Comm &communicator);
369 
373  void
374  reinit(const IndexSet &local_range, const MPI_Comm &communicator);
375 
387  void
388  reinit(
389  const std::shared_ptr<const Utilities::MPI::Partitioner> &partitioner,
390  const MPI_Comm &comm_sm = MPI_COMM_SELF);
391 
410  void
411  reinit(const types::global_dof_index local_size,
412  const types::global_dof_index ghost_size,
413  const MPI_Comm & comm,
414  const MPI_Comm & comm_sm = MPI_COMM_SELF);
415 
428  void
430 
443  operator=(const Vector<Number, MemorySpace> &in_vector);
444 
456  template <typename Number2>
458  operator=(const Vector<Number2, MemorySpace> &in_vector);
459 
461 
501  virtual void
502  compress(::VectorOperation::values operation) override;
503 
525  void
526  update_ghost_values() const;
527 
545  void
546  compress_start(
547  const unsigned int communication_channel = 0,
549 
568  void
569  compress_finish(::VectorOperation::values operation);
570 
588  void
589  update_ghost_values_start(
590  const unsigned int communication_channel = 0) const;
591 
592 
600  void
601  update_ghost_values_finish() const;
602 
614  zero_out_ghosts() const;
615 
624  void
625  zero_out_ghost_values() const;
626 
638  bool
639  has_ghost_elements() const;
640 
655  template <typename Number2>
656  void
657  copy_locally_owned_data_from(const Vector<Number2, MemorySpace> &src);
658 
669  template <typename MemorySpace2>
670  void
671  import(const Vector<Number, MemorySpace2> &src,
672  VectorOperation::values operation);
673 
675 
680 
685  virtual void
687  const bool omit_zeroing_entries = false) override;
688 
693  operator*=(const Number factor) override;
694 
699  operator/=(const Number factor) override;
700 
705  operator+=(const VectorSpaceVector<Number> &V) override;
706 
711  operator-=(const VectorSpaceVector<Number> &V) override;
712 
724  virtual void
726  VectorOperation::values operation,
727  std::shared_ptr<const Utilities::MPI::CommunicationPatternBase>
728  communication_pattern = {}) override;
729 
733  virtual Number
734  operator*(const VectorSpaceVector<Number> &V) const override;
735 
739  virtual void
740  add(const Number a) override;
741 
745  virtual void
746  add(const Number a, const VectorSpaceVector<Number> &V) override;
747 
751  virtual void
752  add(const Number a,
753  const VectorSpaceVector<Number> &V,
754  const Number b,
755  const VectorSpaceVector<Number> &W) override;
756 
761  virtual void
762  add(const std::vector<size_type> &indices,
763  const std::vector<Number> & values);
764 
769  virtual void
770  sadd(const Number s,
771  const Number a,
772  const VectorSpaceVector<Number> &V) override;
773 
779  virtual void
780  scale(const VectorSpaceVector<Number> &scaling_factors) override;
781 
785  virtual void
786  equ(const Number a, const VectorSpaceVector<Number> &V) override;
787 
792  virtual real_type
793  l1_norm() const override;
794 
799  virtual real_type
800  l2_norm() const override;
801 
805  real_type
806  norm_sqr() const;
807 
812  virtual real_type
813  linfty_norm() const override;
814 
835  virtual Number
836  add_and_dot(const Number a,
837  const VectorSpaceVector<Number> &V,
838  const VectorSpaceVector<Number> &W) override;
839 
844  virtual size_type
845  size() const override;
846 
858  virtual ::IndexSet
859  locally_owned_elements() const override;
860 
864  virtual void
865  print(std::ostream & out,
866  const unsigned int precision = 3,
867  const bool scientific = true,
868  const bool across = true) const override;
869 
873  virtual std::size_t
874  memory_consumption() const override;
876 
881 
888  operator=(const Number s) override;
889 
894  template <typename OtherNumber>
895  void
896  add(const std::vector<size_type> & indices,
897  const ::Vector<OtherNumber> &values);
898 
903  template <typename OtherNumber>
904  void
905  add(const size_type n_elements,
906  const size_type * indices,
907  const OtherNumber *values);
908 
913  void
914  sadd(const Number s, const Vector<Number, MemorySpace> &V);
915 
917 
918 
923 
931  size_type
932  local_size() const;
933 
938  size_type
939  locally_owned_size() const;
940 
945  bool
946  in_local_range(const size_type global_index) const;
947 
958  iterator
959  begin();
960 
969  begin() const;
970 
978  iterator
979  end();
980 
989  end() const;
990 
1000  Number
1001  operator()(const size_type global_index) const;
1002 
1012  Number &
1013  operator()(const size_type global_index);
1014 
1022  Number operator[](const size_type global_index) const;
1030  Number &operator[](const size_type global_index);
1031 
1040  Number
1041  local_element(const size_type local_index) const;
1042 
1051  Number &
1052  local_element(const size_type local_index);
1053 
1060  Number *
1061  get_values() const;
1062 
1080  template <typename OtherNumber>
1081  void
1082  extract_subvector_to(const std::vector<size_type> &indices,
1083  std::vector<OtherNumber> & values) const;
1084 
1112  template <typename ForwardIterator, typename OutputIterator>
1113  void
1114  extract_subvector_to(ForwardIterator indices_begin,
1115  const ForwardIterator indices_end,
1116  OutputIterator values_begin) const;
1122  virtual bool
1123  all_zero() const override;
1124 
1128  virtual Number
1129  mean_value() const override;
1130 
1135  real_type
1136  lp_norm(const real_type p) const;
1138 
1143 
1148  const MPI_Comm &
1149  get_mpi_communicator() const;
1150 
1157  const std::shared_ptr<const Utilities::MPI::Partitioner> &
1158  get_partitioner() const;
1159 
1169  bool
1170  partitioners_are_compatible(
1171  const Utilities::MPI::Partitioner &part) const;
1172 
1186  bool
1187  partitioners_are_globally_compatible(
1188  const Utilities::MPI::Partitioner &part) const;
1189 
1193  void
1194  set_ghost_state(const bool ghosted) const;
1195 
1200  const std::vector<ArrayView<const Number>> &
1201  shared_vector_data() const;
1202 
1204 
1210  DeclException0(ExcVectorTypeNotCompatible);
1211 
1217  DeclException0(ExcNotAllowedForCuda);
1218 
1222  DeclException3(ExcNonMatchingElements,
1223  Number,
1224  Number,
1225  unsigned int,
1226  << "Called compress(VectorOperation::insert), but"
1227  << " the element received from a remote processor, value "
1228  << std::setprecision(16) << arg1
1229  << ", does not match with the value "
1230  << std::setprecision(16) << arg2
1231  << " on the owner processor " << arg3);
1232 
1237  ExcAccessToNonLocalElement,
1238  size_type,
1239  size_type,
1240  size_type,
1241  size_type,
1242  << "You tried to access element " << arg1
1243  << " of a distributed vector, but this element is not "
1244  << "stored on the current processor. Note: The range of "
1245  << "locally owned elements is [" << arg2 << "," << arg3
1246  << "], and there are " << arg4 << " ghost elements "
1247  << "that this vector can access."
1248  << "\n\n"
1249  << "A common source for this kind of problem is that you "
1250  << "are passing a 'fully distributed' vector into a function "
1251  << "that needs read access to vector elements that correspond "
1252  << "to degrees of freedom on ghost cells (or at least to "
1253  << "'locally active' degrees of freedom that are not also "
1254  << "'locally owned'). You need to pass a vector that has these "
1255  << "elements as ghost entries.");
1256 
1257  private:
1262  void
1263  add_local(const Number a, const VectorSpaceVector<Number> &V);
1264 
1269  void
1270  sadd_local(const Number s,
1271  const Number a,
1272  const VectorSpaceVector<Number> &V);
1273 
1277  template <typename Number2>
1278  Number
1279  inner_product_local(const Vector<Number2, MemorySpace> &V) const;
1280 
1284  real_type
1285  norm_sqr_local() const;
1286 
1290  Number
1291  mean_value_local() const;
1292 
1296  real_type
1297  l1_norm_local() const;
1298 
1302  real_type
1303  lp_norm_local(const real_type p) const;
1304 
1308  real_type
1309  linfty_norm_local() const;
1310 
1316  Number
1317  add_and_dot_local(const Number a,
1318  const Vector<Number, MemorySpace> &V,
1319  const Vector<Number, MemorySpace> &W);
1320 
1326  std::shared_ptr<const Utilities::MPI::Partitioner> partitioner;
1327 
1332 
1336  mutable ::MemorySpace::MemorySpaceData<Number, MemorySpace> data;
1337 
1342  mutable std::shared_ptr<::parallel::internal::TBBPartitioner>
1344 
1349  mutable ::MemorySpace::MemorySpaceData<Number, MemorySpace>
1351 
1359  mutable bool vector_is_ghosted;
1360 
1361 #ifdef DEAL_II_WITH_MPI
1362 
1370  std::vector<MPI_Request> compress_requests;
1371 
1376  mutable std::vector<MPI_Request> update_ghost_values_requests;
1377 #endif
1378 
1384  mutable std::mutex mutex;
1385 
1390 
1395  void
1396  clear_mpi_requests();
1397 
1401  void
1402  resize_val(const size_type new_allocated_size,
1403  const MPI_Comm &comm_sm = MPI_COMM_SELF);
1404 
1405  // Make all other vector types friends.
1406  template <typename Number2, typename MemorySpace2>
1407  friend class Vector;
1408 
1409  // Make BlockVector type friends.
1410  template <typename Number2>
1411  friend class BlockVector;
1412  };
1416  /*-------------------- Inline functions ---------------------------------*/
1417 
1418 #ifndef DOXYGEN
1419 
1420  namespace internal
1421  {
1422  template <typename Number, typename MemorySpace>
1423  struct Policy
1424  {
1425  static inline typename Vector<Number, MemorySpace>::iterator
1427  {
1428  return nullptr;
1429  }
1430 
1431  static inline typename Vector<Number, MemorySpace>::const_iterator
1432  begin(
1433  const ::MemorySpace::MemorySpaceData<Number, MemorySpace> &)
1434  {
1435  return nullptr;
1436  }
1437 
1438  static inline Number *
1439  get_values(
1441  {
1442  return nullptr;
1443  }
1444  };
1445 
1446 
1447 
1448  template <typename Number>
1449  struct Policy<Number, ::MemorySpace::Host>
1450  {
1451  static inline
1453  begin(::MemorySpace::
1454  MemorySpaceData<Number, ::MemorySpace::Host> &data)
1455  {
1456  return data.values.get();
1457  }
1458 
1459  static inline
1461  begin(const ::MemorySpace::
1462  MemorySpaceData<Number, ::MemorySpace::Host> &data)
1463  {
1464  return data.values.get();
1465  }
1466 
1467  static inline Number *
1468  get_values(::MemorySpace::
1469  MemorySpaceData<Number, ::MemorySpace::Host> &data)
1470  {
1471  return data.values.get();
1472  }
1473  };
1474 
1475 
1476 
1477  template <typename Number>
1478  struct Policy<Number, ::MemorySpace::CUDA>
1479  {
1480  static inline
1482  begin(::MemorySpace::
1483  MemorySpaceData<Number, ::MemorySpace::CUDA> &data)
1484  {
1485  return data.values_dev.get();
1486  }
1487 
1488  static inline
1490  begin(const ::MemorySpace::
1491  MemorySpaceData<Number, ::MemorySpace::CUDA> &data)
1492  {
1493  return data.values_dev.get();
1494  }
1495 
1496  static inline Number *
1497  get_values(::MemorySpace::
1498  MemorySpaceData<Number, ::MemorySpace::CUDA> &data)
1499  {
1500  return data.values_dev.get();
1501  }
1502  };
1503  } // namespace internal
1504 
1505 
1506  template <typename Number, typename MemorySpace>
1507  inline bool
1509  {
1510  return vector_is_ghosted;
1511  }
1512 
1513 
1514 
1515  template <typename Number, typename MemorySpace>
1518  {
1519  return partitioner->size();
1520  }
1521 
1522 
1523 
1524  template <typename Number, typename MemorySpace>
1527  {
1528  return locally_owned_size();
1529  }
1530 
1531 
1532 
1533  template <typename Number, typename MemorySpace>
1536  {
1537  return partitioner->locally_owned_size();
1538  }
1539 
1540 
1541 
1542  template <typename Number, typename MemorySpace>
1543  inline bool
1545  const size_type global_index) const
1546  {
1547  return partitioner->in_local_range(global_index);
1548  }
1549 
1550 
1551 
1552  template <typename Number, typename MemorySpace>
1553  inline IndexSet
1555  {
1556  IndexSet is(size());
1557 
1558  is.add_range(partitioner->local_range().first,
1559  partitioner->local_range().second);
1560 
1561  return is;
1562  }
1563 
1564 
1565 
1566  template <typename Number, typename MemorySpace>
1569  {
1571  }
1572 
1573 
1574 
1575  template <typename Number, typename MemorySpace>
1578  {
1580  }
1581 
1582 
1583 
1584  template <typename Number, typename MemorySpace>
1587  {
1589  partitioner->locally_owned_size();
1590  }
1591 
1592 
1593 
1594  template <typename Number, typename MemorySpace>
1597  {
1599  partitioner->locally_owned_size();
1600  }
1601 
1602 
1603 
1604  template <typename Number, typename MemorySpace>
1605  const std::vector<ArrayView<const Number>> &
1607  {
1608  return data.values_sm;
1609  }
1610 
1611 
1612 
1613  template <typename Number, typename MemorySpace>
1614  inline Number
1615  Vector<Number, MemorySpace>::operator()(const size_type global_index) const
1616  {
1617  Assert((std::is_same<MemorySpace, ::MemorySpace::Host>::value),
1618  ExcMessage(
1619  "This function is only implemented for the Host memory space"));
1620  Assert(
1621  partitioner->in_local_range(global_index) ||
1622  partitioner->ghost_indices().is_element(global_index),
1623  ExcAccessToNonLocalElement(global_index,
1624  partitioner->local_range().first,
1625  partitioner->local_range().second - 1,
1626  partitioner->ghost_indices().n_elements()));
1627  // do not allow reading a vector which is not in ghost mode
1628  Assert(partitioner->in_local_range(global_index) ||
1629  vector_is_ghosted == true,
1630  ExcMessage("You tried to read a ghost element of this vector, "
1631  "but it has not imported its ghost values."));
1632  return data.values[partitioner->global_to_local(global_index)];
1633  }
1634 
1635 
1636 
1637  template <typename Number, typename MemorySpace>
1638  inline Number &
1640  {
1641  Assert((std::is_same<MemorySpace, ::MemorySpace::Host>::value),
1642  ExcMessage(
1643  "This function is only implemented for the Host memory space"));
1644  Assert(
1645  partitioner->in_local_range(global_index) ||
1646  partitioner->ghost_indices().is_element(global_index),
1647  ExcAccessToNonLocalElement(global_index,
1648  partitioner->local_range().first,
1649  partitioner->local_range().second - 1,
1650  partitioner->ghost_indices().n_elements()));
1651  // we would like to prevent reading ghosts from a vector that does not
1652  // have them imported, but this is not possible because we might be in a
1653  // part of the code where the vector has enabled ghosts but is non-const
1654  // (then, the compiler picks this method according to the C++ rule book
1655  // even if a human would pick the const method when this subsequent use
1656  // is just a read)
1657  return data.values[partitioner->global_to_local(global_index)];
1658  }
1659 
1660 
1661 
1662  template <typename Number, typename MemorySpace>
1663  inline Number Vector<Number, MemorySpace>::
1664  operator[](const size_type global_index) const
1665  {
1666  return operator()(global_index);
1667  }
1668 
1669 
1670 
1671  template <typename Number, typename MemorySpace>
1672  inline Number &Vector<Number, MemorySpace>::
1673  operator[](const size_type global_index)
1674  {
1675  return operator()(global_index);
1676  }
1677 
1678 
1679 
1680  template <typename Number, typename MemorySpace>
1681  inline Number
1683  const size_type local_index) const
1684  {
1685  Assert((std::is_same<MemorySpace, ::MemorySpace::Host>::value),
1686  ExcMessage(
1687  "This function is only implemented for the Host memory space"));
1688  AssertIndexRange(local_index,
1689  partitioner->locally_owned_size() +
1690  partitioner->n_ghost_indices());
1691  // do not allow reading a vector which is not in ghost mode
1692  Assert(local_index < locally_owned_size() || vector_is_ghosted == true,
1693  ExcMessage("You tried to read a ghost element of this vector, "
1694  "but it has not imported its ghost values."));
1695 
1696  return data.values[local_index];
1697  }
1698 
1699 
1700 
1701  template <typename Number, typename MemorySpace>
1702  inline Number &
1704  {
1705  Assert((std::is_same<MemorySpace, ::MemorySpace::Host>::value),
1706  ExcMessage(
1707  "This function is only implemented for the Host memory space"));
1708 
1709  AssertIndexRange(local_index,
1710  partitioner->locally_owned_size() +
1711  partitioner->n_ghost_indices());
1712 
1713  return data.values[local_index];
1714  }
1715 
1716 
1717 
1718  template <typename Number, typename MemorySpace>
1719  inline Number *
1721  {
1722  return internal::Policy<Number, MemorySpace>::get_values(data);
1723  }
1724 
1725 
1726 
1727  template <typename Number, typename MemorySpace>
1728  template <typename OtherNumber>
1729  inline void
1731  const std::vector<size_type> &indices,
1732  std::vector<OtherNumber> & values) const
1733  {
1734  for (size_type i = 0; i < indices.size(); ++i)
1735  values[i] = operator()(indices[i]);
1736  }
1737 
1738 
1739 
1740  template <typename Number, typename MemorySpace>
1741  template <typename ForwardIterator, typename OutputIterator>
1742  inline void
1744  ForwardIterator indices_begin,
1745  const ForwardIterator indices_end,
1746  OutputIterator values_begin) const
1747  {
1748  while (indices_begin != indices_end)
1749  {
1750  *values_begin = operator()(*indices_begin);
1751  indices_begin++;
1752  values_begin++;
1753  }
1754  }
1755 
1756 
1757 
1758  template <typename Number, typename MemorySpace>
1759  template <typename OtherNumber>
1760  inline void
1762  const std::vector<size_type> & indices,
1763  const ::Vector<OtherNumber> &values)
1764  {
1765  AssertDimension(indices.size(), values.size());
1766  for (size_type i = 0; i < indices.size(); ++i)
1767  {
1768  Assert(
1769  numbers::is_finite(values[i]),
1770  ExcMessage(
1771  "The given value is not finite but either infinite or Not A Number (NaN)"));
1772  this->operator()(indices[i]) += values(i);
1773  }
1774  }
1775 
1776 
1777 
1778  template <typename Number, typename MemorySpace>
1779  template <typename OtherNumber>
1780  inline void
1782  const size_type * indices,
1783  const OtherNumber *values)
1784  {
1785  for (size_type i = 0; i < n_elements; ++i, ++indices, ++values)
1786  {
1787  Assert(
1788  numbers::is_finite(*values),
1789  ExcMessage(
1790  "The given value is not finite but either infinite or Not A Number (NaN)"));
1791  this->operator()(*indices) += *values;
1792  }
1793  }
1794 
1795 
1796 
1797  template <typename Number, typename MemorySpace>
1798  inline const MPI_Comm &
1800  {
1801  return partitioner->get_mpi_communicator();
1802  }
1803 
1804 
1805 
1806  template <typename Number, typename MemorySpace>
1807  inline const std::shared_ptr<const Utilities::MPI::Partitioner> &
1809  {
1810  return partitioner;
1811  }
1812 
1813 
1814 
1815  template <typename Number, typename MemorySpace>
1816  inline void
1817  Vector<Number, MemorySpace>::set_ghost_state(const bool ghosted) const
1818  {
1819  vector_is_ghosted = ghosted;
1820  }
1821 
1822 #endif
1823 
1824  } // namespace distributed
1825 } // namespace LinearAlgebra
1826 
1827 
1835 template <typename Number, typename MemorySpace>
1836 inline void
1839 {
1840  u.swap(v);
1841 }
1842 
1843 
1847 template <typename Number, typename MemorySpace>
1849  : std::false_type
1850 {};
1851 
1852 
1853 
1854 namespace internal
1855 {
1856  namespace LinearOperatorImplementation
1857  {
1858  template <typename>
1859  class ReinitHelper;
1860 
1865  template <typename Number>
1866  class ReinitHelper<LinearAlgebra::distributed::Vector<Number>>
1867  {
1868  public:
1869  // A helper type-trait that leverage SFINAE to figure out if type T has
1870  // void T::get_mpi_communicator()
1871  template <typename T>
1872  struct has_get_mpi_communicator
1873  {
1874  private:
1875  static bool
1876  detect(...);
1877 
1878  template <typename U>
1879  static decltype(std::declval<U>().get_mpi_communicator())
1880  detect(const U &);
1881 
1882  public:
1883  static const bool value =
1884  !std::is_same<bool, decltype(detect(std::declval<T>()))>::value;
1885  };
1886 
1887  // A helper type-trait that leverage SFINAE to figure out if type T has
1888  // void T::locally_owned_domain_indices()
1889  template <typename T>
1890  struct has_locally_owned_domain_indices
1891  {
1892  private:
1893  static bool
1894  detect(...);
1895 
1896  template <typename U>
1897  static decltype(std::declval<U>().locally_owned_domain_indices())
1898  detect(const U &);
1899 
1900  public:
1901  static const bool value =
1902  !std::is_same<bool, decltype(detect(std::declval<T>()))>::value;
1903  };
1904 
1905  // A helper type-trait that leverage SFINAE to figure out if type T has
1906  // void T::locally_owned_range_indices()
1907  template <typename T>
1908  struct has_locally_owned_range_indices
1909  {
1910  private:
1911  static bool
1912  detect(...);
1913 
1914  template <typename U>
1915  static decltype(std::declval<U>().locally_owned_range_indices())
1916  detect(const U &);
1917 
1918  public:
1919  static const bool value =
1920  !std::is_same<bool, decltype(detect(std::declval<T>()))>::value;
1921  };
1922 
1923  // A helper type-trait that leverage SFINAE to figure out if type T has
1924  // void T::initialize_dof_vector(VectorType v)
1925  template <typename T>
1926  struct has_initialize_dof_vector
1927  {
1928  private:
1929  static bool
1930  detect(...);
1931 
1932  template <typename U>
1933  static decltype(std::declval<U>().initialize_dof_vector(
1934  std::declval<LinearAlgebra::distributed::Vector<Number> &>()))
1935  detect(const U &);
1936 
1937  public:
1938  static const bool value =
1939  !std::is_same<bool, decltype(detect(std::declval<T>()))>::value;
1940  };
1941 
1942  // Used for (Trilinos/PETSc)Wrappers::SparseMatrix
1943  template <typename MatrixType,
1944  typename std::enable_if<
1945  has_get_mpi_communicator<MatrixType>::value &&
1946  has_locally_owned_domain_indices<MatrixType>::value,
1947  MatrixType>::type * = nullptr>
1948  static void
1949  reinit_domain_vector(MatrixType & mat,
1951  bool /*omit_zeroing_entries*/)
1952  {
1953  vec.reinit(mat.locally_owned_domain_indices(),
1954  mat.get_mpi_communicator());
1955  }
1956 
1957  // Used for MatrixFree and DiagonalMatrix
1958  template <
1959  typename MatrixType,
1960  typename std::enable_if<has_initialize_dof_vector<MatrixType>::value,
1961  MatrixType>::type * = nullptr>
1962  static void
1963  reinit_domain_vector(MatrixType & mat,
1965  bool omit_zeroing_entries)
1966  {
1967  mat.initialize_dof_vector(vec);
1968  if (!omit_zeroing_entries)
1969  vec = Number();
1970  }
1971 
1972  // Used for (Trilinos/PETSc)Wrappers::SparseMatrix
1973  template <typename MatrixType,
1974  typename std::enable_if<
1975  has_get_mpi_communicator<MatrixType>::value &&
1976  has_locally_owned_range_indices<MatrixType>::value,
1977  MatrixType>::type * = nullptr>
1978  static void
1979  reinit_range_vector(MatrixType & mat,
1981  bool /*omit_zeroing_entries*/)
1982  {
1983  vec.reinit(mat.locally_owned_range_indices(),
1984  mat.get_mpi_communicator());
1985  }
1986 
1987  // Used for MatrixFree and DiagonalMatrix
1988  template <
1989  typename MatrixType,
1990  typename std::enable_if<has_initialize_dof_vector<MatrixType>::value,
1991  MatrixType>::type * = nullptr>
1992  static void
1993  reinit_range_vector(MatrixType & mat,
1995  bool omit_zeroing_entries)
1996  {
1997  mat.initialize_dof_vector(vec);
1998  if (!omit_zeroing_entries)
1999  vec = Number();
2000  }
2001  };
2002 
2003  } // namespace LinearOperatorImplementation
2004 } /* namespace internal */
2005 
2006 
2008 
2009 #endif
void reinit(MatrixBlock< MatrixType > &v, const BlockSparsityPattern &p)
Definition: matrix_block.h:618
bool in_local_range(const size_type global_index) const
#define AssertDimension(dim1, dim2)
Definition: exceptions.h:1623
std::vector< MPI_Request > update_ghost_values_requests
#define DEAL_II_DEPRECATED_EARLY
Definition: config.h:164
std::vector< value_type > l2_norm(const typename ::Triangulation< dim, spacedim >::cell_iterator &parent, const value_type parent_value)
void scale(const double scaling_factor, Triangulation< dim, spacedim > &triangulation)
Definition: grid_tools.cc:953
std::shared_ptr< const Utilities::MPI::Partitioner > partitioner
#define AssertIndexRange(index, range)
Definition: exceptions.h:1691
__global__ void add_and_dot(Number *res, Number *v1, const Number *v2, const Number *v3, const Number a, const size_type N)
static const char V
void reinit(const size_type size, const bool omit_zeroing_entries=false)
static const char U
size_type locally_owned_size() const
static void reinit_range_vector(MatrixType &mat, LinearAlgebra::distributed::Vector< Number > &vec, bool omit_zeroing_entries)
bool is_finite(const double x)
Definition: numbers.h:527
Number local_element(const size_type local_index) const
void set_ghost_state(const bool ghosted) const
static ::ExceptionBase & ExcMessage(std::string arg1)
static void reinit_domain_vector(MatrixType &mat, LinearAlgebra::distributed::Vector< Number > &vec, bool)
std::string compress(const std::string &input)
Definition: utilities.cc:392
#define Assert(cond, exc)
Definition: exceptions.h:1466
static void reinit_range_vector(MatrixType &mat, LinearAlgebra::distributed::Vector< Number > &vec, bool)
Number linfty_norm(const Tensor< 2, dim, Number > &t)
Definition: tensor.h:2818
#define DeclException0(Exception0)
Definition: exceptions.h:470
void swap(LinearAlgebra::distributed::Vector< Number, MemorySpace > &u, LinearAlgebra::distributed::Vector< Number, MemorySpace > &v)
#define DEAL_II_NAMESPACE_CLOSE
Definition: config.h:394
std::shared_ptr<::parallel::internal::TBBPartitioner > thread_loop_partitioner
VectorType::value_type * end(VectorType &V)
mutable ::MemorySpace::MemorySpaceData< Number, MemorySpace > import_data
const std::vector< ArrayView< const Number > > & shared_vector_data() const
__global__ void equ(Number *val, const Number a, const Number *V_val, const size_type N)
mutable ::MemorySpace::MemorySpaceData< Number, MemorySpace > data
__global__ void sadd(const Number s, Number *val, const Number a, const Number *V_val, const size_type N)
SymmetricTensor< 2, dim, Number > b(const Tensor< 2, dim, Number > &F)
typename numbers::NumberTraits< Number >::real_type real_type
unsigned int global_dof_index
Definition: types.h:76
virtual ::IndexSet locally_owned_elements() const override
virtual size_type size() const override
*braid_SplitCommworld & comm
void swap(Vector< Number, MemorySpace > &v)
#define DEAL_II_NAMESPACE_OPEN
Definition: config.h:393
VectorType::value_type * begin(VectorType &V)
const std::shared_ptr< const Utilities::MPI::Partitioner > & get_partitioner() const
static void reinit_domain_vector(MatrixType &mat, LinearAlgebra::distributed::Vector< Number > &vec, bool omit_zeroing_entries)
#define DeclException4(Exception4, type1, type2, type3, type4, outsequence)
Definition: exceptions.h:584
Number l1_norm(const Tensor< 2, dim, Number > &t)
Definition: tensor.h:2792
Number operator()(const size_type global_index) const
virtual void add(const Number a) override
TrilinosWrappers::types::int_type global_index(const Epetra_BlockMap &map, const ::types::global_dof_index i)
#define DeclException3(Exception3, type1, type2, type3, outsequence)
Definition: exceptions.h:561
std::enable_if< std::is_floating_point< T >::value &&std::is_floating_point< U >::value, typename ProductType< std::complex< T >, std::complex< U > >::type >::type operator*(const std::complex< T > &left, const std::complex< U > &right)
const MPI_Comm & get_mpi_communicator() const
std::vector< MPI_Request > compress_requests
void extract_subvector_to(const std::vector< size_type > &indices, std::vector< OtherNumber > &values) const
Number operator[](const size_type global_index) const
std::enable_if< std::is_fundamental< T >::value, std::size_t >::type memory_consumption(const T &t)