Merge release-5-0 into master
[alexxy/gromacs.git] / src / gromacs / mdlib / clincs.cpp
similarity index 96%
rename from src/gromacs/mdlib/clincs.c
rename to src/gromacs/mdlib/clincs.cpp
index 783ad72c8530158783b5eab8f7f3d647489c9f75..aa4e633f77e0729350f3b990760068ca7f8bafa8 100644 (file)
  * the research papers on the package. Check out http://www.gromacs.org.
  */
 /* This file is completely threadsafe - keep it that way! */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
+#include "gmxpre.h"
 
 #include <math.h>
-#include "main.h"
-#include "constr.h"
-#include "copyrite.h"
-#include "physics.h"
-#include "vec.h"
-#include "pbc.h"
-#include "gromacs/utility/smalloc.h"
-#include "mdrun.h"
-#include "nrnb.h"
-#include "domdec.h"
-#include "mtop_util.h"
-#include "gmx_omp_nthreads.h"
+#include <stdlib.h>
 
+#include "gromacs/domdec/domdec.h"
 #include "gromacs/fileio/gmxfio.h"
-#include "gmx_fatal.h"
+#include "gromacs/legacyheaders/constr.h"
+#include "gromacs/legacyheaders/copyrite.h"
+#include "gromacs/legacyheaders/gmx_omp_nthreads.h"
+#include "gromacs/legacyheaders/mdrun.h"
+#include "gromacs/legacyheaders/nrnb.h"
+#include "gromacs/legacyheaders/types/commrec.h"
+#include "gromacs/math/units.h"
+#include "gromacs/math/vec.h"
+#include "gromacs/mdlib/bitmask.h"
+#include "gromacs/pbcutil/pbc.h"
+#include "gromacs/topology/block.h"
+#include "gromacs/topology/mtop_util.h"
+#include "gromacs/utility/fatalerror.h"
 #include "gromacs/utility/gmxomp.h"
+#include "gromacs/utility/smalloc.h"
 
 typedef struct {
     int    b0;         /* first constraint for this thread */
@@ -97,7 +98,7 @@ typedef struct gmx_lincsdata {
     real           *bllen;        /* the reference bond length */
     int             nth;          /* The number of threads doing LINCS */
     lincs_thread_t *th;           /* LINCS thread division */
-    unsigned       *atf;          /* atom flags for thread parallelization */
+    gmx_bitmask_t  *atf;          /* atom flags for thread parallelization */
     int             atf_nalloc;   /* allocation size of atf */
     /* arrays for temporary storage in the LINCS algorithm */
     rvec           *tmpv;
@@ -364,7 +365,7 @@ static void do_lincsp(rvec *x, rvec *f, rvec *fp, t_pbc *pbc,
                       gmx_bool bCalcVir, tensor rmdf)
 {
     int      b0, b1, b, i, j, k, n;
-    real     tmp0, tmp1, tmp2, im1, im2, mvb, rlen, len, wfac, lam;
+    real     tmp0, tmp1, tmp2, mvb;
     rvec     dx;
     int     *bla, *blnr, *blbnb;
     rvec    *r;
@@ -508,7 +509,7 @@ static void do_lincs(rvec *x, rvec *xp, matrix box, t_pbc *pbc,
                      gmx_bool bCalcVir, tensor vir_r_m_dr)
 {
     int      b0, b1, b, i, j, k, n, iter;
-    real     tmp0, tmp1, tmp2, im1, im2, mvb, rlen, len, len2, dlen2, wfac;
+    real     tmp0, tmp1, tmp2, mvb, rlen, len, len2, dlen2, wfac;
     rvec     dx;
     int     *bla, *blnr, *blbnb;
     rvec    *r;
@@ -651,6 +652,7 @@ static void do_lincs(rvec *x, rvec *xp, matrix box, t_pbc *pbc,
             dlen2 = 2*len2 - norm2(dx);
             if (dlen2 < wfac*len2 && (nlocat == NULL || nlocat[b]))
             {
+                /* not race free - see detailed comment in caller */
                 *warn = b;
             }
             if (dlen2 > 0)
@@ -802,7 +804,7 @@ void set_lincs_matrix(struct gmx_lincsdata *li, real *invmass, real lambda)
                             li->triangle[li->ntriangle] = i;
                             li->tri_bits[li->ntriangle] = 0;
                             li->ntriangle++;
-                            if (li->blnr[i+1] - li->blnr[i] > sizeof(li->tri_bits[0])*8 - 1)
+                            if (li->blnr[i+1] - li->blnr[i] > static_cast<int>(sizeof(li->tri_bits[0])*8 - 1))
                             {
                                 gmx_fatal(FARGS, "A constraint is connected to %d constraints, this is more than the %d allowed for constraints participating in triangles",
                                           li->blnr[i+1] - li->blnr[i],
@@ -1034,7 +1036,7 @@ static void lincs_thread_setup(struct gmx_lincsdata *li, int natoms)
 {
     lincs_thread_t *li_m;
     int             th;
-    unsigned       *atf;
+    gmx_bitmask_t  *atf;
     int             a;
 
     if (natoms > li->atf_nalloc)
@@ -1047,7 +1049,12 @@ static void lincs_thread_setup(struct gmx_lincsdata *li, int natoms)
     /* Clear the atom flags */
     for (a = 0; a < natoms; a++)
     {
-        atf[a] = 0;
+        bitmask_clear(&atf[a]);
+    }
+
+    if (li->nth > BITMASK_SIZE)
+    {
+        gmx_fatal(FARGS, "More than %d threads is not supported for LINCS.", BITMASK_SIZE);
     }
 
     for (th = 0; th < li->nth; th++)
@@ -1061,14 +1068,11 @@ static void lincs_thread_setup(struct gmx_lincsdata *li, int natoms)
         li_th->b0 = (li->nc* th   )/li->nth;
         li_th->b1 = (li->nc*(th+1))/li->nth;
 
-        if (th < sizeof(*atf)*8)
+        /* For each atom set a flag for constraints from each */
+        for (b = li_th->b0; b < li_th->b1; b++)
         {
-            /* For each atom set a flag for constraints from each */
-            for (b = li_th->b0; b < li_th->b1; b++)
-            {
-                atf[li->bla[b*2]  ] |= (1U<<th);
-                atf[li->bla[b*2+1]] |= (1U<<th);
-            }
+            bitmask_set_bit(&atf[li->bla[b*2]], th);
+            bitmask_set_bit(&atf[li->bla[b*2+1]], th);
         }
     }
 
@@ -1076,7 +1080,7 @@ static void lincs_thread_setup(struct gmx_lincsdata *li, int natoms)
     for (th = 0; th < li->nth; th++)
     {
         lincs_thread_t *li_th;
-        unsigned        mask;
+        gmx_bitmask_t   mask;
         int             b;
 
         li_th = &li->th[th];
@@ -1088,35 +1092,24 @@ static void lincs_thread_setup(struct gmx_lincsdata *li, int natoms)
             srenew(li_th->ind_r, li_th->ind_nalloc);
         }
 
-        if (th < sizeof(*atf)*8)
-        {
-            mask = (1U<<th) - 1U;
+        bitmask_init_low_bits(&mask, th);
 
-            li_th->nind   = 0;
-            li_th->nind_r = 0;
-            for (b = li_th->b0; b < li_th->b1; b++)
+        li_th->nind   = 0;
+        li_th->nind_r = 0;
+        for (b = li_th->b0; b < li_th->b1; b++)
+        {
+            /* We let the constraint with the lowest thread index
+             * operate on atoms with constraints from multiple threads.
+             */
+            if (bitmask_is_disjoint(atf[li->bla[b*2]], mask) &&
+                bitmask_is_disjoint(atf[li->bla[b*2+1]], mask))
             {
-                /* We let the constraint with the lowest thread index
-                 * operate on atoms with constraints from multiple threads.
-                 */
-                if (((atf[li->bla[b*2]]   & mask) == 0) &&
-                    ((atf[li->bla[b*2+1]] & mask) == 0))
-                {
-                    /* Add the constraint to the local atom update index */
-                    li_th->ind[li_th->nind++] = b;
-                }
-                else
-                {
-                    /* Add the constraint to the rest block */
-                    li_th->ind_r[li_th->nind_r++] = b;
-                }
+                /* Add the constraint to the local atom update index */
+                li_th->ind[li_th->nind++] = b;
             }
-        }
-        else
-        {
-            /* We are out of bits, assign all constraints to rest */
-            for (b = li_th->b0; b < li_th->b1; b++)
+            else
             {
+                /* Add the constraint to the rest block */
                 li_th->ind_r[li_th->nind_r++] = b;
             }
         }
@@ -1171,7 +1164,6 @@ void set_lincs(t_idef *idef, t_mdatoms *md,
     int          i, k, ncc_alloc, ni, con, nconnect, concon;
     int          type, a1, a2;
     real         lenA = 0, lenB;
-    gmx_bool     bLocal;
 
     li->nc  = 0;
     li->ncc = 0;
@@ -1260,7 +1252,6 @@ void set_lincs(t_idef *idef, t_mdatoms *md,
     li->blnr[con] = nconnect;
     for (i = 0; i < ni; i++)
     {
-        bLocal = TRUE;
         type   = iatom[3*i];
         a1     = iatom[3*i+1];
         a2     = iatom[3*i+2];
@@ -1492,7 +1483,7 @@ gmx_bool constrain_lincs(FILE *fplog, gmx_bool bLog, gmx_bool bEner,
 {
     gmx_bool  bCalcDHDL;
     char      buf[STRLEN], buf2[22], buf3[STRLEN];
-    int       i, warn, p_imax, error;
+    int       i, warn, p_imax;
     real      ncons_loc, p_ssd, p_max = 0;
     rvec      dx;
     gmx_bool  bOK;
@@ -1708,6 +1699,7 @@ gmx_bool constrain_lincs(FILE *fplog, gmx_bool bLog, gmx_bool bEner,
         if (econqCoord)
         {
             /* dhdlambda contains dH/dlambda*dt^2, correct for this */
+            /* TODO This should probably use invdt, so that sd integrator scaling works properly */
             dhdlambda /= ir->delta_t*ir->delta_t;
         }
         *dvdlambda += dhdlambda;