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,2017,2018,2019, 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.
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/mdtypes/state.h"
54 #include "gromacs/pbcutil/pbc.h"
55 #include "gromacs/topology/topology.h"
56 #include "gromacs/trajectory/energyframe.h"
57 #include "gromacs/utility/compare.h"
58 #include "gromacs/utility/fatalerror.h"
59 #include "gromacs/utility/futil.h"
60 #include "gromacs/utility/gmxassert.h"
61 #include "gromacs/utility/smalloc.h"
63 /* The source code in this file should be thread-safe.
64 Please keep it that way. */
66 /* This number should be increased whenever the file format changes! */
67 static const int enx_version
= 5;
69 const char* enx_block_id_name
[] = { "Averaged orientation restraints",
70 "Instantaneous orientation restraints",
71 "Orientation restraint order tensor(s)",
72 "Distance restraints",
79 /* Stuff for reading pre 4.1 energy files */
82 gmx_bool bOldFileOpen
; /* Is this an open old file? */
83 gmx_bool bReadFirstStep
; /* Did we read the first step? */
84 int first_step
; /* First step in the energy file */
85 int step_prev
; /* Previous step */
86 int nsum_prev
; /* Previous step sum length */
87 t_energy
* ener_prev
; /* Previous energy sums */
98 static void enxsubblock_init(t_enxsubblock
* sb
)
102 sb
->type
= xdr_datatype_double
;
104 sb
->type
= xdr_datatype_float
;
120 static void enxsubblock_free(t_enxsubblock
* sb
)
156 for (i
= 0; i
< sb
->sval_alloc
; i
++)
169 /* allocate the appropriate amount of memory for the given type and nr */
170 static void enxsubblock_alloc(t_enxsubblock
* sb
)
172 /* allocate the appropriate amount of memory */
175 case xdr_datatype_float
:
176 if (sb
->nr
> sb
->fval_alloc
)
178 srenew(sb
->fval
, sb
->nr
);
179 sb
->fval_alloc
= sb
->nr
;
182 case xdr_datatype_double
:
183 if (sb
->nr
> sb
->dval_alloc
)
185 srenew(sb
->dval
, sb
->nr
);
186 sb
->dval_alloc
= sb
->nr
;
189 case xdr_datatype_int
:
190 if (sb
->nr
> sb
->ival_alloc
)
192 srenew(sb
->ival
, sb
->nr
);
193 sb
->ival_alloc
= sb
->nr
;
196 case xdr_datatype_int64
:
197 if (sb
->nr
> sb
->lval_alloc
)
199 srenew(sb
->lval
, sb
->nr
);
200 sb
->lval_alloc
= sb
->nr
;
203 case xdr_datatype_char
:
204 if (sb
->nr
> sb
->cval_alloc
)
206 srenew(sb
->cval
, sb
->nr
);
207 sb
->cval_alloc
= sb
->nr
;
210 case xdr_datatype_string
:
211 if (sb
->nr
> sb
->sval_alloc
)
215 srenew(sb
->sval
, sb
->nr
);
216 for (i
= sb
->sval_alloc
; i
< sb
->nr
; i
++)
218 sb
->sval
[i
] = nullptr;
220 sb
->sval_alloc
= sb
->nr
;
223 default: gmx_incons("Unknown block type: this file is corrupted or from the future");
227 static void enxblock_init(t_enxblock
* eb
)
235 static void enxblock_free(t_enxblock
* eb
)
237 if (eb
->nsub_alloc
> 0)
240 for (i
= 0; i
< eb
->nsub_alloc
; i
++)
242 enxsubblock_free(&(eb
->sub
[i
]));
250 void init_enxframe(t_enxframe
* fr
)
259 fr
->nblock_alloc
= 0;
264 void free_enxframe(t_enxframe
* fr
)
272 for (b
= 0; b
< fr
->nblock_alloc
; b
++)
274 enxblock_free(&(fr
->block
[b
]));
279 void add_blocks_enxframe(t_enxframe
* fr
, int n
)
282 if (n
> fr
->nblock_alloc
)
286 srenew(fr
->block
, n
);
287 for (b
= fr
->nblock_alloc
; b
< fr
->nblock
; b
++)
289 enxblock_init(&(fr
->block
[b
]));
291 fr
->nblock_alloc
= n
;
295 t_enxblock
* find_block_id_enxframe(t_enxframe
* ef
, int id
, t_enxblock
* prev
)
297 gmx_off_t starti
= 0;
302 starti
= (prev
- ef
->block
) + 1;
304 for (i
= starti
; i
< ef
->nblock
; i
++)
306 if (ef
->block
[i
].id
== id
)
308 return &(ef
->block
[i
]);
314 void add_subblocks_enxblock(t_enxblock
* eb
, int n
)
317 if (eb
->nsub
> eb
->nsub_alloc
)
322 for (b
= eb
->nsub_alloc
; b
< n
; b
++)
324 enxsubblock_init(&(eb
->sub
[b
]));
330 static void enx_warning(const char* msg
)
332 if (getenv("GMX_ENX_NO_FATAL") != nullptr)
334 gmx_warning("%s", msg
);
338 gmx_fatal(FARGS
, "%s\n%s", msg
,
339 "If you want to use the correct frames before the corrupted frame and avoid this "
340 "fatal error set the env.var. GMX_ENX_NO_FATAL");
344 static void edr_strings(XDR
* xdr
, gmx_bool bRead
, int file_version
, int n
, gmx_enxnm_t
** nms
)
353 for (i
= 0; i
< n
; i
++)
369 if (!xdr_string(xdr
, &(nm
->name
), STRLEN
))
371 gmx_file("Cannot write energy names to file; maybe you are out of disk space?");
373 if (file_version
>= 2)
375 if (!xdr_string(xdr
, &(nm
->unit
), STRLEN
))
377 gmx_file("Cannot write energy names to file; maybe you are out of disk space?");
382 nm
->unit
= gmx_strdup("kJ/mol");
387 void do_enxnms(ener_file_t ef
, int* nre
, gmx_enxnm_t
** nms
)
391 gmx_bool bRead
= gmx_fio_getread(ef
->fio
);
394 xdr
= gmx_fio_getxdr(ef
->fio
);
396 if (!xdr_int(xdr
, &magic
))
400 gmx_file("Cannot write energy names to file; maybe you are out of disk space?");
407 /* Assume this is an old edr format */
410 ef
->eo
.bOldFileOpen
= TRUE
;
411 ef
->eo
.bReadFirstStep
= FALSE
;
412 srenew(ef
->eo
.ener_prev
, *nre
);
416 ef
->eo
.bOldFileOpen
= FALSE
;
420 gmx_fatal(FARGS
, "Energy names magic number mismatch, this is not a GROMACS edr file");
422 file_version
= enx_version
;
423 xdr_int(xdr
, &file_version
);
424 if (file_version
> enx_version
)
426 gmx_fatal(FARGS
, "reading tpx file (%s) version %d with version %d program",
427 gmx_fio_getname(ef
->fio
), file_version
, enx_version
);
431 if (file_version
!= enx_version
)
433 fprintf(stderr
, "Note: enx file_version %d, software version %d\n", file_version
, enx_version
);
436 edr_strings(xdr
, bRead
, file_version
, *nre
, nms
);
439 static gmx_bool
do_eheader(ener_file_t ef
,
443 gmx_bool
* bWrongPrecision
,
446 int magic
= -7777777;
447 real first_real_to_check
;
448 int b
, zero
= 0, dum
= 0;
449 gmx_bool bRead
= gmx_fio_getread(ef
->fio
);
453 xdr_datatype dtreal
= xdr_datatype_float
;
455 xdr_datatype dtreal
= xdr_datatype_double
;
460 *bWrongPrecision
= FALSE
;
464 /* The original energy frame started with a real,
465 * so we have to use a real for compatibility.
466 * This is VERY DIRTY code, since do_eheader can be called
467 * with the wrong precision set and then we could read r > -1e10,
468 * while actually the intention was r < -1e10.
469 * When nre_test >= 0, do_eheader should therefore terminate
470 * before the number of i/o calls starts depending on what has been read
471 * (which is the case for for instance the block sizes for variable
472 * number of blocks, where this number is read before).
474 first_real_to_check
= -2e10
;
475 if (!gmx_fio_do_real(ef
->fio
, first_real_to_check
))
479 if (first_real_to_check
> -1e10
)
481 /* Assume we are reading an old format */
483 fr
->t
= first_real_to_check
;
484 if (!gmx_fio_do_int(ef
->fio
, dum
))
492 if (!gmx_fio_do_int(ef
->fio
, magic
))
496 if (magic
!= -7777777)
498 enx_warning("Energy header magic number mismatch, this is not a GROMACS edr file");
502 *file_version
= enx_version
;
503 if (!gmx_fio_do_int(ef
->fio
, *file_version
))
507 if (*bOK
&& *file_version
> enx_version
)
509 gmx_fatal(FARGS
, "reading tpx file (%s) version %d with version %d program",
510 gmx_fio_getname(ef
->fio
), *file_version
, enx_version
);
512 if (!gmx_fio_do_double(ef
->fio
, fr
->t
))
516 if (!gmx_fio_do_int64(ef
->fio
, fr
->step
))
520 if (!bRead
&& fr
->nsum
== 1)
522 /* Do not store sums of length 1,
523 * since this does not add information.
525 if (!gmx_fio_do_int(ef
->fio
, zero
))
532 if (!gmx_fio_do_int(ef
->fio
, fr
->nsum
))
537 if (*file_version
>= 3)
539 if (!gmx_fio_do_int64(ef
->fio
, fr
->nsteps
))
546 fr
->nsteps
= std::max(1, fr
->nsum
);
548 if (*file_version
>= 5)
550 if (!gmx_fio_do_double(ef
->fio
, fr
->dt
))
560 if (!gmx_fio_do_int(ef
->fio
, fr
->nre
))
564 if (*file_version
< 4)
566 if (!gmx_fio_do_int(ef
->fio
, ndisre
))
573 /* now reserved for possible future use */
574 if (!gmx_fio_do_int(ef
->fio
, dum
))
580 if (!gmx_fio_do_int(ef
->fio
, fr
->nblock
))
591 if (*file_version
>= 4)
593 enx_warning("Distance restraint blocks in old style in new style file");
601 /* Frames could have nre=0, so we can not rely only on the fr->nre check */
602 if (bRead
&& nre_test
>= 0
603 && ((fr
->nre
> 0 && fr
->nre
!= nre_test
) || fr
->nre
< 0 || ndisre
< 0 || fr
->nblock
< 0))
607 *bWrongPrecision
= TRUE
;
612 /* we now know what these should be, or we've already bailed out because
613 of wrong precision */
614 if (*file_version
== 1 && (fr
->t
< 0 || fr
->t
> 1e20
|| fr
->step
< 0))
617 "edr file with negative step number or unreasonable time (and without version "
626 add_blocks_enxframe(fr
, fr
->nblock
);
632 /* sub[0] is the instantaneous data, sub[1] is time averaged */
633 add_subblocks_enxblock(&(fr
->block
[0]), 2);
634 fr
->block
[0].id
= enxDISRE
;
635 fr
->block
[0].sub
[0].nr
= ndisre
;
636 fr
->block
[0].sub
[1].nr
= ndisre
;
637 fr
->block
[0].sub
[0].type
= dtreal
;
638 fr
->block
[0].sub
[1].type
= dtreal
;
642 /* read block header info */
643 for (b
= startb
; b
< fr
->nblock
; b
++)
645 if (*file_version
< 4)
647 /* blocks in old version files always have 1 subblock that
648 consists of reals. */
653 add_subblocks_enxblock(&(fr
->block
[b
]), 1);
657 if (fr
->block
[b
].nsub
!= 1)
659 gmx_incons("Writing an old version .edr file with too many subblocks");
661 if (fr
->block
[b
].sub
[0].type
!= dtreal
)
663 gmx_incons("Writing an old version .edr file the wrong subblock type");
666 nrint
= fr
->block
[b
].sub
[0].nr
;
668 if (!gmx_fio_do_int(ef
->fio
, nrint
))
672 fr
->block
[b
].id
= b
- startb
;
673 fr
->block
[b
].sub
[0].nr
= nrint
;
674 fr
->block
[b
].sub
[0].type
= dtreal
;
679 /* in the new version files, the block header only contains
680 the ID and the number of subblocks */
681 int nsub
= fr
->block
[b
].nsub
;
682 *bOK
= *bOK
&& gmx_fio_do_int(ef
->fio
, fr
->block
[b
].id
);
683 *bOK
= *bOK
&& gmx_fio_do_int(ef
->fio
, nsub
);
685 fr
->block
[b
].nsub
= nsub
;
688 add_subblocks_enxblock(&(fr
->block
[b
]), nsub
);
691 /* read/write type & size for each subblock */
692 for (i
= 0; i
< nsub
; i
++)
694 t_enxsubblock
* sub
= &(fr
->block
[b
].sub
[i
]); /* shortcut */
695 int typenr
= sub
->type
;
697 *bOK
= *bOK
&& gmx_fio_do_int(ef
->fio
, typenr
);
698 *bOK
= *bOK
&& gmx_fio_do_int(ef
->fio
, sub
->nr
);
700 sub
->type
= static_cast<xdr_datatype
>(typenr
);
704 if (!gmx_fio_do_int(ef
->fio
, fr
->e_size
))
709 /* now reserved for possible future use */
710 if (!gmx_fio_do_int(ef
->fio
, dum
))
715 /* Do a dummy int to keep the format compatible with the old code */
716 if (!gmx_fio_do_int(ef
->fio
, dum
))
721 if (*bOK
&& *file_version
== 1 && nre_test
< 0)
723 if (!ef
->eo
.bReadFirstStep
)
725 ef
->eo
.bReadFirstStep
= TRUE
;
726 ef
->eo
.first_step
= fr
->step
;
727 ef
->eo
.step_prev
= fr
->step
;
728 ef
->eo
.nsum_prev
= 0;
731 fr
->nsum
= fr
->step
- ef
->eo
.first_step
+ 1;
732 fr
->nsteps
= fr
->step
- ef
->eo
.step_prev
;
739 void free_enxnms(int n
, gmx_enxnm_t
* nms
)
743 for (i
= 0; i
< n
; i
++)
752 void close_enx(ener_file_t ef
)
759 if (gmx_fio_close(ef
->fio
) != 0)
762 "Cannot close energy file; it might be corrupt, or maybe you are out of disk "
767 void done_ener_file(ener_file_t ef
)
769 // Free the contents, then the pointer itself
774 /*!\brief Return TRUE if a file exists but is empty, otherwise FALSE.
776 * If the file exists but has length larger than zero, if it does not exist, or
777 * if there is a file system error, FALSE will be returned instead.
779 * \param fn File name to test
781 * \return TRUE if file could be open but is empty, otherwise FALSE.
783 static gmx_bool
empty_file(const char* fn
)
790 fp
= gmx_fio_fopen(fn
, "r");
791 ret
= fread(&dum
, sizeof(dum
), 1, fp
);
792 bEmpty
= (feof(fp
) != 0);
795 // bEmpty==TRUE but ret!=0 would likely be some strange I/O error, but at
796 // least it's not a normal empty file, so we return FALSE in that case.
797 return (bEmpty
&& ret
== 0);
801 ener_file_t
open_enx(const char* fn
, const char* mode
)
804 gmx_enxnm_t
* nms
= nullptr;
805 int file_version
= -1;
807 gmx_bool bWrongPrecision
, bOK
= TRUE
;
808 struct ener_file
* ef
;
814 ef
->fio
= gmx_fio_open(fn
, mode
);
815 gmx_fio_setprecision(ef
->fio
, FALSE
);
816 do_enxnms(ef
, &nre
, &nms
);
818 do_eheader(ef
, &file_version
, fr
, nre
, &bWrongPrecision
, &bOK
);
821 gmx_file("Cannot read energy file header. Corrupt file?");
824 /* Now check whether this file is in single precision */
826 && ((fr
->e_size
&& (fr
->nre
== nre
)
827 && (nre
* 4 * static_cast<long int>(sizeof(float)) == fr
->e_size
))))
829 fprintf(stderr
, "Opened %s as single precision energy file\n", fn
);
830 free_enxnms(nre
, nms
);
834 gmx_fio_rewind(ef
->fio
);
835 gmx_fio_setprecision(ef
->fio
, TRUE
);
836 do_enxnms(ef
, &nre
, &nms
);
837 do_eheader(ef
, &file_version
, fr
, nre
, &bWrongPrecision
, &bOK
);
840 gmx_file("Cannot write energy file header; maybe you are out of disk space?");
843 if (((fr
->e_size
&& (fr
->nre
== nre
)
844 && (nre
* 4 * static_cast<long int>(sizeof(double)) == fr
->e_size
))))
846 fprintf(stderr
, "Opened %s as double precision energy file\n", fn
);
852 gmx_fatal(FARGS
, "File %s is empty", fn
);
856 gmx_fatal(FARGS
, "Energy file %s not recognized, maybe different CPU?", fn
);
859 free_enxnms(nre
, nms
);
863 gmx_fio_rewind(ef
->fio
);
867 ef
->fio
= gmx_fio_open(fn
, mode
);
875 t_fileio
* enx_file_pointer(const ener_file
* ef
)
880 static void convert_full_sums(ener_old_t
* ener_old
, t_enxframe
* fr
)
884 double esum_all
, eav_all
;
890 for (i
= 0; i
< fr
->nre
; i
++)
892 if (fr
->ener
[i
].e
!= 0)
896 if (fr
->ener
[i
].esum
!= 0)
901 if (ne
> 0 && ns
== 0)
903 /* We do not have all energy sums */
908 /* Convert old full simulation sums to sums between energy frames */
909 nstep_all
= fr
->step
- ener_old
->first_step
+ 1;
910 if (fr
->nsum
> 1 && fr
->nsum
== nstep_all
&& ener_old
->nsum_prev
> 0)
912 /* Set the new sum length: the frame step difference */
913 fr
->nsum
= fr
->step
- ener_old
->step_prev
;
914 for (i
= 0; i
< fr
->nre
; i
++)
916 esum_all
= fr
->ener
[i
].esum
;
917 eav_all
= fr
->ener
[i
].eav
;
918 fr
->ener
[i
].esum
= esum_all
- ener_old
->ener_prev
[i
].esum
;
920 eav_all
- ener_old
->ener_prev
[i
].eav
921 - gmx::square(ener_old
->ener_prev
[i
].esum
/ (nstep_all
- fr
->nsum
) - esum_all
/ nstep_all
)
922 * (nstep_all
- fr
->nsum
) * nstep_all
/ static_cast<double>(fr
->nsum
);
923 ener_old
->ener_prev
[i
].esum
= esum_all
;
924 ener_old
->ener_prev
[i
].eav
= eav_all
;
926 ener_old
->nsum_prev
= nstep_all
;
928 else if (fr
->nsum
> 0)
930 if (fr
->nsum
!= nstep_all
)
933 "\nWARNING: something is wrong with the energy sums, will not use exact "
935 ener_old
->nsum_prev
= 0;
939 ener_old
->nsum_prev
= nstep_all
;
941 /* Copy all sums to ener_prev */
942 for (i
= 0; i
< fr
->nre
; i
++)
944 ener_old
->ener_prev
[i
].esum
= fr
->ener
[i
].esum
;
945 ener_old
->ener_prev
[i
].eav
= fr
->ener
[i
].eav
;
949 ener_old
->step_prev
= fr
->step
;
952 gmx_bool
do_enx(ener_file_t ef
, t_enxframe
* fr
)
954 int file_version
= -1;
956 gmx_bool bRead
, bOK
, bOK1
, bSane
;
957 real tmp1
, tmp2
, rdum
;
961 bRead
= gmx_fio_getread(ef
->fio
);
964 fr
->e_size
= fr
->nre
* sizeof(fr
->ener
[0].e
) * 4;
965 /*d_size = fr->ndisre*(sizeof(real)*2);*/
968 if (!do_eheader(ef
, &file_version
, fr
, -1, nullptr, &bOK
))
972 fprintf(stderr
, "\rLast energy frame read %d time %8.3f ", ef
->framenr
- 1,
978 fprintf(stderr
, "\nWARNING: Incomplete energy frame: nr %d time %8.3f\n",
984 gmx_file("Cannot write energy file header; maybe you are out of disk space?");
990 if ((ef
->framenr
< 20 || ef
->framenr
% 10 == 0) && (ef
->framenr
< 200 || ef
->framenr
% 100 == 0)
991 && (ef
->framenr
< 2000 || ef
->framenr
% 1000 == 0))
993 fprintf(stderr
, "\rReading energy frame %6d time %8.3f ", ef
->framenr
, fr
->t
);
996 ef
->frametime
= fr
->t
;
998 /* Check sanity of this header */
1000 for (b
= 0; b
< fr
->nblock
; b
++)
1002 bSane
= bSane
|| (fr
->block
[b
].nsub
> 0);
1004 if (!((fr
->step
>= 0) && bSane
) && bRead
)
1006 fprintf(stderr
, "\nWARNING: there may be something wrong with energy file %s\n",
1007 gmx_fio_getname(ef
->fio
));
1008 fprintf(stderr
, "Found: step=%" PRId64
", nre=%d, nblock=%d, time=%g.\n", fr
->step
, fr
->nre
,
1011 if (bRead
&& fr
->nre
> fr
->e_alloc
)
1013 srenew(fr
->ener
, fr
->nre
);
1014 for (i
= fr
->e_alloc
; (i
< fr
->nre
); i
++)
1017 fr
->ener
[i
].eav
= 0;
1018 fr
->ener
[i
].esum
= 0;
1020 fr
->e_alloc
= fr
->nre
;
1023 for (i
= 0; i
< fr
->nre
; i
++)
1025 bOK
= bOK
&& gmx_fio_do_real(ef
->fio
, fr
->ener
[i
].e
);
1027 /* Do not store sums of length 1,
1028 * since this does not add information.
1030 if (file_version
== 1 || (bRead
&& fr
->nsum
> 0) || fr
->nsum
> 1)
1032 tmp1
= fr
->ener
[i
].eav
;
1033 bOK
= bOK
&& gmx_fio_do_real(ef
->fio
, tmp1
);
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
);
1044 fr
->ener
[i
].esum
= tmp2
;
1047 if (file_version
== 1)
1049 /* Old, unused real */
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 */
1071 for (i
= 0; i
< nsub
; i
++)
1073 t_enxsubblock
* sub
= &(fr
->block
[b
].sub
[i
]); /* shortcut */
1077 enxsubblock_alloc(sub
);
1080 /* read/write data */
1083 case xdr_datatype_float
:
1084 bOK1
= gmx_fio_ndo_float(ef
->fio
, sub
->fval
, sub
->nr
);
1086 case xdr_datatype_double
:
1087 bOK1
= gmx_fio_ndo_double(ef
->fio
, sub
->dval
, sub
->nr
);
1089 case xdr_datatype_int
: bOK1
= gmx_fio_ndo_int(ef
->fio
, sub
->ival
, sub
->nr
); break;
1090 case xdr_datatype_int64
:
1091 bOK1
= gmx_fio_ndo_int64(ef
->fio
, sub
->lval
, sub
->nr
);
1093 case xdr_datatype_char
:
1094 bOK1
= gmx_fio_ndo_uchar(ef
->fio
, sub
->cval
, sub
->nr
);
1096 case xdr_datatype_string
:
1097 bOK1
= gmx_fio_ndo_string(ef
->fio
, sub
->sval
, sub
->nr
);
1101 "Reading unknown block data type: this file is corrupted or from the "
1110 if (gmx_fio_flush(ef
->fio
) != 0)
1112 gmx_file("Cannot write energy file; maybe you are out of disk space?");
1120 fprintf(stderr
, "\nLast energy frame read %d", ef
->framenr
- 1);
1121 fprintf(stderr
, "\nWARNING: Incomplete energy frame: nr %d time %8.3f\n", ef
->framenr
, fr
->t
);
1125 gmx_fatal(FARGS
, "could not write energies");
1133 static real
find_energy(const char* name
, int nre
, gmx_enxnm_t
* enm
, t_enxframe
* fr
)
1137 for (i
= 0; i
< nre
; i
++)
1139 if (std::strcmp(enm
[i
].name
, name
) == 0)
1141 return fr
->ener
[i
].e
;
1146 "Could not find energy term named '%s'. Either the energy file is from a different "
1147 "run or this state variable is not stored in the energy file. In the latter case "
1148 "(and if you did not modify the T/P-coupling setup), you can read the state in mdrun "
1149 "instead, by passing in a checkpoint file.",
1154 void get_enx_state(const char* fn
, real t
, const SimulationGroups
& groups
, t_inputrec
* ir
, t_state
* state
)
1156 /* Should match the names in mdebin.c */
1157 static const char* boxvel_nm
[] = { "Box-Vel-XX", "Box-Vel-YY", "Box-Vel-ZZ",
1158 "Box-Vel-YX", "Box-Vel-ZX", "Box-Vel-ZY" };
1160 static const char* baro_nm
[] = { "Barostat" };
1163 int ind0
[] = { XX
, YY
, ZZ
, YY
, ZZ
, ZZ
};
1164 int ind1
[] = { XX
, YY
, ZZ
, XX
, XX
, YY
};
1165 int nre
, nfr
, i
, j
, ni
, npcoupl
;
1168 gmx_enxnm_t
* enm
= nullptr;
1172 in
= open_enx(fn
, "r");
1173 do_enxnms(in
, &nre
, &enm
);
1176 while ((nfr
== 0 || fr
->t
!= t
) && do_enx(in
, fr
))
1181 fprintf(stderr
, "\n");
1183 if (nfr
== 0 || fr
->t
!= t
)
1185 gmx_fatal(FARGS
, "Could not find frame with time %f in '%s'", t
, fn
);
1188 npcoupl
= TRICLINIC(ir
->compress
) ? 6 : 3;
1189 if (ir
->epc
== epcPARRINELLORAHMAN
)
1191 clear_mat(state
->boxv
);
1192 for (i
= 0; i
< npcoupl
; i
++)
1194 state
->boxv
[ind0
[i
]][ind1
[i
]] = find_energy(boxvel_nm
[i
], nre
, enm
, fr
);
1196 fprintf(stderr
, "\nREAD %d BOX VELOCITIES FROM %s\n\n", npcoupl
, fn
);
1199 if (ir
->etc
== etcNOSEHOOVER
)
1205 for (i
= 0; i
< state
->ngtc
; i
++)
1207 ni
= groups
.groups
[SimulationAtomGroupType::TemperatureCoupling
][i
];
1208 bufi
= *(groups
.groupNames
[ni
]);
1209 for (j
= 0; (j
< state
->nhchainlength
); j
++)
1211 if (inputrecNvtTrotter(ir
))
1213 sprintf(cns
, "-%d", j
);
1215 sprintf(buf
, "Xi%s-%s", cns
, bufi
);
1216 state
->nosehoover_xi
[i
] = find_energy(buf
, nre
, enm
, fr
);
1217 sprintf(buf
, "vXi%s-%s", cns
, bufi
);
1218 state
->nosehoover_vxi
[i
] = find_energy(buf
, nre
, enm
, fr
);
1221 fprintf(stderr
, "\nREAD %d NOSE-HOOVER Xi chains FROM %s\n\n", state
->ngtc
, fn
);
1223 if (inputrecNptTrotter(ir
) || inputrecNphTrotter(ir
))
1225 for (i
= 0; i
< state
->nnhpres
; i
++)
1227 bufi
= baro_nm
[0]; /* All barostat DOF's together for now */
1228 for (j
= 0; (j
< state
->nhchainlength
); j
++)
1230 sprintf(buf
, "Xi-%d-%s", j
, bufi
);
1231 state
->nhpres_xi
[i
] = find_energy(buf
, nre
, enm
, fr
);
1232 sprintf(buf
, "vXi-%d-%s", j
, bufi
);
1233 state
->nhpres_vxi
[i
] = find_energy(buf
, nre
, enm
, fr
);
1236 fprintf(stderr
, "\nREAD %d NOSE-HOOVER BAROSTAT Xi chains FROM %s\n\n", state
->nnhpres
, fn
);
1240 free_enxnms(nre
, enm
);
1245 static real
ener_tensor_diag(int n
,
1260 d1
= tensi
[i
] / DIM
;
1261 d2
= tensi
[i
] - d1
* DIM
;
1263 /* Find the diagonal elements d1 and d2 */
1264 len
= std::strlen(enm1
[ind1
[i
]].name
);
1268 for (j
= 0; j
< n
; j
++)
1270 if (tensi
[j
] >= 0 && std::strlen(enm1
[ind1
[j
]].name
) == len
1271 && std::strncmp(enm1
[ind1
[i
]].name
, enm1
[ind1
[j
]].name
, len
- 2) == 0
1272 && (tensi
[j
] == d1
* DIM
+ d1
|| tensi
[j
] == d2
* DIM
+ d2
))
1274 prod1
*= fabs(e1
[ind1
[j
]].e
);
1275 prod2
*= fabs(e2
[ind2
[j
]].e
);
1282 return 0.5 * (std::sqrt(prod1
) + std::sqrt(prod2
));
1290 static gmx_bool
enernm_equal(const char* nm1
, const char* nm2
)
1294 len1
= std::strlen(nm1
);
1295 len2
= std::strlen(nm2
);
1297 /* Remove " (bar)" at the end of a name */
1298 if (len1
> 6 && std::strcmp(nm1
+ len1
- 6, " (bar)") == 0)
1302 if (len2
> 6 && std::strcmp(nm2
+ len2
- 6, " (bar)") == 0)
1307 return (len1
== len2
&& gmx_strncasecmp(nm1
, nm2
, len1
) == 0);
1310 static void cmp_energies(FILE* fp
,
1324 int *tensi
, len
, d1
, d2
;
1325 real ftol_i
, abstol_i
;
1327 snew(tensi
, maxener
);
1328 /* Check for tensor elements ending on "-XX", "-XY", ... , "-ZZ" */
1329 for (i
= 0; (i
< maxener
); i
++)
1333 len
= std::strlen(enm1
[ii
].name
);
1334 if (len
> 3 && enm1
[ii
].name
[len
- 3] == '-')
1336 d1
= enm1
[ii
].name
[len
- 2] - 'X';
1337 d2
= enm1
[ii
].name
[len
- 1] - 'X';
1338 if (d1
>= 0 && d1
< DIM
&& d2
>= 0 && d2
< DIM
)
1340 tensi
[i
] = d1
* DIM
+ d2
;
1345 for (i
= 0; (i
< maxener
); i
++)
1347 /* Check if this is an off-diagonal tensor element */
1348 if (tensi
[i
] >= 0 && tensi
[i
] != 0 && tensi
[i
] != 4 && tensi
[i
] != 8)
1350 /* Turn on the relative tolerance check (4 is maximum relative diff.) */
1352 /* Do the relative tolerance through an absolute tolerance times
1353 * the size of diagonal components of the tensor.
1355 abstol_i
= ftol
* ener_tensor_diag(nre
, ind1
, ind2
, enm1
, tensi
, i
, e1
, e2
);
1358 fprintf(debug
, "tensor '%s' val %f diag %f\n", enm1
[i
].name
, e1
[i
].e
, abstol_i
/ ftol
);
1362 /* We found a diagonal, we need to check with the minimum tolerance */
1363 abstol_i
= std::min(abstol_i
, abstol
);
1367 /* We did not find a diagonal, ignore the relative tolerance check */
1376 if (!equal_real(e1
[ind1
[i
]].e
, e2
[ind2
[i
]].e
, ftol_i
, abstol_i
))
1378 fprintf(fp
, "%-15s step %3d: %12g, step %3d: %12g\n", enm1
[ind1
[i
]].name
, step1
,
1379 e1
[ind1
[i
]].e
, step2
, e2
[ind2
[i
]].e
);
1387 static void cmp_disres(t_enxframe
*fr1
, t_enxframe
*fr2
, real ftol
, real abstol
)
1390 char bav
[64], bt
[64], bs
[22];
1392 cmp_int(stdout
, "ndisre", -1, fr1
->ndisre
, fr2
->ndisre
);
1393 if ((fr1
->ndisre
== fr2
->ndisre
) && (fr1
->ndisre
> 0))
1395 sprintf(bav
, "step %s: disre rav", gmx_step_str(fr1
->step
, bs
));
1396 sprintf(bt
, "step %s: disre rt", gmx_step_str(fr1
->step
, bs
));
1397 for (i
= 0; (i
< fr1
->ndisre
); i
++)
1399 cmp_real(stdout
, bav
, i
, fr1
->disre_rm3tav
[i
], fr2
->disre_rm3tav
[i
], ftol
, abstol
);
1400 cmp_real(stdout
, bt
, i
, fr1
->disre_rt
[i
], fr2
->disre_rt
[i
], ftol
, abstol
);
1406 static void cmp_eblocks(t_enxframe
* fr1
, t_enxframe
* fr2
, real ftol
, real abstol
)
1409 char buf
[64], bs
[22];
1411 cmp_int(stdout
, "nblock", -1, fr1
->nblock
, fr2
->nblock
);
1412 if ((fr1
->nblock
== fr2
->nblock
) && (fr1
->nblock
> 0))
1414 for (j
= 0; (j
< fr1
->nblock
); j
++)
1416 t_enxblock
*b1
, *b2
; /* convenience vars */
1418 b1
= &(fr1
->block
[j
]);
1419 b2
= &(fr2
->block
[j
]);
1421 sprintf(buf
, "step %s: block[%d]", gmx_step_str(fr1
->step
, bs
), j
);
1422 cmp_int(stdout
, buf
, -1, b1
->nsub
, b2
->nsub
);
1423 cmp_int(stdout
, buf
, -1, b1
->id
, b2
->id
);
1425 if ((b1
->nsub
== b2
->nsub
) && (b1
->id
== b2
->id
))
1427 for (i
= 0; i
< b1
->nsub
; i
++)
1429 t_enxsubblock
*s1
, *s2
;
1434 cmp_int(stdout
, buf
, -1, static_cast<int>(s1
->type
), static_cast<int>(s2
->type
));
1435 cmp_int64(stdout
, buf
, s1
->nr
, s2
->nr
);
1437 if ((s1
->type
== s2
->type
) && (s1
->nr
== s2
->nr
))
1441 case xdr_datatype_float
:
1442 for (k
= 0; k
< s1
->nr
; k
++)
1444 cmp_float(stdout
, buf
, i
, s1
->fval
[k
], s2
->fval
[k
], ftol
, abstol
);
1447 case xdr_datatype_double
:
1448 for (k
= 0; k
< s1
->nr
; k
++)
1450 cmp_double(stdout
, buf
, i
, s1
->dval
[k
], s2
->dval
[k
], ftol
, abstol
);
1453 case xdr_datatype_int
:
1454 for (k
= 0; k
< s1
->nr
; k
++)
1456 cmp_int(stdout
, buf
, i
, s1
->ival
[k
], s2
->ival
[k
]);
1459 case xdr_datatype_int64
:
1460 for (k
= 0; k
< s1
->nr
; k
++)
1462 cmp_int64(stdout
, buf
, s1
->lval
[k
], s2
->lval
[k
]);
1465 case xdr_datatype_char
:
1466 for (k
= 0; k
< s1
->nr
; k
++)
1468 cmp_uc(stdout
, buf
, i
, s1
->cval
[k
], s2
->cval
[k
]);
1471 case xdr_datatype_string
:
1472 for (k
= 0; k
< s1
->nr
; k
++)
1474 cmp_str(stdout
, buf
, i
, s1
->sval
[k
], s2
->sval
[k
]);
1477 default: gmx_incons("Unknown data type!!");
1486 void comp_enx(const char* fn1
, const char* fn2
, real ftol
, real abstol
, const char* lastener
)
1488 int nre
, nre1
, nre2
;
1489 ener_file_t in1
, in2
;
1490 int i
, j
, maxener
, *ind1
, *ind2
, *have
;
1491 gmx_enxnm_t
*enm1
= nullptr, *enm2
= nullptr;
1492 t_enxframe
* fr1
, *fr2
;
1495 fprintf(stdout
, "comparing energy file %s and %s\n\n", fn1
, fn2
);
1497 in1
= open_enx(fn1
, "r");
1498 in2
= open_enx(fn2
, "r");
1499 do_enxnms(in1
, &nre1
, &enm1
);
1500 do_enxnms(in2
, &nre2
, &enm2
);
1503 fprintf(stdout
, "There are %d and %d terms in the energy files\n\n", nre1
, nre2
);
1507 fprintf(stdout
, "There are %d terms in the energy files\n\n", nre1
);
1514 for (i
= 0; i
< nre1
; i
++)
1516 for (j
= 0; j
< nre2
; j
++)
1518 if (enernm_equal(enm1
[i
].name
, enm2
[j
].name
))
1527 if (nre
== 0 || ind1
[nre
- 1] != i
)
1529 cmp_str(stdout
, "enm", i
, enm1
[i
].name
, "-");
1532 for (i
= 0; i
< nre2
; i
++)
1536 cmp_str(stdout
, "enm", i
, "-", enm2
[i
].name
);
1541 for (i
= 0; i
< nre
; i
++)
1543 if ((lastener
!= nullptr) && (std::strstr(enm1
[i
].name
, lastener
) != nullptr))
1550 fprintf(stdout
, "There are %d terms to compare in the energy files\n\n", maxener
);
1552 for (i
= 0; i
< maxener
; i
++)
1554 cmp_str(stdout
, "unit", i
, enm1
[ind1
[i
]].unit
, enm2
[ind2
[i
]].unit
);
1561 b1
= do_enx(in1
, fr1
);
1562 b2
= do_enx(in2
, fr2
);
1565 fprintf(stdout
, "\nEnd of file on %s but not on %s\n", fn2
, fn1
);
1569 fprintf(stdout
, "\nEnd of file on %s but not on %s\n", fn1
, fn2
);
1571 else if (!b1
&& !b2
)
1573 fprintf(stdout
, "\nFiles read successfully\n");
1577 cmp_real(stdout
, "t", -1, fr1
->t
, fr2
->t
, ftol
, abstol
);
1578 cmp_int(stdout
, "step", -1, fr1
->step
, fr2
->step
);
1579 /* We don't want to print the nre mismatch for every frame */
1580 /* cmp_int(stdout,"nre",-1,fr1->nre,fr2->nre); */
1581 if ((fr1
->nre
>= nre
) && (fr2
->nre
>= nre
))
1583 cmp_energies(stdout
, fr1
->step
, fr1
->step
, fr1
->ener
, fr2
->ener
, enm1
, ftol
, abstol
,
1584 nre
, ind1
, ind2
, maxener
);
1586 /*cmp_disres(fr1,fr2,ftol,abstol);*/
1587 cmp_eblocks(fr1
, fr2
, ftol
, abstol
);