1*06d45c3eSBenjamin Matthews #ifndef __xlC__
250a6f634SBen Matthews #define _GNU_SOURCE
3*06d45c3eSBenjamin Matthews #endif
450a6f634SBen Matthews #define _WITH_DPRINTF
516223cb9SCameron Smith #include <cstdio>
616223cb9SCameron Smith #include <cstdlib>
716223cb9SCameron Smith #include <cassert>
816223cb9SCameron Smith #include <cstring>
916223cb9SCameron Smith #include <cmath>
1016223cb9SCameron Smith #include <string>
1116223cb9SCameron Smith #include <vector>
1216223cb9SCameron Smith #include <algorithm>
1316223cb9SCameron Smith #include <set>
1416223cb9SCameron Smith
1516223cb9SCameron Smith #include <sys/types.h>
1616223cb9SCameron Smith #include <sys/stat.h>
1716223cb9SCameron Smith #include <dirent.h>
1816223cb9SCameron Smith
1916223cb9SCameron Smith #define OMPI_SKIP_MPICXX 1
2016223cb9SCameron Smith #include <mpi.h>
2116223cb9SCameron Smith
22d7abaf6cSCameron Smith #include "syncio.h"
23d7abaf6cSCameron Smith #include "posixio.h"
24bafa09feSCameron Smith #include "phIO.h"
2516223cb9SCameron Smith
2616223cb9SCameron Smith char read_solution(double** solutiono, int* size, int* nshgo, int* ndofo,
27bafa09feSCameron Smith int nump, int rank, int timestep, int nSyncFiles, char* casedir);
28bafa09feSCameron Smith std::set<int>* find_timesteps(char* casedir, int nSyncFiles);
29bafa09feSCameron Smith double compare_solution(char* lpath, char* rpath,
30bafa09feSCameron Smith int timestep, int nump, int nSyncFiles);
31a93de25bSCameron Smith char* getRestartName(int nSyncFiles);
3216223cb9SCameron Smith
main(int argc,char ** argv)3316223cb9SCameron Smith int main(int argc, char** argv)
3416223cb9SCameron Smith {
3516223cb9SCameron Smith int rank;
3616223cb9SCameron Smith int size;
3716223cb9SCameron Smith MPI_Init(&argc, &argv);
3816223cb9SCameron Smith
3916223cb9SCameron Smith MPI_Comm_rank(MPI_COMM_WORLD, &rank);
4016223cb9SCameron Smith MPI_Comm_size(MPI_COMM_WORLD, &size);
4116223cb9SCameron Smith
42c1ff69edSCameron Smith if(argc != 5) {
43bafa09feSCameron Smith fprintf(stderr, "argc %d\n", argc);
44bafa09feSCameron Smith fprintf(stderr,
45c1ff69edSCameron Smith "Usage: %s <left> <right> <numSyncFiles> <tolerance>\n"
46bafa09feSCameron Smith "where <left> and <right> are different"
47bafa09feSCameron Smith "N-procs_case directories\n", argv[0]);
48bafa09feSCameron Smith MPI_Finalize();
49bafa09feSCameron Smith return 1;
50bafa09feSCameron Smith }
5116223cb9SCameron Smith char* lpath = argv[1];
5216223cb9SCameron Smith char* rpath = argv[2];
53bafa09feSCameron Smith int nSyncFiles = atoi(argv[3]);
54c1ff69edSCameron Smith double tolerance = atof(argv[4]);
5516223cb9SCameron Smith
5616223cb9SCameron Smith int ndof;
5716223cb9SCameron Smith int nshg;
5816223cb9SCameron Smith int solsize;
5916223cb9SCameron Smith double* solution;
6016223cb9SCameron Smith
61bafa09feSCameron Smith std::set<int>* l_timesteps = find_timesteps(lpath, nSyncFiles);
62bafa09feSCameron Smith std::set<int>* r_timesteps = find_timesteps(rpath, nSyncFiles);
6316223cb9SCameron Smith std::set<int>* timesteps_to_check = new std::set<int>;
6416223cb9SCameron Smith std::set_intersection(l_timesteps->begin(), l_timesteps->end(),
6516223cb9SCameron Smith r_timesteps->begin(), r_timesteps->end(),
6616223cb9SCameron Smith std::inserter(*timesteps_to_check, timesteps_to_check->begin()));
6716223cb9SCameron Smith delete l_timesteps;
6816223cb9SCameron Smith delete r_timesteps;
6916223cb9SCameron Smith if(rank == 0)
7016223cb9SCameron Smith printf("Found %d common timesteps\n",
7116223cb9SCameron Smith timesteps_to_check->size());
7216223cb9SCameron Smith #ifdef DBGONLY
73bafa09feSCameron Smith read_solution(&solution, &solsize, &nshg, &ndof,
74bafa09feSCameron Smith size, rank, 0, numSyncFiles, "./");
7516223cb9SCameron Smith printf("nshg: %d, ndof: %d\n", nshg, ndof);
7616223cb9SCameron Smith assert(solsize == ndof*nshg);
7716223cb9SCameron Smith #endif
7816223cb9SCameron Smith double maxerror = 0.0;
7916223cb9SCameron Smith double error;
8016223cb9SCameron Smith double gblmaxerror;
8116223cb9SCameron Smith for(std::set<int>::iterator i = timesteps_to_check->begin();
8216223cb9SCameron Smith i!=timesteps_to_check->end();i++)
8316223cb9SCameron Smith {
84bafa09feSCameron Smith error = compare_solution(lpath, rpath, *i, size, nSyncFiles);
8516223cb9SCameron Smith if(error>maxerror) maxerror = error;
8616223cb9SCameron Smith }
8716223cb9SCameron Smith delete timesteps_to_check;
8816223cb9SCameron Smith MPI_Barrier(MPI_COMM_WORLD);
8916223cb9SCameron Smith MPI_Reduce(&maxerror, &gblmaxerror, 1, MPI_DOUBLE, MPI_MAX, 0,
9016223cb9SCameron Smith MPI_COMM_WORLD);
9116223cb9SCameron Smith if(rank == 0) printf("Maximum difference across all timesteps: %e\n",
9216223cb9SCameron Smith gblmaxerror);
9316223cb9SCameron Smith MPI_Finalize();
94c1ff69edSCameron Smith return (gblmaxerror > tolerance);
9516223cb9SCameron Smith }
compare_solution(char * lpath,char * rpath,int timestep,int nump,int nSyncFiles)96bafa09feSCameron Smith double compare_solution(char* lpath, char* rpath, int timestep, int nump, int nSyncFiles)
9716223cb9SCameron Smith {
9816223cb9SCameron Smith int rank;
9916223cb9SCameron Smith MPI_Comm_rank(MPI_COMM_WORLD, &rank);
10016223cb9SCameron Smith double* lsol;
10116223cb9SCameron Smith double* rsol;
10216223cb9SCameron Smith int lsize;
10316223cb9SCameron Smith int rsize;
10416223cb9SCameron Smith
105bafa09feSCameron Smith read_solution(&lsol, &lsize, NULL, NULL,
106bafa09feSCameron Smith nump, rank, timestep, nSyncFiles, lpath);
107bafa09feSCameron Smith read_solution(&rsol, &rsize, NULL, NULL,
108bafa09feSCameron Smith nump, rank, timestep, nSyncFiles, rpath);
10916223cb9SCameron Smith
11016223cb9SCameron Smith double maxdiff=0.0;
11116223cb9SCameron Smith double gblmaxdiff;
11216223cb9SCameron Smith if(lsize != rsize)
11316223cb9SCameron Smith {
11416223cb9SCameron Smith printf("Error: Solution sizes different: %d, %d\n",
11516223cb9SCameron Smith lsize, rsize);
11616223cb9SCameron Smith assert(lsize == rsize);
11716223cb9SCameron Smith }
11816223cb9SCameron Smith for(int i=0;i<lsize;i++)
11916223cb9SCameron Smith {
12016223cb9SCameron Smith double diff = fabs(lsol[i]-rsol[i]);
12116223cb9SCameron Smith if(diff > maxdiff) maxdiff = diff;
12216223cb9SCameron Smith }
12316223cb9SCameron Smith free(lsol);
12416223cb9SCameron Smith free(rsol);
12516223cb9SCameron Smith MPI_Reduce(&maxdiff, &gblmaxdiff, 1, MPI_DOUBLE, MPI_MAX, 0,
12616223cb9SCameron Smith MPI_COMM_WORLD);
12716223cb9SCameron Smith MPI_Barrier(MPI_COMM_WORLD); //TODO: debugging only
12816223cb9SCameron Smith if(rank == 0)
12916223cb9SCameron Smith printf("Timestep: %d, maximum difference: %e\n", timestep, gblmaxdiff);
13016223cb9SCameron Smith return gblmaxdiff;
13116223cb9SCameron Smith
13216223cb9SCameron Smith }
read_solution(double ** solutiono,int * size,int * nshgo,int * ndofo,int nump,int rank,int timestep,int nSyncFiles,char * casedir)13316223cb9SCameron Smith char read_solution(double** solutiono, int* size, int* nshgo, int* ndofo,
134bafa09feSCameron Smith int nump, int rank, int timestep, int nSyncFiles, char* casedir)
13516223cb9SCameron Smith {
13616223cb9SCameron Smith int iarray[10];
13716223cb9SCameron Smith const char* iformat = "binary";
13816223cb9SCameron Smith int ithree=3;
13916223cb9SCameron Smith int igeombc;
14016223cb9SCameron Smith char* fn;
14116223cb9SCameron Smith int nshg;
14216223cb9SCameron Smith int ndof;
14316223cb9SCameron Smith double* solution;
144bafa09feSCameron Smith phio_fp fp;
145d7abaf6cSCameron Smith if( nSyncFiles == 0 )
146d7abaf6cSCameron Smith posixio_setup(&fp, 'r');
14793b99f60SCameron Smith else if( nSyncFiles > 0 )
148d7abaf6cSCameron Smith syncio_setup_read(nSyncFiles, &fp);
149a93de25bSCameron Smith char rname[1024];
150a93de25bSCameron Smith phio_constructName(fp,"restart",rname);
15193b99f60SCameron Smith asprintf(&fn,"%s/%s%d.",casedir,rname,timestep);
15293b99f60SCameron Smith phio_openfile(fn, fp);
153d7abaf6cSCameron Smith
154bafa09feSCameron Smith phio_readheader(fp, "solution", (void*) iarray, &ithree, "integer", iformat);
15516223cb9SCameron Smith nshg = iarray[0];
15616223cb9SCameron Smith ndof = iarray[1];
15716223cb9SCameron Smith if(size != NULL)
15816223cb9SCameron Smith *size = nshg*ndof;
15916223cb9SCameron Smith solution = (double*) malloc(sizeof(double)*nshg*ndof);
160bafa09feSCameron Smith phio_readdatablock(fp, "solution", solution, size, "double", iformat);
161d7abaf6cSCameron Smith phio_closefile(fp);
16216223cb9SCameron Smith if(solutiono != NULL)
16316223cb9SCameron Smith *solutiono = solution;
16416223cb9SCameron Smith if(nshgo != NULL)
16516223cb9SCameron Smith *nshgo = nshg;
16616223cb9SCameron Smith if(ndofo != NULL)
16716223cb9SCameron Smith *ndofo = ndof;
16816223cb9SCameron Smith free(fn);
16916223cb9SCameron Smith return(0);
17016223cb9SCameron Smith }
17116223cb9SCameron Smith
find_timesteps(char * casedir,int nSyncFiles)172bafa09feSCameron Smith std::set<int>* find_timesteps(char* casedir, int nSyncFiles)
17316223cb9SCameron Smith {
17416223cb9SCameron Smith char* path;
17516223cb9SCameron Smith DIR* dir;
17616223cb9SCameron Smith struct dirent* d;
17716223cb9SCameron Smith int part, ts;
17816223cb9SCameron Smith std::set<int>* step_list = new std::set<int>;
17916223cb9SCameron Smith
18016223cb9SCameron Smith asprintf(&path, "%s", casedir);
18116223cb9SCameron Smith dir = opendir(path);
18216223cb9SCameron Smith if(!dir)
18316223cb9SCameron Smith {
18416223cb9SCameron Smith perror("Error opening case: ");
18516223cb9SCameron Smith MPI_Abort(MPI_COMM_WORLD,1);
18616223cb9SCameron Smith }
187a93de25bSCameron Smith char* rname = getRestartName(nSyncFiles);
188bafa09feSCameron Smith char* fmt;
189bafa09feSCameron Smith asprintf(&fmt, "%s.%%d.%%d", rname);
19016223cb9SCameron Smith while((d=readdir(dir)))
19116223cb9SCameron Smith {
1920acf3134SCameron Smith if(sscanf(d->d_name, fmt, &ts, &part)==2)
19316223cb9SCameron Smith {
19416223cb9SCameron Smith step_list->insert(ts);
19516223cb9SCameron Smith }
19616223cb9SCameron Smith }
197a93de25bSCameron Smith free(rname);
198bafa09feSCameron Smith free(fmt);
19916223cb9SCameron Smith free(path);
200dc953842SCameron Smith closedir(dir);
201bafa09feSCameron Smith return(step_list);
202bafa09feSCameron Smith }
203bafa09feSCameron Smith
getRestartName(int nSyncFiles)204a93de25bSCameron Smith char* getRestartName(int nSyncFiles) {
205a93de25bSCameron Smith char* f;
206bafa09feSCameron Smith if(0 == nSyncFiles)
20793b99f60SCameron Smith asprintf(&f, "restart");
208bafa09feSCameron Smith else if(nSyncFiles > 0)
20993b99f60SCameron Smith asprintf(&f, "restart-dat");
210bafa09feSCameron Smith else {
211bafa09feSCameron Smith fprintf(stderr,
212bafa09feSCameron Smith "ERROR: the number of sync-io files must be"
213bafa09feSCameron Smith "greater than or equal to zero\n");
214bafa09feSCameron Smith MPI_Abort(MPI_COMM_WORLD, 1);
215bafa09feSCameron Smith return NULL;
216bafa09feSCameron Smith }
217a93de25bSCameron Smith return f;
21816223cb9SCameron Smith }
219