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_band_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 
15 #include "Teuchos_ScalarTraits.hpp"
16 #include "Teuchos_RCP.hpp"
17 #include "Teuchos_Version.hpp"
18 
23 
24 #define OTYPE int
25 #ifdef HAVE_TEUCHOS_COMPLEX
26 #define STYPE std::complex<double>
27 #else
28 #define STYPE double
29 #endif
30 
31 // SCALARMAX defines the maximum positive value (with a little leeway) generated for matrix and vector elements and scalars:
32 // random numbers in [-SCALARMAX, SCALARMAX] will be generated.
33 #ifdef HAVE_TEUCHOS_COMPLEX
34 #define SCALARMAX STYPE(10,0)
35 #else
36 #define SCALARMAX STYPE(10)
37 #endif
38 
39 template<typename TYPE>
40 int PrintTestResults(std::string, TYPE, TYPE, bool);
41 
42 int ReturnCodeCheck(std::string, int, int, bool);
43 
47 
48 // Returns ScalarTraits<TYPE>::random() (the input parameters are ignored)
49 template<typename TYPE>
50 TYPE GetRandom(TYPE, TYPE);
51 
52 // Returns a random integer between the two input parameters, inclusive
53 template<>
54 int GetRandom(int, int);
55 
56 // Returns a random double between the two input parameters, plus or minus a random number between 0 and 1
57 template<>
58 double GetRandom(double, double);
59 
60 template<typename T>
61 std::complex<T> GetRandom( std::complex<T>, std::complex<T> );
62 
63 // Generates random matrices and vectors using GetRandom()
64 Teuchos::RCP<DMatrix> GetRandomBandedMatrix(int m, int n, int kl, int ku);
66 
67 // Compares the difference between two vectors using relative euclidean norms
68 // Returns 1 if the comparison failed, the relative difference is greater than the tolerance.
70  const SerialDenseVector<OTYPE,STYPE>& Vector2,
72 
73 // Compares the difference between two matrices using relative euclidean norms
74 // Returns 1 if the comparison failed, the relative difference is greater than the tolerance.
76  const SerialDenseMatrix<OTYPE,STYPE>& Matrix2,
78 
79 int main(int argc, char* argv[])
80 
81 {
82 
83  typedef ScalarTraits<STYPE>::magnitudeType MagnitudeType;
84 
85  int n=10, kl=2, ku=3;
86  MagnitudeType tol = 1e-12*ScalarTraits<MagnitudeType>::one();
87 
88  bool verbose = 0;
89  if (argc>1) if (argv[1][0]=='-' && argv[1][1]=='v') verbose = true;
90 
91  if (verbose)
92  std::cout << Teuchos::Teuchos_Version() << std::endl << std::endl;
93 
94  int numberFailedTests = 0;
95  int returnCode = 0;
96  std::string testName = "", testType = "";
97 
98 #ifdef HAVE_TEUCHOS_COMPLEX
99  testType = "COMPLEX";
100 #else
101  testType = "REAL";
102 #endif
103 
104  if (verbose) std::cout<<std::endl<<"********** CHECKING TEUCHOS SERIAL BAND DENSE SOLVER - " << testType << "-VALUED **********"<<std::endl<<std::endl;
105 
106  // Create dense matrix and vector.
109  DVector xhat(n), b(n), bt(n);
110 
111  // Create a serial dense solver.
113 
116 
117  // Convert the dense matrix to a matrix in LAPACK banded storage
118  AB1 = Teuchos::generalToBanded( A1, kl, ku, true );
119 
120  // Convert the matrix in LAPACK banded storage back to a normal serial dense matrix
121  C1 = Teuchos::bandedToGeneral( AB1 );
122  testName = "Converting matrix formats: generalToBanded and bandedToGeneral random A:";
123  numberFailedTests += CompareMatrices( *A1, *C1, tol );
124  numberFailedTests += ReturnCodeCheck(testName, returnCode, 0, verbose);
125 
126  // Compute the right-hand side vector using multiplication.
128  testName = "Generating right-hand side vector using A*x, where x is a random vector:";
129  numberFailedTests += ReturnCodeCheck(testName, returnCode, 0, verbose);
131  testName = "Generating right-hand side vector using A^T*x, where x is a random vector:";
132  numberFailedTests += ReturnCodeCheck(testName, returnCode, 0, verbose);
133 
134 #ifdef HAVE_TEUCHOS_COMPLEX
135  DVector bct(n);
137  testName = "Generating right-hand side vector using A^H*x, where x is a random vector:";
138  numberFailedTests += ReturnCodeCheck(testName, returnCode, 0, verbose);
139 #endif
140 
141  // Fill the solution vector with zeros.
142  xhat.putScalar( ScalarTraits<STYPE>::zero() );
143 
144  // Pass in matrix and vectors
145  solver1.setMatrix( AB1 );
146  solver1.setVectors( Teuchos::rcp( &xhat, false ), Teuchos::rcp( &b, false ) );
147 
148  // Test1: Simple factor and solve
149  returnCode = solver1.factor();
150  testName = "Simple solve: factor() random A:";
151  numberFailedTests += ReturnCodeCheck(testName, returnCode, 0, verbose);
152 
153  // Non-transpose solve
154  returnCode = solver1.solve();
155  testName = "Simple solve: solve() random A (NO_TRANS):";
156  numberFailedTests += CompareVectors( *x1, xhat, tol );
157  numberFailedTests += ReturnCodeCheck(testName, returnCode, 0, verbose);
158 
159  // Tranpose solve (can be done after factorization, since factorization doesn't depend on this)
160  xhat.putScalar( ScalarTraits<STYPE>::zero() );
161  solver1.setVectors( Teuchos::rcp( &xhat, false ), Teuchos::rcp( &bt, false ) );
163  returnCode = solver1.solve();
164  testName = "Simple solve: solve() random A (TRANS):";
165  numberFailedTests += CompareVectors( *x1, xhat, tol );
166  numberFailedTests += ReturnCodeCheck(testName, returnCode, 0, verbose);
167 
168 #ifdef HAVE_TEUCHOS_COMPLEX
169  // Conjugate tranpose solve (can be done after factorization, since factorization doesn't depend on this)
170  xhat.putScalar( ScalarTraits<STYPE>::zero() );
171  solver1.setVectors( Teuchos::rcp( &xhat, false ), Teuchos::rcp( &bct, false ) );
173  returnCode = solver1.solve();
174  testName = "Simple solve: solve() random A (CONJ_TRANS):";
175  numberFailedTests += CompareVectors( *x1, xhat, tol );
176  numberFailedTests += ReturnCodeCheck(testName, returnCode, 0, verbose);
177 #endif
178 
179  // Test2: Solve with iterative refinement.
180 #ifdef HAVE_TEUCHOSNUMERICS_EIGEN
181  // Iterative refinement not implemented in Eigen
182 #else
183  // Create random linear system
186 
187  // Create LHS through multiplication with A2
188  xhat.putScalar( ScalarTraits<STYPE>::zero() );
191 #ifdef HAVE_TEUCHOS_COMPLEX
193 #endif
194 
195  // Create a serial dense solver.
197  solver2.solveToRefinedSolution( true );
198 
201  // Convert the dense matrix to a matrix in LAPACK banded storage
202  AB2 = Teuchos::generalToBanded( A2, kl, ku, true );
203 
204  // Convert the matrix in LAPACK banded storage back to a normal serial dense matrix
205  C2 = Teuchos::bandedToGeneral( AB2 );
206  testName = "Converting matrix formats: generalToBanded and bandedToGeneral random A:";
207  numberFailedTests += CompareMatrices( *A2, *C2, tol );
208  numberFailedTests += ReturnCodeCheck(testName, returnCode, 0, verbose);
209 
210  // Pass in matrix and vectors
211  solver2.setMatrix( AB2 );
212  solver2.setVectors( Teuchos::rcp( &xhat, false ), Teuchos::rcp( &b, false ) );
213 
214  // Factor and solve with iterative refinement.
215  returnCode = solver2.factor();
216  testName = "Solve with iterative refinement: factor() random A:";
217  numberFailedTests += ReturnCodeCheck(testName, returnCode, 0, verbose);
218 
219  // Non-transpose solve
220  returnCode = solver2.solve();
221  testName = "Solve with iterative refinement: solve() random A (NO_TRANS):";
222  numberFailedTests += CompareVectors( *x2, xhat, tol );
223  numberFailedTests += ReturnCodeCheck(testName, returnCode, 0, verbose);
224 
225  // Tranpose solve (can be done after factorization, since factorization doesn't depend on this)
226  xhat.putScalar( ScalarTraits<STYPE>::zero() );
227  solver2.setVectors( Teuchos::rcp( &xhat, false ), Teuchos::rcp( &bt, false ) );
229  returnCode = solver2.solve();
230  testName = "Solve with iterative refinement: solve() random A (TRANS):";
231  numberFailedTests += CompareVectors( *x2, xhat, tol );
232  numberFailedTests += ReturnCodeCheck(testName, returnCode, 0, verbose);
233 
234 #ifdef HAVE_TEUCHOS_COMPLEX
235  // Conjugate tranpose solve (can be done after factorization, since factorization doesn't depend on this)
236  xhat.putScalar( ScalarTraits<STYPE>::zero() );
237  solver2.setVectors( Teuchos::rcp( &xhat, false ), Teuchos::rcp( &bct, false ) );
239  returnCode = solver2.solve();
240  testName = "Solve with iterative refinement: solve() random A (CONJ_TRANS):";
241  numberFailedTests += CompareVectors( *x2, xhat, tol );
242  numberFailedTests += ReturnCodeCheck(testName, returnCode, 0, verbose);
243 #endif
244 #endif
245 
246  // Test3: Solve with matrix equilibration.
247 
248  // Create random linear system
251 
252  // Create LHS through multiplication with A3
253  xhat.putScalar( ScalarTraits<STYPE>::zero() );
256 #ifdef HAVE_TEUCHOS_COMPLEX
258 #endif
259 
260  // Create a serial dense solver.
262  solver3.factorWithEquilibration( true );
263 
266  // Convert the dense matrix to a matrix in LAPACK banded storage
267  AB3 = Teuchos::generalToBanded( A3, kl, ku, true );
268 
269  // Convert the matrix in LAPACK banded storage back to a normal serial dense matrix
270  C3 = Teuchos::bandedToGeneral( AB3 );
271  testName = "Converting matrix formats: generalToBanded and bandedToGeneral random A:";
272  numberFailedTests += CompareMatrices( *A3, *C3, tol );
273  numberFailedTests += ReturnCodeCheck(testName, returnCode, 0, verbose);
274 
275  // Pass in matrix and vectors
276  solver3.setMatrix( AB3 );
277  solver3.setVectors( Teuchos::rcp( &xhat, false ), Teuchos::rcp( &b, false ) );
278 
279  Teuchos::RCP<BDMatrix> AB3bak = Teuchos::rcp( new BDMatrix( *AB3 ) );
281 
282  // Factor and solve with matrix equilibration.
283  returnCode = solver3.factor();
284  testName = "Solve with matrix equilibration: factor() random A:";
285  numberFailedTests += ReturnCodeCheck(testName, returnCode, 0, verbose);
286 
287  // Non-transpose solve
288  returnCode = solver3.solve();
289  testName = "Solve with matrix equilibration: solve() random A (NO_TRANS):";
290  numberFailedTests += CompareVectors( *x3, xhat, tol );
291  numberFailedTests += ReturnCodeCheck(testName, returnCode, 0, verbose);
292 
293  // Tranpose solve (can be done after factorization, since factorization doesn't depend on this)
294  xhat.putScalar( ScalarTraits<STYPE>::zero() );
295  solver3.setVectors( Teuchos::rcp( &xhat, false ), Teuchos::rcp( &bt, false ) );
297  returnCode = solver3.solve();
298  testName = "Solve with matrix equilibration: solve() random A (TRANS):";
299  numberFailedTests += CompareVectors( *x3, xhat, tol );
300  numberFailedTests += ReturnCodeCheck(testName, returnCode, 0, verbose);
301 
302 #ifdef HAVE_TEUCHOS_COMPLEX
303  // Conjugate tranpose solve (can be done after factorization, since factorization doesn't depend on this)
304  xhat.putScalar( ScalarTraits<STYPE>::zero() );
305  solver3.setVectors( Teuchos::rcp( &xhat, false ), Teuchos::rcp( &bct, false ) );
307  returnCode = solver3.solve();
308  testName = "Solve with matrix equilibration: solve() random A (CONJ_TRANS):";
309  numberFailedTests += CompareVectors( *x3, xhat, tol );
310  numberFailedTests += ReturnCodeCheck(testName, returnCode, 0, verbose);
311 #endif
312 
313  // Non-tranpose solve where factor is not called
314  xhat.putScalar( ScalarTraits<STYPE>::zero() );
315  solver3.setMatrix( AB3bak );
316  solver3.setVectors( Teuchos::rcp( &xhat, false ), b3bak );
318  returnCode = solver3.solve();
319  testName = "Solve with matrix equilibration: solve() without factor() random A (NO_TRANS):";
320  numberFailedTests += CompareVectors( *x3, xhat, tol );
321  numberFailedTests += ReturnCodeCheck(testName, returnCode, 0, verbose);
322 
323  //
324  // If a test failed output the number of failed tests.
325  //
326  if(numberFailedTests > 0)
327  {
328  if (verbose) {
329  std::cout << "Number of failed tests: " << numberFailedTests << std::endl;
330  std::cout << "End Result: TEST FAILED" << std::endl;
331  return -1;
332  }
333  }
334  if(numberFailedTests == 0)
335  std::cout << "End Result: TEST PASSED!" << std::endl;
336 
337  return 0;
338 }
339 
340 template<typename TYPE>
341 int PrintTestResults(std::string testName, TYPE calculatedResult, TYPE expectedResult, bool verbose)
342 {
343  int result;
344  if(calculatedResult == expectedResult)
345  {
346  if(verbose) std::cout << testName << " successful." << std::endl;
347  result = 0;
348  }
349  else
350  {
351  if(verbose) std::cout << testName << " unsuccessful." << std::endl;
352  result = 1;
353  }
354  return result;
355 }
356 
357 int ReturnCodeCheck(std::string testName, int returnCode, int expectedResult, bool verbose)
358 {
359  int result;
360  if(expectedResult == 0)
361  {
362  if(returnCode == 0)
363  {
364  if(verbose) std::cout << testName << " test successful." << std::endl;
365  result = 0;
366  }
367  else
368  {
369  if(verbose) std::cout << testName << " test unsuccessful. Return code was " << returnCode << "." << std::endl;
370  result = 1;
371  }
372  }
373  else
374  {
375  if(returnCode != 0)
376  {
377  if(verbose) std::cout << testName << " test successful -- failed as expected." << std::endl;
378  result = 0;
379  }
380  else
381  {
382  if(verbose) std::cout << testName << " test unsuccessful -- did not fail as expected. Return code was " << returnCode << "." << std::endl;
383  result = 1;
384  }
385  }
386  return result;
387 }
388 
389 template<typename TYPE>
390 TYPE GetRandom(TYPE Low, TYPE High)
391 {
392  return ((TYPE)((double)((1.0 * ScalarTraits<int>::random()) / RAND_MAX) * (High - Low + 1)) + Low);
393 }
394 
395 template<typename T>
396 std::complex<T> GetRandom( std::complex<T> Low, std::complex<T> High)
397 {
398  T lowMag = Low.real();
399  T highMag = High.real();
400  T real = (T)(((1.0 * ScalarTraits<int>::random()) / RAND_MAX) * (highMag - lowMag + ScalarTraits<T>::one())) + lowMag;
401  T imag = (T)(((1.0 * ScalarTraits<int>::random()) / RAND_MAX) * (highMag - lowMag + ScalarTraits<T>::one())) + lowMag;
402  return std::complex<T>( real, imag );
403 }
404 
405 template<>
406 int GetRandom(int Low, int High)
407 {
408  return ((int)((double)((1.0 * ScalarTraits<int>::random()) / RAND_MAX) * (High - Low + 1)) + Low);
409 }
410 
411 template<>
412 double GetRandom(double Low, double High)
413 {
414  return (((double)((1.0 * ScalarTraits<int>::random()) / RAND_MAX) * (High - Low + 1)) + Low + ScalarTraits<double>::random());
415 }
416 
417 Teuchos::RCP<DMatrix> GetRandomBandedMatrix(int m, int n, int kl, int ku)
418 {
419  Teuchos::RCP<DMatrix> newmat = Teuchos::rcp( new DMatrix(m,n) );
420 
421  // Fill dense matrix with random entries.
422  for (int i=0; i<m; i++)
423  for (int j=0; j<n; j++)
424  if (j>= i-kl && j<=i+ku)
425  (*newmat)(i,j) = GetRandom(-SCALARMAX, SCALARMAX);
426 
427  return newmat;
428 }
429 
431 {
432  Teuchos::RCP<DVector> newvec = Teuchos::rcp( new DVector( n ) );
433 
434  // Fill dense vector with random entries.
435  for (int i=0; i<n; i++)
436  (*newvec)(i) = GetRandom(-SCALARMAX, SCALARMAX);
437 
438  return newvec;
439 }
440 
441 /* Function: CompareVectors
442  Purpose: Compares the difference between two vectors using relative euclidean-norms, i.e. ||v_1-v_2||_2/||v_2||_2
443 */
445  const SerialDenseVector<OTYPE,STYPE>& Vector2,
447 {
448  typedef ScalarTraits<STYPE>::magnitudeType MagnitudeType;
449 
450  SerialDenseVector<OTYPE,STYPE> diff( Vector1 );
451  diff -= Vector2;
452 
453  MagnitudeType norm_diff = diff.normFrobenius();
454  MagnitudeType norm_v2 = Vector2.normFrobenius();
455  MagnitudeType temp = norm_diff;
456  if (norm_v2 != ScalarTraits<MagnitudeType>::zero())
457  temp /= norm_v2;
458 
459  if (temp > Tolerance)
460  return 1;
461  else
462  return 0;
463 }
464 
465 /* Function: CompareVectors
466  Purpose: Compares the difference between two matrices using relative euclidean-norms, i.e. ||m_1-m_2||_\inf/||m_2||_\inf
467 */
469  const SerialDenseMatrix<OTYPE,STYPE>& Matrix2,
471 {
472  typedef ScalarTraits<STYPE>::magnitudeType MagnitudeType;
473 
474  SerialDenseMatrix<OTYPE,STYPE> diff( Matrix1 );
475  diff -= Matrix2;
476 
477  MagnitudeType norm_diff = diff.normInf();
478  MagnitudeType norm_m2 = Matrix2.normInf();
479  MagnitudeType temp = norm_diff;
480  if (norm_m2 != ScalarTraits<MagnitudeType>::zero())
481  temp /= norm_m2;
482 
483  if (temp > Tolerance)
484  return 1;
485  else
486  return 0;
487 }
int PrintTestResults(std::string, TYPE, TYPE, bool)
Non-member helper functions on the templated serial, dense matrix/vector classes. ...
Templated serial dense matrix class.
void solveToRefinedSolution(bool flag)
Set whether or not to use iterative refinement to improve solutions to linear systems.
int setMatrix(const RCP< SerialBandDenseMatrix< OrdinalType, ScalarType > > &AB)
Sets the pointer for coefficient matrix.
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.
#define SCALARMAX
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).
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.
Templated serial dense matrix class.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Deprecated.
TYPE GetRandom(TYPE, TYPE)
This class creates and provides basic support for banded dense matrices of templated type...
A class for representing and solving banded dense linear systems.
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)
int solve()
Computes the solution X to AX = B for the this matrix and the B provided to SetVectors()..
int main(int argc, char *argv[])
bool CompareMatrices(TYPE1 *Matrix1, TYPE2 *Matrix2, OType Rows, OType Columns, OType LDM, TYPE2 Tolerance)
Teuchos::RCP< DMatrix > GetRandomBandedMatrix(int m, int n, int kl, int ku)
Teuchos::SerialBandDenseMatrix< OTYPE, STYPE > BDMatrix
ScalarTraits< ScalarType >::magnitudeType normInf() const
Returns the Infinity-norm of the matrix.
int factor()
Computes the in-place LU factorization of the matrix using the LAPACK routine _GBTRF.
Templated serial dense vector class.
Defines basic traits for the scalar field type.
void solveWithTransposeFlag(Teuchos::ETransp trans)
Teuchos::RCP< DVector > GetRandomVector(int n)
Smart reference counting pointer class for automatic garbage collection.
Reference-counted pointer class and non-member templated function implementations.
This class creates and provides basic support for dense rectangular matrix of templated type...