Sort all includes in src/gromacs
[alexxy/gromacs.git] / src / gromacs / mdlib / force.c
index 278c8de8f388246eed1a626ea9393b764ceee60a..a4b3f65ec1283c4204c77db6a45d06899812c6a0 100644 (file)
@@ -1,83 +1,81 @@
-/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+/*
+ * This file is part of the GROMACS molecular simulation package.
  *
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- *                        VERSION 3.2.0
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
+ * Copyright (c) 2001-2004, The GROMACS development team.
+ * Copyright (c) 2013,2014, by the GROMACS development team, led by
+ * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+ * and including many others, as listed in the AUTHORS file in the
+ * top-level source directory and at http://www.gromacs.org.
+ *
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
  * of the License, or (at your option) any later version.
  *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
  *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
  *
- * For more info, check our website at http://www.gromacs.org
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version at http://www.gromacs.org.
  *
- * And Hey:
- * GROwing Monsters And Cloning Shrimps
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the research papers on the package. Check out http://www.gromacs.org.
  */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
+#include "gmxpre.h"
 
+#include "gromacs/legacyheaders/force.h"
+
+#include "config.h"
+
+#include <assert.h>
 #include <math.h>
 #include <string.h>
-#include <assert.h>
-#include "sysstuff.h"
-#include "typedefs.h"
-#include "macros.h"
-#include "smalloc.h"
-#include "macros.h"
-#include "physics.h"
-#include "force.h"
-#include "nonbonded.h"
-#include "names.h"
-#include "network.h"
-#include "pbc.h"
-#include "ns.h"
-#include "nrnb.h"
-#include "bondf.h"
-#include "mshift.h"
-#include "txtdump.h"
-#include "coulomb.h"
-#include "pme.h"
-#include "mdrun.h"
-#include "domdec.h"
-#include "partdec.h"
-#include "qmmm.h"
-#include "gmx_omp_nthreads.h"
 
+#include "gromacs/bonded/bonded.h"
+#include "gromacs/legacyheaders/coulomb.h"
+#include "gromacs/legacyheaders/domdec.h"
+#include "gromacs/legacyheaders/gmx_omp_nthreads.h"
+#include "gromacs/legacyheaders/macros.h"
+#include "gromacs/legacyheaders/mdrun.h"
+#include "gromacs/legacyheaders/names.h"
+#include "gromacs/legacyheaders/network.h"
+#include "gromacs/legacyheaders/nonbonded.h"
+#include "gromacs/legacyheaders/nrnb.h"
+#include "gromacs/legacyheaders/ns.h"
+#include "gromacs/legacyheaders/pme.h"
+#include "gromacs/legacyheaders/qmmm.h"
+#include "gromacs/legacyheaders/txtdump.h"
+#include "gromacs/legacyheaders/typedefs.h"
+#include "gromacs/legacyheaders/types/commrec.h"
+#include "gromacs/math/vec.h"
+#include "gromacs/pbcutil/ishift.h"
+#include "gromacs/pbcutil/mshift.h"
+#include "gromacs/pbcutil/pbc.h"
+#include "gromacs/timing/wallcycle.h"
+#include "gromacs/utility/fatalerror.h"
+#include "gromacs/utility/smalloc.h"
 
 void ns(FILE              *fp,
         t_forcerec        *fr,
-        rvec               x[],
         matrix             box,
         gmx_groups_t      *groups,
-        t_grpopts         *opts,
         gmx_localtop_t    *top,
         t_mdatoms         *md,
         t_commrec         *cr,
         t_nrnb            *nrnb,
-        real              *lambda,
-        real              *dvdlambda,
-        gmx_grppairener_t *grppener,
         gmx_bool           bFillGrid,
         gmx_bool           bDoLongRangeNS)
 {
@@ -95,9 +93,8 @@ void ns(FILE              *fp,
         fr->nlr = 0;
     }
 
-    nsearch = search_neighbours(fp, fr, x, box, top, groups, cr, nrnb, md,
-                                lambda, dvdlambda, grppener,
-                                bFillGrid, bDoLongRangeNS, TRUE);
+    nsearch = search_neighbours(fp, fr, box, top, groups, cr, nrnb, md,
+                                bFillGrid, bDoLongRangeNS);
     if (debug)
     {
         fprintf(debug, "nsearch = %d\n", nsearch);
@@ -115,9 +112,9 @@ void ns(FILE              *fp,
 }
 
 static void reduce_thread_forces(int n, rvec *f,
-                                 tensor vir,
-                                 real *Vcorr,
-                                 int efpt_ind, real *dvdl,
+                                 tensor vir_q, tensor vir_lj,
+                                 real *Vcorr_q, real *Vcorr_lj,
+                                 real *dvdl_q, real *dvdl_lj,
                                  int nthreads, f_thread_t *f_t)
 {
     int t, i;
@@ -133,27 +130,26 @@ static void reduce_thread_forces(int n, rvec *f,
     }
     for (t = 1; t < nthreads; t++)
     {
-        *Vcorr += f_t[t].Vcorr;
-        *dvdl  += f_t[t].dvdl[efpt_ind];
-        m_add(vir, f_t[t].vir, vir);
+        *Vcorr_q  += f_t[t].Vcorr_q;
+        *Vcorr_lj += f_t[t].Vcorr_lj;
+        *dvdl_q   += f_t[t].dvdl[efptCOUL];
+        *dvdl_lj  += f_t[t].dvdl[efptVDW];
+        m_add(vir_q, f_t[t].vir_q, vir_q);
+        m_add(vir_lj, f_t[t].vir_lj, vir_lj);
     }
 }
 
-void do_force_lowlevel(FILE       *fplog,   gmx_large_int_t step,
-                       t_forcerec *fr,      t_inputrec *ir,
+void do_force_lowlevel(t_forcerec *fr,      t_inputrec *ir,
                        t_idef     *idef,    t_commrec  *cr,
                        t_nrnb     *nrnb,    gmx_wallcycle_t wcycle,
                        t_mdatoms  *md,
-                       t_grpopts  *opts,
                        rvec       x[],      history_t  *hist,
                        rvec       f[],
                        rvec       f_longrange[],
                        gmx_enerdata_t *enerd,
                        t_fcdata   *fcd,
-                       gmx_mtop_t     *mtop,
                        gmx_localtop_t *top,
                        gmx_genborn_t *born,
-                       t_atomtypes *atype,
                        gmx_bool       bBornRadii,
                        matrix     box,
                        t_lambda   *fepvals,
@@ -164,27 +160,22 @@ void do_force_lowlevel(FILE       *fplog,   gmx_large_int_t step,
                        int        flags,
                        float      *cycles_pme)
 {
-    int         i, j, status;
+    int         i, j;
     int         donb_flags;
-    gmx_bool    bDoEpot, bSepDVDL, bSB;
+    gmx_bool    bDoEpot, bSB;
     int         pme_flags;
     matrix      boxs;
     rvec        box_size;
-    real        Vsr, Vlr, Vcorr = 0;
     t_pbc       pbc;
-    real        dvdgb;
     char        buf[22];
     double      clam_i, vlam_i;
-    real        dvdl_dum[efptNR], dvdl, dvdl_nb[efptNR], lam_i[efptNR];
-    real        dvdlsum;
+    real        dvdl_dum[efptNR], dvdl_nb[efptNR], lam_i[efptNR];
+    real        dvdl_q, dvdl_lj;
 
 #ifdef GMX_MPI
     double  t0 = 0.0, t1, t2, t3; /* time measurement for coarse load balancing */
 #endif
 
-#define PRINT_SEPDVDL(s, v, dvdlambda) if (bSepDVDL) {fprintf(fplog, sepdvdlformat, s, v, dvdlambda); }
-
-
     set_pbc(&pbc, fr->ePBC, box);
 
     /* reset free energy components */
@@ -200,19 +191,12 @@ void do_force_lowlevel(FILE       *fplog,   gmx_large_int_t step,
         box_size[i] = box[i][i];
     }
 
-    bSepDVDL = (fr->bSepDVDL && do_per_step(step, ir->nstlog));
     debug_gmx();
 
     /* do QMMM first if requested */
     if (fr->bQMMM)
     {
-        enerd->term[F_EQM] = calculate_QMMM(cr, x, f, fr, md);
-    }
-
-    if (bSepDVDL)
-    {
-        fprintf(fplog, "Step %s: non-bonded V and dVdl for node %d:\n",
-                gmx_step_str(step, buf), cr->nodeid);
+        enerd->term[F_EQM] = calculate_QMMM(cr, x, f, fr);
     }
 
     /* Call the short range functions all in one go. */
@@ -230,10 +214,9 @@ void do_force_lowlevel(FILE       *fplog,   gmx_large_int_t step,
     if (ir->nwall)
     {
         /* foreign lambda component for walls */
-        dvdl = do_walls(ir, fr, box, md, x, f, lambda[efptVDW],
-                        enerd->grpp.ener[egLJSR], nrnb);
-        PRINT_SEPDVDL("Walls", 0.0, dvdl);
-        enerd->dvdl_lin[efptVDW] += dvdl;
+        real dvdl_walls = do_walls(ir, fr, box, md, x, f, lambda[efptVDW],
+                                   enerd->grpp.ener[egLJSR], nrnb);
+        enerd->dvdl_lin[efptVDW] += dvdl_walls;
     }
 
     /* If doing GB, reset dvda and calculate the Born radii */
@@ -248,7 +231,7 @@ void do_force_lowlevel(FILE       *fplog,   gmx_large_int_t step,
 
         if (bBornRadii)
         {
-            calc_gb_rad(cr, fr, ir, top, atype, x, &(fr->gblist), born, md, nrnb);
+            calc_gb_rad(cr, fr, ir, top, x, &(fr->gblist), born, md, nrnb);
         }
 
         wallcycle_sub_stop(wcycle, ewcsNONBONDED);
@@ -263,10 +246,15 @@ void do_force_lowlevel(FILE       *fplog,   gmx_large_int_t step,
         /* Add short-range interactions */
         donb_flags |= GMX_NONBONDED_DO_SR;
 
+        /* Currently all group scheme kernels always calculate (shift-)forces */
         if (flags & GMX_FORCE_FORCES)
         {
             donb_flags |= GMX_NONBONDED_DO_FORCE;
         }
+        if (flags & GMX_FORCE_VIRIAL)
+        {
+            donb_flags |= GMX_NONBONDED_DO_SHIFTFORCE;
+        }
         if (flags & GMX_FORCE_ENERGY)
         {
             donb_flags |= GMX_NONBONDED_DO_POTENTIAL;
@@ -277,8 +265,8 @@ void do_force_lowlevel(FILE       *fplog,   gmx_large_int_t step,
         }
 
         wallcycle_sub_start(wcycle, ewcsNONBONDED);
-        do_nonbonded(cr, fr, x, f, f_longrange, md, excl,
-                     &enerd->grpp, box_size, nrnb,
+        do_nonbonded(fr, x, f, f_longrange, md, excl,
+                     &enerd->grpp, nrnb,
                      lambda, dvdl_nb, -1, -1, donb_flags);
 
         /* If we do foreign lambda and we have soft-core interactions
@@ -293,11 +281,11 @@ void do_force_lowlevel(FILE       *fplog,   gmx_large_int_t step,
                     lam_i[j] = (i == 0 ? lambda[j] : fepvals->all_lambda[j][i-1]);
                 }
                 reset_foreign_enerdata(enerd);
-                do_nonbonded(cr, fr, x, f, f_longrange, md, excl,
-                             &(enerd->foreign_grpp), box_size, nrnb,
+                do_nonbonded(fr, x, f, f_longrange, md, excl,
+                             &(enerd->foreign_grpp), nrnb,
                              lam_i, dvdl_dum, -1, -1,
                              (donb_flags & ~GMX_NONBONDED_DO_FORCE) | GMX_NONBONDED_DO_FOREIGNLAMBDA);
-                sum_epot(&ir->opts, &(enerd->foreign_grpp), enerd->foreign_term);
+                sum_epot(&(enerd->foreign_grpp), enerd->foreign_term);
                 enerd->enerpart_lambda[i] += enerd->foreign_term[F_EPOT];
             }
         }
@@ -311,8 +299,8 @@ void do_force_lowlevel(FILE       *fplog,   gmx_large_int_t step,
     if (ir->implicit_solvent)
     {
         wallcycle_sub_start(wcycle, ewcsBONDED);
-        calc_gb_forces(cr, md, born, top, atype, x, f, fr, idef,
-                       ir->gb_algorithm, ir->sa_algorithm, nrnb, bBornRadii, &pbc, graph, enerd);
+        calc_gb_forces(cr, md, born, top, x, f, fr, idef,
+                       ir->gb_algorithm, ir->sa_algorithm, nrnb, &pbc, graph, enerd);
         wallcycle_sub_stop(wcycle, ewcsBONDED);
     }
 
@@ -345,20 +333,6 @@ void do_force_lowlevel(FILE       *fplog,   gmx_large_int_t step,
         enerd->dvdl_lin[efptCOUL] += dvdl_nb[efptCOUL];
     }
 
-    Vsr = 0;
-    if (bSepDVDL)
-    {
-        for (i = 0; i < enerd->grpp.nener; i++)
-        {
-            Vsr +=
-                (fr->bBHAM ?
-                 enerd->grpp.ener[egBHAMSR][i] :
-                 enerd->grpp.ener[egLJSR][i])
-                + enerd->grpp.ener[egCOULSR][i] + enerd->grpp.ener[egGB][i];
-        }
-        dvdlsum = dvdl_nb[efptVDW] + dvdl_nb[efptCOUL];
-        PRINT_SEPDVDL("VdW and Coulomb SR particle-p.", Vsr, dvdlsum);
-    }
     debug_gmx();
 
 
@@ -390,7 +364,7 @@ void do_force_lowlevel(FILE       *fplog,   gmx_large_int_t step,
     /* Check whether we need to do bondeds or correct for exclusions */
     if (fr->bMolPBC &&
         ((flags & GMX_FORCE_BONDED)
-         || EEL_RF(fr->eeltype) || EEL_FULL(fr->eeltype)))
+         || EEL_RF(fr->eeltype) || EEL_FULL(fr->eeltype) || EVDW_PME(fr->vdwtype)))
     {
         /* Since all atoms are in the rectangular or triclinic unit-cell,
          * only single box vector shifts (2 in x) are required.
@@ -402,11 +376,10 @@ void do_force_lowlevel(FILE       *fplog,   gmx_large_int_t step,
     if (flags & GMX_FORCE_BONDED)
     {
         wallcycle_sub_start(wcycle, ewcsBONDED);
-        calc_bonds(fplog, cr->ms,
-                   idef, x, hist, f, fr, &pbc, graph, enerd, nrnb, lambda, md, fcd,
-                   DOMAINDECOMP(cr) ? cr->dd->gatindex : NULL, atype, born,
-                   flags,
-                   fr->bSepDVDL && do_per_step(step, ir->nstlog), step);
+        calc_bonds(cr->ms,
+                   idef, (const rvec *) x, hist, f, fr, &pbc, graph, enerd, nrnb, lambda, md, fcd,
+                   DOMAINDECOMP(cr) ? cr->dd->gatindex : NULL,
+                   flags);
 
         /* Check if we have to determine energy differences
          * at foreign lambda's.
@@ -425,9 +398,9 @@ void do_force_lowlevel(FILE       *fplog,   gmx_large_int_t step,
                 {
                     lam_i[j] = (i == 0 ? lambda[j] : fepvals->all_lambda[j][i-1]);
                 }
-                calc_bonds_lambda(fplog, idef, x, fr, &pbc, graph, &(enerd->foreign_grpp), enerd->foreign_term, nrnb, lam_i, md,
+                calc_bonds_lambda(idef, (const rvec *) x, fr, &pbc, graph, &(enerd->foreign_grpp), enerd->foreign_term, nrnb, lam_i, md,
                                   fcd, DOMAINDECOMP(cr) ? cr->dd->gatindex : NULL);
-                sum_epot(&ir->opts, &(enerd->foreign_grpp), enerd->foreign_term);
+                sum_epot(&(enerd->foreign_grpp), enerd->foreign_term);
                 enerd->enerpart_lambda[i] += enerd->foreign_term[F_EPOT];
             }
         }
@@ -439,8 +412,20 @@ void do_force_lowlevel(FILE       *fplog,   gmx_large_int_t step,
     where();
 
     *cycles_pme = 0;
-    if (EEL_FULL(fr->eeltype))
+    clear_mat(fr->vir_el_recip);
+    clear_mat(fr->vir_lj_recip);
+
+    /* Do long-range electrostatics and/or LJ-PME, including related short-range
+     * corrections.
+     */
+    if (EEL_FULL(fr->eeltype) || EVDW_PME(fr->vdwtype))
     {
+        real Vlr               = 0, Vcorr = 0;
+        real dvdl_long_range   = 0;
+        int  status            = 0;
+        real Vlr_q             = 0, Vlr_lj = 0, Vcorr_q = 0, Vcorr_lj = 0;
+        real dvdl_long_range_q = 0, dvdl_long_range_lj = 0;
+
         bSB = (ir->nwall == 2);
         if (bSB)
         {
@@ -449,19 +434,17 @@ void do_force_lowlevel(FILE       *fplog,   gmx_large_int_t step,
             box_size[ZZ] *= ir->wall_ewald_zfac;
         }
 
-        clear_mat(fr->vir_el_recip);
-
-        if (fr->bEwald)
+        if (EEL_PME_EWALD(fr->eeltype) || EVDW_PME(fr->vdwtype))
         {
-            Vcorr = 0;
-            dvdl  = 0;
-
+            real dvdl_long_range_correction_q   = 0;
+            real dvdl_long_range_correction_lj  = 0;
             /* With the Verlet scheme exclusion forces are calculated
              * in the non-bonded kernel.
              */
             /* The TPI molecule does not have exclusions with the rest
-             * of the system and no intra-molecular PME grid contributions
-             * will be calculated in gmx_pme_calc_energy.
+             * of the system and no intra-molecular PME grid
+             * contributions will be calculated in
+             * gmx_pme_calc_energy.
              */
             if ((ir->cutoff_scheme == ecutsGROUP && fr->n_tpi == 0) ||
                 ir->ewald_geometry != eewg3D ||
@@ -482,172 +465,195 @@ void do_force_lowlevel(FILE       *fplog,   gmx_large_int_t step,
                 {
                     int     s, e, i;
                     rvec   *fnv;
-                    tensor *vir;
-                    real   *Vcorrt, *dvdlt;
+                    tensor *vir_q, *vir_lj;
+                    real   *Vcorrt_q, *Vcorrt_lj, *dvdlt_q, *dvdlt_lj;
                     if (t == 0)
                     {
-                        fnv    = fr->f_novirsum;
-                        vir    = &fr->vir_el_recip;
-                        Vcorrt = &Vcorr;
-                        dvdlt  = &dvdl;
+                        fnv       = fr->f_novirsum;
+                        vir_q     = &fr->vir_el_recip;
+                        vir_lj    = &fr->vir_lj_recip;
+                        Vcorrt_q  = &Vcorr_q;
+                        Vcorrt_lj = &Vcorr_lj;
+                        dvdlt_q   = &dvdl_long_range_correction_q;
+                        dvdlt_lj  = &dvdl_long_range_correction_lj;
                     }
                     else
                     {
-                        fnv    = fr->f_t[t].f;
-                        vir    = &fr->f_t[t].vir;
-                        Vcorrt = &fr->f_t[t].Vcorr;
-                        dvdlt  = &fr->f_t[t].dvdl[efptCOUL];
+                        fnv       = fr->f_t[t].f;
+                        vir_q     = &fr->f_t[t].vir_q;
+                        vir_lj    = &fr->f_t[t].vir_lj;
+                        Vcorrt_q  = &fr->f_t[t].Vcorr_q;
+                        Vcorrt_lj = &fr->f_t[t].Vcorr_lj;
+                        dvdlt_q   = &fr->f_t[t].dvdl[efptCOUL];
+                        dvdlt_lj  = &fr->f_t[t].dvdl[efptVDW];
                         for (i = 0; i < fr->natoms_force; i++)
                         {
                             clear_rvec(fnv[i]);
                         }
-                        clear_mat(*vir);
+                        clear_mat(*vir_q);
+                        clear_mat(*vir_lj);
                     }
-                    *dvdlt  = 0;
-                    *Vcorrt =
-                        ewald_LRcorrection(fplog,
-                                           fr->excl_load[t], fr->excl_load[t+1],
-                                           cr, t, fr,
-                                           md->chargeA,
-                                           md->nChargePerturbed ? md->chargeB : NULL,
-                                           ir->cutoff_scheme != ecutsVERLET,
-                                           excl, x, bSB ? boxs : box, mu_tot,
-                                           ir->ewald_geometry,
-                                           ir->epsilon_surface,
-                                           fnv, *vir,
-                                           lambda[efptCOUL], dvdlt);
+                    *dvdlt_q  = 0;
+                    *dvdlt_lj = 0;
+
+                    ewald_LRcorrection(fr->excl_load[t], fr->excl_load[t+1],
+                                       cr, t, fr,
+                                       md->chargeA,
+                                       md->nChargePerturbed ? md->chargeB : NULL,
+                                       md->sqrt_c6A,
+                                       md->nTypePerturbed ? md->sqrt_c6B : NULL,
+                                       md->sigmaA,
+                                       md->nTypePerturbed ? md->sigmaB : NULL,
+                                       md->sigma3A,
+                                       md->nTypePerturbed ? md->sigma3B : NULL,
+                                       ir->cutoff_scheme != ecutsVERLET,
+                                       excl, x, bSB ? boxs : box, mu_tot,
+                                       ir->ewald_geometry,
+                                       ir->epsilon_surface,
+                                       fnv, *vir_q, *vir_lj,
+                                       Vcorrt_q, Vcorrt_lj,
+                                       lambda[efptCOUL], lambda[efptVDW],
+                                       dvdlt_q, dvdlt_lj);
                 }
                 if (nthreads > 1)
                 {
                     reduce_thread_forces(fr->natoms_force, fr->f_novirsum,
-                                         fr->vir_el_recip,
-                                         &Vcorr, efptCOUL, &dvdl,
+                                         fr->vir_el_recip, fr->vir_lj_recip,
+                                         &Vcorr_q, &Vcorr_lj,
+                                         &dvdl_long_range_correction_q,
+                                         &dvdl_long_range_correction_lj,
                                          nthreads, fr->f_t);
                 }
-
                 wallcycle_sub_stop(wcycle, ewcsEWALD_CORRECTION);
             }
 
-            if (fr->n_tpi == 0)
+            if (EEL_PME_EWALD(fr->eeltype) && fr->n_tpi == 0)
             {
-                Vcorr += ewald_charge_correction(cr, fr, lambda[efptCOUL], box,
-                                                 &dvdl, fr->vir_el_recip);
+                Vcorr_q += ewald_charge_correction(cr, fr, lambda[efptCOUL], box,
+                                                   &dvdl_long_range_correction_q,
+                                                   fr->vir_el_recip);
             }
 
-            PRINT_SEPDVDL("Ewald excl./charge/dip. corr.", Vcorr, dvdl);
-            enerd->dvdl_lin[efptCOUL] += dvdl;
-        }
+            enerd->dvdl_lin[efptCOUL] += dvdl_long_range_correction_q;
+            enerd->dvdl_lin[efptVDW]  += dvdl_long_range_correction_lj;
 
-        status = 0;
-        Vlr    = 0;
-        dvdl   = 0;
-        switch (fr->eeltype)
-        {
-            case eelPME:
-            case eelPMESWITCH:
-            case eelPMEUSER:
-            case eelPMEUSERSWITCH:
-            case eelP3M_AD:
-                if (cr->duty & DUTY_PME)
+            if ((EEL_PME(fr->eeltype) || EVDW_PME(fr->vdwtype)) && (cr->duty & DUTY_PME))
+            {
+                /* Do reciprocal PME for Coulomb and/or LJ. */
+                assert(fr->n_tpi >= 0);
+                if (fr->n_tpi == 0 || (flags & GMX_FORCE_STATECHANGED))
                 {
-                    assert(fr->n_tpi >= 0);
-                    if (fr->n_tpi == 0 || (flags & GMX_FORCE_STATECHANGED))
+                    pme_flags = GMX_PME_SPREAD | GMX_PME_SOLVE;
+                    if (EEL_PME(fr->eeltype))
                     {
-                        pme_flags = GMX_PME_SPREAD_Q | GMX_PME_SOLVE;
-                        if (flags & GMX_FORCE_FORCES)
-                        {
-                            pme_flags |= GMX_PME_CALC_F;
-                        }
-                        if (flags & (GMX_FORCE_VIRIAL | GMX_FORCE_ENERGY))
-                        {
-                            pme_flags |= GMX_PME_CALC_ENER_VIR;
-                        }
-                        if (fr->n_tpi > 0)
-                        {
-                            /* We don't calculate f, but we do want the potential */
-                            pme_flags |= GMX_PME_CALC_POT;
-                        }
-                        wallcycle_start(wcycle, ewcPMEMESH);
-                        status = gmx_pme_do(fr->pmedata,
-                                            md->start, md->homenr - fr->n_tpi,
-                                            x, fr->f_novirsum,
-                                            md->chargeA, md->chargeB,
-                                            bSB ? boxs : box, cr,
-                                            DOMAINDECOMP(cr) ? dd_pme_maxshift_x(cr->dd) : 0,
-                                            DOMAINDECOMP(cr) ? dd_pme_maxshift_y(cr->dd) : 0,
-                                            nrnb, wcycle,
-                                            fr->vir_el_recip, fr->ewaldcoeff,
-                                            &Vlr, lambda[efptCOUL], &dvdl,
-                                            pme_flags);
-                        *cycles_pme = wallcycle_stop(wcycle, ewcPMEMESH);
-
-                        /* We should try to do as little computation after
-                         * this as possible, because parallel PME synchronizes
-                         * the nodes, so we want all load imbalance of the rest
-                         * of the force calculation to be before the PME call.
-                         * DD load balancing is done on the whole time of
-                         * the force call (without PME).
-                         */
+                        pme_flags     |= GMX_PME_DO_COULOMB;
+                    }
+                    if (EVDW_PME(fr->vdwtype))
+                    {
+                        pme_flags |= GMX_PME_DO_LJ;
+                    }
+                    if (flags & GMX_FORCE_FORCES)
+                    {
+                        pme_flags |= GMX_PME_CALC_F;
+                    }
+                    if (flags & GMX_FORCE_VIRIAL)
+                    {
+                        pme_flags |= GMX_PME_CALC_ENER_VIR;
                     }
                     if (fr->n_tpi > 0)
                     {
-                        /* Determine the PME grid energy of the test molecule
-                         * with the PME grid potential of the other charges.
-                         */
-                        gmx_pme_calc_energy(fr->pmedata, fr->n_tpi,
-                                            x + md->homenr - fr->n_tpi,
-                                            md->chargeA + md->homenr - fr->n_tpi,
-                                            &Vlr);
+                        /* We don't calculate f, but we do want the potential */
+                        pme_flags |= GMX_PME_CALC_POT;
+                    }
+                    wallcycle_start(wcycle, ewcPMEMESH);
+                    status = gmx_pme_do(fr->pmedata,
+                                        0, md->homenr - fr->n_tpi,
+                                        x, fr->f_novirsum,
+                                        md->chargeA, md->chargeB,
+                                        md->sqrt_c6A, md->sqrt_c6B,
+                                        md->sigmaA, md->sigmaB,
+                                        bSB ? boxs : box, cr,
+                                        DOMAINDECOMP(cr) ? dd_pme_maxshift_x(cr->dd) : 0,
+                                        DOMAINDECOMP(cr) ? dd_pme_maxshift_y(cr->dd) : 0,
+                                        nrnb, wcycle,
+                                        fr->vir_el_recip, fr->ewaldcoeff_q,
+                                        fr->vir_lj_recip, fr->ewaldcoeff_lj,
+                                        &Vlr_q, &Vlr_lj,
+                                        lambda[efptCOUL], lambda[efptVDW],
+                                        &dvdl_long_range_q, &dvdl_long_range_lj, pme_flags);
+                    *cycles_pme = wallcycle_stop(wcycle, ewcPMEMESH);
+                    if (status != 0)
+                    {
+                        gmx_fatal(FARGS, "Error %d in reciprocal PME routine", status);
+                    }
+                    /* We should try to do as little computation after
+                     * this as possible, because parallel PME synchronizes
+                     * the nodes, so we want all load imbalance of the
+                     * rest of the force calculation to be before the PME
+                     * call.  DD load balancing is done on the whole time
+                     * of the force call (without PME).
+                     */
+                }
+                if (fr->n_tpi > 0)
+                {
+                    if (EVDW_PME(ir->vdwtype))
+                    {
+
+                        gmx_fatal(FARGS, "Test particle insertion not implemented with LJ-PME");
                     }
-                    PRINT_SEPDVDL("PME mesh", Vlr, dvdl);
+                    /* Determine the PME grid energy of the test molecule
+                     * with the PME grid potential of the other charges.
+                     */
+                    gmx_pme_calc_energy(fr->pmedata, fr->n_tpi,
+                                        x + md->homenr - fr->n_tpi,
+                                        md->chargeA + md->homenr - fr->n_tpi,
+                                        &Vlr_q);
                 }
-                break;
-            case eelEWALD:
-                Vlr = do_ewald(fplog, FALSE, ir, x, fr->f_novirsum,
-                               md->chargeA, md->chargeB,
-                               box_size, cr, md->homenr,
-                               fr->vir_el_recip, fr->ewaldcoeff,
-                               lambda[efptCOUL], &dvdl, fr->ewald_table);
-                PRINT_SEPDVDL("Ewald long-range", Vlr, dvdl);
-                break;
-            default:
-                gmx_fatal(FARGS, "No such electrostatics method implemented %s",
-                          eel_names[fr->eeltype]);
+            }
         }
-        if (status != 0)
+
+        if (!EEL_PME(fr->eeltype) && EEL_PME_EWALD(fr->eeltype))
         {
-            gmx_fatal(FARGS, "Error %d in long range electrostatics routine %s",
-                      status, EELTYPE(fr->eeltype));
+            Vlr_q = do_ewald(ir, x, fr->f_novirsum,
+                             md->chargeA, md->chargeB,
+                             box_size, cr, md->homenr,
+                             fr->vir_el_recip, fr->ewaldcoeff_q,
+                             lambda[efptCOUL], &dvdl_long_range_q, fr->ewald_table);
         }
+
         /* Note that with separate PME nodes we get the real energies later */
-        enerd->dvdl_lin[efptCOUL] += dvdl;
-        enerd->term[F_COUL_RECIP]  = Vlr + Vcorr;
+        enerd->dvdl_lin[efptCOUL] += dvdl_long_range_q;
+        enerd->dvdl_lin[efptVDW]  += dvdl_long_range_lj;
+        enerd->term[F_COUL_RECIP]  = Vlr_q + Vcorr_q;
+        enerd->term[F_LJ_RECIP]    = Vlr_lj + Vcorr_lj;
         if (debug)
         {
-            fprintf(debug, "Vlr = %g, Vcorr = %g, Vlr_corr = %g\n",
-                    Vlr, Vcorr, enerd->term[F_COUL_RECIP]);
+            fprintf(debug, "Vlr_q = %g, Vcorr_q = %g, Vlr_corr_q = %g\n",
+                    Vlr_q, Vcorr_q, enerd->term[F_COUL_RECIP]);
             pr_rvecs(debug, 0, "vir_el_recip after corr", fr->vir_el_recip, DIM);
             pr_rvecs(debug, 0, "fshift after LR Corrections", fr->fshift, SHIFTS);
+            fprintf(debug, "Vlr_lj: %g, Vcorr_lj = %g, Vlr_corr_lj = %g\n",
+                    Vlr_lj, Vcorr_lj, enerd->term[F_LJ_RECIP]);
+            pr_rvecs(debug, 0, "vir_lj_recip after corr", fr->vir_lj_recip, DIM);
         }
     }
     else
     {
-        if (EEL_RF(fr->eeltype))
+        /* Is there a reaction-field exclusion correction needed? */
+        if (EEL_RF(fr->eeltype) && eelRF_NEC != fr->eeltype)
         {
-            /* With the Verlet scheme exclusion forces are calculated
+            /* With the Verlet scheme, exclusion forces are calculated
              * in the non-bonded kernel.
              */
-            if (ir->cutoff_scheme != ecutsVERLET && fr->eeltype != eelRF_NEC)
+            if (ir->cutoff_scheme != ecutsVERLET)
             {
-                dvdl                   = 0;
+                real dvdl_rf_excl      = 0;
                 enerd->term[F_RF_EXCL] =
-                    RF_excl_correction(fplog, fr, graph, md, excl, x, f,
-                                       fr->fshift, &pbc, lambda[efptCOUL], &dvdl);
-            }
+                    RF_excl_correction(fr, graph, md, excl, x, f,
+                                       fr->fshift, &pbc, lambda[efptCOUL], &dvdl_rf_excl);
 
-            enerd->dvdl_lin[efptCOUL] += dvdl;
-            PRINT_SEPDVDL("RF exclusion correction",
-                          enerd->term[F_RF_EXCL], dvdl);
+                enerd->dvdl_lin[efptCOUL] += dvdl_rf_excl;
+            }
         }
     }
     where();
@@ -668,7 +674,7 @@ void do_force_lowlevel(FILE       *fplog,   gmx_large_int_t step,
         fr->t_wait += t3-t2;
         if (fr->timesteps == 11)
         {
-            fprintf(stderr, "* PP load balancing info: node %d, step %s, rel wait time=%3.0f%% , load string value: %7.2f\n",
+            fprintf(stderr, "* PP load balancing info: rank %d, step %s, rel wait time=%3.0f%% , load string value: %7.2f\n",
                     cr->nodeid, gmx_step_str(fr->timesteps, buf),
                     100*fr->t_wait/(fr->t_wait+fr->t_fnbf),
                     (fr->t_fnbf+fr->t_wait)/fr->t_fnbf);
@@ -759,7 +765,7 @@ static real sum_v(int n, real v[])
     return t;
 }
 
-void sum_epot(t_grpopts *opts, gmx_grppairener_t *grpp, real *epot)
+void sum_epot(gmx_grppairener_t *grpp, real *epot)
 {
     int i;
 
@@ -851,14 +857,22 @@ void sum_dhdl(gmx_enerdata_t *enerd, real *lambda, t_lambda *fepvals)
      * which is a very good approximation (except for exotic settings).
      * (investigate how to overcome this post 4.6 - MRS)
      */
-    enerd->term[F_DVDL_BONDED] += enerd->term[F_DVDL_CONSTR];
+    if (fepvals->separate_dvdl[efptBONDED])
+    {
+        enerd->term[F_DVDL_BONDED] += enerd->term[F_DVDL_CONSTR];
+    }
+    else
+    {
+        enerd->term[F_DVDL] += enerd->term[F_DVDL_CONSTR];
+    }
     enerd->term[F_DVDL_CONSTR] = 0;
 
     for (i = 0; i < fepvals->n_lambda; i++)
-    {                                         /* note we are iterating over fepvals here!
-                                                 For the current lam, dlam = 0 automatically,
-                                                 so we don't need to add anything to the
-                                                 enerd->enerpart_lambda[0] */
+    {
+        /* note we are iterating over fepvals here!
+           For the current lam, dlam = 0 automatically,
+           so we don't need to add anything to the
+           enerd->enerpart_lambda[0] */
 
         /* we don't need to worry about dvdl_lin contributions to dE at
            current lambda, because the contributions to the current
@@ -902,8 +916,7 @@ void reset_foreign_enerdata(gmx_enerdata_t *enerd)
     }
 }
 
-void reset_enerdata(t_grpopts *opts,
-                    t_forcerec *fr, gmx_bool bNS,
+void reset_enerdata(t_forcerec *fr, gmx_bool bNS,
                     gmx_enerdata_t *enerd,
                     gmx_bool bMaster)
 {