Merge branch 'develop' into fortran-expansion

This commit is contained in:
Axel Kohlmeyer
2022-10-31 17:57:33 -04:00
15 changed files with 336 additions and 68 deletions

View File

@ -1,6 +1,6 @@
--- ---
name: Request for Help name: Request for Help
about: "Don't post help requests here, email the lammps-users mailing list" about: "Don't post help requests here, post in the LAMMPS forum"
title: "" title: ""
labels: invalid labels: invalid
assignees: '' assignees: ''
@ -8,8 +8,9 @@ assignees: ''
--- ---
Please **do not** post requests for help (e.g. with installing or using LAMMPS) here. Please **do not** post requests for help (e.g. with installing or using LAMMPS) here.
Instead send an e-mail to the lammps-users mailing list. Instead, you can post to the LAMMPS category in the Materials Science Community
Discourse forum at: https://matsci.org/lammps/
This issue tracker is for tracking LAMMPS development related issues only. This issue tracker is for tracking LAMMPS development related issues only.
Thanks for your cooperation. Thank you in advance for your cooperation.

View File

@ -2,12 +2,13 @@ LAMMPS Library Interfaces
************************* *************************
As described on the :doc:`library interface to LAMMPS <Howto_library>` As described on the :doc:`library interface to LAMMPS <Howto_library>`
page, LAMMPS can be built as a library (static or shared), so that page, LAMMPS can be built as a library (static or shared), so that it
it can be called by another code, used in a :doc:`coupled manner can be called by another code, used in a :doc:`coupled manner
<Howto_couple>` with other codes, or driven through a :doc:`Python <Howto_couple>` with other codes, or driven through a :doc:`Python
script <Python_head>`. Even the LAMMPS standalone executable is script <Python_head>`. The LAMMPS standalone executable itself is
essentially a thin wrapper on top of the LAMMPS library, creating a essentially a thin wrapper on top of the LAMMPS library, which creates a
LAMMPS instance, processing input and then existing. LAMMPS instance, passes the input for processing to that instance, and
then exits.
Most of the APIs described below are based on C language wrapper Most of the APIs described below are based on C language wrapper
functions in the files ``src/library.h`` and ``src/library.cpp``, but functions in the files ``src/library.h`` and ``src/library.cpp``, but
@ -87,6 +88,18 @@ run LAMMPS in serial mode.
message retrieved <lammps_get_last_error_message>`. We thus message retrieved <lammps_get_last_error_message>`. We thus
recommend enabling C++ exceptions when using the library interface, recommend enabling C++ exceptions when using the library interface,
.. admonition:: Using the C library interface as a plugin
:class: note
Rather than including the C library directly and link to the LAMMPS
library at compile time, you can use the ``liblammpsplugin.h`` header
file and the ``liblammpsplugin.c`` C code in the
``examples/COUPLE/plugin`` folder for an interface to LAMMPS that is
largely identical to the regular library interface, only that it will
load a LAMMPS shared library file at runtime. This can be useful for
applications where the interface to LAMMPS would be an optional
feature.
.. warning:: .. warning::
No checks are made on the arguments of the function calls of the C No checks are made on the arguments of the function calls of the C
@ -163,5 +176,3 @@ The following links provide some examples and references to the C++ API.
:maxdepth: 1 :maxdepth: 1
Cplusplus Cplusplus

View File

@ -112,7 +112,7 @@ requests to compute `gamma`, as shown in example below:
compute max_pace_gamma all reduce max f_pace_gamma compute max_pace_gamma all reduce max f_pace_gamma
variable dump_skip equal "c_max_pace_gamma < 5" variable dump_skip equal "c_max_pace_gamma < 5"
dump pace_dump all custom 20 extrapolative_structures.dump id x y z f_pace_gamma dump pace_dump all custom 20 extrapolative_structures.dump id type x y z f_pace_gamma
dump_modify pace_dump skip v_dump_skip dump_modify pace_dump skip v_dump_skip
variable max_pace_gamma equal c_max_pace_gamma variable max_pace_gamma equal c_max_pace_gamma

1
examples/COUPLE/plugin/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/build

View File

@ -0,0 +1,47 @@
##########################################
# CMake build system for coupling to the LAMMPS library
# where the library is loaded dynamically at runtime.
##########################################
cmake_minimum_required(VERSION 3.10)
# enforce out-of-source build
if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR})
message(FATAL_ERROR "In-source builds are not allowed. You must create and use a build directory. "
"Please remove CMakeCache.txt and CMakeFiles first.")
endif()
project(liblammpsplugin VERSION 1.0 LANGUAGES C)
# by default, install into $HOME/.local (not /usr/local),
# so that no root access (and sudo) is needed
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(CMAKE_INSTALL_PREFIX "$ENV{HOME}/.local" CACHE PATH "Default install path" FORCE)
endif()
# ugly hacks for MSVC which by default always reports an old C++ standard in the __cplusplus macro
# and prints lots of pointless warnings about "unsafe" functions
if(MSVC)
if(CMAKE_C_COMPILER_ID STREQUAL "MSVC")
if(LAMMPS_EXCEPTIONS)
add_compile_options(/EHsc)
endif()
endif()
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
endif()
find_package(MPI REQUIRED)
# do not include the (obsolete) MPI C++ bindings which makes
# for leaner object files and avoids namespace conflicts
set(MPI_CXX_SKIP_MPICXX TRUE)
##########################
add_executable(simple-plugin simple.c liblammpsplugin.c)
target_link_libraries(simple-plugin PRIVATE MPI::MPI_C)
target_compile_definitions(simple-plugin PRIVATE LAMMPS_LIB_MPI)
# link with -ldl or equivalent for plugin loading; except on Windows
if(NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
target_link_libraries(simple-plugin PRIVATE ${CMAKE_DL_LIBS})
endif()

View File

@ -11,32 +11,39 @@ liblammpsplugin.c is the LAMMPS library plugin loader
You can then build the driver executable codes with a compile line You can then build the driver executable codes with a compile line
like below. like below.
mpicc -c -O -Wall -g -I$HOME/lammps/src liblammpsplugin.c mpicc -c -O -DLAMMPS_LIB_MPI -Wall -g liblammpsplugin.c
mpicc -c -O -Wall -g simple.c mpicc -c -O -DLAMMPS_LIB_MPI -Wall -g simple.c
mpicc simple.o liblammpsplugin.o -ldl -o simpleC mpicc simple.o liblammpsplugin.o -ldl -o simple-plugin
or using the provided CMake file with:
mkdir build
cd build
cmake ../
cmake --build .
You also need to build LAMMPS as a shared library You also need to build LAMMPS as a shared library
(see examples/COUPLE/README), e.g. (see examples/COUPLE/README), e.g.
cd $HOME/lammps/src cd $HOME/lammps/src
make mode=shlib mpi make mode=shlib mpi
or or
cd $HOME/lammps cd $HOME/lammps
mkdir build-shared mkdir build-shared
cd build-shared cd build-shared
cmake -D BUILD_LIB=on -D BUILD_SHARED_LIBS=on ../cmake cmake -D BUILD_MPI=on -D BUILD_SHARED_LIBS=on ../cmake
make make
You then run simpleC on a parallel machine You then run simple-plugin on a parallel machine
on some number of processors Q with 3 arguments: on some number of processors Q with 3 arguments:
% mpirun -np Q simpleC P in.lj $HOME/lammps/src/liblammps.so % mpirun -np Q simple-plugin P in.lj $HOME/lammps/src/liblammps.so
or or
% mpirun -np Q simpleC P in.lj $HOME/lammps/build-shared/liblammps.so % mpirun -np Q simple-plugin P in.lj $HOME/lammps/build-shared/liblammps.so
P is the number of procs you want LAMMPS to run on (must be <= Q) and P is the number of procs you want LAMMPS to run on (must be <= Q) and
in.lj is a LAMMPS input script and the last argument is the path to in.lj is a LAMMPS input script and the last argument is the path to

View File

@ -18,10 +18,29 @@
a LAMMPS plugin to some other software. a LAMMPS plugin to some other software.
*/ */
#include "library.h"
#include "liblammpsplugin.h" #include "liblammpsplugin.h"
#include <stdlib.h>
#if defined(_WIN32)
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#if defined(_WIN32_WINNT)
#undef _WIN32_WINNT
#endif
// target Windows version is windows 7 and later
#define _WIN32_WINNT _WIN32_WINNT_WIN7
#define PSAPI_VERSION 2
#include <windows.h>
#else
#include <dlfcn.h> #include <dlfcn.h>
#endif
#include <stdlib.h>
liblammpsplugin_t *liblammpsplugin_load(const char *lib) liblammpsplugin_t *liblammpsplugin_load(const char *lib)
{ {
@ -29,14 +48,29 @@ liblammpsplugin_t *liblammpsplugin_load(const char *lib)
void *handle; void *handle;
if (lib == NULL) return NULL; if (lib == NULL) return NULL;
#ifdef _WIN32
handle = (void *) LoadLibrary(lib);
#else
handle = dlopen(lib,RTLD_NOW|RTLD_GLOBAL); handle = dlopen(lib,RTLD_NOW|RTLD_GLOBAL);
#endif
if (handle == NULL) return NULL; if (handle == NULL) return NULL;
lmp = (liblammpsplugin_t *) malloc(sizeof(liblammpsplugin_t)); lmp = (liblammpsplugin_t *) malloc(sizeof(liblammpsplugin_t));
lmp->handle = handle; lmp->handle = handle;
#define ADDSYM(symbol) lmp->symbol = dlsym(handle,"lammps_" #symbol) #ifdef _WIN32
#define ADDSYM(symbol) *(void **) (&lmp->symbol) = (void *) GetProcAddress((HINSTANCE) handle, "lammps_" #symbol)
#else
#define ADDSYM(symbol) *(void **) (&lmp->symbol) = dlsym(handle,"lammps_" #symbol)
#endif
#if defined(LAMMPS_LIB_MPI)
ADDSYM(open); ADDSYM(open);
#else
lmp->open = NULL;
#endif
ADDSYM(open_no_mpi); ADDSYM(open_no_mpi);
ADDSYM(open_fortran); ADDSYM(open_fortran);
ADDSYM(close); ADDSYM(close);
@ -46,6 +80,8 @@ liblammpsplugin_t *liblammpsplugin_load(const char *lib)
ADDSYM(kokkos_finalize); ADDSYM(kokkos_finalize);
ADDSYM(python_finalize); ADDSYM(python_finalize);
ADDSYM(error);
ADDSYM(file); ADDSYM(file);
ADDSYM(command); ADDSYM(command);
ADDSYM(commands_list); ADDSYM(commands_list);
@ -70,6 +106,7 @@ liblammpsplugin_t *liblammpsplugin_load(const char *lib)
ADDSYM(extract_compute); ADDSYM(extract_compute);
ADDSYM(extract_fix); ADDSYM(extract_fix);
ADDSYM(extract_variable); ADDSYM(extract_variable);
ADDSYM(extract_variable_datatype);
ADDSYM(set_variable); ADDSYM(set_variable);
ADDSYM(gather_atoms); ADDSYM(gather_atoms);
@ -77,8 +114,15 @@ liblammpsplugin_t *liblammpsplugin_load(const char *lib)
ADDSYM(gather_atoms_subset); ADDSYM(gather_atoms_subset);
ADDSYM(scatter_atoms); ADDSYM(scatter_atoms);
ADDSYM(scatter_atoms_subset); ADDSYM(scatter_atoms_subset);
ADDSYM(gather_bonds); ADDSYM(gather_bonds);
ADDSYM(gather);
ADDSYM(gather_concat);
ADDSYM(gather_subset);
ADDSYM(scatter);
ADDSYM(scatter_subset);
ADDSYM(create_atoms); ADDSYM(create_atoms);
ADDSYM(find_pair_neighlist); ADDSYM(find_pair_neighlist);
@ -116,6 +160,9 @@ liblammpsplugin_t *liblammpsplugin_load(const char *lib)
ADDSYM(plugin_count); ADDSYM(plugin_count);
ADDSYM(plugin_name); ADDSYM(plugin_name);
ADDSYM(encode_image_flags);
ADDSYM(decode_image_flags);
ADDSYM(set_fix_external_callback); ADDSYM(set_fix_external_callback);
ADDSYM(fix_external_get_force); ADDSYM(fix_external_get_force);
ADDSYM(fix_external_set_energy_global); ADDSYM(fix_external_set_energy_global);
@ -125,6 +172,8 @@ liblammpsplugin_t *liblammpsplugin_load(const char *lib)
ADDSYM(fix_external_set_vector_length); ADDSYM(fix_external_set_vector_length);
ADDSYM(fix_external_set_vector); ADDSYM(fix_external_set_vector);
ADDSYM(flush_buffers);
ADDSYM(free); ADDSYM(free);
ADDSYM(is_running); ADDSYM(is_running);
@ -139,6 +188,8 @@ liblammpsplugin_t *liblammpsplugin_load(const char *lib)
lmp->has_error = NULL; lmp->has_error = NULL;
lmp->get_last_error_message = NULL; lmp->get_last_error_message = NULL;
#endif #endif
ADDSYM(python_api_version);
return lmp; return lmp;
} }
@ -147,7 +198,11 @@ int liblammpsplugin_release(liblammpsplugin_t *lmp)
if (lmp == NULL) return 1; if (lmp == NULL) return 1;
if (lmp->handle == NULL) return 2; if (lmp->handle == NULL) return 2;
#ifdef _WIN32
FreeLibrary((HINSTANCE) handle);
#else
dlclose(lmp->handle); dlclose(lmp->handle);
#endif
free((void *)lmp); free((void *)lmp);
return 0; return 0;
} }

View File

@ -28,11 +28,71 @@
#define LAMMPS_SMALLBIG #define LAMMPS_SMALLBIG
#endif #endif
#if defined(LAMMPS_LIB_MPI)
#include <mpi.h> #include <mpi.h>
#if defined(LAMMPS_BIGBIG) || defined(LAMMPS_SMALLBIG)
#include <inttypes.h> /* for int64_t */
#endif #endif
#if defined(LAMMPS_BIGBIG) || defined(LAMMPS_SMALLBIG)
#include <stdint.h> /* for int64_t */
#endif
/* The following must be kept in sync with the equivalent constants in
* python/lammps/constants.py, fortran/lammps.f90, tools/swig/lammps.i,
* and examples/COUPLE/plugin/liblammpsplugin.h */
/* Data type constants for extracting data from atoms, computes and fixes */
enum _LMP_DATATYPE_CONST {
LAMMPS_INT = 0, /*!< 32-bit integer (array) */
LAMMPS_INT_2D = 1, /*!< two-dimensional 32-bit integer array */
LAMMPS_DOUBLE = 2, /*!< 64-bit double (array) */
LAMMPS_DOUBLE_2D = 3, /*!< two-dimensional 64-bit double array */
LAMMPS_INT64 = 4, /*!< 64-bit integer (array) */
LAMMPS_INT64_2D = 5, /*!< two-dimensional 64-bit integer array */
LAMMPS_STRING = 6 /*!< C-String */
};
/* Style constants for extracting data from computes and fixes. */
enum _LMP_STYLE_CONST {
LMP_STYLE_GLOBAL = 0, /*!< return global data */
LMP_STYLE_ATOM = 1, /*!< return per-atom data */
LMP_STYLE_LOCAL = 2 /*!< return local data */
};
/* Type and size constants for extracting data from computes and fixes. */
enum _LMP_TYPE_CONST {
LMP_TYPE_SCALAR = 0, /*!< return scalar */
LMP_TYPE_VECTOR = 1, /*!< return vector */
LMP_TYPE_ARRAY = 2, /*!< return array */
LMP_SIZE_VECTOR = 3, /*!< return length of vector */
LMP_SIZE_ROWS = 4, /*!< return number of rows */
LMP_SIZE_COLS = 5 /*!< return number of columns */
};
/* Error codes to select the suitable function in the Error class */
enum _LMP_ERROR_CONST {
LMP_ERROR_WARNING = 0, /*!< call Error::warning() */
LMP_ERROR_ONE = 1, /*!< called from one MPI rank */
LMP_ERROR_ALL = 2, /*!< called from all MPI ranks */
LMP_ERROR_WORLD = 4, /*!< error on Comm::world */
LMP_ERROR_UNIVERSE = 8 /*!< error on Comm::universe */
};
/** Variable style constants for extracting data from variables.
*
* Must be kept in sync with the equivalent constants in python/lammps/constants.py,
* fortran/lammps.f90, and tools/swig/lammps.i */
enum _LMP_VAR_CONST {
LMP_VAR_EQUAL = 0, /*!< compatible with equal-style variables */
LMP_VAR_ATOM = 1, /*!< compatible with atom-style variables */
LMP_VAR_VECTOR = 2, /*!< compatible with vector-style variables */
LMP_VAR_STRING = 3 /*!< return value will be a string (catch-all) */
};
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -49,7 +109,11 @@ struct _liblammpsplugin {
int abiversion; int abiversion;
int has_exceptions; int has_exceptions;
void *handle; void *handle;
#if defined(LAMMPS_LIB_MPI)
void *(*open)(int, char **, MPI_Comm, void **); void *(*open)(int, char **, MPI_Comm, void **);
#else
void *open;
#endif
void *(*open_no_mpi)(int, char **, void **); void *(*open_no_mpi)(int, char **, void **);
void *(*open_fortran)(int, char **, void **, int); void *(*open_fortran)(int, char **, void **, int);
void (*close)(void *); void (*close)(void *);
@ -59,13 +123,15 @@ struct _liblammpsplugin {
void (*kokkos_finalize)(); void (*kokkos_finalize)();
void (*python_finalize)(); void (*python_finalize)();
void (*error)(void *, int, const char *);
void (*file)(void *, char *); void (*file)(void *, char *);
char *(*command)(void *, const char *); char *(*command)(void *, const char *);
void (*commands_list)(void *, int, const char **); void (*commands_list)(void *, int, const char **);
void (*commands_string)(void *, const char *); void (*commands_string)(void *, const char *);
double (*get_natoms)(void *); double (*get_natoms)(void *);
double (*get_thermo)(void *, char *); double (*get_thermo)(void *, const char *);
void (*extract_box)(void *, double *, double *, void (*extract_box)(void *, double *, double *,
double *, double *, double *, int *, int *); double *, double *, double *, int *, int *);
@ -78,12 +144,13 @@ struct _liblammpsplugin {
int *(*extract_global_datatype)(void *, const char *); int *(*extract_global_datatype)(void *, const char *);
void *(*extract_global)(void *, const char *); void *(*extract_global)(void *, const char *);
void *(*extract_atom_datatype)(void *, const char *); int *(*extract_atom_datatype)(void *, const char *);
void *(*extract_atom)(void *, const char *); void *(*extract_atom)(void *, const char *);
void *(*extract_compute)(void *, const char *, int, int); void *(*extract_compute)(void *, const char *, int, int);
void *(*extract_fix)(void *, const char *, int, int, int, int); void *(*extract_fix)(void *, const char *, int, int, int, int);
void *(*extract_variable)(void *, const char *, char *); void *(*extract_variable)(void *, const char *, char *);
int (*extract_variable_datatype)(void *, const char *);
int (*set_variable)(void *, char *, char *); int (*set_variable)(void *, char *, char *);
void (*gather_atoms)(void *, char *, int, int, void *); void (*gather_atoms)(void *, char *, int, int, void *);
@ -93,22 +160,26 @@ struct _liblammpsplugin {
void (*scatter_atoms_subset)(void *, char *, int, int, int, int *, void *); void (*scatter_atoms_subset)(void *, char *, int, int, int, int *, void *);
void (*gather_bonds)(void *, void *); void (*gather_bonds)(void *, void *);
// lammps_create_atoms() takes tagint and imageint as args void (*gather)(void *, char *, int, int, void *);
// ifdef insures they are compatible with rest of LAMMPS void (*gather_concat)(void *, char *, int, int, void *);
// caller must match to how LAMMPS library is built void (*gather_subset)(void *, char *, int, int, int, int *,void *);
void (*scatter)(void *, char *, int, int, void *);
void (*scatter_subset)(void *, char *, int, int, int, int *, void *);
/* lammps_create_atoms() takes tagint and imageint as args
* the ifdef insures they are compatible with rest of LAMMPS
* caller must match to how LAMMPS library is built */
#ifndef LAMMPS_BIGBIG #ifndef LAMMPS_BIGBIG
void (*create_atoms)(void *, int, int *, int *, double *, void (*create_atoms)(void *, int, int *, int *, double *, double *, int *, int);
double *, int *, int);
#else #else
void (*create_atoms)(void *, int, int64_t *, int *, double *, void (*create_atoms)(void *, int, int64_t *, int *, double *, double *, int64_t *, int);
double *, int64_t *, int);
#endif #endif
int (*find_pair_neighlist)(void *, const char *, int, int, int); int (*find_pair_neighlist)(void *, const char *, int, int, int);
int (*find_fix_neighlist)(void *, const char *, int); int (*find_fix_neighlist)(void *, const char *, int);
int (*find_compute_neighlist)(void *, char *, int); int (*find_compute_neighlist)(void *, const char *, int);
int (*neighlist_num_elements)(void *, int); int (*neighlist_num_elements)(void *, int);
void (*neighlist_element_neighbors)(void *, int, int, int *, int *, int **); void (*neighlist_element_neighbors)(void *, int, int, int *, int *, int **);
@ -141,8 +212,16 @@ struct _liblammpsplugin {
int (*plugin_count)(); int (*plugin_count)();
int (*plugin_name)(int, char *, char *, int); int (*plugin_name)(int, char *, char *, int);
void (*set_fix_external_callback)(void *, const char *, FixExternalFnPtr, void*); #if !defined(LAMMPS_BIGBIG)
void (*fix_external_get_force)(void *, const char *); int (*encode_image_flags)(int, int, int);
void (*decode_image_flags)(int, int *);
#else
int64_t (*encode_image_flags)(int, int, int);
void (*decode_image_flags)(int64_t, int *);
#endif
void (*set_fix_external_callback)(void *, const char *, FixExternalFnPtr, void *);
double **(*fix_external_get_force)(void *, const char *);
void (*fix_external_set_energy_global)(void *, const char *, double); void (*fix_external_set_energy_global)(void *, const char *, double);
void (*fix_external_set_energy_peratom)(void *, const char *, double *); void (*fix_external_set_energy_peratom)(void *, const char *, double *);
void (*fix_external_set_virial_global)(void *, const char *, double *); void (*fix_external_set_virial_global)(void *, const char *, double *);
@ -150,6 +229,8 @@ struct _liblammpsplugin {
void (*fix_external_set_vector_length)(void *, const char *, int); void (*fix_external_set_vector_length)(void *, const char *, int);
void (*fix_external_set_vector)(void *, const char *, int, double); void (*fix_external_set_vector)(void *, const char *, int, double);
void (*flush_buffers)(void *);
void (*free)(void *); void (*free)(void *);
void (*is_running)(void *); void (*is_running)(void *);
@ -157,6 +238,8 @@ struct _liblammpsplugin {
int (*has_error)(void *); int (*has_error)(void *);
int (*get_last_error_message)(void *, char *, int); int (*get_last_error_message)(void *, char *, int);
int (*python_api_version)();
}; };
typedef struct _liblammpsplugin liblammpsplugin_t; typedef struct _liblammpsplugin liblammpsplugin_t;

View File

@ -19,10 +19,16 @@
in.lammps = LAMMPS input script in.lammps = LAMMPS input script
See README for compilation instructions */ See README for compilation instructions */
#include <mpi.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <mpi.h>
/* define so interface to lammps_open() is available,
since we will run on split communicator */
#define LAMMPS_LIB_MPI 1
#include "liblammpsplugin.h" /* this is the include for the plugin loader */ #include "liblammpsplugin.h" /* this is the include for the plugin loader */
int main(int narg, char **arg) int main(int narg, char **arg)
@ -87,7 +93,13 @@ int main(int narg, char **arg)
MPI_Abort(MPI_COMM_WORLD,1); MPI_Abort(MPI_COMM_WORLD,1);
} }
} }
if (lammps == 1) lmp = plugin->open(0,NULL,comm_lammps,NULL); if (lammps == 1) {
if (plugin->open == NULL) {
printf("ERROR: liblammpsmpi.c must be compiled with -DLAMMPS_LIB_MPI=1 for this program\n");
MPI_Abort(MPI_COMM_WORLD,2);
}
lmp = plugin->open(0,NULL,comm_lammps,NULL);
}
while (1) { while (1) {
if (me == 0) { if (me == 0) {
@ -112,23 +124,23 @@ int main(int narg, char **arg)
int natoms = plugin->get_natoms(lmp); int natoms = plugin->get_natoms(lmp);
x = (double *) malloc(3*natoms*sizeof(double)); x = (double *) malloc(3*natoms*sizeof(double));
plugin->gather_atoms(lmp,"x",1,3,x); plugin->gather_atoms(lmp,(char *)"x",1,3,x);
v = (double *) malloc(3*natoms*sizeof(double)); v = (double *) malloc(3*natoms*sizeof(double));
plugin->gather_atoms(lmp,"v",1,3,v); plugin->gather_atoms(lmp,(char *)"v",1,3,v);
double epsilon = 0.1; double epsilon = 0.1;
x[0] += epsilon; x[0] += epsilon;
plugin->scatter_atoms(lmp,"x",1,3,x); plugin->scatter_atoms(lmp,(char *)"x",1,3,x);
plugin->command(lmp,"run 1"); plugin->command(lmp,"run 1");
} }
// extract force on single atom two different ways /* extract force on single atom two different ways */
if (lammps == 1) { if (lammps == 1) {
double **f = (double **) plugin->extract_atom(lmp,"f"); double **f = (double **) plugin->extract_atom(lmp,"f");
printf("Force on 1 atom via extract_atom: %g\n",f[0][0]); printf("Force on 1 atom via extract_atom: %g\n",f[0][0]);
double *fx = (double *) plugin->extract_variable(lmp,"fx","all"); double *fx = (double *) plugin->extract_variable(lmp,"fx",(char *)"all");
printf("Force on 1 atom via extract_variable: %g\n",fx[0]); printf("Force on 1 atom via extract_variable: %g\n",fx[0]);
} }
@ -160,7 +172,7 @@ int main(int narg, char **arg)
if (v) free(v); if (v) free(v);
if (type) free(type); if (type) free(type);
// close down LAMMPS /* close down LAMMPS */
if (lammps == 1) { if (lammps == 1) {
plugin->close(lmp); plugin->close(lmp);

View File

@ -1,17 +1,44 @@
cmake_minimum_required(VERSION 3.10) cmake_minimum_required(VERSION 3.10)
project(simple CXX)
set(LAMMPS_SRC_DIRECTORY "" CACHE PATH "Path for lammps source") # enforce out-of-source build
if(NOT LAMMPS_SRC_DIRECTORY STREQUAL "" AND EXISTS ${LAMMPS_SRC_DIRECTORY}/cmake/CMakeLists.txt) if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR})
option(BUILD_LIB "Build LAMMPS library" ON) message(FATAL_ERROR "In-source builds are not allowed. You must create and use a build directory. "
add_subdirectory(${LAMMPS_SRC_DIRECTORY}/cmake lammps) "Please remove CMakeCache.txt and CMakeFiles first.")
else() endif()
project(couple-simple VERSION 1.0 LANGUAGES C CXX)
# by default, install into $HOME/.local (not /usr/local),
# so that no root access (and sudo) is needed
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(CMAKE_INSTALL_PREFIX "$ENV{HOME}/.local" CACHE PATH "Default install path" FORCE)
endif()
# ugly hacks for MSVC which by default always reports an old C++ standard in the __cplusplus macro
# and prints lots of pointless warnings about "unsafe" functions
if(MSVC)
if(CMAKE_C_COMPILER_ID STREQUAL "MSVC")
if(LAMMPS_EXCEPTIONS)
add_compile_options(/EHsc)
endif()
endif()
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
endif()
find_package(MPI QUIET)
# do not include the (obsolete) MPI C++ bindings which makes
# for leaner object files and avoids namespace conflicts
set(MPI_CXX_SKIP_MPICXX TRUE)
##########################
# build within LAMMPS build system
if(NOT LAMMPS_SOURCE_DIR)
find_package(LAMMPS REQUIRED) find_package(LAMMPS REQUIRED)
endif() endif()
add_executable(simpleCC simple.cpp) add_executable(simpleCC simple.cpp)
target_link_libraries(simpleCC LAMMPS::lammps) target_link_libraries(simpleCC LAMMPS::lammps)
enable_language(C)
add_executable(simpleC simple.c) add_executable(simpleC simple.c)
target_link_libraries(simpleC LAMMPS::lammps) target_link_libraries(simpleC LAMMPS::lammps)

View File

@ -44,7 +44,8 @@ MODULE LIBLAMMPS
! Data type constants for extracting data from global, atom, compute, and fix ! Data type constants for extracting data from global, atom, compute, and fix
! !
! Must be kept in sync with the equivalent declarations in ! Must be kept in sync with the equivalent declarations in
! src/library.h, python/lammps/constants.py, and tools/swig/lammps.i ! src/library.h, python/lammps/constants.py, tools/swig/lammps.i,
! and examples/COUPLE/plugin/liblammpsplugin.h
! !
! These are NOT part of the API (the part the user sees) ! These are NOT part of the API (the part the user sees)
INTEGER(c_int), PARAMETER :: & INTEGER(c_int), PARAMETER :: &

View File

@ -22,8 +22,8 @@ LAMMPS_INT64 = 4
LAMMPS_INT64_2D = 5 LAMMPS_INT64_2D = 5
LAMMPS_STRING = 6 LAMMPS_STRING = 6
# these must be kept in sync with the enums in src/library.h, tools/swig/lammps.i # these must be kept in sync with the enums in src/library.h, tools/swig/lammps.i,
# and the constants in fortran/lammps.f90 # examples/COUPLE/plugin/liblammpsplugin.h, and the constants in fortran/lammps.f90
LMP_STYLE_GLOBAL = 0 LMP_STYLE_GLOBAL = 0
LMP_STYLE_ATOM = 1 LMP_STYLE_ATOM = 1
LMP_STYLE_LOCAL = 2 LMP_STYLE_LOCAL = 2

View File

@ -240,15 +240,19 @@ void FixPair::post_force(int /*vflag*/)
// extract pair style fields one by one // extract pair style fields one by one
// store their values in this fix // store their values in this fix
int nlocal = atom->nlocal; const int nlocal = atom->nlocal;
int icol = 0; int icol = 0;
int columns; int columns;
for (int ifield = 0; ifield < nfield; ifield++) { for (int ifield = 0; ifield < nfield; ifield++) {
void *pvoid = pstyle->extract_peratom(fieldname[ifield],columns); void *pvoid = pstyle->extract_peratom(fieldname[ifield],columns);
if (pvoid == nullptr)
error->all(FLERR,"Fix pair pair style cannot extract {}",fieldname[ifield]); // Pair::extract_peratom() may return a null pointer if there are no atoms the sub-domain
// so returning null is only an error if there are local atoms.
if ((pvoid == nullptr) && (nlocal > 0))
error->one(FLERR, "Fix pair cannot extract property {} from pair style", fieldname[ifield]);
if (columns == 0) { if (columns == 0) {
double *pvector = (double *) pvoid; double *pvector = (double *) pvoid;

View File

@ -41,7 +41,7 @@
/** Data type constants for extracting data from atoms, computes and fixes /** Data type constants for extracting data from atoms, computes and fixes
* *
* Must be kept in sync with the equivalent constants in python/lammps/constants.py, * Must be kept in sync with the equivalent constants in python/lammps/constants.py,
* fortran/lammps.f90, and tools/swig/lammps.i */ * fortran/lammps.f90, tools/swig/lammps.i, examples/COUPLE/plugin/liblammpsplugin.h */
enum _LMP_DATATYPE_CONST { enum _LMP_DATATYPE_CONST {
LAMMPS_INT = 0, /*!< 32-bit integer (array) */ LAMMPS_INT = 0, /*!< 32-bit integer (array) */
@ -56,7 +56,7 @@ enum _LMP_DATATYPE_CONST {
/** 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 python/lammps/constants.py, * Must be kept in sync with the equivalent constants in python/lammps/constants.py,
* fortran/lammps.f90, and tools/swig/lammps.i */ * fortran/lammps.f90, tools/swig/lammps.i, and examples/COUPLE/plugin/liblammpsplugin.h */
enum _LMP_STYLE_CONST { enum _LMP_STYLE_CONST {
LMP_STYLE_GLOBAL = 0, /*!< return global data */ LMP_STYLE_GLOBAL = 0, /*!< return global data */
@ -67,7 +67,7 @@ enum _LMP_STYLE_CONST {
/** Type and size constants for extracting data from computes and fixes. /** Type and size constants for extracting data from computes and fixes.
* *
* Must be kept in sync with the equivalent constants in python/lammps/constants.py, * Must be kept in sync with the equivalent constants in python/lammps/constants.py,
* fortran/lammps.f90, and tools/swig/lammps.i */ * fortran/lammps.f90, tools/swig/lammps.i, and examples/COUPLE/plugin/liblammpsplugin.h */
enum _LMP_TYPE_CONST { enum _LMP_TYPE_CONST {
LMP_TYPE_SCALAR = 0, /*!< return scalar */ LMP_TYPE_SCALAR = 0, /*!< return scalar */
@ -81,7 +81,7 @@ enum _LMP_TYPE_CONST {
/** Error codes to select the suitable function in the Error class /** Error codes to select the suitable function in the Error class
* *
* Must be kept in sync with the equivalent constants in python/lammps/constants.py, * Must be kept in sync with the equivalent constants in python/lammps/constants.py,
* fortran/lammps.f90, and tools/swig/lammps.i */ * fortran/lammps.f90, tools/swig/lammps.i, and examples/COUPLE/plugin/liblammpsplugin.h */
enum _LMP_ERROR_CONST { enum _LMP_ERROR_CONST {
LMP_ERROR_WARNING = 0, /*!< call Error::warning() */ LMP_ERROR_WARNING = 0, /*!< call Error::warning() */
@ -94,7 +94,7 @@ enum _LMP_ERROR_CONST {
/** Variable style constants for extracting data from variables. /** Variable style constants for extracting data from variables.
* *
* Must be kept in sync with the equivalent constants in python/lammps/constants.py, * Must be kept in sync with the equivalent constants in python/lammps/constants.py,
* fortran/lammps.f90, and tools/swig/lammps.i */ * fortran/lammps.f90, tools/swig/lammps.i, and examples/COUPLE/plugin/liblammpsplugin.h */
enum _LMP_VAR_CONST { enum _LMP_VAR_CONST {
LMP_VAR_EQUAL = 0, /*!< compatible with equal-style variables */ LMP_VAR_EQUAL = 0, /*!< compatible with equal-style variables */
@ -260,15 +260,14 @@ 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 *handle, const 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 *, const char *, FixExternalFnPtr, void *);
#else #else
typedef void (*FixExternalFnPtr)(void *, int, int, int *, double **, double **); typedef void (*FixExternalFnPtr)(void *, int, int, int *, double **, double **);
void lammps_set_fix_external_callback(void *, const char *, FixExternalFnPtr, void *);
#endif #endif
void lammps_set_fix_external_callback(void *handle, const char *id, FixExternalFnPtr funcptr,
void *ptr);
double **lammps_fix_external_get_force(void *handle, const char *id); double **lammps_fix_external_get_force(void *handle, const char *id);
void lammps_fix_external_set_energy_global(void *handle, const char *id, double eng); void lammps_fix_external_set_energy_global(void *handle, const char *id, double eng);
void lammps_fix_external_set_energy_peratom(void *handle, const char *id, double *eng); void lammps_fix_external_set_energy_peratom(void *handle, const char *id, double *eng);

View File

@ -71,3 +71,23 @@ add_executable(test_library_mpi test_library_mpi.cpp)
target_link_libraries(test_library_mpi PRIVATE lammps GTest::GMock) target_link_libraries(test_library_mpi PRIVATE lammps GTest::GMock)
target_compile_definitions(test_library_mpi PRIVATE ${TEST_CONFIG_DEFS}) target_compile_definitions(test_library_mpi PRIVATE ${TEST_CONFIG_DEFS})
add_mpi_test(NAME LibraryMPI NUM_PROCS 4 COMMAND $<TARGET_FILE:test_library_mpi>) add_mpi_test(NAME LibraryMPI NUM_PROCS 4 COMMAND $<TARGET_FILE:test_library_mpi>)
# simple run tests for coupling to the LAMMPS library
if(BUILD_MPI)
if(BUILD_SHARED_LIBS)
add_subdirectory(${LAMMPS_DIR}/examples/COUPLE/plugin ${CMAKE_BINARY_DIR}/build-couple)
add_test(NAME RunCoupleSimplePlugin
COMMAND $<TARGET_FILE:simple-plugin> 1 ${LAMMPS_DIR}/examples/COUPLE/plugin/in.lj $<TARGET_FILE:lammps>)
set_tests_properties(RunCoupleSimplePlugin PROPERTIES
ENVIRONMENT "TSAN_OPTIONS=ignore_noninstrumented_modules=1;HWLOC_HIDE_ERRORS=2"
PASS_REGULAR_EXPRESSION "LAMMPS \\([0-9]+ [A-Za-z]+ 2[0-9][0-9][0-9]( - Update [0-9]+)?\\)")
endif()
add_subdirectory(${LAMMPS_DIR}/examples/COUPLE/simple ${CMAKE_BINARY_DIR}/build-simple)
add_test(NAME RunCoupleSimpleC
COMMAND $<TARGET_FILE:simpleC> 1 ${LAMMPS_DIR}/examples/COUPLE/simple/in.lj)
add_test(NAME RunCoupleSimpleCC
COMMAND $<TARGET_FILE:simpleCC> 1 ${LAMMPS_DIR}/examples/COUPLE/simple/in.lj)
set_tests_properties(RunCoupleSimpleC RunCoupleSimpleCC PROPERTIES
ENVIRONMENT "TSAN_OPTIONS=ignore_noninstrumented_modules=1;HWLOC_HIDE_ERRORS=2"
PASS_REGULAR_EXPRESSION "LAMMPS \\([0-9]+ [A-Za-z]+ 2[0-9][0-9][0-9]( - Update [0-9]+)?\\)")
endif()