PlayaLinearCombinationTester.hpp
Go to the documentation of this file.
00001 /* @HEADER@ */
00002 // ************************************************************************
00003 // 
00004 //                 Playa: Programmable Linear Algebra
00005 //                 Copyright 2012 Sandia Corporation
00006 // 
00007 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00008 // the U.S. Government retains certain rights in this software.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Kevin Long (kevin.long@ttu.edu)
00038 // 
00039 
00040 /* @HEADER@ */
00041 
00042 
00043 #ifndef PLAYA_LINEARCOMBINATIONTESTER_HPP
00044 #define PLAYA_LINEARCOMBINATIONTESTER_HPP
00045 
00046 #include "PlayaLinearOperatorDecl.hpp"
00047 #include "PlayaLinearCombinationImpl.hpp"
00048 #include "PlayaSimpleComposedOpDecl.hpp"
00049 #include "PlayaSimpleScaledOpDecl.hpp"
00050 #include "PlayaSimpleAddedOpDecl.hpp"
00051 #include "PlayaSimpleIdentityOpDecl.hpp"
00052 #include "PlayaOut.hpp"
00053 #include "PlayaVectorDecl.hpp"
00054 #include "PlayaTesterBase.hpp"
00055 #include "PlayaRandomSparseMatrixBuilderDecl.hpp"
00056 #include "PlayaTestSpecifier.hpp"
00057 #include "Teuchos_ScalarTraits.hpp"
00058 
00059 #ifndef HAVE_TEUCHOS_EXPLICIT_INSTANTIATION
00060 #include "PlayaVectorImpl.hpp"
00061 #include "PlayaLinearOperatorImpl.hpp"
00062 #include "PlayaRandomSparseMatrixBuilderImpl.hpp"
00063 #include "PlayaSimpleComposedOpImpl.hpp"
00064 #include "PlayaSimpleScaledOpImpl.hpp"
00065 #include "PlayaSimpleAddedOpImpl.hpp"
00066 #include "PlayaSimpleTransposedOpImpl.hpp"
00067 #include "PlayaSimpleIdentityOpDecl.hpp"
00068 #endif
00069 
00070 using namespace Playa;
00071 using namespace Teuchos;
00072 
00073 
00074 
00075 
00076 
00077 #define TESTER(form1, form2)\
00078   {\
00079     Out::os() << "testing " #form1 << std::endl;\
00080     Vector<Scalar> _val1 = form1;\
00081     Out::os() << "testing " #form2 << std::endl;\
00082     Vector<Scalar> _val2 = form2;\
00083     Out::os() << "done testing... checking error" << std::endl;\
00084     ScalarMag err = (_val1-_val2).norm2();\
00085     if (!this->checkTest(spec_, err, "[" #form1 "] == [" #form2 "]")) pass = false;\
00086   }
00087     
00088 
00089 
00090 
00091 
00092 
00093 
00094 namespace Playa
00095 {
00096 
00097 /** */
00098 template <class Scalar>
00099 class LinearCombinationTester : public TesterBase<Scalar>
00100 {
00101 public:
00102   /** \brief Local typedef for promoted scalar magnitude */
00103   typedef typename Teuchos::ScalarTraits<Scalar>::magnitudeType ScalarMag;
00104 
00105   /** */
00106   LinearCombinationTester(int nLocalRows, double onProcDensity, 
00107     double offProcDensity,
00108     const VectorType<Scalar>& vecType,
00109     const TestSpecifier<Scalar>& spec);
00110 
00111   /** */
00112   bool runAllTests() const ;
00113 
00114 
00115 private:
00116 
00117   /** */
00118   bool nonModifyingOpTests() const ;
00119 
00120   /** */
00121   bool selfModifyingOpTests() const ;
00122 
00123   TestSpecifier<Scalar> spec_;
00124 
00125   int nLocalRows_;
00126   double onProcDensity_;
00127   double offProcDensity_;
00128   VectorType<Scalar> vecType_;
00129 
00130 };
00131 
00132 template <class Scalar> 
00133 inline LinearCombinationTester<Scalar>
00134 ::LinearCombinationTester(int nLocalRows, double onProcDensity, 
00135   double offProcDensity,
00136   const VectorType<Scalar>& vecType,
00137   const TestSpecifier<Scalar>& spec)
00138   : TesterBase<Scalar>(),
00139     spec_(spec),
00140     nLocalRows_(nLocalRows),
00141     onProcDensity_(onProcDensity),
00142     offProcDensity_(offProcDensity),
00143     vecType_(vecType)
00144 {;}
00145 
00146 template <class Scalar> 
00147 inline bool LinearCombinationTester<Scalar>
00148 ::runAllTests() const
00149 {
00150   bool pass = true;
00151 
00152   pass = nonModifyingOpTests() && pass;
00153   pass = selfModifyingOpTests() && pass;
00154 
00155   return pass;
00156 }
00157 
00158 template <class Scalar> 
00159 inline bool LinearCombinationTester<Scalar>
00160 ::nonModifyingOpTests() const
00161 {
00162   bool pass = true;
00163 
00164   RandomSparseMatrixBuilder<double> ABuilder(nLocalRows_, nLocalRows_, 
00165     onProcDensity_, offProcDensity_, 
00166     vecType_);
00167   RandomSparseMatrixBuilder<double> BBuilder(nLocalRows_, nLocalRows_, 
00168     onProcDensity_, offProcDensity_, 
00169     vecType_);
00170   RandomSparseMatrixBuilder<double> CBuilder(nLocalRows_, nLocalRows_, 
00171     onProcDensity_, offProcDensity_, 
00172     vecType_);
00173 
00174 
00175   LinearOperator<double> A = ABuilder.getOp();
00176   LinearOperator<Scalar> B = BBuilder.getOp();
00177   LinearOperator<Scalar> C = CBuilder.getOp();
00178 
00179   Vector<Scalar> x = A.domain().createMember();
00180   Vector<Scalar> y = A.domain().createMember();
00181   Vector<Scalar> z = A.domain().createMember();
00182 
00183   this->randomizeVec(x);
00184   this->randomizeVec(y);
00185   this->randomizeVec(z);
00186 
00187 
00188   TESTER(x*2.0, 2.0*x);
00189 
00190   TESTER(2.0*(x + y), 2.0*x + 2.0*y);
00191 
00192   TESTER(2.0*(x - y), 2.0*x - 2.0*y);
00193 
00194   TESTER((2.0*x + y) - y, 2.0*x);
00195 
00196   TESTER(-1.0*y + (2.0*x + y), 2.0*x);
00197 
00198   TESTER((x + y)*2.0, 2.0*x + 2.0*y);
00199 
00200   TESTER((x - y)*2.0, 2.0*x - 2.0*y);
00201 
00202   TESTER(2.0*(x - y), -2.0*(y - x));
00203 
00204   TESTER(0.25*(2.0*(x + y) - 2.0*(x - y)), y);
00205 
00206   TESTER((2.0*A)*x, 2.0*(A*x));
00207 
00208   TESTER(2.0*(A*x), (A*x)*2.0);
00209 
00210   TESTER(A*(B*x), (A*B)*x);
00211 
00212   TESTER(2.0*A*(B*x), A*(B*(2.0*x)));
00213 
00214   TESTER(3.0*(2.0*A)*x, 6.0*(A*x));
00215 
00216   TESTER(y + A*x, A*x + y);
00217 
00218 
00219   TESTER(z + (A*x + B*y), (B*y + A*x) + z);
00220 
00221 
00222   TESTER(z - (A*x + B*y), -1.0*((B*y + A*x) - z));
00223 
00224   TESTER(C*z + (A*x + B*y), (B*y + A*x) + C*z);
00225 
00226   TESTER(C*z - (A*x + B*y), -1.0*((B*y + A*x) - C*z));
00227 
00228   TESTER(2.0*z + (A*x + B*y), (B*y + A*x) + 2.0*z);
00229 
00230   TESTER(2.0*z - (A*x + B*y), -1.0*((B*y + A*x) - 2.0*z));
00231 
00232   TESTER(A*x - y, -1.0*(y - A*x));
00233 
00234   TESTER(A*x + B*y, B*y + A*x);
00235 
00236   TESTER(A*x - B*y - A*x + B*y +z, z);
00237 
00238   TESTER(2.0*(A*x + y), 2.0*A*x + 2.0*y);
00239 
00240   TESTER(2.0*(A*x + B*y), A*x + B*y + A*x + B*y);
00241 
00242   TESTER(2.0*(y + A*x), 2.0*y + 2.0*(A*x));
00243 
00244   TESTER(x + 2.0*A*y, x + 2.0*(A*y));
00245 
00246   TESTER(2.0*A*y + x, 2.0*(A*y) + x);
00247 
00248   TESTER(2.0*A*(3.0*B)*y, 6.0*(A*B*y));
00249 
00250   TESTER(2.0*A*(3.0*B)*y, 6.0*(A*(B*y)));
00251 
00252   TESTER(2.0*A*(3.0*B + 2.0*A)*x, 6.0*A*B*x + 4.0*A*A*x );
00253 
00254   TESTER(2.0*(A*x + B*y), 2.0*A*x + 2.0*B*y);
00255 
00256   TESTER(2.0*(A*x - B*y), 2.0*A*x - 2.0*B*y);
00257 
00258   TESTER(2.0*(A*x + B*y + z), 2.0*A*x + 2.0*B*y + 2.0*z);
00259 
00260   TESTER(2.0*(A*x + 3.0*B*y), 2.0*A*x + 6.0*B*y);
00261 
00262   TESTER(2.0*(A*x + 3.0*(z + B*y)), 2.0*A*x + 6.0*B*y + 6.0*z);
00263 
00264   TESTER(2.0*(z + A*x + B*y + z), 2.0*A*x + 2.0*B*y + 4.0*z);
00265 
00266   TESTER(2.0*(3.0*(z + A*x) + B*y), 6.0*z + 6.0*A*x + 2.0*B*y);
00267 
00268   TESTER(2.0*(3.0*(z + A*x) + 4.0*(B*y + z)), 6.0*z + 6.0*A*x + 8.0*B*y + 8.0*z);
00269     
00270   TESTER((A*x + B*y) + (A*y + B*x), (A + B)*x + (A+B)*y);
00271   TESTER((A*x + B*y) - (A*y + B*x), A*x - A*y + B*y - B*x);
00272 
00273   TESTER((A*x + B*y) + 2.0*(A*y + B*x), A*(x + 2.0*y) + B*(2.0*x + y));
00274   TESTER((A*x + B*y) - 2.0*(A*y + B*x), A*(x - 2.0*y) + B*(y - 2.0*x));
00275 
00276 
00277   return pass;
00278 }
00279 
00280 
00281 template <class Scalar> 
00282 inline bool LinearCombinationTester<Scalar>
00283 ::selfModifyingOpTests() const
00284 {
00285   bool pass = true;
00286 
00287   RandomSparseMatrixBuilder<double> ABuilder(nLocalRows_, nLocalRows_, 
00288     onProcDensity_, offProcDensity_, 
00289     vecType_);
00290   RandomSparseMatrixBuilder<double> BBuilder(nLocalRows_, nLocalRows_, 
00291     onProcDensity_, offProcDensity_, 
00292     vecType_);
00293   RandomSparseMatrixBuilder<double> CBuilder(nLocalRows_, nLocalRows_, 
00294     onProcDensity_, offProcDensity_, 
00295     vecType_);
00296 
00297 
00298   LinearOperator<double> A = ABuilder.getOp();
00299   LinearOperator<double> B = BBuilder.getOp();
00300   LinearOperator<double> C = CBuilder.getOp();
00301 
00302   VectorSpace<Scalar> vs = A.domain();
00303   A = identityOperator(vs);
00304   B = identityOperator(vs);
00305   C = identityOperator(vs);
00306 
00307   Vector<Scalar> x = A.domain().createMember();
00308   Vector<Scalar> y = A.domain().createMember();
00309   Vector<Scalar> z = A.domain().createMember();
00310 
00311   this->randomizeVec(x);
00312   this->randomizeVec(y);
00313   this->randomizeVec(z);
00314 
00315   Vector<Scalar> a = x.copy();
00316   Vector<Scalar> b = y.copy();
00317   Vector<Scalar> c = z.copy();
00318     
00319 
00320   Out::os() << "starting linear combination tests" << std::endl;
00321 
00322   x = 2.0*A*x;
00323   Scalar err = (x - 2.0*A*a).norm2();
00324   if (!this->checkTest(spec_, err, "x=2.0*A*x")) pass = false;
00325 
00326   a = x.copy();
00327   x = x + y;
00328   err = (x - (a + y)).norm2();
00329   if (!this->checkTest(spec_, err, "x=x+y")) pass = false;
00330 
00331   a = x.copy();
00332   x = y + x;
00333   err = (x - (y + a)).norm2();
00334   if (!this->checkTest(spec_, err, "x=y+x")) pass = false;
00335 
00336   a = x.copy();
00337   x = A*x + B*y;
00338   err = (x - (A*a + B*y)).norm2();
00339   if (!this->checkTest(spec_, err, "x=A*x+B*y")) pass = false;
00340 
00341   a = x.copy();
00342   x = B*y + A*x;
00343   err = (x - (B*y + A*a)).norm2();
00344   if (!this->checkTest(spec_, err, "x=B*y+A*x")) pass = false;
00345 
00346   a = x.copy();
00347   x = A*x + (B*y + C*x);
00348   err = (x - (A*a + (B*y + C*a))).norm2();
00349   if (!this->checkTest(spec_, err, "x=A*x + (B*y + C*x)")) pass = false;
00350 
00351   a = x.copy();
00352   x = (A*x + B*y) + C*x;
00353   err = (x - ((A*a + B*y) + C*a)).norm2();
00354   if (!this->checkTest(spec_, err, "x=(A*x + B*y) + C*x")) pass = false;
00355 
00356   /* test assignment of OpTimesLC into empty and non-empty vectors */
00357   Vector<Scalar> u;
00358   u = 2.0*A*B*x;
00359   err = (u - 2.0*A*B*x).norm2();
00360   if (!this->checkTest(spec_, err, "(empty) u=2*A*B*x")) pass = false;
00361 
00362   u = 2.0*A*B*x;
00363   err = (u - 2.0*A*B*x).norm2();
00364   if (!this->checkTest(spec_, err, "(non-empty) u=2*A*B*x")) pass = false;
00365 
00366   /* test assignment of LC2 into empty and non-empty vectors */
00367   Vector<Scalar> v;
00368   v = 2.0*x + 3.0*y;
00369   err = (v - (2.0*x + 3.0*y)).norm2();
00370   if (!this->checkTest(spec_, err, "(empty) v=2*x + 3*y")) pass = false;
00371 
00372   v = 2.0*x + 3.0*y;
00373   err = (v - (2.0*x + 3.0*y)).norm2();
00374   if (!this->checkTest(spec_, err, "(non-empty) v=2*x + 3*y")) pass = false;
00375 
00376   /* test assignment of LC3 into empty and non-empty vectors */
00377   Vector<Scalar> w;
00378   w = 2.0*x + 3.0*y + 5.0*z;
00379   err = (w - (2.0*x + 3.0*y + 5.0*z)).norm2();
00380   if (!this->checkTest(spec_, err, "(empty) w=2*x + 3*y + 5*z")) pass = false;
00381 
00382   w = 2.0*x + 3.0*y + 5.0*z;
00383   err = (w - (2.0*x + 3.0*y + 5.0*z)).norm2();
00384   if (!this->checkTest(spec_, err, "(non-empty) w=2*x + 3*y + 5*z")) pass = false;
00385 
00386   /* test assignment of LC4 into empty and non-empty vectors */
00387   Vector<Scalar> w2;
00388   w2 = 2.0*x + 3.0*y + 5.0*z + 7.0*u;
00389   err = (w2 - (2.0*x + 3.0*y + 5.0*z + 7.0*u)).norm2();
00390   if (!this->checkTest(spec_, err, 
00391       "(empty) w2=2*x + 3*y + 5*z + 7*u")) pass = false;
00392 
00393   w2 = 2.0*x + 3.0*y + 5.0*z + 7.0*u;
00394   err = (w2 - (2.0*x + 3.0*y + 5.0*z + 7.0*u)).norm2();
00395   if (!this->checkTest(spec_, err, 
00396       "(non-empty) w2=2*x + 3*y + 5*z + 7*u")) pass = false;
00397 
00398   /* test assignment of LC3 into one of the operands */
00399   x = 2.0*x + 3.0*y + 5.0*z;
00400   err = (w - x).norm2(); // Note: w contains 2x + 3y + 5z 
00401   if (!this->checkTest(spec_, err, "x=2*x + 3*y + 5*z")) pass = false;
00402 
00403 
00404   return pass;
00405 }
00406 
00407   
00408 }
00409 #endif

Site Contact