diff --git a/src/citeme.cpp b/src/citeme.cpp index 5d6118d28a..75896011a7 100644 --- a/src/citeme.cpp +++ b/src/citeme.cpp @@ -40,13 +40,16 @@ CiteMe::CiteMe(LAMMPS *lmp) : Pointers(lmp) CiteMe::~CiteMe() { - if (universe->me) return; - if (cs->size() == 0) return; + if (universe->me || cs->size() == 0) { + delete cs; + return; + } + + delete cs; if (screen) fprintf(screen,cite_nagline); if (logfile) fprintf(logfile,cite_nagline); - delete cs; if (fp) fclose(fp); } diff --git a/src/fix.cpp b/src/fix.cpp index ec172cbf12..b88f3b70ae 100644 --- a/src/fix.cpp +++ b/src/fix.cpp @@ -58,6 +58,7 @@ Fix::Fix(LAMMPS *lmp, int narg, char **arg) : Pointers(lmp) time_depend = 0; create_attribute = 0; restart_pbc = 0; + wd_header = wd_section = 0; cudable_comm = 0; scalar_flag = vector_flag = array_flag = 0; diff --git a/src/fix.h b/src/fix.h index 608c05ca30..c66552dfed 100644 --- a/src/fix.h +++ b/src/fix.h @@ -43,6 +43,8 @@ class Fix : protected Pointers { // setting when a new atom is created int restart_pbc; // 1 if fix moves atoms (except integrate) // so write_restart must remap to PBC + int wd_header; // # of header values fix writes to data file + int wd_section; // # of sections fix writes to data file int cudable_comm; // 1 if fix has CUDA-enabled communication int scalar_flag; // 0/1 if compute_scalar() function exists @@ -165,6 +167,12 @@ class Fix : protected Pointers { virtual void read_data_section(char *, int, char *) {} virtual bigint read_data_skip_lines(char *) {return 0;} + virtual void write_data_header(FILE *, int) {} + virtual void write_data_section_size(int, int &, int &) {} + virtual void write_data_section_pack(int, double **) {} + virtual void write_data_section_keyword(int, FILE *) {} + virtual void write_data_section(int, FILE *, int, double **, int) {} + virtual int modify_param(int, char **) {return 0;} virtual void *extract(const char *, int &) {return NULL;} diff --git a/src/fix_property_atom.cpp b/src/fix_property_atom.cpp index 25b1ea6f6e..80583ae41d 100644 --- a/src/fix_property_atom.cpp +++ b/src/fix_property_atom.cpp @@ -33,6 +33,7 @@ FixPropertyAtom::FixPropertyAtom(LAMMPS *lmp, int narg, char **arg) : if (narg < 4) error->all(FLERR,"Illegal fix property/atom command"); restart_peratom = 1; + wd_section = 1; int iarg = 3; nvalue = narg-iarg; @@ -150,7 +151,7 @@ void FixPropertyAtom::init() } /* ---------------------------------------------------------------------- - unpack section of data file + unpack N lines in buf from section of data file labeled by keyword ------------------------------------------------------------------------- */ void FixPropertyAtom::read_data_section(char *keyword, int n, char *buf) @@ -209,13 +210,95 @@ void FixPropertyAtom::read_data_section(char *keyword, int n, char *buf) delete [] values; } -/* ---------------------------------------------------------------------- */ +/* ---------------------------------------------------------------------- + return # of lines in section of data file labeled by keyword +------------------------------------------------------------------------- */ bigint FixPropertyAtom::read_data_skip_lines(char *keyword) { return atom->natoms; } +/* ---------------------------------------------------------------------- + return size I own for Mth data section + # of data sections = 1 for this fix + nx = # of local atoms + ny = columns = tag + nvalues +------------------------------------------------------------------------- */ + +void FixPropertyAtom::write_data_section_size(int mth, int &nx, int &ny) +{ + nx = atom->nlocal; + ny = nvalue + 1; +} + +/* ---------------------------------------------------------------------- + pack values for Mth data section into buf + buf allocated by caller as Nlocal by Nvalues+1 +------------------------------------------------------------------------- */ + +void FixPropertyAtom::write_data_section_pack(int mth, double **buf) +{ + int i; + + // 1st column = atom tag + // rest of columns = per-atom values + + int *tag = atom->tag; + int nlocal = atom->nlocal; + + for (i = 0; i < nlocal; i++) buf[i][0] = tag[i]; + + for (int m = 0; m < nvalue; m++) { + int mp1 = m+1; + if (style[m] == MOLECULE) { + int *molecule = atom->molecule; + for (i = 0; i < nlocal; i++) buf[i][mp1] = molecule[i]; + } else if (style[m] == INTEGER) { + int *vec = atom->ivector[index[m]]; + for (i = 0; i < nlocal; i++) buf[i][mp1] = vec[i]; + } else if (style[m] == DOUBLE) { + double *vec = atom->dvector[index[m]]; + for (i = 0; i < nlocal; i++) buf[i][mp1] = vec[i]; + } + } +} + +/* ---------------------------------------------------------------------- + write section keyword for Mth data section to file + use MOLECULE if that is only field, else use fix ID + only called by proc 0 +------------------------------------------------------------------------- */ + +void FixPropertyAtom::write_data_section_keyword(int mth, FILE *fp) +{ + if (nvalue == 1 && style[0] == MOLECULE) fprintf(fp,"\nMolecule\n\n"); + else fprintf(fp,"\n%s\n\n",id); +} + +/* ---------------------------------------------------------------------- + write N lines from buf to file + convert buf fields to int or double depending on styles + index can be used to prepend global numbering + only called by proc 0 +------------------------------------------------------------------------- */ + +void FixPropertyAtom::write_data_section(int mth, FILE *fp, + int n, double **buf, int index) +{ + int m; + + for (int i = 0; i < n; i++) { + fprintf(fp,TAGINT_FORMAT,static_cast (buf[i][0])); + for (m = 0; m < nvalue; m++) { + if (style[m] == MOLECULE || style[m] == INTEGER) + fprintf(fp," " TAGINT_FORMAT,static_cast (buf[i][m+1])); + else fprintf(fp," %g",buf[i][m+1]); + } + fprintf(fp,"\n"); + } +} + /* ---------------------------------------------------------------------- memory usage of local atom-based array ------------------------------------------------------------------------- */ diff --git a/src/fix_property_atom.h b/src/fix_property_atom.h index 15bb7aab4a..85e84bb284 100644 --- a/src/fix_property_atom.h +++ b/src/fix_property_atom.h @@ -33,6 +33,10 @@ class FixPropertyAtom : public Fix { void read_data_section(char *, int, char *); bigint read_data_skip_lines(char *); + void write_data_section_size(int, int &, int &); + void write_data_section_pack(int, double **); + void write_data_section_keyword(int, FILE *); + void write_data_section(int, FILE *, int, double **, int); void grow_arrays(int); void copy_arrays(int, int, int); diff --git a/src/write_data.cpp b/src/write_data.cpp index 29ad151114..415b9e320a 100644 --- a/src/write_data.cpp +++ b/src/write_data.cpp @@ -26,6 +26,7 @@ #include "improper.h" #include "update.h" #include "modify.h" +#include "fix.h" #include "domain.h" #include "universe.h" #include "comm.h" @@ -106,12 +107,13 @@ void WriteData::command(int narg, char **arg) if (domain->triclinic) domain->lamda2x(atom->nlocal+atom->nghost); write(file); + delete [] file; } /* ---------------------------------------------------------------------- called from command() - later might let it be directly called within run/minimize loop + might later let it be directly called within run/minimize loop ------------------------------------------------------------------------- */ void WriteData::write(char *file) @@ -174,6 +176,12 @@ void WriteData::write(char *file) if (atom->ndihedrals) dihedrals(); if (atom->nimpropers) impropers(); + // extra sections managed by fixes + + for (int i = 0; i < modify->nfix; i++) + if (modify->fix[i]->wd_section) + for (int m = 0; m < modify->fix[i]->wd_section; m++) fix(i,m); + // close data file if (me == 0) fclose(fp); @@ -211,6 +219,11 @@ void WriteData::header() fprintf(fp,"%d improper types\n",atom->nimpropertypes); } + for (int i = 0; i < modify->nfix; i++) + if (modify->fix[i]->wd_header) + for (int m = 0; m < modify->fix[i]->wd_header; m++) + modify->fix[i]->write_data_header(fp,m); + fprintf(fp,"\n"); fprintf(fp,"%-1.16e %-1.16e xlo xhi\n",domain->boxlo[0],domain->boxhi[0]); @@ -397,7 +410,7 @@ void WriteData::bonds() int foo = atom->avec->pack_bond(buf); - // write one chunk of atoms per proc to file + // write one chunk of info per proc to file // proc 0 pings each proc, receives its chunk, writes to file // all other procs wait for ping, send their chunk to proc 0 @@ -450,7 +463,7 @@ void WriteData::angles() atom->avec->pack_angle(buf); - // write one chunk of atoms per proc to file + // write one chunk of info per proc to file // proc 0 pings each proc, receives its chunk, writes to file // all other procs wait for ping, send their chunk to proc 0 @@ -521,7 +534,7 @@ void WriteData::dihedrals() atom->avec->pack_dihedral(buf); - // write one chunk of atoms per proc to file + // write one chunk of info per proc to file // proc 0 pings each proc, receives its chunk, writes to file // all other procs wait for ping, send their chunk to proc 0 @@ -592,7 +605,7 @@ void WriteData::impropers() atom->avec->pack_improper(buf); - // write one chunk of atoms per proc to file + // write one chunk of info per proc to file // proc 0 pings each proc, receives its chunk, writes to file // all other procs wait for ping, send their chunk to proc 0 @@ -623,3 +636,56 @@ void WriteData::impropers() memory->destroy(buf); } + +/* ---------------------------------------------------------------------- + write out Mth section of data file owned by Fix ifix +------------------------------------------------------------------------- */ + +void WriteData::fix(int ifix, int mth) +{ + // communication buffer for Fix info + + int sendrow,ncol; + modify->fix[ifix]->write_data_section_size(mth,sendrow,ncol); + int maxrow; + MPI_Allreduce(&sendrow,&maxrow,1,MPI_INT,MPI_MAX,world); + + double **buf; + if (me == 0) memory->create(buf,MAX(1,maxrow),ncol,"write_data:buf"); + else memory->create(buf,MAX(1,sendrow),ncol,"write_data:buf"); + + // pack my fix data into buf + + modify->fix[ifix]->write_data_section_pack(mth,buf); + + // write one chunk of info per proc to file + // proc 0 pings each proc, receives its chunk, writes to file + // all other procs wait for ping, send their chunk to proc 0 + + int tmp,recvrow; + MPI_Status status; + MPI_Request request; + + int index = 1; + if (me == 0) { + modify->fix[ifix]->write_data_section_keyword(mth,fp); + for (int iproc = 0; iproc < nprocs; iproc++) { + if (iproc) { + MPI_Irecv(&buf[0][0],maxrow*ncol,MPI_DOUBLE,iproc,0,world,&request); + MPI_Send(&tmp,0,MPI_INT,iproc,0,world); + MPI_Wait(&request,&status); + MPI_Get_count(&status,MPI_DOUBLE,&recvrow); + recvrow /= ncol; + } else recvrow = sendrow; + + modify->fix[ifix]->write_data_section(mth,fp,recvrow,buf,index); + index += recvrow; + } + + } else { + MPI_Recv(&tmp,0,MPI_INT,0,0,world,&status); + MPI_Rsend(&buf[0][0],sendrow*ncol,MPI_DOUBLE,0,0,world); + } + + memory->destroy(buf); +} diff --git a/src/write_data.h b/src/write_data.h index ec4b373090..d9a5150897 100644 --- a/src/write_data.h +++ b/src/write_data.h @@ -47,6 +47,7 @@ class WriteData : protected Pointers { void angles(); void dihedrals(); void impropers(); + void fix(int, int); }; }