116223cb9SCameron Smith #include <cstdio> 216223cb9SCameron Smith #include <cstdlib> 316223cb9SCameron Smith #include <cassert> 416223cb9SCameron Smith #include <cstring> 516223cb9SCameron Smith #include <cmath> 616223cb9SCameron Smith #include <string> 716223cb9SCameron Smith #include <vector> 816223cb9SCameron Smith #include <algorithm> 916223cb9SCameron Smith #include <set> 1016223cb9SCameron Smith 1116223cb9SCameron Smith #include <sys/types.h> 1216223cb9SCameron Smith #include <sys/stat.h> 1316223cb9SCameron Smith #include <dirent.h> 1416223cb9SCameron Smith 1516223cb9SCameron Smith #define OMPI_SKIP_MPICXX 1 1616223cb9SCameron Smith #include <mpi.h> 1716223cb9SCameron Smith 18d7abaf6cSCameron Smith #include "syncio.h" 19d7abaf6cSCameron Smith #include "posixio.h" 20bafa09feSCameron Smith #include "phIO.h" 2116223cb9SCameron Smith 2216223cb9SCameron Smith char read_solution(double** solutiono, int* size, int* nshgo, int* ndofo, 23bafa09feSCameron Smith int nump, int rank, int timestep, int nSyncFiles, char* casedir); 24bafa09feSCameron Smith std::set<int>* find_timesteps(char* casedir, int nSyncFiles); 25bafa09feSCameron Smith double compare_solution(char* lpath, char* rpath, 26bafa09feSCameron Smith int timestep, int nump, int nSyncFiles); 27*a93de25bSCameron Smith char* getRestartName(int nSyncFiles); 2816223cb9SCameron Smith 2916223cb9SCameron Smith int main(int argc, char** argv) 3016223cb9SCameron Smith { 3116223cb9SCameron Smith int rank; 3216223cb9SCameron Smith int size; 3316223cb9SCameron Smith MPI_Init(&argc, &argv); 3416223cb9SCameron Smith 3516223cb9SCameron Smith MPI_Comm_rank(MPI_COMM_WORLD, &rank); 3616223cb9SCameron Smith MPI_Comm_size(MPI_COMM_WORLD, &size); 3716223cb9SCameron Smith 38c1ff69edSCameron Smith if(argc != 5) { 39bafa09feSCameron Smith fprintf(stderr, "argc %d\n", argc); 40bafa09feSCameron Smith fprintf(stderr, 41c1ff69edSCameron Smith "Usage: %s <left> <right> <numSyncFiles> <tolerance>\n" 42bafa09feSCameron Smith "where <left> and <right> are different" 43bafa09feSCameron Smith "N-procs_case directories\n", argv[0]); 44bafa09feSCameron Smith MPI_Finalize(); 45bafa09feSCameron Smith return 1; 46bafa09feSCameron Smith } 4716223cb9SCameron Smith char* lpath = argv[1]; 4816223cb9SCameron Smith char* rpath = argv[2]; 49bafa09feSCameron Smith int nSyncFiles = atoi(argv[3]); 50c1ff69edSCameron Smith double tolerance = atof(argv[4]); 5116223cb9SCameron Smith 5216223cb9SCameron Smith int ndof; 5316223cb9SCameron Smith int nshg; 5416223cb9SCameron Smith int solsize; 5516223cb9SCameron Smith double* solution; 5616223cb9SCameron Smith 57bafa09feSCameron Smith std::set<int>* l_timesteps = find_timesteps(lpath, nSyncFiles); 58bafa09feSCameron Smith std::set<int>* r_timesteps = find_timesteps(rpath, nSyncFiles); 5916223cb9SCameron Smith std::set<int>* timesteps_to_check = new std::set<int>; 6016223cb9SCameron Smith std::set_intersection(l_timesteps->begin(), l_timesteps->end(), 6116223cb9SCameron Smith r_timesteps->begin(), r_timesteps->end(), 6216223cb9SCameron Smith std::inserter(*timesteps_to_check, timesteps_to_check->begin())); 6316223cb9SCameron Smith delete l_timesteps; 6416223cb9SCameron Smith delete r_timesteps; 6516223cb9SCameron Smith if(rank == 0) 6616223cb9SCameron Smith printf("Found %d common timesteps\n", 6716223cb9SCameron Smith timesteps_to_check->size()); 6816223cb9SCameron Smith #ifdef DBGONLY 69bafa09feSCameron Smith read_solution(&solution, &solsize, &nshg, &ndof, 70bafa09feSCameron Smith size, rank, 0, numSyncFiles, "./"); 7116223cb9SCameron Smith printf("nshg: %d, ndof: %d\n", nshg, ndof); 7216223cb9SCameron Smith assert(solsize == ndof*nshg); 7316223cb9SCameron Smith #endif 7416223cb9SCameron Smith double maxerror = 0.0; 7516223cb9SCameron Smith double error; 7616223cb9SCameron Smith double gblmaxerror; 7716223cb9SCameron Smith for(std::set<int>::iterator i = timesteps_to_check->begin(); 7816223cb9SCameron Smith i!=timesteps_to_check->end();i++) 7916223cb9SCameron Smith { 80bafa09feSCameron Smith error = compare_solution(lpath, rpath, *i, size, nSyncFiles); 8116223cb9SCameron Smith if(error>maxerror) maxerror = error; 8216223cb9SCameron Smith } 8316223cb9SCameron Smith delete timesteps_to_check; 8416223cb9SCameron Smith MPI_Barrier(MPI_COMM_WORLD); 8516223cb9SCameron Smith MPI_Reduce(&maxerror, &gblmaxerror, 1, MPI_DOUBLE, MPI_MAX, 0, 8616223cb9SCameron Smith MPI_COMM_WORLD); 8716223cb9SCameron Smith if(rank == 0) printf("Maximum difference across all timesteps: %e\n", 8816223cb9SCameron Smith gblmaxerror); 8916223cb9SCameron Smith MPI_Finalize(); 90c1ff69edSCameron Smith return (gblmaxerror > tolerance); 9116223cb9SCameron Smith } 92bafa09feSCameron Smith double compare_solution(char* lpath, char* rpath, int timestep, int nump, int nSyncFiles) 9316223cb9SCameron Smith { 9416223cb9SCameron Smith int rank; 9516223cb9SCameron Smith MPI_Comm_rank(MPI_COMM_WORLD, &rank); 9616223cb9SCameron Smith double* lsol; 9716223cb9SCameron Smith double* rsol; 9816223cb9SCameron Smith int lsize; 9916223cb9SCameron Smith int rsize; 10016223cb9SCameron Smith 101bafa09feSCameron Smith read_solution(&lsol, &lsize, NULL, NULL, 102bafa09feSCameron Smith nump, rank, timestep, nSyncFiles, lpath); 103bafa09feSCameron Smith read_solution(&rsol, &rsize, NULL, NULL, 104bafa09feSCameron Smith nump, rank, timestep, nSyncFiles, rpath); 10516223cb9SCameron Smith 10616223cb9SCameron Smith double maxdiff=0.0; 10716223cb9SCameron Smith double gblmaxdiff; 10816223cb9SCameron Smith if(lsize != rsize) 10916223cb9SCameron Smith { 11016223cb9SCameron Smith printf("Error: Solution sizes different: %d, %d\n", 11116223cb9SCameron Smith lsize, rsize); 11216223cb9SCameron Smith assert(lsize == rsize); 11316223cb9SCameron Smith } 11416223cb9SCameron Smith for(int i=0;i<lsize;i++) 11516223cb9SCameron Smith { 11616223cb9SCameron Smith double diff = fabs(lsol[i]-rsol[i]); 11716223cb9SCameron Smith if(diff > maxdiff) maxdiff = diff; 11816223cb9SCameron Smith } 11916223cb9SCameron Smith free(lsol); 12016223cb9SCameron Smith free(rsol); 12116223cb9SCameron Smith MPI_Reduce(&maxdiff, &gblmaxdiff, 1, MPI_DOUBLE, MPI_MAX, 0, 12216223cb9SCameron Smith MPI_COMM_WORLD); 12316223cb9SCameron Smith MPI_Barrier(MPI_COMM_WORLD); //TODO: debugging only 12416223cb9SCameron Smith if(rank == 0) 12516223cb9SCameron Smith printf("Timestep: %d, maximum difference: %e\n", timestep, gblmaxdiff); 12616223cb9SCameron Smith return gblmaxdiff; 12716223cb9SCameron Smith 12816223cb9SCameron Smith } 12916223cb9SCameron Smith char read_solution(double** solutiono, int* size, int* nshgo, int* ndofo, 130bafa09feSCameron Smith int nump, int rank, int timestep, int nSyncFiles, char* casedir) 13116223cb9SCameron Smith { 13216223cb9SCameron Smith int iarray[10]; 13316223cb9SCameron Smith const char* iformat = "binary"; 13416223cb9SCameron Smith int ithree=3; 13516223cb9SCameron Smith int igeombc; 13616223cb9SCameron Smith char* fn; 13716223cb9SCameron Smith int nshg; 13816223cb9SCameron Smith int ndof; 13916223cb9SCameron Smith double* solution; 140bafa09feSCameron Smith phio_fp fp; 141d7abaf6cSCameron Smith if( nSyncFiles == 0 ) 142d7abaf6cSCameron Smith posixio_setup(&fp, 'r'); 143d7abaf6cSCameron Smith else if( nSyncFiles == 1 ) 144d7abaf6cSCameron Smith syncio_setup_read(nSyncFiles, &fp); 145*a93de25bSCameron Smith char rname[1024]; 146*a93de25bSCameron Smith phio_constructName(fp,"restart",rname); 147*a93de25bSCameron Smith asprintf(&fn,"%s/%s.%d.",casedir,rname,timestep); 148d7abaf6cSCameron Smith phio_openfile(rname, fp); 149d7abaf6cSCameron Smith 150bafa09feSCameron Smith phio_readheader(fp, "solution", (void*) iarray, &ithree, "integer", iformat); 15116223cb9SCameron Smith nshg = iarray[0]; 15216223cb9SCameron Smith ndof = iarray[1]; 15316223cb9SCameron Smith if(size != NULL) 15416223cb9SCameron Smith *size = nshg*ndof; 15516223cb9SCameron Smith solution = (double*) malloc(sizeof(double)*nshg*ndof); 156bafa09feSCameron Smith phio_readdatablock(fp, "solution", solution, size, "double", iformat); 157d7abaf6cSCameron Smith phio_closefile(fp); 15816223cb9SCameron Smith if(solutiono != NULL) 15916223cb9SCameron Smith *solutiono = solution; 16016223cb9SCameron Smith if(nshgo != NULL) 16116223cb9SCameron Smith *nshgo = nshg; 16216223cb9SCameron Smith if(ndofo != NULL) 16316223cb9SCameron Smith *ndofo = ndof; 16416223cb9SCameron Smith free(fn); 16516223cb9SCameron Smith return(0); 16616223cb9SCameron Smith } 16716223cb9SCameron Smith 168bafa09feSCameron Smith std::set<int>* find_timesteps(char* casedir, int nSyncFiles) 16916223cb9SCameron Smith { 17016223cb9SCameron Smith char* path; 17116223cb9SCameron Smith DIR* dir; 17216223cb9SCameron Smith struct dirent* d; 17316223cb9SCameron Smith int part, ts; 17416223cb9SCameron Smith std::set<int>* step_list = new std::set<int>; 17516223cb9SCameron Smith 17616223cb9SCameron Smith asprintf(&path, "%s", casedir); 17716223cb9SCameron Smith dir = opendir(path); 17816223cb9SCameron Smith if(!dir) 17916223cb9SCameron Smith { 18016223cb9SCameron Smith perror("Error opening case: "); 18116223cb9SCameron Smith MPI_Abort(MPI_COMM_WORLD,1); 18216223cb9SCameron Smith } 183*a93de25bSCameron Smith char* rname = getRestartName(nSyncFiles); 184bafa09feSCameron Smith char* fmt; 185bafa09feSCameron Smith asprintf(&fmt, "%s.%%d.%%d", rname); 18616223cb9SCameron Smith while((d=readdir(dir))) 18716223cb9SCameron Smith { 1880acf3134SCameron Smith if(sscanf(d->d_name, fmt, &ts, &part)==2) 18916223cb9SCameron Smith { 19016223cb9SCameron Smith step_list->insert(ts); 19116223cb9SCameron Smith } 19216223cb9SCameron Smith } 193*a93de25bSCameron Smith free(rname); 194bafa09feSCameron Smith free(fmt); 19516223cb9SCameron Smith free(path); 196dc953842SCameron Smith closedir(dir); 197bafa09feSCameron Smith return(step_list); 198bafa09feSCameron Smith } 199bafa09feSCameron Smith 200*a93de25bSCameron Smith char* getRestartName(int nSyncFiles) { 201*a93de25bSCameron Smith char* f; 202bafa09feSCameron Smith if(0 == nSyncFiles) 203*a93de25bSCameron Smith asprintf(&f, "restart-dat."); 204bafa09feSCameron Smith else if(nSyncFiles > 0) 205*a93de25bSCameron Smith asprintf(&f, "restart."); 206bafa09feSCameron Smith else { 207bafa09feSCameron Smith fprintf(stderr, 208bafa09feSCameron Smith "ERROR: the number of sync-io files must be" 209bafa09feSCameron Smith "greater than or equal to zero\n"); 210bafa09feSCameron Smith MPI_Abort(MPI_COMM_WORLD, 1); 211bafa09feSCameron Smith return NULL; 212bafa09feSCameron Smith } 213*a93de25bSCameron Smith return f; 21416223cb9SCameron Smith } 215