Merge pull request #4174 from akohlmey/atom-map-library-interface
Add support for extracting a few more properties and the Atom::map() function to the library interface
This commit is contained in:
@ -305,6 +305,8 @@ of the contents of the :f:mod:`LIBLAMMPS` Fortran interface to LAMMPS.
|
||||
:ftype extract_setting: function
|
||||
:f extract_global: :f:func:`extract_global`
|
||||
:ftype extract_global: function
|
||||
:f map_atom: :f:func:`map_atom`
|
||||
:ftype map_atom: function
|
||||
:f extract_atom: :f:func:`extract_atom`
|
||||
:ftype extract_atom: function
|
||||
:f extract_compute: :f:func:`extract_compute`
|
||||
|
||||
@ -13,6 +13,7 @@ This section documents the following functions:
|
||||
- :cpp:func:`lammps_extract_setting`
|
||||
- :cpp:func:`lammps_extract_global_datatype`
|
||||
- :cpp:func:`lammps_extract_global`
|
||||
- :cpp:func:`lammps_map_atom`
|
||||
|
||||
--------------------
|
||||
|
||||
@ -120,3 +121,8 @@ subdomains and processors.
|
||||
.. doxygenfunction:: lammps_extract_global
|
||||
:project: progguide
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_map_atom
|
||||
:project: progguide
|
||||
|
||||
|
||||
@ -1765,6 +1765,7 @@ keflag
|
||||
Keir
|
||||
Kelchner
|
||||
Kelkar
|
||||
Kemppainen
|
||||
Kemper
|
||||
kepler
|
||||
Kemppainen
|
||||
@ -2486,6 +2487,7 @@ Nevery
|
||||
newfile
|
||||
Newns
|
||||
newtype
|
||||
nextsort
|
||||
Neyts
|
||||
Nf
|
||||
nfft
|
||||
@ -3292,6 +3294,7 @@ Saidi
|
||||
saip
|
||||
Salanne
|
||||
Salles
|
||||
sametag
|
||||
sandia
|
||||
Sandia
|
||||
sandybrown
|
||||
@ -3457,6 +3460,7 @@ solvated
|
||||
solvation
|
||||
someuser
|
||||
Sorensen
|
||||
sortfreq
|
||||
soundspeed
|
||||
sourceforge
|
||||
Souza
|
||||
|
||||
@ -101,6 +101,7 @@ liblammpsplugin_t *liblammpsplugin_load(const char *lib)
|
||||
ADDSYM(extract_setting);
|
||||
ADDSYM(extract_global_datatype);
|
||||
ADDSYM(extract_global);
|
||||
ADDSYM(map_atom);
|
||||
|
||||
ADDSYM(extract_atom_datatype);
|
||||
ADDSYM(extract_atom);
|
||||
|
||||
@ -146,6 +146,7 @@ struct _liblammpsplugin {
|
||||
int (*extract_setting)(void *, const char *);
|
||||
int *(*extract_global_datatype)(void *, const char *);
|
||||
void *(*extract_global)(void *, const char *);
|
||||
void *(*map_atom)(void *, const void *);
|
||||
|
||||
int *(*extract_atom_datatype)(void *, const char *);
|
||||
void *(*extract_atom)(void *, const char *);
|
||||
|
||||
@ -113,6 +113,9 @@ MODULE LIBLAMMPS
|
||||
PROCEDURE :: get_mpi_comm => lmp_get_mpi_comm
|
||||
PROCEDURE :: extract_setting => lmp_extract_setting
|
||||
PROCEDURE :: extract_global => lmp_extract_global
|
||||
PROCEDURE, PRIVATE :: lmp_map_atom_int
|
||||
PROCEDURE, PRIVATE :: lmp_map_atom_big
|
||||
GENERIC :: map_atom => lmp_map_atom_int, lmp_map_atom_big
|
||||
PROCEDURE :: extract_atom => lmp_extract_atom
|
||||
PROCEDURE :: extract_compute => lmp_extract_compute
|
||||
PROCEDURE :: extract_fix => lmp_extract_fix
|
||||
@ -508,6 +511,13 @@ MODULE LIBLAMMPS
|
||||
TYPE(c_ptr) :: lammps_extract_global
|
||||
END FUNCTION lammps_extract_global
|
||||
|
||||
FUNCTION lammps_map_atom(handle, tag) BIND(C)
|
||||
IMPORT :: c_ptr, c_int
|
||||
IMPLICIT NONE
|
||||
TYPE(c_ptr), INTENT(IN), VALUE :: handle, tag
|
||||
INTEGER(c_int) :: lammps_map_atom
|
||||
END FUNCTION lammps_map_atom
|
||||
|
||||
FUNCTION lammps_extract_atom_datatype(handle, name) BIND(C)
|
||||
IMPORT :: c_ptr, c_int
|
||||
IMPLICIT NONE
|
||||
@ -1323,6 +1333,38 @@ CONTAINS
|
||||
END SELECT
|
||||
END FUNCTION
|
||||
|
||||
! equivalent function to lammps_map_atom (for 32-bit integer tags)
|
||||
INTEGER FUNCTION lmp_map_atom_int(self, id)
|
||||
CLASS(lammps), INTENT(IN) :: self
|
||||
INTEGER(c_int), INTENT(IN), TARGET :: id
|
||||
INTEGER(c_int64_t), TARGET :: id64
|
||||
TYPE(c_ptr) :: Cptr
|
||||
|
||||
IF (SIZE_TAGINT == 8) THEN
|
||||
id64 = id
|
||||
Cptr = C_LOC(id64)
|
||||
ELSE
|
||||
Cptr = C_LOC(id)
|
||||
END IF
|
||||
lmp_map_atom_int = lammps_map_atom(self%handle, Cptr) + 1
|
||||
END FUNCTION lmp_map_atom_int
|
||||
|
||||
! equivalent function to lammps_map_atom (for 64-bit integer tags)
|
||||
INTEGER FUNCTION lmp_map_atom_big(self, id)
|
||||
CLASS(lammps), INTENT(IN) :: self
|
||||
INTEGER(c_int64_t), INTENT(IN), TARGET :: id
|
||||
INTEGER(c_int), TARGET :: id32
|
||||
TYPE(c_ptr) :: Cptr
|
||||
|
||||
IF (SIZE_TAGINT == 8) THEN
|
||||
Cptr = C_LOC(id)
|
||||
ELSE
|
||||
id32 = id
|
||||
Cptr = C_LOC(id32)
|
||||
END IF
|
||||
lmp_map_atom_big = lammps_map_atom(self%handle, Cptr) + 1
|
||||
END FUNCTION lmp_map_atom_big
|
||||
|
||||
! equivalent function to lammps_extract_atom
|
||||
! the assignment is actually overloaded so as to bind the pointers to
|
||||
! lammps data based on the information available from LAMMPS
|
||||
|
||||
@ -269,6 +269,9 @@ class lammps(object):
|
||||
self.lib.lammps_extract_global_datatype.restype = c_int
|
||||
self.lib.lammps_extract_compute.argtypes = [c_void_p, c_char_p, c_int, c_int]
|
||||
|
||||
self.lib.lammps_map_atom.argtypes = [c_void_p, c_void_p]
|
||||
self.lib.lammps_map_atom.restype = c_int
|
||||
|
||||
self.lib.lammps_get_thermo.argtypes = [c_void_p, c_char_p]
|
||||
self.lib.lammps_get_thermo.restype = c_double
|
||||
|
||||
@ -893,6 +896,8 @@ class lammps(object):
|
||||
veclen = vec_dict[name]
|
||||
elif name == 'respa_dt':
|
||||
veclen = self.extract_global('respa_levels',LAMMPS_INT)
|
||||
elif name == 'sametag':
|
||||
veclen = self.extract_setting('nall')
|
||||
else:
|
||||
veclen = 1
|
||||
|
||||
@ -926,6 +931,24 @@ class lammps(object):
|
||||
else: return target_type(ptr[0])
|
||||
return None
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# map global atom ID to local atom index
|
||||
|
||||
def map_atom(self, id):
|
||||
"""Map a global atom ID (aka tag) to the local atom index
|
||||
|
||||
This is a wrapper around the :cpp:func:`lammps_map_atom`
|
||||
function of the C-library interface.
|
||||
|
||||
:param id: atom ID
|
||||
:type id: int
|
||||
:return: local index
|
||||
:rtype: int
|
||||
"""
|
||||
|
||||
tag = self.c_tagint(id)
|
||||
return self.lib.lammps_map_atom(self.lmp, pointer(tag))
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# extract per-atom info datatype
|
||||
|
||||
|
||||
@ -1399,6 +1399,16 @@ int lammps_extract_global_datatype(void * /*handle*/, const char *name)
|
||||
if (strcmp(name,"special_lj") == 0) return LAMMPS_DOUBLE;
|
||||
if (strcmp(name,"special_coul") == 0) return LAMMPS_DOUBLE;
|
||||
|
||||
if (strcmp(name,"map_style") == 0) return LAMMPS_INT;
|
||||
#if defined(LAMMPS_BIGBIG)
|
||||
if (strcmp(name,"map_tag_max") == 0) return LAMMPS_BIGINT;
|
||||
#else
|
||||
if (strcmp(name,"map_tag_max") == 0) return LAMMPS_INT;
|
||||
#endif
|
||||
if (strcmp(name,"sametag") == 0) return LAMMPS_INT;
|
||||
if (strcmp(name,"sortfreq") == 0) return LAMMPS_INT;
|
||||
if (strcmp(name,"nextsort") == 0) return LAMMPS_BIGINT;
|
||||
|
||||
if (strcmp(name,"q_flag") == 0) return LAMMPS_INT;
|
||||
|
||||
if (strcmp(name,"units") == 0) return LAMMPS_STRING;
|
||||
@ -1651,6 +1661,26 @@ report the "native" data type. The following tables are provided:
|
||||
- double
|
||||
- 4
|
||||
- special :doc:`pair weighting factors <special_bonds>` for Coulomb interactions (first element is always 1.0)
|
||||
* - map_style
|
||||
- int
|
||||
- 1
|
||||
- :doc:`atom map setting <atom_modify>`: 0 = none, 1 = array, 2 = hash, 3 = yes
|
||||
* - map_tag_max
|
||||
- bigint or int
|
||||
- 1
|
||||
- largest atom ID that can be mapped to a local index (bigint only with -DLAMMPS_BIGBIG)
|
||||
* - sametag
|
||||
- int
|
||||
- nlocal+nghost
|
||||
- index of next local atom with the same ID in ascending order. -1 signals end.
|
||||
* - sortfreq
|
||||
- int
|
||||
- 1
|
||||
- frequency of atom sorting. 0 means sorting is off.
|
||||
* - nextsort
|
||||
- bigint
|
||||
- 1
|
||||
- timestep when atoms are sorted next
|
||||
* - q_flag
|
||||
- int
|
||||
- 1
|
||||
@ -1846,6 +1876,12 @@ void *lammps_extract_global(void *handle, const char *name)
|
||||
|
||||
if (strcmp(name,"q_flag") == 0) return (void *) &lmp->atom->q_flag;
|
||||
|
||||
if (strcmp(name,"map_style") == 0) return (void *) &lmp->atom->map_style;
|
||||
if (strcmp(name,"map_tag_max") == 0) return (void *) &lmp->atom->map_tag_max;
|
||||
if (strcmp(name,"sametag") == 0) return (void *) lmp->atom->sametag;
|
||||
if (strcmp(name,"sortfreq") == 0) return (void *) &lmp->atom->sortfreq;
|
||||
if (strcmp(name,"nextsort") == 0) return (void *) &lmp->atom->nextsort;
|
||||
|
||||
// global constants defined by units
|
||||
|
||||
if (strcmp(name,"boltz") == 0) return (void *) &lmp->force->boltz;
|
||||
@ -1873,6 +1909,37 @@ void *lammps_extract_global(void *handle, const char *name)
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
/** Map global atom ID to local atom index
|
||||
*
|
||||
\verbatim embed:rst
|
||||
|
||||
.. versionadded:: TBD
|
||||
|
||||
This function returns an integer that corresponds to the local atom
|
||||
index for an atom with the global atom ID *id*. The atom ID is passed
|
||||
as a void pointer so that it can use the same interface for either a
|
||||
32-bit or 64-bit tagint. The size of the tagint can be determined
|
||||
using :cpp:func:`lammps_extract_setting`.
|
||||
|
||||
\endverbatim
|
||||
*
|
||||
* \param handle pointer to a previously created LAMMPS instance
|
||||
* \param id void pointer to the atom ID (of data type tagint, i.e. 32-bit or 64-bit integer)
|
||||
* \return local atom index or -1 if the atom is not found or no map exists
|
||||
* */
|
||||
|
||||
int lammps_map_atom(void *handle, const void *id)
|
||||
{
|
||||
auto lmp = (LAMMPS *) handle;
|
||||
auto tag = (const tagint *) id;
|
||||
if (lmp->atom->map_style > Atom::MAP_NONE)
|
||||
return lmp->atom->map(*tag);
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
/** Get data type of a LAMMPS per-atom property
|
||||
*
|
||||
\verbatim embed:rst
|
||||
|
||||
@ -162,6 +162,8 @@ int lammps_extract_setting(void *handle, const char *keyword);
|
||||
int lammps_extract_global_datatype(void *handle, const char *name);
|
||||
void *lammps_extract_global(void *handle, const char *name);
|
||||
|
||||
int lammps_map_atom(void *handle, const void *id);
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* Library functions to read or modify per-atom data in LAMMPS
|
||||
* ---------------------------------------------------------------------- */
|
||||
|
||||
@ -125,6 +125,7 @@ extern int lammps_get_mpi_comm(void *handle);
|
||||
extern int lammps_extract_setting(void *handle, const char *keyword);
|
||||
extern int lammps_extract_global_datatype(void *handle, const char *name);
|
||||
extern void *lammps_extract_global(void *handle, const char *name);
|
||||
extern int lammps_map_atom(void *handle, const void *id);
|
||||
|
||||
extern int lammps_extract_atom_datatype(void *handle, const char *name);
|
||||
extern void *lammps_extract_atom(void *handle, const char *name);
|
||||
@ -310,6 +311,7 @@ extern int lammps_get_mpi_comm(void *handle);
|
||||
extern int lammps_extract_setting(void *handle, const char *keyword);
|
||||
extern int lammps_extract_global_datatype(void *handle, const char *name);
|
||||
extern void *lammps_extract_global(void *handle, const char *name);
|
||||
extern int lammps_map_atom(void *handle, const void *id);
|
||||
|
||||
extern int lammps_extract_atom_datatype(void *handle, const char *name);
|
||||
extern void *lammps_extract_atom(void *handle, const char *name);
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
// unit tests for checking and changing simulation properties through the library interface
|
||||
|
||||
#include "lammps.h"
|
||||
#include "library.h"
|
||||
|
||||
#include "atom.h"
|
||||
#include "lammps.h"
|
||||
#include "lmptype.h"
|
||||
#include "platform.h"
|
||||
#include <string>
|
||||
@ -14,6 +16,7 @@
|
||||
#define STRINGIFY(val) XSTR(val)
|
||||
#define XSTR(val) #val
|
||||
|
||||
using ::LAMMPS_NS::Atom;
|
||||
using ::LAMMPS_NS::bigint;
|
||||
using ::LAMMPS_NS::tagint;
|
||||
using ::LAMMPS_NS::platform::path_join;
|
||||
@ -400,6 +403,68 @@ TEST_F(LibraryProperties, global)
|
||||
EXPECT_DOUBLE_EQ(special_coul[1], 1.0);
|
||||
EXPECT_DOUBLE_EQ(special_coul[2], 1.0);
|
||||
EXPECT_DOUBLE_EQ(special_coul[3], 1.0);
|
||||
|
||||
EXPECT_EQ(lammps_extract_global_datatype(lmp, "map_style"), LAMMPS_INT);
|
||||
#if defined(LAMMPS_BIGBIG)
|
||||
EXPECT_EQ(lammps_extract_global_datatype(lmp, "map_tag_max"), LAMMPS_BIGINT);
|
||||
#else
|
||||
EXPECT_EQ(lammps_extract_global_datatype(lmp, "map_tag_max"), LAMMPS_INT);
|
||||
#endif
|
||||
EXPECT_EQ(lammps_extract_global_datatype(lmp, "sametag"), LAMMPS_INT);
|
||||
EXPECT_EQ(lammps_extract_global_datatype(lmp, "sortfreq"), LAMMPS_INT);
|
||||
EXPECT_EQ(lammps_extract_global_datatype(lmp, "nextsort"), LAMMPS_BIGINT);
|
||||
int *sametag = (int *)lammps_extract_global(lmp, "sametag");
|
||||
int map_style = *(int *)lammps_extract_global(lmp, "map_style");
|
||||
EXPECT_EQ(map_style, Atom::MAP_ARRAY);
|
||||
EXPECT_NE(sametag, nullptr);
|
||||
|
||||
tagint *tags = (tagint *)lammps_extract_atom(lmp, "id");
|
||||
tagint sometags[] = {1, 5, 10, 15, 20};
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
int idx = lammps_map_atom(lmp, (const void *)&sometags[i]);
|
||||
EXPECT_EQ(sometags[i], tags[idx]);
|
||||
int nextidx = sametag[idx];
|
||||
if (nextidx >= 0) {
|
||||
EXPECT_EQ(sometags[i], tags[nextidx]);
|
||||
}
|
||||
}
|
||||
|
||||
if (!verbose) ::testing::internal::CaptureStdout();
|
||||
lammps_command(lmp, "clear");
|
||||
if (!verbose) ::testing::internal::GetCapturedStdout();
|
||||
map_style = *(int *)lammps_extract_global(lmp, "map_style");
|
||||
EXPECT_EQ(map_style, Atom::MAP_NONE);
|
||||
sametag = (int *)lammps_extract_global(lmp, "sametag");
|
||||
EXPECT_EQ(sametag, nullptr);
|
||||
if (!verbose) ::testing::internal::CaptureStdout();
|
||||
lammps_command(lmp, "atom_modify map yes");
|
||||
lammps_command(lmp, "region box block 0 1 0 1 0 1");
|
||||
lammps_command(lmp, "create_box 1 box");
|
||||
lammps_command(lmp, "mass 1 1.0");
|
||||
lammps_command(lmp, "run 0 post no");
|
||||
if (!verbose) ::testing::internal::GetCapturedStdout();
|
||||
map_style = *(int *)lammps_extract_global(lmp, "map_style");
|
||||
EXPECT_EQ(map_style, Atom::MAP_YES);
|
||||
if (!verbose) ::testing::internal::CaptureStdout();
|
||||
lammps_command(lmp, "clear");
|
||||
lammps_command(lmp, "atom_modify map hash");
|
||||
lammps_command(lmp, "region box block 0 1 0 1 0 1");
|
||||
lammps_command(lmp, "create_box 1 box");
|
||||
lammps_command(lmp, "mass 1 1.0");
|
||||
lammps_command(lmp, "run 0 post no");
|
||||
if (!verbose) ::testing::internal::GetCapturedStdout();
|
||||
map_style = *(int *)lammps_extract_global(lmp, "map_style");
|
||||
EXPECT_EQ(map_style, Atom::MAP_HASH);
|
||||
if (!verbose) ::testing::internal::CaptureStdout();
|
||||
lammps_command(lmp, "clear");
|
||||
lammps_command(lmp, "atom_modify map array");
|
||||
lammps_command(lmp, "region box block 0 1 0 1 0 1");
|
||||
lammps_command(lmp, "create_box 1 box");
|
||||
lammps_command(lmp, "mass 1 1.0");
|
||||
lammps_command(lmp, "run 0 post no");
|
||||
if (!verbose) ::testing::internal::GetCapturedStdout();
|
||||
map_style = *(int *)lammps_extract_global(lmp, "map_style");
|
||||
EXPECT_EQ(map_style, Atom::MAP_ARRAY);
|
||||
};
|
||||
|
||||
TEST_F(LibraryProperties, neighlist)
|
||||
|
||||
@ -609,6 +609,10 @@ create_atoms 1 single &
|
||||
self.lmp.command("special_bonds lj/coul 0.0 1.0 1.0")
|
||||
self.assertEqual(self.lmp.extract_global("special_lj"), [1.0, 0.0, 1.0, 1.0])
|
||||
self.assertEqual(self.lmp.extract_global("special_coul"), [1.0, 0.0, 1.0, 1.0])
|
||||
self.assertEqual(self.lmp.extract_global("map_style"), 0)
|
||||
self.assertEqual(self.lmp.extract_global("map_tag_max"), -1)
|
||||
self.assertEqual(self.lmp.extract_global("sortfreq"), 1000)
|
||||
self.assertEqual(self.lmp.extract_global("nextsort"), 0)
|
||||
|
||||
# set and initialize r-RESPA
|
||||
self.lmp.command("run_style respa 3 5 2 pair 2 kspace 3")
|
||||
@ -660,6 +664,19 @@ create_atoms 1 single &
|
||||
self.assertEqual(vel[i][0:3],result[i][3])
|
||||
self.assertEqual(self.lmp.decode_image_flags(img[i]), result[i][4])
|
||||
|
||||
def test_map_atom(self):
|
||||
self.lmp.command('shell cd ' + os.environ['TEST_INPUT_DIR'])
|
||||
self.lmp.command("newton on on")
|
||||
self.lmp.file("in.fourmol")
|
||||
self.lmp.command("run 4 post no")
|
||||
sometags = [1, 10, 25, 29]
|
||||
tags = self.lmp.extract_atom("id")
|
||||
sametag = self.lmp.extract_global("sametag")
|
||||
for mytag in sometags:
|
||||
myidx = self.lmp.map_atom(mytag)
|
||||
self.assertEqual(mytag, tags[myidx])
|
||||
if sametag[myidx] < 0: continue
|
||||
self.assertEqual(mytag, tags[sametag[myidx]])
|
||||
|
||||
##############################
|
||||
if __name__ == "__main__":
|
||||
|
||||
Reference in New Issue
Block a user