mirror of https://github.com/lammps/lammps.git
Add Python 3 compatibility to PYTHON package
This commit is contained in:
parent
4da8c1c4e2
commit
9a027a01da
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
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
|
||||
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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -25,6 +25,22 @@ 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)
|
||||
|
@ -257,8 +273,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]);
|
||||
|
@ -269,7 +287,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]);
|
||||
|
@ -277,10 +297,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);
|
||||
}
|
||||
|
@ -304,11 +327,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);
|
||||
|
|
Loading…
Reference in New Issue