Merge pull request #449 from rbberger/python_refactoring

Add Python 3 compatibility and expand Python interface availability
This commit is contained in:
sjplimp
2017-05-08 08:29:24 -06:00
committed by GitHub
24 changed files with 384 additions and 186 deletions

View File

@ -118,11 +118,6 @@ check which version of Python you have installed, by simply typing
11.2 Overview of using Python from a LAMMPS script :link(py_2),h4
NOTE: It is not currently possible to use the "python"_python.html
command described in this section with Python 3, only with Python 2.
The C API changed from Python 2 to 3 and the LAMMPS code is not
compatible with both.
LAMMPS has a "python"_python.html command which can be used in an
input script to define and execute a Python function that you write
the code for. The Python function can also be assigned to a LAMMPS

View File

@ -50,7 +50,7 @@ def factorial(n):
return n * factorial(n-1)
""" :pre
python loop input 1 SELF return v_value format -f here """
python loop input 1 SELF return v_value format pf here """
def loop(lmpptr,N,cut0):
from lammps import lammps
lmp = lammps(ptr=lmpptr) :pre
@ -59,7 +59,7 @@ def loop(lmpptr,N,cut0):
for i in range(N):
cut = cut0 + i*0.1
lmp.set_variable("cut",cut) # set a variable in LAMMPS
lmp.set_variable("cut",cut) # set a variable in LAMMPS
lmp.command("pair_style lj/cut $\{cut\}") # LAMMPS commands
lmp.command("pair_coeff * * 1.0 1.0")
lmp.command("run 100")
@ -67,11 +67,6 @@ def loop(lmpptr,N,cut0):
[Description:]
NOTE: It is not currently possible to use the "python"_python.html
command described in this section with Python 3, only with Python 2.
The C API changed from Python 2 to 3 and the LAMMPS code is not
compatible with both.
Define a Python function or execute a previously defined function.
Arguments, including LAMMPS variables, can be passed to the function
from the LAMMPS input script and a value returned by the Python
@ -477,16 +472,7 @@ python"_Section_python.html. Note that it is important that the
stand-alone LAMMPS executable and the LAMMPS shared library be
consistent (built from the same source code files) in order for this
to work. If the two have been built at different times using
different source files, problems may occur.
As described above, you can use the python command to invoke a Python
function which calls back to LAMMPS through its Python-wrapped library
interface. However you cannot do the opposite. I.e. you cannot call
LAMMPS from Python and invoke the python command to "callback" to
Python and execute a Python function. LAMMPS will generate an error
if you try to do that. Note that we think there actually should be a
way to do that, but haven't yet been able to figure out how to do it
successfully.
different source files, problems may occur.
[Related commands:]

View File

@ -55,7 +55,7 @@ using the generated {auto} Makefile.
cd $LAMMPS_DIR/src :pre
# generate custom Makefile
python2 Make.py -jpg -png -s ffmpeg exceptions -m mpi -a file :pre
python Make.py -jpg -png -s ffmpeg exceptions -m mpi -a file :pre
# add packages if necessary
make yes-MOLECULE :pre

View File

@ -1,9 +1,10 @@
# Python function that implements a loop of short runs
# calls back to LAMMPS via "lmp" instance
# lammps() must be called with ptr=lmpptr for this to work
from __future__ import print_function
def loop(N,cut0,thresh,lmpptr):
print "LOOP ARGS",N,cut0,thresh,lmpptr
print("LOOP ARGS",N,cut0,thresh,lmpptr)
from lammps import lammps
lmp = lammps(ptr=lmpptr)
natoms = lmp.get_natoms()
@ -12,11 +13,12 @@ def loop(N,cut0,thresh,lmpptr):
cut = cut0 + i*0.1
lmp.set_variable("cut",cut) # set a variable in LAMMPS
lmp.command("pair_style lj/cut ${cut}") # LAMMPS command
#lmp.command("pair_style lj/cut %d" % cut) # LAMMPS command option
lmp.command("pair_coeff * * 1.0 1.0") # ditto
lmp.command("run 10") # ditto
pe = lmp.extract_compute("thermo_pe",0,0) # extract total PE from LAMMPS
print "PE",pe/natoms,thresh
print("PE",pe/natoms,thresh)
if pe/natoms < thresh: return

View File

@ -25,13 +25,14 @@ run 10
# example of catching a syntax error
python simple here """
from __future__ import print_function
def simple():
import exceptions
print "Inside simple function"
print("Inside simple function")
try:
foo += 1
except Exception, e:
print "FOO error:",e
except Exception as e:
print("FOO error:", e)
"""
python simple invoke

View File

@ -1,6 +1,7 @@
# Settings that the LAMMPS build will import when this package library is used
# See the README file for more explanation
python_SYSINC = $(shell which python2-config > /dev/null 2>&1 && python2-config --includes || python-config --includes )
python_SYSLIB = $(shell which python2-config > /dev/null 2>&1 && python2-config --ldflags || python-config --ldflags)
python_SYSINC = $(shell which python-config > /dev/null 2>&1 && python-config --includes || :)
python_SYSLIB = $(shell which python-config > /dev/null 2>&1 && python-config --ldflags || :)
python_SYSPATH =
PYTHON=python

View File

@ -1,6 +1,7 @@
# Settings that the LAMMPS build will import when this package library is used
# See the README file for more explanation
python_SYSINC = $(shell which python2-config > /dev/null 2>&1 && python2-config --includes || python-config --includes )
python_SYSLIB = $(shell which python2-config > /dev/null 2>&1 && python2-config --ldflags || python-config --ldflags)
python_SYSINC = $(shell which python2-config > /dev/null 2>&1 && python2-config --includes || (which python-config > /dev/null 2>&1 && python-config --includes || :))
python_SYSLIB = $(shell which python2-config > /dev/null 2>&1 && python2-config --ldflags || (which python-config > /dev/null 2>&1 && python-config --ldflags || :))
python_SYSPATH =
PYTHON=$(shell which python2 > /dev/null 2>&1 && echo python2 || echo python)

View File

@ -4,3 +4,4 @@
python_SYSINC = -I/usr/local/include/python2.7
python_SYSLIB = -lpython2.7 -lnsl -ldl -lreadline -ltermcap -lpthread -lutil -lm -Xlinker -export-dynamic
python_SYSPATH =
PYTHON=python2.7

View File

@ -0,0 +1,7 @@
# Settings that the LAMMPS build will import when this package library is used
# See the README file for more explanation
python_SYSINC = $(shell which python3-config > /dev/null 2>&1 && python3-config --includes || (which python-config > /dev/null 2>&1 && python-config --includes || :))
python_SYSLIB = $(shell which python3-config > /dev/null 2>&1 && python3-config --ldflags || (which python-config > /dev/null 2>&1 && python-config --ldflags || :))
python_SYSPATH =
PYTHON=$(shell which python3 > /dev/null 2>&1 && echo python3 || echo python)

View File

@ -1,26 +1,26 @@
The Makefile.lammps file in this directory is used when building
LAMMPS with its PYTHON package installed. The file has several
settings needed to compile and link LAMMPS with the Python library.
You should choose a Makefile.lammps.* file compatible with your system
and your version of Python, and copy it to Makefile.lammps before
building LAMMPS itself. You may need to edit one of the provided
files to match your system.
Note that is not currently possible to use the PYTHON package with
Python 3, only with Python 2. The C API changed from Python 2 to 3
and the LAMMPS code is not compatible with both.
The default Makefile.lammps will automatically choose the default
python interpreter of your system and will infer the flags from
the python-config utility, that is usually bundled with the python
installation. If needed, you can copy one of the other provided
Makefile.lammps.* files to to Makefile.lammps before building
LAMMPS itself.
If you create a new Makefile.lammps file suitable for some version of
Python on some system, that is not a match to one of the provided
Makefile.lammps.* files, you can send it to the developers, and we can
include it in the distribution for others to use.
To illustrate, these are example settings from the
Makefile.lammps.python2.7 file:
The files Makefile.lammps.python2 and Makefile.lammps.python3 are
similar to the default file, but meant for the case that both,
python 2 and python 3, are installed simultaneously and you want
to prefer one over the other. If neither of these files work, you
may have to create a custom Makefile.lammps file suitable for
the version of Python on your system. To illustrate, these are
example settings from the Makefile.lammps.python2.7 file:
python_SYSINC = -I/usr/local/include/python2.7
python_SYSLIB = -lpython2.7 -lnsl -ldl -lreadline -ltermcap -lpthread -lutil -lm
python_SYSPATH =
python_SYSPATH =
PYTHON=python2.7
python_SYSINC refers to the directory where Python's Python.h file is
found. LAMMPS includes this file.
@ -30,10 +30,13 @@ application (LAMMPS in this case) to "embed" Python in the
application. The Python library itself is listed (-lpython2.7) are
are several system libraries needed by Python.
python_SYSPATH = refers to the path (e.g. -L/usr/local/lib) where the
python_SYSPATH refers to the path (e.g. -L/usr/local/lib) where the
Python library can be found. You may not need this setting if the
path is already included in your LD_LIBRARY_PATH environment variable.
PYTHON is the name of the python interpreter. It is used for
installing the LAMMPS python module with "make install-python"
-------------------------
Note that the trickiest issue to figure out for inclusion in

View File

@ -30,7 +30,7 @@ from collections import namedtuple
import os
import select
import re
import sys
class MPIAbortException(Exception):
def __init__(self, message):
@ -151,9 +151,16 @@ class lammps(object):
else:
# magic to convert ptr to ctypes ptr
pythonapi.PyCObject_AsVoidPtr.restype = c_void_p
pythonapi.PyCObject_AsVoidPtr.argtypes = [py_object]
self.lmp = c_void_p(pythonapi.PyCObject_AsVoidPtr(ptr))
if sys.version_info >= (3, 0):
# Python 3 (uses PyCapsule API)
pythonapi.PyCapsule_GetPointer.restype = c_void_p
pythonapi.PyCapsule_GetPointer.argtypes = [py_object, c_char_p]
self.lmp = c_void_p(pythonapi.PyCapsule_GetPointer(ptr, None))
else:
# Python 2 (uses PyCObject API)
pythonapi.PyCObject_AsVoidPtr.restype = c_void_p
pythonapi.PyCObject_AsVoidPtr.argtypes = [py_object]
self.lmp = c_void_p(pythonapi.PyCObject_AsVoidPtr(ptr))
def __del__(self):
if self.lmp and self.opened:
@ -305,7 +312,7 @@ class lammps(object):
def set_variable(self,name,value):
if name: name = name.encode()
if value: value = str(value).encode()
return self.lib.lammps_set_variable(self.lmp,name,str(value))
return self.lib.lammps_set_variable(self.lmp,name,value)
# return current value of thermo keyword

2
src/.gitignore vendored
View File

@ -848,8 +848,6 @@
/pppm_tip4p_cg.h
/prd.cpp
/prd.h
/python.cpp
/python.h
/python_impl.cpp
/python_impl.h
/reader_molfile.cpp

View File

@ -223,7 +223,8 @@ mpi-stubs:
@cd STUBS; $(MAKE) clean; $(MAKE)
# install LAMMPS shared lib and Python wrapper for Python usage
# include python package settings to automatically adapt name of python interpreter
sinclude ../lib/python/Makefile.lammps
install-python:
@$(PYTHON) ../python/install.py

View File

@ -26,11 +26,9 @@ action () {
fi
}
# force rebuild of files with LMP_KOKKOS switch
# also variable so its *.d dependence on changed python_wrapper.h is rebuilt
# force rebuild of files using python header
touch ../python_wrapper.h
touch ../variable.cpp
touch ../python.h
# all package files with no dependencies

View File

@ -25,25 +25,51 @@ enum{NONE,INT,DOUBLE,STRING,PTR};
#define VALUELENGTH 64 // also in variable.cpp
// Wrap API changes between Python 2 and 3 using macros
#if PY_MAJOR_VERSION == 2
#define PY_INT_FROM_LONG(X) PyInt_FromLong(X)
#define PY_INT_AS_LONG(X) PyInt_AsLong(X)
#define PY_STRING_FROM_STRING(X) PyString_FromString(X)
#define PY_VOID_POINTER(X) PyCObject_FromVoidPtr((void *) X, NULL)
#define PY_STRING_AS_STRING(X) PyString_AsString(X)
#elif PY_MAJOR_VERSION == 3
#define PY_INT_FROM_LONG(X) PyLong_FromLong(X)
#define PY_INT_AS_LONG(X) PyLong_AsLong(X)
#define PY_STRING_FROM_STRING(X) PyUnicode_FromString(X)
#define PY_VOID_POINTER(X) PyCapsule_New((void *) X, NULL, NULL)
#define PY_STRING_AS_STRING(X) PyUnicode_AsUTF8(X)
#endif
/* ---------------------------------------------------------------------- */
Python::Python(LAMMPS *lmp) : Pointers(lmp)
PythonImpl::PythonImpl(LAMMPS *lmp) : Pointers(lmp)
{
python_exists = 1;
pyMain = NULL;
// pfuncs stores interface info for each Python function
nfunc = 0;
pfuncs = NULL;
external_interpreter = false;
// one-time initialization of Python interpreter
// pymain stores pointer to main module
external_interpreter = Py_IsInitialized();
Py_Initialize();
PyEval_InitThreads();
PyGILState_STATE gstate = PyGILState_Ensure();
PyObject *pModule = PyImport_AddModule("__main__");
if (!pModule) error->all(FLERR,"Could not initialize embedded Python");
pyMain = (void *) pModule;
PyGILState_Release(gstate);
}
/* ---------------------------------------------------------------------- */
Python::~Python()
PythonImpl::~PythonImpl()
{
if(pyMain) {
// clean up
@ -71,7 +97,7 @@ Python::~Python()
/* ---------------------------------------------------------------------- */
void Python::command(int narg, char **arg)
void PythonImpl::command(int narg, char **arg)
{
if (narg < 2) error->all(FLERR,"Invalid python command");
@ -156,22 +182,7 @@ void Python::command(int narg, char **arg)
int ifunc = create_entry(arg[0]);
// one-time initialization of Python interpreter
// pymain stores pointer to main module
PyGILState_STATE gstate;
if (pyMain == NULL) {
external_interpreter = Py_IsInitialized();
Py_Initialize();
PyEval_InitThreads();
gstate = PyGILState_Ensure();
PyObject *pModule = PyImport_AddModule("__main__");
if (!pModule) error->all(FLERR,"Could not initialize embedded Python");
pyMain = (void *) pModule;
} else {
gstate = PyGILState_Ensure();
}
PyGILState_STATE gstate = PyGILState_Ensure();
// send Python code to Python interpreter
// file: read the file via PyRun_SimpleFile()
@ -230,7 +241,7 @@ void Python::command(int narg, char **arg)
/* ------------------------------------------------------------------ */
void Python::invoke_function(int ifunc, char *result)
void PythonImpl::invoke_function(int ifunc, char *result)
{
PyGILState_STATE gstate = PyGILState_Ensure();
PyObject *pValue;
@ -259,8 +270,10 @@ void Python::invoke_function(int ifunc, char *result)
error->all(FLERR,"Could not evaluate Python function input variable");
}
pValue = PyInt_FromLong(atoi(str));
} else pValue = PyInt_FromLong(pfuncs[ifunc].ivalue[i]);
pValue = PY_INT_FROM_LONG(atoi(str));
} else {
pValue = PY_INT_FROM_LONG(pfuncs[ifunc].ivalue[i]);
}
} else if (itype == DOUBLE) {
if (pfuncs[ifunc].ivarflag[i]) {
str = input->variable->retrieve(pfuncs[ifunc].svalue[i]);
@ -271,7 +284,9 @@ void Python::invoke_function(int ifunc, char *result)
}
pValue = PyFloat_FromDouble(atof(str));
} else pValue = PyFloat_FromDouble(pfuncs[ifunc].dvalue[i]);
} else {
pValue = PyFloat_FromDouble(pfuncs[ifunc].dvalue[i]);
}
} else if (itype == STRING) {
if (pfuncs[ifunc].ivarflag[i]) {
str = input->variable->retrieve(pfuncs[ifunc].svalue[i]);
@ -279,10 +294,13 @@ void Python::invoke_function(int ifunc, char *result)
PyGILState_Release(gstate);
error->all(FLERR,"Could not evaluate Python function input variable");
}
pValue = PyString_FromString(str);
} else pValue = PyString_FromString(pfuncs[ifunc].svalue[i]);
pValue = PY_STRING_FROM_STRING(str);
} else {
pValue = PY_STRING_FROM_STRING(pfuncs[ifunc].svalue[i]);
}
} else if (itype == PTR) {
pValue = PyCObject_FromVoidPtr((void *) lmp,NULL);
pValue = PY_VOID_POINTER(lmp);
}
PyTuple_SetItem(pArgs,i,pValue);
}
@ -306,11 +324,11 @@ void Python::invoke_function(int ifunc, char *result)
if (pfuncs[ifunc].noutput) {
int otype = pfuncs[ifunc].otype;
if (otype == INT) {
sprintf(result,"%ld",PyInt_AsLong(pValue));
sprintf(result,"%ld",PY_INT_AS_LONG(pValue));
} else if (otype == DOUBLE) {
sprintf(result,"%.15g",PyFloat_AsDouble(pValue));
} else if (otype == STRING) {
char *pystr = PyString_AsString(pValue);
char *pystr = PY_STRING_AS_STRING(pValue);
if (pfuncs[ifunc].longstr)
strncpy(pfuncs[ifunc].longstr,pystr,pfuncs[ifunc].length_longstr);
else strncpy(result,pystr,VALUELENGTH-1);
@ -323,7 +341,7 @@ void Python::invoke_function(int ifunc, char *result)
/* ------------------------------------------------------------------ */
int Python::find(char *name)
int PythonImpl::find(char *name)
{
for (int i = 0; i < nfunc; i++)
if (strcmp(name,pfuncs[i].name) == 0) return i;
@ -332,7 +350,7 @@ int Python::find(char *name)
/* ------------------------------------------------------------------ */
int Python::variable_match(char *name, char *varname, int numeric)
int PythonImpl::variable_match(char *name, char *varname, int numeric)
{
int ifunc = find(name);
if (ifunc < 0) return -1;
@ -344,14 +362,14 @@ int Python::variable_match(char *name, char *varname, int numeric)
/* ------------------------------------------------------------------ */
char *Python::long_string(int ifunc)
char *PythonImpl::long_string(int ifunc)
{
return pfuncs[ifunc].longstr;
}
/* ------------------------------------------------------------------ */
int Python::create_entry(char *name)
int PythonImpl::create_entry(char *name)
{
// ifunc = index to entry by name in pfuncs vector, can be old or new
// free old vectors if overwriting old pfunc
@ -461,7 +479,7 @@ int Python::create_entry(char *name)
/* ------------------------------------------------------------------ */
void Python::deallocate(int i)
void PythonImpl::deallocate(int i)
{
delete [] pfuncs[i].itype;
delete [] pfuncs[i].ivarflag;

130
src/PYTHON/python_impl.h Normal file
View File

@ -0,0 +1,130 @@
/* -*- 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.
------------------------------------------------------------------------- */
#ifndef LMP_PYTHON_IMPL_H
#define LMP_PYTHON_IMPL_H
#include "pointers.h"
namespace LAMMPS_NS {
class PythonImpl : protected Pointers, public PythonInterface {
public:
bool external_interpreter;
PythonImpl(class LAMMPS *);
~PythonImpl();
void command(int, char **);
void invoke_function(int, char *);
int find(char *);
int variable_match(char *, char *, int);
char *long_string(int);
private:
int ninput,noutput,length_longstr;
char **istr;
char *ostr,*format;
void *pyMain;
struct PyFunc {
char *name;
int ninput,noutput;
int *itype,*ivarflag;
int *ivalue;
double *dvalue;
char **svalue;
int otype;
char *ovarname;
char *longstr;
int length_longstr;
void *pFunc;
};
PyFunc *pfuncs;
int nfunc;
int create_entry(char *);
void deallocate(int);
};
}
#endif
/* ERROR/WARNING messages:
E: Invalid python 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.
E: Python invoke of undefined function
Cannot invoke a function that has not been previously defined.
E: Python variable does not match Python function
This matching is defined by the python-style variable and the python
command.
E: Cannot embed Python when also extending Python with LAMMPS
When running LAMMPS via Python through the LAMMPS library interface
you cannot also user the input script python command.
E: Could not initialize embedded Python
The main module in Python was not accessible.
E: Could not open Python file
The specified file of Python code cannot be opened. Check that the
path and name are correct.
E: Could not process Python file
The Python code in the specified file was not run successfully by
Python, probably due to errors in the Python code.
E: Could not process Python string
The Python code in the here string was not run successfully by Python,
probably due to errors in the Python code.
E: Could not find Python function
The provided Python code was run successfully, but it not
define a callable function with the required name.
E: Python function is not callable
The provided Python code was run successfully, but it not
define a callable function with the required name.
E: Could not create Python function arguments
This is an internal Python error, possibly because the number
of inputs to the function is too large.
E: Could not evaluate Python function input variable
Self-explanatory.
E: Python function evaluation failed
The Python function did not run successfully and/or did not return a
value (if it is supposed to return a value). This is probably due to
some error condition in the function.
*/

View File

@ -45,6 +45,7 @@
#include "accelerator_kokkos.h"
#include "accelerator_omp.h"
#include "timer.h"
#include "python.h"
#include "memory.h"
#include "version.h"
#include "error.h"
@ -67,6 +68,7 @@ LAMMPS::LAMMPS(int narg, char **arg, MPI_Comm communicator)
error = new Error(this);
universe = new Universe(this,communicator);
output = NULL;
python = NULL;
screen = NULL;
logfile = NULL;
@ -585,6 +587,7 @@ LAMMPS::~LAMMPS()
if (world != universe->uworld) MPI_Comm_free(&world);
delete python;
delete kokkos;
delete [] suffix;
delete [] suffix2;
@ -639,6 +642,8 @@ void LAMMPS::create()
// must be after modify so can create Computes
update = new Update(this); // must be after output, force, neighbor
timer = new Timer(this);
python = new Python(this);
}
/* ----------------------------------------------------------------------
@ -759,6 +764,9 @@ void LAMMPS::destroy()
delete timer;
timer = NULL;
delete python;
python = NULL;
}
/* ----------------------------------------------------------------------

View File

@ -54,6 +54,8 @@ class LAMMPS {
class KokkosLMP *kokkos; // KOKKOS accelerator class
class AtomKokkos *atomKK; // KOKKOS version of Atom class
class Python * python; // Python interface
class CiteMe *citeme; // citation info
LAMMPS(int, char **, MPI_Comm);

View File

@ -56,7 +56,8 @@ class Pointers {
infile(ptr->infile),
screen(ptr->screen),
logfile(ptr->logfile),
atomKK(ptr->atomKK) {}
atomKK(ptr->atomKK),
python(ptr->python) {}
virtual ~Pointers() {}
protected:
@ -83,6 +84,7 @@ class Pointers {
FILE *&logfile;
class AtomKokkos *&atomKK;
class Python *&python;
};
}

99
src/python.cpp Normal file
View File

@ -0,0 +1,99 @@
/* ----------------------------------------------------------------------
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 "python.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
Python::Python(LAMMPS *lmp) : Pointers(lmp)
{
// implementation of Python interface is only loaded on demand
// and only if PYTHON package has been installed and compiled into binary
impl = NULL;
}
/* ---------------------------------------------------------------------- */
Python::~Python()
{
delete impl;
}
/* ---------------------------------------------------------------------- */
PythonInterface::~PythonInterface()
{
}
/* ---------------------------------------------------------------------- */
void Python::init()
{
#if LMP_PYTHON
if (!impl) impl = new PythonImpl(lmp);
#else
error->all(FLERR,"Python support missing! Compile with PYTHON package installed!");
#endif
}
/* ---------------------------------------------------------------------- */
bool Python::is_enabled() const {
#if LMP_PYTHON
return true;
#else
return false;
#endif
}
/* ---------------------------------------------------------------------- */
void Python::command(int narg, char **arg)
{
init();
impl->command(narg, arg);
}
/* ------------------------------------------------------------------ */
void Python::invoke_function(int ifunc, char *result)
{
init();
impl->invoke_function(ifunc, result);
}
/* ------------------------------------------------------------------ */
int Python::find(char *name)
{
init();
return impl->find(name);
}
/* ------------------------------------------------------------------ */
int Python::variable_match(char *name, char *varname, int numeric)
{
init();
return impl->variable_match(name, varname, numeric);
}
/* ------------------------------------------------------------------ */
char * Python::long_string(int ifunc)
{
init();
return impl->long_string(ifunc);
}

View File

@ -18,50 +18,42 @@
namespace LAMMPS_NS {
class Python : protected Pointers {
public:
int python_exists;
bool external_interpreter;
class PythonInterface {
public:
virtual ~PythonInterface();
virtual void command(int, char **) = 0;
virtual void invoke_function(int, char *) = 0;
virtual int find(char *) = 0;
virtual int variable_match(char *, char *, int) = 0;
virtual char * long_string(int ifunc) = 0;
};
class Python : protected Pointers {
public:
Python(class LAMMPS *);
~Python();
void command(int, char **);
void invoke_function(int, char *);
int find(char *);
int variable_match(char *, char *, int);
char *long_string(int);
char * long_string(int ifunc);
private:
int ninput,noutput,length_longstr;
char **istr;
char *ostr,*format;
void *pyMain;
bool is_enabled() const;
void init();
struct PyFunc {
char *name;
int ninput,noutput;
int *itype,*ivarflag;
int *ivalue;
double *dvalue;
char **svalue;
int otype;
char *ovarname;
char *longstr;
int length_longstr;
void *pFunc;
};
PyFunc *pfuncs;
int nfunc;
int create_entry(char *);
void deallocate(int);
private:
PythonInterface * impl;
};
}
#endif
#if LMP_PYTHON
#include "python_impl.h"
#endif
/* ERROR/WARNING messages:
E: Invalid python command

View File

@ -1,47 +0,0 @@
/* -*- 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.
------------------------------------------------------------------------- */
#ifndef LMP_PYTHON_WRAPPER_H
#define LMP_PYTHON_WRAPPER_H
// true interface to embedded Python
// used when PYTHON package is installed
#ifdef LMP_PYTHON
#include "python.h"
#else
// dummy interface to PYTHON
// needed for compiling when PYTHON is not installed
namespace LAMMPS_NS {
class Python {
public:
int python_exists;
Python(class LAMMPS *) {python_exists = 0;}
~Python() {}
void command(int, char **) {}
void invoke_function(int, char *) {}
int find(char *) {return -1;}
int variable_match(char *, char *, int) {return -1;}
char *long_string(int) {return NULL;}
};
}
#endif
#endif

View File

@ -34,7 +34,7 @@
#include "random_mars.h"
#include "math_const.h"
#include "atom_masks.h"
#include "python_wrapper.h"
#include "python.h"
#include "memory.h"
#include "info.h"
#include "error.h"
@ -111,10 +111,6 @@ Variable::Variable(LAMMPS *lmp) : Pointers(lmp)
precedence[MULTIPLY] = precedence[DIVIDE] = precedence[MODULO] = 6;
precedence[CARAT] = 7;
precedence[UNARY] = precedence[NOT] = 8;
// Python wrapper, real or dummy
python = new Python(lmp);
}
/* ---------------------------------------------------------------------- */
@ -144,7 +140,6 @@ Variable::~Variable()
delete randomequal;
delete randomatom;
delete python;
}
/* ----------------------------------------------------------------------
@ -464,7 +459,7 @@ void Variable::set(int narg, char **arg)
} else if (strcmp(arg[1],"python") == 0) {
if (narg != 3) error->all(FLERR,"Illegal variable command");
if (!python->python_exists)
if (!python->is_enabled())
error->all(FLERR,"LAMMPS is not built with Python embedded");
int ivar = find(arg[0]);
if (ivar >= 0) {
@ -735,7 +730,7 @@ void Variable::set_arrays(int i)
void Variable::python_command(int narg, char **arg)
{
if (!python->python_exists)
if (!python->is_enabled())
error->all(FLERR,"LAMMPS is not built with Python embedded");
python->command(narg,arg);
}

View File

@ -78,8 +78,6 @@ class Variable : protected Pointers {
int precedence[18]; // precedence level of math operators
// set length to include up to XOR in enum
class Python *python; // ptr to embedded Python interpreter
struct Tree { // parse tree for atom-style or vector-style vars
double value; // single scalar
double *array; // per-atom or per-type list of doubles