Tpetra Matrix/Vector Services  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
Tpetra_Experimental_BlockMultiVector_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_EXPERIMENTAL_BLOCKMULTIVECTOR_DEF_HPP
00043 #define TPETRA_EXPERIMENTAL_BLOCKMULTIVECTOR_DEF_HPP
00044 
00045 #ifdef DOXYGEN_USE_ONLY
00046 #  include "Tpetra_Experimental_BlockMultiVector_decl.hpp"
00047 #endif
00048 
00049 namespace Tpetra {
00050 namespace Experimental {
00051 
00052 template<class Scalar, class LO, class GO, class Node>
00053 typename BlockMultiVector<Scalar, LO, GO, Node>::mv_type
00054 BlockMultiVector<Scalar, LO, GO, Node>::
00055 getMultiVectorView ()
00056 {
00057   // Make sure that mv_ has view semantics.
00058   mv_.setCopyOrView (Teuchos::View);
00059   // Now the one-argument copy constructor will make a shallow copy,
00060   // and those view semantics will persist in all of its offspring.
00061   return mv_;
00062 }
00063 
00064 template<class Scalar, class LO, class GO, class Node>
00065 Teuchos::RCP<const BlockMultiVector<Scalar, LO, GO, Node> >
00066 BlockMultiVector<Scalar, LO, GO, Node>::
00067 getBlockMultiVectorFromSrcDistObject (const Tpetra::SrcDistObject& src)
00068 {
00069   typedef BlockMultiVector<Scalar, LO, GO, Node> BMV;
00070   const BMV* src_bmv = dynamic_cast<const BMV*> (&src);
00071   TEUCHOS_TEST_FOR_EXCEPTION(
00072     src_bmv == NULL, std::invalid_argument, "Tpetra::Experimental::"
00073     "BlockMultiVector: The source object of an Import or Export to a "
00074     "BlockMultiVector, must also be a BlockMultiVector.");
00075   return Teuchos::rcp (src_bmv, false); // nonowning RCP
00076 }
00077 
00078 template<class Scalar, class LO, class GO, class Node>
00079 BlockMultiVector<Scalar, LO, GO, Node>::
00080 BlockMultiVector (const map_type& meshMap,
00081                   const LO blockSize,
00082                   const LO numVecs) :
00083   dist_object_type (Teuchos::rcp (new map_type (meshMap))), // shallow copy
00084   meshMap_ (meshMap),
00085   pointMap_ (makePointMap (meshMap, blockSize)),
00086   mv_ (Teuchos::rcpFromRef (pointMap_), numVecs), // nonowning RCP is OK, since pointMap_ won't go away
00087   mvData_ (mv_.get1dViewNonConst ().getRawPtr ()),
00088   blockSize_ (blockSize)
00089 {
00090   // Make sure that mv_ has view semantics.
00091   mv_.setCopyOrView (Teuchos::View);
00092 }
00093 
00094 template<class Scalar, class LO, class GO, class Node>
00095 BlockMultiVector<Scalar, LO, GO, Node>::
00096 BlockMultiVector (const map_type& meshMap,
00097                   const map_type& pointMap,
00098                   const LO blockSize,
00099                   const LO numVecs) :
00100   dist_object_type (Teuchos::rcp (new map_type (meshMap))), // shallow copy
00101   meshMap_ (meshMap),
00102   pointMap_ (pointMap),
00103   mv_ (Teuchos::rcpFromRef (pointMap_), numVecs),
00104   mvData_ (mv_.get1dViewNonConst ().getRawPtr ()),
00105   blockSize_ (blockSize)
00106 {
00107   // Make sure that mv_ has view semantics.
00108   mv_.setCopyOrView (Teuchos::View);
00109 }
00110 
00111 template<class Scalar, class LO, class GO, class Node>
00112 BlockMultiVector<Scalar, LO, GO, Node>::
00113 BlockMultiVector (const mv_type& X_mv,
00114                   const map_type& meshMap,
00115                   const LO blockSize) :
00116   dist_object_type (Teuchos::rcp (new map_type (meshMap))), // shallow copy
00117   meshMap_ (meshMap),
00118   mvData_ (NULL), // just for now
00119   blockSize_ (blockSize)
00120 {
00121   using Teuchos::RCP;
00122 
00123   if (X_mv.getCopyOrView () == Teuchos::View) {
00124     // The input MultiVector has view semantics, so assignment just
00125     // does a shallow copy.
00126     mv_ = X_mv;
00127   }
00128   else if (X_mv.getCopyOrView () == Teuchos::Copy) {
00129     // The input MultiVector has copy semantics.  We can't change
00130     // that, but we can make a view of the input MultiVector and
00131     // change the view to have view semantics.  (That sounds silly;
00132     // shouldn't views always have view semantics? but remember that
00133     // "view semantics" just governs the default behavior of the copy
00134     // constructor and assignment operator.)
00135     RCP<const mv_type> X_view_const;
00136     const size_t numCols = X_mv.getNumVectors ();
00137     if (numCols == 0) {
00138       Teuchos::Array<size_t> cols (0); // view will have zero columns
00139       X_view_const = X_mv.subView (cols ());
00140     } else { // Range1D is an inclusive range
00141       X_view_const = X_mv.subView (Teuchos::Range1D (0, numCols-1));
00142     }
00143     TEUCHOS_TEST_FOR_EXCEPTION(
00144       X_view_const.is_null (), std::logic_error, "Tpetra::Experimental::"
00145       "BlockMultiVector constructor: X_mv.subView(...) returned null.  This "
00146       "should never happen.  Please report this bug to the Tpetra developers.");
00147 
00148     // It's perfectly OK to cast away const here.  Those view methods
00149     // should be marked const anyway, because views can't change the
00150     // allocation (just the entries themselves).
00151     RCP<mv_type> X_view = Teuchos::rcp_const_cast<mv_type> (X_view_const);
00152     X_view->setCopyOrView (Teuchos::View);
00153     TEUCHOS_TEST_FOR_EXCEPTION(
00154       X_view->getCopyOrView () != Teuchos::View, std::logic_error, "Tpetra::"
00155       "Experimental::BlockMultiVector constructor: We just set a MultiVector "
00156       "to have view semantics, but it claims that it doesn't have view "
00157       "semantics.  This should never happen.  "
00158       "Please report this bug to the Tpetra developers.");
00159     mv_ = *X_view; // MultiVector::operator= does a shallow copy here
00160   }
00161 
00162   // At this point, mv_ has been assigned, so we can ignore X_mv.
00163   Teuchos::RCP<const map_type> pointMap = mv_.getMap ();
00164   if (! pointMap.is_null ()) {
00165     pointMap_ = *pointMap; // Map::operator= also does a shallow copy
00166   }
00167   mvData_ = mv_.get1dViewNonConst ().getRawPtr ();
00168 }
00169 
00170 template<class Scalar, class LO, class GO, class Node>
00171 BlockMultiVector<Scalar, LO, GO, Node>::
00172 BlockMultiVector () :
00173   dist_object_type (Teuchos::null),
00174   mvData_ (NULL),
00175   blockSize_ (0)
00176 {
00177   // Make sure that mv_ has view semantics.
00178   mv_.setCopyOrView (Teuchos::View);
00179 }
00180 
00181 template<class Scalar, class LO, class GO, class Node>
00182 typename BlockMultiVector<Scalar, LO, GO, Node>::map_type
00183 BlockMultiVector<Scalar, LO, GO, Node>::
00184 makePointMap (const map_type& meshMap, const LO blockSize)
00185 {
00186   typedef Tpetra::global_size_t GST;
00187   typedef typename Teuchos::ArrayView<const GO>::size_type size_type;
00188 
00189   const GST gblNumMeshMapInds =
00190     static_cast<GST> (meshMap.getGlobalNumElements ());
00191   const size_t lclNumMeshMapIndices =
00192     static_cast<size_t> (meshMap.getNodeNumElements ());
00193   const GST gblNumPointMapInds =
00194     gblNumMeshMapInds * static_cast<GST> (blockSize);
00195   const size_t lclNumPointMapInds =
00196     lclNumMeshMapIndices * static_cast<size_t> (blockSize);
00197   const GO indexBase = meshMap.getIndexBase ();
00198 
00199   if (meshMap.isContiguous ()) {
00200     return map_type (gblNumPointMapInds, lclNumPointMapInds, indexBase,
00201                      meshMap.getComm (), meshMap.getNode ());
00202   }
00203   else {
00204     // "Hilbert's Hotel" trick: multiply each process' GIDs by
00205     // blockSize, and fill in.  That ensures correctness even if the
00206     // mesh Map is overlapping.
00207     Teuchos::ArrayView<const GO> lclMeshGblInds = meshMap.getNodeElementList ();
00208     const size_type lclNumMeshGblInds = lclMeshGblInds.size ();
00209     Teuchos::Array<GO> lclPointGblInds (lclNumPointMapInds);
00210     for (size_type g = 0; g < lclNumMeshGblInds; ++g) {
00211       const GO meshGid = lclMeshGblInds[g];
00212       const GO pointGidStart = indexBase + (meshGid - indexBase) * static_cast<GO> (blockSize);
00213       const size_type offset = g * static_cast<size_type> (blockSize);
00214       for (LO k = 0; k < blockSize; ++k) {
00215         const GO pointGid = pointGidStart + static_cast<GO> (k);
00216         lclPointGblInds[offset + static_cast<size_type> (k)] = pointGid;
00217       }
00218     }
00219 
00220     return map_type (gblNumPointMapInds, lclPointGblInds (), indexBase,
00221                      meshMap.getComm (), meshMap.getNode ());
00222   }
00223 }
00224 
00225 
00226 template<class Scalar, class LO, class GO, class Node>
00227 void
00228 BlockMultiVector<Scalar, LO, GO, Node>::
00229 replaceLocalValuesImpl (const LO localRowIndex,
00230                         const LO colIndex,
00231                         const Scalar vals[]) const
00232 {
00233   little_vec_type X_dst = getLocalBlock (localRowIndex, colIndex);
00234   const LO strideX = 1;
00235   const_little_vec_type X_src (vals, getBlockSize (), strideX);
00236   X_dst.assign (X_src);
00237 }
00238 
00239 
00240 template<class Scalar, class LO, class GO, class Node>
00241 bool
00242 BlockMultiVector<Scalar, LO, GO, Node>::
00243 replaceLocalValues (const LO localRowIndex,
00244                     const LO colIndex,
00245                     const Scalar vals[]) const
00246 {
00247   if (! meshMap_.isNodeLocalElement (localRowIndex)) {
00248     return false;
00249   } else {
00250     replaceLocalValuesImpl (localRowIndex, colIndex, vals);
00251     return true;
00252   }
00253 }
00254 
00255 template<class Scalar, class LO, class GO, class Node>
00256 bool
00257 BlockMultiVector<Scalar, LO, GO, Node>::
00258 replaceGlobalValues (const GO globalRowIndex,
00259                      const LO colIndex,
00260                      const Scalar vals[]) const
00261 {
00262   const LO localRowIndex = meshMap_.getLocalElement (globalRowIndex);
00263   if (localRowIndex == Teuchos::OrdinalTraits<LO>::invalid ()) {
00264     return false;
00265   } else {
00266     replaceLocalValuesImpl (localRowIndex, colIndex, vals);
00267     return true;
00268   }
00269 }
00270 
00271 template<class Scalar, class LO, class GO, class Node>
00272 void
00273 BlockMultiVector<Scalar, LO, GO, Node>::
00274 sumIntoLocalValuesImpl (const LO localRowIndex,
00275                         const LO colIndex,
00276                         const Scalar vals[]) const
00277 {
00278   little_vec_type X_dst = getLocalBlock (localRowIndex, colIndex);
00279   const LO strideX = 1;
00280   const_little_vec_type X_src (vals, getBlockSize (), strideX);
00281 
00282   X_dst.update (STS::one (), X_src);
00283 }
00284 
00285 template<class Scalar, class LO, class GO, class Node>
00286 bool
00287 BlockMultiVector<Scalar, LO, GO, Node>::
00288 sumIntoLocalValues (const LO localRowIndex,
00289                     const LO colIndex,
00290                     const Scalar vals[]) const
00291 {
00292   if (! meshMap_.isNodeLocalElement (localRowIndex)) {
00293     return false;
00294   } else {
00295     sumIntoLocalValuesImpl (localRowIndex, colIndex, vals);
00296     return true;
00297   }
00298 }
00299 
00300 template<class Scalar, class LO, class GO, class Node>
00301 bool
00302 BlockMultiVector<Scalar, LO, GO, Node>::
00303 sumIntoGlobalValues (const GO globalRowIndex, const LO colIndex, const Scalar vals[]) const {
00304   const LO localRowIndex = meshMap_.getLocalElement (globalRowIndex);
00305   if (localRowIndex == Teuchos::OrdinalTraits<LO>::invalid ()) {
00306     return false;
00307   } else {
00308     sumIntoLocalValuesImpl (localRowIndex, colIndex, vals);
00309     return true;
00310   }
00311 }
00312 
00313 template<class Scalar, class LO, class GO, class Node>
00314 bool
00315 BlockMultiVector<Scalar, LO, GO, Node>::
00316 getLocalRowView (const LO localRowIndex, const LO colIndex, Scalar*& vals) const
00317 {
00318   if (! meshMap_.isNodeLocalElement (localRowIndex)) {
00319     return false;
00320   } else {
00321     little_vec_type X_ij = getLocalBlock (localRowIndex, colIndex);
00322     vals = X_ij.getRawPtr ();
00323     return true;
00324   }
00325 }
00326 
00327 template<class Scalar, class LO, class GO, class Node>
00328 bool
00329 BlockMultiVector<Scalar, LO, GO, Node>::
00330 getGlobalRowView (const GO globalRowIndex, const LO colIndex, Scalar*& vals) const
00331 {
00332   const LO localRowIndex = meshMap_.getLocalElement (globalRowIndex);
00333   if (localRowIndex == Teuchos::OrdinalTraits<LO>::invalid ()) {
00334     return false;
00335   } else {
00336     little_vec_type X_ij = getLocalBlock (localRowIndex, colIndex);
00337     vals = X_ij.getRawPtr ();
00338     return true;
00339   }
00340 }
00341 
00342 template<class Scalar, class LO, class GO, class Node>
00343 typename BlockMultiVector<Scalar, LO, GO, Node>::little_vec_type
00344 BlockMultiVector<Scalar, LO, GO, Node>::
00345 getLocalBlock (const LO localRowIndex,
00346                const LO colIndex) const
00347 {
00348   if (! isValidLocalMeshIndex (localRowIndex)) {
00349     return little_vec_type (NULL, 0, 0);
00350   } else {
00351     const LO strideX = this->getStrideX ();
00352     const size_t blockSize = getBlockSize ();
00353     const size_t offset = colIndex * this->getStrideY () +
00354       localRowIndex * blockSize * strideX;
00355     return little_vec_type (this->getRawPtr () + offset, blockSize, strideX);
00356   }
00357 }
00358 
00359 template<class Scalar, class LO, class GO, class Node>
00360 Teuchos::RCP<const typename BlockMultiVector<Scalar, LO, GO, Node>::mv_type>
00361 BlockMultiVector<Scalar, LO, GO, Node>::
00362 getMultiVectorFromSrcDistObject (const Tpetra::SrcDistObject& src)
00363 {
00364   using Teuchos::rcp;
00365   using Teuchos::rcpFromRef;
00366 
00367   // The source object of an Import or Export must be a
00368   // BlockMultiVector or MultiVector (a Vector is a MultiVector).  Try
00369   // them in that order; one must succeed.  Note that the target of
00370   // the Import or Export calls checkSizes in DistObject's doTransfer.
00371   typedef BlockMultiVector<Scalar, LO, GO, Node> this_type;
00372   const this_type* srcBlkVec = dynamic_cast<const this_type*> (&src);
00373   if (srcBlkVec == NULL) {
00374     const mv_type* srcMultiVec = dynamic_cast<const mv_type*> (&src);
00375     if (srcMultiVec == NULL) {
00376       // FIXME (mfh 05 May 2014) Tpetra::MultiVector's operator=
00377       // currently does a shallow copy by default.  This is why we
00378       // return by RCP, rather than by value.
00379       return rcp (new mv_type ());
00380     } else { // src is a MultiVector
00381       return rcp (srcMultiVec, false); // nonowning RCP
00382     }
00383   } else { // src is a BlockMultiVector
00384     return rcpFromRef (srcBlkVec->mv_); // nonowning RCP
00385   }
00386 }
00387 
00388 template<class Scalar, class LO, class GO, class Node>
00389 bool BlockMultiVector<Scalar, LO, GO, Node>::
00390 checkSizes (const Tpetra::SrcDistObject& src)
00391 {
00392   return ! getMultiVectorFromSrcDistObject (src).is_null ();
00393 }
00394 
00395 template<class Scalar, class LO, class GO, class Node>
00396 void BlockMultiVector<Scalar, LO, GO, Node>::
00397 copyAndPermute (const Tpetra::SrcDistObject& src,
00398                 size_t numSameIDs,
00399                 const Teuchos::ArrayView<const LO>& permuteToLIDs,
00400                 const Teuchos::ArrayView<const LO>& permuteFromLIDs)
00401 {
00402   const char tfecfFuncName[] = "copyAndPermute";
00403   TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
00404     permuteToLIDs.size() != permuteFromLIDs.size(), std::runtime_error,
00405     ": permuteToLIDs and permuteFromLIDs must have the same size."
00406     << std::endl << "permuteToLIDs.size() = " << permuteToLIDs.size ()
00407     << " != permuteFromLIDs.size() = " << permuteFromLIDs.size () << ".");
00408 
00409   typedef BlockMultiVector<Scalar, LO, GO, Node> BMV;
00410   Teuchos::RCP<const BMV> srcAsBmvPtr = getBlockMultiVectorFromSrcDistObject (src);
00411   TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
00412     srcAsBmvPtr.is_null (), std::invalid_argument,
00413     ": The source of an Import or Export to a BlockMultiVector "
00414     "must also be a BlockMultiVector.");
00415   const BMV& srcAsBmv = *srcAsBmvPtr;
00416 
00417   // FIXME (mfh 23 Apr 2014) This implementation is sequential and
00418   // assumes UVM.
00419 
00420   const LO numVecs = getNumVectors ();
00421   const LO numSame = static_cast<LO> (numSameIDs);
00422   for (LO j = 0; j < numVecs; ++j) {
00423     for (LO lclRow = 0; lclRow < numSame; ++lclRow) {
00424       getLocalBlock (lclRow, j).assign (srcAsBmv.getLocalBlock (lclRow, j));
00425     }
00426   }
00427 
00428   // FIXME (mfh 20 June 2012) For an Export with duplicate GIDs on the
00429   // same process, this merges their values by replacement of the last
00430   // encountered GID, not by the specified merge rule (such as ADD).
00431   const LO numPermuteLIDs = static_cast<LO> (permuteToLIDs.size ());
00432   for (LO j = 0; j < numVecs; ++j) {
00433     for (LO k = numSame; k < numPermuteLIDs; ++k) {
00434       getLocalBlock (permuteToLIDs[k], j).assign (srcAsBmv.getLocalBlock (permuteFromLIDs[k], j));
00435     }
00436   }
00437 }
00438 
00439 template<class Scalar, class LO, class GO, class Node>
00440 void BlockMultiVector<Scalar, LO, GO, Node>::
00441 packAndPrepare (const Tpetra::SrcDistObject& src,
00442                 const Teuchos::ArrayView<const LO>& exportLIDs,
00443                 Teuchos::Array<packet_type>& exports,
00444                 const Teuchos::ArrayView<size_t>& /* numPacketsPerLID */,
00445                 size_t& constantNumPackets,
00446                 Tpetra::Distributor& /* distor */)
00447 {
00448   typedef BlockMultiVector<Scalar, LO, GO, Node> BMV;
00449   typedef typename Teuchos::ArrayView<const LO>::size_type size_type;
00450   const char tfecfFuncName[] = "packAndPrepare";
00451 
00452   Teuchos::RCP<const BMV> srcAsBmvPtr = getBlockMultiVectorFromSrcDistObject (src);
00453   TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
00454     srcAsBmvPtr.is_null (), std::invalid_argument,
00455     ": The source of an Import or Export to a BlockMultiVector "
00456     "must also be a BlockMultiVector.");
00457   const BMV& srcAsBmv = *srcAsBmvPtr;
00458 
00459   const LO numVecs = getNumVectors ();
00460   const LO blockSize = getBlockSize ();
00461 
00462   // Number of things to pack per LID is the block size, times the
00463   // number of columns.  Input LIDs correspond to the mesh points, not
00464   // the degrees of freedom (DOFs).
00465   constantNumPackets =
00466     static_cast<size_t> (blockSize) * static_cast<size_t> (numVecs);
00467   const size_type numMeshLIDs = exportLIDs.size ();
00468 
00469   const size_type requiredExportsSize = numMeshLIDs *
00470     static_cast<size_type> (blockSize) * static_cast<size_type> (numVecs);
00471   exports.resize (requiredExportsSize);
00472 
00473   try {
00474     size_type curExportPos = 0;
00475     for (size_type meshLidIndex = 0; meshLidIndex < numMeshLIDs; ++meshLidIndex) {
00476       for (LO j = 0; j < numVecs; ++j, curExportPos += blockSize) {
00477         const LO meshLid = exportLIDs[meshLidIndex];
00478         Scalar* const curExportPtr = &exports[curExportPos];
00479         little_vec_type X_dst (curExportPtr, blockSize, 1);
00480         little_vec_type X_src = srcAsBmv.getLocalBlock (meshLid, j);
00481 
00482         X_dst.assign (X_src);
00483       }
00484     }
00485   } catch (std::exception& e) {
00486     TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
00487       true, std::logic_error, ": Oh no!  packAndPrepare on Process "
00488       << meshMap_.getComm ()->getRank () << " raised the following exception: "
00489       << e.what ());
00490   }
00491 }
00492 
00493 template<class Scalar, class LO, class GO, class Node>
00494 void BlockMultiVector<Scalar, LO, GO, Node>::
00495 unpackAndCombine (const Teuchos::ArrayView<const LO>& importLIDs,
00496                   const Teuchos::ArrayView<const packet_type>& imports,
00497                   const Teuchos::ArrayView<size_t>& numPacketsPerLID,
00498                   size_t constantNumPackets,
00499                   Tpetra::Distributor& distor,
00500                   Tpetra::CombineMode CM)
00501 {
00502   typedef typename Teuchos::ArrayView<const LO>::size_type size_type;
00503   const char tfecfFuncName[] = "unpackAndCombine";
00504 
00505   TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
00506     CM != ADD && CM != REPLACE && CM != INSERT && CM != ABSMAX && CM != ZERO,
00507     std::invalid_argument, ": Invalid CombineMode: " << CM << ".  Valid "
00508     "CombineMode values are ADD, REPLACE, INSERT, ABSMAX, and ZERO.");
00509 
00510   if (CM == ZERO) {
00511     return; // Combining does nothing, so we don't have to combine anything.
00512   }
00513 
00514   // Number of things to pack per LID is the block size.
00515   // Input LIDs correspond to the mesh points, not the DOFs.
00516   const size_type numMeshLIDs = importLIDs.size ();
00517   const LO blockSize = getBlockSize ();
00518   const LO numVecs = getNumVectors ();
00519 
00520   const size_type requiredImportsSize = numMeshLIDs *
00521     static_cast<size_type> (blockSize) * static_cast<size_type> (numVecs);
00522   TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
00523     imports.size () < requiredImportsSize, std::logic_error,
00524     ": imports.size () = " << imports.size ()
00525     << " < requiredImportsSize = " << requiredImportsSize << ".");
00526 
00527   size_type curImportPos = 0;
00528   for (size_type meshLidIndex = 0; meshLidIndex < numMeshLIDs; ++meshLidIndex) {
00529     for (LO j = 0; j < numVecs; ++j, curImportPos += blockSize) {
00530       const LO meshLid = importLIDs[meshLidIndex];
00531       const Scalar* const curImportPtr = &imports[curImportPos];
00532 
00533       const_little_vec_type X_src (curImportPtr, blockSize, 1);
00534       little_vec_type X_dst = getLocalBlock (meshLid, j);
00535 
00536       if (CM == INSERT || CM == REPLACE) {
00537         X_dst.assign (X_src);
00538       } else if (CM == ADD) {
00539         X_dst.update (STS::one (), X_src);
00540       } else if (CM == ABSMAX) {
00541         X_dst.absmax (X_src);
00542       }
00543     }
00544   }
00545 }
00546 
00547 template<class Scalar, class LO, class GO, class Node>
00548 void BlockMultiVector<Scalar, LO, GO, Node>::
00549 putScalar (const Scalar& val)
00550 {
00551   getMultiVectorView ().putScalar (val);
00552 }
00553 
00554 template<class Scalar, class LO, class GO, class Node>
00555 void BlockMultiVector<Scalar, LO, GO, Node>::
00556 scale (const Scalar& val)
00557 {
00558   getMultiVectorView ().scale (val);
00559 }
00560 
00561 } // namespace Experimental
00562 } // namespace Tpetra
00563 
00564 //
00565 // Explicit instantiation macro
00566 //
00567 // Must be expanded from within the Tpetra namespace!
00568 //
00569 #define TPETRA_EXPERIMENTAL_BLOCKMULTIVECTOR_INSTANT(S,LO,GO,NODE) \
00570   template class Experimental::BlockMultiVector< S, LO, GO, NODE >;
00571 
00572 #endif // TPETRA_EXPERIMENTAL_BLOCKMULTIVECTOR_DEF_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines