Bug Summary

File:gromacs/mdlib/clincs.c
Location:line 1246, column 9
Description:Value stored to 'bLocal' is never read

Annotated Source Code

1/*
2 * This file is part of the GROMACS molecular simulation package.
3 *
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.
10 *
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.
15 *
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.
20 *
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.
25 *
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.
33 *
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.
36 */
37/* This file is completely threadsafe - keep it that way! */
38#ifdef HAVE_CONFIG_H1
39#include <config.h>
40#endif
41
42#include <math.h>
43#include <stdlib.h>
44
45#include "types/commrec.h"
46#include "constr.h"
47#include "copyrite.h"
48#include "physics.h"
49#include "gromacs/math/vec.h"
50#include "pbc.h"
51#include "mdrun.h"
52#include "nrnb.h"
53#include "domdec.h"
54#include "mtop_util.h"
55#include "gmx_omp_nthreads.h"
56
57#include "gromacs/fileio/gmxfio.h"
58#include "gromacs/utility/fatalerror.h"
59#include "gromacs/utility/gmxomp.h"
60#include "gromacs/utility/smalloc.h"
61
62typedef struct {
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 */
71} lincs_thread_t;
72
73typedef 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 */
104 rvec *tmpv;
105 real *tmpncc;
106 real *tmp1;
107 real *tmp2;
108 real *tmp3;
109 real *tmp4;
110 real *mlambda; /* the Lagrange multipliers * -1 */
111 /* storage for the constraint RMS relative deviation output */
112 real rmsd_data[3];
113} t_gmx_lincsdata;
114
115real *lincs_rmsd_data(struct gmx_lincsdata *lincsd)
116{
117 return lincsd->rmsd_data;
118}
119
120real lincs_rmsd(struct gmx_lincsdata *lincsd, gmx_bool bSD2)
121{
122 if (lincsd->rmsd_data[0] > 0)
123 {
124 return sqrt(lincsd->rmsd_data[bSD2 ? 2 : 1]/lincsd->rmsd_data[0]);
125 }
126 else
127 {
128 return 0;
129 }
130}
131
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.
135 */
136static void lincs_matrix_expand(const struct gmx_lincsdata *lincsd,
137 int b0, int b1,
138 const real *blcc,
139 real *rhs1, real *rhs2, real *sol)
140{
141 int nrec, rec, b, j, n, nr0, nr1;
142 real mvb, *swap;
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;
146
147 ntriangle = lincsd->ntriangle;
148 nrec = lincsd->nOrder;
149
150 for (rec = 0; rec < nrec; rec++)
151 {
152#pragma omp barrier
153 for (b = b0; b < b1; b++)
154 {
155 mvb = 0;
156 for (n = blnr[b]; n < blnr[b+1]; n++)
157 {
158 j = blbnb[n];
159 mvb = mvb + blcc[n]*rhs1[j];
160 }
161 rhs2[b] = mvb;
162 sol[b] = sol[b] + mvb;
163 }
164 swap = rhs1;
165 rhs1 = rhs2;
166 rhs2 = swap;
167 } /* nrec*(ncons+2*nrtot) flops */
168
169 if (ntriangle > 0)
170 {
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).
177 */
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.
182 */
183#pragma omp barrier
184 for (b = b0; b < b1; b++)
185 {
186 rhs2[b] = rhs1[b];
187 }
188#pragma omp barrier
189#pragma omp master
190 {
191 for (rec = 0; rec < nrec; rec++)
192 {
193 for (tb = 0; tb < ntriangle; tb++)
194 {
195 b = triangle[tb];
196 bits = tri_bits[tb];
197 mvb = 0;
198 nr0 = blnr[b];
199 nr1 = blnr[b+1];
200 for (n = nr0; n < nr1; n++)
201 {
202 if (bits & (1<<(n-nr0)))
203 {
204 j = blbnb[n];
205 mvb = mvb + blcc[n]*rhs1[j];
206 }
207 }
208 rhs2[b] = mvb;
209 sol[b] = sol[b] + mvb;
210 }
211 swap = rhs1;
212 rhs1 = rhs2;
213 rhs2 = swap;
214 }
215 } /* flops count is missing here */
216
217 /* We need a barrier here as the calling routine will continue
218 * to operate on the thread-local constraints without barrier.
219 */
220#pragma omp barrier
221 }
222}
223
224static void lincs_update_atoms_noind(int ncons, const int *bla,
225 real prefac,
226 const real *fac, rvec *r,
227 const real *invmass,
228 rvec *x)
229{
230 int b, i, j;
231 real mvb, im1, im2, tmp0, tmp1, tmp2;
232
233 if (invmass != NULL((void*)0))
234 {
235 for (b = 0; b < ncons; b++)
236 {
237 i = bla[2*b];
238 j = bla[2*b+1];
239 mvb = prefac*fac[b];
240 im1 = invmass[i];
241 im2 = invmass[j];
242 tmp0 = r[b][0]*mvb;
243 tmp1 = r[b][1]*mvb;
244 tmp2 = r[b][2]*mvb;
245 x[i][0] -= tmp0*im1;
246 x[i][1] -= tmp1*im1;
247 x[i][2] -= tmp2*im1;
248 x[j][0] += tmp0*im2;
249 x[j][1] += tmp1*im2;
250 x[j][2] += tmp2*im2;
251 } /* 16 ncons flops */
252 }
253 else
254 {
255 for (b = 0; b < ncons; b++)
256 {
257 i = bla[2*b];
258 j = bla[2*b+1];
259 mvb = prefac*fac[b];
260 tmp0 = r[b][0]*mvb;
261 tmp1 = r[b][1]*mvb;
262 tmp2 = r[b][2]*mvb;
263 x[i][0] -= tmp0;
264 x[i][1] -= tmp1;
265 x[i][2] -= tmp2;
266 x[j][0] += tmp0;
267 x[j][1] += tmp1;
268 x[j][2] += tmp2;
269 }
270 }
271}
272
273static void lincs_update_atoms_ind(int ncons, const int *ind, const int *bla,
274 real prefac,
275 const real *fac, rvec *r,
276 const real *invmass,
277 rvec *x)
278{
279 int bi, b, i, j;
280 real mvb, im1, im2, tmp0, tmp1, tmp2;
281
282 if (invmass != NULL((void*)0))
283 {
284 for (bi = 0; bi < ncons; bi++)
285 {
286 b = ind[bi];
287 i = bla[2*b];
288 j = bla[2*b+1];
289 mvb = prefac*fac[b];
290 im1 = invmass[i];
291 im2 = invmass[j];
292 tmp0 = r[b][0]*mvb;
293 tmp1 = r[b][1]*mvb;
294 tmp2 = r[b][2]*mvb;
295 x[i][0] -= tmp0*im1;
296 x[i][1] -= tmp1*im1;
297 x[i][2] -= tmp2*im1;
298 x[j][0] += tmp0*im2;
299 x[j][1] += tmp1*im2;
300 x[j][2] += tmp2*im2;
301 } /* 16 ncons flops */
302 }
303 else
304 {
305 for (bi = 0; bi < ncons; bi++)
306 {
307 b = ind[bi];
308 i = bla[2*b];
309 j = bla[2*b+1];
310 mvb = prefac*fac[b];
311 tmp0 = r[b][0]*mvb;
312 tmp1 = r[b][1]*mvb;
313 tmp2 = r[b][2]*mvb;
314 x[i][0] -= tmp0;
315 x[i][1] -= tmp1;
316 x[i][2] -= tmp2;
317 x[j][0] += tmp0;
318 x[j][1] += tmp1;
319 x[j][2] += tmp2;
320 } /* 16 ncons flops */
321 }
322}
323
324static void lincs_update_atoms(struct gmx_lincsdata *li, int th,
325 real prefac,
326 const real *fac, rvec *r,
327 const real *invmass,
328 rvec *x)
329{
330 if (li->nth == 1)
331 {
332 /* Single thread, we simply update for all constraints */
333 lincs_update_atoms_noind(li->nc, li->bla, prefac, fac, r, invmass, x);
334 }
335 else
336 {
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.
340 */
341 lincs_update_atoms_ind(li->th[th].nind, li->th[th].ind,
342 li->bla, prefac, fac, r, invmass, x);
343
344 if (li->th[li->nth].nind > 0)
345 {
346 /* Update the constraints that operate on atoms
347 * in multiple thread atom blocks on the master thread.
348 */
349#pragma omp barrier
350#pragma omp master
351 {
352 lincs_update_atoms_ind(li->th[li->nth].nind,
353 li->th[li->nth].ind,
354 li->bla, prefac, fac, r, invmass, x);
355 }
356 }
357 }
358}
359
360/* LINCS projection, works on derivatives of the coordinates */
361static void do_lincsp(rvec *x, rvec *f, rvec *fp, t_pbc *pbc,
362 struct gmx_lincsdata *lincsd, int th,
363 real *invmass,
364 int econq, real *dvdlambda,
365 gmx_bool bCalcVir, tensor rmdf)
366{
367 int b0, b1, b, i, j, k, n;
368 real tmp0, tmp1, tmp2, im1, im2, mvb, rlen, len, wfac, lam;
369 rvec dx;
370 int *bla, *blnr, *blbnb;
371 rvec *r;
372 real *blc, *blmf, *blcc, *rhs1, *rhs2, *sol;
373
374 b0 = lincsd->th[th].b0;
375 b1 = lincsd->th[th].b1;
376
377 bla = lincsd->bla;
378 r = lincsd->tmpv;
379 blnr = lincsd->blnr;
380 blbnb = lincsd->blbnb;
381 if (econq != econqForce)
382 {
383 /* Use mass-weighted parameters */
384 blc = lincsd->blc;
385 blmf = lincsd->blmf;
386 }
387 else
388 {
389 /* Use non mass-weighted parameters */
390 blc = lincsd->blc1;
391 blmf = lincsd->blmf1;
392 }
393 blcc = lincsd->tmpncc;
394 rhs1 = lincsd->tmp1;
395 rhs2 = lincsd->tmp2;
396 sol = lincsd->tmp3;
397
398 /* Compute normalized i-j vectors */
399 if (pbc)
400 {
401 for (b = b0; b < b1; b++)
402 {
403 pbc_dx_aiuc(pbc, x[bla[2*b]], x[bla[2*b+1]], dx);
404 unitv(dx, r[b]);
405 }
406 }
407 else
408 {
409 for (b = b0; b < b1; b++)
410 {
411 rvec_sub(x[bla[2*b]], x[bla[2*b+1]], dx);
412 unitv(dx, r[b]);
413 } /* 16 ncons flops */
414 }
415
416#pragma omp barrier
417 for (b = b0; b < b1; b++)
418 {
419 tmp0 = r[b][0];
420 tmp1 = r[b][1];
421 tmp2 = r[b][2];
422 i = bla[2*b];
423 j = bla[2*b+1];
424 for (n = blnr[b]; n < blnr[b+1]; n++)
425 {
426 k = blbnb[n];
427 blcc[n] = blmf[n]*(tmp0*r[k][0] + tmp1*r[k][1] + tmp2*r[k][2]);
428 } /* 6 nr flops */
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]));
432 rhs1[b] = mvb;
433 sol[b] = mvb;
434 /* 7 flops */
435 }
436 /* Together: 23*ncons + 6*nrtot flops */
437
438 lincs_matrix_expand(lincsd, b0, b1, blcc, rhs1, rhs2, sol);
439 /* nrec*(ncons+2*nrtot) flops */
440
441 if (econq == econqDeriv_FlexCon)
442 {
443 /* We only want to constraint the flexible constraints,
444 * so we mask out the normal ones by setting sol to 0.
445 */
446 for (b = b0; b < b1; b++)
447 {
448 if (!(lincsd->bllen0[b] == 0 && lincsd->ddist[b] == 0))
449 {
450 sol[b] = 0;
451 }
452 }
453 }
454
455 /* We multiply sol by blc, so we can use lincs_update_atoms for OpenMP */
456 for (b = b0; b < b1; b++)
457 {
458 sol[b] *= blc[b];
459 }
460
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.
463 */
464 lincs_update_atoms(lincsd, th, 1.0, sol, r,
465 (econq != econqForce) ? invmass : NULL((void*)0), fp);
466
467 if (dvdlambda != NULL((void*)0))
468 {
469#pragma omp barrier
470 for (b = b0; b < b1; b++)
471 {
472 *dvdlambda -= sol[b]*lincsd->ddist[b];
473 }
474 /* 10 ncons flops */
475 }
476
477 if (bCalcVir)
478 {
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.
483 */
484 for (b = b0; b < b1; b++)
485 {
486 mvb = lincsd->bllen[b]*sol[b];
487 for (i = 0; i < DIM3; i++)
488 {
489 tmp1 = mvb*r[b][i];
490 for (j = 0; j < DIM3; j++)
491 {
492 rmdf[i][j] += tmp1*r[b][j];
493 }
494 }
495 } /* 23 ncons flops */
496 }
497}
498
499static void do_lincs(rvec *x, rvec *xp, matrix box, t_pbc *pbc,
500 struct gmx_lincsdata *lincsd, int th,
501 real *invmass,
502 t_commrec *cr,
503 gmx_bool bCalcLambda,
504 real wangle, int *warn,
505 real invdt, rvec *v,
506 gmx_bool bCalcVir, tensor vir_r_m_dr)
507{
508 int b0, b1, b, i, j, k, n, iter;
509 real tmp0, tmp1, tmp2, im1, im2, mvb, rlen, len, len2, dlen2, wfac;
510 rvec dx;
511 int *bla, *blnr, *blbnb;
512 rvec *r;
513 real *blc, *blmf, *bllen, *blcc, *rhs1, *rhs2, *sol, *blc_sol, *mlambda;
514 int *nlocat;
515
516 b0 = lincsd->th[th].b0;
517 b1 = lincsd->th[th].b1;
518
519 bla = lincsd->bla;
520 r = lincsd->tmpv;
521 blnr = lincsd->blnr;
522 blbnb = lincsd->blbnb;
523 blc = lincsd->blc;
524 blmf = lincsd->blmf;
525 bllen = lincsd->bllen;
526 blcc = lincsd->tmpncc;
527 rhs1 = lincsd->tmp1;
528 rhs2 = lincsd->tmp2;
529 sol = lincsd->tmp3;
530 blc_sol = lincsd->tmp4;
531 mlambda = lincsd->mlambda;
532
533 if (DOMAINDECOMP(cr)(((cr)->dd != ((void*)0)) && ((cr)->nnodes >
1))
&& cr->dd->constraints)
534 {
535 nlocat = dd_constraints_nlocalatoms(cr->dd);
536 }
537 else
538 {
539 nlocat = NULL((void*)0);
540 }
541
542 if (pbc)
543 {
544 /* Compute normalized i-j vectors */
545 for (b = b0; b < b1; b++)
546 {
547 pbc_dx_aiuc(pbc, x[bla[2*b]], x[bla[2*b+1]], dx);
548 unitv(dx, r[b]);
549 }
550#pragma omp barrier
551 for (b = b0; b < b1; b++)
552 {
553 for (n = blnr[b]; n < blnr[b+1]; n++)
554 {
555 blcc[n] = blmf[n]*iprod(r[b], r[blbnb[n]]);
556 }
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]);
559 rhs1[b] = mvb;
560 sol[b] = mvb;
561 }
562 }
563 else
564 {
565 /* Compute normalized i-j vectors */
566 for (b = b0; b < b1; b++)
567 {
568 i = bla[2*b];
569 j = bla[2*b+1];
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)gmx_software_invsqrt(tmp0*tmp0+tmp1*tmp1+tmp2*tmp2);
574 r[b][0] = rlen*tmp0;
575 r[b][1] = rlen*tmp1;
576 r[b][2] = rlen*tmp2;
577 } /* 16 ncons flops */
578
579#pragma omp barrier
580 for (b = b0; b < b1; b++)
581 {
582 tmp0 = r[b][0];
583 tmp1 = r[b][1];
584 tmp2 = r[b][2];
585 len = bllen[b];
586 i = bla[2*b];
587 j = bla[2*b+1];
588 for (n = blnr[b]; n < blnr[b+1]; n++)
589 {
590 k = blbnb[n];
591 blcc[n] = blmf[n]*(tmp0*r[k][0] + tmp1*r[k][1] + tmp2*r[k][2]);
592 } /* 6 nr flops */
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);
596 rhs1[b] = mvb;
597 sol[b] = mvb;
598 /* 10 flops */
599 }
600 /* Together: 26*ncons + 6*nrtot flops */
601 }
602
603 lincs_matrix_expand(lincsd, b0, b1, blcc, rhs1, rhs2, sol);
604 /* nrec*(ncons+2*nrtot) flops */
605
606 for (b = b0; b < b1; b++)
607 {
608 mlambda[b] = blc[b]*sol[b];
609 }
610
611 /* Update the coordinates */
612 lincs_update_atoms(lincsd, th, 1.0, mlambda, r, invmass, xp);
613
614 /*
615 ******** Correction for centripetal effects ********
616 */
617
618 wfac = cos(DEG2RAD(3.14159265358979323846/180.0)*wangle);
619 wfac = wfac*wfac;
620
621 for (iter = 0; iter < lincsd->nIter; iter++)
622 {
623 if ((lincsd->bCommIter && DOMAINDECOMP(cr)(((cr)->dd != ((void*)0)) && ((cr)->nnodes >
1))
&& cr->dd->constraints))
624 {
625#pragma omp barrier
626#pragma omp master
627 {
628 /* Communicate the corrected non-local coordinates */
629 if (DOMAINDECOMP(cr)(((cr)->dd != ((void*)0)) && ((cr)->nnodes >
1))
)
630 {
631 dd_move_x_constraints(cr->dd, box, xp, NULL((void*)0), FALSE0);
632 }
633 }
634 }
635
636#pragma omp barrier
637 for (b = b0; b < b1; b++)
638 {
639 len = bllen[b];
640 if (pbc)
641 {
642 pbc_dx_aiuc(pbc, xp[bla[2*b]], xp[bla[2*b+1]], dx);
643 }
644 else
645 {
646 rvec_sub(xp[bla[2*b]], xp[bla[2*b+1]], dx);
647 }
648 len2 = len*len;
649 dlen2 = 2*len2 - norm2(dx);
650 if (dlen2 < wfac*len2 && (nlocat == NULL((void*)0) || nlocat[b]))
651 {
652 *warn = b;
653 }
654 if (dlen2 > 0)
655 {
656 mvb = blc[b]*(len - dlen2*gmx_invsqrt(dlen2)gmx_software_invsqrt(dlen2));
657 }
658 else
659 {
660 mvb = blc[b]*len;
661 }
662 rhs1[b] = mvb;
663 sol[b] = mvb;
664 } /* 20*ncons flops */
665
666 lincs_matrix_expand(lincsd, b0, b1, blcc, rhs1, rhs2, sol);
667 /* nrec*(ncons+2*nrtot) flops */
668
669 for (b = b0; b < b1; b++)
670 {
671 mvb = blc[b]*sol[b];
672 blc_sol[b] = mvb;
673 mlambda[b] += mvb;
674 }
675
676 /* Update the coordinates */
677 lincs_update_atoms(lincsd, th, 1.0, blc_sol, r, invmass, xp);
678 }
679 /* nit*ncons*(37+9*nrec) flops */
680
681 if (v != NULL((void*)0))
682 {
683 /* Update the velocities */
684 lincs_update_atoms(lincsd, th, invdt, mlambda, r, invmass, v);
685 /* 16 ncons flops */
686 }
687
688 if (nlocat != NULL((void*)0) && bCalcLambda)
689 {
690 /* In lincs_update_atoms thread might cross-read mlambda */
691#pragma omp barrier
692
693 /* Only account for local atoms */
694 for (b = b0; b < b1; b++)
695 {
696 mlambda[b] *= 0.5*nlocat[b];
697 }
698 }
699
700 if (bCalcVir)
701 {
702 /* Constraint virial */
703 for (b = b0; b < b1; b++)
704 {
705 tmp0 = -bllen[b]*mlambda[b];
706 for (i = 0; i < DIM3; i++)
707 {
708 tmp1 = tmp0*r[b][i];
709 for (j = 0; j < DIM3; j++)
710 {
711 vir_r_m_dr[i][j] -= tmp1*r[b][j];
712 }
713 }
714 } /* 22 ncons flops */
715 }
716
717 /* Total:
718 * 26*ncons + 6*nrtot + nrec*(ncons+2*nrtot)
719 * + nit * (20*ncons + nrec*(ncons+2*nrtot) + 17 ncons)
720 *
721 * (26+nrec)*ncons + (6+2*nrec)*nrtot
722 * + nit * ((37+nrec)*ncons + 2*nrec*nrtot)
723 * if nit=1
724 * (63+nrec)*ncons + (6+4*nrec)*nrtot
725 */
726}
727
728void set_lincs_matrix(struct gmx_lincsdata *li, real *invmass, real lambda)
729{
730 int i, a1, a2, n, k, sign, center;
731 int end, nk, kk;
732 const real invsqrt2 = 0.7071067811865475244;
733
734 for (i = 0; (i < li->nc); i++)
735 {
736 a1 = li->bla[2*i];
737 a2 = li->bla[2*i+1];
738 li->blc[i] = gmx_invsqrt(invmass[a1] + invmass[a2])gmx_software_invsqrt(invmass[a1] + invmass[a2]);
739 li->blc1[i] = invsqrt2;
740 }
741
742 /* Construct the coupling coefficient matrix blmf */
743 li->ntriangle = 0;
744 li->ncc_triangle = 0;
745 for (i = 0; (i < li->nc); i++)
746 {
747 a1 = li->bla[2*i];
748 a2 = li->bla[2*i+1];
749 for (n = li->blnr[i]; (n < li->blnr[i+1]); n++)
750 {
751 k = li->blbnb[n];
752 if (a1 == li->bla[2*k] || a2 == li->bla[2*k+1])
753 {
754 sign = -1;
755 }
756 else
757 {
758 sign = 1;
759 }
760 if (a1 == li->bla[2*k] || a1 == li->bla[2*k+1])
761 {
762 center = a1;
763 end = a2;
764 }
765 else
766 {
767 center = a2;
768 end = a1;
769 }
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)
773 {
774 /* Look for constraint triangles */
775 for (nk = li->blnr[k]; (nk < li->blnr[k+1]); nk++)
776 {
777 kk = li->blbnb[nk];
778 if (kk != i && kk != k &&
779 (li->bla[2*kk] == end || li->bla[2*kk+1] == end))
780 {
781 if (li->ntriangle == 0 ||
782 li->triangle[li->ntriangle-1] < i)
783 {
784 /* Add this constraint to the triangle list */
785 li->triangle[li->ntriangle] = i;
786 li->tri_bits[li->ntriangle] = 0;
787 li->ntriangle++;
788 if (li->blnr[i+1] - li->blnr[i] > sizeof(li->tri_bits[0])*8 - 1)
789 {
790 gmx_fatal(FARGS0, "/home/alexxy/Develop/gromacs/src/gromacs/mdlib/clincs.c",
790
, "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);
793 }
794 }
795 li->tri_bits[li->ntriangle-1] |= (1<<(n-li->blnr[i]));
796 li->ncc_triangle++;
797 }
798 }
799 }
800 }
801 }
802
803 if (debug)
804 {
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);
809 }
810
811 /* Set matlam,
812 * so we know with which lambda value the masses have been set.
813 */
814 li->matlam = lambda;
815}
816
817static int count_triangle_constraints(t_ilist *ilist, t_blocka *at2con)
818{
819 int ncon1, ncon_tot;
820 int c0, a00, a01, n1, c1, a10, a11, ac1, n2, c2, a20, a21;
821 int ncon_triangle;
822 gmx_bool bTriangle;
823 t_iatom *ia1, *ia2, *iap;
824
825 ncon1 = ilist[F_CONSTR].nr/3;
826 ncon_tot = ncon1 + ilist[F_CONSTRNC].nr/3;
827
828 ia1 = ilist[F_CONSTR].iatoms;
829 ia2 = ilist[F_CONSTRNC].iatoms;
830
831 ncon_triangle = 0;
832 for (c0 = 0; c0 < ncon_tot; c0++)
833 {
834 bTriangle = FALSE0;
835 iap = constr_iatomptr(ncon1, ia1, ia2, c0)((c0) < (ncon1) ? (ia1)+(c0)*3 : (ia2)+(c0-ncon1)*3);
836 a00 = iap[1];
837 a01 = iap[2];
838 for (n1 = at2con->index[a01]; n1 < at2con->index[a01+1]; n1++)
839 {
840 c1 = at2con->a[n1];
841 if (c1 != c0)
842 {
843 iap = constr_iatomptr(ncon1, ia1, ia2, c1)((c1) < (ncon1) ? (ia1)+(c1)*3 : (ia2)+(c1-ncon1)*3);
844 a10 = iap[1];
845 a11 = iap[2];
846 if (a10 == a01)
847 {
848 ac1 = a11;
849 }
850 else
851 {
852 ac1 = a10;
853 }
854 for (n2 = at2con->index[ac1]; n2 < at2con->index[ac1+1]; n2++)
855 {
856 c2 = at2con->a[n2];
857 if (c2 != c0 && c2 != c1)
858 {
859 iap = constr_iatomptr(ncon1, ia1, ia2, c2)((c2) < (ncon1) ? (ia1)+(c2)*3 : (ia2)+(c2-ncon1)*3);
860 a20 = iap[1];
861 a21 = iap[2];
862 if (a20 == a00 || a21 == a00)
863 {
864 bTriangle = TRUE1;
865 }
866 }
867 }
868 }
869 }
870 if (bTriangle)
871 {
872 ncon_triangle++;
873 }
874 }
875
876 return ncon_triangle;
877}
878
879static gmx_bool more_than_two_sequential_constraints(const t_ilist *ilist,
880 const t_blocka *at2con)
881{
882 t_iatom *ia1, *ia2, *iap;
883 int ncon1, ncon_tot, c;
884 int a1, a2;
885 gmx_bool bMoreThanTwoSequentialConstraints;
886
887 ncon1 = ilist[F_CONSTR].nr/3;
888 ncon_tot = ncon1 + ilist[F_CONSTRNC].nr/3;
889
890 ia1 = ilist[F_CONSTR].iatoms;
891 ia2 = ilist[F_CONSTRNC].iatoms;
892
893 bMoreThanTwoSequentialConstraints = FALSE0;
894 for (c = 0; c < ncon_tot && !bMoreThanTwoSequentialConstraints; c++)
895 {
896 iap = constr_iatomptr(ncon1, ia1, ia2, c)((c) < (ncon1) ? (ia1)+(c)*3 : (ia2)+(c-ncon1)*3);
897 a1 = iap[1];
898 a2 = iap[2];
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)
902 {
903 bMoreThanTwoSequentialConstraints = TRUE1;
904 }
905 }
906
907 return bMoreThanTwoSequentialConstraints;
908}
909
910static int int_comp(const void *a, const void *b)
911{
912 return (*(int *)a) - (*(int *)b);
913}
914
915gmx_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)
918{
919 struct gmx_lincsdata *li;
920 int mb;
921 gmx_moltype_t *molt;
922
923 if (fplog)
924 {
925 fprintf(fplog, "\nInitializing%s LINear Constraint Solver\n",
926 bPLINCS ? " Parallel" : "");
927 }
928
929 snew(li, 1)(li) = save_calloc("li", "/home/alexxy/Develop/gromacs/src/gromacs/mdlib/clincs.c"
, 929, (1), sizeof(*(li)))
;
930
931 li->ncg =
932 gmx_mtop_ftype_count(mtop, F_CONSTR) +
933 gmx_mtop_ftype_count(mtop, F_CONSTRNC);
934 li->ncg_flex = nflexcon_global;
935
936 li->nIter = nIter;
937 li->nOrder = nProjOrder;
938
939 li->ncg_triangle = 0;
940 li->bCommIter = FALSE0;
941 for (mb = 0; mb < mtop->nmolblock; mb++)
942 {
943 molt = &mtop->moltype[mtop->molblock[mb].type];
944 li->ncg_triangle +=
945 mtop->molblock[mb].nmol*
946 count_triangle_constraints(molt->ilist,
947 &at2con[mtop->molblock[mb].type]);
948 if (bPLINCS && li->bCommIter == FALSE0)
949 {
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.
956 */
957 li->bCommIter = (li->nOrder < 1 || more_than_two_sequential_constraints(molt->ilist, &at2con[mtop->molblock[mb].type]));
958 }
959 }
960 if (debug && bPLINCS)
961 {
962 fprintf(debug, "PLINCS communication before each iteration: %d\n",
963 li->bCommIter);
964 }
965
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().
969 */
970 li->nth = gmx_omp_nthreads_get(emntLINCS);
971 if (li->nth == 1)
972 {
973 snew(li->th, 1)(li->th) = save_calloc("li->th", "/home/alexxy/Develop/gromacs/src/gromacs/mdlib/clincs.c"
, 973, (1), sizeof(*(li->th)))
;
974 }
975 else
976 {
977 /* Allocate an extra elements for "thread-overlap" constraints */
978 snew(li->th, li->nth+1)(li->th) = save_calloc("li->th", "/home/alexxy/Develop/gromacs/src/gromacs/mdlib/clincs.c"
, 978, (li->nth+1), sizeof(*(li->th)))
;
979 }
980 if (debug)
981 {
982 fprintf(debug, "LINCS: using %d threads\n", li->nth);
983 }
984
985 if (bPLINCS || li->ncg_triangle > 0)
986 {
987 please_cite(fplog, "Hess2008a");
988 }
989 else
990 {
991 please_cite(fplog, "Hess97a");
992 }
993
994 if (fplog)
995 {
996 fprintf(fplog, "The number of constraints is %d\n", li->ncg);
997 if (bPLINCS)
998 {
999 fprintf(fplog, "There are inter charge-group constraints,\n"
1000 "will communicate selected coordinates each lincs iteration\n");
1001 }
1002 if (li->ncg_triangle > 0)
1003 {
1004 fprintf(fplog,
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);
1009 }
1010 }
1011
1012 return li;
1013}
1014
1015/* Sets up the work division over the threads */
1016static void lincs_thread_setup(struct gmx_lincsdata *li, int natoms)
1017{
1018 lincs_thread_t *li_m;
1019 int th;
1020 unsigned *atf;
1021 int a;
1022
1023 if (natoms > li->atf_nalloc)
1024 {
1025 li->atf_nalloc = over_alloc_large(natoms)(int)(1.19*(natoms) + 1000);
1026 srenew(li->atf, li->atf_nalloc)(li->atf) = save_realloc("li->atf", "/home/alexxy/Develop/gromacs/src/gromacs/mdlib/clincs.c"
, 1026, (li->atf), (li->atf_nalloc), sizeof(*(li->atf
)))
;
1027 }
1028
1029 atf = li->atf;
1030 /* Clear the atom flags */
1031 for (a = 0; a < natoms; a++)
1032 {
1033 atf[a] = 0;
1034 }
1035
1036 for (th = 0; th < li->nth; th++)
1037 {
1038 lincs_thread_t *li_th;
1039 int b;
1040
1041 li_th = &li->th[th];
1042
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;
1046
1047 if (th < sizeof(*atf)*8)
1048 {
1049 /* For each atom set a flag for constraints from each */
1050 for (b = li_th->b0; b < li_th->b1; b++)
1051 {
1052 atf[li->bla[b*2] ] |= (1U<<th);
1053 atf[li->bla[b*2+1]] |= (1U<<th);
1054 }
1055 }
1056 }
1057
1058#pragma omp parallel for num_threads(li->nth) schedule(static)
1059 for (th = 0; th < li->nth; th++)
1060 {
1061 lincs_thread_t *li_th;
1062 unsigned mask;
1063 int b;
1064
1065 li_th = &li->th[th];
1066
1067 if (li_th->b1 - li_th->b0 > li_th->ind_nalloc)
1068 {
1069 li_th->ind_nalloc = over_alloc_large(li_th->b1-li_th->b0)(int)(1.19*(li_th->b1-li_th->b0) + 1000);
1070 srenew(li_th->ind, li_th->ind_nalloc)(li_th->ind) = save_realloc("li_th->ind", "/home/alexxy/Develop/gromacs/src/gromacs/mdlib/clincs.c"
, 1070, (li_th->ind), (li_th->ind_nalloc), sizeof(*(li_th
->ind)))
;
1071 srenew(li_th->ind_r, li_th->ind_nalloc)(li_th->ind_r) = save_realloc("li_th->ind_r", "/home/alexxy/Develop/gromacs/src/gromacs/mdlib/clincs.c"
, 1071, (li_th->ind_r), (li_th->ind_nalloc), sizeof(*(li_th
->ind_r)))
;
1072 }
1073
1074 if (th < sizeof(*atf)*8)
1075 {
1076 mask = (1U<<th) - 1U;
1077
1078 li_th->nind = 0;
1079 li_th->nind_r = 0;
1080 for (b = li_th->b0; b < li_th->b1; b++)
1081 {
1082 /* We let the constraint with the lowest thread index
1083 * operate on atoms with constraints from multiple threads.
1084 */
1085 if (((atf[li->bla[b*2]] & mask) == 0) &&
1086 ((atf[li->bla[b*2+1]] & mask) == 0))
1087 {
1088 /* Add the constraint to the local atom update index */
1089 li_th->ind[li_th->nind++] = b;
1090 }
1091 else
1092 {
1093 /* Add the constraint to the rest block */
1094 li_th->ind_r[li_th->nind_r++] = b;
1095 }
1096 }
1097 }
1098 else
1099 {
1100 /* We are out of bits, assign all constraints to rest */
1101 for (b = li_th->b0; b < li_th->b1; b++)
1102 {
1103 li_th->ind_r[li_th->nind_r++] = b;
1104 }
1105 }
1106 }
1107
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.
1110 */
1111 li_m = &li->th[li->nth];
1112
1113 li_m->nind = 0;
1114 for (th = 0; th < li->nth; th++)
1115 {
1116 lincs_thread_t *li_th;
1117 int b;
1118
1119 li_th = &li->th[th];
1120
1121 if (li_m->nind + li_th->nind_r > li_m->ind_nalloc)
1122 {
1123 li_m->ind_nalloc = over_alloc_large(li_m->nind+li_th->nind_r)(int)(1.19*(li_m->nind+li_th->nind_r) + 1000);
1124 srenew(li_m->ind, li_m->ind_nalloc)(li_m->ind) = save_realloc("li_m->ind", "/home/alexxy/Develop/gromacs/src/gromacs/mdlib/clincs.c"
, 1124, (li_m->ind), (li_m->ind_nalloc), sizeof(*(li_m->
ind)))
;
1125 }
1126
1127 for (b = 0; b < li_th->nind_r; b++)
1128 {
1129 li_m->ind[li_m->nind++] = li_th->ind_r[b];
1130 }
1131
1132 if (debug)
1133 {
1134 fprintf(debug, "LINCS thread %d: %d constraints\n",
1135 th, li_th->nind);
1136 }
1137 }
1138
1139 if (debug)
1140 {
1141 fprintf(debug, "LINCS thread r: %d constraints\n",
1142 li_m->nind);
1143 }
1144}
1145
1146
1147void set_lincs(t_idef *idef, t_mdatoms *md,
1148 gmx_bool bDynamics, t_commrec *cr,
1149 struct gmx_lincsdata *li)
1150{
1151 int start, natoms, nflexcon;
1152 t_blocka at2con;
1153 t_iatom *iatom;
1154 int i, k, ncc_alloc, ni, con, nconnect, concon;
1155 int type, a1, a2;
1156 real lenA = 0, lenB;
1157 gmx_bool bLocal;
1158
1159 li->nc = 0;
1160 li->ncc = 0;
1161 /* Zero the thread index ranges.
1162 * Otherwise without local constraints we could return with old ranges.
1163 */
1164 for (i = 0; i < li->nth; i++)
1165 {
1166 li->th[i].b0 = 0;
1167 li->th[i].b1 = 0;
1168 li->th[i].nind = 0;
1169 }
1170 if (li->nth > 1)
1171 {
1172 li->th[li->nth].nind = 0;
1173 }
1174
1175 /* This is the local topology, so there are only F_CONSTR constraints */
1176 if (idef->il[F_CONSTR].nr == 0)
1177 {
1178 /* There are no constraints,
1179 * we do not need to fill any data structures.
1180 */
1181 return;
1182 }
1183
1184 if (debug)
1185 {
1186 fprintf(debug, "Building the LINCS connectivity\n");
1187 }
1188
1189 if (DOMAINDECOMP(cr)(((cr)->dd != ((void*)0)) && ((cr)->nnodes >
1))
)
1190 {
1191 if (cr->dd->constraints)
1192 {
1193 dd_get_constraint_range(cr->dd, &start, &natoms);
1194 }
1195 else
1196 {
1197 natoms = cr->dd->nat_home;
1198 }
1199 start = 0;
1200 }
1201 else
1202 {
1203 start = 0;
1204 natoms = md->homenr;
1205 }
1206 at2con = make_at2con(start, natoms, idef->il, idef->iparams, bDynamics,
1207 &nflexcon);
1208
1209
1210 if (idef->il[F_CONSTR].nr/3 > li->nc_alloc || li->nc_alloc == 0)
1211 {
1212 li->nc_alloc = over_alloc_dd(idef->il[F_CONSTR].nr/3);
1213 srenew(li->bllen0, li->nc_alloc)(li->bllen0) = save_realloc("li->bllen0", "/home/alexxy/Develop/gromacs/src/gromacs/mdlib/clincs.c"
, 1213, (li->bllen0), (li->nc_alloc), sizeof(*(li->bllen0
)))
;
1214 srenew(li->ddist, li->nc_alloc)(li->ddist) = save_realloc("li->ddist", "/home/alexxy/Develop/gromacs/src/gromacs/mdlib/clincs.c"
, 1214, (li->ddist), (li->nc_alloc), sizeof(*(li->ddist
)))
;
1215 srenew(li->bla, 2*li->nc_alloc)(li->bla) = save_realloc("li->bla", "/home/alexxy/Develop/gromacs/src/gromacs/mdlib/clincs.c"
, 1215, (li->bla), (2*li->nc_alloc), sizeof(*(li->bla
)))
;
1216 srenew(li->blc, li->nc_alloc)(li->blc) = save_realloc("li->blc", "/home/alexxy/Develop/gromacs/src/gromacs/mdlib/clincs.c"
, 1216, (li->blc), (li->nc_alloc), sizeof(*(li->blc)
))
;
1217 srenew(li->blc1, li->nc_alloc)(li->blc1) = save_realloc("li->blc1", "/home/alexxy/Develop/gromacs/src/gromacs/mdlib/clincs.c"
, 1217, (li->blc1), (li->nc_alloc), sizeof(*(li->blc1
)))
;
1218 srenew(li->blnr, li->nc_alloc+1)(li->blnr) = save_realloc("li->blnr", "/home/alexxy/Develop/gromacs/src/gromacs/mdlib/clincs.c"
, 1218, (li->blnr), (li->nc_alloc+1), sizeof(*(li->blnr
)))
;
1219 srenew(li->bllen, li->nc_alloc)(li->bllen) = save_realloc("li->bllen", "/home/alexxy/Develop/gromacs/src/gromacs/mdlib/clincs.c"
, 1219, (li->bllen), (li->nc_alloc), sizeof(*(li->bllen
)))
;
1220 srenew(li->tmpv, li->nc_alloc)(li->tmpv) = save_realloc("li->tmpv", "/home/alexxy/Develop/gromacs/src/gromacs/mdlib/clincs.c"
, 1220, (li->tmpv), (li->nc_alloc), sizeof(*(li->tmpv
)))
;
1221 srenew(li->tmp1, li->nc_alloc)(li->tmp1) = save_realloc("li->tmp1", "/home/alexxy/Develop/gromacs/src/gromacs/mdlib/clincs.c"
, 1221, (li->tmp1), (li->nc_alloc), sizeof(*(li->tmp1
)))
;
1222 srenew(li->tmp2, li->nc_alloc)(li->tmp2) = save_realloc("li->tmp2", "/home/alexxy/Develop/gromacs/src/gromacs/mdlib/clincs.c"
, 1222, (li->tmp2), (li->nc_alloc), sizeof(*(li->tmp2
)))
;
1223 srenew(li->tmp3, li->nc_alloc)(li->tmp3) = save_realloc("li->tmp3", "/home/alexxy/Develop/gromacs/src/gromacs/mdlib/clincs.c"
, 1223, (li->tmp3), (li->nc_alloc), sizeof(*(li->tmp3
)))
;
1224 srenew(li->tmp4, li->nc_alloc)(li->tmp4) = save_realloc("li->tmp4", "/home/alexxy/Develop/gromacs/src/gromacs/mdlib/clincs.c"
, 1224, (li->tmp4), (li->nc_alloc), sizeof(*(li->tmp4
)))
;
1225 srenew(li->mlambda, li->nc_alloc)(li->mlambda) = save_realloc("li->mlambda", "/home/alexxy/Develop/gromacs/src/gromacs/mdlib/clincs.c"
, 1225, (li->mlambda), (li->nc_alloc), sizeof(*(li->
mlambda)))
;
1226 if (li->ncg_triangle > 0)
1227 {
1228 /* This is allocating too much, but it is difficult to improve */
1229 srenew(li->triangle, li->nc_alloc)(li->triangle) = save_realloc("li->triangle", "/home/alexxy/Develop/gromacs/src/gromacs/mdlib/clincs.c"
, 1229, (li->triangle), (li->nc_alloc), sizeof(*(li->
triangle)))
;
1230 srenew(li->tri_bits, li->nc_alloc)(li->tri_bits) = save_realloc("li->tri_bits", "/home/alexxy/Develop/gromacs/src/gromacs/mdlib/clincs.c"
, 1230, (li->tri_bits), (li->nc_alloc), sizeof(*(li->
tri_bits)))
;
1231 }
1232 }
1233
1234 iatom = idef->il[F_CONSTR].iatoms;
1235
1236 ncc_alloc = li->ncc_alloc;
1237 li->blnr[0] = 0;
1238
1239 ni = idef->il[F_CONSTR].nr/3;
1240
1241 con = 0;
1242 nconnect = 0;
1243 li->blnr[con] = nconnect;
1244 for (i = 0; i < ni; i++)
1245 {
1246 bLocal = TRUE1;
Value stored to 'bLocal' is never read
1247 type = iatom[3*i];
1248 a1 = iatom[3*i+1];
1249 a2 = iatom[3*i+2];
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)
1254 {
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++)
1263 {
1264 concon = at2con.a[k];
1265 if (concon != i)
1266 {
1267 if (nconnect >= ncc_alloc)
1268 {
1269 ncc_alloc = over_alloc_small(nconnect+1)(int)(1.19*(nconnect+1) + 8000);
1270 srenew(li->blbnb, ncc_alloc)(li->blbnb) = save_realloc("li->blbnb", "/home/alexxy/Develop/gromacs/src/gromacs/mdlib/clincs.c"
, 1270, (li->blbnb), (ncc_alloc), sizeof(*(li->blbnb)))
;
1271 }
1272 li->blbnb[nconnect++] = concon;
1273 }
1274 }
1275 for (k = at2con.index[a2-start]; k < at2con.index[a2-start+1]; k++)
1276 {
1277 concon = at2con.a[k];
1278 if (concon != i)
1279 {
1280 if (nconnect+1 > ncc_alloc)
1281 {
1282 ncc_alloc = over_alloc_small(nconnect+1)(int)(1.19*(nconnect+1) + 8000);
1283 srenew(li->blbnb, ncc_alloc)(li->blbnb) = save_realloc("li->blbnb", "/home/alexxy/Develop/gromacs/src/gromacs/mdlib/clincs.c"
, 1283, (li->blbnb), (ncc_alloc), sizeof(*(li->blbnb)))
;
1284 }
1285 li->blbnb[nconnect++] = concon;
1286 }
1287 }
1288 li->blnr[con+1] = nconnect;
1289
1290 if (cr->dd == NULL((void*)0))
1291 {
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);
1295 }
1296 /* Increase the constraint count */
1297 con++;
1298 }
1299 }
1300
1301 done_blocka(&at2con);
1302
1303 /* This is the real number of constraints,
1304 * without dynamics the flexible constraints are not present.
1305 */
1306 li->nc = con;
1307
1308 li->ncc = li->blnr[con];
1309 if (cr->dd == NULL((void*)0))
1310 {
1311 /* Since the matrix is static, we can free some memory */
1312 ncc_alloc = li->ncc;
1313 srenew(li->blbnb, ncc_alloc)(li->blbnb) = save_realloc("li->blbnb", "/home/alexxy/Develop/gromacs/src/gromacs/mdlib/clincs.c"
, 1313, (li->blbnb), (ncc_alloc), sizeof(*(li->blbnb)))
;
1314 }
1315
1316 if (ncc_alloc > li->ncc_alloc)
1317 {
1318 li->ncc_alloc = ncc_alloc;
1319 srenew(li->blmf, li->ncc_alloc)(li->blmf) = save_realloc("li->blmf", "/home/alexxy/Develop/gromacs/src/gromacs/mdlib/clincs.c"
, 1319, (li->blmf), (li->ncc_alloc), sizeof(*(li->blmf
)))
;
1320 srenew(li->blmf1, li->ncc_alloc)(li->blmf1) = save_realloc("li->blmf1", "/home/alexxy/Develop/gromacs/src/gromacs/mdlib/clincs.c"
, 1320, (li->blmf1), (li->ncc_alloc), sizeof(*(li->blmf1
)))
;
1321 srenew(li->tmpncc, li->ncc_alloc)(li->tmpncc) = save_realloc("li->tmpncc", "/home/alexxy/Develop/gromacs/src/gromacs/mdlib/clincs.c"
, 1321, (li->tmpncc), (li->ncc_alloc), sizeof(*(li->
tmpncc)))
;
1322 }
1323
1324 if (debug)
1325 {
1326 fprintf(debug, "Number of constraints is %d, couplings %d\n",
1327 li->nc, li->ncc);
1328 }
1329
1330 if (li->nth == 1)
1331 {
1332 li->th[0].b0 = 0;
1333 li->th[0].b1 = li->nc;
1334 }
1335 else
1336 {
1337 lincs_thread_setup(li, md->nr);
1338 }
1339
1340 set_lincs_matrix(li, md->invmass, md->lambda);
1341}
1342
1343static 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)
1347{
1348 int b, i, j;
1349 rvec v0, v1;
1350 real wfac, d0, d1, cosine;
1351 char buf[STRLEN4096];
1352
1353 wfac = cos(DEG2RAD(3.14159265358979323846/180.0)*wangle);
1354
1355 sprintf(buf, "bonds that rotated more than %g degrees:\n"
1356 " atom 1 atom 2 angle previous, current, constraint length\n",
1357 wangle);
1358 fprintf(stderrstderr, "%s", buf);
1359 if (fplog)
1360 {
1361 fprintf(fplog, "%s", buf);
1362 }
1363
1364 for (b = 0; b < ncons; b++)
1365 {
1366 i = bla[2*b];
1367 j = bla[2*b+1];
1368 if (pbc)
1369 {
1370 pbc_dx_aiuc(pbc, x[i], x[j], v0);
1371 pbc_dx_aiuc(pbc, xprime[i], xprime[j], v1);
1372 }
1373 else
1374 {
1375 rvec_sub(x[i], x[j], v0);
1376 rvec_sub(xprime[i], xprime[j], v1);
1377 }
1378 d0 = norm(v0);
1379 d1 = norm(v1);
1380 cosine = iprod(v0, v1)/(d0*d1);
1381 if (cosine < wfac)
1382 {
1383 sprintf(buf, " %6d %6d %5.1f %8.4f %8.4f %8.4f\n",
1384 ddglatnr(dd, i), ddglatnr(dd, j),
1385 RAD2DEG(180.0/3.14159265358979323846)*acos(cosine), d0, d1, bllen[b]);
1386 fprintf(stderrstderr, "%s", buf);
1387 if (fplog)
1388 {
1389 fprintf(fplog, "%s", buf);
1390 }
1391 if (!gmx_isfinite(d1))
1392 {
1393 gmx_fatal(FARGS0, "/home/alexxy/Develop/gromacs/src/gromacs/mdlib/clincs.c",
1393
, "Bond length not finite.");
1394 }
1395
1396 (*warncount)++;
1397 }
1398 }
1399 if (*warncount > maxwarn)
1400 {
1401 too_many_constraint_warnings(econtLINCS, *warncount);
1402 }
1403}
1404
1405static 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)
1408{
1409 real len, d, ma, ssd2, r2;
1410 int *nlocat, count, b, im;
1411 rvec dx;
1412
1413 if (dd && dd->constraints)
1414 {
1415 nlocat = dd_constraints_nlocalatoms(dd);
1416 }
1417 else
1418 {
1419 nlocat = 0;
1420 }
1421
1422 ma = 0;
1423 ssd2 = 0;
1424 im = 0;
1425 count = 0;
1426 for (b = 0; b < ncons; b++)
1427 {
1428 if (pbc)
1429 {
1430 pbc_dx_aiuc(pbc, x[bla[2*b]], x[bla[2*b+1]], dx);
1431 }
1432 else
1433 {
1434 rvec_sub(x[bla[2*b]], x[bla[2*b+1]], dx);
1435 }
1436 r2 = norm2(dx);
1437 len = r2*gmx_invsqrt(r2)gmx_software_invsqrt(r2);
1438 d = fabs(len/bllen[b]-1);
1439 if (d > ma && (nlocat == NULL((void*)0) || nlocat[b]))
1440 {
1441 ma = d;
1442 im = b;
1443 }
1444 if (nlocat == NULL((void*)0))
1445 {
1446 ssd2 += d*d;
1447 count++;
1448 }
1449 else
1450 {
1451 ssd2 += nlocat[b]*d*d;
1452 count += nlocat[b];
1453 }
1454 }
1455
1456 *ncons_loc = (nlocat ? 0.5 : 1)*count;
1457 *ssd = (nlocat ? 0.5 : 1)*ssd2;
1458 *max = ma;
1459 *imax = im;
1460}
1461
1462gmx_bool constrain_lincs(FILE *fplog, gmx_bool bLog, gmx_bool bEner,
1463 t_inputrec *ir,
1464 gmx_int64_t step,
1465 struct gmx_lincsdata *lincsd, t_mdatoms *md,
1466 t_commrec *cr,
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,
1472 int econq,
1473 t_nrnb *nrnb,
1474 int maxwarn, int *warncount)
1475{
1476 char buf[STRLEN4096], buf2[22], buf3[STRLEN4096];
1477 int i, warn, p_imax, error;
1478 real ncons_loc, p_ssd, p_max = 0;
1479 rvec dx;
1480 gmx_bool bOK;
1481
1482 bOK = TRUE1;
1483
1484 if (lincsd->nc == 0 && cr->dd == NULL((void*)0))
1485 {
1486 if (bLog || bEner)
1487 {
1488 lincsd->rmsd_data[0] = 0;
1489 if (ir->eI == eiSD2 && v == NULL((void*)0))
1490 {
1491 i = 2;
1492 }
1493 else
1494 {
1495 i = 1;
1496 }
1497 lincsd->rmsd_data[i] = 0;
1498 }
1499
1500 return bOK;
1501 }
1502
1503 if (econq == econqCoord)
1504 {
1505 if (ir->efep != efepNO)
1506 {
1507 if (md->nMassPerturbed && lincsd->matlam != md->lambda)
1508 {
1509 set_lincs_matrix(lincsd, md->invmass, md->lambda);
1510 }
1511
1512 for (i = 0; i < lincsd->nc; i++)
1513 {
1514 lincsd->bllen[i] = lincsd->bllen0[i] + lambda*lincsd->ddist[i];
1515 }
1516 }
1517
1518 if (lincsd->ncg_flex)
1519 {
1520 /* Set the flexible constraint lengths to the old lengths */
1521 if (pbc != NULL((void*)0))
1522 {
1523 for (i = 0; i < lincsd->nc; i++)
1524 {
1525 if (lincsd->bllen[i] == 0)
1526 {
1527 pbc_dx_aiuc(pbc, x[lincsd->bla[2*i]], x[lincsd->bla[2*i+1]], dx);
1528 lincsd->bllen[i] = norm(dx);
1529 }
1530 }
1531 }
1532 else
1533 {
1534 for (i = 0; i < lincsd->nc; i++)
1535 {
1536 if (lincsd->bllen[i] == 0)
1537 {
1538 lincsd->bllen[i] =
1539 sqrt(distance2(x[lincsd->bla[2*i]],
1540 x[lincsd->bla[2*i+1]]));
1541 }
1542 }
1543 }
1544 }
1545
1546 if (bLog && fplog)
1547 {
1548 cconerr(cr->dd, lincsd->nc, lincsd->bla, lincsd->bllen, xprime, pbc,
1549 &ncons_loc, &p_ssd, &p_max, &p_imax);
1550 }
1551
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.
1555 */
1556 warn = -1;
1557
1558 /* The OpenMP parallel region of constrain_lincs for coords */
1559#pragma omp parallel num_threads(lincsd->nth)
1560 {
1561 int th = gmx_omp_get_thread_num();
1562
1563 clear_mat(lincsd->th[th].vir_r_m_dr);
1564
1565 do_lincs(x, xprime, box, pbc, lincsd, th,
1566 md->invmass, cr,
1567 bCalcVir || (ir->efep != efepNO),
1568 ir->LincsWarnAngle, &warn,
1569 invdt, v, bCalcVir,
1570 th == 0 ? vir_r_m_dr : lincsd->th[th].vir_r_m_dr);
1571 }
1572
1573 if (ir->efep != efepNO)
1574 {
1575 real dt_2, dvdl = 0;
1576
1577 dt_2 = 1.0/(ir->delta_t*ir->delta_t);
1578 for (i = 0; (i < lincsd->nc); i++)
1579 {
1580 dvdl -= lincsd->mlambda[i]*dt_2*lincsd->ddist[i];
1581 }
1582 *dvdlambda += dvdl;
1583 }
1584
1585 if (bLog && fplog && lincsd->nc > 0)
1586 {
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]));
1592 }
1593 if (bLog || bEner)
1594 {
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((void*)0))
1599 {
1600 i = 2;
1601 }
1602 else
1603 {
1604 i = 1;
1605 }
1606 lincsd->rmsd_data[0] = ncons_loc;
1607 lincsd->rmsd_data[i] = p_ssd;
1608 }
1609 else
1610 {
1611 lincsd->rmsd_data[0] = 0;
1612 lincsd->rmsd_data[1] = 0;
1613 lincsd->rmsd_data[2] = 0;
1614 }
1615 if (bLog && fplog && lincsd->nc > 0)
1616 {
1617 fprintf(fplog,
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]));
1622 }
1623
1624 if (warn >= 0)
1625 {
1626 if (maxwarn >= 0)
1627 {
1628 cconerr(cr->dd, lincsd->nc, lincsd->bla, lincsd->bllen, xprime, pbc,
1629 &ncons_loc, &p_ssd, &p_max, &p_imax);
1630 if (MULTISIM(cr)((cr)->ms))
1631 {
1632 sprintf(buf3, " in simulation %d", cr->ms->sim);
1633 }
1634 else
1635 {
1636 buf3[0] = 0;
1637 }
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,
1642 buf3,
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]));
1646 if (fplog)
1647 {
1648 fprintf(fplog, "%s", buf);
1649 }
1650 fprintf(stderrstderr, "%s", buf);
1651 lincs_warning(fplog, cr->dd, x, xprime, pbc,
1652 lincsd->nc, lincsd->bla, lincsd->bllen,
1653 ir->LincsWarnAngle, maxwarn, warncount);
1654 }
1655 bOK = (p_max < 0.5);
1656 }
1657
1658 if (lincsd->ncg_flex)
1659 {
1660 for (i = 0; (i < lincsd->nc); i++)
1661 {
1662 if (lincsd->bllen0[i] == 0 && lincsd->ddist[i] == 0)
1663 {
1664 lincsd->bllen[i] = 0;
1665 }
1666 }
1667 }
1668 }
1669 else
1670 {
1671 /* The OpenMP parallel region of constrain_lincs for derivatives */
1672#pragma omp parallel num_threads(lincsd->nth)
1673 {
1674 int th = gmx_omp_get_thread_num();
1675
1676 do_lincsp(x, xprime, min_proj, pbc, lincsd, th,
1677 md->invmass, econq, ir->efep != efepNO ? dvdlambda : NULL((void*)0),
1678 bCalcVir, th == 0 ? vir_r_m_dr : lincsd->th[th].vir_r_m_dr);
1679 }
1680 }
1681
1682 if (bCalcVir && lincsd->nth > 1)
1683 {
1684 for (i = 1; i < lincsd->nth; i++)
1685 {
1686 m_add(vir_r_m_dr, lincsd->th[i].vir_r_m_dr, vir_r_m_dr);
1687 }
1688 }
1689
1690 /* count assuming nit=1 */
1691 inc_nrnb(nrnb, eNR_LINCS, lincsd->nc)(nrnb)->n[eNR_LINCS] += lincsd->nc;
1692 inc_nrnb(nrnb, eNR_LINCSMAT, (2+lincsd->nOrder)*lincsd->ncc)(nrnb)->n[eNR_LINCSMAT] += (2+lincsd->nOrder)*lincsd->
ncc
;
1693 if (lincsd->ntriangle > 0)
1694 {
1695 inc_nrnb(nrnb, eNR_LINCSMAT, lincsd->nOrder*lincsd->ncc_triangle)(nrnb)->n[eNR_LINCSMAT] += lincsd->nOrder*lincsd->ncc_triangle;
1696 }
1697 if (v)
1698 {
1699 inc_nrnb(nrnb, eNR_CONSTR_V, lincsd->nc*2)(nrnb)->n[eNR_CONSTR_V] += lincsd->nc*2;
1700 }
1701 if (bCalcVir)
1702 {
1703 inc_nrnb(nrnb, eNR_CONSTR_VIR, lincsd->nc)(nrnb)->n[eNR_CONSTR_VIR] += lincsd->nc;
1704 }
1705
1706 return bOK;
1707}