document and add unit tests for lammps_set_fix_external_callback()
This commit is contained in:
@ -4804,15 +4804,38 @@ void lammps_decode_image_flags(imageint image, int *flags)
|
|||||||
flags[2] = (image >> IMG2BITS) - IMGMAX;
|
flags[2] = (image >> IMG2BITS) - IMGMAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------
|
/* ---------------------------------------------------------------------- */
|
||||||
find fix external with given ID and set the callback function
|
|
||||||
and caller pointer
|
|
||||||
------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
void lammps_set_fix_external_callback(void *handle, char *id, FixExternalFnPtr callback_ptr, void * caller)
|
/** Set the callback function for a fix external instance with given ID.
|
||||||
|
Optionally also set the pointer to the calling object.
|
||||||
|
\verbatim embed:rst
|
||||||
|
|
||||||
|
Fix :doc:`external <fix_external>` allows programs that are running LAMMPS through
|
||||||
|
its library interface to modify certain LAMMPS properties on specific
|
||||||
|
timesteps, similar to the way other fixes do.
|
||||||
|
|
||||||
|
This function sets the callback function which has to have C language
|
||||||
|
bindings with the prototype:
|
||||||
|
|
||||||
|
.. code-block:: c
|
||||||
|
|
||||||
|
void func(void *ptr, bigint timestep, int nlocal, tagint *ids, double **x, double **fexternal);
|
||||||
|
|
||||||
|
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 funcptr pointer to callback function
|
||||||
|
* \param ptr pointer to object in calling code, passed to callback function as first argument */
|
||||||
|
|
||||||
|
void lammps_set_fix_external_callback(void *handle, char *id, FixExternalFnPtr funcptr, void *ptr)
|
||||||
{
|
{
|
||||||
LAMMPS *lmp = (LAMMPS *) handle;
|
LAMMPS *lmp = (LAMMPS *) handle;
|
||||||
FixExternal::FnPtr callback = (FixExternal::FnPtr) callback_ptr;
|
FixExternal::FnPtr callback = (FixExternal::FnPtr) funcptr;
|
||||||
|
|
||||||
BEGIN_CAPTURE
|
BEGIN_CAPTURE
|
||||||
{
|
{
|
||||||
@ -4823,18 +4846,16 @@ void lammps_set_fix_external_callback(void *handle, char *id, FixExternalFnPtr c
|
|||||||
Fix *fix = lmp->modify->fix[ifix];
|
Fix *fix = lmp->modify->fix[ifix];
|
||||||
|
|
||||||
if (strcmp("external",fix->style) != 0)
|
if (strcmp("external",fix->style) != 0)
|
||||||
lmp->error->all(FLERR,"Fix '{}' is not of style "
|
lmp->error->all(FLERR,"Fix '{}' is not of style 'external'", id);
|
||||||
"external!", id);
|
|
||||||
|
|
||||||
FixExternal * fext = (FixExternal*) fix;
|
FixExternal *fext = (FixExternal *) fix;
|
||||||
fext->set_callback(callback, caller);
|
fext->set_callback(callback, ptr);
|
||||||
}
|
}
|
||||||
END_CAPTURE
|
END_CAPTURE
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set global energy contribution from fix external */
|
/* set global energy contribution from fix external */
|
||||||
void lammps_fix_external_set_energy_global(void *handle, char *id,
|
void lammps_fix_external_set_energy_global(void *handle, char *id, double energy)
|
||||||
double energy)
|
|
||||||
{
|
{
|
||||||
LAMMPS *lmp = (LAMMPS *) handle;
|
LAMMPS *lmp = (LAMMPS *) handle;
|
||||||
|
|
||||||
@ -4849,7 +4870,7 @@ void lammps_fix_external_set_energy_global(void *handle, char *id,
|
|||||||
if (strcmp("external",fix->style) != 0)
|
if (strcmp("external",fix->style) != 0)
|
||||||
lmp->error->all(FLERR,"Fix '{}' is not of style external!", id);
|
lmp->error->all(FLERR,"Fix '{}' is not of style external!", id);
|
||||||
|
|
||||||
FixExternal * fext = (FixExternal*) fix;
|
FixExternal *fext = (FixExternal*) fix;
|
||||||
fext->set_energy_global(energy);
|
fext->set_energy_global(energy);
|
||||||
}
|
}
|
||||||
END_CAPTURE
|
END_CAPTURE
|
||||||
|
|||||||
@ -226,7 +226,7 @@ void lammps_decode_image_flags(int64_t image, int *flags);
|
|||||||
|
|
||||||
#if defined(LAMMPS_BIGBIG)
|
#if defined(LAMMPS_BIGBIG)
|
||||||
typedef void (*FixExternalFnPtr)(void *, int64_t, int, int64_t *, double **, double **);
|
typedef void (*FixExternalFnPtr)(void *, int64_t, int, int64_t *, double **, double **);
|
||||||
void lammps_set_fix_external_callback(void *, char *, FixExternalFnPtr, void *);
|
void lammps_set_fix_external_callback(void *handle, char *id, FixExternalFnPtr funcptr, void *ptr);
|
||||||
#elif defined(LAMMPS_SMALLBIG)
|
#elif defined(LAMMPS_SMALLBIG)
|
||||||
typedef void (*FixExternalFnPtr)(void *, int64_t, int, int *, double **, double **);
|
typedef void (*FixExternalFnPtr)(void *, int64_t, int, int *, double **, double **);
|
||||||
void lammps_set_fix_external_callback(void *, char *, FixExternalFnPtr, void *);
|
void lammps_set_fix_external_callback(void *, char *, FixExternalFnPtr, void *);
|
||||||
|
|||||||
@ -7,6 +7,10 @@ add_executable(test_library_commands test_library_commands.cpp test_main.cpp)
|
|||||||
target_link_libraries(test_library_commands PRIVATE lammps GTest::GTest GTest::GMock)
|
target_link_libraries(test_library_commands PRIVATE lammps GTest::GTest GTest::GMock)
|
||||||
add_test(LibraryCommands test_library_commands)
|
add_test(LibraryCommands test_library_commands)
|
||||||
|
|
||||||
|
add_executable(test_library_external test_library_external.cpp test_main.cpp)
|
||||||
|
target_link_libraries(test_library_external PRIVATE lammps GTest::GTest GTest::GMock)
|
||||||
|
add_test(LibraryExternal test_library_external)
|
||||||
|
|
||||||
add_executable(test_library_properties test_library_properties.cpp test_main.cpp)
|
add_executable(test_library_properties test_library_properties.cpp test_main.cpp)
|
||||||
target_link_libraries(test_library_properties PRIVATE lammps GTest::GTest GTest::GMock)
|
target_link_libraries(test_library_properties PRIVATE lammps GTest::GTest GTest::GMock)
|
||||||
target_compile_definitions(test_library_properties PRIVATE -DTEST_INPUT_FOLDER=${CMAKE_CURRENT_SOURCE_DIR})
|
target_compile_definitions(test_library_properties PRIVATE -DTEST_INPUT_FOLDER=${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
|||||||
73
unittest/c-library/test_library_external.cpp
Normal file
73
unittest/c-library/test_library_external.cpp
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
// unit tests creating LAMMPS instances via the library interface
|
||||||
|
|
||||||
|
#include "library.h"
|
||||||
|
|
||||||
|
#include <cinttypes>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "gmock/gmock.h"
|
||||||
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
|
#include "test_main.h"
|
||||||
|
|
||||||
|
using ::testing::HasSubstr;
|
||||||
|
using ::testing::StartsWith;
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#ifdef LAMMPS_SMALLSMALL
|
||||||
|
typedef int32_t step_t;
|
||||||
|
typedef int32_t tag_t;
|
||||||
|
#elif LAMMPS_SMALLBIG
|
||||||
|
typedef int64_t step_t;
|
||||||
|
typedef int32_t tag_t;
|
||||||
|
#else
|
||||||
|
typedef int64_t step_t;
|
||||||
|
typedef int64_t tag_t;
|
||||||
|
#endif
|
||||||
|
static void callback_one(void *lmp, step_t timestep, int nlocal, tag_t *ids, double **x, double **f)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < nlocal; ++i)
|
||||||
|
f[i][0] = f[i][1] = f[i][2] = (double)timestep;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(lammps_external_pf, null_args)
|
||||||
|
{
|
||||||
|
const char *args[] = {"liblammps", "-log", "none", "-nocite"};
|
||||||
|
char **argv = (char **)args;
|
||||||
|
int argc = sizeof(args) / sizeof(char *);
|
||||||
|
|
||||||
|
::testing::internal::CaptureStdout();
|
||||||
|
void *handle = lammps_open_no_mpi(argc, argv, NULL);
|
||||||
|
std::string output = ::testing::internal::GetCapturedStdout();
|
||||||
|
if (verbose) std::cout << output;
|
||||||
|
|
||||||
|
::testing::internal::CaptureStdout();
|
||||||
|
lammps_commands_string(handle, "lattice sc 1.0\n"
|
||||||
|
"region box block -1 1 -1 1 -1 1\n"
|
||||||
|
"create_box 1 box\n"
|
||||||
|
"create_atoms 1 box\n"
|
||||||
|
"mass 1 1.0\n"
|
||||||
|
"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");
|
||||||
|
|
||||||
|
output = ::testing::internal::GetCapturedStdout();
|
||||||
|
if (verbose) std::cout << output;
|
||||||
|
|
||||||
|
::testing::internal::CaptureStdout();
|
||||||
|
lammps_set_fix_external_callback(handle, (char *)"ext", &callback_one, handle);
|
||||||
|
lammps_command(handle, "run 10 post no");
|
||||||
|
double temp = lammps_get_thermo(handle,"temp");
|
||||||
|
output = ::testing::internal::GetCapturedStdout();
|
||||||
|
if (verbose) std::cout << output;
|
||||||
|
EXPECT_DOUBLE_EQ(temp,1.0/30.0);
|
||||||
|
|
||||||
|
::testing::internal::CaptureStdout();
|
||||||
|
lammps_close(handle);
|
||||||
|
output = ::testing::internal::GetCapturedStdout();
|
||||||
|
if (verbose) std::cout << output;
|
||||||
|
}
|
||||||
@ -85,6 +85,11 @@ if(Python_EXECUTABLE)
|
|||||||
COMMAND ${PYTHON_TEST_RUNNER} ${CMAKE_CURRENT_SOURCE_DIR}/python-formats.py -v
|
COMMAND ${PYTHON_TEST_RUNNER} ${CMAKE_CURRENT_SOURCE_DIR}/python-formats.py -v
|
||||||
WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH})
|
WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH})
|
||||||
set_tests_properties(PythonFormats PROPERTIES ENVIRONMENT "${PYTHON_TEST_ENVIRONMENT}")
|
set_tests_properties(PythonFormats PROPERTIES ENVIRONMENT "${PYTHON_TEST_ENVIRONMENT}")
|
||||||
|
|
||||||
|
add_test(NAME PythonFixExternal
|
||||||
|
COMMAND ${PYTHON_TEST_RUNNER} ${CMAKE_CURRENT_SOURCE_DIR}/python-fix-external.py -v
|
||||||
|
WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH})
|
||||||
|
set_tests_properties(PythonFixExternal PROPERTIES ENVIRONMENT "${PYTHON_TEST_ENVIRONMENT}")
|
||||||
else()
|
else()
|
||||||
message(STATUS "Skipping Tests for the LAMMPS Python Module: no suitable Python interpreter")
|
message(STATUS "Skipping Tests for the LAMMPS Python Module: no suitable Python interpreter")
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
42
unittest/python/python-fix-external.py
Normal file
42
unittest/python/python-fix-external.py
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
import sys,os,unittest
|
||||||
|
from ctypes import *
|
||||||
|
from lammps import lammps
|
||||||
|
|
||||||
|
# add timestep dependent force
|
||||||
|
def callback_one(lmp, ntimestep, nlocal, tag, x, f):
|
||||||
|
for i in range(nlocal):
|
||||||
|
f[i][0] = float(ntimestep)
|
||||||
|
f[i][1] = float(ntimestep)
|
||||||
|
f[i][2] = float(ntimestep)
|
||||||
|
|
||||||
|
class PythonExternal(unittest.TestCase):
|
||||||
|
def testExternalCallback(self):
|
||||||
|
"""Test fix external from Python with pf/callback"""
|
||||||
|
|
||||||
|
machine=None
|
||||||
|
if 'LAMMPS_MACHINE_NAME' in os.environ:
|
||||||
|
machine=os.environ['LAMMPS_MACHINE_NAME']
|
||||||
|
lmp=lammps(name=machine, cmdargs=['-nocite', '-log','none', '-echo', 'screen'])
|
||||||
|
|
||||||
|
# a few commands to set up simple system
|
||||||
|
basic_system="""lattice sc 1.0
|
||||||
|
region box block -1 1 -1 1 -1 1
|
||||||
|
create_box 1 box
|
||||||
|
create_atoms 1 box
|
||||||
|
mass 1 1.0
|
||||||
|
pair_style zero 0.1
|
||||||
|
pair_coeff 1 1
|
||||||
|
velocity all set 0.1 0.0 -0.1
|
||||||
|
thermo 5
|
||||||
|
fix 1 all nve
|
||||||
|
fix ext all external pf/callback 5 1
|
||||||
|
"""
|
||||||
|
lmp.commands_string(basic_system)
|
||||||
|
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)
|
||||||
|
|
||||||
|
##############################
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
|
|
||||||
Reference in New Issue
Block a user