|
Tpetra Matrix/Vector Services
Version of the Day
|
00001 // @HEADER 00002 // *********************************************************************** 00003 // 00004 // Tpetra: Templated Linear Algebra Services Package 00005 // Copyright (2008) Sandia Corporation 00006 // 00007 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, 00008 // the U.S. Government retains certain rights in this software. 00009 // 00010 // Redistribution and use in source and binary forms, with or without 00011 // modification, are permitted provided that the following conditions are 00012 // met: 00013 // 00014 // 1. Redistributions of source code must retain the above copyright 00015 // notice, this list of conditions and the following disclaimer. 00016 // 00017 // 2. Redistributions in binary form must reproduce the above copyright 00018 // notice, this list of conditions and the following disclaimer in the 00019 // documentation and/or other materials provided with the distribution. 00020 // 00021 // 3. Neither the name of the Corporation nor the names of the 00022 // contributors may be used to endorse or promote products derived from 00023 // this software without specific prior written permission. 00024 // 00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY 00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE 00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00036 // 00037 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 00038 // 00039 // ************************************************************************ 00040 // @HEADER 00041 00042 #ifndef TPETRA_CRSGRAPH_DECL_HPP 00043 #define TPETRA_CRSGRAPH_DECL_HPP 00044 00045 #include "Tpetra_ConfigDefs.hpp" 00046 00047 #include <Teuchos_CompileTimeAssert.hpp> 00048 #include <Teuchos_Describable.hpp> 00049 #include <Teuchos_ParameterListAcceptorDefaultBase.hpp> 00050 00051 #include <Kokkos_DefaultNode.hpp> 00052 #include <Kokkos_DefaultKernels.hpp> 00053 00054 #include <Tpetra_RowGraph.hpp> 00055 #include <Tpetra_DistObject.hpp> 00056 #include <Tpetra_Exceptions.hpp> 00057 00058 00059 namespace Tpetra { 00060 00061 #ifndef DOXYGEN_SHOULD_SKIP_THIS 00062 // 00063 // Dear users: These are just forward declarations. Please skip 00064 // over them and go down to the CrsMatrix class declaration. Thank 00065 // you. 00066 // 00067 template <class LO, class GO, class N> 00068 class CrsGraph; 00069 00070 template <class S, class LO, class GO, class N> 00071 class CrsMatrix; 00072 00073 namespace Experimental { 00074 template<class S, class LO, class GO, class N> 00075 class BlockCrsMatrix; 00076 } 00077 00078 namespace Details { 00079 // Forward declaration of an implementation detail of CrsGraph::clone. 00080 template<class OutputCrsGraphType, class InputCrsGraphType> 00081 class CrsGraphCopier { 00082 public: 00083 static Teuchos::RCP<OutputCrsGraphType> 00084 clone (const InputCrsGraphType& graphIn, 00085 const Teuchos::RCP<typename OutputCrsGraphType::node_type> nodeOut, 00086 const Teuchos::RCP<Teuchos::ParameterList>& params = Teuchos::null); 00087 }; 00088 } // namespace Details 00089 00090 #endif // DOXYGEN_SHOULD_SKIP_THIS 00091 00100 struct RowInfo { 00101 size_t localRow; 00102 size_t allocSize; 00103 size_t numEntries; 00104 size_t offset1D; 00105 }; 00106 00107 enum ELocalGlobal { 00108 LocalIndices, 00109 GlobalIndices 00110 }; 00111 00170 template <class LocalOrdinal = RowGraph<>::local_ordinal_type, 00171 class GlobalOrdinal = typename RowGraph<LocalOrdinal>::global_ordinal_type, 00172 class Node = typename RowGraph<LocalOrdinal, GlobalOrdinal>::node_type> 00173 class CrsGraph : 00174 public RowGraph<LocalOrdinal,GlobalOrdinal,Node>, 00175 public DistObject<GlobalOrdinal,LocalOrdinal,GlobalOrdinal,Node>, 00176 public Teuchos::ParameterListAcceptorDefaultBase 00177 { 00178 template <class S, class LO, class GO, class N> 00179 friend class CrsMatrix; 00180 template <class S, class LO, class GO, class N> 00181 friend class Experimental::BlockCrsMatrix; 00182 template <class LO2, class GO2, class N2> 00183 friend class CrsGraph; 00184 template<class OutputCrsGraphType, class InputCrsGraphType> 00185 friend class Details::CrsGraphCopier; 00186 00187 public: 00189 typedef LocalOrdinal local_ordinal_type; 00191 typedef GlobalOrdinal global_ordinal_type; 00193 typedef Node node_type; 00194 00196 typedef Tpetra::Map<LocalOrdinal, GlobalOrdinal, node_type> map_type; 00198 typedef Tpetra::Import<LocalOrdinal, GlobalOrdinal, node_type> import_type; 00200 typedef Tpetra::Export<LocalOrdinal, GlobalOrdinal, node_type> export_type; 00201 00203 00204 00222 CrsGraph (const Teuchos::RCP<const map_type>& rowMap, 00223 size_t maxNumEntriesPerRow, 00224 ProfileType pftype = DynamicProfile, 00225 const Teuchos::RCP<Teuchos::ParameterList>& params = null); 00226 00244 CrsGraph (const Teuchos::RCP<const map_type>& rowMap, 00245 const Teuchos::ArrayRCP<const size_t>& NumEntriesPerRowToAlloc, 00246 ProfileType pftype = DynamicProfile, 00247 const Teuchos::RCP<Teuchos::ParameterList>& params = null); 00248 00268 CrsGraph (const Teuchos::RCP<const map_type>& rowMap, 00269 const Teuchos::RCP<const map_type>& colMap, 00270 size_t maxNumEntriesPerRow, 00271 ProfileType pftype = DynamicProfile, 00272 const Teuchos::RCP<Teuchos::ParameterList>& params = null); 00273 00293 CrsGraph (const Teuchos::RCP<const map_type>& rowMap, 00294 const Teuchos::RCP<const map_type>& colMap, 00295 const Teuchos::ArrayRCP<const size_t> &NumEntriesPerRowToAlloc, 00296 ProfileType pftype = DynamicProfile, 00297 const Teuchos::RCP<Teuchos::ParameterList>& params = null); 00298 00318 CrsGraph (const Teuchos::RCP<const map_type>& rowMap, 00319 const Teuchos::RCP<const map_type>& colMap, 00320 const Teuchos::ArrayRCP<size_t> & rowPointers, 00321 const Teuchos::ArrayRCP<LocalOrdinal> & columnIndices, 00322 const Teuchos::RCP<Teuchos::ParameterList>& params = null); 00323 00324 00352 template<class Node2> 00353 Teuchos::RCP<CrsGraph<LocalOrdinal, GlobalOrdinal, Node2> > 00354 clone (const Teuchos::RCP<Node2> &node2, 00355 const Teuchos::RCP<Teuchos::ParameterList> ¶ms = null) const 00356 { 00357 typedef CrsGraph<LocalOrdinal, GlobalOrdinal, Node2> output_crs_graph_type; 00358 typedef CrsGraph<LocalOrdinal, GlobalOrdinal, Node> input_crs_graph_type; 00359 typedef Details::CrsGraphCopier<output_crs_graph_type, input_crs_graph_type> copier_type; 00360 return copier_type::clone (*this, node2, params); 00361 } 00362 00364 virtual ~CrsGraph(); 00365 00367 00368 00369 00371 void setParameterList (const Teuchos::RCP<Teuchos::ParameterList>& params); 00372 00374 Teuchos::RCP<const Teuchos::ParameterList> getValidParameters () const; 00375 00377 00378 00379 00401 void 00402 insertGlobalIndices (GlobalOrdinal globalRow, 00403 const Teuchos::ArrayView<const GlobalOrdinal>& indices); 00404 00406 00420 void 00421 insertLocalIndices (const LocalOrdinal localRow, 00422 const Teuchos::ArrayView<const LocalOrdinal> &indices); 00423 00425 00434 void removeLocalIndices (LocalOrdinal localRow); 00435 00437 00438 00444 00450 void globalAssemble (); 00451 00460 void resumeFill (const Teuchos::RCP<Teuchos::ParameterList> ¶ms = null); 00461 00479 void 00480 fillComplete (const Teuchos::RCP<const map_type> &domainMap, 00481 const Teuchos::RCP<const map_type> &rangeMap, 00482 const Teuchos::RCP<Teuchos::ParameterList> ¶ms = null); 00483 00490 void fillComplete (const Teuchos::RCP<Teuchos::ParameterList> ¶ms = null); 00491 00502 void 00503 expertStaticFillComplete (const Teuchos::RCP<const map_type> & domainMap, 00504 const Teuchos::RCP<const map_type> & rangeMap, 00505 const Teuchos::RCP<const import_type>& importer = Teuchos::null, 00506 const Teuchos::RCP<const export_type>& exporter = Teuchos::null, 00507 const Teuchos::RCP<Teuchos::ParameterList>& params = Teuchos::null); 00509 00510 00511 00513 Teuchos::RCP<const Comm<int> > getComm() const; 00514 00516 Teuchos::RCP<Node> getNode() const; 00517 00519 Teuchos::RCP<const map_type> getRowMap() const; 00520 00522 Teuchos::RCP<const map_type> getColMap() const; 00523 00525 Teuchos::RCP<const map_type> getDomainMap() const; 00526 00528 Teuchos::RCP<const map_type> getRangeMap() const; 00529 00531 Teuchos::RCP<const import_type> getImporter () const; 00532 00534 Teuchos::RCP<const export_type> getExporter () const; 00535 00537 00539 global_size_t getGlobalNumRows() const; 00540 00542 00545 global_size_t getGlobalNumCols() const; 00546 00548 size_t getNodeNumRows() const; 00549 00551 00553 size_t getNodeNumCols() const; 00554 00556 GlobalOrdinal getIndexBase() const; 00557 00559 00561 global_size_t getGlobalNumEntries() const; 00562 00564 size_t getNodeNumEntries() const; 00565 00567 00568 size_t getNumEntriesInGlobalRow(GlobalOrdinal globalRow) const; 00569 00571 00572 size_t getNumEntriesInLocalRow(LocalOrdinal localRow) const; 00573 00575 00582 size_t getNodeAllocationSize() const; 00583 00585 00586 size_t getNumAllocatedEntriesInGlobalRow(GlobalOrdinal globalRow) const; 00587 00589 00590 size_t getNumAllocatedEntriesInLocalRow(LocalOrdinal localRow) const; 00591 00593 00595 global_size_t getGlobalNumDiags() const; 00596 00598 00600 size_t getNodeNumDiags() const; 00601 00614 size_t getGlobalMaxNumRowEntries() const; 00615 00617 00619 size_t getNodeMaxNumRowEntries() const; 00620 00635 bool hasColMap() const; 00636 00644 bool isLowerTriangular() const; 00645 00653 bool isUpperTriangular() const; 00654 00670 bool isLocallyIndexed() const; 00671 00687 bool isGloballyIndexed() const; 00688 00697 bool isFillComplete() const; 00698 00713 bool isFillActive() const; 00714 00722 bool isSorted () const; 00723 00725 00731 bool isStorageOptimized() const; 00732 00734 ProfileType getProfileType() const; 00735 00783 void 00784 getGlobalRowCopy (GlobalOrdinal GlobalRow, 00785 const Teuchos::ArrayView<GlobalOrdinal>& Indices, 00786 size_t& NumIndices) const; 00787 00834 void 00835 getLocalRowCopy (LocalOrdinal LocalRow, 00836 const Teuchos::ArrayView<LocalOrdinal>& indices, 00837 size_t& NumIndices) const; 00838 00858 void 00859 getGlobalRowView (GlobalOrdinal GlobalRow, 00860 Teuchos::ArrayView<const GlobalOrdinal>& Indices) const; 00861 00881 void 00882 getLocalRowView (LocalOrdinal LocalRow, 00883 Teuchos::ArrayView<const LocalOrdinal>& indices) const; 00884 00886 00887 00888 00890 std::string description() const; 00891 00893 void 00894 describe (Teuchos::FancyOStream& out, 00895 const Teuchos::EVerbosityLevel verbLevel = 00896 Teuchos::Describable::verbLevel_default) const; 00898 00899 00900 00901 virtual bool 00902 checkSizes (const SrcDistObject& source); 00903 00904 virtual void 00905 copyAndPermute (const SrcDistObject& source, 00906 size_t numSameIDs, 00907 const Teuchos::ArrayView<const LocalOrdinal> &permuteToLIDs, 00908 const Teuchos::ArrayView<const LocalOrdinal> &permuteFromLIDs); 00909 00910 virtual void 00911 packAndPrepare (const SrcDistObject& source, 00912 const Teuchos::ArrayView<const LocalOrdinal> &exportLIDs, 00913 Teuchos::Array<GlobalOrdinal> &exports, 00914 const Teuchos::ArrayView<size_t> & numPacketsPerLID, 00915 size_t& constantNumPackets, 00916 Distributor &distor); 00917 00918 virtual void 00919 pack (const Teuchos::ArrayView<const LocalOrdinal>& exportLIDs, 00920 Teuchos::Array<GlobalOrdinal>& exports, 00921 const Teuchos::ArrayView<size_t>& numPacketsPerLID, 00922 size_t& constantNumPackets, 00923 Distributor& distor) const; 00924 00925 virtual void 00926 unpackAndCombine (const Teuchos::ArrayView<const LocalOrdinal> &importLIDs, 00927 const Teuchos::ArrayView<const GlobalOrdinal> &imports, 00928 const Teuchos::ArrayView<size_t> &numPacketsPerLID, 00929 size_t constantNumPackets, 00930 Distributor &distor, 00931 CombineMode CM); 00933 00934 00935 00958 void 00959 getNumEntriesPerLocalRowUpperBound (Teuchos::ArrayRCP<const size_t>& boundPerLocalRow, 00960 size_t& boundForAllLocalRows, 00961 bool& boundSameForAllLocalRows) const; 00962 00971 void 00972 setAllIndices (const Teuchos::ArrayRCP<size_t> & rowPointers, 00973 const Teuchos::ArrayRCP<LocalOrdinal> & columnIndices); 00974 00976 00979 Teuchos::ArrayRCP<const size_t> getNodeRowPtrs() const; 00980 00982 00984 Teuchos::ArrayRCP<const LocalOrdinal> getNodePackedIndices() const; 00985 00996 void replaceColMap (const Teuchos::RCP<const map_type>& newColMap); 00997 01017 void 01018 reindexColumns (const Teuchos::RCP<const map_type>& newColMap, 01019 const Teuchos::RCP<const import_type>& newImport = Teuchos::null, 01020 const bool sortIndicesInEachRow = true); 01021 01034 void 01035 replaceDomainMapAndImporter (const Teuchos::RCP<const map_type>& newDomainMap, 01036 const Teuchos::RCP<const import_type>& newImporter); 01037 01065 virtual void 01066 removeEmptyProcessesInPlace (const Teuchos::RCP<const map_type>& newMap); 01068 01069 protected: 01070 typedef typename KokkosClassic::DefaultKernels<void, LocalOrdinal, Node>::SparseOps 01071 sparse_ops_type; 01072 typedef typename sparse_ops_type::template graph<LocalOrdinal, Node>::graph_type 01073 local_graph_type; 01074 01075 // these structs are conveniences, to cut down on the number of 01076 // arguments to some of the methods below. 01077 struct SLocalGlobalViews { 01078 Teuchos::ArrayView<const GlobalOrdinal> ginds; 01079 Teuchos::ArrayView<const LocalOrdinal> linds; 01080 }; 01081 struct SLocalGlobalNCViews { 01082 Teuchos::ArrayView<GlobalOrdinal> ginds; 01083 Teuchos::ArrayView<LocalOrdinal> linds; 01084 }; 01085 // 01086 // Allocation 01087 // 01088 bool indicesAreAllocated() const; 01089 01090 void allocateIndices (ELocalGlobal lg); 01091 01092 template <class T> 01093 Teuchos::ArrayRCP<T> allocateValues1D () const; 01094 template <class T> 01095 Teuchos::ArrayRCP<Array<T> > allocateValues2D () const; 01096 01097 template <ELocalGlobal lg, class T> 01098 RowInfo updateAllocAndValues (RowInfo rowinfo, size_t newAllocSize, Array<T>& rowVals) 01099 { 01100 #ifdef HAVE_TPETRA_DEBUG 01101 TEUCHOS_TEST_FOR_EXCEPT( ! rowMap_->isNodeLocalElement(rowinfo.localRow) ); 01102 TEUCHOS_TEST_FOR_EXCEPT( newAllocSize < rowinfo.allocSize ); 01103 TEUCHOS_TEST_FOR_EXCEPT( (lg == LocalIndices && ! isLocallyIndexed()) || 01104 (lg == GlobalIndices && ! isGloballyIndexed()) ); 01105 TEUCHOS_TEST_FOR_EXCEPT( newAllocSize == 0 ); 01106 TEUCHOS_TEST_FOR_EXCEPT( ! indicesAreAllocated() ); 01107 #endif 01108 // ArrayRCP::resize automatically copies over values on reallocation. 01109 if (lg == LocalIndices) { 01110 lclInds2D_[rowinfo.localRow].resize (newAllocSize); 01111 } 01112 else { // lg == GlobalIndices 01113 gblInds2D_[rowinfo.localRow].resize (newAllocSize); 01114 } 01115 rowVals.resize (newAllocSize); 01116 nodeNumAllocated_ += (newAllocSize - rowinfo.allocSize); 01117 rowinfo.allocSize = newAllocSize; 01118 return rowinfo; 01119 } 01120 01122 01123 01125 void makeColMap (); 01126 void makeIndicesLocal (); 01127 void makeImportExport (); 01128 01130 01131 01132 01133 template<ELocalGlobal lg> 01134 size_t filterIndices (const SLocalGlobalNCViews &inds) const; 01135 01136 template<class T> 01137 size_t 01138 filterGlobalIndicesAndValues (const Teuchos::ArrayView<GlobalOrdinal>& ginds, 01139 const Teuchos::ArrayView<T>& vals) const 01140 { 01141 using Teuchos::ArrayView; 01142 01143 const map_type& cmap = *colMap_; 01144 size_t numFiltered = 0; 01145 typename ArrayView<T>::iterator fvalsend = vals.begin(); 01146 typename ArrayView<T>::iterator valscptr = vals.begin(); 01147 #ifdef HAVE_TPETRA_DEBUG 01148 size_t numFiltered_debug = 0; 01149 #endif 01150 typename ArrayView<GlobalOrdinal>::iterator fend = ginds.begin(); 01151 typename ArrayView<GlobalOrdinal>::iterator cptr = ginds.begin(); 01152 while (cptr != ginds.end()) { 01153 if (cmap.isNodeGlobalElement (*cptr)) { 01154 *fend++ = *cptr; 01155 *fvalsend++ = *valscptr; 01156 #ifdef HAVE_TPETRA_DEBUG 01157 ++numFiltered_debug; 01158 #endif 01159 } 01160 ++cptr; 01161 ++valscptr; 01162 } 01163 numFiltered = fend - ginds.begin(); 01164 #ifdef HAVE_TPETRA_DEBUG 01165 TEUCHOS_TEST_FOR_EXCEPT( numFiltered != numFiltered_debug ); 01166 TEUCHOS_TEST_FOR_EXCEPT( valscptr != vals.end() ); 01167 const size_t numFilteredActual = 01168 static_cast<size_t> (fvalsend - vals.begin ()); 01169 TEUCHOS_TEST_FOR_EXCEPT( numFiltered != numFilteredActual ); 01170 #endif 01171 return numFiltered; 01172 } 01173 01174 template<class T> 01175 size_t 01176 filterLocalIndicesAndValues (const Teuchos::ArrayView<LocalOrdinal>& linds, 01177 const Teuchos::ArrayView<T>& vals) const 01178 { 01179 using Teuchos::ArrayView; 01180 01181 const map_type& cmap = *colMap_; 01182 size_t numFiltered = 0; 01183 typename ArrayView<T>::iterator fvalsend = vals.begin(); 01184 typename ArrayView<T>::iterator valscptr = vals.begin(); 01185 #ifdef HAVE_TPETRA_DEBUG 01186 size_t numFiltered_debug = 0; 01187 #endif 01188 typename ArrayView<LocalOrdinal>::iterator fend = linds.begin(); 01189 typename ArrayView<LocalOrdinal>::iterator cptr = linds.begin(); 01190 while (cptr != linds.end()) { 01191 if (cmap.isNodeLocalElement (*cptr)) { 01192 *fend++ = *cptr; 01193 *fvalsend++ = *valscptr; 01194 #ifdef HAVE_TPETRA_DEBUG 01195 ++numFiltered_debug; 01196 #endif 01197 } 01198 ++cptr; 01199 ++valscptr; 01200 } 01201 numFiltered = fend - linds.begin(); 01202 #ifdef HAVE_TPETRA_DEBUG 01203 TEUCHOS_TEST_FOR_EXCEPT( numFiltered != numFiltered_debug ); 01204 TEUCHOS_TEST_FOR_EXCEPT( valscptr != vals.end() ); 01205 const size_t numFilteredActual = 01206 static_cast<size_t> (fvalsend - vals.begin ()); 01207 TEUCHOS_TEST_FOR_EXCEPT( numFiltered != numFilteredActual ); 01208 #endif 01209 return numFiltered; 01210 } 01211 01241 size_t 01242 insertIndices (const RowInfo& rowInfo, 01243 const SLocalGlobalViews& newInds, 01244 const ELocalGlobal lg, 01245 const ELocalGlobal I); 01246 01286 template<class Scalar> 01287 void 01288 insertIndicesAndValues (const RowInfo& rowInfo, 01289 const SLocalGlobalViews& newInds, 01290 const Teuchos::ArrayView<Scalar>& oldRowVals, 01291 const Teuchos::ArrayView<const Scalar>& newRowVals, 01292 const ELocalGlobal lg, 01293 const ELocalGlobal I) 01294 { 01295 const size_t numNewInds = insertIndices (rowInfo, newInds, lg, I); 01296 typename Teuchos::ArrayView<const Scalar>::const_iterator newRowValsBegin = 01297 newRowVals.begin (); 01298 std::copy (newRowValsBegin, newRowValsBegin + numNewInds, 01299 oldRowVals.begin () + rowInfo.numEntries); 01300 } 01301 01302 void 01303 insertGlobalIndicesImpl (const LocalOrdinal myRow, 01304 const Teuchos::ArrayView<const GlobalOrdinal> &indices); 01305 void 01306 insertLocalIndicesImpl (const LocalOrdinal myRow, 01307 const Teuchos::ArrayView<const LocalOrdinal> &indices); 01309 void 01310 insertLocalIndicesFiltered (const LocalOrdinal localRow, 01311 const Teuchos::ArrayView<const LocalOrdinal> &indices); 01312 01314 void 01315 insertGlobalIndicesFiltered (const GlobalOrdinal localRow, 01316 const Teuchos::ArrayView<const GlobalOrdinal> &indices); 01317 01345 template<class Scalar, class BinaryFunction> 01346 LocalOrdinal 01347 transformLocalValues (RowInfo rowInfo, 01348 const Teuchos::ArrayView<Scalar>& rowVals, 01349 const Teuchos::ArrayView<const LocalOrdinal>& inds, 01350 const Teuchos::ArrayView<const Scalar>& newVals, 01351 BinaryFunction f) const 01352 { 01353 typedef typename Teuchos::ArrayView<Scalar>::size_type size_type; 01354 const size_t STINV = Teuchos::OrdinalTraits<size_t>::invalid (); 01355 const size_type numElts = inds.size (); 01356 size_t hint = 0; // Guess for the current index k into rowVals 01357 01358 // Get a view of the column indices in the row. This amortizes 01359 // the cost of getting the view over all the entries of inds. 01360 Teuchos::ArrayView<const LocalOrdinal> colInds = getLocalView (rowInfo); 01361 01362 LocalOrdinal numValid = 0; // number of valid local column indices 01363 for (size_type j = 0; j < numElts; ++j) { 01364 const size_t k = findLocalIndex (rowInfo, inds[j], colInds, hint); 01365 if (k != STINV) { 01366 rowVals[k] = f (rowVals[k], newVals[j]); // use binary function f 01367 hint = k+1; 01368 ++numValid; 01369 } 01370 } 01371 return numValid; 01372 } 01373 01393 template<class Scalar, class BinaryFunction> 01394 LocalOrdinal 01395 transformGlobalValues (RowInfo rowInfo, 01396 const Teuchos::ArrayView<Scalar>& rowVals, 01397 const Teuchos::ArrayView<const GlobalOrdinal>& inds, 01398 const Teuchos::ArrayView<const Scalar>& newVals, 01399 BinaryFunction f) const 01400 { 01401 typedef typename Teuchos::ArrayView<Scalar>::size_type size_type; 01402 const size_t STINV = Teuchos::OrdinalTraits<size_t>::invalid (); 01403 const size_type numElts = inds.size (); 01404 size_t hint = 0; // guess at the index's relative offset in the row 01405 01406 LocalOrdinal numValid = 0; // number of valid local column indices 01407 for (size_type j = 0; j < numElts; ++j) { 01408 const size_t k = findGlobalIndex (rowInfo, inds[j], hint); 01409 if (k != STINV) { 01410 rowVals[k] = f (rowVals[k], newVals[j]); // use binary function f 01411 hint = k+1; 01412 numValid++; 01413 } 01414 } 01415 return numValid; 01416 } 01417 01419 01420 01421 01423 bool isMerged () const; 01424 01430 void setLocallyModified (); 01431 01433 void sortAllIndices (); 01434 01436 void sortRowIndices (RowInfo rowinfo); 01437 01452 template <class Scalar> 01453 void 01454 sortRowIndicesAndValues (const RowInfo rowinfo, 01455 const Teuchos::ArrayView<Scalar>& values); 01456 01465 void mergeAllIndices (); 01466 01471 void mergeRowIndices (RowInfo rowinfo); 01472 01483 template<class Scalar> 01484 void 01485 mergeRowIndicesAndValues (RowInfo rowinfo, 01486 const Teuchos::ArrayView<Scalar>& rowValues); 01488 01498 void 01499 setDomainRangeMaps (const Teuchos::RCP<const map_type> &domainMap, 01500 const Teuchos::RCP<const map_type> &rangeMap); 01501 01502 void staticAssertions() const; 01503 // global consts 01504 void clearGlobalConstants(); 01505 void computeGlobalConstants(); 01506 01508 01509 01513 RowInfo getRowInfo (size_t myRow) const; 01514 01521 Teuchos::ArrayView<const LocalOrdinal> getLocalView (RowInfo rowinfo) const; 01522 01529 Teuchos::ArrayView<LocalOrdinal> getLocalViewNonConst (RowInfo rowinfo); 01530 01537 Teuchos::ArrayView<const GlobalOrdinal> getGlobalView (RowInfo rowinfo) const; 01538 01545 Teuchos::ArrayView<GlobalOrdinal> getGlobalViewNonConst (RowInfo rowinfo); 01546 01581 size_t 01582 findLocalIndex (RowInfo rowinfo, 01583 LocalOrdinal ind, 01584 size_t hint = 0) const; 01585 01614 size_t 01615 findLocalIndex (RowInfo rowinfo, 01616 LocalOrdinal ind, 01617 Teuchos::ArrayView<const LocalOrdinal> colInds, 01618 size_t hint = 0) const; 01619 01627 size_t findGlobalIndex (RowInfo rowinfo, GlobalOrdinal ind, size_t hint = 0) const; 01628 01630 01631 01632 01633 void fillLocalGraph (const Teuchos::RCP<Teuchos::ParameterList> ¶ms); 01634 const Teuchos::RCP<const local_graph_type> getLocalGraph() const; 01635 const Teuchos::RCP<local_graph_type> getLocalGraphNonConst(); 01636 01638 01647 void checkInternalState() const; 01648 01650 Teuchos::RCP<const map_type> rowMap_; 01652 Teuchos::RCP<const map_type> colMap_; 01654 Teuchos::RCP<const map_type> rangeMap_; 01656 Teuchos::RCP<const map_type> domainMap_; 01657 01664 Teuchos::RCP<const import_type> importer_; 01665 01671 Teuchos::RCP<const export_type> exporter_; 01672 01673 // local data, stored in a KokkosClassic::CrsGraph. only initialized after fillComplete() 01674 Teuchos::RCP<local_graph_type> lclGraph_; 01675 01676 // Local and Global Counts 01677 // nodeNumEntries_ and nodeNumAllocated_ are required to be always consistent 01678 // nodeMaxNumEntries_, nodeNumDiags_ and the global quantities are computed during fillComplete() and only valid when isFillComplete() 01679 global_size_t globalNumEntries_, globalNumDiags_, globalMaxNumRowEntries_; 01680 size_t nodeNumEntries_, nodeNumDiags_, nodeMaxNumRowEntries_, nodeNumAllocated_; 01681 01683 ProfileType pftype_; 01684 01694 Teuchos::ArrayRCP<const size_t> numAllocPerRow_; 01695 01700 size_t numAllocForAllRows_; 01701 01702 // graph indices. before allocation, all are null. 01703 // after allocation, except during makeIndicesLocal(), one of local or global is null. 01704 // we will never have 1D and 2D structures being non-null 01705 // this is host memory 01706 // 1D == StaticAllocation, 2D == DynamicAllocation 01708 // 01709 // 1D/Static structures 01710 // 01712 01714 Teuchos::ArrayRCP<LocalOrdinal> lclInds1D_; 01716 Teuchos::ArrayRCP<GlobalOrdinal> gblInds1D_; 01717 // offset to the beg entries of each row. only used for 1D (Static) allocation. 01718 // i.e., indices for row R are lclInds1D_[i] for i in [b,e) where b = rowPtrs_[R] and e = rowPtrs_[R+1] 01719 // only the first numRowEntries_[R] of these are valid 01720 // both of these are null for 2D (Dynamic) allocations 01721 // rowPtrs_ has length N+1, while numRowEntries_ has length N 01722 // we may delete this to save memory on fillComplete, if "Delete Row Pointers" is specified 01723 Teuchos::ArrayRCP<size_t> rowPtrs_; 01724 01726 // 01727 // 2D/Dynamic structures. 01728 // 01730 01732 Teuchos::ArrayRCP<Teuchos::Array<LocalOrdinal> > lclInds2D_; 01733 01735 Teuchos::ArrayRCP<Teuchos::Array<GlobalOrdinal> > gblInds2D_; 01736 01741 Teuchos::ArrayRCP<size_t> numRowEntries_; 01742 01743 bool indicesAreAllocated_; 01744 bool indicesAreLocal_; 01745 bool indicesAreGlobal_; 01746 bool fillComplete_; 01748 bool lowerTriangular_; 01750 bool upperTriangular_; 01752 bool indicesAreSorted_; 01755 bool noRedundancies_; 01757 bool haveLocalConstants_; 01759 bool haveGlobalConstants_; 01760 01768 std::map<GlobalOrdinal, std::vector<GlobalOrdinal> > nonlocals_; 01769 01781 bool hasRowInfo () const; 01782 01797 bool sortGhostsAssociatedWithEachProcessor_; 01798 01799 }; // class CrsGraph 01800 01807 template <class LocalOrdinal, class GlobalOrdinal, class Node> 01808 Teuchos::RCP<CrsGraph<LocalOrdinal,GlobalOrdinal,Node> > 01809 createCrsGraph (const Teuchos::RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > &map, 01810 size_t maxNumEntriesPerRow = 0, 01811 const Teuchos::RCP<Teuchos::ParameterList>& params = Teuchos::null) 01812 { 01813 using Teuchos::rcp; 01814 typedef CrsGraph<LocalOrdinal, GlobalOrdinal, Node> graph_type; 01815 return rcp (new graph_type (map, maxNumEntriesPerRow, DynamicProfile, params)); 01816 } 01817 01818 01819 01820 namespace Details { 01821 01822 template<class LocalOrdinal, class GlobalOrdinal, class OutputNodeType, class InputNodeType> 01823 class CrsGraphCopier<CrsGraph<LocalOrdinal, GlobalOrdinal, OutputNodeType>, 01824 CrsGraph<LocalOrdinal, GlobalOrdinal, InputNodeType> > { 01825 public: 01826 typedef CrsGraph<LocalOrdinal, GlobalOrdinal, InputNodeType> input_crs_graph_type; 01827 typedef CrsGraph<LocalOrdinal, GlobalOrdinal, OutputNodeType> output_crs_graph_type; 01828 01829 static Teuchos::RCP<output_crs_graph_type> 01830 clone (const input_crs_graph_type& graphIn, 01831 const Teuchos::RCP<OutputNodeType> &nodeOut, 01832 const Teuchos::RCP<Teuchos::ParameterList>& params = Teuchos::null) 01833 { 01834 using Teuchos::arcp; 01835 using Teuchos::ArrayRCP; 01836 using Teuchos::ArrayView; 01837 using Teuchos::null; 01838 using Teuchos::outArg; 01839 using Teuchos::ParameterList; 01840 using Teuchos::parameterList; 01841 using Teuchos::RCP; 01842 using Teuchos::rcp; 01843 using Teuchos::REDUCE_MIN; 01844 using Teuchos::reduceAll; 01845 using Teuchos::sublist; 01846 using std::cerr; 01847 using std::endl; 01848 typedef LocalOrdinal LO; 01849 typedef GlobalOrdinal GO; 01850 typedef typename ArrayView<const GO>::size_type size_type; 01851 typedef ::Tpetra::Map<LO, GO, InputNodeType> input_map_type; 01852 typedef ::Tpetra::Map<LO, GO, OutputNodeType> output_map_type; 01853 const char prefix[] = "Tpetra::Details::CrsGraphCopier::clone: "; 01854 01855 // Set parameters' default values. 01856 bool debug = false; 01857 bool fillCompleteClone = true; 01858 bool useLocalIndices = graphIn.hasColMap (); 01859 ProfileType pftype = StaticProfile; 01860 // If the user provided a ParameterList, get values from there. 01861 if (! params.is_null ()) { 01862 fillCompleteClone = params->get ("fillComplete clone", fillCompleteClone); 01863 useLocalIndices = params->get ("Locally indexed clone", useLocalIndices); 01864 if (params->get ("Static profile clone", true) == false) { 01865 pftype = DynamicProfile; 01866 } 01867 debug = params->get ("Debug", debug); 01868 } 01869 01870 const Teuchos::Comm<int>& comm = * (graphIn.getRowMap ()->getComm ()); 01871 const int myRank = comm.getRank (); 01872 01873 TEUCHOS_TEST_FOR_EXCEPTION( 01874 ! graphIn.hasColMap () && useLocalIndices, std::runtime_error, 01875 prefix << "You asked clone() to use local indices (by setting the " 01876 "\"Locally indexed clone\" parameter to true), but the source graph " 01877 "does not yet have a column Map, so this is impossible."); 01878 01879 if (debug) { 01880 std::ostringstream os; 01881 os << "Process " << myRank << ": Cloning row Map" << endl; 01882 cerr << os.str (); 01883 } 01884 01885 RCP<const output_map_type> clonedRowMap = 01886 graphIn.getRowMap ()->template clone<OutputNodeType> (nodeOut); 01887 01888 // Invoke the output graph's constructor, using the input graph's 01889 // upper bounds on the number of entries in each local row. 01890 RCP<output_crs_graph_type> clonedGraph; // returned by this function 01891 { 01892 ArrayRCP<const size_t> numEntriesPerRow; 01893 size_t numEntriesForAll = 0; 01894 bool boundSameForAllLocalRows = true; 01895 01896 if (debug) { 01897 std::ostringstream os; 01898 os << "Process " << myRank << ": Getting per-row bounds" << endl; 01899 cerr << os.str (); 01900 } 01901 graphIn.getNumEntriesPerLocalRowUpperBound (numEntriesPerRow, 01902 numEntriesForAll, 01903 boundSameForAllLocalRows); 01904 if (debug) { 01905 std::ostringstream os; 01906 os << "Process " << myRank << ": numEntriesForAll = " 01907 << numEntriesForAll << endl; 01908 cerr << os.str (); 01909 } 01910 01911 if (debug) { 01912 std::ostringstream os; 01913 os << "Process " << myRank << ": graphIn.getNodeMaxNumRowEntries() = " 01914 << graphIn.getNodeMaxNumRowEntries () << endl; 01915 cerr << os.str (); 01916 } 01917 01918 RCP<ParameterList> graphparams; 01919 if (params.is_null ()) { 01920 graphparams = parameterList ("CrsGraph"); 01921 } else { 01922 graphparams = sublist (params, "CrsGraph"); 01923 } 01924 if (useLocalIndices) { 01925 RCP<const output_map_type> clonedColMap = 01926 graphIn.getColMap ()->template clone<OutputNodeType> (nodeOut); 01927 if (boundSameForAllLocalRows) { 01928 clonedGraph = rcp (new output_crs_graph_type (clonedRowMap, clonedColMap, 01929 numEntriesForAll, pftype, 01930 graphparams)); 01931 } else { 01932 clonedGraph = rcp (new output_crs_graph_type (clonedRowMap, clonedColMap, 01933 numEntriesPerRow, pftype, 01934 graphparams)); 01935 } 01936 } else { 01937 if (boundSameForAllLocalRows) { 01938 clonedGraph = rcp (new output_crs_graph_type (clonedRowMap, 01939 numEntriesForAll, pftype, 01940 graphparams)); 01941 } else { 01942 clonedGraph = rcp (new output_crs_graph_type (clonedRowMap, 01943 numEntriesPerRow, 01944 pftype, graphparams)); 01945 } 01946 } 01947 01948 if (debug) { 01949 std::ostringstream os; 01950 os << "Process " << myRank << ": Invoked output graph's constructor" << endl; 01951 cerr << os.str (); 01952 } 01953 01954 // done with these 01955 numEntriesPerRow = null; 01956 numEntriesForAll = 0; 01957 } 01958 01959 const input_map_type& inputRowMap = * (graphIn.getRowMap ()); 01960 const size_type numRows = 01961 static_cast<size_type> (inputRowMap.getNodeNumElements ()); 01962 01963 bool failed = false; 01964 01965 if (useLocalIndices) { 01966 const LO localMinLID = inputRowMap.getMinLocalIndex (); 01967 const LO localMaxLID = inputRowMap.getMaxLocalIndex (); 01968 01969 if (graphIn.isLocallyIndexed ()) { 01970 if (numRows != 0) { 01971 try { 01972 ArrayView<const LO> linds; 01973 for (LO lrow = localMinLID; lrow <= localMaxLID; ++lrow) { 01974 graphIn.getLocalRowView (lrow, linds); 01975 if (linds.size () != 0) { 01976 clonedGraph->insertLocalIndices (lrow, linds); 01977 } 01978 } 01979 } 01980 catch (std::exception& e) { 01981 std::ostringstream os; 01982 os << "Process " << myRank << ": copying (reading local by view, " 01983 "writing local) indices into the output graph threw an " 01984 "exception: " << e.what () << endl; 01985 cerr << os.str (); 01986 failed = true; 01987 } 01988 } 01989 } 01990 else { // graphIn.isGloballyIndexed() 01991 TEUCHOS_TEST_FOR_EXCEPTION( 01992 ! graphIn.hasColMap () && useLocalIndices, std::invalid_argument, 01993 prefix << "You asked clone() to use local indices (by setting the " 01994 "\"Locally indexed clone\" parameter to true), but the source graph " 01995 "does not yet have a column Map, so this is impossible."); 01996 01997 // The input graph has a column Map, but is globally indexed. 01998 // That's a bit weird, but we'll run with it. In this case, 01999 // getLocalRowView won't work, but getLocalRowCopy should 02000 // still work; it will just have to convert from global to 02001 // local indices internally. 02002 02003 try { 02004 // Make space for getLocalRowCopy to put column indices. 02005 // 02006 // This is only a hint; we may have to resize in the loop 02007 // below. getNodeMaxNumRowEntries() may return nonsense if 02008 // fill is active. The key bool in CrsGraph is 02009 // haveLocalConstants_. 02010 size_t myMaxNumRowEntries = 02011 graphIn.isFillActive () ? static_cast<size_t> (0) : 02012 graphIn.getNodeMaxNumRowEntries (); 02013 02014 Array<LO> linds (myMaxNumRowEntries); 02015 02016 // Copy each row into the new graph, using local indices. 02017 for (LO lrow = localMinLID; lrow <= localMaxLID; ++lrow) { 02018 size_t theNumEntries = graphIn.getNumEntriesInLocalRow (lrow); 02019 if (theNumEntries > myMaxNumRowEntries) { 02020 myMaxNumRowEntries = theNumEntries; 02021 linds.resize (myMaxNumRowEntries); 02022 } 02023 graphIn.getLocalRowCopy (lrow, linds (), theNumEntries); 02024 if (theNumEntries != 0) { 02025 clonedGraph->insertLocalIndices (lrow, linds (0, theNumEntries)); 02026 } 02027 } 02028 } 02029 catch (std::exception& e) { 02030 std::ostringstream os; 02031 os << "Process " << myRank << ": copying (reading local by copy, " 02032 "writing local) indices into the output graph threw an exception: " 02033 << e.what () << endl; 02034 cerr << os.str (); 02035 failed = true; 02036 } 02037 } 02038 } 02039 else { /* useGlobalIndices */ 02040 if (numRows != 0) { 02041 const GlobalOrdinal localMinGID = inputRowMap.getMinGlobalIndex (); 02042 const GlobalOrdinal localMaxGID = inputRowMap.getMaxGlobalIndex (); 02043 const bool inputRowMapIsContiguous = inputRowMap.isContiguous (); 02044 02045 if (graphIn.isGloballyIndexed ()) { 02046 ArrayView<const GlobalOrdinal> ginds; 02047 02048 if (inputRowMapIsContiguous) { 02049 try { 02050 for (GO grow = localMinGID; grow <= localMaxGID; ++grow) { 02051 graphIn.getGlobalRowView (grow, ginds); 02052 if (ginds.size () != 0) { 02053 clonedGraph->insertGlobalIndices (grow, ginds); 02054 } 02055 } 02056 } 02057 catch (std::exception& e) { 02058 std::ostringstream os; 02059 os << "Process " << myRank << ": copying (reading global by view, " 02060 "writing global) indices into the output graph threw an " 02061 "exception: " << e.what () << endl; 02062 cerr << os.str (); 02063 failed = true; 02064 } 02065 } 02066 else { // input row Map is not contiguous 02067 try { 02068 ArrayView<const GO> inputRowMapGIDs = inputRowMap.getNodeElementList (); 02069 for (size_type k = 0; k < numRows; ++k) { 02070 const GO grow = inputRowMapGIDs[k]; 02071 graphIn.getGlobalRowView (grow, ginds); 02072 if (ginds.size () != 0) { 02073 clonedGraph->insertGlobalIndices (grow, ginds); 02074 } 02075 } 02076 } 02077 catch (std::exception& e) { 02078 std::ostringstream os; 02079 os << "Process " << myRank << ": copying (reading global by view, " 02080 "writing global) indices into the output graph threw an " 02081 "exception: " << e.what () << endl; 02082 cerr << os.str (); 02083 failed = true; 02084 } 02085 } 02086 } 02087 else { // graphIn.isLocallyIndexed() 02088 // Make space for getGlobalRowCopy to put column indices. 02089 // 02090 // This is only a hint; we may have to resize in the loop 02091 // below. getNodeMaxNumRowEntries() may return nonsense if 02092 // fill is active. The key bool in CrsGraph is 02093 // haveLocalConstants_. 02094 size_t myMaxNumRowEntries = 02095 graphIn.isFillActive () ? static_cast<size_t> (0) : 02096 graphIn.getNodeMaxNumRowEntries (); 02097 02098 Array<GO> ginds (myMaxNumRowEntries); 02099 02100 if (inputRowMapIsContiguous) { 02101 try { 02102 for (GO grow = localMinGID; grow <= localMaxGID; ++grow) { 02103 size_t theNumEntries = graphIn.getNumEntriesInGlobalRow (grow); 02104 if (theNumEntries > myMaxNumRowEntries) { 02105 myMaxNumRowEntries = theNumEntries; 02106 ginds.resize (myMaxNumRowEntries); 02107 } 02108 graphIn.getGlobalRowCopy (grow, ginds (), theNumEntries); 02109 if (theNumEntries != 0) { 02110 clonedGraph->insertGlobalIndices (grow, ginds (0, theNumEntries)); 02111 } 02112 } 02113 } 02114 catch (std::exception& e) { 02115 std::ostringstream os; 02116 os << "Process " << myRank << ": copying (reading global by copy, " 02117 "writing global) indices into the output graph threw an " 02118 "exception: " << e.what () << endl; 02119 cerr << os.str (); 02120 failed = true; 02121 } 02122 } 02123 else { // input row Map is not contiguous 02124 try { 02125 ArrayView<const GO> inputRowMapGIDs = inputRowMap.getNodeElementList (); 02126 for (size_type k = 0; k < numRows; ++k) { 02127 const GO grow = inputRowMapGIDs[k]; 02128 02129 size_t theNumEntries = graphIn.getNumEntriesInGlobalRow (grow); 02130 if (theNumEntries > myMaxNumRowEntries) { 02131 myMaxNumRowEntries = theNumEntries; 02132 ginds.resize (myMaxNumRowEntries); 02133 } 02134 graphIn.getGlobalRowCopy (grow, ginds (), theNumEntries); 02135 if (theNumEntries != 0) { 02136 clonedGraph->insertGlobalIndices (grow, ginds (0, theNumEntries)); 02137 } 02138 } 02139 } 02140 catch (std::exception& e) { 02141 std::ostringstream os; 02142 os << "Process " << myRank << ": copying (reading global by copy, " 02143 "writing global) indices into the output graph threw an " 02144 "exception: " << e.what () << endl; 02145 cerr << os.str (); 02146 failed = true; 02147 } 02148 } 02149 } 02150 } // numRows != 0 02151 } 02152 02153 if (debug) { 02154 std::ostringstream os; 02155 os << "Process " << myRank << ": copied entries" << endl; 02156 cerr << os.str (); 02157 } 02158 02159 if (fillCompleteClone) { 02160 RCP<ParameterList> fillparams = params.is_null () ? 02161 parameterList ("fillComplete") : 02162 sublist (params, "fillComplete"); 02163 try { 02164 RCP<const output_map_type> clonedRangeMap; 02165 RCP<const output_map_type> clonedDomainMap; 02166 if (! graphIn.getRangeMap ().is_null () && 02167 graphIn.getRangeMap () != graphIn.getRowMap ()) { 02168 clonedRangeMap = 02169 graphIn.getRangeMap ()->template clone<OutputNodeType> (nodeOut); 02170 } 02171 else { 02172 clonedRangeMap = clonedRowMap; 02173 } 02174 if (! graphIn.getDomainMap ().is_null () 02175 && graphIn.getDomainMap () != graphIn.getRowMap ()) { 02176 clonedDomainMap = 02177 graphIn.getDomainMap ()->template clone<OutputNodeType> (nodeOut); 02178 } 02179 else { 02180 clonedDomainMap = clonedRowMap; 02181 } 02182 02183 if (debug) { 02184 std::ostringstream os; 02185 os << "Process " << myRank << ": About to call fillComplete on " 02186 "cloned graph" << endl; 02187 cerr << os.str (); 02188 } 02189 clonedGraph->fillComplete (clonedDomainMap, clonedRangeMap, fillparams); 02190 } 02191 catch (std::exception &e) { 02192 failed = true; 02193 std::ostringstream os; 02194 os << prefix << "Process " << myRank << ": Caught the following " 02195 "exception while calling fillComplete() on clone of type" 02196 << endl << Teuchos::typeName (*clonedGraph) << endl; 02197 cerr << os.str (); 02198 } 02199 } 02200 02201 int lclSuccess = failed ? 0 : 1; 02202 int gblSuccess = 1; 02203 reduceAll<int, int> (comm, REDUCE_MIN, lclSuccess, outArg (gblSuccess)); 02204 TEUCHOS_TEST_FOR_EXCEPTION( 02205 gblSuccess != 1, std::logic_error, prefix << 02206 "Clone failed on at least one process."); 02207 02208 if (debug) { 02209 std::ostringstream os; 02210 os << "Process " << myRank << ": Done with CrsGraph::clone" << endl; 02211 cerr << os.str (); 02212 } 02213 return clonedGraph; 02214 } 02215 }; 02216 02217 } // namespace Details 02218 } // namespace Tpetra 02219 02220 // Include KokkosRefactor partial specialisation if enabled 02221 #if defined(TPETRA_HAVE_KOKKOS_REFACTOR) 02222 #include "Tpetra_KokkosRefactor_CrsGraph_decl.hpp" 02223 #endif 02224 02225 #endif
1.7.6.1