diff --git a/src/create_atoms.cpp b/src/create_atoms.cpp index 45d3c7f984..82315e7dc5 100644 --- a/src/create_atoms.cpp +++ b/src/create_atoms.cpp @@ -230,7 +230,6 @@ void CreateAtoms::command(int narg, char **arg) } // error check and further setup for variable test - // save local copy of each equal variable string so can restore at end if (!vstr && (xstr || ystr || zstr)) error->all(FLERR,"Incomplete use of variables in create_atoms command"); @@ -248,25 +247,22 @@ void CreateAtoms::command(int narg, char **arg) xvar = input->variable->find(xstr); if (xvar < 0) error->all(FLERR,"Variable name for create_atoms does not exist"); - if (!input->variable->equalstyle(xvar)) + if (!input->variable->internalstyle(xvar)) error->all(FLERR,"Variable for create_atoms is invalid style"); - input->variable->equal_save(xvar,xstr_copy); } if (ystr) { yvar = input->variable->find(ystr); if (yvar < 0) error->all(FLERR,"Variable name for create_atoms does not exist"); - if (!input->variable->equalstyle(yvar)) + if (!input->variable->internalstyle(yvar)) error->all(FLERR,"Variable for create_atoms is invalid style"); - input->variable->equal_save(yvar,ystr_copy); } if (zstr) { zvar = input->variable->find(zstr); if (zvar < 0) error->all(FLERR,"Variable name for create_atoms does not exist"); - if (!input->variable->equalstyle(zvar)) + if (!input->variable->internalstyle(zvar)) error->all(FLERR,"Variable for create_atoms is invalid style"); - input->variable->equal_save(zvar,zstr_copy); } } @@ -377,23 +373,17 @@ void CreateAtoms::command(int narg, char **arg) for (int i = nlocal_previous; i < nlocal; i++) fix->set_arrays(i); } + for (int m = 0; m < modify->ncompute; m++) { Compute *compute = modify->compute[m]; if (compute->create_attribute) for (int i = nlocal_previous; i < nlocal; i++) compute->set_arrays(i); } + for (int i = nlocal_previous; i < nlocal; i++) input->variable->set_arrays(i); - // restore each equal variable string previously saved - - if (varflag) { - if (xstr) input->variable->equal_restore(xvar,xstr_copy); - if (ystr) input->variable->equal_restore(yvar,ystr_copy); - if (zstr) input->variable->equal_restore(zvar,zstr_copy); - } - // set new total # of atoms and error check bigint nblocal = atom->nlocal; @@ -853,16 +843,17 @@ void CreateAtoms::add_molecule(double *center, double *quat_user) /* ---------------------------------------------------------------------- test a generated atom position against variable evaluation - first plug in x,y,z values as requested + first set x,y,z values in internal variables ------------------------------------------------------------------------- */ int CreateAtoms::vartest(double *x) { - if (xstr) input->variable->equal_override(xvar,x[0]); - if (ystr) input->variable->equal_override(yvar,x[1]); - if (zstr) input->variable->equal_override(zvar,x[2]); + if (xstr) input->variable->internal_set(xvar,x[0]); + if (ystr) input->variable->internal_set(yvar,x[1]); + if (zstr) input->variable->internal_set(zvar,x[2]); double value = input->variable->compute_equal(vvar); + if (value == 0.0) return 0; return 1; } diff --git a/src/dump.cpp b/src/dump.cpp index 62c6a6a4d0..ac69c43d10 100644 --- a/src/dump.cpp +++ b/src/dump.cpp @@ -829,7 +829,6 @@ void Dump::modify_params(int narg, char **arg) format_float_user = NULL; // pass format none to child classes which may use it // not an error if they don't - printf("CALL %d %s\n",narg-iarg,arg[iarg]); int n = modify_param(narg-iarg,&arg[iarg]); iarg += 2; continue; diff --git a/src/variable.cpp b/src/variable.cpp index c4a6198cd5..f27de2777c 100644 --- a/src/variable.cpp +++ b/src/variable.cpp @@ -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,VECTOR,PYTHON}; + SCALARFILE,ATOMFILE,FORMAT,EQUAL,ATOM,VECTOR,PYTHON,INTERNAL}; enum{ARG,OP}; // customize by adding a function @@ -92,6 +92,7 @@ Variable::Variable(LAMMPS *lmp) : Pointers(lmp) pad = NULL; reader = NULL; data = NULL; + dvalue = NULL; vecs = NULL; eval_in_progress = NULL; @@ -135,6 +136,7 @@ Variable::~Variable() memory->destroy(pad); memory->sfree(reader); memory->sfree(data); + memory->sfree(dvalue); memory->sfree(vecs); memory->destroy(eval_in_progress); @@ -483,9 +485,33 @@ void Variable::set(int narg, char **arg) strcpy(data[nvar][1],"(undefined)"); } + // INTERNAL + // replace pre-existing var if also style INTERNAL (allows it to be reset) + // num = 1, for string representation of dvalue, set by retrieve() + // dvalue = numeric initialization from 2nd arg, reset by internal_set() + + } else if (strcmp(arg[1],"internal") == 0) { + if (narg != 3) error->all(FLERR,"Illegal variable command"); + int ivar = find(arg[0]); + if (ivar >= 0) { + if (style[ivar] != INTERNAL) + error->all(FLERR,"Cannot redefine variable as a different style"); + dvalue[nvar] = force->numeric(FLERR,arg[2]); + replaceflag = 1; + } else { + if (nvar == maxvar) grow(); + style[nvar] = INTERNAL; + num[nvar] = 1; + which[nvar] = 0; + pad[nvar] = 0; + data[nvar] = new char*[num[nvar]]; + data[nvar][0] = new char[VALUELENGTH]; + dvalue[nvar] = force->numeric(FLERR,arg[2]); + } + } else error->all(FLERR,"Illegal variable command"); - // set name of variable, if not replacing (EQUAL/ATOM/STRING/PYTHON) + // set name of variable, if not replacing one flagged with replaceflag // name must be all alphanumeric chars or underscores if (replaceflag) return; @@ -557,12 +583,13 @@ 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, VECTOR, GETENV, FORMAT, PYTHON + // invalid styles: STRING, EQUAL, WORLD, ATOM, VECTOR, GETENV, + // FORMAT, PYTHON, INTERNAL int istyle = style[find(arg[0])]; if (istyle == STRING || istyle == EQUAL || istyle == WORLD || istyle == GETENV || istyle == ATOM || istyle == VECTOR || - istyle == FORMAT || istyle == PYTHON) + istyle == FORMAT || istyle == PYTHON || istyle == INTERNAL) error->all(FLERR,"Invalid variable style with next command"); // if istyle = UNIVERSE or ULOOP, insure all such variables are incremented @@ -713,13 +740,13 @@ void Variable::python_command(int narg, char **arg) } /* ---------------------------------------------------------------------- - return 1 if variable is EQUAL or PYTHON numeric style, 0 if not + return 1 if variable is EQUAL or INTERNAL or PYTHON numeric style, 0 if not this is checked before call to compute_equal() to return a double ------------------------------------------------------------------------- */ int Variable::equalstyle(int ivar) { - if (style[ivar] == EQUAL) return 1; + if (style[ivar] == EQUAL || style[ivar] == INTERNAL) return 1; if (style[ivar] == PYTHON) { int ifunc = python->variable_match(data[ivar][0],names[ivar],1); if (ifunc < 0) return 0; @@ -766,6 +793,17 @@ char *Variable::pythonstyle(char *name, char *funcname) return data[ivar][1]; } +/* ---------------------------------------------------------------------- + return 1 if variable is INTERNAL style, 0 if not + this is checked before call to set_internal() to assure it can be set +------------------------------------------------------------------------- */ + +int Variable::internalstyle(int ivar) +{ + if (style[ivar] == INTERNAL) return 1; + return 0; +} + /* ---------------------------------------------------------------------- return ptr to the data text associated with a variable if INDEX or WORLD or UNIVERSE or STRING or SCALARFILE, @@ -775,6 +813,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 INTERNAL, convert dvalue and put result in str if ATOM or ATOMFILE or VECTOR, return NULL return NULL if no variable with name, or which value is bad, caller must respond @@ -835,6 +874,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] == INTERNAL) { + sprintf(data[ivar][0],"%.15g",dvalue[ivar]); + str = data[ivar][0]; } else if (style[ivar] == ATOM || style[ivar] == ATOMFILE || style[ivar] == VECTOR) return NULL; @@ -845,7 +887,7 @@ char *Variable::retrieve(char *name) /* ---------------------------------------------------------------------- return result of equal-style variable evaluation - can be EQUAL style or PYTHON numeric style + can be EQUAL or INTERNAL style or PYTHON numeric style for PYTHON, don't need to check python->variable_match() error return, since caller will have already checked via equalstyle() ------------------------------------------------------------------------- */ @@ -856,8 +898,9 @@ double Variable::compute_equal(int ivar) error->all(FLERR,"Variable has circular dependency"); eval_in_progress[ivar] = 1; - double value = 0.0; + double value; if (style[ivar] == EQUAL) value = evaluate(data[ivar][0],NULL); + else if (style[ivar] == INTERNAL) value = dvalue[ivar]; else if (style[ivar] == PYTHON) { int ifunc = python->find(data[ivar][0]); if (ifunc < 0) error->all(FLERR,"Python variable has no function"); @@ -1001,43 +1044,12 @@ int Variable::compute_vector(int ivar, double **result) } /* ---------------------------------------------------------------------- - save copy of EQUAL style ivar formula in copy - allocate copy here, later equal_restore() call will free it - insure data[ivar][0] is of VALUELENGTH since will be overridden - next 3 functions are used by create_atoms to temporarily override variables + set value stored by INTERNAL style ivar ------------------------------------------------------------------------- */ -void Variable::equal_save(int ivar, char *©) +void Variable::internal_set(int ivar, double value) { - int n = strlen(data[ivar][0]) + 1; - copy = new char[n]; - strcpy(copy,data[ivar][0]); - delete [] data[ivar][0]; - data[ivar][0] = new char[VALUELENGTH]; -} - -/* ---------------------------------------------------------------------- - restore formula string of EQUAL style ivar from copy - then free copy, allocated in equal_save() -------------------------------------------------------------------------- */ - -void Variable::equal_restore(int ivar, char *copy) -{ - delete [] data[ivar][0]; - int n = strlen(copy) + 1; - data[ivar][0] = new char[n]; - strcpy(data[ivar][0],copy); - delete [] copy; -} - -/* ---------------------------------------------------------------------- - override EQUAL style ivar formula with value converted to string - data[ivar][0] was set to length 64 in equal_save() -------------------------------------------------------------------------- */ - -void Variable::equal_override(int ivar, double value) -{ - sprintf(data[ivar][0],"%.15g",value); + dvalue[ivar] = value; } /* ---------------------------------------------------------------------- @@ -1084,6 +1096,7 @@ void Variable::grow() for (int i = old; i < maxvar; i++) reader[i] = NULL; data = (char ***) memory->srealloc(data,maxvar*sizeof(char **),"var:data"); + memory->grow(dvalue,maxvar,"var:dvalue"); vecs = (VecVar *) memory->srealloc(vecs,maxvar*sizeof(VecVar),"var:vecvar"); for (int i = old; i < maxvar; i++) { @@ -1806,10 +1819,26 @@ double Variable::evaluate(char *str, Tree **tree) i = ptr-str+1; } - // v_name = scalar from non atom/atomfile and non vector-style variable + // v_name = scalar from internal-style variable + // access value directly - if (nbracket == 0 && style[ivar] != ATOM && style[ivar] != ATOMFILE && - style[ivar] != VECTOR) { + if (nbracket == 0 && style[ivar] == INTERNAL) { + + value1 = dvalue[ivar]; + if (tree) { + Tree *newtree = new Tree(); + newtree->type = VALUE; + newtree->value = value1; + newtree->first = newtree->second = NULL; + newtree->nextra = 0; + treestack[ntreestack++] = newtree; + } else argstack[nargstack++] = value1; + + // v_name = scalar from non atom/atomfile & non vector-style variable + // access value via retrieve() + + } else if (nbracket == 0 && style[ivar] != ATOM && + style[ivar] != ATOMFILE && style[ivar] != VECTOR) { char *var = retrieve(word+2); if (var == NULL) @@ -1847,8 +1876,8 @@ double Variable::evaluate(char *str, Tree **tree) 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"); + error->all(FLERR,"Atomfile-style variable in " + "vector-style variable formula"); Tree *newtree = new Tree(); newtree->type = ATOMARRAY; diff --git a/src/variable.h b/src/variable.h index eecf905015..c24706430d 100644 --- a/src/variable.h +++ b/src/variable.h @@ -37,19 +37,18 @@ class Variable : protected Pointers { int atomstyle(int); int vectorstyle(int); char *pythonstyle(char *, char *); + int internalstyle(int); char *retrieve(char *); double compute_equal(int); double compute_equal(char *); void compute_atom(int, int, double *, int, int); int compute_vector(int, double **); + void internal_set(int, double); + tagint int_between_brackets(char *&, int); double evaluate_boolean(char *); - void equal_save(int, char *&); - void equal_restore(int, char *); - void equal_override(int, double); - unsigned int data_mask(int ivar); unsigned int data_mask(char *str); @@ -64,6 +63,7 @@ class Variable : protected Pointers { int *pad; // 1 = pad loop/uloop variables with 0s, 0 = no pad class VarReader **reader; // variable that reads from file char ***data; // str value of each variable's values + double *dvalue; // single numeric value for internal variables struct VecVar { int n,nmax;