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_ConfigDefs.hpp"
54 #include "Tpetra_RowGraph.hpp"
55 #include "Tpetra_DistObject.hpp"
56 #include "Tpetra_Exceptions.hpp"
57 
58 #include "KokkosCompat_ClassicNodeAPI_Wrapper.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 = Details::DefaultTypes::local_ordinal_type,
264  class GlobalOrdinal = Details::DefaultTypes::global_ordinal_type,
266  const bool classic = Node::classic>
267  class CrsGraph :
268  public RowGraph<LocalOrdinal, GlobalOrdinal, Node>,
269  public DistObject<GlobalOrdinal,
270  LocalOrdinal,
271  GlobalOrdinal,
272  Node>,
273  public Teuchos::ParameterListAcceptorDefaultBase
274  {
275  static_assert (! classic, "The 'classic' version of Tpetra was deprecated long ago, and has been removed.");
276 
277  template <class S, class LO, class GO, class N, const bool isClassic>
278  friend class CrsMatrix;
279  template <class LO2, class GO2, class N2, const bool isClassic>
280  friend class CrsGraph;
281  template <class S, class LO, class GO, class N>
282  friend class ::Tpetra::Experimental::BlockCrsMatrix;
283 
286 
287  public:
289  typedef LocalOrdinal local_ordinal_type;
291  typedef GlobalOrdinal global_ordinal_type;
293  typedef Node node_type;
294 
296  typedef typename Node::device_type device_type;
298  typedef typename device_type::execution_space execution_space;
299 
301  typedef Kokkos::StaticCrsGraph<LocalOrdinal,
302  Kokkos::LayoutLeft,
303  execution_space> local_graph_type;
305  typedef local_graph_type LocalStaticCrsGraphType TPETRA_DEPRECATED;
306 
308  typedef typename local_graph_type::row_map_type t_RowPtrs TPETRA_DEPRECATED;
310  typedef typename local_graph_type::row_map_type::non_const_type t_RowPtrsNC TPETRA_DEPRECATED;
312  typedef typename local_graph_type::entries_type::non_const_type t_LocalOrdinal_1D TPETRA_DEPRECATED;
313 
320 
322 
323 
342  CrsGraph (const Teuchos::RCP<const map_type>& rowMap,
343  size_t maxNumEntriesPerRow,
344  ProfileType pftype = DynamicProfile,
345  const Teuchos::RCP<Teuchos::ParameterList>& params = Teuchos::null);
346 
364  CrsGraph (const Teuchos::RCP<const map_type>& rowMap,
365  const Kokkos::DualView<const size_t*, execution_space>& numEntPerRow,
366  const ProfileType pftype = DynamicProfile,
367  const Teuchos::RCP<Teuchos::ParameterList>& params = Teuchos::null);
368 
387  CrsGraph (const Teuchos::RCP<const map_type>& rowMap,
388  const Teuchos::ArrayRCP<const size_t>& numEntPerRow,
389  const ProfileType pftype = DynamicProfile,
390  const Teuchos::RCP<Teuchos::ParameterList>& params = Teuchos::null);
391 
413  CrsGraph (const Teuchos::RCP<const map_type>& rowMap,
414  const Teuchos::RCP<const map_type>& colMap,
415  const size_t maxNumEntriesPerRow,
416  const ProfileType pftype = DynamicProfile,
417  const Teuchos::RCP<Teuchos::ParameterList>& params = 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 = 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 = 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 = 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 = 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 ParameterList> getValidParameters () const;
591 
593 
595 
617  void
618  insertGlobalIndices (GlobalOrdinal globalRow,
619  const Teuchos::ArrayView<const GlobalOrdinal>& indices);
620 
622 
636  void
637  insertLocalIndices (const LocalOrdinal localRow,
638  const Teuchos::ArrayView<const LocalOrdinal> &indices);
639 
641 
650  void removeLocalIndices (LocalOrdinal localRow);
651 
653 
660 
666  void globalAssemble ();
667 
676  void resumeFill (const Teuchos::RCP<Teuchos::ParameterList>& params = Teuchos::null);
677 
695  void
696  fillComplete (const Teuchos::RCP<const map_type> &domainMap,
697  const Teuchos::RCP<const map_type> &rangeMap,
698  const Teuchos::RCP<Teuchos::ParameterList>& params = Teuchos::null);
699 
706  void fillComplete (const Teuchos::RCP<Teuchos::ParameterList>& params = Teuchos::null);
707 
718  void
719  expertStaticFillComplete (const Teuchos::RCP<const map_type> & domainMap,
720  const Teuchos::RCP<const map_type> & rangeMap,
721  const Teuchos::RCP<const import_type> &importer=Teuchos::null,
722  const Teuchos::RCP<const export_type> &exporter=Teuchos::null,
723  const Teuchos::RCP<Teuchos::ParameterList> &params=Teuchos::null);
725 
727 
729  Teuchos::RCP<const Comm<int> > getComm() const;
730 
732  Teuchos::RCP<node_type> getNode() const;
733 
735  Teuchos::RCP<const map_type> getRowMap () const;
736 
738  Teuchos::RCP<const map_type> getColMap () const;
739 
741  Teuchos::RCP<const map_type> getDomainMap () const;
742 
744  Teuchos::RCP<const map_type> getRangeMap () const;
745 
747  Teuchos::RCP<const import_type> getImporter () const;
748 
750  Teuchos::RCP<const export_type> getExporter () const;
751 
753 
755  global_size_t getGlobalNumRows() const;
756 
758 
761  global_size_t getGlobalNumCols() const;
762 
764  size_t getNodeNumRows() const;
765 
767 
769  size_t getNodeNumCols() const;
770 
772  GlobalOrdinal getIndexBase() const;
773 
775 
777  global_size_t getGlobalNumEntries() const;
778 
780  size_t getNodeNumEntries() const;
781 
783 
784  size_t getNumEntriesInGlobalRow(GlobalOrdinal globalRow) const;
785 
787 
788  size_t getNumEntriesInLocalRow(LocalOrdinal localRow) const;
789 
791 
798  size_t getNodeAllocationSize() const;
799 
801 
802  size_t getNumAllocatedEntriesInGlobalRow(GlobalOrdinal globalRow) const;
803 
805 
806  size_t getNumAllocatedEntriesInLocalRow(LocalOrdinal localRow) const;
807 
809 
811  global_size_t getGlobalNumDiags() const;
812 
814 
816  size_t getNodeNumDiags() const;
817 
830  size_t getGlobalMaxNumRowEntries() const;
831 
833 
835  size_t getNodeMaxNumRowEntries() const;
836 
851  bool hasColMap() const;
852 
860  bool isLowerTriangular() const;
861 
869  bool isUpperTriangular() const;
870 
872  bool isLocallyIndexed() const;
873 
875  bool isGloballyIndexed() const;
876 
878  bool isFillComplete() const;
879 
881  bool isFillActive() const;
882 
890  bool isSorted() const;
891 
893 
899  bool isStorageOptimized() const;
900 
902  ProfileType getProfileType() const;
903 
909  void
910  getGlobalRowCopy (GlobalOrdinal GlobalRow,
911  const Teuchos::ArrayView<GlobalOrdinal>& Indices,
912  size_t& NumIndices) const;
913 
921  void
922  getLocalRowCopy (LocalOrdinal LocalRow,
923  const Teuchos::ArrayView<LocalOrdinal>& indices,
924  size_t& NumIndices) const;
925 
927 
935  void
936  getGlobalRowView (GlobalOrdinal GlobalRow,
937  Teuchos::ArrayView<const GlobalOrdinal>& Indices) const;
938 
940 
948  void
949  getLocalRowView (LocalOrdinal LocalRow,
950  Teuchos::ArrayView<const LocalOrdinal>& indices) const;
951 
953 
955 
957  std::string description() const;
958 
960  void
961  describe (Teuchos::FancyOStream& out,
962  const Teuchos::EVerbosityLevel verbLevel =
963  Teuchos::Describable::verbLevel_default) const;
964 
966 
968 
969  virtual bool
970  checkSizes (const SrcDistObject& source);
971 
972  virtual void
973  copyAndPermute (const SrcDistObject& source,
974  size_t numSameIDs,
975  const Teuchos::ArrayView<const LocalOrdinal> &permuteToLIDs,
976  const Teuchos::ArrayView<const LocalOrdinal> &permuteFromLIDs);
977 
978  virtual void
979  packAndPrepare (const SrcDistObject& source,
980  const Teuchos::ArrayView<const LocalOrdinal> &exportLIDs,
981  Teuchos::Array<GlobalOrdinal> &exports,
982  const Teuchos::ArrayView<size_t> & numPacketsPerLID,
983  size_t& constantNumPackets,
984  Distributor &distor);
985 
986  virtual void
987  pack (const Teuchos::ArrayView<const LocalOrdinal>& exportLIDs,
988  Teuchos::Array<GlobalOrdinal>& exports,
989  const Teuchos::ArrayView<size_t>& numPacketsPerLID,
990  size_t& constantNumPackets,
991  Distributor& distor) const;
992 
993  virtual void
994  unpackAndCombine (const Teuchos::ArrayView<const LocalOrdinal> &importLIDs,
995  const Teuchos::ArrayView<const GlobalOrdinal> &imports,
996  const Teuchos::ArrayView<size_t> &numPacketsPerLID,
997  size_t constantNumPackets,
998  Distributor &distor,
999  CombineMode CM);
1001 
1003 
1026  void
1027  getNumEntriesPerLocalRowUpperBound (Teuchos::ArrayRCP<const size_t>& boundPerLocalRow,
1028  size_t& boundForAllLocalRows,
1029  bool& boundSameForAllLocalRows) const;
1030 
1039  void
1040  setAllIndices (const typename local_graph_type::row_map_type& rowPointers,
1041  const typename local_graph_type::entries_type::non_const_type& columnIndices);
1042 
1051  void
1052  setAllIndices (const Teuchos::ArrayRCP<size_t> & rowPointers,
1053  const Teuchos::ArrayRCP<LocalOrdinal> & columnIndices);
1054 
1062  Teuchos::ArrayRCP<const size_t> getNodeRowPtrs () const;
1063 
1065 
1067  Teuchos::ArrayRCP<const LocalOrdinal> getNodePackedIndices() const;
1068 
1079  void replaceColMap (const Teuchos::RCP<const map_type>& newColMap);
1080 
1100  void
1101  reindexColumns (const Teuchos::RCP<const map_type>& newColMap,
1102  const Teuchos::RCP<const import_type>& newImport = Teuchos::null,
1103  const bool sortIndicesInEachRow = true);
1104 
1117  void
1118  replaceDomainMapAndImporter (const Teuchos::RCP<const map_type>& newDomainMap,
1119  const Teuchos::RCP<const import_type>& newImporter);
1120 
1148  virtual void
1149  removeEmptyProcessesInPlace (const Teuchos::RCP<const map_type>& newMap);
1151 
1152  template<class ViewType, class OffsetViewType >
1153  struct pack_functor {
1154  typedef typename ViewType::execution_space execution_space;
1155  ViewType src;
1156  ViewType dest;
1157  OffsetViewType src_offset;
1158  OffsetViewType dest_offset;
1159  typedef typename OffsetViewType::non_const_value_type ScalarIndx;
1160 
1161  pack_functor(ViewType dest_, ViewType src_, OffsetViewType dest_offset_, OffsetViewType src_offset_):
1162  src(src_),dest(dest_),src_offset(src_offset_),dest_offset(dest_offset_) {};
1163 
1164  KOKKOS_INLINE_FUNCTION
1165  void operator() (size_t row) const {
1166  ScalarIndx i = src_offset(row);
1167  ScalarIndx j = dest_offset(row);
1168  const ScalarIndx k = dest_offset(row+1);
1169  for(;j<k;j++,i++) {
1170  dest(j) = src(i);
1171  }
1172  }
1173  };
1174 
1175  protected:
1176  // these structs are conveniences, to cut down on the number of
1177  // arguments to some of the methods below.
1178  struct SLocalGlobalViews {
1179  Teuchos::ArrayView<const GlobalOrdinal> ginds;
1180  Teuchos::ArrayView<const LocalOrdinal> linds;
1181  };
1182  struct SLocalGlobalNCViews {
1183  Teuchos::ArrayView<GlobalOrdinal> ginds;
1184  Teuchos::ArrayView<LocalOrdinal> linds;
1185  };
1186 
1187  bool indicesAreAllocated () const;
1188  void allocateIndices (const ELocalGlobal lg);
1189 
1190  template <class T>
1191  Teuchos::ArrayRCP<Teuchos::Array<T> > allocateValues2D () const;
1192 
1193  template <class T>
1194  RowInfo updateLocalAllocAndValues (const RowInfo rowInfo,
1195  const size_t newAllocSize,
1196  Teuchos::Array<T>& rowVals)
1197  {
1198 #ifdef HAVE_TPETRA_DEBUG
1199  TEUCHOS_TEST_FOR_EXCEPT( ! isLocallyIndexed () );
1200  TEUCHOS_TEST_FOR_EXCEPT( ! indicesAreAllocated() );
1201  TEUCHOS_TEST_FOR_EXCEPT( newAllocSize == 0 );
1202  TEUCHOS_TEST_FOR_EXCEPT( newAllocSize < rowInfo.allocSize );
1203  TEUCHOS_TEST_FOR_EXCEPT( ! rowMap_->isNodeLocalElement (rowInfo.localRow) );
1204 #endif // HAVE_TPETRA_DEBUG
1205 
1206  // Teuchos::ArrayRCP::resize automatically copies over values on reallocation.
1207  lclInds2D_[rowInfo.localRow].resize (newAllocSize);
1208  rowVals.resize (newAllocSize);
1209  nodeNumAllocated_ += (newAllocSize - rowInfo.allocSize);
1210 
1211  RowInfo rowInfoOut = rowInfo;
1212  rowInfoOut.allocSize = newAllocSize;
1213  return rowInfoOut;
1214  }
1215 
1216  template <class T>
1217  RowInfo
1218  updateGlobalAllocAndValues (const RowInfo rowInfo,
1219  const size_t newAllocSize,
1220  Teuchos::Array<T>& rowVals)
1221  {
1222 #ifdef HAVE_TPETRA_DEBUG
1223  TEUCHOS_TEST_FOR_EXCEPT( ! isGloballyIndexed () );
1224  TEUCHOS_TEST_FOR_EXCEPT( ! indicesAreAllocated () );
1225  TEUCHOS_TEST_FOR_EXCEPT( newAllocSize == 0 );
1226  TEUCHOS_TEST_FOR_EXCEPT( newAllocSize < rowInfo.allocSize );
1227  TEUCHOS_TEST_FOR_EXCEPT( ! rowMap_->isNodeLocalElement (rowInfo.localRow) );
1228 #endif // HAVE_TPETRA_DEBUG
1229 
1230  // Teuchos::ArrayRCP::resize automatically copies over values on reallocation.
1231  gblInds2D_[rowInfo.localRow].resize (newAllocSize);
1232  rowVals.resize (newAllocSize);
1233  nodeNumAllocated_ += (newAllocSize - rowInfo.allocSize);
1234 
1235  RowInfo rowInfoOut = rowInfo;
1236  rowInfoOut.allocSize = newAllocSize;
1237  return rowInfoOut;
1238  }
1239 
1241 
1242 
1244  void makeColMap ();
1245  void makeIndicesLocal ();
1246  void makeImportExport ();
1247 
1249 
1251 
1252  template<ELocalGlobal lg>
1253  size_t filterIndices (const SLocalGlobalNCViews& inds) const
1254  {
1255  using Teuchos::ArrayView;
1256  static_assert (lg == GlobalIndices || lg == LocalIndices,
1257  "Tpetra::CrsGraph::filterIndices: The template parameter "
1258  "lg must be either GlobalIndices or LocalIndicies.");
1259 
1260  const map_type& cmap = *colMap_;
1261  size_t numFiltered = 0;
1262 #ifdef HAVE_TPETRA_DEBUG
1263  size_t numFiltered_debug = 0;
1264 #endif
1265  if (lg == GlobalIndices) {
1266  ArrayView<GlobalOrdinal> ginds = inds.ginds;
1267  typename ArrayView<GlobalOrdinal>::iterator fend = ginds.begin();
1268  typename ArrayView<GlobalOrdinal>::iterator cptr = ginds.begin();
1269  while (cptr != ginds.end()) {
1270  if (cmap.isNodeGlobalElement(*cptr)) {
1271  *fend++ = *cptr;
1272 #ifdef HAVE_TPETRA_DEBUG
1273  ++numFiltered_debug;
1274 #endif
1275  }
1276  ++cptr;
1277  }
1278  numFiltered = fend - ginds.begin();
1279  }
1280  else if (lg == LocalIndices) {
1281  ArrayView<LocalOrdinal> linds = inds.linds;
1282  typename ArrayView<LocalOrdinal>::iterator fend = linds.begin();
1283  typename ArrayView<LocalOrdinal>::iterator cptr = linds.begin();
1284  while (cptr != linds.end()) {
1285  if (cmap.isNodeLocalElement(*cptr)) {
1286  *fend++ = *cptr;
1287 #ifdef HAVE_TPETRA_DEBUG
1288  ++numFiltered_debug;
1289 #endif
1290  }
1291  ++cptr;
1292  }
1293  numFiltered = fend - linds.begin();
1294  }
1295 #ifdef HAVE_TPETRA_DEBUG
1296  TEUCHOS_TEST_FOR_EXCEPT( numFiltered != numFiltered_debug );
1297 #endif
1298  return numFiltered;
1299  }
1300 
1301 
1302  template<class T>
1303  size_t
1304  filterGlobalIndicesAndValues (const Teuchos::ArrayView<GlobalOrdinal>& ginds,
1305  const Teuchos::ArrayView<T>& vals) const
1306  {
1307  using Teuchos::ArrayView;
1308  const map_type& cmap = *colMap_;
1309  size_t numFiltered = 0;
1310  typename ArrayView<T>::iterator fvalsend = vals.begin();
1311  typename ArrayView<T>::iterator valscptr = vals.begin();
1312 #ifdef HAVE_TPETRA_DEBUG
1313  size_t numFiltered_debug = 0;
1314 #endif
1315  typename ArrayView<GlobalOrdinal>::iterator fend = ginds.begin();
1316  typename ArrayView<GlobalOrdinal>::iterator cptr = ginds.begin();
1317  while (cptr != ginds.end()) {
1318  if (cmap.isNodeGlobalElement (*cptr)) {
1319  *fend++ = *cptr;
1320  *fvalsend++ = *valscptr;
1321 #ifdef HAVE_TPETRA_DEBUG
1322  ++numFiltered_debug;
1323 #endif
1324  }
1325  ++cptr;
1326  ++valscptr;
1327  }
1328  numFiltered = fend - ginds.begin();
1329 #ifdef HAVE_TPETRA_DEBUG
1330  TEUCHOS_TEST_FOR_EXCEPT( numFiltered != numFiltered_debug );
1331  TEUCHOS_TEST_FOR_EXCEPT( valscptr != vals.end() );
1332  const size_t numFilteredActual =
1333  static_cast<size_t> (fvalsend - vals.begin ());
1334  TEUCHOS_TEST_FOR_EXCEPT( numFiltered != numFilteredActual );
1335 #endif // HAVE_TPETRA_DEBUG
1336  return numFiltered;
1337  }
1338 
1339  template<class T>
1340  size_t
1341  filterLocalIndicesAndValues (const Teuchos::ArrayView<LocalOrdinal>& linds,
1342  const Teuchos::ArrayView<T>& vals) const
1343  {
1344  using Teuchos::ArrayView;
1345  const map_type& cmap = *colMap_;
1346  size_t numFiltered = 0;
1347  typename ArrayView<T>::iterator fvalsend = vals.begin();
1348  typename ArrayView<T>::iterator valscptr = vals.begin();
1349 #ifdef HAVE_TPETRA_DEBUG
1350  size_t numFiltered_debug = 0;
1351 #endif
1352  typename ArrayView<LocalOrdinal>::iterator fend = linds.begin();
1353  typename ArrayView<LocalOrdinal>::iterator cptr = linds.begin();
1354  while (cptr != linds.end()) {
1355  if (cmap.isNodeLocalElement (*cptr)) {
1356  *fend++ = *cptr;
1357  *fvalsend++ = *valscptr;
1358 #ifdef HAVE_TPETRA_DEBUG
1359  ++numFiltered_debug;
1360 #endif
1361  }
1362  ++cptr;
1363  ++valscptr;
1364  }
1365  numFiltered = fend - linds.begin();
1366 #ifdef HAVE_TPETRA_DEBUG
1367  TEUCHOS_TEST_FOR_EXCEPT( numFiltered != numFiltered_debug );
1368  TEUCHOS_TEST_FOR_EXCEPT( valscptr != vals.end() );
1369  const size_t numFilteredActual =
1370  Teuchos::as<size_t> (fvalsend - vals.begin ());
1371  TEUCHOS_TEST_FOR_EXCEPT( numFiltered != numFilteredActual );
1372 #endif
1373  return numFiltered;
1374  }
1375 
1405  size_t
1406  insertIndices (const RowInfo& rowInfo,
1407  const SLocalGlobalViews& newInds,
1408  const ELocalGlobal lg,
1409  const ELocalGlobal I);
1410 
1450  template<class Scalar>
1451  void
1452  insertIndicesAndValues (const RowInfo& rowInfo,
1453  const SLocalGlobalViews& newInds,
1454  const Teuchos::ArrayView<Scalar>& oldRowVals,
1455  const Teuchos::ArrayView<const Scalar>& newRowVals,
1456  const ELocalGlobal lg,
1457  const ELocalGlobal I);
1458  void
1459  insertGlobalIndicesImpl (const LocalOrdinal myRow,
1460  const Teuchos::ArrayView<const GlobalOrdinal> &indices);
1461  void
1462  insertLocalIndicesImpl (const LocalOrdinal myRow,
1463  const Teuchos::ArrayView<const LocalOrdinal> &indices);
1465  void
1466  insertLocalIndicesFiltered (const LocalOrdinal localRow,
1467  const Teuchos::ArrayView<const LocalOrdinal> &indices);
1468 
1470  void
1471  insertGlobalIndicesFiltered (const GlobalOrdinal localRow,
1472  const Teuchos::ArrayView<const GlobalOrdinal> &indices);
1473 
1478  static const bool useAtomicUpdatesByDefault =
1479 #ifdef KOKKOS_HAVE_SERIAL
1480  ! std::is_same<execution_space, Kokkos::Serial>::value;
1481 #else
1482  true;
1483 #endif // KOKKOS_HAVE_SERIAL
1484 
1523  template<class OutputScalarViewType,
1524  class LocalIndicesViewType,
1525  class InputScalarViewType,
1526  class BinaryFunction>
1527  typename std::enable_if<Kokkos::is_view<OutputScalarViewType>::value &&
1528  Kokkos::is_view<LocalIndicesViewType>::value &&
1529  Kokkos::is_view<InputScalarViewType>::value &&
1530  std::is_same<typename OutputScalarViewType::non_const_value_type,
1531  typename InputScalarViewType::non_const_value_type>::value &&
1532  std::is_same<typename LocalIndicesViewType::non_const_value_type,
1533  local_ordinal_type>::value,
1534  LocalOrdinal>::type
1536  const typename UnmanagedView<OutputScalarViewType>::type& rowVals,
1537  const typename UnmanagedView<LocalIndicesViewType>::type& inds,
1538  const typename UnmanagedView<InputScalarViewType>::type& newVals,
1539  BinaryFunction f,
1540  const bool atomic = useAtomicUpdatesByDefault) const
1541  {
1542  typedef typename OutputScalarViewType::non_const_value_type ST;
1543  typedef LocalOrdinal LO;
1544  typedef GlobalOrdinal GO;
1545 
1546  if (newVals.dimension_0 () != inds.dimension_0 ()) {
1547  // The sizes of the input arrays must match.
1548  return Teuchos::OrdinalTraits<LO>::invalid ();
1549  }
1550  const size_t STINV = Teuchos::OrdinalTraits<size_t>::invalid ();
1551  const LO numElts = static_cast<LO> (inds.dimension_0 ());
1552  LO numValid = 0; // number of valid input column indices
1553  size_t hint = 0; // Guess for the current index k into rowVals
1554 
1555  if (isLocallyIndexed ()) {
1556  // Get a view of the column indices in the row. This amortizes
1557  // the cost of getting the view over all the entries of inds.
1558  auto colInds = this->getLocalKokkosRowView (rowInfo);
1559 
1560  for (LO j = 0; j < numElts; ++j) {
1561  const size_t k =
1562  this->findLocalIndex (rowInfo, inds(j), colInds, hint);
1563  if (k != STINV) {
1564  if (atomic) {
1565  // NOTE (mfh 30 Nov 2015) The commented-out code is
1566  // wrong because another thread may have changed
1567  // rowVals(k) between those two lines of code.
1568  //
1569  //const ST newVal = f (rowVals(k), newVals(j));
1570  //Kokkos::atomic_assign (&rowVals(k), newVal);
1571 
1572  volatile ST* const dest = &rowVals(k);
1573  (void) atomic_binary_function_update (dest, newVals(j), f);
1574  }
1575  else {
1576  rowVals(k) = f (rowVals(k), newVals(j)); // use binary function f
1577  }
1578  hint = k+1;
1579  ++numValid;
1580  }
1581  }
1582  }
1583  else if (isGloballyIndexed ()) {
1584  // NOTE (mfh 26 Nov 2015) Dereferencing an RCP or reading its
1585  // pointer does NOT change its reference count. Thus, this
1586  // code is still thread safe.
1587  if (colMap_.is_null ()) {
1588  // NO input column indices are valid in this case. Either
1589  // the column Map hasn't been set yet (so local indices
1590  // don't exist yet), or the calling process owns no graph
1591  // entries.
1592  return numValid;
1593  }
1594  const map_type& colMap = *colMap_;
1595  // Get a view of the column indices in the row. This amortizes
1596  // the cost of getting the view over all the entries of inds.
1597  auto colInds = this->getGlobalKokkosRowView (rowInfo);
1598 
1599  const GO GINV = Teuchos::OrdinalTraits<GO>::invalid ();
1600  for (LO j = 0; j < numElts; ++j) {
1601  const GO gblColInd = colMap.getGlobalElement (inds(j));
1602  if (gblColInd != GINV) {
1603  const size_t k =
1604  this->findGlobalIndex (rowInfo, gblColInd, colInds, hint);
1605  if (k != STINV) {
1606  if (atomic) {
1607  // NOTE (mfh 30 Nov 2015) The commented-out code is
1608  // wrong because another thread may have changed
1609  // rowVals(k) between those two lines of code.
1610  //
1611  //const ST newVal = f (rowVals(k), newVals(j));
1612  //Kokkos::atomic_assign (&rowVals(k), newVal);
1613 
1614  volatile ST* const dest = &rowVals(k);
1615  (void) atomic_binary_function_update (dest, newVals(j), f);
1616  }
1617  else {
1618  rowVals(k) = f (rowVals(k), newVals(j)); // use binary function f
1619  }
1620  hint = k+1;
1621  numValid++;
1622  }
1623  }
1624  }
1625  }
1626  // If the graph is neither locally nor globally indexed on the
1627  // calling process, that means the calling process has no graph
1628  // entries. Thus, none of the input column indices are valid.
1629 
1630  return numValid;
1631  }
1632 
1652  template<class OutputScalarViewType,
1653  class LocalIndicesViewType,
1654  class InputScalarViewType>
1655  typename std::enable_if<Kokkos::is_view<OutputScalarViewType>::value &&
1656  Kokkos::is_view<LocalIndicesViewType>::value &&
1657  Kokkos::is_view<InputScalarViewType>::value &&
1658  std::is_same<typename OutputScalarViewType::non_const_value_type,
1659  typename InputScalarViewType::non_const_value_type>::value &&
1660  std::is_same<typename LocalIndicesViewType::non_const_value_type,
1661  local_ordinal_type>::value,
1662  LocalOrdinal>::type
1663  sumIntoLocalValues (const RowInfo& rowInfo,
1664  const typename UnmanagedView<OutputScalarViewType>::type& rowVals,
1665  const typename UnmanagedView<LocalIndicesViewType>::type& inds,
1666  const typename UnmanagedView<InputScalarViewType>::type& newVals,
1667  const bool atomic = useAtomicUpdatesByDefault) const
1668  {
1669  typedef LocalOrdinal LO;
1670  typedef GlobalOrdinal GO;
1671 
1672  // Don't call this->hasColMap(), because that changes RCP's
1673  // reference count, which is not thread safe. Just
1674  // dereferencing an RCP or calling RCP::is_null() does not
1675  // change its reference count.
1676  if (colMap_.is_null ()) {
1677  // No such thing as local column indices without a column Map.
1678  return Teuchos::OrdinalTraits<LO>::invalid ();
1679  }
1680  else if (newVals.dimension_0 () != inds.dimension_0 ()) {
1681  // The dimensions of the input arrays must match.
1682  return Teuchos::OrdinalTraits<LO>::invalid ();
1683  }
1684 
1685  const size_t STINV = Teuchos::OrdinalTraits<size_t>::invalid ();
1686  size_t hint = 0; // Guess for the current index k into rowVals
1687  LO numValid = 0; // number of valid local column indices
1688 
1689  // NOTE (mfh 11 Oct 2015) This method assumes UVM. More
1690  // accurately, it assumes that the host execution space can
1691  // access data in both InputMemorySpace and ValsMemorySpace.
1692 
1693  if (isLocallyIndexed ()) {
1694  // Get a view of the column indices in the row. This amortizes
1695  // the cost of getting the view over all the entries of inds.
1696  auto colInds = this->getLocalKokkosRowView (rowInfo);
1697 
1698  const LO numElts = static_cast<LO> (inds.dimension_0 ());
1699  for (LO j = 0; j < numElts; ++j) {
1700  const size_t k = this->findLocalIndex (rowInfo, inds(j), colInds, hint);
1701  if (k != STINV) {
1702  if (atomic) {
1703  Kokkos::atomic_add (&rowVals(k), newVals(j));
1704  }
1705  else {
1706  rowVals(k) += newVals(j);
1707  }
1708  hint = k+1;
1709  ++numValid;
1710  }
1711  }
1712  }
1713  else if (isGloballyIndexed ()) {
1714  // Get a view of the column indices in the row. This amortizes
1715  // the cost of getting the view over all the entries of inds.
1716  auto colInds = this->getGlobalKokkosRowView (rowInfo);
1717 
1718  const LO numElts = static_cast<LO> (inds.dimension_0 ());
1719  for (LO j = 0; j < numElts; ++j) {
1720  const GO gblColInd = this->colMap_->getGlobalElement (inds(j));
1721  if (gblColInd != Teuchos::OrdinalTraits<GO>::invalid ()) {
1722  const size_t k =
1723  this->findGlobalIndex (rowInfo, gblColInd, colInds, hint);
1724  if (k != STINV) {
1725  if (atomic) {
1726  Kokkos::atomic_add (&rowVals(k), newVals(j));
1727  }
1728  else {
1729  rowVals(k) += newVals(j);
1730  }
1731  hint = k+1;
1732  ++numValid;
1733  }
1734  }
1735  }
1736  }
1737  // NOTE (mfh 26 Jun 2014, 26 Nov 2015) In the current version of
1738  // CrsGraph and CrsMatrix, it's possible for a matrix (or graph)
1739  // to be neither locally nor globally indexed on a process.
1740  // This means that the graph or matrix has no entries on that
1741  // process. Epetra also works like this. It's related to lazy
1742  // allocation (on first insertion, not at graph / matrix
1743  // construction). Lazy allocation will go away because it is
1744  // not thread scalable.
1745 
1746  return numValid;
1747  }
1748 
1768  template<class OutputScalarViewType,
1769  class LocalIndicesViewType,
1770  class InputScalarViewType>
1771  typename std::enable_if<Kokkos::is_view<OutputScalarViewType>::value &&
1772  Kokkos::is_view<LocalIndicesViewType>::value &&
1773  Kokkos::is_view<InputScalarViewType>::value &&
1774  std::is_same<typename OutputScalarViewType::non_const_value_type,
1775  typename InputScalarViewType::non_const_value_type>::value &&
1776  std::is_same<typename LocalIndicesViewType::non_const_value_type,
1777  local_ordinal_type>::value,
1778  LocalOrdinal>::type
1779  replaceLocalValues (const RowInfo& rowInfo,
1780  const typename UnmanagedView<OutputScalarViewType>::type& rowVals,
1781  const typename UnmanagedView<LocalIndicesViewType>::type& inds,
1782  const typename UnmanagedView<InputScalarViewType>::type& newVals) const
1783  {
1784  typedef LocalOrdinal LO;
1785  typedef GlobalOrdinal GO;
1786 
1787  // Don't call this->hasColMap(), because that changes RCP's
1788  // reference count, which is not thread safe. Just
1789  // dereferencing an RCP or calling RCP::is_null() does not
1790  // change its reference count.
1791  if (colMap_.is_null ()) {
1792  // No such thing as local column indices without a column Map.
1793  return Teuchos::OrdinalTraits<LO>::invalid ();
1794  }
1795  else if (newVals.dimension_0 () != inds.dimension_0 ()) {
1796  // The dimensions of the input arrays must match.
1797  return Teuchos::OrdinalTraits<LO>::invalid ();
1798  }
1799 
1800  const size_t STINV = Teuchos::OrdinalTraits<size_t>::invalid ();
1801  size_t hint = 0; // Guess for the current index k into rowVals
1802  LO numValid = 0; // number of valid local column indices
1803 
1804  // NOTE (mfh 11 Oct 2015) This method assumes UVM. More
1805  // accurately, it assumes that the host execution space can
1806  // access data in both InputMemorySpace and ValsMemorySpace.
1807 
1808  if (isLocallyIndexed ()) {
1809  // Get a view of the column indices in the row. This amortizes
1810  // the cost of getting the view over all the entries of inds.
1811  auto colInds = this->getLocalKokkosRowView (rowInfo);
1812 
1813  const LO numElts = static_cast<LO> (inds.dimension_0 ());
1814  for (LO j = 0; j < numElts; ++j) {
1815  const size_t k = this->findLocalIndex (rowInfo, inds(j), colInds, hint);
1816  if (k != STINV) {
1817  rowVals(k) = newVals(j);
1818  hint = k+1;
1819  ++numValid;
1820  }
1821  }
1822  }
1823  else if (isGloballyIndexed ()) {
1824  // Get a view of the column indices in the row. This amortizes
1825  // the cost of getting the view over all the entries of inds.
1826  auto colInds = this->getGlobalKokkosRowView (rowInfo);
1827 
1828  const LO numElts = static_cast<LO> (inds.dimension_0 ());
1829  for (LO j = 0; j < numElts; ++j) {
1830  const GO gblColInd = this->colMap_->getGlobalElement (inds(j));
1831  if (gblColInd != Teuchos::OrdinalTraits<GO>::invalid ()) {
1832  const size_t k =
1833  this->findGlobalIndex (rowInfo, gblColInd, colInds, hint);
1834  if (k != STINV) {
1835  rowVals(k) = newVals(j);
1836  hint = k+1;
1837  ++numValid;
1838  }
1839  }
1840  }
1841  }
1842  // NOTE (mfh 26 Jun 2014, 26 Nov 2015) In the current version of
1843  // CrsGraph and CrsMatrix, it's possible for a matrix (or graph)
1844  // to be neither locally nor globally indexed on a process.
1845  // This means that the graph or matrix has no entries on that
1846  // process. Epetra also works like this. It's related to lazy
1847  // allocation (on first insertion, not at graph / matrix
1848  // construction). Lazy allocation will go away because it is
1849  // not thread scalable.
1850 
1851  return numValid;
1852  }
1853 
1877  template<class Scalar, class InputMemorySpace, class ValsMemorySpace>
1878  LocalOrdinal
1879  sumIntoGlobalValues (const RowInfo& rowInfo,
1880  const Kokkos::View<Scalar*, ValsMemorySpace,
1881  Kokkos::MemoryUnmanaged>& rowVals,
1882  const Kokkos::View<const GlobalOrdinal*, InputMemorySpace,
1883  Kokkos::MemoryUnmanaged>& inds,
1884  const Kokkos::View<const Scalar*, InputMemorySpace,
1885  Kokkos::MemoryUnmanaged>& newVals,
1886  const bool atomic = useAtomicUpdatesByDefault) const
1887  {
1888  typedef LocalOrdinal LO;
1889 
1890  if (newVals.dimension_0 () != inds.dimension_0 ()) {
1891  // The dimensions of the input arrays must match.
1892  return Teuchos::OrdinalTraits<LO>::invalid ();
1893  }
1894 
1895  const size_t STINV = Teuchos::OrdinalTraits<size_t>::invalid ();
1896  size_t hint = 0; // guess at the index's relative offset in the row
1897  LO numValid = 0; // number of valid input column indices
1898 
1899  // NOTE (mfh 11 Oct 2015) This method assumes UVM. More
1900  // accurately, it assumes that the host execution space can
1901  // access data in both InputMemorySpace and ValsMemorySpace.
1902 
1903  if (isLocallyIndexed ()) {
1904  // NOTE (mfh 04 Nov 2015) Dereferencing an RCP or reading its
1905  // pointer does NOT change its reference count. Thus, this
1906  // code is still thread safe.
1907  if (colMap_.is_null ()) {
1908  // NO input column indices are valid in this case, since if
1909  // the column Map is null on the calling process, then the
1910  // calling process owns no graph entries.
1911  return numValid;
1912  }
1913  // Get a view of the column indices in the row. This amortizes
1914  // the cost of getting the view over all the entries of inds.
1915  auto colInds = this->getLocalKokkosRowView (rowInfo);
1916  const LO LINV = Teuchos::OrdinalTraits<LO>::invalid ();
1917 
1918  const LO numElts = static_cast<LO> (inds.dimension_0 ());
1919  for (LO j = 0; j < numElts; ++j) {
1920  const LO lclColInd = this->colMap_->getLocalElement (inds(j));
1921  if (lclColInd != LINV) {
1922  const size_t k =
1923  this->findLocalIndex (rowInfo, lclColInd, colInds, hint);
1924  if (k != STINV) {
1925  if (atomic) {
1926  Kokkos::atomic_add (&rowVals(k), newVals(j));
1927  }
1928  else {
1929  rowVals(k) += newVals(j);
1930  }
1931  hint = k+1;
1932  numValid++;
1933  }
1934  }
1935  }
1936  }
1937  else if (isGloballyIndexed ()) {
1938  // Get a view of the column indices in the row. This amortizes
1939  // the cost of getting the view over all the entries of inds.
1940  auto colInds = this->getGlobalKokkosRowView (rowInfo);
1941 
1942  const LO numElts = static_cast<LO> (inds.dimension_0 ());
1943  for (LO j = 0; j < numElts; ++j) {
1944  const size_t k =
1945  this->findGlobalIndex (rowInfo, inds(j), colInds, hint);
1946  if (k != STINV) {
1947  if (atomic) {
1948  Kokkos::atomic_add (&rowVals(k), newVals(j));
1949  }
1950  else {
1951  rowVals(k) += newVals(j);
1952  }
1953  hint = k+1;
1954  numValid++;
1955  }
1956  }
1957  }
1958  // If the graph is neither locally nor globally indexed on the
1959  // calling process, that means the calling process has no graph
1960  // entries. Thus, none of the input column indices are valid.
1961 
1962  return numValid;
1963  }
1964 
1991  template<class Scalar,
1992  class BinaryFunction,
1993  class InputMemorySpace,
1994  class ValsMemorySpace>
1995  LocalOrdinal
1997  const Kokkos::View<Scalar*, ValsMemorySpace,
1998  Kokkos::MemoryUnmanaged>& rowVals,
1999  const Kokkos::View<const GlobalOrdinal*,
2000  InputMemorySpace,
2001  Kokkos::MemoryUnmanaged>& inds,
2002  const Kokkos::View<const Scalar*,
2003  InputMemorySpace,
2004  Kokkos::MemoryUnmanaged>& newVals,
2005  BinaryFunction f,
2006  const bool atomic = useAtomicUpdatesByDefault) const
2007  {
2008  typedef LocalOrdinal LO;
2009  if (newVals.dimension_0 () != inds.dimension_0 ()) {
2010  // The sizes of the input arrays must match.
2011  return Teuchos::OrdinalTraits<LO>::invalid ();
2012  }
2013  const size_t STINV = Teuchos::OrdinalTraits<size_t>::invalid ();
2014  const LO numElts = static_cast<LO> (inds.dimension_0 ());
2015  LO numValid = 0; // number of valid input column indices
2016  size_t hint = 0; // guess at the index's relative offset in the row
2017 
2018  if (isLocallyIndexed ()) {
2019  // NOTE (mfh 04 Nov 2015) Dereferencing an RCP or reading its
2020  // pointer does NOT change its reference count. Thus, this
2021  // code is still thread safe.
2022  if (colMap_.is_null ()) {
2023  // NO input column indices are valid in this case, since if
2024  // the column Map is null on the calling process, then the
2025  // calling process owns no graph entries.
2026  return numValid;
2027  }
2028  const map_type& colMap = *colMap_;
2029  // Get a view of the column indices in the row. This amortizes
2030  // the cost of getting the view over all the entries of inds.
2031  auto colInds = this->getLocalKokkosRowView (rowInfo);
2032 
2033  const LO LINV = Teuchos::OrdinalTraits<LO>::invalid ();
2034  for (LO j = 0; j < numElts; ++j) {
2035  const LO lclColInd = colMap.getLocalElement (inds(j));
2036  if (lclColInd != LINV) {
2037  const size_t k =
2038  this->findLocalIndex (rowInfo, lclColInd, colInds, hint);
2039  if (k != STINV) {
2040  if (atomic) {
2041  // NOTE (mfh 30 Nov 2015) The commented-out code is
2042  // wrong because another thread may have changed
2043  // rowVals[k] between those two lines of code.
2044  //
2045  //const Scalar newVal = f (rowVals(k), newVals(j));
2046  //Kokkos::atomic_assign (&rowVals(k), newVal);
2047 
2048  volatile Scalar* const dest = &rowVals(k);
2049  (void) atomic_binary_function_update (dest, newVals(j), f);
2050  }
2051  else {
2052  rowVals(k) = f (rowVals(k), newVals(j)); // use binary function f
2053  }
2054  hint = k+1;
2055  numValid++;
2056  }
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  for (LO j = 0; j < numElts; ++j) {
2066  const size_t k =
2067  this->findGlobalIndex (rowInfo, inds(j), colInds, hint);
2068  if (k != STINV) {
2069  if (atomic) {
2070  // NOTE (mfh 30 Nov 2015) The commented-out code is
2071  // wrong because another thread may have changed
2072  // rowVals(k) between those two lines of code.
2073  //
2074  //const Scalar newVal = f (rowVals(k), newVals(j));
2075  //Kokkos::atomic_assign (&rowVals(k), newVal);
2076 
2077  volatile Scalar* const dest = &rowVals(k);
2078  (void) atomic_binary_function_update (dest, newVals(j), f);
2079  }
2080  else {
2081  rowVals(k) = f (rowVals(k), newVals(j)); // use binary function f
2082  }
2083  hint = k+1;
2084  numValid++;
2085  }
2086  }
2087  }
2088  // If the graph is neither locally nor globally indexed on the
2089  // calling process, that means the calling process has no graph
2090  // entries. Thus, none of the input column indices are valid.
2091 
2092  return numValid;
2093  }
2094 
2096 
2098 
2100  bool isMerged () const;
2101 
2107  void setLocallyModified ();
2108 
2110  void sortAllIndices ();
2111 
2113  void sortRowIndices (const RowInfo rowinfo);
2114 
2129  template <class Scalar>
2130  void sortRowIndicesAndValues (const RowInfo rowinfo,
2131  const Teuchos::ArrayView<Scalar>& values);
2132 
2141  void mergeAllIndices ();
2142 
2147  void mergeRowIndices (RowInfo rowinfo);
2148 
2159  template<class Scalar>
2160  void
2161  mergeRowIndicesAndValues (RowInfo rowinfo,
2162  const Teuchos::ArrayView<Scalar>& rowValues);
2164 
2174  void
2175  setDomainRangeMaps (const Teuchos::RCP<const map_type>& domainMap,
2176  const Teuchos::RCP<const map_type>& rangeMap);
2177 
2178  void staticAssertions() const;
2179  void clearGlobalConstants();
2180  void computeGlobalConstants();
2181 
2184  RowInfo getRowInfo (const LocalOrdinal myRow) const;
2185 
2198  RowInfo getRowInfoFromGlobalRowIndex (const GlobalOrdinal gblRow) const;
2199 
2203  Teuchos::ArrayView<const LocalOrdinal>
2204  getLocalView (const RowInfo rowinfo) const;
2205 
2209  Teuchos::ArrayView<LocalOrdinal>
2210  getLocalViewNonConst (const RowInfo rowinfo);
2211 
2212  private:
2213 
2220  Kokkos::View<const LocalOrdinal*, execution_space, Kokkos::MemoryUnmanaged>
2221  getLocalKokkosRowView (const RowInfo& rowinfo) const;
2222 
2229  Kokkos::View<LocalOrdinal*, execution_space, Kokkos::MemoryUnmanaged>
2230  getLocalKokkosRowViewNonConst (const RowInfo& rowinfo);
2231 
2238  Kokkos::View<const GlobalOrdinal*, execution_space, Kokkos::MemoryUnmanaged>
2239  getGlobalKokkosRowView (const RowInfo& rowinfo) const;
2240 
2241  protected:
2242 
2246  Teuchos::ArrayView<const GlobalOrdinal>
2247  getGlobalView (const RowInfo rowinfo) const;
2248 
2252  Teuchos::ArrayView<GlobalOrdinal>
2253  getGlobalViewNonConst (const RowInfo rowinfo);
2254 
2289  size_t
2290  findLocalIndex (const RowInfo& rowinfo,
2291  const LocalOrdinal ind,
2292  const size_t hint = 0) const;
2293 
2323  size_t
2324  findLocalIndex (const RowInfo& rowinfo,
2325  const LocalOrdinal ind,
2326  const Kokkos::View<const LocalOrdinal*, device_type,
2327  Kokkos::MemoryUnmanaged>& colInds,
2328  const size_t hint) const;
2329 
2338  size_t
2339  findGlobalIndex (const RowInfo& rowinfo,
2340  const GlobalOrdinal ind,
2341  const size_t hint = 0) const;
2342 
2351  size_t
2352  findGlobalIndex (const RowInfo& rowinfo,
2353  const GlobalOrdinal ind,
2354  const Kokkos::View<const GlobalOrdinal*,
2355  device_type, Kokkos::MemoryUnmanaged>& colInds,
2356  const size_t hint = 0) const;
2357 
2358  public:
2366  local_graph_type getLocalGraph () const;
2367 
2368  protected:
2370  TPETRA_DEPRECATED local_graph_type getLocalGraph_Kokkos () const;
2371 
2372  void fillLocalGraph (const Teuchos::RCP<Teuchos::ParameterList>& params);
2373 
2375  bool hasRowInfo () const;
2376 
2378  void checkInternalState () const;
2379 
2381  Teuchos::RCP<const map_type> rowMap_;
2383  Teuchos::RCP<const map_type> colMap_;
2385  Teuchos::RCP<const map_type> rangeMap_;
2387  Teuchos::RCP<const map_type> domainMap_;
2388 
2395  Teuchos::RCP<const import_type> importer_;
2396 
2402  Teuchos::RCP<const export_type> exporter_;
2403 
2405  local_graph_type lclGraph_;
2406 
2407  // Local and Global Counts
2408  // nodeNumEntries_ and nodeNumAllocated_ are required to be always consistent
2409  // nodeMaxNumEntries_, nodeNumDiags_ and the global quantities are computed during fillComplete() and only valid when isFillComplete()
2410  global_size_t globalNumEntries_, globalNumDiags_, globalMaxNumRowEntries_;
2411  size_t nodeNumEntries_, nodeNumDiags_, nodeMaxNumRowEntries_, nodeNumAllocated_;
2412 
2415 
2433  Kokkos::DualView<const size_t*, Kokkos::LayoutLeft, execution_space> k_numAllocPerRow_;
2434 
2445 
2447 
2448 
2456  typename local_graph_type::entries_type::non_const_type k_lclInds1D_;
2457 
2459  typedef Kokkos::View<GlobalOrdinal*, execution_space> t_GlobalOrdinal_1D;
2460 
2468  t_GlobalOrdinal_1D k_gblInds1D_;
2469 
2497  typename local_graph_type::row_map_type::const_type k_rowPtrs_;
2498 
2500 
2512 
2524  Teuchos::ArrayRCP<Teuchos::Array<LocalOrdinal> > lclInds2D_;
2525 
2537  Teuchos::ArrayRCP<Teuchos::Array<GlobalOrdinal> > gblInds2D_;
2538 
2539  typedef Kokkos::DualView<size_t*, Kokkos::LayoutLeft, execution_space> t_numRowEntries_;
2540 
2547  t_numRowEntries_ k_numRowEntries_;
2548 
2550 
2561 
2562  bool indicesAreAllocated_;
2563  bool indicesAreLocal_;
2564  bool indicesAreGlobal_;
2565  bool fillComplete_;
2566 
2580 
2582  std::map<GlobalOrdinal, std::vector<GlobalOrdinal> > nonlocals_;
2583 
2599 
2600  }; // class CrsGraph
2601 
2608  template <class LocalOrdinal, class GlobalOrdinal, class Node, const bool classic = Node::classic>
2609  Teuchos::RCP<CrsGraph<LocalOrdinal, GlobalOrdinal, Node, classic> >
2610  createCrsGraph (const Teuchos::RCP<const Map<LocalOrdinal, GlobalOrdinal, Node> > &map,
2611  size_t maxNumEntriesPerRow = 0,
2612  const Teuchos::RCP<Teuchos::ParameterList>& params = Teuchos::null)
2613  {
2614  using Teuchos::rcp;
2616  return rcp (new graph_type (map, maxNumEntriesPerRow, DynamicProfile, params));
2617  }
2618 
2619  namespace Details {
2620 
2621  template<class LocalOrdinal,
2622  class GlobalOrdinal,
2623  class OutputNodeType,
2624  class InputNodeType>
2625  class CrsGraphCopier<CrsGraph<LocalOrdinal, GlobalOrdinal, OutputNodeType>,
2626  CrsGraph<LocalOrdinal, GlobalOrdinal, InputNodeType> > {
2627  public:
2628  typedef CrsGraph<LocalOrdinal, GlobalOrdinal, InputNodeType> input_crs_graph_type;
2629  typedef CrsGraph<LocalOrdinal, GlobalOrdinal, OutputNodeType> output_crs_graph_type;
2630 
2631  static Teuchos::RCP<output_crs_graph_type>
2632  clone (const input_crs_graph_type& graphIn,
2633  const Teuchos::RCP<OutputNodeType> &nodeOut,
2634  const Teuchos::RCP<Teuchos::ParameterList>& params = Teuchos::null)
2635  {
2636  using Teuchos::arcp;
2637  using Teuchos::ArrayRCP;
2638  using Teuchos::ArrayView;
2639  using Teuchos::null;
2640  using Teuchos::outArg;
2641  using Teuchos::ParameterList;
2642  using Teuchos::parameterList;
2643  using Teuchos::RCP;
2644  using Teuchos::rcp;
2645  using Teuchos::REDUCE_MIN;
2646  using Teuchos::reduceAll;
2647  using Teuchos::sublist;
2648  using std::cerr;
2649  using std::endl;
2650  typedef LocalOrdinal LO;
2651  typedef GlobalOrdinal GO;
2652  typedef typename ArrayView<const GO>::size_type size_type;
2653  typedef ::Tpetra::Map<LO, GO, InputNodeType> input_map_type;
2654  typedef ::Tpetra::Map<LO, GO, OutputNodeType> output_map_type;
2655  const char prefix[] = "Tpetra::Details::CrsGraphCopier::clone: ";
2656 
2657  // Set parameters' default values.
2658  bool debug = false;
2659  bool fillCompleteClone = true;
2660  bool useLocalIndices = graphIn.hasColMap ();
2661  ProfileType pftype = StaticProfile;
2662  // If the user provided a ParameterList, get values from there.
2663  if (! params.is_null ()) {
2664  fillCompleteClone = params->get ("fillComplete clone", fillCompleteClone);
2665  useLocalIndices = params->get ("Locally indexed clone", useLocalIndices);
2666  if (params->get ("Static profile clone", true) == false) {
2667  pftype = DynamicProfile;
2668  }
2669  debug = params->get ("Debug", debug);
2670  }
2671 
2672  const Teuchos::Comm<int>& comm = * (graphIn.getRowMap ()->getComm ());
2673  const int myRank = comm.getRank ();
2674 
2675  TEUCHOS_TEST_FOR_EXCEPTION(
2676  ! graphIn.hasColMap () && useLocalIndices, std::runtime_error,
2677  prefix << "You asked clone() to use local indices (by setting the "
2678  "\"Locally indexed clone\" parameter to true), but the source graph "
2679  "does not yet have a column Map, so this is impossible.");
2680 
2681  if (debug) {
2682  std::ostringstream os;
2683  os << "Process " << myRank << ": Cloning row Map" << endl;
2684  cerr << os.str ();
2685  }
2686 
2687  RCP<const output_map_type> clonedRowMap =
2688  graphIn.getRowMap ()->template clone<OutputNodeType> (nodeOut);
2689 
2690  // Invoke the output graph's constructor, using the input graph's
2691  // upper bounds on the number of entries in each local row.
2692  RCP<output_crs_graph_type> clonedGraph; // returned by this function
2693  {
2694  ArrayRCP<const size_t> numEntriesPerRow;
2695  size_t numEntriesForAll = 0;
2696  bool boundSameForAllLocalRows = true;
2697 
2698  if (debug) {
2699  std::ostringstream os;
2700  os << "Process " << myRank << ": Getting per-row bounds" << endl;
2701  cerr << os.str ();
2702  }
2703  graphIn.getNumEntriesPerLocalRowUpperBound (numEntriesPerRow,
2704  numEntriesForAll,
2705  boundSameForAllLocalRows);
2706  if (debug) {
2707  std::ostringstream os;
2708  os << "Process " << myRank << ": numEntriesForAll = "
2709  << numEntriesForAll << endl;
2710  cerr << os.str ();
2711  }
2712 
2713  if (debug) {
2714  std::ostringstream os;
2715  os << "Process " << myRank << ": graphIn.getNodeMaxNumRowEntries() = "
2716  << graphIn.getNodeMaxNumRowEntries () << endl;
2717  cerr << os.str ();
2718  }
2719 
2720  RCP<ParameterList> graphparams;
2721  if (params.is_null ()) {
2722  graphparams = parameterList ("CrsGraph");
2723  } else {
2724  graphparams = sublist (params, "CrsGraph");
2725  }
2726  if (useLocalIndices) {
2727  RCP<const output_map_type> clonedColMap =
2728  graphIn.getColMap ()->template clone<OutputNodeType> (nodeOut);
2729  if (boundSameForAllLocalRows) {
2730  clonedGraph = rcp (new output_crs_graph_type (clonedRowMap, clonedColMap,
2731  numEntriesForAll, pftype,
2732  graphparams));
2733  } else {
2734  clonedGraph = rcp (new output_crs_graph_type (clonedRowMap, clonedColMap,
2735  numEntriesPerRow, pftype,
2736  graphparams));
2737  }
2738  } else {
2739  if (boundSameForAllLocalRows) {
2740  clonedGraph = rcp (new output_crs_graph_type (clonedRowMap,
2741  numEntriesForAll, pftype,
2742  graphparams));
2743  } else {
2744  clonedGraph = rcp (new output_crs_graph_type (clonedRowMap,
2745  numEntriesPerRow,
2746  pftype, graphparams));
2747  }
2748  }
2749 
2750  if (debug) {
2751  std::ostringstream os;
2752  os << "Process " << myRank << ": Invoked output graph's constructor" << endl;
2753  cerr << os.str ();
2754  }
2755 
2756  // done with these
2757  numEntriesPerRow = null;
2758  numEntriesForAll = 0;
2759  }
2760 
2761  const input_map_type& inputRowMap = * (graphIn.getRowMap ());
2762  const size_type numRows =
2763  static_cast<size_type> (inputRowMap.getNodeNumElements ());
2764 
2765  bool failed = false;
2766 
2767  if (useLocalIndices) {
2768  const LO localMinLID = inputRowMap.getMinLocalIndex ();
2769  const LO localMaxLID = inputRowMap.getMaxLocalIndex ();
2770 
2771  if (graphIn.isLocallyIndexed ()) {
2772  if (numRows != 0) {
2773  try {
2774  ArrayView<const LO> linds;
2775  for (LO lrow = localMinLID; lrow <= localMaxLID; ++lrow) {
2776  graphIn.getLocalRowView (lrow, linds);
2777  if (linds.size () != 0) {
2778  clonedGraph->insertLocalIndices (lrow, linds);
2779  }
2780  }
2781  }
2782  catch (std::exception& e) {
2783  std::ostringstream os;
2784  os << "Process " << myRank << ": copying (reading local by view, "
2785  "writing local) indices into the output graph threw an "
2786  "exception: " << e.what () << endl;
2787  cerr << os.str ();
2788  failed = true;
2789  }
2790  }
2791  }
2792  else { // graphIn.isGloballyIndexed()
2793  TEUCHOS_TEST_FOR_EXCEPTION(
2794  ! graphIn.hasColMap () && useLocalIndices, std::invalid_argument,
2795  prefix << "You asked clone() to use local indices (by setting the "
2796  "\"Locally indexed clone\" parameter to true), but the source graph "
2797  "does not yet have a column Map, so this is impossible.");
2798 
2799  // The input graph has a column Map, but is globally indexed.
2800  // That's a bit weird, but we'll run with it. In this case,
2801  // getLocalRowView won't work, but getLocalRowCopy should
2802  // still work; it will just have to convert from global to
2803  // local indices internally.
2804 
2805  try {
2806  // Make space for getLocalRowCopy to put column indices.
2807  //
2808  // This is only a hint; we may have to resize in the loop
2809  // below. getNodeMaxNumRowEntries() may return nonsense if
2810  // fill is active. The key bool in CrsGraph is
2811  // haveLocalConstants_.
2812  size_t myMaxNumRowEntries =
2813  graphIn.isFillActive () ? static_cast<size_t> (0) :
2814  graphIn.getNodeMaxNumRowEntries ();
2815 
2816  Array<LO> linds (myMaxNumRowEntries);
2817 
2818  // Copy each row into the new graph, using local indices.
2819  for (LO lrow = localMinLID; lrow <= localMaxLID; ++lrow) {
2820  size_t theNumEntries = graphIn.getNumEntriesInLocalRow (lrow);
2821  if (theNumEntries > myMaxNumRowEntries) {
2822  myMaxNumRowEntries = theNumEntries;
2823  linds.resize (myMaxNumRowEntries);
2824  }
2825  graphIn.getLocalRowCopy (lrow, linds (), theNumEntries);
2826  if (theNumEntries != 0) {
2827  clonedGraph->insertLocalIndices (lrow, linds (0, theNumEntries));
2828  }
2829  }
2830  }
2831  catch (std::exception& e) {
2832  std::ostringstream os;
2833  os << "Process " << myRank << ": copying (reading local by copy, "
2834  "writing local) indices into the output graph threw an exception: "
2835  << e.what () << endl;
2836  cerr << os.str ();
2837  failed = true;
2838  }
2839  }
2840  }
2841  else { /* useGlobalIndices */
2842  if (numRows != 0) {
2843  const GlobalOrdinal localMinGID = inputRowMap.getMinGlobalIndex ();
2844  const GlobalOrdinal localMaxGID = inputRowMap.getMaxGlobalIndex ();
2845  const bool inputRowMapIsContiguous = inputRowMap.isContiguous ();
2846 
2847  if (graphIn.isGloballyIndexed ()) {
2848  ArrayView<const GlobalOrdinal> ginds;
2849 
2850  if (inputRowMapIsContiguous) {
2851  try {
2852  for (GO grow = localMinGID; grow <= localMaxGID; ++grow) {
2853  graphIn.getGlobalRowView (grow, ginds);
2854  if (ginds.size () != 0) {
2855  clonedGraph->insertGlobalIndices (grow, ginds);
2856  }
2857  }
2858  }
2859  catch (std::exception& e) {
2860  std::ostringstream os;
2861  os << "Process " << myRank << ": copying (reading global by view, "
2862  "writing global) indices into the output graph threw an "
2863  "exception: " << e.what () << endl;
2864  cerr << os.str ();
2865  failed = true;
2866  }
2867  }
2868  else { // input row Map is not contiguous
2869  try {
2870  ArrayView<const GO> inputRowMapGIDs = inputRowMap.getNodeElementList ();
2871  for (size_type k = 0; k < numRows; ++k) {
2872  const GO grow = inputRowMapGIDs[k];
2873  graphIn.getGlobalRowView (grow, ginds);
2874  if (ginds.size () != 0) {
2875  clonedGraph->insertGlobalIndices (grow, ginds);
2876  }
2877  }
2878  }
2879  catch (std::exception& e) {
2880  std::ostringstream os;
2881  os << "Process " << myRank << ": copying (reading global by view, "
2882  "writing global) indices into the output graph threw an "
2883  "exception: " << e.what () << endl;
2884  cerr << os.str ();
2885  failed = true;
2886  }
2887  }
2888  }
2889  else { // graphIn.isLocallyIndexed()
2890  // Make space for getGlobalRowCopy to put column indices.
2891  //
2892  // This is only a hint; we may have to resize in the loop
2893  // below. getNodeMaxNumRowEntries() may return nonsense if
2894  // fill is active. The key bool in CrsGraph is
2895  // haveLocalConstants_.
2896  size_t myMaxNumRowEntries =
2897  graphIn.isFillActive () ? static_cast<size_t> (0) :
2898  graphIn.getNodeMaxNumRowEntries ();
2899 
2900  Array<GO> ginds (myMaxNumRowEntries);
2901 
2902  if (inputRowMapIsContiguous) {
2903  try {
2904  for (GO grow = localMinGID; grow <= localMaxGID; ++grow) {
2905  size_t theNumEntries = graphIn.getNumEntriesInGlobalRow (grow);
2906  if (theNumEntries > myMaxNumRowEntries) {
2907  myMaxNumRowEntries = theNumEntries;
2908  ginds.resize (myMaxNumRowEntries);
2909  }
2910  graphIn.getGlobalRowCopy (grow, ginds (), theNumEntries);
2911  if (theNumEntries != 0) {
2912  clonedGraph->insertGlobalIndices (grow, ginds (0, theNumEntries));
2913  }
2914  }
2915  }
2916  catch (std::exception& e) {
2917  std::ostringstream os;
2918  os << "Process " << myRank << ": copying (reading global by copy, "
2919  "writing global) indices into the output graph threw an "
2920  "exception: " << e.what () << endl;
2921  cerr << os.str ();
2922  failed = true;
2923  }
2924  }
2925  else { // input row Map is not contiguous
2926  try {
2927  ArrayView<const GO> inputRowMapGIDs = inputRowMap.getNodeElementList ();
2928  for (size_type k = 0; k < numRows; ++k) {
2929  const GO grow = inputRowMapGIDs[k];
2930 
2931  size_t theNumEntries = graphIn.getNumEntriesInGlobalRow (grow);
2932  if (theNumEntries > myMaxNumRowEntries) {
2933  myMaxNumRowEntries = theNumEntries;
2934  ginds.resize (myMaxNumRowEntries);
2935  }
2936  graphIn.getGlobalRowCopy (grow, ginds (), theNumEntries);
2937  if (theNumEntries != 0) {
2938  clonedGraph->insertGlobalIndices (grow, ginds (0, theNumEntries));
2939  }
2940  }
2941  }
2942  catch (std::exception& e) {
2943  std::ostringstream os;
2944  os << "Process " << myRank << ": copying (reading global by copy, "
2945  "writing global) indices into the output graph threw an "
2946  "exception: " << e.what () << endl;
2947  cerr << os.str ();
2948  failed = true;
2949  }
2950  }
2951  }
2952  } // numRows != 0
2953  }
2954 
2955  if (debug) {
2956  std::ostringstream os;
2957  os << "Process " << myRank << ": copied entries" << endl;
2958  cerr << os.str ();
2959  }
2960 
2961  if (fillCompleteClone) {
2962  RCP<ParameterList> fillparams = params.is_null () ?
2963  parameterList ("fillComplete") :
2964  sublist (params, "fillComplete");
2965  try {
2966  RCP<const output_map_type> clonedRangeMap;
2967  RCP<const output_map_type> clonedDomainMap;
2968  if (! graphIn.getRangeMap ().is_null () &&
2969  graphIn.getRangeMap () != graphIn.getRowMap ()) {
2970  clonedRangeMap =
2971  graphIn.getRangeMap ()->template clone<OutputNodeType> (nodeOut);
2972  }
2973  else {
2974  clonedRangeMap = clonedRowMap;
2975  }
2976  if (! graphIn.getDomainMap ().is_null ()
2977  && graphIn.getDomainMap () != graphIn.getRowMap ()) {
2978  clonedDomainMap =
2979  graphIn.getDomainMap ()->template clone<OutputNodeType> (nodeOut);
2980  }
2981  else {
2982  clonedDomainMap = clonedRowMap;
2983  }
2984 
2985  if (debug) {
2986  std::ostringstream os;
2987  os << "Process " << myRank << ": About to call fillComplete on "
2988  "cloned graph" << endl;
2989  cerr << os.str ();
2990  }
2991  clonedGraph->fillComplete (clonedDomainMap, clonedRangeMap, fillparams);
2992  }
2993  catch (std::exception &e) {
2994  failed = true;
2995  std::ostringstream os;
2996  os << prefix << "Process " << myRank << ": Caught the following "
2997  "exception while calling fillComplete() on clone of type"
2998  << endl << Teuchos::typeName (*clonedGraph) << endl;
2999  cerr << os.str ();
3000  }
3001  }
3002 
3003  int lclSuccess = failed ? 0 : 1;
3004  int gblSuccess = 1;
3005  reduceAll<int, int> (comm, REDUCE_MIN, lclSuccess, outArg (gblSuccess));
3006  TEUCHOS_TEST_FOR_EXCEPTION(
3007  gblSuccess != 1, std::logic_error, prefix <<
3008  "Clone failed on at least one process.");
3009 
3010  if (debug) {
3011  std::ostringstream os;
3012  os << "Process " << myRank << ": Done with CrsGraph::clone" << endl;
3013  cerr << os.str ();
3014  }
3015  return clonedGraph;
3016  }
3017  };
3018 
3019  } // namespace Details
3020 } // namespace Tpetra
3021 
3022 #endif // TPETRA_CRSGRAPH_DECL_HPP
Communication plan for data redistribution from a uniquely-owned to a (possibly) multiply-owned distr...
Namespace Tpetra contains the class and methods constituting the Tpetra library.
std::enable_if< Kokkos::is_view< OutputScalarViewType >::value &&Kokkos::is_view< LocalIndicesViewType >::value &&Kokkos::is_view< InputScalarViewType >::value &&std::is_same< typename OutputScalarViewType::non_const_value_type, typename InputScalarViewType::non_const_value_type >::value &&std::is_same< typename LocalIndicesViewType::non_const_value_type, local_ordinal_type >::value, LocalOrdinal >::type 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.
bool haveGlobalConstants_
Whether all processes have computed global constants.
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.
Sparse matrix that presents a row-oriented interface that lets users read or modify entries...
An abstract interface for graphs accessed by rows.
bool isNodeGlobalElement(GlobalOrdinal globalIndex) const
Whether the given global index is owned by this Map on the calling process.
bool indicesAreSorted_
Whether the graph&#39;s indices are sorted in each row, on this process.
GlobalOrdinal global_ordinal_type
This class&#39; second template parameter; the type of global indices.
bool noRedundancies_
Whether the graph&#39;s indices are non-redundant (merged) in each row, on this process.
KokkosClassic::DefaultNode::DefaultNodeType node_type
Default value of Node template parameter.
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.
t_numRowEntries_ k_numRowEntries_
The number of local entries in each locally owned row.
local_graph_type::entries_type::non_const_type k_lclInds1D_
Local column indices for all rows.
Teuchos::ArrayRCP< Teuchos::Array< GlobalOrdinal > > gblInds2D_
Global column indices for all rows.
LocalOrdinal local_ordinal_type
This class&#39; first template parameter; the type of local indices.
Teuchos::RCP< CrsGraph< LocalOrdinal, GlobalOrdinal, Node, classic > > createCrsGraph(const Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > &map, size_t maxNumEntriesPerRow=0, const Teuchos::RCP< Teuchos::ParameterList > &params=Teuchos::null)
Nonmember function to create an empty CrsGraph given a row Map and the max number of entries allowed ...
void removeEmptyProcessesInPlace(Teuchos::RCP< DistObjectType > &input, const Teuchos::RCP< const Map< typename DistObjectType::local_ordinal_type, typename DistObjectType::global_ordinal_type, typename DistObjectType::node_type > > &newMap)
Remove processes which contain no elements in this object&#39;s Map.
bool upperTriangular_
Whether the graph is locally upper triangular.
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.
int local_ordinal_type
Default value of LocalOrdinal template parameter.
bool isNodeLocalElement(LocalOrdinal localIndex) const
Whether the given local index is valid for this Map on the calling process.
Teuchos::RCP< const map_type > colMap_
The Map describing the distribution of columns of the graph.
Implementation details of Tpetra.
size_t numAllocForAllRows_
The maximum number of entries to allow in each locally owned row.
size_t global_size_t
Global size_t object.
Kokkos::StaticCrsGraph< LocalOrdinal, Kokkos::LayoutLeft, execution_space > local_graph_type
The type of the part of the sparse graph on each MPI process.
bool haveLocalConstants_
Whether this process has computed local constants.
t_GlobalOrdinal_1D k_gblInds1D_
Global column indices for all rows.
local_graph_type lclGraph_
Local graph; only initialized after first fillComplete() call.
Communication plan for data redistribution from a (possibly) multiply-owned to a uniquely-owned distr...
Sets up and executes a communication plan for a Tpetra DistObject.
GlobalOrdinal getGlobalElement(LocalOrdinal localIndex) const
The global index corresponding to the given local index.
CombineMode
Rule for combining data in an Import or Export.
Kokkos::DualView< const size_t *, Kokkos::LayoutLeft, execution_space > k_numAllocPerRow_
The maximum number of entries to allow in each locally owned row, per row.
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.
Node node_type
This class&#39; Kokkos Node type.
Teuchos::RCP< const map_type > rowMap_
The Map describing the distribution of rows of the graph.
Teuchos::ArrayRCP< Teuchos::Array< LocalOrdinal > > lclInds2D_
Local column indices for all rows.
LocalOrdinal getLocalElement(GlobalOrdinal globalIndex) const
The local index corresponding to the given global index.
Tpetra::Map< LocalOrdinal, GlobalOrdinal, Node > map_type
The Map specialization used by this class.
A distributed graph accessed by rows (adjacency lists) and stored sparsely.
Describes a parallel distribution of objects over processes.
Details::EStorageStatus storageStatus_
Status of the graph&#39;s storage, when not in a fill-complete state.
std::enable_if< Kokkos::is_view< OutputScalarViewType >::value &&Kokkos::is_view< LocalIndicesViewType >::value &&Kokkos::is_view< InputScalarViewType >::value &&std::is_same< typename OutputScalarViewType::non_const_value_type, typename InputScalarViewType::non_const_value_type >::value &&std::is_same< typename LocalIndicesViewType::non_const_value_type, local_ordinal_type >::value, LocalOrdinal >::type 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.
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.
std::enable_if< Kokkos::is_view< OutputScalarViewType >::value &&Kokkos::is_view< LocalIndicesViewType >::value &&Kokkos::is_view< InputScalarViewType >::value &&std::is_same< typename OutputScalarViewType::non_const_value_type, typename InputScalarViewType::non_const_value_type >::value &&std::is_same< typename LocalIndicesViewType::non_const_value_type, local_ordinal_type >::value, LocalOrdinal >::type 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.
local_graph_type::row_map_type::const_type k_rowPtrs_
Row offsets for "1-D" storage.
std::map< GlobalOrdinal, std::vector< GlobalOrdinal > > nonlocals_
Nonlocal data given to insertGlobalValues or sumIntoGlobalValues.
local_graph_type::row_map_type t_RowPtrs TPETRA_DEPRECATED
DEPRECATED; use local_graph_type::row_map_type instead.
local_graph_type::row_map_type::non_const_type t_RowPtrsNC TPETRA_DEPRECATED
DEPRECATED; use local_graph_type::row_map_type::non_const_type instead.
Kokkos::View< GlobalOrdinal *, execution_space > t_GlobalOrdinal_1D
Type of the k_gblInds1D_ array of global column indices.
Base class for distributed Tpetra objects that support data redistribution.
Tpetra::Export< LocalOrdinal, GlobalOrdinal, Node > export_type
The Export specialization used by this class.
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.
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.
EStorageStatus
Status of the graph&#39;s or matrix&#39;s storage, when not in a fill-complete state.
Teuchos::RCP< const export_type > exporter_
The Export from the row Map to the range Map.
bool lowerTriangular_
Whether the graph is locally lower triangular.
Tpetra::Import< LocalOrdinal, GlobalOrdinal, Node > import_type
The Import specialization used by this class.