From 2d8bce78a6462e6c1a93496dab29eac66a610e22 Mon Sep 17 00:00:00 2001 From: Richard Berger Date: Tue, 11 Apr 2017 21:22:30 -0400 Subject: [PATCH] Refactor PYTHON package and wrapper classes --- src/.gitignore | 4 +- src/PYTHON/Install.sh | 8 +- src/PYTHON/{python.cpp => python_impl.cpp} | 20 ++-- src/PYTHON/python_impl.h | 130 +++++++++++++++++++++ src/lammps.cpp | 8 ++ src/lammps.h | 2 + src/pointers.h | 4 +- src/python.cpp | 99 ++++++++++++++++ src/{PYTHON => }/python.h | 50 ++++---- src/variable.cpp | 11 +- src/variable.h | 2 - 11 files changed, 280 insertions(+), 58 deletions(-) rename src/PYTHON/{python.cpp => python_impl.cpp} (97%) create mode 100644 src/PYTHON/python_impl.h create mode 100644 src/python.cpp rename src/{PYTHON => }/python.h (84%) diff --git a/src/.gitignore b/src/.gitignore index 97bc2276b0..bb6f0a392e 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -846,8 +846,8 @@ /pppm_tip4p_cg.h /prd.cpp /prd.h -/python.cpp -/python.h +/python_impl.cpp +/python_impl.h /reader_molfile.cpp /reader_molfile.h /reaxc_allocate.cpp diff --git a/src/PYTHON/Install.sh b/src/PYTHON/Install.sh index 71288cf377..50ca3dffc4 100755 --- a/src/PYTHON/Install.sh +++ b/src/PYTHON/Install.sh @@ -26,16 +26,14 @@ action () { fi } -# force rebuild of files with LMP_KOKKOS switch -# also variable so its *.d dependence on changed python_wrapper.h is rebuilt +# force rebuild of files using python header -touch ../python_wrapper.h -touch ../variable.cpp +touch ../python.h # all package files with no dependencies for file in *.cpp *.h; do - test -f ${file} && action $file + action $file done # edit 2 Makefile.package files to include/exclude package info diff --git a/src/PYTHON/python.cpp b/src/PYTHON/python_impl.cpp similarity index 97% rename from src/PYTHON/python.cpp rename to src/PYTHON/python_impl.cpp index c465086f63..d9abb75f13 100644 --- a/src/PYTHON/python.cpp +++ b/src/PYTHON/python_impl.cpp @@ -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; // pfuncs stores interface info for each Python function @@ -59,7 +57,7 @@ Python::Python(LAMMPS *lmp) : Pointers(lmp) /* ---------------------------------------------------------------------- */ -Python::~Python() +PythonImpl::~PythonImpl() { // clean up 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"); @@ -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(); 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++) 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); 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; } /* ------------------------------------------------------------------ */ -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 // 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].ivarflag; diff --git a/src/PYTHON/python_impl.h b/src/PYTHON/python_impl.h new file mode 100644 index 0000000000..07975b3fdf --- /dev/null +++ b/src/PYTHON/python_impl.h @@ -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. + +*/ diff --git a/src/lammps.cpp b/src/lammps.cpp index cc3133f2d9..bde7ca035d 100644 --- a/src/lammps.cpp +++ b/src/lammps.cpp @@ -45,6 +45,7 @@ #include "accelerator_kokkos.h" #include "accelerator_omp.h" #include "timer.h" +#include "python.h" #include "memory.h" #include "version.h" #include "error.h" @@ -67,6 +68,7 @@ LAMMPS::LAMMPS(int narg, char **arg, MPI_Comm communicator) error = new Error(this); universe = new Universe(this,communicator); output = NULL; + python = NULL; screen = NULL; logfile = NULL; @@ -585,6 +587,7 @@ LAMMPS::~LAMMPS() if (world != universe->uworld) MPI_Comm_free(&world); + delete python; delete kokkos; delete [] suffix; delete [] suffix2; @@ -639,6 +642,8 @@ void LAMMPS::create() // must be after modify so can create Computes update = new Update(this); // must be after output, force, neighbor timer = new Timer(this); + + python = new Python(this); } /* ---------------------------------------------------------------------- @@ -759,6 +764,9 @@ void LAMMPS::destroy() delete timer; timer = NULL; + + delete python; + python = NULL; } /* ---------------------------------------------------------------------- diff --git a/src/lammps.h b/src/lammps.h index 02490a1836..c432784a0b 100644 --- a/src/lammps.h +++ b/src/lammps.h @@ -54,6 +54,8 @@ class LAMMPS { class KokkosLMP *kokkos; // KOKKOS accelerator class class AtomKokkos *atomKK; // KOKKOS version of Atom class + class Python * python; // Python interface + class CiteMe *citeme; // citation info LAMMPS(int, char **, MPI_Comm); diff --git a/src/pointers.h b/src/pointers.h index dd528c3a74..82b49c1dad 100644 --- a/src/pointers.h +++ b/src/pointers.h @@ -56,7 +56,8 @@ class Pointers { infile(ptr->infile), screen(ptr->screen), logfile(ptr->logfile), - atomKK(ptr->atomKK) {} + atomKK(ptr->atomKK), + python(ptr->python) {} virtual ~Pointers() {} protected: @@ -83,6 +84,7 @@ class Pointers { FILE *&logfile; class AtomKokkos *&atomKK; + class Python *&python; }; } diff --git a/src/python.cpp b/src/python.cpp new file mode 100644 index 0000000000..da3a874315 --- /dev/null +++ b/src/python.cpp @@ -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); +} diff --git a/src/PYTHON/python.h b/src/python.h similarity index 84% rename from src/PYTHON/python.h rename to src/python.h index 78889b994f..0b504f8944 100644 --- a/src/PYTHON/python.h +++ b/src/python.h @@ -18,50 +18,42 @@ namespace LAMMPS_NS { -class Python : protected Pointers { - public: - int python_exists; - bool external_interpreter; +class PythonInterface { +public: + virtual ~PythonInterface(); + 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(); + void command(int, char **); void invoke_function(int, char *); int find(char *); int variable_match(char *, char *, int); - char *long_string(int); + char * long_string(int ifunc); - private: - int ninput,noutput,length_longstr; - char **istr; - char *ostr,*format; - void *pyMain; + bool is_enabled() const; - 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); +private: + PythonInterface * impl; + void init(); }; } #endif +#if LMP_PYTHON +#include "python_impl.h" +#endif + /* ERROR/WARNING messages: E: Invalid python command diff --git a/src/variable.cpp b/src/variable.cpp index 3eea50a463..6e16597c63 100644 --- a/src/variable.cpp +++ b/src/variable.cpp @@ -34,7 +34,7 @@ #include "random_mars.h" #include "math_const.h" #include "atom_masks.h" -#include "python_wrapper.h" +#include "python.h" #include "memory.h" #include "info.h" #include "error.h" @@ -111,10 +111,6 @@ Variable::Variable(LAMMPS *lmp) : Pointers(lmp) precedence[MULTIPLY] = precedence[DIVIDE] = precedence[MODULO] = 6; precedence[CARAT] = 7; precedence[UNARY] = precedence[NOT] = 8; - - // Python wrapper, real or dummy - - python = new Python(lmp); } /* ---------------------------------------------------------------------- */ @@ -144,7 +140,6 @@ Variable::~Variable() delete randomequal; delete randomatom; - delete python; } /* ---------------------------------------------------------------------- @@ -464,7 +459,7 @@ void Variable::set(int narg, char **arg) } else if (strcmp(arg[1],"python") == 0) { 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"); int ivar = find(arg[0]); if (ivar >= 0) { @@ -735,7 +730,7 @@ void Variable::set_arrays(int i) 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"); python->command(narg,arg); } diff --git a/src/variable.h b/src/variable.h index 76607e96b4..886dd7b422 100644 --- a/src/variable.h +++ b/src/variable.h @@ -78,8 +78,6 @@ class Variable : protected Pointers { int precedence[18]; // precedence level of math operators // 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 double value; // single scalar double *array; // per-atom or per-type list of doubles