|
Teuchos Package Browser (Single Doxygen Collection)
Version of the Day
|
00001 // @HEADER 00002 // *********************************************************************** 00003 // 00004 // Teuchos: Common Tools 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 // Redistribution and use in source and binary forms, with or without 00011 // modification, are permitted provided that the following conditions are 00012 // met: 00013 // 00014 // 1. Redistributions of source code must retain the above copyright 00015 // notice, this list of conditions and the following disclaimer. 00016 // 00017 // 2. Redistributions in binary form must reproduce the above copyright 00018 // notice, this list of conditions and the following disclaimer in the 00019 // documentation and/or other materials provided with the distribution. 00020 // 00021 // 3. Neither the name of the Corporation nor the names of the 00022 // contributors may be used to endorse or promote products derived from 00023 // this software without specific prior written permission. 00024 // 00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY 00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE 00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00036 // 00037 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 00038 // 00039 // *********************************************************************** 00040 // @HEADER 00041 00042 #include "Teuchos_SerialDenseMatrix.hpp" 00043 #include "Teuchos_SerialDenseVector.hpp" 00044 #include "Teuchos_SerialDenseHelpers.hpp" 00045 #include "Teuchos_SerialDenseSolver.hpp" 00046 #include "Teuchos_ScalarTraits.hpp" 00047 #include "Teuchos_RCP.hpp" 00048 #include "Teuchos_Version.hpp" 00049 00050 using Teuchos::ScalarTraits; 00051 using Teuchos::SerialDenseMatrix; 00052 using Teuchos::SerialDenseVector; 00053 00054 #define OTYPE int 00055 #ifdef HAVE_TEUCHOS_COMPLEX 00056 #define STYPE std::complex<double> 00057 #else 00058 #define STYPE double 00059 #endif 00060 00061 // SCALARMAX defines the maximum positive value (with a little leeway) generated for matrix and vector elements and scalars: 00062 // random numbers in [-SCALARMAX, SCALARMAX] will be generated. 00063 #ifdef HAVE_TEUCHOS_COMPLEX 00064 #define SCALARMAX STYPE(10,0) 00065 #else 00066 #define SCALARMAX STYPE(10) 00067 #endif 00068 00069 template<typename TYPE> 00070 int PrintTestResults(std::string, TYPE, TYPE, bool); 00071 00072 int ReturnCodeCheck(std::string, int, int, bool); 00073 00074 typedef SerialDenseVector<OTYPE, STYPE> DVector; 00075 typedef SerialDenseMatrix<OTYPE, STYPE> DMatrix; 00076 00077 // Returns ScalarTraits<TYPE>::random() (the input parameters are ignored) 00078 template<typename TYPE> 00079 TYPE GetRandom(TYPE, TYPE); 00080 00081 // Returns a random integer between the two input parameters, inclusive 00082 template<> 00083 int GetRandom(int, int); 00084 00085 // Returns a random double between the two input parameters, plus or minus a random number between 0 and 1 00086 template<> 00087 double GetRandom(double, double); 00088 00089 template<typename T> 00090 std::complex<T> GetRandom( std::complex<T>, std::complex<T> ); 00091 00092 // Generates random matrices and vectors using GetRandom() 00093 Teuchos::RCP<DMatrix> GetRandomMatrix(int m, int n); 00094 Teuchos::RCP<DVector> GetRandomVector(int n); 00095 00096 // Compares the difference between two vectors using relative euclidean norms 00097 // Returns 1 if the comparison failed, the relative difference is greater than the tolerance. 00098 int CompareVectors(const SerialDenseVector<OTYPE,STYPE>& Vector1, 00099 const SerialDenseVector<OTYPE,STYPE>& Vector2, 00100 ScalarTraits<STYPE>::magnitudeType Tolerance ); 00101 00102 int main(int argc, char* argv[]) 00103 { 00104 typedef ScalarTraits<STYPE>::magnitudeType MagnitudeType; 00105 00106 int n=10, m=8; 00107 MagnitudeType tol = 1e-12*ScalarTraits<MagnitudeType>::one(); 00108 00109 bool verbose = 0; 00110 if (argc>1) if (argv[1][0]=='-' && argv[1][1]=='v') verbose = true; 00111 00112 if (verbose) 00113 std::cout << Teuchos::Teuchos_Version() << std::endl << std::endl; 00114 00115 int numberFailedTests = 0; 00116 int returnCode = 0; 00117 std::string testName = "", testType = ""; 00118 00119 #ifdef HAVE_TEUCHOS_COMPLEX 00120 testType = "COMPLEX"; 00121 #else 00122 testType = "REAL"; 00123 #endif 00124 00125 if (verbose) std::cout<<std::endl<<"********** CHECKING TEUCHOS SERIAL DENSE SOLVER - " << testType << "-VALUED **********"<<std::endl<<std::endl; 00126 00127 // Create dense matrix and vector. 00128 Teuchos::RCP<DMatrix> A1 = GetRandomMatrix(n,n); 00129 Teuchos::RCP<DVector> x1 = GetRandomVector(n); 00130 DVector xhat(n), b(n), bt(n); 00131 00132 // Compute the right-hand side vector using multiplication. 00133 returnCode = b.multiply(Teuchos::NO_TRANS, Teuchos::NO_TRANS, ScalarTraits<STYPE>::one() , *A1, *x1, ScalarTraits<STYPE>::zero()); 00134 testName = "Generating right-hand side vector using A*x, where x is a random vector:"; 00135 numberFailedTests += ReturnCodeCheck(testName, returnCode, 0, verbose); 00136 00137 returnCode = bt.multiply(Teuchos::TRANS, Teuchos::NO_TRANS, ScalarTraits<STYPE>::one() , *A1, *x1, ScalarTraits<STYPE>::zero()); 00138 testName = "Generating right-hand side vector using A^T*x, where x is a random vector:"; 00139 numberFailedTests += ReturnCodeCheck(testName, returnCode, 0, verbose); 00140 00141 #ifdef HAVE_TEUCHOS_COMPLEX 00142 DVector bct(n); 00143 returnCode = bct.multiply(Teuchos::CONJ_TRANS, Teuchos::NO_TRANS, ScalarTraits<STYPE>::one() , *A1, *x1, ScalarTraits<STYPE>::zero()); 00144 testName = "Generating right-hand side vector using A^H*x, where x is a random vector:"; 00145 numberFailedTests += ReturnCodeCheck(testName, returnCode, 0, verbose); 00146 #endif 00147 00148 // Fill the solution vector with zeros. 00149 xhat.putScalar( ScalarTraits<STYPE>::zero() ); 00150 00151 // Create a serial dense solver. 00152 Teuchos::SerialDenseSolver<OTYPE, STYPE> solver1; 00153 00154 // Pass in matrix and vectors 00155 solver1.setMatrix( A1 ); 00156 solver1.setVectors( Teuchos::rcp( &xhat, false ), Teuchos::rcp( &b, false ) ); 00157 00158 // Test1: Simple factor and solve 00159 returnCode = solver1.factor(); 00160 testName = "Simple solve: factor() random A:"; 00161 numberFailedTests += ReturnCodeCheck(testName, returnCode, 0, verbose); 00162 00163 // Non-transpose solve 00164 returnCode = solver1.solve(); 00165 testName = "Simple solve: solve() random A (NO_TRANS):"; 00166 numberFailedTests += CompareVectors( *x1, xhat, tol ); 00167 numberFailedTests += ReturnCodeCheck(testName, returnCode, 0, verbose); 00168 00169 // Tranpose solve (can be done after factorization, since factorization doesn't depend on this) 00170 xhat.putScalar( ScalarTraits<STYPE>::zero() ); 00171 solver1.setVectors( Teuchos::rcp( &xhat, false ), Teuchos::rcp( &bt, false ) ); 00172 solver1.solveWithTransposeFlag( Teuchos::TRANS ); 00173 returnCode = solver1.solve(); 00174 testName = "Simple solve: solve() random A (TRANS):"; 00175 numberFailedTests += CompareVectors( *x1, xhat, tol ); 00176 numberFailedTests += ReturnCodeCheck(testName, returnCode, 0, verbose); 00177 00178 #ifdef HAVE_TEUCHOS_COMPLEX 00179 // Conjugate tranpose solve (can be done after factorization, since factorization doesn't depend on this) 00180 xhat.putScalar( ScalarTraits<STYPE>::zero() ); 00181 solver1.setVectors( Teuchos::rcp( &xhat, false ), Teuchos::rcp( &bct, false ) ); 00182 solver1.solveWithTransposeFlag( Teuchos::CONJ_TRANS ); 00183 returnCode = solver1.solve(); 00184 testName = "Simple solve: solve() random A (CONJ_TRANS):"; 00185 numberFailedTests += CompareVectors( *x1, xhat, tol ); 00186 numberFailedTests += ReturnCodeCheck(testName, returnCode, 0, verbose); 00187 #endif 00188 00189 // Test2: Invert the matrix, inverse should be in A. 00190 returnCode = solver1.invert(); 00191 testName = "Simple solve: invert() random A:"; 00192 numberFailedTests += ReturnCodeCheck(testName, returnCode, 0, verbose); 00193 00194 // Compute the solution vector using multiplication and the inverse. 00195 returnCode = xhat.multiply(Teuchos::NO_TRANS, Teuchos::NO_TRANS, ScalarTraits<STYPE>::one() , *A1, b, ScalarTraits<STYPE>::zero()); 00196 testName = "Computing solution using inverted random A (NO_TRANS):"; 00197 numberFailedTests += CompareVectors( *x1, xhat, tol ); 00198 numberFailedTests += ReturnCodeCheck(testName, returnCode, 0, verbose); 00199 00200 returnCode = xhat.multiply(Teuchos::TRANS, Teuchos::NO_TRANS, ScalarTraits<STYPE>::one() , *A1, bt, ScalarTraits<STYPE>::zero()); 00201 testName = "Computing solution using inverted random A (TRANS):"; 00202 numberFailedTests += CompareVectors( *x1, xhat, tol ); 00203 numberFailedTests += ReturnCodeCheck(testName, returnCode, 0, verbose); 00204 00205 #ifdef HAVE_TEUCHOS_COMPLEX 00206 returnCode = xhat.multiply(Teuchos::CONJ_TRANS, Teuchos::NO_TRANS, ScalarTraits<STYPE>::one() , *A1, bct, ScalarTraits<STYPE>::zero()); 00207 testName = "Computing solution using inverted random A (CONJ_TRANS):"; 00208 numberFailedTests += CompareVectors( *x1, xhat, tol ); 00209 numberFailedTests += ReturnCodeCheck(testName, returnCode, 0, verbose); 00210 #endif 00211 00212 // Test3: Solve with iterative refinement. 00213 00214 // Create random linear system 00215 Teuchos::RCP<DMatrix> A2 = GetRandomMatrix(n,n); 00216 Teuchos::RCP<DVector> x2 = GetRandomVector(n); 00217 00218 // Create LHS through multiplication with A2 00219 xhat.putScalar( ScalarTraits<STYPE>::zero() ); 00220 b.multiply(Teuchos::NO_TRANS, Teuchos::NO_TRANS, ScalarTraits<STYPE>::one() , *A2, *x2, ScalarTraits<STYPE>::zero()); 00221 bt.multiply(Teuchos::TRANS, Teuchos::NO_TRANS, ScalarTraits<STYPE>::one() , *A2, *x2, ScalarTraits<STYPE>::zero()); 00222 #ifdef HAVE_TEUCHOS_COMPLEX 00223 bct.multiply(Teuchos::CONJ_TRANS, Teuchos::NO_TRANS, ScalarTraits<STYPE>::one() , *A2, *x2, ScalarTraits<STYPE>::zero()); 00224 #endif 00225 00226 // Create a serial dense solver. 00227 Teuchos::SerialDenseSolver<OTYPE, STYPE> solver2; 00228 solver2.solveToRefinedSolution( true ); 00229 00230 // Pass in matrix and vectors 00231 solver2.setMatrix( A2 ); 00232 solver2.setVectors( Teuchos::rcp( &xhat, false ), Teuchos::rcp( &b, false ) ); 00233 00234 // Factor and solve with iterative refinement. 00235 returnCode = solver2.factor(); 00236 testName = "Solve with iterative refinement: factor() random A:"; 00237 numberFailedTests += ReturnCodeCheck(testName, returnCode, 0, verbose); 00238 00239 // Non-transpose solve 00240 returnCode = solver2.solve(); 00241 testName = "Solve with iterative refinement: solve() random A (NO_TRANS):"; 00242 numberFailedTests += CompareVectors( *x2, xhat, tol ); 00243 numberFailedTests += ReturnCodeCheck(testName, returnCode, 0, verbose); 00244 00245 // Tranpose solve (can be done after factorization, since factorization doesn't depend on this) 00246 xhat.putScalar( ScalarTraits<STYPE>::zero() ); 00247 solver2.setVectors( Teuchos::rcp( &xhat, false ), Teuchos::rcp( &bt, false ) ); 00248 solver2.solveWithTransposeFlag( Teuchos::TRANS ); 00249 returnCode = solver2.solve(); 00250 testName = "Solve with iterative refinement: solve() random A (TRANS):"; 00251 numberFailedTests += CompareVectors( *x2, xhat, tol ); 00252 numberFailedTests += ReturnCodeCheck(testName, returnCode, 0, verbose); 00253 00254 #ifdef HAVE_TEUCHOS_COMPLEX 00255 // Conjugate tranpose solve (can be done after factorization, since factorization doesn't depend on this) 00256 xhat.putScalar( ScalarTraits<STYPE>::zero() ); 00257 solver2.setVectors( Teuchos::rcp( &xhat, false ), Teuchos::rcp( &bct, false ) ); 00258 solver2.solveWithTransposeFlag( Teuchos::CONJ_TRANS ); 00259 returnCode = solver2.solve(); 00260 testName = "Solve with iterative refinement: solve() random A (CONJ_TRANS):"; 00261 numberFailedTests += CompareVectors( *x2, xhat, tol ); 00262 numberFailedTests += ReturnCodeCheck(testName, returnCode, 0, verbose); 00263 #endif 00264 00265 // Test4: Solve with matrix equilibration. 00266 00267 // Create random linear system 00268 Teuchos::RCP<DMatrix> A3 = GetRandomMatrix(n,n); 00269 Teuchos::RCP<DVector> x3 = GetRandomVector(n); 00270 00271 // Create LHS through multiplication with A3 00272 xhat.putScalar( ScalarTraits<STYPE>::zero() ); 00273 b.multiply(Teuchos::NO_TRANS, Teuchos::NO_TRANS, ScalarTraits<STYPE>::one() , *A3, *x3, ScalarTraits<STYPE>::zero()); 00274 bt.multiply(Teuchos::TRANS, Teuchos::NO_TRANS, ScalarTraits<STYPE>::one() , *A3, *x3, ScalarTraits<STYPE>::zero()); 00275 #ifdef HAVE_TEUCHOS_COMPLEX 00276 bct.multiply(Teuchos::CONJ_TRANS, Teuchos::NO_TRANS, ScalarTraits<STYPE>::one() , *A3, *x3, ScalarTraits<STYPE>::zero()); 00277 #endif 00278 00279 // Create a serial dense solver. 00280 Teuchos::SerialDenseSolver<OTYPE, STYPE> solver3; 00281 solver3.factorWithEquilibration( true ); 00282 00283 // Pass in matrix and vectors 00284 solver3.setMatrix( A3 ); 00285 solver3.setVectors( Teuchos::rcp( &xhat, false ), Teuchos::rcp( &b, false ) ); 00286 00287 // Factor and solve with matrix equilibration. 00288 returnCode = solver3.factor(); 00289 testName = "Solve with matrix equilibration: factor() random A:"; 00290 numberFailedTests += ReturnCodeCheck(testName, returnCode, 0, verbose); 00291 00292 // Non-transpose solve 00293 returnCode = solver3.solve(); 00294 testName = "Solve with matrix equilibration: solve() random A (NO_TRANS):"; 00295 numberFailedTests += CompareVectors( *x3, xhat, tol ); 00296 numberFailedTests += ReturnCodeCheck(testName, returnCode, 0, verbose); 00297 00298 // Tranpose solve (can be done after factorization, since factorization doesn't depend on this) 00299 xhat.putScalar( ScalarTraits<STYPE>::zero() ); 00300 solver3.setVectors( Teuchos::rcp( &xhat, false ), Teuchos::rcp( &bt, false ) ); 00301 solver3.solveWithTransposeFlag( Teuchos::TRANS ); 00302 returnCode = solver3.solve(); 00303 testName = "Solve with matrix equilibration: solve() random A (TRANS):"; 00304 numberFailedTests += CompareVectors( *x3, xhat, tol ); 00305 numberFailedTests += ReturnCodeCheck(testName, returnCode, 0, verbose); 00306 00307 #ifdef HAVE_TEUCHOS_COMPLEX 00308 // Conjugate tranpose solve (can be done after factorization, since factorization doesn't depend on this) 00309 xhat.putScalar( ScalarTraits<STYPE>::zero() ); 00310 solver3.setVectors( Teuchos::rcp( &xhat, false ), Teuchos::rcp( &bct, false ) ); 00311 solver3.solveWithTransposeFlag( Teuchos::CONJ_TRANS ); 00312 returnCode = solver3.solve(); 00313 testName = "Solve with matrix equilibration: solve() random A (CONJ_TRANS):"; 00314 numberFailedTests += CompareVectors( *x3, xhat, tol ); 00315 numberFailedTests += ReturnCodeCheck(testName, returnCode, 0, verbose); 00316 #endif 00317 00318 // 00319 // If a test failed output the number of failed tests. 00320 // 00321 if(numberFailedTests > 0) 00322 { 00323 if (verbose) { 00324 std::cout << "Number of failed tests: " << numberFailedTests << std::endl; 00325 std::cout << "End Result: TEST FAILED" << std::endl; 00326 return -1; 00327 } 00328 } 00329 if(numberFailedTests == 0) 00330 std::cout << "End Result: TEST PASSED" << std::endl; 00331 00332 return 0; 00333 } 00334 00335 template<typename TYPE> 00336 int PrintTestResults(std::string testName, TYPE calculatedResult, TYPE expectedResult, bool verbose) 00337 { 00338 int result; 00339 if(calculatedResult == expectedResult) 00340 { 00341 if(verbose) std::cout << testName << " successful." << std::endl; 00342 result = 0; 00343 } 00344 else 00345 { 00346 if(verbose) std::cout << testName << " unsuccessful." << std::endl; 00347 result = 1; 00348 } 00349 return result; 00350 } 00351 00352 int ReturnCodeCheck(std::string testName, int returnCode, int expectedResult, bool verbose) 00353 { 00354 int result; 00355 if(expectedResult == 0) 00356 { 00357 if(returnCode == 0) 00358 { 00359 if(verbose) std::cout << testName << " test successful." << std::endl; 00360 result = 0; 00361 } 00362 else 00363 { 00364 if(verbose) std::cout << testName << " test unsuccessful. Return code was " << returnCode << "." << std::endl; 00365 result = 1; 00366 } 00367 } 00368 else 00369 { 00370 if(returnCode != 0) 00371 { 00372 if(verbose) std::cout << testName << " test successful -- failed as expected." << std::endl; 00373 result = 0; 00374 } 00375 else 00376 { 00377 if(verbose) std::cout << testName << " test unsuccessful -- did not fail as expected. Return code was " << returnCode << "." << std::endl; 00378 result = 1; 00379 } 00380 } 00381 return result; 00382 } 00383 00384 template<typename TYPE> 00385 TYPE GetRandom(TYPE Low, TYPE High) 00386 { 00387 return ((TYPE)((double)((1.0 * ScalarTraits<int>::random()) / RAND_MAX) * (High - Low + 1)) + Low); 00388 } 00389 00390 template<typename T> 00391 std::complex<T> GetRandom( std::complex<T> Low, std::complex<T> High) 00392 { 00393 T lowMag = Low.real(); 00394 T highMag = High.real(); 00395 T real = (T)(((1.0 * ScalarTraits<int>::random()) / RAND_MAX) * (highMag - lowMag + ScalarTraits<T>::one())) + lowMag; 00396 T imag = (T)(((1.0 * ScalarTraits<int>::random()) / RAND_MAX) * (highMag - lowMag + ScalarTraits<T>::one())) + lowMag; 00397 return std::complex<T>( real, imag ); 00398 } 00399 00400 template<> 00401 int GetRandom(int Low, int High) 00402 { 00403 return ((int)((double)((1.0 * ScalarTraits<int>::random()) / RAND_MAX) * (High - Low + 1)) + Low); 00404 } 00405 00406 template<> 00407 double GetRandom(double Low, double High) 00408 { 00409 return (((double)((1.0 * ScalarTraits<int>::random()) / RAND_MAX) * (High - Low + 1)) + Low + ScalarTraits<double>::random()); 00410 } 00411 00412 Teuchos::RCP<DMatrix> GetRandomMatrix(int m, int n) 00413 { 00414 Teuchos::RCP<DMatrix> newmat = Teuchos::rcp( new DMatrix(m,n) ); 00415 00416 // Fill dense matrix with random entries. 00417 for (int i=0; i<m; i++) 00418 for (int j=0; j<n; j++) 00419 (*newmat)(i,j) = GetRandom(-SCALARMAX, SCALARMAX); 00420 00421 return newmat; 00422 } 00423 00424 Teuchos::RCP<DVector> GetRandomVector(int n) 00425 { 00426 Teuchos::RCP<DVector> newvec = Teuchos::rcp( new DVector( n ) ); 00427 00428 // Fill dense vector with random entries. 00429 for (int i=0; i<n; i++) 00430 (*newvec)(i) = GetRandom(-SCALARMAX, SCALARMAX); 00431 00432 return newvec; 00433 } 00434 00435 /* Function: CompareVectors 00436 Purpose: Compares the difference between two vectors using relative euclidean-norms, i.e. ||v_1-v_2||_2/||v_2||_2 00437 */ 00438 int CompareVectors(const SerialDenseVector<OTYPE,STYPE>& Vector1, 00439 const SerialDenseVector<OTYPE,STYPE>& Vector2, 00440 ScalarTraits<STYPE>::magnitudeType Tolerance ) 00441 { 00442 typedef ScalarTraits<STYPE>::magnitudeType MagnitudeType; 00443 00444 SerialDenseVector<OTYPE,STYPE> diff( Vector1 ); 00445 diff -= Vector2; 00446 00447 MagnitudeType norm_diff = diff.normFrobenius(); 00448 MagnitudeType norm_v2 = Vector2.normFrobenius(); 00449 MagnitudeType temp = norm_diff; 00450 if (norm_v2 != ScalarTraits<MagnitudeType>::zero()) 00451 temp /= norm_v2; 00452 00453 if (temp > Tolerance) 00454 return 1; 00455 else 00456 return 0; 00457 } 00458
1.7.6.1