A function logfreq3(), for logarithmical spacing

Unlike logfreq(), this also allows for fractional ratios
Resolves #1471
This commit is contained in:
Vishnu V. Krishnan 2019-05-26 14:00:21 +05:30
parent cfad0634ac
commit c2a200fe85
No known key found for this signature in database
GPG Key ID: 5B1F4BEE7EED7131
2 changed files with 84 additions and 14 deletions

View File

@ -52,7 +52,7 @@ style = {delete} or {index} or {loop} or {world} or {universe} or {uloop} or {st
sin(x), cos(x), tan(x), asin(x), acos(x), atan(x), atan2(y,x),
random(x,y,z), normal(x,y,z), ceil(x), floor(x), round(x)
ramp(x,y), stagger(x,y), logfreq(x,y,z), logfreq2(x,y,z),
stride(x,y,z), stride2(x,y,z,a,b,c),
logfreq3(x,y,z), stride(x,y,z), stride2(x,y,z,a,b,c),
vdisplace(x,y), swiggle(x,y,z), cwiggle(x,y,z)
group functions = count(group), mass(group), charge(group),
xcm(group,dim), vcm(group,dim), fcm(group,dim),
@ -459,8 +459,8 @@ Math functions: sqrt(x), exp(x), ln(x), log(x), abs(x), \
sin(x), cos(x), tan(x), asin(x), acos(x), atan(x), atan2(y,x), \
random(x,y,z), normal(x,y,z), ceil(x), floor(x), round(x), \
ramp(x,y), stagger(x,y), logfreq(x,y,z), logfreq2(x,y,z), \
stride(x,y,z), stride2(x,y,z,a,b,c), vdisplace(x,y), \
swiggle(x,y,z), cwiggle(x,y,z)
logfreq3(x,y,z), stride(x,y,z), stride2(x,y,z,a,b,c), \
vdisplace(x,y), swiggle(x,y,z), cwiggle(x,y,z)
Group functions: count(ID), mass(ID), charge(ID), xcm(ID,dim), \
vcm(ID,dim), fcm(ID,dim), bound(ID,dir), \
gyration(ID), ke(ID), angmom(ID,dim), torque(ID,dim), \
@ -670,6 +670,16 @@ sequence of output timesteps:
100,150,200,...950,1000,1500,2000,...9500,10000,15000,etc :pre
The logfreq3(x,y,z) function generates y points between x and z (inclusive),
that are separated by a multiplicative ratio: (z/x)^(1/(y-1)). Constraints
are: x,z > 0, y > 1, z-x >= y-1. For eg., if logfreq3(10,25,1000) is used in
a variable by the "fix print"_fix_print.html command, then the interval
between 10 and 1000 is divided into 24 parts with a multiplicative
separation of ~1.21, and it will generate the following sequence of output
timesteps:
10, 13, 15, 18, 22, 27, 32,...384, 465, 563, 682, 826, 1000 :pre
The stride(x,y,z) function uses the current timestep to generate a new
timestep. X,y >= 0 and z > 0 and x <= y are required. The generated
timesteps increase in increments of z, from x to y, i.e. it generates

View File

@ -63,8 +63,8 @@ enum{DONE,ADD,SUBTRACT,MULTIPLY,DIVIDE,CARAT,MODULO,UNARY,
NOT,EQ,NE,LT,LE,GT,GE,AND,OR,XOR,
SQRT,EXP,LN,LOG,ABS,SIN,COS,TAN,ASIN,ACOS,ATAN,ATAN2,
RANDOM,NORMAL,CEIL,FLOOR,ROUND,RAMP,STAGGER,LOGFREQ,LOGFREQ2,
STRIDE,STRIDE2,VDISPLACE,SWIGGLE,CWIGGLE,GMASK,RMASK,GRMASK,
IS_ACTIVE,IS_DEFINED,IS_AVAILABLE,
LOGFREQ3,STRIDE,STRIDE2,VDISPLACE,SWIGGLE,CWIGGLE,GMASK,RMASK,
GRMASK,IS_ACTIVE,IS_DEFINED,IS_AVAILABLE,
VALUE,ATOMARRAY,TYPEARRAY,INTARRAY,BIGINTARRAY,VECTORARRAY};
// customize by adding a special function
@ -2294,8 +2294,8 @@ double Variable::evaluate(char *str, Tree **tree, int ivar)
sqrt(),exp(),ln(),log(),abs(),sin(),cos(),tan(),asin(),acos(),atan(),
atan2(y,x),random(x,y,z),normal(x,y,z),ceil(),floor(),round(),
ramp(x,y),stagger(x,y),logfreq(x,y,z),logfreq2(x,y,z),
stride(x,y,z),vdisplace(x,y),swiggle(x,y,z),cwiggle(x,y,z),
gmask(x),rmask(x),grmask(x,y)
logfreq3(x,y,z),stride(x,y,z),vdisplace(x,y),swiggle(x,y,z),
cwiggle(x,y,z),gmask(x),rmask(x),grmask(x,y)
---------------------------------------------------------------------- */
double Variable::collapse_tree(Tree *tree)
@ -2702,6 +2702,35 @@ double Variable::collapse_tree(Tree *tree)
return tree->value;
}
if (tree->type == LOGFREQ3) {
int ivalue1 = static_cast<int> (collapse_tree(tree->first));
int ivalue2 = static_cast<int> (collapse_tree(tree->second));
int ivalue3 = static_cast<int> (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;
if (ivalue1 <= 0 || ivalue2 <= 1 || ivalue3 <= 0 ||
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 {
tree->value = ivalue1;
double logsp = ivalue1;
double factor = pow(((double)ivalue3)/ivalue1, 1.0/(ivalue2-1));
int linsp = ivalue1;
while (update->ntimestep >= (tree->value)) {
logsp *= factor;
linsp++;
if (linsp > logsp) tree->value = linsp;
else tree->value = ceil(logsp)-(((int)ceil(logsp)-1)/ivalue3);
}
}
if (update->ntimestep > ivalue3)
error->all(FLERR,"Calls to variable exceeded limit");
return tree->value;
}
if (tree->type == STRIDE) {
int ivalue1 = static_cast<int> (collapse_tree(tree->first));
int ivalue2 = static_cast<int> (collapse_tree(tree->second));
@ -2817,8 +2846,8 @@ double Variable::collapse_tree(Tree *tree)
sqrt(),exp(),ln(),log(),sin(),cos(),tan(),asin(),acos(),atan(),
atan2(y,x),random(x,y,z),normal(x,y,z),ceil(),floor(),round(),
ramp(x,y),stagger(x,y),logfreq(x,y,z),logfreq2(x,y,z),
stride(x,y,z),stride2(x,y,z),vdisplace(x,y),swiggle(x,y,z),
cwiggle(x,y,z),gmask(x),rmask(x),grmask(x,y)
logfreq3(x,y,z),stride(x,y,z),stride2(x,y,z),vdisplace(x,y),
swiggle(x,y,z),cwiggle(x,y,z),gmask(x),rmask(x),grmask(x,y)
---------------------------------------------------------------------- */
double Variable::eval_tree(Tree *tree, int i)
@ -3297,8 +3326,8 @@ tagint Variable::int_between_brackets(char *&ptr, int varallow)
sqrt(),exp(),ln(),log(),abs(),sin(),cos(),tan(),asin(),acos(),atan(),
atan2(y,x),random(x,y,z),normal(x,y,z),ceil(),floor(),round(),
ramp(x,y),stagger(x,y),logfreq(x,y,z),logfreq2(x,y,z),
stride(x,y,z),stride2(x,y,z,a,b,c),vdisplace(x,y),swiggle(x,y,z),
cwiggle(x,y,z)
logfreq3(x,y,z),stride(x,y,z),stride2(x,y,z,a,b,c),vdisplace(x,y),
swiggle(x,y,z),cwiggle(x,y,z)
------------------------------------------------------------------------- */
int Variable::math_function(char *word, char *contents, Tree **tree,
@ -3318,9 +3347,9 @@ int Variable::math_function(char *word, char *contents, Tree **tree,
strcmp(word,"floor") && strcmp(word,"round") &&
strcmp(word,"ramp") && strcmp(word,"stagger") &&
strcmp(word,"logfreq") && strcmp(word,"logfreq2") &&
strcmp(word,"stride") && strcmp(word,"stride2") &&
strcmp(word,"vdisplace") && strcmp(word,"swiggle") &&
strcmp(word,"cwiggle"))
strcmp(word,"logfreq3") && strcmp(word,"stride") &&
strcmp(word,"stride2") && strcmp(word,"vdisplace") &&
strcmp(word,"swiggle") && strcmp(word,"cwiggle"))
return 0;
// parse contents for comma-separated args
@ -3580,6 +3609,37 @@ int Variable::math_function(char *word, char *contents, Tree **tree,
argstack[nargstack++] = ceil(value);
}
} else if (strcmp(word,"logfreq3") == 0) {
if (narg != 3)
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]);
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 {
value = ivalue1;
double logsp = ivalue1;
double factor = pow(((double)ivalue3)/ivalue1, 1.0/(ivalue2-1));
int linsp = ivalue1;
while (update->ntimestep >= value) {
logsp *= factor;
linsp++;
if (linsp > logsp) value = linsp;
else value = ceil(logsp)-(((int)ceil(logsp)-1)/ivalue3);
}
}
if (update->ntimestep > ivalue3)
error->all(FLERR,"Calls to variable exceeded limit");
argstack[nargstack++] = value;
}
} else if (strcmp(word,"stride") == 0) {
if (narg != 3)
print_var_error(FLERR,"Invalid math function in variable formula",ivar);