Amesos Package Browser (Single Doxygen Collection)  Development
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Amesos_TestDriver.cpp
Go to the documentation of this file.
1 // @HEADER
2 // ***********************************************************************
3 //
4 // Amesos: Direct Sparse Solver Package
5 // Copyright (2004) Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8 // license for use of this work by or on behalf of the U.S. Government.
9 //
10 // This library is free software; you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as
12 // published by the Free Software Foundation; either version 2.1 of the
13 // License, or (at your option) any later version.
14 //
15 // This library is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 // Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public
21 // License along with this library; if not, write to the Free Software
22 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
23 // USA
24 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
25 //
26 // ***********************************************************************
27 // @HEADER
28 
29 //
30 // Amesos_TestDriver
31 //
32 // usage:
33 // Amesos_TestDriver.exe Solver InputMatrix MatrixType Special Numsolves Transpose MaxError MaxResid
34 // Where solver is: SuperLU, SuperLUdist, SuperLUdist2,
35 // UMFPACK, SPOOLES, DSCPACK, DSCPACKOLD, KLU,
36 // SPOOLESERIAL, MUMPS, SUPERLU, SCALAPACK or AZTEC
37 // special is, at present, only used in SuperLU, where 0 means dgssv
38 // and 1 means dgssvx
39 // examples:
40 // Amesos_TestDriver.exe SPOOLES ImpcolA.rua 0 1 1 0 1e-10 1e-10
41 // source SmallTest.csh
42 //
43 // output:
44 // SST.log (append)
45 // SST.summary (append)
46 //
47 // exits with 0 if test completed (does not imply that the test passed)
48 // exits with -1 if command line options or file permissions are wrong
49 //
50 #include "Amesos_ConfigDefs.h"
51 #include <stdio.h>
52 
54 
55 // #undef HAVE_TIME_H
56 // #undef HAVE_SYS_UTSNAME_H
57 
58 #ifdef HAVE_TIME_H
59 #include <time.h>
60 #endif
61 //
62 // utsname does not work on Paunchy (SunOS) so I disabled this
63 //
64 #ifdef HAVE_SYS_UTSNAME_WORKS_H
65 #include "utsname.h"
66 #endif
67 
68 
69 //
70 // There is undoubtedly a cleaner way to do this. But, I hope that this
71 // will allow this test code to port.
72 //
73 #ifdef HAVE_IOMANIP
74 #include <iomanip>
75 #define USE_IOMANP
76 #elif defined HAVE_IOMANIP_H
77 #include <iomanip.h>
78 #define USE_IOMANIP
79 #endif
80 #ifndef USE_IOMANIP
81 #define setw(a) ("")
82 #define setprecision(a) ("")
83 #endif
84 
85 #ifdef EPETRA_MPI
86 #include "mpi.h"
87 #include "Epetra_MpiComm.h"
88 #else
89 #include "Epetra_SerialComm.h"
90 #endif
91 
92 #include "Epetra_Comm.h"
93 
94 #include "SparseDirectTimingVars.h"
95 #include "Amesos_TestSolver.h"
96 
97 // #ifdef SOLARIS
98 // #include <unistd.h>
99 // #endif
100 
101 #if 0
102 extern "C" {
103 #include "BridgeMPI.h"
104 }
105 #endif
106 
107 // #include "TSF.h"
108 // using std::exception ;
109 
110 int main(int argc, char **argv)
111 {
112 
113  std::vector <double> BBval ;
114  BBval.resize(12);
115  //
116  // The following are the values returned from the tester
117  //
118 #ifdef EPETRA_MPI
119  MPI_Init(&argc,&argv);
120  Epetra_MpiComm Comm (MPI_COMM_WORLD);
121 #else
122  Epetra_SerialComm Comm;
123 #endif
124 
125  Epetra_Object::SetTracebackMode( 2 ); // Turns EPETRA_CHK_ERR() on
126  int MyPID = Comm.MyPID();
127  int NumMpiProcs = Comm.NumProc();
128 
129 #if 0
130  if (MyPID == 0 ) {
131  char junk;
132  std::cin >> junk ; // Wait for character input to give time to attach debuuger
133  }
134 #endif
135 
136  const int MAX_TOLERANCE_RATIO = 10000 ;
137  int exit_value = 0 ;
138  const int MAXNAMELENGTH = 800;
139 
140 #ifdef HAVE_SYS_UTSNAME_WORKS_H
141  utsname uname_buf;
142 #endif
143  char timebuffer[MAXNAMELENGTH];
144 
145  std::string Sprogram ;
146  if ( argc >1 ) Sprogram = argv[1] ;
147  const int NUM_PARAMS = 9 ;
148  const int NUM_SUPERLU_PARAMS = NUM_PARAMS + 1 ;
149  const int NUM_SPOOLES_PARAMS = NUM_PARAMS + 6 ;
150  bool argc_ok = ( argc == NUM_PARAMS ) ;
151  if ( argc == NUM_SPOOLES_PARAMS && Sprogram == "SPOOLES" ) argc_ok = true ;
152  if ( argc == NUM_SPOOLES_PARAMS && Sprogram == "SPOOLESSERIAL" )
153  argc_ok = true ;
154 
155  if ( argc == NUM_SUPERLU_PARAMS && Sprogram == "SuperLU" )
156  argc_ok = true ;
157 
158 //
159 // The usage print should be a subroutine and printed everywhere
160 // that we find a problem with the command line arguments
161 //
162  if ( ! argc_ok ) {
163  if ( MyPID == 0 ) {
164  std::cerr << " argc = " << argc << " Sprogam= " << Sprogram <<
165  " SPOOLES? " << (int) (Sprogram=="SPOOLES") << std::endl ;
166  std::cerr << "Usage: " << argv[0] <<" SolverName InputMatrix special numsolves transpose maxerror maxresid" << std::endl ;
167  std::cerr << " Solvername = UMFPACK, SUPERLUDIST, TAUCS, PARDISO, PARAKLETE, MUMPS, KLU, SUPERLU" << std::endl;
168  std::cerr << " InputMatrix must be a file in Harwell Boeing format"<< std::endl;
169  std::cerr << " special = number of repeats (0 means run just once) " << std::endl ;
170  std::cerr << " numsolves = number of right hand sidess (<0 means MRHS, >1 means BRHS) " << std::endl ;
171  std::cerr << " transpose = 1 means test A^T x = b instead of Ax = b" << std::endl ;
172  std::cerr << " maxerror = maximum allowed error < 0 == no check " << std::endl ;
173  std::cerr << " maxresid = maximum allowed residual < 0 == no check" << std::endl ;
174  std::cerr << " if maxerror == -2 and maxresid == -2, failure (hang or abort) is expected" << std::endl ;
175  std::cerr << " if maxerror == 1e30 and maxresid == 1e30, the solver is expected to finish but produce incorrect results" << std::endl ;
176 
177  }
178 #ifdef EPETRA_MPI
179  MPI_Finalize();
180 #endif
181  exit( -1 ) ;
182  }
183 
184  if ( MyPID == 0 ) {
185 #ifdef HAVE_SYS_UTSNAME_WORKS_H
186  int uname_stat = uname( &uname_buf ) ;
187 #endif
188 
189 #ifdef HAVE_TIME_H
190  time_t now = time( NULL ) ;
191  tm *localnow = localtime( &now ) ;
192  (void) strftime( timebuffer, MAXNAMELENGTH, "20%g%b%d@%H:%M:%S", localnow ) ;
193 #else
194  strcpy( timebuffer, "unknown date" ) ;
195 #endif
196  }
197 
198  //
199  // Open SST.log and SST.summary
200  //
201  char *ShortOutputFileName = (char *) "SST.summary" ;
202  char *LongOutputFileName = (char *) "SST.log" ;
203 
204  bool summary = MyPID == 0 ;
205 #ifdef AMESOS_TEST_VERBOSE
206  bool verbose = ( MyPID == 0 ) && true ;
207 #else
208  bool verbose = ( MyPID == 0 ) && false ;
209 #endif
210  bool log = MyPID == 0 ;
211 #ifdef SOLARIS
212  // log = false ; // On Solaris mpich, the second ofstream.open fails
213 #endif
214 
215  FILE *matrix_fd;
216  std::ofstream summary_file;
217 
218  if ( ( MyPID == 0 ) ) {
219  matrix_fd = fopen( argv[2], "r" ) ;
220  if ( matrix_fd == NULL ) {
221  std::cerr << "Unable to open " << argv[2] << " for reading" << std::endl ;
222  exit_value = - 1;
223  } else {
224  fclose( matrix_fd ) ;
225  }
226 
227  if ( log ) {
228  SparseDirectTimingVars::log_file.open( LongOutputFileName, std::ios::app ) ;
229  if ( SparseDirectTimingVars::log_file.fail() ) {
230  std::cerr << "Unable to open " << LongOutputFileName << " for writing" << std::endl ;
231  exit_value = - 1;
232  }
233  }
234 
235  if ( summary ) {
236  summary_file.open( ShortOutputFileName, std::ios::app ) ;
237  if ( summary_file.fail() ) {
238  std::cerr << "Unable to open " << ShortOutputFileName << " for writing" << std::endl ;
239  exit_value = - 1;
240  }
241  }
242  }
243 
244  //
245  // Check command line parameters
246  //
247  SparseSolverType SparseSolver ;
248 
249  int MatType = atoi( argv[3] ) ;
250  int special = atoi( argv[4] ) ;
251  int numsolves = atoi( argv[5] ) ;
252  int transpose = atoi( argv[6] ) ;
253  double maxerror = atof( argv[7] ) ; // Bump up the error margin for the release (but keep it lower for the dev branch )
254  double maxresid = atof( argv[8] ) ; // Bump up the error margin for the release (but keep it lower for the dev branch )
255 
256  if ( Sprogram == "LAPACK" )
257  SparseSolver = LAPACK ;
258  else if ( Sprogram == "KLU" )
259  SparseSolver = KLU ;
260  else if ( Sprogram == "UMFPACK" )
261  SparseSolver = UMFPACK ;
262  else if ( Sprogram == "SUPERLU" )
263  SparseSolver = SUPERLU ;
264  else if ( Sprogram == "SUPERLUDIST" )
265  SparseSolver = SUPERLUDIST ;
266  else if ( Sprogram == "DSCPACK" )
267  SparseSolver = DSCPACK ;
268  else if ( Sprogram == "TAUCS" )
269  SparseSolver = TAUCS ;
270  else if ( Sprogram == "PARDISO" )
271  SparseSolver = PARDISO ;
272  else if ( Sprogram == "PARAKLETE" )
273  SparseSolver = PARAKLETE ;
274  else if ( Sprogram == "MUMPS" )
275  SparseSolver = MUMPS ;
276  else if ( Sprogram == "SCALAPACK" )
277  SparseSolver = SCALAPACK ;
278  else {
279  if (( MyPID == 0 ) ) std::cerr << "Unknown program: " << Sprogram << std::endl ;
280  exit( -1 ) ;
281  }
282 
283  // return ok because I don't want to break the tests
284  // if the solver is not available
285 #ifndef HAVE_AMESOS_KLU
286  if (SparseSolver == KLU) {
287  std::cerr << "KLU is not installed..." << std::endl;
288  exit(EXIT_SUCCESS);
289  }
290 #endif
291 #ifndef HAVE_AMESOS_UMFPACK
292  if (SparseSolver == UMFPACK) {
293  std::cerr << "UMFPACK is not installed..." << std::endl;
294  exit(EXIT_SUCCESS);
295  }
296 #endif
297 #ifndef HAVE_AMESOS_SUPERLU
298  if (SparseSolver == SUPERLU) {
299  std::cerr << "SUPERLU is not installed..." << std::endl;
300  exit(EXIT_SUCCESS);
301  }
302 #endif
303 #ifndef HAVE_AMESOS_SUPERLUDIST
304  if (SparseSolver == SUPERLUDIST) {
305  std::cerr << "SUPERLUDIST is not installed..." << std::endl;
306  exit(EXIT_SUCCESS);
307  }
308 #endif
309 #ifndef HAVE_AMESOS_TAUCS
310  if (SparseSolver == TAUCS) {
311  std::cerr << "TAUCS is not installed..." << std::endl;
312  exit(EXIT_SUCCESS);
313  }
314 #endif
315 #ifndef HAVE_AMESOS_PARDISO
316  if (SparseSolver == PARDISO) {
317  std::cerr << "PARDISO is not installed..." << std::endl;
318  exit(EXIT_SUCCESS);
319  }
320 #endif
321 #ifndef HAVE_AMESOS_PARAKLETE
322  if (SparseSolver == PARAKLETE) {
323  std::cerr << "PARAKLETE is not installed..." << std::endl;
324  exit(EXIT_SUCCESS);
325  }
326 #endif
327 #ifndef HAVE_AMESOS_MUMPS
328  if (SparseSolver == MUMPS) {
329  std::cerr << "MUMPS is not installed..." << std::endl;
330  exit(EXIT_SUCCESS);
331  }
332 #endif
333 #ifndef HAVE_AMESOS_SCALAPACK
334  if (SparseSolver == SCALAPACK) {
335  std::cerr << "SCALAPACK is not installed..." << std::endl;
336  exit(EXIT_SUCCESS);
337  }
338 #endif
339 #ifndef HAVE_AMESOS_DSCPACK
340  if (SparseSolver == DSCPACK) {
341  std::cerr << "DSCPACK is not installed..." << std::endl;
342  exit(EXIT_SUCCESS);
343  }
344 #endif
345 
346  SuperLU_permc = 1 ; // Set the default to MMD on A'*A
347  if ( argc == NUM_SUPERLU_PARAMS &&
348  ( Sprogram == "SuperLU" || Sprogram == "SuperLUdist" ) ) {
349  SuperLU_permc = atoi( argv[8] );
350  assert( SuperLU_permc >= 0 && SuperLU_permc <= 3 ) ;
351  }
352 
353  const int MaxNumSolves = 3200 ;
354  if ( MatType < 0 || MatType > 1 ) {
355  if ( ( MyPID == 0 ) )
356  std::cerr << " MatType must be 0 or 1, is: "
357  << MatType << std::endl ;
358  exit_value = -1 ;
359  }
360  if ( special < 0 || special > 10000 ) {
361  if ( ( MyPID == 0 ) )
362  std::cerr << " No more than 10000 repeats allowed"
363  << special << std::endl ;
364  exit_value = -1 ;
365  }
366  if ( numsolves< -MaxNumSolves || numsolves > MaxNumSolves ) {
367  if ( ( MyPID == 0 ) )
368  std::cerr << "The number of solves must be between 0 and " << MaxNumSolves
369  << " is: "
370  << numsolves << std::endl ;
371  exit_value = -1 ;
372  }
373  if ( transpose< 0 || transpose > 1) {
374  if ( ( MyPID == 0 ) )
375  std::cerr << "transpose must be 0 (no trans) or 1"
376  << ", it is: "
377  << transpose << std::endl ;
378  exit_value = -1 ;
379  }
380  if ( transpose != 0 && SparseSolver == SUPERLUDIST ) {
381  if ( ( MyPID == 0 ) )
382  std::cerr << "Our use of SUPERLUDIST does not support transpose yet" << std::endl ;
383  exit_value = -1 ;
384  }
385  if ( numsolves != 1 &&
386  SparseSolver != LAPACK &&
387  SparseSolver != SUPERLUDIST &&
388  SparseSolver != DSCPACK &&
389  SparseSolver != UMFPACK &&
390  SparseSolver != KLU &&
391  SparseSolver != TAUCS &&
392  SparseSolver != PARDISO &&
393  SparseSolver != PARAKLETE &&
394  SparseSolver != MUMPS &&
395  SparseSolver != SCALAPACK &&
396  SparseSolver != SUPERLU ) {
397  if ( ( MyPID == 0 ) )
398  std::cerr << "Only LAPACK, SUPERLUDIST, UMFPACK, TAUCS, PARDISO, PARAKLETE, MUMPS, SCALAPACK, KLU and DSCPACK support MRHS and BRHS" << std::endl ;
399  exit_value = -1 ;
400  }
401 
402 
403 #ifdef HAVE_SYS_UTSNAME_WORKS_H
404  char *hostname = uname_buf.nodename ;
405  char *releasenum = uname_buf.release;
406 #else
407  char *hostname = (char *) "";
408 #endif
409 
410 
411 
412  Comm.Broadcast( &exit_value, 1, 0 ) ;
413 
414  if ( exit_value == 0 ) {
415 
416  AMESOS_MatrixType MatrixType = AMESOS_Serial ;
417  if ( MatType == 1 ) MatrixType = AMESOS_Distributed ;
418 
419  if ( log ) {
420  //
421  // Log time stamp and machine information
422  //
423 
424  SparseDirectTimingVars::log_file << std::endl << "TIMESTAMP:" << hostname << " "
425  << argv[1] << " " << timebuffer
426  << " BEGIN RUN" << std::endl ;
427 #ifdef HAVE_SYS_UTSNAME_WORKS_H
428  SparseDirectTimingVars::log_file << uname_buf.sysname <<
429  hostname << releasenum << uname_buf.version <<
430  uname_buf.machine << std::endl ;
431 #endif
432  }
433  if (summary ) {
434  summary_file << std::endl << setw(12) << hostname << " "
435  << setw(12) << argv[1]
436  << " " << setw(-1) << timebuffer << " "
437  << setw(15) << argv[2] << setw(6) << " "
438  << MatType << " "
439  << special << " "
440  << NumMpiProcs << setw(6) << " "
441  << numsolves << setw(3) << " " << transpose << setprecision(12) ;
442  if ( maxresid == -2 && maxerror == -2 ) summary_file << "Failure OK" ;
443  flush( summary_file ) ;
444  }
445  if (MyPID == 0 ) {
446  if ( verbose ) {
447  std::cerr << std::endl << setw(12) << hostname
448  << setw(12) << argv[1]
449  << " " << setw(-1) << timebuffer
450  << setw(15) << argv[2] << setw(6)
451  << MatType << " "
452  << special << " "
453  << NumMpiProcs << setw(6) << " "
454  << numsolves << setw(3) << " " << transpose << setprecision(12) ;
455  if ( maxresid == -2 && maxerror == -2 ) std::cerr << "Failure OK" ;
456  flush( std::cerr ) ;
457  }
458  }
459  //
460  // Perform the test
461  //
463 
464  try {
465 
466  if ( numsolves < 0 ) {
467  Amesos_TestMrhsSolver( Comm, argv[2], - numsolves, SparseSolver, (transpose==1), special, MatrixType ) ;
468  } else {
469  if ( numsolves > 1 ) {
470  Amesos_TestMultiSolver( Comm, argv[2], numsolves, SparseSolver, (transpose==1), special, MatrixType ) ;
471  } else {
472  Amesos_TestSolver( Comm, argv[2], SparseSolver, (transpose==1), special, MatrixType ) ;
473  }
474  }
475  //
476  // Log time and memory estimates
477  //
478  if ( log ) {
480 
481  //
482  // Print a single line to the summary file (and a copy of same to
483  // the log file (details_fd) then print a final line to the log
484  // file.
485  //
486  SparseDirectTimingVars::log_file << std::endl << "TIMESTAMP:" << hostname
487  << argv[1] << timebuffer
488  << " END RUN" << std::endl ;
489 
491  << setw(12) << hostname << setw(9) << argv[1]
492  << " " << setw(-1) << timebuffer
493  << setw(15) << argv[2] << setw(6) << NumMpiProcs << setw(6)
494  << special << " "
495  << numsolves << setw(6)
496  << transpose << setprecision(12) ;
498  SparseDirectTimingVars::log_file << "SS_Result = "
500  << std::endl ;
501 
502  }
503  if (summary ) {
505  if ( verbose )
507  bool ErrorOK = maxerror <= -1 ||
509  bool ResidualOK = maxresid <= -1 ||
511  if ( ErrorOK && ResidualOK ) summary_file << " OK" ;
512  if ( ErrorOK && ResidualOK && verbose ) std::cerr << " OK" ;
513  if ( ! ErrorOK ) {
514  summary_file << " Error too large is: " <<
516  " should be < " << maxerror ;
517  std::cerr << " Error too large is: " <<
519  " should be < " << maxerror ;
520  }
521  //
522  // Here we check to see if the answer is better than we expect.
523  //
524  // 1e30 means that the code promises to complete but makes no
525  // promise about the answer
526  // If maxerror is 1e30, we set it to 10, meaning that if the actual
527  // answer is good to 10/ MAX_TOLERANCE_RATIO (presently 10/1000 = .01)
528  // we print a TOLERANCE is too large message.
529  //
530  if (maxerror == 1e30 ) maxerror = 10 ;
531  if (SparseDirectTimingVars::SS_Result.Get_Error() < maxerror / MAX_TOLERANCE_RATIO &&
532  maxerror > 1.1e-14 ) {
533  summary_file << " Error TOLERANCE is too large: " <<
535  " is allowed to be " << maxerror ;
536  if ( verbose ) {
537  std::cerr << " Error TOLERANCE is too large: " <<
539  " is allowed to be " << maxerror ;
540  }
541  }
542  if ( ! ResidualOK ) {
543  summary_file << " Residual too large is:" <<
545  " should be < " << maxresid ;
546  std::cerr << " Residual too large is:" <<
548  " should be < " << maxresid ;
549  }
550 
551  if (maxresid == 1e30 ) maxresid = 10 ;
552  if (SparseDirectTimingVars::SS_Result.Get_Residual() < maxresid / MAX_TOLERANCE_RATIO &&
553  maxresid > 1.1e-14 ) {
554  summary_file << " Residual TOLERANCE is too large: " <<
556  " is allowed to be " << maxresid ;
557  if ( verbose ) {
558  std::cerr << " Residual TOLERANCE is too large: " <<
560  " is allowed to be " << maxresid ;
561  }
562  }
563 
564  flush( summary_file ) ;
565  if ( verbose ) {
566  std::cerr << std::endl ; // Atlantis won't print anything without this.
567  flush( std::cerr ) ;
568  }
569  }
570  }
571  catch(const std::string &errormsg)
572  {
573  if ( summary ) { summary_file << errormsg ; }
574  if ( log ) SparseDirectTimingVars::log_file << errormsg ;
575  if ( ( verbose ) || summary ) std::cerr << errormsg << std::endl;
576  }
577 
578  }
579 
580  if ( summary ) summary_file.close() ;
581  if ( log ) SparseDirectTimingVars::log_file.close() ;
582 
583 #ifdef EPETRA_MPI
584  MPI_Finalize();
585 #endif
586  exit( exit_value ) ;
587 }
588 
589 
590 
#define setw(a)
const int MatType
virtual void PrintSummary(std::ostream &os) const
int Amesos_TestMrhsSolver(Epetra_Comm &Comm, char *matrix_file, int numsolves, SparseSolverType SparseSolver, bool transpose, int special, AMESOS_MatrixType matrix_type)
static bool verbose
Definition: Amesos.cpp:67
SparseSolverType
int MyPID() const
int Amesos_TestSolver(Epetra_Comm &Comm, char *matrix_file, SparseSolverType SparseSolver, bool transpose, int special, AMESOS_MatrixType matrix_type)
int SuperLU_permc
AMESOS_MatrixType
int main(int argc, char *argv[])
int Amesos_TestMultiSolver(Epetra_Comm &Comm, char *matrix_file, int numsolves, SparseSolverType SparseSolver, bool transpose, int special, AMESOS_MatrixType matrix_type)
int NumProc() const
static std::ofstream log_file
#define setprecision(a)
int Broadcast(double *MyVals, int Count, int Root) const
static SparseSolverResult SS_Result