FEI  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
fei_test_utils.cpp
1 /*--------------------------------------------------------------------*/
2 /* Copyright 2005 Sandia Corporation. */
3 /* Under the terms of Contract DE-AC04-94AL85000, there is a */
4 /* non-exclusive license for use of this work by or on behalf */
5 /* of the U.S. Government. Export of this program may require */
6 /* a license from the United States Government. */
7 /*--------------------------------------------------------------------*/
8 #include <fei_sstream.hpp>
9 #include <fei_fstream.hpp>
10 
11 #include <fei_test_utils.hpp>
12 
13 #include <snl_fei_Utils.hpp>
14 #include <fei_VectorSpace.hpp>
15 #include <fei_MatrixGraph.hpp>
16 #include <fei_Matrix.hpp>
17 
18 #include <cmath>
19 
20 #undef fei_file
21 #define fei_file "fei_test_utils.cpp"
22 #include <fei_ErrMacros.hpp>
23 
24 namespace fei_test_utils {
25 
26 std::string construct_filename(int argc, char** argv)
27 {
28  std::string path(".");
29  std::string filename;
30  std::string result;
31 
32  int dashDarg = whichArg(argc, argv, "-d");
33 
34  int dashIarg = whichArg(argc, argv, "-i");
35 
36  if (dashIarg < 0) {
37  fei::console_out() << "fei_test_utils::construct_filename: argument '-i' not found."
38  << FEI_ENDL;
39  return(result);
40  }
41 
42  if (dashDarg > -1 && argc > dashDarg+1) {
43  if (argv[dashDarg+1] != 0) {
44  path = argv[dashDarg+1];
45  }
46  }
47 
48  if (argc > dashIarg+1) {
49  if (argv[dashIarg+1] != 0) {
50  filename = argv[dashIarg+1];
51  }
52  }
53 
54  FEI_OSTRINGSTREAM osstr;
55  osstr << path;
56 
57  std::size_t string_length = path.size();
58  if (path[string_length-1] != '/') osstr << "/";
59 
60  osstr << filename;
61 
62  return( osstr.str() );
63 }
64 
65 int initialize_mpi(int argc, char** argv, int& localProc, int& numProcs)
66 {
67 #ifndef FEI_SER
68  if (MPI_Init(&argc, &argv) != MPI_SUCCESS) ERReturn(-1);
69  if (MPI_Comm_rank(MPI_COMM_WORLD, &localProc) != MPI_SUCCESS) ERReturn(-1);
70  if (MPI_Comm_size(MPI_COMM_WORLD, &numProcs) != MPI_SUCCESS) ERReturn(-1);
71 #else
72  localProc = 0;
73  numProcs = 1;
74 #endif
75  return(0);
76 }
77 
78 bool bool_arg(const char* flag, int argc, char** argv,
79  bool default_result)
80 {
81  int arg_index = whichArg(argc, argv, flag);
82  bool result = default_result;
83  if (arg_index > -1) {
84  if (argc > arg_index+1) {
85  if (argv[arg_index+1] != 0) {
86  std::string strarg(argv[arg_index+1]);
87  if (strarg == "yes" || strarg == "Yes" || strarg == "YES" ||
88  strarg == "true" || strarg == "True" || strarg == "TRUE") {
89  result = true;
90  }
91 
92  if (strarg == "no" || strarg == "No" || strarg == "NO" ||
93  strarg == "false" || strarg == "False" || strarg == "FALSE") {
94  result = false;
95  }
96  }
97  }
98  }
99 
100  return(result);
101 }
102 
103 std::string get_arg_value(const char* flag, int argc, char** argv)
104 {
105  std::string result;
106  int arg_index = whichArg(argc, argv, flag);
107  if (arg_index > -1) {
108  if (argc > arg_index+1) {
109  if (argv[arg_index+1] != 0) {
110  result = argv[arg_index+1];
111  }
112  }
113  }
114 
115  return(result);
116 }
117 
118 void broadcast_string(MPI_Comm comm, int root, std::string& strg)
119 {
120 #ifdef FEI_SER
121  return;
122 #else
123  int numprocs = 1, localproc = 0;
124  MPI_Comm_size(MPI_COMM_WORLD, &numprocs);
125  MPI_Comm_rank(MPI_COMM_WORLD, &localproc);
126  if (numprocs==1) {
127  return;
128  }
129 
130  if (localproc == root) {
131  int length = strg.size();
132  MPI_Bcast(&length, 1, MPI_INT, root, comm);
133  char* cstr = const_cast<char*>(strg.c_str());
134  MPI_Bcast(cstr, strg.size(), MPI_CHAR, root, comm);
135  }
136  else {
137  int length;
138  MPI_Bcast(&length, 1, MPI_INT, root, comm);
139  char* charstr = new char[length+1];
140  MPI_Bcast(charstr, length, MPI_CHAR, root, comm);
141  charstr[length] = '\0';
142  strg = charstr;
143  delete [] charstr;
144  }
145 
146  return;
147 #endif
148 }
149 
150 void read_file_lines_into_strings(const char* filename,
151  std::vector<std::string>& file_contents)
152 {
153  FEI_IFSTREAM infile(filename);
154  if (!infile) {
155  FEI_OSTRINGSTREAM osstr;
156  osstr << "fei_test_utils::read_file_lines_into_strings ERROR, couldn't open file '"
157  << filename << "'";
158  throw std::runtime_error(osstr.str());
159  }
160 
161  file_contents.clear();
162 
163  std::string line;
164 
165  getline(infile, line);
166  while(!infile.eof()) {
167  file_contents.push_back(line);
168 
169  line.resize(0);
170  getline(infile, line);
171  }
172 }
173 
174 int get_filename_and_read_input(int argc, char** argv,
175  MPI_Comm comm, int localProc,
176  std::vector<std::string>& stdstrings)
177 {
178  std::string filename;
179  if (localProc == 0) {
180  filename = construct_filename(argc, argv);
181  }
182 
183  try {
184  read_input_file(filename.c_str(), comm, stdstrings);
185  }
186  catch(std::runtime_error& exc) {
187  fei::console_out() << exc.what() << FEI_ENDL;
188  ERReturn(-1);
189  }
190 
191  return(0);
192 }
193 
194 void read_input_file(const char* filename,
195  MPI_Comm comm,
196  std::vector<std::string>& file_contents)
197 {
198  int localProc =0;
199 #ifndef FEI_SER
200  int numProcs = 1;
201  MPI_Comm_rank(comm, &localProc);
202  MPI_Comm_size(comm, &numProcs);
203 #endif
204 
205  if (localProc == 0) {
206  read_file_lines_into_strings(filename, file_contents);
207 
208 #ifndef FEI_SER
209  if (numProcs > 1) {
210  int num = file_contents.size();
211 
212  MPI_Bcast(&num, 1, MPI_INT, 0, comm);
213 
214  for(int j=0; j<num; ++j) {
215  const char* cptr = file_contents[j].c_str();
216  int length = strlen(cptr) + 1;
217  MPI_Bcast(&length, 1, MPI_INT, 0, comm);
218  MPI_Bcast((void*)cptr, length, MPI_CHAR, 0, comm);
219  }
220  }
221 #endif
222  }
223 #ifndef FEI_SER
224  else {//localProc != 0
225  int num = -1;
226  MPI_Bcast(&num, 1, MPI_INT, 0, comm);
227 
228  file_contents.resize(0);
229 
230  for(int j=0; j<num; ++j) {
231  int length = 0;
232  MPI_Bcast(&length, 1, MPI_INT, 0, comm);
233  char* newstring = new char[length];
234  MPI_Bcast(newstring, length, MPI_CHAR, 0, comm);
235  std::string strg(newstring);
236  file_contents.push_back(strg);
237  delete [] newstring;
238  }
239  }
240 #endif
241 }
242 
243 double get_file_benchmark(const char* filename,
244  const char* testname)
245 {
246  std::vector<std::string> file_contents;
247  read_file_lines_into_strings(filename, file_contents);
248 
249  double file_benchmark = 0.0;
250  int err2 = snl_fei::getDoubleParamValue(testname,
251  file_contents,
252  file_benchmark);
253  if (err2 != 0) {
254  throw std::runtime_error("fei_test_utils::get_file_benchmark failed to find named benchmark");
255  }
256 
257  return(file_benchmark);
258 }
259 
260 bool within_percentage_margin(double value1,
261  double value2,
262  unsigned margin)
263 {
264  double maxval = std::abs(value1) > std::abs(value2) ? std::abs(value1) : std::abs(value2);
265  if (maxval < 1.e-14) {
266  //They're both close enough to zero, return true without dividing.
267  return(true);
268  }
269 
270  double difference = std::abs(value2 - value1);
271  double lhs = 100.0*(difference/maxval);
272  double rhs = 1.0*margin;
273  return( lhs <= rhs );
274 }
275 
276 int whichArg(int argc, const char*const* argv, const char* findarg)
277 {
278  for(int i=0; i<argc; i++) {
279  if (argv[i] != NULL) {
280  if (strcmp(findarg, argv[i]) == 0) return(i);
281  }
282  }
283  return(-1);
284 }
285 
286 bool check_and_cout_test_result(std::string testname,
287  double value,
288  double file_value,
289  unsigned margin)
290 {
291  bool result = within_percentage_margin(value, file_value, margin);
292  FEI_COUT << testname << " " << value << " ";
293  if (!result) {
294  FEI_COUT << "NOT ";
295  }
296  FEI_COUT << "within "<<margin<<"% of file value " << file_value << ". ";
297 
298  if (result) {
299  FEI_COUT << "passed."<<FEI_ENDL;
300  }
301  else {
302  FEI_COUT << "FAILED."<<FEI_ENDL;
303  }
304  return(result);
305 }
306 
307 std::string check_test_result(double value,
308  double goldvalue,
309  unsigned margin)
310 {
311  bool result = within_percentage_margin(value, goldvalue, margin);
312  return( result ? "passed" : "FAILED");
313 }
314 
315 int compare_with_file_benchmark(const char* name,
316  double benchmark,
317  const char* filename)
318 {
319  if (name == NULL) return(-1);
320  int returnValue = 0;
321 
322 #if defined(FEI_PLATFORM) && defined(FEI_OPT_LEVEL)
323 
324  FEI_OSTRINGSTREAM testname;
325  testname << name<<"_"<<FEI_PLATFORM<<"_"<<FEI_OPT_LEVEL;
326 
327  double file_benchmark = 0.0;
328  bool file_benchmark_available = true;
329  try {
330  file_benchmark = get_file_benchmark(filename, testname.str().c_str());
331  }
332  catch (std::runtime_error& exc) {
333  file_benchmark_available = false;
334  }
335 
336  if (file_benchmark_available) {
337  bool test_passed = check_and_cout_test_result(testname.str(),
338  benchmark,
339  file_benchmark,
340  10);
341  returnValue = test_passed ? 0 : 1;
342  if (returnValue != 0) {
343  return(returnValue);
344  }
345  }
346 
347 #else
348  FEI_COUT << "(compile with -DFEI_PLATFORM=<platform> -DFEI_OPT_LEVEL=<opt|dbg>)"<<FEI_ENDL;
349 #endif
350 
351  return(returnValue);
352 }
353 
354 int dirname(const char* name, char*& dir)
355 {
356  //given a string which is a file-name, create a new string 'dir' and
357  //populate it with the directory-name, or file-name minus the last '/file'
358  //section.
359 
360  int i, len = strlen(name);
361  dir = new char[len];
362  for(i=0; i<len; ++i) {
363  dir[i] = name[i];
364  }
365 
366  i = len-1;
367  if (i > 1) {
368  while(i>0) {
369  if (dir[i] == '/') {
370  dir[i] = '\0';
371  break;
372  }
373  else {
374  dir[i] = '\0';
375  --i;
376  }
377  }
378  }
379 
380  if (i==0) dir[i] = '.';
381 
382  return(0);
383 }
384 
385 void print_args(int argc, char** argv){
386  FEI_COUT << "argc: " << argc << FEI_ENDL;
387 
388  for(int i=0; i<argc; i++){
389  if (argv[i] != NULL) {
390  FEI_COUT << "argv["<<i<<"]: " << argv[i] << FEI_ENDL;
391  }
392  }
393  FEI_COUT << FEI_ENDL;
394 }
395 
396 int compareMatrices(fei::FillableMat& mat1, fei::FillableMat& mat2, double tol)
397 {
398  if (mat1 == mat2) return 0;
399  FEI_COUT << "compareMatrices returned not-equal, tol=="<<tol << FEI_ENDL;
400  return 1;
401 }
402 
403 int readMatrix(const char* baseName, int np, fei::FillableMat& matrix)
404 {
405  for(int i=0; i<np; i++) {
406  FEI_OSTRINGSTREAM fileName;
407  fileName <<baseName<<"."<<np<<"."<<i;
408  FEI_IFSTREAM infile(fileName.str().c_str());
409 
410  infile.setf(IOS_SCIENTIFIC, IOS_FLOATFIELD);
411 
412  int row, col, tmp, numRows, numCols;
413  double value;
414  infile >> numRows;
415  infile >> numCols;
416  infile >> tmp;
417 
418  infile >> row;
419  while(!infile.eof()) {
420  infile >> col;
421  infile >> value;
422 
423  matrix.putCoef(row, col, value);
424 
425  infile >> row;
426  }
427  }
428 
429  return(0);
430 }
431 
432 int readMatrix(const char* fileName, fei::FillableMat& matrix)
433 {
434  matrix.clear();
435 
436  FEI_IFSTREAM infile(fileName);
437  if (!infile) {
438  FEI_COUT << "ERROR opening file " << fileName << FEI_ENDL;
439  return(1);
440  }
441 
442  infile.setf(IOS_SCIENTIFIC, IOS_FLOATFIELD);
443 
444  int row, col, tmp, numRows, numCols;
445  double value;
446  infile >> numRows;
447  infile >> numCols;
448  infile >> tmp;
449 
450  infile >> row;
451  while(!infile.eof()) {
452  infile >> col;
453  infile >> value;
454 
455  matrix.putCoef(row, col, value);
456 
457  infile >> row;
458  }
459 
460  return(0);
461 }
462 
463 int writeMatrix(const char* fileName, fei::FillableMat& matrix)
464 {
465  FEI_OFSTREAM outfile(fileName);
466  if (!outfile) {
467  FEI_COUT << "ERROR opening file " << fileName << FEI_ENDL;
468  return(1);
469  }
470 
471  outfile.setf(IOS_SCIENTIFIC, IOS_FLOATFIELD);
472 
473  outfile << matrix;
474 
475  return(0);
476 }
477 
478 int copy_feiMatrix_to_FillableMat(fei::Matrix& feimat, fei::FillableMat& fmat)
479 {
480  fmat.clear();
481 
483  feimat.getMatrixGraph()->getRowSpace();
484 
485  MPI_Comm comm = rowspace->getCommunicator();
486  int localProc = fei::localProc(comm);
487 
488  std::vector<int> globalOffsets;
489  rowspace->getGlobalIndexOffsets(globalOffsets);
490  int numLocalRows = globalOffsets[localProc+1]-globalOffsets[localProc];
491  int firstLocalRow = globalOffsets[localProc];
492 
493  for(int i=0; i<numLocalRows; ++i) {
494  int row = firstLocalRow+i;
495  int rowLen;
496  feimat.getRowLength(row, rowLen);
497 
498  std::vector<int> colindices(rowLen);
499  std::vector<double> coefs(rowLen);
500 
501  feimat.copyOutRow(row, rowLen, &coefs[0], &colindices[0]);
502 
503  fmat.putRow(row, &colindices[0], &coefs[0], rowLen);
504  }
505 
506  return(0);
507 }
508 
509 } //namespace fei_test_utils
MPI_Comm getCommunicator() const
std::string construct_filename(int argc, char **argv)
void read_file_lines_into_strings(const char *filename, std::vector< std::string > &file_contents)
bool bool_arg(const char *flag, int argc, char **argv, bool default_result)
virtual fei::SharedPtr< fei::VectorSpace > getRowSpace()=0
double get_file_benchmark(const char *filename, const char *testname)
int get_filename_and_read_input(int argc, char **argv, MPI_Comm comm, int localProc, std::vector< std::string > &stdstrings)
virtual int getRowLength(int row, int &length) const =0
int initialize_mpi(int argc, char **argv, int &localProc, int &numProcs)
virtual fei::SharedPtr< fei::MatrixGraph > getMatrixGraph() const =0
void read_input_file(const char *filename, MPI_Comm comm, std::vector< std::string > &file_contents)
void broadcast_string(MPI_Comm comm, int root, std::string &strg)
std::ostream & console_out()
void getGlobalIndexOffsets(std::vector< int > &globalOffsets) const
bool within_percentage_margin(double value1, double value2, unsigned margin)
int localProc(MPI_Comm comm)
std::string get_arg_value(const char *flag, int argc, char **argv)
virtual int copyOutRow(int row, int len, double *coefs, int *indices) const =0