From 3b95736813d66d69aab2da234b99807020e61da3 Mon Sep 17 00:00:00 2001 From: Magnus Lundborg Date: Thu, 26 Nov 2015 11:50:59 +0100 Subject: [PATCH] Write forces and velocities to compressed TNG. If there is no uncompressed coordinate output write forces and velocities to the TNG file with compressed coordinate output. If there is uncompressed coordinate output to a TNG file forces and velocities will be written to it. Use a greatest common divisor to set the frequency of some TNG data output to ensure lambdas and box shape are written at least as often as anything else. This commit closes #1863. Change-Id: I61bb5513f5080847f9098ff4fd7f01c8d1415a8f --- src/gromacs/fileio/tngio.cpp | 123 +++++++++++++++++------------------ src/gromacs/mdlib/mdoutf.cpp | 81 ++++++++++++++--------- 2 files changed, 110 insertions(+), 94 deletions(-) diff --git a/src/gromacs/fileio/tngio.cpp b/src/gromacs/fileio/tngio.cpp index 7976fdbe3d..cf21019a55 100644 --- a/src/gromacs/fileio/tngio.cpp +++ b/src/gromacs/fileio/tngio.cpp @@ -372,7 +372,7 @@ static void set_writing_intervals(tng_trajectory_t tng, set_writing_interval_func_pointer set_writing_interval = tng_util_generic_write_interval_set; #endif int xout, vout, fout; -// int gcd = -1, lowest = -1; + int gcd = -1, lowest = -1; char compression; tng_set_frames_per_frame_set(tng, bUseLossyCompression, ir); @@ -380,8 +380,19 @@ static void set_writing_intervals(tng_trajectory_t tng, if (bUseLossyCompression) { xout = ir->nstxout_compressed; - vout = 0; - fout = 0; + + /* If there is no uncompressed coordinate output write forces + and velocities to the compressed tng file. */ + if (ir->nstxout) + { + vout = 0; + fout = 0; + } + else + { + vout = ir->nstvout; + fout = ir->nstfout; + } compression = TNG_TNG_COMPRESSION; } else @@ -396,34 +407,17 @@ static void set_writing_intervals(tng_trajectory_t tng, set_writing_interval(tng, xout, 3, TNG_TRAJ_POSITIONS, "POSITIONS", TNG_PARTICLE_BLOCK_DATA, compression); - /* The design of TNG makes it awkward to try to write a box - * with multiple periodicities, which might be co-prime. Since - * the use cases for the box with a frame consisting only of - * velocities seem low, for now we associate box writing with - * position writing. */ - set_writing_interval(tng, xout, 9, TNG_TRAJ_BOX_SHAPE, - "BOX SHAPE", TNG_NON_PARTICLE_BLOCK_DATA, - TNG_GZIP_COMPRESSION); /* TODO: if/when we write energies to TNG also, reconsider how * and when box information is written, because GROMACS * behaviour pre-5.0 was to write the box with every * trajectory frame and every energy frame, and probably * people depend on this. */ - /* TODO: If we need to write lambda values at steps when - * positions (or other data) are not also being written, then - * code in mdoutf.c will need to match however that is - * organized here. */ - set_writing_interval(tng, xout, 1, TNG_GMX_LAMBDA, - "LAMBDAS", TNG_NON_PARTICLE_BLOCK_DATA, - TNG_GZIP_COMPRESSION); - - /* FIXME: gcd and lowest currently not used. */ -// gcd = greatest_common_divisor_if_positive(gcd, xout); -// if (lowest < 0 || xout < lowest) -// { -// lowest = xout; -// } + gcd = greatest_common_divisor_if_positive(gcd, xout); + if (lowest < 0 || xout < lowest) + { + lowest = xout; + } } if (vout) { @@ -431,12 +425,11 @@ static void set_writing_intervals(tng_trajectory_t tng, "VELOCITIES", TNG_PARTICLE_BLOCK_DATA, compression); - /* FIXME: gcd and lowest currently not used. */ -// gcd = greatest_common_divisor_if_positive(gcd, vout); -// if (lowest < 0 || vout < lowest) -// { -// lowest = vout; -// } + gcd = greatest_common_divisor_if_positive(gcd, vout); + if (lowest < 0 || vout < lowest) + { + lowest = vout; + } } if (fout) { @@ -444,29 +437,30 @@ static void set_writing_intervals(tng_trajectory_t tng, "FORCES", TNG_PARTICLE_BLOCK_DATA, TNG_GZIP_COMPRESSION); - /* FIXME: gcd and lowest currently not used. */ -// gcd = greatest_common_divisor_if_positive(gcd, fout); -// if (lowest < 0 || fout < lowest) -// { -// lowest = fout; -// } - } - /* FIXME: See above. gcd interval for lambdas is disabled. */ -// if (gcd > 0) -// { -// /* Lambdas written at an interval of the lowest common denominator -// * of other output */ -// set_writing_interval(tng, gcd, 1, TNG_GMX_LAMBDA, -// "LAMBDAS", TNG_NON_PARTICLE_BLOCK_DATA, -// TNG_GZIP_COMPRESSION); -// -// if (gcd < lowest / 10) -// { -// gmx_warning("The lowest common denominator of trajectory output is " -// "every %d step(s), whereas the shortest output interval " -// "is every %d steps.", gcd, lowest); -// } -// } + gcd = greatest_common_divisor_if_positive(gcd, fout); + if (lowest < 0 || fout < lowest) + { + lowest = fout; + } + } + if (gcd > 0) + { + /* Lambdas and box shape written at an interval of the lowest common + denominator of other output */ + set_writing_interval(tng, gcd, 1, TNG_GMX_LAMBDA, + "LAMBDAS", TNG_NON_PARTICLE_BLOCK_DATA, + TNG_GZIP_COMPRESSION); + + set_writing_interval(tng, gcd, 9, TNG_TRAJ_BOX_SHAPE, + "BOX SHAPE", TNG_NON_PARTICLE_BLOCK_DATA, + TNG_GZIP_COMPRESSION); + if (gcd < lowest / 10) + { + gmx_warning("The lowest common denominator of trajectory output is " + "every %d step(s), whereas the shortest output interval " + "is every %d steps.", gcd, lowest); + } + } } #endif @@ -782,16 +776,6 @@ void gmx_fwrite_tng(tng_trajectory_t tng, { gmx_file("Cannot write TNG trajectory frame; maybe you are out of disk space?"); } - /* TNG-MF1 compression only compresses positions and velocities. Use lossless - * compression for box shape regardless of output mode */ - if (write_data(tng, step, elapsedSeconds, - reinterpret_cast(box), - 9, TNG_TRAJ_BOX_SHAPE, "BOX SHAPE", - TNG_NON_PARTICLE_BLOCK_DATA, - TNG_GZIP_COMPRESSION) != TNG_SUCCESS) - { - gmx_file("Cannot write TNG trajectory frame; maybe you are out of disk space?"); - } } if (v) @@ -821,7 +805,16 @@ void gmx_fwrite_tng(tng_trajectory_t tng, } /* TNG-MF1 compression only compresses positions and velocities. Use lossless - * compression for lambdas regardless of output mode */ + * compression for lambdas and box shape regardless of output mode */ + if (write_data(tng, step, elapsedSeconds, + reinterpret_cast(box), + 9, TNG_TRAJ_BOX_SHAPE, "BOX SHAPE", + TNG_NON_PARTICLE_BLOCK_DATA, + TNG_GZIP_COMPRESSION) != TNG_SUCCESS) + { + gmx_file("Cannot write TNG trajectory frame; maybe you are out of disk space?"); + } + if (write_data(tng, step, elapsedSeconds, reinterpret_cast(&lambda), 1, TNG_GMX_LAMBDA, "LAMBDAS", diff --git a/src/gromacs/mdlib/mdoutf.cpp b/src/gromacs/mdlib/mdoutf.cpp index df1ef1f409..96b6bd6528 100644 --- a/src/gromacs/mdlib/mdoutf.cpp +++ b/src/gromacs/mdlib/mdoutf.cpp @@ -112,6 +112,28 @@ gmx_mdoutf_t init_mdoutf(FILE *fplog, int nfile, const t_filenm fnm[], sprintf(filemode, bAppendFiles ? "a+" : "w+"); + 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)) #ifndef GMX_FAHCORE && @@ -128,7 +150,14 @@ gmx_mdoutf_t init_mdoutf(FILE *fplog, int nfile, const t_filenm fnm[], { case efTRR: case efTRN: - of->fp_trn = gmx_trr_open(filename, filemode); + /* If there is no uncompressed coordinate output and + there is compressed TNG output write forces + and/or velocities to the TNG file instead. */ + if (ir->nstxout != 0 || ir->nstxout_compressed == 0 || + !of->tng_low_prec) + { + of->fp_trn = gmx_trr_open(filename, filemode); + } break; case efTNG: gmx_tng_open(filename, filemode[0], &of->tng); @@ -142,28 +171,6 @@ gmx_mdoutf_t init_mdoutf(FILE *fplog, int nfile, const t_filenm fnm[], 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); @@ -333,12 +340,28 @@ void mdoutf_write_to_trajectory_files(FILE *fplog, t_commrec *cr, } } - gmx_fwrite_tng(of->tng, FALSE, step, t, state_local->lambda[efptFEP], - state_local->box, - top_global->natoms, - (mdof_flags & MDOF_X) ? state_global->x : NULL, - (mdof_flags & MDOF_V) ? global_v : NULL, - (mdof_flags & MDOF_F) ? f_global : NULL); + /* If a TNG file is open for uncompressed coordinate output also write + velocities and forces to it. */ + else if (of->tng) + { + gmx_fwrite_tng(of->tng, FALSE, step, t, state_local->lambda[efptFEP], + state_local->box, + top_global->natoms, + (mdof_flags & MDOF_X) ? state_global->x : NULL, + (mdof_flags & MDOF_V) ? global_v : NULL, + (mdof_flags & MDOF_F) ? f_global : NULL); + } + /* If only a TNG file is open for compressed coordinate output (no uncompressed + coordinate output) also write forces and velocities to it. */ + else if (of->tng_low_prec) + { + gmx_fwrite_tng(of->tng_low_prec, FALSE, step, t, state_local->lambda[efptFEP], + state_local->box, + top_global->natoms, + (mdof_flags & MDOF_X) ? state_global->x : NULL, + (mdof_flags & MDOF_V) ? global_v : NULL, + (mdof_flags & MDOF_F) ? f_global : NULL); + } } if (mdof_flags & MDOF_X_COMPRESSED) { -- 2.22.0