Merge branch release-2018
[alexxy/gromacs.git] / src / gromacs / mdlib / clincs.cpp
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,2015,2016,2017,2018, 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 #include "gmxpre.h"
39
40 #include "config.h"
41
42 #include <assert.h>
43 #include <stdlib.h>
44
45 #include <cmath>
46
47 #include <algorithm>
48
49 #include "gromacs/domdec/domdec.h"
50 #include "gromacs/domdec/domdec_struct.h"
51 #include "gromacs/gmxlib/nrnb.h"
52 #include "gromacs/math/functions.h"
53 #include "gromacs/math/units.h"
54 #include "gromacs/math/vec.h"
55 #include "gromacs/mdlib/constr.h"
56 #include "gromacs/mdlib/gmx_omp_nthreads.h"
57 #include "gromacs/mdlib/mdrun.h"
58 #include "gromacs/mdtypes/commrec.h"
59 #include "gromacs/mdtypes/inputrec.h"
60 #include "gromacs/mdtypes/md_enums.h"
61 #include "gromacs/pbcutil/pbc.h"
62 #include "gromacs/pbcutil/pbc-simd.h"
63 #include "gromacs/simd/simd.h"
64 #include "gromacs/simd/simd_math.h"
65 #include "gromacs/simd/vector_operations.h"
66 #include "gromacs/topology/block.h"
67 #include "gromacs/topology/mtop_util.h"
68 #include "gromacs/utility/basedefinitions.h"
69 #include "gromacs/utility/bitmask.h"
70 #include "gromacs/utility/cstringutil.h"
71 #include "gromacs/utility/exceptions.h"
72 #include "gromacs/utility/fatalerror.h"
73 #include "gromacs/utility/gmxomp.h"
74 #include "gromacs/utility/pleasecite.h"
75 #include "gromacs/utility/smalloc.h"
76
77 using namespace gmx; // TODO: Remove when this file is moved into gmx namespace
78
79 typedef struct {
80     int    b0;         /* first constraint for this task */
81     int    b1;         /* b1-1 is the last constraint for this task */
82     int    ntriangle;  /* the number of constraints in triangles */
83     int   *triangle;   /* the list of triangle constraints */
84     int   *tri_bits;   /* the bits tell if the matrix element should be used */
85     int    tri_alloc;  /* allocation size of triangle and tri_bits */
86     int    nind;       /* number of indices */
87     int   *ind;        /* constraint index for updating atom data */
88     int    nind_r;     /* number of indices */
89     int   *ind_r;      /* constraint index for updating atom data */
90     int    ind_nalloc; /* allocation size of ind and ind_r */
91     tensor vir_r_m_dr; /* temporary variable for virial calculation */
92     real   dhdlambda;  /* temporary variable for lambda derivative */
93 } lincs_task_t;
94
95 typedef struct gmx_lincsdata {
96     int             ncg;          /* the global number of constraints */
97     int             ncg_flex;     /* the global number of flexible constraints */
98     int             ncg_triangle; /* the global number of constraints in triangles */
99     int             nIter;        /* the number of iterations */
100     int             nOrder;       /* the order of the matrix expansion */
101     int             max_connect;  /* the maximum number of constrains connected to a single atom */
102
103     int             nc_real;      /* the number of real constraints */
104     int             nc;           /* the number of constraints including padding for SIMD */
105     int             nc_alloc;     /* the number we allocated memory for */
106     int             ncc;          /* the number of constraint connections */
107     int             ncc_alloc;    /* the number we allocated memory for */
108     real            matlam;       /* the FE lambda value used for filling blc and blmf */
109     int            *con_index;    /* mapping from topology to LINCS constraints */
110     real           *bllen0;       /* the reference distance in topology A */
111     real           *ddist;        /* the reference distance in top B - the r.d. in top A */
112     int            *bla;          /* the atom pairs involved in the constraints */
113     real           *blc;          /* 1/sqrt(invmass1 + invmass2) */
114     real           *blc1;         /* as blc, but with all masses 1 */
115     int            *blnr;         /* index into blbnb and blmf */
116     int            *blbnb;        /* list of constraint connections */
117     int             ntriangle;    /* the local number of constraints in triangles */
118     int             ncc_triangle; /* the number of constraint connections in triangles */
119     gmx_bool        bCommIter;    /* communicate before each LINCS interation */
120     real           *blmf;         /* matrix of mass factors for constraint connections */
121     real           *blmf1;        /* as blmf, but with all masses 1 */
122     real           *bllen;        /* the reference bond length */
123     int            *nlocat;       /* the local atom count per constraint, can be NULL */
124
125     int             ntask;        /* The number of tasks = #threads for LINCS */
126     lincs_task_t   *task;         /* LINCS thread division */
127     gmx_bitmask_t  *atf;          /* atom flags for thread parallelization */
128     int             atf_nalloc;   /* allocation size of atf */
129     gmx_bool        bTaskDep;     /* are the LINCS tasks interdependent? */
130     gmx_bool        bTaskDepTri;  /* are there triangle constraints that cross task borders? */
131     /* arrays for temporary storage in the LINCS algorithm */
132     rvec           *tmpv;
133     real           *tmpncc;
134     real           *tmp1;
135     real           *tmp2;
136     real           *tmp3;
137     real           *tmp4;
138     real           *mlambda; /* the Lagrange multipliers * -1 */
139     /* storage for the constraint RMS relative deviation output */
140     real            rmsd_data[3];
141 } t_gmx_lincsdata;
142
143 /* Define simd_width for memory allocation used for SIMD code */
144 #if GMX_SIMD_HAVE_REAL
145 static const int simd_width = GMX_SIMD_REAL_WIDTH;
146 #else
147 static const int simd_width = 1;
148 #endif
149
150 /* Align to 128 bytes, consistent with the current implementation of
151    AlignedAllocator, which currently forces 128 byte alignment. */
152 static const int align_bytes = 128;
153
154 real *lincs_rmsd_data(struct gmx_lincsdata *lincsd)
155 {
156     return lincsd->rmsd_data;
157 }
158
159 real lincs_rmsd(struct gmx_lincsdata *lincsd)
160 {
161     if (lincsd->rmsd_data[0] > 0)
162     {
163         return std::sqrt(lincsd->rmsd_data[1]/lincsd->rmsd_data[0]);
164     }
165     else
166     {
167         return 0;
168     }
169 }
170
171 /* Do a set of nrec LINCS matrix multiplications.
172  * This function will return with up to date thread-local
173  * constraint data, without an OpenMP barrier.
174  */
175 static void lincs_matrix_expand(const struct gmx_lincsdata *lincsd,
176                                 const lincs_task_t *li_task,
177                                 const real *blcc,
178                                 real *rhs1, real *rhs2, real *sol)
179 {
180     int        b0, b1, nrec, rec;
181     const int *blnr  = lincsd->blnr;
182     const int *blbnb = lincsd->blbnb;
183
184     b0   = li_task->b0;
185     b1   = li_task->b1;
186     nrec = lincsd->nOrder;
187
188     for (rec = 0; rec < nrec; rec++)
189     {
190         int b;
191
192         if (lincsd->bTaskDep)
193         {
194 #pragma omp barrier
195         }
196         for (b = b0; b < b1; b++)
197         {
198             real mvb;
199             int  n;
200
201             mvb = 0;
202             for (n = blnr[b]; n < blnr[b+1]; n++)
203             {
204                 mvb = mvb + blcc[n]*rhs1[blbnb[n]];
205             }
206             rhs2[b] = mvb;
207             sol[b]  = sol[b] + mvb;
208         }
209
210         real *swap;
211
212         swap = rhs1;
213         rhs1 = rhs2;
214         rhs2 = swap;
215     } /* nrec*(ncons+2*nrtot) flops */
216
217     if (lincsd->ntriangle > 0)
218     {
219         /* Perform an extra nrec recursions for only the constraints
220          * involved in rigid triangles.
221          * In this way their accuracy should come close to those of the other
222          * constraints, since traingles of constraints can produce eigenvalues
223          * around 0.7, while the effective eigenvalue for bond constraints
224          * is around 0.4 (and 0.7*0.7=0.5).
225          */
226
227         if (lincsd->bTaskDep)
228         {
229             /* We need a barrier here, since other threads might still be
230              * reading the contents of rhs1 and/o rhs2.
231              * We could avoid this barrier by introducing two extra rhs
232              * arrays for the triangle constraints only.
233              */
234 #pragma omp barrier
235         }
236
237         /* Constraints involved in a triangle are ensured to be in the same
238          * LINCS task. This means no barriers are required during the extra
239          * iterations for the triangle constraints.
240          */
241         const int *triangle = li_task->triangle;
242         const int *tri_bits = li_task->tri_bits;
243
244         for (rec = 0; rec < nrec; rec++)
245         {
246             int tb;
247
248             for (tb = 0; tb < li_task->ntriangle; tb++)
249             {
250                 int  b, bits, nr0, nr1, n;
251                 real mvb;
252
253                 b    = triangle[tb];
254                 bits = tri_bits[tb];
255                 mvb  = 0;
256                 nr0  = blnr[b];
257                 nr1  = blnr[b+1];
258                 for (n = nr0; n < nr1; n++)
259                 {
260                     if (bits & (1 << (n - nr0)))
261                     {
262                         mvb = mvb + blcc[n]*rhs1[blbnb[n]];
263                     }
264                 }
265                 rhs2[b] = mvb;
266                 sol[b]  = sol[b] + mvb;
267             }
268
269             real *swap;
270
271             swap = rhs1;
272             rhs1 = rhs2;
273             rhs2 = swap;
274         } /* nrec*(ntriangle + ncc_triangle*2) flops */
275
276         if (lincsd->bTaskDepTri)
277         {
278             /* The constraints triangles are decoupled from each other,
279              * but constraints in one triangle cross thread task borders.
280              * We could probably avoid this with more advanced setup code.
281              */
282 #pragma omp barrier
283         }
284     }
285 }
286
287 static void lincs_update_atoms_noind(int ncons, const int *bla,
288                                      real prefac,
289                                      const real *fac, rvec *r,
290                                      const real *invmass,
291                                      rvec *x)
292 {
293     int  b, i, j;
294     real mvb, im1, im2, tmp0, tmp1, tmp2;
295
296     if (invmass != nullptr)
297     {
298         for (b = 0; b < ncons; b++)
299         {
300             i        = bla[2*b];
301             j        = bla[2*b+1];
302             mvb      = prefac*fac[b];
303             im1      = invmass[i];
304             im2      = invmass[j];
305             tmp0     = r[b][0]*mvb;
306             tmp1     = r[b][1]*mvb;
307             tmp2     = r[b][2]*mvb;
308             x[i][0] -= tmp0*im1;
309             x[i][1] -= tmp1*im1;
310             x[i][2] -= tmp2*im1;
311             x[j][0] += tmp0*im2;
312             x[j][1] += tmp1*im2;
313             x[j][2] += tmp2*im2;
314         } /* 16 ncons flops */
315     }
316     else
317     {
318         for (b = 0; b < ncons; b++)
319         {
320             i        = bla[2*b];
321             j        = bla[2*b+1];
322             mvb      = prefac*fac[b];
323             tmp0     = r[b][0]*mvb;
324             tmp1     = r[b][1]*mvb;
325             tmp2     = r[b][2]*mvb;
326             x[i][0] -= tmp0;
327             x[i][1] -= tmp1;
328             x[i][2] -= tmp2;
329             x[j][0] += tmp0;
330             x[j][1] += tmp1;
331             x[j][2] += tmp2;
332         }
333     }
334 }
335
336 static void lincs_update_atoms_ind(int ncons, const int *ind, const int *bla,
337                                    real prefac,
338                                    const real *fac, rvec *r,
339                                    const real *invmass,
340                                    rvec *x)
341 {
342     int  bi, b, i, j;
343     real mvb, im1, im2, tmp0, tmp1, tmp2;
344
345     if (invmass != nullptr)
346     {
347         for (bi = 0; bi < ncons; bi++)
348         {
349             b        = ind[bi];
350             i        = bla[2*b];
351             j        = bla[2*b+1];
352             mvb      = prefac*fac[b];
353             im1      = invmass[i];
354             im2      = invmass[j];
355             tmp0     = r[b][0]*mvb;
356             tmp1     = r[b][1]*mvb;
357             tmp2     = r[b][2]*mvb;
358             x[i][0] -= tmp0*im1;
359             x[i][1] -= tmp1*im1;
360             x[i][2] -= tmp2*im1;
361             x[j][0] += tmp0*im2;
362             x[j][1] += tmp1*im2;
363             x[j][2] += tmp2*im2;
364         } /* 16 ncons flops */
365     }
366     else
367     {
368         for (bi = 0; bi < ncons; bi++)
369         {
370             b        = ind[bi];
371             i        = bla[2*b];
372             j        = bla[2*b+1];
373             mvb      = prefac*fac[b];
374             tmp0     = r[b][0]*mvb;
375             tmp1     = r[b][1]*mvb;
376             tmp2     = r[b][2]*mvb;
377             x[i][0] -= tmp0;
378             x[i][1] -= tmp1;
379             x[i][2] -= tmp2;
380             x[j][0] += tmp0;
381             x[j][1] += tmp1;
382             x[j][2] += tmp2;
383         } /* 16 ncons flops */
384     }
385 }
386
387 static void lincs_update_atoms(struct gmx_lincsdata *li, int th,
388                                real prefac,
389                                const real *fac, rvec *r,
390                                const real *invmass,
391                                rvec *x)
392 {
393     if (li->ntask == 1)
394     {
395         /* Single thread, we simply update for all constraints */
396         lincs_update_atoms_noind(li->nc_real,
397                                  li->bla, prefac, fac, r, invmass, x);
398     }
399     else
400     {
401         /* Update the atom vector components for our thread local
402          * constraints that only access our local atom range.
403          * This can be done without a barrier.
404          */
405         lincs_update_atoms_ind(li->task[th].nind, li->task[th].ind,
406                                li->bla, prefac, fac, r, invmass, x);
407
408         if (li->task[li->ntask].nind > 0)
409         {
410             /* Update the constraints that operate on atoms
411              * in multiple thread atom blocks on the master thread.
412              */
413 #pragma omp barrier
414 #pragma omp master
415             {
416                 lincs_update_atoms_ind(li->task[li->ntask].nind,
417                                        li->task[li->ntask].ind,
418                                        li->bla, prefac, fac, r, invmass, x);
419             }
420         }
421     }
422 }
423
424 #if GMX_SIMD_HAVE_REAL
425 /* Calculate the constraint distance vectors r to project on from x.
426  * Determine the right-hand side of the matrix equation using quantity f.
427  * This function only differs from calc_dr_x_xp_simd below in that
428  * no constraint length is subtracted and no PBC is used for f.
429  */
430 static void gmx_simdcall
431 calc_dr_x_f_simd(int                       b0,
432                  int                       b1,
433                  const int *               bla,
434                  const rvec * gmx_restrict x,
435                  const rvec * gmx_restrict f,
436                  const real * gmx_restrict blc,
437                  const real *              pbc_simd,
438                  rvec * gmx_restrict       r,
439                  real * gmx_restrict       rhs,
440                  real * gmx_restrict       sol)
441 {
442     assert(b0 % GMX_SIMD_REAL_WIDTH == 0);
443
444     alignas(GMX_SIMD_ALIGNMENT) std::int32_t offset2[GMX_SIMD_REAL_WIDTH];
445
446     for (int i = 0; i < GMX_SIMD_REAL_WIDTH; i++)
447     {
448         offset2[i] = i;
449     }
450
451     for (int bs = b0; bs < b1; bs += GMX_SIMD_REAL_WIDTH)
452     {
453         SimdReal x0_S, y0_S, z0_S;
454         SimdReal x1_S, y1_S, z1_S;
455         SimdReal rx_S, ry_S, rz_S, n2_S, il_S;
456         SimdReal fx_S, fy_S, fz_S, ip_S, rhs_S;
457         alignas(GMX_SIMD_ALIGNMENT) std::int32_t      offset0[GMX_SIMD_REAL_WIDTH];
458         alignas(GMX_SIMD_ALIGNMENT) std::int32_t      offset1[GMX_SIMD_REAL_WIDTH];
459
460         for (int i = 0; i < GMX_SIMD_REAL_WIDTH; i++)
461         {
462             offset0[i] = bla[bs*2 + i*2];
463             offset1[i] = bla[bs*2 + i*2 + 1];
464         }
465
466         gatherLoadUTranspose<3>(reinterpret_cast<const real *>(x), offset0, &x0_S, &y0_S, &z0_S);
467         gatherLoadUTranspose<3>(reinterpret_cast<const real *>(x), offset1, &x1_S, &y1_S, &z1_S);
468         rx_S = x0_S - x1_S;
469         ry_S = y0_S - y1_S;
470         rz_S = z0_S - z1_S;
471
472         pbc_correct_dx_simd(&rx_S, &ry_S, &rz_S, pbc_simd);
473
474         n2_S  = norm2(rx_S, ry_S, rz_S);
475         il_S  = invsqrt(n2_S);
476
477         rx_S  = rx_S * il_S;
478         ry_S  = ry_S * il_S;
479         rz_S  = rz_S * il_S;
480
481         transposeScatterStoreU<3>(reinterpret_cast<real *>(r + bs), offset2, rx_S, ry_S, rz_S);
482
483         gatherLoadUTranspose<3>(reinterpret_cast<const real *>(f), offset0, &x0_S, &y0_S, &z0_S);
484         gatherLoadUTranspose<3>(reinterpret_cast<const real *>(f), offset1, &x1_S, &y1_S, &z1_S);
485         fx_S = x0_S - x1_S;
486         fy_S = y0_S - y1_S;
487         fz_S = z0_S - z1_S;
488
489         ip_S  = iprod(rx_S, ry_S, rz_S, fx_S, fy_S, fz_S);
490
491         rhs_S = load<SimdReal>(blc + bs) * ip_S;
492
493         store(rhs + bs, rhs_S);
494         store(sol + bs, rhs_S);
495     }
496 }
497 #endif // GMX_SIMD_HAVE_REAL
498
499 /* LINCS projection, works on derivatives of the coordinates */
500 static void do_lincsp(rvec *x, rvec *f, rvec *fp, t_pbc *pbc,
501                       struct gmx_lincsdata *lincsd, int th,
502                       real *invmass,
503                       int econq, gmx_bool bCalcDHDL,
504                       gmx_bool bCalcVir, tensor rmdf)
505 {
506     int      b0, b1, b;
507     int     *bla, *blnr, *blbnb;
508     rvec    *r;
509     real    *blc, *blmf, *blcc, *rhs1, *rhs2, *sol;
510
511     b0 = lincsd->task[th].b0;
512     b1 = lincsd->task[th].b1;
513
514     bla    = lincsd->bla;
515     r      = lincsd->tmpv;
516     blnr   = lincsd->blnr;
517     blbnb  = lincsd->blbnb;
518     if (econq != econqForce)
519     {
520         /* Use mass-weighted parameters */
521         blc  = lincsd->blc;
522         blmf = lincsd->blmf;
523     }
524     else
525     {
526         /* Use non mass-weighted parameters */
527         blc  = lincsd->blc1;
528         blmf = lincsd->blmf1;
529     }
530     blcc   = lincsd->tmpncc;
531     rhs1   = lincsd->tmp1;
532     rhs2   = lincsd->tmp2;
533     sol    = lincsd->tmp3;
534
535 #if GMX_SIMD_HAVE_REAL
536     /* This SIMD code does the same as the plain-C code after the #else.
537      * The only difference is that we always call pbc code, as with SIMD
538      * the overhead of pbc computation (when not needed) is small.
539      */
540     alignas(GMX_SIMD_ALIGNMENT) real    pbc_simd[9*GMX_SIMD_REAL_WIDTH];
541
542     /* Convert the pbc struct for SIMD */
543     set_pbc_simd(pbc, pbc_simd);
544
545     /* Compute normalized x i-j vectors, store in r.
546      * Compute the inner product of r and xp i-j and store in rhs1.
547      */
548     calc_dr_x_f_simd(b0, b1, bla, x, f, blc,
549                      pbc_simd,
550                      r, rhs1, sol);
551
552 #else // GMX_SIMD_HAVE_REAL
553
554     /* Compute normalized i-j vectors */
555     if (pbc)
556     {
557         for (b = b0; b < b1; b++)
558         {
559             rvec dx;
560
561             pbc_dx_aiuc(pbc, x[bla[2*b]], x[bla[2*b+1]], dx);
562             unitv(dx, r[b]);
563         }
564     }
565     else
566     {
567         for (b = b0; b < b1; b++)
568         {
569             rvec dx;
570
571             rvec_sub(x[bla[2*b]], x[bla[2*b+1]], dx);
572             unitv(dx, r[b]);
573         } /* 16 ncons flops */
574     }
575
576     for (b = b0; b < b1; b++)
577     {
578         int  i, j;
579         real mvb;
580
581         i       = bla[2*b];
582         j       = bla[2*b+1];
583         mvb     = blc[b]*(r[b][0]*(f[i][0] - f[j][0]) +
584                           r[b][1]*(f[i][1] - f[j][1]) +
585                           r[b][2]*(f[i][2] - f[j][2]));
586         rhs1[b] = mvb;
587         sol[b]  = mvb;
588         /* 7 flops */
589     }
590
591 #endif // GMX_SIMD_HAVE_REAL
592
593     if (lincsd->bTaskDep)
594     {
595         /* We need a barrier, since the matrix construction below
596          * can access entries in r of other threads.
597          */
598 #pragma omp barrier
599     }
600
601     /* Construct the (sparse) LINCS matrix */
602     for (b = b0; b < b1; b++)
603     {
604         int n;
605
606         for (n = blnr[b]; n < blnr[b+1]; n++)
607         {
608             blcc[n] = blmf[n]*iprod(r[b], r[blbnb[n]]);
609         } /* 6 nr flops */
610     }
611     /* Together: 23*ncons + 6*nrtot flops */
612
613     lincs_matrix_expand(lincsd, &lincsd->task[th], blcc, rhs1, rhs2, sol);
614     /* nrec*(ncons+2*nrtot) flops */
615
616     if (econq == econqDeriv_FlexCon)
617     {
618         /* We only want to constraint the flexible constraints,
619          * so we mask out the normal ones by setting sol to 0.
620          */
621         for (b = b0; b < b1; b++)
622         {
623             if (!(lincsd->bllen0[b] == 0 && lincsd->ddist[b] == 0))
624             {
625                 sol[b] = 0;
626             }
627         }
628     }
629
630     /* We multiply sol by blc, so we can use lincs_update_atoms for OpenMP */
631     for (b = b0; b < b1; b++)
632     {
633         sol[b] *= blc[b];
634     }
635
636     /* When constraining forces, we should not use mass weighting,
637      * so we pass invmass=NULL, which results in the use of 1 for all atoms.
638      */
639     lincs_update_atoms(lincsd, th, 1.0, sol, r,
640                        (econq != econqForce) ? invmass : nullptr, fp);
641
642     if (bCalcDHDL)
643     {
644         real dhdlambda;
645
646         dhdlambda = 0;
647         for (b = b0; b < b1; b++)
648         {
649             dhdlambda -= sol[b]*lincsd->ddist[b];
650         }
651
652         lincsd->task[th].dhdlambda = dhdlambda;
653     }
654
655     if (bCalcVir)
656     {
657         /* Constraint virial,
658          * determines sum r_bond x delta f,
659          * where delta f is the constraint correction
660          * of the quantity that is being constrained.
661          */
662         for (b = b0; b < b1; b++)
663         {
664             real mvb, tmp1;
665             int  i, j;
666
667             mvb = lincsd->bllen[b]*sol[b];
668             for (i = 0; i < DIM; i++)
669             {
670                 tmp1 = mvb*r[b][i];
671                 for (j = 0; j < DIM; j++)
672                 {
673                     rmdf[i][j] += tmp1*r[b][j];
674                 }
675             }
676         } /* 23 ncons flops */
677     }
678 }
679
680 #if GMX_SIMD_HAVE_REAL
681 /* Calculate the constraint distance vectors r to project on from x.
682  * Determine the right-hand side of the matrix equation using coordinates xp.
683  */
684 static void gmx_simdcall
685 calc_dr_x_xp_simd(int                       b0,
686                   int                       b1,
687                   const int *               bla,
688                   const rvec * gmx_restrict x,
689                   const rvec * gmx_restrict xp,
690                   const real * gmx_restrict bllen,
691                   const real * gmx_restrict blc,
692                   const real *              pbc_simd,
693                   rvec * gmx_restrict       r,
694                   real * gmx_restrict       rhs,
695                   real * gmx_restrict       sol)
696 {
697     assert(b0 % GMX_SIMD_REAL_WIDTH == 0);
698     alignas(GMX_SIMD_ALIGNMENT) std::int32_t offset2[GMX_SIMD_REAL_WIDTH];
699
700     for (int i = 0; i < GMX_SIMD_REAL_WIDTH; i++)
701     {
702         offset2[i] = i;
703     }
704
705     for (int bs = b0; bs < b1; bs += GMX_SIMD_REAL_WIDTH)
706     {
707         SimdReal x0_S, y0_S, z0_S;
708         SimdReal x1_S, y1_S, z1_S;
709         SimdReal rx_S, ry_S, rz_S, n2_S, il_S;
710         SimdReal rxp_S, ryp_S, rzp_S, ip_S, rhs_S;
711         alignas(GMX_SIMD_ALIGNMENT) std::int32_t      offset0[GMX_SIMD_REAL_WIDTH];
712         alignas(GMX_SIMD_ALIGNMENT) std::int32_t      offset1[GMX_SIMD_REAL_WIDTH];
713
714         for (int i = 0; i < GMX_SIMD_REAL_WIDTH; i++)
715         {
716             offset0[i] = bla[bs*2 + i*2];
717             offset1[i] = bla[bs*2 + i*2 + 1];
718         }
719
720         gatherLoadUTranspose<3>(reinterpret_cast<const real *>(x), offset0, &x0_S, &y0_S, &z0_S);
721         gatherLoadUTranspose<3>(reinterpret_cast<const real *>(x), offset1, &x1_S, &y1_S, &z1_S);
722         rx_S = x0_S - x1_S;
723         ry_S = y0_S - y1_S;
724         rz_S = z0_S - z1_S;
725
726         pbc_correct_dx_simd(&rx_S, &ry_S, &rz_S, pbc_simd);
727
728         n2_S  = norm2(rx_S, ry_S, rz_S);
729         il_S  = invsqrt(n2_S);
730
731         rx_S  = rx_S * il_S;
732         ry_S  = ry_S * il_S;
733         rz_S  = rz_S * il_S;
734
735         transposeScatterStoreU<3>(reinterpret_cast<real *>(r + bs), offset2, rx_S, ry_S, rz_S);
736
737         gatherLoadUTranspose<3>(reinterpret_cast<const real *>(xp), offset0, &x0_S, &y0_S, &z0_S);
738         gatherLoadUTranspose<3>(reinterpret_cast<const real *>(xp), offset1, &x1_S, &y1_S, &z1_S);
739         rxp_S = x0_S - x1_S;
740         ryp_S = y0_S - y1_S;
741         rzp_S = z0_S - z1_S;
742
743         pbc_correct_dx_simd(&rxp_S, &ryp_S, &rzp_S, pbc_simd);
744
745         ip_S  = iprod(rx_S, ry_S, rz_S, rxp_S, ryp_S, rzp_S);
746
747         rhs_S = load<SimdReal>(blc + bs) * (ip_S - load<SimdReal>(bllen + bs));
748
749         store(rhs + bs, rhs_S);
750         store(sol + bs, rhs_S);
751     }
752 }
753 #endif // GMX_SIMD_HAVE_REAL
754
755 /* Determine the distances and right-hand side for the next iteration */
756 gmx_unused static void calc_dist_iter(
757         int                       b0,
758         int                       b1,
759         const int *               bla,
760         const rvec * gmx_restrict xp,
761         const real * gmx_restrict bllen,
762         const real * gmx_restrict blc,
763         const t_pbc *             pbc,
764         real                      wfac,
765         real * gmx_restrict       rhs,
766         real * gmx_restrict       sol,
767         gmx_bool *                bWarn)
768 {
769     int b;
770
771     for (b = b0; b < b1; b++)
772     {
773         real len, len2, dlen2, mvb;
774         rvec dx;
775
776         len = bllen[b];
777         if (pbc)
778         {
779             pbc_dx_aiuc(pbc, xp[bla[2*b]], xp[bla[2*b+1]], dx);
780         }
781         else
782         {
783             rvec_sub(xp[bla[2*b]], xp[bla[2*b+1]], dx);
784         }
785         len2  = len*len;
786         dlen2 = 2*len2 - norm2(dx);
787         if (dlen2 < wfac*len2)
788         {
789             /* not race free - see detailed comment in caller */
790             *bWarn = TRUE;
791         }
792         if (dlen2 > 0)
793         {
794             mvb = blc[b]*(len - dlen2*gmx::invsqrt(dlen2));
795         }
796         else
797         {
798             mvb = blc[b]*len;
799         }
800         rhs[b]  = mvb;
801         sol[b]  = mvb;
802     } /* 20*ncons flops */
803 }
804
805 #if GMX_SIMD_HAVE_REAL
806 /* As the function above, but using SIMD intrinsics */
807 static void gmx_simdcall
808 calc_dist_iter_simd(int                       b0,
809                     int                       b1,
810                     const int *               bla,
811                     const rvec * gmx_restrict x,
812                     const real * gmx_restrict bllen,
813                     const real * gmx_restrict blc,
814                     const real *              pbc_simd,
815                     real                      wfac,
816                     real * gmx_restrict       rhs,
817                     real * gmx_restrict       sol,
818                     gmx_bool *                bWarn)
819 {
820     SimdReal        min_S(GMX_REAL_MIN);
821     SimdReal        two_S(2.0);
822     SimdReal        wfac_S(wfac);
823     SimdBool        warn_S;
824
825     int             bs;
826
827     assert(b0 % GMX_SIMD_REAL_WIDTH == 0);
828
829     /* Initialize all to FALSE */
830     warn_S = (two_S < setZero());
831
832     for (bs = b0; bs < b1; bs += GMX_SIMD_REAL_WIDTH)
833     {
834         SimdReal x0_S, y0_S, z0_S;
835         SimdReal x1_S, y1_S, z1_S;
836         SimdReal rx_S, ry_S, rz_S, n2_S;
837         SimdReal len_S, len2_S, dlen2_S, lc_S, blc_S;
838         alignas(GMX_SIMD_ALIGNMENT) std::int32_t      offset0[GMX_SIMD_REAL_WIDTH];
839         alignas(GMX_SIMD_ALIGNMENT) std::int32_t      offset1[GMX_SIMD_REAL_WIDTH];
840
841         for (int i = 0; i < GMX_SIMD_REAL_WIDTH; i++)
842         {
843             offset0[i] = bla[bs*2 + i*2];
844             offset1[i] = bla[bs*2 + i*2 + 1];
845         }
846
847         gatherLoadUTranspose<3>(reinterpret_cast<const real *>(x), offset0, &x0_S, &y0_S, &z0_S);
848         gatherLoadUTranspose<3>(reinterpret_cast<const real *>(x), offset1, &x1_S, &y1_S, &z1_S);
849         rx_S = x0_S - x1_S;
850         ry_S = y0_S - y1_S;
851         rz_S = z0_S - z1_S;
852
853         pbc_correct_dx_simd(&rx_S, &ry_S, &rz_S, pbc_simd);
854
855         n2_S    = norm2(rx_S, ry_S, rz_S);
856
857         len_S   = load<SimdReal>(bllen + bs);
858         len2_S  = len_S * len_S;
859
860         dlen2_S = fms(two_S, len2_S, n2_S);
861
862         warn_S  = warn_S || (dlen2_S < (wfac_S * len2_S));
863
864         /* Avoid 1/0 by taking the max with REAL_MIN.
865          * Note: when dlen2 is close to zero (90 degree constraint rotation),
866          * the accuracy of the algorithm is no longer relevant.
867          */
868         dlen2_S = max(dlen2_S, min_S);
869
870         lc_S    = fnma(dlen2_S, invsqrt(dlen2_S), len_S);
871
872         blc_S   = load<SimdReal>(blc + bs);
873
874         lc_S    = blc_S * lc_S;
875
876         store(rhs + bs, lc_S);
877         store(sol + bs, lc_S);
878     }
879
880     if (anyTrue(warn_S))
881     {
882         *bWarn = TRUE;
883     }
884 }
885 #endif // GMX_SIMD_HAVE_REAL
886
887 static void do_lincs(rvec *x, rvec *xp, matrix box, t_pbc *pbc,
888                      struct gmx_lincsdata *lincsd, int th,
889                      const real *invmass,
890                      t_commrec *cr,
891                      gmx_bool bCalcDHDL,
892                      real wangle, gmx_bool *bWarn,
893                      real invdt, rvec * gmx_restrict v,
894                      gmx_bool bCalcVir, tensor vir_r_m_dr)
895 {
896     int      b0, b1, b, i, j, n, iter;
897     int     *bla, *blnr, *blbnb;
898     rvec    *r;
899     real    *blc, *blmf, *bllen, *blcc, *rhs1, *rhs2, *sol, *blc_sol, *mlambda;
900     int     *nlocat;
901
902     b0 = lincsd->task[th].b0;
903     b1 = lincsd->task[th].b1;
904
905     bla     = lincsd->bla;
906     r       = lincsd->tmpv;
907     blnr    = lincsd->blnr;
908     blbnb   = lincsd->blbnb;
909     blc     = lincsd->blc;
910     blmf    = lincsd->blmf;
911     bllen   = lincsd->bllen;
912     blcc    = lincsd->tmpncc;
913     rhs1    = lincsd->tmp1;
914     rhs2    = lincsd->tmp2;
915     sol     = lincsd->tmp3;
916     blc_sol = lincsd->tmp4;
917     mlambda = lincsd->mlambda;
918     nlocat  = lincsd->nlocat;
919
920 #if GMX_SIMD_HAVE_REAL
921
922     /* This SIMD code does the same as the plain-C code after the #else.
923      * The only difference is that we always call pbc code, as with SIMD
924      * the overhead of pbc computation (when not needed) is small.
925      */
926     alignas(GMX_SIMD_ALIGNMENT) real    pbc_simd[9*GMX_SIMD_REAL_WIDTH];
927
928     /* Convert the pbc struct for SIMD */
929     set_pbc_simd(pbc, pbc_simd);
930
931     /* Compute normalized x i-j vectors, store in r.
932      * Compute the inner product of r and xp i-j and store in rhs1.
933      */
934     calc_dr_x_xp_simd(b0, b1, bla, x, xp, bllen, blc,
935                       pbc_simd,
936                       r, rhs1, sol);
937
938 #else // GMX_SIMD_HAVE_REAL
939
940     if (pbc)
941     {
942         /* Compute normalized i-j vectors */
943         for (b = b0; b < b1; b++)
944         {
945             rvec dx;
946             real mvb;
947
948             pbc_dx_aiuc(pbc, x[bla[2*b]], x[bla[2*b+1]], dx);
949             unitv(dx, r[b]);
950
951             pbc_dx_aiuc(pbc, xp[bla[2*b]], xp[bla[2*b+1]], dx);
952             mvb     = blc[b]*(iprod(r[b], dx) - bllen[b]);
953             rhs1[b] = mvb;
954             sol[b]  = mvb;
955         }
956     }
957     else
958     {
959         /* Compute normalized i-j vectors */
960         for (b = b0; b < b1; b++)
961         {
962             real tmp0, tmp1, tmp2, rlen, mvb;
963
964             i       = bla[2*b];
965             j       = bla[2*b+1];
966             tmp0    = x[i][0] - x[j][0];
967             tmp1    = x[i][1] - x[j][1];
968             tmp2    = x[i][2] - x[j][2];
969             rlen    = gmx::invsqrt(tmp0*tmp0 + tmp1*tmp1 + tmp2*tmp2);
970             r[b][0] = rlen*tmp0;
971             r[b][1] = rlen*tmp1;
972             r[b][2] = rlen*tmp2;
973             /* 16 ncons flops */
974
975             i       = bla[2*b];
976             j       = bla[2*b+1];
977             mvb     = blc[b]*(r[b][0]*(xp[i][0] - xp[j][0]) +
978                               r[b][1]*(xp[i][1] - xp[j][1]) +
979                               r[b][2]*(xp[i][2] - xp[j][2]) - bllen[b]);
980             rhs1[b] = mvb;
981             sol[b]  = mvb;
982             /* 10 flops */
983         }
984         /* Together: 26*ncons + 6*nrtot flops */
985     }
986
987 #endif // GMX_SIMD_HAVE_REAL
988
989     if (lincsd->bTaskDep)
990     {
991         /* We need a barrier, since the matrix construction below
992          * can access entries in r of other threads.
993          */
994 #pragma omp barrier
995     }
996
997     /* Construct the (sparse) LINCS matrix */
998     for (b = b0; b < b1; b++)
999     {
1000         for (n = blnr[b]; n < blnr[b+1]; n++)
1001         {
1002             blcc[n] = blmf[n]*iprod(r[b], r[blbnb[n]]);
1003         }
1004     }
1005     /* Together: 26*ncons + 6*nrtot flops */
1006
1007     lincs_matrix_expand(lincsd, &lincsd->task[th], blcc, rhs1, rhs2, sol);
1008     /* nrec*(ncons+2*nrtot) flops */
1009
1010 #if GMX_SIMD_HAVE_REAL
1011     for (b = b0; b < b1; b += GMX_SIMD_REAL_WIDTH)
1012     {
1013         SimdReal t1 = load<SimdReal>(blc + b);
1014         SimdReal t2 = load<SimdReal>(sol + b);
1015         store(mlambda + b, t1 * t2);
1016     }
1017 #else
1018     for (b = b0; b < b1; b++)
1019     {
1020         mlambda[b] = blc[b]*sol[b];
1021     }
1022 #endif // GMX_SIMD_HAVE_REAL
1023
1024     /* Update the coordinates */
1025     lincs_update_atoms(lincsd, th, 1.0, mlambda, r, invmass, xp);
1026
1027     /*
1028      ********  Correction for centripetal effects  ********
1029      */
1030
1031     real wfac;
1032
1033     wfac = std::cos(DEG2RAD*wangle);
1034     wfac = wfac*wfac;
1035
1036     for (iter = 0; iter < lincsd->nIter; iter++)
1037     {
1038         if ((lincsd->bCommIter && DOMAINDECOMP(cr) && cr->dd->constraints))
1039         {
1040 #pragma omp barrier
1041 #pragma omp master
1042             {
1043                 /* Communicate the corrected non-local coordinates */
1044                 if (DOMAINDECOMP(cr))
1045                 {
1046                     dd_move_x_constraints(cr->dd, box, xp, nullptr, FALSE);
1047                 }
1048             }
1049 #pragma omp barrier
1050         }
1051         else if (lincsd->bTaskDep)
1052         {
1053 #pragma omp barrier
1054         }
1055
1056 #if GMX_SIMD_HAVE_REAL
1057         calc_dist_iter_simd(b0, b1, bla, xp, bllen, blc, pbc_simd, wfac,
1058                             rhs1, sol, bWarn);
1059 #else
1060         calc_dist_iter(b0, b1, bla, xp, bllen, blc, pbc, wfac,
1061                        rhs1, sol, bWarn);
1062         /* 20*ncons flops */
1063 #endif  // GMX_SIMD_HAVE_REAL
1064
1065         lincs_matrix_expand(lincsd, &lincsd->task[th], blcc, rhs1, rhs2, sol);
1066         /* nrec*(ncons+2*nrtot) flops */
1067
1068 #if GMX_SIMD_HAVE_REAL
1069         for (b = b0; b < b1; b += GMX_SIMD_REAL_WIDTH)
1070         {
1071             SimdReal t1  = load<SimdReal>(blc + b);
1072             SimdReal t2  = load<SimdReal>(sol + b);
1073             SimdReal mvb = t1 * t2;
1074             store(blc_sol + b, mvb);
1075             store(mlambda + b, load<SimdReal>(mlambda + b) + mvb);
1076         }
1077 #else
1078         for (b = b0; b < b1; b++)
1079         {
1080             real mvb;
1081
1082             mvb         = blc[b]*sol[b];
1083             blc_sol[b]  = mvb;
1084             mlambda[b] += mvb;
1085         }
1086 #endif  // GMX_SIMD_HAVE_REAL
1087
1088         /* Update the coordinates */
1089         lincs_update_atoms(lincsd, th, 1.0, blc_sol, r, invmass, xp);
1090     }
1091     /* nit*ncons*(37+9*nrec) flops */
1092
1093     if (v != nullptr)
1094     {
1095         /* Update the velocities */
1096         lincs_update_atoms(lincsd, th, invdt, mlambda, r, invmass, v);
1097         /* 16 ncons flops */
1098     }
1099
1100     if (nlocat != nullptr && (bCalcDHDL || bCalcVir))
1101     {
1102         if (lincsd->bTaskDep)
1103         {
1104             /* In lincs_update_atoms threads might cross-read mlambda */
1105 #pragma omp barrier
1106         }
1107
1108         /* Only account for local atoms */
1109         for (b = b0; b < b1; b++)
1110         {
1111             mlambda[b] *= 0.5*nlocat[b];
1112         }
1113     }
1114
1115     if (bCalcDHDL)
1116     {
1117         real dhdl;
1118
1119         dhdl = 0;
1120         for (b = b0; b < b1; b++)
1121         {
1122             /* Note that this this is dhdl*dt^2, the dt^2 factor is corrected
1123              * later after the contributions are reduced over the threads.
1124              */
1125             dhdl -= lincsd->mlambda[b]*lincsd->ddist[b];
1126         }
1127         lincsd->task[th].dhdlambda = dhdl;
1128     }
1129
1130     if (bCalcVir)
1131     {
1132         /* Constraint virial */
1133         for (b = b0; b < b1; b++)
1134         {
1135             real tmp0, tmp1;
1136
1137             tmp0 = -bllen[b]*mlambda[b];
1138             for (i = 0; i < DIM; i++)
1139             {
1140                 tmp1 = tmp0*r[b][i];
1141                 for (j = 0; j < DIM; j++)
1142                 {
1143                     vir_r_m_dr[i][j] -= tmp1*r[b][j];
1144                 }
1145             }
1146         } /* 22 ncons flops */
1147     }
1148
1149     /* Total:
1150      * 26*ncons + 6*nrtot + nrec*(ncons+2*nrtot)
1151      * + nit * (20*ncons + nrec*(ncons+2*nrtot) + 17 ncons)
1152      *
1153      * (26+nrec)*ncons + (6+2*nrec)*nrtot
1154      * + nit * ((37+nrec)*ncons + 2*nrec*nrtot)
1155      * if nit=1
1156      * (63+nrec)*ncons + (6+4*nrec)*nrtot
1157      */
1158 }
1159
1160 /* Sets the elements in the LINCS matrix for task li_task */
1161 static void set_lincs_matrix_task(struct gmx_lincsdata *li,
1162                                   lincs_task_t         *li_task,
1163                                   const real           *invmass,
1164                                   int                  *ncc_triangle,
1165                                   int                  *nCrossTaskTriangles)
1166 {
1167     int        i;
1168
1169     /* Construct the coupling coefficient matrix blmf */
1170     li_task->ntriangle   = 0;
1171     *ncc_triangle        = 0;
1172     *nCrossTaskTriangles = 0;
1173     for (i = li_task->b0; i < li_task->b1; i++)
1174     {
1175         int a1, a2, n;
1176
1177         a1 = li->bla[2*i];
1178         a2 = li->bla[2*i+1];
1179         for (n = li->blnr[i]; (n < li->blnr[i+1]); n++)
1180         {
1181             int k, sign, center, end;
1182
1183             k = li->blbnb[n];
1184
1185             /* If we are using multiple, independent tasks for LINCS,
1186              * the calls to check_assign_connected should have
1187              * put all connected constraints in our task.
1188              */
1189             assert(li->bTaskDep || (k >= li_task->b0 && k < li_task->b1));
1190
1191             if (a1 == li->bla[2*k] || a2 == li->bla[2*k+1])
1192             {
1193                 sign = -1;
1194             }
1195             else
1196             {
1197                 sign = 1;
1198             }
1199             if (a1 == li->bla[2*k] || a1 == li->bla[2*k+1])
1200             {
1201                 center = a1;
1202                 end    = a2;
1203             }
1204             else
1205             {
1206                 center = a2;
1207                 end    = a1;
1208             }
1209             li->blmf[n]  = sign*invmass[center]*li->blc[i]*li->blc[k];
1210             li->blmf1[n] = sign*0.5;
1211             if (li->ncg_triangle > 0)
1212             {
1213                 int nk, kk;
1214
1215                 /* Look for constraint triangles */
1216                 for (nk = li->blnr[k]; (nk < li->blnr[k+1]); nk++)
1217                 {
1218                     kk = li->blbnb[nk];
1219                     if (kk != i && kk != k &&
1220                         (li->bla[2*kk] == end || li->bla[2*kk+1] == end))
1221                     {
1222                         /* Check if the constraints in this triangle actually
1223                          * belong to a different task. We still assign them
1224                          * here, since it's convenient for the triangle
1225                          * iterations, but we then need an extra barrier.
1226                          */
1227                         if (k  < li_task->b0 || k  >= li_task->b1 ||
1228                             kk < li_task->b0 || kk >= li_task->b1)
1229                         {
1230                             (*nCrossTaskTriangles)++;
1231                         }
1232
1233                         if (li_task->ntriangle == 0 ||
1234                             li_task->triangle[li_task->ntriangle - 1] < i)
1235                         {
1236                             /* Add this constraint to the triangle list */
1237                             li_task->triangle[li_task->ntriangle] = i;
1238                             li_task->tri_bits[li_task->ntriangle] = 0;
1239                             li_task->ntriangle++;
1240                             if (li->blnr[i+1] - li->blnr[i] > static_cast<int>(sizeof(li_task->tri_bits[0])*8 - 1))
1241                             {
1242                                 gmx_fatal(FARGS, "A constraint is connected to %d constraints, this is more than the %d allowed for constraints participating in triangles",
1243                                           li->blnr[i+1] - li->blnr[i],
1244                                           sizeof(li_task->tri_bits[0])*8-1);
1245                             }
1246                         }
1247                         li_task->tri_bits[li_task->ntriangle-1] |= (1 << (n - li->blnr[i]));
1248                         (*ncc_triangle)++;
1249                     }
1250                 }
1251             }
1252         }
1253     }
1254 }
1255
1256 /* Sets the elements in the LINCS matrix */
1257 static void set_lincs_matrix(struct gmx_lincsdata *li, real *invmass, real lambda)
1258 {
1259     int        i;
1260     const real invsqrt2 = 0.7071067811865475244;
1261
1262     for (i = 0; (i < li->nc); i++)
1263     {
1264         int a1, a2;
1265
1266         a1          = li->bla[2*i];
1267         a2          = li->bla[2*i+1];
1268         li->blc[i]  = gmx::invsqrt(invmass[a1] + invmass[a2]);
1269         li->blc1[i] = invsqrt2;
1270     }
1271
1272     /* Construct the coupling coefficient matrix blmf */
1273     int th, ntriangle = 0, ncc_triangle = 0, nCrossTaskTriangles = 0;
1274 #pragma omp parallel for reduction(+: ntriangle, ncc_triangle, nCrossTaskTriangles) num_threads(li->ntask) schedule(static)
1275     for (th = 0; th < li->ntask; th++)
1276     {
1277         try
1278         {
1279             set_lincs_matrix_task(li, &li->task[th], invmass,
1280                                   &ncc_triangle, &nCrossTaskTriangles);
1281             ntriangle = li->task[th].ntriangle;
1282         }
1283         GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
1284     }
1285     li->ntriangle    = ntriangle;
1286     li->ncc_triangle = ncc_triangle;
1287     li->bTaskDepTri  = (nCrossTaskTriangles > 0);
1288
1289     if (debug)
1290     {
1291         fprintf(debug, "The %d constraints participate in %d triangles\n",
1292                 li->nc, li->ntriangle);
1293         fprintf(debug, "There are %d constraint couplings, of which %d in triangles\n",
1294                 li->ncc, li->ncc_triangle);
1295         if (li->ntriangle > 0 && li->ntask > 1)
1296         {
1297             fprintf(debug, "%d constraint triangles contain constraints assigned to different tasks\n",
1298                     nCrossTaskTriangles);
1299         }
1300     }
1301
1302     /* Set matlam,
1303      * so we know with which lambda value the masses have been set.
1304      */
1305     li->matlam = lambda;
1306 }
1307
1308 static int count_triangle_constraints(const t_ilist  *ilist,
1309                                       const t_blocka *at2con)
1310 {
1311     int      ncon1, ncon_tot;
1312     int      c0, a00, a01, n1, c1, a10, a11, ac1, n2, c2, a20, a21;
1313     int      ncon_triangle;
1314     gmx_bool bTriangle;
1315     t_iatom *ia1, *ia2, *iap;
1316
1317     ncon1    = ilist[F_CONSTR].nr/3;
1318     ncon_tot = ncon1 + ilist[F_CONSTRNC].nr/3;
1319
1320     ia1 = ilist[F_CONSTR].iatoms;
1321     ia2 = ilist[F_CONSTRNC].iatoms;
1322
1323     ncon_triangle = 0;
1324     for (c0 = 0; c0 < ncon_tot; c0++)
1325     {
1326         bTriangle = FALSE;
1327         iap       = constr_iatomptr(ncon1, ia1, ia2, c0);
1328         a00       = iap[1];
1329         a01       = iap[2];
1330         for (n1 = at2con->index[a01]; n1 < at2con->index[a01+1]; n1++)
1331         {
1332             c1 = at2con->a[n1];
1333             if (c1 != c0)
1334             {
1335                 iap = constr_iatomptr(ncon1, ia1, ia2, c1);
1336                 a10 = iap[1];
1337                 a11 = iap[2];
1338                 if (a10 == a01)
1339                 {
1340                     ac1 = a11;
1341                 }
1342                 else
1343                 {
1344                     ac1 = a10;
1345                 }
1346                 for (n2 = at2con->index[ac1]; n2 < at2con->index[ac1+1]; n2++)
1347                 {
1348                     c2 = at2con->a[n2];
1349                     if (c2 != c0 && c2 != c1)
1350                     {
1351                         iap = constr_iatomptr(ncon1, ia1, ia2, c2);
1352                         a20 = iap[1];
1353                         a21 = iap[2];
1354                         if (a20 == a00 || a21 == a00)
1355                         {
1356                             bTriangle = TRUE;
1357                         }
1358                     }
1359                 }
1360             }
1361         }
1362         if (bTriangle)
1363         {
1364             ncon_triangle++;
1365         }
1366     }
1367
1368     return ncon_triangle;
1369 }
1370
1371 static gmx_bool more_than_two_sequential_constraints(const t_ilist  *ilist,
1372                                                      const t_blocka *at2con)
1373 {
1374     t_iatom  *ia1, *ia2, *iap;
1375     int       ncon1, ncon_tot, c;
1376     int       a1, a2;
1377     gmx_bool  bMoreThanTwoSequentialConstraints;
1378
1379     ncon1    = ilist[F_CONSTR].nr/3;
1380     ncon_tot = ncon1 + ilist[F_CONSTRNC].nr/3;
1381
1382     ia1 = ilist[F_CONSTR].iatoms;
1383     ia2 = ilist[F_CONSTRNC].iatoms;
1384
1385     bMoreThanTwoSequentialConstraints = FALSE;
1386     for (c = 0; c < ncon_tot && !bMoreThanTwoSequentialConstraints; c++)
1387     {
1388         iap = constr_iatomptr(ncon1, ia1, ia2, c);
1389         a1  = iap[1];
1390         a2  = iap[2];
1391         /* Check if this constraint has constraints connected at both atoms */
1392         if (at2con->index[a1+1] - at2con->index[a1] > 1 &&
1393             at2con->index[a2+1] - at2con->index[a2] > 1)
1394         {
1395             bMoreThanTwoSequentialConstraints = TRUE;
1396         }
1397     }
1398
1399     return bMoreThanTwoSequentialConstraints;
1400 }
1401
1402 static int int_comp(const void *a, const void *b)
1403 {
1404     return (*(int *)a) - (*(int *)b);
1405 }
1406
1407 gmx_lincsdata_t init_lincs(FILE *fplog, const gmx_mtop_t *mtop,
1408                            int nflexcon_global, const t_blocka *at2con,
1409                            gmx_bool bPLINCS, int nIter, int nProjOrder)
1410 {
1411     struct gmx_lincsdata *li;
1412     int                   mt, mb;
1413     gmx_moltype_t        *molt;
1414     gmx_bool              bMoreThanTwoSeq;
1415
1416     if (fplog)
1417     {
1418         fprintf(fplog, "\nInitializing%s LINear Constraint Solver\n",
1419                 bPLINCS ? " Parallel" : "");
1420     }
1421
1422     snew(li, 1);
1423
1424     li->ncg      =
1425         gmx_mtop_ftype_count(mtop, F_CONSTR) +
1426         gmx_mtop_ftype_count(mtop, F_CONSTRNC);
1427     li->ncg_flex = nflexcon_global;
1428
1429     li->nIter  = nIter;
1430     li->nOrder = nProjOrder;
1431
1432     li->max_connect = 0;
1433     for (mt = 0; mt < mtop->nmoltype; mt++)
1434     {
1435         int a;
1436
1437         molt = &mtop->moltype[mt];
1438         for (a = 0; a < molt->atoms.nr; a++)
1439         {
1440             li->max_connect = std::max(li->max_connect,
1441                                        at2con[mt].index[a + 1] - at2con[mt].index[a]);
1442         }
1443     }
1444
1445     li->ncg_triangle = 0;
1446     bMoreThanTwoSeq  = FALSE;
1447     for (mb = 0; mb < mtop->nmolblock; mb++)
1448     {
1449         molt              = &mtop->moltype[mtop->molblock[mb].type];
1450
1451         li->ncg_triangle +=
1452             mtop->molblock[mb].nmol*
1453             count_triangle_constraints(molt->ilist,
1454                                        &at2con[mtop->molblock[mb].type]);
1455
1456         if (!bMoreThanTwoSeq &&
1457             more_than_two_sequential_constraints(molt->ilist, &at2con[mtop->molblock[mb].type]))
1458         {
1459             bMoreThanTwoSeq = TRUE;
1460         }
1461     }
1462
1463     /* Check if we need to communicate not only before LINCS,
1464      * but also before each iteration.
1465      * The check for only two sequential constraints is only
1466      * useful for the common case of H-bond only constraints.
1467      * With more effort we could also make it useful for small
1468      * molecules with nr. sequential constraints <= nOrder-1.
1469      */
1470     li->bCommIter = (bPLINCS && (li->nOrder < 1 || bMoreThanTwoSeq));
1471
1472     if (debug && bPLINCS)
1473     {
1474         fprintf(debug, "PLINCS communication before each iteration: %d\n",
1475                 li->bCommIter);
1476     }
1477
1478     /* LINCS can run on any number of threads.
1479      * Currently the number is fixed for the whole simulation,
1480      * but it could be set in set_lincs().
1481      * The current constraint to task assignment code can create independent
1482      * tasks only when not more than two constraints are connected sequentially.
1483      */
1484     li->ntask    = gmx_omp_nthreads_get(emntLINCS);
1485     li->bTaskDep = (li->ntask > 1 && bMoreThanTwoSeq);
1486     if (debug)
1487     {
1488         fprintf(debug, "LINCS: using %d threads, tasks are %sdependent\n",
1489                 li->ntask, li->bTaskDep ? "" : "in");
1490     }
1491     if (li->ntask == 1)
1492     {
1493         snew(li->task, 1);
1494     }
1495     else
1496     {
1497         /* Allocate an extra elements for "task-overlap" constraints */
1498         snew(li->task, li->ntask + 1);
1499     }
1500
1501     if (bPLINCS || li->ncg_triangle > 0)
1502     {
1503         please_cite(fplog, "Hess2008a");
1504     }
1505     else
1506     {
1507         please_cite(fplog, "Hess97a");
1508     }
1509
1510     if (fplog)
1511     {
1512         fprintf(fplog, "The number of constraints is %d\n", li->ncg);
1513         if (bPLINCS)
1514         {
1515             fprintf(fplog, "There are inter charge-group constraints,\n"
1516                     "will communicate selected coordinates each lincs iteration\n");
1517         }
1518         if (li->ncg_triangle > 0)
1519         {
1520             fprintf(fplog,
1521                     "%d constraints are involved in constraint triangles,\n"
1522                     "will apply an additional matrix expansion of order %d for couplings\n"
1523                     "between constraints inside triangles\n",
1524                     li->ncg_triangle, li->nOrder);
1525         }
1526     }
1527
1528     return li;
1529 }
1530
1531 /* Sets up the work division over the threads */
1532 static void lincs_thread_setup(struct gmx_lincsdata *li, int natoms)
1533 {
1534     lincs_task_t   *li_m;
1535     int             th;
1536     gmx_bitmask_t  *atf;
1537     int             a;
1538
1539     if (natoms > li->atf_nalloc)
1540     {
1541         li->atf_nalloc = over_alloc_large(natoms);
1542         srenew(li->atf, li->atf_nalloc);
1543     }
1544
1545     atf = li->atf;
1546     /* Clear the atom flags */
1547     for (a = 0; a < natoms; a++)
1548     {
1549         bitmask_clear(&atf[a]);
1550     }
1551
1552     if (li->ntask > BITMASK_SIZE)
1553     {
1554         gmx_fatal(FARGS, "More than %d threads is not supported for LINCS.", BITMASK_SIZE);
1555     }
1556
1557     for (th = 0; th < li->ntask; th++)
1558     {
1559         lincs_task_t *li_task;
1560         int           b;
1561
1562         li_task = &li->task[th];
1563
1564         /* For each atom set a flag for constraints from each */
1565         for (b = li_task->b0; b < li_task->b1; b++)
1566         {
1567             bitmask_set_bit(&atf[li->bla[b*2    ]], th);
1568             bitmask_set_bit(&atf[li->bla[b*2 + 1]], th);
1569         }
1570     }
1571
1572 #pragma omp parallel for num_threads(li->ntask) schedule(static)
1573     for (th = 0; th < li->ntask; th++)
1574     {
1575         try
1576         {
1577             lincs_task_t  *li_task;
1578             gmx_bitmask_t  mask;
1579             int            b;
1580
1581             li_task = &li->task[th];
1582
1583             if (li_task->b1 - li_task->b0 > li_task->ind_nalloc)
1584             {
1585                 li_task->ind_nalloc = over_alloc_large(li_task->b1-li_task->b0);
1586                 srenew(li_task->ind, li_task->ind_nalloc);
1587                 srenew(li_task->ind_r, li_task->ind_nalloc);
1588             }
1589
1590             bitmask_init_low_bits(&mask, th);
1591
1592             li_task->nind   = 0;
1593             li_task->nind_r = 0;
1594             for (b = li_task->b0; b < li_task->b1; b++)
1595             {
1596                 /* We let the constraint with the lowest thread index
1597                  * operate on atoms with constraints from multiple threads.
1598                  */
1599                 if (bitmask_is_disjoint(atf[li->bla[b*2]], mask) &&
1600                     bitmask_is_disjoint(atf[li->bla[b*2+1]], mask))
1601                 {
1602                     /* Add the constraint to the local atom update index */
1603                     li_task->ind[li_task->nind++] = b;
1604                 }
1605                 else
1606                 {
1607                     /* Add the constraint to the rest block */
1608                     li_task->ind_r[li_task->nind_r++] = b;
1609                 }
1610             }
1611         }
1612         GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
1613     }
1614
1615     /* We need to copy all constraints which have not be assigned
1616      * to a thread to a separate list which will be handled by one thread.
1617      */
1618     li_m = &li->task[li->ntask];
1619
1620     li_m->nind = 0;
1621     for (th = 0; th < li->ntask; th++)
1622     {
1623         lincs_task_t *li_task;
1624         int           b;
1625
1626         li_task   = &li->task[th];
1627
1628         if (li_m->nind + li_task->nind_r > li_m->ind_nalloc)
1629         {
1630             li_m->ind_nalloc = over_alloc_large(li_m->nind+li_task->nind_r);
1631             srenew(li_m->ind, li_m->ind_nalloc);
1632         }
1633
1634         for (b = 0; b < li_task->nind_r; b++)
1635         {
1636             li_m->ind[li_m->nind++] = li_task->ind_r[b];
1637         }
1638
1639         if (debug)
1640         {
1641             fprintf(debug, "LINCS thread %d: %d constraints\n",
1642                     th, li_task->nind);
1643         }
1644     }
1645
1646     if (debug)
1647     {
1648         fprintf(debug, "LINCS thread r: %d constraints\n",
1649                 li_m->nind);
1650     }
1651 }
1652
1653 /* There is no realloc with alignment, so here we make one for reals.
1654  * Note that this function does not preserve the contents of the memory.
1655  */
1656 static void resize_real_aligned(real **ptr, int nelem)
1657 {
1658     sfree_aligned(*ptr);
1659     snew_aligned(*ptr, nelem, align_bytes);
1660 }
1661
1662 static void assign_constraint(struct gmx_lincsdata *li,
1663                               int constraint_index,
1664                               int a1, int a2,
1665                               real lenA, real lenB,
1666                               const t_blocka *at2con)
1667 {
1668     int con;
1669
1670     con = li->nc;
1671
1672     /* Make an mapping of local topology constraint index to LINCS index */
1673     li->con_index[constraint_index] = con;
1674
1675     li->bllen0[con]  = lenA;
1676     li->ddist[con]   = lenB - lenA;
1677     /* Set the length to the topology A length */
1678     li->bllen[con]   = lenA;
1679     li->bla[2*con]   = a1;
1680     li->bla[2*con+1] = a2;
1681
1682     /* Make space in the constraint connection matrix for constraints
1683      * connected to both end of the current constraint.
1684      */
1685     li->ncc +=
1686         at2con->index[a1 + 1] - at2con->index[a1] - 1 +
1687         at2con->index[a2 + 1] - at2con->index[a2] - 1;
1688
1689     li->blnr[con + 1] = li->ncc;
1690
1691     /* Increase the constraint count */
1692     li->nc++;
1693 }
1694
1695 /* Check if constraint with topology index constraint_index is connected
1696  * to other constraints, and if so add those connected constraints to our task.
1697  */
1698 static void check_assign_connected(struct gmx_lincsdata *li,
1699                                    const t_iatom *iatom,
1700                                    const t_idef *idef,
1701                                    int bDynamics,
1702                                    int a1, int a2,
1703                                    const t_blocka *at2con)
1704 {
1705     /* Currently this function only supports constraint groups
1706      * in which all constraints share at least one atom
1707      * (e.g. H-bond constraints).
1708      * Check both ends of the current constraint for
1709      * connected constraints. We need to assign those
1710      * to the same task.
1711      */
1712     int end;
1713
1714     for (end = 0; end < 2; end++)
1715     {
1716         int a, k;
1717
1718         a = (end == 0 ? a1 : a2);
1719
1720         for (k = at2con->index[a]; k < at2con->index[a + 1]; k++)
1721         {
1722             int cc;
1723
1724             cc = at2con->a[k];
1725             /* Check if constraint cc has not yet been assigned */
1726             if (li->con_index[cc] == -1)
1727             {
1728                 int  type;
1729                 real lenA, lenB;
1730
1731                 type = iatom[cc*3];
1732                 lenA = idef->iparams[type].constr.dA;
1733                 lenB = idef->iparams[type].constr.dB;
1734
1735                 if (bDynamics || lenA != 0 || lenB != 0)
1736                 {
1737                     assign_constraint(li, cc, iatom[3*cc + 1], iatom[3*cc + 2], lenA, lenB, at2con);
1738                 }
1739             }
1740         }
1741     }
1742 }
1743
1744 /* Check if constraint with topology index constraint_index is involved
1745  * in a constraint triangle, and if so add the other two constraints
1746  * in the triangle to our task.
1747  */
1748 static void check_assign_triangle(struct gmx_lincsdata *li,
1749                                   const t_iatom *iatom,
1750                                   const t_idef *idef,
1751                                   int bDynamics,
1752                                   int constraint_index,
1753                                   int a1, int a2,
1754                                   const t_blocka *at2con)
1755 {
1756     int nca, cc[32], ca[32], k;
1757     int c_triangle[2] = { -1, -1 };
1758
1759     nca = 0;
1760     for (k = at2con->index[a1]; k < at2con->index[a1 + 1]; k++)
1761     {
1762         int c;
1763
1764         c = at2con->a[k];
1765         if (c != constraint_index)
1766         {
1767             int aa1, aa2;
1768
1769             aa1 = iatom[c*3 + 1];
1770             aa2 = iatom[c*3 + 2];
1771             if (aa1 != a1)
1772             {
1773                 cc[nca] = c;
1774                 ca[nca] = aa1;
1775                 nca++;
1776             }
1777             if (aa2 != a1)
1778             {
1779                 cc[nca] = c;
1780                 ca[nca] = aa2;
1781                 nca++;
1782             }
1783         }
1784     }
1785
1786     for (k = at2con->index[a2]; k < at2con->index[a2 + 1]; k++)
1787     {
1788         int c;
1789
1790         c = at2con->a[k];
1791         if (c != constraint_index)
1792         {
1793             int aa1, aa2, i;
1794
1795             aa1 = iatom[c*3 + 1];
1796             aa2 = iatom[c*3 + 2];
1797             if (aa1 != a2)
1798             {
1799                 for (i = 0; i < nca; i++)
1800                 {
1801                     if (aa1 == ca[i])
1802                     {
1803                         c_triangle[0] = cc[i];
1804                         c_triangle[1] = c;
1805                     }
1806                 }
1807             }
1808             if (aa2 != a2)
1809             {
1810                 for (i = 0; i < nca; i++)
1811                 {
1812                     if (aa2 == ca[i])
1813                     {
1814                         c_triangle[0] = cc[i];
1815                         c_triangle[1] = c;
1816                     }
1817                 }
1818             }
1819         }
1820     }
1821
1822     if (c_triangle[0] >= 0)
1823     {
1824         int end;
1825
1826         for (end = 0; end < 2; end++)
1827         {
1828             /* Check if constraint c_triangle[end] has not yet been assigned */
1829             if (li->con_index[c_triangle[end]] == -1)
1830             {
1831                 int  i, type;
1832                 real lenA, lenB;
1833
1834                 i    = c_triangle[end]*3;
1835                 type = iatom[i];
1836                 lenA = idef->iparams[type].constr.dA;
1837                 lenB = idef->iparams[type].constr.dB;
1838
1839                 if (bDynamics || lenA != 0 || lenB != 0)
1840                 {
1841                     assign_constraint(li, c_triangle[end], iatom[i + 1], iatom[i + 2], lenA, lenB, at2con);
1842                 }
1843             }
1844         }
1845     }
1846 }
1847
1848 static void set_matrix_indices(struct gmx_lincsdata *li,
1849                                const lincs_task_t   *li_task,
1850                                const t_blocka       *at2con,
1851                                gmx_bool              bSortMatrix)
1852 {
1853     int b;
1854
1855     for (b = li_task->b0; b < li_task->b1; b++)
1856     {
1857         int a1, a2, i, k;
1858
1859         a1 = li->bla[b*2];
1860         a2 = li->bla[b*2 + 1];
1861
1862         i = li->blnr[b];
1863         for (k = at2con->index[a1]; k < at2con->index[a1 + 1]; k++)
1864         {
1865             int concon;
1866
1867             concon = li->con_index[at2con->a[k]];
1868             if (concon != b)
1869             {
1870                 li->blbnb[i++] = concon;
1871             }
1872         }
1873         for (k = at2con->index[a2]; k < at2con->index[a2 + 1]; k++)
1874         {
1875             int concon;
1876
1877             concon = li->con_index[at2con->a[k]];
1878             if (concon != b)
1879             {
1880                 li->blbnb[i++] = concon;
1881             }
1882         }
1883
1884         if (bSortMatrix)
1885         {
1886             /* Order the blbnb matrix to optimize memory access */
1887             qsort(&(li->blbnb[li->blnr[b]]), li->blnr[b + 1] - li->blnr[b],
1888                   sizeof(li->blbnb[0]), int_comp);
1889         }
1890     }
1891 }
1892
1893 void set_lincs(const t_idef         *idef,
1894                const t_mdatoms      *md,
1895                gmx_bool              bDynamics,
1896                t_commrec            *cr,
1897                struct gmx_lincsdata *li)
1898 {
1899     int          natoms, nflexcon;
1900     t_blocka     at2con;
1901     t_iatom     *iatom;
1902     int          i, ncc_alloc_old, ncon_tot;
1903
1904     li->nc_real = 0;
1905     li->nc      = 0;
1906     li->ncc     = 0;
1907     /* Zero the thread index ranges.
1908      * Otherwise without local constraints we could return with old ranges.
1909      */
1910     for (i = 0; i < li->ntask; i++)
1911     {
1912         li->task[i].b0   = 0;
1913         li->task[i].b1   = 0;
1914         li->task[i].nind = 0;
1915     }
1916     if (li->ntask > 1)
1917     {
1918         li->task[li->ntask].nind = 0;
1919     }
1920
1921     /* This is the local topology, so there are only F_CONSTR constraints */
1922     if (idef->il[F_CONSTR].nr == 0)
1923     {
1924         /* There are no constraints,
1925          * we do not need to fill any data structures.
1926          */
1927         return;
1928     }
1929
1930     if (debug)
1931     {
1932         fprintf(debug, "Building the LINCS connectivity\n");
1933     }
1934
1935     if (DOMAINDECOMP(cr))
1936     {
1937         if (cr->dd->constraints)
1938         {
1939             int start;
1940
1941             dd_get_constraint_range(cr->dd, &start, &natoms);
1942         }
1943         else
1944         {
1945             natoms = cr->dd->nat_home;
1946         }
1947     }
1948     else
1949     {
1950         natoms = md->homenr;
1951     }
1952     at2con = make_at2con(0, natoms, idef->il, idef->iparams, bDynamics,
1953                          &nflexcon);
1954
1955     ncon_tot = idef->il[F_CONSTR].nr/3;
1956
1957     /* Ensure we have enough padding for aligned loads for each thread */
1958     if (ncon_tot + li->ntask*simd_width > li->nc_alloc || li->nc_alloc == 0)
1959     {
1960         li->nc_alloc = over_alloc_dd(ncon_tot + li->ntask*simd_width);
1961         srenew(li->con_index, li->nc_alloc);
1962         resize_real_aligned(&li->bllen0, li->nc_alloc);
1963         resize_real_aligned(&li->ddist, li->nc_alloc);
1964         srenew(li->bla, 2*li->nc_alloc);
1965         resize_real_aligned(&li->blc, li->nc_alloc);
1966         resize_real_aligned(&li->blc1, li->nc_alloc);
1967         srenew(li->blnr, li->nc_alloc + 1);
1968         resize_real_aligned(&li->bllen, li->nc_alloc);
1969         srenew(li->tmpv, li->nc_alloc);
1970         if (DOMAINDECOMP(cr))
1971         {
1972             srenew(li->nlocat, li->nc_alloc);
1973         }
1974         resize_real_aligned(&li->tmp1, li->nc_alloc);
1975         resize_real_aligned(&li->tmp2, li->nc_alloc);
1976         resize_real_aligned(&li->tmp3, li->nc_alloc);
1977         resize_real_aligned(&li->tmp4, li->nc_alloc);
1978         resize_real_aligned(&li->mlambda, li->nc_alloc);
1979     }
1980
1981     iatom = idef->il[F_CONSTR].iatoms;
1982
1983     ncc_alloc_old = li->ncc_alloc;
1984     li->blnr[0]   = li->ncc;
1985
1986     /* Assign the constraints for li->ntask LINCS tasks.
1987      * We target a uniform distribution of constraints over the tasks.
1988      * Note that when flexible constraints are present, but are removed here
1989      * (e.g. because we are doing EM) we get imbalance, but since that doesn't
1990      * happen during normal MD, that's ok.
1991      */
1992     int ncon_assign, ncon_target, con, th;
1993
1994     /* Determine the number of constraints we need to assign here */
1995     ncon_assign      = ncon_tot;
1996     if (!bDynamics)
1997     {
1998         /* With energy minimization, flexible constraints are ignored
1999          * (and thus minimized, as they should be).
2000          */
2001         ncon_assign -= nflexcon;
2002     }
2003
2004     /* Set the target constraint count per task to exactly uniform,
2005      * this might be overridden below.
2006      */
2007     ncon_target = (ncon_assign + li->ntask - 1)/li->ntask;
2008
2009     /* Mark all constraints as unassigned by setting their index to -1 */
2010     for (con = 0; con < ncon_tot; con++)
2011     {
2012         li->con_index[con] = -1;
2013     }
2014
2015     con = 0;
2016     for (th = 0; th < li->ntask; th++)
2017     {
2018         lincs_task_t *li_task;
2019
2020         li_task = &li->task[th];
2021
2022 #if GMX_SIMD_HAVE_REAL
2023         /* With indepedent tasks we likely have H-bond constraints or constraint
2024          * pairs. The connected constraints will be pulled into the task, so the
2025          * constraints per task will often exceed ncon_target.
2026          * Triangle constraints can also increase the count, but there are
2027          * relatively few of those, so we usually expect to get ncon_target.
2028          */
2029         if (li->bTaskDep)
2030         {
2031             /* We round ncon_target to a multiple of GMX_SIMD_WIDTH,
2032              * since otherwise a lot of operations can be wasted.
2033              * There are several ways to round here, we choose the one
2034              * that alternates block sizes, which helps with Intel HT.
2035              */
2036             ncon_target = ((ncon_assign*(th + 1))/li->ntask - li->nc_real + GMX_SIMD_REAL_WIDTH - 1) & ~(GMX_SIMD_REAL_WIDTH - 1);
2037         }
2038 #endif  // GMX_SIMD==2 && GMX_SIMD_HAVE_REAL
2039
2040         /* Continue filling the arrays where we left off with the previous task,
2041          * including padding for SIMD.
2042          */
2043         li_task->b0 = li->nc;
2044
2045         while (con < ncon_tot && li->nc - li_task->b0 < ncon_target)
2046         {
2047             if (li->con_index[con] == -1)
2048             {
2049                 int  type, a1, a2;
2050                 real lenA, lenB;
2051
2052                 type   = iatom[3*con];
2053                 a1     = iatom[3*con + 1];
2054                 a2     = iatom[3*con + 2];
2055                 lenA   = idef->iparams[type].constr.dA;
2056                 lenB   = idef->iparams[type].constr.dB;
2057                 /* Skip the flexible constraints when not doing dynamics */
2058                 if (bDynamics || lenA != 0 || lenB != 0)
2059                 {
2060                     assign_constraint(li, con, a1, a2, lenA, lenB, &at2con);
2061
2062                     if (li->ntask > 1 && !li->bTaskDep)
2063                     {
2064                         /* We can generate independent tasks. Check if we
2065                          * need to assign connected constraints to our task.
2066                          */
2067                         check_assign_connected(li, iatom, idef, bDynamics,
2068                                                a1, a2, &at2con);
2069                     }
2070                     if (li->ntask > 1 && li->ncg_triangle > 0)
2071                     {
2072                         /* Ensure constraints in one triangle are assigned
2073                          * to the same task.
2074                          */
2075                         check_assign_triangle(li, iatom, idef, bDynamics,
2076                                               con, a1, a2, &at2con);
2077                     }
2078                 }
2079             }
2080
2081             con++;
2082         }
2083
2084         li_task->b1 = li->nc;
2085
2086         if (simd_width > 1)
2087         {
2088             /* Copy the last atom pair indices and lengths for constraints
2089              * up to a multiple of simd_width, such that we can do all
2090              * SIMD operations without having to worry about end effects.
2091              */
2092             int i, last;
2093
2094             li->nc = ((li_task->b1 + simd_width - 1)/simd_width)*simd_width;
2095             last   = li_task->b1 - 1;
2096             for (i = li_task->b1; i < li->nc; i++)
2097             {
2098                 li->bla[i*2    ] = li->bla[last*2    ];
2099                 li->bla[i*2 + 1] = li->bla[last*2 + 1];
2100                 li->bllen0[i]    = li->bllen0[last];
2101                 li->ddist[i]     = li->ddist[last];
2102                 li->bllen[i]     = li->bllen[last];
2103                 li->blnr[i + 1]  = li->blnr[last + 1];
2104             }
2105         }
2106
2107         /* Keep track of how many constraints we assigned */
2108         li->nc_real += li_task->b1 - li_task->b0;
2109
2110         if (debug)
2111         {
2112             fprintf(debug, "LINCS task %d constraints %d - %d\n",
2113                     th, li_task->b0, li_task->b1);
2114         }
2115     }
2116
2117     assert(li->nc_real == ncon_assign);
2118
2119     gmx_bool bSortMatrix;
2120
2121     /* Without DD we order the blbnb matrix to optimize memory access.
2122      * With DD the overhead of sorting is more than the gain during access.
2123      */
2124     bSortMatrix = !DOMAINDECOMP(cr);
2125
2126     if (li->ncc > li->ncc_alloc)
2127     {
2128         li->ncc_alloc = over_alloc_small(li->ncc);
2129         srenew(li->blbnb, li->ncc_alloc);
2130     }
2131
2132 #pragma omp parallel for num_threads(li->ntask) schedule(static)
2133     for (th = 0; th < li->ntask; th++)
2134     {
2135         try
2136         {
2137             lincs_task_t *li_task;
2138
2139             li_task = &li->task[th];
2140
2141             if (li->ncg_triangle > 0 &&
2142                 li_task->b1 - li_task->b0 > li_task->tri_alloc)
2143             {
2144                 /* This is allocating too much, but it is difficult to improve */
2145                 li_task->tri_alloc = over_alloc_dd(li_task->b1 - li_task->b0);
2146                 srenew(li_task->triangle, li_task->tri_alloc);
2147                 srenew(li_task->tri_bits, li_task->tri_alloc);
2148             }
2149
2150             set_matrix_indices(li, li_task, &at2con, bSortMatrix);
2151         }
2152         GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
2153     }
2154
2155     done_blocka(&at2con);
2156
2157     if (cr->dd == nullptr)
2158     {
2159         /* Since the matrix is static, we should free some memory */
2160         li->ncc_alloc = li->ncc;
2161         srenew(li->blbnb, li->ncc_alloc);
2162     }
2163
2164     if (li->ncc_alloc > ncc_alloc_old)
2165     {
2166         srenew(li->blmf, li->ncc_alloc);
2167         srenew(li->blmf1, li->ncc_alloc);
2168         srenew(li->tmpncc, li->ncc_alloc);
2169     }
2170
2171     if (DOMAINDECOMP(cr) && dd_constraints_nlocalatoms(cr->dd) != nullptr)
2172     {
2173         int *nlocat_dd;
2174
2175         nlocat_dd = dd_constraints_nlocalatoms(cr->dd);
2176
2177         /* Convert nlocat from local topology to LINCS constraint indexing */
2178         for (con = 0; con < ncon_tot; con++)
2179         {
2180             li->nlocat[li->con_index[con]] = nlocat_dd[con];
2181         }
2182     }
2183     else
2184     {
2185         li->nlocat = nullptr;
2186     }
2187
2188     if (debug)
2189     {
2190         fprintf(debug, "Number of constraints is %d, padded %d, couplings %d\n",
2191                 li->nc_real, li->nc, li->ncc);
2192     }
2193
2194     if (li->ntask > 1)
2195     {
2196         lincs_thread_setup(li, md->nr);
2197     }
2198
2199     set_lincs_matrix(li, md->invmass, md->lambda);
2200 }
2201
2202 static void lincs_warning(FILE *fplog,
2203                           gmx_domdec_t *dd, rvec *x, rvec *xprime, t_pbc *pbc,
2204                           int ncons, int *bla, real *bllen, real wangle,
2205                           int maxwarn, int *warncount)
2206 {
2207     int  b, i, j;
2208     rvec v0, v1;
2209     real wfac, d0, d1, cosine;
2210     char buf[STRLEN];
2211
2212     wfac = std::cos(DEG2RAD*wangle);
2213
2214     sprintf(buf, "bonds that rotated more than %g degrees:\n"
2215             " atom 1 atom 2  angle  previous, current, constraint length\n",
2216             wangle);
2217     fprintf(stderr, "%s", buf);
2218     if (fplog)
2219     {
2220         fprintf(fplog, "%s", buf);
2221     }
2222
2223     for (b = 0; b < ncons; b++)
2224     {
2225         i = bla[2*b];
2226         j = bla[2*b+1];
2227         if (pbc)
2228         {
2229             pbc_dx_aiuc(pbc, x[i], x[j], v0);
2230             pbc_dx_aiuc(pbc, xprime[i], xprime[j], v1);
2231         }
2232         else
2233         {
2234             rvec_sub(x[i], x[j], v0);
2235             rvec_sub(xprime[i], xprime[j], v1);
2236         }
2237         d0     = norm(v0);
2238         d1     = norm(v1);
2239         cosine = iprod(v0, v1)/(d0*d1);
2240         if (cosine < wfac)
2241         {
2242             sprintf(buf, " %6d %6d  %5.1f  %8.4f %8.4f    %8.4f\n",
2243                     ddglatnr(dd, i), ddglatnr(dd, j),
2244                     RAD2DEG*std::acos(cosine), d0, d1, bllen[b]);
2245             fprintf(stderr, "%s", buf);
2246             if (fplog)
2247             {
2248                 fprintf(fplog, "%s", buf);
2249             }
2250             if (!std::isfinite(d1))
2251             {
2252                 gmx_fatal(FARGS, "Bond length not finite.");
2253             }
2254
2255             (*warncount)++;
2256         }
2257     }
2258     if (*warncount > maxwarn)
2259     {
2260         too_many_constraint_warnings(econtLINCS, *warncount);
2261     }
2262 }
2263
2264 static void cconerr(const struct gmx_lincsdata *lincsd,
2265                     rvec *x, t_pbc *pbc,
2266                     real *ncons_loc, real *ssd, real *max, int *imax)
2267 {
2268     const int  *bla, *nlocat;
2269     const real *bllen;
2270     real        ma, ssd2;
2271     int         count, im, task;
2272
2273     bla    = lincsd->bla;
2274     bllen  = lincsd->bllen;
2275     nlocat = lincsd->nlocat;
2276
2277     ma    = 0;
2278     ssd2  = 0;
2279     im    = 0;
2280     count = 0;
2281     for (task = 0; task < lincsd->ntask; task++)
2282     {
2283         int b;
2284
2285         for (b = lincsd->task[task].b0; b < lincsd->task[task].b1; b++)
2286         {
2287             real len, d, r2;
2288             rvec dx;
2289
2290             if (pbc)
2291             {
2292                 pbc_dx_aiuc(pbc, x[bla[2*b]], x[bla[2*b+1]], dx);
2293             }
2294             else
2295             {
2296                 rvec_sub(x[bla[2*b]], x[bla[2*b+1]], dx);
2297             }
2298             r2  = norm2(dx);
2299             len = r2*gmx::invsqrt(r2);
2300             d   = std::abs(len/bllen[b]-1);
2301             if (d > ma && (nlocat == nullptr || nlocat[b]))
2302             {
2303                 ma = d;
2304                 im = b;
2305             }
2306             if (nlocat == nullptr)
2307             {
2308                 ssd2 += d*d;
2309                 count++;
2310             }
2311             else
2312             {
2313                 ssd2  += nlocat[b]*d*d;
2314                 count += nlocat[b];
2315             }
2316         }
2317     }
2318
2319     *ncons_loc = (nlocat ? 0.5 : 1)*count;
2320     *ssd       = (nlocat ? 0.5 : 1)*ssd2;
2321     *max       = ma;
2322     *imax      = im;
2323 }
2324
2325 gmx_bool constrain_lincs(FILE *fplog, gmx_bool bLog, gmx_bool bEner,
2326                          t_inputrec *ir,
2327                          gmx_int64_t step,
2328                          struct gmx_lincsdata *lincsd, t_mdatoms *md,
2329                          t_commrec *cr,
2330                          rvec *x, rvec *xprime, rvec *min_proj,
2331                          matrix box, t_pbc *pbc,
2332                          real lambda, real *dvdlambda,
2333                          real invdt, rvec *v,
2334                          gmx_bool bCalcVir, tensor vir_r_m_dr,
2335                          int econq,
2336                          t_nrnb *nrnb,
2337                          int maxwarn, int *warncount)
2338 {
2339     gmx_bool  bCalcDHDL;
2340     char      buf[STRLEN], buf2[22], buf3[STRLEN];
2341     int       i, p_imax;
2342     real      ncons_loc, p_ssd, p_max = 0;
2343     rvec      dx;
2344     gmx_bool  bOK, bWarn;
2345
2346     bOK = TRUE;
2347
2348     /* This boolean should be set by a flag passed to this routine.
2349      * We can also easily check if any constraint length is changed,
2350      * if not dH/dlambda=0 and we can also set the boolean to FALSE.
2351      */
2352     bCalcDHDL = (ir->efep != efepNO && dvdlambda != nullptr);
2353
2354     if (lincsd->nc == 0 && cr->dd == nullptr)
2355     {
2356         if (bLog || bEner)
2357         {
2358             lincsd->rmsd_data[0] = 0;
2359             lincsd->rmsd_data[1] = 0;
2360         }
2361
2362         return bOK;
2363     }
2364
2365     if (econq == econqCoord)
2366     {
2367         /* We can't use bCalcDHDL here, since NULL can be passed for dvdlambda
2368          * also with efep!=fepNO.
2369          */
2370         if (ir->efep != efepNO)
2371         {
2372             if (md->nMassPerturbed && lincsd->matlam != md->lambda)
2373             {
2374                 set_lincs_matrix(lincsd, md->invmass, md->lambda);
2375             }
2376
2377             for (i = 0; i < lincsd->nc; i++)
2378             {
2379                 lincsd->bllen[i] = lincsd->bllen0[i] + lambda*lincsd->ddist[i];
2380             }
2381         }
2382
2383         if (lincsd->ncg_flex)
2384         {
2385             /* Set the flexible constraint lengths to the old lengths */
2386             if (pbc != nullptr)
2387             {
2388                 for (i = 0; i < lincsd->nc; i++)
2389                 {
2390                     if (lincsd->bllen[i] == 0)
2391                     {
2392                         pbc_dx_aiuc(pbc, x[lincsd->bla[2*i]], x[lincsd->bla[2*i+1]], dx);
2393                         lincsd->bllen[i] = norm(dx);
2394                     }
2395                 }
2396             }
2397             else
2398             {
2399                 for (i = 0; i < lincsd->nc; i++)
2400                 {
2401                     if (lincsd->bllen[i] == 0)
2402                     {
2403                         lincsd->bllen[i] =
2404                             std::sqrt(distance2(x[lincsd->bla[2*i]],
2405                                                 x[lincsd->bla[2*i+1]]));
2406                     }
2407                 }
2408             }
2409         }
2410
2411         if (bLog && fplog)
2412         {
2413             cconerr(lincsd, xprime, pbc,
2414                     &ncons_loc, &p_ssd, &p_max, &p_imax);
2415         }
2416
2417         /* This bWarn var can be updated by multiple threads
2418          * at the same time. But as we only need to detect
2419          * if a warning occurred or not, this is not an issue.
2420          */
2421         bWarn = FALSE;
2422
2423         /* The OpenMP parallel region of constrain_lincs for coords */
2424 #pragma omp parallel num_threads(lincsd->ntask)
2425         {
2426             try
2427             {
2428                 int th = gmx_omp_get_thread_num();
2429
2430                 clear_mat(lincsd->task[th].vir_r_m_dr);
2431
2432                 do_lincs(x, xprime, box, pbc, lincsd, th,
2433                          md->invmass, cr,
2434                          bCalcDHDL,
2435                          ir->LincsWarnAngle, &bWarn,
2436                          invdt, v, bCalcVir,
2437                          th == 0 ? vir_r_m_dr : lincsd->task[th].vir_r_m_dr);
2438             }
2439             GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
2440         }
2441
2442         if (bLog && fplog && lincsd->nc > 0)
2443         {
2444             fprintf(fplog, "   Rel. Constraint Deviation:  RMS         MAX     between atoms\n");
2445             fprintf(fplog, "       Before LINCS          %.6f    %.6f %6d %6d\n",
2446                     std::sqrt(p_ssd/ncons_loc), p_max,
2447                     ddglatnr(cr->dd, lincsd->bla[2*p_imax]),
2448                     ddglatnr(cr->dd, lincsd->bla[2*p_imax+1]));
2449         }
2450         if (bLog || bEner)
2451         {
2452             cconerr(lincsd, xprime, pbc,
2453                     &ncons_loc, &p_ssd, &p_max, &p_imax);
2454             lincsd->rmsd_data[0] = ncons_loc;
2455             lincsd->rmsd_data[1] = p_ssd;
2456         }
2457         else
2458         {
2459             lincsd->rmsd_data[0] = 0;
2460             lincsd->rmsd_data[1] = 0;
2461             lincsd->rmsd_data[2] = 0;
2462         }
2463         if (bLog && fplog && lincsd->nc > 0)
2464         {
2465             fprintf(fplog,
2466                     "        After LINCS          %.6f    %.6f %6d %6d\n\n",
2467                     std::sqrt(p_ssd/ncons_loc), p_max,
2468                     ddglatnr(cr->dd, lincsd->bla[2*p_imax]),
2469                     ddglatnr(cr->dd, lincsd->bla[2*p_imax+1]));
2470         }
2471
2472         if (bWarn)
2473         {
2474             if (maxwarn < INT_MAX)
2475             {
2476                 cconerr(lincsd, xprime, pbc,
2477                         &ncons_loc, &p_ssd, &p_max, &p_imax);
2478                 if (MULTISIM(cr))
2479                 {
2480                     sprintf(buf3, " in simulation %d", cr->ms->sim);
2481                 }
2482                 else
2483                 {
2484                     buf3[0] = 0;
2485                 }
2486                 sprintf(buf, "\nStep %s, time %g (ps)  LINCS WARNING%s\n"
2487                         "relative constraint deviation after LINCS:\n"
2488                         "rms %.6f, max %.6f (between atoms %d and %d)\n",
2489                         gmx_step_str(step, buf2), ir->init_t+step*ir->delta_t,
2490                         buf3,
2491                         std::sqrt(p_ssd/ncons_loc), p_max,
2492                         ddglatnr(cr->dd, lincsd->bla[2*p_imax]),
2493                         ddglatnr(cr->dd, lincsd->bla[2*p_imax+1]));
2494                 if (fplog)
2495                 {
2496                     fprintf(fplog, "%s", buf);
2497                 }
2498                 fprintf(stderr, "%s", buf);
2499                 lincs_warning(fplog, cr->dd, x, xprime, pbc,
2500                               lincsd->nc, lincsd->bla, lincsd->bllen,
2501                               ir->LincsWarnAngle, maxwarn, warncount);
2502             }
2503             bOK = (p_max < 0.5);
2504         }
2505
2506         if (lincsd->ncg_flex)
2507         {
2508             for (i = 0; (i < lincsd->nc); i++)
2509             {
2510                 if (lincsd->bllen0[i] == 0 && lincsd->ddist[i] == 0)
2511                 {
2512                     lincsd->bllen[i] = 0;
2513                 }
2514             }
2515         }
2516     }
2517     else
2518     {
2519         /* The OpenMP parallel region of constrain_lincs for derivatives */
2520 #pragma omp parallel num_threads(lincsd->ntask)
2521         {
2522             try
2523             {
2524                 int th = gmx_omp_get_thread_num();
2525
2526                 do_lincsp(x, xprime, min_proj, pbc, lincsd, th,
2527                           md->invmass, econq, bCalcDHDL,
2528                           bCalcVir, th == 0 ? vir_r_m_dr : lincsd->task[th].vir_r_m_dr);
2529             }
2530             GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
2531         }
2532     }
2533
2534     if (bCalcDHDL)
2535     {
2536         /* Reduce the dH/dlambda contributions over the threads */
2537         real dhdlambda;
2538         int  th;
2539
2540         dhdlambda = 0;
2541         for (th = 0; th < lincsd->ntask; th++)
2542         {
2543             dhdlambda += lincsd->task[th].dhdlambda;
2544         }
2545         if (econq == econqCoord)
2546         {
2547             /* dhdlambda contains dH/dlambda*dt^2, correct for this */
2548             /* TODO This should probably use invdt, so that sd integrator scaling works properly */
2549             dhdlambda /= ir->delta_t*ir->delta_t;
2550         }
2551         *dvdlambda += dhdlambda;
2552     }
2553
2554     if (bCalcVir && lincsd->ntask > 1)
2555     {
2556         for (i = 1; i < lincsd->ntask; i++)
2557         {
2558             m_add(vir_r_m_dr, lincsd->task[i].vir_r_m_dr, vir_r_m_dr);
2559         }
2560     }
2561
2562     /* count assuming nit=1 */
2563     inc_nrnb(nrnb, eNR_LINCS, lincsd->nc_real);
2564     inc_nrnb(nrnb, eNR_LINCSMAT, (2+lincsd->nOrder)*lincsd->ncc);
2565     if (lincsd->ntriangle > 0)
2566     {
2567         inc_nrnb(nrnb, eNR_LINCSMAT, lincsd->nOrder*lincsd->ncc_triangle);
2568     }
2569     if (v)
2570     {
2571         inc_nrnb(nrnb, eNR_CONSTR_V, lincsd->nc_real*2);
2572     }
2573     if (bCalcVir)
2574     {
2575         inc_nrnb(nrnb, eNR_CONSTR_VIR, lincsd->nc_real);
2576     }
2577
2578     return bOK;
2579 }