add support for set_vector for fix external in c-library, python and unittest

This commit is contained in:
Axel Kohlmeyer
2021-07-16 23:41:25 -04:00
parent d462bb3131
commit fa654f2270
7 changed files with 188 additions and 16 deletions

1
.gitignore vendored
View File

@ -44,6 +44,7 @@ Thumbs.db
/build*
/CMakeCache.txt
/CMakeFiles/
/Testing
/Makefile
/cmake_install.cmake
/lmp

View File

@ -8,7 +8,11 @@ functions. They do not directly call the LAMMPS library.
- :cpp:func:`lammps_decode_image_flags`
- :cpp:func:`lammps_set_fix_external_callback`
- :cpp:func:`lammps_fix_external_set_energy_global`
- :cpp:func:`lammps_fix_external_set_energy_peratom`
- :cpp:func:`lammps_fix_external_set_virial_global`
- :cpp:func:`lammps_fix_external_set_virial_peratom`
- :cpp:func:`lammps_fix_external_set_vector_length`
- :cpp:func:`lammps_fix_external_set_vector`
- :cpp:func:`lammps_free`
- :cpp:func:`lammps_is_running`
- :cpp:func:`lammps_force_timeout`
@ -43,11 +47,31 @@ where such memory buffers were allocated that require the use of
-----------------------
.. doxygenfunction:: lammps_fix_external_set_energy_peratom
:project: progguide
-----------------------
.. doxygenfunction:: lammps_fix_external_set_virial_global
:project: progguide
-----------------------
.. doxygenfunction:: lammps_fix_external_set_virial_peratom
:project: progguide
-----------------------
.. doxygenfunction:: lammps_fix_external_set_vector_length
:project: progguide
-----------------------
.. doxygenfunction:: lammps_fix_external_set_vector
:project: progguide
-----------------------
.. doxygenfunction:: lammps_free
:project: progguide

View File

@ -303,6 +303,9 @@ class lammps(object):
self.lib.lammps_fix_external_set_energy_peratom.argtypes = [c_void_p, c_char_p, POINTER(c_double)]
self.lib.lammps_fix_external_set_virial_peratom.argtypes = [c_void_p, c_char_p, POINTER(POINTER(c_double))]
self.lib.lammps_fix_external_set_vector_length.argtypes = [c_void_p, c_char_p, c_int]
self.lib.lammps_fix_external_set_vector.argtypes = [c_void_p, c_char_p, c_int, c_double]
# detect if Python is using a version of mpi4py that can pass communicators
# only needed if LAMMPS has been compiled with MPI support.
self.has_mpi4py = False
@ -1806,6 +1809,40 @@ class lammps(object):
with ExceptionCheck(self):
return self.lib.lammps_fix_external_set_energy_global(self.lmp, fix_id.encode(), eng)
# -------------------------------------------------------------------------
def fix_external_set_vector_length(self, fix_id, length):
"""Set the vector length for a global vector stored with fix external for analysis
This is a wrapper around the :cpp:func:`lammps_fix_external_set_vector_length` function
of the C-library interface.
:param fix_id: Fix-ID of a fix external instance
:type: string
:param length: length of the global vector
:type: int
"""
with ExceptionCheck(self):
return self.lib.lammps_fix_external_set_vector_length(self.lmp, fix_id.encode(), length)
# -------------------------------------------------------------------------
def fix_external_set_vector(self, fix_id, idx, val):
"""Store a global vector value for a fix external instance with the given ID.
This is a wrapper around the :cpp:func:`lammps_fix_external_set_vector` function
of the C-library interface.
:param fix_id: Fix-ID of a fix external instance
:type: string
:param idx: 1-based index of the value in the global vector
:type: int
:param val: value to be stored in the global vector
:type: float
"""
with ExceptionCheck(self):
return self.lib.lammps_fix_external_set_vector(self.lmp, fix_id.encode(), idx, val)
# -------------------------------------------------------------------------
def get_neighlist(self, idx):

View File

@ -4821,7 +4821,7 @@ mode. The function has to have C language bindings with the prototype:
void func(void *ptr, bigint timestep, int nlocal, tagint *ids, double **x, double **fexternal);
This is an alternative to the array mechanism set up by :cpp:func:`lammps_fix_external_set_force`.
This is an alternative to the array mechanism set up by :cpp:func:`lammps_fix_external_get_force`.
Please see the documentation for :doc:`fix external <fix_external>` for
more information about how to use the fix and how to couple it with an
@ -4913,7 +4913,7 @@ double **lammps_fix_external_get_force(void *handle, const char *id)
\verbatim embed:rst
This is a companion function to :cpp:func:`lammps_set_fix_external_callback` and
:cpp:func:`lammps_fix_external_set_force` to also set the contribution
:cpp:func:`lammps_fix_external_get_force` to also set the contribution
to the global energy from the external code.
Please see the documentation for :doc:`fix external <fix_external>` for
@ -4952,7 +4952,7 @@ void lammps_fix_external_set_energy_global(void *handle, const char *id, double
\verbatim embed:rst
This is a companion function to :cpp:func:`lammps_set_fix_external_callback` and
:cpp:func:`lammps_fix_external_set_force` to also set the contribution
:cpp:func:`lammps_fix_external_get_force` to also set the contribution
to the global virial from the external code.
Please see the documentation for :doc:`fix external <fix_external>` for
@ -4991,7 +4991,7 @@ void lammps_fix_external_set_virial_global(void *handle, const char *id, double
\verbatim embed:rst
This is a companion function to :cpp:func:`lammps_set_fix_external_callback` and
:cpp:func:`lammps_fix_external_set_force` to also set the contribution
:cpp:func:`lammps_fix_external_get_force` to also set the contribution
to the per-atom energy from the external code.
Please see the documentation for :doc:`fix external <fix_external>` for
@ -5030,7 +5030,7 @@ void lammps_fix_external_set_energy_peratom(void *handle, const char *id, double
\verbatim embed:rst
This is a companion function to :cpp:func:`lammps_set_fix_external_callback` and
:cpp:func:`lammps_fix_external_set_force` to also set the contribution
:cpp:func:`lammps_fix_external_get_force` to also set the contribution
to the per-atom virial from the external code.
Please see the documentation for :doc:`fix external <fix_external>` for
@ -5064,6 +5064,86 @@ void lammps_fix_external_set_virial_peratom(void *handle, const char *id, double
END_CAPTURE
}
/** Set the vector length for a global vector stored with fix external for analysis
\verbatim embed:rst
This is a companion function to :cpp:func:`lammps_set_fix_external_callback` and
:cpp:func:`lammps_fix_external_get_force` to set the length of a global vector of
properties that will be stored with the fix via :cpp:func:`lammps_fix_external_set_vector`.
Please see the documentation for :doc:`fix external <fix_external>` for
more information about how to use the fix and how to couple it with an
external code.
\endverbatim
*
* \param handle pointer to a previously created LAMMPS instance cast to ``void *``.
* \param id fix ID of fix external instance
* \param len length of the global vector to be stored with the fix */
void lammps_fix_external_set_vector_length(void *handle, const char *id, int len)
{
LAMMPS *lmp = (LAMMPS *) handle;
BEGIN_CAPTURE
{
int ifix = lmp->modify->find_fix(id);
if (ifix < 0)
lmp->error->all(FLERR,"Can not find fix with ID '{}'!", id);
Fix *fix = lmp->modify->fix[ifix];
if (strcmp("external",fix->style) != 0)
lmp->error->all(FLERR,"Fix '{}' is not of style external!", id);
FixExternal *fext = (FixExternal*) fix;
fext->set_vector_length(len);
}
END_CAPTURE
}
/** Store global vector for a fix external instance with the given ID.
\verbatim embed:rst
This is a companion function to :cpp:func:`lammps_set_fix_external_callback` and
:cpp:func:`lammps_fix_external_get_force` to set the values of a global vector of
properties that will be stored with the fix. The length of the vector
must be set beforehand with :cpp:func:`lammps_fix_external_set_vector_length`.
Please see the documentation for :doc:`fix external <fix_external>` for
more information about how to use the fix and how to couple it with an
external code.
\endverbatim
*
* \param handle pointer to a previously created LAMMPS instance cast to ``void *``.
* \param id fix ID of fix external instance
* \param idx 1 based index of in global vector
* \param val value to be stored in global vector */
void lammps_fix_external_set_vector(void *handle, const char *id, int idx, double val)
{
LAMMPS *lmp = (LAMMPS *) handle;
BEGIN_CAPTURE
{
int ifix = lmp->modify->find_fix(id);
if (ifix < 0)
lmp->error->all(FLERR,"Can not find fix with ID '{}'!", id);
Fix *fix = lmp->modify->fix[ifix];
if (strcmp("external",fix->style) != 0)
lmp->error->all(FLERR,"Fix '{}' is not of style external!", id);
FixExternal * fext = (FixExternal*) fix;
fext->set_vector(idx, val);
}
END_CAPTURE
}
/* ---------------------------------------------------------------------- */
/** Free memory buffer allocated by LAMMPS.

View File

@ -240,7 +240,7 @@ void lammps_fix_external_set_energy_peratom(void *handle, const char *id, double
void lammps_fix_external_set_virial_global(void *handle, const char *id, double *virial);
void lammps_fix_external_set_virial_peratom(void *handle, const char *id, double **virial);
void lammps_fix_external_set_vector_length(void *handle, const char *id, int len);
void lammps_fix_external_set_virial_peratom(void *handle, const char *id, double **val);
void lammps_fix_external_set_vector(void *handle, const char *id, int idx, double val);
void lammps_free(void *ptr);

View File

@ -28,12 +28,20 @@ static void callback_one(void *handle, step_t timestep, int nlocal, tag_t *, dou
{
for (int i = 0; i < nlocal; ++i)
f[i][0] = f[i][1] = f[i][2] = (double)timestep;
if (timestep < 10)
lammps_fix_external_set_energy_global(handle, "ext", 0.0);
else
lammps_fix_external_set_energy_global(handle, "ext", 1.0);
double v[6] = {1.0, 1.0, 1.0, 0.0, 0.0, 0.0};
lammps_fix_external_set_virial_global(handle, "ext", v);
if (timestep < 10) {
lammps_fix_external_set_energy_global(handle, "ext", 0.5);
lammps_fix_external_set_vector(handle, "ext", 1, timestep);
lammps_fix_external_set_vector(handle, "ext", 3, 1.0);
lammps_fix_external_set_vector(handle, "ext", 4, -0.25);
} else {
lammps_fix_external_set_energy_global(handle, "ext", 1.0);
lammps_fix_external_set_vector(handle, "ext", 2, timestep);
lammps_fix_external_set_vector(handle, "ext", 5, -1.0);
lammps_fix_external_set_vector(handle, "ext", 6, 0.25);
}
}
}
@ -57,11 +65,12 @@ TEST(lammps_external, callback)
"pair_style zero 0.1\n"
"pair_coeff 1 1\n"
"velocity all set 0.1 0.0 -0.1\n"
"thermo 5\n"
"fix 1 all nve\n"
"fix ext all external pf/callback 5 1\n"
"thermo_style custom step temp pe ke etotal press\n"
"thermo 5\n"
"fix_modify ext energy yes virial yes\n");
lammps_fix_external_set_vector_length(handle, "ext", 6);
output = ::testing::internal::GetCapturedStdout();
if (verbose) std::cout << output;
@ -71,11 +80,19 @@ TEST(lammps_external, callback)
double temp = lammps_get_thermo(handle, "temp");
double pe = lammps_get_thermo(handle, "pe");
double press = lammps_get_thermo(handle, "press");
double val = 0.0;
double *valp;
for (int i = 0; i < 6; ++i) {
valp = (double *)lammps_extract_fix(handle, "ext", LMP_STYLE_GLOBAL, LMP_TYPE_VECTOR, i, 0);
val += *valp;
lammps_free(valp);
}
output = ::testing::internal::GetCapturedStdout();
if (verbose) std::cout << output;
EXPECT_DOUBLE_EQ(temp, 1.0 / 30.0);
EXPECT_DOUBLE_EQ(pe, 1.0 / 8.0);
EXPECT_DOUBLE_EQ(press, 0.15416666666666667);
EXPECT_DOUBLE_EQ(val, 15);
::testing::internal::CaptureStdout();
lammps_close(handle);

View File

@ -1,6 +1,6 @@
import sys,os,unittest
from ctypes import *
from lammps import lammps
from lammps import lammps, LMP_STYLE_GLOBAL, LMP_TYPE_VECTOR
# add timestep dependent force
def callback_one(lmp, ntimestep, nlocal, tag, x, f):
@ -9,9 +9,15 @@ def callback_one(lmp, ntimestep, nlocal, tag, x, f):
f[i][1] = float(ntimestep)
f[i][2] = float(ntimestep)
if ntimestep < 10:
lmp.fix_external_set_energy_global("ext",0.5)
lmp.fix_external_set_energy_global("ext", 0.5)
lmp.fix_external_set_vector("ext", 1, ntimestep)
lmp.fix_external_set_vector("ext", 3, 1.0)
lmp.fix_external_set_vector("ext", 4, -0.25)
else:
lmp.fix_external_set_energy_global("ext",1.0)
lmp.fix_external_set_energy_global("ext", 1.0)
lmp.fix_external_set_vector("ext", 2, ntimestep)
lmp.fix_external_set_vector("ext", 5, -1.0)
lmp.fix_external_set_vector("ext", 6, 0.25)
class PythonExternal(unittest.TestCase):
def testExternalCallback(self):
@ -31,15 +37,22 @@ class PythonExternal(unittest.TestCase):
pair_style zero 0.1
pair_coeff 1 1
velocity all set 0.1 0.0 -0.1
thermo_style custom step temp pe ke etotal press
thermo 5
fix 1 all nve
fix ext all external pf/callback 5 1
fix_modify ext energy yes virial yes
"""
lmp.commands_string(basic_system)
lmp.fix_external_set_vector_length("ext",6);
lmp.set_fix_external_callback("ext",callback_one,lmp)
lmp.command("run 10 post no")
self.assertAlmostEqual(lmp.get_thermo("temp"),1.0/30.0,14)
self.assertAlmostEqual(lmp.get_thermo("pe"),1.0/8.0,14)
val = 0.0
for i in range(0,6):
val += lmp.extract_fix("ext",LMP_STYLE_GLOBAL,LMP_TYPE_VECTOR,nrow=i)
self.assertAlmostEqual(val,15.0,14)
def testExternalArray(self):
"""Test fix external from Python with pf/array"""