Tpetra Matrix/Vector Services Version of the Day
Tpetra_CrsGraph_def.hpp
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 // FINISH: need to check that fill is active before performing a number of the methods here; adding to the tests currently
00043 
00044 #ifndef TPETRA_CRSGRAPH_DEF_HPP
00045 #define TPETRA_CRSGRAPH_DEF_HPP
00046 
00047 #include <Kokkos_NodeTrace.hpp>
00048 #include <Teuchos_Assert.hpp>
00049 #include <Teuchos_NullIteratorTraits.hpp>
00050 #include <Teuchos_as.hpp>
00051 #include <algorithm>
00052 #include <string>
00053 #include <utility>
00054 #include <Teuchos_SerialDenseMatrix.hpp>
00055 
00056 #ifdef DOXYGEN_USE_ONLY
00057   #include "Tpetra_CrsGraph_decl.hpp"
00058 #endif
00059 
00060 namespace Tpetra {
00061 
00062   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
00063   CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::
00064   CrsGraph (const RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > &rowMap,
00065             size_t maxNumEntriesPerRow,
00066             ProfileType pftype,
00067             const Teuchos::RCP<Teuchos::ParameterList>& plist)
00068   : DistObject<GlobalOrdinal,LocalOrdinal,GlobalOrdinal,Node>(rowMap)
00069   , rowMap_(rowMap)
00070   , lclGraph_(rowMap->getNodeNumElements(), rowMap->getNode())
00071   , nodeNumEntries_(0)
00072   , nodeNumAllocated_(OrdinalTraits<size_t>::invalid())
00073   , pftype_(pftype)
00074   , numAllocForAllRows_(maxNumEntriesPerRow)
00075   , indicesAreAllocated_(false)
00076   , indicesAreLocal_(false)
00077   , indicesAreGlobal_(false)
00078   {
00079     typedef Teuchos::OrdinalTraits<size_t> OTST;
00080 
00081     staticAssertions();
00082     TEUCHOS_TEST_FOR_EXCEPTION(maxNumEntriesPerRow == OTST::invalid(),
00083       std::invalid_argument, "The allocation hint must be a valid size_t value, "
00084       "which in this case means it must not be Teuchos::OrdinalTraits<size_t>::"
00085       "invalid().");
00086     if (! plist.is_null ()) {
00087       this->setParameterList (plist);
00088     }
00089     resumeFill();
00090     checkInternalState();
00091   }
00092 
00093 
00094   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
00095   CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::
00096   CrsGraph (const RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > &rowMap,
00097             const RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > &colMap,
00098             size_t maxNumEntriesPerRow,
00099             ProfileType pftype,
00100             const Teuchos::RCP<Teuchos::ParameterList>& plist)
00101   : DistObject<GlobalOrdinal,LocalOrdinal,GlobalOrdinal,Node>(rowMap)
00102   , rowMap_(rowMap)
00103   , colMap_(colMap)
00104   , lclGraph_(rowMap->getNodeNumElements(), rowMap->getNode())
00105   , nodeNumEntries_(0)
00106   , nodeNumAllocated_(OrdinalTraits<size_t>::invalid())
00107   , pftype_(pftype)
00108   , numAllocForAllRows_(maxNumEntriesPerRow)
00109   , indicesAreAllocated_(false)
00110   , indicesAreLocal_(false)
00111   , indicesAreGlobal_(false)
00112   {
00113     typedef Teuchos::OrdinalTraits<size_t> OTST;
00114 
00115     staticAssertions();
00116     TEUCHOS_TEST_FOR_EXCEPTION(maxNumEntriesPerRow == OTST::invalid(),
00117       std::invalid_argument, "The allocation hint must be a valid size_t value, "
00118       "which in this case means it must not be Teuchos::OrdinalTraits<size_t>::"
00119       "invalid().");
00120     if (! plist.is_null ()) {
00121       this->setParameterList (plist);
00122     }
00123     resumeFill();
00124     checkInternalState();
00125   }
00126 
00127 
00128   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
00129   CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::
00130   CrsGraph (const RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > &rowMap,
00131             const ArrayRCP<const size_t> &NumEntriesPerRowToAlloc,
00132             ProfileType pftype,
00133             const Teuchos::RCP<Teuchos::ParameterList>& plist)
00134   : DistObject<GlobalOrdinal,LocalOrdinal,GlobalOrdinal,Node>(rowMap)
00135   , rowMap_(rowMap)
00136   , lclGraph_(rowMap->getNodeNumElements(), rowMap->getNode())
00137   , nodeNumEntries_(0)
00138   , nodeNumAllocated_(OrdinalTraits<size_t>::invalid())
00139   , pftype_(pftype)
00140   , numAllocPerRow_(NumEntriesPerRowToAlloc)
00141   , numAllocForAllRows_(0)
00142   , indicesAreAllocated_(false)
00143   , indicesAreLocal_(false)
00144   , indicesAreGlobal_(false)
00145   {
00146     typedef Teuchos::OrdinalTraits<size_t> OTST;
00147     std::string tfecfFuncName("CrsGraph(rowMap,NumEntriesPerRowToAlloc)");
00148 
00149     staticAssertions();
00150     if (! plist.is_null ()) {
00151       this->setParameterList (plist);
00152     }
00153     TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC((size_t)NumEntriesPerRowToAlloc.size() != getNodeNumRows(), std::invalid_argument,
00154         ": NumEntriesPerRowToAlloc must have as many entries as specified by rowMap for this node.");
00155     //size_t numMin = OTST::max();
00156     //size_t numMax = OTST::zero();
00157     for (size_t r=0; r < getNodeNumRows(); ++r) {
00158       const size_t curRowCount = NumEntriesPerRowToAlloc[r];
00159       TEUCHOS_TEST_FOR_EXCEPTION(curRowCount == OTST::invalid(),
00160         std::invalid_argument, "NumEntriesPerRowToAlloc[" << r << "] specifies "
00161         "an invalid number of entries (Teuchos::OrdinalTraits<size_t>::"
00162         "invalid()).");
00163       //numMin = std::min<size_t> (numMin, curRowCount);
00164       //numMax = std::max<size_t> (numMax, curRowCount);
00165     }
00166     resumeFill();
00167     checkInternalState();
00168   }
00169 
00170 
00171   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
00172   CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::
00173   CrsGraph (const RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > &rowMap,
00174             const RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > &colMap,
00175             const ArrayRCP<const size_t> &NumEntriesPerRowToAlloc,
00176             ProfileType pftype,
00177             const Teuchos::RCP<Teuchos::ParameterList>& plist)
00178   : DistObject<GlobalOrdinal,LocalOrdinal,GlobalOrdinal,Node>(rowMap)
00179   , rowMap_(rowMap)
00180   , colMap_(colMap)
00181   , lclGraph_(rowMap->getNodeNumElements(), rowMap->getNode())
00182   , nodeNumEntries_(0)
00183   , nodeNumAllocated_(OrdinalTraits<size_t>::invalid())
00184   , pftype_(pftype)
00185   , numAllocPerRow_(NumEntriesPerRowToAlloc)
00186   , numAllocForAllRows_(0)
00187   , indicesAreAllocated_(false)
00188   , indicesAreLocal_(false)
00189   , indicesAreGlobal_(false)
00190   {
00191     typedef Teuchos::OrdinalTraits<size_t> OTST;
00192     std::string tfecfFuncName("CrsGraph(rowMap,colMap,NumEntriesPerRowToAlloc)");
00193 
00194     staticAssertions();
00195     if (! plist.is_null ()) {
00196       this->setParameterList (plist);
00197     }
00198     TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC((size_t)NumEntriesPerRowToAlloc.size() != getNodeNumRows(), std::invalid_argument,
00199         ": NumEntriesPerRowToAlloc must have as many entries as specified by rowMap for this node.");
00200     //size_t numMin = OTST::max();
00201     //size_t numMax = OTST::zero();
00202     for (size_t r=0; r < getNodeNumRows(); ++r) {
00203       const size_t curRowCount = NumEntriesPerRowToAlloc[r];
00204       TEUCHOS_TEST_FOR_EXCEPTION(curRowCount == OTST::invalid(),
00205         std::invalid_argument, "NumEntriesPerRowToAlloc[" << r << "] specifies "
00206         "an invalid number of entries (Teuchos::OrdinalTraits<size_t>::"
00207         "invalid()).");
00208       //numMin = std::min<size_t> (numMin, curRowCount);
00209       //numMax = std::max<size_t> (numMax, curRowCount);
00210     }
00211     resumeFill();
00212     checkInternalState();
00213   }
00214 
00215 
00216   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
00217   CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::~CrsGraph()
00218   {}
00219 
00220   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
00221   Teuchos::RCP<const Teuchos::ParameterList>
00222   CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::
00223   getValidParameters () const
00224   {
00225     using Teuchos::ParameterList;
00226     using Teuchos::parameterList;
00227     using Teuchos::RCP;
00228     using Teuchos::rcp_const_cast;
00229     using Teuchos::sublist;
00230 
00231     RCP<ParameterList> plist = parameterList ("Tpetra::CrsGraph");
00232 
00233     // Make a sublist for the Import.
00234     RCP<ParameterList> importSublist = parameterList ("Import");
00235 
00236     // FIXME (mfh 02 Apr 2012) We should really have the Import and
00237     // Export objects fill in these lists.  However, we don't want to
00238     // create an Import or Export unless we need them.  For now, we
00239     // know that the Import and Export just pass the list directly to
00240     // their Distributor, so we can create a Distributor here
00241     // (Distributor's constructor is a lightweight operation) and have
00242     // it fill in the list.
00243 
00244     // Fill in Distributor default parameters by creating a
00245     // Distributor and asking it to do the work.
00246     Distributor distributor (rowMap_->getComm(), importSublist);
00247     plist->set ("Import", *importSublist, "How the Import performs communication.");
00248 
00249     // Make a sublist for the Export.  For now, it's a clone of the
00250     // Import sublist.  It's not a shallow copy, though, since we
00251     // might like the Import to do communication differently than the
00252     // Export.
00253     plist->set ("Export", *importSublist, "How the Export performs communication.");
00254 
00255     return rcp_const_cast<const ParameterList> (plist);
00256   }
00257 
00258   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
00259   void
00260   CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::
00261   setParameterList (const Teuchos::RCP<Teuchos::ParameterList>& plist)
00262   {
00263     using Teuchos::ParameterList;
00264     using Teuchos::RCP;
00265 
00266     RCP<const ParameterList> validParams = getValidParameters ();
00267     plist->validateParametersAndSetDefaults (*validParams);
00268     this->setMyParamList (plist);
00269   }
00270 
00271   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
00272   global_size_t CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::getGlobalNumRows() const
00273   {
00274     return rowMap_->getGlobalNumElements();
00275   }
00276 
00277 
00278   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
00279   global_size_t CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::getGlobalNumCols() const
00280   {
00281     std::string tfecfFuncName("getGlobalNumCols()");
00282     TEUCHOS_TEST_FOR_EXCEPTION(isFillComplete() == false, std::runtime_error, ": requires domain map (which requires fillComplete()).");
00283     return getDomainMap()->getGlobalNumElements();
00284   }
00285 
00286 
00287   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
00288   size_t CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::getNodeNumRows() const
00289   {
00290     return rowMap_->getNodeNumElements();
00291   }
00292 
00293 
00294   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
00295   size_t CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::getNodeNumCols() const
00296   {
00297     std::string tfecfFuncName("getNodeNumCols()");
00298     TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(hasColMap() != true, std::runtime_error, ": requires column map.");
00299     return colMap_->getNodeNumElements();
00300   }
00301 
00302 
00303   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
00304   size_t CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::getNodeNumDiags() const
00305   {
00306     return nodeNumDiags_;
00307   }
00308 
00309 
00310   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
00311   global_size_t CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::getGlobalNumDiags() const
00312   {
00313     return globalNumDiags_;
00314   }
00315 
00316 
00317   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
00318   RCP<Node>
00319   CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::getNode() const
00320   {
00321     return rowMap_->getNode();
00322   }
00323 
00324 
00325   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
00326   const RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > &
00327   CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::getRowMap() const
00328   {
00329     return rowMap_;
00330   }
00331 
00332 
00333   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
00334   const RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > &
00335   CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::getColMap() const
00336   {
00337     return colMap_;
00338   }
00339 
00340 
00341   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
00342   const RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > &
00343   CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::getDomainMap() const
00344   {
00345     return domainMap_;
00346   }
00347 
00348 
00349   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
00350   const RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > &
00351   CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::getRangeMap() const
00352   {
00353     return rangeMap_;
00354   }
00355 
00356 
00357   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
00358   RCP<const Import<LocalOrdinal,GlobalOrdinal,Node> >
00359   CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::getImporter() const
00360   {
00361     return importer_;
00362   }
00363 
00364 
00365   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
00366   RCP<const Export<LocalOrdinal,GlobalOrdinal,Node> >
00367   CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::getExporter() const
00368   {
00369     return exporter_;
00370   }
00371 
00372 
00373   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
00374   bool CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::hasColMap() const
00375   {
00376     return (colMap_ != null);
00377   }
00378 
00379 
00380   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
00381   bool CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::isStorageOptimized() const
00382   {
00383     bool isOpt = lclGraph_.isOptimized();
00384 #ifdef HAVE_TPETRA_DEBUG
00385     std::string tfecfFuncName("isStorageOptimized()");
00386     TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC( (isOpt == true) && (getProfileType() == DynamicProfile), std::logic_error,
00387         ": Violated stated post-conditions. Please contact Tpetra team.");
00388 #endif
00389     return isOpt;
00390   }
00391 
00392 
00393   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
00394   ProfileType CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::getProfileType() const
00395   {
00396     return pftype_;
00397   }
00398 
00399 
00400   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
00401   global_size_t CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::getGlobalNumEntries() const
00402   {
00403     return globalNumEntries_;
00404   }
00405 
00406 
00407   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
00408   size_t CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::getNodeNumEntries() const
00409   {
00410     return nodeNumEntries_;
00411   }
00412 
00413 
00414   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
00415   global_size_t CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::getGlobalMaxNumRowEntries() const
00416   {
00417     return globalMaxNumRowEntries_;
00418   }
00419 
00420 
00421   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
00422   size_t CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::getNodeMaxNumRowEntries() const
00423   {
00424     return nodeMaxNumRowEntries_;
00425   }
00426 
00427 
00428   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
00429   bool CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::isFillComplete() const
00430   {
00431     return fillComplete_;
00432   }
00433 
00434 
00435   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
00436   bool CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::isFillActive() const
00437   {
00438     return !fillComplete_;
00439   }
00440 
00441 
00442   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
00443   bool CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::isUpperTriangular() const
00444   {
00445     return upperTriangular_;
00446   }
00447 
00448 
00449   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
00450   bool CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::isLowerTriangular() const
00451   {
00452     return lowerTriangular_;
00453   }
00454 
00455 
00456   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
00457   bool CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::isLocallyIndexed() const
00458   {
00459     return indicesAreLocal_;
00460   }
00461 
00462 
00463   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
00464   bool CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::isGloballyIndexed() const
00465   {
00466     return indicesAreGlobal_;
00467   }
00468 
00469 
00470   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
00471   size_t CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::getNodeAllocationSize() const
00472   {
00473     return nodeNumAllocated_;
00474   }
00475 
00476 
00477   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
00478   const RCP<const Comm<int> > &
00479   CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::getComm() const
00480   {
00481     return rowMap_->getComm();
00482   }
00483 
00484   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
00485   GlobalOrdinal CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::getIndexBase() const
00486   {
00487     return rowMap_->getIndexBase();
00488   }
00489 
00490   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
00491   bool CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::indicesAreAllocated() const
00492   {
00493     return indicesAreAllocated_;
00494   }
00495 
00496 
00499   //                                                                         //
00500   //                    Internal utility methods                             //
00501   //                                                                         //
00504 
00505 
00508   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
00509   bool CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::isSorted() const
00510   {
00511     return indicesAreSorted_;
00512   }
00513 
00514 
00517   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
00518   bool CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::isMerged() const
00519   {
00520     return noRedundancies_;
00521   }
00522 
00523 
00526   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
00527   void CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::setSorted(bool sorted)
00528   {
00529     indicesAreSorted_ = sorted;
00530   }
00531 
00532 
00535   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
00536   void CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::setMerged(bool merged)
00537   {
00538     noRedundancies_ = merged;
00539   }
00540 
00541 
00544   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
00545   void CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::allocateIndices(ELocalGlobal lg)
00546   {
00547     // this is a protected function, only callable by us. if it was called incorrectly, it is our fault.
00548     std::string tfecfFuncName("allocateIndices()");
00549     TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC( isLocallyIndexed()  && lg==GlobalIndices, std::logic_error, ": Internal logic error. Please contact Tpetra team.");
00550     TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC( isGloballyIndexed() && lg==LocalIndices,  std::logic_error, ": Internal logic error. Please contact Tpetra team.");
00551     TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC( indicesAreAllocated() == true,            std::logic_error, ": Internal logic error. Please contact Tpetra team.");
00552     const size_t numRows = getNodeNumRows();
00553     indicesAreLocal_  = (lg == LocalIndices);
00554     indicesAreGlobal_ = (lg == GlobalIndices);
00555     nodeNumAllocated_ = 0;
00556     if (getProfileType() == StaticProfile) {
00557       //
00558       //  STATIC ALLOCATION PROFILE
00559       //
00560       // determine how many entries to allocate and setup offsets into 1D arrays
00561       rowBegs_    = arcp<size_t>(numRows+1);
00562       rowBegs_[numRows] = 0;
00563       if (numRows > 0) {
00564         rowEnds_    = arcp<size_t>(numRows);
00565         // allocate offsets
00566         if (numAllocPerRow_ != null) {
00567           nodeNumAllocated_ = 0;
00568           for (size_t i=0; i < numRows; ++i) {
00569             rowBegs_[i] = nodeNumAllocated_;
00570             rowEnds_[i] = rowBegs_[i];
00571             nodeNumAllocated_ += numAllocPerRow_[i];
00572           }
00573           rowBegs_[numRows] = nodeNumAllocated_;
00574         }
00575         else {
00576           nodeNumAllocated_ = numAllocForAllRows_ * numRows;
00577           rowBegs_[0] = 0;
00578           for (size_t i=0; i < numRows; ++i) {
00579             rowEnds_[i]   = rowBegs_[i];
00580             rowBegs_[i+1] = rowBegs_[i] + numAllocForAllRows_;
00581           }
00582         }
00583         // allocate the indices
00584         if (nodeNumAllocated_ > 0) {
00585           if (lg == LocalIndices) {
00586             lclInds1D_ = arcp<LocalOrdinal>(nodeNumAllocated_);
00587           }
00588           else {
00589             gblInds1D_ = arcp<GlobalOrdinal>(nodeNumAllocated_);
00590           }
00591         }
00592       }
00593     }
00594     else {
00595       if (numRows > 0) {
00596         numEntriesPerRow_ = arcp<size_t>(numRows);
00597         std::fill( numEntriesPerRow_.begin(), numEntriesPerRow_.end(), (size_t)0 );
00598         //
00599         //  DYNAMIC ALLOCATION PROFILE
00600         //
00601         ArrayRCP<const size_t>::iterator numalloc = numAllocPerRow_.begin();
00602         size_t howmany = numAllocForAllRows_;
00603         if (lg == LocalIndices) {
00604           lclInds2D_ = arcp< ArrayRCP<LocalOrdinal> >(numRows);
00605           nodeNumAllocated_ = 0;
00606           for (size_t i=0; i < numRows; ++i) {
00607             if (numAllocPerRow_ != null) howmany = *numalloc++;
00608             nodeNumAllocated_ += howmany;
00609             if (howmany > 0) lclInds2D_[i] = arcp<LocalOrdinal>(howmany);
00610           }
00611         }
00612         else { // allocate global indices
00613           gblInds2D_ = arcp< ArrayRCP<GlobalOrdinal> >(numRows);
00614           nodeNumAllocated_ = 0;
00615           for (size_t i=0; i < numRows; ++i) {
00616             if (numAllocPerRow_ != null) howmany = *numalloc++;
00617             nodeNumAllocated_ += howmany;
00618             if (howmany > 0) gblInds2D_[i] = arcp<GlobalOrdinal>(howmany);
00619           }
00620         }
00621       }
00622     } // if numRows > 0
00623     // done with these
00624     numAllocForAllRows_ = 0;
00625     numAllocPerRow_     = null;
00626     indicesAreAllocated_ = true;
00627     checkInternalState();
00628   }
00629 
00630 
00633   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
00634   template <class T>
00635   void CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::allocateValues(ArrayRCP<T> &values1D, ArrayRCP<ArrayRCP<T> > &values2D) const
00636   {
00637     std::string tfecfFuncName("allocateValues()");
00638     TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC( indicesAreAllocated() == false, std::runtime_error, ": graph indices must be allocated before values.");
00639     values1D = null;
00640     values2D = null;
00641     if (getProfileType() == StaticProfile) {
00642       if (lclInds1D_ != null) {
00643         values1D = arcp<T>(lclInds1D_.size());
00644       }
00645       else if (gblInds1D_ != null) {
00646         values1D = arcp<T>(gblInds1D_.size());
00647       }
00648     }
00649     else {
00650       values2D = arcp<ArrayRCP<T> >(getNodeNumRows());
00651       if (lclInds2D_ != null) {
00652         for (size_t r=0; r < (size_t)lclInds2D_.size(); ++r) {
00653           if (lclInds2D_[r] != null) {
00654             values2D[r] = arcp<T>(lclInds2D_[r].size());
00655           }
00656         }
00657       }
00658       else if (gblInds2D_ != null) {
00659         for (size_t r=0; r < (size_t)gblInds2D_.size(); ++r) {
00660           if (gblInds2D_[r] != null) {
00661             values2D[r] = arcp<T>(gblInds2D_[r].size());
00662           }
00663         }
00664       }
00665     }
00666   }
00667 
00668 
00671   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
00672   template <ELocalGlobal lg>
00673   RowInfo CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::updateAlloc(RowInfo rowinfo, size_t newAllocSize)
00674   {
00675 #ifdef HAVE_TPETRA_DEBUG
00676     TEUCHOS_TEST_FOR_EXCEPT( rowMap_->isNodeLocalElement(rowinfo.localRow) == false );
00677     TEUCHOS_TEST_FOR_EXCEPT( newAllocSize < rowinfo.allocSize );
00678     TEUCHOS_TEST_FOR_EXCEPT( (lg == LocalIndices && isLocallyIndexed() == false) || (lg == GlobalIndices && isGloballyIndexed() == false) );
00679     TEUCHOS_TEST_FOR_EXCEPT( newAllocSize == 0 );
00680     TEUCHOS_TEST_FOR_EXCEPT( indicesAreAllocated() == false );
00681 #endif
00682     // allocate a larger space for row "lrow"
00683     // copy any existing data from previous allocation to new allocation
00684     // update sizes
00685     if (lg == LocalIndices) {
00686       ArrayRCP<LocalOrdinal> old_alloc = lclInds2D_[rowinfo.localRow];
00687       lclInds2D_[rowinfo.localRow] = arcp<LocalOrdinal>(newAllocSize);
00688       std::copy(old_alloc.begin(), old_alloc.begin() + rowinfo.numEntries, lclInds2D_[rowinfo.localRow].begin());
00689     }
00690     else /* if lg == GlobalIndices */ {
00691       ArrayRCP<GlobalOrdinal> old_alloc = gblInds2D_[rowinfo.localRow];
00692       gblInds2D_[rowinfo.localRow] = arcp<GlobalOrdinal>(newAllocSize);
00693       std::copy(old_alloc.begin(), old_alloc.begin() + rowinfo.numEntries, gblInds2D_[rowinfo.localRow].begin());
00694     }
00695     //
00696     nodeNumAllocated_ += (newAllocSize - rowinfo.allocSize);
00697     rowinfo.allocSize = newAllocSize;
00698     return rowinfo;
00699   }
00700 
00701 
00704   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
00705   template <ELocalGlobal lg, class T>
00706   RowInfo CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::updateAllocAndValues(RowInfo rowinfo, size_t newAllocSize, ArrayRCP<T> &rowVals)
00707   {
00708 #ifdef HAVE_TPETRA_DEBUG
00709     TEUCHOS_TEST_FOR_EXCEPT( ! rowMap_->isNodeLocalElement(rowinfo.localRow) );
00710     TEUCHOS_TEST_FOR_EXCEPT( newAllocSize < rowinfo.allocSize );
00711     TEUCHOS_TEST_FOR_EXCEPT( (lg == LocalIndices && ! isLocallyIndexed()) || (lg == GlobalIndices && ! isGloballyIndexed()) );
00712     TEUCHOS_TEST_FOR_EXCEPT( newAllocSize == 0 );
00713     TEUCHOS_TEST_FOR_EXCEPT( ! indicesAreAllocated() );
00714 #endif
00715     // allocate a larger space for row "lrow"
00716     // copy any existing data from previous allocation to new allocation
00717     // update sizes
00718     if (lg == LocalIndices) {
00719       ArrayRCP<LocalOrdinal> old_alloc = lclInds2D_[rowinfo.localRow];
00720       lclInds2D_[rowinfo.localRow] = arcp<LocalOrdinal>(newAllocSize);
00721       std::copy(old_alloc.begin(), old_alloc.begin() + rowinfo.numEntries, lclInds2D_[rowinfo.localRow].begin());
00722     }
00723     else /* if lg == GlobalIndices */ {
00724       ArrayRCP<GlobalOrdinal> old_alloc = gblInds2D_[rowinfo.localRow];
00725       gblInds2D_[rowinfo.localRow] = arcp<GlobalOrdinal>(newAllocSize);
00726       std::copy(old_alloc.begin(), old_alloc.begin() + rowinfo.numEntries, gblInds2D_[rowinfo.localRow].begin());
00727     }
00728     ArrayRCP<const T> oldVals = rowVals;
00729     rowVals = arcp<T>(newAllocSize);
00730     std::copy(oldVals.begin(), oldVals.begin() + rowinfo.numEntries, rowVals.begin());
00731     //
00732     nodeNumAllocated_ += (newAllocSize - rowinfo.allocSize);
00733     rowinfo.allocSize = newAllocSize;
00734     return rowinfo;
00735   }
00736 
00737 
00740   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
00741   ArrayView<const LocalOrdinal> CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::getLocalView(RowInfo rowinfo) const
00742   {
00743     ArrayView<const LocalOrdinal> view;
00744     if (rowinfo.allocSize > 0) {
00745       if (lclInds1D_ != null) {
00746         view = lclInds1D_(rowinfo.offset1D,rowinfo.allocSize);
00747       }
00748       else if (lclInds2D_[rowinfo.localRow] != null) {
00749         view = lclInds2D_[rowinfo.localRow]();
00750       }
00751     }
00752     return view;
00753   }
00754 
00755 
00758   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
00759   ArrayView<LocalOrdinal> CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::getLocalViewNonConst(RowInfo rowinfo)
00760   {
00761     ArrayView<LocalOrdinal> view;
00762     if (rowinfo.allocSize > 0) {
00763       if (lclInds1D_ != null) {
00764         view = lclInds1D_(rowinfo.offset1D,rowinfo.allocSize);
00765       }
00766       else if (lclInds2D_[rowinfo.localRow] != null) {
00767         view = lclInds2D_[rowinfo.localRow]();
00768       }
00769     }
00770     return view;
00771   }
00772 
00773 
00776   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
00777   ArrayView<const GlobalOrdinal> CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::getGlobalView(RowInfo rowinfo) const
00778   {
00779     ArrayView<const GlobalOrdinal> view;
00780     if (rowinfo.allocSize > 0) {
00781       if (gblInds1D_ != null) {
00782         view = gblInds1D_(rowinfo.offset1D,rowinfo.allocSize);
00783       }
00784       else if (gblInds2D_[rowinfo.localRow] != null) {
00785         view = gblInds2D_[rowinfo.localRow]();
00786       }
00787     }
00788     return view;
00789   }
00790 
00791 
00794   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
00795   ArrayView<GlobalOrdinal> CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::getGlobalViewNonConst(RowInfo rowinfo)
00796   {
00797     ArrayView<GlobalOrdinal> view;
00798     if (rowinfo.allocSize > 0) {
00799       if (gblInds1D_ != null) {
00800         view = gblInds1D_(rowinfo.offset1D,rowinfo.allocSize);
00801       }
00802       else if (gblInds2D_[rowinfo.localRow] != null) {
00803         view = gblInds2D_[rowinfo.localRow]();
00804       }
00805     }
00806     return view;
00807   }
00808 
00809 
00812   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
00813   RowInfo CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::getRowInfo(size_t myRow) const
00814   {
00815 #ifdef HAVE_TPETRA_DEBUG
00816     std::string tfecfFuncName("getRowInfo()");
00817     TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(rowMap_->isNodeLocalElement(myRow) == false, std::logic_error, ": Internal logic error. Please contact Tpetra team.");
00818 #endif
00819     const size_t STINV = OrdinalTraits<size_t>::invalid();
00820     RowInfo ret;
00821     ret.localRow = myRow;
00822     if (nodeNumAllocated_ != 0 && nodeNumAllocated_ != STINV) {
00823       // graph data structures have the info that we need
00824       //
00825       // if static graph, offsets tell us the allocation size
00826       if (getProfileType() == StaticProfile) {
00827         ret.offset1D   = rowBegs_[myRow];
00828         ret.numEntries = rowEnds_[myRow] - rowBegs_[myRow];
00829         ret.allocSize  = rowBegs_[myRow+1] - rowBegs_[myRow];
00830       }
00831       else {
00832         ret.offset1D = STINV;
00833         if (isLocallyIndexed()) {
00834           ret.allocSize = lclInds2D_[myRow].size();
00835         }
00836         else {
00837           ret.allocSize = gblInds2D_[myRow].size();
00838         }
00839         ret.numEntries = numEntriesPerRow_[myRow];
00840       }
00841     }
00842     else if (nodeNumAllocated_ == 0) {
00843       // have performed allocation, but the graph has no allocation or entries
00844       ret.allocSize = 0;
00845       ret.numEntries = 0;
00846       ret.offset1D = STINV;
00847     }
00848     else if (indicesAreAllocated() == false) {
00849       // haven't performed allocation yet; probably won't hit this code
00850       if (numAllocPerRow_ == null) {
00851         ret.allocSize = numAllocForAllRows_;
00852       }
00853       else {
00854         ret.allocSize = numAllocPerRow_[myRow];
00855       }
00856       ret.numEntries = 0;
00857       ret.offset1D = STINV;
00858     }
00859     else {
00860       // don't know how we ended up here...
00861       TEUCHOS_TEST_FOR_EXCEPT(true);
00862     }
00863     return ret;
00864   }
00865 
00866 
00869   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
00870   void CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::staticAssertions() const
00871   {
00872     // Assumption: sizeof(GlobalOrdinal) >= sizeof(LocalOrdinal)
00873     //    This is so that we can store LocalOrdinals in the memory formerly occupied by GlobalOrdinals
00874     // Assumption: max(GlobalOrdinal) >= max(LocalOrdinal)  and  max(size_t) >= max(LocalOrdinal)
00875     //    This is so that we can represent any LocalOrdinal as a size_t, and any LocalOrdinal as a GlobalOrdinal
00876     Teuchos::CompileTimeAssert<sizeof(GlobalOrdinal) < sizeof(LocalOrdinal)> cta_size1; (void)cta_size1;
00877     Teuchos::CompileTimeAssert<sizeof(global_size_t) < sizeof(size_t)      > cta_size2; (void)cta_size2;
00878     // can't call max() with CompileTimeAssert, because it isn't a constant expression; will need to make this a runtime check
00879     std::string msg = typeName(*this) + ": Object cannot be allocated with stated template arguments: size assumptions are not valid.";
00880     TEUCHOS_TEST_FOR_EXCEPTION( (size_t)OrdinalTraits<LocalOrdinal>::max() > OrdinalTraits<size_t>::max(),          std::runtime_error, msg);
00881     TEUCHOS_TEST_FOR_EXCEPTION( (global_size_t)OrdinalTraits<LocalOrdinal>::max() > (global_size_t)OrdinalTraits<GlobalOrdinal>::max(),           std::runtime_error, msg);
00882     TEUCHOS_TEST_FOR_EXCEPTION( (size_t)OrdinalTraits<GlobalOrdinal>::max() > OrdinalTraits<global_size_t>::max(),  std::runtime_error, msg);
00883     TEUCHOS_TEST_FOR_EXCEPTION( OrdinalTraits<size_t>::max() > OrdinalTraits<global_size_t>::max(),                 std::runtime_error, msg);
00884   }
00885 
00886 
00889   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
00890   template <ELocalGlobal lg>
00891   size_t CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::filterIndices(const SLocalGlobalNCViews &inds) const
00892   {
00893     const Map<LocalOrdinal,GlobalOrdinal,Node> &cmap = *colMap_;
00894     Teuchos::CompileTimeAssert<lg != GlobalIndices && lg != LocalIndices> cta_lg;
00895     (void)cta_lg;
00896     size_t numFiltered = 0;
00897 #ifdef HAVE_TPETRA_DEBUG
00898     size_t numFiltered_debug = 0;
00899 #endif
00900     if (lg == GlobalIndices) {
00901       ArrayView<GlobalOrdinal> ginds = inds.ginds;
00902       typename ArrayView<GlobalOrdinal>::iterator fend = ginds.begin(),
00903                                                   cptr = ginds.begin();
00904       while (cptr != ginds.end()) {
00905         if (cmap.isNodeGlobalElement(*cptr)) {
00906           *fend++ = *cptr;
00907 #ifdef HAVE_TPETRA_DEBUG
00908           ++numFiltered_debug;
00909 #endif
00910         }
00911         ++cptr;
00912       }
00913       numFiltered = fend - ginds.begin();
00914     }
00915     else if (lg == LocalIndices) {
00916       ArrayView<LocalOrdinal> linds = inds.linds;
00917       typename ArrayView<LocalOrdinal>::iterator fend = linds.begin(),
00918                                                  cptr = linds.begin();
00919       while (cptr != linds.end()) {
00920         if (cmap.isNodeLocalElement(*cptr)) {
00921           *fend++ = *cptr;
00922 #ifdef HAVE_TPETRA_DEBUG
00923           ++numFiltered_debug;
00924 #endif
00925         }
00926         ++cptr;
00927       }
00928       numFiltered = fend - linds.begin();
00929     }
00930 #ifdef HAVE_TPETRA_DEBUG
00931     TEUCHOS_TEST_FOR_EXCEPT( numFiltered != numFiltered_debug );
00932 #endif
00933     return numFiltered;
00934   }
00935 
00936 
00939   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
00940   template <ELocalGlobal lg, class T>
00941   size_t CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::filterIndicesAndValues(const SLocalGlobalNCViews &inds, const ArrayView<T> &vals) const
00942   {
00943     const Map<LocalOrdinal,GlobalOrdinal,Node> &cmap = *colMap_;
00944     Teuchos::CompileTimeAssert<lg != GlobalIndices && lg != LocalIndices> cta_lg;
00945     (void)cta_lg;
00946     size_t numFiltered = 0;
00947     typename ArrayView<T>::iterator fvalsend = vals.begin(),
00948                                     valscptr = vals.begin();
00949 #ifdef HAVE_TPETRA_DEBUG
00950     size_t numFiltered_debug = 0;
00951 #endif
00952     if (lg == GlobalIndices) {
00953       ArrayView<GlobalOrdinal> ginds = inds.ginds;
00954       typename ArrayView<GlobalOrdinal>::iterator fend = ginds.begin(),
00955                                                   cptr = ginds.begin();
00956       while (cptr != ginds.end()) {
00957         if (cmap.isNodeGlobalElement(*cptr)) {
00958           *fend++ = *cptr;
00959           *fvalsend++ = *valscptr;
00960 #ifdef HAVE_TPETRA_DEBUG
00961           ++numFiltered_debug;
00962 #endif
00963         }
00964         ++cptr;
00965         ++valscptr;
00966       }
00967       numFiltered = fend - ginds.begin();
00968     }
00969     else if (lg == LocalIndices) {
00970       ArrayView<LocalOrdinal> linds = inds.linds;
00971       typename ArrayView<LocalOrdinal>::iterator fend = linds.begin(),
00972                                                  cptr = linds.begin();
00973       while (cptr != linds.end()) {
00974         if (cmap.isNodeLocalElement(*cptr)) {
00975           *fend++ = *cptr;
00976           *fvalsend++ = *valscptr;
00977 #ifdef HAVE_TPETRA_DEBUG
00978           ++numFiltered_debug;
00979 #endif
00980         }
00981         ++cptr;
00982         ++valscptr;
00983       }
00984       numFiltered = fend - linds.begin();
00985     }
00986 #ifdef HAVE_TPETRA_DEBUG
00987     TEUCHOS_TEST_FOR_EXCEPT( numFiltered != numFiltered_debug );
00988     TEUCHOS_TEST_FOR_EXCEPT( valscptr != vals.end() );
00989     TEUCHOS_TEST_FOR_EXCEPT( numFiltered != (size_t)(fvalsend - vals.begin()) );
00990 #endif
00991     return numFiltered;
00992   }
00993 
00994 
00997   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
00998   template <ELocalGlobal lg, ELocalGlobal I>
00999   size_t CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::insertIndices(RowInfo rowinfo, const SLocalGlobalViews &newInds)
01000   {
01001     Teuchos::CompileTimeAssert<lg != GlobalIndices && lg != LocalIndices> cta_lg; (void)cta_lg;
01002     size_t numNewInds = 0;
01003     if (lg == GlobalIndices) {
01004       ArrayView<const GlobalOrdinal> new_ginds = newInds.ginds;
01005       numNewInds = new_ginds.size();
01006       if (I == GlobalIndices) {
01007         ArrayView<GlobalOrdinal> gind_view = getGlobalViewNonConst(rowinfo);
01008         std::copy(new_ginds.begin(), new_ginds.end(), gind_view.begin()+rowinfo.numEntries);
01009       }
01010       else if (I == LocalIndices) {
01011         ArrayView<LocalOrdinal> lind_view = getLocalViewNonConst(rowinfo);
01012         typename ArrayView<const GlobalOrdinal>::iterator         in = new_ginds.begin();
01013         const typename ArrayView<const GlobalOrdinal>::iterator stop = new_ginds.end();
01014         typename ArrayView<LocalOrdinal>::iterator out = lind_view.begin()+rowinfo.numEntries;
01015         while (in != stop) {
01016           *out++ = colMap_->getLocalElement (*in++);
01017         }
01018       }
01019     }
01020     else if (lg == LocalIndices) {
01021       ArrayView<const LocalOrdinal> new_linds = newInds.linds;
01022       numNewInds = new_linds.size();
01023       if (I == LocalIndices) {
01024         ArrayView<LocalOrdinal> lind_view = getLocalViewNonConst(rowinfo);
01025         std::copy(new_linds.begin(), new_linds.end(), lind_view.begin()+rowinfo.numEntries);
01026       }
01027       else if (I == GlobalIndices) {
01028         // not needed yet
01029         TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Tpetra::CrsGraph::"
01030           "insertIndices: the case where the input indices are local and the "
01031           "indices to write are global (lg=LocalIndices, I=GlobalIndices) has "
01032           "not yet been implemented.");
01033       }
01034     }
01035     if (getProfileType() == StaticProfile) {
01036       rowEnds_[rowinfo.localRow] += numNewInds;
01037     }
01038     else {
01039       numEntriesPerRow_[rowinfo.localRow] += numNewInds;
01040     }
01041     nodeNumEntries_ += numNewInds;
01042     setSorted(false);
01043     noRedundancies_ = false;
01044     return numNewInds;
01045   }
01046 
01047 
01050   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
01051   template <ELocalGlobal lg, ELocalGlobal I, class IterO, class IterN>
01052   void CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::insertIndicesAndValues(RowInfo rowinfo, const SLocalGlobalViews &newInds, IterO rowVals, IterN newVals)
01053   {
01054     size_t numNewInds = insertIndices<lg,I>(rowinfo,newInds);
01055     std::copy( newVals, newVals + numNewInds, rowVals + rowinfo.numEntries );
01056   }
01057 
01058 
01061   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
01062   template <ELocalGlobal lg, class IterO, class IterN, class BinaryFunction>
01063   void CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::transformValues(RowInfo rowinfo, const SLocalGlobalViews &inds, IterO rowVals, IterN newVals, BinaryFunction f) const
01064   {
01065     Teuchos::CompileTimeAssert<lg != GlobalIndices && lg != LocalIndices> cta_lg; (void)cta_lg;
01066     const size_t STINV = OrdinalTraits<size_t>::invalid();
01067     if (lg == GlobalIndices) {
01068       ArrayView<const GlobalOrdinal> search_ginds = inds.ginds;
01069       for (size_t j=0; j < (size_t)search_ginds.size(); ++j) {
01070         const size_t k = findGlobalIndex(rowinfo, search_ginds[j]);
01071         if (k != STINV) {
01072           rowVals[k] = f( rowVals[k], newVals[j] );
01073         }
01074       }
01075     }
01076     else if (lg == LocalIndices) {
01077       ArrayView<const LocalOrdinal> search_linds = inds.linds;
01078       for (size_t j=0; j < (size_t)search_linds.size(); ++j) {
01079         const size_t k = findLocalIndex(rowinfo, search_linds[j]);
01080         if (k != STINV) {
01081           rowVals[k] = f( rowVals[k], newVals[j] );
01082         }
01083       }
01084     }
01085   }
01086 
01087 
01090   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
01091   void CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::sortRowIndices(RowInfo rowinfo)
01092   {
01093     if (rowinfo.numEntries > 0) {
01094       ArrayView<LocalOrdinal> inds_view = getLocalViewNonConst(rowinfo);
01095       std::sort(inds_view.begin(), inds_view.begin() + rowinfo.numEntries);
01096     }
01097   }
01098 
01099 
01102   // in the future, perhaps this could use std::sort with a boost::zip_iterator
01103   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
01104   template <class Scalar>
01105   void CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::sortRowIndicesAndValues(RowInfo rowinfo, ArrayView<Scalar> values)
01106   {
01107     if (rowinfo.numEntries > 0) {
01108       ArrayView<LocalOrdinal> inds_view = getLocalViewNonConst(rowinfo);
01109       sort2(inds_view.begin(), inds_view.begin()+rowinfo.numEntries, values.begin());
01110     }
01111   }
01112 
01113 
01116   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
01117   void CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::mergeRowIndices(RowInfo rowinfo)
01118   {
01119     ArrayView<LocalOrdinal> inds_view = getLocalViewNonConst(rowinfo);
01120     typename ArrayView<LocalOrdinal>::iterator beg, end, newend;
01121     beg = inds_view.begin();
01122     end = inds_view.begin() + rowinfo.numEntries;
01123     newend = std::unique(beg,end);
01124     const size_t mergedEntries = newend - beg;
01125 #ifdef HAVE_TPETRA_DEBUG
01126     // merge should not have eliminated any entries; if so, the assignment below will destory the packed structure
01127     TEUCHOS_TEST_FOR_EXCEPT( isStorageOptimized() && mergedEntries != rowinfo.numEntries );
01128 #endif
01129     if (getProfileType() == StaticProfile) {
01130       rowEnds_[rowinfo.localRow] = rowBegs_[rowinfo.localRow] + mergedEntries;
01131     }
01132     else {
01133       numEntriesPerRow_[rowinfo.localRow] = mergedEntries;
01134     }
01135     nodeNumEntries_ -= (rowinfo.numEntries - mergedEntries);
01136   }
01137 
01138 
01141   // in the future, this could use std::unique with a boost::zip_iterator
01142   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
01143   template <class Iter, class BinaryFunction>
01144   void CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::mergeRowIndicesAndValues(RowInfo rowinfo, Iter rowValueIter, BinaryFunction f)
01145   {
01146     ArrayView<LocalOrdinal> inds_view = getLocalViewNonConst(rowinfo);
01147     typename ArrayView<LocalOrdinal>::iterator beg, end, newend;
01148     beg = inds_view.begin();
01149     end = inds_view.begin() + rowinfo.numEntries;
01150     newend = beg;
01151     if (beg != end) {
01152       typename ArrayView<LocalOrdinal>::iterator cur = beg + 1;
01153       Iter vcur = rowValueIter + 1,
01154            vend = rowValueIter;
01155       cur = beg+1;
01156       while (cur != end) {
01157         if (*cur != *newend) {
01158           // new entry; save it
01159           ++newend;
01160           ++vend;
01161           (*newend) = (*cur);
01162           (*vend) = (*vcur);
01163         }
01164         else {
01165           // old entry; merge it
01166           (*vend) = f(*vend,*vcur);
01167         }
01168         ++cur;
01169         ++vcur;
01170       }
01171       ++newend; // point one past the last entry, per typical [beg,end) semantics
01172     }
01173     const size_t mergedEntries = newend - beg;
01174 #ifdef HAVE_TPETRA_DEBUG
01175     // merge should not have eliminated any entries; if so, the assignment below will destory the packed structure
01176     TEUCHOS_TEST_FOR_EXCEPT( isStorageOptimized() && mergedEntries != rowinfo.numEntries );
01177 #endif
01178     if (getProfileType() == StaticProfile) {
01179       rowEnds_[rowinfo.localRow] = rowBegs_[rowinfo.localRow] + mergedEntries;
01180     }
01181     else {
01182       numEntriesPerRow_[rowinfo.localRow] = mergedEntries;
01183     }
01184     nodeNumEntries_ -= (rowinfo.numEntries - mergedEntries);
01185   }
01186 
01187 
01190   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
01191   void CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::setDomainRangeMaps(
01192                                 const RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > &domainMap,
01193                                 const RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > &rangeMap)
01194   {
01195     // simple pointer comparison for equality
01196     if (domainMap_ != domainMap) {
01197       domainMap_ = domainMap;
01198       importer_ = null;
01199     }
01200     if (rangeMap_ != rangeMap) {
01201       rangeMap_  = rangeMap;
01202       exporter_ = null;
01203     }
01204   }
01205 
01206 
01209   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
01210   size_t CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::findLocalIndex(RowInfo rowinfo, LocalOrdinal ind) const
01211   {
01212     typedef typename ArrayView<const LocalOrdinal>::iterator IT;
01213     bool found = true;
01214     // get a view of the row, if it wasn't passed by the caller
01215     ArrayView<const LocalOrdinal> rowinds = getLocalView(rowinfo);
01216     IT rptr, locptr = Teuchos::NullIteratorTraits<IT>::getNull();
01217     rptr = rowinds.begin();
01218     if (isSorted()) {
01219       // binary search
01220       std::pair<IT,IT> p = std::equal_range(rptr,rptr+rowinfo.numEntries,ind);
01221       if (p.first == p.second) found = false;
01222       else locptr = p.first;
01223     }
01224     else {
01225       // direct search
01226       locptr = std::find(rptr,rptr+rowinfo.numEntries,ind);
01227       if (locptr == rptr+rowinfo.numEntries) found = false;
01228     }
01229     size_t ret = OrdinalTraits<size_t>::invalid();
01230     if (found) {
01231       ret = (locptr - rptr);
01232     }
01233     return ret;
01234   }
01235 
01236 
01239   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
01240   size_t CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::findGlobalIndex(RowInfo rowinfo, GlobalOrdinal ind) const
01241   {
01242     typedef typename ArrayView<const GlobalOrdinal>::iterator IT;
01243     bool found = true;
01244     // get a view of the row, if it wasn't passed by the caller
01245     ArrayView<const GlobalOrdinal> rowinds = getGlobalView(rowinfo);
01246     IT rptr, locptr = Teuchos::NullIteratorTraits<IT>::getNull();
01247     rptr = rowinds.begin();
01248     if (isSorted()) {
01249       // binary search
01250       std::pair<IT,IT> p = std::equal_range(rptr,rptr+rowinfo.numEntries,ind);
01251       if (p.first == p.second) found = false;
01252       else locptr = p.first;
01253     }
01254     else {
01255       // direct search
01256       locptr = std::find(rptr,rptr+rowinfo.numEntries,ind);
01257       if (locptr == rptr+rowinfo.numEntries) found = false;
01258     }
01259     size_t ret = OrdinalTraits<size_t>::invalid();
01260     if (found) {
01261       ret = (locptr - rptr);
01262     }
01263     return ret;
01264   }
01265 
01266 
01269   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
01270   void CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::clearGlobalConstants()
01271   {
01272     globalNumEntries_       = OrdinalTraits<global_size_t>::invalid();
01273     globalNumDiags_         = OrdinalTraits<global_size_t>::invalid();
01274     globalMaxNumRowEntries_ = OrdinalTraits<global_size_t>::invalid();
01275     nodeNumDiags_           = OrdinalTraits<       size_t>::invalid();
01276     nodeMaxNumRowEntries_   = OrdinalTraits<       size_t>::invalid();
01277     haveGlobalConstants_    = false;
01278   }
01279 
01280 
01283   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
01284   void CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::checkInternalState() const
01285   {
01286 #ifdef HAVE_TPETRA_DEBUG
01287     const global_size_t GSTI = OrdinalTraits<global_size_t>::invalid();
01288     const size_t         STI = OrdinalTraits<size_t>::invalid();
01289     std::string err = typeName(*this) + "::checkInternalState(): Likely internal logic error. Please contact Tpetra team.";
01290     // check the internal state of this data structure
01291     // this is called by numerous state-changing methods, in a debug build, to ensure that the object
01292     // always remains in a valid state
01293     // the graph should have been allocated with a row map
01294     TEUCHOS_TEST_FOR_EXCEPTION( rowMap_ == null,                    std::logic_error, err );
01295     // am either complete or active
01296     TEUCHOS_TEST_FOR_EXCEPTION( isFillActive() == isFillComplete(), std::logic_error, err );
01297     // if the graph has been fill completed, then all maps should be present
01298     TEUCHOS_TEST_FOR_EXCEPTION( isFillComplete() == true && (colMap_ == null || rangeMap_ == null || domainMap_ == null), std::logic_error, err );
01299     // if storage has been optimized, then indices should have been allocated (even if trivially so)
01300     TEUCHOS_TEST_FOR_EXCEPTION( isStorageOptimized() == true && indicesAreAllocated() == false, std::logic_error, err );
01301     // if storage has been optimized, then number of allocated is now the number of entries
01302     TEUCHOS_TEST_FOR_EXCEPTION( isStorageOptimized() == true && getNodeAllocationSize() != getNodeNumEntries(), std::logic_error, err );
01303     // if graph doesn't have the global constants, then they should all be marked as invalid
01304     TEUCHOS_TEST_FOR_EXCEPTION( haveGlobalConstants_ == false && ( globalNumEntries_ != GSTI || globalNumDiags_ != GSTI || globalMaxNumRowEntries_ != GSTI ), std::logic_error, err );
01305     // if the graph has global cosntants, then they should be valid.
01306     TEUCHOS_TEST_FOR_EXCEPTION( haveGlobalConstants_ == true && ( globalNumEntries_ == GSTI || globalNumDiags_ == GSTI || globalMaxNumRowEntries_ == GSTI ), std::logic_error, err );
01307     TEUCHOS_TEST_FOR_EXCEPTION( haveGlobalConstants_ == true && ( globalNumEntries_ < nodeNumEntries_ || globalNumDiags_ < nodeNumDiags_ || globalMaxNumRowEntries_ < nodeMaxNumRowEntries_ ),
01308                         std::logic_error, err );
01309     // if indices are allocated, then the allocation specifications should have been released
01310     TEUCHOS_TEST_FOR_EXCEPTION( indicesAreAllocated() == true  && (numAllocForAllRows_ != 0 || numAllocPerRow_ != null),                        std::logic_error, err );
01311     // if indices are not allocated, then information dictating allocation quantities should be present
01312     TEUCHOS_TEST_FOR_EXCEPTION( indicesAreAllocated() == false && (nodeNumAllocated_ != STI || nodeNumEntries_ != 0),                           std::logic_error, err );
01313     // if storage is optimized, then profile should be static
01314     TEUCHOS_TEST_FOR_EXCEPTION( isStorageOptimized() && pftype_ != StaticProfile,                                                               std::logic_error, err );
01315     // rowBegs_ is required to have N+1 rows; rowBegs_[N] == gblInds1D_.size()/lclInds1D_.size()
01316     TEUCHOS_TEST_FOR_EXCEPTION( isGloballyIndexed() && rowBegs_ != null && ((size_t)rowBegs_.size() != getNodeNumRows()+1 || rowBegs_[getNodeNumRows()] != (size_t)gblInds1D_.size()), std::logic_error, err );
01317     TEUCHOS_TEST_FOR_EXCEPTION(  isLocallyIndexed() && rowBegs_ != null && ((size_t)rowBegs_.size() != getNodeNumRows()+1 || rowBegs_[getNodeNumRows()] != (size_t)lclInds1D_.size()), std::logic_error, err );
01318     // rowEnds_ is required to have N rows
01319     TEUCHOS_TEST_FOR_EXCEPTION( rowEnds_ != null && (size_t)rowEnds_.size() != getNodeNumRows(),                                                std::logic_error, err );
01320     // if profile is dynamic and we have allocated, then 2D allocations should be present
01321     TEUCHOS_TEST_FOR_EXCEPTION( pftype_ == DynamicProfile && indicesAreAllocated() && getNodeNumRows() > 0 && lclInds2D_ == null && gblInds2D_ == null,
01322                                                                                                                                         std::logic_error, err );
01323     // if profile is dynamic, then numentries and 2D indices are needed and should be present
01324     TEUCHOS_TEST_FOR_EXCEPTION( pftype_ == DynamicProfile && indicesAreAllocated() && getNodeNumRows() > 0 && (numEntriesPerRow_ == null || (lclInds2D_ == null && gblInds2D_ == null)),
01325                                                                                                                                         std::logic_error, err );
01326     // if profile is dynamic, then 1D allocations should not be present
01327     TEUCHOS_TEST_FOR_EXCEPTION( pftype_ == DynamicProfile && (lclInds1D_ != null || gblInds1D_ != null),                                        std::logic_error, err );
01328     // if profile is dynamic, then row offsets should not be present
01329     TEUCHOS_TEST_FOR_EXCEPTION( pftype_ == DynamicProfile && (rowBegs_ != null || rowEnds_ != null),                                            std::logic_error, err );
01330     // if profile is static and we have allocated non-trivially, then 1D allocations should be present
01331     TEUCHOS_TEST_FOR_EXCEPTION( pftype_ == StaticProfile && indicesAreAllocated() && getNodeAllocationSize() > 0 && lclInds1D_ == null && gblInds1D_ == null,
01332                                                                                                                                         std::logic_error, err );
01333     // if profile is static and we have a non-trivial application, then row offsets should be allocated
01334     TEUCHOS_TEST_FOR_EXCEPTION( pftype_ == StaticProfile && indicesAreAllocated() && getNodeNumRows() > 0 && (rowBegs_ == null || rowEnds_ == null),
01335                                                                                                                                         std::logic_error, err );
01336     // if profile is static, then 2D allocations should not be present
01337     TEUCHOS_TEST_FOR_EXCEPTION( pftype_ == StaticProfile && (lclInds2D_ != null || gblInds2D_ != null),                                         std::logic_error, err );
01338     // if profile is static, then we have no need for numentries and it should not be present
01339     TEUCHOS_TEST_FOR_EXCEPTION( pftype_ == StaticProfile && indicesAreAllocated() && getNodeNumRows() > 0 && numEntriesPerRow_ != null,         std::logic_error, err );
01340     // if indices are not allocated, then none of the buffers should be.
01341     TEUCHOS_TEST_FOR_EXCEPTION( indicesAreAllocated() == false && (rowBegs_ != null || rowEnds_ != null  || numEntriesPerRow_ != null ||
01342                                                            lclInds1D_ != null || lclInds2D_ != null ||
01343                                                            gblInds1D_ != null || gblInds2D_ != null),                                   std::logic_error, err );
01344     // indices may be local or global only if they are allocated (numAllocated is redundant; could simply be indicesAreLocal_ || indicesAreGlobal_)
01345     TEUCHOS_TEST_FOR_EXCEPTION( (indicesAreLocal_ == true || indicesAreGlobal_ == true) && indicesAreAllocated_ == false,         std::logic_error, err );
01346     // indices may be local or global, but not both
01347     TEUCHOS_TEST_FOR_EXCEPTION( indicesAreLocal_ == true && indicesAreGlobal_ == true,                                            std::logic_error, err );
01348     // if indices are local, then global allocations should not be present
01349     TEUCHOS_TEST_FOR_EXCEPTION( indicesAreLocal_ == true && (gblInds1D_ != null || gblInds2D_ != null),                           std::logic_error, err );
01350     // if indices are global, then local allocations should not be present
01351     TEUCHOS_TEST_FOR_EXCEPTION( indicesAreGlobal_ == true && (lclInds1D_ != null || lclInds2D_ != null),                          std::logic_error, err );
01352     // if indices are local, then local allocations should be present
01353     TEUCHOS_TEST_FOR_EXCEPTION( indicesAreLocal_ == true && getNodeAllocationSize() > 0 && lclInds1D_ == null && getNodeNumRows() > 0 && lclInds2D_ == null,
01354                                                                                                                           std::logic_error, err );
01355     // if indices are global, then global allocations should be present
01356     TEUCHOS_TEST_FOR_EXCEPTION( indicesAreGlobal_ == true && getNodeAllocationSize() > 0 && gblInds1D_ == null && getNodeNumRows() > 0 && gblInds2D_ == null,
01357                                                                                                                           std::logic_error, err );
01358     // if indices are allocated, then we should have recorded how many were allocated
01359     TEUCHOS_TEST_FOR_EXCEPTION( indicesAreAllocated() == true  && nodeNumAllocated_ == STI,                                       std::logic_error, err );
01360     // if indices are not allocated, then the allocation size should be marked invalid
01361     TEUCHOS_TEST_FOR_EXCEPTION( indicesAreAllocated() == false && nodeNumAllocated_ != STI,                                       std::logic_error, err );
01362     // check the actual allocations
01363     if (indicesAreAllocated()) {
01364       size_t actualNumAllocated = 0;
01365       if (pftype_ == DynamicProfile) {
01366         if (isGloballyIndexed() && gblInds2D_ != null) {
01367           for (size_t r = 0; r < getNodeNumRows(); ++r) {
01368             actualNumAllocated += gblInds2D_[r].size();
01369           }
01370         }
01371         else if (isLocallyIndexed() && lclInds2D_ != null) {
01372           for (size_t r = 0; r < getNodeNumRows(); ++r) {
01373             actualNumAllocated += lclInds2D_[r].size();
01374           }
01375         }
01376       }
01377       else { // pftype_ == StaticProfile)
01378         actualNumAllocated = rowBegs_[getNodeNumRows()];
01379         TEUCHOS_TEST_FOR_EXCEPTION(  isLocallyIndexed() == true && (size_t)lclInds1D_.size() != actualNumAllocated, std::logic_error, err );
01380         TEUCHOS_TEST_FOR_EXCEPTION( isGloballyIndexed() == true && (size_t)gblInds1D_.size() != actualNumAllocated, std::logic_error, err );
01381       }
01382       TEUCHOS_TEST_FOR_EXCEPTION(indicesAreAllocated() == true && actualNumAllocated != nodeNumAllocated_, std::logic_error, err );
01383     }
01384 #endif
01385   }
01386 
01387 
01390   //                                                                         //
01391   //                  User-visible class methods                             //
01392   //                                                                         //
01395 
01396 
01399   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
01400   size_t CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::getNumEntriesInGlobalRow(GlobalOrdinal globalRow) const
01401   {
01402     const LocalOrdinal lrow = rowMap_->getLocalElement(globalRow);
01403     size_t ret = OrdinalTraits<size_t>::invalid();
01404     if (lrow != OrdinalTraits<LocalOrdinal>::invalid())
01405     {
01406       RowInfo rowinfo = getRowInfo(lrow);
01407       ret = rowinfo.numEntries;
01408     }
01409     return ret;
01410   }
01411 
01412 
01415   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
01416   size_t CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::getNumEntriesInLocalRow(LocalOrdinal localRow) const
01417   {
01418     size_t ret = OrdinalTraits<size_t>::invalid();
01419     if (rowMap_->isNodeLocalElement(localRow)) {
01420       RowInfo rowinfo = getRowInfo(localRow);
01421       ret = rowinfo.numEntries;
01422     }
01423     return ret;
01424   }
01425 
01426 
01429   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
01430   size_t CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::getNumAllocatedEntriesInGlobalRow(GlobalOrdinal globalRow) const
01431   {
01432     const LocalOrdinal lrow = rowMap_->getLocalElement(globalRow);
01433     size_t ret = OrdinalTraits<size_t>::invalid();
01434     if (lrow != OrdinalTraits<LocalOrdinal>::invalid())
01435     {
01436       RowInfo rowinfo = getRowInfo(lrow);
01437       ret = rowinfo.allocSize;
01438     }
01439     return ret;
01440   }
01441 
01442 
01445   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
01446   size_t CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::getNumAllocatedEntriesInLocalRow(LocalOrdinal localRow) const
01447   {
01448     size_t ret = OrdinalTraits<size_t>::invalid();
01449     if (rowMap_->isNodeLocalElement(localRow)) {
01450       RowInfo rowinfo = getRowInfo(localRow);
01451       ret = rowinfo.allocSize;
01452     }
01453     return ret;
01454   }
01455 
01456 
01459   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
01460   ArrayRCP<const size_t> CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::getNodeRowBegs() const
01461   {
01462     return rowBegs_;
01463   }
01464 
01465 
01468   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
01469   ArrayRCP<const LocalOrdinal> CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::getNodePackedIndices() const
01470   {
01471     return lclInds1D_;
01472   }
01473 
01474 
01477   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
01478   void CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::getLocalRowCopy(LocalOrdinal localRow, const ArrayView<LocalOrdinal> &indices, size_t &NumIndices) const
01479   {
01480     // can only do this if
01481     // * we have local indices: isLocallyIndexed()
01482     // or
01483     // * we are capable of producing them: isGloballyIndexed() && hasColMap()
01484     // short circuit if we aren't allocated
01485     std::string tfecfFuncName("getLocalRowCopy(localRow,...)");
01486     TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(isGloballyIndexed() == true && hasColMap() == false, std::runtime_error, ": local indices cannot be produced.");
01487     TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(rowMap_->isNodeLocalElement(localRow) == false, std::runtime_error,
01488         ": localRow (== " << localRow << ") is not valid on this node.");
01489     const RowInfo rowinfo = getRowInfo(localRow);
01490     NumIndices = rowinfo.numEntries;
01491     TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC((size_t)indices.size() < NumIndices, std::runtime_error,
01492         ": specified storage (size==" << indices.size()
01493         << ") is not large enough to hold all entries for this row (NumIndices == " << NumIndices << ").");
01494     if (isLocallyIndexed()) {
01495       ArrayView<const LocalOrdinal> lview = getLocalView(rowinfo);
01496       std::copy( lview.begin(), lview.begin() + NumIndices, indices.begin());
01497     }
01498     else if (isGloballyIndexed()) {
01499       ArrayView<const GlobalOrdinal> gview = getGlobalView(rowinfo);
01500       for (size_t j=0; j < NumIndices; ++j) {
01501         indices[j] = colMap_->getLocalElement(gview[j]);
01502       }
01503     }
01504     else {
01505 #ifdef HAVE_TPETRA_DEBUG
01506       // should have fallen in one of the above
01507       TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC( indicesAreAllocated() == true, std::logic_error, ": Internal logic error. Please contact Tpetra team.");
01508 #endif
01509       NumIndices = 0;
01510     }
01511     return;
01512   }
01513 
01514 
01517   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
01518   void CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::getGlobalRowCopy(GlobalOrdinal globalRow, const ArrayView<GlobalOrdinal> &indices, size_t &NumIndices) const
01519   {
01520     // we either currently store global indices, or we have a column map with which to transcribe our local indices for the user
01521     const LocalOrdinal lrow = rowMap_->getLocalElement(globalRow);
01522     std::string tfecfFuncName("getGlobalRowCopy(globalRow,...)");
01523     TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(lrow == OrdinalTraits<LocalOrdinal>::invalid(), std::runtime_error,
01524         ": globalRow (== " << globalRow << ") does not belong to this node.");
01525     const RowInfo rowinfo = getRowInfo((size_t)lrow);
01526     NumIndices = rowinfo.numEntries;
01527     TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC((size_t)indices.size() < NumIndices, std::runtime_error,
01528         ": specified storage (size==" << indices.size()
01529         << ") is not large enough to hold all entries for this row (NumIndices == " << NumIndices << ").");
01530     if (isLocallyIndexed()) {
01531       ArrayView<const LocalOrdinal> lview = getLocalView(rowinfo);
01532       for (size_t j=0; j < NumIndices; ++j) {
01533         indices[j] = colMap_->getGlobalElement(lview[j]);
01534       }
01535     }
01536     else if (isGloballyIndexed()) {
01537       ArrayView<const GlobalOrdinal> gview = getGlobalView(rowinfo);
01538       std::copy(gview.begin(), gview.begin() + NumIndices, indices.begin());
01539     }
01540     return;
01541   }
01542 
01543 
01546   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
01547   void CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::getLocalRowView(LocalOrdinal localRow, ArrayView<const LocalOrdinal> &indices) const
01548   {
01549     std::string tfecfFuncName("getLocalRowView()");
01550     TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(isGloballyIndexed() == true, std::runtime_error, ": local indices cannot be provided.");
01551     indices = null;
01552     if (rowMap_->isNodeLocalElement(localRow) == true) {
01553       const RowInfo rowinfo = getRowInfo(localRow);
01554       if (rowinfo.numEntries > 0) {
01555         indices = getLocalView(rowinfo);
01556         indices = indices(0,rowinfo.numEntries);
01557       }
01558     }
01559 #ifdef HAVE_TPETRA_DEBUG
01560     TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC( (size_t)indices.size() != getNumEntriesInLocalRow(localRow), std::logic_error, ": Violated stated post-conditions. Please contact Tpetra team.");
01561 #endif
01562     return;
01563   }
01564 
01565 
01568   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
01569   void CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::getGlobalRowView(GlobalOrdinal globalRow, ArrayView<const GlobalOrdinal> &indices) const
01570   {
01571     std::string tfecfFuncName("getGlobalRowView()");
01572     TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(isLocallyIndexed() == true, std::runtime_error, ": global indices cannot be provided.");
01573     indices = null;
01574     if (rowMap_->isNodeGlobalElement(globalRow) == true) {
01575       const LocalOrdinal lrow = rowMap_->getLocalElement(globalRow);
01576       const RowInfo rowinfo = getRowInfo(lrow);
01577       if (rowinfo.numEntries > 0) {
01578         indices = getGlobalView(rowinfo);
01579         indices = indices(0,rowinfo.numEntries);
01580       }
01581     }
01582 #ifdef HAVE_TPETRA_DEBUG
01583     TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC( (size_t)indices.size() != getNumEntriesInGlobalRow(globalRow), std::logic_error, ": Violated stated post-conditions. Please contact Tpetra team.");
01584 #endif
01585     return;
01586   }
01587 
01588 
01591   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
01592   void CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::insertLocalIndices(
01593             LocalOrdinal localRow, const ArrayView<const LocalOrdinal> &indices)
01594   {
01595     std::string tfecfFuncName("insertLocalIndices()");
01596     TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC( isFillActive() == false,                        std::runtime_error, ": requires that fill is active.");
01597     TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC( isGloballyIndexed() == true,                    std::runtime_error, ": graph indices are global; use insertGlobalIndices().");
01598     TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC( hasColMap() == false,                           std::runtime_error, ": cannot insert local indices without a column map.");
01599     TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC( rowMap_->isNodeLocalElement(localRow) == false, std::runtime_error, ": row does not belong to this node.");
01600     if (indicesAreAllocated() == false) {
01601       allocateIndices(LocalIndices);
01602     }
01603     // use column map to filter the entries
01604     Array<LocalOrdinal> f_inds(indices);
01605     SLocalGlobalNCViews inds_ncview;
01606     inds_ncview.linds = f_inds();
01607     const size_t numFilteredEntries = filterIndices<LocalIndices>(inds_ncview);
01608     if (numFilteredEntries > 0) {
01609       RowInfo rowInfo = getRowInfo(localRow);
01610       const size_t curNumEntries = rowInfo.numEntries;
01611       const size_t newNumEntries = curNumEntries + numFilteredEntries;
01612       if (newNumEntries > rowInfo.allocSize) {
01613         TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(getProfileType() == StaticProfile, std::runtime_error, ": new indices exceed statically allocated graph structure.");
01614         TPETRA_EFFICIENCY_WARNING(true,std::runtime_error,
01615             "::insertLocalIndices(): Pre-allocated space has been exceeded, requiring new allocation. To improve efficiency, suggest larger allocation.");
01616         // update allocation only as much as necessary
01617         rowInfo = updateAlloc<LocalIndices>(rowInfo, newNumEntries);
01618       }
01619       SLocalGlobalViews inds_view;
01620       inds_view.linds = f_inds(0,numFilteredEntries);
01621       insertIndices<LocalIndices,LocalIndices>(rowInfo, inds_view);
01622     }
01623 #ifdef HAVE_TPETRA_DEBUG
01624     TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(indicesAreAllocated() == false || isLocallyIndexed() == false, std::logic_error,
01625         ": Violated stated post-conditions. Please contact Tpetra team.");
01626 #endif
01627   }
01628 
01629 
01632   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
01633   void CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::insertGlobalIndices(
01634             GlobalOrdinal grow, const ArrayView<const GlobalOrdinal> &indices)
01635   {
01636     std::string tfecfFuncName("insertGlobalIndices()");
01637     TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(isLocallyIndexed() == true, std::runtime_error, ": graph indices are local; use insertLocalIndices().");
01638     // this can't really be satisfied for now, because if we are fillComplete(), then we are local
01639     // in the future, this may change. however, the rule that modification require active fill will not change.
01640     TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC( isFillActive() == false, std::runtime_error, ": requires that fill is active.");
01641     if (indicesAreAllocated() == false) {
01642       allocateIndices(GlobalIndices);
01643     }
01644     const LocalOrdinal myRow = rowMap_->getLocalElement(grow);
01645     if (myRow != OrdinalTraits<LocalOrdinal>::invalid())
01646     {
01647       // if we have a column map, use it to filter the entries.
01648       Array<GlobalOrdinal> filtered_indices;
01649       SLocalGlobalViews inds_view;
01650       if (hasColMap()) {
01651         SLocalGlobalNCViews inds_ncview;
01652         // filter indices and values through the column map
01653         filtered_indices.assign(indices.begin(), indices.end());
01654         inds_ncview.ginds = filtered_indices();
01655         const size_t numFilteredEntries = filterIndices<GlobalIndices>(inds_ncview);
01656         inds_view.ginds = filtered_indices(0,numFilteredEntries);
01657       }
01658       else {
01659         inds_view.ginds = indices;
01660       }
01661       const size_t numFilteredEntries = inds_view.ginds.size();
01662       // add the new indices and values
01663       if (numFilteredEntries > 0) {
01664         RowInfo rowInfo = getRowInfo(myRow);
01665         const size_t curNumEntries = rowInfo.numEntries;
01666         const size_t newNumEntries = curNumEntries + numFilteredEntries;
01667         if (newNumEntries > rowInfo.allocSize) {
01668           TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(getProfileType() == StaticProfile, std::runtime_error, ": new indices exceed statically allocated graph structure.");
01669           TPETRA_EFFICIENCY_WARNING(true,std::runtime_error,
01670               "::insertGlobalValues(): Pre-allocated space has been exceeded, requiring new allocation. To improve efficiency, suggest larger allocation.");
01671           // update allocation only as much as necessary
01672           rowInfo = updateAlloc<GlobalIndices>(rowInfo, newNumEntries);
01673         }
01674         insertIndices<GlobalIndices,GlobalIndices>(rowInfo, inds_view);
01675 #ifdef HAVE_TPETRA_DEBUG
01676         {
01677           const size_t chkNewNumEntries = getNumEntriesInLocalRow(myRow);
01678           TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(chkNewNumEntries != newNumEntries, std::logic_error, ": Internal logic error. Please contact Tpetra team.");
01679         }
01680 #endif
01681       }
01682     }
01683     else {
01684       // a nonlocal row
01685       for (typename ArrayView<const GlobalOrdinal>::iterator i=indices.begin(); i != indices.end(); ++i) {
01686         nonlocals_[grow].push_back(*i);
01687       }
01688     }
01689 #ifdef HAVE_TPETRA_DEBUG
01690     TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(indicesAreAllocated() == false || isGloballyIndexed() == false, std::logic_error,
01691         ": Violated stated post-conditions. Please contact Tpetra team.");
01692 #endif
01693   }
01694 
01695 
01698   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
01699   void CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::removeLocalIndices(LocalOrdinal lrow)
01700   {
01701     std::string tfecfFuncName("removeLocalIndices()");
01702     TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC( isFillActive() == false,                    std::runtime_error, ": requires that fill is active.");
01703     TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC( isStorageOptimized() == true,               std::runtime_error, ": cannot remove indices after optimizeStorage() has been called.");
01704     TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC( isGloballyIndexed() == true,                std::runtime_error, ": graph indices are global; use removeGlobalIndices().");
01705     TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC( rowMap_->isNodeLocalElement(lrow) == false, std::runtime_error, ": row does not belong to this node.");
01706     if (indicesAreAllocated() == false) {
01707       allocateIndices(LocalIndices);
01708     }
01709     //
01710     clearGlobalConstants();
01711     //
01712     RowInfo sizeInfo = getRowInfo(lrow);
01713     if (sizeInfo.allocSize > 0 && numEntriesPerRow_ != null) {
01714       numEntriesPerRow_[lrow] = 0;
01715     }
01716 #ifdef HAVE_TPETRA_DEBUG
01717     TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(getNumEntriesInLocalRow(lrow) != 0 || indicesAreAllocated() == false || isLocallyIndexed() == false, std::logic_error,
01718         ": Violated stated post-conditions. Please contact Tpetra team.");
01719 #endif
01720   }
01721 
01722 
01723   // TODO: in the future, globalAssemble() should use import/export functionality
01726   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
01727   void CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::globalAssemble()
01728   {
01729     using Teuchos::as;
01730     using Teuchos::gatherAll;
01731     using Teuchos::ireceive;
01732     using Teuchos::isend;
01733     using Teuchos::outArg;
01734     using Teuchos::RCP;
01735     using Teuchos::REDUCE_MAX;
01736     using Teuchos::reduceAll;
01737     using Teuchos::waitAll;
01738     using std::deque;
01739     using std::pair;
01740     using std::make_pair;
01741     typedef GlobalOrdinal GO;
01742     typedef typename std::map<GO, std::deque<GO> >::const_iterator NLITER;
01743 
01744     std::string tfecfFuncName("globalAssemble()"); // for exception macro
01745     RCP<const Teuchos::Comm<int> > comm = getComm();
01746 
01747     const int numImages = comm->getSize();
01748     const int myImageID = comm->getRank();
01749 #ifdef HAVE_TPETRA_DEBUG
01750     Teuchos::barrier (*comm);
01751 #endif // HAVE_TPETRA_DEBUG
01752 
01753     TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC( ! isFillActive(), std::runtime_error,
01754       ": requires that fill is active.");
01755     // Determine if any nodes have global entries to share
01756     {
01757       size_t MyNonlocals = nonlocals_.size(), MaxGlobalNonlocals;
01758       reduceAll (*comm, REDUCE_MAX, MyNonlocals, outArg (MaxGlobalNonlocals));
01759       if (MaxGlobalNonlocals == 0) {
01760         return;  // no entries to share
01761       }
01762     }
01763 
01764     // compute a list of NLRs from nonlocals_ and use it to compute:
01765     //      IdsAndRows: a vector of (id,row) pairs
01766     //          NLR2Id: a map from NLR to the Id that owns it
01767     // globalNeighbors: a global graph of connectivity between images: globalNeighbors(i,j) indicates that j sends to i
01768     //         sendIDs: a list of all images I send to
01769     //         recvIDs: a list of all images I receive from (constructed later)
01770     Array<pair<int, GO> > IdsAndRows;
01771     std::map<GO, int> NLR2Id;
01772     Teuchos::SerialDenseMatrix<int, char> globalNeighbors;
01773     Array<int> sendIDs, recvIDs;
01774     {
01775       // nonlocals_ contains the entries we are holding for all non-local rows
01776       // we want a list of the rows for which we have data
01777       Array<GO> NLRs;
01778       std::set<GO> setOfRows;
01779       for (NLITER iter = nonlocals_.begin(); iter != nonlocals_.end(); ++iter) {
01780         setOfRows.insert(iter->first);
01781       }
01782       // copy the elements in the set into an Array
01783       NLRs.resize(setOfRows.size());
01784       std::copy(setOfRows.begin(), setOfRows.end(), NLRs.begin());
01785 
01786       // get a list of ImageIDs for the non-local rows (NLRs)
01787       Array<int> NLRIds(NLRs.size());
01788       {
01789         LookupStatus stat = rowMap_->getRemoteIndexList(NLRs(),NLRIds());
01790         char lclerror = ( stat == IDNotPresent ? 1 : 0 );
01791         char gblerror;
01792         reduceAll (*getComm(), REDUCE_MAX, lclerror, outArg (gblerror));
01793         TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(gblerror != 0, std::runtime_error,
01794           ": nonlocal entries correspond to invalid rows.");
01795       }
01796 
01797       // build up a list of neighbors, as well as a map between NLRs and Ids
01798       // localNeighbors[i] != 0 iff I have data to send to image i
01799       // put NLRs,Ids into an array of pairs
01800       IdsAndRows.reserve(NLRs.size());
01801       Array<char> localNeighbors(numImages, 0);
01802       typename Array<GO>::const_iterator nlr;
01803       typename Array<int>::const_iterator id;
01804       for (nlr = NLRs.begin(), id = NLRIds.begin();
01805            nlr != NLRs.end(); ++nlr, ++id) {
01806         NLR2Id[*nlr] = *id;
01807         localNeighbors[*id] = 1;
01808         // IdsAndRows.push_back(make_pair<int,GlobalOrdinal>(*id,*nlr));
01809         IdsAndRows.push_back(make_pair(*id,*nlr));
01810       }
01811       for (int j=0; j<numImages; ++j) {
01812         if (localNeighbors[j]) {
01813           sendIDs.push_back(j);
01814         }
01815       }
01816       // sort IdsAndRows, by Ids first, then rows
01817       std::sort(IdsAndRows.begin(),IdsAndRows.end());
01818       // gather from other nodes to form the full graph
01819       globalNeighbors.shapeUninitialized(numImages,numImages);
01820       gatherAll (*getComm(), numImages, localNeighbors.getRawPtr(),
01821                  numImages * numImages, globalNeighbors.values());
01822       // globalNeighbors at this point contains (on all images) the
01823       // connectivity between the images.
01824       // globalNeighbors(i,j) != 0 means that j sends to i/that i receives from j
01825     }
01826 
01828     // FIGURE OUT WHO IS SENDING TO WHOM AND HOW MUCH
01829     // DO THIS IN THE PROCESS OF PACKING ALL OUTGOING DATA ACCORDING TO DESTINATION ID
01831 
01832     // loop over all columns to know from which images I can expect to receive something
01833     for (int j=0; j<numImages; ++j) {
01834       if (globalNeighbors(myImageID,j)) {
01835         recvIDs.push_back(j);
01836       }
01837     }
01838     const size_t numRecvs = recvIDs.size();
01839 
01840     // we know how many we're sending to already
01841     // form a contiguous list of all data to be sent
01842     // track the number of entries for each ID
01843     Array<pair<GO, GO> > IJSendBuffer;
01844     Array<size_t> sendSizes(sendIDs.size(), 0);
01845     size_t numSends = 0;
01846     for (typename Array<pair<int, GO> >::const_iterator IdAndRow = IdsAndRows.begin();
01847          IdAndRow != IdsAndRows.end(); ++IdAndRow) {
01848       int id = IdAndRow->first;
01849       GO row = IdAndRow->second;
01850       // have we advanced to a new send?
01851       if (sendIDs[numSends] != id) {
01852         numSends++;
01853         TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(sendIDs[numSends] != id,
01854           std::logic_error, ": internal logic error. Contact Tpetra team.");
01855       }
01856       // copy data for row into contiguous storage
01857       for (typename deque<GO>::const_iterator j = nonlocals_[row].begin(); j != nonlocals_[row].end(); ++j)
01858       {
01859         IJSendBuffer.push_back( pair<GlobalOrdinal,GlobalOrdinal>(row,*j) );
01860         sendSizes[numSends]++;
01861       }
01862     }
01863     if (IdsAndRows.size() > 0) {
01864       numSends++; // one last increment, to make it a count instead of an index
01865     }
01866     TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(as<typename Array<int>::size_type>(numSends) != sendIDs.size(), std::logic_error, ": internal logic error. Contact Tpetra team.");
01867 
01868     // don't need this data anymore
01869     nonlocals_.clear();
01870 
01872     // TRANSMIT SIZE INFO BETWEEN SENDERS AND RECEIVERS
01874 
01875     // Array of pending nonblocking communication requests.  It's OK
01876     // to mix nonblocking send and receive requests in the same
01877     // waitAll() call.
01878     Array<RCP<Teuchos::CommRequest> > requests;
01879 
01880     // perform non-blocking sends: send sizes to our recipients
01881     for (size_t s = 0; s < numSends ; ++s) {
01882       // We're using a nonowning RCP because all communication
01883       // will be local to this method and the scope of our data
01884       requests.push_back (isend<int, size_t> (*comm,
01885                                               rcp (&sendSizes[s], false),
01886                                               sendIDs[s]));
01887     }
01888     // perform non-blocking receives: receive sizes from our senders
01889     Array<size_t> recvSizes (numRecvs);
01890     for (size_t r = 0; r < numRecvs; ++r) {
01891       // We're using a nonowning RCP because all communication
01892       // will be local to this method and the scope of our data
01893       requests.push_back (ireceive (*comm, rcp (&recvSizes[r], false), recvIDs[r]));
01894     }
01895     // Wait on all the nonblocking sends and receives.
01896     if (! requests.empty()) {
01897       waitAll (*comm, requests());
01898     }
01899 #ifdef HAVE_TPETRA_DEBUG
01900     Teuchos::barrier (*comm);
01901 #endif // HAVE_TPETRA_DEBUG
01902 
01903     // This doesn't necessarily deallocate the array.
01904     requests.resize (0);
01905 
01907     // NOW SEND/RECEIVE ALL ROW DATA
01909     // from the size info, build the ArrayViews into IJSendBuffer
01910     Array<ArrayView<pair<GO,GO> > > sendBuffers(numSends,null);
01911     {
01912       size_t cur = 0;
01913       for (size_t s=0; s<numSends; ++s) {
01914         sendBuffers[s] = IJSendBuffer(cur,sendSizes[s]);
01915         cur += sendSizes[s];
01916       }
01917     }
01918     // perform non-blocking sends
01919     for (size_t s=0; s < numSends ; ++s)
01920     {
01921       // We're using a nonowning RCP because all communication
01922       // will be local to this method and the scope of our data
01923       ArrayRCP<pair<GO,GO> > tmpSendBuf =
01924         arcp (sendBuffers[s].getRawPtr(), 0, sendBuffers[s].size(), false);
01925       requests.push_back (isend<int, pair<GO,GO> > (*comm, tmpSendBuf, sendIDs[s]));
01926     }
01927     // calculate amount of storage needed for receives
01928     // setup pointers for the receives as well
01929     size_t totalRecvSize = std::accumulate (recvSizes.begin(), recvSizes.end(), 0);
01930     Array<pair<GO,GO> > IJRecvBuffer (totalRecvSize);
01931     // from the size info, build the ArrayViews into IJRecvBuffer
01932     Array<ArrayView<pair<GO,GO> > > recvBuffers (numRecvs, null);
01933     {
01934       size_t cur = 0;
01935       for (size_t r=0; r<numRecvs; ++r) {
01936         recvBuffers[r] = IJRecvBuffer(cur,recvSizes[r]);
01937         cur += recvSizes[r];
01938       }
01939     }
01940     // perform non-blocking recvs
01941     for (size_t r = 0; r < numRecvs; ++r) {
01942       // We're using a nonowning RCP because all communication
01943       // will be local to this method and the scope of our data
01944       ArrayRCP<pair<GO,GO> > tmpRecvBuf =
01945         arcp (recvBuffers[r].getRawPtr(), 0, recvBuffers[r].size(), false);
01946       requests.push_back (ireceive (*comm, tmpRecvBuf, recvIDs[r]));
01947     }
01948     // perform waits
01949     if (! requests.empty()) {
01950       waitAll (*comm, requests());
01951     }
01952 #ifdef HAVE_TPETRA_DEBUG
01953     Teuchos::barrier (*comm);
01954 #endif // HAVE_TPETRA_DEBUG
01955 
01957     // NOW PROCESS THE RECEIVED ROW DATA
01959     // TODO: instead of adding one entry at a time, add one row at a time.
01960     //       this requires resorting; they arrived sorted by sending node, so that entries could be non-contiguous if we received
01961     //       multiple entries for a particular row from different processors.
01962     //       it also requires restoring the data, which may make it not worth the trouble.
01963     for (typename Array<pair<GO,GO> >::const_iterator ij = IJRecvBuffer.begin();
01964          ij != IJRecvBuffer.end(); ++ij)
01965     {
01966       insertGlobalIndices(ij->first, tuple<GO> (ij->second));
01967     }
01968     checkInternalState();
01969   }
01970 
01971 
01974   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
01975   void CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::resumeFill()
01976   {
01977 #ifdef HAVE_TPETRA_DEBUG
01978     Teuchos::barrier( *rowMap_->getComm() );
01979 #endif
01980     clearGlobalConstants();
01981     lclGraph_.clear();
01982     setSorted(true);
01983     lowerTriangular_  = false;
01984     upperTriangular_  = false;
01985     noRedundancies_   = false;
01986     fillComplete_ = false;
01987 #ifdef HAVE_TPETRA_DEBUG
01988     std::string tfecfFuncName("resumeFill()");
01989     TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC( isFillActive() == false || isFillComplete() == true, std::logic_error, ": Violated stated post-conditions. Please contact Tpetra team.");
01990 #endif
01991   }
01992 
01993 
01996   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
01997   void CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::fillComplete(OptimizeOption os)
01998   {
01999     fillComplete(rowMap_,rowMap_,os);
02000   }
02001 
02002 
02005   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
02006   void CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::fillComplete(
02007                                     const RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > &domainMap,
02008                                     const RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > &rangeMap,
02009                                     OptimizeOption os)
02010   {
02011 #ifdef HAVE_TPETRA_DEBUG
02012     Teuchos::barrier( *rowMap_->getComm() );
02013 #endif // HAVE_TPETRA_DEBUG
02014     std::string tfecfFuncName("fillComplete()");
02015     TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC( ! isFillActive() || isFillComplete(),
02016       std::runtime_error, ": Graph fill state must be active (isFillActive() "
02017       "must be true) before calling fillComplete().");
02018 
02019     // allocate if unallocated
02020     if (! indicesAreAllocated()) {
02021       // allocate global, in case we do not have a column map
02022       allocateIndices( GlobalIndices );
02023     }
02024     // Global assemble, if we need to (we certainly don't need to if
02025     // there's only one process).  This call only costs a single
02026     // all-reduce if we don't need global assembly.
02027     if (getComm()->getSize() > 1) {
02028       globalAssemble();
02029     }
02030     else {
02031       TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(nonlocals_.size() > 0, std::runtime_error, ": cannot have non-local entries on a serial run. Invalid entries were submitted to the CrsMatrix.");
02032     }
02033     // set domain/range map: may clear the import/export objects
02034     setDomainRangeMaps(domainMap,rangeMap);
02035     // make column map
02036     if (! hasColMap()) {
02037       makeColMap();
02038     }
02039     if (isGloballyIndexed()) {
02040       makeIndicesLocal();
02041     }
02042     if (! isSorted()) {
02043       sortAllIndices();
02044     }
02045     if (! isMerged()) {
02046       mergeAllIndices();
02047     }
02048     makeImportExport(); // Make Import and Export objects
02049     computeGlobalConstants();
02050     // fill local objects
02051     fillLocalGraph(os);
02052     //
02053     fillComplete_ = true;
02054 #ifdef HAVE_TPETRA_DEBUG
02055     TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC( isFillActive() == true || isFillComplete() == false, std::logic_error, ": Violated stated post-conditions. Please contact Tpetra team.");
02056 #endif
02057     //
02058     checkInternalState();
02059   }
02060 
02061 
02064   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
02065   void CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::pushToLocalGraph()
02066   {
02067     TEUCHOS_TEST_FOR_EXCEPTION(lclGraph_.isFinalized (), std::logic_error,
02068       Teuchos::typeName (*this) << "::pushToLocalGraph(): This method should "
02069       "never be called if the local graph (lclGraph_) is finalized.  "
02070       "Please report this bug to the Tpetra developers.");
02071 
02072     if (getProfileType() == StaticProfile) {
02073       // mfh 03 May 2012: This mainly just copies pointers; it doesn't
02074       // copy data from host to device.
02075       lclGraph_.set1DStructure (lclInds1D_, rowBegs_, rowEnds_);
02076       // This relinquishes ownership of the pointers.  Now lclGraph_
02077       // owns the pointers.
02078       lclInds1D_ = null;
02079       rowBegs_   = null;
02080       rowEnds_   = null;
02081     }
02082     else {
02083       // mfh 03 May 2012: This mainly just copies pointers; it doesn't
02084       // copy data from host to device.
02085       lclGraph_.set2DStructure(lclInds2D_,numEntriesPerRow_);
02086       // This relinquishes ownership of the pointers.  Now lclGraph_
02087       // owns the pointers.
02088       lclInds2D_ = null;
02089       numEntriesPerRow_ = null;
02090     }
02091     nodeNumAllocated_ = 0;
02092     nodeNumEntries_   = 0;
02093   }
02094 
02095 
02098   template<class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
02099   void
02100   CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::
02101   pullFromLocalGraph ()
02102   {
02103     TEUCHOS_TEST_FOR_EXCEPTION(! lclGraph_.isFinalized (), std::logic_error,
02104       Teuchos::typeName (*this) << "::pullFromLocalGraph(): This method should "
02105       "never be called if the local graph (lclGraph_) is not yet finalized.  "
02106       "Please report this bug to the Tpetra developers.");
02107 
02108     // get new data from local graph
02109     // this requires updating the allocation size, but not necessarily the
02110     if (lclGraph_.is1DStructure()) {
02111       // mfh 03 May 2012: This also just copies the pointers; it
02112       // doesn't copy their contents or transfer data from device to
02113       // host.
02114       //
02115       // FIXME (mfh 03 May 2012) Why does the Tpetra::CrsMatrix need
02116       // to keep these pointers around, if the Kokkos::CrsGraph owns
02117       // them?
02118       lclGraph_.get1DStructure (lclInds1D_, rowBegs_, rowEnds_);
02119       pftype_ = StaticProfile;
02120 #ifdef HAVE_TPETRA_DEBUG
02121       TEUCHOS_TEST_FOR_EXCEPT( rowBegs_ == null );
02122 #endif
02123       nodeNumAllocated_ = rowBegs_[getNodeNumRows()];
02124       if (nodeNumAllocated_ > 0) {
02125         lclInds1D_ = lclInds1D_.persistingView(0,nodeNumAllocated_);
02126       }
02127       nodeNumEntries_ = 0;
02128       for (size_t r=0; r < getNodeNumRows(); ++r) {
02129         nodeNumEntries_ += rowEnds_[r] - rowBegs_[r];
02130       }
02131     }
02132     else {
02133       // mfh 03 May 2012: This also just copies the pointers; it
02134       // doesn't copy their contents or transfer data from device to
02135       // host.
02136       //
02137       // FIXME (mfh 03 May 2012) Why does the Tpetra::CrsMatrix need
02138       // to keep these pointers around, if the Kokkos::CrsGraph owns
02139       // them?
02140       lclGraph_.get2DStructure (lclInds2D_, numEntriesPerRow_);
02141       pftype_ = DynamicProfile;
02142       nodeNumAllocated_ = 0;
02143       nodeNumEntries_   = 0;
02144       for (size_t r=0; r < getNodeNumRows(); ++r) {
02145         nodeNumAllocated_ += lclInds2D_[r].size();
02146         nodeNumEntries_   += numEntriesPerRow_[r];
02147       }
02148     }
02149   }
02150 
02151 
02154   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
02155   void CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::fillLocalGraph(OptimizeOption os)
02156   {
02157     pushToLocalGraph();
02158     // finalize local graph(with os)
02159     const bool optStorage = (os == DoOptimizeStorage);
02160     lclGraph_.finalize( optStorage );
02161     // get the data back from the local objects
02162     pullFromLocalGraph();
02163   }
02164 
02165 
02168   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
02169   const Kokkos::CrsGraph<LocalOrdinal,Node,LocalMatOps> &
02170   CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::getLocalGraph() const
02171   {
02172     return lclGraph_;
02173   }
02174 
02175 
02178   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
02179   Kokkos::CrsGraph<LocalOrdinal,Node,LocalMatOps> &
02180   CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::getLocalGraphNonConst()
02181   {
02182     return lclGraph_;
02183   }
02184 
02185 
02188   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
02189   void CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::computeGlobalConstants()
02190   {
02191     // compute the local constants first
02192     const size_t nlrs = getNodeNumRows();
02193     // reset all local properties
02194     upperTriangular_ = true;
02195     lowerTriangular_ = true;
02196     nodeMaxNumRowEntries_ = 0;
02197     nodeNumDiags_         = 0;
02198     // indices are already sorted in each row
02199     const Map<LocalOrdinal,GlobalOrdinal,Node> &rowMap = *rowMap_;
02200     if (indicesAreAllocated() == true && nodeNumAllocated_ > 0) {
02201       for (size_t r=0; r < nlrs; ++r) {
02202         GlobalOrdinal rgid = rowMap.getGlobalElement(r);
02203         // determine the local column index for this row, used for delimiting the diagonal
02204         const LocalOrdinal rlcid = colMap_->getLocalElement(rgid);
02205         RowInfo rowinfo = getRowInfo(r);
02206         ArrayView<const LocalOrdinal> rview = getLocalView(rowinfo);
02207         typename ArrayRCP<const LocalOrdinal>::iterator beg, end, cur;
02208         beg = rview.begin();
02209         end = beg + rowinfo.numEntries;
02210         if (beg != end) {
02211           for (cur = beg; cur != end; ++cur) {
02212             // is this the diagonal?
02213             if (rlcid == (*cur)) ++nodeNumDiags_;
02214           }
02215           // because of sorting, smallest column index is (*beg); it indicates upper triangularity
02216           if (Teuchos::as<size_t>(beg[0]) < r) upperTriangular_ = false;
02217           // because of sorting, largest column index is (*newend); it indicates lower triangularity
02218           if (r < Teuchos::as<size_t>(end[-1])) lowerTriangular_ = false;
02219         }
02220         // compute num entries for this row, accumulate into nodeNumEntries_, update nodeMaxNumRowEntries_
02221         nodeMaxNumRowEntries_ = std::max( nodeMaxNumRowEntries_, rowinfo.numEntries );
02222       }
02223     }
02224 
02225     // compute global constants using computed local constants
02226     if (haveGlobalConstants_ == false) {
02227       global_size_t lcl[2], gbl[2];
02228       lcl[0] = nodeNumEntries_;
02229       lcl[1] = nodeNumDiags_;
02230       Teuchos::reduceAll<int,global_size_t>(*getComm(),Teuchos::REDUCE_SUM,2,lcl,gbl);
02231       globalNumEntries_ = gbl[0];
02232       globalNumDiags_   = gbl[1];
02233       Teuchos::reduceAll<int,global_size_t>(*getComm(),Teuchos::REDUCE_MAX,nodeMaxNumRowEntries_,
02234           outArg(globalMaxNumRowEntries_));
02235       haveGlobalConstants_ = true;
02236     }
02237   }
02238 
02239 
02242   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
02243   void CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::makeIndicesLocal()
02244   {
02245     // All nodes must be in the same index state.
02246     // Update index state by checking isLocallyIndexed/Global on all nodes
02247     computeIndexState();
02248     std::string tfecfFuncName("makeIndicesLocal()");
02249     TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(isLocallyIndexed() && isGloballyIndexed(), std::logic_error,
02250         ": inconsistent index state. Indices must be local on all nodes or global on all nodes.");
02251     // If user has not prescribed column map, create one from indices
02252     makeColMap();
02253     // Transform indices to local index space
02254     const size_t nlrs = getNodeNumRows();
02255     //
02256     if (isGloballyIndexed() && nlrs > 0) {
02257       // allocate data for local indices
02258       if (getProfileType() == StaticProfile) {
02259         // reinterpret the the compute buffer as LocalOrdinal
02260         if (nodeNumAllocated_) {
02261           lclInds1D_ = arcp_reinterpret_cast<LocalOrdinal>(gblInds1D_).persistingView(0,nodeNumAllocated_);
02262         }
02263         for (size_t r=0; r < getNodeNumRows(); ++r) {
02264           const size_t offset   = rowBegs_[r],
02265                        numentry = rowEnds_[r] - rowBegs_[r];
02266           for (size_t j=0; j<numentry; ++j) {
02267             GlobalOrdinal gid = gblInds1D_[offset + j];
02268             LocalOrdinal  lid = colMap_->getLocalElement(gid);
02269             lclInds1D_[offset + j] = lid;
02270 #ifdef HAVE_TPETRA_DEBUG
02271             TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(lclInds1D_[offset + j] == OrdinalTraits<LocalOrdinal>::invalid(), std::logic_error,
02272                 ": Internal error in fillComplete(). Please contact Tpetra team.");
02273 #endif
02274           }
02275         }
02276         // done with this pointer (allocation will persist in lclInds1D_)
02277         gblInds1D_ = null;
02278       }
02279       else {  // getProfileType() == DynamicProfile
02280         lclInds2D_ = arcp< ArrayRCP<LocalOrdinal> >(nlrs);
02281         // if we have views, then make views
02282         for (size_t r=0; r < getNodeNumRows(); ++r) {
02283           if (gblInds2D_[r] != null) {
02284             ArrayRCP<GlobalOrdinal> ginds = gblInds2D_[r];
02285             const size_t rna = gblInds2D_[r].size();
02286             ArrayRCP< LocalOrdinal> linds = arcp_reinterpret_cast<LocalOrdinal>(ginds).persistingView(0,rna);
02287             // do the conversion in situ. this must be done from front to back.
02288             const size_t numentry = numEntriesPerRow_[r];
02289             for (size_t j=0; j < numentry; ++j) {
02290               GlobalOrdinal gid = ginds[j];
02291               LocalOrdinal  lid = colMap_->getLocalElement(gid);
02292               linds[j] = lid;
02293 #ifdef HAVE_TPETRA_DEBUG
02294               TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(linds[j] == OrdinalTraits<LocalOrdinal>::invalid(), std::logic_error,
02295                   ": Internal error in makeIndicesLocal(). Please contact Tpetra team.");
02296 #endif
02297             }
02298             // reinterpret the the compute buffer as LocalOrdinal; keep the original size
02299             lclInds2D_[r] = linds;
02300             gblInds2D_[r] = null;
02301           }
02302         }
02303         gblInds2D_ = null;
02304       }
02305     }
02306     indicesAreLocal_  = true;
02307     indicesAreGlobal_ = false;
02308     checkInternalState();
02309   }
02310 
02311 
02314   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
02315   void CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::computeIndexState()
02316   {
02317     char myIndices[2] = {0,0};
02318     if (indicesAreLocal_)  myIndices[0] = 1;
02319     if (indicesAreGlobal_) myIndices[1] = 1;
02320     char allIndices[2];
02321     Teuchos::reduceAll(*getComm(),Teuchos::REDUCE_MAX,2,myIndices,allIndices);
02322     indicesAreLocal_  = (allIndices[0]==1);  // If indices are local on one PE, should be local on all
02323     indicesAreGlobal_ = (allIndices[1]==1);  // If indices are global on one PE should be local on all
02324   }
02325 
02326 
02327 
02330   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
02331   void CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::sortAllIndices()
02332   {
02333     TEUCHOS_TEST_FOR_EXCEPT(isGloballyIndexed()==true);   // this should be called only after makeIndicesLocal()
02334     if (isSorted() == false) {
02335       for (size_t row=0; row < getNodeNumRows(); ++row) {
02336         RowInfo rowInfo = getRowInfo(row);
02337         sortRowIndices(rowInfo);
02338       }
02339     }
02340     // we just sorted every row
02341     setSorted(true);
02342   }
02343 
02344 
02347   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
02348   void CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::makeColMap()
02349   {
02350     std::string tfecfFuncName("makeColMap()");
02351     typedef OrdinalTraits<GlobalOrdinal> GOT;
02352     //
02353     if (hasColMap()) return;
02354     const size_t nlrs = getNodeNumRows();
02355     //
02356     computeIndexState();
02357     TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(isLocallyIndexed() == true, std::runtime_error, ": indices must still be global when making the column map.");
02358     // ultimate goal: list of indices for column map
02359     Array<GlobalOrdinal> myColumns;
02360     // if isGloballyIndexed() == false and isLocallyIndexed() == false, then we have nothing to do
02361     if (isGloballyIndexed() == true) {
02362       // Construct two lists of columns for which we have a non-zero
02363       // Local GIDs: Column GIDs which are locally present on the Domain map
02364       // Remote GIDs: Column GIDs which are not locally present present on the Domain map
02365       //
02366       // instead of list of local GIDs, we will use a set<LocalOrdinal> LocalGID.
02367       //
02368       const LocalOrdinal LINV = OrdinalTraits<LocalOrdinal>::invalid();
02369       size_t numLocalColGIDs = 0, numRemoteColGIDs = 0;
02370       //
02371       // initial: partitioning into local and remote
02372       Array<char> GIDisLocal(domainMap_->getNodeNumElements(),0);
02373       std::set<GlobalOrdinal> RemoteGIDSet;
02374       for (size_t r=0; r < nlrs; ++r) {
02375         RowInfo rowinfo = getRowInfo(r);
02376         if (rowinfo.numEntries > 0) {
02377           ArrayView<const GlobalOrdinal> rowgids = getGlobalView(rowinfo);
02378           rowgids = rowgids(0,rowinfo.numEntries);
02379           for (typename ArrayView<const GlobalOrdinal>::iterator cind = rowgids.begin(); cind != rowgids.end(); ++cind)
02380           {
02381             GlobalOrdinal gid = (*cind);
02382             LocalOrdinal lid = domainMap_->getLocalElement(gid);
02383             if (lid != LINV) {
02384               char alreadyFound = GIDisLocal[lid];
02385               if (alreadyFound == 0) {
02386                 GIDisLocal[lid] = 1;
02387                 ++numLocalColGIDs;
02388               }
02389             }
02390             else {
02391               std::pair<typename std::set<GlobalOrdinal>::iterator, bool> ip;
02392               ip = RemoteGIDSet.insert(gid);
02393               if (ip.second == true) { // gid did not exist in the set and was actually inserted
02394                 ++numRemoteColGIDs;
02395               }
02396             }
02397           }
02398         }
02399       }
02400 
02401       // Possible short-circuit for serial scenario
02402       // If the all domain GIDs are present as column indices, then set ColMap=DomainMap
02403       // By construction, LocalGIDs \subset DomainGIDs
02404       // If we have
02405       //   * Number of remote GIDs is 0, so that ColGIDs == LocalGIDs,
02406       // and
02407       //   * Number of local GIDs is number of domain GIDs
02408       // then
02409       //   * LocalGIDs \subset DomainGIDs && size(LocalGIDs) == size(DomainGIDs) => DomainGIDs == LocalGIDs == ColGIDs
02410       // on this node.
02411       // We will concern ourselves only with the special case of a serial DomainMap, obviating the need for a communication.
02412       // If
02413       //   * DomainMap has a serial comm
02414       // then we can set Column map as Domain map and return. Benefit: this graph won't need an Import object later.
02415       //
02416       // Note, for a serial domain map, there can be no RemoteGIDs, because there are no remote nodes.
02417       // Likely explanations for this are:
02418       //  * user submitted erroneous column indices
02419       //  * user submitted erroneous domain map
02420       if (Teuchos::size(*domainMap_->getComm()) == 1)
02421       {
02422         TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(numRemoteColGIDs != 0, std::runtime_error,
02423             ": Some column IDs are not in the domain map." << std::endl
02424             << "Either these column IDs are invalid or the domain map is invalid." << std::endl
02425             << "Remember, for a rectangular matrix, the domain map must be passed to fillComplete().");
02426         if (numLocalColGIDs == domainMap_->getNodeNumElements()) {
02427           colMap_ = domainMap_;
02428           checkInternalState();
02429           return;
02430         }
02431       }
02432 
02433       // Now, populate myColumns() with a list of all column GIDs.
02434       // Put local GIDs at the front: they correspond to "same" and "permuted" entries between the column map and the domain map
02435       // Put remote GIDs at the back
02436       myColumns.resize(numLocalColGIDs + numRemoteColGIDs);
02437       // get pointers into myColumns for each part
02438       ArrayView<GlobalOrdinal> LocalColGIDs, RemoteColGIDs;
02439       LocalColGIDs  = myColumns(0,numLocalColGIDs);
02440       RemoteColGIDs = myColumns(numLocalColGIDs,numRemoteColGIDs);
02441 
02442       // Copy the Remote GIDs into myColumns
02443       std::copy(RemoteGIDSet.begin(), RemoteGIDSet.end(), RemoteColGIDs.begin());
02444       // We will make a list of corresponding node IDs
02445       Array<int> RemoteImageIDs(numRemoteColGIDs);
02446       // Lookup the Remote Nodes IDs in the Domain map
02447       {
02448         LookupStatus stat = domainMap_->getRemoteIndexList(RemoteColGIDs, RemoteImageIDs());
02449         // This error check is crucial: this tells us that one of the remote indices was not present in the domain map.
02450         // This means that the Import object cannot be constructed, because of incongruity between the column map and domain map.
02451         //   * The user has made a mistake in the column indices
02452         //   * The user has made a mistake w.r.t. the domain map
02453         // Same error message as above for serial case.
02454         char missingID_lcl = (stat == IDNotPresent ? 1 : 0);
02455         char missingID_gbl;
02456         Teuchos::reduceAll<int,char>(*getComm(),Teuchos::REDUCE_MAX,missingID_lcl,
02457           outArg(missingID_gbl));
02458         TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(missingID_gbl == 1, std::runtime_error,
02459             ": Some column IDs are not in the domain map." << std::endl
02460             << "Either these column IDs are invalid or the domain map is invalid." << std::endl
02461             << "Common cause: for a rectangular matrix, the domain map must be passed to fillComplete().");
02462       }
02463       // Sort External column indices so that all columns coming from a given remote processor are contiguous
02464       // This obviates the need for the Distributor associated with the Import from having to reorder data.
02465       sort2(RemoteImageIDs.begin(), RemoteImageIDs.end(), RemoteColGIDs.begin());
02466 
02467       // Copy the Local GIDs into myColumns. Two cases:
02468       // (1) If the number of Local column GIDs is the same as the number of Local domain GIDs, we
02469       //     can simply read the domain GIDs into the front part of ColIndices (see logic above from the serial short circuit case)
02470       // (2) We step through the GIDs of the DomainMap, checking to see if each domain GID is a column GID.
02471       //     we want to do this to maintain a consistent ordering of GIDs between the columns and the domain.
02472       ArrayView<const GlobalOrdinal> mge = domainMap_->getNodeElementList();
02473       if (numLocalColGIDs == domainMap_->getNodeNumElements()) {
02474         std::copy(mge.begin(), mge.end(), LocalColGIDs.begin());
02475       }
02476       else {
02477         size_t numlocalagain = 0;
02478         for (size_t i=0; i < domainMap_->getNodeNumElements(); ++i) {
02479           if (GIDisLocal[i]) {
02480             LocalColGIDs[numlocalagain++] = mge[i];
02481           }
02482         }
02483         TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(numlocalagain != numLocalColGIDs, std::logic_error, ": Internal logic error. Please contact Tpetra team.");
02484       }
02485     }
02486     colMap_ = rcp(new Map<LocalOrdinal,GlobalOrdinal,Node>(GOT::invalid(), myColumns, domainMap_->getIndexBase(), domainMap_->getComm(), domainMap_->getNode()) );
02487     checkInternalState();
02488     return;
02489   }
02490 
02491 
02492   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
02493   void CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::mergeAllIndices()
02494   {
02495     TEUCHOS_TEST_FOR_EXCEPT( isGloballyIndexed() ); // call only after makeIndicesLocal()
02496     TEUCHOS_TEST_FOR_EXCEPT( ! isSorted() ); // call only after sortIndices()
02497     if (! isMerged ()) {
02498       for (size_t row=0; row < getNodeNumRows(); ++row) {
02499         RowInfo rowInfo = getRowInfo(row);
02500         mergeRowIndices(rowInfo);
02501       }
02502       // we just merged every row
02503       setMerged(true);
02504     }
02505   }
02506 
02507 
02508   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
02509   void
02510   CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::makeImportExport()
02511   {
02512     using Teuchos::ParameterList;
02513     using Teuchos::RCP;
02514     using Teuchos::rcp;
02515     using Teuchos::sublist;
02516     typedef Import<LocalOrdinal,GlobalOrdinal,Node> import_type;
02517     typedef Export<LocalOrdinal,GlobalOrdinal,Node> export_type;
02518 
02519     TEUCHOS_TEST_FOR_EXCEPTION(! hasColMap (), std::logic_error, "Tpetra::"
02520       "CrsGraph: It's not allowed to call makeImportExport() unless the graph "
02521       "has a column Map.");
02522     RCP<ParameterList> plist = this->getNonconstParameterList (); // could be null
02523 
02524     // Create the Import instance if necessary.
02525     if (domainMap_ != colMap_ && (! domainMap_->isSameAs (*colMap_))) {
02526       if (plist.is_null () || ! plist->isSublist ("Import")) {
02527         importer_ = rcp (new import_type (domainMap_, colMap_));
02528       }
02529       else {
02530         RCP<ParameterList> importSublist = sublist (plist, "Import", true);
02531         importer_ = rcp (new import_type (domainMap_, colMap_, importSublist));
02532       }
02533     }
02534     else {
02535       importer_ = null;
02536     }
02537 
02538     // Create the Export instance if necessary.
02539     if (rangeMap_ != rowMap_ && (!rangeMap_->isSameAs(*rowMap_))) {
02540       if (plist.is_null () || ! plist->isSublist ("Export")) {
02541         exporter_ = rcp (new export_type (rowMap_, rangeMap_));
02542       }
02543       else {
02544         RCP<ParameterList> exportSublist = sublist (plist, "Export", true);
02545         exporter_ = rcp (new export_type (rowMap_, rangeMap_, exportSublist));
02546       }
02547     }
02548     else {
02549       exporter_ = null;
02550     }
02551   }
02552 
02553 
02554   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
02555   std::string
02556   CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::description() const
02557   {
02558     std::ostringstream oss;
02559     oss << DistObject<GlobalOrdinal,LocalOrdinal,GlobalOrdinal,Node>::description();
02560     if (isFillComplete()) {
02561       oss << "{status = fill complete"
02562           << ", global rows = " << getGlobalNumRows()
02563           << ", global cols = " << getGlobalNumCols()
02564           << ", global num entries = " << getGlobalNumEntries()
02565           << "}";
02566     }
02567     else {
02568       oss << "{status = fill not complete"
02569           << ", global rows = " << getGlobalNumRows()
02570           << "}";
02571     }
02572     return oss.str();
02573   }
02574 
02575 
02576   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
02577   void
02578   CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::
02579   describe (Teuchos::FancyOStream &out,
02580             const Teuchos::EVerbosityLevel verbLevel) const
02581   {
02582     using std::endl;
02583     using std::setw;
02584     using Teuchos::VERB_DEFAULT;
02585     using Teuchos::VERB_NONE;
02586     using Teuchos::VERB_LOW;
02587     using Teuchos::VERB_MEDIUM;
02588     using Teuchos::VERB_HIGH;
02589     using Teuchos::VERB_EXTREME;
02590     Teuchos::EVerbosityLevel vl = verbLevel;
02591     if (vl == VERB_DEFAULT) vl = VERB_LOW;
02592     RCP<const Comm<int> > comm = this->getComm();
02593     const int myImageID = comm->getRank(),
02594               numImages = comm->getSize();
02595     size_t width = 1;
02596     for (size_t dec=10; dec<getGlobalNumRows(); dec *= 10) {
02597       ++width;
02598     }
02599     width = std::max<size_t>(width,Teuchos::as<size_t>(11)) + 2;
02600     Teuchos::OSTab tab(out);
02601     //    none: print nothing
02602     //     low: print O(1) info from node 0
02603     //  medium: print O(P) info, num entries per node
02604     //    high: print O(N) info, num entries per row
02605     // extreme: print O(NNZ) info: print graph indices
02606     //
02607     // for medium and higher, print constituent objects at specified verbLevel
02608     if (vl != VERB_NONE) {
02609       if (myImageID == 0) out << this->description() << std::endl;
02610       // O(1) globals, minus what was already printed by description()
02611       if (isFillComplete() && myImageID == 0) {
02612         out << "Global number of diagonals = " << globalNumDiags_ << std::endl;
02613         out << "Global max number of entries = " << globalMaxNumRowEntries_ << std::endl;
02614       }
02615       // constituent objects
02616       if (vl == VERB_MEDIUM || vl == VERB_HIGH || vl == VERB_EXTREME) {
02617         if (myImageID == 0) out << "\nRow map: " << std::endl;
02618         rowMap_->describe(out,vl);
02619         if (colMap_ != null) {
02620           if (myImageID == 0) out << "\nColumn map: " << std::endl;
02621           colMap_->describe(out,vl);
02622         }
02623         if (domainMap_ != null) {
02624           if (myImageID == 0) out << "\nDomain map: " << std::endl;
02625           domainMap_->describe(out,vl);
02626         }
02627         if (rangeMap_ != null) {
02628           if (myImageID == 0) out << "\nRange map: " << std::endl;
02629           rangeMap_->describe(out,vl);
02630         }
02631       }
02632       // O(P) data
02633       if (vl == VERB_MEDIUM || vl == VERB_HIGH || vl == VERB_EXTREME) {
02634         for (int imageCtr = 0; imageCtr < numImages; ++imageCtr) {
02635           if (myImageID == imageCtr) {
02636             out << "Node ID = " << imageCtr << std::endl
02637                 << "Node number of entries = " << nodeNumEntries_ << std::endl
02638                 << "Node number of diagonals = " << nodeNumDiags_ << std::endl
02639                 << "Node max number of entries = " << nodeMaxNumRowEntries_ << std::endl;
02640             if (indicesAreAllocated()) {
02641               out << "Node number of allocated entries = " << nodeNumAllocated_ << std::endl;
02642             }
02643             else {
02644               out << "Indices are not allocated." << std::endl;
02645             }
02646           }
02647           comm->barrier();
02648           comm->barrier();
02649           comm->barrier();
02650         }
02651       }
02652       // O(N) and O(NNZ) data
02653       if (vl == VERB_HIGH || vl == VERB_EXTREME) {
02654         for (int imageCtr = 0; imageCtr < numImages; ++imageCtr) {
02655           if (myImageID == imageCtr) {
02656             out << std::setw(width) << "Node ID"
02657                 << std::setw(width) << "Global Row"
02658                 << std::setw(width) << "Num Entries";
02659             if (vl == VERB_EXTREME) {
02660               out << "Entries";
02661             }
02662             out << std::endl;
02663             for (size_t r=0; r < getNodeNumRows(); ++r) {
02664               RowInfo rowinfo = getRowInfo(r);
02665               GlobalOrdinal gid = rowMap_->getGlobalElement(r);
02666               out << std::setw(width) << myImageID
02667                   << std::setw(width) << gid
02668                   << std::setw(width) << rowinfo.numEntries;
02669               if (vl == VERB_EXTREME) {
02670                 if (isGloballyIndexed()) {
02671                   ArrayView<const GlobalOrdinal> rowview = getGlobalView(rowinfo);
02672                   for (size_t j=0; j < rowinfo.numEntries; ++j) out << rowview[j] << " ";
02673                 }
02674                 else if (isLocallyIndexed()) {
02675                   ArrayView<const LocalOrdinal> rowview = getLocalView(rowinfo);
02676                   for (size_t j=0; j < rowinfo.numEntries; ++j) out << colMap_->getGlobalElement(rowview[j]) << " ";
02677                 }
02678               }
02679               out << std::endl;
02680             }
02681           }
02682           comm->barrier();
02683           comm->barrier();
02684           comm->barrier();
02685         }
02686       }
02687     }
02688   }
02689 
02690 
02691   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
02692   bool CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::checkSizes(const DistObject<GlobalOrdinal,LocalOrdinal,GlobalOrdinal,Node>& source)
02693   {
02694     // It's not clear what kind of compatibility checks on sizes can be performed here.
02695     // Epetra_CrsGraph doesn't check any sizes for compatibility.
02696     return true;
02697   }
02698 
02699 
02700   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
02701   void CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::copyAndPermute(
02702                           const DistObject<GlobalOrdinal,LocalOrdinal,GlobalOrdinal,Node> & source,
02703                           size_t numSameIDs,
02704                           const ArrayView<const LocalOrdinal> &permuteToLIDs,
02705                           const ArrayView<const LocalOrdinal> &permuteFromLIDs)
02706   {
02707     const CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>& src_graph = dynamic_cast<const CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>&>(source);
02708     std::string tfecfFuncName("copyAndPermute()");
02709     TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(permuteToLIDs.size() != permuteFromLIDs.size(), std::runtime_error, ": permuteToLIDs and permuteFromLIDs must have the same size.");
02710     bool src_filled = src_graph.isFillComplete();
02711 
02712     Array<GlobalOrdinal> row_copy;
02713     LocalOrdinal myid = 0;
02714     for (size_t i=0; i<numSameIDs; ++i, ++myid) {
02715       GlobalOrdinal gid = src_graph.getMap()->getGlobalElement(myid);
02716       if (src_filled) {
02717         size_t row_length = src_graph.getNumEntriesInGlobalRow(gid);
02718         row_copy.resize(row_length);
02719         size_t check_row_length = 0;
02720         src_graph.getGlobalRowCopy(gid, row_copy(), check_row_length);
02721         insertGlobalIndices( gid, row_copy() );
02722       }
02723       else {
02724         ArrayView<const GlobalOrdinal> row;
02725         src_graph.getGlobalRowView( gid,row );
02726         insertGlobalIndices( gid, row );
02727       }
02728     }
02729 
02730     for (LocalOrdinal i=0; i<permuteToLIDs.size(); ++i) {
02731       GlobalOrdinal mygid = this->getMap()->getGlobalElement(permuteToLIDs[i]);
02732       GlobalOrdinal srcgid= src_graph.getMap()->getGlobalElement(permuteFromLIDs[i]);
02733       if (src_filled) {
02734         size_t row_length = src_graph.getNumEntriesInGlobalRow(srcgid);
02735         row_copy.resize(row_length);
02736         size_t check_row_length = 0;
02737         src_graph.getGlobalRowCopy(srcgid, row_copy(), check_row_length);
02738         insertGlobalIndices( mygid, row_copy() );
02739       }
02740       else {
02741         ArrayView<const GlobalOrdinal> row;
02742         src_graph.getGlobalRowView( srcgid, row );
02743         insertGlobalIndices( mygid, row );
02744       }
02745     }
02746   }
02747 
02748 
02749   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
02750   void
02751   CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::
02752   packAndPrepare (const DistObject<GlobalOrdinal,LocalOrdinal,GlobalOrdinal,Node> & source,
02753                   const ArrayView<const LocalOrdinal> &exportLIDs,
02754                   Array<GlobalOrdinal> &exports,
02755                   const ArrayView<size_t> & numPacketsPerLID,
02756                   size_t& constantNumPackets,
02757                   Distributor &distor)
02758   {
02759     std::string tfecfFuncName("packAndPrepare()");
02760     TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(exportLIDs.size() != numPacketsPerLID.size(), std::runtime_error,
02761         ": exportLIDs and numPacketsPerLID must have the same size.");
02762     const CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>& src_graph = dynamic_cast<const CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>&>(source);
02763     // We don't check whether src_graph has had fillComplete called, because it doesn't matter whether the
02764     // *source* graph has been fillComplete'd. The target graph can not be fillComplete'd yet.
02765     TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->isFillComplete() == true, std::runtime_error,
02766          ": import/export operations are not allowed on destination CrsGraph after fillComplete has been called.");
02767     constantNumPackets = 0;
02768     // first set the contents of numPacketsPerLID, and accumulate a total-num-packets:
02769     size_t totalNumPackets = 0;
02770     Array<GlobalOrdinal> row;
02771     for (LocalOrdinal i=0; i<exportLIDs.size(); ++i) {
02772       GlobalOrdinal GID = src_graph.getMap()->getGlobalElement(exportLIDs[i]);
02773       size_t row_length = src_graph.getNumEntriesInGlobalRow(GID);
02774       numPacketsPerLID[i] = row_length;
02775       totalNumPackets += row_length;
02776     }
02777 
02778     exports.resize(totalNumPackets);
02779 
02780     // now loop again and pack rows of indices into exports:
02781     size_t exportsOffset = 0;
02782     for (LocalOrdinal i=0; i<exportLIDs.size(); ++i) {
02783       GlobalOrdinal GID = src_graph.getMap()->getGlobalElement(exportLIDs[i]);
02784       size_t row_length = src_graph.getNumEntriesInGlobalRow(GID);
02785       row.resize(row_length);
02786       size_t check_row_length = 0;
02787       src_graph.getGlobalRowCopy(GID, row(), check_row_length);
02788       typename Array<GlobalOrdinal>::const_iterator
02789         row_iter = row.begin(), row_end = row.end();
02790       size_t j = 0;
02791       for (; row_iter != row_end; ++row_iter, ++j) {
02792         exports[exportsOffset+j] = *row_iter;
02793       }
02794       exportsOffset += row.size();
02795     }
02796   }
02797 
02798 
02799   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
02800   void CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::unpackAndCombine(
02801                             const ArrayView<const LocalOrdinal> &importLIDs,
02802                             const ArrayView<const GlobalOrdinal> &imports,
02803                             const ArrayView<size_t> &numPacketsPerLID,
02804                             size_t constantNumPackets,
02805                             Distributor & /* distor */,
02806                             CombineMode /* CM */)
02807   {
02808     // FIXME (mfh 02 Apr 2012) REPLACE combine mode has a perfectly
02809     // reasonable meaning, whether or not the matrix is fill complete.
02810     // It's just more work to implement.
02811 
02812     // We are not checking the value of the CombineMode input-argument.
02813     // For CrsGraph, we only support import/export operations if fillComplete has not yet been called.
02814     // Any incoming column-indices are inserted into the target graph. In this context, CombineMode values
02815     // of ADD vs INSERT are equivalent. What is the meaning of REPLACE for CrsGraph? If a duplicate column-index
02816     // is inserted, it will be compressed out when fillComplete is called.
02817     //
02818     // Note: I think REPLACE means that an existing row is replaced by the imported row, i.e., the existing indices are cleared. CGB, 6/17/2010
02819 
02820     std::string tfecfFuncName("unpackAndCombine()");
02821     TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(importLIDs.size() != numPacketsPerLID.size(), std::runtime_error,
02822         ": importLIDs and numPacketsPerLID must have the same size.");
02823     TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->isFillComplete() == true, std::runtime_error,
02824         ": import/export operations are not allowed on destination CrsGraph after fillComplete has been called.");
02825     size_t importsOffset = 0;
02826     typename ArrayView<const LocalOrdinal>::iterator
02827       impLIDiter = importLIDs.begin(), impLIDend = importLIDs.end();
02828     size_t i = 0;
02829     for (; impLIDiter != impLIDend; ++impLIDiter, ++i) {
02830       LocalOrdinal row_length = numPacketsPerLID[i];
02831       const ArrayView<const GlobalOrdinal> row(&imports[importsOffset], row_length);
02832       insertGlobalIndices(this->getMap()->getGlobalElement(*impLIDiter), row);
02833       importsOffset += row_length;
02834     }
02835   }
02836 
02837 
02840   //                                                                         //
02841   //                         Deprecated methods                              //
02842   //                                                                         //
02845 
02846 
02848   // DEPRECATED
02850   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
02851   ArrayRCP<const LocalOrdinal> CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::getLocalRowView(LocalOrdinal localRow) const
02852   {
02853     std::string tfecfFuncName("getLocalRowView(localRow)");
02854     TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(isGloballyIndexed() == true, std::runtime_error,
02855         ": local indices do not exist.");
02856     TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(rowMap_->isNodeLocalElement(localRow) == false, std::runtime_error,
02857         ": localRow (== " << localRow << ") is not valid on this node.");
02858     ArrayRCP<const LocalOrdinal> ret;
02859     RowInfo sizeInfo = getRowInfo(localRow);
02860     if (getProfileType() == StaticProfile && sizeInfo.numEntries > 0) {
02861       ret = lclInds1D_.persistingView(sizeInfo.offset1D,sizeInfo.numEntries);
02862     }
02863     else if (getProfileType() == DynamicProfile && sizeInfo.numEntries > 0) {
02864       ret = lclInds2D_[localRow].persistingView(0,sizeInfo.numEntries);
02865     }
02866     return ret;
02867   }
02868 
02869 
02871   // DEPRECATED
02873   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
02874   ArrayRCP<const GlobalOrdinal> CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::getGlobalRowView(GlobalOrdinal globalRow) const
02875   {
02876     std::string tfecfFuncName("getGlobalRowView(globalRow)");
02877     TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(isLocallyIndexed() == true, std::runtime_error,
02878         ": global indices do not exist.");
02879     const LocalOrdinal lrow = rowMap_->getLocalElement(globalRow);
02880     TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(lrow == OrdinalTraits<LocalOrdinal>::invalid(), std::runtime_error,
02881         ": globalRow (== " << globalRow << ") does not belong to this node.");
02882     ArrayRCP<const GlobalOrdinal> ret;
02883     RowInfo sizeInfo = getRowInfo(lrow);
02884     if (getProfileType() == StaticProfile && sizeInfo.numEntries > 0) {
02885       ret = gblInds1D_.persistingView(sizeInfo.offset1D,sizeInfo.numEntries);
02886     }
02887     else if (getProfileType() == DynamicProfile && sizeInfo.numEntries > 0) {
02888       ret = gblInds2D_[lrow].persistingView(0,sizeInfo.numEntries);
02889     }
02890     return ret;
02891   }
02892 
02893 
02895   // DEPRECATED
02897   template <class LocalOrdinal, class GlobalOrdinal, class Node, class LocalMatOps>
02898   void CrsGraph<LocalOrdinal,GlobalOrdinal,Node,LocalMatOps>::optimizeStorage ()
02899   {
02900     // provided only for backwards compatibility
02901     // previous semantics required that fillComplete() had been called.
02902     std::string tfecfFuncName("optimizeStorage()");
02903     TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(! isFillComplete(), std::runtime_error,
02904       ": requires that fillComplete() has already been called.");
02905     if (! isStorageOptimized ()) {
02906       resumeFill ();
02907       fillComplete (DoOptimizeStorage);
02908     }
02909   }
02910 
02911 } // namespace Tpetra
02912 
02913 
02914 //
02915 // Explicit instantiation macro
02916 //
02917 // Must be expanded from within the Tpetra namespace!
02918 //
02919 
02920 #define TPETRA_CRSGRAPH_INSTANT(LO,GO,NODE) \
02921   \
02922   template class CrsGraph< LO , GO , NODE >; \
02923 
02924 
02925 #endif // TPETRA_CRSGRAPH_DEF_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines