Files
lammps/src/fix_property_atom.cpp
Axel Kohlmeyer adf1beea74 add mechanism to check for known data file section names
using this mechanism we can reject custom section names that will
conflict with existing section names and thus avoid misleading errors.
apply this also to fix property atom, where the section name is
determined by the fix ID.
in addition, allow to specify NULL as section name, which will use
the fix ID.
2021-10-28 14:23:27 -04:00

842 lines
27 KiB
C++

// clang-format off
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/, 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 "fix_property_atom.h"
#include "atom.h"
#include "comm.h"
#include "error.h"
#include "memory.h"
#include "read_data.h"
#include "tokenizer.h"
#include <cstring>
using namespace LAMMPS_NS;
using namespace FixConst;
enum{MOLECULE,CHARGE,RMASS,IVEC,DVEC,IARRAY,DARRAY};
/* ---------------------------------------------------------------------- */
FixPropertyAtom::FixPropertyAtom(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg),
nvalue(0), styles(nullptr), index(nullptr), astyle(nullptr)
{
if (narg < 4) error->all(FLERR,"Illegal fix property/atom command");
restart_peratom = 1;
wd_section = 1;
int iarg = 3;
nvalue = narg-iarg;
styles = new int[nvalue];
cols = new int[nvalue];
index = new int[nvalue];
molecule_flag = 0;
q_flag = 0;
rmass_flag = 0;
nvalue = 0;
values_peratom = 0;
while (iarg < narg) {
if (strcmp(arg[iarg],"mol") == 0) {
if (atom->molecule_flag)
error->all(FLERR,"Fix property/atom mol when atom_style already has molecule attribute");
if (molecule_flag)
error->all(FLERR,"Fix property/atom cannot specify mol twice");
styles[nvalue] = MOLECULE;
cols[nvalue] = 0;
atom->molecule_flag = molecule_flag = 1;
values_peratom++;
nvalue++;
iarg++;
} else if (strcmp(arg[iarg],"q") == 0) {
if (atom->q_flag)
error->all(FLERR,"Fix property/atom q when atom_style already has charge attribute");
if (q_flag)
error->all(FLERR,"Fix property/atom cannot specify q twice");
styles[nvalue] = CHARGE;
cols[nvalue] = 0;
atom->q_flag = q_flag = 1;
values_peratom++;
nvalue++;
iarg++;
} else if (strcmp(arg[iarg],"rmass") == 0) {
if (atom->rmass_flag)
error->all(FLERR,"Fix property/atom rmass when atom_style already has rmass attribute");
if (rmass_flag)
error->all(FLERR,"Fix property/atom cannot specify rmass twice");
styles[nvalue] = RMASS;
cols[nvalue] = 0;
atom->rmass_flag = rmass_flag = 1;
values_peratom++;
nvalue++;
iarg++;
// custom atom vector
} else if (utils::strmatch(arg[iarg],"^i_")) {
styles[nvalue] = IVEC;
int flag,ncols;
index[nvalue] = atom->find_custom(&arg[iarg][2],flag,ncols);
if (index[nvalue] >= 0)
error->all(FLERR,"Fix property/atom vector name already exists");
if (ReadData::is_data_section(id))
error->all(FLERR,"Fix property/atom fix ID must not be a data file section name");
index[nvalue] = atom->add_custom(&arg[iarg][2],0,0);
cols[nvalue] = 0;
values_peratom++;
nvalue++;
iarg++;
} else if (utils::strmatch(arg[iarg],"^d_")) {
styles[nvalue] = DVEC;
int flag,ncols;
index[nvalue] = atom->find_custom(&arg[iarg][2],flag,ncols);
if (index[nvalue] >= 0)
error->all(FLERR,"Fix property/atom vector name already exists");
if (ReadData::is_data_section(id))
error->all(FLERR,"Fix property/atom fix ID must not be a data file section name");
index[nvalue] = atom->add_custom(&arg[iarg][2],1,0);
cols[nvalue] = 0;
values_peratom++;
nvalue++;
iarg++;
// custom atom array
} else if (utils::strmatch(arg[iarg],"^[id]2_")) {
if (iarg+2 > narg) error->all(FLERR,"Illegal fix property/atom command");
int which,flag,ncols;
which = atom->find_custom(&arg[iarg][3],flag,ncols);
if (which >= 0)
error->all(FLERR,"Fix property/atom array name {} already exists", &arg[iarg][3]);
if (ReadData::is_data_section(id))
error->all(FLERR,"Fix property/atom fix ID must not be a data file section name");
ncols = utils::inumeric(FLERR,arg[iarg+1],true,lmp);
if (ncols < 1)
error->all(FLERR,"Invalid array columns number {} in fix property/atom", ncols);
if (arg[iarg][0] == 'i') {
which = 0;
styles[nvalue] = IARRAY;
} else {
which = 1;
styles[nvalue] = DARRAY;
}
index[nvalue] = atom->add_custom(&arg[iarg][3],which,ncols);
cols[nvalue] = ncols;
values_peratom += ncols;
nvalue++;
iarg += 2;
// no match
} else break;
}
// optional args
border = 0;
while (iarg < narg) {
if (strcmp(arg[iarg],"ghost") == 0) {
if (iarg+2 > narg) error->all(FLERR,"Illegal fix property/atom command");
border = utils::logical(FLERR,arg[iarg+1],false,lmp);
iarg += 2;
} else error->all(FLERR,"Illegal fix property/atom command");
}
if (border) comm_border = values_peratom;
// warn if mol or charge keyword used without ghost yes
if (border == 0) {
int flag = 0;
for (int i = 0; i < nvalue; i++)
if (styles[i] == MOLECULE
|| styles[i] == CHARGE
|| styles[i] == RMASS) flag = 1;
if (flag && comm->me == 0)
error->warning(FLERR,"Fix property/atom mol or charge or rmass "
"w/out ghost communication");
}
// store current atom style
astyle = utils::strdup(atom->atom_style);
// perform initial allocation of atom-based array
// register with Atom class
nmax_old = 0;
if (!lmp->kokkos) FixPropertyAtom::grow_arrays(atom->nmax);
atom->add_callback(Atom::GROW);
atom->add_callback(Atom::RESTART);
if (border) atom->add_callback(Atom::BORDER);
}
/* ---------------------------------------------------------------------- */
FixPropertyAtom::~FixPropertyAtom()
{
// unregister callbacks to this fix from Atom class
atom->delete_callback(id,Atom::GROW);
atom->delete_callback(id,Atom::RESTART);
if (border) atom->delete_callback(id,Atom::BORDER);
// deallocate per-atom vectors in Atom class
// set ptrs to a null pointer, so they no longer exist for Atom class
for (int nv = 0; nv < nvalue; nv++) {
if (styles[nv] == MOLECULE) {
atom->molecule_flag = 0;
memory->destroy(atom->molecule);
atom->molecule = nullptr;
} else if (styles[nv] == CHARGE) {
atom->q_flag = 0;
memory->destroy(atom->q);
atom->q = nullptr;
} else if (styles[nv] == RMASS) {
atom->rmass_flag = 0;
memory->destroy(atom->rmass);
atom->rmass = nullptr;
} else if (styles[nv] == IVEC) {
atom->remove_custom(index[nv],0,cols[nv]);
} else if (styles[nv] == DVEC) {
atom->remove_custom(index[nv],1,cols[nv]);
} else if (styles[nv] == IARRAY) {
atom->remove_custom(index[nv],0,cols[nv]);
} else if (styles[nv] == DARRAY) {
atom->remove_custom(index[nv],1,cols[nv]);
}
}
delete [] styles;
delete [] cols;
delete [] index;
delete [] astyle;
}
/* ---------------------------------------------------------------------- */
int FixPropertyAtom::setmask()
{
int mask = 0;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixPropertyAtom::init()
{
// error if atom style has changed since fix was defined
// don't allow this because user could change to style that defines molecule,q
if (strcmp(astyle,atom->atom_style) != 0)
error->all(FLERR,"Atom style was redefined after using fix property/atom");
}
/* ----------------------------------------------------------------------
unpack N lines in buf from section of data file labeled by keyword
id_offset is applied to first atomID field if multiple data files are read
------------------------------------------------------------------------- */
void FixPropertyAtom::read_data_section(char *keyword, int n, char *buf, tagint id_offset)
{
int j,k,m,ncol;
tagint itag;
char *next;
int mapflag = 0;
if (atom->map_style == Atom::MAP_NONE) {
mapflag = 1;
atom->map_init();
atom->map_set();
}
// loop over lines of atom info
// tokenize the line into values
// if I own atom tag, assign its values
tagint map_tag_max = atom->map_tag_max;
for (int i = 0; i < n; i++) {
next = strchr(buf,'\n');
*next = '\0';
try {
ValueTokenizer values(buf);
if ((int)values.count() != values_peratom+1)
error->all(FLERR,"Incorrect format in {} section of data file: {}"
" expected {} and got {}",keyword,buf,values_peratom+1,values.count());
itag = values.next_tagint() + id_offset;
if (itag <= 0 || itag > map_tag_max)
error->all(FLERR,"Invalid atom ID {} in {} section of data file",itag, keyword);
// assign words in line to per-atom vectors
if ((m = atom->map(itag)) >= 0) {
for (j = 0; j < nvalue; j++) {
if (styles[j] == MOLECULE) {
atom->molecule[m] = values.next_tagint();
} else if (styles[j] == CHARGE) {
atom->q[m] = values.next_double();
} else if (styles[j] == RMASS) {
atom->rmass[m] = values.next_double();
} else if (styles[j] == IVEC) {
atom->ivector[index[j]][m] = values.next_int();
} else if (styles[j] == DVEC) {
atom->dvector[index[j]][m] = values.next_double();
} else if (styles[j] == IARRAY) {
ncol = cols[j];
for (k = 0; k < ncol; k++)
atom->iarray[index[j]][m][k] = values.next_int();
} else if (styles[j] == DARRAY) {
ncol = cols[j];
for (k = 0; k < ncol; k++)
atom->darray[index[j]][m][k] = values.next_double();
}
}
}
} catch (TokenizerException &e) {
error->all(FLERR,"Invalid format in {} section of data file '{}': {}",keyword, buf,e.what());
}
buf = next + 1;
}
if (mapflag) {
atom->map_delete();
atom->map_style = 0;
}
}
/* ----------------------------------------------------------------------
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 + values_peratom
------------------------------------------------------------------------- */
void FixPropertyAtom::write_data_section_size(int /*mth*/, int &nx, int &ny)
{
nx = atom->nlocal;
ny = values_peratom + 1;
}
/* ----------------------------------------------------------------------
pack values for Mth data section into 2d buf
buf allocated by caller as Nlocal by Nvalues+1
------------------------------------------------------------------------- */
void FixPropertyAtom::write_data_section_pack(int /*mth*/, double **buf)
{
int i,k,ncol;
// 1st column = atom tag
// rest of columns = per-atom values
tagint *tag = atom->tag;
int nlocal = atom->nlocal;
for (i = 0; i < nlocal; i++) buf[i][0] = ubuf(tag[i]).d;
int icol = 1;
for (int nv = 0; nv < nvalue; nv++) {
if (styles[nv] == MOLECULE) {
tagint *molecule = atom->molecule;
for (i = 0; i < nlocal; i++) buf[i][icol] = ubuf(molecule[i]).d;
icol++;
} else if (styles[nv] == CHARGE) {
double *q = atom->q;
for (i = 0; i < nlocal; i++) buf[i][icol] = q[i];
icol++;
} else if (styles[nv] == RMASS) {
double *rmass = atom->rmass;
for (i = 0; i < nlocal; i++) buf[i][icol] = rmass[i];
icol++;
} else if (styles[nv] == IVEC) {
int *ivec = atom->ivector[index[nv]];
for (i = 0; i < nlocal; i++) buf[i][icol] = ubuf(ivec[i]).d;
icol++;
} else if (styles[nv] == DVEC) {
double *dvec = atom->dvector[index[nv]];
for (i = 0; i < nlocal; i++) buf[i][icol] = dvec[i];
icol++;
} else if (styles[nv] == IARRAY) {
int **iarray = atom->iarray[index[nv]];
ncol = cols[nv];
for (i = 0; i < nlocal; i++)
for (k = 0; k < ncol; k++)
buf[i][icol+k] = ubuf(iarray[i][k]).d;
icol += ncol;
} else if (styles[nv] == DARRAY) {
double **darray = atom->darray[index[nv]];
ncol = cols[nv];
for (i = 0; i < nlocal; i++)
for (k = 0; k < ncol; k++)
buf[i][icol+k] = darray[i][k];
icol += ncol;
}
}
}
/* ----------------------------------------------------------------------
write a Molecules or Charges section if that is only field
manages by this fix instance. Otherwise write everything
to the section labeled by the fix ID
only called by proc 0
------------------------------------------------------------------------- */
void FixPropertyAtom::write_data_section_keyword(int /*mth*/, FILE *fp)
{
if (nvalue == 1 && styles[0] == MOLECULE) fprintf(fp,"\nMolecules\n\n");
else if (nvalue == 1 && styles[0] == CHARGE) fprintf(fp,"\nCharges\n\n");
else {
fprintf(fp,"\n%s #",id);
// write column hint as comment
for (int i = 0; i < nvalue; ++i) {
if (styles[i] == MOLECULE) fputs(" mol",fp);
else if (styles[i] == CHARGE) fputs(" q",fp);
else if (styles[i] == RMASS) fputs(" rmass",fp);
else if (styles[i] == IVEC) fprintf(fp," i_%s", atom->ivname[index[i]]);
else if (styles[i] == DVEC) fprintf(fp, " d_%s", atom->dvname[index[i]]);
else if (styles[i] == IARRAY) fprintf(fp, " i_%s", atom->ianame[index[i]]);
else if (styles[i] == DARRAY) fprintf(fp, " d_%s", atom->daname[index[i]]);
}
fputs("\n\n",fp);
}
}
/* ----------------------------------------------------------------------
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 k,icol,ncol,nv;
for (int i = 0; i < n; i++) {
fprintf(fp,TAGINT_FORMAT,(tagint) ubuf(buf[i][0]).i);
icol = 1;
for (nv = 0; nv < nvalue; nv++) {
if (styles[nv] == MOLECULE)
fprintf(fp," " TAGINT_FORMAT,(tagint) ubuf(buf[i][icol++]).i);
else if (styles[nv] == CHARGE)
fprintf(fp," %g",buf[i][icol++]);
else if (styles[nv] == RMASS)
fprintf(fp," %g",buf[i][icol++]);
else if (styles[nv] == IVEC)
fprintf(fp," %d",(int) ubuf(buf[i][icol++]).i);
else if (styles[nv] == DVEC)
fprintf(fp," %g",buf[i][icol++]);
else if (styles[nv] == IARRAY) {
ncol = cols[nv];
for (k = 0; k < ncol; k++)
fprintf(fp," %d",(int) ubuf(buf[i][icol+k]).i);
icol += ncol;
} else if (styles[nv] == DARRAY) {
ncol = cols[nv];
for (k = 0; k < ncol; k++)
fprintf(fp," %g",buf[i][icol+k]);
icol += ncol;
}
}
fprintf(fp,"\n");
}
}
/* ----------------------------------------------------------------------
memory usage of local atom-based array
------------------------------------------------------------------------- */
double FixPropertyAtom::memory_usage()
{
double bytes = 0.0;
for (int m = 0; m < nvalue; m++) {
if (styles[m] == MOLECULE) bytes = atom->nmax * sizeof(tagint);
else if (styles[m] == CHARGE) bytes = atom->nmax * sizeof(double);
else if (styles[m] == RMASS) bytes = atom->nmax * sizeof(double);
else if (styles[m] == IVEC) bytes = atom->nmax * sizeof(int);
else if (styles[m] == DVEC) bytes = atom->nmax * sizeof(double);
else if (styles[m] == IARRAY) bytes = (size_t) atom->nmax * cols[m] * sizeof(int);
else if (styles[m] == DARRAY) bytes = (size_t) atom->nmax * cols[m] * sizeof(double);
}
return bytes;
}
/* ----------------------------------------------------------------------
allocate atom-based arrays
also initialize new values to 0
since AtomVec class won't do it as atoms are added,
e.g. in create_atom() or data_atom()
------------------------------------------------------------------------- */
void FixPropertyAtom::grow_arrays(int nmax)
{
for (int nv = 0; nv < nvalue; nv++) {
if (styles[nv] == MOLECULE) {
memory->grow(atom->molecule,nmax,"atom:molecule");
size_t nbytes = (nmax-nmax_old) * sizeof(tagint);
memset(&atom->molecule[nmax_old],0,nbytes);
} else if (styles[nv] == CHARGE) {
memory->grow(atom->q,nmax,"atom:q");
size_t nbytes = (nmax-nmax_old) * sizeof(double);
memset(&atom->q[nmax_old],0,nbytes);
} else if (styles[nv] == RMASS) {
memory->grow(atom->rmass,nmax,"atom:rmass");
size_t nbytes = (nmax-nmax_old) * sizeof(double);
memset(&atom->rmass[nmax_old],0,nbytes);
} else if (styles[nv] == IVEC) {
memory->grow(atom->ivector[index[nv]],nmax,"atom:ivector");
size_t nbytes = (nmax-nmax_old) * sizeof(int);
memset(&atom->ivector[index[nv]][nmax_old],0,nbytes);
} else if (styles[nv] == DVEC) {
memory->grow(atom->dvector[index[nv]],nmax,"atom:dvector");
size_t nbytes = (nmax-nmax_old) * sizeof(double);
memset(&atom->dvector[index[nv]][nmax_old],0,nbytes);
} else if (styles[nv] == IARRAY) {
memory->grow(atom->iarray[index[nv]],nmax,cols[nv],"atom:iarray");
size_t nbytes = (size_t) (nmax-nmax_old) * cols[nv] * sizeof(int);
if (nbytes) memset(&atom->iarray[index[nv]][nmax_old][0],0,nbytes);
} else if (styles[nv] == DARRAY) {
memory->grow(atom->darray[index[nv]],nmax,cols[nv],"atom:darray");
size_t nbytes = (size_t) (nmax-nmax_old) * cols[nv] * sizeof(double);
if (nbytes) memset(&atom->darray[index[nv]][nmax_old][0],0,nbytes);
}
}
nmax_old = nmax;
}
/* ----------------------------------------------------------------------
copy values within local atom-based arrays
------------------------------------------------------------------------- */
void FixPropertyAtom::copy_arrays(int i, int j, int /*delflag*/)
{
int k,ncol;
for (int nv = 0; nv < nvalue; nv++) {
if (styles[nv] == MOLECULE)
atom->molecule[j] = atom->molecule[i];
else if (styles[nv] == CHARGE)
atom->q[j] = atom->q[i];
else if (styles[nv] == RMASS)
atom->rmass[j] = atom->rmass[i];
else if (styles[nv] == IVEC)
atom->ivector[index[nv]][j] = atom->ivector[index[nv]][i];
else if (styles[nv] == DVEC)
atom->dvector[index[nv]][j] = atom->dvector[index[nv]][i];
else if (styles[nv] == IARRAY) {
ncol = cols[nv];
for (k = 0; k < ncol; k++)
atom->iarray[index[nv]][j][k] = atom->iarray[index[nv]][i][k];
} else if (styles[nv] == DARRAY) {
ncol = cols[nv];
for (k = 0; k < ncol; k++)
atom->darray[index[nv]][j][k] = atom->darray[index[nv]][i][k];
}
}
}
/* ----------------------------------------------------------------------
pack values for border communication at re-neighboring
------------------------------------------------------------------------- */
int FixPropertyAtom::pack_border(int n, int *list, double *buf)
{
int i,j,k,ncol;
int m = 0;
for (int nv = 0; nv < nvalue; nv++) {
if (styles[nv] == MOLECULE) {
tagint *molecule = atom->molecule;
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = ubuf(molecule[j]).d;
}
} else if (styles[nv] == CHARGE) {
double *q = atom->q;
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = q[j];
}
} else if (styles[nv] == RMASS) {
double *rmass = atom->rmass;
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = rmass[j];
}
} else if (styles[nv] == IVEC) {
int *ivector = atom->ivector[index[nv]];
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = ubuf(ivector[j]).d;
}
} else if (styles[nv] == DVEC) {
double *dvector = atom->dvector[index[nv]];
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = dvector[j];
}
} else if (styles[nv] == IARRAY) {
int **iarray = atom->iarray[index[nv]];
ncol = cols[nv];
for (i = 0; i < n; i++) {
j = list[i];
for (k = 0; k < ncol; k++)
buf[m++] = ubuf(iarray[j][k]).d;
}
} else if (styles[nv] == DARRAY) {
double **darray = atom->darray[index[nv]];
ncol = cols[nv];
for (i = 0; i < n; i++) {
j = list[i];
for (k = 0; k < ncol; k++)
buf[m++] = darray[j][k];
}
}
}
return m;
}
/* ----------------------------------------------------------------------
unpack values for border communication at re-neighboring
------------------------------------------------------------------------- */
int FixPropertyAtom::unpack_border(int n, int first, double *buf)
{
int i,k,last,ncol;
int m = 0;
for (int nv = 0; nv < nvalue; nv++) {
if (styles[nv] == MOLECULE) {
tagint *molecule = atom->molecule;
last = first + n;
for (i = first; i < last; i++)
molecule[i] = (tagint) ubuf(buf[m++]).i;
} else if (styles[nv] == CHARGE) {
double *q = atom->q;
last = first + n;
for (i = first; i < last; i++)
q[i] = buf[m++];
} else if (styles[nv] == RMASS) {
double *rmass = atom->rmass;
last = first + n;
for (i = first; i < last; i++)
rmass[i] = buf[m++];
} else if (styles[nv] == IVEC) {
int *ivector = atom->ivector[index[nv]];
last = first + n;
for (i = first; i < last; i++)
ivector[i] = (int) ubuf(buf[m++]).i;
} else if (styles[nv] == DVEC) {
double *dvector = atom->dvector[index[nv]];
last = first + n;
for (i = first; i < last; i++)
dvector[i] = buf[m++];
} else if (styles[nv] == IARRAY) {
int **iarray = atom->iarray[index[nv]];
ncol = cols[nv];
last = first + n;
for (i = first; i < last; i++)
for (k = 0; k < ncol; k++)
iarray[i][k] = (int) ubuf(buf[m++]).i;
} else if (styles[nv] == DARRAY) {
double **darray = atom->darray[index[nv]];
ncol = cols[nv];
last = first + n;
for (i = first; i < last; i++)
for (k = 0; k < ncol; k++)
darray[i][k] = buf[m++];
}
}
return m;
}
/* ----------------------------------------------------------------------
pack values in local atom-based array for exchange with another proc
------------------------------------------------------------------------- */
int FixPropertyAtom::pack_exchange(int i, double *buf)
{
int k,ncol;
int m = 0;
for (int nv = 0; nv < nvalue; nv++) {
if (styles[nv] == MOLECULE) buf[m++] = ubuf(atom->molecule[i]).d;
else if (styles[nv] == CHARGE) buf[m++] = atom->q[i];
else if (styles[nv] == RMASS) buf[m++] = atom->rmass[i];
else if (styles[nv] == IVEC) buf[m++] = ubuf(atom->ivector[index[nv]][i]).d;
else if (styles[nv] == DVEC) buf[m++] = atom->dvector[index[nv]][i];
else if (styles[nv] == IARRAY) {
ncol = cols[nv];
for (k = 0; k < ncol; k++)
buf[m++] = ubuf(atom->iarray[index[nv]][i][k]).d;
} else if (styles[nv] == DARRAY) {
ncol = cols[nv];
for (k = 0; k < ncol; k++)
buf[m++] = atom->darray[index[nv]][i][k];
}
}
return m;
}
/* ----------------------------------------------------------------------
unpack values in local atom-based array from exchange with another proc
------------------------------------------------------------------------- */
int FixPropertyAtom::unpack_exchange(int nlocal, double *buf)
{
int k,ncol;
int m = 0;
for (int nv = 0; nv < nvalue; nv++) {
if (styles[nv] == MOLECULE)
atom->molecule[nlocal] = (tagint) ubuf(buf[m++]).i;
else if (styles[nv] == CHARGE)
atom->q[nlocal] = buf[m++];
else if (styles[nv] == RMASS)
atom->rmass[nlocal] = buf[m++];
else if (styles[nv] == IVEC)
atom->ivector[index[nv]][nlocal] = (int) ubuf(buf[m++]).i;
else if (styles[nv] == DVEC)
atom->dvector[index[nv]][nlocal] = buf[m++];
else if (styles[nv] == IARRAY) {
ncol = cols[nv];
for (k = 0; k < ncol; k++)
atom->iarray[index[nv]][nlocal][k] = (int) ubuf(buf[m++]).i;
} else if (styles[nv] == DARRAY) {
ncol = cols[nv];
for (k = 0; k < ncol; k++)
atom->darray[index[nv]][nlocal][k] = buf[m++];
}
}
return m;
}
/* ----------------------------------------------------------------------
pack values in local atom-based arrays for restart file
------------------------------------------------------------------------- */
int FixPropertyAtom::pack_restart(int i, double *buf)
{
int k,ncol;
// pack buf[0] this way because other fixes unpack it
buf[0] = values_peratom+1;
int m = 1;
for (int nv = 0; nv < nvalue; nv++) {
if (styles[nv] == MOLECULE) buf[m++] = ubuf(atom->molecule[i]).d;
else if (styles[nv] == CHARGE) buf[m++] = atom->q[i];
else if (styles[nv] == RMASS) buf[m++] = atom->rmass[i];
else if (styles[nv] == IVEC) buf[m++] = ubuf(atom->ivector[index[nv]][i]).d;
else if (styles[nv] == DVEC) buf[m++] = atom->dvector[index[nv]][i];
else if (styles[nv] == IARRAY) {
ncol = cols[nv];
for (k = 0; k < ncol; k++)
buf[m++] = ubuf(atom->iarray[index[nv]][i][k]).d;
} else if (styles[nv] == DARRAY) {
ncol = cols[nv];
for (k = 0; k < ncol; k++)
buf[m++] = atom->darray[index[nv]][i][k];
}
}
return values_peratom+1;
}
/* ----------------------------------------------------------------------
unpack values from atom->extra array to restart the fix
------------------------------------------------------------------------- */
void FixPropertyAtom::unpack_restart(int nlocal, int nth)
{
int k,ncol;
double **extra = atom->extra;
// skip to Nth set of extra values
// unpack the Nth first values this way because other fixes pack them
int m = 0;
for (int i = 0; i < nth; i++) m += static_cast<int> (extra[nlocal][m]);
m++;
for (int nv = 0; nv < nvalue; nv++) {
if (styles[nv] == MOLECULE)
atom->molecule[nlocal] = (tagint) ubuf(extra[nlocal][m++]).i;
else if (styles[nv] == CHARGE)
atom->q[nlocal] = extra[nlocal][m++];
else if (styles[nv] == RMASS)
atom->rmass[nlocal] = extra[nlocal][m++];
else if (styles[nv] == IVEC)
atom->ivector[index[nv]][nlocal] = (int) ubuf(extra[nlocal][m++]).i;
else if (styles[nv] == DVEC)
atom->dvector[index[nv]][nlocal] = extra[nlocal][m++];
else if (styles[nv] == IARRAY) {
ncol = cols[nv];
for (k = 0; k < ncol; k++)
atom->iarray[index[nv]][nlocal][k] = (int) ubuf(extra[nlocal][m++]).i;
} else if (styles[nv] == DARRAY) {
ncol = cols[nv];
for (k = 0; k < ncol; k++)
atom->darray[index[nv]][nlocal][k] = extra[nlocal][m++];
}
}
}
/* ----------------------------------------------------------------------
maxsize of any atom's restart data
------------------------------------------------------------------------- */
int FixPropertyAtom::maxsize_restart()
{
return values_peratom+1;
}
/* ----------------------------------------------------------------------
size of atom nlocal's restart data
------------------------------------------------------------------------- */
int FixPropertyAtom::size_restart(int /*nlocal*/)
{
return values_peratom+1;
}