Commit f3cfb9c8 authored by jrgissing's avatar jrgissing
Browse files

add exactly N particles to available lattice points

a couple other modifications which helped setting up and testing simulations for bond/react
parent e84b6d80
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
@@ -24,13 +24,14 @@ style = {box} or {region} or {single} or {random} :l
    seed = random # seed (positive integer)
    region-ID = create atoms within this region, use NULL for entire simulation box :pre
zero or more keyword/value pairs may be appended :l
keyword = {mol} or {basis} or {remap} or {var} or {set} or {units} :l
keyword = {mol} or {basis} or {insert} or {remap} or {var} or {set} or {units} :l
  {mol} value = template-ID seed
    template-ID = ID of molecule template specified in a separate "molecule"_molecule.html command
    seed = random # seed (positive integer)
  {basis} values = M itype
    M = which basis atom
    itype = atom type (1-N) to assign to this basis atom
  {insert} value = number of particles to insert
  {remap} value = {yes} or {no}
  {var} value = name = variable name to evaluate for test of atom creation
  {set} values = dim name
@@ -193,6 +194,11 @@ command for specifics on how basis atoms are defined for the unit cell
of the lattice.  By default, all created atoms are assigned the
argument {type} as their atom type.

The {insert} keyword can be used in conjuction with the {box} or
{region} styles to limit the total number of particles inserted. The
specified number of particles are placed randomly on the available
lattice points.

The {remap} keyword only applies to the {single} style.  If it is set
to {yes}, then if the specified position is outside the simulation
box, it will mapped back into the box, assuming the relevant
+155 −36
Original line number Diff line number Diff line
@@ -54,6 +54,9 @@ CreateAtoms::CreateAtoms(LAMMPS *lmp) : Pointers(lmp) {}

void CreateAtoms::command(int narg, char **arg)
{
  MPI_Comm_rank(world,&me);
  MPI_Comm_size(world,&nprocs);
  
  if (domain->box_exist == 0)
    error->all(FLERR,"Create_atoms command before simulation box is defined");
  if (modify->nfix_restart_peratom)
@@ -107,9 +110,12 @@ void CreateAtoms::command(int narg, char **arg)
  remapflag = 0;
  mode = ATOM;
  int molseed;
  int nboxseed;
  varflag = 0;
  vstr = xstr = ystr = zstr = NULL;
  quatone[0] = quatone[1] = quatone[2] = 0.0;
  nlattpts = created_Nmask = nbox = nboxflag = 0;
  Nmask = NULL;
  
  nbasis = domain->lattice->nbasis;
  basistype = new int[nbasis];
@@ -192,6 +198,12 @@ void CreateAtoms::command(int narg, char **arg)
      MathExtra::norm3(axisone);
      MathExtra::axisangle_to_quat(axisone,thetaone,quatone);
      iarg += 5;
    } else if (strcmp(arg[iarg],"insert") == 0) {
      if (iarg+3 > narg) error->all(FLERR,"Illegal create_atoms command");
      nbox = force->inumeric(FLERR,arg[iarg+1]);
      nboxseed = force->inumeric(FLERR,arg[iarg+2]);
      nboxflag = 1;
      iarg += 3;
    } else error->all(FLERR,"Illegal create_atoms command");
  }

@@ -229,6 +241,10 @@ void CreateAtoms::command(int narg, char **arg)
    ranmol = new RanMars(lmp,molseed+comm->me);
  }

  if (nboxflag) {
    ranbox = new RanMars(lmp,nboxseed+comm->me);
  }
  
  // error check and further setup for variable test

  if (!vstr && (xstr || ystr || zstr))
@@ -517,6 +533,7 @@ void CreateAtoms::command(int narg, char **arg)
  delete [] xstr;
  delete [] ystr;
  delete [] zstr;
  delete [] Nmask;
  
  // print status

@@ -735,6 +752,12 @@ void CreateAtoms::add_lattice()
  double *coord;

  int i,j,k,m;
  
  // first pass: count how many particles will be inserted
  // second pass: filter to N number of particles (and insert)
  int maskcntr = 0;
  for (int pass = 0; pass < 2; pass++) {
    if (pass == 1) lattice_mask();
    for (k = klo; k <= khi; k++)
      for (j = jlo; j <= jhi; j++)
        for (i = ilo; i <= ihi; i++)
@@ -769,11 +792,107 @@ void CreateAtoms::add_lattice()
                coord[2] < sublo[2] || coord[2] >= subhi[2]) continue;
    
            // add the atom or entire molecule to my list of atoms

            if (pass == 0) nlattpts++;
            else {
              if (Nmask[maskcntr++])
                if (mode == ATOM) atom->avec->create_atom(basistype[m],x);
                else add_molecule(x);
            }
          }
  }
}

/* ----------------------------------------------------------------------
   define a random mask to insert only N particles on lattice
------------------------------------------------------------------------- */

void CreateAtoms::lattice_mask()
{

  Nmask = new int[nlattpts];
  for (int i = 0; i < nlattpts; i++) 
    Nmask[i] = 1;
  
  if (nbox == 0 && nboxflag && me == 0) error->warning(FLERR,"Specifying an 'insert' value of '0' is equivalent to no 'insert' keyword");
  
  int nboxme = 0;
  if (nbox > 0) {
    if (nprocs > 1) {
      int *allnlattpts = new int[nprocs]();
      
      MPI_Allgather(&nlattpts, 1, MPI_INT, allnlattpts, 1, MPI_INT, world);
      
      int total_lattpts = 0;
      for (int i = 0; i < nprocs; i++)
        total_lattpts += allnlattpts[i];
      
      if (nbox > total_lattpts) error->all(FLERR,"Attempting to insert more particles than available lattice points");
      if (nbox < 0) error->all(FLERR,"Cannot insert a negative number of particles (in this universe)");
      
      // adjust nboxme based on personal number of eligible lattice points
      
      nboxme = round(nbox*nlattpts/total_lattpts);
      
      // readjust so that all nboxme's add to exactly nbox
      
      int sum_nboxme;
      MPI_Allreduce(&nboxme,&sum_nboxme,1,MPI_INT,MPI_SUM,world);
      
      if (nbox != sum_nboxme) {
      
        int diff = nbox - sum_nboxme;
        int diff_sign = 1;
        if (diff < 0) {
          diff_sign = -1;
          diff = -diff;
        }
        
        // go around adding or subtracting one from all processors (if there's space) until equal
        int which_proc = 0;
        int success_me = 0, success_all = 0;
        int failed_me = 0, failed_all = 0;
        while (success_all < diff && failed_all < nprocs) {
          if (me == which_proc++ && !failed_me)
            if (nboxme < nlattpts) {
              nboxme += diff_sign;
              success_me++;
            } else {
              failed_me == 1;
            }
          MPI_Allreduce(&success_me,&success_all,1,MPI_INT,MPI_SUM,world);
          MPI_Allreduce(&failed_me,&failed_all,1,MPI_INT,MPI_SUM,world);
          if (which_proc > nprocs)
            which_proc = 0;
        }
        // should have guaranteed success at this point
        if (failed_all == nprocs) error->warning(FLERR,"This is an uncaught error. Ask developer");
      }
      
    } else nboxme = nbox;
    
    // let's insert N particles onto available lattice points by instead
    // poking [nlattpts - N] holes into the lattice, randomly
    int nholes = nlattpts - nboxme;
    int noptions = nlattpts;
    for (int i = 0; i < nholes; i++) {
      int hindex = ceil(ranbox->uniform()*noptions);
      int optcount = 0;
      for (int j = 0; j < nlattpts; j++) {
        if (Nmask[j] == 1) {
          optcount++;
          if (optcount == hindex) {
            Nmask[j] = 0;
            noptions--;
            break;
          }  
        }
      }
    }
  }
  
  created_Nmask = 1;
  
}

/* ----------------------------------------------------------------------
   add a randomly rotated molecule with its center at center
+16 −2
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ class CreateAtoms : protected Pointers {
  void command(int, char **);

 private:
  int me,nprocs;
  int ntype,style,mode,nregion,nbasis,nrandom,seed;
  int *basistype;
  double xone[3],quatone[4];
@@ -41,6 +42,7 @@ class CreateAtoms : protected Pointers {

  class Molecule *onemol;
  class RanMars *ranmol;
  class RanMars *ranbox;
  
  int triclinic;
  double sublo[3],subhi[3];   // epsilon-extended proc sub-box for adding atoms
@@ -48,7 +50,11 @@ class CreateAtoms : protected Pointers {
  void add_single();
  void add_random();
  void add_lattice();
  void lattice_mask();
  void add_molecule(double *, double * = NULL);
  int nlattpts;                // number of eligible lattice points
  int *Nmask;                  // used to insert N number of particles on lattice
  int created_Nmask,nbox,nboxflag; 
  int vartest(double *);       // evaluate a variable with new atom position
};

@@ -152,4 +158,12 @@ E: No overlap of box and region for create_atoms

Self-explanatory.

E: Attempting to insert more particles than available lattice points

Self-explanatory.

W: Specifying an 'insert' value of '0' is equivalent to no 'insert' keyword

Self-explanatory.

*/