Refactor PYTHON package and wrapper classes

This commit is contained in:
Richard Berger 2017-04-11 21:22:30 -04:00
parent 9a027a01da
commit 2d8bce78a6
11 changed files with 280 additions and 58 deletions

4
src/.gitignore vendored
View File

@ -846,8 +846,8 @@
/pppm_tip4p_cg.h /pppm_tip4p_cg.h
/prd.cpp /prd.cpp
/prd.h /prd.h
/python.cpp /python_impl.cpp
/python.h /python_impl.h
/reader_molfile.cpp /reader_molfile.cpp
/reader_molfile.h /reader_molfile.h
/reaxc_allocate.cpp /reaxc_allocate.cpp

View File

@ -26,16 +26,14 @@ action () {
fi fi
} }
# force rebuild of files with LMP_KOKKOS switch # force rebuild of files using python header
# also variable so its *.d dependence on changed python_wrapper.h is rebuilt
touch ../python_wrapper.h touch ../python.h
touch ../variable.cpp
# all package files with no dependencies # all package files with no dependencies
for file in *.cpp *.h; do for file in *.cpp *.h; do
test -f ${file} && action $file action $file
done done
# edit 2 Makefile.package files to include/exclude package info # edit 2 Makefile.package files to include/exclude package info

View File

@ -43,10 +43,8 @@ enum{NONE,INT,DOUBLE,STRING,PTR};
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
Python::Python(LAMMPS *lmp) : Pointers(lmp) PythonImpl::PythonImpl(LAMMPS *lmp) : Pointers(lmp)
{ {
python_exists = 1;
pyMain = NULL; pyMain = NULL;
// pfuncs stores interface info for each Python function // pfuncs stores interface info for each Python function
@ -59,7 +57,7 @@ Python::Python(LAMMPS *lmp) : Pointers(lmp)
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
Python::~Python() PythonImpl::~PythonImpl()
{ {
// clean up // clean up
PyGILState_STATE gstate = PyGILState_Ensure(); PyGILState_STATE gstate = PyGILState_Ensure();
@ -85,7 +83,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"); if (narg < 2) error->all(FLERR,"Invalid python command");
@ -244,7 +242,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(); PyGILState_STATE gstate = PyGILState_Ensure();
PyObject *pValue; PyObject *pValue;
@ -344,7 +342,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++) for (int i = 0; i < nfunc; i++)
if (strcmp(name,pfuncs[i].name) == 0) return i; if (strcmp(name,pfuncs[i].name) == 0) return i;
@ -353,7 +351,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); int ifunc = find(name);
if (ifunc < 0) return -1; if (ifunc < 0) return -1;
@ -365,14 +363,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; 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 // ifunc = index to entry by name in pfuncs vector, can be old or new
// free old vectors if overwriting old pfunc // free old vectors if overwriting old pfunc
@ -482,7 +480,7 @@ int Python::create_entry(char *name)
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
void Python::deallocate(int i) void PythonImpl::deallocate(int i)
{ {
delete [] pfuncs[i].itype; delete [] pfuncs[i].itype;
delete [] pfuncs[i].ivarflag; 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_kokkos.h"
#include "accelerator_omp.h" #include "accelerator_omp.h"
#include "timer.h" #include "timer.h"
#include "python.h"
#include "memory.h" #include "memory.h"
#include "version.h" #include "version.h"
#include "error.h" #include "error.h"
@ -67,6 +68,7 @@ LAMMPS::LAMMPS(int narg, char **arg, MPI_Comm communicator)
error = new Error(this); error = new Error(this);
universe = new Universe(this,communicator); universe = new Universe(this,communicator);
output = NULL; output = NULL;
python = NULL;
screen = NULL; screen = NULL;
logfile = NULL; logfile = NULL;
@ -585,6 +587,7 @@ LAMMPS::~LAMMPS()
if (world != universe->uworld) MPI_Comm_free(&world); if (world != universe->uworld) MPI_Comm_free(&world);
delete python;
delete kokkos; delete kokkos;
delete [] suffix; delete [] suffix;
delete [] suffix2; delete [] suffix2;
@ -639,6 +642,8 @@ void LAMMPS::create()
// must be after modify so can create Computes // must be after modify so can create Computes
update = new Update(this); // must be after output, force, neighbor update = new Update(this); // must be after output, force, neighbor
timer = new Timer(this); timer = new Timer(this);
python = new Python(this);
} }
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
@ -759,6 +764,9 @@ void LAMMPS::destroy()
delete timer; delete timer;
timer = NULL; timer = NULL;
delete python;
python = NULL;
} }
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------

View File

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

View File

@ -56,7 +56,8 @@ class Pointers {
infile(ptr->infile), infile(ptr->infile),
screen(ptr->screen), screen(ptr->screen),
logfile(ptr->logfile), logfile(ptr->logfile),
atomKK(ptr->atomKK) {} atomKK(ptr->atomKK),
python(ptr->python) {}
virtual ~Pointers() {} virtual ~Pointers() {}
protected: protected:
@ -83,6 +84,7 @@ class Pointers {
FILE *&logfile; FILE *&logfile;
class AtomKokkos *&atomKK; 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
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)
{
if(!impl) init();
impl->command(narg, arg);
}
/* ------------------------------------------------------------------ */
void Python::invoke_function(int ifunc, char *result)
{
if(!impl) init();
impl->invoke_function(ifunc, result);
}
/* ------------------------------------------------------------------ */
int Python::find(char *name)
{
if(!impl) init();
return impl->find(name);
}
/* ------------------------------------------------------------------ */
int Python::variable_match(char *name, char *varname, int numeric)
{
if(!impl) init();
return impl->variable_match(name, varname, numeric);
}
/* ------------------------------------------------------------------ */
char * Python::long_string(int ifunc)
{
if(!impl) init();
return impl->long_string(ifunc);
}

View File

@ -18,50 +18,42 @@
namespace LAMMPS_NS { namespace LAMMPS_NS {
class Python : protected Pointers { class PythonInterface {
public: public:
int python_exists; virtual ~PythonInterface();
bool external_interpreter; 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(class LAMMPS *);
~Python(); ~Python();
void command(int, char **); void command(int, char **);
void invoke_function(int, char *); void invoke_function(int, char *);
int find(char *); int find(char *);
int variable_match(char *, char *, int); int variable_match(char *, char *, int);
char *long_string(int); char * long_string(int ifunc);
private: bool is_enabled() const;
int ninput,noutput,length_longstr;
char **istr;
char *ostr,*format;
void *pyMain;
struct PyFunc { private:
char *name; PythonInterface * impl;
int ninput,noutput; void init();
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 #endif
#if LMP_PYTHON
#include "python_impl.h"
#endif
/* ERROR/WARNING messages: /* ERROR/WARNING messages:
E: Invalid python command E: Invalid python command

View File

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

View File

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