fei_test_utils.cpp

00001 /*--------------------------------------------------------------------*/
00002 /*    Copyright 2005 Sandia Corporation.                              */
00003 /*    Under the terms of Contract DE-AC04-94AL85000, there is a       */
00004 /*    non-exclusive license for use of this work by or on behalf      */
00005 /*    of the U.S. Government.  Export of this program may require     */
00006 /*    a license from the United States Government.                    */
00007 /*--------------------------------------------------------------------*/
00008 #include <fei_sstream.hpp>
00009 #include <fei_fstream.hpp>
00010 
00011 #include <fei_test_utils.hpp>
00012 
00013 #include <snl_fei_Utils.hpp>
00014 #include <fei_VectorSpace.hpp>
00015 #include <fei_MatrixGraph.hpp>
00016 #include <fei_Matrix.hpp>
00017 
00018 #include <cmath>
00019 
00020 #undef fei_file
00021 #define fei_file "fei_test_utils.cpp"
00022 #include <fei_ErrMacros.hpp>
00023 
00024 namespace fei_test_utils {
00025 
00026 std::string construct_filename(int argc, char** argv)
00027 {
00028   std::string path(".");
00029   std::string filename;
00030   std::string result;
00031 
00032   int dashDarg = whichArg(argc, argv, "-d");
00033 
00034   int dashIarg = whichArg(argc, argv, "-i");
00035 
00036   if (dashIarg < 0) {
00037     FEI_CERR << "fei_test_utils::construct_filename: argument '-i' not found."
00038              << FEI_ENDL;
00039     return(result);
00040   }
00041 
00042   if (dashDarg > -1 && argc > dashDarg+1) {
00043     if (argv[dashDarg+1] != 0) {
00044       path = argv[dashDarg+1];
00045     }
00046   }
00047 
00048   if (argc > dashIarg+1) {
00049     if (argv[dashIarg+1] != 0) {
00050       filename = argv[dashIarg+1];
00051     }
00052   }
00053 
00054   FEI_OSTRINGSTREAM osstr;
00055   osstr << path;
00056 
00057   std::size_t string_length = path.size();
00058   if (path[string_length-1] != '/') osstr << "/";
00059   
00060   osstr << filename;
00061 
00062   return( osstr.str() );
00063 }
00064 
00065 int initialize_mpi(int argc, char** argv, int& localProc, int& numProcs)
00066 {
00067 #ifndef FEI_SER
00068   if (MPI_Init(&argc, &argv) != MPI_SUCCESS) ERReturn(-1);
00069   if (MPI_Comm_rank(MPI_COMM_WORLD, &localProc) != MPI_SUCCESS) ERReturn(-1);
00070   if (MPI_Comm_size(MPI_COMM_WORLD, &numProcs) != MPI_SUCCESS) ERReturn(-1);
00071 #else
00072   localProc = 0;
00073   numProcs = 1;
00074 #endif
00075   return(0);
00076 }
00077 
00078 bool bool_arg(const char* flag, int argc, char** argv,
00079                        bool default_result)
00080 {
00081   int arg_index = whichArg(argc, argv, flag);
00082   bool result = default_result;
00083   if (arg_index > -1) {
00084     if (argc > arg_index+1) {
00085       if (argv[arg_index+1] != 0) {
00086         std::string strarg(argv[arg_index+1]);
00087         if (strarg == "yes" || strarg == "Yes" || strarg == "YES" ||
00088             strarg == "true" || strarg == "True" || strarg == "TRUE") {
00089           result = true;
00090         }
00091 
00092         if (strarg == "no" || strarg == "No" || strarg == "NO" ||
00093             strarg == "false" || strarg == "False" || strarg == "FALSE") {
00094           result = false;
00095         }
00096       }
00097     }
00098   }
00099 
00100   return(result);
00101 }
00102 
00103 std::string get_arg_value(const char* flag, int argc, char** argv)
00104 {
00105   std::string result;
00106   int arg_index = whichArg(argc, argv, flag);
00107   if (arg_index > -1) {
00108     if (argc > arg_index+1) {
00109       if (argv[arg_index+1] != 0) {
00110         result = argv[arg_index+1];
00111       }
00112     }
00113   }
00114 
00115   return(result);
00116 }
00117 
00118 void broadcast_string(MPI_Comm comm, int root, std::string& strg)
00119 {
00120 #ifdef FEI_SER
00121   return;
00122 #else
00123   int numprocs = 1, localproc = 0;
00124   MPI_Comm_size(MPI_COMM_WORLD, &numprocs);
00125   MPI_Comm_rank(MPI_COMM_WORLD, &localproc);
00126   if (numprocs==1) {
00127     return;
00128   }
00129 
00130   if (localproc == root) {
00131     int length = strg.size();
00132     MPI_Bcast(&length, 1, MPI_INT, root, comm);
00133     char* cstr = const_cast<char*>(strg.c_str());
00134     MPI_Bcast(cstr, strg.size(), MPI_CHAR, root, comm);
00135   }
00136   else {
00137     int length;
00138     MPI_Bcast(&length, 1, MPI_INT, root, comm);
00139     char* charstr = new char[length+1];
00140     MPI_Bcast(charstr, length, MPI_CHAR, root, comm);
00141     charstr[length] = '\0';
00142     strg = charstr;
00143     delete [] charstr;
00144   }
00145 
00146   return;
00147 #endif
00148 }
00149 
00150 void read_file_lines_into_strings(const char* filename,
00151            std::vector<std::string>& file_contents)
00152 {
00153   FEI_IFSTREAM infile(filename);
00154   if (!infile) {
00155     FEI_OSTRINGSTREAM osstr;
00156     osstr << "fei_test_utils::read_file_lines_into_strings ERROR, couldn't open file '"
00157          << filename << "'";
00158     throw std::runtime_error(osstr.str());
00159   }
00160 
00161   file_contents.clear();
00162 
00163   std::string line;
00164 
00165   getline(infile, line);
00166   while(!infile.eof()) {
00167     file_contents.push_back(line);
00168 
00169     line.resize(0);
00170     getline(infile, line);
00171   }
00172 }
00173 
00174 int get_filename_and_read_input(int argc, char** argv,
00175          MPI_Comm comm, int localProc,
00176          std::vector<std::string>& stdstrings)
00177 {
00178   std::string filename;
00179   if (localProc == 0) {
00180     filename = construct_filename(argc, argv);
00181   }
00182 
00183   try {
00184     read_input_file(filename.c_str(), comm, stdstrings);
00185   }
00186   catch(std::runtime_error& exc) {
00187     FEI_CERR << exc.what() << FEI_ENDL;
00188     ERReturn(-1);
00189   }
00190 
00191   return(0);
00192 }
00193 
00194 void read_input_file(const char* filename,
00195           MPI_Comm comm,
00196           std::vector<std::string>& file_contents)
00197 {
00198   int localProc =0;
00199 #ifndef FEI_SER
00200   int numProcs = 1;
00201   MPI_Comm_rank(comm, &localProc);
00202   MPI_Comm_size(comm, &numProcs);
00203 #endif
00204 
00205   if (localProc == 0) {
00206     read_file_lines_into_strings(filename, file_contents);
00207 
00208 #ifndef FEI_SER
00209     if (numProcs > 1) {
00210       int num = file_contents.size();
00211 
00212       MPI_Bcast(&num, 1, MPI_INT, 0, comm);
00213 
00214       for(int j=0; j<num; ++j) {
00215         const char* cptr = file_contents[j].c_str();
00216         int length = strlen(cptr) + 1;
00217         MPI_Bcast(&length, 1, MPI_INT, 0, comm);
00218         MPI_Bcast((void*)cptr, length, MPI_CHAR, 0, comm);
00219       }
00220     }
00221 #endif
00222   }
00223 #ifndef FEI_SER
00224   else {//localProc != 0
00225     int num = -1;
00226     MPI_Bcast(&num, 1, MPI_INT, 0, comm);
00227 
00228     file_contents.resize(0);
00229 
00230     for(int j=0; j<num; ++j) {
00231       int length = 0;
00232       MPI_Bcast(&length, 1, MPI_INT, 0, comm);
00233       char* newstring = new char[length];
00234       MPI_Bcast(newstring, length, MPI_CHAR, 0, comm);
00235       std::string strg(newstring);
00236       file_contents.push_back(strg);
00237       delete [] newstring;
00238     }
00239   }
00240 #endif
00241 }
00242 
00243 double get_file_benchmark(const char* filename,
00244          const char* testname)
00245 {
00246   std::vector<std::string> file_contents;
00247   read_file_lines_into_strings(filename, file_contents);
00248 
00249   double file_benchmark = 0.0;
00250   int err2 = snl_fei::getDoubleParamValue(testname,
00251             file_contents,
00252             file_benchmark);
00253   if (err2 != 0) {
00254     throw std::runtime_error("fei_test_utils::get_file_benchmark failed to find named benchmark");
00255   }
00256 
00257   return(file_benchmark);
00258 }
00259 
00260 bool within_percentage_margin(double value1,
00261              double value2,
00262              unsigned margin)
00263 {
00264   double maxval = std::abs(value1) > std::abs(value2) ? std::abs(value1) : std::abs(value2);
00265   if (maxval < 1.e-14) {
00266     //They're both close enough to zero, return true without dividing.
00267     return(true);
00268   }
00269 
00270   double difference = std::abs(value2 - value1);
00271   double lhs = 100.0*(difference/maxval);
00272   double rhs = 1.0*margin;
00273   return( lhs <= rhs );
00274 }
00275 
00276 int whichArg(int argc, const char*const* argv, const char* findarg)
00277 {
00278   for(int i=0; i<argc; i++) {
00279     if (argv[i] != NULL) {
00280       if (strcmp(findarg, argv[i]) == 0) return(i);
00281     }
00282   }
00283   return(-1);
00284 }
00285 
00286 bool check_and_cout_test_result(std::string testname,
00287          double value,
00288          double file_value,
00289          unsigned margin)
00290 {
00291   bool result = within_percentage_margin(value, file_value, margin);
00292   FEI_COUT << testname << " " << value << " ";
00293   if (!result) {
00294     FEI_COUT << "NOT ";
00295   }
00296   FEI_COUT << "within "<<margin<<"% of file value " << file_value << ". ";
00297 
00298   if (result) {
00299     FEI_COUT << "passed."<<FEI_ENDL;
00300   }
00301   else {
00302     FEI_COUT << "FAILED."<<FEI_ENDL;
00303   }
00304   return(result);
00305 }
00306 
00307 std::string check_test_result(double value,
00308         double goldvalue,
00309         unsigned margin)
00310 {
00311   bool result = within_percentage_margin(value, goldvalue, margin);
00312   return( result ? "passed" : "FAILED");
00313 }
00314 
00315 int compare_with_file_benchmark(const char* name,
00316          double benchmark,
00317          const char* filename)
00318 {
00319   if (name == NULL) return(-1);
00320   int returnValue = 0;
00321 
00322 #if defined(FEI_PLATFORM) && defined(FEI_OPT_LEVEL)
00323 
00324   FEI_OSTRINGSTREAM testname;
00325   testname << name<<"_"<<FEI_PLATFORM<<"_"<<FEI_OPT_LEVEL;
00326 
00327   double file_benchmark = 0.0;
00328   bool file_benchmark_available = true;
00329   try {
00330     file_benchmark = get_file_benchmark(filename, testname.str().c_str());
00331   }
00332   catch (std::runtime_error& exc) {
00333     file_benchmark_available = false;
00334   }
00335 
00336   if (file_benchmark_available) {
00337     bool test_passed = check_and_cout_test_result(testname.str(),
00338                  benchmark,
00339                  file_benchmark,
00340                  10);
00341     returnValue = test_passed ? 0 : 1;
00342     if (returnValue != 0) {
00343       return(returnValue);
00344     }
00345   }
00346 
00347 #else
00348   FEI_COUT << "(compile with -DFEI_PLATFORM=<platform> -DFEI_OPT_LEVEL=<opt|dbg>)"<<FEI_ENDL;
00349 #endif
00350 
00351   return(returnValue);
00352 }
00353 
00354 int dirname(const char* name, char*& dir)
00355 {
00356   //given a string which is a file-name, create a new string 'dir' and
00357   //populate it with the directory-name, or file-name minus the last '/file'
00358   //section.
00359 
00360   int i, len = strlen(name);
00361   dir = new char[len];
00362   for(i=0; i<len; ++i) {
00363     dir[i] = name[i];
00364   }
00365 
00366   i = len-1;
00367   if (i > 1) {
00368     while(i>0) {
00369       if (dir[i] == '/') {
00370   dir[i] = '\0';
00371   break;
00372       }
00373       else {
00374   dir[i] = '\0';
00375   --i;
00376       }
00377     }
00378   }
00379 
00380   if (i==0) dir[i] = '.';
00381 
00382   return(0);
00383 }
00384 
00385 void print_args(int argc, char** argv){
00386     FEI_COUT << "argc: " << argc << FEI_ENDL;
00387 
00388     for(int i=0; i<argc; i++){
00389       if (argv[i] != NULL) {
00390         FEI_COUT << "argv["<<i<<"]: " << argv[i] << FEI_ENDL;
00391       }
00392     }
00393     FEI_COUT << FEI_ENDL;
00394 }
00395 
00396 int compareMatrices(fei::FillableMat& mat1, fei::FillableMat& mat2, double tol)
00397 {
00398   if (mat1 == mat2) return 0;
00399   FEI_COUT << "compareMatrices returned not-equal, tol=="<<tol << FEI_ENDL;
00400   return 1;
00401 }
00402 
00403 int readMatrix(const char* baseName, int np, fei::FillableMat& matrix)
00404 {
00405   for(int i=0; i<np; i++) {
00406     FEI_OSTRINGSTREAM fileName;
00407     fileName <<baseName<<"."<<np<<"."<<i;
00408     FEI_IFSTREAM infile(fileName.str().c_str());
00409 
00410     infile.setf(IOS_SCIENTIFIC, IOS_FLOATFIELD);
00411 
00412     int row, col, tmp, numRows, numCols;
00413     double value;
00414     infile >> numRows;
00415     infile >> numCols;
00416     infile >> tmp;
00417 
00418     infile >> row;
00419     while(!infile.eof()) {
00420       infile >> col;
00421       infile >> value;
00422 
00423       matrix.putCoef(row, col, value);
00424 
00425       infile >> row;
00426     }
00427   }
00428 
00429   return(0);
00430 }
00431 
00432 int readMatrix(const char* fileName, fei::FillableMat& matrix)
00433 {
00434   matrix.clear();
00435 
00436   FEI_IFSTREAM infile(fileName);
00437   if (!infile) {
00438     FEI_COUT << "ERROR opening file " << fileName << FEI_ENDL;
00439     return(1);
00440   }
00441 
00442   infile.setf(IOS_SCIENTIFIC, IOS_FLOATFIELD);
00443 
00444   int row, col, tmp, numRows, numCols;
00445   double value;
00446   infile >> numRows;
00447   infile >> numCols;
00448   infile >> tmp;
00449 
00450   infile >> row;
00451   while(!infile.eof()) {
00452     infile >> col;
00453     infile >> value;
00454 
00455     matrix.putCoef(row, col, value);
00456 
00457     infile >> row;
00458   }
00459 
00460   return(0);
00461 }
00462 
00463 int writeMatrix(const char* fileName, fei::FillableMat& matrix)
00464 {
00465   FEI_OFSTREAM outfile(fileName);
00466   if (!outfile) {
00467     FEI_COUT << "ERROR opening file " << fileName << FEI_ENDL;
00468     return(1);
00469   }
00470 
00471   outfile.setf(IOS_SCIENTIFIC, IOS_FLOATFIELD);
00472 
00473   outfile << matrix;
00474 
00475   return(0);
00476 }
00477 
00478 int copy_feiMatrix_to_FillableMat(fei::Matrix& feimat, fei::FillableMat& fmat)
00479 {
00480   fmat.clear();
00481 
00482   fei::SharedPtr<fei::VectorSpace> rowspace =
00483     feimat.getMatrixGraph()->getRowSpace();
00484 
00485   MPI_Comm comm = rowspace->getCommunicator();
00486   int localProc = fei::localProc(comm);
00487 
00488   std::vector<int> globalOffsets;
00489   rowspace->getGlobalIndexOffsets(globalOffsets);
00490   int numLocalRows = globalOffsets[localProc+1]-globalOffsets[localProc];
00491   int firstLocalRow = globalOffsets[localProc];
00492 
00493   for(int i=0; i<numLocalRows; ++i) {
00494     int row = firstLocalRow+i;
00495     int rowLen;
00496     feimat.getRowLength(row, rowLen);
00497 
00498     std::vector<int> colindices(rowLen);
00499     std::vector<double> coefs(rowLen);
00500 
00501     feimat.copyOutRow(row, rowLen, &coefs[0], &colindices[0]);
00502 
00503     fmat.putRow(row, &colindices[0], &coefs[0], rowLen);
00504   }
00505 
00506   return(0);
00507 }
00508 
00509 } //namespace fei_test_utils

Generated on Tue Jul 13 09:27:46 2010 for FEI by  doxygen 1.4.7