Teuchos Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
cxx_main_spd_solver.cpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // Teuchos: Common Tools Package
4 //
5 // Copyright 2004 NTESS and the Teuchos contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
16 #include "Teuchos_ScalarTraits.hpp"
17 #include "Teuchos_RCP.hpp"
18 #include "Teuchos_Version.hpp"
19 
24 
25 #define OTYPE int
26 #ifdef HAVE_TEUCHOS_COMPLEX
27 #define STYPE std::complex<double>
28 #else
29 #define STYPE double
30 #endif
31 
32 // SCALARMAX defines the maximum positive value (with a little leeway) generated for matrix and vector elements and scalars:
33 // random numbers in [-SCALARMAX, SCALARMAX] will be generated.
34 #ifdef HAVE_TEUCHOS_COMPLEX
35 #define SCALARMAX STYPE(10,0)
36 #else
37 #define SCALARMAX STYPE(10)
38 #endif
39 
40 template<typename TYPE>
41 int PrintTestResults(std::string, TYPE, TYPE, bool);
42 
43 int ReturnCodeCheck(std::string, int, int, bool);
44 
48 
49 // Returns ScalarTraits<TYPE>::random() (the input parameters are ignored)
50 template<typename TYPE>
51 TYPE GetRandom(TYPE, TYPE);
52 
53 // Returns a random integer between the two input parameters, inclusive
54 template<>
55 int GetRandom(int, int);
56 
57 // Returns a random double between the two input parameters, plus or minus a random number between 0 and 1
58 template<>
59 double GetRandom(double, double);
60 
61 template<typename T>
62 std::complex<T> GetRandom( std::complex<T>, std::complex<T> );
63 
64 // Generates random matrices and vectors using GetRandom()
68 
69 // Compares the difference between two vectors using relative euclidean norms
70 // Returns 1 if the comparison failed, the relative difference is greater than the tolerance.
72  const SerialDenseVector<OTYPE,STYPE>& Vector2,
74 
75 int main(int argc, char* argv[])
76 {
77  typedef ScalarTraits<STYPE>::magnitudeType MagnitudeType;
78 
79  int n=10;
80  MagnitudeType tol = 1e-12*ScalarTraits<MagnitudeType>::one();
81 
82  bool verbose = 0;
83  if (argc>1) if (argv[1][0]=='-' && argv[1][1]=='v') verbose = true;
84 
85  if (verbose)
86  std::cout << Teuchos::Teuchos_Version() << std::endl << std::endl;
87 
88  int numberFailedTests = 0, failedComparison = 0;
89  int returnCode = 0;
90  std::string testName = "", testType = "";
91 
92 #ifdef HAVE_TEUCHOS_COMPLEX
93  testType = "COMPLEX";
94 #else
95  testType = "REAL";
96 #endif
97 
98  if (verbose) std::cout<<std::endl<<"********** CHECKING TEUCHOS SERIAL SPD DENSE SOLVER - " << testType << "-VALUED **********"<<std::endl<<std::endl;
99 
100  // Create dense matrix and vector.
103  DVector xhat(n), b(n), bt(n);
104 
105  Teuchos::RCP<DMatrix> A1full = Teuchos::rcp( new DMatrix(n,n) );
106  for (int j=0; j<n; ++j) {
107  for (int i=0; i<=j; ++i) {
108  (*A1full)(i,j) = (*A1)(i,j);
109  }
110  }
111  for (int j=0; j<n; ++j) {
112  for (int i=j+1; i<n; ++i) {
113  (*A1full)(i,j) = ScalarTraits<STYPE>::conjugate( (*A1)(i,j) );
114  }
115  }
116 
117  // Compute the right-hand side vector using multiplication.
118  returnCode = b.multiply(Teuchos::NO_TRANS, Teuchos::NO_TRANS, ScalarTraits<STYPE>::one() , *A1full, *x1, ScalarTraits<STYPE>::zero());
119  testName = "Generating right-hand side vector using A*x, where x is a random vector:";
120  numberFailedTests += ReturnCodeCheck(testName, returnCode, 0, verbose);
121 
122  // Fill the solution vector with zeros.
123  xhat.putScalar( ScalarTraits<STYPE>::zero() );
124 
125  // Create a serial spd dense solver.
127 
128  // Pass in matrix and vectors
129  solver1.setMatrix( A1 );
130  solver1.setVectors( Teuchos::rcp( &xhat, false ), Teuchos::rcp( &b, false ) );
131 
132  // Test1: Simple factor and solve
133  returnCode = solver1.factor();
134  testName = "Simple solve: factor() random A:";
135  numberFailedTests += ReturnCodeCheck(testName, returnCode, 0, verbose);
136 
137  // Non-transpose solve
138  returnCode = solver1.solve();
139  testName = "Simple solve: solve() random A (NO_TRANS):";
140  failedComparison = CompareVectors( *x1, xhat, tol );
141  if(verbose && failedComparison>0) std::cout << "COMPARISON FAILED : ";
142  numberFailedTests += failedComparison;
143  numberFailedTests += ReturnCodeCheck(testName, returnCode, 0, verbose);
144 
145  // Test2: Solve with iterative refinement.
146 #ifdef HAVE_TEUCHOSNUMERICS_EIGEN
147  // Iterative refinement not implemented in Eigen
148 #else
149  // Create random linear system
152 
153  Teuchos::RCP<DMatrix> A2full = Teuchos::rcp( new DMatrix(n,n) );
154  for (int j=0; j<n; ++j) {
155  for (int i=0; i<=j; ++i) {
156  (*A2full)(i,j) = (*A2)(i,j);
157  }
158  }
159  for (int j=0; j<n; ++j) {
160  for (int i=j+1; i<n; ++i) {
161  (*A2full)(i,j) = ScalarTraits<STYPE>::conjugate( (*A2)(i,j) );
162  }
163  }
164 
165  // Create LHS through multiplication with A2
166  xhat.putScalar( ScalarTraits<STYPE>::zero() );
168 
169  // Create a serial dense solver.
171  solver2.solveToRefinedSolution( true );
172 
173  // Pass in matrix and vectors
174  solver2.setMatrix( A2 );
175  solver2.setVectors( Teuchos::rcp( &xhat, false ), Teuchos::rcp( &b, false ) );
176 
177  // Factor and solve with iterative refinement.
178  returnCode = solver2.factor();
179  testName = "Solve with iterative refinement: factor() random A:";
180  numberFailedTests += ReturnCodeCheck(testName, returnCode, 0, verbose);
181 
182  // Non-transpose solve
183  returnCode = solver2.solve();
184  testName = "Solve with iterative refinement: solve() random A (NO_TRANS):";
185  failedComparison = CompareVectors( *x2, xhat, tol );
186  if(verbose && failedComparison>0) std::cout << "COMPARISON FAILED : ";
187  numberFailedTests += failedComparison;
188  numberFailedTests += ReturnCodeCheck(testName, returnCode, 0, verbose);
189 
190 #endif
191 
192  // Test3: Solve with matrix equilibration.
193 
194  // Create random linear system
197 
198  Teuchos::RCP<DMatrix> A3full = Teuchos::rcp( new DMatrix(n,n) );
199  for (int j=0; j<n; ++j) {
200  for (int i=0; i<=j; ++i) {
201  (*A3full)(i,j) = (*A3)(i,j);
202  }
203  }
204  for (int j=0; j<n; ++j) {
205  for (int i=j+1; i<n; ++i) {
206  (*A3full)(i,j) = ScalarTraits<STYPE>::conjugate( (*A3)(i,j) );
207  }
208  }
209 
210  // Create LHS through multiplication with A3
211  xhat.putScalar( ScalarTraits<STYPE>::zero() );
213 
214  Teuchos::RCP<SDMatrix> A3bak = Teuchos::rcp( new SDMatrix( *A3 ) );
216 
217  // Create a serial dense solver.
219  solver3.factorWithEquilibration( true );
220 
221  // Pass in matrix and vectors
222  solver3.setMatrix( A3 );
223  solver3.setVectors( Teuchos::rcp( &xhat, false ), Teuchos::rcp( &b, false ) );
224 
225  // Factor and solve with matrix equilibration.
226  returnCode = solver3.factor();
227  testName = "Solve with matrix equilibration: factor() random A:";
228  numberFailedTests += ReturnCodeCheck(testName, returnCode, 0, verbose);
229 
230  // Non-transpose solve
231  returnCode = solver3.solve();
232  testName = "Solve with matrix equilibration: solve() random A (NO_TRANS):";
233  failedComparison = CompareVectors( *x3, xhat, tol );
234  if(verbose && failedComparison>0) std::cout << "COMPARISON FAILED : ";
235  numberFailedTests += failedComparison;
236  numberFailedTests += ReturnCodeCheck(testName, returnCode, 0, verbose);
237 
238  // Factor and solve with matrix equilibration, where only solve is called.
239  solver3.setMatrix( A3bak );
240  solver3.setVectors( Teuchos::rcp( &xhat, false ), b3bak );
241  returnCode = solver3.solve();
242  testName = "Solve with matrix equilibration: solve() without factor() random A (NO_TRANS):";
243  failedComparison = CompareVectors( *x3, xhat, tol );
244  if(verbose && failedComparison>0) std::cout << "COMPARISON FAILED : ";
245  numberFailedTests += failedComparison;
246  numberFailedTests += ReturnCodeCheck(testName, returnCode, 0, verbose);
247 
248  //
249  // If a test failed output the number of failed tests.
250  //
251  if(numberFailedTests > 0)
252  {
253  if (verbose) {
254  std::cout << "Number of failed tests: " << numberFailedTests << std::endl;
255  std::cout << "End Result: TEST FAILED" << std::endl;
256  return -1;
257  }
258  }
259  if(numberFailedTests == 0)
260  std::cout << "End Result: TEST PASSED" << std::endl;
261 
262  return 0;
263 
264 }
265 
266 template<typename TYPE>
267 int PrintTestResults(std::string testName, TYPE calculatedResult, TYPE expectedResult, bool verbose)
268 {
269  int result;
270  if(calculatedResult == expectedResult)
271  {
272  if(verbose) std::cout << testName << " successful." << std::endl;
273  result = 0;
274  }
275  else
276  {
277  if(verbose) std::cout << testName << " unsuccessful." << std::endl;
278  result = 1;
279  }
280  return result;
281 }
282 
283 int ReturnCodeCheck(std::string testName, int returnCode, int expectedResult, bool verbose)
284 {
285  int result;
286  if(expectedResult == 0)
287  {
288  if(returnCode == 0)
289  {
290  if(verbose) std::cout << testName << " test successful." << std::endl;
291  result = 0;
292  }
293  else
294  {
295  if(verbose) std::cout << testName << " test unsuccessful. Return code was " << returnCode << "." << std::endl;
296  result = 1;
297  }
298  }
299  else
300  {
301  if(returnCode != 0)
302  {
303  if(verbose) std::cout << testName << " test successful -- failed as expected." << std::endl;
304  result = 0;
305  }
306  else
307  {
308  if(verbose) std::cout << testName << " test unsuccessful -- did not fail as expected. Return code was " << returnCode << "." << std::endl;
309  result = 1;
310  }
311  }
312  return result;
313 }
314 
315 template<typename TYPE>
316 TYPE GetRandom(TYPE Low, TYPE High)
317 {
318  return ((TYPE)((double)((1.0 * ScalarTraits<int>::random()) / RAND_MAX) * (High - Low + 1)) + Low);
319 }
320 
321 template<typename T>
322 std::complex<T> GetRandom( std::complex<T> Low, std::complex<T> High)
323 {
324  T lowMag = Low.real();
325  T highMag = High.real();
326  T real = (T)(((1.0 * ScalarTraits<int>::random()) / RAND_MAX) * (highMag - lowMag + ScalarTraits<T>::one())) + lowMag;
327  T imag = (T)(((1.0 * ScalarTraits<int>::random()) / RAND_MAX) * (highMag - lowMag + ScalarTraits<T>::one())) + lowMag;
328  return std::complex<T>( real, imag );
329 }
330 
331 template<>
332 int GetRandom(int Low, int High)
333 {
334  return ((int)((double)((1.0 * ScalarTraits<int>::random()) / RAND_MAX) * (High - Low + 1)) + Low);
335 }
336 
337 template<>
338 double GetRandom(double Low, double High)
339 {
340  return (((double)((1.0 * ScalarTraits<int>::random()) / RAND_MAX) * (High - Low + 1)) + Low + ScalarTraits<double>::random());
341 }
342 
344 {
345 
347  Teuchos::RCP<DMatrix> tmp = Teuchos::rcp( new DMatrix(n,n) );
348  Teuchos::RCP<DMatrix> tmp2 = Teuchos::rcp( new DMatrix(n,n) );
351 
352  // QR factor a random matrix and get the orthogonal Q
355  solver.setMatrix( A );
356  solver.factor();
357  solver.formQ();
358  Q = solver.getQ();
359 
360  // Get n random positive eigenvalues and put them in a diagonal matrix D
362  for (int i=0; i<n; ++i) {
365  }
366 
367  // Form the spd matrix Q' D Q
370 
371  mat->setUpper();
372  for (int j=0; j<n; ++j) {
373  for (int i=0; i<=j; ++i) {
374  (*mat)(i,j) = (*tmp2)(i,j);
375  }
376  }
377 
378  return mat;
379 }
380 
382 {
383  Teuchos::RCP<DMatrix> newmat = Teuchos::rcp( new DMatrix(m,n) );
384 
385  // Fill dense matrix with random entries.
386  for (int i=0; i<m; i++)
387  for (int j=0; j<n; j++)
388  (*newmat)(i,j) = GetRandom(-SCALARMAX, SCALARMAX);
389 
390  return newmat;
391 }
392 
394 {
395  Teuchos::RCP<DVector> newvec = Teuchos::rcp( new DVector( n ) );
396 
397  // Fill dense vector with random entries.
398  for (int i=0; i<n; i++)
399  (*newvec)(i) = GetRandom(-SCALARMAX, SCALARMAX);
400 
401  return newvec;
402 }
403 
404 /* Function: CompareVectors
405  Purpose: Compares the difference between two vectors using relative euclidean-norms, i.e. ||v_1-v_2||_2/||v_2||_2
406 */
408  const SerialDenseVector<OTYPE,STYPE>& Vector2,
410 {
411  typedef ScalarTraits<STYPE>::magnitudeType MagnitudeType;
412 
413  SerialDenseVector<OTYPE,STYPE> diff( Vector1 );
414  diff -= Vector2;
415 
416  MagnitudeType norm_diff = diff.normFrobenius();
417  MagnitudeType norm_v2 = Vector2.normFrobenius();
418  MagnitudeType temp = norm_diff;
419  if (norm_v2 != ScalarTraits<MagnitudeType>::zero())
420  temp /= norm_v2;
421 
422  if (temp > Tolerance)
423  return 1;
424  else
425  return 0;
426 }
void solveToRefinedSolution(bool flag)
Causes all solves to compute solution to best ability using iterative refinement. ...
SerialSymDenseMatrix< OTYPE, STYPE > SDMatrix
Teuchos::RCP< SDMatrix > GetRandomSpdMatrix(int n)
A class for constructing and using Hermitian positive definite dense matrices.
int PrintTestResults(std::string, TYPE, TYPE, bool)
Non-member helper functions on the templated serial, dense matrix/vector classes. ...
int setMatrix(const RCP< SerialDenseMatrix< OrdinalType, ScalarType > > &A)
Sets the pointers for coefficient matrix.
Templated serial dense matrix class.
int formQ()
Explicitly forms the unitary matrix Q.
Teuchos::SerialDenseVector< int, std::complex< Real > > DVector
int multiply(ETransp transa, ETransp transb, ScalarType alpha, const SerialDenseMatrix< OrdinalType, ScalarType > &A, const SerialDenseMatrix< OrdinalType, ScalarType > &B, ScalarType beta)
Multiply A * B and add them to this; this = beta * this + alpha*A*B.
int factor()
Computes the in-place Cholesky factorization of the matrix using the LAPACK routine DPOTRF...
This class creates and provides basic support for symmetric, positive-definite dense matrices of temp...
Templated class for solving dense linear problems.
This class creates and provides basic support for dense vectors of templated type as a specialization...
ScalarTraits< ScalarType >::magnitudeType normFrobenius() const
Returns the Frobenius-norm of the matrix.
This structure defines some basic traits for a scalar field type.
#define SCALARMAX
A class for solving dense linear problems.
void setUpper()
Specify that the upper triangle of the this matrix should be used.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Deprecated.
int setMatrix(const RCP< SerialSymDenseMatrix< OrdinalType, ScalarType > > &A_in)
Sets the pointers for coefficient matrix.
TYPE GetRandom(TYPE, TYPE)
int solve()
Computes the solution X to AX = B for the this matrix and the B provided to SetVectors()..
int setVectors(const RCP< SerialDenseMatrix< OrdinalType, ScalarType > > &X, const RCP< SerialDenseMatrix< OrdinalType, ScalarType > > &B)
Sets the pointers for left and right hand side vector(s).
Teuchos::RCP< DMatrix > GetRandomMatrix(int m, int n)
bool CompareVectors(TYPE1 *Vector1, TYPE2 *Vector2, OType Size, TYPE2 Tolerance)
Teuchos::SerialDenseMatrix< int, std::complex< Real > > DMatrix
std::string Teuchos_Version()
int ReturnCodeCheck(std::string, int, int, bool)
Templated serial, dense, symmetric matrix class.
int main(int argc, char *argv[])
Templated class for constructing and using Hermitian positive definite dense matrices.
void factorWithEquilibration(bool flag)
Causes equilibration to be called just before the matrix factorization as part of the call to factor...
Templated serial dense vector class.
Defines basic traits for the scalar field type.
Teuchos::RCP< DVector > GetRandomVector(int n)
Smart reference counting pointer class for automatic garbage collection.
RCP< SerialDenseMatrix< OrdinalType, ScalarType > > getQ() const
Returns pointer to Q (assuming factorization has been performed).
int factor()
Computes the in-place QR factorization of the matrix using the LAPACK routine _GETRF or the Eigen cla...
Reference-counted pointer class and non-member templated function implementations.
This class creates and provides basic support for dense rectangular matrix of templated type...