Tpetra parallel linear algebra  Version of the Day
Tpetra_MultiVector_decl.hpp
Go to the documentation of this file.
1 // @HEADER
2 // ***********************************************************************
3 //
4 // Tpetra: Templated Linear Algebra Services Package
5 // Copyright (2008) Sandia Corporation
6 //
7 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
8 // the U.S. Government retains certain rights in this software.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
38 //
39 // ************************************************************************
40 // @HEADER
41 
42 #ifndef TPETRA_MULTIVECTOR_DECL_HPP
43 #define TPETRA_MULTIVECTOR_DECL_HPP
44 
53 
54 #include "Tpetra_ConfigDefs.hpp"
55 #include "Tpetra_DistObject.hpp"
56 #include "Tpetra_Map_decl.hpp"
57 
58 #include "Kokkos_DualView.hpp"
59 #include "Kokkos_MultiVector.hpp"
60 
61 #include "Teuchos_BLAS_types.hpp"
62 #include "Teuchos_DataAccess.hpp"
63 #include "Teuchos_Range1D.hpp"
64 
65 #include "KokkosCompat_ClassicNodeAPI_Wrapper.hpp"
66 #include "Kokkos_InnerProductSpaceTraits.hpp"
67 #include "Kokkos_ArithTraits.hpp"
68 
69 #include "Tpetra_KokkosRefactor_DistObject.hpp"
70 #include "Tpetra_KokkosRefactor_Details_MultiVectorLocalDeepCopy.hpp"
71 #include <type_traits>
72 
73 namespace Tpetra {
74 
75 #ifndef DOXYGEN_SHOULD_SKIP_THIS
76  // forward declaration of Map
77  template<class LO, class GO, class N> class Map;
78 
79  // forward declaration of Vector, needed to prevent circular inclusions
80  template<class S, class LO, class GO, class N, const bool classic> class Vector;
81 
82  // forward declaration of MultiVector (declared later in this file)
83  template<class S, class LO, class GO, class N, const bool classic> class MultiVector;
84 #endif // DOXYGEN_SHOULD_SKIP_THIS
85 
86  namespace Details {
112  template<class DstMultiVectorType, class SrcMultiVectorType>
114  typedef DstMultiVectorType dst_mv_type;
115  typedef SrcMultiVectorType src_mv_type;
116 
117  static Teuchos::RCP<dst_mv_type>
118  clone (const src_mv_type& X,
119  const Teuchos::RCP<typename dst_mv_type::node_type>& node2);
120  };
121 
122  } // namespace Details
123 
144  template <class DS, class DL, class DG, class DN, const bool dstClassic,
145  class SS, class SL, class SG, class SN, const bool srcClassic>
146  void
149 
157  template <class ST, class LO, class GO, class NT, const bool classic = NT::classic>
160 
170  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node, const bool classic = Node::classic>
171  Teuchos::RCP<MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node, classic> >
172  createMultiVector (const Teuchos::RCP<const Map<LocalOrdinal, GlobalOrdinal, Node> >& map,
173  const size_t numVectors);
174 
395  template <class Scalar = Details::DefaultTypes::scalar_type,
396  class LocalOrdinal = Details::DefaultTypes::local_ordinal_type,
397  class GlobalOrdinal = Details::DefaultTypes::global_ordinal_type,
399  const bool classic = Node::classic>
400  class MultiVector :
401  public DistObject<Scalar, LocalOrdinal, GlobalOrdinal, Node>
402  {
403  static_assert (! classic, "The 'classic' version of Tpetra was deprecated long ago, and has been removed.");
404 
405  public:
407 
408 
411  typedef Scalar scalar_type;
427  typedef typename Kokkos::Details::ArithTraits<Scalar>::val_type impl_scalar_type;
429  typedef LocalOrdinal local_ordinal_type;
431  typedef GlobalOrdinal global_ordinal_type;
433  typedef Node node_type;
434 
436  typedef typename Node::device_type device_type;
437 
438  private:
441 
442  public:
448  typedef typename Kokkos::Details::InnerProductSpaceTraits<impl_scalar_type>::dot_type dot_type;
449 
456  typedef typename Kokkos::Details::ArithTraits<impl_scalar_type>::mag_type mag_type;
457 
464  typedef typename Node::execution_space execution_space;
465 
488  typedef Kokkos::DualView<impl_scalar_type**, Kokkos::LayoutLeft,
489  typename execution_space::execution_space> dual_view_type;
490 
493 
495 
497 
499  MultiVector ();
500 
507  MultiVector (const Teuchos::RCP<const map_type>& map,
508  const size_t numVecs,
509  const bool zeroOut = true);
510 
513 
523  const Teuchos::DataAccess copyOrView);
524 
540  MultiVector (const Teuchos::RCP<const map_type>& map,
541  const Teuchos::ArrayView<const Scalar>& A,
542  const size_t LDA,
543  const size_t NumVectors);
544 
558  MultiVector (const Teuchos::RCP<const map_type>& map,
559  const Teuchos::ArrayView<const Teuchos::ArrayView<const Scalar> >&ArrayOfPtrs,
560  const size_t NumVectors);
561 
574  MultiVector (const Teuchos::RCP<const map_type>& map,
575  const dual_view_type& view);
576 
615  MultiVector (const Teuchos::RCP<const map_type>& map,
616  const typename dual_view_type::t_dev& d_view);
617 
640  MultiVector (const Teuchos::RCP<const map_type>& map,
641  const dual_view_type& view,
642  const dual_view_type& origView);
643 
661  MultiVector (const Teuchos::RCP<const map_type>& map,
662  const dual_view_type& view,
663  const Teuchos::ArrayView<const size_t>& whichVectors);
664 
692  MultiVector (const Teuchos::RCP<const map_type>& map,
693  const dual_view_type& view,
694  const dual_view_type& origView,
695  const Teuchos::ArrayView<const size_t>& whichVectors);
696 
756  const map_type& subMap,
757  const size_t offset = 0);
758 
767  template <class Node2>
768  Teuchos::RCP<MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node2> >
769  clone (const Teuchos::RCP<Node2>& node2) const;
770 
772  virtual ~MultiVector ();
773 
775 
777 
778  protected:
783  static const bool useAtomicUpdatesByDefault =
784 #ifdef KOKKOS_HAVE_SERIAL
785  ! std::is_same<execution_space, Kokkos::Serial>::value;
786 #else
787  true;
788 #endif // KOKKOS_HAVE_SERIAL
789 
790  public:
807  void
808  replaceGlobalValue (GlobalOrdinal globalRow,
809  size_t col,
810  const impl_scalar_type& value) const;
811 
829  template<typename T>
830  typename std::enable_if<! std::is_same<T, impl_scalar_type>::value && std::is_convertible<T, impl_scalar_type>::value, void>::type
831  replaceGlobalValue (GlobalOrdinal globalRow,
832  size_t col,
833  const T& value) const
834  {
835  replaceGlobalValue (globalRow, col, static_cast<impl_scalar_type> (value));
836  }
837 
860  void
861  sumIntoGlobalValue (const GlobalOrdinal globalRow,
862  const size_t col,
863  const impl_scalar_type& value,
864  const bool atomic = useAtomicUpdatesByDefault) const;
865 
892  template<typename T>
893  typename std::enable_if<! std::is_same<T, impl_scalar_type>::value && std::is_convertible<T, impl_scalar_type>::value, void>::type
894  sumIntoGlobalValue (const GlobalOrdinal globalRow,
895  const size_t col,
896  const T& value,
897  const bool atomic = useAtomicUpdatesByDefault) const
898  {
899  sumIntoGlobalValue (globalRow, col, static_cast<impl_scalar_type> (value), atomic);
900  }
901 
918  void
919  replaceLocalValue (LocalOrdinal localRow,
920  size_t col,
921  const impl_scalar_type& value) const;
922 
940  template<typename T>
941  typename std::enable_if<! std::is_same<T, impl_scalar_type>::value && std::is_convertible<T, impl_scalar_type>::value, void>::type
942  replaceLocalValue (LocalOrdinal localRow,
943  size_t col,
944  const T& value) const
945  {
946  replaceLocalValue (localRow, col, static_cast<impl_scalar_type> (value));
947  }
948 
969  void
970  sumIntoLocalValue (const LocalOrdinal localRow,
971  const size_t col,
972  const impl_scalar_type& value,
973  const bool atomic = useAtomicUpdatesByDefault) const;
974 
999  template<typename T>
1000  typename std::enable_if<! std::is_same<T, impl_scalar_type>::value && std::is_convertible<T, impl_scalar_type>::value, void>::type
1001  sumIntoLocalValue (LocalOrdinal localRow,
1002  size_t col,
1003  const T& value,
1004  const bool atomic = useAtomicUpdatesByDefault) const
1005  {
1006  sumIntoLocalValue (localRow, col, static_cast<impl_scalar_type> (value), atomic);
1007  }
1008 
1010  void putScalar (const Scalar& value);
1011 
1018  template<typename T>
1019  typename std::enable_if<! std::is_same<T, impl_scalar_type>::value && std::is_convertible<T, impl_scalar_type>::value, void>::type
1020  putScalar (const T& value)
1021  {
1022  putScalar (static_cast<impl_scalar_type> (value));
1023  }
1024 
1040  void randomize();
1041 
1107  void replaceMap (const Teuchos::RCP<const map_type>& map);
1108 
1115  void reduce();
1116 
1133 
1135 
1137 
1145 
1147  Teuchos::RCP<MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node, classic> >
1148  subCopy (const Teuchos::Range1D& colRng) const;
1149 
1151  Teuchos::RCP<MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node, classic> >
1152  subCopy (const Teuchos::ArrayView<const size_t>& cols) const;
1153 
1155  Teuchos::RCP<const MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node, classic> >
1156  subView (const Teuchos::Range1D& colRng) const;
1157 
1159  Teuchos::RCP<const MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node, classic> >
1160  subView (const Teuchos::ArrayView<const size_t>& cols) const;
1161 
1163  Teuchos::RCP<MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node, classic> >
1164  subViewNonConst (const Teuchos::Range1D& colRng);
1165 
1167  Teuchos::RCP<MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node, classic> >
1168  subViewNonConst (const Teuchos::ArrayView<const size_t>& cols);
1169 
1232  Teuchos::RCP<const MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node, classic> >
1233  offsetView (const Teuchos::RCP<const map_type>& subMap,
1234  const size_t offset) const;
1235 
1253  Teuchos::RCP<MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node, classic> >
1254  offsetViewNonConst (const Teuchos::RCP<const map_type>& subMap,
1255  const size_t offset);
1256 
1258  Teuchos::RCP<const Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node, classic> >
1259  getVector (const size_t j) const;
1260 
1262  Teuchos::RCP<Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node, classic> >
1263  getVectorNonConst (const size_t j);
1264 
1266  Teuchos::ArrayRCP<const Scalar> getData (size_t j) const;
1267 
1269  Teuchos::ArrayRCP<Scalar> getDataNonConst (size_t j);
1270 
1278  void
1279  get1dCopy (const Teuchos::ArrayView<Scalar>& A,
1280  const size_t LDA) const;
1281 
1288  void
1289  get2dCopy (const Teuchos::ArrayView<const Teuchos::ArrayView<Scalar> >& ArrayOfPtrs) const;
1290 
1296  Teuchos::ArrayRCP<const Scalar> get1dView () const;
1297 
1299  Teuchos::ArrayRCP<Teuchos::ArrayRCP<const Scalar> > get2dView () const;
1300 
1306  Teuchos::ArrayRCP<Scalar> get1dViewNonConst ();
1307 
1309  Teuchos::ArrayRCP<Teuchos::ArrayRCP<Scalar> > get2dViewNonConst ();
1310 
1319  KokkosClassic::MultiVector<Scalar, Node> getLocalMV () const;
1320 
1332  dual_view_type getDualView () const;
1333 
1352  template<class TargetDeviceType>
1353  void sync () {
1354  getDualView ().template sync<TargetDeviceType> ();
1355  }
1356 
1362  template<class TargetDeviceType>
1363  void modify () {
1364  getDualView ().template modify<TargetDeviceType> ();
1365  }
1366 
1398  template<class TargetDeviceType>
1399  typename Kokkos::Impl::if_c<
1400  std::is_same<
1401  typename device_type::memory_space,
1402  typename TargetDeviceType::memory_space>::value,
1403  typename dual_view_type::t_dev,
1404  typename dual_view_type::t_host>::type
1405  getLocalView () const {
1406  return getDualView ().template view<TargetDeviceType> ();
1407  }
1408 
1410 
1412 
1426  void
1428  const Teuchos::ArrayView<dot_type>& dots) const;
1429 
1441  template <typename T>
1442  typename std::enable_if< ! (std::is_same<dot_type, T>::value), void >::type
1444  const Teuchos::ArrayView<T> &dots) const
1445  {
1446  const size_t sz = static_cast<size_t> (dots.size ());
1447  Teuchos::Array<dot_type> dts (sz);
1448  this->dot (A, dts);
1449  for (size_t i = 0; i < sz; ++i) {
1450  // If T and dot_type differ, this does an implicit conversion.
1451  dots[i] = dts[i];
1452  }
1453  }
1454 
1456  template <typename T>
1457  typename std::enable_if< ! (std::is_same<dot_type, T>::value), void >::type
1459  std::vector<T>& dots) const
1460  {
1461  const size_t sz = dots.size ();
1462  Teuchos::Array<dot_type> dts (sz);
1463  this->dot (A, dts);
1464  for (size_t i = 0; i < sz; ++i) {
1465  // If T and dot_type differ, this does an implicit conversion.
1466  dots[i] = dts[i];
1467  }
1468  }
1469 
1487  void
1489  const Kokkos::View<dot_type*, device_type>& dots) const;
1490 
1503  template <typename T>
1504  typename std::enable_if< ! (std::is_same<dot_type, T>::value), void >::type
1506  const Kokkos::View<T*, device_type>& dots) const
1507  {
1508  const size_t numDots = dots.dimension_0 ();
1509  Kokkos::View<dot_type*, device_type> dts ("MV::dot tmp", numDots);
1510  // Call overload that takes a Kokkos::View<dot_type*, device_type>.
1511  this->dot (A, dts);
1512  // FIXME (mfh 14 Jul 2014) Does this actually work if dot_type
1513  // and T differ? We would need a test for this, but only the
1514  // Sacado and Stokhos packages are likely to care about this use
1515  // case. It could also come up for Kokkos::complex ->
1516  // std::complex conversions, but those two implementations
1517  // should generally be bitwise compatible.
1518  Kokkos::deep_copy (dots, dts);
1519  }
1520 
1523 
1526 
1534  void scale (const Scalar& alpha);
1535 
1544  void scale (const Teuchos::ArrayView<const Scalar>& alpha);
1545 
1554  void scale (const Kokkos::View<const impl_scalar_type*, device_type>& alpha);
1555 
1564  void
1565  scale (const Scalar& alpha,
1567 
1574  void
1575  update (const Scalar& alpha,
1577  const Scalar& beta);
1578 
1585  void
1586  update (const Scalar& alpha,
1588  const Scalar& beta,
1590  const Scalar& gamma);
1591 
1603  void norm1 (const Kokkos::View<mag_type*, device_type>& norms) const;
1604 
1618  template <typename T>
1619  typename std::enable_if< ! (std::is_same<mag_type, T>::value), void >::type
1620  norm1 (const Kokkos::View<T*, device_type>& norms) const
1621  {
1622  const size_t numNorms = norms.dimension_0 ();
1623  Kokkos::View<mag_type*, device_type> tmpNorms ("MV::norm1 tmp", numNorms);
1624  // Call overload that takes a Kokkos::View<mag_type*, device_type>.
1625  this->norm1 (tmpNorms);
1626  // FIXME (mfh 15 Jul 2014) Does this actually work if mag_type
1627  // and T differ? We would need a test for this, but only the
1628  // Sacado and Stokhos packages are likely to care about this use
1629  // case. It could also come up with Kokkos::complex ->
1630  // std::complex conversion.
1631  Kokkos::deep_copy (norms, tmpNorms);
1632  }
1633 
1634 
1640  void norm1 (const Teuchos::ArrayView<mag_type>& norms) const;
1641 
1654  template <typename T>
1655  typename std::enable_if< ! (std::is_same<mag_type,T>::value), void >::type
1656  norm1 (const Teuchos::ArrayView<T>& norms) const
1657  {
1658  typedef typename Teuchos::ArrayView<T>::size_type size_type;
1659  const size_type sz = norms.size ();
1660  Teuchos::Array<mag_type> theNorms (sz);
1661  this->norm1 (theNorms);
1662  for (size_type i = 0; i < sz; ++i) {
1663  // If T and mag_type differ, this does an implicit conversion.
1664  norms[i] = theNorms[i];
1665  }
1666  }
1667 
1680  void norm2 (const Kokkos::View<mag_type*, device_type>& norms) const;
1681 
1693  template<typename T>
1694  typename std::enable_if< ! (std::is_same<mag_type, T>::value), void >::type
1695  norm2 (const Kokkos::View<T*, device_type>& norms) const
1696  {
1697  const size_t numNorms = norms.dimension_0 ();
1698  Kokkos::View<mag_type*, device_type> theNorms ("MV::norm2 tmp", numNorms);
1699  // Call overload that takes a Kokkos::View<mag_type*, device_type>.
1700  this->norm2 (theNorms);
1701  // FIXME (mfh 14 Jul 2014) Does this actually work if mag_type
1702  // and T differ? We would need a test for this, but only the
1703  // Sacado and Stokhos packages are likely to care about this use
1704  // case. This could also come up with Kokkos::complex ->
1705  // std::complex conversion.
1706  Kokkos::deep_copy (norms, theNorms);
1707  }
1708 
1715  void norm2 (const Teuchos::ArrayView<mag_type>& norms) const;
1716 
1729  template <typename T>
1730  typename std::enable_if< ! (std::is_same<mag_type,T>::value), void >::type
1731  norm2 (const Teuchos::ArrayView<T>& norms) const
1732  {
1733  typedef typename Teuchos::ArrayView<T>::size_type size_type;
1734  const size_type sz = norms.size ();
1735  Teuchos::Array<mag_type> theNorms (sz);
1736  this->norm2 (theNorms);
1737  for (size_type i = 0; i < sz; ++i) {
1738  // If T and mag_type differ, this does an implicit conversion.
1739  norms[i] = theNorms[i];
1740  }
1741  }
1742 
1749  void normInf (const Kokkos::View<mag_type*, device_type>& norms) const;
1750 
1762  template<typename T>
1763  typename std::enable_if< ! (std::is_same<mag_type, T>::value), void >::type
1764  normInf (const Kokkos::View<T*, device_type>& norms) const
1765  {
1766  const size_t numNorms = norms.dimension_0 ();
1767  Kokkos::View<mag_type*, device_type> theNorms ("MV::normInf tmp", numNorms);
1768  // Call overload that takes a Kokkos::View<mag_type*, device_type>.
1769  this->normInf (theNorms);
1770  // FIXME (mfh 15 Jul 2014) Does this actually work if mag_type
1771  // and T differ? We would need a test for this, but only the
1772  // Sacado and Stokhos packages are likely to care about this use
1773  // case. This could also come up with Kokkos::complex ->
1774  // std::complex conversion.
1775  Kokkos::deep_copy (norms, theNorms);
1776  }
1777 
1783  void normInf (const Teuchos::ArrayView<mag_type>& norms) const;
1784 
1797  template <typename T>
1798  typename std::enable_if< ! (std::is_same<mag_type,T>::value), void >::type
1799  normInf (const Teuchos::ArrayView<T>& norms) const
1800  {
1801  typedef typename Teuchos::ArrayView<T>::size_type size_type;
1802  const size_type sz = norms.size ();
1803  Teuchos::Array<mag_type> theNorms (sz);
1804  this->norm2 (theNorms);
1805  for (size_type i = 0; i < sz; ++i) {
1806  // If T and mag_type differ, this does an implicit conversion.
1807  norms[i] = theNorms[i];
1808  }
1809  }
1810 
1817  void TPETRA_DEPRECATED
1819  const Teuchos::ArrayView<mag_type>& norms) const;
1820 
1837  template <typename T>
1838  typename std::enable_if< ! (std::is_same<mag_type,T>::value), void >::type
1839  TPETRA_DEPRECATED
1841  const Teuchos::ArrayView<T>& norms) const
1842  {
1843  typedef typename Teuchos::ArrayView<T>::size_type size_type;
1844  const size_type sz = norms.size ();
1845  Teuchos::Array<mag_type> theNorms (sz);
1846  this->normWeighted (weights, theNorms);
1847  for (size_type i = 0; i < sz; ++i) {
1848  // If T and mag_type differ, this does an implicit conversion.
1849  norms[i] = theNorms[i];
1850  }
1851  }
1852 
1857  void meanValue (const Teuchos::ArrayView<impl_scalar_type>& means) const;
1858 
1859  template <typename T>
1860  typename std::enable_if<! std::is_same<impl_scalar_type, T>::value, void>::type
1861  meanValue (const Teuchos::ArrayView<T>& means) const
1862  {
1863  typedef typename Teuchos::Array<T>::size_type size_type;
1864  const size_type numMeans = means.size ();
1865 
1866  Teuchos::Array<impl_scalar_type> theMeans (numMeans);
1867  this->meanValue (theMeans ());
1868  for (size_type k = 0; k < numMeans; ++k) {
1869  means[k] = static_cast<T> (theMeans[k]);
1870  }
1871  }
1872 
1878  void
1879  multiply (Teuchos::ETransp transA,
1880  Teuchos::ETransp transB,
1881  const Scalar& alpha,
1884  const Scalar& beta);
1885 
1906  void
1907  elementWiseMultiply (Scalar scalarAB,
1910  Scalar scalarThis);
1912 
1914 
1916  size_t getNumVectors() const;
1917 
1919  size_t getLocalLength() const;
1920 
1922  global_size_t getGlobalLength() const;
1923 
1929  size_t getStride() const;
1930 
1934  bool isConstantStride() const;
1935 
1937 
1939 
1940 
1942  virtual std::string description() const;
1943 
1972  virtual void
1973  describe (Teuchos::FancyOStream& out,
1974  const Teuchos::EVerbosityLevel verbLevel =
1975  Teuchos::Describable::verbLevel_default) const;
1977 
1991  virtual void
1992  removeEmptyProcessesInPlace (const Teuchos::RCP<const map_type>& newMap);
1993 
2004  void setCopyOrView (const Teuchos::DataAccess copyOrView) {
2005  TEUCHOS_TEST_FOR_EXCEPTION(
2006  copyOrView == Teuchos::Copy, std::invalid_argument,
2007  "Tpetra::MultiVector::setCopyOrView: The Kokkos refactor version of "
2008  "MultiVector _only_ implements view semantics. You may not call this "
2009  "method with copyOrView = Teuchos::Copy. The only valid argument is "
2010  "Teuchos::View.");
2011  }
2012 
2023  Teuchos::DataAccess getCopyOrView () const {
2024  return Teuchos::View;
2025  }
2026 
2041  void
2043 
2044  protected:
2045  template <class DS, class DL, class DG, class DN, const bool dstClassic,
2046  class SS, class SL, class SG, class SN, const bool srcClassic>
2047  friend void
2050 
2057  mutable dual_view_type view_;
2058 
2088  mutable dual_view_type origView_;
2089 
2102  Teuchos::Array<size_t> whichVectors_;
2103 
2105 
2106 
2108  enum EWhichNorm {
2109  NORM_ONE, //<! Use the one-norm
2110  NORM_TWO, //<! Use the two-norm
2111  NORM_INF //<! Use the infinity-norm
2112  };
2113 
2121  void
2122  normImpl (const Kokkos::View<mag_type*, device_type>& norms,
2123  const EWhichNorm whichNorm) const;
2124 
2126 
2128 
2129  // Return true if and only if VectorIndex is a valid column index.
2130  bool vectorIndexOutOfRange (const size_t VectorIndex) const;
2131 
2136  template <class T>
2137  Teuchos::ArrayRCP<T>
2138  getSubArrayRCP (Teuchos::ArrayRCP<T> arr, size_t j) const;
2139 
2141  size_t getOrigNumLocalRows () const;
2142 
2144  size_t getOrigNumLocalCols () const;
2145 
2147 
2149 
2154  virtual bool
2155  checkSizes (const SrcDistObject& sourceObj);
2156 
2158  virtual size_t constantNumberOfPackets () const;
2159 
2161  virtual bool useNewInterface () { return true; }
2162 
2163  virtual void
2164  copyAndPermuteNew (
2165  const SrcDistObject& sourceObj,
2166  size_t numSameIDs,
2167  const Kokkos::View<const local_ordinal_type*, execution_space>& permuteToLIDs,
2168  const Kokkos::View<const local_ordinal_type*, execution_space>& permuteFromLIDs);
2169 
2170  virtual void
2171  packAndPrepareNew (
2172  const SrcDistObject& sourceObj,
2173  const Kokkos::View<const local_ordinal_type*, execution_space>& exportLIDs,
2174  Kokkos::View<impl_scalar_type*, execution_space>& exports,
2175  const Kokkos::View<size_t*, execution_space>& numPacketsPerLID,
2176  size_t& constantNumPackets,
2177  Distributor &distor);
2178 
2179  virtual void
2180  unpackAndCombineNew (
2181  const Kokkos::View<const LocalOrdinal*, execution_space>& importLIDs,
2182  const Kokkos::View<const impl_scalar_type*, execution_space>& imports,
2183  const Kokkos::View<size_t*, execution_space>& numPacketsPerLID,
2184  size_t constantNumPackets,
2185  Distributor &distor,
2186  CombineMode CM);
2187 
2188  void createViews () const;
2189  void createViewsNonConst (KokkosClassic::ReadWriteOption rwo);
2190  void releaseViews () const;
2192 
2193  typename dual_view_type::t_dev getKokkosView() const { return view_.d_view; }
2194 
2195  }; // class MultiVector
2196 
2197  namespace Details {
2198 
2199  template<class DstMultiVectorType,
2200  class SrcMultiVectorType>
2201  Teuchos::RCP<typename MultiVectorCloner<DstMultiVectorType, SrcMultiVectorType>::dst_mv_type>
2202  MultiVectorCloner<DstMultiVectorType, SrcMultiVectorType>::
2203  clone (const src_mv_type& X,
2204  const Teuchos::RCP<typename dst_mv_type::node_type>& node2)
2205  {
2206  typedef typename src_mv_type::map_type src_map_type;
2207  typedef typename dst_mv_type::map_type dst_map_type;
2208  typedef typename dst_mv_type::node_type dst_node_type;
2209  typedef typename dst_mv_type::dual_view_type dst_dual_view_type;
2210 
2211  // Clone X's Map to have the new Node type.
2212  RCP<const src_map_type> map1 = X.getMap ();
2213  RCP<const dst_map_type> map2 = map1.is_null () ?
2214  Teuchos::null : map1->template clone<dst_node_type> (node2);
2215 
2216  const size_t lclNumRows = X.getLocalLength ();
2217  const size_t numCols = X.getNumVectors ();
2218  dst_dual_view_type Y_view ("MV::dual_view", lclNumRows, numCols);
2219 
2220  RCP<dst_mv_type> Y (new dst_mv_type (map2, Y_view));
2221  // Let deep_copy do the work for us, to avoid code duplication.
2222  ::Tpetra::deep_copy (Y, X);
2223  return Y ;
2224  }
2225 
2226  } // namespace Details
2227 
2230  template <class ST, class LO, class GO, class NT, const bool classic>
2231  void
2234  {
2235  // NOTE (mfh 11 Sep 2014) We can't implement deep_copy with
2236  // shallow-copy operator=, because that would invalidate existing
2237  // views of dst!
2238  dst.assign (src);
2239  }
2240 
2241  // Implementation of the most generic version of MultiVector deep_copy.
2242  template <class DS, class DL, class DG, class DN, const bool dstClassic,
2243  class SS, class SL, class SG, class SN, const bool srcClassic>
2244  void
2247  {
2248  typedef typename DN::device_type DD;
2249  //typedef typename SN::device_type SD;
2250 
2251  TEUCHOS_TEST_FOR_EXCEPTION(
2252  dst.getGlobalLength () != src.getGlobalLength () ||
2253  dst.getNumVectors () != src.getNumVectors (), std::invalid_argument,
2254  "Tpetra::deep_copy: Global dimensions of the two Tpetra::MultiVector "
2255  "objects do not match. src has dimensions [" << src.getGlobalLength ()
2256  << "," << src.getNumVectors () << "], and dst has dimensions ["
2257  << dst.getGlobalLength () << "," << dst.getNumVectors () << "].");
2258 
2259  // FIXME (mfh 28 Jul 2014) Don't throw; just set a local error flag.
2260  TEUCHOS_TEST_FOR_EXCEPTION(
2261  dst.getLocalLength () != src.getLocalLength (), std::invalid_argument,
2262  "Tpetra::deep_copy: The local row counts of the two Tpetra::MultiVector "
2263  "objects do not match. src has " << src.getLocalLength () << " row(s) "
2264  << " and dst has " << dst.getLocalLength () << " row(s).");
2265 
2266  if (src.isConstantStride () && dst.isConstantStride ()) {
2269 
2270  if (src.getDualView ().modified_device >= src.getDualView ().modified_host) {
2271  // Device memory has the most recent version of src.
2272  dst.template modify<DES> (); // We are about to modify dst on device.
2273  // Copy from src to dst on device.
2274  Details::localDeepCopyConstStride (dst.getDualView ().d_view,
2275  src.getDualView ().d_view);
2276  dst.template sync<HES> (); // Sync dst from device to host.
2277  }
2278  else { // Host memory has the most recent version of src.
2279  dst.template modify<HES> (); // We are about to modify dst on host.
2280  // Copy from src to dst on host.
2281  Details::localDeepCopyConstStride (dst.getDualView ().h_view,
2282  src.getDualView ().h_view);
2283  dst.template sync<DES> (); // Sync dst from host to device.
2284  }
2285  }
2286  else {
2287  typedef Kokkos::DualView<SL*, DD> whichvecs_type;
2288  typedef typename whichvecs_type::t_dev::execution_space DES;
2289  typedef typename whichvecs_type::t_host::execution_space HES;
2290 
2291  if (dst.isConstantStride ()) {
2292  const SL numWhichVecs = static_cast<SL> (src.whichVectors_.size ());
2293  const std::string whichVecsLabel ("MV::deep_copy::whichVecs");
2294 
2295  // We can't sync src, since it is only an input argument.
2296  // Thus, we have to use the most recently modified version of
2297  // src, which coudl be either the device or host version.
2298  if (src.getDualView ().modified_device >= src.getDualView ().modified_host) {
2299  // Copy from the device version of src.
2300  //
2301  // whichVecs tells the kernel which vectors (columns) of src
2302  // to copy. Fill whichVecs on the host, and sync to device.
2303  whichvecs_type whichVecs (whichVecsLabel, numWhichVecs);
2304  whichVecs.template modify<HES> ();
2305  for (SL i = 0; i < numWhichVecs; ++i) {
2306  whichVecs.h_view(i) = static_cast<SL> (src.whichVectors_[i]);
2307  }
2308  // Sync the host version of whichVecs to the device.
2309  whichVecs.template sync<DES> ();
2310 
2311  // Mark the device version of dst's DualView as modified.
2312  dst.template modify<DES> ();
2313  // Copy from the selected vectors of src to dst, on the device.
2314  Details::localDeepCopy (dst.getDualView ().d_view,
2315  src.getDualView ().d_view,
2316  dst.isConstantStride (),
2317  src.isConstantStride (),
2318  whichVecs.d_view,
2319  whichVecs.d_view);
2320  // Sync dst's DualView to the host. This is cheaper than
2321  // repeating the above copy from src to dst on the host.
2322  dst.template sync<HES> ();
2323  }
2324  else { // host version of src was the most recently modified
2325  // Copy from the host version of src.
2326  //
2327  // whichVecs tells the kernel which vectors (columns) of src
2328  // to copy. Fill whichVecs on the host, and use it there.
2329  typedef Kokkos::View<SL*, HES> the_whichvecs_type;
2330  the_whichvecs_type whichVecs (whichVecsLabel, numWhichVecs);
2331  for (SL i = 0; i < numWhichVecs; ++i) {
2332  whichVecs(i) = static_cast<SL> (src.whichVectors_[i]);
2333  }
2334  // Copy from the selected vectors of src to dst, on the
2335  // host. The function ignores the first instance of
2336  // 'whichVecs' in this case.
2337  Details::localDeepCopy (dst.getDualView ().h_view,
2338  src.getDualView ().h_view,
2339  dst.isConstantStride (),
2340  src.isConstantStride (),
2341  whichVecs, whichVecs);
2342  // Sync dst back to the device, since we only copied on the host.
2343  dst.template sync<DES> ();
2344  }
2345  }
2346  else { // dst is NOT constant stride
2347  if (src.isConstantStride ()) {
2348  if (src.getDualView ().modified_device >= src.getDualView ().modified_host) {
2349  // Copy from the device version of src.
2350  //
2351  // whichVecs tells the kernel which vectors (columns) of dst
2352  // to copy. Fill whichVecs on the host, and sync to device.
2353  typedef Kokkos::DualView<DL*, DES> the_whichvecs_type;
2354  const std::string whichVecsLabel ("MV::deep_copy::whichVecs");
2355  const DL numWhichVecs = static_cast<DL> (dst.whichVectors_.size ());
2356  the_whichvecs_type whichVecs (whichVecsLabel, numWhichVecs);
2357  whichVecs.template modify<HES> ();
2358  for (DL i = 0; i < numWhichVecs; ++i) {
2359  whichVecs.h_view(i) = dst.whichVectors_[i];
2360  }
2361  // Sync the host version of whichVecs to the device.
2362  whichVecs.template sync<DES> ();
2363 
2364  // Copy src to the selected vectors of dst, on the device.
2365  Details::localDeepCopy (dst.getDualView ().d_view,
2366  src.getDualView ().d_view,
2367  dst.isConstantStride (),
2368  src.isConstantStride (),
2369  whichVecs.d_view,
2370  whichVecs.d_view);
2371  // We can't sync src and repeat the above copy on the
2372  // host, so sync dst back to the host.
2373  //
2374  // FIXME (mfh 29 Jul 2014) This may overwrite columns that
2375  // don't actually belong to dst's view.
2376  dst.template sync<HES> ();
2377  }
2378  else { // host version of src was the most recently modified
2379  // Copy from the host version of src.
2380  //
2381  // whichVecs tells the kernel which vectors (columns) of src
2382  // to copy. Fill whichVecs on the host, and use it there.
2383  typedef Kokkos::View<DL*, HES> the_whichvecs_type;
2384  const DL numWhichVecs = static_cast<DL> (dst.whichVectors_.size ());
2385  the_whichvecs_type whichVecs ("MV::deep_copy::whichVecs", numWhichVecs);
2386  for (DL i = 0; i < numWhichVecs; ++i) {
2387  whichVecs(i) = static_cast<DL> (dst.whichVectors_[i]);
2388  }
2389  // Copy from src to the selected vectors of dst, on the host.
2390  Details::localDeepCopy (dst.getDualView ().h_view,
2391  src.getDualView ().h_view,
2392  dst.isConstantStride (),
2393  src.isConstantStride (),
2394  whichVecs, whichVecs);
2395  // Sync dst back to the device, since we only copied on the host.
2396  //
2397  // FIXME (mfh 29 Jul 2014) This may overwrite columns that
2398  // don't actually belong to dst's view.
2399  dst.template sync<DES> ();
2400  }
2401  }
2402  else { // neither src nor dst have constant stride
2403  if (src.getDualView ().modified_device >= src.getDualView ().modified_host) {
2404  // Copy from the device version of src.
2405  //
2406  // whichVectorsDst tells the kernel which vectors
2407  // (columns) of dst to copy. Fill it on the host, and
2408  // sync to device.
2409  const DL dstNumWhichVecs = static_cast<DL> (dst.whichVectors_.size ());
2410  Kokkos::DualView<DL*, DES> whichVecsDst ("MV::deep_copy::whichVecsDst",
2411  dstNumWhichVecs);
2412  whichVecsDst.template modify<HES> ();
2413  for (DL i = 0; i < dstNumWhichVecs; ++i) {
2414  whichVecsDst.h_view(i) = static_cast<DL> (dst.whichVectors_[i]);
2415  }
2416  // Sync the host version of whichVecsDst to the device.
2417  whichVecsDst.template sync<DES> ();
2418 
2419  // whichVectorsSrc tells the kernel which vectors
2420  // (columns) of src to copy. Fill it on the host, and
2421  // sync to device. Use the destination MultiVector's
2422  // LocalOrdinal type here.
2423  const DL srcNumWhichVecs = static_cast<DL> (src.whichVectors_.size ());
2424  Kokkos::DualView<DL*, DES> whichVecsSrc ("MV::deep_copy::whichVecsSrc",
2425  srcNumWhichVecs);
2426  whichVecsSrc.template modify<HES> ();
2427  for (DL i = 0; i < srcNumWhichVecs; ++i) {
2428  whichVecsSrc.h_view(i) = static_cast<DL> (src.whichVectors_[i]);
2429  }
2430  // Sync the host version of whichVecsSrc to the device.
2431  whichVecsSrc.template sync<DES> ();
2432 
2433  // Copy from the selected vectors of src to the selected
2434  // vectors of dst, on the device.
2435  Details::localDeepCopy (dst.getDualView ().d_view,
2436  src.getDualView ().d_view,
2437  dst.isConstantStride (),
2438  src.isConstantStride (),
2439  whichVecsDst.d_view,
2440  whichVecsSrc.d_view);
2441  }
2442  else {
2443  const DL dstNumWhichVecs = static_cast<DL> (dst.whichVectors_.size ());
2444  Kokkos::View<DL*, HES> whichVectorsDst ("dstWhichVecs", dstNumWhichVecs);
2445  for (DL i = 0; i < dstNumWhichVecs; ++i) {
2446  whichVectorsDst(i) = dst.whichVectors_[i];
2447  }
2448 
2449  // Use the destination MultiVector's LocalOrdinal type here.
2450  const DL srcNumWhichVecs = static_cast<DL> (src.whichVectors_.size ());
2451  Kokkos::View<DL*, HES> whichVectorsSrc ("srcWhichVecs", srcNumWhichVecs);
2452  for (DL i = 0; i < srcNumWhichVecs; ++i) {
2453  whichVectorsSrc(i) = src.whichVectors_[i];
2454  }
2455 
2456  // Copy from the selected vectors of src to the selected
2457  // vectors of dst, on the host.
2458  Details::localDeepCopy (dst.getDualView ().h_view,
2459  src.getDualView ().h_view,
2460  dst.isConstantStride (),
2461  src.isConstantStride (),
2462  whichVectorsDst, whichVectorsSrc);
2463  // We can't sync src and repeat the above copy on the
2464  // host, so sync dst back to the host.
2465  //
2466  // FIXME (mfh 29 Jul 2014) This may overwrite columns that
2467  // don't actually belong to dst's view.
2468  dst.template sync<HES> ();
2469  }
2470  }
2471  }
2472  }
2473  }
2474 } // namespace Tpetra
2475 
2476 
2477 namespace Teuchos {
2478 
2479  // Give Teuchos::TypeNameTraits<Tpetra::MultiVector<...> > a
2480  // human-readable definition.
2481  template<class SC, class LO, class GO, class NT, const bool classic>
2482  class TypeNameTraits<Tpetra::MultiVector<SC, LO, GO, NT, classic> > {
2483  public:
2484  static std::string name () {
2485  return std::string ("Tpetra::MultiVector<") +
2486  TypeNameTraits<SC>::name () + "," +
2487  TypeNameTraits<LO>::name () + "," +
2488  TypeNameTraits<GO>::name () + "," +
2489  TypeNameTraits<NT>::name () + ">";
2490  }
2491 
2492  static std::string
2493  concreteName (const Tpetra::MultiVector<SC, LO, GO, NT, classic>&) {
2494  return name ();
2495  }
2496  };
2497 } // namespace Teuchos
2498 
2499 #endif // TPETRA_MULTIVECTOR_DECL_HPP
size_t getLocalLength() const
Local number of rows on the calling process.
Node node_type
This class&#39; fourth template parameter; the Kokkos Node type.
Namespace Tpetra contains the class and methods constituting the Tpetra library.
std::enable_if<!std::is_same< T, impl_scalar_type >::value &&std::is_convertible< T, impl_scalar_type >::value, void >::type sumIntoGlobalValue(const GlobalOrdinal globalRow, const size_t col, const T &value, const bool atomic=useAtomicUpdatesByDefault) const
Like the above sumIntoGlobalValue, but only enabled if T differs from impl_scalar_type.
void sync()
Update data on device or host only if data in the other space has been marked as modified.
MultiVector< ST, LO, GO, NT, classic > createCopy(const MultiVector< ST, LO, GO, NT, classic > &src)
Return a deep copy of the given MultiVector.
KokkosClassic::DefaultNode::DefaultNodeType node_type
Default value of Node template parameter.
void setCopyOrView(const Teuchos::DataAccess copyOrView)
Set whether this has copy (copyOrView = Teuchos::Copy) or view (copyOrView = Teuchos::View) semantics...
Teuchos::Array< size_t > whichVectors_
Indices of columns this multivector is viewing.
One or more distributed dense vectors.
void deep_copy(MultiVector< ST, LO, GO, NT, classic > &dst, const MultiVector< ST, LO, GO, NT, classic > &src)
Specialization of deep_copy for MultiVector objects with the same template parameters.
std::enable_if<!std::is_same< T, impl_scalar_type >::value &&std::is_convertible< T, impl_scalar_type >::value, void >::type replaceGlobalValue(GlobalOrdinal globalRow, size_t col, const T &value) const
Like the above replaceGlobalValue, but only enabled if T differs from impl_scalar_type.
void deep_copy(MultiVector< DS, DL, DG, DN, dstClassic > &dst, const MultiVector< SS, SL, SG, SN, srcClassic > &src)
Copy the contents of the MultiVector src into dst.
Node::device_type device_type
The Kokkos device type.
std::enable_if<!std::is_same< T, impl_scalar_type >::value &&std::is_convertible< T, impl_scalar_type >::value, void >::type putScalar(const T &value)
Set all values in the multivector with the given value.
void removeEmptyProcessesInPlace(Teuchos::RCP< DistObjectType > &input, const Teuchos::RCP< const Map< typename DistObjectType::local_ordinal_type, typename DistObjectType::global_ordinal_type, typename DistObjectType::node_type > > &newMap)
Remove processes which contain no elements in this object&#39;s Map.
Map< LocalOrdinal, GlobalOrdinal, Node > map_type
The type of the Map specialization used by this class.
bool isConstantStride() const
Whether this multivector has constant stride between columns.
dual_view_type view_
The Kokkos::DualView containing the MultiVector&#39;s data.
Kokkos::Details::InnerProductSpaceTraits< impl_scalar_type >::dot_type dot_type
Type of an inner ("dot") product result.
int local_ordinal_type
Default value of LocalOrdinal template parameter.
virtual bool useNewInterface()
Whether this class implements the old or new interface of DistObject.
Teuchos::RCP< MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node, classic > > createMultiVector(const Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > &map, const size_t numVectors)
Nonmember MultiVector "constructor": Create a MultiVector from a given Map.
void modify()
Mark data as modified on the given device TargetDeviceType.
Implementation details of Tpetra.
size_t global_size_t
Global size_t object.
Declarations for the Tpetra::Map class and related nonmember constructors.
Scalar scalar_type
This class&#39; first template parameter; the type of each entry in the MultiVector.
dual_view_type getDualView() const
Get the Kokkos::DualView which implements local storage.
Node::execution_space execution_space
Type of the (new) Kokkos execution space.
Sets up and executes a communication plan for a Tpetra DistObject.
CombineMode
Rule for combining data in an Import or Export.
Abstract base class for objects that can be the source of an Import or Export operation.
double scalar_type
Default value of Scalar template parameter.
std::enable_if<!std::is_same< T, impl_scalar_type >::value &&std::is_convertible< T, impl_scalar_type >::value, void >::type replaceLocalValue(LocalOrdinal localRow, size_t col, const T &value) const
Like the above replaceLocalValue, but only enabled if T differs from impl_scalar_type.
Teuchos::DataAccess getCopyOrView() const
Get whether this has copy (copyOrView = Teuchos::Copy) or view (copyOrView = Teuchos::View) semantics...
global_size_t getGlobalLength() const
Global number of rows in the multivector.
Kokkos::Details::ArithTraits< Scalar >::val_type impl_scalar_type
The type used internally in place of Scalar.
Implementation of Tpetra::MultiVector::clone().
Kokkos::Details::ArithTraits< impl_scalar_type >::mag_type mag_type
Type of a norm result.
Kokkos::DualView< impl_scalar_type **, Kokkos::LayoutLeft, typename execution_space::execution_space > dual_view_type
Kokkos::DualView specialization used by this class.
Describes a parallel distribution of objects over processes.
A distributed dense vector.
void assign(const MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node, classic > &src)
Copy the contents of src into *this (deep copy).
LocalOrdinal local_ordinal_type
This class&#39; second template parameter; the type of local indices.
size_t getNumVectors() const
Number of columns in the multivector.
Kokkos::Impl::if_c< std::is_same< typename device_type::memory_space, typename TargetDeviceType::memory_space >::value, typename dual_view_type::t_dev, typename dual_view_type::t_host >::type getLocalView() const
Return a view of the local data on a specific device.
EWhichNorm
Input argument for normImpl() (which see).
Base class for distributed Tpetra objects that support data redistribution.
GlobalOrdinal global_ordinal_type
This class&#39; third template parameter; the type of global indices.
dual_view_type origView_
The "original view" of the MultiVector&#39;s data.
std::enable_if<!std::is_same< T, impl_scalar_type >::value &&std::is_convertible< T, impl_scalar_type >::value, void >::type sumIntoLocalValue(LocalOrdinal localRow, size_t col, const T &value, const bool atomic=useAtomicUpdatesByDefault) const
Like the above sumIntoLocalValue, but only enabled if T differs from impl_scalar_type.