Unverified Commit a828facb authored by Axel Kohlmeyer's avatar Axel Kohlmeyer Committed by GitHub
Browse files

Merge pull request #1900 from akohlmey/couple-lammps-plugin

Example for loading LAMMPS as a plugin from a shared library
parents 37e6fd1b e87b3a21
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -70,6 +70,8 @@ examples/COUPLE/README for more details:

* simple: simple driver programs in C++ and C which invoke LAMMPS as a
  library
* plugin: simple driver program in C which invokes LAMMPS as a plugin
  from a shared library.
* lammps\_quest: coupling of LAMMPS and `Quest <quest_>`_, to run classical
  MD with quantum forces calculated by a density functional code
* lammps\_spparks: coupling of LAMMPS and `SPPARKS <spparks_>`_, to couple
+1 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ These are the sub-directories included in this directory:

simple		    simple example of driver code calling LAMMPS as a lib
multiple	    example of driver code calling multiple instances of LAMMPS
plugin              example for loading LAMMPS at runtime from a shared library
lammps_mc           client/server coupling of Monte Carlo client 
                      with LAMMPS server for energy evaluation
lammps_nwchem       client/server coupling of LAMMPS client with 
+63 −0
Original line number Diff line number Diff line
This directory has a simple C code that shows how LAMMPS can be included
in an application as a shared library loaded at runtime. The code is
essentially the same as in the "simple" example that links to LAMMPS
either with a static or shared library. The purpose is to illustrate
how another code could be built without having a LAMMPS library present
and then load the (separately compiled) shared library.

simple.c           is the C driver
liblammpsplugin.c  is the LAMMPS library plugin loader

You can then build the driver executable codes with a compile line
like below.

mpicc -c -O -Wall -g -I$HOME/lammps/src liblammpsplugin.c
mpicc -c -O -Wall -g simple.c
mpicc simple.o liblammsplugin.o -ldl -o simpleC

You also need to build LAMMPS as a shared library
(see examples/COUPLE/README), e.g. 

cd $HOME/lammps/src
make mode=shlib mpi

or 

cd $HOME/lammps
mkdir build-shared
cd build-shared
cmake -D BUILD_LIB=on -D BUILD_SHARED_LIBS=on ../cmake
make

You then run simpleC on a parallel machine
on some number of processors Q with 3 arguments:

% mpirun -np Q simpleC P in.lj $HOME/lammps/src/liblammps.so

or

% mpirun -np Q simpleC P in.lj $HOME/lammps/build-shared/liblammps.so

P is the number of procs you want LAMMPS to run on (must be <= Q) and
in.lj is a LAMMPS input script and the last argument is the path to
the LAMMPS shared library. This either has to be an absolute path, or
liblammps.so has to be in a folder that is included in the environment
variable LD_LIBRARY_PATH so it will be found by the dynamic object loader.

The driver will launch LAMMPS on P procs, read the input script a line
at a time, and pass each command line to LAMMPS.  The final line of
the script is a "run" command, so LAMMPS will run the problem.

The driver then requests all the atom coordinates from LAMMPS, moves
one of the atoms a small amount "epsilon", passes the coordinates back
to LAMMPS, and runs LAMMPS again.  If you look at the output, you
should see a small energy change between runs, due to the moved atom.

The C driver is calling C-style routines in the src/library.cpp file
of LAMMPS through the function pointers in the liblammpsplugin_t struct.
This has the benefit that your binary is not linked to liblammps.so directly
and thus you can change the name of the shared library (e.g. to have 
different variants compiled, or to load a different LAMMPS versions without
having to update your executable). The shared library still has to be
compatible with the compilation settings the plugin code.
+25 −0
Original line number Diff line number Diff line
# 3d Lennard-Jones melt

units		lj
atom_style	atomic
atom_modify	map array

lattice		fcc 0.8442
region		box block 0 4 0 4 0 4
create_box	1 box
create_atoms	1 box
mass		1 1.0

velocity	all create 1.44 87287 loop geom

pair_style	lj/cut 2.5
pair_coeff	1 1 1.0 1.0 2.5

neighbor	0.3 bin
neigh_modify	delay 0 every 20 check no

fix		1 all nve

variable        fx atom fx

run		10
+99 −0
Original line number Diff line number Diff line
/* -*- 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.
------------------------------------------------------------------------- */

/*
   Variant of the C style library interface to LAMMPS
   that uses a shared library and dynamically opens it,
   so this can be used as a prototype code to integrate
   a LAMMPS plugin to some other software.
*/

#include "library.h"
#include "liblammpsplugin.h"
#include <stdlib.h>
#include <dlfcn.h>

liblammpsplugin_t *liblammpsplugin_load(const char *lib)
{
  liblammpsplugin_t *lmp;
  void *handle;

  if (lib == NULL) return NULL;
  handle = dlopen(lib,RTLD_NOW|RTLD_GLOBAL);
  if (handle == NULL) return NULL;
  
  lmp = (liblammpsplugin_t *) malloc(sizeof(liblammpsplugin_t));
  lmp->handle = handle;

#define ADDSYM(symbol) lmp->symbol = dlsym(handle,"lammps_" #symbol)
  ADDSYM(open);
  ADDSYM(open_no_mpi);
  ADDSYM(close);
  ADDSYM(version);
  ADDSYM(file);
  ADDSYM(command);
  ADDSYM(commands_list);
  ADDSYM(commands_string);
  ADDSYM(free);
  ADDSYM(extract_setting);
  ADDSYM(extract_global);
  ADDSYM(extract_box);
  ADDSYM(extract_atom);
  ADDSYM(extract_compute);
  ADDSYM(extract_fix);
  ADDSYM(extract_variable);

  ADDSYM(get_thermo);
  ADDSYM(get_natoms);

  ADDSYM(set_variable);
  ADDSYM(reset_box);

  ADDSYM(gather_atoms);
  ADDSYM(gather_atoms_concat);
  ADDSYM(gather_atoms_subset);
  ADDSYM(scatter_atoms);
  ADDSYM(scatter_atoms_subset);

  ADDSYM(set_fix_external_callback);

  ADDSYM(config_has_package);
  ADDSYM(config_package_count);
  ADDSYM(config_package_name);
  ADDSYM(config_has_gzip_support);
  ADDSYM(config_has_png_support);
  ADDSYM(config_has_jpeg_support);
  ADDSYM(config_has_ffmpeg_support);
  ADDSYM(config_has_exceptions);
  ADDSYM(create_atoms);
#ifdef LAMMPS_EXCEPTIONS
  lmp->has_exceptions = 1;
  ADDSYM(has_error);
  ADDSYM(get_last_error_message);
#else
  lmp->has_exceptions = 0;
  lmp->has_error = NULL;
  lmp->get_last_error_message = NULL;
#endif
  return lmp;
}

int liblammpsplugin_release(liblammpsplugin_t *lmp)
{
  if (lmp == NULL) return 1;
  if (lmp->handle == NULL) return 2;

  dlclose(lmp->handle);
  free((void *)lmp);
  return 0;
}
Loading