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 the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00008 // the U.S. Government retains certain rights in this software.
00009 // 
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 
00038 // 
00039 // ************************************************************************
00040 // @HEADER
00041 
00042 #ifndef TPETRA_BLOCKMAP_DEF_HPP
00043 #define TPETRA_BLOCKMAP_DEF_HPP
00044 
00045 #include "Tpetra_ConfigDefs.hpp"
00046 #include "Tpetra_Distributor.hpp"
00047 
00048 #ifdef DOXYGEN_USE_ONLY
00049 #include "Tpetra_BlockMap_decl.hpp"
00050 #endif
00051 
00052 namespace Tpetra {
00053 
00054 template<class LocalOrdinal,class GlobalOrdinal,class Node>
00055 BlockMap<LocalOrdinal,GlobalOrdinal,Node>::BlockMap(
00056     global_size_t numGlobalBlocks,
00057     LocalOrdinal blockSize,
00058     GlobalOrdinal indexBase,
00059     const Teuchos::RCP<const Teuchos::Comm<int> > &comm,
00060     const Teuchos::RCP<Node> &node)
00061  : pointMap_(),
00062    globalNumBlocks_(numGlobalBlocks),
00063    myGlobalBlockIDs_(),
00064    pbuf_firstPointInBlock_(),
00065    view_firstPointInBlock_(),
00066    blockIDsAreContiguous_(true),
00067    constantBlockSize_(blockSize)
00068 {
00069   TEUCHOS_TEST_FOR_EXCEPTION( blockSize <= 0, std::runtime_error,
00070        "Tpetra::BlockMap::BlockMap ERROR: blockSize must be greater than 0.");
00071 
00072   global_size_t numGlobalPoints = numGlobalBlocks*blockSize;
00073 
00074   //we compute numLocalPoints to make sure that Tpetra::Map doesn't split
00075   //numGlobalPoints in a way that would separate the points within a block
00076   //onto different mpi processors.
00077 
00078   size_t numLocalPoints = numGlobalBlocks/comm->getSize();
00079   int remainder = numGlobalBlocks%comm->getSize();
00080   int localProc = comm->getRank();
00081   if (localProc < remainder) ++numLocalPoints;
00082   numLocalPoints *= blockSize;
00083 
00084   //now create the point-map specifying both numGlobalPoints and numLocalPoints:
00085   pointMap_ = Teuchos::rcp(new Map<LocalOrdinal,GlobalOrdinal,Node>(numGlobalPoints, numLocalPoints, indexBase, comm, node));
00086 
00087   size_t numLocalBlocks = pointMap_->getNodeNumElements()/blockSize;
00088   size_t checkLocalBlocks = numLocalPoints/blockSize;
00089   //can there be an inconsistency here???
00090   TEUCHOS_TEST_FOR_EXCEPTION(numLocalBlocks != checkLocalBlocks, std::runtime_error,
00091        "Tpetra::BlockMap::BlockMap ERROR: internal failure, numLocalBlocks not consistent with point-map.");
00092   
00093   myGlobalBlockIDs_.resize(numLocalBlocks);
00094   pbuf_firstPointInBlock_ = node->template allocBuffer<LocalOrdinal>(numLocalBlocks+1);
00095   Teuchos::ArrayRCP<LocalOrdinal> v_firstPoints = node->template viewBufferNonConst<LocalOrdinal>(Kokkos::WriteOnly, numLocalBlocks+1, pbuf_firstPointInBlock_);
00096 
00097   LocalOrdinal firstPoint = pointMap_->getMinLocalIndex();
00098   GlobalOrdinal blockID = pointMap_->getMinGlobalIndex()/blockSize;
00099   for(size_t i=0; i<numLocalBlocks; ++i) {
00100     myGlobalBlockIDs_[i] = blockID++;
00101     v_firstPoints[i] = firstPoint;
00102     firstPoint += blockSize;
00103   }
00104   v_firstPoints[numLocalBlocks] = firstPoint;
00105   v_firstPoints = Teuchos::null;
00106   view_firstPointInBlock_ = node->template viewBuffer<LocalOrdinal>(numLocalBlocks+1, pbuf_firstPointInBlock_);
00107 }
00108 
00109 template<class LocalOrdinal,class GlobalOrdinal,class Node>
00110 BlockMap<LocalOrdinal,GlobalOrdinal,Node>::BlockMap(
00111     global_size_t numGlobalBlocks,
00112     size_t numLocalBlocks,
00113     LocalOrdinal blockSize,
00114     GlobalOrdinal indexBase,
00115     const Teuchos::RCP<const Teuchos::Comm<int> > &comm,
00116     const Teuchos::RCP<Node> &node)
00117  : pointMap_(),
00118    globalNumBlocks_(numGlobalBlocks),
00119    myGlobalBlockIDs_(),
00120    pbuf_firstPointInBlock_(),
00121    view_firstPointInBlock_(),
00122    blockIDsAreContiguous_(true),
00123    constantBlockSize_(blockSize)
00124 {
00125   TEUCHOS_TEST_FOR_EXCEPTION( blockSize <= 0, std::runtime_error,
00126        "Tpetra::BlockMap::BlockMap ERROR: blockSize must be greater than 0.");
00127 
00128   global_size_t numGlobalPoints = numGlobalBlocks*blockSize;
00129   if (numGlobalBlocks == Teuchos::OrdinalTraits<global_size_t>::invalid()) {
00130     numGlobalPoints = Teuchos::OrdinalTraits<global_size_t>::invalid();
00131   }
00132 
00133   size_t numLocalPoints = numLocalBlocks*blockSize;
00134 
00135   //now create the point-map specifying both numGlobalPoints and numLocalPoints:
00136   pointMap_ = Teuchos::rcp(new Map<LocalOrdinal,GlobalOrdinal,Node>(numGlobalPoints, numLocalPoints, indexBase, comm, node));
00137 
00138   if (numGlobalBlocks == Teuchos::OrdinalTraits<global_size_t>::invalid()) {
00139     Teuchos::reduceAll<int, global_size_t>(*comm, Teuchos::REDUCE_SUM,
00140              1, &numLocalBlocks, &globalNumBlocks_);
00141   }
00142 
00143   myGlobalBlockIDs_.resize(numLocalBlocks);
00144   pbuf_firstPointInBlock_ = node->template allocBuffer<LocalOrdinal>(numLocalBlocks+1);
00145   Teuchos::ArrayRCP<LocalOrdinal> v_firstPoints = node->template viewBufferNonConst<LocalOrdinal>(Kokkos::WriteOnly, numLocalBlocks+1, pbuf_firstPointInBlock_);
00146 
00147   LocalOrdinal firstPoint = pointMap_->getMinLocalIndex();
00148   GlobalOrdinal blockID = pointMap_->getMinGlobalIndex()/blockSize;
00149   for(size_t i=0; i<numLocalBlocks; ++i) {
00150     myGlobalBlockIDs_[i] = blockID++;
00151     v_firstPoints[i] = firstPoint;
00152     firstPoint += blockSize;
00153   }
00154   v_firstPoints[numLocalBlocks] = firstPoint;
00155   v_firstPoints = Teuchos::null;
00156   view_firstPointInBlock_ = node->template viewBuffer<LocalOrdinal>(numLocalBlocks+1, pbuf_firstPointInBlock_);
00157 }
00158 
00159 template<class LocalOrdinal,class GlobalOrdinal,class Node>
00160 BlockMap<LocalOrdinal,GlobalOrdinal,Node>::BlockMap(
00161     global_size_t numGlobalBlocks,
00162     const Teuchos::ArrayView<const GlobalOrdinal>& myGlobalBlockIDs,
00163     const Teuchos::ArrayView<const GlobalOrdinal>& myFirstGlobalPointInBlocks,
00164     const Teuchos::ArrayView<const LocalOrdinal>& blockSizes,
00165     GlobalOrdinal indexBase,
00166     const Teuchos::RCP<const Teuchos::Comm<int> > &comm,
00167     const Teuchos::RCP<Node> &node)
00168  : pointMap_(),
00169    globalNumBlocks_(numGlobalBlocks),
00170    myGlobalBlockIDs_(myGlobalBlockIDs),
00171    pbuf_firstPointInBlock_(),
00172    view_firstPointInBlock_(),
00173    blockIDsAreContiguous_(false),
00174    constantBlockSize_(0)
00175 {
00176   TEUCHOS_TEST_FOR_EXCEPTION(myGlobalBlockIDs_.size()!=blockSizes.size(), std::runtime_error,
00177              "Tpetra::BlockMap::BlockMap ERROR: input myGlobalBlockIDs and blockSizes arrays must have the same length.");
00178 
00179   size_t sum_blockSizes = 0;
00180   Teuchos::Array<GlobalOrdinal> myGlobalPoints;
00181   typename Teuchos::ArrayView<const LocalOrdinal>::const_iterator
00182     iter = blockSizes.begin(), iend = blockSizes.end();
00183   size_t i = 0;
00184   for(; iter!=iend; ++iter) {
00185     LocalOrdinal bsize = *iter;
00186     sum_blockSizes += bsize;
00187     GlobalOrdinal firstPoint = myFirstGlobalPointInBlocks[i++];
00188     for(LocalOrdinal j=0; j<bsize; ++j) {
00189       myGlobalPoints.push_back(firstPoint+j);
00190     }
00191   }
00192 
00193   pointMap_ = Teuchos::rcp(new Map<LocalOrdinal,GlobalOrdinal,Node>(Teuchos::OrdinalTraits<global_size_t>::invalid(), myGlobalPoints(), indexBase, comm, node));
00194 
00195   global_size_t global_sum;
00196   Teuchos::reduceAll<int,global_size_t>(*comm, Teuchos::REDUCE_SUM,
00197                 Teuchos::as<global_size_t>(myGlobalBlockIDs.size()), Teuchos::outArg(global_sum));
00198   globalNumBlocks_ = global_sum;
00199 
00200   iter = blockSizes.begin();
00201   LocalOrdinal firstBlockSize = iter==iend ? 0 : *iter;
00202   LocalOrdinal firstPoint = pointMap_->getMinLocalIndex();
00203   LocalOrdinal numLocalBlocks = myGlobalBlockIDs.size();
00204   pbuf_firstPointInBlock_ = node->template allocBuffer<LocalOrdinal>(numLocalBlocks+1);
00205   Teuchos::ArrayRCP<LocalOrdinal> v_firstPoints = node->template viewBufferNonConst<LocalOrdinal>(Kokkos::WriteOnly, numLocalBlocks+1, pbuf_firstPointInBlock_);
00206 
00207   bool blockSizesAreConstant = true;
00208   i=0;
00209   for(; iter!=iend; ++iter, ++i) {
00210     v_firstPoints[i] = firstPoint;
00211     firstPoint += *iter;
00212     if (*iter != firstBlockSize) {
00213       blockSizesAreConstant = false;
00214     }
00215   }
00216   v_firstPoints[i] = firstPoint;
00217   v_firstPoints = Teuchos::null;
00218   if (blockSizesAreConstant) constantBlockSize_ = firstBlockSize;
00219 
00220   size_t num_points = pointMap_->getNodeNumElements();
00221   TEUCHOS_TEST_FOR_EXCEPTION(sum_blockSizes != num_points, std::runtime_error,
00222             "Tpetra::BlockMap::BlockMap ERROR: internal failure, sum of block-sizes must equal pointMap->getNodeNumElements().");
00223 
00224   typename Teuchos::Array<GlobalOrdinal>::const_iterator
00225     b_iter = myGlobalBlockIDs_.begin(), b_end = myGlobalBlockIDs_.end();
00226   GlobalOrdinal id = b_iter==b_end ? 0 : *b_iter;
00227   if (b_iter != b_end) ++b_iter;
00228   blockIDsAreContiguous_ = true;
00229   for(; b_iter != b_end; ++b_iter) {
00230     if (*b_iter != id+1) {
00231       blockIDsAreContiguous_ = false;
00232       break;
00233     }
00234     ++id;
00235   }
00236   if (blockIDsAreContiguous_ == false) {
00237     setup_noncontig_mapping();
00238   }
00239 
00240   view_firstPointInBlock_ = node->template viewBuffer<LocalOrdinal>(numLocalBlocks+1, pbuf_firstPointInBlock_);
00241 }
00242 
00243 template<class LocalOrdinal,class GlobalOrdinal,class Node>
00244 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)
00245  : pointMap_(pointMap),
00246    globalNumBlocks_(Teuchos::OrdinalTraits<LocalOrdinal>::invalid()),
00247    myGlobalBlockIDs_(myGlobalBlockIDs),
00248    pbuf_firstPointInBlock_(),
00249    view_firstPointInBlock_(),
00250    blockIDsAreContiguous_(false),
00251    constantBlockSize_(0)
00252 {
00253   TEUCHOS_TEST_FOR_EXCEPTION(myGlobalBlockIDs_.size()!=blockSizes.size(), std::runtime_error,
00254              "Tpetra::BlockMap::BlockMap ERROR: input myGlobalBlockIDs and blockSizes arrays must have the same length.");
00255 
00256   global_size_t numLocalBlocks = myGlobalBlockIDs.size();
00257   Teuchos::reduceAll<int,global_size_t>(*pointMap->getComm(), Teuchos::REDUCE_SUM, 1, &numLocalBlocks, &globalNumBlocks_);
00258 
00259   LocalOrdinal firstPoint = pointMap->getMinLocalIndex();
00260   size_t sum_blockSizes = 0;
00261   typename Teuchos::ArrayView<const LocalOrdinal>::const_iterator
00262     iter = blockSizes.begin(), iend = blockSizes.end();
00263   LocalOrdinal firstBlockSize = *iter;
00264 
00265   pbuf_firstPointInBlock_ = node->template allocBuffer<LocalOrdinal>(myGlobalBlockIDs.size()+1);
00266   Teuchos::ArrayRCP<LocalOrdinal> v_firstPoints = node->template viewBufferNonConst<LocalOrdinal>(Kokkos::WriteOnly, numLocalBlocks+1, pbuf_firstPointInBlock_);
00267 
00268   bool blockSizesAreConstant = true;
00269   size_t i=0;
00270   for(; iter!=iend; ++iter, ++i) {
00271     sum_blockSizes += *iter;
00272     v_firstPoints[i] = firstPoint;
00273     firstPoint += *iter;
00274     if (*iter != firstBlockSize) {
00275       blockSizesAreConstant = false;
00276     }
00277   }
00278   v_firstPoints[i] = firstPoint;
00279   v_firstPoints = Teuchos::null;
00280   if (blockSizesAreConstant) constantBlockSize_ = firstBlockSize;
00281 
00282   size_t num_points = pointMap->getNodeNumElements();
00283   TEUCHOS_TEST_FOR_EXCEPTION(sum_blockSizes != num_points, std::runtime_error,
00284             "Tpetra::BlockMap::BlockMap ERROR: sum of block-sizes must equal pointMap->getNodeNumElements().");
00285 
00286   typename Teuchos::Array<GlobalOrdinal>::const_iterator
00287     b_iter = myGlobalBlockIDs_.begin(), b_end = myGlobalBlockIDs_.end();
00288   GlobalOrdinal id = *b_iter;
00289   ++b_iter;
00290   blockIDsAreContiguous_ = true;
00291   for(; b_iter != b_end; ++b_iter) {
00292     if (*b_iter != id+1) {
00293       blockIDsAreContiguous_ = false;
00294       break;
00295     }
00296     ++id;
00297   }
00298   if (blockIDsAreContiguous_ == false) {
00299     setup_noncontig_mapping();
00300   }
00301 
00302   view_firstPointInBlock_ = node->template viewBuffer<LocalOrdinal>(numLocalBlocks+1, pbuf_firstPointInBlock_);
00303 }
00304 
00305 template<class LocalOrdinal,class GlobalOrdinal,class Node>
00306 void
00307 BlockMap<LocalOrdinal,GlobalOrdinal,Node>::getRemoteBlockInfo(
00308     const Teuchos::ArrayView<const GlobalOrdinal>& GBIDs,
00309     const Teuchos::ArrayView<GlobalOrdinal>& firstGlobalPointInBlocks,
00310     const Teuchos::ArrayView<LocalOrdinal>& blockSizes) const
00311 {
00312   Teuchos::RCP<const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > pbmap =
00313       convertBlockMapToPointMap(*this);
00314 
00315   Teuchos::Array<int> remoteProcs(GBIDs.size());
00316   pbmap->getRemoteIndexList(GBIDs(), remoteProcs());
00317 
00318   Tpetra::Distributor distor(pbmap->getComm());
00319 
00320   Tpetra::ArrayRCP<GlobalOrdinal> exportGBIDs;
00321   Tpetra::ArrayRCP<int> exportProcs;
00322 
00323   distor.createFromRecvs(GBIDs(), remoteProcs(), exportGBIDs, exportProcs);
00324 
00325   Tpetra::Array<GlobalOrdinal> exportFirstPointInBlocks(exportGBIDs.size());
00326   Tpetra::Array<LocalOrdinal> exportSizes(exportGBIDs.size());
00327 
00328   typename Teuchos::ArrayRCP<GlobalOrdinal>::const_iterator
00329     iter = exportGBIDs.begin(),
00330     iter_end = exportGBIDs.end();
00331   for(int i=0; iter!=iter_end; ++iter, ++i) {
00332     GlobalOrdinal gbid = *iter;
00333     LocalOrdinal lbid = getLocalBlockID(gbid);
00334     exportFirstPointInBlocks[i] = getFirstGlobalPointInLocalBlock(lbid);
00335     exportSizes[i] = getLocalBlockSize(lbid);
00336   }
00337 
00338   size_t numPackets = 1;
00339   distor.doPostsAndWaits(exportFirstPointInBlocks().getConst(),
00340                          numPackets, firstGlobalPointInBlocks);
00341 
00342   distor.doPostsAndWaits(exportSizes().getConst(), numPackets, blockSizes);
00343 }
00344 
00345 template<class LocalOrdinal,class GlobalOrdinal,class Node>
00346 void
00347 BlockMap<LocalOrdinal,GlobalOrdinal,Node>::setup_noncontig_mapping()
00348 {
00349   //possibly need to use a hash (unordered_map) here...
00350   typedef typename Teuchos::Array<GlobalOrdinal>::size_type Tsize_t;
00351   for(Tsize_t i=0; i<myGlobalBlockIDs_.size(); ++i) {
00352     LocalOrdinal li = i;
00353     map_global_to_local_.insert(std::make_pair(myGlobalBlockIDs_[i],li));
00354   }
00355 }
00356 
00357 template<class LocalOrdinal,class GlobalOrdinal,class Node>
00358 global_size_t
00359 BlockMap<LocalOrdinal,GlobalOrdinal,Node>::getGlobalNumBlocks() const
00360 {
00361   return globalNumBlocks_;
00362 }
00363 
00364 template<class LocalOrdinal,class GlobalOrdinal,class Node>
00365 size_t
00366 BlockMap<LocalOrdinal,GlobalOrdinal,Node>::getNodeNumBlocks() const
00367 {
00368   return myGlobalBlockIDs_.size();
00369 }
00370 
00371 template<class LocalOrdinal,class GlobalOrdinal,class Node>
00372 Teuchos::ArrayView<const GlobalOrdinal>
00373 BlockMap<LocalOrdinal,GlobalOrdinal,Node>::getNodeBlockIDs() const
00374 {
00375   return myGlobalBlockIDs_();
00376 }
00377 
00378 template<class LocalOrdinal,class GlobalOrdinal,class Node>
00379 bool
00380 BlockMap<LocalOrdinal,GlobalOrdinal,Node>::isBlockSizeConstant() const
00381 { return constantBlockSize_ != 0; }
00382 
00383 template<class LocalOrdinal,class GlobalOrdinal,class Node>
00384 Teuchos::ArrayRCP<const LocalOrdinal>
00385 BlockMap<LocalOrdinal,GlobalOrdinal,Node>::getNodeFirstPointInBlocks() const
00386 {
00387   return view_firstPointInBlock_;
00388 }
00389 
00390 template<class LocalOrdinal,class GlobalOrdinal,class Node>
00391 Teuchos::ArrayRCP<const LocalOrdinal>
00392 BlockMap<LocalOrdinal,GlobalOrdinal,Node>::getNodeFirstPointInBlocks_Device() const
00393 {
00394   return pbuf_firstPointInBlock_;
00395 }
00396 
00397 template<class LocalOrdinal,class GlobalOrdinal,class Node>
00398 GlobalOrdinal
00399 BlockMap<LocalOrdinal,GlobalOrdinal,Node>::getGlobalBlockID(LocalOrdinal localBlockID) const
00400 {
00401   LocalOrdinal invalid = Teuchos::OrdinalTraits<LocalOrdinal>::invalid();
00402   if (localBlockID < 0 || localBlockID >= myGlobalBlockIDs_.size()) {
00403     return invalid;
00404   }
00405 
00406   return myGlobalBlockIDs_[localBlockID];
00407 }
00408 
00409 template<class LocalOrdinal,class GlobalOrdinal,class Node>
00410 LocalOrdinal
00411 BlockMap<LocalOrdinal,GlobalOrdinal,Node>::getLocalBlockID(GlobalOrdinal globalBlockID) const
00412 {
00413   LocalOrdinal invalid = Teuchos::OrdinalTraits<LocalOrdinal>::invalid();
00414   if (myGlobalBlockIDs_.size() == 0) {
00415     return invalid;
00416   }
00417 
00418   if (blockIDsAreContiguous_ == false) {
00419     //need to use a hash (unordered_map) here instead of a map...
00420     typename std::map<GlobalOrdinal,LocalOrdinal>::const_iterator iter =
00421       map_global_to_local_.find(globalBlockID);
00422     if (iter == map_global_to_local_.end()) return invalid;
00423     return iter->second;
00424   }
00425 
00426   LocalOrdinal localBlockID = globalBlockID - myGlobalBlockIDs_[0];
00427   LocalOrdinal numLocalBlocks = myGlobalBlockIDs_.size();
00428 
00429   if (localBlockID < 0 || localBlockID >= numLocalBlocks) {
00430     return invalid;
00431   }
00432 
00433   return localBlockID;
00434 }
00435 
00436 template<class LocalOrdinal,class GlobalOrdinal,class Node>
00437 LocalOrdinal
00438 BlockMap<LocalOrdinal,GlobalOrdinal,Node>::getLocalBlockSize(LocalOrdinal localBlockID) const
00439 {
00440   if (constantBlockSize_ != 0) {
00441     return constantBlockSize_;
00442   }
00443 
00444   //should this be a debug-mode-only range check?
00445   if (localBlockID < 0 || localBlockID >= view_firstPointInBlock_.size()) {
00446     throw std::runtime_error("Tpetra::BlockMap::getLocalBlockSize ERROR: localBlockID out of range.");
00447   }
00448 
00449   return view_firstPointInBlock_[localBlockID+1]-view_firstPointInBlock_[localBlockID];
00450 }
00451 
00452 template<class LocalOrdinal,class GlobalOrdinal,class Node>
00453 LocalOrdinal
00454 BlockMap<LocalOrdinal,GlobalOrdinal,Node>::getFirstLocalPointInLocalBlock(LocalOrdinal localBlockID) const
00455 {
00456   //should this be a debug-mode-only range check?
00457   if (localBlockID < 0 || localBlockID >= view_firstPointInBlock_.size()) {
00458     throw std::runtime_error("Tpetra::BlockMap::getFirstLocalPointInLocalBlock ERROR: localBlockID out of range.");
00459   }
00460 
00461   return view_firstPointInBlock_[localBlockID];
00462 }
00463 
00464 template<class LocalOrdinal,class GlobalOrdinal,class Node>
00465 GlobalOrdinal
00466 BlockMap<LocalOrdinal,GlobalOrdinal,Node>::getFirstGlobalPointInLocalBlock(LocalOrdinal localBlockID) const
00467 {
00468   //should this be a debug-mode-only range check?
00469   if (localBlockID < 0 || localBlockID >= view_firstPointInBlock_.size()) {
00470     throw std::runtime_error("Tpetra::BlockMap::getFirstGlobalPointInLocalBlock ERROR: localBlockID out of range.");
00471   }
00472 
00473   return pointMap_->getGlobalElement(view_firstPointInBlock_[localBlockID]);
00474 }
00475 
00476 }//namespace Tpetra
00477 
00478 //
00479 // Explicit instantiation macro
00480 //
00481 // Must be expanded from within the Tpetra namespace!
00482 //
00483 
00484 #define TPETRA_BLOCKMAP_INSTANT(LO,GO,NODE) \
00485   \
00486   template class BlockMap< LO , GO , NODE >;
00487 
00488 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines