diff --git a/examples/python/in.pair_python_hybrid b/examples/python/in.pair_python_hybrid index 914b840e86..b917910a29 100644 --- a/examples/python/in.pair_python_hybrid +++ b/examples/python/in.pair_python_hybrid @@ -12,7 +12,7 @@ mass * 1.0 velocity all create 3.0 87287 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 neighbor 0.3 bin @@ -31,7 +31,7 @@ clear read_restart hybrid.restart 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 fix 1 all nve @@ -47,7 +47,7 @@ atom_style atomic read_data hybrid.data 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 neighbor 0.3 bin diff --git a/examples/python/in.pair_python_melt b/examples/python/in.pair_python_melt index ae37aafa77..2367ea0026 100644 --- a/examples/python/in.pair_python_melt +++ b/examples/python/in.pair_python_melt @@ -12,7 +12,7 @@ mass * 1.0 velocity all create 3.0 87287 pair_style python 2.5 -pair_coeff * * lj-melt-potential.py lj +pair_coeff * * potentials.LAMMPSLJCutPotential lj neighbor 0.3 bin neigh_modify every 20 delay 0 check no @@ -30,7 +30,7 @@ clear read_restart melt.restart pair_style python 2.5 -pair_coeff * * lj-melt-potential.py lj +pair_coeff * * potentials.LAMMPSLJCutPotential lj fix 1 all nve @@ -45,7 +45,7 @@ atom_style atomic read_data melt.data pair_style python 2.5 -pair_coeff * * lj-melt-potential.py lj +pair_coeff * * potentials.LAMMPSLJCutPotential lj neighbor 0.3 bin neigh_modify every 20 delay 0 check no diff --git a/examples/python/lj-melt-potential.py b/examples/python/potentials.py similarity index 96% rename from examples/python/lj-melt-potential.py rename to examples/python/potentials.py index 3d7332faa8..2438a8ba46 100644 --- a/examples/python/lj-melt-potential.py +++ b/examples/python/potentials.py @@ -32,6 +32,3 @@ class LAMMPSLJCutPotential(object): lj3 = coeff[4] lj4 = coeff[5] return (r6inv * (lj3*r6inv - lj4)) - -lammps_pair_style = LAMMPSLJCutPotential() - diff --git a/src/PYTHON/pair_python.cpp b/src/PYTHON/pair_python.cpp index 485efee58d..60f317ee96 100644 --- a/src/PYTHON/pair_python.cpp +++ b/src/PYTHON/pair_python.cpp @@ -42,12 +42,26 @@ PairPython::PairPython(LAMMPS *lmp) : Pair(lmp) { reinitflag = 0; 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() { + if(py_potential) Py_DECREF((PyObject*) py_potential); + if (allocated) { memory->destroy(setflag); memory->destroy(cutsq); @@ -234,34 +248,56 @@ void PairPython::coeff(int narg, char **arg) error->all(FLERR,"Incorrect args for pair coefficients"); // 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 (fp == NULL) - error->all(FLERR,"Cannot open python pair potential class file"); + if (lastpos == NULL) { + error->all(FLERR,"Python pair style requires fully qualified class name"); + } + + 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(); - int err = PyRun_SimpleFile(fp,arg[2]); - if (err) { + PyObject * pModule = PyImport_ImportModule(module_name); + if (!pModule) { + PyErr_Print(); + PyErr_Clear(); 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 // by calling 'lammps_pair_style.map_coeff(name,type)' - PyObject *pModule = PyImport_AddModule("__main__"); - if (!pModule) error->all(FLERR,"Could not initialize embedded Python"); + PyObject *py_pair_type = PyObject_GetAttrString(pModule, cls_name); + 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) { PyErr_Print(); PyErr_Clear(); 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"); if (!py_map_coeff) {