{
fprintf(fplog, sepdvdlformat, "Constraint dV/dl", 0.0, dvdl_constr);
}
- enerd->term[F_DVDL_CONSTR] += dvdl_constr;
+ if (bVV)
+ {
+ /* this factor or 2 correction is necessary
+ because half of the constraint force is removed
+ in the vv step, so we have to double it. See
+ the Redmine issue #1255. It is not yet clear
+ if the factor of 2 is exact, or just a very
+ good approximation, and this will be
+ investigated. The next step is to see if this
+ can be done adding a dhdl contribution from the
+ rattle step, but this is somewhat more
+ complicated with the current code. Will be
+ investigated, hopefully for 4.6.3. However,
+ this current solution is much better than
+ having it completely wrong.
+ */
+ enerd->term[F_DVDL_CONSTR] += 2*dvdl_constr;
+ }
+ else
+ {
+ enerd->term[F_DVDL_CONSTR] += dvdl_constr;
+ }
}
else if (graph)
{
bFirstIterate = FALSE;
}
- /* only add constraint dvdl after constraints */
- enerd->term[F_DVDL_CONSTR] += dvdl_constr;
if (!bVV || bRerunMD)
{
/* sum up the foreign energy and dhdl terms for md and sd. currently done every step so that dhdl is correct in the .edr */
* which is a very good approximation (except for exotic settings).
* (investigate how to overcome this post 4.6 - MRS)
*/
- enerd->term[F_DVDL_BONDED] += enerd->term[F_DVDL_CONSTR];
+ if (fepvals->separate_dvdl[efptBONDED])
+ {
+ enerd->term[F_DVDL_BONDED] += enerd->term[F_DVDL_CONSTR];
+ }
+ else
+ {
+ enerd->term[F_DVDL] += enerd->term[F_DVDL_CONSTR];
+ }
enerd->term[F_DVDL_CONSTR] = 0;
for (i = 0; i < fepvals->n_lambda; i++)
{
if (ir->efep != efepNO)
{
+ real bondA,bondB;
dt_2 = 1/sqr(ir->delta_t);
dvdl = 0;
for (i = 0; i < ncons; i++)
{
type = idef->il[F_CONSTR].iatoms[3*i];
- dvdl += lagr[i]*dt_2*
- (idef->iparams[type].constr.dB-idef->iparams[type].constr.dA);
+
+ /* dh/dl contribution from constraint force is dh/dr (constraint force) dot dr/dl */
+ /* constraint force is -\sum_i lagr_i* d(constraint)/dr, with constrant = r^2-d^2 */
+ /* constraint force is -\sum_i lagr_i* 2 r */
+ /* so dh/dl = -\sum_i lagr_i* 2 r * dr/dl */
+ /* However, by comparison with lincs and with
+ comparison with a full thermodynamics cycle (see
+ redmine issue #1255), this is off by a factor of
+ two -- the 2r should apparently just be r. Further
+ investigation should be done at some point to
+ understand why and see if there is something deeper
+ we are missing */
+
+ bondA = idef->iparams[type].constr.dA;
+ bondB = idef->iparams[type].constr.dB;
+ dvdl += lagr[i] * dt_2 * ((1.0-lambda)*bondA + lambda*bondB) * (bondB-bondA);
}
*dvdlambda += dvdl;
}