static void list_tng(const char gmx_unused *fn) { #ifdef GMX_USE_TNG tng_trajectory_t tng; gmx_int64_t nframe = 0; gmx_int64_t i, *block_ids = NULL, step, ndatablocks; gmx_bool bOK; gmx_tng_open(fn, 'r', &tng); gmx_print_tng_molecule_system(tng, stdout); bOK = gmx_get_tng_data_block_types_of_next_frame(tng, -1, 0, NULL, &step, &ndatablocks, &block_ids); do { for (i = 0; i < ndatablocks; i++) { double frame_time; real prec, *values = NULL; gmx_int64_t n_values_per_frame, n_atoms; char block_name[STRLEN]; gmx_get_tng_data_next_frame_of_block_type(tng, block_ids[i], &values, &step, &frame_time, &n_values_per_frame, &n_atoms, &prec, block_name, STRLEN, &bOK); if (!bOK) { /* Can't write any output because we don't know what arrays are valid. */ fprintf(stderr, "\nWARNING: Incomplete frame at time %g, will not write output\n", frame_time); } else { list_tng_inner(fn, (0 == i), values, step, frame_time, n_values_per_frame, n_atoms, prec, nframe, block_name); } } nframe++; } while (gmx_get_tng_data_block_types_of_next_frame(tng, step, 0, NULL, &step, &ndatablocks, &block_ids)); if (block_ids) { sfree(block_ids); } gmx_tng_close(&tng); #endif }
t_trxstatus * trjtools_gmx_prepare_tng_writing(const char *filename, char filemode, t_trxstatus *in, const char *infile, const int natoms, const gmx_mtop_t *mtop, gmx::ArrayRef<const int> index, const char *index_group_name) { if (filemode != 'w' && filemode != 'a') { gmx_incons("Sorry, can only prepare for TNG output."); } t_trxstatus *out; snew(out, 1); status_init(out); if (in != nullptr) { gmx_prepare_tng_writing(filename, filemode, &in->tng, &out->tng, natoms, mtop, index, index_group_name); } else if ((infile) && (efTNG == fn2ftp(infile))) { gmx_tng_trajectory_t tng_in; gmx_tng_open(infile, 'r', &tng_in); gmx_prepare_tng_writing(filename, filemode, &tng_in, &out->tng, natoms, mtop, index, index_group_name); } else { // we start from a file that is not a tng file or have been unable to load the // input file, so we need to populate the fields independently of it gmx_prepare_tng_writing(filename, filemode, nullptr, &out->tng, natoms, mtop, index, index_group_name); } return out; }
void trjtools_gmx_prepare_tng_writing(const char *filename, char filemode, t_trxstatus *in, t_trxstatus **out, const char *infile, const int natoms, const gmx_mtop_t *mtop, const int *index, const char *index_group_name) { if (filemode != 'w' && filemode != 'a') { gmx_incons("Sorry, can only prepare for TNG output."); } if (*out == nullptr) { snew((*out), 1); } status_init(*out); if (in != nullptr) { gmx_prepare_tng_writing(filename, filemode, &in->tng, &(*out)->tng, natoms, mtop, index, index_group_name); } else if (efTNG == fn2ftp(infile)) { tng_trajectory_t tng_in; gmx_tng_open(infile, 'r', &tng_in); gmx_prepare_tng_writing(filename, filemode, &tng_in, &(*out)->tng, natoms, mtop, index, index_group_name); } }
bool read_first_frame(const gmx_output_env_t *oenv, t_trxstatus **status, const char *fn, t_trxframe *fr, int flags) { t_fileio *fio = nullptr; gmx_bool bFirst, bOK; int ftp = fn2ftp(fn); clear_trxframe(fr, TRUE); bFirst = TRUE; snew((*status), 1); status_init( *status ); initcount(*status); (*status)->flags = flags; if (efTNG == ftp) { /* Special treatment for TNG files */ gmx_tng_open(fn, 'r', &(*status)->tng); } else { fio = (*status)->fio = gmx_fio_open(fn, "r"); } switch (ftp) { case efTRR: break; case efCPT: read_checkpoint_trxframe(fio, fr); bFirst = FALSE; break; case efG96: { /* Can not rewind a compressed file, so open it twice */ if (!(*status)->persistent_line) { /* allocate the persistent line */ snew((*status)->persistent_line, STRLEN+1); } t_symtab *symtab = nullptr; read_g96_conf(gmx_fio_getfp(fio), fn, nullptr, fr, symtab, (*status)->persistent_line); gmx_fio_close(fio); clear_trxframe(fr, FALSE); if (flags & (TRX_READ_X | TRX_NEED_X)) { snew(fr->x, fr->natoms); } if (flags & (TRX_READ_V | TRX_NEED_V)) { snew(fr->v, fr->natoms); } (*status)->fio = gmx_fio_open(fn, "r"); break; } case efXTC: if (read_first_xtc(fio, &fr->natoms, &fr->step, &fr->time, fr->box, &fr->x, &fr->prec, &bOK) == 0) { GMX_RELEASE_ASSERT(!bOK, "Inconsistent results - OK status from read_first_xtc, but 0 atom coords read"); fr->not_ok = DATA_NOT_OK; } if (fr->not_ok) { fr->natoms = 0; printincomp(*status, fr); } else { fr->bPrec = (fr->prec > 0); fr->bStep = TRUE; fr->bTime = TRUE; fr->bX = TRUE; fr->bBox = TRUE; printcount(*status, oenv, fr->time, FALSE); } bFirst = FALSE; break; case efTNG: fr->step = -1; if (!gmx_read_next_tng_frame((*status)->tng, fr, nullptr, 0)) { fr->not_ok = DATA_NOT_OK; fr->natoms = 0; printincomp(*status, fr); } else { printcount(*status, oenv, fr->time, FALSE); } bFirst = FALSE; break; case efPDB: pdb_first_x(*status, gmx_fio_getfp(fio), fr); if (fr->natoms) { printcount(*status, oenv, fr->time, FALSE); } bFirst = FALSE; break; case efGRO: if (gro_first_x_or_v(gmx_fio_getfp(fio), fr)) { printcount(*status, oenv, fr->time, FALSE); } bFirst = FALSE; break; default: #if GMX_USE_PLUGINS fprintf(stderr, "The file format of %s is not a known trajectory format to GROMACS.\n" "Please make sure that the file is a trajectory!\n" "GROMACS will now assume it to be a trajectory and will try to open it using the VMD plug-ins.\n" "This will only work in case the VMD plugins are found and it is a trajectory format supported by VMD.\n", fn); gmx_fio_fp_close(fio); /*only close the file without removing FIO entry*/ if (!read_first_vmd_frame(fn, &(*status)->vmdplugin, fr)) { gmx_fatal(FARGS, "Not supported in read_first_frame: %s", fn); } #else gmx_fatal(FARGS, "Not supported in read_first_frame: %s. Please make sure that the file is a trajectory.\n" "GROMACS is not compiled with plug-in support. Thus it cannot read non-GROMACS trajectory formats using the VMD plug-ins.\n" "Please compile with plug-in support if you want to read non-GROMACS trajectory formats.\n", fn); #endif break; } (*status)->tf = fr->time; /* Return FALSE if we read a frame that's past the set ending time. */ if (!bFirst && (!(flags & TRX_DONT_SKIP) && check_times(fr->time) > 0)) { (*status)->t0 = fr->time; return FALSE; } if (bFirst || (!(flags & TRX_DONT_SKIP) && check_times(fr->time) < 0)) { /* Read a frame when no frame was read or the first was skipped */ if (!read_next_frame(oenv, *status, fr)) { return FALSE; } } (*status)->t0 = fr->time; /* We need the number of atoms for random-access XTC searching, even when * we don't have access to the actual frame data. */ (*status)->natoms = fr->natoms; return (fr->natoms > 0); }
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 gmx_prepare_tng_writing(const char *filename, char mode, tng_trajectory_t *input, tng_trajectory_t *output, int nAtoms, const gmx_mtop_t *mtop, const int *index, const char *indexGroupName) { #if GMX_USE_TNG /* FIXME after 5.0: Currently only standard block types are read */ const int defaultNumIds = 5; static gmx_int64_t fallbackIds[defaultNumIds] = { TNG_TRAJ_BOX_SHAPE, TNG_TRAJ_POSITIONS, TNG_TRAJ_VELOCITIES, TNG_TRAJ_FORCES, TNG_GMX_LAMBDA }; static char fallbackNames[defaultNumIds][32] = { "BOX SHAPE", "POSITIONS", "VELOCITIES", "FORCES", "LAMBDAS" }; typedef tng_function_status (*set_writing_interval_func_pointer)(tng_trajectory_t, const gmx_int64_t, const gmx_int64_t, const gmx_int64_t, const char*, const char, const char); #if GMX_DOUBLE set_writing_interval_func_pointer set_writing_interval = tng_util_generic_write_interval_double_set; #else set_writing_interval_func_pointer set_writing_interval = tng_util_generic_write_interval_set; #endif gmx_tng_open(filename, mode, output); /* Do we have an input file in TNG format? If so, then there's more data we can copy over, rather than having to improvise. */ if (*input) { /* Set parameters (compression, time per frame, molecule * information, number of frames per frame set and writing * intervals of positions, box shape and lambdas) of the * output tng container based on their respective values int * the input tng container */ double time, compression_precision; gmx_int64_t n_frames_per_frame_set, interval = -1; tng_compression_precision_get(*input, &compression_precision); tng_compression_precision_set(*output, compression_precision); // TODO make this configurable in a future version char compression_type = TNG_TNG_COMPRESSION; tng_molecule_system_copy(*input, *output); tng_time_per_frame_get(*input, &time); tng_time_per_frame_set(*output, time); tng_num_frames_per_frame_set_get(*input, &n_frames_per_frame_set); tng_num_frames_per_frame_set_set(*output, n_frames_per_frame_set); for (int i = 0; i < defaultNumIds; i++) { if (tng_data_get_stride_length(*input, fallbackIds[i], -1, &interval) == TNG_SUCCESS) { switch (fallbackIds[i]) { case TNG_TRAJ_POSITIONS: case TNG_TRAJ_VELOCITIES: set_writing_interval(*output, interval, 3, fallbackIds[i], fallbackNames[i], TNG_PARTICLE_BLOCK_DATA, compression_type); break; case TNG_TRAJ_FORCES: set_writing_interval(*output, interval, 3, fallbackIds[i], fallbackNames[i], TNG_PARTICLE_BLOCK_DATA, TNG_GZIP_COMPRESSION); break; case TNG_TRAJ_BOX_SHAPE: set_writing_interval(*output, interval, 9, fallbackIds[i], fallbackNames[i], TNG_NON_PARTICLE_BLOCK_DATA, TNG_GZIP_COMPRESSION); break; case TNG_GMX_LAMBDA: set_writing_interval(*output, interval, 1, fallbackIds[i], fallbackNames[i], TNG_NON_PARTICLE_BLOCK_DATA, TNG_GZIP_COMPRESSION); default: continue; } } } } else { /* TODO after trjconv is modularized: fix this so the user can change precision when they are doing an operation where this makes sense, and not otherwise. char compression = bUseLossyCompression ? TNG_TNG_COMPRESSION : TNG_GZIP_COMPRESSION; gmx_tng_set_compression_precision(*output, ndec2prec(nDecimalsOfPrecision)); */ gmx_tng_add_mtop(*output, mtop); tng_num_frames_per_frame_set_set(*output, 1); } if (index && nAtoms > 0) { gmx_tng_setup_atom_subgroup(*output, nAtoms, index, indexGroupName); } /* If for some reason there are more requested atoms than there are atoms in the * molecular system create a number of implicit atoms (without atom data) to * compensate for that. */ if (nAtoms >= 0) { tng_implicit_num_particles_set(*output, nAtoms); } #else GMX_UNUSED_VALUE(filename); GMX_UNUSED_VALUE(mode); GMX_UNUSED_VALUE(input); GMX_UNUSED_VALUE(output); GMX_UNUSED_VALUE(nAtoms); GMX_UNUSED_VALUE(mtop); GMX_UNUSED_VALUE(index); GMX_UNUSED_VALUE(indexGroupName); #endif }