From e364b80724ae4258e0f3eedbf49236a69fbf0c25 Mon Sep 17 00:00:00 2001 From: Steve Plimpton <sjplimp@sandia.gov> Date: Fri, 16 Dec 2016 10:24:25 -0700 Subject: [PATCH] added length keyword to python command --- doc/src/python.txt | 15 ++++++++++++++- src/PYTHON/python.cpp | 28 +++++++++++++++++++++++++++- src/PYTHON/python.h | 5 ++++- src/USER-INTEL/fix_intel.cpp | 2 -- src/fix_shear_history.cpp | 2 +- src/variable.cpp | 4 ++++ 6 files changed, 50 insertions(+), 6 deletions(-) diff --git a/doc/src/python.txt b/doc/src/python.txt index 773992bddd..7da69a0319 100644 --- a/doc/src/python.txt +++ b/doc/src/python.txt @@ -14,7 +14,7 @@ python func keyword args ... :pre func = name of Python function :ulb,l one or more keyword/args pairs must be appended :l -keyword = {invoke} or {input} or {return} or {format} or {file} or {here} or {exists} +keyword = {invoke} or {input} or {return} or {format} or {length} or {file} or {here} or {exists} {invoke} arg = none = invoke the previously defined Python function {input} args = N i1 i2 ... iN N = # of inputs to function @@ -29,6 +29,8 @@ keyword = {invoke} or {input} or {return} or {format} or {file} or {here} or {ex M = N+1 if there is a return value fstring = each character (i,f,s,p) corresponds in order to an input or return value 'i' = integer, 'f' = floating point, 's' = string, 'p' = SELF + {length} arg = Nlen + Nlen = max length of string returned from Python function {file} arg = filename filename = file of Python code, which defines func {here} arg = inline @@ -165,6 +167,17 @@ equal-style variable as an argument, but only if the output of the Python function is flagged as a numeric value ("i" or "f") via the {format} keyword. +If the {return} keyword is used and the {format} keyword specifies the +output as a string, then the default maximum length of that string is +63 characters (64-1 for the string terminator). If you want to return +a longer string, the {length} keyword can be specified with its {Nlen} +value set to a larger number (the code allocates space for Nlen+1 to +include the string terminator). If the Python function generates a +string longer than the default 63 or the specified {Nlen}, it will be +trunctated. + +:line + Either the {file}, {here}, or {exists} keyword must be used, but only one of them. These keywords specify what Python code to load into the Python interpreter. The {file} keyword gives the name of a file, diff --git a/src/PYTHON/python.cpp b/src/PYTHON/python.cpp index c9947f3521..6c89be6922 100644 --- a/src/PYTHON/python.cpp +++ b/src/PYTHON/python.cpp @@ -89,6 +89,7 @@ void Python::command(int narg, char **arg) istr = NULL; ostr = NULL; format = NULL; + length_longstr = 0; char *pyfile = NULL; char *herestr = NULL; int existflag = 0; @@ -115,6 +116,11 @@ void Python::command(int narg, char **arg) format = new char[n]; strcpy(format,arg[iarg+1]); iarg += 2; + } else if (strcmp(arg[iarg],"length") == 0) { + if (iarg+2 > narg) error->all(FLERR,"Invalid python command"); + length_longstr = force->inumeric(FLERR,arg[iarg+1]); + if (length_longstr <= 0) error->all(FLERR,"Invalid python command"); + iarg += 2; } else if (strcmp(arg[iarg],"file") == 0) { if (iarg+2 > narg) error->all(FLERR,"Invalid python command"); delete[] pyfile; @@ -249,6 +255,7 @@ void Python::invoke_function(int ifunc, char *result) // function returned a value // assign it to result string stored by python-style variable + // or if user specified a length, assign it to longstr if (pfuncs[ifunc].noutput) { int otype = pfuncs[ifunc].otype; @@ -258,7 +265,9 @@ void Python::invoke_function(int ifunc, char *result) sprintf(result,"%.15g",PyFloat_AsDouble(pValue)); } else if (otype == STRING) { char *pystr = PyString_AsString(pValue); - strncpy(result,pystr,VALUELENGTH-1); + if (pfuncs[ifunc].longstr) + strncpy(pfuncs[ifunc].longstr,pystr,pfuncs[ifunc].length_longstr); + else strncpy(result,pystr,VALUELENGTH-1); } Py_DECREF(pValue); } @@ -287,6 +296,13 @@ int Python::variable_match(char *name, char *varname, int numeric) /* ------------------------------------------------------------------ */ +char *Python::long_string(int ifunc) +{ + return pfuncs[ifunc].longstr; +} + +/* ------------------------------------------------------------------ */ + int Python::create_entry(char *name) { // ifunc = index to entry by name in pfuncs vector, can be old or new @@ -370,6 +386,7 @@ int Python::create_entry(char *name) // process output as value or variable pfuncs[ifunc].ovarname = NULL; + pfuncs[ifunc].longstr = NULL; if (!noutput) return ifunc; char type = format[ninput]; @@ -378,6 +395,14 @@ int Python::create_entry(char *name) else if (type == 's') pfuncs[ifunc].otype = STRING; else error->all(FLERR,"Invalid python command"); + if (length_longstr) { + if (pfuncs[ifunc].otype != STRING) + error->all(FLERR,"Python command length keyword " + "cannot be used unless output is a string"); + pfuncs[ifunc].length_longstr = length_longstr; + pfuncs[ifunc].longstr = new char[length_longstr+1]; + } + if (strstr(ostr,"v_") != ostr) error->all(FLERR,"Invalid python command"); int n = strlen(&ostr[2]) + 1; pfuncs[ifunc].ovarname = new char[n]; @@ -398,4 +423,5 @@ void Python::deallocate(int i) delete [] pfuncs[i].svalue[j]; delete [] pfuncs[i].svalue; delete [] pfuncs[i].ovarname; + delete [] pfuncs[i].longstr; } diff --git a/src/PYTHON/python.h b/src/PYTHON/python.h index d1622728ac..61e5f015e2 100644 --- a/src/PYTHON/python.h +++ b/src/PYTHON/python.h @@ -28,9 +28,10 @@ class Python : protected Pointers { void invoke_function(int, char *); int find(char *); int variable_match(char *, char *, int); + char *long_string(int); private: - int ninput,noutput; + int ninput,noutput,length_longstr; char **istr; char *ostr,*format; void *pyMain; @@ -44,6 +45,8 @@ class Python : protected Pointers { char **svalue; int otype; char *ovarname; + char *longstr; + int length_longstr; void *pFunc; }; diff --git a/src/USER-INTEL/fix_intel.cpp b/src/USER-INTEL/fix_intel.cpp index 84f4994901..7c5dd0b34c 100644 --- a/src/USER-INTEL/fix_intel.cpp +++ b/src/USER-INTEL/fix_intel.cpp @@ -325,8 +325,6 @@ void FixIntel::init() error->all(FLERR, "Currently, cannot use more than one intel style with hybrid."); - neighbor->fix_intel = (void *)this; - check_neighbor_intel(); if (_precision_mode == PREC_MODE_SINGLE) _single_buffers->zero_ev(); diff --git a/src/fix_shear_history.cpp b/src/fix_shear_history.cpp index 42d088875b..379de9bcd3 100644 --- a/src/fix_shear_history.cpp +++ b/src/fix_shear_history.cpp @@ -526,7 +526,7 @@ double FixShearHistory::memory_usage() { int nmax = atom->nmax; double bytes = nmax * sizeof(int); - bytes += nmax * sizeof(int *); + bytes += nmax * sizeof(tagint *); bytes += nmax * sizeof(double *); int nmypage = comm->nthreads; diff --git a/src/variable.cpp b/src/variable.cpp index 2f985a7c8e..67c8951974 100644 --- a/src/variable.cpp +++ b/src/variable.cpp @@ -875,6 +875,10 @@ char *Variable::retrieve(char *name) error->all(FLERR,"Python variable does not match Python function"); python->invoke_function(ifunc,data[ivar][1]); str = data[ivar][1]; + // if Python func returns a string longer than VALUELENGTH + // then the Python class stores the result, query it via long_string() + char *strlong = python->long_string(ifunc); + if (strlong) str = strlong; } else if (style[ivar] == INTERNAL) { sprintf(data[ivar][0],"%.15g",dvalue[ivar]); str = data[ivar][0]; -- GitLab