|
Tpetra Matrix/Vector Services Version of the Day
|
00001 // @HEADER 00002 // *********************************************************************** 00003 // 00004 // Tpetra: Templated Linear Algebra Services Package 00005 // Copyright (2008) Sandia Corporation 00006 // 00007 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, 00008 // the U.S. Government retains certain rights in this software. 00009 // 00010 // Redistribution and use in source and binary forms, with or without 00011 // modification, are permitted provided that the following conditions are 00012 // met: 00013 // 00014 // 1. Redistributions of source code must retain the above copyright 00015 // notice, this list of conditions and the following disclaimer. 00016 // 00017 // 2. Redistributions in binary form must reproduce the above copyright 00018 // notice, this list of conditions and the following disclaimer in the 00019 // documentation and/or other materials provided with the distribution. 00020 // 00021 // 3. Neither the name of the Corporation nor the names of the 00022 // contributors may be used to endorse or promote products derived from 00023 // this software without specific prior written permission. 00024 // 00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY 00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE 00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00036 // 00037 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 00038 // 00039 // ************************************************************************ 00040 // @HEADER 00041 00042 // 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
1.7.4