1*50a6f634SBen Matthews #define _GNU_SOURCE 2*50a6f634SBen Matthews #define _WITH_DPRINTF 316223cb9SCameron Smith #include <cstdio> 416223cb9SCameron Smith #include <cstdlib> 516223cb9SCameron Smith #include <cassert> 616223cb9SCameron Smith #include <cstring> 716223cb9SCameron Smith #include <cmath> 816223cb9SCameron Smith #include <string> 916223cb9SCameron Smith #include <vector> 1016223cb9SCameron Smith #include <algorithm> 1116223cb9SCameron Smith #include <set> 1216223cb9SCameron Smith 1316223cb9SCameron Smith #include <sys/types.h> 1416223cb9SCameron Smith #include <sys/stat.h> 1516223cb9SCameron Smith #include <dirent.h> 1616223cb9SCameron Smith 1716223cb9SCameron Smith #define OMPI_SKIP_MPICXX 1 1816223cb9SCameron Smith #include <mpi.h> 1916223cb9SCameron Smith 20d7abaf6cSCameron Smith #include "syncio.h" 21d7abaf6cSCameron Smith #include "posixio.h" 22bafa09feSCameron Smith #include "phIO.h" 2316223cb9SCameron Smith 2416223cb9SCameron Smith char read_solution(double** solutiono, int* size, int* nshgo, int* ndofo, 25bafa09feSCameron Smith int nump, int rank, int timestep, int nSyncFiles, char* casedir); 26bafa09feSCameron Smith std::set<int>* find_timesteps(char* casedir, int nSyncFiles); 27bafa09feSCameron Smith double compare_solution(char* lpath, char* rpath, 28bafa09feSCameron Smith int timestep, int nump, int nSyncFiles); 29a93de25bSCameron Smith char* getRestartName(int nSyncFiles); 3016223cb9SCameron Smith 3116223cb9SCameron Smith int main(int argc, char** argv) 3216223cb9SCameron Smith { 3316223cb9SCameron Smith int rank; 3416223cb9SCameron Smith int size; 3516223cb9SCameron Smith MPI_Init(&argc, &argv); 3616223cb9SCameron Smith 3716223cb9SCameron Smith MPI_Comm_rank(MPI_COMM_WORLD, &rank); 3816223cb9SCameron Smith MPI_Comm_size(MPI_COMM_WORLD, &size); 3916223cb9SCameron Smith 40c1ff69edSCameron Smith if(argc != 5) { 41bafa09feSCameron Smith fprintf(stderr, "argc %d\n", argc); 42bafa09feSCameron Smith fprintf(stderr, 43c1ff69edSCameron Smith "Usage: %s <left> <right> <numSyncFiles> <tolerance>\n" 44bafa09feSCameron Smith "where <left> and <right> are different" 45bafa09feSCameron Smith "N-procs_case directories\n", argv[0]); 46bafa09feSCameron Smith MPI_Finalize(); 47bafa09feSCameron Smith return 1; 48bafa09feSCameron Smith } 4916223cb9SCameron Smith char* lpath = argv[1]; 5016223cb9SCameron Smith char* rpath = argv[2]; 51bafa09feSCameron Smith int nSyncFiles = atoi(argv[3]); 52c1ff69edSCameron Smith double tolerance = atof(argv[4]); 5316223cb9SCameron Smith 5416223cb9SCameron Smith int ndof; 5516223cb9SCameron Smith int nshg; 5616223cb9SCameron Smith int solsize; 5716223cb9SCameron Smith double* solution; 5816223cb9SCameron Smith 59bafa09feSCameron Smith std::set<int>* l_timesteps = find_timesteps(lpath, nSyncFiles); 60bafa09feSCameron Smith std::set<int>* r_timesteps = find_timesteps(rpath, nSyncFiles); 6116223cb9SCameron Smith std::set<int>* timesteps_to_check = new std::set<int>; 6216223cb9SCameron Smith std::set_intersection(l_timesteps->begin(), l_timesteps->end(), 6316223cb9SCameron Smith r_timesteps->begin(), r_timesteps->end(), 6416223cb9SCameron Smith std::inserter(*timesteps_to_check, timesteps_to_check->begin())); 6516223cb9SCameron Smith delete l_timesteps; 6616223cb9SCameron Smith delete r_timesteps; 6716223cb9SCameron Smith if(rank == 0) 6816223cb9SCameron Smith printf("Found %d common timesteps\n", 6916223cb9SCameron Smith timesteps_to_check->size()); 7016223cb9SCameron Smith #ifdef DBGONLY 71bafa09feSCameron Smith read_solution(&solution, &solsize, &nshg, &ndof, 72bafa09feSCameron Smith size, rank, 0, numSyncFiles, "./"); 7316223cb9SCameron Smith printf("nshg: %d, ndof: %d\n", nshg, ndof); 7416223cb9SCameron Smith assert(solsize == ndof*nshg); 7516223cb9SCameron Smith #endif 7616223cb9SCameron Smith double maxerror = 0.0; 7716223cb9SCameron Smith double error; 7816223cb9SCameron Smith double gblmaxerror; 7916223cb9SCameron Smith for(std::set<int>::iterator i = timesteps_to_check->begin(); 8016223cb9SCameron Smith i!=timesteps_to_check->end();i++) 8116223cb9SCameron Smith { 82bafa09feSCameron Smith error = compare_solution(lpath, rpath, *i, size, nSyncFiles); 8316223cb9SCameron Smith if(error>maxerror) maxerror = error; 8416223cb9SCameron Smith } 8516223cb9SCameron Smith delete timesteps_to_check; 8616223cb9SCameron Smith MPI_Barrier(MPI_COMM_WORLD); 8716223cb9SCameron Smith MPI_Reduce(&maxerror, &gblmaxerror, 1, MPI_DOUBLE, MPI_MAX, 0, 8816223cb9SCameron Smith MPI_COMM_WORLD); 8916223cb9SCameron Smith if(rank == 0) printf("Maximum difference across all timesteps: %e\n", 9016223cb9SCameron Smith gblmaxerror); 9116223cb9SCameron Smith MPI_Finalize(); 92c1ff69edSCameron Smith return (gblmaxerror > tolerance); 9316223cb9SCameron Smith } 94bafa09feSCameron Smith double compare_solution(char* lpath, char* rpath, int timestep, int nump, int nSyncFiles) 9516223cb9SCameron Smith { 9616223cb9SCameron Smith int rank; 9716223cb9SCameron Smith MPI_Comm_rank(MPI_COMM_WORLD, &rank); 9816223cb9SCameron Smith double* lsol; 9916223cb9SCameron Smith double* rsol; 10016223cb9SCameron Smith int lsize; 10116223cb9SCameron Smith int rsize; 10216223cb9SCameron Smith 103bafa09feSCameron Smith read_solution(&lsol, &lsize, NULL, NULL, 104bafa09feSCameron Smith nump, rank, timestep, nSyncFiles, lpath); 105bafa09feSCameron Smith read_solution(&rsol, &rsize, NULL, NULL, 106bafa09feSCameron Smith nump, rank, timestep, nSyncFiles, rpath); 10716223cb9SCameron Smith 10816223cb9SCameron Smith double maxdiff=0.0; 10916223cb9SCameron Smith double gblmaxdiff; 11016223cb9SCameron Smith if(lsize != rsize) 11116223cb9SCameron Smith { 11216223cb9SCameron Smith printf("Error: Solution sizes different: %d, %d\n", 11316223cb9SCameron Smith lsize, rsize); 11416223cb9SCameron Smith assert(lsize == rsize); 11516223cb9SCameron Smith } 11616223cb9SCameron Smith for(int i=0;i<lsize;i++) 11716223cb9SCameron Smith { 11816223cb9SCameron Smith double diff = fabs(lsol[i]-rsol[i]); 11916223cb9SCameron Smith if(diff > maxdiff) maxdiff = diff; 12016223cb9SCameron Smith } 12116223cb9SCameron Smith free(lsol); 12216223cb9SCameron Smith free(rsol); 12316223cb9SCameron Smith MPI_Reduce(&maxdiff, &gblmaxdiff, 1, MPI_DOUBLE, MPI_MAX, 0, 12416223cb9SCameron Smith MPI_COMM_WORLD); 12516223cb9SCameron Smith MPI_Barrier(MPI_COMM_WORLD); //TODO: debugging only 12616223cb9SCameron Smith if(rank == 0) 12716223cb9SCameron Smith printf("Timestep: %d, maximum difference: %e\n", timestep, gblmaxdiff); 12816223cb9SCameron Smith return gblmaxdiff; 12916223cb9SCameron Smith 13016223cb9SCameron Smith } 13116223cb9SCameron Smith char read_solution(double** solutiono, int* size, int* nshgo, int* ndofo, 132bafa09feSCameron Smith int nump, int rank, int timestep, int nSyncFiles, char* casedir) 13316223cb9SCameron Smith { 13416223cb9SCameron Smith int iarray[10]; 13516223cb9SCameron Smith const char* iformat = "binary"; 13616223cb9SCameron Smith int ithree=3; 13716223cb9SCameron Smith int igeombc; 13816223cb9SCameron Smith char* fn; 13916223cb9SCameron Smith int nshg; 14016223cb9SCameron Smith int ndof; 14116223cb9SCameron Smith double* solution; 142bafa09feSCameron Smith phio_fp fp; 143d7abaf6cSCameron Smith if( nSyncFiles == 0 ) 144d7abaf6cSCameron Smith posixio_setup(&fp, 'r'); 14593b99f60SCameron Smith else if( nSyncFiles > 0 ) 146d7abaf6cSCameron Smith syncio_setup_read(nSyncFiles, &fp); 147a93de25bSCameron Smith char rname[1024]; 148a93de25bSCameron Smith phio_constructName(fp,"restart",rname); 14993b99f60SCameron Smith asprintf(&fn,"%s/%s%d.",casedir,rname,timestep); 15093b99f60SCameron Smith phio_openfile(fn, fp); 151d7abaf6cSCameron Smith 152bafa09feSCameron Smith phio_readheader(fp, "solution", (void*) iarray, &ithree, "integer", iformat); 15316223cb9SCameron Smith nshg = iarray[0]; 15416223cb9SCameron Smith ndof = iarray[1]; 15516223cb9SCameron Smith if(size != NULL) 15616223cb9SCameron Smith *size = nshg*ndof; 15716223cb9SCameron Smith solution = (double*) malloc(sizeof(double)*nshg*ndof); 158bafa09feSCameron Smith phio_readdatablock(fp, "solution", solution, size, "double", iformat); 159d7abaf6cSCameron Smith phio_closefile(fp); 16016223cb9SCameron Smith if(solutiono != NULL) 16116223cb9SCameron Smith *solutiono = solution; 16216223cb9SCameron Smith if(nshgo != NULL) 16316223cb9SCameron Smith *nshgo = nshg; 16416223cb9SCameron Smith if(ndofo != NULL) 16516223cb9SCameron Smith *ndofo = ndof; 16616223cb9SCameron Smith free(fn); 16716223cb9SCameron Smith return(0); 16816223cb9SCameron Smith } 16916223cb9SCameron Smith 170bafa09feSCameron Smith std::set<int>* find_timesteps(char* casedir, int nSyncFiles) 17116223cb9SCameron Smith { 17216223cb9SCameron Smith char* path; 17316223cb9SCameron Smith DIR* dir; 17416223cb9SCameron Smith struct dirent* d; 17516223cb9SCameron Smith int part, ts; 17616223cb9SCameron Smith std::set<int>* step_list = new std::set<int>; 17716223cb9SCameron Smith 17816223cb9SCameron Smith asprintf(&path, "%s", casedir); 17916223cb9SCameron Smith dir = opendir(path); 18016223cb9SCameron Smith if(!dir) 18116223cb9SCameron Smith { 18216223cb9SCameron Smith perror("Error opening case: "); 18316223cb9SCameron Smith MPI_Abort(MPI_COMM_WORLD,1); 18416223cb9SCameron Smith } 185a93de25bSCameron Smith char* rname = getRestartName(nSyncFiles); 186bafa09feSCameron Smith char* fmt; 187bafa09feSCameron Smith asprintf(&fmt, "%s.%%d.%%d", rname); 18816223cb9SCameron Smith while((d=readdir(dir))) 18916223cb9SCameron Smith { 1900acf3134SCameron Smith if(sscanf(d->d_name, fmt, &ts, &part)==2) 19116223cb9SCameron Smith { 19216223cb9SCameron Smith step_list->insert(ts); 19316223cb9SCameron Smith } 19416223cb9SCameron Smith } 195a93de25bSCameron Smith free(rname); 196bafa09feSCameron Smith free(fmt); 19716223cb9SCameron Smith free(path); 198dc953842SCameron Smith closedir(dir); 199bafa09feSCameron Smith return(step_list); 200bafa09feSCameron Smith } 201bafa09feSCameron Smith 202a93de25bSCameron Smith char* getRestartName(int nSyncFiles) { 203a93de25bSCameron Smith char* f; 204bafa09feSCameron Smith if(0 == nSyncFiles) 20593b99f60SCameron Smith asprintf(&f, "restart"); 206bafa09feSCameron Smith else if(nSyncFiles > 0) 20793b99f60SCameron Smith asprintf(&f, "restart-dat"); 208bafa09feSCameron Smith else { 209bafa09feSCameron Smith fprintf(stderr, 210bafa09feSCameron Smith "ERROR: the number of sync-io files must be" 211bafa09feSCameron Smith "greater than or equal to zero\n"); 212bafa09feSCameron Smith MPI_Abort(MPI_COMM_WORLD, 1); 213bafa09feSCameron Smith return NULL; 214bafa09feSCameron Smith } 215a93de25bSCameron Smith return f; 21616223cb9SCameron Smith } 217