xref: /phasta/checkphasta/checkphasta.cpp (revision 50a6f6340c649c1738186cf6fd8c42a882135a5f)
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