Thyra_VectorOpTester.hpp

00001 // @HEADER
00002 // ***********************************************************************
00003 // 
00004 //    Thyra: Interfaces and Support for Abstract Numerical Algorithms
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 THYRA_VECTOROPTESTER_HPP
00030 #define THYRA_VECTOROPTESTER_HPP
00031 
00032 #include "Thyra_VectorImpl.hpp"
00033 #include "Thyra_VectorSpaceImpl.hpp"
00034 #include "Thyra_TesterBase.hpp"
00035 #include "Teuchos_ScalarTraits.hpp"
00036 #include "Teuchos_CommHelpers.hpp"
00037 #include "Thyra_ProductVectorSpaceBase.hpp"
00038 #include "Thyra_LinearCombinationImpl.hpp"
00039 
00040 namespace Thyra
00041 {
00042 using namespace Teuchos;
00043 using std::ostream;
00044 
00049 template <class Scalar>
00050 class VectorOpTester : public TesterBase<Scalar>
00051 {
00052 public:
00054   typedef typename Teuchos::ScalarTraits<Scalar>::magnitudeType ScalarMag;
00055 
00057   VectorOpTester(const RCP<const Comm<int> >& comm,
00058     const VectorSpace<Scalar>& space,
00059     Teuchos::RCP<Teuchos::FancyOStream>& out,
00060     const TestSpecifier<Scalar>& spec);
00061 
00063   bool runAllTests() const ;
00064 
00066   bool sumTest() const ;
00067 
00069   bool setElementUsingBracketTest() const ;
00070 
00072   bool dotStarTest() const ;
00073 
00075   bool scalarMultTest() const ;
00076 
00078   bool overloadedUpdateTest() const ;
00079 
00080 private:
00081   TestSpecifier<Scalar> spec_;
00082 };
00083 
00084 template <class Scalar> 
00085 inline VectorOpTester<Scalar>
00086 ::VectorOpTester(const RCP<const Comm<int> >& comm,
00087   const VectorSpace<Scalar>& space,
00088   Teuchos::RCP<Teuchos::FancyOStream>& out,
00089   const TestSpecifier<Scalar>& spec)
00090   : TesterBase<Scalar>(comm, space, 1, out),
00091     spec_(spec)
00092 {;}
00093 
00094 template <class Scalar> 
00095 inline bool VectorOpTester<Scalar>
00096 ::runAllTests() const
00097 {
00098   bool pass = true;
00099 
00100   pass = setElementUsingBracketTest() && pass;
00101   pass = sumTest() && pass;
00102   pass = dotStarTest() && pass;
00103   pass = scalarMultTest() && pass;
00104   pass = overloadedUpdateTest() && pass;
00105 
00106   return pass;
00107 }
00108 
00109 template <class Scalar> 
00110 inline bool VectorOpTester<Scalar>
00111 ::sumTest() const 
00112 {
00113 
00114   using std::endl;
00115 
00116   typedef Teuchos::ScalarTraits<Scalar> ST;
00117   ScalarMag err = ST::magnitude(ST::zero());
00118     
00119   this->out() << "running vector addition test..." << endl;
00120 
00121   Vector<Scalar> a = this->space().createMember();
00122   Vector<Scalar> b = this->space().createMember();
00123   Vector<Scalar> x = this->space().createMember();
00124   Vector<Scalar> y = this->space().createMember();
00125   randomizeVec(a);
00126   randomizeVec(b);
00127     
00128   /* do the operation with member functions */
00129   x = a + b ;
00130     
00131   /* do the operation elementwise. For off-processor elements, 
00132    * this is a no-op */
00133   for (int i=0; i<this->space().dim(); i++)
00134   {
00135     Scalar a_i = a[i];
00136     Scalar b_i = b[i];
00137     y[i] = a_i + b_i;
00138   }
00139   err = normInf(x-y);
00140   return this->checkTest(spec_, err, "vector addition");
00141 }
00142 
00143  
00144 
00145 
00146 template <class Scalar> 
00147 inline bool VectorOpTester<Scalar>
00148 ::setElementUsingBracketTest() const 
00149 {
00150 
00151   using std::endl;
00152 
00153   typedef Teuchos::ScalarTraits<Index> IST;
00154   typedef Teuchos::ScalarTraits<Scalar> ST;
00155 
00156   /* this test requires a comparison operator to make sense */
00157   if (ST::isComparable && spec_.doTest())
00158   {
00159     ScalarMag err = ST::magnitude(ST::zero());
00160 
00161     Vector<Scalar> a = this->space().createMember();
00162 
00163     /* We will load a vector with zeros, then set a randomly 
00164      * selected element to 1.0 and 
00165      * another to -1.0. Run minloc and maxloc to test that the minimum and
00166      * maximum values are at the expected locations. */
00167 
00168     zeroOut(a);
00169 
00170     int N = this->space().dim();
00171     int nTrials = 50;
00172 
00173     /* pick a seed in a way that is deterministic across processors */
00174     unsigned int seed = 107*N % 101;
00175     ST::seedrandom( seed );
00176 
00177     for (int t=0; t<nTrials; t++)
00178     {
00179       zeroOut(a);
00180       Index minIndex = IST::random() % N;
00181       Index maxIndex = IST::random() % N;
00182       /* skip cases where we've generated identical indices */
00183       if (minIndex == maxIndex) continue;
00184       a[minIndex] = -ST::one();
00185       a[maxIndex] = ST::one();
00186       Index findMin = -1;
00187       Index findMax = -1;
00188       Scalar minVal = Thyra::minloc(a, findMin);
00189       Scalar maxVal = Thyra::maxloc(a, findMax);
00190       err += ST::magnitude(-ST::one() - minVal);
00191       err += ST::magnitude(ST::one() - maxVal);
00192       err += ST::magnitude(findMin - minIndex);
00193       err += ST::magnitude(findMax - maxIndex);
00194     }
00195 
00196     return this->checkTest(spec_, err, "bracket operator");
00197   }
00198   else
00199   {
00200     this->out() << "skipping bracket operator test..." << endl;
00201     return true;
00202   }
00203 }
00204 
00205 /* specialize the set element test for complex types to a no-op. 
00206  * This is because minloc and maxloc do not exist for complex vectors 
00207  */
00208 #ifdef HAVE_THYRA_COMPLEX
00209 
00210 
00211 template <> 
00212 inline bool VectorOpTester<std::complex<double> >
00213 ::setElementUsingBracketTest() const 
00214 {
00215   using std::endl;
00216   this->out() << "skipping vector bracket operator test..." << endl;
00217   return true;
00218 }
00219 
00220 
00221 #if defined(HAVE_THYRA_FLOAT)
00222 template <> 
00223 inline bool VectorOpTester<std::complex<float> >
00224 ::setElementUsingBracketTest() const 
00225 {
00226   using std::endl;
00227   this->out() << "skipping vector bracket operator test..." << endl;
00228   return true;
00229 }
00230 #endif
00231 
00232 
00233 #endif // HAVE_THYRA_COMPLEX
00234   
00235 
00236 template <class Scalar> 
00237 inline bool VectorOpTester<Scalar>
00238 ::dotStarTest() const 
00239 {
00240 
00241   using std::endl;
00242 
00243   typedef Teuchos::ScalarTraits<Scalar> ST;
00244   ScalarMag err = ST::magnitude(ST::zero());
00245 
00246   this->out() << "running vector dotStar test..." << endl;
00247     
00248   Vector<Scalar> a = this->space().createMember();
00249   Vector<Scalar> b = this->space().createMember();
00250   Vector<Scalar> x = this->space().createMember();
00251   Vector<Scalar> y = this->space().createMember();
00252   Vector<Scalar> z = this->space().createMember();
00253   randomizeVec(a);
00254   randomizeVec(b);
00255     
00256   x = dotStar(a,b);
00257   z = dotSlash(x, b);
00258     
00259   err = normInf(a-z);
00260     
00261   this->out() << "|dotStar error|=" << err << endl;
00262   return this->checkTest(spec_, err, "dot-star");
00263 }
00264 
00265 
00266 
00267 template <class Scalar> 
00268 inline bool VectorOpTester<Scalar>
00269 ::scalarMultTest() const 
00270 {
00271 
00272   using std::endl;
00273 
00274   typedef Teuchos::ScalarTraits<Scalar> ST;
00275   ScalarMag err = ST::magnitude(ST::zero());
00276 
00277   this->out() << "running vector scalarMult test..." << endl;
00278     
00279   Vector<Scalar> a = this->space().createMember();
00280   Vector<Scalar> x = this->space().createMember();
00281   Vector<Scalar> y = this->space().createMember();
00282   randomizeVec(a);
00283     
00284     
00285   /* do the operation with member functions */
00286   Scalar alpha = 3.14;
00287   x = alpha * a;
00288     
00289   /* do the operation elementwise */
00290     
00291   for (int i=0; i<this->space().dim(); i++)
00292   {
00293     Scalar a_i = a[i];
00294     y[i]= alpha *a_i;
00295   }
00296     
00297   err = normInf(x-y);
00298     
00299   this->out() << "|scalarMult error|=" << err << endl;
00300   return this->checkTest(spec_, err, "scalar multiplication");
00301 
00302 }
00303  
00304 template <class Scalar> 
00305 inline bool VectorOpTester<Scalar>
00306 ::overloadedUpdateTest() const 
00307 {
00308 
00309   using std::endl;
00310 
00311   typedef Teuchos::ScalarTraits<Scalar> ST;
00312   ScalarMag err = ST::magnitude(ST::zero());
00313 
00314   this->out() << "running vector overloadedUpdate test..." << endl;
00315     
00316   Vector<Scalar> a = this->space().createMember();
00317   Vector<Scalar> b = this->space().createMember();
00318   Vector<Scalar> x = this->space().createMember();
00319   Vector<Scalar> y = this->space().createMember();
00320   randomizeVec(a);
00321   randomizeVec(b);
00322     
00323   /* do the operation with member functions */
00324   Scalar alpha = 3.14;
00325   Scalar beta = 1.4;
00326   x = alpha*a + beta*b;
00327     
00328   /* do the operation elementwise */
00329   for (int i=0; i<this->space().dim(); i++)
00330   {
00331     Scalar a_i = a[i];
00332     Scalar b_i = b[i];
00333     y[i] = alpha*a_i + beta*b_i;
00334   }
00335     
00336   err = normInf(x-y);
00337     
00338   this->out() << "|overloadedUpdate error|=" << err << endl;
00339   return this->checkTest(spec_, err, "overloaded update");
00340 
00341 }
00342 
00343 
00344 } // namespace Thyra
00345 
00346 #endif

Generated on Wed May 12 21:26:54 2010 for Thyra Operator/Vector Support by  doxygen 1.4.7