Merge release-4-6 into master
[alexxy/gromacs.git] / src / gromacs / mdlib / vsite.c
1 /* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
2  *
3  *
4  *                This source code is part of
5  *
6  *                 G   R   O   M   A   C   S
7  *
8  *          GROningen MAchine for Chemical Simulations
9  *
10  *                        VERSION 3.2.0
11  * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
12  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
13  * Copyright (c) 2001-2004, The GROMACS development team,
14  * check out http://www.gromacs.org for more information.
15
16  * This program is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU General Public License
18  * as published by the Free Software Foundation; either version 2
19  * of the License, or (at your option) any later version.
20  *
21  * If you want to redistribute modifications, please consider that
22  * scientific software is very special. Version control is crucial -
23  * bugs must be traceable. We will be happy to consider code for
24  * inclusion in the official distribution, but derived work must not
25  * be called official GROMACS. Details are found in the README & COPYING
26  * files - if they are missing, get the official version at www.gromacs.org.
27  *
28  * To help us fund GROMACS development, we humbly ask that you cite
29  * the papers on the package - you can find them in the top README file.
30  *
31  * For more info, check our website at http://www.gromacs.org
32  *
33  * And Hey:
34  * GROwing Monsters And Cloning Shrimps
35  */
36 #ifdef HAVE_CONFIG_H
37 #include <config.h>
38 #endif
39
40 #include <stdio.h>
41 #include "typedefs.h"
42 #include "vsite.h"
43 #include "macros.h"
44 #include "smalloc.h"
45 #include "nrnb.h"
46 #include "vec.h"
47 #include "mvdata.h"
48 #include "network.h"
49 #include "mshift.h"
50 #include "pbc.h"
51 #include "domdec.h"
52 #include "partdec.h"
53 #include "mtop_util.h"
54 #include "gmx_omp_nthreads.h"
55 #include "gmx_omp.h"
56
57 /* Routines to send/recieve coordinates and force
58  * of constructing atoms.
59  */
60
61 static void move_construct_x(t_comm_vsites *vsitecomm, rvec x[], t_commrec *cr)
62 {
63     rvec *sendbuf;
64     rvec *recvbuf;
65     int   i, ia;
66
67     sendbuf = vsitecomm->send_buf;
68     recvbuf = vsitecomm->recv_buf;
69
70
71     /* Prepare pulse left by copying to send buffer */
72     for (i = 0; i < vsitecomm->left_export_nconstruct; i++)
73     {
74         ia = vsitecomm->left_export_construct[i];
75         copy_rvec(x[ia], sendbuf[i]);
76     }
77
78     /* Pulse coordinates left */
79     gmx_tx_rx_real(cr, GMX_LEFT, (real *)sendbuf, 3*vsitecomm->left_export_nconstruct, GMX_RIGHT, (real *)recvbuf, 3*vsitecomm->right_import_nconstruct);
80
81     /* Copy from receive buffer to coordinate array */
82     for (i = 0; i < vsitecomm->right_import_nconstruct; i++)
83     {
84         ia = vsitecomm->right_import_construct[i];
85         copy_rvec(recvbuf[i], x[ia]);
86     }
87
88     /* Prepare pulse right by copying to send buffer */
89     for (i = 0; i < vsitecomm->right_export_nconstruct; i++)
90     {
91         ia = vsitecomm->right_export_construct[i];
92         copy_rvec(x[ia], sendbuf[i]);
93     }
94
95     /* Pulse coordinates right */
96     gmx_tx_rx_real(cr, GMX_RIGHT, (real *)sendbuf, 3*vsitecomm->right_export_nconstruct, GMX_LEFT, (real *)recvbuf, 3*vsitecomm->left_import_nconstruct);
97
98     /* Copy from receive buffer to coordinate array */
99     for (i = 0; i < vsitecomm->left_import_nconstruct; i++)
100     {
101         ia = vsitecomm->left_import_construct[i];
102         copy_rvec(recvbuf[i], x[ia]);
103     }
104 }
105
106
107 static void move_construct_f(t_comm_vsites *vsitecomm, rvec f[], t_commrec *cr)
108 {
109     rvec *sendbuf;
110     rvec *recvbuf;
111     int   i, ia;
112
113     sendbuf = vsitecomm->send_buf;
114     recvbuf = vsitecomm->recv_buf;
115
116     /* Prepare pulse right by copying to send buffer */
117     for (i = 0; i < vsitecomm->right_import_nconstruct; i++)
118     {
119         ia = vsitecomm->right_import_construct[i];
120         copy_rvec(f[ia], sendbuf[i]);
121         clear_rvec(f[ia]);     /* Zero it here after moving, just to simplify debug book-keeping... */
122     }
123
124     /* Pulse forces right */
125     gmx_tx_rx_real(cr, GMX_RIGHT, (real *)sendbuf, 3*vsitecomm->right_import_nconstruct, GMX_LEFT, (real *)recvbuf, 3*vsitecomm->left_export_nconstruct);
126
127     /* Copy from receive buffer to coordinate array */
128     for (i = 0; i < vsitecomm->left_export_nconstruct; i++)
129     {
130         ia = vsitecomm->left_export_construct[i];
131         rvec_inc(f[ia], recvbuf[i]);
132     }
133
134     /* Prepare pulse left by copying to send buffer */
135     for (i = 0; i < vsitecomm->left_import_nconstruct; i++)
136     {
137         ia = vsitecomm->left_import_construct[i];
138         copy_rvec(f[ia], sendbuf[i]);
139         clear_rvec(f[ia]);     /* Zero it here after moving, just to simplify debug book-keeping... */
140     }
141
142     /* Pulse coordinates left */
143     gmx_tx_rx_real(cr, GMX_LEFT, (real *)sendbuf, 3*vsitecomm->left_import_nconstruct, GMX_RIGHT, (real *)recvbuf, 3*vsitecomm->right_export_nconstruct);
144
145     /* Copy from receive buffer to coordinate array */
146     for (i = 0; i < vsitecomm->right_export_nconstruct; i++)
147     {
148         ia = vsitecomm->right_export_construct[i];
149         rvec_inc(f[ia], recvbuf[i]);
150     }
151
152     /* All forces are now on the home processors */
153 }
154
155
156 static void
157 pd_clear_nonlocal_constructs(t_comm_vsites *vsitecomm, rvec f[])
158 {
159     int i, ia;
160
161     for (i = 0; i < vsitecomm->left_import_nconstruct; i++)
162     {
163         ia = vsitecomm->left_import_construct[i];
164         clear_rvec(f[ia]);
165     }
166     for (i = 0; i < vsitecomm->right_import_nconstruct; i++)
167     {
168         ia = vsitecomm->right_import_construct[i];
169         clear_rvec(f[ia]);
170     }
171 }
172
173
174
175 static int pbc_rvec_sub(const t_pbc *pbc, const rvec xi, const rvec xj, rvec dx)
176 {
177     if (pbc)
178     {
179         return pbc_dx_aiuc(pbc, xi, xj, dx);
180     }
181     else
182     {
183         rvec_sub(xi, xj, dx);
184         return CENTRAL;
185     }
186 }
187
188 /* Vsite construction routines */
189
190 static void constr_vsite2(rvec xi, rvec xj, rvec x, real a, t_pbc *pbc)
191 {
192     real b;
193     rvec dx;
194
195     b = 1.0-a;
196     /* 1 flop */
197
198     if (pbc)
199     {
200         pbc_dx_aiuc(pbc, xj, xi, dx);
201         x[XX] = xi[XX] + a*dx[XX];
202         x[YY] = xi[YY] + a*dx[YY];
203         x[ZZ] = xi[ZZ] + a*dx[ZZ];
204     }
205     else
206     {
207         x[XX] = b*xi[XX] + a*xj[XX];
208         x[YY] = b*xi[YY] + a*xj[YY];
209         x[ZZ] = b*xi[ZZ] + a*xj[ZZ];
210         /* 9 Flops */
211     }
212
213     /* TOTAL: 10 flops */
214 }
215
216 static void constr_vsite3(rvec xi, rvec xj, rvec xk, rvec x, real a, real b,
217                           t_pbc *pbc)
218 {
219     real c;
220     rvec dxj, dxk;
221
222     c = 1.0-a-b;
223     /* 2 flops */
224
225     if (pbc)
226     {
227         pbc_dx_aiuc(pbc, xj, xi, dxj);
228         pbc_dx_aiuc(pbc, xk, xi, dxk);
229         x[XX] = xi[XX] + a*dxj[XX] + b*dxk[XX];
230         x[YY] = xi[YY] + a*dxj[YY] + b*dxk[YY];
231         x[ZZ] = xi[ZZ] + a*dxj[ZZ] + b*dxk[ZZ];
232     }
233     else
234     {
235         x[XX] = c*xi[XX] + a*xj[XX] + b*xk[XX];
236         x[YY] = c*xi[YY] + a*xj[YY] + b*xk[YY];
237         x[ZZ] = c*xi[ZZ] + a*xj[ZZ] + b*xk[ZZ];
238         /* 15 Flops */
239     }
240
241     /* TOTAL: 17 flops */
242 }
243
244 static void constr_vsite3FD(rvec xi, rvec xj, rvec xk, rvec x, real a, real b,
245                             t_pbc *pbc)
246 {
247     rvec xij, xjk, temp;
248     real c;
249
250     pbc_rvec_sub(pbc, xj, xi, xij);
251     pbc_rvec_sub(pbc, xk, xj, xjk);
252     /* 6 flops */
253
254     /* temp goes from i to a point on the line jk */
255     temp[XX] = xij[XX] + a*xjk[XX];
256     temp[YY] = xij[YY] + a*xjk[YY];
257     temp[ZZ] = xij[ZZ] + a*xjk[ZZ];
258     /* 6 flops */
259
260     c = b*gmx_invsqrt(iprod(temp, temp));
261     /* 6 + 10 flops */
262
263     x[XX] = xi[XX] + c*temp[XX];
264     x[YY] = xi[YY] + c*temp[YY];
265     x[ZZ] = xi[ZZ] + c*temp[ZZ];
266     /* 6 Flops */
267
268     /* TOTAL: 34 flops */
269 }
270
271 static void constr_vsite3FAD(rvec xi, rvec xj, rvec xk, rvec x, real a, real b, t_pbc *pbc)
272 {
273     rvec xij, xjk, xp;
274     real a1, b1, c1, invdij;
275
276     pbc_rvec_sub(pbc, xj, xi, xij);
277     pbc_rvec_sub(pbc, xk, xj, xjk);
278     /* 6 flops */
279
280     invdij = gmx_invsqrt(iprod(xij, xij));
281     c1     = invdij * invdij * iprod(xij, xjk);
282     xp[XX] = xjk[XX] - c1*xij[XX];
283     xp[YY] = xjk[YY] - c1*xij[YY];
284     xp[ZZ] = xjk[ZZ] - c1*xij[ZZ];
285     a1     = a*invdij;
286     b1     = b*gmx_invsqrt(iprod(xp, xp));
287     /* 45 */
288
289     x[XX] = xi[XX] + a1*xij[XX] + b1*xp[XX];
290     x[YY] = xi[YY] + a1*xij[YY] + b1*xp[YY];
291     x[ZZ] = xi[ZZ] + a1*xij[ZZ] + b1*xp[ZZ];
292     /* 12 Flops */
293
294     /* TOTAL: 63 flops */
295 }
296
297 static void constr_vsite3OUT(rvec xi, rvec xj, rvec xk, rvec x,
298                              real a, real b, real c, t_pbc *pbc)
299 {
300     rvec xij, xik, temp;
301
302     pbc_rvec_sub(pbc, xj, xi, xij);
303     pbc_rvec_sub(pbc, xk, xi, xik);
304     cprod(xij, xik, temp);
305     /* 15 Flops */
306
307     x[XX] = xi[XX] + a*xij[XX] + b*xik[XX] + c*temp[XX];
308     x[YY] = xi[YY] + a*xij[YY] + b*xik[YY] + c*temp[YY];
309     x[ZZ] = xi[ZZ] + a*xij[ZZ] + b*xik[ZZ] + c*temp[ZZ];
310     /* 18 Flops */
311
312     /* TOTAL: 33 flops */
313 }
314
315 static void constr_vsite4FD(rvec xi, rvec xj, rvec xk, rvec xl, rvec x,
316                             real a, real b, real c, t_pbc *pbc)
317 {
318     rvec xij, xjk, xjl, temp;
319     real d;
320
321     pbc_rvec_sub(pbc, xj, xi, xij);
322     pbc_rvec_sub(pbc, xk, xj, xjk);
323     pbc_rvec_sub(pbc, xl, xj, xjl);
324     /* 9 flops */
325
326     /* temp goes from i to a point on the plane jkl */
327     temp[XX] = xij[XX] + a*xjk[XX] + b*xjl[XX];
328     temp[YY] = xij[YY] + a*xjk[YY] + b*xjl[YY];
329     temp[ZZ] = xij[ZZ] + a*xjk[ZZ] + b*xjl[ZZ];
330     /* 12 flops */
331
332     d = c*gmx_invsqrt(iprod(temp, temp));
333     /* 6 + 10 flops */
334
335     x[XX] = xi[XX] + d*temp[XX];
336     x[YY] = xi[YY] + d*temp[YY];
337     x[ZZ] = xi[ZZ] + d*temp[ZZ];
338     /* 6 Flops */
339
340     /* TOTAL: 43 flops */
341 }
342
343
344 static void constr_vsite4FDN(rvec xi, rvec xj, rvec xk, rvec xl, rvec x,
345                              real a, real b, real c, t_pbc *pbc)
346 {
347     rvec xij, xik, xil, ra, rb, rja, rjb, rm;
348     real d;
349
350     pbc_rvec_sub(pbc, xj, xi, xij);
351     pbc_rvec_sub(pbc, xk, xi, xik);
352     pbc_rvec_sub(pbc, xl, xi, xil);
353     /* 9 flops */
354
355     ra[XX] = a*xik[XX];
356     ra[YY] = a*xik[YY];
357     ra[ZZ] = a*xik[ZZ];
358
359     rb[XX] = b*xil[XX];
360     rb[YY] = b*xil[YY];
361     rb[ZZ] = b*xil[ZZ];
362
363     /* 6 flops */
364
365     rvec_sub(ra, xij, rja);
366     rvec_sub(rb, xij, rjb);
367     /* 6 flops */
368
369     cprod(rja, rjb, rm);
370     /* 9 flops */
371
372     d = c*gmx_invsqrt(norm2(rm));
373     /* 5+5+1 flops */
374
375     x[XX] = xi[XX] + d*rm[XX];
376     x[YY] = xi[YY] + d*rm[YY];
377     x[ZZ] = xi[ZZ] + d*rm[ZZ];
378     /* 6 Flops */
379
380     /* TOTAL: 47 flops */
381 }
382
383
384 static int constr_vsiten(t_iatom *ia, t_iparams ip[],
385                          rvec *x, t_pbc *pbc)
386 {
387     rvec xs, x1, dx;
388     dvec dsum;
389     int  n3, av, ai, i;
390     real a;
391
392     n3 = 3*ip[ia[0]].vsiten.n;
393     av = ia[1];
394     ai = ia[2];
395     copy_rvec(x[ai], x1);
396     clear_dvec(dsum);
397     for (i = 3; i < n3; i += 3)
398     {
399         ai = ia[i+2];
400         a  = ip[ia[i]].vsiten.a;
401         if (pbc)
402         {
403             pbc_dx_aiuc(pbc, x[ai], x1, dx);
404         }
405         else
406         {
407             rvec_sub(x[ai], x1, dx);
408         }
409         dsum[XX] += a*dx[XX];
410         dsum[YY] += a*dx[YY];
411         dsum[ZZ] += a*dx[ZZ];
412         /* 9 Flops */
413     }
414
415     x[av][XX] = x1[XX] + dsum[XX];
416     x[av][YY] = x1[YY] + dsum[YY];
417     x[av][ZZ] = x1[ZZ] + dsum[ZZ];
418
419     return n3;
420 }
421
422
423 void construct_vsites_thread(gmx_vsite_t *vsite,
424                              rvec x[], t_nrnb *nrnb,
425                              real dt, rvec *v,
426                              t_iparams ip[], t_ilist ilist[],
427                              t_pbc *pbc_null)
428 {
429     gmx_bool   bPBCAll;
430     rvec       xpbc, xv, vv, dx;
431     real       a1, b1, c1, inv_dt;
432     int        i, inc, ii, nra, nr, tp, ftype;
433     t_iatom    avsite, ai, aj, ak, al, pbc_atom;
434     t_iatom   *ia;
435     t_pbc     *pbc_null2;
436     int       *vsite_pbc, ishift;
437     rvec       reftmp, vtmp, rtmp;
438
439     if (v != NULL)
440     {
441         inv_dt = 1.0/dt;
442     }
443     else
444     {
445         inv_dt = 1.0;
446     }
447
448     bPBCAll = (pbc_null != NULL && !vsite->bHaveChargeGroups);
449
450     pbc_null2 = NULL;
451     vsite_pbc = NULL;
452     for (ftype = 0; (ftype < F_NRE); ftype++)
453     {
454         if ((interaction_function[ftype].flags & IF_VSITE) &&
455             ilist[ftype].nr > 0)
456         {
457             nra    = interaction_function[ftype].nratoms;
458             inc    = 1 + nra;
459             nr     = ilist[ftype].nr;
460             ia     = ilist[ftype].iatoms;
461
462             if (bPBCAll)
463             {
464                 pbc_null2 = pbc_null;
465             }
466             else if (pbc_null != NULL)
467             {
468                 vsite_pbc = vsite->vsite_pbc_loc[ftype-F_VSITE2];
469             }
470
471             for (i = 0; i < nr; )
472             {
473                 tp   = ia[0];
474
475                 /* The vsite and constructing atoms */
476                 avsite = ia[1];
477                 ai     = ia[2];
478                 aj     = ia[3];
479
480                 /* Constants for constructing vsites */
481                 a1   = ip[tp].vsite.a;
482                 /* Check what kind of pbc we need to use */
483                 if (bPBCAll)
484                 {
485                     /* No charge groups, vsite follows its own pbc */
486                     pbc_atom = avsite;
487                     copy_rvec(x[avsite], xpbc);
488                 }
489                 else if (vsite_pbc != NULL)
490                 {
491                     pbc_atom = vsite_pbc[i/(1+nra)];
492                     if (pbc_atom > -2)
493                     {
494                         if (pbc_atom >= 0)
495                         {
496                             /* We need to copy the coordinates here,
497                              * single for single atom cg's pbc_atom
498                              * is the vsite itself.
499                              */
500                             copy_rvec(x[pbc_atom], xpbc);
501                         }
502                         pbc_null2 = pbc_null;
503                     }
504                     else
505                     {
506                         pbc_null2 = NULL;
507                     }
508                 }
509                 else
510                 {
511                     pbc_atom = -2;
512                 }
513                 /* Copy the old position */
514                 copy_rvec(x[avsite], xv);
515
516                 /* Construct the vsite depending on type */
517                 switch (ftype)
518                 {
519                     case F_VSITE2:
520                         constr_vsite2(x[ai], x[aj], x[avsite], a1, pbc_null2);
521                         break;
522                     case F_VSITE3:
523                         ak = ia[4];
524                         b1 = ip[tp].vsite.b;
525                         constr_vsite3(x[ai], x[aj], x[ak], x[avsite], a1, b1, pbc_null2);
526                         break;
527                     case F_VSITE3FD:
528                         ak = ia[4];
529                         b1 = ip[tp].vsite.b;
530                         constr_vsite3FD(x[ai], x[aj], x[ak], x[avsite], a1, b1, pbc_null2);
531                         break;
532                     case F_VSITE3FAD:
533                         ak = ia[4];
534                         b1 = ip[tp].vsite.b;
535                         constr_vsite3FAD(x[ai], x[aj], x[ak], x[avsite], a1, b1, pbc_null2);
536                         break;
537                     case F_VSITE3OUT:
538                         ak = ia[4];
539                         b1 = ip[tp].vsite.b;
540                         c1 = ip[tp].vsite.c;
541                         constr_vsite3OUT(x[ai], x[aj], x[ak], x[avsite], a1, b1, c1, pbc_null2);
542                         break;
543                     case F_VSITE4FD:
544                         ak = ia[4];
545                         al = ia[5];
546                         b1 = ip[tp].vsite.b;
547                         c1 = ip[tp].vsite.c;
548                         constr_vsite4FD(x[ai], x[aj], x[ak], x[al], x[avsite], a1, b1, c1,
549                                         pbc_null2);
550                         break;
551                     case F_VSITE4FDN:
552                         ak = ia[4];
553                         al = ia[5];
554                         b1 = ip[tp].vsite.b;
555                         c1 = ip[tp].vsite.c;
556                         constr_vsite4FDN(x[ai], x[aj], x[ak], x[al], x[avsite], a1, b1, c1,
557                                          pbc_null2);
558                         break;
559                     case F_VSITEN:
560                         inc = constr_vsiten(ia, ip, x, pbc_null2);
561                         break;
562                     default:
563                         gmx_fatal(FARGS, "No such vsite type %d in %s, line %d",
564                                   ftype, __FILE__, __LINE__);
565                 }
566
567                 if (pbc_atom >= 0)
568                 {
569                     /* Match the pbc of this vsite to the rest of its charge group */
570                     ishift = pbc_dx_aiuc(pbc_null, x[avsite], xpbc, dx);
571                     if (ishift != CENTRAL)
572                     {
573                         rvec_add(xpbc, dx, x[avsite]);
574                     }
575                 }
576                 if (v != NULL)
577                 {
578                     /* Calculate velocity of vsite... */
579                     rvec_sub(x[avsite], xv, vv);
580                     svmul(inv_dt, vv, v[avsite]);
581                 }
582
583                 /* Increment loop variables */
584                 i  += inc;
585                 ia += inc;
586             }
587         }
588     }
589 }
590
591 void construct_vsites(FILE *log, gmx_vsite_t *vsite,
592                       rvec x[], t_nrnb *nrnb,
593                       real dt, rvec *v,
594                       t_iparams ip[], t_ilist ilist[],
595                       int ePBC, gmx_bool bMolPBC, t_graph *graph,
596                       t_commrec *cr, matrix box)
597 {
598     t_pbc     pbc, *pbc_null;
599     gmx_bool  bDomDec;
600     int       nthreads;
601
602     bDomDec = cr && DOMAINDECOMP(cr);
603
604     /* We only need to do pbc when we have inter-cg vsites */
605     if (ePBC != epbcNONE && (bDomDec || bMolPBC) && vsite->n_intercg_vsite)
606     {
607         /* This is wasting some CPU time as we now do this multiple times
608          * per MD step. But how often do we have vsites with full pbc?
609          */
610         pbc_null = set_pbc_dd(&pbc, ePBC, cr != NULL ? cr->dd : NULL, FALSE, box);
611     }
612     else
613     {
614         pbc_null = NULL;
615     }
616
617     if (cr)
618     {
619         if (bDomDec)
620         {
621             dd_move_x_vsites(cr->dd, box, x);
622         }
623         else if (vsite->bPDvsitecomm)
624         {
625             /* I'm not sure whether the periodicity and shift are guaranteed
626              * to be consistent between different nodes when running e.g. polymers
627              * in parallel. In this special case we thus unshift/shift,
628              * but only when necessary. This is to make sure the coordinates
629              * we move don't end up a box away...
630              */
631             if (graph != NULL)
632             {
633                 unshift_self(graph, box, x);
634             }
635
636             move_construct_x(vsite->vsitecomm, x, cr);
637
638             if (graph != NULL)
639             {
640                 shift_self(graph, box, x);
641             }
642         }
643     }
644
645     if (vsite->nthreads == 1)
646     {
647         construct_vsites_thread(vsite,
648                                 x, nrnb, dt, v,
649                                 ip, ilist,
650                                 pbc_null);
651     }
652     else
653     {
654 #pragma omp parallel num_threads(vsite->nthreads)
655         {
656             construct_vsites_thread(vsite,
657                                     x, nrnb, dt, v,
658                                     ip, vsite->tdata[gmx_omp_get_thread_num()].ilist,
659                                     pbc_null);
660         }
661         /* Now we can construct the vsites that might depend on other vsites */
662         construct_vsites_thread(vsite,
663                                 x, nrnb, dt, v,
664                                 ip, vsite->tdata[vsite->nthreads].ilist,
665                                 pbc_null);
666     }
667 }
668
669 static void spread_vsite2(t_iatom ia[], real a,
670                           rvec x[], rvec f[], rvec fshift[],
671                           t_pbc *pbc, t_graph *g)
672 {
673     rvec    fi, fj, dx;
674     t_iatom av, ai, aj;
675     ivec    di;
676     real    b;
677     int     siv, sij;
678
679     av = ia[1];
680     ai = ia[2];
681     aj = ia[3];
682
683     svmul(1-a, f[av], fi);
684     svmul(  a, f[av], fj);
685     /* 7 flop */
686
687     rvec_inc(f[ai], fi);
688     rvec_inc(f[aj], fj);
689     /* 6 Flops */
690
691     if (g)
692     {
693         ivec_sub(SHIFT_IVEC(g, ai), SHIFT_IVEC(g, av), di);
694         siv = IVEC2IS(di);
695         ivec_sub(SHIFT_IVEC(g, ai), SHIFT_IVEC(g, aj), di);
696         sij = IVEC2IS(di);
697     }
698     else if (pbc)
699     {
700         siv = pbc_dx_aiuc(pbc, x[ai], x[av], dx);
701         sij = pbc_dx_aiuc(pbc, x[ai], x[aj], dx);
702     }
703     else
704     {
705         siv = CENTRAL;
706         sij = CENTRAL;
707     }
708
709     if (fshift && (siv != CENTRAL || sij != CENTRAL))
710     {
711         rvec_inc(fshift[siv], f[av]);
712         rvec_dec(fshift[CENTRAL], fi);
713         rvec_dec(fshift[sij], fj);
714     }
715
716     /* TOTAL: 13 flops */
717 }
718
719 void construct_vsites_mtop(FILE *log, gmx_vsite_t *vsite,
720                            gmx_mtop_t *mtop, rvec x[])
721 {
722     int             as, mb, mol;
723     gmx_molblock_t *molb;
724     gmx_moltype_t  *molt;
725
726     as = 0;
727     for (mb = 0; mb < mtop->nmolblock; mb++)
728     {
729         molb = &mtop->molblock[mb];
730         molt = &mtop->moltype[molb->type];
731         for (mol = 0; mol < molb->nmol; mol++)
732         {
733             construct_vsites(log, vsite, x+as, NULL, 0.0, NULL,
734                              mtop->ffparams.iparams, molt->ilist,
735                              epbcNONE, TRUE, NULL, NULL, NULL);
736             as += molt->atoms.nr;
737         }
738     }
739 }
740
741 static void spread_vsite3(t_iatom ia[], real a, real b,
742                           rvec x[], rvec f[], rvec fshift[],
743                           t_pbc *pbc, t_graph *g)
744 {
745     rvec    fi, fj, fk, dx;
746     atom_id av, ai, aj, ak;
747     ivec    di;
748     int     siv, sij, sik;
749
750     av = ia[1];
751     ai = ia[2];
752     aj = ia[3];
753     ak = ia[4];
754
755     svmul(1-a-b, f[av], fi);
756     svmul(    a, f[av], fj);
757     svmul(    b, f[av], fk);
758     /* 11 flops */
759
760     rvec_inc(f[ai], fi);
761     rvec_inc(f[aj], fj);
762     rvec_inc(f[ak], fk);
763     /* 9 Flops */
764
765     if (g)
766     {
767         ivec_sub(SHIFT_IVEC(g, ai), SHIFT_IVEC(g, ia[1]), di);
768         siv = IVEC2IS(di);
769         ivec_sub(SHIFT_IVEC(g, ai), SHIFT_IVEC(g, aj), di);
770         sij = IVEC2IS(di);
771         ivec_sub(SHIFT_IVEC(g, ai), SHIFT_IVEC(g, ak), di);
772         sik = IVEC2IS(di);
773     }
774     else if (pbc)
775     {
776         siv = pbc_dx_aiuc(pbc, x[ai], x[av], dx);
777         sij = pbc_dx_aiuc(pbc, x[ai], x[aj], dx);
778         sik = pbc_dx_aiuc(pbc, x[ai], x[ak], dx);
779     }
780     else
781     {
782         siv = CENTRAL;
783         sij = CENTRAL;
784         sik = CENTRAL;
785     }
786
787     if (fshift && (siv != CENTRAL || sij != CENTRAL || sik != CENTRAL))
788     {
789         rvec_inc(fshift[siv], f[av]);
790         rvec_dec(fshift[CENTRAL], fi);
791         rvec_dec(fshift[sij], fj);
792         rvec_dec(fshift[sik], fk);
793     }
794
795     /* TOTAL: 20 flops */
796 }
797
798 static void spread_vsite3FD(t_iatom ia[], real a, real b,
799                             rvec x[], rvec f[], rvec fshift[],
800                             gmx_bool VirCorr, matrix dxdf,
801                             t_pbc *pbc, t_graph *g)
802 {
803     real    fx, fy, fz, c, invl, fproj, a1;
804     rvec    xvi, xij, xjk, xix, fv, temp;
805     t_iatom av, ai, aj, ak;
806     int     svi, sji, skj, d;
807     ivec    di;
808
809     av = ia[1];
810     ai = ia[2];
811     aj = ia[3];
812     ak = ia[4];
813     copy_rvec(f[av], fv);
814
815     sji = pbc_rvec_sub(pbc, x[aj], x[ai], xij);
816     skj = pbc_rvec_sub(pbc, x[ak], x[aj], xjk);
817     /* 6 flops */
818
819     /* xix goes from i to point x on the line jk */
820     xix[XX] = xij[XX]+a*xjk[XX];
821     xix[YY] = xij[YY]+a*xjk[YY];
822     xix[ZZ] = xij[ZZ]+a*xjk[ZZ];
823     /* 6 flops */
824
825     invl = gmx_invsqrt(iprod(xix, xix));
826     c    = b*invl;
827     /* 4 + ?10? flops */
828
829     fproj = iprod(xix, fv)*invl*invl; /* = (xix . f)/(xix . xix) */
830
831     temp[XX] = c*(fv[XX]-fproj*xix[XX]);
832     temp[YY] = c*(fv[YY]-fproj*xix[YY]);
833     temp[ZZ] = c*(fv[ZZ]-fproj*xix[ZZ]);
834     /* 16 */
835
836     /* c is already calculated in constr_vsite3FD
837        storing c somewhere will save 26 flops!     */
838
839     a1         = 1-a;
840     f[ai][XX] += fv[XX] - temp[XX];
841     f[ai][YY] += fv[YY] - temp[YY];
842     f[ai][ZZ] += fv[ZZ] - temp[ZZ];
843     f[aj][XX] += a1*temp[XX];
844     f[aj][YY] += a1*temp[YY];
845     f[aj][ZZ] += a1*temp[ZZ];
846     f[ak][XX] += a*temp[XX];
847     f[ak][YY] += a*temp[YY];
848     f[ak][ZZ] += a*temp[ZZ];
849     /* 19 Flops */
850
851     if (g)
852     {
853         ivec_sub(SHIFT_IVEC(g, ia[1]), SHIFT_IVEC(g, ai), di);
854         svi = IVEC2IS(di);
855         ivec_sub(SHIFT_IVEC(g, aj), SHIFT_IVEC(g, ai), di);
856         sji = IVEC2IS(di);
857         ivec_sub(SHIFT_IVEC(g, ak), SHIFT_IVEC(g, aj), di);
858         skj = IVEC2IS(di);
859     }
860     else if (pbc)
861     {
862         svi = pbc_rvec_sub(pbc, x[av], x[ai], xvi);
863     }
864     else
865     {
866         svi = CENTRAL;
867     }
868
869     if (fshift && (svi != CENTRAL || sji != CENTRAL || skj != CENTRAL))
870     {
871         rvec_dec(fshift[svi], fv);
872         fshift[CENTRAL][XX] += fv[XX] - (1 + a)*temp[XX];
873         fshift[CENTRAL][YY] += fv[YY] - (1 + a)*temp[YY];
874         fshift[CENTRAL][ZZ] += fv[ZZ] - (1 + a)*temp[ZZ];
875         fshift[    sji][XX] += temp[XX];
876         fshift[    sji][YY] += temp[YY];
877         fshift[    sji][ZZ] += temp[ZZ];
878         fshift[    skj][XX] += a*temp[XX];
879         fshift[    skj][YY] += a*temp[YY];
880         fshift[    skj][ZZ] += a*temp[ZZ];
881     }
882
883     if (VirCorr)
884     {
885         /* When VirCorr=TRUE, the virial for the current forces is not
886          * calculated from the redistributed forces. This means that
887          * the effect of non-linear virtual site constructions on the virial
888          * needs to be added separately. This contribution can be calculated
889          * in many ways, but the simplest and cheapest way is to use
890          * the first constructing atom ai as a reference position in space:
891          * subtract (xv-xi)*fv and add (xj-xi)*fj + (xk-xi)*fk.
892          */
893         rvec xiv;
894         int  i, j;
895
896         pbc_rvec_sub(pbc, x[av], x[ai], xiv);
897
898         for (i = 0; i < DIM; i++)
899         {
900             for (j = 0; j < DIM; j++)
901             {
902                 /* As xix is a linear combination of j and k, use that here */
903                 dxdf[i][j] += -xiv[i]*fv[j] + xix[i]*temp[j];
904             }
905         }
906     }
907
908     /* TOTAL: 61 flops */
909 }
910
911 static void spread_vsite3FAD(t_iatom ia[], real a, real b,
912                              rvec x[], rvec f[], rvec fshift[],
913                              gmx_bool VirCorr, matrix dxdf,
914                              t_pbc *pbc, t_graph *g)
915 {
916     rvec    xvi, xij, xjk, xperp, Fpij, Fppp, fv, f1, f2, f3;
917     real    a1, b1, c1, c2, invdij, invdij2, invdp, fproj;
918     t_iatom av, ai, aj, ak;
919     int     svi, sji, skj, d;
920     ivec    di;
921
922     av = ia[1];
923     ai = ia[2];
924     aj = ia[3];
925     ak = ia[4];
926     copy_rvec(f[ia[1]], fv);
927
928     sji = pbc_rvec_sub(pbc, x[aj], x[ai], xij);
929     skj = pbc_rvec_sub(pbc, x[ak], x[aj], xjk);
930     /* 6 flops */
931
932     invdij    = gmx_invsqrt(iprod(xij, xij));
933     invdij2   = invdij * invdij;
934     c1        = iprod(xij, xjk) * invdij2;
935     xperp[XX] = xjk[XX] - c1*xij[XX];
936     xperp[YY] = xjk[YY] - c1*xij[YY];
937     xperp[ZZ] = xjk[ZZ] - c1*xij[ZZ];
938     /* xperp in plane ijk, perp. to ij */
939     invdp = gmx_invsqrt(iprod(xperp, xperp));
940     a1    = a*invdij;
941     b1    = b*invdp;
942     /* 45 flops */
943
944     /* a1, b1 and c1 are already calculated in constr_vsite3FAD
945        storing them somewhere will save 45 flops!     */
946
947     fproj = iprod(xij, fv)*invdij2;
948     svmul(fproj,                      xij,  Fpij);    /* proj. f on xij */
949     svmul(iprod(xperp, fv)*invdp*invdp, xperp, Fppp); /* proj. f on xperp */
950     svmul(b1*fproj,                   xperp, f3);
951     /* 23 flops */
952
953     rvec_sub(fv, Fpij, f1); /* f1 = f - Fpij */
954     rvec_sub(f1, Fppp, f2); /* f2 = f - Fpij - Fppp */
955     for (d = 0; (d < DIM); d++)
956     {
957         f1[d] *= a1;
958         f2[d] *= b1;
959     }
960     /* 12 flops */
961
962     c2         = 1+c1;
963     f[ai][XX] += fv[XX] - f1[XX] + c1*f2[XX] + f3[XX];
964     f[ai][YY] += fv[YY] - f1[YY] + c1*f2[YY] + f3[YY];
965     f[ai][ZZ] += fv[ZZ] - f1[ZZ] + c1*f2[ZZ] + f3[ZZ];
966     f[aj][XX] +=          f1[XX] - c2*f2[XX] - f3[XX];
967     f[aj][YY] +=          f1[YY] - c2*f2[YY] - f3[YY];
968     f[aj][ZZ] +=          f1[ZZ] - c2*f2[ZZ] - f3[ZZ];
969     f[ak][XX] +=                      f2[XX];
970     f[ak][YY] +=                      f2[YY];
971     f[ak][ZZ] +=                      f2[ZZ];
972     /* 30 Flops */
973
974     if (g)
975     {
976         ivec_sub(SHIFT_IVEC(g, ia[1]), SHIFT_IVEC(g, ai), di);
977         svi = IVEC2IS(di);
978         ivec_sub(SHIFT_IVEC(g, aj), SHIFT_IVEC(g, ai), di);
979         sji = IVEC2IS(di);
980         ivec_sub(SHIFT_IVEC(g, ak), SHIFT_IVEC(g, aj), di);
981         skj = IVEC2IS(di);
982     }
983     else if (pbc)
984     {
985         svi = pbc_rvec_sub(pbc, x[av], x[ai], xvi);
986     }
987     else
988     {
989         svi = CENTRAL;
990     }
991
992     if (fshift && (svi != CENTRAL || sji != CENTRAL || skj != CENTRAL))
993     {
994         rvec_dec(fshift[svi], fv);
995         fshift[CENTRAL][XX] += fv[XX] - f1[XX] - (1-c1)*f2[XX] + f3[XX];
996         fshift[CENTRAL][YY] += fv[YY] - f1[YY] - (1-c1)*f2[YY] + f3[YY];
997         fshift[CENTRAL][ZZ] += fv[ZZ] - f1[ZZ] - (1-c1)*f2[ZZ] + f3[ZZ];
998         fshift[    sji][XX] +=          f1[XX] -    c1 *f2[XX] - f3[XX];
999         fshift[    sji][YY] +=          f1[YY] -    c1 *f2[YY] - f3[YY];
1000         fshift[    sji][ZZ] +=          f1[ZZ] -    c1 *f2[ZZ] - f3[ZZ];
1001         fshift[    skj][XX] +=                          f2[XX];
1002         fshift[    skj][YY] +=                          f2[YY];
1003         fshift[    skj][ZZ] +=                          f2[ZZ];
1004     }
1005
1006     if (VirCorr)
1007     {
1008         rvec xiv;
1009         int  i, j;
1010
1011         pbc_rvec_sub(pbc, x[av], x[ai], xiv);
1012
1013         for (i = 0; i < DIM; i++)
1014         {
1015             for (j = 0; j < DIM; j++)
1016             {
1017                 /* Note that xik=xij+xjk, so we have to add xij*f2 */
1018                 dxdf[i][j] +=
1019                     -xiv[i]*fv[j]
1020                     + xij[i]*(f1[j] + (1 - c2)*f2[j] - f3[j])
1021                     + xjk[i]*f2[j];
1022             }
1023         }
1024     }
1025
1026     /* TOTAL: 113 flops */
1027 }
1028
1029 static void spread_vsite3OUT(t_iatom ia[], real a, real b, real c,
1030                              rvec x[], rvec f[], rvec fshift[],
1031                              gmx_bool VirCorr, matrix dxdf,
1032                              t_pbc *pbc, t_graph *g)
1033 {
1034     rvec    xvi, xij, xik, fv, fj, fk;
1035     real    cfx, cfy, cfz;
1036     atom_id av, ai, aj, ak;
1037     ivec    di;
1038     int     svi, sji, ski;
1039
1040     av = ia[1];
1041     ai = ia[2];
1042     aj = ia[3];
1043     ak = ia[4];
1044
1045     sji = pbc_rvec_sub(pbc, x[aj], x[ai], xij);
1046     ski = pbc_rvec_sub(pbc, x[ak], x[ai], xik);
1047     /* 6 Flops */
1048
1049     copy_rvec(f[av], fv);
1050
1051     cfx = c*fv[XX];
1052     cfy = c*fv[YY];
1053     cfz = c*fv[ZZ];
1054     /* 3 Flops */
1055
1056     fj[XX] = a*fv[XX]     -  xik[ZZ]*cfy +  xik[YY]*cfz;
1057     fj[YY] =  xik[ZZ]*cfx + a*fv[YY]     -  xik[XX]*cfz;
1058     fj[ZZ] = -xik[YY]*cfx +  xik[XX]*cfy + a*fv[ZZ];
1059
1060     fk[XX] = b*fv[XX]     +  xij[ZZ]*cfy -  xij[YY]*cfz;
1061     fk[YY] = -xij[ZZ]*cfx + b*fv[YY]     +  xij[XX]*cfz;
1062     fk[ZZ] =  xij[YY]*cfx -  xij[XX]*cfy + b*fv[ZZ];
1063     /* 30 Flops */
1064
1065     f[ai][XX] += fv[XX] - fj[XX] - fk[XX];
1066     f[ai][YY] += fv[YY] - fj[YY] - fk[YY];
1067     f[ai][ZZ] += fv[ZZ] - fj[ZZ] - fk[ZZ];
1068     rvec_inc(f[aj], fj);
1069     rvec_inc(f[ak], fk);
1070     /* 15 Flops */
1071
1072     if (g)
1073     {
1074         ivec_sub(SHIFT_IVEC(g, ia[1]), SHIFT_IVEC(g, ai), di);
1075         svi = IVEC2IS(di);
1076         ivec_sub(SHIFT_IVEC(g, aj), SHIFT_IVEC(g, ai), di);
1077         sji = IVEC2IS(di);
1078         ivec_sub(SHIFT_IVEC(g, ak), SHIFT_IVEC(g, ai), di);
1079         ski = IVEC2IS(di);
1080     }
1081     else if (pbc)
1082     {
1083         svi = pbc_rvec_sub(pbc, x[av], x[ai], xvi);
1084     }
1085     else
1086     {
1087         svi = CENTRAL;
1088     }
1089
1090     if (fshift && (svi != CENTRAL || sji != CENTRAL || ski != CENTRAL))
1091     {
1092         rvec_dec(fshift[svi], fv);
1093         fshift[CENTRAL][XX] += fv[XX] - fj[XX] - fk[XX];
1094         fshift[CENTRAL][YY] += fv[YY] - fj[YY] - fk[YY];
1095         fshift[CENTRAL][ZZ] += fv[ZZ] - fj[ZZ] - fk[ZZ];
1096         rvec_inc(fshift[sji], fj);
1097         rvec_inc(fshift[ski], fk);
1098     }
1099
1100     if (VirCorr)
1101     {
1102         rvec xiv;
1103         int  i, j;
1104
1105         pbc_rvec_sub(pbc, x[av], x[ai], xiv);
1106
1107         for (i = 0; i < DIM; i++)
1108         {
1109             for (j = 0; j < DIM; j++)
1110             {
1111                 dxdf[i][j] += -xiv[i]*fv[j] + xij[i]*fj[j] + xik[i]*fk[j];
1112             }
1113         }
1114     }
1115
1116     /* TOTAL: 54 flops */
1117 }
1118
1119 static void spread_vsite4FD(t_iatom ia[], real a, real b, real c,
1120                             rvec x[], rvec f[], rvec fshift[],
1121                             gmx_bool VirCorr, matrix dxdf,
1122                             t_pbc *pbc, t_graph *g)
1123 {
1124     real    d, invl, fproj, a1;
1125     rvec    xvi, xij, xjk, xjl, xix, fv, temp;
1126     atom_id av, ai, aj, ak, al;
1127     ivec    di;
1128     int     svi, sji, skj, slj, m;
1129
1130     av = ia[1];
1131     ai = ia[2];
1132     aj = ia[3];
1133     ak = ia[4];
1134     al = ia[5];
1135
1136     sji = pbc_rvec_sub(pbc, x[aj], x[ai], xij);
1137     skj = pbc_rvec_sub(pbc, x[ak], x[aj], xjk);
1138     slj = pbc_rvec_sub(pbc, x[al], x[aj], xjl);
1139     /* 9 flops */
1140
1141     /* xix goes from i to point x on the plane jkl */
1142     for (m = 0; m < DIM; m++)
1143     {
1144         xix[m] = xij[m] + a*xjk[m] + b*xjl[m];
1145     }
1146     /* 12 flops */
1147
1148     invl = gmx_invsqrt(iprod(xix, xix));
1149     d    = c*invl;
1150     /* 4 + ?10? flops */
1151
1152     copy_rvec(f[av], fv);
1153
1154     fproj = iprod(xix, fv)*invl*invl; /* = (xix . f)/(xix . xix) */
1155
1156     for (m = 0; m < DIM; m++)
1157     {
1158         temp[m] = d*(fv[m] - fproj*xix[m]);
1159     }
1160     /* 16 */
1161
1162     /* c is already calculated in constr_vsite3FD
1163        storing c somewhere will save 35 flops!     */
1164
1165     a1 = 1 - a - b;
1166     for (m = 0; m < DIM; m++)
1167     {
1168         f[ai][m] += fv[m] - temp[m];
1169         f[aj][m] += a1*temp[m];
1170         f[ak][m] += a*temp[m];
1171         f[al][m] += b*temp[m];
1172     }
1173     /* 26 Flops */
1174
1175     if (g)
1176     {
1177         ivec_sub(SHIFT_IVEC(g, ia[1]), SHIFT_IVEC(g, ai), di);
1178         svi = IVEC2IS(di);
1179         ivec_sub(SHIFT_IVEC(g, aj), SHIFT_IVEC(g, ai), di);
1180         sji = IVEC2IS(di);
1181         ivec_sub(SHIFT_IVEC(g, ak), SHIFT_IVEC(g, aj), di);
1182         skj = IVEC2IS(di);
1183         ivec_sub(SHIFT_IVEC(g, al), SHIFT_IVEC(g, aj), di);
1184         slj = IVEC2IS(di);
1185     }
1186     else if (pbc)
1187     {
1188         svi = pbc_rvec_sub(pbc, x[av], x[ai], xvi);
1189     }
1190     else
1191     {
1192         svi = CENTRAL;
1193     }
1194
1195     if (fshift &&
1196         (svi != CENTRAL || sji != CENTRAL || skj != CENTRAL || slj != CENTRAL))
1197     {
1198         rvec_dec(fshift[svi], fv);
1199         for (m = 0; m < DIM; m++)
1200         {
1201             fshift[CENTRAL][m] += fv[m] - (1 + a + b)*temp[m];
1202             fshift[    sji][m] += temp[m];
1203             fshift[    skj][m] += a*temp[m];
1204             fshift[    slj][m] += b*temp[m];
1205         }
1206     }
1207
1208     if (VirCorr)
1209     {
1210         rvec xiv;
1211         int  i, j;
1212
1213         pbc_rvec_sub(pbc, x[av], x[ai], xiv);
1214
1215         for (i = 0; i < DIM; i++)
1216         {
1217             for (j = 0; j < DIM; j++)
1218             {
1219                 dxdf[i][j] += -xiv[i]*fv[j] + xix[i]*temp[j];
1220             }
1221         }
1222     }
1223
1224     /* TOTAL: 77 flops */
1225 }
1226
1227
1228 static void spread_vsite4FDN(t_iatom ia[], real a, real b, real c,
1229                              rvec x[], rvec f[], rvec fshift[],
1230                              gmx_bool VirCorr, matrix dxdf,
1231                              t_pbc *pbc, t_graph *g)
1232 {
1233     rvec xvi, xij, xik, xil, ra, rb, rja, rjb, rab, rm, rt;
1234     rvec fv, fj, fk, fl;
1235     real invrm, denom;
1236     real cfx, cfy, cfz;
1237     ivec di;
1238     int  av, ai, aj, ak, al;
1239     int  svi, sij, sik, sil;
1240
1241     /* DEBUG: check atom indices */
1242     av = ia[1];
1243     ai = ia[2];
1244     aj = ia[3];
1245     ak = ia[4];
1246     al = ia[5];
1247
1248     copy_rvec(f[av], fv);
1249
1250     sij = pbc_rvec_sub(pbc, x[aj], x[ai], xij);
1251     sik = pbc_rvec_sub(pbc, x[ak], x[ai], xik);
1252     sil = pbc_rvec_sub(pbc, x[al], x[ai], xil);
1253     /* 9 flops */
1254
1255     ra[XX] = a*xik[XX];
1256     ra[YY] = a*xik[YY];
1257     ra[ZZ] = a*xik[ZZ];
1258
1259     rb[XX] = b*xil[XX];
1260     rb[YY] = b*xil[YY];
1261     rb[ZZ] = b*xil[ZZ];
1262
1263     /* 6 flops */
1264
1265     rvec_sub(ra, xij, rja);
1266     rvec_sub(rb, xij, rjb);
1267     rvec_sub(rb, ra, rab);
1268     /* 9 flops */
1269
1270     cprod(rja, rjb, rm);
1271     /* 9 flops */
1272
1273     invrm = gmx_invsqrt(norm2(rm));
1274     denom = invrm*invrm;
1275     /* 5+5+2 flops */
1276
1277     cfx = c*invrm*fv[XX];
1278     cfy = c*invrm*fv[YY];
1279     cfz = c*invrm*fv[ZZ];
1280     /* 6 Flops */
1281
1282     cprod(rm, rab, rt);
1283     /* 9 flops */
1284
1285     rt[XX] *= denom;
1286     rt[YY] *= denom;
1287     rt[ZZ] *= denom;
1288     /* 3flops */
1289
1290     fj[XX] = (        -rm[XX]*rt[XX]) * cfx + ( rab[ZZ]-rm[YY]*rt[XX]) * cfy + (-rab[YY]-rm[ZZ]*rt[XX]) * cfz;
1291     fj[YY] = (-rab[ZZ]-rm[XX]*rt[YY]) * cfx + (        -rm[YY]*rt[YY]) * cfy + ( rab[XX]-rm[ZZ]*rt[YY]) * cfz;
1292     fj[ZZ] = ( rab[YY]-rm[XX]*rt[ZZ]) * cfx + (-rab[XX]-rm[YY]*rt[ZZ]) * cfy + (        -rm[ZZ]*rt[ZZ]) * cfz;
1293     /* 30 flops */
1294
1295     cprod(rjb, rm, rt);
1296     /* 9 flops */
1297
1298     rt[XX] *= denom*a;
1299     rt[YY] *= denom*a;
1300     rt[ZZ] *= denom*a;
1301     /* 3flops */
1302
1303     fk[XX] = (          -rm[XX]*rt[XX]) * cfx + (-a*rjb[ZZ]-rm[YY]*rt[XX]) * cfy + ( a*rjb[YY]-rm[ZZ]*rt[XX]) * cfz;
1304     fk[YY] = ( a*rjb[ZZ]-rm[XX]*rt[YY]) * cfx + (          -rm[YY]*rt[YY]) * cfy + (-a*rjb[XX]-rm[ZZ]*rt[YY]) * cfz;
1305     fk[ZZ] = (-a*rjb[YY]-rm[XX]*rt[ZZ]) * cfx + ( a*rjb[XX]-rm[YY]*rt[ZZ]) * cfy + (          -rm[ZZ]*rt[ZZ]) * cfz;
1306     /* 36 flops */
1307
1308     cprod(rm, rja, rt);
1309     /* 9 flops */
1310
1311     rt[XX] *= denom*b;
1312     rt[YY] *= denom*b;
1313     rt[ZZ] *= denom*b;
1314     /* 3flops */
1315
1316     fl[XX] = (          -rm[XX]*rt[XX]) * cfx + ( b*rja[ZZ]-rm[YY]*rt[XX]) * cfy + (-b*rja[YY]-rm[ZZ]*rt[XX]) * cfz;
1317     fl[YY] = (-b*rja[ZZ]-rm[XX]*rt[YY]) * cfx + (          -rm[YY]*rt[YY]) * cfy + ( b*rja[XX]-rm[ZZ]*rt[YY]) * cfz;
1318     fl[ZZ] = ( b*rja[YY]-rm[XX]*rt[ZZ]) * cfx + (-b*rja[XX]-rm[YY]*rt[ZZ]) * cfy + (          -rm[ZZ]*rt[ZZ]) * cfz;
1319     /* 36 flops */
1320
1321     f[ai][XX] += fv[XX] - fj[XX] - fk[XX] - fl[XX];
1322     f[ai][YY] += fv[YY] - fj[YY] - fk[YY] - fl[YY];
1323     f[ai][ZZ] += fv[ZZ] - fj[ZZ] - fk[ZZ] - fl[ZZ];
1324     rvec_inc(f[aj], fj);
1325     rvec_inc(f[ak], fk);
1326     rvec_inc(f[al], fl);
1327     /* 21 flops */
1328
1329     if (g)
1330     {
1331         ivec_sub(SHIFT_IVEC(g, av), SHIFT_IVEC(g, ai), di);
1332         svi = IVEC2IS(di);
1333         ivec_sub(SHIFT_IVEC(g, aj), SHIFT_IVEC(g, ai), di);
1334         sij = IVEC2IS(di);
1335         ivec_sub(SHIFT_IVEC(g, ak), SHIFT_IVEC(g, ai), di);
1336         sik = IVEC2IS(di);
1337         ivec_sub(SHIFT_IVEC(g, al), SHIFT_IVEC(g, ai), di);
1338         sil = IVEC2IS(di);
1339     }
1340     else if (pbc)
1341     {
1342         svi = pbc_rvec_sub(pbc, x[av], x[ai], xvi);
1343     }
1344     else
1345     {
1346         svi = CENTRAL;
1347     }
1348
1349     if (fshift && (svi != CENTRAL || sij != CENTRAL || sik != CENTRAL || sil != CENTRAL))
1350     {
1351         rvec_dec(fshift[svi], fv);
1352         fshift[CENTRAL][XX] += fv[XX] - fj[XX] - fk[XX] - fl[XX];
1353         fshift[CENTRAL][YY] += fv[YY] - fj[YY] - fk[YY] - fl[YY];
1354         fshift[CENTRAL][ZZ] += fv[ZZ] - fj[ZZ] - fk[ZZ] - fl[ZZ];
1355         rvec_inc(fshift[sij], fj);
1356         rvec_inc(fshift[sik], fk);
1357         rvec_inc(fshift[sil], fl);
1358     }
1359
1360     if (VirCorr)
1361     {
1362         rvec xiv;
1363         int  i, j;
1364
1365         pbc_rvec_sub(pbc, x[av], x[ai], xiv);
1366
1367         for (i = 0; i < DIM; i++)
1368         {
1369             for (j = 0; j < DIM; j++)
1370             {
1371                 dxdf[i][j] += -xiv[i]*fv[j] + xij[i]*fj[j] + xik[i]*fk[j] + xil[i]*fl[j];
1372             }
1373         }
1374     }
1375
1376     /* Total: 207 flops (Yuck!) */
1377 }
1378
1379
1380 static int spread_vsiten(t_iatom ia[], t_iparams ip[],
1381                          rvec x[], rvec f[], rvec fshift[],
1382                          t_pbc *pbc, t_graph *g)
1383 {
1384     rvec xv, dx, fi;
1385     int  n3, av, i, ai;
1386     real a;
1387     ivec di;
1388     int  siv;
1389
1390     n3 = 3*ip[ia[0]].vsiten.n;
1391     av = ia[1];
1392     copy_rvec(x[av], xv);
1393
1394     for (i = 0; i < n3; i += 3)
1395     {
1396         ai = ia[i+2];
1397         if (g)
1398         {
1399             ivec_sub(SHIFT_IVEC(g, ai), SHIFT_IVEC(g, av), di);
1400             siv = IVEC2IS(di);
1401         }
1402         else if (pbc)
1403         {
1404             siv = pbc_dx_aiuc(pbc, x[ai], xv, dx);
1405         }
1406         else
1407         {
1408             siv = CENTRAL;
1409         }
1410         a = ip[ia[i]].vsiten.a;
1411         svmul(a, f[av], fi);
1412         rvec_inc(f[ai], fi);
1413         if (fshift && siv != CENTRAL)
1414         {
1415             rvec_inc(fshift[siv], fi);
1416             rvec_dec(fshift[CENTRAL], fi);
1417         }
1418         /* 6 Flops */
1419     }
1420
1421     return n3;
1422 }
1423
1424
1425 static int vsite_count(const t_ilist *ilist, int ftype)
1426 {
1427     if (ftype == F_VSITEN)
1428     {
1429         return ilist[ftype].nr/3;
1430     }
1431     else
1432     {
1433         return ilist[ftype].nr/(1 + interaction_function[ftype].nratoms);
1434     }
1435 }
1436
1437 static void spread_vsite_f_thread(gmx_vsite_t *vsite,
1438                                   rvec x[], rvec f[], rvec *fshift,
1439                                   gmx_bool VirCorr, matrix dxdf,
1440                                   t_iparams ip[], t_ilist ilist[],
1441                                   t_graph *g, t_pbc *pbc_null)
1442 {
1443     gmx_bool   bPBCAll;
1444     real       a1, b1, c1;
1445     int        i, inc, m, nra, nr, tp, ftype;
1446     t_iatom   *ia;
1447     t_pbc     *pbc_null2;
1448     int       *vsite_pbc;
1449
1450     if (VirCorr)
1451     {
1452         clear_mat(dxdf);
1453     }
1454
1455     bPBCAll = (pbc_null != NULL && !vsite->bHaveChargeGroups);
1456
1457     /* this loop goes backwards to be able to build *
1458      * higher type vsites from lower types         */
1459     pbc_null2 = NULL;
1460     vsite_pbc = NULL;
1461     for (ftype = F_NRE-1; (ftype >= 0); ftype--)
1462     {
1463         if ((interaction_function[ftype].flags & IF_VSITE) &&
1464             ilist[ftype].nr > 0)
1465         {
1466             nra    = interaction_function[ftype].nratoms;
1467             inc    = 1 + nra;
1468             nr     = ilist[ftype].nr;
1469             ia     = ilist[ftype].iatoms;
1470
1471             if (bPBCAll)
1472             {
1473                 pbc_null2 = pbc_null;
1474             }
1475             else if (pbc_null != NULL)
1476             {
1477                 vsite_pbc = vsite->vsite_pbc_loc[ftype-F_VSITE2];
1478             }
1479
1480             for (i = 0; i < nr; )
1481             {
1482                 if (vsite_pbc != NULL)
1483                 {
1484                     if (vsite_pbc[i/(1+nra)] > -2)
1485                     {
1486                         pbc_null2 = pbc_null;
1487                     }
1488                     else
1489                     {
1490                         pbc_null2 = NULL;
1491                     }
1492                 }
1493
1494                 tp   = ia[0];
1495
1496                 /* Constants for constructing */
1497                 a1   = ip[tp].vsite.a;
1498                 /* Construct the vsite depending on type */
1499                 switch (ftype)
1500                 {
1501                     case F_VSITE2:
1502                         spread_vsite2(ia, a1, x, f, fshift, pbc_null2, g);
1503                         break;
1504                     case F_VSITE3:
1505                         b1 = ip[tp].vsite.b;
1506                         spread_vsite3(ia, a1, b1, x, f, fshift, pbc_null2, g);
1507                         break;
1508                     case F_VSITE3FD:
1509                         b1 = ip[tp].vsite.b;
1510                         spread_vsite3FD(ia, a1, b1, x, f, fshift, VirCorr, dxdf, pbc_null2, g);
1511                         break;
1512                     case F_VSITE3FAD:
1513                         b1 = ip[tp].vsite.b;
1514                         spread_vsite3FAD(ia, a1, b1, x, f, fshift, VirCorr, dxdf, pbc_null2, g);
1515                         break;
1516                     case F_VSITE3OUT:
1517                         b1 = ip[tp].vsite.b;
1518                         c1 = ip[tp].vsite.c;
1519                         spread_vsite3OUT(ia, a1, b1, c1, x, f, fshift, VirCorr, dxdf, pbc_null2, g);
1520                         break;
1521                     case F_VSITE4FD:
1522                         b1 = ip[tp].vsite.b;
1523                         c1 = ip[tp].vsite.c;
1524                         spread_vsite4FD(ia, a1, b1, c1, x, f, fshift, VirCorr, dxdf, pbc_null2, g);
1525                         break;
1526                     case F_VSITE4FDN:
1527                         b1 = ip[tp].vsite.b;
1528                         c1 = ip[tp].vsite.c;
1529                         spread_vsite4FDN(ia, a1, b1, c1, x, f, fshift, VirCorr, dxdf, pbc_null2, g);
1530                         break;
1531                     case F_VSITEN:
1532                         inc = spread_vsiten(ia, ip, x, f, fshift, pbc_null2, g);
1533                         break;
1534                     default:
1535                         gmx_fatal(FARGS, "No such vsite type %d in %s, line %d",
1536                                   ftype, __FILE__, __LINE__);
1537                 }
1538                 clear_rvec(f[ia[1]]);
1539
1540                 /* Increment loop variables */
1541                 i  += inc;
1542                 ia += inc;
1543             }
1544         }
1545     }
1546 }
1547
1548 void spread_vsite_f(FILE *log, gmx_vsite_t *vsite,
1549                     rvec x[], rvec f[], rvec *fshift,
1550                     gmx_bool VirCorr, matrix vir,
1551                     t_nrnb *nrnb, t_idef *idef,
1552                     int ePBC, gmx_bool bMolPBC, t_graph *g, matrix box,
1553                     t_commrec *cr)
1554 {
1555     t_pbc pbc, *pbc_null;
1556     int   th;
1557
1558     /* We only need to do pbc when we have inter-cg vsites */
1559     if ((DOMAINDECOMP(cr) || bMolPBC) && vsite->n_intercg_vsite)
1560     {
1561         /* This is wasting some CPU time as we now do this multiple times
1562          * per MD step. But how often do we have vsites with full pbc?
1563          */
1564         pbc_null = set_pbc_dd(&pbc, ePBC, cr->dd, FALSE, box);
1565     }
1566     else
1567     {
1568         pbc_null = NULL;
1569     }
1570
1571     if (DOMAINDECOMP(cr))
1572     {
1573         dd_clear_f_vsites(cr->dd, f);
1574     }
1575     else if (PARTDECOMP(cr) && vsite->vsitecomm != NULL)
1576     {
1577         pd_clear_nonlocal_constructs(vsite->vsitecomm, f);
1578     }
1579
1580     if (vsite->nthreads == 1)
1581     {
1582         spread_vsite_f_thread(vsite,
1583                               x, f, fshift,
1584                               VirCorr, vsite->tdata[0].dxdf,
1585                               idef->iparams, idef->il,
1586                               g, pbc_null);
1587     }
1588     else
1589     {
1590         /* First spread the vsites that might depend on other vsites */
1591         spread_vsite_f_thread(vsite,
1592                               x, f, fshift,
1593                               VirCorr, vsite->tdata[vsite->nthreads].dxdf,
1594                               idef->iparams,
1595                               vsite->tdata[vsite->nthreads].ilist,
1596                               g, pbc_null);
1597
1598 #pragma omp parallel num_threads(vsite->nthreads)
1599         {
1600             int   thread;
1601             rvec *fshift_t;
1602
1603             thread = gmx_omp_get_thread_num();
1604
1605             if (thread == 0 || fshift == NULL)
1606             {
1607                 fshift_t = fshift;
1608             }
1609             else
1610             {
1611                 int i;
1612
1613                 fshift_t = vsite->tdata[thread].fshift;
1614
1615                 for (i = 0; i < SHIFTS; i++)
1616                 {
1617                     clear_rvec(fshift_t[i]);
1618                 }
1619             }
1620
1621             spread_vsite_f_thread(vsite,
1622                                   x, f, fshift_t,
1623                                   VirCorr, vsite->tdata[thread].dxdf,
1624                                   idef->iparams,
1625                                   vsite->tdata[thread].ilist,
1626                                   g, pbc_null);
1627         }
1628
1629         if (fshift != NULL)
1630         {
1631             int i;
1632
1633             for (th = 1; th < vsite->nthreads; th++)
1634             {
1635                 for (i = 0; i < SHIFTS; i++)
1636                 {
1637                     rvec_inc(fshift[i], vsite->tdata[th].fshift[i]);
1638                 }
1639             }
1640         }
1641     }
1642
1643     if (VirCorr)
1644     {
1645         int i, j;
1646
1647         for (th = 0; th < (vsite->nthreads == 1 ? 1 : vsite->nthreads+1); th++)
1648         {
1649             for (i = 0; i < DIM; i++)
1650             {
1651                 for (j = 0; j < DIM; j++)
1652                 {
1653                     vir[i][j] += -0.5*vsite->tdata[th].dxdf[i][j];
1654                 }
1655             }
1656         }
1657     }
1658
1659     if (DOMAINDECOMP(cr))
1660     {
1661         dd_move_f_vsites(cr->dd, f, fshift);
1662     }
1663     else if (vsite->bPDvsitecomm)
1664     {
1665         /* We only move forces here, and they are independent of shifts */
1666         move_construct_f(vsite->vsitecomm, f, cr);
1667     }
1668
1669     inc_nrnb(nrnb, eNR_VSITE2,   vsite_count(idef->il, F_VSITE2));
1670     inc_nrnb(nrnb, eNR_VSITE3,   vsite_count(idef->il, F_VSITE3));
1671     inc_nrnb(nrnb, eNR_VSITE3FD, vsite_count(idef->il, F_VSITE3FD));
1672     inc_nrnb(nrnb, eNR_VSITE3FAD, vsite_count(idef->il, F_VSITE3FAD));
1673     inc_nrnb(nrnb, eNR_VSITE3OUT, vsite_count(idef->il, F_VSITE3OUT));
1674     inc_nrnb(nrnb, eNR_VSITE4FD, vsite_count(idef->il, F_VSITE4FD));
1675     inc_nrnb(nrnb, eNR_VSITE4FDN, vsite_count(idef->il, F_VSITE4FDN));
1676     inc_nrnb(nrnb, eNR_VSITEN,   vsite_count(idef->il, F_VSITEN));
1677 }
1678
1679 static int *atom2cg(t_block *cgs)
1680 {
1681     int *a2cg, cg, i;
1682
1683     snew(a2cg, cgs->index[cgs->nr]);
1684     for (cg = 0; cg < cgs->nr; cg++)
1685     {
1686         for (i = cgs->index[cg]; i < cgs->index[cg+1]; i++)
1687         {
1688             a2cg[i] = cg;
1689         }
1690     }
1691
1692     return a2cg;
1693 }
1694
1695 static int count_intercg_vsite(gmx_mtop_t *mtop,
1696                                gmx_bool   *bHaveChargeGroups)
1697 {
1698     int             mb, mt, ftype, nral, i, cg, a;
1699     gmx_molblock_t *molb;
1700     gmx_moltype_t  *molt;
1701     int            *a2cg;
1702     t_ilist        *il;
1703     t_iatom        *ia;
1704     int             n_intercg_vsite;
1705
1706     *bHaveChargeGroups = FALSE;
1707
1708     n_intercg_vsite = 0;
1709     for (mb = 0; mb < mtop->nmolblock; mb++)
1710     {
1711         molb = &mtop->molblock[mb];
1712         molt = &mtop->moltype[molb->type];
1713
1714         if (molt->cgs.nr < molt->atoms.nr)
1715         {
1716             *bHaveChargeGroups = TRUE;
1717         }
1718
1719         a2cg = atom2cg(&molt->cgs);
1720         for (ftype = 0; ftype < F_NRE; ftype++)
1721         {
1722             if (interaction_function[ftype].flags & IF_VSITE)
1723             {
1724                 nral = NRAL(ftype);
1725                 il   = &molt->ilist[ftype];
1726                 ia   = il->iatoms;
1727                 for (i = 0; i < il->nr; i += 1+nral)
1728                 {
1729                     cg = a2cg[ia[1+i]];
1730                     for (a = 1; a < nral; a++)
1731                     {
1732                         if (a2cg[ia[1+a]] != cg)
1733                         {
1734                             n_intercg_vsite += molb->nmol;
1735                             break;
1736                         }
1737                     }
1738                 }
1739             }
1740         }
1741         sfree(a2cg);
1742     }
1743
1744     return n_intercg_vsite;
1745 }
1746
1747 static int **get_vsite_pbc(t_iparams *iparams, t_ilist *ilist,
1748                            t_atom *atom, t_mdatoms *md,
1749                            t_block *cgs, int *a2cg)
1750 {
1751     int      ftype, nral, i, j, vsi, vsite, cg_v, cg_c, a, nc3 = 0;
1752     t_ilist *il;
1753     t_iatom *ia;
1754     int    **vsite_pbc, *vsite_pbc_f;
1755     char    *pbc_set;
1756     gmx_bool bViteOnlyCG_and_FirstAtom;
1757
1758     /* Make an array that tells if the pbc of an atom is set */
1759     snew(pbc_set, cgs->index[cgs->nr]);
1760     /* PBC is set for all non vsites */
1761     for (a = 0; a < cgs->index[cgs->nr]; a++)
1762     {
1763         if ((atom && atom[a].ptype != eptVSite) ||
1764             (md   && md->ptype[a]  != eptVSite))
1765         {
1766             pbc_set[a] = 1;
1767         }
1768     }
1769
1770     snew(vsite_pbc, F_VSITEN-F_VSITE2+1);
1771
1772     for (ftype = 0; ftype < F_NRE; ftype++)
1773     {
1774         if (interaction_function[ftype].flags & IF_VSITE)
1775         {
1776             nral = NRAL(ftype);
1777             il   = &ilist[ftype];
1778             ia   = il->iatoms;
1779
1780             snew(vsite_pbc[ftype-F_VSITE2], il->nr/(1+nral));
1781             vsite_pbc_f = vsite_pbc[ftype-F_VSITE2];
1782
1783             i = 0;
1784             while (i < il->nr)
1785             {
1786                 vsi   = i/(1+nral);
1787                 vsite = ia[i+1];
1788                 cg_v  = a2cg[vsite];
1789                 /* A value of -2 signals that this vsite and its contructing
1790                  * atoms are all within the same cg, so no pbc is required.
1791                  */
1792                 vsite_pbc_f[vsi] = -2;
1793                 /* Check if constructing atoms are outside the vsite's cg */
1794                 nc3 = 0;
1795                 if (ftype == F_VSITEN)
1796                 {
1797                     nc3 = 3*iparams[ia[i]].vsiten.n;
1798                     for (j = 0; j < nc3; j += 3)
1799                     {
1800                         if (a2cg[ia[i+j+2]] != cg_v)
1801                         {
1802                             vsite_pbc_f[vsi] = -1;
1803                         }
1804                     }
1805                 }
1806                 else
1807                 {
1808                     for (a = 1; a < nral; a++)
1809                     {
1810                         if (a2cg[ia[i+1+a]] != cg_v)
1811                         {
1812                             vsite_pbc_f[vsi] = -1;
1813                         }
1814                     }
1815                 }
1816                 if (vsite_pbc_f[vsi] == -1)
1817                 {
1818                     /* Check if this is the first processed atom of a vsite only cg */
1819                     bViteOnlyCG_and_FirstAtom = TRUE;
1820                     for (a = cgs->index[cg_v]; a < cgs->index[cg_v+1]; a++)
1821                     {
1822                         /* Non-vsites already have pbc set, so simply check for pbc_set */
1823                         if (pbc_set[a])
1824                         {
1825                             bViteOnlyCG_and_FirstAtom = FALSE;
1826                             break;
1827                         }
1828                     }
1829                     if (bViteOnlyCG_and_FirstAtom)
1830                     {
1831                         /* First processed atom of a vsite only charge group.
1832                          * The pbc of the input coordinates to construct_vsites
1833                          * should be preserved.
1834                          */
1835                         vsite_pbc_f[vsi] = vsite;
1836                     }
1837                     else if (cg_v != a2cg[ia[1+i+1]])
1838                     {
1839                         /* This vsite has a different charge group index
1840                          * than it's first constructing atom
1841                          * and the charge group has more than one atom,
1842                          * search for the first normal particle
1843                          * or vsite that already had its pbc defined.
1844                          * If nothing is found, use full pbc for this vsite.
1845                          */
1846                         for (a = cgs->index[cg_v]; a < cgs->index[cg_v+1]; a++)
1847                         {
1848                             if (a != vsite && pbc_set[a])
1849                             {
1850                                 vsite_pbc_f[vsi] = a;
1851                                 if (gmx_debug_at)
1852                                 {
1853                                     fprintf(debug, "vsite %d match pbc with atom %d\n",
1854                                             vsite+1, a+1);
1855                                 }
1856                                 break;
1857                             }
1858                         }
1859                         if (gmx_debug_at)
1860                         {
1861                             fprintf(debug, "vsite atom %d  cg %d - %d pbc atom %d\n",
1862                                     vsite+1, cgs->index[cg_v]+1, cgs->index[cg_v+1],
1863                                     vsite_pbc_f[vsi]+1);
1864                         }
1865                     }
1866                 }
1867                 if (ftype == F_VSITEN)
1868                 {
1869                     /* The other entries in vsite_pbc_f are not used for center vsites */
1870                     i += nc3;
1871                 }
1872                 else
1873                 {
1874                     i += 1+nral;
1875                 }
1876
1877                 /* This vsite now has its pbc defined */
1878                 pbc_set[vsite] = 1;
1879             }
1880         }
1881     }
1882
1883     sfree(pbc_set);
1884
1885     return vsite_pbc;
1886 }
1887
1888
1889 gmx_vsite_t *init_vsite(gmx_mtop_t *mtop, t_commrec *cr,
1890                         gmx_bool bSerial_NoPBC)
1891 {
1892     int            nvsite, i;
1893     int           *a2cg, cg;
1894     gmx_vsite_t   *vsite;
1895     int            mt;
1896     gmx_moltype_t *molt;
1897     int            nthreads;
1898
1899     /* check if there are vsites */
1900     nvsite = 0;
1901     for (i = 0; i < F_NRE; i++)
1902     {
1903         if (interaction_function[i].flags & IF_VSITE)
1904         {
1905             nvsite += gmx_mtop_ftype_count(mtop, i);
1906         }
1907     }
1908
1909     if (nvsite == 0)
1910     {
1911         return NULL;
1912     }
1913
1914     snew(vsite, 1);
1915
1916     vsite->n_intercg_vsite = count_intercg_vsite(mtop,
1917                                                  &vsite->bHaveChargeGroups);
1918
1919     /* If we don't have charge groups, the vsite follows its own pbc */
1920     if (!bSerial_NoPBC &&
1921         vsite->bHaveChargeGroups &&
1922         vsite->n_intercg_vsite > 0 && DOMAINDECOMP(cr))
1923     {
1924         vsite->nvsite_pbc_molt = mtop->nmoltype;
1925         snew(vsite->vsite_pbc_molt, vsite->nvsite_pbc_molt);
1926         for (mt = 0; mt < mtop->nmoltype; mt++)
1927         {
1928             molt = &mtop->moltype[mt];
1929             /* Make an atom to charge group index */
1930             a2cg = atom2cg(&molt->cgs);
1931             vsite->vsite_pbc_molt[mt] = get_vsite_pbc(mtop->ffparams.iparams,
1932                                                       molt->ilist,
1933                                                       molt->atoms.atom, NULL,
1934                                                       &molt->cgs, a2cg);
1935             sfree(a2cg);
1936         }
1937
1938         snew(vsite->vsite_pbc_loc_nalloc, F_VSITEN-F_VSITE2+1);
1939         snew(vsite->vsite_pbc_loc, F_VSITEN-F_VSITE2+1);
1940     }
1941
1942     if (bSerial_NoPBC)
1943     {
1944         vsite->nthreads = 1;
1945     }
1946     else
1947     {
1948         vsite->nthreads = gmx_omp_nthreads_get(emntVSITE);
1949     }
1950     if (!bSerial_NoPBC)
1951     {
1952         /* We need one extra thread data structure for the overlap vsites */
1953         snew(vsite->tdata, vsite->nthreads+1);
1954     }
1955
1956     vsite->th_ind        = NULL;
1957     vsite->th_ind_nalloc = 0;
1958
1959     return vsite;
1960 }
1961
1962 static void prepare_vsite_thread(const t_ilist      *ilist,
1963                                  gmx_vsite_thread_t *vsite_th)
1964 {
1965     int ftype;
1966
1967     for (ftype = 0; ftype < F_NRE; ftype++)
1968     {
1969         if (interaction_function[ftype].flags & IF_VSITE)
1970         {
1971             if (ilist[ftype].nr > vsite_th->ilist[ftype].nalloc)
1972             {
1973                 vsite_th->ilist[ftype].nalloc = over_alloc_large(ilist[ftype].nr);
1974                 srenew(vsite_th->ilist[ftype].iatoms, vsite_th->ilist[ftype].nalloc);
1975             }
1976
1977             vsite_th->ilist[ftype].nr = 0;
1978         }
1979     }
1980 }
1981
1982 void split_vsites_over_threads(const t_ilist   *ilist,
1983                                const t_mdatoms *mdatoms,
1984                                gmx_bool         bLimitRange,
1985                                gmx_vsite_t     *vsite)
1986 {
1987     int      th;
1988     int      vsite_atom_range, natperthread;
1989     int     *th_ind;
1990     int      ftype;
1991     t_iatom *iat;
1992     t_ilist *il_th;
1993     int      nral1, inc, i, j;
1994
1995     if (vsite->nthreads == 1)
1996     {
1997         /* Nothing to do */
1998         return;
1999     }
2000
2001 #pragma omp parallel for num_threads(vsite->nthreads) schedule(static)
2002     for (th = 0; th < vsite->nthreads; th++)
2003     {
2004         prepare_vsite_thread(ilist, &vsite->tdata[th]);
2005     }
2006     /* Master threads does the (potential) overlap vsites */
2007     prepare_vsite_thread(ilist, &vsite->tdata[vsite->nthreads]);
2008
2009     /* The current way of distributing the vsites over threads in primitive.
2010      * We divide the atom range 0 - natoms_in_vsite uniformly over threads,
2011      * without taking into account how the vsites are distributed.
2012      * Without domain decomposition we bLimitRange=TRUE and we at least
2013      * tighten the upper bound of the range (useful for common systems
2014      * such as a vsite-protein in 3-site water).
2015      */
2016     if (bLimitRange)
2017     {
2018         vsite_atom_range = -1;
2019         for (ftype = 0; ftype < F_NRE; ftype++)
2020         {
2021             if ((interaction_function[ftype].flags & IF_VSITE) &&
2022                 ftype != F_VSITEN)
2023             {
2024                 nral1 = 1 + NRAL(ftype);
2025                 iat   = ilist[ftype].iatoms;
2026                 for (i = 0; i < ilist[ftype].nr; i += nral1)
2027                 {
2028                     for (j = i+1; j < i+nral1; j++)
2029                     {
2030                         vsite_atom_range = max(vsite_atom_range, iat[j]);
2031                     }
2032                 }
2033             }
2034         }
2035         vsite_atom_range++;
2036     }
2037     else
2038     {
2039         vsite_atom_range = mdatoms->homenr;
2040     }
2041     natperthread = (vsite_atom_range + vsite->nthreads - 1)/vsite->nthreads;
2042
2043     if (debug)
2044     {
2045         fprintf(debug, "virtual site thread dist: natoms %d, range %d, natperthread %d\n", mdatoms->nr, vsite_atom_range, natperthread);
2046     }
2047
2048     /* To simplify the vsite assignment, we make an index which tells us
2049      * to which thread particles, both non-vsites and vsites, are assigned.
2050      */
2051     if (mdatoms->nr > vsite->th_ind_nalloc)
2052     {
2053         vsite->th_ind_nalloc = over_alloc_large(mdatoms->nr);
2054         srenew(vsite->th_ind, vsite->th_ind_nalloc);
2055     }
2056     th_ind = vsite->th_ind;
2057     th     = 0;
2058     for (i = 0; i < mdatoms->nr; i++)
2059     {
2060         if (mdatoms->ptype[i] == eptVSite)
2061         {
2062             /* vsites are not assigned to a thread yet */
2063             th_ind[i] = -1;
2064         }
2065         else
2066         {
2067             /* assign non-vsite particles to thread th */
2068             th_ind[i] = th;
2069         }
2070         if (i == (th + 1)*natperthread && th < vsite->nthreads)
2071         {
2072             th++;
2073         }
2074     }
2075
2076     for (ftype = 0; ftype < F_NRE; ftype++)
2077     {
2078         if ((interaction_function[ftype].flags & IF_VSITE) &&
2079             ftype != F_VSITEN)
2080         {
2081             nral1 = 1 + NRAL(ftype);
2082             inc   = nral1;
2083             iat   = ilist[ftype].iatoms;
2084             for (i = 0; i < ilist[ftype].nr; )
2085             {
2086                 th = iat[1+i]/natperthread;
2087                 /* We would like to assign this vsite the thread th,
2088                  * but it might depend on atoms outside the atom range of th
2089                  * or on another vsite not assigned to thread th.
2090                  */
2091                 if (ftype != F_VSITEN)
2092                 {
2093                     for (j = i+2; j < i+nral1; j++)
2094                     {
2095                         if (th_ind[iat[j]] != th)
2096                         {
2097                             /* Some constructing atoms are not assigned to
2098                              * thread th, move this vsite to a separate batch.
2099                              */
2100                             th = vsite->nthreads;
2101                         }
2102                     }
2103                 }
2104                 else
2105                 {
2106                     inc = iat[i];
2107                     for (j = i+2; j < i+inc; j += 3)
2108                     {
2109                         if (th_ind[iat[j]] != th)
2110                         {
2111                             th = vsite->nthreads;
2112                         }
2113                     }
2114                 }
2115                 /* Copy this vsite to the thread data struct of thread th */
2116                 il_th = &vsite->tdata[th].ilist[ftype];
2117                 for (j = i; j < i+inc; j++)
2118                 {
2119                     il_th->iatoms[il_th->nr++] = iat[j];
2120                 }
2121                 /* Update this vsite's thread index entry */
2122                 th_ind[iat[1+i]] = th;
2123
2124                 i += inc;
2125             }
2126         }
2127     }
2128
2129     if (debug)
2130     {
2131         for (ftype = 0; ftype < F_NRE; ftype++)
2132         {
2133             if ((interaction_function[ftype].flags & IF_VSITE) &&
2134                 ilist[ftype].nr > 0)
2135             {
2136                 fprintf(debug, "%-20s thread dist:",
2137                         interaction_function[ftype].longname);
2138                 for (th = 0; th < vsite->nthreads+1; th++)
2139                 {
2140                     fprintf(debug, " %4d", vsite->tdata[th].ilist[ftype].nr);
2141                 }
2142                 fprintf(debug, "\n");
2143             }
2144         }
2145     }
2146 }
2147
2148 void set_vsite_top(gmx_vsite_t *vsite, gmx_localtop_t *top, t_mdatoms *md,
2149                    t_commrec *cr)
2150 {
2151     int *a2cg;
2152
2153     if (vsite->n_intercg_vsite > 0)
2154     {
2155         if (vsite->bHaveChargeGroups)
2156         {
2157             /* Make an atom to charge group index */
2158             a2cg                 = atom2cg(&top->cgs);
2159             vsite->vsite_pbc_loc = get_vsite_pbc(top->idef.iparams,
2160                                                  top->idef.il, NULL, md,
2161                                                  &top->cgs, a2cg);
2162             sfree(a2cg);
2163         }
2164
2165         if (PARTDECOMP(cr))
2166         {
2167             snew(vsite->vsitecomm, 1);
2168             vsite->bPDvsitecomm =
2169                 setup_parallel_vsites(&(top->idef), cr, vsite->vsitecomm);
2170         }
2171     }
2172
2173     if (vsite->nthreads > 1)
2174     {
2175         if (vsite->bHaveChargeGroups || PARTDECOMP(cr))
2176         {
2177             gmx_incons("Can not use threads virtual sites combined with charge groups or particle decomposition");
2178         }
2179
2180         split_vsites_over_threads(top->idef.il, md, !DOMAINDECOMP(cr), vsite);
2181     }
2182 }