-/* -*- 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/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/listed-forces/bonded.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)
{
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);
}
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;
+ int nthreads_loop gmx_unused;
/* This reduction can run over any number of threads */
-#pragma omp parallel for num_threads(gmx_omp_nthreads_get(emntBonded)) private(t) schedule(static)
+ nthreads_loop = gmx_omp_nthreads_get(emntBonded);
+#pragma omp parallel for num_threads(nthreads_loop) private(t) schedule(static)
for (i = 0; i < n; i++)
{
for (t = 1; t < nthreads; t++)
}
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,
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 */
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. */
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 */
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);
/* 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;
}
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
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];
}
}
/* MRS: Eventually, many need to include free energy contribution here! */
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);
- wallcycle_sub_stop(wcycle, ewcsBONDED);
+ wallcycle_sub_start(wcycle, ewcsLISTED);
+ 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, ewcsLISTED);
}
#ifdef GMX_MPI
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();
pr_rvecs(debug, 0, "fshift after SR", fr->fshift, SHIFTS);
}
- /* Shift the coordinates. Must be done before bonded forces and PPPM,
+ /* Shift the coordinates. Must be done before listed forces and PPPM,
* but is also necessary for SHAKE and update, therefore it can NOT
- * go when no bonded forces have to be evaluated.
+ * go when no listed forces have to be evaluated.
*/
/* Here sometimes we would not need to shift with NBFonly,
inc_nrnb(nrnb, eNR_SHIFTX, graph->nnodes);
}
}
- /* Check whether we need to do bondeds or correct for exclusions */
+ /* Check whether we need to do listed interactions or correct for exclusions */
if (fr->bMolPBC &&
- ((flags & GMX_FORCE_BONDED)
- || EEL_RF(fr->eeltype) || EEL_FULL(fr->eeltype)))
+ ((flags & GMX_FORCE_LISTED)
+ || 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.
}
debug_gmx();
- if (flags & GMX_FORCE_BONDED)
+ if (flags & GMX_FORCE_LISTED)
{
- 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);
+ wallcycle_sub_start(wcycle, ewcsLISTED);
+ 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.
{
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];
}
}
debug_gmx();
- wallcycle_sub_stop(wcycle, ewcsBONDED);
+ wallcycle_sub_stop(wcycle, ewcsLISTED);
}
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)
{
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 ||
{
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(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;
}
- PRINT_SEPDVDL("PME mesh", Vlr, dvdl);
+ 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");
+ }
+ /* 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();
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);
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;
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
}
}
-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)
{