00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #ifndef TPETRA_MULTIVECTOR_HPP
00032 #define TPETRA_MULTIVECTOR_HPP
00033
00034 #include <Teuchos_TestForException.hpp>
00035 #include <Teuchos_as.hpp>
00036 #include <Teuchos_CommHelpers.hpp>
00037 #include <Teuchos_OrdinalTraits.hpp>
00038 #include <Teuchos_Array.hpp>
00039 #include <Teuchos_Ptr.hpp>
00040 #include <Teuchos_BLAS.hpp>
00041
00042 #include "Tpetra_MultiVectorDecl.hpp"
00043 #include "Tpetra_MultiVectorData.hpp"
00044
00045 namespace Tpetra {
00046
00047 template <typename Ordinal, typename Scalar>
00048 MultiVector<Ordinal,Scalar>::MultiVector(const Map<Ordinal> &map, Ordinal NumVectors, bool zeroOut)
00049 : DistObject<Ordinal,Scalar>(map, map.getComm(), "Tpetra::MultiVector")
00050 {
00051 using Teuchos::as;
00052 TEST_FOR_EXCEPTION(NumVectors < 1, std::invalid_argument,
00053 "Tpetra::MultiVector::MultiVector(): NumVectors must be strictly positive.");
00054 const Ordinal myLen = myLength();
00055 MVData_ = Teuchos::rcp( new MultiVectorData<Ordinal,Scalar>() );
00056 MVData_->constantStride_ = true;
00057 MVData_->stride_ = myLen;
00058 MVData_->ptrs_.resize(NumVectors,Teuchos::null);
00059 if (myLen > as<Ordinal>(0)) {
00060 MVData_->values_ = Teuchos::arcp<Scalar>(NumVectors*myLen);
00061 if (zeroOut) {
00062 std::fill(MVData_->values_.begin(),MVData_->values_.end(),Teuchos::ScalarTraits<Scalar>::zero());
00063 }
00064 for (Ordinal i = as<Ordinal>(0); i < NumVectors; ++i) {
00065 MVData_->ptrs_[i] = MVData_->values_(i*myLen,myLen);
00066 }
00067 }
00068 MVData_->updateConstPointers();
00069 }
00070
00071
00072 template <typename Ordinal, typename Scalar>
00073 MultiVector<Ordinal,Scalar>::MultiVector(const MultiVector<Ordinal,Scalar> &source)
00074 : DistObject<Ordinal,Scalar>(source)
00075 {
00076
00077
00078 using Teuchos::as;
00079 const Ordinal myLen = myLength();
00080 const Ordinal numVecs = source.numVectors();
00081 MVData_ = Teuchos::rcp( new MultiVectorData<Ordinal,Scalar>() );
00082 MVData_->constantStride_ = true;
00083 MVData_->stride_ = myLen;
00084 MVData_->ptrs_.resize(numVecs,Teuchos::null);
00085 if (myLen > as<Ordinal>(0)) {
00086 MVData_->values_ = Teuchos::arcp<Scalar>(numVecs*myLen);
00087 for (Ordinal i = as<Ordinal>(0); i < numVecs; ++i) {
00088 MVData_->ptrs_[i] = MVData_->values_(i*myLen,myLen);
00089 std::copy( source.MVData_->ptrs_[i].begin(), source.MVData_->ptrs_[i].end(), MVData_->ptrs_[i].begin() );
00090 }
00091 }
00092 MVData_->updateConstPointers();
00093 }
00094
00095
00096 template <typename Ordinal, typename Scalar>
00097 MultiVector<Ordinal,Scalar>::MultiVector(const Map<Ordinal> &map, const Teuchos::ArrayView<const Scalar> &A, Ordinal LDA, Ordinal NumVectors)
00098 : DistObject<Ordinal,Scalar>(map, map.getComm(), "Tpetra::MultiVector")
00099 {
00100 using Teuchos::ArrayView;
00101 using Teuchos::as;
00102 TEST_FOR_EXCEPTION(NumVectors < 1, std::invalid_argument,
00103 "Tpetra::MultiVector::MultiVector(): NumVectors must be strictly positive.");
00104 const Ordinal myLen = myLength();
00105 #ifdef TEUCHOS_DEBUG
00106
00107 TEST_FOR_EXCEPTION(A.size() < LDA*(NumVectors-1)+myLen, std::runtime_error,
00108 "Tpetra::MultiVector::MultiVector(): A,LDA must be large enough to accomodate the local entries.");
00109 #endif
00110 TEST_FOR_EXCEPTION(LDA < myLen, std::invalid_argument,
00111 "Tpetra::MultiVector::MultiVector(): LDA must be large enough to accomodate the local entries.");
00112 MVData_ = Teuchos::rcp( new MultiVectorData<Ordinal,Scalar>() );
00113 MVData_->constantStride_ = true;
00114 MVData_->stride_ = myLen;
00115 MVData_->ptrs_.resize(NumVectors,Teuchos::null);
00116 if (myLen > as<Ordinal>(0)) {
00117 MVData_->values_ = Teuchos::arcp<Scalar>(NumVectors*myLen);
00118 for (Ordinal i = as<Ordinal>(0); i < NumVectors; ++i) {
00119 MVData_->ptrs_[i] = MVData_->values_(i*myLen,myLen);
00120
00121 ArrayView<const Scalar> Aptr = A(i*LDA,myLen);
00122 std::copy(Aptr.begin(),Aptr.end(),MVData_->ptrs_[i].begin());
00123 }
00124 }
00125 MVData_->updateConstPointers();
00126 }
00127
00128
00129 template <typename Ordinal, typename Scalar>
00130 MultiVector<Ordinal,Scalar>::MultiVector(const Map<Ordinal> &map, const Teuchos::RCP<MultiVectorData<Ordinal,Scalar> > &mvdata)
00131 : DistObject<Ordinal,Scalar>(map, map.getComm(), "Tpetra::MultiVector"), MVData_(mvdata)
00132 {}
00133
00134
00135 template <typename Ordinal, typename Scalar>
00136 MultiVector<Ordinal,Scalar>::MultiVector(const Map<Ordinal> &map, const Teuchos::ArrayView<const Teuchos::ArrayView<const Scalar> > &arrayOfArrays)
00137 : DistObject<Ordinal,Scalar>(map, map.getComm(), "Tpetra::MultiVector")
00138 {
00139 using Teuchos::as;
00140 const Ordinal myLen = myLength();
00141 Ordinal NumVectors = arrayOfArrays.size();
00142 TEST_FOR_EXCEPTION(NumVectors < 1, std::runtime_error,
00143 "Tpetra::MultiVector::MultiVector(map,arrayOfArrays): arrayOfArrays.size() must be strictly positive.");
00144 MVData_ = Teuchos::rcp( new MultiVectorData<Ordinal,Scalar>() );
00145 MVData_->constantStride_ = true;
00146 MVData_->stride_ = myLen;
00147 MVData_->ptrs_.resize(NumVectors,Teuchos::null);
00148 if (myLen > as<Ordinal>(0)) {
00149 MVData_->values_ = Teuchos::arcp<Scalar>(NumVectors*myLen);
00150 for (Ordinal i = as<Ordinal>(0); i < NumVectors; ++i) {
00151 MVData_->ptrs_[i] = MVData_->values_(i*myLen,myLen);
00152 #ifdef TEUCHOS_DEBUG
00153 TEST_FOR_EXCEPTION(arrayOfArrays[i].size() != myLength(), std::runtime_error,
00154 "Tpetra::MultiVector::MultiVector(map,arrayOfArrays): arrayOfArrays[" << i << "].size() (==" << arrayOfArrays[i].size()
00155 << ") != myLength() (==" << myLength() << ")");
00156 #endif
00157 std::copy(arrayOfArrays[i].begin(),arrayOfArrays[i].end(),MVData_->ptrs_[i].begin());
00158 }
00159 }
00160 MVData_->updateConstPointers();
00161 }
00162
00163
00164 template <typename Ordinal, typename Scalar>
00165 MultiVector<Ordinal,Scalar>::~MultiVector()
00166 {}
00167
00168
00169 template <typename Ordinal, typename Scalar>
00170 bool MultiVector<Ordinal,Scalar>::constantStride() const
00171 {
00172 return MVData_->constantStride_;
00173 }
00174
00175
00176 template <typename Ordinal, typename Scalar>
00177 Ordinal MultiVector<Ordinal,Scalar>::myLength() const
00178 {
00179 return this->getMap().getNumMyEntries();
00180 }
00181
00182
00183 template <typename Ordinal, typename Scalar>
00184 Ordinal MultiVector<Ordinal,Scalar>::globalLength() const
00185 {
00186 return this->getMap().getNumGlobalEntries();
00187 }
00188
00189
00190 template <typename Ordinal, typename Scalar>
00191 Ordinal MultiVector<Ordinal,Scalar>::stride() const
00192 {
00193 return MVData_->stride_;
00194 }
00195
00196
00197 template <typename Ordinal, typename Scalar>
00198 void MultiVector<Ordinal,Scalar>::print(std::ostream &os) const
00199 {
00200 using std::endl;
00201 Teuchos::RCP<const Teuchos::Comm<Ordinal> > comm = this->getMap().getComm();
00202 const int myImageID = comm->getRank();
00203 const int numImages = comm->getSize();
00204 for (int imageCtr = 0; imageCtr < numImages; ++imageCtr) {
00205 if (myImageID == imageCtr) {
00206 if (myImageID == 0) {
00207 os << "Number of vectors: " << numVectors() << endl;
00208 os << "Global length: " << globalLength() << endl;
00209 }
00210 os << "Local length: " << myLength() << endl;
00211 os << "Local stride: " << stride() << endl;
00212 os << "Constant stride: " << (constantStride() ? "true" : "false") << endl;
00213 }
00214
00215 comm->barrier();
00216 comm->barrier();
00217 comm->barrier();
00218 }
00219 }
00220
00221
00222 template <typename Ordinal, typename Scalar>
00223 void MultiVector<Ordinal,Scalar>::printValues(std::ostream &os) const
00224 {
00225 using std::endl;
00226 using std::setw;
00227 Teuchos::RCP<const Teuchos::Comm<Ordinal> > comm = this->getMap().getComm();
00228 const Map<Ordinal> &map = this->getMap();
00229 const int myImageID = comm->getRank();
00230 const int numImages = comm->getSize();
00231 for (int imageCtr = 0; imageCtr < numImages; ++imageCtr) {
00232 if (myImageID == imageCtr) {
00233 for (int i=0; i<myLength(); ++i) {
00234 os << setw(4) << map.getGlobalIndex(i) << "\t";
00235 for (int j=0; j<numVectors(); ++j) {
00236 os << setw(20) << MVData_->ptrs_[j][i] << " ";
00237 }
00238 os << endl;
00239 }
00240 }
00241
00242 comm->barrier();
00243 comm->barrier();
00244 comm->barrier();
00245 }
00246 }
00247
00248
00249 template<typename Ordinal, typename Scalar>
00250 bool MultiVector<Ordinal,Scalar>::checkSizes(const DistObject<Ordinal,Scalar> &sourceObj, Ordinal &packetSize)
00251 {
00252 const MultiVector<Ordinal,Scalar> &A = dynamic_cast<const MultiVector<Ordinal,Scalar>&>(sourceObj);
00253
00254 packetSize = this->numVectors();
00255 return (A.numVectors() == packetSize);
00256 }
00257
00258 template<typename Ordinal, typename Scalar>
00259 void MultiVector<Ordinal,Scalar>::copyAndPermute(
00260 const DistObject<Ordinal,Scalar> & sourceObj,
00261 Ordinal numSameIDs,
00262 const Teuchos::ArrayView<const Ordinal> &permuteToLIDs,
00263 const Teuchos::ArrayView<const Ordinal> &permuteFromLIDs)
00264 {
00265 typedef Teuchos::OrdinalTraits<Ordinal> OT;
00266 using Teuchos::ArrayView;
00267 const MultiVector<Ordinal,Scalar> &sourceMV = dynamic_cast<const MultiVector<Ordinal,Scalar> &>(sourceObj);
00268 ArrayView<Scalar> dstView(Teuchos::null);
00269 ArrayView<const Scalar> srcView(Teuchos::null);
00270 typename ArrayView<const Ordinal>::iterator pTo, pFrom;
00271 #ifdef TEUCHOS_DEBUG
00272
00273 TEST_FOR_EXCEPTION(permuteToLIDs.size() != permuteFromLIDs.size(), std::runtime_error,
00274 "Tpetra::MultiVector::copyAndPermute(): permuteToLIDs and permuteFromLIDs must have the same size.");
00275 #endif
00276
00277 for (Ordinal j = OT::zero(); j < numVectors(); ++j) {
00278
00279
00280 dstView = (*this)[j];
00281 srcView = sourceMV[j];
00282 std::copy(srcView.begin(),srcView.begin()+numSameIDs,dstView.begin());
00283
00284 for (pTo = permuteToLIDs.begin(), pFrom = permuteFromLIDs.begin();
00285 pTo != permuteToLIDs.end(); ++pTo, ++pFrom)
00286 {
00287 dstView[*pTo] = srcView[*pFrom];
00288 }
00289 }
00290 }
00291
00292
00293 template<typename Ordinal, typename Scalar>
00294 void MultiVector<Ordinal,Scalar>::packAndPrepare(
00295 const DistObject<Ordinal,Scalar> & sourceObj,
00296 const Teuchos::ArrayView<const Ordinal> &exportLIDs,
00297 const Teuchos::ArrayView<Scalar> &exports,
00298 Distributor<Ordinal> &distor)
00299 {
00300 const MultiVector<Ordinal,Scalar> &sourceMV = dynamic_cast<const MultiVector<Ordinal,Scalar> &>(sourceObj);
00301 typedef Teuchos::OrdinalTraits<Ordinal> OT;
00302 using Teuchos::ArrayView;
00303 (void)distor;
00304
00305
00306
00307
00308
00309
00310 #ifdef TEUCHOS_DEBUG
00311 TEST_FOR_EXCEPTION(exports.size() != numVectors()*exportLIDs.size(), std::runtime_error,
00312 "Tpetra::MultiVector::packAndPrepare(): sizing of exports buffer should be appropriate for the amount of data to be exported.");
00313 #endif
00314 typename ArrayView< Scalar>::iterator expptr;
00315 typename ArrayView<const Ordinal>::iterator idptr;
00316 expptr = exports.begin();
00317 for (idptr = exportLIDs.begin(); idptr != exportLIDs.end(); ++idptr) {
00318 for (Ordinal j = OT::zero(); j < numVectors(); ++j) {
00319 *expptr++ = sourceMV[j][*idptr];
00320 }
00321 }
00322 }
00323
00324
00325 template<typename Ordinal, typename Scalar>
00326 void MultiVector<Ordinal,Scalar>::unpackAndCombine(
00327 const Teuchos::ArrayView<const Ordinal> &importLIDs,
00328 const Teuchos::ArrayView<const Scalar> &imports,
00329 Distributor<Ordinal> &distor,
00330 CombineMode CM)
00331 {
00332 (void)distor;
00333 typedef Teuchos::OrdinalTraits<Ordinal> OT;
00334 using Teuchos::ArrayView;
00335
00336
00337
00338
00339
00340
00341 #ifdef TEUCHOS_DEBUG
00342 TEST_FOR_EXCEPTION(imports.size() != numVectors()*importLIDs.size(), std::runtime_error,
00343 "Tpetra::MultiVector::unpackAndCombine(): sizing of imports buffer should be appropriate for the amount of data to be exported.");
00344 #endif
00345 typename ArrayView<const Scalar>::iterator impptr;
00346 typename ArrayView<const Ordinal>::iterator idptr;
00347 impptr = imports.begin();
00348 if (CM == INSERT || CM == REPLACE)
00349 {
00350 for (idptr = importLIDs.begin(); idptr != importLIDs.end(); ++idptr) {
00351 for (Ordinal j = OT::zero(); j < numVectors(); ++j) {
00352 (*this)[j][*idptr] = *impptr++;
00353 }
00354 }
00355 }
00356 else if (CM == ADD) {
00357 for (idptr = importLIDs.begin(); idptr != importLIDs.end(); ++idptr) {
00358 for (Ordinal j = OT::zero(); j < numVectors(); ++j) {
00359 (*this)[j][*idptr] += *impptr++;
00360 }
00361 }
00362 }
00363 else {
00364 TEST_FOR_EXCEPTION(CM != ADD && CM != REPLACE && CM != INSERT, std::invalid_argument,
00365 "Tpetra::MultiVector::unpackAndCombine(): Invalid CombineMode: " << CM);
00366 }
00367 }
00368
00369
00370 template<typename Ordinal, typename Scalar>
00371 Ordinal MultiVector<Ordinal,Scalar>::numVectors() const
00372 {
00373 return Teuchos::as<Ordinal>(MVData_->ptrs_.size());
00374 }
00375
00376
00377 template<typename Ordinal, typename Scalar>
00378 void MultiVector<Ordinal,Scalar>::dot(
00379 const MultiVector<Ordinal,Scalar> &A,
00380 const Teuchos::ArrayView<Scalar> &dots) const
00381 {
00382 Teuchos::BLAS<int,Scalar> blas;
00383 const Ordinal ZERO = Teuchos::OrdinalTraits<Ordinal>::zero();
00384 const Ordinal ONE = Teuchos::OrdinalTraits<Ordinal>::one();
00385
00386
00387 const Ordinal numVecs = this->numVectors();
00388 TEST_FOR_EXCEPTION( !this->getMap().isCompatible(A.getMap()), std::runtime_error,
00389 "Tpetra::MultiVector::dots(): MultiVectors must have compatible Maps.");
00390 TEST_FOR_EXCEPTION(A.numVectors() != numVecs, std::runtime_error,
00391 "Tpetra::MultiVector::dots(): MultiVectors must have the same number of vectors.");
00392 #ifdef TEUCHOS_DEBUG
00393 TEST_FOR_EXCEPTION(dots.size() != numVecs, std::runtime_error,
00394 "Tpetra::MultiVector::dots(A,dots): dots.size() must be as large as the number of vectors in *this and A.");
00395 #endif
00396 Teuchos::Array<Scalar> ldots(numVecs);
00397 for (Ordinal i=ZERO; i<numVecs; ++i) {
00398 ldots[i] = blas.DOT(MVData_->cPtrs_[i].size(),MVData_->cPtrs_[i].getRawPtr(),ONE,A[i].getRawPtr(),ONE);
00399 }
00400 if (this->isDistributed()) {
00401
00402 Teuchos::reduceAll(*this->getMap().getComm(),Teuchos::REDUCE_SUM,numVecs,ldots.getRawPtr(),dots.getRawPtr());
00403 }
00404 else {
00405 std::copy(ldots.begin(),ldots.end(),dots.begin());
00406 }
00407 }
00408
00409
00410 template<typename Ordinal, typename Scalar>
00411 void MultiVector<Ordinal,Scalar>::norm1(
00412 const Teuchos::ArrayView<typename Teuchos::ScalarTraits<Scalar>::magnitudeType> &norms) const
00413 {
00414 Teuchos::BLAS<int,Scalar> blas;
00415 typedef typename Teuchos::ScalarTraits<Scalar>::magnitudeType Mag;
00416 const Ordinal ZERO = Teuchos::OrdinalTraits<Ordinal>::zero();
00417 const Ordinal ONE = Teuchos::OrdinalTraits<Ordinal>::one();
00418
00419
00420 const Ordinal numVecs = this->numVectors();
00421 #ifdef TEUCHOS_DEBUG
00422 TEST_FOR_EXCEPTION(norms.size() != numVecs, std::runtime_error,
00423 "Tpetra::MultiVector::norm1(norms): norms.size() must be as large as the number of vectors in *this.");
00424 #endif
00425 Teuchos::Array<Mag> lnorms(numVecs);
00426 for (Ordinal i=ZERO; i<numVecs; ++i) {
00427 lnorms[i] = blas.ASUM(MVData_->cPtrs_[i].size(),MVData_->cPtrs_[i].getRawPtr(),ONE);
00428 }
00429 if (this->isDistributed()) {
00430
00431 Teuchos::reduceAll(*this->getMap().getComm(),Teuchos::REDUCE_SUM,numVecs,lnorms.getRawPtr(),norms.getRawPtr());
00432 }
00433 else {
00434 std::copy(lnorms.begin(),lnorms.end(),norms.begin());
00435 }
00436 }
00437
00438
00439 template<typename Ordinal, typename Scalar>
00440 void MultiVector<Ordinal,Scalar>::norm2(
00441 const Teuchos::ArrayView<typename Teuchos::ScalarTraits<Scalar>::magnitudeType> &norms) const
00442 {
00443 using Teuchos::ScalarTraits;
00444 using Teuchos::ArrayView;
00445 typedef typename ScalarTraits<Scalar>::magnitudeType Mag;
00446 const Ordinal ZERO = Teuchos::OrdinalTraits<Ordinal>::zero();
00447
00448
00449 const Ordinal numVecs = this->numVectors();
00450 #ifdef TEUCHOS_DEBUG
00451 TEST_FOR_EXCEPTION(norms.size() != numVecs, std::runtime_error,
00452 "Tpetra::MultiVector::norm2(norms): norms.size() must be as large as the number of vectors in *this.");
00453 #endif
00454 Teuchos::Array<Mag> lnorms(numVecs,ScalarTraits<Mag>::zero());
00455 for (Ordinal j=ZERO; j<numVecs; ++j) {
00456 typename Teuchos::ArrayView<const Scalar>::iterator cpos = MVData_->cPtrs_[j].begin(),
00457 cend = MVData_->cPtrs_[j].end();
00458 for (; cpos != cend; ++cpos) {
00459 lnorms[j] += ScalarTraits<Scalar>::magnitude(
00460 (*cpos) * ScalarTraits<Scalar>::conjugate(*cpos)
00461 );
00462 }
00463 }
00464 if (this->isDistributed()) {
00465
00466 Teuchos::reduceAll(*this->getMap().getComm(),Teuchos::REDUCE_SUM,numVecs,lnorms.getRawPtr(),norms.getRawPtr());
00467 }
00468 else {
00469 std::copy(lnorms.begin(),lnorms.end(),norms.begin());
00470 }
00471 for (typename ArrayView<Mag>::iterator n = norms.begin(); n != norms.begin()+numVecs; ++n) {
00472 *n = ScalarTraits<Mag>::squareroot(*n);
00473 }
00474 }
00475
00476
00477 template<typename Ordinal, typename Scalar>
00478 void MultiVector<Ordinal,Scalar>::normWeighted(
00479 const MultiVector<Ordinal,Scalar> &weights,
00480 const Teuchos::ArrayView<typename Teuchos::ScalarTraits<Scalar>::magnitudeType> &norms) const
00481 {
00482 using Teuchos::ScalarTraits;
00483 using Teuchos::ArrayView;
00484 using Teuchos::ArrayRCP;
00485 using Teuchos::Array;
00486 using Teuchos::as;
00487 typedef ScalarTraits<Scalar> SCT;
00488 typedef typename SCT::magnitudeType Mag;
00489 const Ordinal ZERO = Teuchos::OrdinalTraits<Ordinal>::zero();
00490 const Ordinal ONE = Teuchos::OrdinalTraits<Ordinal>::one();
00491 const Ordinal numImages = this->getMap().getComm()->getSize();
00492 bool OneW = false;
00493 const Ordinal numVecs = this->numVectors();
00494 if (weights.numVectors() == ONE) {
00495 OneW = true;
00496 }
00497 else {
00498 TEST_FOR_EXCEPTION(weights.numVectors() != numVecs, std::runtime_error,
00499 "Tpetra::MultiVector::normWeighted(): MultiVector of weights must contain either one vector or the same number of vectors as this.");
00500 }
00501 TEST_FOR_EXCEPTION( !this->getMap().isCompatible(weights.getMap()), std::runtime_error,
00502 "Tpetra::MultiVector::normWeighted(): MultiVectors must have compatible Maps.");
00503 #ifdef TEUCHOS_DEBUG
00504 TEST_FOR_EXCEPTION(norms.size() != numVecs, std::runtime_error,
00505 "Tpetra::MultiVector::normWeighted(): norms.size() must be as large as the number of vectors in *this.");
00506 #endif
00507
00508
00509 Array<Mag> lnorms(numVecs,ScalarTraits<Mag>::zero());
00510 for (Ordinal j=ZERO; j<numVecs; ++j) {
00511 typename ArrayView<const Scalar>::iterator wpos = (OneW ? weights[0] : weights[j]).begin(),
00512 cpos = MVData_->cPtrs_[j].begin(),
00513 cend = MVData_->cPtrs_[j].end();
00514 for (; cpos != cend; ++cpos, ++wpos) {
00515 Scalar tmp = *cpos / *wpos;
00516 lnorms[j] += SCT::magnitude( tmp * SCT::conjugate(tmp) );
00517 }
00518 }
00519 if (this->isDistributed()) {
00520
00521 Teuchos::reduceAll(*this->getMap().getComm(),Teuchos::REDUCE_SUM,numVecs,lnorms.getRawPtr(),norms.getRawPtr());
00522 }
00523 else {
00524 std::copy(lnorms.begin(),lnorms.end(),norms.begin());
00525 }
00526 for (typename ArrayView<Mag>::iterator n = norms.begin(); n != norms.begin()+numVecs; ++n) {
00527 *n = ScalarTraits<Mag>::squareroot(*n/as<Mag>(numImages));
00528 }
00529 }
00530
00531
00532 template<typename Ordinal, typename Scalar>
00533 void MultiVector<Ordinal,Scalar>::normInf(
00534 const Teuchos::ArrayView<typename Teuchos::ScalarTraits<Scalar>::magnitudeType> &norms) const
00535 {
00536 Teuchos::BLAS<int,Scalar> blas;
00537 typedef typename Teuchos::ScalarTraits<Scalar>::magnitudeType Mag;
00538 const Ordinal ZERO = Teuchos::OrdinalTraits<Ordinal>::zero();
00539 const Ordinal ONE = Teuchos::OrdinalTraits<Ordinal>::one();
00540
00541
00542 const Ordinal numVecs = this->numVectors();
00543 #ifdef TEUCHOS_DEBUG
00544 TEST_FOR_EXCEPTION(norms.size() != numVecs, std::runtime_error,
00545 "Tpetra::MultiVector::normInf(norms): norms.size() must be as large as the number of vectors in *this.");
00546 #endif
00547 Teuchos::Array<Mag> lnorms(numVecs);
00548 for (Ordinal i=ZERO; i<numVecs; ++i) {
00549
00550 Ordinal ind = blas.IAMAX(MVData_->cPtrs_[i].size(),MVData_->cPtrs_[i].getRawPtr(),ONE) - ONE;
00551 lnorms[i] = Teuchos::ScalarTraits<Scalar>::magnitude( MVData_->cPtrs_[i][ind] );
00552 }
00553 if (this->isDistributed()) {
00554
00555 Teuchos::reduceAll(*this->getMap().getComm(),Teuchos::REDUCE_MAX,numVecs,lnorms.getRawPtr(),norms.getRawPtr());
00556 }
00557 else {
00558 std::copy(lnorms.begin(),lnorms.end(),norms.begin());
00559 }
00560 }
00561
00562
00563 template<typename Ordinal, typename Scalar>
00564 void MultiVector<Ordinal,Scalar>::random()
00565 {
00566 const Ordinal ZERO = Teuchos::OrdinalTraits<Ordinal>::zero();
00567 const Ordinal numVecs = this->numVectors();
00568 for (Ordinal j=ZERO; j<numVecs; ++j) {
00569 typename Teuchos::ArrayView<Scalar>::iterator cpos = MVData_->ptrs_[j].begin(),
00570 cend = MVData_->ptrs_[j].end();
00571 for (; cpos != cend; ++cpos) {
00572 *cpos = Teuchos::ScalarTraits<Scalar>::random();
00573 }
00574 }
00575 }
00576
00577
00578 template<typename Ordinal, typename Scalar>
00579 void MultiVector<Ordinal,Scalar>::putScalar(const Scalar &alpha)
00580 {
00581 using Teuchos::OrdinalTraits;
00582 using Teuchos::ArrayView;
00583 const Ordinal numVecs = this->numVectors();
00584 for (Ordinal i = OrdinalTraits<Ordinal>::zero(); i < numVecs; ++i) {
00585 ArrayView<Scalar> &curpos = MVData_->ptrs_[i];
00586 std::fill(curpos.begin(),curpos.end(),alpha);
00587 }
00588 }
00589
00590
00591 template<typename Ordinal, typename Scalar>
00592 void MultiVector<Ordinal,Scalar>::scale(const Scalar &alpha)
00593 {
00594 Teuchos::BLAS<int,Scalar> blas;
00595 using Teuchos::OrdinalTraits;
00596 const Ordinal ONE = Teuchos::OrdinalTraits<Ordinal>::one();
00597 using Teuchos::ArrayView;
00598 const Ordinal numVecs = this->numVectors();
00599 if (alpha == Teuchos::ScalarTraits<Scalar>::one()) {
00600
00601 }
00602 else if (alpha == Teuchos::ScalarTraits<Scalar>::zero()) {
00603 putScalar(alpha);
00604 }
00605 else {
00606 for (Ordinal i = OrdinalTraits<Ordinal>::zero(); i < numVecs; ++i) {
00607 ArrayView<Scalar> &curpos = MVData_->ptrs_[i];
00608 blas.SCAL(curpos.size(),alpha,curpos.getRawPtr(),ONE);
00609 }
00610 }
00611 }
00612
00613 template<typename Ordinal, typename Scalar>
00614 void MultiVector<Ordinal,Scalar>::scale(Teuchos::ArrayView<const Scalar> alphas)
00615 {
00616 Teuchos::BLAS<int,Scalar> blas;
00617 using Teuchos::OrdinalTraits;
00618 const Ordinal ONE = Teuchos::OrdinalTraits<Ordinal>::one();
00619 using Teuchos::ArrayView;
00620 const Ordinal numVecs = this->numVectors();
00621 #ifdef TEUCHOS_DEBUG
00622 TEST_FOR_EXCEPTION(alphas.size() != numVecs, std::runtime_error,
00623 "Tpetra::MultiVector::scale(alphas): alphas.size() must be as large as the number of vectors in *this.");
00624 #endif
00625 for (Ordinal i = OrdinalTraits<Ordinal>::zero(); i < numVecs; ++i) {
00626 if (alphas[i] == Teuchos::ScalarTraits<Scalar>::one()) {
00627
00628 }
00629 else if (alphas[i] == Teuchos::ScalarTraits<Scalar>::zero()) {
00630 ArrayView<Scalar> &curpos = MVData_->ptrs_[i];
00631 std::fill(curpos.begin(),curpos.end(),Teuchos::ScalarTraits<Scalar>::zero());
00632 }
00633 else {
00634 ArrayView<Scalar> &curpos = MVData_->ptrs_[i];
00635 blas.SCAL(curpos.size(),alphas[i],curpos.getRawPtr(),ONE);
00636 }
00637 }
00638 }
00639
00640 template<typename Ordinal, typename Scalar>
00641 void MultiVector<Ordinal,Scalar>::scale(const Scalar &alpha, const MultiVector<Ordinal,Scalar> &A)
00642 {
00643 Teuchos::BLAS<int,Scalar> blas;
00644 using Teuchos::OrdinalTraits;
00645 using Teuchos::ArrayView;
00646 const Ordinal numVecs = this->numVectors();
00647 TEST_FOR_EXCEPTION( !this->getMap().isCompatible(A.getMap()), std::runtime_error,
00648 "Tpetra::MultiVector::scale(): MultiVectors must have compatible Maps.");
00649 TEST_FOR_EXCEPTION(A.numVectors() != numVecs, std::runtime_error,
00650 "Tpetra::MultiVector::scale(): MultiVectors must have the same number of vectors.");
00651 const Ordinal ONE = Teuchos::OrdinalTraits<Ordinal>::one();
00652 if (alpha == Teuchos::ScalarTraits<Scalar>::zero()) {
00653 putScalar(alpha);
00654 }
00655 else if (alpha == Teuchos::ScalarTraits<Scalar>::one()) {
00656 *this = A;
00657 }
00658 else {
00659
00660 for (Ordinal i = OrdinalTraits<Ordinal>::zero(); i < numVecs; ++i) {
00661 ArrayView<Scalar> &curpos = MVData_->ptrs_[i],
00662 &Apos = A.MVData_->ptrs_[i];
00663
00664 blas.COPY(curpos.size(),Apos.getRawPtr(),ONE,curpos.getRawPtr(),ONE);
00665
00666 blas.SCAL(curpos.size(),alpha,curpos.getRawPtr(),ONE);
00667 }
00668 }
00669 }
00670
00671
00672 template<typename Ordinal, typename Scalar>
00673 void MultiVector<Ordinal,Scalar>::reciprocal(const MultiVector<Ordinal,Scalar> &A)
00674 {
00675 Teuchos::BLAS<int,Scalar> blas;
00676 using Teuchos::OrdinalTraits;
00677 using Teuchos::ScalarTraits;
00678 using Teuchos::ArrayView;
00679 const Ordinal numVecs = this->numVectors();
00680 TEST_FOR_EXCEPTION( !this->getMap().isCompatible(A.getMap()), std::runtime_error,
00681 "Tpetra::MultiVector::reciprocal(): MultiVectors must have compatible Maps.");
00682 TEST_FOR_EXCEPTION(A.numVectors() != numVecs, std::runtime_error,
00683 "Tpetra::MultiVector::reciprocal(): MultiVectors must have the same number of vectors.");
00684 for (Ordinal i = OrdinalTraits<Ordinal>::zero(); i < numVecs; ++i) {
00685 typename Teuchos::ArrayView<Scalar>::iterator curpos = MVData_->ptrs_[i].begin(),
00686 Apos = A.MVData_->ptrs_[i].begin();
00687 for (; curpos != MVData_->ptrs_[i].end(); ++curpos, ++Apos) {
00688 #ifdef TEUCHOS_DEBUG
00689 TEST_FOR_EXCEPTION( ScalarTraits<Scalar>::magnitude(*Apos) <= ScalarTraits<Scalar>::sfmin() ||
00690 *Apos == ScalarTraits<Scalar>::sfmin(), std::runtime_error,
00691 "Tpetra::MultiVector::reciprocal(): element of A was zero or too small to invert: " << *Apos );
00692 #endif
00693 *curpos = ScalarTraits<Scalar>::one()/(*Apos);
00694 }
00695 }
00696 }
00697
00698
00699 template<typename Ordinal, typename Scalar>
00700 void MultiVector<Ordinal,Scalar>::abs(const MultiVector<Ordinal,Scalar> &A)
00701 {
00702 Teuchos::BLAS<int,Scalar> blas;
00703 using Teuchos::OrdinalTraits;
00704 using Teuchos::ArrayView;
00705 const Ordinal numVecs = this->numVectors();
00706 TEST_FOR_EXCEPTION(A.numVectors() != numVecs, std::runtime_error,
00707 "Tpetra::MultiVector::abs(): MultiVectors must have the same number of vectors.");
00708 TEST_FOR_EXCEPTION( !this->getMap().isCompatible(A.getMap()), std::runtime_error,
00709 "Tpetra::MultiVector::abs(): MultiVectors must have compatible Maps.");
00710 for (Ordinal j = OrdinalTraits<Ordinal>::zero(); j < numVecs; ++j) {
00711 typename ArrayView<Scalar>::iterator curpos = MVData_->ptrs_[j].begin(),
00712 Apos = A.MVData_->ptrs_[j].begin();
00713 for (; curpos != MVData_->ptrs_[j].end(); ++curpos, ++Apos) {
00714 *curpos = Teuchos::ScalarTraits<Scalar>::magnitude(*Apos);
00715 }
00716 }
00717 }
00718
00719
00720 template<typename Ordinal, typename Scalar>
00721 void MultiVector<Ordinal,Scalar>::update(const Scalar &alpha, const MultiVector<Ordinal,Scalar> &A, const Scalar &beta)
00722 {
00723 typedef Teuchos::ScalarTraits<Scalar> ST;
00724 typedef typename Teuchos::ArrayView<Scalar>::iterator avi;
00725 typedef typename Teuchos::ArrayView<const Scalar>::iterator avci;
00726 using Teuchos::OrdinalTraits;
00727 using Teuchos::ArrayView;
00728 if (alpha == ST::zero()) {
00729 scale(beta);
00730 return;
00731 }
00732 const Ordinal numVecs = this->numVectors();
00733 TEST_FOR_EXCEPTION( !this->getMap().isCompatible(A.getMap()), std::runtime_error,
00734 "Tpetra::MultiVector::update(): MultiVectors must have compatible Maps.");
00735 TEST_FOR_EXCEPTION(A.numVectors() != numVecs, std::runtime_error,
00736 "Tpetra::MultiVector::update(): MultiVectors must have the same number of vectors.");
00737
00738 if (beta == ST::zero()) {
00739 scale(alpha,A);
00740 return;
00741 }
00742 else if (beta == ST::one()) {
00743 if (alpha == ST::one()) {
00744 for (Ordinal i = OrdinalTraits<Ordinal>::zero(); i < numVecs; ++i) {
00745 avi curpos = MVData_->ptrs_[i].begin(), cend = MVData_->ptrs_[i].end(); avci Apos = A.MVData_->cPtrs_[i].begin();
00746 for (; curpos != cend; ++curpos, ++Apos) { *curpos = (*curpos) + (*Apos); }
00747 }
00748 }
00749 else {
00750 for (Ordinal i = OrdinalTraits<Ordinal>::zero(); i < numVecs; ++i) {
00751 avi curpos = MVData_->ptrs_[i].begin(), cend = MVData_->ptrs_[i].end(); avci Apos = A.MVData_->cPtrs_[i].begin();
00752 for (; curpos != cend; ++curpos, ++Apos) { *curpos = (*curpos) + alpha*(*Apos); }
00753 }
00754 }
00755 }
00756 else {
00757 if (alpha == ST::one()) {
00758 for (Ordinal i = OrdinalTraits<Ordinal>::zero(); i < numVecs; ++i) {
00759 avi curpos = MVData_->ptrs_[i].begin(), cend = MVData_->ptrs_[i].end(); avci Apos = A.MVData_->cPtrs_[i].begin();
00760 for (; curpos != cend; ++curpos, ++Apos) { *curpos = beta*(*curpos) + (*Apos); }
00761 }
00762 }
00763 else {
00764 for (Ordinal i = OrdinalTraits<Ordinal>::zero(); i < numVecs; ++i) {
00765 avi curpos = MVData_->ptrs_[i].begin(), cend = MVData_->ptrs_[i].end(); avci Apos = A.MVData_->cPtrs_[i].begin();
00766 for (; curpos != cend; ++curpos, ++Apos) { *curpos = beta*(*curpos) + alpha*(*Apos); }
00767 }
00768 }
00769 }
00770 }
00771
00772
00773 template<typename Ordinal, typename Scalar>
00774 void MultiVector<Ordinal,Scalar>::update(const Scalar &alpha, const MultiVector<Ordinal,Scalar> &A, const Scalar &beta, const MultiVector<Ordinal,Scalar> &B, const Scalar &gamma)
00775 {
00776 typedef typename Teuchos::ArrayView<Scalar>::iterator avi;
00777 typedef typename Teuchos::ArrayView<const Scalar>::iterator avci;
00778 typedef Teuchos::ScalarTraits<Scalar> ST;
00779 using Teuchos::OrdinalTraits;
00780 using Teuchos::ArrayRCP;
00781 if (alpha == ST::zero()) {
00782 update(beta,B,gamma);
00783 return;
00784 }
00785 else if (beta == ST::zero()) {
00786 update(alpha,A,gamma);
00787 return;
00788 }
00789 const Ordinal numVecs = this->numVectors();
00790 TEST_FOR_EXCEPTION( !this->getMap().isCompatible(A.getMap()) || !this->getMap().isCompatible(B.getMap()),
00791 std::runtime_error,
00792 "Tpetra::MultiVector::update(): MultiVectors must have compatible Maps.");
00793 TEST_FOR_EXCEPTION(A.numVectors() != numVecs || B.numVectors() != numVecs, std::runtime_error,
00794 "Tpetra::MultiVector::update(): MultiVectors must have the same number of vectors.");
00795
00796
00797 Teuchos::Ptr<const MultiVector<Ordinal,Scalar> > Aptr = Teuchos::ptr(&A), Bptr = Teuchos::ptr(&B);
00798 Teuchos::Ptr<const Scalar> lalpha = Teuchos::ptr(&alpha),
00799 lbeta = Teuchos::ptr(&beta);
00800 if (alpha!=ST::one() && beta==ST::one()) {
00801
00802 Aptr = Teuchos::ptr(&B);
00803 Bptr = Teuchos::ptr(&A);
00804 lalpha = Teuchos::ptr(&beta);
00805 lbeta = Teuchos::ptr(&alpha);
00806 }
00807
00808 if (gamma == ST::zero()) {
00809 if (*lalpha == ST::one()) {
00810 if (*lbeta == ST::one()) {
00811 for (Ordinal i = OrdinalTraits<Ordinal>::zero(); i < numVecs; ++i) {
00812 avi curpos = MVData_->ptrs_[i].begin(), cend = MVData_->ptrs_[i].end(); avci Apos = Aptr->MVData_->cPtrs_[i].begin(), Bpos = Bptr->MVData_->cPtrs_[i].begin();
00813 for (; curpos != cend; ++curpos, ++Apos, ++Bpos) { *curpos = (*Apos) + (*Bpos); }
00814 }
00815 }
00816 else {
00817 for (Ordinal i = OrdinalTraits<Ordinal>::zero(); i < numVecs; ++i) {
00818 avi curpos = MVData_->ptrs_[i].begin(), cend = MVData_->ptrs_[i].end(); avci Apos = Aptr->MVData_->cPtrs_[i].begin(), Bpos = Bptr->MVData_->cPtrs_[i].begin();
00819 for (; curpos != cend; ++curpos, ++Apos, ++Bpos) { *curpos = (*Apos) + (*lbeta)*(*Bpos); }
00820 }
00821 }
00822 }
00823 else {
00824 for (Ordinal i = OrdinalTraits<Ordinal>::zero(); i < numVecs; ++i) {
00825 avi curpos = MVData_->ptrs_[i].begin(), cend = MVData_->ptrs_[i].end(); avci Apos = Aptr->MVData_->cPtrs_[i].begin(), Bpos = Bptr->MVData_->cPtrs_[i].begin();
00826 for (; curpos != cend; ++curpos, ++Apos, ++Bpos) { *curpos = (*lalpha)*(*Apos) + (*lbeta)*(*Bpos); }
00827 }
00828 }
00829 }
00830 else if (gamma == ST::one()) {
00831 if ((*lalpha) == ST::one()) {
00832 if ((*lbeta) == ST::one()) {
00833 for (Ordinal i = OrdinalTraits<Ordinal>::zero(); i < numVecs; ++i) {
00834 avi curpos = MVData_->ptrs_[i].begin(), cend = MVData_->ptrs_[i].end(); avci Apos = Aptr->MVData_->cPtrs_[i].begin(), Bpos = Bptr->MVData_->cPtrs_[i].begin();
00835 for (; curpos != cend; ++curpos, ++Apos, ++Bpos) { *curpos = (*curpos) + (*Apos) + (*Bpos); }
00836 }
00837 }
00838 else {
00839 for (Ordinal i = OrdinalTraits<Ordinal>::zero(); i < numVecs; ++i) {
00840 avi curpos = MVData_->ptrs_[i].begin(), cend = MVData_->ptrs_[i].end(); avci Apos = Aptr->MVData_->cPtrs_[i].begin(), Bpos = Bptr->MVData_->cPtrs_[i].begin();
00841 for (; curpos != cend; ++curpos, ++Apos, ++Bpos) { *curpos = (*curpos) + (*Apos) + (*lbeta)*(*Bpos); }
00842 }
00843 }
00844 }
00845 else {
00846 for (Ordinal i = OrdinalTraits<Ordinal>::zero(); i < numVecs; ++i) {
00847 avi curpos = MVData_->ptrs_[i].begin(), cend = MVData_->ptrs_[i].end(); avci Apos = Aptr->MVData_->cPtrs_[i].begin(), Bpos = Bptr->MVData_->cPtrs_[i].begin();
00848 for (; curpos != cend; ++curpos, ++Apos, ++Bpos) { *curpos = (*curpos) + (*lalpha)*(*Apos) + (*lbeta)*(*Bpos); }
00849 }
00850 }
00851 }
00852 else {
00853 if ((*lalpha) == ST::one()) {
00854 if ((*lbeta) == ST::one()) {
00855 for (Ordinal i = OrdinalTraits<Ordinal>::zero(); i < numVecs; ++i) {
00856 avi curpos = MVData_->ptrs_[i].begin(), cend = MVData_->ptrs_[i].end(); avci Apos = Aptr->MVData_->cPtrs_[i].begin(), Bpos = Bptr->MVData_->cPtrs_[i].begin();
00857 for (; curpos != cend; ++curpos, ++Apos, ++Bpos) { *curpos = gamma*(*curpos) + (*Apos) + (*Bpos); }
00858 }
00859 }
00860 else {
00861 for (Ordinal i = OrdinalTraits<Ordinal>::zero(); i < numVecs; ++i) {
00862 avi curpos = MVData_->ptrs_[i].begin(), cend = MVData_->ptrs_[i].end(); avci Apos = Aptr->MVData_->cPtrs_[i].begin(), Bpos = Bptr->MVData_->cPtrs_[i].begin();
00863 for (; curpos != cend; ++curpos, ++Apos, ++Bpos) { *curpos = gamma*(*curpos) + (*Apos) + (*lbeta)*(*Bpos); }
00864 }
00865 }
00866 }
00867 else {
00868 for (Ordinal i = OrdinalTraits<Ordinal>::zero(); i < numVecs; ++i) {
00869 avi curpos = MVData_->ptrs_[i].begin(), cend = MVData_->ptrs_[i].end(); avci Apos = Aptr->MVData_->cPtrs_[i].begin(), Bpos = Bptr->MVData_->cPtrs_[i].begin();
00870 for (; curpos != cend; ++curpos, ++Apos, ++Bpos) { *curpos = gamma*(*curpos) + (*lalpha)*(*Apos) + (*lbeta)*(*Bpos); }
00871 }
00872 }
00873 }
00874 }
00875
00876
00877 template<typename Ordinal, typename Scalar>
00878 Teuchos::ArrayView<const Scalar> MultiVector<Ordinal,Scalar>::operator[](Ordinal i) const
00879 {
00880
00881 return MVData_->cPtrs_[i];
00882 }
00883
00884 template<typename Ordinal, typename Scalar>
00885 Teuchos::ArrayView<Scalar> MultiVector<Ordinal,Scalar>::operator[](Ordinal i)
00886 {
00887
00888 return MVData_->ptrs_[i];
00889 }
00890
00891 template<typename Ordinal, typename Scalar>
00892 MultiVector<Ordinal,Scalar>& MultiVector<Ordinal,Scalar>::operator=(const MultiVector<Ordinal,Scalar> &source) {
00893
00894 if (this != &source) {
00895 TEST_FOR_EXCEPTION( !this->getMap().isCompatible(source.getMap()), std::runtime_error,
00896 "Tpetra::MultiVector::operator=(): MultiVectors must have compatible Maps.");
00897 if (constantStride() && source.constantStride() && myLength()==stride() && source.myLength()==source.stride()) {
00898
00899 std::copy( source.MVData_->values_.begin(), source.MVData_->values_.begin() + source.numVectors()*source.stride(),
00900 MVData_->values_.begin() );
00901 }
00902 else {
00903 for (Ordinal j=0; j<numVectors(); ++j) {
00904 std::copy( source.MVData_->ptrs_[j].begin(), source.MVData_->ptrs_[j].end(),
00905 MVData_->ptrs_[j].begin() );
00906 }
00907 }
00908 }
00909 return(*this);
00910 }
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922 template<typename Ordinal, typename Scalar>
00923 Teuchos::RCP<MultiVector<Ordinal,Scalar> > MultiVector<Ordinal,Scalar>::subCopy(const Teuchos::ArrayView<const Teuchos_Index> &cols) const
00924 {
00925
00926 Ordinal numCols = cols.size();
00927
00928 const bool zeroData = false;
00929 Teuchos::RCP<MultiVector<Ordinal,Scalar> > mv = rcp( new MultiVector<Ordinal,Scalar>(this->getMap(),numCols,zeroData) );
00930
00931 for (Ordinal j=0; j<numCols; ++j)
00932 {
00933 std::copy( MVData_->ptrs_[cols[j]].begin(), MVData_->ptrs_[cols[j]].end(), mv->MVData_->ptrs_[j].begin() );
00934 }
00935 return mv;
00936 }
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950 template<typename Ordinal, typename Scalar>
00951 Teuchos::RCP<MultiVector<Ordinal,Scalar> > MultiVector<Ordinal,Scalar>::subView(const Teuchos::ArrayView<const Teuchos_Index> &cols)
00952 {
00953 using Teuchos::as;
00954 const Ordinal numVecs = cols.size();
00955 Teuchos::RCP<MultiVectorData<Ordinal,Scalar> > mvdata = Teuchos::rcp( new MultiVectorData<Ordinal,Scalar>() );
00956
00957 mvdata->constantStride_ = false;
00958 mvdata->values_ = MVData_->values_;
00959 mvdata->stride_ = stride();
00960 mvdata->ptrs_.resize(numVecs,Teuchos::null);
00961 for (Ordinal j = as<Ordinal>(0); j < numVecs; ++j) {
00962 mvdata->ptrs_[j] = MVData_->ptrs_[cols[j]];
00963 }
00964 mvdata->updateConstPointers();
00965 Teuchos::RCP<MultiVector<Ordinal,Scalar> > mv = Teuchos::rcp( new MultiVector<Ordinal,Scalar>(this->getMap(),mvdata) );
00966 return mv;
00967 }
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981 template<typename Ordinal, typename Scalar>
00982 Teuchos::RCP<const MultiVector<Ordinal,Scalar> > MultiVector<Ordinal,Scalar>::subViewConst(const Teuchos::ArrayView<const Teuchos_Index> &cols) const
00983 {
00984 using Teuchos::as;
00985 const Ordinal numVecs = cols.size();
00986 Teuchos::RCP<MultiVectorData<Ordinal,Scalar> > mvdata = Teuchos::rcp( new MultiVectorData<Ordinal,Scalar>() );
00987 mvdata->constantStride_ = false;
00988 mvdata->stride_ = stride();
00989 mvdata->values_ = MVData_->values_;
00990 mvdata->ptrs_.resize(numVecs,Teuchos::null);
00991 for (Ordinal j = as<Ordinal>(0); j < numVecs; ++j) {
00992 mvdata->ptrs_[j] = MVData_->ptrs_[cols[j]];
00993 }
00994 mvdata->updateConstPointers();
00995 Teuchos::RCP<MultiVector<Ordinal,Scalar> > mv = Teuchos::rcp( new MultiVector<Ordinal,Scalar>(this->getMap(),mvdata) );
00996 return mv;
00997 }
00998
00999 template<typename Ordinal, typename Scalar>
01000 void MultiVector<Ordinal,Scalar>::extractCopy(Teuchos::ArrayView<Scalar> A, Ordinal &MyLDA) const
01001 {
01002 TEST_FOR_EXCEPTION(constantStride() == false, std::runtime_error,
01003 "MultiVector::extractCopy(A,LDA): only supported for constant stride multivectors.");
01004 #ifdef TEUCHOS_DEBUG
01005 TEST_FOR_EXCEPTION(A.size() != stride()*numVectors(), std::runtime_error,
01006 "MultiVector::extractCopy(A,LDA): A must be large enough to hold contents of MultiVector.");
01007 #endif
01008 MyLDA = stride();
01009 std::copy(MVData_->values_.begin(), MVData_->values_.begin()+stride()*numVectors(),
01010 A.begin());
01011 }
01012
01013 template<typename Ordinal, typename Scalar>
01014 void MultiVector<Ordinal,Scalar>::extractCopy(Teuchos::ArrayView<const Teuchos::ArrayView<Scalar> > arrayOfArrays) const
01015 {
01016 #ifdef TEUCHOS_DEBUG
01017 TEST_FOR_EXCEPTION(arrayOfArrays.size() != numVectors(), std::runtime_error,
01018 "Tpetra::MultiVector::extractCopy(arrayOfArrays): arrayOfArrays.size() (==" << arrayOfArrays.size() << ") must match"
01019 "numVectors() (==" << numVectors() << ")");
01020 for (typename Teuchos::ArrayView<const Teuchos::ArrayView<Scalar> >::iterator it=arrayOfArrays.begin();
01021 it != arrayOfArrays.end(); ++it) {
01022 TEST_FOR_EXCEPTION(it->size() != myLength(), std::runtime_error,
01023 "Tpetra::MultiVector::extractCopy(arrayOfArrays): ArrayView's size (=="
01024 << it->size() << ") must match local MultiVector length (==" << myLength() << ")");
01025 }
01026 #endif
01027
01028 for (Ordinal i=0; i<numVectors(); ++i) {
01029 std::copy(MVData_->ptrs_[i].begin(), MVData_->ptrs_[i].end(), arrayOfArrays[i].begin());
01030 }
01031 }
01032
01033 template<typename Ordinal, typename Scalar>
01034 void MultiVector<Ordinal,Scalar>::extractView(Teuchos::ArrayView<Scalar> &A, Ordinal &MyLDA)
01035 {
01036 TEST_FOR_EXCEPTION(constantStride() == false, std::runtime_error,
01037 "MultiVector::extractView(A,LDA): only supported for constant stride multivectors.");
01038 A = MVData_->values_;
01039 MyLDA = MVData_->stride_;
01040 }
01041
01042 template<typename Ordinal, typename Scalar>
01043 void MultiVector<Ordinal,Scalar>::extractConstView(Teuchos::ArrayView<const Scalar> &A, Ordinal &MyLDA) const
01044 {
01045 TEST_FOR_EXCEPTION(constantStride() == false, std::runtime_error,
01046 "MultiVector::extractConstView(A,LDA): only supported for constant stride multivectors.");
01047 A = MVData_->values_.getConst();
01048 MyLDA = MVData_->stride_;
01049 }
01050
01051 template<typename Ordinal, typename Scalar>
01052 Teuchos::ArrayView<const Teuchos::ArrayView<Scalar> > MultiVector<Ordinal,Scalar>::extractView()
01053 {
01054 return MVData_->ptrs_().getConst();
01055 }
01056
01057 template<typename Ordinal, typename Scalar>
01058 Teuchos::ArrayView<const Teuchos::ArrayView<const Scalar> > MultiVector<Ordinal,Scalar>::extractConstView() const
01059 {
01060 return MVData_->cPtrs_().getConst();
01061 }
01062
01063 template<typename Ordinal, typename Scalar>
01064 void MultiVector<Ordinal,Scalar>::multiply(Teuchos::ETransp transA, Teuchos::ETransp transB, const Scalar &alpha, const MultiVector<Ordinal,Scalar> &A, const MultiVector<Ordinal,Scalar> &B, const Scalar &beta)
01065 {
01066
01067
01068
01069
01070
01071 using Teuchos::NO_TRANS;
01072 using Teuchos::TRANS;
01073 using Teuchos::CONJ_TRANS;
01074 using Teuchos::null;
01075 using Teuchos::ScalarTraits;
01076 using Teuchos::OrdinalTraits;
01077 using Teuchos::as;
01078 using Teuchos::RCP;
01079 using Teuchos::ArrayRCP;
01080 using Teuchos::Array;
01081 using Teuchos::ArrayView;
01082 using Teuchos::rcp;
01083 using Teuchos::arcp;
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104 std::string errPrefix("Tpetra::MultiVector::multiply(transOpA,transOpB,A,B): ");
01105
01106 TEST_FOR_EXCEPTION( ScalarTraits<Scalar>::isComplex && (transA == TRANS || transB == TRANS), std::invalid_argument,
01107 errPrefix << "non-conjugate transpose not supported for complex types.");
01108 transA = (transA == NO_TRANS ? NO_TRANS : CONJ_TRANS);
01109 transB = (transB == NO_TRANS ? NO_TRANS : CONJ_TRANS);
01110
01111
01112 Ordinal A_nrows = (transA==CONJ_TRANS) ? A.numVectors() : A.myLength();
01113 Ordinal A_ncols = (transA==CONJ_TRANS) ? A.myLength() : A.numVectors();
01114 Ordinal B_nrows = (transB==CONJ_TRANS) ? B.numVectors() : B.myLength();
01115 Ordinal B_ncols = (transB==CONJ_TRANS) ? B.myLength() : B.numVectors();
01116
01117 Scalar beta_local = beta;
01118
01119 TEST_FOR_EXCEPTION( myLength() != A_nrows || numVectors() != B_ncols || A_ncols != B_nrows, std::runtime_error,
01120 errPrefix << "dimension of *this, op(A) and op(B) must be consistent.");
01121
01122 bool A_is_local = !A.isDistributed();
01123 bool B_is_local = !B.isDistributed();
01124 bool C_is_local = !this->isDistributed();
01125 bool Case1 = ( C_is_local && A_is_local && B_is_local);
01126 bool Case2 = ( C_is_local && !A_is_local && !B_is_local && transA==CONJ_TRANS && transB==NO_TRANS);
01127 bool Case3 = (!C_is_local && !A_is_local && B_is_local && transA==NO_TRANS );
01128
01129
01130 TEST_FOR_EXCEPTION( !Case1 && !Case2 && !Case3, std::runtime_error,
01131 errPrefix << "multiplication of op(A) and op(B) into *this is not a supported use case.");
01132
01133 if (beta != ScalarTraits<Scalar>::zero() && Case2)
01134 {
01135
01136
01137
01138
01139 int MyPID = this->getMap().getComm()->getRank();
01140 if (MyPID!=0) beta_local = ScalarTraits<Scalar>::zero();
01141 }
01142
01143
01144 RCP<const MultiVector<Ordinal,Scalar> > Atmp, Btmp;
01145 RCP<MultiVector<Ordinal,Scalar> > Ctmp;
01146 if (constantStride() == false) Ctmp = rcp(new MultiVector<Ordinal,Scalar>(*this));
01147 else Ctmp = rcp(this,false);
01148
01149 if (A.constantStride() == false) Atmp = rcp(new MultiVector<Ordinal,Scalar>(A));
01150 else Atmp = rcp(&A,false);
01151
01152 if (B.constantStride() == false) Btmp = rcp(new MultiVector<Ordinal,Scalar>(B));
01153 else Btmp = rcp(&B,false);
01154
01155 #ifdef TEUCHOS_DEBUG
01156 TEST_FOR_EXCEPTION(!Ctmp->constantStride() || !Btmp->constantStride() || !Atmp->constantStride(), std::logic_error,
01157 errPrefix << "failed making temporary strided copies of input multivectors.");
01158 #endif
01159
01160 Ordinal m = this->myLength();
01161 Ordinal n = this->numVectors();
01162 Ordinal k = A_ncols;
01163 Ordinal lda, ldb, ldc;
01164 ArrayView<const Scalar> Ap(Teuchos::null), Bp(Teuchos::null);
01165 ArrayView<Scalar> Cp(Teuchos::null);
01166 Atmp->extractConstView(Ap,lda);
01167 Btmp->extractConstView(Bp,ldb);
01168 Ctmp->extractView(Cp,ldc);
01169
01170 Teuchos::BLAS<int,Scalar> blas;
01171
01172 blas.GEMM(transA,transB,m,n,k,alpha,Ap.getRawPtr(),lda,Bp.getRawPtr(),ldb,beta_local,Cp.getRawPtr(),ldc);
01173
01174
01175 Atmp = null;
01176 Btmp = null;
01177
01178
01179 if (constantStride() == false) {
01180 Array<ArrayView<Scalar> > aoa(MVData_->ptrs_.size(),null);
01181 for (Ordinal i=0; i<as<Ordinal>(aoa.size()); ++i) {
01182 aoa[i] = MVData_->ptrs_[i]();
01183 }
01184 Ctmp->extractCopy(aoa());
01185 }
01186 Ctmp = null;
01187
01188
01189 if (Case2)
01190 {
01191 RCP<const Teuchos::Comm<Ordinal> > comm = this->getMap().getComm();
01192
01193
01194
01195
01196
01197 ArrayRCP<Scalar> source = arcp<Scalar>(m*n), target;
01198 bool packed = constantStride() && (stride() == m);
01199 if (packed) {
01200
01201
01202 std::copy(MVData_->values_.begin(),MVData_->values_.begin()+m*n,
01203 source.begin());
01204
01205 target = MVData_->values_;
01206 }
01207 else {
01208
01209 ArrayRCP<Scalar> sptr = source;
01210 for (Ordinal j=OrdinalTraits<Ordinal>::zero(); j<n; ++j)
01211 {
01212
01213 std::copy(MVData_->ptrs_[j].begin(),MVData_->ptrs_[j].begin()+m,
01214 sptr.begin());
01215
01216 sptr += m;
01217 }
01218
01219 target = arcp<Scalar>(m*n);
01220 }
01221
01222 Teuchos::reduceAll<Ordinal,Scalar>(*comm,Teuchos::REDUCE_SUM,m*n,source.getRawPtr(),target.getRawPtr());
01223 if (!packed) {
01224
01225 ArrayRCP<Scalar> tptr = target;
01226 for (Ordinal j=OrdinalTraits<Ordinal>::zero(); j<n; ++j)
01227 {
01228 std::copy(tptr.begin(),tptr.begin()+m,
01229 MVData_->ptrs_[j].begin()
01230 );
01231 tptr += m;
01232 }
01233 }
01234
01235 source = null;
01236 target = null;
01237 }
01238 }
01239
01240
01241 template<typename Ordinal, typename Scalar>
01242 void MultiVector<Ordinal,Scalar>::reduce()
01243 {
01244 using Teuchos::as;
01245 typedef Teuchos::OrdinalTraits<Ordinal> OT;
01246
01247 TEST_FOR_EXCEPTION(this->isDistributed() == true, std::runtime_error,
01248 "Tpetra::MultiVector::reduce() should only be called for non-distributed MultiVectors.");
01249
01250
01251
01252
01253 Ordinal bufsize = myLength() * numVectors();
01254 Teuchos::ArrayRCP<Scalar> sndbuf, rcvbuf;
01255 if (constantStride() == true) {
01256 sndbuf = Teuchos::arcpClone<Scalar>(MVData_->values_());
01257 #ifdef TEUCHOS_DEBUG
01258 TEST_FOR_EXCEPTION(sndbuf.size() != MVData_->values_.size(), std::logic_error,
01259 "Tpetra::MultiVector::reduce(): Error in Tpetra. Please contact Tpetra developers.");
01260 #endif
01261 rcvbuf = MVData_->values_;
01262 }
01263 else {
01264 sndbuf = Teuchos::arcp<Scalar>(bufsize);
01265 rcvbuf = Teuchos::arcp<Scalar>(bufsize);
01266 Teuchos::ArrayRCP<Scalar> sndptr = sndbuf;
01267 for (Ordinal j=OT::zero(); j<numVectors(); ++j) {
01268 Teuchos::ArrayView<const Scalar> jvec = (*this)[j];
01269 std::copy(jvec.begin(),jvec.end(),sndptr);
01270 sndptr += myLength();
01271 }
01272 }
01273 Teuchos::reduceAll(*(this->getMap().getComm()), Teuchos::REDUCE_SUM, bufsize, sndbuf().getConst().getRawPtr(), rcvbuf.getRawPtr() );
01274 if (constantStride() == false) {
01275 Teuchos::ArrayRCP<const Scalar> rcvptr = rcvbuf;
01276 for (Ordinal j=OT::zero(); j<numVectors(); ++j) {
01277 Teuchos::ArrayView<Scalar> jvec = (*this)[j];
01278 std::copy(rcvptr.begin(),rcvptr.begin()+myLength(),jvec.begin());
01279 rcvptr += myLength();
01280 }
01281 }
01282 }
01283
01284 template<typename Ordinal, typename Scalar>
01285 void MultiVector<Ordinal,Scalar>::replaceMap(const Map<Ordinal> &map)
01286 {
01287 TEST_FOR_EXCEPT(true);
01288 }
01289
01290 template<typename Ordinal, typename Scalar>
01291 void MultiVector<Ordinal,Scalar>::replaceMyValue(Ordinal MyRow, Ordinal VectorIndex, const Scalar &ScalarValue)
01292 {
01293 #ifdef TEUCHOS_DEBUG
01294 TEST_FOR_EXCEPTION(MyRow < this->getMap().getMinLocalIndex() || MyRow > this->getMap().getMaxLocalIndex(), std::runtime_error,
01295 "Tpetra::MultiVector::replaceMyValue(): row index is invalid.");
01296 TEST_FOR_EXCEPTION(VectorIndex < 0 || VectorIndex >= numVectors(), std::runtime_error,
01297 "Tpetra::MultiVector::replaceMyValue(): vector index is invalid.");
01298 #endif
01299 MVData_->ptrs_[VectorIndex][MyRow] = ScalarValue;
01300 }
01301
01302 template<typename Ordinal, typename Scalar>
01303 void MultiVector<Ordinal,Scalar>::sumIntoMyValue(Ordinal MyRow, Ordinal VectorIndex, const Scalar &ScalarValue)
01304 {
01305 #ifdef TEUCHOS_DEBUG
01306 TEST_FOR_EXCEPTION(MyRow < this->getMap().getMinLocalIndex() || MyRow > this->getMap().getMaxLocalIndex(), std::runtime_error,
01307 "Tpetra::MultiVector::sumIntoMyValue(): row index is invalid.");
01308 TEST_FOR_EXCEPTION(VectorIndex < 0 || VectorIndex >= numVectors(), std::runtime_error,
01309 "Tpetra::MultiVector::sumIntoMyValue(): vector index is invalid.");
01310 #endif
01311 MVData_->ptrs_[VectorIndex][MyRow] += ScalarValue;
01312 }
01313
01314 template<typename Ordinal, typename Scalar>
01315 void MultiVector<Ordinal,Scalar>::replaceGlobalValue(Ordinal GlobalRow, Ordinal VectorIndex, const Scalar &ScalarValue)
01316 {
01317 #ifdef TEUCHOS_DEBUG
01318 TEST_FOR_EXCEPTION(!this->getMap().isMyGlobalIndex(GlobalRow), std::runtime_error,
01319 "Tpetra::MultiVector::replaceGlobalValue(): row index is not present on this processor.");
01320 TEST_FOR_EXCEPTION(VectorIndex < 0 || VectorIndex >= numVectors(), std::runtime_error,
01321 "Tpetra::MultiVector::replaceGlobalValue(): vector index is invalid.");
01322 #endif
01323 Ordinal MyRow = this->getMap().getLocalIndex(GlobalRow);
01324 MVData_->ptrs_[VectorIndex][MyRow] = ScalarValue;
01325 }
01326
01327 template<typename Ordinal, typename Scalar>
01328 void MultiVector<Ordinal,Scalar>::sumIntoGlobalValue(Ordinal GlobalRow, Ordinal VectorIndex, const Scalar &ScalarValue)
01329 {
01330 #ifdef TEUCHOS_DEBUG
01331 TEST_FOR_EXCEPTION(!this->getMap().isMyGlobalIndex(GlobalRow), std::runtime_error,
01332 "Tpetra::MultiVector::sumIntoGlobalValue(): row index is not present on this processor.");
01333 TEST_FOR_EXCEPTION(VectorIndex < 0 || VectorIndex >= numVectors(), std::runtime_error,
01334 "Tpetra::MultiVector::sumIntoGlobalValue(): vector index is invalid.");
01335 #endif
01336 Ordinal MyRow = this->getMap().getLocalIndex(GlobalRow);
01337 MVData_->ptrs_[VectorIndex][MyRow] += ScalarValue;
01338 }
01339
01340 }
01341
01342 #endif // TPETRA_MULTIVECTOR_HPP