static real constr_r_max_moltype(FILE *fplog, gmx_moltype_t *molt,t_iparams *iparams, t_inputrec *ir) { int natoms,nflexcon,*path,at,count; t_blocka at2con; real r0,r1,r2maxA,r2maxB,rmax,lam0,lam1; if (molt->ilist[F_CONSTR].nr == 0 && molt->ilist[F_CONSTRNC].nr == 0) { return 0; } natoms = molt->atoms.nr; at2con = make_at2con(0,natoms,molt->ilist,iparams, EI_DYNAMICS(ir->eI),&nflexcon); snew(path,1+ir->nProjOrder); for(at=0; at<1+ir->nProjOrder; at++) path[at] = -1; r2maxA = 0; for(at=0; at<natoms; at++) { r0 = 0; r1 = 0; count = 0; constr_recur(&at2con,molt->ilist,iparams, FALSE,at,0,1+ir->nProjOrder,path,r0,r1,&r2maxA,&count); } if (ir->efep == efepNO) { rmax = sqrt(r2maxA); } else { r2maxB = 0; for(at=0; at<natoms; at++) { r0 = 0; r1 = 0; count = 0; constr_recur(&at2con,molt->ilist,iparams, TRUE,at,0,1+ir->nProjOrder,path,r0,r1,&r2maxB,&count); } lam0 = ir->init_lambda; if (EI_DYNAMICS(ir->eI)) lam0 += ir->init_step*ir->delta_lambda; rmax = (1 - lam0)*sqrt(r2maxA) + lam0*sqrt(r2maxB); if (EI_DYNAMICS(ir->eI)) { lam1 = ir->init_lambda + (ir->init_step + ir->nsteps)*ir->delta_lambda; rmax = max(rmax,(1 - lam1)*sqrt(r2maxA) + lam1*sqrt(r2maxB)); } } done_blocka(&at2con); sfree(path); return rmax; }
static void prepare_verlet_scheme(FILE *fplog, t_commrec *cr, t_inputrec *ir, int nstlist_cmdline, const gmx_mtop_t *mtop, matrix box, gmx_bool bUseGPU) { /* For NVE simulations, we will retain the initial list buffer */ if (EI_DYNAMICS(ir->eI) && ir->verletbuf_tol > 0 && !(EI_MD(ir->eI) && ir->etc == etcNO)) { /* Update the Verlet buffer size for the current run setup */ verletbuf_list_setup_t ls; real rlist_new; /* Here we assume SIMD-enabled kernels are being used. But as currently * calc_verlet_buffer_size gives the same results for 4x8 and 4x4 * and 4x2 gives a larger buffer than 4x4, this is ok. */ verletbuf_get_list_setup(TRUE, bUseGPU, &ls); calc_verlet_buffer_size(mtop, det(box), ir, -1, &ls, NULL, &rlist_new); if (rlist_new != ir->rlist) { if (fplog != NULL) { fprintf(fplog, "\nChanging rlist from %g to %g for non-bonded %dx%d atom kernels\n\n", ir->rlist, rlist_new, ls.cluster_size_i, ls.cluster_size_j); } ir->rlist = rlist_new; ir->rlistlong = rlist_new; } } if (nstlist_cmdline > 0 && (!EI_DYNAMICS(ir->eI) || ir->verletbuf_tol <= 0)) { gmx_fatal(FARGS, "Can not set nstlist without %s", !EI_DYNAMICS(ir->eI) ? "dynamics" : "verlet-buffer-tolerance"); } if (EI_DYNAMICS(ir->eI)) { /* Set or try nstlist values */ increase_nstlist(fplog, cr, ir, nstlist_cmdline, mtop, box, bUseGPU); } }
std::unique_ptr<BoxDeformation> prepareBoxDeformation(const matrix &initialBox, t_commrec *cr, const t_inputrec &inputrec) { if (!inputrecDeform(&inputrec)) { return nullptr; } if (!EI_DYNAMICS(inputrec.eI)) { GMX_THROW(NotImplementedError("Box deformation is only supported with dynamical integrators")); } matrix box; // Only the rank that read the tpr has the global state, and thus // the initial box, so we pass that around. if (SIMMASTER(cr)) { copy_mat(initialBox, box); } if (PAR(cr)) { gmx_bcast(sizeof(box), box, cr); } return compat::make_unique<BoxDeformation>(inputrec.delta_t, inputrec.init_step, inputrec.deform, box); }
/* Override the value in inputrec with value passed on the command line (if any) */ static void override_nsteps_cmdline(FILE *fplog, gmx_int64_t nsteps_cmdline, t_inputrec *ir, const t_commrec *cr) { assert(ir); assert(cr); /* override with anything else than the default -2 */ if (nsteps_cmdline > -2) { char sbuf_steps[STEPSTRSIZE]; char sbuf_msg[STRLEN]; ir->nsteps = nsteps_cmdline; if (EI_DYNAMICS(ir->eI) && nsteps_cmdline != -1) { sprintf(sbuf_msg, "Overriding nsteps with value passed on the command line: %s steps, %.3g ps", gmx_step_str(nsteps_cmdline, sbuf_steps), fabs(nsteps_cmdline*ir->delta_t)); } else { sprintf(sbuf_msg, "Overriding nsteps with value passed on the command line: %s steps", gmx_step_str(nsteps_cmdline, sbuf_steps)); } md_print_warn(cr, fplog, "%s\n", sbuf_msg); } else if (nsteps_cmdline < -2) { gmx_fatal(FARGS, "Invalid nsteps value passed on the command line: %d", nsteps_cmdline); } /* Do nothing if nsteps_cmdline == -2 */ }
void set_constraints(struct gmx_constr *constr, gmx_localtop_t *top,t_inputrec *ir, t_mdatoms *md,gmx_domdec_t *dd) { t_idef *idef; int ncons; if (constr->ncon_tot > 0) { idef = &top->idef; ncons = idef->il[F_CONSTR].nr/3; /* With DD we might also need to call LINCS with ncons=0 for communicating * coordinates to other nodes that do have constraints. */ if (ir->eConstrAlg == econtLINCS) { set_lincs(idef,md,EI_DYNAMICS(ir->eI),dd,constr->lincsd); } if (ir->eConstrAlg == econtSHAKE) { if (dd) { make_shake_sblock_dd(constr,&idef->il[F_CONSTR],&top->cgs,dd); } else { make_shake_sblock_pd(constr,idef,md); } if (ncons > constr->lagr_nalloc) { constr->lagr_nalloc = over_alloc_dd(ncons); srenew(constr->lagr,constr->lagr_nalloc); } } } /* Make a selection of the local atoms for essential dynamics */ if (constr->ed && dd) { dd_make_local_ed_indices(dd,constr->ed,md); } }
void set_state_entries(t_state *state, const t_inputrec *ir) { /* The entries in the state in the tpx file might not correspond * with what is needed, so we correct this here. */ state->flags = 0; if (ir->efep != efepNO || ir->bExpanded) { state->flags |= (1<<estLAMBDA); state->flags |= (1<<estFEPSTATE); } state->flags |= (1<<estX); if (state->lambda == NULL) { snew(state->lambda, efptNR); } if (state->x == NULL) { /* We need to allocate one element extra, since we might use * (unaligned) 4-wide SIMD loads to access rvec entries. */ snew(state->x, state->nalloc + 1); } if (EI_DYNAMICS(ir->eI)) { state->flags |= (1<<estV); if (state->v == NULL) { snew(state->v, state->nalloc + 1); } } if (ir->eI == eiCG) { state->flags |= (1<<estCGP); if (state->cg_p == NULL) { /* cg_p is not stored in the tpx file, so we need to allocate it */ snew(state->cg_p, state->nalloc + 1); } } state->nnhpres = 0; if (ir->ePBC != epbcNONE) { state->flags |= (1<<estBOX); if (inputrecPreserveShape(ir)) { state->flags |= (1<<estBOX_REL); } if ((ir->epc == epcPARRINELLORAHMAN) || (ir->epc == epcMTTK)) { state->flags |= (1<<estBOXV); } if (ir->epc != epcNO) { if (inputrecNptTrotter(ir) || (inputrecNphTrotter(ir))) { state->nnhpres = 1; state->flags |= (1<<estNHPRES_XI); state->flags |= (1<<estNHPRES_VXI); state->flags |= (1<<estSVIR_PREV); state->flags |= (1<<estFVIR_PREV); state->flags |= (1<<estVETA); state->flags |= (1<<estVOL0); } else { state->flags |= (1<<estPRES_PREV); } } } if (ir->etc == etcNOSEHOOVER) { state->flags |= (1<<estNH_XI); state->flags |= (1<<estNH_VXI); } if (ir->etc == etcVRESCALE) { state->flags |= (1<<estTC_INT); } init_gtc_state(state, state->ngtc, state->nnhpres, ir->opts.nhchainlength); /* allocate the space for nose-hoover chains */ init_ekinstate(&state->ekinstate, ir); snew(state->enerhist, 1); init_energyhistory(state->enerhist); init_df_history(&state->dfhist, ir->fepvals->n_lambda); state->swapstate.eSwapCoords = ir->eSwapCoords; }
void set_state_entries(t_state *state, const t_inputrec *ir) { /* The entries in the state in the tpx file might not correspond * with what is needed, so we correct this here. */ state->flags = 0; if (ir->efep != efepNO || ir->bExpanded) { state->flags |= (1<<estLAMBDA); state->flags |= (1<<estFEPSTATE); } state->flags |= (1<<estX); state->lambda.resize(efptNR); GMX_RELEASE_ASSERT(state->x.size() >= static_cast<unsigned int>(state->natoms), "We should start a run with an initialized state->x"); if (EI_DYNAMICS(ir->eI)) { state->flags |= (1<<estV); state->v.resize(state->natoms + 1); } if (ir->eI == eiCG) { state->flags |= (1<<estCGP); /* cg_p is not stored in the tpx file, so we need to allocate it */ state->cg_p.resize(state->natoms + 1); } state->nnhpres = 0; if (ir->ePBC != epbcNONE) { state->flags |= (1<<estBOX); if (inputrecPreserveShape(ir)) { state->flags |= (1<<estBOX_REL); } if ((ir->epc == epcPARRINELLORAHMAN) || (ir->epc == epcMTTK)) { state->flags |= (1<<estBOXV); state->flags |= (1<<estPRES_PREV); } if (inputrecNptTrotter(ir) || (inputrecNphTrotter(ir))) { state->nnhpres = 1; state->flags |= (1<<estNHPRES_XI); state->flags |= (1<<estNHPRES_VXI); state->flags |= (1<<estSVIR_PREV); state->flags |= (1<<estFVIR_PREV); state->flags |= (1<<estVETA); state->flags |= (1<<estVOL0); } } if (ir->etc == etcNOSEHOOVER) { state->flags |= (1<<estNH_XI); state->flags |= (1<<estNH_VXI); } if (ir->etc == etcVRESCALE) { state->flags |= (1<<estTC_INT); } init_gtc_state(state, state->ngtc, state->nnhpres, ir->opts.nhchainlength); /* allocate the space for nose-hoover chains */ init_ekinstate(&state->ekinstate, ir); if (ir->bExpanded) { snew(state->dfhist, 1); init_df_history(state->dfhist, ir->fepvals->n_lambda); } if (ir->eSwapCoords != eswapNO) { if (state->swapstate == NULL) { snew(state->swapstate, 1); } state->swapstate->eSwapCoords = ir->eSwapCoords; } }
int check_nstglobalcomm(FILE *fplog, t_commrec *cr, int nstglobalcomm, t_inputrec *ir) { if (!EI_DYNAMICS(ir->eI)) { nstglobalcomm = 1; } if (nstglobalcomm == -1) { if (!(ir->nstcalcenergy > 0 || ir->nstlist > 0 || ir->etc != etcNO || ir->epc != epcNO)) { nstglobalcomm = 10; if (ir->nstenergy > 0 && ir->nstenergy < nstglobalcomm) { nstglobalcomm = ir->nstenergy; } } else { /* Ensure that we do timely global communication for * (possibly) each of the four following options. */ nstglobalcomm = lcd4(ir->nstcalcenergy, ir->nstlist, ir->etc != etcNO ? ir->nsttcouple : 0, ir->epc != epcNO ? ir->nstpcouple : 0); } } else { if (ir->nstlist > 0 && nstglobalcomm > ir->nstlist && nstglobalcomm % ir->nstlist != 0) { nstglobalcomm = (nstglobalcomm / ir->nstlist)*ir->nstlist; md_print_warn(cr, fplog, "WARNING: nstglobalcomm is larger than nstlist, but not a multiple, setting it to %d\n", nstglobalcomm); } if (ir->nstcalcenergy > 0) { check_nst_param(fplog, cr, "-gcom", nstglobalcomm, "nstcalcenergy", &ir->nstcalcenergy); } if (ir->etc != etcNO && ir->nsttcouple > 0) { check_nst_param(fplog, cr, "-gcom", nstglobalcomm, "nsttcouple", &ir->nsttcouple); } if (ir->epc != epcNO && ir->nstpcouple > 0) { check_nst_param(fplog, cr, "-gcom", nstglobalcomm, "nstpcouple", &ir->nstpcouple); } check_nst_param(fplog, cr, "-gcom", nstglobalcomm, "nstenergy", &ir->nstenergy); check_nst_param(fplog, cr, "-gcom", nstglobalcomm, "nstlog", &ir->nstlog); } if (ir->comm_mode != ecmNO && ir->nstcomm < nstglobalcomm) { md_print_warn(cr, fplog, "WARNING: Changing nstcomm from %d to %d\n", ir->nstcomm, nstglobalcomm); ir->nstcomm = nstglobalcomm; } return nstglobalcomm; }
void set_constraints(struct gmx_constr *constr, gmx_localtop_t *top, t_inputrec *ir, t_mdatoms *md, t_commrec *cr) { t_idef *idef; int ncons; t_ilist *settle; int iO, iH; idef = &top->idef; if (constr->ncon_tot > 0) { /* We are using the local topology, * so there are only F_CONSTR constraints. */ ncons = idef->il[F_CONSTR].nr/3; /* With DD we might also need to call LINCS with ncons=0 for * communicating coordinates to other nodes that do have constraints. */ if (ir->eConstrAlg == econtLINCS) { set_lincs(idef, md, EI_DYNAMICS(ir->eI), cr, constr->lincsd); } if (ir->eConstrAlg == econtSHAKE) { if (cr->dd) { make_shake_sblock_dd(constr, &idef->il[F_CONSTR], &top->cgs, cr->dd); } else { make_shake_sblock_serial(constr, idef, md); } if (ncons > constr->lagr_nalloc) { constr->lagr_nalloc = over_alloc_dd(ncons); srenew(constr->lagr, constr->lagr_nalloc); } } } if (idef->il[F_SETTLE].nr > 0 && constr->settled == NULL) { settle = &idef->il[F_SETTLE]; iO = settle->iatoms[1]; iH = settle->iatoms[2]; constr->settled = settle_init(md->massT[iO], md->massT[iH], md->invmass[iO], md->invmass[iH], idef->iparams[settle->iatoms[0]].settle.doh, idef->iparams[settle->iatoms[0]].settle.dhh); } /* Make a selection of the local atoms for essential dynamics */ if (constr->ed && cr->dd) { dd_make_local_ed_indices(cr->dd, constr->ed); } }
gmx_constr_t init_constraints(FILE *fplog, gmx_mtop_t *mtop, t_inputrec *ir, gmx_edsam_t ed, t_state *state, t_commrec *cr) { int ncon, nset, nmol, settle_type, i, natoms, mt, nflexcon; struct gmx_constr *constr; char *env; t_ilist *ilist; gmx_mtop_ilistloop_t iloop; ncon = gmx_mtop_ftype_count(mtop, F_CONSTR) + gmx_mtop_ftype_count(mtop, F_CONSTRNC); nset = gmx_mtop_ftype_count(mtop, F_SETTLE); if (ncon+nset == 0 && ir->ePull != epullCONSTRAINT && ed == NULL) { return NULL; } snew(constr, 1); constr->ncon_tot = ncon; constr->nflexcon = 0; if (ncon > 0) { constr->n_at2con_mt = mtop->nmoltype; snew(constr->at2con_mt, constr->n_at2con_mt); for (mt = 0; mt < mtop->nmoltype; mt++) { constr->at2con_mt[mt] = make_at2con(0, mtop->moltype[mt].atoms.nr, mtop->moltype[mt].ilist, mtop->ffparams.iparams, EI_DYNAMICS(ir->eI), &nflexcon); for (i = 0; i < mtop->nmolblock; i++) { if (mtop->molblock[i].type == mt) { constr->nflexcon += mtop->molblock[i].nmol*nflexcon; } } } if (constr->nflexcon > 0) { if (fplog) { fprintf(fplog, "There are %d flexible constraints\n", constr->nflexcon); if (ir->fc_stepsize == 0) { fprintf(fplog, "\n" "WARNING: step size for flexible constraining = 0\n" " All flexible constraints will be rigid.\n" " Will try to keep all flexible constraints at their original length,\n" " but the lengths may exhibit some drift.\n\n"); constr->nflexcon = 0; } } if (constr->nflexcon > 0) { please_cite(fplog, "Hess2002"); } } if (ir->eConstrAlg == econtLINCS) { constr->lincsd = init_lincs(fplog, mtop, constr->nflexcon, constr->at2con_mt, DOMAINDECOMP(cr) && cr->dd->bInterCGcons, ir->nLincsIter, ir->nProjOrder); } if (ir->eConstrAlg == econtSHAKE) { if (DOMAINDECOMP(cr) && cr->dd->bInterCGcons) { gmx_fatal(FARGS, "SHAKE is not supported with domain decomposition and constraint that cross charge group boundaries, use LINCS"); } if (constr->nflexcon) { gmx_fatal(FARGS, "For this system also velocities and/or forces need to be constrained, this can not be done with SHAKE, you should select LINCS"); } please_cite(fplog, "Ryckaert77a"); if (ir->bShakeSOR) { please_cite(fplog, "Barth95a"); } constr->shaked = shake_init(); } } if (nset > 0) { please_cite(fplog, "Miyamoto92a"); constr->bInterCGsettles = inter_charge_group_settles(mtop); /* Check that we have only one settle type */ settle_type = -1; iloop = gmx_mtop_ilistloop_init(mtop); while (gmx_mtop_ilistloop_next(iloop, &ilist, &nmol)) { for (i = 0; i < ilist[F_SETTLE].nr; i += 4) { if (settle_type == -1) { settle_type = ilist[F_SETTLE].iatoms[i]; } else if (ilist[F_SETTLE].iatoms[i] != settle_type) { gmx_fatal(FARGS, "The [molecules] section of your topology specifies more than one block of\n" "a [moleculetype] with a [settles] block. Only one such is allowed. If you\n" "are trying to partition your solvent into different *groups* (e.g. for\n" "freezing, T-coupling, etc.) then you are using the wrong approach. Index\n" "files specify groups. Otherwise, you may wish to change the least-used\n" "block of molecules with SETTLE constraints into 3 normal constraints."); } } } constr->n_at2settle_mt = mtop->nmoltype; snew(constr->at2settle_mt, constr->n_at2settle_mt); for (mt = 0; mt < mtop->nmoltype; mt++) { constr->at2settle_mt[mt] = make_at2settle(mtop->moltype[mt].atoms.nr, &mtop->moltype[mt].ilist[F_SETTLE]); } } constr->maxwarn = 999; env = getenv("GMX_MAXCONSTRWARN"); if (env) { constr->maxwarn = 0; sscanf(env, "%d", &constr->maxwarn); if (fplog) { fprintf(fplog, "Setting the maximum number of constraint warnings to %d\n", constr->maxwarn); } if (MASTER(cr)) { fprintf(stderr, "Setting the maximum number of constraint warnings to %d\n", constr->maxwarn); } } if (constr->maxwarn < 0 && fplog) { fprintf(fplog, "maxwarn < 0, will not stop on constraint errors\n"); } constr->warncount_lincs = 0; constr->warncount_settle = 0; /* Initialize the essential dynamics sampling. * Put the pointer to the ED struct in constr */ constr->ed = ed; if (ed != NULL || state->edsamstate.nED > 0) { init_edsam(mtop, ir, cr, ed, state->x, state->box, &state->edsamstate); } constr->warn_mtop = mtop; return constr; }
int main (int argc, char *argv[]) { static char *desc[] = { "tpbconv can edit run input files in four ways.[PAR]" "[BB]1st.[bb] by modifying the number of steps in a run input file", "with option [TT]-nsteps[tt] or option [TT]-runtime[tt].[PAR]", "[BB]2st.[bb] (OBSOLETE) by creating a run input file", "for a continuation run when your simulation has crashed due to e.g.", "a full disk, or by making a continuation run input file.", "This option is obsolete, since mdrun now writes and reads", "checkpoint files.", "Note that a frame with coordinates and velocities is needed.", "When pressure and/or Nose-Hoover temperature coupling is used", "an energy file can be supplied to get an exact continuation", "of the original run.[PAR]", "[BB]3nd.[bb] by creating a tpx file for a subset of your original", "tpx file, which is useful when you want to remove the solvent from", "your tpx file, or when you want to make e.g. a pure Ca tpx file.", "[BB]WARNING: this tpx file is not fully functional[bb].", "[BB]4rd.[bb] by setting the charges of a specified group", "to zero. This is useful when doing free energy estimates", "using the LIE (Linear Interaction Energy) method." }; char *top_fn,*frame_fn; int fp,fp_ener=-1; t_trnheader head; int i,frame,run_step,nsteps_org; real run_t,state_t; bool bOK,bNsteps,bExtend,bUntil,bTime,bTraj; bool bFrame,bUse,bSel,bNeedEner,bReadEner,bScanEner; gmx_mtop_t mtop; t_atoms atoms; t_inputrec *ir,*irnew=NULL; t_gromppopts *gopts; t_state state; rvec *newx=NULL,*newv=NULL,*tmpx,*tmpv; matrix newbox; int gnx; char *grpname; atom_id *index=NULL; int nre; char **enm=NULL; t_enxframe *fr_ener=NULL; t_filenm fnm[] = { { efTPX, NULL, NULL, ffREAD }, { efTRN, "-f", NULL, ffOPTRD }, { efENX, "-e", NULL, ffOPTRD }, { efNDX, NULL, NULL, ffOPTRD }, { efTPX, "-o", "tpxout",ffWRITE } }; #define NFILE asize(fnm) /* Command line options */ static int nsteps_req = -1; static real runtime_req = -1; static real start_t = -1.0, extend_t = 0.0, until_t = 0.0; static bool bContinuation = TRUE,bZeroQ = FALSE; static t_pargs pa[] = { { "-nsteps", FALSE, etINT, {&nsteps_req}, "Change the number of steps" }, { "-runtime", FALSE, etREAL, {&runtime_req}, "Set the run time (ps)" }, { "-time", FALSE, etREAL, {&start_t}, "Continue from frame at this time (ps) instead of the last frame" }, { "-extend", FALSE, etREAL, {&extend_t}, "Extend runtime by this amount (ps)" }, { "-until", FALSE, etREAL, {&until_t}, "Extend runtime until this ending time (ps)" }, { "-zeroq", FALSE, etBOOL, {&bZeroQ}, "Set the charges of a group (from the index) to zero" }, { "-cont", FALSE, etBOOL, {&bContinuation}, "For exact continuation, the constraints should not be solved before the first step" } }; int nerror = 0; CopyRight(stdout,argv[0]); /* Parse the command line */ parse_common_args(&argc,argv,0,NFILE,fnm,asize(pa),pa, asize(desc),desc,0,NULL); bNsteps = (nsteps_req >= 0 || runtime_req >= 0); bExtend = opt2parg_bSet("-extend",asize(pa),pa); bUntil = opt2parg_bSet("-until",asize(pa),pa); bTime = opt2parg_bSet("-time",asize(pa),pa); bTraj = (opt2bSet("-f",NFILE,fnm) || bTime); top_fn = ftp2fn(efTPX,NFILE,fnm); fprintf(stderr,"Reading toplogy and shit from %s\n",top_fn); snew(ir,1); read_tpx_state(top_fn,&run_step,&run_t,ir,&state,NULL,&mtop); if (bTraj) { fprintf(stderr,"\n" "NOTE: Reading the state from trajectory is an obsolete feaure of tpbconv.\n" " Continuation should be done by loading a checkpoint file with mdrun -cpi\n" " This guarantees that all state variables are transferred.\n" " tpbconv is now only useful for increasing nsteps,\n" " but even that can often be avoided by using mdrun -maxh\n" "\n"); if (ir->bContinuation != bContinuation) fprintf(stderr,"Modifying ir->bContinuation to %s\n", bool_names[bContinuation]); ir->bContinuation = bContinuation; bNeedEner = (ir->epc == epcPARRINELLORAHMAN || ir->etc == etcNOSEHOOVER); bReadEner = (bNeedEner && ftp2bSet(efENX,NFILE,fnm)); bScanEner = (bReadEner && !bTime); if (ir->epc != epcNO || EI_SD(ir->eI) || ir->eI == eiBD) { fprintf(stderr,"NOTE: The simulation uses pressure coupling and/or stochastic dynamics.\n" "tpbconv can not provide binary identical continuation.\n" "If you want that, supply a checkpoint file to mdrun\n\n"); } if (EI_SD(ir->eI) || ir->eI == eiBD) { fprintf(stderr,"\nChanging ld-seed from %d ",ir->ld_seed); ir->ld_seed = make_seed(); fprintf(stderr,"to %d\n\n",ir->ld_seed); } frame_fn = ftp2fn(efTRN,NFILE,fnm); fprintf(stderr, "\nREADING COORDS, VELS AND BOX FROM TRAJECTORY %s...\n\n", frame_fn); fp = open_trn(frame_fn,"r"); if (bScanEner) { fp_ener = open_enx(ftp2fn(efENX,NFILE,fnm),"r"); do_enxnms(fp_ener,&nre,&enm); snew(fr_ener,1); fr_ener->t = -1e-12; } /* Now scan until the last set of x and v (step == 0) * or the ones at step step. */ bFrame = TRUE; frame = 0; while (bFrame) { bFrame = fread_trnheader(fp,&head,&bOK); if (bOK && frame == 0) { if (mtop.natoms != head.natoms) gmx_fatal(FARGS,"Number of atoms in Topology (%d) " "is not the same as in Trajectory (%d)\n", mtop.natoms,head.natoms); snew(newx,head.natoms); snew(newv,head.natoms); } bFrame = bFrame && bOK; if (bFrame) { bOK = fread_htrn(fp,&head,newbox,newx,newv,NULL); } bFrame = bFrame && bOK; bUse = FALSE; if (bFrame && (head.x_size) && (head.v_size || !EI_STATE_VELOCITY(ir->eI))) { bUse = TRUE; if (bScanEner) { /* Read until the energy time is >= the trajectory time */ while (fr_ener->t < head.t && do_enx(fp_ener,fr_ener)); bUse = (fr_ener->t == head.t); } if (bUse) { tmpx = newx; newx = state.x; state.x = tmpx; tmpv = newv; newv = state.v; state.v = tmpv; run_t = head.t; run_step = head.step; state.lambda = head.lambda; copy_mat(newbox,state.box); } } if (bFrame || !bOK) { fprintf(stderr,"\r%s %s frame %6d: step %6d time %8.3f", bUse ? "Read " : "Skipped",ftp2ext(fn2ftp(frame_fn)), frame,head.step,head.t); frame++; if (bTime && (head.t >= start_t)) bFrame = FALSE; } } if (bScanEner) { close_enx(fp_ener); free_enxframe(fr_ener); for(i=0; i<nre; i++) sfree(enm[i]); sfree(enm); } close_trn(fp); fprintf(stderr,"\n"); if (!bOK) fprintf(stderr,"%s frame %d (step %d, time %g) is incomplete\n", ftp2ext(fn2ftp(frame_fn)),frame-1,head.step,head.t); fprintf(stderr,"\nUsing frame of step %d time %g\n",run_step,run_t); if (bNeedEner) { if (bReadEner) { get_enx_state(ftp2fn(efENX,NFILE,fnm),run_t,&mtop.groups,ir,&state); } else { fprintf(stderr,"\nWARNING: The simulation uses %s temperature and/or %s pressure coupling,\n" " the continuation will only be exact when an energy file is supplied\n\n", ETCOUPLTYPE(etcNOSEHOOVER), EPCOUPLTYPE(epcPARRINELLORAHMAN)); } } } if (bNsteps) { if (nsteps_req < 0) { if (!EI_DYNAMICS(ir->eI)) { gmx_fatal(FARGS,"Can not set the run time with integrator '%s'", EI(ir->eI)); } nsteps_req = (int)(runtime_req/ir->delta_t + 0.5); } fprintf(stderr,"Setting nsteps to %d\n",nsteps_req); ir->nsteps = nsteps_req; } else { /* Determine total number of steps remaining */ if (bExtend) { ir->nsteps = ir->nsteps - (run_step - ir->init_step) + (int)(extend_t/ir->delta_t + 0.5); printf("Extending remaining runtime of by %g ps (now %d steps)\n", extend_t,ir->nsteps); } else if (bUntil) { printf("nsteps = %d, run_step = %d, current_t = %g, until = %g\n", ir->nsteps,run_step,run_t,until_t); ir->nsteps = (int)((until_t - run_t)/ir->delta_t + 0.5); printf("Extending remaining runtime until %g ps (now %d steps)\n", until_t,ir->nsteps); } else { ir->nsteps -= run_step - ir->init_step; /* Print message */ printf("%d steps (%g ps) remaining from first run.\n", ir->nsteps,ir->nsteps*ir->delta_t); } } if (bNsteps || bZeroQ || (ir->nsteps > 0)) { ir->init_step = run_step; if (ftp2bSet(efNDX,NFILE,fnm) || !(bNsteps || bExtend || bUntil || bTraj)) { atoms = gmx_mtop_global_atoms(&mtop); get_index(&atoms,ftp2fn_null(efNDX,NFILE,fnm),1, &gnx,&index,&grpname); if (!bZeroQ) { bSel = (gnx != state.natoms); for (i=0; ((i<gnx) && (!bSel)); i++) bSel = (i!=index[i]); } else bSel = FALSE; if (bSel) { fprintf(stderr,"Will write subset %s of original tpx containing %d " "atoms\n",grpname,gnx); reduce_topology_x(gnx,index,&mtop,state.x,state.v); state.natoms = gnx; } else if (bZeroQ) { zeroq(gnx,index,&mtop); fprintf(stderr,"Zero-ing charges for group %s\n",grpname); } else fprintf(stderr,"Will write full tpx file (no selection)\n"); } state_t = ir->init_t + ir->init_step*ir->delta_t; fprintf(stderr,"Writing statusfile with starting step %10d and length %10d steps...\n", ir->init_step,ir->nsteps); fprintf(stderr," time %10.3f and length %10.3f ps\n", state_t,ir->nsteps*ir->delta_t); write_tpx_state(opt2fn("-o",NFILE,fnm),0,state_t,ir,&state,&mtop); } else printf("You've simulated long enough. Not writing tpr file\n"); thanx(stderr); return 0; }
void init_membed(FILE *fplog, gmx_membed_t *membed, int nfile, const t_filenm fnm[], gmx_mtop_t *mtop, t_inputrec *inputrec, t_state *state, t_commrec *cr,real *cpt) { char *ins; int i,rm_bonded_at,fr_id,fr_i=0,tmp_id,warn=0; int ng,j,max_lip_rm,ins_grp_id,ins_nat,mem_nat,ntype,lip_rm,tpr_version; real prot_area; rvec *r_ins=NULL; t_block *ins_at,*rest_at; pos_ins_t *pos_ins; mem_t *mem_p; rm_t *rm_p; gmx_groups_t *groups; gmx_bool bExcl=FALSE; t_atoms atoms; t_pbc *pbc; char **piecename=NULL; /* input variables */ const char *membed_input; real xy_fac = 0.5; real xy_max = 1.0; real z_fac = 1.0; real z_max = 1.0; int it_xy = 1000; int it_z = 0; real probe_rad = 0.22; int low_up_rm = 0; int maxwarn=0; int pieces=1; gmx_bool bALLOW_ASYMMETRY=FALSE; snew(ins_at,1); snew(pos_ins,1); if(MASTER(cr)) { /* get input data out membed file */ membed_input = opt2fn("-membed",nfile,fnm); get_input(membed_input,&xy_fac,&xy_max,&z_fac,&z_max,&it_xy,&it_z,&probe_rad,&low_up_rm,&maxwarn,&pieces,&bALLOW_ASYMMETRY); tpr_version = get_tpr_version(ftp2fn(efTPX,nfile,fnm)); if (tpr_version<58) gmx_fatal(FARGS,"Version of *.tpr file to old (%d). Rerun grompp with gromacs VERSION 4.0.3 or newer.\n",tpr_version); if( !EI_DYNAMICS(inputrec->eI) ) gmx_input("Change integrator to a dynamics integrator in mdp file (e.g. md or sd)."); if(PAR(cr)) gmx_input("Sorry, parallel g_membed is not yet fully functional."); #ifdef GMX_OPENMM gmx_input("Sorry, g_membed does not work with openmm."); #endif if(*cpt>=0) { fprintf(stderr,"\nSetting -cpt to -1, because embedding cannot be restarted from cpt-files.\n"); *cpt=-1; } groups=&(mtop->groups); atoms=gmx_mtop_global_atoms(mtop); snew(mem_p,1); fprintf(stderr,"\nSelect a group to embed in the membrane:\n"); get_index(&atoms,opt2fn_null("-mn",nfile,fnm),1,&(ins_at->nr),&(ins_at->index),&ins); ins_grp_id = search_string(ins,groups->ngrpname,(groups->grpname)); fprintf(stderr,"\nSelect a group to embed %s into (e.g. the membrane):\n",ins); get_index(&atoms,opt2fn_null("-mn",nfile,fnm),1,&(mem_p->mem_at.nr),&(mem_p->mem_at.index),&(mem_p->name)); pos_ins->pieces=pieces; snew(pos_ins->nidx,pieces); snew(pos_ins->subindex,pieces); snew(piecename,pieces); if (pieces>1) { fprintf(stderr,"\nSelect pieces to embed:\n"); get_index(&atoms,opt2fn_null("-mn",nfile,fnm),pieces,pos_ins->nidx,pos_ins->subindex,piecename); } else { /*use whole embedded group*/ snew(pos_ins->nidx,1); snew(pos_ins->subindex,1); pos_ins->nidx[0]=ins_at->nr; pos_ins->subindex[0]=ins_at->index; } if(probe_rad<0.2199999) { warn++; fprintf(stderr,"\nWarning %d:\nA probe radius (-rad) smaller than 0.2 can result in overlap between waters " "and the group to embed, which will result in Lincs errors etc.\nIf you are sure, you can increase maxwarn.\n\n",warn); } if(xy_fac<0.09999999) { warn++; fprintf(stderr,"\nWarning %d:\nThe initial size of %s is probably too smal.\n" "If you are sure, you can increase maxwarn.\n\n",warn,ins); } if(it_xy<1000) { warn++; fprintf(stderr,"\nWarning %d;\nThe number of steps used to grow the xy-coordinates of %s (%d) is probably too small.\n" "Increase -nxy or, if you are sure, you can increase maxwarn.\n\n",warn,ins,it_xy); } if( (it_z<100) && ( z_fac<0.99999999 || z_fac>1.0000001) ) { warn++; fprintf(stderr,"\nWarning %d;\nThe number of steps used to grow the z-coordinate of %s (%d) is probably too small.\n" "Increase -nz or, if you are sure, you can increase maxwarn.\n\n",warn,ins,it_z); } if(it_xy+it_z>inputrec->nsteps) { warn++; fprintf(stderr,"\nWarning %d:\nThe number of growth steps (-nxy + -nz) is larger than the number of steps in the tpr.\n" "If you are sure, you can increase maxwarn.\n\n",warn); } fr_id=-1; if( inputrec->opts.ngfrz==1) gmx_fatal(FARGS,"You did not specify \"%s\" as a freezegroup.",ins); for(i=0;i<inputrec->opts.ngfrz;i++) { tmp_id = mtop->groups.grps[egcFREEZE].nm_ind[i]; if(ins_grp_id==tmp_id) { fr_id=tmp_id; fr_i=i; } } if (fr_id == -1 ) gmx_fatal(FARGS,"\"%s\" not as freezegroup defined in the mdp-file.",ins); for(i=0;i<DIM;i++) if( inputrec->opts.nFreeze[fr_i][i] != 1) gmx_fatal(FARGS,"freeze dimensions for %s are not Y Y Y\n",ins); ng = groups->grps[egcENER].nr; if (ng == 1) gmx_input("No energy groups defined. This is necessary for energy exclusion in the freeze group"); for(i=0;i<ng;i++) { for(j=0;j<ng;j++) { if (inputrec->opts.egp_flags[ng*i+j] == EGP_EXCL) { bExcl = TRUE; if ( (groups->grps[egcENER].nm_ind[i] != ins_grp_id) || (groups->grps[egcENER].nm_ind[j] != ins_grp_id) ) gmx_fatal(FARGS,"Energy exclusions \"%s\" and \"%s\" do not match the group to embed \"%s\"", *groups->grpname[groups->grps[egcENER].nm_ind[i]], *groups->grpname[groups->grps[egcENER].nm_ind[j]],ins); } } } if (!bExcl) gmx_input("No energy exclusion groups defined. This is necessary for energy exclusion in the freeze group"); /* Guess the area the protein will occupy in the membrane plane Calculate area per lipid*/ snew(rest_at,1); ins_nat = init_ins_at(ins_at,rest_at,state,pos_ins,groups,ins_grp_id,xy_max); /* Check moleculetypes in insertion group */ check_types(ins_at,rest_at,mtop); mem_nat = init_mem_at(mem_p,mtop,state->x,state->box,pos_ins); prot_area = est_prot_area(pos_ins,state->x,ins_at,mem_p); if ( (prot_area>7.5) && ( (state->box[XX][XX]*state->box[YY][YY]-state->box[XX][YY]*state->box[YY][XX])<50) ) { warn++; fprintf(stderr,"\nWarning %d:\nThe xy-area is very small compared to the area of the protein.\n" "This might cause pressure problems during the growth phase. Just try with\n" "current setup (-maxwarn + 1), but if pressure problems occur, lower the\n" "compressibility in the mdp-file or use no pressure coupling at all.\n\n",warn); } if(warn>maxwarn) gmx_fatal(FARGS,"Too many warnings.\n"); printf("The estimated area of the protein in the membrane is %.3f nm^2\n",prot_area); printf("\nThere are %d lipids in the membrane part that overlaps the protein.\nThe area per lipid is %.4f nm^2.\n",mem_p->nmol,mem_p->lip_area); /* Maximum number of lipids to be removed*/ max_lip_rm=(int)(2*prot_area/mem_p->lip_area); printf("Maximum number of lipids that will be removed is %d.\n",max_lip_rm); printf("\nWill resize the protein by a factor of %.3f in the xy plane and %.3f in the z direction.\n" "This resizing will be done with respect to the geometrical center of all protein atoms\n" "that span the membrane region, i.e. z between %.3f and %.3f\n\n",xy_fac,z_fac,mem_p->zmin,mem_p->zmax); /* resize the protein by xy and by z if necessary*/ snew(r_ins,ins_at->nr); init_resize(ins_at,r_ins,pos_ins,mem_p,state->x,bALLOW_ASYMMETRY); membed->fac[0]=membed->fac[1]=xy_fac; membed->fac[2]=z_fac; membed->xy_step =(xy_max-xy_fac)/(double)(it_xy); membed->z_step =(z_max-z_fac)/(double)(it_z-1); resize(r_ins,state->x,pos_ins,membed->fac); /* remove overlapping lipids and water from the membrane box*/ /*mark molecules to be removed*/ snew(pbc,1); set_pbc(pbc,inputrec->ePBC,state->box); snew(rm_p,1); lip_rm = gen_rm_list(rm_p,ins_at,rest_at,pbc,mtop,state->x, r_ins, mem_p,pos_ins,probe_rad,low_up_rm,bALLOW_ASYMMETRY); lip_rm -= low_up_rm; if(fplog) for(i=0;i<rm_p->nr;i++) fprintf(fplog,"rm mol %d\n",rm_p->mol[i]); for(i=0;i<mtop->nmolblock;i++) { ntype=0; for(j=0;j<rm_p->nr;j++) if(rm_p->block[j]==i) ntype++; printf("Will remove %d %s molecules\n",ntype,*(mtop->moltype[mtop->molblock[i].type].name)); } if(lip_rm>max_lip_rm) { warn++; fprintf(stderr,"\nWarning %d:\nTrying to remove a larger lipid area than the estimated protein area\n" "Try making the -xyinit resize factor smaller.\n\n",warn); } /*remove all lipids and waters overlapping and update all important structures*/ rm_group(inputrec,groups,mtop,rm_p,state,ins_at,pos_ins); rm_bonded_at = rm_bonded(ins_at,mtop); if (rm_bonded_at != ins_at->nr) { fprintf(stderr,"Warning: The number of atoms for which the bonded interactions are removed is %d, " "while %d atoms are embedded. Make sure that the atoms to be embedded are not in the same" "molecule type as atoms that are not to be embedded.\n",rm_bonded_at,ins_at->nr); } if(warn>maxwarn) gmx_fatal(FARGS,"Too many warnings.\nIf you are sure these warnings are harmless, you can increase -maxwarn"); if (ftp2bSet(efTOP,nfile,fnm)) top_update(opt2fn("-mp",nfile,fnm),ins,rm_p,mtop); sfree(pbc); sfree(rest_at); if (pieces>1) { sfree(piecename); } membed->it_xy=it_xy; membed->it_z=it_z; membed->pos_ins=pos_ins; membed->r_ins=r_ins; } }
int mdrunner(gmx_hw_opt_t *hw_opt, FILE *fplog, t_commrec *cr, int nfile, const t_filenm fnm[], const output_env_t oenv, gmx_bool bVerbose, gmx_bool bCompact, int nstglobalcomm, ivec ddxyz, int dd_node_order, real rdd, real rconstr, const char *dddlb_opt, real dlb_scale, const char *ddcsx, const char *ddcsy, const char *ddcsz, const char *nbpu_opt, int nstlist_cmdline, gmx_int64_t nsteps_cmdline, int nstepout, int resetstep, int gmx_unused nmultisim, int repl_ex_nst, int repl_ex_nex, int repl_ex_seed, real pforce, real cpt_period, real max_hours, int imdport, unsigned long Flags) { gmx_bool bForceUseGPU, bTryUseGPU, bRerunMD; t_inputrec *inputrec; t_state *state = NULL; matrix box; gmx_ddbox_t ddbox = {0}; int npme_major, npme_minor; t_nrnb *nrnb; gmx_mtop_t *mtop = NULL; t_mdatoms *mdatoms = NULL; t_forcerec *fr = NULL; t_fcdata *fcd = NULL; real ewaldcoeff_q = 0; real ewaldcoeff_lj = 0; struct gmx_pme_t **pmedata = NULL; gmx_vsite_t *vsite = NULL; gmx_constr_t constr; int nChargePerturbed = -1, nTypePerturbed = 0, status; gmx_wallcycle_t wcycle; gmx_bool bReadEkin; gmx_walltime_accounting_t walltime_accounting = NULL; int rc; gmx_int64_t reset_counters; gmx_edsam_t ed = NULL; int nthreads_pme = 1; int nthreads_pp = 1; gmx_membed_t membed = NULL; gmx_hw_info_t *hwinfo = NULL; /* The master rank decides early on bUseGPU and broadcasts this later */ gmx_bool bUseGPU = FALSE; /* CAUTION: threads may be started later on in this function, so cr doesn't reflect the final parallel state right now */ snew(inputrec, 1); snew(mtop, 1); if (Flags & MD_APPENDFILES) { fplog = NULL; } bRerunMD = (Flags & MD_RERUN); bForceUseGPU = (strncmp(nbpu_opt, "gpu", 3) == 0); bTryUseGPU = (strncmp(nbpu_opt, "auto", 4) == 0) || bForceUseGPU; /* Detect hardware, gather information. This is an operation that is * global for this process (MPI rank). */ hwinfo = gmx_detect_hardware(fplog, cr, bTryUseGPU); gmx_print_detected_hardware(fplog, cr, hwinfo); if (fplog != NULL) { /* Print references after all software/hardware printing */ please_cite(fplog, "Abraham2015"); please_cite(fplog, "Pall2015"); please_cite(fplog, "Pronk2013"); please_cite(fplog, "Hess2008b"); please_cite(fplog, "Spoel2005a"); please_cite(fplog, "Lindahl2001a"); please_cite(fplog, "Berendsen95a"); } snew(state, 1); if (SIMMASTER(cr)) { /* Read (nearly) all data required for the simulation */ read_tpx_state(ftp2fn(efTPR, nfile, fnm), inputrec, state, NULL, mtop); if (inputrec->cutoff_scheme == ecutsVERLET) { /* Here the master rank decides if all ranks will use GPUs */ bUseGPU = (hwinfo->gpu_info.n_dev_compatible > 0 || getenv("GMX_EMULATE_GPU") != NULL); /* TODO add GPU kernels for this and replace this check by: * (bUseGPU && (ir->vdwtype == evdwPME && * ir->ljpme_combination_rule == eljpmeLB)) * update the message text and the content of nbnxn_acceleration_supported. */ if (bUseGPU && !nbnxn_gpu_acceleration_supported(fplog, cr, inputrec, bRerunMD)) { /* Fallback message printed by nbnxn_acceleration_supported */ if (bForceUseGPU) { gmx_fatal(FARGS, "GPU acceleration requested, but not supported with the given input settings"); } bUseGPU = FALSE; } prepare_verlet_scheme(fplog, cr, inputrec, nstlist_cmdline, mtop, state->box, bUseGPU); } else { if (nstlist_cmdline > 0) { gmx_fatal(FARGS, "Can not set nstlist with the group cut-off scheme"); } if (hwinfo->gpu_info.n_dev_compatible > 0) { md_print_warn(cr, fplog, "NOTE: GPU(s) found, but the current simulation can not use GPUs\n" " To use a GPU, set the mdp option: cutoff-scheme = Verlet\n"); } if (bForceUseGPU) { gmx_fatal(FARGS, "GPU requested, but can't be used without cutoff-scheme=Verlet"); } #ifdef GMX_TARGET_BGQ md_print_warn(cr, fplog, "NOTE: There is no SIMD implementation of the group scheme kernels on\n" " BlueGene/Q. You will observe better performance from using the\n" " Verlet cut-off scheme.\n"); #endif } if (inputrec->eI == eiSD2) { md_print_warn(cr, fplog, "The stochastic dynamics integrator %s is deprecated, since\n" "it is slower than integrator %s and is slightly less accurate\n" "with constraints. Use the %s integrator.", ei_names[inputrec->eI], ei_names[eiSD1], ei_names[eiSD1]); } } /* Check and update the hardware options for internal consistency */ check_and_update_hw_opt_1(hw_opt, cr); /* Early check for externally set process affinity. */ gmx_check_thread_affinity_set(fplog, cr, hw_opt, hwinfo->nthreads_hw_avail, FALSE); #ifdef GMX_THREAD_MPI if (SIMMASTER(cr)) { if (cr->npmenodes > 0 && hw_opt->nthreads_tmpi <= 0) { gmx_fatal(FARGS, "You need to explicitly specify the number of MPI threads (-ntmpi) when using separate PME ranks"); } /* Since the master knows the cut-off scheme, update hw_opt for this. * This is done later for normal MPI and also once more with tMPI * for all tMPI ranks. */ check_and_update_hw_opt_2(hw_opt, inputrec->cutoff_scheme); /* NOW the threads will be started: */ hw_opt->nthreads_tmpi = get_nthreads_mpi(hwinfo, hw_opt, inputrec, mtop, cr, fplog, bUseGPU); if (hw_opt->nthreads_tmpi > 1) { t_commrec *cr_old = cr; /* now start the threads. */ cr = mdrunner_start_threads(hw_opt, fplog, cr_old, nfile, fnm, oenv, bVerbose, bCompact, nstglobalcomm, ddxyz, dd_node_order, rdd, rconstr, dddlb_opt, dlb_scale, ddcsx, ddcsy, ddcsz, nbpu_opt, nstlist_cmdline, nsteps_cmdline, nstepout, resetstep, nmultisim, repl_ex_nst, repl_ex_nex, repl_ex_seed, pforce, cpt_period, max_hours, Flags); /* the main thread continues here with a new cr. We don't deallocate the old cr because other threads may still be reading it. */ if (cr == NULL) { gmx_comm("Failed to spawn threads"); } } } #endif /* END OF CAUTION: cr is now reliable */ /* g_membed initialisation * * Because we change the mtop, init_membed is called before the init_parallel * * (in case we ever want to make it run in parallel) */ if (opt2bSet("-membed", nfile, fnm)) { if (MASTER(cr)) { fprintf(stderr, "Initializing membed"); } membed = init_membed(fplog, nfile, fnm, mtop, inputrec, state, cr, &cpt_period); } if (PAR(cr)) { /* now broadcast everything to the non-master nodes/threads: */ init_parallel(cr, inputrec, mtop); /* The master rank decided on the use of GPUs, * broadcast this information to all ranks. */ gmx_bcast_sim(sizeof(bUseGPU), &bUseGPU, cr); } if (fplog != NULL) { pr_inputrec(fplog, 0, "Input Parameters", inputrec, FALSE); fprintf(fplog, "\n"); } /* now make sure the state is initialized and propagated */ set_state_entries(state, inputrec); /* A parallel command line option consistency check that we can only do after any threads have started. */ if (!PAR(cr) && (ddxyz[XX] > 1 || ddxyz[YY] > 1 || ddxyz[ZZ] > 1 || cr->npmenodes > 0)) { gmx_fatal(FARGS, "The -dd or -npme option request a parallel simulation, " #ifndef GMX_MPI "but %s was compiled without threads or MPI enabled" #else #ifdef GMX_THREAD_MPI "but the number of threads (option -nt) is 1" #else "but %s was not started through mpirun/mpiexec or only one rank was requested through mpirun/mpiexec" #endif #endif , output_env_get_program_display_name(oenv) ); } if (bRerunMD && (EI_ENERGY_MINIMIZATION(inputrec->eI) || eiNM == inputrec->eI)) { gmx_fatal(FARGS, "The .mdp file specified an energy mininization or normal mode algorithm, and these are not compatible with mdrun -rerun"); } if (can_use_allvsall(inputrec, TRUE, cr, fplog) && DOMAINDECOMP(cr)) { gmx_fatal(FARGS, "All-vs-all loops do not work with domain decomposition, use a single MPI rank"); } if (!(EEL_PME(inputrec->coulombtype) || EVDW_PME(inputrec->vdwtype))) { if (cr->npmenodes > 0) { gmx_fatal_collective(FARGS, cr, NULL, "PME-only ranks are requested, but the system does not use PME for electrostatics or LJ"); } cr->npmenodes = 0; } if (bUseGPU && cr->npmenodes < 0) { /* With GPUs we don't automatically use PME-only ranks. PME ranks can * improve performance with many threads per GPU, since our OpenMP * scaling is bad, but it's difficult to automate the setup. */ cr->npmenodes = 0; } #ifdef GMX_FAHCORE if (MASTER(cr)) { fcRegisterSteps(inputrec->nsteps, inputrec->init_step); } #endif /* NMR restraints must be initialized before load_checkpoint, * since with time averaging the history is added to t_state. * For proper consistency check we therefore need to extend * t_state here. * So the PME-only nodes (if present) will also initialize * the distance restraints. */ snew(fcd, 1); /* This needs to be called before read_checkpoint to extend the state */ init_disres(fplog, mtop, inputrec, cr, fcd, state, repl_ex_nst > 0); init_orires(fplog, mtop, state->x, inputrec, cr, &(fcd->orires), state); if (DEFORM(*inputrec)) { /* Store the deform reference box before reading the checkpoint */ if (SIMMASTER(cr)) { copy_mat(state->box, box); } if (PAR(cr)) { gmx_bcast(sizeof(box), box, cr); } /* Because we do not have the update struct available yet * in which the reference values should be stored, * we store them temporarily in static variables. * This should be thread safe, since they are only written once * and with identical values. */ tMPI_Thread_mutex_lock(&deform_init_box_mutex); deform_init_init_step_tpx = inputrec->init_step; copy_mat(box, deform_init_box_tpx); tMPI_Thread_mutex_unlock(&deform_init_box_mutex); } if (opt2bSet("-cpi", nfile, fnm)) { /* Check if checkpoint file exists before doing continuation. * This way we can use identical input options for the first and subsequent runs... */ if (gmx_fexist_master(opt2fn_master("-cpi", nfile, fnm, cr), cr) ) { load_checkpoint(opt2fn_master("-cpi", nfile, fnm, cr), &fplog, cr, ddxyz, inputrec, state, &bReadEkin, (Flags & MD_APPENDFILES), (Flags & MD_APPENDFILESSET)); if (bReadEkin) { Flags |= MD_READ_EKIN; } } } if (MASTER(cr) && (Flags & MD_APPENDFILES)) { gmx_log_open(ftp2fn(efLOG, nfile, fnm), cr, Flags, &fplog); } /* override nsteps with value from cmdline */ override_nsteps_cmdline(fplog, nsteps_cmdline, inputrec, cr); if (SIMMASTER(cr)) { copy_mat(state->box, box); } if (PAR(cr)) { gmx_bcast(sizeof(box), box, cr); } /* Essential dynamics */ if (opt2bSet("-ei", nfile, fnm)) { /* Open input and output files, allocate space for ED data structure */ ed = ed_open(mtop->natoms, &state->edsamstate, nfile, fnm, Flags, oenv, cr); } if (PAR(cr) && !(EI_TPI(inputrec->eI) || inputrec->eI == eiNM)) { cr->dd = init_domain_decomposition(fplog, cr, Flags, ddxyz, rdd, rconstr, dddlb_opt, dlb_scale, ddcsx, ddcsy, ddcsz, mtop, inputrec, box, state->x, &ddbox, &npme_major, &npme_minor); make_dd_communicators(fplog, cr, dd_node_order); /* Set overallocation to avoid frequent reallocation of arrays */ set_over_alloc_dd(TRUE); } else { /* PME, if used, is done on all nodes with 1D decomposition */ cr->npmenodes = 0; cr->duty = (DUTY_PP | DUTY_PME); npme_major = 1; npme_minor = 1; if (inputrec->ePBC == epbcSCREW) { gmx_fatal(FARGS, "pbc=%s is only implemented with domain decomposition", epbc_names[inputrec->ePBC]); } } if (PAR(cr)) { /* After possible communicator splitting in make_dd_communicators. * we can set up the intra/inter node communication. */ gmx_setup_nodecomm(fplog, cr); } /* Initialize per-physical-node MPI process/thread ID and counters. */ gmx_init_intranode_counters(cr); #ifdef GMX_MPI if (MULTISIM(cr)) { md_print_info(cr, fplog, "This is simulation %d out of %d running as a composite GROMACS\n" "multi-simulation job. Setup for this simulation:\n\n", cr->ms->sim, cr->ms->nsim); } md_print_info(cr, fplog, "Using %d MPI %s\n", cr->nnodes, #ifdef GMX_THREAD_MPI cr->nnodes == 1 ? "thread" : "threads" #else cr->nnodes == 1 ? "process" : "processes" #endif ); fflush(stderr); #endif /* Check and update hw_opt for the cut-off scheme */ check_and_update_hw_opt_2(hw_opt, inputrec->cutoff_scheme); /* Check and update hw_opt for the number of MPI ranks */ check_and_update_hw_opt_3(hw_opt); gmx_omp_nthreads_init(fplog, cr, hwinfo->nthreads_hw_avail, hw_opt->nthreads_omp, hw_opt->nthreads_omp_pme, (cr->duty & DUTY_PP) == 0, inputrec->cutoff_scheme == ecutsVERLET); #ifndef NDEBUG if (integrator[inputrec->eI].func != do_tpi && inputrec->cutoff_scheme == ecutsVERLET) { gmx_feenableexcept(); } #endif if (bUseGPU) { /* Select GPU id's to use */ gmx_select_gpu_ids(fplog, cr, &hwinfo->gpu_info, bForceUseGPU, &hw_opt->gpu_opt); } else { /* Ignore (potentially) manually selected GPUs */ hw_opt->gpu_opt.n_dev_use = 0; } /* check consistency across ranks of things like SIMD * support and number of GPUs selected */ gmx_check_hw_runconf_consistency(fplog, hwinfo, cr, hw_opt, bUseGPU); /* Now that we know the setup is consistent, check for efficiency */ check_resource_division_efficiency(hwinfo, hw_opt, Flags & MD_NTOMPSET, cr, fplog); if (DOMAINDECOMP(cr)) { /* When we share GPUs over ranks, we need to know this for the DLB */ dd_setup_dlb_resource_sharing(cr, hwinfo, hw_opt); } /* getting number of PP/PME threads PME: env variable should be read only on one node to make sure it is identical everywhere; */ /* TODO nthreads_pp is only used for pinning threads. * This is a temporary solution until we have a hw topology library. */ nthreads_pp = gmx_omp_nthreads_get(emntNonbonded); nthreads_pme = gmx_omp_nthreads_get(emntPME); wcycle = wallcycle_init(fplog, resetstep, cr, nthreads_pp, nthreads_pme); if (PAR(cr)) { /* Master synchronizes its value of reset_counters with all nodes * including PME only nodes */ reset_counters = wcycle_get_reset_counters(wcycle); gmx_bcast_sim(sizeof(reset_counters), &reset_counters, cr); wcycle_set_reset_counters(wcycle, reset_counters); } snew(nrnb, 1); if (cr->duty & DUTY_PP) { bcast_state(cr, state); /* Initiate forcerecord */ fr = mk_forcerec(); fr->hwinfo = hwinfo; fr->gpu_opt = &hw_opt->gpu_opt; init_forcerec(fplog, oenv, fr, fcd, inputrec, mtop, cr, box, opt2fn("-table", nfile, fnm), opt2fn("-tabletf", nfile, fnm), opt2fn("-tablep", nfile, fnm), opt2fn("-tableb", nfile, fnm), nbpu_opt, FALSE, pforce); /* version for PCA_NOT_READ_NODE (see md.c) */ /*init_forcerec(fplog,fr,fcd,inputrec,mtop,cr,box,FALSE, "nofile","nofile","nofile","nofile",FALSE,pforce); */ /* Initialize QM-MM */ if (fr->bQMMM) { init_QMMMrec(cr, mtop, inputrec, fr); } /* Initialize the mdatoms structure. * mdatoms is not filled with atom data, * as this can not be done now with domain decomposition. */ mdatoms = init_mdatoms(fplog, mtop, inputrec->efep != efepNO); /* Initialize the virtual site communication */ vsite = init_vsite(mtop, cr, FALSE); calc_shifts(box, fr->shift_vec); /* With periodic molecules the charge groups should be whole at start up * and the virtual sites should not be far from their proper positions. */ if (!inputrec->bContinuation && MASTER(cr) && !(inputrec->ePBC != epbcNONE && inputrec->bPeriodicMols)) { /* Make molecules whole at start of run */ if (fr->ePBC != epbcNONE) { do_pbc_first_mtop(fplog, inputrec->ePBC, box, mtop, state->x); } if (vsite) { /* Correct initial vsite positions are required * for the initial distribution in the domain decomposition * and for the initial shell prediction. */ construct_vsites_mtop(vsite, mtop, state->x); } } if (EEL_PME(fr->eeltype) || EVDW_PME(fr->vdwtype)) { ewaldcoeff_q = fr->ewaldcoeff_q; ewaldcoeff_lj = fr->ewaldcoeff_lj; pmedata = &fr->pmedata; } else { pmedata = NULL; } } else { /* This is a PME only node */ /* We don't need the state */ done_state(state); ewaldcoeff_q = calc_ewaldcoeff_q(inputrec->rcoulomb, inputrec->ewald_rtol); ewaldcoeff_lj = calc_ewaldcoeff_lj(inputrec->rvdw, inputrec->ewald_rtol_lj); snew(pmedata, 1); } if (hw_opt->thread_affinity != threadaffOFF) { /* Before setting affinity, check whether the affinity has changed * - which indicates that probably the OpenMP library has changed it * since we first checked). */ gmx_check_thread_affinity_set(fplog, cr, hw_opt, hwinfo->nthreads_hw_avail, TRUE); /* Set the CPU affinity */ gmx_set_thread_affinity(fplog, cr, hw_opt, hwinfo); } /* Initiate PME if necessary, * either on all nodes or on dedicated PME nodes only. */ if (EEL_PME(inputrec->coulombtype) || EVDW_PME(inputrec->vdwtype)) { if (mdatoms) { nChargePerturbed = mdatoms->nChargePerturbed; if (EVDW_PME(inputrec->vdwtype)) { nTypePerturbed = mdatoms->nTypePerturbed; } } if (cr->npmenodes > 0) { /* The PME only nodes need to know nChargePerturbed(FEP on Q) and nTypePerturbed(FEP on LJ)*/ gmx_bcast_sim(sizeof(nChargePerturbed), &nChargePerturbed, cr); gmx_bcast_sim(sizeof(nTypePerturbed), &nTypePerturbed, cr); } if (cr->duty & DUTY_PME) { status = gmx_pme_init(pmedata, cr, npme_major, npme_minor, inputrec, mtop ? mtop->natoms : 0, nChargePerturbed, nTypePerturbed, (Flags & MD_REPRODUCIBLE), nthreads_pme); if (status != 0) { gmx_fatal(FARGS, "Error %d initializing PME", status); } } } if (integrator[inputrec->eI].func == do_md) { /* Turn on signal handling on all nodes */ /* * (A user signal from the PME nodes (if any) * is communicated to the PP nodes. */ signal_handler_install(); } if (cr->duty & DUTY_PP) { /* Assumes uniform use of the number of OpenMP threads */ walltime_accounting = walltime_accounting_init(gmx_omp_nthreads_get(emntDefault)); if (inputrec->bPull) { /* Initialize pull code */ inputrec->pull_work = init_pull(fplog, inputrec->pull, inputrec, nfile, fnm, mtop, cr, oenv, inputrec->fepvals->init_lambda, EI_DYNAMICS(inputrec->eI) && MASTER(cr), Flags); } if (inputrec->bRot) { /* Initialize enforced rotation code */ init_rot(fplog, inputrec, nfile, fnm, cr, state->x, box, mtop, oenv, bVerbose, Flags); } if (inputrec->eSwapCoords != eswapNO) { /* Initialize ion swapping code */ init_swapcoords(fplog, bVerbose, inputrec, opt2fn_master("-swap", nfile, fnm, cr), mtop, state->x, state->box, &state->swapstate, cr, oenv, Flags); } constr = init_constraints(fplog, mtop, inputrec, ed, state, cr); if (DOMAINDECOMP(cr)) { GMX_RELEASE_ASSERT(fr, "fr was NULL while cr->duty was DUTY_PP"); dd_init_bondeds(fplog, cr->dd, mtop, vsite, inputrec, Flags & MD_DDBONDCHECK, fr->cginfo_mb); set_dd_parameters(fplog, cr->dd, dlb_scale, inputrec, &ddbox); setup_dd_grid(fplog, cr->dd); } /* Now do whatever the user wants us to do (how flexible...) */ integrator[inputrec->eI].func(fplog, cr, nfile, fnm, oenv, bVerbose, bCompact, nstglobalcomm, vsite, constr, nstepout, inputrec, mtop, fcd, state, mdatoms, nrnb, wcycle, ed, fr, repl_ex_nst, repl_ex_nex, repl_ex_seed, membed, cpt_period, max_hours, imdport, Flags, walltime_accounting); if (inputrec->bPull) { finish_pull(inputrec->pull_work); } if (inputrec->bRot) { finish_rot(inputrec->rot); } } else { GMX_RELEASE_ASSERT(pmedata, "pmedata was NULL while cr->duty was not DUTY_PP"); /* do PME only */ walltime_accounting = walltime_accounting_init(gmx_omp_nthreads_get(emntPME)); gmx_pmeonly(*pmedata, cr, nrnb, wcycle, walltime_accounting, ewaldcoeff_q, ewaldcoeff_lj, inputrec); } wallcycle_stop(wcycle, ewcRUN); /* Finish up, write some stuff * if rerunMD, don't write last frame again */ finish_run(fplog, cr, inputrec, nrnb, wcycle, walltime_accounting, fr ? fr->nbv : NULL, EI_DYNAMICS(inputrec->eI) && !MULTISIM(cr)); /* Free GPU memory and context */ free_gpu_resources(fr, cr, &hwinfo->gpu_info, fr ? fr->gpu_opt : NULL); if (opt2bSet("-membed", nfile, fnm)) { sfree(membed); } gmx_hardware_info_free(hwinfo); /* Does what it says */ print_date_and_time(fplog, cr->nodeid, "Finished mdrun", gmx_gettime()); walltime_accounting_destroy(walltime_accounting); /* PLUMED */ if(plumedswitch){ plumed_finalize(plumedmain); } /* END PLUMED */ /* Close logfile already here if we were appending to it */ if (MASTER(cr) && (Flags & MD_APPENDFILES)) { gmx_log_close(fplog); } rc = (int)gmx_get_stop_condition(); done_ed(&ed); #ifdef GMX_THREAD_MPI /* we need to join all threads. The sub-threads join when they exit this function, but the master thread needs to be told to wait for that. */ if (PAR(cr) && MASTER(cr)) { tMPI_Finalize(); } #endif return rc; }
static void set_state_entries(t_state *state,t_inputrec *ir,int nnodes) { /* The entries in the state in the tpx file might not correspond * with what is needed, so we correct this here. */ state->flags = 0; if (ir->efep != efepNO) state->flags |= (1<<estLAMBDA); state->flags |= (1<<estX); if (state->x == NULL) snew(state->x,state->nalloc); if (EI_DYNAMICS(ir->eI)) { state->flags |= (1<<estV); if (state->v == NULL) snew(state->v,state->nalloc); } if (ir->eI == eiSD2) { state->flags |= (1<<estSDX); if (state->sd_X == NULL) { /* sd_X is not stored in the tpx file, so we need to allocate it */ snew(state->sd_X,state->nalloc); } } if (ir->eI == eiCG) { state->flags |= (1<<estCGP); } if (EI_SD(ir->eI) || ir->eI == eiBD || ir->etc == etcVRESCALE) { state->nrng = gmx_rng_n(); state->nrngi = 1; if (EI_SD(ir->eI) || ir->eI == eiBD) { /* This will be correct later with DD */ state->nrng *= nnodes; state->nrngi *= nnodes; } state->flags |= ((1<<estLD_RNG) | (1<<estLD_RNGI)); snew(state->ld_rng, state->nrng); snew(state->ld_rngi,state->nrngi); } else { state->nrng = 0; } if (ir->ePBC != epbcNONE) { state->flags |= (1<<estBOX); if (PRESERVE_SHAPE(*ir)) { state->flags |= (1<<estBOX_REL); } if (ir->epc == epcPARRINELLORAHMAN) { state->flags |= (1<<estBOXV); } if (ir->epc != epcNO) { state->flags |= (1<<estPRES_PREV); } if (ir->etc == etcNOSEHOOVER) { state->flags |= (1<<estNH_XI); } } if (ir->etc == etcNOSEHOOVER || ir->etc == etcVRESCALE) { state->flags |= (1<<estTC_INT); } init_ekinstate(&state->ekinstate,ir); init_energyhistory(&state->enerhist); }
void init_disres(FILE *fplog, const gmx_mtop_t *mtop, t_inputrec *ir, const t_commrec *cr, t_fcdata *fcd, t_state *state, gmx_bool bIsREMD) { int fa, nmol, npair, np; t_disresdata *dd; history_t *hist; gmx_mtop_ilistloop_t iloop; t_ilist *il; char *ptr; dd = &(fcd->disres); if (gmx_mtop_ftype_count(mtop, F_DISRES) == 0) { dd->nres = 0; return; } if (fplog) { fprintf(fplog, "Initializing the distance restraints\n"); } if (ir->eDisre == edrEnsemble) { gmx_fatal(FARGS, "Sorry, distance restraints with ensemble averaging over multiple molecules in one system are not functional in this version of GROMACS"); } dd->dr_weighting = ir->eDisreWeighting; dd->dr_fc = ir->dr_fc; if (EI_DYNAMICS(ir->eI)) { dd->dr_tau = ir->dr_tau; } else { dd->dr_tau = 0.0; } if (dd->dr_tau == 0.0) { dd->dr_bMixed = FALSE; dd->ETerm = 0.0; } else { dd->dr_bMixed = ir->bDisreMixed; dd->ETerm = std::exp(-(ir->delta_t/ir->dr_tau)); } dd->ETerm1 = 1.0 - dd->ETerm; dd->nres = 0; dd->npair = 0; iloop = gmx_mtop_ilistloop_init(mtop); while (gmx_mtop_ilistloop_next(iloop, &il, &nmol)) { np = 0; for (fa = 0; fa < il[F_DISRES].nr; fa += 3) { np++; npair = mtop->ffparams.iparams[il[F_DISRES].iatoms[fa]].disres.npair; if (np == npair) { dd->nres += (ir->eDisre == edrEnsemble ? 1 : nmol)*npair; dd->npair += nmol*npair; np = 0; } } } if (cr && PAR(cr)) { /* Temporary check, will be removed when disre is implemented with DD */ const char *notestr = "NOTE: atoms involved in distance restraints should be within the same domain. If this is not the case mdrun generates a fatal error. If you encounter this, use a single MPI rank (Verlet+OpenMP+GPUs work fine)."; if (MASTER(cr)) { fprintf(stderr, "\n%s\n\n", notestr); } if (fplog) { fprintf(fplog, "%s\n", notestr); } if (dd->dr_tau != 0 || ir->eDisre == edrEnsemble || cr->ms != NULL || dd->nres != dd->npair) { gmx_fatal(FARGS, "Time or ensemble averaged or multiple pair distance restraints do not work (yet) with domain decomposition, use a single MPI rank%s", cr->ms ? " per simulation" : ""); } if (ir->nstdisreout != 0) { if (fplog) { fprintf(fplog, "\nWARNING: Can not write distance restraint data to energy file with domain decomposition\n\n"); } if (MASTER(cr)) { fprintf(stderr, "\nWARNING: Can not write distance restraint data to energy file with domain decomposition\n"); } ir->nstdisreout = 0; } } snew(dd->rt, dd->npair); if (dd->dr_tau != 0.0) { hist = &state->hist; /* Set the "history lack" factor to 1 */ state->flags |= (1<<estDISRE_INITF); hist->disre_initf = 1.0; /* Allocate space for the r^-3 time averages */ state->flags |= (1<<estDISRE_RM3TAV); hist->ndisrepairs = dd->npair; snew(hist->disre_rm3tav, hist->ndisrepairs); } /* Allocate space for a copy of rm3tav, * so we can call do_force without modifying the state. */ snew(dd->rm3tav, dd->npair); /* Allocate Rt_6 and Rtav_6 consecutively in memory so they can be * averaged over the processors in one call (in calc_disre_R_6) */ snew(dd->Rt_6, 2*dd->nres); dd->Rtav_6 = &(dd->Rt_6[dd->nres]); ptr = getenv("GMX_DISRE_ENSEMBLE_SIZE"); if (cr && cr->ms != NULL && ptr != NULL && !bIsREMD) { #ifdef GMX_MPI dd->nsystems = 0; sscanf(ptr, "%d", &dd->nsystems); if (fplog) { fprintf(fplog, "Found GMX_DISRE_ENSEMBLE_SIZE set to %d systems per ensemble\n", dd->nsystems); } /* This check is only valid on MASTER(cr), so probably * ensemble-averaged distance restraints are broken on more * than one processor per simulation system. */ if (MASTER(cr)) { check_multi_int(fplog, cr->ms, dd->nsystems, "the number of systems per ensemble", FALSE); } gmx_bcast_sim(sizeof(int), &dd->nsystems, cr); /* We use to allow any value of nsystems which was a divisor * of ms->nsim. But this required an extra communicator which * was stored in t_fcdata. This pulled in mpi.h in nearly all C files. */ if (!(cr->ms->nsim == 1 || cr->ms->nsim == dd->nsystems)) { gmx_fatal(FARGS, "GMX_DISRE_ENSEMBLE_SIZE (%d) is not equal to 1 or the number of systems (option -multi) %d", dd->nsystems, cr->ms->nsim); } if (fplog) { fprintf(fplog, "Our ensemble consists of systems:"); for (int i = 0; i < dd->nsystems; i++) { fprintf(fplog, " %d", (cr->ms->sim/dd->nsystems)*dd->nsystems+i); } fprintf(fplog, "\n"); } snew(dd->Rtl_6, dd->nres); #endif } else { dd->nsystems = 1; dd->Rtl_6 = dd->Rt_6; } if (dd->npair > 0) { if (fplog) { fprintf(fplog, "There are %d distance restraints involving %d atom pairs\n", dd->nres, dd->npair); } /* Have to avoid g_disre de-referencing cr blindly, mdrun not * doing consistency checks for ensemble-averaged distance * restraints when that's not happening, and only doing those * checks from appropriate processes (since check_multi_int is * too broken to check whether the communication will * succeed...) */ if (cr && cr->ms && dd->nsystems > 1 && MASTER(cr)) { check_multi_int(fplog, cr->ms, fcd->disres.nres, "the number of distance restraints", FALSE); } please_cite(fplog, "Tropp80a"); please_cite(fplog, "Torda89a"); } }
gmx_mdoutf_t init_mdoutf(FILE *fplog, int nfile, const t_filenm fnm[], int mdrun_flags, const t_commrec *cr, const t_inputrec *ir, gmx_mtop_t *top_global, const gmx_output_env_t *oenv, gmx_wallcycle_t wcycle) { gmx_mdoutf_t of; char filemode[3]; gmx_bool bAppendFiles, bCiteTng = FALSE; int i; snew(of, 1); of->fp_trn = NULL; of->fp_ene = NULL; of->fp_xtc = NULL; of->tng = NULL; of->tng_low_prec = NULL; of->fp_dhdl = NULL; of->fp_field = NULL; of->eIntegrator = ir->eI; of->bExpanded = ir->bExpanded; of->elamstats = ir->expandedvals->elamstats; of->simulation_part = ir->simulation_part; of->x_compression_precision = static_cast<int>(ir->x_compression_precision); of->wcycle = wcycle; if (MASTER(cr)) { bAppendFiles = (mdrun_flags & MD_APPENDFILES); of->bKeepAndNumCPT = (mdrun_flags & MD_KEEPANDNUMCPT); sprintf(filemode, bAppendFiles ? "a+" : "w+"); if ((EI_DYNAMICS(ir->eI) || EI_ENERGY_MINIMIZATION(ir->eI)) #ifndef GMX_FAHCORE && !(EI_DYNAMICS(ir->eI) && ir->nstxout == 0 && ir->nstvout == 0 && ir->nstfout == 0) #endif ) { const char *filename; filename = ftp2fn(efTRN, nfile, fnm); switch (fn2ftp(filename)) { case efTRR: case efTRN: of->fp_trn = gmx_trr_open(filename, filemode); break; case efTNG: gmx_tng_open(filename, filemode[0], &of->tng); if (filemode[0] == 'w') { gmx_tng_prepare_md_writing(of->tng, top_global, ir); } bCiteTng = TRUE; break; default: gmx_incons("Invalid full precision file format"); } } if (EI_DYNAMICS(ir->eI) && ir->nstxout_compressed > 0) { const char *filename; filename = ftp2fn(efCOMPRESSED, nfile, fnm); switch (fn2ftp(filename)) { case efXTC: of->fp_xtc = open_xtc(filename, filemode); break; case efTNG: gmx_tng_open(filename, filemode[0], &of->tng_low_prec); if (filemode[0] == 'w') { gmx_tng_prepare_low_prec_writing(of->tng_low_prec, top_global, ir); } bCiteTng = TRUE; break; default: gmx_incons("Invalid reduced precision file format"); } } if (EI_DYNAMICS(ir->eI) || EI_ENERGY_MINIMIZATION(ir->eI)) { of->fp_ene = open_enx(ftp2fn(efEDR, nfile, fnm), filemode); } of->fn_cpt = opt2fn("-cpo", nfile, fnm); if ((ir->efep != efepNO || ir->bSimTemp) && ir->fepvals->nstdhdl > 0 && (ir->fepvals->separate_dhdl_file == esepdhdlfileYES ) && EI_DYNAMICS(ir->eI)) { if (bAppendFiles) { of->fp_dhdl = gmx_fio_fopen(opt2fn("-dhdl", nfile, fnm), filemode); } else { of->fp_dhdl = open_dhdl(opt2fn("-dhdl", nfile, fnm), ir, oenv); } } if (opt2bSet("-field", nfile, fnm) && (ir->ex[XX].n || ir->ex[YY].n || ir->ex[ZZ].n)) { if (bAppendFiles) { of->fp_field = gmx_fio_fopen(opt2fn("-field", nfile, fnm), filemode); } else { of->fp_field = xvgropen(opt2fn("-field", nfile, fnm), "Applied electric field", "Time (ps)", "E (V/nm)", oenv); } } /* Set up atom counts so they can be passed to actual trajectory-writing routines later. Also, XTC writing needs to know what (and how many) atoms might be in the XTC groups, and how to look up later which ones they are. */ of->natoms_global = top_global->natoms; of->groups = &top_global->groups; of->natoms_x_compressed = 0; for (i = 0; (i < top_global->natoms); i++) { if (ggrpnr(of->groups, egcCompressedX, i) == 0) { of->natoms_x_compressed++; } } } if (bCiteTng) { please_cite(fplog, "Lundborg2014"); } return of; }
t_mdebin *init_mdebin(ener_file_t fp_ene, const gmx_mtop_t *mtop, const t_inputrec *ir, FILE *fp_dhdl) { const char *ener_nm[F_NRE]; static const char *vir_nm[] = { "Vir-XX", "Vir-XY", "Vir-XZ", "Vir-YX", "Vir-YY", "Vir-YZ", "Vir-ZX", "Vir-ZY", "Vir-ZZ" }; static const char *sv_nm[] = { "ShakeVir-XX", "ShakeVir-XY", "ShakeVir-XZ", "ShakeVir-YX", "ShakeVir-YY", "ShakeVir-YZ", "ShakeVir-ZX", "ShakeVir-ZY", "ShakeVir-ZZ" }; static const char *fv_nm[] = { "ForceVir-XX", "ForceVir-XY", "ForceVir-XZ", "ForceVir-YX", "ForceVir-YY", "ForceVir-YZ", "ForceVir-ZX", "ForceVir-ZY", "ForceVir-ZZ" }; static const char *pres_nm[] = { "Pres-XX","Pres-XY","Pres-XZ", "Pres-YX","Pres-YY","Pres-YZ", "Pres-ZX","Pres-ZY","Pres-ZZ" }; static const char *surft_nm[] = { "#Surf*SurfTen" }; static const char *mu_nm[] = { "Mu-X", "Mu-Y", "Mu-Z" }; static const char *vcos_nm[] = { "2CosZ*Vel-X" }; static const char *visc_nm[] = { "1/Viscosity" }; static const char *baro_nm[] = { "Barostat" }; char **grpnms; const gmx_groups_t *groups; char **gnm; char buf[256]; const char *bufi; t_mdebin *md; int i,j,ni,nj,n,nh,k,kk,ncon,nset; gmx_bool bBHAM,bNoseHoover,b14; snew(md,1); if (EI_DYNAMICS(ir->eI)) { md->delta_t = ir->delta_t; } else { md->delta_t = 0; } groups = &mtop->groups; bBHAM = (mtop->ffparams.functype[0] == F_BHAM); b14 = (gmx_mtop_ftype_count(mtop,F_LJ14) > 0 || gmx_mtop_ftype_count(mtop,F_LJC14_Q) > 0); ncon = gmx_mtop_ftype_count(mtop,F_CONSTR); nset = gmx_mtop_ftype_count(mtop,F_SETTLE); md->bConstr = (ncon > 0 || nset > 0); md->bConstrVir = FALSE; if (md->bConstr) { if (ncon > 0 && ir->eConstrAlg == econtLINCS) { if (ir->eI == eiSD2) md->nCrmsd = 2; else md->nCrmsd = 1; } md->bConstrVir = (getenv("GMX_CONSTRAINTVIR") != NULL); } else { md->nCrmsd = 0; } /* Energy monitoring */ for(i=0;i<egNR;i++) { md->bEInd[i]=FALSE; } #ifndef GMX_OPENMM for(i=0; i<F_NRE; i++) { md->bEner[i] = FALSE; if (i == F_LJ) md->bEner[i] = !bBHAM; else if (i == F_BHAM) md->bEner[i] = bBHAM; else if (i == F_EQM) md->bEner[i] = ir->bQMMM; else if (i == F_COUL_LR) md->bEner[i] = (ir->rcoulomb > ir->rlist); else if (i == F_LJ_LR) md->bEner[i] = (!bBHAM && ir->rvdw > ir->rlist); else if (i == F_BHAM_LR) md->bEner[i] = (bBHAM && ir->rvdw > ir->rlist); else if (i == F_RF_EXCL) md->bEner[i] = (EEL_RF(ir->coulombtype) && ir->coulombtype != eelRF_NEC); else if (i == F_COUL_RECIP) md->bEner[i] = EEL_FULL(ir->coulombtype); else if (i == F_LJ14) md->bEner[i] = b14; else if (i == F_COUL14) md->bEner[i] = b14; else if (i == F_LJC14_Q || i == F_LJC_PAIRS_NB) md->bEner[i] = FALSE; else if ((i == F_DVDL) || (i == F_DKDL)) md->bEner[i] = (ir->efep != efepNO); else if (i == F_DHDL_CON) md->bEner[i] = (ir->efep != efepNO && md->bConstr); else if ((interaction_function[i].flags & IF_VSITE) || (i == F_CONSTR) || (i == F_CONSTRNC) || (i == F_SETTLE)) md->bEner[i] = FALSE; else if ((i == F_COUL_SR) || (i == F_EPOT) || (i == F_PRES) || (i==F_EQM)) md->bEner[i] = TRUE; else if ((i == F_GBPOL) && ir->implicit_solvent==eisGBSA) md->bEner[i] = TRUE; else if ((i == F_NPSOLVATION) && ir->implicit_solvent==eisGBSA && (ir->sa_algorithm != esaNO)) md->bEner[i] = TRUE; else if ((i == F_GB12) || (i == F_GB13) || (i == F_GB14)) md->bEner[i] = FALSE; else if ((i == F_ETOT) || (i == F_EKIN) || (i == F_TEMP)) md->bEner[i] = EI_DYNAMICS(ir->eI); else if (i==F_VTEMP) md->bEner[i] = (EI_DYNAMICS(ir->eI) && getenv("GMX_VIRIAL_TEMPERATURE")); else if (i == F_DISPCORR || i == F_PDISPCORR) md->bEner[i] = (ir->eDispCorr != edispcNO); else if (i == F_DISRESVIOL) md->bEner[i] = (gmx_mtop_ftype_count(mtop,F_DISRES) > 0); else if (i == F_ORIRESDEV) md->bEner[i] = (gmx_mtop_ftype_count(mtop,F_ORIRES) > 0); else if (i == F_CONNBONDS) md->bEner[i] = FALSE; else if (i == F_COM_PULL) md->bEner[i] = (ir->ePull == epullUMBRELLA || ir->ePull == epullCONST_F); else if (i == F_ECONSERVED) md->bEner[i] = ((ir->etc == etcNOSEHOOVER || ir->etc == etcVRESCALE) && (ir->epc == epcNO || ir->epc==epcMTTK)); else md->bEner[i] = (gmx_mtop_ftype_count(mtop,i) > 0); } #else /* OpenMM always produces only the following 4 energy terms */ md->bEner[F_EPOT] = TRUE; md->bEner[F_EKIN] = TRUE; md->bEner[F_ETOT] = TRUE; md->bEner[F_TEMP] = TRUE; #endif md->f_nre=0; for(i=0; i<F_NRE; i++) { if (md->bEner[i]) { /* FIXME: The constness should not be cast away */ /*ener_nm[f_nre]=(char *)interaction_function[i].longname;*/ ener_nm[md->f_nre]=interaction_function[i].longname; md->f_nre++; } } md->epc = ir->epc; for (i=0;i<DIM;i++) { for (j=0;j<DIM;j++) { md->ref_p[i][j] = ir->ref_p[i][j]; } } md->bTricl = TRICLINIC(ir->compress) || TRICLINIC(ir->deform); md->bDynBox = DYNAMIC_BOX(*ir); md->etc = ir->etc; md->bNHC_trotter = IR_NVT_TROTTER(ir); md->bMTTK = IR_NPT_TROTTER(ir); md->ebin = mk_ebin(); /* Pass NULL for unit to let get_ebin_space determine the units * for interaction_function[i].longname */ md->ie = get_ebin_space(md->ebin,md->f_nre,ener_nm,NULL); if (md->nCrmsd) { /* This should be called directly after the call for md->ie, * such that md->iconrmsd follows directly in the list. */ md->iconrmsd = get_ebin_space(md->ebin,md->nCrmsd,conrmsd_nm,""); } if (md->bDynBox) { md->ib = get_ebin_space(md->ebin, md->bTricl ? NTRICLBOXS : NBOXS, md->bTricl ? tricl_boxs_nm : boxs_nm, unit_length); md->ivol = get_ebin_space(md->ebin, 1, vol_nm, unit_volume); md->idens = get_ebin_space(md->ebin, 1, dens_nm, unit_density_SI); md->ipv = get_ebin_space(md->ebin, 1, pv_nm, unit_energy); md->ienthalpy = get_ebin_space(md->ebin, 1, enthalpy_nm, unit_energy); } if (md->bConstrVir) { md->isvir = get_ebin_space(md->ebin,asize(sv_nm),sv_nm,unit_energy); md->ifvir = get_ebin_space(md->ebin,asize(fv_nm),fv_nm,unit_energy); } md->ivir = get_ebin_space(md->ebin,asize(vir_nm),vir_nm,unit_energy); md->ipres = get_ebin_space(md->ebin,asize(pres_nm),pres_nm,unit_pres_bar); md->isurft = get_ebin_space(md->ebin,asize(surft_nm),surft_nm, unit_surft_bar); if (md->epc == epcPARRINELLORAHMAN || md->epc == epcMTTK) { md->ipc = get_ebin_space(md->ebin,md->bTricl ? 6 : 3, boxvel_nm,unit_vel); } md->imu = get_ebin_space(md->ebin,asize(mu_nm),mu_nm,unit_dipole_D); if (ir->cos_accel != 0) { md->ivcos = get_ebin_space(md->ebin,asize(vcos_nm),vcos_nm,unit_vel); md->ivisc = get_ebin_space(md->ebin,asize(visc_nm),visc_nm, unit_invvisc_SI); } /* Energy monitoring */ for(i=0;i<egNR;i++) { md->bEInd[i] = FALSE; } md->bEInd[egCOULSR] = TRUE; md->bEInd[egLJSR ] = TRUE; if (ir->rcoulomb > ir->rlist) { md->bEInd[egCOULLR] = TRUE; } if (!bBHAM) { if (ir->rvdw > ir->rlist) { md->bEInd[egLJLR] = TRUE; } } else { md->bEInd[egLJSR] = FALSE; md->bEInd[egBHAMSR] = TRUE; if (ir->rvdw > ir->rlist) { md->bEInd[egBHAMLR] = TRUE; } } if (b14) { md->bEInd[egLJ14] = TRUE; md->bEInd[egCOUL14] = TRUE; } md->nEc=0; for(i=0; (i<egNR); i++) { if (md->bEInd[i]) { md->nEc++; } } n=groups->grps[egcENER].nr; md->nEg=n; md->nE=(n*(n+1))/2; snew(md->igrp,md->nE); if (md->nE > 1) { n=0; snew(gnm,md->nEc); for(k=0; (k<md->nEc); k++) { snew(gnm[k],STRLEN); } for(i=0; (i<groups->grps[egcENER].nr); i++) { ni=groups->grps[egcENER].nm_ind[i]; for(j=i; (j<groups->grps[egcENER].nr); j++) { nj=groups->grps[egcENER].nm_ind[j]; for(k=kk=0; (k<egNR); k++) { if (md->bEInd[k]) { sprintf(gnm[kk],"%s:%s-%s",egrp_nm[k], *(groups->grpname[ni]),*(groups->grpname[nj])); kk++; } } md->igrp[n]=get_ebin_space(md->ebin,md->nEc, (const char **)gnm,unit_energy); n++; } } for(k=0; (k<md->nEc); k++) { sfree(gnm[k]); } sfree(gnm); if (n != md->nE) { gmx_incons("Number of energy terms wrong"); } } md->nTC=groups->grps[egcTC].nr; md->nNHC = ir->opts.nhchainlength; /* shorthand for number of NH chains */ if (md->bMTTK) { md->nTCP = 1; /* assume only one possible coupling system for barostat for now */ } else { md->nTCP = 0; } if (md->etc == etcNOSEHOOVER) { if (md->bNHC_trotter) { md->mde_n = 2*md->nNHC*md->nTC; } else { md->mde_n = 2*md->nTC; } if (md->epc == epcMTTK) { md->mdeb_n = 2*md->nNHC*md->nTCP; } } else { md->mde_n = md->nTC; md->mdeb_n = 0; } snew(md->tmp_r,md->mde_n); snew(md->tmp_v,md->mde_n); snew(md->grpnms,md->mde_n); grpnms = md->grpnms; for(i=0; (i<md->nTC); i++) { ni=groups->grps[egcTC].nm_ind[i]; sprintf(buf,"T-%s",*(groups->grpname[ni])); grpnms[i]=strdup(buf); } md->itemp=get_ebin_space(md->ebin,md->nTC,(const char **)grpnms, unit_temp_K); bNoseHoover = (getenv("GMX_NOSEHOOVER_CHAINS") != NULL); /* whether to print Nose-Hoover chains */ if (md->etc == etcNOSEHOOVER) { if (bNoseHoover) { if (md->bNHC_trotter) { for(i=0; (i<md->nTC); i++) { ni=groups->grps[egcTC].nm_ind[i]; bufi = *(groups->grpname[ni]); for(j=0; (j<md->nNHC); j++) { sprintf(buf,"Xi-%d-%s",j,bufi); grpnms[2*(i*md->nNHC+j)]=strdup(buf); sprintf(buf,"vXi-%d-%s",j,bufi); grpnms[2*(i*md->nNHC+j)+1]=strdup(buf); } } md->itc=get_ebin_space(md->ebin,md->mde_n, (const char **)grpnms,unit_invtime); if (md->bMTTK) { for(i=0; (i<md->nTCP); i++) { bufi = baro_nm[0]; /* All barostat DOF's together for now. */ for(j=0; (j<md->nNHC); j++) { sprintf(buf,"Xi-%d-%s",j,bufi); grpnms[2*(i*md->nNHC+j)]=strdup(buf); sprintf(buf,"vXi-%d-%s",j,bufi); grpnms[2*(i*md->nNHC+j)+1]=strdup(buf); } } md->itcb=get_ebin_space(md->ebin,md->mdeb_n, (const char **)grpnms,unit_invtime); } } else { for(i=0; (i<md->nTC); i++) { ni=groups->grps[egcTC].nm_ind[i]; bufi = *(groups->grpname[ni]); sprintf(buf,"Xi-%s",bufi); grpnms[2*i]=strdup(buf); sprintf(buf,"vXi-%s",bufi); grpnms[2*i+1]=strdup(buf); } md->itc=get_ebin_space(md->ebin,md->mde_n, (const char **)grpnms,unit_invtime); } } } else if (md->etc == etcBERENDSEN || md->etc == etcYES || md->etc == etcVRESCALE) { for(i=0; (i<md->nTC); i++) { ni=groups->grps[egcTC].nm_ind[i]; sprintf(buf,"Lamb-%s",*(groups->grpname[ni])); grpnms[i]=strdup(buf); } md->itc=get_ebin_space(md->ebin,md->mde_n,(const char **)grpnms,""); } sfree(grpnms); md->nU=groups->grps[egcACC].nr; if (md->nU > 1) { snew(grpnms,3*md->nU); for(i=0; (i<md->nU); i++) { ni=groups->grps[egcACC].nm_ind[i]; sprintf(buf,"Ux-%s",*(groups->grpname[ni])); grpnms[3*i+XX]=strdup(buf); sprintf(buf,"Uy-%s",*(groups->grpname[ni])); grpnms[3*i+YY]=strdup(buf); sprintf(buf,"Uz-%s",*(groups->grpname[ni])); grpnms[3*i+ZZ]=strdup(buf); } md->iu=get_ebin_space(md->ebin,3*md->nU,(const char **)grpnms,unit_vel); sfree(grpnms); } if ( fp_ene ) { do_enxnms(fp_ene,&md->ebin->nener,&md->ebin->enm); } md->print_grpnms=NULL; /* check whether we're going to write dh histograms */ md->dhc=NULL; if (ir->separate_dhdl_file == sepdhdlfileNO ) { int i; snew(md->dhc, 1); mde_delta_h_coll_init(md->dhc, ir); md->fp_dhdl = NULL; } else { md->fp_dhdl = fp_dhdl; } md->dhdl_derivatives = (ir->dhdl_derivatives==dhdlderivativesYES); return md; }
bool constrain(FILE *fplog,bool bLog,bool bEner, struct gmx_constr *constr, t_idef *idef,t_inputrec *ir, t_commrec *cr, gmx_step_t step,int delta_step, t_mdatoms *md, rvec *x,rvec *xprime,rvec *min_proj,matrix box, real lambda,real *dvdlambda, rvec *v,tensor *vir, t_nrnb *nrnb,int econq) { bool bOK; int start,homenr; int i,j; int ncons,error; tensor rmdr; real invdt,vir_fac,t; t_ilist *settle; int nsettle; t_pbc pbc; char buf[22]; if (econq == econqForceDispl && !EI_ENERGY_MINIMIZATION(ir->eI)) { gmx_incons("constrain called for forces displacements while not doing energy minimization, can not do this while the LINCS and SETTLE constraint connection matrices are mass weighted"); } bOK = TRUE; start = md->start; homenr = md->homenr; if (ir->delta_t == 0) { invdt = 0; } else { invdt = 1/ir->delta_t; } if (ir->efep != efepNO && EI_DYNAMICS(ir->eI)) { /* Set the constraint lengths for the step at which this configuration * is meant to be. The invmasses should not be changed. */ lambda += delta_step*ir->delta_lambda; } if (vir != NULL) { clear_mat(rmdr); } where(); if (constr->lincsd) { bOK = constrain_lincs(fplog,bLog,bEner,ir,step,constr->lincsd,md,cr, x,xprime,min_proj,box,lambda,dvdlambda, invdt,v,vir!=NULL,rmdr, econq,nrnb, constr->maxwarn,&constr->warncount_lincs); if (!bOK && constr->maxwarn >= 0 && fplog) { fprintf(fplog,"Constraint error in algorithm %s at step %s\n", econstr_names[econtLINCS],gmx_step_str(step,buf)); } } if (constr->nblocks > 0) { if (econq != econqCoord) { gmx_fatal(FARGS,"Internal error, SHAKE called for constraining something else than coordinates"); } bOK = bshakef(fplog,constr->shaked, homenr,md->invmass,constr->nblocks,constr->sblock, idef,ir,box,x,xprime,nrnb, constr->lagr,lambda,dvdlambda, invdt,v,vir!=NULL,rmdr,constr->maxwarn>=0); if (!bOK && constr->maxwarn >= 0 && fplog) { fprintf(fplog,"Constraint error in algorithm %s at step %s\n", econstr_names[econtSHAKE],gmx_step_str(step,buf)); } } settle = &idef->il[F_SETTLE]; if (settle->nr > 0) { nsettle = settle->nr/2; switch (econq) { case econqCoord: csettle(constr->settled, nsettle,settle->iatoms,x[0],xprime[0], invdt,v[0],vir!=NULL,rmdr,&error); inc_nrnb(nrnb,eNR_SETTLE,nsettle); if (v != NULL) { inc_nrnb(nrnb,eNR_CONSTR_V,nsettle*3); } if (vir != NULL) { inc_nrnb(nrnb,eNR_CONSTR_VIR,nsettle*3); } bOK = (error < 0); if (!bOK && constr->maxwarn >= 0) { char buf[256]; sprintf(buf, "\nt = %.3f ps: Water molecule starting at atom %d can not be " "settled.\nCheck for bad contacts and/or reduce the timestep.\n", ir->init_t+step*ir->delta_t, ddglatnr(cr->dd,settle->iatoms[error*2+1])); if (fplog) { fprintf(fplog,"%s",buf); } fprintf(stderr,"%s",buf); constr->warncount_settle++; if (constr->warncount_settle > constr->maxwarn) { too_many_constraint_warnings(-1,constr->warncount_settle); } break; case econqVeloc: case econqDeriv: case econqForce: case econqForceDispl: settle_proj(fplog,constr->settled,econq, nsettle,settle->iatoms,x, xprime,min_proj,vir!=NULL,rmdr); /* This is an overestimate */ inc_nrnb(nrnb,eNR_SETTLE,nsettle); break; case econqDeriv_FlexCon: /* Nothing to do, since the are no flexible constraints in settles */ break; default: gmx_incons("Unknown constraint quantity for settle"); } } } if (vir != NULL) { switch (econq) { case econqCoord: vir_fac = 0.5/(ir->delta_t*ir->delta_t); break; case econqVeloc: /* Assume that these are velocities */ vir_fac = 0.5/ir->delta_t; break; case econqForce: case econqForceDispl: vir_fac = 0.5; break; default: vir_fac = 0; gmx_incons("Unsupported constraint quantity for virial"); } for(i=0; i<DIM; i++) { for(j=0; j<DIM; j++) { (*vir)[i][j] = vir_fac*rmdr[i][j]; } } } if (!bOK && constr->maxwarn >= 0) { dump_confs(fplog,step,constr->warn_mtop,start,homenr,cr,x,xprime,box); } if (econq == econqCoord) { if (ir->ePull == epullCONSTRAINT) { if (EI_DYNAMICS(ir->eI)) { t = ir->init_t + (step + delta_step)*ir->delta_t; } else { t = ir->init_t; } set_pbc(&pbc,ir->ePBC,box); pull_constraint(ir->pull,md,&pbc,cr,ir->delta_t,t,x,xprime,v,*vir); } if (constr->ed && delta_step > 0) { /* apply the essential dynamcs constraints here */ do_edsam(ir,step,md,cr,xprime,v,box,constr->ed); } } return bOK; }
void finish_run(FILE *fplog,t_commrec *cr,char *confout, t_inputrec *inputrec, t_nrnb nrnb[],gmx_wallcycle_t wcycle, double nodetime,double realtime,int nsteps_done, bool bWriteStat) { int i,j; t_nrnb *nrnb_all=NULL,ntot; real delta_t; double nbfs,mflop; double cycles[ewcNR]; #ifdef GMX_MPI int sender; double nrnb_buf[4]; MPI_Status status; #endif wallcycle_sum(cr,wcycle,cycles); if (cr->nnodes > 1) { if (SIMMASTER(cr)) snew(nrnb_all,cr->nnodes); #ifdef GMX_MPI MPI_Gather(nrnb,sizeof(t_nrnb),MPI_BYTE, nrnb_all,sizeof(t_nrnb),MPI_BYTE, 0,cr->mpi_comm_mysim); #endif } else { nrnb_all = nrnb; } if (SIMMASTER(cr)) { for(i=0; (i<eNRNB); i++) ntot.n[i]=0; for(i=0; (i<cr->nnodes); i++) for(j=0; (j<eNRNB); j++) ntot.n[j] += nrnb_all[i].n[j]; print_flop(fplog,&ntot,&nbfs,&mflop); if (nrnb_all) { sfree(nrnb_all); } } if ((cr->duty & DUTY_PP) && DOMAINDECOMP(cr)) { print_dd_statistics(cr,inputrec,fplog); } if (SIMMASTER(cr)) { if (PARTDECOMP(cr)) { pr_load(fplog,cr,nrnb_all); } wallcycle_print(fplog,cr->nnodes,cr->npmenodes,realtime,wcycle,cycles); if (EI_DYNAMICS(inputrec->eI)) { delta_t = inputrec->delta_t; } else { delta_t = 0; } if (fplog) { print_perf(fplog,nodetime,realtime,cr->nnodes-cr->npmenodes, nsteps_done,delta_t,nbfs,mflop); } if (bWriteStat) { print_perf(stderr,nodetime,realtime,cr->nnodes-cr->npmenodes, nsteps_done,delta_t,nbfs,mflop); } /* runtime=inputrec->nsteps*inputrec->delta_t; if (bWriteStat) { if (cr->nnodes == 1) fprintf(stderr,"\n\n"); print_perf(stderr,nodetime,realtime,runtime,&ntot, cr->nnodes-cr->npmenodes,FALSE); } wallcycle_print(fplog,cr->nnodes,cr->npmenodes,realtime,wcycle,cycles); print_perf(fplog,nodetime,realtime,runtime,&ntot,cr->nnodes-cr->npmenodes, TRUE); if (PARTDECOMP(cr)) pr_load(fplog,cr,nrnb_all); if (cr->nnodes > 1) sfree(nrnb_all); */ } }
t_mdebin *init_mdebin(ener_file_t fp_ene, const gmx_mtop_t *mtop, const t_inputrec *ir, FILE *fp_dhdl) { const char *ener_nm[F_NRE]; static const char *vir_nm[] = { "Vir-XX", "Vir-XY", "Vir-XZ", "Vir-YX", "Vir-YY", "Vir-YZ", "Vir-ZX", "Vir-ZY", "Vir-ZZ" }; static const char *sv_nm[] = { "ShakeVir-XX", "ShakeVir-XY", "ShakeVir-XZ", "ShakeVir-YX", "ShakeVir-YY", "ShakeVir-YZ", "ShakeVir-ZX", "ShakeVir-ZY", "ShakeVir-ZZ" }; static const char *fv_nm[] = { "ForceVir-XX", "ForceVir-XY", "ForceVir-XZ", "ForceVir-YX", "ForceVir-YY", "ForceVir-YZ", "ForceVir-ZX", "ForceVir-ZY", "ForceVir-ZZ" }; static const char *pres_nm[] = { "Pres-XX", "Pres-XY", "Pres-XZ", "Pres-YX", "Pres-YY", "Pres-YZ", "Pres-ZX", "Pres-ZY", "Pres-ZZ" }; static const char *surft_nm[] = { "#Surf*SurfTen" }; static const char *mu_nm[] = { "Mu-X", "Mu-Y", "Mu-Z" }; static const char *vcos_nm[] = { "2CosZ*Vel-X" }; static const char *visc_nm[] = { "1/Viscosity" }; static const char *baro_nm[] = { "Barostat" }; char **grpnms; const gmx_groups_t *groups; char **gnm; char buf[256]; const char *bufi; t_mdebin *md; int i, j, ni, nj, n, k, kk, ncon, nset; gmx_bool bBHAM, b14; snew(md, 1); if (EI_DYNAMICS(ir->eI)) { md->delta_t = ir->delta_t; } else { md->delta_t = 0; } groups = &mtop->groups; bBHAM = (mtop->ffparams.functype[0] == F_BHAM); b14 = (gmx_mtop_ftype_count(mtop, F_LJ14) > 0 || gmx_mtop_ftype_count(mtop, F_LJC14_Q) > 0); ncon = gmx_mtop_ftype_count(mtop, F_CONSTR); nset = gmx_mtop_ftype_count(mtop, F_SETTLE); md->bConstr = (ncon > 0 || nset > 0); md->bConstrVir = FALSE; if (md->bConstr) { if (ncon > 0 && ir->eConstrAlg == econtLINCS) { md->nCrmsd = 1; } md->bConstrVir = (getenv("GMX_CONSTRAINTVIR") != NULL); } else { md->nCrmsd = 0; } /* Energy monitoring */ for (i = 0; i < egNR; i++) { md->bEInd[i] = FALSE; } for (i = 0; i < F_NRE; i++) { md->bEner[i] = FALSE; if (i == F_LJ) { md->bEner[i] = !bBHAM; } else if (i == F_BHAM) { md->bEner[i] = bBHAM; } else if (i == F_EQM) { md->bEner[i] = ir->bQMMM; } else if (i == F_RF_EXCL) { md->bEner[i] = (EEL_RF(ir->coulombtype) && ir->cutoff_scheme == ecutsGROUP); } else if (i == F_COUL_RECIP) { md->bEner[i] = EEL_FULL(ir->coulombtype); } else if (i == F_LJ_RECIP) { md->bEner[i] = EVDW_PME(ir->vdwtype); } else if (i == F_LJ14) { md->bEner[i] = b14; } else if (i == F_COUL14) { md->bEner[i] = b14; } else if (i == F_LJC14_Q || i == F_LJC_PAIRS_NB) { md->bEner[i] = FALSE; } else if ((i == F_DVDL_COUL && ir->fepvals->separate_dvdl[efptCOUL]) || (i == F_DVDL_VDW && ir->fepvals->separate_dvdl[efptVDW]) || (i == F_DVDL_BONDED && ir->fepvals->separate_dvdl[efptBONDED]) || (i == F_DVDL_RESTRAINT && ir->fepvals->separate_dvdl[efptRESTRAINT]) || (i == F_DKDL && ir->fepvals->separate_dvdl[efptMASS]) || (i == F_DVDL && ir->fepvals->separate_dvdl[efptFEP])) { md->bEner[i] = (ir->efep != efepNO); } else if ((interaction_function[i].flags & IF_VSITE) || (i == F_CONSTR) || (i == F_CONSTRNC) || (i == F_SETTLE)) { md->bEner[i] = FALSE; } else if ((i == F_COUL_SR) || (i == F_EPOT) || (i == F_PRES) || (i == F_EQM)) { md->bEner[i] = TRUE; } else if ((i == F_GBPOL) && ir->implicit_solvent == eisGBSA) { md->bEner[i] = TRUE; } else if ((i == F_NPSOLVATION) && ir->implicit_solvent == eisGBSA && (ir->sa_algorithm != esaNO)) { md->bEner[i] = TRUE; } else if ((i == F_GB12) || (i == F_GB13) || (i == F_GB14)) { md->bEner[i] = FALSE; } else if ((i == F_ETOT) || (i == F_EKIN) || (i == F_TEMP)) { md->bEner[i] = EI_DYNAMICS(ir->eI); } else if (i == F_DISPCORR || i == F_PDISPCORR) { md->bEner[i] = (ir->eDispCorr != edispcNO); } else if (i == F_DISRESVIOL) { md->bEner[i] = (gmx_mtop_ftype_count(mtop, F_DISRES) > 0); } else if (i == F_ORIRESDEV) { md->bEner[i] = (gmx_mtop_ftype_count(mtop, F_ORIRES) > 0); } else if (i == F_CONNBONDS) { md->bEner[i] = FALSE; } else if (i == F_COM_PULL) { md->bEner[i] = (ir->bPull && pull_have_potential(ir->pull_work)); } else if (i == F_ECONSERVED) { md->bEner[i] = ((ir->etc == etcNOSEHOOVER || ir->etc == etcVRESCALE) && (ir->epc == epcNO || ir->epc == epcMTTK)); } else { md->bEner[i] = (gmx_mtop_ftype_count(mtop, i) > 0); } } md->f_nre = 0; for (i = 0; i < F_NRE; i++) { if (md->bEner[i]) { ener_nm[md->f_nre] = interaction_function[i].longname; md->f_nre++; } } md->epc = ir->epc; md->bDiagPres = !TRICLINIC(ir->ref_p); md->ref_p = (ir->ref_p[XX][XX]+ir->ref_p[YY][YY]+ir->ref_p[ZZ][ZZ])/DIM; md->bTricl = TRICLINIC(ir->compress) || TRICLINIC(ir->deform); md->bDynBox = inputrecDynamicBox(ir); md->etc = ir->etc; md->bNHC_trotter = inputrecNvtTrotter(ir); md->bPrintNHChains = ir->bPrintNHChains; md->bMTTK = (inputrecNptTrotter(ir) || inputrecNphTrotter(ir)); md->bMu = inputrecNeedMutot(ir); md->ebin = mk_ebin(); /* Pass NULL for unit to let get_ebin_space determine the units * for interaction_function[i].longname */ md->ie = get_ebin_space(md->ebin, md->f_nre, ener_nm, NULL); if (md->nCrmsd) { /* This should be called directly after the call for md->ie, * such that md->iconrmsd follows directly in the list. */ md->iconrmsd = get_ebin_space(md->ebin, md->nCrmsd, conrmsd_nm, ""); } if (md->bDynBox) { md->ib = get_ebin_space(md->ebin, md->bTricl ? NTRICLBOXS : NBOXS, md->bTricl ? tricl_boxs_nm : boxs_nm, unit_length); md->ivol = get_ebin_space(md->ebin, 1, vol_nm, unit_volume); md->idens = get_ebin_space(md->ebin, 1, dens_nm, unit_density_SI); if (md->bDiagPres) { md->ipv = get_ebin_space(md->ebin, 1, pv_nm, unit_energy); md->ienthalpy = get_ebin_space(md->ebin, 1, enthalpy_nm, unit_energy); } } if (md->bConstrVir) { md->isvir = get_ebin_space(md->ebin, asize(sv_nm), sv_nm, unit_energy); md->ifvir = get_ebin_space(md->ebin, asize(fv_nm), fv_nm, unit_energy); } md->ivir = get_ebin_space(md->ebin, asize(vir_nm), vir_nm, unit_energy); md->ipres = get_ebin_space(md->ebin, asize(pres_nm), pres_nm, unit_pres_bar); md->isurft = get_ebin_space(md->ebin, asize(surft_nm), surft_nm, unit_surft_bar); if (md->epc == epcPARRINELLORAHMAN || md->epc == epcMTTK) { md->ipc = get_ebin_space(md->ebin, md->bTricl ? 6 : 3, boxvel_nm, unit_vel); } if (md->bMu) { md->imu = get_ebin_space(md->ebin, asize(mu_nm), mu_nm, unit_dipole_D); } if (ir->cos_accel != 0) { md->ivcos = get_ebin_space(md->ebin, asize(vcos_nm), vcos_nm, unit_vel); md->ivisc = get_ebin_space(md->ebin, asize(visc_nm), visc_nm, unit_invvisc_SI); } /* Energy monitoring */ for (i = 0; i < egNR; i++) { md->bEInd[i] = FALSE; } md->bEInd[egCOULSR] = TRUE; md->bEInd[egLJSR ] = TRUE; if (bBHAM) { md->bEInd[egLJSR] = FALSE; md->bEInd[egBHAMSR] = TRUE; } if (b14) { md->bEInd[egLJ14] = TRUE; md->bEInd[egCOUL14] = TRUE; } md->nEc = 0; for (i = 0; (i < egNR); i++) { if (md->bEInd[i]) { md->nEc++; } } n = groups->grps[egcENER].nr; md->nEg = n; md->nE = (n*(n+1))/2; snew(md->igrp, md->nE); if (md->nE > 1) { n = 0; snew(gnm, md->nEc); for (k = 0; (k < md->nEc); k++) { snew(gnm[k], STRLEN); } for (i = 0; (i < groups->grps[egcENER].nr); i++) { ni = groups->grps[egcENER].nm_ind[i]; for (j = i; (j < groups->grps[egcENER].nr); j++) { nj = groups->grps[egcENER].nm_ind[j]; for (k = kk = 0; (k < egNR); k++) { if (md->bEInd[k]) { sprintf(gnm[kk], "%s:%s-%s", egrp_nm[k], *(groups->grpname[ni]), *(groups->grpname[nj])); kk++; } } md->igrp[n] = get_ebin_space(md->ebin, md->nEc, (const char **)gnm, unit_energy); n++; } } for (k = 0; (k < md->nEc); k++) { sfree(gnm[k]); } sfree(gnm); if (n != md->nE) { gmx_incons("Number of energy terms wrong"); } } md->nTC = groups->grps[egcTC].nr; md->nNHC = ir->opts.nhchainlength; /* shorthand for number of NH chains */ if (md->bMTTK) { md->nTCP = 1; /* assume only one possible coupling system for barostat for now */ } else { md->nTCP = 0; } if (md->etc == etcNOSEHOOVER) { if (md->bNHC_trotter) { md->mde_n = 2*md->nNHC*md->nTC; } else { md->mde_n = 2*md->nTC; } if (md->epc == epcMTTK) { md->mdeb_n = 2*md->nNHC*md->nTCP; } } else { md->mde_n = md->nTC; md->mdeb_n = 0; } snew(md->tmp_r, md->mde_n); snew(md->tmp_v, md->mde_n); snew(md->grpnms, md->mde_n); grpnms = md->grpnms; for (i = 0; (i < md->nTC); i++) { ni = groups->grps[egcTC].nm_ind[i]; sprintf(buf, "T-%s", *(groups->grpname[ni])); grpnms[i] = gmx_strdup(buf); } md->itemp = get_ebin_space(md->ebin, md->nTC, (const char **)grpnms, unit_temp_K); if (md->etc == etcNOSEHOOVER) { if (md->bPrintNHChains) { if (md->bNHC_trotter) { for (i = 0; (i < md->nTC); i++) { ni = groups->grps[egcTC].nm_ind[i]; bufi = *(groups->grpname[ni]); for (j = 0; (j < md->nNHC); j++) { sprintf(buf, "Xi-%d-%s", j, bufi); grpnms[2*(i*md->nNHC+j)] = gmx_strdup(buf); sprintf(buf, "vXi-%d-%s", j, bufi); grpnms[2*(i*md->nNHC+j)+1] = gmx_strdup(buf); } } md->itc = get_ebin_space(md->ebin, md->mde_n, (const char **)grpnms, unit_invtime); if (md->bMTTK) { for (i = 0; (i < md->nTCP); i++) { bufi = baro_nm[0]; /* All barostat DOF's together for now. */ for (j = 0; (j < md->nNHC); j++) { sprintf(buf, "Xi-%d-%s", j, bufi); grpnms[2*(i*md->nNHC+j)] = gmx_strdup(buf); sprintf(buf, "vXi-%d-%s", j, bufi); grpnms[2*(i*md->nNHC+j)+1] = gmx_strdup(buf); } } md->itcb = get_ebin_space(md->ebin, md->mdeb_n, (const char **)grpnms, unit_invtime); } } else { for (i = 0; (i < md->nTC); i++) { ni = groups->grps[egcTC].nm_ind[i]; bufi = *(groups->grpname[ni]); sprintf(buf, "Xi-%s", bufi); grpnms[2*i] = gmx_strdup(buf); sprintf(buf, "vXi-%s", bufi); grpnms[2*i+1] = gmx_strdup(buf); } md->itc = get_ebin_space(md->ebin, md->mde_n, (const char **)grpnms, unit_invtime); } } } else if (md->etc == etcBERENDSEN || md->etc == etcYES || md->etc == etcVRESCALE) { for (i = 0; (i < md->nTC); i++) { ni = groups->grps[egcTC].nm_ind[i]; sprintf(buf, "Lamb-%s", *(groups->grpname[ni])); grpnms[i] = gmx_strdup(buf); } md->itc = get_ebin_space(md->ebin, md->mde_n, (const char **)grpnms, ""); } sfree(grpnms); md->nU = groups->grps[egcACC].nr; if (md->nU > 1) { snew(grpnms, 3*md->nU); for (i = 0; (i < md->nU); i++) { ni = groups->grps[egcACC].nm_ind[i]; sprintf(buf, "Ux-%s", *(groups->grpname[ni])); grpnms[3*i+XX] = gmx_strdup(buf); sprintf(buf, "Uy-%s", *(groups->grpname[ni])); grpnms[3*i+YY] = gmx_strdup(buf); sprintf(buf, "Uz-%s", *(groups->grpname[ni])); grpnms[3*i+ZZ] = gmx_strdup(buf); } md->iu = get_ebin_space(md->ebin, 3*md->nU, (const char **)grpnms, unit_vel); sfree(grpnms); } if (fp_ene) { do_enxnms(fp_ene, &md->ebin->nener, &md->ebin->enm); } md->print_grpnms = NULL; /* check whether we're going to write dh histograms */ md->dhc = NULL; if (ir->fepvals->separate_dhdl_file == esepdhdlfileNO) { /* Currently dh histograms are only written with dynamics */ if (EI_DYNAMICS(ir->eI)) { snew(md->dhc, 1); mde_delta_h_coll_init(md->dhc, ir); } md->fp_dhdl = NULL; snew(md->dE, ir->fepvals->n_lambda); } else { md->fp_dhdl = fp_dhdl; snew(md->dE, ir->fepvals->n_lambda); } if (ir->bSimTemp) { int i; snew(md->temperatures, ir->fepvals->n_lambda); for (i = 0; i < ir->fepvals->n_lambda; i++) { md->temperatures[i] = ir->simtempvals->temperatures[i]; } } return md; }
void init_md(FILE *fplog, t_commrec *cr,t_inputrec *ir,real *t,real *t0, real *lambda,real *lam0, t_nrnb *nrnb,gmx_mtop_t *mtop, gmx_stochd_t *sd, int nfile,t_filenm fnm[], int *fp_trn,int *fp_xtc,int *fp_ene,char **fn_cpt, FILE **fp_dgdl,FILE **fp_field, t_mdebin **mdebin, tensor force_vir,tensor shake_vir,rvec mu_tot, bool *bNEMD,bool *bSimAnn,t_vcm **vcm, unsigned long Flags) { int i,j,n; real tmpt,mod; char filemode[2]; sprintf(filemode, (Flags & MD_APPENDFILES) ? "a" : "w"); /* Initial values */ *t = *t0 = ir->init_t; if (ir->efep != efepNO) { *lam0 = ir->init_lambda; *lambda = *lam0 + ir->init_step*ir->delta_lambda; } else { *lambda = *lam0 = 0.0; } *bSimAnn=FALSE; for(i=0;i<ir->opts.ngtc;i++) { /* set bSimAnn if any group is being annealed */ if(ir->opts.annealing[i]!=eannNO) *bSimAnn = TRUE; } if (*bSimAnn) { update_annealing_target_temp(&(ir->opts),ir->init_t); } *bNEMD = (ir->opts.ngacc > 1) || (norm(ir->opts.acc[0]) > 0); if (sd && (ir->eI == eiBD || EI_SD(ir->eI) || ir->etc == etcVRESCALE)) { *sd = init_stochd(fplog,ir); } if (vcm) { *vcm = init_vcm(fplog,&mtop->groups,ir); } if (EI_DYNAMICS(ir->eI) && !(Flags & MD_APPENDFILES)) { if (ir->etc == etcBERENDSEN) { please_cite(fplog,"Berendsen84a"); } if (ir->etc == etcVRESCALE) { please_cite(fplog,"Bussi2007a"); } } init_nrnb(nrnb); if (nfile != -1) { *fp_trn = -1; *fp_ene = -1; *fp_xtc = -1; if (MASTER(cr)) { *fp_trn = open_trn(ftp2fn(efTRN,nfile,fnm), filemode); if (ir->nstxtcout > 0) { *fp_xtc = open_xtc(ftp2fn(efXTC,nfile,fnm), filemode); } *fp_ene = open_enx(ftp2fn(efENX,nfile,fnm), filemode); *fn_cpt = opt2fn("-cpo",nfile,fnm); if ((fp_dgdl != NULL) && ir->efep!=efepNO) { if(Flags & MD_APPENDFILES) { *fp_dgdl= gmx_fio_fopen(opt2fn("-dgdl",nfile,fnm),filemode); } else { *fp_dgdl = xvgropen(opt2fn("-dgdl",nfile,fnm), "dG/d\\8l\\4","Time (ps)", "dG/d\\8l\\4 (kJ mol\\S-1\\N [\\8l\\4]\\S-1\\N)"); } } if ((fp_field != NULL) && (ir->ex[XX].n || ir->ex[YY].n ||ir->ex[ZZ].n)) { if(Flags & MD_APPENDFILES) { *fp_field = gmx_fio_fopen(opt2fn("-field",nfile,fnm),filemode); } else { *fp_field = xvgropen(opt2fn("-field",nfile,fnm), "Applied electric field","Time (ps)", "E (V/nm)"); } } } *mdebin = init_mdebin( (Flags & MD_APPENDFILES) ? -1 : *fp_ene,mtop,ir); } /* Initiate variables */ clear_mat(force_vir); clear_mat(shake_vir); clear_rvec(mu_tot); debug_gmx(); }
gmx_bool constrain(FILE *fplog, gmx_bool bLog, gmx_bool bEner, struct gmx_constr *constr, t_idef *idef, t_inputrec *ir, gmx_ekindata_t *ekind, t_commrec *cr, gmx_int64_t step, int delta_step, t_mdatoms *md, rvec *x, rvec *xprime, rvec *min_proj, gmx_bool bMolPBC, matrix box, real lambda, real *dvdlambda, rvec *v, tensor *vir, t_nrnb *nrnb, int econq, gmx_bool bPscal, real veta, real vetanew) { gmx_bool bOK, bDump; int start, homenr, nrend; int i, j, d; int ncons, settle_error; tensor vir_r_m_dr; rvec *vstor; real invdt, vir_fac, t; t_ilist *settle; int nsettle; t_pbc pbc, *pbc_null; char buf[22]; t_vetavars vetavar; int nth, th; if (econq == econqForceDispl && !EI_ENERGY_MINIMIZATION(ir->eI)) { gmx_incons("constrain called for forces displacements while not doing energy minimization, can not do this while the LINCS and SETTLE constraint connection matrices are mass weighted"); } bOK = TRUE; bDump = FALSE; start = 0; homenr = md->homenr; nrend = start+homenr; /* set constants for pressure control integration */ init_vetavars(&vetavar, econq != econqCoord, veta, vetanew, ir, ekind, bPscal); if (ir->delta_t == 0) { invdt = 0; } else { invdt = 1/ir->delta_t; } if (ir->efep != efepNO && EI_DYNAMICS(ir->eI)) { /* Set the constraint lengths for the step at which this configuration * is meant to be. The invmasses should not be changed. */ lambda += delta_step*ir->fepvals->delta_lambda; } if (vir != NULL) { clear_mat(vir_r_m_dr); } where(); settle = &idef->il[F_SETTLE]; nsettle = settle->nr/(1+NRAL(F_SETTLE)); if (nsettle > 0) { nth = gmx_omp_nthreads_get(emntSETTLE); } else { nth = 1; } if (nth > 1 && constr->vir_r_m_dr_th == NULL) { snew(constr->vir_r_m_dr_th, nth); snew(constr->settle_error, nth); } settle_error = -1; /* We do not need full pbc when constraints do not cross charge groups, * i.e. when dd->constraint_comm==NULL. * Note that PBC for constraints is different from PBC for bondeds. * For constraints there is both forward and backward communication. */ if (ir->ePBC != epbcNONE && (cr->dd || bMolPBC) && !(cr->dd && cr->dd->constraint_comm == NULL)) { /* With pbc=screw the screw has been changed to a shift * by the constraint coordinate communication routine, * so that here we can use normal pbc. */ pbc_null = set_pbc_dd(&pbc, ir->ePBC, cr->dd, FALSE, box); } else { pbc_null = NULL; } /* Communicate the coordinates required for the non-local constraints * for LINCS and/or SETTLE. */ if (cr->dd) { dd_move_x_constraints(cr->dd, box, x, xprime, econq == econqCoord); } if (constr->lincsd != NULL) { bOK = constrain_lincs(fplog, bLog, bEner, ir, step, constr->lincsd, md, cr, x, xprime, min_proj, box, pbc_null, lambda, dvdlambda, invdt, v, vir != NULL, vir_r_m_dr, econq, nrnb, constr->maxwarn, &constr->warncount_lincs); if (!bOK && constr->maxwarn >= 0) { if (fplog != NULL) { fprintf(fplog, "Constraint error in algorithm %s at step %s\n", econstr_names[econtLINCS], gmx_step_str(step, buf)); } bDump = TRUE; } } if (constr->nblocks > 0) { switch (econq) { case (econqCoord): bOK = bshakef(fplog, constr->shaked, md->invmass, constr->nblocks, constr->sblock, idef, ir, x, xprime, nrnb, constr->lagr, lambda, dvdlambda, invdt, v, vir != NULL, vir_r_m_dr, constr->maxwarn >= 0, econq, &vetavar); break; case (econqVeloc): bOK = bshakef(fplog, constr->shaked, md->invmass, constr->nblocks, constr->sblock, idef, ir, x, min_proj, nrnb, constr->lagr, lambda, dvdlambda, invdt, NULL, vir != NULL, vir_r_m_dr, constr->maxwarn >= 0, econq, &vetavar); break; default: gmx_fatal(FARGS, "Internal error, SHAKE called for constraining something else than coordinates"); break; } if (!bOK && constr->maxwarn >= 0) { if (fplog != NULL) { fprintf(fplog, "Constraint error in algorithm %s at step %s\n", econstr_names[econtSHAKE], gmx_step_str(step, buf)); } bDump = TRUE; } } if (nsettle > 0) { int calcvir_atom_end; if (vir == NULL) { calcvir_atom_end = 0; } else { calcvir_atom_end = md->homenr; } switch (econq) { case econqCoord: #pragma omp parallel for num_threads(nth) schedule(static) for (th = 0; th < nth; th++) { int start_th, end_th; if (th > 0) { clear_mat(constr->vir_r_m_dr_th[th]); } start_th = (nsettle* th )/nth; end_th = (nsettle*(th+1))/nth; if (start_th >= 0 && end_th - start_th > 0) { csettle(constr->settled, end_th-start_th, settle->iatoms+start_th*(1+NRAL(F_SETTLE)), pbc_null, x[0], xprime[0], invdt, v ? v[0] : NULL, calcvir_atom_end, th == 0 ? vir_r_m_dr : constr->vir_r_m_dr_th[th], th == 0 ? &settle_error : &constr->settle_error[th], &vetavar); } } inc_nrnb(nrnb, eNR_SETTLE, nsettle); if (v != NULL) { inc_nrnb(nrnb, eNR_CONSTR_V, nsettle*3); } if (vir != NULL) { inc_nrnb(nrnb, eNR_CONSTR_VIR, nsettle*3); } break; case econqVeloc: case econqDeriv: case econqForce: case econqForceDispl: #pragma omp parallel for num_threads(nth) schedule(static) for (th = 0; th < nth; th++) { int start_th, end_th; if (th > 0) { clear_mat(constr->vir_r_m_dr_th[th]); } start_th = (nsettle* th )/nth; end_th = (nsettle*(th+1))/nth; if (start_th >= 0 && end_th - start_th > 0) { settle_proj(constr->settled, econq, end_th-start_th, settle->iatoms+start_th*(1+NRAL(F_SETTLE)), pbc_null, x, xprime, min_proj, calcvir_atom_end, th == 0 ? vir_r_m_dr : constr->vir_r_m_dr_th[th], &vetavar); } } /* This is an overestimate */ inc_nrnb(nrnb, eNR_SETTLE, nsettle); break; case econqDeriv_FlexCon: /* Nothing to do, since the are no flexible constraints in settles */ break; default: gmx_incons("Unknown constraint quantity for settle"); } } if (settle->nr > 0) { /* Combine virial and error info of the other threads */ for (i = 1; i < nth; i++) { m_add(vir_r_m_dr, constr->vir_r_m_dr_th[i], vir_r_m_dr); settle_error = constr->settle_error[i]; } if (econq == econqCoord && settle_error >= 0) { bOK = FALSE; if (constr->maxwarn >= 0) { char buf[256]; sprintf(buf, "\nstep " "%"GMX_PRId64 ": Water molecule starting at atom %d can not be " "settled.\nCheck for bad contacts and/or reduce the timestep if appropriate.\n", step, ddglatnr(cr->dd, settle->iatoms[settle_error*(1+NRAL(F_SETTLE))+1])); if (fplog) { fprintf(fplog, "%s", buf); } fprintf(stderr, "%s", buf); constr->warncount_settle++; if (constr->warncount_settle > constr->maxwarn) { too_many_constraint_warnings(-1, constr->warncount_settle); } bDump = TRUE; } } } free_vetavars(&vetavar); if (vir != NULL) { switch (econq) { case econqCoord: vir_fac = 0.5/(ir->delta_t*ir->delta_t); break; case econqVeloc: vir_fac = 0.5/ir->delta_t; break; case econqForce: case econqForceDispl: vir_fac = 0.5; break; default: vir_fac = 0; gmx_incons("Unsupported constraint quantity for virial"); } if (EI_VV(ir->eI)) { vir_fac *= 2; /* only constraining over half the distance here */ } for (i = 0; i < DIM; i++) { for (j = 0; j < DIM; j++) { (*vir)[i][j] = vir_fac*vir_r_m_dr[i][j]; } } } if (bDump) { dump_confs(fplog, step, constr->warn_mtop, start, homenr, cr, x, xprime, box); } if (econq == econqCoord) { if (ir->ePull == epullCONSTRAINT) { if (EI_DYNAMICS(ir->eI)) { t = ir->init_t + (step + delta_step)*ir->delta_t; } else { t = ir->init_t; } set_pbc(&pbc, ir->ePBC, box); pull_constraint(ir->pull, md, &pbc, cr, ir->delta_t, t, x, xprime, v, *vir); } if (constr->ed && delta_step > 0) { /* apply the essential dynamcs constraints here */ do_edsam(ir, step, cr, xprime, v, box, constr->ed); } } return bOK; }
void init_disres(FILE *fplog,const gmx_mtop_t *mtop, t_inputrec *ir,const t_commrec *cr,gmx_bool bPartDecomp, t_fcdata *fcd,t_state *state) { int fa,nmol,i,npair,np; t_iparams *ip; t_disresdata *dd; history_t *hist; gmx_mtop_ilistloop_t iloop; t_ilist *il; char *ptr; dd = &(fcd->disres); if (gmx_mtop_ftype_count(mtop,F_DISRES) == 0) { dd->nres = 0; return; } if (fplog) { fprintf(fplog,"Initializing the distance restraints\n"); } if (ir->eDisre == edrEnsemble) { gmx_fatal(FARGS,"Sorry, distance restraints with ensemble averaging over multiple molecules in one system are not functional in this version of GROMACS"); } dd->dr_weighting = ir->eDisreWeighting; dd->dr_fc = ir->dr_fc; if (EI_DYNAMICS(ir->eI)) { dd->dr_tau = ir->dr_tau; } else { dd->dr_tau = 0.0; } if (dd->dr_tau == 0.0) { dd->dr_bMixed = FALSE; dd->ETerm = 0.0; } else { dd->dr_bMixed = ir->bDisreMixed; dd->ETerm = exp(-(ir->delta_t/ir->dr_tau)); } dd->ETerm1 = 1.0 - dd->ETerm; ip = mtop->ffparams.iparams; dd->nres = 0; dd->npair = 0; iloop = gmx_mtop_ilistloop_init(mtop); while (gmx_mtop_ilistloop_next(iloop,&il,&nmol)) { np = 0; for(fa=0; fa<il[F_DISRES].nr; fa+=3) { np++; npair = mtop->ffparams.iparams[il[F_DISRES].iatoms[fa]].disres.npair; if (np == npair) { dd->nres += (ir->eDisre==edrEnsemble ? 1 : nmol)*npair; dd->npair += nmol*npair; np = 0; } } } if (cr && PAR(cr) && !bPartDecomp) { /* Temporary check, will be removed when disre is implemented with DD */ const char *notestr="NOTE: atoms involved in distance restraints should be within the longest cut-off distance, if this is not the case mdrun generates a fatal error, in that case use particle decomposition (mdrun option -pd)"; if (MASTER(cr)) fprintf(stderr,"\n%s\n\n",notestr); if (fplog) fprintf(fplog,"%s\n",notestr); if (dd->dr_tau != 0 || ir->eDisre == edrEnsemble || cr->ms != NULL || dd->nres != dd->npair) { gmx_fatal(FARGS,"Time or ensemble averaged or multiple pair distance restraints do not work (yet) with domain decomposition, use particle decomposition (mdrun option -pd)"); } if (ir->nstdisreout != 0) { if (fplog) { fprintf(fplog,"\nWARNING: Can not write distance restraint data to energy file with domain decomposition\n\n"); } if (MASTER(cr)) { fprintf(stderr,"\nWARNING: Can not write distance restraint data to energy file with domain decomposition\n"); } ir->nstdisreout = 0; } } snew(dd->rt,dd->npair); if (dd->dr_tau != 0.0) { hist = &state->hist; /* Set the "history lack" factor to 1 */ state->flags |= (1<<estDISRE_INITF); hist->disre_initf = 1.0; /* Allocate space for the r^-3 time averages */ state->flags |= (1<<estDISRE_RM3TAV); hist->ndisrepairs = dd->npair; snew(hist->disre_rm3tav,hist->ndisrepairs); } /* Allocate space for a copy of rm3tav, * so we can call do_force without modifying the state. */ snew(dd->rm3tav,dd->npair); /* Allocate Rt_6 and Rtav_6 consecutively in memory so they can be * averaged over the processors in one call (in calc_disre_R_6) */ snew(dd->Rt_6,2*dd->nres); dd->Rtav_6 = &(dd->Rt_6[dd->nres]); ptr = getenv("GMX_DISRE_ENSEMBLE_SIZE"); if (cr && cr->ms != NULL && ptr != NULL) { #ifdef GMX_MPI dd->nsystems = 0; sscanf(ptr,"%d",&dd->nsystems); if (fplog) { fprintf(fplog,"Found GMX_DISRE_ENSEMBLE_SIZE set to %d systems per ensemble\n",dd->nsystems); } check_multi_int(fplog,cr->ms,dd->nsystems, "the number of systems per ensemble"); if (dd->nsystems <= 0 || cr->ms->nsim % dd->nsystems != 0) { gmx_fatal(FARGS,"The number of systems %d is not divisible by the number of systems per ensemble %d\n",cr->ms->nsim,dd->nsystems); } /* Split the inter-master communicator into different ensembles */ MPI_Comm_split(cr->ms->mpi_comm_masters, cr->ms->sim/dd->nsystems, cr->ms->sim, &dd->mpi_comm_ensemble); if (fplog) { fprintf(fplog,"Our ensemble consists of systems:"); for(i=0; i<dd->nsystems; i++) { fprintf(fplog," %d", (cr->ms->sim/dd->nsystems)*dd->nsystems+i); } fprintf(fplog,"\n"); } snew(dd->Rtl_6,dd->nres); #endif } else { dd->nsystems = 1; dd->Rtl_6 = dd->Rt_6; } if (dd->npair > 0) { if (fplog) { fprintf(fplog,"There are %d distance restraints involving %d atom pairs\n",dd->nres,dd->npair); } if (cr && cr->ms) { check_multi_int(fplog,cr->ms,fcd->disres.nres, "the number of distance restraints"); } please_cite(fplog,"Tropp80a"); please_cite(fplog,"Torda89a"); } }
gmx_repl_ex_t init_replica_exchange(FILE *fplog, const gmx_multisim_t *ms, const t_state *state, const t_inputrec *ir, int nst, int nex, int init_seed) { real temp, pres; int i, j, k; struct gmx_repl_ex *re; gmx_bool bTemp; gmx_bool bLambda = FALSE; fprintf(fplog, "\nInitializing Replica Exchange\n"); if (ms == NULL || ms->nsim == 1) { gmx_fatal(FARGS, "Nothing to exchange with only one replica, maybe you forgot to set the -multi option of mdrun?"); } if (!EI_DYNAMICS(ir->eI)) { gmx_fatal(FARGS, "Replica exchange is only supported by dynamical simulations"); /* Note that PAR(cr) is defined by cr->nnodes > 1, which is * distinct from MULTISIM(cr). A multi-simulation only runs * with real MPI parallelism, but this does not imply PAR(cr) * is true! * * Since we are using a dynamical integrator, the only * decomposition is DD, so PAR(cr) and DOMAINDECOMP(cr) are * synonymous. The only way for cr->nnodes > 1 to be true is * if we are using DD. */ } snew(re, 1); re->repl = ms->sim; re->nrepl = ms->nsim; snew(re->q, ereENDSINGLE); fprintf(fplog, "Repl There are %d replicas:\n", re->nrepl); check_multi_int(fplog, ms, state->natoms, "the number of atoms", FALSE); check_multi_int(fplog, ms, ir->eI, "the integrator", FALSE); check_multi_int64(fplog, ms, ir->init_step+ir->nsteps, "init_step+nsteps", FALSE); check_multi_int64(fplog, ms, (ir->init_step+nst-1)/nst, "first exchange step: init_step/-replex", FALSE); check_multi_int(fplog, ms, ir->etc, "the temperature coupling", FALSE); check_multi_int(fplog, ms, ir->opts.ngtc, "the number of temperature coupling groups", FALSE); check_multi_int(fplog, ms, ir->epc, "the pressure coupling", FALSE); check_multi_int(fplog, ms, ir->efep, "free energy", FALSE); check_multi_int(fplog, ms, ir->fepvals->n_lambda, "number of lambda states", FALSE); re->temp = ir->opts.ref_t[0]; for (i = 1; (i < ir->opts.ngtc); i++) { if (ir->opts.ref_t[i] != re->temp) { fprintf(fplog, "\nWARNING: The temperatures of the different temperature coupling groups are not identical\n\n"); fprintf(stderr, "\nWARNING: The temperatures of the different temperature coupling groups are not identical\n\n"); } } re->type = -1; bTemp = repl_quantity(ms, re, ereTEMP, re->temp); if (ir->efep != efepNO) { bLambda = repl_quantity(ms, re, ereLAMBDA, (real)ir->fepvals->init_fep_state); } if (re->type == -1) /* nothing was assigned */ { gmx_fatal(FARGS, "The properties of the %d systems are all the same, there is nothing to exchange", re->nrepl); } if (bLambda && bTemp) { re->type = ereTL; } if (bTemp) { please_cite(fplog, "Sugita1999a"); if (ir->epc != epcNO) { re->bNPT = TRUE; fprintf(fplog, "Repl Using Constant Pressure REMD.\n"); please_cite(fplog, "Okabe2001a"); } if (ir->etc == etcBERENDSEN) { gmx_fatal(FARGS, "REMD with the %s thermostat does not produce correct potential energy distributions, consider using the %s thermostat instead", ETCOUPLTYPE(ir->etc), ETCOUPLTYPE(etcVRESCALE)); } } if (bLambda) { if (ir->fepvals->delta_lambda != 0) /* check this? */ { gmx_fatal(FARGS, "delta_lambda is not zero"); } } if (re->bNPT) { snew(re->pres, re->nrepl); if (ir->epct == epctSURFACETENSION) { pres = ir->ref_p[ZZ][ZZ]; } else { pres = 0; j = 0; for (i = 0; i < DIM; i++) { if (ir->compress[i][i] != 0) { pres += ir->ref_p[i][i]; j++; } } pres /= j; } re->pres[re->repl] = pres; gmx_sum_sim(re->nrepl, re->pres, ms); } /* Make an index for increasing replica order */ /* only makes sense if one or the other is varying, not both! if both are varying, we trust the order the person gave. */ snew(re->ind, re->nrepl); for (i = 0; i < re->nrepl; i++) { re->ind[i] = i; } if (re->type < ereENDSINGLE) { for (i = 0; i < re->nrepl; i++) { for (j = i+1; j < re->nrepl; j++) { if (re->q[re->type][re->ind[j]] < re->q[re->type][re->ind[i]]) { k = re->ind[i]; re->ind[i] = re->ind[j]; re->ind[j] = k; } else if (re->q[re->type][re->ind[j]] == re->q[re->type][re->ind[i]]) { gmx_fatal(FARGS, "Two replicas have identical %ss", erename[re->type]); } } } } /* keep track of all the swaps, starting with the initial placement. */ snew(re->allswaps, re->nrepl); for (i = 0; i < re->nrepl; i++) { re->allswaps[i] = re->ind[i]; } switch (re->type) { case ereTEMP: fprintf(fplog, "\nReplica exchange in temperature\n"); for (i = 0; i < re->nrepl; i++) { fprintf(fplog, " %5.1f", re->q[re->type][re->ind[i]]); } fprintf(fplog, "\n"); break; case ereLAMBDA: fprintf(fplog, "\nReplica exchange in lambda\n"); for (i = 0; i < re->nrepl; i++) { fprintf(fplog, " %3d", (int)re->q[re->type][re->ind[i]]); } fprintf(fplog, "\n"); break; case ereTL: fprintf(fplog, "\nReplica exchange in temperature and lambda state\n"); for (i = 0; i < re->nrepl; i++) { fprintf(fplog, " %5.1f", re->q[ereTEMP][re->ind[i]]); } fprintf(fplog, "\n"); for (i = 0; i < re->nrepl; i++) { fprintf(fplog, " %5d", (int)re->q[ereLAMBDA][re->ind[i]]); } fprintf(fplog, "\n"); break; default: gmx_incons("Unknown replica exchange quantity"); } if (re->bNPT) { fprintf(fplog, "\nRepl p"); for (i = 0; i < re->nrepl; i++) { fprintf(fplog, " %5.2f", re->pres[re->ind[i]]); } for (i = 0; i < re->nrepl; i++) { if ((i > 0) && (re->pres[re->ind[i]] < re->pres[re->ind[i-1]])) { fprintf(fplog, "\nWARNING: The reference pressures decrease with increasing temperatures\n\n"); fprintf(stderr, "\nWARNING: The reference pressures decrease with increasing temperatures\n\n"); } } } re->nst = nst; if (init_seed == -1) { if (MASTERSIM(ms)) { re->seed = (int)gmx_rng_make_seed(); } else { re->seed = 0; } gmx_sumi_sim(1, &(re->seed), ms); } else { re->seed = init_seed; } fprintf(fplog, "\nReplica exchange interval: %d\n", re->nst); fprintf(fplog, "\nReplica random seed: %d\n", re->seed); re->rng = gmx_rng_init(re->seed); re->nattempt[0] = 0; re->nattempt[1] = 0; snew(re->prob_sum, re->nrepl); snew(re->nexchange, re->nrepl); snew(re->nmoves, re->nrepl); for (i = 0; i < re->nrepl; i++) { snew(re->nmoves[i], re->nrepl); } fprintf(fplog, "Replica exchange information below: x=exchange, pr=probability\n"); /* generate space for the helper functions so we don't have to snew each time */ snew(re->destinations, re->nrepl); snew(re->incycle, re->nrepl); snew(re->tmpswap, re->nrepl); snew(re->cyclic, re->nrepl); snew(re->order, re->nrepl); for (i = 0; i < re->nrepl; i++) { snew(re->cyclic[i], re->nrepl); snew(re->order[i], re->nrepl); } /* allocate space for the functions storing the data for the replicas */ /* not all of these arrays needed in all cases, but they don't take up much space, since the max size is nrepl**2 */ snew(re->prob, re->nrepl); snew(re->bEx, re->nrepl); snew(re->beta, re->nrepl); snew(re->Vol, re->nrepl); snew(re->Epot, re->nrepl); snew(re->de, re->nrepl); for (i = 0; i < re->nrepl; i++) { snew(re->de[i], re->nrepl); } re->nex = nex; return re; }
int check_nstglobalcomm(const gmx::MDLogger &mdlog, int nstglobalcomm, t_inputrec *ir) { if (!EI_DYNAMICS(ir->eI)) { nstglobalcomm = 1; } if (nstglobalcomm == -1) { // Set up the default behaviour if (!(ir->nstcalcenergy > 0 || ir->nstlist > 0 || ir->etc != etcNO || ir->epc != epcNO)) { /* The user didn't choose the period for anything important, so we just make sure we can send signals and write output suitably. */ nstglobalcomm = 10; if (ir->nstenergy > 0 && ir->nstenergy < nstglobalcomm) { nstglobalcomm = ir->nstenergy; } } else { /* The user has made a choice (perhaps implicitly), so we * ensure that we do timely intra-simulation communication * for (possibly) each of the four parts that care. * * TODO Does the Verlet scheme (+ DD) need any * communication at nstlist steps? Is the use of nstlist * here a leftover of the twin-range scheme? Can we remove * nstlist when we remove the group scheme? */ nstglobalcomm = lcd4(ir->nstcalcenergy, ir->nstlist, ir->etc != etcNO ? ir->nsttcouple : 0, ir->epc != epcNO ? ir->nstpcouple : 0); } } else { // Check that the user's choice of mdrun -gcom will work if (ir->nstlist > 0 && nstglobalcomm > ir->nstlist && nstglobalcomm % ir->nstlist != 0) { nstglobalcomm = (nstglobalcomm / ir->nstlist)*ir->nstlist; GMX_LOG(mdlog.warning).asParagraph().appendTextFormatted( "WARNING: nstglobalcomm is larger than nstlist, but not a multiple, setting it to %d", nstglobalcomm); } if (ir->nstcalcenergy > 0) { check_nst_param(mdlog, "-gcom", nstglobalcomm, "nstcalcenergy", &ir->nstcalcenergy); } if (ir->etc != etcNO && ir->nsttcouple > 0) { check_nst_param(mdlog, "-gcom", nstglobalcomm, "nsttcouple", &ir->nsttcouple); } if (ir->epc != epcNO && ir->nstpcouple > 0) { check_nst_param(mdlog, "-gcom", nstglobalcomm, "nstpcouple", &ir->nstpcouple); } check_nst_param(mdlog, "-gcom", nstglobalcomm, "nstenergy", &ir->nstenergy); check_nst_param(mdlog, "-gcom", nstglobalcomm, "nstlog", &ir->nstlog); } if (ir->comm_mode != ecmNO && ir->nstcomm < nstglobalcomm) { GMX_LOG(mdlog.warning).asParagraph().appendTextFormatted( "WARNING: Changing nstcomm from %d to %d", ir->nstcomm, nstglobalcomm); ir->nstcomm = nstglobalcomm; } GMX_LOG(mdlog.info).appendTextFormatted( "Intra-simulation communication will occur every %d steps.\n", nstglobalcomm); return nstglobalcomm; }
void set_state_entries(t_state *state, const t_inputrec *ir) { /* The entries in the state in the tpx file might not correspond * with what is needed, so we correct this here. */ state->flags = 0; if (ir->efep != efepNO || ir->bExpanded) { state->flags |= (1<<estLAMBDA); state->flags |= (1<<estFEPSTATE); } state->flags |= (1<<estX); if (state->lambda == NULL) { snew(state->lambda, efptNR); } if (state->x == NULL) { snew(state->x, state->nalloc); } if (EI_DYNAMICS(ir->eI)) { state->flags |= (1<<estV); if (state->v == NULL) { snew(state->v, state->nalloc); } } if (ir->eI == eiSD2) { state->flags |= (1<<estSDX); if (state->sd_X == NULL) { /* sd_X is not stored in the tpx file, so we need to allocate it */ snew(state->sd_X, state->nalloc); } } if (ir->eI == eiCG) { state->flags |= (1<<estCGP); if (state->cg_p == NULL) { /* cg_p is not stored in the tpx file, so we need to allocate it */ snew(state->cg_p, state->nalloc); } } state->nnhpres = 0; if (ir->ePBC != epbcNONE) { state->flags |= (1<<estBOX); if (PRESERVE_SHAPE(*ir)) { state->flags |= (1<<estBOX_REL); } if ((ir->epc == epcPARRINELLORAHMAN) || (ir->epc == epcMTTK)) { state->flags |= (1<<estBOXV); } if (ir->epc != epcNO) { if (IR_NPT_TROTTER(ir) || (IR_NPH_TROTTER(ir))) { state->nnhpres = 1; state->flags |= (1<<estNHPRES_XI); state->flags |= (1<<estNHPRES_VXI); state->flags |= (1<<estSVIR_PREV); state->flags |= (1<<estFVIR_PREV); state->flags |= (1<<estVETA); state->flags |= (1<<estVOL0); } else { state->flags |= (1<<estPRES_PREV); } } } if (ir->etc == etcNOSEHOOVER) { state->flags |= (1<<estNH_XI); state->flags |= (1<<estNH_VXI); } if (ir->etc == etcVRESCALE) { state->flags |= (1<<estTC_INT); } init_gtc_state(state, state->ngtc, state->nnhpres, ir->opts.nhchainlength); /* allocate the space for nose-hoover chains */ init_ekinstate(&state->ekinstate, ir); init_energyhistory(&state->enerhist); init_df_history(&state->dfhist, ir->fepvals->n_lambda); state->swapstate.eSwapCoords = ir->eSwapCoords; }
t_mdebin *init_mdebin(int fp_ene, const gmx_mtop_t *mtop, const t_inputrec *ir) { char *ener_nm[F_NRE]; static char *vir_nm[] = { "Vir-XX", "Vir-XY", "Vir-XZ", "Vir-YX", "Vir-YY", "Vir-YZ", "Vir-ZX", "Vir-ZY", "Vir-ZZ" }; static char *sv_nm[] = { "ShakeVir-XX", "ShakeVir-XY", "ShakeVir-XZ", "ShakeVir-YX", "ShakeVir-YY", "ShakeVir-YZ", "ShakeVir-ZX", "ShakeVir-ZY", "ShakeVir-ZZ" }; static char *fv_nm[] = { "ForceVir-XX", "ForceVir-XY", "ForceVir-XZ", "ForceVir-YX", "ForceVir-YY", "ForceVir-YZ", "ForceVir-ZX", "ForceVir-ZY", "ForceVir-ZZ" }; static char *pres_nm[] = { "Pres-XX (bar)","Pres-XY (bar)","Pres-XZ (bar)", "Pres-YX (bar)","Pres-YY (bar)","Pres-YZ (bar)", "Pres-ZX (bar)","Pres-ZY (bar)","Pres-ZZ (bar)" }; static char *surft_nm[] = { "#Surf*SurfTen" }; static char *mu_nm[] = { "Mu-X", "Mu-Y", "Mu-Z" }; static char *vcos_nm[] = { "2CosZ*Vel-X" }; static char *visc_nm[] = { "1/Viscosity (SI)" }; static char **grpnms; const gmx_groups_t *groups; char **gnm; char buf[256]; t_mdebin *md; int i,j,ni,nj,n,k,kk,ncon,nset; bool bBHAM,b14; f_nre = 0; // otherwise, multiple calls to mdrunner_integrate are not possible!NnCrmsd; groups = &mtop->groups; bBHAM = (mtop->ffparams.functype[0] == F_BHAM); b14 = (gmx_mtop_ftype_count(mtop,F_LJ14) > 0 || gmx_mtop_ftype_count(mtop,F_LJC14_Q) > 0); ncon = gmx_mtop_ftype_count(mtop,F_CONSTR); nset = gmx_mtop_ftype_count(mtop,F_SETTLE); bConstr = (ncon > 0 || nset > 0); bConstrVir = FALSE; if (bConstr) { if (ncon > 0 && ir->eConstrAlg == econtLINCS) { if (ir->eI == eiSD2) nCrmsd = 2; else nCrmsd = 1; } bConstrVir = (getenv("GMX_CONSTRAINTVIR") != NULL); } else { nCrmsd = 0; } for(i=0; i<F_NRE; i++) { bEner[i] = FALSE; if (i == F_LJ) bEner[i] = !bBHAM; else if (i == F_BHAM) bEner[i] = bBHAM; else if (i == F_EQM) bEner[i] = ir->bQMMM; else if (i == F_COUL_LR) bEner[i] = (ir->rcoulomb > ir->rlist); else if (i == F_LJ_LR) bEner[i] = (!bBHAM && ir->rvdw > ir->rlist); else if (i == F_BHAM_LR) bEner[i] = (bBHAM && ir->rvdw > ir->rlist); else if (i == F_RF_EXCL) bEner[i] = (EEL_RF(ir->coulombtype) && ir->coulombtype != eelRF_NEC); else if (i == F_COUL_RECIP) bEner[i] = EEL_FULL(ir->coulombtype); else if (i == F_LJ14) bEner[i] = b14; else if (i == F_COUL14) bEner[i] = b14; else if (i == F_LJC14_Q || i == F_LJC_PAIRS_NB) bEner[i] = FALSE; else if ((i == F_DVDL) || (i == F_DKDL)) bEner[i] = (ir->efep != efepNO); else if (i == F_DGDL_CON) bEner[i] = (ir->efep != efepNO && bConstr); else if ((interaction_function[i].flags & IF_VSITE) || (i == F_CONSTR) || (i == F_SETTLE)) bEner[i] = FALSE; else if ((i == F_COUL_SR) || (i == F_EPOT) || (i == F_PRES) || (i==F_EQM)) bEner[i] = TRUE; else if ((i == F_ETOT) || (i == F_EKIN) || (i == F_TEMP)) bEner[i] = EI_DYNAMICS(ir->eI); else if (i == F_DISPCORR) bEner[i] = (ir->eDispCorr != edispcNO); else if (i == F_DISRESVIOL) bEner[i] = (gmx_mtop_ftype_count(mtop,F_DISRES) > 0); else if (i == F_ORIRESDEV) bEner[i] = (gmx_mtop_ftype_count(mtop,F_ORIRES) > 0); else if (i == F_CONNBONDS) bEner[i] = FALSE; else if (i == F_COM_PULL) bEner[i] = (ir->ePull == epullUMBRELLA || ir->ePull == epullCONST_F); else if (i == F_ECONSERVED) bEner[i] = ((ir->etc == etcNOSEHOOVER || ir->etc == etcVRESCALE) && ir->epc == epcNO); else bEner[i] = (gmx_mtop_ftype_count(mtop,i) > 0); } for(i=0; i<F_NRE; i++) if (bEner[i]) { ener_nm[f_nre]=interaction_function[i].longname; f_nre++; } epc = ir->epc; bTricl = TRICLINIC(ir->compress) || TRICLINIC(ir->deform); bDynBox = DYNAMIC_BOX(*ir); etc = ir->etc; /* Energy monitoring */ snew(md,1); md->ebin = mk_ebin(); md->ie = get_ebin_space(md->ebin,f_nre,ener_nm); if (nCrmsd) { /* This should be called directly after the call for md->ie, * such that md->iconrmsd follows directly in the list. */ md->iconrmsd = get_ebin_space(md->ebin,nCrmsd,conrmsd_nm); } if (bDynBox) md->ib = get_ebin_space(md->ebin, bTricl ? NTRICLBOXS : NBOXS, bTricl ? tricl_boxs_nm : boxs_nm); if (bConstrVir) { md->isvir = get_ebin_space(md->ebin,asize(sv_nm),sv_nm); md->ifvir = get_ebin_space(md->ebin,asize(fv_nm),fv_nm); } md->ivir = get_ebin_space(md->ebin,asize(vir_nm),vir_nm); md->ipres = get_ebin_space(md->ebin,asize(pres_nm),pres_nm); md->isurft = get_ebin_space(md->ebin,asize(surft_nm),surft_nm); if (epc == epcPARRINELLORAHMAN) { md->ipc = get_ebin_space(md->ebin,bTricl ? 6 : 3,boxvel_nm); } md->imu = get_ebin_space(md->ebin,asize(mu_nm),mu_nm); if (ir->cos_accel != 0) { md->ivcos = get_ebin_space(md->ebin,asize(vcos_nm),vcos_nm); md->ivisc = get_ebin_space(md->ebin,asize(visc_nm),visc_nm); } if (ir->rcoulomb > ir->rlist) bEInd[egCOULLR] = TRUE; if (!bBHAM) { if (ir->rvdw > ir->rlist) bEInd[egLJLR] = TRUE; } else { bEInd[egLJSR] = FALSE; bEInd[egBHAMSR] = TRUE; if (ir->rvdw > ir->rlist) bEInd[egBHAMLR] = TRUE; } if (b14) { bEInd[egLJ14] = TRUE; bEInd[egCOUL14] = TRUE; } md->nEc=0; for(i=0; (i<egNR); i++) if (bEInd[i]) md->nEc++; n=groups->grps[egcENER].nr; md->nEg=n; md->nE=(n*(n+1))/2; snew(md->igrp,md->nE); if (md->nE > 1) { n=0; snew(gnm,md->nEc); for(k=0; (k<md->nEc); k++) snew(gnm[k],STRLEN); for(i=0; (i<groups->grps[egcENER].nr); i++) { ni=groups->grps[egcENER].nm_ind[i]; for(j=i; (j<groups->grps[egcENER].nr); j++) { nj=groups->grps[egcENER].nm_ind[j]; for(k=kk=0; (k<egNR); k++) { if (bEInd[k]) { sprintf(gnm[kk],"%s:%s-%s",egrp_nm[k], *(groups->grpname[ni]),*(groups->grpname[nj])); kk++; } } md->igrp[n]=get_ebin_space(md->ebin,md->nEc,gnm); n++; } } for(k=0; (k<md->nEc); k++) sfree(gnm[k]); sfree(gnm); if (n != md->nE) gmx_incons("Number of energy terms wrong"); } md->nTC=groups->grps[egcTC].nr; snew(grpnms,md->nTC); for(i=0; (i<md->nTC); i++) { ni=groups->grps[egcTC].nm_ind[i]; sprintf(buf,"T-%s",*(groups->grpname[ni])); grpnms[i]=strdup(buf); } md->itemp=get_ebin_space(md->ebin,md->nTC,grpnms); sfree(*grpnms); if (etc == etcNOSEHOOVER) { for(i=0; (i<md->nTC); i++) { ni=groups->grps[egcTC].nm_ind[i]; sprintf(buf,"Xi-%s",*(groups->grpname[ni])); grpnms[i]=strdup(buf); } md->itc=get_ebin_space(md->ebin,md->nTC,grpnms); sfree(*grpnms); } else if (etc == etcBERENDSEN || etc == etcYES || etc == etcVRESCALE) { for(i=0; (i<md->nTC); i++) { ni=groups->grps[egcTC].nm_ind[i]; sprintf(buf,"Lamb-%s",*(groups->grpname[ni])); grpnms[i]=strdup(buf); } md->itc=get_ebin_space(md->ebin,md->nTC,grpnms); sfree(*grpnms); } sfree(grpnms); md->nU=groups->grps[egcACC].nr; if (md->nU > 1) { snew(grpnms,3*md->nU); for(i=0; (i<md->nU); i++) { ni=groups->grps[egcACC].nm_ind[i]; sprintf(buf,"Ux-%s",*(groups->grpname[ni])); grpnms[3*i+XX]=strdup(buf); sprintf(buf,"Uy-%s",*(groups->grpname[ni])); grpnms[3*i+YY]=strdup(buf); sprintf(buf,"Uz-%s",*(groups->grpname[ni])); grpnms[3*i+ZZ]=strdup(buf); } md->iu=get_ebin_space(md->ebin,3*md->nU,grpnms); sfree(*grpnms); sfree(grpnms); } if (fp_ene != -1) do_enxnms(fp_ene,&md->ebin->nener,&md->ebin->enm); return md; }