Reimplement constant acceleration groups
[alexxy/gromacs.git] / src / gromacs / mdrun / shellfc.cpp
index 37522931b0c85e45460bfcee2936e11fea1e3bb6..7657596888178a4f4b6e4cb6ebaab1a9b8cd84af 100644 (file)
@@ -54,6 +54,7 @@
 #include "gromacs/gmxlib/network.h"
 #include "gromacs/math/functions.h"
 #include "gromacs/math/units.h"
+#include "gromacs/math/utilities.h"
 #include "gromacs/math/vec.h"
 #include "gromacs/math/vecdump.h"
 #include "gromacs/mdlib/constr.h"
@@ -61,7 +62,6 @@
 #include "gromacs/mdlib/force.h"
 #include "gromacs/mdlib/force_flags.h"
 #include "gromacs/mdlib/gmx_omp_nthreads.h"
-#include "gromacs/mdlib/mdatoms.h"
 #include "gromacs/mdlib/vsite.h"
 #include "gromacs/mdtypes/commrec.h"
 #include "gromacs/mdtypes/enerdata.h"
@@ -152,20 +152,17 @@ static void pr_shell(FILE* fplog, ArrayRef<const t_shell> shells)
  * started, but even when called, the prediction was always
  * over-written by a subsequent call in the MD loop, so has been
  * removed. */
-static void predict_shells(FILE*                   fplog,
-                           ArrayRef<RVec>          x,
-                           ArrayRef<RVec>          v,
-                           real                    dt,
-                           ArrayRef<const t_shell> shells,
-                           const real              mass[],
-                           gmx_mtop_t*             mtop,
-                           gmx_bool                bInit)
+static void predict_shells(FILE*                     fplog,
+                           ArrayRef<RVec>            x,
+                           ArrayRef<RVec>            v,
+                           real                      dt,
+                           ArrayRef<const t_shell>   shells,
+                           gmx::ArrayRef<const real> mass,
+                           gmx_bool                  bInit)
 {
     int  m, n1, n2, n3;
     real dt_1, fudge, tm, m1, m2, m3;
 
-    GMX_RELEASE_ASSERT(mass || mtop, "Must have masses or a way to look them up");
-
     /* We introduce a fudge factor for performance reasons: with this choice
      * the initial force on the shells is about a factor of two lower than
      * without
@@ -188,7 +185,6 @@ static void predict_shells(FILE*                   fplog,
         dt_1 = fudge * dt;
     }
 
-    int molb = 0;
     for (const t_shell& shell : shells)
     {
         const int s1 = shell.shellIndex;
@@ -208,17 +204,8 @@ static void predict_shells(FILE*                   fplog,
             case 2:
                 n1 = shell.nucl1;
                 n2 = shell.nucl2;
-                if (mass)
-                {
-                    m1 = mass[n1];
-                    m2 = mass[n2];
-                }
-                else
-                {
-                    /* Not the correct masses with FE, but it is just a prediction... */
-                    m1 = mtopGetAtomMass(mtop, n1, &molb);
-                    m2 = mtopGetAtomMass(mtop, n2, &molb);
-                }
+                m1 = mass[n1];
+                m2 = mass[n2];
                 tm = dt_1 / (m1 + m2);
                 for (m = 0; (m < DIM); m++)
                 {
@@ -229,19 +216,9 @@ static void predict_shells(FILE*                   fplog,
                 n1 = shell.nucl1;
                 n2 = shell.nucl2;
                 n3 = shell.nucl3;
-                if (mass)
-                {
-                    m1 = mass[n1];
-                    m2 = mass[n2];
-                    m3 = mass[n3];
-                }
-                else
-                {
-                    /* Not the correct masses with FE, but it is just a prediction... */
-                    m1 = mtopGetAtomMass(mtop, n1, &molb);
-                    m2 = mtopGetAtomMass(mtop, n2, &molb);
-                    m3 = mtopGetAtomMass(mtop, n3, &molb);
-                }
+                m1 = mass[n1];
+                m2 = mass[n2];
+                m3 = mass[n3];
                 tm = dt_1 / (m1 + m2 + m3);
                 for (m = 0; (m < DIM); m++)
                 {
@@ -254,7 +231,7 @@ static void predict_shells(FILE*                   fplog,
 }
 
 gmx_shellfc_t* init_shell_flexcon(FILE*             fplog,
-                                  const gmx_mtop_t* mtop,
+                                  const gmx_mtop_t& mtop,
                                   int               nflexcon,
                                   int               nstcalcenergy,
                                   bool              usingDomainDecomposition,
@@ -270,22 +247,21 @@ gmx_shellfc_t* init_shell_flexcon(FILE*             fplog,
 #define NBT asize(bondtypes)
     const gmx_ffparams_t* ffparams;
 
-    const std::array<int, eptNR> numParticles = gmx_mtop_particletype_count(*mtop);
+    const gmx::EnumerationArray<ParticleType, int> numParticles = gmx_mtop_particletype_count(mtop);
     if (fplog)
     {
         /* Print the number of each particle type */
-        int pType = 0;
-        for (const auto& n : numParticles)
+        for (const auto entry : gmx::keysOf(numParticles))
         {
-            if (n != 0)
+            const int number = numParticles[entry];
+            if (number != 0)
             {
-                fprintf(fplog, "There are: %d %ss\n", n, ptype_str[pType]);
+                fprintf(fplog, "There are: %d %ss\n", number, enumValueToString(entry));
             }
-            pType++;
         }
     }
 
-    nshell = numParticles[eptShell];
+    nshell = numParticles[ParticleType::Shell];
 
     if (nshell == 0 && nflexcon == 0)
     {
@@ -311,7 +287,7 @@ gmx_shellfc_t* init_shell_flexcon(FILE*             fplog,
                   "not supported in combination with shell particles.\nPlease make a new tpr file.",
                   nstcalcenergy);
     }
-    if (usingDomainDecomposition)
+    if (nshell > 0 && usingDomainDecomposition)
     {
         gmx_fatal(
                 FARGS,
@@ -321,14 +297,14 @@ gmx_shellfc_t* init_shell_flexcon(FILE*             fplog,
     /* We have shells: fill the shell data structure */
 
     /* Global system sized array, this should be avoided */
-    std::vector<int> shell_index(mtop->natoms);
+    std::vector<int> shell_index(mtop.natoms);
 
     nshell = 0;
-    for (const AtomProxy atomP : AtomRange(*mtop))
+    for (const AtomProxy atomP : AtomRange(mtop))
     {
         const t_atom& local = atomP.atom();
         int           i     = atomP.globalAtomNumber();
-        if (local.ptype == eptShell)
+        if (local.ptype == ParticleType::Shell)
         {
             shell_index[i] = nshell++;
         }
@@ -336,25 +312,25 @@ gmx_shellfc_t* init_shell_flexcon(FILE*             fplog,
 
     std::vector<t_shell> shell(nshell);
 
-    ffparams = &mtop->ffparams;
+    ffparams = &mtop.ffparams;
 
     /* Now fill the structures */
     /* TODO: See if we can use update groups that cover shell constructions */
     shfc->bInterCG = FALSE;
     ns             = 0;
     a_offset       = 0;
-    for (size_t mb = 0; mb < mtop->molblock.size(); mb++)
+    for (size_t mb = 0; mb < mtop.molblock.size(); mb++)
     {
-        const gmx_molblock_t* molb = &mtop->molblock[mb];
-        const gmx_moltype_t*  molt = &mtop->moltype[molb->type];
+        const gmx_molblock_t& molb = mtop.molblock[mb];
+        const gmx_moltype_t&  molt = mtop.moltype[molb.type];
 
-        const t_atom* atom = molt->atoms.atom;
-        for (mol = 0; mol < molb->nmol; mol++)
+        const t_atom* atom = molt.atoms.atom;
+        for (mol = 0; mol < molb.nmol; mol++)
         {
             for (j = 0; (j < NBT); j++)
             {
-                const int* ia = molt->ilist[bondtypes[j]].iatoms.data();
-                for (i = 0; (i < molt->ilist[bondtypes[j]].size());)
+                const int* ia = molt.ilist[bondtypes[j]].iatoms.data();
+                for (i = 0; (i < molt.ilist[bondtypes[j]].size());)
                 {
                     type  = ia[0];
                     ftype = ffparams->functype[type];
@@ -370,12 +346,12 @@ gmx_shellfc_t* init_shell_flexcon(FILE*             fplog,
                         case F_CUBICBONDS:
                         case F_POLARIZATION:
                         case F_ANHARM_POL:
-                            if (atom[ia[1]].ptype == eptShell)
+                            if (atom[ia[1]].ptype == ParticleType::Shell)
                             {
                                 aS = ia[1];
                                 aN = ia[2];
                             }
-                            else if (atom[ia[2]].ptype == eptShell)
+                            else if (atom[ia[2]].ptype == ParticleType::Shell)
                             {
                                 aS = ia[2];
                                 aN = ia[1];
@@ -455,7 +431,7 @@ gmx_shellfc_t* init_shell_flexcon(FILE*             fplog,
                                               aS + 1,
                                               mb + 1);
                                 }
-                                shell[nsi].k += gmx::square(qS) * ONE_4PI_EPS0
+                                shell[nsi].k += gmx::square(qS) * gmx::c_one4PiEps0
                                                 / ffparams->iparams[type].polarize.alpha;
                                 break;
                             case F_WATER_POL:
@@ -473,7 +449,7 @@ gmx_shellfc_t* init_shell_flexcon(FILE*             fplog,
                                          + ffparams->iparams[type].wpol.al_y
                                          + ffparams->iparams[type].wpol.al_z)
                                         / 3.0;
-                                shell[nsi].k += gmx::square(qS) * ONE_4PI_EPS0 / alpha;
+                                shell[nsi].k += gmx::square(qS) * gmx::c_one4PiEps0 / alpha;
                                 break;
                             default: gmx_fatal(FARGS, "Death Horror: %s, %d", __FILE__, __LINE__);
                         }
@@ -483,7 +459,7 @@ gmx_shellfc_t* init_shell_flexcon(FILE*             fplog,
                     i += nra + 1;
                 }
             }
-            a_offset += molt->atoms.nr;
+            a_offset += molt.atoms.nr;
         }
         /* Done with this molecule type */
     }
@@ -559,12 +535,12 @@ gmx_shellfc_t* init_shell_flexcon(FILE*             fplog,
     return shfc;
 }
 
-void gmx::make_local_shells(const t_commrec* cr, const t_mdatoms* md, gmx_shellfc_t* shfc)
+void gmx::make_local_shells(const t_commrec* cr, const t_mdatoms& md, gmx_shellfc_t* shfc)
 {
     int           a0, a1;
     gmx_domdec_t* dd = nullptr;
 
-    if (DOMAINDECOMP(cr))
+    if (haveDDAtomOrdering(*cr))
     {
         dd = cr->dd;
         a0 = 0;
@@ -582,9 +558,10 @@ void gmx::make_local_shells(const t_commrec* cr, const t_mdatoms* md, gmx_shellf
 
     std::vector<t_shell>& shells = shfc->shells;
     shells.clear();
+    auto* ptype = md.ptype;
     for (int i = a0; i < a1; i++)
     {
-        if (md->ptype[i] == eptShell)
+        if (ptype[i] == ParticleType::Shell)
         {
             if (dd)
             {
@@ -842,7 +819,7 @@ static void init_adir(gmx_shellfc_t*            shfc,
                       const t_commrec*          cr,
                       int                       dd_ac1,
                       int64_t                   step,
-                      const t_mdatoms*          md,
+                      const t_mdatoms&          md,
                       int                       end,
                       ArrayRefWithPadding<RVec> xOld,
                       ArrayRef<RVec>            x_init,
@@ -853,11 +830,10 @@ static void init_adir(gmx_shellfc_t*            shfc,
                       ArrayRef<const real>      lambda,
                       real*                     dvdlambda)
 {
-    double          dt, w_dt;
-    int             n, d;
-    unsigned short* ptype;
+    double dt, w_dt;
+    int    n, d;
 
-    if (DOMAINDECOMP(cr))
+    if (haveDDAtomOrdering(*cr))
     {
         n = dd_ac1;
     }
@@ -872,18 +848,18 @@ static void init_adir(gmx_shellfc_t*            shfc,
     rvec* x_old = as_rvec_array(xOld.paddedArrayRef().data());
     rvec* x     = as_rvec_array(xCurrent.paddedArrayRef().data());
 
-    ptype = md->ptype;
-
-    dt = ir->delta_t;
+    auto* ptype   = md.ptype;
+    auto  invmass = gmx::arrayRefFromArray(md.invmass, md.nr);
+    dt            = ir->delta_t;
 
-    /* Does NOT work with freeze groups (yet) */
+    /* Does NOT work with freeze or acceleration groups (yet) */
     for (n = 0; n < end; n++)
     {
-        w_dt = md->invmass[n] * dt;
+        w_dt = invmass[n] * dt;
 
         for (d = 0; d < DIM; d++)
         {
-            if ((ptype[n] != eptVSite) && (ptype[n] != eptShell))
+            if ((ptype[n] != ParticleType::VSite) && (ptype[n] != ParticleType::Shell))
             {
                 xnold[n][d] = x[n][d] - (x_init[n][d] - x_old[n][d]);
                 xnew[n][d]  = 2 * x[n][d] - x_old[n][d] + f[n][d] * w_dt * dt;
@@ -907,8 +883,8 @@ static void init_adir(gmx_shellfc_t*            shfc,
                   shfc->adir_xnold.arrayRefWithPadding(),
                   {},
                   box,
-                  lambda[efptBONDED],
-                  &(dvdlambda[efptBONDED]),
+                  lambda[static_cast<int>(FreeEnergyPerturbationCouplingType::Bonded)],
+                  &(dvdlambda[static_cast<int>(FreeEnergyPerturbationCouplingType::Bonded)]),
                   {},
                   computeVirial,
                   nullptr,
@@ -922,8 +898,8 @@ static void init_adir(gmx_shellfc_t*            shfc,
                   shfc->adir_xnew.arrayRefWithPadding(),
                   {},
                   box,
-                  lambda[efptBONDED],
-                  &(dvdlambda[efptBONDED]),
+                  lambda[static_cast<int>(FreeEnergyPerturbationCouplingType::Bonded)],
+                  &(dvdlambda[static_cast<int>(FreeEnergyPerturbationCouplingType::Bonded)]),
                   {},
                   computeVirial,
                   nullptr,
@@ -934,7 +910,7 @@ static void init_adir(gmx_shellfc_t*            shfc,
         for (d = 0; d < DIM; d++)
         {
             xnew[n][d] = -(2 * x[n][d] - xnold[n][d] - xnew[n][d]) / gmx::square(dt)
-                         - f[n][d] * md->invmass[n];
+                         - f[n][d] * invmass[n];
         }
         clear_rvec(acc_dir[n]);
     }
@@ -949,8 +925,8 @@ static void init_adir(gmx_shellfc_t*            shfc,
                   shfc->adir_xnew.arrayRefWithPadding(),
                   acc_dir,
                   box,
-                  lambda[efptBONDED],
-                  &(dvdlambda[efptBONDED]),
+                  lambda[static_cast<int>(FreeEnergyPerturbationCouplingType::Bonded)],
+                  &(dvdlambda[static_cast<int>(FreeEnergyPerturbationCouplingType::Bonded)]),
                   {},
                   computeVirial,
                   nullptr,
@@ -979,9 +955,10 @@ void relax_shell_flexcon(FILE*                         fplog,
                          const history_t*              hist,
                          gmx::ForceBuffersView*        f,
                          tensor                        force_vir,
-                         const t_mdatoms*              md,
+                         const t_mdatoms&              md,
+                         CpuPpLongRangeNonbondeds*     longRangeNonbondeds,
                          t_nrnb*                       nrnb,
-                         gmx_wallcycle_t               wcycle,
+                         gmx_wallcycle               wcycle,
                          gmx_shellfc_t*                shfc,
                          t_forcerec*                   fr,
                          gmx::MdrunScheduleWorkload*   runScheduleWork,
@@ -995,7 +972,7 @@ void relax_shell_flexcon(FILE*                         fplog,
     real dum = 0;
     char sbuf[22];
     int  nat, dd_ac0, dd_ac1 = 0, i;
-    int  homenr = md->homenr, end = homenr;
+    int  homenr = md.homenr, end = homenr;
     int  d, Min = 0, count = 0;
 #define Try (1 - Min) /* At start Try = 1 */
 
@@ -1006,12 +983,12 @@ void relax_shell_flexcon(FILE*                         fplog,
     ArrayRef<t_shell> shells       = shfc->shells;
     const int         nflexcon     = shfc->nflexcon;
 
-    if (DOMAINDECOMP(cr))
+    if (haveDDAtomOrdering(*cr))
     {
-        nat = dd_natoms_vsite(cr->dd);
+        nat = dd_natoms_vsite(*cr->dd);
         if (nflexcon > 0)
         {
-            dd_get_constraint_range(cr->dd, &dd_ac0, &dd_ac1);
+            dd_get_constraint_range(*cr->dd, &dd_ac0, &dd_ac1);
             nat = std::max(nat, dd_ac1);
         }
     }
@@ -1042,14 +1019,14 @@ void relax_shell_flexcon(FILE*                         fplog,
     ArrayRef<RVec> x = xPadded.unpaddedArrayRef();
     ArrayRef<RVec> v = vPadded.unpaddedArrayRef();
 
-    if (bDoNS && inputrec->pbcType != PbcType::No && !DOMAINDECOMP(cr))
+    if (bDoNS && inputrec->pbcType != PbcType::No && !haveDDAtomOrdering(*cr))
     {
         /* This is the only time where the coordinates are used
          * before do_force is called, which normally puts all
          * charge groups in the box.
          */
         put_atoms_in_box_omp(
-                fr->pbcType, box, x.subArray(0, md->homenr), gmx_omp_nthreads_get(emntDefault));
+                fr->pbcType, box, x.subArray(0, md.homenr), gmx_omp_nthreads_get(ModuleMultiThread::Default));
     }
 
     if (nflexcon)
@@ -1066,12 +1043,13 @@ void relax_shell_flexcon(FILE*                         fplog,
         }
     }
 
+    auto massT = gmx::arrayRefFromArray(md.massT, md.nr);
     /* Do a prediction of the shell positions, when appropriate.
      * Without velocities (EM, NM, BD) we only do initial prediction.
      */
     if (shfc->predictShells && !bCont && (EI_STATE_VELOCITY(inputrec->eI) || bInit))
     {
-        predict_shells(fplog, x, v, inputrec->delta_t, shells, md->massT, nullptr, bInit);
+        predict_shells(fplog, x, v, inputrec->delta_t, shells, massT, bInit);
     }
 
     /* Calculate the forces first time around */
@@ -1098,7 +1076,7 @@ void relax_shell_flexcon(FILE*                         fplog,
              hist,
              &forceViewInit,
              force_vir,
-             md,
+             &md,
              enerd,
              lambda,
              fr,
@@ -1107,6 +1085,7 @@ void relax_shell_flexcon(FILE*                         fplog,
              mu_tot,
              t,
              nullptr,
+             longRangeNonbondeds,
              (bDoNS ? GMX_FORCE_NS : 0) | shellfc_flags,
              ddBalanceRegionHandler);
 
@@ -1132,10 +1111,10 @@ void relax_shell_flexcon(FILE*                         fplog,
 
         for (i = 0; i < end; i++)
         {
-            sf_dir += md->massT[i] * norm2(shfc->acc_dir[i]);
+            sf_dir += massT[i] * norm2(shfc->acc_dir[i]);
         }
     }
-    accumulatePotentialEnergies(enerd, lambda, inputrec->fepvals);
+    accumulatePotentialEnergies(enerd, lambda, inputrec->fepvals.get());
     Epot[Min] = enerd->term[F_EPOT];
 
     df[Min] = rms_force(cr, forceWithPadding[Min].paddedArrayRef(), shells, nflexcon, &sf_dir, &Epot[Min]);
@@ -1147,7 +1126,7 @@ void relax_shell_flexcon(FILE*                         fplog,
 
     if (gmx_debug_at)
     {
-        pr_rvecs(debug, 0, "force0", as_rvec_array(force[Min].data()), md->nr);
+        pr_rvecs(debug, 0, "force0", as_rvec_array(force[Min].data()), md.nr);
     }
 
     if (!shells.empty() || nflexcon > 0)
@@ -1186,7 +1165,7 @@ void relax_shell_flexcon(FILE*                         fplog,
     {
         if (vsite)
         {
-            vsite->construct(pos[Min], inputrec->delta_t, v, box);
+            vsite->construct(pos[Min], v, box, gmx::VSiteOperation::PositionsAndVelocities);
         }
 
         if (nflexcon)
@@ -1238,7 +1217,7 @@ void relax_shell_flexcon(FILE*                         fplog,
                  hist,
                  &forceViewTry,
                  force_vir,
-                 md,
+                 &md,
                  enerd,
                  lambda,
                  fr,
@@ -1247,9 +1226,10 @@ void relax_shell_flexcon(FILE*                         fplog,
                  mu_tot,
                  t,
                  nullptr,
+                 longRangeNonbondeds,
                  shellfc_flags,
                  ddBalanceRegionHandler);
-        accumulatePotentialEnergies(enerd, lambda, inputrec->fepvals);
+        accumulatePotentialEnergies(enerd, lambda, inputrec->fepvals.get());
         if (gmx_debug_at)
         {
             pr_rvecs(debug, 0, "RELAX: force[Min]", as_rvec_array(force[Min].data()), homenr);
@@ -1278,7 +1258,7 @@ void relax_shell_flexcon(FILE*                         fplog,
             ArrayRef<const RVec> acc_dir = shfc->acc_dir;
             for (i = 0; i < end; i++)
             {
-                sf_dir += md->massT[i] * norm2(acc_dir[i]);
+                sf_dir += massT[i] * norm2(acc_dir[i]);
             }
         }