Commit 110bb79b authored by Richard Berger's avatar Richard Berger
Browse files

Implement fix python mentioned in issue #454

Allows to call a python function at defined points in the integration loop
parent d84f8898
Loading
Loading
Loading
Loading
+50 −0
Original line number Diff line number Diff line
# 3d Lennard-Jones melt

units		lj
atom_style	atomic

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

velocity	all create 3.0 87287

pair_style	lj/cut 2.5
pair_coeff	1 1 1.0 1.0 2.5

neighbor	0.3 bin
neigh_modify	every 20 delay 0 check no

python         end_of_step_callback here """
from __future__ import print_function
from lammps import lammps

def end_of_step_callback(lmp):
  L = lammps(ptr=lmp)
  t = L.extract_global("ntimestep", 0)
  print("### END OF STEP ###", t)

def post_force_callback(lmp, v):
  L = lammps(ptr=lmp)
  t = L.extract_global("ntimestep", 0)
  print("### POST_FORCE ###", t)
"""

fix		1 all nve
fix     2 all python end_of_step end_of_step_callback
fix     3 all python post_force post_force_callback

#dump		id all atom 50 dump.melt

#dump		2 all image 25 image.*.jpg type type &
#		axes yes 0.8 0.02 view 60 -30
#dump_modify	2 pad 3

#dump		3 all movie 25 movie.mpg type type &
#		axes yes 0.8 0.02 view 60 -30
#dump_modify	3 pad 3

thermo		50
run		250
+2 −0
Original line number Diff line number Diff line
@@ -850,6 +850,8 @@
/prd.h
/python_impl.cpp
/python_impl.h
/fix_python.cpp
/fix_python.h
/reader_molfile.cpp
/reader_molfile.h
/reaxc_allocate.cpp
+106 −0
Original line number Diff line number Diff line
/* ----------------------------------------------------------------------
   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.
------------------------------------------------------------------------- */

#include <stdio.h>
#include <string.h>
#include "fix_python.h"
#include "atom.h"
#include "force.h"
#include "update.h"
#include "respa.h"
#include "error.h"
#include "python.h"

using namespace LAMMPS_NS;
using namespace FixConst;

// Wrap API changes between Python 2 and 3 using macros
#if PY_MAJOR_VERSION == 2
#define PY_VOID_POINTER(X) PyCObject_FromVoidPtr((void *) X, NULL)
#elif PY_MAJOR_VERSION == 3
#define PY_VOID_POINTER(X) PyCapsule_New((void *) X, NULL, NULL)
#endif

/* ---------------------------------------------------------------------- */

FixPython::FixPython(LAMMPS *lmp, int narg, char **arg) :
  Fix(lmp, narg, arg)
{
  if (narg != 5) error->all(FLERR,"Illegal fix python command");

  // ensure Python interpreter is initialized
  python->init();

  if (strcmp(arg[3],"post_force") == 0) {
    selected_callback = POST_FORCE;
  } else if (strcmp(arg[3],"end_of_step") == 0) {
    selected_callback = END_OF_STEP;
  }

  // get Python function
  PyGILState_STATE gstate = PyGILState_Ensure();

  PyObject * pyMain = PyImport_AddModule("__main__");

  if (!pyMain) {
    PyGILState_Release(gstate);
    error->all(FLERR,"Could not initialize embedded Python");
  }

  char * fname = arg[4];
  pFunc = PyObject_GetAttrString(pyMain, fname);

  if (!pFunc) {
    PyGILState_Release(gstate);
    error->all(FLERR,"Could not find Python function");
  }

  PyGILState_Release(gstate);
}

/* ---------------------------------------------------------------------- */

int FixPython::setmask()
{
  return selected_callback;
}

/* ---------------------------------------------------------------------- */

void FixPython::end_of_step()
{
  PyGILState_STATE gstate = PyGILState_Ensure();

  PyObject * ptr = PY_VOID_POINTER(lmp);
  PyObject * arglist = Py_BuildValue("(O)", ptr);

  PyObject * result = PyEval_CallObject(pFunc, arglist);
  Py_DECREF(arglist);

  PyGILState_Release(gstate);
}

/* ---------------------------------------------------------------------- */

void FixPython::post_force(int vflag)
{
  PyGILState_STATE gstate = PyGILState_Ensure();

  PyObject * ptr = PY_VOID_POINTER(lmp);
  PyObject * arglist = Py_BuildValue("(Oi)", ptr, vflag);

  PyObject * result = PyEval_CallObject(pFunc, arglist);
  Py_DECREF(arglist);

  PyGILState_Release(gstate);
}
+54 −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.
------------------------------------------------------------------------- */

#ifdef FIX_CLASS

FixStyle(python,FixPython)

#else

#ifndef LMP_FIX_PYTHON_H
#define LMP_FIX_PYTHON_H

#include "fix.h"
#include <Python.h>

namespace LAMMPS_NS {

class FixPython : public Fix {
 public:
  FixPython(class LAMMPS *, int, char **);
  virtual ~FixPython() {}
  int setmask();
  virtual void end_of_step();
  virtual void post_force(int);

 private:
  PyObject * pFunc;
  int selected_callback;
};

}

#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.

*/