diff --git a/doc/src/fix_adapt.rst b/doc/src/fix_adapt.rst index 2b39917d86..a6c07fad4d 100644 --- a/doc/src/fix_adapt.rst +++ b/doc/src/fix_adapt.rst @@ -14,7 +14,7 @@ Syntax * adapt = style name of this fix command * N = adapt simulation settings every this many timesteps * one or more attribute/arg pairs may be appended -* attribute = *pair* or *bond* or *angle* or *kspace* or *atom* +* attribute = *pair* or *bond* or *angle* or *improper* or *kspace* or *atom* .. parsed-literal:: @@ -33,6 +33,11 @@ Syntax aparam = parameter to adapt over time I = type angle to set parameter for (integer or type label) v_name = variable with name that calculates value of aparam + *improper* args = istyle iparam I v_name + istyle = improper style name (e.g., cvff) + iparam = parameter to adapt over time + I = type improper to set parameter for (integer or type label) + v_name = variable with name that calculates value of iparam *kspace* arg = v_name v_name = variable with name that calculates scale factor on :math:`k`-space terms *atom* args = atomparam v_name @@ -428,6 +433,56 @@ this fix uses to reset theta0 needs to generate values in radians. ---------- +.. versionadded:: TBD + +The *improper* keyword uses the specified variable to change the value of +an improper coefficient over time, very similar to how the *angle* keyword +operates. The only difference is that now an improper coefficient for a +given improper type is adapted. + +A wild-card asterisk can be used in place of or in conjunction with the +improper type argument to set the coefficients for multiple improper types. +This takes the form "\*" or "\*n" or "m\*" or "m\*n". If :math:`N` is +the number of improper types, then an asterisk with no numeric values means +all types from 1 to :math:`N`. A leading asterisk means all types from +1 to n (inclusive). A trailing asterisk means all types from m to +:math:`N` (inclusive). A middle asterisk means all types from m to n +(inclusive). + +If :doc:`improper_style hybrid ` is used, *istyle* should be a +sub-style name. The improper styles that currently work with fix adapt are: + ++---------------------------------------------------------+----------------+----------------+ +| :doc:`amoeba ` | k | type impropers | ++---------------------------------------------------------+----------------+----------------+ +| :doc:`class2 ` | k,chi0 | type impropers | ++---------------------------------------------------------+----------------+----------------+ +| :doc:`cossq ` | k,chi0 | type impropers | ++---------------------------------------------------------+----------------+----------------+ +| :doc:`cvff ` | k,d,n | type impropers | ++---------------------------------------------------------+----------------+----------------+ +| :doc:`distance ` | k2,k4 | type impropers | ++---------------------------------------------------------+----------------+----------------+ +| :doc:`distharm ` | k,d0 | type impropers | ++---------------------------------------------------------+----------------+----------------+ +| :doc:`fourier ` | k,C0,C1,C2 | type impropers | ++---------------------------------------------------------+----------------+----------------+ +| :doc:`harmonic ` | k,chi0 | type impropers | ++---------------------------------------------------------+----------------+----------------+ +| :doc:`inversion/harmonic ` | k,w0 | type impropers | ++---------------------------------------------------------+----------------+----------------+ +| :doc:`ring ` | k,theta0 | type impropers | ++---------------------------------------------------------+----------------+----------------+ +| :doc:`umbrella ` | k,w0 | type impropers | ++---------------------------------------------------------+----------------+----------------+ +| :doc:`sqdistharm ` | k | type impropers | ++---------------------------------------------------------+----------------+----------------+ + +Note that internally, chi0 and theta0 are stored in radians, so the variable +this fix use to reset chi0 or theta0 needs to generate values in radians. + +---------- + The *kspace* keyword used the specified variable as a scale factor on the energy, forces, virial calculated by whatever :math:`k`-space solver is defined by the :doc:`kspace_style ` command. If the diff --git a/src/AMOEBA/improper_amoeba.cpp b/src/AMOEBA/improper_amoeba.cpp index f14713cd20..d8b00888f5 100644 --- a/src/AMOEBA/improper_amoeba.cpp +++ b/src/AMOEBA/improper_amoeba.cpp @@ -337,3 +337,14 @@ void ImproperAmoeba::write_data(FILE *fp) for (int i = 1; i <= atom->nimpropertypes; i++) fprintf(fp,"%d %g\n",i,k[i]); } + +/* ---------------------------------------------------------------------- + return ptr to internal members upon request +------------------------------------------------------------------------ */ + +void *ImproperAmoeba::extract(const char *str, int &dim) +{ + dim = 1; + if (strcmp(str, "k") == 0) return (void *) k; + return nullptr; +} diff --git a/src/AMOEBA/improper_amoeba.h b/src/AMOEBA/improper_amoeba.h index d5a783a82f..f997b61629 100644 --- a/src/AMOEBA/improper_amoeba.h +++ b/src/AMOEBA/improper_amoeba.h @@ -34,6 +34,7 @@ class ImproperAmoeba : public Improper { void write_restart(FILE *) override; void read_restart(FILE *) override; void write_data(FILE *) override; + void *extract(const char *, int &) override; protected: int disable; diff --git a/src/CLASS2/improper_class2.cpp b/src/CLASS2/improper_class2.cpp index e53b06969c..20e1670f92 100644 --- a/src/CLASS2/improper_class2.cpp +++ b/src/CLASS2/improper_class2.cpp @@ -843,3 +843,15 @@ void ImproperClass2::write_data(FILE *fp) aa_theta0_1[i]*180.0/MY_PI,aa_theta0_2[i]*180.0/MY_PI, aa_theta0_3[i]*180.0/MY_PI); } + +/* ---------------------------------------------------------------------- + return ptr to internal members upon request +------------------------------------------------------------------------ */ + +void *ImproperClass2::extract(const char *str, int &dim) +{ + dim = 1; + if (strcmp(str, "k") == 0) return (void *) k0; + if (strcmp(str, "chi0") == 0) return (void *) chi0; + return nullptr; +} diff --git a/src/CLASS2/improper_class2.h b/src/CLASS2/improper_class2.h index 6102ef945c..3e30c8be53 100644 --- a/src/CLASS2/improper_class2.h +++ b/src/CLASS2/improper_class2.h @@ -33,6 +33,7 @@ class ImproperClass2 : public Improper { void write_restart(FILE *) override; void read_restart(FILE *) override; void write_data(FILE *) override; + void *extract(const char *, int &) override; protected: double *k0, *chi0; diff --git a/src/EXTRA-MOLECULE/improper_cossq.cpp b/src/EXTRA-MOLECULE/improper_cossq.cpp index 5d7a425217..e68930a9d8 100644 --- a/src/EXTRA-MOLECULE/improper_cossq.cpp +++ b/src/EXTRA-MOLECULE/improper_cossq.cpp @@ -309,3 +309,15 @@ void ImproperCossq::write_data(FILE *fp) for (int i = 1; i <= atom->nimpropertypes; i++) fprintf(fp,"%d %g %g\n",i,k[i],chi[i]/MY_PI*180.0); } + +/* ---------------------------------------------------------------------- + return ptr to internal members upon request +------------------------------------------------------------------------ */ + +void *ImproperCossq::extract(const char *str, int &dim) +{ + dim = 1; + if (strcmp(str, "k") == 0) return (void *) k; + if (strcmp(str, "chi0") == 0) return (void *) chi; + return nullptr; +} diff --git a/src/EXTRA-MOLECULE/improper_cossq.h b/src/EXTRA-MOLECULE/improper_cossq.h index cc7e94ca5c..bcc12e654f 100644 --- a/src/EXTRA-MOLECULE/improper_cossq.h +++ b/src/EXTRA-MOLECULE/improper_cossq.h @@ -33,6 +33,7 @@ class ImproperCossq : public Improper { void write_restart(FILE *) override; void read_restart(FILE *) override; void write_data(FILE *) override; + void *extract(const char *, int &) override; protected: double *k, *chi; diff --git a/src/EXTRA-MOLECULE/improper_distance.cpp b/src/EXTRA-MOLECULE/improper_distance.cpp index b8376020dd..ec55abaf2b 100644 --- a/src/EXTRA-MOLECULE/improper_distance.cpp +++ b/src/EXTRA-MOLECULE/improper_distance.cpp @@ -268,3 +268,16 @@ void ImproperDistance::write_data(FILE *fp) for (int i = 1; i <= atom->nimpropertypes; i++) fprintf(fp,"%d %g %g\n",i,k[i],chi[i]); } + + +/* ---------------------------------------------------------------------- + return ptr to internal members upon request +------------------------------------------------------------------------ */ + +void *ImproperDistance::extract(const char *str, int &dim) +{ + dim = 1; + if (strcmp(str, "k2") == 0) return (void *) k; + if (strcmp(str, "k4") == 0) return (void *) chi; + return nullptr; +} diff --git a/src/EXTRA-MOLECULE/improper_distance.h b/src/EXTRA-MOLECULE/improper_distance.h index b0bfaea6e6..67d5cacc46 100644 --- a/src/EXTRA-MOLECULE/improper_distance.h +++ b/src/EXTRA-MOLECULE/improper_distance.h @@ -33,6 +33,7 @@ class ImproperDistance : public Improper { void write_restart(FILE *) override; void read_restart(FILE *) override; void write_data(FILE *) override; + void *extract(const char *, int &) override; private: double *k, *chi; diff --git a/src/EXTRA-MOLECULE/improper_fourier.cpp b/src/EXTRA-MOLECULE/improper_fourier.cpp index b2814f4d1f..350612a559 100644 --- a/src/EXTRA-MOLECULE/improper_fourier.cpp +++ b/src/EXTRA-MOLECULE/improper_fourier.cpp @@ -337,3 +337,17 @@ void ImproperFourier::write_data(FILE *fp) for (int i = 1; i <= atom->nimpropertypes; i++) fprintf(fp,"%d %g %g %g %g %d\n",i,k[i],C0[i],C1[i],C2[i],all[i]); } + +/* ---------------------------------------------------------------------- + return ptr to internal members upon request +------------------------------------------------------------------------ */ + +void *ImproperFourier::extract(const char *str, int &dim) +{ + dim = 1; + if (strcmp(str, "k") == 0) return (void *) k; + if (strcmp(str, "C0") == 0) return (void *) C0; + if (strcmp(str, "C1") == 0) return (void *) C1; + if (strcmp(str, "C2") == 0) return (void *) C2; + return nullptr; +} diff --git a/src/EXTRA-MOLECULE/improper_fourier.h b/src/EXTRA-MOLECULE/improper_fourier.h index 96354b6818..a4ec0d6096 100644 --- a/src/EXTRA-MOLECULE/improper_fourier.h +++ b/src/EXTRA-MOLECULE/improper_fourier.h @@ -33,6 +33,7 @@ class ImproperFourier : public Improper { void write_restart(FILE *) override; void read_restart(FILE *) override; void write_data(FILE *) override; + void *extract(const char *, int &) override; protected: double *k, *C0, *C1, *C2; diff --git a/src/EXTRA-MOLECULE/improper_ring.cpp b/src/EXTRA-MOLECULE/improper_ring.cpp index 57adb50260..7595a25c64 100644 --- a/src/EXTRA-MOLECULE/improper_ring.cpp +++ b/src/EXTRA-MOLECULE/improper_ring.cpp @@ -339,3 +339,16 @@ void ImproperRing::write_data(FILE *fp) for (int i = 1; i <= atom->nimpropertypes; i++) fprintf(fp,"%d %g %g\n",i,k[i],acos(chi[i])/MY_PI*180.0); } + + +/* ---------------------------------------------------------------------- + return ptr to internal members upon request +------------------------------------------------------------------------ */ + +void *ImproperRing::extract(const char *str, int &dim) +{ + dim = 1; + if (strcmp(str, "k") == 0) return (void *) k; + if (strcmp(str, "theta0") == 0) return (void *) chi; + return nullptr; +} diff --git a/src/EXTRA-MOLECULE/improper_ring.h b/src/EXTRA-MOLECULE/improper_ring.h index db8a681f75..0c68b4e15a 100644 --- a/src/EXTRA-MOLECULE/improper_ring.h +++ b/src/EXTRA-MOLECULE/improper_ring.h @@ -33,6 +33,7 @@ class ImproperRing : public Improper { void write_restart(FILE *) override; void read_restart(FILE *) override; void write_data(FILE *) override; + void *extract(const char *, int &) override; protected: double *k, *chi; diff --git a/src/MOFFF/improper_inversion_harmonic.cpp b/src/MOFFF/improper_inversion_harmonic.cpp index 0a4661c6b1..7e51d4338c 100644 --- a/src/MOFFF/improper_inversion_harmonic.cpp +++ b/src/MOFFF/improper_inversion_harmonic.cpp @@ -332,3 +332,15 @@ void ImproperInversionHarmonic::write_data(FILE *fp) for (int i = 1; i <= atom->nimpropertypes; i++) fprintf(fp,"%d %g %g\n",i,kw[i],w0[i]/MY_PI*180.0); } + +/* ---------------------------------------------------------------------- + return ptr to internal members upon request +------------------------------------------------------------------------ */ + +void *ImproperInversionHarmonic::extract(const char *str, int &dim) +{ + dim = 1; + if (strcmp(str, "k") == 0) return (void *) kw; + if (strcmp(str, "w0") == 0) return (void *) w0; + return nullptr; +} diff --git a/src/MOFFF/improper_inversion_harmonic.h b/src/MOFFF/improper_inversion_harmonic.h index 2ad1bceba1..eabb91194f 100644 --- a/src/MOFFF/improper_inversion_harmonic.h +++ b/src/MOFFF/improper_inversion_harmonic.h @@ -33,6 +33,7 @@ class ImproperInversionHarmonic : public Improper { void write_restart(FILE *) override; void read_restart(FILE *) override; void write_data(FILE *) override; + void *extract(const char *, int &) override; protected: double *kw, *w0; diff --git a/src/MOLECULE/improper_cvff.cpp b/src/MOLECULE/improper_cvff.cpp index 11dace26d1..480d106549 100644 --- a/src/MOLECULE/improper_cvff.cpp +++ b/src/MOLECULE/improper_cvff.cpp @@ -337,3 +337,16 @@ void ImproperCvff::write_data(FILE *fp) for (int i = 1; i <= atom->nimpropertypes; i++) fprintf(fp, "%d %g %d %d\n", i, k[i], sign[i], multiplicity[i]); } + +/* ---------------------------------------------------------------------- + return ptr to internal members upon request +------------------------------------------------------------------------ */ + +void *ImproperCvff::extract(const char *str, int &dim) +{ + dim = 1; + if (strcmp(str, "k") == 0) return (void *) k; + if (strcmp(str, "d") == 0) return (void *) sign; + if (strcmp(str, "n") == 0) return (void *) multiplicity; + return nullptr; +} diff --git a/src/MOLECULE/improper_cvff.h b/src/MOLECULE/improper_cvff.h index ff550fe9e8..07ff607417 100644 --- a/src/MOLECULE/improper_cvff.h +++ b/src/MOLECULE/improper_cvff.h @@ -33,6 +33,7 @@ class ImproperCvff : public Improper { void write_restart(FILE *) override; void read_restart(FILE *) override; void write_data(FILE *) override; + void *extract(const char *, int &) override; protected: double *k; diff --git a/src/MOLECULE/improper_harmonic.cpp b/src/MOLECULE/improper_harmonic.cpp index 5f25d678db..02a9d7a60d 100644 --- a/src/MOLECULE/improper_harmonic.cpp +++ b/src/MOLECULE/improper_harmonic.cpp @@ -276,3 +276,15 @@ void ImproperHarmonic::write_data(FILE *fp) for (int i = 1; i <= atom->nimpropertypes; i++) fprintf(fp, "%d %g %g\n", i, k[i], RAD2DEG * chi[i]); } + +/* ---------------------------------------------------------------------- + return ptr to internal members upon request +------------------------------------------------------------------------ */ + +void *ImproperHarmonic::extract(const char *str, int &dim) +{ + dim = 1; + if (strcmp(str, "k") == 0) return (void *) k; + if (strcmp(str, "chi0") == 0) return (void *) chi; + return nullptr; +} diff --git a/src/MOLECULE/improper_harmonic.h b/src/MOLECULE/improper_harmonic.h index 89ebe49dec..a0047c28f2 100644 --- a/src/MOLECULE/improper_harmonic.h +++ b/src/MOLECULE/improper_harmonic.h @@ -33,6 +33,7 @@ class ImproperHarmonic : public Improper { void write_restart(FILE *) override; void read_restart(FILE *) override; void write_data(FILE *) override; + void *extract(const char *, int &) override; protected: double *k, *chi; diff --git a/src/MOLECULE/improper_umbrella.cpp b/src/MOLECULE/improper_umbrella.cpp index d3dcf4da41..3c8e2c0d93 100644 --- a/src/MOLECULE/improper_umbrella.cpp +++ b/src/MOLECULE/improper_umbrella.cpp @@ -322,3 +322,16 @@ void ImproperUmbrella::write_data(FILE *fp) for (int i = 1; i <= atom->nimpropertypes; i++) fprintf(fp, "%d %g %g\n", i, kw[i], RAD2DEG * w0[i]); } + + +/* ---------------------------------------------------------------------- + return ptr to internal members upon request +------------------------------------------------------------------------ */ + +void *ImproperUmbrella::extract(const char *str, int &dim) +{ + dim = 1; + if (strcmp(str, "k") == 0) return (void *) kw; + if (strcmp(str, "w0") == 0) return (void *) w0; + return nullptr; +} diff --git a/src/MOLECULE/improper_umbrella.h b/src/MOLECULE/improper_umbrella.h index 9441810861..a6791ffe20 100644 --- a/src/MOLECULE/improper_umbrella.h +++ b/src/MOLECULE/improper_umbrella.h @@ -33,6 +33,7 @@ class ImproperUmbrella : public Improper { void write_restart(FILE *) override; void read_restart(FILE *) override; void write_data(FILE *) override; + void *extract(const char *, int &) override; protected: double *kw, *w0, *C; diff --git a/src/YAFF/improper_distharm.cpp b/src/YAFF/improper_distharm.cpp index c056b310ee..69d14cc997 100644 --- a/src/YAFF/improper_distharm.cpp +++ b/src/YAFF/improper_distharm.cpp @@ -226,12 +226,9 @@ void ImproperDistHarm::coeff(int narg, char **arg) double k_one = utils::numeric(FLERR,arg[1],false,lmp); double chi_one = utils::numeric(FLERR,arg[2],false,lmp); - // convert chi from degrees to radians - int count = 0; for (int i = ilo; i <= ihi; i++) { k[i] = k_one; - //chi[i] = chi_one/180.0 * PI; chi[i] = chi_one; setflag[i] = 1; count++; @@ -267,3 +264,15 @@ void ImproperDistHarm::read_restart(FILE *fp) for (int i = 1; i <= atom->nimpropertypes; i++) setflag[i] = 1; } + +/* ---------------------------------------------------------------------- + return ptr to internal members upon request +------------------------------------------------------------------------ */ + +void *ImproperDistHarm::extract(const char *str, int &dim) +{ + dim = 1; + if (strcmp(str, "k") == 0) return (void *) k; + if (strcmp(str, "d0") == 0) return (void *) chi; + return nullptr; +} diff --git a/src/YAFF/improper_distharm.h b/src/YAFF/improper_distharm.h index 911bbadb0d..6896af3e15 100644 --- a/src/YAFF/improper_distharm.h +++ b/src/YAFF/improper_distharm.h @@ -32,6 +32,7 @@ class ImproperDistHarm : public Improper { void coeff(int, char **) override; void write_restart(FILE *) override; void read_restart(FILE *) override; + void *extract(const char *, int &) override; private: double *k, *chi; diff --git a/src/YAFF/improper_sqdistharm.cpp b/src/YAFF/improper_sqdistharm.cpp index f3a34f3976..1981c61f38 100644 --- a/src/YAFF/improper_sqdistharm.cpp +++ b/src/YAFF/improper_sqdistharm.cpp @@ -267,3 +267,14 @@ void ImproperSQDistHarm::read_restart(FILE *fp) for (int i = 1; i <= atom->nimpropertypes; i++) setflag[i] = 1; } + +/* ---------------------------------------------------------------------- + return ptr to internal members upon request +------------------------------------------------------------------------ */ + +void *ImproperSQDistHarm::extract(const char *str, int &dim) +{ + dim = 1; + if (strcmp(str, "k") == 0) return (void *) k; + return nullptr; +} diff --git a/src/YAFF/improper_sqdistharm.h b/src/YAFF/improper_sqdistharm.h index 4cd89a294e..d8d4131362 100644 --- a/src/YAFF/improper_sqdistharm.h +++ b/src/YAFF/improper_sqdistharm.h @@ -32,6 +32,7 @@ class ImproperSQDistHarm : public Improper { void coeff(int, char **) override; void write_restart(FILE *) override; void read_restart(FILE *) override; + void *extract(const char *, int &) override; private: double *k, *chi; diff --git a/src/fix_adapt.cpp b/src/fix_adapt.cpp index 418e2e4a80..eb7125caf7 100644 --- a/src/fix_adapt.cpp +++ b/src/fix_adapt.cpp @@ -24,6 +24,8 @@ #include "fix_store_atom.h" #include "force.h" #include "group.h" +#include "improper.h" +#include "improper_hybrid.h" #include "input.h" #include "kspace.h" #include "math_const.h" @@ -41,14 +43,14 @@ using namespace LAMMPS_NS; using namespace FixConst; using namespace MathConst; -enum{PAIR, KSPACE, ATOM, BOND, ANGLE}; +enum{PAIR, KSPACE, ATOM, BOND, ANGLE, IMPROPER}; enum{DIAMETER, CHARGE}; /* ---------------------------------------------------------------------- */ FixAdapt::FixAdapt(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, narg, arg), nadapt(0), anypair(0), anybond(0), anyangle(0), - id_fix_diam(nullptr), id_fix_chg(nullptr), adapt(nullptr) + anyimproper(0), id_fix_diam(nullptr), id_fix_chg(nullptr), adapt(nullptr) { if (narg < 5) utils::missing_cmd_args(FLERR,"fix adapt", error); nevery = utils::inumeric(FLERR,arg[3],false,lmp); @@ -83,6 +85,10 @@ FixAdapt::FixAdapt(LAMMPS *lmp, int narg, char **arg) : if (iarg+5 > narg) utils::missing_cmd_args(FLERR,"fix adapt angle", error); nadapt++; iarg += 5; + } else if (strcmp(arg[iarg],"improper") == 0) { + if (iarg+5 > narg) utils::missing_cmd_args(FLERR,"fix adapt improper", error); + nadapt++; + iarg += 5; } else break; } @@ -149,6 +155,19 @@ FixAdapt::FixAdapt(LAMMPS *lmp, int narg, char **arg) : nadapt++; iarg += 5; + } else if (strcmp(arg[iarg],"improper") == 0) { + adapt[nadapt].which = IMPROPER; + adapt[nadapt].improper = nullptr; + adapt[nadapt].istyle = utils::strdup(arg[iarg+1]); + adapt[nadapt].iparam = utils::strdup(arg[iarg+2]); + utils::bounds_typelabel(FLERR, arg[iarg+3], 1, atom->nimpropertypes, + adapt[nadapt].ilo, adapt[nadapt].ihi, lmp, Atom::IMPROPER); + if (utils::strmatch(arg[iarg+4],"^v_")) { + adapt[nadapt].var = utils::strdup(arg[iarg+4]+2); + } else error->all(FLERR,"Argument #{} must be variable not {}", iarg+5, arg[iarg+4]); + nadapt++; + iarg += 5; + } else if (strcmp(arg[iarg],"kspace") == 0) { adapt[nadapt].which = KSPACE; if (utils::strmatch(arg[iarg+1],"^v_")) { @@ -224,6 +243,13 @@ FixAdapt::FixAdapt(LAMMPS *lmp, int narg, char **arg) : n = atom->nangletypes; for (int m = 0; m < nadapt; ++m) if (adapt[m].which == ANGLE) memory->create(adapt[m].vector_orig,n+1,"adapt:vector_orig"); + + // allocate improper style arrays: + + n = atom->nimpropertypes; + for (int m = 0; m < nadapt; ++m) + if (adapt[m].which == IMPROPER) memory->create(adapt[m].vector_orig,n+1,"adapt:vector_orig"); + } /* ---------------------------------------------------------------------- */ @@ -244,6 +270,10 @@ FixAdapt::~FixAdapt() delete[] adapt[m].astyle; delete[] adapt[m].aparam; memory->destroy(adapt[m].vector_orig); + } else if (adapt[m].which == IMPROPER) { + delete[] adapt[m].istyle; + delete[] adapt[m].iparam; + memory->destroy(adapt[m].vector_orig); } } delete[] adapt; @@ -338,6 +368,7 @@ void FixAdapt::init() anypair = 0; anybond = 0; anyangle = 0; + anyimproper = 0; for (int m = 0; m < nadapt; m++) { Adapt *ad = &adapt[m]; @@ -478,6 +509,40 @@ void FixAdapt::init() delete[] astyle; + } else if (ad->which == IMPROPER) { + ad->improper = nullptr; + anyimproper = 1; + + char *istyle = utils::strdup(ad->istyle); + if (lmp->suffix_enable) + ad->improper = force->improper_match(fmt::format("{}/{}",istyle,lmp->suffix)); + + if (ad->improper == nullptr) ad->improper = force->improper_match(istyle); + if (ad->improper == nullptr ) + error->all(FLERR,"Fix adapt improper style {} does not exist", istyle); + + void *ptr = ad->improper->extract(ad->iparam,ad->idim); + + if (ptr == nullptr) + error->all(FLERR,"Fix adapt improper style parameter {} not supported", ad->iparam); + + // for improper styles, use a vector + + if (ad->idim == 1) ad->vector = (double *) ptr; + + if (utils::strmatch(force->improper_style,"^hybrid")) { + auto improper = dynamic_cast(force->improper); + if (improper) { + for (i = ad->ilo; i <= ad->ihi; i++) { + if (!improper->check_itype(i,istyle)) + error->all(FLERR,"Fix adapt type improper range is not valid " + "for improper hybrid sub-style {}", istyle); + } + } + } + + delete[] istyle; + } else if (ad->which == KSPACE) { if (force->kspace == nullptr) error->all(FLERR, Error::NOLASTLINE, @@ -504,7 +569,7 @@ void FixAdapt::init() if (restart_reset) restart_reset = 0; - // make copy of original pair/bond/angle array values + // make copy of original pair/bond/angle/improper array values for (int m = 0; m < nadapt; m++) { Adapt *ad = &adapt[m]; @@ -522,6 +587,10 @@ void FixAdapt::init() } else if (ad->which == ANGLE && ad->adim == 1) { for (i = ad->ilo; i <= ad->ihi; ++i ) ad->vector_orig[i] = ad->vector[i]; + + } else if (ad->which == IMPROPER && ad->idim == 1) { + for (i = ad->ilo; i <= ad->ihi; ++i ) + ad->vector_orig[i] = ad->vector[i]; } } @@ -641,6 +710,18 @@ void FixAdapt::change_settings() ad->vector[i] = value; } + // set improper type array values: + + } else if (ad->which == IMPROPER) { + if (ad->idim == 1) { + if (scaleflag) + for (i = ad->ilo; i <= ad->ihi; ++i ) + ad->vector[i] = value*ad->vector_orig[i]; + else + for (i = ad->ilo; i <= ad->ihi; ++i ) + ad->vector[i] = value; + } + // set kspace scale factor } else if (ad->which == KSPACE) { @@ -716,6 +797,7 @@ void FixAdapt::change_settings() if (anypair) force->pair->reinit(); if (anybond) force->bond->reinit(); if (anyangle) force->angle->reinit(); + if (anyimproper) force->improper->reinit(); // reset KSpace charges if charges have changed @@ -750,6 +832,12 @@ void FixAdapt::restore_settings() ad->vector[i] = ad->vector_orig[i]; } + } else if (ad->which == IMPROPER) { + if (ad->idim == 1) { + for (int i = ad->ilo; i <= ad->ihi; i++) + ad->vector[i] = ad->vector_orig[i]; + } + } else if (ad->which == KSPACE) { *kspace_scale = 1.0; @@ -790,6 +878,7 @@ void FixAdapt::restore_settings() if (anypair) force->pair->reinit(); if (anybond) force->bond->reinit(); if (anyangle) force->angle->reinit(); + if (anyimproper) force->improper->reinit(); if (chgflag && force->kspace) force->kspace->qsum_qsq(); } diff --git a/src/fix_adapt.h b/src/fix_adapt.h index 20964a8b12..9f064a163e 100644 --- a/src/fix_adapt.h +++ b/src/fix_adapt.h @@ -44,7 +44,7 @@ class FixAdapt : public Fix { private: int nadapt, resetflag, scaleflag, massflag; - int anypair, anybond, anyangle; + int anypair, anybond, anyangle, anyimproper; int nlevels_respa; char *id_fix_diam, *id_fix_chg; class FixStoreAtom *fix_diam, *fix_chg; @@ -57,8 +57,9 @@ class FixAdapt : public Fix { char *pstyle, *pparam; char *bstyle, *bparam; char *astyle, *aparam; + char *istyle, *iparam; int ilo, ihi, jlo, jhi; - int pdim, bdim, adim; + int pdim, bdim, adim, idim; double *scalar, scalar_orig; double *vector, *vector_orig; double **array, **array_orig; @@ -66,6 +67,7 @@ class FixAdapt : public Fix { class Pair *pair; class Bond *bond; class Angle *angle; + class Improper *improper; }; Adapt *adapt; diff --git a/src/improper.cpp b/src/improper.cpp index 02158dfff1..77570f565c 100644 --- a/src/improper.cpp +++ b/src/improper.cpp @@ -31,6 +31,7 @@ Improper::Improper(LAMMPS *_lmp) : Pointers(_lmp) { energy = 0.0; writedata = 0; + reinitflag = 1; for (int i = 0; i < 4; i++) symmatoms[i] = 0; allocated = 0; @@ -427,3 +428,15 @@ double Improper::memory_usage() bytes += (double) comm->nthreads * maxvatom * 6 * sizeof(double); return bytes; } + +/* ----------------------------------------------------------------------- + reset all type-based improper params via init() +-------------------------------------------------------------------------- */ + +void Improper::reinit() +{ + if (!reinitflag) + error->all(FLERR, "Fix adapt interface to this improper style not supported"); + + init(); +} diff --git a/src/improper.h b/src/improper.h index f65ba3bdbc..0f539bdece 100644 --- a/src/improper.h +++ b/src/improper.h @@ -37,6 +37,9 @@ class Improper : protected Pointers { // CENTROID_AVAIL = different and implemented // CENTROID_NOTAVAIL = different, not yet implemented + int reinitflag; // 0 if not compatible with fix adapt + // extract() method may still need to be added + int symmatoms[4]; // symmetry atom(s) of improper style // value of 0: interchangable atoms // value of 1: central atom @@ -67,6 +70,8 @@ class Improper : protected Pointers { du = 0.0; du2 = 0.0; } + virtual void *extract(const char *, int &) { return nullptr; } + void reinit(); protected: int suffix_flag; // suffix compatibility flag diff --git a/src/improper_hybrid.cpp b/src/improper_hybrid.cpp index 5337f062b4..1edfe5ceb7 100644 --- a/src/improper_hybrid.cpp +++ b/src/improper_hybrid.cpp @@ -320,6 +320,14 @@ void ImproperHybrid::init_style() if (styles[m]) styles[m]->init_style(); } +/* ---------------------------------------------------------------------- */ + +int ImproperHybrid::check_itype(int itype, char *substyle) +{ + if (strcmp(keywords[map[itype]], substyle) == 0) return 1; + return 0; +} + /* ---------------------------------------------------------------------- proc 0 writes to restart file ------------------------------------------------------------------------- */ diff --git a/src/improper_hybrid.h b/src/improper_hybrid.h index 89a4664da2..86df8ea9d0 100644 --- a/src/improper_hybrid.h +++ b/src/improper_hybrid.h @@ -40,6 +40,8 @@ class ImproperHybrid : public Improper { void read_restart(FILE *) override; double memory_usage() override; + int check_itype(int, char *); + protected: int *map; // which style each improper type points to diff --git a/unittest/force-styles/test_improper_style.cpp b/unittest/force-styles/test_improper_style.cpp index e272033e85..4a8c3d5106 100644 --- a/unittest/force-styles/test_improper_style.cpp +++ b/unittest/force-styles/test_improper_style.cpp @@ -720,3 +720,44 @@ TEST(ImproperStyle, numdiff) cleanup_lammps(lmp, test_config); if (!verbose) ::testing::internal::GetCapturedStdout(); } + +TEST(ImproperStyle, extract) +{ + if (test_config.skip_tests.count(test_info_->name())) GTEST_SKIP(); + + LAMMPS::argv args = {"ImproperStyle", "-log", "none", "-echo", "screen", "-nocite"}; + + if (!verbose) ::testing::internal::CaptureStdout(); + LAMMPS *lmp = nullptr; + try { + lmp = init_lammps(args, test_config, true); + } catch (std::exception &e) { + if (!verbose) ::testing::internal::GetCapturedStdout(); + FAIL() << e.what(); + } + if (!verbose) ::testing::internal::GetCapturedStdout(); + + if (!lmp) { + std::cerr << "One or more prerequisite styles are not available " + "in this LAMMPS configuration:\n"; + for (auto prerequisite : test_config.prerequisites) { + std::cerr << prerequisite.first << "_style " << prerequisite.second << "\n"; + } + GTEST_SKIP(); + } + + auto *improper = lmp->force->improper; + void *ptr = nullptr; + int dim = 0; + for (auto extract : test_config.extract) { + ptr = improper->extract(extract.first.c_str(), dim); + EXPECT_NE(ptr, nullptr); + EXPECT_EQ(dim, extract.second); + } + ptr = improper->extract("does_not_exist", dim); + EXPECT_EQ(ptr, nullptr); + + if (!verbose) ::testing::internal::CaptureStdout(); + cleanup_lammps(lmp, test_config); + if (!verbose) ::testing::internal::GetCapturedStdout(); +} diff --git a/unittest/force-styles/tests/improper-class2.yaml b/unittest/force-styles/tests/improper-class2.yaml index 4350441eeb..eba334a1e6 100644 --- a/unittest/force-styles/tests/improper-class2.yaml +++ b/unittest/force-styles/tests/improper-class2.yaml @@ -14,7 +14,9 @@ improper_coeff: ! | 1 75.0 169 2 45.0 10 * aa 75 42 31 125.4 130.01 115.06 -extract: ! "" +extract: ! | + k 1 + chi0 1 natoms: 29 init_energy: 1375.7372366975192 init_stress: ! |- diff --git a/unittest/force-styles/tests/improper-cossq.yaml b/unittest/force-styles/tests/improper-cossq.yaml index 4faaa2214a..2e2767d368 100644 --- a/unittest/force-styles/tests/improper-cossq.yaml +++ b/unittest/force-styles/tests/improper-cossq.yaml @@ -13,7 +13,9 @@ improper_style: cossq improper_coeff: ! | 1 75.0 120.2 2 45.0 59.5 -extract: ! "" +extract: ! | + k 1 + chi0 1 natoms: 29 init_energy: 47.901206451962224 init_stress: ! |- diff --git a/unittest/force-styles/tests/improper-cvff.yaml b/unittest/force-styles/tests/improper-cvff.yaml index 3a300de4d6..be18107884 100644 --- a/unittest/force-styles/tests/improper-cvff.yaml +++ b/unittest/force-styles/tests/improper-cvff.yaml @@ -13,7 +13,10 @@ improper_style: cvff improper_coeff: ! | 1 75.0 -1 5 2 45.0 +1 2 -extract: ! "" +extract: ! | + k 1 + d 1 + n 1 natoms: 29 init_energy: 89.33266688553577 init_stress: ! |2- diff --git a/unittest/force-styles/tests/improper-distance.yaml b/unittest/force-styles/tests/improper-distance.yaml index 91df7b7bae..3c64d4af52 100644 --- a/unittest/force-styles/tests/improper-distance.yaml +++ b/unittest/force-styles/tests/improper-distance.yaml @@ -13,7 +13,9 @@ improper_style: distance improper_coeff: ! | 1 75.0 120.2 2 45.0 59.5 -extract: ! "" +extract: ! | + k2 1 + k4 1 natoms: 29 init_energy: 0.0747454910197192 init_stress: ! |- diff --git a/unittest/force-styles/tests/improper-distharm.yaml b/unittest/force-styles/tests/improper-distharm.yaml index e2916d3d74..1ae48c8488 100644 --- a/unittest/force-styles/tests/improper-distharm.yaml +++ b/unittest/force-styles/tests/improper-distharm.yaml @@ -13,7 +13,9 @@ improper_style: distharm improper_coeff: ! | 1 75.0 5.5 2 45.0 6.2 -extract: ! "" +extract: ! | + k 1 + d0 1 natoms: 29 init_energy: 3973.601605432119 init_stress: ! |2- diff --git a/unittest/force-styles/tests/improper-fourier.yaml b/unittest/force-styles/tests/improper-fourier.yaml index 278698a190..096d9c0fa1 100644 --- a/unittest/force-styles/tests/improper-fourier.yaml +++ b/unittest/force-styles/tests/improper-fourier.yaml @@ -13,7 +13,11 @@ improper_style: fourier improper_coeff: ! | 1 75.0 0.9 0.2 0.3 1 2 45.0 0.5 0.1 0.8 0 -extract: ! "" +extract: ! | + k 1 + C0 1 + C1 1 + C2 1 natoms: 29 init_energy: 376.7915390602297 init_stress: ! |2- diff --git a/unittest/force-styles/tests/improper-harmonic.yaml b/unittest/force-styles/tests/improper-harmonic.yaml index 7ac0dbe06e..7b2e14ee9e 100644 --- a/unittest/force-styles/tests/improper-harmonic.yaml +++ b/unittest/force-styles/tests/improper-harmonic.yaml @@ -13,7 +13,9 @@ improper_style: harmonic improper_coeff: ! | 1 75.0 120.2 2 45.0 59.5 -extract: ! "" +extract: ! | + k 1 + chi0 1 natoms: 29 init_energy: 369.34096479618404 init_stress: ! |2- diff --git a/unittest/force-styles/tests/improper-inversion_harmonic.yaml b/unittest/force-styles/tests/improper-inversion_harmonic.yaml index 73eade4958..44fd09763d 100644 --- a/unittest/force-styles/tests/improper-inversion_harmonic.yaml +++ b/unittest/force-styles/tests/improper-inversion_harmonic.yaml @@ -13,7 +13,9 @@ improper_style: inversion/harmonic improper_coeff: ! | 1 75.0 0.1 2 45.0 1.0 -extract: ! "" +extract: ! | + k 1 + w0 1 natoms: 29 init_energy: 0.35230115027159387 init_stress: ! |- diff --git a/unittest/force-styles/tests/improper-ring.yaml b/unittest/force-styles/tests/improper-ring.yaml index 6a824f9699..48cb944af3 100644 --- a/unittest/force-styles/tests/improper-ring.yaml +++ b/unittest/force-styles/tests/improper-ring.yaml @@ -13,7 +13,9 @@ improper_style: ring improper_coeff: ! | 1 75.0 120.2 2 45.0 59.5 -extract: ! "" +extract: ! | + k 1 + theta0 1 natoms: 29 init_energy: 31535.23771704055 init_stress: ! |- diff --git a/unittest/force-styles/tests/improper-sqdistharm.yaml b/unittest/force-styles/tests/improper-sqdistharm.yaml index 8bf671efbd..7e08c86fc7 100644 --- a/unittest/force-styles/tests/improper-sqdistharm.yaml +++ b/unittest/force-styles/tests/improper-sqdistharm.yaml @@ -13,7 +13,8 @@ improper_style: sqdistharm improper_coeff: ! | 1 75.0 5.5 2 45.0 6.2 -extract: ! "" +extract: ! | + k 1 natoms: 29 init_energy: 3997.62616072489 init_stress: ! |2- diff --git a/unittest/force-styles/tests/improper-umbrella.yaml b/unittest/force-styles/tests/improper-umbrella.yaml index ff6822e9d8..61557813c8 100644 --- a/unittest/force-styles/tests/improper-umbrella.yaml +++ b/unittest/force-styles/tests/improper-umbrella.yaml @@ -13,7 +13,9 @@ improper_style: umbrella improper_coeff: ! | 1 75.0 120.2 2 45.0 59.5 -extract: ! "" +extract: ! | + k 1 + w0 1 natoms: 29 init_energy: 120.51735030260785 init_stress: ! |2-