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* /build*
/CMakeCache.txt /CMakeCache.txt
/CMakeFiles/ /CMakeFiles/
/Testing
/Makefile /Makefile
/cmake_install.cmake /cmake_install.cmake
/lmp /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_decode_image_flags`
- :cpp:func:`lammps_set_fix_external_callback` - :cpp:func:`lammps_set_fix_external_callback`
- :cpp:func:`lammps_fix_external_set_energy_global` - :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_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_free`
- :cpp:func:`lammps_is_running` - :cpp:func:`lammps_is_running`
- :cpp:func:`lammps_force_timeout` - :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 .. doxygenfunction:: lammps_fix_external_set_virial_global
:project: progguide :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 .. doxygenfunction:: lammps_free
:project: progguide :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_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_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 # detect if Python is using a version of mpi4py that can pass communicators
# only needed if LAMMPS has been compiled with MPI support. # only needed if LAMMPS has been compiled with MPI support.
self.has_mpi4py = False self.has_mpi4py = False
@ -1806,6 +1809,40 @@ class lammps(object):
with ExceptionCheck(self): with ExceptionCheck(self):
return self.lib.lammps_fix_external_set_energy_global(self.lmp, fix_id.encode(), eng) 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): 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); 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 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 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 \verbatim embed:rst
This is a companion function to :cpp:func:`lammps_set_fix_external_callback` and 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. to the global energy from the external code.
Please see the documentation for :doc:`fix external <fix_external>` for 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 \verbatim embed:rst
This is a companion function to :cpp:func:`lammps_set_fix_external_callback` and 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. to the global virial from the external code.
Please see the documentation for :doc:`fix external <fix_external>` for 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 \verbatim embed:rst
This is a companion function to :cpp:func:`lammps_set_fix_external_callback` and 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. to the per-atom energy from the external code.
Please see the documentation for :doc:`fix external <fix_external>` for 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 \verbatim embed:rst
This is a companion function to :cpp:func:`lammps_set_fix_external_callback` and 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. to the per-atom virial from the external code.
Please see the documentation for :doc:`fix external <fix_external>` for 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 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. /** 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_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_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_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); 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) for (int i = 0; i < nlocal; ++i)
f[i][0] = f[i][1] = f[i][2] = (double)timestep; 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}; double v[6] = {1.0, 1.0, 1.0, 0.0, 0.0, 0.0};
lammps_fix_external_set_virial_global(handle, "ext", v); 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_style zero 0.1\n"
"pair_coeff 1 1\n" "pair_coeff 1 1\n"
"velocity all set 0.1 0.0 -0.1\n" "velocity all set 0.1 0.0 -0.1\n"
"thermo 5\n"
"fix 1 all nve\n" "fix 1 all nve\n"
"fix ext all external pf/callback 5 1\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"); "fix_modify ext energy yes virial yes\n");
lammps_fix_external_set_vector_length(handle, "ext", 6);
output = ::testing::internal::GetCapturedStdout(); output = ::testing::internal::GetCapturedStdout();
if (verbose) std::cout << output; if (verbose) std::cout << output;
@ -71,11 +80,19 @@ TEST(lammps_external, callback)
double temp = lammps_get_thermo(handle, "temp"); double temp = lammps_get_thermo(handle, "temp");
double pe = lammps_get_thermo(handle, "pe"); double pe = lammps_get_thermo(handle, "pe");
double press = lammps_get_thermo(handle, "press"); double press = lammps_get_thermo(handle, "press");
output = ::testing::internal::GetCapturedStdout(); 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; if (verbose) std::cout << output;
EXPECT_DOUBLE_EQ(temp, 1.0 / 30.0); EXPECT_DOUBLE_EQ(temp, 1.0 / 30.0);
EXPECT_DOUBLE_EQ(pe, 1.0 / 8.0); EXPECT_DOUBLE_EQ(pe, 1.0 / 8.0);
EXPECT_DOUBLE_EQ(press, 0.15416666666666667); EXPECT_DOUBLE_EQ(press, 0.15416666666666667);
EXPECT_DOUBLE_EQ(val, 15);
::testing::internal::CaptureStdout(); ::testing::internal::CaptureStdout();
lammps_close(handle); lammps_close(handle);

View File

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