Add Python 3 compatibility to PYTHON package
This commit is contained in:
@ -1,9 +1,10 @@
|
|||||||
# Python function that implements a loop of short runs
|
# Python function that implements a loop of short runs
|
||||||
# calls back to LAMMPS via "lmp" instance
|
# calls back to LAMMPS via "lmp" instance
|
||||||
# lammps() must be called with ptr=lmpptr for this to work
|
# lammps() must be called with ptr=lmpptr for this to work
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
def loop(N,cut0,thresh,lmpptr):
|
def loop(N,cut0,thresh,lmpptr):
|
||||||
print "LOOP ARGS",N,cut0,thresh,lmpptr
|
print("LOOP ARGS",N,cut0,thresh,lmpptr)
|
||||||
from lammps import lammps
|
from lammps import lammps
|
||||||
lmp = lammps(ptr=lmpptr)
|
lmp = lammps(ptr=lmpptr)
|
||||||
natoms = lmp.get_natoms()
|
natoms = lmp.get_natoms()
|
||||||
@ -12,11 +13,12 @@ def loop(N,cut0,thresh,lmpptr):
|
|||||||
cut = cut0 + i*0.1
|
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 command
|
lmp.command("pair_style lj/cut ${cut}") # LAMMPS command
|
||||||
#lmp.command("pair_style lj/cut %d" % cut) # LAMMPS command option
|
#lmp.command("pair_style lj/cut %d" % cut) # LAMMPS command option
|
||||||
|
|
||||||
lmp.command("pair_coeff * * 1.0 1.0") # ditto
|
lmp.command("pair_coeff * * 1.0 1.0") # ditto
|
||||||
lmp.command("run 10") # ditto
|
lmp.command("run 10") # ditto
|
||||||
pe = lmp.extract_compute("thermo_pe",0,0) # extract total PE from LAMMPS
|
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
|
if pe/natoms < thresh: return
|
||||||
|
|||||||
@ -25,13 +25,14 @@ run 10
|
|||||||
# example of catching a syntax error
|
# example of catching a syntax error
|
||||||
|
|
||||||
python simple here """
|
python simple here """
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
def simple():
|
def simple():
|
||||||
import exceptions
|
print("Inside simple function")
|
||||||
print "Inside simple function"
|
|
||||||
try:
|
try:
|
||||||
foo += 1
|
foo += 1
|
||||||
except Exception, e:
|
except Exception as e:
|
||||||
print "FOO error:",e
|
print("FOO error:", e)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
python simple invoke
|
python simple invoke
|
||||||
|
|||||||
6
lib/python/Makefile.lammps.python3
Normal file
6
lib/python/Makefile.lammps.python3
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# 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 || python-config --includes )
|
||||||
|
python_SYSLIB = $(shell which python3-config > /dev/null 2>&1 && python3-config --ldflags || python-config --ldflags)
|
||||||
|
python_SYSPATH =
|
||||||
@ -6,10 +6,6 @@ and your version of Python, and copy it to Makefile.lammps before
|
|||||||
building LAMMPS itself. You may need to edit one of the provided
|
building LAMMPS itself. You may need to edit one of the provided
|
||||||
files to match your system.
|
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.
|
|
||||||
|
|
||||||
If you create a new Makefile.lammps file suitable for some version of
|
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
|
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
|
Makefile.lammps.* files, you can send it to the developers, and we can
|
||||||
|
|||||||
@ -30,7 +30,7 @@ from collections import namedtuple
|
|||||||
import os
|
import os
|
||||||
import select
|
import select
|
||||||
import re
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
class MPIAbortException(Exception):
|
class MPIAbortException(Exception):
|
||||||
def __init__(self, message):
|
def __init__(self, message):
|
||||||
@ -151,9 +151,16 @@ class lammps(object):
|
|||||||
|
|
||||||
else:
|
else:
|
||||||
# magic to convert ptr to ctypes ptr
|
# magic to convert ptr to ctypes ptr
|
||||||
pythonapi.PyCObject_AsVoidPtr.restype = c_void_p
|
if sys.version_info >= (3, 0):
|
||||||
pythonapi.PyCObject_AsVoidPtr.argtypes = [py_object]
|
# Python 3 (uses PyCapsule API)
|
||||||
self.lmp = c_void_p(pythonapi.PyCObject_AsVoidPtr(ptr))
|
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):
|
def __del__(self):
|
||||||
if self.lmp and self.opened:
|
if self.lmp and self.opened:
|
||||||
@ -305,7 +312,7 @@ class lammps(object):
|
|||||||
def set_variable(self,name,value):
|
def set_variable(self,name,value):
|
||||||
if name: name = name.encode()
|
if name: name = name.encode()
|
||||||
if value: value = str(value).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
|
# return current value of thermo keyword
|
||||||
|
|
||||||
|
|||||||
@ -25,6 +25,22 @@ enum{NONE,INT,DOUBLE,STRING,PTR};
|
|||||||
|
|
||||||
#define VALUELENGTH 64 // also in variable.cpp
|
#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)
|
Python::Python(LAMMPS *lmp) : Pointers(lmp)
|
||||||
@ -257,8 +273,10 @@ void Python::invoke_function(int ifunc, char *result)
|
|||||||
error->all(FLERR,"Could not evaluate Python function input variable");
|
error->all(FLERR,"Could not evaluate Python function input variable");
|
||||||
}
|
}
|
||||||
|
|
||||||
pValue = PyInt_FromLong(atoi(str));
|
pValue = PY_INT_FROM_LONG(atoi(str));
|
||||||
} else pValue = PyInt_FromLong(pfuncs[ifunc].ivalue[i]);
|
} else {
|
||||||
|
pValue = PY_INT_FROM_LONG(pfuncs[ifunc].ivalue[i]);
|
||||||
|
}
|
||||||
} else if (itype == DOUBLE) {
|
} else if (itype == DOUBLE) {
|
||||||
if (pfuncs[ifunc].ivarflag[i]) {
|
if (pfuncs[ifunc].ivarflag[i]) {
|
||||||
str = input->variable->retrieve(pfuncs[ifunc].svalue[i]);
|
str = input->variable->retrieve(pfuncs[ifunc].svalue[i]);
|
||||||
@ -269,7 +287,9 @@ void Python::invoke_function(int ifunc, char *result)
|
|||||||
}
|
}
|
||||||
|
|
||||||
pValue = PyFloat_FromDouble(atof(str));
|
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) {
|
} else if (itype == STRING) {
|
||||||
if (pfuncs[ifunc].ivarflag[i]) {
|
if (pfuncs[ifunc].ivarflag[i]) {
|
||||||
str = input->variable->retrieve(pfuncs[ifunc].svalue[i]);
|
str = input->variable->retrieve(pfuncs[ifunc].svalue[i]);
|
||||||
@ -277,10 +297,13 @@ void Python::invoke_function(int ifunc, char *result)
|
|||||||
PyGILState_Release(gstate);
|
PyGILState_Release(gstate);
|
||||||
error->all(FLERR,"Could not evaluate Python function input variable");
|
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) {
|
} else if (itype == PTR) {
|
||||||
pValue = PyCObject_FromVoidPtr((void *) lmp,NULL);
|
pValue = PY_VOID_POINTER(lmp);
|
||||||
}
|
}
|
||||||
PyTuple_SetItem(pArgs,i,pValue);
|
PyTuple_SetItem(pArgs,i,pValue);
|
||||||
}
|
}
|
||||||
@ -304,11 +327,11 @@ void Python::invoke_function(int ifunc, char *result)
|
|||||||
if (pfuncs[ifunc].noutput) {
|
if (pfuncs[ifunc].noutput) {
|
||||||
int otype = pfuncs[ifunc].otype;
|
int otype = pfuncs[ifunc].otype;
|
||||||
if (otype == INT) {
|
if (otype == INT) {
|
||||||
sprintf(result,"%ld",PyInt_AsLong(pValue));
|
sprintf(result,"%ld",PY_INT_AS_LONG(pValue));
|
||||||
} else if (otype == DOUBLE) {
|
} else if (otype == DOUBLE) {
|
||||||
sprintf(result,"%.15g",PyFloat_AsDouble(pValue));
|
sprintf(result,"%.15g",PyFloat_AsDouble(pValue));
|
||||||
} else if (otype == STRING) {
|
} else if (otype == STRING) {
|
||||||
char *pystr = PyString_AsString(pValue);
|
char *pystr = PY_STRING_AS_STRING(pValue);
|
||||||
if (pfuncs[ifunc].longstr)
|
if (pfuncs[ifunc].longstr)
|
||||||
strncpy(pfuncs[ifunc].longstr,pystr,pfuncs[ifunc].length_longstr);
|
strncpy(pfuncs[ifunc].longstr,pystr,pfuncs[ifunc].length_longstr);
|
||||||
else strncpy(result,pystr,VALUELENGTH-1);
|
else strncpy(result,pystr,VALUELENGTH-1);
|
||||||
|
|||||||
Reference in New Issue
Block a user