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 18*bafa09feSCameron Smith #include "phIO.h" 1916223cb9SCameron Smith 2016223cb9SCameron Smith char read_solution(double** solutiono, int* size, int* nshgo, int* ndofo, 21*bafa09feSCameron Smith int nump, int rank, int timestep, int nSyncFiles, char* casedir); 22*bafa09feSCameron Smith std::set<int>* find_timesteps(char* casedir, int nSyncFiles); 23*bafa09feSCameron Smith double compare_solution(char* lpath, char* rpath, 24*bafa09feSCameron Smith int timestep, int nump, int nSyncFiles); 25*bafa09feSCameron Smith const char* getRestartName(int nSyncFiles); 2616223cb9SCameron Smith 2716223cb9SCameron Smith int main(int argc, char** argv) 2816223cb9SCameron Smith { 2916223cb9SCameron Smith int rank; 3016223cb9SCameron Smith int size; 3116223cb9SCameron Smith MPI_Init(&argc, &argv); 3216223cb9SCameron Smith 3316223cb9SCameron Smith MPI_Comm_rank(MPI_COMM_WORLD, &rank); 3416223cb9SCameron Smith MPI_Comm_size(MPI_COMM_WORLD, &size); 3516223cb9SCameron Smith 36*bafa09feSCameron Smith if(argc != 4) { 37*bafa09feSCameron Smith fprintf(stderr, "argc %d\n", argc); 38*bafa09feSCameron Smith fprintf(stderr, 39*bafa09feSCameron Smith "Usage: %s <left> <right> <numSyncFiles>\n" 40*bafa09feSCameron Smith "where <left> and <right> are different" 41*bafa09feSCameron Smith "N-procs_case directories\n", argv[0]); 42*bafa09feSCameron Smith MPI_Finalize(); 43*bafa09feSCameron Smith return 1; 44*bafa09feSCameron Smith } 4516223cb9SCameron Smith char* lpath = argv[1]; 4616223cb9SCameron Smith char* rpath = argv[2]; 47*bafa09feSCameron Smith int nSyncFiles = atoi(argv[3]); 4816223cb9SCameron Smith 4916223cb9SCameron Smith int ndof; 5016223cb9SCameron Smith int nshg; 5116223cb9SCameron Smith int solsize; 5216223cb9SCameron Smith double* solution; 5316223cb9SCameron Smith 54*bafa09feSCameron Smith std::set<int>* l_timesteps = find_timesteps(lpath, nSyncFiles); 55*bafa09feSCameron Smith std::set<int>* r_timesteps = find_timesteps(rpath, nSyncFiles); 5616223cb9SCameron Smith std::set<int>* timesteps_to_check = new std::set<int>; 5716223cb9SCameron Smith std::set_intersection(l_timesteps->begin(), l_timesteps->end(), 5816223cb9SCameron Smith r_timesteps->begin(), r_timesteps->end(), 5916223cb9SCameron Smith std::inserter(*timesteps_to_check, timesteps_to_check->begin())); 6016223cb9SCameron Smith delete l_timesteps; 6116223cb9SCameron Smith delete r_timesteps; 6216223cb9SCameron Smith if(rank == 0) 6316223cb9SCameron Smith printf("Found %d common timesteps\n", 6416223cb9SCameron Smith timesteps_to_check->size()); 6516223cb9SCameron Smith #ifdef DBGONLY 66*bafa09feSCameron Smith read_solution(&solution, &solsize, &nshg, &ndof, 67*bafa09feSCameron Smith size, rank, 0, numSyncFiles, "./"); 6816223cb9SCameron Smith printf("nshg: %d, ndof: %d\n", nshg, ndof); 6916223cb9SCameron Smith assert(solsize == ndof*nshg); 7016223cb9SCameron Smith #endif 7116223cb9SCameron Smith double maxerror = 0.0; 7216223cb9SCameron Smith double error; 7316223cb9SCameron Smith double gblmaxerror; 7416223cb9SCameron Smith for(std::set<int>::iterator i = timesteps_to_check->begin(); 7516223cb9SCameron Smith i!=timesteps_to_check->end();i++) 7616223cb9SCameron Smith { 77*bafa09feSCameron Smith error = compare_solution(lpath, rpath, *i, size, nSyncFiles); 7816223cb9SCameron Smith if(error>maxerror) maxerror = error; 7916223cb9SCameron Smith } 8016223cb9SCameron Smith delete timesteps_to_check; 8116223cb9SCameron Smith MPI_Barrier(MPI_COMM_WORLD); 8216223cb9SCameron Smith MPI_Reduce(&maxerror, &gblmaxerror, 1, MPI_DOUBLE, MPI_MAX, 0, 8316223cb9SCameron Smith MPI_COMM_WORLD); 8416223cb9SCameron Smith if(rank == 0) printf("Maximum difference across all timesteps: %e\n", 8516223cb9SCameron Smith gblmaxerror); 8616223cb9SCameron Smith MPI_Finalize(); 8716223cb9SCameron Smith } 88*bafa09feSCameron Smith double compare_solution(char* lpath, char* rpath, int timestep, int nump, int nSyncFiles) 8916223cb9SCameron Smith { 9016223cb9SCameron Smith int rank; 9116223cb9SCameron Smith MPI_Comm_rank(MPI_COMM_WORLD, &rank); 9216223cb9SCameron Smith double* lsol; 9316223cb9SCameron Smith double* rsol; 9416223cb9SCameron Smith int lsize; 9516223cb9SCameron Smith int rsize; 9616223cb9SCameron Smith 97*bafa09feSCameron Smith read_solution(&lsol, &lsize, NULL, NULL, 98*bafa09feSCameron Smith nump, rank, timestep, nSyncFiles, lpath); 99*bafa09feSCameron Smith read_solution(&rsol, &rsize, NULL, NULL, 100*bafa09feSCameron Smith nump, rank, timestep, nSyncFiles, rpath); 10116223cb9SCameron Smith 10216223cb9SCameron Smith double maxdiff=0.0; 10316223cb9SCameron Smith double gblmaxdiff; 10416223cb9SCameron Smith if(lsize != rsize) 10516223cb9SCameron Smith { 10616223cb9SCameron Smith printf("Error: Solution sizes different: %d, %d\n", 10716223cb9SCameron Smith lsize, rsize); 10816223cb9SCameron Smith assert(lsize == rsize); 10916223cb9SCameron Smith } 11016223cb9SCameron Smith for(int i=0;i<lsize;i++) 11116223cb9SCameron Smith { 11216223cb9SCameron Smith double diff = fabs(lsol[i]-rsol[i]); 11316223cb9SCameron Smith if(diff > maxdiff) maxdiff = diff; 11416223cb9SCameron Smith } 11516223cb9SCameron Smith free(lsol); 11616223cb9SCameron Smith free(rsol); 11716223cb9SCameron Smith MPI_Reduce(&maxdiff, &gblmaxdiff, 1, MPI_DOUBLE, MPI_MAX, 0, 11816223cb9SCameron Smith MPI_COMM_WORLD); 11916223cb9SCameron Smith MPI_Barrier(MPI_COMM_WORLD); //TODO: debugging only 12016223cb9SCameron Smith if(rank == 0) 12116223cb9SCameron Smith printf("Timestep: %d, maximum difference: %e\n", timestep, gblmaxdiff); 12216223cb9SCameron Smith return gblmaxdiff; 12316223cb9SCameron Smith 12416223cb9SCameron Smith } 12516223cb9SCameron Smith char read_solution(double** solutiono, int* size, int* nshgo, int* ndofo, 126*bafa09feSCameron Smith int nump, int rank, int timestep, int nSyncFiles, char* casedir) 12716223cb9SCameron Smith { 12816223cb9SCameron Smith int iarray[10]; 12916223cb9SCameron Smith const char* iformat = "binary"; 13016223cb9SCameron Smith int ithree=3; 13116223cb9SCameron Smith int igeombc; 13216223cb9SCameron Smith char* fn; 13316223cb9SCameron Smith int nshg; 13416223cb9SCameron Smith int ndof; 13516223cb9SCameron Smith double* solution; 136*bafa09feSCameron Smith const char* rname = getRestartName(nSyncFiles); 137*bafa09feSCameron Smith asprintf(&fn,"%s/%s.%d",casedir,rname,timestep); 138*bafa09feSCameron Smith phio_fp fp; 139*bafa09feSCameron Smith phio_openfile_read(fn,&nSyncFiles,&fp); 140*bafa09feSCameron Smith phio_readheader(fp, "solution", (void*) iarray, &ithree, "integer", iformat); 14116223cb9SCameron Smith nshg = iarray[0]; 14216223cb9SCameron Smith ndof = iarray[1]; 14316223cb9SCameron Smith if(size != NULL) 14416223cb9SCameron Smith *size = nshg*ndof; 14516223cb9SCameron Smith solution = (double*) malloc(sizeof(double)*nshg*ndof); 146*bafa09feSCameron Smith phio_readdatablock(fp, "solution", solution, size, "double", iformat); 147*bafa09feSCameron Smith phio_closefile_read(fp); 14816223cb9SCameron Smith if(solutiono != NULL) 14916223cb9SCameron Smith *solutiono = solution; 15016223cb9SCameron Smith if(nshgo != NULL) 15116223cb9SCameron Smith *nshgo = nshg; 15216223cb9SCameron Smith if(ndofo != NULL) 15316223cb9SCameron Smith *ndofo = ndof; 15416223cb9SCameron Smith free(fn); 15516223cb9SCameron Smith return(0); 15616223cb9SCameron Smith } 15716223cb9SCameron Smith 158*bafa09feSCameron Smith std::set<int>* find_timesteps(char* casedir, int nSyncFiles) 15916223cb9SCameron Smith { 16016223cb9SCameron Smith char* path; 16116223cb9SCameron Smith DIR* dir; 16216223cb9SCameron Smith struct dirent* d; 16316223cb9SCameron Smith int part, ts; 16416223cb9SCameron Smith std::set<int>* step_list = new std::set<int>; 16516223cb9SCameron Smith 16616223cb9SCameron Smith asprintf(&path, "%s", casedir); 16716223cb9SCameron Smith dir = opendir(path); 16816223cb9SCameron Smith if(!dir) 16916223cb9SCameron Smith { 17016223cb9SCameron Smith perror("Error opening case: "); 17116223cb9SCameron Smith MPI_Abort(MPI_COMM_WORLD,1); 17216223cb9SCameron Smith } 173*bafa09feSCameron Smith const char* rname = getRestartName(nSyncFiles); 174*bafa09feSCameron Smith char* fmt; 175*bafa09feSCameron Smith asprintf(&fmt, "%s.%%d.%%d", rname); 176*bafa09feSCameron Smith fprintf(stderr, "fmt %s\n", fmt); 17716223cb9SCameron Smith while((d=readdir(dir))) 17816223cb9SCameron Smith { 17916223cb9SCameron Smith if(sscanf(d->d_name, "restart.%d.%d", &ts, &part)==2) 18016223cb9SCameron Smith { 18116223cb9SCameron Smith step_list->insert(ts); 18216223cb9SCameron Smith } 18316223cb9SCameron Smith } 184*bafa09feSCameron Smith free(fmt); 18516223cb9SCameron Smith free(path); 186*bafa09feSCameron Smith return(step_list); 187*bafa09feSCameron Smith } 188*bafa09feSCameron Smith 189*bafa09feSCameron Smith const char* getRestartName(int nSyncFiles) { 190*bafa09feSCameron Smith if(0 == nSyncFiles) 191*bafa09feSCameron Smith return "restart"; 192*bafa09feSCameron Smith else if(nSyncFiles > 0) 193*bafa09feSCameron Smith return "restart-dat"; 194*bafa09feSCameron Smith else { 195*bafa09feSCameron Smith fprintf(stderr, 196*bafa09feSCameron Smith "ERROR: the number of sync-io files must be" 197*bafa09feSCameron Smith "greater than or equal to zero\n"); 198*bafa09feSCameron Smith MPI_Abort(MPI_COMM_WORLD, 1); 199*bafa09feSCameron Smith return NULL; 200*bafa09feSCameron Smith } 20116223cb9SCameron Smith } 202