From 544dde674bfbd8dd7004cd345f084819cad8bc1a Mon Sep 17 00:00:00 2001 From: sjplimp <sjplimp@f3b2605a-c512-4ea7-a41b-209d697bcdaa> Date: Tue, 12 Oct 2010 17:58:40 +0000 Subject: [PATCH] git-svn-id: svn://svn.icms.temple.edu/lammps-ro/trunk@5023 f3b2605a-c512-4ea7-a41b-209d697bcdaa --- src/COLLOID/fix_wall_colloid.cpp | 10 +- src/COLLOID/fix_wall_colloid.h | 2 +- src/fix_gravity.cpp | 4 +- src/fix_wall.cpp | 220 ++++++------- src/fix_wall.h | 12 +- src/fix_wall_harmonic.cpp | 10 +- src/fix_wall_harmonic.h | 2 +- src/fix_wall_lj126.cpp | 10 +- src/fix_wall_lj126.h | 2 +- src/fix_wall_lj93.cpp | 10 +- src/fix_wall_lj93.h | 2 +- src/fix_wall_reflect.cpp | 282 ++++++---------- src/fix_wall_reflect.h | 9 +- src/variable.cpp | 533 +++++++++++++++++++++---------- src/variable.h | 3 + 15 files changed, 608 insertions(+), 503 deletions(-) diff --git a/src/COLLOID/fix_wall_colloid.cpp b/src/COLLOID/fix_wall_colloid.cpp index 8fcef726c6..4859378bcf 100644 --- a/src/COLLOID/fix_wall_colloid.cpp +++ b/src/COLLOID/fix_wall_colloid.cpp @@ -84,11 +84,13 @@ void FixWallColloid::precompute(int m) } /* ---------------------------------------------------------------------- - interaction of all particles in group with all 6 walls (if defined) + interaction of all particles in group with a wall + m = index of wall coeffs + which = xlo,xhi,ylo,yhi,zlo,zhi error if any finite-size particle is touching or penetrating wall ------------------------------------------------------------------------- */ -void FixWallColloid::wall_particle(int m, double coord) +void FixWallColloid::wall_particle(int m, int which, double coord) { double delta,delta2,rinv,r2inv,r4inv,r8inv,fwall; double r2,rinv2,r2inv2,r4inv2,r6inv2; @@ -102,8 +104,8 @@ void FixWallColloid::wall_particle(int m, double coord) int *type = atom->type; int nlocal = atom->nlocal; - int dim = m/2; - int side = m % 2; + int dim = which / 2; + int side = which % 2; if (side == 0) side = -1; int onflag = 0; diff --git a/src/COLLOID/fix_wall_colloid.h b/src/COLLOID/fix_wall_colloid.h index 1d09975e18..4b1734cf78 100644 --- a/src/COLLOID/fix_wall_colloid.h +++ b/src/COLLOID/fix_wall_colloid.h @@ -29,7 +29,7 @@ class FixWallColloid : public FixWall { FixWallColloid(class LAMMPS *, int, char **); void init(); void precompute(int); - void wall_particle(int, double); + void wall_particle(int, int, double); private: double coeff1[6],coeff2[6],coeff3[6],coeff4[6],offset[6]; diff --git a/src/fix_gravity.cpp b/src/fix_gravity.cpp index 8070ccc51a..7d7c362875 100644 --- a/src/fix_gravity.cpp +++ b/src/fix_gravity.cpp @@ -62,8 +62,8 @@ FixGravity::FixGravity(LAMMPS *lmp, int narg, char **arg) : zdir = atof(arg[7]); } else error->all("Illegal fix gravity command"); - double PI = 2.0 * asin(1.0); - degree2rad = 2.0*PI / 360.0; + double PI = 4.0*atan(1.0); + degree2rad = PI/180.0; if (style == CHUTE || style == SPHERICAL || style == GRADIENT) { if (domain->dimension == 3) { diff --git a/src/fix_wall.cpp b/src/fix_wall.cpp index fee8d27fa2..78632c99d8 100644 --- a/src/fix_wall.cpp +++ b/src/fix_wall.cpp @@ -16,16 +16,18 @@ #include "string.h" #include "fix_wall.h" #include "atom.h" +#include "input.h" +#include "variable.h" #include "domain.h" #include "lattice.h" #include "update.h" -#include "output.h" #include "respa.h" #include "error.h" using namespace LAMMPS_NS; enum{XLO,XHI,YLO,YHI,ZLO,ZHI}; +enum{NONE,EDGE,CONSTANT,VARIABLE}; /* ---------------------------------------------------------------------- */ @@ -34,17 +36,13 @@ FixWall::FixWall(LAMMPS *lmp, int narg, char **arg) : { scalar_flag = 1; vector_flag = 1; - size_vector = 6; global_freq = 1; extscalar = 1; extvector = 1; - time_depend = 1; // parse args - for (int m = 0; m < 6; m++) wallflag[m] = 0; - velflag = 0; - wigflag = 0; + nwall = 0; int scaleflag = 1; int iarg = 3; @@ -53,39 +51,42 @@ FixWall::FixWall(LAMMPS *lmp, int narg, char **arg) : (strcmp(arg[iarg],"ylo") == 0) || (strcmp(arg[iarg],"yhi") == 0) || (strcmp(arg[iarg],"zlo") == 0) || (strcmp(arg[iarg],"zhi") == 0)) { if (iarg+5 > narg) error->all("Illegal fix wall command"); - int m; - if (strcmp(arg[iarg],"xlo") == 0) m = XLO; - else if (strcmp(arg[iarg],"xhi") == 0) m = XHI; - else if (strcmp(arg[iarg],"ylo") == 0) m = YLO; - else if (strcmp(arg[iarg],"yhi") == 0) m = YHI; - else if (strcmp(arg[iarg],"zlo") == 0) m = ZLO; - else if (strcmp(arg[iarg],"zhi") == 0) m = ZHI; - wallflag[m] = 1; - coord0[m] = atof(arg[iarg+1]); - epsilon[m] = atof(arg[iarg+2]); - sigma[m] = atof(arg[iarg+3]); - cutoff[m] = atof(arg[iarg+4]); + + int newwall; + if (strcmp(arg[iarg],"xlo") == 0) newwall = XLO; + else if (strcmp(arg[iarg],"xhi") == 0) newwall = XHI; + else if (strcmp(arg[iarg],"ylo") == 0) newwall = YLO; + else if (strcmp(arg[iarg],"yhi") == 0) newwall = YHI; + else if (strcmp(arg[iarg],"zlo") == 0) newwall = ZLO; + else if (strcmp(arg[iarg],"zhi") == 0) newwall = ZHI; + + for (int m = 0; m < nwall; m++) + if (newwall == wallwhich[m]) + error->all("Wall defined twice in fix wall command"); + + wallwhich[nwall] = newwall; + if (strcmp(arg[iarg+1],"EDGE") == 0) { + wallstyle[nwall] = EDGE; + int dim = wallwhich[nwall] / 2; + int side = wallwhich[nwall] % 2; + if (side == 0) coord0[nwall] = domain->boxlo[dim]; + else coord0[nwall] = domain->boxhi[dim]; + } else if (strstr(arg[iarg+1],"v_") == arg[iarg+1]) { + wallstyle[nwall] = VARIABLE; + int n = strlen(&arg[iarg+1][2]) + 1; + varstr[nwall] = new char[n]; + strcpy(varstr[nwall],&arg[iarg+1][2]); + } else { + wallstyle[nwall] = CONSTANT; + coord0[nwall] = atof(arg[iarg+1]); + } + + epsilon[nwall] = atof(arg[iarg+2]); + sigma[nwall] = atof(arg[iarg+3]); + cutoff[nwall] = atof(arg[iarg+4]); + nwall++; iarg += 5; - } else if (strcmp(arg[iarg],"vel") == 0) { - if (iarg+2 > narg) error->all("Illegal fix wall command"); - velflag = 1; - double vtmp = atof(arg[iarg+1]); - for (int m = 0; m < 6; m++) vel[m] = vtmp; - iarg += 2; - } else if (strcmp(arg[iarg],"wiggle/sin") == 0) { - if (iarg+3 > narg) error->all("Illegal fix wall command"); - wigflag = 1; - double atmp = atof(arg[iarg+1]); - period = atof(arg[iarg+2]); - for (int m = 0; m < 6; m++) amplitude[m] = atmp; - iarg += 3; - } else if (strcmp(arg[iarg],"wiggle/cos") == 0) { - if (iarg+3 > narg) error->all("Illegal fix wall command"); - wigflag = 2; - double atmp = atof(arg[iarg+1]); - period = atof(arg[iarg+2]); - for (int m = 0; m < 6; m++) amplitude[m] = atmp; - iarg += 3; + } else if (strcmp(arg[iarg],"units") == 0) { if (iarg+2 > narg) error->all("Illegal fix wall command"); if (strcmp(arg[iarg+1],"box") == 0) scaleflag = 0; @@ -95,66 +96,70 @@ FixWall::FixWall(LAMMPS *lmp, int narg, char **arg) : } else error->all("Illegal fix wall command"); } + size_vector = nwall; + // error check - int flag = 0; - for (int m = 0; m < 6; m++) if (wallflag[m]) flag = 1; - if (!flag) error->all("Illegal fix wall command"); - - for (int m = 0; m < 6; m++) - if (wallflag[m] && cutoff[m] <= 0.0) + if (nwall == 0) error->all("Illegal fix wall command"); + for (int m = 0; m < nwall; m++) + if (cutoff[m] <= 0.0) error->all("Fix wall cutoff <= 0.0"); - if (velflag && wigflag) - error->all("Cannot set both vel and wiggle in fix wall command"); - - if ((wallflag[XLO] || wallflag[XHI]) && domain->xperiodic) - error->all("Cannot use fix wall in periodic dimension"); - if ((wallflag[YLO] || wallflag[YHI]) && domain->yperiodic) - error->all("Cannot use fix wall in periodic dimension"); - if ((wallflag[ZLO] || wallflag[ZHI]) && domain->zperiodic) - error->all("Cannot use fix wall in periodic dimension"); - - if ((wallflag[ZLO] || wallflag[ZHI]) && domain->dimension == 2) - error->all("Cannot use fix wall zlo/zhi for a 2d simulation"); - - // setup scaling - - if (scaleflag && domain->lattice == NULL) - error->all("Use of fix wall with undefined lattice"); - - double xscale,yscale,zscale; - if (scaleflag) { - xscale = domain->lattice->xlattice; - yscale = domain->lattice->ylattice; - zscale = domain->lattice->zlattice; - } - else xscale = yscale = zscale = 1.0; - - // apply scaling factors to coord0, vel, amplitude - - double scale; - for (int m = 0; m < 6; m++) { - if (wallflag[m] == 0) continue; - if (m < 2) scale = xscale; - else if (m < 4) scale = yscale; - else scale = zscale; - coord0[m] *= scale; - if (velflag) vel[m] *= scale; - if (wigflag) amplitude[m] *= scale; + for (int m = 0; m < nwall; m++) { + if ((wallwhich[m] == XLO || wallwhich[m] == XHI) && domain->xperiodic) + error->all("Cannot use fix wall in periodic dimension"); + if ((wallwhich[m] == YLO || wallwhich[m] == YHI) && domain->yperiodic) + error->all("Cannot use fix wall in periodic dimension"); + if ((wallwhich[m] == ZLO || wallwhich[m] == ZHI) && domain->zperiodic) + error->all("Cannot use fix wall in periodic dimension"); } - // setup oscillations + for (int m = 0; m < nwall; m++) + if ((wallwhich[m] == ZLO || wallwhich[m] == ZHI) && domain->dimension == 2) + error->all("Cannot use fix wall zlo/zhi for a 2d simulation"); + + // scale coord for CONSTANT walls - if (wigflag) { - double PI = 4.0 * atan(1.0); - omega = 2.0*PI / period; + int flag = 0; + for (int m = 0; m < nwall; m++) + if (wallstyle[m] == CONSTANT) flag = 1; + + if (flag) { + if (scaleflag && domain->lattice == NULL) + error->all("Use of fix wall with undefined lattice"); + + double xscale,yscale,zscale; + if (scaleflag) { + xscale = domain->lattice->xlattice; + yscale = domain->lattice->ylattice; + zscale = domain->lattice->zlattice; + } + else xscale = yscale = zscale = 1.0; + + double scale; + for (int m = 0; m < nwall; m++) { + if (wallwhich[m] < YLO) scale = xscale; + else if (wallwhich[m] < ZLO) scale = yscale; + else scale = zscale; + if (wallstyle[m] == CONSTANT) coord0[m] *= scale; + } } + // set time_depend if any wall positions are variable + + for (int m = 0; m < nwall; m++) + if (wallstyle[m] == VARIABLE) time_depend = 1; + eflag = 0; - for (int m = 0; m < 7; m++) ewall[m] = 0.0; + for (int m = 0; m <= nwall; m++) ewall[m] = 0.0; +} - time_origin = update->ntimestep; +/* ---------------------------------------------------------------------- */ + +FixWall::~FixWall() +{ + for (int m = 0; m < nwall; m++) + if (wallstyle[m] == VARIABLE) delete [] varstr[m]; } /* ---------------------------------------------------------------------- */ @@ -175,10 +180,18 @@ void FixWall::init() { dt = update->dt; + for (int m = 0; m < nwall; m++) { + if (wallstyle[m] != VARIABLE) continue; + varindex[m] = input->variable->find(varstr[m]); + if (varindex[m] < 0) + error->all("Variable name for fix wall does not exist"); + if (!input->variable->equalstyle(varindex[m])) + error->all("Variable for fix wall is invalid style"); + } + // setup coefficients - for (int m = 0; m < 6; m++) - if (wallflag[m]) precompute(m); + for (int m = 0; m < nwall; m++) precompute(m); if (strcmp(update->integrate_style,"respa") == 0) nlevels_respa = ((Respa *) update->integrate)->nlevels; @@ -209,29 +222,18 @@ void FixWall::min_setup(int vflag) void FixWall::post_force(int vflag) { eflag = 0; - for (int m = 0; m < 7; m++) ewall[m] = 0.0; + for (int m = 0; m <= nwall; m++) ewall[m] = 0.0; - // coord0 = initial position of wall // coord = current position of wall + // evaluate variable if necessary - double delta = (update->ntimestep - time_origin) * dt; double coord; + for (int m = 0; m < nwall; m++) { + if (wallstyle[m] == VARIABLE) + coord = input->variable->compute_equal(varindex[m]); + else coord = coord0[m]; - for (int m = 0; m < 6; m++) { - if (wallflag[m] == 0) continue; - - if (velflag) { - if (m % 2 == 0) coord = coord0[m] + delta*vel[m]; - else coord = coord0[m] - delta*vel[m]; - } else if (wigflag == 1) { - if (m % 2 == 0) coord = coord0[m] + amplitude[m]*sin(omega*delta); - else coord = coord0[m] - amplitude[m]*sin(omega*delta); - } else if (wigflag == 2) { - if (m % 2 == 0) coord = coord0[m] + amplitude[m]*(1.0-cos(omega*delta)); - else coord = coord0[m] - amplitude[m]*(1.0-cos(omega*delta)); - } else coord = coord0[m]; - - wall_particle(m,coord); + wall_particle(m,wallwhich[m],coord); } } @@ -258,7 +260,7 @@ double FixWall::compute_scalar() // only sum across procs one time if (eflag == 0) { - MPI_Allreduce(ewall,ewall_all,7,MPI_DOUBLE,MPI_SUM,world); + MPI_Allreduce(ewall,ewall_all,nwall+1,MPI_DOUBLE,MPI_SUM,world); eflag = 1; } return ewall_all[0]; @@ -273,7 +275,7 @@ double FixWall::compute_vector(int n) // only sum across procs one time if (eflag == 0) { - MPI_Allreduce(ewall,ewall_all,7,MPI_DOUBLE,MPI_SUM,world); + MPI_Allreduce(ewall,ewall_all,nwall+1,MPI_DOUBLE,MPI_SUM,world); eflag = 1; } return ewall_all[n+1]; diff --git a/src/fix_wall.h b/src/fix_wall.h index dc7c26963a..04abd315f2 100644 --- a/src/fix_wall.h +++ b/src/fix_wall.h @@ -21,7 +21,7 @@ namespace LAMMPS_NS { class FixWall : public Fix { public: FixWall(class LAMMPS *, int, char **); - virtual ~FixWall() {} + virtual ~FixWall(); int setmask(); virtual void init(); void setup(int); @@ -33,14 +33,14 @@ class FixWall : public Fix { double compute_vector(int); virtual void precompute(int) = 0; - virtual void wall_particle(int, double) = 0; + virtual void wall_particle(int, int, double) = 0; protected: - int wallflag[6]; + int nwall; + int wallwhich[6],wallstyle[6]; double coord0[6],epsilon[6],sigma[6],cutoff[6]; - int velflag,wigflag; - double vel[6],amplitude[6]; - double period,omega; + char *varstr[6]; + int varindex[6]; int eflag; double ewall[7],ewall_all[7]; int nlevels_respa; diff --git a/src/fix_wall_harmonic.cpp b/src/fix_wall_harmonic.cpp index d8b18aebd5..4d0660a0f4 100644 --- a/src/fix_wall_harmonic.cpp +++ b/src/fix_wall_harmonic.cpp @@ -24,11 +24,13 @@ FixWallHarmonic::FixWallHarmonic(LAMMPS *lmp, int narg, char **arg) : FixWall(lmp, narg, arg) {} /* ---------------------------------------------------------------------- - interaction of all particles in group with all 6 walls (if defined) + interaction of all particles in group with a wall + m = index of wall coeffs + which = xlo,xhi,ylo,yhi,zlo,zhi error if any particle is on or behind wall ------------------------------------------------------------------------- */ -void FixWallHarmonic::wall_particle(int m, double coord) +void FixWallHarmonic::wall_particle(int m, int which, double coord) { double delta,dr,fwall; @@ -37,8 +39,8 @@ void FixWallHarmonic::wall_particle(int m, double coord) int *mask = atom->mask; int nlocal = atom->nlocal; - int dim = m/2; - int side = m % 2; + int dim = which / 2; + int side = which % 2; if (side == 0) side = -1; int onflag = 0; diff --git a/src/fix_wall_harmonic.h b/src/fix_wall_harmonic.h index 391a2880e3..a5aa575e01 100644 --- a/src/fix_wall_harmonic.h +++ b/src/fix_wall_harmonic.h @@ -28,7 +28,7 @@ class FixWallHarmonic : public FixWall { public: FixWallHarmonic(class LAMMPS *, int, char **); void precompute(int) {} - void wall_particle(int, double); + void wall_particle(int, int, double); private: double offset[6]; diff --git a/src/fix_wall_lj126.cpp b/src/fix_wall_lj126.cpp index 1379676a49..132cea9c0b 100644 --- a/src/fix_wall_lj126.cpp +++ b/src/fix_wall_lj126.cpp @@ -38,11 +38,13 @@ void FixWallLJ126::precompute(int m) } /* ---------------------------------------------------------------------- - interaction of all particles in group with all 6 walls (if defined) + interaction of all particles in group with a wall + m = index of wall coeffs + which = xlo,xhi,ylo,yhi,zlo,zhi error if any particle is on or behind wall ------------------------------------------------------------------------- */ -void FixWallLJ126::wall_particle(int m, double coord) +void FixWallLJ126::wall_particle(int m, int which, double coord) { double delta,rinv,r2inv,r6inv,fwall; @@ -51,8 +53,8 @@ void FixWallLJ126::wall_particle(int m, double coord) int *mask = atom->mask; int nlocal = atom->nlocal; - int dim = m/2; - int side = m % 2; + int dim = which / 2; + int side = which % 2; if (side == 0) side = -1; int onflag = 0; diff --git a/src/fix_wall_lj126.h b/src/fix_wall_lj126.h index 1a4f17db47..eba0ffa3e5 100644 --- a/src/fix_wall_lj126.h +++ b/src/fix_wall_lj126.h @@ -28,7 +28,7 @@ class FixWallLJ126 : public FixWall { public: FixWallLJ126(class LAMMPS *, int, char **); void precompute(int); - void wall_particle(int, double); + void wall_particle(int, int, double); private: double coeff1[6],coeff2[6],coeff3[6],coeff4[6],offset[6]; diff --git a/src/fix_wall_lj93.cpp b/src/fix_wall_lj93.cpp index 99f5f90903..e106ec5e6a 100644 --- a/src/fix_wall_lj93.cpp +++ b/src/fix_wall_lj93.cpp @@ -39,11 +39,13 @@ void FixWallLJ93::precompute(int m) } /* ---------------------------------------------------------------------- - interaction of all particles in group with all 6 walls (if defined) + interaction of all particles in group with a wall + m = index of wall coeffs + which = xlo,xhi,ylo,yhi,zlo,zhi error if any particle is on or behind wall ------------------------------------------------------------------------- */ -void FixWallLJ93::wall_particle(int m, double coord) +void FixWallLJ93::wall_particle(int m, int which, double coord) { double delta,rinv,r2inv,r4inv,r10inv,fwall; @@ -52,8 +54,8 @@ void FixWallLJ93::wall_particle(int m, double coord) int *mask = atom->mask; int nlocal = atom->nlocal; - int dim = m/2; - int side = m % 2; + int dim = which / 2; + int side = which % 2; if (side == 0) side = -1; int onflag = 0; diff --git a/src/fix_wall_lj93.h b/src/fix_wall_lj93.h index 3a6cd77957..78df357c64 100644 --- a/src/fix_wall_lj93.h +++ b/src/fix_wall_lj93.h @@ -28,7 +28,7 @@ class FixWallLJ93 : public FixWall { public: FixWallLJ93(class LAMMPS *, int, char **); void precompute(int); - void wall_particle(int, double); + void wall_particle(int, int, double); private: double coeff1[6],coeff2[6],coeff3[6],coeff4[6],offset[6]; diff --git a/src/fix_wall_reflect.cpp b/src/fix_wall_reflect.cpp index ba9aea7b4a..56bb32e270 100644 --- a/src/fix_wall_reflect.cpp +++ b/src/fix_wall_reflect.cpp @@ -25,6 +25,7 @@ using namespace LAMMPS_NS; +enum{XLO,XHI,YLO,YHI,ZLO,ZHI}; enum{NONE,EDGE,CONSTANT,VARIABLE}; /* ---------------------------------------------------------------------- */ @@ -34,101 +35,48 @@ FixWallReflect::FixWallReflect(LAMMPS *lmp, int narg, char **arg) : { if (narg < 4) error->all("Illegal fix wall/reflect command"); - xloflag = xhiflag = yloflag = yhiflag = zloflag = zhiflag = NONE; - xlostr = xhistr = ylostr = yhistr = zlostr = zhistr = NULL; + // parse args + + nwall = 0; int scaleflag = 1; int iarg = 3; while (iarg < narg) { - if (strcmp(arg[iarg],"xlo") == 0) { + if ((strcmp(arg[iarg],"xlo") == 0) || (strcmp(arg[iarg],"xhi") == 0) || + (strcmp(arg[iarg],"ylo") == 0) || (strcmp(arg[iarg],"yhi") == 0) || + (strcmp(arg[iarg],"zlo") == 0) || (strcmp(arg[iarg],"zhi") == 0)) { if (iarg+2 > narg) error->all("Illegal fix wall/reflect command"); + + int newwall; + if (strcmp(arg[iarg],"xlo") == 0) newwall = XLO; + else if (strcmp(arg[iarg],"xhi") == 0) newwall = XHI; + else if (strcmp(arg[iarg],"ylo") == 0) newwall = YLO; + else if (strcmp(arg[iarg],"yhi") == 0) newwall = YHI; + else if (strcmp(arg[iarg],"zlo") == 0) newwall = ZLO; + else if (strcmp(arg[iarg],"zhi") == 0) newwall = ZHI; + + for (int m = 0; m < nwall; m++) + if (newwall == wallwhich[m]) + error->all("Wall defined twice in fix wall/reflect command"); + + wallwhich[nwall] = newwall; if (strcmp(arg[iarg+1],"EDGE") == 0) { - xloflag = EDGE; - xlo = domain->boxlo[0]; + wallstyle[nwall] = EDGE; + int dim = wallwhich[nwall] / 2; + int side = wallwhich[nwall] % 2; + if (side == 0) coord0[nwall] = domain->boxlo[dim]; + else coord0[nwall] = domain->boxhi[dim]; } else if (strstr(arg[iarg+1],"v_") == arg[iarg+1]) { - xloflag = VARIABLE; + wallstyle[nwall] = VARIABLE; int n = strlen(&arg[iarg+1][2]) + 1; - xlostr = new char[n]; - strcpy(xlostr,&arg[iarg+1][2]); + varstr[nwall] = new char[n]; + strcpy(varstr[nwall],&arg[iarg+1][2]); } else { - xloflag = CONSTANT; - xlo = atof(arg[iarg+1]); - } - iarg += 2; - } else if (strcmp(arg[iarg],"xhi") == 0) { - if (iarg+2 > narg) error->all("Illegal fix wall/reflect command"); - if (strcmp(arg[iarg+1],"EDGE") == 0) { - xhiflag = EDGE; - xhi = domain->boxhi[0]; - } else if (strstr(arg[iarg+1],"v_") == arg[iarg+1]) { - xhiflag = VARIABLE; - int n = strlen(&arg[iarg+1][2]) + 1; - xhistr = new char[n]; - strcpy(xhistr,&arg[iarg+1][2]); - } else { - xhiflag = CONSTANT; - xhi = atof(arg[iarg+1]); - } - iarg += 2; - } else if (strcmp(arg[iarg],"ylo") == 0) { - if (iarg+2 > narg) error->all("Illegal fix wall/reflect command"); - if (strcmp(arg[iarg+1],"EDGE") == 0) { - yloflag = EDGE; - ylo = domain->boxlo[1]; - } else if (strstr(arg[iarg+1],"v_") == arg[iarg+1]) { - yloflag = VARIABLE; - int n = strlen(&arg[iarg+1][2]) + 1; - ylostr = new char[n]; - strcpy(ylostr,&arg[iarg+1][2]); - } else { - yloflag = CONSTANT; - ylo = atof(arg[iarg+1]); - } - iarg += 2; - } else if (strcmp(arg[iarg],"yhi") == 0) { - if (iarg+2 > narg) error->all("Illegal fix wall/reflect command"); - if (strcmp(arg[iarg+1],"EDGE") == 0) { - yhiflag = EDGE; - yhi = domain->boxhi[1]; - } else if (strstr(arg[iarg+1],"v_") == arg[iarg+1]) { - yhiflag = VARIABLE; - int n = strlen(&arg[iarg+1][2]) + 1; - yhistr = new char[n]; - strcpy(yhistr,&arg[iarg+1][2]); - } else { - yhiflag = CONSTANT; - yhi = atof(arg[iarg+1]); - } - iarg += 2; - } else if (strcmp(arg[iarg],"zlo") == 0) { - if (iarg+2 > narg) error->all("Illegal fix wall/reflect command"); - if (strcmp(arg[iarg+1],"EDGE") == 0) { - zloflag = EDGE; - zlo = domain->boxlo[2]; - } else if (strstr(arg[iarg+1],"v_") == arg[iarg+1]) { - zloflag = VARIABLE; - int n = strlen(&arg[iarg+1][2]) + 1; - zlostr = new char[n]; - strcpy(zlostr,&arg[iarg+1][2]); - } else { - zloflag = CONSTANT; - zlo = atof(arg[iarg+1]); - } - iarg += 2; - } else if (strcmp(arg[iarg],"zhi") == 0) { - if (iarg+2 > narg) error->all("Illegal fix wall/reflect command"); - if (strcmp(arg[iarg+1],"EDGE") == 0) { - zhiflag = EDGE; - zhi = domain->boxhi[2]; - } else if (strstr(arg[iarg+1],"v_") == arg[iarg+1]) { - zhiflag = VARIABLE; - int n = strlen(&arg[iarg+1][2]) + 1; - zhistr = new char[n]; - strcpy(zhistr,&arg[iarg+1][2]); - } else { - zhiflag = CONSTANT; - zhi = atof(arg[iarg+1]); + wallstyle[nwall] = CONSTANT; + coord0[nwall] = atof(arg[iarg+1]); } + + nwall++; iarg += 2; } else if (strcmp(arg[iarg],"units") == 0) { @@ -140,15 +88,32 @@ FixWallReflect::FixWallReflect(LAMMPS *lmp, int narg, char **arg) : } else error->all("Illegal fix wall/reflect command"); } - // setup scaling if any wall positions were set as CONSTANT - // apply scaling factors to wall positions + // error check - if (xloflag == CONSTANT || xhiflag == CONSTANT || - yloflag == CONSTANT || yhiflag == CONSTANT || - zloflag == CONSTANT || zhiflag == CONSTANT) { + if (nwall == 0) error->all("Illegal fix wall command"); + for (int m = 0; m < nwall; m++) { + if ((wallwhich[m] == XLO || wallwhich[m] == XHI) && domain->xperiodic) + error->all("Cannot use fix wall/reflect in periodic dimension"); + if ((wallwhich[m] == YLO || wallwhich[m] == YHI) && domain->yperiodic) + error->all("Cannot use fix wall/reflect in periodic dimension"); + if ((wallwhich[m] == ZLO || wallwhich[m] == ZHI) && domain->zperiodic) + error->all("Cannot use fix wall/reflect in periodic dimension"); + } + + for (int m = 0; m < nwall; m++) + if ((wallwhich[m] == ZLO || wallwhich[m] == ZHI) && domain->dimension == 2) + error->all("Cannot use fix wall/reflect zlo/zhi for a 2d simulation"); + + // scale coord for CONSTANT walls + + int flag = 0; + for (int m = 0; m < nwall; m++) + if (wallstyle[m] == CONSTANT) flag = 1; + + if (flag) { if (scaleflag && domain->lattice == NULL) - error->all("Use of fix wall/reflect with undefined lattice"); + error->all("Use of fix wall with undefined lattice"); double xscale,yscale,zscale; if (scaleflag) { @@ -158,37 +123,27 @@ FixWallReflect::FixWallReflect(LAMMPS *lmp, int narg, char **arg) : } else xscale = yscale = zscale = 1.0; - if (xloflag == CONSTANT) xlo *= xscale; - if (xhiflag == CONSTANT) xhi *= xscale; - if (yloflag == CONSTANT) ylo *= xscale; - if (yhiflag == CONSTANT) yhi *= xscale; - if (zloflag == CONSTANT) zlo *= xscale; - if (zhiflag == CONSTANT) zhi *= xscale; + double scale; + for (int m = 0; m < nwall; m++) { + if (wallwhich[m] < YLO) scale = xscale; + else if (wallwhich[m] < ZLO) scale = yscale; + else scale = zscale; + if (wallstyle[m] == CONSTANT) coord0[m] *= scale; + } } - // error checks + // set time_depend if any wall positions are variable - if (!xloflag && !xhiflag && !yloflag && !yhiflag && !zloflag && !zhiflag) - error->all("Illegal fix wall/reflect command"); - - if ((xloflag || xhiflag) && domain->xperiodic) - error->all("Cannot use wall in periodic dimension"); - if ((yloflag || yhiflag) && domain->yperiodic) - error->all("Cannot use wall in periodic dimension"); - if ((zloflag || zhiflag) && domain->zperiodic) - error->all("Cannot use wall in periodic dimension"); + for (int m = 0; m < nwall; m++) + if (wallstyle[m] == VARIABLE) time_depend = 1; } /* ---------------------------------------------------------------------- */ FixWallReflect::~FixWallReflect() { - delete [] xlostr; - delete [] xhistr; - delete [] ylostr; - delete [] yhistr; - delete [] zlostr; - delete [] zhistr; + for (int m = 0; m < nwall; m++) + if (wallstyle[m] == VARIABLE) delete [] varstr[m]; } /* ---------------------------------------------------------------------- */ @@ -205,46 +160,12 @@ int FixWallReflect::setmask() void FixWallReflect::init() { - if (xlostr) { - xlovar = input->variable->find(xlostr); - if (xlovar < 0) - error->all("Variable name for fix wall/relect does not exist"); - if (!input->variable->equalstyle(xlovar)) - error->all("Variable for fix wall/reflect is invalid style"); - } - if (xhistr) { - xhivar = input->variable->find(xhistr); - if (xhivar < 0) - error->all("Variable name for fix wall/relect does not exist"); - if (!input->variable->equalstyle(xhivar)) - error->all("Variable for fix wall/reflect is invalid style"); - } - if (ylostr) { - ylovar = input->variable->find(ylostr); - if (ylovar < 0) - error->all("Variable name for fix wall/relect does not exist"); - if (!input->variable->equalstyle(ylovar)) - error->all("Variable for fix wall/reflect is invalid style"); - } - if (yhistr) { - yhivar = input->variable->find(yhistr); - if (yhivar < 0) - error->all("Variable name for fix wall/relect does not exist"); - if (!input->variable->equalstyle(yhivar)) - error->all("Variable for fix wall/reflect is invalid style"); - } - if (zlostr) { - zlovar = input->variable->find(zlostr); - if (zlovar < 0) - error->all("Variable name for fix wall/relect does not exist"); - if (!input->variable->equalstyle(zlovar)) - error->all("Variable for fix wall/reflect is invalid style"); - } - if (zhistr) { - zhivar = input->variable->find(zhistr); - if (zhivar < 0) - error->all("Variable name for fix wall/relect does not exist"); - if (!input->variable->equalstyle(zhivar)) + for (int m = 0; m < nwall; m++) { + if (wallstyle[m] != VARIABLE) continue; + varindex[m] = input->variable->find(varstr[m]); + if (varindex[m] < 0) + error->all("Variable name for fix wall/reflect does not exist"); + if (!input->variable->equalstyle(varindex[m])) error->all("Variable for fix wall/reflect is invalid style"); } @@ -261,44 +182,35 @@ void FixWallReflect::init() void FixWallReflect::post_integrate() { - if (xloflag == VARIABLE) xlo = input->variable->compute_equal(xlovar); - if (xhiflag == VARIABLE) xhi = input->variable->compute_equal(xhivar); - if (yloflag == VARIABLE) ylo = input->variable->compute_equal(ylovar); - if (yhiflag == VARIABLE) yhi = input->variable->compute_equal(yhivar); - if (zloflag == VARIABLE) zlo = input->variable->compute_equal(zlovar); - if (zhiflag == VARIABLE) zhi = input->variable->compute_equal(zhivar); + int i,dim,side; + double coord; double **x = atom->x; double **v = atom->v; int *mask = atom->mask; int nlocal = atom->nlocal; - for (int i = 0; i < nlocal; i++) { - if (mask[i] & groupbit) { - if (xloflag && x[i][0] < xlo) { - x[i][0] = xlo + (xlo - x[i][0]); - v[i][0] = -v[i][0]; + for (int m = 0; m < nwall; m++) { + if (wallstyle[m] == VARIABLE) + coord = input->variable->compute_equal(varindex[m]); + else coord = coord0[m]; + + dim = wallwhich[m] / 2; + side = wallwhich[m] % 2; + + for (i = 0; i < nlocal; i++) + if (mask[i] & groupbit) { + if (side == 0) { + if (x[i][dim] < coord) { + x[i][dim] = coord + (coord - x[i][dim]); + v[i][dim] = -v[i][dim]; + } + } else { + if (x[i][0] > coord) { + x[i][dim] = coord - (x[i][dim] - coord); + v[i][dim] = -v[i][dim]; + } + } } - if (xhiflag && x[i][0] > xhi) { - x[i][0] = xhi - (x[i][0] - xhi); - v[i][0] = -v[i][0]; - } - if (yloflag && x[i][1] < ylo) { - x[i][1] = ylo + (ylo - x[i][1]); - v[i][1] = -v[i][1]; - } - if (yhiflag && x[i][1] > yhi) { - x[i][1] = yhi - (x[i][1] - yhi); - v[i][1] = -v[i][1]; - } - if (zloflag && x[i][2] < zlo) { - x[i][2] = zlo + (zlo - x[i][2]); - v[i][2] = -v[i][2]; - } - if (zhiflag && x[i][2] > zhi) { - x[i][2] = zhi - (x[i][2] - zhi); - v[i][2] = -v[i][2]; - } - } } } diff --git a/src/fix_wall_reflect.h b/src/fix_wall_reflect.h index f0f7ef41fb..b0bda7b465 100644 --- a/src/fix_wall_reflect.h +++ b/src/fix_wall_reflect.h @@ -33,10 +33,11 @@ class FixWallReflect : public Fix { void post_integrate(); private: - int xloflag,xhiflag,yloflag,yhiflag,zloflag,zhiflag; - char *xlostr,*xhistr,*ylostr,*yhistr,*zlostr,*zhistr; - int xlovar,xhivar,ylovar,yhivar,zlovar,zhivar; - double xlo,xhi,ylo,yhi,zlo,zhi; + int nwall; + int wallwhich[6],wallstyle[6]; + double coord0[6]; + char *varstr[6]; + int varindex[6]; }; } diff --git a/src/variable.cpp b/src/variable.cpp index a943000735..5e1aba8270 100644 --- a/src/variable.cpp +++ b/src/variable.cpp @@ -43,11 +43,18 @@ using namespace LAMMPS_NS; enum{INDEX,LOOP,WORLD,UNIVERSE,ULOOP,STRING,EQUAL,ATOM}; enum{ARG,OP}; + +// customize by adding a math function + enum{DONE,ADD,SUBTRACT,MULTIPLY,DIVIDE,CARAT,UNARY, EQ,NE,LT,LE,GT,GE,AND,OR, SQRT,EXP,LN,LOG,SIN,COS,TAN,ASIN,ACOS,ATAN,ATAN2, - RANDOM,NORMAL,CEIL,FLOOR,ROUND, + RANDOM,NORMAL,CEIL,FLOOR,ROUND,RAMP,STAGGER,LOGFREQ, + VLINEAR,SWIGGLE,CWIGGLE, VALUE,ATOMARRAY,TYPEARRAY,INTARRAY}; + +// customize by adding a special function + enum{SUM,XMIN,XMAX,AVE,TRAP}; #define INVOKED_SCALAR 1 @@ -83,6 +90,8 @@ Variable::Variable(LAMMPS *lmp) : Pointers(lmp) precedence[MULTIPLY] = precedence[DIVIDE] = 6; precedence[CARAT] = 7; precedence[UNARY] = 8; + + PI = 4.0*atan(1.0); } /* ---------------------------------------------------------------------- */ @@ -595,6 +604,7 @@ void Variable::copy(int narg, char **from, char **to) sqrt(x),exp(x),ln(x),log(x), sin(x),cos(x),tan(x),asin(x),atan2(y,x),... group function = count(group), mass(group), xcm(group,x), ... + special function = sum(x),min(x), ... atom value = x[i], y[i], vx[i], ... atom vector = x, y, vx, ... compute = c_ID, c_ID[i], c_ID[i][j] @@ -686,10 +696,10 @@ double Variable::evaluate(char *str, Tree **tree) // ---------------- // letter: c_ID, c_ID[], c_ID[][], f_ID, f_ID[], f_ID[][], - // v_name, v_name[], exp(), xcm(,), x, x[], vol + // v_name, v_name[], exp(), xcm(,), x, x[], PI, vol // ---------------- - } else if (islower(onechar)) { + } else if (isalpha(onechar)) { if (expect == OP) error->all("Invalid syntax in variable formula"); expect = OP; @@ -1134,7 +1144,8 @@ double Variable::evaluate(char *str, Tree **tree) delete [] id; // ---------------- - // math/group/special function or atom value/vector or thermo keyword + // math/group/special function or atom value/vector or + // constant or thermo keyword // ---------------- } else { @@ -1183,6 +1194,20 @@ double Variable::evaluate(char *str, Tree **tree) atom_vector(word,tree,treestack,ntreestack); + // ---------------- + // constant + // ---------------- + + } else if (is_constant(word)) { + value1 = constant(word); + if (tree) { + Tree *newtree = new Tree(); + newtree->type = VALUE; + newtree->value = value1; + newtree->left = newtree->middle = newtree->right = NULL; + treestack[ntreestack++] = newtree; + } else argstack[nargstack++] = value1; + // ---------------- // thermo keyword // ---------------- @@ -1350,7 +1375,9 @@ double Variable::evaluate(char *str, Tree **tree) process an evaulation tree customize by adding a math function: sqrt(),exp(),ln(),log(),sin(),cos(),tan(),asin(),acos(),atan(), - atan2(y,x),random(x,y,z),normal(x,y,z),ceil(),floor(),round() + atan2(y,x),random(x,y,z),normal(x,y,z),ceil(),floor(),round(), + ramp(x,y),stagger(x,y),logfreq(x,y,z), + vlinear(x,y),swiggle(x,y,z),cwiggle(x,y,z) ---------------------------------------------------------------------- */ double Variable::eval_tree(Tree *tree, int i) @@ -1368,12 +1395,12 @@ double Variable::eval_tree(Tree *tree, int i) return eval_tree(tree->left,i) * eval_tree(tree->right,i); if (tree->type == DIVIDE) { double denom = eval_tree(tree->right,i); - if (denom == 0.0) error->all("Divide by 0 in variable formula"); + if (denom == 0.0) error->one("Divide by 0 in variable formula"); return eval_tree(tree->left,i) / denom; } if (tree->type == CARAT) { double exponent = eval_tree(tree->right,i); - if (exponent == 0.0) error->all("Power by 0 in variable formula"); + if (exponent == 0.0) error->one("Power by 0 in variable formula"); return pow(eval_tree(tree->left,i),exponent); } if (tree->type == UNARY) @@ -1416,7 +1443,7 @@ double Variable::eval_tree(Tree *tree, int i) if (tree->type == SQRT) { double arg = eval_tree(tree->left,i); - if (arg < 0.0) error->all("Sqrt of negative value in variable formula"); + if (arg < 0.0) error->one("Sqrt of negative value in variable formula"); return sqrt(arg); } if (tree->type == EXP) @@ -1424,13 +1451,13 @@ double Variable::eval_tree(Tree *tree, int i) if (tree->type == LN) { double arg = eval_tree(tree->left,i); if (arg <= 0.0) - error->all("Log of zero/negative value in variable formula"); + error->one("Log of zero/negative value in variable formula"); return log(arg); } if (tree->type == LOG) { double arg = eval_tree(tree->left,i); if (arg <= 0.0) - error->all("Log of zero/negative value in variable formula"); + error->one("Log of zero/negative value in variable formula"); return log10(arg); } @@ -1444,13 +1471,13 @@ double Variable::eval_tree(Tree *tree, int i) if (tree->type == ASIN) { double arg = eval_tree(tree->left,i); if (arg < -1.0 || arg > 1.0) - error->all("Arcsin of invalid value in variable formula"); + error->one("Arcsin of invalid value in variable formula"); return asin(arg); } if (tree->type == ACOS) { double arg = eval_tree(tree->left,i); if (arg < -1.0 || arg > 1.0) - error->all("Arccos of invalid value in variable formula"); + error->one("Arccos of invalid value in variable formula"); return acos(arg); } if (tree->type == ATAN) @@ -1463,6 +1490,7 @@ double Variable::eval_tree(Tree *tree, int i) double upper = eval_tree(tree->middle,i); if (randomatom == NULL) { int seed = static_cast<int> (eval_tree(tree->right,i)); + if (seed <= 0) error->one("Invalid math function in variable formula"); randomatom = new RanMars(lmp,seed+me); } return randomatom->uniform()*(upper-lower)+lower; @@ -1470,11 +1498,13 @@ double Variable::eval_tree(Tree *tree, int i) if (tree->type == NORMAL) { double mu = eval_tree(tree->left,i); double sigma = eval_tree(tree->middle,i); + if (sigma < 0.0) error->one("Invalid math function in variable formula"); if (randomatom == NULL) { int seed = static_cast<int> (eval_tree(tree->right,i)); + if (seed <= 0) error->one("Invalid math function in variable formula"); randomatom = new RanMars(lmp,seed+me); } - return randomatom->gaussian()*sigma + mu; + return mu + sigma*randomatom->gaussian(); } if (tree->type == CEIL) @@ -1484,6 +1514,76 @@ double Variable::eval_tree(Tree *tree, int i) if (tree->type == ROUND) return MYROUND(eval_tree(tree->left,i)); + if (tree->type == RAMP) { + double arg1 = eval_tree(tree->left,i); + double arg2 = eval_tree(tree->right,i); + double delta = update->ntimestep - update->beginstep; + delta /= update->endstep - update->beginstep; + double arg = arg1 + delta*(arg2-arg1); + return arg; + } + + if (tree->type == STAGGER) { + int ivalue1 = static_cast<int> (eval_tree(tree->left,i)); + int ivalue2 = static_cast<int> (eval_tree(tree->right,i)); + if (ivalue1 <= 0 || ivalue2 <= 0 || ivalue1 <= ivalue2) + error->one("Invalid math function in variable formula"); + int lower = update->ntimestep/ivalue1 * ivalue1; + int delta = update->ntimestep - lower; + double arg; + if (delta < ivalue2) arg = lower+ivalue2; + else arg = lower+ivalue1; + return arg; + } + + if (tree->type == LOGFREQ) { + int ivalue1 = static_cast<int> (eval_tree(tree->left,i)); + int ivalue2 = static_cast<int> (eval_tree(tree->middle,i)); + int ivalue3 = static_cast<int> (eval_tree(tree->right,i)); + if (ivalue1 <= 0 || ivalue2 <= 0 || ivalue3 <= 0 || ivalue2 >= ivalue3) + error->one("Invalid math function in variable formula"); + double arg; + if (update->ntimestep < ivalue1) arg = ivalue1; + else { + int lower = ivalue1; + while (update->ntimestep >= ivalue3*lower) lower *= ivalue3; + int multiple = update->ntimestep/lower; + if (multiple < ivalue2) arg = (multiple+1)*lower; + else arg = lower*ivalue3; + } + return arg; + } + + if (tree->type == VLINEAR) { + double arg1 = eval_tree(tree->left,i); + double arg2 = eval_tree(tree->right,i); + double delta = update->ntimestep - update->beginstep; + double arg = arg1 + arg2*delta*update->dt; + return arg; + } + + if (tree->type == SWIGGLE) { + double arg1 = eval_tree(tree->left,i); + double arg2 = eval_tree(tree->middle,i); + double arg3 = eval_tree(tree->right,i); + if (arg3 == 0.0) error->one("Invalid math function in variable formula"); + double delta = update->ntimestep - update->beginstep; + double omega = 2.0*PI/arg3; + double arg = arg1 + arg2*sin(omega*delta*update->dt); + return arg; + } + + if (tree->type == CWIGGLE) { + double arg1 = eval_tree(tree->left,i); + double arg2 = eval_tree(tree->middle,i); + double arg3 = eval_tree(tree->right,i); + if (arg3 == 0.0) error->one("Invalid math function in variable formula"); + double delta = update->ntimestep - update->beginstep; + double omega = 2.0*PI/arg3; + double arg = arg1 + arg2*(1.0-cos(omega*delta*update->dt)); + return arg; + } + return 0.0; } @@ -1563,9 +1663,11 @@ int Variable::int_between_brackets(char *&ptr) word = math function contents = str between parentheses with one,two,three args return 0 if not a match, 1 if successfully processed - customize by adding a math function in 2 places: + customize by adding a math function: sqrt(),exp(),ln(),log(),sin(),cos(),tan(),asin(),acos(),atan(), - atan2(y,x),random(x,y,z),normal(x,y,z),ceil(),floor(),round() + atan2(y,x),random(x,y,z),normal(x,y,z),ceil(),floor(),round(), + ramp(x,y),stagger(x,y),logfreq(x,y,z), + vlinear(x,y),swiggle(x,y,z),cwiggle(x,y,z) ------------------------------------------------------------------------- */ int Variable::math_function(char *word, char *contents, Tree **tree, @@ -1581,7 +1683,10 @@ int Variable::math_function(char *word, char *contents, Tree **tree, strcmp(word,"acos") && strcmp(word,"atan") && strcmp(word,"atan2") && strcmp(word,"random") && strcmp(word,"normal") && strcmp(word,"ceil") && - strcmp(word,"floor") && strcmp(word,"round")) + strcmp(word,"floor") && strcmp(word,"round") && + strcmp(word,"ramp") && strcmp(word,"stagger") && + strcmp(word,"logfreq") && strcmp(word,"vlinear") && + strcmp(word,"swiggle") && strcmp(word,"cwiggle")) return 0; // parse contents for arg1,arg2,arg3 separated by commas @@ -1728,6 +1833,7 @@ int Variable::math_function(char *word, char *contents, Tree **tree, else { if (randomequal == NULL) { int seed = static_cast<int> (value3); + if (seed <= 0) error->all("Invalid math function in variable formula"); randomequal = new RanMars(lmp,seed); } argstack[nargstack++] = randomequal->uniform()*(value2-value1) + value1; @@ -1736,11 +1842,14 @@ int Variable::math_function(char *word, char *contents, Tree **tree, if (narg != 3) error->all("Invalid math function in variable formula"); if (tree) newtree->type = NORMAL; else { + if (value2 < 0.0) + error->all("Invalid math function in variable formula"); if (randomequal == NULL) { int seed = static_cast<int> (value3); + if (seed <= 0) error->all("Invalid math function in variable formula"); randomequal = new RanMars(lmp,seed); } - argstack[nargstack++] = randomequal->gaussian()*value2 + value1; + argstack[nargstack++] = value1 + value2*randomequal->gaussian(); } } else if (strcmp(word,"ceil") == 0) { @@ -1757,6 +1866,94 @@ int Variable::math_function(char *word, char *contents, Tree **tree, if (narg != 1) error->all("Invalid math function in variable formula"); if (tree) newtree->type = ROUND; else argstack[nargstack++] = MYROUND(value1); + + } else if (strcmp(word,"ramp") == 0) { + if (narg != 2) error->all("Invalid math function in variable formula"); + if (update->whichflag == 0) + error->all("Cannot use ramp in variable formula between runs"); + if (tree) newtree->type = RAMP; + else { + double delta = update->ntimestep - update->beginstep; + delta /= update->endstep - update->beginstep; + double value = value1 + delta*(value2-value1); + argstack[nargstack++] = value; + } + + } else if (strcmp(word,"stagger") == 0) { + if (narg != 2) error->all("Invalid math function in variable formula"); + if (tree) newtree->type = STAGGER; + else { + int ivalue1 = static_cast<int> (value1); + int ivalue2 = static_cast<int> (value2); + if (ivalue1 <= 0 || ivalue2 <= 0 || ivalue1 <= ivalue2) + error->all("Invalid math function in variable formula"); + int lower = update->ntimestep/ivalue1 * ivalue1; + int delta = update->ntimestep - lower; + double value; + if (delta < ivalue2) value = lower+ivalue2; + else value = lower+ivalue1; + argstack[nargstack++] = value; + } + + } else if (strcmp(word,"logfreq") == 0) { + if (narg != 3) error->all("Invalid math function in variable formula"); + if (tree) newtree->type = LOGFREQ; + else { + int ivalue1 = static_cast<int> (value1); + int ivalue2 = static_cast<int> (value2); + int ivalue3 = static_cast<int> (value3); + if (ivalue1 <= 0 || ivalue2 <= 0 || ivalue3 <= 0 || ivalue2 >= ivalue3) + error->all("Invalid math function in variable formula"); + double value; + if (update->ntimestep < ivalue1) value = ivalue1; + else { + int lower = ivalue1; + while (update->ntimestep >= ivalue3*lower) lower *= ivalue3; + int multiple = update->ntimestep/lower; + if (multiple < ivalue2) value = (multiple+1)*lower; + else value = lower*ivalue3; + } + argstack[nargstack++] = value; + } + + } else if (strcmp(word,"vlinear") == 0) { + if (narg != 2) error->all("Invalid math function in variable formula"); + if (update->whichflag == 0) + error->all("Cannot use vlinear in variable formula between runs"); + if (tree) newtree->type = VLINEAR; + else { + double delta = update->ntimestep - update->beginstep; + double value = value1 + value2*delta*update->dt; + argstack[nargstack++] = value; + } + + } else if (strcmp(word,"swiggle") == 0) { + if (narg != 3) error->all("Invalid math function in variable formula"); + if (update->whichflag == 0) + error->all("Cannot use swiggle in variable formula between runs"); + if (tree) newtree->type = CWIGGLE; + else { + if (value3 == 0.0) + error->all("Invalid math function in variable formula"); + double delta = update->ntimestep - update->beginstep; + double omega = 2.0*PI/value3; + double value = value1 + value2*sin(omega*delta*update->dt); + argstack[nargstack++] = value; + } + + } else if (strcmp(word,"cwiggle") == 0) { + if (narg != 3) error->all("Invalid math function in variable formula"); + if (update->whichflag == 0) + error->all("Cannot use cwiggle in variable formula between runs"); + if (tree) newtree->type = CWIGGLE; + else { + if (value3 == 0.0) + error->all("Invalid math function in variable formula"); + double delta = update->ntimestep - update->beginstep; + double omega = 2.0*PI/value3; + double value = value1 + value2*(1.0-cos(omega*delta*update->dt)); + argstack[nargstack++] = value; + } } delete [] arg1; @@ -1772,7 +1969,7 @@ int Variable::math_function(char *word, char *contents, Tree **tree, word = group function contents = str between parentheses with one,two,three args return 0 if not a match, 1 if successfully processed - customize by adding a group function in 2 places with optional region arg: + customize by adding a group function with optional region arg: count(group),mass(group),charge(group), xcm(group,dim),vcm(group,dim),fcm(group,dim), bound(group,xmin),gyration(group),ke(group),angmom(group), @@ -2017,9 +2214,8 @@ int Variable::region_function(char *id) word = special function contents = str between parentheses with one,two,three args return 0 if not a match, 1 if successfully processed - customize by adding a special function in 2 places - ramp(x,y),stagger(x,y),logfreq(x,y,z),sum(x),min(x),max(x), - ave(x),trap(x) + customize by adding a special function: + sum(x),min(x),max(x),ave(x),trap(x) ------------------------------------------------------------------------- */ int Variable::special_function(char *word, char *contents, Tree **tree, @@ -2028,9 +2224,7 @@ int Variable::special_function(char *word, char *contents, Tree **tree, { // word not a match to any special function - if (strcmp(word,"ramp") && strcmp(word,"stagger") && - strcmp(word,"logfreq") && strcmp(word,"sum") && - strcmp(word,"min") && strcmp(word,"max") && + if (strcmp(word,"sum") && strcmp(word,"min") && strcmp(word,"max") && strcmp(word,"ave") && strcmp(word,"trap")) return 0; @@ -2066,163 +2260,122 @@ int Variable::special_function(char *word, char *contents, Tree **tree, // match word to special function - double value; + int method; + if (strcmp(word,"sum") == 0) method = SUM; + else if (strcmp(word,"min") == 0) method = XMIN; + else if (strcmp(word,"max") == 0) method = XMAX; + else if (strcmp(word,"ave") == 0) method = AVE; + else if (strcmp(word,"trap") == 0) method = TRAP; - if (strcmp(word,"ramp") == 0) { - if (narg != 2) error->all("Invalid special function in variable formula"); - if (update->whichflag == 0) - error->all("Cannot use ramp in variable formula between runs"); - double value1 = numeric(arg1); - double value2 = numeric(arg2); - double delta = update->ntimestep - update->beginstep; - delta /= update->endstep - update->beginstep; - value = value1 + delta*(value2-value1); + if (narg != 1) error->all("Invalid special function in variable formula"); + + Compute *compute = NULL; + Fix *fix = NULL; + int index,nvec,nstride; - } else if (strcmp(word,"stagger") == 0) { - if (narg != 2) error->all("Invalid special function in variable formula"); - int ivalue1 = inumeric(arg1); - int ivalue2 = inumeric(arg2); - if (ivalue1 <= 0 || ivalue2 <= 0 || ivalue1 <= ivalue2) - error->all("Invalid special function in variable formula"); - int lower = update->ntimestep/ivalue1 * ivalue1; - int delta = update->ntimestep - lower; - if (delta < ivalue2) value = lower+ivalue2; - else value = lower+ivalue1; + if (strstr(arg1,"c_") == arg1) { + ptr1 = strchr(arg1,'['); + if (ptr1) { + ptr2 = ptr1; + index = int_between_brackets(ptr2); + *ptr1 = '\0'; + } else index = 0; - } else if (strcmp(word,"logfreq") == 0) { - if (narg != 3) error->all("Invalid special function in variable formula"); - int ivalue1 = inumeric(arg1); - int ivalue2 = inumeric(arg2); - int ivalue3 = inumeric(arg3); - if (ivalue1 <= 0 || ivalue2 <= 0 || ivalue3 <= 0 || ivalue2 >= ivalue3) - error->all("Invalid special function in variable formula"); - if (update->ntimestep < ivalue1) value = ivalue1; - else { - int lower = ivalue1; - while (update->ntimestep >= ivalue3*lower) lower *= ivalue3; - int multiple = update->ntimestep/lower; - if (multiple < ivalue2) value = (multiple+1)*lower; - else value = lower*ivalue3; - } - - } else { - if (narg != 1) error->all("Invalid special function in variable formula"); - - int method; - if (strcmp(word,"sum") == 0) method = SUM; - else if (strcmp(word,"min") == 0) method = XMIN; - else if (strcmp(word,"max") == 0) method = XMAX; - else if (strcmp(word,"ave") == 0) method = AVE; - else if (strcmp(word,"trap") == 0) method = TRAP; - - Compute *compute = NULL; - Fix *fix = NULL; - int index,nvec,nstride; - - if (strstr(arg1,"c_") == arg1) { - ptr1 = strchr(arg1,'['); - if (ptr1) { - ptr2 = ptr1; - index = int_between_brackets(ptr2); - *ptr1 = '\0'; - } else index = 0; - - int icompute = modify->find_compute(&arg1[2]); - if (icompute < 0) error->all("Invalid compute ID in variable formula"); - compute = modify->compute[icompute]; - if (index == 0 && compute->vector_flag) { - if (update->whichflag == 0) { - if (compute->invoked_vector != update->ntimestep) - error->all("Compute used in variable between runs is not current"); - } else if (!(compute->invoked_flag & INVOKED_VECTOR)) { - compute->compute_vector(); - compute->invoked_flag |= INVOKED_VECTOR; - } - nvec = compute->size_vector; - nstride = 1; - } else if (index && compute->array_flag) { - if (index > compute->size_array_cols) - error->all("Variable formula compute array " - "is accessed out-of-range"); - if (update->whichflag == 0) { - if (compute->invoked_array != update->ntimestep) - error->all("Compute used in variable between runs is not current"); - } else if (!(compute->invoked_flag & INVOKED_ARRAY)) { - compute->compute_array(); - compute->invoked_flag |= INVOKED_ARRAY; - } - nvec = compute->size_array_rows; - nstride = compute->size_array_cols; - } else error->all("Mismatched compute in variable formula"); - - } else if (strstr(arg1,"f_") == arg1) { - ptr1 = strchr(arg1,'['); - if (ptr1) { - ptr2 = ptr1; - index = int_between_brackets(ptr2); - *ptr1 = '\0'; - } else index = 0; - - int ifix = modify->find_fix(&arg1[2]); - if (ifix < 0) error->all("Invalid fix ID in variable formula"); - fix = modify->fix[ifix]; - if (index == 0 && fix->vector_flag) { - if (update->whichflag > 0 && update->ntimestep % fix->global_freq) - error->all("Fix in variable not computed at compatible time"); - nvec = fix->size_vector; - nstride = 1; - } else if (index && fix->array_flag) { - if (index > fix->size_array_cols) - error->all("Variable formula fix array is accessed out-of-range"); - if (update->whichflag > 0 && update->ntimestep % fix->global_freq) - error->all("Fix in variable not computed at compatible time"); - nvec = fix->size_array_rows; - nstride = fix->size_array_cols; - } else error->all("Mismatched fix in variable formula"); - - } else error->all("Invalid special function in variable formula"); + int icompute = modify->find_compute(&arg1[2]); + if (icompute < 0) error->all("Invalid compute ID in variable formula"); + compute = modify->compute[icompute]; + if (index == 0 && compute->vector_flag) { + if (update->whichflag == 0) { + if (compute->invoked_vector != update->ntimestep) + error->all("Compute used in variable between runs is not current"); + } else if (!(compute->invoked_flag & INVOKED_VECTOR)) { + compute->compute_vector(); + compute->invoked_flag |= INVOKED_VECTOR; + } + nvec = compute->size_vector; + nstride = 1; + } else if (index && compute->array_flag) { + if (index > compute->size_array_cols) + error->all("Variable formula compute array " + "is accessed out-of-range"); + if (update->whichflag == 0) { + if (compute->invoked_array != update->ntimestep) + error->all("Compute used in variable between runs is not current"); + } else if (!(compute->invoked_flag & INVOKED_ARRAY)) { + compute->compute_array(); + compute->invoked_flag |= INVOKED_ARRAY; + } + nvec = compute->size_array_rows; + nstride = compute->size_array_cols; + } else error->all("Mismatched compute in variable formula"); - value = 0.0; - if (method == XMIN) value = BIG; - if (method == XMAX) value = -BIG; - - if (compute) { - double *vec; - if (index) vec = &compute->array[0][index]; - else vec = compute->vector; - - int j = 0; - for (int i = 0; i < nvec; i++) { - if (method == SUM) value += vec[j]; - else if (method == XMIN) value = MIN(value,vec[j]); - else if (method == XMAX) value = MAX(value,vec[j]); - else if (method == AVE) value += vec[j]; - else if (method == TRAP) { - if (i > 0 && i < nvec-1) value += vec[j]; - else value += 0.5*vec[j]; - } - j += nstride; + } else if (strstr(arg1,"f_") == arg1) { + ptr1 = strchr(arg1,'['); + if (ptr1) { + ptr2 = ptr1; + index = int_between_brackets(ptr2); + *ptr1 = '\0'; + } else index = 0; + + int ifix = modify->find_fix(&arg1[2]); + if (ifix < 0) error->all("Invalid fix ID in variable formula"); + fix = modify->fix[ifix]; + if (index == 0 && fix->vector_flag) { + if (update->whichflag > 0 && update->ntimestep % fix->global_freq) + error->all("Fix in variable not computed at compatible time"); + nvec = fix->size_vector; + nstride = 1; + } else if (index && fix->array_flag) { + if (index > fix->size_array_cols) + error->all("Variable formula fix array is accessed out-of-range"); + if (update->whichflag > 0 && update->ntimestep % fix->global_freq) + error->all("Fix in variable not computed at compatible time"); + nvec = fix->size_array_rows; + nstride = fix->size_array_cols; + } else error->all("Mismatched fix in variable formula"); + + } else error->all("Invalid special function in variable formula"); + + double value = 0.0; + if (method == XMIN) value = BIG; + if (method == XMAX) value = -BIG; + + if (compute) { + double *vec; + if (index) vec = &compute->array[0][index]; + else vec = compute->vector; + + int j = 0; + for (int i = 0; i < nvec; i++) { + if (method == SUM) value += vec[j]; + else if (method == XMIN) value = MIN(value,vec[j]); + else if (method == XMAX) value = MAX(value,vec[j]); + else if (method == AVE) value += vec[j]; + else if (method == TRAP) { + if (i > 0 && i < nvec-1) value += vec[j]; + else value += 0.5*vec[j]; } + j += nstride; } - - if (fix) { - double one; - for (int i = 0; i < nvec; i++) { - if (index) one = fix->compute_array(i,index-1); - else one = fix->compute_vector(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) { - if (i > 1 && i < nvec) value += one; - else value += 0.5*one; - } - } - } - - if (method == AVE) value /= nvec; } + + if (fix) { + double one; + for (int i = 0; i < nvec; i++) { + if (index) one = fix->compute_array(i,index-1); + else one = fix->compute_vector(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) { + if (i > 1 && i < nvec) value += one; + else value += 0.5*one; + } + } + } + + if (method == AVE) value /= nvec; delete [] arg1; delete [] arg2; @@ -2247,7 +2400,8 @@ int Variable::special_function(char *word, char *contents, Tree **tree, flag = 1 -> vector is a per-atom compute or fix quantity with nstride id = positive global ID of atom, converted to local index push result onto tree or arg stack - customize by adding an atom vector: mass,type,x,y,z,vx,vy,vz,fx,fy,fz + customize by adding an atom vector: + mass,type,x,y,z,vx,vy,vz,fx,fy,fz ------------------------------------------------------------------------- */ void Variable::peratom2global(int flag, char *word, @@ -2300,7 +2454,8 @@ void Variable::peratom2global(int flag, char *word, /* ---------------------------------------------------------------------- check if word matches an atom vector return 1 if yes, else 0 - customize by adding an atom vector: mass,type,x,y,z,vx,vy,vz,fx,fy,fz + customize by adding an atom vector: + mass,type,x,y,z,vx,vy,vz,fx,fy,fz ------------------------------------------------------------------------- */ int Variable::is_atom_vector(char *word) @@ -2323,7 +2478,8 @@ int Variable::is_atom_vector(char *word) process an atom vector in formula push result onto tree word = atom vector - customize by adding an atom vector: mass,type,x,y,z,vx,vy,vz,fx,fy,fz + customize by adding an atom vector: + mass,type,x,y,z,vx,vy,vz,fx,fy,fz ------------------------------------------------------------------------- */ void Variable::atom_vector(char *word, Tree **tree, @@ -2362,6 +2518,29 @@ void Variable::atom_vector(char *word, Tree **tree, else if (strcmp(word,"fz") == 0) newtree->array = &atom->f[0][2]; } +/* ---------------------------------------------------------------------- + check if word matches a constant + return 1 if yes, else 0 + customize by adding a constant: PI +------------------------------------------------------------------------- */ + +int Variable::is_constant(char *word) +{ + if (strcmp(word,"PI") == 0) return 1; + return 0; +} + +/* ---------------------------------------------------------------------- + process a constant in formula + customize by adding a constant: PI +------------------------------------------------------------------------- */ + +double Variable::constant(char *word) +{ + if (strcmp(word,"PI") == 0) return PI; + return 0.0; +} + /* ---------------------------------------------------------------------- read a floating point value from a string generate an error if not a legitimate floating point value diff --git a/src/variable.h b/src/variable.h index 4d075f0818..f5cec503c5 100644 --- a/src/variable.h +++ b/src/variable.h @@ -43,6 +43,7 @@ class Variable : protected Pointers { int *which; // next available value for each variable int *pad; // 1 = pad loop/uloop variables with 0s, 0 = no pad char ***data; // str value of each variable's values + double PI; class RanMars *randomequal; // random number generator for equal-style vars class RanMars *randomatom; // random number generator for atom-style vars @@ -74,6 +75,8 @@ class Variable : protected Pointers { Tree **, Tree **, int &, double *, int &); int is_atom_vector(char *); void atom_vector(char *, Tree **, Tree **, int &); + int is_constant(char *); + double constant(char *); double numeric(char *); int inumeric(char *); void print_tree(Tree *, int);