Tpetra Matrix/Vector Services Version of the Day
Tpetra_BlockMap_def.hpp
00001 // @HEADER
00002 // ***********************************************************************
00003 // 
00004 //          Tpetra: Templated Linear Algebra Services Package
00005 //                 Copyright (2008) Sandia Corporation
00006 // 
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 // 
00010 // This library is free software; you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as
00012 // published by the Free Software Foundation; either version 2.1 of the
00013 // License, or (at your option) any later version.
00014 //  
00015 // This library is distributed in the hope that it will be useful, but
00016 // WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 // Lesser General Public License for more details.
00019 //  
00020 // You should have received a copy of the GNU Lesser General Public
00021 // License along with this library; if not, write to the Free Software
00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00023 // USA
00024 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 
00025 // 
00026 // ***********************************************************************
00027 // @HEADER
00028 
00029 #ifndef TPETRA_BLOCKMAP_DEF_HPP
00030 #define TPETRA_BLOCKMAP_DEF_HPP
00031 
00032 #include "Tpetra_ConfigDefs.hpp"
00033 #include "Tpetra_Distributor.hpp"
00034 
00035 #ifdef DOXYGEN_USE_ONLY
00036 #include "Tpetra_BlockMap_decl.hpp"
00037 #endif
00038 
00039 namespace Tpetra {
00040 
00041 template<class LocalOrdinal,class GlobalOrdinal,class Node>
00042 BlockMap<LocalOrdinal,GlobalOrdinal,Node>::BlockMap(
00043     global_size_t numGlobalBlocks,
00044     LocalOrdinal blockSize,
00045     GlobalOrdinal indexBase,
00046     const Teuchos::RCP<const Teuchos::Comm<int> > &comm,
00047     const Teuchos::RCP<Node> &node)
00048  : pointMap_(),
00049    globalNumBlocks_(numGlobalBlocks),
00050    myGlobalBlockIDs_(),
00051    pbuf_firstPointInBlock_(),
00052    view_firstPointInBlock_(),
00053    blockIDsAreContiguous_(true),
00054    constantBlockSize_(blockSize)
00055 {
00056   TEST_FOR_EXCEPTION( blockSize <= 0, std::runtime_error,
00057        "Tpetra::BlockMap::BlockMap ERROR: blockSize must be greater than 0.");
00058 
00059   global_size_t numGlobalPoints = numGlobalBlocks*blockSize;
00060 
00061   //we compute numLocalPoints to make sure that Tpetra::Map doesn't split
00062   //numGlobalPoints in a way that would separate the points within a block
00063   //onto different mpi processors.
00064 
00065   size_t numLocalPoints = numGlobalBlocks/comm->getSize();
00066   int remainder = numGlobalBlocks%comm->getSize();
00067   int localProc = comm->getRank();
00068   if (localProc < remainder) ++numLocalPoints;
00069   numLocalPoints *= blockSize;
00070 
00071   //now create the point-map specifying both numGlobalPoints and numLocalPoints:
00072   pointMap_ = Teuchos::rcp(new Map<LocalOrdinal,GlobalOrdinal,Node>(numGlobalPoints, numLocalPoints, indexBase, comm, node));
00073 
00074   size_t numLocalBlocks = pointMap_->getNodeNumElements()/blockSize;
00075   size_t checkLocalBlocks = numLocalPoints/blockSize;
00076   //can there be an inconsistency here???
00077   TEST_FOR_EXCEPTION(numLocalBlocks != checkLocalBlocks, std::runtime_error,
00078        "Tpetra::BlockMap::BlockMap ERROR: internal failure, numLocalBlocks not consistent with point-map.");
00079   
00080   myGlobalBlockIDs_.resize(numLocalBlocks);
00081   pbuf_firstPointInBlock_ = node->template allocBuffer<LocalOrdinal>(numLocalBlocks+1);
00082   Teuchos::ArrayRCP<LocalOrdinal> v_firstPoints = node->template viewBufferNonConst<LocalOrdinal>(Kokkos::WriteOnly, numLocalBlocks+1, pbuf_firstPointInBlock_);
00083 
00084   LocalOrdinal firstPoint = pointMap_->getMinLocalIndex();
00085   GlobalOrdinal blockID = pointMap_->getMinGlobalIndex()/blockSize;
00086   for(size_t i=0; i<numLocalBlocks; ++i) {
00087     myGlobalBlockIDs_[i] = blockID++;
00088     v_firstPoints[i] = firstPoint;
00089     firstPoint += blockSize;
00090   }
00091   v_firstPoints[numLocalBlocks] = firstPoint;
00092   v_firstPoints = Teuchos::null;
00093   view_firstPointInBlock_ = node->template viewBuffer<LocalOrdinal>(numLocalBlocks+1, pbuf_firstPointInBlock_);
00094 }
00095 
00096 template<class LocalOrdinal,class GlobalOrdinal,class Node>
00097 BlockMap<LocalOrdinal,GlobalOrdinal,Node>::BlockMap(
00098     global_size_t numGlobalBlocks,
00099     size_t numLocalBlocks,
00100     LocalOrdinal blockSize,
00101     GlobalOrdinal indexBase,
00102     const Teuchos::RCP<const Teuchos::Comm<int> > &comm,
00103     const Teuchos::RCP<Node> &node)
00104  : pointMap_(),
00105    globalNumBlocks_(numGlobalBlocks),
00106    myGlobalBlockIDs_(),
00107    pbuf_firstPointInBlock_(),
00108    view_firstPointInBlock_(),
00109    blockIDsAreContiguous_(true),
00110    constantBlockSize_(blockSize)
00111 {
00112   TEST_FOR_EXCEPTION( blockSize <= 0, std::runtime_error,
00113        "Tpetra::BlockMap::BlockMap ERROR: blockSize must be greater than 0.");
00114 
00115   global_size_t numGlobalPoints = numGlobalBlocks*blockSize;
00116   if (numGlobalBlocks == Teuchos::OrdinalTraits<global_size_t>::invalid()) {
00117     numGlobalPoints = Teuchos::OrdinalTraits<global_size_t>::invalid();
00118   }
00119 
00120   size_t numLocalPoints = numLocalBlocks*blockSize;
00121 
00122   //now create the point-map specifying both numGlobalPoints and numLocalPoints:
00123   pointMap_ = Teuchos::rcp(new Map<LocalOrdinal,GlobalOrdinal,Node>(numGlobalPoints, numLocalPoints, indexBase, comm, node));
00124 
00125   if (numGlobalBlocks == Teuchos::OrdinalTraits<global_size_t>::invalid()) {
00126     Teuchos::reduceAll<int, global_size_t>(*comm, Teuchos::REDUCE_SUM,
00127              1, &numLocalBlocks, &globalNumBlocks_);
00128   }
00129 
00130   myGlobalBlockIDs_.resize(numLocalBlocks);
00131   pbuf_firstPointInBlock_ = node->template allocBuffer<LocalOrdinal>(numLocalBlocks+1);
00132   Teuchos::ArrayRCP<LocalOrdinal> v_firstPoints = node->template viewBufferNonConst<LocalOrdinal>(Kokkos::WriteOnly, numLocalBlocks+1, pbuf_firstPointInBlock_);
00133 
00134   LocalOrdinal firstPoint = pointMap_->getMinLocalIndex();
00135   GlobalOrdinal blockID = pointMap_->getMinGlobalIndex()/blockSize;
00136   for(size_t i=0; i<numLocalBlocks; ++i) {
00137     myGlobalBlockIDs_[i] = blockID++;
00138     v_firstPoints[i] = firstPoint;
00139     firstPoint += blockSize;
00140   }
00141   v_firstPoints[numLocalBlocks] = firstPoint;
00142   v_firstPoints = Teuchos::null;
00143   view_firstPointInBlock_ = node->template viewBuffer<LocalOrdinal>(numLocalBlocks+1, pbuf_firstPointInBlock_);
00144 }
00145 
00146 template<class LocalOrdinal,class GlobalOrdinal,class Node>
00147 BlockMap<LocalOrdinal,GlobalOrdinal,Node>::BlockMap(
00148     global_size_t numGlobalBlocks,
00149     const Teuchos::ArrayView<const GlobalOrdinal>& myGlobalBlockIDs,
00150     const Teuchos::ArrayView<const GlobalOrdinal>& myFirstGlobalPointInBlocks,
00151     const Teuchos::ArrayView<const LocalOrdinal>& blockSizes,
00152     GlobalOrdinal indexBase,
00153     const Teuchos::RCP<const Teuchos::Comm<int> > &comm,
00154     const Teuchos::RCP<Node> &node)
00155  : pointMap_(),
00156    globalNumBlocks_(numGlobalBlocks),
00157    myGlobalBlockIDs_(myGlobalBlockIDs),
00158    pbuf_firstPointInBlock_(),
00159    view_firstPointInBlock_(),
00160    blockIDsAreContiguous_(false),
00161    constantBlockSize_(0)
00162 {
00163   TEST_FOR_EXCEPTION(myGlobalBlockIDs_.size()!=blockSizes.size(), std::runtime_error,
00164              "Tpetra::BlockMap::BlockMap ERROR: input myGlobalBlockIDs and blockSizes arrays must have the same length.");
00165 
00166   size_t sum_blockSizes = 0;
00167   Teuchos::Array<GlobalOrdinal> myGlobalPoints;
00168   typename Teuchos::ArrayView<const LocalOrdinal>::const_iterator
00169     iter = blockSizes.begin(), iend = blockSizes.end();
00170   size_t i = 0;
00171   for(; iter!=iend; ++iter) {
00172     LocalOrdinal bsize = *iter;
00173     sum_blockSizes += bsize;
00174     GlobalOrdinal firstPoint = myFirstGlobalPointInBlocks[i++];
00175     for(LocalOrdinal j=0; j<bsize; ++j) {
00176       myGlobalPoints.push_back(firstPoint+j);
00177     }
00178   }
00179 
00180   pointMap_ = Teuchos::rcp(new Map<LocalOrdinal,GlobalOrdinal,Node>(Teuchos::OrdinalTraits<global_size_t>::invalid(), myGlobalPoints(), indexBase, comm, node));
00181 
00182   global_size_t global_sum;
00183   Teuchos::reduceAll<int,global_size_t>(*comm, Teuchos::REDUCE_SUM,
00184                 Teuchos::as<global_size_t>(myGlobalBlockIDs.size()), Teuchos::outArg(global_sum));
00185   globalNumBlocks_ = global_sum;
00186 
00187   iter = blockSizes.begin();
00188   LocalOrdinal firstBlockSize = iter==iend ? 0 : *iter;
00189   LocalOrdinal firstPoint = pointMap_->getMinLocalIndex();
00190   LocalOrdinal numLocalBlocks = myGlobalBlockIDs.size();
00191   pbuf_firstPointInBlock_ = node->template allocBuffer<LocalOrdinal>(numLocalBlocks+1);
00192   Teuchos::ArrayRCP<LocalOrdinal> v_firstPoints = node->template viewBufferNonConst<LocalOrdinal>(Kokkos::WriteOnly, numLocalBlocks+1, pbuf_firstPointInBlock_);
00193 
00194   bool blockSizesAreConstant = true;
00195   i=0;
00196   for(; iter!=iend; ++iter, ++i) {
00197     v_firstPoints[i] = firstPoint;
00198     firstPoint += *iter;
00199     if (*iter != firstBlockSize) {
00200       blockSizesAreConstant = false;
00201     }
00202   }
00203   v_firstPoints[i] = firstPoint;
00204   v_firstPoints = Teuchos::null;
00205   if (blockSizesAreConstant) constantBlockSize_ = firstBlockSize;
00206 
00207   size_t num_points = pointMap_->getNodeNumElements();
00208   TEST_FOR_EXCEPTION(sum_blockSizes != num_points, std::runtime_error,
00209             "Tpetra::BlockMap::BlockMap ERROR: internal failure, sum of block-sizes must equal pointMap->getNodeNumElements().");
00210 
00211   typename Teuchos::Array<GlobalOrdinal>::const_iterator
00212     b_iter = myGlobalBlockIDs_.begin(), b_end = myGlobalBlockIDs_.end();
00213   GlobalOrdinal id = b_iter==b_end ? 0 : *b_iter;
00214   if (b_iter != b_end) ++b_iter;
00215   blockIDsAreContiguous_ = true;
00216   for(; b_iter != b_end; ++b_iter) {
00217     if (*b_iter != id+1) {
00218       blockIDsAreContiguous_ = false;
00219       break;
00220     }
00221     ++id;
00222   }
00223   if (blockIDsAreContiguous_ == false) {
00224     setup_noncontig_mapping();
00225   }
00226 
00227   view_firstPointInBlock_ = node->template viewBuffer<LocalOrdinal>(numLocalBlocks+1, pbuf_firstPointInBlock_);
00228 }
00229 
00230 template<class LocalOrdinal,class GlobalOrdinal,class Node>
00231 BlockMap<LocalOrdinal,GlobalOrdinal,Node>::BlockMap(const Teuchos::RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> >& pointMap, const Teuchos::ArrayView<const GlobalOrdinal>& myGlobalBlockIDs, const Teuchos::ArrayView<const LocalOrdinal>& blockSizes, const Teuchos::RCP<Node>& node)
00232  : pointMap_(pointMap),
00233    globalNumBlocks_(Teuchos::OrdinalTraits<LocalOrdinal>::invalid()),
00234    myGlobalBlockIDs_(myGlobalBlockIDs),
00235    pbuf_firstPointInBlock_(),
00236    view_firstPointInBlock_(),
00237    blockIDsAreContiguous_(false),
00238    constantBlockSize_(0)
00239 {
00240   TEST_FOR_EXCEPTION(myGlobalBlockIDs_.size()!=blockSizes.size(), std::runtime_error,
00241              "Tpetra::BlockMap::BlockMap ERROR: input myGlobalBlockIDs and blockSizes arrays must have the same length.");
00242 
00243   global_size_t numLocalBlocks = myGlobalBlockIDs.size();
00244   Teuchos::reduceAll<int,global_size_t>(*pointMap->getComm(), Teuchos::REDUCE_SUM, 1, &numLocalBlocks, &globalNumBlocks_);
00245 
00246   LocalOrdinal firstPoint = pointMap->getMinLocalIndex();
00247   size_t sum_blockSizes = 0;
00248   typename Teuchos::ArrayView<const LocalOrdinal>::const_iterator
00249     iter = blockSizes.begin(), iend = blockSizes.end();
00250   LocalOrdinal firstBlockSize = *iter;
00251 
00252   pbuf_firstPointInBlock_ = node->template allocBuffer<LocalOrdinal>(myGlobalBlockIDs.size()+1);
00253   Teuchos::ArrayRCP<LocalOrdinal> v_firstPoints = node->template viewBufferNonConst<LocalOrdinal>(Kokkos::WriteOnly, numLocalBlocks+1, pbuf_firstPointInBlock_);
00254 
00255   bool blockSizesAreConstant = true;
00256   size_t i=0;
00257   for(; iter!=iend; ++iter, ++i) {
00258     sum_blockSizes += *iter;
00259     v_firstPoints[i] = firstPoint;
00260     firstPoint += *iter;
00261     if (*iter != firstBlockSize) {
00262       blockSizesAreConstant = false;
00263     }
00264   }
00265   v_firstPoints[i] = firstPoint;
00266   v_firstPoints = Teuchos::null;
00267   if (blockSizesAreConstant) constantBlockSize_ = firstBlockSize;
00268 
00269   size_t num_points = pointMap->getNodeNumElements();
00270   TEST_FOR_EXCEPTION(sum_blockSizes != num_points, std::runtime_error,
00271             "Tpetra::BlockMap::BlockMap ERROR: sum of block-sizes must equal pointMap->getNodeNumElements().");
00272 
00273   typename Teuchos::Array<GlobalOrdinal>::const_iterator
00274     b_iter = myGlobalBlockIDs_.begin(), b_end = myGlobalBlockIDs_.end();
00275   GlobalOrdinal id = *b_iter;
00276   ++b_iter;
00277   blockIDsAreContiguous_ = true;
00278   for(; b_iter != b_end; ++b_iter) {
00279     if (*b_iter != id+1) {
00280       blockIDsAreContiguous_ = false;
00281       break;
00282     }
00283     ++id;
00284   }
00285   if (blockIDsAreContiguous_ == false) {
00286     setup_noncontig_mapping();
00287   }
00288 
00289   view_firstPointInBlock_ = node->template viewBuffer<LocalOrdinal>(numLocalBlocks+1, pbuf_firstPointInBlock_);
00290 }
00291 
00292 template<class LocalOrdinal,class GlobalOrdinal,class Node>
00293 void
00294 BlockMap<LocalOrdinal,GlobalOrdinal,Node>::getRemoteBlockInfo(
00295     const Teuchos::ArrayView<const GlobalOrdinal>& GBIDs,
00296     const Teuchos::ArrayView<GlobalOrdinal>& firstGlobalPointInBlocks,
00297     const Teuchos::ArrayView<LocalOrdinal>& blockSizes) const
00298 {
00299   Teuchos::RCP<const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > pbmap =
00300       convertBlockMapToPointMap(*this);
00301 
00302   Teuchos::Array<int> remoteProcs(GBIDs.size());
00303   pbmap->getRemoteIndexList(GBIDs(), remoteProcs());
00304 
00305   Tpetra::Distributor distor(pbmap->getComm());
00306 
00307   Tpetra::ArrayRCP<GlobalOrdinal> exportGBIDs;
00308   Tpetra::ArrayRCP<int> exportProcs;
00309 
00310   distor.createFromRecvs(GBIDs(), remoteProcs(), exportGBIDs, exportProcs);
00311 
00312   Tpetra::Array<GlobalOrdinal> exportFirstPointInBlocks(exportGBIDs.size());
00313   Tpetra::Array<LocalOrdinal> exportSizes(exportGBIDs.size());
00314 
00315   typename Teuchos::ArrayRCP<GlobalOrdinal>::const_iterator
00316     iter = exportGBIDs.begin(),
00317     iter_end = exportGBIDs.end();
00318   for(int i=0; iter!=iter_end; ++iter, ++i) {
00319     GlobalOrdinal gbid = *iter;
00320     LocalOrdinal lbid = getLocalBlockID(gbid);
00321     exportFirstPointInBlocks[i] = getFirstGlobalPointInLocalBlock(lbid);
00322     exportSizes[i] = getLocalBlockSize(lbid);
00323   }
00324 
00325   size_t numPackets = 1;
00326   distor.doPostsAndWaits(exportFirstPointInBlocks().getConst(),
00327                          numPackets, firstGlobalPointInBlocks);
00328 
00329   distor.doPostsAndWaits(exportSizes().getConst(), numPackets, blockSizes);
00330 }
00331 
00332 template<class LocalOrdinal,class GlobalOrdinal,class Node>
00333 void
00334 BlockMap<LocalOrdinal,GlobalOrdinal,Node>::setup_noncontig_mapping()
00335 {
00336   //possibly need to use a hash (unordered_map) here...
00337   typedef typename Teuchos::Array<GlobalOrdinal>::size_type Tsize_t;
00338   for(Tsize_t i=0; i<myGlobalBlockIDs_.size(); ++i) {
00339     LocalOrdinal li = i;
00340     map_global_to_local_.insert(std::make_pair(myGlobalBlockIDs_[i],li));
00341   }
00342 }
00343 
00344 template<class LocalOrdinal,class GlobalOrdinal,class Node>
00345 global_size_t
00346 BlockMap<LocalOrdinal,GlobalOrdinal,Node>::getGlobalNumBlocks() const
00347 {
00348   return globalNumBlocks_;
00349 }
00350 
00351 template<class LocalOrdinal,class GlobalOrdinal,class Node>
00352 size_t
00353 BlockMap<LocalOrdinal,GlobalOrdinal,Node>::getNodeNumBlocks() const
00354 {
00355   return myGlobalBlockIDs_.size();
00356 }
00357 
00358 template<class LocalOrdinal,class GlobalOrdinal,class Node>
00359 Teuchos::ArrayView<const GlobalOrdinal>
00360 BlockMap<LocalOrdinal,GlobalOrdinal,Node>::getNodeBlockIDs() const
00361 {
00362   return myGlobalBlockIDs_();
00363 }
00364 
00365 template<class LocalOrdinal,class GlobalOrdinal,class Node>
00366 bool
00367 BlockMap<LocalOrdinal,GlobalOrdinal,Node>::isBlockSizeConstant() const
00368 { return constantBlockSize_ != 0; }
00369 
00370 template<class LocalOrdinal,class GlobalOrdinal,class Node>
00371 Teuchos::ArrayRCP<const LocalOrdinal>
00372 BlockMap<LocalOrdinal,GlobalOrdinal,Node>::getNodeFirstPointInBlocks() const
00373 {
00374   return view_firstPointInBlock_;
00375 }
00376 
00377 template<class LocalOrdinal,class GlobalOrdinal,class Node>
00378 Teuchos::ArrayRCP<const LocalOrdinal>
00379 BlockMap<LocalOrdinal,GlobalOrdinal,Node>::getNodeFirstPointInBlocks_Device() const
00380 {
00381   return pbuf_firstPointInBlock_;
00382 }
00383 
00384 template<class LocalOrdinal,class GlobalOrdinal,class Node>
00385 GlobalOrdinal
00386 BlockMap<LocalOrdinal,GlobalOrdinal,Node>::getGlobalBlockID(LocalOrdinal localBlockID) const
00387 {
00388   LocalOrdinal invalid = Teuchos::OrdinalTraits<LocalOrdinal>::invalid();
00389   if (localBlockID < 0 || localBlockID >= myGlobalBlockIDs_.size()) {
00390     return invalid;
00391   }
00392 
00393   return myGlobalBlockIDs_[localBlockID];
00394 }
00395 
00396 template<class LocalOrdinal,class GlobalOrdinal,class Node>
00397 LocalOrdinal
00398 BlockMap<LocalOrdinal,GlobalOrdinal,Node>::getLocalBlockID(GlobalOrdinal globalBlockID) const
00399 {
00400   LocalOrdinal invalid = Teuchos::OrdinalTraits<LocalOrdinal>::invalid();
00401   if (myGlobalBlockIDs_.size() == 0) {
00402     return invalid;
00403   }
00404 
00405   if (blockIDsAreContiguous_ == false) {
00406     //need to use a hash (unordered_map) here instead of a map...
00407     typename std::map<GlobalOrdinal,LocalOrdinal>::const_iterator iter =
00408       map_global_to_local_.find(globalBlockID);
00409     if (iter == map_global_to_local_.end()) return invalid;
00410     return iter->second;
00411   }
00412 
00413   LocalOrdinal localBlockID = globalBlockID - myGlobalBlockIDs_[0];
00414   LocalOrdinal numLocalBlocks = myGlobalBlockIDs_.size();
00415 
00416   if (localBlockID < 0 || localBlockID >= numLocalBlocks) {
00417     return invalid;
00418   }
00419 
00420   return localBlockID;
00421 }
00422 
00423 template<class LocalOrdinal,class GlobalOrdinal,class Node>
00424 LocalOrdinal
00425 BlockMap<LocalOrdinal,GlobalOrdinal,Node>::getLocalBlockSize(LocalOrdinal localBlockID) const
00426 {
00427   if (constantBlockSize_ != 0) {
00428     return constantBlockSize_;
00429   }
00430 
00431   //should this be a debug-mode-only range check?
00432   if (localBlockID < 0 || localBlockID >= view_firstPointInBlock_.size()) {
00433     throw std::runtime_error("Tpetra::BlockMap::getLocalBlockSize ERROR: localBlockID out of range.");
00434   }
00435 
00436   return view_firstPointInBlock_[localBlockID+1]-view_firstPointInBlock_[localBlockID];
00437 }
00438 
00439 template<class LocalOrdinal,class GlobalOrdinal,class Node>
00440 LocalOrdinal
00441 BlockMap<LocalOrdinal,GlobalOrdinal,Node>::getFirstLocalPointInLocalBlock(LocalOrdinal localBlockID) const
00442 {
00443   //should this be a debug-mode-only range check?
00444   if (localBlockID < 0 || localBlockID >= view_firstPointInBlock_.size()) {
00445     throw std::runtime_error("Tpetra::BlockMap::getFirstLocalPointInLocalBlock ERROR: localBlockID out of range.");
00446   }
00447 
00448   return view_firstPointInBlock_[localBlockID];
00449 }
00450 
00451 template<class LocalOrdinal,class GlobalOrdinal,class Node>
00452 GlobalOrdinal
00453 BlockMap<LocalOrdinal,GlobalOrdinal,Node>::getFirstGlobalPointInLocalBlock(LocalOrdinal localBlockID) const
00454 {
00455   //should this be a debug-mode-only range check?
00456   if (localBlockID < 0 || localBlockID >= view_firstPointInBlock_.size()) {
00457     throw std::runtime_error("Tpetra::BlockMap::getFirstGlobalPointInLocalBlock ERROR: localBlockID out of range.");
00458   }
00459 
00460   return pointMap_->getGlobalElement(view_firstPointInBlock_[localBlockID]);
00461 }
00462 
00463 }//namespace Tpetra
00464 
00465 //
00466 // Explicit instantiation macro
00467 //
00468 // Must be expanded from within the Tpetra namespace!
00469 //
00470 
00471 #define TPETRA_BLOCKMAP_INSTANT(LO,GO,NODE) \
00472   \
00473   template class BlockMap< LO , GO , NODE >;
00474 
00475 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines