fixed the reported temperature with Brownian dynamics
[alexxy/gromacs.git] / src / gmxlib / checkpoint.c
1 /* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
2  *
3  * 
4  * This file is part of Gromacs        Copyright (c) 1991-2008
5  * David van der Spoel, Erik Lindahl, Berk Hess, University of Groningen.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * To help us fund GROMACS development, we humbly ask that you cite
13  * the research papers on the package. Check out http://www.gromacs.org
14  * 
15  * And Hey:
16  * Gnomes, ROck Monsters And Chili Sauce
17  */
18
19 /* The source code in this file should be thread-safe. 
20  Please keep it that way. */
21
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26 #include "gmx_header_config.h"
27
28 #include <string.h>
29 #include <time.h>
30
31 #ifdef HAVE_SYS_TIME_H
32 #include <sys/time.h>
33 #endif
34
35
36 #ifdef GMX_NATIVE_WINDOWS
37 /* _chsize_s */
38 #include <io.h>
39 #include <sys/locking.h>
40 #endif
41
42
43 #include "filenm.h"
44 #include "names.h"
45 #include "typedefs.h"
46 #include "smalloc.h"
47 #include "gmxfio.h"
48 #include "xdrf.h"
49 #include "statutil.h"
50 #include "txtdump.h"
51 #include "vec.h"
52 #include "network.h"
53 #include "gmx_random.h"
54 #include "checkpoint.h"
55 #include "futil.h"
56 #include "string2.h"
57 #include <fcntl.h>
58
59
60 #ifdef GMX_FAHCORE
61 #include "corewrap.h"
62 #endif
63
64
65 /* Portable version of ctime_r implemented in src/gmxlib/string2.c, but we do not want it declared in public installed headers */
66 char *
67 gmx_ctime_r(const time_t *clock,char *buf, int n);
68
69
70 #define CPT_MAGIC1 171817
71 #define CPT_MAGIC2 171819
72
73 #ifdef GMX_DOUBLE
74 #define GMX_CPT_BUILD_DP 1
75 #else
76 #define GMX_CPT_BUILD_DP 0
77 #endif
78
79 /* cpt_version should normally only be changed
80  * when the header of footer format changes.
81  * The state data format itself is backward and forward compatible.
82  * But old code can not read a new entry that is present in the file
83  * (but can read a new format when new entries are not present).
84  */
85 static const int cpt_version = 13;
86
87
88 const char *est_names[estNR]=
89 {
90     "FE-lambda",
91     "box", "box-rel", "box-v", "pres_prev",
92     "nosehoover-xi", "thermostat-integral",
93     "x", "v", "SDx", "CGp", "LD-rng", "LD-rng-i",
94     "disre_initf", "disre_rm3tav",
95     "orire_initf", "orire_Dtav",
96     "svir_prev", "nosehoover-vxi", "v_eta", "vol0", "nhpres_xi", "nhpres_vxi", "fvir_prev",
97 };
98
99 enum { eeksEKIN_N, eeksEKINH, eeksDEKINDL, eeksMVCOS, eeksEKINF, eeksEKINO, eeksEKINSCALEF, eeksEKINSCALEH, eeksVSCALE, eeksEKINTOTAL, eeksNR };
100
101 const char *eeks_names[eeksNR]=
102 {
103     "Ekin_n", "Ekinh", "dEkindlambda", "mv_cos",
104     "Ekinf", "Ekinh_old", "EkinScaleF_NHC", "EkinScaleH_NHC","Vscale_NHC","Ekin_Total"
105 };
106
107 enum { eenhENERGY_N, eenhENERGY_AVER, eenhENERGY_SUM, eenhENERGY_NSUM,
108        eenhENERGY_SUM_SIM, eenhENERGY_NSUM_SIM,
109        eenhENERGY_NSTEPS, eenhENERGY_NSTEPS_SIM, 
110        eenhENERGY_DELTA_H_NN,
111        eenhENERGY_DELTA_H_LIST, 
112        eenhENERGY_DELTA_H_STARTTIME, 
113        eenhENERGY_DELTA_H_STARTLAMBDA, 
114        eenhNR };
115
116 const char *eenh_names[eenhNR]=
117 {
118     "energy_n", "energy_aver", "energy_sum", "energy_nsum",
119     "energy_sum_sim", "energy_nsum_sim",
120     "energy_nsteps", "energy_nsteps_sim", 
121     "energy_delta_h_nn",
122     "energy_delta_h_list", 
123     "energy_delta_h_start_time", 
124     "energy_delta_h_start_lambda"
125 };
126
127
128
129 #ifdef GMX_NATIVE_WINDOWS
130 static int
131 gmx_wintruncate(const char *filename, __int64 size)
132 {
133 #ifdef GMX_FAHCORE
134     /*we do this elsewhere*/
135     return 0;
136 #else
137     FILE *fp;
138     int   rc;
139     
140     fp=fopen(filename,"rb+");
141     
142     if(fp==NULL)
143     {
144         return -1;
145     }
146     
147     return _chsize_s( fileno(fp), size);
148 #endif
149 }
150 #endif
151
152
153 enum { ecprREAL, ecprRVEC, ecprMATRIX };
154
155 static const char *st_names(int cptp,int ecpt)
156 {
157     switch (cptp)
158     {
159     case 0: return est_names [ecpt]; break;
160     case 1: return eeks_names[ecpt]; break;
161     case 2: return eenh_names[ecpt]; break;
162     }
163
164     return NULL;
165 }
166
167 static void cp_warning(FILE *fp)
168 {
169     fprintf(fp,"\nWARNING: Checkpoint file is corrupted or truncated\n\n");
170 }
171
172 static void cp_error()
173 {
174     gmx_fatal(FARGS,"Checkpoint file corrupted/truncated, or maybe you are out of disk space?");
175 }
176
177 static void do_cpt_string_err(XDR *xd,gmx_bool bRead,const char *desc,char **s,FILE *list)
178 {
179 #define CPTSTRLEN 1024
180     bool_t res=0;
181     
182     if (bRead)
183     {
184         snew(*s,CPTSTRLEN);
185     }
186     res = xdr_string(xd,s,CPTSTRLEN);
187     if (res == 0)
188     {
189         cp_error();
190     }
191     if (list)
192     {
193         fprintf(list,"%s = %s\n",desc,*s);
194         sfree(*s);
195     }
196 }
197
198 static int do_cpt_int(XDR *xd,const char *desc,int *i,FILE *list)
199 {
200     bool_t res=0;
201     
202     res = xdr_int(xd,i);
203     if (res == 0)
204     {
205         return -1;
206     }
207     if (list)
208     {
209         fprintf(list,"%s = %d\n",desc,*i);
210     }
211     return 0;
212 }
213
214 static int do_cpt_u_chars(XDR *xd,const char *desc,int n,unsigned char *i,FILE *list)
215 {
216     bool_t res=1;
217     int j;
218     if (list)
219     {
220         fprintf(list,"%s = ",desc);
221     }
222     for (j=0; j<n && res; j++)
223     {
224         res &= xdr_u_char(xd,&i[j]);
225         if (list)
226         {
227             fprintf(list,"%02x",i[j]);
228         }
229     }
230     if (list)
231     {
232         fprintf(list,"\n");
233     }
234     if (res == 0)
235     {
236         return -1;
237     }
238
239     return 0;
240 }
241
242 static void do_cpt_int_err(XDR *xd,const char *desc,int *i,FILE *list)
243 {
244     if (do_cpt_int(xd,desc,i,list) < 0)
245     {
246         cp_error();
247     }
248 }
249
250 static void do_cpt_step_err(XDR *xd,const char *desc,gmx_large_int_t *i,FILE *list)
251 {
252     bool_t res=0;
253     char   buf[STEPSTRSIZE];
254
255     res = xdr_gmx_large_int(xd,i,"reading checkpoint file");
256     if (res == 0)
257     {
258         cp_error();
259     }
260     if (list)
261     {
262         fprintf(list,"%s = %s\n",desc,gmx_step_str(*i,buf));
263     }
264 }
265
266 static void do_cpt_double_err(XDR *xd,const char *desc,double *f,FILE *list)
267 {
268     bool_t res=0;
269     
270     res = xdr_double(xd,f);
271     if (res == 0)
272     {
273         cp_error();
274     }
275     if (list)
276     {
277         fprintf(list,"%s = %f\n",desc,*f);
278     }
279 }
280
281 /* If nval >= 0, nval is used; on read this should match the passed value.
282  * If nval n<0, *nptr is used; on read the value is stored in nptr
283  */
284 static int do_cpte_reals_low(XDR *xd,int cptp,int ecpt,int sflags,
285                              int nval,int *nptr,real **v,
286                              FILE *list,int erealtype)
287 {
288     bool_t res=0;
289 #ifndef GMX_DOUBLE
290     int  dtc=xdr_datatype_float; 
291 #else
292     int  dtc=xdr_datatype_double;
293 #endif
294     real *vp,*va=NULL;
295     float  *vf;
296     double *vd;
297     int  nf,dt,i;
298     
299     if (list == NULL)
300     {
301         if (nval >= 0)
302         {
303             nf = nval;
304         }
305         else
306         {
307         if (nptr == NULL)
308         {
309             gmx_incons("*ntpr=NULL in do_cpte_reals_low");
310         }
311         nf = *nptr;
312         }
313     }
314     res = xdr_int(xd,&nf);
315     if (res == 0)
316     {
317         return -1;
318     }
319     if (list == NULL)
320     {
321         if (nval >= 0)
322         {
323             if (nf != nval)
324             {
325                 gmx_fatal(FARGS,"Count mismatch for state entry %s, code count is %d, file count is %d\n",st_names(cptp,ecpt),nval,nf);
326             }
327         }
328         else
329         {
330             *nptr = nf;
331         }
332     }
333     dt = dtc;
334     res = xdr_int(xd,&dt);
335     if (res == 0)
336     {
337         return -1;
338     }
339     if (dt != dtc)
340     {
341         fprintf(stderr,"Precision mismatch for state entry %s, code precision is %s, file precision is %s\n",
342                 st_names(cptp,ecpt),xdr_datatype_names[dtc],
343                 xdr_datatype_names[dt]);
344     }
345     if (list || !(sflags & (1<<ecpt)))
346     {
347         snew(va,nf);
348         vp = va;
349     }
350     else
351     {
352         if (*v == NULL)
353         {
354             snew(*v,nf);
355         }
356         vp = *v;
357     }
358     if (dt == xdr_datatype_float)
359     {
360         if (dtc == xdr_datatype_float)
361         {
362             vf = (float *)vp;
363         }
364         else
365         {
366             snew(vf,nf);
367         }
368         res = xdr_vector(xd,(char *)vf,nf,
369                          (unsigned int)sizeof(float),(xdrproc_t)xdr_float);
370         if (res == 0)
371         {
372             return -1;
373         }
374         if (dtc != xdr_datatype_float)
375         {
376             for(i=0; i<nf; i++)
377             {
378                 vp[i] = vf[i];
379             }
380             sfree(vf);
381         }
382     }
383     else
384     {
385         if (dtc == xdr_datatype_double)
386         {
387             vd = (double *)vp;
388         }
389         else
390         {
391             snew(vd,nf);
392         }
393         res = xdr_vector(xd,(char *)vd,nf,
394                          (unsigned int)sizeof(double),(xdrproc_t)xdr_double);
395         if (res == 0)
396         {
397             return -1;
398         }
399         if (dtc != xdr_datatype_double)
400         {
401             for(i=0; i<nf; i++)
402             {
403                 vp[i] = vd[i];
404             }
405             sfree(vd);
406         }
407     }
408     
409     if (list)
410     {
411         switch (erealtype)
412         {
413         case ecprREAL:
414             pr_reals(list,0,st_names(cptp,ecpt),vp,nf);
415             break;
416         case ecprRVEC:
417             pr_rvecs(list,0,st_names(cptp,ecpt),(rvec *)vp,nf/3);
418             break;
419         default:
420             gmx_incons("Unknown checkpoint real type");
421         }
422     }
423     if (va)
424     {
425         sfree(va);
426     }
427
428     return 0;
429 }
430
431
432 /* This function stores n along with the reals for reading,
433  * but on reading it assumes that n matches the value in the checkpoint file,
434  * a fatal error is generated when this is not the case.
435  */
436 static int do_cpte_reals(XDR *xd,int cptp,int ecpt,int sflags,
437                          int n,real **v,FILE *list)
438 {
439     return do_cpte_reals_low(xd,cptp,ecpt,sflags,n,NULL,v,list,ecprREAL);
440 }
441
442 /* This function does the same as do_cpte_reals,
443  * except that on reading it ignores the passed value of *n
444  * and stored the value read from the checkpoint file in *n.
445  */
446 static int do_cpte_n_reals(XDR *xd,int cptp,int ecpt,int sflags,
447                            int *n,real **v,FILE *list)
448 {
449     return do_cpte_reals_low(xd,cptp,ecpt,sflags,-1,n,v,list,ecprREAL);
450 }
451
452 static int do_cpte_real(XDR *xd,int cptp,int ecpt,int sflags,
453                         real *r,FILE *list)
454 {
455     int n;
456
457     return do_cpte_reals_low(xd,cptp,ecpt,sflags,1,NULL,&r,list,ecprREAL);
458 }
459
460 static int do_cpte_ints(XDR *xd,int cptp,int ecpt,int sflags,
461                         int n,int **v,FILE *list)
462 {
463     bool_t res=0;
464     int  dtc=xdr_datatype_int;
465     int *vp,*va=NULL;
466     int  nf,dt,i;
467     
468     nf = n;
469     res = xdr_int(xd,&nf);
470     if (res == 0)
471     {
472         return -1;
473     }
474     if (list == NULL && v != NULL && nf != n)
475     {
476         gmx_fatal(FARGS,"Count mismatch for state entry %s, code count is %d, file count is %d\n",st_names(cptp,ecpt),n,nf);
477     }
478     dt = dtc;
479     res = xdr_int(xd,&dt);
480     if (res == 0)
481     {
482         return -1;
483     }
484     if (dt != dtc)
485     {
486         gmx_fatal(FARGS,"Type mismatch for state entry %s, code type is %s, file type is %s\n",
487                   st_names(cptp,ecpt),xdr_datatype_names[dtc],
488                   xdr_datatype_names[dt]);
489     }
490     if (list || !(sflags & (1<<ecpt)) || v == NULL)
491     {
492         snew(va,nf);
493         vp = va;
494     }
495     else
496     {
497         if (*v == NULL)
498         {
499             snew(*v,nf);
500         }
501         vp = *v;
502     }
503     res = xdr_vector(xd,(char *)vp,nf,
504                      (unsigned int)sizeof(int),(xdrproc_t)xdr_int);
505     if (res == 0)
506     {
507         return -1;
508     }
509     if (list)
510     {
511         pr_ivec(list,0,st_names(cptp,ecpt),vp,nf,TRUE);
512     }
513     if (va)
514     {
515         sfree(va);
516     }
517
518     return 0;
519 }
520
521 static int do_cpte_int(XDR *xd,int cptp,int ecpt,int sflags,
522                        int *i,FILE *list)
523 {
524     return do_cpte_ints(xd,cptp,ecpt,sflags,1,&i,list);
525 }
526
527 static int do_cpte_doubles(XDR *xd,int cptp,int ecpt,int sflags,
528                            int n,double **v,FILE *list)
529 {
530     bool_t res=0;
531     int  dtc=xdr_datatype_double;
532     double *vp,*va=NULL;
533     int  nf,dt,i;
534     
535     nf = n;
536     res = xdr_int(xd,&nf);
537     if (res == 0)
538     {
539         return -1;
540     }
541     if (list == NULL && nf != n)
542     {
543         gmx_fatal(FARGS,"Count mismatch for state entry %s, code count is %d, file count is %d\n",st_names(cptp,ecpt),n,nf);
544     }
545     dt = dtc;
546     res = xdr_int(xd,&dt);
547     if (res == 0)
548     {
549         return -1;
550     }
551     if (dt != dtc)
552     {
553         gmx_fatal(FARGS,"Precision mismatch for state entry %s, code precision is %s, file precision is %s\n",
554                   st_names(cptp,ecpt),xdr_datatype_names[dtc],
555                   xdr_datatype_names[dt]);
556     }
557     if (list || !(sflags & (1<<ecpt)))
558     {
559         snew(va,nf);
560         vp = va;
561     }
562     else
563     {
564         if (*v == NULL)
565         {
566             snew(*v,nf);
567         }
568         vp = *v;
569     }
570     res = xdr_vector(xd,(char *)vp,nf,
571                      (unsigned int)sizeof(double),(xdrproc_t)xdr_double);
572     if (res == 0)
573     {
574         return -1;
575     }
576     if (list)
577     {
578         pr_doubles(list,0,st_names(cptp,ecpt),vp,nf);
579     }
580     if (va)
581     {
582         sfree(va);
583     }
584
585     return 0;
586 }
587
588 static int do_cpte_double(XDR *xd,int cptp,int ecpt,int sflags,
589                           double *r,FILE *list)
590 {
591     return do_cpte_doubles(xd,cptp,ecpt,sflags,1,&r,list);
592 }
593
594
595 static int do_cpte_rvecs(XDR *xd,int cptp,int ecpt,int sflags,
596                          int n,rvec **v,FILE *list)
597 {
598     int n3;
599
600     return do_cpte_reals_low(xd,cptp,ecpt,sflags,
601                              n*DIM,NULL,(real **)v,list,ecprRVEC);
602 }
603
604 static int do_cpte_matrix(XDR *xd,int cptp,int ecpt,int sflags,
605                           matrix v,FILE *list)
606 {
607     real *vr;
608     real ret;
609
610     vr = (real *)&(v[0][0]);
611     ret = do_cpte_reals_low(xd,cptp,ecpt,sflags,
612                             DIM*DIM,NULL,&vr,NULL,ecprMATRIX);
613     
614     if (list && ret == 0)
615     {
616         pr_rvecs(list,0,st_names(cptp,ecpt),v,DIM);
617     }
618     
619     return ret;
620 }
621
622 static int do_cpte_matrices(XDR *xd,int cptp,int ecpt,int sflags,
623                             int n,matrix **v,FILE *list)
624 {
625     bool_t res=0;
626     matrix *vp,*va=NULL;
627     real *vr;
628     int  nf,i,j,k;
629     int  ret;
630
631     nf = n;
632     res = xdr_int(xd,&nf);
633     if (res == 0)
634     {
635         return -1;
636     }
637     if (list == NULL && nf != n)
638     {
639         gmx_fatal(FARGS,"Count mismatch for state entry %s, code count is %d, file count is %d\n",st_names(cptp,ecpt),n,nf);
640     }
641     if (list || !(sflags & (1<<ecpt)))
642     {
643         snew(va,nf);
644         vp = va;
645     }
646     else
647     {
648         if (*v == NULL)
649         {
650             snew(*v,nf);
651         }
652         vp = *v;
653     }
654     snew(vr,nf*DIM*DIM);
655     for(i=0; i<nf; i++)
656     {
657         for(j=0; j<DIM; j++)
658         {
659             for(k=0; k<DIM; k++)
660             {
661                 vr[(i*DIM+j)*DIM+k] = vp[i][j][k];
662             }
663         }
664     }
665     ret = do_cpte_reals_low(xd,cptp,ecpt,sflags,
666                             nf*DIM*DIM,NULL,&vr,NULL,ecprMATRIX);
667     for(i=0; i<nf; i++)
668     {
669         for(j=0; j<DIM; j++)
670         {
671             for(k=0; k<DIM; k++)
672             {
673                 vp[i][j][k] = vr[(i*DIM+j)*DIM+k];
674             }
675         }
676     }
677     sfree(vr);
678     
679     if (list && ret == 0)
680     {
681         for(i=0; i<nf; i++)
682         {
683             pr_rvecs(list,0,st_names(cptp,ecpt),vp[i],DIM);
684         }
685     }
686     if (va)
687     {
688         sfree(va);
689     }
690     
691     return ret;
692 }
693
694 static void do_cpt_header(XDR *xd,gmx_bool bRead,int *file_version,
695                           char **version,char **btime,char **buser,char **bmach,
696                           int *double_prec,
697                           char **fprog,char **ftime,
698                           int *eIntegrator,int *simulation_part,
699                           gmx_large_int_t *step,double *t,
700                           int *nnodes,int *dd_nc,int *npme,
701                           int *natoms,int *ngtc, int *nnhpres, int *nhchainlength,
702                           int *flags_state,int *flags_eks,int *flags_enh,
703                           FILE *list)
704 {
705     bool_t res=0;
706     int  magic;
707     int  idum=0;
708     int  i;
709     char *fhost;
710
711     if (bRead)
712     {
713         magic = -1;
714     }
715     else
716     {
717         magic = CPT_MAGIC1;
718     }
719     res = xdr_int(xd,&magic);
720     if (res == 0)
721     {
722         gmx_fatal(FARGS,"The checkpoint file is empty/corrupted, or maybe you are out of disk space?");
723     }
724     if (magic != CPT_MAGIC1)
725     {
726         gmx_fatal(FARGS,"Start of file magic number mismatch, checkpoint file has %d, should be %d\n"
727                   "The checkpoint file is corrupted or not a checkpoint file",
728                   magic,CPT_MAGIC1);
729     }
730     if (!bRead)
731     {
732         snew(fhost,255);
733 #ifdef HAVE_UNISTD_H
734         if (gethostname(fhost,255) != 0)
735         {
736             sprintf(fhost,"unknown");
737         }
738 #else
739         sprintf(fhost,"unknown");
740 #endif  
741     }
742     do_cpt_string_err(xd,bRead,"GROMACS version"           ,version,list);
743     do_cpt_string_err(xd,bRead,"GROMACS build time"        ,btime,list);
744     do_cpt_string_err(xd,bRead,"GROMACS build user"        ,buser,list);
745     do_cpt_string_err(xd,bRead,"GROMACS build machine"     ,bmach,list);
746     do_cpt_string_err(xd,bRead,"generating program"        ,fprog,list);
747     do_cpt_string_err(xd,bRead,"generation time"           ,ftime,list);
748     *file_version = cpt_version;
749     do_cpt_int_err(xd,"checkpoint file version",file_version,list);
750     if (*file_version > cpt_version)
751     {
752         gmx_fatal(FARGS,"Attempting to read a checkpoint file of version %d with code of version %d\n",*file_version,cpt_version);
753     }
754     if (*file_version >= 13)
755     {
756         do_cpt_int_err(xd,"GROMACS double precision",double_prec,list);
757     }
758     else
759     {
760         *double_prec = -1;
761     }
762     if (*file_version >= 12)
763     {
764         do_cpt_string_err(xd,bRead,"generating host"           ,&fhost,list);
765         if (list == NULL)
766         {
767             sfree(fhost);
768         }
769     }
770     do_cpt_int_err(xd,"#atoms"            ,natoms     ,list);
771     do_cpt_int_err(xd,"#T-coupling groups",ngtc       ,list);
772     if (*file_version >= 10) 
773     {
774         do_cpt_int_err(xd,"#Nose-Hoover T-chains",nhchainlength,list);
775     }
776     else
777     {
778         *nhchainlength = 1;
779     }
780     if (*file_version >= 11)
781     {
782         do_cpt_int_err(xd,"#Nose-Hoover T-chains for barostat ",nnhpres,list);
783     }
784     else
785     {
786         *nnhpres = 0;
787     }
788     do_cpt_int_err(xd,"integrator"        ,eIntegrator,list);
789         if (*file_version >= 3)
790         {
791                 do_cpt_int_err(xd,"simulation part #", simulation_part,list);
792         }
793         else
794         {
795                 *simulation_part = 1;
796         }
797     if (*file_version >= 5)
798     {
799         do_cpt_step_err(xd,"step"         ,step       ,list);
800     }
801     else
802     {
803         do_cpt_int_err(xd,"step"          ,&idum      ,list);
804         *step = idum;
805     }
806     do_cpt_double_err(xd,"t"              ,t          ,list);
807     do_cpt_int_err(xd,"#PP-nodes"         ,nnodes     ,list);
808     idum = 1;
809     do_cpt_int_err(xd,"dd_nc[x]",dd_nc ? &(dd_nc[0]) : &idum,list);
810     do_cpt_int_err(xd,"dd_nc[y]",dd_nc ? &(dd_nc[1]) : &idum,list);
811     do_cpt_int_err(xd,"dd_nc[z]",dd_nc ? &(dd_nc[2]) : &idum,list);
812     do_cpt_int_err(xd,"#PME-only nodes",npme,list);
813     do_cpt_int_err(xd,"state flags",flags_state,list);
814         if (*file_version >= 4)
815     {
816         do_cpt_int_err(xd,"ekin data flags",flags_eks,list);
817         do_cpt_int_err(xd,"energy history flags",flags_enh,list);
818     }
819     else
820     {
821         *flags_eks  = 0;
822         *flags_enh   = (*flags_state >> (estORIRE_DTAV+1));
823         *flags_state = (*flags_state & ~((1<<(estORIRE_DTAV+1)) |
824                                          (1<<(estORIRE_DTAV+2)) |
825                                          (1<<(estORIRE_DTAV+3))));
826     }
827 }
828
829 static int do_cpt_footer(XDR *xd,gmx_bool bRead,int file_version)
830 {
831     bool_t res=0;
832     int  magic;
833     
834     if (file_version >= 2)
835     {
836         magic = CPT_MAGIC2;
837         res = xdr_int(xd,&magic);
838         if (res == 0)
839         {
840             cp_error();
841         }
842         if (magic != CPT_MAGIC2)
843         {
844             return -1;
845         }
846     }
847
848     return 0;
849 }
850
851 static int do_cpt_state(XDR *xd,gmx_bool bRead,
852                         int fflags,t_state *state,
853                         gmx_bool bReadRNG,FILE *list)
854 {
855     int  sflags;
856     int  **rng_p,**rngi_p;
857     int  i;
858     int  ret;
859     int  nnht,nnhtp;
860
861     ret = 0;
862     
863     nnht = state->nhchainlength*state->ngtc;
864     nnhtp = state->nhchainlength*state->nnhpres;
865
866     if (bReadRNG)
867     {
868         rng_p  = (int **)&state->ld_rng;
869         rngi_p = &state->ld_rngi;
870     }
871     else
872     {
873         /* Do not read the RNG data */
874         rng_p  = NULL;
875         rngi_p = NULL;
876     }
877
878     sflags = state->flags;
879     for(i=0; (i<estNR && ret == 0); i++)
880     {
881         if (fflags & (1<<i))
882         {
883             switch (i)
884             {
885             case estLAMBDA:  ret = do_cpte_real(xd,0,i,sflags,&state->lambda,list); break;
886             case estBOX:     ret = do_cpte_matrix(xd,0,i,sflags,state->box,list); break;
887             case estBOX_REL: ret = do_cpte_matrix(xd,0,i,sflags,state->box_rel,list); break;
888             case estBOXV:    ret = do_cpte_matrix(xd,0,i,sflags,state->boxv,list); break;
889             case estPRES_PREV: ret = do_cpte_matrix(xd,0,i,sflags,state->pres_prev,list); break;
890             case estSVIR_PREV:  ret = do_cpte_matrix(xd,0,i,sflags,state->svir_prev,list); break;
891             case estFVIR_PREV:  ret = do_cpte_matrix(xd,0,i,sflags,state->fvir_prev,list); break;
892             case estNH_XI:   ret = do_cpte_doubles(xd,0,i,sflags,nnht,&state->nosehoover_xi,list); break;
893             case estNH_VXI:  ret = do_cpte_doubles(xd,0,i,sflags,nnht,&state->nosehoover_vxi,list); break;
894             case estNHPRES_XI:   ret = do_cpte_doubles(xd,0,i,sflags,nnhtp,&state->nhpres_xi,list); break;
895             case estNHPRES_VXI:  ret = do_cpte_doubles(xd,0,i,sflags,nnhtp,&state->nhpres_vxi,list); break;
896             case estTC_INT:  ret = do_cpte_doubles(xd,0,i,sflags,state->ngtc,&state->therm_integral,list); break;
897             case estVETA:    ret = do_cpte_real(xd,0,i,sflags,&state->veta,list); break;
898             case estVOL0:    ret = do_cpte_real(xd,0,i,sflags,&state->vol0,list); break;
899             case estX:       ret = do_cpte_rvecs(xd,0,i,sflags,state->natoms,&state->x,list); break;
900             case estV:       ret = do_cpte_rvecs(xd,0,i,sflags,state->natoms,&state->v,list); break;
901             case estSDX:     ret = do_cpte_rvecs(xd,0,i,sflags,state->natoms,&state->sd_X,list); break;
902             case estLD_RNG:  ret = do_cpte_ints(xd,0,i,sflags,state->nrng,rng_p,list); break;
903             case estLD_RNGI: ret = do_cpte_ints(xd,0,i,sflags,state->nrngi,rngi_p,list); break;
904             case estDISRE_INITF:  ret = do_cpte_real (xd,0,i,sflags,&state->hist.disre_initf,list); break;
905             case estDISRE_RM3TAV: ret = do_cpte_n_reals(xd,0,i,sflags,&state->hist.ndisrepairs,&state->hist.disre_rm3tav,list); break;
906             case estORIRE_INITF:  ret = do_cpte_real (xd,0,i,sflags,&state->hist.orire_initf,list); break;
907             case estORIRE_DTAV:   ret = do_cpte_n_reals(xd,0,i,sflags,&state->hist.norire_Dtav,&state->hist.orire_Dtav,list); break;
908             default:
909                 gmx_fatal(FARGS,"Unknown state entry %d\n"
910                           "You are probably reading a new checkpoint file with old code",i);
911             }
912         }
913     }
914     
915     return ret;
916 }
917
918 static int do_cpt_ekinstate(XDR *xd,gmx_bool bRead,
919                             int fflags,ekinstate_t *ekins,
920                             FILE *list)
921 {
922     int  i;
923     int  ret;
924
925     ret = 0;
926
927     for(i=0; (i<eeksNR && ret == 0); i++)
928     {
929         if (fflags & (1<<i))
930         {
931             switch (i)
932             {
933                 
934                         case eeksEKIN_N:     ret = do_cpte_int(xd,1,i,fflags,&ekins->ekin_n,list); break;
935                         case eeksEKINH :     ret = do_cpte_matrices(xd,1,i,fflags,ekins->ekin_n,&ekins->ekinh,list); break;
936                         case eeksEKINF:      ret = do_cpte_matrices(xd,1,i,fflags,ekins->ekin_n,&ekins->ekinf,list); break;
937                         case eeksEKINO:      ret = do_cpte_matrices(xd,1,i,fflags,ekins->ekin_n,&ekins->ekinh_old,list); break;
938             case eeksEKINTOTAL:  ret = do_cpte_matrix(xd,1,i,fflags,ekins->ekin_total,list); break;
939             case eeksEKINSCALEF: ret = do_cpte_doubles(xd,1,i,fflags,ekins->ekin_n,&ekins->ekinscalef_nhc,list); break;
940             case eeksVSCALE:     ret = do_cpte_doubles(xd,1,i,fflags,ekins->ekin_n,&ekins->vscale_nhc,list); break;
941             case eeksEKINSCALEH: ret = do_cpte_doubles(xd,1,i,fflags,ekins->ekin_n,&ekins->ekinscaleh_nhc,list); break;
942                         case eeksDEKINDL :   ret = do_cpte_real(xd,1,i,fflags,&ekins->dekindl,list); break;
943             case eeksMVCOS:      ret = do_cpte_real(xd,1,i,fflags,&ekins->mvcos,list); break;                   
944             default:
945                 gmx_fatal(FARGS,"Unknown ekin data state entry %d\n"
946                           "You are probably reading a new checkpoint file with old code",i);
947             }
948         }
949     }
950     
951     return ret;
952 }
953
954
955 static int do_cpt_enerhist(XDR *xd,gmx_bool bRead,
956                            int fflags,energyhistory_t *enerhist,
957                            FILE *list)
958 {
959     int  i;
960     int  j;
961     int  ret;
962
963     ret = 0;
964
965     if (bRead)
966     {
967         enerhist->nsteps     = 0;
968         enerhist->nsum       = 0;
969         enerhist->nsteps_sim = 0;
970         enerhist->nsum_sim   = 0;
971         enerhist->dht        = NULL;
972
973         if (fflags & (1<< eenhENERGY_DELTA_H_NN) )
974         {
975             snew(enerhist->dht,1);
976             enerhist->dht->ndh = NULL;
977             enerhist->dht->dh = NULL;
978             enerhist->dht->start_lambda_set=FALSE;
979         }
980     }
981
982     for(i=0; (i<eenhNR && ret == 0); i++)
983     {
984         if (fflags & (1<<i))
985         {
986             switch (i)
987             {
988                 case eenhENERGY_N:     ret = do_cpte_int(xd,2,i,fflags,&enerhist->nener,list); break;
989                 case eenhENERGY_AVER:  ret = do_cpte_doubles(xd,2,i,fflags,enerhist->nener,&enerhist->ener_ave,list); break;
990                 case eenhENERGY_SUM:   ret = do_cpte_doubles(xd,2,i,fflags,enerhist->nener,&enerhist->ener_sum,list); break;
991                 case eenhENERGY_NSUM:  do_cpt_step_err(xd,eenh_names[i],&enerhist->nsum,list); break;
992                 case eenhENERGY_SUM_SIM: ret = do_cpte_doubles(xd,2,i,fflags,enerhist->nener,&enerhist->ener_sum_sim,list); break;
993                 case eenhENERGY_NSUM_SIM:   do_cpt_step_err(xd,eenh_names[i],&enerhist->nsum_sim,list); break;
994                 case eenhENERGY_NSTEPS:     do_cpt_step_err(xd,eenh_names[i],&enerhist->nsteps,list); break;
995                 case eenhENERGY_NSTEPS_SIM: do_cpt_step_err(xd,eenh_names[i],&enerhist->nsteps_sim,list); break;
996                 case eenhENERGY_DELTA_H_NN: do_cpt_int_err(xd,eenh_names[i], &(enerhist->dht->nndh), list); 
997                     if (bRead) /* now allocate memory for it */
998                     {
999                         snew(enerhist->dht->dh, enerhist->dht->nndh);
1000                         snew(enerhist->dht->ndh, enerhist->dht->nndh);
1001                         for(j=0;j<enerhist->dht->nndh;j++)
1002                         {
1003                             enerhist->dht->ndh[j] = 0;
1004                             enerhist->dht->dh[j] = NULL;
1005                         }
1006                     }
1007                 break;
1008                 case eenhENERGY_DELTA_H_LIST: 
1009                     for(j=0;j<enerhist->dht->nndh;j++)
1010                     {
1011                         ret=do_cpte_n_reals(xd, 2, i, fflags, &enerhist->dht->ndh[j], &(enerhist->dht->dh[j]), list); 
1012                     }
1013                     break;
1014                 case eenhENERGY_DELTA_H_STARTTIME: 
1015                     ret=do_cpte_double(xd, 2, i, fflags, &(enerhist->dht->start_time), list); break;
1016                 case eenhENERGY_DELTA_H_STARTLAMBDA: 
1017                     enerhist->dht->start_lambda_set=TRUE;
1018                     ret=do_cpte_double(xd, 2, i, fflags, &(enerhist->dht->start_lambda), list); break;
1019                 default:
1020                     gmx_fatal(FARGS,"Unknown energy history entry %d\n"
1021                               "You are probably reading a new checkpoint file with old code",i);
1022             }
1023         }
1024     }
1025
1026     if ((fflags & (1<<eenhENERGY_SUM)) && !(fflags & (1<<eenhENERGY_SUM_SIM)))
1027     {
1028         /* Assume we have an old file format and copy sum to sum_sim */
1029         srenew(enerhist->ener_sum_sim,enerhist->nener);
1030         for(i=0; i<enerhist->nener; i++)
1031         {
1032             enerhist->ener_sum_sim[i] = enerhist->ener_sum[i];
1033         }
1034         fflags |= (1<<eenhENERGY_SUM_SIM);
1035     }
1036     
1037     if ( (fflags & (1<<eenhENERGY_NSUM)) &&
1038         !(fflags & (1<<eenhENERGY_NSTEPS)))
1039     {
1040         /* Assume we have an old file format and copy nsum to nsteps */
1041         enerhist->nsteps = enerhist->nsum;
1042         fflags |= (1<<eenhENERGY_NSTEPS);
1043     }
1044     if ( (fflags & (1<<eenhENERGY_NSUM_SIM)) &&
1045         !(fflags & (1<<eenhENERGY_NSTEPS_SIM)))
1046     {
1047         /* Assume we have an old file format and copy nsum to nsteps */
1048         enerhist->nsteps_sim = enerhist->nsum_sim;
1049         fflags |= (1<<eenhENERGY_NSTEPS_SIM);
1050     }
1051
1052     return ret;
1053 }
1054
1055 static int do_cpt_files(XDR *xd, gmx_bool bRead, 
1056                         gmx_file_position_t **p_outputfiles, int *nfiles, 
1057                         FILE *list, int file_version)
1058 {
1059     int    i,j;
1060     gmx_off_t  offset;
1061     gmx_off_t  mask = 0xFFFFFFFFL;
1062     int    offset_high,offset_low;
1063     char   *buf;
1064     gmx_file_position_t *outputfiles;
1065
1066     if (do_cpt_int(xd,"number of output files",nfiles,list) != 0)
1067     {
1068         return -1;
1069     }
1070
1071     if(bRead)
1072     {
1073         snew(*p_outputfiles,*nfiles);
1074     }
1075
1076     outputfiles = *p_outputfiles;
1077
1078     for(i=0;i<*nfiles;i++)
1079     {
1080         /* 64-bit XDR numbers are not portable, so it is stored as separate high/low fractions */
1081         if(bRead)
1082         {
1083             do_cpt_string_err(xd,bRead,"output filename",&buf,list);
1084             strncpy(outputfiles[i].filename,buf,CPTSTRLEN-1);
1085             if(list==NULL)
1086             {
1087                 sfree(buf);                     
1088             }
1089
1090             if (do_cpt_int(xd,"file_offset_high",&offset_high,list) != 0)
1091             {
1092                 return -1;
1093             }
1094             if (do_cpt_int(xd,"file_offset_low",&offset_low,list) != 0)
1095             {
1096                 return -1;
1097             }
1098 #if (SIZEOF_GMX_OFF_T > 4)
1099             outputfiles[i].offset = ( ((gmx_off_t) offset_high) << 32 ) | ( (gmx_off_t) offset_low & mask );
1100 #else
1101             outputfiles[i].offset = offset_low;
1102 #endif
1103         }
1104         else
1105         {
1106             buf = outputfiles[i].filename;
1107             do_cpt_string_err(xd,bRead,"output filename",&buf,list);
1108             /* writing */
1109             offset      = outputfiles[i].offset;
1110             if (offset == -1)
1111             {
1112                 offset_low  = -1;
1113                 offset_high = -1;
1114             }
1115             else
1116             {
1117 #if (SIZEOF_GMX_OFF_T > 4)
1118                 offset_low  = (int) (offset & mask);
1119                 offset_high = (int) ((offset >> 32) & mask);
1120 #else
1121                 offset_low  = offset;
1122                 offset_high = 0;
1123 #endif
1124             }
1125             if (do_cpt_int(xd,"file_offset_high",&offset_high,list) != 0)
1126             {
1127                 return -1;
1128             }
1129             if (do_cpt_int(xd,"file_offset_low",&offset_low,list) != 0)
1130             {
1131                 return -1;
1132             }
1133         }
1134         if (file_version >= 8)
1135         {
1136             if (do_cpt_int(xd,"file_checksum_size",&(outputfiles[i].chksum_size),
1137                            list) != 0)
1138             {
1139                 return -1;
1140             }
1141             if (do_cpt_u_chars(xd,"file_checksum",16,outputfiles[i].chksum,list) != 0)
1142             {
1143                 return -1;
1144             }
1145         } 
1146         else 
1147         {
1148             outputfiles[i].chksum_size = -1;
1149         }
1150     }
1151     return 0;
1152 }
1153
1154
1155 void write_checkpoint(const char *fn,gmx_bool bNumberAndKeep,
1156                       FILE *fplog,t_commrec *cr,
1157                       int eIntegrator,int simulation_part,
1158                       gmx_large_int_t step,double t,t_state *state)
1159 {
1160     t_fileio *fp;
1161     int  file_version;
1162     char *version;
1163     char *btime;
1164     char *buser;
1165     char *bmach;
1166     int  double_prec;
1167     char *fprog;
1168     char *fntemp; /* the temporary checkpoint file name */
1169     time_t now;
1170     char timebuf[STRLEN];
1171     int  nppnodes,npmenodes,flag_64bit;
1172     char buf[1024],suffix[5+STEPSTRSIZE],sbuf[STEPSTRSIZE];
1173     gmx_file_position_t *outputfiles;
1174     int  noutputfiles;
1175     char *ftime;
1176     int  flags_eks,flags_enh,i;
1177     t_fileio *ret;
1178                 
1179     if (PAR(cr))
1180     {
1181         if (DOMAINDECOMP(cr))
1182         {
1183             nppnodes  = cr->dd->nnodes;
1184             npmenodes = cr->npmenodes;
1185         }
1186         else
1187         {
1188             nppnodes  = cr->nnodes;
1189             npmenodes = 0;
1190         }
1191     }
1192     else
1193     {
1194         nppnodes  = 1;
1195         npmenodes = 0;
1196     }
1197
1198     /* make the new temporary filename */
1199     snew(fntemp, strlen(fn)+5+STEPSTRSIZE);
1200     strcpy(fntemp,fn);
1201     fntemp[strlen(fn) - strlen(ftp2ext(fn2ftp(fn))) - 1] = '\0';
1202     sprintf(suffix,"_%s%s","step",gmx_step_str(step,sbuf));
1203     strcat(fntemp,suffix);
1204     strcat(fntemp,fn+strlen(fn) - strlen(ftp2ext(fn2ftp(fn))) - 1);
1205    
1206     time(&now);
1207     gmx_ctime_r(&now,timebuf,STRLEN);
1208
1209     if (fplog)
1210     { 
1211         fprintf(fplog,"Writing checkpoint, step %s at %s\n\n",
1212                 gmx_step_str(step,buf),timebuf);
1213     }
1214     
1215     /* Get offsets for open files */
1216     gmx_fio_get_output_file_positions(&outputfiles, &noutputfiles);
1217
1218     fp = gmx_fio_open(fntemp,"w");
1219         
1220     if (state->ekinstate.bUpToDate)
1221     {
1222         flags_eks =
1223             ((1<<eeksEKIN_N) | (1<<eeksEKINH) | (1<<eeksEKINF) | 
1224              (1<<eeksEKINO) | (1<<eeksEKINSCALEF) | (1<<eeksEKINSCALEH) | 
1225              (1<<eeksVSCALE) | (1<<eeksDEKINDL) | (1<<eeksMVCOS));
1226     }
1227     else
1228     {
1229         flags_eks = 0;
1230     }
1231
1232     flags_enh = 0;
1233     if (state->enerhist.nsum > 0 || state->enerhist.nsum_sim > 0)
1234     {
1235         flags_enh |= (1<<eenhENERGY_N);
1236         if (state->enerhist.nsum > 0)
1237         {
1238             flags_enh |= ((1<<eenhENERGY_AVER) | (1<<eenhENERGY_SUM) |
1239                           (1<<eenhENERGY_NSTEPS) | (1<<eenhENERGY_NSUM));
1240         }
1241         if (state->enerhist.nsum_sim > 0)
1242         {
1243             flags_enh |= ((1<<eenhENERGY_SUM_SIM) | (1<<eenhENERGY_NSTEPS_SIM) |
1244                           (1<<eenhENERGY_NSUM_SIM));
1245         }
1246         if (state->enerhist.dht)
1247         {
1248             flags_enh |= ( (1<< eenhENERGY_DELTA_H_NN) |
1249                            (1<< eenhENERGY_DELTA_H_LIST) | 
1250                            (1<< eenhENERGY_DELTA_H_STARTTIME) |
1251                            (1<< eenhENERGY_DELTA_H_STARTLAMBDA) );
1252         }
1253     }
1254
1255     
1256     version = gmx_strdup(VERSION);
1257     btime   = gmx_strdup(BUILD_TIME);
1258     buser   = gmx_strdup(BUILD_USER);
1259     bmach   = gmx_strdup(BUILD_MACHINE);
1260     double_prec = GMX_CPT_BUILD_DP;
1261     fprog   = gmx_strdup(Program());
1262
1263     ftime   = &(timebuf[0]);
1264     
1265     do_cpt_header(gmx_fio_getxdr(fp),FALSE,&file_version,
1266                   &version,&btime,&buser,&bmach,&double_prec,&fprog,&ftime,
1267                   &eIntegrator,&simulation_part,&step,&t,&nppnodes,
1268                   DOMAINDECOMP(cr) ? cr->dd->nc : NULL,&npmenodes,
1269                   &state->natoms,&state->ngtc,&state->nnhpres,
1270                   &state->nhchainlength, &state->flags,&flags_eks,&flags_enh,
1271                   NULL);
1272     
1273     sfree(version);
1274     sfree(btime);
1275     sfree(buser);
1276     sfree(bmach);
1277     sfree(fprog);
1278
1279     if((do_cpt_state(gmx_fio_getxdr(fp),FALSE,state->flags,state,TRUE,NULL) < 0)        ||
1280        (do_cpt_ekinstate(gmx_fio_getxdr(fp),FALSE,flags_eks,&state->ekinstate,NULL) < 0)||
1281        (do_cpt_enerhist(gmx_fio_getxdr(fp),FALSE,flags_enh,&state->enerhist,NULL) < 0)  ||
1282        (do_cpt_files(gmx_fio_getxdr(fp),FALSE,&outputfiles,&noutputfiles,NULL,
1283                      file_version) < 0))
1284     {
1285         gmx_file("Cannot read/write checkpoint; corrupt file, or maybe you are out of disk space?");
1286     }
1287
1288     do_cpt_footer(gmx_fio_getxdr(fp),FALSE,file_version);
1289
1290     /* we really, REALLY, want to make sure to physically write the checkpoint, 
1291        and all the files it depends on, out to disk. Because we've
1292        opened the checkpoint with gmx_fio_open(), it's in our list
1293        of open files.  */
1294     ret=gmx_fio_all_output_fsync();
1295
1296     if (ret)
1297     {
1298         char buf[STRLEN];
1299         sprintf(buf,
1300                 "Cannot fsync '%s'; maybe you are out of disk space?",
1301                 gmx_fio_getname(ret));
1302
1303         if (getenv(GMX_IGNORE_FSYNC_FAILURE_ENV)==NULL)
1304         {
1305             gmx_file(buf);
1306         }
1307         else
1308         {
1309             gmx_warning(buf);
1310         }
1311     }
1312
1313     if( gmx_fio_close(fp) != 0)
1314     {
1315         gmx_file("Cannot read/write checkpoint; corrupt file, or maybe you are out of disk space?");
1316     }
1317
1318     /* we don't move the checkpoint if the user specified they didn't want it,
1319        or if the fsyncs failed */
1320     if (!bNumberAndKeep && !ret)
1321     {
1322         if (gmx_fexist(fn))
1323         {
1324             /* Rename the previous checkpoint file */
1325             strcpy(buf,fn);
1326             buf[strlen(fn) - strlen(ftp2ext(fn2ftp(fn))) - 1] = '\0';
1327             strcat(buf,"_prev");
1328             strcat(buf,fn+strlen(fn) - strlen(ftp2ext(fn2ftp(fn))) - 1);
1329 #ifndef GMX_FAHCORE
1330             /* we copy here so that if something goes wrong between now and
1331              * the rename below, there's always a state.cpt.
1332              * If renames are atomic (such as in POSIX systems),
1333              * this copying should be unneccesary.
1334              */
1335             gmx_file_copy(fn, buf, FALSE);
1336             /* We don't really care if this fails: 
1337              * there's already a new checkpoint.
1338              */
1339 #else
1340             gmx_file_rename(fn, buf);
1341 #endif
1342         }
1343         if (gmx_file_rename(fntemp, fn) != 0)
1344         {
1345             gmx_file("Cannot rename checkpoint file; maybe you are out of disk space?");
1346         }
1347     }
1348
1349     sfree(outputfiles);
1350     sfree(fntemp);
1351
1352 #ifdef GMX_FAHCORE
1353     /*code for alternate checkpointing scheme.  moved from top of loop over 
1354       steps */
1355     fcRequestCheckPoint();
1356     if ( fcCheckPointParallel( cr->nodeid, NULL,0) == 0 ) {
1357         gmx_fatal( 3,__FILE__,__LINE__, "Checkpoint error on step %d\n", step );
1358     }
1359 #endif /* end GMX_FAHCORE block */
1360 }
1361
1362 static void print_flag_mismatch(FILE *fplog,int sflags,int fflags)
1363 {
1364     int i;
1365     
1366     fprintf(fplog,"\nState entry mismatch between the simulation and the checkpoint file\n");
1367     fprintf(fplog,"Entries which are not present in the checkpoint file will not be updated\n");
1368     fprintf(fplog,"  %24s    %11s    %11s\n","","simulation","checkpoint");
1369     for(i=0; i<estNR; i++)
1370     {
1371         if ((sflags & (1<<i)) || (fflags & (1<<i)))
1372         {
1373             fprintf(fplog,"  %24s    %11s    %11s\n",
1374                     est_names[i],
1375                     (sflags & (1<<i)) ? "  present  " : "not present",
1376                     (fflags & (1<<i)) ? "  present  " : "not present");
1377         }
1378     }
1379 }
1380
1381 static void check_int(FILE *fplog,const char *type,int p,int f,gmx_bool *mm)
1382 {
1383         FILE *fp = fplog ? fplog : stderr;
1384
1385     if (p != f)
1386     {
1387                 fprintf(fp,"  %s mismatch,\n",type);
1388                 fprintf(fp,"    current program: %d\n",p);
1389                 fprintf(fp,"    checkpoint file: %d\n",f);
1390                 fprintf(fp,"\n");
1391         *mm = TRUE;
1392     }
1393 }
1394
1395 static void check_string(FILE *fplog,const char *type,const char *p,
1396                          const char *f,gmx_bool *mm)
1397 {
1398         FILE *fp = fplog ? fplog : stderr;
1399         
1400     if (strcmp(p,f) != 0)
1401     {
1402                 fprintf(fp,"  %s mismatch,\n",type);
1403                 fprintf(fp,"    current program: %s\n",p);
1404                 fprintf(fp,"    checkpoint file: %s\n",f);
1405                 fprintf(fp,"\n");
1406         *mm = TRUE;
1407     }
1408 }
1409
1410 static void check_match(FILE *fplog,
1411                         char *version,
1412                         char *btime,char *buser,char *bmach,int double_prec,
1413                         char *fprog,
1414                         t_commrec *cr,gmx_bool bPartDecomp,int npp_f,int npme_f,
1415                         ivec dd_nc,ivec dd_nc_f)
1416 {
1417     int  npp;
1418     gmx_bool mm;
1419     
1420     mm = FALSE;
1421     
1422     check_string(fplog,"Version"      ,VERSION      ,version,&mm);
1423     check_string(fplog,"Build time"   ,BUILD_TIME   ,btime  ,&mm);
1424     check_string(fplog,"Build user"   ,BUILD_USER   ,buser  ,&mm);
1425     check_string(fplog,"Build machine",BUILD_MACHINE,bmach  ,&mm);
1426     check_int   (fplog,"Double prec." ,GMX_CPT_BUILD_DP,double_prec,&mm);
1427     check_string(fplog,"Program name" ,Program()    ,fprog  ,&mm);
1428     
1429     check_int   (fplog,"#nodes"       ,cr->nnodes   ,npp_f+npme_f ,&mm);
1430     if (bPartDecomp)
1431     {
1432         dd_nc[XX] = 1;
1433         dd_nc[YY] = 1;
1434         dd_nc[ZZ] = 1;
1435     }
1436     if (cr->nnodes > 1)
1437     {
1438         check_int (fplog,"#PME-nodes"  ,cr->npmenodes,npme_f     ,&mm);
1439
1440         npp = cr->nnodes;
1441         if (cr->npmenodes >= 0)
1442         {
1443             npp -= cr->npmenodes;
1444         }
1445         if (npp == npp_f)
1446         {
1447             check_int (fplog,"#DD-cells[x]",dd_nc[XX]    ,dd_nc_f[XX],&mm);
1448             check_int (fplog,"#DD-cells[y]",dd_nc[YY]    ,dd_nc_f[YY],&mm);
1449             check_int (fplog,"#DD-cells[z]",dd_nc[ZZ]    ,dd_nc_f[ZZ],&mm);
1450         }
1451     }
1452     
1453     if (mm)
1454     {
1455                 fprintf(stderr,
1456                                 "Gromacs binary or parallel settings not identical to previous run.\n"
1457                                 "Continuation is exact, but is not guaranteed to be binary identical%s.\n\n",
1458                                 fplog ? ",\n see the log file for details" : "");
1459                 
1460         if (fplog)
1461         {
1462                         fprintf(fplog,
1463                                         "Gromacs binary or parallel settings not identical to previous run.\n"
1464                                         "Continuation is exact, but is not guaranteed to be binary identical.\n\n");
1465                 }
1466     }
1467 }
1468
1469 static void read_checkpoint(const char *fn,FILE **pfplog,
1470                             t_commrec *cr,gmx_bool bPartDecomp,ivec dd_nc,
1471                             int eIntegrator,gmx_large_int_t *step,double *t,
1472                             t_state *state,gmx_bool *bReadRNG,gmx_bool *bReadEkin,
1473                             int *simulation_part,gmx_bool bAppendOutputFiles)
1474 {
1475     t_fileio *fp;
1476     int  i,j,rc;
1477     int  file_version;
1478     char *version,*btime,*buser,*bmach,*fprog,*ftime;
1479     int  double_prec;
1480         char filename[STRLEN],buf[STEPSTRSIZE];
1481     int  nppnodes,eIntegrator_f,nppnodes_f,npmenodes_f;
1482     ivec dd_nc_f;
1483     int  natoms,ngtc,nnhpres,nhchainlength,fflags,flags_eks,flags_enh;
1484     int  d;
1485     int  ret;
1486     gmx_file_position_t *outputfiles;
1487     int  nfiles;
1488     t_fileio *chksum_file;
1489     FILE* fplog = *pfplog;
1490     unsigned char digest[16];
1491 #ifndef GMX_NATIVE_WINDOWS
1492     struct flock fl;  /* don't initialize here: the struct order is OS 
1493                          dependent! */
1494 #endif
1495
1496     const char *int_warn=
1497               "WARNING: The checkpoint file was generated with integrator %s,\n"
1498               "         while the simulation uses integrator %s\n\n";
1499     const char *sd_note=
1500         "NOTE: The checkpoint file was for %d nodes doing SD or BD,\n"
1501         "      while the simulation uses %d SD or BD nodes,\n"
1502         "      continuation will be exact, except for the random state\n\n";
1503     
1504 #ifndef GMX_NATIVE_WINDOWS
1505     fl.l_type=F_WRLCK;
1506     fl.l_whence=SEEK_SET;
1507     fl.l_start=0;
1508     fl.l_len=0;
1509     fl.l_pid=0;
1510 #endif
1511
1512     if (PARTDECOMP(cr))
1513     {
1514         gmx_fatal(FARGS,
1515                   "read_checkpoint not (yet) supported with particle decomposition");
1516     }
1517     
1518     fp = gmx_fio_open(fn,"r");
1519     do_cpt_header(gmx_fio_getxdr(fp),TRUE,&file_version,
1520                   &version,&btime,&buser,&bmach,&double_prec,&fprog,&ftime,
1521                   &eIntegrator_f,simulation_part,step,t,
1522                   &nppnodes_f,dd_nc_f,&npmenodes_f,
1523                   &natoms,&ngtc,&nnhpres,&nhchainlength,
1524                   &fflags,&flags_eks,&flags_enh,NULL);
1525
1526     if (bAppendOutputFiles &&
1527         file_version >= 13 && double_prec != GMX_CPT_BUILD_DP)
1528     {
1529         gmx_fatal(FARGS,"Output file appending requested, but the code and checkpoint file precision (single/double) don't match");
1530     }
1531     
1532     if (cr == NULL || MASTER(cr))
1533     {
1534         fprintf(stderr,"\nReading checkpoint file %s generated: %s\n\n",
1535                 fn,ftime);
1536     }
1537         
1538         /* This will not be written if we do appending, since fplog is still NULL then */
1539     if (fplog)
1540     {
1541         fprintf(fplog,"\n");
1542         fprintf(fplog,"Reading checkpoint file %s\n",fn);
1543         fprintf(fplog,"  file generated by:     %s\n",fprog);  
1544         fprintf(fplog,"  file generated at:     %s\n",ftime);  
1545         fprintf(fplog,"  GROMACS build time:    %s\n",btime);  
1546         fprintf(fplog,"  GROMACS build user:    %s\n",buser);  
1547         fprintf(fplog,"  GROMACS build machine: %s\n",bmach);  
1548         fprintf(fplog,"  GROMACS double prec.:  %d\n",double_prec);
1549         fprintf(fplog,"  simulation part #:     %d\n",*simulation_part);
1550         fprintf(fplog,"  step:                  %s\n",gmx_step_str(*step,buf));
1551         fprintf(fplog,"  time:                  %f\n",*t);  
1552         fprintf(fplog,"\n");
1553     }
1554     
1555     if (natoms != state->natoms)
1556     {
1557         gmx_fatal(FARGS,"Checkpoint file is for a system of %d atoms, while the current system consists of %d atoms",natoms,state->natoms);
1558     }
1559     if (ngtc != state->ngtc)
1560     {
1561         gmx_fatal(FARGS,"Checkpoint file is for a system of %d T-coupling groups, while the current system consists of %d T-coupling groups",ngtc,state->ngtc);
1562     }
1563     if (nnhpres != state->nnhpres)
1564     {
1565         gmx_fatal(FARGS,"Checkpoint file is for a system of %d NH-pressure-coupling variables, while the current system consists of %d NH-pressure-coupling variables",nnhpres,state->nnhpres);
1566     }
1567
1568     init_gtc_state(state,state->ngtc,state->nnhpres,nhchainlength); /* need to keep this here to keep the tpr format working */
1569     /* write over whatever was read; we use the number of Nose-Hoover chains from the checkpoint */
1570     
1571     if (eIntegrator_f != eIntegrator)
1572     {
1573         if (MASTER(cr))
1574         {
1575             fprintf(stderr,int_warn,EI(eIntegrator_f),EI(eIntegrator));
1576         }
1577                 if(bAppendOutputFiles)
1578                 {
1579                         gmx_fatal(FARGS,
1580                                           "Output file appending requested, but input/checkpoint integrators do not match.\n"
1581                                           "Stopping the run to prevent you from ruining all your data...\n"
1582                                           "If you _really_ know what you are doing, try with the -noappend option.\n");
1583                 }
1584         if (fplog)
1585         {
1586             fprintf(fplog,int_warn,EI(eIntegrator_f),EI(eIntegrator));
1587         }
1588     }
1589
1590     if (!PAR(cr))
1591     {
1592         nppnodes = 1;
1593         cr->npmenodes = 0;
1594     }
1595     else if (bPartDecomp)
1596     {
1597         nppnodes = cr->nnodes;
1598         cr->npmenodes = 0;
1599     }
1600     else if (cr->nnodes == nppnodes_f + npmenodes_f)
1601     {
1602         if (cr->npmenodes < 0)
1603         {
1604             cr->npmenodes = npmenodes_f;
1605         }
1606         nppnodes = cr->nnodes - cr->npmenodes;
1607         if (nppnodes == nppnodes_f)
1608         {
1609             for(d=0; d<DIM; d++)
1610             {
1611                 if (dd_nc[d] == 0)
1612                 {
1613                     dd_nc[d] = dd_nc_f[d];
1614                 }
1615             }
1616         }
1617     }
1618     else
1619     {
1620         /* The number of PP nodes has not been set yet */
1621         nppnodes = -1;
1622     }
1623
1624     if ((EI_SD(eIntegrator) || eIntegrator == eiBD) && nppnodes > 0)
1625     {
1626         /* Correct the RNG state size for the number of PP nodes.
1627          * Such assignments should all be moved to one central function.
1628          */
1629         state->nrng  = nppnodes*gmx_rng_n();
1630         state->nrngi = nppnodes;
1631     }
1632     
1633     *bReadRNG = TRUE;
1634     if (fflags != state->flags)
1635     {
1636                 
1637         if (MASTER(cr))
1638         {
1639                         if(bAppendOutputFiles)
1640                         {
1641                                 gmx_fatal(FARGS,
1642                                                   "Output file appending requested, but input and checkpoint states are not identical.\n"
1643                                                   "Stopping the run to prevent you from ruining all your data...\n"
1644                                                   "You can try with the -noappend option, and get more info in the log file.\n");
1645                         }
1646                         
1647             if (getenv("GMX_ALLOW_CPT_MISMATCH") == NULL)
1648             {
1649                 gmx_fatal(FARGS,"You seem to have switched ensemble, integrator, T and/or P-coupling algorithm between the cpt and tpr file. The recommended way of doing this is passing the cpt file to grompp (with option -t) instead of to mdrun. If you know what you are doing, you can override this error by setting the env.var. GMX_ALLOW_CPT_MISMATCH");
1650             }
1651             else
1652             {
1653                 fprintf(stderr,
1654                         "WARNING: The checkpoint state entries do not match the simulation,\n"
1655                         "         see the log file for details\n\n");
1656             }
1657         }
1658                 
1659                 if(fplog)
1660                 {
1661                         print_flag_mismatch(fplog,state->flags,fflags);
1662                 }
1663     }
1664     else
1665     {
1666         if ((EI_SD(eIntegrator) || eIntegrator == eiBD) &&
1667             nppnodes != nppnodes_f)
1668         {
1669             *bReadRNG = FALSE;
1670             if (MASTER(cr))
1671             {
1672                 fprintf(stderr,sd_note,nppnodes_f,nppnodes);
1673             }
1674             if (fplog)
1675             {
1676                 fprintf(fplog ,sd_note,nppnodes_f,nppnodes);
1677             }
1678         }
1679         if (MASTER(cr))
1680         {
1681             check_match(fplog,version,btime,buser,bmach,double_prec,fprog,
1682                         cr,bPartDecomp,nppnodes_f,npmenodes_f,dd_nc,dd_nc_f);
1683         }
1684     }
1685     ret = do_cpt_state(gmx_fio_getxdr(fp),TRUE,fflags,state,*bReadRNG,NULL);
1686     if (ret)
1687     {
1688         cp_error();
1689     }
1690     ret = do_cpt_ekinstate(gmx_fio_getxdr(fp),TRUE,
1691                            flags_eks,&state->ekinstate,NULL);
1692     if (ret)
1693     {
1694         cp_error();
1695     }
1696     *bReadEkin = ((flags_eks & (1<<eeksEKINH)) || (flags_eks & (1<<eeksEKINF)) || (flags_eks & (1<<eeksEKINO)) ||
1697                   ((flags_eks & (1<<eeksEKINSCALEF)) | (flags_eks & (1<<eeksEKINSCALEH)) | (flags_eks & (1<<eeksVSCALE))));
1698     
1699     ret = do_cpt_enerhist(gmx_fio_getxdr(fp),TRUE,
1700                           flags_enh,&state->enerhist,NULL);
1701     if (ret)
1702     {
1703         cp_error();
1704     }
1705
1706     if (file_version < 6)
1707     {
1708         const char *warn="Reading checkpoint file in old format, assuming that the run that generated this file started at step 0, if this is not the case the averages stored in the energy file will be incorrect.";
1709
1710         fprintf(stderr,"\nWARNING: %s\n\n",warn);
1711         if (fplog)
1712         {
1713             fprintf(fplog,"\nWARNING: %s\n\n",warn);
1714         }
1715         state->enerhist.nsum     = *step;
1716         state->enerhist.nsum_sim = *step;
1717     }
1718
1719         ret = do_cpt_files(gmx_fio_getxdr(fp),TRUE,&outputfiles,&nfiles,NULL,file_version);
1720         if (ret)
1721         {
1722                 cp_error();
1723         }
1724                                            
1725     ret = do_cpt_footer(gmx_fio_getxdr(fp),TRUE,file_version);
1726     if (ret)
1727     {
1728         cp_error();
1729     }
1730     if( gmx_fio_close(fp) != 0)
1731         {
1732         gmx_file("Cannot read/write checkpoint; corrupt file, or maybe you are out of disk space?");
1733         }
1734     
1735     sfree(fprog);
1736     sfree(ftime);
1737     sfree(btime);
1738     sfree(buser);
1739     sfree(bmach);
1740         
1741         /* If the user wants to append to output files,
1742      * we use the file pointer positions of the output files stored
1743      * in the checkpoint file and truncate the files such that any frames
1744      * written after the checkpoint time are removed.
1745      * All files are md5sum checked such that we can be sure that
1746      * we do not truncate other (maybe imprortant) files.
1747          */
1748     if (bAppendOutputFiles)
1749     {
1750         if (fn2ftp(outputfiles[0].filename)!=efLOG)
1751         {
1752             /* make sure first file is log file so that it is OK to use it for 
1753              * locking
1754              */
1755             gmx_fatal(FARGS,"The first output file should always be the log "
1756                       "file but instead is: %s", outputfiles[0].filename);
1757         }
1758         for(i=0;i<nfiles;i++)
1759         {
1760             if (outputfiles[i].offset < 0)
1761             {
1762                 gmx_fatal(FARGS,"The original run wrote a file called '%s' which "
1763                     "is larger than 2 GB, but mdrun did not support large file"
1764                     " offsets. Can not append. Run mdrun with -noappend",
1765                     outputfiles[i].filename);
1766             }
1767 #ifdef GMX_FAHCORE
1768             chksum_file=gmx_fio_open(outputfiles[i].filename,"a");
1769
1770 #else
1771             chksum_file=gmx_fio_open(outputfiles[i].filename,"r+");
1772
1773             /* lock log file */                
1774             if (i==0)
1775             {
1776 #ifndef GMX_NATIVE_WINDOWS
1777                 if (fcntl(fileno(gmx_fio_getfp(chksum_file)), F_SETLK, &fl)
1778                     ==-1)
1779 #else
1780                 if (_locking(fileno(gmx_fio_getfp(chksum_file)), _LK_NBLCK, LONG_MAX)==-1)
1781 #endif
1782                 {
1783                     if (errno!=EACCES && errno!=EAGAIN)
1784                     {
1785                         gmx_fatal(FARGS,"Failed to lock: %s. %s.",
1786                                   outputfiles[i].filename, strerror(errno));
1787                     }
1788                     else 
1789                     {
1790                         gmx_fatal(FARGS,"Failed to lock: %s. Already running "
1791                                   "simulation?", outputfiles[i].filename);
1792                     }
1793                 }
1794             }
1795             
1796             /* compute md5 chksum */ 
1797             if (outputfiles[i].chksum_size != -1)
1798             {
1799                 if (gmx_fio_get_file_md5(chksum_file,outputfiles[i].offset,
1800                                      digest) != outputfiles[i].chksum_size)  /*at the end of the call the file position is at the end of the file*/
1801                 {
1802                     gmx_fatal(FARGS,"Can't read %d bytes of '%s' to compute checksum. The file has been replaced or its contents has been modified.",
1803                               outputfiles[i].chksum_size, 
1804                               outputfiles[i].filename);
1805                 }
1806             } 
1807             if (i==0)  /*log file needs to be seeked in case we need to truncate (other files are truncated below)*/
1808             {
1809                 if (gmx_fio_seek(chksum_file,outputfiles[i].offset))
1810                 {
1811                         gmx_fatal(FARGS,"Seek error! Failed to truncate log-file: %s.", strerror(errno));
1812                 }
1813             }
1814 #endif
1815             
1816             if (i==0) /*open log file here - so that lock is never lifted 
1817                         after chksum is calculated */
1818             {
1819                 *pfplog = gmx_fio_getfp(chksum_file);
1820             }
1821             else
1822             {
1823                 gmx_fio_close(chksum_file);
1824             }
1825 #ifndef GMX_FAHCORE            
1826             /* compare md5 chksum */
1827             if (outputfiles[i].chksum_size != -1 &&
1828                 memcmp(digest,outputfiles[i].chksum,16)!=0) 
1829             {
1830                 if (debug)
1831                 {
1832                     fprintf(debug,"chksum for %s: ",outputfiles[i].filename);
1833                     for (j=0; j<16; j++)
1834                     {
1835                         fprintf(debug,"%02x",digest[j]);
1836                     }
1837                     fprintf(debug,"\n");
1838                 }
1839                 gmx_fatal(FARGS,"Checksum wrong for '%s'. The file has been replaced or its contents has been modified.",
1840                           outputfiles[i].filename);
1841             }
1842 #endif        
1843
1844               
1845             if (i!=0) /*log file is already seeked to correct position */
1846             {
1847 #ifdef GMX_NATIVE_WINDOWS
1848                 rc = gmx_wintruncate(outputfiles[i].filename,outputfiles[i].offset);
1849 #else            
1850                 rc = truncate(outputfiles[i].filename,outputfiles[i].offset);
1851 #endif
1852                 if(rc!=0)
1853                 {
1854                     gmx_fatal(FARGS,"Truncation of file %s failed.",outputfiles[i].filename);
1855                 }
1856             }
1857         }
1858     }
1859
1860     sfree(outputfiles);
1861 }
1862
1863
1864 void load_checkpoint(const char *fn,FILE **fplog,
1865                      t_commrec *cr,gmx_bool bPartDecomp,ivec dd_nc,
1866                      t_inputrec *ir,t_state *state,
1867                      gmx_bool *bReadRNG,gmx_bool *bReadEkin,gmx_bool bAppend)
1868 {
1869     gmx_large_int_t step;
1870     double t;
1871
1872     if (SIMMASTER(cr)) {
1873       /* Read the state from the checkpoint file */
1874       read_checkpoint(fn,fplog,
1875                       cr,bPartDecomp,dd_nc,
1876                       ir->eI,&step,&t,state,bReadRNG,bReadEkin,
1877                       &ir->simulation_part,bAppend);
1878     }
1879     if (PAR(cr)) {
1880       gmx_bcast(sizeof(cr->npmenodes),&cr->npmenodes,cr);
1881       gmx_bcast(DIM*sizeof(dd_nc[0]),dd_nc,cr);
1882       gmx_bcast(sizeof(step),&step,cr);
1883       gmx_bcast(sizeof(*bReadRNG),bReadRNG,cr);
1884       gmx_bcast(sizeof(*bReadEkin),bReadEkin,cr);
1885     }
1886     ir->bContinuation    = TRUE;
1887     if (ir->nsteps >= 0)
1888     {
1889         ir->nsteps          += ir->init_step - step;
1890     }
1891     ir->init_step        = step;
1892         ir->simulation_part += 1;
1893 }
1894
1895 static void read_checkpoint_data(t_fileio *fp,int *simulation_part,
1896                                  gmx_large_int_t *step,double *t,t_state *state,
1897                                  gmx_bool bReadRNG,
1898                                  int *nfiles,gmx_file_position_t **outputfiles)
1899 {
1900     int  file_version;
1901     char *version,*btime,*buser,*bmach,*fprog,*ftime;
1902     int  double_prec;
1903     int  eIntegrator;
1904     int  nppnodes,npme;
1905     ivec dd_nc;
1906     int  flags_eks,flags_enh;
1907     int  nfiles_loc;
1908     gmx_file_position_t *files_loc=NULL;
1909     int  ret;
1910         
1911     do_cpt_header(gmx_fio_getxdr(fp),TRUE,&file_version,
1912                   &version,&btime,&buser,&bmach,&double_prec,&fprog,&ftime,
1913                   &eIntegrator,simulation_part,step,t,&nppnodes,dd_nc,&npme,
1914                   &state->natoms,&state->ngtc,&state->nnhpres,&state->nhchainlength,
1915                   &state->flags,&flags_eks,&flags_enh,NULL);
1916     ret =
1917         do_cpt_state(gmx_fio_getxdr(fp),TRUE,state->flags,state,bReadRNG,NULL);
1918     if (ret)
1919     {
1920         cp_error();
1921     }
1922     ret = do_cpt_ekinstate(gmx_fio_getxdr(fp),TRUE,
1923                            flags_eks,&state->ekinstate,NULL);
1924     if (ret)
1925     {
1926         cp_error();
1927     }
1928     ret = do_cpt_enerhist(gmx_fio_getxdr(fp),TRUE,
1929                           flags_enh,&state->enerhist,NULL);
1930     if (ret)
1931     {
1932         cp_error();
1933     }
1934
1935     ret = do_cpt_files(gmx_fio_getxdr(fp),TRUE,
1936                        outputfiles != NULL ? outputfiles : &files_loc,
1937                        outputfiles != NULL ? nfiles : &nfiles_loc,
1938                        NULL,file_version);
1939     if (files_loc != NULL)
1940     {
1941         sfree(files_loc);
1942     }
1943         
1944     if (ret)
1945     {
1946         cp_error();
1947     }
1948         
1949     ret = do_cpt_footer(gmx_fio_getxdr(fp),TRUE,file_version);
1950     if (ret)
1951     {
1952         cp_error();
1953     }
1954
1955     sfree(fprog);
1956     sfree(ftime);
1957     sfree(btime);
1958     sfree(buser);
1959     sfree(bmach);
1960 }
1961
1962 void 
1963 read_checkpoint_state(const char *fn,int *simulation_part,
1964                       gmx_large_int_t *step,double *t,t_state *state)
1965 {
1966     t_fileio *fp;
1967     
1968     fp = gmx_fio_open(fn,"r");
1969     read_checkpoint_data(fp,simulation_part,step,t,state,FALSE,NULL,NULL);
1970     if( gmx_fio_close(fp) != 0)
1971         {
1972         gmx_file("Cannot read/write checkpoint; corrupt file, or maybe you are out of disk space?");
1973         }
1974 }
1975
1976 void read_checkpoint_trxframe(t_fileio *fp,t_trxframe *fr)
1977 {
1978     t_state state;
1979     int simulation_part;
1980     gmx_large_int_t step;
1981     double t;
1982     
1983     init_state(&state,0,0,0,0);
1984     
1985     read_checkpoint_data(fp,&simulation_part,&step,&t,&state,FALSE,NULL,NULL);
1986     
1987     fr->natoms  = state.natoms;
1988     fr->bTitle  = FALSE;
1989     fr->bStep   = TRUE;
1990     fr->step    = gmx_large_int_to_int(step,
1991                                     "conversion of checkpoint to trajectory");
1992     fr->bTime   = TRUE;
1993     fr->time    = t;
1994     fr->bLambda = TRUE;
1995     fr->lambda  = state.lambda;
1996     fr->bAtoms  = FALSE;
1997     fr->bX      = (state.flags & (1<<estX));
1998     if (fr->bX)
1999     {
2000         fr->x     = state.x;
2001         state.x   = NULL;
2002     }
2003     fr->bV      = (state.flags & (1<<estV));
2004     if (fr->bV)
2005     {
2006         fr->v     = state.v;
2007         state.v   = NULL;
2008     }
2009     fr->bF      = FALSE;
2010     fr->bBox    = (state.flags & (1<<estBOX));
2011     if (fr->bBox)
2012     {
2013         copy_mat(state.box,fr->box);
2014     }
2015     done_state(&state);
2016 }
2017
2018 void list_checkpoint(const char *fn,FILE *out)
2019 {
2020     t_fileio *fp;
2021     int  file_version;
2022     char *version,*btime,*buser,*bmach,*fprog,*ftime;
2023     int  double_prec;
2024     int  eIntegrator,simulation_part,nppnodes,npme;
2025     gmx_large_int_t step;
2026     double t;
2027     ivec dd_nc;
2028     t_state state;
2029     int  flags_eks,flags_enh;
2030     int  indent;
2031     int  i,j;
2032     int  ret;
2033     gmx_file_position_t *outputfiles;
2034         int  nfiles;
2035         
2036     init_state(&state,-1,-1,-1,-1);
2037
2038     fp = gmx_fio_open(fn,"r");
2039     do_cpt_header(gmx_fio_getxdr(fp),TRUE,&file_version,
2040                   &version,&btime,&buser,&bmach,&double_prec,&fprog,&ftime,
2041                   &eIntegrator,&simulation_part,&step,&t,&nppnodes,dd_nc,&npme,
2042                   &state.natoms,&state.ngtc,&state.nnhpres,&state.nhchainlength,
2043                   &state.flags,&flags_eks,&flags_enh,out);
2044     ret = do_cpt_state(gmx_fio_getxdr(fp),TRUE,state.flags,&state,TRUE,out);
2045     if (ret)
2046     {
2047         cp_error();
2048     }
2049     ret = do_cpt_ekinstate(gmx_fio_getxdr(fp),TRUE,
2050                            flags_eks,&state.ekinstate,out);
2051     if (ret)
2052     {
2053         cp_error();
2054     }
2055     ret = do_cpt_enerhist(gmx_fio_getxdr(fp),TRUE,
2056                           flags_enh,&state.enerhist,out);
2057
2058     if (ret == 0)
2059     {
2060                 do_cpt_files(gmx_fio_getxdr(fp),TRUE,&outputfiles,&nfiles,out,file_version);
2061         }
2062         
2063     if (ret == 0)
2064     {
2065         ret = do_cpt_footer(gmx_fio_getxdr(fp),TRUE,file_version);
2066     }
2067         
2068     if (ret)
2069     {
2070         cp_warning(out);
2071     }
2072     if( gmx_fio_close(fp) != 0)
2073         {
2074         gmx_file("Cannot read/write checkpoint; corrupt file, or maybe you are out of disk space?");
2075         }
2076     
2077     done_state(&state);
2078 }
2079
2080
2081 static gmx_bool exist_output_file(const char *fnm_cp,int nfile,const t_filenm fnm[])
2082 {
2083     int i;
2084
2085     /* Check if the output file name stored in the checkpoint file
2086      * is one of the output file names of mdrun.
2087      */
2088     i = 0;
2089     while (i < nfile &&
2090            !(is_output(&fnm[i]) && strcmp(fnm_cp,fnm[i].fns[0]) == 0))
2091     {
2092         i++;
2093     }
2094     
2095     return (i < nfile && gmx_fexist(fnm_cp));
2096 }
2097
2098 /* This routine cannot print tons of data, since it is called before the log file is opened. */
2099 gmx_bool read_checkpoint_simulation_part(const char *filename, int *simulation_part,
2100                                      gmx_large_int_t *cpt_step,t_commrec *cr,
2101                                      gmx_bool bAppendReq,
2102                                      int nfile,const t_filenm fnm[],
2103                                      const char *part_suffix,gmx_bool *bAddPart)
2104 {
2105     t_fileio *fp;
2106     gmx_large_int_t step=0;
2107         double t;
2108     t_state state;
2109     int  nfiles;
2110     gmx_file_position_t *outputfiles;
2111     int  nexist,f;
2112     gmx_bool bAppend;
2113     char *fn,suf_up[STRLEN];
2114
2115     bAppend = FALSE;
2116
2117     if (SIMMASTER(cr)) {
2118         if(!gmx_fexist(filename) || (!(fp = gmx_fio_open(filename,"r")) ))
2119         {
2120             *simulation_part = 0;
2121         }
2122         else 
2123         {
2124             init_state(&state,0,0,0,0);
2125
2126             read_checkpoint_data(fp,simulation_part,&step,&t,&state,FALSE,
2127                                  &nfiles,&outputfiles);
2128             if( gmx_fio_close(fp) != 0)
2129             {
2130                 gmx_file("Cannot read/write checkpoint; corrupt file, or maybe you are out of disk space?");
2131             }
2132             done_state(&state);
2133
2134             if (bAppendReq)
2135             {
2136                 nexist = 0;
2137                 for(f=0; f<nfiles; f++)
2138                 {
2139                     if (exist_output_file(outputfiles[f].filename,nfile,fnm))
2140                     {
2141                         nexist++;
2142                     }
2143                 }
2144                 if (nexist == nfiles)
2145                 {
2146                     bAppend = bAppendReq;
2147                 }
2148                 else if (nexist > 0)
2149                 {
2150                     fprintf(stderr,
2151                             "Output file appending has been requested,\n"
2152                             "but some output files listed in the checkpoint file %s\n"
2153                             "are not present or are named differently by the current program:\n",
2154                             filename);
2155                     fprintf(stderr,"output files present:");
2156                     for(f=0; f<nfiles; f++)
2157                     {
2158                         if (exist_output_file(outputfiles[f].filename,
2159                                               nfile,fnm))
2160                         {
2161                             fprintf(stderr," %s",outputfiles[f].filename);
2162                         }
2163                     }
2164                     fprintf(stderr,"\n");
2165                     fprintf(stderr,"output files not present or named differently:");
2166                     for(f=0; f<nfiles; f++)
2167                     {
2168                         if (!exist_output_file(outputfiles[f].filename,
2169                                                nfile,fnm))
2170                         {
2171                             fprintf(stderr," %s",outputfiles[f].filename);
2172                         }
2173                     }
2174                     fprintf(stderr,"\n");
2175                     
2176                     gmx_fatal(FARGS,"File appending requested, but only %d of the %d output files are present",nexist,nfiles);
2177                 }
2178             }
2179             
2180             if (bAppend)
2181             {
2182                 if (nfiles == 0)
2183                 {
2184                     gmx_fatal(FARGS,"File appending requested, but no output file information is stored in the checkpoint file");
2185                 }
2186                 fn = outputfiles[0].filename;
2187                 if (strlen(fn) < 4 ||
2188                     gmx_strcasecmp(fn+strlen(fn)-4,ftp2ext(efLOG)) == 0)
2189                 {
2190                     gmx_fatal(FARGS,"File appending requested, but the log file is not the first file listed in the checkpoint file");
2191                 }
2192                 /* Set bAddPart to whether the suffix string '.part' is present
2193                  * in the log file name.
2194                  */
2195                 strcpy(suf_up,part_suffix);
2196                 upstring(suf_up);
2197                 *bAddPart = (strstr(fn,part_suffix) != NULL ||
2198                              strstr(fn,suf_up) != NULL);
2199             }
2200
2201             sfree(outputfiles);
2202         }
2203     }
2204     if (PAR(cr))
2205     {
2206         gmx_bcast(sizeof(*simulation_part),simulation_part,cr);
2207
2208         if (*simulation_part > 0 && bAppendReq)
2209         {
2210             gmx_bcast(sizeof(bAppend),&bAppend,cr);
2211             gmx_bcast(sizeof(*bAddPart),bAddPart,cr);
2212         }
2213     }
2214     if (NULL != cpt_step)
2215     {
2216         *cpt_step = step;
2217     }
2218
2219     return bAppend;
2220 }