Exemple #1
0
void Velocity::create(double t_desired, int seed)
{
  int i;

  if (seed <= 0) error->all(FLERR,"Illegal velocity create command");

  // if temperature = NULL, create a new ComputeTemp with the velocity group

  int tflag = 0;
  if (temperature == NULL) {
    char **arg = new char*[3];
    arg[0] = (char *) "velocity_temp";
    arg[1] = group->names[igroup];
    arg[2] = (char *) "temp";
    temperature = new ComputeTemp(lmp,3,arg);
    tflag = 1;
    delete [] arg;
  }

  // initialize temperature computation
  // warn if groups don't match

  if (igroup != temperature->igroup && comm->me == 0)
    error->warning(FLERR,"Mismatch between velocity and compute groups");
  temperature->init();
  temperature->setup();

  // store a copy of current velocities

  double **v = atom->v;
  int nlocal = atom->nlocal;
  double **vhold;
  memory->create(vhold,nlocal,3,"velocity:vnew");

  for (i = 0; i < nlocal; i++) {
    vhold[i][0] = v[i][0];
    vhold[i][1] = v[i][1];
    vhold[i][2] = v[i][2];
  }

  // create new velocities, in uniform or gaussian distribution
  // loop option determines looping style, ALL is default
  //   ALL = loop over all natoms, only set those I own via atom->map
  //    cannot do this if atom IDs do not span 1-Natoms (some were deleted)
  //    will produce same V, independent of P, if atoms were read-in
  //    will NOT produce same V, independent of P, if used create_atoms
  //   LOCAL = only loop over my atoms, adjust RNG to be proc-specific
  //    will never produce same V, independent of P
  //   GEOM = only loop over my atoms
  //    choose RNG for each atom based on its xyz coord (geometry)
  //      via random->reset()
  //    will always produce same V, independent of P
  // adjust by factor for atom mass
  // for 2d, set Vz to 0.0

  double *rmass = atom->rmass;
  double *mass = atom->mass;
  int *type = atom->type;
  int *mask = atom->mask;
  int dimension = domain->dimension;

  int m;
  double vx,vy,vz,factor;
  RanPark *random;

  if (loop_flag == ALL) {

    // create an atom map if one doesn't exist already

    int mapflag = 0;
    if (atom->map_style == 0) {
      mapflag = 1;
      atom->map_style = 1;
      atom->nghost = 0;
      atom->map_init();
      atom->map_set();
    }

    // error check

    if (atom->natoms > MAXSMALLINT)
      error->all(FLERR,"Too big a problem to use velocity create loop all");
    if (atom->tag_enable == 0)
      error->all(FLERR,
                 "Cannot use velocity create loop all unless atoms have IDs");
    if (atom->tag_consecutive() == 0)
      error->all(FLERR,
                 "Atom IDs must be consecutive for velocity create loop all");

    // loop over all atoms in system
    // generate RNGs for all atoms, only assign to ones I own
    // use either per-type mass or per-atom rmass

    random = new RanPark(lmp,seed);
    int natoms = static_cast<int> (atom->natoms);

    for (i = 1; i <= natoms; i++) {
      if (dist_flag == 0) {
        vx = random->uniform();
        vy = random->uniform();
        vz = random->uniform();
      } else {
        vx = random->gaussian();
        vy = random->gaussian();
        vz = random->gaussian();
      }
      m = atom->map(i);
      if (m >= 0 && m < nlocal) {
        if (mask[m] & groupbit) {
          if (rmass) factor = 1.0/sqrt(rmass[m]);
          else factor = 1.0/sqrt(mass[type[m]]);
          v[m][0] = vx * factor;
          v[m][1] = vy * factor;
          if (dimension == 3) v[m][2] = vz * factor;
          else v[m][2] = 0.0;
        }
      }
    }

    // delete temporary atom map

    if (mapflag) {
      atom->map_delete();
      atom->map_style = 0;
    }

  } else if (loop_flag == LOCAL) {
    random = new RanPark(lmp,seed + comm->me);
    for (i = 0; i < WARMUP; i++) random->uniform();

    for (i = 0; i < nlocal; i++) {
      if (mask[i] & groupbit) {
        if (dist_flag == 0) {
          vx = random->uniform();
          vy = random->uniform();
          vz = random->uniform();
        } else {
          vx = random->gaussian();
          vy = random->gaussian();
          vz = random->gaussian();
        }
        if (rmass) factor = 1.0/sqrt(rmass[i]);
        else factor = 1.0/sqrt(mass[type[i]]);
        v[i][0] = vx * factor;
        v[i][1] = vy * factor;
        if (dimension == 3) v[i][2] = vz * factor;
        else v[i][2] = 0.0;
      }
    }

  } else if (loop_flag == GEOM) {
    random = new RanPark(lmp,1);
    double **x = atom->x;

    for (i = 0; i < nlocal; i++) {
      if (mask[i] & groupbit) {
        random->reset(seed,x[i]);
        if (dist_flag == 0) {
          vx = random->uniform();
          vy = random->uniform();
          vz = random->uniform();
        } else {
          vx = random->gaussian();
          vy = random->gaussian();
          vz = random->gaussian();
        }

        if (rmass) factor = 1.0/sqrt(rmass[i]);
        else factor = 1.0/sqrt(mass[type[i]]);
        v[i][0] = vx * factor;
        v[i][1] = vy * factor;
        if (dimension == 3) v[i][2] = vz * factor;
        else v[i][2] = 0.0;
      }
    }
  }

  // apply momentum and rotation zeroing

  if (momentum_flag) zero_momentum();
  if (rotation_flag) zero_rotation();

  // scale temp to desired value

  double t = temperature->compute_scalar();
  rescale(t,t_desired);

  // if sum_flag set, add back in previous velocities

  if (sum_flag) {
    for (i = 0; i < nlocal; i++) {
      if (mask[i] & groupbit) {
        v[i][0] += vhold[i][0];
        v[i][1] += vhold[i][1];
        v[i][2] += vhold[i][2];
      }
    }
  }

  // free local memory
  // if temperature was created, delete it

  memory->destroy(vhold);
  delete random;
  if (tflag) delete temperature;
}
Exemple #2
0
void DisplaceAtoms::command(int narg, char **arg)
{
  int i;

  if (domain->box_exist == 0) 
    error->all(FLERR,"Displace_atoms command before simulation box is defined");
  if (narg < 2) error->all(FLERR,"Illegal displace_atoms command");
  if (modify->nfix_restart_peratom) 
    error->all(FLERR,"Cannot displace_atoms after "
	       "reading restart file with per-atom info");

  if (comm->me == 0 && screen) fprintf(screen,"Displacing atoms ...\n");

  // group and style

  int igroup = group->find(arg[0]);
  if (igroup == -1) error->all(FLERR,"Could not find displace_atoms group ID");
  int groupbit = group->bitmask[igroup];

  int style;
  if (strcmp(arg[1],"move") == 0) style = MOVE;
  else if (strcmp(arg[1],"ramp") == 0) style = RAMP;
  else if (strcmp(arg[1],"random") == 0) style = RANDOM;
  else error->all(FLERR,"Illegal displace_atoms command");

  // set option defaults

  scaleflag = 1;

  // read options from end of input line

  if (style == MOVE) options(narg-5,&arg[5]);
  else if (style == RAMP) options(narg-8,&arg[8]);
  else if (style == RANDOM) options(narg-6,&arg[6]);

  // setup scaling

  if (scaleflag && domain->lattice == NULL)
    error->all(FLERR,"Use of displace_atoms 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;

  // move atoms by 3-vector

  if (style == MOVE) {

    double delx = xscale*atof(arg[2]);
    double dely = yscale*atof(arg[3]);
    double delz = zscale*atof(arg[4]);

    double **x = atom->x;
    int *mask = atom->mask;
    int nlocal = atom->nlocal;

    for (i = 0; i < nlocal; i++) {
      if (mask[i] & groupbit) {
	x[i][0] += delx;
	x[i][1] += dely;
	x[i][2] += delz;
      }
    }
  }

  // move atoms in ramped fashion
    
  if (style == RAMP) {

    int d_dim;
    if (strcmp(arg[2],"x") == 0) d_dim = 0;
    else if (strcmp(arg[2],"y") == 0) d_dim = 1;
    else if (strcmp(arg[2],"z") == 0) d_dim = 2;
    else error->all(FLERR,"Illegal displace_atoms ramp command");

    double d_lo,d_hi;
    if (d_dim == 0) {
      d_lo = xscale*atof(arg[3]);
      d_hi = xscale*atof(arg[4]);
    } else if (d_dim == 1) {
      d_lo = yscale*atof(arg[3]);
      d_hi = yscale*atof(arg[4]);
    } else if (d_dim == 2) {
      d_lo = zscale*atof(arg[3]);
      d_hi = zscale*atof(arg[4]);
    }

    int coord_dim;
    if (strcmp(arg[5],"x") == 0) coord_dim = 0;
    else if (strcmp(arg[5],"y") == 0) coord_dim = 1;
    else if (strcmp(arg[5],"z") == 0) coord_dim = 2;
    else error->all(FLERR,"Illegal displace_atoms ramp command");

    double coord_lo,coord_hi;
    if (coord_dim == 0) {
      coord_lo = xscale*atof(arg[6]);
      coord_hi = xscale*atof(arg[7]);
    } else if (coord_dim == 1) {
      coord_lo = yscale*atof(arg[6]);
      coord_hi = yscale*atof(arg[7]);
    } else if (coord_dim == 2) {
      coord_lo = zscale*atof(arg[6]);
      coord_hi = zscale*atof(arg[7]);
    }

    double **x = atom->x;
    int *mask = atom->mask;
    int nlocal = atom->nlocal;

    double fraction,dramp;

    for (i = 0; i < nlocal; i++) {
      if (mask[i] & groupbit) {
	fraction = (x[i][coord_dim] - coord_lo) / (coord_hi - coord_lo);
	fraction = MAX(fraction,0.0);
	fraction = MIN(fraction,1.0);
	dramp = d_lo + fraction*(d_hi - d_lo);
	x[i][d_dim] += dramp;
      }
    }
  }

  // move atoms randomly
  // makes atom result independent of what proc owns it via random->reset()
    
  if (style == RANDOM) {
    RanPark *random = new RanPark(lmp,1);

    double dx = xscale*atof(arg[2]);
    double dy = yscale*atof(arg[3]);
    double dz = zscale*atof(arg[4]);
    int seed = atoi(arg[5]);
    if (seed <= 0) error->all(FLERR,"Illegal displace_atoms random command");

    double **x = atom->x;
    int *mask = atom->mask;
    int nlocal = atom->nlocal;

    for (i = 0; i < nlocal; i++) {
      if (mask[i] & groupbit) {
	random->reset(seed,x[i]);
	x[i][0] += dx * 2.0*(random->uniform()-0.5);
	x[i][1] += dy * 2.0*(random->uniform()-0.5);
	x[i][2] += dz * 2.0*(random->uniform()-0.5);
      }
    }

    delete random;
  }

  // move atoms back inside simulation box and to new processors
  // use remap() instead of pbc() in case atoms moved a long distance
  // use irregular() in case atoms moved a long distance

  double **x = atom->x;
  int *image = atom->image;
  int nlocal = atom->nlocal;
  for (i = 0; i < nlocal; i++) domain->remap(x[i],image[i]);

  if (domain->triclinic) domain->x2lamda(atom->nlocal);
  domain->reset_box();
  Irregular *irregular = new Irregular(lmp);
  irregular->migrate_atoms();
  delete irregular;
  if (domain->triclinic) domain->lamda2x(atom->nlocal);

  // check if any atoms were lost

  bigint natoms;
  bigint nblocal = atom->nlocal;
  MPI_Allreduce(&nblocal,&natoms,1,MPI_LMP_BIGINT,MPI_SUM,world);
  if (natoms != atom->natoms) {
    char str[128];
    sprintf(str,"Lost atoms via displace_atoms: original " BIGINT_FORMAT 
	    " current " BIGINT_FORMAT,atom->natoms,natoms);
    error->all(FLERR,str);
  }
}
Exemple #3
0
void CreateAtoms::add_random()
{
  double xlo,ylo,zlo,xhi,yhi,zhi,zmid;
  double lamda[3],*coord;
  double *boxlo,*boxhi;

  // random number generator, same for all procs

  RanPark *random = new RanPark(lmp,seed);

  // bounding box for atom creation
  // in real units, even if triclinic
  // only limit bbox by region if its bboxflag is set (interior region)

  if (triclinic == 0) {
    xlo = domain->boxlo[0]; xhi = domain->boxhi[0];
    ylo = domain->boxlo[1]; yhi = domain->boxhi[1];
    zlo = domain->boxlo[2]; zhi = domain->boxhi[2];
    zmid = zlo + 0.5*(zhi-zlo);
  } else {
    xlo = domain->boxlo_bound[0]; xhi = domain->boxhi_bound[0];
    ylo = domain->boxlo_bound[1]; yhi = domain->boxhi_bound[1];
    zlo = domain->boxlo_bound[2]; zhi = domain->boxhi_bound[2];
    zmid = zlo + 0.5*(zhi-zlo);
    boxlo = domain->boxlo_lamda;
    boxhi = domain->boxhi_lamda;
  }

  if (nregion >= 0 && domain->regions[nregion]->bboxflag) {
    xlo = MAX(xlo,domain->regions[nregion]->extent_xlo);
    xhi = MIN(xhi,domain->regions[nregion]->extent_xhi);
    ylo = MAX(ylo,domain->regions[nregion]->extent_ylo);
    yhi = MIN(yhi,domain->regions[nregion]->extent_yhi);
    zlo = MAX(zlo,domain->regions[nregion]->extent_zlo);
    zhi = MIN(zhi,domain->regions[nregion]->extent_zhi);
  }

  // generate random positions for each new atom/molecule within bounding box
  // iterate until atom is within region, variable, and triclinic simulation box
  // if final atom position is in my subbox, create it

  if (xlo > xhi || ylo > yhi || zlo > zhi)
    error->all(FLERR,"No overlap of box and region for create_atoms");

  int valid;
  for (int i = 0; i < nrandom; i++) {
    while (1) {
      xone[0] = xlo + random->uniform() * (xhi-xlo);
      xone[1] = ylo + random->uniform() * (yhi-ylo);
      xone[2] = zlo + random->uniform() * (zhi-zlo);
      if (domain->dimension == 2) xone[2] = zmid;

      valid = 1;
      if (nregion >= 0 &&
          domain->regions[nregion]->match(xone[0],xone[1],xone[2]) == 0)
        valid = 0;
      if (varflag && vartest(xone) == 0) valid = 0;
      if (triclinic) {
        domain->x2lamda(xone,lamda);
        coord = lamda;
        if (coord[0] < boxlo[0] || coord[0] >= boxhi[0] ||
            coord[1] < boxlo[1] || coord[1] >= boxhi[1] ||
            coord[2] < boxlo[2] || coord[2] >= boxhi[2]) valid = 0;
      } else coord = xone;

      if (valid) break;
    }

    // if triclinic, coord is now in lamda units

    if (coord[0] >= sublo[0] && coord[0] < subhi[0] &&
        coord[1] >= sublo[1] && coord[1] < subhi[1] &&
        coord[2] >= sublo[2] && coord[2] < subhi[2]) {
      if (mode == ATOM) atom->avec->create_atom(ntype,xone);
      else add_molecule(xone);
    }
  }

  // clean-up

  delete random;
}
void DisplaceAtoms::command(int narg, char **arg)
{
    int i;

    if (domain->box_exist == 0)
        error->all(FLERR,"Displace_atoms command before simulation box is defined");
    if (narg < 2) error->all(FLERR,"Illegal displace_atoms command");
    if (modify->nfix_restart_peratom)
        error->all(FLERR,"Cannot displace_atoms after "
                   "reading restart file with per-atom info");

    if (comm->me == 0 && screen) fprintf(screen,"Displacing atoms ...\n");

    // group and style

    igroup = group->find(arg[0]);
    if (igroup == -1) error->all(FLERR,"Could not find displace_atoms group ID");
    groupbit = group->bitmask[igroup];

    int style = -1;
    if (strcmp(arg[1],"move") == 0) style = MOVE;
    else if (strcmp(arg[1],"ramp") == 0) style = RAMP;
    else if (strcmp(arg[1],"random") == 0) style = RANDOM;
    else if (strcmp(arg[1],"rotate") == 0) style = ROTATE;
    else error->all(FLERR,"Illegal displace_atoms command");

    // set option defaults

    scaleflag = 1;

    // read options from end of input line

    if (style == MOVE) options(narg-5,&arg[5]);
    else if (style == RAMP) options(narg-8,&arg[8]);
    else if (style == RANDOM) options(narg-6,&arg[6]);
    else if (style == ROTATE) options(narg-9,&arg[9]);

    // setup scaling

    double xscale,yscale,zscale;
    if (scaleflag) {
        xscale = domain->lattice->xlattice;
        yscale = domain->lattice->ylattice;
        zscale = domain->lattice->zlattice;
    }
    else xscale = yscale = zscale = 1.0;

    // move atoms by 3-vector or specified variable(s)

    if (style == MOVE) {
        move(0,arg[2],xscale);
        move(1,arg[3],yscale);
        move(2,arg[4],zscale);
    }

    // move atoms in ramped fashion

    if (style == RAMP) {

        int d_dim;
        if (strcmp(arg[2],"x") == 0) d_dim = 0;
        else if (strcmp(arg[2],"y") == 0) d_dim = 1;
        else if (strcmp(arg[2],"z") == 0) d_dim = 2;
        else error->all(FLERR,"Illegal displace_atoms ramp command");

        double d_lo,d_hi;
        if (d_dim == 0) {
            d_lo = xscale*force->numeric(FLERR,arg[3]);
            d_hi = xscale*force->numeric(FLERR,arg[4]);
        } else if (d_dim == 1) {
            d_lo = yscale*force->numeric(FLERR,arg[3]);
            d_hi = yscale*force->numeric(FLERR,arg[4]);
        } else if (d_dim == 2) {
            d_lo = zscale*force->numeric(FLERR,arg[3]);
            d_hi = zscale*force->numeric(FLERR,arg[4]);
        }

        int coord_dim;
        if (strcmp(arg[5],"x") == 0) coord_dim = 0;
        else if (strcmp(arg[5],"y") == 0) coord_dim = 1;
        else if (strcmp(arg[5],"z") == 0) coord_dim = 2;
        else error->all(FLERR,"Illegal displace_atoms ramp command");

        double coord_lo,coord_hi;
        if (coord_dim == 0) {
            coord_lo = xscale*force->numeric(FLERR,arg[6]);
            coord_hi = xscale*force->numeric(FLERR,arg[7]);
        } else if (coord_dim == 1) {
            coord_lo = yscale*force->numeric(FLERR,arg[6]);
            coord_hi = yscale*force->numeric(FLERR,arg[7]);
        } else if (coord_dim == 2) {
            coord_lo = zscale*force->numeric(FLERR,arg[6]);
            coord_hi = zscale*force->numeric(FLERR,arg[7]);
        }

        double **x = atom->x;
        int *mask = atom->mask;
        int nlocal = atom->nlocal;

        double fraction,dramp;

        for (i = 0; i < nlocal; i++) {
            if (mask[i] & groupbit) {
                fraction = (x[i][coord_dim] - coord_lo) / (coord_hi - coord_lo);
                fraction = MAX(fraction,0.0);
                fraction = MIN(fraction,1.0);
                dramp = d_lo + fraction*(d_hi - d_lo);
                x[i][d_dim] += dramp;
            }
        }
    }

    // move atoms randomly
    // makes atom result independent of what proc owns it via random->reset()

    if (style == RANDOM) {
        RanPark *random = new RanPark(lmp,1);

        double dx = xscale*force->numeric(FLERR,arg[2]);
        double dy = yscale*force->numeric(FLERR,arg[3]);
        double dz = zscale*force->numeric(FLERR,arg[4]);
        int seed = force->inumeric(FLERR,arg[5]);
        if (seed <= 0) error->all(FLERR,"Illegal displace_atoms random command");

        double **x = atom->x;
        int *mask = atom->mask;
        int nlocal = atom->nlocal;

        for (i = 0; i < nlocal; i++) {
            if (mask[i] & groupbit) {
                random->reset(seed,x[i]);
                x[i][0] += dx * 2.0*(random->uniform()-0.5);
                x[i][1] += dy * 2.0*(random->uniform()-0.5);
                x[i][2] += dz * 2.0*(random->uniform()-0.5);
            }
        }

        delete random;
    }

    // rotate atoms by right-hand rule by theta around R
    // P = point = vector = point of rotation
    // R = vector = axis of rotation
    // R0 = runit = unit vector for R
    // D = X - P = vector from P to X
    // C = (D dot R0) R0 = projection of atom coord onto R line
    // A = D - C = vector from R line to X
    // B = R0 cross A = vector perp to A in plane of rotation
    // A,B define plane of circular rotation around R line
    // X = P + C + A cos(theta) + B sin(theta)

    if (style == ROTATE) {
        double theta_new;
        double axis[3],point[3],qrotate[4],qnew[4];
        double a[3],b[3],c[3],d[3],disp[3],runit[3];
        double *quat;

        int dim = domain->dimension;
        point[0] = xscale*force->numeric(FLERR,arg[2]);
        point[1] = yscale*force->numeric(FLERR,arg[3]);
        point[2] = zscale*force->numeric(FLERR,arg[4]);
        axis[0] = force->numeric(FLERR,arg[5]);
        axis[1] = force->numeric(FLERR,arg[6]);
        axis[2] = force->numeric(FLERR,arg[7]);
        double theta = force->numeric(FLERR,arg[8]);
        if (dim == 2 && (axis[0] != 0.0 || axis[1] != 0.0))
            error->all(FLERR,"Invalid displace_atoms rotate axis for 2d");

        double len = sqrt(axis[0]*axis[0] + axis[1]*axis[1] + axis[2]*axis[2]);
        if (len == 0.0)
            error->all(FLERR,"Zero length rotation vector with displace_atoms");
        runit[0] = axis[0]/len;
        runit[1] = axis[1]/len;
        runit[2] = axis[2]/len;

        double angle = MY_PI*theta/180.0;
        double sine = sin(angle);
        double cosine = cos(angle);
        double ddotr;

        // flags for additional orientation info stored by some atom styles

        int ellipsoid_flag = atom->ellipsoid_flag;
        int line_flag = atom->line_flag;
        int tri_flag = atom->tri_flag;
        int body_flag = atom->body_flag;

        int theta_flag = 0;
        int quat_flag = 0;
        if (line_flag) theta_flag = 1;
        if (ellipsoid_flag || tri_flag || body_flag) quat_flag = 1;

        // AtomVec pointers to retrieve per-atom storage of extra quantities

        AtomVecEllipsoid *avec_ellipsoid =
            (AtomVecEllipsoid *) atom->style_match("ellipsoid");
        AtomVecLine *avec_line = (AtomVecLine *) atom->style_match("line");
        AtomVecTri *avec_tri = (AtomVecTri *) atom->style_match("tri");
        AtomVecBody *avec_body = (AtomVecBody *) atom->style_match("body");

        double **x = atom->x;
        int *ellipsoid = atom->ellipsoid;
        int *line = atom->line;
        int *tri = atom->tri;
        int *body = atom->body;
        int *mask = atom->mask;
        int nlocal = atom->nlocal;

        for (i = 0; i < nlocal; i++) {
            if (mask[i] & groupbit) {
                d[0] = x[i][0] - point[0];
                d[1] = x[i][1] - point[1];
                d[2] = x[i][2] - point[2];
                ddotr = d[0]*runit[0] + d[1]*runit[1] + d[2]*runit[2];
                c[0] = ddotr*runit[0];
                c[1] = ddotr*runit[1];
                c[2] = ddotr*runit[2];
                a[0] = d[0] - c[0];
                a[1] = d[1] - c[1];
                a[2] = d[2] - c[2];
                b[0] = runit[1]*a[2] - runit[2]*a[1];
                b[1] = runit[2]*a[0] - runit[0]*a[2];
                b[2] = runit[0]*a[1] - runit[1]*a[0];
                disp[0] = a[0]*cosine  + b[0]*sine;
                disp[1] = a[1]*cosine  + b[1]*sine;
                disp[2] = a[2]*cosine  + b[2]*sine;
                x[i][0] = point[0] + c[0] + disp[0];
                x[i][1] = point[1] + c[1] + disp[1];
                if (dim == 3) x[i][2] = point[2] + c[2] + disp[2];

                // theta for lines

                if (theta_flag && line[i] >= 0.0) {
                    theta_new = fmod(avec_line->bonus[line[i]].theta+angle,MY_2PI);
                    avec_line->bonus[atom->line[i]].theta = theta_new;
                }

                // quats for ellipsoids, tris, and bodies

                if (quat_flag) {
                    quat = NULL;
                    if (ellipsoid_flag && ellipsoid[i] >= 0)
                        quat = avec_ellipsoid->bonus[ellipsoid[i]].quat;
                    else if (tri_flag && tri[i] >= 0)
                        quat = avec_tri->bonus[tri[i]].quat;
                    else if (body_flag && body[i] >= 0)
                        quat = avec_body->bonus[body[i]].quat;
                    if (quat) {
                        qrotate[0] = cosine;
                        qrotate[1] = runit[0]*sine;
                        qrotate[2] = runit[1]*sine;
                        qrotate[3] = runit[2]*sine;
                        MathExtra::quatquat(qrotate,quat,qnew);
                        quat[0] = qnew[0];
                        quat[1] = qnew[1];
                        quat[2] = qnew[2];
                        quat[3] = qnew[3];
                    }
                }
            }
        }
    }

    // move atoms back inside simulation box and to new processors
    // use remap() instead of pbc() in case atoms moved a long distance
    // use irregular() in case atoms moved a long distance

    double **x = atom->x;
    imageint *image = atom->image;
    int nlocal = atom->nlocal;
    for (i = 0; i < nlocal; i++) domain->remap(x[i],image[i]);

    if (domain->triclinic) domain->x2lamda(atom->nlocal);
    domain->reset_box();
    Irregular *irregular = new Irregular(lmp);
    irregular->migrate_atoms(1);
    delete irregular;
    if (domain->triclinic) domain->lamda2x(atom->nlocal);

    // check if any atoms were lost

    bigint natoms;
    bigint nblocal = atom->nlocal;
    MPI_Allreduce(&nblocal,&natoms,1,MPI_LMP_BIGINT,MPI_SUM,world);
    if (natoms != atom->natoms && comm->me == 0) {
        char str[128];
        sprintf(str,"Lost atoms via displace_atoms: original " BIGINT_FORMAT
                " current " BIGINT_FORMAT,atom->natoms,natoms);
        error->warning(FLERR,str);
    }
}
Exemple #5
0
void DisplaceAtoms::command(int narg, char **arg)
{
  int i;

  if (domain->box_exist == 0)
    error->all(FLERR,"Displace_atoms command before simulation box is defined");
  if (narg < 2) error->all(FLERR,"Illegal displace_atoms command");
  if (modify->nfix_restart_peratom)
    error->all(FLERR,"Cannot displace_atoms after "
               "reading restart file with per-atom info");

  if (comm->me == 0 && screen) fprintf(screen,"Displacing atoms ...\n");

  // group and style

  int igroup = group->find(arg[0]);
  if (igroup == -1) error->all(FLERR,"Could not find displace_atoms group ID");
  int groupbit = group->bitmask[igroup];

  int style;
  if (strcmp(arg[1],"move") == 0) style = MOVE;
  else if (strcmp(arg[1],"ramp") == 0) style = RAMP;
  else if (strcmp(arg[1],"random") == 0) style = RANDOM;
  else if (strcmp(arg[1],"rotate") == 0) style = ROTATE;
  else error->all(FLERR,"Illegal displace_atoms command");

  // set option defaults

  scaleflag = 1;

  // read options from end of input line

  if (style == MOVE) options(narg-5,&arg[5]);
  else if (style == RAMP) options(narg-8,&arg[8]);
  else if (style == RANDOM) options(narg-6,&arg[6]);
  else if (style == ROTATE) options(narg-9,&arg[9]);

  // setup scaling

  double xscale,yscale,zscale;
  if (scaleflag) {
    xscale = domain->lattice->xlattice;
    yscale = domain->lattice->ylattice;
    zscale = domain->lattice->zlattice;
  }
  else xscale = yscale = zscale = 1.0;

  // move atoms by 3-vector

  if (style == MOVE) {

    double delx = xscale*atof(arg[2]);
    double dely = yscale*atof(arg[3]);
    double delz = zscale*atof(arg[4]);

    double **x = atom->x;
    int *mask = atom->mask;
    int nlocal = atom->nlocal;

    for (i = 0; i < nlocal; i++) {
      if (mask[i] & groupbit) {
        x[i][0] += delx;
        x[i][1] += dely;
        x[i][2] += delz;
      }
    }
  }

  // move atoms in ramped fashion

  if (style == RAMP) {

    int d_dim;
    if (strcmp(arg[2],"x") == 0) d_dim = 0;
    else if (strcmp(arg[2],"y") == 0) d_dim = 1;
    else if (strcmp(arg[2],"z") == 0) d_dim = 2;
    else error->all(FLERR,"Illegal displace_atoms ramp command");

    double d_lo,d_hi;
    if (d_dim == 0) {
      d_lo = xscale*atof(arg[3]);
      d_hi = xscale*atof(arg[4]);
    } else if (d_dim == 1) {
      d_lo = yscale*atof(arg[3]);
      d_hi = yscale*atof(arg[4]);
    } else if (d_dim == 2) {
      d_lo = zscale*atof(arg[3]);
      d_hi = zscale*atof(arg[4]);
    }

    int coord_dim;
    if (strcmp(arg[5],"x") == 0) coord_dim = 0;
    else if (strcmp(arg[5],"y") == 0) coord_dim = 1;
    else if (strcmp(arg[5],"z") == 0) coord_dim = 2;
    else error->all(FLERR,"Illegal displace_atoms ramp command");

    double coord_lo,coord_hi;
    if (coord_dim == 0) {
      coord_lo = xscale*atof(arg[6]);
      coord_hi = xscale*atof(arg[7]);
    } else if (coord_dim == 1) {
      coord_lo = yscale*atof(arg[6]);
      coord_hi = yscale*atof(arg[7]);
    } else if (coord_dim == 2) {
      coord_lo = zscale*atof(arg[6]);
      coord_hi = zscale*atof(arg[7]);
    }

    double **x = atom->x;
    int *mask = atom->mask;
    int nlocal = atom->nlocal;

    double fraction,dramp;

    for (i = 0; i < nlocal; i++) {
      if (mask[i] & groupbit) {
        fraction = (x[i][coord_dim] - coord_lo) / (coord_hi - coord_lo);
        fraction = MAX(fraction,0.0);
        fraction = MIN(fraction,1.0);
        dramp = d_lo + fraction*(d_hi - d_lo);
        x[i][d_dim] += dramp;
      }
    }
  }

  // move atoms randomly
  // makes atom result independent of what proc owns it via random->reset()

  if (style == RANDOM) {
    RanPark *random = new RanPark(lmp,1);

    double dx = xscale*atof(arg[2]);
    double dy = yscale*atof(arg[3]);
    double dz = zscale*atof(arg[4]);
    int seed = atoi(arg[5]);
    if (seed <= 0) error->all(FLERR,"Illegal displace_atoms random command");

    double **x = atom->x;
    int *mask = atom->mask;
    int nlocal = atom->nlocal;

    for (i = 0; i < nlocal; i++) {
      if (mask[i] & groupbit) {
        random->reset(seed,x[i]);
        x[i][0] += dx * 2.0*(random->uniform()-0.5);
        x[i][1] += dy * 2.0*(random->uniform()-0.5);
        x[i][2] += dz * 2.0*(random->uniform()-0.5);
      }
    }

    delete random;
  }
 
  // rotate atoms by right-hand rule by theta around R
  // P = point = vector = point of rotation
  // R = vector = axis of rotation
  // R0 = runit = unit vector for R
  // D = X - P = vector from P to X
  // C = (D dot R0) R0 = projection of atom coord onto R line
  // A = D - C = vector from R line to X
  // B = R0 cross A = vector perp to A in plane of rotation
  // A,B define plane of circular rotation around R line
  // X = P + C + A cos(theta) + B sin(theta)

  if (style == ROTATE) {
    double axis[3],point[3];
    double a[3],b[3],c[3],d[3],disp[3],runit[3];
    
    int dim = domain->dimension;
    point[0] = xscale*atof(arg[2]);
    point[1] = yscale*atof(arg[3]);
    point[2] = zscale*atof(arg[4]);
    axis[0] = atof(arg[5]);
    axis[1] = atof(arg[6]);
    axis[2] = atof(arg[7]);
    double theta = atof(arg[8]);
    if (dim == 2 and (axis[0] != 0.0 || axis[1] != 0.0))
      error->all(FLERR,"Invalid displace_atoms rotate axis for 2d");

    double len = sqrt(axis[0]*axis[0] + axis[1]*axis[1] + axis[2]*axis[2]);
    if (len == 0.0)
      error->all(FLERR,"Zero length rotation vector with displace_atoms");
    runit[0] = axis[0]/len;
    runit[1] = axis[1]/len;
    runit[2] = axis[2]/len;

    double sine = sin(MY_PI*theta/180.0);
    double cosine = cos(MY_PI*theta/180.0);
    double ddotr;

    double **x = atom->x;
    int *mask = atom->mask;
    int nlocal = atom->nlocal;

    for (i = 0; i < nlocal; i++) {
      if (mask[i] & groupbit) {
        d[0] = x[i][0] - point[0];
        d[1] = x[i][1] - point[1];
        d[2] = x[i][2] - point[2];
        ddotr = d[0]*runit[0] + d[1]*runit[1] + d[2]*runit[2];
        c[0] = ddotr*runit[0];
        c[1] = ddotr*runit[1];
        c[2] = ddotr*runit[2];
        a[0] = d[0] - c[0];
        a[1] = d[1] - c[1];
        a[2] = d[2] - c[2];
        b[0] = runit[1]*a[2] - runit[2]*a[1];
        b[1] = runit[2]*a[0] - runit[0]*a[2];
        b[2] = runit[0]*a[1] - runit[1]*a[0];
        disp[0] = a[0]*cosine  + b[0]*sine;
        disp[1] = a[1]*cosine  + b[1]*sine;
        disp[2] = a[2]*cosine  + b[2]*sine;
        x[i][0] = point[0] + c[0] + disp[0];
        x[i][1] = point[1] + c[1] + disp[1];
        if (dim == 3) x[i][2] = point[2] + c[2] + disp[2];
      }
    }
  }

  // move atoms back inside simulation box and to new processors
  // use remap() instead of pbc() in case atoms moved a long distance
  // use irregular() in case atoms moved a long distance

  double **x = atom->x;
  tagint *image = atom->image;
  int nlocal = atom->nlocal;
  for (i = 0; i < nlocal; i++) domain->remap(x[i],image[i]);

  if (domain->triclinic) domain->x2lamda(atom->nlocal);
  domain->reset_box();
  Irregular *irregular = new Irregular(lmp);
  irregular->migrate_atoms();
  delete irregular;
  if (domain->triclinic) domain->lamda2x(atom->nlocal);

  // check if any atoms were lost

  bigint natoms;
  bigint nblocal = atom->nlocal;
  MPI_Allreduce(&nblocal,&natoms,1,MPI_LMP_BIGINT,MPI_SUM,world);
  if (natoms != atom->natoms && comm->me == 0) {
    char str[128];
    sprintf(str,"Lost atoms via displace_atoms: original " BIGINT_FORMAT
            " current " BIGINT_FORMAT,atom->natoms,natoms);
    error->warning(FLERR,str);
  }
}