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.
37 /* This file is completely threadsafe - keep it that way! */
45 #include "types/commrec.h"
48 #include "gromacs/math/units.h"
49 #include "gromacs/math/vec.h"
54 #include "mtop_util.h"
55 #include "gmx_omp_nthreads.h"
57 #include "gromacs/fileio/gmxfio.h"
58 #include "gromacs/utility/fatalerror.h"
59 #include "gromacs/utility/gmxomp.h"
60 #include "gromacs/utility/smalloc.h"
63 int b0
; /* first constraint for this thread */
64 int b1
; /* b1-1 is the last constraint for this thread */
65 int nind
; /* number of indices */
66 int *ind
; /* constraint index for updating atom data */
67 int nind_r
; /* number of indices */
68 int *ind_r
; /* constraint index for updating atom data */
69 int ind_nalloc
; /* allocation size of ind and ind_r */
70 tensor vir_r_m_dr
; /* temporary variable for virial calculation */
73 typedef struct gmx_lincsdata
{
74 int ncg
; /* the global number of constraints */
75 int ncg_flex
; /* the global number of flexible constraints */
76 int ncg_triangle
; /* the global number of constraints in triangles */
77 int nIter
; /* the number of iterations */
78 int nOrder
; /* the order of the matrix expansion */
79 int nc
; /* the number of constraints */
80 int nc_alloc
; /* the number we allocated memory for */
81 int ncc
; /* the number of constraint connections */
82 int ncc_alloc
; /* the number we allocated memory for */
83 real matlam
; /* the FE lambda value used for filling blc and blmf */
84 real
*bllen0
; /* the reference distance in topology A */
85 real
*ddist
; /* the reference distance in top B - the r.d. in top A */
86 int *bla
; /* the atom pairs involved in the constraints */
87 real
*blc
; /* 1/sqrt(invmass1 + invmass2) */
88 real
*blc1
; /* as blc, but with all masses 1 */
89 int *blnr
; /* index into blbnb and blmf */
90 int *blbnb
; /* list of constraint connections */
91 int ntriangle
; /* the local number of constraints in triangles */
92 int *triangle
; /* the list of triangle constraints */
93 int *tri_bits
; /* the bits tell if the matrix element should be used */
94 int ncc_triangle
; /* the number of constraint connections in triangles */
95 gmx_bool bCommIter
; /* communicate before each LINCS interation */
96 real
*blmf
; /* matrix of mass factors for constraint connections */
97 real
*blmf1
; /* as blmf, but with all masses 1 */
98 real
*bllen
; /* the reference bond length */
99 int nth
; /* The number of threads doing LINCS */
100 lincs_thread_t
*th
; /* LINCS thread division */
101 unsigned *atf
; /* atom flags for thread parallelization */
102 int atf_nalloc
; /* allocation size of atf */
103 /* arrays for temporary storage in the LINCS algorithm */
110 real
*mlambda
; /* the Lagrange multipliers * -1 */
111 /* storage for the constraint RMS relative deviation output */
115 real
*lincs_rmsd_data(struct gmx_lincsdata
*lincsd
)
117 return lincsd
->rmsd_data
;
120 real
lincs_rmsd(struct gmx_lincsdata
*lincsd
, gmx_bool bSD2
)
122 if (lincsd
->rmsd_data
[0] > 0)
124 return sqrt(lincsd
->rmsd_data
[bSD2
? 2 : 1]/lincsd
->rmsd_data
[0]);
132 /* Do a set of nrec LINCS matrix multiplications.
133 * This function will return with up to date thread-local
134 * constraint data, without an OpenMP barrier.
136 static void lincs_matrix_expand(const struct gmx_lincsdata
*lincsd
,
139 real
*rhs1
, real
*rhs2
, real
*sol
)
141 int nrec
, rec
, b
, j
, n
, nr0
, nr1
;
143 int ntriangle
, tb
, bits
;
144 const int *blnr
= lincsd
->blnr
, *blbnb
= lincsd
->blbnb
;
145 const int *triangle
= lincsd
->triangle
, *tri_bits
= lincsd
->tri_bits
;
147 ntriangle
= lincsd
->ntriangle
;
148 nrec
= lincsd
->nOrder
;
150 for (rec
= 0; rec
< nrec
; rec
++)
153 for (b
= b0
; b
< b1
; b
++)
156 for (n
= blnr
[b
]; n
< blnr
[b
+1]; n
++)
159 mvb
= mvb
+ blcc
[n
]*rhs1
[j
];
162 sol
[b
] = sol
[b
] + mvb
;
167 } /* nrec*(ncons+2*nrtot) flops */
171 /* Perform an extra nrec recursions for only the constraints
172 * involved in rigid triangles.
173 * In this way their accuracy should come close to those of the other
174 * constraints, since traingles of constraints can produce eigenvalues
175 * around 0.7, while the effective eigenvalue for bond constraints
176 * is around 0.4 (and 0.7*0.7=0.5).
178 /* We need to copy the temporary array, since only the elements
179 * for constraints involved in triangles are updated and then
180 * the pointers are swapped. This saving copying the whole arrary.
181 * We need barrier as other threads might still be reading from rhs2.
184 for (b
= b0
; b
< b1
; b
++)
191 for (rec
= 0; rec
< nrec
; rec
++)
193 for (tb
= 0; tb
< ntriangle
; tb
++)
200 for (n
= nr0
; n
< nr1
; n
++)
202 if (bits
& (1<<(n
-nr0
)))
205 mvb
= mvb
+ blcc
[n
]*rhs1
[j
];
209 sol
[b
] = sol
[b
] + mvb
;
215 } /* flops count is missing here */
217 /* We need a barrier here as the calling routine will continue
218 * to operate on the thread-local constraints without barrier.
224 static void lincs_update_atoms_noind(int ncons
, const int *bla
,
226 const real
*fac
, rvec
*r
,
231 real mvb
, im1
, im2
, tmp0
, tmp1
, tmp2
;
235 for (b
= 0; b
< ncons
; b
++)
251 } /* 16 ncons flops */
255 for (b
= 0; b
< ncons
; b
++)
273 static void lincs_update_atoms_ind(int ncons
, const int *ind
, const int *bla
,
275 const real
*fac
, rvec
*r
,
280 real mvb
, im1
, im2
, tmp0
, tmp1
, tmp2
;
284 for (bi
= 0; bi
< ncons
; bi
++)
301 } /* 16 ncons flops */
305 for (bi
= 0; bi
< ncons
; bi
++)
320 } /* 16 ncons flops */
324 static void lincs_update_atoms(struct gmx_lincsdata
*li
, int th
,
326 const real
*fac
, rvec
*r
,
332 /* Single thread, we simply update for all constraints */
333 lincs_update_atoms_noind(li
->nc
, li
->bla
, prefac
, fac
, r
, invmass
, x
);
337 /* Update the atom vector components for our thread local
338 * constraints that only access our local atom range.
339 * This can be done without a barrier.
341 lincs_update_atoms_ind(li
->th
[th
].nind
, li
->th
[th
].ind
,
342 li
->bla
, prefac
, fac
, r
, invmass
, x
);
344 if (li
->th
[li
->nth
].nind
> 0)
346 /* Update the constraints that operate on atoms
347 * in multiple thread atom blocks on the master thread.
352 lincs_update_atoms_ind(li
->th
[li
->nth
].nind
,
354 li
->bla
, prefac
, fac
, r
, invmass
, x
);
360 /* LINCS projection, works on derivatives of the coordinates */
361 static void do_lincsp(rvec
*x
, rvec
*f
, rvec
*fp
, t_pbc
*pbc
,
362 struct gmx_lincsdata
*lincsd
, int th
,
364 int econq
, real
*dvdlambda
,
365 gmx_bool bCalcVir
, tensor rmdf
)
367 int b0
, b1
, b
, i
, j
, k
, n
;
368 real tmp0
, tmp1
, tmp2
, im1
, im2
, mvb
, rlen
, len
, wfac
, lam
;
370 int *bla
, *blnr
, *blbnb
;
372 real
*blc
, *blmf
, *blcc
, *rhs1
, *rhs2
, *sol
;
374 b0
= lincsd
->th
[th
].b0
;
375 b1
= lincsd
->th
[th
].b1
;
380 blbnb
= lincsd
->blbnb
;
381 if (econq
!= econqForce
)
383 /* Use mass-weighted parameters */
389 /* Use non mass-weighted parameters */
391 blmf
= lincsd
->blmf1
;
393 blcc
= lincsd
->tmpncc
;
398 /* Compute normalized i-j vectors */
401 for (b
= b0
; b
< b1
; b
++)
403 pbc_dx_aiuc(pbc
, x
[bla
[2*b
]], x
[bla
[2*b
+1]], dx
);
409 for (b
= b0
; b
< b1
; b
++)
411 rvec_sub(x
[bla
[2*b
]], x
[bla
[2*b
+1]], dx
);
413 } /* 16 ncons flops */
417 for (b
= b0
; b
< b1
; b
++)
424 for (n
= blnr
[b
]; n
< blnr
[b
+1]; n
++)
427 blcc
[n
] = blmf
[n
]*(tmp0
*r
[k
][0] + tmp1
*r
[k
][1] + tmp2
*r
[k
][2]);
429 mvb
= blc
[b
]*(tmp0
*(f
[i
][0] - f
[j
][0]) +
430 tmp1
*(f
[i
][1] - f
[j
][1]) +
431 tmp2
*(f
[i
][2] - f
[j
][2]));
436 /* Together: 23*ncons + 6*nrtot flops */
438 lincs_matrix_expand(lincsd
, b0
, b1
, blcc
, rhs1
, rhs2
, sol
);
439 /* nrec*(ncons+2*nrtot) flops */
441 if (econq
== econqDeriv_FlexCon
)
443 /* We only want to constraint the flexible constraints,
444 * so we mask out the normal ones by setting sol to 0.
446 for (b
= b0
; b
< b1
; b
++)
448 if (!(lincsd
->bllen0
[b
] == 0 && lincsd
->ddist
[b
] == 0))
455 /* We multiply sol by blc, so we can use lincs_update_atoms for OpenMP */
456 for (b
= b0
; b
< b1
; b
++)
461 /* When constraining forces, we should not use mass weighting,
462 * so we pass invmass=NULL, which results in the use of 1 for all atoms.
464 lincs_update_atoms(lincsd
, th
, 1.0, sol
, r
,
465 (econq
!= econqForce
) ? invmass
: NULL
, fp
);
467 if (dvdlambda
!= NULL
)
470 for (b
= b0
; b
< b1
; b
++)
472 *dvdlambda
-= sol
[b
]*lincsd
->ddist
[b
];
479 /* Constraint virial,
480 * determines sum r_bond x delta f,
481 * where delta f is the constraint correction
482 * of the quantity that is being constrained.
484 for (b
= b0
; b
< b1
; b
++)
486 mvb
= lincsd
->bllen
[b
]*sol
[b
];
487 for (i
= 0; i
< DIM
; i
++)
490 for (j
= 0; j
< DIM
; j
++)
492 rmdf
[i
][j
] += tmp1
*r
[b
][j
];
495 } /* 23 ncons flops */
499 static void do_lincs(rvec
*x
, rvec
*xp
, matrix box
, t_pbc
*pbc
,
500 struct gmx_lincsdata
*lincsd
, int th
,
503 gmx_bool bCalcLambda
,
504 real wangle
, int *warn
,
506 gmx_bool bCalcVir
, tensor vir_r_m_dr
)
508 int b0
, b1
, b
, i
, j
, k
, n
, iter
;
509 real tmp0
, tmp1
, tmp2
, im1
, im2
, mvb
, rlen
, len
, len2
, dlen2
, wfac
;
511 int *bla
, *blnr
, *blbnb
;
513 real
*blc
, *blmf
, *bllen
, *blcc
, *rhs1
, *rhs2
, *sol
, *blc_sol
, *mlambda
;
516 b0
= lincsd
->th
[th
].b0
;
517 b1
= lincsd
->th
[th
].b1
;
522 blbnb
= lincsd
->blbnb
;
525 bllen
= lincsd
->bllen
;
526 blcc
= lincsd
->tmpncc
;
530 blc_sol
= lincsd
->tmp4
;
531 mlambda
= lincsd
->mlambda
;
533 if (DOMAINDECOMP(cr
) && cr
->dd
->constraints
)
535 nlocat
= dd_constraints_nlocalatoms(cr
->dd
);
544 /* Compute normalized i-j vectors */
545 for (b
= b0
; b
< b1
; b
++)
547 pbc_dx_aiuc(pbc
, x
[bla
[2*b
]], x
[bla
[2*b
+1]], dx
);
551 for (b
= b0
; b
< b1
; b
++)
553 for (n
= blnr
[b
]; n
< blnr
[b
+1]; n
++)
555 blcc
[n
] = blmf
[n
]*iprod(r
[b
], r
[blbnb
[n
]]);
557 pbc_dx_aiuc(pbc
, xp
[bla
[2*b
]], xp
[bla
[2*b
+1]], dx
);
558 mvb
= blc
[b
]*(iprod(r
[b
], dx
) - bllen
[b
]);
565 /* Compute normalized i-j vectors */
566 for (b
= b0
; b
< b1
; b
++)
570 tmp0
= x
[i
][0] - x
[j
][0];
571 tmp1
= x
[i
][1] - x
[j
][1];
572 tmp2
= x
[i
][2] - x
[j
][2];
573 rlen
= gmx_invsqrt(tmp0
*tmp0
+tmp1
*tmp1
+tmp2
*tmp2
);
577 } /* 16 ncons flops */
580 for (b
= b0
; b
< b1
; b
++)
588 for (n
= blnr
[b
]; n
< blnr
[b
+1]; n
++)
591 blcc
[n
] = blmf
[n
]*(tmp0
*r
[k
][0] + tmp1
*r
[k
][1] + tmp2
*r
[k
][2]);
593 mvb
= blc
[b
]*(tmp0
*(xp
[i
][0] - xp
[j
][0]) +
594 tmp1
*(xp
[i
][1] - xp
[j
][1]) +
595 tmp2
*(xp
[i
][2] - xp
[j
][2]) - len
);
600 /* Together: 26*ncons + 6*nrtot flops */
603 lincs_matrix_expand(lincsd
, b0
, b1
, blcc
, rhs1
, rhs2
, sol
);
604 /* nrec*(ncons+2*nrtot) flops */
606 for (b
= b0
; b
< b1
; b
++)
608 mlambda
[b
] = blc
[b
]*sol
[b
];
611 /* Update the coordinates */
612 lincs_update_atoms(lincsd
, th
, 1.0, mlambda
, r
, invmass
, xp
);
615 ******** Correction for centripetal effects ********
618 wfac
= cos(DEG2RAD
*wangle
);
621 for (iter
= 0; iter
< lincsd
->nIter
; iter
++)
623 if ((lincsd
->bCommIter
&& DOMAINDECOMP(cr
) && cr
->dd
->constraints
))
628 /* Communicate the corrected non-local coordinates */
629 if (DOMAINDECOMP(cr
))
631 dd_move_x_constraints(cr
->dd
, box
, xp
, NULL
, FALSE
);
637 for (b
= b0
; b
< b1
; b
++)
642 pbc_dx_aiuc(pbc
, xp
[bla
[2*b
]], xp
[bla
[2*b
+1]], dx
);
646 rvec_sub(xp
[bla
[2*b
]], xp
[bla
[2*b
+1]], dx
);
649 dlen2
= 2*len2
- norm2(dx
);
650 if (dlen2
< wfac
*len2
&& (nlocat
== NULL
|| nlocat
[b
]))
656 mvb
= blc
[b
]*(len
- dlen2
*gmx_invsqrt(dlen2
));
664 } /* 20*ncons flops */
666 lincs_matrix_expand(lincsd
, b0
, b1
, blcc
, rhs1
, rhs2
, sol
);
667 /* nrec*(ncons+2*nrtot) flops */
669 for (b
= b0
; b
< b1
; b
++)
676 /* Update the coordinates */
677 lincs_update_atoms(lincsd
, th
, 1.0, blc_sol
, r
, invmass
, xp
);
679 /* nit*ncons*(37+9*nrec) flops */
683 /* Update the velocities */
684 lincs_update_atoms(lincsd
, th
, invdt
, mlambda
, r
, invmass
, v
);
688 if (nlocat
!= NULL
&& bCalcLambda
)
690 /* In lincs_update_atoms thread might cross-read mlambda */
693 /* Only account for local atoms */
694 for (b
= b0
; b
< b1
; b
++)
696 mlambda
[b
] *= 0.5*nlocat
[b
];
702 /* Constraint virial */
703 for (b
= b0
; b
< b1
; b
++)
705 tmp0
= -bllen
[b
]*mlambda
[b
];
706 for (i
= 0; i
< DIM
; i
++)
709 for (j
= 0; j
< DIM
; j
++)
711 vir_r_m_dr
[i
][j
] -= tmp1
*r
[b
][j
];
714 } /* 22 ncons flops */
718 * 26*ncons + 6*nrtot + nrec*(ncons+2*nrtot)
719 * + nit * (20*ncons + nrec*(ncons+2*nrtot) + 17 ncons)
721 * (26+nrec)*ncons + (6+2*nrec)*nrtot
722 * + nit * ((37+nrec)*ncons + 2*nrec*nrtot)
724 * (63+nrec)*ncons + (6+4*nrec)*nrtot
728 void set_lincs_matrix(struct gmx_lincsdata
*li
, real
*invmass
, real lambda
)
730 int i
, a1
, a2
, n
, k
, sign
, center
;
732 const real invsqrt2
= 0.7071067811865475244;
734 for (i
= 0; (i
< li
->nc
); i
++)
738 li
->blc
[i
] = gmx_invsqrt(invmass
[a1
] + invmass
[a2
]);
739 li
->blc1
[i
] = invsqrt2
;
742 /* Construct the coupling coefficient matrix blmf */
744 li
->ncc_triangle
= 0;
745 for (i
= 0; (i
< li
->nc
); i
++)
749 for (n
= li
->blnr
[i
]; (n
< li
->blnr
[i
+1]); n
++)
752 if (a1
== li
->bla
[2*k
] || a2
== li
->bla
[2*k
+1])
760 if (a1
== li
->bla
[2*k
] || a1
== li
->bla
[2*k
+1])
770 li
->blmf
[n
] = sign
*invmass
[center
]*li
->blc
[i
]*li
->blc
[k
];
771 li
->blmf1
[n
] = sign
*0.5;
772 if (li
->ncg_triangle
> 0)
774 /* Look for constraint triangles */
775 for (nk
= li
->blnr
[k
]; (nk
< li
->blnr
[k
+1]); nk
++)
778 if (kk
!= i
&& kk
!= k
&&
779 (li
->bla
[2*kk
] == end
|| li
->bla
[2*kk
+1] == end
))
781 if (li
->ntriangle
== 0 ||
782 li
->triangle
[li
->ntriangle
-1] < i
)
784 /* Add this constraint to the triangle list */
785 li
->triangle
[li
->ntriangle
] = i
;
786 li
->tri_bits
[li
->ntriangle
] = 0;
788 if (li
->blnr
[i
+1] - li
->blnr
[i
] > sizeof(li
->tri_bits
[0])*8 - 1)
790 gmx_fatal(FARGS
, "A constraint is connected to %d constraints, this is more than the %d allowed for constraints participating in triangles",
791 li
->blnr
[i
+1] - li
->blnr
[i
],
792 sizeof(li
->tri_bits
[0])*8-1);
795 li
->tri_bits
[li
->ntriangle
-1] |= (1<<(n
-li
->blnr
[i
]));
805 fprintf(debug
, "Of the %d constraints %d participate in triangles\n",
806 li
->nc
, li
->ntriangle
);
807 fprintf(debug
, "There are %d couplings of which %d in triangles\n",
808 li
->ncc
, li
->ncc_triangle
);
812 * so we know with which lambda value the masses have been set.
817 static int count_triangle_constraints(t_ilist
*ilist
, t_blocka
*at2con
)
820 int c0
, a00
, a01
, n1
, c1
, a10
, a11
, ac1
, n2
, c2
, a20
, a21
;
823 t_iatom
*ia1
, *ia2
, *iap
;
825 ncon1
= ilist
[F_CONSTR
].nr
/3;
826 ncon_tot
= ncon1
+ ilist
[F_CONSTRNC
].nr
/3;
828 ia1
= ilist
[F_CONSTR
].iatoms
;
829 ia2
= ilist
[F_CONSTRNC
].iatoms
;
832 for (c0
= 0; c0
< ncon_tot
; c0
++)
835 iap
= constr_iatomptr(ncon1
, ia1
, ia2
, c0
);
838 for (n1
= at2con
->index
[a01
]; n1
< at2con
->index
[a01
+1]; n1
++)
843 iap
= constr_iatomptr(ncon1
, ia1
, ia2
, c1
);
854 for (n2
= at2con
->index
[ac1
]; n2
< at2con
->index
[ac1
+1]; n2
++)
857 if (c2
!= c0
&& c2
!= c1
)
859 iap
= constr_iatomptr(ncon1
, ia1
, ia2
, c2
);
862 if (a20
== a00
|| a21
== a00
)
876 return ncon_triangle
;
879 static gmx_bool
more_than_two_sequential_constraints(const t_ilist
*ilist
,
880 const t_blocka
*at2con
)
882 t_iatom
*ia1
, *ia2
, *iap
;
883 int ncon1
, ncon_tot
, c
;
885 gmx_bool bMoreThanTwoSequentialConstraints
;
887 ncon1
= ilist
[F_CONSTR
].nr
/3;
888 ncon_tot
= ncon1
+ ilist
[F_CONSTRNC
].nr
/3;
890 ia1
= ilist
[F_CONSTR
].iatoms
;
891 ia2
= ilist
[F_CONSTRNC
].iatoms
;
893 bMoreThanTwoSequentialConstraints
= FALSE
;
894 for (c
= 0; c
< ncon_tot
&& !bMoreThanTwoSequentialConstraints
; c
++)
896 iap
= constr_iatomptr(ncon1
, ia1
, ia2
, c
);
899 /* Check if this constraint has constraints connected at both atoms */
900 if (at2con
->index
[a1
+1] - at2con
->index
[a1
] > 1 &&
901 at2con
->index
[a2
+1] - at2con
->index
[a2
] > 1)
903 bMoreThanTwoSequentialConstraints
= TRUE
;
907 return bMoreThanTwoSequentialConstraints
;
910 static int int_comp(const void *a
, const void *b
)
912 return (*(int *)a
) - (*(int *)b
);
915 gmx_lincsdata_t
init_lincs(FILE *fplog
, gmx_mtop_t
*mtop
,
916 int nflexcon_global
, t_blocka
*at2con
,
917 gmx_bool bPLINCS
, int nIter
, int nProjOrder
)
919 struct gmx_lincsdata
*li
;
925 fprintf(fplog
, "\nInitializing%s LINear Constraint Solver\n",
926 bPLINCS
? " Parallel" : "");
932 gmx_mtop_ftype_count(mtop
, F_CONSTR
) +
933 gmx_mtop_ftype_count(mtop
, F_CONSTRNC
);
934 li
->ncg_flex
= nflexcon_global
;
937 li
->nOrder
= nProjOrder
;
939 li
->ncg_triangle
= 0;
940 li
->bCommIter
= FALSE
;
941 for (mb
= 0; mb
< mtop
->nmolblock
; mb
++)
943 molt
= &mtop
->moltype
[mtop
->molblock
[mb
].type
];
945 mtop
->molblock
[mb
].nmol
*
946 count_triangle_constraints(molt
->ilist
,
947 &at2con
[mtop
->molblock
[mb
].type
]);
948 if (bPLINCS
&& li
->bCommIter
== FALSE
)
950 /* Check if we need to communicate not only before LINCS,
951 * but also before each iteration.
952 * The check for only two sequential constraints is only
953 * useful for the common case of H-bond only constraints.
954 * With more effort we could also make it useful for small
955 * molecules with nr. sequential constraints <= nOrder-1.
957 li
->bCommIter
= (li
->nOrder
< 1 || more_than_two_sequential_constraints(molt
->ilist
, &at2con
[mtop
->molblock
[mb
].type
]));
960 if (debug
&& bPLINCS
)
962 fprintf(debug
, "PLINCS communication before each iteration: %d\n",
966 /* LINCS can run on any number of threads.
967 * Currently the number is fixed for the whole simulation,
968 * but it could be set in set_lincs().
970 li
->nth
= gmx_omp_nthreads_get(emntLINCS
);
977 /* Allocate an extra elements for "thread-overlap" constraints */
978 snew(li
->th
, li
->nth
+1);
982 fprintf(debug
, "LINCS: using %d threads\n", li
->nth
);
985 if (bPLINCS
|| li
->ncg_triangle
> 0)
987 please_cite(fplog
, "Hess2008a");
991 please_cite(fplog
, "Hess97a");
996 fprintf(fplog
, "The number of constraints is %d\n", li
->ncg
);
999 fprintf(fplog
, "There are inter charge-group constraints,\n"
1000 "will communicate selected coordinates each lincs iteration\n");
1002 if (li
->ncg_triangle
> 0)
1005 "%d constraints are involved in constraint triangles,\n"
1006 "will apply an additional matrix expansion of order %d for couplings\n"
1007 "between constraints inside triangles\n",
1008 li
->ncg_triangle
, li
->nOrder
);
1015 /* Sets up the work division over the threads */
1016 static void lincs_thread_setup(struct gmx_lincsdata
*li
, int natoms
)
1018 lincs_thread_t
*li_m
;
1023 if (natoms
> li
->atf_nalloc
)
1025 li
->atf_nalloc
= over_alloc_large(natoms
);
1026 srenew(li
->atf
, li
->atf_nalloc
);
1030 /* Clear the atom flags */
1031 for (a
= 0; a
< natoms
; a
++)
1036 for (th
= 0; th
< li
->nth
; th
++)
1038 lincs_thread_t
*li_th
;
1041 li_th
= &li
->th
[th
];
1043 /* The constraints are divided equally over the threads */
1044 li_th
->b0
= (li
->nc
* th
)/li
->nth
;
1045 li_th
->b1
= (li
->nc
*(th
+1))/li
->nth
;
1047 if (th
< sizeof(*atf
)*8)
1049 /* For each atom set a flag for constraints from each */
1050 for (b
= li_th
->b0
; b
< li_th
->b1
; b
++)
1052 atf
[li
->bla
[b
*2] ] |= (1U<<th
);
1053 atf
[li
->bla
[b
*2+1]] |= (1U<<th
);
1058 #pragma omp parallel for num_threads(li->nth) schedule(static)
1059 for (th
= 0; th
< li
->nth
; th
++)
1061 lincs_thread_t
*li_th
;
1065 li_th
= &li
->th
[th
];
1067 if (li_th
->b1
- li_th
->b0
> li_th
->ind_nalloc
)
1069 li_th
->ind_nalloc
= over_alloc_large(li_th
->b1
-li_th
->b0
);
1070 srenew(li_th
->ind
, li_th
->ind_nalloc
);
1071 srenew(li_th
->ind_r
, li_th
->ind_nalloc
);
1074 if (th
< sizeof(*atf
)*8)
1076 mask
= (1U<<th
) - 1U;
1080 for (b
= li_th
->b0
; b
< li_th
->b1
; b
++)
1082 /* We let the constraint with the lowest thread index
1083 * operate on atoms with constraints from multiple threads.
1085 if (((atf
[li
->bla
[b
*2]] & mask
) == 0) &&
1086 ((atf
[li
->bla
[b
*2+1]] & mask
) == 0))
1088 /* Add the constraint to the local atom update index */
1089 li_th
->ind
[li_th
->nind
++] = b
;
1093 /* Add the constraint to the rest block */
1094 li_th
->ind_r
[li_th
->nind_r
++] = b
;
1100 /* We are out of bits, assign all constraints to rest */
1101 for (b
= li_th
->b0
; b
< li_th
->b1
; b
++)
1103 li_th
->ind_r
[li_th
->nind_r
++] = b
;
1108 /* We need to copy all constraints which have not be assigned
1109 * to a thread to a separate list which will be handled by one thread.
1111 li_m
= &li
->th
[li
->nth
];
1114 for (th
= 0; th
< li
->nth
; th
++)
1116 lincs_thread_t
*li_th
;
1119 li_th
= &li
->th
[th
];
1121 if (li_m
->nind
+ li_th
->nind_r
> li_m
->ind_nalloc
)
1123 li_m
->ind_nalloc
= over_alloc_large(li_m
->nind
+li_th
->nind_r
);
1124 srenew(li_m
->ind
, li_m
->ind_nalloc
);
1127 for (b
= 0; b
< li_th
->nind_r
; b
++)
1129 li_m
->ind
[li_m
->nind
++] = li_th
->ind_r
[b
];
1134 fprintf(debug
, "LINCS thread %d: %d constraints\n",
1141 fprintf(debug
, "LINCS thread r: %d constraints\n",
1147 void set_lincs(t_idef
*idef
, t_mdatoms
*md
,
1148 gmx_bool bDynamics
, t_commrec
*cr
,
1149 struct gmx_lincsdata
*li
)
1151 int start
, natoms
, nflexcon
;
1154 int i
, k
, ncc_alloc
, ni
, con
, nconnect
, concon
;
1156 real lenA
= 0, lenB
;
1161 /* Zero the thread index ranges.
1162 * Otherwise without local constraints we could return with old ranges.
1164 for (i
= 0; i
< li
->nth
; i
++)
1172 li
->th
[li
->nth
].nind
= 0;
1175 /* This is the local topology, so there are only F_CONSTR constraints */
1176 if (idef
->il
[F_CONSTR
].nr
== 0)
1178 /* There are no constraints,
1179 * we do not need to fill any data structures.
1186 fprintf(debug
, "Building the LINCS connectivity\n");
1189 if (DOMAINDECOMP(cr
))
1191 if (cr
->dd
->constraints
)
1193 dd_get_constraint_range(cr
->dd
, &start
, &natoms
);
1197 natoms
= cr
->dd
->nat_home
;
1204 natoms
= md
->homenr
;
1206 at2con
= make_at2con(start
, natoms
, idef
->il
, idef
->iparams
, bDynamics
,
1210 if (idef
->il
[F_CONSTR
].nr
/3 > li
->nc_alloc
|| li
->nc_alloc
== 0)
1212 li
->nc_alloc
= over_alloc_dd(idef
->il
[F_CONSTR
].nr
/3);
1213 srenew(li
->bllen0
, li
->nc_alloc
);
1214 srenew(li
->ddist
, li
->nc_alloc
);
1215 srenew(li
->bla
, 2*li
->nc_alloc
);
1216 srenew(li
->blc
, li
->nc_alloc
);
1217 srenew(li
->blc1
, li
->nc_alloc
);
1218 srenew(li
->blnr
, li
->nc_alloc
+1);
1219 srenew(li
->bllen
, li
->nc_alloc
);
1220 srenew(li
->tmpv
, li
->nc_alloc
);
1221 srenew(li
->tmp1
, li
->nc_alloc
);
1222 srenew(li
->tmp2
, li
->nc_alloc
);
1223 srenew(li
->tmp3
, li
->nc_alloc
);
1224 srenew(li
->tmp4
, li
->nc_alloc
);
1225 srenew(li
->mlambda
, li
->nc_alloc
);
1226 if (li
->ncg_triangle
> 0)
1228 /* This is allocating too much, but it is difficult to improve */
1229 srenew(li
->triangle
, li
->nc_alloc
);
1230 srenew(li
->tri_bits
, li
->nc_alloc
);
1234 iatom
= idef
->il
[F_CONSTR
].iatoms
;
1236 ncc_alloc
= li
->ncc_alloc
;
1239 ni
= idef
->il
[F_CONSTR
].nr
/3;
1243 li
->blnr
[con
] = nconnect
;
1244 for (i
= 0; i
< ni
; i
++)
1250 lenA
= idef
->iparams
[type
].constr
.dA
;
1251 lenB
= idef
->iparams
[type
].constr
.dB
;
1252 /* Skip the flexible constraints when not doing dynamics */
1253 if (bDynamics
|| lenA
!= 0 || lenB
!= 0)
1255 li
->bllen0
[con
] = lenA
;
1256 li
->ddist
[con
] = lenB
- lenA
;
1257 /* Set the length to the topology A length */
1258 li
->bllen
[con
] = li
->bllen0
[con
];
1259 li
->bla
[2*con
] = a1
;
1260 li
->bla
[2*con
+1] = a2
;
1261 /* Construct the constraint connection matrix blbnb */
1262 for (k
= at2con
.index
[a1
-start
]; k
< at2con
.index
[a1
-start
+1]; k
++)
1264 concon
= at2con
.a
[k
];
1267 if (nconnect
>= ncc_alloc
)
1269 ncc_alloc
= over_alloc_small(nconnect
+1);
1270 srenew(li
->blbnb
, ncc_alloc
);
1272 li
->blbnb
[nconnect
++] = concon
;
1275 for (k
= at2con
.index
[a2
-start
]; k
< at2con
.index
[a2
-start
+1]; k
++)
1277 concon
= at2con
.a
[k
];
1280 if (nconnect
+1 > ncc_alloc
)
1282 ncc_alloc
= over_alloc_small(nconnect
+1);
1283 srenew(li
->blbnb
, ncc_alloc
);
1285 li
->blbnb
[nconnect
++] = concon
;
1288 li
->blnr
[con
+1] = nconnect
;
1292 /* Order the blbnb matrix to optimize memory access */
1293 qsort(&(li
->blbnb
[li
->blnr
[con
]]), li
->blnr
[con
+1]-li
->blnr
[con
],
1294 sizeof(li
->blbnb
[0]), int_comp
);
1296 /* Increase the constraint count */
1301 done_blocka(&at2con
);
1303 /* This is the real number of constraints,
1304 * without dynamics the flexible constraints are not present.
1308 li
->ncc
= li
->blnr
[con
];
1311 /* Since the matrix is static, we can free some memory */
1312 ncc_alloc
= li
->ncc
;
1313 srenew(li
->blbnb
, ncc_alloc
);
1316 if (ncc_alloc
> li
->ncc_alloc
)
1318 li
->ncc_alloc
= ncc_alloc
;
1319 srenew(li
->blmf
, li
->ncc_alloc
);
1320 srenew(li
->blmf1
, li
->ncc_alloc
);
1321 srenew(li
->tmpncc
, li
->ncc_alloc
);
1326 fprintf(debug
, "Number of constraints is %d, couplings %d\n",
1333 li
->th
[0].b1
= li
->nc
;
1337 lincs_thread_setup(li
, md
->nr
);
1340 set_lincs_matrix(li
, md
->invmass
, md
->lambda
);
1343 static void lincs_warning(FILE *fplog
,
1344 gmx_domdec_t
*dd
, rvec
*x
, rvec
*xprime
, t_pbc
*pbc
,
1345 int ncons
, int *bla
, real
*bllen
, real wangle
,
1346 int maxwarn
, int *warncount
)
1350 real wfac
, d0
, d1
, cosine
;
1353 wfac
= cos(DEG2RAD
*wangle
);
1355 sprintf(buf
, "bonds that rotated more than %g degrees:\n"
1356 " atom 1 atom 2 angle previous, current, constraint length\n",
1358 fprintf(stderr
, "%s", buf
);
1361 fprintf(fplog
, "%s", buf
);
1364 for (b
= 0; b
< ncons
; b
++)
1370 pbc_dx_aiuc(pbc
, x
[i
], x
[j
], v0
);
1371 pbc_dx_aiuc(pbc
, xprime
[i
], xprime
[j
], v1
);
1375 rvec_sub(x
[i
], x
[j
], v0
);
1376 rvec_sub(xprime
[i
], xprime
[j
], v1
);
1380 cosine
= iprod(v0
, v1
)/(d0
*d1
);
1383 sprintf(buf
, " %6d %6d %5.1f %8.4f %8.4f %8.4f\n",
1384 ddglatnr(dd
, i
), ddglatnr(dd
, j
),
1385 RAD2DEG
*acos(cosine
), d0
, d1
, bllen
[b
]);
1386 fprintf(stderr
, "%s", buf
);
1389 fprintf(fplog
, "%s", buf
);
1391 if (!gmx_isfinite(d1
))
1393 gmx_fatal(FARGS
, "Bond length not finite.");
1399 if (*warncount
> maxwarn
)
1401 too_many_constraint_warnings(econtLINCS
, *warncount
);
1405 static void cconerr(gmx_domdec_t
*dd
,
1406 int ncons
, int *bla
, real
*bllen
, rvec
*x
, t_pbc
*pbc
,
1407 real
*ncons_loc
, real
*ssd
, real
*max
, int *imax
)
1409 real len
, d
, ma
, ssd2
, r2
;
1410 int *nlocat
, count
, b
, im
;
1413 if (dd
&& dd
->constraints
)
1415 nlocat
= dd_constraints_nlocalatoms(dd
);
1426 for (b
= 0; b
< ncons
; b
++)
1430 pbc_dx_aiuc(pbc
, x
[bla
[2*b
]], x
[bla
[2*b
+1]], dx
);
1434 rvec_sub(x
[bla
[2*b
]], x
[bla
[2*b
+1]], dx
);
1437 len
= r2
*gmx_invsqrt(r2
);
1438 d
= fabs(len
/bllen
[b
]-1);
1439 if (d
> ma
&& (nlocat
== NULL
|| nlocat
[b
]))
1451 ssd2
+= nlocat
[b
]*d
*d
;
1456 *ncons_loc
= (nlocat
? 0.5 : 1)*count
;
1457 *ssd
= (nlocat
? 0.5 : 1)*ssd2
;
1462 gmx_bool
constrain_lincs(FILE *fplog
, gmx_bool bLog
, gmx_bool bEner
,
1465 struct gmx_lincsdata
*lincsd
, t_mdatoms
*md
,
1467 rvec
*x
, rvec
*xprime
, rvec
*min_proj
,
1468 matrix box
, t_pbc
*pbc
,
1469 real lambda
, real
*dvdlambda
,
1470 real invdt
, rvec
*v
,
1471 gmx_bool bCalcVir
, tensor vir_r_m_dr
,
1474 int maxwarn
, int *warncount
)
1476 char buf
[STRLEN
], buf2
[22], buf3
[STRLEN
];
1477 int i
, warn
, p_imax
, error
;
1478 real ncons_loc
, p_ssd
, p_max
= 0;
1484 if (lincsd
->nc
== 0 && cr
->dd
== NULL
)
1488 lincsd
->rmsd_data
[0] = 0;
1489 if (ir
->eI
== eiSD2
&& v
== NULL
)
1497 lincsd
->rmsd_data
[i
] = 0;
1503 if (econq
== econqCoord
)
1505 if (ir
->efep
!= efepNO
)
1507 if (md
->nMassPerturbed
&& lincsd
->matlam
!= md
->lambda
)
1509 set_lincs_matrix(lincsd
, md
->invmass
, md
->lambda
);
1512 for (i
= 0; i
< lincsd
->nc
; i
++)
1514 lincsd
->bllen
[i
] = lincsd
->bllen0
[i
] + lambda
*lincsd
->ddist
[i
];
1518 if (lincsd
->ncg_flex
)
1520 /* Set the flexible constraint lengths to the old lengths */
1523 for (i
= 0; i
< lincsd
->nc
; i
++)
1525 if (lincsd
->bllen
[i
] == 0)
1527 pbc_dx_aiuc(pbc
, x
[lincsd
->bla
[2*i
]], x
[lincsd
->bla
[2*i
+1]], dx
);
1528 lincsd
->bllen
[i
] = norm(dx
);
1534 for (i
= 0; i
< lincsd
->nc
; i
++)
1536 if (lincsd
->bllen
[i
] == 0)
1539 sqrt(distance2(x
[lincsd
->bla
[2*i
]],
1540 x
[lincsd
->bla
[2*i
+1]]));
1548 cconerr(cr
->dd
, lincsd
->nc
, lincsd
->bla
, lincsd
->bllen
, xprime
, pbc
,
1549 &ncons_loc
, &p_ssd
, &p_max
, &p_imax
);
1552 /* This warn var can be updated by multiple threads
1553 * at the same time. But as we only need to detect
1554 * if a warning occured or not, this is not an issue.
1558 /* The OpenMP parallel region of constrain_lincs for coords */
1559 #pragma omp parallel num_threads(lincsd->nth)
1561 int th
= gmx_omp_get_thread_num();
1563 clear_mat(lincsd
->th
[th
].vir_r_m_dr
);
1565 do_lincs(x
, xprime
, box
, pbc
, lincsd
, th
,
1567 bCalcVir
|| (ir
->efep
!= efepNO
),
1568 ir
->LincsWarnAngle
, &warn
,
1570 th
== 0 ? vir_r_m_dr
: lincsd
->th
[th
].vir_r_m_dr
);
1573 if (ir
->efep
!= efepNO
)
1575 real dt_2
, dvdl
= 0;
1577 dt_2
= 1.0/(ir
->delta_t
*ir
->delta_t
);
1578 for (i
= 0; (i
< lincsd
->nc
); i
++)
1580 dvdl
-= lincsd
->mlambda
[i
]*dt_2
*lincsd
->ddist
[i
];
1585 if (bLog
&& fplog
&& lincsd
->nc
> 0)
1587 fprintf(fplog
, " Rel. Constraint Deviation: RMS MAX between atoms\n");
1588 fprintf(fplog
, " Before LINCS %.6f %.6f %6d %6d\n",
1589 sqrt(p_ssd
/ncons_loc
), p_max
,
1590 ddglatnr(cr
->dd
, lincsd
->bla
[2*p_imax
]),
1591 ddglatnr(cr
->dd
, lincsd
->bla
[2*p_imax
+1]));
1595 cconerr(cr
->dd
, lincsd
->nc
, lincsd
->bla
, lincsd
->bllen
, xprime
, pbc
,
1596 &ncons_loc
, &p_ssd
, &p_max
, &p_imax
);
1597 /* Check if we are doing the second part of SD */
1598 if (ir
->eI
== eiSD2
&& v
== NULL
)
1606 lincsd
->rmsd_data
[0] = ncons_loc
;
1607 lincsd
->rmsd_data
[i
] = p_ssd
;
1611 lincsd
->rmsd_data
[0] = 0;
1612 lincsd
->rmsd_data
[1] = 0;
1613 lincsd
->rmsd_data
[2] = 0;
1615 if (bLog
&& fplog
&& lincsd
->nc
> 0)
1618 " After LINCS %.6f %.6f %6d %6d\n\n",
1619 sqrt(p_ssd
/ncons_loc
), p_max
,
1620 ddglatnr(cr
->dd
, lincsd
->bla
[2*p_imax
]),
1621 ddglatnr(cr
->dd
, lincsd
->bla
[2*p_imax
+1]));
1628 cconerr(cr
->dd
, lincsd
->nc
, lincsd
->bla
, lincsd
->bllen
, xprime
, pbc
,
1629 &ncons_loc
, &p_ssd
, &p_max
, &p_imax
);
1632 sprintf(buf3
, " in simulation %d", cr
->ms
->sim
);
1638 sprintf(buf
, "\nStep %s, time %g (ps) LINCS WARNING%s\n"
1639 "relative constraint deviation after LINCS:\n"
1640 "rms %.6f, max %.6f (between atoms %d and %d)\n",
1641 gmx_step_str(step
, buf2
), ir
->init_t
+step
*ir
->delta_t
,
1643 sqrt(p_ssd
/ncons_loc
), p_max
,
1644 ddglatnr(cr
->dd
, lincsd
->bla
[2*p_imax
]),
1645 ddglatnr(cr
->dd
, lincsd
->bla
[2*p_imax
+1]));
1648 fprintf(fplog
, "%s", buf
);
1650 fprintf(stderr
, "%s", buf
);
1651 lincs_warning(fplog
, cr
->dd
, x
, xprime
, pbc
,
1652 lincsd
->nc
, lincsd
->bla
, lincsd
->bllen
,
1653 ir
->LincsWarnAngle
, maxwarn
, warncount
);
1655 bOK
= (p_max
< 0.5);
1658 if (lincsd
->ncg_flex
)
1660 for (i
= 0; (i
< lincsd
->nc
); i
++)
1662 if (lincsd
->bllen0
[i
] == 0 && lincsd
->ddist
[i
] == 0)
1664 lincsd
->bllen
[i
] = 0;
1671 /* The OpenMP parallel region of constrain_lincs for derivatives */
1672 #pragma omp parallel num_threads(lincsd->nth)
1674 int th
= gmx_omp_get_thread_num();
1676 do_lincsp(x
, xprime
, min_proj
, pbc
, lincsd
, th
,
1677 md
->invmass
, econq
, ir
->efep
!= efepNO
? dvdlambda
: NULL
,
1678 bCalcVir
, th
== 0 ? vir_r_m_dr
: lincsd
->th
[th
].vir_r_m_dr
);
1682 if (bCalcVir
&& lincsd
->nth
> 1)
1684 for (i
= 1; i
< lincsd
->nth
; i
++)
1686 m_add(vir_r_m_dr
, lincsd
->th
[i
].vir_r_m_dr
, vir_r_m_dr
);
1690 /* count assuming nit=1 */
1691 inc_nrnb(nrnb
, eNR_LINCS
, lincsd
->nc
);
1692 inc_nrnb(nrnb
, eNR_LINCSMAT
, (2+lincsd
->nOrder
)*lincsd
->ncc
);
1693 if (lincsd
->ntriangle
> 0)
1695 inc_nrnb(nrnb
, eNR_LINCSMAT
, lincsd
->nOrder
*lincsd
->ncc_triangle
);
1699 inc_nrnb(nrnb
, eNR_CONSTR_V
, lincsd
->nc
*2);
1703 inc_nrnb(nrnb
, eNR_CONSTR_VIR
, lincsd
->nc
);