add support for loading plugins for fixes

This commit is contained in:
Axel Kohlmeyer
2021-03-11 21:19:04 -05:00
parent f982d98574
commit 9209cbba92
8 changed files with 325 additions and 8 deletions

View File

@ -57,17 +57,54 @@ function would look like this:
plugin.name = "morse2"; plugin.name = "morse2";
plugin.info = "Morse2 variant pair style v1.0"; plugin.info = "Morse2 variant pair style v1.0";
plugin.author = "Axel Kohlmeyer (akohlmey@gmail.com)"; plugin.author = "Axel Kohlmeyer (akohlmey@gmail.com)";
plugin.creator = (lammpsplugin_factory *) &morse2creator; plugin.creator1 = (lammpsplugin_factory1 *) &morse2creator;
plugin.creator2 = nullptr;
plugin.handle = handle; plugin.handle = handle;
(*register_plugin)(&plugin,lmp); (*register_plugin)(&plugin,lmp);
} }
The factory function in this example is called ``morse2creator()``. It The factory function in this example is called ``morse2creator()``. It
receives a pointer to the LAMMPS class as argument and returns a receives a pointer to the LAMMPS class as only argument and thus has to
be assigned to the *creator1* 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. pointer to the allocated class instance derived from the ``Pair`` class.
This function may be declared static to avoid clashes with other plugins. This function may be declared static to avoid clashes with other plugins.
The name of the derived class, ``PairMorse2``, must be unique inside The name of the derived class, ``PairMorse2``, must be unique inside
the entire LAMMPS executable. the entire LAMMPS executable.
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 *creator2* 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.creator1 = nullptr;
plugin.creator2 = (lammpsplugin_factory2 *) &nve2creator;
plugin.handle = handle;
(*register_plugin)(&plugin,lmp);
}
The initialization function **must** be called ``lammpsplugin_init``, it The initialization function **must** be called ``lammpsplugin_init``, it
**must** have C bindings and it takes three void pointers as arguments. **must** have C bindings and it takes three void pointers as arguments.

View File

@ -2,9 +2,14 @@ CXX=mpicxx
CXXFLAGS=-I../../src -Wall -Wextra -O3 -fPIC -I../../src/USER-OMP -fopenmp CXXFLAGS=-I../../src -Wall -Wextra -O3 -fPIC -I../../src/USER-OMP -fopenmp
LD=$(CXX) -shared -rdynamic -fopenmp LD=$(CXX) -shared -rdynamic -fopenmp
default: morse2plugin.so nve2plugin.so
morse2plugin.so: morse2plugin.o pair_morse2.o pair_morse2_omp.o morse2plugin.so: morse2plugin.o pair_morse2.o pair_morse2_omp.o
$(LD) -o $@ $^ $(LD) -o $@ $^
nve2plugin.so: nve2plugin.o fix_nve2.o
$(LD) -o $@ $^
.cpp.o: .cpp.o:
$(CXX) -o $@ $(CXXFLAGS) -c $< $(CXX) -o $@ $(CXXFLAGS) -c $<
@ -12,6 +17,9 @@ pair_morse2.o: pair_morse2.cpp pair_morse2.h
pair_morse2_omp.o: pair_morse2_omp.cpp pair_morse2_omp.h 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 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
clean: clean:
rm -f *~ *.so *.o log.lammps rm -f *~ *.so *.o log.lammps

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

@ -31,13 +31,14 @@ extern "C" void lammpsplugin_init(void *lmp, void *handle, void *regfunc)
plugin.name = "morse2"; plugin.name = "morse2";
plugin.info = "Morse2 variant pair style v1.0"; plugin.info = "Morse2 variant pair style v1.0";
plugin.author = "Axel Kohlmeyer (akohlmey@gmail.com)"; plugin.author = "Axel Kohlmeyer (akohlmey@gmail.com)";
plugin.creator = (lammpsplugin_factory *) &morse2creator; plugin.creator1 = (lammpsplugin_factory1 *) &morse2creator;
plugin.creator2 = nullptr;
plugin.handle = handle; plugin.handle = handle;
(*register_plugin)(&plugin,lmp); (*register_plugin)(&plugin,lmp);
// also register morse2/omp pair style. only need to update changed fields // also register morse2/omp pair style. only need to update changed fields
plugin.name = "morse2/omp"; plugin.name = "morse2/omp";
plugin.info = "Morse2 variant pair style for OpenMP v1.0"; plugin.info = "Morse2 variant pair style for OpenMP v1.0";
plugin.creator = (lammpsplugin_factory *) &morse2ompcreator; plugin.creator1 = (lammpsplugin_factory1 *) &morse2ompcreator;
(*register_plugin)(&plugin,lmp); (*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.creator2 = (lammpsplugin_factory2 *) &nve2creator;
plugin.handle = handle;
(*register_plugin)(&plugin,lmp);
}

View File

@ -18,7 +18,8 @@
extern "C" { extern "C" {
typedef void *(lammpsplugin_factory)(void *); typedef void *(lammpsplugin_factory1)(void *);
typedef void *(lammpsplugin_factory2)(void *, int, char **);
typedef struct { typedef struct {
const char *version; const char *version;
@ -26,7 +27,8 @@ extern "C" {
const char *name; const char *name;
const char *info; const char *info;
const char *author; const char *author;
lammpsplugin_factory *creator; lammpsplugin_factory1 *creator1;
lammpsplugin_factory2 *creator2;
void *handle; void *handle;
} lammpsplugin_t; } lammpsplugin_t;

View File

@ -114,10 +114,20 @@ namespace LAMMPS_NS
plugin->name)); plugin->name));
} }
(*pair_map)[plugin->name] = (Force::PairCreator)plugin->creator; (*pair_map)[plugin->name] = (Force::PairCreator)plugin->creator1;
} 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->creator2;
} else { } else {
utils::logmesg(lmp,fmt::format("Loading plugin for {} styles not " utils::logmesg(lmp,fmt::format("Loading plugin for {} styles not "
"yet implemented\n", pstyle)); "yet implemented\n",pstyle));
pluginlist.pop_back(); pluginlist.pop_back();
} }
} }