void gmx_trr_read_single_frame(const char *fn, int *step, real *t, real *lambda, rvec *box, int *natoms, rvec *x, rvec *v, rvec *f) { t_fileio *fio = gmx_trr_open(fn, "r"); do_trr_frame(fio, true, step, t, lambda, box, natoms, x, v, f); gmx_trr_close(fio); }
void gmx_trr_write_single_frame(const char *fn, int step, real t, real lambda, rvec *box, int natoms, rvec *x, rvec *v, rvec *f) { t_fileio *fio = gmx_trr_open(fn, "w"); do_trr_frame(fio, false, &step, &t, &lambda, box, &natoms, x, v, f); gmx_trr_close(fio); }
void gmx_trr_read_single_header(const char *fn, gmx_trr_header_t *header) { t_fileio *fio = gmx_trr_open(fn, "r"); gmx_bool bOK; if (!do_trr_frame_header(fio, true, header, &bOK)) { gmx_fatal(FARGS, "Empty file %s", fn); } gmx_trr_close(fio); }
static void dump_dih_trr(int nframes, int nangles, real **dih, const char *fn, real *time) { int i, j, k, l, m, na; struct t_fileio *fio; rvec *x; matrix box = {{2, 0, 0}, {0, 2, 0}, {0, 0, 2}}; na = (nangles*2); if ((na % 3) != 0) { na = 1+na/3; } else { na = na/3; } printf("There are %d dihedrals. Will fill %d atom positions with cos/sin\n", nangles, na); snew(x, na); fio = gmx_trr_open(fn, "w"); for (i = 0; (i < nframes); i++) { k = l = 0; for (j = 0; (j < nangles); j++) { for (m = 0; (m < 2); m++) { // This is just because the compler and static-analyzer cannot // know that dih[j][i] is always valid. Since it occurs in the innermost // loop over angles and will only trigger on coding errors, we // only enable it for debug builds. GMX_ASSERT(dih != nullptr && dih[j] != nullptr, "Incorrect dihedral array data"); x[k][l] = (m == 0) ? std::cos(dih[j][i]) : std::sin(dih[j][i]); l++; if (l == DIM) { l = 0; k++; } } } gmx_trr_write_frame(fio, i, time[i], 0, box, na, x, nullptr, nullptr); } gmx_trr_close(fio); sfree(x); }
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; }
void read_eigenvectors(const char *file, int *natoms, gmx_bool *bFit, rvec **xref, gmx_bool *bDMR, rvec **xav, gmx_bool *bDMA, int *nvec, int **eignr, rvec ***eigvec, real **eigval) { gmx_trr_header_t head; int i, snew_size; struct t_fileio *status; rvec *x; matrix box; gmx_bool bOK; *bDMR = FALSE; /* read (reference (t=-1) and) average (t=0) structure */ status = gmx_trr_open(file, "r"); gmx_trr_read_frame_header(status, &head, &bOK); *natoms = head.natoms; snew(*xav, *natoms); gmx_trr_read_frame_data(status, &head, box, *xav, NULL, NULL); if ((head.t >= -1.1) && (head.t <= -0.9)) { snew(*xref, *natoms); for (i = 0; i < *natoms; i++) { copy_rvec((*xav)[i], (*xref)[i]); } *bDMR = (head.lambda > 0.5); *bFit = (head.lambda > -0.5); if (*bFit) { fprintf(stderr, "Read %smass weighted reference structure with %d atoms from %s\n", *bDMR ? "" : "non ", *natoms, file); } else { fprintf(stderr, "Eigenvectors in %s were determined without fitting\n", file); sfree(*xref); *xref = NULL; } gmx_trr_read_frame_header(status, &head, &bOK); gmx_trr_read_frame_data(status, &head, box, *xav, NULL, NULL); } else { *bFit = TRUE; *xref = NULL; } *bDMA = (head.lambda > 0.5); if ((head.t <= -0.01) || (head.t >= 0.01)) { fprintf(stderr, "WARNING: %s does not start with t=0, which should be the " "average structure. This might not be a eigenvector file. " "Some things might go wrong.\n", file); } else { fprintf(stderr, "Read %smass weighted average/minimum structure with %d atoms from %s\n", *bDMA ? "" : "non ", *natoms, file); } snew(x, *natoms); snew_size = 10; snew(*eignr, snew_size); snew(*eigval, snew_size); snew(*eigvec, snew_size); *nvec = 0; while (gmx_trr_read_frame_header(status, &head, &bOK)) { gmx_trr_read_frame_data(status, &head, box, x, NULL, NULL); if (*nvec >= snew_size) { snew_size += 10; srenew(*eignr, snew_size); srenew(*eigval, snew_size); srenew(*eigvec, snew_size); } i = head.step; (*eigval)[*nvec] = head.t; (*eignr)[*nvec] = i-1; snew((*eigvec)[*nvec], *natoms); for (i = 0; i < *natoms; i++) { copy_rvec(x[i], (*eigvec)[*nvec][i]); } (*nvec)++; } sfree(x); gmx_trr_close(status); fprintf(stderr, "Read %d eigenvectors (for %d atoms)\n\n", *nvec, *natoms); }
void write_eigenvectors(const char *trrname, int natoms, const real mat[], gmx_bool bReverse, int begin, int end, int WriteXref, const rvec *xref, gmx_bool bDMR, const rvec xav[], gmx_bool bDMA, const real eigval[]) { struct t_fileio *trrout; int ndim, i, j, d, vec; matrix zerobox; rvec *x; ndim = natoms*DIM; clear_mat(zerobox); snew(x, natoms); fprintf (stderr, "\nWriting %saverage structure & eigenvectors %d--%d to %s\n", (WriteXref == eWXR_YES) ? "reference, " : "", begin, end, trrname); trrout = gmx_trr_open(trrname, "w"); if (WriteXref == eWXR_YES) { /* misuse lambda: 0/1 mass weighted fit no/yes */ gmx_trr_write_frame(trrout, -1, -1, bDMR ? 1.0 : 0.0, zerobox, natoms, xref, NULL, NULL); } else if (WriteXref == eWXR_NOFIT) { /* misuse lambda: -1 no fit */ gmx_trr_write_frame(trrout, -1, -1, -1.0, zerobox, natoms, x, NULL, NULL); } /* misuse lambda: 0/1 mass weighted analysis no/yes */ gmx_trr_write_frame(trrout, 0, 0, bDMA ? 1.0 : 0.0, zerobox, natoms, xav, NULL, NULL); for (i = 0; i <= (end-begin); i++) { if (!bReverse) { vec = i; } else { vec = ndim-i-1; } for (j = 0; j < natoms; j++) { for (d = 0; d < DIM; d++) { x[j][d] = mat[vec*ndim+DIM*j+d]; } } /* Store the eigenvalue in the time field */ gmx_trr_write_frame(trrout, begin+i, eigval[vec], 0, zerobox, natoms, x, NULL, NULL); } gmx_trr_close(trrout); sfree(x); }
int gmx_convert_tpr(int argc, char *argv[]) { const char *desc[] = { "[THISMODULE] 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 [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]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; struct t_fileio *fp; ener_file_t fp_ener = NULL; gmx_trr_header_t head; int i; gmx_int64_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; 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]; gmx_output_env_t *oenv; t_filenm fnm[] = { { efTPR, NULL, NULL, ffREAD }, { efTRN, "-f", NULL, ffOPTRD }, { efEDR, "-e", NULL, ffOPTRD }, { efNDX, NULL, NULL, ffOPTRD }, { efTPR, "-o", "tprout", 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" }, }; /* 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); 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(efTPR, NFILE, fnm); fprintf(stderr, "Reading toplogy and stuff from %s\n", top_fn); snew(ir, 1); 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 (!EI_STATE_VELOCITY(ir->eI)) { bVel = FALSE; } if (bTraj) { fprintf(stderr, "\n" "NOTE: Reading the state from trajectory is an obsolete feature of gmx convert-tpr.\n" " Continuation should be done by loading a checkpoint file with mdrun -cpi\n" " This guarantees that all state variables are transferred.\n" " gmx convert-tpr 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" "gmx convert-tpr 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 %" GMX_PRId64 " ", ir->ld_seed); ir->ld_seed = (gmx_int64_t)gmx_rng_make_seed(); fprintf(stderr, "to %" GMX_PRId64 "\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 = gmx_trr_open(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 = gmx_trr_read_frame_header(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 = gmx_trr_read_frame_data(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_PRId64, "%6", GMX_PRId64, " %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); } gmx_trr_close(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_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 || 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(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; }
static void list_trr(const char *fn) { t_fileio *fpread; int nframe, indent; char buf[256]; rvec *x, *v, *f; matrix box; gmx_trr_header_t trrheader; gmx_bool bOK; fpread = gmx_trr_open(fn, "r"); nframe = 0; while (gmx_trr_read_frame_header(fpread, &trrheader, &bOK)) { snew(x, trrheader.natoms); snew(v, trrheader.natoms); snew(f, trrheader.natoms); if (gmx_trr_read_frame_data(fpread, &trrheader, trrheader.box_size ? box : NULL, trrheader.x_size ? x : NULL, trrheader.v_size ? v : NULL, trrheader.f_size ? f : NULL)) { sprintf(buf, "%s frame %d", fn, nframe); indent = 0; indent = pr_title(stdout, indent, buf); pr_indent(stdout, indent); fprintf(stdout, "natoms=%10d step=%10d time=%12.7e lambda=%10g\n", trrheader.natoms, trrheader.step, trrheader.t, trrheader.lambda); if (trrheader.box_size) { pr_rvecs(stdout, indent, "box", box, DIM); } if (trrheader.x_size) { pr_rvecs(stdout, indent, "x", x, trrheader.natoms); } if (trrheader.v_size) { pr_rvecs(stdout, indent, "v", v, trrheader.natoms); } if (trrheader.f_size) { pr_rvecs(stdout, indent, "f", f, trrheader.natoms); } } else { fprintf(stderr, "\nWARNING: Incomplete frame: nr %d, t=%g\n", nframe, trrheader.t); } sfree(x); sfree(v); sfree(f); nframe++; } if (!bOK) { fprintf(stderr, "\nWARNING: Incomplete frame header: nr %d, t=%g\n", nframe, trrheader.t); } gmx_trr_close(fpread); }