git-svn-id: svn://svn.icms.temple.edu/lammps-ro/trunk@14696 f3b2605a-c512-4ea7-a41b-209d697bcdaa

This commit is contained in:
sjplimp
2016-03-01 18:22:28 +00:00
parent 23ab6d4c0c
commit d1a65e5f6a
9 changed files with 639 additions and 88 deletions

View File

@ -52,7 +52,7 @@ using namespace MathConst;
#define MYROUND(a) (( a-floor(a) ) >= .5) ? ceil(a) : floor(a)
enum{INDEX,LOOP,WORLD,UNIVERSE,ULOOP,STRING,GETENV,
SCALARFILE,ATOMFILE,FORMAT,EQUAL,ATOM,PYTHON};
SCALARFILE,ATOMFILE,FORMAT,EQUAL,ATOM,VECTOR,PYTHON};
enum{ARG,OP};
// customize by adding a function
@ -65,7 +65,7 @@ enum{DONE,ADD,SUBTRACT,MULTIPLY,DIVIDE,CARAT,MODULO,UNARY,
RANDOM,NORMAL,CEIL,FLOOR,ROUND,RAMP,STAGGER,LOGFREQ,LOGFREQ2,
STRIDE,STRIDE2,VDISPLACE,SWIGGLE,CWIGGLE,GMASK,RMASK,GRMASK,
IS_ACTIVE,IS_DEFINED,IS_AVAILABLE,
VALUE,ATOMARRAY,TYPEARRAY,INTARRAY,BIGINTARRAY};
VALUE,ATOMARRAY,TYPEARRAY,INTARRAY,BIGINTARRAY,VECTORARRAY};
// customize by adding a special function
@ -92,6 +92,7 @@ Variable::Variable(LAMMPS *lmp) : Pointers(lmp)
pad = NULL;
reader = NULL;
data = NULL;
vecs = NULL;
eval_in_progress = NULL;
@ -125,6 +126,7 @@ Variable::~Variable()
if (style[i] == LOOP || style[i] == ULOOP) delete [] data[i][0];
else for (int j = 0; j < num[i]; j++) delete [] data[i][j];
delete [] data[i];
if (style[i] == VECTOR) memory->destroy(vecs[i].values);
}
memory->sfree(names);
memory->destroy(style);
@ -133,6 +135,7 @@ Variable::~Variable()
memory->destroy(pad);
memory->sfree(reader);
memory->sfree(data);
memory->sfree(vecs);
memory->destroy(eval_in_progress);
@ -428,6 +431,30 @@ void Variable::set(int narg, char **arg)
copy(1,&arg[2],data[nvar]);
}
// VECTOR
// replace pre-existing var if also style VECTOR (allows it to be reset)
// num = 1, which = 1st value
// data = 1 value, string to eval
} else if (strcmp(arg[1],"vector") == 0) {
if (narg != 3) error->all(FLERR,"Illegal variable command");
int ivar = find(arg[0]);
if (ivar >= 0) {
if (style[ivar] != VECTOR)
error->all(FLERR,"Cannot redefine variable as a different style");
delete [] data[ivar][0];
copy(1,&arg[2],data[ivar]);
replaceflag = 1;
} else {
if (nvar == maxvar) grow();
style[nvar] = VECTOR;
num[nvar] = 1;
which[nvar] = 0;
pad[nvar] = 0;
data[nvar] = new char*[num[nvar]];
copy(1,&arg[2],data[nvar]);
}
// PYTHON
// replace pre-existing var if also style PYTHON (allows it to be reset)
// num = 2, which = 1st value
@ -530,12 +557,12 @@ int Variable::next(int narg, char **arg)
error->all(FLERR,"All variables in next command must be same style");
}
// invalid styles: STRING, EQUAL, WORLD, ATOM, GETENV, FORMAT, PYTHON
// invalid styles: STRING, EQUAL, WORLD, ATOM, VECTOR, GETENV, FORMAT, PYTHON
int istyle = style[find(arg[0])];
if (istyle == STRING || istyle == EQUAL || istyle == WORLD ||
istyle == GETENV || istyle == ATOM || istyle == FORMAT ||
istyle == PYTHON)
istyle == GETENV || istyle == ATOM || istyle == VECTOR ||
istyle == FORMAT || istyle == PYTHON)
error->all(FLERR,"Invalid variable style with next command");
// if istyle = UNIVERSE or ULOOP, insure all such variables are incremented
@ -712,6 +739,17 @@ int Variable::atomstyle(int ivar)
return 0;
}
/* ----------------------------------------------------------------------
return 1 if variable is VECTOR style, 0 if not
this is checked before call to compute_vector() to return a vector of doubles
------------------------------------------------------------------------- */
int Variable::vectorstyle(int ivar)
{
if (style[ivar] == VECTOR) return 1;
return 0;
}
/* ----------------------------------------------------------------------
check if variable with name is PYTHON and matches funcname
called by Python class before it invokes a Python function
@ -737,7 +775,7 @@ char *Variable::pythonstyle(char *name, char *funcname)
if FORMAT, evaluate its variable and put formatted result in str
if GETENV, query environment and put result in str
if PYTHON, evaluate Python function, it will put result in str
if ATOM or ATOMFILE, return NULL
if ATOM or ATOMFILE or VECTOR, return NULL
return NULL if no variable with name, or which value is bad,
caller must respond
------------------------------------------------------------------------- */
@ -797,8 +835,9 @@ 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];
} else if (style[ivar] == ATOM || style[ivar] == ATOMFILE) return NULL;
} else if (style[ivar] == ATOM || style[ivar] == ATOMFILE ||
style[ivar] == VECTOR) return NULL;
eval_in_progress[ivar] = 0;
return str;
@ -859,6 +898,7 @@ void Variable::compute_atom(int ivar, int igroup,
eval_in_progress[ivar] = 1;
if (style[ivar] == ATOM) {
treetype = ATOM;
evaluate(data[ivar][0],&tree);
collapse_tree(tree);
} else vstore = reader[ivar]->fixstore->vstore;
@ -908,10 +948,58 @@ void Variable::compute_atom(int ivar, int igroup,
}
if (style[ivar] == ATOM) free_tree(tree);
eval_in_progress[ivar] = 0;
}
/* ----------------------------------------------------------------------
compute result of vector-style variable evaluation
return length of vector and result pointer to vector values
if length == 0 or -1 (mismatch), generate an error
if variable already computed on this timestep, just return
else evaulate the formula and its length, store results in VecVar entry
------------------------------------------------------------------------- */
int Variable::compute_vector(int ivar, double **result)
{
Tree *tree;
if (vecs[ivar].currentstep == update->ntimestep) {
*result = vecs[ivar].values;
return vecs[ivar].n;
}
if (eval_in_progress[ivar])
error->all(FLERR,"Variable has circular dependency");
eval_in_progress[ivar] = 1;
treetype = VECTOR;
evaluate(data[ivar][0],&tree);
collapse_tree(tree);
int nlen = size_tree_vector(tree);
if (nlen == 0) error->all(FLERR,"Vector-style variable has zero length");
if (nlen < 0) error->all(FLERR,
"Inconsistent lengths in vector-style variable");
// (re)allocate space for results if necessary
if (nlen > vecs[ivar].nmax) {
memory->destroy(vecs[ivar].values);
vecs[ivar].nmax = nlen;
memory->create(vecs[ivar].values,vecs[ivar].nmax,"variable:values");
}
vecs[ivar].n = nlen;
vecs[ivar].currentstep = update->ntimestep;
double *vec = vecs[ivar].values;
for (int i = 0; i < nlen; i++)
vec[i] = eval_tree(tree,i);
free_tree(tree);
eval_in_progress[ivar] = 0;
*result = vec;
return nlen;
}
/* ----------------------------------------------------------------------
save copy of EQUAL style ivar formula in copy
allocate copy here, later equal_restore() call will free it
@ -997,6 +1085,13 @@ void Variable::grow()
data = (char ***) memory->srealloc(data,maxvar*sizeof(char **),"var:data");
vecs = (VecVar *) memory->srealloc(vecs,maxvar*sizeof(VecVar),"var:vecvar");
for (int i = old; i < maxvar; i++) {
vecs[i].nmax = 0;
vecs[i].currentstep = -1;
vecs[i].values = NULL;
}
memory->grow(eval_in_progress,maxvar,"var:eval_in_progress");
for (int i = 0; i < maxvar; i++) eval_in_progress[i] = 0;
}
@ -1017,7 +1112,8 @@ void Variable::copy(int narg, char **from, char **to)
/* ----------------------------------------------------------------------
recursive evaluation of a string str
str is an equal-style or atom-style formula containing one or more items:
str is an equal-style or atom-style or vector-style formula
containing one or more items:
number = 0.0, -5.45, 2.8e-4, ...
constant = PI, version, yes, no, on, off
thermo keyword = ke, vol, atoms, ...
@ -1034,7 +1130,7 @@ void Variable::copy(int narg, char **from, char **to)
variable = v_name, v_name[i]
equal-style variables passes in tree = NULL:
evaluate the formula, return result as a double
atom-style variable passes in tree = non-NULL:
atom-style and vector-style variables pass in tree = non-NULL:
parse the formula but do not evaluate it
create a parse tree and return it
------------------------------------------------------------------------- */
@ -1145,11 +1241,17 @@ double Variable::evaluate(char *str, Tree **tree)
// compute
// ----------------
if (strncmp(word,"c_",2) == 0) {
if (strncmp(word,"c_",2) == 0 || strncmp(word,"C_",2) == 0) {
if (domain->box_exist == 0)
error->all(FLERR,
"Variable evaluation before simulation box is defined");
// uppercase used to force access of
// global vector vs global scalar, and global array vs global vector
int lowercase = 1;
if (word[0] == 'C') lowercase = 0;
int icompute = modify->find_compute(word+2);
if (icompute < 0)
error->all(FLERR,"Invalid compute ID in variable formula");
@ -1176,9 +1278,9 @@ double Variable::evaluate(char *str, Tree **tree)
}
}
// c_ID = scalar from global scalar
// c_ID = scalar from global scalar, must be lowercase
if (nbracket == 0 && compute->scalar_flag) {
if (nbracket == 0 && compute->scalar_flag && lowercase) {
if (update->whichflag == 0) {
if (compute->invoked_scalar != update->ntimestep)
@ -1199,9 +1301,9 @@ double Variable::evaluate(char *str, Tree **tree)
treestack[ntreestack++] = newtree;
} else argstack[nargstack++] = value1;
// c_ID[i] = scalar from global vector
// c_ID[i] = scalar from global vector, must be lowercase
} else if (nbracket == 1 && compute->vector_flag) {
} else if (nbracket == 1 && compute->vector_flag && lowercase) {
if (index1 > compute->size_vector &&
compute->size_vector_variable == 0)
@ -1228,9 +1330,9 @@ double Variable::evaluate(char *str, Tree **tree)
treestack[ntreestack++] = newtree;
} else argstack[nargstack++] = value1;
// c_ID[i][j] = scalar from global array
// c_ID[i][j] = scalar from global array, must be lowercase
} else if (nbracket == 2 && compute->array_flag) {
} else if (nbracket == 2 && compute->array_flag && lowercase) {
if (index1 > compute->size_array_rows &&
compute->size_array_rows_variable == 0)
@ -1260,6 +1362,68 @@ double Variable::evaluate(char *str, Tree **tree)
treestack[ntreestack++] = newtree;
} else argstack[nargstack++] = value1;
// c_ID = vector from global vector, lowercase or uppercase
} else if (nbracket == 0 && compute->vector_flag) {
if (tree == NULL)
error->all(FLERR,
"Compute global vector in equal-style variable formula");
if (treetype == ATOM)
error->all(FLERR,
"Compute global vector in atom-style variable formula");
if (compute->size_vector == 0)
error->all(FLERR,"Variable formula compute vector is zero length");
if (update->whichflag == 0) {
if (compute->invoked_vector != update->ntimestep)
error->all(FLERR,"Compute used in variable between runs "
"is not current");
} else if (!(compute->invoked_flag & INVOKED_VECTOR)) {
compute->compute_vector();
compute->invoked_flag |= INVOKED_VECTOR;
}
Tree *newtree = new Tree();
newtree->type = VECTORARRAY;
newtree->array = compute->vector;
newtree->nvector = compute->size_vector;
newtree->nstride = 1;
newtree->selfalloc = 0;
newtree->first = newtree->second = NULL;
newtree->nextra = 0;
treestack[ntreestack++] = newtree;
// c_ID[i] = vector from global array, lowercase or uppercase
} else if (nbracket == 1 && compute->array_flag) {
if (tree == NULL)
error->all(FLERR,
"Compute global vector in equal-style variable formula");
if (treetype == ATOM)
error->all(FLERR,
"Compute global vector in atom-style variable formula");
if (compute->size_array_rows == 0)
error->all(FLERR,"Variable formula compute array is zero length");
if (update->whichflag == 0) {
if (compute->invoked_array != update->ntimestep)
error->all(FLERR,"Compute used in variable between runs "
"is not current");
} else if (!(compute->invoked_flag & INVOKED_ARRAY)) {
compute->compute_array();
compute->invoked_flag |= INVOKED_ARRAY;
}
Tree *newtree = new Tree();
newtree->type = VECTORARRAY;
newtree->array = &compute->array[0][index1-1];
newtree->nvector = compute->size_array_rows;
newtree->nstride = compute->size_array_cols;
newtree->selfalloc = 0;
newtree->first = newtree->second = NULL;
newtree->nextra = 0;
treestack[ntreestack++] = newtree;
// c_ID[i] = scalar from per-atom vector
} else if (nbracket == 1 && compute->peratom_flag &&
@ -1311,6 +1475,9 @@ double Variable::evaluate(char *str, Tree **tree)
if (tree == NULL)
error->all(FLERR,
"Per-atom compute in equal-style variable formula");
if (treetype == VECTOR)
error->all(FLERR,
"Per-atom compute in vector-style variable formula");
if (update->whichflag == 0) {
if (compute->invoked_peratom != update->ntimestep)
error->all(FLERR,"Compute used in variable between runs "
@ -1337,6 +1504,9 @@ double Variable::evaluate(char *str, Tree **tree)
if (tree == NULL)
error->all(FLERR,
"Per-atom compute in equal-style variable formula");
if (treetype == VECTOR)
error->all(FLERR,
"Per-atom compute in vector-style variable formula");
if (index1 > compute->size_peratom_cols)
error->all(FLERR,"Variable formula compute array "
"is accessed out-of-range");
@ -1367,11 +1537,17 @@ double Variable::evaluate(char *str, Tree **tree)
// fix
// ----------------
} else if (strncmp(word,"f_",2) == 0) {
} else if (strncmp(word,"f_",2) == 0 || strncmp(word,"F_",2) == 0) {
if (domain->box_exist == 0)
error->all(FLERR,
"Variable evaluation before simulation box is defined");
// uppercase used to force access of
// global vector vs global scalar, and global array vs global vector
int lowercase = 1;
if (word[0] == 'F') lowercase = 0;
int ifix = modify->find_fix(word+2);
if (ifix < 0) error->all(FLERR,"Invalid fix ID in variable formula");
Fix *fix = modify->fix[ifix];
@ -1397,9 +1573,9 @@ double Variable::evaluate(char *str, Tree **tree)
}
}
// f_ID = scalar from global scalar
// f_ID = scalar from global scalar, must be lowercase
if (nbracket == 0 && fix->scalar_flag) {
if (nbracket == 0 && fix->scalar_flag && lowercase) {
if (update->whichflag > 0 && update->ntimestep % fix->global_freq)
error->all(FLERR,"Fix in variable not computed at compatible time");
@ -1414,9 +1590,9 @@ double Variable::evaluate(char *str, Tree **tree)
treestack[ntreestack++] = newtree;
} else argstack[nargstack++] = value1;
// f_ID[i] = scalar from global vector
// f_ID[i] = scalar from global vector, must be lowercase
} else if (nbracket == 1 && fix->vector_flag) {
} else if (nbracket == 1 && fix->vector_flag && lowercase) {
if (index1 > fix->size_vector &&
fix->size_vector_variable == 0)
@ -1435,9 +1611,9 @@ double Variable::evaluate(char *str, Tree **tree)
treestack[ntreestack++] = newtree;
} else argstack[nargstack++] = value1;
// f_ID[i][j] = scalar from global array
// f_ID[i][j] = scalar from global array, must be lowercase
} else if (nbracket == 2 && fix->array_flag) {
} else if (nbracket == 2 && fix->array_flag && lowercase) {
if (index1 > fix->size_array_rows &&
fix->size_array_rows_variable == 0)
@ -1459,6 +1635,68 @@ double Variable::evaluate(char *str, Tree **tree)
treestack[ntreestack++] = newtree;
} else argstack[nargstack++] = value1;
// f_ID = vector from global vector, lowercase or uppercase
} else if (nbracket == 0 && fix->vector_flag) {
if (update->whichflag > 0 && update->ntimestep % fix->global_freq)
error->all(FLERR,"Fix in variable not computed at compatible time");
if (tree == NULL)
error->all(FLERR,"Fix global vector in "
"equal-style variable formula");
if (treetype == ATOM)
error->all(FLERR,"Fix global vector in "
"atom-style variable formula");
if (fix->size_vector == 0)
error->all(FLERR,"Variable formula fix vector is zero length");
int nvec = fix->size_vector;
double *vec;
memory->create(vec,nvec,"variable:values");
for (int m = 0; m < nvec; m++)
vec[m] = fix->compute_vector(m);
Tree *newtree = new Tree();
newtree->type = VECTORARRAY;
newtree->array = vec;
newtree->nvector = nvec;
newtree->nstride = 1;
newtree->selfalloc = 1;
newtree->first = newtree->second = NULL;
newtree->nextra = 0;
treestack[ntreestack++] = newtree;
// f_ID[i] = vector from global array, lowercase or uppercase
} else if (nbracket == 1 && fix->array_flag) {
if (update->whichflag > 0 && update->ntimestep % fix->global_freq)
error->all(FLERR,"Fix in variable not computed at compatible time");
if (tree == NULL)
error->all(FLERR,"Fix global vector in "
"equal-style variable formula");
if (treetype == ATOM)
error->all(FLERR,"Fix global vector in "
"atom-style variable formula");
if (fix->size_array_rows == 0)
error->all(FLERR,"Variable formula fix array is zero length");
int nvec = fix->size_array_rows;
double *vec;
memory->create(vec,nvec,"variable:values");
for (int m = 0; m < nvec; m++)
vec[m] = fix->compute_array(m,index1-1);
Tree *newtree = new Tree();
newtree->type = VECTORARRAY;
newtree->array = vec;
newtree->nvector = nvec;
newtree->nstride = 1;
newtree->selfalloc = 1;
newtree->first = newtree->second = NULL;
newtree->nextra = 0;
treestack[ntreestack++] = newtree;
// f_ID[i] = scalar from per-atom vector
} else if (nbracket == 1 && fix->peratom_flag &&
@ -1568,9 +1806,10 @@ double Variable::evaluate(char *str, Tree **tree)
i = ptr-str+1;
}
// v_name = scalar from non atom/atomfile variable
// v_name = scalar from non atom/atomfile and non vector-style variable
if (nbracket == 0 && style[ivar] != ATOM && style[ivar] != ATOMFILE) {
if (nbracket == 0 && style[ivar] != ATOM && style[ivar] != ATOMFILE &&
style[ivar] != VECTOR) {
char *var = retrieve(word+2);
if (var == NULL)
@ -1592,6 +1831,10 @@ double Variable::evaluate(char *str, Tree **tree)
if (tree == NULL)
error->all(FLERR,
"Atom-style variable in equal-style variable formula");
if (treetype == VECTOR)
error->all(FLERR,
"Atom-style variable in vector-style variable formula");
Tree *newtree;
evaluate(data[ivar][0],&newtree);
treestack[ntreestack++] = newtree;
@ -1603,6 +1846,10 @@ double Variable::evaluate(char *str, Tree **tree)
if (tree == NULL)
error->all(FLERR,"Atomfile-style variable in "
"equal-style variable formula");
if (treetype == VECTOR)
error->all(FLERR,
"Atomfile-style variable in vector-style variable formula");
Tree *newtree = new Tree();
newtree->type = ATOMARRAY;
newtree->array = reader[ivar]->fixstore->vstore;
@ -1612,6 +1859,31 @@ double Variable::evaluate(char *str, Tree **tree)
newtree->nextra = 0;
treestack[ntreestack++] = newtree;
// v_name = vector from vector-style variable
// evaluate the vector-style variable, put result in newtree
} else if (nbracket == 0 && style[ivar] == VECTOR) {
if (tree == NULL)
error->all(FLERR,
"Vector-style variable in equal-style variable formula");
if (treetype == ATOM)
error->all(FLERR,
"Vector-style variable in atom-style variable formula");
double *vec;
int nvec = compute_vector(ivar,&vec);
Tree *newtree = new Tree();
newtree->type = VECTORARRAY;
newtree->array = vec;
newtree->nvector = nvec;
newtree->nstride = 1;
newtree->selfalloc = 0;
newtree->first = newtree->second = NULL;
newtree->nextra = 0;
treestack[ntreestack++] = newtree;
// v_name[N] = scalar from atom-style variable
// compute the per-atom variable in result
// use peratom2global to extract single value from result
@ -1632,6 +1904,26 @@ double Variable::evaluate(char *str, Tree **tree)
peratom2global(1,NULL,reader[ivar]->fixstore->vstore,1,index,
tree,treestack,ntreestack,argstack,nargstack);
// v_name[N] = scalar from vector-style variable
// compute the vector-style variable, extract single value
} else if (nbracket && style[ivar] == VECTOR) {
double *vec;
int nvec = compute_vector(ivar,&vec);
if (index <= 0 || index > nvec)
error->all(FLERR,"Invalid index into vector-style variable");
int m = index; // convert from tagint to int
if (tree) {
Tree *newtree = new Tree();
newtree->type = VALUE;
newtree->value = vec[m-1];
newtree->first = newtree->second = NULL;
newtree->nextra = 0;
treestack[ntreestack++] = newtree;
} else argstack[nargstack++] = vec[m-1];
} else error->all(FLERR,"Mismatched variable in variable formula");
// ----------------
@ -1892,7 +2184,7 @@ double Variable::evaluate(char *str, Tree **tree)
one-time collapse of an atom-style variable parse tree
tree was created by one-time parsing of formula string via evaluate()
only keep tree nodes that depend on
ATOMARRAY, TYPEARRAY, INTARRAY, BIGINTARRAY
ATOMARRAY, TYPEARRAY, INTARRAY, BIGINTARRAY, VECTOR
remainder is converted to single VALUE
this enables optimal eval_tree loop over atoms
customize by adding a function:
@ -1912,6 +2204,7 @@ double Variable::collapse_tree(Tree *tree)
if (tree->type == TYPEARRAY) return 0.0;
if (tree->type == INTARRAY) return 0.0;
if (tree->type == BIGINTARRAY) return 0.0;
if (tree->type == VECTORARRAY) return 0.0;
if (tree->type == ADD) {
arg1 = collapse_tree(tree->first);
@ -2403,7 +2696,8 @@ double Variable::collapse_tree(Tree *tree)
}
/* ----------------------------------------------------------------------
evaluate an atom-style variable parse tree for atom I
evaluate an atom-style or vector-style variable parse tree
index I = atom I or vector index I
tree was created by one-time parsing of formula string via evaulate()
customize by adding a function:
sqrt(),exp(),ln(),log(),sin(),cos(),tan(),asin(),acos(),atan(),
@ -2422,6 +2716,7 @@ double Variable::eval_tree(Tree *tree, int i)
if (tree->type == TYPEARRAY) return tree->array[atom->type[i]];
if (tree->type == INTARRAY) return (double) tree->iarray[i*tree->nstride];
if (tree->type == BIGINTARRAY) return (double) tree->barray[i*tree->nstride];
if (tree->type == VECTORARRAY) return tree->array[i*tree->nstride];
if (tree->type == ADD)
return eval_tree(tree->first,i) + eval_tree(tree->second,i);
@ -2728,6 +3023,40 @@ double Variable::eval_tree(Tree *tree, int i)
return 0.0;
}
/* ----------------------------------------------------------------------
scan entire tree, find size of vectors for vector-style variable
return N for consistent vector size
return 0 for no vector size, caller flags as error
return -1 for inconsistent vector size, caller flags as error
------------------------------------------------------------------------- */
int Variable::size_tree_vector(Tree *tree)
{
int nsize = 0;
if (tree->type == VECTORARRAY) nsize = tree->nvector;
if (tree->first) nsize = compare_tree_vector(nsize,size_tree_vector(tree->first));
if (tree->second) nsize = compare_tree_vector(nsize,size_tree_vector(tree->second));
if (tree->nextra) {
for (int i = 0; i < tree->nextra; i++)
nsize = compare_tree_vector(nsize,size_tree_vector(tree->extra[i]));
}
return nsize;
}
/* ----------------------------------------------------------------------
compare size of two vectors for vector-style variable
return positive size if same or one has no size 0
return -1 error if one is already error or not same positive size
------------------------------------------------------------------------- */
int Variable::compare_tree_vector(int i, int j)
{
if (i < 0 || j < 0) return -1;
if (i == 0 || j == 0) return MAX(i,j);
if (i != j) return -1;
return i;
}
/* ---------------------------------------------------------------------- */
void Variable::free_tree(Tree *tree)
@ -2739,9 +3068,7 @@ void Variable::free_tree(Tree *tree)
delete [] tree->extra;
}
if (tree->type == ATOMARRAY && tree->selfalloc)
memory->destroy(tree->array);
if (tree->selfalloc) memory->destroy(tree->array);
delete tree;
}
@ -3532,9 +3859,12 @@ int Variable::special_function(char *word, char *contents, Tree **tree,
Compute *compute = NULL;
Fix *fix = NULL;
int ivar = -1;
int index,nvec,nstride;
char *ptr1,*ptr2;
// argument is compute
if (strstr(args[0],"c_") == args[0]) {
ptr1 = strchr(args[0],'[');
if (ptr1) {
@ -3574,6 +3904,8 @@ int Variable::special_function(char *word, char *contents, Tree **tree,
nstride = compute->size_array_cols;
} else error->all(FLERR,"Mismatched compute in variable formula");
// argument is fix
} else if (strstr(args[0],"f_") == args[0]) {
ptr1 = strchr(args[0],'[');
if (ptr1) {
@ -3600,6 +3932,28 @@ int Variable::special_function(char *word, char *contents, Tree **tree,
nstride = fix->size_array_cols;
} else error->all(FLERR,"Mismatched fix in variable formula");
// argument is vector-style variable
} else if (strstr(args[0],"v_") == args[0]) {
ptr1 = strchr(args[0],'[');
if (ptr1) {
ptr2 = ptr1;
index = (int) int_between_brackets(ptr2,0);
*ptr1 = '\0';
} else index = 0;
if (index)
error->all(FLERR,"Invalid special function in variable formula");
ivar = find(&args[0][2]);
if (ivar < 0) error->all(FLERR,"Invalid special function in variable formula");
if (style[ivar] != VECTOR)
error->all(FLERR,"Mis-matched special function variable in variable formula");
if (eval_in_progress[ivar]) error->all(FLERR,"Variable has circular dependency");
double *vec;
nvec = compute_vector(ivar,&vec);
nstride = 1;
} else error->all(FLERR,"Invalid special function in variable formula");
value = 0.0;
@ -3661,6 +4015,28 @@ int Variable::special_function(char *word, char *contents, Tree **tree,
}
}
if (ivar >= 0) {
double one;
double *vec = vecs[ivar].values;
for (int i = 0; i < nvec; i++) {
one = vec[i];
if (method == SUM) value += one;
else if (method == XMIN) value = MIN(value,one);
else if (method == XMAX) value = MAX(value,one);
else if (method == AVE) value += one;
else if (method == TRAP) value += one;
else if (method == SLOPE) {
if (nvec > 1) xvalue = (double) i / (nvec-1);
else xvalue = 0.0;
sx += xvalue;
sy += one;
sxx += xvalue*xvalue;
sxy += xvalue*one;
}
}
if (method == TRAP) value -= 0.5*vec[0] + 0.5*vec[nvec-1];
}
if (method == AVE) value /= nvec;
if (method == SLOPE) {