2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5 * Copyright (c) 2001-2004, The GROMACS development team.
6 * Copyright (c) 2013,2014, by the GROMACS development team, led by
7 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
8 * and including many others, as listed in the AUTHORS file in the
9 * top-level source directory and at http://www.gromacs.org.
11 * GROMACS is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public License
13 * as published by the Free Software Foundation; either version 2.1
14 * of the License, or (at your option) any later version.
16 * GROMACS is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with GROMACS; if not, see
23 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
24 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 * If you want to redistribute modifications to GROMACS, please
27 * consider that scientific software is very special. Version
28 * control is crucial - bugs must be traceable. We will be happy to
29 * consider code for inclusion in the official distribution, but
30 * derived work must not be called official GROMACS. Details are found
31 * in the README & COPYING files - if they are missing, get the
32 * official version at http://www.gromacs.org.
34 * To help us fund GROMACS development, we humbly ask that you cite
35 * the research papers on the package. Check out http://www.gromacs.org.
44 #include "gromacs/legacyheaders/constr.h"
46 #include "gromacs/math/vec.h"
47 #include "gromacs/pbcutil/ishift.h"
48 #include "gromacs/pbcutil/pbc.h"
49 #include "gromacs/utility/fatalerror.h"
50 #include "gromacs/utility/smalloc.h"
71 typedef struct gmx_settledata
78 static void init_proj_matrix(settleparam_t *p,
79 real invmO, real invmH, real dOH, real dHH)
86 /* We normalize the inverse masses with imO for the matrix inversion.
87 * so we can keep using masses of almost zero for frozen particles,
88 * without running out of the float range in m_inv.
93 /* Construct the constraint coupling matrix */
94 mat[0][0] = imOn + imHn;
95 mat[0][1] = imOn*(1 - 0.5*dHH*dHH/(dOH*dOH));
96 mat[0][2] = imHn*0.5*dHH/dOH;
97 mat[1][1] = mat[0][0];
98 mat[1][2] = mat[0][2];
99 mat[2][2] = imHn + imHn;
100 mat[1][0] = mat[0][1];
101 mat[2][0] = mat[0][2];
102 mat[2][1] = mat[1][2];
104 m_inv(mat, p->invmat);
106 msmul(p->invmat, 1/p->imO, p->invmat);
112 static void settleparam_init(settleparam_t *p,
113 real mO, real mH, real invmO, real invmH,
125 p->ra = 2.0*mH*sqrt(dOH*dOH - p->rc*p->rc)/wohh;
126 p->rb = sqrt(dOH*dOH - p->rc*p->rc) - p->ra;
129 /* For projection: connection matrix inversion */
130 init_proj_matrix(p, invmO, invmH, dOH, dHH);
134 fprintf(debug, "wh =%g, rc = %g, ra = %g\n",
135 p->wh, p->rc, p->ra);
136 fprintf(debug, "rb = %g, irc2 = %g, dHH = %g, dOH = %g\n",
137 p->rb, p->irc2, p->dHH, p->dOH);
141 gmx_settledata_t settle_init(real mO, real mH, real invmO, real invmH,
144 gmx_settledata_t settled;
148 settleparam_init(&settled->massw, mO, mH, invmO, invmH, dOH, dHH);
150 settleparam_init(&settled->mass1, 1.0, 1.0, 1.0, 1.0, dOH, dHH);
156 static void check_cons(FILE *fp, char *title, real x[], int OW1, int HW2, int HW3)
158 rvec dOH1, dOH2, dHH;
161 for (m = 0; (m < DIM); m++)
163 dOH1[m] = x[OW1+m]-x[HW2+m];
164 dOH2[m] = x[OW1+m]-x[HW3+m];
165 dHH[m] = x[HW2+m]-x[HW3+m];
167 fprintf(fp, "%10s, OW1=%3d, HW2=%3d, HW3=%3d, dOH1: %8.3f, dOH2: %8.3f, dHH: %8.3f\n",
168 title, OW1/DIM, HW2/DIM, HW3/DIM, norm(dOH1), norm(dOH2), norm(dHH));
173 void settle_proj(gmx_settledata_t settled, int econq,
174 int nsettle, t_iatom iatoms[],
177 rvec *der, rvec *derp,
178 int calcvir_atom_end, tensor vir_r_m_dder,
181 /* Settle for projection out constraint components
182 * of derivatives of the coordinates.
183 * Berk Hess 2008-1-10
187 real imO, imH, dOH, dHH, invdOH, invdHH;
189 int i, m, m2, ow1, hw2, hw3;
190 rvec roh2, roh3, rhh, dc, fc, fcv;
191 rvec derm[3], derpm[3];
192 real invvscale, vscale_nhc, veta;
195 calcvir_atom_end *= DIM;
197 if (econq == econqForce)
207 copy_mat(p->invmat, invmat);
213 veta = vetavar->veta;
214 vscale_nhc = vetavar->vscale_nhc[0]; /* assume the first temperature control group. */
220 for (i = 0; i < nsettle; i++)
227 for (m = 0; m < DIM; m++)
229 /* in the velocity case, these are the velocities, so we
230 need to modify with the pressure control velocities! */
232 derm[0][m] = vscale_nhc*der[ow1][m] + veta*x[ow1][m];
233 derm[1][m] = vscale_nhc*der[hw2][m] + veta*x[hw2][m];
234 derm[2][m] = vscale_nhc*der[hw3][m] + veta*x[hw3][m];
241 rvec_sub(x[ow1], x[hw2], roh2);
242 rvec_sub(x[ow1], x[hw3], roh3);
243 rvec_sub(x[hw2], x[hw3], rhh);
247 pbc_dx_aiuc(pbc, x[ow1], x[hw2], roh2);
248 pbc_dx_aiuc(pbc, x[ow1], x[hw3], roh3);
249 pbc_dx_aiuc(pbc, x[hw2], x[hw3], rhh);
251 svmul(invdOH, roh2, roh2);
252 svmul(invdOH, roh3, roh3);
253 svmul(invdHH, rhh, rhh);
256 /* Determine the projections of der(modified) on the bonds */
258 for (m = 0; m < DIM; m++)
260 dc[0] += (derm[0][m] - derm[1][m])*roh2[m];
261 dc[1] += (derm[0][m] - derm[2][m])*roh3[m];
262 dc[2] += (derm[1][m] - derm[2][m])*rhh [m];
266 /* Determine the correction for the three bonds */
267 mvmul(invmat, dc, fc);
270 /* divide velocity by vscale_nhc for determining constrained velocities, since they
271 have not yet been multiplied */
272 svmul(1.0/vscale_nhc, fc, fcv);
275 /* Subtract the corrections from derp */
276 for (m = 0; m < DIM; m++)
278 derp[ow1][m] -= imO*( fcv[0]*roh2[m] + fcv[1]*roh3[m]);
279 derp[hw2][m] -= imH*(-fcv[0]*roh2[m] + fcv[2]*rhh [m]);
280 derp[hw3][m] -= imH*(-fcv[1]*roh3[m] - fcv[2]*rhh [m]);
285 if (ow1 < calcvir_atom_end)
287 /* Determining r \dot m der is easy,
288 * since fc contains the mass weighted corrections for der.
291 for (m = 0; m < DIM; m++)
293 for (m2 = 0; m2 < DIM; m2++)
295 vir_r_m_dder[m][m2] +=
296 dOH*roh2[m]*roh2[m2]*fcv[0] +
297 dOH*roh3[m]*roh3[m2]*fcv[1] +
298 dHH*rhh [m]*rhh [m2]*fcv[2];
304 if (calcvir_atom_end > 0)
306 /* Correct r_m_dder, which will be used to calcualate the virial;
307 * we need to use the unscaled multipliers in the virial.
309 msmul(vir_r_m_dder, 1.0/vetavar->vscale, vir_r_m_dder);
314 void csettle(gmx_settledata_t settled,
315 int nsettle, t_iatom iatoms[],
317 real b4[], real after[],
318 real invdt, real *v, int CalcVirAtomEnd,
323 /* ***************************************************************** */
325 /* Subroutine : setlep - reset positions of TIP3P waters ** */
326 /* Author : Shuichi Miyamoto ** */
327 /* Date of last update : Oct. 1, 1992 ** */
329 /* Reference for the SETTLE algorithm ** */
330 /* S. Miyamoto et al., J. Comp. Chem., 13, 952 (1992). ** */
332 /* ***************************************************************** */
334 /* Initialized data */
336 real wh, ra, rb, rc, irc2;
337 real mOs, mHs, invdts;
339 /* Local variables */
340 real gama, beta, alpa, xcom, ycom, zcom, al2be2, tmp, tmp2;
341 real axlng, aylng, azlng, trns11, trns21, trns31, trns12, trns22,
342 trns32, trns13, trns23, trns33, cosphi, costhe, sinphi, sinthe,
343 cospsi, xaksxd, yaksxd, xakszd, yakszd, zakszd, zaksxd, xaksyd,
344 xb0, yb0, zb0, xc0, yc0, zc0, xa1;
345 real ya1, za1, xb1, yb1;
346 real zb1, xc1, yc1, zc1, yaksyd, zaksyd, sinpsi, xa3, ya3, za3,
347 xb3, yb3, zb3, xc3, yc3, zc3, xb0d, yb0d, xc0d, yc0d,
348 za1d, xb1d, yb1d, zb1d, xc1d, yc1d, zc1d, ya2d, xb2d, yb2d, yc2d,
349 xa3d, ya3d, za3d, xb3d, yb3d, zb3d, xc3d, yc3d, zc3d;
351 real dax, day, daz, dbx, dby, dbz, dcx, dcy, dcz;
352 real mdax, mday, mdaz, mdbx, mdby, mdbz, mdcx, mdcy, mdcz;
356 int i, ow1, hw2, hw3;
358 rvec dx, sh_hw2 = {0, 0, 0}, sh_hw3 = {0, 0, 0};
373 mOs = p->mO / vetavar->rvscale;
374 mHs = p->mH / vetavar->rvscale;
375 invdts = invdt / vetavar->rscale;
380 for (i = 0; i < nsettle; ++i)
383 /* --- Step1 A1' --- */
384 ow1 = iatoms[i*4+1] * 3;
385 hw2 = iatoms[i*4+2] * 3;
386 hw3 = iatoms[i*4+3] * 3;
389 xb0 = b4[hw2 + XX] - b4[ow1 + XX];
390 yb0 = b4[hw2 + YY] - b4[ow1 + YY];
391 zb0 = b4[hw2 + ZZ] - b4[ow1 + ZZ];
392 xc0 = b4[hw3 + XX] - b4[ow1 + XX];
393 yc0 = b4[hw3 + YY] - b4[ow1 + YY];
394 zc0 = b4[hw3 + ZZ] - b4[ow1 + ZZ];
397 rvec_sub(after+hw2, after+ow1, doh2);
398 rvec_sub(after+hw3, after+ow1, doh3);
403 pbc_dx_aiuc(pbc, b4+hw2, b4+ow1, dx);
407 pbc_dx_aiuc(pbc, b4+hw3, b4+ow1, dx);
412 /* Tedious way of doing pbc */
413 is = pbc_dx_aiuc(pbc, after+hw2, after+ow1, doh2);
420 sh_hw2[XX] = after[hw2 + XX] - (after[ow1 + XX] + doh2[XX]);
421 sh_hw2[YY] = after[hw2 + YY] - (after[ow1 + YY] + doh2[YY]);
422 sh_hw2[ZZ] = after[hw2 + ZZ] - (after[ow1 + ZZ] + doh2[ZZ]);
423 rvec_dec(after+hw2, sh_hw2);
425 is = pbc_dx_aiuc(pbc, after+hw3, after+ow1, doh3);
432 sh_hw3[XX] = after[hw3 + XX] - (after[ow1 + XX] + doh3[XX]);
433 sh_hw3[YY] = after[hw3 + YY] - (after[ow1 + YY] + doh3[YY]);
434 sh_hw3[ZZ] = after[hw3 + ZZ] - (after[ow1 + ZZ] + doh3[ZZ]);
435 rvec_dec(after+hw3, sh_hw3);
439 /* Not calculating the center of mass using the oxygen position
440 * and the O-H distances, as done below, will make SETTLE
441 * the largest source of energy drift for simulations of water,
442 * as then the oxygen coordinate is multiplied by 0.89 at every step,
443 * which can then transfer a systematic rounding to the oxygen velocity.
445 xa1 = -(doh2[XX] + doh3[XX]) * wh;
446 ya1 = -(doh2[YY] + doh3[YY]) * wh;
447 za1 = -(doh2[ZZ] + doh3[ZZ]) * wh;
449 xcom = after[ow1 + XX] - xa1;
450 ycom = after[ow1 + YY] - ya1;
451 zcom = after[ow1 + ZZ] - za1;
453 xb1 = after[hw2 + XX] - xcom;
454 yb1 = after[hw2 + YY] - ycom;
455 zb1 = after[hw2 + ZZ] - zcom;
456 xc1 = after[hw3 + XX] - xcom;
457 yc1 = after[hw3 + YY] - ycom;
458 zc1 = after[hw3 + ZZ] - zcom;
461 xakszd = yb0 * zc0 - zb0 * yc0;
462 yakszd = zb0 * xc0 - xb0 * zc0;
463 zakszd = xb0 * yc0 - yb0 * xc0;
464 xaksxd = ya1 * zakszd - za1 * yakszd;
465 yaksxd = za1 * xakszd - xa1 * zakszd;
466 zaksxd = xa1 * yakszd - ya1 * xakszd;
467 xaksyd = yakszd * zaksxd - zakszd * yaksxd;
468 yaksyd = zakszd * xaksxd - xakszd * zaksxd;
469 zaksyd = xakszd * yaksxd - yakszd * xaksxd;
472 axlng = gmx_invsqrt(xaksxd * xaksxd + yaksxd * yaksxd + zaksxd * zaksxd);
473 aylng = gmx_invsqrt(xaksyd * xaksyd + yaksyd * yaksyd + zaksyd * zaksyd);
474 azlng = gmx_invsqrt(xakszd * xakszd + yakszd * yakszd + zakszd * zakszd);
476 trns11 = xaksxd * axlng;
477 trns21 = yaksxd * axlng;
478 trns31 = zaksxd * axlng;
479 trns12 = xaksyd * aylng;
480 trns22 = yaksyd * aylng;
481 trns32 = zaksyd * aylng;
482 trns13 = xakszd * azlng;
483 trns23 = yakszd * azlng;
484 trns33 = zakszd * azlng;
487 xb0d = trns11 * xb0 + trns21 * yb0 + trns31 * zb0;
488 yb0d = trns12 * xb0 + trns22 * yb0 + trns32 * zb0;
489 xc0d = trns11 * xc0 + trns21 * yc0 + trns31 * zc0;
490 yc0d = trns12 * xc0 + trns22 * yc0 + trns32 * zc0;
492 xa1d = trns11 * xa1 + trns21 * ya1 + trns31 * za1;
493 ya1d = trns12 * xa1 + trns22 * ya1 + trns32 * za1;
495 za1d = trns13 * xa1 + trns23 * ya1 + trns33 * za1;
496 xb1d = trns11 * xb1 + trns21 * yb1 + trns31 * zb1;
497 yb1d = trns12 * xb1 + trns22 * yb1 + trns32 * zb1;
498 zb1d = trns13 * xb1 + trns23 * yb1 + trns33 * zb1;
499 xc1d = trns11 * xc1 + trns21 * yc1 + trns31 * zc1;
500 yc1d = trns12 * xc1 + trns22 * yc1 + trns32 * zc1;
501 zc1d = trns13 * xc1 + trns23 * yc1 + trns33 * zc1;
504 sinphi = za1d * gmx_invsqrt(ra*ra);
505 tmp = 1.0 - sinphi * sinphi;
512 tmp2 = gmx_invsqrt(tmp);
514 sinpsi = (zb1d - zc1d) * irc2 * tmp2;
515 tmp2 = 1.0 - sinpsi * sinpsi;
522 cospsi = tmp2*gmx_invsqrt(tmp2);
532 t2 = rc * sinpsi * sinphi;
537 /* --- Step3 al,be,ga --- */
538 alpa = xb2d * (xb0d - xc0d) + yb0d * yb2d + yc0d * yc2d;
539 beta = xb2d * (yc0d - yb0d) + xb0d * yb2d + xc0d * yc2d;
540 gama = xb0d * yb1d - xb1d * yb0d + xc0d * yc1d - xc1d * yc0d;
541 al2be2 = alpa * alpa + beta * beta;
542 tmp2 = (al2be2 - gama * gama);
543 sinthe = (alpa * gama - beta * tmp2*gmx_invsqrt(tmp2)) * gmx_invsqrt(al2be2*al2be2);
546 /* --- Step4 A3' --- */
547 tmp2 = 1.0 - sinthe * sinthe;
548 costhe = tmp2*gmx_invsqrt(tmp2);
549 xa3d = -ya2d * sinthe;
550 ya3d = ya2d * costhe;
552 xb3d = xb2d * costhe - yb2d * sinthe;
553 yb3d = xb2d * sinthe + yb2d * costhe;
555 xc3d = -xb2d * costhe - yc2d * sinthe;
556 yc3d = -xb2d * sinthe + yc2d * costhe;
560 /* --- Step5 A3 --- */
561 xa3 = trns11 * xa3d + trns12 * ya3d + trns13 * za3d;
562 ya3 = trns21 * xa3d + trns22 * ya3d + trns23 * za3d;
563 za3 = trns31 * xa3d + trns32 * ya3d + trns33 * za3d;
564 xb3 = trns11 * xb3d + trns12 * yb3d + trns13 * zb3d;
565 yb3 = trns21 * xb3d + trns22 * yb3d + trns23 * zb3d;
566 zb3 = trns31 * xb3d + trns32 * yb3d + trns33 * zb3d;
567 xc3 = trns11 * xc3d + trns12 * yc3d + trns13 * zc3d;
568 yc3 = trns21 * xc3d + trns22 * yc3d + trns23 * zc3d;
569 zc3 = trns31 * xc3d + trns32 * yc3d + trns33 * zc3d;
571 after[ow1] = xcom + xa3;
572 after[ow1 + 1] = ycom + ya3;
573 after[ow1 + 2] = zcom + za3;
574 after[hw2] = xcom + xb3;
575 after[hw2 + 1] = ycom + yb3;
576 after[hw2 + 2] = zcom + zb3;
577 after[hw3] = xcom + xc3;
578 after[hw3 + 1] = ycom + yc3;
579 after[hw3 + 2] = zcom + zc3;
584 rvec_inc(after+hw2, sh_hw2);
585 rvec_inc(after+hw3, sh_hw3);
597 /* 9 flops, counted with the virial */
601 v[ow1] += dax*invdts;
602 v[ow1 + 1] += day*invdts;
603 v[ow1 + 2] += daz*invdts;
604 v[hw2] += dbx*invdts;
605 v[hw2 + 1] += dby*invdts;
606 v[hw2 + 2] += dbz*invdts;
607 v[hw3] += dcx*invdts;
608 v[hw3 + 1] += dcy*invdts;
609 v[hw3 + 2] += dcz*invdts;
613 if (ow1 < CalcVirAtomEnd)
624 vir_r_m_dr[XX][XX] -= b4[ow1 ]*mdax + (b4[ow1 ]+xb0)*mdbx + (b4[ow1 ]+xc0)*mdcx;
625 vir_r_m_dr[XX][YY] -= b4[ow1 ]*mday + (b4[ow1 ]+xb0)*mdby + (b4[ow1 ]+xc0)*mdcy;
626 vir_r_m_dr[XX][ZZ] -= b4[ow1 ]*mdaz + (b4[ow1 ]+xb0)*mdbz + (b4[ow1 ]+xc0)*mdcz;
627 vir_r_m_dr[YY][XX] -= b4[ow1+1]*mdax + (b4[ow1+1]+yb0)*mdbx + (b4[ow1+1]+yc0)*mdcx;
628 vir_r_m_dr[YY][YY] -= b4[ow1+1]*mday + (b4[ow1+1]+yb0)*mdby + (b4[ow1+1]+yc0)*mdcy;
629 vir_r_m_dr[YY][ZZ] -= b4[ow1+1]*mdaz + (b4[ow1+1]+yb0)*mdbz + (b4[ow1+1]+yc0)*mdcz;
630 vir_r_m_dr[ZZ][XX] -= b4[ow1+2]*mdax + (b4[ow1+2]+zb0)*mdbx + (b4[ow1+2]+zc0)*mdcx;
631 vir_r_m_dr[ZZ][YY] -= b4[ow1+2]*mday + (b4[ow1+2]+zb0)*mdby + (b4[ow1+2]+zc0)*mdcy;
632 vir_r_m_dr[ZZ][ZZ] -= b4[ow1+2]*mdaz + (b4[ow1+2]+zb0)*mdbz + (b4[ow1+2]+zc0)*mdcz;
643 check_cons(debug, "settle", after, ow1, hw2, hw3);