Dear Axel and Giacomo,
Thanks for your replies and sorry for the late reply
We have been coding the types of restraints that we needed. In particular:
- we extended the “fix restrain bond” adding a new argument:
fix ID group-ID restrain keyword args
bond args = atom1 atom2 Kstart Kstop r0start r0stop
atom1,atom2 = IDs of 2 atoms in bond
Kstart,Kstop = restraint coefficients at start/end of run (energy units)
r0start,r0stop = equilibrium bond distance (distance units)
- we defined a new fix for lowerbound harmonic restraints. It is a harmonic restraint to keep atoms far apart from each other, and vanishes above the equilibrium bond distance.
lbound args = atom1 atom2 Kstart Kstop r0start r0stop
atom1,atom2 = IDs of 2 atoms in bond
Kstart,Kstop = restraint coefficients at start/end of run (energy units)
r0start,r0stop = equilibrium bond distance (distance units)
These harmonics are useful to implement restraint-based modelling approaches for the structural determination of biological molecules using molecular dynamics. They were first implemented using Colvars (see https://www.biorxiv.org/content/10.1101/642009v1), but we recently discovered that using the “fix restraint” option they can be used much more efficiently.
We have implemented them with a modified “fix restrain” class of the Lammps code:
https://github.com/lammps/lammps/blob/fa7085be077d9271f8400c27c63613cf1a652144/src/fix_restrain.cpp#L222
So it looks like:
/* ----------------------------------------------------------------------
apply harmonic lower-bound bond restraints
---------------------------------------------------------------------- */
void FixRestrain::restrain_lbound(int m)
{
int i1,i2;
double delx,dely,delz,fbond;
double rsq,r,dr,rk;
double **x = atom->x;
double **f = atom->f;
int nlocal = atom->nlocal;
int newton_bond = force->newton_bond;
double delta = update->ntimestep - update->beginstep;
if (delta != 0.0) delta /= update->endstep - update->beginstep;
double k = kstart[m] + delta * (kstop[m] - kstart[m]);
// New
double deq = deqstart[m] + delta * (deqstop[m] - deqstart[m]);
i1 = atom->map(ids[m][0]);
i2 = atom->map(ids[m][1]);
// newton_bond on: only processor owning i2 computes restraint
// newton_bond off: only processors owning either of i1,i2 computes restraint
if (newton_bond) {
if (i2 == -1 || i2 >= nlocal) return;
if (i1 == -1) {
char str[128];
sprintf(str,
"Restrain atoms %d %d missing on proc %d at step " BIGINT_FORMAT,
ids[m][0],ids[m][1],
comm->me,update->ntimestep);
error->one(FLERR,str);
}
} else {
if ((i1 == -1 || i1 >= nlocal) && (i2 == -1 || i2 >= nlocal)) return;
if (i1 == -1 || i2 == -1) {
char str[128];
sprintf(str,
"Restrain atoms %d %d missing on proc %d at step " BIGINT_FORMAT,
ids[m][0],ids[m][1],
comm->me,update->ntimestep);
error->one(FLERR,str);
}
}
delx = x[i1][0] - x[i2][0];
dely = x[i1][1] - x[i2][1];
delz = x[i1][2] - x[i2][2];
domain->minimum_image(delx,dely,delz);
rsq = delxdelx + delydely + delz*delz;
r = sqrt(rsq);
// Old
//dr = r - target[m];
// New
dr = r - deq;
rk = k * dr;
// force & energy
// Old
//if (r > 0.0) fbond = -2.0*rk/r;
//else fbond = 0.0;
//ebond += rk*dr;
//energy += rk*dr;
// New
if (dr < 0) {
if (r > 0.0) fbond = -2.0*rk/r;
else fbond = 0.0;
elbound += rk*dr;
energy += rk*dr;
} else {
fbond = 0.0;
elbound += 0.0;
energy += 0.0;
}
// apply force to each of 2 atoms
if (newton_bond || i1 < nlocal) {
f[i1][0] += delx*fbond;
f[i1][1] += dely*fbond;
f[i1][2] += delz*fbond;
}
if (newton_bond || i2 < nlocal) {
f[i2][0] -= delx*fbond;
f[i2][1] -= dely*fbond;
f[i2][2] -= delz*fbond;
}
}
Among other smalls parts of fix_restrain.cpp and fix_restrain.h (we can send you the added code if needed). Then we can use the restraints in lammps together with harmonic restraints:
fix bond1 all restrain bond 1 50 0.0 1.0 50.0 1.0
fix bond2 all restrain bond 1 25 0.0 1.0 50.0 1.0
fix lbound1 all restrain lbound 1 5 0.0 1000.0 5.0 5.0
This code has been tested and works very well. We are wondering if it is possible to share this code with other Lammps users.
Could we include these changes in Lammps? Or it is better to include them as a USER plugin?
Best regards,
Julen