Change how a Python pair style is loaded
Implements a class loader which takes a fully qualified Python class name, loads the module and creates an object instance. To add flexibility, the current working directory and the directory specified by the LAMMPS_POTENTIALS environment variable are added to the module search path.
This commit is contained in:
@ -12,7 +12,7 @@ mass * 1.0
|
|||||||
velocity all create 3.0 87287
|
velocity all create 3.0 87287
|
||||||
|
|
||||||
pair_style hybrid lj/cut 2.5 python 2.5
|
pair_style hybrid lj/cut 2.5 python 2.5
|
||||||
pair_coeff * * python lj-melt-potential.py lj NULL
|
pair_coeff * * python potentials.LAMMPSLJCutPotential lj NULL
|
||||||
pair_coeff * 2 lj/cut 1.0 1.0
|
pair_coeff * 2 lj/cut 1.0 1.0
|
||||||
|
|
||||||
neighbor 0.3 bin
|
neighbor 0.3 bin
|
||||||
@ -31,7 +31,7 @@ clear
|
|||||||
read_restart hybrid.restart
|
read_restart hybrid.restart
|
||||||
|
|
||||||
pair_style hybrid lj/cut 2.5 python 2.5
|
pair_style hybrid lj/cut 2.5 python 2.5
|
||||||
pair_coeff * * python lj-melt-potential.py lj NULL
|
pair_coeff * * python potentials.LAMMPSLJCutPotential lj NULL
|
||||||
pair_coeff * 2 lj/cut 1.0 1.0
|
pair_coeff * 2 lj/cut 1.0 1.0
|
||||||
|
|
||||||
fix 1 all nve
|
fix 1 all nve
|
||||||
@ -47,7 +47,7 @@ atom_style atomic
|
|||||||
read_data hybrid.data
|
read_data hybrid.data
|
||||||
|
|
||||||
pair_style hybrid lj/cut 2.5 python 2.5
|
pair_style hybrid lj/cut 2.5 python 2.5
|
||||||
pair_coeff * * python lj-melt-potential.py lj NULL
|
pair_coeff * * python potentials.LAMMPSLJCutPotential lj NULL
|
||||||
pair_coeff * 2 lj/cut 1.0 1.0
|
pair_coeff * 2 lj/cut 1.0 1.0
|
||||||
|
|
||||||
neighbor 0.3 bin
|
neighbor 0.3 bin
|
||||||
|
|||||||
@ -12,7 +12,7 @@ mass * 1.0
|
|||||||
velocity all create 3.0 87287
|
velocity all create 3.0 87287
|
||||||
|
|
||||||
pair_style python 2.5
|
pair_style python 2.5
|
||||||
pair_coeff * * lj-melt-potential.py lj
|
pair_coeff * * potentials.LAMMPSLJCutPotential lj
|
||||||
|
|
||||||
neighbor 0.3 bin
|
neighbor 0.3 bin
|
||||||
neigh_modify every 20 delay 0 check no
|
neigh_modify every 20 delay 0 check no
|
||||||
@ -30,7 +30,7 @@ clear
|
|||||||
read_restart melt.restart
|
read_restart melt.restart
|
||||||
|
|
||||||
pair_style python 2.5
|
pair_style python 2.5
|
||||||
pair_coeff * * lj-melt-potential.py lj
|
pair_coeff * * potentials.LAMMPSLJCutPotential lj
|
||||||
|
|
||||||
fix 1 all nve
|
fix 1 all nve
|
||||||
|
|
||||||
@ -45,7 +45,7 @@ atom_style atomic
|
|||||||
read_data melt.data
|
read_data melt.data
|
||||||
|
|
||||||
pair_style python 2.5
|
pair_style python 2.5
|
||||||
pair_coeff * * lj-melt-potential.py lj
|
pair_coeff * * potentials.LAMMPSLJCutPotential lj
|
||||||
|
|
||||||
neighbor 0.3 bin
|
neighbor 0.3 bin
|
||||||
neigh_modify every 20 delay 0 check no
|
neigh_modify every 20 delay 0 check no
|
||||||
|
|||||||
@ -32,6 +32,3 @@ class LAMMPSLJCutPotential(object):
|
|||||||
lj3 = coeff[4]
|
lj3 = coeff[4]
|
||||||
lj4 = coeff[5]
|
lj4 = coeff[5]
|
||||||
return (r6inv * (lj3*r6inv - lj4))
|
return (r6inv * (lj3*r6inv - lj4))
|
||||||
|
|
||||||
lammps_pair_style = LAMMPSLJCutPotential()
|
|
||||||
|
|
||||||
@ -42,12 +42,26 @@ PairPython::PairPython(LAMMPS *lmp) : Pair(lmp) {
|
|||||||
reinitflag = 0;
|
reinitflag = 0;
|
||||||
|
|
||||||
python->init();
|
python->init();
|
||||||
|
|
||||||
|
py_potential = NULL;
|
||||||
|
|
||||||
|
// add current directory to PYTHONPATH
|
||||||
|
PyObject * py_path = PySys_GetObject("path");
|
||||||
|
PyList_Append(py_path, PY_STRING_FROM_STRING("."));
|
||||||
|
|
||||||
|
// if LAMMPS_POTENTIALS environment variable is set, add it to PYTHONPATH as well
|
||||||
|
const char * potentials_path = getenv("LAMMPS_POTENTIALS");
|
||||||
|
if (potentials_path != NULL) {
|
||||||
|
PyList_Append(py_path, PY_STRING_FROM_STRING(potentials_path));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
PairPython::~PairPython()
|
PairPython::~PairPython()
|
||||||
{
|
{
|
||||||
|
if(py_potential) Py_DECREF((PyObject*) py_potential);
|
||||||
|
|
||||||
if (allocated) {
|
if (allocated) {
|
||||||
memory->destroy(setflag);
|
memory->destroy(setflag);
|
||||||
memory->destroy(cutsq);
|
memory->destroy(cutsq);
|
||||||
@ -234,34 +248,56 @@ void PairPython::coeff(int narg, char **arg)
|
|||||||
error->all(FLERR,"Incorrect args for pair coefficients");
|
error->all(FLERR,"Incorrect args for pair coefficients");
|
||||||
|
|
||||||
// check if python potential file exists and source it
|
// check if python potential file exists and source it
|
||||||
|
char * full_cls_name = arg[2];
|
||||||
|
char * lastpos = strrchr(full_cls_name, '.');
|
||||||
|
|
||||||
FILE *fp = fopen(arg[2],"r");
|
if (lastpos == NULL) {
|
||||||
if (fp == NULL)
|
error->all(FLERR,"Python pair style requires fully qualified class name");
|
||||||
error->all(FLERR,"Cannot open python pair potential class file");
|
}
|
||||||
|
|
||||||
|
size_t module_name_length = strlen(full_cls_name) - strlen(lastpos);
|
||||||
|
size_t cls_name_length = strlen(lastpos)-1;
|
||||||
|
|
||||||
|
char * module_name = new char[module_name_length+1];
|
||||||
|
char * cls_name = new char[cls_name_length+1];
|
||||||
|
strncpy(module_name, full_cls_name, module_name_length);
|
||||||
|
module_name[module_name_length] = 0;
|
||||||
|
|
||||||
|
strcpy(cls_name, lastpos+1);
|
||||||
|
|
||||||
PyGILState_STATE gstate = PyGILState_Ensure();
|
PyGILState_STATE gstate = PyGILState_Ensure();
|
||||||
|
|
||||||
int err = PyRun_SimpleFile(fp,arg[2]);
|
PyObject * pModule = PyImport_ImportModule(module_name);
|
||||||
if (err) {
|
if (!pModule) {
|
||||||
|
PyErr_Print();
|
||||||
|
PyErr_Clear();
|
||||||
PyGILState_Release(gstate);
|
PyGILState_Release(gstate);
|
||||||
error->all(FLERR,"Loading python pair style class failure");
|
error->all(FLERR,"Loading python pair style module failure");
|
||||||
}
|
}
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
// create LAMMPS atom type to potential file type mapping in python class
|
// create LAMMPS atom type to potential file type mapping in python class
|
||||||
// by calling 'lammps_pair_style.map_coeff(name,type)'
|
// by calling 'lammps_pair_style.map_coeff(name,type)'
|
||||||
|
|
||||||
PyObject *pModule = PyImport_AddModule("__main__");
|
PyObject *py_pair_type = PyObject_GetAttrString(pModule, cls_name);
|
||||||
if (!pModule) error->all(FLERR,"Could not initialize embedded Python");
|
if (!py_pair_type) {
|
||||||
|
PyErr_Print();
|
||||||
|
PyErr_Clear();
|
||||||
|
PyGILState_Release(gstate);
|
||||||
|
error->all(FLERR,"Could not find pair style class in module'");
|
||||||
|
}
|
||||||
|
|
||||||
PyObject *py_pair_instance = PyObject_GetAttrString(pModule,"lammps_pair_style");
|
delete [] module_name;
|
||||||
|
delete [] cls_name;
|
||||||
|
|
||||||
|
PyObject * py_pair_instance = PyObject_CallObject(py_pair_type, NULL);
|
||||||
if (!py_pair_instance) {
|
if (!py_pair_instance) {
|
||||||
PyErr_Print();
|
PyErr_Print();
|
||||||
PyErr_Clear();
|
PyErr_Clear();
|
||||||
PyGILState_Release(gstate);
|
PyGILState_Release(gstate);
|
||||||
error->all(FLERR,"Could not find 'lammps_pair_style instance'");
|
error->all(FLERR,"Could not instantiate instance of pair style class'");
|
||||||
}
|
}
|
||||||
py_potential = (void *) py_pair_instance; // XXX do we need to increment reference counter?
|
|
||||||
|
py_potential = (void *) py_pair_instance;
|
||||||
|
|
||||||
PyObject *py_map_coeff = PyObject_GetAttrString(py_pair_instance,"map_coeff");
|
PyObject *py_map_coeff = PyObject_GetAttrString(py_pair_instance,"map_coeff");
|
||||||
if (!py_map_coeff) {
|
if (!py_map_coeff) {
|
||||||
|
|||||||
Reference in New Issue
Block a user