Merge branch 'develop' into molecule-refactor-for-json

This commit is contained in:
Axel Kohlmeyer
2025-06-12 21:21:38 -04:00
31 changed files with 1460 additions and 82 deletions

View File

@ -1,9 +1,8 @@
# preset that enables KOKKOS and selects CUDA compilation with OpenMP
# enabled as well. The GPU architecture *must* match your hardware
# enabled as well. The GPU architecture *must* match your hardware (If not manually set, Kokkos will try to autodetect it).
set(PKG_KOKKOS ON CACHE BOOL "" FORCE)
set(Kokkos_ENABLE_SERIAL ON CACHE BOOL "" FORCE)
set(Kokkos_ENABLE_CUDA ON CACHE BOOL "" FORCE)
set(Kokkos_ARCH_PASCAL60 ON CACHE BOOL "" FORCE)
set(BUILD_OMP ON CACHE BOOL "" FORCE)
get_filename_component(NVCC_WRAPPER_CMD ${CMAKE_CURRENT_SOURCE_DIR}/../lib/kokkos/bin/nvcc_wrapper ABSOLUTE)
set(CMAKE_CXX_COMPILER ${NVCC_WRAPPER_CMD} CACHE FILEPATH "" FORCE)

View File

@ -31,3 +31,5 @@ OPT.
* :doc:`pppm/dielectric <kspace_style>`
* :doc:`pppm/electrode (i) <kspace_style>`
* :doc:`scafacos <kspace_style>`
* :doc:`zero <kspace_style>`

View File

@ -68,24 +68,25 @@ Members of ``lammpsplugin_t``
* - author
- String with the name and email of the author
* - creator.v1
- Pointer to factory function for pair, bond, angle, dihedral, improper, kspace, or command styles
- Pointer to factory function for pair, bond, angle, dihedral, improper, kspace, command, or minimize styles
* - creator.v2
- Pointer to factory function for compute, fix, or region styles
- Pointer to factory function for compute, fix, region, or run styles
* - handle
- Pointer to the open DSO file handle
Only one of the two 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) or command 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.
(i.e. pair, bond, angle, dihedral, or improper styles), command styles,
or minimize 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,
region, or run 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.
Pair style example
^^^^^^^^^^^^^^^^^^
@ -247,8 +248,8 @@ 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.
in a global 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
@ -263,6 +264,21 @@ the plugin will override the existing code. This can be used to modify
the behavior of existing styles or to debug new versions of them without
having to re-compile or re-install all of LAMMPS.
.. versionchanged:: 12Jun2025
When using the :doc:`clear <clear>` command, plugins are not unloaded
but restored to their respective style maps. This also applies when
multiple LAMMPS instances are created and deleted through the library
interface. The :doc:`plugin load <plugin>` load command may be issued
again, but for existing plugins they will be skipped. To replace
plugins they must be explicitly unloaded with :doc:`plugin unload
<plugin>`. When multiple LAMMPS instances are created concurrently, any
loaded plugins will be added to the global list of plugins, but are not
immediately available to any LAMMPS instance that was created before
loading the plugin. To "import" such plugins, the :doc:`plugin restore
<plugin>` may be used. Plugins are only removed when they are explicitly
unloaded or the LAMMPS interface is "finalized".
Compiling plugins
^^^^^^^^^^^^^^^^^

View File

@ -69,10 +69,11 @@ statement. Internally, it will call either
:cpp:func:`lammps_open_fortran` or :cpp:func:`lammps_open_no_mpi` from
the C library API to create the class instance. All arguments are
optional and :cpp:func:`lammps_mpi_init` will be called automatically
if it is needed. Similarly, a possible call to
:cpp:func:`lammps_mpi_finalize` is integrated into the :f:func:`close`
function and triggered with the optional logical argument set to
``.TRUE.``. Here is a simple example:
if it is needed. Similarly, optional calls to
:cpp:func:`lammps_mpi_finalize`, :cpp:func:`lammps_kokkos_finalize`,
:cpp:func:`lammps_python_finalize`, and :cpp:func:`lammps_plugin_finalize`
are integrated into the :f:func:`close` function and triggered with the
optional logical argument set to ``.TRUE.``. Here is a simple example:
.. code-block:: fortran
@ -521,8 +522,8 @@ Procedures Bound to the :f:type:`lammps` Derived Type
This method will close down the LAMMPS instance through calling
:cpp:func:`lammps_close`. If the *finalize* argument is present and
has a value of ``.TRUE.``, then this subroutine also calls
:cpp:func:`lammps_kokkos_finalize` and
:cpp:func:`lammps_mpi_finalize`.
:cpp:func:`lammps_kokkos_finalize`, :cpp:func:`lammps_mpi_finalize`,
:cpp:func:`lammps_python_finalize`, and :cpp:func:`lammps_plugin_finalize`.
:o finalize: shut down the MPI environment of the LAMMPS
library if ``.TRUE.``.
@ -530,6 +531,8 @@ Procedures Bound to the :f:type:`lammps` Derived Type
:to: :cpp:func:`lammps_close`
:to: :cpp:func:`lammps_mpi_finalize`
:to: :cpp:func:`lammps_kokkos_finalize`
:to: :cpp:func:`lammps_python_finalize`
:to: :cpp:func:`lammps_plugin_finalize`
--------

View File

@ -11,6 +11,7 @@ This section documents the following functions:
- :cpp:func:`lammps_mpi_finalize`
- :cpp:func:`lammps_kokkos_finalize`
- :cpp:func:`lammps_python_finalize`
- :cpp:func:`lammps_plugin_finalize`
- :cpp:func:`lammps_error`
--------------------
@ -119,5 +120,10 @@ calling program.
-----------------------
.. doxygenfunction:: lammps_plugin_finalize
:project: progguide
-----------------------
.. doxygenfunction:: lammps_error
:project: progguide

View File

@ -32,6 +32,7 @@
.. index:: kspace_style msm/cg/omp
.. index:: kspace_style msm/dielectric
.. index:: kspace_style scafacos
.. index:: kspace_style zero
kspace_style command
====================
@ -43,7 +44,7 @@ Syntax
kspace_style style value
* style = *none* or *ewald* or *ewald/dipole* or *ewald/dipole/spin* or *ewald/disp* or *ewald/disp/dipole* or *ewald/omp* or *ewald/electrode* or *pppm* or *pppm/cg* or *pppm/disp* or *pppm/tip4p* or *pppm/stagger* or *pppm/disp/tip4p* or *pppm/gpu* or *pppm/intel* or *pppm/disp/intel* or *pppm/kk* or *pppm/omp* or *pppm/cg/omp* or *pppm/disp/tip4p/omp* or *pppm/tip4p/omp* or *pppm/dielectic* or *pppm/disp/dielectric* or *pppm/electrode* or *pppm/electrode/intel* or *msm* or *msm/cg* or *msm/omp* or *msm/cg/omp* or *msm/dielectric* or *scafacos*
* style = *none* or *ewald* or *ewald/dipole* or *ewald/dipole/spin* or *ewald/disp* or *ewald/disp/dipole* or *ewald/omp* or *ewald/electrode* or *pppm* or *pppm/cg* or *pppm/disp* or *pppm/tip4p* or *pppm/stagger* or *pppm/disp/tip4p* or *pppm/gpu* or *pppm/intel* or *pppm/disp/intel* or *pppm/kk* or *pppm/omp* or *pppm/cg/omp* or *pppm/disp/tip4p/omp* or *pppm/tip4p/omp* or *pppm/dielectic* or *pppm/disp/dielectric* or *pppm/electrode* or *pppm/electrode/intel* or *msm* or *msm/cg* or *msm/omp* or *msm/cg/omp* or *msm/dielectric* or *scafacos* or *zero*
.. parsed-literal::
@ -121,6 +122,7 @@ Syntax
*scafacos* values = method accuracy
method = fmm or p2nfft or p3m or ewald or direct
accuracy = desired relative error in forces
*zero* value = none
Examples
""""""""
@ -132,6 +134,7 @@ Examples
kspace_style msm 1.0e-4
kspace_style scafacos fmm 1.0e-4
kspace_style none
kspace_style zero
Used in input scripts:
@ -375,6 +378,13 @@ other ScaFaCoS options currently exposed to LAMMPS.
----------
.. versionadded:: 12Jun2025
The *zero* style does not do any calculations, but is compatible
with all pair styles that require some version of a kspace style.
----------
The specified *accuracy* determines the relative RMS error in per-atom
forces calculated by the long-range solver. It is set as a
dimensionless number, relative to the force that two unit point

View File

@ -10,16 +10,17 @@ Syntax
plugin command args
* command = *load* or *unload* or *list* or *clear*
* command = *load* or *unload* or *list* or *clear* or *restore*
* 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 *kspace* or *compute* or *fix* or *region* or *command*
*style* = *pair* or *bond* or *angle* or *dihedral* or *improper* or *kspace* or *compute* or *fix* or *region* or *command* or *run* or *min*
*list* = print a list of currently loaded plugins
*clear* = unload all currently loaded plugins
*restore* = restore all loaded plugins
Examples
""""""""
@ -31,6 +32,7 @@ Examples
plugin unload command hello
plugin list
plugin clear
plugin restore
Description
"""""""""""
@ -40,22 +42,46 @@ 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.
.. admonition:: Plugins are a global, per-executable property
:class: Hint
Unlike most settings in LAMMPS, plugins are a per-executable global
property. Loading a plugin means that it is not only available for
the current LAMMPS instance but for all *future* LAMMPS instances.
After a :doc:`clear <clear>` command, all currently loaded plugins
will be restored and do not need to be loaded again.
When using the library interface or the Python or Fortran module
to create multiple concurrent LAMMPS instances, all plugins should
be loaded by the first created LAMMPS instance as all future instances
will inherit them. To import plugins that were loaded by a different
LAMMPS instance, use the *restore* command.
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
plugin DSO with the given filename. A message with information about
the plugin style and name and more will be printed. Individual DSO
files may contain multiple plugins. If a plugin is already loaded
it will be skipped. 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.
that style instance will be deleted and replaced by the default setting
for that style.
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.
.. versionadded:: 12Jun2025
The *restore* command will restore all currently loaded plugins.
This allows to "import" plugins into a different LAMMPS instance.
.. admonition:: Automatic loading of plugins
:class: note

View File

@ -79,6 +79,7 @@ liblammpsplugin_t *liblammpsplugin_load(const char *lib)
ADDSYM(mpi_finalize);
ADDSYM(kokkos_finalize);
ADDSYM(python_finalize);
ADDSYM(plugin_finalize);
ADDSYM(error);
ADDSYM(expand);

View File

@ -134,6 +134,7 @@ struct _liblammpsplugin {
void (*mpi_finalize)();
void (*kokkos_finalize)();
void (*python_finalize)();
void (*plugin_finalize)();
void (*error)(void *, int, const char *);
char *(*expand)(void *, const char *);

View File

@ -94,7 +94,13 @@ 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 "" SUFFIX ".so")
add_library(kspaceplugin MODULE kspaceplugin.cpp kspace_zero2.cpp)
target_link_libraries(kspaceplugin PRIVATE lammps)
add_library(runminplugin MODULE runminplugin.cpp min_cg2.cpp verlet2.cpp)
target_link_libraries(runminplugin PRIVATE lammps)
set_target_properties(morse2plugin nve2plugin helloplugin zero2plugin kspaceplugin runminplugin PROPERTIES PREFIX "" SUFFIX ".so")
# MacOS seems to need this
if(CMAKE_SYSTEM_NAME STREQUAL Darwin)
@ -105,13 +111,13 @@ elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows")
set_target_properties(morse2plugin nve2plugin helloplugin zero2plugin
PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS TRUE)
if(CMAKE_CROSSCOMPILING)
set_target_properties(morse2plugin nve2plugin helloplugin zero2plugin
set_target_properties(morse2plugin nve2plugin helloplugin zero2plugin kspaceplugin runminplugin
PROPERTIES LINK_FLAGS "-Wl,--export-all-symbols")
endif()
else()
set_target_properties(morse2plugin nve2plugin helloplugin zero2plugin PROPERTIES
set_target_properties(morse2plugin nve2plugin helloplugin zero2plugin kspaceplugin runminplugin PROPERTIES
LINK_FLAGS "-rdynamic")
endif()
add_custom_target(plugins ALL ${CMAKE_COMMAND} -E echo "Building Plugins"
DEPENDS morse2plugin nve2plugin helloplugin zero2plugin morse2plugin)
DEPENDS morse2plugin nve2plugin helloplugin zero2plugin morse2plugin kspaceplugin runminplugin)

View File

@ -0,0 +1,112 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/, Sandia National Laboratories
LAMMPS development team: developers@lammps.org
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)
------------------------------------------------------------------------- */
#include "kspace_zero2.h"
#include "atom.h"
#include "comm.h"
#include "domain.h"
#include "error.h"
#include "force.h"
#include "pair.h"
#include <cstring>
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
KSpaceZero2::KSpaceZero2(LAMMPS *lmp) : KSpace(lmp)
{
ewaldflag = 1;
pppmflag = 1;
msmflag = 1;
dispersionflag = 1;
tip4pflag = 1;
dipoleflag = 1;
spinflag = 1;
}
/* ---------------------------------------------------------------------- */
void KSpaceZero2::settings(int narg, char **arg)
{
if (narg != 1) error->all(FLERR, "Illegal kspace_style {} command", force->kspace_style);
accuracy_relative = fabs(utils::numeric(FLERR, arg[0], false, lmp));
if (accuracy_relative > 1.0)
error->all(FLERR, "Invalid relative accuracy {:g} for kspace_style {}", accuracy_relative,
force->kspace_style);
if ((narg != 0) && (narg != 1)) error->all(FLERR, "Illegal kspace_style command");
}
/* ---------------------------------------------------------------------- */
void KSpaceZero2::init()
{
if (comm->me == 0) utils::logmesg(lmp, "Dummy KSpace initialization ...\n");
// error checks
if (force->pair == nullptr) error->all(FLERR, "KSpace solver requires a pair style");
if (!atom->q_flag) error->all(FLERR, "KSpace style zero2 requires atom attribute q");
// compute two charge force
two_charge();
int itmp;
auto p_cutoff = (double *) force->pair->extract("cut_coul", itmp);
if (p_cutoff == nullptr) error->all(FLERR, "KSpace style is incompatible with Pair style");
double cutoff = *p_cutoff;
qsum_qsq();
accuracy = accuracy_relative * two_charge_force;
// make initial g_ewald estimate
// based on desired accuracy and real space cutoff
// fluid-occupied volume used to estimate real-space error
// zprd used rather than zprd_slab
if (!gewaldflag) {
if (accuracy <= 0.0) error->all(FLERR, "KSpace accuracy must be > 0");
if (q2 == 0.0) error->all(FLERR, "Must use 'kspace_modify gewald' for uncharged system");
g_ewald = accuracy * sqrt(atom->natoms * cutoff * domain->xprd * domain->yprd * domain->zprd) /
(2.0 * q2);
if (g_ewald >= 1.0)
g_ewald = (1.35 - 0.15 * log(accuracy)) / cutoff;
else
g_ewald = sqrt(-log(g_ewald)) / cutoff;
}
if (comm->me == 0) utils::logmesg(lmp, " G vector (1/distance) = {:.8g}\n", g_ewald);
}
/* ---------------------------------------------------------------------- */
void KSpaceZero2::setup()
{
if (comm->me == 0) utils::logmesg(lmp, "Dummy KSpace setup\n");
}
/* ---------------------------------------------------------------------- */
void KSpaceZero2::compute(int eflag, int vflag)
{
ev_init(eflag, vflag);
}

View File

@ -0,0 +1,32 @@
/* -*- c++ -*- ----------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/ Sandia National Laboratories
LAMMPS development team: developers@lammps.org
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_KSPACE_ZERO2_H
#define LMP_KSPACE_ZERO2_H
#include "kspace.h"
namespace LAMMPS_NS {
class KSpaceZero2 : public KSpace {
public:
KSpaceZero2(class LAMMPS *);
void init() override;
void setup() override;
void settings(int, char **) override;
void compute(int, int) override;
};
} // namespace LAMMPS_NS
#endif

View File

@ -0,0 +1,34 @@
#include "lammpsplugin.h"
#include "comm.h"
#include "command.h"
#include "error.h"
#include "version.h"
#include <cstring>
#include "kspace_zero2.h"
using namespace LAMMPS_NS;
static KSpace *zero2creator(LAMMPS *lmp)
{
KSpace *ptr = (KSpace *) new KSpaceZero2(lmp);
return ptr;
}
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 = "kspace";
plugin.name = "zero2";
plugin.info = "zero2 KSpace style v1.0";
plugin.author = "Axel Kohlmeyer (akohlmey@gmail.com)";
plugin.creator.v1 = (lammpsplugin_factory1 *) &zero2creator;
plugin.handle = handle;
(*register_plugin)(&plugin, lmp);
}

View File

@ -0,0 +1,192 @@
// clang-format off
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/, Sandia National Laboratories
LAMMPS development team: developers@lammps.org
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 "min_cg2.h"
#include "error.h"
#include "output.h"
#include "timer.h"
#include "update.h"
#include <cmath>
using namespace LAMMPS_NS;
// EPS_ENERGY = minimum normalization for energy tolerance
static constexpr double EPS_ENERGY = 1.0e-8;
/* ---------------------------------------------------------------------- */
MinCG2::MinCG2(LAMMPS *lmp) : MinLineSearch(lmp) {}
/* ----------------------------------------------------------------------
minimization via conjugate gradient iterations
------------------------------------------------------------------------- */
int MinCG2::iterate(int maxiter)
{
int i,m,n,fail,ntimestep;
double beta,gg,dot[2],dotall[2],fdotf;
double *fatom,*gatom,*hatom;
// nlimit = max # of CG iterations before restarting
// set to ndoftotal unless too big
int nlimit = static_cast<int> (MIN(MAXSMALLINT,ndoftotal));
// initialize working vectors
for (i = 0; i < nvec; i++) h[i] = g[i] = fvec[i];
if (nextra_atom)
for (m = 0; m < nextra_atom; m++) {
fatom = fextra_atom[m];
gatom = gextra_atom[m];
hatom = hextra_atom[m];
n = extra_nlen[m];
for (i = 0; i < n; i++) hatom[i] = gatom[i] = fatom[i];
}
if (nextra_global)
for (i = 0; i < nextra_global; i++) hextra[i] = gextra[i] = fextra[i];
gg = fnorm_sqr();
for (int iter = 0; iter < maxiter; iter++) {
if (timer->check_timeout(niter))
return TIMEOUT;
ntimestep = ++update->ntimestep;
niter++;
// line minimization along direction h from current atom->x
eprevious = ecurrent;
fail = (this->*linemin)(ecurrent,alpha_final);
if (fail) return fail;
// function evaluation criterion
if (neval >= update->max_eval) return MAXEVAL;
// energy tolerance criterion
if (fabs(ecurrent-eprevious) <
update->etol * 0.5*(fabs(ecurrent) + fabs(eprevious) + EPS_ENERGY))
return ETOL;
// force tolerance criterion
dot[0] = dot[1] = 0.0;
for (i = 0; i < nvec; i++) {
dot[0] += fvec[i]*fvec[i];
dot[1] += fvec[i]*g[i];
}
if (nextra_atom)
for (m = 0; m < nextra_atom; m++) {
fatom = fextra_atom[m];
gatom = gextra_atom[m];
n = extra_nlen[m];
for (i = 0; i < n; i++) {
dot[0] += fatom[i]*fatom[i];
dot[1] += fatom[i]*gatom[i];
}
}
MPI_Allreduce(dot,dotall,2,MPI_DOUBLE,MPI_SUM,world);
if (nextra_global)
for (i = 0; i < nextra_global; i++) {
dotall[0] += fextra[i]*fextra[i];
dotall[1] += fextra[i]*gextra[i];
}
fdotf = 0.0;
if (update->ftol > 0.0) {
if (normstyle == MAX) fdotf = fnorm_max(); // max force norm
else if (normstyle == INF) fdotf = fnorm_inf(); // infinite force norm
else if (normstyle == TWO) fdotf = dotall[0]; // same as fnorm_sqr(), Euclidean force 2-norm
else error->all(FLERR,"Illegal min_modify command");
if (fdotf < update->ftol*update->ftol) return FTOL;
}
// update new search direction h from new f = -Grad(x) and old g
// this is Polak-Ribieri formulation
// beta = dotall[0]/gg would be Fletcher-Reeves
// reinitialize CG every ndof iterations by setting beta = 0.0
beta = MAX(0.0,(dotall[0] - dotall[1])/gg);
if ((niter+1) % nlimit == 0) beta = 0.0;
gg = dotall[0];
for (i = 0; i < nvec; i++) {
g[i] = fvec[i];
h[i] = g[i] + beta*h[i];
}
if (nextra_atom)
for (m = 0; m < nextra_atom; m++) {
fatom = fextra_atom[m];
gatom = gextra_atom[m];
hatom = hextra_atom[m];
n = extra_nlen[m];
for (i = 0; i < n; i++) {
gatom[i] = fatom[i];
hatom[i] = gatom[i] + beta*hatom[i];
}
}
if (nextra_global)
for (i = 0; i < nextra_global; i++) {
gextra[i] = fextra[i];
hextra[i] = gextra[i] + beta*hextra[i];
}
// reinitialize CG if new search direction h is not downhill
dot[0] = 0.0;
for (i = 0; i < nvec; i++) dot[0] += g[i]*h[i];
if (nextra_atom)
for (m = 0; m < nextra_atom; m++) {
gatom = gextra_atom[m];
hatom = hextra_atom[m];
n = extra_nlen[m];
for (i = 0; i < n; i++) dot[0] += gatom[i]*hatom[i];
}
MPI_Allreduce(dot,dotall,1,MPI_DOUBLE,MPI_SUM,world);
if (nextra_global)
for (i = 0; i < nextra_global; i++)
dotall[0] += gextra[i]*hextra[i];
if (dotall[0] <= 0.0) {
for (i = 0; i < nvec; i++) h[i] = g[i];
if (nextra_atom)
for (m = 0; m < nextra_atom; m++) {
gatom = gextra_atom[m];
hatom = hextra_atom[m];
n = extra_nlen[m];
for (i = 0; i < n; i++) hatom[i] = gatom[i];
}
if (nextra_global)
for (i = 0; i < nextra_global; i++) hextra[i] = gextra[i];
}
// output for thermo, dump, restart files
if (output->next == ntimestep) {
timer->stamp();
output->write(ntimestep);
timer->stamp(Timer::OUTPUT);
}
}
return MAXITER;
}

View File

@ -0,0 +1,29 @@
/* -*- c++ -*- ----------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/, Sandia National Laboratories
LAMMPS development team: developers@lammps.org
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_MIN_CG2_H
#define LMP_MIN_CG2_H
#include "min_linesearch.h"
namespace LAMMPS_NS {
class MinCG2 : public MinLineSearch {
public:
MinCG2(class LAMMPS *);
int iterate(int) override;
};
} // namespace LAMMPS_NS
#endif

View File

@ -0,0 +1,45 @@
#include "lammpsplugin.h"
#include "version.h"
#include <cstring>
#include "min_cg2.h"
#include "verlet2.h"
using namespace LAMMPS_NS;
static Min *min_cg2creator(LAMMPS *lmp)
{
return new MinCG2(lmp);
}
static Integrate *verlet2creator(LAMMPS *lmp, int argc, char **argv)
{
return new Verlet2(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 = "min";
plugin.name = "cg2";
plugin.info = "CG2 minimize style v1.0";
plugin.author = "Axel Kohlmeyer (akohlmey@gmail.com)";
plugin.creator.v1 = (lammpsplugin_factory1 *) &min_cg2creator;
plugin.handle = handle;
(*register_plugin)(&plugin, lmp);
plugin.style = "run";
plugin.name = "verlet2";
plugin.info = "Verlet2 run style v1.0";
plugin.author = "Axel Kohlmeyer (akohlmey@gmail.com)";
plugin.creator.v2 = (lammpsplugin_factory2 *) &verlet2creator;
plugin.handle = handle;
(*register_plugin)(&plugin, lmp);
}

View File

@ -0,0 +1,426 @@
// clang-format off
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/, Sandia National Laboratories
LAMMPS development team: developers@lammps.org
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 "verlet2.h"
#include "angle.h"
#include "atom.h"
#include "atom_vec.h"
#include "bond.h"
#include "comm.h"
#include "dihedral.h"
#include "domain.h"
#include "error.h"
#include "fix.h"
#include "force.h"
#include "improper.h"
#include "kspace.h"
#include "modify.h"
#include "neighbor.h"
#include "output.h"
#include "pair.h"
#include "timer.h"
#include "update.h"
#include <cstring>
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
Verlet2::Verlet2(LAMMPS *lmp, int narg, char **arg) :
Integrate(lmp, narg, arg) {}
Verlet2::~Verlet2()
{
// do nothing
}
/* ----------------------------------------------------------------------
initialization before run
------------------------------------------------------------------------- */
void Verlet2::init()
{
Integrate::init();
// warn if no fixes doing time integration
bool do_time_integrate = false;
for (const auto &fix : modify->get_fix_list())
if (fix->time_integrate) do_time_integrate = true;
if (!do_time_integrate && (comm->me == 0))
error->warning(FLERR,"No fixes with time integration, atoms won't move" + utils::errorurl(28));
// virial_style:
// VIRIAL_PAIR if computed explicitly in pair via sum over pair interactions
// VIRIAL_FDOTR if computed implicitly in pair by
// virial_fdotr_compute() via sum over ghosts
if (force->newton_pair) virial_style = VIRIAL_FDOTR;
else virial_style = VIRIAL_PAIR;
// setup lists of computes for global and per-atom PE and pressure
ev_setup();
// detect if fix omp is present for clearing force arrays
if (modify->get_fix_by_id("package_omp")) external_force_clear = 1;
// set flags for arrays to clear in force_clear()
torqueflag = extraflag = 0;
if (atom->torque_flag) torqueflag = 1;
if (atom->avec->forceclearflag) extraflag = 1;
// orthogonal vs triclinic simulation box
triclinic = domain->triclinic;
}
/* ----------------------------------------------------------------------
setup before run
------------------------------------------------------------------------- */
void Verlet2::setup(int flag)
{
if (comm->me == 0 && screen) {
fputs("Setting up Verlet2 run ...\n",screen);
if (flag) {
utils::print(screen," Unit style : {}\n"
" Current step : {}\n"
" Time step : {}\n",
update->unit_style,update->ntimestep,update->dt);
timer->print_timeout(screen);
}
}
if (lmp->kokkos)
error->all(FLERR,"KOKKOS package requires run_style verlet2/kk");
update->setupflag = 1;
// setup domain, communication and neighboring
// acquire ghosts
// build neighbor lists
atom->setup();
modify->setup_pre_exchange();
if (triclinic) domain->x2lamda(atom->nlocal);
domain->pbc();
domain->reset_box();
comm->setup();
if (neighbor->style) neighbor->setup_bins();
comm->exchange();
if (atom->sortfreq > 0) atom->sort();
comm->borders();
if (triclinic) domain->lamda2x(atom->nlocal+atom->nghost);
domain->image_check();
domain->box_too_small_check();
modify->setup_pre_neighbor();
neighbor->build(1);
modify->setup_post_neighbor();
neighbor->ncalls = 0;
// compute all forces
force->setup();
ev_set(update->ntimestep);
force_clear();
modify->setup_pre_force(vflag);
if (pair_compute_flag) force->pair->compute(eflag,vflag);
else if (force->pair) force->pair->compute_dummy(eflag,vflag);
if (atom->molecular != Atom::ATOMIC) {
if (force->bond) force->bond->compute(eflag,vflag);
if (force->angle) force->angle->compute(eflag,vflag);
if (force->dihedral) force->dihedral->compute(eflag,vflag);
if (force->improper) force->improper->compute(eflag,vflag);
}
if (force->kspace) {
force->kspace->setup();
if (kspace_compute_flag) force->kspace->compute(eflag,vflag);
else force->kspace->compute_dummy(eflag,vflag);
}
modify->setup_pre_reverse(eflag,vflag);
if (force->newton) comm->reverse_comm();
modify->setup(vflag);
output->setup(flag);
update->setupflag = 0;
}
/* ----------------------------------------------------------------------
setup without output
flag = 0 = just force calculation
flag = 1 = reneighbor and force calculation
------------------------------------------------------------------------- */
void Verlet2::setup_minimal(int flag)
{
update->setupflag = 1;
// setup domain, communication and neighboring
// acquire ghosts
// build neighbor lists
if (flag) {
modify->setup_pre_exchange();
if (triclinic) domain->x2lamda(atom->nlocal);
domain->pbc();
domain->reset_box();
comm->setup();
if (neighbor->style) neighbor->setup_bins();
comm->exchange();
comm->borders();
if (triclinic) domain->lamda2x(atom->nlocal+atom->nghost);
domain->image_check();
domain->box_too_small_check();
modify->setup_pre_neighbor();
neighbor->build(1);
modify->setup_post_neighbor();
neighbor->ncalls = 0;
}
// compute all forces
ev_set(update->ntimestep);
force_clear();
modify->setup_pre_force(vflag);
if (pair_compute_flag) force->pair->compute(eflag,vflag);
else if (force->pair) force->pair->compute_dummy(eflag,vflag);
if (atom->molecular != Atom::ATOMIC) {
if (force->bond) force->bond->compute(eflag,vflag);
if (force->angle) force->angle->compute(eflag,vflag);
if (force->dihedral) force->dihedral->compute(eflag,vflag);
if (force->improper) force->improper->compute(eflag,vflag);
}
if (force->kspace) {
force->kspace->setup();
if (kspace_compute_flag) force->kspace->compute(eflag,vflag);
else force->kspace->compute_dummy(eflag,vflag);
}
modify->setup_pre_reverse(eflag,vflag);
if (force->newton) comm->reverse_comm();
modify->setup(vflag);
update->setupflag = 0;
}
/* ----------------------------------------------------------------------
run for N steps
------------------------------------------------------------------------- */
void Verlet2::run(int n)
{
bigint ntimestep;
int nflag,sortflag;
int n_post_integrate = modify->n_post_integrate;
int n_pre_exchange = modify->n_pre_exchange;
int n_pre_neighbor = modify->n_pre_neighbor;
int n_post_neighbor = modify->n_post_neighbor;
int n_pre_force = modify->n_pre_force;
int n_pre_reverse = modify->n_pre_reverse;
int n_post_force_any = modify->n_post_force_any;
int n_end_of_step = modify->n_end_of_step;
if (atom->sortfreq > 0) sortflag = 1;
else sortflag = 0;
for (int i = 0; i < n; i++) {
if (timer->check_timeout(i)) {
update->nsteps = i;
break;
}
ntimestep = ++update->ntimestep;
ev_set(ntimestep);
// initial time integration
timer->stamp();
modify->initial_integrate(vflag);
if (n_post_integrate) modify->post_integrate();
timer->stamp(Timer::MODIFY);
// regular communication vs neighbor list rebuild
nflag = neighbor->decide();
if (nflag == 0) {
timer->stamp();
comm->forward_comm();
timer->stamp(Timer::COMM);
} else {
if (n_pre_exchange) {
timer->stamp();
modify->pre_exchange();
timer->stamp(Timer::MODIFY);
}
if (triclinic) domain->x2lamda(atom->nlocal);
domain->pbc();
if (domain->box_change) {
domain->reset_box();
comm->setup();
if (neighbor->style) neighbor->setup_bins();
}
timer->stamp();
comm->exchange();
if (sortflag && ntimestep >= atom->nextsort) atom->sort();
comm->borders();
if (triclinic) domain->lamda2x(atom->nlocal+atom->nghost);
timer->stamp(Timer::COMM);
if (n_pre_neighbor) {
modify->pre_neighbor();
timer->stamp(Timer::MODIFY);
}
neighbor->build(1);
timer->stamp(Timer::NEIGH);
if (n_post_neighbor) {
modify->post_neighbor();
timer->stamp(Timer::MODIFY);
}
}
// force computations
// important for pair to come before bonded contributions
// since some bonded potentials tally pairwise energy/virial
// and Pair:ev_tally() needs to be called before any tallying
force_clear();
timer->stamp();
if (n_pre_force) {
modify->pre_force(vflag);
timer->stamp(Timer::MODIFY);
}
if (pair_compute_flag) {
force->pair->compute(eflag,vflag);
timer->stamp(Timer::PAIR);
}
if (atom->molecular != Atom::ATOMIC) {
if (force->bond) force->bond->compute(eflag,vflag);
if (force->angle) force->angle->compute(eflag,vflag);
if (force->dihedral) force->dihedral->compute(eflag,vflag);
if (force->improper) force->improper->compute(eflag,vflag);
timer->stamp(Timer::BOND);
}
if (kspace_compute_flag) {
force->kspace->compute(eflag,vflag);
timer->stamp(Timer::KSPACE);
}
if (n_pre_reverse) {
modify->pre_reverse(eflag,vflag);
timer->stamp(Timer::MODIFY);
}
// reverse communication of forces
if (force->newton) {
comm->reverse_comm();
timer->stamp(Timer::COMM);
}
// force modifications, final time integration, diagnostics
if (n_post_force_any) modify->post_force(vflag);
modify->final_integrate();
if (n_end_of_step) modify->end_of_step();
timer->stamp(Timer::MODIFY);
// all output
if (ntimestep == output->next) {
timer->stamp();
output->write(ntimestep);
timer->stamp(Timer::OUTPUT);
}
}
}
/* ---------------------------------------------------------------------- */
void Verlet2::cleanup()
{
modify->post_run();
domain->box_too_small_check();
update->update_time();
}
/* ----------------------------------------------------------------------
clear force on own & ghost atoms
clear other arrays as needed
------------------------------------------------------------------------- */
void Verlet2::force_clear()
{
size_t nbytes;
if (external_force_clear) return;
// clear force on all particles
// if either newton flag is set, also include ghosts
// when using threads always clear all forces.
int nlocal = atom->nlocal;
if (neighbor->includegroup == 0) {
nbytes = sizeof(double) * nlocal;
if (force->newton) nbytes += sizeof(double) * atom->nghost;
if (nbytes) {
memset(&atom->f[0][0],0,3*nbytes);
if (torqueflag) memset(&atom->torque[0][0],0,3*nbytes);
if (extraflag) atom->avec->force_clear(0,nbytes);
}
// neighbor includegroup flag is set
// clear force only on initial nfirst particles
// if either newton flag is set, also include ghosts
} else {
nbytes = sizeof(double) * atom->nfirst;
if (nbytes) {
memset(&atom->f[0][0],0,3*nbytes);
if (torqueflag) memset(&atom->torque[0][0],0,3*nbytes);
if (extraflag) atom->avec->force_clear(0,nbytes);
}
if (force->newton) {
nbytes = sizeof(double) * atom->nghost;
if (nbytes) {
memset(&atom->f[nlocal][0],0,3*nbytes);
if (torqueflag) memset(&atom->torque[nlocal][0],0,3*nbytes);
if (extraflag) atom->avec->force_clear(nlocal,nbytes);
}
}
}
}

View File

@ -0,0 +1,39 @@
/* -*- c++ -*- ----------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/, Sandia National Laboratories
LAMMPS development team: developers@lammps.org
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_VERLET2_H
#define LMP_VERLET2_H
#include "integrate.h"
namespace LAMMPS_NS {
class Verlet2 : public Integrate {
public:
Verlet2(class LAMMPS *, int, char **);
~Verlet2() override;
void init() override;
void setup(int flag) override;
void setup_minimal(int) override;
void run(int) override;
void force_clear() override;
void cleanup() override;
protected:
int triclinic; // 0 if domain is orthog, 1 if triclinic
int torqueflag, extraflag;
};
} // namespace LAMMPS_NS
#endif

View File

@ -408,6 +408,12 @@ MODULE LIBLAMMPS
SUBROUTINE lammps_kokkos_finalize() BIND(C)
END SUBROUTINE lammps_kokkos_finalize
SUBROUTINE lammps_python_finalize() BIND(C)
END SUBROUTINE lammps_python_finalize
SUBROUTINE lammps_plugin_finalize() BIND(C)
END SUBROUTINE lammps_plugin_finalize
SUBROUTINE lammps_error(handle, error_type, error_text) BIND(C)
IMPORT :: c_ptr, c_int
IMPLICIT NONE
@ -1135,7 +1141,7 @@ CONTAINS
SIZE_IMAGEINT = lmp_extract_setting(lmp_open, 'imageint')
END FUNCTION lmp_open
! Combined Fortran wrapper around lammps_close() and lammps_mpi_finalize()
! Combined Fortran wrapper around lammps_close() and lammps_*_finalize()
SUBROUTINE lmp_close(self, finalize)
CLASS(lammps), INTENT(IN) :: self
LOGICAL, INTENT(IN), OPTIONAL :: finalize
@ -1146,6 +1152,8 @@ CONTAINS
IF (finalize) THEN
CALL lammps_kokkos_finalize()
CALL lammps_mpi_finalize()
CALL lammps_python_finalize()
CALL lammps_plugin_finalize()
END IF
END IF
END SUBROUTINE lmp_close

View File

@ -653,8 +653,9 @@ class lammps(object):
def finalize(self):
"""Shut down the MPI communication and Kokkos environment (if active) through the
library interface by calling :cpp:func:`lammps_mpi_finalize` and
:cpp:func:`lammps_kokkos_finalize`.
library interface by calling :cpp:func:`lammps_mpi_finalize`,
:cpp:func:`lammps_kokkos_finalize`, :cpp:func:`lammps_python_finalize`, and
:cpp:func:`lammps_plugin_finalize`
You cannot create or use any LAMMPS instances after this function is called
unless LAMMPS was compiled without MPI and without Kokkos support.
@ -662,6 +663,8 @@ class lammps(object):
self.close()
self.lib.lammps_kokkos_finalize()
self.lib.lammps_mpi_finalize()
self.lib.lammps_python_finalize()
self.lib.lammps_plugin_finalize()
# -------------------------------------------------------------------------

View File

@ -21,6 +21,7 @@
#include "force.h"
#include "input.h"
#include "modify.h"
#include "update.h"
#include <cstring>
#include <list>
@ -57,6 +58,9 @@ void Plugin::command(int narg, char **arg)
} else if (cmd == "clear") {
plugin_clear(lmp);
} else if (cmd == "restore") {
plugin_restore(lmp, false);
} else if (cmd == "list") {
if (comm->me == 0) {
int num = plugin_get_num_plugins();
@ -67,15 +71,16 @@ void Plugin::command(int narg, char **arg)
}
}
} else
error->all(FLERR, "Illegal plugin command");
error->all(FLERR, "Unknown plugin command {}", cmd);
}
// auto-load DSOs from designated folder(s)
void plugin_auto_load(LAMMPS *lmp)
{
#if defined(LMP_PLUGIN)
for (const auto &plugin_dir : platform::list_pathenv("LAMMPS_PLUGIN_PATH")) {
bool oldverbose = verbose;
verbose = false;
for (const auto &plugin_dir : platform::list_pathenv("LAMMPS_PLUGIN_PATH")) {
int count = 0;
for (const auto &file : platform::list_directory(plugin_dir)) {
if (utils::strmatch(file, "\\plugin.so$"))
@ -83,6 +88,7 @@ void plugin_auto_load(LAMMPS *lmp)
}
if (lmp->comm->me == 0) utils::logmesg(lmp, "Loaded {} plugins from {}\n", count, plugin_dir);
}
verbose = oldverbose;
#endif
}
@ -249,6 +255,23 @@ void plugin_register(lammpsplugin_t *plugin, void *ptr)
}
(*command_map)[plugin->name] = (Input::CommandCreator) plugin->creator.v1;
} else if (pstyle == "run") {
auto integrate_map = lmp->update->integrate_map;
if (integrate_map->find(plugin->name) != integrate_map->end()) {
if (lmp->comm->me == 0)
lmp->error->warning(FLERR, "Overriding built-in run style {} from plugin", plugin->name);
}
(*integrate_map)[plugin->name] = (Update::IntegrateCreator) plugin->creator.v2;
} else if (pstyle == "min") {
auto minimize_map = lmp->update->minimize_map;
if (minimize_map->find(plugin->name) != minimize_map->end()) {
if (lmp->comm->me == 0)
lmp->error->warning(FLERR, "Overriding built-in minimize style {} from plugin",
plugin->name);
}
(*minimize_map)[plugin->name] = (Update::MinimizeCreator) plugin->creator.v1;
} else {
utils::logmesg(lmp, "Loading plugins for {} styles not yet implemented\n", pstyle);
pluginlist.pop_back();
@ -272,7 +295,8 @@ void plugin_unload(const char *style, const char *name, LAMMPS *lmp)
(strcmp(style, "angle") != 0) && (strcmp(style, "dihedral") != 0) &&
(strcmp(style, "improper") != 0) && (strcmp(style, "kspace") != 0) &&
(strcmp(style, "compute") != 0) && (strcmp(style, "fix") != 0) &&
(strcmp(style, "region") != 0) && (strcmp(style, "command") != 0)) {
(strcmp(style, "region") != 0) && (strcmp(style, "command") != 0) &&
(strcmp(style, "run") != 0) && (strcmp(style, "min") != 0)) {
if (me == 0)
utils::logmesg(lmp, "Ignoring unload: {} is not a supported plugin style\n", style);
return;
@ -301,9 +325,6 @@ void plugin_unload(const char *style, const char *name, LAMMPS *lmp)
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) {
@ -314,87 +335,121 @@ void plugin_unload(const char *style, const char *name, LAMMPS *lmp)
}
}
} else if (pstyle == "bond") {
auto found = lmp->force->pair_map->find(name);
if (found != lmp->force->pair_map->end()) lmp->force->pair_map->erase(found);
auto found = lmp->force->bond_map->find(name);
if (found != lmp->force->bond_map->end()) lmp->force->bond_map->erase(found);
} else if (pstyle == "bond") {
// 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->bond_map->find(name);
if (found != lmp->force->bond_map->end()) lmp->force->bond_map->erase(found);
auto found = lmp->force->angle_map->find(name);
if (found != lmp->force->angle_map->end()) lmp->force->angle_map->erase(found);
} else if (pstyle == "angle") {
// 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->angle_map->find(name);
if (found != lmp->force->angle_map->end()) lmp->force->angle_map->erase(found);
auto found = lmp->force->dihedral_map->find(name);
if (found != lmp->force->dihedral_map->end()) lmp->force->dihedral_map->erase(found);
} else if (pstyle == "dihedral") {
// 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->dihedral_map->find(name);
if (found != lmp->force->dihedral_map->end()) lmp->force->dihedral_map->erase(found);
auto found = lmp->force->improper_map->find(name);
if (found != lmp->force->improper_map->end()) lmp->force->improper_map->erase(found);
} else if (pstyle == "improper") {
// 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);
auto found = lmp->force->improper_map->find(name);
if (found != lmp->force->improper_map->end()) lmp->force->improper_map->erase(found);
} else if (pstyle == "kspace") {
// must delete kspace style instance if in use
if ((lmp->force->kspace_style != nullptr) && (lmp->force->kspace_match(name, 1) != nullptr))
lmp->force->create_kspace("none", 0);
auto kspace_map = lmp->force->kspace_map;
auto found = kspace_map->find(name);
if (found != kspace_map->end()) kspace_map->erase(name);
} 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);
// must delete all compute instances using this compute style
for (auto &icompute : lmp->modify->get_compute_by_style(name))
lmp->modify->delete_compute(icompute->id);
} else if (pstyle == "fix") {
auto compute_map = lmp->modify->compute_map;
auto found = compute_map->find(name);
if (found != compute_map->end()) compute_map->erase(name);
auto fix_map = lmp->modify->fix_map;
auto found = fix_map->find(name);
if (found != fix_map->end()) fix_map->erase(name);
} else if (pstyle == "fix") {
// must delete all fix instances using this fix style
for (auto &ifix : lmp->modify->get_fix_by_style(name)) lmp->modify->delete_fix(ifix->id);
auto fix_map = lmp->modify->fix_map;
auto found = fix_map->find(name);
if (found != fix_map->end()) fix_map->erase(name);
} else if (pstyle == "region") {
// must delete all region instances using this region style
for (auto &iregion : lmp->domain->get_region_by_style(name))
lmp->domain->delete_region(iregion);
auto region_map = lmp->domain->region_map;
auto found = region_map->find(name);
if (found != region_map->end()) region_map->erase(name);
for (auto &iregion : lmp->domain->get_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);
} else if (pstyle == "run") {
// must restore default run style if plugin style is in use
if (strcmp(name, lmp->update->integrate_style) == 0) {
char *str = (char *) "verlet";
lmp->update->create_integrate(1, &str, 1);
}
auto integrate_map = lmp->update->integrate_map;
auto found = integrate_map->find(name);
if (found != integrate_map->end()) integrate_map->erase(name);
} else if (pstyle == "min") {
// must restore default minimize style if plugin style is in use
if (strcmp(name, lmp->update->minimize_style) == 0) {
char *str = (char *) "cg";
lmp->update->create_minimize(1, &str, 1);
}
auto minimize_map = lmp->update->minimize_map;
auto found = minimize_map->find(name);
if (found != minimize_map->end()) minimize_map->erase(name);
}
// if reference count is down to zero, close DSO handle.
@ -404,18 +459,157 @@ void plugin_unload(const char *style, const char *name, LAMMPS *lmp)
#endif
}
/* --------------------------------------------------------------------
restore previously loaded plugins
-------------------------------------------------------------------- */
void plugin_restore(LAMMPS *lmp, bool warnflag)
{
for (auto &plugin : pluginlist) {
if (lmp->comm->me == 0)
utils::logmesg(lmp, "Restoring plugin: {} by {}\n", plugin.info, plugin.author);
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 (warnflag && (lmp->comm->me == 0))
lmp->error->warning(FLERR, "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 (warnflag && (lmp->comm->me == 0))
lmp->error->warning(FLERR, "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 (warnflag && (lmp->comm->me == 0))
lmp->error->warning(FLERR, "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 (warnflag && (lmp->comm->me == 0))
lmp->error->warning(FLERR, "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 (warnflag && (lmp->comm->me == 0))
lmp->error->warning(FLERR, "Overriding built-in improper style {} from plugin",
plugin.name);
}
(*improper_map)[plugin.name] = (Force::ImproperCreator) plugin.creator.v1;
} else if (pstyle == "kspace") {
auto kspace_map = lmp->force->kspace_map;
if (kspace_map->find(plugin.name) != kspace_map->end()) {
if (warnflag && (lmp->comm->me == 0))
lmp->error->warning(FLERR, "Overriding built-in kspace style {} from plugin",
plugin.name);
}
(*kspace_map)[plugin.name] = (Force::KSpaceCreator) plugin.creator.v1;
} else if (pstyle == "compute") {
auto compute_map = lmp->modify->compute_map;
if (compute_map->find(plugin.name) != compute_map->end()) {
if (warnflag && (lmp->comm->me == 0))
lmp->error->warning(FLERR, "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 (warnflag && (lmp->comm->me == 0))
lmp->error->warning(FLERR, "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 (warnflag && (lmp->comm->me == 0))
lmp->error->warning(FLERR, "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 (warnflag && (lmp->comm->me == 0))
lmp->error->warning(FLERR, "Overriding built-in command style {} from plugin",
plugin.name);
}
(*command_map)[plugin.name] = (Input::CommandCreator) plugin.creator.v1;
} else if (pstyle == "run") {
auto integrate_map = lmp->update->integrate_map;
if (integrate_map->find(plugin.name) != integrate_map->end()) {
if (warnflag && (lmp->comm->me == 0))
lmp->error->warning(FLERR, "Overriding built-in run style {} from plugin", plugin.name);
}
(*integrate_map)[plugin.name] = (Update::IntegrateCreator) plugin.creator.v2;
} else if (pstyle == "min") {
auto minimize_map = lmp->update->minimize_map;
if (minimize_map->find(plugin.name) != minimize_map->end()) {
if (warnflag && (lmp->comm->me == 0))
lmp->error->warning(FLERR, "Overriding built-in minimize style {} from plugin",
plugin.name);
}
(*minimize_map)[plugin.name] = (Update::MinimizeCreator) plugin.creator.v1;
}
}
}
/* --------------------------------------------------------------------
unload all loaded plugins
-------------------------------------------------------------------- */
void plugin_clear(LAMMPS *lmp)
{
verbose = false;
bool oldverbose = verbose;
verbose = true;
while (pluginlist.size() > 0) {
auto p = pluginlist.begin();
plugin_unload(p->style, p->name, lmp);
}
verbose = true;
verbose = oldverbose;
}
/* --------------------------------------------------------------------
unload all shared objects
-------------------------------------------------------------------- */
void plugin_finalize()
{
#if defined(LMP_PLUGIN)
while (pluginlist.size() > 0) {
auto p = pluginlist.begin();
void *handle = p->handle;
plugin_erase(p->style, p->name);
// if reference count is down to zero, close DSO handle.
--dso_refcounter[handle];
if (dso_refcounter[handle] == 0) { platform::dlclose(handle); }
}
#endif
}
/* --------------------------------------------------------------------

View File

@ -34,10 +34,12 @@ class Plugin : public Command {
void plugin_auto_load(LAMMPS *);
int plugin_load(const char *, LAMMPS *);
void plugin_register(lammpsplugin_t *, void *);
void plugin_restore(LAMMPS *, bool);
void plugin_unload(const char *, const char *, LAMMPS *);
void plugin_erase(const char *, const char *);
void plugin_clear(LAMMPS *);
void plugin_finalize();
int plugin_get_num_plugins();
int plugin_find(const char *, const char *);

View File

@ -33,15 +33,15 @@ static constexpr double SMALL = 0.00001;
/* ---------------------------------------------------------------------- */
KSpace::KSpace(LAMMPS *lmp) : Pointers(lmp)
KSpace::KSpace(LAMMPS *lmp) :
Pointers(lmp), eatom(nullptr), vatom(nullptr), gcons(nullptr), dgcons(nullptr)
{
order_allocated = 0;
energy = 0.0;
virial[0] = virial[1] = virial[2] = virial[3] = virial[4] = virial[5] = 0.0;
triclinic_support = 1;
ewaldflag = pppmflag = msmflag = dispersionflag = tip4pflag =
dipoleflag = spinflag = 0;
ewaldflag = pppmflag = msmflag = dispersionflag = tip4pflag = dipoleflag = spinflag = 0;
compute_flag = 1;
group_group_enable = 0;
stagger_flag = 0;
@ -83,14 +83,17 @@ KSpace::KSpace(LAMMPS *lmp) : Pointers(lmp)
accuracy_real_6 = -1.0;
accuracy_kspace_6 = -1.0;
qqrd2e = force->qqrd2e;
g_ewald = g_ewald_6 = 0.0;
scale = 1.0;
neighrequest_flag = 1;
mixflag = 0;
splittol = 1.0e-6;
scale = 1.0;
maxeatom = maxvatom = 0;
eatom = nullptr;
vatom = nullptr;
centroidstressflag = CENTROID_NOTAVAIL;
execution_space = Host;

112
src/kspace_zero.cpp Normal file
View File

@ -0,0 +1,112 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/, Sandia National Laboratories
LAMMPS development team: developers@lammps.org
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)
------------------------------------------------------------------------- */
#include "kspace_zero.h"
#include "atom.h"
#include "comm.h"
#include "domain.h"
#include "error.h"
#include "force.h"
#include "pair.h"
#include <cstring>
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
KSpaceZero::KSpaceZero(LAMMPS *lmp) : KSpace(lmp)
{
ewaldflag = 1;
pppmflag = 1;
msmflag = 1;
dispersionflag = 1;
tip4pflag = 1;
dipoleflag = 1;
spinflag = 1;
}
/* ---------------------------------------------------------------------- */
void KSpaceZero::settings(int narg, char **arg)
{
if (narg != 1) error->all(FLERR, "Illegal kspace_style {} command", force->kspace_style);
accuracy_relative = fabs(utils::numeric(FLERR, arg[0], false, lmp));
if (accuracy_relative > 1.0)
error->all(FLERR, "Invalid relative accuracy {:g} for kspace_style {}", accuracy_relative,
force->kspace_style);
if ((narg != 0) && (narg != 1)) error->all(FLERR, "Illegal kspace_style command");
}
/* ---------------------------------------------------------------------- */
void KSpaceZero::init()
{
if (comm->me == 0) utils::logmesg(lmp, "Dummy KSpace initialization ...\n");
// error checks
if (force->pair == nullptr) error->all(FLERR, "KSpace solver requires a pair style");
if (!atom->q_flag) error->all(FLERR, "KSpace style zero requires atom attribute q");
// compute two charge force
two_charge();
int itmp;
auto p_cutoff = (double *) force->pair->extract("cut_coul", itmp);
if (p_cutoff == nullptr) error->all(FLERR, "KSpace style is incompatible with Pair style");
double cutoff = *p_cutoff;
qsum_qsq();
accuracy = accuracy_relative * two_charge_force;
// make initial g_ewald estimate
// based on desired accuracy and real space cutoff
// fluid-occupied volume used to estimate real-space error
// zprd used rather than zprd_slab
if (!gewaldflag) {
if (accuracy <= 0.0) error->all(FLERR, "KSpace accuracy must be > 0");
if (q2 == 0.0) error->all(FLERR, "Must use 'kspace_modify gewald' for uncharged system");
g_ewald = accuracy * sqrt(atom->natoms * cutoff * domain->xprd * domain->yprd * domain->zprd) /
(2.0 * q2);
if (g_ewald >= 1.0)
g_ewald = (1.35 - 0.15 * log(accuracy)) / cutoff;
else
g_ewald = sqrt(-log(g_ewald)) / cutoff;
}
if (comm->me == 0) utils::logmesg(lmp, " G vector (1/distance) = {:.8g}\n", g_ewald);
}
/* ---------------------------------------------------------------------- */
void KSpaceZero::setup()
{
if (comm->me == 0) utils::logmesg(lmp, "Dummy KSpace setup\n");
}
/* ---------------------------------------------------------------------- */
void KSpaceZero::compute(int eflag, int vflag)
{
ev_init(eflag, vflag);
}

39
src/kspace_zero.h Normal file
View File

@ -0,0 +1,39 @@
/* -*- c++ -*- ----------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/ Sandia National Laboratories
LAMMPS development team: developers@lammps.org
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 KSPACE_CLASS
// clang-format off
KSpaceStyle(zero,KSpaceZero);
// clang-format on
#else
#ifndef LMP_KSPACE_ZERO_H
#define LMP_KSPACE_ZERO_H
#include "kspace.h"
namespace LAMMPS_NS {
class KSpaceZero : public KSpace {
public:
KSpaceZero(class LAMMPS *);
void init() override;
void setup() override;
void settings(int, char **) override;
void compute(int, int) override;
};
} // namespace LAMMPS_NS
#endif
#endif

View File

@ -883,8 +883,9 @@ void LAMMPS::create()
python = new Python(this);
// auto-load plugins
// restore and auto-load plugins
#if defined(LMP_PLUGIN)
plugin_restore(this, true);
plugin_auto_load(this);
#endif
}
@ -991,11 +992,6 @@ void LAMMPS::init()
void LAMMPS::destroy()
{
// must wipe out all plugins first, if configured
#if defined(LMP_PLUGIN)
plugin_clear(this);
#endif
delete update;
update = nullptr;

View File

@ -357,7 +357,8 @@ completed and then MPI is cleanly shut down. After calling this
function no more MPI calls may be made.
*See also*
:cpp:func:`lammps_kokkos_finalize`, :cpp:func:`lammps_python_finalize`
:cpp:func:`lammps_kokkos_finalize`, :cpp:func:`lammps_python_finalize`,
:cpp:func:`lammps_plugin_finalize`
\endverbatim */
void lammps_mpi_finalize()
@ -389,7 +390,8 @@ closed (to release associated resources).
After calling this function no Kokkos functionality may be used.
*See also*
:cpp:func:`lammps_mpi_finalize`, :cpp:func:`lammps_python_finalize`
:cpp:func:`lammps_mpi_finalize`, :cpp:func:`lammps_python_finalize`,
:cpp:func:`lammps_plugin_finalize`
\endverbatim */
void lammps_kokkos_finalize()
@ -399,6 +401,35 @@ void lammps_kokkos_finalize()
/* ---------------------------------------------------------------------- */
/** Unload all plugins and release the corresponding DSO handles
*
\verbatim embed:rst
.. versionadded:: TBD
This function clears the list of all loaded plugins and closes the
corresponding DSO handles and releases the imported executable code.
However, this is **not** done when a LAMMPS instance is deleted because
plugins and their shared objects are global properties.
This function can be called to explicitly clear out all loaded plugins
in case it is safe to do so.
*See also*
:cpp:func:`lammps_mpi_finalize`, :cpp:func:`lammps_kokkos_finalize`,
:cpp:func:`lammps_python_finalize`
\endverbatim */
void lammps_plugin_finalize()
{
#if defined(LMP_PLUGIN)
plugin_finalize();
#endif
}
/* ---------------------------------------------------------------------- */
/** Clear the embedded Python environment
*
\verbatim embed:rst
@ -425,7 +456,8 @@ This function can be called to explicitly clear the Python
environment in case it is safe to do so.
*See also*
:cpp:func:`lammps_mpi_finalize`, :cpp:func:`lammps_kokkos_finalize`
:cpp:func:`lammps_mpi_finalize`, :cpp:func:`lammps_kokkos_finalize`,
:cpp:func:`lammps_plugin_finalize`
\endverbatim */
void lammps_python_finalize()
@ -433,7 +465,6 @@ void lammps_python_finalize()
Python::finalize();
}
/* ---------------------------------------------------------------------- */
/** Call a LAMMPS Error class function

View File

@ -140,6 +140,7 @@ void lammps_close(void *handle);
void lammps_mpi_init();
void lammps_mpi_finalize();
void lammps_kokkos_finalize();
void lammps_plugin_finalize();
void lammps_python_finalize();
void lammps_error(void *handle, int error_type, const char *error_text);

View File

@ -35,6 +35,7 @@ static void finalize()
{
lammps_kokkos_finalize();
lammps_python_finalize();
lammps_plugin_finalize();
}
/* ----------------------------------------------------------------------

View File

@ -99,6 +99,13 @@ Update::Update(LAMMPS *lmp) :
Update::~Update()
{
// restore default styles to avoid segfaults from plugins
char *str = (char *) "verlet";
create_integrate(1, &str, 1);
str = (char *) "cg";
create_minimize(1, &str, 1);
delete[] unit_style;
delete[] integrate_style;

View File

@ -116,6 +116,7 @@ extern void lammps_mpi_init();
extern void lammps_mpi_finalize();
extern void lammps_kokkos_finalize();
extern void lammps_python_finalize();
extern void lammps_plugin_finalize();
extern void lammps_error(void *handle, int error_type, const char *error_text);
extern char *lammps_expand(void *handle, const char *line);
@ -315,6 +316,7 @@ extern void lammps_mpi_init();
extern void lammps_mpi_finalize();
extern void lammps_kokkos_finalize();
extern void lammps_python_finalize();
extern void lammps_plugin_finalize();
extern void lammps_error(void *handle, int error_type, const char *error_text);
extern char *lammps_expand(void *handle, const char *line);