Improved version for builds from modified trees.
[gromacs/qmmm-gamess-us.git] / src / mdlib / clincs.c
blob966dbac0adbaee5316b4a5b0e9da554aadd3d03c
1 /* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
3 *
4 * This source code is part of
5 *
6 * G R O M A C S
7 *
8 * GROningen MAchine for Chemical Simulations
9 *
10 * VERSION 3.2.0
11 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
12 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
13 * Copyright (c) 2001-2004, The GROMACS development team,
14 * check out http://www.gromacs.org for more information.
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
21 * If you want to redistribute modifications, please consider that
22 * scientific software is very special. Version control is crucial -
23 * bugs must be traceable. We will be happy to consider code for
24 * inclusion in the official distribution, but derived work must not
25 * be called official GROMACS. Details are found in the README & COPYING
26 * files - if they are missing, get the official version at www.gromacs.org.
28 * To help us fund GROMACS development, we humbly ask that you cite
29 * the papers on the package - you can find them in the top README file.
31 * For more info, check our website at http://www.gromacs.org
33 * And Hey:
34 * GROwing Monsters And Cloning Shrimps
36 /* This file is completely threadsafe - keep it that way! */
37 #ifdef HAVE_CONFIG_H
38 #include <config.h>
39 #endif
41 #include <math.h>
42 #include "main.h"
43 #include "constr.h"
44 #include "copyrite.h"
45 #include "physics.h"
46 #include "vec.h"
47 #include "pbc.h"
48 #include "smalloc.h"
49 #include "mdrun.h"
50 #include "nrnb.h"
51 #include "domdec.h"
52 #include "partdec.h"
53 #include "mtop_util.h"
54 #include "gmxfio.h"
56 typedef struct gmx_lincsdata {
57 int ncg; /* the global number of constraints */
58 int ncg_flex; /* the global number of flexible constraints */
59 int ncg_triangle;/* the global number of constraints in triangles */
60 int nIter; /* the number of iterations */
61 int nOrder; /* the order of the matrix expansion */
62 int nc; /* the number of constraints */
63 int nc_alloc; /* the number we allocated memory for */
64 int ncc; /* the number of constraint connections */
65 int ncc_alloc; /* the number we allocated memory for */
66 real matlam; /* the FE lambda value used for filling blc and blmf */
67 real *bllen0; /* the reference distance in topology A */
68 real *ddist; /* the reference distance in top B - the r.d. in top A */
69 int *bla; /* the atom pairs involved in the constraints */
70 real *blc; /* 1/sqrt(invmass1 + invmass2) */
71 real *blc1; /* as blc, but with all masses 1 */
72 int *blnr; /* index into blbnb and blmf */
73 int *blbnb; /* list of constraint connections */
74 int ntriangle; /* the local number of constraints in triangles */
75 int *triangle; /* the list of triangle constraints */
76 int *tri_bits; /* the bits tell if the matrix element should be used */
77 int ncc_triangle;/* the number of constraint connections in triangles */
78 real *blmf; /* matrix of mass factors for constraint connections */
79 real *blmf1; /* as blmf, but with all masses 1 */
80 real *bllen; /* the reference bond length */
81 /* arrays for temporary storage in the LINCS algorithm */
82 rvec *tmpv;
83 real *tmpncc;
84 real *tmp1;
85 real *tmp2;
86 real *tmp3;
87 real *lambda; /* the Lagrange multipliers */
88 /* storage for the constraint RMS relative deviation output */
89 real rmsd_data[3];
90 } t_gmx_lincsdata;
92 real *lincs_rmsd_data(struct gmx_lincsdata *lincsd)
94 return lincsd->rmsd_data;
97 real lincs_rmsd(struct gmx_lincsdata *lincsd,bool bSD2)
99 if (lincsd->rmsd_data[0] > 0)
101 return sqrt(lincsd->rmsd_data[bSD2 ? 2 : 1]/lincsd->rmsd_data[0]);
103 else
105 return 0;
109 static void lincs_matrix_expand(const struct gmx_lincsdata *lincsd,
110 const real *blcc,
111 real *rhs1,real *rhs2,real *sol)
113 int nrec,rec,ncons,b,j,n,nr0,nr1;
114 real mvb,*swap;
115 int ntriangle,tb,bits;
116 const int *blnr=lincsd->blnr,*blbnb=lincsd->blbnb;
117 const int *triangle=lincsd->triangle,*tri_bits=lincsd->tri_bits;
119 ncons = lincsd->nc;
120 ntriangle = lincsd->ntriangle;
121 nrec = lincsd->nOrder;
123 for(rec=0; rec<nrec; rec++)
125 for(b=0; b<ncons; b++)
127 mvb = 0;
128 for(n=blnr[b]; n<blnr[b+1]; n++)
130 j = blbnb[n];
131 mvb = mvb + blcc[n]*rhs1[j];
133 rhs2[b] = mvb;
134 sol[b] = sol[b] + mvb;
136 swap = rhs1;
137 rhs1 = rhs2;
138 rhs2 = swap;
139 } /* nrec*(ncons+2*nrtot) flops */
141 if (ntriangle > 0)
143 /* Perform an extra nrec recursions for only the constraints
144 * involved in rigid triangles.
145 * In this way their accuracy should come close to those of the other
146 * constraints, since traingles of constraints can produce eigenvalues
147 * around 0.7, while the effective eigenvalue for bond constraints
148 * is around 0.4 (and 0.7*0.7=0.5).
150 /* We need to copy the temporary array, since only the elements
151 * for constraints involved in triangles are updated
152 * and then the pointers are swapped.
154 for(b=0; b<ncons; b++)
156 rhs2[b] = rhs1[b];
158 for(rec=0; rec<nrec; rec++)
160 for(tb=0; tb<ntriangle; tb++)
162 b = triangle[tb];
163 bits = tri_bits[tb];
164 mvb = 0;
165 nr0 = blnr[b];
166 nr1 = blnr[b+1];
167 for(n=nr0; n<nr1; n++)
169 if (bits & (1<<(n-nr0)))
171 j = blbnb[n];
172 mvb = mvb + blcc[n]*rhs1[j];
175 rhs2[b] = mvb;
176 sol[b] = sol[b] + mvb;
178 swap = rhs1;
179 rhs1 = rhs2;
180 rhs2 = swap;
181 } /* flops count is missing here */
185 static void do_lincsp(rvec *x,rvec *f,rvec *fp,t_pbc *pbc,
186 struct gmx_lincsdata *lincsd,real *invmass,
187 int econq,real *dvdlambda,
188 bool bCalcVir,tensor rmdf)
190 int b,i,j,k,n;
191 real tmp0,tmp1,tmp2,im1,im2,mvb,rlen,len,wfac,lam;
192 rvec dx;
193 int ncons,*bla,*blnr,*blbnb;
194 rvec *r;
195 real *blc,*blmf,*blcc,*rhs1,*rhs2,*sol;
197 ncons = lincsd->nc;
198 bla = lincsd->bla;
199 r = lincsd->tmpv;
200 blnr = lincsd->blnr;
201 blbnb = lincsd->blbnb;
202 if (econq != econqForce)
204 /* Use mass-weighted parameters */
205 blc = lincsd->blc;
206 blmf = lincsd->blmf;
208 else
210 /* Use non mass-weighted parameters */
211 blc = lincsd->blc1;
212 blmf = lincsd->blmf1;
214 blcc = lincsd->tmpncc;
215 rhs1 = lincsd->tmp1;
216 rhs2 = lincsd->tmp2;
217 sol = lincsd->tmp3;
219 if (econq != econqForce)
221 dvdlambda = NULL;
224 /* Compute normalized i-j vectors */
225 if (pbc)
227 for(b=0; b<ncons; b++)
229 pbc_dx_aiuc(pbc,x[bla[2*b]],x[bla[2*b+1]],dx);
230 unitv(dx,r[b]);
233 else
235 for(b=0; b<ncons; b++)
237 rvec_sub(x[bla[2*b]],x[bla[2*b+1]],dx);
238 unitv(dx,r[b]);
239 } /* 16 ncons flops */
242 for(b=0; b<ncons; b++)
244 tmp0 = r[b][0];
245 tmp1 = r[b][1];
246 tmp2 = r[b][2];
247 i = bla[2*b];
248 j = bla[2*b+1];
249 for(n=blnr[b]; n<blnr[b+1]; n++)
251 k = blbnb[n];
252 blcc[n] = blmf[n]*(tmp0*r[k][0] + tmp1*r[k][1] + tmp2*r[k][2]);
253 } /* 6 nr flops */
254 mvb = blc[b]*(tmp0*(f[i][0] - f[j][0]) +
255 tmp1*(f[i][1] - f[j][1]) +
256 tmp2*(f[i][2] - f[j][2]));
257 rhs1[b] = mvb;
258 sol[b] = mvb;
259 /* 7 flops */
261 /* Together: 23*ncons + 6*nrtot flops */
263 lincs_matrix_expand(lincsd,blcc,rhs1,rhs2,sol);
264 /* nrec*(ncons+2*nrtot) flops */
266 if (econq != econqForce)
268 for(b=0; b<ncons; b++)
270 /* With econqDeriv_FlexCon only use the flexible constraints */
271 if (econq != econqDeriv_FlexCon ||
272 (lincsd->bllen0[b] == 0 && lincsd->ddist[b] == 0))
274 i = bla[2*b];
275 j = bla[2*b+1];
276 mvb = blc[b]*sol[b];
277 im1 = invmass[i];
278 im2 = invmass[j];
279 tmp0 = r[b][0]*mvb;
280 tmp1 = r[b][1]*mvb;
281 tmp2 = r[b][2]*mvb;
282 fp[i][0] -= tmp0*im1;
283 fp[i][1] -= tmp1*im1;
284 fp[i][2] -= tmp2*im1;
285 fp[j][0] += tmp0*im2;
286 fp[j][1] += tmp1*im2;
287 fp[j][2] += tmp2*im2;
288 if (dvdlambda)
290 /* This is only correct with forces and invmass=1 */
291 *dvdlambda -= mvb*lincsd->ddist[b];
294 } /* 16 ncons flops */
296 else
298 for(b=0; b<ncons; b++)
300 i = bla[2*b];
301 j = bla[2*b+1];
302 mvb = blc[b]*sol[b];
303 tmp0 = r[b][0]*mvb;
304 tmp1 = r[b][1]*mvb;
305 tmp2 = r[b][2]*mvb;
306 fp[i][0] -= tmp0;
307 fp[i][1] -= tmp1;
308 fp[i][2] -= tmp2;
309 fp[j][0] += tmp0;
310 fp[j][1] += tmp1;
311 fp[j][2] += tmp2;
312 if (dvdlambda)
314 *dvdlambda -= mvb*lincsd->ddist[b];
317 /* 10 ncons flops */
320 if (bCalcVir)
322 /* Constraint virial,
323 * determines sum r_bond x delta f,
324 * where delta f is the constraint correction
325 * of the quantity that is being constrained.
327 for(b=0; b<ncons; b++)
329 mvb = lincsd->bllen[b]*blc[b]*sol[b];
330 for(i=0; i<DIM; i++)
332 tmp1 = mvb*r[b][i];
333 for(j=0; j<DIM; j++)
335 rmdf[i][j] += tmp1*r[b][j];
338 } /* 23 ncons flops */
342 static void do_lincs(rvec *x,rvec *xp,matrix box,t_pbc *pbc,
343 struct gmx_lincsdata *lincsd,real *invmass,
344 t_commrec *cr,
345 real wangle,int *warn,
346 real invdt,rvec *v,
347 bool bCalcVir,tensor rmdr)
349 int b,i,j,k,n,iter;
350 real tmp0,tmp1,tmp2,im1,im2,mvb,rlen,len,len2,dlen2,wfac,lam;
351 rvec dx;
352 int ncons,*bla,*blnr,*blbnb;
353 rvec *r;
354 real *blc,*blmf,*bllen,*blcc,*rhs1,*rhs2,*sol,*lambda;
355 int *nlocat;
357 ncons = lincsd->nc;
358 bla = lincsd->bla;
359 r = lincsd->tmpv;
360 blnr = lincsd->blnr;
361 blbnb = lincsd->blbnb;
362 blc = lincsd->blc;
363 blmf = lincsd->blmf;
364 bllen = lincsd->bllen;
365 blcc = lincsd->tmpncc;
366 rhs1 = lincsd->tmp1;
367 rhs2 = lincsd->tmp2;
368 sol = lincsd->tmp3;
369 lambda = lincsd->lambda;
371 if (DOMAINDECOMP(cr) && cr->dd->constraints)
373 nlocat = dd_constraints_nlocalatoms(cr->dd);
375 else if (PARTDECOMP(cr))
377 nlocat = pd_constraints_nlocalatoms(cr->pd);
379 else
381 nlocat = NULL;
384 *warn = 0;
386 if (pbc)
388 /* Compute normalized i-j vectors */
389 for(b=0; b<ncons; b++)
391 pbc_dx_aiuc(pbc,x[bla[2*b]],x[bla[2*b+1]],dx);
392 unitv(dx,r[b]);
394 for(b=0; b<ncons; b++)
396 for(n=blnr[b]; n<blnr[b+1]; n++)
398 blcc[n] = blmf[n]*iprod(r[b],r[blbnb[n]]);
400 pbc_dx_aiuc(pbc,xp[bla[2*b]],xp[bla[2*b+1]],dx);
401 mvb = blc[b]*(iprod(r[b],dx) - bllen[b]);
402 rhs1[b] = mvb;
403 sol[b] = mvb;
406 else
408 /* Compute normalized i-j vectors */
409 for(b=0; b<ncons; b++)
411 i = bla[2*b];
412 j = bla[2*b+1];
413 tmp0 = x[i][0] - x[j][0];
414 tmp1 = x[i][1] - x[j][1];
415 tmp2 = x[i][2] - x[j][2];
416 rlen = gmx_invsqrt(tmp0*tmp0+tmp1*tmp1+tmp2*tmp2);
417 r[b][0] = rlen*tmp0;
418 r[b][1] = rlen*tmp1;
419 r[b][2] = rlen*tmp2;
420 } /* 16 ncons flops */
422 for(b=0; b<ncons; b++)
424 tmp0 = r[b][0];
425 tmp1 = r[b][1];
426 tmp2 = r[b][2];
427 len = bllen[b];
428 i = bla[2*b];
429 j = bla[2*b+1];
430 for(n=blnr[b]; n<blnr[b+1]; n++)
432 k = blbnb[n];
433 blcc[n] = blmf[n]*(tmp0*r[k][0] + tmp1*r[k][1] + tmp2*r[k][2]);
434 } /* 6 nr flops */
435 mvb = blc[b]*(tmp0*(xp[i][0] - xp[j][0]) +
436 tmp1*(xp[i][1] - xp[j][1]) +
437 tmp2*(xp[i][2] - xp[j][2]) - len);
438 rhs1[b] = mvb;
439 sol[b] = mvb;
440 /* 10 flops */
442 /* Together: 26*ncons + 6*nrtot flops */
445 lincs_matrix_expand(lincsd,blcc,rhs1,rhs2,sol);
446 /* nrec*(ncons+2*nrtot) flops */
448 for(b=0; b<ncons; b++)
450 i = bla[2*b];
451 j = bla[2*b+1];
452 mvb = blc[b]*sol[b];
453 lambda[b] = -mvb;
454 im1 = invmass[i];
455 im2 = invmass[j];
456 tmp0 = r[b][0]*mvb;
457 tmp1 = r[b][1]*mvb;
458 tmp2 = r[b][2]*mvb;
459 xp[i][0] -= tmp0*im1;
460 xp[i][1] -= tmp1*im1;
461 xp[i][2] -= tmp2*im1;
462 xp[j][0] += tmp0*im2;
463 xp[j][1] += tmp1*im2;
464 xp[j][2] += tmp2*im2;
465 } /* 16 ncons flops */
469 ******** Correction for centripetal effects ********
472 wfac = cos(DEG2RAD*wangle);
473 wfac = wfac*wfac;
475 for(iter=0; iter<lincsd->nIter; iter++)
477 if (DOMAINDECOMP(cr) && cr->dd->constraints)
479 /* Communicate the corrected non-local coordinates */
480 dd_move_x_constraints(cr->dd,box,xp,NULL);
482 else if (PARTDECOMP(cr))
484 pd_move_x_constraints(cr,xp,NULL);
487 for(b=0; b<ncons; b++)
489 len = bllen[b];
490 if (pbc)
492 pbc_dx_aiuc(pbc,xp[bla[2*b]],xp[bla[2*b+1]],dx);
494 else
496 rvec_sub(xp[bla[2*b]],xp[bla[2*b+1]],dx);
498 len2 = len*len;
499 dlen2 = 2*len2 - norm2(dx);
500 if (dlen2 < wfac*len2 && (nlocat==NULL || nlocat[b]))
502 *warn = b;
504 if (dlen2 > 0)
506 mvb = blc[b]*(len - dlen2*gmx_invsqrt(dlen2));
508 else
510 mvb = blc[b]*len;
512 rhs1[b] = mvb;
513 sol[b] = mvb;
514 } /* 20*ncons flops */
516 lincs_matrix_expand(lincsd,blcc,rhs1,rhs2,sol);
517 /* nrec*(ncons+2*nrtot) flops */
519 for(b=0; b<ncons; b++)
521 i = bla[2*b];
522 j = bla[2*b+1];
523 lam = lambda[b];
524 mvb = blc[b]*sol[b];
525 lambda[b] = lam - mvb;
526 im1 = invmass[i];
527 im2 = invmass[j];
528 tmp0 = r[b][0]*mvb;
529 tmp1 = r[b][1]*mvb;
530 tmp2 = r[b][2]*mvb;
531 xp[i][0] -= tmp0*im1;
532 xp[i][1] -= tmp1*im1;
533 xp[i][2] -= tmp2*im1;
534 xp[j][0] += tmp0*im2;
535 xp[j][1] += tmp1*im2;
536 xp[j][2] += tmp2*im2;
537 } /* 17 ncons flops */
538 } /* nit*ncons*(37+9*nrec) flops */
540 if (v)
542 /* Correct the velocities */
543 for(b=0; b<ncons; b++)
545 i = bla[2*b];
546 j = bla[2*b+1];
547 im1 = invmass[i]*lambda[b]*invdt;
548 im2 = invmass[j]*lambda[b]*invdt;
549 v[i][0] += im1*r[b][0];
550 v[i][1] += im1*r[b][1];
551 v[i][2] += im1*r[b][2];
552 v[j][0] -= im2*r[b][0];
553 v[j][1] -= im2*r[b][1];
554 v[j][2] -= im2*r[b][2];
555 } /* 16 ncons flops */
558 if (nlocat)
560 /* Only account for local atoms */
561 for(b=0; b<ncons; b++)
563 lambda[b] *= 0.5*nlocat[b];
567 if (bCalcVir)
569 /* Constraint virial */
570 for(b=0; b<ncons; b++)
572 tmp0 = bllen[b]*lambda[b];
573 for(i=0; i<DIM; i++)
575 tmp1 = tmp0*r[b][i];
576 for(j=0; j<DIM; j++)
578 rmdr[i][j] -= tmp1*r[b][j];
581 } /* 22 ncons flops */
584 /* Total:
585 * 26*ncons + 6*nrtot + nrec*(ncons+2*nrtot)
586 * + nit * (20*ncons + nrec*(ncons+2*nrtot) + 17 ncons)
588 * (26+nrec)*ncons + (6+2*nrec)*nrtot
589 * + nit * ((37+nrec)*ncons + 2*nrec*nrtot)
590 * if nit=1
591 * (63+nrec)*ncons + (6+4*nrec)*nrtot
595 void set_lincs_matrix(struct gmx_lincsdata *li,real *invmass,real lambda)
597 int i,a1,a2,n,k,sign,center;
598 int end,nk,kk;
599 const real invsqrt2=0.7071067811865475244;
601 for(i=0; (i<li->nc); i++)
603 a1 = li->bla[2*i];
604 a2 = li->bla[2*i+1];
605 li->blc[i] = gmx_invsqrt(invmass[a1] + invmass[a2]);
606 li->blc1[i] = invsqrt2;
609 /* Construct the coupling coefficient matrix blmf */
610 li->ntriangle = 0;
611 li->ncc_triangle = 0;
612 for(i=0; (i<li->nc); i++)
614 a1 = li->bla[2*i];
615 a2 = li->bla[2*i+1];
616 for(n=li->blnr[i]; (n<li->blnr[i+1]); n++)
618 k = li->blbnb[n];
619 if (a1 == li->bla[2*k] || a2 == li->bla[2*k+1])
621 sign = -1;
623 else
625 sign = 1;
627 if (a1 == li->bla[2*k] || a1 == li->bla[2*k+1])
629 center = a1;
630 end = a2;
632 else
634 center = a2;
635 end = a1;
637 li->blmf[n] = sign*invmass[center]*li->blc[i]*li->blc[k];
638 li->blmf1[n] = sign*0.5;
639 if (li->ncg_triangle > 0)
641 /* Look for constraint triangles */
642 for(nk=li->blnr[k]; (nk<li->blnr[k+1]); nk++)
644 kk = li->blbnb[nk];
645 if (kk != i && kk != k &&
646 (li->bla[2*kk] == end || li->bla[2*kk+1] == end))
648 if (li->ntriangle == 0 ||
649 li->triangle[li->ntriangle-1] < i)
651 /* Add this constraint to the triangle list */
652 li->triangle[li->ntriangle] = i;
653 li->tri_bits[li->ntriangle] = 0;
654 li->ntriangle++;
655 if (li->blnr[i+1] - li->blnr[i] > sizeof(li->tri_bits[0])*8 - 1)
657 gmx_fatal(FARGS,"A constraint is connected to %d constraints, this is more than the %d allowed for constraints participating in triangles",
658 li->blnr[i+1] - li->blnr[i],
659 sizeof(li->tri_bits[0])*8-1);
662 li->tri_bits[li->ntriangle-1] |= (1<<(n-li->blnr[i]));
663 li->ncc_triangle++;
670 if (debug)
672 fprintf(debug,"Of the %d constraints %d participate in triangles\n",
673 li->nc,li->ntriangle);
674 fprintf(debug,"There are %d couplings of which %d in triangles\n",
675 li->ncc,li->ncc_triangle);
678 /* Set matlam,
679 * so we know with which lambda value the masses have been set.
681 li->matlam = lambda;
684 static int count_triangle_constraints(t_ilist *ilist,t_blocka *at2con)
686 int ncon1,ncon_tot;
687 int c0,a00,a01,n1,c1,a10,a11,ac1,n2,c2,a20,a21;
688 int ncon_triangle;
689 bool bTriangle;
690 t_iatom *ia1,*ia2,*iap;
692 ncon1 = ilist[F_CONSTR].nr/3;
693 ncon_tot = ncon1 + ilist[F_CONSTRNC].nr/3;
695 ia1 = ilist[F_CONSTR].iatoms;
696 ia2 = ilist[F_CONSTRNC].iatoms;
698 ncon_triangle = 0;
699 for(c0=0; c0<ncon_tot; c0++)
701 bTriangle = FALSE;
702 iap = constr_iatomptr(ncon1,ia1,ia2,c0);
703 a00 = iap[1];
704 a01 = iap[2];
705 for(n1=at2con->index[a01]; n1<at2con->index[a01+1]; n1++)
707 c1 = at2con->a[n1];
708 if (c1 != c0)
710 iap = constr_iatomptr(ncon1,ia1,ia2,c1);
711 a10 = iap[1];
712 a11 = iap[2];
713 if (a10 == a01)
715 ac1 = a11;
717 else
719 ac1 = a10;
721 for(n2=at2con->index[ac1]; n2<at2con->index[ac1+1]; n2++)
723 c2 = at2con->a[n2];
724 if (c2 != c0 && c2 != c1)
726 iap = constr_iatomptr(ncon1,ia1,ia2,c2);
727 a20 = iap[1];
728 a21 = iap[2];
729 if (a20 == a00 || a21 == a00)
731 bTriangle = TRUE;
737 if (bTriangle)
739 ncon_triangle++;
743 return ncon_triangle;
746 static int int_comp(const void *a,const void *b)
748 return (*(int *)a) - (*(int *)b);
751 gmx_lincsdata_t init_lincs(FILE *fplog,gmx_mtop_t *mtop,
752 int nflexcon_global,t_blocka *at2con,
753 bool bPLINCS,int nIter,int nProjOrder)
755 struct gmx_lincsdata *li;
756 int mb;
757 gmx_moltype_t *molt;
759 if (fplog)
761 fprintf(fplog,"\nInitializing%s LINear Constraint Solver\n",
762 bPLINCS ? " Parallel" : "");
765 snew(li,1);
767 li->ncg =
768 gmx_mtop_ftype_count(mtop,F_CONSTR) +
769 gmx_mtop_ftype_count(mtop,F_CONSTRNC);
770 li->ncg_flex = nflexcon_global;
772 li->ncg_triangle = 0;
773 for(mb=0; mb<mtop->nmolblock; mb++)
775 molt = &mtop->moltype[mtop->molblock[mb].type];
776 li->ncg_triangle +=
777 mtop->molblock[mb].nmol*
778 count_triangle_constraints(molt->ilist,
779 &at2con[mtop->molblock[mb].type]);
782 li->nIter = nIter;
783 li->nOrder = nProjOrder;
785 if (bPLINCS || li->ncg_triangle > 0)
787 please_cite(fplog,"Hess2008a");
789 else
791 please_cite(fplog,"Hess97a");
794 if (fplog)
796 fprintf(fplog,"The number of constraints is %d\n",li->ncg);
797 if (bPLINCS)
799 fprintf(fplog,"There are inter charge-group constraints,\n"
800 "will communicate selected coordinates each lincs iteration\n");
802 if (li->ncg_triangle > 0)
804 fprintf(fplog,
805 "%d constraints are involved in constraint triangles,\n"
806 "will apply an additional matrix expansion of order %d for couplings\n"
807 "between constraints inside triangles\n",
808 li->ncg_triangle,li->nOrder);
812 return li;
815 void set_lincs(t_idef *idef,t_mdatoms *md,
816 bool bDynamics,t_commrec *cr,
817 struct gmx_lincsdata *li)
819 int start,natoms,nflexcon;
820 t_blocka at2con;
821 t_iatom *iatom;
822 int i,k,ncc_alloc,ni,con,nconnect,concon;
823 int type,a1,a2;
824 real lenA=0,lenB;
825 bool bLocal;
827 li->nc = 0;
828 li->ncc = 0;
830 /* This is the local topology, so there are only F_CONSTR constraints */
831 if (idef->il[F_CONSTR].nr == 0)
833 /* There are no constraints,
834 * we do not need to fill any data structures.
836 return;
839 if (debug)
841 fprintf(debug,"Building the LINCS connectivity\n");
844 if (DOMAINDECOMP(cr))
846 if (cr->dd->constraints)
848 dd_get_constraint_range(cr->dd,&start,&natoms);
850 else
852 natoms = cr->dd->nat_home;
854 start = 0;
856 else if(PARTDECOMP(cr))
858 pd_get_constraint_range(cr->pd,&start,&natoms);
860 else
862 start = md->start;
863 natoms = md->homenr;
865 at2con = make_at2con(start,natoms,idef->il,idef->iparams,bDynamics,
866 &nflexcon);
869 if (idef->il[F_CONSTR].nr/3 > li->nc_alloc || li->nc_alloc == 0)
871 li->nc_alloc = over_alloc_dd(idef->il[F_CONSTR].nr/3);
872 srenew(li->bllen0,li->nc_alloc);
873 srenew(li->ddist,li->nc_alloc);
874 srenew(li->bla,2*li->nc_alloc);
875 srenew(li->blc,li->nc_alloc);
876 srenew(li->blc1,li->nc_alloc);
877 srenew(li->blnr,li->nc_alloc+1);
878 srenew(li->bllen,li->nc_alloc);
879 srenew(li->tmpv,li->nc_alloc);
880 srenew(li->tmp1,li->nc_alloc);
881 srenew(li->tmp2,li->nc_alloc);
882 srenew(li->tmp3,li->nc_alloc);
883 srenew(li->lambda,li->nc_alloc);
884 if (li->ncg_triangle > 0)
886 /* This is allocating too much, but it is difficult to improve */
887 srenew(li->triangle,li->nc_alloc);
888 srenew(li->tri_bits,li->nc_alloc);
892 iatom = idef->il[F_CONSTR].iatoms;
894 ncc_alloc = li->ncc_alloc;
895 li->blnr[0] = 0;
897 ni = idef->il[F_CONSTR].nr/3;
899 con = 0;
900 nconnect = 0;
901 li->blnr[con] = nconnect;
902 for(i=0; i<ni; i++)
904 bLocal = TRUE;
905 type = iatom[3*i];
906 a1 = iatom[3*i+1];
907 a2 = iatom[3*i+2];
908 lenA = idef->iparams[type].constr.dA;
909 lenB = idef->iparams[type].constr.dB;
910 /* Skip the flexible constraints when not doing dynamics */
911 if (bDynamics || lenA!=0 || lenB!=0)
913 li->bllen0[con] = lenA;
914 li->ddist[con] = lenB - lenA;
915 /* Set the length to the topology A length */
916 li->bllen[con] = li->bllen0[con];
917 li->bla[2*con] = a1;
918 li->bla[2*con+1] = a2;
919 /* Construct the constraint connection matrix blbnb */
920 for(k=at2con.index[a1-start]; k<at2con.index[a1-start+1]; k++)
922 concon = at2con.a[k];
923 if (concon != i)
925 if (nconnect >= ncc_alloc)
927 ncc_alloc = over_alloc_small(nconnect+1);
928 srenew(li->blbnb,ncc_alloc);
930 li->blbnb[nconnect++] = concon;
933 for(k=at2con.index[a2-start]; k<at2con.index[a2-start+1]; k++)
935 concon = at2con.a[k];
936 if (concon != i)
938 if (nconnect+1 > ncc_alloc)
940 ncc_alloc = over_alloc_small(nconnect+1);
941 srenew(li->blbnb,ncc_alloc);
943 li->blbnb[nconnect++] = concon;
946 li->blnr[con+1] = nconnect;
948 if (cr->dd == NULL)
950 /* Order the blbnb matrix to optimize memory access */
951 qsort(&(li->blbnb[li->blnr[con]]),li->blnr[con+1]-li->blnr[con],
952 sizeof(li->blbnb[0]),int_comp);
954 /* Increase the constraint count */
955 con++;
959 done_blocka(&at2con);
961 /* This is the real number of constraints,
962 * without dynamics the flexible constraints are not present.
964 li->nc = con;
966 li->ncc = li->blnr[con];
967 if (cr->dd == NULL)
969 /* Since the matrix is static, we can free some memory */
970 ncc_alloc = li->ncc;
971 srenew(li->blbnb,ncc_alloc);
974 if (ncc_alloc > li->ncc_alloc)
976 li->ncc_alloc = ncc_alloc;
977 srenew(li->blmf,li->ncc_alloc);
978 srenew(li->blmf1,li->ncc_alloc);
979 srenew(li->tmpncc,li->ncc_alloc);
982 if (debug)
984 fprintf(debug,"Number of constraints is %d, couplings %d\n",
985 li->nc,li->ncc);
988 set_lincs_matrix(li,md->invmass,md->lambda);
991 static void lincs_warning(FILE *fplog,
992 gmx_domdec_t *dd,rvec *x,rvec *xprime,t_pbc *pbc,
993 int ncons,int *bla,real *bllen,real wangle,
994 int maxwarn,int *warncount)
996 int b,i,j;
997 rvec v0,v1;
998 real wfac,d0,d1,cosine;
999 char buf[STRLEN];
1001 wfac=cos(DEG2RAD*wangle);
1003 sprintf(buf,"bonds that rotated more than %g degrees:\n"
1004 " atom 1 atom 2 angle previous, current, constraint length\n",
1005 wangle);
1006 fprintf(stderr,"%s",buf);
1007 if (fplog)
1009 fprintf(fplog,"%s",buf);
1012 for(b=0;b<ncons;b++)
1014 i = bla[2*b];
1015 j = bla[2*b+1];
1016 if (pbc)
1018 pbc_dx_aiuc(pbc,x[i],x[j],v0);
1019 pbc_dx_aiuc(pbc,xprime[i],xprime[j],v1);
1021 else
1023 rvec_sub(x[i],x[j],v0);
1024 rvec_sub(xprime[i],xprime[j],v1);
1026 d0 = norm(v0);
1027 d1 = norm(v1);
1028 cosine = iprod(v0,v1)/(d0*d1);
1029 if (cosine < wfac)
1031 sprintf(buf," %6d %6d %5.1f %8.4f %8.4f %8.4f\n",
1032 ddglatnr(dd,i),ddglatnr(dd,j),
1033 RAD2DEG*acos(cosine),d0,d1,bllen[b]);
1034 fprintf(stderr,"%s",buf);
1035 if (fplog)
1037 fprintf(fplog,"%s",buf);
1039 #ifdef HAS_ISFINITE
1040 if (!isfinite(d1))
1041 gmx_fatal(FARGS,"Bond length not finite.")
1042 #else
1043 #ifdef HAS__ISFINITE
1044 if (!_isfinite(d1))
1045 gmx_fatal(FARGS,"Bond length not finite.")
1046 #endif
1047 #endif
1049 (*warncount)++;
1052 if (*warncount > maxwarn)
1054 too_many_constraint_warnings(econtLINCS,*warncount);
1058 static void cconerr(gmx_domdec_t *dd,
1059 int ncons,int *bla,real *bllen,rvec *x,t_pbc *pbc,
1060 real *ncons_loc,real *ssd,real *max,int *imax)
1062 real len,d,ma,ssd2,r2;
1063 int *nlocat,count,b,im;
1064 rvec dx;
1066 if (dd && dd->constraints)
1068 nlocat = dd_constraints_nlocalatoms(dd);
1070 else
1072 nlocat = 0;
1075 ma = 0;
1076 ssd2 = 0;
1077 im = 0;
1078 count = 0;
1079 for(b=0;b<ncons;b++)
1081 if (pbc)
1083 pbc_dx_aiuc(pbc,x[bla[2*b]],x[bla[2*b+1]],dx);
1085 else {
1086 rvec_sub(x[bla[2*b]],x[bla[2*b+1]],dx);
1088 r2 = norm2(dx);
1089 len = r2*gmx_invsqrt(r2);
1090 d = fabs(len/bllen[b]-1);
1091 if (d > ma && (nlocat==NULL || nlocat[b]))
1093 ma = d;
1094 im = b;
1096 if (nlocat == NULL)
1098 ssd2 += d*d;
1099 count++;
1101 else
1103 ssd2 += nlocat[b]*d*d;
1104 count += nlocat[b];
1108 *ncons_loc = (nlocat ? 0.5 : 1)*count;
1109 *ssd = (nlocat ? 0.5 : 1)*ssd2;
1110 *max = ma;
1111 *imax = im;
1114 static void dump_conf(gmx_domdec_t *dd,struct gmx_lincsdata *li,
1115 t_blocka *at2con,
1116 char *name,bool bAll,rvec *x,matrix box)
1118 char str[STRLEN];
1119 FILE *fp;
1120 int ac0,ac1,i;
1122 dd_get_constraint_range(dd,&ac0,&ac1);
1124 sprintf(str,"%s_%d_%d_%d.pdb",name,dd->ci[XX],dd->ci[YY],dd->ci[ZZ]);
1125 fp = gmx_fio_fopen(str,"w");
1126 fprintf(fp,"CRYST1%9.3f%9.3f%9.3f%7.2f%7.2f%7.2f P 1 1\n",
1127 10*norm(box[XX]),10*norm(box[YY]),10*norm(box[ZZ]),
1128 90.0,90.0,90.0);
1129 for(i=0; i<ac1; i++)
1131 if (i < dd->nat_home || (bAll && i >= ac0 && i < ac1))
1133 fprintf(fp,"%-6s%5u %-4.4s%3.3s %c%4d %8.3f%8.3f%8.3f%6.2f%6.2f\n",
1134 "ATOM",ddglatnr(dd,i),"C","ALA",' ',i+1,
1135 10*x[i][XX],10*x[i][YY],10*x[i][ZZ],
1136 1.0,i<dd->nat_tot ? 0.0 : 1.0);
1139 if (bAll)
1141 for(i=0; i<li->nc; i++)
1143 fprintf(fp,"CONECT%5d%5d\n",
1144 ddglatnr(dd,li->bla[2*i]),
1145 ddglatnr(dd,li->bla[2*i+1]));
1148 gmx_fio_fclose(fp);
1151 bool constrain_lincs(FILE *fplog,bool bLog,bool bEner,
1152 t_inputrec *ir,
1153 gmx_large_int_t step,
1154 struct gmx_lincsdata *lincsd,t_mdatoms *md,
1155 t_commrec *cr,
1156 rvec *x,rvec *xprime,rvec *min_proj,matrix box,
1157 real lambda,real *dvdlambda,
1158 real invdt,rvec *v,
1159 bool bCalcVir,tensor rmdr,
1160 int econq,
1161 t_nrnb *nrnb,
1162 int maxwarn,int *warncount)
1164 char buf[STRLEN],buf2[22];
1165 int i,warn,p_imax,error;
1166 real ncons_loc,p_ssd,p_max;
1167 t_pbc pbc,*pbc_null;
1168 rvec dx;
1169 bool bOK;
1171 bOK = TRUE;
1173 if (lincsd->nc == 0 && cr->dd == NULL)
1175 if (bLog || bEner)
1177 lincsd->rmsd_data[0] = 0;
1178 if (ir->eI == eiSD2 && v == NULL)
1180 i = 2;
1182 else
1184 i = 1;
1186 lincsd->rmsd_data[i] = 0;
1189 return bOK;
1192 /* We do not need full pbc when constraints do not cross charge groups,
1193 * i.e. when dd->constraint_comm==NULL
1195 if ((cr->dd || ir->bPeriodicMols) && !(cr->dd && cr->dd->constraint_comm==NULL))
1197 /* With pbc=screw the screw has been changed to a shift
1198 * by the constraint coordinate communication routine,
1199 * so that here we can use normal pbc.
1201 pbc_null = set_pbc_dd(&pbc,ir->ePBC,cr->dd,FALSE,box);
1203 else
1205 pbc_null = NULL;
1207 if (cr->dd)
1209 /* Communicate the coordinates required for the non-local constraints */
1210 dd_move_x_constraints(cr->dd,box,x,xprime);
1211 /* dump_conf(dd,lincsd,NULL,"con",TRUE,xprime,box); */
1213 else if (PARTDECOMP(cr))
1215 pd_move_x_constraints(cr,x,xprime);
1218 if (econq == econqCoord)
1220 if (ir->efep != efepNO)
1222 if (md->nMassPerturbed && lincsd->matlam != md->lambda)
1224 set_lincs_matrix(lincsd,md->invmass,md->lambda);
1227 for(i=0; i<lincsd->nc; i++)
1229 lincsd->bllen[i] = lincsd->bllen0[i] + lambda*lincsd->ddist[i];
1233 if (lincsd->ncg_flex)
1235 /* Set the flexible constraint lengths to the old lengths */
1236 if (pbc_null)
1238 for(i=0; i<lincsd->nc; i++)
1240 if (lincsd->bllen[i] == 0) {
1241 pbc_dx_aiuc(pbc_null,x[lincsd->bla[2*i]],x[lincsd->bla[2*i+1]],dx);
1242 lincsd->bllen[i] = norm(dx);
1246 else
1248 for(i=0; i<lincsd->nc; i++)
1250 if (lincsd->bllen[i] == 0)
1252 lincsd->bllen[i] =
1253 sqrt(distance2(x[lincsd->bla[2*i]],
1254 x[lincsd->bla[2*i+1]]));
1260 if (bLog && fplog)
1262 cconerr(cr->dd,lincsd->nc,lincsd->bla,lincsd->bllen,xprime,pbc_null,
1263 &ncons_loc,&p_ssd,&p_max,&p_imax);
1266 do_lincs(x,xprime,box,pbc_null,lincsd,md->invmass,cr,
1267 ir->LincsWarnAngle,&warn,
1268 invdt,v,bCalcVir,rmdr);
1270 if (ir->efep != efepNO)
1272 real dt_2,dvdl=0;
1274 dt_2 = 1.0/(ir->delta_t*ir->delta_t);
1275 for(i=0; (i<lincsd->nc); i++)
1277 dvdl += lincsd->lambda[i]*dt_2*lincsd->ddist[i];
1279 *dvdlambda += dvdl;
1282 if (bLog && fplog && lincsd->nc > 0)
1284 fprintf(fplog," Rel. Constraint Deviation: RMS MAX between atoms\n");
1285 fprintf(fplog," Before LINCS %.6f %.6f %6d %6d\n",
1286 sqrt(p_ssd/ncons_loc),p_max,
1287 ddglatnr(cr->dd,lincsd->bla[2*p_imax]),
1288 ddglatnr(cr->dd,lincsd->bla[2*p_imax+1]));
1290 if (bLog || bEner)
1292 cconerr(cr->dd,lincsd->nc,lincsd->bla,lincsd->bllen,xprime,pbc_null,
1293 &ncons_loc,&p_ssd,&p_max,&p_imax);
1294 lincsd->rmsd_data[0] = ncons_loc;
1295 /* Check if we are doing the second part of SD */
1296 if (ir->eI == eiSD2 && v == NULL)
1298 i = 2;
1300 else
1302 i = 1;
1304 lincsd->rmsd_data[0] = ncons_loc;
1305 lincsd->rmsd_data[i] = p_ssd;
1307 if (bLog && fplog && lincsd->nc > 0)
1309 fprintf(fplog,
1310 " After LINCS %.6f %.6f %6d %6d\n\n",
1311 sqrt(p_ssd/ncons_loc),p_max,
1312 ddglatnr(cr->dd,lincsd->bla[2*p_imax]),
1313 ddglatnr(cr->dd,lincsd->bla[2*p_imax+1]));
1316 if (warn > 0)
1318 if (maxwarn >= 0)
1320 cconerr(cr->dd,lincsd->nc,lincsd->bla,lincsd->bllen,xprime,pbc_null,
1321 &ncons_loc,&p_ssd,&p_max,&p_imax);
1322 sprintf(buf,"\nStep %s, time %g (ps) LINCS WARNING\n"
1323 "relative constraint deviation after LINCS:\n"
1324 "rms %.6f, max %.6f (between atoms %d and %d)\n",
1325 gmx_step_str(step,buf2),ir->init_t+step*ir->delta_t,
1326 sqrt(p_ssd/ncons_loc),p_max,
1327 ddglatnr(cr->dd,lincsd->bla[2*p_imax]),
1328 ddglatnr(cr->dd,lincsd->bla[2*p_imax+1]));
1329 if (fplog)
1331 fprintf(fplog,"%s",buf);
1333 fprintf(stderr,"%s",buf);
1334 lincs_warning(fplog,cr->dd,x,xprime,pbc_null,
1335 lincsd->nc,lincsd->bla,lincsd->bllen,
1336 ir->LincsWarnAngle,maxwarn,warncount);
1338 bOK = (p_max < 0.5);
1341 if (lincsd->ncg_flex) {
1342 for(i=0; (i<lincsd->nc); i++)
1343 if (lincsd->bllen0[i] == 0 && lincsd->ddist[i] == 0)
1344 lincsd->bllen[i] = 0;
1347 else
1349 do_lincsp(x,xprime,min_proj,pbc_null,lincsd,md->invmass,econq,dvdlambda,
1350 bCalcVir,rmdr);
1353 /* count assuming nit=1 */
1354 inc_nrnb(nrnb,eNR_LINCS,lincsd->nc);
1355 inc_nrnb(nrnb,eNR_LINCSMAT,(2+lincsd->nOrder)*lincsd->ncc);
1356 if (lincsd->ntriangle > 0)
1358 inc_nrnb(nrnb,eNR_LINCSMAT,lincsd->nOrder*lincsd->ncc_triangle);
1360 if (v)
1362 inc_nrnb(nrnb,eNR_CONSTR_V,lincsd->nc*2);
1364 if (bCalcVir)
1366 inc_nrnb(nrnb,eNR_CONSTR_VIR,lincsd->nc);
1369 return bOK;