|
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 #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
1.7.6.1