static void edr_nms(int fp,int *nre,char ***nms) { XDR *xdr; bool bRead = gmx_fio_getread(fp); int i; char **NM; xdr = gmx_fio_getxdr(fp); NM=*nms; if (!xdr_int(xdr,nre)) { if(!bRead) gmx_file("Cannot write energy names to file; maybe you are out of quota?"); *nre=0; return; } if (*nre == -55555) { /* In the 4.1 edr format the first entry is the magic number */ gmx_fatal(FARGS,"You are trying to read an edr file of GROMACS version 4.1 or later with GROMACS version 4.0"); } if (NM == NULL) { snew(NM,*nre); } for(i=0; i<*nre; i++) { if (bRead && NM[i]) { sfree(NM[i]); NM[i] = NULL; } if(!xdr_string(xdr,&(NM[i]),STRLEN)) gmx_file("Cannot write energy names to file; maybe you are out of quota?"); } *nms=NM; }
FILE *ffopen(const char *file,const char *mode) { #ifdef SKIP_FFOPS return fopen(file,mode); #else FILE *ff=NULL; char buf[256],*bf,*bufsize=0,*ptr; gmx_bool bRead; int bs; if (mode[0]=='w') { make_backup(file); } where(); bRead= (mode[0]=='r'&&mode[1]!='+'); strcpy(buf,file); if (gmx_fexist(buf) || !bRead) { if ((ff=fopen(buf,mode))==NULL) gmx_file(buf); where(); /* Check whether we should be using buffering (default) or not * (for debugging) */ if (bUnbuffered || ((bufsize=getenv("LOG_BUFS")) != NULL)) { /* Check whether to use completely unbuffered */ if (bUnbuffered) bs = 0; else bs=strtol(bufsize, NULL, 10); if (bs <= 0) setbuf(ff,NULL); else { snew(ptr,bs+8); if (setvbuf(ff,ptr,_IOFBF,bs) != 0) gmx_file("Buffering File"); } } where(); } else { sprintf(buf,"%s.Z",file); if (gmx_fexist(buf)) { ff=uncompress(buf,mode); } else { sprintf(buf,"%s.gz",file); if (gmx_fexist(buf)) { ff=gunzip(buf,mode); } else gmx_file(file); } } return ff; #endif }
static gmx_bool do_trr_frame(t_fileio *fio, bool bRead, int *step, real *t, real *lambda, rvec *box, int *natoms, rvec *x, rvec *v, rvec *f) { gmx_trr_header_t *sh; gmx_bool bOK; snew(sh, 1); if (!bRead) { sh->box_size = (box) ? sizeof(matrix) : 0; sh->x_size = ((x) ? (*natoms*sizeof(x[0])) : 0); sh->v_size = ((v) ? (*natoms*sizeof(v[0])) : 0); sh->f_size = ((f) ? (*natoms*sizeof(f[0])) : 0); sh->natoms = *natoms; sh->step = *step; sh->nre = 0; sh->t = *t; sh->lambda = *lambda; } if (!do_trr_frame_header(fio, bRead, sh, &bOK)) { return FALSE; } if (bRead) { *natoms = sh->natoms; *step = sh->step; *t = sh->t; *lambda = sh->lambda; if (sh->ir_size) { gmx_file("inputrec in trr file"); } if (sh->e_size) { gmx_file("energies in trr file"); } if (sh->top_size) { gmx_file("topology in trr file"); } if (sh->sym_size) { gmx_file("symbol table in trr file"); } } bOK = do_trr_frame_data(fio, sh, box, x, v, f); sfree(sh); return bOK; }
static char *next_item(FILE *fp) { /* This routine reads strings from the file fp, strips comment * and buffers. If there are multiple strings on a line, they will * be stored here, and indices in the line buffer (buf) will be * stored in bufindex. This way we can uncomment on the fly, * without too much double work. Each string is first read through * fscanf in this routine, and then through sscanf in do_read. * No unnecessary string copying is done. */ #define MAXBUF 20 static char buf[STRLEN]; static int bufindex[MAXBUF]; int i,j0; char ccc; if (nbuf) { j0 = bufindex[0]; for(i=1; (i<nbuf); i++) bufindex[i-1] = bufindex[i]; nbuf--; return buf+j0; } else { /* First read until we find something that is not comment */ if (fgets2(buf,STRLEN-1,fp) == NULL) gmx_file("End of file"); i = 0; do { /* Skip over leading spaces */ while ((buf[i] != '\0') && (buf[i] != ';') && isspace(buf[i])) i++; /* Store start of something non-space */ j0 = i; /* Look for next spaces */ while ((buf[i] != '\0') && (buf[i] != ';') && !isspace(buf[i])) i++; /* Store the last character in the string */ ccc = buf[i]; /* If the string is non-empty, add it to the list */ if (i > j0) { buf[i] = '\0'; bufindex[nbuf++] = j0; /* We increment i here; otherwise the next test for buf[i] would be * '\0', since we test the main loop for ccc anyway, we cant go SEGV */ i++; } } while ((ccc != '\0') && (ccc != ';')); return next_item(fp); } }
static int nFloatSize(gmx_trr_header_t *sh) { int nflsize = 0; if (sh->box_size) { nflsize = sh->box_size/(DIM*DIM); } else if (sh->x_size) { nflsize = sh->x_size/(sh->natoms*DIM); } else if (sh->v_size) { nflsize = sh->v_size/(sh->natoms*DIM); } else if (sh->f_size) { nflsize = sh->f_size/(sh->natoms*DIM); } else { gmx_file("Can not determine precision of trr file"); } if (((nflsize != sizeof(float)) && (nflsize != sizeof(double)))) { gmx_fatal(FARGS, "Float size %d. Maybe different CPU?", nflsize); } return nflsize; }
void close_enx(ener_file_t ef) { if(gmx_fio_close(ef->fio) != 0) { gmx_file("Cannot close energy file; it might be corrupt, or maybe you are out of quota?"); } }
void close_enx(int fp) { if(gmx_fio_close(fp) != 0) { gmx_file("Cannot close energy file; it might be corrupt, or maybe you are out of quota?"); } }
/* The fio_mutex should ALWAYS be locked when this function is called */ static int gmx_fio_int_get_file_position(t_fileio *fio, gmx_off_t *offset) { char buf[STRLEN]; /* Flush the file, so we are sure it is written */ if (gmx_fio_int_flush(fio)) { char buf[STRLEN]; sprintf( buf, "Cannot write file '%s'; maybe you are out of disk space?", fio->fn); gmx_file(buf); } /* We cannot count on XDR being able to write 64-bit integers, so separate into high/low 32-bit values. In case the filesystem has 128-bit offsets we only care about the first 64 bits - we'll have to fix this when exabyte-size output files are common... */ *offset = gmx_ftell(fio->fp); return 0; }
static char *next_item(FILE *fp, char *buf, int buflen) { int rd; gmx_bool in_comment = FALSE; gmx_bool in_token = FALSE; int i = 0; /* This routine reads strings from the file fp, strips comment * and buffers. For thread-safety reasons, It reads through getc() */ rd = getc(fp); if (rd == EOF) { gmx_file("End of file"); } do { if (in_comment) { if (rd == '\n') { in_comment = FALSE; } } else if (in_token) { if (isspace(rd) || rd == ';') { break; } buf[i++] = (char) rd; } else { if (!isspace(rd)) { if (rd == ';') { in_comment = TRUE; } else { in_token = TRUE; buf[i++] = (char) (rd); } } } if (i >= buflen - 2) { break; } } while ((rd = getc(fp)) != EOF); fprintf(stderr, "WARNING, ftpASC file type not tested!\n"); buf[i] = 0; return buf; }
void gmx_trr_write_frame(t_fileio *fio, int step, real t, real lambda, rvec *box, int natoms, rvec *x, rvec *v, rvec *f) { if (!do_trr_frame(fio, false, &step, &t, &lambda, box, &natoms, x, v, f)) { gmx_file("Cannot write trajectory frame; maybe you are out of disk space?"); } }
void fwrite_trn(t_fileio *fio, int step, real t, real lambda, rvec *box, int natoms, rvec *x, rvec *v, rvec *f) { if (do_trn(fio, FALSE, &step, &t, &lambda, box, &natoms, x, v, f) == FALSE) { gmx_file("Cannot write trajectory frame; maybe you are out of disk space?"); } }
void fwrite_trn(int fp,int step,real t,real lambda, rvec *box,int natoms,rvec *x,rvec *v,rvec *f) { if( do_trn(fp,FALSE,&step,&t,&lambda,box,&natoms,x,v,f) == FALSE) { gmx_file("Cannot write trajectory frame; maybe you are out of quota?"); } }
static void edr_strings(XDR *xdr,gmx_bool bRead,int file_version, int n,gmx_enxnm_t **nms) { int i; gmx_enxnm_t *nm; if (*nms == NULL) { snew(*nms,n); } for(i=0; i<n; i++) { nm = &(*nms)[i]; if (bRead) { if (nm->name) { sfree(nm->name); nm->name = NULL; } if (nm->unit) { sfree(nm->unit); nm->unit = NULL; } } if(!xdr_string(xdr,&(nm->name),STRLEN)) { gmx_file("Cannot write energy names to file; maybe you are out of quota?"); } if (file_version >= 2) { if(!xdr_string(xdr,&(nm->unit),STRLEN)) { gmx_file("Cannot write energy names to file; maybe you are out of quota?"); } } else { nm->unit = strdup("kJ/mol"); } } }
void do_enxnms(ener_file_t ef,int *nre,gmx_enxnm_t **nms) { int magic=-55555; XDR *xdr; gmx_bool bRead = gmx_fio_getread(ef->fio); int file_version; int i; gmx_fio_checktype(ef->fio); xdr = gmx_fio_getxdr(ef->fio); if (!xdr_int(xdr,&magic)) { if(!bRead) { gmx_file("Cannot write energy names to file; maybe you are out of quota?"); } *nre=0; return; } if (magic > 0) { /* Assume this is an old edr format */ file_version = 1; *nre = magic; ef->eo.bOldFileOpen = TRUE; ef->eo.bReadFirstStep = FALSE; srenew(ef->eo.ener_prev,*nre); } else { ef->eo.bOldFileOpen=FALSE; if (magic != -55555) { gmx_fatal(FARGS,"Energy names magic number mismatch, this is not a GROMACS edr file"); } file_version = enx_version; xdr_int(xdr,&file_version); if (file_version > enx_version) { gmx_fatal(FARGS,"reading tpx file (%s) version %d with version %d program",gmx_fio_getname(ef->fio),file_version,enx_version); } xdr_int(xdr,nre); } if (file_version != enx_version) { fprintf(stderr,"Note: enx file_version %d, software version %d\n", file_version,enx_version); } edr_strings(xdr,bRead,file_version,*nre,nms); }
void close_enx(ener_file_t ef) { if (ef == NULL) { // Nothing to do return; } if (gmx_fio_close(ef->fio) != 0) { gmx_file("Cannot close energy file; it might be corrupt, or maybe you are out of disk space?"); } }
int gmx_fio_get_output_file_positions(gmx_file_position_t **p_outputfiles, int *p_nfiles) { int i,nfiles,rc,nalloc; int pos_hi,pos_lo; long pos; gmx_file_position_t * outputfiles; char buf[STRLEN]; nfiles = 0; nalloc = 100; snew(outputfiles,nalloc); for(i=0; i<nFIO; i++) { /* Skip the checkpoint files themselves, since they could be open when we call this routine... */ if(FIO[i].bOpen && !FIO[i].bRead && !FIO[i].bStdio && FIO[i].iFTP!=efCPT) { /* This is an output file currently open for writing, add it */ if(nfiles == nalloc) { nalloc += 100; srenew(outputfiles,nalloc); } strncpy(outputfiles[nfiles].filename,FIO[i].fn,STRLEN-1); /* Flush the file, so we are sure it is written */ if (gmx_fio_flush(i) != 0) { sprintf(buf,"Cannot write file '%s'; maybe you are out of disk space or quota?",FIO[i].fn); gmx_file(buf); } /* We cannot count on XDR being able to write 64-bit integers, so separate into high/low 32-bit values. * In case the filesystem has 128-bit offsets we only care about the first 64 bits - we'll have to fix * this when exabyte-size output files are common... */ #ifdef HAVE_FSEEKO outputfiles[nfiles].offset = ftello(FIO[i].fp); #else outputfiles[nfiles].offset = ftell(FIO[i].fp); #endif nfiles++; } } *p_nfiles = nfiles; *p_outputfiles = outputfiles; return 0; }
static void wr_ener_nms(FILE *out,int nre,char *nms[]) { int i,rc; rc = 0; rc = fprintf(out,"%d\n",nre); for(i=0; (i<nre) && rc>=0; i++) rc=fprintf(out,"%s\n",nms[i]); if(rc<0) { gmx_file("Cannot write energy names to file; maybe you are out of quota?"); } }
static void addTngMoleculeFromTopology(tng_trajectory_t tng, const char *moleculeName, const t_atoms *atoms, gmx_int64_t numMolecules, tng_molecule_t *tngMol) { if (tng_molecule_add(tng, moleculeName, tngMol) != TNG_SUCCESS) { gmx_file("Cannot add molecule to TNG molecular system."); } /* FIXME: The TNG atoms should contain mass and atomB info (for free * energy calculations), i.e. in when it's available in TNG (2.0). */ for (int atomIt = 0; atomIt < atoms->nr; atomIt++) { const t_atom *at = &atoms->atom[atomIt]; /* FIXME: Currently the TNG API can only add atoms belonging to a * residue and chain. Wait for TNG 2.0*/ if (atoms->nres > 0) { const t_resinfo *resInfo = &atoms->resinfo[at->resind]; char chainName[2] = {resInfo->chainid, 0}; tng_chain_t tngChain = NULL; tng_residue_t tngRes = NULL; tng_atom_t tngAtom = NULL; if (tng_molecule_chain_find (tng, *tngMol, chainName, (gmx_int64_t)-1, &tngChain) != TNG_SUCCESS) { tng_molecule_chain_add (tng, *tngMol, chainName, &tngChain); } /* FIXME: When TNG supports both residue index and residue * number the latter should be used. Wait for TNG 2.0*/ if (tng_chain_residue_find(tng, tngChain, *resInfo->name, at->resind + 1, &tngRes) != TNG_SUCCESS) { tng_chain_residue_add(tng, tngChain, *resInfo->name, &tngRes); } tng_residue_atom_add(tng, tngRes, *(atoms->atomname[atomIt]), *(atoms->atomtype[atomIt]), &tngAtom); } } tng_molecule_cnt_set(tng, *tngMol, numMolecules); }
int gmx_fio_seek(t_fileio* fio, gmx_off_t fpos) { int rc; gmx_fio_lock(fio); if (fio->fp) { rc = gmx_fseek(fio->fp, fpos, SEEK_SET); } else { gmx_file(fio->fn); rc = -1; } gmx_fio_unlock(fio); return rc; }
int gro_first_x_or_v(FILE *status,t_trxframe *fr) { char title[STRLEN]; frewind(status); fprintf(stderr,"Reading frames from gro file"); get_coordnum_fp(status, title, &fr->natoms); frewind(status); fprintf(stderr," '%s', %d atoms.\n",title, fr->natoms); fr->bTitle = TRUE; fr->title = title; if (fr->natoms==0) gmx_file("No coordinates in gro file"); snew(fr->x,fr->natoms); snew(fr->v,fr->natoms); gro_next_x_or_v(status, fr); return fr->natoms; }
int read_xpm_matrix(char *fnm,t_matrix **matrix) { FILE *in; char *line; int nmat; in=gmx_fio_fopen(fnm,"r"); nmat=0; while (fgetline(&line,STRLEN,in)) { if (strstr(line,"/* XPM */")) { srenew(*matrix,nmat+1); read_xpm_entry(in,&(*matrix)[nmat]); nmat++; } } gmx_fio_fclose(in); if (nmat==0) gmx_file("Invalid XPixMap"); return nmat; }
gmx_bool gmx_get_tng_data_block_types_of_next_frame(tng_trajectory_t input, int frame, int nRequestedIds, gmx_int64_t *requestedIds, gmx_int64_t *nextFrame, gmx_int64_t *nBlocks, gmx_int64_t **blockIds) { #if GMX_USE_TNG tng_function_status stat; stat = tng_util_trajectory_next_frame_present_data_blocks_find(input, frame, nRequestedIds, requestedIds, nextFrame, nBlocks, blockIds); if (stat == TNG_CRITICAL) { gmx_file("Cannot read TNG file. Cannot find data blocks of next frame."); } else if (stat == TNG_FAILURE) { return FALSE; } return TRUE; #else GMX_UNUSED_VALUE(input); GMX_UNUSED_VALUE(frame); GMX_UNUSED_VALUE(nRequestedIds); GMX_UNUSED_VALUE(requestedIds); GMX_UNUSED_VALUE(nextFrame); GMX_UNUSED_VALUE(nBlocks); GMX_UNUSED_VALUE(blockIds); return FALSE; #endif }
void mdoutf_write_to_trajectory_files(FILE *fplog, t_commrec *cr, gmx_mdoutf_t of, int mdof_flags, gmx_mtop_t *top_global, gmx_int64_t step, double t, t_state *state_local, t_state *state_global, rvec *f_local, rvec *f_global) { rvec *local_v; rvec *global_v; /* MRS -- defining these variables is to manage the difference * between half step and full step velocities, but there must be a better way . . . */ local_v = state_local->v; global_v = state_global->v; if (DOMAINDECOMP(cr)) { if (mdof_flags & MDOF_CPT) { dd_collect_state(cr->dd, state_local, state_global); } else { if (mdof_flags & (MDOF_X | MDOF_X_COMPRESSED)) { dd_collect_vec(cr->dd, state_local, state_local->x, state_global->x); } if (mdof_flags & MDOF_V) { dd_collect_vec(cr->dd, state_local, local_v, global_v); } } if (mdof_flags & MDOF_F) { dd_collect_vec(cr->dd, state_local, f_local, f_global); } } else { if (mdof_flags & MDOF_CPT) { /* All pointers in state_local are equal to state_global, * but we need to copy the non-pointer entries. */ state_global->lambda = state_local->lambda; state_global->veta = state_local->veta; state_global->vol0 = state_local->vol0; copy_mat(state_local->box, state_global->box); copy_mat(state_local->boxv, state_global->boxv); copy_mat(state_local->svir_prev, state_global->svir_prev); copy_mat(state_local->fvir_prev, state_global->fvir_prev); copy_mat(state_local->pres_prev, state_global->pres_prev); } } if (MASTER(cr)) { if (mdof_flags & MDOF_CPT) { fflush_tng(of->tng); fflush_tng(of->tng_low_prec); write_checkpoint(of->fn_cpt, of->bKeepAndNumCPT, fplog, cr, of->eIntegrator, of->simulation_part, of->bExpanded, of->elamstats, step, t, state_global); } if (mdof_flags & (MDOF_X | MDOF_V | MDOF_F)) { if (of->fp_trn) { gmx_trr_write_frame(of->fp_trn, 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 (gmx_fio_flush(of->fp_trn) != 0) { gmx_file("Cannot write trajectory; maybe you are out of disk space?"); } } 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 (mdof_flags & MDOF_X_COMPRESSED) { rvec *xxtc = NULL; if (of->natoms_x_compressed == of->natoms_global) { /* We are writing the positions of all of the atoms to the compressed output */ xxtc = state_global->x; } else { /* We are writing the positions of only a subset of the atoms to the compressed output, so we have to make a copy of the subset of coordinates. */ int i, j; snew(xxtc, of->natoms_x_compressed); for (i = 0, j = 0; (i < of->natoms_global); i++) { if (ggrpnr(of->groups, egcCompressedX, i) == 0) { copy_rvec(state_global->x[i], xxtc[j++]); } } } if (write_xtc(of->fp_xtc, of->natoms_x_compressed, step, t, state_local->box, xxtc, of->x_compression_precision) == 0) { gmx_fatal(FARGS, "XTC error - maybe you are out of disk space?"); } gmx_fwrite_tng(of->tng_low_prec, TRUE, step, t, state_local->lambda[efptFEP], state_local->box, of->natoms_x_compressed, xxtc, NULL, NULL); if (of->natoms_x_compressed != of->natoms_global) { sfree(xxtc); } } } }
void gmx_tng_open(const char *filename, char mode, tng_trajectory_t *tng) { #ifdef GMX_USE_TNG /* First check whether we have to make a backup, * only for writing, not for read or append. */ if (mode == 'w') { #ifndef GMX_FAHCORE /* only make backups for normal gromacs */ make_backup(filename); #endif } /* tng must not be pointing at already allocated memory. * Memory will be allocated by tng_util_trajectory_open() and must * later on be freed by tng_util_trajectory_close(). */ if (TNG_SUCCESS != tng_util_trajectory_open(filename, mode, tng)) { /* TNG does return more than one degree of error, but there is no use case for GROMACS handling the non-fatal errors gracefully. */ gmx_fatal(FARGS, "%s while opening %s for %s", gmx_strerror("file"), filename, modeToVerb(mode)); } if (mode == 'w' || mode == 'a') { /* FIXME in TNG: When adding data to the header, subsequent blocks might get * overwritten. This could be solved by moving the first trajectory * frame set(s) to the end of the file. Could that cause other problems, * e.g. when continuing a simulation? */ char hostname[256]; gmx_gethostname(hostname, 256); if (mode == 'w') { tng_first_computer_name_set(*tng, hostname); } /* TODO: This should be implemented when the above fixme is done (adding data to * the header). */ // else // { // tng_last_computer_name_set(*tng, hostname); // } char programInfo[256]; const char *precisionString = ""; #ifdef GMX_DOUBLE precisionString = " (double precision)"; #endif sprintf(programInfo, "%.100s, %.128s%.24s", gmx::getProgramContext().displayName(), GromacsVersion(), precisionString); if (mode == 'w') { tng_first_program_name_set(*tng, programInfo); } /* TODO: This should be implemented when the above fixme is done (adding data to * the header). */ // else // { // tng_last_program_name_set(*tng, programInfo); // } #ifdef HAVE_UNISTD_H char username[256]; getlogin_r(username, 256); if (mode == 'w') { tng_first_user_name_set(*tng, username); } /* TODO: This should be implemented when the above fixme is done (adding data to * the header). */ // else // { // tng_last_user_name_set(*tng, username); // } #endif } #else gmx_file("GROMACS was compiled without TNG support, cannot handle this file type"); GMX_UNUSED_VALUE(filename); GMX_UNUSED_VALUE(mode); GMX_UNUSED_VALUE(tng); #endif }
void gmx_fwrite_tng(tng_trajectory_t tng, const gmx_bool bUseLossyCompression, int step, real elapsedPicoSeconds, real lambda, const rvec *box, int nAtoms, const rvec *x, const rvec *v, const rvec *f) { #ifdef GMX_USE_TNG typedef tng_function_status (*write_data_func_pointer)(tng_trajectory_t, const gmx_int64_t, const double, const real*, const gmx_int64_t, const gmx_int64_t, const char*, const char, const char); #ifdef GMX_DOUBLE static write_data_func_pointer write_data = tng_util_generic_with_time_double_write; #else static write_data_func_pointer write_data = tng_util_generic_with_time_write; #endif double elapsedSeconds = elapsedPicoSeconds * PICO; gmx_int64_t nParticles; char compression; if (!tng) { /* This function might get called when the type of the compressed trajectory is actually XTC. So we exit and move on. */ return; } tng_num_particles_get(tng, &nParticles); if (nAtoms != (int)nParticles) { tng_implicit_num_particles_set(tng, nAtoms); } if (bUseLossyCompression) { compression = TNG_TNG_COMPRESSION; } else { compression = TNG_GZIP_COMPRESSION; } /* The writing is done using write_data, which writes float or double * depending on the GROMACS compilation. */ if (x) { GMX_ASSERT(box, "Need a non-NULL box if positions are written"); if (write_data(tng, step, elapsedSeconds, reinterpret_cast<const real *>(x), 3, TNG_TRAJ_POSITIONS, "POSITIONS", TNG_PARTICLE_BLOCK_DATA, compression) != TNG_SUCCESS) { 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<const real *>(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) { if (write_data(tng, step, elapsedSeconds, reinterpret_cast<const real *>(v), 3, TNG_TRAJ_VELOCITIES, "VELOCITIES", TNG_PARTICLE_BLOCK_DATA, compression) != TNG_SUCCESS) { gmx_file("Cannot write TNG trajectory frame; maybe you are out of disk space?"); } } if (f) { /* TNG-MF1 compression only compresses positions and velocities. Use lossless * compression for forces regardless of output mode */ if (write_data(tng, step, elapsedSeconds, reinterpret_cast<const real *>(f), 3, TNG_TRAJ_FORCES, "FORCES", TNG_PARTICLE_BLOCK_DATA, TNG_GZIP_COMPRESSION) != TNG_SUCCESS) { 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 lambdas regardless of output mode */ if (write_data(tng, step, elapsedSeconds, reinterpret_cast<const real *>(&lambda), 1, TNG_GMX_LAMBDA, "LAMBDAS", TNG_NON_PARTICLE_BLOCK_DATA, TNG_GZIP_COMPRESSION) != TNG_SUCCESS) { gmx_file("Cannot write TNG trajectory frame; maybe you are out of disk space?"); } #else GMX_UNUSED_VALUE(tng); GMX_UNUSED_VALUE(bUseLossyCompression); GMX_UNUSED_VALUE(step); GMX_UNUSED_VALUE(elapsedPicoSeconds); GMX_UNUSED_VALUE(lambda); GMX_UNUSED_VALUE(box); GMX_UNUSED_VALUE(nAtoms); GMX_UNUSED_VALUE(x); GMX_UNUSED_VALUE(v); GMX_UNUSED_VALUE(f); #endif }
static void clust_size(const char *ndx, const char *trx, const char *xpm, const char *xpmw, const char *ncl, const char *acl, const char *mcl, const char *histo, const char *tempf, const char *mcn, gmx_bool bMol, gmx_bool bPBC, const char *tpr, real cut, int nskip, int nlevels, t_rgb rmid, t_rgb rhi, int ndf, const output_env_t oenv) { FILE *fp, *gp, *hp, *tp; atom_id *index = NULL; int nindex, natoms; t_trxstatus *status; rvec *x = NULL, *v = NULL, dx; t_pbc pbc; char *gname; char timebuf[32]; gmx_bool bSame, bTPRwarn = TRUE; /* Topology stuff */ t_trxframe fr; t_tpxheader tpxh; gmx_mtop_t *mtop = NULL; int ePBC = -1; t_block *mols = NULL; gmx_mtop_atomlookup_t alook; t_atom *atom; int version, generation, ii, jj; real temp, tfac; /* Cluster size distribution (matrix) */ real **cs_dist = NULL; real tf, dx2, cut2, *t_x = NULL, *t_y, cmid, cmax, cav, ekin; int i, j, k, ai, aj, ci, cj, nframe, nclust, n_x, max_size = 0; int *clust_index, *clust_size, max_clust_size, max_clust_ind, nav, nhisto; t_rgb rlo = { 1.0, 1.0, 1.0 }; clear_trxframe(&fr, TRUE); sprintf(timebuf, "Time (%s)", output_env_get_time_unit(oenv)); tf = output_env_get_time_factor(oenv); fp = xvgropen(ncl, "Number of clusters", timebuf, "N", oenv); gp = xvgropen(acl, "Average cluster size", timebuf, "#molecules", oenv); hp = xvgropen(mcl, "Max cluster size", timebuf, "#molecules", oenv); tp = xvgropen(tempf, "Temperature of largest cluster", timebuf, "T (K)", oenv); if (!read_first_frame(oenv, &status, trx, &fr, TRX_NEED_X | TRX_READ_V)) { gmx_file(trx); } natoms = fr.natoms; x = fr.x; if (tpr) { snew(mtop, 1); read_tpxheader(tpr, &tpxh, TRUE, &version, &generation); if (tpxh.natoms != natoms) { gmx_fatal(FARGS, "tpr (%d atoms) and trajectory (%d atoms) do not match!", tpxh.natoms, natoms); } ePBC = read_tpx(tpr, NULL, NULL, &natoms, NULL, NULL, mtop); } if (ndf <= -1) { tfac = 1; } else { tfac = ndf/(3.0*natoms); } if (bMol) { if (ndx) { printf("Using molecules rather than atoms. Not reading index file %s\n", ndx); } GMX_RELEASE_ASSERT(mtop != NULL, "Trying to access mtop->mols from NULL mtop pointer"); mols = &(mtop->mols); /* Make dummy index */ nindex = mols->nr; snew(index, nindex); for (i = 0; (i < nindex); i++) { index[i] = i; } gname = gmx_strdup("mols"); } else { rd_index(ndx, 1, &nindex, &index, &gname); } alook = gmx_mtop_atomlookup_init(mtop); snew(clust_index, nindex); snew(clust_size, nindex); cut2 = cut*cut; nframe = 0; n_x = 0; snew(t_y, nindex); for (i = 0; (i < nindex); i++) { t_y[i] = i+1; } max_clust_size = 1; max_clust_ind = -1; do { if ((nskip == 0) || ((nskip > 0) && ((nframe % nskip) == 0))) { if (bPBC) { set_pbc(&pbc, ePBC, fr.box); } max_clust_size = 1; max_clust_ind = -1; /* Put all atoms/molecules in their own cluster, with size 1 */ for (i = 0; (i < nindex); i++) { /* Cluster index is indexed with atom index number */ clust_index[i] = i; /* Cluster size is indexed with cluster number */ clust_size[i] = 1; } /* Loop over atoms */ for (i = 0; (i < nindex); i++) { ai = index[i]; ci = clust_index[i]; /* Loop over atoms (only half a matrix) */ for (j = i+1; (j < nindex); j++) { cj = clust_index[j]; /* If they are not in the same cluster already */ if (ci != cj) { aj = index[j]; /* Compute distance */ if (bMol) { GMX_RELEASE_ASSERT(mols != NULL, "Cannot access index[] from NULL mols pointer"); bSame = FALSE; for (ii = mols->index[ai]; !bSame && (ii < mols->index[ai+1]); ii++) { for (jj = mols->index[aj]; !bSame && (jj < mols->index[aj+1]); jj++) { if (bPBC) { pbc_dx(&pbc, x[ii], x[jj], dx); } else { rvec_sub(x[ii], x[jj], dx); } dx2 = iprod(dx, dx); bSame = (dx2 < cut2); } } } else { if (bPBC) { pbc_dx(&pbc, x[ai], x[aj], dx); } else { rvec_sub(x[ai], x[aj], dx); } dx2 = iprod(dx, dx); bSame = (dx2 < cut2); } /* If distance less than cut-off */ if (bSame) { /* Merge clusters: check for all atoms whether they are in * cluster cj and if so, put them in ci */ for (k = 0; (k < nindex); k++) { if (clust_index[k] == cj) { if (clust_size[cj] <= 0) { gmx_fatal(FARGS, "negative cluster size %d for element %d", clust_size[cj], cj); } clust_size[cj]--; clust_index[k] = ci; clust_size[ci]++; } } } } } } n_x++; srenew(t_x, n_x); t_x[n_x-1] = fr.time*tf; srenew(cs_dist, n_x); snew(cs_dist[n_x-1], nindex); nclust = 0; cav = 0; nav = 0; for (i = 0; (i < nindex); i++) { ci = clust_size[i]; if (ci > max_clust_size) { max_clust_size = ci; max_clust_ind = i; } if (ci > 0) { nclust++; cs_dist[n_x-1][ci-1] += 1.0; max_size = std::max(max_size, ci); if (ci > 1) { cav += ci; nav++; } } } fprintf(fp, "%14.6e %10d\n", fr.time, nclust); if (nav > 0) { fprintf(gp, "%14.6e %10.3f\n", fr.time, cav/nav); } fprintf(hp, "%14.6e %10d\n", fr.time, max_clust_size); } /* Analyse velocities, if present */ if (fr.bV) { if (!tpr) { if (bTPRwarn) { printf("You need a [REF].tpr[ref] file to analyse temperatures\n"); bTPRwarn = FALSE; } } else { v = fr.v; /* Loop over clusters and for each cluster compute 1/2 m v^2 */ if (max_clust_ind >= 0) { ekin = 0; for (i = 0; (i < nindex); i++) { if (clust_index[i] == max_clust_ind) { ai = index[i]; gmx_mtop_atomnr_to_atom(alook, ai, &atom); ekin += 0.5*atom->m*iprod(v[ai], v[ai]); } } temp = (ekin*2.0)/(3.0*tfac*max_clust_size*BOLTZ); fprintf(tp, "%10.3f %10.3f\n", fr.time, temp); } } } nframe++; } while (read_next_frame(oenv, status, &fr)); close_trx(status); xvgrclose(fp); xvgrclose(gp); xvgrclose(hp); xvgrclose(tp); gmx_mtop_atomlookup_destroy(alook); if (max_clust_ind >= 0) { fp = gmx_ffopen(mcn, "w"); fprintf(fp, "[ max_clust ]\n"); for (i = 0; (i < nindex); i++) { if (clust_index[i] == max_clust_ind) { if (bMol) { GMX_RELEASE_ASSERT(mols != NULL, "Cannot access index[] from NULL mols pointer"); for (j = mols->index[i]; (j < mols->index[i+1]); j++) { fprintf(fp, "%d\n", j+1); } } else { fprintf(fp, "%d\n", index[i]+1); } } } gmx_ffclose(fp); } /* Print the real distribution cluster-size/numer, averaged over the trajectory. */ fp = xvgropen(histo, "Cluster size distribution", "Cluster size", "()", oenv); nhisto = 0; fprintf(fp, "%5d %8.3f\n", 0, 0.0); for (j = 0; (j < max_size); j++) { real nelem = 0; for (i = 0; (i < n_x); i++) { nelem += cs_dist[i][j]; } fprintf(fp, "%5d %8.3f\n", j+1, nelem/n_x); nhisto += static_cast<int>((j+1)*nelem/n_x); } fprintf(fp, "%5d %8.3f\n", j+1, 0.0); xvgrclose(fp); fprintf(stderr, "Total number of atoms in clusters = %d\n", nhisto); /* Look for the smallest entry that is not zero * This will make that zero is white, and not zero is coloured. */ cmid = 100.0; cmax = 0.0; for (i = 0; (i < n_x); i++) { for (j = 0; (j < max_size); j++) { if ((cs_dist[i][j] > 0) && (cs_dist[i][j] < cmid)) { cmid = cs_dist[i][j]; } cmax = std::max(cs_dist[i][j], cmax); } } fprintf(stderr, "cmid: %g, cmax: %g, max_size: %d\n", cmid, cmax, max_size); cmid = 1; fp = gmx_ffopen(xpm, "w"); write_xpm3(fp, 0, "Cluster size distribution", "# clusters", timebuf, "Size", n_x, max_size, t_x, t_y, cs_dist, 0, cmid, cmax, rlo, rmid, rhi, &nlevels); gmx_ffclose(fp); cmid = 100.0; cmax = 0.0; for (i = 0; (i < n_x); i++) { for (j = 0; (j < max_size); j++) { cs_dist[i][j] *= (j+1); if ((cs_dist[i][j] > 0) && (cs_dist[i][j] < cmid)) { cmid = cs_dist[i][j]; } cmax = std::max(cs_dist[i][j], cmax); } } fprintf(stderr, "cmid: %g, cmax: %g, max_size: %d\n", cmid, cmax, max_size); fp = gmx_ffopen(xpmw, "w"); write_xpm3(fp, 0, "Weighted cluster size distribution", "Fraction", timebuf, "Size", n_x, max_size, t_x, t_y, cs_dist, 0, cmid, cmax, rlo, rmid, rhi, &nlevels); gmx_ffclose(fp); sfree(clust_index); sfree(clust_size); sfree(index); }
gmx_bool do_enx(ener_file_t ef,t_enxframe *fr) { int file_version=-1; int i,b; gmx_bool bRead,bOK,bOK1,bSane; real tmp1,tmp2,rdum; char buf[22]; /*int d_size;*/ bOK = TRUE; bRead = gmx_fio_getread(ef->fio); if (!bRead) { fr->e_size = fr->nre*sizeof(fr->ener[0].e)*4; /*d_size = fr->ndisre*(sizeof(real)*2);*/ } gmx_fio_checktype(ef->fio); if (!do_eheader(ef,&file_version,fr,-1,NULL,&bOK)) { if (bRead) { fprintf(stderr,"\rLast energy frame read %d time %8.3f ", ef->framenr-1,ef->frametime); if (!bOK) { fprintf(stderr, "\nWARNING: Incomplete energy frame: nr %d time %8.3f\n", ef->framenr,fr->t); } } else { gmx_file("Cannot write energy file header; maybe you are out of quota?"); } return FALSE; } if (bRead) { if ((ef->framenr < 20 || ef->framenr % 10 == 0) && (ef->framenr < 200 || ef->framenr % 100 == 0) && (ef->framenr < 2000 || ef->framenr % 1000 == 0)) { fprintf(stderr,"\rReading energy frame %6d time %8.3f ", ef->framenr,fr->t); } ef->framenr++; ef->frametime = fr->t; } /* Check sanity of this header */ bSane = fr->nre > 0 ; for(b=0; b<fr->nblock; b++) { bSane = bSane || (fr->block[b].nsub > 0); } if (!((fr->step >= 0) && bSane)) { fprintf(stderr,"\nWARNING: there may be something wrong with energy file %s\n", gmx_fio_getname(ef->fio)); fprintf(stderr,"Found: step=%s, nre=%d, nblock=%d, time=%g.\n" "Trying to skip frame expect a crash though\n", gmx_step_str(fr->step,buf),fr->nre,fr->nblock,fr->t); } if (bRead && fr->nre > fr->e_alloc) { srenew(fr->ener,fr->nre); for(i=fr->e_alloc; (i<fr->nre); i++) { fr->ener[i].e = 0; fr->ener[i].eav = 0; fr->ener[i].esum = 0; } fr->e_alloc = fr->nre; } for(i=0; i<fr->nre; i++) { bOK = bOK && gmx_fio_do_real(ef->fio, fr->ener[i].e); /* Do not store sums of length 1, * since this does not add information. */ if (file_version == 1 || (bRead && fr->nsum > 0) || fr->nsum > 1) { tmp1 = fr->ener[i].eav; bOK = bOK && gmx_fio_do_real(ef->fio, tmp1); if (bRead) fr->ener[i].eav = tmp1; /* This is to save only in single precision (unless compiled in DP) */ tmp2 = fr->ener[i].esum; bOK = bOK && gmx_fio_do_real(ef->fio, tmp2); if (bRead) fr->ener[i].esum = tmp2; if (file_version == 1) { /* Old, unused real */ rdum = 0; bOK = bOK && gmx_fio_do_real(ef->fio, rdum); } } } /* Here we can not check for file_version==1, since one could have * continued an old format simulation with a new one with mdrun -append. */ if (bRead && ef->eo.bOldFileOpen) { /* Convert old full simulation sums to sums between energy frames */ convert_full_sums(&(ef->eo),fr); } /* read the blocks */ for(b=0; b<fr->nblock; b++) { /* now read the subblocks. */ int nsub=fr->block[b].nsub; /* shortcut */ int i; for(i=0;i<nsub;i++) { t_enxsubblock *sub=&(fr->block[b].sub[i]); /* shortcut */ if (bRead) { enxsubblock_alloc(sub); } /* read/write data */ bOK1=TRUE; switch (sub->type) { case xdr_datatype_float: bOK1=gmx_fio_ndo_float(ef->fio, sub->fval, sub->nr); break; case xdr_datatype_double: bOK1=gmx_fio_ndo_double(ef->fio, sub->dval, sub->nr); break; case xdr_datatype_int: bOK1=gmx_fio_ndo_int(ef->fio, sub->ival, sub->nr); break; case xdr_datatype_large_int: bOK1=gmx_fio_ndo_gmx_large_int(ef->fio, sub->lval, sub->nr); break; case xdr_datatype_char: bOK1=gmx_fio_ndo_uchar(ef->fio, sub->cval, sub->nr); break; case xdr_datatype_string: bOK1=gmx_fio_ndo_string(ef->fio, sub->sval, sub->nr); break; default: gmx_incons("Reading unknown block data type: this file is corrupted or from the future"); } bOK = bOK && bOK1; } } if(!bRead) { if( gmx_fio_flush(ef->fio) != 0) { gmx_file("Cannot write energy file; maybe you are out of quota?"); } } if (!bOK) { if (bRead) { fprintf(stderr,"\nLast energy frame read %d", ef->framenr-1); fprintf(stderr,"\nWARNING: Incomplete energy frame: nr %d time %8.3f\n", ef->framenr,fr->t); } else { gmx_fatal(FARGS,"could not write energies"); } return FALSE; } return TRUE; }
ener_file_t open_enx(const char *fn,const char *mode) { int nre,i; gmx_enxnm_t *nms=NULL; int file_version=-1; t_enxframe *fr; gmx_bool bWrongPrecision,bOK=TRUE; struct ener_file *ef; snew(ef,1); if (mode[0]=='r') { ef->fio=gmx_fio_open(fn,mode); gmx_fio_checktype(ef->fio); gmx_fio_setprecision(ef->fio,FALSE); do_enxnms(ef,&nre,&nms); snew(fr,1); do_eheader(ef,&file_version,fr,nre,&bWrongPrecision,&bOK); if(!bOK) { gmx_file("Cannot read energy file header. Corrupt file?"); } /* Now check whether this file is in single precision */ if (!bWrongPrecision && ((fr->e_size && (fr->nre == nre) && (nre*4*(long int)sizeof(float) == fr->e_size)) ) ) { fprintf(stderr,"Opened %s as single precision energy file\n",fn); free_enxnms(nre,nms); } else { gmx_fio_rewind(ef->fio); gmx_fio_checktype(ef->fio); gmx_fio_setprecision(ef->fio,TRUE); do_enxnms(ef,&nre,&nms); do_eheader(ef,&file_version,fr,nre,&bWrongPrecision,&bOK); if(!bOK) { gmx_file("Cannot write energy file header; maybe you are out of quota?"); } if (((fr->e_size && (fr->nre == nre) && (nre*4*(long int)sizeof(double) == fr->e_size)) )) fprintf(stderr,"Opened %s as double precision energy file\n", fn); else { if (empty_file(fn)) gmx_fatal(FARGS,"File %s is empty",fn); else gmx_fatal(FARGS,"Energy file %s not recognized, maybe different CPU?", fn); } free_enxnms(nre,nms); } free_enxframe(fr); sfree(fr); gmx_fio_rewind(ef->fio); } else ef->fio = gmx_fio_open(fn,mode); ef->framenr=0; ef->frametime=0; return ef; }
/* TODO: If/when TNG acquires the ability to copy data blocks without * uncompressing them, then this implemenation should be reconsidered. * Ideally, gmx trjconv -f a.tng -o b.tng -b 10 -e 20 would be fast * and lose no information. */ gmx_bool gmx_read_next_tng_frame(tng_trajectory_t input, t_trxframe *fr, gmx_int64_t *requestedIds, int numRequestedIds) { #if GMX_USE_TNG gmx_bool bOK = TRUE; tng_function_status stat; gmx_int64_t numberOfAtoms = -1, frameNumber = -1; gmx_int64_t nBlocks, blockId, *blockIds = NULL, codecId; char datatype = -1; void *values = NULL; double frameTime = -1.0; int size, blockDependency; double prec; const int defaultNumIds = 5; static gmx_int64_t fallbackRequestedIds[defaultNumIds] = { TNG_TRAJ_BOX_SHAPE, TNG_TRAJ_POSITIONS, TNG_TRAJ_VELOCITIES, TNG_TRAJ_FORCES, TNG_GMX_LAMBDA }; fr->bStep = FALSE; fr->bTime = FALSE; fr->bLambda = FALSE; fr->bAtoms = FALSE; fr->bPrec = FALSE; fr->bX = FALSE; fr->bV = FALSE; fr->bF = FALSE; fr->bBox = FALSE; /* If no specific IDs were requested read all block types that can * currently be interpreted */ if (!requestedIds || numRequestedIds == 0) { numRequestedIds = defaultNumIds; requestedIds = fallbackRequestedIds; } stat = tng_num_particles_get(input, &numberOfAtoms); if (stat != TNG_SUCCESS) { gmx_file("Cannot determine number of atoms from TNG file."); } fr->natoms = numberOfAtoms; if (!gmx_get_tng_data_block_types_of_next_frame(input, fr->step, numRequestedIds, requestedIds, &frameNumber, &nBlocks, &blockIds)) { return FALSE; } if (nBlocks == 0) { return FALSE; } for (gmx_int64_t i = 0; i < nBlocks; i++) { blockId = blockIds[i]; tng_data_block_dependency_get(input, blockId, &blockDependency); if (blockDependency & TNG_PARTICLE_DEPENDENT) { stat = tng_util_particle_data_next_frame_read(input, blockId, &values, &datatype, &frameNumber, &frameTime); } else { stat = tng_util_non_particle_data_next_frame_read(input, blockId, &values, &datatype, &frameNumber, &frameTime); } if (stat == TNG_CRITICAL) { gmx_file("Cannot read positions from TNG file."); return FALSE; } else if (stat == TNG_FAILURE) { continue; } switch (blockId) { case TNG_TRAJ_BOX_SHAPE: switch (datatype) { case TNG_INT_DATA: size = sizeof(gmx_int64_t); break; case TNG_FLOAT_DATA: size = sizeof(float); break; case TNG_DOUBLE_DATA: size = sizeof(double); break; default: gmx_incons("Illegal datatype of box shape values!"); } for (int i = 0; i < DIM; i++) { convert_array_to_real_array(reinterpret_cast<char *>(values) + size * i * DIM, reinterpret_cast<real *>(fr->box[i]), getDistanceScaleFactor(input), 1, DIM, datatype); } fr->bBox = TRUE; break; case TNG_TRAJ_POSITIONS: srenew(fr->x, fr->natoms); convert_array_to_real_array(values, reinterpret_cast<real *>(fr->x), getDistanceScaleFactor(input), fr->natoms, DIM, datatype); fr->bX = TRUE; tng_util_frame_current_compression_get(input, blockId, &codecId, &prec); /* This must be updated if/when more lossy compression methods are added */ if (codecId == TNG_TNG_COMPRESSION) { fr->prec = prec; fr->bPrec = TRUE; } break; case TNG_TRAJ_VELOCITIES: srenew(fr->v, fr->natoms); convert_array_to_real_array(values, (real *) fr->v, getDistanceScaleFactor(input), fr->natoms, DIM, datatype); fr->bV = TRUE; tng_util_frame_current_compression_get(input, blockId, &codecId, &prec); /* This must be updated if/when more lossy compression methods are added */ if (codecId == TNG_TNG_COMPRESSION) { fr->prec = prec; fr->bPrec = TRUE; } break; case TNG_TRAJ_FORCES: srenew(fr->f, fr->natoms); convert_array_to_real_array(values, reinterpret_cast<real *>(fr->f), getDistanceScaleFactor(input), fr->natoms, DIM, datatype); fr->bF = TRUE; break; case TNG_GMX_LAMBDA: switch (datatype) { case TNG_FLOAT_DATA: fr->lambda = *(reinterpret_cast<float *>(values)); break; case TNG_DOUBLE_DATA: fr->lambda = *(reinterpret_cast<double *>(values)); break; default: gmx_incons("Illegal datatype lambda value!"); } fr->bLambda = TRUE; break; default: gmx_warning("Illegal block type! Currently GROMACS tools can only handle certain data types. Skipping block."); } /* values does not have to be freed before reading next frame. It will * be reallocated if it is not NULL. */ } fr->step = static_cast<int>(frameNumber); fr->bStep = TRUE; // Convert the time to ps fr->time = frameTime / PICO; fr->bTime = TRUE; /* values must be freed before leaving this function */ sfree(values); return bOK; #else GMX_UNUSED_VALUE(input); GMX_UNUSED_VALUE(fr); GMX_UNUSED_VALUE(requestedIds); GMX_UNUSED_VALUE(numRequestedIds); return FALSE; #endif }
gmx_bool gmx_get_tng_data_next_frame_of_block_type(tng_trajectory_t input, gmx_int64_t blockId, real **values, gmx_int64_t *frameNumber, double *frameTime, gmx_int64_t *nValuesPerFrame, gmx_int64_t *nAtoms, real *prec, char *name, int maxLen, gmx_bool *bOK) { #if GMX_USE_TNG tng_function_status stat; char datatype = -1; gmx_int64_t codecId; int blockDependency; void *data = 0; double localPrec; stat = tng_data_block_name_get(input, blockId, name, maxLen); if (stat != TNG_SUCCESS) { gmx_file("Cannot read next frame of TNG file"); } stat = tng_data_block_dependency_get(input, blockId, &blockDependency); if (stat != TNG_SUCCESS) { gmx_file("Cannot read next frame of TNG file"); } if (blockDependency & TNG_PARTICLE_DEPENDENT) { tng_num_particles_get(input, nAtoms); stat = tng_util_particle_data_next_frame_read(input, blockId, &data, &datatype, frameNumber, frameTime); } else { *nAtoms = 1; /* There are not actually any atoms, but it is used for allocating memory */ stat = tng_util_non_particle_data_next_frame_read(input, blockId, &data, &datatype, frameNumber, frameTime); } if (stat == TNG_CRITICAL) { gmx_file("Cannot read next frame of TNG file"); } if (stat == TNG_FAILURE) { *bOK = TRUE; return FALSE; } stat = tng_data_block_num_values_per_frame_get(input, blockId, nValuesPerFrame); if (stat != TNG_SUCCESS) { gmx_file("Cannot read next frame of TNG file"); } snew(*values, sizeof(real) * *nValuesPerFrame * *nAtoms); convert_array_to_real_array(data, *values, getDistanceScaleFactor(input), *nAtoms, *nValuesPerFrame, datatype); tng_util_frame_current_compression_get(input, blockId, &codecId, &localPrec); /* This must be updated if/when more lossy compression methods are added */ if (codecId != TNG_TNG_COMPRESSION) { *prec = -1.0; } else { *prec = localPrec; } *bOK = TRUE; return TRUE; #else GMX_UNUSED_VALUE(input); GMX_UNUSED_VALUE(blockId); GMX_UNUSED_VALUE(values); GMX_UNUSED_VALUE(frameNumber); GMX_UNUSED_VALUE(frameTime); GMX_UNUSED_VALUE(nValuesPerFrame); GMX_UNUSED_VALUE(nAtoms); GMX_UNUSED_VALUE(prec); GMX_UNUSED_VALUE(name); GMX_UNUSED_VALUE(maxLen); GMX_UNUSED_VALUE(bOK); return FALSE; #endif }