#include #include #include #include //#define OMPI_SKIP_MPICXX 1 //Added in the CMakeList.txt file #include #include #include "phastaIO.h" #include #include enum { DIR_FANOUT = 2048 }; inline int cscompare( const char teststring[], const char targetstring[] ) { char* s1 = const_cast(teststring); char* s2 = const_cast(targetstring); while( *s1 == ' ') s1++; while( *s2 == ' ') s2++; while( ( *s1 ) && ( *s2 ) && ( *s2 != '?') && ( tolower( *s1 )==tolower( *s2 ) ) ) { s1++; s2++; while( *s1 == ' ') s1++; while( *s2 == ' ') s2++; } if ( !( *s1 ) || ( *s1 == '?') ) return 1; else return 0; } inline int computenitems(const int localpartid, const int fieldid, const int myrank, const char *fieldName, int ***para, const int intHeader, const int numVariables) { // This routine computes the number of items in the data block based on // - the name of the fields // - the integers read from the header int nItems = -1; if (cscompare("nbc values",fieldName)) nItems = para[localpartid][fieldid][0] * (numVariables+1); else if (cscompare("nbc codes",fieldName)) nItems = para[localpartid][fieldid][0] * 2; else if ( intHeader==1) nItems = para[localpartid][fieldid][0]; else nItems = para[localpartid][fieldid][0] * para[localpartid][fieldid][1]; return nItems; } int main(int argc, char *argv[]) { MPI_Init(&argc,&argv); int myrank, N_procs; MPI_Comm_rank(MPI_COMM_WORLD, &myrank); MPI_Comm_size(MPI_COMM_WORLD, &N_procs); FILE * pFile,* AccessoryFileHandle; char target[1024], pool[256], tempString[128],numpe[8],numstart[8]; char * temp, * token; int fieldCompareMark; bool readField; int i, j, k, N_geombc_double, N_geombc_integer, N_restart_double; int N_restart_integer, N_steps, N_parts, N_files; pFile = fopen("./IO.O2N.input","r"); if (pFile == NULL) printf("Error openning\n"); fgets( target, 1024, pFile ); token = strtok ( target, ";" );strcpy(pool,token); temp = strtok ( pool, ":" );temp = strtok ( NULL, ":" ); N_geombc_double = atoi(temp); fgets( target, 1024, pFile ); token = strtok ( target, ";" );strcpy(pool,token); temp = strtok ( pool, ":" );temp = strtok ( NULL, ":" ); N_geombc_integer = atoi(temp); fgets( target, 1024, pFile ); token = strtok ( target, ";" );strcpy(pool,token); temp = strtok ( pool, ":" );temp = strtok ( NULL, ":" ); N_restart_double = atoi(temp); fgets( target, 1024, pFile ); token = strtok ( target, ";" );strcpy(pool,token); temp = strtok ( pool, ":" );temp = strtok ( NULL, ":" ); N_restart_integer = atoi(temp); fgets( target, 1024, pFile ); token = strtok ( target, ";" );strcpy(pool,token); temp = strtok ( pool, ":" );temp = strtok ( NULL, ":" ); strncpy(numstart,temp,1); N_steps = atoi(temp); fgets( target, 1024, pFile ); token = strtok ( target, ";" );strcpy(pool,token); temp = strtok ( pool, ":" );temp = strtok ( NULL, ":" ); strncpy(numpe,temp,1); N_parts = atoi(temp); if(myrank==0){ printf("numpe is %d and start is %d\n",N_parts,N_steps); } fgets( target, 1024, pFile ); token = strtok ( target, ";" );strcpy(pool,token); temp = strtok ( pool, ":" );temp = strtok ( NULL, ":" ); N_files = atoi(temp); double ***Dfield; int ***Ifield; int ***paraD, ***paraI, *expectD, *expectI; char **fieldNameD, **fileTypeD, **dataTypeD, **headerTypeD; char **fieldNameI, **fileTypeI, **dataTypeI, **headerTypeI; int* WriteLockD = new int[N_geombc_double]; int* WriteLockI = new int[N_geombc_integer]; int nppp = N_parts/N_procs; int startpart = myrank * nppp +1; int endpart = startpart + nppp - 1; char gfname[64], numTemp[128]; int iarray[10], igeom, isize,TempFileHandle; //////////////////////////////////////// // Test if the user has given the right parameters related to the number of parts, procs and SyncIO files //////////////////////////////////////// if (N_parts%N_files!=0) { printf("Input error: number of parts should be a multiple of number of files!\n"); printf("Please modify the IO.O2N.input file!\n"); return 0; } if (N_procs%N_files!=0) { printf("Input error: number of procs should be a multiple of number of files!\n"); printf("Please modify the IO.O2N.input file!\n"); return 0; } if (N_parts%N_procs!=0) { printf("Input error: number of parts should be a multiple of number of procs!\n"); printf("Please modify the IO.O2N.input file!\n"); return 0; } ///////////////////////////////////// // Create numpe.in and numstart.dat //////////////////////////////////////// if (myrank==0) { //MR CHANGE bzero((void*)gfname,64); sprintf(gfname,"./%d-procs_case-SyncIO-%d",N_parts,N_files); if(0numBoundaryFields[i] ) // for ( k = 0; k < expectD[j]; k++ ) // paraD[i][j][k] = 0; } sprintf(fieldtag,"%s@%d",fieldNameD[j],GPID); /* if ( expectD[j]==1 ) isize = paraD[i][j][0]; else isize = paraD[i][j][0] * paraD[i][j][1]; //specially designed for nbc values fields //check the size in presolver codes //Yeah, you have to open restart to get the size if ( fieldCompareMark==1 ) isize = paraD[i][j][0] * (numVariables[i]+1); */ if ( cscompare("header",headerTypeD[j]) ) isize = 0; else // block isize = computenitems(i,j,myrank,fieldNameD[j],paraD,expectD[j],numVariables[i]); for ( k = 0; k < expectD[j]; k++ ) iarray[k] = paraD[i][j][k]; //printf("write fieldname: %s part: %d isize: %d iarray: %d\n",fieldNameD[j],startpart+i,isize, iarray[0]); writeheader( &writeHandle, fieldtag, (void*)iarray, &expectD[j], &isize, "double", "binary"); writedatablock( &writeHandle, fieldtag, (void*)Dfield[i][j], &isize, "double", "binary"); if ( cscompare("block",headerTypeD[j]) ) delete [] Dfield[i][j]; } delete [] paraD[i][j]; } } for ( i = 0; i < nppp; i++ ) { interiorMark[i]=0; boundaryMark[i]=0; codesMark[i]=0; } MPI_Barrier(MPI_COMM_WORLD); if(myrank==0){ printf("Starting to write some blocks (integers) in the geombc.dat-## files\n"); } // Now the other fields listed in IO.O2N.input for ( j = 0; j < N_geombc_integer; j++ ) { for ( i = 0; i < nppp; i++ ) { //if ( WriteLockI[i] == 0 ) { GPID = startpart + i; bzero((void*)fieldtag,255); if (cscompare("connectivity interior",fieldNameI[j])) { interiorMark[i]++; bzero((void*)fieldNameI[j],128); sprintf(fieldNameI[j],"connectivity interior%d",interiorMark[i]); // if ( interiorMark[i]>numInteriorFields[i] ) // for ( k = 0; k < expectI[j]; k++ ) // paraI[i][j][k] = 0; } if (cscompare("connectivity boundary",fieldNameI[j])) { boundaryMark[i]++; bzero((void*)fieldNameI[j],128); sprintf(fieldNameI[j],"connectivity boundary%d",boundaryMark[i]); // if ( boundaryMark[i]>numBoundaryFields[i] ) // for ( k = 0; k < expectI[j]; k++ ) // paraI[i][j][k] = 0; } fieldCompareMark=0; if (cscompare("nbc codes",fieldNameI[j])) { fieldCompareMark=1; codesMark[i]++; bzero((void*)fieldNameI[j],128); sprintf(fieldNameI[j],"nbc codes%d",codesMark[i]); // if ( codesMark[i]>numBoundaryFields[i] ) // for ( k = 0; k < expectI[j]; k++ ) // paraI[i][j][k] = 0; } sprintf(fieldtag,"%s@%d",fieldNameI[j],GPID); // if ( expectI[j]==1) // isize = paraI[i][j][0]; // else // isize = paraI[i][j][0] * paraI[i][j][1]; //MR CHANGE // printf("rank,j,i,isize %d %d %d %d\n",myrank,j,i,isize); //specially designed for nbc codes fields //check the size in presolver codes // if (fieldCompareMark==1) // isize = paraI[i][j][0] * 2; if ( cscompare("header",headerTypeI[j]) ) isize = 0; else isize = computenitems(i,j,myrank,fieldNameI[j],paraI,expectI[j],numVariables[i]); for ( k = 0; k < expectI[j]; k++ ) iarray[k] = paraI[i][j][k]; // printf("write fieldname: %s part: %d isize: %d iarray: %d\n",fieldNameI[j],startpart+i,isize, iarray[0]); writeheader( &writeHandle, fieldtag, (void*)iarray, &expectI[j], &isize, "integer", "binary"); writedatablock( &writeHandle, fieldtag, (void*)Ifield[i][j], &isize, "integer", "binary" ); if ( cscompare("block",headerTypeI[j]) ){ // printf("rank %d - deleting Ifield %d %d\n",myrank,i,j); delete [] Ifield[i][j]; // printf("rank %d - Ifield deleted %d %d\n",myrank,i,j); } } // printf("rank %d - deleting paraI %d %d\n",myrank,i,j); delete [] paraI[i][j]; // printf("rank %d - paraI deleted %d %d\n",myrank,i,j); } } MPI_Barrier(MPI_COMM_WORLD); if(myrank==0){ printf("Closing geombc-dat.##.## files\n"); } closefile(&writeHandle, "write"); finalizephmpiio(&writeHandle); if(myrank==0){ printf("Free memory related to geombc-dat.##.## files\n"); } for ( i = 0; i < nppp; i++ ) { delete [] Dfield[i]; delete [] paraD[i]; delete [] Ifield[i]; delete [] paraI[i]; } for ( i = 0; i < N_geombc_double; i++ ) { delete [] fieldNameD[i]; delete [] fileTypeD[i]; delete [] dataTypeD[i]; delete [] headerTypeD[i]; } for ( i = 0; i < N_geombc_integer; i++ ) { delete [] fieldNameI[i]; delete [] fileTypeI[i]; delete [] dataTypeI[i]; delete [] headerTypeI[i]; } delete [] Dfield; delete [] Ifield; delete [] paraD; delete [] paraI; delete [] expectD; delete [] expectI; delete [] fieldNameD; delete [] fileTypeD; delete [] dataTypeD; delete [] headerTypeD; delete [] fieldNameI; delete [] fileTypeI; delete [] dataTypeI; delete [] headerTypeI; MPI_Barrier(MPI_COMM_WORLD); if(myrank==0){ printf("Done with geombc-dat.##.## files\n"); } /////////////////////// restart data //////////////////////////// int irestart; Dfield = new double**[N_restart_double]; Ifield = new int**[N_restart_integer]; paraD = new int**[N_restart_double]; paraI = new int**[N_restart_integer]; expectD = new int[N_restart_double]; expectI = new int[N_restart_integer]; fieldNameD = new char*[N_restart_double]; fileTypeD = new char*[N_restart_double]; dataTypeD = new char*[N_restart_double]; headerTypeD = new char*[N_restart_double]; fieldNameI = new char*[N_restart_integer]; fileTypeI = new char*[N_restart_integer]; dataTypeI = new char*[N_restart_integer]; headerTypeI = new char*[N_restart_integer]; if (N_restart_double>0) for ( i = 0; i < N_restart_double; i++ ) { WriteLockD[i]=0; Dfield[i] = new double*[nppp]; paraD[i] = new int*[nppp]; fieldNameD[i] = new char[128]; fileTypeD[i] = new char[128]; dataTypeD[i] = new char[128]; headerTypeD[i] = new char[128]; } if (N_restart_integer>0) for ( i = 0; i < N_restart_integer; i++ ) { WriteLockI[i]=0; Ifield[i] = new int*[nppp]; paraI[i] = new int*[nppp]; fieldNameI[i] = new char[128]; fileTypeI[i] = new char[128]; dataTypeI[i] = new char[128]; headerTypeI[i] = new char[128]; } //////////////////////////////////////////////////////////////// // temporary fix: in the new version the double and integer // can mix and match to avoid the order confusion //////////////////////////////////////////////////////////////// double_counter=0,int_counter=0; for ( i = 0; i < N_restart_double+N_restart_integer; i++ ) { fgets( target, 1024, pFile ); temp = strtok( target, ";" ); token = strtok( temp, "," ); strcpy( S1, token ); token = strtok ( NULL, "," ); strcpy( S2, token ); token = strtok ( NULL, "," ); strcpy( S3, token ); token = strtok ( NULL, "," ); strcpy( S4, token ); token = strtok ( NULL, "," ); strcpy( S5, token ); if (cscompare(S3,"double")) { strcpy( fileTypeD[double_counter], S1 ); strcpy( fieldNameD[double_counter], S2 ); strcpy( dataTypeD[double_counter], S3 ); strcpy( headerTypeD[double_counter], S4 ); strcpy( numTemp, S5 ); expectD[double_counter] = atoi (numTemp); double_counter++; } if (cscompare(S3,"integer")) { strcpy( fileTypeI[int_counter], S1 ); strcpy( fieldNameI[int_counter], S2 ); strcpy( dataTypeI[int_counter], S3 ); strcpy( headerTypeI[int_counter], S4 ); strcpy( numTemp, S5 ); expectI[int_counter] = atoi (numTemp); int_counter++; } } MPI_Barrier(MPI_COMM_WORLD); if(myrank==0){ printf("Starting to read some blocks (doubles) in the restart.dat.##.## files\n"); } for ( i = 0; i < N_restart_double; i++ ) { for ( j = 0; j < nppp; j++ ) { if(existsubdir) { subdir = (startpart+j-1) / DIR_FANOUT; sprintf(gfname,"./%d-procs_case/%d/restart.%d.%d",N_parts, subdir, N_steps,startpart+j); } else sprintf(gfname,"./%d-procs_case/restart.%d.%d",N_parts, N_steps, startpart+j); openfile(gfname,"read",&irestart); for ( k = 0; k < 10; k++ ) iarray[k]=0; paraD[i][j] = new int[expectD[i]]; iarray[0]=-1; readheader( &irestart, fieldNameD[i], (void*)iarray, &expectD[i], "double", "binary" ); for ( k = 0; k < expectD[i]; k++ ) paraD[i][j][k] = iarray[k]; if ( iarray[0]==-1 ) WriteLockD[i]=1; if ( WriteLockD[i]==0 ) { if ( cscompare("block",headerTypeD[i]) ) { if ( expectD[i]==1) isize = paraD[i][j][0]; else isize = paraD[i][j][0] * paraD[i][j][1]; Dfield[i][j] = new double[isize]; readdatablock( &irestart, fieldNameD[i], (void*)Dfield[i][j], &isize, "double", "binary" ); } } closefile(&irestart, "read"); } } MPI_Barrier(MPI_COMM_WORLD); if(myrank==0){ printf("Starting to read some blocks (integers) in the restart.dat.##.## files\n"); } for ( i = 0; i < N_restart_integer; i++ ) { for ( j = 0; j < nppp; j++ ) { if(existsubdir) { subdir = (startpart+j-1) / DIR_FANOUT; sprintf(gfname,"./%d-procs_case/%d/restart.%d.%d",N_parts, subdir, N_steps, startpart+j); } else sprintf(gfname,"./%d-procs_case/restart.%d.%d",N_parts, N_steps, startpart+j); openfile(gfname,"read",&irestart); for ( k = 0; k < 10; k++ ) iarray[k]=0; paraI[i][j] = new int[expectI[i]]; iarray[0]=-1; readheader( &irestart, fieldNameI[i], (void*)iarray, &expectI[i], "integer", "binary" ); for ( k = 0; k < expectI[i]; k++ ) paraI[i][j][k] = iarray[k]; if ( iarray[0]==-1 ) WriteLockI[i]=1; if ( WriteLockI[i]==0 ) { if ( cscompare("block",headerTypeI[i]) ) { if ( expectI[i]==1) isize = paraI[i][j][0]; else isize = paraI[i][j][0] * paraI[i][j][1]; Ifield[i][j] = new int[isize]; readdatablock( &irestart, fieldNameI[i], (void*)Ifield[i][j], &isize, "integer", "binary" ); } } closefile(&irestart, "read"); } } fclose(pFile); ///////////////////// Writing /////////////////////////////// int N_restart = N_restart_double + N_restart_integer; bzero((void*)fname,255); //MR CHANGE // sprintf(fname,"./%d-procs_case/restart-dat.%d.%d",N_parts,N_steps,((int)(myrank/(N_procs/N_files))+1)); sprintf(fname,"./%d-procs_case-SyncIO-%d/restart-dat.%d.%d",N_parts,N_files,N_steps,((int)(myrank/(N_procs/N_files))+1)); //MR CHANGE END initphmpiio(&N_restart, &nppf, &N_files,&writeHandle, "write"); // initphmpiio(&N_restart, &nppf, &N_files,&writeHandle); openfile(fname, "write", &writeHandle); MPI_Barrier(MPI_COMM_WORLD); if(myrank==0){ printf("Starting to write some blocks (doubles) in the restart-dat.##.## files\n"); } for ( i = 0; i < N_restart_double; i++ ) { for ( j = 0; j < nppp; j++ ) { if (WriteLockD[i]==0) { GPID = startpart + j; bzero((void*)fieldtag,255); sprintf(fieldtag,"%s@%d",fieldNameD[i],GPID); if ( expectD[i]==1) isize = paraD[i][j][0]; else isize = paraD[i][j][0] * paraD[i][j][1]; for ( k = 0; k < expectD[i]; k++ ) iarray[k] = paraD[i][j][k]; if ( cscompare("header",headerTypeD[i]) ) isize = 0; writeheader( &writeHandle, fieldtag, (void*)iarray, &expectD[i], &isize, "double", "binary"); writedatablock( &writeHandle, fieldtag, (void*)Dfield[i][j], &isize, "double", "binary" ); if ( cscompare("block",headerTypeD[i]) ) delete [] Dfield[i][j]; } delete [] paraD[i][j]; } } MPI_Barrier(MPI_COMM_WORLD); if(myrank==0){ printf("Starting to write some blocks (integers) in the restart.dat.##.## files\n"); } for ( i = 0; i < N_restart_integer; i++ ) { for ( j = 0; j < nppp; j++ ) { if (WriteLockI[i]==0) { GPID = startpart + j; bzero((void*)fieldtag,255); sprintf(fieldtag,"%s@%d",fieldNameI[i],GPID); if ( expectI[i]==1) isize = paraI[i][j][0]; else isize = paraI[i][j][0] * paraI[i][j][1]; for ( k = 0; k < expectI[i]; k++ ) iarray[k] = paraI[i][j][k]; if ( cscompare("header",headerTypeI[i]) ) isize = 0; writeheader( &writeHandle, fieldtag, (void*)iarray, &expectI[i], &isize, "integer", "binary"); writedatablock( &writeHandle, fieldtag, (void*)Ifield[i][j], &isize, "integer", "binary" ); if ( cscompare("block",headerTypeI[i]) ) delete [] Ifield[i][j]; } delete [] paraI[i][j]; } } MPI_Barrier(MPI_COMM_WORLD); if(myrank==0){ printf("Closing restart-dat.##.## files\n"); } closefile(&writeHandle, "write"); finalizephmpiio(&writeHandle); MPI_Barrier(MPI_COMM_WORLD); if(myrank==0){ printf("Free memory related to restart-dat.##.## files\n"); } for ( i = 0; i < N_restart_double; i++ ) { delete [] Dfield[i]; delete [] paraD[i]; delete [] fieldNameD[i]; delete [] fileTypeD[i]; delete [] dataTypeD[i]; delete [] headerTypeD[i]; } for ( i = 0; i < N_restart_integer; i++ ) { delete [] Ifield[i]; delete [] paraI[i]; delete [] fieldNameI[i]; delete [] fileTypeI[i]; delete [] dataTypeI[i]; delete [] headerTypeI[i]; } delete [] Dfield; delete [] Ifield; delete [] paraD; delete [] paraI; delete [] expectD; delete [] expectI; delete [] fieldNameD; delete [] fileTypeD; delete [] dataTypeD; delete [] headerTypeD; delete [] fieldNameI; delete [] fileTypeI; delete [] dataTypeI; delete [] headerTypeI; delete [] WriteLockD; delete [] WriteLockI; delete [] interiorMark; delete [] boundaryMark; delete [] codesMark; delete [] valuesMark; delete [] numVariables; if (myrank==0) { printf("\nFinished transfer, please check data using:\n"); printf(" grep -a ': <' filename \n\n"); printf("Note that the size of the fields is computed based on previous geombc files\n"); printf("Check the routine 'computenitems' if you have any reason to think it has changes for the fields you are interested in\n\n"); } MPI_Finalize(); }