diff --git a/src/AMOEBA/pair_amoeba.cpp b/src/AMOEBA/pair_amoeba.cpp index de505f4a4e9..4cb5c39b610 100644 --- a/src/AMOEBA/pair_amoeba.cpp +++ b/src/AMOEBA/pair_amoeba.cpp @@ -1,4 +1,3 @@ -// clang-format off /* ---------------------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator https://www.lammps.org/ Sandia National Laboratories @@ -39,17 +38,19 @@ using namespace LAMMPS_NS; using MathSpecial::powint; -enum{INDUCE,RSD,SETUP_AMOEBA,SETUP_HIPPO,KMPOLE,AMGROUP,PVAL}; // forward comm -enum{FIELD,ZRSD,TORQUE,UFLD}; // reverse comm -enum{ARITHMETIC,GEOMETRIC,CUBIC_MEAN,R_MIN,SIGMA,DIAMETER,HARMONIC,HHG,W_H}; -enum{HAL,REPULSE,QFER,DISP,MPOLE,POLAR,USOLV,DISP_LONG,MPOLE_LONG,POLAR_LONG}; -enum{MPOLE_GRID,POLAR_GRID,POLAR_GRIDC,DISP_GRID,INDUCE_GRID,INDUCE_GRIDC}; -enum{MUTUAL,OPT,TCG,DIRECT}; -enum{GEAR,ASPC,LSQR}; +enum { INDUCE, RSD, SETUP_AMOEBA, SETUP_HIPPO, KMPOLE, AMGROUP, PVAL }; // forward comm +enum { FIELD, ZRSD, TORQUE, UFLD }; // reverse comm +enum { ARITHMETIC, GEOMETRIC, CUBIC_MEAN, R_MIN, SIGMA, DIAMETER, HARMONIC, HHG, W_H }; +enum { HAL, REPULSE, QFER, DISP, MPOLE, POLAR, USOLV, DISP_LONG, MPOLE_LONG, POLAR_LONG }; +enum { MPOLE_GRID, POLAR_GRID, POLAR_GRIDC, DISP_GRID, INDUCE_GRID, INDUCE_GRIDC }; +enum { MUTUAL, OPT, TCG, DIRECT }; +enum { GEAR, ASPC, LSQR }; static constexpr int DELTASTACK = 16; #define DEBUG_AMOEBA 0 +// clang-format off + /* ---------------------------------------------------------------------- */ PairAmoeba::PairAmoeba(LAMMPS *lmp) : Pair(lmp) @@ -429,7 +430,7 @@ void PairAmoeba::compute(int eflag, int vflag) // output FF settings to screen and logfile // delay until here because RMS force accuracy is computed based on rpole - if (first_flag_compute && (comm->me == 0)) print_settings(); + if (first_flag_compute) print_settings(); first_flag_compute = 0; if (amoeba) pbc_xred(); @@ -827,28 +828,36 @@ void PairAmoeba::init_style() // check if all custom atom arrays were set via fix property/atom - int flag,cols; - - index_amtype = atom->find_custom("amtype",flag,cols); - if (index_amtype < 0 || flag || cols) - error->all(FLERR,"Pair {} amtype is not defined", mystyle); - index_amgroup = atom->find_custom("amgroup",flag,cols); - if (index_amgroup < 0 || flag || cols) - error->all(FLERR,"Pair {} amgroup is not defined", mystyle); - - index_redID = atom->find_custom("redID",flag,cols); - if (index_redID < 0 || !flag || cols) - error->all(FLERR,"Pair {} redID is not defined", mystyle); - index_xyzaxis = atom->find_custom("xyzaxis",flag,cols); - if (index_xyzaxis < 0 || !flag || cols == 0) - error->all(FLERR,"Pair {} xyzaxis is not defined", mystyle); - - index_polaxe = atom->find_custom("polaxe",flag,cols); - if (index_polaxe < 0 || flag || cols) - error->all(FLERR,"Pair {} polaxe is not defined", mystyle); - index_pval = atom->find_custom("pval",flag,cols); - if (index_pval < 0 || !flag || cols) - error->all(FLERR,"Pair {} pval is not defined", mystyle); + // clang-format on + const char *names[6] = {"amtype", "amgroup", "redID", "xyzaxis", "polaxe", "pval"}; + const int flag_check[6] = {0, 0, 1, 1, 0, 1}; // correct type (0 int, 1 dbl) + const int cols_check[6] = {0, 0, 0, 3, 0, 0}; // xyzaxis 3 cols, all others 0 + const int ghost_check[6] = {1, 1, 1, 0, 0, 1}; // which types need ghost; TO-DO: check + int flag, cols, ghost, index[6]; + + // clang-format off + + for (int i = 0; i < 6; i++) { + if (ghost_check[i]) { + index[i] = atom->find_custom_ghost(names[i], flag, cols, ghost); + } else { + index[i] = atom->find_custom(names[i], flag, cols); + } + std::string err = ""; + if (index[i] < 0) err = "was not defined"; + else if (flag_check[i] != flag) err = "has the wrong type"; + else if (cols_check[i] != cols) err = "has the wrong number of columns"; + else if (ghost_check[i] && !ghost) err = "must be set by fix property/atom with ghost yes"; + if (err != "") + error->all(FLERR,"Pair {} per-atom variable {} {}", mystyle, names[i], err); + } + + index_amtype = index[0]; + index_amgroup = index[1]; + index_redID = index[2]; + index_xyzaxis = index[3]; + index_polaxe = index[4]; + index_pval = index[5]; // ------------------------------------------------------------------- // one-time initializations @@ -1069,79 +1078,86 @@ void PairAmoeba::init_style() void PairAmoeba::print_settings() { std::string mesg = utils::uppercase(mystyle) + " force field settings\n"; + double estimated_mpole_accuracy = 0.0; - if (amoeba) { - choose(HAL); - mesg += fmt::format(" hal: cut {} taper {} vscale {} {} {} {}\n", sqrt(off2),sqrt(cut2), - special_hal[1],special_hal[2],special_hal[3],special_hal[4]); - } else { - choose(REPULSE); - mesg += fmt::format(" repulsion: cut {} taper {} rscale {} {} {} {}\n", sqrt(off2),sqrt(cut2), - special_repel[1],special_repel[2],special_repel[3],special_repel[4]); + if (use_ewald) { + choose(MPOLE_LONG); + estimated_mpole_accuracy = final_accuracy_mpole(); + } - choose(QFER); - mesg += fmt::format(" qxfer: cut {} taper {} mscale {} {} {} {}\n", sqrt(off2),sqrt(cut2), - special_mpole[1],special_mpole[2],special_mpole[3],special_mpole[4]); + if (comm->me == 0) { + if (amoeba) { + choose(HAL); + mesg += fmt::format(" hal: cut {} taper {} vscale {} {} {} {}\n", sqrt(off2),sqrt(cut2), + special_hal[1],special_hal[2],special_hal[3],special_hal[4]); + } else { + choose(REPULSE); + mesg += fmt::format(" repulsion: cut {} taper {} rscale {} {} {} {}\n", sqrt(off2),sqrt(cut2), + special_repel[1],special_repel[2],special_repel[3],special_repel[4]); + + choose(QFER); + mesg += fmt::format(" qxfer: cut {} taper {} mscale {} {} {} {}\n", sqrt(off2),sqrt(cut2), + special_mpole[1],special_mpole[2],special_mpole[3],special_mpole[4]); + + if (use_dewald) { + choose(DISP_LONG); + mesg += fmt::format(" dispersion: cut {} aewald {} bsorder {} FFT {} {} {} " + "dspscale {} {} {} {}\n", sqrt(off2),aewald,bsdorder,ndfft1,ndfft2,ndfft3, + special_disp[1],special_disp[2],special_disp[3],special_disp[4]); + } else { + choose(DISP); + mesg += fmt::format(" dispersion: cut {} aewald {} dspscale {} {} {} {}\n", + sqrt(off2),aewald,special_disp[1], + special_disp[2],special_disp[3],special_disp[4]); + } + } - if (use_dewald) { - choose(DISP_LONG); - mesg += fmt::format(" dispersion: cut {} aewald {} bsorder {} FFT {} {} {} " - "dspscale {} {} {} {}\n", sqrt(off2),aewald,bsdorder,ndfft1,ndfft2,ndfft3, - special_disp[1],special_disp[2],special_disp[3],special_disp[4]); + if (use_ewald) { + choose(MPOLE_LONG); + mesg += fmt::format(" multipole: cut {} aewald {} bsorder {} FFT {} {} {}\n" + " estimated absolute RMS force accuracy = {:.8g}\n" + " estimated relative RMS force accuracy = {:.8g}\n" + " mscale {} {} {} {}\n", + sqrt(off2),aewald,bseorder,nefft1,nefft2,nefft3, + estimated_mpole_accuracy,estimated_mpole_accuracy/two_charge_force, + special_mpole[1],special_mpole[2],special_mpole[3],special_mpole[4]); } else { - choose(DISP); - mesg += fmt::format(" dispersion: cut {} aewald {} dspscale {} {} {} {}\n", - sqrt(off2),aewald,special_disp[1], - special_disp[2],special_disp[3],special_disp[4]); + choose(MPOLE); + mesg += fmt::format(" multipole: cut {} aewald {} mscale {} {} {} {}\n", sqrt(off2),aewald, + special_mpole[1],special_mpole[2],special_mpole[3],special_mpole[4]); } - } - if (use_ewald) { - choose(MPOLE_LONG); - double estimated_accuracy = final_accuracy_mpole(); - mesg += fmt::format(" multipole: cut {} aewald {} bsorder {} FFT {} {} {}; " - "estimated absolute RMS force accuracy = {:.8g}; " - "estimated relative RMS force accuracy = {:.8g}; " - "mscale {} {} {} {}\n", - sqrt(off2),aewald,bseorder,nefft1,nefft2,nefft3, - estimated_accuracy,estimated_accuracy/two_charge_force, - special_mpole[1],special_mpole[2],special_mpole[3],special_mpole[4]); - } else { - choose(MPOLE); - mesg += fmt::format(" multipole: cut {} aewald {} mscale {} {} {} {}\n", sqrt(off2),aewald, - special_mpole[1],special_mpole[2],special_mpole[3],special_mpole[4]); - } + if (use_ewald) { + choose(POLAR_LONG); + mesg += fmt::format(" polar: cut {} aewald {} bsorder {} FFT {} {} {}\n", + sqrt(off2),aewald,bsporder,nefft1,nefft2,nefft3); + mesg += fmt::format(" pscale {} {} {} {} piscale {} {} {} {} " + "wscale {} {} {} {} d/u scale {} {}\n", + special_polar_pscale[1],special_polar_pscale[2], + special_polar_pscale[3],special_polar_pscale[4], + special_polar_piscale[1],special_polar_piscale[2], + special_polar_piscale[3],special_polar_piscale[4], + special_polar_wscale[1],special_polar_wscale[2], + special_polar_wscale[3],special_polar_wscale[4], + polar_dscale,polar_uscale); + } else { + choose(POLAR); + mesg += fmt::format(" polar: cut {} aewald {}\n",sqrt(off2),aewald); + mesg += fmt::format(" pscale {} {} {} {} piscale {} {} {} {} " + "wscale {} {} {} {} d/u scale {} {}\n", + special_polar_pscale[1],special_polar_pscale[2], + special_polar_pscale[3],special_polar_pscale[4], + special_polar_piscale[1],special_polar_piscale[2], + special_polar_piscale[3],special_polar_piscale[4], + special_polar_wscale[1],special_polar_wscale[2], + special_polar_wscale[3],special_polar_wscale[4], + polar_dscale,polar_uscale); + } - if (use_ewald) { - choose(POLAR_LONG); - mesg += fmt::format(" polar: cut {} aewald {} bsorder {} FFT {} {} {}\n", - sqrt(off2),aewald,bsporder,nefft1,nefft2,nefft3); - mesg += fmt::format(" pscale {} {} {} {} piscale {} {} {} {} " - "wscale {} {} {} {} d/u scale {} {}\n", - special_polar_pscale[1],special_polar_pscale[2], - special_polar_pscale[3],special_polar_pscale[4], - special_polar_piscale[1],special_polar_piscale[2], - special_polar_piscale[3],special_polar_piscale[4], - special_polar_wscale[1],special_polar_wscale[2], - special_polar_wscale[3],special_polar_wscale[4], - polar_dscale,polar_uscale); - } else { - choose(POLAR); - mesg += fmt::format(" polar: cut {} aewald {}\n",sqrt(off2),aewald); - mesg += fmt::format(" pscale {} {} {} {} piscale {} {} {} {} " - "wscale {} {} {} {} d/u scale {} {}\n", - special_polar_pscale[1],special_polar_pscale[2], - special_polar_pscale[3],special_polar_pscale[4], - special_polar_piscale[1],special_polar_piscale[2], - special_polar_piscale[3],special_polar_piscale[4], - special_polar_wscale[1],special_polar_wscale[2], - special_polar_wscale[3],special_polar_wscale[4], - polar_dscale,polar_uscale); + choose(USOLV); + mesg += fmt::format(" precondition: cut {}\n",sqrt(off2)); + utils::logmesg(lmp, mesg); } - - choose(USOLV); - mesg += fmt::format(" precondition: cut {}\n",sqrt(off2)); - utils::logmesg(lmp, mesg); } /* ---------------------------------------------------------------------- diff --git a/src/KOKKOS/atom_kokkos.cpp b/src/KOKKOS/atom_kokkos.cpp index 501b719ad43..af1816c1d30 100644 --- a/src/KOKKOS/atom_kokkos.cpp +++ b/src/KOKKOS/atom_kokkos.cpp @@ -300,7 +300,7 @@ void AtomKokkos::grow(unsigned int mask) return index in ivector or dvector of its location ------------------------------------------------------------------------- */ -int AtomKokkos::add_custom(const char *name, int flag, int cols) +int AtomKokkos::add_custom(const char *name, int flag, int cols, int ghost) { int index = -1; @@ -309,6 +309,8 @@ int AtomKokkos::add_custom(const char *name, int flag, int cols) nivector++; ivname = (char **) memory->srealloc(ivname, nivector * sizeof(char *), "atom:ivname"); ivname[index] = utils::strdup(name); + ivghost = (int *) memory->srealloc(ivghost,nivector * sizeof(int),"atom:ivghost"); + ivghost[index] = ghost; ivector = (int **) memory->srealloc(ivector, nivector * sizeof(int *), "atom:ivector"); memory->create(ivector[index], nmax, "atom:ivector"); @@ -317,6 +319,8 @@ int AtomKokkos::add_custom(const char *name, int flag, int cols) ndvector++; dvname = (char **) memory->srealloc(dvname, ndvector * sizeof(char *), "atom:dvname"); dvname[index] = utils::strdup(name); + dvghost = (int *) memory->srealloc(dvghost, ndvector * sizeof(int), "atom:dvghost"); + dvghost[index] = ghost; dvector = (double **) memory->srealloc(dvector, ndvector * sizeof(double *), "atom:dvector"); this->sync(Device, DVECTOR_MASK); memoryKK->grow_kokkos(k_dvector, dvector, ndvector, nmax, "atom:dvector"); @@ -327,6 +331,8 @@ int AtomKokkos::add_custom(const char *name, int flag, int cols) niarray++; ianame = (char **) memory->srealloc(ianame, niarray * sizeof(char *), "atom:ianame"); ianame[index] = utils::strdup(name); + iaghost = (int *) memory->srealloc(iaghost, niarray * sizeof(int), "atom:iaghost"); + iaghost[index] = ghost; iarray = (int ***) memory->srealloc(iarray, niarray * sizeof(int **), "atom:iarray"); memory->create(iarray[index], nmax, cols, "atom:iarray"); @@ -338,6 +344,8 @@ int AtomKokkos::add_custom(const char *name, int flag, int cols) ndarray++; daname = (char **) memory->srealloc(daname, ndarray * sizeof(char *), "atom:daname"); daname[index] = utils::strdup(name); + daghost = (int *) memory->srealloc(daghost, ndarray * sizeof(int), "atom:daghost"); + daghost[index] = ghost; darray = (double ***) memory->srealloc(darray, ndarray * sizeof(double **), "atom:darray"); memory->create(darray[index], nmax, cols, "atom:darray"); @@ -345,6 +353,9 @@ int AtomKokkos::add_custom(const char *name, int flag, int cols) dcols[index] = cols; } + if (index < 0) + error->all(FLERR,"Invalid call to AtomKokkos::add_custom()"); + return index; } diff --git a/src/KOKKOS/atom_kokkos.h b/src/KOKKOS/atom_kokkos.h index e6269b5527a..db132bce694 100644 --- a/src/KOKKOS/atom_kokkos.h +++ b/src/KOKKOS/atom_kokkos.h @@ -154,7 +154,7 @@ class AtomKokkos : public Atom { void sync_overlapping_device(const ExecutionSpace space, unsigned int mask); void sort() override; virtual void grow(unsigned int mask); - int add_custom(const char *, int, int) override; + int add_custom(const char *, int, int, int border = 0) override; void remove_custom(int, int, int) override; virtual void deallocate_topology(); private: diff --git a/src/atom.cpp b/src/atom.cpp index 195587b5936..f7f61d6cedf 100644 --- a/src/atom.cpp +++ b/src/atom.cpp @@ -235,6 +235,7 @@ Atom::Atom(LAMMPS *_lmp) : Pointers(_lmp), atom_style(nullptr), avec(nullptr), a darray = nullptr; icols = dcols = nullptr; ivname = dvname = ianame = daname = nullptr; + ivghost = dvghost = iaghost = daghost = nullptr; // initialize atom style and array existence flags @@ -334,6 +335,10 @@ Atom::~Atom() memory->sfree(darray); memory->sfree(icols); memory->sfree(dcols); + memory->destroy(ivghost); + memory->destroy(dvghost); + memory->destroy(iaghost); + memory->destroy(daghost); // delete user-defined molecules @@ -2609,6 +2614,18 @@ void Atom::update_callback(int ifix) if (extra_border[i] > ifix) extra_border[i]--; } +/** \brief Find a custom per-atom property with given name +\verbatim embed:rst + +This function returns the list index of a custom per-atom property +with the name "name", also returning by reference its data type and +number of values per atom. +\endverbatim + * \param name Name of the property (w/o a "i_" or "d_" or "i2_" or "d2_" prefix) + * \param &flag Returns data type of property: 0 for int, 1 for double + * \param &cols Returns number of values: 0 for a single value, 1 or more for a vector of values + * \return index of property in the respective list of properties + */ /* ---------------------------------------------------------------------- find custom per-atom vector with name return index if found, -1 if not found @@ -2652,6 +2669,33 @@ int Atom::find_custom(const char *name, int &flag, int &cols) return -1; } +/** \brief Find a custom per-atom property with given name and retrieve ghost property +\verbatim embed:rst + +This function returns the list index of a custom per-atom property +with the name "name", also returning by reference its data type, +number of values per atom, and if it is communicated to ghost particles. +Classes rarely need to check on ghost communication and so `find_custom` +is typically preferred to this function. See :doc:`pair amoeba ` +for an example where checking ghost communication is necessary. +\endverbatim + * \param name Name of the property (w/o a "i_" or "d_" or "i2_" or "d2_" prefix) + * \param &flag Returns data type of property: 0 for int, 1 for double + * \param &cols Returns number of values: 0 for a single value, 1 or more for a vector of values + * \param &ghost Returns whether property is communicated to ghost atoms: 0 for no, 1 for yes + * \return index of property in the respective list of properties + */ +int Atom::find_custom_ghost(const char *name, int &flag, int &cols, int &ghost) +{ + int i = find_custom(name, flag, cols); + if (i == -1) return i; + if ((flag == 0) && (cols == 0)) ghost = ivghost[i]; + else if ((flag == 1) && (cols == 0)) ghost = dvghost[i]; + else if ((flag == 0) && (cols == 1)) ghost = iaghost[i]; + else if ((flag == 1) && (cols == 1)) ghost = daghost[i]; + return i; +} + /** \brief Add a custom per-atom property with the given name and type and size \verbatim embed:rst @@ -2662,9 +2706,10 @@ This function is called, e.g. from :doc:`fix property/atom `. * \param name Name of the property (w/o a "i_" or "d_" or "i2_" or "d2_" prefix) * \param flag Data type of property: 0 for int, 1 for double * \param cols Number of values: 0 for a single value, 1 or more for a vector of values + * \param ghost Whether property is communicated to ghost atoms: 0 for no, 1 for yes * \return index of property in the respective list of properties */ -int Atom::add_custom(const char *name, int flag, int cols) +int Atom::add_custom(const char *name, int flag, int cols, int ghost) { int index = -1; @@ -2673,6 +2718,8 @@ int Atom::add_custom(const char *name, int flag, int cols) nivector++; ivname = (char **) memory->srealloc(ivname,nivector*sizeof(char *),"atom:ivname"); ivname[index] = utils::strdup(name); + ivghost = (int *) memory->srealloc(ivghost,nivector*sizeof(int),"atom:ivghost"); + ivghost[index] = ghost; ivector = (int **) memory->srealloc(ivector,nivector*sizeof(int *),"atom:ivector"); memory->create(ivector[index],nmax,"atom:ivector"); @@ -2681,6 +2728,8 @@ int Atom::add_custom(const char *name, int flag, int cols) ndvector++; dvname = (char **) memory->srealloc(dvname,ndvector*sizeof(char *),"atom:dvname"); dvname[index] = utils::strdup(name); + dvghost = (int *) memory->srealloc(dvghost,ndvector*sizeof(int),"atom:dvghost"); + dvghost[index] = ghost; dvector = (double **) memory->srealloc(dvector,ndvector*sizeof(double *),"atom:dvector"); memory->create(dvector[index],nmax,"atom:dvector"); @@ -2689,6 +2738,8 @@ int Atom::add_custom(const char *name, int flag, int cols) niarray++; ianame = (char **) memory->srealloc(ianame,niarray*sizeof(char *),"atom:ianame"); ianame[index] = utils::strdup(name); + iaghost = (int *) memory->srealloc(iaghost,niarray*sizeof(int),"atom:iaghost"); + iaghost[index] = ghost; iarray = (int ***) memory->srealloc(iarray,niarray*sizeof(int **),"atom:iarray"); memory->create(iarray[index],nmax,cols,"atom:iarray"); icols = (int *) memory->srealloc(icols,niarray*sizeof(int),"atom:icols"); @@ -2699,6 +2750,8 @@ int Atom::add_custom(const char *name, int flag, int cols) ndarray++; daname = (char **) memory->srealloc(daname,ndarray*sizeof(char *),"atom:daname"); daname[index] = utils::strdup(name); + daghost = (int *) memory->srealloc(daghost,ndarray*sizeof(int),"atom:daghost"); + daghost[index] = ghost; darray = (double ***) memory->srealloc(darray,ndarray*sizeof(double **),"atom:darray"); memory->create(darray[index],nmax,cols,"atom:darray"); dcols = (int *) memory->srealloc(dcols,ndarray*sizeof(int),"atom:dcols"); @@ -2707,6 +2760,7 @@ int Atom::add_custom(const char *name, int flag, int cols) if (index < 0) error->all(FLERR,"Invalid call to Atom::add_custom()"); + return index; } diff --git a/src/atom.h b/src/atom.h index 2ceecefe5eb..f238b2d5b10 100644 --- a/src/atom.h +++ b/src/atom.h @@ -242,6 +242,7 @@ class Atom : protected Pointers { int *icols, *dcols; char **ivname, **dvname, **ianame, **daname; int nivector, ndvector, niarray, ndarray; + int *ivghost, *dvghost, *iaghost, *daghost; // molecule templates // each template can be a set of consecutive molecules @@ -363,7 +364,8 @@ class Atom : protected Pointers { void update_callback(int); int find_custom(const char *, int &, int &); - virtual int add_custom(const char *, int, int); + int find_custom_ghost(const char *, int &, int &, int &); + virtual int add_custom(const char *, int, int, int ghost = 0); virtual void remove_custom(int, int, int); void *extract(const char *); diff --git a/src/fix_property_atom.cpp b/src/fix_property_atom.cpp index 9613523059d..de96b5c39d6 100644 --- a/src/fix_property_atom.cpp +++ b/src/fix_property_atom.cpp @@ -51,6 +51,19 @@ FixPropertyAtom::FixPropertyAtom(LAMMPS *lmp, int narg, char **arg) : nvalue = 0; values_peratom = 0; + // check for ghost keyword to use as add_custom() arg + + 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 iarg++; + } + + iarg = 3; + while (iarg < narg) { if (strcmp(arg[iarg], "mol") == 0) { if (atom->molecule_flag) @@ -112,7 +125,7 @@ FixPropertyAtom::FixPropertyAtom(LAMMPS *lmp, int narg, char **arg) : 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); + index[nvalue] = atom->add_custom(&arg[iarg][2], 0, 0, border); cols[nvalue] = 0; values_peratom++; nvalue++; @@ -125,7 +138,7 @@ FixPropertyAtom::FixPropertyAtom(LAMMPS *lmp, int narg, char **arg) : 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); + index[nvalue] = atom->add_custom(&arg[iarg][2], 1, 0, border); cols[nvalue] = 0; values_peratom++; nvalue++; @@ -154,7 +167,7 @@ FixPropertyAtom::FixPropertyAtom(LAMMPS *lmp, int narg, char **arg) : which = 1; styles[nvalue] = DARRAY; } - index[nvalue] = atom->add_custom(&arg[iarg][3], which, ncols); + index[nvalue] = atom->add_custom(&arg[iarg][3], which, ncols, border); cols[nvalue] = ncols; values_peratom += ncols; nvalue++; @@ -168,11 +181,8 @@ FixPropertyAtom::FixPropertyAtom(LAMMPS *lmp, int narg, char **arg) : // 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); + if (strcmp(arg[iarg], "ghost") == 0) { // skip here, since handled earlier iarg += 2; } else if (strcmp(arg[iarg], "writedata") == 0) { if (iarg + 2 > narg) error->all(FLERR, "Illegal fix property/atom command");