Split up compare.*
[gromacs.git] / src / gromacs / fileio / enxio.cpp
blobc8e208dcc7803f132fd8b3548e675266acc5a0d9
1 /*
2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5 * Copyright (c) 2001-2004, The GROMACS development team.
6 * Copyright (c) 2013,2014,2015,2016, by the GROMACS development team, led by
7 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
8 * and including many others, as listed in the AUTHORS file in the
9 * top-level source directory and at http://www.gromacs.org.
11 * GROMACS is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public License
13 * as published by the Free Software Foundation; either version 2.1
14 * of the License, or (at your option) any later version.
16 * GROMACS is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with GROMACS; if not, see
23 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
24 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 * If you want to redistribute modifications to GROMACS, please
27 * consider that scientific software is very special. Version
28 * control is crucial - bugs must be traceable. We will be happy to
29 * consider code for inclusion in the official distribution, but
30 * derived work must not be called official GROMACS. Details are found
31 * in the README & COPYING files - if they are missing, get the
32 * official version at http://www.gromacs.org.
34 * To help us fund GROMACS development, we humbly ask that you cite
35 * the research papers on the package. Check out http://www.gromacs.org.
37 #include "gmxpre.h"
39 #include "enxio.h"
41 #include <cstdlib>
42 #include <cstring>
44 #include <algorithm>
46 #include "gromacs/fileio/gmxfio.h"
47 #include "gromacs/fileio/gmxfio-xdr.h"
48 #include "gromacs/fileio/xdrf.h"
49 #include "gromacs/math/functions.h"
50 #include "gromacs/math/vec.h"
51 #include "gromacs/mdtypes/inputrec.h"
52 #include "gromacs/mdtypes/md_enums.h"
53 #include "gromacs/pbcutil/pbc.h"
54 #include "gromacs/topology/topology.h"
55 #include "gromacs/utility/compare.h"
56 #include "gromacs/utility/fatalerror.h"
57 #include "gromacs/utility/futil.h"
58 #include "gromacs/utility/gmxassert.h"
59 #include "gromacs/utility/smalloc.h"
61 /* The source code in this file should be thread-safe.
62 Please keep it that way. */
64 /* This number should be increased whenever the file format changes! */
65 static const int enx_version = 5;
67 const char *enx_block_id_name[] = {
68 "Averaged orientation restraints",
69 "Instantaneous orientation restraints",
70 "Orientation restraint order tensor(s)",
71 "Distance restraints",
72 "Free energy data",
73 "BAR histogram",
74 "Delta H raw data"
78 /* Stuff for reading pre 4.1 energy files */
79 typedef struct {
80 gmx_bool bOldFileOpen; /* Is this an open old file? */
81 gmx_bool bReadFirstStep; /* Did we read the first step? */
82 int first_step; /* First step in the energy file */
83 int step_prev; /* Previous step */
84 int nsum_prev; /* Previous step sum length */
85 t_energy *ener_prev; /* Previous energy sums */
86 } ener_old_t;
88 struct ener_file
90 ener_old_t eo;
91 t_fileio *fio;
92 int framenr;
93 real frametime;
96 static void enxsubblock_init(t_enxsubblock *sb)
98 sb->nr = 0;
99 #if GMX_DOUBLE
100 sb->type = xdr_datatype_double;
101 #else
102 sb->type = xdr_datatype_float;
103 #endif
104 sb->fval = NULL;
105 sb->dval = NULL;
106 sb->ival = NULL;
107 sb->lval = NULL;
108 sb->cval = NULL;
109 sb->sval = NULL;
110 sb->fval_alloc = 0;
111 sb->dval_alloc = 0;
112 sb->ival_alloc = 0;
113 sb->lval_alloc = 0;
114 sb->cval_alloc = 0;
115 sb->sval_alloc = 0;
118 static void enxsubblock_free(t_enxsubblock *sb)
120 if (sb->fval_alloc)
122 sfree(sb->fval);
123 sb->fval_alloc = 0;
124 sb->fval = NULL;
126 if (sb->dval_alloc)
128 sfree(sb->dval);
129 sb->dval_alloc = 0;
130 sb->dval = NULL;
132 if (sb->ival_alloc)
134 sfree(sb->ival);
135 sb->ival_alloc = 0;
136 sb->ival = NULL;
138 if (sb->lval_alloc)
140 sfree(sb->lval);
141 sb->lval_alloc = 0;
142 sb->lval = NULL;
144 if (sb->cval_alloc)
146 sfree(sb->cval);
147 sb->cval_alloc = 0;
148 sb->cval = NULL;
150 if (sb->sval_alloc)
152 int i;
154 for (i = 0; i < sb->sval_alloc; i++)
156 if (sb->sval[i])
158 sfree(sb->sval[i]);
161 sfree(sb->sval);
162 sb->sval_alloc = 0;
163 sb->sval = NULL;
167 /* allocate the appropriate amount of memory for the given type and nr */
168 static void enxsubblock_alloc(t_enxsubblock *sb)
170 /* allocate the appropriate amount of memory */
171 switch (sb->type)
173 case xdr_datatype_float:
174 if (sb->nr > sb->fval_alloc)
176 srenew(sb->fval, sb->nr);
177 sb->fval_alloc = sb->nr;
179 break;
180 case xdr_datatype_double:
181 if (sb->nr > sb->dval_alloc)
183 srenew(sb->dval, sb->nr);
184 sb->dval_alloc = sb->nr;
186 break;
187 case xdr_datatype_int:
188 if (sb->nr > sb->ival_alloc)
190 srenew(sb->ival, sb->nr);
191 sb->ival_alloc = sb->nr;
193 break;
194 case xdr_datatype_int64:
195 if (sb->nr > sb->lval_alloc)
197 srenew(sb->lval, sb->nr);
198 sb->lval_alloc = sb->nr;
200 break;
201 case xdr_datatype_char:
202 if (sb->nr > sb->cval_alloc)
204 srenew(sb->cval, sb->nr);
205 sb->cval_alloc = sb->nr;
207 break;
208 case xdr_datatype_string:
209 if (sb->nr > sb->sval_alloc)
211 int i;
213 srenew(sb->sval, sb->nr);
214 for (i = sb->sval_alloc; i < sb->nr; i++)
216 sb->sval[i] = NULL;
218 sb->sval_alloc = sb->nr;
220 break;
221 default:
222 gmx_incons("Unknown block type: this file is corrupted or from the future");
226 static void enxblock_init(t_enxblock *eb)
228 eb->id = enxOR;
229 eb->nsub = 0;
230 eb->sub = NULL;
231 eb->nsub_alloc = 0;
234 static void enxblock_free(t_enxblock *eb)
236 if (eb->nsub_alloc > 0)
238 int i;
239 for (i = 0; i < eb->nsub_alloc; i++)
241 enxsubblock_free(&(eb->sub[i]));
243 sfree(eb->sub);
244 eb->nsub_alloc = 0;
245 eb->sub = NULL;
249 void init_enxframe(t_enxframe *fr)
251 fr->e_alloc = 0;
252 fr->ener = NULL;
254 /*fr->d_alloc=0;*/
255 fr->ener = NULL;
257 /*fr->ndisre=0;*/
259 fr->nblock = 0;
260 fr->nblock_alloc = 0;
261 fr->block = NULL;
265 void free_enxframe(t_enxframe *fr)
267 int b;
269 if (fr->e_alloc)
271 sfree(fr->ener);
273 for (b = 0; b < fr->nblock_alloc; b++)
275 enxblock_free(&(fr->block[b]));
277 sfree(fr->block);
280 void add_blocks_enxframe(t_enxframe *fr, int n)
282 fr->nblock = n;
283 if (n > fr->nblock_alloc)
285 int b;
287 srenew(fr->block, n);
288 for (b = fr->nblock_alloc; b < fr->nblock; b++)
290 enxblock_init(&(fr->block[b]));
292 fr->nblock_alloc = n;
296 t_enxblock *find_block_id_enxframe(t_enxframe *ef, int id, t_enxblock *prev)
298 gmx_off_t starti = 0;
299 gmx_off_t i;
301 if (prev)
303 starti = (prev - ef->block) + 1;
305 for (i = starti; i < ef->nblock; i++)
307 if (ef->block[i].id == id)
309 return &(ef->block[i]);
312 return NULL;
315 void add_subblocks_enxblock(t_enxblock *eb, int n)
317 eb->nsub = n;
318 if (eb->nsub > eb->nsub_alloc)
320 int b;
322 srenew(eb->sub, n);
323 for (b = eb->nsub_alloc; b < n; b++)
325 enxsubblock_init(&(eb->sub[b]));
327 eb->nsub_alloc = n;
331 static void enx_warning(const char *msg)
333 if (getenv("GMX_ENX_NO_FATAL") != NULL)
335 gmx_warning(msg);
337 else
339 gmx_fatal(FARGS, "%s\n%s",
340 msg,
341 "If you want to use the correct frames before the corrupted frame and avoid this fatal error set the env.var. GMX_ENX_NO_FATAL");
345 static void edr_strings(XDR *xdr, gmx_bool bRead, int file_version,
346 int n, gmx_enxnm_t **nms)
348 int i;
349 gmx_enxnm_t *nm;
351 if (*nms == NULL)
353 snew(*nms, n);
355 for (i = 0; i < n; i++)
357 nm = &(*nms)[i];
358 if (bRead)
360 if (nm->name)
362 sfree(nm->name);
363 nm->name = NULL;
365 if (nm->unit)
367 sfree(nm->unit);
368 nm->unit = NULL;
371 if (!xdr_string(xdr, &(nm->name), STRLEN))
373 gmx_file("Cannot write energy names to file; maybe you are out of disk space?");
375 if (file_version >= 2)
377 if (!xdr_string(xdr, &(nm->unit), STRLEN))
379 gmx_file("Cannot write energy names to file; maybe you are out of disk space?");
382 else
384 nm->unit = gmx_strdup("kJ/mol");
389 void do_enxnms(ener_file_t ef, int *nre, gmx_enxnm_t **nms)
391 int magic = -55555;
392 XDR *xdr;
393 gmx_bool bRead = gmx_fio_getread(ef->fio);
394 int file_version;
396 xdr = gmx_fio_getxdr(ef->fio);
398 if (!xdr_int(xdr, &magic))
400 if (!bRead)
402 gmx_file("Cannot write energy names to file; maybe you are out of disk space?");
404 *nre = 0;
405 return;
407 if (magic > 0)
409 /* Assume this is an old edr format */
410 file_version = 1;
411 *nre = magic;
412 ef->eo.bOldFileOpen = TRUE;
413 ef->eo.bReadFirstStep = FALSE;
414 srenew(ef->eo.ener_prev, *nre);
416 else
418 ef->eo.bOldFileOpen = FALSE;
420 if (magic != -55555)
422 gmx_fatal(FARGS, "Energy names magic number mismatch, this is not a GROMACS edr file");
424 file_version = enx_version;
425 xdr_int(xdr, &file_version);
426 if (file_version > enx_version)
428 gmx_fatal(FARGS, "reading tpx file (%s) version %d with version %d program", gmx_fio_getname(ef->fio), file_version, enx_version);
430 xdr_int(xdr, nre);
432 if (file_version != enx_version)
434 fprintf(stderr, "Note: enx file_version %d, software version %d\n",
435 file_version, enx_version);
438 edr_strings(xdr, bRead, file_version, *nre, nms);
441 static gmx_bool do_eheader(ener_file_t ef, int *file_version, t_enxframe *fr,
442 int nre_test, gmx_bool *bWrongPrecision, gmx_bool *bOK)
444 int magic = -7777777;
445 real first_real_to_check;
446 int b, zero = 0, dum = 0;
447 gmx_bool bRead = gmx_fio_getread(ef->fio);
448 int ndisre = 0;
449 int startb = 0;
450 #if !GMX_DOUBLE
451 xdr_datatype dtreal = xdr_datatype_float;
452 #else
453 xdr_datatype dtreal = xdr_datatype_double;
454 #endif
456 if (bWrongPrecision)
458 *bWrongPrecision = FALSE;
461 *bOK = TRUE;
462 /* The original energy frame started with a real,
463 * so we have to use a real for compatibility.
464 * This is VERY DIRTY code, since do_eheader can be called
465 * with the wrong precision set and then we could read r > -1e10,
466 * while actually the intention was r < -1e10.
467 * When nre_test >= 0, do_eheader should therefore terminate
468 * before the number of i/o calls starts depending on what has been read
469 * (which is the case for for instance the block sizes for variable
470 * number of blocks, where this number is read before).
472 first_real_to_check = -2e10;
473 if (!gmx_fio_do_real(ef->fio, first_real_to_check))
475 return FALSE;
477 if (first_real_to_check > -1e10)
479 /* Assume we are reading an old format */
480 *file_version = 1;
481 fr->t = first_real_to_check;
482 if (!gmx_fio_do_int(ef->fio, dum))
484 *bOK = FALSE;
486 fr->step = dum;
488 else
490 if (!gmx_fio_do_int(ef->fio, magic))
492 *bOK = FALSE;
494 if (magic != -7777777)
496 enx_warning("Energy header magic number mismatch, this is not a GROMACS edr file");
497 *bOK = FALSE;
498 return FALSE;
500 *file_version = enx_version;
501 if (!gmx_fio_do_int(ef->fio, *file_version))
503 *bOK = FALSE;
505 if (*bOK && *file_version > enx_version)
507 gmx_fatal(FARGS, "reading tpx file (%s) version %d with version %d program", gmx_fio_getname(ef->fio), file_version, enx_version);
509 if (!gmx_fio_do_double(ef->fio, fr->t))
511 *bOK = FALSE;
513 if (!gmx_fio_do_int64(ef->fio, fr->step))
515 *bOK = FALSE;
517 if (!bRead && fr->nsum == 1)
519 /* Do not store sums of length 1,
520 * since this does not add information.
522 if (!gmx_fio_do_int(ef->fio, zero))
524 *bOK = FALSE;
527 else
529 if (!gmx_fio_do_int(ef->fio, fr->nsum))
531 *bOK = FALSE;
534 if (*file_version >= 3)
536 if (!gmx_fio_do_int64(ef->fio, fr->nsteps))
538 *bOK = FALSE;
541 else
543 fr->nsteps = std::max(1, fr->nsum);
545 if (*file_version >= 5)
547 if (!gmx_fio_do_double(ef->fio, fr->dt))
549 *bOK = FALSE;
552 else
554 fr->dt = 0;
557 if (!gmx_fio_do_int(ef->fio, fr->nre))
559 *bOK = FALSE;
561 if (*file_version < 4)
563 if (!gmx_fio_do_int(ef->fio, ndisre))
565 *bOK = FALSE;
568 else
570 /* now reserved for possible future use */
571 if (!gmx_fio_do_int(ef->fio, dum))
573 *bOK = FALSE;
577 if (!gmx_fio_do_int(ef->fio, fr->nblock))
579 *bOK = FALSE;
581 if (fr->nblock < 0)
583 *bOK = FALSE;
586 if (ndisre != 0)
588 if (*file_version >= 4)
590 enx_warning("Distance restraint blocks in old style in new style file");
591 *bOK = FALSE;
592 return FALSE;
594 fr->nblock += 1;
598 /* Frames could have nre=0, so we can not rely only on the fr->nre check */
599 if (bRead && nre_test >= 0 &&
600 ((fr->nre > 0 && fr->nre != nre_test) ||
601 fr->nre < 0 || ndisre < 0 || fr->nblock < 0))
603 if (bWrongPrecision)
605 *bWrongPrecision = TRUE;
607 return *bOK;
610 /* we now know what these should be, or we've already bailed out because
611 of wrong precision */
612 if (*file_version == 1 && (fr->t < 0 || fr->t > 1e20 || fr->step < 0 ) )
614 enx_warning("edr file with negative step number or unreasonable time (and without version number).");
615 *bOK = FALSE;
616 return FALSE;
620 if (*bOK && bRead)
622 add_blocks_enxframe(fr, fr->nblock);
625 startb = 0;
626 if (ndisre > 0)
628 /* sub[0] is the instantaneous data, sub[1] is time averaged */
629 add_subblocks_enxblock(&(fr->block[0]), 2);
630 fr->block[0].id = enxDISRE;
631 fr->block[0].sub[0].nr = ndisre;
632 fr->block[0].sub[1].nr = ndisre;
633 fr->block[0].sub[0].type = dtreal;
634 fr->block[0].sub[1].type = dtreal;
635 startb++;
638 /* read block header info */
639 for (b = startb; b < fr->nblock; b++)
641 if (*file_version < 4)
643 /* blocks in old version files always have 1 subblock that
644 consists of reals. */
645 int nrint;
647 if (bRead)
649 add_subblocks_enxblock(&(fr->block[b]), 1);
651 else
653 if (fr->block[b].nsub != 1)
655 gmx_incons("Writing an old version .edr file with too many subblocks");
657 if (fr->block[b].sub[0].type != dtreal)
659 gmx_incons("Writing an old version .edr file the wrong subblock type");
662 nrint = fr->block[b].sub[0].nr;
664 if (!gmx_fio_do_int(ef->fio, nrint))
666 *bOK = FALSE;
668 fr->block[b].id = b - startb;
669 fr->block[b].sub[0].nr = nrint;
670 fr->block[b].sub[0].type = dtreal;
672 else
674 int i;
675 /* in the new version files, the block header only contains
676 the ID and the number of subblocks */
677 int nsub = fr->block[b].nsub;
678 *bOK = *bOK && gmx_fio_do_int(ef->fio, fr->block[b].id);
679 *bOK = *bOK && gmx_fio_do_int(ef->fio, nsub);
681 fr->block[b].nsub = nsub;
682 if (bRead)
684 add_subblocks_enxblock(&(fr->block[b]), nsub);
687 /* read/write type & size for each subblock */
688 for (i = 0; i < nsub; i++)
690 t_enxsubblock *sub = &(fr->block[b].sub[i]); /* shortcut */
691 int typenr = sub->type;
693 *bOK = *bOK && gmx_fio_do_int(ef->fio, typenr);
694 *bOK = *bOK && gmx_fio_do_int(ef->fio, sub->nr);
696 sub->type = (xdr_datatype)typenr;
700 if (!gmx_fio_do_int(ef->fio, fr->e_size))
702 *bOK = FALSE;
705 /* now reserved for possible future use */
706 if (!gmx_fio_do_int(ef->fio, dum))
708 *bOK = FALSE;
711 /* Do a dummy int to keep the format compatible with the old code */
712 if (!gmx_fio_do_int(ef->fio, dum))
714 *bOK = FALSE;
717 if (*bOK && *file_version == 1 && nre_test < 0)
719 if (!ef->eo.bReadFirstStep)
721 ef->eo.bReadFirstStep = TRUE;
722 ef->eo.first_step = fr->step;
723 ef->eo.step_prev = fr->step;
724 ef->eo.nsum_prev = 0;
727 fr->nsum = fr->step - ef->eo.first_step + 1;
728 fr->nsteps = fr->step - ef->eo.step_prev;
729 fr->dt = 0;
732 return *bOK;
735 void free_enxnms(int n, gmx_enxnm_t *nms)
737 int i;
739 for (i = 0; i < n; i++)
741 sfree(nms[i].name);
742 sfree(nms[i].unit);
745 sfree(nms);
748 void close_enx(ener_file_t ef)
750 if (ef == NULL)
752 // Nothing to do
753 return;
755 if (gmx_fio_close(ef->fio) != 0)
757 gmx_file("Cannot close energy file; it might be corrupt, or maybe you are out of disk space?");
761 void done_ener_file(ener_file_t ef)
763 // Free the contents, then the pointer itself
764 close_enx(ef);
765 sfree(ef);
768 /*!\brief Return TRUE if a file exists but is empty, otherwise FALSE.
770 * If the file exists but has length larger than zero, if it does not exist, or
771 * if there is a file system error, FALSE will be returned instead.
773 * \param fn File name to test
775 * \return TRUE if file could be open but is empty, otherwise FALSE.
777 static gmx_bool
778 empty_file(const char *fn)
780 FILE *fp;
781 char dum;
782 int ret;
783 gmx_bool bEmpty;
785 fp = gmx_fio_fopen(fn, "r");
786 ret = fread(&dum, sizeof(dum), 1, fp);
787 bEmpty = feof(fp);
788 gmx_fio_fclose(fp);
790 // bEmpty==TRUE but ret!=0 would likely be some strange I/O error, but at
791 // least it's not a normal empty file, so we return FALSE in that case.
792 return (bEmpty && ret == 0);
796 ener_file_t open_enx(const char *fn, const char *mode)
798 int nre;
799 gmx_enxnm_t *nms = NULL;
800 int file_version = -1;
801 t_enxframe *fr;
802 gmx_bool bWrongPrecision, bOK = TRUE;
803 struct ener_file *ef;
805 snew(ef, 1);
807 if (mode[0] == 'r')
809 ef->fio = gmx_fio_open(fn, mode);
810 gmx_fio_setprecision(ef->fio, FALSE);
811 do_enxnms(ef, &nre, &nms);
812 snew(fr, 1);
813 do_eheader(ef, &file_version, fr, nre, &bWrongPrecision, &bOK);
814 if (!bOK)
816 gmx_file("Cannot read energy file header. Corrupt file?");
819 /* Now check whether this file is in single precision */
820 if (!bWrongPrecision &&
821 ((fr->e_size && (fr->nre == nre) &&
822 (nre*4*(long int)sizeof(float) == fr->e_size)) ) )
824 fprintf(stderr, "Opened %s as single precision energy file\n", fn);
825 free_enxnms(nre, nms);
827 else
829 gmx_fio_rewind(ef->fio);
830 gmx_fio_setprecision(ef->fio, TRUE);
831 do_enxnms(ef, &nre, &nms);
832 do_eheader(ef, &file_version, fr, nre, &bWrongPrecision, &bOK);
833 if (!bOK)
835 gmx_file("Cannot write energy file header; maybe you are out of disk space?");
838 if (((fr->e_size && (fr->nre == nre) &&
839 (nre*4*(long int)sizeof(double) == fr->e_size)) ))
841 fprintf(stderr, "Opened %s as double precision energy file\n",
842 fn);
844 else
846 if (empty_file(fn))
848 gmx_fatal(FARGS, "File %s is empty", fn);
850 else
852 gmx_fatal(FARGS, "Energy file %s not recognized, maybe different CPU?",
853 fn);
856 free_enxnms(nre, nms);
858 free_enxframe(fr);
859 sfree(fr);
860 gmx_fio_rewind(ef->fio);
862 else
864 ef->fio = gmx_fio_open(fn, mode);
867 ef->framenr = 0;
868 ef->frametime = 0;
869 return ef;
872 t_fileio *enx_file_pointer(const ener_file_t ef)
874 return ef->fio;
877 static void convert_full_sums(ener_old_t *ener_old, t_enxframe *fr)
879 int nstep_all;
880 int ne, ns, i;
881 double esum_all, eav_all;
883 if (fr->nsum > 0)
885 ne = 0;
886 ns = 0;
887 for (i = 0; i < fr->nre; i++)
889 if (fr->ener[i].e != 0)
891 ne++;
893 if (fr->ener[i].esum != 0)
895 ns++;
898 if (ne > 0 && ns == 0)
900 /* We do not have all energy sums */
901 fr->nsum = 0;
905 /* Convert old full simulation sums to sums between energy frames */
906 nstep_all = fr->step - ener_old->first_step + 1;
907 if (fr->nsum > 1 && fr->nsum == nstep_all && ener_old->nsum_prev > 0)
909 /* Set the new sum length: the frame step difference */
910 fr->nsum = fr->step - ener_old->step_prev;
911 for (i = 0; i < fr->nre; i++)
913 esum_all = fr->ener[i].esum;
914 eav_all = fr->ener[i].eav;
915 fr->ener[i].esum = esum_all - ener_old->ener_prev[i].esum;
916 fr->ener[i].eav = eav_all - ener_old->ener_prev[i].eav
917 - gmx::square(ener_old->ener_prev[i].esum/(nstep_all - fr->nsum)
918 - esum_all/nstep_all)*
919 (nstep_all - fr->nsum)*nstep_all/(double)fr->nsum;
920 ener_old->ener_prev[i].esum = esum_all;
921 ener_old->ener_prev[i].eav = eav_all;
923 ener_old->nsum_prev = nstep_all;
925 else if (fr->nsum > 0)
927 if (fr->nsum != nstep_all)
929 fprintf(stderr, "\nWARNING: something is wrong with the energy sums, will not use exact averages\n");
930 ener_old->nsum_prev = 0;
932 else
934 ener_old->nsum_prev = nstep_all;
936 /* Copy all sums to ener_prev */
937 for (i = 0; i < fr->nre; i++)
939 ener_old->ener_prev[i].esum = fr->ener[i].esum;
940 ener_old->ener_prev[i].eav = fr->ener[i].eav;
944 ener_old->step_prev = fr->step;
947 gmx_bool do_enx(ener_file_t ef, t_enxframe *fr)
949 int file_version = -1;
950 int i, b;
951 gmx_bool bRead, bOK, bOK1, bSane;
952 real tmp1, tmp2, rdum;
953 /*int d_size;*/
955 bOK = TRUE;
956 bRead = gmx_fio_getread(ef->fio);
957 if (!bRead)
959 fr->e_size = fr->nre*sizeof(fr->ener[0].e)*4;
960 /*d_size = fr->ndisre*(sizeof(real)*2);*/
963 if (!do_eheader(ef, &file_version, fr, -1, NULL, &bOK))
965 if (bRead)
967 fprintf(stderr, "\rLast energy frame read %d time %8.3f ",
968 ef->framenr-1, ef->frametime);
969 fflush(stderr);
971 if (!bOK)
973 fprintf(stderr,
974 "\nWARNING: Incomplete energy frame: nr %d time %8.3f\n",
975 ef->framenr, fr->t);
978 else
980 gmx_file("Cannot write energy file header; maybe you are out of disk space?");
982 return FALSE;
984 if (bRead)
986 if ((ef->framenr < 20 || ef->framenr % 10 == 0) &&
987 (ef->framenr < 200 || ef->framenr % 100 == 0) &&
988 (ef->framenr < 2000 || ef->framenr % 1000 == 0))
990 fprintf(stderr, "\rReading energy frame %6d time %8.3f ",
991 ef->framenr, fr->t);
993 ef->framenr++;
994 ef->frametime = fr->t;
996 /* Check sanity of this header */
997 bSane = fr->nre > 0;
998 for (b = 0; b < fr->nblock; b++)
1000 bSane = bSane || (fr->block[b].nsub > 0);
1002 if (!((fr->step >= 0) && bSane))
1004 fprintf(stderr, "\nWARNING: there may be something wrong with energy file %s\n",
1005 gmx_fio_getname(ef->fio));
1006 fprintf(stderr, "Found: step=%" GMX_PRId64 ", nre=%d, nblock=%d, time=%g.\n"
1007 "Trying to skip frame expect a crash though\n",
1008 fr->step, fr->nre, fr->nblock, fr->t);
1010 if (bRead && fr->nre > fr->e_alloc)
1012 srenew(fr->ener, fr->nre);
1013 for (i = fr->e_alloc; (i < fr->nre); i++)
1015 fr->ener[i].e = 0;
1016 fr->ener[i].eav = 0;
1017 fr->ener[i].esum = 0;
1019 fr->e_alloc = fr->nre;
1022 for (i = 0; i < fr->nre; i++)
1024 bOK = bOK && gmx_fio_do_real(ef->fio, fr->ener[i].e);
1026 /* Do not store sums of length 1,
1027 * since this does not add information.
1029 if (file_version == 1 ||
1030 (bRead && fr->nsum > 0) || fr->nsum > 1)
1032 tmp1 = fr->ener[i].eav;
1033 bOK = bOK && gmx_fio_do_real(ef->fio, tmp1);
1034 if (bRead)
1036 fr->ener[i].eav = tmp1;
1039 /* This is to save only in single precision (unless compiled in DP) */
1040 tmp2 = fr->ener[i].esum;
1041 bOK = bOK && gmx_fio_do_real(ef->fio, tmp2);
1042 if (bRead)
1044 fr->ener[i].esum = tmp2;
1047 if (file_version == 1)
1049 /* Old, unused real */
1050 rdum = 0;
1051 bOK = bOK && gmx_fio_do_real(ef->fio, rdum);
1056 /* Here we can not check for file_version==1, since one could have
1057 * continued an old format simulation with a new one with mdrun -append.
1059 if (bRead && ef->eo.bOldFileOpen)
1061 /* Convert old full simulation sums to sums between energy frames */
1062 convert_full_sums(&(ef->eo), fr);
1064 /* read the blocks */
1065 for (b = 0; b < fr->nblock; b++)
1067 /* now read the subblocks. */
1068 int nsub = fr->block[b].nsub; /* shortcut */
1069 int i;
1071 for (i = 0; i < nsub; i++)
1073 t_enxsubblock *sub = &(fr->block[b].sub[i]); /* shortcut */
1075 if (bRead)
1077 enxsubblock_alloc(sub);
1080 /* read/write data */
1081 switch (sub->type)
1083 case xdr_datatype_float:
1084 bOK1 = gmx_fio_ndo_float(ef->fio, sub->fval, sub->nr);
1085 break;
1086 case xdr_datatype_double:
1087 bOK1 = gmx_fio_ndo_double(ef->fio, sub->dval, sub->nr);
1088 break;
1089 case xdr_datatype_int:
1090 bOK1 = gmx_fio_ndo_int(ef->fio, sub->ival, sub->nr);
1091 break;
1092 case xdr_datatype_int64:
1093 bOK1 = gmx_fio_ndo_int64(ef->fio, sub->lval, sub->nr);
1094 break;
1095 case xdr_datatype_char:
1096 bOK1 = gmx_fio_ndo_uchar(ef->fio, sub->cval, sub->nr);
1097 break;
1098 case xdr_datatype_string:
1099 bOK1 = gmx_fio_ndo_string(ef->fio, sub->sval, sub->nr);
1100 break;
1101 default:
1102 gmx_incons("Reading unknown block data type: this file is corrupted or from the future");
1104 bOK = bOK && bOK1;
1108 if (!bRead)
1110 if (gmx_fio_flush(ef->fio) != 0)
1112 gmx_file("Cannot write energy file; maybe you are out of disk space?");
1116 if (!bOK)
1118 if (bRead)
1120 fprintf(stderr, "\nLast energy frame read %d",
1121 ef->framenr-1);
1122 fprintf(stderr, "\nWARNING: Incomplete energy frame: nr %d time %8.3f\n",
1123 ef->framenr, fr->t);
1125 else
1127 gmx_fatal(FARGS, "could not write energies");
1129 return FALSE;
1132 return TRUE;
1135 static real find_energy(const char *name, int nre, gmx_enxnm_t *enm,
1136 t_enxframe *fr)
1138 int i;
1140 for (i = 0; i < nre; i++)
1142 if (std::strcmp(enm[i].name, name) == 0)
1144 return fr->ener[i].e;
1148 gmx_fatal(FARGS, "Could not find energy term named '%s'", name);
1150 return 0;
1154 void get_enx_state(const char *fn, real t, const gmx_groups_t *groups, t_inputrec *ir,
1155 t_state *state)
1157 /* Should match the names in mdebin.c */
1158 static const char *boxvel_nm[] = {
1159 "Box-Vel-XX", "Box-Vel-YY", "Box-Vel-ZZ",
1160 "Box-Vel-YX", "Box-Vel-ZX", "Box-Vel-ZY"
1163 static const char *baro_nm[] = {
1164 "Barostat"
1168 int ind0[] = { XX, YY, ZZ, YY, ZZ, ZZ };
1169 int ind1[] = { XX, YY, ZZ, XX, XX, YY };
1170 int nre, nfr, i, j, ni, npcoupl;
1171 char buf[STRLEN];
1172 const char *bufi;
1173 gmx_enxnm_t *enm = NULL;
1174 t_enxframe *fr;
1175 ener_file_t in;
1177 in = open_enx(fn, "r");
1178 do_enxnms(in, &nre, &enm);
1179 snew(fr, 1);
1180 nfr = 0;
1181 while ((nfr == 0 || fr->t != t) && do_enx(in, fr))
1183 nfr++;
1185 close_enx(in);
1186 fprintf(stderr, "\n");
1188 if (nfr == 0 || fr->t != t)
1190 gmx_fatal(FARGS, "Could not find frame with time %f in '%s'", t, fn);
1193 npcoupl = TRICLINIC(ir->compress) ? 6 : 3;
1194 if (ir->epc == epcPARRINELLORAHMAN)
1196 clear_mat(state->boxv);
1197 for (i = 0; i < npcoupl; i++)
1199 state->boxv[ind0[i]][ind1[i]] =
1200 find_energy(boxvel_nm[i], nre, enm, fr);
1202 fprintf(stderr, "\nREAD %d BOX VELOCITIES FROM %s\n\n", npcoupl, fn);
1205 if (ir->etc == etcNOSEHOOVER)
1207 char cns[20];
1209 cns[0] = '\0';
1211 for (i = 0; i < state->ngtc; i++)
1213 ni = groups->grps[egcTC].nm_ind[i];
1214 bufi = *(groups->grpname[ni]);
1215 for (j = 0; (j < state->nhchainlength); j++)
1217 if (inputrecNvtTrotter(ir))
1219 sprintf(cns, "-%d", j);
1221 sprintf(buf, "Xi%s-%s", cns, bufi);
1222 state->nosehoover_xi[i] = find_energy(buf, nre, enm, fr);
1223 sprintf(buf, "vXi%s-%s", cns, bufi);
1224 state->nosehoover_vxi[i] = find_energy(buf, nre, enm, fr);
1228 fprintf(stderr, "\nREAD %d NOSE-HOOVER Xi chains FROM %s\n\n", state->ngtc, fn);
1230 if (inputrecNptTrotter(ir) || inputrecNphTrotter(ir))
1232 for (i = 0; i < state->nnhpres; i++)
1234 bufi = baro_nm[0]; /* All barostat DOF's together for now */
1235 for (j = 0; (j < state->nhchainlength); j++)
1237 sprintf(buf, "Xi-%d-%s", j, bufi);
1238 state->nhpres_xi[i] = find_energy(buf, nre, enm, fr);
1239 sprintf(buf, "vXi-%d-%s", j, bufi);
1240 state->nhpres_vxi[i] = find_energy(buf, nre, enm, fr);
1243 fprintf(stderr, "\nREAD %d NOSE-HOOVER BAROSTAT Xi chains FROM %s\n\n", state->nnhpres, fn);
1247 free_enxnms(nre, enm);
1248 free_enxframe(fr);
1249 sfree(fr);
1252 static real ener_tensor_diag(int n, int *ind1, int *ind2,
1253 gmx_enxnm_t *enm1,
1254 int *tensi, int i,
1255 t_energy e1[], t_energy e2[])
1257 int d1, d2;
1258 int j;
1259 real prod1, prod2;
1260 int nfound;
1261 size_t len;
1263 d1 = tensi[i]/DIM;
1264 d2 = tensi[i] - d1*DIM;
1266 /* Find the diagonal elements d1 and d2 */
1267 len = std::strlen(enm1[ind1[i]].name);
1268 prod1 = 1;
1269 prod2 = 1;
1270 nfound = 0;
1271 for (j = 0; j < n; j++)
1273 if (tensi[j] >= 0 &&
1274 std::strlen(enm1[ind1[j]].name) == len &&
1275 std::strncmp(enm1[ind1[i]].name, enm1[ind1[j]].name, len-2) == 0 &&
1276 (tensi[j] == d1*DIM+d1 || tensi[j] == d2*DIM+d2))
1278 prod1 *= fabs(e1[ind1[j]].e);
1279 prod2 *= fabs(e2[ind2[j]].e);
1280 nfound++;
1284 if (nfound == 2)
1286 return 0.5*(std::sqrt(prod1) + std::sqrt(prod2));
1288 else
1290 return 0;
1294 static gmx_bool enernm_equal(const char *nm1, const char *nm2)
1296 int len1, len2;
1298 len1 = std::strlen(nm1);
1299 len2 = std::strlen(nm2);
1301 /* Remove " (bar)" at the end of a name */
1302 if (len1 > 6 && std::strcmp(nm1+len1-6, " (bar)") == 0)
1304 len1 -= 6;
1306 if (len2 > 6 && std::strcmp(nm2+len2-6, " (bar)") == 0)
1308 len2 -= 6;
1311 return (len1 == len2 && gmx_strncasecmp(nm1, nm2, len1) == 0);
1314 static void cmp_energies(FILE *fp, int step1, int step2,
1315 t_energy e1[], t_energy e2[],
1316 gmx_enxnm_t *enm1,
1317 real ftol, real abstol,
1318 int nre, int *ind1, int *ind2, int maxener)
1320 int i, ii;
1321 int *tensi, len, d1, d2;
1322 real ftol_i, abstol_i;
1324 snew(tensi, maxener);
1325 /* Check for tensor elements ending on "-XX", "-XY", ... , "-ZZ" */
1326 for (i = 0; (i < maxener); i++)
1328 ii = ind1[i];
1329 tensi[i] = -1;
1330 len = std::strlen(enm1[ii].name);
1331 if (len > 3 && enm1[ii].name[len-3] == '-')
1333 d1 = enm1[ii].name[len-2] - 'X';
1334 d2 = enm1[ii].name[len-1] - 'X';
1335 if (d1 >= 0 && d1 < DIM &&
1336 d2 >= 0 && d2 < DIM)
1338 tensi[i] = d1*DIM + d2;
1343 for (i = 0; (i < maxener); i++)
1345 /* Check if this is an off-diagonal tensor element */
1346 if (tensi[i] >= 0 && tensi[i] != 0 && tensi[i] != 4 && tensi[i] != 8)
1348 /* Turn on the relative tolerance check (4 is maximum relative diff.) */
1349 ftol_i = 5;
1350 /* Do the relative tolerance through an absolute tolerance times
1351 * the size of diagonal components of the tensor.
1353 abstol_i = ftol*ener_tensor_diag(nre, ind1, ind2, enm1, tensi, i, e1, e2);
1354 if (debug)
1356 fprintf(debug, "tensor '%s' val %f diag %f\n",
1357 enm1[i].name, e1[i].e, abstol_i/ftol);
1359 if (abstol_i > 0)
1361 /* We found a diagonal, we need to check with the minimum tolerance */
1362 abstol_i = std::min(abstol_i, abstol);
1364 else
1366 /* We did not find a diagonal, ignore the relative tolerance check */
1367 abstol_i = abstol;
1370 else
1372 ftol_i = ftol;
1373 abstol_i = abstol;
1375 if (!equal_real(e1[ind1[i]].e, e2[ind2[i]].e, ftol_i, abstol_i))
1377 fprintf(fp, "%-15s step %3d: %12g, step %3d: %12g\n",
1378 enm1[ind1[i]].name,
1379 step1, e1[ind1[i]].e,
1380 step2, e2[ind2[i]].e);
1384 sfree(tensi);
1387 #if 0
1388 static void cmp_disres(t_enxframe *fr1, t_enxframe *fr2, real ftol, real abstol)
1390 int i;
1391 char bav[64], bt[64], bs[22];
1393 cmp_int(stdout, "ndisre", -1, fr1->ndisre, fr2->ndisre);
1394 if ((fr1->ndisre == fr2->ndisre) && (fr1->ndisre > 0))
1396 sprintf(bav, "step %s: disre rav", gmx_step_str(fr1->step, bs));
1397 sprintf(bt, "step %s: disre rt", gmx_step_str(fr1->step, bs));
1398 for (i = 0; (i < fr1->ndisre); i++)
1400 cmp_real(stdout, bav, i, fr1->disre_rm3tav[i], fr2->disre_rm3tav[i], ftol, abstol);
1401 cmp_real(stdout, bt, i, fr1->disre_rt[i], fr2->disre_rt[i], ftol, abstol);
1405 #endif
1407 static void cmp_eblocks(t_enxframe *fr1, t_enxframe *fr2, real ftol, real abstol)
1409 int i, j, k;
1410 char buf[64], bs[22];
1412 cmp_int(stdout, "nblock", -1, fr1->nblock, fr2->nblock);
1413 if ((fr1->nblock == fr2->nblock) && (fr1->nblock > 0))
1415 for (j = 0; (j < fr1->nblock); j++)
1417 t_enxblock *b1, *b2; /* convenience vars */
1419 b1 = &(fr1->block[j]);
1420 b2 = &(fr2->block[j]);
1422 sprintf(buf, "step %s: block[%d]", gmx_step_str(fr1->step, bs), j);
1423 cmp_int(stdout, buf, -1, b1->nsub, b2->nsub);
1424 cmp_int(stdout, buf, -1, b1->id, b2->id);
1426 if ( (b1->nsub == b2->nsub) && (b1->id == b2->id) )
1428 for (i = 0; i < b1->nsub; i++)
1430 t_enxsubblock *s1, *s2;
1432 s1 = &(b1->sub[i]);
1433 s2 = &(b2->sub[i]);
1435 cmp_int(stdout, buf, -1, (int)s1->type, (int)s2->type);
1436 cmp_int64(stdout, buf, s1->nr, s2->nr);
1438 if ((s1->type == s2->type) && (s1->nr == s2->nr))
1440 switch (s1->type)
1442 case xdr_datatype_float:
1443 for (k = 0; k < s1->nr; k++)
1445 cmp_float(stdout, buf, i,
1446 s1->fval[k], s2->fval[k],
1447 ftol, abstol);
1449 break;
1450 case xdr_datatype_double:
1451 for (k = 0; k < s1->nr; k++)
1453 cmp_double(stdout, buf, i,
1454 s1->dval[k], s2->dval[k],
1455 ftol, abstol);
1457 break;
1458 case xdr_datatype_int:
1459 for (k = 0; k < s1->nr; k++)
1461 cmp_int(stdout, buf, i,
1462 s1->ival[k], s2->ival[k]);
1464 break;
1465 case xdr_datatype_int64:
1466 for (k = 0; k < s1->nr; k++)
1468 cmp_int64(stdout, buf,
1469 s1->lval[k], s2->lval[k]);
1471 break;
1472 case xdr_datatype_char:
1473 for (k = 0; k < s1->nr; k++)
1475 cmp_uc(stdout, buf, i,
1476 s1->cval[k], s2->cval[k]);
1478 break;
1479 case xdr_datatype_string:
1480 for (k = 0; k < s1->nr; k++)
1482 cmp_str(stdout, buf, i,
1483 s1->sval[k], s2->sval[k]);
1485 break;
1486 default:
1487 gmx_incons("Unknown data type!!");
1496 void comp_enx(const char *fn1, const char *fn2, real ftol, real abstol, const char *lastener)
1498 int nre, nre1, nre2;
1499 ener_file_t in1, in2;
1500 int i, j, maxener, *ind1, *ind2, *have;
1501 gmx_enxnm_t *enm1 = NULL, *enm2 = NULL;
1502 t_enxframe *fr1, *fr2;
1503 gmx_bool b1, b2;
1505 fprintf(stdout, "comparing energy file %s and %s\n\n", fn1, fn2);
1507 in1 = open_enx(fn1, "r");
1508 in2 = open_enx(fn2, "r");
1509 do_enxnms(in1, &nre1, &enm1);
1510 do_enxnms(in2, &nre2, &enm2);
1511 if (nre1 != nre2)
1513 fprintf(stdout, "There are %d and %d terms in the energy files\n\n",
1514 nre1, nre2);
1516 else
1518 fprintf(stdout, "There are %d terms in the energy files\n\n", nre1);
1521 snew(ind1, nre1);
1522 snew(ind2, nre2);
1523 snew(have, nre2);
1524 nre = 0;
1525 for (i = 0; i < nre1; i++)
1527 for (j = 0; j < nre2; j++)
1529 if (enernm_equal(enm1[i].name, enm2[j].name))
1531 ind1[nre] = i;
1532 ind2[nre] = j;
1533 have[j] = 1;
1534 nre++;
1535 break;
1538 if (nre == 0 || ind1[nre-1] != i)
1540 cmp_str(stdout, "enm", i, enm1[i].name, "-");
1543 for (i = 0; i < nre2; i++)
1545 if (have[i] == 0)
1547 cmp_str(stdout, "enm", i, "-", enm2[i].name);
1551 maxener = nre;
1552 for (i = 0; i < nre; i++)
1554 if ((lastener != NULL) && (std::strstr(enm1[i].name, lastener) != NULL))
1556 maxener = i+1;
1557 break;
1561 fprintf(stdout, "There are %d terms to compare in the energy files\n\n",
1562 maxener);
1564 for (i = 0; i < maxener; i++)
1566 cmp_str(stdout, "unit", i, enm1[ind1[i]].unit, enm2[ind2[i]].unit);
1569 snew(fr1, 1);
1570 snew(fr2, 1);
1573 b1 = do_enx(in1, fr1);
1574 b2 = do_enx(in2, fr2);
1575 if (b1 && !b2)
1577 fprintf(stdout, "\nEnd of file on %s but not on %s\n", fn2, fn1);
1579 else if (!b1 && b2)
1581 fprintf(stdout, "\nEnd of file on %s but not on %s\n", fn1, fn2);
1583 else if (!b1 && !b2)
1585 fprintf(stdout, "\nFiles read successfully\n");
1587 else
1589 cmp_real(stdout, "t", -1, fr1->t, fr2->t, ftol, abstol);
1590 cmp_int(stdout, "step", -1, fr1->step, fr2->step);
1591 /* We don't want to print the nre mismatch for every frame */
1592 /* cmp_int(stdout,"nre",-1,fr1->nre,fr2->nre); */
1593 if ((fr1->nre >= nre) && (fr2->nre >= nre))
1595 cmp_energies(stdout, fr1->step, fr1->step, fr1->ener, fr2->ener,
1596 enm1, ftol, abstol, nre, ind1, ind2, maxener);
1598 /*cmp_disres(fr1,fr2,ftol,abstol);*/
1599 cmp_eblocks(fr1, fr2, ftol, abstol);
1602 while (b1 && b2);
1604 close_enx(in1);
1605 close_enx(in2);
1607 free_enxframe(fr2);
1608 sfree(fr2);
1609 free_enxframe(fr1);
1610 sfree(fr1);