FEI Version of the Day
Loading...
Searching...
No Matches
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
24namespace fei_test_utils {
25
26std::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
65int 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
78bool 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
103std::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
118void 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
150void 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
174int 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
194void 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
243double 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
260bool 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
276int 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
286bool 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
307std::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
315int 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
354int 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
385void 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
396int 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
403int 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
432int 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
463int 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
478int 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
virtual fei::SharedPtr< fei::VectorSpace > getRowSpace()=0
virtual int copyOutRow(int row, int len, double *coefs, int *indices) const =0
virtual fei::SharedPtr< fei::MatrixGraph > getMatrixGraph() const =0
virtual int getRowLength(int row, int &length) const =0
int initialize_mpi(int argc, char **argv, int &localProc, int &numProcs)
int get_filename_and_read_input(int argc, char **argv, MPI_Comm comm, int localProc, std::vector< std::string > &stdstrings)
std::string construct_filename(int argc, char **argv)
bool bool_arg(const char *flag, int argc, char **argv, bool default_result)
bool within_percentage_margin(double value1, double value2, unsigned margin)
void broadcast_string(MPI_Comm comm, int root, std::string &strg)
double get_file_benchmark(const char *filename, const char *testname)
void read_input_file(const char *filename, MPI_Comm comm, std::vector< std::string > &file_contents)
void read_file_lines_into_strings(const char *filename, std::vector< std::string > &file_contents)
std::string get_arg_value(const char *flag, int argc, char **argv)
int localProc(MPI_Comm comm)
std::ostream & console_out()