Reference documentation for deal.II version Git 78a8940608 2021-04-17 09:24:19 -0400
\(\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  {
247  template <typename Number, typename MemorySpace = MemorySpace::Host>
249  public Subscriptor
250  {
251  public:
253  using value_type = Number;
254  using pointer = value_type *;
255  using const_pointer = const value_type *;
256  using iterator = value_type *;
257  using const_iterator = const value_type *;
259  using const_reference = const value_type &;
262 
263  static_assert(
264  std::is_same<MemorySpace, ::MemorySpace::Host>::value ||
265  std::is_same<MemorySpace, ::MemorySpace::CUDA>::value,
266  "MemorySpace should be Host or CUDA");
267 
275  Vector();
276 
283  Vector(const Vector<Number, MemorySpace> &in_vector);
284 
289  Vector(const size_type size);
290 
307  Vector(const IndexSet &local_range,
308  const IndexSet &ghost_indices,
309  const MPI_Comm &communicator);
310 
314  Vector(const IndexSet &local_range, const MPI_Comm &communicator);
315 
322  Vector(
323  const std::shared_ptr<const Utilities::MPI::Partitioner> &partitioner);
324 
328  virtual ~Vector() override;
329 
334  void
335  reinit(const size_type size, const bool omit_zeroing_entries = false);
336 
347  template <typename Number2>
348  void
349  reinit(const Vector<Number2, MemorySpace> &in_vector,
350  const bool omit_zeroing_entries = false);
351 
368  void
369  reinit(const IndexSet &local_range,
370  const IndexSet &ghost_indices,
371  const MPI_Comm &communicator);
372 
376  void
377  reinit(const IndexSet &local_range, const MPI_Comm &communicator);
378 
391  void
392  reinit(
393  const std::shared_ptr<const Utilities::MPI::Partitioner> &partitioner,
394  const MPI_Comm &comm_sm = MPI_COMM_SELF);
395 
415  void
416  reinit(const types::global_dof_index local_size,
417  const types::global_dof_index ghost_size,
418  const MPI_Comm & comm,
419  const MPI_Comm & comm_sm = MPI_COMM_SELF);
420 
433  void
435 
448  operator=(const Vector<Number, MemorySpace> &in_vector);
449 
461  template <typename Number2>
463  operator=(const Vector<Number2, MemorySpace> &in_vector);
464 
466 
506  virtual void
507  compress(::VectorOperation::values operation) override;
508 
530  void
531  update_ghost_values() const;
532 
550  void
551  compress_start(
552  const unsigned int communication_channel = 0,
554 
573  void
574  compress_finish(::VectorOperation::values operation);
575 
593  void
594  update_ghost_values_start(
595  const unsigned int communication_channel = 0) const;
596 
597 
605  void
606  update_ghost_values_finish() const;
607 
619  zero_out_ghosts() const;
620 
629  void
630  zero_out_ghost_values() const;
631 
643  bool
644  has_ghost_elements() const;
645 
660  template <typename Number2>
661  void
662  copy_locally_owned_data_from(const Vector<Number2, MemorySpace> &src);
663 
674  template <typename MemorySpace2>
675  void
676  import(const Vector<Number, MemorySpace2> &src,
677  VectorOperation::values operation);
678 
680 
685 
690  virtual void
692  const bool omit_zeroing_entries = false) override;
693 
698  operator*=(const Number factor) override;
699 
704  operator/=(const Number factor) override;
705 
710  operator+=(const VectorSpaceVector<Number> &V) override;
711 
716  operator-=(const VectorSpaceVector<Number> &V) override;
717 
729  virtual void
731  VectorOperation::values operation,
732  std::shared_ptr<const Utilities::MPI::CommunicationPatternBase>
733  communication_pattern = {}) override;
734 
738  virtual Number
739  operator*(const VectorSpaceVector<Number> &V) const override;
740 
744  virtual void
745  add(const Number a) override;
746 
750  virtual void
751  add(const Number a, const VectorSpaceVector<Number> &V) override;
752 
756  virtual void
757  add(const Number a,
758  const VectorSpaceVector<Number> &V,
759  const Number b,
760  const VectorSpaceVector<Number> &W) override;
761 
766  virtual void
767  add(const std::vector<size_type> &indices,
768  const std::vector<Number> & values);
769 
774  virtual void
775  sadd(const Number s,
776  const Number a,
777  const VectorSpaceVector<Number> &V) override;
778 
784  virtual void
785  scale(const VectorSpaceVector<Number> &scaling_factors) override;
786 
790  virtual void
791  equ(const Number a, const VectorSpaceVector<Number> &V) override;
792 
797  virtual real_type
798  l1_norm() const override;
799 
804  virtual real_type
805  l2_norm() const override;
806 
810  real_type
811  norm_sqr() const;
812 
817  virtual real_type
818  linfty_norm() const override;
819 
840  virtual Number
841  add_and_dot(const Number a,
842  const VectorSpaceVector<Number> &V,
843  const VectorSpaceVector<Number> &W) override;
844 
849  virtual size_type
850  size() const override;
851 
863  virtual ::IndexSet
864  locally_owned_elements() const override;
865 
869  virtual void
870  print(std::ostream & out,
871  const unsigned int precision = 3,
872  const bool scientific = true,
873  const bool across = true) const override;
874 
878  virtual std::size_t
879  memory_consumption() const override;
881 
886 
893  operator=(const Number s) override;
894 
899  template <typename OtherNumber>
900  void
901  add(const std::vector<size_type> & indices,
902  const ::Vector<OtherNumber> &values);
903 
908  template <typename OtherNumber>
909  void
910  add(const size_type n_elements,
911  const size_type * indices,
912  const OtherNumber *values);
913 
918  void
919  sadd(const Number s, const Vector<Number, MemorySpace> &V);
920 
922 
923 
928 
936  size_type
937  local_size() const;
938 
943  size_type
944  locally_owned_size() const;
945 
950  bool
951  in_local_range(const size_type global_index) const;
952 
963  iterator
964  begin();
965 
974  begin() const;
975 
983  iterator
984  end();
985 
994  end() const;
995 
1005  Number
1006  operator()(const size_type global_index) const;
1007 
1017  Number &
1018  operator()(const size_type global_index);
1019 
1027  Number operator[](const size_type global_index) const;
1035  Number &operator[](const size_type global_index);
1036 
1045  Number
1046  local_element(const size_type local_index) const;
1047 
1056  Number &
1057  local_element(const size_type local_index);
1058 
1065  Number *
1066  get_values() const;
1067 
1085  template <typename OtherNumber>
1086  void
1087  extract_subvector_to(const std::vector<size_type> &indices,
1088  std::vector<OtherNumber> & values) const;
1089 
1117  template <typename ForwardIterator, typename OutputIterator>
1118  void
1119  extract_subvector_to(ForwardIterator indices_begin,
1120  const ForwardIterator indices_end,
1121  OutputIterator values_begin) const;
1127  virtual bool
1128  all_zero() const override;
1129 
1133  virtual Number
1134  mean_value() const override;
1135 
1140  real_type
1141  lp_norm(const real_type p) const;
1143 
1148 
1153  const MPI_Comm &
1154  get_mpi_communicator() const;
1155 
1162  const std::shared_ptr<const Utilities::MPI::Partitioner> &
1163  get_partitioner() const;
1164 
1174  bool
1175  partitioners_are_compatible(
1176  const Utilities::MPI::Partitioner &part) const;
1177 
1191  bool
1192  partitioners_are_globally_compatible(
1193  const Utilities::MPI::Partitioner &part) const;
1194 
1198  void
1199  set_ghost_state(const bool ghosted) const;
1200 
1205  const std::vector<ArrayView<const Number>> &
1206  shared_vector_data() const;
1207 
1209 
1215  DeclException0(ExcVectorTypeNotCompatible);
1216 
1222  DeclException0(ExcNotAllowedForCuda);
1223 
1227  DeclException3(ExcNonMatchingElements,
1228  Number,
1229  Number,
1230  unsigned int,
1231  << "Called compress(VectorOperation::insert), but"
1232  << " the element received from a remote processor, value "
1233  << std::setprecision(16) << arg1
1234  << ", does not match with the value "
1235  << std::setprecision(16) << arg2
1236  << " on the owner processor " << arg3);
1237 
1242  ExcAccessToNonLocalElement,
1243  size_type,
1244  size_type,
1245  size_type,
1246  size_type,
1247  << "You tried to access element " << arg1
1248  << " of a distributed vector, but this element is not "
1249  << "stored on the current processor. Note: The range of "
1250  << "locally owned elements is [" << arg2 << "," << arg3
1251  << "], and there are " << arg4 << " ghost elements "
1252  << "that this vector can access."
1253  << "\n\n"
1254  << "A common source for this kind of problem is that you "
1255  << "are passing a 'fully distributed' vector into a function "
1256  << "that needs read access to vector elements that correspond "
1257  << "to degrees of freedom on ghost cells (or at least to "
1258  << "'locally active' degrees of freedom that are not also "
1259  << "'locally owned'). You need to pass a vector that has these "
1260  << "elements as ghost entries.");
1261 
1262  private:
1267  void
1268  add_local(const Number a, const VectorSpaceVector<Number> &V);
1269 
1274  void
1275  sadd_local(const Number s,
1276  const Number a,
1277  const VectorSpaceVector<Number> &V);
1278 
1282  template <typename Number2>
1283  Number
1284  inner_product_local(const Vector<Number2, MemorySpace> &V) const;
1285 
1289  real_type
1290  norm_sqr_local() const;
1291 
1295  Number
1296  mean_value_local() const;
1297 
1301  real_type
1302  l1_norm_local() const;
1303 
1307  real_type
1308  lp_norm_local(const real_type p) const;
1309 
1313  real_type
1314  linfty_norm_local() const;
1315 
1321  Number
1322  add_and_dot_local(const Number a,
1323  const Vector<Number, MemorySpace> &V,
1324  const Vector<Number, MemorySpace> &W);
1325 
1331  std::shared_ptr<const Utilities::MPI::Partitioner> partitioner;
1332 
1337 
1341  mutable ::MemorySpace::MemorySpaceData<Number, MemorySpace> data;
1342 
1347  mutable std::shared_ptr<::parallel::internal::TBBPartitioner>
1349 
1354  mutable ::MemorySpace::MemorySpaceData<Number, MemorySpace>
1356 
1364  mutable bool vector_is_ghosted;
1365 
1366 #ifdef DEAL_II_WITH_MPI
1367 
1375  std::vector<MPI_Request> compress_requests;
1376 
1381  mutable std::vector<MPI_Request> update_ghost_values_requests;
1382 #endif
1383 
1389  mutable std::mutex mutex;
1390 
1397 
1402  void
1403  clear_mpi_requests();
1404 
1408  void
1409  resize_val(const size_type new_allocated_size,
1410  const MPI_Comm &comm_sm = MPI_COMM_SELF);
1411 
1412  // Make all other vector types friends.
1413  template <typename Number2, typename MemorySpace2>
1414  friend class Vector;
1415 
1416  // Make BlockVector type friends.
1417  template <typename Number2>
1418  friend class BlockVector;
1419  };
1423  /*-------------------- Inline functions ---------------------------------*/
1424 
1425 #ifndef DOXYGEN
1426 
1427  namespace internal
1428  {
1429  template <typename Number, typename MemorySpace>
1430  struct Policy
1431  {
1432  static inline typename Vector<Number, MemorySpace>::iterator
1434  {
1435  return nullptr;
1436  }
1437 
1438  static inline typename Vector<Number, MemorySpace>::const_iterator
1439  begin(
1440  const ::MemorySpace::MemorySpaceData<Number, MemorySpace> &)
1441  {
1442  return nullptr;
1443  }
1444 
1445  static inline Number *
1446  get_values(
1448  {
1449  return nullptr;
1450  }
1451  };
1452 
1453 
1454 
1455  template <typename Number>
1456  struct Policy<Number, ::MemorySpace::Host>
1457  {
1458  static inline
1460  begin(::MemorySpace::
1461  MemorySpaceData<Number, ::MemorySpace::Host> &data)
1462  {
1463  return data.values.get();
1464  }
1465 
1466  static inline
1468  begin(const ::MemorySpace::
1469  MemorySpaceData<Number, ::MemorySpace::Host> &data)
1470  {
1471  return data.values.get();
1472  }
1473 
1474  static inline Number *
1475  get_values(::MemorySpace::
1476  MemorySpaceData<Number, ::MemorySpace::Host> &data)
1477  {
1478  return data.values.get();
1479  }
1480  };
1481 
1482 
1483 
1484  template <typename Number>
1485  struct Policy<Number, ::MemorySpace::CUDA>
1486  {
1487  static inline
1489  begin(::MemorySpace::
1490  MemorySpaceData<Number, ::MemorySpace::CUDA> &data)
1491  {
1492  return data.values_dev.get();
1493  }
1494 
1495  static inline
1497  begin(const ::MemorySpace::
1498  MemorySpaceData<Number, ::MemorySpace::CUDA> &data)
1499  {
1500  return data.values_dev.get();
1501  }
1502 
1503  static inline Number *
1504  get_values(::MemorySpace::
1505  MemorySpaceData<Number, ::MemorySpace::CUDA> &data)
1506  {
1507  return data.values_dev.get();
1508  }
1509  };
1510  } // namespace internal
1511 
1512 
1513  template <typename Number, typename MemorySpace>
1514  inline bool
1516  {
1517  return vector_is_ghosted;
1518  }
1519 
1520 
1521 
1522  template <typename Number, typename MemorySpace>
1525  {
1526  return partitioner->size();
1527  }
1528 
1529 
1530 
1531  template <typename Number, typename MemorySpace>
1534  {
1535  return locally_owned_size();
1536  }
1537 
1538 
1539 
1540  template <typename Number, typename MemorySpace>
1543  {
1544  return partitioner->locally_owned_size();
1545  }
1546 
1547 
1548 
1549  template <typename Number, typename MemorySpace>
1550  inline bool
1552  const size_type global_index) const
1553  {
1554  return partitioner->in_local_range(global_index);
1555  }
1556 
1557 
1558 
1559  template <typename Number, typename MemorySpace>
1560  inline IndexSet
1562  {
1563  IndexSet is(size());
1564 
1565  is.add_range(partitioner->local_range().first,
1566  partitioner->local_range().second);
1567 
1568  return is;
1569  }
1570 
1571 
1572 
1573  template <typename Number, typename MemorySpace>
1576  {
1578  }
1579 
1580 
1581 
1582  template <typename Number, typename MemorySpace>
1585  {
1587  }
1588 
1589 
1590 
1591  template <typename Number, typename MemorySpace>
1594  {
1596  partitioner->locally_owned_size();
1597  }
1598 
1599 
1600 
1601  template <typename Number, typename MemorySpace>
1604  {
1606  partitioner->locally_owned_size();
1607  }
1608 
1609 
1610 
1611  template <typename Number, typename MemorySpace>
1612  const std::vector<ArrayView<const Number>> &
1614  {
1615  return data.values_sm;
1616  }
1617 
1618 
1619 
1620  template <typename Number, typename MemorySpace>
1621  inline Number
1622  Vector<Number, MemorySpace>::operator()(const size_type global_index) const
1623  {
1624  Assert((std::is_same<MemorySpace, ::MemorySpace::Host>::value),
1625  ExcMessage(
1626  "This function is only implemented for the Host memory space"));
1627  Assert(
1628  partitioner->in_local_range(global_index) ||
1629  partitioner->ghost_indices().is_element(global_index),
1630  ExcAccessToNonLocalElement(global_index,
1631  partitioner->local_range().first,
1632  partitioner->local_range().second - 1,
1633  partitioner->ghost_indices().n_elements()));
1634  // do not allow reading a vector which is not in ghost mode
1635  Assert(partitioner->in_local_range(global_index) ||
1636  vector_is_ghosted == true,
1637  ExcMessage("You tried to read a ghost element of this vector, "
1638  "but it has not imported its ghost values."));
1639  return data.values[partitioner->global_to_local(global_index)];
1640  }
1641 
1642 
1643 
1644  template <typename Number, typename MemorySpace>
1645  inline Number &
1647  {
1648  Assert((std::is_same<MemorySpace, ::MemorySpace::Host>::value),
1649  ExcMessage(
1650  "This function is only implemented for the Host memory space"));
1651  Assert(
1652  partitioner->in_local_range(global_index) ||
1653  partitioner->ghost_indices().is_element(global_index),
1654  ExcAccessToNonLocalElement(global_index,
1655  partitioner->local_range().first,
1656  partitioner->local_range().second - 1,
1657  partitioner->ghost_indices().n_elements()));
1658  // we would like to prevent reading ghosts from a vector that does not
1659  // have them imported, but this is not possible because we might be in a
1660  // part of the code where the vector has enabled ghosts but is non-const
1661  // (then, the compiler picks this method according to the C++ rule book
1662  // even if a human would pick the const method when this subsequent use
1663  // is just a read)
1664  return data.values[partitioner->global_to_local(global_index)];
1665  }
1666 
1667 
1668 
1669  template <typename Number, typename MemorySpace>
1670  inline Number Vector<Number, MemorySpace>::
1671  operator[](const size_type global_index) const
1672  {
1673  return operator()(global_index);
1674  }
1675 
1676 
1677 
1678  template <typename Number, typename MemorySpace>
1679  inline Number &Vector<Number, MemorySpace>::
1680  operator[](const size_type global_index)
1681  {
1682  return operator()(global_index);
1683  }
1684 
1685 
1686 
1687  template <typename Number, typename MemorySpace>
1688  inline Number
1690  const size_type local_index) const
1691  {
1692  Assert((std::is_same<MemorySpace, ::MemorySpace::Host>::value),
1693  ExcMessage(
1694  "This function is only implemented for the Host memory space"));
1695  AssertIndexRange(local_index,
1696  partitioner->locally_owned_size() +
1697  partitioner->n_ghost_indices());
1698  // do not allow reading a vector which is not in ghost mode
1699  Assert(local_index < locally_owned_size() || vector_is_ghosted == true,
1700  ExcMessage("You tried to read a ghost element of this vector, "
1701  "but it has not imported its ghost values."));
1702 
1703  return data.values[local_index];
1704  }
1705 
1706 
1707 
1708  template <typename Number, typename MemorySpace>
1709  inline Number &
1711  {
1712  Assert((std::is_same<MemorySpace, ::MemorySpace::Host>::value),
1713  ExcMessage(
1714  "This function is only implemented for the Host memory space"));
1715 
1716  AssertIndexRange(local_index,
1717  partitioner->locally_owned_size() +
1718  partitioner->n_ghost_indices());
1719 
1720  return data.values[local_index];
1721  }
1722 
1723 
1724 
1725  template <typename Number, typename MemorySpace>
1726  inline Number *
1728  {
1729  return internal::Policy<Number, MemorySpace>::get_values(data);
1730  }
1731 
1732 
1733 
1734  template <typename Number, typename MemorySpace>
1735  template <typename OtherNumber>
1736  inline void
1738  const std::vector<size_type> &indices,
1739  std::vector<OtherNumber> & values) const
1740  {
1741  for (size_type i = 0; i < indices.size(); ++i)
1742  values[i] = operator()(indices[i]);
1743  }
1744 
1745 
1746 
1747  template <typename Number, typename MemorySpace>
1748  template <typename ForwardIterator, typename OutputIterator>
1749  inline void
1751  ForwardIterator indices_begin,
1752  const ForwardIterator indices_end,
1753  OutputIterator values_begin) const
1754  {
1755  while (indices_begin != indices_end)
1756  {
1757  *values_begin = operator()(*indices_begin);
1758  indices_begin++;
1759  values_begin++;
1760  }
1761  }
1762 
1763 
1764 
1765  template <typename Number, typename MemorySpace>
1766  template <typename OtherNumber>
1767  inline void
1769  const std::vector<size_type> & indices,
1770  const ::Vector<OtherNumber> &values)
1771  {
1772  AssertDimension(indices.size(), values.size());
1773  for (size_type i = 0; i < indices.size(); ++i)
1774  {
1775  Assert(
1776  numbers::is_finite(values[i]),
1777  ExcMessage(
1778  "The given value is not finite but either infinite or Not A Number (NaN)"));
1779  this->operator()(indices[i]) += values(i);
1780  }
1781  }
1782 
1783 
1784 
1785  template <typename Number, typename MemorySpace>
1786  template <typename OtherNumber>
1787  inline void
1789  const size_type * indices,
1790  const OtherNumber *values)
1791  {
1792  for (size_type i = 0; i < n_elements; ++i, ++indices, ++values)
1793  {
1794  Assert(
1795  numbers::is_finite(*values),
1796  ExcMessage(
1797  "The given value is not finite but either infinite or Not A Number (NaN)"));
1798  this->operator()(*indices) += *values;
1799  }
1800  }
1801 
1802 
1803 
1804  template <typename Number, typename MemorySpace>
1805  inline const MPI_Comm &
1807  {
1808  return partitioner->get_mpi_communicator();
1809  }
1810 
1811 
1812 
1813  template <typename Number, typename MemorySpace>
1814  inline const std::shared_ptr<const Utilities::MPI::Partitioner> &
1816  {
1817  return partitioner;
1818  }
1819 
1820 
1821 
1822  template <typename Number, typename MemorySpace>
1823  inline void
1824  Vector<Number, MemorySpace>::set_ghost_state(const bool ghosted) const
1825  {
1826  vector_is_ghosted = ghosted;
1827  }
1828 
1829 #endif
1830 
1831  } // namespace distributed
1832 } // namespace LinearAlgebra
1833 
1834 
1842 template <typename Number, typename MemorySpace>
1843 inline void
1846 {
1847  u.swap(v);
1848 }
1849 
1850 
1854 template <typename Number, typename MemorySpace>
1856  : std::false_type
1857 {};
1858 
1859 
1860 
1861 namespace internal
1862 {
1863  namespace LinearOperatorImplementation
1864  {
1865  template <typename>
1866  class ReinitHelper;
1867 
1872  template <typename Number>
1873  class ReinitHelper<LinearAlgebra::distributed::Vector<Number>>
1874  {
1875  public:
1876  // A helper type-trait that leverage SFINAE to figure out if type T has
1877  // void T::get_mpi_communicator()
1878  template <typename T>
1879  struct has_get_mpi_communicator
1880  {
1881  private:
1882  static bool
1883  detect(...);
1884 
1885  template <typename U>
1886  static decltype(std::declval<U>().get_mpi_communicator())
1887  detect(const U &);
1888 
1889  public:
1890  static const bool value =
1891  !std::is_same<bool, decltype(detect(std::declval<T>()))>::value;
1892  };
1893 
1894  // A helper type-trait that leverage SFINAE to figure out if type T has
1895  // void T::locally_owned_domain_indices()
1896  template <typename T>
1897  struct has_locally_owned_domain_indices
1898  {
1899  private:
1900  static bool
1901  detect(...);
1902 
1903  template <typename U>
1904  static decltype(std::declval<U>().locally_owned_domain_indices())
1905  detect(const U &);
1906 
1907  public:
1908  static const bool value =
1909  !std::is_same<bool, decltype(detect(std::declval<T>()))>::value;
1910  };
1911 
1912  // A helper type-trait that leverage SFINAE to figure out if type T has
1913  // void T::locally_owned_range_indices()
1914  template <typename T>
1915  struct has_locally_owned_range_indices
1916  {
1917  private:
1918  static bool
1919  detect(...);
1920 
1921  template <typename U>
1922  static decltype(std::declval<U>().locally_owned_range_indices())
1923  detect(const U &);
1924 
1925  public:
1926  static const bool value =
1927  !std::is_same<bool, decltype(detect(std::declval<T>()))>::value;
1928  };
1929 
1930  // A helper type-trait that leverage SFINAE to figure out if type T has
1931  // void T::initialize_dof_vector(VectorType v)
1932  template <typename T>
1933  struct has_initialize_dof_vector
1934  {
1935  private:
1936  static bool
1937  detect(...);
1938 
1939  template <typename U>
1940  static decltype(std::declval<U>().initialize_dof_vector(
1941  std::declval<LinearAlgebra::distributed::Vector<Number> &>()))
1942  detect(const U &);
1943 
1944  public:
1945  static const bool value =
1946  !std::is_same<bool, decltype(detect(std::declval<T>()))>::value;
1947  };
1948 
1949  // Used for (Trilinos/PETSc)Wrappers::SparseMatrix
1950  template <typename MatrixType,
1951  typename std::enable_if<
1952  has_get_mpi_communicator<MatrixType>::value &&
1953  has_locally_owned_domain_indices<MatrixType>::value,
1954  MatrixType>::type * = nullptr>
1955  static void
1956  reinit_domain_vector(MatrixType & mat,
1958  bool /*omit_zeroing_entries*/)
1959  {
1960  vec.reinit(mat.locally_owned_domain_indices(),
1961  mat.get_mpi_communicator());
1962  }
1963 
1964  // Used for MatrixFree and DiagonalMatrix
1965  template <
1966  typename MatrixType,
1967  typename std::enable_if<has_initialize_dof_vector<MatrixType>::value,
1968  MatrixType>::type * = nullptr>
1969  static void
1970  reinit_domain_vector(MatrixType & mat,
1972  bool omit_zeroing_entries)
1973  {
1974  mat.initialize_dof_vector(vec);
1975  if (!omit_zeroing_entries)
1976  vec = Number();
1977  }
1978 
1979  // Used for (Trilinos/PETSc)Wrappers::SparseMatrix
1980  template <typename MatrixType,
1981  typename std::enable_if<
1982  has_get_mpi_communicator<MatrixType>::value &&
1983  has_locally_owned_range_indices<MatrixType>::value,
1984  MatrixType>::type * = nullptr>
1985  static void
1986  reinit_range_vector(MatrixType & mat,
1988  bool /*omit_zeroing_entries*/)
1989  {
1990  vec.reinit(mat.locally_owned_range_indices(),
1991  mat.get_mpi_communicator());
1992  }
1993 
1994  // Used for MatrixFree and DiagonalMatrix
1995  template <
1996  typename MatrixType,
1997  typename std::enable_if<has_initialize_dof_vector<MatrixType>::value,
1998  MatrixType>::type * = nullptr>
1999  static void
2000  reinit_range_vector(MatrixType & mat,
2002  bool omit_zeroing_entries)
2003  {
2004  mat.initialize_dof_vector(vec);
2005  if (!omit_zeroing_entries)
2006  vec = Number();
2007  }
2008  };
2009 
2010  } // namespace LinearOperatorImplementation
2011 } /* namespace internal */
2012 
2013 
2015 
2016 #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:166
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:954
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:396
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:395
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)