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 
705  template <class Node2>
706  Teuchos::RCP<MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node2> >
707  clone (const Teuchos::RCP<Node2>& node2) const;
708 
710  virtual ~MultiVector ();
711 
713 
715 
732  void
733  replaceGlobalValue (GlobalOrdinal globalRow,
734  size_t col,
735  const impl_scalar_type& value);
736 
754  template<typename T>
755  typename std::enable_if<! std::is_same<T, impl_scalar_type>::value && std::is_convertible<T, impl_scalar_type>::value, void>::type
756  replaceGlobalValue (GlobalOrdinal globalRow,
757  size_t col,
758  const T& value)
759  {
760  replaceGlobalValue (globalRow, col, static_cast<impl_scalar_type> (value));
761  }
762 
779  void
780  sumIntoGlobalValue (GlobalOrdinal globalRow,
781  size_t col,
782  const impl_scalar_type& value);
783 
801  template<typename T>
802  typename std::enable_if<! std::is_same<T, impl_scalar_type>::value && std::is_convertible<T, impl_scalar_type>::value, void>::type
803  sumIntoGlobalValue (GlobalOrdinal globalRow,
804  size_t col,
805  const T& value)
806  {
807  sumIntoGlobalValue (globalRow, col, static_cast<impl_scalar_type> (value));
808  }
809 
826  void
827  replaceLocalValue (LocalOrdinal localRow,
828  size_t col,
829  const impl_scalar_type& value);
830 
848  template<typename T>
849  typename std::enable_if<! std::is_same<T, impl_scalar_type>::value && std::is_convertible<T, impl_scalar_type>::value, void>::type
850  replaceLocalValue (LocalOrdinal localRow,
851  size_t col,
852  const T& value)
853  {
854  replaceLocalValue (localRow, col, static_cast<impl_scalar_type> (value));
855  }
856 
873  void
874  sumIntoLocalValue (LocalOrdinal localRow,
875  size_t col,
876  const impl_scalar_type& value);
877 
895  template<typename T>
896  typename std::enable_if<! std::is_same<T, impl_scalar_type>::value && std::is_convertible<T, impl_scalar_type>::value, void>::type
897  sumIntoLocalValue (LocalOrdinal localRow,
898  size_t col,
899  const T& value)
900  {
901  sumIntoLocalValue (localRow, col, static_cast<impl_scalar_type> (value));
902  }
903 
905  void putScalar (const Scalar& value);
906 
922  void randomize();
923 
989  void replaceMap (const Teuchos::RCP<const map_type>& map);
990 
997  void reduce();
998 
1015 
1017 
1019 
1027 
1029  Teuchos::RCP<MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node, classic> >
1030  subCopy (const Teuchos::Range1D& colRng) const;
1031 
1033  Teuchos::RCP<MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node, classic> >
1034  subCopy (const Teuchos::ArrayView<const size_t>& cols) const;
1035 
1037  Teuchos::RCP<const MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node, classic> >
1038  subView (const Teuchos::Range1D& colRng) const;
1039 
1041  Teuchos::RCP<const MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node, classic> >
1042  subView (const Teuchos::ArrayView<const size_t>& cols) const;
1043 
1045  Teuchos::RCP<MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node, classic> >
1046  subViewNonConst (const Teuchos::Range1D& colRng);
1047 
1049  Teuchos::RCP<MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node, classic> >
1050  subViewNonConst (const Teuchos::ArrayView<const size_t>& cols);
1051 
1114  Teuchos::RCP<const MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node, classic> >
1115  offsetView (const Teuchos::RCP<const map_type>& subMap,
1116  const size_t offset) const;
1117 
1135  Teuchos::RCP<MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node, classic> >
1136  offsetViewNonConst (const Teuchos::RCP<const map_type>& subMap,
1137  const size_t offset);
1138 
1140  Teuchos::RCP<const Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node, classic> >
1141  getVector (const size_t j) const;
1142 
1144  Teuchos::RCP<Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node, classic> >
1145  getVectorNonConst (const size_t j);
1146 
1148  Teuchos::ArrayRCP<const Scalar> getData (size_t j) const;
1149 
1151  Teuchos::ArrayRCP<Scalar> getDataNonConst (size_t j);
1152 
1160  void
1161  get1dCopy (const Teuchos::ArrayView<Scalar>& A,
1162  const size_t LDA) const;
1163 
1170  void
1171  get2dCopy (const Teuchos::ArrayView<const Teuchos::ArrayView<Scalar> >& ArrayOfPtrs) const;
1172 
1178  Teuchos::ArrayRCP<const Scalar> get1dView () const;
1179 
1181  Teuchos::ArrayRCP<Teuchos::ArrayRCP<const Scalar> > get2dView () const;
1182 
1188  Teuchos::ArrayRCP<Scalar> get1dViewNonConst ();
1189 
1191  Teuchos::ArrayRCP<Teuchos::ArrayRCP<Scalar> > get2dViewNonConst ();
1192 
1201  KokkosClassic::MultiVector<Scalar, Node> getLocalMV () const;
1202 
1214  dual_view_type getDualView () const;
1215 
1234  template<class TargetDeviceType>
1235  void sync () {
1236  getDualView ().template sync<TargetDeviceType> ();
1237  }
1238 
1244  template<class TargetDeviceType>
1245  void modify () {
1246  getDualView ().template modify<TargetDeviceType> ();
1247  }
1248 
1280  template<class TargetDeviceType>
1281  typename Kokkos::Impl::if_c<
1282  std::is_same<
1283  typename device_type::memory_space,
1284  typename TargetDeviceType::memory_space>::value,
1285  typename dual_view_type::t_dev,
1286  typename dual_view_type::t_host>::type
1287  getLocalView () const {
1288  return getDualView ().template view<TargetDeviceType> ();
1289  }
1290 
1292 
1294 
1308  void
1310  const Teuchos::ArrayView<dot_type>& dots) const;
1311 
1323  template <typename T>
1324  typename std::enable_if< ! (std::is_same<dot_type, T>::value), void >::type
1326  const Teuchos::ArrayView<T> &dots) const
1327  {
1328  const size_t sz = static_cast<size_t> (dots.size ());
1329  Teuchos::Array<dot_type> dts (sz);
1330  this->dot (A, dts);
1331  for (size_t i = 0; i < sz; ++i) {
1332  // If T and dot_type differ, this does an implicit conversion.
1333  dots[i] = dts[i];
1334  }
1335  }
1336 
1338  template <typename T>
1339  typename std::enable_if< ! (std::is_same<dot_type, T>::value), void >::type
1341  std::vector<T>& dots) const
1342  {
1343  const size_t sz = dots.size ();
1344  Teuchos::Array<dot_type> dts (sz);
1345  this->dot (A, dts);
1346  for (size_t i = 0; i < sz; ++i) {
1347  // If T and dot_type differ, this does an implicit conversion.
1348  dots[i] = dts[i];
1349  }
1350  }
1351 
1369  void
1371  const Kokkos::View<dot_type*, device_type>& dots) const;
1372 
1385  template <typename T>
1386  typename std::enable_if< ! (std::is_same<dot_type, T>::value), void >::type
1388  const Kokkos::View<T*, device_type>& dots) const
1389  {
1390  const size_t numDots = dots.dimension_0 ();
1391  Kokkos::View<dot_type*, device_type> dts ("MV::dot tmp", numDots);
1392  // Call overload that takes a Kokkos::View<dot_type*, device_type>.
1393  this->dot (A, dts);
1394  // FIXME (mfh 14 Jul 2014) Does this actually work if dot_type
1395  // and T differ? We would need a test for this, but only the
1396  // Sacado and Stokhos packages are likely to care about this use
1397  // case. It could also come up for Kokkos::complex ->
1398  // std::complex conversions, but those two implementations
1399  // should generally be bitwise compatible.
1400  Kokkos::deep_copy (dots, dts);
1401  }
1402 
1405 
1408 
1416  void scale (const Scalar& alpha);
1417 
1426  void scale (const Teuchos::ArrayView<const Scalar>& alpha);
1427 
1436  void scale (const Kokkos::View<const impl_scalar_type*, device_type>& alpha);
1437 
1446  void
1447  scale (const Scalar& alpha,
1449 
1456  void
1457  update (const Scalar& alpha,
1459  const Scalar& beta);
1460 
1467  void
1468  update (const Scalar& alpha,
1470  const Scalar& beta,
1472  const Scalar& gamma);
1473 
1485  void norm1 (const Kokkos::View<mag_type*, device_type>& norms) const;
1486 
1500  template <typename T>
1501  typename std::enable_if< ! (std::is_same<mag_type, T>::value), void >::type
1502  norm1 (const Kokkos::View<T*, device_type>& norms) const
1503  {
1504  const size_t numNorms = norms.dimension_0 ();
1505  Kokkos::View<mag_type*, device_type> tmpNorms ("MV::norm1 tmp", numNorms);
1506  // Call overload that takes a Kokkos::View<mag_type*, device_type>.
1507  this->norm1 (tmpNorms);
1508  // FIXME (mfh 15 Jul 2014) Does this actually work if mag_type
1509  // and T differ? We would need a test for this, but only the
1510  // Sacado and Stokhos packages are likely to care about this use
1511  // case. It could also come up with Kokkos::complex ->
1512  // std::complex conversion.
1513  Kokkos::deep_copy (norms, tmpNorms);
1514  }
1515 
1516 
1522  void norm1 (const Teuchos::ArrayView<mag_type>& norms) const;
1523 
1536  template <typename T>
1537  typename std::enable_if< ! (std::is_same<mag_type,T>::value), void >::type
1538  norm1 (const Teuchos::ArrayView<T>& norms) const
1539  {
1540  typedef typename Teuchos::ArrayView<T>::size_type size_type;
1541  const size_type sz = norms.size ();
1542  Teuchos::Array<mag_type> theNorms (sz);
1543  this->norm1 (theNorms);
1544  for (size_type i = 0; i < sz; ++i) {
1545  // If T and mag_type differ, this does an implicit conversion.
1546  norms[i] = theNorms[i];
1547  }
1548  }
1549 
1562  void norm2 (const Kokkos::View<mag_type*, device_type>& norms) const;
1563 
1575  template<typename T>
1576  typename std::enable_if< ! (std::is_same<mag_type, T>::value), void >::type
1577  norm2 (const Kokkos::View<T*, device_type>& norms) const
1578  {
1579  const size_t numNorms = norms.dimension_0 ();
1580  Kokkos::View<mag_type*, device_type> theNorms ("MV::norm2 tmp", numNorms);
1581  // Call overload that takes a Kokkos::View<mag_type*, device_type>.
1582  this->norm2 (theNorms);
1583  // FIXME (mfh 14 Jul 2014) Does this actually work if mag_type
1584  // and T differ? We would need a test for this, but only the
1585  // Sacado and Stokhos packages are likely to care about this use
1586  // case. This could also come up with Kokkos::complex ->
1587  // std::complex conversion.
1588  Kokkos::deep_copy (norms, theNorms);
1589  }
1590 
1597  void norm2 (const Teuchos::ArrayView<mag_type>& norms) const;
1598 
1611  template <typename T>
1612  typename std::enable_if< ! (std::is_same<mag_type,T>::value), void >::type
1613  norm2 (const Teuchos::ArrayView<T>& norms) const
1614  {
1615  typedef typename Teuchos::ArrayView<T>::size_type size_type;
1616  const size_type sz = norms.size ();
1617  Teuchos::Array<mag_type> theNorms (sz);
1618  this->norm2 (theNorms);
1619  for (size_type i = 0; i < sz; ++i) {
1620  // If T and mag_type differ, this does an implicit conversion.
1621  norms[i] = theNorms[i];
1622  }
1623  }
1624 
1631  void normInf (const Kokkos::View<mag_type*, device_type>& norms) const;
1632 
1644  template<typename T>
1645  typename std::enable_if< ! (std::is_same<mag_type, T>::value), void >::type
1646  normInf (const Kokkos::View<T*, device_type>& norms) const
1647  {
1648  const size_t numNorms = norms.dimension_0 ();
1649  Kokkos::View<mag_type*, device_type> theNorms ("MV::normInf tmp", numNorms);
1650  // Call overload that takes a Kokkos::View<mag_type*, device_type>.
1651  this->normInf (theNorms);
1652  // FIXME (mfh 15 Jul 2014) Does this actually work if mag_type
1653  // and T differ? We would need a test for this, but only the
1654  // Sacado and Stokhos packages are likely to care about this use
1655  // case. This could also come up with Kokkos::complex ->
1656  // std::complex conversion.
1657  Kokkos::deep_copy (norms, theNorms);
1658  }
1659 
1665  void normInf (const Teuchos::ArrayView<mag_type>& norms) const;
1666 
1679  template <typename T>
1680  typename std::enable_if< ! (std::is_same<mag_type,T>::value), void >::type
1681  normInf (const Teuchos::ArrayView<T>& norms) const
1682  {
1683  typedef typename Teuchos::ArrayView<T>::size_type size_type;
1684  const size_type sz = norms.size ();
1685  Teuchos::Array<mag_type> theNorms (sz);
1686  this->norm2 (theNorms);
1687  for (size_type i = 0; i < sz; ++i) {
1688  // If T and mag_type differ, this does an implicit conversion.
1689  norms[i] = theNorms[i];
1690  }
1691  }
1692 
1695  void
1697  const Teuchos::ArrayView<mag_type>& norms) const;
1698 
1713  template <typename T>
1714  typename std::enable_if< ! (std::is_same<mag_type,T>::value), void >::type
1716  const Teuchos::ArrayView<T>& norms) const
1717  {
1718  typedef typename Teuchos::ArrayView<T>::size_type size_type;
1719  const size_type sz = norms.size ();
1720  Teuchos::Array<mag_type> theNorms (sz);
1721  this->normWeighted (weights, theNorms);
1722  for (size_type i = 0; i < sz; ++i) {
1723  // If T and mag_type differ, this does an implicit conversion.
1724  norms[i] = theNorms[i];
1725  }
1726  }
1727 
1732  void meanValue (const Teuchos::ArrayView<impl_scalar_type>& means) const;
1733 
1734  template <typename T>
1735  typename std::enable_if<! std::is_same<impl_scalar_type, T>::value, void>::type
1736  meanValue (const Teuchos::ArrayView<T>& means) const
1737  {
1738  typedef typename Teuchos::Array<T>::size_type size_type;
1739  const size_type numMeans = means.size ();
1740 
1741  Teuchos::Array<impl_scalar_type> theMeans (numMeans);
1742  this->meanValue (theMeans ());
1743  for (size_type k = 0; k < numMeans; ++k) {
1744  means[k] = static_cast<T> (theMeans[k]);
1745  }
1746  }
1747 
1753  void
1754  multiply (Teuchos::ETransp transA,
1755  Teuchos::ETransp transB,
1756  const Scalar& alpha,
1759  const Scalar& beta);
1760 
1781  void
1782  elementWiseMultiply (Scalar scalarAB,
1785  Scalar scalarThis);
1787 
1789 
1791  size_t getNumVectors() const;
1792 
1794  size_t getLocalLength() const;
1795 
1797  global_size_t getGlobalLength() const;
1798 
1804  size_t getStride() const;
1805 
1809  bool isConstantStride() const;
1810 
1812 
1814 
1815 
1817  virtual std::string description() const;
1818 
1847  virtual void
1848  describe (Teuchos::FancyOStream& out,
1849  const Teuchos::EVerbosityLevel verbLevel =
1850  Teuchos::Describable::verbLevel_default) const;
1852 
1866  virtual void
1867  removeEmptyProcessesInPlace (const Teuchos::RCP<const map_type>& newMap);
1868 
1879  void setCopyOrView (const Teuchos::DataAccess copyOrView) {
1880  TEUCHOS_TEST_FOR_EXCEPTION(
1881  copyOrView == Teuchos::Copy, std::invalid_argument,
1882  "Tpetra::MultiVector::setCopyOrView: The Kokkos refactor version of "
1883  "MultiVector _only_ implements view semantics. You may not call this "
1884  "method with copyOrView = Teuchos::Copy. The only valid argument is "
1885  "Teuchos::View.");
1886  }
1887 
1898  Teuchos::DataAccess getCopyOrView () const {
1899  return Teuchos::View;
1900  }
1901 
1916  void
1918 
1919  protected:
1920  template <class DS, class DL, class DG, class DN, const bool dstClassic,
1921  class SS, class SL, class SG, class SN, const bool srcClassic>
1922  friend void
1925 
1932  mutable dual_view_type view_;
1933 
1963  mutable dual_view_type origView_;
1964 
1977  Teuchos::Array<size_t> whichVectors_;
1978 
1980 
1981 
1983  enum EWhichNorm {
1984  NORM_ONE, //<! Use the one-norm
1985  NORM_TWO, //<! Use the two-norm
1986  NORM_INF //<! Use the infinity-norm
1987  };
1988 
1996  void
1997  normImpl (const Kokkos::View<mag_type*, device_type>& norms,
1998  const EWhichNorm whichNorm) const;
1999 
2001 
2003 
2004  // Return true if and only if VectorIndex is a valid column index.
2005  bool vectorIndexOutOfRange (const size_t VectorIndex) const;
2006 
2011  template <class T>
2012  Teuchos::ArrayRCP<T>
2013  getSubArrayRCP (Teuchos::ArrayRCP<T> arr, size_t j) const;
2014 
2016  size_t getOrigNumLocalRows () const;
2017 
2019  size_t getOrigNumLocalCols () const;
2020 
2022 
2024 
2029  virtual bool
2030  checkSizes (const SrcDistObject& sourceObj);
2031 
2033  virtual size_t constantNumberOfPackets () const;
2034 
2036  virtual bool useNewInterface () { return true; }
2037 
2038  virtual void
2039  copyAndPermuteNew (
2040  const SrcDistObject& sourceObj,
2041  size_t numSameIDs,
2042  const Kokkos::View<const local_ordinal_type*, execution_space>& permuteToLIDs,
2043  const Kokkos::View<const local_ordinal_type*, execution_space>& permuteFromLIDs);
2044 
2045  virtual void
2046  packAndPrepareNew (
2047  const SrcDistObject& sourceObj,
2048  const Kokkos::View<const local_ordinal_type*, execution_space>& exportLIDs,
2049  Kokkos::View<impl_scalar_type*, execution_space>& exports,
2050  const Kokkos::View<size_t*, execution_space>& numPacketsPerLID,
2051  size_t& constantNumPackets,
2052  Distributor &distor);
2053 
2054  virtual void
2055  unpackAndCombineNew (
2056  const Kokkos::View<const LocalOrdinal*, execution_space>& importLIDs,
2057  const Kokkos::View<const impl_scalar_type*, execution_space>& imports,
2058  const Kokkos::View<size_t*, execution_space>& numPacketsPerLID,
2059  size_t constantNumPackets,
2060  Distributor &distor,
2061  CombineMode CM);
2062 
2063  void createViews () const;
2064  void createViewsNonConst (KokkosClassic::ReadWriteOption rwo);
2065  void releaseViews () const;
2067 
2068  typename dual_view_type::t_dev getKokkosView() const { return view_.d_view; }
2069 
2070  }; // class MultiVector
2071 
2072  namespace Details {
2073 
2074  template<class DstMultiVectorType,
2075  class SrcMultiVectorType>
2076  Teuchos::RCP<typename MultiVectorCloner<DstMultiVectorType, SrcMultiVectorType>::dst_mv_type>
2077  MultiVectorCloner<DstMultiVectorType, SrcMultiVectorType>::
2078  clone (const src_mv_type& X,
2079  const Teuchos::RCP<typename dst_mv_type::node_type>& node2)
2080  {
2081  typedef typename src_mv_type::map_type src_map_type;
2082  typedef typename dst_mv_type::map_type dst_map_type;
2083  typedef typename dst_mv_type::node_type dst_node_type;
2084  typedef typename dst_mv_type::dual_view_type dst_dual_view_type;
2085 
2086  // Clone X's Map to have the new Node type.
2087  RCP<const src_map_type> map1 = X.getMap ();
2088  RCP<const dst_map_type> map2 = map1.is_null () ?
2089  Teuchos::null : map1->template clone<dst_node_type> (node2);
2090 
2091  const size_t lclNumRows = X.getLocalLength ();
2092  const size_t numCols = X.getNumVectors ();
2093  dst_dual_view_type Y_view ("MV::dual_view", lclNumRows, numCols);
2094 
2095  RCP<dst_mv_type> Y (new dst_mv_type (map2, Y_view));
2096  // Let deep_copy do the work for us, to avoid code duplication.
2097  ::Tpetra::deep_copy (Y, X);
2098  return Y ;
2099  }
2100 
2101  } // namespace Details
2102 
2105  template <class ST, class LO, class GO, class NT, const bool classic>
2106  void
2109  {
2110  // NOTE (mfh 11 Sep 2014) We can't implement deep_copy with
2111  // shallow-copy operator=, because that would invalidate existing
2112  // views of dst!
2113  dst.assign (src);
2114  }
2115 
2116  // Implementation of the most generic version of MultiVector deep_copy.
2117  template <class DS, class DL, class DG, class DN, const bool dstClassic,
2118  class SS, class SL, class SG, class SN, const bool srcClassic>
2119  void
2122  {
2123  typedef typename DN::device_type DD;
2124  //typedef typename SN::device_type SD;
2125 
2126  TEUCHOS_TEST_FOR_EXCEPTION(
2127  dst.getGlobalLength () != src.getGlobalLength () ||
2128  dst.getNumVectors () != src.getNumVectors (), std::invalid_argument,
2129  "Tpetra::deep_copy: Global dimensions of the two Tpetra::MultiVector "
2130  "objects do not match. src has dimensions [" << src.getGlobalLength ()
2131  << "," << src.getNumVectors () << "], and dst has dimensions ["
2132  << dst.getGlobalLength () << "," << dst.getNumVectors () << "].");
2133 
2134  // FIXME (mfh 28 Jul 2014) Don't throw; just set a local error flag.
2135  TEUCHOS_TEST_FOR_EXCEPTION(
2136  dst.getLocalLength () != src.getLocalLength (), std::invalid_argument,
2137  "Tpetra::deep_copy: The local row counts of the two Tpetra::MultiVector "
2138  "objects do not match. src has " << src.getLocalLength () << " row(s) "
2139  << " and dst has " << dst.getLocalLength () << " row(s).");
2140 
2141  if (src.isConstantStride () && dst.isConstantStride ()) {
2144 
2145  if (src.getDualView ().modified_device >= src.getDualView ().modified_host) {
2146  // Device memory has the most recent version of src.
2147  dst.template modify<DES> (); // We are about to modify dst on device.
2148  // Copy from src to dst on device.
2149  Details::localDeepCopyConstStride (dst.getDualView ().d_view,
2150  src.getDualView ().d_view);
2151  dst.template sync<HES> (); // Sync dst from device to host.
2152  }
2153  else { // Host memory has the most recent version of src.
2154  dst.template modify<HES> (); // We are about to modify dst on host.
2155  // Copy from src to dst on host.
2156  Details::localDeepCopyConstStride (dst.getDualView ().h_view,
2157  src.getDualView ().h_view);
2158  dst.template sync<DES> (); // Sync dst from host to device.
2159  }
2160  }
2161  else {
2162  typedef Kokkos::DualView<SL*, DD> whichvecs_type;
2163  typedef typename whichvecs_type::t_dev::execution_space DES;
2164  typedef typename whichvecs_type::t_host::execution_space HES;
2165 
2166  if (dst.isConstantStride ()) {
2167  const SL numWhichVecs = static_cast<SL> (src.whichVectors_.size ());
2168  const std::string whichVecsLabel ("MV::deep_copy::whichVecs");
2169 
2170  // We can't sync src, since it is only an input argument.
2171  // Thus, we have to use the most recently modified version of
2172  // src, which coudl be either the device or host version.
2173  if (src.getDualView ().modified_device >= src.getDualView ().modified_host) {
2174  // Copy from the device version of src.
2175  //
2176  // whichVecs tells the kernel which vectors (columns) of src
2177  // to copy. Fill whichVecs on the host, and sync to device.
2178  whichvecs_type whichVecs (whichVecsLabel, numWhichVecs);
2179  whichVecs.template modify<HES> ();
2180  for (SL i = 0; i < numWhichVecs; ++i) {
2181  whichVecs.h_view(i) = static_cast<SL> (src.whichVectors_[i]);
2182  }
2183  // Sync the host version of whichVecs to the device.
2184  whichVecs.template sync<DES> ();
2185 
2186  // Mark the device version of dst's DualView as modified.
2187  dst.template modify<DES> ();
2188  // Copy from the selected vectors of src to dst, on the device.
2189  Details::localDeepCopy (dst.getDualView ().d_view,
2190  src.getDualView ().d_view,
2191  dst.isConstantStride (),
2192  src.isConstantStride (),
2193  whichVecs.d_view,
2194  whichVecs.d_view);
2195  // Sync dst's DualView to the host. This is cheaper than
2196  // repeating the above copy from src to dst on the host.
2197  dst.template sync<HES> ();
2198  }
2199  else { // host version of src was the most recently modified
2200  // Copy from the host version of src.
2201  //
2202  // whichVecs tells the kernel which vectors (columns) of src
2203  // to copy. Fill whichVecs on the host, and use it there.
2204  typedef Kokkos::View<SL*, HES> the_whichvecs_type;
2205  the_whichvecs_type whichVecs (whichVecsLabel, numWhichVecs);
2206  for (SL i = 0; i < numWhichVecs; ++i) {
2207  whichVecs(i) = static_cast<SL> (src.whichVectors_[i]);
2208  }
2209  // Copy from the selected vectors of src to dst, on the
2210  // host. The function ignores the first instance of
2211  // 'whichVecs' in this case.
2212  Details::localDeepCopy (dst.getDualView ().h_view,
2213  src.getDualView ().h_view,
2214  dst.isConstantStride (),
2215  src.isConstantStride (),
2216  whichVecs, whichVecs);
2217  // Sync dst back to the device, since we only copied on the host.
2218  dst.template sync<DES> ();
2219  }
2220  }
2221  else { // dst is NOT constant stride
2222  if (src.isConstantStride ()) {
2223  if (src.getDualView ().modified_device >= src.getDualView ().modified_host) {
2224  // Copy from the device version of src.
2225  //
2226  // whichVecs tells the kernel which vectors (columns) of dst
2227  // to copy. Fill whichVecs on the host, and sync to device.
2228  typedef Kokkos::DualView<DL*, DES> the_whichvecs_type;
2229  const std::string whichVecsLabel ("MV::deep_copy::whichVecs");
2230  const DL numWhichVecs = static_cast<DL> (dst.whichVectors_.size ());
2231  the_whichvecs_type whichVecs (whichVecsLabel, numWhichVecs);
2232  whichVecs.template modify<HES> ();
2233  for (DL i = 0; i < numWhichVecs; ++i) {
2234  whichVecs.h_view(i) = dst.whichVectors_[i];
2235  }
2236  // Sync the host version of whichVecs to the device.
2237  whichVecs.template sync<DES> ();
2238 
2239  // Copy src to the selected vectors of dst, on the device.
2240  Details::localDeepCopy (dst.getDualView ().d_view,
2241  src.getDualView ().d_view,
2242  dst.isConstantStride (),
2243  src.isConstantStride (),
2244  whichVecs.d_view,
2245  whichVecs.d_view);
2246  // We can't sync src and repeat the above copy on the
2247  // host, so sync dst back to the host.
2248  //
2249  // FIXME (mfh 29 Jul 2014) This may overwrite columns that
2250  // don't actually belong to dst's view.
2251  dst.template sync<HES> ();
2252  }
2253  else { // host version of src was the most recently modified
2254  // Copy from the host version of src.
2255  //
2256  // whichVecs tells the kernel which vectors (columns) of src
2257  // to copy. Fill whichVecs on the host, and use it there.
2258  typedef Kokkos::View<DL*, HES> the_whichvecs_type;
2259  const DL numWhichVecs = static_cast<DL> (dst.whichVectors_.size ());
2260  the_whichvecs_type whichVecs ("MV::deep_copy::whichVecs", numWhichVecs);
2261  for (DL i = 0; i < numWhichVecs; ++i) {
2262  whichVecs(i) = static_cast<DL> (dst.whichVectors_[i]);
2263  }
2264  // Copy from src to the selected vectors of dst, on the host.
2265  Details::localDeepCopy (dst.getDualView ().h_view,
2266  src.getDualView ().h_view,
2267  dst.isConstantStride (),
2268  src.isConstantStride (),
2269  whichVecs, whichVecs);
2270  // Sync dst back to the device, since we only copied on the host.
2271  //
2272  // FIXME (mfh 29 Jul 2014) This may overwrite columns that
2273  // don't actually belong to dst's view.
2274  dst.template sync<DES> ();
2275  }
2276  }
2277  else { // neither src nor dst have constant stride
2278  if (src.getDualView ().modified_device >= src.getDualView ().modified_host) {
2279  // Copy from the device version of src.
2280  //
2281  // whichVectorsDst tells the kernel which vectors
2282  // (columns) of dst to copy. Fill it on the host, and
2283  // sync to device.
2284  const DL dstNumWhichVecs = static_cast<DL> (dst.whichVectors_.size ());
2285  Kokkos::DualView<DL*, DES> whichVecsDst ("MV::deep_copy::whichVecsDst",
2286  dstNumWhichVecs);
2287  whichVecsDst.template modify<HES> ();
2288  for (DL i = 0; i < dstNumWhichVecs; ++i) {
2289  whichVecsDst.h_view(i) = static_cast<DL> (dst.whichVectors_[i]);
2290  }
2291  // Sync the host version of whichVecsDst to the device.
2292  whichVecsDst.template sync<DES> ();
2293 
2294  // whichVectorsSrc tells the kernel which vectors
2295  // (columns) of src to copy. Fill it on the host, and
2296  // sync to device. Use the destination MultiVector's
2297  // LocalOrdinal type here.
2298  const DL srcNumWhichVecs = static_cast<DL> (src.whichVectors_.size ());
2299  Kokkos::DualView<DL*, DES> whichVecsSrc ("MV::deep_copy::whichVecsSrc",
2300  srcNumWhichVecs);
2301  whichVecsSrc.template modify<HES> ();
2302  for (DL i = 0; i < srcNumWhichVecs; ++i) {
2303  whichVecsSrc.h_view(i) = static_cast<DL> (src.whichVectors_[i]);
2304  }
2305  // Sync the host version of whichVecsSrc to the device.
2306  whichVecsSrc.template sync<DES> ();
2307 
2308  // Copy from the selected vectors of src to the selected
2309  // vectors of dst, on the device.
2310  Details::localDeepCopy (dst.getDualView ().d_view,
2311  src.getDualView ().d_view,
2312  dst.isConstantStride (),
2313  src.isConstantStride (),
2314  whichVecsDst.d_view,
2315  whichVecsSrc.d_view);
2316  }
2317  else {
2318  const DL dstNumWhichVecs = static_cast<DL> (dst.whichVectors_.size ());
2319  Kokkos::View<DL*, HES> whichVectorsDst ("dstWhichVecs", dstNumWhichVecs);
2320  for (DL i = 0; i < dstNumWhichVecs; ++i) {
2321  whichVectorsDst(i) = dst.whichVectors_[i];
2322  }
2323 
2324  // Use the destination MultiVector's LocalOrdinal type here.
2325  const DL srcNumWhichVecs = static_cast<DL> (src.whichVectors_.size ());
2326  Kokkos::View<DL*, HES> whichVectorsSrc ("srcWhichVecs", srcNumWhichVecs);
2327  for (DL i = 0; i < srcNumWhichVecs; ++i) {
2328  whichVectorsSrc(i) = src.whichVectors_[i];
2329  }
2330 
2331  // Copy from the selected vectors of src to the selected
2332  // vectors of dst, on the host.
2333  Details::localDeepCopy (dst.getDualView ().h_view,
2334  src.getDualView ().h_view,
2335  dst.isConstantStride (),
2336  src.isConstantStride (),
2337  whichVectorsDst, whichVectorsSrc);
2338  // We can't sync src and repeat the above copy on the
2339  // host, so sync dst back to the host.
2340  //
2341  // FIXME (mfh 29 Jul 2014) This may overwrite columns that
2342  // don't actually belong to dst's view.
2343  dst.template sync<HES> ();
2344  }
2345  }
2346  }
2347  }
2348  }
2349 
2350 } // namespace Tpetra
2351 
2352 
2353 namespace Teuchos {
2354 
2355  // Give Teuchos::TypeNameTraits<Tpetra::MultiVector<...> > a
2356  // human-readable definition.
2357  template<class SC, class LO, class GO, class NT, const bool classic>
2358  class TypeNameTraits<Tpetra::MultiVector<SC, LO, GO, NT, classic> > {
2359  public:
2360  static std::string name () {
2361  return std::string ("Tpetra::MultiVector<") +
2362  TypeNameTraits<SC>::name () + "," +
2363  TypeNameTraits<LO>::name () + "," +
2364  TypeNameTraits<GO>::name () + "," +
2365  TypeNameTraits<NT>::name () + ">";
2366  }
2367 
2368  static std::string
2369  concreteName (const Tpetra::MultiVector<SC, LO, GO, NT, classic>&) {
2370  return name ();
2371  }
2372  };
2373 } // namespace Teuchos
2374 
2375 #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.
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...
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)
Like the above replaceGlobalValue, but only enabled if T differs from impl_scalar_type.
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.
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.
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.
std::enable_if<!std::is_same< T, impl_scalar_type >::value &&std::is_convertible< T, impl_scalar_type >::value, void >::type sumIntoGlobalValue(GlobalOrdinal globalRow, size_t col, const T &value)
Like the above sumIntoGlobalValue, but only enabled if T differs from impl_scalar_type.
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)
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.
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)
Like the above sumIntoLocalValue, but only enabled if T differs from impl_scalar_type.
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.