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; }
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); } }
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); } }
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); } }