Reference documentation for deal.II version 9.1.0-pre
la_parallel_vector.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 #ifndef dealii_la_parallel_vector_h
17 #define dealii_la_parallel_vector_h
18 
19 #include <deal.II/base/config.h>
20 
21 #include <deal.II/base/mpi.h>
22 #include <deal.II/base/numbers.h>
23 #include <deal.II/base/partitioner.h>
24 #include <deal.II/base/thread_management.h>
25 
26 #include <deal.II/lac/vector_operation.h>
27 #include <deal.II/lac/vector_space_vector.h>
28 #include <deal.II/lac/vector_type_traits.h>
29 
30 #include <iomanip>
31 #include <memory>
32 
33 DEAL_II_NAMESPACE_OPEN
34 
35 namespace LinearAlgebra
36 {
37  namespace distributed
38  {
39  template <typename>
40  class BlockVector;
41  }
42 } // namespace LinearAlgebra
43 
44 namespace LinearAlgebra
45 {
46  template <typename>
48 }
49 
50 #ifdef DEAL_II_WITH_PETSC
51 namespace PETScWrappers
52 {
53  namespace MPI
54  {
55  class Vector;
56  }
57 } // namespace PETScWrappers
58 #endif
59 
60 #ifdef DEAL_II_WITH_TRILINOS
61 namespace TrilinosWrappers
62 {
63  namespace MPI
64  {
65  class Vector;
66  }
67 } // namespace TrilinosWrappers
68 #endif
69 
70 namespace LinearAlgebra
71 {
72  namespace distributed
73  {
180  template <typename Number>
182  public Subscriptor
183  {
184  public:
185  using value_type = Number;
186  using pointer = value_type *;
187  using const_pointer = const value_type *;
188  using iterator = value_type *;
189  using const_iterator = const value_type *;
190  using reference = value_type &;
191  using const_reference = const value_type &;
192  using size_type = types::global_dof_index;
193  using real_type = typename numbers::NumberTraits<Number>::real_type;
194 
202  Vector();
203 
207  Vector(const Vector<Number> &in_vector);
208 
213  Vector(const size_type size);
214 
231  Vector(const IndexSet &local_range,
232  const IndexSet &ghost_indices,
233  const MPI_Comm communicator);
234 
238  Vector(const IndexSet &local_range, const MPI_Comm communicator);
239 
246  Vector(
247  const std::shared_ptr<const Utilities::MPI::Partitioner> &partitioner);
248 
252  virtual ~Vector() override;
253 
258  void
259  reinit(const size_type size, const bool omit_zeroing_entries = false);
260 
271  template <typename Number2>
272  void
273  reinit(const Vector<Number2> &in_vector,
274  const bool omit_zeroing_entries = false);
275 
292  void
293  reinit(const IndexSet &local_range,
294  const IndexSet &ghost_indices,
295  const MPI_Comm communicator);
296 
300  void
301  reinit(const IndexSet &local_range, const MPI_Comm communicator);
302 
309  void
310  reinit(
311  const std::shared_ptr<const Utilities::MPI::Partitioner> &partitioner);
312 
328  void
329  swap(Vector<Number> &v);
330 
343  operator=(const Vector<Number> &in_vector);
344 
356  template <typename Number2>
358  operator=(const Vector<Number2> &in_vector);
359 
360 #ifdef DEAL_II_WITH_PETSC
361 
371  DEAL_II_DEPRECATED
373  operator=(const PETScWrappers::MPI::Vector &petsc_vec);
374 #endif
375 
376 #ifdef DEAL_II_WITH_TRILINOS
377 
388  DEAL_II_DEPRECATED
390  operator=(const TrilinosWrappers::MPI::Vector &trilinos_vec);
391 #endif
392 
393 
433  virtual void
434  compress(::VectorOperation::values operation) override;
435 
457  void
458  update_ghost_values() const;
459 
474  void
475  compress_start(
476  const unsigned int communication_channel = 0,
478 
494  void
495  compress_finish(::VectorOperation::values operation);
496 
511  void
512  update_ghost_values_start(
513  const unsigned int communication_channel = 0) const;
514 
515 
523  void
524  update_ghost_values_finish() const;
525 
534  void
535  zero_out_ghosts() const;
536 
548  bool
549  has_ghost_elements() const;
550 
565  template <typename Number2>
566  void
567  copy_locally_owned_data_from(const Vector<Number2> &src);
568 
570 
575 
580  virtual void
581  reinit(const VectorSpaceVector<Number> &V,
582  const bool omit_zeroing_entries = false) override;
583 
587  virtual Vector<Number> &
588  operator*=(const Number factor) override;
589 
593  virtual Vector<Number> &
594  operator/=(const Number factor) override;
595 
599  virtual Vector<Number> &
600  operator+=(const VectorSpaceVector<Number> &V) override;
601 
605  virtual Vector<Number> &
606  operator-=(const VectorSpaceVector<Number> &V) override;
607 
616  virtual void
617  import(
619  VectorOperation::values operation,
620  std::shared_ptr<const CommunicationPatternBase> communication_pattern =
621  std::shared_ptr<const CommunicationPatternBase>()) override;
622 
626  virtual Number
627  operator*(const VectorSpaceVector<Number> &V) const override;
628 
632  virtual void
633  add(const Number a) override;
634 
638  virtual void
639  add(const Number a, const VectorSpaceVector<Number> &V) override;
640 
644  virtual void
645  add(const Number a,
646  const VectorSpaceVector<Number> &V,
647  const Number b,
648  const VectorSpaceVector<Number> &W) override;
649 
654  virtual void
655  add(const std::vector<size_type> &indices,
656  const std::vector<Number> & values);
657 
662  virtual void
663  sadd(const Number s,
664  const Number a,
665  const VectorSpaceVector<Number> &V) override;
666 
672  virtual void
673  scale(const VectorSpaceVector<Number> &scaling_factors) override;
674 
678  virtual void
679  equ(const Number a, const VectorSpaceVector<Number> &V) override;
680 
685  virtual real_type
686  l1_norm() const override;
687 
692  virtual real_type
693  l2_norm() const override;
694 
698  real_type
699  norm_sqr() const;
700 
705  virtual real_type
706  linfty_norm() const override;
707 
728  virtual Number
729  add_and_dot(const Number a,
730  const VectorSpaceVector<Number> &V,
731  const VectorSpaceVector<Number> &W) override;
732 
737  virtual size_type
738  size() const override;
739 
751  virtual ::IndexSet
752  locally_owned_elements() const override;
753 
757  virtual void
758  print(std::ostream & out,
759  const unsigned int precision = 3,
760  const bool scientific = true,
761  const bool across = true) const override;
762 
766  virtual std::size_t
767  memory_consumption() const override;
769 
774 
780  virtual Vector<Number> &
781  operator=(const Number s) override;
782 
787  template <typename OtherNumber>
788  void
789  add(const std::vector<size_type> & indices,
790  const ::Vector<OtherNumber> &values);
791 
796  template <typename OtherNumber>
797  void
798  add(const size_type n_elements,
799  const size_type * indices,
800  const OtherNumber *values);
801 
806  void
807  sadd(const Number s, const Vector<Number> &V);
808 
814  DEAL_II_DEPRECATED
815  void
816  sadd(const Number s,
817  const Number a,
818  const Vector<Number> &V,
819  const Number b,
820  const Vector<Number> &W);
821 
827  DEAL_II_DEPRECATED
828  void
829  equ(const Number a,
830  const Vector<Number> &u,
831  const Number b,
832  const Vector<Number> &v);
833 
835 
836 
841 
846  size_type
847  local_size() const;
848 
856  DEAL_II_DEPRECATED
857  std::pair<size_type, size_type>
858  local_range() const;
859 
866  DEAL_II_DEPRECATED
867  bool
868  in_local_range(const size_type global_index) const;
869 
875  DEAL_II_DEPRECATED
876  size_type
877  n_ghost_entries() const;
878 
886  DEAL_II_DEPRECATED
887  const IndexSet &
888  ghost_elements() const;
889 
897  DEAL_II_DEPRECATED
898  bool
899  is_ghost_entry(const types::global_dof_index global_index) const;
900 
908  iterator
909  begin();
910 
915  const_iterator
916  begin() const;
917 
922  iterator
923  end();
924 
929  const_iterator
930  end() const;
931 
941  Number
942  operator()(const size_type global_index) const;
943 
953  Number &
954  operator()(const size_type global_index);
955 
963  Number operator[](const size_type global_index) const;
971  Number &operator[](const size_type global_index);
972 
981  Number
982  local_element(const size_type local_index) const;
983 
992  Number &
993  local_element(const size_type local_index);
994 
1010  template <typename OtherNumber>
1011  void
1012  extract_subvector_to(const std::vector<size_type> &indices,
1013  std::vector<OtherNumber> & values) const;
1014 
1042  template <typename ForwardIterator, typename OutputIterator>
1043  void
1044  extract_subvector_to(ForwardIterator indices_begin,
1045  const ForwardIterator indices_end,
1046  OutputIterator values_begin) const;
1052  virtual bool
1053  all_zero() const override;
1054 
1058  virtual Number
1059  mean_value() const override;
1060 
1065  real_type
1066  lp_norm(const real_type p) const;
1068 
1073 
1078  const MPI_Comm &
1079  get_mpi_communicator() const;
1080 
1087  const std::shared_ptr<const Utilities::MPI::Partitioner> &
1088  get_partitioner() const;
1089 
1099  bool
1100  partitioners_are_compatible(
1101  const Utilities::MPI::Partitioner &part) const;
1102 
1116  bool
1117  partitioners_are_globally_compatible(
1118  const Utilities::MPI::Partitioner &part) const;
1120 
1126  DeclException0(ExcVectorTypeNotCompatible);
1127 
1131  DeclException3(ExcNonMatchingElements,
1132  Number,
1133  Number,
1134  unsigned int,
1135  << "Called compress(VectorOperation::insert), but"
1136  << " the element received from a remote processor, value "
1137  << std::setprecision(16) << arg1
1138  << ", does not match with the value "
1139  << std::setprecision(16) << arg2
1140  << " on the owner processor " << arg3);
1141 
1145  DeclException4(ExcAccessToNonLocalElement,
1146  size_type,
1147  size_type,
1148  size_type,
1149  size_type,
1150  << "You tried to access element " << arg1
1151  << " of a distributed vector, but this element is not "
1152  << "stored on the current processor. Note: The range of "
1153  << "locally owned elements is " << arg2 << " to " << arg3
1154  << ", and there are " << arg4 << " ghost elements "
1155  << "that this vector can access.");
1156 
1157  private:
1162  void
1163  add_local(const Number a, const VectorSpaceVector<Number> &V);
1164 
1169  void
1170  sadd_local(const Number s,
1171  const Number a,
1172  const VectorSpaceVector<Number> &V);
1173 
1177  bool
1178  all_zero_local() const;
1179 
1183  template <typename Number2>
1184  Number
1185  inner_product_local(const Vector<Number2> &V) const;
1186 
1190  real_type
1191  norm_sqr_local() const;
1192 
1196  Number
1197  mean_value_local() const;
1198 
1202  real_type
1203  l1_norm_local() const;
1204 
1208  real_type
1209  lp_norm_local(const real_type p) const;
1210 
1214  real_type
1215  linfty_norm_local() const;
1216 
1222  Number
1223  add_and_dot_local(const Number a,
1224  const Vector<Number> &V,
1225  const Vector<Number> &W);
1226 
1232  std::shared_ptr<const Utilities::MPI::Partitioner> partitioner;
1233 
1237  size_type allocated_size;
1238 
1246  std::unique_ptr<Number[], decltype(&free)> values;
1247 
1252  mutable std::shared_ptr<::parallel::internal::TBBPartitioner>
1254 
1260  mutable std::unique_ptr<Number[]> import_data;
1261 
1269  mutable bool vector_is_ghosted;
1270 
1271 #ifdef DEAL_II_WITH_MPI
1272 
1280  std::vector<MPI_Request> compress_requests;
1281 
1286  mutable std::vector<MPI_Request> update_ghost_values_requests;
1287 #endif
1288 
1295 
1300  void
1301  clear_mpi_requests();
1302 
1306  void
1307  resize_val(const size_type new_allocated_size);
1308 
1309  /*
1310  * Make all other vector types friends.
1311  */
1312  template <typename Number2>
1313  friend class Vector;
1314 
1318  template <typename Number2>
1319  friend class BlockVector;
1320  };
1324  /*-------------------- Inline functions ---------------------------------*/
1325 
1326 #ifndef DOXYGEN
1327 
1328 
1329  template <typename Number>
1330  inline bool
1332  {
1333  return vector_is_ghosted;
1334  }
1335 
1336 
1337 
1338  template <typename Number>
1339  inline typename Vector<Number>::size_type
1340  Vector<Number>::size() const
1341  {
1342  return partitioner->size();
1343  }
1344 
1345 
1346 
1347  template <typename Number>
1348  inline typename Vector<Number>::size_type
1350  {
1351  return partitioner->local_size();
1352  }
1353 
1354 
1355 
1356  template <typename Number>
1357  inline std::pair<typename Vector<Number>::size_type,
1358  typename Vector<Number>::size_type>
1360  {
1361  return partitioner->local_range();
1362  }
1363 
1364 
1365 
1366  template <typename Number>
1367  inline bool
1368  Vector<Number>::in_local_range(const size_type global_index) const
1369  {
1370  return partitioner->in_local_range(global_index);
1371  }
1372 
1373 
1374 
1375  template <typename Number>
1376  inline IndexSet
1378  {
1379  IndexSet is(size());
1380 
1381  is.add_range(partitioner->local_range().first,
1382  partitioner->local_range().second);
1383 
1384  return is;
1385  }
1386 
1387 
1388 
1389  template <typename Number>
1390  inline typename Vector<Number>::size_type
1392  {
1393  return partitioner->n_ghost_indices();
1394  }
1395 
1396 
1397 
1398  template <typename Number>
1399  inline const IndexSet &
1401  {
1402  return partitioner->ghost_indices();
1403  }
1404 
1405 
1406 
1407  template <typename Number>
1408  inline bool
1409  Vector<Number>::is_ghost_entry(const size_type global_index) const
1410  {
1411  return partitioner->is_ghost_entry(global_index);
1412  }
1413 
1414 
1415 
1416  template <typename Number>
1417  inline typename Vector<Number>::iterator
1419  {
1420  return values.get();
1421  }
1422 
1423 
1424 
1425  template <typename Number>
1426  inline typename Vector<Number>::const_iterator
1427  Vector<Number>::begin() const
1428  {
1429  return values.get();
1430  }
1431 
1432 
1433 
1434  template <typename Number>
1435  inline typename Vector<Number>::iterator
1437  {
1438  return values.get() + partitioner->local_size();
1439  }
1440 
1441 
1442 
1443  template <typename Number>
1444  inline typename Vector<Number>::const_iterator
1445  Vector<Number>::end() const
1446  {
1447  return values.get() + partitioner->local_size();
1448  }
1449 
1450 
1451 
1452  template <typename Number>
1453  inline Number
1454  Vector<Number>::operator()(const size_type global_index) const
1455  {
1456  Assert(
1457  partitioner->in_local_range(global_index) ||
1458  partitioner->ghost_indices().is_element(global_index),
1459  ExcAccessToNonLocalElement(global_index,
1460  partitioner->local_range().first,
1461  partitioner->local_range().second,
1462  partitioner->ghost_indices().n_elements()));
1463  // do not allow reading a vector which is not in ghost mode
1464  Assert(partitioner->in_local_range(global_index) ||
1465  vector_is_ghosted == true,
1466  ExcMessage("You tried to read a ghost element of this vector, "
1467  "but it has not imported its ghost values."));
1468  return values[partitioner->global_to_local(global_index)];
1469  }
1470 
1471 
1472 
1473  template <typename Number>
1474  inline Number &
1475  Vector<Number>::operator()(const size_type global_index)
1476  {
1477  Assert(
1478  partitioner->in_local_range(global_index) ||
1479  partitioner->ghost_indices().is_element(global_index),
1480  ExcAccessToNonLocalElement(global_index,
1481  partitioner->local_range().first,
1482  partitioner->local_range().second,
1483  partitioner->ghost_indices().n_elements()));
1484  // we would like to prevent reading ghosts from a vector that does not
1485  // have them imported, but this is not possible because we might be in a
1486  // part of the code where the vector has enabled ghosts but is non-const
1487  // (then, the compiler picks this method according to the C++ rule book
1488  // even if a human would pick the const method when this subsequent use
1489  // is just a read)
1490  return values[partitioner->global_to_local(global_index)];
1491  }
1492 
1493 
1494 
1495  template <typename Number>
1496  inline Number Vector<Number>::operator[](const size_type global_index) const
1497  {
1498  return operator()(global_index);
1499  }
1500 
1501 
1502 
1503  template <typename Number>
1504  inline Number &Vector<Number>::operator[](const size_type global_index)
1505  {
1506  return operator()(global_index);
1507  }
1508 
1509 
1510 
1511  template <typename Number>
1512  inline Number
1513  Vector<Number>::local_element(const size_type local_index) const
1514  {
1515  AssertIndexRange(local_index,
1516  partitioner->local_size() +
1517  partitioner->n_ghost_indices());
1518  // do not allow reading a vector which is not in ghost mode
1519  Assert(local_index < local_size() || vector_is_ghosted == true,
1520  ExcMessage("You tried to read a ghost element of this vector, "
1521  "but it has not imported its ghost values."));
1522  return values[local_index];
1523  }
1524 
1525 
1526 
1527  template <typename Number>
1528  inline Number &
1529  Vector<Number>::local_element(const size_type local_index)
1530  {
1531  AssertIndexRange(local_index,
1532  partitioner->local_size() +
1533  partitioner->n_ghost_indices());
1534  return values[local_index];
1535  }
1536 
1537 
1538 
1539  template <typename Number>
1540  template <typename OtherNumber>
1541  inline void
1542  Vector<Number>::extract_subvector_to(const std::vector<size_type> &indices,
1543  std::vector<OtherNumber> &values) const
1544  {
1545  for (size_type i = 0; i < indices.size(); ++i)
1546  values[i] = operator()(indices[i]);
1547  }
1548 
1549 
1550 
1551  template <typename Number>
1552  template <typename ForwardIterator, typename OutputIterator>
1553  inline void
1554  Vector<Number>::extract_subvector_to(ForwardIterator indices_begin,
1555  const ForwardIterator indices_end,
1556  OutputIterator values_begin) const
1557  {
1558  while (indices_begin != indices_end)
1559  {
1560  *values_begin = operator()(*indices_begin);
1561  indices_begin++;
1562  values_begin++;
1563  }
1564  }
1565 
1566 
1567 
1568  template <typename Number>
1569  template <typename OtherNumber>
1570  inline void
1571  Vector<Number>::add(const std::vector<size_type> & indices,
1572  const ::Vector<OtherNumber> &values)
1573  {
1574  AssertDimension(indices.size(), values.size());
1575  for (size_type i = 0; i < indices.size(); ++i)
1576  {
1577  Assert(
1578  numbers::is_finite(values[i]),
1579  ExcMessage(
1580  "The given value is not finite but either infinite or Not A Number (NaN)"));
1581  this->operator()(indices[i]) += values(i);
1582  }
1583  }
1584 
1585 
1586 
1587  template <typename Number>
1588  template <typename OtherNumber>
1589  inline void
1590  Vector<Number>::add(const size_type n_elements,
1591  const size_type * indices,
1592  const OtherNumber *values)
1593  {
1594  for (size_type i = 0; i < n_elements; ++i, ++indices, ++values)
1595  {
1596  Assert(
1597  numbers::is_finite(*values),
1598  ExcMessage(
1599  "The given value is not finite but either infinite or Not A Number (NaN)"));
1600  this->operator()(*indices) += *values;
1601  }
1602  }
1603 
1604 
1605 
1606  template <typename Number>
1607  inline const MPI_Comm &
1609  {
1610  return partitioner->get_mpi_communicator();
1611  }
1612 
1613 
1614 
1615  template <typename Number>
1616  inline const std::shared_ptr<const Utilities::MPI::Partitioner> &
1618  {
1619  return partitioner;
1620  }
1621 
1622 #endif
1623 
1624  } // namespace distributed
1625 } // namespace LinearAlgebra
1626 
1627 
1636 template <typename Number>
1637 inline void
1640 {
1641  u.swap(v);
1642 }
1643 
1644 
1650 template <typename Number>
1651 struct is_serial_vector<LinearAlgebra::distributed::Vector<Number>>
1652  : std::false_type
1653 {};
1654 
1655 
1656 namespace internal
1657 {
1658  namespace LinearOperatorImplementation
1659  {
1660  template <typename>
1661  class ReinitHelper;
1662 
1667  template <typename Number>
1668  class ReinitHelper<LinearAlgebra::distributed::Vector<Number>>
1669  {
1670  public:
1671  template <typename Matrix>
1672  static void
1673  reinit_range_vector(const Matrix & matrix,
1675  bool omit_zeroing_entries)
1676  {
1677  matrix.initialize_dof_vector(v);
1678  if (!omit_zeroing_entries)
1679  v = Number();
1680  }
1681 
1682  template <typename Matrix>
1683  static void
1684  reinit_domain_vector(const Matrix & matrix,
1686  bool omit_zeroing_entries)
1687  {
1688  matrix.initialize_dof_vector(v);
1689  if (!omit_zeroing_entries)
1690  v = Number();
1691  }
1692  };
1693 
1694  } // namespace LinearOperatorImplementation
1695 } /* namespace internal */
1696 
1697 
1698 DEAL_II_NAMESPACE_CLOSE
1699 
1700 #endif
const std::shared_ptr< const Utilities::MPI::Partitioner > & get_partitioner() const
#define AssertDimension(dim1, dim2)
Definition: exceptions.h:1366
Number local_element(const size_type local_index) const
std::vector< MPI_Request > compress_requests
void swap(LinearAlgebra::distributed::Vector< Number > &u, LinearAlgebra::distributed::Vector< Number > &v)
std::unique_ptr< Number[]> import_data
#define AssertIndexRange(index, range)
Definition: exceptions.h:1407
SymmetricTensor< rank_, dim, Number > operator*(const SymmetricTensor< rank_, dim, Number > &t, const Number &factor)
unsigned long long int global_dof_index
Definition: types.h:72
bool is_finite(const double x)
Definition: numbers.h:428
std::vector< MPI_Request > update_ghost_values_requests
void extract_subvector_to(const std::vector< size_type > &indices, std::vector< OtherNumber > &values) const
value_type operator()(const size_type i) const
void swap(Vector< Number > &v)
static::ExceptionBase & ExcMessage(std::string arg1)
Number operator()(const size_type global_index) const
size_type n_ghost_entries() const
virtual size_type size() const override
std::shared_ptr<::parallel::internal::TBBPartitioner > thread_loop_partitioner
#define Assert(cond, exc)
Definition: exceptions.h:1227
std::unique_ptr< Number[], decltype(&free)> values
virtual void add(const Number a) override
#define DeclException0(Exception0)
Definition: exceptions.h:385
virtual ::IndexSet locally_owned_elements() const override
bool is_ghost_entry(const types::global_dof_index global_index) const
const MPI_Comm & get_mpi_communicator() const
std::pair< size_type, size_type > local_range() const
void swap(Vector< Number > &u, Vector< Number > &v)
Definition: vector.h:1353
const IndexSet & ghost_elements() const
std::shared_ptr< const Utilities::MPI::Partitioner > partitioner
Number operator[](const size_type global_index) const
#define DeclException4(Exception4, type1, type2, type3, type4, outsequence)
Definition: exceptions.h:444
#define DeclException3(Exception3, type1, type2, type3, outsequence)
Definition: exceptions.h:432
bool in_local_range(const size_type global_index) const