added length keyword to python command

This commit is contained in:
Steve Plimpton 2016-12-16 10:24:25 -07:00
parent f509f133af
commit e364b80724
6 changed files with 50 additions and 6 deletions

View File

@ -14,7 +14,7 @@ python func keyword args ... :pre
func = name of Python function :ulb,l func = name of Python function :ulb,l
one or more keyword/args pairs must be appended :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 {invoke} arg = none = invoke the previously defined Python function
{input} args = N i1 i2 ... iN {input} args = N i1 i2 ... iN
N = # of inputs to function 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 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 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 'i' = integer, 'f' = floating point, 's' = string, 'p' = SELF
{length} arg = Nlen
Nlen = max length of string returned from Python function
{file} arg = filename {file} arg = filename
filename = file of Python code, which defines func filename = file of Python code, which defines func
{here} arg = inline {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 Python function is flagged as a numeric value ("i" or "f") via the
{format} keyword. {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 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 one of them. These keywords specify what Python code to load into the
Python interpreter. The {file} keyword gives the name of a file, Python interpreter. The {file} keyword gives the name of a file,

View File

@ -89,6 +89,7 @@ void Python::command(int narg, char **arg)
istr = NULL; istr = NULL;
ostr = NULL; ostr = NULL;
format = NULL; format = NULL;
length_longstr = 0;
char *pyfile = NULL; char *pyfile = NULL;
char *herestr = NULL; char *herestr = NULL;
int existflag = 0; int existflag = 0;
@ -115,6 +116,11 @@ void Python::command(int narg, char **arg)
format = new char[n]; format = new char[n];
strcpy(format,arg[iarg+1]); strcpy(format,arg[iarg+1]);
iarg += 2; 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) { } else if (strcmp(arg[iarg],"file") == 0) {
if (iarg+2 > narg) error->all(FLERR,"Invalid python command"); if (iarg+2 > narg) error->all(FLERR,"Invalid python command");
delete[] pyfile; delete[] pyfile;
@ -249,6 +255,7 @@ void Python::invoke_function(int ifunc, char *result)
// function returned a value // function returned a value
// assign it to result string stored by python-style variable // assign it to result string stored by python-style variable
// or if user specified a length, assign it to longstr
if (pfuncs[ifunc].noutput) { if (pfuncs[ifunc].noutput) {
int otype = pfuncs[ifunc].otype; int otype = pfuncs[ifunc].otype;
@ -258,7 +265,9 @@ void Python::invoke_function(int ifunc, char *result)
sprintf(result,"%.15g",PyFloat_AsDouble(pValue)); sprintf(result,"%.15g",PyFloat_AsDouble(pValue));
} else if (otype == STRING) { } else if (otype == STRING) {
char *pystr = PyString_AsString(pValue); 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); 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) int Python::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
@ -370,6 +386,7 @@ int Python::create_entry(char *name)
// process output as value or variable // process output as value or variable
pfuncs[ifunc].ovarname = NULL; pfuncs[ifunc].ovarname = NULL;
pfuncs[ifunc].longstr = NULL;
if (!noutput) return ifunc; if (!noutput) return ifunc;
char type = format[ninput]; char type = format[ninput];
@ -378,6 +395,14 @@ int Python::create_entry(char *name)
else if (type == 's') pfuncs[ifunc].otype = STRING; else if (type == 's') pfuncs[ifunc].otype = STRING;
else error->all(FLERR,"Invalid python command"); 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"); if (strstr(ostr,"v_") != ostr) error->all(FLERR,"Invalid python command");
int n = strlen(&ostr[2]) + 1; int n = strlen(&ostr[2]) + 1;
pfuncs[ifunc].ovarname = new char[n]; pfuncs[ifunc].ovarname = new char[n];
@ -398,4 +423,5 @@ void Python::deallocate(int i)
delete [] pfuncs[i].svalue[j]; delete [] pfuncs[i].svalue[j];
delete [] pfuncs[i].svalue; delete [] pfuncs[i].svalue;
delete [] pfuncs[i].ovarname; delete [] pfuncs[i].ovarname;
delete [] pfuncs[i].longstr;
} }

View File

@ -28,9 +28,10 @@ class Python : protected Pointers {
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);
private: private:
int ninput,noutput; int ninput,noutput,length_longstr;
char **istr; char **istr;
char *ostr,*format; char *ostr,*format;
void *pyMain; void *pyMain;
@ -44,6 +45,8 @@ class Python : protected Pointers {
char **svalue; char **svalue;
int otype; int otype;
char *ovarname; char *ovarname;
char *longstr;
int length_longstr;
void *pFunc; void *pFunc;
}; };

View File

@ -325,8 +325,6 @@ void FixIntel::init()
error->all(FLERR, error->all(FLERR,
"Currently, cannot use more than one intel style with hybrid."); "Currently, cannot use more than one intel style with hybrid.");
neighbor->fix_intel = (void *)this;
check_neighbor_intel(); check_neighbor_intel();
if (_precision_mode == PREC_MODE_SINGLE) if (_precision_mode == PREC_MODE_SINGLE)
_single_buffers->zero_ev(); _single_buffers->zero_ev();

View File

@ -526,7 +526,7 @@ double FixShearHistory::memory_usage()
{ {
int nmax = atom->nmax; int nmax = atom->nmax;
double bytes = nmax * sizeof(int); double bytes = nmax * sizeof(int);
bytes += nmax * sizeof(int *); bytes += nmax * sizeof(tagint *);
bytes += nmax * sizeof(double *); bytes += nmax * sizeof(double *);
int nmypage = comm->nthreads; int nmypage = comm->nthreads;

View File

@ -875,6 +875,10 @@ char *Variable::retrieve(char *name)
error->all(FLERR,"Python variable does not match Python function"); error->all(FLERR,"Python variable does not match Python function");
python->invoke_function(ifunc,data[ivar][1]); python->invoke_function(ifunc,data[ivar][1]);
str = 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) { } else if (style[ivar] == INTERNAL) {
sprintf(data[ivar][0],"%.15g",dvalue[ivar]); sprintf(data[ivar][0],"%.15g",dvalue[ivar]);
str = data[ivar][0]; str = data[ivar][0];