git-svn-id: svn://svn.icms.temple.edu/lammps-ro/trunk@11095 f3b2605a-c512-4ea7-a41b-209d697bcdaa
This commit is contained in:
@ -57,12 +57,12 @@ class Dump : protected Pointers {
|
||||
int binary; // 1 if dump file is written binary, 0 no
|
||||
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
|
||||
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
|
||||
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
|
||||
|
||||
int header_flag; // 0 = item, 2 = xyz
|
||||
|
||||
@ -706,9 +706,13 @@ void Output::create_restart(int narg, char **arg)
|
||||
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;
|
||||
|
||||
if (varflag) {
|
||||
@ -725,7 +729,7 @@ void Output::create_restart(int narg, char **arg)
|
||||
if (strchr(restart1,'*') == NULL) strcat(restart1,".*");
|
||||
}
|
||||
|
||||
if (narg == 3) {
|
||||
if (nfile == 2) {
|
||||
restart_flag = restart_flag_double = 1;
|
||||
|
||||
if (varflag) {
|
||||
@ -745,7 +749,35 @@ void Output::create_restart(int narg, char **arg)
|
||||
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]);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
|
||||
@ -15,7 +15,6 @@
|
||||
#include "mpi.h"
|
||||
#include "string.h"
|
||||
#include "stdlib.h"
|
||||
//#include "sys/types.h"
|
||||
#include "dirent.h"
|
||||
#include "read_restart.h"
|
||||
#include "atom.h"
|
||||
@ -43,21 +42,24 @@ using namespace LAMMPS_NS;
|
||||
|
||||
// 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,
|
||||
UNITS,NTIMESTEP,DIMENSION,NPROCS,PROCGRID_0,PROCGRID_1,PROCGRID_2,
|
||||
NEWTON_PAIR,NEWTON_BOND,XPERIODIC,YPERIODIC,ZPERIODIC,
|
||||
BOUNDARY_00,BOUNDARY_01,BOUNDARY_10,BOUNDARY_11,BOUNDARY_20,BOUNDARY_21,
|
||||
UNITS,NTIMESTEP,DIMENSION,NPROCS,PROCGRID,
|
||||
NEWTON_PAIR,NEWTON_BOND,
|
||||
XPERIODIC,YPERIODIC,ZPERIODIC,BOUNDARY,
|
||||
ATOM_STYLE,NATOMS,NTYPES,
|
||||
NBONDS,NBONDTYPES,BOND_PER_ATOM,
|
||||
NANGLES,NANGLETYPES,ANGLE_PER_ATOM,
|
||||
NDIHEDRALS,NDIHEDRALTYPES,DIHEDRAL_PER_ATOM,
|
||||
NIMPROPERS,NIMPROPERTYPES,IMPROPER_PER_ATOM,
|
||||
BOXLO_0,BOXHI_0,BOXLO_1,BOXHI_1,BOXLO_2,BOXHI_2,
|
||||
SPECIAL_LJ_1,SPECIAL_LJ_2,SPECIAL_LJ_3,
|
||||
SPECIAL_COUL_1,SPECIAL_COUL_2,SPECIAL_COUL_3,
|
||||
XY,XZ,YZ};
|
||||
enum{MASS};
|
||||
enum{PAIR,BOND,ANGLE,DIHEDRAL,IMPROPER};
|
||||
TRICLINIC,BOXLO,BOXHI,XY,XZ,YZ,
|
||||
SPECIAL_LJ,SPECIAL_COUL,
|
||||
MASS,PAIR,BOND,ANGLE,DIHEDRAL,IMPROPER,
|
||||
MULTIPROC,MPIIO,PROCSPERFILE,PERPROC};
|
||||
|
||||
#define LB_FACTOR 1.1
|
||||
|
||||
@ -90,14 +92,18 @@ void ReadRestart::command(int narg, char **arg)
|
||||
MPI_Bcast(file,n,MPI_CHAR,0,world);
|
||||
} else strcpy(file,arg[0]);
|
||||
|
||||
// check if filename contains "%"
|
||||
// check for multiproc files and an MPI-IO filename
|
||||
|
||||
int multiproc;
|
||||
if (strchr(file,'%')) multiproc = 1;
|
||||
if (strchr(arg[0],'%')) multiproc = 1;
|
||||
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
|
||||
// auto-detect whether byte swapping needs to be done as file is read
|
||||
|
||||
if (me == 0) {
|
||||
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);
|
||||
error->one(FLERR,str);
|
||||
}
|
||||
swapflag = autodetect(&fp,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;
|
||||
|
||||
// problem setup using info from header
|
||||
@ -153,12 +162,19 @@ void ReadRestart::command(int narg, char **arg)
|
||||
atom->nextra_store = nextra;
|
||||
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:
|
||||
// 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
|
||||
// check for atom in sub-domain differs for orthogonal vs triclinic box
|
||||
// close restart file when done
|
||||
|
||||
AtomVec *avec = atom->avec;
|
||||
|
||||
@ -167,6 +183,7 @@ void ReadRestart::command(int narg, char **arg)
|
||||
int m;
|
||||
|
||||
if (multiproc == 0) {
|
||||
|
||||
int triclinic = domain->triclinic;
|
||||
double *x,lamda[3];
|
||||
double *coord,*sublo,*subhi;
|
||||
@ -179,17 +196,16 @@ void ReadRestart::command(int narg, char **arg)
|
||||
}
|
||||
|
||||
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();
|
||||
if (n > maxbuf) {
|
||||
maxbuf = n;
|
||||
memory->destroy(buf);
|
||||
memory->create(buf,maxbuf,"read_restart:buf");
|
||||
}
|
||||
|
||||
if (n > 0) {
|
||||
if (me == 0) nread_double(buf,n,fp);
|
||||
MPI_Bcast(buf,n,MPI_DOUBLE,0,world);
|
||||
}
|
||||
read_double_vec(n,buf);
|
||||
|
||||
m = 0;
|
||||
while (m < n) {
|
||||
@ -210,42 +226,166 @@ void ReadRestart::command(int narg, char **arg)
|
||||
|
||||
if (me == 0) fclose(fp);
|
||||
|
||||
// one file per proc:
|
||||
// nprocs_file = # of files
|
||||
// each proc reads 1/P fraction of files, keeping all atoms in the files
|
||||
// perform irregular comm to migrate atoms to correct procs
|
||||
// close restart file when done
|
||||
// multiple files with procs <= files
|
||||
// # of files = multiproc_file
|
||||
// each proc reads a subset of files, striding by nprocs
|
||||
// each proc keeps all atoms in all perproc chunks in its files
|
||||
|
||||
} else {
|
||||
if (me == 0) fclose(fp);
|
||||
char *perproc = new char[strlen(file) + 16];
|
||||
} else if (nprocs <= multiproc_file) {
|
||||
|
||||
char *procfile = new char[strlen(file) + 16];
|
||||
char *ptr = strchr(file,'%');
|
||||
|
||||
for (int iproc = me; iproc < nprocs_file; iproc += nprocs) {
|
||||
for (int iproc = me; iproc < multiproc_file; iproc += nprocs) {
|
||||
*ptr = '\0';
|
||||
sprintf(perproc,"%s%d%s",file,iproc,ptr+1);
|
||||
sprintf(procfile,"%s%d%s",file,iproc,ptr+1);
|
||||
*ptr = '%';
|
||||
fp = fopen(perproc,"rb");
|
||||
fp = fopen(procfile,"rb");
|
||||
if (fp == NULL) {
|
||||
char str[128];
|
||||
sprintf(str,"Cannot open restart file %s",perproc);
|
||||
sprintf(str,"Cannot open restart file %s",procfile);
|
||||
error->one(FLERR,str);
|
||||
}
|
||||
|
||||
nread_int(&n,1,fp);
|
||||
int flag;
|
||||
fread(&flag,sizeof(int),1,fp);
|
||||
if (flag != PROCSPERFILE)
|
||||
error->one(FLERR,"Invalid flag in peratom section of restart file");
|
||||
int procsperfile;
|
||||
fread(&procsperfile,sizeof(int),1,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");
|
||||
}
|
||||
if (n > 0) nread_double(buf,n,fp);
|
||||
fread(buf,sizeof(double),n,fp);
|
||||
|
||||
m = 0;
|
||||
while (m < n) m += avec->unpack_restart(&buf[m]);
|
||||
}
|
||||
|
||||
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
|
||||
// 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
|
||||
|
||||
bigint natoms;
|
||||
@ -451,13 +586,13 @@ void ReadRestart::file_search(char *infile, char *outfile)
|
||||
read header of restart file
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void ReadRestart::header()
|
||||
void ReadRestart::header(int outofdate)
|
||||
{
|
||||
int px,py,pz;
|
||||
int xperiodic,yperiodic,zperiodic;
|
||||
int boundary[3][2];
|
||||
|
||||
// read flags and values until flag = -1
|
||||
// read flags and fields until flag = -1
|
||||
|
||||
int flag = read_int();
|
||||
while (flag >= 0) {
|
||||
@ -465,13 +600,13 @@ void ReadRestart::header()
|
||||
// check restart file version, warn if different
|
||||
|
||||
if (flag == VERSION) {
|
||||
char *version = read_char();
|
||||
if (strcmp(version,universe->version) != 0 && me == 0) {
|
||||
error->warning(FLERR,
|
||||
"Restart file version does not match LAMMPS version");
|
||||
char *version = read_string();
|
||||
if (me == 0) {
|
||||
if (screen) fprintf(screen," restart file = %s, LAMMPS = %s\n",
|
||||
version,universe->version);
|
||||
}
|
||||
if (outofdate)
|
||||
error->all(FLERR,"Restart file too old for current version to read");
|
||||
delete [] version;
|
||||
|
||||
// check lmptype.h sizes, error if different
|
||||
@ -493,7 +628,7 @@ void ReadRestart::header()
|
||||
// so that timestep,neighbor-skin are not changed
|
||||
|
||||
} else if (flag == UNITS) {
|
||||
char *style = read_char();
|
||||
char *style = read_string();
|
||||
if (strcmp(style,update->unit_style) != 0) update->set_units(style);
|
||||
delete [] style;
|
||||
|
||||
@ -518,15 +653,14 @@ void ReadRestart::header()
|
||||
|
||||
// don't set procgrid, warn if different
|
||||
|
||||
} else if (flag == PROCGRID_0) {
|
||||
px = read_int();
|
||||
} else if (flag == PROCGRID_1) {
|
||||
py = read_int();
|
||||
} else if (flag == PROCGRID_2) {
|
||||
pz = read_int();
|
||||
} else if (flag == PROCGRID) {
|
||||
int procgrid[3];
|
||||
read_int();
|
||||
read_int_vec(3,procgrid);
|
||||
if (comm->user_procgrid[0] != 0 &&
|
||||
(px != comm->user_procgrid[0] || py != comm->user_procgrid[1] ||
|
||||
pz != comm->user_procgrid[2]) && me == 0)
|
||||
(procgrid[0] != comm->user_procgrid[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");
|
||||
|
||||
// don't set newton_pair, leave input script value unchanged
|
||||
@ -562,18 +696,10 @@ void ReadRestart::header()
|
||||
yperiodic = read_int();
|
||||
} else if (flag == ZPERIODIC) {
|
||||
zperiodic = read_int();
|
||||
} else if (flag == BOUNDARY_00) {
|
||||
boundary[0][0] = read_int();
|
||||
} else if (flag == BOUNDARY_01) {
|
||||
boundary[0][1] = read_int();
|
||||
} 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();
|
||||
} else if (flag == BOUNDARY) {
|
||||
int boundary[3][2];
|
||||
read_int();
|
||||
read_int_vec(6,&boundary[0][0]);
|
||||
|
||||
if (domain->boundary[0][0] || domain->boundary[0][1] ||
|
||||
domain->boundary[1][0] || domain->boundary[1][1] ||
|
||||
@ -615,7 +741,7 @@ void ReadRestart::header()
|
||||
// if style = hybrid, read additional sub-class arguments
|
||||
|
||||
} else if (flag == ATOM_STYLE) {
|
||||
char *style = read_char();
|
||||
char *style = read_string();
|
||||
|
||||
int nwords = 0;
|
||||
char **words = NULL;
|
||||
@ -623,7 +749,7 @@ void ReadRestart::header()
|
||||
if (strcmp(style,"hybrid") == 0) {
|
||||
nwords = read_int();
|
||||
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);
|
||||
@ -662,42 +788,28 @@ void ReadRestart::header()
|
||||
} else if (flag == IMPROPER_PER_ATOM) {
|
||||
atom->improper_per_atom = read_int();
|
||||
|
||||
} else if (flag == BOXLO_0) {
|
||||
domain->boxlo[0] = read_double();
|
||||
} else if (flag == BOXHI_0) {
|
||||
domain->boxhi[0] = read_double();
|
||||
} else if (flag == BOXLO_1) {
|
||||
domain->boxlo[1] = read_double();
|
||||
} else if (flag == BOXHI_1) {
|
||||
domain->boxhi[1] = read_double();
|
||||
} 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 == TRICLINIC) {
|
||||
domain->triclinic = read_int();
|
||||
} else if (flag == BOXLO) {
|
||||
read_int();
|
||||
read_double_vec(3,domain->boxlo);
|
||||
} else if (flag == BOXHI) {
|
||||
read_int();
|
||||
read_double_vec(3,domain->boxhi);
|
||||
} else if (flag == XY) {
|
||||
domain->triclinic = 1;
|
||||
domain->xy = read_double();
|
||||
} else if (flag == XZ) {
|
||||
domain->triclinic = 1;
|
||||
domain->xz = read_double();
|
||||
} else if (flag == YZ) {
|
||||
domain->triclinic = 1;
|
||||
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");
|
||||
|
||||
flag = read_int();
|
||||
@ -712,9 +824,9 @@ void ReadRestart::type_arrays()
|
||||
while (flag >= 0) {
|
||||
|
||||
if (flag == MASS) {
|
||||
read_int();
|
||||
double *mass = new double[atom->ntypes+1];
|
||||
if (me == 0) nread_double(&mass[1],atom->ntypes,fp);
|
||||
MPI_Bcast(&mass[1],atom->ntypes,MPI_DOUBLE,0,world);
|
||||
read_double_vec(atom->ntypes,&mass[1]);
|
||||
atom->set_mass(mass);
|
||||
delete [] mass;
|
||||
|
||||
@ -736,55 +848,31 @@ void ReadRestart::force_fields()
|
||||
while (flag >= 0) {
|
||||
|
||||
if (flag == PAIR) {
|
||||
n = read_int();
|
||||
style = new char[n];
|
||||
if (me == 0) nread_char(style,n,fp);
|
||||
MPI_Bcast(style,n,MPI_CHAR,0,world);
|
||||
|
||||
style = read_string();
|
||||
force->create_pair(style);
|
||||
delete [] style;
|
||||
if (force->pair->restartinfo) force->pair->read_restart(fp);
|
||||
else {
|
||||
delete force->pair;
|
||||
force->pair = NULL;
|
||||
}
|
||||
force->pair->read_restart(fp);
|
||||
|
||||
} else if (flag == BOND) {
|
||||
n = read_int();
|
||||
style = new char[n];
|
||||
if (me == 0) nread_char(style,n,fp);
|
||||
MPI_Bcast(style,n,MPI_CHAR,0,world);
|
||||
|
||||
style = read_string();
|
||||
force->create_bond(style);
|
||||
delete [] style;
|
||||
force->bond->read_restart(fp);
|
||||
|
||||
} else if (flag == ANGLE) {
|
||||
n = read_int();
|
||||
style = new char[n];
|
||||
if (me == 0) nread_char(style,n,fp);
|
||||
MPI_Bcast(style,n,MPI_CHAR,0,world);
|
||||
|
||||
style = read_string();
|
||||
force->create_angle(style);
|
||||
delete [] style;
|
||||
force->angle->read_restart(fp);
|
||||
|
||||
} else if (flag == DIHEDRAL) {
|
||||
n = read_int();
|
||||
style = new char[n];
|
||||
if (me == 0) nread_char(style,n,fp);
|
||||
MPI_Bcast(style,n,MPI_CHAR,0,world);
|
||||
|
||||
style = read_string();
|
||||
force->create_dihedral(style);
|
||||
delete [] style;
|
||||
force->dihedral->read_restart(fp);
|
||||
|
||||
} else if (flag == IMPROPER) {
|
||||
n = read_int();
|
||||
style = new char[n];
|
||||
if (me == 0) nread_char(style,n,fp);
|
||||
MPI_Bcast(style,n,MPI_CHAR,0,world);
|
||||
|
||||
style = read_string();
|
||||
force->create_improper(style);
|
||||
delete [] style;
|
||||
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);
|
||||
if (swapflag) {}
|
||||
int n = strlen(MAGIC_STRING) + 1;
|
||||
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);
|
||||
if (swapflag) {}
|
||||
int endian;
|
||||
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 value;
|
||||
if (me == 0) {
|
||||
fread(&value,sizeof(int),1,fp);
|
||||
if (swapflag) {}
|
||||
}
|
||||
if (me == 0) fread(&value,sizeof(int),1,fp);
|
||||
MPI_Bcast(&value,1,MPI_INT,0,world);
|
||||
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
|
||||
------------------------------------------------------------------------- */
|
||||
@ -887,35 +980,57 @@ char *ReadRestart::read_char()
|
||||
bigint ReadRestart::read_bigint()
|
||||
{
|
||||
bigint value;
|
||||
if (me == 0) {
|
||||
fread(&value,sizeof(bigint),1,fp);
|
||||
if (swapflag) {}
|
||||
}
|
||||
if (me == 0) fread(&value,sizeof(bigint),1,fp);
|
||||
MPI_Bcast(&value,1,MPI_LMP_BIGINT,0,world);
|
||||
return value;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
auto-detect if restart file needs to be byte-swapped on this platform
|
||||
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
|
||||
read a double from restart file and bcast it
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
int ReadRestart::autodetect(FILE **pfp, char *file)
|
||||
double ReadRestart::read_double()
|
||||
{
|
||||
FILE *fp = *pfp;
|
||||
|
||||
// read, check, set return flag
|
||||
|
||||
int flag = 0;
|
||||
|
||||
// reset file pointer
|
||||
|
||||
fclose(fp);
|
||||
fp = fopen(file,"rb");
|
||||
*pfp = fp;
|
||||
|
||||
return flag;
|
||||
double value;
|
||||
if (me == 0) fread(&value,sizeof(double),1,fp);
|
||||
MPI_Bcast(&value,1,MPI_DOUBLE,0,world);
|
||||
return value;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
read a char string (including NULL) and bcast it
|
||||
str is allocated here, ptr is returned, caller must deallocate
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
char *ReadRestart::read_string()
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
@ -31,24 +31,30 @@ class ReadRestart : protected Pointers {
|
||||
void command(int, char **);
|
||||
|
||||
private:
|
||||
int me,nprocs,nprocs_file;
|
||||
int me,nprocs,nprocs_file,multiproc_file;
|
||||
FILE *fp;
|
||||
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 header();
|
||||
void header(int);
|
||||
void type_arrays();
|
||||
void force_fields();
|
||||
|
||||
void nread_int(int *, int, FILE *);
|
||||
void nread_double(double *, int, FILE *);
|
||||
void nread_char(char *, int, FILE *);
|
||||
void magic_string();
|
||||
void endian();
|
||||
int version_numeric();
|
||||
void file_layout();
|
||||
|
||||
int read_int();
|
||||
double read_double();
|
||||
char *read_char();
|
||||
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 *);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@ -39,23 +39,26 @@
|
||||
|
||||
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,
|
||||
UNITS,NTIMESTEP,DIMENSION,NPROCS,PROCGRID_0,PROCGRID_1,PROCGRID_2,
|
||||
NEWTON_PAIR,NEWTON_BOND,XPERIODIC,YPERIODIC,ZPERIODIC,
|
||||
BOUNDARY_00,BOUNDARY_01,BOUNDARY_10,BOUNDARY_11,BOUNDARY_20,BOUNDARY_21,
|
||||
UNITS,NTIMESTEP,DIMENSION,NPROCS,PROCGRID,
|
||||
NEWTON_PAIR,NEWTON_BOND,
|
||||
XPERIODIC,YPERIODIC,ZPERIODIC,BOUNDARY,
|
||||
ATOM_STYLE,NATOMS,NTYPES,
|
||||
NBONDS,NBONDTYPES,BOND_PER_ATOM,
|
||||
NANGLES,NANGLETYPES,ANGLE_PER_ATOM,
|
||||
NDIHEDRALS,NDIHEDRALTYPES,DIHEDRAL_PER_ATOM,
|
||||
NIMPROPERS,NIMPROPERTYPES,IMPROPER_PER_ATOM,
|
||||
BOXLO_0,BOXHI_0,BOXLO_1,BOXHI_1,BOXLO_2,BOXHI_2,
|
||||
SPECIAL_LJ_1,SPECIAL_LJ_2,SPECIAL_LJ_3,
|
||||
SPECIAL_COUL_1,SPECIAL_COUL_2,SPECIAL_COUL_3,
|
||||
XY,XZ,YZ};
|
||||
enum{MASS};
|
||||
enum{PAIR,BOND,ANGLE,DIHEDRAL,IMPROPER};
|
||||
TRICLINIC,BOXLO,BOXHI,XY,XZ,YZ,
|
||||
SPECIAL_LJ,SPECIAL_COUL,
|
||||
MASS,PAIR,BOND,ANGLE,DIHEDRAL,IMPROPER,
|
||||
MULTIPROC,MPIIO,PROCSPERFILE,PERPROC};
|
||||
|
||||
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_size(world,&nprocs);
|
||||
multiproc = 0;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
@ -75,7 +79,7 @@ void WriteRestart::command(int narg, char **arg)
|
||||
{
|
||||
if (domain->box_exist == 0)
|
||||
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
|
||||
|
||||
@ -88,6 +92,21 @@ void WriteRestart::command(int narg, char **arg)
|
||||
sprintf(file,"%s" BIGINT_FORMAT "%s",arg[0],update->ntimestep,ptr+1);
|
||||
} 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
|
||||
// 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;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
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
|
||||
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)
|
||||
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
|
||||
|
||||
if (me == 0) {
|
||||
@ -164,8 +249,15 @@ void WriteRestart::write(char *file)
|
||||
if (multiproc) delete [] hfile;
|
||||
}
|
||||
|
||||
// proc 0 writes header, groups, ntype-length arrays, force field
|
||||
// all procs write fix info
|
||||
// proc 0 writes magic string, endian flag, numeric version
|
||||
|
||||
if (me == 0) {
|
||||
magic_string();
|
||||
endian();
|
||||
version_numeric();
|
||||
}
|
||||
|
||||
// proc 0 writes header, groups, pertype info, force field info
|
||||
|
||||
if (me == 0) {
|
||||
header();
|
||||
@ -174,9 +266,11 @@ void WriteRestart::write(char *file)
|
||||
force_fields();
|
||||
}
|
||||
|
||||
// all procs write fix info
|
||||
|
||||
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
|
||||
|
||||
int max_size;
|
||||
@ -184,8 +278,35 @@ void WriteRestart::write(char *file)
|
||||
MPI_Allreduce(&send_size,&max_size,1,MPI_INT,MPI_MAX,world);
|
||||
|
||||
double *buf;
|
||||
if (me == 0) memory->create(buf,max_size,"write_restart:buf");
|
||||
else memory->create(buf,send_size,"write_restart:buf");
|
||||
memory->create(buf,max_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
|
||||
|
||||
@ -242,55 +363,31 @@ void WriteRestart::write(char *file)
|
||||
}
|
||||
}
|
||||
|
||||
// if single file:
|
||||
// write one chunk of atoms per proc to file
|
||||
// proc 0 pings each proc, receives its chunk, writes to file
|
||||
// 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
|
||||
// filewriter = 1 = this proc writes to file
|
||||
// ping each proc in my cluster, receive its data, write data to file
|
||||
// else wait for ping from fileproc, send my data to fileproc
|
||||
|
||||
if (multiproc == 0) {
|
||||
int tmp,recv_size;
|
||||
MPI_Status status;
|
||||
MPI_Request request;
|
||||
|
||||
if (me == 0) {
|
||||
for (int iproc = 0; iproc < nprocs; iproc++) {
|
||||
if (filewriter) {
|
||||
write_int(PROCSPERFILE,nclusterprocs);
|
||||
for (int iproc = 0; iproc < nclusterprocs; iproc++) {
|
||||
if (iproc) {
|
||||
MPI_Irecv(buf,max_size,MPI_DOUBLE,iproc,0,world,&request);
|
||||
MPI_Send(&tmp,0,MPI_INT,iproc,0,world);
|
||||
MPI_Irecv(buf,max_size,MPI_DOUBLE,me+iproc,0,world,&request);
|
||||
MPI_Send(&tmp,0,MPI_INT,me+iproc,0,world);
|
||||
MPI_Wait(&request,&status);
|
||||
MPI_Get_count(&status,MPI_DOUBLE,&recv_size);
|
||||
} else recv_size = send_size;
|
||||
|
||||
fwrite(&recv_size,sizeof(int),1,fp);
|
||||
fwrite(buf,sizeof(double),recv_size,fp);
|
||||
write_double_vec(PERPROC,recv_size,buf);
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
} else {
|
||||
MPI_Recv(&tmp,0,MPI_INT,0,0,world,&status);
|
||||
MPI_Rsend(buf,send_size,MPI_DOUBLE,0,0,world);
|
||||
}
|
||||
|
||||
} else {
|
||||
if (me == 0) fclose(fp);
|
||||
|
||||
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);
|
||||
MPI_Recv(&tmp,0,MPI_INT,fileproc,0,world,&status);
|
||||
MPI_Rsend(buf,send_size,MPI_DOUBLE,fileproc,0,world);
|
||||
}
|
||||
|
||||
memory->destroy(buf);
|
||||
@ -308,35 +405,28 @@ void WriteRestart::write(char *file)
|
||||
|
||||
void WriteRestart::header()
|
||||
{
|
||||
write_char(VERSION,universe->version);
|
||||
write_string(VERSION,universe->version);
|
||||
write_int(SMALLINT,sizeof(smallint));
|
||||
write_int(TAGINT,sizeof(tagint));
|
||||
write_int(BIGINT,sizeof(bigint));
|
||||
write_char(UNITS,update->unit_style);
|
||||
write_string(UNITS,update->unit_style);
|
||||
write_bigint(NTIMESTEP,update->ntimestep);
|
||||
write_int(DIMENSION,domain->dimension);
|
||||
write_int(NPROCS,nprocs);
|
||||
write_int(PROCGRID_0,comm->procgrid[0]);
|
||||
write_int(PROCGRID_1,comm->procgrid[1]);
|
||||
write_int(PROCGRID_2,comm->procgrid[2]);
|
||||
write_int_vec(PROCGRID,3,comm->procgrid);
|
||||
write_int(NEWTON_PAIR,force->newton_pair);
|
||||
write_int(NEWTON_BOND,force->newton_bond);
|
||||
write_int(XPERIODIC,domain->xperiodic);
|
||||
write_int(YPERIODIC,domain->yperiodic);
|
||||
write_int(ZPERIODIC,domain->zperiodic);
|
||||
write_int(BOUNDARY_00,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]);
|
||||
write_int_vec(BOUNDARY,6,&domain->boundary[0][0]);
|
||||
|
||||
// atom_style must be written before atom class values
|
||||
// so read_restart can create class before reading class values
|
||||
// if style = hybrid, also write sub-class styles
|
||||
// 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) {
|
||||
AtomVecHybrid *avec_hybrid = (AtomVecHybrid *) atom->avec;
|
||||
@ -349,8 +439,7 @@ void WriteRestart::header()
|
||||
fwrite(keywords[i],sizeof(char),n,fp);
|
||||
}
|
||||
}
|
||||
|
||||
if (me == 0) atom->avec->write_restart_settings(fp);
|
||||
atom->avec->write_restart_settings(fp);
|
||||
|
||||
write_bigint(NATOMS,natoms);
|
||||
write_int(NTYPES,atom->ntypes);
|
||||
@ -367,25 +456,15 @@ void WriteRestart::header()
|
||||
write_int(NIMPROPERTYPES,atom->nimpropertypes);
|
||||
write_int(IMPROPER_PER_ATOM,atom->improper_per_atom);
|
||||
|
||||
write_double(BOXLO_0,domain->boxlo[0]);
|
||||
write_double(BOXHI_0,domain->boxhi[0]);
|
||||
write_double(BOXLO_1,domain->boxlo[1]);
|
||||
write_double(BOXHI_1,domain->boxhi[1]);
|
||||
write_double(BOXLO_2,domain->boxlo[2]);
|
||||
write_double(BOXHI_2,domain->boxhi[2]);
|
||||
|
||||
write_double(SPECIAL_LJ_1,force->special_lj[1]);
|
||||
write_double(SPECIAL_LJ_2,force->special_lj[2]);
|
||||
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_int(TRICLINIC,domain->triclinic);
|
||||
write_double_vec(BOXLO,3,domain->boxlo);
|
||||
write_double_vec(BOXHI,3,domain->boxhi);
|
||||
write_double(XY,domain->xy);
|
||||
write_double(XZ,domain->xz);
|
||||
write_double(YZ,domain->yz);
|
||||
}
|
||||
|
||||
write_double_vec(SPECIAL_LJ,3,&force->special_lj[1]);
|
||||
write_double_vec(SPECIAL_COUL,3,&force->special_coul[1]);
|
||||
|
||||
// -1 flag signals end of header
|
||||
|
||||
@ -399,11 +478,7 @@ void WriteRestart::header()
|
||||
|
||||
void WriteRestart::type_arrays()
|
||||
{
|
||||
if (atom->mass) {
|
||||
int flag = MASS;
|
||||
fwrite(&flag,sizeof(int),1,fp);
|
||||
fwrite(&atom->mass[1],sizeof(double),atom->ntypes,fp);
|
||||
}
|
||||
if (atom->mass) write_double_vec(MASS,atom->ntypes,&atom->mass[1]);
|
||||
|
||||
// -1 flag signals end of type arrays
|
||||
|
||||
@ -417,44 +492,24 @@ void WriteRestart::type_arrays()
|
||||
|
||||
void WriteRestart::force_fields()
|
||||
{
|
||||
if (force->pair) {
|
||||
int flag = PAIR;
|
||||
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);
|
||||
if (force->pair && force->pair->restartinfo) {
|
||||
write_string(PAIR,force->pair_style);
|
||||
force->pair->write_restart(fp);
|
||||
}
|
||||
if (atom->avec->bonds_allow && force->bond) {
|
||||
int flag = BOND;
|
||||
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);
|
||||
write_string(BOND,force->bond_style);
|
||||
force->bond->write_restart(fp);
|
||||
}
|
||||
if (atom->avec->angles_allow && force->angle) {
|
||||
int flag = ANGLE;
|
||||
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);
|
||||
write_string(ANGLE,force->angle_style);
|
||||
force->angle->write_restart(fp);
|
||||
}
|
||||
if (atom->avec->dihedrals_allow && force->dihedral) {
|
||||
int flag = DIHEDRAL;
|
||||
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);
|
||||
write_string(DIHEDRAL,force->dihedral_style);
|
||||
force->dihedral->write_restart(fp);
|
||||
}
|
||||
if (atom->avec->impropers_allow && force->improper) {
|
||||
int flag = IMPROPER;
|
||||
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);
|
||||
write_string(IMPROPER,force->improper_style);
|
||||
force->improper->write_restart(fp);
|
||||
}
|
||||
|
||||
@ -464,6 +519,62 @@ void WriteRestart::force_fields()
|
||||
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
|
||||
------------------------------------------------------------------------- */
|
||||
@ -474,6 +585,16 @@ void WriteRestart::write_int(int flag, int value)
|
||||
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
|
||||
------------------------------------------------------------------------- */
|
||||
@ -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;
|
||||
fwrite(&flag,sizeof(int),1,fp);
|
||||
fwrite(&n,sizeof(int),1,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(&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);
|
||||
}
|
||||
|
||||
@ -29,6 +29,7 @@ class WriteRestart : protected Pointers {
|
||||
public:
|
||||
WriteRestart(class LAMMPS *);
|
||||
void command(int, char **);
|
||||
void multiproc_options(int, int, int, char **);
|
||||
void write(char *);
|
||||
|
||||
private:
|
||||
@ -36,14 +37,29 @@ class WriteRestart : protected Pointers {
|
||||
FILE *fp;
|
||||
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 type_arrays();
|
||||
void force_fields();
|
||||
void file_layout(int);
|
||||
|
||||
void magic_string();
|
||||
void endian();
|
||||
void version_numeric();
|
||||
|
||||
void write_int(int, int);
|
||||
void write_double(int, double);
|
||||
void write_char(int, char *);
|
||||
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 *);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user