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

This commit is contained in:
sjplimp
2012-06-01 16:41:08 +00:00
parent e2f8449535
commit 75d99d30f5
6 changed files with 1173 additions and 17 deletions

View File

@ -402,7 +402,8 @@ void Atom::modify_params(int narg, char **arg)
else if (strcmp(arg[iarg+1],"hash") == 0) map_style = 2;
else error->all(FLERR,"Illegal atom_modify command");
if (domain->box_exist)
error->all(FLERR,"Atom_modify map command after simulation box is defined");
error->all(FLERR,
"Atom_modify map command after simulation box is defined");
iarg += 2;
} else if (strcmp(arg[iarg],"first") == 0) {
if (iarg+2 > narg) error->all(FLERR,"Illegal atom_modify command");
@ -1051,7 +1052,8 @@ void Atom::data_dihedrals(int n, char *buf)
atom4 <= 0 || atom4 > map_tag_max)
error->one(FLERR,"Invalid atom ID in Dihedrals section of data file");
if (itype <= 0 || itype > ndihedraltypes)
error->one(FLERR,"Invalid dihedral type in Dihedrals section of data file");
error->one(FLERR,
"Invalid dihedral type in Dihedrals section of data file");
if ((m = map(atom2)) >= 0) {
dihedral_type[m][num_dihedral[m]] = itype;
dihedral_atom1[m][num_dihedral[m]] = atom1;
@ -1110,7 +1112,8 @@ void Atom::data_impropers(int n, char *buf)
atom4 <= 0 || atom4 > map_tag_max)
error->one(FLERR,"Invalid atom ID in Impropers section of data file");
if (itype <= 0 || itype > nimpropertypes)
error->one(FLERR,"Invalid improper type in Impropers section of data file");
error->one(FLERR,
"Invalid improper type in Impropers section of data file");
if ((m = map(atom2)) >= 0) {
improper_type[m][num_improper[m]] = itype;
improper_atom1[m][num_improper[m]] = atom1;
@ -1177,7 +1180,8 @@ void Atom::set_mass(const char *str)
int n = sscanf(str,"%d %lg",&itype,&mass_one);
if (n != 2) error->all(FLERR,"Invalid mass line in data file");
if (itype < 1 || itype > ntypes) error->all(FLERR,"Invalid type for mass set");
if (itype < 1 || itype > ntypes)
error->all(FLERR,"Invalid type for mass set");
mass[itype] = mass_one;
mass_setflag[itype] = 1;
@ -1193,7 +1197,8 @@ void Atom::set_mass(const char *str)
void Atom::set_mass(int itype, double value)
{
if (mass == NULL) error->all(FLERR,"Cannot set mass for this atom style");
if (itype < 1 || itype > ntypes) error->all(FLERR,"Invalid type for mass set");
if (itype < 1 || itype > ntypes)
error->all(FLERR,"Invalid type for mass set");
mass[itype] = value;
mass_setflag[itype] = 1;

View File

@ -192,7 +192,6 @@ void CreateAtoms::command(int narg, char **arg)
// reset simulation now that more atoms are defined
// add tags for newly created atoms if possible
// if global map exists, reset it
// if a molecular system, set nspecial to 0 for new atoms
if (atom->natoms > MAXTAGINT) atom->tag_enable = 0;
if (atom->natoms <= MAXTAGINT) atom->tag_extend();
@ -202,14 +201,18 @@ void CreateAtoms::command(int narg, char **arg)
atom->map_init();
atom->map_set();
}
if (atom->molecular) {
int **nspecial = atom->nspecial;
for (int i = nlocal_previous; i < atom->nlocal; i++) {
nspecial[i][0] = 0;
nspecial[i][1] = 0;
nspecial[i][2] = 0;
}
}
// if a molecular system, set nspecial to 0 for new atoms
// NOTE: 31May12, don't think this is needed, avec->create_atom() does it
//if (atom->molecular) {
// int **nspecial = atom->nspecial;
// for (int i = nlocal_previous; i < atom->nlocal; i++) {
// nspecial[i][0] = 0;
// nspecial[i][1] = 0;
// nspecial[i][2] = 0;
// }
//}
}
/* ----------------------------------------------------------------------

672
src/read_dump.cpp Normal file
View File

@ -0,0 +1,672 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Timothy Sirk (U Vermont)
------------------------------------------------------------------------- */
#include "mpi.h"
#include "string.h"
#include "stdlib.h"
#include "read_dump.h"
#include "read_dump_native.h"
#include "atom.h"
#include "atom_vec.h"
#include "update.h"
#include "domain.h"
#include "comm.h"
#include "irregular.h"
#include "error.h"
#include "memory.h"
using namespace LAMMPS_NS;
#define CHUNK 1024
#define EPSILON 1.0e-6
enum{ID,TYPE,X,Y,Z,VX,VY,VZ,IX,IY,IZ};
enum{UNSET,UNSCALED,SCALED};
enum{NATIVE};
/* ---------------------------------------------------------------------- */
ReadDump::ReadDump(LAMMPS *lmp) : Pointers(lmp)
{
MPI_Comm_rank(world,&me);
MPI_Comm_size(world,&nprocs);
}
/* ---------------------------------------------------------------------- */
void ReadDump::command(int narg, char **arg)
{
if (narg < 2) error->all(FLERR,"Illegal read_dump command");
nstep = ATOBIGINT(arg[1]);
// per-field vectors
int firstfield = 2;
fieldtype = new int[narg];
fieldlabel = new char*[narg];
// scan ahead to see if "add yes" keyword/value is used
// requires extra "type" field from from dump file
// add id and type fields as needed
int iarg;
for (iarg = firstfield; iarg < narg; iarg++)
if (strcmp(arg[iarg],"add") == 0)
if (iarg < narg-1 && strcmp(arg[iarg+1],"yes") == 0) break;
nfield = 0;
fieldtype[nfield++] = ID;
if (iarg < narg) fieldtype[nfield++] = TYPE;
// parse fields
iarg = firstfield;
while (iarg < narg) {
if (strcmp(arg[iarg],"x") == 0) fieldtype[nfield++] = X;
else if (strcmp(arg[iarg],"y") == 0) fieldtype[nfield++] = Y;
else if (strcmp(arg[iarg],"z") == 0) fieldtype[nfield++] = Z;
else if (strcmp(arg[iarg],"vx") == 0) fieldtype[nfield++] = VX;
else if (strcmp(arg[iarg],"vy") == 0) fieldtype[nfield++] = VY;
else if (strcmp(arg[iarg],"vz") == 0) fieldtype[nfield++] = VZ;
else if (strcmp(arg[iarg],"ix") == 0) fieldtype[nfield++] = IX;
else if (strcmp(arg[iarg],"iy") == 0) fieldtype[nfield++] = IY;
else if (strcmp(arg[iarg],"iz") == 0) fieldtype[nfield++] = IZ;
else break;
iarg++;
}
dimension = domain->dimension;
triclinic = domain->triclinic;
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)
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");
// parse optional args
boxflag = 1;
replaceflag = 1;
purgeflag = 0;
trimflag = 0;
addflag = 0;
for (int i = 0; i < nfield; i++) fieldlabel[i] = NULL;
scaledflag = UNSCALED;
format = NATIVE;
while (iarg < narg) {
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 = 1;
else if (strcmp(arg[iarg+1],"no") == 0) addflag = 0;
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 i;
for (i = 0; i < nfield; i++)
if (strcmp(arg[firstfield+i],arg[iarg+1]) == 0) break;
if (i == nfield) error->all(FLERR,"Illegal read_dump command");
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) scaledflag = SCALED;
else if (strcmp(arg[iarg+1],"no") == 0) scaledflag = UNSCALED;
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");
if (strcmp(arg[iarg+1],"native") == 0) format = NATIVE;
else error->all(FLERR,"Illegal read_dump command");
iarg += 2;
} else error->all(FLERR,"Illegal read_dump command");
}
if (purgeflag && (replaceflag || trimflag))
error->all(FLERR,"If read_dump purges it cannot replace or trim");
// allocate snapshot field buffer
memory->create(fields,CHUNK,nfield,"read_dump:fields");
// create reader class
// could make this a parent class and customize with other readers
if (format == NATIVE) reader = new ReadDumpNative(lmp);
// proc 0 opens dump file and scans to correct snapshot
// after scan these values are set, so Bcast them:
// nsnapatoms, box[3][3], scaled
// NOTE: fieldlabel is just ptrs to input args in read_dump command
// will not persist if want to use labels in rerun() command
if (me == 0) {
if (screen) fprintf(screen,"Scanning dump file ...\n");
open(arg[0]);
reader->init(fp);
reader->scan(nstep,nfield,fieldtype,fieldlabel,scaledflag,
nsnapatoms,box,scaled);
}
MPI_Bcast(&nsnapatoms,1,MPI_LMP_BIGINT,0,world);
MPI_Bcast(&box[0][0],9,MPI_DOUBLE,0,world);
MPI_Bcast(&scaled,1,MPI_INT,0,world);
// for scaled coords and triclinic box:
// yindex,zindex = index of Y and Z fields
// already known to exist because checked in scan()
// needed for unscaling to absolute coords in xfield(), yfield(), zfield()
if (scaled == SCALED && triclinic) {
for (int i = 0; i < nfield; i++) {
if (fieldtype[i] == Y) yindex = i;
if (fieldtype[i] == Z) zindex = i;
}
}
// make local copy of snapshot box params
xlo = box[0][0];
xhi = box[0][1];
ylo = box[1][0];
yhi = box[1][1];
zlo = box[2][0];
zhi = box[2][1];
xprd = xhi - xlo;
yprd = yhi - ylo;
zprd = zhi - zlo;
if (triclinic) {
xy = box[0][2];
xz = box[1][2];
yz = box[2][2];
}
// reset timestep to nstep
char *tstr[1];
char str[32];
sprintf(str,BIGINT_FORMAT,nstep);
tstr[0] = str;
update->reset_timestep(1,tstr);
// reset simulation box from snapshot box parameters if requested
// do it now, so if adding atoms, procs will have correct sub-domains
// call domain->reset_box() later,
// since can't shrink wrap until atom coords change and atoms are added
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();
domain->set_local_box();
}
// read in the snapshot
if (me == 0)
if (screen) fprintf(screen,"Reading snapshot from dump file ...\n");
// counters
bigint natoms_prev = atom->natoms;
npurge = nreplace = ntrim = nadd = 0;
// if purgeflag set, delete all current atoms
if (purgeflag) {
if (atom->map_style) atom->map_clear();
npurge = atom->nlocal;
atom->nlocal = atom->nghost = 0;
atom->natoms = 0;
}
// to match existing atoms to dump atoms:
// must build map if not a molecular system
int mapflag = 0;
if (atom->map_style == 0) {
mapflag = 1;
atom->map_style = 1;
atom->map_init();
atom->map_set();
}
// uflag[i] = 1 for each owned atom appearing in dump
// ucflag = similar flag for each chunk atom, used in process_atoms()
int nlocal = atom->nlocal;
memory->create(uflag,nlocal,"read_dump:uflag");
for (int i = 0; i < nlocal; i++) uflag[i] = 0;
memory->create(ucflag,CHUNK,"read_dump:ucflag");
memory->create(ucflag_all,CHUNK,"read_dump:ucflag");
// read, broadcast, and process atoms from snapshot in chunks
addproc = -1;
int nchunk;
bigint nread = 0;
while (nread < nsnapatoms) {
nchunk = MIN(nsnapatoms-nread,CHUNK);
if (me == 0) reader->read(nchunk,fields);
MPI_Bcast(&fields[0][0],nchunk*nfield,MPI_DOUBLE,0,world);
process_atoms(nchunk);
nread += nchunk;
}
// if addflag set, add tags to new atoms if possible
if (addflag) {
bigint nblocal = atom->nlocal;
MPI_Allreduce(&nblocal,&atom->natoms,1,MPI_LMP_BIGINT,MPI_SUM,world);
if (atom->natoms < 0 || atom->natoms > MAXBIGINT)
error->all(FLERR,"Too many total atoms");
if (atom->natoms > MAXTAGINT) atom->tag_enable = 0;
if (atom->natoms <= MAXTAGINT) atom->tag_extend();
}
// if trimflag set, delete atoms not replaced by snapshot atoms
if (trimflag) {
delete_atoms(uflag);
bigint nblocal = atom->nlocal;
MPI_Allreduce(&nblocal,&atom->natoms,1,MPI_LMP_BIGINT,MPI_SUM,world);
}
// delete atom map if created it above
// else reinitialize map for current atoms
// do this before migrating atoms to new procs via Irregular
if (mapflag) {
atom->map_delete();
atom->map_style = 0;
} else {
atom->nghost = 0;
atom->map_init();
atom->map_set();
}
// close dump file
if (me == 0) {
if (compressed) pclose(fp);
else fclose(fp);
}
// move atoms back inside simulation box and to new processors
// use remap() instead of pbc() in case atoms moved a long distance
// adjust image flags of all atoms (old and new) based on current box
// use irregular() in case atoms moved a long distance
double **x = atom->x;
int *image = atom->image;
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();
delete irregular;
if (triclinic) domain->lamda2x(atom->nlocal);
domain->print_box(" ");
// clean up
delete reader;
delete [] fieldtype;
delete [] fieldlabel;
memory->destroy(fields);
memory->destroy(uflag);
memory->destroy(ucflag);
memory->destroy(ucflag_all);
// print out stats
bigint npurge_all,nreplace_all,ntrim_all,nadd_all;
bigint tmp;
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);
if (me == 0) {
if (screen) {
fprintf(screen," " BIGINT_FORMAT " atoms before read\n",natoms_prev);
fprintf(screen," " BIGINT_FORMAT " atoms in snapshot\n",nsnapatoms);
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",nsnapatoms);
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);
}
}
}
/* ----------------------------------------------------------------------
process each of N atoms in chunk read from dump file
if in replace mode and atom ID matches current atom,
overwrite atom info with fields from dump file
if in add mode and atom ID does not match any current atom,
create new atom with dump file field values,
and assign to a proc in round-robin manner
use round-robin method, b/c atom coords may not be inside simulation box
------------------------------------------------------------------------- */
void ReadDump::process_atoms(int n)
{
int i,m,ifield,itype;
int xbox,ybox,zbox;
double **x = atom->x;
double **v = atom->v;
int *image = atom->image;
int nlocal = atom->nlocal;
for (i = 0; i < n; i++) {
ucflag[i] = 0;
// map() call is invalid if purged all atoms
// setting m = -1 forces new atom not to match
if (!purgeflag) m = atom->map(static_cast<int> (fields[i][0]));
else m = -1;
if (m < 0 || m >= nlocal) continue;
ucflag[i] = 1;
uflag[m] = 1;
if (replaceflag) {
nreplace++;
// current image flags
xbox = (image[m] & 1023) - 512;
ybox = (image[m] >> 10 & 1023) - 512;
zbox = (image[m] >> 20) - 512;
// overwrite atom attributes with field info
// start from field 1 since 0 = id, 1 will be skipped if type
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 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;
}
}
// replace image flag in case changed by ix,iy,iz fields
image[m] = (xbox << 20) | (ybox << 10) | zbox;
}
}
// create any atoms in chunk that no processor owned
// add atoms in round-robin sequence on processors
// cannot do it geometrically b/c dump coords may not be in simulation box
if (!addflag) return;
MPI_Allreduce(ucflag,ucflag_all,n,MPI_INT,MPI_SUM,world);
double lamda[3],one[3];
double *coord;
for (i = 0; i < n; i++) {
if (ucflag_all[i]) continue;
// each processor adds every Pth atom
addproc++;
if (addproc == nprocs) addproc = 0;
if (addproc != me) continue;
// create type and coord fields from dump file
// coord = 0.0 unless corresponding dump file field was specified
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;
}
}
// create the atom on proc that owns it
// reset v,image ptrs in case they are reallocated
atom->avec->create_atom(itype,one);
nadd++;
v = atom->v;
image = atom->image;
m = atom->nlocal;
// set atom attributes from other dump file fields
// xyzbox = 512 is default value set by create_atom()
xbox = ybox = zbox = 512;
for (ifield = 1; ifield < nfield; ifield++) {
switch (fieldtype[ifield]) {
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 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;
}
// replace image flag in case changed by ix,iy,iz fields
image[m] = (xbox << 20) | (ybox << 10) | zbox;
}
}
}
/* ----------------------------------------------------------------------
delete atoms not flagged as replaced by dump atoms
------------------------------------------------------------------------- */
void ReadDump::delete_atoms(int *uflag)
{
AtomVec *avec = atom->avec;
int nlocal = atom->nlocal;
int i = 0;
while (i < nlocal) {
if (uflag[i] == 0) {
avec->copy(nlocal-1,i,1);
uflag[i] = uflag[nlocal-1];
nlocal--;
ntrim++;
} else i++;
}
atom->nlocal = nlocal;
}
/* ----------------------------------------------------------------------
convert XYZ fields in dump file into absolute, unscaled coordinates
depends on scaled vs unscaled and triclinic vs orthogonal
does not depend on wrapped vs unwrapped
------------------------------------------------------------------------- */
double ReadDump::xfield(int i, int j)
{
if (scaled == UNSCALED) 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 == UNSCALED) 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 == UNSCALED) return fields[i][j];
return fields[i][j]*zprd + zlo;
}
/* ----------------------------------------------------------------------
proc 0 opens dump file
test if gzipped
------------------------------------------------------------------------- */
void ReadDump::open(char *file)
{
compressed = 0;
char *suffix = file + strlen(file) - 3;
if (suffix > file && strcmp(suffix,".gz") == 0) compressed = 1;
if (!compressed) fp = fopen(file,"r");
else {
#ifdef LAMMPS_GZIP
char gunzip[128];
sprintf(gunzip,"gunzip -c %s",file);
fp = popen(gunzip,"r");
#else
error->one(FLERR,"Cannot open gzipped file");
#endif
}
if (fp == NULL) {
char str[128];
sprintf(str,"Cannot open file %s",file);
error->one(FLERR,str);
}
}

84
src/read_dump.h Normal file
View File

@ -0,0 +1,84 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
Contributed by Timothy Sirk
------------------------------------------------------------------------- */
#ifdef COMMAND_CLASS
CommandStyle(read_dump,ReadDump)
#else
#ifndef LMP_READ_DUMP_H
#define LMP_READ_DUMP_H
#include "stdio.h"
#include "pointers.h"
namespace LAMMPS_NS {
class ReadDump : protected Pointers {
public:
ReadDump(class LAMMPS *);
~ReadDump() {}
void command(int, char **);
private:
int me,nprocs;
FILE *fp;
int dimension;
int triclinic;
bigint nstep; // timestep to find in dump file
int boxflag; // use dump file box params
int replaceflag,addflag; // flags for processing dump snapshot atoms
int trimflag,purgeflag;
int scaledflag; // user setting for coordinate scaling
int scaled; // actual setting for coordinate scaling
int format; // style of dump file
int compressed; // flag for dump file compression
int nfield; // # of fields to extract from dump file
int *fieldtype; // type of each field = X,VY,IZ,etc
char **fieldlabel; // user specified label for field
double **fields; // per-atom field values
double box[3][3]; // dump file box parameters
double xlo,xhi,ylo,yhi,zlo,zhi,xy,xz,yz;
double xprd,yprd,zprd;
bigint nsnapatoms; // # of atoms in dump file shapshot
int npurge,nreplace,ntrim,nadd; // stats on processed atoms
int addproc; // proc that should add next atom
int yindex,zindex; // field index for Y,Z coords
int *uflag; // set to 1 if snapshot atom matches owned atom
int *ucflag,*ucflag_all; // set to 1 if snapshot chunk atom was processed
class ReadDumpNative *reader; // class that reads native dump file
void process_atoms(int);
void delete_atoms(int *);
double xfield(int, int);
double yfield(int, int);
double zfield(int, int);
void open(char *);
};
}
#endif
#endif

341
src/read_dump_native.cpp Normal file
View File

@ -0,0 +1,341 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "string.h"
#include "stdlib.h"
#include "read_dump_native.h"
#include "atom.h"
#include "domain.h"
#include "error.h"
using namespace LAMMPS_NS;
#define MAXLINE 1024 // max line length in dump file
enum{ID,TYPE,X,Y,Z,VX,VY,VZ,IX,IY,IZ};
enum{UNSET,UNSCALED,SCALED};
/* ---------------------------------------------------------------------- */
ReadDumpNative::ReadDumpNative(LAMMPS *lmp) : Pointers(lmp)
{
dimension = domain->dimension;
triclinic = domain->triclinic;
line = new char[MAXLINE];
words = NULL;
fieldindex = NULL;
}
/* ---------------------------------------------------------------------- */
ReadDumpNative::~ReadDumpNative()
{
delete [] line;
delete [] words;
delete [] fieldindex;
}
/* ---------------------------------------------------------------------- */
void ReadDumpNative::init(FILE *fpcaller)
{
fp = fpcaller;
}
/* ----------------------------------------------------------------------
proc 0 scans dump file until reaching snapshot with timestamp = Nstep
extract natoms and box bounds from snapshot
set fieldindex for specified fields and overall scaled setting
error check on current vs new box and fields
NOTE: error checking should maybe be moved to parent
------------------------------------------------------------------------- */
void ReadDumpNative::scan(bigint nstep,
int nfield_caller, int *fieldtype,
char **fieldlabel, int scaledflag,
bigint &natoms, double box[3][3], int &scaled)
{
int nchunk,triclinic_snap,s_index,u_index,su_index;
bigint ntimestep,nremain;
char *bc,*names;
nfield = nfield_caller;
read_lines(1);
while (1) {
if (strstr(line,"ITEM: TIMESTEP") != line)
error->one(FLERR,"Incorrectly formatted dump file");
read_lines(1);
sscanf(line,BIGINT_FORMAT,&ntimestep);
if (ntimestep > nstep)
error->one(FLERR,"Dump file does not contain requested snapshot");
read_lines(2);
sscanf(line,BIGINT_FORMAT,&natoms);
// skip snapshot
// invoke read_lines() in chunks no larger than MAXSMALLINT
if (ntimestep < nstep) {
read_lines(5);
nremain = natoms;
while (nremain) {
nchunk = MIN(nremain,MAXSMALLINT);
read_lines(nchunk);
nremain -= nchunk;
}
read_lines(1);
} else break;
}
// found correct snapshot
// read box size and boundary conditions
triclinic_snap = 0;
box[0][2] = box[1][2] = box[2][2] = 0.0;
read_lines(1);
bc = &line[strlen("ITEM: BOX BOUNDS ")];
if (bc[0] == 'x') {
triclinic_snap = 1;
bc = &bc[9];
}
char boundstr[9];
domain->boundary_string(boundstr);
if (strstr(bc,boundstr) != bc)
error->warning(FLERR,"Read_dump boundary flags do not match simulation");
read_lines(1);
if (!triclinic_snap) sscanf(line,"%lg %lg",&box[0][0],&box[0][1]);
else sscanf(line,"%lg %lg %lg",&box[0][0],&box[0][1],&box[0][2]);
read_lines(1);
if (!triclinic_snap) sscanf(line,"%lg %lg",&box[1][0],&box[1][1]);
else sscanf(line,"%lg %lg %lg",&box[1][0],&box[1][1],&box[1][2]);
read_lines(1);
if (!triclinic_snap) sscanf(line,"%lg %lg",&box[2][0],&box[2][1]);
else sscanf(line,"%lg %lg %lg",&box[2][0],&box[2][1],&box[2][2]);
// read ITEM: ATOMS line
// labels = column labels
read_lines(1);
names = &line[strlen("ITEM: ATOMS ")];
nwords = atom->count_words(names);
char **labels = new char*[nwords];
labels[0] = strtok(names," \t\n\r\f");
if (labels[0] == NULL)
error->one(FLERR,"Incorrect atom format in dump file");
for (int m = 1; m < nwords; m++) {
labels[m] = strtok(NULL," \t\n\r\f");
if (labels[m] == NULL)
error->one(FLERR,"Incorrect atom format in dump file");
}
// match each field with column
fieldindex = new int[nfield];
int xflag = UNSET;
int yflag = UNSET;
int zflag = UNSET;
for (int i = 0; i < nfield; i++) {
if (fieldlabel[i]) {
fieldindex[i] = find_label(fieldlabel[i],nwords,labels);
if (fieldtype[i] == X) xflag = scaledflag;
else if (fieldtype[i] == Y) yflag = scaledflag;
else if (fieldtype[i] == Z) zflag = scaledflag;
}
else if (fieldtype[i] == ID)
fieldindex[i] = find_label("id",nwords,labels);
else if (fieldtype[i] == TYPE)
fieldindex[i] = find_label("type",nwords,labels);
else if (fieldtype[i] == X) {
fieldindex[i] = find_label("x",nwords,labels);
xflag = UNSCALED;
if (fieldindex[i] < 0) {
fieldindex[i] = nwords;
s_index = find_label("xs",nwords,labels);
u_index = find_label("xu",nwords,labels);
su_index = find_label("xsu",nwords,labels);
if (s_index >= 0 && s_index < fieldindex[i]) {
fieldindex[i] = s_index;
xflag = SCALED;
}
if (u_index >= 0 && u_index < fieldindex[i]) {
fieldindex[i] = u_index;
xflag = UNSCALED;
}
if (su_index >= 0 && su_index < fieldindex[i]) {
fieldindex[i] = su_index;
xflag = SCALED;
}
}
if (fieldindex[i] == nwords) fieldindex[i] = -1;
} else if (fieldtype[i] == Y) {
fieldindex[i] = find_label("y",nwords,labels);
yflag = UNSCALED;
if (fieldindex[i] < 0) {
fieldindex[i] = nwords;
s_index = find_label("ys",nwords,labels);
u_index = find_label("yu",nwords,labels);
su_index = find_label("ysu",nwords,labels);
if (s_index >= 0 && s_index < fieldindex[i]) {
fieldindex[i] = s_index;
yflag = SCALED;
}
if (u_index >= 0 && u_index < fieldindex[i]) {
fieldindex[i] = u_index;
yflag = UNSCALED;
}
if (su_index >= 0 && su_index < fieldindex[i]) {
fieldindex[i] = su_index;
yflag = SCALED;
}
}
if (fieldindex[i] == nwords) fieldindex[i] = -1;
} else if (fieldtype[i] == Z) {
fieldindex[i] = find_label("z",nwords,labels);
zflag = UNSCALED;
if (fieldindex[i] < 0) {
fieldindex[i] = nwords;
s_index = find_label("zs",nwords,labels);
u_index = find_label("zu",nwords,labels);
su_index = find_label("zsu",nwords,labels);
if (s_index >= 0 && s_index < fieldindex[i]) {
fieldindex[i] = s_index;
zflag = SCALED;
}
if (u_index >= 0 && u_index < fieldindex[i]) {
fieldindex[i] = u_index;
zflag = UNSCALED;
}
if (su_index >= 0 && su_index < fieldindex[i]) {
fieldindex[i] = su_index;
zflag = SCALED;
}
}
if (fieldindex[i] == nwords) fieldindex[i] = -1;
} else if (fieldtype[i] == VX)
fieldindex[i] = find_label("vx",nwords,labels);
else if (fieldtype[i] == VY)
fieldindex[i] = find_label("vy",nwords,labels);
else if (fieldtype[i] == VZ)
fieldindex[i] = find_label("vz",nwords,labels);
else if (fieldtype[i] == IX)
fieldindex[i] = find_label("ix",nwords,labels);
else if (fieldtype[i] == IY)
fieldindex[i] = find_label("iy",nwords,labels);
else if (fieldtype[i] == IZ)
fieldindex[i] = find_label("iz",nwords,labels);
}
// error checks
if ((triclinic_snap && !triclinic) ||
(!triclinic_snap && triclinic))
error->one(FLERR,"Read_dump triclinic setting does not match simulation");
for (int i = 0; i < nfield; i++)
if (fieldindex[i] < 0)
error->one(FLERR,"Read_dump field not found in dump file");
// set overall scaling of coordinates
// error if x,y,z scaling is not the same
scaled = MAX(xflag,yflag);
scaled = MAX(zflag,scaled);
if ((xflag != UNSET && xflag != scaled) ||
(yflag != UNSET && yflag != scaled) ||
(zflag != UNSET && zflag != scaled))
error->one(FLERR,"Read_dump x,y,z fields do not have consistent scaling");
// scaled, triclinic coords require all 3 x,y,z fields to perform unscaling
if (scaled == SCALED && triclinic) {
int flag = 0;
if (xflag != scaled) flag = 1;
if (yflag != scaled) flag = 1;
if (dimension == 3 && zflag != scaled) flag = 1;
if (flag)
error->one(FLERR,"All read_dump x,y,z fields must be specified for "
"scaled, triclinic coords");
}
delete [] labels;
// create vector of word ptrs for future parsing of per-atom lines
words = new char*[nwords];
}
/* ----------------------------------------------------------------------
proc 0 reads N atom lines from dump file
stores appropriate values in fields array
------------------------------------------------------------------------- */
void ReadDumpNative::read(int n, double **fields)
{
int i,m;
char *eof;
for (int i = 0; i < n; i++) {
eof = fgets(line,MAXLINE,fp);
if (eof == NULL) error->one(FLERR,"Unexpected end of dump file");
// tokenize the line
words[0] = strtok(line," \t\n\r\f");
for (m = 1; m < nwords; m++)
words[m] = strtok(NULL," \t\n\r\f");
// convert selected fields to floats
for (m = 0; m < nfield; m++)
fields[i][m] = atof(words[fieldindex[m]]);
}
}
/* ----------------------------------------------------------------------
match label to any of N labels
return index of match or -1 if no match
------------------------------------------------------------------------- */
int ReadDumpNative::find_label(const char *label, int n, char **labels)
{
for (int i = 0; i < n; i++)
if (strcmp(label,labels[i]) == 0) return i;
return -1;
}
/* ----------------------------------------------------------------------
proc 0 reads N lines from file
only last one is saved in line
------------------------------------------------------------------------- */
void ReadDumpNative::read_lines(int n)
{
char *eof;
for (int i = 0; i < n; i++) eof = fgets(line,MAXLINE,fp);
if (eof == NULL) error->one(FLERR,"Unexpected end of dump file");
}

51
src/read_dump_native.h Normal file
View File

@ -0,0 +1,51 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
Contributed by Timothy Sirk
------------------------------------------------------------------------- */
#ifndef LMP_READ_DUMP_NATIVE_H
#define LMP_READ_DUMP_NATIVE_H
#include "stdio.h"
#include "pointers.h"
namespace LAMMPS_NS {
class ReadDumpNative : protected Pointers {
public:
ReadDumpNative(class LAMMPS *);
~ReadDumpNative();
void init(FILE *);
void scan(bigint, int, int *, char **, int, bigint &, double [3][3], int &);
void read(int, double **);
private:
FILE *fp; // pointer to file opened by caller
char *line; // line read from dump file
int dimension;
int triclinic;
int nwords; // # of per-atom columns in dump file
char **words; // ptrs to words in parsed per-atom line
int nfield; // # of fields to extract for each atom
int *fieldindex; // index into words for each field
int find_label(const char *, int, char **);
void read_lines(int);
};
}
#endif