Tpetra parallel linear algebra  Version of the Day
Tpetra_CrsGraph_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_CRSGRAPH_DECL_HPP
43 #define TPETRA_CRSGRAPH_DECL_HPP
44 
52 
53 #include "Tpetra_RowGraph.hpp"
54 #include "Tpetra_DistObject.hpp"
55 #include "Tpetra_Exceptions.hpp"
56 #include "Tpetra_Util.hpp" // need this here for sort2
57 
58 #include "Kokkos_Sparse_findRelOffset.hpp"
59 #include "Kokkos_DualView.hpp"
60 #include "Kokkos_StaticCrsGraph.hpp"
61 
62 #include "Teuchos_Describable.hpp"
63 #include "Teuchos_ParameterListAcceptorDefaultBase.hpp"
64 
65 
66 namespace Tpetra {
67 
68 #ifndef DOXYGEN_SHOULD_SKIP_THIS
69  //
70  // Dear users: These are just forward declarations. Please skip
71  // over them and go down to the CrsMatrix class declaration. Thank
72  // you.
73  //
74  template <class LO, class GO, class N, const bool isClassic>
75  class CrsGraph;
76 
77  // forward declaration (needed for "friend" inside CrsGraph)
78  template <class S, class LO, class GO, class N, const bool isClassic>
79  class CrsMatrix;
80 
81  namespace Experimental {
82  // forward declaration (needed for "friend" inside CrsGraph)
83  template<class S, class LO, class GO, class N>
84  class BlockCrsMatrix;
85  } // namespace Experimental
86 
87  namespace Details {
88  // Forward declaration of an implementation detail of CrsGraph::clone.
89  template<class OutputCrsGraphType, class InputCrsGraphType>
90  class CrsGraphCopier {
91  public:
92  static Teuchos::RCP<OutputCrsGraphType>
93  clone (const InputCrsGraphType& graphIn,
94  const Teuchos::RCP<typename OutputCrsGraphType::node_type> nodeOut,
95  const Teuchos::RCP<Teuchos::ParameterList>& params = Teuchos::null);
96  };
97  } // namespace Details
98 
99  namespace { // (anonymous)
100 
101  template<class ViewType>
102  struct UnmanagedView {
103  static_assert (Kokkos::is_view<ViewType>::value,
104  "ViewType must be a Kokkos::View specialization.");
105  // FIXME (mfh 02 Dec 2015) Right now, this strips away other
106  // memory traits. Christian will add an "AllTraits" enum which is
107  // the enum value of MemoryTraits<T>, that will help us fix this.
108  typedef Kokkos::View<typename ViewType::data_type,
109  typename ViewType::array_layout,
110  typename ViewType::device_type,
111  Kokkos::MemoryUnmanaged> type;
112  };
113 
114  template<class T, class BinaryFunction>
115  T atomic_binary_function_update (volatile T* const dest, const T& inputVal, BinaryFunction f)
116  {
117  T oldVal = *dest;
118  T assume;
119 
120  // NOTE (mfh 30 Nov 2015) I do NOT need a fence here for IBM
121  // POWER architectures, because 'newval' depends on 'assume',
122  // which depends on 'oldVal', which depends on '*dest'. This
123  // sets up a chain of read dependencies that should ensure
124  // correct behavior given a sane memory model.
125  do {
126  assume = oldVal;
127  T newVal = f (assume, inputVal);
128  oldVal = Kokkos::atomic_compare_exchange (dest, assume, newVal);
129  } while (assume != oldVal);
130 
131  return oldVal;
132  }
133 
134  } // namespace (anonymous)
135 #endif // DOXYGEN_SHOULD_SKIP_THIS
136 
145  struct RowInfo {
146  size_t localRow;
147  size_t allocSize;
148  size_t numEntries;
149  size_t offset1D;
150  };
151 
152  enum ELocalGlobal {
153  LocalIndices,
154  GlobalIndices
155  };
156 
157  namespace Details {
198  STORAGE_2D, //<! 2-D storage
199  STORAGE_1D_UNPACKED, //<! 1-D "unpacked" storage
200  STORAGE_1D_PACKED, //<! 1-D "packed" storage
201  STORAGE_UB //<! Invalid value; upper bound on enum values
202  };
203  } // namespace Details
204 
263  template <class LocalOrdinal = ::Tpetra::Details::DefaultTypes::local_ordinal_type,
264  class GlobalOrdinal = ::Tpetra::Details::DefaultTypes::global_ordinal_type,
266  const bool classic = Node::classic>
267  class CrsGraph :
268  public RowGraph<LocalOrdinal, GlobalOrdinal, Node>,
269  public DistObject<GlobalOrdinal,
270  LocalOrdinal,
271  GlobalOrdinal,
272  Node>,
273  public Teuchos::ParameterListAcceptorDefaultBase
274  {
275  static_assert (! classic, "The 'classic' version of Tpetra was deprecated long ago, and has been removed.");
276 
277  template <class S, class LO, class GO, class N, const bool isClassic>
278  friend class CrsMatrix;
279  template <class LO2, class GO2, class N2, const bool isClassic>
280  friend class CrsGraph;
281  template <class S, class LO, class GO, class N>
282  friend class ::Tpetra::Experimental::BlockCrsMatrix;
283 
286 
287  public:
289  typedef LocalOrdinal local_ordinal_type;
291  typedef GlobalOrdinal global_ordinal_type;
293  typedef Node node_type;
294 
296  typedef typename Node::device_type device_type;
298  typedef typename device_type::execution_space execution_space;
299 
301  typedef Kokkos::StaticCrsGraph<LocalOrdinal,
302  Kokkos::LayoutLeft,
303  execution_space> local_graph_type;
305  typedef local_graph_type LocalStaticCrsGraphType TPETRA_DEPRECATED;
306 
308  typedef typename local_graph_type::row_map_type t_RowPtrs TPETRA_DEPRECATED;
310  typedef typename local_graph_type::row_map_type::non_const_type t_RowPtrsNC TPETRA_DEPRECATED;
312  typedef typename local_graph_type::entries_type::non_const_type t_LocalOrdinal_1D TPETRA_DEPRECATED;
313 
320 
322 
323 
342  CrsGraph (const Teuchos::RCP<const map_type>& rowMap,
343  size_t maxNumEntriesPerRow,
344  ProfileType pftype = DynamicProfile,
345  const Teuchos::RCP<Teuchos::ParameterList>& params = Teuchos::null);
346 
364  CrsGraph (const Teuchos::RCP<const map_type>& rowMap,
365  const Kokkos::DualView<const size_t*, execution_space>& numEntPerRow,
366  const ProfileType pftype = DynamicProfile,
367  const Teuchos::RCP<Teuchos::ParameterList>& params = Teuchos::null);
368 
387  CrsGraph (const Teuchos::RCP<const map_type>& rowMap,
388  const Teuchos::ArrayRCP<const size_t>& numEntPerRow,
389  const ProfileType pftype = DynamicProfile,
390  const Teuchos::RCP<Teuchos::ParameterList>& params = Teuchos::null);
391 
413  CrsGraph (const Teuchos::RCP<const map_type>& rowMap,
414  const Teuchos::RCP<const map_type>& colMap,
415  const size_t maxNumEntriesPerRow,
416  const ProfileType pftype = DynamicProfile,
417  const Teuchos::RCP<Teuchos::ParameterList>& params = Teuchos::null);
418 
437  CrsGraph (const Teuchos::RCP<const map_type>& rowMap,
438  const Teuchos::RCP<const map_type>& colMap,
439  const Kokkos::DualView<const size_t*, execution_space>& numEntPerRow,
440  ProfileType pftype = DynamicProfile,
441  const Teuchos::RCP<Teuchos::ParameterList>& params = Teuchos::null);
442 
462  CrsGraph (const Teuchos::RCP<const map_type>& rowMap,
463  const Teuchos::RCP<const map_type>& colMap,
464  const Teuchos::ArrayRCP<const size_t>& numEntPerRow,
465  ProfileType pftype = DynamicProfile,
466  const Teuchos::RCP<Teuchos::ParameterList>& params = Teuchos::null);
467 
487  CrsGraph (const Teuchos::RCP<const map_type>& rowMap,
488  const Teuchos::RCP<const map_type>& colMap,
489  const typename local_graph_type::row_map_type& rowPointers,
490  const typename local_graph_type::entries_type::non_const_type& columnIndices,
491  const Teuchos::RCP<Teuchos::ParameterList>& params = Teuchos::null);
492 
512  CrsGraph (const Teuchos::RCP<const map_type>& rowMap,
513  const Teuchos::RCP<const map_type>& colMap,
514  const Teuchos::ArrayRCP<size_t> & rowPointers,
515  const Teuchos::ArrayRCP<LocalOrdinal> & columnIndices,
516  const Teuchos::RCP<Teuchos::ParameterList>& params = Teuchos::null);
517 
536  CrsGraph (const Teuchos::RCP<const map_type>& rowMap,
537  const Teuchos::RCP<const map_type>& colMap,
538  const local_graph_type& lclGraph,
539  const Teuchos::RCP<Teuchos::ParameterList>& params);
540 
568  template<class Node2>
569  Teuchos::RCP<CrsGraph<LocalOrdinal, GlobalOrdinal, Node2, Node2::classic> >
570  clone (const Teuchos::RCP<Node2>& node2,
571  const Teuchos::RCP<Teuchos::ParameterList>& params = Teuchos::null) const
572  {
574  typedef CrsGraph<LocalOrdinal, GlobalOrdinal, Node, classic> input_crs_graph_type;
575  typedef Details::CrsGraphCopier<output_crs_graph_type, input_crs_graph_type> copier_type;
576  return copier_type::clone (*this, node2, params);
577  }
578 
580  virtual ~CrsGraph();
581 
583 
585 
587  void setParameterList (const Teuchos::RCP<Teuchos::ParameterList>& params);
588 
590  Teuchos::RCP<const Teuchos::ParameterList> getValidParameters () const;
591 
593 
595 
617  void
618  insertGlobalIndices (const GlobalOrdinal globalRow,
619  const Teuchos::ArrayView<const GlobalOrdinal>& indices);
620 
627  void
628  insertGlobalIndices (const GlobalOrdinal globalRow,
629  const LocalOrdinal numEnt,
630  const GlobalOrdinal inds[]);
631 
633 
647  void
648  insertLocalIndices (const LocalOrdinal localRow,
649  const Teuchos::ArrayView<const LocalOrdinal> &indices);
650 
657  void
658  insertLocalIndices (const LocalOrdinal localRow,
659  const LocalOrdinal numEnt,
660  const LocalOrdinal inds[]);
661 
663 
672  void removeLocalIndices (LocalOrdinal localRow);
673 
675 
682 
688  void globalAssemble ();
689 
698  void resumeFill (const Teuchos::RCP<Teuchos::ParameterList>& params = Teuchos::null);
699 
734  void
735  fillComplete (const Teuchos::RCP<const map_type> &domainMap,
736  const Teuchos::RCP<const map_type> &rangeMap,
737  const Teuchos::RCP<Teuchos::ParameterList>& params = Teuchos::null);
738 
763  void
764  fillComplete (const Teuchos::RCP<Teuchos::ParameterList>& params = Teuchos::null);
765 
791  void
792  expertStaticFillComplete (const Teuchos::RCP<const map_type> & domainMap,
793  const Teuchos::RCP<const map_type> & rangeMap,
794  const Teuchos::RCP<const import_type> &importer=Teuchos::null,
795  const Teuchos::RCP<const export_type> &exporter=Teuchos::null,
796  const Teuchos::RCP<Teuchos::ParameterList> &params=Teuchos::null);
798 
800 
802  Teuchos::RCP<const Teuchos::Comm<int> > getComm() const;
803 
805  Teuchos::RCP<node_type> getNode() const;
806 
808  Teuchos::RCP<const map_type> getRowMap () const;
809 
811  Teuchos::RCP<const map_type> getColMap () const;
812 
814  Teuchos::RCP<const map_type> getDomainMap () const;
815 
817  Teuchos::RCP<const map_type> getRangeMap () const;
818 
820  Teuchos::RCP<const import_type> getImporter () const;
821 
823  Teuchos::RCP<const export_type> getExporter () const;
824 
826 
828  global_size_t getGlobalNumRows() const;
829 
831 
834  global_size_t getGlobalNumCols() const;
835 
837  size_t getNodeNumRows() const;
838 
840 
842  size_t getNodeNumCols() const;
843 
845  GlobalOrdinal getIndexBase() const;
846 
848 
850  global_size_t getGlobalNumEntries() const;
851 
853  size_t getNodeNumEntries() const;
854 
856 
857  size_t getNumEntriesInGlobalRow(GlobalOrdinal globalRow) const;
858 
865  size_t getNumEntriesInLocalRow (LocalOrdinal localRow) const;
866 
868 
875  size_t getNodeAllocationSize() const;
876 
878 
879  size_t getNumAllocatedEntriesInGlobalRow(GlobalOrdinal globalRow) const;
880 
882 
883  size_t getNumAllocatedEntriesInLocalRow(LocalOrdinal localRow) const;
884 
886 
888  global_size_t getGlobalNumDiags() const;
889 
891 
893  size_t getNodeNumDiags() const;
894 
907  size_t getGlobalMaxNumRowEntries() const;
908 
910 
912  size_t getNodeMaxNumRowEntries() const;
913 
928  bool hasColMap() const;
929 
937  bool isLowerTriangular() const;
938 
946  bool isUpperTriangular() const;
947 
949  bool isLocallyIndexed() const;
950 
952  bool isGloballyIndexed() const;
953 
955  bool isFillComplete() const;
956 
958  bool isFillActive() const;
959 
967  bool isSorted() const;
968 
970 
976  bool isStorageOptimized() const;
977 
979  ProfileType getProfileType() const;
980 
986  void
987  getGlobalRowCopy (GlobalOrdinal GlobalRow,
988  const Teuchos::ArrayView<GlobalOrdinal>& Indices,
989  size_t& NumIndices) const;
990 
998  void
999  getLocalRowCopy (LocalOrdinal LocalRow,
1000  const Teuchos::ArrayView<LocalOrdinal>& indices,
1001  size_t& NumIndices) const;
1002 
1013  void
1014  getGlobalRowView (const GlobalOrdinal gblRow,
1015  Teuchos::ArrayView<const GlobalOrdinal>& gblColInds) const;
1016 
1019  bool supportsRowViews () const;
1020 
1031  void
1032  getLocalRowView (const LocalOrdinal lclRow,
1033  Teuchos::ArrayView<const LocalOrdinal>& lclColInds) const;
1034 
1036 
1038 
1040  std::string description() const;
1041 
1043  void
1044  describe (Teuchos::FancyOStream& out,
1045  const Teuchos::EVerbosityLevel verbLevel =
1046  Teuchos::Describable::verbLevel_default) const;
1047 
1049 
1051 
1052  virtual bool
1053  checkSizes (const SrcDistObject& source);
1054 
1055  virtual void
1056  copyAndPermute (const SrcDistObject& source,
1057  size_t numSameIDs,
1058  const Teuchos::ArrayView<const LocalOrdinal> &permuteToLIDs,
1059  const Teuchos::ArrayView<const LocalOrdinal> &permuteFromLIDs);
1060 
1061  virtual void
1062  packAndPrepare (const SrcDistObject& source,
1063  const Teuchos::ArrayView<const LocalOrdinal> &exportLIDs,
1064  Teuchos::Array<GlobalOrdinal> &exports,
1065  const Teuchos::ArrayView<size_t> & numPacketsPerLID,
1066  size_t& constantNumPackets,
1067  Distributor &distor);
1068 
1069  virtual void
1070  pack (const Teuchos::ArrayView<const LocalOrdinal>& exportLIDs,
1071  Teuchos::Array<GlobalOrdinal>& exports,
1072  const Teuchos::ArrayView<size_t>& numPacketsPerLID,
1073  size_t& constantNumPackets,
1074  Distributor& distor) const;
1075 
1076  virtual void
1077  unpackAndCombine (const Teuchos::ArrayView<const LocalOrdinal> &importLIDs,
1078  const Teuchos::ArrayView<const GlobalOrdinal> &imports,
1079  const Teuchos::ArrayView<size_t> &numPacketsPerLID,
1080  size_t constantNumPackets,
1081  Distributor &distor,
1082  CombineMode CM);
1084 
1086 
1129  void
1130  getLocalDiagOffsets (const Kokkos::View<size_t*, device_type, Kokkos::MemoryUnmanaged>& offsets) const;
1131 
1141  void
1142  getLocalDiagOffsets (Teuchos::ArrayRCP<size_t>& offsets) const;
1143 
1166  void
1167  getNumEntriesPerLocalRowUpperBound (Teuchos::ArrayRCP<const size_t>& boundPerLocalRow,
1168  size_t& boundForAllLocalRows,
1169  bool& boundSameForAllLocalRows) const;
1170 
1179  void
1180  setAllIndices (const typename local_graph_type::row_map_type& rowPointers,
1181  const typename local_graph_type::entries_type::non_const_type& columnIndices);
1182 
1191  void
1192  setAllIndices (const Teuchos::ArrayRCP<size_t> & rowPointers,
1193  const Teuchos::ArrayRCP<LocalOrdinal> & columnIndices);
1194 
1202  Teuchos::ArrayRCP<const size_t> getNodeRowPtrs () const;
1203 
1205 
1207  Teuchos::ArrayRCP<const LocalOrdinal> getNodePackedIndices() const;
1208 
1219  void replaceColMap (const Teuchos::RCP<const map_type>& newColMap);
1220 
1240  void
1241  reindexColumns (const Teuchos::RCP<const map_type>& newColMap,
1242  const Teuchos::RCP<const import_type>& newImport = Teuchos::null,
1243  const bool sortIndicesInEachRow = true);
1244 
1258  void
1259  replaceDomainMapAndImporter (const Teuchos::RCP<const map_type>& newDomainMap,
1260  const Teuchos::RCP<const import_type>& newImporter);
1261 
1290  virtual void
1291  removeEmptyProcessesInPlace (const Teuchos::RCP<const map_type>& newMap);
1293 
1294  template<class ViewType, class OffsetViewType >
1295  struct pack_functor {
1296  typedef typename ViewType::execution_space execution_space;
1297  ViewType src;
1298  ViewType dest;
1299  OffsetViewType src_offset;
1300  OffsetViewType dest_offset;
1301  typedef typename OffsetViewType::non_const_value_type ScalarIndx;
1302 
1303  pack_functor(ViewType dest_, ViewType src_, OffsetViewType dest_offset_, OffsetViewType src_offset_):
1304  src(src_),dest(dest_),src_offset(src_offset_),dest_offset(dest_offset_) {};
1305 
1306  KOKKOS_INLINE_FUNCTION
1307  void operator() (size_t row) const {
1308  ScalarIndx i = src_offset(row);
1309  ScalarIndx j = dest_offset(row);
1310  const ScalarIndx k = dest_offset(row+1);
1311  for(;j<k;j++,i++) {
1312  dest(j) = src(i);
1313  }
1314  }
1315  };
1316 
1317  protected:
1318  // these structs are conveniences, to cut down on the number of
1319  // arguments to some of the methods below.
1320  struct SLocalGlobalViews {
1321  Teuchos::ArrayView<const GlobalOrdinal> ginds;
1322  Teuchos::ArrayView<const LocalOrdinal> linds;
1323  };
1324  struct SLocalGlobalNCViews {
1325  Teuchos::ArrayView<GlobalOrdinal> ginds;
1326  Teuchos::ArrayView<LocalOrdinal> linds;
1327  };
1328 
1329  bool indicesAreAllocated () const;
1330  void allocateIndices (const ELocalGlobal lg);
1331 
1332  template <class T>
1333  Teuchos::ArrayRCP<Teuchos::Array<T> > allocateValues2D () const
1334  {
1335  using Teuchos::arcp;
1336  using Teuchos::Array;
1337  using Teuchos::ArrayRCP;
1338  using Teuchos::null;
1339  const char tfecfFuncName[] = "allocateValues2D: ";
1340 
1341  TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1342  (! indicesAreAllocated (), std::runtime_error,
1343  "Graph indices must be allocated before values.");
1344  TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1345  (getProfileType () != DynamicProfile, std::runtime_error,
1346  "Graph indices must be allocated in a dynamic profile.");
1347 
1348  ArrayRCP<Array<T> > values2D;
1349  values2D = arcp<Array<T> > (getNodeNumRows ());
1350  if (lclInds2D_ != null) {
1351  const size_t numRows = lclInds2D_.size ();
1352  for (size_t r = 0; r < numRows; ++r) {
1353  values2D[r].resize (lclInds2D_[r].size ());
1354  }
1355  }
1356  else if (gblInds2D_ != null) {
1357  const size_t numRows = gblInds2D_.size ();
1358  for (size_t r = 0; r < numRows; ++r) {
1359  values2D[r].resize (gblInds2D_[r].size ());
1360  }
1361  }
1362  return values2D;
1363  }
1364 
1365  template <class T>
1366  RowInfo updateLocalAllocAndValues (const RowInfo rowInfo,
1367  const size_t newAllocSize,
1368  Teuchos::Array<T>& rowVals)
1369  {
1370 #ifdef HAVE_TPETRA_DEBUG
1371  TEUCHOS_TEST_FOR_EXCEPT( ! isLocallyIndexed () );
1372  TEUCHOS_TEST_FOR_EXCEPT( ! indicesAreAllocated() );
1373  TEUCHOS_TEST_FOR_EXCEPT( newAllocSize == 0 );
1374  TEUCHOS_TEST_FOR_EXCEPT( newAllocSize < rowInfo.allocSize );
1375  TEUCHOS_TEST_FOR_EXCEPT( ! rowMap_->isNodeLocalElement (rowInfo.localRow) );
1376 #endif // HAVE_TPETRA_DEBUG
1377 
1378  // Teuchos::ArrayRCP::resize automatically copies over values on reallocation.
1379  lclInds2D_[rowInfo.localRow].resize (newAllocSize);
1380  rowVals.resize (newAllocSize);
1381 
1382  RowInfo rowInfoOut = rowInfo;
1383  rowInfoOut.allocSize = newAllocSize;
1384  return rowInfoOut;
1385  }
1386 
1387  template <class T>
1388  RowInfo
1389  updateGlobalAllocAndValues (const RowInfo rowInfo,
1390  const size_t newAllocSize,
1391  Teuchos::Array<T>& rowVals)
1392  {
1393 #ifdef HAVE_TPETRA_DEBUG
1394  TEUCHOS_TEST_FOR_EXCEPT( ! isGloballyIndexed () );
1395  TEUCHOS_TEST_FOR_EXCEPT( ! indicesAreAllocated () );
1396  TEUCHOS_TEST_FOR_EXCEPT( newAllocSize == 0 );
1397  TEUCHOS_TEST_FOR_EXCEPT( newAllocSize < rowInfo.allocSize );
1398  TEUCHOS_TEST_FOR_EXCEPT( ! rowMap_->isNodeLocalElement (rowInfo.localRow) );
1399 #endif // HAVE_TPETRA_DEBUG
1400 
1401  // Teuchos::ArrayRCP::resize automatically copies over values on reallocation.
1402  gblInds2D_[rowInfo.localRow].resize (newAllocSize);
1403  rowVals.resize (newAllocSize);
1404 
1405  RowInfo rowInfoOut = rowInfo;
1406  rowInfoOut.allocSize = newAllocSize;
1407  return rowInfoOut;
1408  }
1409 
1411 
1412 
1418  void makeColMap ();
1419 
1420  void makeIndicesLocal ();
1421  void makeImportExport ();
1422 
1424 
1426 
1427  template<ELocalGlobal lg>
1428  size_t filterIndices (const SLocalGlobalNCViews& inds) const
1429  {
1430  using Teuchos::ArrayView;
1431  static_assert (lg == GlobalIndices || lg == LocalIndices,
1432  "Tpetra::CrsGraph::filterIndices: The template parameter "
1433  "lg must be either GlobalIndices or LocalIndicies.");
1434 
1435  const map_type& cmap = *colMap_;
1436  size_t numFiltered = 0;
1437 #ifdef HAVE_TPETRA_DEBUG
1438  size_t numFiltered_debug = 0;
1439 #endif
1440  if (lg == GlobalIndices) {
1441  ArrayView<GlobalOrdinal> ginds = inds.ginds;
1442  typename ArrayView<GlobalOrdinal>::iterator fend = ginds.begin();
1443  typename ArrayView<GlobalOrdinal>::iterator cptr = ginds.begin();
1444  while (cptr != ginds.end()) {
1445  if (cmap.isNodeGlobalElement(*cptr)) {
1446  *fend++ = *cptr;
1447 #ifdef HAVE_TPETRA_DEBUG
1448  ++numFiltered_debug;
1449 #endif
1450  }
1451  ++cptr;
1452  }
1453  numFiltered = fend - ginds.begin();
1454  }
1455  else if (lg == LocalIndices) {
1456  ArrayView<LocalOrdinal> linds = inds.linds;
1457  typename ArrayView<LocalOrdinal>::iterator fend = linds.begin();
1458  typename ArrayView<LocalOrdinal>::iterator cptr = linds.begin();
1459  while (cptr != linds.end()) {
1460  if (cmap.isNodeLocalElement(*cptr)) {
1461  *fend++ = *cptr;
1462 #ifdef HAVE_TPETRA_DEBUG
1463  ++numFiltered_debug;
1464 #endif
1465  }
1466  ++cptr;
1467  }
1468  numFiltered = fend - linds.begin();
1469  }
1470 #ifdef HAVE_TPETRA_DEBUG
1471  TEUCHOS_TEST_FOR_EXCEPT( numFiltered != numFiltered_debug );
1472 #endif
1473  return numFiltered;
1474  }
1475 
1476 
1477  template<class T>
1478  size_t
1479  filterGlobalIndicesAndValues (const Teuchos::ArrayView<GlobalOrdinal>& ginds,
1480  const Teuchos::ArrayView<T>& vals) const
1481  {
1482  using Teuchos::ArrayView;
1483  const map_type& cmap = *colMap_;
1484  size_t numFiltered = 0;
1485  typename ArrayView<T>::iterator fvalsend = vals.begin();
1486  typename ArrayView<T>::iterator valscptr = vals.begin();
1487 #ifdef HAVE_TPETRA_DEBUG
1488  size_t numFiltered_debug = 0;
1489 #endif
1490  typename ArrayView<GlobalOrdinal>::iterator fend = ginds.begin();
1491  typename ArrayView<GlobalOrdinal>::iterator cptr = ginds.begin();
1492  while (cptr != ginds.end()) {
1493  if (cmap.isNodeGlobalElement (*cptr)) {
1494  *fend++ = *cptr;
1495  *fvalsend++ = *valscptr;
1496 #ifdef HAVE_TPETRA_DEBUG
1497  ++numFiltered_debug;
1498 #endif
1499  }
1500  ++cptr;
1501  ++valscptr;
1502  }
1503  numFiltered = fend - ginds.begin();
1504 #ifdef HAVE_TPETRA_DEBUG
1505  TEUCHOS_TEST_FOR_EXCEPT( numFiltered != numFiltered_debug );
1506  TEUCHOS_TEST_FOR_EXCEPT( valscptr != vals.end() );
1507  const size_t numFilteredActual =
1508  static_cast<size_t> (fvalsend - vals.begin ());
1509  TEUCHOS_TEST_FOR_EXCEPT( numFiltered != numFilteredActual );
1510 #endif // HAVE_TPETRA_DEBUG
1511  return numFiltered;
1512  }
1513 
1514  template<class T>
1515  size_t
1516  filterLocalIndicesAndValues (const Teuchos::ArrayView<LocalOrdinal>& linds,
1517  const Teuchos::ArrayView<T>& vals) const
1518  {
1519  using Teuchos::ArrayView;
1520  const map_type& cmap = *colMap_;
1521  size_t numFiltered = 0;
1522  typename ArrayView<T>::iterator fvalsend = vals.begin();
1523  typename ArrayView<T>::iterator valscptr = vals.begin();
1524 #ifdef HAVE_TPETRA_DEBUG
1525  size_t numFiltered_debug = 0;
1526 #endif
1527  typename ArrayView<LocalOrdinal>::iterator fend = linds.begin();
1528  typename ArrayView<LocalOrdinal>::iterator cptr = linds.begin();
1529  while (cptr != linds.end()) {
1530  if (cmap.isNodeLocalElement (*cptr)) {
1531  *fend++ = *cptr;
1532  *fvalsend++ = *valscptr;
1533 #ifdef HAVE_TPETRA_DEBUG
1534  ++numFiltered_debug;
1535 #endif
1536  }
1537  ++cptr;
1538  ++valscptr;
1539  }
1540  numFiltered = fend - linds.begin();
1541 #ifdef HAVE_TPETRA_DEBUG
1542  TEUCHOS_TEST_FOR_EXCEPT( numFiltered != numFiltered_debug );
1543  TEUCHOS_TEST_FOR_EXCEPT( valscptr != vals.end() );
1544  const size_t numFilteredActual =
1545  Teuchos::as<size_t> (fvalsend - vals.begin ());
1546  TEUCHOS_TEST_FOR_EXCEPT( numFiltered != numFilteredActual );
1547 #endif
1548  return numFiltered;
1549  }
1550 
1580  size_t
1581  insertIndices (const RowInfo& rowInfo,
1582  const SLocalGlobalViews& newInds,
1583  const ELocalGlobal lg,
1584  const ELocalGlobal I);
1585 
1625  template<class Scalar>
1626  void
1628  const SLocalGlobalViews& newInds,
1629  const Teuchos::ArrayView<Scalar>& oldRowVals,
1630  const Teuchos::ArrayView<const Scalar>& newRowVals,
1631  const ELocalGlobal lg,
1632  const ELocalGlobal I)
1633  {
1634 #ifdef HAVE_TPETRA_DEBUG
1635  const char tfecfFuncName[] = "insertIndicesAndValues: ";
1636 #endif // HAVE_TPETRA_DEBUG
1637 
1638 #ifdef HAVE_TPETRA_DEBUG
1639  size_t numNewInds = 0;
1640  try {
1641  numNewInds = insertIndices (rowInfo, newInds, lg, I);
1642  } catch (std::exception& e) {
1643  TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1644  (true, std::runtime_error, "insertIndices threw an exception: "
1645  << e.what ());
1646  }
1647  TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1648  (numNewInds > static_cast<size_t> (oldRowVals.size ()),
1649  std::runtime_error, "numNewInds (" << numNewInds << ") > "
1650  "oldRowVals.size() (" << oldRowVals.size () << ".");
1651 #else
1652  const size_t numNewInds = insertIndices (rowInfo, newInds, lg, I);
1653 #endif // HAVE_TPETRA_DEBUG
1654 
1655  typedef typename Teuchos::ArrayView<Scalar>::size_type size_type;
1656 
1657 #ifdef HAVE_TPETRA_DEBUG
1658  TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1659  (rowInfo.numEntries + numNewInds > static_cast<size_t> (oldRowVals.size ()),
1660  std::runtime_error, "rowInfo.numEntries (" << rowInfo.numEntries << ")"
1661  " + numNewInds (" << numNewInds << ") > oldRowVals.size() ("
1662  << oldRowVals.size () << ").");
1663  TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1664  (static_cast<size_type> (numNewInds) > newRowVals.size (),
1665  std::runtime_error, "numNewInds (" << numNewInds << ") > "
1666  "newRowVals.size() (" << newRowVals.size () << ").");
1667 #endif // HAVE_TPETRA_DEBUG
1668 
1669  size_type oldInd = static_cast<size_type> (rowInfo.numEntries);
1670 
1671 #ifdef HAVE_TPETRA_DEBUG
1672  try {
1673 #endif // HAVE_TPETRA_DEBUG
1674  //NOTE: The code in the else branch fails on GCC 4.9 and newer in the assignement oldRowVals[oldInd] = newRowVals[newInd];
1675  //We supply a workaround n as well as other code variants which produce or not produce the error
1676 #if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)
1677 #define GCC_VERSION __GNUC__*100+__GNUC_MINOR__*10+__GNUC_PATCHLEVEL__
1678 #if GCC_VERSION >= 490
1679 #define GCC_WORKAROUND
1680 #endif
1681 #endif
1682 #ifdef GCC_WORKAROUND
1683  size_type nNI = static_cast<size_type>(numNewInds);
1684  if (nNI > 0)
1685  memcpy(&oldRowVals[oldInd], &newRowVals[0], nNI*sizeof(Scalar));
1686  /*
1687  //Original Code Fails
1688  for (size_type newInd = 0; newInd < static_cast<size_type> (numNewInds);
1689  ++newInd, ++oldInd) {
1690  oldRowVals[oldInd] = newRowVals[newInd];
1691  }
1692 
1693  //char cast variant fails
1694  char* oldRowValPtr = (char*)&oldRowVals[oldInd];
1695  const char* newRowValPtr = (const char*) &newRowVals[0];
1696 
1697  for(size_type newInd = 0; newInd < (nNI * sizeof(Scalar)); newInd++) {
1698  oldRowValPtr[newInd] = newRowValPtr[newInd];
1699  }
1700 
1701  //Raw ptr variant fails
1702  Scalar* oldRowValPtr = &oldRowVals[oldInd];
1703  Scalar* newRowValPtr = const_cast<Scalar*>(&newRowVals[0]);
1704 
1705  for(size_type newInd = 0; newInd < nNI; newInd++) {
1706  oldRowValPtr[newInd] = newRowValPtr[newInd];
1707  }
1708 
1709  //memcpy works
1710  for (size_type newInd = 0; newInd < nNI; newInd++) {
1711  memcpy( &oldRowVals[oldInd+newInd], &newRowVals[newInd], sizeof(Scalar));
1712  }
1713 
1714  //just one loop index fails
1715  for (size_type newInd = 0; newInd < nNI; newInd++) {
1716  oldRowVals[oldInd+newInd] = newRowVals[newInd];
1717  }
1718 
1719  //inline increment fails
1720  for (size_type newInd = 0; newInd < numNewInds;) {
1721  oldRowVals[oldInd++] = newRowVals[newInd++];
1722  }
1723 
1724  */
1725 
1726 #else // GCC Workaround above
1727  for (size_type newInd = 0; newInd < static_cast<size_type> (numNewInds);
1728  ++newInd, ++oldInd) {
1729  oldRowVals[oldInd] = newRowVals[newInd];
1730  }
1731 #endif // GCC Workaround
1732 #ifdef HAVE_TPETRA_DEBUG
1733  }
1734  catch (std::exception& e) {
1735  TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1736  (true, std::runtime_error, "for loop for copying values threw an "
1737  "exception: " << e.what ());
1738  }
1739 #endif // HAVE_TPETRA_DEBUG
1740  }
1741 
1742  void
1743  insertGlobalIndicesImpl (const LocalOrdinal myRow,
1744  const Teuchos::ArrayView<const GlobalOrdinal> &indices);
1745  void
1746  insertLocalIndicesImpl (const LocalOrdinal myRow,
1747  const Teuchos::ArrayView<const LocalOrdinal> &indices);
1749  void
1750  insertLocalIndicesFiltered (const LocalOrdinal localRow,
1751  const Teuchos::ArrayView<const LocalOrdinal> &indices);
1752 
1754  void
1755  insertGlobalIndicesFiltered (const GlobalOrdinal localRow,
1756  const Teuchos::ArrayView<const GlobalOrdinal> &indices);
1757 
1762  static const bool useAtomicUpdatesByDefault =
1763 #ifdef KOKKOS_HAVE_SERIAL
1764  ! std::is_same<execution_space, Kokkos::Serial>::value;
1765 #else
1766  true;
1767 #endif // KOKKOS_HAVE_SERIAL
1768 
1807  template<class OutputScalarViewType,
1808  class LocalIndicesViewType,
1809  class InputScalarViewType,
1810  class BinaryFunction>
1811  LocalOrdinal
1813  const typename UnmanagedView<OutputScalarViewType>::type& rowVals,
1814  const typename UnmanagedView<LocalIndicesViewType>::type& inds,
1815  const typename UnmanagedView<InputScalarViewType>::type& newVals,
1816  BinaryFunction f,
1817  const bool atomic = useAtomicUpdatesByDefault) const
1818  {
1819  // We use static_assert here to check the template parameters,
1820  // rather than std::enable_if (e.g., on the return value, to
1821  // enable compilation only if the template parameters match the
1822  // desired attributes). This turns obscure link errors into
1823  // clear compilation errors. It also makes the return value a
1824  // lot easier to see.
1825  static_assert (Kokkos::is_view<OutputScalarViewType>::value,
1826  "Template parameter OutputScalarViewType must be "
1827  "a Kokkos::View.");
1828  static_assert (Kokkos::is_view<LocalIndicesViewType>::value,
1829  "Template parameter LocalIndicesViewType must be "
1830  "a Kokkos::View.");
1831  static_assert (Kokkos::is_view<InputScalarViewType>::value,
1832  "Template parameter InputScalarViewType must be a "
1833  "Kokkos::View.");
1834  static_assert (static_cast<int> (OutputScalarViewType::rank) == 1,
1835  "Template parameter OutputScalarViewType must "
1836  "have rank 1.");
1837  static_assert (static_cast<int> (LocalIndicesViewType::rank) == 1,
1838  "Template parameter LocalIndicesViewType must "
1839  "have rank 1.");
1840  static_assert (static_cast<int> (InputScalarViewType::rank) == 1,
1841  "Template parameter InputScalarViewType must have "
1842  "rank 1.");
1843  static_assert (std::is_same<
1844  typename OutputScalarViewType::non_const_value_type,
1845  typename InputScalarViewType::non_const_value_type>::value,
1846  "Template parameters OutputScalarViewType and "
1847  "InputScalarViewType must contain values of the same "
1848  "type.");
1849  static_assert (std::is_same<
1850  typename LocalIndicesViewType::non_const_value_type,
1851  local_ordinal_type>::value,
1852  "Template parameter LocalIndicesViewType must "
1853  "contain values of type local_ordinal_type.");
1854 
1855  typedef typename OutputScalarViewType::non_const_value_type ST;
1856  typedef LocalOrdinal LO;
1857  typedef GlobalOrdinal GO;
1858 
1859  if (newVals.dimension_0 () != inds.dimension_0 ()) {
1860  // The sizes of the input arrays must match.
1861  return Teuchos::OrdinalTraits<LO>::invalid ();
1862  }
1863  const LO numElts = static_cast<LO> (inds.dimension_0 ());
1864  const bool sorted = this->isSorted ();
1865 
1866  LO numValid = 0; // number of valid input column indices
1867  size_t hint = 0; // Guess for the current index k into rowVals
1868 
1869  if (isLocallyIndexed ()) {
1870  // Get a view of the column indices in the row. This amortizes
1871  // the cost of getting the view over all the entries of inds.
1872  auto colInds = this->getLocalKokkosRowView (rowInfo);
1873 
1874  for (LO j = 0; j < numElts; ++j) {
1875  const LO lclColInd = inds(j);
1876  const size_t offset =
1877  KokkosSparse::findRelOffset (colInds, rowInfo.numEntries,
1878  lclColInd, hint, sorted);
1879  if (offset != rowInfo.numEntries) {
1880  if (atomic) {
1881  // NOTE (mfh 30 Nov 2015) The commented-out code is
1882  // wrong because another thread may have changed
1883  // rowVals(offset) between those two lines of code.
1884  //
1885  //const ST newVal = f (rowVals(offset), newVals(j));
1886  //Kokkos::atomic_assign (&rowVals(offset), newVal);
1887 
1888  volatile ST* const dest = &rowVals(offset);
1889  (void) atomic_binary_function_update (dest, newVals(j), f);
1890  }
1891  else {
1892  // use binary function f
1893  rowVals(offset) = f (rowVals(offset), newVals(j));
1894  }
1895  hint = offset + 1;
1896  ++numValid;
1897  }
1898  }
1899  }
1900  else if (isGloballyIndexed ()) {
1901  // NOTE (mfh 26 Nov 2015) Dereferencing an RCP or reading its
1902  // pointer does NOT change its reference count. Thus, this
1903  // code is still thread safe.
1904  if (colMap_.is_null ()) {
1905  // NO input column indices are valid in this case. Either
1906  // the column Map hasn't been set yet (so local indices
1907  // don't exist yet), or the calling process owns no graph
1908  // entries.
1909  return numValid;
1910  }
1911  const map_type& colMap = *colMap_;
1912  // Get a view of the column indices in the row. This amortizes
1913  // the cost of getting the view over all the entries of inds.
1914  auto colInds = this->getGlobalKokkosRowView (rowInfo);
1915 
1916  const GO GINV = Teuchos::OrdinalTraits<GO>::invalid ();
1917  for (LO j = 0; j < numElts; ++j) {
1918  const GO gblColInd = colMap.getGlobalElement (inds(j));
1919  if (gblColInd != GINV) {
1920  const size_t offset =
1921  KokkosSparse::findRelOffset (colInds, rowInfo.numEntries,
1922  gblColInd, hint, sorted);
1923  if (offset != rowInfo.numEntries) {
1924  if (atomic) {
1925  // NOTE (mfh 30 Nov 2015) The commented-out code is
1926  // wrong because another thread may have changed
1927  // rowVals(offset) between those two lines of code.
1928  //
1929  //const ST newVal = f (rowVals(offset), newVals(j));
1930  //Kokkos::atomic_assign (&rowVals(offset), newVal);
1931 
1932  volatile ST* const dest = &rowVals(offset);
1933  (void) atomic_binary_function_update (dest, newVals(j), f);
1934  }
1935  else {
1936  // use binary function f
1937  rowVals(offset) = f (rowVals(offset), newVals(j));
1938  }
1939  hint = offset + 1;
1940  numValid++;
1941  }
1942  }
1943  }
1944  }
1945  // If the graph is neither locally nor globally indexed on the
1946  // calling process, that means the calling process has no graph
1947  // entries. Thus, none of the input column indices are valid.
1948 
1949  return numValid;
1950  }
1951 
1973  template<class OutputScalarViewType,
1974  class LocalIndicesViewType,
1975  class InputScalarViewType>
1976  LocalOrdinal
1977  sumIntoLocalValues (const RowInfo& rowInfo,
1978  const typename UnmanagedView<OutputScalarViewType>::type& rowVals,
1979  const typename UnmanagedView<LocalIndicesViewType>::type& inds,
1980  const typename UnmanagedView<InputScalarViewType>::type& newVals,
1981  const bool atomic = useAtomicUpdatesByDefault) const
1982  {
1983  // We use static_assert here to check the template parameters,
1984  // rather than std::enable_if (e.g., on the return value, to
1985  // enable compilation only if the template parameters match the
1986  // desired attributes). This turns obscure link errors into
1987  // clear compilation errors. It also makes the return value a
1988  // lot easier to see.
1989  static_assert (Kokkos::is_view<OutputScalarViewType>::value,
1990  "Template parameter OutputScalarViewType must be "
1991  "a Kokkos::View.");
1992  static_assert (Kokkos::is_view<LocalIndicesViewType>::value,
1993  "Template parameter LocalIndicesViewType must be "
1994  "a Kokkos::View.");
1995  static_assert (Kokkos::is_view<InputScalarViewType>::value,
1996  "Template parameter InputScalarViewType must be a "
1997  "Kokkos::View.");
1998  static_assert (static_cast<int> (OutputScalarViewType::rank) == 1,
1999  "Template parameter OutputScalarViewType must "
2000  "have rank 1.");
2001  static_assert (static_cast<int> (LocalIndicesViewType::rank) == 1,
2002  "Template parameter LocalIndicesViewType must "
2003  "have rank 1.");
2004  static_assert (static_cast<int> (InputScalarViewType::rank) == 1,
2005  "Template parameter InputScalarViewType must have "
2006  "rank 1.");
2007  static_assert (std::is_same<
2008  typename OutputScalarViewType::non_const_value_type,
2009  typename InputScalarViewType::non_const_value_type>::value,
2010  "Template parameters OutputScalarViewType and "
2011  "InputScalarViewType must contain values of the same "
2012  "type.");
2013  static_assert (std::is_same<
2014  typename LocalIndicesViewType::non_const_value_type,
2015  local_ordinal_type>::value,
2016  "Template parameter LocalIndicesViewType must "
2017  "contain values of type local_ordinal_type.");
2018 
2019  typedef LocalOrdinal LO;
2020  typedef GlobalOrdinal GO;
2021 
2022  // Don't call this->hasColMap(), because that changes RCP's
2023  // reference count, which is not thread safe. Just
2024  // dereferencing an RCP or calling RCP::is_null() does not
2025  // change its reference count.
2026  if (colMap_.is_null ()) {
2027  // No such thing as local column indices without a column Map.
2028  return Teuchos::OrdinalTraits<LO>::invalid ();
2029  }
2030  else if (newVals.dimension_0 () != inds.dimension_0 ()) {
2031  // The dimensions of the input arrays must match.
2032  return Teuchos::OrdinalTraits<LO>::invalid ();
2033  }
2034 
2035  const bool sorted = this->isSorted ();
2036 
2037  size_t hint = 0; // Guess for the current index k into rowVals
2038  LO numValid = 0; // number of valid local column indices
2039 
2040  // NOTE (mfh 11 Oct 2015) This method assumes UVM. More
2041  // accurately, it assumes that the host execution space can
2042  // access data in both InputMemorySpace and ValsMemorySpace.
2043 
2044  if (isLocallyIndexed ()) {
2045  // Get a view of the column indices in the row. This amortizes
2046  // the cost of getting the view over all the entries of inds.
2047  auto colInds = this->getLocalKokkosRowView (rowInfo);
2048 
2049  const LO numElts = static_cast<LO> (inds.dimension_0 ());
2050  for (LO j = 0; j < numElts; ++j) {
2051  const LO lclColInd = inds(j);
2052  const size_t offset =
2053  KokkosSparse::findRelOffset (colInds, rowInfo.numEntries,
2054  lclColInd, hint, sorted);
2055  if (offset != rowInfo.numEntries) {
2056  if (atomic) {
2057  Kokkos::atomic_add (&rowVals(offset), newVals(j));
2058  }
2059  else {
2060  rowVals(offset) += newVals(j);
2061  }
2062  hint = offset + 1;
2063  ++numValid;
2064  }
2065  }
2066  }
2067  else if (isGloballyIndexed ()) {
2068  // Get a view of the column indices in the row. This amortizes
2069  // the cost of getting the view over all the entries of inds.
2070  auto colInds = this->getGlobalKokkosRowView (rowInfo);
2071 
2072  const LO numElts = static_cast<LO> (inds.dimension_0 ());
2073  for (LO j = 0; j < numElts; ++j) {
2074  const GO gblColInd = this->colMap_->getGlobalElement (inds(j));
2075  if (gblColInd != Teuchos::OrdinalTraits<GO>::invalid ()) {
2076  const size_t offset =
2077  KokkosSparse::findRelOffset (colInds, rowInfo.numEntries,
2078  gblColInd, hint, sorted);
2079  if (offset != rowInfo.numEntries) {
2080  if (atomic) {
2081  Kokkos::atomic_add (&rowVals(offset), newVals(j));
2082  }
2083  else {
2084  rowVals(offset) += newVals(j);
2085  }
2086  hint = offset + 1;
2087  ++numValid;
2088  }
2089  }
2090  }
2091  }
2092  // NOTE (mfh 26 Jun 2014, 26 Nov 2015) In the current version of
2093  // CrsGraph and CrsMatrix, it's possible for a matrix (or graph)
2094  // to be neither locally nor globally indexed on a process.
2095  // This means that the graph or matrix has no entries on that
2096  // process. Epetra also works like this. It's related to lazy
2097  // allocation (on first insertion, not at graph / matrix
2098  // construction). Lazy allocation will go away because it is
2099  // not thread scalable.
2100 
2101  return numValid;
2102  }
2103 
2128  template<class OutputScalarViewType,
2129  class LocalIndicesViewType,
2130  class InputScalarViewType>
2131  LocalOrdinal
2132  replaceLocalValues (const RowInfo& rowInfo,
2133  const typename UnmanagedView<OutputScalarViewType>::type& rowVals,
2134  const typename UnmanagedView<LocalIndicesViewType>::type& inds,
2135  const typename UnmanagedView<InputScalarViewType>::type& newVals) const
2136  {
2137  // We use static_assert here to check the template parameters,
2138  // rather than std::enable_if (e.g., on the return value, to
2139  // enable compilation only if the template parameters match the
2140  // desired attributes). This turns obscure link errors into
2141  // clear compilation errors. It also makes the return value a
2142  // lot easier to see.
2143  static_assert (Kokkos::is_view<OutputScalarViewType>::value,
2144  "Template parameter OutputScalarViewType must be "
2145  "a Kokkos::View.");
2146  static_assert (Kokkos::is_view<LocalIndicesViewType>::value,
2147  "Template parameter LocalIndicesViewType must be "
2148  "a Kokkos::View.");
2149  static_assert (Kokkos::is_view<InputScalarViewType>::value,
2150  "Template parameter InputScalarViewType must be a "
2151  "Kokkos::View.");
2152  static_assert (static_cast<int> (OutputScalarViewType::rank) == 1,
2153  "Template parameter OutputScalarViewType must "
2154  "have rank 1.");
2155  static_assert (static_cast<int> (LocalIndicesViewType::rank) == 1,
2156  "Template parameter LocalIndicesViewType must "
2157  "have rank 1.");
2158  static_assert (static_cast<int> (InputScalarViewType::rank) == 1,
2159  "Template parameter InputScalarViewType must have "
2160  "rank 1.");
2161  static_assert (std::is_same<
2162  typename OutputScalarViewType::non_const_value_type,
2163  typename InputScalarViewType::non_const_value_type>::value,
2164  "Template parameters OutputScalarViewType and "
2165  "InputScalarViewType must contain values of the same "
2166  "type.");
2167  static_assert (std::is_same<
2168  typename LocalIndicesViewType::non_const_value_type,
2169  local_ordinal_type>::value,
2170  "Template parameter LocalIndicesViewType must "
2171  "contain values of type local_ordinal_type.");
2172 
2173  typedef LocalOrdinal LO;
2174  typedef GlobalOrdinal GO;
2175 
2176  // Don't call this->hasColMap(), because that changes RCP's
2177  // reference count, which is not thread safe. Just
2178  // dereferencing an RCP or calling RCP::is_null() does not
2179  // change its reference count.
2180  if (colMap_.is_null ()) {
2181  // No such thing as local column indices without a column Map.
2182  return Teuchos::OrdinalTraits<LO>::invalid ();
2183  }
2184  else if (newVals.dimension_0 () != inds.dimension_0 ()) {
2185  // The dimensions of the input arrays must match.
2186  return Teuchos::OrdinalTraits<LO>::invalid ();
2187  }
2188 
2189  const bool sorted = this->isSorted ();
2190 
2191  size_t hint = 0; // Guess for the current index k into rowVals
2192  LO numValid = 0; // number of valid local column indices
2193 
2194  // NOTE (mfh 11 Oct 2015) This method assumes UVM. More
2195  // accurately, it assumes that the host execution space can
2196  // access data in all the Views.
2197 
2198  if (isLocallyIndexed ()) {
2199  // Get a view of the column indices in the row. This amortizes
2200  // the cost of getting the view over all the entries of inds.
2201  auto colInds = this->getLocalKokkosRowView (rowInfo);
2202 
2203  const LO numElts = static_cast<LO> (inds.dimension_0 ());
2204  for (LO j = 0; j < numElts; ++j) {
2205  const LO lclColInd = inds(j);
2206  const size_t offset =
2207  KokkosSparse::findRelOffset (colInds, rowInfo.numEntries,
2208  lclColInd, hint, sorted);
2209  if (offset != rowInfo.numEntries) {
2210  rowVals(offset) = newVals(j);
2211  hint = offset + 1;
2212  ++numValid;
2213  }
2214  }
2215  }
2216  else if (isGloballyIndexed ()) {
2217  // Get a view of the column indices in the row. This amortizes
2218  // the cost of getting the view over all the entries of inds.
2219  auto colInds = this->getGlobalKokkosRowView (rowInfo);
2220 
2221  const LO numElts = static_cast<LO> (inds.dimension_0 ());
2222  for (LO j = 0; j < numElts; ++j) {
2223  const GO gblColInd = this->colMap_->getGlobalElement (inds(j));
2224  if (gblColInd != Teuchos::OrdinalTraits<GO>::invalid ()) {
2225  const size_t offset =
2226  KokkosSparse::findRelOffset (colInds, rowInfo.numEntries,
2227  gblColInd, hint, sorted);
2228  if (offset != rowInfo.numEntries) {
2229  rowVals(offset) = newVals(j);
2230  hint = offset + 1;
2231  ++numValid;
2232  }
2233  }
2234  }
2235  }
2236  // NOTE (mfh 26 Jun 2014, 26 Nov 2015) In the current version of
2237  // CrsGraph and CrsMatrix, it's possible for a matrix (or graph)
2238  // to be neither locally nor globally indexed on a process.
2239  // This means that the graph or matrix has no entries on that
2240  // process. Epetra also works like this. It's related to lazy
2241  // allocation (on first insertion, not at graph / matrix
2242  // construction). Lazy allocation will go away because it is
2243  // not thread scalable.
2244 
2245  return numValid;
2246  }
2247 
2271  template<class Scalar, class InputMemorySpace, class ValsMemorySpace>
2272  LocalOrdinal
2273  sumIntoGlobalValues (const RowInfo& rowInfo,
2274  const Kokkos::View<Scalar*, ValsMemorySpace,
2275  Kokkos::MemoryUnmanaged>& rowVals,
2276  const Kokkos::View<const GlobalOrdinal*, InputMemorySpace,
2277  Kokkos::MemoryUnmanaged>& inds,
2278  const Kokkos::View<const Scalar*, InputMemorySpace,
2279  Kokkos::MemoryUnmanaged>& newVals,
2280  const bool atomic = useAtomicUpdatesByDefault) const
2281  {
2282  typedef LocalOrdinal LO;
2283  typedef GlobalOrdinal GO;
2284 
2285  if (newVals.dimension_0 () != inds.dimension_0 ()) {
2286  // The dimensions of the input arrays must match.
2287  return Teuchos::OrdinalTraits<LO>::invalid ();
2288  }
2289 
2290  const bool sorted = this->isSorted ();
2291 
2292  size_t hint = 0; // guess at the index's relative offset in the row
2293  LO numValid = 0; // number of valid input column indices
2294 
2295  // NOTE (mfh 11 Oct 2015) This method assumes UVM. More
2296  // accurately, it assumes that the host execution space can
2297  // access data in both InputMemorySpace and ValsMemorySpace.
2298 
2299  if (isLocallyIndexed ()) {
2300  // NOTE (mfh 04 Nov 2015) Dereferencing an RCP or reading its
2301  // pointer does NOT change its reference count. Thus, this
2302  // code is still thread safe.
2303  if (colMap_.is_null ()) {
2304  // NO input column indices are valid in this case, since if
2305  // the column Map is null on the calling process, then the
2306  // calling process owns no graph entries.
2307  return numValid;
2308  }
2309  // Get a view of the column indices in the row. This amortizes
2310  // the cost of getting the view over all the entries of inds.
2311  auto colInds = this->getLocalKokkosRowView (rowInfo);
2312  const LO LINV = Teuchos::OrdinalTraits<LO>::invalid ();
2313 
2314  const LO numElts = static_cast<LO> (inds.dimension_0 ());
2315  for (LO j = 0; j < numElts; ++j) {
2316  const LO lclColInd = this->colMap_->getLocalElement (inds(j));
2317  if (lclColInd != LINV) {
2318  const size_t offset =
2319  KokkosSparse::findRelOffset (colInds, rowInfo.numEntries,
2320  lclColInd, hint, sorted);
2321  if (offset != rowInfo.numEntries) {
2322  if (atomic) {
2323  Kokkos::atomic_add (&rowVals(offset), newVals(j));
2324  }
2325  else {
2326  rowVals(offset) += newVals(j);
2327  }
2328  hint = offset + 1;
2329  numValid++;
2330  }
2331  }
2332  }
2333  }
2334  else if (isGloballyIndexed ()) {
2335  // Get a view of the column indices in the row. This amortizes
2336  // the cost of getting the view over all the entries of inds.
2337  auto colInds = this->getGlobalKokkosRowView (rowInfo);
2338 
2339  const LO numElts = static_cast<LO> (inds.dimension_0 ());
2340  for (LO j = 0; j < numElts; ++j) {
2341  const GO gblColInd = inds(j);
2342  const size_t offset =
2343  KokkosSparse::findRelOffset (colInds, rowInfo.numEntries,
2344  gblColInd, hint, sorted);
2345  if (offset != rowInfo.numEntries) {
2346  if (atomic) {
2347  Kokkos::atomic_add (&rowVals(offset), newVals(j));
2348  }
2349  else {
2350  rowVals(offset) += newVals(j);
2351  }
2352  hint = offset + 1;
2353  numValid++;
2354  }
2355  }
2356  }
2357  // If the graph is neither locally nor globally indexed on the
2358  // calling process, that means the calling process has no graph
2359  // entries. Thus, none of the input column indices are valid.
2360 
2361  return numValid;
2362  }
2363 
2388  template<class OutputScalarViewType,
2389  class GlobalIndicesViewType,
2390  class InputScalarViewType>
2391  LocalOrdinal
2392  replaceGlobalValues (const RowInfo& rowInfo,
2393  const typename UnmanagedView<OutputScalarViewType>::type& rowVals,
2394  const typename UnmanagedView<GlobalIndicesViewType>::type& inds,
2395  const typename UnmanagedView<InputScalarViewType>::type& newVals) const
2396  {
2397  // We use static_assert here to check the template parameters,
2398  // rather than std::enable_if (e.g., on the return value, to
2399  // enable compilation only if the template parameters match the
2400  // desired attributes). This turns obscure link errors into
2401  // clear compilation errors. It also makes the return value a
2402  // lot easier to see.
2403  static_assert (Kokkos::is_view<OutputScalarViewType>::value,
2404  "Template parameter OutputScalarViewType must be "
2405  "a Kokkos::View.");
2406  static_assert (Kokkos::is_view<GlobalIndicesViewType>::value,
2407  "Template parameter GlobalIndicesViewType must be "
2408  "a Kokkos::View.");
2409  static_assert (Kokkos::is_view<InputScalarViewType>::value,
2410  "Template parameter InputScalarViewType must be a "
2411  "Kokkos::View.");
2412  static_assert (static_cast<int> (OutputScalarViewType::rank) == 1,
2413  "Template parameter OutputScalarViewType must "
2414  "have rank 1.");
2415  static_assert (static_cast<int> (GlobalIndicesViewType::rank) == 1,
2416  "Template parameter GlobalIndicesViewType must "
2417  "have rank 1.");
2418  static_assert (static_cast<int> (InputScalarViewType::rank) == 1,
2419  "Template parameter InputScalarViewType must have "
2420  "rank 1.");
2421  static_assert (std::is_same<
2422  typename OutputScalarViewType::non_const_value_type,
2423  typename InputScalarViewType::non_const_value_type>::value,
2424  "Template parameters OutputScalarViewType and "
2425  "InputScalarViewType must contain values of the same "
2426  "type.");
2427  static_assert (std::is_same<
2428  typename GlobalIndicesViewType::non_const_value_type,
2429  global_ordinal_type>::value,
2430  "Template parameter GlobalIndicesViewType must "
2431  "contain values of type global_ordinal_type.");
2432 
2433  typedef LocalOrdinal LO;
2434  typedef GlobalOrdinal GO;
2435 
2436  if (newVals.dimension_0 () != inds.dimension_0 ()) {
2437  // The dimensions of the input arrays must match.
2438  return Teuchos::OrdinalTraits<LO>::invalid ();
2439  }
2440 
2441  const bool sorted = this->isSorted ();
2442 
2443  size_t hint = 0; // guess at the index's relative offset in the row
2444  LO numValid = 0; // number of valid input column indices
2445 
2446  // NOTE (mfh 11 Oct 2015) This method assumes UVM. More
2447  // accurately, it assumes that the host execution space can
2448  // access data in all the Views.
2449 
2450  if (isLocallyIndexed ()) {
2451  // NOTE (mfh 04 Nov 2015) Dereferencing an RCP or reading its
2452  // pointer does NOT change its reference count. Thus, this
2453  // code is still thread safe.
2454  if (colMap_.is_null ()) {
2455  // NO input column indices are valid in this case, since if
2456  // the column Map is null on the calling process, then the
2457  // calling process owns no graph entries.
2458  return numValid;
2459  }
2460  // Get a view of the column indices in the row. This amortizes
2461  // the cost of getting the view over all the entries of inds.
2462  auto colInds = this->getLocalKokkosRowView (rowInfo);
2463  const LO LINV = Teuchos::OrdinalTraits<LO>::invalid ();
2464 
2465  const LO numElts = static_cast<LO> (inds.dimension_0 ());
2466  for (LO j = 0; j < numElts; ++j) {
2467  const LO lclColInd = this->colMap_->getLocalElement (inds(j));
2468  if (lclColInd != LINV) {
2469  const size_t offset =
2470  KokkosSparse::findRelOffset (colInds, rowInfo.numEntries,
2471  lclColInd, hint, sorted);
2472  if (offset != rowInfo.numEntries) {
2473  rowVals(offset) = newVals(j);
2474  hint = offset + 1;
2475  numValid++;
2476  }
2477  }
2478  }
2479  }
2480  else if (isGloballyIndexed ()) {
2481  // Get a view of the column indices in the row. This amortizes
2482  // the cost of getting the view over all the entries of inds.
2483  auto colInds = this->getGlobalKokkosRowView (rowInfo);
2484 
2485  const LO numElts = static_cast<LO> (inds.dimension_0 ());
2486  for (LO j = 0; j < numElts; ++j) {
2487  const GO gblColInd = inds(j);
2488  const size_t offset =
2489  KokkosSparse::findRelOffset (colInds, rowInfo.numEntries,
2490  gblColInd, hint, sorted);
2491  if (offset != rowInfo.numEntries) {
2492  rowVals(offset) = newVals(j);
2493  hint = offset + 1;
2494  numValid++;
2495  }
2496  }
2497  }
2498  // If the graph is neither locally nor globally indexed on the
2499  // calling process, that means the calling process has no graph
2500  // entries. Thus, none of the input column indices are valid.
2501 
2502  return numValid;
2503  }
2504 
2531  template<class Scalar,
2532  class BinaryFunction,
2533  class InputMemorySpace,
2534  class ValsMemorySpace>
2535  LocalOrdinal
2537  const Kokkos::View<Scalar*, ValsMemorySpace,
2538  Kokkos::MemoryUnmanaged>& rowVals,
2539  const Kokkos::View<const GlobalOrdinal*,
2540  InputMemorySpace,
2541  Kokkos::MemoryUnmanaged>& inds,
2542  const Kokkos::View<const Scalar*,
2543  InputMemorySpace,
2544  Kokkos::MemoryUnmanaged>& newVals,
2545  BinaryFunction f,
2546  const bool atomic = useAtomicUpdatesByDefault) const
2547  {
2548  typedef LocalOrdinal LO;
2549  typedef GlobalOrdinal GO;
2550 
2551  if (newVals.dimension_0 () != inds.dimension_0 ()) {
2552  // The sizes of the input arrays must match.
2553  return Teuchos::OrdinalTraits<LO>::invalid ();
2554  }
2555 
2556  const LO numElts = static_cast<LO> (inds.dimension_0 ());
2557  const bool sorted = this->isSorted ();
2558 
2559  LO numValid = 0; // number of valid input column indices
2560  size_t hint = 0; // guess at the index's relative offset in the row
2561 
2562  if (isLocallyIndexed ()) {
2563  // NOTE (mfh 04 Nov 2015) Dereferencing an RCP or reading its
2564  // pointer does NOT change its reference count. Thus, this
2565  // code is still thread safe.
2566  if (colMap_.is_null ()) {
2567  // NO input column indices are valid in this case, since if
2568  // the column Map is null on the calling process, then the
2569  // calling process owns no graph entries.
2570  return numValid;
2571  }
2572  const map_type& colMap = *colMap_;
2573  // Get a view of the column indices in the row. This amortizes
2574  // the cost of getting the view over all the entries of inds.
2575  auto colInds = this->getLocalKokkosRowView (rowInfo);
2576 
2577  const LO LINV = Teuchos::OrdinalTraits<LO>::invalid ();
2578  for (LO j = 0; j < numElts; ++j) {
2579  const LO lclColInd = colMap.getLocalElement (inds(j));
2580  if (lclColInd != LINV) {
2581  const size_t offset =
2582  KokkosSparse::findRelOffset (colInds, rowInfo.numEntries,
2583  lclColInd, hint, sorted);
2584  if (offset != rowInfo.numEntries) {
2585  if (atomic) {
2586  // NOTE (mfh 30 Nov 2015) The commented-out code is
2587  // wrong because another thread may have changed
2588  // rowVals(offset) between those two lines of code.
2589  //
2590  //const Scalar newVal = f (rowVals(offset), newVals(j));
2591  //Kokkos::atomic_assign (&rowVals(offset), newVal);
2592 
2593  volatile Scalar* const dest = &rowVals(offset);
2594  (void) atomic_binary_function_update (dest, newVals(j), f);
2595  }
2596  else {
2597  // use binary function f
2598  rowVals(offset) = f (rowVals(offset), newVals(j));
2599  }
2600  hint = offset + 1;
2601  numValid++;
2602  }
2603  }
2604  }
2605  }
2606  else if (isGloballyIndexed ()) {
2607  // Get a view of the column indices in the row. This amortizes
2608  // the cost of getting the view over all the entries of inds.
2609  auto colInds = this->getGlobalKokkosRowView (rowInfo);
2610 
2611  for (LO j = 0; j < numElts; ++j) {
2612  const GO gblColInd = inds(j);
2613  const size_t offset =
2614  KokkosSparse::findRelOffset (colInds, rowInfo.numEntries,
2615  gblColInd, hint, sorted);
2616  if (offset != rowInfo.numEntries) {
2617  if (atomic) {
2618  // NOTE (mfh 30 Nov 2015) The commented-out code is
2619  // wrong because another thread may have changed
2620  // rowVals(offset) between those two lines of code.
2621  //
2622  //const Scalar newVal = f (rowVals(offset), newVals(j));
2623  //Kokkos::atomic_assign (&rowVals(offset), newVal);
2624 
2625  volatile Scalar* const dest = &rowVals(offset);
2626  (void) atomic_binary_function_update (dest, newVals(j), f);
2627  }
2628  else {
2629  // use binary function f
2630  rowVals(offset) = f (rowVals(offset), newVals(j));
2631  }
2632  hint = offset + 1;
2633  numValid++;
2634  }
2635  }
2636  }
2637  // If the graph is neither locally nor globally indexed on the
2638  // calling process, that means the calling process has no graph
2639  // entries. Thus, none of the input column indices are valid.
2640 
2641  return numValid;
2642  }
2643 
2645 
2647 
2649  bool isMerged () const;
2650 
2656  void setLocallyModified ();
2657 
2658  private:
2663  void
2664  sortAndMergeAllIndices (const bool sorted, const bool merged);
2665 
2666  // mfh 08 May 2017: I only restore "protected" here for backwards
2667  // compatibility.
2668  protected:
2669 
2671  void sortRowIndices (const RowInfo& rowinfo);
2672 
2681  size_t mergeRowIndices (const RowInfo& rowInfo);
2682 
2684 
2694  void
2695  setDomainRangeMaps (const Teuchos::RCP<const map_type>& domainMap,
2696  const Teuchos::RCP<const map_type>& rangeMap);
2697 
2698  void staticAssertions() const;
2699  void clearGlobalConstants();
2700  public:
2702  bool haveGlobalConstants() const { return haveGlobalConstants_;}
2703 
2709  void computeGlobalConstants();
2710  protected:
2711 
2713  // This is implied by the computation of global constants, and this is only used a
2714  // as an alterantive if the global constants are not computed
2716  void computeLocalConstants();
2717 
2720  RowInfo getRowInfo (const LocalOrdinal myRow) const;
2721 
2734  RowInfo getRowInfoFromGlobalRowIndex (const GlobalOrdinal gblRow) const;
2735 
2739  Teuchos::ArrayView<const LocalOrdinal>
2740  getLocalView (const RowInfo rowinfo) const;
2741 
2745  Teuchos::ArrayView<LocalOrdinal>
2746  getLocalViewNonConst (const RowInfo rowinfo);
2747 
2758  LocalOrdinal
2759  getLocalViewRawConst (const LocalOrdinal*& lclInds,
2760  LocalOrdinal& numEnt,
2761  const RowInfo& rowinfo) const;
2762 
2763  private:
2764 
2771  Kokkos::View<const LocalOrdinal*, execution_space, Kokkos::MemoryUnmanaged>
2772  getLocalKokkosRowView (const RowInfo& rowInfo) const;
2773 
2780  Kokkos::View<LocalOrdinal*, execution_space, Kokkos::MemoryUnmanaged>
2781  getLocalKokkosRowViewNonConst (const RowInfo& rowInfo);
2782 
2789  Kokkos::View<const GlobalOrdinal*, execution_space, Kokkos::MemoryUnmanaged>
2790  getGlobalKokkosRowView (const RowInfo& rowInfo) const;
2791 
2792  protected:
2793 
2797  Teuchos::ArrayView<const GlobalOrdinal>
2798  getGlobalView (const RowInfo& rowinfo) const;
2799 
2803  Teuchos::ArrayView<GlobalOrdinal>
2804  getGlobalViewNonConst (const RowInfo& rowinfo);
2805 
2817  LocalOrdinal
2818  getGlobalViewRawConst (const GlobalOrdinal*& gblInds,
2819  LocalOrdinal& numEnt,
2820  const RowInfo& rowinfo) const;
2821 
2822  public:
2830  local_graph_type getLocalGraph () const;
2831 
2832  protected:
2833  void fillLocalGraph (const Teuchos::RCP<Teuchos::ParameterList>& params);
2834 
2836  bool hasRowInfo () const;
2837 
2839  void checkInternalState () const;
2840 
2842  Teuchos::RCP<const map_type> rowMap_;
2844  Teuchos::RCP<const map_type> colMap_;
2846  Teuchos::RCP<const map_type> rangeMap_;
2848  Teuchos::RCP<const map_type> domainMap_;
2849 
2856  Teuchos::RCP<const import_type> importer_;
2857 
2863  Teuchos::RCP<const export_type> exporter_;
2864 
2866  local_graph_type lclGraph_;
2867 
2870 
2875 
2880 
2885 
2890 
2895 
2898 
2924  typename Kokkos::View<const size_t*, execution_space>::HostMirror
2926 
2937 
2939 
2940 
2948  typename local_graph_type::entries_type::non_const_type k_lclInds1D_;
2949 
2951  typedef Kokkos::View<GlobalOrdinal*, execution_space> t_GlobalOrdinal_1D;
2952 
2960  t_GlobalOrdinal_1D k_gblInds1D_;
2961 
2986  typename local_graph_type::row_map_type::const_type k_rowPtrs_;
2987 
2989 
3001 
3013  Teuchos::ArrayRCP<Teuchos::Array<LocalOrdinal> > lclInds2D_;
3014 
3026  Teuchos::ArrayRCP<Teuchos::Array<GlobalOrdinal> > gblInds2D_;
3027 
3034  typename Kokkos::View<size_t*, Kokkos::LayoutLeft, device_type>::HostMirror
3037 
3048 
3049  bool indicesAreAllocated_;
3050  bool indicesAreLocal_;
3051  bool indicesAreGlobal_;
3052  bool fillComplete_;
3053 
3067 
3069  std::map<GlobalOrdinal, std::vector<GlobalOrdinal> > nonlocals_;
3070 
3086 
3087  }; // class CrsGraph
3088 
3095  template <class LocalOrdinal, class GlobalOrdinal, class Node, const bool classic = Node::classic>
3096  Teuchos::RCP<CrsGraph<LocalOrdinal, GlobalOrdinal, Node, classic> >
3097  createCrsGraph (const Teuchos::RCP<const Map<LocalOrdinal, GlobalOrdinal, Node> > &map,
3098  size_t maxNumEntriesPerRow = 0,
3099  const Teuchos::RCP<Teuchos::ParameterList>& params = Teuchos::null)
3100  {
3101  using Teuchos::rcp;
3103  return rcp (new graph_type (map, maxNumEntriesPerRow, DynamicProfile, params));
3104  }
3105 
3106  namespace Details {
3107 
3108  template<class LocalOrdinal,
3109  class GlobalOrdinal,
3110  class OutputNodeType,
3111  class InputNodeType>
3112  class CrsGraphCopier<CrsGraph<LocalOrdinal, GlobalOrdinal, OutputNodeType>,
3113  CrsGraph<LocalOrdinal, GlobalOrdinal, InputNodeType> > {
3114  public:
3115  typedef CrsGraph<LocalOrdinal, GlobalOrdinal, InputNodeType> input_crs_graph_type;
3116  typedef CrsGraph<LocalOrdinal, GlobalOrdinal, OutputNodeType> output_crs_graph_type;
3117 
3118  static Teuchos::RCP<output_crs_graph_type>
3119  clone (const input_crs_graph_type& graphIn,
3120  const Teuchos::RCP<OutputNodeType> &nodeOut,
3121  const Teuchos::RCP<Teuchos::ParameterList>& params = Teuchos::null)
3122  {
3123  using Teuchos::arcp;
3124  using Teuchos::Array;
3125  using Teuchos::ArrayRCP;
3126  using Teuchos::ArrayView;
3127  using Teuchos::null;
3128  using Teuchos::outArg;
3129  using Teuchos::ParameterList;
3130  using Teuchos::parameterList;
3131  using Teuchos::RCP;
3132  using Teuchos::rcp;
3133  using Teuchos::REDUCE_MIN;
3134  using Teuchos::reduceAll;
3135  using Teuchos::sublist;
3136  using std::cerr;
3137  using std::endl;
3138  typedef LocalOrdinal LO;
3139  typedef GlobalOrdinal GO;
3140  typedef typename ArrayView<const GO>::size_type size_type;
3141  typedef ::Tpetra::Map<LO, GO, InputNodeType> input_map_type;
3142  typedef ::Tpetra::Map<LO, GO, OutputNodeType> output_map_type;
3143  const char prefix[] = "Tpetra::Details::CrsGraphCopier::clone: ";
3144 
3145  // Set parameters' default values.
3146  bool debug = false;
3147  bool fillCompleteClone = true;
3148  bool useLocalIndices = graphIn.hasColMap ();
3149  ProfileType pftype = StaticProfile;
3150  // If the user provided a ParameterList, get values from there.
3151  if (! params.is_null ()) {
3152  fillCompleteClone = params->get ("fillComplete clone", fillCompleteClone);
3153  useLocalIndices = params->get ("Locally indexed clone", useLocalIndices);
3154  if (params->get ("Static profile clone", true) == false) {
3155  pftype = DynamicProfile;
3156  }
3157  debug = params->get ("Debug", debug);
3158  }
3159 
3160  const Teuchos::Comm<int>& comm = * (graphIn.getRowMap ()->getComm ());
3161  const int myRank = comm.getRank ();
3162 
3163  TEUCHOS_TEST_FOR_EXCEPTION(
3164  ! graphIn.hasColMap () && useLocalIndices, std::runtime_error,
3165  prefix << "You asked clone() to use local indices (by setting the "
3166  "\"Locally indexed clone\" parameter to true), but the source graph "
3167  "does not yet have a column Map, so this is impossible.");
3168 
3169  if (debug) {
3170  std::ostringstream os;
3171  os << "Process " << myRank << ": Cloning row Map" << endl;
3172  cerr << os.str ();
3173  }
3174 
3175  RCP<const output_map_type> clonedRowMap =
3176  graphIn.getRowMap ()->template clone<OutputNodeType> (nodeOut);
3177 
3178  // Invoke the output graph's constructor, using the input graph's
3179  // upper bounds on the number of entries in each local row.
3180  RCP<output_crs_graph_type> clonedGraph; // returned by this function
3181  {
3182  ArrayRCP<const size_t> numEntriesPerRow;
3183  size_t numEntriesForAll = 0;
3184  bool boundSameForAllLocalRows = true;
3185 
3186  if (debug) {
3187  std::ostringstream os;
3188  os << "Process " << myRank << ": Getting per-row bounds" << endl;
3189  cerr << os.str ();
3190  }
3191  graphIn.getNumEntriesPerLocalRowUpperBound (numEntriesPerRow,
3192  numEntriesForAll,
3193  boundSameForAllLocalRows);
3194  if (debug) {
3195  std::ostringstream os;
3196  os << "Process " << myRank << ": numEntriesForAll = "
3197  << numEntriesForAll << endl;
3198  cerr << os.str ();
3199  }
3200 
3201  if (debug) {
3202  std::ostringstream os;
3203  os << "Process " << myRank << ": graphIn.getNodeMaxNumRowEntries() = "
3204  << graphIn.getNodeMaxNumRowEntries () << endl;
3205  cerr << os.str ();
3206  }
3207 
3208  RCP<ParameterList> graphparams;
3209  if (params.is_null ()) {
3210  graphparams = parameterList ("CrsGraph");
3211  } else {
3212  graphparams = sublist (params, "CrsGraph");
3213  }
3214  if (useLocalIndices) {
3215  RCP<const output_map_type> clonedColMap =
3216  graphIn.getColMap ()->template clone<OutputNodeType> (nodeOut);
3217  if (boundSameForAllLocalRows) {
3218  clonedGraph = rcp (new output_crs_graph_type (clonedRowMap, clonedColMap,
3219  numEntriesForAll, pftype,
3220  graphparams));
3221  } else {
3222  clonedGraph = rcp (new output_crs_graph_type (clonedRowMap, clonedColMap,
3223  numEntriesPerRow, pftype,
3224  graphparams));
3225  }
3226  } else {
3227  if (boundSameForAllLocalRows) {
3228  clonedGraph = rcp (new output_crs_graph_type (clonedRowMap,
3229  numEntriesForAll, pftype,
3230  graphparams));
3231  } else {
3232  clonedGraph = rcp (new output_crs_graph_type (clonedRowMap,
3233  numEntriesPerRow,
3234  pftype, graphparams));
3235  }
3236  }
3237 
3238  if (debug) {
3239  std::ostringstream os;
3240  os << "Process " << myRank << ": Invoked output graph's constructor" << endl;
3241  cerr << os.str ();
3242  }
3243 
3244  // done with these
3245  numEntriesPerRow = null;
3246  numEntriesForAll = 0;
3247  }
3248 
3249  const input_map_type& inputRowMap = * (graphIn.getRowMap ());
3250  const size_type numRows =
3251  static_cast<size_type> (inputRowMap.getNodeNumElements ());
3252 
3253  bool failed = false;
3254 
3255  if (useLocalIndices) {
3256  const LO localMinLID = inputRowMap.getMinLocalIndex ();
3257  const LO localMaxLID = inputRowMap.getMaxLocalIndex ();
3258 
3259  if (graphIn.isLocallyIndexed ()) {
3260  if (numRows != 0) {
3261  try {
3262  ArrayView<const LO> linds;
3263  for (LO lrow = localMinLID; lrow <= localMaxLID; ++lrow) {
3264  graphIn.getLocalRowView (lrow, linds);
3265  if (linds.size () != 0) {
3266  clonedGraph->insertLocalIndices (lrow, linds);
3267  }
3268  }
3269  }
3270  catch (std::exception& e) {
3271  std::ostringstream os;
3272  os << "Process " << myRank << ": copying (reading local by view, "
3273  "writing local) indices into the output graph threw an "
3274  "exception: " << e.what () << endl;
3275  cerr << os.str ();
3276  failed = true;
3277  }
3278  }
3279  }
3280  else { // graphIn.isGloballyIndexed()
3281  TEUCHOS_TEST_FOR_EXCEPTION(
3282  ! graphIn.hasColMap () && useLocalIndices, std::invalid_argument,
3283  prefix << "You asked clone() to use local indices (by setting the "
3284  "\"Locally indexed clone\" parameter to true), but the source graph "
3285  "does not yet have a column Map, so this is impossible.");
3286 
3287  // The input graph has a column Map, but is globally indexed.
3288  // That's a bit weird, but we'll run with it. In this case,
3289  // getLocalRowView won't work, but getLocalRowCopy should
3290  // still work; it will just have to convert from global to
3291  // local indices internally.
3292 
3293  try {
3294  // Make space for getLocalRowCopy to put column indices.
3295  //
3296  // This is only a hint; we may have to resize in the loop
3297  // below. getNodeMaxNumRowEntries() may return nonsense if
3298  // fill is active. The key bool in CrsGraph is
3299  // haveLocalConstants_.
3300  size_t myMaxNumRowEntries =
3301  graphIn.isFillActive () ? static_cast<size_t> (0) :
3302  graphIn.getNodeMaxNumRowEntries ();
3303 
3304  Array<LO> linds (myMaxNumRowEntries);
3305 
3306  // Copy each row into the new graph, using local indices.
3307  for (LO lrow = localMinLID; lrow <= localMaxLID; ++lrow) {
3308  size_t theNumEntries = graphIn.getNumEntriesInLocalRow (lrow);
3309  if (theNumEntries > myMaxNumRowEntries) {
3310  myMaxNumRowEntries = theNumEntries;
3311  linds.resize (myMaxNumRowEntries);
3312  }
3313  graphIn.getLocalRowCopy (lrow, linds (), theNumEntries);
3314  if (theNumEntries != 0) {
3315  clonedGraph->insertLocalIndices (lrow, linds (0, theNumEntries));
3316  }
3317  }
3318  }
3319  catch (std::exception& e) {
3320  std::ostringstream os;
3321  os << "Process " << myRank << ": copying (reading local by copy, "
3322  "writing local) indices into the output graph threw an exception: "
3323  << e.what () << endl;
3324  cerr << os.str ();
3325  failed = true;
3326  }
3327  }
3328  }
3329  else { /* useGlobalIndices */
3330  if (numRows != 0) {
3331  const GlobalOrdinal localMinGID = inputRowMap.getMinGlobalIndex ();
3332  const GlobalOrdinal localMaxGID = inputRowMap.getMaxGlobalIndex ();
3333  const bool inputRowMapIsContiguous = inputRowMap.isContiguous ();
3334 
3335  if (graphIn.isGloballyIndexed ()) {
3336  ArrayView<const GlobalOrdinal> ginds;
3337 
3338  if (inputRowMapIsContiguous) {
3339  try {
3340  for (GO grow = localMinGID; grow <= localMaxGID; ++grow) {
3341  graphIn.getGlobalRowView (grow, ginds);
3342  if (ginds.size () != 0) {
3343  clonedGraph->insertGlobalIndices (grow, ginds);
3344  }
3345  }
3346  }
3347  catch (std::exception& e) {
3348  std::ostringstream os;
3349  os << "Process " << myRank << ": copying (reading global by view, "
3350  "writing global) indices into the output graph threw an "
3351  "exception: " << e.what () << endl;
3352  cerr << os.str ();
3353  failed = true;
3354  }
3355  }
3356  else { // input row Map is not contiguous
3357  try {
3358  ArrayView<const GO> inputRowMapGIDs = inputRowMap.getNodeElementList ();
3359  for (size_type k = 0; k < numRows; ++k) {
3360  const GO grow = inputRowMapGIDs[k];
3361  graphIn.getGlobalRowView (grow, ginds);
3362  if (ginds.size () != 0) {
3363  clonedGraph->insertGlobalIndices (grow, ginds);
3364  }
3365  }
3366  }
3367  catch (std::exception& e) {
3368  std::ostringstream os;
3369  os << "Process " << myRank << ": copying (reading global by view, "
3370  "writing global) indices into the output graph threw an "
3371  "exception: " << e.what () << endl;
3372  cerr << os.str ();
3373  failed = true;
3374  }
3375  }
3376  }
3377  else { // graphIn.isLocallyIndexed()
3378  // Make space for getGlobalRowCopy to put column indices.
3379  //
3380  // This is only a hint; we may have to resize in the loop
3381  // below. getNodeMaxNumRowEntries() may return nonsense if
3382  // fill is active. The key bool in CrsGraph is
3383  // haveLocalConstants_.
3384  size_t myMaxNumRowEntries =
3385  graphIn.isFillActive () ? static_cast<size_t> (0) :
3386  graphIn.getNodeMaxNumRowEntries ();
3387 
3388  Array<GO> ginds (myMaxNumRowEntries);
3389 
3390  if (inputRowMapIsContiguous) {
3391  try {
3392  for (GO grow = localMinGID; grow <= localMaxGID; ++grow) {
3393  size_t theNumEntries = graphIn.getNumEntriesInGlobalRow (grow);
3394  if (theNumEntries > myMaxNumRowEntries) {
3395  myMaxNumRowEntries = theNumEntries;
3396  ginds.resize (myMaxNumRowEntries);
3397  }
3398  graphIn.getGlobalRowCopy (grow, ginds (), theNumEntries);
3399  if (theNumEntries != 0) {
3400  clonedGraph->insertGlobalIndices (grow, ginds (0, theNumEntries));
3401  }
3402  }
3403  }
3404  catch (std::exception& e) {
3405  std::ostringstream os;
3406  os << "Process " << myRank << ": copying (reading global by copy, "
3407  "writing global) indices into the output graph threw an "
3408  "exception: " << e.what () << endl;
3409  cerr << os.str ();
3410  failed = true;
3411  }
3412  }
3413  else { // input row Map is not contiguous
3414  try {
3415  ArrayView<const GO> inputRowMapGIDs = inputRowMap.getNodeElementList ();
3416  for (size_type k = 0; k < numRows; ++k) {
3417  const GO grow = inputRowMapGIDs[k];
3418 
3419  size_t theNumEntries = graphIn.getNumEntriesInGlobalRow (grow);
3420  if (theNumEntries > myMaxNumRowEntries) {
3421  myMaxNumRowEntries = theNumEntries;
3422  ginds.resize (myMaxNumRowEntries);
3423  }
3424  graphIn.getGlobalRowCopy (grow, ginds (), theNumEntries);
3425  if (theNumEntries != 0) {
3426  clonedGraph->insertGlobalIndices (grow, ginds (0, theNumEntries));
3427  }
3428  }
3429  }
3430  catch (std::exception& e) {
3431  std::ostringstream os;
3432  os << "Process " << myRank << ": copying (reading global by copy, "
3433  "writing global) indices into the output graph threw an "
3434  "exception: " << e.what () << endl;
3435  cerr << os.str ();
3436  failed = true;
3437  }
3438  }
3439  }
3440  } // numRows != 0
3441  }
3442 
3443  if (debug) {
3444  std::ostringstream os;
3445  os << "Process " << myRank << ": copied entries" << endl;
3446  cerr << os.str ();
3447  }
3448 
3449  if (fillCompleteClone) {
3450  RCP<ParameterList> fillparams = params.is_null () ?
3451  parameterList ("fillComplete") :
3452  sublist (params, "fillComplete");
3453  try {
3454  RCP<const output_map_type> clonedRangeMap;
3455  RCP<const output_map_type> clonedDomainMap;
3456  if (! graphIn.getRangeMap ().is_null () &&
3457  graphIn.getRangeMap () != graphIn.getRowMap ()) {
3458  clonedRangeMap =
3459  graphIn.getRangeMap ()->template clone<OutputNodeType> (nodeOut);
3460  }
3461  else {
3462  clonedRangeMap = clonedRowMap;
3463  }
3464  if (! graphIn.getDomainMap ().is_null ()
3465  && graphIn.getDomainMap () != graphIn.getRowMap ()) {
3466  clonedDomainMap =
3467  graphIn.getDomainMap ()->template clone<OutputNodeType> (nodeOut);
3468  }
3469  else {
3470  clonedDomainMap = clonedRowMap;
3471  }
3472 
3473  if (debug) {
3474  std::ostringstream os;
3475  os << "Process " << myRank << ": About to call fillComplete on "
3476  "cloned graph" << endl;
3477  cerr << os.str ();
3478  }
3479  clonedGraph->fillComplete (clonedDomainMap, clonedRangeMap, fillparams);
3480  }
3481  catch (std::exception &e) {
3482  failed = true;
3483  std::ostringstream os;
3484  os << prefix << "Process " << myRank << ": Caught the following "
3485  "exception while calling fillComplete() on clone of type"
3486  << endl << Teuchos::typeName (*clonedGraph) << endl;
3487  cerr << os.str ();
3488  }
3489  }
3490 
3491  int lclSuccess = failed ? 0 : 1;
3492  int gblSuccess = 1;
3493  reduceAll<int, int> (comm, REDUCE_MIN, lclSuccess, outArg (gblSuccess));
3494  TEUCHOS_TEST_FOR_EXCEPTION(
3495  gblSuccess != 1, std::logic_error, prefix <<
3496  "Clone failed on at least one process.");
3497 
3498  if (debug) {
3499  std::ostringstream os;
3500  os << "Process " << myRank << ": Done with CrsGraph::clone" << endl;
3501  cerr << os.str ();
3502  }
3503  return clonedGraph;
3504  }
3505  };
3506 
3507  } // namespace Details
3508 } // namespace Tpetra
3509 
3510 #endif // TPETRA_CRSGRAPH_DECL_HPP
Communication plan for data redistribution from a uniquely-owned to a (possibly) multiply-owned distr...
LocalOrdinal sumIntoGlobalValues(const RowInfo &rowInfo, const Kokkos::View< Scalar *, ValsMemorySpace, Kokkos::MemoryUnmanaged > &rowVals, const Kokkos::View< const GlobalOrdinal *, InputMemorySpace, Kokkos::MemoryUnmanaged > &inds, const Kokkos::View< const Scalar *, InputMemorySpace, Kokkos::MemoryUnmanaged > &newVals, const bool atomic=useAtomicUpdatesByDefault) const
Implementation detail of CrsMatrix::sumIntoGlobalValues.
Namespace Tpetra contains the class and methods constituting the Tpetra library.
size_t nodeMaxNumRowEntries_
Local maximum of the number of entries in each row.
bool haveGlobalConstants_
Whether all processes have computed global constants.
Sparse matrix that presents a row-oriented interface that lets users read or modify entries...
global_size_t globalMaxNumRowEntries_
Global maximum of the number of entries in each row.
An abstract interface for graphs accessed by rows.
bool indicesAreSorted_
Whether the graph&#39;s indices are sorted in each row, on this process.
GlobalOrdinal global_ordinal_type
This class&#39; second template parameter; the type of global indices.
bool noRedundancies_
Whether the graph&#39;s indices are non-redundant (merged) in each row, on this process.
size_t nodeNumDiags_
Local number of (populated) diagonal entries.
KokkosClassic::DefaultNode::DefaultNodeType node_type
Default value of Node template parameter.
bool isNodeGlobalElement(GlobalOrdinal globalIndex) const
Whether the given global index is owned by this Map on the calling process.
local_graph_type LocalStaticCrsGraphType TPETRA_DEPRECATED
DEPRECATED; use local_graph_type (above) instead.
bool sortGhostsAssociatedWithEachProcessor_
Whether to require makeColMap() (and therefore fillComplete()) to order column Map GIDs associated wi...
Node::device_type device_type
This class&#39; Kokkos device type.
Teuchos::RCP< const map_type > rangeMap_
The Map describing the range of the (matrix corresponding to the) graph.
ProfileType pftype_
Whether the graph was allocated with static or dynamic profile.
int makeColMap(Teuchos::RCP< const Tpetra::Map< LO, GO, NT > > &colMap, const Teuchos::RCP< const Tpetra::Map< LO, GO, NT > > &domMap, const RowGraph< LO, GO, NT > &graph, const bool sortEachProcsGids=true, std::ostream *errStrm=NULL)
Make the graph&#39;s column Map.
local_graph_type::entries_type::non_const_type k_lclInds1D_
Local column indices for all rows.
Teuchos::ArrayRCP< Teuchos::Array< GlobalOrdinal > > gblInds2D_
Global column indices for all rows.
LocalOrdinal local_ordinal_type
This class&#39; first template parameter; the type of local indices.
Teuchos::RCP< CrsGraph< LocalOrdinal, GlobalOrdinal, Node, classic > > createCrsGraph(const Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > &map, size_t maxNumEntriesPerRow=0, const Teuchos::RCP< Teuchos::ParameterList > &params=Teuchos::null)
Nonmember function to create an empty CrsGraph given a row Map and the max number of entries allowed ...
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.
size_t nodeNumEntries_
Local number of (populated) entries; must always be consistent.
bool upperTriangular_
Whether the graph is locally upper triangular.
LocalOrdinal sumIntoLocalValues(const RowInfo &rowInfo, const typename UnmanagedView< OutputScalarViewType >::type &rowVals, const typename UnmanagedView< LocalIndicesViewType >::type &inds, const typename UnmanagedView< InputScalarViewType >::type &newVals, const bool atomic=useAtomicUpdatesByDefault) const
Implementation detail of CrsMatrix::sumIntoLocalValues.
Teuchos::RCP< const map_type > domainMap_
The Map describing the domain of the (matrix corresponding to the) graph.
Allocation information for a locally owned row in a CrsGraph or CrsMatrix.
LocalOrdinal getLocalElement(GlobalOrdinal globalIndex) const
The local index corresponding to the given global index.
int local_ordinal_type
Default value of LocalOrdinal template parameter.
LocalOrdinal replaceLocalValues(const RowInfo &rowInfo, const typename UnmanagedView< OutputScalarViewType >::type &rowVals, const typename UnmanagedView< LocalIndicesViewType >::type &inds, const typename UnmanagedView< InputScalarViewType >::type &newVals) const
Implementation detail of CrsMatrix::replaceLocalValues.
LocalOrdinal transformLocalValues(const RowInfo &rowInfo, const typename UnmanagedView< OutputScalarViewType >::type &rowVals, const typename UnmanagedView< LocalIndicesViewType >::type &inds, const typename UnmanagedView< InputScalarViewType >::type &newVals, BinaryFunction f, const bool atomic=useAtomicUpdatesByDefault) const
Transform the given values using local indices.
Teuchos::RCP< const map_type > colMap_
The Map describing the distribution of columns of the graph.
Implementation details of Tpetra.
size_t numAllocForAllRows_
The maximum number of entries to allow in each locally owned row.
global_size_t globalNumDiags_
Global number of (populated) diagonal entries.
size_t global_size_t
Global size_t object.
Kokkos::StaticCrsGraph< LocalOrdinal, Kokkos::LayoutLeft, execution_space > local_graph_type
The type of the part of the sparse graph on each MPI process.
bool haveLocalConstants_
Whether this process has computed local constants.
t_GlobalOrdinal_1D k_gblInds1D_
Global column indices for all rows.
local_graph_type lclGraph_
Local graph; only initialized after first fillComplete() call.
Communication plan for data redistribution from a (possibly) multiply-owned to a uniquely-owned distr...
void insertIndicesAndValues(const RowInfo &rowInfo, const SLocalGlobalViews &newInds, const Teuchos::ArrayView< Scalar > &oldRowVals, const Teuchos::ArrayView< const Scalar > &newRowVals, const ELocalGlobal lg, const ELocalGlobal I)
Insert indices and their values into the given row.
Sets up and executes a communication plan for a Tpetra DistObject.
CombineMode
Rule for combining data in an Import or Export.
Teuchos::RCP< CrsGraph< LocalOrdinal, GlobalOrdinal, Node2, Node2::classic > > clone(const Teuchos::RCP< Node2 > &node2, const Teuchos::RCP< Teuchos::ParameterList > &params=Teuchos::null) const
Create a cloned CrsGraph for a different Node type.
GlobalOrdinal getGlobalElement(LocalOrdinal localIndex) const
The global index corresponding to the given local index.
Abstract base class for objects that can be the source of an Import or Export operation.
Teuchos::RCP< const import_type > importer_
The Import from the domain Map to the column Map.
LocalOrdinal transformGlobalValues(const RowInfo &rowInfo, const Kokkos::View< Scalar *, ValsMemorySpace, Kokkos::MemoryUnmanaged > &rowVals, const Kokkos::View< const GlobalOrdinal *, InputMemorySpace, Kokkos::MemoryUnmanaged > &inds, const Kokkos::View< const Scalar *, InputMemorySpace, Kokkos::MemoryUnmanaged > &newVals, BinaryFunction f, const bool atomic=useAtomicUpdatesByDefault) const
Transform the given values using global indices.
Node node_type
This class&#39; Kokkos Node type.
Teuchos::RCP< const map_type > rowMap_
The Map describing the distribution of rows of the graph.
Teuchos::ArrayRCP< Teuchos::Array< LocalOrdinal > > lclInds2D_
Local column indices for all rows.
bool haveGlobalConstants() const
Returns true if globalConstants have been computed; false otherwise.
Tpetra::Map< LocalOrdinal, GlobalOrdinal, Node > map_type
The Map specialization used by this class.
A distributed graph accessed by rows (adjacency lists) and stored sparsely.
global_size_t globalNumEntries_
Global number of entries in the graph.
A parallel distribution of indices over processes.
Details::EStorageStatus storageStatus_
Status of the graph&#39;s storage, when not in a fill-complete state.
Stand-alone utility functions and macros.
device_type::execution_space execution_space
This class&#39; Kokkos execution space.
local_graph_type::entries_type::non_const_type t_LocalOrdinal_1D TPETRA_DEPRECATED
DEPRECATED; use local_graph_type::entries_type::non_const_type instead.
local_graph_type::row_map_type::const_type k_rowPtrs_
Row offsets for "1-D" storage.
Kokkos::View< size_t *, Kokkos::LayoutLeft, device_type >::HostMirror k_numRowEntries_
The number of local entries in each locally owned row.
std::map< GlobalOrdinal, std::vector< GlobalOrdinal > > nonlocals_
Nonlocal data given to insertGlobalValues or sumIntoGlobalValues.
local_graph_type::row_map_type t_RowPtrs TPETRA_DEPRECATED
DEPRECATED; use local_graph_type::row_map_type instead.
local_graph_type::row_map_type::non_const_type t_RowPtrsNC TPETRA_DEPRECATED
DEPRECATED; use local_graph_type::row_map_type::non_const_type instead.
Kokkos::View< GlobalOrdinal *, execution_space > t_GlobalOrdinal_1D
Type of the k_gblInds1D_ array of global column indices.
Base class for distributed Tpetra objects that support data redistribution.
bool isNodeLocalElement(LocalOrdinal localIndex) const
Whether the given local index is valid for this Map on the calling process.
Tpetra::Export< LocalOrdinal, GlobalOrdinal, Node > export_type
The Export specialization used by this class.
LocalOrdinal replaceGlobalValues(const RowInfo &rowInfo, const typename UnmanagedView< OutputScalarViewType >::type &rowVals, const typename UnmanagedView< GlobalIndicesViewType >::type &inds, const typename UnmanagedView< InputScalarViewType >::type &newVals) const
Implementation detail of CrsMatrix::replaceGlobalValues.
EStorageStatus
Status of the graph&#39;s or matrix&#39;s storage, when not in a fill-complete state.
Teuchos::RCP< const export_type > exporter_
The Export from the row Map to the range Map.
bool lowerTriangular_
Whether the graph is locally lower triangular.
Kokkos::View< const size_t *, execution_space >::HostMirror k_numAllocPerRow_
The maximum number of entries to allow in each locally owned row, per row.
Tpetra::Import< LocalOrdinal, GlobalOrdinal, Node > import_type
The Import specialization used by this class.