Page MenuHomec4science

create_atoms.cpp
No OneTemporary

File Metadata

Created
Sat, Jun 8, 01:15

create_atoms.cpp

/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "string.h"
#include "create_atoms.h"
#include "atom.h"
#include "atom_vec.h"
#include "molecule.h"
#include "comm.h"
#include "irregular.h"
#include "modify.h"
#include "force.h"
#include "special.h"
#include "fix.h"
#include "domain.h"
#include "lattice.h"
#include "region.h"
#include "random_park.h"
#include "random_mars.h"
#include "math_extra.h"
#include "math_const.h"
#include "error.h"
using namespace LAMMPS_NS;
using namespace MathConst;
#define BIG 1.0e30
#define EPSILON 1.0e-6
enum{BOX,REGION,SINGLE,RANDOM};
enum{ATOM,MOLECULE};
/* ---------------------------------------------------------------------- */
CreateAtoms::CreateAtoms(LAMMPS *lmp) : Pointers(lmp) {}
/* ---------------------------------------------------------------------- */
void CreateAtoms::command(int narg, char **arg)
{
if (domain->box_exist == 0)
error->all(FLERR,"Create_atoms command before simulation box is defined");
if (modify->nfix_restart_peratom)
error->all(FLERR,"Cannot create_atoms after "
"reading restart file with per-atom info");
// parse arguments
if (narg < 2) error->all(FLERR,"Illegal create_atoms command");
ntype = force->inumeric(FLERR,arg[0]);
int iarg;
if (strcmp(arg[1],"box") == 0) {
style = BOX;
iarg = 2;
} else if (strcmp(arg[1],"region") == 0) {
style = REGION;
if (narg < 3) error->all(FLERR,"Illegal create_atoms command");
nregion = domain->find_region(arg[2]);
if (nregion == -1) error->all(FLERR,
"Create_atoms region ID does not exist");
domain->regions[nregion]->init();
iarg = 3;;
} else if (strcmp(arg[1],"single") == 0) {
style = SINGLE;
if (narg < 5) error->all(FLERR,"Illegal create_atoms command");
xone[0] = force->numeric(FLERR,arg[2]);
xone[1] = force->numeric(FLERR,arg[3]);
xone[2] = force->numeric(FLERR,arg[4]);
iarg = 5;
} else if (strcmp(arg[1],"random") == 0) {
style = RANDOM;
if (narg < 5) error->all(FLERR,"Illegal create_atoms command");
nrandom = force->inumeric(FLERR,arg[2]);
seed = force->inumeric(FLERR,arg[3]);
if (strcmp(arg[4],"NULL") == 0) nregion = -1;
else {
nregion = domain->find_region(arg[4]);
if (nregion == -1) error->all(FLERR,
"Create_atoms region ID does not exist");
domain->regions[nregion]->init();
}
iarg = 5;
} else error->all(FLERR,"Illegal create_atoms command");
// process optional keywords
int scaleflag = 1;
remapflag = 0;
mode = ATOM;
int molseed;
nbasis = domain->lattice->nbasis;
basistype = new int[nbasis];
for (int i = 0; i < nbasis; i++) basistype[i] = ntype;
while (iarg < narg) {
if (strcmp(arg[iarg],"basis") == 0) {
if (iarg+3 > narg) error->all(FLERR,"Illegal create_atoms command");
int ibasis = force->inumeric(FLERR,arg[iarg+1]);
int itype = force->inumeric(FLERR,arg[iarg+2]);
if (ibasis <= 0 || ibasis > nbasis || itype <= 0 || itype > atom->ntypes)
error->all(FLERR,"Invalid basis setting in create_atoms command");
basistype[ibasis-1] = itype;
iarg += 3;
} else if (strcmp(arg[iarg],"remap") == 0) {
if (iarg+2 > narg) error->all(FLERR,"Illegal create_atoms command");
if (strcmp(arg[iarg+1],"yes") == 0) remapflag = 1;
else if (strcmp(arg[iarg+1],"no") == 0) remapflag = 0;
else error->all(FLERR,"Illegal create_atoms command");
iarg += 2;
} else if (strcmp(arg[iarg],"mol") == 0) {
if (iarg+3 > narg) error->all(FLERR,"Illegal create_atoms command");
int imol = atom->find_molecule(arg[iarg+1]);
if (imol == -1) error->all(FLERR,"Molecule template ID for "
"create_atoms does not exist");
if (atom->molecules[imol]->nset > 1 && comm->me == 0)
error->warning(FLERR,"Molecule template for "
"create_atoms has multiple molecules");
mode = MOLECULE;
onemol = atom->molecules[imol];
molseed = force->inumeric(FLERR,arg[iarg+2]);
iarg += 3;
} else if (strcmp(arg[iarg],"units") == 0) {
if (iarg+2 > narg) error->all(FLERR,"Illegal create_atoms command");
if (strcmp(arg[iarg+1],"box") == 0) scaleflag = 0;
else if (strcmp(arg[iarg+1],"lattice") == 0) scaleflag = 1;
else error->all(FLERR,"Illegal create_atoms command");
iarg += 2;
} else error->all(FLERR,"Illegal create_atoms command");
}
// error checks
if (mode == ATOM && (ntype <= 0 || ntype > atom->ntypes))
error->all(FLERR,"Invalid atom type in create_atoms command");
if (style == RANDOM) {
if (nrandom < 0) error->all(FLERR,"Illegal create_atoms command");
if (seed <= 0) error->all(FLERR,"Illegal create_atoms command");
}
// error check and further setup for mode = MOLECULE
ranmol = NULL;
if (mode == MOLECULE) {
if (onemol->xflag == 0)
error->all(FLERR,"Create_atoms molecule must have coordinates");
if (onemol->typeflag == 0)
error->all(FLERR,"Create_atoms molecule must have atom types");
if (ntype+onemol->maxtype <= 0 || ntype+onemol->maxtype > atom->ntypes)
error->all(FLERR,"Invalid atom type in create_atoms mol command");
if (onemol->tag_require && !atom->tag_enable)
error->all(FLERR,
"Create_atoms molecule has atom IDs, but system does not");
// create_atoms uses geoemetric center of molecule for insertion
onemol->compute_center();
// molecule random number generator, different for each proc
ranmol = new RanMars(lmp,molseed+comm->me);
}
// demand non-none lattice be defined for BOX and REGION
// else setup scaling for SINGLE and RANDOM
// could use domain->lattice->lattice2box() to do conversion of
// lattice to box, but not consistent with other uses of units=lattice
// triclinic remapping occurs in add_single()
if (style == BOX || style == REGION) {
if (nbasis == 0)
error->all(FLERR,"Cannot create atoms with undefined lattice");
} else if (scaleflag == 1) {
xone[0] *= domain->lattice->xlattice;
xone[1] *= domain->lattice->ylattice;
xone[2] *= domain->lattice->zlattice;
}
// set bounds for my proc in sublo[3] & subhi[3]
// if periodic and style = BOX or REGION, i.e. using lattice:
// should create exactly 1 atom when 2 images are both "on" the boundary
// either image may be slightly inside/outside true box due to round-off
// if I am lo proc, decrement lower bound by EPSILON
// this will insure lo image is created
// if I am hi proc, decrement upper bound by 2.0*EPSILON
// this will insure hi image is not created
// thus insertion box is EPSILON smaller than true box
// and is shifted away from true boundary
// which is where atoms are likely to be generated
triclinic = domain->triclinic;
double epsilon[3];
if (triclinic) epsilon[0] = epsilon[1] = epsilon[2] = EPSILON;
else {
epsilon[0] = domain->prd[0] * EPSILON;
epsilon[1] = domain->prd[1] * EPSILON;
epsilon[2] = domain->prd[2] * EPSILON;
}
if (triclinic == 0) {
sublo[0] = domain->sublo[0]; subhi[0] = domain->subhi[0];
sublo[1] = domain->sublo[1]; subhi[1] = domain->subhi[1];
sublo[2] = domain->sublo[2]; subhi[2] = domain->subhi[2];
} else {
sublo[0] = domain->sublo_lamda[0]; subhi[0] = domain->subhi_lamda[0];
sublo[1] = domain->sublo_lamda[1]; subhi[1] = domain->subhi_lamda[1];
sublo[2] = domain->sublo_lamda[2]; subhi[2] = domain->subhi_lamda[2];
}
if (style == BOX || style == REGION) {
if (domain->xperiodic) {
if (comm->myloc[0] == 0) sublo[0] -= epsilon[0];
if (comm->myloc[0] == comm->procgrid[0]-1) subhi[0] -= 2.0*epsilon[0];
}
if (domain->yperiodic) {
if (comm->myloc[1] == 0) sublo[1] -= epsilon[1];
if (comm->myloc[1] == comm->procgrid[1]-1) subhi[1] -= 2.0*epsilon[1];
}
if (domain->zperiodic) {
if (comm->myloc[2] == 0) sublo[2] -= epsilon[2];
if (comm->myloc[2] == comm->procgrid[2]-1) subhi[2] -= 2.0*epsilon[2];
}
}
// add atoms/molecules in one of 3 ways
bigint natoms_previous = atom->natoms;
int nlocal_previous = atom->nlocal;
if (style == SINGLE) add_single();
else if (style == RANDOM) add_random();
else add_lattice();
// invoke set_arrays() for fixes that need initialization of new atoms
int nlocal = atom->nlocal;
for (int m = 0; m < modify->nfix; m++) {
Fix *fix = modify->fix[m];
if (fix->create_attribute)
for (int i = nlocal_previous; i < nlocal; i++)
fix->set_arrays(i);
}
// set new total # of atoms and error check
bigint nblocal = atom->nlocal;
MPI_Allreduce(&nblocal,&atom->natoms,1,MPI_LMP_BIGINT,MPI_SUM,world);
if (atom->natoms < 0 || atom->natoms >= MAXBIGINT)
error->all(FLERR,"Too many total atoms");
// add IDs for newly created atoms
// check that atom IDs are valid
if (atom->tag_enable) atom->tag_extend();
atom->tag_check();
// if molecular system or user-requested, create global mapping of atoms
// zero nghost in case are adding new atoms to existing atoms
if (atom->molecular || atom->map_user) {
atom->nghost = 0;
atom->map_init();
atom->map_set();
}
// for MOLECULE mode:
// set molecule IDs for created atoms if used
// reset new molecule bond,angle,etc and special values
// send atoms to new owning procs via irregular comm
// since not all atoms I created will be within my sub-domain
// perform special list build if needed
if (mode == MOLECULE) {
// molcreate = # of molecules I created
int molcreate = (atom->nlocal - nlocal_previous) / onemol->natoms;
// maxmol = max molecule ID across all procs, for previous atoms
// moloffset = max molecule ID for all molecules owned by previous procs
// including molecules existing before this creation
tagint moloffset;
tagint *molecule = atom->molecule;
if (molecule) {
tagint max = 0;
for (int i = 0; i < nlocal_previous; i++) max = MAX(max,molecule[i]);
tagint maxmol;
MPI_Allreduce(&max,&maxmol,1,MPI_LMP_TAGINT,MPI_MAX,world);
MPI_Scan(&molcreate,&moloffset,1,MPI_INT,MPI_SUM,world);
moloffset = moloffset - molcreate + maxmol;
}
// loop over molecules I created
// set their molecule ID
// reset their bond,angle,etc and special values
int natoms = onemol->natoms;
tagint offset = 0;
tagint *tag = atom->tag;
int *num_bond = atom->num_bond;
int *num_angle = atom->num_angle;
int *num_dihedral = atom->num_dihedral;
int *num_improper = atom->num_improper;
tagint **bond_atom = atom->bond_atom;
tagint **angle_atom1 = atom->angle_atom1;
tagint **angle_atom2 = atom->angle_atom2;
tagint **angle_atom3 = atom->angle_atom3;
tagint **dihedral_atom1 = atom->dihedral_atom1;
tagint **dihedral_atom2 = atom->dihedral_atom2;
tagint **dihedral_atom3 = atom->dihedral_atom3;
tagint **dihedral_atom4 = atom->dihedral_atom4;
tagint **improper_atom1 = atom->improper_atom1;
tagint **improper_atom2 = atom->improper_atom2;
tagint **improper_atom3 = atom->improper_atom3;
tagint **improper_atom4 = atom->improper_atom4;
int **nspecial = atom->nspecial;
tagint **special = atom->special;
int ilocal = nlocal_previous;
for (int i = 0; i < molcreate; i++) {
if (tag) offset = tag[ilocal]-1;
for (int m = 0; m < natoms; m++) {
if (molecule) molecule[ilocal] = moloffset + i+1;
if (onemol->bondflag)
for (int j = 0; j < num_bond[ilocal]; j++)
bond_atom[ilocal][j] += offset;
if (onemol->angleflag)
for (int j = 0; j < num_angle[ilocal]; j++) {
angle_atom1[ilocal][j] += offset;
angle_atom2[ilocal][j] += offset;
angle_atom3[ilocal][j] += offset;
}
if (onemol->dihedralflag)
for (int j = 0; j < num_dihedral[ilocal]; j++) {
dihedral_atom1[ilocal][j] += offset;
dihedral_atom2[ilocal][j] += offset;
dihedral_atom3[ilocal][j] += offset;
dihedral_atom4[ilocal][j] += offset;
}
if (onemol->improperflag)
for (int j = 0; j < num_improper[ilocal]; j++) {
improper_atom1[ilocal][j] += offset;
improper_atom2[ilocal][j] += offset;
improper_atom3[ilocal][j] += offset;
improper_atom4[ilocal][j] += offset;
}
if (onemol->specialflag)
for (int j = 0; j < nspecial[ilocal][2]; j++)
special[ilocal][j] += offset;
ilocal++;
}
}
// perform irregular comm to migrate atoms to new owning procs
double **x = atom->x;
imageint *image = atom->image;
int nlocal = atom->nlocal;
for (int 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);
}
// clean up
delete ranmol;
if (domain->lattice) delete [] basistype;
// print status
if (comm->me == 0) {
if (screen)
fprintf(screen,"Created " BIGINT_FORMAT " atoms\n",
atom->natoms-natoms_previous);
if (logfile)
fprintf(logfile,"Created " BIGINT_FORMAT " atoms\n",
atom->natoms-natoms_previous);
}
// for MOLECULE mode:
// create special bond lists for molecular systems
// only if onemol added bonds but not special info
if (mode == MOLECULE) {
if (atom->molecular && onemol->bondflag && !onemol->specialflag) {
Special special(lmp);
special.build();
}
}
}
/* ----------------------------------------------------------------------
add single atom with coords at xone if it's in my sub-box
if triclinic, xone is in lamda coords
------------------------------------------------------------------------- */
void CreateAtoms::add_single()
{
// remap atom if requested
if (remapflag) {
imageint imagetmp = ((imageint) IMGMAX << IMG2BITS) |
((imageint) IMGMAX << IMGBITS) | IMGMAX;
domain->remap(xone,imagetmp);
}
// if triclinic, convert to lamda coords (0-1)
double lamda[3],*coord;
if (triclinic) {
domain->x2lamda(xone,lamda);
coord = lamda;
} else coord = xone;
// if atom/molecule is in my subbox, create it
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);
}
}
/* ----------------------------------------------------------------------
add Nrandom atoms at random locations
------------------------------------------------------------------------- */
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 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 (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;
}
/* ----------------------------------------------------------------------
add many atoms by looping over lattice
------------------------------------------------------------------------- */
void CreateAtoms::add_lattice()
{
// convert 8 corners of my subdomain from box coords to lattice coords
// for orthogonal, use corner pts of my subbox
// for triclinic, use bounding box of my subbox
// xyz min to max = bounding box around the domain corners in lattice space
double bboxlo[3],bboxhi[3];
if (triclinic == 0) {
bboxlo[0] = domain->sublo[0]; bboxhi[0] = domain->subhi[0];
bboxlo[1] = domain->sublo[1]; bboxhi[1] = domain->subhi[1];
bboxlo[2] = domain->sublo[2]; bboxhi[2] = domain->subhi[2];
} else domain->bbox(domain->sublo_lamda,domain->subhi_lamda,bboxlo,bboxhi);
double xmin,ymin,zmin,xmax,ymax,zmax;
xmin = ymin = zmin = BIG;
xmax = ymax = zmax = -BIG;
domain->lattice->bbox(1,bboxlo[0],bboxlo[1],bboxlo[2],
xmin,ymin,zmin,xmax,ymax,zmax);
domain->lattice->bbox(1,bboxhi[0],bboxlo[1],bboxlo[2],
xmin,ymin,zmin,xmax,ymax,zmax);
domain->lattice->bbox(1,bboxlo[0],bboxhi[1],bboxlo[2],
xmin,ymin,zmin,xmax,ymax,zmax);
domain->lattice->bbox(1,bboxhi[0],bboxhi[1],bboxlo[2],
xmin,ymin,zmin,xmax,ymax,zmax);
domain->lattice->bbox(1,bboxlo[0],bboxlo[1],bboxhi[2],
xmin,ymin,zmin,xmax,ymax,zmax);
domain->lattice->bbox(1,bboxhi[0],bboxlo[1],bboxhi[2],
xmin,ymin,zmin,xmax,ymax,zmax);
domain->lattice->bbox(1,bboxlo[0],bboxhi[1],bboxhi[2],
xmin,ymin,zmin,xmax,ymax,zmax);
domain->lattice->bbox(1,bboxhi[0],bboxhi[1],bboxhi[2],
xmin,ymin,zmin,xmax,ymax,zmax);
// ilo:ihi,jlo:jhi,klo:khi = loop bounds for lattice overlap of my subbox
// overlap = any part of a unit cell (face,edge,pt) in common with my subbox
// in lattice space, subbox is a tilted box
// but bbox of subbox is aligned with lattice axes
// so ilo:khi unit cells should completely tile bounding box
// decrement lo, increment hi to avoid round-off issues in lattice->bbox(),
// which can lead to missing atoms in rare cases
// extra decrement of lo if min < 0, since static_cast(-1.5) = -1
int ilo,ihi,jlo,jhi,klo,khi;
ilo = static_cast<int> (xmin) - 1;
jlo = static_cast<int> (ymin) - 1;
klo = static_cast<int> (zmin) - 1;
ihi = static_cast<int> (xmax) + 1;
jhi = static_cast<int> (ymax) + 1;
khi = static_cast<int> (zmax) + 1;
if (xmin < 0.0) ilo--;
if (ymin < 0.0) jlo--;
if (zmin < 0.0) klo--;
// iterate on 3d periodic lattice of unit cells using loop bounds
// iterate on nbasis atoms in each unit cell
// convert lattice coords to box coords
// add atom or molecule (on each basis point) if it meets all criteria
double **basis = domain->lattice->basis;
double x[3],lamda[3];
double *coord;
int i,j,k,m;
for (k = klo; k <= khi; k++)
for (j = jlo; j <= jhi; j++)
for (i = ilo; i <= ihi; i++)
for (m = 0; m < nbasis; m++) {
x[0] = i + basis[m][0];
x[1] = j + basis[m][1];
x[2] = k + basis[m][2];
// convert from lattice coords to box coords
domain->lattice->lattice2box(x[0],x[1],x[2]);
// if a region was specified, test if atom is in it
if (style == REGION)
if (!domain->regions[nregion]->match(x[0],x[1],x[2])) continue;
// test if atom/molecule position is in my subbox
if (triclinic) {
domain->x2lamda(x,lamda);
coord = lamda;
} else coord = x;
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]) continue;
// add the atom or entire molecule to my list of atoms
if (mode == ATOM) atom->avec->create_atom(basistype[m],x);
else add_molecule(x);
}
}
/* ----------------------------------------------------------------------
add a randomly rotated molecule with its center at center
------------------------------------------------------------------------- */
void CreateAtoms::add_molecule(double *center)
{
int n;
double r[3],rotmat[3][3],quat[4],xnew[3];
if (domain->dimension == 3) {
r[0] = ranmol->uniform() - 0.5;
r[1] = ranmol->uniform() - 0.5;
r[2] = ranmol->uniform() - 0.5;
} else {
r[0] = r[1] = 0.0;
r[2] = 1.0;
}
double theta = ranmol->uniform() * MY_2PI;
MathExtra::norm3(r);
MathExtra::axisangle_to_quat(r,theta,quat);
MathExtra::quat_to_mat(quat,rotmat);
// create atoms in molecule with atom ID = 0 and mol ID = 0
// reset in caller after all moleclues created by all procs
// pass add_molecule_atom an offset of 0 since don't know
// max tag of atoms in previous molecules at this point
int natoms = onemol->natoms;
for (int m = 0; m < natoms; m++) {
MathExtra::matvec(rotmat,onemol->dx[m],xnew);
MathExtra::add3(xnew,center,xnew);
atom->avec->create_atom(ntype+onemol->type[m],xnew);
n = atom->nlocal - 1;
atom->add_molecule_atom(onemol,m,n,0);
}
}

Event Timeline