#endif
#include "typedefs.h"
-#include "smalloc.h"
+#include "gromacs/utility/smalloc.h"
#include "sysstuff.h"
#include "vec.h"
#include "vcm.h"
#include "coulomb.h"
#include "constr.h"
#include "shellfc.h"
-#include "compute_io.h"
+#include "gromacs/gmxpreprocess/compute_io.h"
#include "checkpoint.h"
#include "mtop_util.h"
#include "sighandler.h"
#include "txtdump.h"
-#include "string2.h"
+#include "gromacs/utility/cstringutil.h"
#include "pme_loadbal.h"
#include "bondf.h"
#include "membed.h"
#include "gromacs/timing/walltime_accounting.h"
#include "gromacs/pulling/pull.h"
#include "gromacs/swap/swapcoords.h"
+#include "gromacs/imd/imd.h"
#ifdef GMX_FAHCORE
#include "corewrap.h"
int repl_ex_nst, int repl_ex_nex, int repl_ex_seed, gmx_membed_t membed,
real cpt_period, real max_hours,
const char gmx_unused *deviceOptions,
+ int imdport,
unsigned long Flags,
gmx_walltime_accounting_t walltime_accounting)
{
int count, nconverged = 0;
real timestep = 0;
double tcount = 0;
- gmx_bool bConverged = TRUE, bOK, bSumEkinhOld, bExchanged, bNeedRepartition;
+ gmx_bool bConverged = TRUE, bOK, bSumEkinhOld, bDoReplEx, bExchanged, bNeedRepartition;
gmx_bool bAppend;
gmx_bool bResetCountersHalfMaxH = FALSE;
gmx_bool bVV, bIterativeCase, bFirstIterate, bTemp, bPres, bTrotter;
double cycles_pmes;
gmx_bool bPMETuneTry = FALSE, bPMETuneRunning = FALSE;
+ /* Interactive MD */
+ gmx_bool bIMDstep = FALSE;
+
#ifdef GMX_FAHCORE
/* Temporary addition for FAHCORE checkpointing */
int chkpt_ret;
&(state_global->fep_state), lam0,
nrnb, top_global, &upd,
nfile, fnm, &outf, &mdebin,
- force_vir, shake_vir, mu_tot, &bSimAnn, &vcm, Flags);
+ force_vir, shake_vir, mu_tot, &bSimAnn, &vcm, Flags, wcycle);
clear_mat(total_vir);
clear_mat(pres);
debug_gmx();
/* Check for polarizable models and flexible constraints */
- shellfc = init_shell_flexcon(fplog, fr->cutoff_scheme == ecutsVERLET,
+ shellfc = init_shell_flexcon(fplog,
top_global, n_flexible_constraints(constr),
(ir->bContinuation ||
(DOMAINDECOMP(cr) && !MASTER(cr))) ?
NULL : state_global->x);
+ if (shellfc && ir->nstcalcenergy != 1)
+ {
+ gmx_fatal(FARGS, "You have nstcalcenergy set to a value (%d) that is different from 1.\nThis is not supported in combinations with shell particles.\nPlease make a new tpr file.", ir->nstcalcenergy);
+ }
+ if (shellfc && DOMAINDECOMP(cr))
+ {
+ gmx_fatal(FARGS, "Shell particles are not implemented with domain decomposition, use a single rank");
+ }
+ if (shellfc && ir->eI == eiNM)
+ {
+ /* Currently shells don't work with Normal Modes */
+ gmx_fatal(FARGS, "Normal Mode analysis is not supported with shells.\nIf you'd like to help with adding support, we have an open discussion at http://redmine.gromacs.org/issues/879\n");
+ }
+
+ if (vsite && ir->eI == eiNM)
+ {
+ /* Currently virtual sites don't work with Normal Modes */
+ gmx_fatal(FARGS, "Normal Mode analysis is not supported with virtual sites.\nIf you'd like to help with adding support, we have an open discussion at http://redmine.gromacs.org/issues/879\n");
+ }
if (DEFORM(*ir))
{
setup_bonded_threading(fr, &top->idef);
}
+ /* Set up interactive MD (IMD) */
+ init_IMD(ir, cr, top_global, fplog, ir->nstcalcenergy, state_global->x,
+ nfile, fnm, oenv, imdport, Flags);
+
if (DOMAINDECOMP(cr))
{
/* Distribute the charge groups over the nodes from the master node */
set_constraints(constr, top, ir, mdatoms, cr);
}
- if (repl_ex_nst > 0)
- {
- /* We need to be sure replica exchange can only occur
- * when the energies are current */
- check_nst_param(fplog, cr, "nstcalcenergy", ir->nstcalcenergy,
- "repl_ex_nst", &repl_ex_nst);
- /* This check needs to happen before inter-simulation
- * signals are initialized, too */
- }
if (repl_ex_nst > 0 && MASTER(cr))
{
repl_ex = init_replica_exchange(fplog, cr->ms, state_global, ir,
bStartingFromCpt = (Flags & MD_STARTFROMCPT) && bInitStep;
bLastStep = FALSE;
bSumEkinhOld = FALSE;
+ bDoReplEx = FALSE;
bExchanged = FALSE;
bNeedRepartition = FALSE;
&& (ir->bExpanded) && (step > 0) && (!bStartingFromCpt));
}
+ bDoReplEx = ((repl_ex_nst > 0) && (step > 0) && !bLastStep &&
+ do_per_step(step, repl_ex_nst));
+
if (bSimAnn)
{
update_annealing_target_temp(&(ir->opts), t);
do_ene = (do_per_step(step, ir->nstenergy) || bLastStep);
- if (do_ene || do_log)
+ if (do_ene || do_log || bDoReplEx)
{
bCalcVir = TRUE;
bCalcEner = TRUE;
if (bVV && !bStartingFromCpt && !bRerunMD)
/* ############### START FIRST UPDATE HALF-STEP FOR VV METHODS############### */
{
+ wallcycle_start(wcycle, ewcUPDATE);
if (ir->eI == eiVV && bInitStep)
{
/* if using velocity verlet with full time step Ekin,
* step to combine the long-range forces on these steps.
* For nstcalclr=1 this is not done, since the forces would have been added
* directly to the short-range forces already.
+ *
+ * TODO Remove various aspects of VV+twin-range in master
+ * branch, because VV integrators did not ever support
+ * twin-range multiple time stepping with constraints.
*/
bUpdateDoLR = (fr->bTwinRange && do_per_step(step, ir->nstcalclr));
update_coords(fplog, step, ir, mdatoms, state, fr->bMolPBC,
- f, bUpdateDoLR, fr->f_twin, fcd,
+ f, bUpdateDoLR, fr->f_twin, bCalcVir ? &fr->vir_twin_constr : NULL, fcd,
ekind, M, upd, bInitStep, etrtVELOCITY1,
cr, nrnb, constr, &top->idef);
bOK = TRUE;
if (!bRerunMD || rerun_fr.bV || bForceUpdate) /* Why is rerun_fr.bV here? Unclear. */
{
+ wallcycle_stop(wcycle, ewcUPDATE);
update_constraints(fplog, step, NULL, ir, ekind, mdatoms,
state, fr->bMolPBC, graph, f,
&top->idef, shake_vir,
cr, nrnb, wcycle, upd, constr,
TRUE, bCalcVir, vetanew);
+ wallcycle_start(wcycle, ewcUPDATE);
+
+ if (bCalcVir && bUpdateDoLR && ir->nstcalclr > 1)
+ {
+ /* Correct the virial for multiple time stepping */
+ m_sub(shake_vir, fr->vir_twin_constr, shake_vir);
+ }
if (!bOK)
{
So we need information from the last step in the first half of the integration */
if (bGStat || do_per_step(step-1, nstglobalcomm))
{
+ wallcycle_stop(wcycle, ewcUPDATE);
compute_globals(fplog, gstat, cr, ir, fr, ekind, state, state_global, mdatoms, nrnb, vcm,
wcycle, enerd, force_vir, shake_vir, total_vir, pres, mu_tot,
constr, NULL, FALSE, state->box,
time step kinetic energy for the pressure (always true now, since we want accurate statistics).
b) If we are using EkinAveEkin for the kinetic energy for the temperature control, we still feed in
EkinAveVel because it's needed for the pressure */
+ wallcycle_start(wcycle, ewcUPDATE);
}
/* temperature scaling and pressure scaling to produce the extended variables at t+dt */
if (!bInitStep)
{
if (bExchanged)
{
-
+ wallcycle_stop(wcycle, ewcUPDATE);
/* We need the kinetic energy at minus the half step for determining
* the full step kinetic energy and possibly for T-coupling.*/
/* This may not be quite working correctly yet . . . . */
constr, NULL, FALSE, state->box,
top_global, &bSumEkinhOld,
CGLO_RERUNMD | CGLO_GSTAT | CGLO_TEMPERATURE);
+ wallcycle_start(wcycle, ewcUPDATE);
}
}
}
{
copy_rvecn(cbuf, state->v, 0, state->natoms);
}
+ wallcycle_stop(wcycle, ewcUPDATE);
}
/* MRS -- now done iterating -- compute the conserved quantity */
do_md_trajectory_writing(fplog, cr, nfile, fnm, step, step_rel, t,
ir, state, state_global, top_global, fr,
outf, mdebin, ekind, f, f_global,
- wcycle, &nchkpt,
+ &nchkpt,
bCPT, bRerunMD, bLastStep, (Flags & MD_CONFOUT),
bSumEkinhOld);
+ /* Check if IMD step and do IMD communication, if bIMD is TRUE. */
+ bIMDstep = do_IMD(ir->bIMD, step, cr, bNS, state->box, state->x, ir, t, wcycle);
/* kludge -- virial is lost with restart for NPT control. Must restart */
if (bStartingFromCpt && bVV)
/* velocity half-step update */
update_coords(fplog, step, ir, mdatoms, state, fr->bMolPBC, f,
- bUpdateDoLR, fr->f_twin, fcd,
+ bUpdateDoLR, fr->f_twin, bCalcVir ? &fr->vir_twin_constr : NULL, fcd,
ekind, M, upd, FALSE, etrtVELOCITY2,
cr, nrnb, constr, &top->idef);
}
bUpdateDoLR = (fr->bTwinRange && do_per_step(step, ir->nstcalclr));
update_coords(fplog, step, ir, mdatoms, state, fr->bMolPBC, f,
- bUpdateDoLR, fr->f_twin, fcd,
+ bUpdateDoLR, fr->f_twin, bCalcVir ? &fr->vir_twin_constr : NULL, fcd,
ekind, M, upd, bInitStep, etrtPOSITION, cr, nrnb, constr, &top->idef);
wallcycle_stop(wcycle, ewcUPDATE);
cr, nrnb, wcycle, upd, constr,
FALSE, bCalcVir, state->veta);
+ if (bCalcVir && bUpdateDoLR && ir->nstcalclr > 1)
+ {
+ /* Correct the virial for multiple time stepping */
+ m_sub(shake_vir, fr->vir_twin_constr, shake_vir);
+ }
+
if (ir->eI == eiVVAK)
{
/* erase F_EKIN and F_TEMP here? */
bUpdateDoLR = (fr->bTwinRange && do_per_step(step, ir->nstcalclr));
update_coords(fplog, step, ir, mdatoms, state, fr->bMolPBC, f,
- bUpdateDoLR, fr->f_twin, fcd,
+ bUpdateDoLR, fr->f_twin, bCalcVir ? &fr->vir_twin_constr : NULL, fcd,
ekind, M, upd, bInitStep, etrtPOSITION, cr, nrnb, constr, &top->idef);
wallcycle_stop(wcycle, ewcUPDATE);
/* Replica exchange */
bExchanged = FALSE;
- if ((repl_ex_nst > 0) && (step > 0) && !bLastStep &&
- do_per_step(step, repl_ex_nst))
+ if (bDoReplEx)
{
bExchanged = replica_exchange(fplog, cr, repl_ex,
state_global, enerd,
}
dd_bcast(cr->dd, sizeof(gmx_bool), &bPMETuneRunning);
+ if (bPMETuneRunning &&
+ fr->nbv->bUseGPU && DOMAINDECOMP(cr) &&
+ !(cr->duty & DUTY_PME))
+ {
+ /* Lock DLB=auto to off (does nothing when DLB=yes/no).
+ * With GPUs + separate PME ranks, we don't want DLB.
+ * This could happen when we scan coarse grids and
+ * it would then never be turned off again.
+ * This would hurt performance at the final, optimal
+ * grid spacing, where DLB almost never helps.
+ * Also, DLB can limit the cut-off for PME tuning.
+ */
+ dd_dlb_set_lock(cr->dd, TRUE);
+ }
+
if (bPMETuneRunning || step_rel > ir->nstlist*50)
{
bPMETuneTry = FALSE;
{
calc_enervirdiff(NULL, ir->eDispCorr, fr);
}
+
+ if (!bPMETuneRunning &&
+ DOMAINDECOMP(cr) &&
+ dd_dlb_is_locked(cr->dd))
+ {
+ /* Unlock the DLB=auto, DLB is allowed to activate
+ * (but we don't expect it to activate in most cases).
+ */
+ dd_dlb_set_lock(cr->dd, FALSE);
+ }
}
cycles_pmes = 0;
}
gs.set[eglsRESETCOUNTERS] = 0;
}
+ /* If bIMD is TRUE, the master updates the IMD energy record and sends positions to VMD client */
+ IMD_prep_energies_send_positions(ir->bIMD && MASTER(cr), bIMDstep, ir->imd, enerd, step, bCalcEner, wcycle);
+
}
/* End of main MD loop */
debug_gmx();
+ /* Closing TNG files can include compressing data. Therefore it is good to do that
+ * before stopping the time measurements. */
+ mdoutf_tng_close(outf);
+
/* Stop measuring walltime */
walltime_accounting_end(walltime_accounting);
print_replica_exchange_statistics(fplog, repl_ex);
}
+ /* IMD cleanup, if bIMD is TRUE. */
+ IMD_finalize(ir->bIMD, ir->imd);
+
walltime_accounting_set_nsteps_done(walltime_accounting, step_rel);
return 0;