Add datatype introspection methods to library

Adds lammps_extract_atom_datatype and lammps_extract_global_datatype functions
to allow extracting type information of properties.
This commit is contained in:
Richard Berger
2020-09-17 13:43:43 -04:00
parent 706a898163
commit d88810f13a
6 changed files with 273 additions and 0 deletions

View File

@ -40,6 +40,7 @@ LAMMPS_DOUBLE2D = 3
LAMMPS_BIGINT = 4 LAMMPS_BIGINT = 4
LAMMPS_TAGINT = 5 LAMMPS_TAGINT = 5
LAMMPS_STRING = 6 LAMMPS_STRING = 6
LAMMPS_TAGINT2D = 7
# these must be kept in sync with the enums in library.h # these must be kept in sync with the enums in library.h
LMP_STYLE_GLOBAL = 0 LMP_STYLE_GLOBAL = 0

View File

@ -30,6 +30,7 @@
#include "neighbor.h" #include "neighbor.h"
#include "update.h" #include "update.h"
#include "variable.h" #include "variable.h"
#include "library.h"
#include <algorithm> #include <algorithm>
#include <cstring> #include <cstring>
@ -2580,6 +2581,80 @@ void *Atom::extract(const char *name)
return nullptr; return nullptr;
} }
/** Provide data type about internal data of the Atom class
*
* \param name string with the keyword of the desired property.
* \return data type constant for desired property or -1 */
int Atom::extract_datatype(const char *name)
{
// --------------------------------------------------------------------
// 5th customization section: customize by adding new variable name
if (strcmp(name,"mass") == 0) return LAMMPS_DOUBLE;
if (strcmp(name,"id") == 0) return LAMMPS_TAGINT;
if (strcmp(name,"type") == 0) return LAMMPS_INT;
if (strcmp(name,"mask") == 0) return LAMMPS_INT;
if (strcmp(name,"image") == 0) return LAMMPS_TAGINT;
if (strcmp(name,"x") == 0) return LAMMPS_DOUBLE2D;
if (strcmp(name,"v") == 0) return LAMMPS_DOUBLE2D;
if (strcmp(name,"f") == 0) return LAMMPS_DOUBLE2D;
if (strcmp(name,"molecule") == 0) return LAMMPS_TAGINT;
if (strcmp(name,"q") == 0) return LAMMPS_DOUBLE;
if (strcmp(name,"mu") == 0) return LAMMPS_DOUBLE2D;
if (strcmp(name,"omega") == 0) return LAMMPS_DOUBLE2D;
if (strcmp(name,"angmom") == 0) return LAMMPS_DOUBLE2D;
if (strcmp(name,"torque") == 0) return LAMMPS_DOUBLE2D;
if (strcmp(name,"radius") == 0) return LAMMPS_DOUBLE;
if (strcmp(name,"rmass") == 0) return LAMMPS_DOUBLE;
if (strcmp(name,"ellipsoid") == 0) return LAMMPS_INT;
if (strcmp(name,"line") == 0) return LAMMPS_INT;
if (strcmp(name,"tri") == 0) return LAMMPS_INT;
if (strcmp(name,"body") == 0) return LAMMPS_INT;
if (strcmp(name,"vfrac") == 0) return LAMMPS_DOUBLE;
if (strcmp(name,"s0") == 0) return LAMMPS_DOUBLE;
if (strcmp(name,"x0") == 0) return LAMMPS_DOUBLE2D;
if (strcmp(name,"spin") == 0) return LAMMPS_INT;
if (strcmp(name,"eradius") == 0) return LAMMPS_DOUBLE;
if (strcmp(name,"ervel") == 0) return LAMMPS_DOUBLE;
if (strcmp(name,"erforce") == 0) return LAMMPS_DOUBLE;
if (strcmp(name,"ervelforce") == 0) return LAMMPS_DOUBLE;
if (strcmp(name,"cs") == 0) return LAMMPS_DOUBLE2D;
if (strcmp(name,"csforce") == 0) return LAMMPS_DOUBLE2D;
if (strcmp(name,"vforce") == 0) return LAMMPS_DOUBLE2D;
if (strcmp(name,"etag") == 0) return LAMMPS_INT;
if (strcmp(name,"rho") == 0) return LAMMPS_DOUBLE;
if (strcmp(name,"drho") == 0) return LAMMPS_DOUBLE;
if (strcmp(name,"esph") == 0) return LAMMPS_DOUBLE;
if (strcmp(name,"desph") == 0) return LAMMPS_DOUBLE;
if (strcmp(name,"cv") == 0) return LAMMPS_DOUBLE;
if (strcmp(name,"vest") == 0) return LAMMPS_DOUBLE2D;
// USER-MESONT package
if (strcmp(name,"length") == 0) return LAMMPS_DOUBLE;
if (strcmp(name,"buckling") == 0) return LAMMPS_INT;
if (strcmp(name,"bond_nt") == 0) return LAMMPS_TAGINT2D;
if (strcmp(name, "contact_radius") == 0) return LAMMPS_DOUBLE;
if (strcmp(name, "smd_data_9") == 0) return LAMMPS_DOUBLE2D;
if (strcmp(name, "smd_stress") == 0) return LAMMPS_DOUBLE2D;
if (strcmp(name, "eff_plastic_strain") == 0) return LAMMPS_DOUBLE;
if (strcmp(name, "eff_plastic_strain_rate") == 0) return LAMMPS_DOUBLE;
if (strcmp(name, "damage") == 0) return LAMMPS_DOUBLE;
if (strcmp(name,"dpdTheta") == 0) return LAMMPS_DOUBLE;
if (strcmp(name,"edpd_temp") == 0) return LAMMPS_DOUBLE;
// end of customization section
// --------------------------------------------------------------------
return -1;
}
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
return # of bytes of allocated memory return # of bytes of allocated memory
call to avec tallies per-atom vectors call to avec tallies per-atom vectors

View File

@ -335,6 +335,7 @@ class Atom : protected Pointers {
virtual void sync_modify(ExecutionSpace, unsigned int, unsigned int) {} virtual void sync_modify(ExecutionSpace, unsigned int, unsigned int) {}
void *extract(const char *); void *extract(const char *);
int extract_datatype(const char *);
inline int* get_map_array() {return map_array;}; inline int* get_map_array() {return map_array;};
inline int get_map_size() {return map_tag_max+1;}; inline int get_map_size() {return map_tag_max+1;};

View File

@ -1206,6 +1206,98 @@ void *lammps_extract_atom(void *handle, const char *name)
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
/** Get data type of internal global LAMMPS variables or arrays.
*
* TODO
*
* \param handle pointer to a previously created LAMMPS instance
* \param name string with the name of the extracted property
* \return integer constant encoding the data type of the property
or -1 if not found. */
int lammps_extract_global_datatype(void *handle, const char *name)
{
LAMMPS *lmp = (LAMMPS *) handle;
if (strcmp(name,"units") == 0) return LAMMPS_STRING;
if (strcmp(name,"dt") == 0) return LAMMPS_DOUBLE;
if (strcmp(name,"ntimestep") == 0) return LAMMPS_BIGINT;
if (strcmp(name,"boxlo") == 0) return LAMMPS_DOUBLE;
if (strcmp(name,"boxhi") == 0) return LAMMPS_DOUBLE;
if (strcmp(name,"boxxlo") == 0) return LAMMPS_DOUBLE;
if (strcmp(name,"boxxhi") == 0) return LAMMPS_DOUBLE;
if (strcmp(name,"boxylo") == 0) return LAMMPS_DOUBLE;
if (strcmp(name,"boxyhi") == 0) return LAMMPS_DOUBLE;
if (strcmp(name,"boxzlo") == 0) return LAMMPS_DOUBLE;
if (strcmp(name,"boxzhi") == 0) return LAMMPS_DOUBLE;
if (strcmp(name,"periodicity") == 0) return LAMMPS_INT;
if (strcmp(name,"triclinic") == 0) return LAMMPS_INT;
if (strcmp(name,"xy") == 0) return LAMMPS_DOUBLE;
if (strcmp(name,"xz") == 0) return LAMMPS_DOUBLE;
if (strcmp(name,"yz") == 0) return LAMMPS_DOUBLE;
if (strcmp(name,"natoms") == 0) return LAMMPS_BIGINT;
if (strcmp(name,"nbonds") == 0) return LAMMPS_BIGINT;
if (strcmp(name,"nangles") == 0) return LAMMPS_BIGINT;
if (strcmp(name,"ndihedrals") == 0) return LAMMPS_BIGINT;
if (strcmp(name,"nimpropers") == 0) return LAMMPS_BIGINT;
if (strcmp(name,"nlocal") == 0) return LAMMPS_INT;
if (strcmp(name,"nghost") == 0) return LAMMPS_INT;
if (strcmp(name,"nmax") == 0) return LAMMPS_INT;
if (strcmp(name,"ntypes") == 0) return LAMMPS_INT;
if (strcmp(name,"q_flag") == 0) return LAMMPS_INT;
// update->atime can be referenced as a pointer
// thermo "timer" data cannot be, since it is computed on request
// lammps_get_thermo() can access all thermo keywords by value
if (strcmp(name,"atime") == 0) return LAMMPS_DOUBLE;
if (strcmp(name,"atimestep") == 0) return LAMMPS_BIGINT;
// global constants defined by units
if (strcmp(name,"boltz") == 0) return LAMMPS_DOUBLE;
if (strcmp(name,"hplanck") == 0) return LAMMPS_DOUBLE;
if (strcmp(name,"mvv2e") == 0) return LAMMPS_DOUBLE;
if (strcmp(name,"ftm2v") == 0) return LAMMPS_DOUBLE;
if (strcmp(name,"mv2d") == 0) return LAMMPS_DOUBLE;
if (strcmp(name,"nktv2p") == 0) return LAMMPS_DOUBLE;
if (strcmp(name,"qqr2e") == 0) return LAMMPS_DOUBLE;
if (strcmp(name,"qe2f") == 0) return LAMMPS_DOUBLE;
if (strcmp(name,"vxmu2f") == 0) return LAMMPS_DOUBLE;
if (strcmp(name,"xxt2kmu") == 0) return LAMMPS_DOUBLE;
if (strcmp(name,"dielectric") == 0) return LAMMPS_DOUBLE;
if (strcmp(name,"qqrd2e") == 0) return LAMMPS_DOUBLE;
if (strcmp(name,"e_mass") == 0) return LAMMPS_DOUBLE;
if (strcmp(name,"hhmrr2e") == 0) return LAMMPS_DOUBLE;
if (strcmp(name,"mvh2r") == 0) return LAMMPS_DOUBLE;
if (strcmp(name,"angstrom") == 0) return LAMMPS_DOUBLE;
if (strcmp(name,"femtosecond") == 0) return LAMMPS_DOUBLE;
if (strcmp(name,"qelectron") == 0) return LAMMPS_DOUBLE;
return -1;
}
/* ---------------------------------------------------------------------- */
/** Get data type of a LAMMPS per-atom property
*
* TODO
*
* \param handle pointer to a previously created LAMMPS instance
* \param name string with the name of the extracted property
* \return integer constant encoding the data type of the property
* or -1 if not found. */
int lammps_extract_atom_datatype(void *handle, const char *name)
{
LAMMPS *lmp = (LAMMPS *) handle;
return lmp->atom->extract_datatype(name);
}
/* ---------------------------------------------------------------------- */
/** Create N atoms from list of coordinates /** Create N atoms from list of coordinates
* *
\verbatim embed:rst \verbatim embed:rst

View File

@ -40,6 +40,21 @@
#include <inttypes.h> /* for int64_t */ #include <inttypes.h> /* for int64_t */
#endif #endif
/** Data type constants for extracting data from atoms, computes and fixes
*
* Must be kept in sync with the equivalent constants in lammps.py */
enum _LMP_DATATYPE_CONST {
LAMMPS_INT = 0,
LAMMPS_INT2D = 1,
LAMMPS_DOUBLE = 2,
LAMMPS_DOUBLE2D = 3,
LAMMPS_BIGINT = 4,
LAMMPS_TAGINT = 5,
LAMMPS_STRING = 6,
LAMMPS_TAGINT2D = 7
};
/** Style constants for extracting data from computes and fixes. /** Style constants for extracting data from computes and fixes.
* *
* Must be kept in sync with the equivalent constants in lammps.py */ * Must be kept in sync with the equivalent constants in lammps.py */
@ -113,6 +128,9 @@ int lammps_extract_setting(void *handle, const char *keyword);
void *lammps_extract_global(void *handle, const char *name); void *lammps_extract_global(void *handle, const char *name);
void *lammps_extract_atom(void *handle, const char *name); void *lammps_extract_atom(void *handle, const char *name);
int lammps_extract_global_datatype(void *handle, const char *name);
int lammps_extract_atom_datatype(void *handle, const char *name);
#if !defined(LAMMPS_BIGBIG) #if !defined(LAMMPS_BIGBIG)
int lammps_create_atoms(void *handle, int n, int *id, int *type, int lammps_create_atoms(void *handle, int n, int *id, int *type,
double *x, double *v, int *image, int bexpand); double *x, double *v, int *image, int bexpand);

View File

@ -251,4 +251,90 @@ TEST_F(LibraryProperties, global)
EXPECT_EQ((*b_ptr), 2); EXPECT_EQ((*b_ptr), 2);
d_ptr = (double *)lammps_extract_global(lmp, "dt"); d_ptr = (double *)lammps_extract_global(lmp, "dt");
EXPECT_DOUBLE_EQ((*d_ptr), 0.1); EXPECT_DOUBLE_EQ((*d_ptr), 0.1);
int dtype = lammps_extract_global_datatype(lmp, "dt");
EXPECT_EQ(dtype, LAMMPS_DOUBLE);
}; };
class AtomProperties : public ::testing::Test {
protected:
void *lmp;
AtomProperties(){};
~AtomProperties() override{};
void SetUp() override
{
const char *args[] = {"LAMMPS_test", "-log", "none",
"-echo", "screen", "-nocite"};
char **argv = (char **)args;
int argc = sizeof(args) / sizeof(char *);
::testing::internal::CaptureStdout();
lmp = lammps_open_no_mpi(argc, argv, NULL);
std::string output = ::testing::internal::GetCapturedStdout();
if (verbose) std::cout << output;
EXPECT_THAT(output, StartsWith("LAMMPS ("));
::testing::internal::CaptureStdout();
lammps_command(lmp, "region box block 0 2 0 2 0 2");
lammps_command(lmp, "create_box 1 box");
lammps_command(lmp, "mass 1 3.0");
lammps_command(lmp, "create_atoms 1 single 1.0 1.0 1.5");
lammps_command(lmp, "create_atoms 1 single 0.2 0.1 0.1");
output = ::testing::internal::GetCapturedStdout();
if (verbose) std::cout << output;
}
void TearDown() override
{
::testing::internal::CaptureStdout();
lammps_close(lmp);
std::string output = ::testing::internal::GetCapturedStdout();
EXPECT_THAT(output, HasSubstr("Total wall time:"));
if (verbose) std::cout << output;
lmp = nullptr;
}
};
TEST_F(AtomProperties, invalid)
{
ASSERT_EQ(lammps_extract_atom(lmp, "UNKNOWN"), nullptr);
}
TEST_F(AtomProperties, mass)
{
EXPECT_EQ(lammps_extract_atom_datatype(lmp, "mass"), LAMMPS_DOUBLE);
double * mass = (double *)lammps_extract_atom(lmp, "mass");
ASSERT_NE(mass, nullptr);
ASSERT_DOUBLE_EQ(mass[1], 3.0);
}
TEST_F(AtomProperties, id)
{
EXPECT_EQ(lammps_extract_atom_datatype(lmp, "id"), LAMMPS_TAGINT);
LAMMPS_NS::tagint * id = (LAMMPS_NS::tagint *)lammps_extract_atom(lmp, "id");
ASSERT_NE(id, nullptr);
ASSERT_EQ(id[0], 1);
ASSERT_EQ(id[1], 2);
}
TEST_F(AtomProperties, type)
{
EXPECT_EQ(lammps_extract_atom_datatype(lmp, "type"), LAMMPS_INT);
int * type = (LAMMPS_NS::tagint *)lammps_extract_atom(lmp, "type");
ASSERT_NE(type, nullptr);
ASSERT_EQ(type[0], 1);
ASSERT_EQ(type[1], 1);
}
TEST_F(AtomProperties, position)
{
EXPECT_EQ(lammps_extract_atom_datatype(lmp, "x"), LAMMPS_DOUBLE2D);
double ** x = (double **)lammps_extract_atom(lmp, "x");
ASSERT_NE(x, nullptr);
EXPECT_DOUBLE_EQ(x[0][0], 1.0);
EXPECT_DOUBLE_EQ(x[0][1], 1.0);
EXPECT_DOUBLE_EQ(x[0][2], 1.5);
EXPECT_DOUBLE_EQ(x[1][0], 0.2);
EXPECT_DOUBLE_EQ(x[1][1], 0.1);
EXPECT_DOUBLE_EQ(x[1][2], 0.1);
}