diff --git a/examples/python/in.fix_python b/examples/python/in.fix_python new file mode 100644 index 0000000000..426b456688 --- /dev/null +++ b/examples/python/in.fix_python @@ -0,0 +1,50 @@ +# 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 diff --git a/src/.gitignore b/src/.gitignore index 620c6965d0..df5cea6eb3 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -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 diff --git a/src/PYTHON/fix_python.cpp b/src/PYTHON/fix_python.cpp new file mode 100644 index 0000000000..08beb511cb --- /dev/null +++ b/src/PYTHON/fix_python.cpp @@ -0,0 +1,106 @@ +/* ---------------------------------------------------------------------- + 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 +#include +#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); +} diff --git a/src/PYTHON/fix_python.h b/src/PYTHON/fix_python.h new file mode 100644 index 0000000000..534cd74cfb --- /dev/null +++ b/src/PYTHON/fix_python.h @@ -0,0 +1,54 @@ +/* -*- 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 + +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. + +*/