/* Read in the tpr file and save information we need later in info */ static void read_tpr_file(const char *fn_sim_tpr, t_inputinfo *info, t_state *state, gmx_mtop_t *mtop, t_inputrec *ir, real user_beta, real fracself) { read_tpx_state(fn_sim_tpr,ir,state,NULL,mtop); /* The values of the original tpr input file are save in the first * place [0] of the arrays */ info->orig_sim_steps = ir->nsteps; info->pme_order[0] = ir->pme_order; info->rcoulomb[0] = ir->rcoulomb; info->rvdw[0] = ir->rvdw; info->nkx[0] = ir->nkx; info->nky[0] = ir->nky; info->nkz[0] = ir->nkz; info->ewald_rtol[0] = ir->ewald_rtol; info->fracself = fracself; if (user_beta > 0) info->ewald_beta[0] = user_beta; else info->ewald_beta[0] = calc_ewaldcoeff(info->rcoulomb[0],info->ewald_rtol[0]); /* Check if PME was chosen */ if (EEL_PME(ir->coulombtype) == FALSE) gmx_fatal(FARGS, "Can only do optimizations for simulations with PME"); /* Check if rcoulomb == rlist, which is necessary for PME */ if (!(ir->rcoulomb == ir->rlist)) gmx_fatal(FARGS, "PME requires rcoulomb (%f) to be equal to rlist (%f).", ir->rcoulomb, ir->rlist); }
static void comp_tpx(const char *fn1, const char *fn2, gmx_bool bRMSD, real ftol, real abstol) { const char *ff[2]; gmx::MDModules mdModules[2]; t_inputrec *ir[2] = { mdModules[0].inputrec(), mdModules[1].inputrec() }; t_state state[2]; gmx_mtop_t mtop[2]; t_topology top[2]; int i; ff[0] = fn1; ff[1] = fn2; for (i = 0; i < (fn2 ? 2 : 1); i++) { read_tpx_state(ff[i], ir[i], &state[i], &(mtop[i])); } if (fn2) { cmp_inputrec(stdout, ir[0], ir[1], ftol, abstol); /* Convert gmx_mtop_t to t_topology. * We should implement direct mtop comparison, * but it might be useful to keep t_topology comparison as an option. */ top[0] = gmx_mtop_t_to_t_topology(&mtop[0], false); top[1] = gmx_mtop_t_to_t_topology(&mtop[1], false); cmp_top(stdout, &top[0], &top[1], ftol, abstol); cmp_groups(stdout, &mtop[0].groups, &mtop[1].groups, mtop[0].natoms, mtop[1].natoms); comp_state(&state[0], &state[1], bRMSD, ftol, abstol); } else { if (ir[0]->efep == efepNO) { fprintf(stdout, "inputrec->efep = %s\n", efep_names[ir[0]->efep]); } else { if (ir[0]->bPull) { comp_pull_AB(stdout, ir[0]->pull, ftol, abstol); } /* Convert gmx_mtop_t to t_topology. * We should implement direct mtop comparison, * but it might be useful to keep t_topology comparison as an option. */ top[0] = gmx_mtop_t_to_t_topology(&mtop[0], true); cmp_top(stdout, &top[0], NULL, ftol, abstol); } } }
void init_single(FILE *fplog,t_inputrec *inputrec, char *tpxfile,gmx_mtop_t *mtop, t_state *state) { int step; real t; read_tpx_state(tpxfile,&step,&t,inputrec,state,NULL,mtop); set_state_entries(state,inputrec,1); if (fplog) pr_inputrec(fplog,0,"Input Parameters",inputrec,FALSE); }
static void tpx2methods(const char *tpx, const char *tex) { FILE *fp; t_inputrec ir; t_state state; gmx_mtop_t mtop; read_tpx_state(tpx, &ir, &state, &mtop); fp = gmx_fio_fopen(tex, "w"); fprintf(fp, "\\section{Methods}\n"); tpx2system(fp, &mtop); tpx2params(fp, &ir); gmx_fio_fclose(fp); }
void init_parallel(FILE *log,char *tpxfile,t_commrec *cr, t_inputrec *inputrec,gmx_mtop_t *mtop, t_state *state, int list) { int step; real t; char buf[256]; if (MASTER(cr)) { init_inputrec(inputrec); read_tpx_state(tpxfile,&step,&t,inputrec,state,NULL,mtop); /* When we will be doing domain decomposition with separate PME nodes * the rng entries will be too large, we correct for this later. */ set_state_entries(state,inputrec,cr->nnodes); } bcast_ir_mtop(cr,inputrec,mtop); if (inputrec->eI == eiBD || EI_SD(inputrec->eI)) { /* Make sure the random seeds are different on each node */ inputrec->ld_seed += cr->nodeid; } /* Printing */ if (list!=0 && log!=NULL) { if (list&LIST_INPUTREC) pr_inputrec(log,0,"parameters of the run",inputrec,FALSE); if (list&LIST_X) pr_rvecs(log,0,"box",state->box,DIM); if (list&LIST_X) pr_rvecs(log,0,"box_rel",state->box_rel,DIM); if (list&LIST_V) pr_rvecs(log,0,"boxv",state->boxv,DIM); if (list&LIST_X) pr_rvecs(log,0,int_title("x",0,buf,255),state->x,state->natoms); if (list&LIST_V) pr_rvecs(log,0,int_title("v",0,buf,255),state->v,state->natoms); if (list&LIST_TOP) pr_mtop(log,0,int_title("topology",cr->nodeid,buf,255),mtop,TRUE); fflush(log); } }
static void list_tpx(const char *fn, gmx_bool bShowNumbers, const char *mdpfn, gmx_bool bSysTop) { FILE *gp; int fp, indent, i, j, **gcount, atot; t_state state; rvec *f = NULL; t_inputrec ir; t_tpxheader tpx; gmx_mtop_t mtop; gmx_groups_t *groups; t_topology top; read_tpxheader(fn, &tpx, TRUE, NULL, NULL); read_tpx_state(fn, tpx.bIr ? &ir : NULL, &state, tpx.bF ? f : NULL, tpx.bTop ? &mtop : NULL); if (mdpfn && tpx.bIr) { gp = gmx_fio_fopen(mdpfn, "w"); pr_inputrec(gp, 0, NULL, &(ir), TRUE); gmx_fio_fclose(gp); } if (!mdpfn) { if (bSysTop) { top = gmx_mtop_t_to_t_topology(&mtop); } if (available(stdout, &tpx, 0, fn)) { indent = 0; indent = pr_title(stdout, indent, fn); pr_inputrec(stdout, 0, "inputrec", tpx.bIr ? &(ir) : NULL, FALSE); indent = 0; pr_header(stdout, indent, "header", &(tpx)); if (!bSysTop) { pr_mtop(stdout, indent, "topology", &(mtop), bShowNumbers); } else { pr_top(stdout, indent, "topology", &(top), bShowNumbers); } pr_rvecs(stdout, indent, "box", tpx.bBox ? state.box : NULL, DIM); pr_rvecs(stdout, indent, "box_rel", tpx.bBox ? state.box_rel : NULL, DIM); pr_rvecs(stdout, indent, "boxv", tpx.bBox ? state.boxv : NULL, DIM); pr_rvecs(stdout, indent, "pres_prev", tpx.bBox ? state.pres_prev : NULL, DIM); pr_rvecs(stdout, indent, "svir_prev", tpx.bBox ? state.svir_prev : NULL, DIM); pr_rvecs(stdout, indent, "fvir_prev", tpx.bBox ? state.fvir_prev : NULL, DIM); /* leave nosehoover_xi in for now to match the tpr version */ pr_doubles(stdout, indent, "nosehoover_xi", state.nosehoover_xi, state.ngtc); /*pr_doubles(stdout,indent,"nosehoover_vxi",state.nosehoover_vxi,state.ngtc);*/ /*pr_doubles(stdout,indent,"therm_integral",state.therm_integral,state.ngtc);*/ pr_rvecs(stdout, indent, "x", tpx.bX ? state.x : NULL, state.natoms); pr_rvecs(stdout, indent, "v", tpx.bV ? state.v : NULL, state.natoms); if (tpx.bF) { pr_rvecs(stdout, indent, "f", f, state.natoms); } } groups = &mtop.groups; snew(gcount, egcNR); for (i = 0; (i < egcNR); i++) { snew(gcount[i], groups->grps[i].nr); } for (i = 0; (i < mtop.natoms); i++) { for (j = 0; (j < egcNR); j++) { gcount[j][ggrpnr(groups, j, i)]++; } } printf("Group statistics\n"); for (i = 0; (i < egcNR); i++) { atot = 0; printf("%-12s: ", gtypes[i]); for (j = 0; (j < groups->grps[i].nr); j++) { printf(" %5d", gcount[i][j]); atot += gcount[i][j]; } printf(" (total %d atoms)\n", atot); sfree(gcount[i]); } sfree(gcount); } done_state(&state); sfree(f); }
void chk_trj(const output_env_t oenv, const char *fn, const char *tpr, real tol) { t_trxframe fr; t_count count; t_fr_time first, last; int j = -1, new_natoms, natoms; real rdum, tt, old_t1, old_t2, prec; gmx_bool bShowTimestep = TRUE, bOK, newline = FALSE; t_trxstatus *status; gmx_mtop_t mtop; gmx_localtop_t *top = NULL; t_state state; t_inputrec ir; if (tpr) { read_tpx_state(tpr, &ir, &state, NULL, &mtop); top = gmx_mtop_generate_local_top(&mtop, &ir); } new_natoms = -1; natoms = -1; printf("Checking file %s\n", fn); j = 0; old_t2 = -2.0; old_t1 = -1.0; count.bStep = 0; count.bTime = 0; count.bLambda = 0; count.bX = 0; count.bV = 0; count.bF = 0; count.bBox = 0; first.bStep = 0; first.bTime = 0; first.bLambda = 0; first.bX = 0; first.bV = 0; first.bF = 0; first.bBox = 0; last.bStep = 0; last.bTime = 0; last.bLambda = 0; last.bX = 0; last.bV = 0; last.bF = 0; last.bBox = 0; read_first_frame(oenv, &status, fn, &fr, TRX_READ_X | TRX_READ_V | TRX_READ_F); do { if (j == 0) { fprintf(stderr, "\n# Atoms %d\n", fr.natoms); if (fr.bPrec) { fprintf(stderr, "Precision %g (nm)\n", 1/fr.prec); } } newline = TRUE; if ((natoms > 0) && (new_natoms != natoms)) { fprintf(stderr, "\nNumber of atoms at t=%g don't match (%d, %d)\n", old_t1, natoms, new_natoms); newline = FALSE; } if (j >= 2) { if (fabs((fr.time-old_t1)-(old_t1-old_t2)) > 0.1*(fabs(fr.time-old_t1)+fabs(old_t1-old_t2)) ) { bShowTimestep = FALSE; fprintf(stderr, "%sTimesteps at t=%g don't match (%g, %g)\n", newline ? "\n" : "", old_t1, old_t1-old_t2, fr.time-old_t1); } } natoms = new_natoms; if (tpr) { chk_bonds(&top->idef, ir.ePBC, fr.x, fr.box, tol); } if (fr.bX) { chk_coords(j, natoms, fr.x, fr.box, 1e5, tol); } if (fr.bV) { chk_vels(j, natoms, fr.v); } if (fr.bF) { chk_forces(j, natoms, fr.f); } old_t2 = old_t1; old_t1 = fr.time; j++; new_natoms = fr.natoms; #define INC(s, n, f, l, item) if (s.item != 0) { if (n.item == 0) { first.item = fr.time; } last.item = fr.time; n.item++; \ } INC(fr, count, first, last, bStep); INC(fr, count, first, last, bTime); INC(fr, count, first, last, bLambda); INC(fr, count, first, last, bX); INC(fr, count, first, last, bV); INC(fr, count, first, last, bF); INC(fr, count, first, last, bBox); #undef INC } while (read_next_frame(oenv, status, &fr)); fprintf(stderr, "\n"); close_trj(status); fprintf(stderr, "\nItem #frames"); if (bShowTimestep) { fprintf(stderr, " Timestep (ps)"); } fprintf(stderr, "\n"); #define PRINTITEM(label, item) fprintf(stderr, "%-10s %6d", label, count.item); if ((bShowTimestep) && (count.item > 1)) {fprintf(stderr, " %g\n", (last.item-first.item)/(count.item-1)); }else fprintf(stderr, "\n") PRINTITEM ( "Step", bStep ); PRINTITEM ( "Time", bTime ); PRINTITEM ( "Lambda", bLambda ); PRINTITEM ( "Coords", bX ); PRINTITEM ( "Velocities", bV ); PRINTITEM ( "Forces", bF ); PRINTITEM ( "Box", bBox ); }
int cmain (int argc, char *argv[]) { const char *desc[] = { "tpbconv can edit run input files in four ways.[PAR]", "[BB]1.[bb] by modifying the number of steps in a run input file", "with options [TT]-extend[tt], [TT]-until[tt] or [TT]-nsteps[tt]", "(nsteps=-1 means unlimited number of steps)[PAR]", "[BB]2.[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.", "[BB]Note[bb] 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]3.[bb] by creating a [TT].tpx[tt] file for a subset of your original", "tpx file, which is useful when you want to remove the solvent from", "your [TT].tpx[tt] file, or when you want to make e.g. a pure C[GRK]alpha[grk] [TT].tpx[tt] file.", "Note that you may need to use [TT]-nsteps -1[tt] (or similar) to get", "this to work.", "[BB]WARNING: this [TT].tpx[tt] file is not fully functional[bb].[PAR]", "[BB]4.[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." }; const char *top_fn, *frame_fn; t_fileio *fp; ener_file_t fp_ener = NULL; t_trnheader head; int i; gmx_large_int_t nsteps_req, run_step, frame; double run_t, state_t; gmx_bool bOK, bNsteps, bExtend, bUntil, bTime, bTraj; gmx_bool bFrame, bUse, bSel, bNeedEner, bReadEner, bScanEner, bFepState; 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; gmx_enxnm_t *enm = NULL; t_enxframe *fr_ener = NULL; char buf[200], buf2[200]; output_env_t oenv; t_filenm fnm[] = { { efTPX, NULL, NULL, ffREAD }, { efTRN, "-f", NULL, ffOPTRD }, { efEDR, "-e", NULL, ffOPTRD }, { efNDX, NULL, NULL, ffOPTRD }, { efTPX, "-o", "tpxout", ffWRITE } }; #define NFILE asize(fnm) /* Command line options */ static int nsteps_req_int = 0; static real start_t = -1.0, extend_t = 0.0, until_t = 0.0; static int init_fep_state = 0; static gmx_bool bContinuation = TRUE, bZeroQ = FALSE, bVel = TRUE; static t_pargs pa[] = { { "-extend", FALSE, etREAL, {&extend_t}, "Extend runtime by this amount (ps)" }, { "-until", FALSE, etREAL, {&until_t}, "Extend runtime until this ending time (ps)" }, { "-nsteps", FALSE, etINT, {&nsteps_req_int}, "Change the number of steps" }, { "-time", FALSE, etREAL, {&start_t}, "Continue from frame at this time (ps) instead of the last frame" }, { "-zeroq", FALSE, etBOOL, {&bZeroQ}, "Set the charges of a group (from the index) to zero" }, { "-vel", FALSE, etBOOL, {&bVel}, "Require velocities from trajectory" }, { "-cont", FALSE, etBOOL, {&bContinuation}, "For exact continuation, the constraints should not be applied before the first step" }, { "-init_fep_state", FALSE, etINT, {&init_fep_state}, "fep state to initialize from" }, }; int nerror = 0; CopyRight(stderr, argv[0]); /* Parse the command line */ parse_common_args(&argc, argv, 0, NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, NULL, &oenv); /* Convert int to gmx_large_int_t */ nsteps_req = nsteps_req_int; bNsteps = opt2parg_bSet("-nsteps", asize(pa), pa); bExtend = opt2parg_bSet("-extend", asize(pa), pa); bUntil = opt2parg_bSet("-until", asize(pa), pa); bFepState = opt2parg_bSet("-init_fep_state", 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 stuff from %s\n", top_fn); snew(ir, 1); read_tpx_state(top_fn, ir, &state, NULL, &mtop); run_step = ir->init_step; run_t = ir->init_step*ir->delta_t + ir->init_t; if (!EI_STATE_VELOCITY(ir->eI)) { bVel = FALSE; } if (bTraj) { fprintf(stderr, "\n" "NOTE: Reading the state from trajectory is an obsolete feature 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(efEDR, 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); if (fn2ftp(frame_fn) == efCPT) { int sim_part; fprintf(stderr, "\nREADING STATE FROM CHECKPOINT %s...\n\n", frame_fn); read_checkpoint_state(frame_fn, &sim_part, &run_step, &run_t, &state); } else { 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(efEDR, 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 || !bVel)) { 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.fep_state = head.fep_state; state.lambda[efptFEP] = head.lambda; copy_mat(newbox, state.box); } } if (bFrame || !bOK) { sprintf(buf, "\r%s %s frame %s%s: step %s%s time %s", "%s", "%s", "%6", gmx_large_int_fmt, "%6", gmx_large_int_fmt, " %8.3f"); fprintf(stderr, buf, 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); free_enxnms(nre, enm); } close_trn(fp); fprintf(stderr, "\n"); if (!bOK) { fprintf(stderr, "%s frame %s (step %s, time %g) is incomplete\n", ftp2ext(fn2ftp(frame_fn)), gmx_step_str(frame-1, buf2), gmx_step_str(head.step, buf), head.t); } fprintf(stderr, "\nUsing frame of step %s time %g\n", gmx_step_str(run_step, buf), run_t); if (bNeedEner) { if (bReadEner) { get_enx_state(ftp2fn(efEDR, 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 (bFepState) { ir->fepvals->init_fep_state = init_fep_state; } } } if (bNsteps) { fprintf(stderr, "Setting nsteps to %s\n", gmx_step_str(nsteps_req, buf)); ir->nsteps = nsteps_req; } else { /* Determine total number of steps remaining */ if (bExtend) { ir->nsteps = ir->nsteps - (run_step - ir->init_step) + (gmx_large_int_t)(extend_t/ir->delta_t + 0.5); printf("Extending remaining runtime of by %g ps (now %s steps)\n", extend_t, gmx_step_str(ir->nsteps, buf)); } else if (bUntil) { printf("nsteps = %s, run_step = %s, current_t = %g, until = %g\n", gmx_step_str(ir->nsteps, buf), gmx_step_str(run_step, buf2), run_t, until_t); ir->nsteps = (gmx_large_int_t)((until_t - run_t)/ir->delta_t + 0.5); printf("Extending remaining runtime until %g ps (now %s steps)\n", until_t, gmx_step_str(ir->nsteps, buf)); } else { ir->nsteps -= run_step - ir->init_step; /* Print message */ printf("%s steps (%g ps) remaining from first run.\n", gmx_step_str(ir->nsteps, buf), 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; sprintf(buf, "Writing statusfile with starting step %s%s and length %s%s steps...\n", "%10", gmx_large_int_fmt, "%10", gmx_large_int_fmt); fprintf(stderr, buf, 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), ir, &state, &mtop); } else { printf("You've simulated long enough. Not writing tpr file\n"); } thanx(stderr); return 0; }
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; }
// works void test1() { const char *intopol = "../topol.tpr", *incpt = "../state0.cpt", *outtopol = "../new.tpr"; const unsigned int seed = 42; // read the header t_tpxheader header; int version, generation; read_tpxheader(intopol, &header, FALSE, &version, &generation); // decide if forces can be read from tpr rvec *forces; if (header.bF) { snew(forces, 1); } else { forces = NULL; } // read the topology file t_inputrec ir; t_state topol_state; gmx_mtop_t mtop; init_inputrec(&ir); init_state(&topol_state, -1, -1, -1, -1); init_mtop(&mtop); read_tpx_state(intopol, &ir, &topol_state, forces, &mtop); // read the checkpoint int sim_part; gmx_large_int_t step; double time; t_state cpt_state; t_commrec comm; init_state(&cpt_state, -1, -1, -1, -1); printf("Opening %s for reading\n", incpt); read_checkpoint_state(incpt, &sim_part, &step, &time, &cpt_state); printf("ld_rng = %d\n", (int) cpt_state.ld_rng); printf("ld_rngi = %d\n" , (int) cpt_state.ld_rngi); // update the state to be written /* gmx_rng_t rng = gmx_rng_init(seed); */ /* unsigned int rng_state, rng_index; */ /* gmx_rng_get_state(rng, &rng_state, &rng_index); */ ir.ld_seed = 42; ir.init_t = time; ir.init_step = step; ir.init_lambda = cpt_state.lambda; /* // write the new tpr */ /* write_tpx_state(outtopol, */ /* &ir, &cpt_state, &mtop); */ }
int gmx_convert_tpr(int argc, char *argv[]) { const char *desc[] = { "[THISMODULE] can edit run input files in three ways.[PAR]", "[BB]1.[bb] by modifying the number of steps in a run input file", "with options [TT]-extend[tt], [TT]-until[tt] or [TT]-nsteps[tt]", "(nsteps=-1 means unlimited number of steps)[PAR]", "[BB]2.[bb] by creating a [REF].tpx[ref] file for a subset of your original", "tpx file, which is useful when you want to remove the solvent from", "your [REF].tpx[ref] file, or when you want to make e.g. a pure C[GRK]alpha[grk] [REF].tpx[ref] file.", "Note that you may need to use [TT]-nsteps -1[tt] (or similar) to get", "this to work.", "[BB]WARNING: this [REF].tpx[ref] file is not fully functional[bb].[PAR]", "[BB]3.[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." }; const char *top_fn; int i; gmx_int64_t nsteps_req, run_step; double run_t, state_t; gmx_bool bSel; gmx_bool bNsteps, bExtend, bUntil; gmx_mtop_t mtop; t_atoms atoms; t_inputrec *ir; t_state state; int gnx; char *grpname; int *index = NULL; char buf[200], buf2[200]; gmx_output_env_t *oenv; t_filenm fnm[] = { { efTPR, NULL, NULL, ffREAD }, { efNDX, NULL, NULL, ffOPTRD }, { efTPR, "-o", "tprout", ffWRITE } }; #define NFILE asize(fnm) /* Command line options */ static int nsteps_req_int = 0; static real extend_t = 0.0, until_t = 0.0; static gmx_bool bZeroQ = FALSE; static t_pargs pa[] = { { "-extend", FALSE, etREAL, {&extend_t}, "Extend runtime by this amount (ps)" }, { "-until", FALSE, etREAL, {&until_t}, "Extend runtime until this ending time (ps)" }, { "-nsteps", FALSE, etINT, {&nsteps_req_int}, "Change the number of steps" }, { "-zeroq", FALSE, etBOOL, {&bZeroQ}, "Set the charges of a group (from the index) to zero" } }; /* Parse the command line */ if (!parse_common_args(&argc, argv, 0, NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, NULL, &oenv)) { return 0; } /* Convert int to gmx_int64_t */ nsteps_req = nsteps_req_int; bNsteps = opt2parg_bSet("-nsteps", asize(pa), pa); bExtend = opt2parg_bSet("-extend", asize(pa), pa); bUntil = opt2parg_bSet("-until", asize(pa), pa); top_fn = ftp2fn(efTPR, NFILE, fnm); fprintf(stderr, "Reading toplogy and stuff from %s\n", top_fn); gmx::MDModules mdModules; ir = mdModules.inputrec(); read_tpx_state(top_fn, ir, &state, &mtop); run_step = ir->init_step; run_t = ir->init_step*ir->delta_t + ir->init_t; if (bNsteps) { fprintf(stderr, "Setting nsteps to %s\n", gmx_step_str(nsteps_req, buf)); ir->nsteps = nsteps_req; } else { /* Determine total number of steps remaining */ if (bExtend) { ir->nsteps = ir->nsteps - (run_step - ir->init_step) + (gmx_int64_t)(extend_t/ir->delta_t + 0.5); printf("Extending remaining runtime of by %g ps (now %s steps)\n", extend_t, gmx_step_str(ir->nsteps, buf)); } else if (bUntil) { printf("nsteps = %s, run_step = %s, current_t = %g, until = %g\n", gmx_step_str(ir->nsteps, buf), gmx_step_str(run_step, buf2), run_t, until_t); ir->nsteps = (gmx_int64_t)((until_t - run_t)/ir->delta_t + 0.5); printf("Extending remaining runtime until %g ps (now %s steps)\n", until_t, gmx_step_str(ir->nsteps, buf)); } else { ir->nsteps -= run_step - ir->init_step; /* Print message */ printf("%s steps (%g ps) remaining from first run.\n", gmx_step_str(ir->nsteps, buf), ir->nsteps*ir->delta_t); } } if (bNsteps || bZeroQ || (ir->nsteps > 0)) { ir->init_step = run_step; if (ftp2bSet(efNDX, NFILE, fnm) || !(bNsteps || bExtend || bUntil)) { 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, as_rvec_array(state.x.data()), as_rvec_array(state.v.data())); state.natoms = gnx; } else if (bZeroQ) { zeroq(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; sprintf(buf, "Writing statusfile with starting step %s%s and length %s%s steps...\n", "%10", GMX_PRId64, "%10", GMX_PRId64); fprintf(stderr, buf, 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), ir, &state, &mtop); } else { printf("You've simulated long enough. Not writing tpr file\n"); } return 0; }