diff --git a/src/XTC/dump_xtc.h b/src/XTC/dump_xtc.h index 8d7d89df4..081891b22 100644 --- a/src/XTC/dump_xtc.h +++ b/src/XTC/dump_xtc.h @@ -1,107 +1,107 @@ /* -*- 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. ------------------------------------------------------------------------- */ #ifdef DUMP_CLASS DumpStyle(xtc,DumpXTC) #else #ifndef LMP_DUMP_XTC_H #define LMP_DUMP_XTC_H #include "dump.h" #ifdef LAMMPS_XDR #include "xdr_compat.h" #else #include "rpc/rpc.h" #include "rpc/xdr.h" #endif namespace LAMMPS_NS { class DumpXTC : public Dump { public: DumpXTC(class LAMMPS *, int, char**); - ~DumpXTC(); + virtual ~DumpXTC(); private: int natoms,ntotal; int nevery_save; int unwrap_flag; // 1 if atom coords are unwrapped, 0 if no float precision; // user-adjustable precision setting float *coords; double sfactor; XDR xd; void init_style(); int modify_param(int, char **); void openfile(); void write_header(bigint); void pack(int *); void write_data(int, double *); bigint memory_usage(); void write_frame(); }; } #endif #endif /* ERROR/WARNING messages: E: Illegal ... command Self-explanatory. Check the input script syntax and compare to the documentation for the command. You can use -echo screen as a command-line option when running LAMMPS to see the offending line. E: Invalid dump xtc filename Filenames used with the dump xtc style cannot be binary or compressed or cause multiple files to be written. E: Too many atoms for dump xtc The system size must fit in a 32-bit integer to use this dump style. E: Dump xtc requires sorting by atom ID Use the dump_modify sort command to enable this. E: Cannot set dump_modify flush for dump xtc Self-explanatory. E: Cannot use variable every setting for dump xtc The format of this file requires snapshots at regular intervals. E: Cannot change dump_modify every for dump xtc The frequency of writing dump xtc snapshots cannot be changed. E: Cannot open dump file The output file for the dump command cannot be opened. Check that the path and name are correct. E: Too big a timestep for dump xtc The timestep must fit in a 32-bit integer to use this dump style. */ diff --git a/src/dump.cpp b/src/dump.cpp index 551cde0ad..9b1b10fe9 100644 --- a/src/dump.cpp +++ b/src/dump.cpp @@ -1,810 +1,814 @@ /* ---------------------------------------------------------------------- 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 "lmptype.h" #include "mpi.h" #include "stdlib.h" #include "string.h" #include "stdio.h" #include "dump.h" #include "atom.h" #include "irregular.h" #include "update.h" #include "domain.h" #include "group.h" #include "output.h" #include "memory.h" #include "error.h" #include "force.h" using namespace LAMMPS_NS; // allocate space for static class variable Dump *Dump::dumpptr; #define BIG 1.0e20 #define IBIG 2147483647 #define EPSILON 1.0e-6 enum{ASCEND,DESCEND}; /* ---------------------------------------------------------------------- */ Dump::Dump(LAMMPS *lmp, int narg, char **arg) : Pointers(lmp) { MPI_Comm_rank(world,&me); MPI_Comm_size(world,&nprocs); int n = strlen(arg[0]) + 1; id = new char[n]; strcpy(id,arg[0]); igroup = group->find(arg[1]); groupbit = group->bitmask[igroup]; n = strlen(arg[2]) + 1; style = new char[n]; strcpy(style,arg[2]); n = strlen(arg[4]) + 1; filename = new char[n]; strcpy(filename,arg[4]); comm_forward = comm_reverse = 0; first_flag = 0; flush_flag = 1; format = NULL; format_user = NULL; format_default = NULL; clearstep = 0; sort_flag = 0; append_flag = 0; padflag = 0; maxbuf = maxids = maxsort = maxproc = 0; buf = bufsort = NULL; ids = idsort = index = proclist = NULL; irregular = NULL; // parse filename for special syntax // if contains '%', write one file per proc and replace % with proc-ID // if contains '*', write one file per timestep and replace * with timestep // check file suffixes // if ends in .bin = binary file // else if ends in .gz = gzipped text file // else ASCII text file fp = NULL; singlefile_opened = 0; compressed = 0; binary = 0; multifile = 0; multiproc = 0; nclusterprocs = nprocs; filewriter = 0; if (me == 0) filewriter = 1; fileproc = 0; multiname = NULL; char *ptr; if (ptr = strchr(filename,'%')) { multiproc = 1; nclusterprocs = 1; filewriter = 1; fileproc = me; MPI_Comm_split(world,me,0,&clustercomm); multiname = new char[strlen(filename) + 16]; *ptr = '\0'; sprintf(multiname,"%s%d%s",filename,me,ptr+1); *ptr = '%'; } if (strchr(filename,'*')) multifile = 1; char *suffix = filename + strlen(filename) - strlen(".bin"); if (suffix > filename && strcmp(suffix,".bin") == 0) binary = 1; suffix = filename + strlen(filename) - strlen(".gz"); if (suffix > filename && strcmp(suffix,".gz") == 0) compressed = 1; } /* ---------------------------------------------------------------------- */ Dump::~Dump() { delete [] id; delete [] style; delete [] filename; delete [] multiname; delete [] format; delete [] format_default; delete [] format_user; memory->destroy(buf); memory->destroy(bufsort); memory->destroy(ids); memory->destroy(idsort); memory->destroy(index); memory->destroy(proclist); delete irregular; if (multiproc) MPI_Comm_free(&clustercomm); // XTC style sets fp to NULL since it closes file in its destructor if (multifile == 0 && fp != NULL) { if (compressed) { if (filewriter) pclose(fp); } else { if (filewriter) fclose(fp); } } } /* ---------------------------------------------------------------------- */ void Dump::init() { init_style(); if (!sort_flag) { memory->destroy(bufsort); memory->destroy(ids); memory->destroy(idsort); memory->destroy(index); memory->destroy(proclist); delete irregular; maxids = maxsort = maxproc = 0; bufsort = NULL; ids = idsort = index = proclist = NULL; irregular = NULL; } if (sort_flag) { if (multiproc > 1) error->all(FLERR, "Cannot dump sort when multiple procs write the dump file"); if (sortcol == 0 && atom->tag_enable == 0) error->all(FLERR,"Cannot dump sort on atom IDs with no atom IDs defined"); if (sortcol && sortcol > size_one) error->all(FLERR,"Dump sort column is invalid"); if (nprocs > 1 && irregular == NULL) irregular = new Irregular(lmp); bigint size = group->count(igroup); if (size > MAXSMALLINT) error->all(FLERR,"Too many atoms to dump sort"); // set reorderflag = 1 if can simply reorder local atoms rather than sort // criteria: sorting by ID, atom IDs are consecutive from 1 to Natoms // min/max IDs of group match size of group // compute ntotal_reorder, nme_reorder, idlo/idhi to test against later reorderflag = 0; if (sortcol == 0 && atom->tag_consecutive()) { int *tag = atom->tag; int *mask = atom->mask; int nlocal = atom->nlocal; int min = IBIG; int max = 0; for (int i = 0; i < nlocal; i++) if (mask[i] & groupbit) { min = MIN(min,tag[i]); max = MAX(max,tag[i]); } int minall,maxall; MPI_Allreduce(&min,&minall,1,MPI_INT,MPI_MIN,world); MPI_Allreduce(&max,&maxall,1,MPI_INT,MPI_MAX,world); int isize = static_cast<int> (size); if (maxall-minall+1 == isize) { reorderflag = 1; double range = maxall-minall + EPSILON; idlo = static_cast<int> (range*me/nprocs + minall); int idhi = static_cast<int> (range*(me+1)/nprocs + minall); int lom1 = static_cast<int> ((idlo-1-minall)/range * nprocs); int lo = static_cast<int> ((idlo-minall)/range * nprocs); int him1 = static_cast<int> ((idhi-1-minall)/range * nprocs); int hi = static_cast<int> ((idhi-minall)/range * nprocs); if (me && me == lom1) idlo--; else if (me && me != lo) idlo++; if (me+1 == him1) idhi--; else if (me+1 != hi) idhi++; nme_reorder = idhi-idlo; ntotal_reorder = isize; } } } } /* ---------------------------------------------------------------------- */ int Dump::count() { if (igroup == 0) return atom->nlocal; int *mask = atom->mask; int nlocal = atom->nlocal; int m = 0; for (int i = 0; i < nlocal; i++) if (mask[i] & groupbit) m++; return m; } /* ---------------------------------------------------------------------- */ void Dump::write() { // if file per timestep, open new file if (multifile) openfile(); // simulation box bounds if (domain->triclinic == 0) { boxxlo = domain->boxlo[0]; boxxhi = domain->boxhi[0]; boxylo = domain->boxlo[1]; boxyhi = domain->boxhi[1]; boxzlo = domain->boxlo[2]; boxzhi = domain->boxhi[2]; } else { boxxlo = domain->boxlo_bound[0]; boxxhi = domain->boxhi_bound[0]; boxylo = domain->boxlo_bound[1]; boxyhi = domain->boxhi_bound[1]; boxzlo = domain->boxlo_bound[2]; boxzhi = domain->boxhi_bound[2]; boxxy = domain->xy; boxxz = domain->xz; boxyz = domain->yz; } // nme = # of dump lines this proc contributes to dump nme = count(); // ntotal = total # of dump lines in snapshot // nmax = max # of dump lines on any proc bigint bnme = nme; MPI_Allreduce(&bnme,&ntotal,1,MPI_LMP_BIGINT,MPI_SUM,world); int nmax; if (multiproc != nprocs) MPI_Allreduce(&nme,&nmax,1,MPI_INT,MPI_MAX,world); else nmax = nme; // write timestep header // for multiproc, // nheader = # of lines in this file via Allreduce on clustercomm bigint nheader = ntotal; if (multiproc) MPI_Allreduce(&bnme,&nheader,1,MPI_LMP_BIGINT,MPI_SUM,clustercomm); if (filewriter) write_header(nheader); // insure filewriter proc can receive everyone's info // limit nmax*size_one to int since used as arg in MPI_Rsend() below // pack my data into buf // if sorting on IDs also request ID list from pack() // sort buf as needed if (nmax > maxbuf) { if ((bigint) nmax * size_one > MAXSMALLINT) error->all(FLERR,"Too much per-proc info for dump"); maxbuf = nmax; memory->destroy(buf); memory->create(buf,maxbuf*size_one,"dump:buf"); } if (sort_flag && sortcol == 0 && nmax > maxids) { maxids = nmax; memory->destroy(ids); memory->create(ids,maxids,"dump:ids"); } if (sort_flag && sortcol == 0) pack(ids); else pack(NULL); if (sort_flag) sort(); // 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 int tmp,nlines; MPI_Status status; MPI_Request request; if (filewriter) { for (int iproc = 0; iproc < nclusterprocs; iproc++) { if (iproc) { MPI_Irecv(buf,maxbuf*size_one,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,&nlines); nlines /= size_one; } else nlines = nme; write_data(nlines,buf); } if (flush_flag) fflush(fp); } else { MPI_Recv(&tmp,0,MPI_INT,fileproc,0,world,&status); MPI_Rsend(buf,nme*size_one,MPI_DOUBLE,fileproc,0,world); } // if file per timestep, close file if I am filewriter if (multifile) { if (compressed) { if (filewriter) pclose(fp); } else { if (filewriter) fclose(fp); } } } /* ---------------------------------------------------------------------- generic opening of a dump file ASCII or binary or gzipped some derived classes override this function ------------------------------------------------------------------------- */ void Dump::openfile() { // single file, already opened, so just return if (singlefile_opened) return; if (multifile == 0) singlefile_opened = 1; // if one file per timestep, replace '*' with current timestep char *filecurrent = filename; if (multiproc) filecurrent = multiname; if (multifile) { char *filestar = filecurrent; filecurrent = new char[strlen(filestar) + 16]; char *ptr = strchr(filestar,'*'); *ptr = '\0'; if (padflag == 0) sprintf(filecurrent,"%s" BIGINT_FORMAT "%s", filestar,update->ntimestep,ptr+1); else { char bif[8],pad[16]; strcpy(bif,BIGINT_FORMAT); sprintf(pad,"%%s%%0%d%s%%s",padflag,&bif[1]); sprintf(filecurrent,pad,filestar,update->ntimestep,ptr+1); } *ptr = '*'; } // each proc with filewriter = 1 opens a file if (filewriter) { if (compressed) { #ifdef LAMMPS_GZIP char gzip[128]; sprintf(gzip,"gzip -6 > %s",filecurrent); +#ifdef _WIN32 + fp = _popen(gzip,"wb"); +#else fp = popen(gzip,"w"); +#endif #else error->one(FLERR,"Cannot open gzipped file"); #endif } else if (binary) { fp = fopen(filecurrent,"wb"); } else if (append_flag) { fp = fopen(filecurrent,"a"); } else { fp = fopen(filecurrent,"w"); } if (fp == NULL) error->one(FLERR,"Cannot open dump file"); } else fp = NULL; // delete string with timestep replaced if (multifile) delete [] filecurrent; } /* ---------------------------------------------------------------------- parallel sort of buf across all procs changes nme, reorders datums in buf, grows buf if necessary ------------------------------------------------------------------------- */ void Dump::sort() { int i,iproc; double value; // if single proc, swap ptrs to buf,ids <-> bufsort,idsort if (nprocs == 1) { if (nme > maxsort) { maxsort = nme; memory->destroy(bufsort); memory->create(bufsort,maxsort*size_one,"dump:bufsort"); memory->destroy(index); memory->create(index,maxsort,"dump:index"); if (sortcol == 0) { memory->destroy(idsort); memory->create(idsort,maxsort,"dump:idsort"); } } double *dptr = buf; buf = bufsort; bufsort = dptr; if (sortcol == 0) { int *iptr = ids; ids = idsort; idsort = iptr; } // if multiple procs, exchange datums between procs via irregular } else { // grow proclist if necessary if (nme > maxproc) { maxproc = nme; memory->destroy(proclist); memory->create(proclist,maxproc,"dump:proclist"); } // proclist[i] = which proc Ith datum will be sent to if (sortcol == 0) { int min = IBIG; int max = 0; for (i = 0; i < nme; i++) { min = MIN(min,ids[i]); max = MAX(max,ids[i]); } int minall,maxall; MPI_Allreduce(&min,&minall,1,MPI_INT,MPI_MIN,world); MPI_Allreduce(&max,&maxall,1,MPI_INT,MPI_MAX,world); double range = maxall-minall + EPSILON; for (i = 0; i < nme; i++) { iproc = static_cast<int> ((ids[i]-minall)/range * nprocs); proclist[i] = iproc; } } else { double min = BIG; double max = -BIG; for (i = 0; i < nme; i++) { value = buf[i*size_one + sortcolm1]; min = MIN(min,value); max = MAX(max,value); } double minall,maxall; MPI_Allreduce(&min,&minall,1,MPI_DOUBLE,MPI_MIN,world); MPI_Allreduce(&max,&maxall,1,MPI_DOUBLE,MPI_MAX,world); double range = maxall-minall + EPSILON*(maxall-minall); if (range == 0.0) range = EPSILON; for (i = 0; i < nme; i++) { value = buf[i*size_one + sortcolm1]; iproc = static_cast<int> ((value-minall)/range * nprocs); proclist[i] = iproc; } } // create comm plan, grow recv bufs if necessary, // exchange datums, destroy plan // if sorting on atom IDs, exchange IDs also nme = irregular->create_data(nme,proclist); if (nme > maxsort) { maxsort = nme; memory->destroy(bufsort); memory->create(bufsort,maxsort*size_one,"dump:bufsort"); memory->destroy(index); memory->create(index,maxsort,"dump:index"); if (sortcol == 0) { memory->destroy(idsort); memory->create(idsort,maxsort,"dump:idsort"); } } irregular->exchange_data((char *) buf,size_one*sizeof(double), (char *) bufsort); if (sortcol == 0) irregular->exchange_data((char *) ids,sizeof(int),(char *) idsort); irregular->destroy_data(); } // if reorder flag is set & total/per-proc counts match pre-computed values, // then create index directly from idsort // else quicksort of index using IDs or buf column as comparator if (reorderflag) { if (ntotal != ntotal_reorder) reorderflag = 0; int flag = 0; if (nme != nme_reorder) flag = 1; int flagall; MPI_Allreduce(&flag,&flagall,1,MPI_INT,MPI_SUM,world); if (flagall) reorderflag = 0; if (reorderflag) for (i = 0; i < nme; i++) index[idsort[i]-idlo] = i; } if (!reorderflag) { dumpptr = this; for (i = 0; i < nme; i++) index[i] = i; if (sortcol == 0) qsort(index,nme,sizeof(int),idcompare); else if (sortorder == ASCEND) qsort(index,nme,sizeof(int),bufcompare); else qsort(index,nme,sizeof(int),bufcompare_reverse); } // reset buf size and maxbuf to largest of any post-sort nme values // this insures proc 0 can receive everyone's info int nmax; MPI_Allreduce(&nme,&nmax,1,MPI_INT,MPI_MAX,world); if (nmax > maxbuf) { maxbuf = nmax; memory->destroy(buf); memory->create(buf,maxbuf*size_one,"dump:buf"); } // copy data from bufsort to buf using index int nbytes = size_one*sizeof(double); for (i = 0; i < nme; i++) memcpy(&buf[i*size_one],&bufsort[index[i]*size_one],nbytes); } /* ---------------------------------------------------------------------- compare two atom IDs called via qsort() in sort() method is a static method so access data via dumpptr ------------------------------------------------------------------------- */ int Dump::idcompare(const void *pi, const void *pj) { int *idsort = dumpptr->idsort; int i = *((int *) pi); int j = *((int *) pj); if (idsort[i] < idsort[j]) return -1; if (idsort[i] > idsort[j]) return 1; return 0; } /* ---------------------------------------------------------------------- compare two buffer values with size_one stride called via qsort() in sort() method is a static method so access data via dumpptr sort in ASCENDing order ------------------------------------------------------------------------- */ int Dump::bufcompare(const void *pi, const void *pj) { double *bufsort = dumpptr->bufsort; int size_one = dumpptr->size_one; int sortcolm1 = dumpptr->sortcolm1; int i = *((int *) pi)*size_one + sortcolm1; int j = *((int *) pj)*size_one + sortcolm1; if (bufsort[i] < bufsort[j]) return -1; if (bufsort[i] > bufsort[j]) return 1; return 0; } /* ---------------------------------------------------------------------- compare two buffer values with size_one stride called via qsort() in sort() method is a static method so access data via dumpptr sort in DESCENDing order ------------------------------------------------------------------------- */ int Dump::bufcompare_reverse(const void *pi, const void *pj) { double *bufsort = dumpptr->bufsort; int size_one = dumpptr->size_one; int sortcolm1 = dumpptr->sortcolm1; int i = *((int *) pi)*size_one + sortcolm1; int j = *((int *) pj)*size_one + sortcolm1; if (bufsort[i] > bufsort[j]) return -1; if (bufsort[i] < bufsort[j]) return 1; return 0; } /* ---------------------------------------------------------------------- process params common to all dumps here if unknown param, call modify_param specific to the dump ------------------------------------------------------------------------- */ void Dump::modify_params(int narg, char **arg) { if (narg == 0) error->all(FLERR,"Illegal dump_modify command"); int iarg = 0; while (iarg < narg) { if (strcmp(arg[iarg],"append") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal dump_modify command"); if (strcmp(arg[iarg+1],"yes") == 0) append_flag = 1; else if (strcmp(arg[iarg+1],"no") == 0) append_flag = 0; else error->all(FLERR,"Illegal dump_modify command"); iarg += 2; } else if (strcmp(arg[iarg],"every") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal dump_modify command"); int idump; for (idump = 0; idump < output->ndump; idump++) if (strcmp(id,output->dump[idump]->id) == 0) break; int n; if (strstr(arg[iarg+1],"v_") == arg[iarg+1]) { delete [] output->var_dump[idump]; n = strlen(&arg[iarg+1][2]) + 1; output->var_dump[idump] = new char[n]; strcpy(output->var_dump[idump],&arg[iarg+1][2]); n = 0; } else { n = force->inumeric(FLERR,arg[iarg+1]); if (n <= 0) error->all(FLERR,"Illegal dump_modify command"); } output->every_dump[idump] = n; iarg += 2; } else if (strcmp(arg[iarg],"first") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal dump_modify command"); if (strcmp(arg[iarg+1],"yes") == 0) first_flag = 1; else if (strcmp(arg[iarg+1],"no") == 0) first_flag = 0; else error->all(FLERR,"Illegal dump_modify command"); iarg += 2; } else if (strcmp(arg[iarg],"fileper") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal dump_modify command"); if (!multiproc) error->all(FLERR,"Cannot use dump_modify fileper " "without % in dump file name"); int nper = force->inumeric(FLERR,arg[iarg+1]); if (nper <= 0) error->all(FLERR,"Illegal dump_modify 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; int icluster = fileproc/nper; MPI_Comm_free(&clustercomm); MPI_Comm_split(world,icluster,0,&clustercomm); delete [] multiname; multiname = new char[strlen(filename) + 16]; char *ptr = strchr(filename,'%'); *ptr = '\0'; sprintf(multiname,"%s%d%s",filename,icluster,ptr+1); *ptr = '%'; iarg += 2; } else if (strcmp(arg[iarg],"flush") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal dump_modify command"); if (strcmp(arg[iarg+1],"yes") == 0) flush_flag = 1; else if (strcmp(arg[iarg+1],"no") == 0) flush_flag = 0; else error->all(FLERR,"Illegal dump_modify command"); iarg += 2; } else if (strcmp(arg[iarg],"format") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal dump_modify command"); delete [] format_user; format_user = NULL; if (strcmp(arg[iarg+1],"none")) { int n = strlen(arg[iarg+1]) + 1; format_user = new char[n]; strcpy(format_user,arg[iarg+1]); } iarg += 2; } else if (strcmp(arg[iarg],"nfile") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal dump_modify command"); if (!multiproc) error->all(FLERR,"Cannot use dump_modify nfile " "without % in dump file name"); int nfile = force->inumeric(FLERR,arg[iarg+1]); if (nfile <= 0) error->all(FLERR,"Illegal dump_modify command"); nfile = MIN(nfile,nprocs); multiproc = nfile; int 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; MPI_Comm_free(&clustercomm); MPI_Comm_split(world,icluster,0,&clustercomm); delete [] multiname; multiname = new char[strlen(filename) + 16]; char *ptr = strchr(filename,'%'); *ptr = '\0'; sprintf(multiname,"%s%d%s",filename,icluster,ptr+1); *ptr = '%'; iarg += 2; } else if (strcmp(arg[iarg],"pad") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal dump_modify command"); padflag = force->inumeric(FLERR,arg[iarg+1]); if (padflag < 0) error->all(FLERR,"Illegal dump_modify command"); iarg += 2; } else if (strcmp(arg[iarg],"sort") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal dump_modify command"); if (strcmp(arg[iarg+1],"off") == 0) sort_flag = 0; else if (strcmp(arg[iarg+1],"id") == 0) { sort_flag = 1; sortcol = 0; sortorder = ASCEND; } else { sort_flag = 1; sortcol = force->inumeric(FLERR,arg[iarg+1]); sortorder = ASCEND; if (sortcol == 0) error->all(FLERR,"Illegal dump_modify command"); if (sortcol < 0) { sortorder = DESCEND; sortcol = -sortcol; } sortcolm1 = sortcol - 1; } iarg += 2; } else { int n = modify_param(narg-iarg,&arg[iarg]); if (n == 0) error->all(FLERR,"Illegal dump_modify command"); iarg += n; } } } /* ---------------------------------------------------------------------- return # of bytes of allocated memory ------------------------------------------------------------------------- */ bigint Dump::memory_usage() { bigint bytes = memory->usage(buf,size_one*maxbuf); if (sort_flag) { if (sortcol == 0) bytes += memory->usage(ids,maxids); bytes += memory->usage(bufsort,size_one*maxsort); if (sortcol == 0) bytes += memory->usage(idsort,maxsort); bytes += memory->usage(index,maxsort); bytes += memory->usage(proclist,maxproc); if (irregular) bytes += irregular->memory_usage(); } return bytes; } diff --git a/src/dump.h b/src/dump.h index 12113df54..3f581767e 100644 --- a/src/dump.h +++ b/src/dump.h @@ -1,174 +1,175 @@ -/* ---------------------------------------------------------------------- +/* -*- 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. ------------------------------------------------------------------------- */ #ifndef LMP_DUMP_H #define LMP_DUMP_H #include "mpi.h" #include "stdio.h" #include "pointers.h" namespace LAMMPS_NS { class Dump : protected Pointers { public: char *id; // user-defined name of Dump char *style; // style of Dump int igroup,groupbit; // group that Dump is performed on int first_flag; // 0 if no initial dump, 1 if yes initial dump int clearstep; // 1 if dump invokes computes, 0 if not int comm_forward; // size of forward communication (0 if none) int comm_reverse; // size of reverse communication (0 if none) // static variable across all Dump objects static Dump *dumpptr; // holds a ptr to Dump currently being used Dump(class LAMMPS *, int, char **); virtual ~Dump(); void init(); virtual void write(); virtual int pack_comm(int, int *, double *, int, int *) {return 0;} virtual void unpack_comm(int, int, double *) {} virtual int pack_reverse_comm(int, int, double *) {return 0;} virtual void unpack_reverse_comm(int, int *, double *) {} void modify_params(int, char **); virtual bigint memory_usage(); protected: int me,nprocs; // proc info char *filename; // user-specified file int compressed; // 1 if dump file is written compressed, 0 no int binary; // 1 if dump file is written binary, 0 no int multifile; // 0 = one big file, 1 = one file per timestep int 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 MPI_Comm clustercomm; // MPI communicator within my cluster of procs int header_flag; // 0 = item, 2 = xyz int flush_flag; // 0 if no flush, 1 if flush every dump int sort_flag; // 1 if sorted output int append_flag; // 1 if open file in append mode, 0 if not int padflag; // timestep padding in filename int singlefile_opened; // 1 = one big file, already opened, else 0 int sortcol; // 0 to sort on ID, 1-N on columns int sortcolm1; // sortcol - 1 int sortorder; // ASCEND or DESCEND char boundstr[9]; // encoding of boundary flags char *format_default; // default format string char *format_user; // format string set by user char *format; // format string for the file write FILE *fp; // file to write dump to int size_one; // # of quantities for one atom int nme; // # of atoms in this dump from me double boxxlo,boxxhi; // local copies of domain values double boxylo,boxyhi; // lo/hi are bounding box for triclinic double boxzlo,boxzhi; double boxxy,boxxz,boxyz; bigint ntotal; // total # of per-atom lines in snapshot int reorderflag; // 1 if OK to reorder instead of sort int ntotal_reorder; // # of atoms that must be in snapshot int nme_reorder; // # of atoms I must own in snapshot int idlo; // lowest ID I own when reordering int maxbuf; // size of buf double *buf; // memory for atom quantities int maxids; // size of ids int maxsort; // size of bufsort, idsort, index int maxproc; // size of proclist int *ids; // list of atom IDs, if sorting on IDs double *bufsort; int *idsort,*index,*proclist; class Irregular *irregular; virtual void init_style() = 0; virtual void openfile(); virtual int modify_param(int, char **) {return 0;} virtual void write_header(bigint) = 0; virtual int count(); virtual void pack(int *) = 0; virtual void write_data(int, double *) = 0; void sort(); static int idcompare(const void *, const void *); static int bufcompare(const void *, const void *); static int bufcompare_reverse(const void *, const void *); }; } #endif /* ERROR/WARNING messages: E: Cannot dump sort when multiple procs write the dump file UNDOCUMENTED E: Cannot dump sort on atom IDs with no atom IDs defined Self-explanatory. E: Dump sort column is invalid Self-explanatory. E: Too many atoms to dump sort Cannot sort when running with more than 2^31 atoms. E: Too much per-proc info for dump Number of local atoms times number of columns must fit in a 32-bit integer for dump. E: Cannot open gzipped file -LAMMPS is attempting to open a gzipped version of the specified file -but was unsuccessful. Check that the path and name are correct. +LAMMPS was compiled without support for reading and writing gzipped +files through a pipeline to the gzip program with -DLAMMPS_GZIP. E: Cannot open dump file -The output file for the dump command cannot be opened. Check that the -path and name are correct. +The specified file cannot be opened. Check that the path and name are +correct. If the file is a compressed file, also check that the gzip +executable can be found and run. E: Illegal ... command Self-explanatory. Check the input script syntax and compare to the documentation for the command. You can use -echo screen as a command-line option when running LAMMPS to see the offending line. E: Cannot use dump_modify fileper without % in dump file name UNDOCUMENTED E: Cannot use dump_modify nfile without % in dump file name UNDOCUMENTED */ diff --git a/src/dump_image.cpp b/src/dump_image.cpp index a0063ff30..51c77158e 100644 --- a/src/dump_image.cpp +++ b/src/dump_image.cpp @@ -1,1068 +1,1070 @@ /* ---------------------------------------------------------------------- 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 "math.h" #include "ctype.h" #include "stdlib.h" #include "string.h" #include "dump_image.h" #include "image.h" #include "atom.h" #include "domain.h" #include "group.h" #include "force.h" #include "comm.h" #include "input.h" #include "variable.h" #include "math_const.h" #include "error.h" #include "memory.h" using namespace LAMMPS_NS; using namespace MathConst; #define BIG 1.0e20 -enum{PPM,JPG,PNG}; enum{NUMERIC,ATOM,TYPE,ELEMENT,ATTRIBUTE}; enum{STATIC,DYNAMIC}; enum{NO,YES}; /* ---------------------------------------------------------------------- */ DumpImage::DumpImage(LAMMPS *lmp, int narg, char **arg) : DumpCustom(lmp, narg, arg) { if (binary || multiproc) error->all(FLERR,"Invalid dump image filename"); // force binary flag on to avoid corrupted output on Windows binary = 1; // set filetype based on filename suffix int n = strlen(filename); if (strlen(filename) > 4 && strcmp(&filename[n-4],".jpg") == 0) filetype = JPG; else if (strlen(filename) > 4 && strcmp(&filename[n-4],".JPG") == 0) filetype = JPG; else if (strlen(filename) > 5 && strcmp(&filename[n-5],".jpeg") == 0) filetype = JPG; else if (strlen(filename) > 5 && strcmp(&filename[n-5],".JPEG") == 0) filetype = JPG; else if (strlen(filename) > 4 && strcmp(&filename[n-4],".png") == 0) filetype = PNG; else if (strlen(filename) > 4 && strcmp(&filename[n-4],".PNG") == 0) filetype = PNG; else filetype = PPM; #ifndef LAMMPS_JPEG if (filetype == JPG) error->all(FLERR,"Support for writing images in JPEG format not included"); #endif #ifndef LAMMPS_PNG if (filetype == PNG) error->all(FLERR,"Support for writing images in PNG format not included"); #endif // atom color,diameter settings if (nfield != 2) error->all(FLERR,"Illegal dump image command"); acolor = ATTRIBUTE; if (strcmp(arg[5],"type") == 0) acolor = TYPE; else if (strcmp(arg[5],"element") == 0) acolor = ELEMENT; adiam = ATTRIBUTE; if (strcmp(arg[6],"type") == 0) adiam = TYPE; else if (strcmp(arg[6],"element") == 0) adiam = ELEMENT; // create Image class with single colormap for atoms // change defaults for 2d image = new Image(lmp,1); if (domain->dimension == 2) { image->theta = 0.0; image->phi = 0.0; image->up[0] = 0.0; image->up[1] = 1.0; image->up[2] = 0.0; } // set defaults for optional args atomflag = YES; if (atom->nbondtypes == 0) bondflag = NO; else { bondflag = YES; bcolor = ATOM; bdiam = NUMERIC; bdiamvalue = 0.5; } thetastr = phistr = NULL; cflag = STATIC; cx = cy = cz = 0.5; cxstr = cystr = czstr = NULL; upxstr = upystr = upzstr = NULL; zoomstr = NULL; perspstr = NULL; boxflag = YES; boxdiam = 0.02; axesflag = NO; // parse optional args int iarg = ioptional; while (iarg < narg) { if (strcmp(arg[iarg],"adiam") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal dump image command"); adiam = NUMERIC; adiamvalue = force->numeric(FLERR,arg[iarg+1]); if (adiamvalue <= 0.0) error->all(FLERR,"Illegal dump image command"); iarg += 2; } else if (strcmp(arg[iarg],"atom") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal dump image command"); if (strcmp(arg[iarg+1],"yes") == 0) atomflag = YES; else if (strcmp(arg[iarg+1],"no") == 0) atomflag = NO; else error->all(FLERR,"Illegal dump image command"); iarg += 2; } else if (strcmp(arg[iarg],"bond") == 0) { if (iarg+3 > narg) error->all(FLERR,"Illegal dump image command"); if (atom->nbondtypes == 0) error->all(FLERR,"Dump image bond not allowed with no bond types"); bondflag = YES; if (strcmp(arg[iarg+1],"none") == 0) bondflag = NO; else if (strcmp(arg[iarg+1],"atom") == 0) bcolor = ATOM; else if (strcmp(arg[iarg+1],"type") == 0) bcolor = TYPE; else error->all(FLERR,"Illegal dump image command"); if (!islower(arg[iarg+2][0])) { bdiam = NUMERIC; bdiamvalue = force->numeric(FLERR,arg[iarg+2]); if (bdiamvalue <= 0.0) error->all(FLERR,"Illegal dump image command"); } else if (strcmp(arg[iarg+2],"atom") == 0) bdiam = ATOM; else if (strcmp(arg[iarg+2],"type") == 0) bdiam = TYPE; else if (strcmp(arg[iarg+2],"none") == 0) bondflag = NO; else error->all(FLERR,"Illegal dump image command"); iarg += 3; } else if (strcmp(arg[iarg],"size") == 0) { if (iarg+3 > narg) error->all(FLERR,"Illegal dump image command"); int width = force->inumeric(FLERR,arg[iarg+1]); int height = force->inumeric(FLERR,arg[iarg+2]); if (width <= 0 || height <= 0) error->all(FLERR,"Illegal dump image command"); image->width = width; image->height = height; iarg += 3; } else if (strcmp(arg[iarg],"view") == 0) { if (iarg+3 > narg) error->all(FLERR,"Illegal dump image command"); if (strstr(arg[iarg+1],"v_") == arg[iarg+1]) { int n = strlen(&arg[iarg+1][2]) + 1; thetastr = new char[n]; strcpy(thetastr,&arg[iarg+1][2]); } else { double theta = force->numeric(FLERR,arg[iarg+1]); if (theta < 0.0 || theta > 180.0) error->all(FLERR,"Invalid dump image theta value"); theta *= MY_PI/180.0; image->theta = theta; } if (strstr(arg[iarg+2],"v_") == arg[iarg+2]) { int n = strlen(&arg[iarg+2][2]) + 1; phistr = new char[n]; strcpy(phistr,&arg[iarg+2][2]); } else { double phi = force->numeric(FLERR,arg[iarg+2]); phi *= MY_PI/180.0; image->phi = phi; } iarg += 3; } else if (strcmp(arg[iarg],"center") == 0) { if (iarg+5 > narg) error->all(FLERR,"Illegal dump image command"); if (strcmp(arg[iarg+1],"s") == 0) cflag = STATIC; else if (strcmp(arg[iarg+1],"d") == 0) cflag = DYNAMIC; else error->all(FLERR,"Illegal dump image command"); if (strstr(arg[iarg+2],"v_") == arg[iarg+2]) { int n = strlen(&arg[iarg+2][2]) + 1; cxstr = new char[n]; strcpy(cxstr,&arg[iarg+2][2]); cflag = DYNAMIC; } else cx = force->numeric(FLERR,arg[iarg+2]); if (strstr(arg[iarg+3],"v_") == arg[iarg+3]) { int n = strlen(&arg[iarg+3][2]) + 1; cystr = new char[n]; strcpy(cystr,&arg[iarg+3][2]); cflag = DYNAMIC; } else cy = force->numeric(FLERR,arg[iarg+3]); if (strstr(arg[iarg+4],"v_") == arg[iarg+4]) { int n = strlen(&arg[iarg+4][2]) + 1; czstr = new char[n]; strcpy(czstr,&arg[iarg+4][2]); cflag = DYNAMIC; } else cz = force->numeric(FLERR,arg[iarg+4]); iarg += 5; } else if (strcmp(arg[iarg],"up") == 0) { if (iarg+4 > narg) error->all(FLERR,"Illegal dump image command"); if (strstr(arg[iarg+1],"v_") == arg[iarg+1]) { int n = strlen(&arg[iarg+1][2]) + 1; upxstr = new char[n]; strcpy(upxstr,&arg[iarg+1][2]); } else image->up[0] = force->numeric(FLERR,arg[iarg+1]); if (strstr(arg[iarg+2],"v_") == arg[iarg+2]) { int n = strlen(&arg[iarg+2][2]) + 1; upystr = new char[n]; strcpy(upystr,&arg[iarg+2][2]); } else image->up[1] = force->numeric(FLERR,arg[iarg+2]); if (strstr(arg[iarg+3],"v_") == arg[iarg+3]) { int n = strlen(&arg[iarg+3][2]) + 1; upzstr = new char[n]; strcpy(upzstr,&arg[iarg+3][2]); } else image->up[2] = force->numeric(FLERR,arg[iarg+3]); iarg += 4; } else if (strcmp(arg[iarg],"zoom") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal dump image command"); if (strstr(arg[iarg+1],"v_") == arg[iarg+1]) { int n = strlen(&arg[iarg+1][2]) + 1; zoomstr = new char[n]; strcpy(zoomstr,&arg[iarg+1][2]); } else { double zoom = force->numeric(FLERR,arg[iarg+1]); if (zoom <= 0.0) error->all(FLERR,"Illegal dump image command"); image->zoom = zoom; } iarg += 2; } else if (strcmp(arg[iarg],"persp") == 0) { error->all(FLERR,"Dump image persp option is not yet supported"); if (iarg+2 > narg) error->all(FLERR,"Illegal dump image command"); if (strstr(arg[iarg+1],"v_") == arg[iarg+1]) { int n = strlen(&arg[iarg+1][2]) + 1; perspstr = new char[n]; strcpy(perspstr,&arg[iarg+1][2]); } else { double persp = force->numeric(FLERR,arg[iarg+1]); if (persp < 0.0) error->all(FLERR,"Illegal dump image command"); image->persp = persp; } iarg += 2; } else if (strcmp(arg[iarg],"box") == 0) { if (iarg+3 > narg) error->all(FLERR,"Illegal dump image command"); if (strcmp(arg[iarg+1],"yes") == 0) boxflag = YES; else if (strcmp(arg[iarg+1],"no") == 0) boxflag = NO; else error->all(FLERR,"Illegal dump image command"); boxdiam = force->numeric(FLERR,arg[iarg+2]); if (boxdiam < 0.0) error->all(FLERR,"Illegal dump image command"); iarg += 3; } else if (strcmp(arg[iarg],"axes") == 0) { if (iarg+3 > narg) error->all(FLERR,"Illegal dump image command"); if (strcmp(arg[iarg+1],"yes") == 0) axesflag = YES; else if (strcmp(arg[iarg+1],"no") == 0) axesflag = NO; else error->all(FLERR,"Illegal dump image command"); axeslen = force->numeric(FLERR,arg[iarg+2]); axesdiam = force->numeric(FLERR,arg[iarg+3]); if (axeslen < 0.0 || axesdiam < 0.0) error->all(FLERR,"Illegal dump image command"); iarg += 4; } else if (strcmp(arg[iarg],"shiny") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal dump image command"); double shiny = force->numeric(FLERR,arg[iarg+1]); if (shiny < 0.0 || shiny > 1.0) error->all(FLERR,"Illegal dump image command"); image->shiny = shiny; iarg += 2; } else if (strcmp(arg[iarg],"ssao") == 0) { if (iarg+4 > narg) error->all(FLERR,"Illegal dump image command"); if (strcmp(arg[iarg+1],"yes") == 0) image->ssao = YES; else if (strcmp(arg[iarg+1],"no") == 0) image->ssao = NO; else error->all(FLERR,"Illegal dump image command"); int seed = force->inumeric(FLERR,arg[iarg+2]); if (seed <= 0) error->all(FLERR,"Illegal dump image command"); image->seed = seed; double ssaoint = force->numeric(FLERR,arg[iarg+3]); if (ssaoint < 0.0 || ssaoint > 1.0) error->all(FLERR,"Illegal dump image command"); image->ssaoint = ssaoint; iarg += 4; } else error->all(FLERR,"Illegal dump image command"); } // allocate image buffer now that image size is known image->buffers(); // communication neede for bonds colored by atoms if (bondflag) { if (bcolor == ATOM || bdiam == ATOM) comm_forward = 3; else comm_forward = 1; } // additional defaults for dump_modify options diamtype = new double[ntypes+1]; diamelement = new double[ntypes+1]; colortype = new double*[ntypes+1]; colorelement = new double*[ntypes+1]; for (int i = 1; i <= ntypes; i++) { diamtype[i] = 1.0; if (i % 6 == 1) colortype[i] = image->color2rgb("red"); else if (i % 6 == 2) colortype[i] = image->color2rgb("green"); else if (i % 6 == 3) colortype[i] = image->color2rgb("blue"); else if (i % 6 == 4) colortype[i] = image->color2rgb("yellow"); else if (i % 6 == 5) colortype[i] = image->color2rgb("aqua"); else if (i % 6 == 0) colortype[i] = image->color2rgb("cyan"); } if (bondflag) { bdiamtype = new double[atom->nbondtypes+1]; bcolortype = new double*[atom->nbondtypes+1]; for (int i = 1; i <= atom->nbondtypes; i++) { bdiamtype[i] = 0.5; if (i % 6 == 1) bcolortype[i] = image->color2rgb("red"); else if (i % 6 == 2) bcolortype[i] = image->color2rgb("green"); else if (i % 6 == 3) bcolortype[i] = image->color2rgb("blue"); else if (i % 6 == 4) bcolortype[i] = image->color2rgb("yellow"); else if (i % 6 == 5) bcolortype[i] = image->color2rgb("aqua"); else if (i % 6 == 0) bcolortype[i] = image->color2rgb("cyan"); } } else { bdiamtype = NULL; bcolortype = NULL; } // viewflag = DYNAMIC if any view parameter is dynamic viewflag = STATIC; if (thetastr || phistr || cflag == DYNAMIC || upxstr || upystr || upzstr || zoomstr || perspstr) viewflag = DYNAMIC; box_bounds(); if (cflag == STATIC) box_center(); if (viewflag == STATIC) view_params(); // local data maxbufcopy = 0; chooseghost = NULL; bufcopy = NULL; } /* ---------------------------------------------------------------------- */ DumpImage::~DumpImage() { delete image; delete [] diamtype; delete [] diamelement; delete [] colortype; delete [] colorelement; delete [] bdiamtype; delete [] bcolortype; memory->destroy(chooseghost); memory->destroy(bufcopy); } /* ---------------------------------------------------------------------- */ void DumpImage::init_style() { if (multifile == 0) error->all(FLERR,"Dump image requires one snapshot per file"); if (sort_flag) error->all(FLERR,"Dump image cannot perform sorting"); DumpCustom::init_style(); // check variables if (thetastr) { thetavar = input->variable->find(thetastr); if (thetavar < 0) error->all(FLERR,"Variable name for dump image theta does not exist"); if (!input->variable->equalstyle(thetavar)) error->all(FLERR,"Variable for dump image theta is invalid style"); } if (phistr) { phivar = input->variable->find(phistr); if (phivar < 0) error->all(FLERR,"Variable name for dump image phi does not exist"); if (!input->variable->equalstyle(phivar)) error->all(FLERR,"Variable for dump image phi is invalid style"); } if (cxstr) { cxvar = input->variable->find(cxstr); if (cxvar < 0) error->all(FLERR,"Variable name for dump image center does not exist"); if (!input->variable->equalstyle(cxvar)) error->all(FLERR,"Variable for dump image center is invalid style"); } if (cystr) { cyvar = input->variable->find(cystr); if (cyvar < 0) error->all(FLERR,"Variable name for dump image center does not exist"); if (!input->variable->equalstyle(cyvar)) error->all(FLERR,"Variable for dump image center is invalid style"); } if (czstr) { czvar = input->variable->find(czstr); if (czvar < 0) error->all(FLERR,"Variable name for dump image center does not exist"); if (!input->variable->equalstyle(czvar)) error->all(FLERR,"Variable for dump image center is invalid style"); } if (upxstr) { upxvar = input->variable->find(upxstr); if (upxvar < 0) error->all(FLERR,"Variable name for dump image center does not exist"); if (!input->variable->equalstyle(upxvar)) error->all(FLERR,"Variable for dump image center is invalid style"); } if (upystr) { upyvar = input->variable->find(upystr); if (upyvar < 0) error->all(FLERR,"Variable name for dump image center does not exist"); if (!input->variable->equalstyle(upyvar)) error->all(FLERR,"Variable for dump image center is invalid style"); } if (upzstr) { upzvar = input->variable->find(upzstr); if (upzvar < 0) error->all(FLERR,"Variable name for dump image center does not exist"); if (!input->variable->equalstyle(upzvar)) error->all(FLERR,"Variable for dump image center is invalid style"); } if (zoomstr) { zoomvar = input->variable->find(zoomstr); if (zoomvar < 0) error->all(FLERR,"Variable name for dump image zoom does not exist"); if (!input->variable->equalstyle(zoomvar)) error->all(FLERR,"Variable for dump image zoom is invalid style"); } if (perspstr) { perspvar = input->variable->find(perspstr); if (perspvar < 0) error->all(FLERR,"Variable name for dump image persp does not exist"); if (!input->variable->equalstyle(perspvar)) error->all(FLERR,"Variable for dump image persp is invalid style"); } // set up type -> element mapping if (atomflag && acolor == ELEMENT) { for (int i = 1; i <= ntypes; i++) { colorelement[i] = image->element2color(typenames[i]); if (colorelement[i] == NULL) error->all(FLERR,"Invalid dump image element name"); } } if (atomflag && adiam == ELEMENT) { for (int i = 1; i <= ntypes; i++) { diamelement[i] = image->element2diam(typenames[i]); if (diamelement[i] == 0.0) error->all(FLERR,"Invalid dump image element name"); } } } /* ---------------------------------------------------------------------- */ void DumpImage::write() { // open new file openfile(); // reset box center and view parameters if dynamic box_bounds(); if (cflag == DYNAMIC) box_center(); if (viewflag == DYNAMIC) view_params(); // nme = # of atoms this proc will contribute to dump nme = count(); if (nme > maxbuf) { maxbuf = nme; memory->destroy(buf); memory->create(buf,maxbuf*size_one,"dump:buf"); } // pack buf with color & diameter pack(NULL); // set minmax color range if using dynamic atom color map if (acolor == ATTRIBUTE && image->map_dynamic(0)) { double two[2],twoall[2]; double lo = BIG; double hi = -BIG; int m = 0; for (int i = 0; i < nchoose; i++) { lo = MIN(lo,buf[m]); hi = MAX(hi,buf[m]); m += size_one; } two[0] = -lo; two[1] = hi; MPI_Allreduce(two,twoall,2,MPI_DOUBLE,MPI_MAX,world); int flag = image->map_minmax(0,-twoall[0],twoall[1]); if (flag) error->all(FLERR,"Invalid color map min/max values"); } // create image on each proc, then merge them image->clear(); create_image(); image->merge(); // write image file if (me == 0) { if (filetype == JPG) image->write_JPG(fp); else if (filetype == PNG) image->write_PNG(fp); else image->write_PPM(fp); - fclose(fp); + if (multifile) { + fclose(fp); + fp = NULL; + } } } /* ---------------------------------------------------------------------- simulation box bounds ------------------------------------------------------------------------- */ void DumpImage::box_bounds() { if (domain->triclinic == 0) { boxxlo = domain->boxlo[0]; boxxhi = domain->boxhi[0]; boxylo = domain->boxlo[1]; boxyhi = domain->boxhi[1]; boxzlo = domain->boxlo[2]; boxzhi = domain->boxhi[2]; } else { boxxlo = domain->boxlo_bound[0]; boxxhi = domain->boxhi_bound[0]; boxylo = domain->boxlo_bound[1]; boxyhi = domain->boxhi_bound[1]; boxzlo = domain->boxlo_bound[2]; boxzhi = domain->boxhi_bound[2]; boxxy = domain->xy; boxxz = domain->xz; boxyz = domain->yz; } } /* ---------------------------------------------------------------------- reset view parameters called once from constructor if view is STATIC called every snapshot from write() if view is DYNAMIC ------------------------------------------------------------------------- */ void DumpImage::box_center() { if (cxstr) cx = input->variable->compute_equal(cxvar); if (cystr) cy = input->variable->compute_equal(cyvar); if (czstr) cz = input->variable->compute_equal(czvar); image->xctr = boxxlo + cx*(boxxhi-boxxlo); image->yctr = boxylo + cy*(boxyhi-boxylo); image->zctr = boxzlo + cz*(boxzhi-boxzlo); } /* ---------------------------------------------------------------------- reset view parameters in Image class called once from constructor if view is STATIC called every snapshot from write() if view is DYNAMIC ------------------------------------------------------------------------- */ void DumpImage::view_params() { // view direction theta and phi if (thetastr) { double theta = input->variable->compute_equal(thetavar); if (theta < 0.0 || theta > 180.0) error->all(FLERR,"Invalid dump image theta value"); theta *= MY_PI/180.0; image->theta = theta; } if (phistr) { double phi = input->variable->compute_equal(phivar); phi *= MY_PI/180.0; image->phi = phi; } // up vector if (upxstr) image->up[0] = input->variable->compute_equal(upxvar); if (upystr) image->up[1] = input->variable->compute_equal(upyvar); if (upzstr) image->up[2] = input->variable->compute_equal(upzvar); // zoom and perspective if (zoomstr) image->zoom = input->variable->compute_equal(zoomvar); if (image->zoom <= 0.0) error->all(FLERR,"Invalid dump image zoom value"); if (perspstr) image->persp = input->variable->compute_equal(perspvar); if (image->persp < 0.0) error->all(FLERR,"Invalid dump image persp value"); // remainder of view setup is internal to Image class image->view_params(boxxlo,boxxhi,boxylo,boxyhi,boxzlo,boxzhi); } /* ---------------------------------------------------------------------- create image for atoms on this proc every pixel has depth ------------------------------------------------------------------------- */ void DumpImage::create_image() { int i,j,m,itype,atom1,atom2; double diameter,delx,dely,delz; double *color,*color1,*color2; double xmid[3]; // render my atoms if (atomflag) { double **x = atom->x; m = 0; for (i = 0; i < nchoose; i++) { j = clist[i]; if (acolor == TYPE) { itype = static_cast<int> (buf[m]); color = colortype[itype]; } else if (acolor == ELEMENT) { itype = static_cast<int> (buf[m]); color = colorelement[itype]; } else if (acolor == ATTRIBUTE) { color = image->map_value2color(0,buf[m]); } if (adiam == NUMERIC) { diameter = adiamvalue; } else if (adiam == TYPE) { itype = static_cast<int> (buf[m+1]); diameter = diamtype[itype]; } else if (adiam == ELEMENT) { itype = static_cast<int> (buf[m+1]); diameter = diamelement[itype]; } else if (adiam == ATTRIBUTE) { diameter = buf[m+1]; } image->draw_sphere(x[j],color,diameter); m += size_one; } } // render bonds for my atoms // both atoms in bond must be selected for bond to be rendered // if newton_bond is off, only render bond once // render bond in 2 pieces if crosses periodic boundary // if bond is deleted (type = 0), do not render // if bond is turned off (type < 0), still render if (bondflag) { double **x = atom->x; int *tag = atom->tag; int **bond_atom = atom->bond_atom; int **bond_type = atom->bond_type; int *num_bond = atom->num_bond; int *type = atom->type; int nlocal = atom->nlocal; int nall = atom->nlocal + atom->nghost; int newton_bond = force->newton_bond; // communicate choose flag for ghost atoms to know if they are selected // if bcolor/bdiam = ATOM, setup bufcopy to comm atom color/diam attributes if (nall > maxbufcopy) { maxbufcopy = atom->nmax; memory->destroy(chooseghost); memory->create(chooseghost,maxbufcopy,"dump:chooseghost"); if (comm_forward == 3) { memory->destroy(bufcopy); memory->create(bufcopy,maxbufcopy,2,"dump:bufcopy"); } } for (i = 0; i < nlocal; i++) chooseghost[i] = choose[i]; if (comm_forward == 3) { for (i = 0; i < nlocal; i++) bufcopy[i][0] = bufcopy[i][1] = 0.0; m = 0; for (i = 0; i < nchoose; i++) { j = clist[i]; bufcopy[j][0] = buf[m]; bufcopy[j][1] = buf[m+1]; m += size_one; } } comm->forward_comm_dump(this); for (i = 0; i < nchoose; i++) { atom1 = clist[i]; for (m = 0; m < num_bond[atom1]; m++) { atom2 = atom->map(bond_atom[atom1][m]); if (atom2 < 0 || !chooseghost[atom2]) continue; if (newton_bond == 0 && tag[atom1] > tag[atom2]) continue; if (bond_type[atom1][m] == 0) continue; if (bcolor == ATOM) { if (acolor == TYPE) { color1 = colortype[type[atom1]]; color2 = colortype[type[atom2]]; } else if (acolor == ELEMENT) { color1 = colorelement[type[atom1]]; color2 = colorelement[type[atom2]]; } else if (acolor == ATTRIBUTE) { color1 = image->map_value2color(0,bufcopy[atom1][0]); color2 = image->map_value2color(0,bufcopy[atom2][0]); } } else if (bcolor == TYPE) { itype = bond_type[atom1][m]; if (itype < 0) itype = -itype; color = bcolortype[itype]; } if (bdiam == NUMERIC) { diameter = bdiamvalue; } else if (bdiam == ATOM) { if (adiam == NUMERIC) { diameter = adiamvalue; } else if (adiam == TYPE) { diameter = MIN(diamtype[type[atom1]],diamtype[type[atom1]]); } else if (adiam == ELEMENT) { diameter = MIN(diamelement[type[atom1]],diamelement[type[atom1]]); } else if (adiam == ATTRIBUTE) { diameter = MIN(bufcopy[atom1][1],bufcopy[atom2][1]); } } else if (bdiam == TYPE) { itype = bond_type[atom1][m]; if (itype < 0) itype = -itype; diameter = bdiamtype[itype]; } // draw cylinder in 2 pieces if bcolor = ATOM // or bond crosses periodic boundary delx = x[atom2][0] - x[atom1][0]; dely = x[atom2][1] - x[atom1][1]; delz = x[atom2][2] - x[atom1][2]; if (bcolor == ATOM || domain->minimum_image_check(delx,dely,delz)) { domain->minimum_image(delx,dely,delz); xmid[0] = x[atom1][0] + 0.5*delx; xmid[1] = x[atom1][1] + 0.5*dely; xmid[2] = x[atom1][2] + 0.5*delz; if (bcolor == ATOM) image->draw_cylinder(x[atom1],xmid,color1,diameter,3); else image->draw_cylinder(x[atom1],xmid,color,diameter,3); xmid[0] = x[atom2][0] - 0.5*delx; xmid[1] = x[atom2][1] - 0.5*dely; xmid[2] = x[atom2][2] - 0.5*delz; if (bcolor == ATOM) image->draw_cylinder(xmid,x[atom2],color2,diameter,3); else image->draw_cylinder(xmid,x[atom2],color,diameter,3); } else image->draw_cylinder(x[atom1],x[atom2],color,diameter,3); } } } // render outline of simulation box, orthogonal or triclinic if (boxflag) { double diameter = MIN(boxxhi-boxxlo,boxyhi-boxylo); if (domain->dimension == 3) diameter = MIN(diameter,boxzhi-boxzlo); diameter *= boxdiam; double (*boxcorners)[3]; double box[8][3]; if (domain->triclinic == 0) { box[0][0] = boxxlo; box[0][1] = boxylo; box[0][2] = boxzlo; box[1][0] = boxxhi; box[1][1] = boxylo; box[1][2] = boxzlo; box[2][0] = boxxlo; box[2][1] = boxyhi; box[2][2] = boxzlo; box[3][0] = boxxhi; box[3][1] = boxyhi; box[3][2] = boxzlo; box[4][0] = boxxlo; box[4][1] = boxylo; box[4][2] = boxzhi; box[5][0] = boxxhi; box[5][1] = boxylo; box[5][2] = boxzhi; box[6][0] = boxxlo; box[6][1] = boxyhi; box[6][2] = boxzhi; box[7][0] = boxxhi; box[7][1] = boxyhi; box[7][2] = boxzhi; boxcorners = box; } else { domain->box_corners(); boxcorners = domain->corners; } image->draw_box(boxcorners,diameter); } // render XYZ axes in red/green/blue // offset by 10% of box size and scale by axeslen if (axesflag) { double diameter = MIN(boxxhi-boxxlo,boxyhi-boxylo); if (domain->dimension == 3) diameter = MIN(diameter,boxzhi-boxzlo); diameter *= axesdiam; double (*boxcorners)[3]; double axes[4][3]; if (domain->triclinic == 0) { axes[0][0] = boxxlo; axes[0][1] = boxylo; axes[0][2] = boxzlo; axes[1][0] = boxxhi; axes[1][1] = boxylo; axes[1][2] = boxzlo; axes[2][0] = boxxlo; axes[2][1] = boxyhi; axes[2][2] = boxzlo; axes[3][0] = boxxlo; axes[3][1] = boxylo; axes[3][2] = boxzhi; } else { domain->box_corners(); boxcorners = domain->corners; axes[0][0] = boxcorners[0][0]; axes[0][1] = boxcorners[0][1]; axes[0][2] = boxcorners[0][2]; axes[1][0] = boxcorners[1][0]; axes[1][1] = boxcorners[1][1]; axes[1][2] = boxcorners[1][2]; axes[2][0] = boxcorners[2][0]; axes[2][1] = boxcorners[2][1]; axes[2][2] = boxcorners[2][2]; axes[3][0] = boxcorners[4][0]; axes[3][1] = boxcorners[4][1]; axes[3][2] = boxcorners[4][2]; } double offset = MAX(boxxhi-boxxlo,boxyhi-boxylo); if (domain->dimension == 3) offset = MAX(offset,boxzhi-boxzlo); offset *= 0.1; axes[0][0] -= offset; axes[0][1] -= offset; axes[0][2] -= offset; axes[1][0] -= offset; axes[1][1] -= offset; axes[1][2] -= offset; axes[2][0] -= offset; axes[2][1] -= offset; axes[2][2] -= offset; axes[3][0] -= offset; axes[3][1] -= offset; axes[3][2] -= offset; axes[1][0] = axes[0][0] + axeslen*(axes[1][0]-axes[0][0]); axes[1][1] = axes[0][1] + axeslen*(axes[1][1]-axes[0][1]); axes[1][2] = axes[0][2] + axeslen*(axes[1][2]-axes[0][2]); axes[2][0] = axes[0][0] + axeslen*(axes[2][0]-axes[0][0]); axes[2][1] = axes[0][1] + axeslen*(axes[2][1]-axes[0][1]); axes[2][2] = axes[0][2] + axeslen*(axes[2][2]-axes[0][2]); axes[3][0] = axes[0][0] + axeslen*(axes[3][0]-axes[0][0]); axes[3][1] = axes[0][1] + axeslen*(axes[3][1]-axes[0][1]); axes[3][2] = axes[0][2] + axeslen*(axes[3][2]-axes[0][2]); image->draw_axes(axes,diameter); } } /* ---------------------------------------------------------------------- */ int DumpImage::pack_comm(int n, int *list, double *buf, int pbc_flag, int *pbc) { int i,j,m; m = 0; if (comm_forward == 1) { for (i = 0; i < n; i++) { j = list[i]; buf[m++] = chooseghost[j]; } } else { for (i = 0; i < n; i++) { j = list[i]; buf[m++] = chooseghost[j]; buf[m++] = bufcopy[j][0]; buf[m++] = bufcopy[j][1]; } } return comm_forward; } /* ---------------------------------------------------------------------- */ void DumpImage::unpack_comm(int n, int first, double *buf) { int i,m,last; m = 0; last = first + n; if (comm_forward == 1) for (i = first; i < last; i++) chooseghost[i] = static_cast<int> (buf[m++]); else { for (i = first; i < last; i++) { chooseghost[i] = static_cast<int> (buf[m++]); bufcopy[i][0] = buf[m++]; bufcopy[i][1] = buf[m++]; } } } /* ---------------------------------------------------------------------- */ int DumpImage::modify_param(int narg, char **arg) { int n = DumpCustom::modify_param(narg,arg); if (n) return n; if (strcmp(arg[0],"acolor") == 0) { if (narg < 3) error->all(FLERR,"Illegal dump_modify command"); int nlo,nhi; force->bounds(arg[1],atom->ntypes,nlo,nhi); // ptrs = list of ncount colornames separated by '/' int ncount = 1; char *nextptr; char *ptr = arg[2]; while (nextptr = strchr(ptr,'/')) { ptr = nextptr + 1; ncount++; } char **ptrs = new char*[ncount+1]; ncount = 0; ptrs[ncount++] = strtok(arg[2],"/"); while (ptrs[ncount++] = strtok(NULL,"/")); ncount--; // assign each of ncount colors in round-robin fashion to types int m = 0; for (int i = nlo; i <= nhi; i++) { colortype[i] = image->color2rgb(ptrs[m%ncount]); if (colortype[i] == NULL) error->all(FLERR,"Invalid color in dump_modify command"); m++; } delete [] ptrs; return 3; } if (strcmp(arg[0],"adiam") == 0) { if (narg < 3) error->all(FLERR,"Illegal dump_modify command"); int nlo,nhi; force->bounds(arg[1],atom->ntypes,nlo,nhi); double diam = force->numeric(FLERR,arg[2]); if (diam <= 0.0) error->all(FLERR,"Illegal dump_modify command"); for (int i = nlo; i <= nhi; i++) diamtype[i] = diam; return 3; } if (strcmp(arg[0],"amap") == 0) { if (narg < 6) error->all(FLERR,"Illegal dump_modify command"); if (strlen(arg[3]) != 2) error->all(FLERR,"Illegal dump_modify command"); int factor = 2; if (arg[3][0] == 's') factor = 1; int nentry = force->inumeric(FLERR,arg[5]); if (nentry < 1) error->all(FLERR,"Illegal dump_modify command"); int n = 6 + factor*nentry; if (narg < n) error->all(FLERR,"Illegal dump_modify command"); int flag = image->map_reset(0,n-1,&arg[1]); if (flag) error->all(FLERR,"Illegal dump_modify command"); return n; } if (strcmp(arg[0],"bcolor") == 0) { if (narg < 3) error->all(FLERR,"Illegal dump_modify command"); if (atom->nbondtypes == 0) error->all(FLERR,"Dump modify bcolor not allowed with no bond types"); int nlo,nhi; force->bounds(arg[1],atom->nbondtypes,nlo,nhi); // ptrs = list of ncount colornames separated by '/' int ncount = 1; char *nextptr; char *ptr = arg[2]; while (nextptr = strchr(ptr,'/')) { ptr = nextptr + 1; ncount++; } char **ptrs = new char*[ncount+1]; ncount = 0; ptrs[ncount++] = strtok(arg[2],"/"); while (ptrs[ncount++] = strtok(NULL,"/")); ncount--; // assign each of ncount colors in round-robin fashion to types int m = 0; for (int i = nlo; i <= nhi; i++) { bcolortype[i] = image->color2rgb(ptrs[m%ncount]); if (bcolortype[i] == NULL) error->all(FLERR,"Invalid color in dump_modify command"); m++; } delete [] ptrs; return 3; } if (strcmp(arg[0],"bdiam") == 0) { if (narg < 3) error->all(FLERR,"Illegal dump_modify command"); if (atom->nbondtypes == 0) error->all(FLERR,"Dump modify bdiam not allowed with no bond types"); int nlo,nhi; force->bounds(arg[1],atom->ntypes,nlo,nhi); double diam = force->numeric(FLERR,arg[2]); if (diam <= 0.0) error->all(FLERR,"Illegal dump_modify command"); for (int i = nlo; i <= nhi; i++) bdiamtype[i] = diam; return 3; } if (strcmp(arg[0],"backcolor") == 0) { if (narg < 2) error->all(FLERR,"Illegal dump_modify command"); double *color = image->color2rgb(arg[1]); if (color == NULL) error->all(FLERR,"Invalid color in dump_modify command"); image->background[0] = static_cast<int> (color[0]*255.0); image->background[1] = static_cast<int> (color[1]*255.0); image->background[2] = static_cast<int> (color[2]*255.0); return 2; } if (strcmp(arg[0],"boxcolor") == 0) { if (narg < 2) error->all(FLERR,"Illegal dump_modify command"); image->boxcolor = image->color2rgb(arg[1]); if (image->boxcolor == NULL) error->all(FLERR,"Invalid color in dump_modify command"); return 2; } if (strcmp(arg[0],"color") == 0) { if (narg < 5) error->all(FLERR,"Illegal dump_modify command"); int flag = image->addcolor(arg[1],force->numeric(FLERR,arg[2]),force->numeric(FLERR,arg[3]),force->numeric(FLERR,arg[4])); if (flag) error->all(FLERR,"Illegal dump_modify command"); return 5; } return 0; } diff --git a/src/dump_image.h b/src/dump_image.h index 53230b6cb..9c42c584c 100644 --- a/src/dump_image.h +++ b/src/dump_image.h @@ -1,184 +1,190 @@ -/* ---------------------------------------------------------------------- +/* -*- 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. ------------------------------------------------------------------------- */ #ifdef DUMP_CLASS DumpStyle(image,DumpImage) #else #ifndef LMP_DUMP_IMAGE_H #define LMP_DUMP_IMAGE_H #include "dump_custom.h" namespace LAMMPS_NS { class DumpImage : public DumpCustom { public: DumpImage(class LAMMPS *, int, char**); - ~DumpImage(); + virtual ~DumpImage(); int pack_comm(int, int *, double *, int, int *); void unpack_comm(int, int, double *); - private: + protected: int filetype; + enum{PPM,JPG,PNG}; + int acolor,adiam; // what determines color/diam of atoms double adiamvalue; // atom diameter value int atomflag,bondflag; // 0/1 for draw atoms,bonds int bcolor,bdiam; // what determines color/diam of bonds double bdiamvalue; // bond diameter value char *thetastr,*phistr; // variables for view theta,phi int thetavar,phivar; // index to theta,phi vars int cflag; // static/dynamic box center double cx,cy,cz; // fractional box center char *cxstr,*cystr,*czstr; // variables for box center int cxvar,cyvar,czvar; // index to box center vars char *upxstr,*upystr,*upzstr; // view up vector variables int upxvar,upyvar,upzvar; // index to up vector vars char *zoomstr,*perspstr; // view zoom and perspective variables int zoomvar,perspvar; // index to zoom,persp vars int boxflag,axesflag; // 0/1 for draw box and axes double boxdiam,axeslen,axesdiam; // params for drawing box and axes int viewflag; // overall view is static or dynamic double *diamtype,*diamelement,*bdiamtype; // per-type diameters double **colortype,**colorelement,**bcolortype; // per-type colors class Image *image; // class that renders each image int *chooseghost; // extended choose array for comm double **bufcopy; // buffer for communicating bond/atom info int maxbufcopy; - void init_style(); + virtual void init_style(); int modify_param(int, char **); void write(); void box_center(); void view_params(); void box_bounds(); void create_image(); }; } #endif #endif /* ERROR/WARNING messages: E: Invalid dump image filename The file produced by dump image cannot be binary and must be for a single processor. -E: Cannot dump JPG file +E: Support for writing images in JPEG format not included LAMMPS was not built with the -DLAMMPS_JPEG switch in the Makefile. +E: Support for writing images in PNG format not included + +LAMMPS was not built with the -DLAMMPS_PNG switch in the Makefile. + E: Illegal ... command Self-explanatory. Check the input script syntax and compare to the documentation for the command. You can use -echo screen as a command-line option when running LAMMPS to see the offending line. E: Dump image bond not allowed with no bond types Self-explanatory. E: Invalid dump image theta value Theta must be between 0.0 and 180.0 inclusive. E: Dump image persp option is not yet supported Self-explanatory. E: Dump image requires one snapshot per file Use a "*" in the filename. E: Dump image cannot perform sorting Self-explanatory. E: Variable name for dump image theta does not exist Self-explanatory. E: Variable for dump image theta is invalid style Must be an equal-style variable. E: Variable name for dump image phi does not exist Self-explanatory. E: Variable for dump image phi is invalid style Must be an equal-style variable. E: Variable name for dump image center does not exist Self-explanatory. E: Variable for dump image center is invalid style Must be an equal-style variable. E: Variable name for dump image zoom does not exist Self-explanatory. E: Variable for dump image zoom is invalid style Must be an equal-style variable. E: Variable name for dump image persp does not exist Self-explanatory. E: Variable for dump image persp is invalid style Must be an equal-style variable. E: Invalid dump image element name The specified element name was not in the standard list of elements. See the dump_modify doc page. E: Invalid dump image zoom value Zoom value must be > 0.0. E: Invalid dump image persp value Persp value must be >= 0.0. E: Invalid color in dump_modify command The specified color name was not in the list of recognized colors. See the dump_modify doc page. E: Dump modify bcolor not allowed with no bond types Self-explanatory. E: Dump modify bdiam not allowed with no bond types Self-explanatory. */ diff --git a/src/dump_movie.cpp b/src/dump_movie.cpp new file mode 100644 index 000000000..6c11f64e1 --- /dev/null +++ b/src/dump_movie.cpp @@ -0,0 +1,106 @@ +/* ---------------------------------------------------------------------- + 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: Axel Kohlmeyer (Temple U) +------------------------------------------------------------------------- */ + +#include "stdio.h" +#include "stdlib.h" +#include "string.h" +#include "dump_movie.h" +#include "comm.h" +#include "force.h" +#include "memory.h" +#include "error.h" + +using namespace LAMMPS_NS; + +/* ---------------------------------------------------------------------- */ + +DumpMovie::DumpMovie(LAMMPS *lmp, int narg, char **arg) : + DumpImage(lmp, narg, arg) +{ + if (multiproc || compressed || multifile) + error->all(FLERR,"Invalid dump movie filename"); + + filetype = PPM; + bitrate = 2000; + framerate = 24; + fp = NULL; +} + +/* ---------------------------------------------------------------------- */ + +void DumpMovie::openfile() +{ + char moviecmd[1024]; + + if ((comm->me == 0) && (fp == NULL)) { + +#ifdef LAMMPS_FFMPEG + sprintf(moviecmd,"ffmpeg -v error -y -r %.2f -f image2pipe -c:v ppm -i - " + "-r 24.0 -b:v %dk %s ", framerate, bitrate, filename); +#else + error->one(FLERR,"Cannot generate movie file"); +#endif + +#if defined(_WIN32) + fp = _popen(moviecmd,"wb"); +#else + fp = popen(moviecmd,"w"); +#endif + + if (fp == NULL) { + char str[128]; + sprintf(str,"Failed to open FFmpeg pipeline to file %s",filename); + error->one(FLERR,str); + } + } +} +/* ---------------------------------------------------------------------- */ + +void DumpMovie::init_style() +{ + // initialize image style circumventing multifile check + + multifile = 1; + DumpImage::init_style(); + multifile = 0; +} + +/* ---------------------------------------------------------------------- */ + +int DumpMovie::modify_param(int narg, char **arg) +{ + int n = DumpImage::modify_param(narg,arg); + if (n) return n; + + if (strcmp(arg[0],"bitrate") == 0) { + if (narg < 2) error->all(FLERR,"Illegal dump_modify command"); + bitrate = force->inumeric(FLERR,arg[1]); + if (bitrate <= 0.0) error->all(FLERR,"Illegal dump_modify command"); + return 2; + } + + if (strcmp(arg[0],"framerate") == 0) { + if (narg < 2) error->all(FLERR,"Illegal dump_modify command"); + framerate = force->numeric(FLERR,arg[1]); + if ((framerate <= 0.1) || (framerate > 24.0)) + error->all(FLERR,"Illegal dump_modify framerate command"); + return 2; + } + + return 0; +} + diff --git a/src/dump_movie.h b/src/dump_movie.h new file mode 100644 index 000000000..2cb4d878d --- /dev/null +++ b/src/dump_movie.h @@ -0,0 +1,73 @@ +/* -*- 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. +------------------------------------------------------------------------- */ + +#ifdef DUMP_CLASS + +DumpStyle(movie,DumpMovie) + +#else + +#ifndef LMP_DUMP_MOVIE_H +#define LMP_DUMP_MOVIE_H + +#include "dump_image.h" + +namespace LAMMPS_NS { + +class DumpMovie : public DumpImage { + public: + DumpMovie(LAMMPS *, int, char**); + + virtual void openfile(); + virtual void init_style(); + virtual int modify_param(int, char **); + + protected: + double framerate; // frame rate of animation + int bitrate; // bitrate of video file in kbps +}; + +} + +#endif +#endif + +/* ERROR/WARNING messages: + +E: Invalid dump movie filename + +The file produced by dump movie cannot be binary or compressed +and must be a single file for a single processor. + +E: Cannot generate movie file + +LAMMPS was built without the -DLAMMPS_FFMPEG switch in the Makefile + +E: Illegal ... command + +Self-explanatory. Check the input script syntax and compare to the +documentation for the command. You can use -echo screen as a +command-line option when running LAMMPS to see the offending line. + +E: pipe:: Input/output error + +Harmless. This happens when the pipeline to FFmpeg is closed and no +more image data is sent to be appended to the movie. FFmpeg will +simply terminate and close the movie file. + +E: Failed to open FFmpeg pipeline to file %s + +The specified file cannot be opened. Check that the path and name are +correct and writable and that the FFmpeg executable can be found and run. + +*/ diff --git a/src/fix_tmd.cpp b/src/fix_tmd.cpp index e8ab940d6..11c8c7920 100644 --- a/src/fix_tmd.cpp +++ b/src/fix_tmd.cpp @@ -1,541 +1,547 @@ /* ---------------------------------------------------------------------- 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 authors: Paul Crozier (SNL) Christian Burisch (Bochum Univeristy, Germany) ------------------------------------------------------------------------- */ #include "lmptype.h" #include "mpi.h" #include "math.h" #include "stdlib.h" #include "string.h" #include "fix_tmd.h" #include "atom.h" #include "update.h" #include "modify.h" #include "domain.h" #include "group.h" #include "respa.h" #include "force.h" #include "memory.h" #include "error.h" using namespace LAMMPS_NS; using namespace FixConst; #define CHUNK 1000 #define MAXLINE 256 /* ---------------------------------------------------------------------- */ FixTMD::FixTMD(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, narg, arg) { if (narg < 6) error->all(FLERR,"Illegal fix tmd command"); rho_stop = force->numeric(FLERR,arg[3]); nfileevery = force->inumeric(FLERR,arg[5]); if (rho_stop < 0 || nfileevery < 0) error->all(FLERR,"Illegal fix tmd command"); if (nfileevery && narg != 7) error->all(FLERR,"Illegal fix tmd command"); MPI_Comm_rank(world,&me); // perform initial allocation of atom-based arrays // register with Atom class xf = NULL; xold = NULL; grow_arrays(atom->nmax); atom->add_callback(0); // make sure an atom map exists before reading in target coordinates if (atom->map_style == 0) error->all(FLERR,"Cannot use fix TMD unless atom map exists"); // read from arg[4] and store coordinates of final target in xf readfile(arg[4]); // open arg[6] statistics file and write header if (nfileevery) { if (narg != 7) error->all(FLERR,"Illegal fix tmd command"); if (me == 0) { fp = fopen(arg[6],"w"); if (fp == NULL) { char str[128]; sprintf(str,"Cannot open fix tmd file %s",arg[6]); error->one(FLERR,str); } fprintf(fp,"%s %s\n","# Step rho_target rho_old gamma_back", "gamma_forward lambda work_lambda work_analytical"); } } masstotal = group->mass(igroup); // rho_start = initial rho // xold = initial x or 0.0 if not in group int *mask = atom->mask; int *type = atom->type; tagint *image = atom->image; double **x = atom->x; double *mass = atom->mass; int nlocal = atom->nlocal; double dx,dy,dz; rho_start = 0.0; for (int i = 0; i < nlocal; i++) { if (mask[i] & groupbit) { domain->unmap(x[i],image[i],xold[i]); dx = xold[i][0] - xf[i][0]; dy = xold[i][1] - xf[i][1]; dz = xold[i][2] - xf[i][2]; rho_start += mass[type[i]]*(dx*dx + dy*dy + dz*dz); } else xold[i][0] = xold[i][1] = xold[i][2] = 0.0; } double rho_start_total; MPI_Allreduce(&rho_start,&rho_start_total,1,MPI_DOUBLE,MPI_SUM,world); rho_start = sqrt(rho_start_total/masstotal); rho_old = rho_start; work_lambda = 0.0; work_analytical = 0.0; previous_stat = 0; } /* ---------------------------------------------------------------------- */ FixTMD::~FixTMD() { if (nfileevery && me == 0) fclose(fp); // unregister callbacks to this fix from Atom class atom->delete_callback(id,0); // delete locally stored arrays memory->destroy(xf); memory->destroy(xold); } /* ---------------------------------------------------------------------- */ int FixTMD::setmask() { int mask = 0; mask |= INITIAL_INTEGRATE; mask |= INITIAL_INTEGRATE_RESPA; return mask; } /* ---------------------------------------------------------------------- */ void FixTMD::init() { // check that no integrator fix comes after a TMD fix int flag = 0; for (int i = 0; i < modify->nfix; i++) { if (strcmp(modify->fix[i]->style,"tmd") == 0) flag = 1; if (flag && strcmp(modify->fix[i]->style,"nve") == 0) flag = 2; if (flag && strcmp(modify->fix[i]->style,"nvt") == 0) flag = 2; if (flag && strcmp(modify->fix[i]->style,"npt") == 0) flag = 2; if (flag && strcmp(modify->fix[i]->style,"nph") == 0) flag = 2; } if (flag == 2) error->all(FLERR,"Fix tmd must come after integration fixes"); // timesteps dtv = update->dt; dtf = update->dt * force->ftm2v; if (strstr(update->integrate_style,"respa")) step_respa = ((Respa *) update->integrate)->step; } /* ---------------------------------------------------------------------- */ void FixTMD::initial_integrate(int vflag) { double a,b,c,d,e; double dx,dy,dz,dxkt,dykt,dzkt; double dxold,dyold,dzold,xback,yback,zback; double gamma_forward,gamma_back,gamma_max,lambda; double kt,fr,kttotal,frtotal,dtfm; double unwrap[3]; double **x = atom->x; double **v = atom->v; double **f = atom->f; double *mass = atom->mass; tagint *image = atom->image; int *type = atom->type; int *mask = atom->mask; int nlocal = atom->nlocal; double delta = update->ntimestep - update->beginstep; if (delta != 0.0) delta /= update->endstep - update->beginstep; double rho_target = rho_start + delta * (rho_stop - rho_start); // compute the Lagrange multiplier a = b = e = 0.0; for (int i = 0; i < nlocal; i++) { if (mask[i] & groupbit) { dxold = xold[i][0] - xf[i][0]; dyold = xold[i][1] - xf[i][1]; dzold = xold[i][2] - xf[i][2]; domain->unmap(x[i],image[i],unwrap); dx = unwrap[0] - xf[i][0]; dy = unwrap[1] - xf[i][1]; dz = unwrap[2] - xf[i][2]; a += mass[type[i]]*(dxold*dxold + dyold*dyold + dzold*dzold); b += mass[type[i]]*(dx *dxold + dy *dyold + dz *dzold); e += mass[type[i]]*(dx *dx + dy *dy + dz *dz); } } double abe[3],abetotal[3]; abe[0] = a; abe[1] = b; abe[2] = e; MPI_Allreduce(abe,abetotal,3,MPI_DOUBLE,MPI_SUM,world); a = abetotal[0]/masstotal; b = 2.0*abetotal[1]/masstotal; e = abetotal[2]/masstotal; c = e - rho_old*rho_old; d = b*b - 4*a*c; if (d < 0) d = 0; if (b >= 0) gamma_max = (-b - sqrt(d))/(2*a); else gamma_max = (-b + sqrt(d))/(2*a); gamma_back = c/(a*gamma_max); if (a == 0.0) gamma_back = 0; c = e - rho_target*rho_target; d = b*b - 4*a*c; if (d < 0) d = 0; if (b >= 0) gamma_max = (-b - sqrt(d))/(2*a); else gamma_max = (-b + sqrt(d))/(2*a); gamma_forward = c/(a*gamma_max); if (a == 0.0) gamma_forward = 0; fr = kt = 0.0; for (int i = 0; i < nlocal; i++) { if (mask[i] & groupbit) { dxold = xold[i][0] - xf[i][0]; dyold = xold[i][1] - xf[i][1]; dzold = xold[i][2] - xf[i][2]; domain->unmap(x[i],image[i],unwrap); xback = unwrap[0] + gamma_back*dxold; yback = unwrap[1] + gamma_back*dyold; zback = unwrap[2] + gamma_back*dzold; dxkt = xback - xold[i][0]; dykt = yback - xold[i][1]; dzkt = zback - xold[i][2]; kt += mass[type[i]]*(dxkt*dxkt + dykt*dykt + dzkt*dzkt); fr += f[i][0]*dxold + f[i][1]*dyold + f[i][2]*dzold; } } double r[2],rtotal[2]; r[0] = fr; r[1] = kt; MPI_Allreduce(r,rtotal,2,MPI_DOUBLE,MPI_SUM,world); frtotal = rtotal[0]; kttotal = rtotal[1]; // stat write of mean constraint force based on previous time step constraint if (nfileevery && me == 0) { work_analytical += (-frtotal - kttotal/dtv/dtf)*(rho_target - rho_old)/rho_old; lambda = gamma_back*rho_old*masstotal/dtv/dtf; work_lambda += lambda*(rho_target - rho_old); if (!(update->ntimestep % nfileevery) && (previous_stat != update->ntimestep)) { fprintf(fp, BIGINT_FORMAT " %g %g %g %g %g %g %g\n", update->ntimestep,rho_target,rho_old, gamma_back,gamma_forward,lambda,work_lambda,work_analytical); fflush(fp); previous_stat = update->ntimestep; } } rho_old = rho_target; // apply the constraint and save constrained positions for next step for (int i = 0; i < nlocal; i++) { if (mask[i] & groupbit) { dtfm = dtf / mass[type[i]]; dxold = xold[i][0] - xf[i][0]; x[i][0] += gamma_forward*dxold; v[i][0] += gamma_forward*dxold/dtv; f[i][0] += gamma_forward*dxold/dtv/dtfm; dyold = xold[i][1] - xf[i][1]; x[i][1] += gamma_forward*dyold; v[i][1] += gamma_forward*dyold/dtv; f[i][1] += gamma_forward*dyold/dtv/dtfm; dzold = xold[i][2] - xf[i][2]; x[i][2] += gamma_forward*dzold; v[i][2] += gamma_forward*dzold/dtv; f[i][2] += gamma_forward*dzold/dtv/dtfm; domain->unmap(x[i],image[i],xold[i]); } } } /* ---------------------------------------------------------------------- */ void FixTMD::initial_integrate_respa(int vflag, int ilevel, int flag) { if (flag) return; // only used by NPT,NPH dtv = step_respa[ilevel]; dtf = step_respa[ilevel] * force->ftm2v; if (ilevel == 0) initial_integrate(vflag); } /* ---------------------------------------------------------------------- memory usage of local atom-based arrays ------------------------------------------------------------------------- */ double FixTMD::memory_usage() { double bytes = 2*atom->nmax*3 * sizeof(double); return bytes; } /* ---------------------------------------------------------------------- allocate atom-based arrays ------------------------------------------------------------------------- */ void FixTMD::grow_arrays(int nmax) { memory->grow(xf,nmax,3,"fix_tmd:xf"); memory->grow(xold,nmax,3,"fix_tmd:xold"); } /* ---------------------------------------------------------------------- copy values within local atom-based arrays ------------------------------------------------------------------------- */ void FixTMD::copy_arrays(int i, int j, int delflag) { xf[j][0] = xf[i][0]; xf[j][1] = xf[i][1]; xf[j][2] = xf[i][2]; xold[j][0] = xold[i][0]; xold[j][1] = xold[i][1]; xold[j][2] = xold[i][2]; } /* ---------------------------------------------------------------------- pack values in local atom-based arrays for exchange with another proc ------------------------------------------------------------------------- */ int FixTMD::pack_exchange(int i, double *buf) { buf[0] = xf[i][0]; buf[1] = xf[i][1]; buf[2] = xf[i][2]; buf[3] = xold[i][0]; buf[4] = xold[i][1]; buf[5] = xold[i][2]; return 6; } /* ---------------------------------------------------------------------- unpack values in local atom-based arrays from exchange with another proc ------------------------------------------------------------------------- */ int FixTMD::unpack_exchange(int nlocal, double *buf) { xf[nlocal][0] = buf[0]; xf[nlocal][1] = buf[1]; xf[nlocal][2] = buf[2]; xold[nlocal][0] = buf[3]; xold[nlocal][1] = buf[4]; xold[nlocal][2] = buf[5]; return 6; } /* ---------------------------------------------------------------------- read target coordinates from file, store with appropriate atom ------------------------------------------------------------------------- */ void FixTMD::readfile(char *file) { if (me == 0) { if (screen) fprintf(screen,"Reading TMD target file %s ...\n",file); open(file); } int *mask = atom->mask; int nlocal = atom->nlocal; char *buffer = new char[CHUNK*MAXLINE]; - char *ptr,*next,*bufptr; + char *next,*bufptr; int i,m,nlines,tag,imageflag,ix,iy,iz; double x,y,z,xprd,yprd,zprd; int firstline = 1; int ncount = 0; char *eof = NULL; xprd = yprd = zprd = -1.0; while (!eof) { if (me == 0) { m = 0; for (nlines = 0; nlines < CHUNK; nlines++) { eof = fgets(&buffer[m],MAXLINE,fp); if (eof == NULL) break; m += strlen(&buffer[m]); } if (buffer[m-1] != '\n') strcpy(&buffer[m++],"\n"); m++; } MPI_Bcast(&eof,1,MPI_INT,0,world); MPI_Bcast(&nlines,1,MPI_INT,0,world); MPI_Bcast(&m,1,MPI_INT,0,world); MPI_Bcast(buffer,m,MPI_CHAR,0,world); bufptr = buffer; for (i = 0; i < nlines; i++) { next = strchr(bufptr,'\n'); *next = '\0'; if (firstline) { if (strstr(bufptr,"xlo xhi")) { double lo,hi; sscanf(bufptr,"%lg %lg",&lo,&hi); xprd = hi - lo; bufptr = next + 1; continue; } else if (strstr(bufptr,"ylo yhi")) { double lo,hi; sscanf(bufptr,"%lg %lg",&lo,&hi); yprd = hi - lo; bufptr = next + 1; continue; } else if (strstr(bufptr,"zlo zhi")) { double lo,hi; sscanf(bufptr,"%lg %lg",&lo,&hi); zprd = hi - lo; bufptr = next + 1; continue; } else if (atom->count_words(bufptr) == 4) { if (xprd >= 0.0 || yprd >= 0.0 || zprd >= 0.0) error->all(FLERR,"Incorrect format in TMD target file"); imageflag = 0; firstline = 0; } else if (atom->count_words(bufptr) == 7) { if (xprd < 0.0 || yprd < 0.0 || zprd < 0.0) error->all(FLERR,"Incorrect format in TMD target file"); imageflag = 1; firstline = 0; } else error->all(FLERR,"Incorrect format in TMD target file"); } if (imageflag) sscanf(bufptr,"%d %lg %lg %lg %d %d %d",&tag,&x,&y,&z,&ix,&iy,&iz); else sscanf(bufptr,"%d %lg %lg %lg",&tag,&x,&y,&z); m = atom->map(tag); if (m >= 0 && m < nlocal && mask[m] & groupbit) { if (imageflag) { xf[m][0] = x + ix*xprd; xf[m][1] = y + iy*yprd; xf[m][2] = z + iz*zprd; } else { xf[m][0] = x; xf[m][1] = y; xf[m][2] = z; } ncount++; } bufptr = next + 1; } } // clean up delete [] buffer; if (me == 0) { if (compressed) pclose(fp); else fclose(fp); } // check that all atoms in group were listed in target file // set xf = 0.0 for atoms not in group int gcount = 0; for (i = 0; i < nlocal; i++) if (mask[i] & groupbit) gcount++; else xf[i][0] = xf[i][1] = xf[i][2] = 0.0; int flag = 0; if (gcount != ncount) flag = 1; int flagall; MPI_Allreduce(&flag,&flagall,1,MPI_INT,MPI_SUM,world); if (flagall) error->all(FLERR,"TMD target file did not list all group atoms"); } /* ---------------------------------------------------------------------- proc 0 opens TMD data file test if gzipped ------------------------------------------------------------------------- */ void FixTMD::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); + sprintf(gunzip,"gzip -c -d %s",file); + +#ifdef _WIN32 + fp = _popen(gunzip,"rb"); +#else fp = popen(gunzip,"r"); +#endif + #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); } } /* ---------------------------------------------------------------------- */ void FixTMD::reset_dt() { dtv = update->dt; dtf = update->dt * force->ftm2v; } diff --git a/src/fix_tmd.h b/src/fix_tmd.h index a6b96fbb1..d00bb303e 100644 --- a/src/fix_tmd.h +++ b/src/fix_tmd.h @@ -1,109 +1,110 @@ -/* ---------------------------------------------------------------------- +/* -*- 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. ------------------------------------------------------------------------- */ #ifdef FIX_CLASS FixStyle(tmd,FixTMD) #else #ifndef LMP_FIX_TMD_H #define LMP_FIX_TMD_H #include "stdio.h" #include "fix.h" namespace LAMMPS_NS { class FixTMD : public Fix { public: FixTMD(class LAMMPS *, int, char **); ~FixTMD(); int setmask(); void init(); void initial_integrate(int); void initial_integrate_respa(int, int, int); double memory_usage(); void grow_arrays(int); void copy_arrays(int, int, int); int pack_exchange(int, double *); int unpack_exchange(int, double *); void reset_dt(); private: int me; int nfileevery,compressed; bigint previous_stat; FILE *fp; double rho_start,rho_stop,rho_old,masstotal; double dtv,dtf; double *step_respa; double work_lambda,work_analytical; double **xf,**xold; void readfile(char *); void open(char *); }; } #endif #endif /* ERROR/WARNING messages: E: Illegal ... command Self-explanatory. Check the input script syntax and compare to the documentation for the command. You can use -echo screen as a command-line option when running LAMMPS to see the offending line. E: Cannot use fix TMD unless atom map exists Using this fix requires the ability to lookup an atom index, which is provided by an atom map. An atom map does not exist (by default) for non-molecular problems. Using the atom_modify map command will force an atom map to be created. E: Cannot open fix tmd file %s The output file for the fix tmd command cannot be opened. Check that the path and name are correct. E: Fix tmd must come after integration fixes Any fix tmd command must appear in the input script after all time integration fixes (nve, nvt, npt). See the fix tmd documentation for details. E: Incorrect format in TMD target file Format of file read by fix tmd command is incorrect. E: TMD target file did not list all group atoms The target file for the fix tmd command did not list all atoms in the fix group. E: Cannot open gzipped file -LAMMPS is attempting to open a gzipped version of the specified file -but was unsuccessful. Check that the path and name are correct. +LAMMPS was compiled without support for reading and writing gzipped +files through a pipeline to the gzip program with -DLAMMPS_GZIP. E: Cannot open file %s The specified file cannot be opened. Check that the path and name are -correct. +correct. If the file is a compressed file, also check that the gzip +executable can be found and run. */ diff --git a/src/reader.cpp b/src/reader.cpp index 79dbb1c04..588b21062 100644 --- a/src/reader.cpp +++ b/src/reader.cpp @@ -1,69 +1,75 @@ /* ---------------------------------------------------------------------- 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 "stdio.h" #include "string.h" #include "reader.h" #include "error.h" using namespace LAMMPS_NS; /* ---------------------------------------------------------------------- */ Reader::Reader(LAMMPS *lmp) : Pointers(lmp) { fp = NULL; } /* ---------------------------------------------------------------------- try to open given file generic version for ASCII files that may be compressed ------------------------------------------------------------------------- */ void Reader::open_file(const char *file) { if (fp != NULL) close_file(); compressed = 0; const 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[1024]; - sprintf(gunzip,"gunzip -c %s",file); + sprintf(gunzip,"gzip -c -d %s",file); + +#ifdef _WIN32 + fp = _popen(gunzip,"rb"); +#else fp = popen(gunzip,"r"); +#endif + #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 file if open generic version for ASCII files that may be compressed ------------------------------------------------------------------------- */ void Reader::close_file() { if (fp == NULL) return; if (compressed) pclose(fp); else fclose(fp); fp = NULL; } diff --git a/src/reader.h b/src/reader.h index 571016ba7..8f36bf622 100644 --- a/src/reader.h +++ b/src/reader.h @@ -1,60 +1,61 @@ /* -*- 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. Contributed by Timothy Sirk ------------------------------------------------------------------------- */ #ifndef LMP_READER_H #define LMP_READER_H #include "pointers.h" namespace LAMMPS_NS { class Reader : protected Pointers { public: Reader(class LAMMPS *); virtual ~Reader() {} virtual void settings(int, char**) {}; virtual int read_time(bigint &) = 0; virtual void skip() = 0; virtual bigint read_header(double [3][3], int &, int, int, int *, char **, int, int, int &, int &, int &, int &) = 0; virtual void read_atoms(int, int, double **) = 0; virtual void open_file(const char *); virtual void close_file(); protected: FILE *fp; // pointer to opened file or pipe int compressed; // flag for dump file compression }; } #endif /* ERROR/WARNING messages: E: Cannot open gzipped file -LAMMPS is attempting to open a gzipped version of the specified file -but was unsuccessful. Check that the path and name are correct. +LAMMPS was compiled without support for reading and writing gzipped +files through a pipeline to the gzip program with -DLAMMPS_GZIP. E: Cannot open file %s The specified file cannot be opened. Check that the path and name are -correct. +correct. If the file is a compressed file, also check that the gzip +executable can be found and run. */