Files
lammps/src/read_dump.cpp

866 lines
25 KiB
C++

/* ----------------------------------------------------------------------
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 (ARL)
------------------------------------------------------------------------- */
#include "lmptype.h"
#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);
dimension = domain->dimension;
triclinic = domain->triclinic;
nfiles = 0;
files = NULL;
nfield = 0;
fieldtype = NULL;
fieldlabel = NULL;
fields = NULL;
uflag = ucflag = ucflag_all = NULL;
reader = NULL;
}
/* ---------------------------------------------------------------------- */
ReadDump::~ReadDump()
{
for (int i = 0; i < nfiles; i++) delete [] files[i];
delete [] files;
for (int i = 0; i < nfield; i++) delete [] fieldlabel[i];
delete [] fieldlabel;
delete [] fieldtype;
memory->destroy(fields);
memory->destroy(uflag);
memory->destroy(ucflag);
memory->destroy(ucflag_all);
delete reader;
}
/* ---------------------------------------------------------------------- */
void ReadDump::command(int narg, char **arg)
{
if (narg < 2) error->all(FLERR,"Illegal read_dump command");
store_files(1,&arg[0]);
bigint nstep = ATOBIGINT(arg[1]);
fields_and_keywords(narg-2,&arg[2]);
setup_reader();
// find the snapshot and read/bcast/process header info
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);
// reset timestep to nstep
update->reset_timestep(nstep);
// counters
// read in the snapshot and reset system
if (me == 0 && screen)
fprintf(screen,"Reading snapshot from dump file ...\n");
bigint natoms_prev = atom->natoms;
atoms();
// NOTE: this logic is not yet right
if (me == 0) close();
// 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);
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",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);
}
}
}
/* ---------------------------------------------------------------------- */
void ReadDump::store_files(int nstr, char **str)
{
nfiles = nstr;
files = new char*[nfiles];
for (int i = 0; i < nfiles; i++) {
int n = strlen(str[i]) + 1;
files[i] = new char[n];
strcpy(files[i],str[i]);
}
}
/* ---------------------------------------------------------------------- */
void ReadDump::setup_reader()
{
// create reader class
// could make this a parent class and customize with other readers
if (format == NATIVE) reader = new ReadDumpNative(lmp);
// allocate snapshot field buffer
memory->create(fields,CHUNK,nfield,"read_dump:fields");
}
/* ----------------------------------------------------------------------
seek Nrequest timestep in one or more dump files
Nrequest can be a timestamp or -1 to match first step with exact = 0
if exact = 1, must find exactly Nrequest
if exact = 0, find first step >= Nrequest
return matching ntimestep or -1 if did not find a match
------------------------------------------------------------------------- */
bigint ReadDump::seek(bigint nrequest, int exact)
{
int ifile,eofflag;
bigint ntimestep;
if (me == 0) {
for (ifile = 0; ifile < nfiles; ifile++) {
ntimestep = -1;
open(files[ifile]);
reader->file(fp);
while (1) {
eofflag = reader->read_time(ntimestep);
if (eofflag) break;
if (ntimestep >= nrequest) break;
reader->skip();
}
if (ntimestep >= nrequest) break;
close();
}
currentfile = ifile;
if (ntimestep < nrequest) close();
if (ntimestep < nrequest) ntimestep = -1;
if (exact && ntimestep != nrequest) ntimestep = -1;
}
MPI_Bcast(&ntimestep,1,MPI_LMP_BIGINT,0,world);
return ntimestep;
}
/* ----------------------------------------------------------------------
find next matching snapshot in one or more dump files
Ncurrent = current timestep from last snapshot
Nstop = match no timestep bigger than Nstop
Nevery = only match timesteps that are a multiple of Nevery
Nskip = skip every this many timesteps
return matching ntimestep or -1 if did not find a match
------------------------------------------------------------------------- */
bigint ReadDump::next(bigint ncurrent, bigint nstop, int nevery, int nskip)
{
int ifile,eofflag;
bigint ntimestep;
// NOTE: this logic is not yet right
if (me == 0) {
for (ifile = currentfile; ifile < nfiles; ifile++) {
ntimestep = -1;
if (ifile != currentfile) open(files[ifile]);
reader->file(fp);
while (1) {
eofflag = reader->read_time(ntimestep);
if (eofflag) ntimestep = -1;
break;
}
if (ntimestep > ncurrent) break;
close();
}
currentfile = ifile;
}
MPI_Bcast(&ntimestep,1,MPI_LMP_BIGINT,0,world);
return ntimestep;
}
/* ----------------------------------------------------------------------
read and broadcast and store snapshot header info
set nsnapatoms = # of atoms in snapshot
set yindex,zindex
------------------------------------------------------------------------- */
void ReadDump::header(int fieldinfo)
{
int triclinic_snap;
int fieldflag,xflag,yflag,zflag;
if (me == 0)
nsnapatoms = reader->read_header(box,triclinic_snap,
fieldinfo,nfield,fieldtype,fieldlabel,
scaledflag,fieldflag,xflag,yflag,zflag);
MPI_Bcast(&nsnapatoms,1,MPI_LMP_BIGINT,0,world);
MPI_Bcast(&triclinic_snap,1,MPI_INT,0,world);
MPI_Bcast(&box[0][0],9,MPI_DOUBLE,0,world);
// local copy of snapshot box parameters
// used in xfield,yfield,zfield when converting dump atom to absolute coords
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_snap) {
xy = box[0][2];
xz = box[1][2];
yz = box[2][2];
}
// done if not checking fields
if (!fieldinfo) return;
MPI_Bcast(&fieldflag,1,MPI_INT,0,world);
MPI_Bcast(&xflag,1,MPI_INT,0,world);
MPI_Bcast(&yflag,1,MPI_INT,0,world);
MPI_Bcast(&zflag,1,MPI_INT,0,world);
// error check on current vs new box and fields
if ((triclinic_snap && !triclinic) ||
(!triclinic_snap && triclinic))
error->one(FLERR,"Read_dump triclinic status does not match simulation");
// error check field and scaling info
if (fieldflag < 0)
error->one(FLERR,"Read_dump field not found in dump file");
// set overall scaling of coordinates
// error if x,y,z scaling are 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
// set yindex,zindex = column index of Y and Z fields in fields array
// needed for unscaling to absolute coords in xfield(), yfield(), zfield()
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");
for (int i = 0; i < nfield; i++) {
if (fieldtype[i] == Y) yindex = i;
if (fieldtype[i] == Z) zindex = i;
}
}
}
/* ---------------------------------------------------------------------- */
void ReadDump::atoms()
{
// initialize counters
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()
// NOTE: this logic is sloppy
memory->destroy(uflag);
memory->destroy(ucflag);
memory->destroy(ucflag_all);
uflag = ucflag = ucflag_all = NULL;
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_atoms(nchunk,nfield,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();
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();
}
// overwrite simulation box with dump snapshot box if requested
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();
// would be OK to do this, except it prints out info
//comm->set_proc_grid();
domain->set_local_box();
}
// 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);
}
/* ----------------------------------------------------------------------
process arg list for dump file fields and optional keywords
------------------------------------------------------------------------- */
void ReadDump::fields_and_keywords(int narg, char **arg)
{
// per-field vectors, leave space for ID + TYPE
fieldtype = new int[narg+2];
fieldlabel = new char*[narg+2];
// add id and type fields as needed
// scan ahead to see if "add yes" keyword/value is used
// requires extra "type" field from from dump file
int iarg;
for (iarg = 0; 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 = 0;
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++;
}
// check for no fields
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 (fieldlabel[i] && strcmp(arg[iarg+1],fieldlabel[i]) == 0) 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) 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");
}
/* ----------------------------------------------------------------------
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()
{
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);
}
}
/* ----------------------------------------------------------------------
close current dump file
only called by proc 0
------------------------------------------------------------------------- */
void ReadDump::close()
{
if (compressed) pclose(fp);
else fclose(fp);
}