Unverified Commit ed87faec authored by Axel Kohlmeyer's avatar Axel Kohlmeyer Committed by GitHub
Browse files

Merge pull request #1697 from jrgissing/bond/react-angle-constraints

Bond/react: angle constraints
parents aa2b8857 23040a98
Loading
Loading
Loading
Loading
+13 −4
Original line number Diff line number Diff line
@@ -266,7 +266,7 @@ either 'none' or 'charges.' Further details are provided in the
discussion of the 'update_edges' keyword. The fourth optional section
begins with the keyword 'Constraints' and lists additional criteria
that must be satisfied in order for the reaction to occur. Currently,
there is one type of constraint available, as discussed below.
there are two types of constraints available, as discussed below.

A sample map file is given below:

@@ -300,14 +300,23 @@ Equivalences :pre
:line

Any number of additional constraints may be specified in the
Constraints section of the map file. Currently there is one type of
additional constraint, of type 'distance', whose syntax is as follows:
Constraints section of the map file. The constraint of type 'distance'
has syntax as follows:

distance {ID1} {ID2} {rmin} {rmax} :pre

where 'distance' is the required keyword, {ID1} and {ID2} are
pre-reaction atom IDs, and these two atoms must be separated by a
distance between {rmin} and {rmax} for the reaction to occur. This
distance between {rmin} and {rmax} for the reaction to occur.

The constraint of type 'angle' has the following syntax:

angle {ID1} {ID2} {ID3} {amin} {amax} :pre

where 'angle' is the required keyword, {ID1}, {ID2} and {ID3} are
pre-reaction atom IDs, and these three atoms must form an angle
between {amin} and {amax} for the reaction to occur (where {ID2} is
the central atom). Angles must be specified in degrees. This
constraint can be used to enforce a certain orientation between
reacting molecules.

+89 −23
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ Contributing Author: Jacob Gissinger (jacob.gissinger@colorado.edu)
#include "molecule.h"
#include "group.h"
#include "citeme.h"
#include "math_const.h"
#include "memory.h"
#include "error.h"

@@ -42,6 +43,7 @@ Contributing Author: Jacob Gissinger (jacob.gissinger@colorado.edu)

using namespace LAMMPS_NS;
using namespace FixConst;
using namespace MathConst;

static const char cite_fix_bond_react[] =
  "fix bond/react:\n\n"
@@ -57,7 +59,7 @@ static const char cite_fix_bond_react[] =
#define BIG 1.0e20
#define DELTA 16
#define MAXGUESS 20 // max # of guesses allowed by superimpose algorithm
#define MAXCONARGS 5 // max # of arguments for any type of constraint
#define MAXCONARGS 7 // max # of arguments for any type of constraint + rxnID

// various statuses of superimpose algorithm:
// ACCEPT: site successfully matched to pre-reacted template
@@ -68,6 +70,9 @@ static const char cite_fix_bond_react[] =
// RESTORE: restore mode, load most recent restore point
enum{ACCEPT,REJECT,PROCEED,CONTINUE,GUESSFAIL,RESTORE};

// types of available reaction constraints
enum{DISTANCE,ANGLE};

/* ---------------------------------------------------------------------- */

FixBondReact::FixBondReact(LAMMPS *lmp, int narg, char **arg) :
@@ -94,6 +99,7 @@ FixBondReact::FixBondReact(LAMMPS *lmp, int narg, char **arg) :
  global_freq = 1;
  extvector = 0;
  rxnID = 0;
  nconstraints = 0;
  status = PROCEED;

  nxspecial = NULL;
@@ -169,8 +175,7 @@ FixBondReact::FixBondReact(LAMMPS *lmp, int narg, char **arg) :
  memory->create(limit_duration,nreacts,"bond/react:limit_duration");
  memory->create(stabilize_steps_flag,nreacts,"bond/react:stabilize_steps_flag");
  memory->create(update_edges_flag,nreacts,"bond/react:update_edges_flag");
  memory->create(nconstraints,nreacts,"bond/react:nconstraints");
  memory->create(constraints,nreacts,MAXCONARGS,"bond/react:constraints");
  memory->create(constraints,1,MAXCONARGS,"bond/react:constraints");
  memory->create(iatomtype,nreacts,"bond/react:iatomtype");
  memory->create(jatomtype,nreacts,"bond/react:jatomtype");
  memory->create(ibonding,nreacts,"bond/react:ibonding");
@@ -188,7 +193,6 @@ FixBondReact::FixBondReact(LAMMPS *lmp, int narg, char **arg) :
    max_rxn[i] = INT_MAX;
    stabilize_steps_flag[i] = 0;
    update_edges_flag[i] = 0;
    nconstraints[i] = 0;
    // set default limit duration to 60 timesteps
    limit_duration[i] = 60;
    reaction_count[i] = 0;
@@ -1138,6 +1142,22 @@ void FixBondReact::superimpose_algorithm()
      glove[myjbonding-1][1] = created[lcl_inst][1][rxnID];
      glove_counter++;

      // special case, only two atoms in reaction templates
      // then: bonding onemol_nxspecials guaranteed to be equal, and either 0 or 1
      if (glove_counter == onemol->natoms) {
        tagint local_atom1 = atom->map(glove[myibonding-1][1]);
        tagint local_atom2 = atom->map(glove[myjbonding-1][1]);
        if ( (nxspecial[local_atom1][0] == onemol_nxspecial[myibonding-1][0] &&
              nxspecial[local_atom2][0] == nxspecial[local_atom1][0]) &&
             (nxspecial[local_atom1][0] == 0 ||
              xspecial[local_atom1][0] == atom->tag[local_atom2]) &&
             check_constraints() ) {
          status = ACCEPT;
          glove_ghostcheck();
        } else
          status = REJECT;
      }

      avail_guesses = 0;

      for (int i = 0; i < max_natoms; i++)
@@ -1617,21 +1637,50 @@ evaluate constraints: return 0 if any aren't satisfied

int FixBondReact::check_constraints()
{
  tagint atom1,atom2;
  tagint atom1,atom2,atom3;
  double delx,dely,delz,rsq;
  double delx1,dely1,delz1,delx2,dely2,delz2;
  double rsq1,rsq2,r1,r2,c;

  double **x = atom->x;

  for (int i = 0; i < nconstraints[rxnID]; i++) {
    if (constraints[rxnID][0] == 0) { // 'distance' type
      atom1 = atom->map(glove[(int) constraints[rxnID][1]-1][1]);
      atom2 = atom->map(glove[(int) constraints[rxnID][2]-1][1]);
  for (int i = 0; i < nconstraints; i++) {
    if (constraints[i][0] == rxnID) {
      if (constraints[i][1] == DISTANCE) {
        atom1 = atom->map(glove[(int) constraints[i][2]-1][1]);
        atom2 = atom->map(glove[(int) constraints[i][3]-1][1]);
        delx = x[atom1][0] - x[atom2][0];
        dely = x[atom1][1] - x[atom2][1];
        delz = x[atom1][2] - x[atom2][2];
        domain->minimum_image(delx,dely,delz); // ghost location fix
        rsq = delx*delx + dely*dely + delz*delz;
      if (rsq < constraints[rxnID][3] || rsq > constraints[rxnID][4]) return 0;
        if (rsq < constraints[i][4] || rsq > constraints[i][5]) return 0;
      } else if (constraints[i][1] == ANGLE) {
        atom1 = atom->map(glove[(int) constraints[i][2]-1][1]);
        atom2 = atom->map(glove[(int) constraints[i][3]-1][1]);
        atom3 = atom->map(glove[(int) constraints[i][4]-1][1]);

        // 1st bond
        delx1 = x[atom1][0] - x[atom2][0];
        dely1 = x[atom1][1] - x[atom2][1];
        delz1 = x[atom1][2] - x[atom2][2];
        rsq1 = delx1*delx1 + dely1*dely1 + delz1*delz1;
        r1 = sqrt(rsq1);

        // 2nd bond
        delx2 = x[atom3][0] - x[atom2][0];
        dely2 = x[atom3][1] - x[atom2][1];
        delz2 = x[atom3][2] - x[atom2][2];
        rsq2 = delx2*delx2 + dely2*dely2 + delz2*delz2;
        r2 = sqrt(rsq2);

        // angle (cos and sin)
        c = delx1*delx2 + dely1*dely2 + delz1*delz2;
        c /= r1*r2;
        if (c > 1.0) c = 1.0;
        if (c < -1.0) c = -1.0;
        if (acos(c) < constraints[i][5] || acos(c) > constraints[i][6]) return 0;
      }
    }
  }
  return 1;
@@ -2757,13 +2806,20 @@ void FixBondReact::read(int myrxn)
    if (strspn(line," \t\n\r") == strlen(line)) continue;

    if (strstr(line,"edgeIDs")) sscanf(line,"%d",&nedge);
    else if (strstr(line,"equivalences")) sscanf(line,"%d",&nequivalent);
    else if (strstr(line,"equivalences")) {
      sscanf(line,"%d",&nequivalent);
      if (nequivalent != onemol->natoms)
        error->one(FLERR,"Bond/react: Number of equivalences in map file must "
                                  "equal number of atoms in reaction templates");
    }
    else if (strstr(line,"customIDs")) sscanf(line,"%d",&ncustom);
    else if (strstr(line,"deleteIDs")) sscanf(line,"%d",&ndelete);
    else if (strstr(line,"constraints")) sscanf(line,"%d",&nconstraints[myrxn]);
    else if (strstr(line,"constraints")) sscanf(line,"%d",&nconstr);
    else break;
  }

  memory->grow(constraints,nconstraints+nconstr,MAXCONARGS,"bond/react:constraints");

  //count = NULL;

  // grab keyword and skip next line
@@ -2874,18 +2930,28 @@ void FixBondReact::Constraints(char *line, int myrxn)
  double tmp[MAXCONARGS];
  int n = strlen("distance") + 1;
  char *constraint_type = new char[n];
  for (int i = 0; i < nconstraints[myrxn]; i++) {
  for (int i = 0; i < nconstr; i++) {
    readline(line);
    sscanf(line,"%s",constraint_type);
    constraints[nconstraints][0] = myrxn;
    if (strcmp(constraint_type,"distance") == 0) {
      constraints[myrxn][0] = 0; // 0 = 'distance' ...maybe use another enum eventually
      constraints[nconstraints][1] = DISTANCE;
      sscanf(line,"%*s %lg %lg %lg %lg",&tmp[0],&tmp[1],&tmp[2],&tmp[3]);
      constraints[myrxn][1] = tmp[0];
      constraints[myrxn][2] = tmp[1];
      constraints[myrxn][3] = tmp[2]*tmp[2]; // using square of distance
      constraints[myrxn][4] = tmp[3]*tmp[3];
      constraints[nconstraints][2] = tmp[0];
      constraints[nconstraints][3] = tmp[1];
      constraints[nconstraints][4] = tmp[2]*tmp[2]; // using square of distance
      constraints[nconstraints][5] = tmp[3]*tmp[3];
    } else if (strcmp(constraint_type,"angle") == 0) {
      constraints[nconstraints][1] = ANGLE;
      sscanf(line,"%*s %lg %lg %lg %lg %lg",&tmp[0],&tmp[1],&tmp[2],&tmp[3],&tmp[4]);
      constraints[nconstraints][2] = tmp[0];
      constraints[nconstraints][3] = tmp[1];
      constraints[nconstraints][4] = tmp[2];
      constraints[nconstraints][5] = tmp[3]/180.0 * MY_PI;
      constraints[nconstraints][6] = tmp[4]/180.0 * MY_PI;
    } else
      error->one(FLERR,"Bond/react: Illegal constraint type in 'Constraints' section of map file");
    nconstraints++;
  }
  delete [] constraint_type;
}
+2 −2
Original line number Diff line number Diff line
@@ -64,7 +64,7 @@ class FixBondReact : public Fix {
  int custom_exclude_flag;
  int *stabilize_steps_flag;
  int *update_edges_flag;
  int *nconstraints;
  int nconstraints;
  double **constraints;
  int status;
  int *groupbits;
@@ -108,7 +108,7 @@ class FixBondReact : public Fix {

  int *ibonding,*jbonding;
  int *closeneigh; // indicates if bonding atoms of a rxn are 1-2, 1-3, or 1-4 neighbors
  int nedge,nequivalent,ncustom,ndelete; // number of edge, equivalent, custom atoms in mapping file
  int nedge,nequivalent,ncustom,ndelete,nconstr; // # edge, equivalent, custom atoms in mapping file
  int attempted_rxn; // there was an attempt!
  int *local_rxn_count;
  int *ghostly_rxn_count;