add kimplugin source and CMake based build support

This commit is contained in:
Axel Kohlmeyer
2022-04-07 11:51:52 -04:00
parent b4cc158981
commit 9b969648d5
5 changed files with 276 additions and 5 deletions

View File

@ -262,3 +262,24 @@ A plugin may be registered under an existing style name. In that case
the plugin will override the existing code. This can be used to modify
the behavior of existing styles or to debug new versions of them without
having to re-compile or re-install all of LAMMPS.
Compiling plugins
^^^^^^^^^^^^^^^^^
Plugins need to be compiled with the same compilers and libraries
(e.g. MPI) and compilation settings (MPI on/off, OpenMP, integer sizes)
as the LAMMPS executable and library. Otherwise the plugin will likely
not load due to mismatches in the function signatures (LAMMPS is C++ so
scope, type, and number of arguments are encoded into the symbol names
and thus differences in them will lead to failed plugin load commands.
Compilation of the plugin can be done managed via both, CMake or
traditional GNU makefiles. Some examples that can be used as a template
are in the ``examples/plugins`` folder. The CMake script code has some
small adjustments to allow building he plugins for running unit tests
with them. Another example that converts the KIM package into a plugin
can be found in the ``examples/kim/plugin`` folder. No changes to the
sources of the KIM package themselves are needed; only the plugin
interface and loader code needs to be added. This example only supports
building with CMake, but is probably a more typical example. To compile
you need to run CMake with -DLAMMPS_SOURCE_DIR=<path/to/lammps/src/folder>.
Other configuration setting are identical to those for compiling LAMMPS.

View File

@ -70,12 +70,11 @@ Restrictions
""""""""""""
The *plugin* command is part of the PLUGIN package. It is
only enabled if LAMMPS was built with that package.
See the :doc:`Build package <Build_package>` page for
more info. Plugins are not available on Windows.
only enabled if LAMMPS was built with that package. See
the :doc:`Build package <Build_package>` page for more info.
If plugins access functions or classes from a package, LAMMPS must
have been compiled with that package included.
If plugins access functions or classes from a package,
LAMMPS must have been compiled with that package included.
Plugins are dependent on the LAMMPS binary interface (ABI)
and particularly the MPI library used. So they are not guaranteed

View File

@ -0,0 +1,109 @@
##########################################
# CMake build system for plugin examples.
# The is meant to be used as a template for plugins that are
# distributed independent from the LAMMPS package.
##########################################
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(kimplugin VERSION 1.0 LANGUAGES CXX)
set(LAMMPS_SOURCE_DIR "" CACHE PATH "Location of LAMMPS sources folder")
if(NOT LAMMPS_SOURCE_DIR)
message(FATAL_ERROR "Must set LAMMPS_SOURCE_DIR")
endif()
# 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)
add_compile_options(/Zc:__cplusplus)
add_compile_options(/wd4244)
add_compile_options(/wd4267)
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
endif()
# C++11 is required
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Need -restrict with Intel compilers
if(CMAKE_CXX_COMPILER_ID STREQUAL "Intel")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -restrict")
endif()
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR})
include(CheckIncludeFileCXX)
include(LAMMPSInterfaceCXX)
##########################
# building the plugins
add_library(kimplugin MODULE kimplugin.cpp ${LAMMPS_SOURCE_DIR}/KIM/pair_kim.cpp
${LAMMPS_SOURCE_DIR}/KIM/fix_store_kim.cpp ${LAMMPS_SOURCE_DIR}/KIM/kim_command.cpp
${LAMMPS_SOURCE_DIR}/KIM/kim_init.cpp ${LAMMPS_SOURCE_DIR}/KIM/kim_interactions.cpp
${LAMMPS_SOURCE_DIR}/KIM/kim_param.cpp ${LAMMPS_SOURCE_DIR}/KIM/kim_property.cpp
${LAMMPS_SOURCE_DIR}/KIM/kim_query.cpp ${LAMMPS_SOURCE_DIR}/KIM/kim_units.cpp)
target_link_libraries(kimplugin PRIVATE lammps)
target_include_directories(kimplugin PRIVATE ${LAMMPS_SOURCE_DIR}/KIM)
set_target_properties(kimplugin PROPERTIES PREFIX "" SUFFIX ".so")
set(KIM-API_MIN_VERSION 2.1.3)
find_package(PkgConfig REQUIRED)
if(KIM-API_FOUND AND KIM-API_VERSION VERSION_GREATER_EQUAL 2.2.0)
# For kim-api >= 2.2.0
find_package(KIM-API 2.2.0 CONFIG REQUIRED)
target_link_libraries(kimplugin PRIVATE KIM-API::kim-api)
else()
# For kim-api 2.1.3 (consistent with previous version of this file)
find_package(PkgConfig REQUIRED)
pkg_check_modules(KIM-API REQUIRED IMPORTED_TARGET libkim-api>=${KIM-API_MIN_VERSION})
target_link_libraries(kimplugin PRIVATE PkgConfig::KIM-API)
endif()
##########################
# need libcurl
find_package(CURL)
if(CURL_FOUND)
if(CMAKE_VERSION VERSION_LESS 3.12)
target_include_directories(kimplugin PRIVATE ${CURL_INCLUDE_DIRS})
target_link_libraries(kimplugin PRIVATE ${CURL_LIBRARIES})
else()
target_link_libraries(kimplugin PRIVATE CURL::libcurl)
endif()
target_compile_definitions(kimplugin PRIVATE -DLMP_KIM_CURL)
set(LMP_DEBUG_CURL OFF CACHE STRING "Set libcurl verbose mode on/off. If on, it displays a lot of verbose information about its operations.")
mark_as_advanced(LMP_DEBUG_CURL)
if(LMP_DEBUG_CURL)
target_compile_definitions(kimplugin PRIVATE -DLMP_DEBUG_CURL)
endif()
set(LMP_NO_SSL_CHECK OFF CACHE STRING "Tell libcurl to not verify the peer. If on, the connection succeeds regardless of the names in the certificate. Insecure - Use with caution!")
mark_as_advanced(LMP_NO_SSL_CHECK)
if(LMP_NO_SSL_CHECK)
target_compile_definitions(kimplugin PRIVATE -DLMP_NO_SSL_CHECK)
endif()
endif()
# MacOS seems to need this
if(CMAKE_SYSTEM_NAME STREQUAL Darwin)
set_target_properties(kimplugin PROPERTIES LINK_FLAGS "-Wl,-undefined,dynamic_lookup")
elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows")
# tell CMake to export all symbols to a .dll on Windows with special case for MinGW cross-compilers
set_target_properties(kimplugin.so PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS TRUE)
if(CMAKE_CROSSCOMPILING)
set_target_properties(kimplugin PROPERTIES LINK_FLAGS "-Wl,--export-all-symbols")
endif()
else()
set_target_properties(kimplugin PROPERTIES LINK_FLAGS "-rdynamic")
endif()

View File

@ -0,0 +1,88 @@
# Cmake script code to define the LAMMPS C++ interface
# settings required for building LAMMPS plugins
################################################################################
# helper function
function(validate_option name values)
string(TOLOWER ${${name}} needle_lower)
string(TOUPPER ${${name}} needle_upper)
list(FIND ${values} ${needle_lower} IDX_LOWER)
list(FIND ${values} ${needle_upper} IDX_UPPER)
if(${IDX_LOWER} LESS 0 AND ${IDX_UPPER} LESS 0)
list_to_bulletpoints(POSSIBLE_VALUE_LIST ${${values}})
message(FATAL_ERROR "\n########################################################################\n"
"Invalid value '${${name}}' for option ${name}\n"
"\n"
"Possible values are:\n"
"${POSSIBLE_VALUE_LIST}"
"########################################################################")
endif()
endfunction(validate_option)
#################################################################################
# LAMMPS C++ interface. We only need the header related parts.
add_library(lammps INTERFACE)
target_include_directories(lammps INTERFACE ${LAMMPS_SOURCE_DIR})
if((CMAKE_SYSTEM_NAME STREQUAL "Windows") AND CMAKE_CROSSCOMPILING)
target_link_libraries(lammps INTERFACE ${CMAKE_BINARY_DIR}/../liblammps.dll.a)
endif()
################################################################################
# MPI configuration
if(NOT CMAKE_CROSSCOMPILING)
set(MPI_CXX_SKIP_MPICXX TRUE)
find_package(MPI QUIET)
option(BUILD_MPI "Build MPI version" ${MPI_FOUND})
else()
option(BUILD_MPI "Build MPI version" OFF)
endif()
if(BUILD_MPI)
find_package(MPI REQUIRED)
option(LAMMPS_LONGLONG_TO_LONG "Workaround if your system or MPI version does not recognize 'long long' data types" OFF)
if(LAMMPS_LONGLONG_TO_LONG)
target_compile_definitions(lammps INTERFACE -DLAMMPS_LONGLONG_TO_LONG)
endif()
target_link_libraries(lammps INTERFACE MPI::MPI_CXX)
else()
target_include_directories(lammps INTERFACE "${LAMMPS_SOURCE_DIR}/STUBS")
endif()
set(LAMMPS_SIZES "smallbig" CACHE STRING "LAMMPS integer sizes (smallsmall: all 32-bit, smallbig: 64-bit #atoms #timesteps, bigbig: also 64-bit imageint, 64-bit atom ids)")
set(LAMMPS_SIZES_VALUES smallbig bigbig smallsmall)
set_property(CACHE LAMMPS_SIZES PROPERTY STRINGS ${LAMMPS_SIZES_VALUES})
validate_option(LAMMPS_SIZES LAMMPS_SIZES_VALUES)
string(TOUPPER ${LAMMPS_SIZES} LAMMPS_SIZES)
target_compile_definitions(lammps INTERFACE -DLAMMPS_${LAMMPS_SIZES})
################################################################################
# detect if we may enable OpenMP support by default
set(BUILD_OMP_DEFAULT OFF)
find_package(OpenMP QUIET)
if(OpenMP_FOUND)
check_include_file_cxx(omp.h HAVE_OMP_H_INCLUDE)
if(HAVE_OMP_H_INCLUDE)
set(BUILD_OMP_DEFAULT ON)
endif()
endif()
option(BUILD_OMP "Build with OpenMP support" ${BUILD_OMP_DEFAULT})
if(BUILD_OMP)
find_package(OpenMP REQUIRED)
check_include_file_cxx(omp.h HAVE_OMP_H_INCLUDE)
if(NOT HAVE_OMP_H_INCLUDE)
message(FATAL_ERROR "Cannot find the 'omp.h' header file required for full OpenMP support")
endif()
if (((CMAKE_CXX_COMPILER_ID STREQUAL "GNU") AND (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 9.0)) OR
(CMAKE_CXX_COMPILER_ID STREQUAL "PGI") OR
((CMAKE_CXX_COMPILER_ID STREQUAL "Clang") AND (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 10.0)) OR
((CMAKE_CXX_COMPILER_ID STREQUAL "Intel") AND (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.0)))
# GCC 9.x and later plus Clang 10.x and later implement strict OpenMP 4.0 semantics for consts.
# Intel 18.0 was tested to support both, so we switch to OpenMP 4+ from 19.x onward to be safe.
target_compile_definitions(lammps INTERFACE -DLAMMPS_OMP_COMPAT=4)
else()
target_compile_definitions(lammps INTERFACE -DLAMMPS_OMP_COMPAT=3)
endif()
target_link_libraries(lammps INTERFACE OpenMP::OpenMP_CXX)
endif()

View File

@ -0,0 +1,54 @@
#include "lammpsplugin.h"
#include "version.h"
#include "pair_kim.h"
#include "fix_store_kim.h"
#include "kim_command.h"
using namespace LAMMPS_NS;
static Pair *pair_kim_creator(LAMMPS *lmp)
{
return new PairKIM(lmp);
}
static Fix *fix_store_kim_creator(LAMMPS *lmp, int argc, char **argv)
{
return new FixStoreKIM(lmp, argc, argv);
}
static Command *kim_command_creator(LAMMPS *lmp)
{
return new KimCommand(lmp);
}
extern "C" void lammpsplugin_init(void *lmp, void *handle, void *regfunc)
{
lammpsplugin_t plugin;
lammpsplugin_regfunc register_plugin = (lammpsplugin_regfunc) regfunc;
// register kim pair style
plugin.version = LAMMPS_VERSION;
plugin.style = "pair";
plugin.name = "kim";
plugin.info = "KIM plugin pair style v1.0";
plugin.author = "Axel Kohlmeyer (akohlmey@gmail.com)";
plugin.creator.v1 = (lammpsplugin_factory1 *) &pair_kim_creator;
plugin.handle = handle;
(*register_plugin)(&plugin, lmp);
// register fix STORE/KIM only need to update changed fields
plugin.style = "fix";
plugin.name = "STORE/KIM";
plugin.info = "Internal settings storage for KIM fix style v1.0";
plugin.creator.v2 = (lammpsplugin_factory2 *) &fix_store_kim_creator;
(*register_plugin)(&plugin, lmp);
// register KIM command
plugin.style = "command";
plugin.name = "kim";
plugin.info = "kim command style v1.0";
plugin.creator.v1 = (lammpsplugin_factory1 *) &kim_command_creator;
(*register_plugin)(&plugin, lmp);
}