Merge branch 'master' of https://github.com/lammps/lammps into lammps-master

This commit is contained in:
Jacob Gissinger
2021-04-27 14:46:33 -04:00
4905 changed files with 257534 additions and 191333 deletions

View File

@ -31,6 +31,7 @@
#include "random_mars.h"
#include "region.h"
#include "thermo.h"
#include "tokenizer.h"
#include "universe.h"
#include "update.h"
@ -38,7 +39,7 @@
#include <cmath>
#include <cstring>
#include <unistd.h>
#include <vector>
#include <unordered_map>
using namespace LAMMPS_NS;
using namespace MathConst;
@ -52,8 +53,6 @@ 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,INTERNAL};
enum{ARG,OP};
// customize by adding a function
@ -65,20 +64,30 @@ enum{DONE,ADD,SUBTRACT,MULTIPLY,DIVIDE,CARAT,MODULO,UNARY,
SQRT,EXP,LN,LOG,ABS,SIN,COS,TAN,ASIN,ACOS,ATAN,ATAN2,
RANDOM,NORMAL,CEIL,FLOOR,ROUND,RAMP,STAGGER,LOGFREQ,LOGFREQ2,
LOGFREQ3,STRIDE,STRIDE2,VDISPLACE,SWIGGLE,CWIGGLE,GMASK,RMASK,
GRMASK,IS_ACTIVE,IS_DEFINED,IS_AVAILABLE,
GRMASK,IS_ACTIVE,IS_DEFINED,IS_AVAILABLE,IS_FILE,
VALUE,ATOMARRAY,TYPEARRAY,INTARRAY,BIGINTARRAY,VECTORARRAY};
// customize by adding a special function
enum{SUM,XMIN,XMAX,AVE,TRAP,SLOPE};
#define INVOKED_SCALAR 1
#define INVOKED_VECTOR 2
#define INVOKED_ARRAY 4
#define INVOKED_PERATOM 8
#define BIG 1.0e20
// constants for variable expressions. customize by adding new items.
// if needed (cf. 'version') initialize in Variable class constructor.
static std::unordered_map<std::string, double> constants = {
{"PI", MY_PI },
{"version", -1 },
{"yes", 1 },
{"no", 0 },
{"on", 1 },
{"off", 0 },
{"true", 1 },
{"false", 0 }
};
/* ---------------------------------------------------------------------- */
Variable::Variable(LAMMPS *lmp) : Pointers(lmp)
@ -101,6 +110,10 @@ Variable::Variable(LAMMPS *lmp) : Pointers(lmp)
randomequal = nullptr;
randomatom = nullptr;
// override initializer since LAMMPS class needs to be instantiated
constants["version"] = lmp->num_ver;
// customize by assigning a precedence level
precedence[DONE] = 0;
@ -189,9 +202,7 @@ void Variable::set(int narg, char **arg)
nlast = utils::inumeric(FLERR,arg[2],false,lmp);
if (nlast <= 0) error->all(FLERR,"Illegal variable command");
if (narg == 4 && strcmp(arg[3],"pad") == 0) {
char digits[12];
sprintf(digits,"%d",nlast);
pad[nvar] = strlen(digits);
pad[nvar] = fmt::format("{}",nlast).size();
} else pad[nvar] = 0;
} else if (narg == 4 || (narg == 5 && strcmp(arg[4],"pad") == 0)) {
nfirst = utils::inumeric(FLERR,arg[2],false,lmp);
@ -199,9 +210,7 @@ void Variable::set(int narg, char **arg)
if (nfirst > nlast || nlast < 0)
error->all(FLERR,"Illegal variable command");
if (narg == 5 && strcmp(arg[4],"pad") == 0) {
char digits[12];
sprintf(digits,"%d",nlast);
pad[nvar] = strlen(digits);
pad[nvar] = fmt::format("{}",nlast).size();
} else pad[nvar] = 0;
} else error->all(FLERR,"Illegal variable command");
num[nvar] = nlast;
@ -327,13 +336,12 @@ void Variable::set(int narg, char **arg)
}
if (nvar == maxvar) grow();
style[nvar] = GETENV;
num[nvar] = 1;
num[nvar] = 2;
which[nvar] = 0;
pad[nvar] = 0;
data[nvar] = new char*[num[nvar]];
copy(1,&arg[2],data[nvar]);
data[nvar][1] = new char[VALUELENGTH];
strcpy(data[nvar][1],"(undefined)");
data[nvar][0] = utils::strdup(arg[2]);
data[nvar][1] = utils::strdup("(undefined)");
// SCALARFILE for strings or numbers
// which = 1st value
@ -404,7 +412,7 @@ void Variable::set(int narg, char **arg)
if (style[ivar] != EQUAL)
error->all(FLERR,"Cannot redefine variable as a different style");
delete [] data[ivar][0];
copy(1,&arg[2],data[ivar]);
data[ivar][0] = utils::strdup(arg[2]);
replaceflag = 1;
} else {
if (nvar == maxvar) grow();
@ -413,7 +421,7 @@ void Variable::set(int narg, char **arg)
which[nvar] = 0;
pad[nvar] = 0;
data[nvar] = new char*[num[nvar]];
copy(1,&arg[2],data[nvar]);
data[nvar][0] = utils::strdup(arg[2]);
data[nvar][1] = new char[VALUELENGTH];
strcpy(data[nvar][1],"(undefined)");
}
@ -430,7 +438,7 @@ void Variable::set(int narg, char **arg)
if (style[ivar] != ATOM)
error->all(FLERR,"Cannot redefine variable as a different style");
delete [] data[ivar][0];
copy(1,&arg[2],data[ivar]);
data[ivar][0] = utils::strdup(arg[2]);
replaceflag = 1;
} else {
if (nvar == maxvar) grow();
@ -439,7 +447,7 @@ void Variable::set(int narg, char **arg)
which[nvar] = 0;
pad[nvar] = 0;
data[nvar] = new char*[num[nvar]];
copy(1,&arg[2],data[nvar]);
data[nvar][0] = utils::strdup(arg[2]);
}
// VECTOR
@ -454,7 +462,7 @@ void Variable::set(int narg, char **arg)
if (style[ivar] != VECTOR)
error->all(FLERR,"Cannot redefine variable as a different style");
delete [] data[ivar][0];
copy(1,&arg[2],data[ivar]);
data[ivar][0] = utils::strdup(arg[2]);
replaceflag = 1;
} else {
if (nvar == maxvar) grow();
@ -463,7 +471,7 @@ void Variable::set(int narg, char **arg)
which[nvar] = 0;
pad[nvar] = 0;
data[nvar] = new char*[num[nvar]];
copy(1,&arg[2],data[nvar]);
data[nvar][0] = utils::strdup(arg[2]);
}
// PYTHON
@ -480,7 +488,7 @@ void Variable::set(int narg, char **arg)
if (style[ivar] != PYTHON)
error->all(FLERR,"Cannot redefine variable as a different style");
delete [] data[ivar][0];
copy(1,&arg[2],data[ivar]);
data[ivar][0] = utils::strdup(arg[2]);
replaceflag = 1;
} else {
if (nvar == maxvar) grow();
@ -489,7 +497,7 @@ void Variable::set(int narg, char **arg)
which[nvar] = 1;
pad[nvar] = 0;
data[nvar] = new char*[num[nvar]];
copy(1,&arg[2],data[nvar]);
data[nvar][0] = utils::strdup(arg[2]);
data[nvar][1] = new char[VALUELENGTH];
strcpy(data[nvar][1],"(undefined)");
}
@ -525,15 +533,10 @@ void Variable::set(int narg, char **arg)
if (replaceflag) return;
int n = strlen(arg[0]) + 1;
names[nvar] = new char[n];
strcpy(names[nvar],arg[0]);
for (int i = 0; i < n-1; i++)
if (!isalnum(names[nvar][i]) && names[nvar][i] != '_')
error->all(FLERR,fmt::format("Variable name '{}' must have only "
"alphanumeric characters or underscores",
names[nvar]));
if (!utils::is_id(arg[0]))
error->all(FLERR,fmt::format("Variable name '{}' must have only alphanu"
"meric characters or underscores",arg[0]));
names[nvar] = utils::strdup(arg[0]);
nvar++;
}
@ -581,8 +584,7 @@ int Variable::set_string(const char *name, const char *str)
if (ivar < 0) return -1;
if (style[ivar] != STRING) return -1;
delete [] data[ivar][0];
data[ivar][0] = new char[strlen(str)+1];
strcpy(data[ivar][0],str);
data[ivar][0] = utils::strdup(str);
return 0;
}
@ -902,11 +904,8 @@ char *Variable::retrieve(const char *name)
sprintf(padstr,"%%0%dd",pad[ivar]);
sprintf(result,padstr,which[ivar]+1);
}
int n = strlen(result) + 1;
delete [] data[ivar][0];
data[ivar][0] = new char[n];
strcpy(data[ivar][0],result);
str = data[ivar][0];
str = data[ivar][0] = utils::strdup(result);
} else if (style[ivar] == EQUAL) {
double answer = evaluate(data[ivar][0],nullptr,ivar);
sprintf(data[ivar][1],"%.15g",answer);
@ -921,13 +920,8 @@ char *Variable::retrieve(const char *name)
} else if (style[ivar] == GETENV) {
const char *result = getenv(data[ivar][0]);
if (result == nullptr) result = (const char *) "";
int n = strlen(result) + 1;
if (n > VALUELENGTH) {
delete [] data[ivar][1];
data[ivar][1] = new char[n];
}
strcpy(data[ivar][1],result);
str = data[ivar][1];
delete [] data[ivar][1];
str = data[ivar][1] = utils::strdup(result);
} else if (style[ivar] == PYTHON) {
int ifunc = python->variable_match(data[ivar][0],name,0);
if (ifunc < 0)
@ -986,9 +980,12 @@ double Variable::compute_equal(int ivar)
don't need to flag eval_in_progress since is an immediate variable
------------------------------------------------------------------------- */
double Variable::compute_equal(char *str)
double Variable::compute_equal(const std::string &str)
{
return evaluate(str,nullptr,-1);
char *ptr = utils::strdup(str);
double val = evaluate(ptr,nullptr,-1);
delete[] ptr;
return val;
}
/* ----------------------------------------------------------------------
@ -1189,12 +1186,8 @@ void Variable::grow()
void Variable::copy(int narg, char **from, char **to)
{
int n;
for (int i = 0; i < narg; i++) {
n = strlen(from[i]) + 1;
to[i] = new char[n];
strcpy(to[i],from[i]);
}
for (int i = 0; i < narg; i++)
to[i] = utils::strdup(from[i]);
}
/* ----------------------------------------------------------------------
@ -1239,6 +1232,9 @@ double Variable::evaluate(char *str, Tree **tree, int ivar)
int i = 0;
int expect = ARG;
if (str == nullptr)
print_var_error(FLERR,"Invalid syntax in variable formula",ivar);
while (1) {
onechar = str[i];
@ -1255,7 +1251,7 @@ double Variable::evaluate(char *str, Tree **tree, int ivar)
print_var_error(FLERR,"Invalid syntax in variable formula",ivar);
expect = OP;
char *contents;
char *contents = nullptr;
i = find_matching_paren(str,i,contents,ivar);
i++;
@ -1380,9 +1376,9 @@ double Variable::evaluate(char *str, Tree **tree, int ivar)
if (compute->invoked_scalar != update->ntimestep)
print_var_error(FLERR,"Compute used in variable between "
"runs is not current",ivar);
} else if (!(compute->invoked_flag & INVOKED_SCALAR)) {
} else if (!(compute->invoked_flag & Compute::INVOKED_SCALAR)) {
compute->compute_scalar();
compute->invoked_flag |= INVOKED_SCALAR;
compute->invoked_flag |= Compute::INVOKED_SCALAR;
}
value1 = compute->scalar;
@ -1407,9 +1403,9 @@ double Variable::evaluate(char *str, Tree **tree, int ivar)
if (compute->invoked_vector != update->ntimestep)
print_var_error(FLERR,"Compute used in variable between runs "
"is not current",ivar);
} else if (!(compute->invoked_flag & INVOKED_VECTOR)) {
} else if (!(compute->invoked_flag & Compute::INVOKED_VECTOR)) {
compute->compute_vector();
compute->invoked_flag |= INVOKED_VECTOR;
compute->invoked_flag |= Compute::INVOKED_VECTOR;
}
if (compute->size_vector_variable &&
@ -1439,9 +1435,9 @@ double Variable::evaluate(char *str, Tree **tree, int ivar)
if (compute->invoked_array != update->ntimestep)
print_var_error(FLERR,"Compute used in variable between runs "
"is not current",ivar);
} else if (!(compute->invoked_flag & INVOKED_ARRAY)) {
} else if (!(compute->invoked_flag & Compute::INVOKED_ARRAY)) {
compute->compute_array();
compute->invoked_flag |= INVOKED_ARRAY;
compute->invoked_flag |= Compute::INVOKED_ARRAY;
}
if (compute->size_array_rows_variable &&
@ -1473,9 +1469,9 @@ double Variable::evaluate(char *str, Tree **tree, int ivar)
if (compute->invoked_vector != update->ntimestep)
print_var_error(FLERR,"Compute used in variable between "
"runs is not current",ivar);
} else if (!(compute->invoked_flag & INVOKED_VECTOR)) {
} else if (!(compute->invoked_flag & Compute::INVOKED_VECTOR)) {
compute->compute_vector();
compute->invoked_flag |= INVOKED_VECTOR;
compute->invoked_flag |= Compute::INVOKED_VECTOR;
}
Tree *newtree = new Tree();
@ -1505,9 +1501,9 @@ double Variable::evaluate(char *str, Tree **tree, int ivar)
if (compute->invoked_array != update->ntimestep)
print_var_error(FLERR,"Compute used in variable between "
"runs is not current",ivar);
} else if (!(compute->invoked_flag & INVOKED_ARRAY)) {
} else if (!(compute->invoked_flag & Compute::INVOKED_ARRAY)) {
compute->compute_array();
compute->invoked_flag |= INVOKED_ARRAY;
compute->invoked_flag |= Compute::INVOKED_ARRAY;
}
Tree *newtree = new Tree();
@ -1529,9 +1525,9 @@ double Variable::evaluate(char *str, Tree **tree, int ivar)
if (compute->invoked_peratom != update->ntimestep)
print_var_error(FLERR,"Compute used in variable "
"between runs is not current",ivar);
} else if (!(compute->invoked_flag & INVOKED_PERATOM)) {
} else if (!(compute->invoked_flag & Compute::INVOKED_PERATOM)) {
compute->compute_peratom();
compute->invoked_flag |= INVOKED_PERATOM;
compute->invoked_flag |= Compute::INVOKED_PERATOM;
}
peratom2global(1,nullptr,compute->vector_atom,1,index1,
@ -1549,9 +1545,9 @@ double Variable::evaluate(char *str, Tree **tree, int ivar)
if (compute->invoked_peratom != update->ntimestep)
print_var_error(FLERR,"Compute used in variable "
"between runs is not current",ivar);
} else if (!(compute->invoked_flag & INVOKED_PERATOM)) {
} else if (!(compute->invoked_flag & Compute::INVOKED_PERATOM)) {
compute->compute_peratom();
compute->invoked_flag |= INVOKED_PERATOM;
compute->invoked_flag |= Compute::INVOKED_PERATOM;
}
if (compute->array_atom)
@ -1578,9 +1574,9 @@ double Variable::evaluate(char *str, Tree **tree, int ivar)
if (compute->invoked_peratom != update->ntimestep)
print_var_error(FLERR,"Compute used in variable "
"between runs is not current",ivar);
} else if (!(compute->invoked_flag & INVOKED_PERATOM)) {
} else if (!(compute->invoked_flag & Compute::INVOKED_PERATOM)) {
compute->compute_peratom();
compute->invoked_flag |= INVOKED_PERATOM;
compute->invoked_flag |= Compute::INVOKED_PERATOM;
}
Tree *newtree = new Tree();
@ -1610,9 +1606,9 @@ double Variable::evaluate(char *str, Tree **tree, int ivar)
if (compute->invoked_peratom != update->ntimestep)
print_var_error(FLERR,"Compute used in variable "
"between runs is not current",ivar);
} else if (!(compute->invoked_flag & INVOKED_PERATOM)) {
} else if (!(compute->invoked_flag & Compute::INVOKED_PERATOM)) {
compute->compute_peratom();
compute->invoked_flag |= INVOKED_PERATOM;
compute->invoked_flag |= Compute::INVOKED_PERATOM;
}
Tree *newtree = new Tree();
@ -2071,7 +2067,7 @@ double Variable::evaluate(char *str, Tree **tree, int ivar)
// ----------------
if (str[i] == '(') {
char *contents;
char *contents = nullptr;
i = find_matching_paren(str,i,contents,ivar);
i++;
@ -2119,8 +2115,8 @@ double Variable::evaluate(char *str, Tree **tree, int ivar)
// constant
// ----------------
} else if (is_constant(word)) {
value1 = constant(word);
} else if (constants.find(word) != constants.end()) {
value1 = constants[word];
if (tree) {
Tree *newtree = new Tree();
newtree->type = VALUE;
@ -2344,7 +2340,7 @@ double Variable::evaluate(char *str, Tree **tree, int ivar)
double Variable::collapse_tree(Tree *tree)
{
double arg1,arg2;
double arg1,arg2,arg3;
if (tree->type == VALUE) return tree->value;
if (tree->type == ATOMARRAY) return 0.0;
@ -2757,7 +2753,7 @@ double Variable::collapse_tree(Tree *tree)
ivalue3-ivalue1+1 < ivalue2 )
error->all(FLERR,"Invalid math function in variable formula");
if (update->ntimestep < ivalue1) tree->value = ivalue1;
//else if (update->ntimestep <= ivalue3){
//else if (update->ntimestep <= ivalue3) {
else {
tree->value = ivalue1;
double logsp = ivalue1;
@ -2811,19 +2807,19 @@ double Variable::collapse_tree(Tree *tree)
error->one(FLERR,"Invalid math function in variable formula");
if (ivalue4 < ivalue1 || ivalue5 > ivalue2)
error->one(FLERR,"Invalid math function in variable formula");
bigint istep;
bigint istep, offset;
if (update->ntimestep < ivalue1) istep = ivalue1;
else if (update->ntimestep < ivalue2) {
if (update->ntimestep < ivalue4 || update->ntimestep > ivalue5) {
bigint offset = update->ntimestep - ivalue1;
offset = update->ntimestep - ivalue1;
istep = ivalue1 + (offset/ivalue3)*ivalue3 + ivalue3;
if (update->ntimestep < ivalue2 && istep > ivalue4)
tree->value = ivalue4;
} else {
bigint offset = update->ntimestep - ivalue4;
offset = update->ntimestep - ivalue4;
istep = ivalue4 + (offset/ivalue6)*ivalue6 + ivalue6;
if (istep > ivalue5) {
bigint offset = ivalue5 - ivalue1;
offset = ivalue5 - ivalue1;
istep = ivalue1 + (offset/ivalue3)*ivalue3 + ivalue3;
if (istep > ivalue2) istep = MAXBIGINT;
}
@ -2834,8 +2830,8 @@ double Variable::collapse_tree(Tree *tree)
}
if (tree->type == VDISPLACE) {
double arg1 = collapse_tree(tree->first);
double arg2 = collapse_tree(tree->second);
arg1 = collapse_tree(tree->first);
arg2 = collapse_tree(tree->second);
if (tree->first->type != VALUE || tree->second->type != VALUE) return 0.0;
tree->type = VALUE;
double delta = update->ntimestep - update->beginstep;
@ -2844,9 +2840,9 @@ double Variable::collapse_tree(Tree *tree)
}
if (tree->type == SWIGGLE) {
double arg1 = collapse_tree(tree->first);
double arg2 = collapse_tree(tree->second);
double arg3 = collapse_tree(tree->extra[0]);
arg1 = collapse_tree(tree->first);
arg2 = collapse_tree(tree->second);
arg3 = collapse_tree(tree->extra[0]);
if (tree->first->type != VALUE || tree->second->type != VALUE ||
tree->extra[0]->type != VALUE) return 0.0;
tree->type = VALUE;
@ -2859,9 +2855,9 @@ double Variable::collapse_tree(Tree *tree)
}
if (tree->type == CWIGGLE) {
double arg1 = collapse_tree(tree->first);
double arg2 = collapse_tree(tree->second);
double arg3 = collapse_tree(tree->extra[0]);
arg1 = collapse_tree(tree->first);
arg2 = collapse_tree(tree->second);
arg3 = collapse_tree(tree->extra[0]);
if (tree->first->type != VALUE || tree->second->type != VALUE ||
tree->extra[0]->type != VALUE) return 0.0;
tree->type = VALUE;
@ -3063,28 +3059,28 @@ double Variable::eval_tree(Tree *tree, int i)
}
if (tree->type == STAGGER) {
int ivalue1 = static_cast<int> (eval_tree(tree->first,i));
int ivalue2 = static_cast<int> (eval_tree(tree->second,i));
bigint ivalue1 = static_cast<bigint> (eval_tree(tree->first,i));
bigint ivalue2 = static_cast<bigint> (eval_tree(tree->second,i));
if (ivalue1 <= 0 || ivalue2 <= 0 || ivalue1 <= ivalue2)
error->one(FLERR,"Invalid math function in variable formula");
int lower = update->ntimestep/ivalue1 * ivalue1;
int delta = update->ntimestep - lower;
bigint lower = update->ntimestep/ivalue1 * ivalue1;
bigint delta = update->ntimestep - lower;
if (delta < ivalue2) arg = lower+ivalue2;
else arg = lower+ivalue1;
return arg;
}
if (tree->type == LOGFREQ) {
int ivalue1 = static_cast<int> (eval_tree(tree->first,i));
int ivalue2 = static_cast<int> (eval_tree(tree->second,i));
int ivalue3 = static_cast<int> (eval_tree(tree->extra[0],i));
bigint ivalue1 = static_cast<bigint> (eval_tree(tree->first,i));
bigint ivalue2 = static_cast<bigint> (eval_tree(tree->second,i));
bigint ivalue3 = static_cast<bigint> (eval_tree(tree->extra[0],i));
if (ivalue1 <= 0 || ivalue2 <= 0 || ivalue3 <= 0 || ivalue2 >= ivalue3)
error->one(FLERR,"Invalid math function in variable formula");
if (update->ntimestep < ivalue1) arg = ivalue1;
else {
int lower = ivalue1;
bigint lower = ivalue1;
while (update->ntimestep >= ivalue3*lower) lower *= ivalue3;
int multiple = update->ntimestep/lower;
bigint multiple = update->ntimestep/lower;
if (multiple < ivalue2) arg = (multiple+1)*lower;
else arg = lower*ivalue3;
}
@ -3092,16 +3088,16 @@ double Variable::eval_tree(Tree *tree, int i)
}
if (tree->type == LOGFREQ2) {
int ivalue1 = static_cast<int> (eval_tree(tree->first,i));
int ivalue2 = static_cast<int> (eval_tree(tree->second,i));
int ivalue3 = static_cast<int> (eval_tree(tree->extra[0],i));
bigint ivalue1 = static_cast<bigint> (eval_tree(tree->first,i));
bigint ivalue2 = static_cast<bigint> (eval_tree(tree->second,i));
bigint ivalue3 = static_cast<bigint> (eval_tree(tree->extra[0],i));
if (ivalue1 <= 0 || ivalue2 <= 0 || ivalue3 <= 0 )
error->all(FLERR,"Invalid math function in variable formula");
if (update->ntimestep < ivalue1) arg = ivalue1;
else {
arg = ivalue1;
double delta = ivalue1*(ivalue3-1.0)/ivalue2;
int count = 0;
bigint count = 0;
while (update->ntimestep >= arg) {
arg += delta;
count++;
@ -3113,14 +3109,14 @@ double Variable::eval_tree(Tree *tree, int i)
}
if (tree->type == STRIDE) {
int ivalue1 = static_cast<int> (eval_tree(tree->first,i));
int ivalue2 = static_cast<int> (eval_tree(tree->second,i));
int ivalue3 = static_cast<int> (eval_tree(tree->extra[0],i));
bigint ivalue1 = static_cast<bigint> (eval_tree(tree->first,i));
bigint ivalue2 = static_cast<bigint> (eval_tree(tree->second,i));
bigint ivalue3 = static_cast<bigint> (eval_tree(tree->extra[0],i));
if (ivalue1 < 0 || ivalue2 < 0 || ivalue3 <= 0 || ivalue1 > ivalue2)
error->one(FLERR,"Invalid math function in variable formula");
if (update->ntimestep < ivalue1) arg = ivalue1;
else if (update->ntimestep < ivalue2) {
int offset = update->ntimestep - ivalue1;
bigint offset = update->ntimestep - ivalue1;
arg = ivalue1 + (offset/ivalue3)*ivalue3 + ivalue3;
if (arg > ivalue2) arg = (double) MAXBIGINT;
} else arg = (double) MAXBIGINT;
@ -3128,31 +3124,31 @@ double Variable::eval_tree(Tree *tree, int i)
}
if (tree->type == STRIDE2) {
int ivalue1 = static_cast<int> (eval_tree(tree->first,i));
int ivalue2 = static_cast<int> (eval_tree(tree->second,i));
int ivalue3 = static_cast<int> (eval_tree(tree->extra[0],i));
int ivalue4 = static_cast<int> (eval_tree(tree->extra[1],i));
int ivalue5 = static_cast<int> (eval_tree(tree->extra[2],i));
int ivalue6 = static_cast<int> (eval_tree(tree->extra[3],i));
bigint ivalue1 = static_cast<bigint> (eval_tree(tree->first,i));
bigint ivalue2 = static_cast<bigint> (eval_tree(tree->second,i));
bigint ivalue3 = static_cast<bigint> (eval_tree(tree->extra[0],i));
bigint ivalue4 = static_cast<bigint> (eval_tree(tree->extra[1],i));
bigint ivalue5 = static_cast<bigint> (eval_tree(tree->extra[2],i));
bigint ivalue6 = static_cast<bigint> (eval_tree(tree->extra[3],i));
if (ivalue1 < 0 || ivalue2 < 0 || ivalue3 <= 0 || ivalue1 > ivalue2)
error->one(FLERR,"Invalid math function in variable formula");
if (ivalue4 < 0 || ivalue5 < 0 || ivalue6 <= 0 || ivalue4 > ivalue5)
error->one(FLERR,"Invalid math function in variable formula");
if (ivalue4 < ivalue1 || ivalue5 > ivalue2)
error->one(FLERR,"Invalid math function in variable formula");
bigint istep;
bigint istep, offset;
if (update->ntimestep < ivalue1) istep = ivalue1;
else if (update->ntimestep < ivalue2) {
if (update->ntimestep < ivalue4 || update->ntimestep > ivalue5) {
int offset = update->ntimestep - ivalue1;
offset = update->ntimestep - ivalue1;
istep = ivalue1 + (offset/ivalue3)*ivalue3 + ivalue3;
if (update->ntimestep < ivalue2 && istep > ivalue4)
tree->value = ivalue4;
} else {
int offset = update->ntimestep - ivalue4;
offset = update->ntimestep - ivalue4;
istep = ivalue4 + (offset/ivalue6)*ivalue6 + ivalue6;
if (istep > ivalue5) {
int offset = ivalue5 - ivalue1;
offset = ivalue5 - ivalue1;
istep = ivalue1 + (offset/ivalue3)*ivalue3 + ivalue3;
if (istep > ivalue2) istep = MAXBIGINT;
}
@ -3291,6 +3287,7 @@ int Variable::find_matching_paren(char *str, int i, char *&contents, int ivar)
int istop = i;
int n = istop - istart - 1;
delete[] contents;
contents = new char[n+1];
strncpy(contents,&str[istart+1],n);
contents[n] = '\0';
@ -3315,7 +3312,7 @@ tagint Variable::int_between_brackets(char *&ptr, int varallow)
char *start = ++ptr;
if (varallow && strstr(ptr,"v_") == ptr) {
if (varallow && utils::strmatch(ptr,"^v_")) {
varflag = 1;
while (*ptr && *ptr != ']') {
if (!isalnum(*ptr) && *ptr != '_')
@ -3594,12 +3591,12 @@ int Variable::math_function(char *word, char *contents, Tree **tree,
print_var_error(FLERR,"Invalid math function in variable formula",ivar);
if (tree) newtree->type = STAGGER;
else {
int ivalue1 = static_cast<int> (value1);
int ivalue2 = static_cast<int> (value2);
bigint ivalue1 = static_cast<bigint> (value1);
bigint ivalue2 = static_cast<bigint> (value2);
if (ivalue1 <= 0 || ivalue2 <= 0 || ivalue1 <= ivalue2)
print_var_error(FLERR,"Invalid math function in variable formula",ivar);
int lower = update->ntimestep/ivalue1 * ivalue1;
int delta = update->ntimestep - lower;
bigint lower = update->ntimestep/ivalue1 * ivalue1;
bigint delta = update->ntimestep - lower;
double value;
if (delta < ivalue2) value = lower+ivalue2;
else value = lower+ivalue1;
@ -3611,17 +3608,17 @@ int Variable::math_function(char *word, char *contents, Tree **tree,
print_var_error(FLERR,"Invalid math function in variable formula",ivar);
if (tree) newtree->type = LOGFREQ;
else {
int ivalue1 = static_cast<int> (value1);
int ivalue2 = static_cast<int> (value2);
int ivalue3 = static_cast<int> (values[0]);
bigint ivalue1 = static_cast<bigint> (value1);
bigint ivalue2 = static_cast<bigint> (value2);
bigint ivalue3 = static_cast<bigint> (values[0]);
if (ivalue1 <= 0 || ivalue2 <= 0 || ivalue3 <= 0 || ivalue2 >= ivalue3)
print_var_error(FLERR,"Invalid math function in variable formula",ivar);
double value;
if (update->ntimestep < ivalue1) value = ivalue1;
else {
int lower = ivalue1;
bigint lower = ivalue1;
while (update->ntimestep >= ivalue3*lower) lower *= ivalue3;
int multiple = update->ntimestep/lower;
bigint multiple = update->ntimestep/lower;
if (multiple < ivalue2) value = (multiple+1)*lower;
else value = lower*ivalue3;
}
@ -3633,9 +3630,9 @@ int Variable::math_function(char *word, char *contents, Tree **tree,
print_var_error(FLERR,"Invalid math function in variable formula",ivar);
if (tree) newtree->type = LOGFREQ2;
else {
int ivalue1 = static_cast<int> (value1);
int ivalue2 = static_cast<int> (value2);
int ivalue3 = static_cast<int> (values[0]);
bigint ivalue1 = static_cast<bigint> (value1);
bigint ivalue2 = static_cast<bigint> (value2);
bigint ivalue3 = static_cast<bigint> (values[0]);
if (ivalue1 <= 0 || ivalue2 <= 0 || ivalue3 <= 0 )
print_var_error(FLERR,"Invalid math function in variable formula",ivar);
double value;
@ -3643,7 +3640,7 @@ int Variable::math_function(char *word, char *contents, Tree **tree,
else {
value = ivalue1;
double delta = ivalue1*(ivalue3-1.0)/ivalue2;
int count = 0;
bigint count = 0;
while (update->ntimestep >= value) {
value += delta;
count++;
@ -3658,25 +3655,25 @@ int Variable::math_function(char *word, char *contents, Tree **tree,
print_var_error(FLERR,"Invalid math function in variable formula",ivar);
if (tree) newtree->type = LOGFREQ3;
else {
int ivalue1 = static_cast<int> (value1);
int ivalue2 = static_cast<int> (value2);
int ivalue3 = static_cast<int> (values[0]);
bigint ivalue1 = static_cast<bigint> (value1);
bigint ivalue2 = static_cast<bigint> (value2);
bigint ivalue3 = static_cast<bigint> (values[0]);
if (ivalue1 <= 0 || ivalue2 <= 1 || ivalue3 <= 0 ||
ivalue3-ivalue1+1 < ivalue2 )
print_var_error(FLERR,"Invalid math function in variable formula",ivar);
double value;
if (update->ntimestep < ivalue1) value = ivalue1;
//else if (update->ntimestep <= ivalue3){
//else if (update->ntimestep <= ivalue3) {
else {
value = ivalue1;
double logsp = ivalue1;
double factor = pow(((double)ivalue3)/ivalue1, 1.0/(ivalue2-1));
int linsp = ivalue1;
bigint linsp = ivalue1;
while (update->ntimestep >= value) {
logsp *= factor;
linsp++;
if (linsp > logsp) value = linsp;
else value = ceil(logsp)-(((int)ceil(logsp)-1)/ivalue3);
else value = ceil(logsp)-(((bigint)ceil(logsp)-1)/ivalue3);
}
}
if (update->ntimestep > ivalue3)
@ -3689,15 +3686,15 @@ int Variable::math_function(char *word, char *contents, Tree **tree,
print_var_error(FLERR,"Invalid math function in variable formula",ivar);
if (tree) newtree->type = STRIDE;
else {
int ivalue1 = static_cast<int> (value1);
int ivalue2 = static_cast<int> (value2);
int ivalue3 = static_cast<int> (values[0]);
bigint ivalue1 = static_cast<bigint> (value1);
bigint ivalue2 = static_cast<bigint> (value2);
bigint ivalue3 = static_cast<bigint> (values[0]);
if (ivalue1 < 0 || ivalue2 < 0 || ivalue3 <= 0 || ivalue1 > ivalue2)
error->one(FLERR,"Invalid math function in variable formula");
double value;
if (update->ntimestep < ivalue1) value = ivalue1;
else if (update->ntimestep < ivalue2) {
int offset = update->ntimestep - ivalue1;
bigint offset = update->ntimestep - ivalue1;
value = ivalue1 + (offset/ivalue3)*ivalue3 + ivalue3;
if (value > ivalue2) value = (double) MAXBIGINT;
} else value = (double) MAXBIGINT;
@ -3709,30 +3706,30 @@ int Variable::math_function(char *word, char *contents, Tree **tree,
print_var_error(FLERR,"Invalid math function in variable formula",ivar);
if (tree) newtree->type = STRIDE2;
else {
int ivalue1 = static_cast<int> (value1);
int ivalue2 = static_cast<int> (value2);
int ivalue3 = static_cast<int> (values[0]);
int ivalue4 = static_cast<int> (values[1]);
int ivalue5 = static_cast<int> (values[2]);
int ivalue6 = static_cast<int> (values[3]);
bigint ivalue1 = static_cast<bigint> (value1);
bigint ivalue2 = static_cast<bigint> (value2);
bigint ivalue3 = static_cast<bigint> (values[0]);
bigint ivalue4 = static_cast<bigint> (values[1]);
bigint ivalue5 = static_cast<bigint> (values[2]);
bigint ivalue6 = static_cast<bigint> (values[3]);
if (ivalue1 < 0 || ivalue2 < 0 || ivalue3 <= 0 || ivalue1 > ivalue2)
error->one(FLERR,"Invalid math function in variable formula");
if (ivalue4 < 0 || ivalue5 < 0 || ivalue6 <= 0 || ivalue4 > ivalue5)
error->one(FLERR,"Invalid math function in variable formula");
if (ivalue4 < ivalue1 || ivalue5 > ivalue2)
error->one(FLERR,"Invalid math function in variable formula");
bigint istep;
bigint istep, offset;
if (update->ntimestep < ivalue1) istep = ivalue1;
else if (update->ntimestep < ivalue2) {
if (update->ntimestep < ivalue4 || update->ntimestep > ivalue5) {
int offset = update->ntimestep - ivalue1;
offset = update->ntimestep - ivalue1;
istep = ivalue1 + (offset/ivalue3)*ivalue3 + ivalue3;
if (update->ntimestep < ivalue4 && istep > ivalue4) istep = ivalue4;
} else {
int offset = update->ntimestep - ivalue4;
offset = update->ntimestep - ivalue4;
istep = ivalue4 + (offset/ivalue6)*ivalue6 + ivalue6;
if (istep > ivalue5) {
int offset = ivalue5 - ivalue1;
offset = ivalue5 - ivalue1;
istep = ivalue1 + (offset/ivalue3)*ivalue3 + ivalue3;
if (istep > ivalue2) istep = MAXBIGINT;
}
@ -4084,7 +4081,7 @@ int Variable::special_function(char *word, char *contents, Tree **tree,
strcmp(word,"gmask") && strcmp(word,"rmask") &&
strcmp(word,"grmask") && strcmp(word,"next") &&
strcmp(word,"is_active") && strcmp(word,"is_defined") &&
strcmp(word,"is_available"))
strcmp(word,"is_available") && strcmp(word,"is_file"))
return 0;
// parse contents for comma-separated args
@ -4112,13 +4109,13 @@ int Variable::special_function(char *word, char *contents, Tree **tree,
Compute *compute = nullptr;
Fix *fix = nullptr;
int ivar = -1;
int index,nvec,nstride;
char *ptr1,*ptr2;
int ivar = -1;
// argument is compute
if (strstr(args[0],"c_") == args[0]) {
if (utils::strmatch(args[0],"^c_")) {
ptr1 = strchr(args[0],'[');
if (ptr1) {
ptr2 = ptr1;
@ -4139,9 +4136,9 @@ int Variable::special_function(char *word, char *contents, Tree **tree,
if (compute->invoked_vector != update->ntimestep)
print_var_error(FLERR,"Compute used in variable between runs "
"is not current",ivar);
} else if (!(compute->invoked_flag & INVOKED_VECTOR)) {
} else if (!(compute->invoked_flag & Compute::INVOKED_VECTOR)) {
compute->compute_vector();
compute->invoked_flag |= INVOKED_VECTOR;
compute->invoked_flag |= Compute::INVOKED_VECTOR;
}
nvec = compute->size_vector;
nstride = 1;
@ -4153,9 +4150,9 @@ int Variable::special_function(char *word, char *contents, Tree **tree,
if (compute->invoked_array != update->ntimestep)
print_var_error(FLERR,"Compute used in variable between runs "
"is not current",ivar);
} else if (!(compute->invoked_flag & INVOKED_ARRAY)) {
} else if (!(compute->invoked_flag & Compute::INVOKED_ARRAY)) {
compute->compute_array();
compute->invoked_flag |= INVOKED_ARRAY;
compute->invoked_flag |= Compute::INVOKED_ARRAY;
}
nvec = compute->size_array_rows;
nstride = compute->size_array_cols;
@ -4163,7 +4160,7 @@ int Variable::special_function(char *word, char *contents, Tree **tree,
// argument is fix
} else if (strstr(args[0],"f_") == args[0]) {
} else if (utils::strmatch(args[0],"^f_")) {
ptr1 = strchr(args[0],'[');
if (ptr1) {
ptr2 = ptr1;
@ -4201,7 +4198,7 @@ int Variable::special_function(char *word, char *contents, Tree **tree,
// argument is vector-style variable
} else if (strstr(args[0],"v_") == args[0]) {
} else if (utils::strmatch(args[0],"^v_")) {
ptr1 = strchr(args[0],'[');
if (ptr1) {
ptr2 = ptr1;
@ -4493,6 +4490,26 @@ int Variable::special_function(char *word, char *contents, Tree **tree,
// save value in tree or on argstack
if (tree) {
Tree *newtree = new Tree();
newtree->type = VALUE;
newtree->value = value;
newtree->first = newtree->second = nullptr;
newtree->nextra = 0;
treestack[ntreestack++] = newtree;
} else argstack[nargstack++] = value;
} else if (strcmp(word,"is_file") == 0) {
if (narg != 1)
print_var_error(FLERR,"Invalid is_file() function in "
"variable formula",ivar);
FILE *fp = fopen(args[0],"r");
value = (fp == nullptr) ? 0.0 : 1.0;
if (fp) fclose(fp);
// save value in tree or on argstack
if (tree) {
Tree *newtree = new Tree();
newtree->type = VALUE;
@ -4752,43 +4769,6 @@ void Variable::atom_vector(char *word, Tree **tree,
}
}
/* ----------------------------------------------------------------------
check if word matches a constant
return 1 if yes, else 0
customize by adding a constant: PI, version
------------------------------------------------------------------------- */
int Variable::is_constant(char *word)
{
if (strcmp(word,"PI") == 0) return 1;
if (strcmp(word,"version") == 0) return 1;
if (strcmp(word,"yes") == 0) return 1;
if (strcmp(word,"no") == 0) return 1;
if (strcmp(word,"on") == 0) return 1;
if (strcmp(word,"off") == 0) return 1;
if (strcmp(word,"true") == 0) return 1;
if (strcmp(word,"false") == 0) return 1;
return 0;
}
/* ----------------------------------------------------------------------
process a constant in formula
customize by adding a constant: PI, version
------------------------------------------------------------------------- */
double Variable::constant(char *word)
{
if (strcmp(word,"PI") == 0) return MY_PI;
if (strcmp(word,"version") == 0) return lmp->num_ver;
if (strcmp(word,"yes") == 0) return 1.0;
if (strcmp(word,"no") == 0) return 0.0;
if (strcmp(word,"on") == 0) return 1.0;
if (strcmp(word,"off") == 0) return 0.0;
if (strcmp(word,"true") == 0) return 1.0;
if (strcmp(word,"false") == 0) return 0.0;
return 0.0;
}
/* ----------------------------------------------------------------------
parse string for comma-separated args
store copy of each arg in args array
@ -4797,18 +4777,14 @@ double Variable::constant(char *word)
int Variable::parse_args(char *str, char **args)
{
int n;
char *ptrnext;
int narg = 0;
int narg = 0;
char *ptr = str;
while (ptr && narg < MAXFUNCARG) {
ptrnext = find_next_comma(ptr);
if (ptrnext) *ptrnext = '\0';
n = strlen(ptr) + 1;
args[narg] = new char[n];
strcpy(args[narg],ptr);
args[narg] = utils::strdup(ptr);
narg++;
ptr = ptrnext;
if (ptr) ptr++;
@ -4818,7 +4794,6 @@ int Variable::parse_args(char *str, char **args)
return narg;
}
/* ----------------------------------------------------------------------
find next comma in str
skip commas inside one or more nested parenthesis
@ -4917,7 +4892,7 @@ double Variable::evaluate_boolean(char *str)
error->all(FLERR,"Invalid Boolean syntax in if command");
expect = OP;
char *contents;
char *contents = nullptr;
i = find_matching_paren(str,i,contents,-1);
i++;
@ -5152,14 +5127,13 @@ VarReader::VarReader(LAMMPS *lmp, char *name, char *file, int flag) :
id_fix = nullptr;
buffer = nullptr;
if (style == ATOMFILE) {
if (style == Variable::ATOMFILE) {
if (atom->map_style == Atom::MAP_NONE)
error->all(FLERR,"Cannot use atomfile-style "
"variable unless an atom map exists");
std::string cmd = name + std::string("_VARIABLE_STORE");
id_fix = new char[cmd.size()+1];
strcpy(id_fix,cmd.c_str());
id_fix = utils::strdup(cmd);
cmd += " all STORE peratom 0 1";
modify->add_fix(cmd);
@ -5203,17 +5177,17 @@ int VarReader::read_scalar(char *str)
if (me == 0) {
while (1) {
if (fgets(str,MAXLINE,fp) == nullptr) n = 0;
else n = strlen(str);
if (n == 0) break; // end of file
str[n-1] = '\0'; // strip newline
if ((ptr = strchr(str,'#'))) *ptr = '\0'; // strip comment
if (strtok(str," \t\n\r\f") == nullptr) continue; // skip if blank
n = strlen(str) + 1;
ptr = fgets(str,MAXLINE,fp);
if (!ptr) { n=0; break; } // end of file
ptr[strcspn(ptr,"#")] = '\0'; // strip comment
ptr += strspn(ptr," \t\n\r\f"); // strip leading whitespace
ptr[strcspn(ptr," \t\n\r\f")] = '\0'; // strip trailing whitespace
n = strlen(ptr) + 1;
if (n == 1) continue; // skip if blank line
break;
}
memmove(str,ptr,n); // move trimmed string back
}
MPI_Bcast(&n,1,MPI_INT,0,world);
if (n == 0) return 1;
MPI_Bcast(str,n,MPI_CHAR,0,world);
@ -5246,20 +5220,20 @@ int VarReader::read_peratom()
char str[MAXLINE];
if (me == 0) {
while (1) {
if (fgets(str,MAXLINE,fp) == nullptr) n = 0;
else n = strlen(str);
if (n == 0) break; // end of file
str[n-1] = '\0'; // strip newline
if ((ptr = strchr(str,'#'))) *ptr = '\0'; // strip comment
if (strtok(str," \t\n\r\f") == nullptr) continue; // skip if blank
n = strlen(str) + 1;
ptr = fgets(str,MAXLINE,fp);
if (!ptr) { n=0; break; } // end of file
ptr[strcspn(ptr,"#")] = '\0'; // strip comment
ptr += strspn(ptr," \t\n\r\f"); // strip leading whitespace
ptr[strcspn(ptr," \t\n\r\f")] = '\0'; // strip trailing whitespace
n = strlen(ptr) + 1;
if (n == 1) continue; // skip if blank line
break;
}
memmove(str,ptr,n); // move trimmed string back
}
MPI_Bcast(&n,1,MPI_INT,0,world);
if (n == 0) return 1;
MPI_Bcast(str,n,MPI_CHAR,0,world);
bigint nlines = utils::bnumeric(FLERR,str,false,lmp);
tagint map_tag_max = atom->map_tag_max;
@ -5267,16 +5241,24 @@ int VarReader::read_peratom()
bigint nread = 0;
while (nread < nlines) {
nchunk = MIN(nlines-nread,CHUNK);
eof = comm->read_lines_from_file(fp,nchunk,MAXLINE,buffer);
eof = utils::read_lines_from_file(fp,nchunk,MAXLINE,buffer,me,world);
if (eof) return 1;
char *buf = buffer;
for (i = 0; i < nchunk; i++) {
next = strchr(buf,'\n');
*next = '\0';
int rv = sscanf(buf,TAGINT_FORMAT " %lg",&tag,&value);
if (tag <= 0 || tag > map_tag_max || rv != 2)
error->one(FLERR,"Invalid atom ID in variable file");
try {
ValueTokenizer words(buf);
tag = words.next_bigint();
value = words.next_double();
} catch (TokenizerException &e) {
error->all(FLERR,fmt::format("Invalid atomfile line '{}': {}",
buf,e.what()));
}
if ((tag <= 0) || (tag > map_tag_max))
error->all(FLERR,fmt::format("Invalid atom ID {} in variable "
"file", tag));
if ((m = atom->map(tag)) >= 0) vstore[m] = value;
buf = next + 1;
}