From dce1231052f7329a4fa211d51d5ca655266dbd9c Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sun, 12 Jan 2025 00:39:18 -0500 Subject: [PATCH] add a lammps_eval() function to the C library interface and all derived wrappers --- doc/src/Fortran.rst | 2 ++ doc/src/Library_objects.rst | 6 +++++ examples/COUPLE/plugin/liblammpsplugin.c | 1 + examples/COUPLE/plugin/liblammpsplugin.h | 1 + fortran/lammps.f90 | 24 +++++++++++++++++-- python/lammps/core.py | 27 +++++++++++++++++++++ src/library.cpp | 30 ++++++++++++++++++++++++ src/library.h | 1 + tools/swig/lammps.i | 4 ++++ 9 files changed, 94 insertions(+), 2 deletions(-) diff --git a/doc/src/Fortran.rst b/doc/src/Fortran.rst index d50c7bdcf3..bc641a237f 100644 --- a/doc/src/Fortran.rst +++ b/doc/src/Fortran.rst @@ -321,6 +321,8 @@ of the contents of the :f:mod:`LIBLAMMPS` Fortran interface to LAMMPS. :ftype set_string_variable: subroutine :f set_internal_variable: :f:subr:`set_internal_variable` :ftype set_internal_variable: subroutine + :f eval: :f:func:`eval` + :ftype eval: function :f gather_atoms: :f:subr:`gather_atoms` :ftype gather_atoms: subroutine :f gather_atoms_concat: :f:subr:`gather_atoms_concat` diff --git a/doc/src/Library_objects.rst b/doc/src/Library_objects.rst index 7c0ca824d7..89056a5db0 100644 --- a/doc/src/Library_objects.rst +++ b/doc/src/Library_objects.rst @@ -12,6 +12,7 @@ fixes, or variables in LAMMPS using the following functions: - :cpp:func:`lammps_set_string_variable` - :cpp:func:`lammps_set_internal_variable` - :cpp:func:`lammps_variable_info` +- :cpp:func:`lammps_eval` ----------------------- @@ -55,6 +56,11 @@ fixes, or variables in LAMMPS using the following functions: ----------------------- +.. doxygenfunction:: lammps_eval + :project: progguide + +----------------------- + .. doxygenenum:: _LMP_DATATYPE_CONST .. doxygenenum:: _LMP_STYLE_CONST diff --git a/examples/COUPLE/plugin/liblammpsplugin.c b/examples/COUPLE/plugin/liblammpsplugin.c index 5b1308a5cc..99e38df32b 100644 --- a/examples/COUPLE/plugin/liblammpsplugin.c +++ b/examples/COUPLE/plugin/liblammpsplugin.c @@ -117,6 +117,7 @@ liblammpsplugin_t *liblammpsplugin_load(const char *lib) ADDSYM(set_string_variable); ADDSYM(set_internal_variable); ADDSYM(variable_info); + ADDSYM(eval); ADDSYM(gather_atoms); ADDSYM(gather_atoms_concat); diff --git a/examples/COUPLE/plugin/liblammpsplugin.h b/examples/COUPLE/plugin/liblammpsplugin.h index b2df98d630..dd1c9628f5 100644 --- a/examples/COUPLE/plugin/liblammpsplugin.h +++ b/examples/COUPLE/plugin/liblammpsplugin.h @@ -163,6 +163,7 @@ struct _liblammpsplugin { int (*set_string_variable)(void *, const char *, const char *); int (*set_internal_variable)(void *, const char *, double); int (*variable_info)(void *, int, char *, int); + double (*eval)(void *, const char *); void (*gather_atoms)(void *, const char *, int, int, void *); void (*gather_atoms_concat)(void *, const char *, int, int, void *); diff --git a/fortran/lammps.f90 b/fortran/lammps.f90 index 1cc6992c27..552b3dfad3 100644 --- a/fortran/lammps.f90 +++ b/fortran/lammps.f90 @@ -126,6 +126,7 @@ MODULE LIBLAMMPS PROCEDURE :: set_variable => lmp_set_variable PROCEDURE :: set_string_variable => lmp_set_string_variable PROCEDURE :: set_internal_variable => lmp_set_internal_variable + PROCEDURE :: eval => lmp_eval PROCEDURE, PRIVATE :: lmp_gather_atoms_int PROCEDURE, PRIVATE :: lmp_gather_atoms_double GENERIC :: gather_atoms => lmp_gather_atoms_int, & @@ -618,7 +619,14 @@ MODULE LIBLAMMPS INTEGER(c_int) :: lammps_set_internal_variable END FUNCTION lammps_set_internal_variable - SUBROUTINE lammps_gather_atoms(handle, name, type, count, data) BIND(C) + FUNCTION lammps_eval(handle, expr) BIND(C) + IMPORT :: c_ptr, c_double + IMPLICIT NONE + TYPE(c_ptr), VALUE :: handle, expr + REAL(c_double) :: lammps_eval + END FUNCTION lammps_eval + + SUBROUTINE lammps_gather_atoms(handle, name, TYPE, count, DATA) BIND(C) IMPORT :: c_int, c_ptr IMPLICIT NONE TYPE(c_ptr), VALUE :: handle, name, data @@ -1812,7 +1820,7 @@ CONTAINS 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 + REAL(c_double), INTENT(IN) :: val INTEGER :: err TYPE(c_ptr) :: Cname @@ -1826,6 +1834,18 @@ CONTAINS END IF END SUBROUTINE lmp_set_internal_variable + ! equivalent function to lammps_eval + FUNCTION lmp_eval(self, expr) + CLASS(lammps), INTENT(IN) :: self + CHARACTER(LEN=*), INTENT(IN) :: expr + REAL(c_double) :: lmp_eval + TYPE(c_ptr) :: Cexpr + + Cexpr = f2c_string(expr) + lmp_eval = lammps_eval(self%handle, Cexpr) + CALL lammps_free(Cexpr) + END FUNCTION lmp_eval + ! 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 30df44f050..d6fb63b815 100644 --- a/python/lammps/core.py +++ b/python/lammps/core.py @@ -339,6 +339,9 @@ class lammps(object): self.lib.lammps_extract_variable_datatype.argtypes = [c_void_p, c_char_p] self.lib.lammps_extract_variable_datatype.restype = c_int + self.lib.lammps_eval.argtypes = [c_void_p, c_char_p] + self.lib.lammps_eval.restype = c_double + self.lib.lammps_fix_external_get_force.argtypes = [c_void_p, c_char_p] self.lib.lammps_fix_external_get_force.restype = POINTER(POINTER(c_double)) @@ -1533,6 +1536,30 @@ class lammps(object): # ------------------------------------------------------------------------- + def eval(self, expr): + """ Evaluate a LAMMPS immediate variable expression + + .. versionadded:: TBD + + This function is a wrapper around the function :cpp:func:`lammps_eval` + of the C library interface. It evaluates and expression like in + immediate variables and returns the value. + + :param expr: immediate variable expression + :type name: string + :return: the result of the evaluation + :rtype: c_double + """ + + if expr: newexpr = expr.encode() + else: return None + + with ExceptionCheck(self): + return self.lib.lammps_eval(self.lmp, newexpr) + return None + + # ------------------------------------------------------------------------- + # 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 cee1304db6..cb5c62aa87 100644 --- a/src/library.cpp +++ b/src/library.cpp @@ -2904,6 +2904,36 @@ int lammps_variable_info(void *handle, int idx, char *buffer, int buf_size) { return 0; } +/** Evaluate an immediate variable expression + * +\verbatim embed:rst + +.. versionadded:: TBD + +This function takes a string with an expression, like what can be used +for :doc:`equal style variables `, evaluates it and returns +the resulting (scalar) value as a floating point number. + +\endverbatim + + * \param handle pointer to a previously created LAMMPS instance cast to ``void *``. + * \param expr string with expression + * \return result from expression */ + +double lammps_eval(void *handle, const char *expr) +{ + auto lmp = (LAMMPS *) handle; + double result = 0.0; + + BEGIN_CAPTURE + { + result = lmp->input->variable->compute_equal(expr); + } + END_CAPTURE + + return result; +} + // ---------------------------------------------------------------------- // Library functions for scatter/gather operations of data // ---------------------------------------------------------------------- diff --git a/src/library.h b/src/library.h index 36e67470ae..f64ae9e7c2 100644 --- a/src/library.h +++ b/src/library.h @@ -189,6 +189,7 @@ 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); +double lammps_eval(void *handle, const char *expr); /* ---------------------------------------------------------------------- * Library functions for scatter/gather operations of data diff --git a/tools/swig/lammps.i b/tools/swig/lammps.i index 119edc4367..bc9f46f407 100644 --- a/tools/swig/lammps.i +++ b/tools/swig/lammps.i @@ -141,6 +141,8 @@ extern int lammps_extract_variable_datatype(void *handle, const char *name); 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 int lammps_variable_info(void *handle, int idx, char *buf, int bufsize); +extern double lammps_eval(void *handle, const char *expr); extern void lammps_gather_atoms(void *, char *, int, int, void *); extern void lammps_gather_atoms_concat(void *, char *, int, int, void *); @@ -332,6 +334,8 @@ extern int lammps_extract_variable_datatype(void *handle, const char *name); 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 int lammps_variable_info(void *handle, int idx, char *buf, int bufsize); +extern double lammps_eval(void *handle, const char *expr); extern void lammps_gather_atoms(void *, char *, int, int, void *); extern void lammps_gather_atoms_concat(void *, char *, int, int, void *);