Merge branch 'master' of https://github.com/lammps/lammps into kk_pair_fix_comm

This commit is contained in:
Stan Moore
2020-12-24 08:08:19 -07:00
7 changed files with 270 additions and 196 deletions

View File

@ -55,8 +55,8 @@ if(DOWNLOAD_PLUMED)
endif()
include(ExternalProject)
ExternalProject_Add(plumed_build
URL https://github.com/plumed/plumed2/releases/download/v2.6.1/plumed-src-2.6.1.tgz
URL_MD5 89a9a450fc6025299fe16af235957163
URL https://github.com/plumed/plumed2/releases/download/v2.7.0/plumed-src-2.7.0.tgz
URL_MD5 95f29dd0c067577f11972ff90dfc7d12
BUILD_IN_SOURCE 1
CONFIGURE_COMMAND <SOURCE_DIR>/configure --prefix=<INSTALL_DIR>
${CONFIGURE_REQUEST_PIC}

View File

@ -457,6 +457,23 @@ example, the molecule fragment could consist of only the backbone
atoms of a polymer chain. This constraint can be used to enforce a
specific relative position and orientation between reacting molecules.
By default, all constraints must be satisfied for the reaction to
occur. In other words, constraints are evaluated as a series of
logical values using the logical AND operator "&&". More complex logic
can be achieved by explicitly adding the logical AND operator "&&" or
the logical OR operator "||" after a given constraint command. If a
logical operator is specified after a constraint, it must be placed
after all constraint parameters, on the same line as the constraint
(one per line). Similarly, parentheses can be used to group
constraints. The expression that results from concatenating all
constraints should be a valid logical expression that can be read by
the :doc:`variable <variable>` command after converting each
constraint to a logical value. Because exactly one constraint is
allowed per line, having a valid logical expression implies that left
parentheses "(" should only appear before a constraint, and right
parentheses ")" should only appear after a constraint and before any
logical operator.
Once a reaction site has been successfully identified, data structures
within LAMMPS that store bond topology are updated to reflect the
post-reacted molecule template. All force fields with fixed bonds,
@ -599,8 +616,8 @@ reset_mol_ids = yes, custom_charges = no, molecule = off
.. _Gissinger:
**(Gissinger)** Gissinger, Jensen and Wise, Polymer, 128, 211 (2017).
**(Gissinger)** Gissinger, Jensen and Wise, Polymer, 128, 211-217 (2017).
.. _Gissinger2020:
**(Gissinger)** Gissinger, Jensen and Wise, Macromolecules (2020, in press).
**(Gissinger)** Gissinger, Jensen and Wise, Macromolecules, 53, 22, 99539961 (2020).

View File

@ -17,7 +17,7 @@ parser = ArgumentParser(prog='Install.py',
# settings
version = "2.6.1"
version = "2.7.0"
mode = "static"
# help message
@ -49,6 +49,7 @@ checksums = { \
'2.5.4' : 'f31b7d16a4be2e30aa7d5c19c3d37853', \
'2.6.0' : '204d2edae58d9b10ba3ad460cad64191', \
'2.6.1' : '89a9a450fc6025299fe16af235957163', \
'2.7.0' : '95f29dd0c067577f11972ff90dfc7d12', \
}
# parse and process arguments

View File

@ -2542,13 +2542,13 @@ void FixShake::stats()
const auto bcnt = b_count_all[i]/2;
if (bcnt)
mesg += fmt::format("{:>6d} {:<9.6} {:<11.6} {:>8d}\n",i,
b_ave_all[i]/bcnt,b_max_all[i]-b_min_all[i],bcnt);
b_ave_all[i]/bcnt/2.0,b_max_all[i]-b_min_all[i],bcnt);
}
for (i = 1; i < na; i++) {
const auto acnt = a_count_all[i]/3;
if (acnt)
mesg += fmt::format("{:>6d} {:<9.6} {:<11.6} {:>8d}\n",i,
a_ave_all[i]/acnt,a_max_all[i]-a_min_all[i],acnt);
a_ave_all[i]/acnt/3.0,a_max_all[i]-a_min_all[i],acnt);
}
utils::logmesg(lmp,mesg);
}

View File

@ -78,9 +78,9 @@ FixPlumed::FixPlumed(LAMMPS *lmp, int narg, char **arg) :
int api_version=0;
p->cmd("getApiVersion",&api_version);
if ((api_version < 5) || (api_version > 7))
if ((api_version < 5) || (api_version > 8))
error->all(FLERR,"Incompatible API version for PLUMED in fix plumed. "
"Only Plumed 2.4.x, 2.5.x, and 2.6.x are tested and supported.");
"Only Plumed 2.4.x, 2.5.x, 2.6.x, 2.7.x are tested and supported.");
#if !defined(MPI_STUBS)
// If the -partition option is activated then enable

View File

@ -82,6 +82,9 @@ enum{ACCEPT,REJECT,PROCEED,CONTINUE,GUESSFAIL,RESTORE};
// types of available reaction constraints
enum{DISTANCE,ANGLE,DIHEDRAL,ARRHENIUS,RMSD};
// ID type used by constraint
enum{ATOM,FRAG};
// keyword values that accept variables as input
enum{NEVERY,RMIN,RMAX,PROB};
@ -115,7 +118,6 @@ FixBondReact::FixBondReact(LAMMPS *lmp, int narg, char **arg) :
global_freq = 1;
extvector = 0;
rxnID = 0;
nconstraints = 0;
narrhenius = 0;
status = PROCEED;
@ -206,7 +208,9 @@ FixBondReact::FixBondReact(LAMMPS *lmp, int narg, char **arg) :
memory->create(stabilize_steps_flag,nreacts,"bond/react:stabilize_steps_flag");
memory->create(custom_charges_fragid,nreacts,"bond/react:custom_charges_fragid");
memory->create(molecule_keyword,nreacts,"bond/react:molecule_keyword");
memory->create(constraints,1,MAXCONARGS,"bond/react:constraints");
memory->create(nconstraints,nreacts,"bond/react:nconstraints");
memory->create(constraintstr,nreacts,MAXLINE,"bond/react:constraintstr");
memory->create(constraints,0,nreacts,"bond/react:constraints");
memory->create(var_flag,NUMVARVALS,nreacts,"bond/react:var_flag");
memory->create(var_id,NUMVARVALS,nreacts,"bond/react:var_id");
memory->create(iatomtype,nreacts,"bond/react:iatomtype");
@ -227,6 +231,7 @@ FixBondReact::FixBondReact(LAMMPS *lmp, int narg, char **arg) :
stabilize_steps_flag[i] = 0;
custom_charges_fragid[i] = -1;
molecule_keyword[i] = OFF;
nconstraints[i] = 0;
// set default limit duration to 60 timesteps
limit_duration[i] = 60;
reaction_count[i] = 0;
@ -440,9 +445,11 @@ FixBondReact::FixBondReact(LAMMPS *lmp, int narg, char **arg) :
rrhandom = new class RanMars*[narrhenius];
int tmp = 0;
for (int i = 0; i < nconstraints; i++) {
if (constraints[i][1] == ARRHENIUS) {
rrhandom[tmp++] = new RanMars(lmp,(int) constraints[i][6] + me);
for (int i = 0; i < nreacts; i++) {
for (int j = 0; j < nconstraints[i]; j++) {
if (constraints[j][i].type == ARRHENIUS) {
rrhandom[tmp++] = new RanMars(lmp,(int) constraints[j][i].par[4] + me);
}
}
}
@ -562,6 +569,9 @@ FixBondReact::~FixBondReact()
memory->destroy(stabilize_steps_flag);
memory->destroy(custom_charges_fragid);
memory->destroy(molecule_keyword);
memory->destroy(constraints);
memory->destroy(nconstraints);
// need to delete rxn_name and constraintstr
memory->destroy(iatomtype);
memory->destroy(jatomtype);
@ -1795,163 +1805,178 @@ int FixBondReact::check_constraints()
tagint atom1,atom2;
double **x = atom->x;
for (int i = 0; i < nconstraints; i++) {
if (constraints[i][0] == rxnID) {
if (constraints[i][1] == DISTANCE) {
get_IDcoords((int) constraints[i][2], (int) constraints[i][3], x1);
get_IDcoords((int) constraints[i][4], (int) constraints[i][5], x2);
delx = x1[0] - x2[0];
dely = x1[1] - x2[1];
delz = x1[2] - x2[2];
domain->minimum_image(delx,dely,delz); // ghost location fix
rsq = delx*delx + dely*dely + delz*delz;
if (rsq < constraints[i][6] || rsq > constraints[i][7]) return 0;
} else if (constraints[i][1] == ANGLE) {
get_IDcoords((int) constraints[i][2], (int) constraints[i][3], x1);
get_IDcoords((int) constraints[i][4], (int) constraints[i][5], x2);
get_IDcoords((int) constraints[i][6], (int) constraints[i][7], x3);
int *satisfied;
memory->create(satisfied,nconstraints[rxnID],"bond/react:satisfied");
for (int i = 0; i < nconstraints[rxnID]; i++)
satisfied[i] = 1;
// 1st bond
delx1 = x1[0] - x2[0];
dely1 = x1[1] - x2[1];
delz1 = x1[2] - x2[2];
domain->minimum_image(delx1,dely1,delz1); // ghost location fix
rsq1 = delx1*delx1 + dely1*dely1 + delz1*delz1;
r1 = sqrt(rsq1);
for (int i = 0; i < nconstraints[rxnID]; i++) {
if (constraints[i][rxnID].type == DISTANCE) {
get_IDcoords(constraints[i][rxnID].idtype[0], constraints[i][rxnID].id[0], x1);
get_IDcoords(constraints[i][rxnID].idtype[1], constraints[i][rxnID].id[1], x2);
delx = x1[0] - x2[0];
dely = x1[1] - x2[1];
delz = x1[2] - x2[2];
domain->minimum_image(delx,dely,delz); // ghost location fix
rsq = delx*delx + dely*dely + delz*delz;
if (rsq < constraints[i][rxnID].par[0] || rsq > constraints[i][rxnID].par[1]) satisfied[i] = 0;
} else if (constraints[i][rxnID].type == ANGLE) {
get_IDcoords(constraints[i][rxnID].idtype[0], constraints[i][rxnID].id[0], x1);
get_IDcoords(constraints[i][rxnID].idtype[1], constraints[i][rxnID].id[1], x2);
get_IDcoords(constraints[i][rxnID].idtype[2], constraints[i][rxnID].id[2], x3);
// 2nd bond
delx2 = x3[0] - x2[0];
dely2 = x3[1] - x2[1];
delz2 = x3[2] - x2[2];
domain->minimum_image(delx2,dely2,delz2); // ghost location fix
rsq2 = delx2*delx2 + dely2*dely2 + delz2*delz2;
r2 = sqrt(rsq2);
// 1st bond
delx1 = x1[0] - x2[0];
dely1 = x1[1] - x2[1];
delz1 = x1[2] - x2[2];
domain->minimum_image(delx1,dely1,delz1); // ghost location fix
rsq1 = delx1*delx1 + dely1*dely1 + delz1*delz1;
r1 = sqrt(rsq1);
// 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][8] || acos(c) > constraints[i][9]) return 0;
} else if (constraints[i][1] == DIHEDRAL) {
// phi calculation from dihedral style harmonic
get_IDcoords((int) constraints[i][2], (int) constraints[i][3], x1);
get_IDcoords((int) constraints[i][4], (int) constraints[i][5], x2);
get_IDcoords((int) constraints[i][6], (int) constraints[i][7], x3);
get_IDcoords((int) constraints[i][8], (int) constraints[i][9], x4);
// 2nd bond
delx2 = x3[0] - x2[0];
dely2 = x3[1] - x2[1];
delz2 = x3[2] - x2[2];
domain->minimum_image(delx2,dely2,delz2); // ghost location fix
rsq2 = delx2*delx2 + dely2*dely2 + delz2*delz2;
r2 = sqrt(rsq2);
vb1x = x1[0] - x2[0];
vb1y = x1[1] - x2[1];
vb1z = x1[2] - x2[2];
domain->minimum_image(vb1x,vb1y,vb1z);
// 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][rxnID].par[0] || acos(c) > constraints[i][rxnID].par[1]) satisfied[i] = 0;
} else if (constraints[i][rxnID].type == DIHEDRAL) {
// phi calculation from dihedral style harmonic
get_IDcoords(constraints[i][rxnID].idtype[0], constraints[i][rxnID].id[0], x1);
get_IDcoords(constraints[i][rxnID].idtype[1], constraints[i][rxnID].id[1], x2);
get_IDcoords(constraints[i][rxnID].idtype[2], constraints[i][rxnID].id[2], x3);
get_IDcoords(constraints[i][rxnID].idtype[3], constraints[i][rxnID].id[3], x4);
vb2x = x3[0] - x2[0];
vb2y = x3[1] - x2[1];
vb2z = x3[2] - x2[2];
domain->minimum_image(vb2x,vb2y,vb2z);
vb1x = x1[0] - x2[0];
vb1y = x1[1] - x2[1];
vb1z = x1[2] - x2[2];
domain->minimum_image(vb1x,vb1y,vb1z);
vb2xm = -vb2x;
vb2ym = -vb2y;
vb2zm = -vb2z;
domain->minimum_image(vb2xm,vb2ym,vb2zm);
vb2x = x3[0] - x2[0];
vb2y = x3[1] - x2[1];
vb2z = x3[2] - x2[2];
domain->minimum_image(vb2x,vb2y,vb2z);
vb3x = x4[0] - x3[0];
vb3y = x4[1] - x3[1];
vb3z = x4[2] - x3[2];
domain->minimum_image(vb3x,vb3y,vb3z);
vb2xm = -vb2x;
vb2ym = -vb2y;
vb2zm = -vb2z;
domain->minimum_image(vb2xm,vb2ym,vb2zm);
ax = vb1y*vb2zm - vb1z*vb2ym;
ay = vb1z*vb2xm - vb1x*vb2zm;
az = vb1x*vb2ym - vb1y*vb2xm;
bx = vb3y*vb2zm - vb3z*vb2ym;
by = vb3z*vb2xm - vb3x*vb2zm;
bz = vb3x*vb2ym - vb3y*vb2xm;
vb3x = x4[0] - x3[0];
vb3y = x4[1] - x3[1];
vb3z = x4[2] - x3[2];
domain->minimum_image(vb3x,vb3y,vb3z);
rasq = ax*ax + ay*ay + az*az;
rbsq = bx*bx + by*by + bz*bz;
rgsq = vb2xm*vb2xm + vb2ym*vb2ym + vb2zm*vb2zm;
rg = sqrt(rgsq);
ax = vb1y*vb2zm - vb1z*vb2ym;
ay = vb1z*vb2xm - vb1x*vb2zm;
az = vb1x*vb2ym - vb1y*vb2xm;
bx = vb3y*vb2zm - vb3z*vb2ym;
by = vb3z*vb2xm - vb3x*vb2zm;
bz = vb3x*vb2ym - vb3y*vb2xm;
ra2inv = rb2inv = 0.0;
if (rasq > 0) ra2inv = 1.0/rasq;
if (rbsq > 0) rb2inv = 1.0/rbsq;
rabinv = sqrt(ra2inv*rb2inv);
rasq = ax*ax + ay*ay + az*az;
rbsq = bx*bx + by*by + bz*bz;
rgsq = vb2xm*vb2xm + vb2ym*vb2ym + vb2zm*vb2zm;
rg = sqrt(rgsq);
c = (ax*bx + ay*by + az*bz)*rabinv;
s = rg*rabinv*(ax*vb3x + ay*vb3y + az*vb3z);
ra2inv = rb2inv = 0.0;
if (rasq > 0) ra2inv = 1.0/rasq;
if (rbsq > 0) rb2inv = 1.0/rbsq;
rabinv = sqrt(ra2inv*rb2inv);
if (c > 1.0) c = 1.0;
if (c < -1.0) c = -1.0;
phi = atan2(s,c);
c = (ax*bx + ay*by + az*bz)*rabinv;
s = rg*rabinv*(ax*vb3x + ay*vb3y + az*vb3z);
ANDgate = 0;
if (constraints[i][10] < constraints[i][11]) {
if (phi > constraints[i][10] && phi < constraints[i][11]) ANDgate = 1;
} else {
if (phi > constraints[i][10] || phi < constraints[i][11]) ANDgate = 1;
}
if (constraints[i][12] < constraints[i][13]) {
if (phi > constraints[i][12] && phi < constraints[i][13]) ANDgate = 1;
} else {
if (phi > constraints[i][12] || phi < constraints[i][13]) ANDgate = 1;
}
if (ANDgate != 1) return 0;
} else if (constraints[i][1] == ARRHENIUS) {
t = get_temperature();
prrhob = constraints[i][3]*pow(t,constraints[i][4])*
exp(-constraints[i][5]/(force->boltz*t));
if (prrhob < rrhandom[(int) constraints[i][2]]->uniform()) return 0;
} else if (constraints[i][1] == RMSD) {
// call superpose
int iatom;
int iref = -1; // choose first atom as reference
int n2superpose = 0;
double **xfrozen; // coordinates for the "frozen" target molecule
double **xmobile; // coordinates for the "mobile" molecule
int ifragment = constraints[i][3];
if (ifragment >= 0) {
for (int j = 0; j < onemol->natoms; j++)
if (onemol->fragmentmask[ifragment][j]) n2superpose++;
memory->create(xfrozen,n2superpose,3,"bond/react:xfrozen");
memory->create(xmobile,n2superpose,3,"bond/react:xmobile");
int myincr = 0;
for (int j = 0; j < onemol->natoms; j++) {
if (onemol->fragmentmask[ifragment][j]) {
iatom = atom->map(glove[j][1]);
if (iref == -1) iref = iatom;
iatom = domain->closest_image(iref,iatom);
for (int k = 0; k < 3; k++) {
xfrozen[myincr][k] = x[iatom][k];
xmobile[myincr][k] = onemol->x[j][k];
}
myincr++;
}
}
} else {
int iatom;
int iref = -1; // choose first atom as reference
n2superpose = onemol->natoms;
memory->create(xfrozen,n2superpose,3,"bond/react:xfrozen");
memory->create(xmobile,n2superpose,3,"bond/react:xmobile");
for (int j = 0; j < n2superpose; j++) {
if (c > 1.0) c = 1.0;
if (c < -1.0) c = -1.0;
phi = atan2(s,c);
ANDgate = 0;
if (constraints[i][rxnID].par[0] < constraints[i][rxnID].par[1]) {
if (phi > constraints[i][rxnID].par[0] && phi < constraints[i][rxnID].par[1]) ANDgate = 1;
} else {
if (phi > constraints[i][rxnID].par[0] || phi < constraints[i][rxnID].par[1]) ANDgate = 1;
}
if (constraints[i][rxnID].par[2] < constraints[i][rxnID].par[3]) {
if (phi > constraints[i][rxnID].par[2] && phi < constraints[i][rxnID].par[3]) ANDgate = 1;
} else {
if (phi > constraints[i][rxnID].par[2] || phi < constraints[i][rxnID].par[3]) ANDgate = 1;
}
if (ANDgate != 1) satisfied[i] = 0;
} else if (constraints[i][rxnID].type == ARRHENIUS) {
t = get_temperature();
prrhob = constraints[i][rxnID].par[1]*pow(t,constraints[i][rxnID].par[2])*
exp(-constraints[i][rxnID].par[3]/(force->boltz*t));
if (prrhob < rrhandom[(int) constraints[i][rxnID].par[0]]->uniform()) satisfied[i] = 0;
} else if (constraints[i][rxnID].type == RMSD) {
// call superpose
int iatom;
int iref = -1; // choose first atom as reference
int n2superpose = 0;
double **xfrozen; // coordinates for the "frozen" target molecule
double **xmobile; // coordinates for the "mobile" molecule
int ifragment = constraints[i][rxnID].id[0];
if (ifragment >= 0) {
for (int j = 0; j < onemol->natoms; j++)
if (onemol->fragmentmask[ifragment][j]) n2superpose++;
memory->create(xfrozen,n2superpose,3,"bond/react:xfrozen");
memory->create(xmobile,n2superpose,3,"bond/react:xmobile");
int myincr = 0;
for (int j = 0; j < onemol->natoms; j++) {
if (onemol->fragmentmask[ifragment][j]) {
iatom = atom->map(glove[j][1]);
if (iref == -1) iref = iatom;
iatom = domain->closest_image(iref,iatom);
for (int k = 0; k < 3; k++) {
xfrozen[j][k] = x[iatom][k];
xmobile[j][k] = onemol->x[j][k];
xfrozen[myincr][k] = x[iatom][k];
xmobile[myincr][k] = onemol->x[j][k];
}
myincr++;
}
}
} else {
int iatom;
int iref = -1; // choose first atom as reference
n2superpose = onemol->natoms;
memory->create(xfrozen,n2superpose,3,"bond/react:xfrozen");
memory->create(xmobile,n2superpose,3,"bond/react:xmobile");
for (int j = 0; j < n2superpose; j++) {
iatom = atom->map(glove[j][1]);
if (iref == -1) iref = iatom;
iatom = domain->closest_image(iref,iatom);
for (int k = 0; k < 3; k++) {
xfrozen[j][k] = x[iatom][k];
xmobile[j][k] = onemol->x[j][k];
}
}
Superpose3D<double, double **> superposer(n2superpose);
double rmsd = superposer.Superpose(xfrozen, xmobile);
if (rmsd > constraints[i][2]) return 0;
memory->destroy(xfrozen);
memory->destroy(xmobile);
}
Superpose3D<double, double **> superposer(n2superpose);
double rmsd = superposer.Superpose(xfrozen, xmobile);
memory->destroy(xfrozen);
memory->destroy(xmobile);
if (rmsd > constraints[i][rxnID].par[0]) satisfied[i] = 0;
}
}
if (nconstraints[rxnID] > 0) {
char evalstr[MAXLINE],*ptr,valstr;
strcpy(evalstr,constraintstr[rxnID]);
for (int i = 0; i < nconstraints[rxnID]; i++) {
sprintf(&valstr,"%d", satisfied[i]);
ptr = strchr(evalstr,'C');
*ptr = valstr;
}
double verdict = input->variable->evaluate_boolean(evalstr);
if (verdict == 0.0) return 0;
}
// let's also check chirality within 'check_constraint'
for (int i = 0; i < onemol->natoms; i++) {
if (chiral_atoms[i][0][rxnID] == 1) {
@ -1975,6 +2000,7 @@ int FixBondReact::check_constraints()
}
}
memory->destroy(satisfied);
return 1;
}
@ -1987,7 +2013,7 @@ fragment: given pre-reacted molID (onemol) and fragID,
void FixBondReact::get_IDcoords(int mode, int myID, double *center)
{
double **x = atom->x;
if (mode == 1) {
if (mode == ATOM) {
int iatom = atom->map(glove[myID-1][1]);
for (int i = 0; i < 3; i++)
center[i] = x[iatom][i];
@ -3216,8 +3242,8 @@ void FixBondReact::read(int myrxn)
else if (strstr(line,"deleteIDs")) sscanf(line,"%d",&ndelete);
else if (strstr(line,"chiralIDs")) sscanf(line,"%d",&nchiral);
else if (strstr(line,"constraints")) {
sscanf(line,"%d",&nconstr);
memory->grow(constraints,nconstraints+nconstr,MAXCONARGS,"bond/react:constraints");
sscanf(line,"%d",&nconstraints[myrxn]);
memory->grow(constraints,nconstraints[myrxn],nreacts,"bond/react:constraints");
} else break;
}
@ -3252,7 +3278,7 @@ void FixBondReact::read(int myrxn)
} else if (strcmp(keyword,"ChiralIDs") == 0) {
ChiralCenters(line, myrxn);
} else if (strcmp(keyword,"Constraints") == 0) {
Constraints(line, myrxn);
ReadConstraints(line, myrxn);
} else error->one(FLERR,"Bond/react: Unknown section in map file");
parse_keyword(1,line,keyword);
@ -3350,69 +3376,89 @@ void FixBondReact::ChiralCenters(char *line, int myrxn)
}
}
void FixBondReact::Constraints(char *line, int myrxn)
void FixBondReact::ReadConstraints(char *line, int myrxn)
{
double tmp[MAXCONARGS];
char **strargs;
char **strargs,*ptr;
memory->create(strargs,MAXCONARGS,MAXLINE,"bond/react:strargs");
char *constraint_type = new char[MAXLINE];
for (int i = 0; i < nconstr; i++) {
strcpy(constraintstr[myrxn],"("); // string for boolean constraint logic
for (int i = 0; i < nconstraints[myrxn]; i++) {
readline(line);
if (ptr = strrchr(line,'(')) { // reverse char search
strncat(constraintstr[myrxn],line,ptr-line+1);
line = ptr + 1;
}
// 'C' indicates where to sub in next constraint
strcat(constraintstr[myrxn],"C");
if (ptr = strchr(line,')')) {
strncat(constraintstr[myrxn],ptr,strrchr(line,')')-ptr+1);
}
if (ptr = strstr(line,"&&")) {
strcat(constraintstr[myrxn],"&&");
*ptr = '\0';
} else if (ptr = strstr(line,"||")) {
strcat(constraintstr[myrxn],"||");
*ptr = '\0';
} else if (i+1 < nconstraints[myrxn]){
strcat(constraintstr[myrxn],"&&");
}
if (ptr = strchr(line,')'))
*ptr = '\0';
sscanf(line,"%s",constraint_type);
constraints[nconstraints][0] = myrxn;
if (strcmp(constraint_type,"distance") == 0) {
constraints[nconstraints][1] = DISTANCE;
constraints[i][myrxn].type = DISTANCE;
sscanf(line,"%*s %s %s %lg %lg",strargs[0],strargs[1],&tmp[0],&tmp[1]);
readID(strargs[0], nconstraints, 2, 3);
readID(strargs[1], nconstraints, 4, 5);
readID(strargs[0], i, myrxn, 0);
readID(strargs[1], i, myrxn, 1);
// cutoffs
constraints[nconstraints][6] = tmp[0]*tmp[0]; // using square of distance
constraints[nconstraints][7] = tmp[1]*tmp[1];
constraints[i][myrxn].par[0] = tmp[0]*tmp[0]; // using square of distance
constraints[i][myrxn].par[1] = tmp[1]*tmp[1];
} else if (strcmp(constraint_type,"angle") == 0) {
constraints[nconstraints][1] = ANGLE;
constraints[i][myrxn].type = ANGLE;
sscanf(line,"%*s %s %s %s %lg %lg",strargs[0],strargs[1],strargs[2],&tmp[0],&tmp[1]);
readID(strargs[0], nconstraints, 2, 3);
readID(strargs[1], nconstraints, 4, 5);
readID(strargs[2], nconstraints, 6, 7);
constraints[nconstraints][8] = tmp[0]/180.0 * MY_PI;
constraints[nconstraints][9] = tmp[1]/180.0 * MY_PI;
readID(strargs[0], i, myrxn, 0);
readID(strargs[1], i, myrxn, 1);
readID(strargs[2], i, myrxn, 2);
constraints[i][myrxn].par[0] = tmp[0]/180.0 * MY_PI;
constraints[i][myrxn].par[1] = tmp[1]/180.0 * MY_PI;
} else if (strcmp(constraint_type,"dihedral") == 0) {
constraints[nconstraints][1] = DIHEDRAL;
constraints[i][myrxn].type = DIHEDRAL;
tmp[2] = 181.0; // impossible range
tmp[3] = 182.0;
sscanf(line,"%*s %s %s %s %s %lg %lg %lg %lg",strargs[0],strargs[1],
strargs[2],strargs[3],&tmp[0],&tmp[1],&tmp[2],&tmp[3]);
readID(strargs[0], nconstraints, 2, 3);
readID(strargs[1], nconstraints, 4, 5);
readID(strargs[2], nconstraints, 6, 7);
readID(strargs[3], nconstraints, 8, 9);
constraints[nconstraints][10] = tmp[0]/180.0 * MY_PI;
constraints[nconstraints][11] = tmp[1]/180.0 * MY_PI;
constraints[nconstraints][12] = tmp[2]/180.0 * MY_PI;
constraints[nconstraints][13] = tmp[3]/180.0 * MY_PI;
readID(strargs[0], i, myrxn, 0);
readID(strargs[1], i, myrxn, 1);
readID(strargs[2], i, myrxn, 2);
readID(strargs[3], i, myrxn, 3);
constraints[i][myrxn].par[0] = tmp[0]/180.0 * MY_PI;
constraints[i][myrxn].par[1] = tmp[1]/180.0 * MY_PI;
constraints[i][myrxn].par[2] = tmp[2]/180.0 * MY_PI;
constraints[i][myrxn].par[3] = tmp[3]/180.0 * MY_PI;
} else if (strcmp(constraint_type,"arrhenius") == 0) {
constraints[nconstraints][1] = ARRHENIUS;
constraints[nconstraints][2] = narrhenius++;
constraints[i][myrxn].type = ARRHENIUS;
constraints[i][myrxn].par[0] = narrhenius++;
sscanf(line,"%*s %lg %lg %lg %lg",&tmp[0],&tmp[1],&tmp[2],&tmp[3]);
constraints[nconstraints][3] = tmp[0];
constraints[nconstraints][4] = tmp[1];
constraints[nconstraints][5] = tmp[2];
constraints[nconstraints][6] = tmp[3];
constraints[i][myrxn].par[1] = tmp[0];
constraints[i][myrxn].par[2] = tmp[1];
constraints[i][myrxn].par[3] = tmp[2];
constraints[i][myrxn].par[4] = tmp[3];
} else if (strcmp(constraint_type,"rmsd") == 0) {
constraints[nconstraints][1] = RMSD;
constraints[i][myrxn].type = RMSD;
strcpy(strargs[0],"0");
sscanf(line,"%*s %lg %s",&tmp[0],strargs[0]);
constraints[nconstraints][2] = tmp[0]; // RMSDmax
constraints[nconstraints][3] = -1; // optional molecule fragment
constraints[i][myrxn].par[0] = tmp[0]; // RMSDmax
constraints[i][myrxn].id[0] = -1; // optional molecule fragment
if (isalpha(strargs[0][0])) {
int ifragment = onemol->findfragment(strargs[0]);
if (ifragment < 0) error->one(FLERR,"Bond/react: Molecule fragment does not exist");
else constraints[nconstraints][3] = ifragment;
else constraints[i][myrxn].id[0] = ifragment;
}
} else
error->one(FLERR,"Bond/react: Illegal constraint type in 'Constraints' section of map file");
nconstraints++;
}
strcat(constraintstr[myrxn],")"); // close boolean constraint logic string
delete [] constraint_type;
memory->destroy(strargs);
}
@ -3422,18 +3468,18 @@ if ID starts with character, assume it is a pre-reaction molecule fragment ID
otherwise, it is a pre-reaction atom ID
---------------------------------------------------------------------- */
void FixBondReact::readID(char *strarg, int iconstr, int mode, int myID)
void FixBondReact::readID(char *strarg, int iconstr, int myrxn, int i)
{
if (isalpha(strarg[0])) {
constraints[iconstr][mode] = 0; // fragment vs. atom ID flag
constraints[iconstr][myrxn].idtype[i] = FRAG; // fragment vs. atom ID flag
int ifragment = onemol->findfragment(strarg);
if (ifragment < 0) error->one(FLERR,"Bond/react: Molecule fragment does not exist");
constraints[iconstr][myID] = ifragment;
constraints[iconstr][myrxn].id[i] = ifragment;
} else {
constraints[iconstr][mode] = 1; // fragment vs. atom ID flag
constraints[iconstr][myrxn].idtype[i] = ATOM; // fragment vs. atom ID flag
int iatom = atoi(strarg);
if (iatom > onemol->natoms) error->one(FLERR,"Bond/react: Invalid template atom ID in map file");
constraints[iconstr][myID] = iatom;
constraints[iconstr][myrxn].id[i] = iatom;
}
}

View File

@ -31,7 +31,9 @@ namespace LAMMPS_NS {
class FixBondReact : public Fix {
public:
enum {MAXLINE=256};
enum {MAXLINE=256}; // max length of line read from files
enum {MAXCONIDS=4}; // max # of IDs used by any constraint
enum {MAXCONPAR=4}; // max # of constraint parameters
FixBondReact(class LAMMPS *, int, char **);
~FixBondReact();
@ -66,9 +68,9 @@ class FixBondReact : public Fix {
int *stabilize_steps_flag;
int *custom_charges_fragid;
int *molecule_keyword;
int nconstraints;
int *nconstraints;
char **constraintstr;
int narrhenius;
double **constraints;
int **var_flag,**var_id; // for keyword values with variable inputs
int status;
int *groupbits;
@ -114,7 +116,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,ndelete,nchiral,nconstr; // # edge, equivalent atoms in mapping file
int nedge,nequivalent,ndelete,nchiral; // # edge, equivalent atoms in mapping file
int attempted_rxn; // there was an attempt!
int *local_rxn_count;
int *ghostly_rxn_count;
@ -155,7 +157,7 @@ class FixBondReact : public Fix {
void DeleteAtoms(char *, int);
void CustomCharges(int, int);
void ChiralCenters(char *, int);
void Constraints(char *, int);
void ReadConstraints(char *, int);
void readID(char *, int, int, int);
void make_a_guess ();
@ -195,6 +197,14 @@ class FixBondReact : public Fix {
};
Set *set;
struct Constraint {
int type;
int id[MAXCONIDS];
int idtype[MAXCONIDS];
double par[MAXCONPAR];
};
Constraint **constraints;
// DEBUG
void print_bb();