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 18bafa09feSCameron Smith #include "phIO.h" 1916223cb9SCameron Smith 2016223cb9SCameron Smith char read_solution(double** solutiono, int* size, int* nshgo, int* ndofo, 21bafa09feSCameron Smith int nump, int rank, int timestep, int nSyncFiles, char* casedir); 22bafa09feSCameron Smith std::set<int>* find_timesteps(char* casedir, int nSyncFiles); 23bafa09feSCameron Smith double compare_solution(char* lpath, char* rpath, 24bafa09feSCameron Smith int timestep, int nump, int nSyncFiles); 25bafa09feSCameron 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 36bafa09feSCameron Smith if(argc != 4) { 37bafa09feSCameron Smith fprintf(stderr, "argc %d\n", argc); 38bafa09feSCameron Smith fprintf(stderr, 39bafa09feSCameron Smith "Usage: %s <left> <right> <numSyncFiles>\n" 40bafa09feSCameron Smith "where <left> and <right> are different" 41bafa09feSCameron Smith "N-procs_case directories\n", argv[0]); 42bafa09feSCameron Smith MPI_Finalize(); 43bafa09feSCameron Smith return 1; 44bafa09feSCameron Smith } 4516223cb9SCameron Smith char* lpath = argv[1]; 4616223cb9SCameron Smith char* rpath = argv[2]; 47bafa09feSCameron 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 54bafa09feSCameron Smith std::set<int>* l_timesteps = find_timesteps(lpath, nSyncFiles); 55bafa09feSCameron 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 66bafa09feSCameron Smith read_solution(&solution, &solsize, &nshg, &ndof, 67bafa09feSCameron 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 { 77bafa09feSCameron 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 } 88bafa09feSCameron 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 97bafa09feSCameron Smith read_solution(&lsol, &lsize, NULL, NULL, 98bafa09feSCameron Smith nump, rank, timestep, nSyncFiles, lpath); 99bafa09feSCameron Smith read_solution(&rsol, &rsize, NULL, NULL, 100bafa09feSCameron 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, 126bafa09feSCameron 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; 136bafa09feSCameron Smith const char* rname = getRestartName(nSyncFiles); 137*0acf3134SCameron Smith asprintf(&fn,"%s/%s.%d.",casedir,rname,timestep); 138bafa09feSCameron Smith phio_fp fp; 139bafa09feSCameron Smith phio_openfile_read(fn,&nSyncFiles,&fp); 140bafa09feSCameron 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); 146bafa09feSCameron Smith phio_readdatablock(fp, "solution", solution, size, "double", iformat); 147bafa09feSCameron 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 158bafa09feSCameron 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 } 173bafa09feSCameron Smith const char* rname = getRestartName(nSyncFiles); 174bafa09feSCameron Smith char* fmt; 175bafa09feSCameron Smith asprintf(&fmt, "%s.%%d.%%d", rname); 17616223cb9SCameron Smith while((d=readdir(dir))) 17716223cb9SCameron Smith { 178*0acf3134SCameron Smith if(sscanf(d->d_name, fmt, &ts, &part)==2) 17916223cb9SCameron Smith { 18016223cb9SCameron Smith step_list->insert(ts); 18116223cb9SCameron Smith } 18216223cb9SCameron Smith } 183bafa09feSCameron Smith free(fmt); 18416223cb9SCameron Smith free(path); 185bafa09feSCameron Smith return(step_list); 186bafa09feSCameron Smith } 187bafa09feSCameron Smith 188bafa09feSCameron Smith const char* getRestartName(int nSyncFiles) { 189bafa09feSCameron Smith if(0 == nSyncFiles) 190bafa09feSCameron Smith return "restart"; 191bafa09feSCameron Smith else if(nSyncFiles > 0) 192bafa09feSCameron Smith return "restart-dat"; 193bafa09feSCameron Smith else { 194bafa09feSCameron Smith fprintf(stderr, 195bafa09feSCameron Smith "ERROR: the number of sync-io files must be" 196bafa09feSCameron Smith "greater than or equal to zero\n"); 197bafa09feSCameron Smith MPI_Abort(MPI_COMM_WORLD, 1); 198bafa09feSCameron Smith return NULL; 199bafa09feSCameron Smith } 20016223cb9SCameron Smith } 201