diff --git a/doc/src/Fortran.rst b/doc/src/Fortran.rst index 76fdff753a8..c8d153b2e3e 100644 --- a/doc/src/Fortran.rst +++ b/doc/src/Fortran.rst @@ -315,6 +315,10 @@ of the contents of the :f:mod:`LIBLAMMPS` Fortran interface to LAMMPS. :ftype extract_variable: function :f set_variable: :f:subr:`set_variable` :ftype set_variable: subroutine + :f set_string_variable: :f:subr:`set_set_string_variable` + :ftype set_string_variable: subroutine + :f set_internal_variable: :f:subr:`set_internal_variable` + :ftype set_internal_variable: subroutine :f gather_atoms: :f:subr:`gather_atoms` :ftype gather_atoms: subroutine :f gather_atoms_concat: :f:subr:`gather_atoms_concat` @@ -1398,18 +1402,55 @@ Procedures Bound to the :f:type:`lammps` Derived Type Set the value of a string-style variable. - .. versionadded:: 3Nov2022 + .. deprecated:: TBD This function assigns a new value from the string *str* to the string-style variable *name*\ . If *name* does not exist or is not a string-style variable, an error is generated. + .. warning:: + + This subroutine is deprecated and :f:subr:`set_string_variable` + should be used instead. + :p character(len=*) name: name of the variable :p character(len=*) str: new value to assign to the variable :to: :cpp:func:`lammps_set_variable` -------- +.. f:subroutine:: set_string_variable(name, str) + + Set the value of a string-style variable. + + .. versionadded:: TBD + + This function assigns a new value from the string *str* to the string-style + variable *name*\ . If *name* does not exist or is not a string-style + variable, an error is generated. + + :p character(len=*) name: name of the variable + :p character(len=*) str: new value to assign to the variable + :to: :cpp:func:`lammps_set_string_variable` + +-------- + +.. f:subroutine:: set_internal_variable(name, val) + + Set the value of a internal-style variable. + + .. versionadded:: TBD + + This function assigns a new value from the floating-point number *val* to + the internal-style variable *name*\ . If *name* does not exist or is not + an internal-style variable, an error is generated. + + :p character(len=*) name: name of the variable + :p read(c_double) val: new value to assign to the variable + :to: :cpp:func:`lammps_set_internal_variable` + +-------- + .. f:subroutine:: gather_atoms(name, count, data) This function calls :cpp:func:`lammps_gather_atoms` to gather the named diff --git a/doc/src/Library_objects.rst b/doc/src/Library_objects.rst index db21817cfd7..7c0ca824d7a 100644 --- a/doc/src/Library_objects.rst +++ b/doc/src/Library_objects.rst @@ -9,6 +9,8 @@ fixes, or variables in LAMMPS using the following functions: - :cpp:func:`lammps_extract_variable_datatype` - :cpp:func:`lammps_extract_variable` - :cpp:func:`lammps_set_variable` +- :cpp:func:`lammps_set_string_variable` +- :cpp:func:`lammps_set_internal_variable` - :cpp:func:`lammps_variable_info` ----------------------- @@ -38,6 +40,16 @@ fixes, or variables in LAMMPS using the following functions: ----------------------- +.. doxygenfunction:: lammps_set_string_variable + :project: progguide + +----------------------- + +.. doxygenfunction:: lammps_set_internal_variable + :project: progguide + +----------------------- + .. doxygenfunction:: lammps_variable_info :project: progguide diff --git a/examples/COUPLE/plugin/liblammpsplugin.c b/examples/COUPLE/plugin/liblammpsplugin.c index 5228e07e9c2..011c3202546 100644 --- a/examples/COUPLE/plugin/liblammpsplugin.c +++ b/examples/COUPLE/plugin/liblammpsplugin.c @@ -110,6 +110,8 @@ liblammpsplugin_t *liblammpsplugin_load(const char *lib) ADDSYM(extract_variable); ADDSYM(extract_variable_datatype); ADDSYM(set_variable); + ADDSYM(set_string_variable); + ADDSYM(set_internal_variable); ADDSYM(variable_info); ADDSYM(gather_atoms); diff --git a/examples/COUPLE/plugin/liblammpsplugin.h b/examples/COUPLE/plugin/liblammpsplugin.h index 92398dfb271..1d647e8e934 100644 --- a/examples/COUPLE/plugin/liblammpsplugin.h +++ b/examples/COUPLE/plugin/liblammpsplugin.h @@ -152,9 +152,11 @@ struct _liblammpsplugin { void *(*extract_compute)(void *, const char *, int, int); void *(*extract_fix)(void *, const char *, int, int, int, int); - void *(*extract_variable)(void *, const char *, char *); + void *(*extract_variable)(void *, const char *, const char *); int (*extract_variable_datatype)(void *, const char *); - int (*set_variable)(void *, char *, char *); + int (*set_variable)(void *, const char *, const char *); + int (*set_string_variable)(void *, const char *, const char *); + int (*set_internal_variable)(void *, const char *, double); int (*variable_info)(void *, int, char *, int); void (*gather_atoms)(void *, const char *, int, int, void *); diff --git a/fortran/lammps.f90 b/fortran/lammps.f90 index 28e40bca443..071dffebc06 100644 --- a/fortran/lammps.f90 +++ b/fortran/lammps.f90 @@ -118,6 +118,8 @@ MODULE LIBLAMMPS PROCEDURE :: extract_fix => lmp_extract_fix PROCEDURE :: extract_variable => lmp_extract_variable PROCEDURE :: set_variable => lmp_set_variable + PROCEDURE :: set_string_variable => lmp_set_string_variable + PROCEDURE :: set_internal_variable => lmp_set_internal_variable PROCEDURE, PRIVATE :: lmp_gather_atoms_int PROCEDURE, PRIVATE :: lmp_gather_atoms_double GENERIC :: gather_atoms => lmp_gather_atoms_int, & @@ -557,6 +559,21 @@ FUNCTION lammps_set_variable(handle, name, str) BIND(C) INTEGER(c_int) :: lammps_set_variable END FUNCTION lammps_set_variable + FUNCTION lammps_set_string_variable(handle, name, str) BIND(C) + IMPORT :: c_int, c_ptr + IMPLICIT NONE + TYPE(c_ptr), VALUE :: handle, name, str + INTEGER(c_int) :: lammps_set_string_variable + END FUNCTION lammps_set_string_variable + + FUNCTION lammps_set_internal_variable(handle, name, val) BIND(C) + IMPORT :: c_int, c_ptr, c_double + IMPLICIT NONE + TYPE(c_ptr), VALUE :: handle, name + REAL(c_double), VALUE :: val + INTEGER(c_int) :: lammps_set_internal_variable + END FUNCTION lammps_set_internal_variable + SUBROUTINE lammps_gather_atoms(handle, name, type, count, data) BIND(C) IMPORT :: c_int, c_ptr IMPLICIT NONE @@ -1631,6 +1648,43 @@ SUBROUTINE lmp_set_variable(self, name, str) END IF END SUBROUTINE lmp_set_variable + ! equivalent function to lammps_set_string_variable + SUBROUTINE lmp_set_string_variable(self, name, str) + CLASS(lammps), INTENT(IN) :: self + CHARACTER(LEN=*), INTENT(IN) :: name, str + INTEGER :: err + TYPE(c_ptr) :: Cstr, Cname + + Cstr = f2c_string(str) + Cname = f2c_string(name) + err = lammps_set_string_variable(self%handle, Cname, Cstr) + CALL lammps_free(Cname) + CALL lammps_free(Cstr) + IF (err /= 0) THEN + CALL lmp_error(self, LMP_ERROR_WARNING + LMP_ERROR_WORLD, & + 'WARNING: unable to set string variable "' // name & + // '" [Fortran/set_variable]') + END IF + END SUBROUTINE lmp_set_string_variable + + ! equivalent function to lammps_set_internal_variable + SUBROUTINE lmp_set_internal_variable(self, name, val) + CLASS(lammps), INTENT(IN) :: self + CHARACTER(LEN=*), INTENT(IN) :: name + REAL(KIND=c_double), INTENT(IN) :: val + INTEGER :: err + TYPE(c_ptr) :: Cstr, Cname + + Cname = f2c_string(name) + err = lammps_set_internal_variable(self%handle, Cname, val) + CALL lammps_free(Cname) + IF (err /= 0) THEN + CALL lmp_error(self, LMP_ERROR_WARNING + LMP_ERROR_WORLD, & + 'WARNING: unable to set internal variable "' // name & + // '" [Fortran/set_variable]') + END IF + END SUBROUTINE lmp_set_internal_variable + ! equivalent function to lammps_gather_atoms (for integers) SUBROUTINE lmp_gather_atoms_int(self, name, count, data) CLASS(lammps), INTENT(IN) :: self diff --git a/python/lammps/core.py b/python/lammps/core.py index 1ff123760b0..f4ba7d398bc 100644 --- a/python/lammps/core.py +++ b/python/lammps/core.py @@ -282,6 +282,8 @@ def __init__(self,name='',cmdargs=None,ptr=None,comm=None): self.lib.lammps_config_accelerator.argtypes = [c_char_p, c_char_p, c_char_p] self.lib.lammps_set_variable.argtypes = [c_void_p, c_char_p, c_char_p] + self.lib.lammps_set_string_variable.argtypes = [c_void_p, c_char_p, c_char_p] + self.lib.lammps_set_internal_variable.argtypes = [c_void_p, c_char_p, c_double] self.lib.lammps_has_style.argtypes = [c_void_p, c_char_p, c_char_p] @@ -1252,6 +1254,8 @@ def flush_buffers(self): def set_variable(self,name,value): """Set a new value for a LAMMPS string style variable + .. deprecated:: TBD + This is a wrapper around the :cpp:func:`lammps_set_variable` function of the C-library interface. @@ -1271,6 +1275,52 @@ def set_variable(self,name,value): # ------------------------------------------------------------------------- + def set_string_variable(self,name,value): + """Set a new value for a LAMMPS string style variable + + .. versionadded:: TBD + + This is a wrapper around the :cpp:func:`lammps_set_string_variable` + function of the C-library interface. + + :param name: name of the variable + :type name: string + :param value: new variable value + :type value: any. will be converted to a string + :return: either 0 on success or -1 on failure + :rtype: int + """ + if name: name = name.encode() + else: return -1 + if value: value = str(value).encode() + else: return -1 + with ExceptionCheck(self): + return self.lib.lammps_set_string_variable(self.lmp,name,value) + + # ------------------------------------------------------------------------- + + def set_internal_variable(self,name,value): + """Set a new value for a LAMMPS internal style variable + + .. versionadded:: TBD + + This is a wrapper around the :cpp:func:`lammps_set_internal_variable` + function of the C-library interface. + + :param name: name of the variable + :type name: string + :param value: new variable value + :type value: float or compatible. will be converted to float + :return: either 0 on success or -1 on failure + :rtype: int + """ + if name: name = name.encode() + else: return -1 + with ExceptionCheck(self): + return self.lib.lammps_set_internal_variable(self.lmp,name,value) + + # ------------------------------------------------------------------------- + # return vector of atom properties gathered across procs # 3 variants to match src/library.cpp # name = atom property recognized by LAMMPS in atom->extract() diff --git a/src/library.cpp b/src/library.cpp index a629df7b8c0..65034ef0d6a 100644 --- a/src/library.cpp +++ b/src/library.cpp @@ -2451,19 +2451,69 @@ int lammps_extract_variable_datatype(void *handle, const char *name) } /* ---------------------------------------------------------------------- */ +// for printing obsolete function call warning only once +static int set_variable_deprecated_flag = 1; /** Set the value of a string-style variable. - * - * This function assigns a new value from the string str to the - * string-style variable name. Returns -1 if a variable of that - * name does not exist or is not a string-style variable, otherwise 0. - * +\verbatim embed:rst + +.. deprecated:: TBD + +This function assigns a new value from the string str to the +string-style variable *name*. This is a way to directly change the +string value of a LAMMPS variable that was previous defined with a +:doc:`variable name string ` command without using any +LAMMPS commands to delete and redefine the variable. + +Returns -1 if a variable of that name does not exist or if it is not +a string-style variable, otherwise 0. + +.. warning:: + + This function is deprecated and :cpp:func:`lammps_set_string_variable` + should be used instead. + + \endverbatim + +* \param handle pointer to a previously created LAMMPS instance + * \param name name of the variable + * \param str new value of the variable + * \return 0 on success or -1 on failure */ + +int lammps_set_variable(void *handle, const char *name, const char *str) +{ + if (set_variable_deprecated_flag) { + fprintf(stderr,"Using the 'lammps_set_variable()' function is deprecated. " + "Please use 'lammps_set_string_variable()' instead.\n"); + set_variable_deprecated_flag = 0; + } + return lammps_set_string_variable(handle, name, str); +} + +/* ---------------------------------------------------------------------- */ + +/** Set the value of a string-style variable. +\verbatim embed:rst + +.. versionadded:: TBD + +This function assigns a new value from the string str to the +string-style variable *name*. This is a way to directly change the +string value of a LAMMPS variable that was previous defined with a +:doc:`variable name string ` command without using any +LAMMPS commands to delete and redefine the variable. + +Returns -1 if a variable of that name does not exist or if it is not +a string-style variable, otherwise 0. + +\endverbatim + * \param handle pointer to a previously created LAMMPS instance * \param name name of the variable * \param str new value of the variable * \return 0 on success or -1 on failure */ -int lammps_set_variable(void *handle, char *name, char *str) +int lammps_set_string_variable(void *handle, const char *name, const char *str) { auto lmp = (LAMMPS *) handle; int err = -1; @@ -2477,6 +2527,44 @@ int lammps_set_variable(void *handle, char *name, char *str) return err; } +/* ---------------------------------------------------------------------- */ + +/** Set the value of an internal-style variable. + * +\verbatim embed:rst + +This function assigns a new value from the floating point number *value* +to the internal-style variable *name*. This is a way to directly change +the numerical value of such a LAMMPS variable that was previous defined +with a :doc:`variable name internal ` command without using +any LAMMPS commands to delete and redefine the variable. + +Returns -1 if a variable of that name does not exist or is not an +internal-style variable, otherwise 0. + +\endverbatim + + * \param handle pointer to a previously created LAMMPS instance + * \param name name of the variable + * \param value new value of the variable + * \return 0 on success or -1 on failure + */ +int lammps_set_internal_variable(void *handle, const char *name, double value) +{ + auto lmp = (LAMMPS *) handle; + + BEGIN_CAPTURE + { + int ivar = lmp->input->variable->find(name); + if (ivar < 0) return -1; + if (lmp->input->variable->internalstyle(ivar)) { + lmp->input->variable->internal_set(ivar, value); + return 0; + } + } + END_CAPTURE + return -1; +} /* ---------------------------------------------------------------------- */ diff --git a/src/library.h b/src/library.h index 7db86bd71d0..10cac6741a3 100644 --- a/src/library.h +++ b/src/library.h @@ -177,7 +177,9 @@ void *lammps_extract_compute(void *handle, const char *, int, int); void *lammps_extract_fix(void *handle, const char *, int, int, int, int); void *lammps_extract_variable(void *handle, const char *, const char *); int lammps_extract_variable_datatype(void *handle, const char *name); -int lammps_set_variable(void *handle, char *name, char *str); +int lammps_set_variable(void *handle, const char *name, const char *str); +int lammps_set_string_variable(void *handle, const char *name, const char *str); +int lammps_set_internal_variable(void *handle, const char *name, double value); int lammps_variable_info(void *handle, int idx, char *buf, int bufsize); /* ---------------------------------------------------------------------- diff --git a/tools/swig/lammps.i b/tools/swig/lammps.i index 91a68661076..b0670b40a43 100644 --- a/tools/swig/lammps.i +++ b/tools/swig/lammps.i @@ -129,11 +129,13 @@ extern void *lammps_extract_global(void *handle, const char *name); extern int lammps_extract_atom_datatype(void *handle, const char *name); extern void *lammps_extract_atom(void *handle, const char *name); -extern void *lammps_extract_compute(void *handle, char *id, int, int); -extern void *lammps_extract_fix(void *handle, char *, int, int, int, int); -extern void *lammps_extract_variable(void *handle, char *, char *); +extern void *lammps_extract_compute(void *handle, const char *id, int, int); +extern void *lammps_extract_fix(void *handle, const char *, int, int, int, int); +extern void *lammps_extract_variable(void *handle, const char *, const char *); extern int lammps_extract_variable_datatype(void *handle, const char *name); -extern int lammps_set_variable(void *, char *, char *); +extern int lammps_set_variable(void *, const char *, const char *); +extern int lammps_set_string_variable(void *, const char *, const char *); +extern int lammps_set_internal_variable(void *, const char *, double); extern void lammps_gather_atoms(void *, char *, int, int, void *); extern void lammps_gather_atoms_concat(void *, char *, int, int, void *); @@ -312,11 +314,13 @@ extern void *lammps_extract_global(void *handle, const char *name); extern int lammps_extract_atom_datatype(void *handle, const char *name); extern void *lammps_extract_atom(void *handle, const char *name); -extern void *lammps_extract_compute(void *handle, char *id, int, int); -extern void *lammps_extract_fix(void *handle, char *, int, int, int, int); -extern void *lammps_extract_variable(void *handle, char *, char *); +extern void *lammps_extract_compute(void *handle, const char *id, int, int); +extern void *lammps_extract_fix(void *handle, const char *, int, int, int, int); +extern void *lammps_extract_variable(void *handle, const char *, const char *); extern int lammps_extract_variable_datatype(void *handle, const char *name); -extern int lammps_set_variable(void *, char *, char *); +extern int lammps_set_variable(void *, const char *, const char *); +extern int lammps_set_string_variable(void *, const char *, const char *); +extern int lammps_set_internal_variable(void *, const char *, double); extern void lammps_gather_atoms(void *, char *, int, int, void *); extern void lammps_gather_atoms_concat(void *, char *, int, int, void *); diff --git a/unittest/commands/test_variables.cpp b/unittest/commands/test_variables.cpp index 7a9b87fbe2a..c631b695284 100644 --- a/unittest/commands/test_variables.cpp +++ b/unittest/commands/test_variables.cpp @@ -780,6 +780,25 @@ TEST_F(VariableTest, Format) // TEST_FAILURE(".*ERROR: Incorrect conversion in format string.*", // command("print \"${f1idx}\"");); } + +TEST_F(VariableTest, Set) +{ + BEGIN_HIDE_OUTPUT(); + command("variable three string three"); + command("variable ten internal 10.0"); + END_HIDE_OUTPUT(); + ASSERT_EQ(variable->nvar, 3); + ASSERT_THAT(variable->retrieve("three"), StrEq("three")); + ASSERT_THAT(variable->retrieve("ten"), StrEq("10")); + + ASSERT_EQ(variable->internalstyle(variable->find("three")), 0); + ASSERT_EQ(variable->internalstyle(variable->find("ten")), 1); + + variable->set_string("three", "new"); + ASSERT_THAT(variable->retrieve("three"), StrEq("new")); + variable->internal_set(variable->find("ten"), -2.5); + ASSERT_THAT(variable->retrieve("ten"), StrEq("-2.5")); +} } // namespace LAMMPS_NS int main(int argc, char **argv) diff --git a/unittest/fortran/test_fortran_extract_variable.f90 b/unittest/fortran/test_fortran_extract_variable.f90 index b4b5ab87277..619962daf94 100644 --- a/unittest/fortran/test_fortran_extract_variable.f90 +++ b/unittest/fortran/test_fortran_extract_variable.f90 @@ -361,15 +361,23 @@ FUNCTION f_lammps_extract_variable_vector(i) BIND(C) f_lammps_extract_variable_vector = vector(i) END FUNCTION f_lammps_extract_variable_vector -SUBROUTINE f_lammps_set_variable_string() BIND(C) - USE, INTRINSIC :: ISO_C_BINDING, ONLY : c_double, c_int +SUBROUTINE f_lammps_set_string_variable() BIND(C) USE LIBLAMMPS USE keepstuff, ONLY : lmp, f2c_string IMPLICIT NONE CHARACTER(LEN=40) :: string string = "this is the new string" - CALL lmp%set_variable('str', string) -END SUBROUTINE f_lammps_set_variable_string + CALL lmp%set_string_variable('str', string) +END SUBROUTINE f_lammps_set_string_variable + +SUBROUTINE f_lammps_set_internal_variable() BIND(C) + USE, INTRINSIC :: ISO_C_BINDING, ONLY : c_double + USE LIBLAMMPS + USE keepstuff, ONLY : lmp, f2c_string + IMPLICIT NONE + + CALL lmp%set_internal_variable('int', -2.5_c_double) +END SUBROUTINE f_lammps_set_internal_variable ! vim: sts=2 ts=2 sw=2 et diff --git a/unittest/fortran/wrap_extract_variable.cpp b/unittest/fortran/wrap_extract_variable.cpp index 8c81897c0a1..b1f79e149ad 100644 --- a/unittest/fortran/wrap_extract_variable.cpp +++ b/unittest/fortran/wrap_extract_variable.cpp @@ -43,7 +43,9 @@ double f_lammps_extract_variable_internal(); double f_lammps_extract_variable_equal(); double f_lammps_extract_variable_atom(int); double f_lammps_extract_variable_vector(int); -void f_lammps_set_variable_string(); +void f_lammps_set_string_variable(); +void f_lammps_set_internal_variable(); + char *c_path_join(const char *, const char *); } @@ -155,7 +157,7 @@ TEST_F(LAMMPS_extract_variable, string) char *fstr = f_lammps_extract_variable_string(); EXPECT_STREQ(fstr, "this is a string"); std::free(fstr); - f_lammps_set_variable_string(); + f_lammps_set_string_variable(); fstr = f_lammps_extract_variable_string(); EXPECT_STREQ(fstr, "this is the new string"); std::free(fstr); @@ -254,6 +256,8 @@ TEST_F(LAMMPS_extract_variable, internal) { f_lammps_setup_extract_variable(); EXPECT_DOUBLE_EQ(f_lammps_extract_variable_internal(), 4.0); + f_lammps_set_internal_variable(); + EXPECT_DOUBLE_EQ(f_lammps_extract_variable_internal(), -2.5); }; TEST_F(LAMMPS_extract_variable, equal) diff --git a/unittest/python/python-commands.py b/unittest/python/python-commands.py index 1c257511915..c9f16f6a71c 100644 --- a/unittest/python/python-commands.py +++ b/unittest/python/python-commands.py @@ -475,6 +475,26 @@ def test_extract_variable_equalstyle(self): a = self.lmp.extract_variable("a") self.assertEqual(a, 3.14) + def test_extract_variable_stringstyle(self): + self.lmp.command("variable a string xxx") + a = self.lmp.extract_variable("a") + self.assertEqual(a, 'xxx') + + rv = self.lmp.set_string_variable("a","20") + a = self.lmp.extract_variable("a") + self.assertEqual(a, '20') + self.assertEqual(rv, 0) + + def test_extract_variable_internalstyle(self): + self.lmp.command("variable a internal 2.0") + a = self.lmp.extract_variable("a") + self.assertEqual(a, 2.0) + + rv = self.lmp.set_internal_variable("a",-4.5) + a = self.lmp.extract_variable("a") + self.assertEqual(a, -4.5) + self.assertEqual(rv, 0) + def test_extract_variable_atomstyle(self): self.lmp.command("units lj") self.lmp.command("atom_style atomic")