diff --git a/doc/src/variable.txt b/doc/src/variable.txt index d75391d354..b545f6cee2 100644 --- a/doc/src/variable.txt +++ b/doc/src/variable.txt @@ -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 diff --git a/src/variable.cpp b/src/variable.cpp index 7cbdc57d3a..ea7f3044d7 100644 --- a/src/variable.cpp +++ b/src/variable.cpp @@ -64,8 +64,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 @@ -2297,8 +2297,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) @@ -2705,6 +2705,35 @@ double Variable::collapse_tree(Tree *tree) return tree->value; } + if (tree->type == LOGFREQ3) { + int ivalue1 = static_cast (collapse_tree(tree->first)); + int ivalue2 = static_cast (collapse_tree(tree->second)); + int ivalue3 = static_cast (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 (collapse_tree(tree->first)); int ivalue2 = static_cast (collapse_tree(tree->second)); @@ -2820,8 +2849,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) @@ -3300,8 +3329,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, @@ -3321,9 +3350,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 @@ -3583,6 +3612,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 (value1); + int ivalue2 = static_cast (value2); + int ivalue3 = static_cast (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);