git-svn-id: svn://svn.icms.temple.edu/lammps-ro/trunk@11095 f3b2605a-c512-4ea7-a41b-209d697bcdaa

This commit is contained in:
sjplimp
2013-12-06 22:32:32 +00:00
parent 6831bc9d32
commit 6bfbfa78f4
6 changed files with 691 additions and 389 deletions

View File

@ -57,12 +57,12 @@ class Dump : protected Pointers {
int binary; // 1 if dump file is written binary, 0 no int binary; // 1 if dump file is written binary, 0 no
int multifile; // 0 = one big file, 1 = one file per timestep int multifile; // 0 = one big file, 1 = one file per timestep
int multiproc; // 0 = proc 0 writes for all, int multiproc; // 0 = proc 0 writes for all
// else # of procs writing files // else # of procs writing files
int nclusterprocs; // # of procs in my cluster that write to one file int nclusterprocs; // # of procs in my cluster that write to one file
int filewriter; // 1 if this proc writes a file, else 0 int filewriter; // 1 if this proc writes a file, else 0
int fileproc; // ID of proc in my cluster who writes to file int fileproc; // ID of proc in my cluster who writes to file
char *multiname; // dump filename with % converted to cluster ID char *multiname; // filename with % converted to cluster ID
MPI_Comm clustercomm; // MPI communicator within my cluster of procs MPI_Comm clustercomm; // MPI communicator within my cluster of procs
int header_flag; // 0 = item, 2 = xyz int header_flag; // 0 = item, 2 = xyz

View File

@ -706,9 +706,13 @@ void Output::create_restart(int narg, char **arg)
return; return;
} }
if (narg != 2 && narg != 3) error->all(FLERR,"Illegal restart command"); if (narg < 2) error->all(FLERR,"Illegal restart command");
if (narg == 2) { int nfile = 0;
if (narg % 2 == 0) nfile = 1;
else nfile = 2;
if (nfile = 1) {
restart_flag = restart_flag_single = 1; restart_flag = restart_flag_single = 1;
if (varflag) { if (varflag) {
@ -725,7 +729,7 @@ void Output::create_restart(int narg, char **arg)
if (strchr(restart1,'*') == NULL) strcat(restart1,".*"); if (strchr(restart1,'*') == NULL) strcat(restart1,".*");
} }
if (narg == 3) { if (nfile == 2) {
restart_flag = restart_flag_double = 1; restart_flag = restart_flag_double = 1;
if (varflag) { if (varflag) {
@ -745,7 +749,35 @@ void Output::create_restart(int narg, char **arg)
strcpy(restart2b,arg[2]); strcpy(restart2b,arg[2]);
} }
if (restart == NULL) restart = new WriteRestart(lmp); // check for multiproc output and an MPI-IO filename
// if 2 filenames, must be consistent
int multiproc;
if (strchr(arg[1],'%')) multiproc = comm->nprocs;
else multiproc = 0;
if (nfile == 2) {
if (multiproc && !strchr(arg[2],'%'))
error->all(FLERR,"Both restart files must have '%' or neither");
if (!multiproc && strchr(arg[2],'%'))
error->all(FLERR,"Both restart files must have '%' or neither");
}
int mpiio;
if (strstr(arg[1],".mpi")) mpiio = 1;
else mpiio = 0;
if (nfile == 2) {
if (mpiio && !strstr(arg[2],".mpi"))
error->all(FLERR,"Both restart files must use MPI-IO or neither");
if (!mpiio && strstr(arg[2],".mpi"))
error->all(FLERR,"Both restart files must use MPI-IO or neither");
}
// setup output style and process optional args
delete restart;
restart = new WriteRestart(lmp);
int iarg = nfile+1;
restart->multiproc_options(multiproc,mpiio,narg-iarg,&arg[iarg]);
} }
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------

View File

@ -15,7 +15,6 @@
#include "mpi.h" #include "mpi.h"
#include "string.h" #include "string.h"
#include "stdlib.h" #include "stdlib.h"
//#include "sys/types.h"
#include "dirent.h" #include "dirent.h"
#include "read_restart.h" #include "read_restart.h"
#include "atom.h" #include "atom.h"
@ -43,21 +42,24 @@ using namespace LAMMPS_NS;
// same as write_restart.cpp // same as write_restart.cpp
#define MAGIC_STRING "LammpS RestartT"
#define ENDIAN 0x0001
#define ENDIANSWAP 0x1000
#define VERSION_NUMERIC 0
enum{VERSION,SMALLINT,TAGINT,BIGINT, enum{VERSION,SMALLINT,TAGINT,BIGINT,
UNITS,NTIMESTEP,DIMENSION,NPROCS,PROCGRID_0,PROCGRID_1,PROCGRID_2, UNITS,NTIMESTEP,DIMENSION,NPROCS,PROCGRID,
NEWTON_PAIR,NEWTON_BOND,XPERIODIC,YPERIODIC,ZPERIODIC, NEWTON_PAIR,NEWTON_BOND,
BOUNDARY_00,BOUNDARY_01,BOUNDARY_10,BOUNDARY_11,BOUNDARY_20,BOUNDARY_21, XPERIODIC,YPERIODIC,ZPERIODIC,BOUNDARY,
ATOM_STYLE,NATOMS,NTYPES, ATOM_STYLE,NATOMS,NTYPES,
NBONDS,NBONDTYPES,BOND_PER_ATOM, NBONDS,NBONDTYPES,BOND_PER_ATOM,
NANGLES,NANGLETYPES,ANGLE_PER_ATOM, NANGLES,NANGLETYPES,ANGLE_PER_ATOM,
NDIHEDRALS,NDIHEDRALTYPES,DIHEDRAL_PER_ATOM, NDIHEDRALS,NDIHEDRALTYPES,DIHEDRAL_PER_ATOM,
NIMPROPERS,NIMPROPERTYPES,IMPROPER_PER_ATOM, NIMPROPERS,NIMPROPERTYPES,IMPROPER_PER_ATOM,
BOXLO_0,BOXHI_0,BOXLO_1,BOXHI_1,BOXLO_2,BOXHI_2, TRICLINIC,BOXLO,BOXHI,XY,XZ,YZ,
SPECIAL_LJ_1,SPECIAL_LJ_2,SPECIAL_LJ_3, SPECIAL_LJ,SPECIAL_COUL,
SPECIAL_COUL_1,SPECIAL_COUL_2,SPECIAL_COUL_3, MASS,PAIR,BOND,ANGLE,DIHEDRAL,IMPROPER,
XY,XZ,YZ}; MULTIPROC,MPIIO,PROCSPERFILE,PERPROC};
enum{MASS};
enum{PAIR,BOND,ANGLE,DIHEDRAL,IMPROPER};
#define LB_FACTOR 1.1 #define LB_FACTOR 1.1
@ -90,14 +92,18 @@ void ReadRestart::command(int narg, char **arg)
MPI_Bcast(file,n,MPI_CHAR,0,world); MPI_Bcast(file,n,MPI_CHAR,0,world);
} else strcpy(file,arg[0]); } else strcpy(file,arg[0]);
// check if filename contains "%" // check for multiproc files and an MPI-IO filename
int multiproc; if (strchr(arg[0],'%')) multiproc = 1;
if (strchr(file,'%')) multiproc = 1;
else multiproc = 0; else multiproc = 0;
if (strstr(arg[0],".mpi")) mpiio = 1;
else mpiio = 0;
if (multiproc && mpiio)
error->all(FLERR,
"Read restart MPI-IO output not allowed with '%' in filename");
// open single restart file or base file for multiproc case // open single restart file or base file for multiproc case
// auto-detect whether byte swapping needs to be done as file is read
if (me == 0) { if (me == 0) {
if (screen) fprintf(screen,"Reading restart file ...\n"); if (screen) fprintf(screen,"Reading restart file ...\n");
@ -115,15 +121,18 @@ void ReadRestart::command(int narg, char **arg)
sprintf(str,"Cannot open restart file %s",hfile); sprintf(str,"Cannot open restart file %s",hfile);
error->one(FLERR,str); error->one(FLERR,str);
} }
swapflag = autodetect(&fp,hfile);
if (multiproc) delete [] hfile; if (multiproc) delete [] hfile;
} }
MPI_Bcast(&swapflag,1,MPI_INT,0,world); // read magic string, endian flag, numeric version
// read header info and create atom style and simulation box magic_string();
endian();
int outofdate = version_numeric();
header(); // read header info which creates simulation box
header(outofdate);
domain->box_exist = 1; domain->box_exist = 1;
// problem setup using info from header // problem setup using info from header
@ -153,12 +162,19 @@ void ReadRestart::command(int narg, char **arg)
atom->nextra_store = nextra; atom->nextra_store = nextra;
memory->create(atom->extra,n,nextra,"atom:extra"); memory->create(atom->extra,n,nextra,"atom:extra");
// read file layout info
file_layout();
// all done with reading header info
if (me == 0) fclose(fp);
// single file: // single file:
// nprocs_file = # of chunks in file // nprocs_file = # of chunks in file
// proc 0 reads chunks one at a time and bcasts it to other procs // proc 0 reads a chunk and bcasts it to other procs
// each proc unpacks the atoms, saving ones in it's sub-domain // each proc unpacks the atoms, saving ones in it's sub-domain
// check for atom in sub-domain differs for orthogonal vs triclinic box // check for atom in sub-domain differs for orthogonal vs triclinic box
// close restart file when done
AtomVec *avec = atom->avec; AtomVec *avec = atom->avec;
@ -167,6 +183,7 @@ void ReadRestart::command(int narg, char **arg)
int m; int m;
if (multiproc == 0) { if (multiproc == 0) {
int triclinic = domain->triclinic; int triclinic = domain->triclinic;
double *x,lamda[3]; double *x,lamda[3];
double *coord,*sublo,*subhi; double *coord,*sublo,*subhi;
@ -179,17 +196,16 @@ void ReadRestart::command(int narg, char **arg)
} }
for (int iproc = 0; iproc < nprocs_file; iproc++) { for (int iproc = 0; iproc < nprocs_file; iproc++) {
if (read_int() != PERPROC)
error->all(FLERR,"Invalid flag in peratom section of restart file");
n = read_int(); n = read_int();
if (n > maxbuf) { if (n > maxbuf) {
maxbuf = n; maxbuf = n;
memory->destroy(buf); memory->destroy(buf);
memory->create(buf,maxbuf,"read_restart:buf"); memory->create(buf,maxbuf,"read_restart:buf");
} }
read_double_vec(n,buf);
if (n > 0) {
if (me == 0) nread_double(buf,n,fp);
MPI_Bcast(buf,n,MPI_DOUBLE,0,world);
}
m = 0; m = 0;
while (m < n) { while (m < n) {
@ -210,42 +226,166 @@ void ReadRestart::command(int narg, char **arg)
if (me == 0) fclose(fp); if (me == 0) fclose(fp);
// one file per proc: // multiple files with procs <= files
// nprocs_file = # of files // # of files = multiproc_file
// each proc reads 1/P fraction of files, keeping all atoms in the files // each proc reads a subset of files, striding by nprocs
// perform irregular comm to migrate atoms to correct procs // each proc keeps all atoms in all perproc chunks in its files
// close restart file when done
} else { } else if (nprocs <= multiproc_file) {
if (me == 0) fclose(fp);
char *perproc = new char[strlen(file) + 16]; char *procfile = new char[strlen(file) + 16];
char *ptr = strchr(file,'%'); char *ptr = strchr(file,'%');
for (int iproc = me; iproc < nprocs_file; iproc += nprocs) { for (int iproc = me; iproc < multiproc_file; iproc += nprocs) {
*ptr = '\0'; *ptr = '\0';
sprintf(perproc,"%s%d%s",file,iproc,ptr+1); sprintf(procfile,"%s%d%s",file,iproc,ptr+1);
*ptr = '%'; *ptr = '%';
fp = fopen(perproc,"rb"); fp = fopen(procfile,"rb");
if (fp == NULL) { if (fp == NULL) {
char str[128]; char str[128];
sprintf(str,"Cannot open restart file %s",perproc); sprintf(str,"Cannot open restart file %s",procfile);
error->one(FLERR,str); error->one(FLERR,str);
} }
nread_int(&n,1,fp); int flag;
if (n > maxbuf) { fread(&flag,sizeof(int),1,fp);
maxbuf = n; if (flag != PROCSPERFILE)
memory->destroy(buf); error->one(FLERR,"Invalid flag in peratom section of restart file");
memory->create(buf,maxbuf,"read_restart:buf"); int procsperfile;
} fread(&procsperfile,sizeof(int),1,fp);
if (n > 0) nread_double(buf,n,fp);
for (int i = 0; i < procsperfile; i++) {
fread(&flag,sizeof(int),1,fp);
if (flag != PERPROC)
error->one(FLERR,"Invalid flag in peratom section of restart file");
fread(&n,sizeof(int),1,fp);
if (n > maxbuf) {
maxbuf = n;
memory->destroy(buf);
memory->create(buf,maxbuf,"read_restart:buf");
}
fread(buf,sizeof(double),n,fp);
m = 0;
while (m < n) m += avec->unpack_restart(&buf[m]);
}
m = 0;
while (m < n) m += avec->unpack_restart(&buf[m]);
fclose(fp); fclose(fp);
} }
delete [] perproc; delete [] procfile;
// multiple files with procs > files
// # of files = multiproc_file
// cluster procs based on # of files
// 1st proc in each cluster reads per-proc chunks from file
// sends chunks round-robin to other procs in its cluster
// each proc keeps all atoms in its perproc chunks in file
} else {
// nclusterprocs = # of procs in my cluster that read from one file
// filewriter = 1 if this proc reads file, else 0
// fileproc = ID of proc in my cluster who reads from file
// clustercomm = MPI communicator within my cluster of procs
int nfile = multiproc_file;
int icluster = static_cast<int> ((bigint) me * nfile/nprocs);
int fileproc = static_cast<int> ((bigint) icluster * nprocs/nfile);
int fcluster = static_cast<int> ((bigint) fileproc * nfile/nprocs);
if (fcluster < icluster) fileproc++;
int fileprocnext =
static_cast<int> ((bigint) (icluster+1) * nprocs/nfile);
fcluster = static_cast<int> ((bigint) fileprocnext * nfile/nprocs);
if (fcluster < icluster+1) fileprocnext++;
int nclusterprocs = fileprocnext - fileproc;
int filereader = 0;
if (me == fileproc) filereader = 1;
MPI_Comm clustercomm;
MPI_Comm_split(world,icluster,0,&clustercomm);
if (filereader) {
char *procfile = new char[strlen(file) + 16];
char *ptr = strchr(file,'%');
*ptr = '\0';
sprintf(procfile,"%s%d%s",file,icluster,ptr+1);
*ptr = '%';
fp = fopen(procfile,"rb");
if (fp == NULL) {
char str[128];
sprintf(str,"Cannot open restart file %s",procfile);
error->one(FLERR,str);
}
delete [] procfile;
}
int flag,procsperfile;
if (filereader) {
fread(&flag,sizeof(int),1,fp);
if (flag != PROCSPERFILE)
error->one(FLERR,"Invalid flag in peratom section of restart file");
fread(&procsperfile,sizeof(int),1,fp);
}
MPI_Bcast(&procsperfile,1,MPI_INT,0,clustercomm);
int tmp,iproc;
MPI_Status status;
MPI_Request request;
for (int i = 0; i < procsperfile; i++) {
if (filereader) {
fread(&flag,sizeof(int),1,fp);
if (flag != PERPROC)
error->one(FLERR,"Invalid flag in peratom section of restart file");
fread(&n,sizeof(int),1,fp);
if (n > maxbuf) {
maxbuf = n;
memory->destroy(buf);
memory->create(buf,maxbuf,"read_restart:buf");
}
fread(buf,sizeof(double),n,fp);
if (i % nclusterprocs) {
iproc = me + (i % nclusterprocs);
MPI_Send(&n,1,MPI_INT,iproc,0,world);
MPI_Recv(&tmp,0,MPI_INT,iproc,0,world,&status);
MPI_Rsend(buf,n,MPI_DOUBLE,iproc,0,world);
}
} else if (i % nclusterprocs == me - fileproc) {
MPI_Recv(&n,1,MPI_INT,fileproc,0,world,&status);
if (n > maxbuf) {
maxbuf = n;
memory->destroy(buf);
memory->create(buf,maxbuf,"read_restart:buf");
}
MPI_Irecv(buf,n,MPI_DOUBLE,fileproc,0,world,&request);
MPI_Send(&tmp,0,MPI_INT,fileproc,0,world);
MPI_Wait(&request,&status);
}
if (i % nclusterprocs == me - fileproc) {
m = 0;
while (m < n) m += avec->unpack_restart(&buf[m]);
}
}
if (filereader) fclose(fp);
MPI_Comm_free(&clustercomm);
}
// clean-up memory
delete [] file;
memory->destroy(buf);
// for multiproc files:
// perform irregular comm to migrate atoms to correct procs
if (multiproc) {
// create a temporary fix to hold and migrate extra atom info // create a temporary fix to hold and migrate extra atom info
// necessary b/c irregular will migrate atoms // necessary b/c irregular will migrate atoms
@ -294,11 +434,6 @@ void ReadRestart::command(int narg, char **arg)
} }
} }
// clean-up memory
delete [] file;
memory->destroy(buf);
// check that all atoms were assigned to procs // check that all atoms were assigned to procs
bigint natoms; bigint natoms;
@ -451,13 +586,13 @@ void ReadRestart::file_search(char *infile, char *outfile)
read header of restart file read header of restart file
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
void ReadRestart::header() void ReadRestart::header(int outofdate)
{ {
int px,py,pz; int px,py,pz;
int xperiodic,yperiodic,zperiodic; int xperiodic,yperiodic,zperiodic;
int boundary[3][2]; int boundary[3][2];
// read flags and values until flag = -1 // read flags and fields until flag = -1
int flag = read_int(); int flag = read_int();
while (flag >= 0) { while (flag >= 0) {
@ -465,16 +600,16 @@ void ReadRestart::header()
// check restart file version, warn if different // check restart file version, warn if different
if (flag == VERSION) { if (flag == VERSION) {
char *version = read_char(); char *version = read_string();
if (strcmp(version,universe->version) != 0 && me == 0) { if (me == 0) {
error->warning(FLERR,
"Restart file version does not match LAMMPS version");
if (screen) fprintf(screen," restart file = %s, LAMMPS = %s\n", if (screen) fprintf(screen," restart file = %s, LAMMPS = %s\n",
version,universe->version); version,universe->version);
} }
if (outofdate)
error->all(FLERR,"Restart file too old for current version to read");
delete [] version; delete [] version;
// check lmptype.h sizes, error if different // check lmptype.h sizes, error if different
} else if (flag == SMALLINT) { } else if (flag == SMALLINT) {
int size = read_int(); int size = read_int();
@ -489,18 +624,18 @@ void ReadRestart::header()
if (size != sizeof(bigint)) if (size != sizeof(bigint))
error->all(FLERR,"Bigint setting in lmptype.h is not compatible"); error->all(FLERR,"Bigint setting in lmptype.h is not compatible");
// reset unit_style only if different // reset unit_style only if different
// so that timestep,neighbor-skin are not changed // so that timestep,neighbor-skin are not changed
} else if (flag == UNITS) { } else if (flag == UNITS) {
char *style = read_char(); char *style = read_string();
if (strcmp(style,update->unit_style) != 0) update->set_units(style); if (strcmp(style,update->unit_style) != 0) update->set_units(style);
delete [] style; delete [] style;
} else if (flag == NTIMESTEP) { } else if (flag == NTIMESTEP) {
update->ntimestep = read_bigint(); update->ntimestep = read_bigint();
// set dimension from restart file // set dimension from restart file
} else if (flag == DIMENSION) { } else if (flag == DIMENSION) {
int dimension = read_int(); int dimension = read_int();
@ -509,24 +644,23 @@ void ReadRestart::header()
error->all(FLERR, error->all(FLERR,
"Cannot run 2d simulation with nonperiodic Z dimension"); "Cannot run 2d simulation with nonperiodic Z dimension");
// read nprocs from restart file, warn if different // read nprocs from restart file, warn if different
} else if (flag == NPROCS) { } else if (flag == NPROCS) {
nprocs_file = read_int(); nprocs_file = read_int();
if (nprocs_file != comm->nprocs && me == 0) if (nprocs_file != comm->nprocs && me == 0)
error->warning(FLERR,"Restart file used different # of processors"); error->warning(FLERR,"Restart file used different # of processors");
// don't set procgrid, warn if different // don't set procgrid, warn if different
} else if (flag == PROCGRID_0) { } else if (flag == PROCGRID) {
px = read_int(); int procgrid[3];
} else if (flag == PROCGRID_1) { read_int();
py = read_int(); read_int_vec(3,procgrid);
} else if (flag == PROCGRID_2) {
pz = read_int();
if (comm->user_procgrid[0] != 0 && if (comm->user_procgrid[0] != 0 &&
(px != comm->user_procgrid[0] || py != comm->user_procgrid[1] || (procgrid[0] != comm->user_procgrid[0] ||
pz != comm->user_procgrid[2]) && me == 0) procgrid[1] != comm->user_procgrid[1] ||
procgrid[2] != comm->user_procgrid[2]) && me == 0)
error->warning(FLERR,"Restart file used different 3d processor grid"); error->warning(FLERR,"Restart file used different 3d processor grid");
// don't set newton_pair, leave input script value unchanged // don't set newton_pair, leave input script value unchanged
@ -562,18 +696,10 @@ void ReadRestart::header()
yperiodic = read_int(); yperiodic = read_int();
} else if (flag == ZPERIODIC) { } else if (flag == ZPERIODIC) {
zperiodic = read_int(); zperiodic = read_int();
} else if (flag == BOUNDARY_00) { } else if (flag == BOUNDARY) {
boundary[0][0] = read_int(); int boundary[3][2];
} else if (flag == BOUNDARY_01) { read_int();
boundary[0][1] = read_int(); read_int_vec(6,&boundary[0][0]);
} else if (flag == BOUNDARY_10) {
boundary[1][0] = read_int();
} else if (flag == BOUNDARY_11) {
boundary[1][1] = read_int();
} else if (flag == BOUNDARY_20) {
boundary[2][0] = read_int();
} else if (flag == BOUNDARY_21) {
boundary[2][1] = read_int();
if (domain->boundary[0][0] || domain->boundary[0][1] || if (domain->boundary[0][0] || domain->boundary[0][1] ||
domain->boundary[1][0] || domain->boundary[1][1] || domain->boundary[1][0] || domain->boundary[1][1] ||
@ -611,11 +737,11 @@ void ReadRestart::header()
domain->nonperiodic = 2; domain->nonperiodic = 2;
} }
// create new AtomVec class // create new AtomVec class
// if style = hybrid, read additional sub-class arguments // if style = hybrid, read additional sub-class arguments
} else if (flag == ATOM_STYLE) { } else if (flag == ATOM_STYLE) {
char *style = read_char(); char *style = read_string();
int nwords = 0; int nwords = 0;
char **words = NULL; char **words = NULL;
@ -623,7 +749,7 @@ void ReadRestart::header()
if (strcmp(style,"hybrid") == 0) { if (strcmp(style,"hybrid") == 0) {
nwords = read_int(); nwords = read_int();
words = new char*[nwords]; words = new char*[nwords];
for (int i = 0; i < nwords; i++) words[i] = read_char(); for (int i = 0; i < nwords; i++) words[i] = read_string();
} }
atom->create_avec(style,nwords,words); atom->create_avec(style,nwords,words);
@ -662,42 +788,28 @@ void ReadRestart::header()
} else if (flag == IMPROPER_PER_ATOM) { } else if (flag == IMPROPER_PER_ATOM) {
atom->improper_per_atom = read_int(); atom->improper_per_atom = read_int();
} else if (flag == BOXLO_0) { } else if (flag == TRICLINIC) {
domain->boxlo[0] = read_double(); domain->triclinic = read_int();
} else if (flag == BOXHI_0) { } else if (flag == BOXLO) {
domain->boxhi[0] = read_double(); read_int();
} else if (flag == BOXLO_1) { read_double_vec(3,domain->boxlo);
domain->boxlo[1] = read_double(); } else if (flag == BOXHI) {
} else if (flag == BOXHI_1) { read_int();
domain->boxhi[1] = read_double(); read_double_vec(3,domain->boxhi);
} else if (flag == BOXLO_2) {
domain->boxlo[2] = read_double();
} else if (flag == BOXHI_2) {
domain->boxhi[2] = read_double();
} else if (flag == SPECIAL_LJ_1) {
force->special_lj[1] = read_double();
} else if (flag == SPECIAL_LJ_2) {
force->special_lj[2] = read_double();
} else if (flag == SPECIAL_LJ_3) {
force->special_lj[3] = read_double();
} else if (flag == SPECIAL_COUL_1) {
force->special_coul[1] = read_double();
} else if (flag == SPECIAL_COUL_2) {
force->special_coul[2] = read_double();
} else if (flag == SPECIAL_COUL_3) {
force->special_coul[3] = read_double();
} else if (flag == XY) { } else if (flag == XY) {
domain->triclinic = 1;
domain->xy = read_double(); domain->xy = read_double();
} else if (flag == XZ) { } else if (flag == XZ) {
domain->triclinic = 1;
domain->xz = read_double(); domain->xz = read_double();
} else if (flag == YZ) { } else if (flag == YZ) {
domain->triclinic = 1;
domain->yz = read_double(); domain->yz = read_double();
} else if (flag == SPECIAL_LJ) {
read_int();
read_double_vec(3,&force->special_lj[1]);
} else if (flag == SPECIAL_COUL) {
read_int();
read_double_vec(3,&force->special_coul[1]);
} else error->all(FLERR,"Invalid flag in header section of restart file"); } else error->all(FLERR,"Invalid flag in header section of restart file");
flag = read_int(); flag = read_int();
@ -712,9 +824,9 @@ void ReadRestart::type_arrays()
while (flag >= 0) { while (flag >= 0) {
if (flag == MASS) { if (flag == MASS) {
read_int();
double *mass = new double[atom->ntypes+1]; double *mass = new double[atom->ntypes+1];
if (me == 0) nread_double(&mass[1],atom->ntypes,fp); read_double_vec(atom->ntypes,&mass[1]);
MPI_Bcast(&mass[1],atom->ntypes,MPI_DOUBLE,0,world);
atom->set_mass(mass); atom->set_mass(mass);
delete [] mass; delete [] mass;
@ -736,55 +848,31 @@ void ReadRestart::force_fields()
while (flag >= 0) { while (flag >= 0) {
if (flag == PAIR) { if (flag == PAIR) {
n = read_int(); style = read_string();
style = new char[n];
if (me == 0) nread_char(style,n,fp);
MPI_Bcast(style,n,MPI_CHAR,0,world);
force->create_pair(style); force->create_pair(style);
delete [] style; delete [] style;
if (force->pair->restartinfo) force->pair->read_restart(fp); force->pair->read_restart(fp);
else {
delete force->pair;
force->pair = NULL;
}
} else if (flag == BOND) { } else if (flag == BOND) {
n = read_int(); style = read_string();
style = new char[n];
if (me == 0) nread_char(style,n,fp);
MPI_Bcast(style,n,MPI_CHAR,0,world);
force->create_bond(style); force->create_bond(style);
delete [] style; delete [] style;
force->bond->read_restart(fp); force->bond->read_restart(fp);
} else if (flag == ANGLE) { } else if (flag == ANGLE) {
n = read_int(); style = read_string();
style = new char[n];
if (me == 0) nread_char(style,n,fp);
MPI_Bcast(style,n,MPI_CHAR,0,world);
force->create_angle(style); force->create_angle(style);
delete [] style; delete [] style;
force->angle->read_restart(fp); force->angle->read_restart(fp);
} else if (flag == DIHEDRAL) { } else if (flag == DIHEDRAL) {
n = read_int(); style = read_string();
style = new char[n];
if (me == 0) nread_char(style,n,fp);
MPI_Bcast(style,n,MPI_CHAR,0,world);
force->create_dihedral(style); force->create_dihedral(style);
delete [] style; delete [] style;
force->dihedral->read_restart(fp); force->dihedral->read_restart(fp);
} else if (flag == IMPROPER) { } else if (flag == IMPROPER) {
n = read_int(); style = read_string();
style = new char[n];
if (me == 0) nread_char(style,n,fp);
MPI_Bcast(style,n,MPI_CHAR,0,world);
force->create_improper(style); force->create_improper(style);
delete [] style; delete [] style;
force->improper->read_restart(fp); force->improper->read_restart(fp);
@ -796,36 +884,81 @@ void ReadRestart::force_fields()
} }
} }
/* ---------------------------------------------------------------------- */
void ReadRestart::file_layout()
{
int flag = read_int();
while (flag >= 0) {
if (flag == MULTIPROC) {
multiproc_file = read_int();
if (multiproc == 0 && multiproc_file)
error->all(FLERR,"Restart file is not a multi-proc file");
if (multiproc && multiproc_file == 0)
error->all(FLERR,"Restart file is a multi-proc file");
} else if (flag = MPIIO) {
int mpiio_file = read_int();
if (mpiio == 0 && mpiio_file)
error->all(FLERR,"Restart file is a MPI-IO file");
if (mpiio && mpiio_file == 0)
error->all(FLERR,"Restart file is not a MPI-IO file");
}
flag = read_int();
}
}
// ----------------------------------------------------------------------
// ----------------------------------------------------------------------
// low-level fread methods
// ----------------------------------------------------------------------
// ----------------------------------------------------------------------
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
read N ints from restart file
do not bcast them, caller does that if required
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
void ReadRestart::nread_int(int *buf, int n, FILE *fp) void ReadRestart::magic_string()
{ {
fread(buf,sizeof(int),n,fp); int n = strlen(MAGIC_STRING) + 1;
if (swapflag) {} char *str = new char[n];
int count;
if (me == 0) count = fread(str,sizeof(char),n,fp);
MPI_Bcast(&count,1,MPI_INT,0,world);
if (count < n)
error->all(FLERR,"Invalid LAMMPS restart file");
MPI_Bcast(str,n,MPI_CHAR,0,world);
if (strcmp(str,MAGIC_STRING) != 0)
error->all(FLERR,"Invalid LAMMPS restart file");
delete [] str;
} }
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
read N doubles from restart file
do not bcast them, caller does that if required
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
void ReadRestart::nread_double(double *buf, int n, FILE *fp) void ReadRestart::endian()
{ {
fread(buf,sizeof(double),n,fp); int endian;
if (swapflag) {} if (me == 0) fread(&endian,sizeof(int),1,fp);
MPI_Bcast(&endian,1,MPI_INT,0,world);
if (endian == ENDIAN) return;
if (endian == ENDIANSWAP)
error->all(FLERR,"Restart file byte ordering is swapped");
else error->all(FLERR,"Restart file byte ordering is not recognized");
} }
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
read N chars from restart file
do not bcast them, caller does that if required
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
void ReadRestart::nread_char(char *buf, int n, FILE *fp) int ReadRestart::version_numeric()
{ {
fread(buf,sizeof(char),n,fp); int vn;
if (me == 0) fread(&vn,sizeof(int),1,fp);
MPI_Bcast(&vn,1,MPI_INT,0,world);
if (vn < VERSION_NUMERIC) return 1;
return 0;
} }
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
@ -835,51 +968,11 @@ void ReadRestart::nread_char(char *buf, int n, FILE *fp)
int ReadRestart::read_int() int ReadRestart::read_int()
{ {
int value; int value;
if (me == 0) { if (me == 0) fread(&value,sizeof(int),1,fp);
fread(&value,sizeof(int),1,fp);
if (swapflag) {}
}
MPI_Bcast(&value,1,MPI_INT,0,world); MPI_Bcast(&value,1,MPI_INT,0,world);
return value; return value;
} }
/* ----------------------------------------------------------------------
read a double from restart file and bcast it
------------------------------------------------------------------------- */
double ReadRestart::read_double()
{
double value;
if (me == 0) {
fread(&value,sizeof(double),1,fp);
if (swapflag) {}
}
MPI_Bcast(&value,1,MPI_DOUBLE,0,world);
return value;
}
/* ----------------------------------------------------------------------
read a char str from restart file and bcast it
str is allocated here, ptr is returned, caller must deallocate
------------------------------------------------------------------------- */
char *ReadRestart::read_char()
{
int n;
if (me == 0) {
fread(&n,sizeof(int),1,fp);
if (swapflag) {}
}
MPI_Bcast(&n,1,MPI_INT,0,world);
char *value = new char[n];
if (me == 0) {
fread(value,sizeof(char),n,fp);
if (swapflag) {}
}
MPI_Bcast(value,n,MPI_CHAR,0,world);
return value;
}
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
read a bigint from restart file and bcast it read a bigint from restart file and bcast it
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
@ -887,35 +980,57 @@ char *ReadRestart::read_char()
bigint ReadRestart::read_bigint() bigint ReadRestart::read_bigint()
{ {
bigint value; bigint value;
if (me == 0) { if (me == 0) fread(&value,sizeof(bigint),1,fp);
fread(&value,sizeof(bigint),1,fp);
if (swapflag) {}
}
MPI_Bcast(&value,1,MPI_LMP_BIGINT,0,world); MPI_Bcast(&value,1,MPI_LMP_BIGINT,0,world);
return value; return value;
} }
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
auto-detect if restart file needs to be byte-swapped on this platform read a double from restart file and bcast it
return 0 if not, 1 if it does
re-open file with fp after checking first few bytes
read a bigint from restart file and bcast it
NOTE: not yet fully implemented, ditto for swapflag logic
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
int ReadRestart::autodetect(FILE **pfp, char *file) double ReadRestart::read_double()
{ {
FILE *fp = *pfp; double value;
if (me == 0) fread(&value,sizeof(double),1,fp);
// read, check, set return flag MPI_Bcast(&value,1,MPI_DOUBLE,0,world);
return value;
int flag = 0; }
// reset file pointer /* ----------------------------------------------------------------------
read a char string (including NULL) and bcast it
fclose(fp); str is allocated here, ptr is returned, caller must deallocate
fp = fopen(file,"rb"); ------------------------------------------------------------------------- */
*pfp = fp;
char *ReadRestart::read_string()
return flag; {
int n;
if (me == 0) fread(&n,sizeof(int),1,fp);
MPI_Bcast(&n,1,MPI_INT,0,world);
char *value = new char[n];
if (me == 0) fread(value,sizeof(char),n,fp);
MPI_Bcast(value,n,MPI_CHAR,0,world);
return value;
}
/* ----------------------------------------------------------------------
read vector of N ints from restart file and bcast them
do not bcast them, caller does that if required
------------------------------------------------------------------------- */
void ReadRestart::read_int_vec(int n, int *vec)
{
if (me == 0) fread(vec,sizeof(int),n,fp);
MPI_Bcast(vec,n,MPI_INT,0,world);
}
/* ----------------------------------------------------------------------
read vector of N doubles from restart file and bcast them
do not bcast them, caller does that if required
------------------------------------------------------------------------- */
void ReadRestart::read_double_vec(int n, double *vec)
{
if (me == 0) fread(vec,sizeof(double),n,fp);
MPI_Bcast(vec,n,MPI_DOUBLE,0,world);
} }

View File

@ -31,24 +31,30 @@ class ReadRestart : protected Pointers {
void command(int, char **); void command(int, char **);
private: private:
int me,nprocs,nprocs_file; int me,nprocs,nprocs_file,multiproc_file;
FILE *fp; FILE *fp;
int nfix_restart_global,nfix_restart_peratom; int nfix_restart_global,nfix_restart_peratom;
int swapflag;
int mpiio; // 1 for MPIIO output, else 0
int multiproc; // 0 = proc 0 writes for all
// else # of procs writing files
void file_search(char *, char *); void file_search(char *, char *);
void header(); void header(int);
void type_arrays(); void type_arrays();
void force_fields(); void force_fields();
void nread_int(int *, int, FILE *); void magic_string();
void nread_double(double *, int, FILE *); void endian();
void nread_char(char *, int, FILE *); int version_numeric();
void file_layout();
int read_int(); int read_int();
double read_double();
char *read_char();
bigint read_bigint(); bigint read_bigint();
int autodetect(FILE **, char *); double read_double();
char *read_string();
void read_int_vec(int, int *);
void read_double_vec(int, double *);
}; };
} }

View File

@ -39,23 +39,26 @@
using namespace LAMMPS_NS; using namespace LAMMPS_NS;
// same as read_restart.cpp and tools/restart2data.cpp // same as read_restart.cpp
#define MAGIC_STRING "LammpS RestartT"
#define ENDIAN 0x0001
#define ENDIANSWAP 0x1000
#define VERSION_NUMERIC 0
enum{VERSION,SMALLINT,TAGINT,BIGINT, enum{VERSION,SMALLINT,TAGINT,BIGINT,
UNITS,NTIMESTEP,DIMENSION,NPROCS,PROCGRID_0,PROCGRID_1,PROCGRID_2, UNITS,NTIMESTEP,DIMENSION,NPROCS,PROCGRID,
NEWTON_PAIR,NEWTON_BOND,XPERIODIC,YPERIODIC,ZPERIODIC, NEWTON_PAIR,NEWTON_BOND,
BOUNDARY_00,BOUNDARY_01,BOUNDARY_10,BOUNDARY_11,BOUNDARY_20,BOUNDARY_21, XPERIODIC,YPERIODIC,ZPERIODIC,BOUNDARY,
ATOM_STYLE,NATOMS,NTYPES, ATOM_STYLE,NATOMS,NTYPES,
NBONDS,NBONDTYPES,BOND_PER_ATOM, NBONDS,NBONDTYPES,BOND_PER_ATOM,
NANGLES,NANGLETYPES,ANGLE_PER_ATOM, NANGLES,NANGLETYPES,ANGLE_PER_ATOM,
NDIHEDRALS,NDIHEDRALTYPES,DIHEDRAL_PER_ATOM, NDIHEDRALS,NDIHEDRALTYPES,DIHEDRAL_PER_ATOM,
NIMPROPERS,NIMPROPERTYPES,IMPROPER_PER_ATOM, NIMPROPERS,NIMPROPERTYPES,IMPROPER_PER_ATOM,
BOXLO_0,BOXHI_0,BOXLO_1,BOXHI_1,BOXLO_2,BOXHI_2, TRICLINIC,BOXLO,BOXHI,XY,XZ,YZ,
SPECIAL_LJ_1,SPECIAL_LJ_2,SPECIAL_LJ_3, SPECIAL_LJ,SPECIAL_COUL,
SPECIAL_COUL_1,SPECIAL_COUL_2,SPECIAL_COUL_3, MASS,PAIR,BOND,ANGLE,DIHEDRAL,IMPROPER,
XY,XZ,YZ}; MULTIPROC,MPIIO,PROCSPERFILE,PERPROC};
enum{MASS};
enum{PAIR,BOND,ANGLE,DIHEDRAL,IMPROPER};
enum{IGNORE,WARN,ERROR}; // same as thermo.cpp enum{IGNORE,WARN,ERROR}; // same as thermo.cpp
@ -65,6 +68,7 @@ WriteRestart::WriteRestart(LAMMPS *lmp) : Pointers(lmp)
{ {
MPI_Comm_rank(world,&me); MPI_Comm_rank(world,&me);
MPI_Comm_size(world,&nprocs); MPI_Comm_size(world,&nprocs);
multiproc = 0;
} }
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
@ -75,7 +79,7 @@ void WriteRestart::command(int narg, char **arg)
{ {
if (domain->box_exist == 0) if (domain->box_exist == 0)
error->all(FLERR,"Write_restart command before simulation box is defined"); error->all(FLERR,"Write_restart command before simulation box is defined");
if (narg != 1) error->all(FLERR,"Illegal write_restart command"); if (narg < 1) error->all(FLERR,"Illegal write_restart command");
// if filename contains a "*", replace with current timestep // if filename contains a "*", replace with current timestep
@ -88,6 +92,21 @@ void WriteRestart::command(int narg, char **arg)
sprintf(file,"%s" BIGINT_FORMAT "%s",arg[0],update->ntimestep,ptr+1); sprintf(file,"%s" BIGINT_FORMAT "%s",arg[0],update->ntimestep,ptr+1);
} else strcpy(file,arg[0]); } else strcpy(file,arg[0]);
// check for multiproc output and an MPI-IO filename
if (strchr(arg[0],'%')) multiproc = nprocs;
else multiproc = 0;
if (strstr(arg[0],".mpi")) mpiio = 1;
else mpiio = 0;
if (multiproc && mpiio)
error->all(FLERR,
"Write restart MPI-IO output not allowed with '%' in filename");
// setup output style and process optional args
// also called by Output class for periodic restart files
multiproc_options(multiproc,mpiio,narg-1,&arg[1]);
// init entire system since comm->exchange is done // init entire system since comm->exchange is done
// comm::init needs neighbor::init needs pair::init needs kspace::init, etc // comm::init needs neighbor::init needs pair::init needs kspace::init, etc
@ -114,6 +133,78 @@ void WriteRestart::command(int narg, char **arg)
delete [] file; delete [] file;
} }
/* ----------------------------------------------------------------------
------------------------------------------------------------------------- */
void WriteRestart::multiproc_options(int multiproc_caller, int mpiio_caller,
int narg, char **arg)
{
multiproc = multiproc_caller;
mpiio = mpiio_caller;
// defaults for multiproc file writing
nclusterprocs = nprocs;
filewriter = 0;
if (me == 0) filewriter = 1;
fileproc = 0;
if (multiproc) {
nclusterprocs = 1;
filewriter = 1;
fileproc = me;
icluster = me;
}
// optional args
int iarg = 0;
while (iarg < narg) {
if (strcmp(arg[iarg],"fileper") == 0) {
if (iarg+2 > narg) error->all(FLERR,"Illegal write_restart command");
if (!multiproc)
error->all(FLERR,"Cannot use write_restart fileper "
"without % in restart file name");
int nper = force->inumeric(FLERR,arg[iarg+1]);
if (nper <= 0) error->all(FLERR,"Illegal write_restart command");
multiproc = nprocs/nper;
if (nprocs % nper) multiproc++;
fileproc = me/nper * nper;
int fileprocnext = MIN(fileproc+nper,nprocs);
nclusterprocs = fileprocnext - fileproc;
if (me == fileproc) filewriter = 1;
else filewriter = 0;
icluster = fileproc/nper;
iarg += 2;
} else if (strcmp(arg[iarg],"nfile") == 0) {
if (iarg+2 > narg) error->all(FLERR,"Illegal write_restart command");
if (!multiproc)
error->all(FLERR,"Cannot use write_restart nfile "
"without % in restart file name");
int nfile = force->inumeric(FLERR,arg[iarg+1]);
if (nfile <= 0) error->all(FLERR,"Illegal write_restart command");
nfile = MIN(nfile,nprocs);
multiproc = nfile;
icluster = static_cast<int> ((bigint) me * nfile/nprocs);
fileproc = static_cast<int> ((bigint) icluster * nprocs/nfile);
int fcluster = static_cast<int> ((bigint) fileproc * nfile/nprocs);
if (fcluster < icluster) fileproc++;
int fileprocnext =
static_cast<int> ((bigint) (icluster+1) * nprocs/nfile);
fcluster = static_cast<int> ((bigint) fileprocnext * nfile/nprocs);
if (fcluster < icluster+1) fileprocnext++;
nclusterprocs = fileprocnext - fileproc;
if (me == fileproc) filewriter = 1;
else filewriter = 0;
iarg += 2;
} else error->all(FLERR,"Illegal write_restart command");
}
}
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
called from command() and directly from output within run/minimize loop called from command() and directly from output within run/minimize loop
file = final file name to write, except may contain a "%" file = final file name to write, except may contain a "%"
@ -138,12 +229,6 @@ void WriteRestart::write(char *file)
if (natoms != atom->natoms && output->thermo->lostflag == ERROR) if (natoms != atom->natoms && output->thermo->lostflag == ERROR)
error->all(FLERR,"Atom count is inconsistent, cannot write restart file"); error->all(FLERR,"Atom count is inconsistent, cannot write restart file");
// check if filename contains "%"
int multiproc;
if (strchr(file,'%')) multiproc = 1;
else multiproc = 0;
// open single restart file or base file for multiproc case // open single restart file or base file for multiproc case
if (me == 0) { if (me == 0) {
@ -164,8 +249,15 @@ void WriteRestart::write(char *file)
if (multiproc) delete [] hfile; if (multiproc) delete [] hfile;
} }
// proc 0 writes header, groups, ntype-length arrays, force field // proc 0 writes magic string, endian flag, numeric version
// all procs write fix info
if (me == 0) {
magic_string();
endian();
version_numeric();
}
// proc 0 writes header, groups, pertype info, force field info
if (me == 0) { if (me == 0) {
header(); header();
@ -174,9 +266,11 @@ void WriteRestart::write(char *file)
force_fields(); force_fields();
} }
// all procs write fix info
modify->write_restart(fp); modify->write_restart(fp);
// communication buffer for all my atom's info // communication buffer for my atom info
// max_size = largest buffer needed by any proc // max_size = largest buffer needed by any proc
int max_size; int max_size;
@ -184,8 +278,35 @@ void WriteRestart::write(char *file)
MPI_Allreduce(&send_size,&max_size,1,MPI_INT,MPI_MAX,world); MPI_Allreduce(&send_size,&max_size,1,MPI_INT,MPI_MAX,world);
double *buf; double *buf;
if (me == 0) memory->create(buf,max_size,"write_restart:buf"); memory->create(buf,max_size,"write_restart:buf");
else memory->create(buf,send_size,"write_restart:buf");
// all procs write file layout info which may include per-proc sizes
file_layout(send_size);
// header info is complete
// if multiproc output:
// close header file, open multiname file on each writing proc
if (multiproc) {
if (me == 0) fclose(fp);
char *multiname = new char[strlen(file) + 16];
char *ptr = strchr(file,'%');
*ptr = '\0';
sprintf(multiname,"%s%d%s",file,icluster,ptr+1);
if (filewriter) {
fp = fopen(multiname,"wb");
if (fp == NULL) {
char str[128];
sprintf(str,"Cannot open restart file %s",multiname);
error->one(FLERR,str);
}
}
delete [] multiname;
}
// pack my atom data into buf // pack my atom data into buf
@ -242,55 +363,31 @@ void WriteRestart::write(char *file)
} }
} }
// if single file: // filewriter = 1 = this proc writes to file
// write one chunk of atoms per proc to file // ping each proc in my cluster, receive its data, write data to file
// proc 0 pings each proc, receives its chunk, writes to file // else wait for ping from fileproc, send my data to fileproc
// all other procs wait for ping, send their chunk to proc 0
// else if one file per proc:
// each proc opens its own file and writes its chunk directly
if (multiproc == 0) { int tmp,recv_size;
int tmp,recv_size; MPI_Status status;
MPI_Status status; MPI_Request request;
MPI_Request request;
if (me == 0) { if (filewriter) {
for (int iproc = 0; iproc < nprocs; iproc++) { write_int(PROCSPERFILE,nclusterprocs);
if (iproc) { for (int iproc = 0; iproc < nclusterprocs; iproc++) {
MPI_Irecv(buf,max_size,MPI_DOUBLE,iproc,0,world,&request); if (iproc) {
MPI_Send(&tmp,0,MPI_INT,iproc,0,world); MPI_Irecv(buf,max_size,MPI_DOUBLE,me+iproc,0,world,&request);
MPI_Wait(&request,&status); MPI_Send(&tmp,0,MPI_INT,me+iproc,0,world);
MPI_Get_count(&status,MPI_DOUBLE,&recv_size); MPI_Wait(&request,&status);
} else recv_size = send_size; MPI_Get_count(&status,MPI_DOUBLE,&recv_size);
} else recv_size = send_size;
fwrite(&recv_size,sizeof(int),1,fp); write_double_vec(PERPROC,recv_size,buf);
fwrite(buf,sizeof(double),recv_size,fp);
}
fclose(fp);
} else {
MPI_Recv(&tmp,0,MPI_INT,0,0,world,&status);
MPI_Rsend(buf,send_size,MPI_DOUBLE,0,0,world);
} }
fclose(fp);
} else { } else {
if (me == 0) fclose(fp); MPI_Recv(&tmp,0,MPI_INT,fileproc,0,world,&status);
MPI_Rsend(buf,send_size,MPI_DOUBLE,fileproc,0,world);
char *perproc = new char[strlen(file) + 16];
char *ptr = strchr(file,'%');
*ptr = '\0';
sprintf(perproc,"%s%d%s",file,me,ptr+1);
*ptr = '%';
fp = fopen(perproc,"wb");
if (fp == NULL) {
char str[128];
sprintf(str,"Cannot open restart file %s",perproc);
error->one(FLERR,str);
}
delete [] perproc;
fwrite(&send_size,sizeof(int),1,fp);
fwrite(buf,sizeof(double),send_size,fp);
fclose(fp);
} }
memory->destroy(buf); memory->destroy(buf);
@ -308,35 +405,28 @@ void WriteRestart::write(char *file)
void WriteRestart::header() void WriteRestart::header()
{ {
write_char(VERSION,universe->version); write_string(VERSION,universe->version);
write_int(SMALLINT,sizeof(smallint)); write_int(SMALLINT,sizeof(smallint));
write_int(TAGINT,sizeof(tagint)); write_int(TAGINT,sizeof(tagint));
write_int(BIGINT,sizeof(bigint)); write_int(BIGINT,sizeof(bigint));
write_char(UNITS,update->unit_style); write_string(UNITS,update->unit_style);
write_bigint(NTIMESTEP,update->ntimestep); write_bigint(NTIMESTEP,update->ntimestep);
write_int(DIMENSION,domain->dimension); write_int(DIMENSION,domain->dimension);
write_int(NPROCS,nprocs); write_int(NPROCS,nprocs);
write_int(PROCGRID_0,comm->procgrid[0]); write_int_vec(PROCGRID,3,comm->procgrid);
write_int(PROCGRID_1,comm->procgrid[1]);
write_int(PROCGRID_2,comm->procgrid[2]);
write_int(NEWTON_PAIR,force->newton_pair); write_int(NEWTON_PAIR,force->newton_pair);
write_int(NEWTON_BOND,force->newton_bond); write_int(NEWTON_BOND,force->newton_bond);
write_int(XPERIODIC,domain->xperiodic); write_int(XPERIODIC,domain->xperiodic);
write_int(YPERIODIC,domain->yperiodic); write_int(YPERIODIC,domain->yperiodic);
write_int(ZPERIODIC,domain->zperiodic); write_int(ZPERIODIC,domain->zperiodic);
write_int(BOUNDARY_00,domain->boundary[0][0]); write_int_vec(BOUNDARY,6,&domain->boundary[0][0]);
write_int(BOUNDARY_01,domain->boundary[0][1]);
write_int(BOUNDARY_10,domain->boundary[1][0]);
write_int(BOUNDARY_11,domain->boundary[1][1]);
write_int(BOUNDARY_20,domain->boundary[2][0]);
write_int(BOUNDARY_21,domain->boundary[2][1]);
// atom_style must be written before atom class values // atom_style must be written before atom class values
// so read_restart can create class before reading class values // so read_restart can create class before reading class values
// if style = hybrid, also write sub-class styles // if style = hybrid, also write sub-class styles
// avec->write_restart() writes atom_style specific info // avec->write_restart() writes atom_style specific info
write_char(ATOM_STYLE,atom->atom_style); write_string(ATOM_STYLE,atom->atom_style);
if (strcmp(atom->atom_style,"hybrid") == 0) { if (strcmp(atom->atom_style,"hybrid") == 0) {
AtomVecHybrid *avec_hybrid = (AtomVecHybrid *) atom->avec; AtomVecHybrid *avec_hybrid = (AtomVecHybrid *) atom->avec;
@ -349,8 +439,7 @@ void WriteRestart::header()
fwrite(keywords[i],sizeof(char),n,fp); fwrite(keywords[i],sizeof(char),n,fp);
} }
} }
atom->avec->write_restart_settings(fp);
if (me == 0) atom->avec->write_restart_settings(fp);
write_bigint(NATOMS,natoms); write_bigint(NATOMS,natoms);
write_int(NTYPES,atom->ntypes); write_int(NTYPES,atom->ntypes);
@ -367,25 +456,15 @@ void WriteRestart::header()
write_int(NIMPROPERTYPES,atom->nimpropertypes); write_int(NIMPROPERTYPES,atom->nimpropertypes);
write_int(IMPROPER_PER_ATOM,atom->improper_per_atom); write_int(IMPROPER_PER_ATOM,atom->improper_per_atom);
write_double(BOXLO_0,domain->boxlo[0]); write_int(TRICLINIC,domain->triclinic);
write_double(BOXHI_0,domain->boxhi[0]); write_double_vec(BOXLO,3,domain->boxlo);
write_double(BOXLO_1,domain->boxlo[1]); write_double_vec(BOXHI,3,domain->boxhi);
write_double(BOXHI_1,domain->boxhi[1]); write_double(XY,domain->xy);
write_double(BOXLO_2,domain->boxlo[2]); write_double(XZ,domain->xz);
write_double(BOXHI_2,domain->boxhi[2]); write_double(YZ,domain->yz);
write_double(SPECIAL_LJ_1,force->special_lj[1]); write_double_vec(SPECIAL_LJ,3,&force->special_lj[1]);
write_double(SPECIAL_LJ_2,force->special_lj[2]); write_double_vec(SPECIAL_COUL,3,&force->special_coul[1]);
write_double(SPECIAL_LJ_3,force->special_lj[3]);
write_double(SPECIAL_COUL_1,force->special_coul[1]);
write_double(SPECIAL_COUL_2,force->special_coul[2]);
write_double(SPECIAL_COUL_3,force->special_coul[3]);
if (domain->triclinic) {
write_double(XY,domain->xy);
write_double(XZ,domain->xz);
write_double(YZ,domain->yz);
}
// -1 flag signals end of header // -1 flag signals end of header
@ -399,11 +478,7 @@ void WriteRestart::header()
void WriteRestart::type_arrays() void WriteRestart::type_arrays()
{ {
if (atom->mass) { if (atom->mass) write_double_vec(MASS,atom->ntypes,&atom->mass[1]);
int flag = MASS;
fwrite(&flag,sizeof(int),1,fp);
fwrite(&atom->mass[1],sizeof(double),atom->ntypes,fp);
}
// -1 flag signals end of type arrays // -1 flag signals end of type arrays
@ -417,44 +492,24 @@ void WriteRestart::type_arrays()
void WriteRestart::force_fields() void WriteRestart::force_fields()
{ {
if (force->pair) { if (force->pair && force->pair->restartinfo) {
int flag = PAIR; write_string(PAIR,force->pair_style);
fwrite(&flag,sizeof(int),1,fp);
int n = strlen(force->pair_style) + 1;
fwrite(&n,sizeof(int),1,fp);
fwrite(force->pair_style,sizeof(char),n,fp);
force->pair->write_restart(fp); force->pair->write_restart(fp);
} }
if (atom->avec->bonds_allow && force->bond) { if (atom->avec->bonds_allow && force->bond) {
int flag = BOND; write_string(BOND,force->bond_style);
fwrite(&flag,sizeof(int),1,fp);
int n = strlen(force->bond_style) + 1;
fwrite(&n,sizeof(int),1,fp);
fwrite(force->bond_style,sizeof(char),n,fp);
force->bond->write_restart(fp); force->bond->write_restart(fp);
} }
if (atom->avec->angles_allow && force->angle) { if (atom->avec->angles_allow && force->angle) {
int flag = ANGLE; write_string(ANGLE,force->angle_style);
fwrite(&flag,sizeof(int),1,fp);
int n = strlen(force->angle_style) + 1;
fwrite(&n,sizeof(int),1,fp);
fwrite(force->angle_style,sizeof(char),n,fp);
force->angle->write_restart(fp); force->angle->write_restart(fp);
} }
if (atom->avec->dihedrals_allow && force->dihedral) { if (atom->avec->dihedrals_allow && force->dihedral) {
int flag = DIHEDRAL; write_string(DIHEDRAL,force->dihedral_style);
fwrite(&flag,sizeof(int),1,fp);
int n = strlen(force->dihedral_style) + 1;
fwrite(&n,sizeof(int),1,fp);
fwrite(force->dihedral_style,sizeof(char),n,fp);
force->dihedral->write_restart(fp); force->dihedral->write_restart(fp);
} }
if (atom->avec->impropers_allow && force->improper) { if (atom->avec->impropers_allow && force->improper) {
int flag = IMPROPER; write_string(IMPROPER,force->improper_style);
fwrite(&flag,sizeof(int),1,fp);
int n = strlen(force->improper_style) + 1;
fwrite(&n,sizeof(int),1,fp);
fwrite(force->improper_style,sizeof(char),n,fp);
force->improper->write_restart(fp); force->improper->write_restart(fp);
} }
@ -464,6 +519,62 @@ void WriteRestart::force_fields()
fwrite(&flag,sizeof(int),1,fp); fwrite(&flag,sizeof(int),1,fp);
} }
/* ----------------------------------------------------------------------
proc 0 writes out file layout info
all procs call this method, only proc 0 writes to file
------------------------------------------------------------------------- */
void WriteRestart::file_layout(int send_size)
{
if (me == 0) {
write_int(MULTIPROC,multiproc);
write_int(MPIIO,mpiio);
}
// -1 flag signals end of file layout info
if (me == 0) {
int flag = -1;
fwrite(&flag,sizeof(int),1,fp);
}
}
// ----------------------------------------------------------------------
// ----------------------------------------------------------------------
// low-level fwrite methods
// ----------------------------------------------------------------------
// ----------------------------------------------------------------------
/* ----------------------------------------------------------------------
------------------------------------------------------------------------- */
void WriteRestart::magic_string()
{
int n = strlen(MAGIC_STRING) + 1;
char *str = new char[n];
strcpy(str,MAGIC_STRING);
fwrite(str,sizeof(char),n,fp);
delete [] str;
}
/* ----------------------------------------------------------------------
------------------------------------------------------------------------- */
void WriteRestart::endian()
{
int endian = ENDIAN;
fwrite(&endian,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
------------------------------------------------------------------------- */
void WriteRestart::version_numeric()
{
int vn = VERSION_NUMERIC;
fwrite(&vn,sizeof(int),1,fp);
}
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
write a flag and an int into restart file write a flag and an int into restart file
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
@ -474,6 +585,16 @@ void WriteRestart::write_int(int flag, int value)
fwrite(&value,sizeof(int),1,fp); fwrite(&value,sizeof(int),1,fp);
} }
/* ----------------------------------------------------------------------
write a flag and a bigint into restart file
------------------------------------------------------------------------- */
void WriteRestart::write_bigint(int flag, bigint value)
{
fwrite(&flag,sizeof(int),1,fp);
fwrite(&value,sizeof(bigint),1,fp);
}
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
write a flag and a double into restart file write a flag and a double into restart file
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
@ -485,23 +606,35 @@ void WriteRestart::write_double(int flag, double value)
} }
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
write a flag and a char str into restart file write a flag and a char string (including NULL) into restart file
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
void WriteRestart::write_char(int flag, char *value) void WriteRestart::write_string(int flag, char *value)
{ {
fwrite(&flag,sizeof(int),1,fp);
int n = strlen(value) + 1; int n = strlen(value) + 1;
fwrite(&flag,sizeof(int),1,fp);
fwrite(&n,sizeof(int),1,fp); fwrite(&n,sizeof(int),1,fp);
fwrite(value,sizeof(char),n,fp); fwrite(value,sizeof(char),n,fp);
} }
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
write a flag and a bigint into restart file write a flag and vector of N ints into restart file
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
void WriteRestart::write_bigint(int flag, bigint value) void WriteRestart::write_int_vec(int flag, int n, int *vec)
{ {
fwrite(&flag,sizeof(int),1,fp); fwrite(&flag,sizeof(int),1,fp);
fwrite(&value,sizeof(bigint),1,fp); fwrite(&n,sizeof(int),1,fp);
fwrite(vec,sizeof(int),n,fp);
}
/* ----------------------------------------------------------------------
write a flag and vector of N doubles into restart file
------------------------------------------------------------------------- */
void WriteRestart::write_double_vec(int flag, int n, double *vec)
{
fwrite(&flag,sizeof(int),1,fp);
fwrite(&n,sizeof(int),1,fp);
fwrite(vec,sizeof(double),n,fp);
} }

View File

@ -29,6 +29,7 @@ class WriteRestart : protected Pointers {
public: public:
WriteRestart(class LAMMPS *); WriteRestart(class LAMMPS *);
void command(int, char **); void command(int, char **);
void multiproc_options(int, int, int, char **);
void write(char *); void write(char *);
private: private:
@ -36,14 +37,29 @@ class WriteRestart : protected Pointers {
FILE *fp; FILE *fp;
bigint natoms; // natoms (sum of nlocal) to write into file bigint natoms; // natoms (sum of nlocal) to write into file
int mpiio; // 1 for MPIIO output, else 0
int multiproc; // 0 = proc 0 writes for all
// else # of procs writing files
int nclusterprocs; // # of procs in my cluster that write to one file
int filewriter; // 1 if this proc writes a file, else 0
int fileproc; // ID of proc in my cluster who writes to file
int icluster; // which cluster I am in
void header(); void header();
void type_arrays(); void type_arrays();
void force_fields(); void force_fields();
void file_layout(int);
void magic_string();
void endian();
void version_numeric();
void write_int(int, int); void write_int(int, int);
void write_double(int, double);
void write_char(int, char *);
void write_bigint(int, bigint); void write_bigint(int, bigint);
void write_double(int, double);
void write_string(int, char *);
void write_int_vec(int, int, int *);
void write_double_vec(int, int, double *);
}; };
} }