#include "read_dump.h"
#include <mpi.h>
#include <cstring>
#include <string>
#include "reader.h"
#include "style_reader.h"
#include "atom.h"
#include "atom_vec.h"
#include "update.h"
#include "domain.h"
#include "comm.h"
#include "force.h"
#include "irregular.h"
#include "error.h"
#include "memory.h"
#include "utils.h"
using namespace LAMMPS_NS;
#define CHUNK 16384
enum{ID,TYPE,X,Y,Z,VX,VY,VZ,Q,IX,IY,IZ,FX,FY,FZ};
enum{UNSET,NOSCALE_NOWRAP,NOSCALE_WRAP,SCALE_NOWRAP,SCALE_WRAP};
enum{NOADD,YESADD,KEEPADD};
ReadDump::ReadDump(LAMMPS *lmp) : Pointers(lmp)
{
MPI_Comm_rank(world,&me);
MPI_Comm_size(world,&nprocs);
dimension = domain->dimension;
triclinic = domain->triclinic;
nfile = 0;
files = NULL;
nnew = maxnew = 0;
nfield = 0;
fieldtype = NULL;
fieldlabel = NULL;
fields = NULL;
buf = NULL;
int n = strlen("native") + 1;
readerstyle = new char[n];
strcpy(readerstyle,"native");
nreader = 0;
readers = NULL;
nsnapatoms = NULL;
clustercomm = MPI_COMM_NULL;
}
ReadDump::~ReadDump()
{
for (int i = 0; i < nfile; i++) delete [] files[i];
delete [] files;
for (int i = 0; i < nfield; i++) delete [] fieldlabel[i];
delete [] fieldlabel;
delete [] fieldtype;
delete [] readerstyle;
memory->destroy(fields);
memory->destroy(buf);
for (int i = 0; i < nreader; i++) delete readers[i];
delete [] readers;
delete [] nsnapatoms;
MPI_Comm_free(&clustercomm);
}
void ReadDump::command(int narg, char **arg)
{
if (domain->box_exist == 0)
error->all(FLERR,"Read_dump command before simulation box is defined");
if (narg < 2) error->all(FLERR,"Illegal read_dump command");
store_files(1,&arg[0]);
bigint nstep = force->bnumeric(FLERR,arg[1]);
int nremain = narg - 2;
if (nremain) nremain = fields_and_keywords(nremain,&arg[narg-nremain]);
else nremain = fields_and_keywords(0,NULL);
if (nremain) setup_reader(nremain,&arg[narg-nremain]);
else setup_reader(0,NULL);
if (me == 0 && screen) fprintf(screen,"Scanning dump file ...\n");
bigint ntimestep = seek(nstep,1);
if (ntimestep < 0)
error->all(FLERR,"Dump file does not contain requested snapshot");
header(1);
update->reset_timestep(nstep);
if (me == 0 && screen)
fprintf(screen,"Reading snapshot from dump file ...\n");
bigint natoms_prev = atom->natoms;
atoms();
if (filereader)
for (int i = 0; i < nreader; i++)
readers[i]->close_file();
bigint nsnap_all,npurge_all,nreplace_all,ntrim_all,nadd_all;
bigint tmp = 0;
if (filereader)
for (int i = 0; i < nreader; i++)
tmp += nsnapatoms[i];
MPI_Allreduce(&tmp,&nsnap_all,1,MPI_LMP_BIGINT,MPI_SUM,world);
tmp = npurge;
MPI_Allreduce(&tmp,&npurge_all,1,MPI_LMP_BIGINT,MPI_SUM,world);
tmp = nreplace;
MPI_Allreduce(&tmp,&nreplace_all,1,MPI_LMP_BIGINT,MPI_SUM,world);
tmp = ntrim;
MPI_Allreduce(&tmp,&ntrim_all,1,MPI_LMP_BIGINT,MPI_SUM,world);
tmp = nadd;
MPI_Allreduce(&tmp,&nadd_all,1,MPI_LMP_BIGINT,MPI_SUM,world);
domain->print_box(" ");
if (me == 0) {
if (screen) {
fprintf(screen," " BIGINT_FORMAT " atoms before read\n",natoms_prev);
fprintf(screen," " BIGINT_FORMAT " atoms in snapshot\n",nsnap_all);
fprintf(screen," " BIGINT_FORMAT " atoms purged\n",npurge_all);
fprintf(screen," " BIGINT_FORMAT " atoms replaced\n",nreplace_all);
fprintf(screen," " BIGINT_FORMAT " atoms trimmed\n",ntrim_all);
fprintf(screen," " BIGINT_FORMAT " atoms added\n",nadd_all);
fprintf(screen," " BIGINT_FORMAT " atoms after read\n",atom->natoms);
}
if (logfile) {
fprintf(logfile," " BIGINT_FORMAT " atoms before read\n",natoms_prev);
fprintf(logfile," " BIGINT_FORMAT " atoms in snapshot\n",nsnap_all);
fprintf(logfile," " BIGINT_FORMAT " atoms purged\n",npurge_all);
fprintf(logfile," " BIGINT_FORMAT " atoms replaced\n",nreplace_all);
fprintf(logfile," " BIGINT_FORMAT " atoms trimmed\n",ntrim_all);
fprintf(logfile," " BIGINT_FORMAT " atoms added\n",nadd_all);
fprintf(logfile," " BIGINT_FORMAT " atoms after read\n",atom->natoms);
}
}
}
void ReadDump::store_files(int nstr, char **str)
{
nfile = nstr;
files = new char*[nfile];
for (int i = 0; i < nfile; i++) {
int n = strlen(str[i]) + 1;
files[i] = new char[n];
strcpy(files[i],str[i]);
if (i == 0) {
if (strchr(files[i],'%')) multiproc = 1;
else multiproc = 0;
} else {
if (multiproc && !strchr(files[i],'%'))
error->all(FLERR,"All read_dump files must be serial or parallel");
if (!multiproc && strchr(files[i],'%'))
error->all(FLERR,"All read_dump files must be serial or parallel");
}
}
}
void ReadDump::setup_reader(int narg, char **arg)
{
if (multiproc == 0) {
nreader = 1;
firstfile = -1;
MPI_Comm_dup(world,&clustercomm);
} else if (multiproc_nfile >= nprocs) {
firstfile = static_cast<int> ((bigint) me * multiproc_nfile/nprocs);
int lastfile = static_cast<int> ((bigint) (me+1) * multiproc_nfile/nprocs);
nreader = lastfile - firstfile;
MPI_Comm_split(world,me,0,&clustercomm);
} else if (multiproc_nfile < nprocs) {
nreader = 1;
int icluster = static_cast<int> ((bigint) me * multiproc_nfile/nprocs);
firstfile = icluster;
MPI_Comm_split(world,icluster,0,&clustercomm);
}
MPI_Comm_rank(clustercomm,&me_cluster);
MPI_Comm_size(clustercomm,&nprocs_cluster);
if (me_cluster == 0) filereader = 1;
else filereader = 0;
readers = new Reader*[nreader];
nsnapatoms = new bigint[nreader];
if (0) return;
#define READER_CLASS
#define ReaderStyle(key,Class) \
else if (strcmp(readerstyle,#key) == 0) { \
for (int i = 0; i < nreader; i++) \
readers[i] = new Class(lmp); \
}
#include "style_reader.h"
#undef READER_CLASS
else error->all(FLERR,utils::check_packages_for_style("reader",readerstyle,lmp).c_str());
if (narg > 0 && filereader)
for (int i = 0; i < nreader; i++)
readers[i]->settings(narg,arg);
}
bigint ReadDump::seek(bigint nrequest, int exact)
{
int ifile,eofflag;
bigint ntimestep;
if (me == 0) {
for (ifile = 0; ifile < nfile; ifile++) {
ntimestep = -1;
if (multiproc) {
char *ptr = strchr(files[ifile],'%');
char *multiname = new char[strlen(files[ifile]) + 16];
*ptr = '\0';
sprintf(multiname,"%s%d%s",files[ifile],0,ptr+1);
*ptr = '%';
readers[0]->open_file(multiname);
delete [] multiname;
} else readers[0]->open_file(files[ifile]);
while (1) {
eofflag = readers[0]->read_time(ntimestep);
if (eofflag) break;
if (ntimestep >= nrequest) break;
readers[0]->skip();
}
if (ntimestep >= nrequest) break;
readers[0]->close_file();
}
currentfile = ifile;
if (ntimestep < nrequest) ntimestep = -1;
if (exact && ntimestep != nrequest) ntimestep = -1;
}
MPI_Bcast(&ntimestep,1,MPI_LMP_BIGINT,0,world);
MPI_Bcast(¤tfile,1,MPI_INT,0,world);
if (ntimestep < 0) {
if (filereader)
for (int i = 0; i < nreader; i++)
readers[i]->close_file();
return ntimestep;
}
if (multiproc && filereader) {
for (int i = 0; i < nreader; i++) {
if (me == 0 && i == 0) continue; char *ptr = strchr(files[currentfile],'%');
char *multiname = new char[strlen(files[currentfile]) + 16];
*ptr = '\0';
sprintf(multiname,"%s%d%s",files[currentfile],firstfile+i,ptr+1);
*ptr = '%';
readers[i]->open_file(multiname);
delete [] multiname;
bigint step;
while (1) {
eofflag = readers[i]->read_time(step);
if (eofflag) break;
if (step == ntimestep) break;
readers[i]->skip();
}
if (eofflag)
error->one(FLERR,"Read dump parallel files "
"do not all have same timestep");
}
}
return ntimestep;
}
bigint ReadDump::next(bigint ncurrent, bigint nlast, int nevery, int nskip)
{
int ifile,eofflag;
bigint ntimestep;
if (me == 0) {
int iskip = 0;
for (ifile = currentfile; ifile < nfile; ifile++) {
ntimestep = -1;
if (ifile != currentfile) {
if (multiproc) {
char *ptr = strchr(files[ifile],'%');
char *multiname = new char[strlen(files[ifile]) + 16];
*ptr = '\0';
sprintf(multiname,"%s%d%s",files[ifile],0,ptr+1);
*ptr = '%';
readers[0]->open_file(multiname);
delete [] multiname;
} else readers[0]->open_file(files[ifile]);
}
while (1) {
eofflag = readers[0]->read_time(ntimestep);
if (eofflag) break;
if (ntimestep > nlast) break;
if (ntimestep <= ncurrent) {
readers[0]->skip();
continue;
}
if (iskip == nskip) iskip = 0;
iskip++;
if (nevery && ntimestep % nevery) readers[0]->skip();
else if (iskip < nskip) readers[0]->skip();
else break;
}
if (eofflag) readers[0]->close_file();
else break;
}
currentfile = ifile;
if (eofflag) ntimestep = -1;
if (ntimestep <= ncurrent) ntimestep = -1;
if (ntimestep > nlast) ntimestep = -1;
}
MPI_Bcast(&ntimestep,1,MPI_LMP_BIGINT,0,world);
MPI_Bcast(¤tfile,1,MPI_INT,0,world);
if (ntimestep < 0) {
for (int i = 0; i < nreader; i++)
readers[i]->close_file();
return ntimestep;
}
if (multiproc && filereader) {
for (int i = 0; i < nreader; i++) {
if (me == 0 && i == 0) continue;
char *ptr = strchr(files[currentfile],'%');
char *multiname = new char[strlen(files[currentfile]) + 16];
*ptr = '\0';
sprintf(multiname,"%s%d%s",files[currentfile],firstfile+i,ptr+1);
*ptr = '%';
readers[i]->open_file(multiname);
delete [] multiname;
bigint step;
while (1) {
eofflag = readers[i]->read_time(step);
if (eofflag) break;
if (step == ntimestep) break;
readers[i]->skip();
}
if (eofflag)
error->one(FLERR,"Read dump parallel files "
"do not all have same timestep");
}
}
return ntimestep;
}
void ReadDump::header(int fieldinfo)
{
int boxinfo, triclinic_snap;
int fieldflag,xflag,yflag,zflag;
if (filereader) {
for (int i = 0; i < nreader; i++)
nsnapatoms[i] = readers[i]->read_header(box,boxinfo,triclinic_snap,fieldinfo,
nfield,fieldtype,fieldlabel,
scaleflag,wrapflag,fieldflag,
xflag,yflag,zflag);
}
MPI_Bcast(nsnapatoms,nreader,MPI_LMP_BIGINT,0,clustercomm);
MPI_Bcast(&boxinfo,1,MPI_INT,0,clustercomm);
MPI_Bcast(&triclinic_snap,1,MPI_INT,0,clustercomm);
MPI_Bcast(&box[0][0],9,MPI_DOUBLE,0,clustercomm);
if (boxinfo) {
xlo = box[0][0];
xhi = box[0][1];
ylo = box[1][0];
yhi = box[1][1];
zlo = box[2][0];
zhi = box[2][1];
if (triclinic_snap) {
xy = box[0][2];
xz = box[1][2];
yz = box[2][2];
double xdelta = MIN(0.0,xy);
xdelta = MIN(xdelta,xz);
xdelta = MIN(xdelta,xy+xz);
xlo = xlo - xdelta;
xdelta = MAX(0.0,xy);
xdelta = MAX(xdelta,xz);
xdelta = MAX(xdelta,xy+xz);
xhi = xhi - xdelta;
ylo = ylo - MIN(0.0,yz);
yhi = yhi - MAX(0.0,yz);
}
xprd = xhi - xlo;
yprd = yhi - ylo;
zprd = zhi - zlo;
}
if (!fieldinfo) return;
MPI_Bcast(&fieldflag,1,MPI_INT,0,clustercomm);
MPI_Bcast(&xflag,1,MPI_INT,0,clustercomm);
MPI_Bcast(&yflag,1,MPI_INT,0,clustercomm);
MPI_Bcast(&zflag,1,MPI_INT,0,clustercomm);
if (boxflag) {
if (!boxinfo)
error->all(FLERR,"No box information in dump, must use 'box no'");
else if ((triclinic_snap && !triclinic) ||
(!triclinic_snap && triclinic))
error->one(FLERR,"Read_dump triclinic status does not match simulation");
}
if (fieldflag < 0)
error->one(FLERR,"Read_dump field not found in dump file");
int value = MAX(xflag,yflag);
value = MAX(zflag,value);
if ((xflag != UNSET && xflag != value) ||
(yflag != UNSET && yflag != value) ||
(zflag != UNSET && zflag != value))
error->one(FLERR,
"Read_dump xyz fields do not have consistent scaling/wrapping");
value = UNSET;
if (xflag != UNSET) value = xflag;
if (yflag != UNSET) value = yflag;
if (zflag != UNSET) value = zflag;
if (value == UNSET) {
scaled = wrapped = 0;
} else if (value == NOSCALE_NOWRAP) {
scaled = wrapped = 0;
} else if (value == NOSCALE_WRAP) {
scaled = 0;
wrapped = 1;
} else if (value == SCALE_NOWRAP) {
scaled = 1;
wrapped = 0;
} else if (value == SCALE_WRAP) {
scaled = wrapped = 1;
}
if (scaled && triclinic == 1) {
int flag = 0;
if (xflag == UNSET) flag = 1;
if (yflag == UNSET) flag = 1;
if (dimension == 3 && zflag == UNSET) flag = 1;
if (flag)
error->one(FLERR,"All read_dump x,y,z fields must be specified for "
"scaled, triclinic coords");
for (int i = 0; i < nfield; i++) {
if (fieldtype[i] == Y) yindex = i;
if (fieldtype[i] == Z) zindex = i;
}
}
}
void ReadDump::atoms()
{
npurge = nreplace = ntrim = nadd = 0;
if (purgeflag) {
if (atom->map_style) atom->map_clear();
npurge = atom->nlocal;
atom->nlocal = atom->nghost = 0;
atom->natoms = 0;
}
read_atoms();
if (!purgeflag && nprocs > 1) migrate_old_atoms();
if (!purgeflag && nprocs > 1) migrate_new_atoms();
int mapflag = 0;
if (atom->map_style == 0) {
mapflag = 1;
atom->map_init();
atom->map_set();
}
process_atoms();
atom->tag_check();
if (mapflag) {
atom->map_delete();
atom->map_style = 0;
} else {
atom->nghost = 0;
atom->map_init();
atom->map_set();
}
if (boxflag) {
domain->boxlo[0] = xlo;
domain->boxhi[0] = xhi;
domain->boxlo[1] = ylo;
domain->boxhi[1] = yhi;
if (dimension == 3) {
domain->boxlo[2] = zlo;
domain->boxhi[2] = zhi;
}
if (triclinic) {
domain->xy = xy;
if (dimension == 3) {
domain->xz = xz;
domain->yz = yz;
}
}
domain->set_initial_box();
domain->set_global_box();
comm->set_proc_grid(0);
domain->set_local_box();
}
migrate_atoms_by_coords();
}
void ReadDump::read_atoms()
{
int count,nread,nsend,nrecv,otherproc;
bigint nsnap,ntotal,ofirst,olast,rfirst,rlast,lo,hi;
MPI_Request request;
MPI_Status status;
if (!multiproc || multiproc_nfile < nprocs) {
nsnap = nsnapatoms[0];
if (filereader) {
if (!buf) memory->create(buf,CHUNK,nfield,"read_dump:buf");
otherproc = 0;
ofirst = (bigint) otherproc * nsnap/nprocs_cluster;
olast = (bigint) (otherproc+1) * nsnap/nprocs_cluster;
if (olast-ofirst > MAXSMALLINT)
error->one(FLERR,"Read dump snapshot is too large for a proc");
nnew = static_cast<int> (olast - ofirst);
if (nnew > maxnew || maxnew == 0) {
memory->destroy(fields);
maxnew = MAX(nnew,1); memory->create(fields,maxnew,nfield,"read_dump:fields");
}
ntotal = 0;
while (ntotal < nsnap) {
nread = MIN(CHUNK,nsnap-ntotal);
readers[0]->read_atoms(nread,nfield,buf);
rfirst = ntotal;
rlast = ntotal + nread;
nsend = 0;
while (nsend < nread) {
lo = MAX(ofirst,rfirst);
hi = MIN(olast,rlast);
if (otherproc) MPI_Send(&buf[nsend][0],(hi-lo)*nfield,MPI_DOUBLE,
otherproc,0,clustercomm);
else
memcpy(&fields[rfirst][0],&buf[nsend][0],
(hi-lo)*nfield*sizeof(double));
nsend += hi-lo;
if (hi == olast) {
otherproc++;
ofirst = (bigint) otherproc * nsnap/nprocs_cluster;
olast = (bigint) (otherproc+1) * nsnap/nprocs_cluster;
}
}
ntotal += nread;
}
} else {
ofirst = (bigint) me_cluster * nsnap/nprocs_cluster;
olast = (bigint) (me_cluster+1) * nsnap/nprocs_cluster;
if (olast-ofirst > MAXSMALLINT)
error->one(FLERR,"Read dump snapshot is too large for a proc");
nnew = static_cast<int> (olast - ofirst);
if (nnew > maxnew || maxnew == 0) {
memory->destroy(fields);
maxnew = MAX(nnew,1); memory->create(fields,maxnew,nfield,"read_dump:fields");
}
nrecv = 0;
while (nrecv < nnew) {
MPI_Irecv(&fields[nrecv][0],(nnew-nrecv)*nfield,MPI_DOUBLE,0,0,
clustercomm,&request);
MPI_Wait(&request,&status);
MPI_Get_count(&status,MPI_DOUBLE,&count);
nrecv += count/nfield;
}
}
} else if (multiproc_nfile >= nprocs) {
bigint sum = 0;
for (int i = 0; i < nreader; i++)
sum += nsnapatoms[i];
if (sum > MAXSMALLINT)
error->one(FLERR,"Read dump snapshot is too large for a proc");
nnew = static_cast<int> (sum);
if (nnew > maxnew || maxnew == 0) {
memory->destroy(fields);
maxnew = MAX(nnew,1); memory->create(fields,maxnew,nfield,"read_dump:fields");
}
nnew = 0;
for (int i = 0; i < nreader; i++) {
nsnap = nsnapatoms[i];
ntotal = 0;
while (ntotal < nsnap) {
nread = MIN(CHUNK,nsnap-ntotal);
readers[i]->read_atoms(nread,nfield,&fields[nnew+ntotal]);
ntotal += nread;
}
nnew += nsnap;
}
}
}
void ReadDump::process_atoms()
{
int i,m,ifield,itype;
int xbox,ybox,zbox;
tagint mtag;
int *updateflag,*newflag;
int nlocal = atom->nlocal;
memory->create(updateflag,nlocal,"read_dump:updateflag");
for (int i = 0; i < nlocal; i++) updateflag[i] = 0;
memory->create(newflag,nnew,"read_dump:newflag");
for (int i = 0; i < nnew; i++) newflag[i] = 1;
double **x = atom->x;
double **v = atom->v;
double *q = atom->q;
double **f = atom->f;
tagint *tag = atom->tag;
imageint *image = atom->image;
tagint map_tag_max = atom->map_tag_max;
for (i = 0; i < nnew; i++) {
mtag = static_cast<tagint> (fields[i][0]);
if (mtag <= map_tag_max) m = atom->map(mtag);
else m = -1;
if (m < 0 || m >= nlocal) continue;
updateflag[m] = 1;
newflag[i] = 0;
if (replaceflag) {
nreplace++;
xbox = (image[m] & IMGMASK) - IMGMAX;
ybox = (image[m] >> IMGBITS & IMGMASK) - IMGMAX;
zbox = (image[m] >> IMG2BITS) - IMGMAX;
for (ifield = 1; ifield < nfield; ifield++) {
switch (fieldtype[ifield]) {
case X:
x[m][0] = xfield(i,ifield);
break;
case Y:
x[m][1] = yfield(i,ifield);
break;
case Z:
x[m][2] = zfield(i,ifield);
break;
case VX:
v[m][0] = fields[i][ifield];
break;
case Q:
q[m] = fields[i][ifield];
break;
case VY:
v[m][1] = fields[i][ifield];
break;
case VZ:
v[m][2] = fields[i][ifield];
break;
case IX:
xbox = static_cast<int> (fields[i][ifield]);
break;
case IY:
ybox = static_cast<int> (fields[i][ifield]);
break;
case IZ:
zbox = static_cast<int> (fields[i][ifield]);
break;
case FX:
f[m][0] = fields[i][ifield];
break;
case FY:
f[m][1] = fields[i][ifield];
break;
case FZ:
f[m][2] = fields[i][ifield];
break;
}
}
if (!wrapped) xbox = ybox = zbox = 0;
image[m] = ((imageint) (xbox + IMGMAX) & IMGMASK) |
(((imageint) (ybox + IMGMAX) & IMGMASK) << IMGBITS) |
(((imageint) (zbox + IMGMAX) & IMGMASK) << IMG2BITS);
}
}
if (trimflag) {
AtomVec *avec = atom->avec;
int i = 0;
while (i < nlocal) {
if (!updateflag[i]) {
avec->copy(nlocal-1,i,1);
updateflag[i] = updateflag[nlocal-1];
nlocal--;
ntrim++;
} else i++;
}
atom->nlocal = nlocal;
bigint nblocal = atom->nlocal;
MPI_Allreduce(&nblocal,&atom->natoms,1,MPI_LMP_BIGINT,MPI_SUM,world);
}
if (addflag == NOADD) {
memory->destroy(updateflag);
memory->destroy(newflag);
return;
}
int tflag = 0;
for (ifield = 0; ifield < nfield; ifield++)
if (fieldtype[ifield] == TYPE) tflag = 1;
if (!tflag)
error->all(FLERR,"Cannot add atoms if dump file does not store atom type");
int nlocal_previous = atom->nlocal;
double one[3];
for (i = 0; i < nnew; i++) {
if (!newflag[i]) continue;
itype = 0;
one[0] = one[1] = one[2] = 0.0;
for (ifield = 1; ifield < nfield; ifield++) {
switch (fieldtype[ifield]) {
case TYPE:
itype = static_cast<int> (fields[i][ifield]);
break;
case X:
one[0] = xfield(i,ifield);
break;
case Y:
one[1] = yfield(i,ifield);
break;
case Z:
one[2] = zfield(i,ifield);
break;
}
}
m = atom->nlocal;
atom->avec->create_atom(itype,one);
nadd++;
tag = atom->tag;
v = atom->v;
q = atom->q;
image = atom->image;
xbox = ybox = zbox = 0;
for (ifield = 0; ifield < nfield; ifield++) {
switch (fieldtype[ifield]) {
case ID:
if (addflag == KEEPADD)
tag[m] = static_cast<tagint> (fields[i][ifield]);
break;
case VX:
v[m][0] = fields[i][ifield];
break;
case VY:
v[m][1] = fields[i][ifield];
break;
case VZ:
v[m][2] = fields[i][ifield];
break;
case Q:
q[m] = fields[i][ifield];
break;
case IX:
xbox = static_cast<int> (fields[i][ifield]);
break;
case IY:
ybox = static_cast<int> (fields[i][ifield]);
break;
case IZ:
zbox = static_cast<int> (fields[i][ifield]);
break;
}
image[m] = ((imageint) (xbox + IMGMAX) & IMGMASK) |
(((imageint) (ybox + IMGMAX) & IMGMASK) << IMGBITS) |
(((imageint) (zbox + IMGMAX) & IMGMASK) << IMG2BITS);
}
}
if (addflag == YESADD || addflag == KEEPADD) {
bigint nblocal = atom->nlocal;
MPI_Allreduce(&nblocal,&atom->natoms,1,MPI_LMP_BIGINT,MPI_SUM,world);
}
if (addflag == YESADD) {
if (atom->natoms < 0 || atom->natoms >= MAXBIGINT)
error->all(FLERR,"Too many total atoms");
if (atom->tag_enable) atom->tag_extend();
}
atom->data_fix_compute_variable(nlocal_previous,atom->nlocal);
memory->destroy(updateflag);
memory->destroy(newflag);
}
void ReadDump::migrate_old_atoms()
{
tagint *tag = atom->tag;
int nlocal = atom->nlocal;
int *procassign;
memory->create(procassign,nlocal,"read_dump:procassign");
for (int i = 0; i < nlocal; i++)
procassign[i] = tag[i] % nprocs;
Irregular *irregular = new Irregular(lmp);
irregular->migrate_atoms(1,1,procassign);
delete irregular;
memory->destroy(procassign);
}
void ReadDump::migrate_new_atoms()
{
tagint mtag;
int *procassign;
double **newfields;
memory->create(procassign,nnew,"read_dump:procassign");
for (int i = 0; i < nnew; i++) {
mtag = static_cast<tagint> (fields[i][0]);
procassign[i] = mtag % nprocs;
}
Irregular *irregular = new Irregular(lmp);
int nrecv = irregular->create_data(nnew,procassign,1);
int newmaxnew = MAX(nrecv,maxnew);
newmaxnew = MAX(newmaxnew,1); memory->create(newfields,newmaxnew,nfield,"read_dump:newfields");
irregular->exchange_data((char *) &fields[0][0],nfield*sizeof(double),
(char *) &newfields[0][0]);
irregular->destroy_data();
delete irregular;
memory->destroy(fields);
memory->destroy(procassign);
fields = newfields;
maxnew = newmaxnew;
nnew = nrecv;
}
void ReadDump::migrate_atoms_by_coords()
{
double **x = atom->x;
imageint *image = atom->image;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) domain->remap(x[i],image[i]);
if (triclinic) domain->x2lamda(atom->nlocal);
domain->reset_box();
Irregular *irregular = new Irregular(lmp);
irregular->migrate_atoms(1);
delete irregular;
if (triclinic) domain->lamda2x(atom->nlocal);
}
int ReadDump::fields_and_keywords(int narg, char **arg)
{
fieldtype = new int[narg+2];
fieldlabel = new char*[narg+2];
int iarg;
for (iarg = 0; iarg < narg; iarg++)
if (strcmp(arg[iarg],"add") == 0)
if (iarg < narg-1 && (strcmp(arg[iarg+1],"yes") == 0 ||
strcmp(arg[iarg+1],"keep") == 0)) break;
nfield = 0;
fieldtype[nfield++] = ID;
if (iarg < narg) fieldtype[nfield++] = TYPE;
iarg = 0;
while (iarg < narg) {
int type = whichtype(arg[iarg]);
if (type < 0) break;
if (type == Q && !atom->q_flag)
error->all(FLERR,"Read dump of atom property that isn't allocated");
fieldtype[nfield++] = type;
iarg++;
}
if (fieldtype[nfield-1] == ID || fieldtype[nfield-1] == TYPE)
error->all(FLERR,"Illegal read_dump command");
if (dimension == 2) {
for (int i = 0; i < nfield; i++)
if (fieldtype[i] == Z || fieldtype[i] == VZ ||
fieldtype[i] == IZ || fieldtype[i] == FZ)
error->all(FLERR,"Illegal read_dump command");
}
for (int i = 0; i < nfield; i++)
for (int j = i+1; j < nfield; j++)
if (fieldtype[i] == fieldtype[j])
error->all(FLERR,"Duplicate fields in read_dump command");
multiproc_nfile = 0;
boxflag = 1;
replaceflag = 1;
purgeflag = 0;
trimflag = 0;
addflag = NOADD;
for (int i = 0; i < nfield; i++) fieldlabel[i] = NULL;
scaleflag = 0;
wrapflag = 1;
while (iarg < narg) {
if (strcmp(arg[iarg],"nfile") == 0) {
if (iarg+2 > narg) error->all(FLERR,"Illegal read_dump command");
multiproc_nfile = force->inumeric(FLERR,arg[iarg+1]);
iarg += 2;
} else if (strcmp(arg[iarg],"box") == 0) {
if (iarg+2 > narg) error->all(FLERR,"Illegal read_dump command");
if (strcmp(arg[iarg+1],"yes") == 0) boxflag = 1;
else if (strcmp(arg[iarg+1],"no") == 0) boxflag = 0;
else error->all(FLERR,"Illegal read_dump command");
iarg += 2;
} else if (strcmp(arg[iarg],"replace") == 0) {
if (iarg+2 > narg) error->all(FLERR,"Illegal read_dump command");
if (strcmp(arg[iarg+1],"yes") == 0) replaceflag = 1;
else if (strcmp(arg[iarg+1],"no") == 0) replaceflag = 0;
else error->all(FLERR,"Illegal read_dump command");
iarg += 2;
} else if (strcmp(arg[iarg],"purge") == 0) {
if (iarg+2 > narg) error->all(FLERR,"Illegal read_dump command");
if (strcmp(arg[iarg+1],"yes") == 0) purgeflag = 1;
else if (strcmp(arg[iarg+1],"no") == 0) purgeflag = 0;
else error->all(FLERR,"Illegal read_dump command");
iarg += 2;
} else if (strcmp(arg[iarg],"trim") == 0) {
if (iarg+2 > narg) error->all(FLERR,"Illegal read_dump command");
if (strcmp(arg[iarg+1],"yes") == 0) trimflag = 1;
else if (strcmp(arg[iarg+1],"no") == 0) trimflag = 0;
else error->all(FLERR,"Illegal read_dump command");
iarg += 2;
} else if (strcmp(arg[iarg],"add") == 0) {
if (iarg+2 > narg) error->all(FLERR,"Illegal read_dump command");
if (strcmp(arg[iarg+1],"yes") == 0) addflag = YESADD;
else if (strcmp(arg[iarg+1],"no") == 0) addflag = NOADD;
else if (strcmp(arg[iarg+1],"keep") == 0) addflag = KEEPADD;
else error->all(FLERR,"Illegal read_dump command");
iarg += 2;
} else if (strcmp(arg[iarg],"label") == 0) {
if (iarg+3 > narg) error->all(FLERR,"Illegal read_dump command");
int type = whichtype(arg[iarg+1]);
int i;
for (i = 0; i < nfield; i++)
if (type == fieldtype[i]) break;
if (i == nfield) error->all(FLERR,"Illegal read_dump command");
int n = strlen(arg[iarg+2]) + 1;
fieldlabel[i] = new char[n];
strcpy(fieldlabel[i],arg[iarg+2]);
iarg += 3;
} else if (strcmp(arg[iarg],"scaled") == 0) {
if (iarg+2 > narg) error->all(FLERR,"Illegal read_dump command");
if (strcmp(arg[iarg+1],"yes") == 0) scaleflag = 1;
else if (strcmp(arg[iarg+1],"no") == 0) scaleflag = 0;
else error->all(FLERR,"Illegal read_dump command");
iarg += 2;
} else if (strcmp(arg[iarg],"wrapped") == 0) {
if (iarg+2 > narg) error->all(FLERR,"Illegal read_dump command");
if (strcmp(arg[iarg+1],"yes") == 0) wrapflag = 1;
else if (strcmp(arg[iarg+1],"no") == 0) wrapflag = 0;
else error->all(FLERR,"Illegal read_dump command");
iarg += 2;
} else if (strcmp(arg[iarg],"format") == 0) {
if (iarg+2 > narg) error->all(FLERR,"Illegal read_dump command");
delete [] readerstyle;
int n = strlen(arg[iarg+1]) + 1;
readerstyle = new char[n];
strcpy(readerstyle,arg[iarg+1]);
iarg += 2;
break;
} else error->all(FLERR,"Illegal read_dump command");
}
if (multiproc == 0 && multiproc_nfile)
error->all(FLERR,"Dump file is not a multi-proc file");
if (multiproc && multiproc_nfile == 0)
error->all(FLERR,"Dump file is a multi-proc file");
if (purgeflag && (replaceflag || trimflag))
error->all(FLERR,"If read_dump purges it cannot replace or trim");
if (addflag == KEEPADD && atom->tag_enable == 0)
error->all(FLERR,"Read_dump cannot use 'add keep' without atom IDs");
return narg-iarg;
}
int ReadDump::whichtype(char *str)
{
int type = -1;
if (strcmp(str,"id") == 0) type = ID;
else if (strcmp(str,"type") == 0) type = TYPE;
else if (strcmp(str,"x") == 0) type = X;
else if (strcmp(str,"y") == 0) type = Y;
else if (strcmp(str,"z") == 0) type = Z;
else if (strcmp(str,"vx") == 0) type = VX;
else if (strcmp(str,"vy") == 0) type = VY;
else if (strcmp(str,"vz") == 0) type = VZ;
else if (strcmp(str,"q") == 0) type = Q;
else if (strcmp(str,"ix") == 0) type = IX;
else if (strcmp(str,"iy") == 0) type = IY;
else if (strcmp(str,"iz") == 0) type = IZ;
else if (strcmp(str,"fx") == 0) type = FX;
else if (strcmp(str,"fy") == 0) type = FY;
else if (strcmp(str,"fz") == 0) type = FZ;
return type;
}
double ReadDump::xfield(int i, int j)
{
if (!scaled) return fields[i][j];
else if (!triclinic) return fields[i][j]*xprd + xlo;
else if (dimension == 2)
return xprd*fields[i][j] + xy*fields[i][yindex] + xlo;
return xprd*fields[i][j] + xy*fields[i][yindex] + xz*fields[i][zindex] + xlo;
}
double ReadDump::yfield(int i, int j)
{
if (!scaled) return fields[i][j];
else if (!triclinic) return fields[i][j]*yprd + ylo;
else if (dimension == 2) return yprd*fields[i][j] + ylo;
return yprd*fields[i][j] + yz*fields[i][zindex] + ylo;
}
double ReadDump::zfield(int i, int j)
{
if (!scaled) return fields[i][j];
return fields[i][j]*zprd + zlo;
}