AnasaziMVOPTester.hpp

Go to the documentation of this file.
00001 // @HEADER
00002 // ***********************************************************************
00003 //
00004 //                 Anasazi: Block Eigensolvers Package
00005 //                 Copyright (2004) Sandia Corporation
00006 //
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 //
00010 // This library is free software; you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as
00012 // published by the Free Software Foundation; either version 2.1 of the
00013 // License, or (at your option) any later version.
00014 //
00015 // This library is distributed in the hope that it will be useful, but
00016 // WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 // Lesser General Public License for more details.
00019 //
00020 // You should have received a copy of the GNU Lesser General Public
00021 // License along with this library; if not, write to the Free Software
00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00023 // USA
00024 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
00025 //
00026 // ***********************************************************************
00027 // @HEADER
00028 //
00029 #ifndef ANASAZI_MVOPTESTER_HPP
00030 #define ANASAZI_MVOPTESTER_HPP
00031 
00032 // Assumptions that I have made:
00033 // * I assume/verify that a multivector must have at least one vector. This seems 
00034 //   to be consistent with Epetra_MultiVec.
00035 // * I do not assume that an operator is deterministic; I do assume that the
00036 //   operator, applied to 0, will return 0.
00037 
00046 #include "AnasaziConfigDefs.hpp"
00047 #include "AnasaziTypes.hpp"
00048 
00049 #include "AnasaziMultiVecTraits.hpp"
00050 #include "AnasaziOperatorTraits.hpp"
00051 #include "AnasaziOutputManager.hpp"
00052 
00053 #include "Teuchos_RCP.hpp"
00054 
00055 
00056 namespace Anasazi {
00057 
00063   template< class ScalarType, class MV >
00064   bool TestMultiVecTraits( 
00065                 const Teuchos::RCP<OutputManager<ScalarType> > &om,
00066                 const Teuchos::RCP<const MV> &A ) {
00067 
00068     using std::endl;
00069 
00070     /* MVT Contract:
00071 
00072          Clone(MV,int)
00073          CloneCopy(MV)
00074          CloneCopy(MV,vector<int>)
00075            USER: will request positive number of vectors
00076              MV: will return a multivector with exactly the number of
00077                    requested vectors.
00078                  vectors are the same dimension as the cloned MV
00079          
00080 
00081          CloneView(MV,vector<int>) [const and non-const]
00082            USER: There is no assumed communication between creation and
00083            destruction of a view. I.e., after a view is created, changes to the
00084            source multivector are not reflected in the view. Likewise, until
00085            destruction of the view, changes in the view are not reflected in the
00086            source multivector.
00087 
00088          GetVecLength 
00089              MV: will always be positive (MV cannot have zero vectors)
00090 
00091          GetNumberVecs 
00092              MV: will always be positive (MV cannot have zero vectors)
00093 
00094          MvAddMv 
00095            USER: multivecs will be of the same dimension and same number of vecs
00096              MV: input vectors will not be modified
00097                  performing C=0*A+1*B will assign B to C exactly
00098          
00099          MvTimesMatAddMv
00100            USER: multivecs and serialdensematrix will be of the proper shape
00101              MV: input arguments will not be modified
00102                  following arithmetic relations hold exactly:
00103                    A*I = A
00104                    0*B = B
00105                    1*B = B
00106 
00107          MvTransMv 
00108            USER: SerialDenseMatrix will be large enough to hold results.
00109              MV: SerialDenseMatrix will not be resized.
00110                  Inner products will satisfy |a'*b| <= |a|*|b|
00111                  alpha == 0  =>  SerialDenseMatrix == 0
00112 
00113          MvDot 
00114           USER: Results vector will be large enough for results.
00115                 Both multivectors will have the same number of vectors.
00116                     (Epetra crashes, otherwise.)
00117             MV: Inner products will satisfy |a'*b| <= |a|*|b|
00118                 Results vector will not be resized.
00119 
00120          MvNorm 
00121              MV: vector norm is always non-negative, and zero
00122                    only for zero vectors.
00123                  results vector should not be resized
00124 
00125          SetBlock 
00126           USER: indices will be distinct
00127             MV: assigns copies of the vectors to the specified
00128                 locations, leaving the other vectors untouched.
00129 
00130          MvRandom 
00131              MV: Generate zero vector with "zero" probability
00132                  Don't gen the same vectors twice.
00133 
00134          MvInit 
00135              MV: Init(alpha) sets all elements to alpha
00136 
00137          MvPrint
00138              MV: routine does not modify vectors (not tested here)
00139     *********************************************************************/
00140 
00141     typedef MultiVecTraits<ScalarType, MV>    MVT;
00142     typedef Teuchos::ScalarTraits<ScalarType> SCT;
00143     typedef typename SCT::magnitudeType       MagType;
00144 
00145     const ScalarType one      = SCT::one();
00146     const ScalarType zero     = SCT::zero();
00147     const MagType    zero_mag = Teuchos::ScalarTraits<MagType>::zero();
00148 
00149     // Don't change these two without checking the initialization of ind below
00150     const int numvecs   = 10;
00151     const int numvecs_2 = 5;
00152 
00153     int i,j;
00154     std::vector<int> ind(numvecs_2);
00155 
00156     /* Initialize indices for selected copies/views
00157        The MVT specialization should not assume that 
00158        these are ordered or even distinct.
00159        Also retrieve the edges.
00160 
00161        However, to spice things up, grab the first vector,
00162        last vector, and choose the others randomly.
00163     */
00164     ind[0] = 0;
00165     ind[numvecs_2-1] = numvecs-1;
00166     for (i=1; i<numvecs_2-1; i++) {
00167       ind[i] = rand() % numvecs;
00168     }
00169 
00170 
00171     /*********** GetNumberVecs() *****************************************
00172        Verify:
00173        1) This number should be strictly positive
00174     *********************************************************************/
00175     if ( MVT::GetNumberVecs(*A) <= 0 ) {
00176       om->stream(Warnings)
00177         << "*** ERROR *** MultiVectorTraits::GetNumberVecs()." << endl
00178         << "Returned <= 0." << endl;
00179       return false;
00180     }
00181 
00182 
00183     /*********** GetVecLength() ******************************************
00184        Verify:
00185        1) This number should be strictly positive
00186     *********************************************************************/
00187     if ( MVT::GetVecLength(*A) <= 0 ) {
00188       om->stream(Warnings)
00189         << "*** ERROR *** MultiVectorTraits::GetVecLength()" << endl
00190         << "Returned <= 0." << endl;
00191       return false;
00192     }
00193 
00194 
00195     /*********** Clone() and MvNorm() ************************************
00196        Verify:
00197        1) Clone() allows us to specify the number of vectors
00198        2) Clone() returns a multivector of the same dimension
00199        3) Vector norms shouldn't be negative
00200        4) MvNorm result vector should not be resized
00201     *********************************************************************/
00202     {
00203       Teuchos::RCP<MV> B = MVT::Clone(*A,numvecs);
00204       std::vector<MagType> norms(2*numvecs);
00205       bool ResizeWarning = false;
00206       if ( MVT::GetNumberVecs(*B) != numvecs ) {
00207         om->stream(Warnings)
00208           << "*** ERROR *** MultiVecTraits::Clone()." << endl
00209           << "Did not allocate requested number of vectors." << endl;
00210         return false;
00211       }
00212       if ( MVT::GetVecLength(*B) != MVT::GetVecLength(*A) ) {
00213         om->stream(Warnings)
00214           << "*** ERROR *** MultiVecTraits::Clone()." << endl
00215           << "Did not allocate requested number of vectors." << endl;
00216         return false;
00217       }
00218       MVT::MvNorm(*B, &norms);
00219       if ( norms.size() != 2*numvecs && ResizeWarning==false ) {
00220         om->stream(Warnings)
00221           << "*** WARNING *** MultiVecTraits::MvNorm()." << endl
00222           << "Method resized the output vector." << endl;
00223         ResizeWarning = true;
00224       }
00225       for (i=0; i<numvecs; i++) {
00226         if ( norms[i] < zero_mag ) {
00227           om->stream(Warnings)
00228             << "*** ERROR *** MultiVecTraits::Clone()." << endl
00229             << "Vector had negative norm." << endl;
00230           return false;
00231         }
00232       }
00233     }
00234 
00235 
00236     /*********** MvRandom() and MvNorm() and MvInit() ********************
00237        Verify:
00238        1) Set vectors to zero
00239        2) Check that norm is zero
00240        3) Perform MvRandom. 
00241        4) Verify that vectors aren't zero anymore
00242        5) Perform MvRandom again. 
00243        6) Verify that vector norms are different than before
00244        
00245        Without knowing something about the random distribution, 
00246        this is about the best that we can do, to make sure that MvRandom 
00247        did at least *something*.
00248        
00249        Also, make sure vector norms aren't negative.
00250     *********************************************************************/
00251     {
00252       Teuchos::RCP<MV> B = MVT::Clone(*A,numvecs);
00253       std::vector<MagType> norms(numvecs), norms2(numvecs);
00254 
00255       MVT::MvInit(*B);
00256       MVT::MvNorm(*B, &norms);
00257       for (i=0; i<numvecs; i++) {
00258         if ( norms[i] != zero_mag ) {
00259           om->stream(Warnings)
00260             << "*** ERROR *** MultiVecTraits::MvInit() "
00261             << "and MultiVecTraits::MvNorm()" << endl
00262             << "Supposedly zero vector has non-zero norm." << endl;
00263           return false;
00264         }
00265       }
00266       MVT::MvRandom(*B);
00267       MVT::MvNorm(*B, &norms);
00268       MVT::MvRandom(*B);
00269       MVT::MvNorm(*B, &norms2);
00270       for (i=0; i<numvecs; i++) {
00271         if ( norms[i] == zero_mag || norms2[i] == zero_mag ) {
00272           om->stream(Warnings)
00273             << "*** ERROR *** MultiVecTraits::MvRandom()." << endl
00274             << "Random vector was empty (very unlikely)." << endl;
00275           return false;
00276         }
00277         else if ( norms[i] < zero_mag || norms2[i] < zero_mag ) {
00278           om->stream(Warnings)
00279             << "*** ERROR *** MultiVecTraits::MvRandom()." << endl
00280             << "Vector had negative norm." << endl;
00281           return false;
00282         }
00283         else if ( norms[i] == norms2[i] ) {
00284           om->stream(Warnings)
00285             << "*** ERROR *** MutliVecTraits::MvRandom()." << endl
00286             << "Vectors not random enough." << endl;
00287           return false;
00288         }
00289       }
00290     }
00291 
00292 
00293     /*********** MvInit() and MvNorm() ***********************************
00294        A vector of ones of dimension n should have norm sqrt(n)
00295        1) Init vectors to all ones
00296        2) Verify that norm is sqrt(n)
00297        3) Verify that norms aren't negative
00298 
00299        Note: I'm not sure that we can expect this to hold in practice.
00300               Maybe something like abs(norm-sqrt(n)) < SCT::eps()  ???
00301               The sum of 1^2==1 should be n, but what about sqrt(n)?
00302               They may be using a different square root than ScalartTraits
00303               On my iBook G4 and on jeter, this test works.
00304               Right now, this has been demoted to a warning.
00305     *********************************************************************/
00306     {
00307       Teuchos::RCP<MV> B = MVT::Clone(*A,numvecs);
00308       std::vector<MagType> norms(numvecs);
00309 
00310       MVT::MvInit(*B,one);
00311       MVT::MvNorm(*B, &norms);
00312       bool BadNormWarning = false;
00313       for (i=0; i<numvecs; i++) {
00314         if ( norms[i] < zero_mag ) {
00315           om->stream(Warnings)
00316             << "*** ERROR *** MultiVecTraits::MvRandom()." << endl
00317             << "Vector had negative norm." << endl;
00318           return false;
00319         }
00320         else if ( norms[i] != SCT::squareroot(MVT::GetVecLength(*B)) && !BadNormWarning ) {
00321           om->stream(Warnings)
00322             << endl
00323             << "Warning testing MultiVecTraits::MvInit()." << endl
00324             << "Ones vector should have norm sqrt(dim)." << endl
00325             << "norms[i]: " << norms[i] << "\tdim: " << MVT::GetVecLength(*B) << endl << endl;
00326           BadNormWarning = true;
00327         }
00328       }
00329     }
00330 
00331 
00332     /*********** MvInit() and MvNorm() ***********************************
00333        A vector of zeros of dimension n should have norm 0
00334        1) Verify that norms aren't negative
00335        2) Verify that norms are zero
00336 
00337        We must know this works before the next tests.
00338     *********************************************************************/
00339     {
00340       Teuchos::RCP<MV> B = MVT::Clone(*A,numvecs);
00341       std::vector<MagType> norms(numvecs);
00342       MVT::MvInit(*B, zero_mag);
00343       MVT::MvNorm(*B, &norms);
00344       for (i=0; i<numvecs; i++) {
00345         if ( norms[i] < zero_mag ) {
00346           om->stream(Warnings)
00347             << "*** ERROR *** MultiVecTraits::MvInit()." << endl
00348             << "Vector had negative norm." << endl;
00349           return false;
00350         }
00351         else if ( norms[i] != zero_mag ) {
00352           om->stream(Warnings)
00353             << "*** ERROR *** MultiVecTraits::MvInit()." << endl
00354             << "Zero vector should have norm zero." << endl;
00355           return false;
00356         }
00357       }
00358     }
00359 
00360 
00361     /*********** CloneCopy(MV,vector<int>) and MvNorm ********************
00362        1) Check quantity/length of vectors
00363        2) Check vector norms for agreement
00364        3) Zero out B and make sure that C norms are not affected
00365     *********************************************************************/
00366     {
00367       Teuchos::RCP<MV> B, C;
00368       std::vector<MagType> norms(numvecs), norms2(numvecs);
00369 
00370       B = MVT::Clone(*A,numvecs);
00371       MVT::MvRandom(*B);
00372       MVT::MvNorm(*B, &norms);
00373       C = MVT::CloneCopy(*B,ind);
00374       MVT::MvNorm(*C, &norms2);
00375       if ( MVT::GetNumberVecs(*C) != numvecs_2 ) {
00376         om->stream(Warnings)
00377           << "*** ERROR *** MultiVecTraits::CloneCopy(ind)." << endl
00378           << "Wrong number of vectors." << endl;
00379         return false;
00380       }
00381       if ( MVT::GetVecLength(*C) != MVT::GetVecLength(*B) ) {
00382         om->stream(Warnings)
00383           << "*** ERROR *** MultiVecTraits::CloneCopy(ind)." << endl
00384           << "Vector lengths don't match." << endl;
00385         return false;
00386       }
00387       for (i=0; i<numvecs_2; i++) {
00388         if ( norms2[i] != norms[ind[i]] ) {
00389           om->stream(Warnings)
00390             << "*** ERROR *** MultiVecTraits::CloneCopy(ind)." << endl
00391             << "Copied vectors do not agree:" 
00392             << norms2[i] << " != " << norms[ind[i]] << endl;
00393           return false;
00394         }
00395       }
00396       MVT::MvInit(*B,zero);
00397       MVT::MvNorm(*C, &norms); 
00398       for (i=0; i<numvecs_2; i++) {
00399         if ( norms2[i] != norms[i] ) {
00400           om->stream(Warnings)
00401             << "*** ERROR *** MultiVecTraits::CloneCopy(ind)." << endl
00402             << "Copied vectors were not independent." << endl;
00403           return false;
00404         }
00405       }
00406     }    
00407 
00408 
00409     /*********** CloneCopy(MV) and MvNorm ********************************
00410        1) Check quantity
00411        2) Check value of norms
00412        3) Zero out B and make sure that C is still okay
00413     *********************************************************************/
00414     {
00415       Teuchos::RCP<MV> B, C;
00416       std::vector<MagType> norms(numvecs), norms2(numvecs);
00417 
00418       B = MVT::Clone(*A,numvecs);
00419       MVT::MvRandom(*B);
00420       MVT::MvNorm(*B, &norms);
00421       C = MVT::CloneCopy(*B);
00422       MVT::MvNorm(*C, &norms2);
00423       if ( MVT::GetNumberVecs(*C) != numvecs ) {
00424         om->stream(Warnings)
00425           << "*** ERROR *** MultiVecTraits::CloneCopy()." << endl
00426           << "Wrong number of vectors." << endl;
00427         return false;
00428       }
00429       for (i=0; i<numvecs; i++) {
00430         if ( norms2[i] != norms[i] ) {
00431           om->stream(Warnings)
00432             << "*** ERROR *** MultiVecTraits::CloneCopy()." << endl
00433             << "Copied vectors do not agree." << endl;
00434           return false;
00435         }
00436       }
00437       MVT::MvInit(*B,zero);
00438       MVT::MvNorm(*C, &norms); 
00439       for (i=0; i<numvecs; i++) {
00440         if ( norms2[i] != norms[i] ) {
00441           om->stream(Warnings)
00442             << "*** ERROR *** MultiVecTraits::CloneCopy()." << endl
00443             << "Copied vectors were not independent." << endl;
00444           return false;
00445         }
00446       }
00447     }
00448 
00449 
00450     /*********** CloneView(MV,vector<int>) and MvNorm ********************
00451        Check that we have a view of the selected vectors
00452        1) Check quantity
00453        2) Check value of norms
00454        3) Zero out B and make sure that C is zero as well
00455     *********************************************************************/
00456     {
00457       Teuchos::RCP<MV> B, C;
00458       std::vector<MagType> norms(numvecs), norms2(numvecs);
00459 
00460       B = MVT::Clone(*A,numvecs); 
00461       MVT::MvRandom(*B);
00462       MVT::MvNorm(*B, &norms);
00463       C = MVT::CloneView(*B,ind);
00464       MVT::MvNorm(*C, &norms2);
00465       if ( MVT::GetNumberVecs(*C) != numvecs_2 ) {
00466         om->stream(Warnings)
00467           << "*** ERROR *** MultiVecTraits::CloneView(ind)." << endl
00468           << "Wrong number of vectors." << endl;
00469         return false;
00470       }
00471       for (i=0; i<numvecs_2; i++) {
00472         if ( norms2[i] != norms[ind[i]] ) {
00473           om->stream(Warnings)
00474             << "*** ERROR *** MultiVecTraits::CloneView(ind)." << endl
00475             << "Viewed vectors do not agree." << endl;
00476           return false;
00477         }
00478       }
00479       /*
00480       MVT::MvInit(*B,zero);
00481       MVT::MvNorm(*C, &norms2); 
00482       for (i=0; i<numvecs_2; i++) {
00483         if ( norms2[i] != zero ) {
00484           if ( om->isVerbosityAndPrint(Warnings) ) {
00485             out << "*** ERROR *** MultiVecTraits::CloneView(ind)." << endl
00486                 << "Copied vectors were not dependent." << endl;
00487           }
00488           return false;
00489         }
00490       }
00491       */
00492     }
00493 
00494 
00495     /*********** const CloneView(MV,vector<int>) and MvNorm() ************
00496        Check that we have a view of the selected vectors.
00497        1) Check quantity
00498        2) Check value of norms for agreement
00499        3) Zero out B and make sure that C is zerod as well
00500     *********************************************************************/
00501     {
00502       Teuchos::RCP<MV> B;
00503       Teuchos::RCP<const MV> constB, C;
00504       std::vector<MagType> normsB(numvecs), normsC(numvecs_2);
00505       std::vector<int> allind(numvecs);
00506       for (i=0; i<numvecs; i++) {
00507         allind[i] = i;
00508       }
00509 
00510       B = MVT::Clone(*A,numvecs);
00511       MVT::MvRandom( *B );
00512       // need a const MV to test const CloneView
00513       constB = MVT::CloneView(*B,allind);
00514       MVT::MvNorm(*constB, &normsB);
00515       C = MVT::CloneView(*constB,ind);
00516       MVT::MvNorm(*C, &normsC);
00517       if ( MVT::GetNumberVecs(*C) != numvecs_2 ) {
00518         om->stream(Warnings)
00519           << "*** ERROR *** const MultiVecTraits::CloneView(ind)." << endl
00520           << "Wrong number of vectors." << endl;
00521         return false;
00522       }
00523       for (i=0; i<numvecs_2; i++) {
00524         if ( normsC[i] != normsB[ind[i]] ) {
00525           om->stream(Warnings)
00526             << "*** ERROR *** const MultiVecTraits::CloneView(ind)." << endl
00527             << "Viewed vectors do not agree." << endl;
00528           return false;
00529         }
00530       }
00531       /*
00532       MVT::MvInit(const_cast<MV&>(*C),zero);
00533       MVT::MvNorm(*constB, &normsB); 
00534       for (i=0; i<numvecs_2; i++) {
00535         if ( normsB[ind[i]] != SCT::zero() ) {
00536           if ( om->isVerbosityAndPrint(Warnings) ) {
00537             out << "*** ERROR *** const MultiVecTraits::CloneView(ind)." << endl
00538                 << "Copied vectors were not dependent." << endl;
00539           }
00540           return false;
00541         }
00542       }
00543       */
00544     }
00545 
00546 
00547     /*********** SetBlock() and MvNorm() *********************************
00548        SetBlock() will copy the vectors from C into B 
00549        1) Verify that the specified vectors were copied
00550        2) Verify that the other vectors were not modified
00551        3) Verify that C was not modified
00552        4) Change C and then check B to make sure it was not modified
00553       
00554        Use a different index set than has been used so far (distinct entries).
00555        This is because duplicate entries will cause the vector to be
00556        overwritten, making it more difficult to test.
00557     *********************************************************************/
00558     {
00559       Teuchos::RCP<MV> B, C;
00560       std::vector<MagType> normsB1(numvecs), normsB2(numvecs),
00561                            normsC1(numvecs_2), normsC2(numvecs_2);
00562 
00563       B = MVT::Clone(*A,numvecs);
00564       C = MVT::Clone(*A,numvecs_2);
00565       // Just do every other one, interleaving the vectors of C into B
00566       ind.resize(numvecs_2);
00567       for (i=0; i<numvecs_2; i++) {
00568         ind[i] = 2*i;
00569       }
00570       MVT::MvRandom(*B);
00571       MVT::MvRandom(*C);
00572 
00573       MVT::MvNorm(*B,&normsB1);
00574       MVT::MvNorm(*C,&normsC1);
00575       MVT::SetBlock(*C,ind,*B);
00576       MVT::MvNorm(*B,&normsB2);
00577       MVT::MvNorm(*C,&normsC2);
00578 
00579       // check that C was not changed by SetBlock
00580       for (i=0; i<numvecs_2; i++) {
00581         if ( normsC1[i] != normsC2[i] ) {
00582           om->stream(Warnings)
00583             << "*** ERROR *** MultiVecTraits::SetBlock()." << endl
00584             << "Operation modified source vectors." << endl;
00585           return false;
00586         }
00587       }
00588       // check that the correct vectors of B were modified
00589       // and the others were not
00590       for (i=0; i<numvecs; i++) {
00591         if (i % 2 == 0) {
00592           // should be a vector from C
00593           if ( normsB2[i] != normsC1[i/2] ) {
00594             om->stream(Warnings)
00595               << "*** ERROR *** MultiVecTraits::SetBlock()." << endl
00596               << "Copied vectors do not agree." << endl;
00597             return false;
00598           }
00599         }
00600         else {
00601           // should be an original vector
00602           if ( normsB1[i] != normsB2[i] ) {
00603             om->stream(Warnings)
00604               << "*** ERROR *** MultiVecTraits::SetBlock()." << endl
00605               << "Incorrect vectors were modified." << endl;
00606             return false;
00607           }
00608         }
00609       }
00610       MVT::MvInit(*C,zero);
00611       MVT::MvNorm(*B,&normsB1);
00612       // verify that we copied and didn't reference
00613       for (i=0; i<numvecs; i++) {
00614         if ( normsB1[i] != normsB2[i] ) {
00615           om->stream(Warnings)
00616             << "*** ERROR *** MultiVecTraits::SetBlock()." << endl
00617             << "Copied vectors were not independent." << endl;
00618           return false;
00619         }
00620       }
00621     }
00622 
00623 
00624     /*********** SetBlock() and MvNorm() *********************************
00625        SetBlock() will copy the vectors from C into B 
00626        1) Verify that the specified vectors were copied
00627        2) Verify that the other vectors were not modified
00628        3) Verify that C was not modified
00629        4) Change C and then check B to make sure it was not modified
00630 
00631        Use a different index set than has been used so far (distinct entries).
00632        This is because duplicate entries will cause the vector to be
00633        overwritten, making it more difficult to test.
00634 
00635        These tests are the same as the ones above, except that the
00636        number of indices (to be copied into B) is less than the number
00637        of vectors in C, so that not all of C is put into B.
00638     *********************************************************************/
00639     {
00640       Teuchos::RCP<MV> B, C;
00641       // set these: we assume below that setSize*2=BSize
00642       const int BSize   = 10, 
00643                 CSize   = 6,
00644                 setSize = 5;
00645       std::vector<MagType> normsB1(BSize), normsB2(BSize),
00646                            normsC1(CSize), normsC2(CSize);
00647 
00648       B = MVT::Clone(*A,BSize);
00649       C = MVT::Clone(*A,CSize);
00650       // Just do every other one, interleaving the vectors of C into B
00651       ind.resize(setSize);
00652       for (i=0; i<setSize; i++) {
00653         ind[i] = 2*i;
00654       }
00655       MVT::MvRandom(*B);
00656       MVT::MvRandom(*C);
00657 
00658       MVT::MvNorm(*B,&normsB1);
00659       MVT::MvNorm(*C,&normsC1);
00660       MVT::SetBlock(*C,ind,*B);
00661       MVT::MvNorm(*B,&normsB2);
00662       MVT::MvNorm(*C,&normsC2);
00663 
00664       // check that C was not changed by SetBlock
00665       for (i=0; i<CSize; i++) {
00666         if ( normsC1[i] != normsC2[i] ) {
00667           om->stream(Warnings)
00668             << "*** ERROR *** MultiVecTraits::SetBlock()." << endl
00669             << "Operation modified source vectors." << endl;
00670           return false;
00671         }
00672       }
00673       // check that the correct vectors of B were modified
00674       // and the others were not
00675       for (i=0; i<BSize; i++) {
00676         if (i % 2 == 0) {
00677           // should be a vector from C
00678           if ( normsB2[i] != normsC1[i/2] ) {
00679             om->stream(Warnings)
00680               << "*** ERROR *** MultiVecTraits::SetBlock()." << endl
00681               << "Copied vectors do not agree." << endl;
00682             return false;
00683           }
00684         }
00685         else {
00686           // should be an original vector
00687           if ( normsB1[i] != normsB2[i] ) {
00688             om->stream(Warnings)
00689               << "*** ERROR *** MultiVecTraits::SetBlock()." << endl
00690               << "Incorrect vectors were modified." << endl;
00691             return false;
00692           }
00693         }
00694       }
00695       MVT::MvInit(*C,zero);
00696       MVT::MvNorm(*B,&normsB1);
00697       // verify that we copied and didn't reference
00698       for (i=0; i<numvecs; i++) {
00699         if ( normsB1[i] != normsB2[i] ) {
00700           om->stream(Warnings)
00701             << "*** ERROR *** MultiVecTraits::SetBlock()." << endl
00702             << "Copied vectors were not independent." << endl;
00703           return false;
00704         }
00705       }
00706     }
00707 
00708 
00709     /*********** MvTransMv() *********************************************
00710       Performs C = alpha * A^H * B, where
00711         alpha is type ScalarType
00712         A,B are type MV with p and q vectors, respectively
00713         C is a SerialDenseMatrix<int,ScalarType> ALREADY sized to p by q
00714 
00715         Verify:
00716         1) C is not resized by the routine
00717         3) Check that zero*(A^H B) == zero
00718         3) Check inner product inequality:
00719                                         [ |a1|*|b1|    ...    |ap|*|b1| ]
00720            [a1 ... ap]^H [b1 ... bq] <= [    ...    |ai|*|bj|    ...    ]
00721                                         [ |ap|*|b1|    ...    |ap|*|bq| ]
00722         4) Zero B and check that C is zero
00723         5) Zero A and check that C is zero
00724 
00725         Note: Should we really require that C is correctly sized already?
00726         Epetra does (and crashes if it isn't.)
00727     *********************************************************************/
00728     {
00729       const int p = 7;
00730       const int q = 9;
00731       Teuchos::RCP<MV> B, C;
00732       std::vector<MagType> normsB(p), normsC(q);
00733       Teuchos::SerialDenseMatrix<int,ScalarType> SDM(p,q);
00734 
00735       B = MVT::Clone(*A,p);
00736       C = MVT::Clone(*A,q);
00737    
00738       // randomize the multivectors
00739       MVT::MvRandom(*B);
00740       MVT::MvNorm(*B,&normsB);
00741       MVT::MvRandom(*C);
00742       MVT::MvNorm(*C,&normsC);
00743    
00744       // perform SDM  = zero() * B^H * C
00745       MVT::MvTransMv( zero, *B, *C, SDM );
00746    
00747       // check the sizes: not allowed to have shrunk
00748       if ( SDM.numRows() != p || SDM.numCols() != q ) {
00749         om->stream(Warnings)
00750           << "*** ERROR *** MultiVecTraits::MvTransMv()." << endl
00751           << "Routine resized SerialDenseMatrix." << endl;
00752         return false;
00753       }
00754    
00755       // check that zero**A^H*B == zero
00756       if ( SDM.normOne() != zero ) {
00757         om->stream(Warnings)
00758           << "*** ERROR *** MultiVecTraits::MvTransMv()." << endl
00759           << "Scalar argument processed incorrectly." << endl;
00760         return false;
00761       }
00762    
00763       // perform SDM  = one * B^H * C
00764       MVT::MvTransMv( one, *B, *C, SDM );
00765    
00766       // check the norms: a^H b = |a| |b| cos(theta) <= |a| |b|
00767       // with equality only when a and b are colinear
00768       for (i=0; i<p; i++) {
00769         for (j=0; j<q; j++) {
00770           if (   SCT::magnitude(SDM(i,j)) 
00771                > SCT::magnitude(normsB[i]*normsC[j]) ) {
00772             om->stream(Warnings)
00773               << "*** ERROR *** MultiVecTraits::MvTransMv()." << endl
00774               << "Triangle inequality did not hold: " 
00775               << SCT::magnitude(SDM(i,j)) 
00776               << " > " 
00777               << SCT::magnitude(normsB[i]*normsC[j]) 
00778               << endl;
00779             return false;
00780           }
00781         }
00782       }
00783       MVT::MvInit(*C);
00784       MVT::MvRandom(*B);
00785       MVT::MvTransMv( one, *B, *C, SDM );
00786       for (i=0; i<p; i++) {
00787         for (j=0; j<q; j++) {
00788           if ( SDM(i,j) != zero ) {
00789             om->stream(Warnings)
00790               << "*** ERROR *** MultiVecTraits::MvTransMv()." << endl
00791               << "Inner products not zero for C==0." << endl;
00792             return false;
00793           }
00794         }
00795       }
00796       MVT::MvInit(*B);
00797       MVT::MvRandom(*C);
00798       MVT::MvTransMv( one, *B, *C, SDM );
00799       for (i=0; i<p; i++) {
00800         for (j=0; j<q; j++) {
00801           if ( SDM(i,j) != zero ) {
00802             om->stream(Warnings)
00803               << "*** ERROR *** MultiVecTraits::MvTransMv()." << endl
00804               << "Inner products not zero for B==0." << endl;
00805             return false;
00806           }
00807         }
00808       }
00809     } 
00810 
00811 
00812     /*********** MvDot() *************************************************
00813         Verify:
00814         1) Results vector not resized
00815         2) Inner product inequalities are satisfied
00816         3) Zero vectors give zero inner products
00817     *********************************************************************/
00818     {
00819       const int p = 7;
00820       const int q = 9;
00821       Teuchos::RCP<MV> B, C;
00822       std::vector<ScalarType> iprods(p+q);
00823       std::vector<MagType> normsB(numvecs), normsC(numvecs);
00824 
00825       B = MVT::Clone(*A,p);
00826       C = MVT::Clone(*A,p);
00827 
00828       MVT::MvRandom(*B);
00829       MVT::MvRandom(*C);
00830       MVT::MvNorm(*B,&normsB);
00831       MVT::MvNorm(*C,&normsC);
00832       MVT::MvDot( *B, *C, &iprods );
00833       if ( iprods.size() != p+q ) {
00834         om->stream(Warnings)
00835           << "*** ERROR *** MultiVecTraits::MvDot." << endl
00836           << "Routine resized results vector." << endl;
00837         return false;
00838       }
00839       for (i=0; i<ANASAZI_MIN(p,q); i++) {
00840         if ( SCT::magnitude(iprods[i]) 
00841              > SCT::magnitude(normsB[i]*normsC[i]) ) {
00842           om->stream(Warnings)
00843             << "*** ERROR *** MultiVecTraits::MvDot()." << endl
00844             << "Inner products not valid." << endl;
00845           return false;
00846         }
00847       }
00848       MVT::MvInit(*B);
00849       MVT::MvRandom(*C);
00850       MVT::MvDot( *B, *C, &iprods );
00851       for (i=0; i<p; i++) {
00852         if ( iprods[i] != zero ) {
00853           om->stream(Warnings)
00854             << "*** ERROR *** MultiVecTraits::MvDot()." << endl
00855             << "Inner products not zero for B==0." << endl;
00856           return false;
00857         }
00858       }
00859       MVT::MvInit(*C);
00860       MVT::MvRandom(*B);
00861       MVT::MvDot( *B, *C, &iprods );
00862       for (i=0; i<p; i++) {
00863         if ( iprods[i] != zero ) {
00864           om->stream(Warnings)
00865             << "*** ERROR *** MultiVecTraits::MvDot()." << endl
00866             << "Inner products not zero for C==0." << endl;
00867           return false;
00868         }
00869       }
00870     }
00871 
00872 
00873     /*********** MvAddMv() ***********************************************
00874        D = alpha*B + beta*C
00875        1) Use alpha==0,beta==1 and check that D == C
00876        2) Use alpha==1,beta==0 and check that D == B
00877        3) Use D==0 and D!=0 and check that result is the same
00878        4) Check that input arguments are not modified 
00879     *********************************************************************/
00880     {
00881       const int p = 7;
00882       Teuchos::RCP<MV> B, C, D;
00883       std::vector<MagType> normsB1(p), normsB2(p),
00884                            normsC1(p), normsC2(p),
00885                            normsD1(p), normsD2(p);
00886       ScalarType alpha = SCT::random(),
00887                   beta = SCT::random();
00888 
00889       B = MVT::Clone(*A,p);
00890       C = MVT::Clone(*A,p);
00891       D = MVT::Clone(*A,p);
00892 
00893       MVT::MvRandom(*B);
00894       MVT::MvRandom(*C);
00895       MVT::MvNorm(*B,&normsB1);
00896       MVT::MvNorm(*C,&normsC1);
00897    
00898       // check that 0*B+1*C == C
00899       MVT::MvAddMv(zero,*B,one,*C,*D);
00900       MVT::MvNorm(*B,&normsB2);
00901       MVT::MvNorm(*C,&normsC2);
00902       MVT::MvNorm(*D,&normsD1);
00903       for (i=0; i<p; i++) {
00904         if ( normsB1[i] != normsB2[i] ) {
00905           om->stream(Warnings)
00906             << "*** ERROR *** MultiVecTraits::MvAddMv()." << endl
00907             << "Input arguments were modified." << endl;
00908           return false;
00909         }
00910         else if ( normsC1[i] != normsC2[i] ) {
00911           om->stream(Warnings)
00912             << "*** ERROR *** MultiVecTraits::MvAddMv()." << endl
00913             << "Input arguments were modified." << endl;
00914           return false;
00915         }
00916         else if ( normsC1[i] != normsD1[i] ) {
00917           om->stream(Warnings)
00918             << "*** ERROR *** MultiVecTraits::MvAddMv()." << endl
00919             << "Assignment did not work." << endl;
00920           return false;
00921         }
00922       }
00923 
00924       // check that 1*B+0*C == B
00925       MVT::MvAddMv(one,*B,zero,*C,*D);
00926       MVT::MvNorm(*B,&normsB2);
00927       MVT::MvNorm(*C,&normsC2);
00928       MVT::MvNorm(*D,&normsD1);
00929       for (i=0; i<p; i++) {
00930         if ( normsB1[i] != normsB2[i] ) {
00931           om->stream(Warnings)
00932             << "*** ERROR *** MultiVecTraits::MvAddMv()." << endl
00933             << "Input arguments were modified." << endl;
00934           return false;
00935         }
00936         else if ( normsC1[i] != normsC2[i] ) {
00937           om->stream(Warnings)
00938             << "*** ERROR *** MultiVecTraits::MvAddMv()." << endl
00939             << "Input arguments were modified." << endl;
00940           return false;
00941         }
00942         else if ( normsB1[i] != normsD1[i] ) {
00943           om->stream(Warnings)
00944             << "*** ERROR *** MultiVecTraits::MvAddMv()." << endl
00945             << "Assignment did not work." << endl;
00946           return false;
00947         }
00948       }
00949 
00950       // check that alpha*B+beta*C -> D is invariant under initial D
00951       // first, try random D
00952       MVT::MvRandom(*D);
00953       MVT::MvAddMv(alpha,*B,beta,*C,*D);
00954       MVT::MvNorm(*B,&normsB2);
00955       MVT::MvNorm(*C,&normsC2);
00956       MVT::MvNorm(*D,&normsD1);
00957       // check that input args are not modified
00958       for (i=0; i<p; i++) {
00959         if ( normsB1[i] != normsB2[i] ) {
00960           om->stream(Warnings)
00961             << "*** ERROR *** MultiVecTraits::MvAddMv()." << endl
00962             << "Input arguments were modified." << endl;
00963           return false;
00964         }
00965         else if ( normsC1[i] != normsC2[i] ) {
00966           om->stream(Warnings)
00967             << "*** ERROR *** MultiVecTraits::MvAddMv()." << endl
00968             << "Input arguments were modified." << endl;
00969           return false;
00970         }
00971       }
00972       // next, try zero D
00973       MVT::MvInit(*D);
00974       MVT::MvAddMv(alpha,*B,beta,*C,*D);
00975       MVT::MvNorm(*B,&normsB2);
00976       MVT::MvNorm(*C,&normsC2);
00977       MVT::MvNorm(*D,&normsD2);
00978       // check that input args are not modified and that D is the same
00979       // as the above test
00980       for (i=0; i<p; i++) {
00981         if ( normsB1[i] != normsB2[i] ) {
00982           om->stream(Warnings)
00983             << "*** ERROR *** MultiVecTraits::MvAddMv()." << endl
00984             << "Input arguments were modified." << endl;
00985           return false;
00986         }
00987         else if ( normsC1[i] != normsC2[i] ) {
00988           om->stream(Warnings)
00989             << "*** ERROR *** MultiVecTraits::MvAddMv()." << endl
00990             << "Input arguments were modified." << endl;
00991           return false;
00992         }
00993         else if ( normsD1[i] != normsD2[i] ) {
00994           om->stream(Warnings)
00995             << "*** ERROR *** MultiVecTraits::MvAddMv()." << endl
00996             << "Results varies depending on initial state of dest vectors." << endl;
00997           return false;
00998         }
00999       }
01000     }
01001 
01002     /*********** MvAddMv() ***********************************************
01003        Similar to above, but where B or C are potentially the same 
01004        object as D. This case is commonly used, for example, to affect
01005        A <- alpha*A
01006        via 
01007        MvAddMv(alpha,A,zero,A,A)
01008           ** OR **
01009        MvAddMv(zero,A,alpha,A,A)
01010       
01011        The result is that the operation has to be "atomic". That is, 
01012        B and C are no longer reliable after D is modified, so that 
01013        the assignment to D must be the last thing to occur.
01014 
01015        D = alpha*B + beta*C
01016 
01017        1) Use alpha==0,beta==1 and check that D == C
01018        2) Use alpha==1,beta==0 and check that D == B
01019     *********************************************************************/
01020     {
01021       const int p = 7;
01022       Teuchos::RCP<MV> B, C, D;
01023       std::vector<MagType> normsB(p),
01024                            normsD(p);
01025       std::vector<int> lclindex(p);
01026       for (i=0; i<p; i++) lclindex[i] = i;
01027 
01028       B = MVT::Clone(*A,p);
01029       C = MVT::CloneView(*B,lclindex);
01030       D = MVT::CloneView(*B,lclindex);
01031 
01032       MVT::MvRandom(*B);
01033       MVT::MvNorm(*B,&normsB);
01034    
01035       // check that 0*B+1*C == C
01036       MVT::MvAddMv(zero,*B,one,*C,*D);
01037       MVT::MvNorm(*D,&normsD);
01038       for (i=0; i<p; i++) {
01039         if ( normsB[i] != normsD[i] ) {
01040           om->stream(Warnings)
01041             << "*** ERROR *** MultiVecTraits::MvAddMv() #2" << endl
01042             << "Assignment did not work." << endl;
01043           return false;
01044         }
01045       }
01046 
01047       // check that 1*B+0*C == B
01048       MVT::MvAddMv(one,*B,zero,*C,*D);
01049       MVT::MvNorm(*D,&normsD);
01050       for (i=0; i<p; i++) {
01051         if ( normsB[i] != normsD[i] ) {
01052           om->stream(Warnings)
01053             << "*** ERROR *** MultiVecTraits::MvAddMv() #2" << endl
01054             << "Assignment did not work." << endl;
01055           return false;
01056         }
01057       }
01058 
01059     }
01060 
01061 
01062     /*********** MvTimesMatAddMv() 7 by 5 ********************************
01063        C = alpha*B*SDM + beta*C
01064        1) Use alpha==0, SDM!=0, beta==1 and check that C is unchanged
01065        2) Use alpha==0, SDM!=0, beta==0 and check that C is set to zero
01066        3) Use alpha==1, SDM==I, beta==0 and check that C is set to B
01067        4) Use alpha==1, SDM==0, beta==1 and check that C is unchanged
01068        5) Test with non-square matrices
01069        6) Always check that input arguments are not modified 
01070     *********************************************************************/
01071     {
01072       const int p = 7, q = 5;
01073       Teuchos::RCP<MV> B, C;
01074       Teuchos::SerialDenseMatrix<int,ScalarType> SDM(p,q);
01075       std::vector<MagType> normsC1(q), normsC2(q),
01076                            normsB1(p), normsB2(p);
01077       
01078       B = MVT::Clone(*A,p);
01079       C = MVT::Clone(*A,q);
01080 
01081       // Test 1: alpha==0, SDM!=0, beta==1 and check that C is unchanged
01082       MVT::MvRandom(*B);
01083       MVT::MvRandom(*C);
01084       MVT::MvNorm(*B,&normsB1);
01085       MVT::MvNorm(*C,&normsC1);
01086       SDM.random();
01087       MVT::MvTimesMatAddMv(zero,*B,SDM,one,*C);
01088       MVT::MvNorm(*B,&normsB2);
01089       MVT::MvNorm(*C,&normsC2);
01090       for (i=0; i<p; i++) {
01091         if ( normsB1[i] != normsB2[i] ) {
01092           om->stream(Warnings)
01093             << "*** ERROR *** MultiVecTraits::MvTimesMatAddMv()." << endl
01094             << "Input vectors were modified." << endl;
01095           return false;
01096         }
01097       }
01098       for (i=0; i<q; i++) {
01099         if ( normsC1[i] != normsC2[i] ) {
01100           om->stream(Warnings)
01101             << "*** ERROR *** MultiVecTraits::MvTimesMatAddMv()." << endl
01102             << "Arithmetic test 1 failed." << endl;
01103           return false;
01104         }
01105       }
01106 
01107       // Test 2: alpha==0, SDM!=0, beta==0 and check that C is set to zero
01108       MVT::MvRandom(*B);
01109       MVT::MvRandom(*C);
01110       MVT::MvNorm(*B,&normsB1);
01111       MVT::MvNorm(*C,&normsC1);
01112       SDM.random();
01113       MVT::MvTimesMatAddMv(zero,*B,SDM,zero,*C);
01114       MVT::MvNorm(*B,&normsB2);
01115       MVT::MvNorm(*C,&normsC2);
01116       for (i=0; i<p; i++) {
01117         if ( normsB1[i] != normsB2[i] ) {
01118           om->stream(Warnings)
01119             << "*** ERROR *** MultiVecTraits::MvTimesMatAddMv()." << endl
01120             << "Input vectors were modified." << endl;
01121           return false;
01122         }
01123       }
01124       for (i=0; i<q; i++) {
01125         if ( normsC2[i] != zero ) {
01126           om->stream(Warnings)
01127             << "*** ERROR *** MultiVecTraits::MvTimesMatAddMv()." << endl
01128             << "Arithmetic test 2 failed: " 
01129             << normsC2[i] 
01130             << " != " 
01131             << zero 
01132             << endl;
01133           return false;
01134         }
01135       }
01136 
01137       // Test 3: alpha==1, SDM==|I|, beta==0 and check that C is set to B
01138       //                        |0|
01139       MVT::MvRandom(*B);
01140       MVT::MvRandom(*C);
01141       MVT::MvNorm(*B,&normsB1);
01142       MVT::MvNorm(*C,&normsC1);
01143       SDM.scale(zero);
01144       for (i=0; i<q; i++) {
01145         SDM(i,i) = one;
01146       }
01147       MVT::MvTimesMatAddMv(one,*B,SDM,zero,*C);
01148       MVT::MvNorm(*B,&normsB2);
01149       MVT::MvNorm(*C,&normsC2);
01150       for (i=0; i<p; i++) {
01151         if ( normsB1[i] != normsB2[i] ) {
01152           om->stream(Warnings)
01153             << "*** ERROR *** MultiVecTraits::MvTimesMatAddMv()." << endl
01154             << "Input vectors were modified." << endl;
01155           return false;
01156         }
01157       }
01158       for (i=0; i<q; i++) {
01159         if ( normsB1[i] != normsC2[i] ) {
01160           om->stream(Warnings)
01161             << "*** ERROR *** MultiVecTraits::MvTimesMatAddMv()." << endl
01162             << "Arithmetic test 3 failed: "
01163             << normsB1[i] 
01164             << " != "
01165             << normsC2[i]
01166             << endl;
01167           return false;
01168         }
01169       }
01170 
01171       // Test 4: alpha==1, SDM==0, beta==1 and check that C is unchanged
01172       MVT::MvRandom(*B);
01173       MVT::MvRandom(*C);
01174       MVT::MvNorm(*B,&normsB1);
01175       MVT::MvNorm(*C,&normsC1);
01176       SDM.scale(zero);
01177       MVT::MvTimesMatAddMv(one,*B,SDM,one,*C);
01178       MVT::MvNorm(*B,&normsB2);
01179       MVT::MvNorm(*C,&normsC2);
01180       for (i=0; i<p; i++) {
01181         if ( normsB1[i] != normsB2[i] ) {
01182           om->stream(Warnings)
01183             << "*** ERROR *** MultiVecTraits::MvTimesMatAddMv()." << endl
01184             << "Input vectors were modified." << endl;
01185           return false;
01186         }
01187       }
01188       for (i=0; i<q; i++) {
01189         if ( normsC1[i] != normsC2[i] ) {
01190           om->stream(Warnings)
01191             << "*** ERROR *** MultiVecTraits::MvTimesMatAddMv()." << endl
01192             << "Arithmetic test 4 failed." << endl;
01193           return false;
01194         }
01195       }
01196     }
01197 
01198     /*********** MvTimesMatAddMv() 5 by 7 ********************************
01199        C = alpha*B*SDM + beta*C
01200        1) Use alpha==0, SDM!=0, beta==1 and check that C is unchanged
01201        2) Use alpha==0, SDM!=0, beta==0 and check that C is set to zero
01202        3) Use alpha==1, SDM==I, beta==0 and check that C is set to B
01203        4) Use alpha==1, SDM==0, beta==1 and check that C is unchanged
01204        5) Test with non-square matrices
01205        6) Always check that input arguments are not modified 
01206     *********************************************************************/
01207     {
01208       const int p = 5, q = 7;
01209       Teuchos::RCP<MV> B, C;
01210       Teuchos::SerialDenseMatrix<int,ScalarType> SDM(p,q);
01211       std::vector<MagType> normsC1(q), normsC2(q),
01212                            normsB1(p), normsB2(p);
01213       
01214       B = MVT::Clone(*A,p);
01215       C = MVT::Clone(*A,q);
01216 
01217       // Test 5: alpha==0, SDM!=0, beta==1 and check that C is unchanged
01218       MVT::MvRandom(*B);
01219       MVT::MvRandom(*C);
01220       MVT::MvNorm(*B,&normsB1);
01221       MVT::MvNorm(*C,&normsC1);
01222       SDM.random();
01223       MVT::MvTimesMatAddMv(zero,*B,SDM,one,*C);
01224       MVT::MvNorm(*B,&normsB2);
01225       MVT::MvNorm(*C,&normsC2);
01226       for (i=0; i<p; i++) {
01227         if ( normsB1[i] != normsB2[i] ) {
01228           om->stream(Warnings)
01229             << "*** ERROR *** MultiVecTraits::MvTimesMatAddMv()." << endl
01230             << "Input vectors were modified." << endl;
01231           return false;
01232         }
01233       }
01234       for (i=0; i<q; i++) {
01235         if ( normsC1[i] != normsC2[i] ) {
01236           om->stream(Warnings)
01237             << "*** ERROR *** MultiVecTraits::MvTimesMatAddMv()." << endl
01238             << "Arithmetic test 5 failed." << endl;
01239           return false;
01240         }
01241       }
01242 
01243       // Test 6: alpha==0, SDM!=0, beta==0 and check that C is set to zero
01244       MVT::MvRandom(*B);
01245       MVT::MvRandom(*C);
01246       MVT::MvNorm(*B,&normsB1);
01247       MVT::MvNorm(*C,&normsC1);
01248       SDM.random();
01249       MVT::MvTimesMatAddMv(zero,*B,SDM,zero,*C);
01250       MVT::MvNorm(*B,&normsB2);
01251       MVT::MvNorm(*C,&normsC2);
01252       for (i=0; i<p; i++) {
01253         if ( normsB1[i] != normsB2[i] ) {
01254           om->stream(Warnings)
01255             << "*** ERROR *** MultiVecTraits::MvTimesMatAddMv()." << endl
01256             << "Input vectors were modified." << endl;
01257           return false;
01258         }
01259       }
01260       for (i=0; i<q; i++) {
01261         if ( normsC2[i] != zero ) {
01262           om->stream(Warnings)
01263             << "*** ERROR *** MultiVecTraits::MvTimesMatAddMv()." << endl
01264             << "Arithmetic test 6 failed: " 
01265             << normsC2[i] 
01266             << " != " 
01267             << zero 
01268             << endl;
01269           return false;
01270         }
01271       }
01272 
01273       // Test 7: alpha==1, SDM==[I 0], beta==0 and check that C is set to B
01274       MVT::MvRandom(*B);
01275       MVT::MvRandom(*C);
01276       MVT::MvNorm(*B,&normsB1);
01277       MVT::MvNorm(*C,&normsC1);
01278       SDM.scale(zero);
01279       for (i=0; i<p; i++) {
01280         SDM(i,i) = one;
01281       }
01282       MVT::MvTimesMatAddMv(one,*B,SDM,zero,*C);
01283       MVT::MvNorm(*B,&normsB2);
01284       MVT::MvNorm(*C,&normsC2);
01285       for (i=0; i<p; i++) {
01286         if ( normsB1[i] != normsB2[i] ) {
01287           om->stream(Warnings)
01288             << "*** ERROR *** MultiVecTraits::MvTimesMatAddMv()." << endl
01289             << "Input vectors were modified." << endl;
01290           return false;
01291         }
01292       }
01293       for (i=0; i<p; i++) {
01294         if ( normsB1[i] != normsC2[i] ) {
01295           om->stream(Warnings)
01296             << "*** ERROR *** MultiVecTraits::MvTimesMatAddMv()." << endl
01297             << "Arithmetic test 7 failed." << endl;
01298           return false;
01299         }
01300       }
01301       for (i=p; i<q; i++) {
01302         if ( normsC2[i] != zero ) {
01303           om->stream(Warnings)
01304             << "*** ERROR *** MultiVecTraits::MvTimesMatAddMv()." << endl
01305             << "Arithmetic test 7 failed." << endl;
01306           return false;
01307         }
01308       }
01309 
01310       // Test 8: alpha==1, SDM==0, beta==1 and check that C is unchanged
01311       MVT::MvRandom(*B);
01312       MVT::MvRandom(*C);
01313       MVT::MvNorm(*B,&normsB1);
01314       MVT::MvNorm(*C,&normsC1);
01315       SDM.scale(zero);
01316       MVT::MvTimesMatAddMv(one,*B,SDM,one,*C);
01317       MVT::MvNorm(*B,&normsB2);
01318       MVT::MvNorm(*C,&normsC2);
01319       for (i=0; i<p; i++) {
01320         if ( normsB1[i] != normsB2[i] ) {
01321           om->stream(Warnings)
01322             << "*** ERROR *** MultiVecTraits::MvTimesMatAddMv()." << endl
01323             << "Input vectors were modified." << endl;
01324           return false;
01325         }
01326       }
01327       for (i=0; i<q; i++) {
01328         if ( normsC1[i] != normsC2[i] ) {
01329           om->stream(Warnings)
01330             << "*** ERROR *** MultiVecTraits::MvTimesMatAddMv()." << endl
01331             << "Arithmetic test 8 failed." << endl;
01332           return false;
01333         }
01334       }
01335     }
01336 
01337     return true;
01338 
01339   }
01340 
01341 
01342 
01348   template< class ScalarType, class MV, class OP>
01349   bool TestOperatorTraits( 
01350                 const Teuchos::RCP<OutputManager<ScalarType> > &om,
01351                 const Teuchos::RCP<const MV> &A,
01352                 const Teuchos::RCP<const OP> &M) {
01353 
01354     using std::endl;
01355 
01356     /* OPT Contract:
01357        Apply()
01358          MV: OP*zero == zero
01359              Warn if OP is not deterministic (OP*A != OP*A)
01360              Does not modify input arguments
01361     *********************************************************************/
01362 
01363     typedef MultiVecTraits<ScalarType, MV>     MVT;
01364     typedef Teuchos::ScalarTraits<ScalarType>  SCT;
01365     typedef OperatorTraits<ScalarType, MV, OP> OPT;
01366     typedef typename SCT::magnitudeType        MagType;
01367 
01368     const int numvecs = 10;
01369 
01370     Teuchos::RCP<MV> B = MVT::Clone(*A,numvecs), 
01371                              C = MVT::Clone(*A,numvecs);
01372 
01373     std::vector<MagType> normsB1(numvecs), normsB2(numvecs),
01374                          normsC1(numvecs), normsC2(numvecs);
01375     bool NonDeterministicWarning;
01376     int i;
01377 
01378 
01379     /*********** Apply() *************************************************
01380         Verify:
01381         1) OP*B == OP*B; OP is deterministic (just warn on this)
01382         2) OP*zero == 0
01383         3) OP*B doesn't modify B
01384         4) OP*B is invariant under initial state of destination vectors
01385     *********************************************************************/
01386     MVT::MvInit(*B);
01387     MVT::MvRandom(*C);
01388     MVT::MvNorm(*B,&normsB1);
01389     OPT::Apply(*M,*B,*C);
01390     MVT::MvNorm(*B,&normsB2);
01391     MVT::MvNorm(*C,&normsC2);
01392     for (i=0; i<numvecs; i++) {
01393       if (normsB2[i] != normsB1[i]) {
01394         om->stream(Warnings)
01395           << "*** ERROR *** OperatorTraits::Apply() [1]" << endl
01396           << "Apply() modified the input vectors." << endl;
01397         return false;
01398       }
01399       if (normsC2[i] != SCT::zero()) {
01400         om->stream(Warnings)
01401           << "*** ERROR *** OperatorTraits::Apply() [1]" << endl
01402           << "Operator applied to zero did not return zero." << endl;
01403         return false;
01404       }
01405     }
01406 
01407     // If we send in a random matrix, we should not get a zero return
01408     MVT::MvRandom(*B);
01409     MVT::MvNorm(*B,&normsB1);
01410     OPT::Apply(*M,*B,*C);
01411     MVT::MvNorm(*B,&normsB2);
01412     MVT::MvNorm(*C,&normsC2);
01413     bool ZeroWarning = false;
01414     for (i=0; i<numvecs; i++) {
01415       if (normsB2[i] != normsB1[i]) {
01416         om->stream(Warnings)
01417           << "*** ERROR *** OperatorTraits::Apply() [2]" << endl
01418           << "Apply() modified the input vectors." << endl;
01419         return false;
01420       }
01421       if (normsC2[i] == SCT::zero() && ZeroWarning==false ) {
01422         om->stream(Warnings)
01423           << "*** ERROR *** OperatorTraits::Apply() [2]" << endl
01424           << "Operator applied to random vectors returned zero." << endl;
01425         ZeroWarning = true;
01426       }
01427     }
01428 
01429     // Apply operator with C init'd to zero
01430     MVT::MvRandom(*B);
01431     MVT::MvNorm(*B,&normsB1);
01432     MVT::MvInit(*C);
01433     OPT::Apply(*M,*B,*C);
01434     MVT::MvNorm(*B,&normsB2);
01435     MVT::MvNorm(*C,&normsC1);
01436     for (i=0; i<numvecs; i++) {
01437       if (normsB2[i] != normsB1[i]) {
01438         om->stream(Warnings)
01439           << "*** ERROR *** OperatorTraits::Apply() [3]" << endl
01440           << "Apply() modified the input vectors." << endl;
01441         return false;
01442       }
01443     }
01444 
01445     // Apply operator with C init'd to random
01446     // Check that result is the same as before; warn if not.
01447     // This could be a result of a bug, or a non-constant
01448     //   operator. We do not want to prejudice against a 
01449     //   stochastic operator.
01450     MVT::MvRandom(*C);
01451     OPT::Apply(*M,*B,*C);
01452     MVT::MvNorm(*B,&normsB2);
01453     MVT::MvNorm(*C,&normsC2);
01454     NonDeterministicWarning = false;
01455     for (i=0; i<numvecs; i++) {
01456       if (normsB2[i] != normsB1[i]) {
01457         om->stream(Warnings)
01458           << "*** ERROR *** OperatorTraits::Apply() [4]" << endl
01459           << "Apply() modified the input vectors." << endl;
01460         return false;
01461       }
01462       if (normsC1[i] != normsC2[i] && !NonDeterministicWarning) {
01463         om->stream(Warnings)
01464           << endl
01465           << "*** WARNING *** OperatorTraits::Apply() [4]" << endl
01466           << "Apply() returned two different results." << endl << endl;
01467         NonDeterministicWarning = true;
01468       }
01469     }
01470 
01471     return true;
01472 
01473   }
01474 
01475 }
01476 
01477 #endif

Generated on Tue Oct 20 12:45:18 2009 for Anasazi by doxygen 1.4.7