From c7e794146f9cd04d3e5b2a57bb7e5dc096547a08 Mon Sep 17 00:00:00 2001 From: Steve Plimpton Date: Wed, 13 Sep 2023 10:03:05 -0600 Subject: [PATCH] initial support for write_data --- src/DIELECTRIC/atom_vec_dielectric.cpp | 4 +- src/DIELECTRIC/atom_vec_dielectric.h | 2 +- src/MACHDYN/atom_vec_smd.cpp | 2 +- src/atom.cpp | 2 + src/atom_vec.cpp | 102 ++++++++++++++++++++++++- src/atom_vec.h | 9 ++- src/read_data.cpp | 2 +- src/write_data.cpp | 33 +++----- 8 files changed, 124 insertions(+), 32 deletions(-) diff --git a/src/DIELECTRIC/atom_vec_dielectric.cpp b/src/DIELECTRIC/atom_vec_dielectric.cpp index a06b4d599b..735d770b04 100644 --- a/src/DIELECTRIC/atom_vec_dielectric.cpp +++ b/src/DIELECTRIC/atom_vec_dielectric.cpp @@ -194,9 +194,9 @@ void AtomVecDielectric::data_atom_post(int ilocal) child class operates on dipole moment mu ------------------------------------------------------------------------- */ -void AtomVecDielectric::data_general_to_restricted(int nlocal_previous, int nlocal) +void AtomVecDielectric::read_data_general_to_restricted(int nlocal_previous, int nlocal) { - AtomVec::data_general_to_restricted(nlocal_previous, nlocal); + AtomVec::read_data_general_to_restricted(nlocal_previous, nlocal); for (int i = nlocal_previous; i < nlocal; i++) domain->general_to_restricted_vector(mu[i]); diff --git a/src/DIELECTRIC/atom_vec_dielectric.h b/src/DIELECTRIC/atom_vec_dielectric.h index fefbc99c4f..8bef111cb4 100644 --- a/src/DIELECTRIC/atom_vec_dielectric.h +++ b/src/DIELECTRIC/atom_vec_dielectric.h @@ -35,7 +35,7 @@ class AtomVecDielectric : virtual public AtomVec { void grow_pointers() override; void create_atom_post(int) override; void data_atom_post(int) override; - void data_general_to_restricted(int, int); + void read_data_general_to_restricted(int, int); void unpack_restart_init(int) override; int property_atom(const std::string &) override; void pack_property_atom(int, double *, int, int) override; diff --git a/src/MACHDYN/atom_vec_smd.cpp b/src/MACHDYN/atom_vec_smd.cpp index 0f5e7f82f0..27f23c5362 100644 --- a/src/MACHDYN/atom_vec_smd.cpp +++ b/src/MACHDYN/atom_vec_smd.cpp @@ -160,7 +160,7 @@ void AtomVecSMD::data_atom_post(int ilocal) // x and x0 are in Atoms section of data file // reset x0 b/c x may have been modified in Atom::data_atoms() // for PBC, shift, etc - // this also means no need for data_general_to_restricted() method + // this also means no need for read_data_general_to_restricted() method // to rotate x0 for general triclinic x0[ilocal][0] = x[ilocal][0]; diff --git a/src/atom.cpp b/src/atom.cpp index 4674ded045..7f472e44f4 100644 --- a/src/atom.cpp +++ b/src/atom.cpp @@ -1191,6 +1191,7 @@ void Atom::data_atoms(int n, char *buf, tagint id_offset, tagint mol_offset, } // convert atom coords from general triclinic to restricted triclinic + // so can decide which proc owns the atom if (triclinic_general) domain->general_to_restricted_coords(xdata); @@ -1216,6 +1217,7 @@ void Atom::data_atoms(int n, char *buf, tagint id_offset, tagint mol_offset, if (coord[0] >= sublo[0] && coord[0] < subhi[0] && coord[1] >= sublo[1] && coord[1] < subhi[1] && coord[2] >= sublo[2] && coord[2] < subhi[2]) { + avec->data_atom(xdata,imagedata,values,typestr); typestr = utils::utf8_subst(typestr); if (id_offset) tag[nlocal-1] += id_offset; diff --git a/src/atom_vec.cpp b/src/atom_vec.cpp index d8684aaf94..f7a0f6f566 100644 --- a/src/atom_vec.cpp +++ b/src/atom_vec.cpp @@ -68,6 +68,9 @@ AtomVec::AtomVec(LAMMPS *lmp) : Pointers(lmp) image = nullptr; x = v = f = nullptr; + x_hold = nullptr; + v_hold = omega_hold = angmom_hold = nullptr; + threads = nullptr; } @@ -2223,12 +2226,12 @@ void AtomVec::write_improper(FILE *fp, int n, tagint **buf, int index) } /* ---------------------------------------------------------------------- - convert read_data file info from general to restricted triclinic + convert info input by read_data from general to restricted triclinic parent class only operates on data from Velocities section of data file child classes operate on all other data: Atoms, Ellipsoids, Lines, Triangles, etc ------------------------------------------------------------------------- */ -void AtomVec::data_general_to_restricted(int nlocal_previous, int nlocal) +void AtomVec::read_data_general_to_restricted(int nlocal_previous, int nlocal) { int datatype, cols; void *pdata; @@ -2239,7 +2242,7 @@ void AtomVec::data_general_to_restricted(int nlocal_previous, int nlocal) cols = mdata_vel.cols[n]; // operate on v, omega, angmom - // no other read_data atom fields are Nx3 double arrays + // no other read_data Velocities fields are Nx3 double arrays if (datatype == Atom::DOUBLE) { if (cols == 3) { @@ -2251,6 +2254,99 @@ void AtomVec::data_general_to_restricted(int nlocal_previous, int nlocal) } } +/* ---------------------------------------------------------------------- + convert info output by write_data from restricted to general triclinic + parent class only operates on x and data from Velocities section of data file + child classes operate on all other data: Atoms, Ellipsoids, Lines, Triangles, etc +------------------------------------------------------------------------- */ + +void AtomVec::write_data_restricted_to_general() +{ + int datatype, cols; + void *pdata; + + int nlocal = atom->nlocal; + + memory->create(x_hold,nlocal,3,"atomvec:x_hold"); + if (nlocal) memcpy(&x_hold[0][0],&x[0][0],3*nlocal*sizeof(double)); + for (int i = 0; i < nlocal; i++) + domain->restricted_to_general_coords(x[i]); + + double **omega = atom->omega; + double **angmom = atom->angmom; + + for (int n = 1; n < ndata_vel; n++) { + pdata = mdata_vel.pdata[n]; + datatype = mdata_vel.datatype[n]; + cols = mdata_vel.cols[n]; + + // operate on v, omega, angmom + // no other write_data Velocities fields are Nx3 double arrays + + if (datatype == Atom::DOUBLE) { + if (cols == 3) { + double **array = *((double ***) pdata); + + if (array == v) { + memory->create(v_hold,nlocal,3,"atomvec:v_hold"); + if (nlocal) memcpy(&v_hold[0][0],&v[0][0],3*nlocal*sizeof(double)); + for (int i = 0; i < nlocal; i++) + domain->restricted_to_general_vector(v[i]); + } else if (array == omega) { + memory->create(omega_hold,nlocal,3,"atomvec:omega_hold"); + if (nlocal) memcpy(&omega_hold[0][0],&omega[0][0],3*nlocal*sizeof(double)); + for (int i = 0; i < nlocal; i++) + domain->restricted_to_general_vector(omega[i]); + } else if (array == angmom) { + memory->create(angmom_hold,nlocal,3,"atomvec:angmom_hold"); + if (nlocal) memcpy(&angmom_hold[0][0],&angmom[0][0],3*nlocal*sizeof(double)); + for (int i = 0; i < nlocal; i++) + domain->restricted_to_general_vector(angmom[i]); + } + } + } + } +} + +/* ---------------------------------------------------------------------- + restore info output by write_data to restricted triclinic + original data is in "hold" arrays + parent class only operates on x and data from Velocities section of data file + child classes operate on all other data: Atoms, Ellipsoids, Lines, Triangles, etc +------------------------------------------------------------------------- */ + +void AtomVec::write_data_restore_restricted() +{ + int nlocal = atom->nlocal; + + if (x_hold) { + memcpy(&x[0][0],&x_hold[0][0],3*nlocal*sizeof(double)); + memory->destroy(x_hold); + x_hold = nullptr; + } + + // operate on v, omega, angmom + // no other write_data Velocities fields are Nx3 double arrays + + if (v_hold) { + memcpy(&v[0][0],&v_hold[0][0],3*nlocal*sizeof(double)); + memory->destroy(v_hold); + v_hold = nullptr; + } + + if (omega_hold) { + memcpy(&atom->omega[0][0],&omega_hold[0][0],3*nlocal*sizeof(double)); + memory->destroy(omega_hold); + omega_hold = nullptr; + } + + if (angmom_hold) { + memcpy(&atom->angmom[0][0],&angmom_hold[0][0],3*nlocal*sizeof(double)); + memory->destroy(angmom_hold); + angmom_hold = nullptr; + } +} + /* ---------------------------------------------------------------------- return # of bytes of allocated memory ------------------------------------------------------------------------- */ diff --git a/src/atom_vec.h b/src/atom_vec.h index b0c77635f8..55fe7e2f7d 100644 --- a/src/atom_vec.h +++ b/src/atom_vec.h @@ -152,7 +152,9 @@ class AtomVec : protected Pointers { virtual int pack_data_bonus(double *, int) { return 0; } virtual void write_data_bonus(FILE *, int, double *, int) {} - virtual void data_general_to_restricted(int, int); + virtual void read_data_general_to_restricted(int, int); + virtual void write_data_restricted_to_general(); + virtual void write_data_restore_restricted(); virtual int property_atom(const std::string &) { return -1; } virtual void pack_property_atom(int, double *, int, int) {} @@ -171,6 +173,11 @@ class AtomVec : protected Pointers { imageint *image; double **x, **v, **f; + // copies of original unrotated fields for write_data for general triclinic + + double **x_hold; + double **v_hold, **omega_hold, **angmom_hold; + // standard list of peratom fields always operated on by different methods // common to all styles, so not listed in field strings diff --git a/src/read_data.cpp b/src/read_data.cpp index 219a361584..ab3876a25e 100644 --- a/src/read_data.cpp +++ b/src/read_data.cpp @@ -1066,7 +1066,7 @@ void ReadData::command(int narg, char **arg) // on any quantities read from data file which require it if (triclinic_general) - atom->avec->data_general_to_restricted(nlocal_previous, atom->nlocal); + atom->avec->read_data_general_to_restricted(nlocal_previous, atom->nlocal); // init per-atom fix/compute/variable values for created atoms diff --git a/src/write_data.cpp b/src/write_data.cpp index 960a4ff1cf..49e041b6ce 100644 --- a/src/write_data.cpp +++ b/src/write_data.cpp @@ -97,7 +97,7 @@ void WriteData::command(int narg, char **arg) } else if (strcmp(arg[iarg],"nofix") == 0) { fixflag = 0; iarg++; - } else if (strcmp(arg[iarg],"triclinic") == 0) { + } else if (strcmp(arg[iarg],"triclinic/general") == 0) { triclinic_general = 1; iarg++; } else if (strcmp(arg[iarg],"nolabelmap") == 0) { @@ -213,32 +213,14 @@ void WriteData::write(const std::string &file) if (coeffflag) force_fields(); } - // per atom info in Atoms and Velocities sections // if general triclinic: - // save restricted triclinic atom coords - // transform atom coords from restricted to general - // restore saved atom coords after output + // reset internal per-atom data that needs rotation + + atom->avec->write_data_restricted_to_general(); - double **xstore = nullptr; - - if (triclinic_general) { - double **x = atom->x; - int nlocal = atom->nlocal; - memory->create(xstore,nlocal,3,"write_data:xstore"); - if (nlocal) memcpy(&xstore[0][0],&x[0][0],3*nlocal*sizeof(double)); - for (int i = 0; i < nlocal; i++) - domain->restricted_to_general_coords(x[i]); - } + // per atom info in Atoms and Velocities sections if (natoms) atoms(); - - if (triclinic_general) { - double **x = atom->x; - int nlocal = atom->nlocal; - if (nlocal) memcpy(&x[0][0],&xstore[0][0],3*nlocal*sizeof(double)); - memory->destroy(xstore); - } - if (natoms) velocities(); // molecular topology info if defined @@ -265,6 +247,11 @@ void WriteData::write(const std::string &file) if (ifix->wd_section) for (int m = 0; m < ifix->wd_section; m++) fix(ifix,m); + // if general triclinic: + // restore internal per-atom data that was rotated + + atom->avec->write_data_restore_restricted(); + // close data file if (me == 0) fclose(fp);