Merge remote-tracking branch 'github/master' into collected-small-changes

This commit is contained in:
Axel Kohlmeyer 2021-04-02 16:08:51 -04:00
commit c62b1b1050
No known key found for this signature in database
GPG Key ID: D9B44E93BF0C375A
60 changed files with 3797 additions and 38 deletions

View File

@ -113,7 +113,7 @@ option(CMAKE_VERBOSE_MAKEFILE "Generate verbose Makefiles" OFF)
set(STANDARD_PACKAGES ASPHERE BODY CLASS2 COLLOID COMPRESS DIPOLE
GRANULAR KSPACE LATTE MANYBODY MC MESSAGE MISC MLIAP MOLECULE PERI POEMS
QEQ REPLICA RIGID SHOCK SPIN SNAP SRD KIM PYTHON MSCG MPIIO VORONOI
PLUGIN QEQ REPLICA RIGID SHOCK SPIN SNAP SRD KIM PYTHON MSCG MPIIO VORONOI
USER-ADIOS USER-ATC USER-AWPMD USER-BOCS USER-CGDNA USER-MESODPD USER-CGSDK
USER-COLVARS USER-DIFFRACTION USER-DPD USER-DRUDE USER-EFF USER-FEP USER-H5MD
USER-LB USER-MANIFOLD USER-MEAMC USER-MESONT USER-MGPT USER-MISC USER-MOFFF
@ -533,6 +533,18 @@ foreach(PKG_WITH_INCL CORESHELL QEQ USER-OMP USER-SDPD KOKKOS OPT USER-INTEL GPU
endif()
endforeach()
if(PKG_PLUGIN)
if(BUILD_SHARED_LIBS)
target_compile_definitions(lammps PRIVATE -DLMP_PLUGIN)
else()
message(WARNING "Plugin loading will not work unless BUILD_SHARED_LIBS is enabled")
endif()
# link with -ldl or equivalent for plugin loading; except on Windows
if(NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
target_link_libraries(lammps PRIVATE ${CMAKE_DL_LIBS})
endif()
endif()
######################################################################
# the windows version of LAMMPS requires a couple extra libraries
# and the MPI library - if use - has to be linked right before those

View File

@ -2,8 +2,4 @@ set(MOLFILE_INCLUDE_DIR "${LAMMPS_LIB_SOURCE_DIR}/molfile" CACHE STRING "Path to
set(MOLFILE_INCLUDE_DIRS "${MOLFILE_INCLUDE_DIR}")
add_library(molfile INTERFACE)
target_include_directories(molfile INTERFACE ${MOLFILE_INCLUDE_DIRS})
# no need to link with -ldl on windows
if(NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
target_link_libraries(molfile INTERFACE ${CMAKE_DL_LIBS})
endif()
target_link_libraries(lammps PRIVATE molfile)

View File

@ -4,7 +4,7 @@
set(ALL_PACKAGES ASPHERE BODY CLASS2 COLLOID COMPRESS CORESHELL DIPOLE
GRANULAR KSPACE MANYBODY MC MISC MLIAP MOLECULE OPT PERI
POEMS PYTHON QEQ REPLICA RIGID SHOCK SNAP SPIN SRD VORONOI
PLUGIN POEMS PYTHON QEQ REPLICA RIGID SHOCK SNAP SPIN SRD VORONOI
USER-BOCS USER-CGDNA USER-CGSDK USER-COLVARS USER-DIFFRACTION
USER-DPD USER-DRUDE USER-EFF USER-FEP USER-MEAMC USER-MESODPD
USER-MISC USER-MOFFF USER-OMP USER-PHONON USER-REACTION

View File

@ -86,6 +86,7 @@ An alphabetic list of all general LAMMPS commands.
* :doc:`pair_style <pair_style>`
* :doc:`pair_write <pair_write>`
* :doc:`partition <partition>`
* :doc:`plugin <plugin>`
* :doc:`prd <prd>`
* :doc:`print <print>`
* :doc:`processors <processors>`

View File

@ -14,6 +14,7 @@ of time and requests from the LAMMPS user community.
Developer_flow
Developer_write
Developer_notes
Developer_plugins
Developer_unittest
Classes
Developer_utils

View File

@ -0,0 +1,258 @@
Writing plugins
---------------
Plugins provide a mechanism to add functionality to a LAMMPS executable
without recompiling LAMMPS. The functionality for this and the
:doc:`plugin command <plugin>` are implemented in the
:ref:`PLUGIN package <PKG-PLUGIN>` which must be installed to use plugins.
Plugins use the operating system's capability to load dynamic shared
object (DSO) files in a way similar shared libraries and then reference
specific functions in those DSOs. Any DSO file with plugins has to include
an initialization function with a specific name, "lammpsplugin_init", that
has to follow specific rules described below. When loading the DSO with
the "plugin" command, this function is looked up and called and will then
register the contained plugin(s) with LAMMPS.
From the programmer perspective this can work because of the object
oriented design of LAMMPS where all pair style commands are derived from
the class Pair, all fix style commands from the class Fix and so on and
usually only functions present in those base classes are called
directly. When a :doc:`pair_style` command or :doc:`fix` command is
issued a new instance of such a derived class is created. This is done
by a so-called factory function which is mapped to the style name. Thus
when, for example, the LAMMPS processes the command ``pair_style lj/cut
2.5``, LAMMPS will look up the factory function for creating the
``PairLJCut`` class and then execute it. The return value of that
function is a ``Pair *`` pointer and the pointer will be assigned to the
location for the currently active pair style.
A DSO file with a plugin thus has to implement such a factory function
and register it with LAMMPS so that it gets added to the map of available
styles of the given category. To register a plugin with LAMMPS an
initialization function has to be present in the DSO file called
``lammpsplugin_init`` which is called with three ``void *`` arguments:
a pointer to the current LAMMPS instance, a pointer to the opened DSO
handle, and a pointer to the registration function. The registration
function takes two arguments: a pointer to a ``lammpsplugin_t`` struct
with information about the plugin and a pointer to the current LAMMPS
instance. Please see below for an example of how the registration is
done.
Members of ``lammpsplugin_t``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. list-table::
:header-rows: 1
:widths: auto
* - Member
- Description
* - version
- LAMMPS Version string the plugin was compiled for
* - style
- Style of the plugin (pair, bond, fix, command, etc.)
* - name
- Name of the plugin style
* - info
- String with information about the plugin
* - author
- String with the name and email of the author
* - creator.v1
- Pointer to factory function for pair, bond, angle, dihedral, or improper styles
* - creator.v2
- Pointer to factory function for compute, fix, or region styles
* - creator.v3
- Pointer to factory function for command styles
* - handle
- Pointer to the open DSO file handle
Only one of the three alternate creator entries can be used at a time
and which of those is determined by the style of plugin. The "creator.v1"
element is for factory functions of supported styles computing forces (i.e.
pair, bond, angle, dihedral, or improper styles) and the function takes
as single argument the pointer to the LAMMPS instance. The factory function
is cast to the ``lammpsplugin_factory1`` type before assignment. The
"creator.v2" element is for factory functions creating an instance of
a fix, compute, or region style and takes three arguments: a pointer to
the LAMMPS instance, an integer with the length of the argument list and
a ``char **`` pointer to the list of arguments. The factory function pointer
needs to be cast to the ``lammpsplugin_factory2`` type before assignment.
The "creator.v3" element takes the same arguments as "creator.v3" but is
specific to creating command styles: the factory function has to instantiate
the command style locally passing the LAMMPS pointer as argument and then
call its "command" member function with the number and list of arguments.
The factory function pointer needs to be cast to the
``lammpsplugin_factory3`` type before assignment.
Pair style example
^^^^^^^^^^^^^^^^^^
As an example, a hypothetical pair style plugin "morse2" implemented in
a class ``PairMorse2`` in the files ``pair_morse2.h`` and
``pair_morse2.cpp`` with the factory function and initialization
function would look like this:
.. code-block:: C++
#include "lammpsplugin.h"
#include "version.h"
#include "pair_morse2.h"
using namespace LAMMPS_NS;
static Pair *morse2creator(LAMMPS *lmp)
{
return new PairMorse2(lmp);
}
extern "C" void lammpsplugin_init(void *lmp, void *handle, void *regfunc)
{
lammpsplugin_regfunc register_plugin = (lammpsplugin_regfunc) regfunc;
lammpsplugin_t plugin;
plugin.version = LAMMPS_VERSION;
plugin.style = "pair";
plugin.name = "morse2";
plugin.info = "Morse2 variant pair style v1.0";
plugin.author = "Axel Kohlmeyer (akohlmey@gmail.com)";
plugin.creator.v1 = (lammpsplugin_factory1 *) &morse2creator;
plugin.handle = handle;
(*register_plugin)(&plugin,lmp);
}
The factory function in this example is called ``morse2creator()``. It
receives a pointer to the LAMMPS class as only argument and thus has to
be assigned to the *creator.v1* member of the plugin struct and cast to the
``lammpsplugin_factory1`` pointer type. It returns a
pointer to the allocated class instance derived from the ``Pair`` class.
This function may be declared static to avoid clashes with other plugins.
The name of the derived class, ``PairMorse2``, must be unique inside
the entire LAMMPS executable.
Fix style example
^^^^^^^^^^^^^^^^^
If the factory function would be for a fix or compute, which take three
arguments (a pointer to the LAMMPS class, the number of arguments and the
list of argument strings), then the pointer type is ``lammpsplugin_factory2``
and it must be assigned to the *creator.v2* member of the plugin struct.
Below is an example for that:
.. code-block:: C++
#include "lammpsplugin.h"
#include "version.h"
#include "fix_nve2.h"
using namespace LAMMPS_NS;
static Fix *nve2creator(LAMMPS *lmp, int argc, char **argv)
{
return new FixNVE2(lmp,argc,argv);
}
extern "C" void lammpsplugin_init(void *lmp, void *handle, void *regfunc)
{
lammpsplugin_regfunc register_plugin = (lammpsplugin_regfunc) regfunc;
lammpsplugin_t plugin;
plugin.version = LAMMPS_VERSION;
plugin.style = "fix";
plugin.name = "nve2";
plugin.info = "NVE2 variant fix style v1.0";
plugin.author = "Axel Kohlmeyer (akohlmey@gmail.com)";
plugin.creator.v2 = (lammpsplugin_factory2 *) &nve2creator;
plugin.handle = handle;
(*register_plugin)(&plugin,lmp);
}
Command style example
^^^^^^^^^^^^^^^^^^^^^
For command styles there is a third variant of factory function as
demonstrated in the following example, which also shows that the
implementation of the plugin class may also be within the same
file as the plugin interface code:
.. code-block:: C++
#include "lammpsplugin.h"
#include "comm.h"
#include "error.h"
#include "pointers.h"
#include "version.h"
#include <cstring>
namespace LAMMPS_NS {
class Hello : protected Pointers {
public:
Hello(class LAMMPS *lmp) : Pointers(lmp) {};
void command(int, char **);
};
}
using namespace LAMMPS_NS;
void Hello::command(int argc, char **argv)
{
if (argc != 1) error->all(FLERR,"Illegal hello command");
if (comm->me == 0)
utils::logmesg(lmp,fmt::format("Hello, {}!\n",argv[0]));
}
static void hellocreator(LAMMPS *lmp, int argc, char **argv)
{
Hello hello(lmp);
hello.command(argc,argv);
}
extern "C" void lammpsplugin_init(void *lmp, void *handle, void *regfunc)
{
lammpsplugin_t plugin;
lammpsplugin_regfunc register_plugin = (lammpsplugin_regfunc) regfunc;
plugin.version = LAMMPS_VERSION;
plugin.style = "command";
plugin.name = "hello";
plugin.info = "Hello world command v1.0";
plugin.author = "Axel Kohlmeyer (akohlmey@gmail.com)";
plugin.creator.v3 = (lammpsplugin_factory3 *) &hellocreator;
plugin.handle = handle;
(*register_plugin)(&plugin,lmp);
}
Additional Details
^^^^^^^^^^^^^^^^^^
The initialization function **must** be called ``lammpsplugin_init``, it
**must** have C bindings and it takes three void pointers as arguments.
The first is a pointer to the LAMMPS class that calls it and it needs to
be passed to the registration function. The second argument is a
pointer to the internal handle of the DSO file, this needs to be added
to the plugin info struct, so that the DSO can be closed and unloaded
when all its contained plugins are unloaded. The third argument is a
function pointer to the registration function and needs to be stored
in a variable of ``lammpsplugin_regfunc`` type and then called with a
pointer to the ``lammpsplugin_t`` struct and the pointer to the LAMMPS
instance as arguments to register a single plugin. There may be multiple
calls to multiple plugins in the same initialization function.
To register a plugin a struct of the ``lammpsplugin_t`` needs to be filled
with relevant info: current LAMMPS version string, kind of style, name of
style, info string, author string, pointer to factory function, and the
DSO handle. The registration function is called with a pointer to the address
of this struct and the pointer of the LAMMPS class. The registration function
will then add the factory function of the plugin style to the respective
style map under the provided name. It will also make a copy of the struct
in a list of all loaded plugins and update the reference counter for loaded
plugins from this specific DSO file.
The pair style itself (i.e. the PairMorse2 class in this example) can be
written just like any other pair style that is included in LAMMPS. For
a plugin, the use of the ``PairStyle`` macro in the section encapsulated
by ``#ifdef PAIR_CLASS`` is not needed, since the mapping of the class
name to the style name is done by the plugin registration function with
the information from the ``lammpsplugin_t`` struct. It may be included
in case the new code is intended to be later included in LAMMPS directly.

View File

@ -50,6 +50,7 @@ page gives those details.
* :ref:`MSCG <PKG-MSCG>`
* :ref:`OPT <PKG-OPT>`
* :ref:`PERI <PKG-PERI>`
* :ref:`PLUGIN <PKG-PLUGIN>`
* :ref:`POEMS <PKG-POEMS>`
* :ref:`PYTHON <PKG-PYTHON>`
* :ref:`QEQ <PKG-QEQ>`
@ -843,6 +844,28 @@ Foster (UTSA).
----------
.. _PKG-PLUGIN:
PLUGIN package
--------------
**Contents:**
A :doc:`plugin <plugin>` command that can load and unload several
kind of styles in LAMMPS from shared object files at runtime without
having to recompile and relink LAMMPS.
**Authors:** Axel Kohlmeyer (Temple U)
**Supporting info:**
* src/PLUGIN: filenames -> commands
* :doc:`plugin command <plugin>`
* :doc:`Information on writing plugins <Developer_plugins>`
* examples/plugin
----------
.. _PKG-POEMS:
POEMS package

View File

@ -77,6 +77,7 @@ Commands
pair_style
pair_write
partition
plugin
prd
print
processors

90
doc/src/plugin.rst Normal file
View File

@ -0,0 +1,90 @@
.. index:: plugin
plugin command
==============
Syntax
""""""
.. parsed-literal::
plugin command args
* command = *load* or *unload* or *list* or *clear*
* args = list of arguments for a particular plugin command
.. parsed-literal::
*load* file = load plugin(s) from shared object in *file*
*unload* style name = unload plugin *name* of style *style*
*style* = *pair* or *bond* or *angle* or *dihedral* or *improper* or *compute* or *fix* or *region* or *command*
*list* = print a list of currently loaded plugins
*clear* = unload all currently loaded plugins
Examples
""""""""
.. code-block:: LAMMPS
plugin load morse2plugin.so
plugin unload pair morse2/omp
plugin unload command hello
plugin list
plugin clear
Description
"""""""""""
The plugin command allows to load (and unload) additional styles and
commands into a LAMMPS binary from so-called dynamic shared object (DSO)
files. This enables to add new functionality to an existing LAMMPS
binary without having to recompile and link the entire executable.
The *load* command will load and initialize all plugins contained in the
plugin DSO with the given filename. A message with information the
plugin style and name and more will be printed. Individual DSO files
may contain multiple plugins. More details about how to write and
compile the plugin DSO is given in programmer's guide part of the manual
under :doc:`Developer_plugins`.
The *unload* command will remove the given style or the given name from
the list of available styles. If the plugin style is currently in use,
that style instance will be deleted.
The *list* command will print a list of the loaded plugins and their
styles and names.
The *clear* command will unload all currently loaded plugins.
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>` doc page for
more info. Plugins are not available on Windows.
For the loading of plugins to work the LAMMPS library must be
:ref:`compiled as a shared library <library>`. 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
to work when the plugin was compiled with a different MPI library
or different compilation settings or a different LAMMPS version.
There are no checks, so if there is a mismatch the plugin object
will either not load or data corruption and crashes may happen.
Related commands
""""""""""""""""
none
Default
"""""""
none

View File

@ -1588,6 +1588,7 @@ lammps
Lammps
LAMMPS
lammpsplot
lammpsplugin
Lampis
Lamoureux
Lanczos

1
examples/plugins/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/build*

View File

@ -0,0 +1,68 @@
##########################################
# 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(plugins VERSION 1.0 LANGUAGES CXX)
# NOTE: the next line should be commented out when used outside of the LAMMPS package
get_filename_component(LAMMPS_SOURCE_DIR ${PROJECT_SOURCE_DIR}/../../src ABSOLUTE)
set(LAMMPS_HEADER_DIR ${LAMMPS_SOURCE_DIR} CACHE PATH "Location of LAMMPS headers")
if(NOT LAMMPS_HEADER_DIR)
message(FATAL_ERROR "Must set LAMMPS_HEADER_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()
# C++11 is required
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# bail out on windows
if(CMAKE_SYSTEM_NAME STREQUAL Windows)
message(FATAL_ERROR "LAMMPS plugins are currently not supported on Windows")
endif()
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR})
include(CheckIncludeFileCXX)
include(LAMMPSInterfaceCXX)
##########################
# building the plugins
add_library(morse2plugin MODULE morse2plugin.cpp pair_morse2.cpp pair_morse2_omp.cpp)
target_include_directories(morse2plugin PRIVATE "${LAMMPS_HEADER_DIR}/USER-OMP")
target_link_libraries(morse2plugin PRIVATE lammps)
add_library(nve2plugin MODULE nve2plugin.cpp fix_nve2.cpp)
target_link_libraries(nve2plugin PRIVATE lammps)
add_library(helloplugin MODULE helloplugin.cpp)
target_link_libraries(helloplugin PRIVATE lammps)
add_library(zero2plugin MODULE zero2plugin.cpp pair_zero2.cpp bond_zero2.cpp
angle_zero2.cpp dihedral_zero2.cpp improper_zero2.cpp)
target_link_libraries(zero2plugin PRIVATE lammps)
set_target_properties(morse2plugin nve2plugin helloplugin zero2plugin PROPERTIES
PREFIX ""
LINK_FLAGS "-rdynamic")
# MacOS seems to need this
if(CMAKE_SYSTEM_NAME STREQUAL Darwin)
set_target_properties(morse2plugin nve2plugin helloplugin zero2plugin PROPERTIES
LINK_FLAGS "-Wl,-undefined,dynamic_lookup")
endif()

View File

@ -0,0 +1,86 @@
# 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_HEADER_DIR})
################################################################################
# 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,6 @@
CXX=mpicxx
CXXFLAGS=-I../../src -Wall -Wextra -O3 -fPIC -I../../src/USER-OMP -fopenmp
LD=$(CXX) -shared -rdynamic -fopenmp
DSOEXT=.so
include Makefile.common

View File

@ -0,0 +1,36 @@
default: morse2plugin$(DSOEXT) nve2plugin$(DSOEXT) helloplugin$(DSOEXT) zero2plugin$(DSOEXT)
helloplugin$(DSOEXT): helloplugin.o
$(LD) -o $@ $^
morse2plugin$(DSOEXT): morse2plugin.o pair_morse2.o pair_morse2_omp.o
$(LD) -o $@ $^
nve2plugin$(DSOEXT): nve2plugin.o fix_nve2.o
$(LD) -o $@ $^
zero2plugin$(DSOEXT): zero2plugin.o pair_zero2.o bond_zero2.o angle_zero2.o dihedral_zero2.o improper_zero2.o
$(LD) -o $@ $^
.cpp.o:
$(CXX) -o $@ $(CXXFLAGS) -c $<
helloplugin.o: helloplugin.cpp
pair_morse2.o: pair_morse2.cpp pair_morse2.h
pair_morse2_omp.o: pair_morse2_omp.cpp pair_morse2_omp.h pair_morse2.h
morse2plugin.o: morse2plugin.cpp pair_morse2.h pair_morse2_omp.h
fix_nve2.o: fix_nve2.cpp fix_nve2.h
nve2plugin.o: nve2plugin.cpp fix_nve2.h
pair_zero2.o: pair_zero2.cpp pair_zero2.h
bond_zero2.o: bond_zero2.cpp bond_zero2.h
angle_zero2.o: angle_zero2.cpp angle_zero2.h
dihedral_zero2.o: dihedral_zero2.cpp dihedral_zero2.h
improper_zero2.o: improper_zero2.cpp improper_zero2.h
zero2plugin.o: zero2plugin.cpp pair_zero2.h bond_zero2.h angle_zero2.h dihedral_zero2.h
clean:
rm -rf *~ *.so *.dylib *.o log.lammps CMakeCache.txt CMakeFiles

View File

@ -0,0 +1,6 @@
CXX=mpicxx
CXXFLAGS=-I../../src -Wall -Wextra -O3 -fPIC -I../../src/USER-OMP
LD=$(CXX) -bundle -rdynamic -Wl,-undefined,dynamic_lookup
DSOEXT=.dylib
include Makefile.common

View File

@ -0,0 +1,6 @@
CXX=g++
CXXFLAGS=-I../../src -I../../src/STUBS -Wall -Wextra -O3 -fPIC -I../../src/USER-OMP -fopenmp
LD=$(CXX) -shared -rdynamic -fopenmp
DSOEXT=.so
include Makefile.common

View File

@ -0,0 +1,152 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://lammps.sandia.gov/, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Carsten Svaneborg (SDU)
------------------------------------------------------------------------- */
#include "angle_zero2.h"
#include "atom.h"
#include "comm.h"
#include "math_const.h"
#include "memory.h"
#include "error.h"
#include <cstring>
using namespace LAMMPS_NS;
using namespace MathConst;
/* ---------------------------------------------------------------------- */
AngleZero2::AngleZero2(LAMMPS *lmp) : Angle(lmp), coeffflag(1) {}
/* ---------------------------------------------------------------------- */
AngleZero2::~AngleZero2()
{
if (allocated && !copymode) {
memory->destroy(setflag);
memory->destroy(theta0);
}
}
/* ---------------------------------------------------------------------- */
void AngleZero2::compute(int eflag, int vflag)
{
ev_init(eflag,vflag);
}
/* ---------------------------------------------------------------------- */
void AngleZero2::settings(int narg, char **arg)
{
if ((narg != 0) && (narg != 1))
error->all(FLERR,"Illegal angle_style command");
if (narg == 1) {
if (strcmp("nocoeff",arg[0]) == 0) coeffflag=0;
else error->all(FLERR,"Illegal angle_style command");
}
}
/* ---------------------------------------------------------------------- */
void AngleZero2::allocate()
{
allocated = 1;
int n = atom->nangletypes;
memory->create(theta0,n+1,"angle:theta0");
memory->create(setflag,n+1,"angle:setflag");
for (int i = 1; i <= n; i++) setflag[i] = 0;
}
/* ----------------------------------------------------------------------
set coeffs for one or more types
------------------------------------------------------------------------- */
void AngleZero2::coeff(int narg, char **arg)
{
if ((narg < 1) || (coeffflag && narg > 2))
error->all(FLERR,"Incorrect args for angle coefficients");
if (!allocated) allocate();
int ilo,ihi;
utils::bounds(FLERR,arg[0],1,atom->nangletypes,ilo,ihi,error);
double theta0_one = 0.0;
if (coeffflag && (narg == 2))
theta0_one = utils::numeric(FLERR,arg[1],false,lmp);
// convert theta0 from degrees to radians
int count = 0;
for (int i = ilo; i <= ihi; i++) {
setflag[i] = 1;
theta0[i] = theta0_one/180.0 * MY_PI;
count++;
}
if (count == 0) error->all(FLERR,"Incorrect args for angle coefficients");
}
/* ---------------------------------------------------------------------- */
double AngleZero2::equilibrium_angle(int i)
{
return theta0[i];
}
/* ----------------------------------------------------------------------
proc 0 writes out coeffs to restart file
------------------------------------------------------------------------- */
void AngleZero2::write_restart(FILE *fp) {
fwrite(&theta0[1],sizeof(double),atom->nangletypes,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads coeffs from restart file, bcasts them
------------------------------------------------------------------------- */
void AngleZero2::read_restart(FILE *fp)
{
allocate();
if (comm->me == 0) {
utils::sfread(FLERR,&theta0[1],sizeof(double),atom->nangletypes,fp,nullptr,error);
}
MPI_Bcast(&theta0[1],atom->nangletypes,MPI_DOUBLE,0,world);
for (int i = 1; i <= atom->nangletypes; i++) setflag[i] = 1;
}
/* ----------------------------------------------------------------------
proc 0 writes to data file
------------------------------------------------------------------------- */
void AngleZero2::write_data(FILE *fp)
{
for (int i = 1; i <= atom->nangletypes; i++)
fprintf(fp,"%d %g\n",i,theta0[i]/MY_PI*180.0);
}
/* ---------------------------------------------------------------------- */
double AngleZero2::single(int /*type*/, int /*i1*/, int /*i2*/, int /*i3*/)
{
return 0.0;
}

View File

@ -0,0 +1,57 @@
/* -*- c++ -*- ----------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#ifndef LMP_ANGLE_ZERO2_H
#define LMP_ANGLE_ZERO2_H
#include "angle.h"
namespace LAMMPS_NS {
class AngleZero2 : public Angle {
public:
AngleZero2(class LAMMPS *);
virtual ~AngleZero2();
virtual void compute(int, int);
virtual void coeff(int, char **);
virtual void settings(int, char **);
double equilibrium_angle(int);
void write_restart(FILE *);
void read_restart(FILE *);
void write_data(FILE *);
double single(int, int, int, int);
protected:
double *theta0;
int coeffflag;
void allocate();
};
}
#endif
/* ERROR/WARNING messages:
E: Illegal ... command
UNDOCUMENTED
E: Incorrect args for angle coefficients
Self-explanatory. Check the input script or data file.
*/

View File

@ -0,0 +1,161 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://lammps.sandia.gov/, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Carsten Svaneborg (SDU)
------------------------------------------------------------------------- */
#include "bond_zero2.h"
#include "atom.h"
#include "comm.h"
#include "error.h"
#include "memory.h"
#include <cstring>
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
BondZero2::BondZero2(LAMMPS *lmp) : Bond(lmp), coeffflag(1) {}
/* ---------------------------------------------------------------------- */
BondZero2::~BondZero2()
{
if (allocated && !copymode) {
memory->destroy(setflag);
memory->destroy(r0);
}
}
/* ---------------------------------------------------------------------- */
void BondZero2::compute(int eflag, int vflag)
{
ev_init(eflag,vflag);
}
/* ---------------------------------------------------------------------- */
void BondZero2::settings(int narg, char **arg)
{
if ((narg != 0) && (narg != 1))
error->all(FLERR,"Illegal bond_style command");
if (narg == 1) {
if (strcmp("nocoeff",arg[0]) == 0) coeffflag=0;
else error->all(FLERR,"Illegal bond_style command");
}
}
/* ---------------------------------------------------------------------- */
void BondZero2::allocate()
{
allocated = 1;
int n = atom->nbondtypes;
memory->create(r0,n+1,"bond:r0");
memory->create(setflag,n+1,"bond:setflag");
for (int i = 1; i <= n; i++) setflag[i] = 0;
}
/* ----------------------------------------------------------------------
set coeffs for one or more types
------------------------------------------------------------------------- */
void BondZero2::coeff(int narg, char **arg)
{
if ((narg < 1) || (coeffflag && narg > 2))
error->all(FLERR,"Incorrect args for bond coefficients");
if (!allocated) allocate();
int ilo,ihi;
utils::bounds(FLERR,arg[0],1,atom->nbondtypes,ilo,ihi,error);
double r0_one = 0.0;
if (coeffflag && (narg == 2))
r0_one = utils::numeric(FLERR,arg[1],false,lmp);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
setflag[i] = 1;
r0[i] = r0_one;
count++;
}
if (count == 0) error->all(FLERR,"Incorrect args for bond coefficients");
}
/* ----------------------------------------------------------------------
return an equilbrium bond length
------------------------------------------------------------------------- */
double BondZero2::equilibrium_distance(int i)
{
return r0[i];
}
/* ----------------------------------------------------------------------
proc 0 writes out coeffs to restart file
------------------------------------------------------------------------- */
void BondZero2::write_restart(FILE *fp) {
fwrite(&r0[1],sizeof(double),atom->nbondtypes,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads coeffs from restart file, bcasts them
------------------------------------------------------------------------- */
void BondZero2::read_restart(FILE *fp)
{
allocate();
if (comm->me == 0) {
utils::sfread(FLERR,&r0[1],sizeof(double),atom->nbondtypes,fp,nullptr,error);
}
MPI_Bcast(&r0[1],atom->nbondtypes,MPI_DOUBLE,0,world);
for (int i = 1; i <= atom->nbondtypes; i++) setflag[i] = 1;
}
/* ----------------------------------------------------------------------
proc 0 writes to data file
------------------------------------------------------------------------- */
void BondZero2::write_data(FILE *fp)
{
for (int i = 1; i <= atom->nbondtypes; i++)
fprintf(fp,"%d %g\n",i,r0[i]);
}
/* ---------------------------------------------------------------------- */
double BondZero2::single(int /*type*/, double /*rsq*/, int /*i*/, int /*j*/,
double & /*fforce*/)
{
return 0.0;
}
/* ---------------------------------------------------------------------- */
void *BondZero2::extract(const char *str, int &dim)
{
dim = 1;
if (strcmp(str,"r0")==0) return (void*) r0;
return nullptr;
}

View File

@ -0,0 +1,58 @@
/* -*- c++ -*- ----------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#ifndef LMP_BOND_ZERO2_H
#define LMP_BOND_ZERO2_H
#include "bond.h"
namespace LAMMPS_NS {
class BondZero2 : public Bond {
public:
BondZero2(class LAMMPS *);
virtual ~BondZero2();
virtual void compute(int, int);
virtual void settings(int, char **);
void coeff(int, char **);
double equilibrium_distance(int);
void write_restart(FILE *);
void read_restart(FILE *);
void write_data(FILE *);
double single(int, double, int, int, double &);
virtual void *extract(const char *, int &);
protected:
double *r0;
int coeffflag;
virtual void allocate();
};
}
#endif
/* ERROR/WARNING messages:
E: Illegal ... command
UNDOCUMENTED
E: Incorrect args for bond coefficients
Self-explanatory. Check the input script or data file.
*/

View File

@ -0,0 +1,121 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://lammps.sandia.gov/, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Carsten Svaneborg (SDU)
------------------------------------------------------------------------- */
#include "dihedral_zero2.h"
#include "atom.h"
#include "error.h"
#include "memory.h"
#include <cstring>
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
DihedralZero2::DihedralZero2(LAMMPS *lmp) : Dihedral(lmp), coeffflag(1)
{
writedata = 1;
}
/* ---------------------------------------------------------------------- */
DihedralZero2::~DihedralZero2()
{
if (allocated && !copymode) {
memory->destroy(setflag);
}
}
/* ---------------------------------------------------------------------- */
void DihedralZero2::compute(int eflag, int vflag)
{
ev_init(eflag,vflag);
}
/* ---------------------------------------------------------------------- */
void DihedralZero2::settings(int narg, char **arg)
{
if ((narg != 0) && (narg != 1))
error->all(FLERR,"Illegal dihedral_style command");
if (narg == 1) {
if (strcmp("nocoeff",arg[0]) == 0) coeffflag=0;
else error->all(FLERR,"Illegal dihedral_style command");
}
}
/* ---------------------------------------------------------------------- */
void DihedralZero2::allocate()
{
allocated = 1;
int n = atom->ndihedraltypes;
memory->create(setflag,n+1,"dihedral:setflag");
for (int i = 1; i <= n; i++) setflag[i] = 0;
}
/* ----------------------------------------------------------------------
set coeffs for one or more types
------------------------------------------------------------------------- */
void DihedralZero2::coeff(int narg, char **arg)
{
if ((narg < 1) || (coeffflag && narg > 1))
error->all(FLERR,"Incorrect args for dihedral coefficients");
if (!allocated) allocate();
int ilo,ihi;
utils::bounds(FLERR,arg[0],1,atom->ndihedraltypes,ilo,ihi,error);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
setflag[i] = 1;
count++;
}
if (count == 0) error->all(FLERR,"Incorrect args for dihedral coefficients");
}
/* ----------------------------------------------------------------------
proc 0 writes out coeffs to restart file
------------------------------------------------------------------------- */
void DihedralZero2::write_restart(FILE * /*fp*/) {}
/* ----------------------------------------------------------------------
proc 0 reads coeffs from restart file, bcasts them
------------------------------------------------------------------------- */
void DihedralZero2::read_restart(FILE * /*fp*/)
{
allocate();
for (int i = 1; i <= atom->ndihedraltypes; i++) setflag[i] = 1;
}
/* ----------------------------------------------------------------------
proc 0 writes to data file
------------------------------------------------------------------------- */
void DihedralZero2::write_data(FILE *fp) {
for (int i = 1; i <= atom->ndihedraltypes; i++)
fprintf(fp,"%d\n",i);
}

View File

@ -0,0 +1,57 @@
/* -*- c++ -*- ----------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
Identical to dihedral harmonic, except if all k's are zero the
force loop is skipped.
------------------------------------------------------------------------- */
#ifndef LMP_DIHEDRAL_ZERO2_H
#define LMP_DIHEDRAL_ZERO2_H
#include "dihedral.h"
namespace LAMMPS_NS {
class DihedralZero2 : public Dihedral {
public:
DihedralZero2(class LAMMPS *);
virtual ~DihedralZero2();
virtual void compute(int, int);
virtual void coeff(int, char **);
virtual void settings(int, char **);
void write_restart(FILE *);
void read_restart(FILE *);
void write_data(FILE *);
protected:
int coeffflag;
virtual void allocate();
};
}
#endif
/* ERROR/WARNING messages:
E: Illegal ... command
UNDOCUMENTED
E: Incorrect args for dihedral coefficients
UNDOCUMENTED
*/

View File

@ -0,0 +1,171 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://lammps.sandia.gov/, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "fix_nve2.h"
#include <cstring>
#include "atom.h"
#include "force.h"
#include "update.h"
#include "respa.h"
#include "error.h"
using namespace LAMMPS_NS;
using namespace FixConst;
/* ---------------------------------------------------------------------- */
FixNVE2::FixNVE2(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
if (strcmp(style,"nve/sphere") != 0 && narg < 3)
error->all(FLERR,"Illegal fix nve command");
dynamic_group_allow = 1;
time_integrate = 1;
}
/* ---------------------------------------------------------------------- */
int FixNVE2::setmask()
{
int mask = 0;
mask |= INITIAL_INTEGRATE;
mask |= FINAL_INTEGRATE;
mask |= INITIAL_INTEGRATE_RESPA;
mask |= FINAL_INTEGRATE_RESPA;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixNVE2::init()
{
dtv = update->dt;
dtf = 0.5 * update->dt * force->ftm2v;
if (strstr(update->integrate_style,"respa"))
step_respa = ((Respa *) update->integrate)->step;
}
/* ----------------------------------------------------------------------
allow for both per-type and per-atom mass
------------------------------------------------------------------------- */
void FixNVE2::initial_integrate(int /*vflag*/)
{
double dtfm;
// update v and x of atoms in group
double **x = atom->x;
double **v = atom->v;
double **f = atom->f;
double *rmass = atom->rmass;
double *mass = atom->mass;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (igroup == atom->firstgroup) nlocal = atom->nfirst;
if (rmass) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
dtfm = dtf / rmass[i];
v[i][0] += dtfm * f[i][0];
v[i][1] += dtfm * f[i][1];
v[i][2] += dtfm * f[i][2];
x[i][0] += dtv * v[i][0];
x[i][1] += dtv * v[i][1];
x[i][2] += dtv * v[i][2];
}
} else {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
dtfm = dtf / mass[type[i]];
v[i][0] += dtfm * f[i][0];
v[i][1] += dtfm * f[i][1];
v[i][2] += dtfm * f[i][2];
x[i][0] += dtv * v[i][0];
x[i][1] += dtv * v[i][1];
x[i][2] += dtv * v[i][2];
}
}
}
/* ---------------------------------------------------------------------- */
void FixNVE2::final_integrate()
{
double dtfm;
// update v of atoms in group
double **v = atom->v;
double **f = atom->f;
double *rmass = atom->rmass;
double *mass = atom->mass;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (igroup == atom->firstgroup) nlocal = atom->nfirst;
if (rmass) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
dtfm = dtf / rmass[i];
v[i][0] += dtfm * f[i][0];
v[i][1] += dtfm * f[i][1];
v[i][2] += dtfm * f[i][2];
}
} else {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
dtfm = dtf / mass[type[i]];
v[i][0] += dtfm * f[i][0];
v[i][1] += dtfm * f[i][1];
v[i][2] += dtfm * f[i][2];
}
}
}
/* ---------------------------------------------------------------------- */
void FixNVE2::initial_integrate_respa(int vflag, int ilevel, int /*iloop*/)
{
dtv = step_respa[ilevel];
dtf = 0.5 * step_respa[ilevel] * force->ftm2v;
// innermost level - NVE update of v and x
// all other levels - NVE update of v
if (ilevel == 0) initial_integrate(vflag);
else final_integrate();
}
/* ---------------------------------------------------------------------- */
void FixNVE2::final_integrate_respa(int ilevel, int /*iloop*/)
{
dtf = 0.5 * step_respa[ilevel] * force->ftm2v;
final_integrate();
}
/* ---------------------------------------------------------------------- */
void FixNVE2::reset_dt()
{
dtv = update->dt;
dtf = 0.5 * update->dt * force->ftm2v;
}

View File

@ -0,0 +1,58 @@
/* -*- c++ -*- ----------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#ifdef FIX_CLASS
FixStyle(nve2,FixNVE2)
#else
#ifndef LMP_FIX_NVE2_H
#define LMP_FIX_NVE2_H
#include "fix.h"
namespace LAMMPS_NS {
class FixNVE2 : public Fix {
public:
FixNVE2(class LAMMPS *, int, char **);
virtual ~FixNVE2() {}
int setmask();
virtual void init();
virtual void initial_integrate(int);
virtual void final_integrate();
virtual void initial_integrate_respa(int, int, int);
virtual void final_integrate_respa(int, int);
virtual void reset_dt();
protected:
double dtv,dtf;
double *step_respa;
int mass_require;
};
}
#endif
#endif
/* ERROR/WARNING messages:
E: Illegal ... command
Self-explanatory. Check the input script syntax and compare to the
documentation for the command. You can use -echo screen as a
command-line option when running LAMMPS to see the offending line.
*/

View File

@ -0,0 +1,47 @@
#include "lammpsplugin.h"
#include "comm.h"
#include "error.h"
#include "pointers.h"
#include "version.h"
#include <cstring>
namespace LAMMPS_NS {
class Hello : protected Pointers {
public:
Hello(class LAMMPS *lmp) : Pointers(lmp) {};
void command(int, char **);
};
}
using namespace LAMMPS_NS;
void Hello::command(int argc, char **argv)
{
if (argc != 1) error->all(FLERR,"Illegal hello command");
if (comm->me == 0)
utils::logmesg(lmp,fmt::format("Hello, {}!\n",argv[0]));
}
static void hellocreator(LAMMPS *lmp, int argc, char **argv)
{
Hello hello(lmp);
hello.command(argc,argv);
}
extern "C" void lammpsplugin_init(void *lmp, void *handle, void *regfunc)
{
lammpsplugin_t plugin;
lammpsplugin_regfunc register_plugin = (lammpsplugin_regfunc) regfunc;
plugin.version = LAMMPS_VERSION;
plugin.style = "command";
plugin.name = "hello";
plugin.info = "Hello world command v1.0";
plugin.author = "Axel Kohlmeyer (akohlmey@gmail.com)";
plugin.creator.v3 = (lammpsplugin_factory3 *) &hellocreator;
plugin.handle = handle;
(*register_plugin)(&plugin,lmp);
}

View File

@ -0,0 +1,122 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://lammps.sandia.gov/, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Carsten Svaneborg (SDU)
------------------------------------------------------------------------- */
#include "improper_zero2.h"
#include "atom.h"
#include "error.h"
#include "memory.h"
#include <cstring>
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
ImproperZero2::ImproperZero2(LAMMPS *lmp) : Improper(lmp), coeffflag(1)
{
writedata = 1;
}
/* ---------------------------------------------------------------------- */
ImproperZero2::~ImproperZero2()
{
if (allocated && !copymode) {
memory->destroy(setflag);
}
}
/* ---------------------------------------------------------------------- */
void ImproperZero2::compute(int eflag, int vflag)
{
ev_init(eflag,vflag);
}
/* ---------------------------------------------------------------------- */
void ImproperZero2::settings(int narg, char **arg)
{
if ((narg != 0) && (narg != 1))
error->all(FLERR,"Illegal improper_style command");
if (narg == 1) {
if (strcmp("nocoeff",arg[0]) == 0) coeffflag=0;
else error->all(FLERR,"Illegal improper_style command");
}
}
/* ---------------------------------------------------------------------- */
void ImproperZero2::allocate()
{
allocated = 1;
int n = atom->nimpropertypes;
memory->create(setflag,n+1,"improper:setflag");
for (int i = 1; i <= n; i++) setflag[i] = 0;
}
/* ----------------------------------------------------------------------
set coeffs for one or more types
------------------------------------------------------------------------- */
void ImproperZero2::coeff(int narg, char **arg)
{
if ((narg < 1) || (coeffflag && narg > 1))
error->all(FLERR,"Incorrect args for improper coefficients");
if (!allocated) allocate();
int ilo,ihi;
utils::bounds(FLERR,arg[0],1,atom->nimpropertypes,ilo,ihi,error);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
setflag[i] = 1;
count++;
}
if (count == 0) error->all(FLERR,"Incorrect args for improper coefficients");
}
/* ----------------------------------------------------------------------
proc 0 writes out coeffs to restart file
------------------------------------------------------------------------- */
void ImproperZero2::write_restart(FILE * /*fp*/) {}
/* ----------------------------------------------------------------------
proc 0 reads coeffs from restart file, bcasts them
------------------------------------------------------------------------- */
void ImproperZero2::read_restart(FILE * /*fp*/)
{
allocate();
for (int i = 1; i <= atom->nimpropertypes; i++) setflag[i] = 1;
}
/* ----------------------------------------------------------------------
proc 0 writes to data file
------------------------------------------------------------------------- */
void ImproperZero2::write_data(FILE *fp) {
for (int i = 1; i <= atom->nimpropertypes; i++)
fprintf(fp,"%d\n",i);
}

View File

@ -0,0 +1,53 @@
/* -*- c++ -*- ----------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#ifndef LMP_IMPROPER_ZERO2_H
#define LMP_IMPROPER_ZERO2_H
#include "improper.h"
namespace LAMMPS_NS {
class ImproperZero2 : public Improper {
public:
ImproperZero2(class LAMMPS *);
virtual ~ImproperZero2();
virtual void compute(int, int);
virtual void coeff(int, char **);
virtual void settings(int, char **);
void write_restart(FILE *);
void read_restart(FILE *);
void write_data(FILE *);
protected:
int coeffflag;
virtual void allocate();
};
}
#endif
/* ERROR/WARNING messages:
E: Illegal ... command
UNDOCUMENTED
E: Incorrect args for improper coefficients
Self-explanatory. Check the input script or data file.
*/

View File

@ -0,0 +1,43 @@
#include "lammpsplugin.h"
#include "version.h"
#include <cstring>
#include "pair_morse2.h"
#include "pair_morse2_omp.h"
using namespace LAMMPS_NS;
static Pair *morse2creator(LAMMPS *lmp)
{
return new PairMorse2(lmp);
}
static Pair *morse2ompcreator(LAMMPS *lmp)
{
return new PairMorse2OMP(lmp);
}
extern "C" void lammpsplugin_init(void *lmp, void *handle, void *regfunc)
{
lammpsplugin_t plugin;
lammpsplugin_regfunc register_plugin = (lammpsplugin_regfunc) regfunc;
// register plain morse2 pair style
plugin.version = LAMMPS_VERSION;
plugin.style = "pair";
plugin.name = "morse2";
plugin.info = "Morse2 variant pair style v1.0";
plugin.author = "Axel Kohlmeyer (akohlmey@gmail.com)";
plugin.creator.v1 = (lammpsplugin_factory1 *) &morse2creator;
plugin.handle = handle;
(*register_plugin)(&plugin,lmp);
// also register morse2/omp pair style. only need to update changed fields
plugin.name = "morse2/omp";
plugin.info = "Morse2 variant pair style for OpenMP v1.0";
plugin.creator.v1 = (lammpsplugin_factory1 *) &morse2ompcreator;
(*register_plugin)(&plugin,lmp);
}

View File

@ -0,0 +1,30 @@
#include "lammpsplugin.h"
#include "version.h"
#include <cstring>
#include "fix_nve2.h"
using namespace LAMMPS_NS;
static Fix *nve2creator(LAMMPS *lmp, int argc, char **argv)
{
return new FixNVE2(lmp, argc, argv);
}
extern "C" void lammpsplugin_init(void *lmp, void *handle, void *regfunc)
{
lammpsplugin_t plugin;
lammpsplugin_regfunc register_plugin = (lammpsplugin_regfunc) regfunc;
plugin.version = LAMMPS_VERSION;
plugin.style = "fix";
plugin.name = "nve2";
plugin.info = "NVE2 variant fix style v1.0";
plugin.author = "Axel Kohlmeyer (akohlmey@gmail.com)";
plugin.creator.v2 = (lammpsplugin_factory2 *) &nve2creator;
plugin.handle = handle;
(*register_plugin)(&plugin,lmp);
}

View File

@ -0,0 +1,359 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://lammps.sandia.gov/, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "pair_morse2.h"
#include <cmath>
#include <cstring>
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "neigh_list.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
PairMorse2::PairMorse2(LAMMPS *lmp) : Pair(lmp)
{
writedata = 1;
}
/* ---------------------------------------------------------------------- */
PairMorse2::~PairMorse2()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(cut);
memory->destroy(d0);
memory->destroy(alpha);
memory->destroy(r0);
memory->destroy(morse1);
memory->destroy(offset);
}
}
/* ---------------------------------------------------------------------- */
void PairMorse2::compute(int eflag, int vflag)
{
int i,j,ii,jj,inum,jnum,itype,jtype;
double xtmp,ytmp,ztmp,delx,dely,delz,evdwl,fpair;
double rsq,r,dr,dexp,factor_lj;
int *ilist,*jlist,*numneigh,**firstneigh;
evdwl = 0.0;
ev_init(eflag,vflag);
double **x = atom->x;
double **f = atom->f;
int *type = atom->type;
int nlocal = atom->nlocal;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
if (rsq < cutsq[itype][jtype]) {
r = sqrt(rsq);
dr = r - r0[itype][jtype];
dexp = exp(-alpha[itype][jtype] * dr);
fpair = factor_lj * morse1[itype][jtype] * (dexp*dexp - dexp) / r;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (newton_pair || j < nlocal) {
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
}
if (eflag) {
evdwl = d0[itype][jtype] * (dexp*dexp - 2.0*dexp) -
offset[itype][jtype];
evdwl *= factor_lj;
}
if (evflag) ev_tally(i,j,nlocal,newton_pair,
evdwl,0.0,fpair,delx,dely,delz);
}
}
}
if (vflag_fdotr) virial_fdotr_compute();
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairMorse2::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq,n+1,n+1,"pair:cutsq");
memory->create(cut,n+1,n+1,"pair:cut");
memory->create(d0,n+1,n+1,"pair:d0");
memory->create(alpha,n+1,n+1,"pair:alpha");
memory->create(r0,n+1,n+1,"pair:r0");
memory->create(morse1,n+1,n+1,"pair:morse1");
memory->create(offset,n+1,n+1,"pair:offset");
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairMorse2::settings(int narg, char **arg)
{
if (narg != 1) error->all(FLERR,"Illegal pair_style command");
cut_global = utils::numeric(FLERR,arg[0],false,lmp);
// reset cutoffs that have been explicitly set
if (allocated) {
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++)
if (setflag[i][j]) cut[i][j] = cut_global;
}
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairMorse2::coeff(int narg, char **arg)
{
if (narg < 5 || narg > 6)
error->all(FLERR,"Incorrect args for pair coefficients");
if (!allocated) allocate();
int ilo,ihi,jlo,jhi;
utils::bounds(FLERR,arg[0],1,atom->ntypes,ilo,ihi,error);
utils::bounds(FLERR,arg[1],1,atom->ntypes,jlo,jhi,error);
double d0_one = utils::numeric(FLERR,arg[2],false,lmp);
double alpha_one = utils::numeric(FLERR,arg[3],false,lmp);
double r0_one = utils::numeric(FLERR,arg[4],false,lmp);
double cut_one = cut_global;
if (narg == 6) cut_one = utils::numeric(FLERR,arg[5],false,lmp);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
for (int j = MAX(jlo,i); j <= jhi; j++) {
d0[i][j] = d0_one;
alpha[i][j] = alpha_one;
r0[i][j] = r0_one;
cut[i][j] = cut_one;
setflag[i][j] = 1;
count++;
}
}
if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairMorse2::init_one(int i, int j)
{
if (setflag[i][j] == 0) error->all(FLERR,"All pair coeffs are not set");
morse1[i][j] = 2.0*d0[i][j]*alpha[i][j];
if (offset_flag) {
double alpha_dr = -alpha[i][j] * (cut[i][j] - r0[i][j]);
offset[i][j] = d0[i][j] * (exp(2.0*alpha_dr) - 2.0*exp(alpha_dr));
} else offset[i][j] = 0.0;
d0[j][i] = d0[i][j];
alpha[j][i] = alpha[i][j];
r0[j][i] = r0[i][j];
morse1[j][i] = morse1[i][j];
offset[j][i] = offset[i][j];
return cut[i][j];
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairMorse2::write_restart(FILE *fp)
{
write_restart_settings(fp);
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
fwrite(&setflag[i][j],sizeof(int),1,fp);
if (setflag[i][j]) {
fwrite(&d0[i][j],sizeof(double),1,fp);
fwrite(&alpha[i][j],sizeof(double),1,fp);
fwrite(&r0[i][j],sizeof(double),1,fp);
fwrite(&cut[i][j],sizeof(double),1,fp);
}
}
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairMorse2::read_restart(FILE *fp)
{
read_restart_settings(fp);
allocate();
int i,j;
int me = comm->me;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
if (me == 0) utils::sfread(FLERR,&setflag[i][j],sizeof(int),1,fp,nullptr,error);
MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world);
if (setflag[i][j]) {
if (me == 0) {
utils::sfread(FLERR,&d0[i][j],sizeof(double),1,fp,nullptr,error);
utils::sfread(FLERR,&alpha[i][j],sizeof(double),1,fp,nullptr,error);
utils::sfread(FLERR,&r0[i][j],sizeof(double),1,fp,nullptr,error);
utils::sfread(FLERR,&cut[i][j],sizeof(double),1,fp,nullptr,error);
}
MPI_Bcast(&d0[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&alpha[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&r0[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut[i][j],1,MPI_DOUBLE,0,world);
}
}
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairMorse2::write_restart_settings(FILE *fp)
{
fwrite(&cut_global,sizeof(double),1,fp);
fwrite(&offset_flag,sizeof(int),1,fp);
fwrite(&mix_flag,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairMorse2::read_restart_settings(FILE *fp)
{
if (comm->me == 0) {
utils::sfread(FLERR,&cut_global,sizeof(double),1,fp,nullptr,error);
utils::sfread(FLERR,&offset_flag,sizeof(int),1,fp,nullptr,error);
utils::sfread(FLERR,&mix_flag,sizeof(int),1,fp,nullptr,error);
}
MPI_Bcast(&cut_global,1,MPI_DOUBLE,0,world);
MPI_Bcast(&offset_flag,1,MPI_INT,0,world);
MPI_Bcast(&mix_flag,1,MPI_INT,0,world);
}
/* ----------------------------------------------------------------------
proc 0 writes to data file
------------------------------------------------------------------------- */
void PairMorse2::write_data(FILE *fp)
{
for (int i = 1; i <= atom->ntypes; i++)
fprintf(fp,"%d %g %g %g\n",i,d0[i][i],alpha[i][i],r0[i][i]);
}
/* ----------------------------------------------------------------------
proc 0 writes all pairs to data file
------------------------------------------------------------------------- */
void PairMorse2::write_data_all(FILE *fp)
{
for (int i = 1; i <= atom->ntypes; i++)
for (int j = i; j <= atom->ntypes; j++)
fprintf(fp,"%d %d %g %g %g %g\n",
i,j,d0[i][j],alpha[i][j],r0[i][j],cut[i][j]);
}
/* ---------------------------------------------------------------------- */
double PairMorse2::single(int /*i*/, int /*j*/, int itype, int jtype, double rsq,
double /*factor_coul*/, double factor_lj,
double &fforce)
{
double r,dr,dexp,phi;
r = sqrt(rsq);
dr = r - r0[itype][jtype];
dexp = exp(-alpha[itype][jtype] * dr);
fforce = factor_lj * morse1[itype][jtype] * (dexp*dexp - dexp) / r;
phi = d0[itype][jtype] * (dexp*dexp - 2.0*dexp) - offset[itype][jtype];
return factor_lj*phi;
}
/* ---------------------------------------------------------------------- */
void *PairMorse2::extract(const char *str, int &dim)
{
dim = 2;
if (strcmp(str,"d0") == 0) return (void *) d0;
if (strcmp(str,"r0") == 0) return (void *) r0;
if (strcmp(str,"alpha") == 0) return (void *) alpha;
return nullptr;
}

View File

@ -0,0 +1,70 @@
/* -*- c++ -*- ----------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#ifndef LMP_PAIR_MORSE2_H
#define LMP_PAIR_MORSE2_H
#include "pair.h"
namespace LAMMPS_NS {
class PairMorse2 : public Pair {
public:
PairMorse2(class LAMMPS *);
virtual ~PairMorse2();
virtual void compute(int, int);
void settings(int, char **);
void coeff(int, char **);
double init_one(int, int);
void write_restart(FILE *);
void read_restart(FILE *);
void write_restart_settings(FILE *);
void read_restart_settings(FILE *);
void write_data(FILE *);
void write_data_all(FILE *);
double single(int, int, int, int, double, double, double, double &);
void *extract(const char *, int &);
protected:
double cut_global;
double **cut;
double **d0,**alpha,**r0;
double **morse1;
double **offset;
virtual void allocate();
};
}
#endif
/* ERROR/WARNING messages:
E: Illegal ... command
Self-explanatory. Check the input script syntax and compare to the
documentation for the command. You can use -echo screen as a
command-line option when running LAMMPS to see the offending line.
E: Incorrect args for pair coefficients
Self-explanatory. Check the input script or data file.
E: All pair coeffs are not set
All pair coefficients must be set in the data file or by the
pair_coeff command before running a simulation.
*/

View File

@ -0,0 +1,160 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://lammps.sandia.gov/, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
This software is distributed under the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Axel Kohlmeyer (Temple U)
------------------------------------------------------------------------- */
#include "pair_morse2_omp.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "neigh_list.h"
#include "suffix.h"
#include <cmath>
#include "omp_compat.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
PairMorse2OMP::PairMorse2OMP(LAMMPS *lmp) :
PairMorse2(lmp), ThrOMP(lmp, THR_PAIR)
{
suffix_flag |= Suffix::OMP;
respa_enable = 0;
}
/* ---------------------------------------------------------------------- */
void PairMorse2OMP::compute(int eflag, int vflag)
{
ev_init(eflag,vflag);
const int nall = atom->nlocal + atom->nghost;
const int nthreads = comm->nthreads;
const int inum = list->inum;
#if defined(_OPENMP)
#pragma omp parallel LMP_DEFAULT_NONE LMP_SHARED(eflag,vflag)
#endif
{
int ifrom, ito, tid;
loop_setup_thr(ifrom, ito, tid, inum, nthreads);
ThrData *thr = fix->get_thr(tid);
thr->timer(Timer::START);
ev_setup_thr(eflag, vflag, nall, eatom, vatom, nullptr, thr);
if (evflag) {
if (eflag) {
if (force->newton_pair) eval<1,1,1>(ifrom, ito, thr);
else eval<1,1,0>(ifrom, ito, thr);
} else {
if (force->newton_pair) eval<1,0,1>(ifrom, ito, thr);
else eval<1,0,0>(ifrom, ito, thr);
}
} else {
if (force->newton_pair) eval<0,0,1>(ifrom, ito, thr);
else eval<0,0,0>(ifrom, ito, thr);
}
thr->timer(Timer::PAIR);
reduce_thr(this, eflag, vflag, thr);
} // end of omp parallel region
}
template <int EVFLAG, int EFLAG, int NEWTON_PAIR>
void PairMorse2OMP::eval(int iifrom, int iito, ThrData * const thr)
{
int i,j,ii,jj,jnum,itype,jtype;
double xtmp,ytmp,ztmp,delx,dely,delz,evdwl,fpair;
double rsq,r,dr,dexp,factor_lj;
int *ilist,*jlist,*numneigh,**firstneigh;
evdwl = 0.0;
const dbl3_t * _noalias const x = (dbl3_t *) atom->x[0];
dbl3_t * _noalias const f = (dbl3_t *) thr->get_f()[0];
const int * _noalias const type = atom->type;
const int nlocal = atom->nlocal;
const double * _noalias const special_lj = force->special_lj;
double fxtmp,fytmp,fztmp;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
for (ii = iifrom; ii < iito; ++ii) {
i = ilist[ii];
xtmp = x[i].x;
ytmp = x[i].y;
ztmp = x[i].z;
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
fxtmp=fytmp=fztmp=0.0;
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j].x;
dely = ytmp - x[j].y;
delz = ztmp - x[j].z;
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
if (rsq < cutsq[itype][jtype]) {
r = sqrt(rsq);
dr = r - r0[itype][jtype];
dexp = exp(-alpha[itype][jtype] * dr);
fpair = factor_lj * morse1[itype][jtype] * (dexp*dexp - dexp) / r;
fxtmp += delx*fpair;
fytmp += dely*fpair;
fztmp += delz*fpair;
if (NEWTON_PAIR || j < nlocal) {
f[j].x -= delx*fpair;
f[j].y -= dely*fpair;
f[j].z -= delz*fpair;
}
if (EFLAG) {
evdwl = d0[itype][jtype] * (dexp*dexp - 2.0*dexp) -
offset[itype][jtype];
evdwl *= factor_lj;
}
if (EVFLAG) ev_tally_thr(this,i,j,nlocal,NEWTON_PAIR,
evdwl,0.0,fpair,delx,dely,delz,thr);
}
}
f[i].x += fxtmp;
f[i].y += fytmp;
f[i].z += fztmp;
}
}
/* ---------------------------------------------------------------------- */
double PairMorse2OMP::memory_usage()
{
double bytes = memory_usage_thr();
bytes += PairMorse2::memory_usage();
return bytes;
}

View File

@ -0,0 +1,41 @@
/* -*- c++ -*- ----------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Axel Kohlmeyer (Temple U)
------------------------------------------------------------------------- */
#ifndef LMP_PAIR_MORSE2_OMP_H
#define LMP_PAIR_MORSE2_OMP_H
#include "pair_morse2.h"
#include "thr_omp.h"
namespace LAMMPS_NS {
class PairMorse2OMP : public PairMorse2, public ThrOMP {
public:
PairMorse2OMP(class LAMMPS *);
virtual void compute(int, int);
virtual double memory_usage();
private:
template <int EVFLAG, int EFLAG, int NEWTON_PAIR>
void eval(int ifrom, int ito, ThrData * const thr);
};
}
#endif

View File

@ -0,0 +1,247 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://lammps.sandia.gov/, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Carsten Svaneborg (SDU)
------------------------------------------------------------------------- */
#include "pair_zero2.h"
#include "atom.h"
#include "comm.h"
#include "memory.h"
#include "error.h"
#include <cstring>
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
PairZero2::PairZero2(LAMMPS *lmp) : Pair(lmp) {
coeffflag=1;
writedata=1;
single_enable=1;
respa_enable=1;
}
/* ---------------------------------------------------------------------- */
PairZero2::~PairZero2()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(cut);
}
}
/* ---------------------------------------------------------------------- */
void PairZero2::compute(int eflag, int vflag)
{
ev_init(eflag,vflag);
if (vflag_fdotr) virial_fdotr_compute();
}
/* ---------------------------------------------------------------------- */
void PairZero2::compute_outer(int eflag, int vflag)
{
ev_init(eflag,vflag);
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairZero2::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq,n+1,n+1,"pair:cutsq");
memory->create(cut,n+1,n+1,"pair:cut");
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairZero2::settings(int narg, char **arg)
{
if ((narg != 1) && (narg != 2))
error->all(FLERR,"Illegal pair_style command");
cut_global = utils::numeric(FLERR,arg[0],false,lmp);
if (narg == 2) {
if (strcmp("nocoeff",arg[1]) == 0) coeffflag=0;
else error->all(FLERR,"Illegal pair_style command");
}
// reset cutoffs that have been explicitly set
if (allocated) {
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i+1; j <= atom->ntypes; j++)
cut[i][j] = cut_global;
}
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairZero2::coeff(int narg, char **arg)
{
if ((narg < 2) || (coeffflag && narg > 3))
error->all(FLERR,"Incorrect args for pair coefficients");
if (!allocated) allocate();
int ilo,ihi,jlo,jhi;
utils::bounds(FLERR,arg[0],1,atom->ntypes,ilo,ihi,error);
utils::bounds(FLERR,arg[1],1,atom->ntypes,jlo,jhi,error);
double cut_one = cut_global;
if (coeffflag && (narg == 3)) cut_one = utils::numeric(FLERR,arg[2],false,lmp);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
for (int j = MAX(jlo,i); j <= jhi; j++) {
cut[i][j] = cut_one;
setflag[i][j] = 1;
count++;
}
}
if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairZero2::init_one(int i, int j)
{
if (setflag[i][j] == 0) {
cut[i][j] = mix_distance(cut[i][i],cut[j][j]);
}
return cut[i][j];
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairZero2::write_restart(FILE *fp)
{
write_restart_settings(fp);
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
fwrite(&setflag[i][j],sizeof(int),1,fp);
if (setflag[i][j]) {
fwrite(&cut[i][j],sizeof(double),1,fp);
}
}
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairZero2::read_restart(FILE *fp)
{
read_restart_settings(fp);
allocate();
int i,j;
int me = comm->me;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
if (me == 0) utils::sfread(FLERR,&setflag[i][j],sizeof(int),1,fp,nullptr,error);
MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world);
if (setflag[i][j]) {
if (me == 0) {
utils::sfread(FLERR,&cut[i][j],sizeof(double),1,fp,nullptr,error);
}
MPI_Bcast(&cut[i][j],1,MPI_DOUBLE,0,world);
}
}
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairZero2::write_restart_settings(FILE *fp)
{
fwrite(&cut_global,sizeof(double),1,fp);
fwrite(&coeffflag,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairZero2::read_restart_settings(FILE *fp)
{
int me = comm->me;
if (me == 0) {
utils::sfread(FLERR,&cut_global,sizeof(double),1,fp,nullptr,error);
utils::sfread(FLERR,&coeffflag,sizeof(int),1,fp,nullptr,error);
}
MPI_Bcast(&cut_global,1,MPI_DOUBLE,0,world);
MPI_Bcast(&coeffflag,1,MPI_INT,0,world);
}
/* ----------------------------------------------------------------------
proc 0 writes to data file
------------------------------------------------------------------------- */
void PairZero2::write_data(FILE *fp)
{
for (int i = 1; i <= atom->ntypes; i++)
fprintf(fp,"%d\n",i);
}
/* ----------------------------------------------------------------------
proc 0 writes all pairs to data file
------------------------------------------------------------------------- */
void PairZero2::write_data_all(FILE *fp)
{
for (int i = 1; i <= atom->ntypes; i++)
for (int j = i; j <= atom->ntypes; j++)
fprintf(fp,"%d %d %g\n",i,j,cut[i][j]);
}
/* ---------------------------------------------------------------------- */
double PairZero2::single(int /*i*/, int /*j*/, int /* itype */, int /* jtype */,
double /* rsq */, double /*factor_coul*/,
double /* factor_lj */, double &fforce)
{
fforce = 0.0;
return 0.0;
}

View File

@ -0,0 +1,77 @@
/* -*- c++ -*- ----------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
Pair zero is a dummy pair interaction useful for requiring a
force cutoff distance in the absence of pair-interactions or
with hybrid/overlay if a larger force cutoff distance is required.
This can be used in conjunction with bond/create to create bonds
that are longer than the cutoff of a given force field, or to
calculate radial distribution functions for models without
pair interactions.
------------------------------------------------------------------------- */
#ifndef LMP_PAIR_ZERO2_H
#define LMP_PAIR_ZERO2_H
#include "pair.h"
namespace LAMMPS_NS {
class PairZero2 : public Pair {
public:
PairZero2(class LAMMPS *);
virtual ~PairZero2();
virtual void compute(int, int);
virtual void compute_outer(int, int);
void settings(int, char **);
void coeff(int, char **);
double init_one(int, int);
void write_restart(FILE *);
void read_restart(FILE *);
void write_restart_settings(FILE *);
void read_restart_settings(FILE *);
void write_data(FILE *);
void write_data_all(FILE *);
double single(int, int, int, int, double, double, double, double &);
protected:
double cut_global;
double **cut;
int coeffflag;
virtual void allocate();
};
}
#endif
/* ERROR/WARNING messages:
E: Illegal ... command
Self-explanatory. Check the input script syntax and compare to the
documentation for the command. You can use -echo screen as a
command-line option when running LAMMPS to see the offending line.
E: Incorrect args for pair coefficients
Self-explanatory. Check the input script or data file.
U: Pair cutoff < Respa interior cutoff
One or more pairwise cutoffs are too short to use with the specified
rRESPA cutoffs.
*/

View File

@ -0,0 +1,78 @@
#include "lammpsplugin.h"
#include "version.h"
#include <cstring>
#include "pair_zero2.h"
#include "bond_zero2.h"
#include "angle_zero2.h"
#include "dihedral_zero2.h"
#include "improper_zero2.h"
using namespace LAMMPS_NS;
static Pair *pairzerocreator(LAMMPS *lmp)
{
return new PairZero2(lmp);
}
static Bond *bondzerocreator(LAMMPS *lmp)
{
return new BondZero2(lmp);
}
static Angle *anglezerocreator(LAMMPS *lmp)
{
return new AngleZero2(lmp);
}
static Dihedral *dihedralzerocreator(LAMMPS *lmp)
{
return new DihedralZero2(lmp);
}
static Improper *improperzerocreator(LAMMPS *lmp)
{
return new ImproperZero2(lmp);
}
extern "C" void lammpsplugin_init(void *lmp, void *handle, void *regfunc)
{
lammpsplugin_t plugin;
lammpsplugin_regfunc register_plugin = (lammpsplugin_regfunc) regfunc;
// register zero2 pair style
plugin.version = LAMMPS_VERSION;
plugin.style = "pair";
plugin.name = "zero2";
plugin.info = "Zero2 variant pair style v1.0";
plugin.author = "Axel Kohlmeyer (akohlmey@gmail.com)";
plugin.creator.v1 = (lammpsplugin_factory1 *) &pairzerocreator;
plugin.handle = handle;
(*register_plugin)(&plugin,lmp);
// register zero2 bond style
plugin.style = "bond";
plugin.info = "Zero2 variant bond style v1.0";
plugin.creator.v1 = (lammpsplugin_factory1 *) &bondzerocreator;
(*register_plugin)(&plugin,lmp);
// register zero2 angle style
plugin.style = "angle";
plugin.info = "Zero2 variant angle style v1.0";
plugin.creator.v1 = (lammpsplugin_factory1 *) &anglezerocreator;
(*register_plugin)(&plugin,lmp);
// register zero2 dihedral style
plugin.style = "dihedral";
plugin.info = "Zero2 variant dihedral style v1.0";
plugin.creator.v1 = (lammpsplugin_factory1 *) &dihedralzerocreator;
(*register_plugin)(&plugin,lmp);
// register zero2 improper style
plugin.style = "improper";
plugin.info = "Zero2 variant improper style v1.0";
plugin.creator.v1 = (lammpsplugin_factory1 *) &improperzerocreator;
(*register_plugin)(&plugin,lmp);
}

View File

@ -19,12 +19,12 @@ atc atomistic-to-continuum methods, USER-ATC package
from Reese Jones, Jeremy Templeton, Jon Zimmerman (Sandia)
awpmd antisymmetrized wave packet molecular dynamics, AWPMD package
from Ilya Valuev (JIHT RAS)
colvars collective variable module (Metadynamics, ABF and more)
colvars collective variable module (Metadynamics, ABF and more)
from Giacomo Fiorin and Jerome Henin (ICMS, Temple U)
compress hook to system lib for performing I/O compression, COMPRESS pkg
from Axel Kohlmeyer (Temple U)
gpu general GPU routines, GPU package
from Mike Brown (ORNL)
from Axel Kohlmeyer (Temple U)
gpu general GPU routines, GPU package
from Mike Brown (ORNL)
h5md ch5md library for output of MD data in HDF5 format
from Pierre de Buyl (KU Leuven)
kim hooks to the KIM library, used by KIM package
@ -32,26 +32,28 @@ kim hooks to the KIM library, used by KIM package
kokkos Kokkos package for GPU and many-core acceleration
from Kokkos development team (Sandia)
linalg set of BLAS and LAPACK routines needed by USER-ATC package
from Axel Kohlmeyer (Temple U)
from Axel Kohlmeyer (Temple U)
message client/server communication library via MPI, sockets, files
from Steve Plimpton (Sandia)
from Steve Plimpton (Sandia)
molfile hooks to VMD molfile plugins, used by the USER-MOLFILE package
from Axel Kohlmeyer (Temple U) and the VMD development team
mscg hooks to the MSCG library, used by fix_mscg command
from Jacob Wagner and Greg Voth group (U Chicago)
netcdf hooks to a NetCDF library installed on your system
from Lars Pastewka (Karlsruhe Institute of Technology)
poems POEMS rigid-body integration package, POEMS package
plugin settings to load styles into LAMMPS from plugins
from Axel Kohlmeyer (Temple U)
poems POEMS rigid-body integration package, POEMS package
from Rudranarayan Mukherjee (RPI)
python hooks to the system Python library, used by the PYTHON package
from the LAMMPS development team
qmmm quantum mechanics/molecular mechanics coupling interface
qmmm quantum mechanics/molecular mechanics coupling interface
from Axel Kohlmeyer (Temple U)
quip interface to QUIP/libAtoms framework, USER-QUIP package
from Albert Bartok-Partay and Gabor Csanyi (U Cambridge)
smd hooks to Eigen library, used by USER-SMD package
from Georg Ganzenmueller (Ernst Mach Institute, Germany)
voronoi hooks to the Voro++ library, used by compute voronoi/atom command
from Daniel Schwen (LANL)
from Daniel Schwen (LANL)
vtk hooks to the VTK library, used by dump custom/vtk command
from Richard Berger (JKU)

View File

@ -0,0 +1,16 @@
# This file contains the hooks to build and link LAMMPS so it can load plugins
#
# The plugin_SYSINC and plugin_SYSPATH variables do not typically need
# to be set. If the dl library is not in a place the linker can find
# it, specify its directory via the plugin_SYSPATH variable, e.g.
# -Ldir.
# -----------------------------------------------------------
# Settings that the LAMMPS build will import when this package is installed
ifeq ($(mode),shared)
plugin_SYSINC = -DLMP_PLUGIN
endif
plugin_SYSLIB = -ldl
plugin_SYSPATH =

16
lib/plugin/README Normal file
View File

@ -0,0 +1,16 @@
This directory has a Makefile.lammps file with settings that allows
LAMMPS to dynamically link LAMMPS plugins. More details about this
are in the manual.
In order to be able to dynamically load and execute the plugins from
inside LAMMPS, you need to link with a system library containing functions
like dlopen(), dlsym() and so on for dynamic linking of executable code
into an executable. This library is defined by setting the plugin_SYSLIB
variable in the Makefile.lammps file in this dir. For this mechanism
to work, LAMMPS must be built as a shared library (i.e. with mode=shared).
For Linux and most current unix-like operating systems, this can be
kept at the default setting of "-ldl" (on some platforms this library
is called "-ldld"). The Windows platform is currently not supported.
See the header of Makefile.lammps for more info.

View File

@ -278,6 +278,9 @@ class lammps(object):
self.lib.lammps_id_name.argtypes = [c_void_p, c_char_p, c_int, c_char_p, c_int]
self.lib.lammps_plugin_count.argtypes = [ ]
self.lib.lammps_plugin_name.argtypes = [c_int, c_char_p, c_char_p, c_int]
self.lib.lammps_version.argtypes = [c_void_p]
self.lib.lammps_get_os_info.argtypes = [c_char_p, c_int]
@ -1655,6 +1658,29 @@ class lammps(object):
# -------------------------------------------------------------------------
def available_plugins(self, category):
"""Returns a list of plugins available for a given category
This is a wrapper around the functions :cpp:func:`lammps_plugin_count()`
and :cpp:func:`lammps_plugin_name()` of the library interface.
.. versionadded:: 10Mar2021
:return: list of style/name pairs of loaded plugins
:rtype: list
"""
available_plugins = []
num = self.lib.lammps_plugin_count(self.lmp)
sty = create_string_buffer(100)
nam = create_string_buffer(100)
for idx in range(num):
self.lib.lammps_plugin_name(idx, sty, nam, 100)
available_plugins.append([sty.value.decode(), nam.value.decode()])
return available_plugins
# -------------------------------------------------------------------------
def set_fix_external_callback(self, fix_name, callback, caller=None):
import numpy as np

4
src/.gitignore vendored
View File

@ -172,6 +172,10 @@
/pair_lj_charmmfsw_coul_long.cpp
/pair_lj_charmmfsw_coul_long.h
/plugin.cpp
/plugin.h
/lammpsplugin.h
/atom_vec_spin.cpp
/atom_vec_spin.h
/compute_spin.cpp

View File

@ -13,12 +13,12 @@ DEPFLAGS = -M
LINK = mpicxx
LINKFLAGS = -g -O3
LIB =
LIB =
SIZE = size
ARCHIVE = ar
ARFLAGS = -rc
SHLIBFLAGS = -shared
SHLIBFLAGS = -shared -rdynamic
# ---------------------------------------------------------------------
# LAMMPS-specific settings, all OPTIONAL

View File

@ -13,12 +13,12 @@ DEPFLAGS = -M
LINK = g++
LINKFLAGS = -g -O
LIB =
LIB =
SIZE = size
ARCHIVE = ar
ARFLAGS = -rc
SHLIBFLAGS = -shared
SHLIBFLAGS = -shared -rdynamic
# ---------------------------------------------------------------------
# LAMMPS-specific settings, all OPTIONAL

View File

@ -48,7 +48,7 @@ endif
PACKAGE = asphere body class2 colloid compress coreshell dipole gpu \
granular kim kokkos kspace latte manybody mc message misc \
mliap molecule mpiio mscg opt peri poems \
mliap molecule mpiio mscg opt peri plugin poems \
python qeq replica rigid shock snap spin srd voronoi
PACKUSER = user-adios user-atc user-awpmd user-bocs user-cgdna user-cgsdk user-colvars \

64
src/PLUGIN/Install.sh Executable file
View File

@ -0,0 +1,64 @@
# Install/unInstall package files in LAMMPS
# mode = 0/1/2 for uninstall/install/update
mode=$1
# enforce using portable C locale
LC_ALL=C
export LC_ALL
# arg1 = file, arg2 = file it depends on
action () {
if (test $mode = 0) then
rm -f ../$1
elif (! cmp -s $1 ../$1) then
if (test -z "$2" || test -e ../$2) then
cp $1 ..
if (test $mode = 2) then
echo " updating src/$1"
fi
fi
elif (test -n "$2") then
if (test ! -e ../$2) then
rm -f ../$1
fi
fi
}
# all package files with no dependencies
for file in *.cpp *.h; do
test -f ${file} && action $file
done
# edit 2 Makefile.package files to include/exclude package info
if (test $1 = 1) then
if (test -e ../Makefile.package) then
sed -i -e 's/[^ \t]*plugin[^ \t]* //' ../Makefile.package
sed -i -e 's|^PKG_SYSINC =[ \t]*|&$(plugin_SYSINC) |' ../Makefile.package
sed -i -e 's|^PKG_SYSLIB =[ \t]*|&$(plugin_SYSLIB) |' ../Makefile.package
sed -i -e 's|^PKG_SYSPATH =[ \t]*|&$(plugin_SYSPATH) |' ../Makefile.package
fi
if (test -e ../Makefile.package.settings) then
sed -i -e '/^include.*plugin.*$/d' ../Makefile.package.settings
# multiline form needed for BSD sed on Macs
sed -i -e '4 i \
include ..\/..\/lib\/plugin\/Makefile.lammps
' ../Makefile.package.settings
fi
elif (test $1 = 0) then
if (test -e ../Makefile.package) then
sed -i -e 's/[^ \t]*plugin[^ \t]* //' ../Makefile.package
fi
if (test -e ../Makefile.package.settings) then
sed -i -e '/^include.*plugin.*$/d' ../Makefile.package.settings
fi
fi

12
src/PLUGIN/README Normal file
View File

@ -0,0 +1,12 @@
This package provides a plugin command that can load LAMMPS
styles linked into shared object files into a LAMMPS binary
at run time without having to recompile and relink LAMMPS.
For more details please see the LAMMPS manual.
To be able to dynamically load and execute the plugins from inside
LAMMPS, you need to link with an appropriate system library, which
is done using the settings in lib/plugin/Makefile.lammps. See
that file and the lib/plugin/README file for more details.
The person who created this package is Axel Kohlmeyer at Temple U
(akohlmey at gmail.com). Contact him directly if you have questions.

495
src/PLUGIN/plugin.cpp Normal file
View File

@ -0,0 +1,495 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://lammps.sandia.gov/, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "plugin.h"
#include "comm.h"
#include "domain.h"
#include "error.h"
#include "input.h"
#include "force.h"
#include "lammps.h"
#include "modify.h"
#include <map>
#include <list>
#ifdef _WIN32
#include <windows.h>
#else
#include <dlfcn.h>
#endif
namespace LAMMPS_NS
{
// list of plugin information data for loaded styles
static std::list<lammpsplugin_t> pluginlist;
// map for counting references to dso handles
static std::map<void *, int> dso_refcounter;
/* ---------------------------------------------------------------------- */
Plugin::Plugin(LAMMPS *lmp) : Pointers(lmp) {}
/* ---------------------------------------------------------------------- */
void Plugin::command(int narg, char **arg)
{
if (narg < 1) error->all(FLERR,"Illegal plugin command");
#if defined(LMP_PLUGIN)
std::string cmd = arg[0];
if (cmd == "load") {
if (narg < 2) error->all(FLERR,"Illegal plugin load command");
for (int i=1; i < narg; ++i)
plugin_load(arg[i],lmp);
} else if (cmd == "unload") {
if (narg != 3) error->all(FLERR,"Illegal plugin unload command");
plugin_unload(arg[1],arg[2],lmp);
} else if (cmd == "clear") {
plugin_clear(lmp);
} else if (cmd == "list") {
if (comm->me == 0) {
int num = plugin_get_num_plugins();
utils::logmesg(lmp,"Currently loaded plugins\n");
for (int i=0; i < num; ++i) {
auto entry = plugin_get_info(i);
utils::logmesg(lmp,fmt::format("{:4}: {} style plugin {}\n",
i+1,entry->style,entry->name));
}
}
} else error->all(FLERR,"Illegal plugin command");
#else
if (comm->me == 0)
error->warning(FLERR,"Ignoring plugin command. LAMMPS must be built as "
"a shared library for it to work.");
#endif
}
// load DSO and call included registration function
void plugin_load(const char *file, LAMMPS *lmp)
{
#if defined(LMP_PLUGIN)
int me = lmp->comm->me;
#if defined(WIN32)
lmp->error->all(FLERR,"Loading of plugins on Windows is not supported\n");
#else
// open DSO file from given path; load symbols globally
dlerror();
void *dso = dlopen(file,RTLD_NOW|RTLD_GLOBAL);
if (dso == nullptr) {
if (me == 0)
utils::logmesg(lmp,fmt::format("Open of file {} failed: {}\n",
file,dlerror()));
return;
}
// look up lammpsplugin_init() function in DSO
// function must have C bindings so there is no name mangling
dlerror();
void *initfunc = dlsym(dso,"lammpsplugin_init");
if (initfunc == nullptr) {
dlclose(dso);
if (me == 0)
utils::logmesg(lmp,fmt::format("Plugin symbol lookup failure in "
"file {}: {}\n",file,dlerror()));
return;
}
// call initializer function loaded from DSO and pass a pointer
// to the LAMMPS instance, the DSO handle (for reference counting)
// and plugin registration function pointer
(*(lammpsplugin_initfunc)(initfunc))((void *)lmp, dso,
(void *)&plugin_register);
#endif
#endif
}
/* --------------------------------------------------------------------
register a new style from a plugin with LAMMPS
this is the callback function that is called from within
the plugin initializer function. all plugin information
is taken from the lammpsplugin_t struct.
-------------------------------------------------------------------- */
void plugin_register(lammpsplugin_t *plugin, void *ptr)
{
#if defined(LMP_PLUGIN)
LAMMPS *lmp = (LAMMPS *)ptr;
int me = lmp->comm->me;
if (plugin == nullptr) return;
// ignore load request if same plugin already loaded
int idx = plugin_find(plugin->style,plugin->name);
if (idx >= 0) {
if (me == 0)
utils::logmesg(lmp,fmt::format("Ignoring load of {} style {}: must "
"unload existing {} plugin first\n",
plugin->style,plugin->name,plugin->name));
return;
}
if (me == 0) {
utils::logmesg(lmp,fmt::format("Loading plugin: {} by {}\n",
plugin->info,plugin->author));
// print version info only if the versions of host and plugin don't match
if ((plugin->version) && (strcmp(plugin->version,lmp->version) != 0))
utils::logmesg(lmp,fmt::format(" compiled for LAMMPS version {} "
"loaded into LAMMPS version {}\n",
plugin->version,lmp->version));
}
pluginlist.push_back(*plugin);
if (dso_refcounter.find(plugin->handle) != dso_refcounter.end()) {
++ dso_refcounter[plugin->handle];
} else {
dso_refcounter[plugin->handle] = 1;
}
std::string pstyle = plugin->style;
if (pstyle == "pair") {
auto pair_map = lmp->force->pair_map;
if (pair_map->find(plugin->name) != pair_map->end()) {
if (lmp->comm->me == 0)
lmp->error->warning(FLERR,fmt::format("Overriding built-in pair "
"style {} from plugin",
plugin->name));
}
(*pair_map)[plugin->name] = (Force::PairCreator)plugin->creator.v1;
} else if (pstyle == "bond") {
auto bond_map = lmp->force->bond_map;
if (bond_map->find(plugin->name) != bond_map->end()) {
if (lmp->comm->me == 0)
lmp->error->warning(FLERR,fmt::format("Overriding built-in bond "
"style {} from plugin",
plugin->name));
}
(*bond_map)[plugin->name] = (Force::BondCreator)plugin->creator.v1;
} else if (pstyle == "angle") {
auto angle_map = lmp->force->angle_map;
if (angle_map->find(plugin->name) != angle_map->end()) {
if (lmp->comm->me == 0)
lmp->error->warning(FLERR,fmt::format("Overriding built-in angle "
"style {} from plugin",
plugin->name));
}
(*angle_map)[plugin->name] = (Force::AngleCreator)plugin->creator.v1;
} else if (pstyle == "dihedral") {
auto dihedral_map = lmp->force->dihedral_map;
if (dihedral_map->find(plugin->name) != dihedral_map->end()) {
if (lmp->comm->me == 0)
lmp->error->warning(FLERR,fmt::format("Overriding built-in dihedral "
"style {} from plugin",
plugin->name));
}
(*dihedral_map)[plugin->name] = (Force::DihedralCreator)plugin->creator.v1;
} else if (pstyle == "improper") {
auto improper_map = lmp->force->improper_map;
if (improper_map->find(plugin->name) != improper_map->end()) {
if (lmp->comm->me == 0)
lmp->error->warning(FLERR,fmt::format("Overriding built-in improper "
"style {} from plugin",
plugin->name));
}
(*improper_map)[plugin->name] = (Force::ImproperCreator)plugin->creator.v1;
} else if (pstyle == "compute") {
auto compute_map = lmp->modify->compute_map;
if (compute_map->find(plugin->name) != compute_map->end()) {
if (lmp->comm->me == 0)
lmp->error->warning(FLERR,fmt::format("Overriding built-in compute "
"style {} from plugin",
plugin->name));
}
(*compute_map)[plugin->name] = (Modify::ComputeCreator)plugin->creator.v2;
} else if (pstyle == "fix") {
auto fix_map = lmp->modify->fix_map;
if (fix_map->find(plugin->name) != fix_map->end()) {
if (lmp->comm->me == 0)
lmp->error->warning(FLERR,fmt::format("Overriding built-in fix "
"style {} from plugin",
plugin->name));
}
(*fix_map)[plugin->name] = (Modify::FixCreator)plugin->creator.v2;
} else if (pstyle == "region") {
auto region_map = lmp->domain->region_map;
if (region_map->find(plugin->name) != region_map->end()) {
if (lmp->comm->me == 0)
lmp->error->warning(FLERR,fmt::format("Overriding built-in region "
"style {} from plugin",
plugin->name));
}
(*region_map)[plugin->name] = (Domain::RegionCreator)plugin->creator.v2;
} else if (pstyle == "command") {
auto command_map = lmp->input->command_map;
if (command_map->find(plugin->name) != command_map->end()) {
if (lmp->comm->me == 0)
lmp->error->warning(FLERR,fmt::format("Overriding built-in command "
"style {} from plugin",
plugin->name));
}
(*command_map)[plugin->name] = (Input::CommandCreator)plugin->creator.v3;
} else {
utils::logmesg(lmp,fmt::format("Loading plugin for {} styles not "
"yet implemented\n",pstyle));
pluginlist.pop_back();
}
#endif
}
/* --------------------------------------------------------------------
remove plugin from given style table and plugin list
optionally close the DSO handle if it is the last plugin from that DSO
must also delete style instances if style is currently active
-------------------------------------------------------------------- */
void plugin_unload(const char *style, const char *name, LAMMPS *lmp)
{
#if defined(LMP_PLUGIN)
int me = lmp->comm->me;
// ignore unload request from unsupported style categories
if ((strcmp(style,"pair") != 0) && (strcmp(style,"bond") != 0)
&& (strcmp(style,"angle") != 0) && (strcmp(style,"dihedral") != 0)
&& (strcmp(style,"improper") != 0) && (strcmp(style,"compute") != 0)
&& (strcmp(style,"fix") != 0) && (strcmp(style,"region") != 0)
&& (strcmp(style,"command") != 0)) {
if (me == 0)
utils::logmesg(lmp,fmt::format("Ignoring unload: {} is not a "
"supported plugin style\n",style));
return;
}
// ignore unload request if not loaded from a plugin
int idx = plugin_find(style,name);
if (idx < 0) {
if (me == 0)
utils::logmesg(lmp,fmt::format("Ignoring unload of {} style {}: not "
"loaded from a plugin\n",style,name));
return;
}
// make copy of DSO handle for later use
void *handle = plugin_get_info(idx)->handle;
// remove selected plugin from list of plugins
if (me == 0)
utils::logmesg(lmp,fmt::format("Unloading {} style {}\n",style,name));
plugin_erase(style,name);
// remove style of given name from corresponding map
// must delete style instance if currently active so
// we can close the DSO handle if the last reference is gone.
std::string pstyle = style;
if (pstyle == "pair") {
auto found = lmp->force->pair_map->find(name);
if (found != lmp->force->pair_map->end())
lmp->force->pair_map->erase(found);
// must delete pair style instance if in use
if (lmp->force->pair_style) {
if (utils::strmatch(lmp->force->pair_style,"^hybrid")) {
if (lmp->force->pair_match(name,1,1) != nullptr)
lmp->force->create_pair("none",0);
} else {
if (strcmp(lmp->force->pair_style,name) == 0)
lmp->force->create_pair("none",0);
}
}
} else if (pstyle == "bond") {
auto found = lmp->force->bond_map->find(name);
if (found != lmp->force->bond_map->end())
lmp->force->bond_map->erase(found);
// must delete bond style instance if in use
if ((lmp->force->bond_style != nullptr)
&& (lmp->force->bond_match(name) != nullptr))
lmp->force->create_bond("none",0);
} else if (pstyle == "angle") {
auto found = lmp->force->angle_map->find(name);
if (found != lmp->force->angle_map->end())
lmp->force->angle_map->erase(found);
// must delete angle style instance if in use
if ((lmp->force->angle_style != nullptr)
&& (lmp->force->angle_match(name) != nullptr))
lmp->force->create_angle("none",0);
} else if (pstyle == "dihedral") {
auto found = lmp->force->dihedral_map->find(name);
if (found != lmp->force->dihedral_map->end())
lmp->force->dihedral_map->erase(found);
// must delete dihedral style instance if in use
if ((lmp->force->dihedral_style)
&& (lmp->force->dihedral_match(name) != nullptr))
lmp->force->create_dihedral("none",0);
} else if (pstyle == "improper") {
auto found = lmp->force->improper_map->find(name);
if (found != lmp->force->improper_map->end())
lmp->force->improper_map->erase(found);
// must delete improper style instance if in use
if ((lmp->force->improper_style != nullptr)
&& (lmp->force->improper_match(name) != nullptr))
lmp->force->create_improper("none",0);
} else if (pstyle == "compute") {
auto compute_map = lmp->modify->compute_map;
auto found = compute_map->find(name);
if (found != compute_map->end()) compute_map->erase(name);
for (int icompute = lmp->modify->find_compute_by_style(name);
icompute >= 0; icompute = lmp->modify->find_compute_by_style(name))
lmp->modify->delete_compute(icompute);
} else if (pstyle == "fix") {
auto fix_map = lmp->modify->fix_map;
auto found = fix_map->find(name);
if (found != fix_map->end()) fix_map->erase(name);
for (int ifix = lmp->modify->find_fix_by_style(name);
ifix >= 0; ifix = lmp->modify->find_fix_by_style(name))
lmp->modify->delete_fix(ifix);
} else if (pstyle == "region") {
auto region_map = lmp->domain->region_map;
auto found = region_map->find(name);
if (found != region_map->end()) region_map->erase(name);
for (int iregion = lmp->domain->find_region_by_style(name);
iregion >= 0; iregion = lmp->domain->find_region_by_style(name))
lmp->domain->delete_region(iregion);
} else if (pstyle == "command") {
auto command_map = lmp->input->command_map;
auto found = command_map->find(name);
if (found != command_map->end()) command_map->erase(name);
}
// if reference count is down to zero, close DSO handle.
-- dso_refcounter[handle];
if (dso_refcounter[handle] == 0) {
#ifndef WIN32
dlclose(handle);
#endif
}
#endif
}
/* --------------------------------------------------------------------
unload all loaded plugins
-------------------------------------------------------------------- */
void plugin_clear(LAMMPS *lmp)
{
while (pluginlist.size() > 0) {
auto p = pluginlist.begin();
plugin_unload(p->style,p->name,lmp);
}
}
/* --------------------------------------------------------------------
remove plugin of given name and style from internal lists
-------------------------------------------------------------------- */
void plugin_erase(const char *style, const char *name)
{
for (auto p=pluginlist.begin(); p != pluginlist.end(); ++p) {
if ((strcmp(style,p->style) == 0)
&& (strcmp(name,p->name) == 0)) {
pluginlist.erase(p);
return;
}
}
}
/* --------------------------------------------------------------------
number of styles loaded from plugin files
-------------------------------------------------------------------- */
int plugin_get_num_plugins()
{
return pluginlist.size();
}
/* --------------------------------------------------------------------
return position index in list of given plugin of given style
-------------------------------------------------------------------- */
int plugin_find(const char *style, const char *name)
{
int i=0;
for (auto entry : pluginlist) {
if ((strcmp(style,entry.style) == 0)
&& (strcmp(name,entry.name) == 0))
return i;
++i;
}
return -1;
}
/* --------------------------------------------------------------------
get pointer to plugin initializer struct at position idx
-------------------------------------------------------------------- */
const lammpsplugin_t *plugin_get_info(int idx)
{
int i=0;
for (auto p=pluginlist.begin(); p != pluginlist.end(); ++p) {
if (i == idx) return &(*p);
++i;
}
return nullptr;
}
}

48
src/PLUGIN/plugin.h Normal file
View File

@ -0,0 +1,48 @@
/* -*- c++ -*- ----------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#ifdef COMMAND_CLASS
CommandStyle(plugin,Plugin)
#else
#ifndef LMP_PLUGIN_H
#define LMP_PLUGIN_H
#include "lammpsplugin.h"
#include "pointers.h"
namespace LAMMPS_NS
{
class Plugin : protected Pointers {
public:
Plugin(class LAMMPS *);
void command(int, char **);
};
void plugin_load(const char *, LAMMPS *);
void plugin_register(lammpsplugin_t *, void *);
void plugin_unload(const char *, const char *, LAMMPS *);
void plugin_erase(const char *, const char *);
void plugin_clear(LAMMPS *);
int plugin_get_num_plugins();
int plugin_find(const char *, const char *);
const lammpsplugin_t *plugin_get_info(int);
}
#endif
#endif

View File

@ -1816,8 +1816,18 @@ void Domain::delete_region(int narg, char **arg)
int iregion = find_region(arg[0]);
if (iregion == -1) error->all(FLERR,"Delete region ID does not exist");
delete_region(iregion);
}
void Domain::delete_region(int iregion)
{
if ((iregion < 0) || (iregion >= nregion)) return;
// delete and move other Regions down in list one slot
delete regions[iregion];
regions[iregion] = regions[nregion-1];
for (int i = iregion+1; iregion < nregion; ++i)
regions[i-1] = regions[i];
nregion--;
}
@ -1833,6 +1843,18 @@ int Domain::find_region(const std::string &name)
return -1;
}
/* ----------------------------------------------------------------------
return region index if name matches existing region style
return -1 if no such region
------------------------------------------------------------------------- */
int Domain::find_region_by_style(const std::string &name)
{
for (int iregion = 0; iregion < nregion; iregion++)
if (name == regions[iregion]->style) return iregion;
return -1;
}
/* ----------------------------------------------------------------------
(re)set boundary settings
flag = 0, called from the input script

View File

@ -130,7 +130,9 @@ class Domain : protected Pointers {
void set_lattice(int, char **);
void add_region(int, char **);
void delete_region(int, char **);
void delete_region(int);
int find_region(const std::string &);
int find_region_by_style(const std::string &);
void set_boundary(int, char **, int);
void set_box(int, char **);
void print_box(const std::string &);

View File

@ -82,6 +82,7 @@ class Input : protected Pointers {
void log();
void next_command();
void partition();
void plugin();
void print();
void python();
void quit();

48
src/lammpsplugin.h Normal file
View File

@ -0,0 +1,48 @@
/* -*- c++ -*- ----------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#ifndef LMP_LAMMPSPLUGIN_H
#define LMP_LAMMPSPLUGIN_H
// C style API and data structure required for dynamic loading
extern "C" {
typedef void *(lammpsplugin_factory1)(void *);
typedef void *(lammpsplugin_factory2)(void *, int, char **);
typedef void (lammpsplugin_factory3)(void *, int, char **);
typedef struct {
const char *version;
const char *style;
const char *name;
const char *info;
const char *author;
union {
lammpsplugin_factory1 *v1;
lammpsplugin_factory2 *v2;
lammpsplugin_factory3 *v3;
} creator;
void *handle;
} lammpsplugin_t;
typedef void (*lammpsplugin_regfunc)(lammpsplugin_t *, void *);
typedef void (*lammpsplugin_initfunc)(void *, void *, void *);
// prototype for initializer function required
// to load a plugin; uses C bindings
void lammpsplugin_init(void *, void *, void *);
}
#endif

View File

@ -40,6 +40,9 @@
#include "region.h"
#include "respa.h"
#include "output.h"
#if defined(LMP_PLUGIN)
#include "plugin.h"
#endif
#include "thermo.h"
#include "timer.h"
#include "universe.h"
@ -981,7 +984,7 @@ to then decide how to cast the (void*) pointer and access the data.
\endverbatim
*
* \param handle pointer to a previously created LAMMPS instance
* \param handle pointer to a previously created LAMMPS instance (unused)
* \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. */
@ -4595,6 +4598,65 @@ int lammps_id_name(void *handle, const char *category, int idx,
return 0;
}
/* ---------------------------------------------------------------------- */
/** Count the number of loaded plugins
*
\verbatim embed:rst
This function counts how many plugins are currently loaded.
.. versionadded:: 10Mar2021
\endverbatim
*
* \return number of loaded plugins
*/
int lammps_plugin_count()
{
#if defined(LMP_PLUGIN)
return plugin_get_num_plugins();
#else
return 0;
#endif
}
/* ---------------------------------------------------------------------- */
/** Look up the info of a loaded plugin by its index in the list of plugins
*
\verbatim embed:rst
This function copies the name of the *style* plugin with the index
*idx* into the provided C-style string buffer. The length of the buffer
must be provided as *buf_size* argument. If the name of the style
exceeds the length of the buffer, it will be truncated accordingly.
If the index is out of range, the function returns 0 and *buffer* is
set to an empty string, otherwise 1.
.. versionadded:: 10Mar2021
\endverbatim
*
* \param idx index of the plugin in the list all or *style* plugins
* \param stylebuf string buffer to copy the style of the plugin to
* \param namebuf string buffer to copy the name of the plugin to
* \param buf_size size of the provided string buffers
* \return 1 if successful, otherwise 0
*/
int lammps_plugin_name(int idx, char *stylebuf, char *namebuf, int buf_size)
{
#if defined(LMP_PLUGIN)
stylebuf[0] = namebuf[0] = '\0';
const lammpsplugin_t *plugin = plugin_get_info(idx);
if (plugin) {
strncpy(stylebuf,plugin->style,buf_size);
strncpy(namebuf,plugin->name,buf_size);
return 1;
}
#endif
return 0;
}
// ----------------------------------------------------------------------
// utility functions
// ----------------------------------------------------------------------

View File

@ -205,6 +205,9 @@ int lammps_has_id(void *, const char *, const char *);
int lammps_id_count(void *, const char *);
int lammps_id_name(void *, const char *, int, char *, int);
int lammps_plugin_count();
int lammps_plugin_name(int, char *, char *, int);
/* ----------------------------------------------------------------------
* Utility functions
* ---------------------------------------------------------------------- */

View File

@ -1069,10 +1069,12 @@ void Modify::delete_fix(const std::string &id)
void Modify::delete_fix(int ifix)
{
if (fix[ifix]) delete fix[ifix];
atom->update_callback(ifix);
if ((ifix < 0) || (ifix >= nfix)) return;
// move other Fixes and fmask down in list one slot
// delete instance and move other Fixes and fmask down in list one slot
delete fix[ifix];
atom->update_callback(ifix);
for (int i = ifix+1; i < nfix; i++) fix[i-1] = fix[i];
for (int i = ifix+1; i < nfix; i++) fmask[i-1] = fmask[i];
@ -1099,11 +1101,9 @@ int Modify::find_fix(const std::string &id)
int Modify::find_fix_by_style(const char *style)
{
int ifix;
for (ifix = 0; ifix < nfix; ifix++)
if (utils::strmatch(fix[ifix]->style,style)) break;
if (ifix == nfix) return -1;
return ifix;
for (int ifix = 0; ifix < nfix; ifix++)
if (utils::strmatch(fix[ifix]->style,style)) return ifix;
return -1;
}
/* ----------------------------------------------------------------------
@ -1326,10 +1326,16 @@ void Modify::delete_compute(const std::string &id)
{
int icompute = find_compute(id);
if (icompute < 0) error->all(FLERR,"Could not find compute ID to delete");
delete_compute(icompute);
}
void Modify::delete_compute(int icompute)
{
if ((icompute < 0) || (icompute >= ncompute)) return;
// delete and move other Computes down in list one slot
delete compute[icompute];
// move other Computes down in list one slot
for (int i = icompute+1; i < ncompute; i++) compute[i-1] = compute[i];
ncompute--;
}
@ -1347,6 +1353,18 @@ int Modify::find_compute(const std::string &id)
return -1;
}
/* ----------------------------------------------------------------------
find a compute by style
return index of compute or -1 if not found
------------------------------------------------------------------------- */
int Modify::find_compute_by_style(const char *style)
{
for (int icompute = 0; icompute < ncompute; icompute++)
if (utils::strmatch(compute[icompute]->style,style)) return icompute;
return -1;
}
/* ----------------------------------------------------------------------
clear invoked flag of all computes
called everywhere that computes are used, before computes are invoked

View File

@ -109,21 +109,24 @@ class Modify : protected Pointers {
void delete_fix(int);
int find_fix(const std::string &);
int find_fix_by_style(const char *);
int check_package(const char *);
int check_rigid_group_overlap(int);
int check_rigid_region_overlap(int, class Region *);
int check_rigid_list_overlap(int *);
void add_compute(int, char **, int trysuffix=1);
void add_compute(const std::string &, int trysuffix=1);
void modify_compute(int, char **);
void delete_compute(const std::string &);
void delete_compute(int);
int find_compute(const std::string &);
int find_compute_by_style(const char *);
void clearstep_compute();
void addstep_compute(bigint);
void addstep_compute_all(bigint);
int check_package(const char *);
int check_rigid_group_overlap(int);
int check_rigid_region_overlap(int, class Region *);
int check_rigid_list_overlap(int *);
void write_restart(FILE *);
int read_restart(FILE *);
void restart_deallocate(int);

View File

@ -128,6 +128,7 @@ const char *cmdlist[] = {"clear",
"pair_modify",
"pair_style",
"pair_write",
"plugin",
"processors",
"region",
"reset_timestep",
@ -347,6 +348,59 @@ static char *variable_expand_generator(const char *text, int state)
return nullptr;
}
static char *plugin_generator(const char *text, int state)
{
const char *subcmd[] = {"load", "unload", "list", "clear", NULL};
const char *sub;
static std::size_t idx, len;
if (!state) idx = 0;
len = strlen(text);
while ((sub = subcmd[idx]) != NULL) {
++idx;
if (strncmp(text,sub,len) == 0)
return dupstring(sub);
}
return nullptr;
}
static char *plugin_style_generator(const char *text, int state)
{
const char *styles[] = {"pair", "fix", "command", NULL};
const char *s;
static std::size_t idx, len;
if (!state) idx = 0;
len = strlen(text);
while ((s = styles[idx]) != NULL) {
++idx;
if (strncmp(text,s,len) == 0)
return dupstring(s);
}
return nullptr;
}
static char *plugin_name_generator(const char *text, int state)
{
auto words = utils::split_words(text);
if (words.size() < 4) return nullptr;
static std::size_t idx, len;
if (!state) idx = 0;
len = words[3].size();
int nmax = lammps_plugin_count();
while (idx < nmax) {
char style[buflen], name[buflen];
lammps_plugin_name(idx, style, name, buflen);
++idx;
if (words[2] == style) {
if (strncmp(name, words[3].c_str(), len) == 0)
return dupstring(name);
}
}
return nullptr;
}
static char *atom_generator(const char *text, int state)
{
return style_generator<ATOM_STYLE>(text, state);
@ -477,14 +531,21 @@ static char **cmd_completion(const char *text, int start, int)
matches = rl_completion_matches(text, dump_id_generator);
} else if (words[0] == "fix_modify") {
matches = rl_completion_matches(text, fix_id_generator);
} else if (words[0] == "plugin") {
matches = rl_completion_matches(text, plugin_generator);
}
} else if (words.size() == 2) { // expand third word
// these commands have a group name as 3rd word
if ((words[0] == "fix") || (words[0] == "compute") || (words[0] == "dump")) {
if ((words[0] == "fix")
|| (words[0] == "compute")
|| (words[0] == "dump")) {
matches = rl_completion_matches(text, group_generator);
} else if (words[0] == "region") {
matches = rl_completion_matches(text, region_generator);
// plugin style is the third word
} else if ((words[0] == "plugin") && (words[1] == "unload")) {
matches = rl_completion_matches(text, plugin_style_generator);
}
} else if (words.size() == 3) { // expand fourth word
@ -495,6 +556,9 @@ static char **cmd_completion(const char *text, int start, int)
matches = rl_completion_matches(text, compute_generator);
} else if (words[0] == "dump") {
matches = rl_completion_matches(text, dump_generator);
// plugin name is the fourth word
} else if ((words[0] == "plugin") && (words[1] == "unload")) {
matches = rl_completion_matches(rl_line_buffer, plugin_name_generator);
}
}
}

View File

@ -1,5 +1,31 @@
# build LAMMPS plugins, but not on Windows
if(NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Windows" AND PKG_PLUGIN)
ExternalProject_Add(plugins
SOURCE_DIR "${LAMMPS_DIR}/examples/plugins"
BINARY_DIR ${CMAKE_BINARY_DIR}/build-plugins
INSTALL_DIR ${CMAKE_BINARY_DIR}
CMAKE_ARGS ${CMAKE_REQUEST_PIC}
-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
-DCMAKE_INSTALL_PREFIX=<INSTALL_DIR>
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
-DCMAKE_MAKE_PROGRAM=${CMAKE_MAKE_PROGRAM}
-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}
BUILD_BYPRODUCTS <BINARY_DIR>/morse2plugin${CMAKE_SHARED_LIBRARY_SUFFIX}
<BINARY_DIR>/nve2plugin${CMAKE_SHARED_LIBRARY_SUFFIX}
<BINARY_DIR>/helloplugin${CMAKE_SHARED_LIBRARY_SUFFIX}
INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_if_different
<BINARY_DIR>/morse2plugin${CMAKE_SHARED_LIBRARY_SUFFIX}
<BINARY_DIR>/nve2plugin${CMAKE_SHARED_LIBRARY_SUFFIX}
<BINARY_DIR>/helloplugin${CMAKE_SHARED_LIBRARY_SUFFIX}
${CMAKE_CURRENT_BINARY_DIR}
TEST_COMMAND "")
endif()
add_executable(test_simple_commands test_simple_commands.cpp)
if(PKG_PLUGIN)
add_dependencies(test_simple_commands plugins)
endif()
target_link_libraries(test_simple_commands PRIVATE lammps GTest::GMock GTest::GTest)
add_test(NAME SimpleCommands COMMAND test_simple_commands WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})

View File

@ -367,6 +367,79 @@ TEST_F(SimpleCommandsTest, Units)
TEST_FAILURE(".*ERROR: Illegal units command.*", lmp->input->one("units unknown"););
}
#if defined(LMP_PLUGIN)
TEST_F(SimpleCommandsTest, Plugin)
{
#if defined(__APPLE__)
std::string loadfmt("plugin load {}plugin.dylib");
#else
std::string loadfmt("plugin load {}plugin.so");
#endif
::testing::internal::CaptureStdout();
lmp->input->one(fmt::format(loadfmt, "hello"));
auto text = ::testing::internal::GetCapturedStdout();
if (verbose) std::cout << text;
ASSERT_THAT(text, MatchesRegex(".*Loading plugin: Hello world command.*"));
::testing::internal::CaptureStdout();
lmp->input->one(fmt::format(loadfmt, "xxx"));
text = ::testing::internal::GetCapturedStdout();
if (verbose) std::cout << text;
ASSERT_THAT(text, MatchesRegex(".*Open of file xxx.* failed.*"));
::testing::internal::CaptureStdout();
lmp->input->one(fmt::format(loadfmt, "nve2"));
text = ::testing::internal::GetCapturedStdout();
if (verbose) std::cout << text;
ASSERT_THAT(text, MatchesRegex(".*Loading plugin: NVE2 variant fix style.*"));
::testing::internal::CaptureStdout();
lmp->input->one("plugin list");
text = ::testing::internal::GetCapturedStdout();
if (verbose) std::cout << text;
ASSERT_THAT(text, MatchesRegex(".*1: command style plugin hello"
".*2: fix style plugin nve2.*"));
::testing::internal::CaptureStdout();
lmp->input->one(fmt::format(loadfmt, "hello"));
text = ::testing::internal::GetCapturedStdout();
if (verbose) std::cout << text;
ASSERT_THAT(text, MatchesRegex(".*Ignoring load of command style hello: "
"must unload existing hello plugin.*"));
::testing::internal::CaptureStdout();
lmp->input->one("plugin unload command hello");
text = ::testing::internal::GetCapturedStdout();
if (verbose) std::cout << text;
ASSERT_THAT(text, MatchesRegex(".*Unloading command style hello.*"));
::testing::internal::CaptureStdout();
lmp->input->one("plugin unload pair nve2");
text = ::testing::internal::GetCapturedStdout();
if (verbose) std::cout << text;
ASSERT_THAT(text, MatchesRegex(".*Ignoring unload of pair style nve2: "
"not loaded from a plugin.*"));
::testing::internal::CaptureStdout();
lmp->input->one("plugin unload fix nve2");
text = ::testing::internal::GetCapturedStdout();
if (verbose) std::cout << text;
ASSERT_THAT(text, MatchesRegex(".*Unloading fix style nve2.*"));
::testing::internal::CaptureStdout();
lmp->input->one("plugin unload fix nve");
text = ::testing::internal::GetCapturedStdout();
if (verbose) std::cout << text;
ASSERT_THAT(text, MatchesRegex(".*Ignoring unload of fix style nve: "
"not loaded from a plugin.*"));
::testing::internal::CaptureStdout();
lmp->input->one("plugin list");
text = ::testing::internal::GetCapturedStdout();
if (verbose) std::cout << text;
ASSERT_THAT(text, MatchesRegex(".*Currently loaded plugins.*"));
}
#endif
TEST_F(SimpleCommandsTest, Shell)
{
if (!verbose) ::testing::internal::CaptureStdout();