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,
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 
829 
831 
835 
837  size_t getNodeNumRows() const;
838 
840 
842  size_t getNodeNumCols() const;
843 
845  GlobalOrdinal getIndexBase() const;
846 
848 
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 
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 (GlobalOrdinal GlobalRow,
1015  Teuchos::ArrayView<const GlobalOrdinal>& Indices) const;
1016 
1027  void
1028  getLocalRowView (LocalOrdinal LocalRow,
1029  Teuchos::ArrayView<const LocalOrdinal>& indices) const;
1030 
1032 
1034 
1036  std::string description() const;
1037 
1039  void
1040  describe (Teuchos::FancyOStream& out,
1041  const Teuchos::EVerbosityLevel verbLevel =
1042  Teuchos::Describable::verbLevel_default) const;
1043 
1045 
1047 
1048  virtual bool
1049  checkSizes (const SrcDistObject& source);
1050 
1051  virtual void
1052  copyAndPermute (const SrcDistObject& source,
1053  size_t numSameIDs,
1054  const Teuchos::ArrayView<const LocalOrdinal> &permuteToLIDs,
1055  const Teuchos::ArrayView<const LocalOrdinal> &permuteFromLIDs);
1056 
1057  virtual void
1058  packAndPrepare (const SrcDistObject& source,
1059  const Teuchos::ArrayView<const LocalOrdinal> &exportLIDs,
1060  Teuchos::Array<GlobalOrdinal> &exports,
1061  const Teuchos::ArrayView<size_t> & numPacketsPerLID,
1062  size_t& constantNumPackets,
1063  Distributor &distor);
1064 
1065  virtual void
1066  pack (const Teuchos::ArrayView<const LocalOrdinal>& exportLIDs,
1067  Teuchos::Array<GlobalOrdinal>& exports,
1068  const Teuchos::ArrayView<size_t>& numPacketsPerLID,
1069  size_t& constantNumPackets,
1070  Distributor& distor) const;
1071 
1072  virtual void
1073  unpackAndCombine (const Teuchos::ArrayView<const LocalOrdinal> &importLIDs,
1074  const Teuchos::ArrayView<const GlobalOrdinal> &imports,
1075  const Teuchos::ArrayView<size_t> &numPacketsPerLID,
1076  size_t constantNumPackets,
1077  Distributor &distor,
1078  CombineMode CM);
1080 
1082 
1125  void
1126  getLocalDiagOffsets (const Kokkos::View<size_t*, device_type, Kokkos::MemoryUnmanaged>& offsets) const;
1127 
1137  void
1138  getLocalDiagOffsets (Teuchos::ArrayRCP<size_t>& offsets) const;
1139 
1162  void
1163  getNumEntriesPerLocalRowUpperBound (Teuchos::ArrayRCP<const size_t>& boundPerLocalRow,
1164  size_t& boundForAllLocalRows,
1165  bool& boundSameForAllLocalRows) const;
1166 
1175  void
1176  setAllIndices (const typename local_graph_type::row_map_type& rowPointers,
1177  const typename local_graph_type::entries_type::non_const_type& columnIndices);
1178 
1187  void
1188  setAllIndices (const Teuchos::ArrayRCP<size_t> & rowPointers,
1189  const Teuchos::ArrayRCP<LocalOrdinal> & columnIndices);
1190 
1198  Teuchos::ArrayRCP<const size_t> getNodeRowPtrs () const;
1199 
1201 
1203  Teuchos::ArrayRCP<const LocalOrdinal> getNodePackedIndices() const;
1204 
1215  void replaceColMap (const Teuchos::RCP<const map_type>& newColMap);
1216 
1236  void
1237  reindexColumns (const Teuchos::RCP<const map_type>& newColMap,
1238  const Teuchos::RCP<const import_type>& newImport = Teuchos::null,
1239  const bool sortIndicesInEachRow = true);
1240 
1254  void
1255  replaceDomainMapAndImporter (const Teuchos::RCP<const map_type>& newDomainMap,
1256  const Teuchos::RCP<const import_type>& newImporter);
1257 
1286  virtual void
1287  removeEmptyProcessesInPlace (const Teuchos::RCP<const map_type>& newMap);
1289 
1290  template<class ViewType, class OffsetViewType >
1291  struct pack_functor {
1292  typedef typename ViewType::execution_space execution_space;
1293  ViewType src;
1294  ViewType dest;
1295  OffsetViewType src_offset;
1296  OffsetViewType dest_offset;
1297  typedef typename OffsetViewType::non_const_value_type ScalarIndx;
1298 
1299  pack_functor(ViewType dest_, ViewType src_, OffsetViewType dest_offset_, OffsetViewType src_offset_):
1300  src(src_),dest(dest_),src_offset(src_offset_),dest_offset(dest_offset_) {};
1301 
1302  KOKKOS_INLINE_FUNCTION
1303  void operator() (size_t row) const {
1304  ScalarIndx i = src_offset(row);
1305  ScalarIndx j = dest_offset(row);
1306  const ScalarIndx k = dest_offset(row+1);
1307  for(;j<k;j++,i++) {
1308  dest(j) = src(i);
1309  }
1310  }
1311  };
1312 
1313  protected:
1314  // these structs are conveniences, to cut down on the number of
1315  // arguments to some of the methods below.
1316  struct SLocalGlobalViews {
1317  Teuchos::ArrayView<const GlobalOrdinal> ginds;
1318  Teuchos::ArrayView<const LocalOrdinal> linds;
1319  };
1320  struct SLocalGlobalNCViews {
1321  Teuchos::ArrayView<GlobalOrdinal> ginds;
1322  Teuchos::ArrayView<LocalOrdinal> linds;
1323  };
1324 
1325  bool indicesAreAllocated () const;
1326  void allocateIndices (const ELocalGlobal lg);
1327 
1328  template <class T>
1329  Teuchos::ArrayRCP<Teuchos::Array<T> > allocateValues2D () const
1330  {
1331  using Teuchos::arcp;
1332  using Teuchos::Array;
1333  using Teuchos::ArrayRCP;
1334  using Teuchos::null;
1335  const char tfecfFuncName[] = "allocateValues2D: ";
1336 
1337  TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1338  (! indicesAreAllocated (), std::runtime_error,
1339  "Graph indices must be allocated before values.");
1340  TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1341  (getProfileType () != DynamicProfile, std::runtime_error,
1342  "Graph indices must be allocated in a dynamic profile.");
1343 
1344  ArrayRCP<Array<T> > values2D;
1345  values2D = arcp<Array<T> > (getNodeNumRows ());
1346  if (lclInds2D_ != null) {
1347  const size_t numRows = lclInds2D_.size ();
1348  for (size_t r = 0; r < numRows; ++r) {
1349  values2D[r].resize (lclInds2D_[r].size ());
1350  }
1351  }
1352  else if (gblInds2D_ != null) {
1353  const size_t numRows = gblInds2D_.size ();
1354  for (size_t r = 0; r < numRows; ++r) {
1355  values2D[r].resize (gblInds2D_[r].size ());
1356  }
1357  }
1358  return values2D;
1359  }
1360 
1361  template <class T>
1362  RowInfo updateLocalAllocAndValues (const RowInfo rowInfo,
1363  const size_t newAllocSize,
1364  Teuchos::Array<T>& rowVals)
1365  {
1366 #ifdef HAVE_TPETRA_DEBUG
1367  TEUCHOS_TEST_FOR_EXCEPT( ! isLocallyIndexed () );
1368  TEUCHOS_TEST_FOR_EXCEPT( ! indicesAreAllocated() );
1369  TEUCHOS_TEST_FOR_EXCEPT( newAllocSize == 0 );
1370  TEUCHOS_TEST_FOR_EXCEPT( newAllocSize < rowInfo.allocSize );
1371  TEUCHOS_TEST_FOR_EXCEPT( ! rowMap_->isNodeLocalElement (rowInfo.localRow) );
1372 #endif // HAVE_TPETRA_DEBUG
1373 
1374  // Teuchos::ArrayRCP::resize automatically copies over values on reallocation.
1375  lclInds2D_[rowInfo.localRow].resize (newAllocSize);
1376  rowVals.resize (newAllocSize);
1377  nodeNumAllocated_ += (newAllocSize - rowInfo.allocSize);
1378 
1379  RowInfo rowInfoOut = rowInfo;
1380  rowInfoOut.allocSize = newAllocSize;
1381  return rowInfoOut;
1382  }
1383 
1384  template <class T>
1385  RowInfo
1386  updateGlobalAllocAndValues (const RowInfo rowInfo,
1387  const size_t newAllocSize,
1388  Teuchos::Array<T>& rowVals)
1389  {
1390 #ifdef HAVE_TPETRA_DEBUG
1391  TEUCHOS_TEST_FOR_EXCEPT( ! isGloballyIndexed () );
1392  TEUCHOS_TEST_FOR_EXCEPT( ! indicesAreAllocated () );
1393  TEUCHOS_TEST_FOR_EXCEPT( newAllocSize == 0 );
1394  TEUCHOS_TEST_FOR_EXCEPT( newAllocSize < rowInfo.allocSize );
1395  TEUCHOS_TEST_FOR_EXCEPT( ! rowMap_->isNodeLocalElement (rowInfo.localRow) );
1396 #endif // HAVE_TPETRA_DEBUG
1397 
1398  // Teuchos::ArrayRCP::resize automatically copies over values on reallocation.
1399  gblInds2D_[rowInfo.localRow].resize (newAllocSize);
1400  rowVals.resize (newAllocSize);
1401  nodeNumAllocated_ += (newAllocSize - rowInfo.allocSize);
1402 
1403  RowInfo rowInfoOut = rowInfo;
1404  rowInfoOut.allocSize = newAllocSize;
1405  return rowInfoOut;
1406  }
1407 
1409 
1410 
1412  void makeColMap ();
1413  void makeIndicesLocal ();
1414  void makeImportExport ();
1415 
1417 
1419 
1420  template<ELocalGlobal lg>
1421  size_t filterIndices (const SLocalGlobalNCViews& inds) const
1422  {
1423  using Teuchos::ArrayView;
1424  static_assert (lg == GlobalIndices || lg == LocalIndices,
1425  "Tpetra::CrsGraph::filterIndices: The template parameter "
1426  "lg must be either GlobalIndices or LocalIndicies.");
1427 
1428  const map_type& cmap = *colMap_;
1429  size_t numFiltered = 0;
1430 #ifdef HAVE_TPETRA_DEBUG
1431  size_t numFiltered_debug = 0;
1432 #endif
1433  if (lg == GlobalIndices) {
1434  ArrayView<GlobalOrdinal> ginds = inds.ginds;
1435  typename ArrayView<GlobalOrdinal>::iterator fend = ginds.begin();
1436  typename ArrayView<GlobalOrdinal>::iterator cptr = ginds.begin();
1437  while (cptr != ginds.end()) {
1438  if (cmap.isNodeGlobalElement(*cptr)) {
1439  *fend++ = *cptr;
1440 #ifdef HAVE_TPETRA_DEBUG
1441  ++numFiltered_debug;
1442 #endif
1443  }
1444  ++cptr;
1445  }
1446  numFiltered = fend - ginds.begin();
1447  }
1448  else if (lg == LocalIndices) {
1449  ArrayView<LocalOrdinal> linds = inds.linds;
1450  typename ArrayView<LocalOrdinal>::iterator fend = linds.begin();
1451  typename ArrayView<LocalOrdinal>::iterator cptr = linds.begin();
1452  while (cptr != linds.end()) {
1453  if (cmap.isNodeLocalElement(*cptr)) {
1454  *fend++ = *cptr;
1455 #ifdef HAVE_TPETRA_DEBUG
1456  ++numFiltered_debug;
1457 #endif
1458  }
1459  ++cptr;
1460  }
1461  numFiltered = fend - linds.begin();
1462  }
1463 #ifdef HAVE_TPETRA_DEBUG
1464  TEUCHOS_TEST_FOR_EXCEPT( numFiltered != numFiltered_debug );
1465 #endif
1466  return numFiltered;
1467  }
1468 
1469 
1470  template<class T>
1471  size_t
1472  filterGlobalIndicesAndValues (const Teuchos::ArrayView<GlobalOrdinal>& ginds,
1473  const Teuchos::ArrayView<T>& vals) const
1474  {
1475  using Teuchos::ArrayView;
1476  const map_type& cmap = *colMap_;
1477  size_t numFiltered = 0;
1478  typename ArrayView<T>::iterator fvalsend = vals.begin();
1479  typename ArrayView<T>::iterator valscptr = vals.begin();
1480 #ifdef HAVE_TPETRA_DEBUG
1481  size_t numFiltered_debug = 0;
1482 #endif
1483  typename ArrayView<GlobalOrdinal>::iterator fend = ginds.begin();
1484  typename ArrayView<GlobalOrdinal>::iterator cptr = ginds.begin();
1485  while (cptr != ginds.end()) {
1486  if (cmap.isNodeGlobalElement (*cptr)) {
1487  *fend++ = *cptr;
1488  *fvalsend++ = *valscptr;
1489 #ifdef HAVE_TPETRA_DEBUG
1490  ++numFiltered_debug;
1491 #endif
1492  }
1493  ++cptr;
1494  ++valscptr;
1495  }
1496  numFiltered = fend - ginds.begin();
1497 #ifdef HAVE_TPETRA_DEBUG
1498  TEUCHOS_TEST_FOR_EXCEPT( numFiltered != numFiltered_debug );
1499  TEUCHOS_TEST_FOR_EXCEPT( valscptr != vals.end() );
1500  const size_t numFilteredActual =
1501  static_cast<size_t> (fvalsend - vals.begin ());
1502  TEUCHOS_TEST_FOR_EXCEPT( numFiltered != numFilteredActual );
1503 #endif // HAVE_TPETRA_DEBUG
1504  return numFiltered;
1505  }
1506 
1507  template<class T>
1508  size_t
1509  filterLocalIndicesAndValues (const Teuchos::ArrayView<LocalOrdinal>& linds,
1510  const Teuchos::ArrayView<T>& vals) const
1511  {
1512  using Teuchos::ArrayView;
1513  const map_type& cmap = *colMap_;
1514  size_t numFiltered = 0;
1515  typename ArrayView<T>::iterator fvalsend = vals.begin();
1516  typename ArrayView<T>::iterator valscptr = vals.begin();
1517 #ifdef HAVE_TPETRA_DEBUG
1518  size_t numFiltered_debug = 0;
1519 #endif
1520  typename ArrayView<LocalOrdinal>::iterator fend = linds.begin();
1521  typename ArrayView<LocalOrdinal>::iterator cptr = linds.begin();
1522  while (cptr != linds.end()) {
1523  if (cmap.isNodeLocalElement (*cptr)) {
1524  *fend++ = *cptr;
1525  *fvalsend++ = *valscptr;
1526 #ifdef HAVE_TPETRA_DEBUG
1527  ++numFiltered_debug;
1528 #endif
1529  }
1530  ++cptr;
1531  ++valscptr;
1532  }
1533  numFiltered = fend - linds.begin();
1534 #ifdef HAVE_TPETRA_DEBUG
1535  TEUCHOS_TEST_FOR_EXCEPT( numFiltered != numFiltered_debug );
1536  TEUCHOS_TEST_FOR_EXCEPT( valscptr != vals.end() );
1537  const size_t numFilteredActual =
1538  Teuchos::as<size_t> (fvalsend - vals.begin ());
1539  TEUCHOS_TEST_FOR_EXCEPT( numFiltered != numFilteredActual );
1540 #endif
1541  return numFiltered;
1542  }
1543 
1573  size_t
1574  insertIndices (const RowInfo& rowInfo,
1575  const SLocalGlobalViews& newInds,
1576  const ELocalGlobal lg,
1577  const ELocalGlobal I);
1578 
1618  template<class Scalar>
1619  void
1621  const SLocalGlobalViews& newInds,
1622  const Teuchos::ArrayView<Scalar>& oldRowVals,
1623  const Teuchos::ArrayView<const Scalar>& newRowVals,
1624  const ELocalGlobal lg,
1625  const ELocalGlobal I)
1626  {
1627 #ifdef HAVE_TPETRA_DEBUG
1628  const char tfecfFuncName[] = "insertIndicesAndValues: ";
1629 #endif // HAVE_TPETRA_DEBUG
1630 
1631 #ifdef HAVE_TPETRA_DEBUG
1632  size_t numNewInds = 0;
1633  try {
1634  numNewInds = insertIndices (rowInfo, newInds, lg, I);
1635  } catch (std::exception& e) {
1636  TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1637  (true, std::runtime_error, "insertIndices threw an exception: "
1638  << e.what ());
1639  }
1640  TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1641  (numNewInds > static_cast<size_t> (oldRowVals.size ()),
1642  std::runtime_error, "numNewInds (" << numNewInds << ") > "
1643  "oldRowVals.size() (" << oldRowVals.size () << ".");
1644 #else
1645  const size_t numNewInds = insertIndices (rowInfo, newInds, lg, I);
1646 #endif // HAVE_TPETRA_DEBUG
1647 
1648  typedef typename Teuchos::ArrayView<Scalar>::size_type size_type;
1649 
1650 #ifdef HAVE_TPETRA_DEBUG
1651  TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1652  (rowInfo.numEntries + numNewInds > static_cast<size_t> (oldRowVals.size ()),
1653  std::runtime_error, "rowInfo.numEntries (" << rowInfo.numEntries << ")"
1654  " + numNewInds (" << numNewInds << ") > oldRowVals.size() ("
1655  << oldRowVals.size () << ").");
1656  TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1657  (static_cast<size_type> (numNewInds) > newRowVals.size (),
1658  std::runtime_error, "numNewInds (" << numNewInds << ") > "
1659  "newRowVals.size() (" << newRowVals.size () << ").");
1660 #endif // HAVE_TPETRA_DEBUG
1661 
1662  size_type oldInd = static_cast<size_type> (rowInfo.numEntries);
1663 
1664 #ifdef HAVE_TPETRA_DEBUG
1665  try {
1666 #endif // HAVE_TPETRA_DEBUG
1667  //NOTE: The code in the else branch fails on GCC 4.9 and newer in the assignement oldRowVals[oldInd] = newRowVals[newInd];
1668  //We supply a workaround n as well as other code variants which produce or not produce the error
1669 #if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)
1670 #define GCC_VERSION __GNUC__*100+__GNUC_MINOR__*10+__GNUC_PATCHLEVEL__
1671 #if GCC_VERSION >= 490
1672 #define GCC_WORKAROUND
1673 #endif
1674 #endif
1675 #ifdef GCC_WORKAROUND
1676  size_type nNI = static_cast<size_type>(numNewInds);
1677  if (nNI > 0)
1678  memcpy(&oldRowVals[oldInd], &newRowVals[0], nNI*sizeof(Scalar));
1679  /*
1680  //Original Code Fails
1681  for (size_type newInd = 0; newInd < static_cast<size_type> (numNewInds);
1682  ++newInd, ++oldInd) {
1683  oldRowVals[oldInd] = newRowVals[newInd];
1684  }
1685 
1686  //char cast variant fails
1687  char* oldRowValPtr = (char*)&oldRowVals[oldInd];
1688  const char* newRowValPtr = (const char*) &newRowVals[0];
1689 
1690  for(size_type newInd = 0; newInd < (nNI * sizeof(Scalar)); newInd++) {
1691  oldRowValPtr[newInd] = newRowValPtr[newInd];
1692  }
1693 
1694  //Raw ptr variant fails
1695  Scalar* oldRowValPtr = &oldRowVals[oldInd];
1696  Scalar* newRowValPtr = const_cast<Scalar*>(&newRowVals[0]);
1697 
1698  for(size_type newInd = 0; newInd < nNI; newInd++) {
1699  oldRowValPtr[newInd] = newRowValPtr[newInd];
1700  }
1701 
1702  //memcpy works
1703  for (size_type newInd = 0; newInd < nNI; newInd++) {
1704  memcpy( &oldRowVals[oldInd+newInd], &newRowVals[newInd], sizeof(Scalar));
1705  }
1706 
1707  //just one loop index fails
1708  for (size_type newInd = 0; newInd < nNI; newInd++) {
1709  oldRowVals[oldInd+newInd] = newRowVals[newInd];
1710  }
1711 
1712  //inline increment fails
1713  for (size_type newInd = 0; newInd < numNewInds;) {
1714  oldRowVals[oldInd++] = newRowVals[newInd++];
1715  }
1716 
1717  */
1718 
1719 #else // GCC Workaround above
1720  for (size_type newInd = 0; newInd < static_cast<size_type> (numNewInds);
1721  ++newInd, ++oldInd) {
1722  oldRowVals[oldInd] = newRowVals[newInd];
1723  }
1724 #endif // GCC Workaround
1725 #ifdef HAVE_TPETRA_DEBUG
1726  }
1727  catch (std::exception& e) {
1728  TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1729  (true, std::runtime_error, "for loop for copying values threw an "
1730  "exception: " << e.what ());
1731  }
1732 #endif // HAVE_TPETRA_DEBUG
1733  }
1734 
1735  void
1736  insertGlobalIndicesImpl (const LocalOrdinal myRow,
1737  const Teuchos::ArrayView<const GlobalOrdinal> &indices);
1738  void
1739  insertLocalIndicesImpl (const LocalOrdinal myRow,
1740  const Teuchos::ArrayView<const LocalOrdinal> &indices);
1742  void
1743  insertLocalIndicesFiltered (const LocalOrdinal localRow,
1744  const Teuchos::ArrayView<const LocalOrdinal> &indices);
1745 
1747  void
1748  insertGlobalIndicesFiltered (const GlobalOrdinal localRow,
1749  const Teuchos::ArrayView<const GlobalOrdinal> &indices);
1750 
1755  static const bool useAtomicUpdatesByDefault =
1756 #ifdef KOKKOS_HAVE_SERIAL
1757  ! std::is_same<execution_space, Kokkos::Serial>::value;
1758 #else
1759  true;
1760 #endif // KOKKOS_HAVE_SERIAL
1761 
1800  template<class OutputScalarViewType,
1801  class LocalIndicesViewType,
1802  class InputScalarViewType,
1803  class BinaryFunction>
1804  LocalOrdinal
1806  const typename UnmanagedView<OutputScalarViewType>::type& rowVals,
1807  const typename UnmanagedView<LocalIndicesViewType>::type& inds,
1808  const typename UnmanagedView<InputScalarViewType>::type& newVals,
1809  BinaryFunction f,
1810  const bool atomic = useAtomicUpdatesByDefault) const
1811  {
1812  // We use static_assert here to check the template parameters,
1813  // rather than std::enable_if (e.g., on the return value, to
1814  // enable compilation only if the template parameters match the
1815  // desired attributes). This turns obscure link errors into
1816  // clear compilation errors. It also makes the return value a
1817  // lot easier to see.
1818  static_assert (Kokkos::is_view<OutputScalarViewType>::value,
1819  "Template parameter OutputScalarViewType must be "
1820  "a Kokkos::View.");
1821  static_assert (Kokkos::is_view<LocalIndicesViewType>::value,
1822  "Template parameter LocalIndicesViewType must be "
1823  "a Kokkos::View.");
1824  static_assert (Kokkos::is_view<InputScalarViewType>::value,
1825  "Template parameter InputScalarViewType must be a "
1826  "Kokkos::View.");
1827  static_assert (static_cast<int> (OutputScalarViewType::rank) == 1,
1828  "Template parameter OutputScalarViewType must "
1829  "have rank 1.");
1830  static_assert (static_cast<int> (LocalIndicesViewType::rank) == 1,
1831  "Template parameter LocalIndicesViewType must "
1832  "have rank 1.");
1833  static_assert (static_cast<int> (InputScalarViewType::rank) == 1,
1834  "Template parameter InputScalarViewType must have "
1835  "rank 1.");
1836  static_assert (std::is_same<
1837  typename OutputScalarViewType::non_const_value_type,
1838  typename InputScalarViewType::non_const_value_type>::value,
1839  "Template parameters OutputScalarViewType and "
1840  "InputScalarViewType must contain values of the same "
1841  "type.");
1842  static_assert (std::is_same<
1843  typename LocalIndicesViewType::non_const_value_type,
1844  local_ordinal_type>::value,
1845  "Template parameter LocalIndicesViewType must "
1846  "contain values of type local_ordinal_type.");
1847 
1848  typedef typename OutputScalarViewType::non_const_value_type ST;
1849  typedef LocalOrdinal LO;
1850  typedef GlobalOrdinal GO;
1851 
1852  if (newVals.dimension_0 () != inds.dimension_0 ()) {
1853  // The sizes of the input arrays must match.
1854  return Teuchos::OrdinalTraits<LO>::invalid ();
1855  }
1856  const LO numElts = static_cast<LO> (inds.dimension_0 ());
1857  const bool sorted = this->isSorted ();
1858 
1859  LO numValid = 0; // number of valid input column indices
1860  size_t hint = 0; // Guess for the current index k into rowVals
1861 
1862  if (isLocallyIndexed ()) {
1863  // Get a view of the column indices in the row. This amortizes
1864  // the cost of getting the view over all the entries of inds.
1865  auto colInds = this->getLocalKokkosRowView (rowInfo);
1866 
1867  for (LO j = 0; j < numElts; ++j) {
1868  const LO lclColInd = inds(j);
1869  const size_t offset =
1870  KokkosSparse::findRelOffset (colInds, rowInfo.numEntries,
1871  lclColInd, hint, sorted);
1872  if (offset != rowInfo.numEntries) {
1873  if (atomic) {
1874  // NOTE (mfh 30 Nov 2015) The commented-out code is
1875  // wrong because another thread may have changed
1876  // rowVals(offset) between those two lines of code.
1877  //
1878  //const ST newVal = f (rowVals(offset), newVals(j));
1879  //Kokkos::atomic_assign (&rowVals(offset), newVal);
1880 
1881  volatile ST* const dest = &rowVals(offset);
1882  (void) atomic_binary_function_update (dest, newVals(j), f);
1883  }
1884  else {
1885  // use binary function f
1886  rowVals(offset) = f (rowVals(offset), newVals(j));
1887  }
1888  hint = offset + 1;
1889  ++numValid;
1890  }
1891  }
1892  }
1893  else if (isGloballyIndexed ()) {
1894  // NOTE (mfh 26 Nov 2015) Dereferencing an RCP or reading its
1895  // pointer does NOT change its reference count. Thus, this
1896  // code is still thread safe.
1897  if (colMap_.is_null ()) {
1898  // NO input column indices are valid in this case. Either
1899  // the column Map hasn't been set yet (so local indices
1900  // don't exist yet), or the calling process owns no graph
1901  // entries.
1902  return numValid;
1903  }
1904  const map_type& colMap = *colMap_;
1905  // Get a view of the column indices in the row. This amortizes
1906  // the cost of getting the view over all the entries of inds.
1907  auto colInds = this->getGlobalKokkosRowView (rowInfo);
1908 
1909  const GO GINV = Teuchos::OrdinalTraits<GO>::invalid ();
1910  for (LO j = 0; j < numElts; ++j) {
1911  const GO gblColInd = colMap.getGlobalElement (inds(j));
1912  if (gblColInd != GINV) {
1913  const size_t offset =
1914  KokkosSparse::findRelOffset (colInds, rowInfo.numEntries,
1915  gblColInd, hint, sorted);
1916  if (offset != rowInfo.numEntries) {
1917  if (atomic) {
1918  // NOTE (mfh 30 Nov 2015) The commented-out code is
1919  // wrong because another thread may have changed
1920  // rowVals(offset) between those two lines of code.
1921  //
1922  //const ST newVal = f (rowVals(offset), newVals(j));
1923  //Kokkos::atomic_assign (&rowVals(offset), newVal);
1924 
1925  volatile ST* const dest = &rowVals(offset);
1926  (void) atomic_binary_function_update (dest, newVals(j), f);
1927  }
1928  else {
1929  // use binary function f
1930  rowVals(offset) = f (rowVals(offset), newVals(j));
1931  }
1932  hint = offset + 1;
1933  numValid++;
1934  }
1935  }
1936  }
1937  }
1938  // If the graph is neither locally nor globally indexed on the
1939  // calling process, that means the calling process has no graph
1940  // entries. Thus, none of the input column indices are valid.
1941 
1942  return numValid;
1943  }
1944 
1966  template<class OutputScalarViewType,
1967  class LocalIndicesViewType,
1968  class InputScalarViewType>
1969  LocalOrdinal
1970  sumIntoLocalValues (const RowInfo& rowInfo,
1971  const typename UnmanagedView<OutputScalarViewType>::type& rowVals,
1972  const typename UnmanagedView<LocalIndicesViewType>::type& inds,
1973  const typename UnmanagedView<InputScalarViewType>::type& newVals,
1974  const bool atomic = useAtomicUpdatesByDefault) const
1975  {
1976  // We use static_assert here to check the template parameters,
1977  // rather than std::enable_if (e.g., on the return value, to
1978  // enable compilation only if the template parameters match the
1979  // desired attributes). This turns obscure link errors into
1980  // clear compilation errors. It also makes the return value a
1981  // lot easier to see.
1982  static_assert (Kokkos::is_view<OutputScalarViewType>::value,
1983  "Template parameter OutputScalarViewType must be "
1984  "a Kokkos::View.");
1985  static_assert (Kokkos::is_view<LocalIndicesViewType>::value,
1986  "Template parameter LocalIndicesViewType must be "
1987  "a Kokkos::View.");
1988  static_assert (Kokkos::is_view<InputScalarViewType>::value,
1989  "Template parameter InputScalarViewType must be a "
1990  "Kokkos::View.");
1991  static_assert (static_cast<int> (OutputScalarViewType::rank) == 1,
1992  "Template parameter OutputScalarViewType must "
1993  "have rank 1.");
1994  static_assert (static_cast<int> (LocalIndicesViewType::rank) == 1,
1995  "Template parameter LocalIndicesViewType must "
1996  "have rank 1.");
1997  static_assert (static_cast<int> (InputScalarViewType::rank) == 1,
1998  "Template parameter InputScalarViewType must have "
1999  "rank 1.");
2000  static_assert (std::is_same<
2001  typename OutputScalarViewType::non_const_value_type,
2002  typename InputScalarViewType::non_const_value_type>::value,
2003  "Template parameters OutputScalarViewType and "
2004  "InputScalarViewType must contain values of the same "
2005  "type.");
2006  static_assert (std::is_same<
2007  typename LocalIndicesViewType::non_const_value_type,
2008  local_ordinal_type>::value,
2009  "Template parameter LocalIndicesViewType must "
2010  "contain values of type local_ordinal_type.");
2011 
2012  typedef LocalOrdinal LO;
2013  typedef GlobalOrdinal GO;
2014 
2015  // Don't call this->hasColMap(), because that changes RCP's
2016  // reference count, which is not thread safe. Just
2017  // dereferencing an RCP or calling RCP::is_null() does not
2018  // change its reference count.
2019  if (colMap_.is_null ()) {
2020  // No such thing as local column indices without a column Map.
2021  return Teuchos::OrdinalTraits<LO>::invalid ();
2022  }
2023  else if (newVals.dimension_0 () != inds.dimension_0 ()) {
2024  // The dimensions of the input arrays must match.
2025  return Teuchos::OrdinalTraits<LO>::invalid ();
2026  }
2027 
2028  const bool sorted = this->isSorted ();
2029 
2030  size_t hint = 0; // Guess for the current index k into rowVals
2031  LO numValid = 0; // number of valid local column indices
2032 
2033  // NOTE (mfh 11 Oct 2015) This method assumes UVM. More
2034  // accurately, it assumes that the host execution space can
2035  // access data in both InputMemorySpace and ValsMemorySpace.
2036 
2037  if (isLocallyIndexed ()) {
2038  // Get a view of the column indices in the row. This amortizes
2039  // the cost of getting the view over all the entries of inds.
2040  auto colInds = this->getLocalKokkosRowView (rowInfo);
2041 
2042  const LO numElts = static_cast<LO> (inds.dimension_0 ());
2043  for (LO j = 0; j < numElts; ++j) {
2044  const LO lclColInd = inds(j);
2045  const size_t offset =
2046  KokkosSparse::findRelOffset (colInds, rowInfo.numEntries,
2047  lclColInd, hint, sorted);
2048  if (offset != rowInfo.numEntries) {
2049  if (atomic) {
2050  Kokkos::atomic_add (&rowVals(offset), newVals(j));
2051  }
2052  else {
2053  rowVals(offset) += newVals(j);
2054  }
2055  hint = offset + 1;
2056  ++numValid;
2057  }
2058  }
2059  }
2060  else if (isGloballyIndexed ()) {
2061  // Get a view of the column indices in the row. This amortizes
2062  // the cost of getting the view over all the entries of inds.
2063  auto colInds = this->getGlobalKokkosRowView (rowInfo);
2064 
2065  const LO numElts = static_cast<LO> (inds.dimension_0 ());
2066  for (LO j = 0; j < numElts; ++j) {
2067  const GO gblColInd = this->colMap_->getGlobalElement (inds(j));
2068  if (gblColInd != Teuchos::OrdinalTraits<GO>::invalid ()) {
2069  const size_t offset =
2070  KokkosSparse::findRelOffset (colInds, rowInfo.numEntries,
2071  gblColInd, hint, sorted);
2072  if (offset != rowInfo.numEntries) {
2073  if (atomic) {
2074  Kokkos::atomic_add (&rowVals(offset), newVals(j));
2075  }
2076  else {
2077  rowVals(offset) += newVals(j);
2078  }
2079  hint = offset + 1;
2080  ++numValid;
2081  }
2082  }
2083  }
2084  }
2085  // NOTE (mfh 26 Jun 2014, 26 Nov 2015) In the current version of
2086  // CrsGraph and CrsMatrix, it's possible for a matrix (or graph)
2087  // to be neither locally nor globally indexed on a process.
2088  // This means that the graph or matrix has no entries on that
2089  // process. Epetra also works like this. It's related to lazy
2090  // allocation (on first insertion, not at graph / matrix
2091  // construction). Lazy allocation will go away because it is
2092  // not thread scalable.
2093 
2094  return numValid;
2095  }
2096 
2121  template<class OutputScalarViewType,
2122  class LocalIndicesViewType,
2123  class InputScalarViewType>
2124  LocalOrdinal
2125  replaceLocalValues (const RowInfo& rowInfo,
2126  const typename UnmanagedView<OutputScalarViewType>::type& rowVals,
2127  const typename UnmanagedView<LocalIndicesViewType>::type& inds,
2128  const typename UnmanagedView<InputScalarViewType>::type& newVals) const
2129  {
2130  // We use static_assert here to check the template parameters,
2131  // rather than std::enable_if (e.g., on the return value, to
2132  // enable compilation only if the template parameters match the
2133  // desired attributes). This turns obscure link errors into
2134  // clear compilation errors. It also makes the return value a
2135  // lot easier to see.
2136  static_assert (Kokkos::is_view<OutputScalarViewType>::value,
2137  "Template parameter OutputScalarViewType must be "
2138  "a Kokkos::View.");
2139  static_assert (Kokkos::is_view<LocalIndicesViewType>::value,
2140  "Template parameter LocalIndicesViewType must be "
2141  "a Kokkos::View.");
2142  static_assert (Kokkos::is_view<InputScalarViewType>::value,
2143  "Template parameter InputScalarViewType must be a "
2144  "Kokkos::View.");
2145  static_assert (static_cast<int> (OutputScalarViewType::rank) == 1,
2146  "Template parameter OutputScalarViewType must "
2147  "have rank 1.");
2148  static_assert (static_cast<int> (LocalIndicesViewType::rank) == 1,
2149  "Template parameter LocalIndicesViewType must "
2150  "have rank 1.");
2151  static_assert (static_cast<int> (InputScalarViewType::rank) == 1,
2152  "Template parameter InputScalarViewType must have "
2153  "rank 1.");
2154  static_assert (std::is_same<
2155  typename OutputScalarViewType::non_const_value_type,
2156  typename InputScalarViewType::non_const_value_type>::value,
2157  "Template parameters OutputScalarViewType and "
2158  "InputScalarViewType must contain values of the same "
2159  "type.");
2160  static_assert (std::is_same<
2161  typename LocalIndicesViewType::non_const_value_type,
2162  local_ordinal_type>::value,
2163  "Template parameter LocalIndicesViewType must "
2164  "contain values of type local_ordinal_type.");
2165 
2166  typedef LocalOrdinal LO;
2167  typedef GlobalOrdinal GO;
2168 
2169  // Don't call this->hasColMap(), because that changes RCP's
2170  // reference count, which is not thread safe. Just
2171  // dereferencing an RCP or calling RCP::is_null() does not
2172  // change its reference count.
2173  if (colMap_.is_null ()) {
2174  // No such thing as local column indices without a column Map.
2175  return Teuchos::OrdinalTraits<LO>::invalid ();
2176  }
2177  else if (newVals.dimension_0 () != inds.dimension_0 ()) {
2178  // The dimensions of the input arrays must match.
2179  return Teuchos::OrdinalTraits<LO>::invalid ();
2180  }
2181 
2182  const bool sorted = this->isSorted ();
2183 
2184  size_t hint = 0; // Guess for the current index k into rowVals
2185  LO numValid = 0; // number of valid local column indices
2186 
2187  // NOTE (mfh 11 Oct 2015) This method assumes UVM. More
2188  // accurately, it assumes that the host execution space can
2189  // access data in all the Views.
2190 
2191  if (isLocallyIndexed ()) {
2192  // Get a view of the column indices in the row. This amortizes
2193  // the cost of getting the view over all the entries of inds.
2194  auto colInds = this->getLocalKokkosRowView (rowInfo);
2195 
2196  const LO numElts = static_cast<LO> (inds.dimension_0 ());
2197  for (LO j = 0; j < numElts; ++j) {
2198  const LO lclColInd = inds(j);
2199  const size_t offset =
2200  KokkosSparse::findRelOffset (colInds, rowInfo.numEntries,
2201  lclColInd, hint, sorted);
2202  if (offset != rowInfo.numEntries) {
2203  rowVals(offset) = newVals(j);
2204  hint = offset + 1;
2205  ++numValid;
2206  }
2207  }
2208  }
2209  else if (isGloballyIndexed ()) {
2210  // Get a view of the column indices in the row. This amortizes
2211  // the cost of getting the view over all the entries of inds.
2212  auto colInds = this->getGlobalKokkosRowView (rowInfo);
2213 
2214  const LO numElts = static_cast<LO> (inds.dimension_0 ());
2215  for (LO j = 0; j < numElts; ++j) {
2216  const GO gblColInd = this->colMap_->getGlobalElement (inds(j));
2217  if (gblColInd != Teuchos::OrdinalTraits<GO>::invalid ()) {
2218  const size_t offset =
2219  KokkosSparse::findRelOffset (colInds, rowInfo.numEntries,
2220  gblColInd, hint, sorted);
2221  if (offset != rowInfo.numEntries) {
2222  rowVals(offset) = newVals(j);
2223  hint = offset + 1;
2224  ++numValid;
2225  }
2226  }
2227  }
2228  }
2229  // NOTE (mfh 26 Jun 2014, 26 Nov 2015) In the current version of
2230  // CrsGraph and CrsMatrix, it's possible for a matrix (or graph)
2231  // to be neither locally nor globally indexed on a process.
2232  // This means that the graph or matrix has no entries on that
2233  // process. Epetra also works like this. It's related to lazy
2234  // allocation (on first insertion, not at graph / matrix
2235  // construction). Lazy allocation will go away because it is
2236  // not thread scalable.
2237 
2238  return numValid;
2239  }
2240 
2264  template<class Scalar, class InputMemorySpace, class ValsMemorySpace>
2265  LocalOrdinal
2266  sumIntoGlobalValues (const RowInfo& rowInfo,
2267  const Kokkos::View<Scalar*, ValsMemorySpace,
2268  Kokkos::MemoryUnmanaged>& rowVals,
2269  const Kokkos::View<const GlobalOrdinal*, InputMemorySpace,
2270  Kokkos::MemoryUnmanaged>& inds,
2271  const Kokkos::View<const Scalar*, InputMemorySpace,
2272  Kokkos::MemoryUnmanaged>& newVals,
2273  const bool atomic = useAtomicUpdatesByDefault) const
2274  {
2275  typedef LocalOrdinal LO;
2276  typedef GlobalOrdinal GO;
2277 
2278  if (newVals.dimension_0 () != inds.dimension_0 ()) {
2279  // The dimensions of the input arrays must match.
2280  return Teuchos::OrdinalTraits<LO>::invalid ();
2281  }
2282 
2283  const bool sorted = this->isSorted ();
2284 
2285  size_t hint = 0; // guess at the index's relative offset in the row
2286  LO numValid = 0; // number of valid input column indices
2287 
2288  // NOTE (mfh 11 Oct 2015) This method assumes UVM. More
2289  // accurately, it assumes that the host execution space can
2290  // access data in both InputMemorySpace and ValsMemorySpace.
2291 
2292  if (isLocallyIndexed ()) {
2293  // NOTE (mfh 04 Nov 2015) Dereferencing an RCP or reading its
2294  // pointer does NOT change its reference count. Thus, this
2295  // code is still thread safe.
2296  if (colMap_.is_null ()) {
2297  // NO input column indices are valid in this case, since if
2298  // the column Map is null on the calling process, then the
2299  // calling process owns no graph entries.
2300  return numValid;
2301  }
2302  // Get a view of the column indices in the row. This amortizes
2303  // the cost of getting the view over all the entries of inds.
2304  auto colInds = this->getLocalKokkosRowView (rowInfo);
2305  const LO LINV = Teuchos::OrdinalTraits<LO>::invalid ();
2306 
2307  const LO numElts = static_cast<LO> (inds.dimension_0 ());
2308  for (LO j = 0; j < numElts; ++j) {
2309  const LO lclColInd = this->colMap_->getLocalElement (inds(j));
2310  if (lclColInd != LINV) {
2311  const size_t offset =
2312  KokkosSparse::findRelOffset (colInds, rowInfo.numEntries,
2313  lclColInd, hint, sorted);
2314  if (offset != rowInfo.numEntries) {
2315  if (atomic) {
2316  Kokkos::atomic_add (&rowVals(offset), newVals(j));
2317  }
2318  else {
2319  rowVals(offset) += newVals(j);
2320  }
2321  hint = offset + 1;
2322  numValid++;
2323  }
2324  }
2325  }
2326  }
2327  else if (isGloballyIndexed ()) {
2328  // Get a view of the column indices in the row. This amortizes
2329  // the cost of getting the view over all the entries of inds.
2330  auto colInds = this->getGlobalKokkosRowView (rowInfo);
2331 
2332  const LO numElts = static_cast<LO> (inds.dimension_0 ());
2333  for (LO j = 0; j < numElts; ++j) {
2334  const GO gblColInd = inds(j);
2335  const size_t offset =
2336  KokkosSparse::findRelOffset (colInds, rowInfo.numEntries,
2337  gblColInd, hint, sorted);
2338  if (offset != rowInfo.numEntries) {
2339  if (atomic) {
2340  Kokkos::atomic_add (&rowVals(offset), newVals(j));
2341  }
2342  else {
2343  rowVals(offset) += newVals(j);
2344  }
2345  hint = offset + 1;
2346  numValid++;
2347  }
2348  }
2349  }
2350  // If the graph is neither locally nor globally indexed on the
2351  // calling process, that means the calling process has no graph
2352  // entries. Thus, none of the input column indices are valid.
2353 
2354  return numValid;
2355  }
2356 
2381  template<class OutputScalarViewType,
2382  class GlobalIndicesViewType,
2383  class InputScalarViewType>
2384  LocalOrdinal
2385  replaceGlobalValues (const RowInfo& rowInfo,
2386  const typename UnmanagedView<OutputScalarViewType>::type& rowVals,
2387  const typename UnmanagedView<GlobalIndicesViewType>::type& inds,
2388  const typename UnmanagedView<InputScalarViewType>::type& newVals) const
2389  {
2390  // We use static_assert here to check the template parameters,
2391  // rather than std::enable_if (e.g., on the return value, to
2392  // enable compilation only if the template parameters match the
2393  // desired attributes). This turns obscure link errors into
2394  // clear compilation errors. It also makes the return value a
2395  // lot easier to see.
2396  static_assert (Kokkos::is_view<OutputScalarViewType>::value,
2397  "Template parameter OutputScalarViewType must be "
2398  "a Kokkos::View.");
2399  static_assert (Kokkos::is_view<GlobalIndicesViewType>::value,
2400  "Template parameter GlobalIndicesViewType must be "
2401  "a Kokkos::View.");
2402  static_assert (Kokkos::is_view<InputScalarViewType>::value,
2403  "Template parameter InputScalarViewType must be a "
2404  "Kokkos::View.");
2405  static_assert (static_cast<int> (OutputScalarViewType::rank) == 1,
2406  "Template parameter OutputScalarViewType must "
2407  "have rank 1.");
2408  static_assert (static_cast<int> (GlobalIndicesViewType::rank) == 1,
2409  "Template parameter GlobalIndicesViewType must "
2410  "have rank 1.");
2411  static_assert (static_cast<int> (InputScalarViewType::rank) == 1,
2412  "Template parameter InputScalarViewType must have "
2413  "rank 1.");
2414  static_assert (std::is_same<
2415  typename OutputScalarViewType::non_const_value_type,
2416  typename InputScalarViewType::non_const_value_type>::value,
2417  "Template parameters OutputScalarViewType and "
2418  "InputScalarViewType must contain values of the same "
2419  "type.");
2420  static_assert (std::is_same<
2421  typename GlobalIndicesViewType::non_const_value_type,
2422  global_ordinal_type>::value,
2423  "Template parameter GlobalIndicesViewType must "
2424  "contain values of type global_ordinal_type.");
2425 
2426  typedef LocalOrdinal LO;
2427  typedef GlobalOrdinal GO;
2428 
2429  if (newVals.dimension_0 () != inds.dimension_0 ()) {
2430  // The dimensions of the input arrays must match.
2431  return Teuchos::OrdinalTraits<LO>::invalid ();
2432  }
2433 
2434  const bool sorted = this->isSorted ();
2435 
2436  size_t hint = 0; // guess at the index's relative offset in the row
2437  LO numValid = 0; // number of valid input column indices
2438 
2439  // NOTE (mfh 11 Oct 2015) This method assumes UVM. More
2440  // accurately, it assumes that the host execution space can
2441  // access data in all the Views.
2442 
2443  if (isLocallyIndexed ()) {
2444  // NOTE (mfh 04 Nov 2015) Dereferencing an RCP or reading its
2445  // pointer does NOT change its reference count. Thus, this
2446  // code is still thread safe.
2447  if (colMap_.is_null ()) {
2448  // NO input column indices are valid in this case, since if
2449  // the column Map is null on the calling process, then the
2450  // calling process owns no graph entries.
2451  return numValid;
2452  }
2453  // Get a view of the column indices in the row. This amortizes
2454  // the cost of getting the view over all the entries of inds.
2455  auto colInds = this->getLocalKokkosRowView (rowInfo);
2456  const LO LINV = Teuchos::OrdinalTraits<LO>::invalid ();
2457 
2458  const LO numElts = static_cast<LO> (inds.dimension_0 ());
2459  for (LO j = 0; j < numElts; ++j) {
2460  const LO lclColInd = this->colMap_->getLocalElement (inds(j));
2461  if (lclColInd != LINV) {
2462  const size_t offset =
2463  KokkosSparse::findRelOffset (colInds, rowInfo.numEntries,
2464  lclColInd, hint, sorted);
2465  if (offset != rowInfo.numEntries) {
2466  rowVals(offset) = newVals(j);
2467  hint = offset + 1;
2468  numValid++;
2469  }
2470  }
2471  }
2472  }
2473  else if (isGloballyIndexed ()) {
2474  // Get a view of the column indices in the row. This amortizes
2475  // the cost of getting the view over all the entries of inds.
2476  auto colInds = this->getGlobalKokkosRowView (rowInfo);
2477 
2478  const LO numElts = static_cast<LO> (inds.dimension_0 ());
2479  for (LO j = 0; j < numElts; ++j) {
2480  const GO gblColInd = inds(j);
2481  const size_t offset =
2482  KokkosSparse::findRelOffset (colInds, rowInfo.numEntries,
2483  gblColInd, hint, sorted);
2484  if (offset != rowInfo.numEntries) {
2485  rowVals(offset) = newVals(j);
2486  hint = offset + 1;
2487  numValid++;
2488  }
2489  }
2490  }
2491  // If the graph is neither locally nor globally indexed on the
2492  // calling process, that means the calling process has no graph
2493  // entries. Thus, none of the input column indices are valid.
2494 
2495  return numValid;
2496  }
2497 
2524  template<class Scalar,
2525  class BinaryFunction,
2526  class InputMemorySpace,
2527  class ValsMemorySpace>
2528  LocalOrdinal
2530  const Kokkos::View<Scalar*, ValsMemorySpace,
2531  Kokkos::MemoryUnmanaged>& rowVals,
2532  const Kokkos::View<const GlobalOrdinal*,
2533  InputMemorySpace,
2534  Kokkos::MemoryUnmanaged>& inds,
2535  const Kokkos::View<const Scalar*,
2536  InputMemorySpace,
2537  Kokkos::MemoryUnmanaged>& newVals,
2538  BinaryFunction f,
2539  const bool atomic = useAtomicUpdatesByDefault) const
2540  {
2541  typedef LocalOrdinal LO;
2542  typedef GlobalOrdinal GO;
2543 
2544  if (newVals.dimension_0 () != inds.dimension_0 ()) {
2545  // The sizes of the input arrays must match.
2546  return Teuchos::OrdinalTraits<LO>::invalid ();
2547  }
2548 
2549  const LO numElts = static_cast<LO> (inds.dimension_0 ());
2550  const bool sorted = this->isSorted ();
2551 
2552  LO numValid = 0; // number of valid input column indices
2553  size_t hint = 0; // guess at the index's relative offset in the row
2554 
2555  if (isLocallyIndexed ()) {
2556  // NOTE (mfh 04 Nov 2015) Dereferencing an RCP or reading its
2557  // pointer does NOT change its reference count. Thus, this
2558  // code is still thread safe.
2559  if (colMap_.is_null ()) {
2560  // NO input column indices are valid in this case, since if
2561  // the column Map is null on the calling process, then the
2562  // calling process owns no graph entries.
2563  return numValid;
2564  }
2565  const map_type& colMap = *colMap_;
2566  // Get a view of the column indices in the row. This amortizes
2567  // the cost of getting the view over all the entries of inds.
2568  auto colInds = this->getLocalKokkosRowView (rowInfo);
2569 
2570  const LO LINV = Teuchos::OrdinalTraits<LO>::invalid ();
2571  for (LO j = 0; j < numElts; ++j) {
2572  const LO lclColInd = colMap.getLocalElement (inds(j));
2573  if (lclColInd != LINV) {
2574  const size_t offset =
2575  KokkosSparse::findRelOffset (colInds, rowInfo.numEntries,
2576  lclColInd, hint, sorted);
2577  if (offset != rowInfo.numEntries) {
2578  if (atomic) {
2579  // NOTE (mfh 30 Nov 2015) The commented-out code is
2580  // wrong because another thread may have changed
2581  // rowVals(offset) between those two lines of code.
2582  //
2583  //const Scalar newVal = f (rowVals(offset), newVals(j));
2584  //Kokkos::atomic_assign (&rowVals(offset), newVal);
2585 
2586  volatile Scalar* const dest = &rowVals(offset);
2587  (void) atomic_binary_function_update (dest, newVals(j), f);
2588  }
2589  else {
2590  // use binary function f
2591  rowVals(offset) = f (rowVals(offset), newVals(j));
2592  }
2593  hint = offset + 1;
2594  numValid++;
2595  }
2596  }
2597  }
2598  }
2599  else if (isGloballyIndexed ()) {
2600  // Get a view of the column indices in the row. This amortizes
2601  // the cost of getting the view over all the entries of inds.
2602  auto colInds = this->getGlobalKokkosRowView (rowInfo);
2603 
2604  for (LO j = 0; j < numElts; ++j) {
2605  const GO gblColInd = inds(j);
2606  const size_t offset =
2607  KokkosSparse::findRelOffset (colInds, rowInfo.numEntries,
2608  gblColInd, hint, sorted);
2609  if (offset != rowInfo.numEntries) {
2610  if (atomic) {
2611  // NOTE (mfh 30 Nov 2015) The commented-out code is
2612  // wrong because another thread may have changed
2613  // rowVals(offset) between those two lines of code.
2614  //
2615  //const Scalar newVal = f (rowVals(offset), newVals(j));
2616  //Kokkos::atomic_assign (&rowVals(offset), newVal);
2617 
2618  volatile Scalar* const dest = &rowVals(offset);
2619  (void) atomic_binary_function_update (dest, newVals(j), f);
2620  }
2621  else {
2622  // use binary function f
2623  rowVals(offset) = f (rowVals(offset), newVals(j));
2624  }
2625  hint = offset + 1;
2626  numValid++;
2627  }
2628  }
2629  }
2630  // If the graph is neither locally nor globally indexed on the
2631  // calling process, that means the calling process has no graph
2632  // entries. Thus, none of the input column indices are valid.
2633 
2634  return numValid;
2635  }
2636 
2638 
2640 
2642  bool isMerged () const;
2643 
2649  void setLocallyModified ();
2650 
2652  void sortAllIndices ();
2653 
2655  void sortRowIndices (const RowInfo rowinfo);
2656 
2671  template <class Scalar>
2672  void
2674  const Teuchos::ArrayView<Scalar>& values)
2675  {
2676  if (rowinfo.numEntries > 0) {
2677  Teuchos::ArrayView<LocalOrdinal> inds_view =
2678  this->getLocalViewNonConst (rowinfo);
2679  sort2 (inds_view.begin (), inds_view.begin () + rowinfo.numEntries,
2680  values.begin ());
2681  }
2682  }
2683 
2692  void mergeAllIndices ();
2693 
2698  void mergeRowIndices (RowInfo rowinfo);
2699 
2710  template<class Scalar>
2711  void
2713  const Teuchos::ArrayView<Scalar>& rowValues)
2714  {
2715  using Teuchos::ArrayView;
2716  const char tfecfFuncName[] = "mergeRowIndicesAndValues: ";
2717  TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2718  (isStorageOptimized(), std::logic_error, "It is invalid to call this "
2719  "method if the graph's storage has already been optimized. Please "
2720  "report this bug to the Tpetra developers.");
2721 
2722  typedef typename ArrayView<Scalar>::iterator Iter;
2723  Iter rowValueIter = rowValues.begin ();
2724  ArrayView<LocalOrdinal> inds_view = getLocalViewNonConst (rowinfo);
2725  typename ArrayView<LocalOrdinal>::iterator beg, end, newend;
2726 
2727  // beg,end define a half-exclusive interval over which to iterate.
2728  beg = inds_view.begin();
2729  end = inds_view.begin() + rowinfo.numEntries;
2730  newend = beg;
2731  if (beg != end) {
2732  typename ArrayView<LocalOrdinal>::iterator cur = beg + 1;
2733  Iter vcur = rowValueIter + 1;
2734  Iter vend = rowValueIter;
2735  cur = beg+1;
2736  while (cur != end) {
2737  if (*cur != *newend) {
2738  // new entry; save it
2739  ++newend;
2740  ++vend;
2741  (*newend) = (*cur);
2742  (*vend) = (*vcur);
2743  }
2744  else {
2745  // old entry; merge it
2746  //(*vend) = f (*vend, *vcur);
2747  (*vend) += *vcur;
2748  }
2749  ++cur;
2750  ++vcur;
2751  }
2752  ++newend; // one past the last entry, per typical [beg,end) semantics
2753  }
2754  const size_t mergedEntries = newend - beg;
2755 #ifdef HAVE_TPETRA_DEBUG
2756  // merge should not have eliminated any entries; if so, the
2757  // assignment below will destroy the packed structure
2758  TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2759  (isStorageOptimized() && mergedEntries != rowinfo.numEntries,
2760  std::logic_error,
2761  "Merge was incorrect; it eliminated entries from the graph. "
2762  << "Please report this bug to the Tpetra developers.");
2763 #endif // HAVE_TPETRA_DEBUG
2764 
2765  k_numRowEntries_(rowinfo.localRow) = mergedEntries;
2766  nodeNumEntries_ -= (rowinfo.numEntries - mergedEntries);
2767  }
2768 
2770 
2780  void
2781  setDomainRangeMaps (const Teuchos::RCP<const map_type>& domainMap,
2782  const Teuchos::RCP<const map_type>& rangeMap);
2783 
2784  void staticAssertions() const;
2785  void clearGlobalConstants();
2786  void computeGlobalConstants();
2787 
2790  RowInfo getRowInfo (const LocalOrdinal myRow) const;
2791 
2804  RowInfo getRowInfoFromGlobalRowIndex (const GlobalOrdinal gblRow) const;
2805 
2809  Teuchos::ArrayView<const LocalOrdinal>
2810  getLocalView (const RowInfo rowinfo) const;
2811 
2815  Teuchos::ArrayView<LocalOrdinal>
2816  getLocalViewNonConst (const RowInfo rowinfo);
2817 
2828  LocalOrdinal
2829  getLocalViewRawConst (const LocalOrdinal*& lclInds,
2830  LocalOrdinal& numEnt,
2831  const RowInfo& rowinfo) const;
2832 
2833  private:
2834 
2841  Kokkos::View<const LocalOrdinal*, execution_space, Kokkos::MemoryUnmanaged>
2842  getLocalKokkosRowView (const RowInfo& rowinfo) const;
2843 
2850  Kokkos::View<LocalOrdinal*, execution_space, Kokkos::MemoryUnmanaged>
2851  getLocalKokkosRowViewNonConst (const RowInfo& rowinfo);
2852 
2859  Kokkos::View<const GlobalOrdinal*, execution_space, Kokkos::MemoryUnmanaged>
2860  getGlobalKokkosRowView (const RowInfo& rowinfo) const;
2861 
2862  protected:
2863 
2867  Teuchos::ArrayView<const GlobalOrdinal>
2868  getGlobalView (const RowInfo rowinfo) const;
2869 
2873  Teuchos::ArrayView<GlobalOrdinal>
2874  getGlobalViewNonConst (const RowInfo rowinfo);
2875 
2887  LocalOrdinal
2888  getGlobalViewRawConst (const GlobalOrdinal*& gblInds,
2889  LocalOrdinal& numEnt,
2890  const RowInfo& rowinfo) const;
2891 
2892  public:
2901 
2902  protected:
2903  void fillLocalGraph (const Teuchos::RCP<Teuchos::ParameterList>& params);
2904 
2906  bool hasRowInfo () const;
2907 
2909  void checkInternalState () const;
2910 
2912  Teuchos::RCP<const map_type> rowMap_;
2914  Teuchos::RCP<const map_type> colMap_;
2916  Teuchos::RCP<const map_type> rangeMap_;
2918  Teuchos::RCP<const map_type> domainMap_;
2919 
2926  Teuchos::RCP<const import_type> importer_;
2927 
2933  Teuchos::RCP<const export_type> exporter_;
2934 
2937 
2938  // Local and Global Counts
2939  // nodeNumEntries_ and nodeNumAllocated_ are required to be always consistent
2940  // nodeMaxNumEntries_, nodeNumDiags_ and the global quantities are computed during fillComplete() and only valid when isFillComplete()
2941  global_size_t globalNumEntries_, globalNumDiags_, globalMaxNumRowEntries_;
2942  size_t nodeNumEntries_, nodeNumDiags_, nodeMaxNumRowEntries_, nodeNumAllocated_;
2943 
2946 
2972  typename Kokkos::View<const size_t*, execution_space>::HostMirror
2974 
2985 
2987 
2988 
2996  typename local_graph_type::entries_type::non_const_type k_lclInds1D_;
2997 
2999  typedef Kokkos::View<GlobalOrdinal*, execution_space> t_GlobalOrdinal_1D;
3000 
3009 
3034  typename local_graph_type::row_map_type::const_type k_rowPtrs_;
3035 
3037 
3049 
3061  Teuchos::ArrayRCP<Teuchos::Array<LocalOrdinal> > lclInds2D_;
3062 
3074  Teuchos::ArrayRCP<Teuchos::Array<GlobalOrdinal> > gblInds2D_;
3075 
3082  typename Kokkos::View<size_t*, Kokkos::LayoutLeft, device_type>::HostMirror
3085 
3096 
3097  bool indicesAreAllocated_;
3098  bool indicesAreLocal_;
3099  bool indicesAreGlobal_;
3100  bool fillComplete_;
3101 
3115 
3117  std::map<GlobalOrdinal, std::vector<GlobalOrdinal> > nonlocals_;
3118 
3134 
3135  }; // class CrsGraph
3136 
3143  template <class LocalOrdinal, class GlobalOrdinal, class Node, const bool classic = Node::classic>
3144  Teuchos::RCP<CrsGraph<LocalOrdinal, GlobalOrdinal, Node, classic> >
3145  createCrsGraph (const Teuchos::RCP<const Map<LocalOrdinal, GlobalOrdinal, Node> > &map,
3146  size_t maxNumEntriesPerRow = 0,
3147  const Teuchos::RCP<Teuchos::ParameterList>& params = Teuchos::null)
3148  {
3149  using Teuchos::rcp;
3151  return rcp (new graph_type (map, maxNumEntriesPerRow, DynamicProfile, params));
3152  }
3153 
3154  namespace Details {
3155 
3156  template<class LocalOrdinal,
3157  class GlobalOrdinal,
3158  class OutputNodeType,
3159  class InputNodeType>
3160  class CrsGraphCopier<CrsGraph<LocalOrdinal, GlobalOrdinal, OutputNodeType>,
3161  CrsGraph<LocalOrdinal, GlobalOrdinal, InputNodeType> > {
3162  public:
3163  typedef CrsGraph<LocalOrdinal, GlobalOrdinal, InputNodeType> input_crs_graph_type;
3164  typedef CrsGraph<LocalOrdinal, GlobalOrdinal, OutputNodeType> output_crs_graph_type;
3165 
3166  static Teuchos::RCP<output_crs_graph_type>
3167  clone (const input_crs_graph_type& graphIn,
3168  const Teuchos::RCP<OutputNodeType> &nodeOut,
3169  const Teuchos::RCP<Teuchos::ParameterList>& params = Teuchos::null)
3170  {
3171  using Teuchos::arcp;
3172  using Teuchos::Array;
3173  using Teuchos::ArrayRCP;
3174  using Teuchos::ArrayView;
3175  using Teuchos::null;
3176  using Teuchos::outArg;
3177  using Teuchos::ParameterList;
3178  using Teuchos::parameterList;
3179  using Teuchos::RCP;
3180  using Teuchos::rcp;
3181  using Teuchos::REDUCE_MIN;
3182  using Teuchos::reduceAll;
3183  using Teuchos::sublist;
3184  using std::cerr;
3185  using std::endl;
3186  typedef LocalOrdinal LO;
3187  typedef GlobalOrdinal GO;
3188  typedef typename ArrayView<const GO>::size_type size_type;
3189  typedef ::Tpetra::Map<LO, GO, InputNodeType> input_map_type;
3190  typedef ::Tpetra::Map<LO, GO, OutputNodeType> output_map_type;
3191  const char prefix[] = "Tpetra::Details::CrsGraphCopier::clone: ";
3192 
3193  // Set parameters' default values.
3194  bool debug = false;
3195  bool fillCompleteClone = true;
3196  bool useLocalIndices = graphIn.hasColMap ();
3197  ProfileType pftype = StaticProfile;
3198  // If the user provided a ParameterList, get values from there.
3199  if (! params.is_null ()) {
3200  fillCompleteClone = params->get ("fillComplete clone", fillCompleteClone);
3201  useLocalIndices = params->get ("Locally indexed clone", useLocalIndices);
3202  if (params->get ("Static profile clone", true) == false) {
3203  pftype = DynamicProfile;
3204  }
3205  debug = params->get ("Debug", debug);
3206  }
3207 
3208  const Teuchos::Comm<int>& comm = * (graphIn.getRowMap ()->getComm ());
3209  const int myRank = comm.getRank ();
3210 
3211  TEUCHOS_TEST_FOR_EXCEPTION(
3212  ! graphIn.hasColMap () && useLocalIndices, std::runtime_error,
3213  prefix << "You asked clone() to use local indices (by setting the "
3214  "\"Locally indexed clone\" parameter to true), but the source graph "
3215  "does not yet have a column Map, so this is impossible.");
3216 
3217  if (debug) {
3218  std::ostringstream os;
3219  os << "Process " << myRank << ": Cloning row Map" << endl;
3220  cerr << os.str ();
3221  }
3222 
3223  RCP<const output_map_type> clonedRowMap =
3224  graphIn.getRowMap ()->template clone<OutputNodeType> (nodeOut);
3225 
3226  // Invoke the output graph's constructor, using the input graph's
3227  // upper bounds on the number of entries in each local row.
3228  RCP<output_crs_graph_type> clonedGraph; // returned by this function
3229  {
3230  ArrayRCP<const size_t> numEntriesPerRow;
3231  size_t numEntriesForAll = 0;
3232  bool boundSameForAllLocalRows = true;
3233 
3234  if (debug) {
3235  std::ostringstream os;
3236  os << "Process " << myRank << ": Getting per-row bounds" << endl;
3237  cerr << os.str ();
3238  }
3239  graphIn.getNumEntriesPerLocalRowUpperBound (numEntriesPerRow,
3240  numEntriesForAll,
3241  boundSameForAllLocalRows);
3242  if (debug) {
3243  std::ostringstream os;
3244  os << "Process " << myRank << ": numEntriesForAll = "
3245  << numEntriesForAll << endl;
3246  cerr << os.str ();
3247  }
3248 
3249  if (debug) {
3250  std::ostringstream os;
3251  os << "Process " << myRank << ": graphIn.getNodeMaxNumRowEntries() = "
3252  << graphIn.getNodeMaxNumRowEntries () << endl;
3253  cerr << os.str ();
3254  }
3255 
3256  RCP<ParameterList> graphparams;
3257  if (params.is_null ()) {
3258  graphparams = parameterList ("CrsGraph");
3259  } else {
3260  graphparams = sublist (params, "CrsGraph");
3261  }
3262  if (useLocalIndices) {
3263  RCP<const output_map_type> clonedColMap =
3264  graphIn.getColMap ()->template clone<OutputNodeType> (nodeOut);
3265  if (boundSameForAllLocalRows) {
3266  clonedGraph = rcp (new output_crs_graph_type (clonedRowMap, clonedColMap,
3267  numEntriesForAll, pftype,
3268  graphparams));
3269  } else {
3270  clonedGraph = rcp (new output_crs_graph_type (clonedRowMap, clonedColMap,
3271  numEntriesPerRow, pftype,
3272  graphparams));
3273  }
3274  } else {
3275  if (boundSameForAllLocalRows) {
3276  clonedGraph = rcp (new output_crs_graph_type (clonedRowMap,
3277  numEntriesForAll, pftype,
3278  graphparams));
3279  } else {
3280  clonedGraph = rcp (new output_crs_graph_type (clonedRowMap,
3281  numEntriesPerRow,
3282  pftype, graphparams));
3283  }
3284  }
3285 
3286  if (debug) {
3287  std::ostringstream os;
3288  os << "Process " << myRank << ": Invoked output graph's constructor" << endl;
3289  cerr << os.str ();
3290  }
3291 
3292  // done with these
3293  numEntriesPerRow = null;
3294  numEntriesForAll = 0;
3295  }
3296 
3297  const input_map_type& inputRowMap = * (graphIn.getRowMap ());
3298  const size_type numRows =
3299  static_cast<size_type> (inputRowMap.getNodeNumElements ());
3300 
3301  bool failed = false;
3302 
3303  if (useLocalIndices) {
3304  const LO localMinLID = inputRowMap.getMinLocalIndex ();
3305  const LO localMaxLID = inputRowMap.getMaxLocalIndex ();
3306 
3307  if (graphIn.isLocallyIndexed ()) {
3308  if (numRows != 0) {
3309  try {
3310  ArrayView<const LO> linds;
3311  for (LO lrow = localMinLID; lrow <= localMaxLID; ++lrow) {
3312  graphIn.getLocalRowView (lrow, linds);
3313  if (linds.size () != 0) {
3314  clonedGraph->insertLocalIndices (lrow, linds);
3315  }
3316  }
3317  }
3318  catch (std::exception& e) {
3319  std::ostringstream os;
3320  os << "Process " << myRank << ": copying (reading local by view, "
3321  "writing local) indices into the output graph threw an "
3322  "exception: " << e.what () << endl;
3323  cerr << os.str ();
3324  failed = true;
3325  }
3326  }
3327  }
3328  else { // graphIn.isGloballyIndexed()
3329  TEUCHOS_TEST_FOR_EXCEPTION(
3330  ! graphIn.hasColMap () && useLocalIndices, std::invalid_argument,
3331  prefix << "You asked clone() to use local indices (by setting the "
3332  "\"Locally indexed clone\" parameter to true), but the source graph "
3333  "does not yet have a column Map, so this is impossible.");
3334 
3335  // The input graph has a column Map, but is globally indexed.
3336  // That's a bit weird, but we'll run with it. In this case,
3337  // getLocalRowView won't work, but getLocalRowCopy should
3338  // still work; it will just have to convert from global to
3339  // local indices internally.
3340 
3341  try {
3342  // Make space for getLocalRowCopy to put column indices.
3343  //
3344  // This is only a hint; we may have to resize in the loop
3345  // below. getNodeMaxNumRowEntries() may return nonsense if
3346  // fill is active. The key bool in CrsGraph is
3347  // haveLocalConstants_.
3348  size_t myMaxNumRowEntries =
3349  graphIn.isFillActive () ? static_cast<size_t> (0) :
3350  graphIn.getNodeMaxNumRowEntries ();
3351 
3352  Array<LO> linds (myMaxNumRowEntries);
3353 
3354  // Copy each row into the new graph, using local indices.
3355  for (LO lrow = localMinLID; lrow <= localMaxLID; ++lrow) {
3356  size_t theNumEntries = graphIn.getNumEntriesInLocalRow (lrow);
3357  if (theNumEntries > myMaxNumRowEntries) {
3358  myMaxNumRowEntries = theNumEntries;
3359  linds.resize (myMaxNumRowEntries);
3360  }
3361  graphIn.getLocalRowCopy (lrow, linds (), theNumEntries);
3362  if (theNumEntries != 0) {
3363  clonedGraph->insertLocalIndices (lrow, linds (0, theNumEntries));
3364  }
3365  }
3366  }
3367  catch (std::exception& e) {
3368  std::ostringstream os;
3369  os << "Process " << myRank << ": copying (reading local by copy, "
3370  "writing local) indices into the output graph threw an exception: "
3371  << e.what () << endl;
3372  cerr << os.str ();
3373  failed = true;
3374  }
3375  }
3376  }
3377  else { /* useGlobalIndices */
3378  if (numRows != 0) {
3379  const GlobalOrdinal localMinGID = inputRowMap.getMinGlobalIndex ();
3380  const GlobalOrdinal localMaxGID = inputRowMap.getMaxGlobalIndex ();
3381  const bool inputRowMapIsContiguous = inputRowMap.isContiguous ();
3382 
3383  if (graphIn.isGloballyIndexed ()) {
3384  ArrayView<const GlobalOrdinal> ginds;
3385 
3386  if (inputRowMapIsContiguous) {
3387  try {
3388  for (GO grow = localMinGID; grow <= localMaxGID; ++grow) {
3389  graphIn.getGlobalRowView (grow, ginds);
3390  if (ginds.size () != 0) {
3391  clonedGraph->insertGlobalIndices (grow, ginds);
3392  }
3393  }
3394  }
3395  catch (std::exception& e) {
3396  std::ostringstream os;
3397  os << "Process " << myRank << ": copying (reading global by view, "
3398  "writing global) indices into the output graph threw an "
3399  "exception: " << e.what () << endl;
3400  cerr << os.str ();
3401  failed = true;
3402  }
3403  }
3404  else { // input row Map is not contiguous
3405  try {
3406  ArrayView<const GO> inputRowMapGIDs = inputRowMap.getNodeElementList ();
3407  for (size_type k = 0; k < numRows; ++k) {
3408  const GO grow = inputRowMapGIDs[k];
3409  graphIn.getGlobalRowView (grow, ginds);
3410  if (ginds.size () != 0) {
3411  clonedGraph->insertGlobalIndices (grow, ginds);
3412  }
3413  }
3414  }
3415  catch (std::exception& e) {
3416  std::ostringstream os;
3417  os << "Process " << myRank << ": copying (reading global by view, "
3418  "writing global) indices into the output graph threw an "
3419  "exception: " << e.what () << endl;
3420  cerr << os.str ();
3421  failed = true;
3422  }
3423  }
3424  }
3425  else { // graphIn.isLocallyIndexed()
3426  // Make space for getGlobalRowCopy to put column indices.
3427  //
3428  // This is only a hint; we may have to resize in the loop
3429  // below. getNodeMaxNumRowEntries() may return nonsense if
3430  // fill is active. The key bool in CrsGraph is
3431  // haveLocalConstants_.
3432  size_t myMaxNumRowEntries =
3433  graphIn.isFillActive () ? static_cast<size_t> (0) :
3434  graphIn.getNodeMaxNumRowEntries ();
3435 
3436  Array<GO> ginds (myMaxNumRowEntries);
3437 
3438  if (inputRowMapIsContiguous) {
3439  try {
3440  for (GO grow = localMinGID; grow <= localMaxGID; ++grow) {
3441  size_t theNumEntries = graphIn.getNumEntriesInGlobalRow (grow);
3442  if (theNumEntries > myMaxNumRowEntries) {
3443  myMaxNumRowEntries = theNumEntries;
3444  ginds.resize (myMaxNumRowEntries);
3445  }
3446  graphIn.getGlobalRowCopy (grow, ginds (), theNumEntries);
3447  if (theNumEntries != 0) {
3448  clonedGraph->insertGlobalIndices (grow, ginds (0, theNumEntries));
3449  }
3450  }
3451  }
3452  catch (std::exception& e) {
3453  std::ostringstream os;
3454  os << "Process " << myRank << ": copying (reading global by copy, "
3455  "writing global) indices into the output graph threw an "
3456  "exception: " << e.what () << endl;
3457  cerr << os.str ();
3458  failed = true;
3459  }
3460  }
3461  else { // input row Map is not contiguous
3462  try {
3463  ArrayView<const GO> inputRowMapGIDs = inputRowMap.getNodeElementList ();
3464  for (size_type k = 0; k < numRows; ++k) {
3465  const GO grow = inputRowMapGIDs[k];
3466 
3467  size_t theNumEntries = graphIn.getNumEntriesInGlobalRow (grow);
3468  if (theNumEntries > myMaxNumRowEntries) {
3469  myMaxNumRowEntries = theNumEntries;
3470  ginds.resize (myMaxNumRowEntries);
3471  }
3472  graphIn.getGlobalRowCopy (grow, ginds (), theNumEntries);
3473  if (theNumEntries != 0) {
3474  clonedGraph->insertGlobalIndices (grow, ginds (0, theNumEntries));
3475  }
3476  }
3477  }
3478  catch (std::exception& e) {
3479  std::ostringstream os;
3480  os << "Process " << myRank << ": copying (reading global by copy, "
3481  "writing global) indices into the output graph threw an "
3482  "exception: " << e.what () << endl;
3483  cerr << os.str ();
3484  failed = true;
3485  }
3486  }
3487  }
3488  } // numRows != 0
3489  }
3490 
3491  if (debug) {
3492  std::ostringstream os;
3493  os << "Process " << myRank << ": copied entries" << endl;
3494  cerr << os.str ();
3495  }
3496 
3497  if (fillCompleteClone) {
3498  RCP<ParameterList> fillparams = params.is_null () ?
3499  parameterList ("fillComplete") :
3500  sublist (params, "fillComplete");
3501  try {
3502  RCP<const output_map_type> clonedRangeMap;
3503  RCP<const output_map_type> clonedDomainMap;
3504  if (! graphIn.getRangeMap ().is_null () &&
3505  graphIn.getRangeMap () != graphIn.getRowMap ()) {
3506  clonedRangeMap =
3507  graphIn.getRangeMap ()->template clone<OutputNodeType> (nodeOut);
3508  }
3509  else {
3510  clonedRangeMap = clonedRowMap;
3511  }
3512  if (! graphIn.getDomainMap ().is_null ()
3513  && graphIn.getDomainMap () != graphIn.getRowMap ()) {
3514  clonedDomainMap =
3515  graphIn.getDomainMap ()->template clone<OutputNodeType> (nodeOut);
3516  }
3517  else {
3518  clonedDomainMap = clonedRowMap;
3519  }
3520 
3521  if (debug) {
3522  std::ostringstream os;
3523  os << "Process " << myRank << ": About to call fillComplete on "
3524  "cloned graph" << endl;
3525  cerr << os.str ();
3526  }
3527  clonedGraph->fillComplete (clonedDomainMap, clonedRangeMap, fillparams);
3528  }
3529  catch (std::exception &e) {
3530  failed = true;
3531  std::ostringstream os;
3532  os << prefix << "Process " << myRank << ": Caught the following "
3533  "exception while calling fillComplete() on clone of type"
3534  << endl << Teuchos::typeName (*clonedGraph) << endl;
3535  cerr << os.str ();
3536  }
3537  }
3538 
3539  int lclSuccess = failed ? 0 : 1;
3540  int gblSuccess = 1;
3541  reduceAll<int, int> (comm, REDUCE_MIN, lclSuccess, outArg (gblSuccess));
3542  TEUCHOS_TEST_FOR_EXCEPTION(
3543  gblSuccess != 1, std::logic_error, prefix <<
3544  "Clone failed on at least one process.");
3545 
3546  if (debug) {
3547  std::ostringstream os;
3548  os << "Process " << myRank << ": Done with CrsGraph::clone" << endl;
3549  cerr << os.str ();
3550  }
3551  return clonedGraph;
3552  }
3553  };
3554 
3555  } // namespace Details
3556 } // namespace Tpetra
3557 
3558 #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.
ProfileType getProfileType() const
Returns true if the graph was allocated with static data structures.
RowInfo getRowInfoFromGlobalRowIndex(const GlobalOrdinal gblRow) const
Get information about the locally owned row with global index gblRow.
Namespace Tpetra contains the class and methods constituting the Tpetra library.
bool haveGlobalConstants_
Whether all processes have computed global constants.
virtual void copyAndPermute(const SrcDistObject &source, size_t numSameIDs, const Teuchos::ArrayView< const LocalOrdinal > &permuteToLIDs, const Teuchos::ArrayView< const LocalOrdinal > &permuteFromLIDs)
Perform copies and permutations that are local to this process.
Sparse matrix that presents a row-oriented interface that lets users read or modify entries...
void expertStaticFillComplete(const Teuchos::RCP< const map_type > &domainMap, const Teuchos::RCP< const map_type > &rangeMap, const Teuchos::RCP< const import_type > &importer=Teuchos::null, const Teuchos::RCP< const export_type > &exporter=Teuchos::null, const Teuchos::RCP< Teuchos::ParameterList > &params=Teuchos::null)
Perform a fillComplete on a graph that already has data, via setAllIndices().
void insertLocalIndicesFiltered(const LocalOrdinal localRow, const Teuchos::ArrayView< const LocalOrdinal > &indices)
Like insertLocalIndices(), but with column Map filtering.
Teuchos::ArrayView< LocalOrdinal > getLocalViewNonConst(const RowInfo rowinfo)
Get a nonconst, nonowned, locally indexed view of the locally owned row myRow, such that rowinfo = ge...
virtual void removeEmptyProcessesInPlace(const Teuchos::RCP< const map_type > &newMap)
Remove processes owning zero rows from the Maps and their communicator.
size_t getNodeNumEntries() const
Returns the local number of entries in the graph.
An abstract interface for graphs accessed by rows.
bool indicesAreSorted_
Whether the graph&#39;s indices are sorted in each row, on this process.
virtual void pack(const Teuchos::ArrayView< const LocalOrdinal > &exportLIDs, Teuchos::Array< GlobalOrdinal > &exports, const Teuchos::ArrayView< size_t > &numPacketsPerLID, size_t &constantNumPackets, Distributor &distor) const
Pack this object&#39;s data for Import or Export.
GlobalOrdinal global_ordinal_type
This class&#39; second template parameter; the type of global indices.
GlobalOrdinal getIndexBase() const
Returns the index base for global indices for this graph.
void removeLocalIndices(LocalOrdinal localRow)
Remove all graph indices from the specified local row.
bool noRedundancies_
Whether the graph&#39;s indices are non-redundant (merged) in each row, on this process.
KokkosClassic::DefaultNode::DefaultNodeType node_type
Default value of Node template parameter.
global_size_t getGlobalNumEntries() const
Returns the global number of entries in the graph.
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.
Teuchos::RCP< const map_type > getRowMap() const
Returns the Map that describes the row distribution in this graph.
void mergeRowIndices(RowInfo rowinfo)
Merge duplicate row indices in the given row.
void setAllIndices(const typename local_graph_type::row_map_type &rowPointers, const typename local_graph_type::entries_type::non_const_type &columnIndices)
Set the graph&#39;s data directly, using 1-D storage.
local_graph_type::entries_type::non_const_type k_lclInds1D_
Local column indices for all rows.
Teuchos::RCP< const map_type > getRangeMap() const
Returns the Map associated with the domain of this graph.
void mergeRowIndicesAndValues(RowInfo rowinfo, const Teuchos::ArrayView< Scalar > &rowValues)
Merge duplicate row indices in the given row, along with their corresponding values.
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.
global_size_t getGlobalNumRows() const
Returns the number of global rows in the graph.
void resumeFill(const Teuchos::RCP< Teuchos::ParameterList > &params=Teuchos::null)
size_t getNodeNumDiags() const
Returns the number of local diagonal entries, based on global row/column index comparisons.
size_t getNumEntriesInGlobalRow(GlobalOrdinal globalRow) const
Returns the current number of entries on this node in the specified global row.
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 getNumEntriesPerLocalRowUpperBound(Teuchos::ArrayRCP< const size_t > &boundPerLocalRow, size_t &boundForAllLocalRows, bool &boundSameForAllLocalRows) const
Get an upper bound on the number of entries that can be stored in each row.
void getLocalRowView(LocalOrdinal LocalRow, Teuchos::ArrayView< const LocalOrdinal > &indices) const
Get a const, non-persisting view of the given local row&#39;s local column indices, as a Teuchos::ArrayVi...
bool isFillComplete() const
Returns true if fillComplete() has been called and the graph is in compute mode.
void fillComplete(const Teuchos::RCP< const map_type > &domainMap, const Teuchos::RCP< const map_type > &rangeMap, const Teuchos::RCP< Teuchos::ParameterList > &params=Teuchos::null)
Tell the graph that you are done changing its structure.
Teuchos::RCP< const Teuchos::Comm< int > > getComm() const
Returns the communicator.
bool upperTriangular_
Whether the graph is locally upper triangular.
void insertGlobalIndices(const GlobalOrdinal globalRow, const Teuchos::ArrayView< const GlobalOrdinal > &indices)
Insert global indices into the graph.
void setParameterList(const Teuchos::RCP< Teuchos::ParameterList > &params)
Set the given list of parameters (must be nonnull).
void getLocalDiagOffsets(const Kokkos::View< size_t *, device_type, Kokkos::MemoryUnmanaged > &offsets) const
Get offsets of the diagonal entries in the graph.
void insertGlobalIndicesFiltered(const GlobalOrdinal localRow, const Teuchos::ArrayView< const GlobalOrdinal > &indices)
Like insertGlobalIndices(), but with column Map filtering.
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.
RowInfo getRowInfo(const LocalOrdinal myRow) const
Get information about the locally owned row with local index myRow.
int local_ordinal_type
Default value of LocalOrdinal template parameter.
Teuchos::ArrayView< const LocalOrdinal > getLocalView(const RowInfo rowinfo) const
Get a const, nonowned, locally indexed view of the locally owned row myRow, such that rowinfo = getRo...
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.
size_t getNodeNumCols() const
Returns the number of columns connected to the locally owned rows of this graph.
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< node_type > getNode() const
Returns the underlying node.
void replaceColMap(const Teuchos::RCP< const map_type > &newColMap)
Replace the graph&#39;s current column Map with the given Map.
Teuchos::RCP< const map_type > colMap_
The Map describing the distribution of columns of the graph.
Implementation details of Tpetra.
bool isSorted() const
Whether graph indices in all rows are known to be sorted.
size_t numAllocForAllRows_
The maximum number of entries to allow in each locally owned row.
Teuchos::RCP< const map_type > getDomainMap() const
Returns the Map associated with the domain of this graph.
size_t global_size_t
Global size_t object.
bool hasRowInfo() const
Whether it is correct to call getRowInfo().
Kokkos::StaticCrsGraph< LocalOrdinal, Kokkos::LayoutLeft, execution_space > local_graph_type
The type of the part of the sparse graph on each MPI process.
Teuchos::RCP< const import_type > getImporter() const
Returns the importer associated with this graph.
bool haveLocalConstants_
Whether this process has computed local constants.
t_GlobalOrdinal_1D k_gblInds1D_
Global column indices for all rows.
size_t getNumAllocatedEntriesInGlobalRow(GlobalOrdinal globalRow) const
Returns the current number of allocated entries for this node in the specified global row ...
Teuchos::ArrayView< const GlobalOrdinal > getGlobalView(const RowInfo rowinfo) const
Get a const, nonowned, globally indexed view of the locally owned row myRow, such that rowinfo = getR...
void getLocalRowCopy(LocalOrdinal LocalRow, const Teuchos::ArrayView< LocalOrdinal > &indices, size_t &NumIndices) const
Get a copy of the given row, using local indices.
local_graph_type lclGraph_
Local graph; only initialized after first fillComplete() call.
void globalAssemble()
Communicate non-local contributions to other processes.
bool isMerged() const
Whether duplicate column indices in each row have been merged.
Communication plan for data redistribution from a (possibly) multiply-owned to a uniquely-owned distr...
Teuchos::RCP< const export_type > getExporter() const
Returns the exporter associated with this graph.
void sortRowIndicesAndValues(const RowInfo rowinfo, const Teuchos::ArrayView< Scalar > &values)
Sort the column indices and their values in the given row.
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const
Default parameter list suitable for validation.
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.
void makeColMap()
Make the graph&#39;s column Map, if it does not already have one.
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.
void getGlobalRowView(GlobalOrdinal GlobalRow, Teuchos::ArrayView< const GlobalOrdinal > &Indices) const
Get a const, non-persisting view of the given global row&#39;s global column indices, as a Teuchos::Array...
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.
size_t getNodeNumRows() const
Returns the number of graph rows owned on the calling node.
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.
void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel=Teuchos::Describable::verbLevel_default) const
Print the object to the given output stream with given verbosity level.
void reindexColumns(const Teuchos::RCP< const map_type > &newColMap, const Teuchos::RCP< const import_type > &newImport=Teuchos::null, const bool sortIndicesInEachRow=true)
Reindex the column indices in place, and replace the column Map. Optionally, replace the Import objec...
void checkInternalState() const
Throw an exception if the internal state is not consistent.
size_t insertIndices(const RowInfo &rowInfo, const SLocalGlobalViews &newInds, const ELocalGlobal lg, const ELocalGlobal I)
Insert indices into the given row.
bool isLocallyIndexed() const
If graph indices are in the local range, this function returns true. Otherwise, this function returns...
Teuchos::ArrayView< GlobalOrdinal > getGlobalViewNonConst(const RowInfo rowinfo)
Get a nonconst, nonowned, globally indexed view of the locally owned row myRow, such that rowinfo = g...
size_t getNodeMaxNumRowEntries() const
Maximum number of entries in all rows owned by the calling process.
bool isUpperTriangular() const
Whether the graph is locally upper triangular.
bool isFillActive() const
Returns true if resumeFill() has been called and the graph is in edit mode.
Teuchos::RCP< const map_type > rowMap_
The Map describing the distribution of rows of the graph.
size_t getGlobalMaxNumRowEntries() const
Maximum number of entries in all rows over all processes.
bool isLowerTriangular() const
Whether the graph is locally lower triangular.
Teuchos::ArrayRCP< Teuchos::Array< LocalOrdinal > > lclInds2D_
Local column indices for all rows.
Teuchos::ArrayRCP< const size_t > getNodeRowPtrs() const
Get a host view of the row offsets.
bool isGloballyIndexed() const
If graph indices are in the global range, this function returns true. Otherwise, this function return...
Tpetra::Map< LocalOrdinal, GlobalOrdinal, Node > map_type
The Map specialization used by this class.
void sort2(const IT1 &first1, const IT1 &last1, const IT2 &first2)
Sort the first array, and apply the resulting permutation to the second array.
A distributed graph accessed by rows (adjacency lists) and stored sparsely.
Describes a parallel distribution of objects over processes.
void setDomainRangeMaps(const Teuchos::RCP< const map_type > &domainMap, const Teuchos::RCP< const map_type > &rangeMap)
Teuchos::RCP< const map_type > getColMap() const
Returns the Map that describes the column distribution in this graph.
size_t getNumEntriesInLocalRow(LocalOrdinal localRow) const
Get the number of entries in the given row (local index).
Details::EStorageStatus storageStatus_
Status of the graph&#39;s storage, when not in a fill-complete state.
std::string description() const
Return a simple one-line description of this object.
LocalOrdinal getLocalViewRawConst(const LocalOrdinal *&lclInds, LocalOrdinal &numEnt, const RowInfo &rowinfo) const
Get a pointer to the local column indices of a locally owned row, using the result of getRowInfo...
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.
size_t getNodeAllocationSize() const
Returns the total number of indices allocated for the graph, across all rows on this node...
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.
void replaceDomainMapAndImporter(const Teuchos::RCP< const map_type > &newDomainMap, const Teuchos::RCP< const import_type > &newImporter)
Replace the current domain Map and Import with the given parameters.
void mergeAllIndices()
Merge duplicate row indices in all of the rows.
void getGlobalRowCopy(GlobalOrdinal GlobalRow, const Teuchos::ArrayView< GlobalOrdinal > &Indices, size_t &NumIndices) const
Get a copy of the given row, using global indices.
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.
static const bool useAtomicUpdatesByDefault
Whether sumIntoLocalValues and transformLocalValues should use atomic updates by default.
void setLocallyModified()
Report that we made a local modification to its structure.
virtual ~CrsGraph()
Destructor.
Kokkos::View< GlobalOrdinal *, execution_space > t_GlobalOrdinal_1D
Type of the k_gblInds1D_ array of global column indices.
bool isStorageOptimized() const
Returns true if storage has been optimized.
Base class for distributed Tpetra objects that support data redistribution.
Tpetra::Export< LocalOrdinal, GlobalOrdinal, Node > export_type
The Export specialization used by this class.
void sortAllIndices()
Sort the column indices in all the rows.
Teuchos::ArrayRCP< const LocalOrdinal > getNodePackedIndices() const
Get an Teuchos::ArrayRCP of the packed column-indices.
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.
void sortRowIndices(const RowInfo rowinfo)
Sort the column indices in the given row.
void insertLocalIndices(const LocalOrdinal localRow, const Teuchos::ArrayView< const LocalOrdinal > &indices)
Insert local indices into the graph.
global_size_t getGlobalNumCols() const
Returns the number of global columns in the graph.
bool hasColMap() const
Whether the graph has a column Map.
global_size_t getGlobalNumDiags() const
Returns the number of global diagonal entries, based on global row/column index comparisons.
EStorageStatus
Status of the graph&#39;s or matrix&#39;s storage, when not in a fill-complete state.
LocalOrdinal getGlobalViewRawConst(const GlobalOrdinal *&gblInds, LocalOrdinal &numEnt, const RowInfo &rowinfo) const
Get a pointer to the global column indices of a locally owned row, using the result of getRowInfoFrom...
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.
size_t getNumAllocatedEntriesInLocalRow(LocalOrdinal localRow) const
Returns the current number of allocated entries on this node in the specified local row...
virtual bool checkSizes(const SrcDistObject &source)
Compare the source and target (this) objects for compatibility.
Kokkos::View< const size_t *, execution_space >::HostMirror k_numAllocPerRow_
The maximum number of entries to allow in each locally owned row, per row.
local_graph_type getLocalGraph() const
Get the local graph.
Tpetra::Import< LocalOrdinal, GlobalOrdinal, Node > import_type
The Import specialization used by this class.