Skip to content

Commit

Permalink
Merge pull request lammps#4174 from akohlmey/atom-map-library-interface
Browse files Browse the repository at this point in the history
Add support for extracting a few more properties and the Atom::map() function to the library interface
  • Loading branch information
stanmoore1 authored Jun 4, 2024
2 parents c1a71b3 + c2ce733 commit f5253eb
Show file tree
Hide file tree
Showing 12 changed files with 233 additions and 1 deletion.
2 changes: 2 additions & 0 deletions doc/src/Fortran.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand Down
6 changes: 6 additions & 0 deletions doc/src/Library_properties.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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`

--------------------

Expand Down Expand Up @@ -120,3 +121,8 @@ subdomains and processors.
.. doxygenfunction:: lammps_extract_global
:project: progguide

-----------------------

.. doxygenfunction:: lammps_map_atom
:project: progguide

4 changes: 4 additions & 0 deletions doc/utils/sphinx-config/false_positives.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1765,6 +1765,7 @@ keflag
Keir
Kelchner
Kelkar
Kemppainen
Kemper
kepler
Kemppainen
Expand Down Expand Up @@ -2486,6 +2487,7 @@ Nevery
newfile
Newns
newtype
nextsort
Neyts
Nf
nfft
Expand Down Expand Up @@ -3292,6 +3294,7 @@ Saidi
saip
Salanne
Salles
sametag
sandia
Sandia
sandybrown
Expand Down Expand Up @@ -3457,6 +3460,7 @@ solvated
solvation
someuser
Sorensen
sortfreq
soundspeed
sourceforge
Souza
Expand Down
1 change: 1 addition & 0 deletions examples/COUPLE/plugin/liblammpsplugin.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions examples/COUPLE/plugin/liblammpsplugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 *);
Expand Down
42 changes: 42 additions & 0 deletions fortran/lammps.f90
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -508,6 +511,13 @@ FUNCTION lammps_extract_global(handle, name) BIND(C)
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
Expand Down Expand Up @@ -1323,6 +1333,38 @@ FUNCTION lmp_extract_global(self, name) RESULT(global_data)
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
Expand Down
23 changes: 23 additions & 0 deletions python/lammps/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,9 @@ def __init__(self,name='',cmdargs=None,ptr=None,comm=None):
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

Expand Down Expand Up @@ -893,6 +896,8 @@ def extract_global(self, name, dtype=LAMMPS_AUTODETECT):
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

Expand Down Expand Up @@ -926,6 +931,24 @@ def extract_global(self, name, dtype=LAMMPS_AUTODETECT):
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

Expand Down
67 changes: 67 additions & 0 deletions src/library.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions src/library.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
* ---------------------------------------------------------------------- */
Expand Down
2 changes: 2 additions & 0 deletions tools/swig/lammps.i
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
67 changes: 66 additions & 1 deletion unittest/c-library/test_library_properties.cpp
Original file line number Diff line number Diff line change
@@ -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>
Expand All @@ -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;
Expand Down Expand Up @@ -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)
Expand Down
Loading

0 comments on commit f5253eb

Please sign in to comment.