Merge release-4-6 into release-5-0
[alexxy/gromacs.git] / src / gromacs / fileio / confio.c
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5  * Copyright (c) 2001-2004, The GROMACS development team.
6  * Copyright (c) 2013,2014, 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.
10  *
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.
15  *
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.
20  *
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.
25  *
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.
33  *
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.
36  */
37 #ifdef HAVE_CONFIG_H
38 #include <config.h>
39 #endif
40
41 #include <math.h>
42 #include "sysstuff.h"
43 #include "typedefs.h"
44 #include "gromacs/utility/smalloc.h"
45 #include "sysstuff.h"
46 #include <errno.h>
47 #include "macros.h"
48 #include "gromacs/utility/cstringutil.h"
49 #include "confio.h"
50 #include "vec.h"
51 #include "symtab.h"
52 #include "futil.h"
53 #include "xdrf.h"
54 #include "filenm.h"
55 #include "pdbio.h"
56 #include "tpxio.h"
57 #include "trxio.h"
58 #include "gmx_fatal.h"
59 #include "copyrite.h"
60 #include "pbc.h"
61 #include "mtop_util.h"
62 #include "gmxfio.h"
63
64 #define CHAR_SHIFT 24
65
66 static int read_g96_pos(char line[], t_symtab *symtab,
67                         FILE *fp, const char *infile,
68                         t_trxframe *fr)
69 {
70     t_atoms   *atoms;
71     gmx_bool   bEnd;
72     int        nwanted, natoms, atnr, resnr = 0, oldres, newres, shift;
73     char       anm[STRLEN], resnm[STRLEN];
74     char       c1, c2;
75     double     db1, db2, db3;
76
77     nwanted = fr->natoms;
78
79     atoms = fr->atoms;
80
81     natoms = 0;
82
83     if (fr->bX)
84     {
85         if (fr->bAtoms)
86         {
87             shift = CHAR_SHIFT;
88         }
89         else
90         {
91             shift = 0;
92         }
93         newres  = -1;
94         oldres  = -666; /* Unlikely number for the first residue! */
95         bEnd    = FALSE;
96         while (!bEnd && fgets2(line, STRLEN, fp))
97         {
98             bEnd = (strncmp(line, "END", 3) == 0);
99             if (!bEnd  && (line[0] != '#'))
100             {
101                 if (sscanf(line+shift, "%15lf%15lf%15lf", &db1, &db2, &db3) != 3)
102                 {
103                     gmx_fatal(FARGS, "Did not find 3 coordinates for atom %d in %s\n",
104                               natoms+1, infile);
105                 }
106                 if ((nwanted != -1) && (natoms >= nwanted))
107                 {
108                     gmx_fatal(FARGS,
109                               "Found more coordinates (%d) in %s than expected %d\n",
110                               natoms, infile, nwanted);
111                 }
112                 if (atoms)
113                 {
114                     if (fr->bAtoms &&
115                         (sscanf(line, "%5d%c%5s%c%5s%7d", &resnr, &c1, resnm, &c2, anm, &atnr)
116                          != 6))
117                     {
118                         if (oldres >= 0)
119                         {
120                             resnr = oldres;
121                         }
122                         else
123                         {
124                             resnr    = 1;
125                             strncpy(resnm, "???", sizeof(resnm)-1);
126                         }
127                         strncpy(anm, "???", sizeof(anm)-1);
128                     }
129                     atoms->atomname[natoms] = put_symtab(symtab, anm);
130                     if (resnr != oldres)
131                     {
132                         oldres = resnr;
133                         newres++;
134                         if (newres >= atoms->nr)
135                         {
136                             gmx_fatal(FARGS, "More residues than atoms in %s (natoms = %d)",
137                                       infile, atoms->nr);
138                         }
139                         atoms->atom[natoms].resind = newres;
140                         if (newres+1 > atoms->nres)
141                         {
142                             atoms->nres = newres+1;
143                         }
144                         t_atoms_set_resinfo(atoms, natoms, symtab, resnm, resnr, ' ', 0, ' ');
145                     }
146                     else
147                     {
148                         atoms->atom[natoms].resind = newres;
149                     }
150                 }
151                 if (fr->x)
152                 {
153                     fr->x[natoms][0] = db1;
154                     fr->x[natoms][1] = db2;
155                     fr->x[natoms][2] = db3;
156                 }
157                 natoms++;
158             }
159         }
160         if ((nwanted != -1) && natoms != nwanted)
161         {
162             fprintf(stderr,
163                     "Warning: found less coordinates (%d) in %s than expected %d\n",
164                     natoms, infile, nwanted);
165         }
166     }
167
168     fr->natoms = natoms;
169
170     return natoms;
171 }
172
173 static int read_g96_vel(char line[], FILE *fp, const char *infile,
174                         t_trxframe *fr)
175 {
176     gmx_bool   bEnd;
177     int        nwanted, natoms = -1, shift;
178     double     db1, db2, db3;
179
180     nwanted = fr->natoms;
181
182     if (fr->v && fr->bV)
183     {
184         if (strcmp(line, "VELOCITYRED") == 0)
185         {
186             shift = 0;
187         }
188         else
189         {
190             shift = CHAR_SHIFT;
191         }
192         natoms = 0;
193         bEnd   = FALSE;
194         while (!bEnd && fgets2(line, STRLEN, fp))
195         {
196             bEnd = (strncmp(line, "END", 3) == 0);
197             if (!bEnd && (line[0] != '#'))
198             {
199                 if (sscanf(line+shift, "%15lf%15lf%15lf", &db1, &db2, &db3) != 3)
200                 {
201                     gmx_fatal(FARGS, "Did not find 3 velocities for atom %d in %s",
202                               natoms+1, infile);
203                 }
204                 if ((nwanted != -1) && (natoms >= nwanted))
205                 {
206                     gmx_fatal(FARGS, "Found more velocities (%d) in %s than expected %d\n",
207                               natoms, infile, nwanted);
208                 }
209                 if (fr->v)
210                 {
211                     fr->v[natoms][0] = db1;
212                     fr->v[natoms][1] = db2;
213                     fr->v[natoms][2] = db3;
214                 }
215                 natoms++;
216             }
217         }
218         if ((nwanted != -1) && (natoms != nwanted))
219         {
220             fprintf(stderr,
221                     "Warning: found less velocities (%d) in %s than expected %d\n",
222                     natoms, infile, nwanted);
223         }
224     }
225
226     return natoms;
227 }
228
229 int read_g96_conf(FILE *fp, const char *infile, t_trxframe *fr, char *line)
230 {
231     t_symtab  *symtab = NULL;
232     gmx_bool   bAtStart, bTime, bAtoms, bPos, bVel, bBox, bEnd, bFinished;
233     int        natoms, nbp;
234     double     db1, db2, db3, db4, db5, db6, db7, db8, db9;
235
236     bAtStart = (ftell(fp) == 0);
237
238     clear_trxframe(fr, FALSE);
239
240     if (!symtab)
241     {
242         snew(symtab, 1);
243         open_symtab(symtab);
244     }
245
246     natoms = 0;
247
248     if (bAtStart)
249     {
250         while (!fr->bTitle && fgets2(line, STRLEN, fp))
251         {
252             fr->bTitle = (strcmp(line, "TITLE") == 0);
253         }
254         if (fr->title == NULL)
255         {
256             fgets2(line, STRLEN, fp);
257             fr->title = strdup(line);
258         }
259         bEnd = FALSE;
260         while (!bEnd && fgets2(line, STRLEN, fp))
261         {
262             bEnd = (strcmp(line, "END") == 0);
263         }
264         fgets2(line, STRLEN, fp);
265     }
266
267     /* Do not get a line if we are not at the start of the file, *
268      * because without a parameter file we don't know what is in *
269      * the trajectory and we have already read the line in the   *
270      * previous call (VERY DIRTY).                               */
271     bFinished = FALSE;
272     do
273     {
274         bTime  = (strcmp(line, "TIMESTEP") == 0);
275         bAtoms = (strcmp(line, "POSITION") == 0);
276         bPos   = (bAtoms || (strcmp(line, "POSITIONRED") == 0));
277         bVel   = (strncmp(line, "VELOCITY", 8) == 0);
278         bBox   = (strcmp(line, "BOX") == 0);
279         if (bTime)
280         {
281             if (!fr->bTime && !fr->bX)
282             {
283                 fr->bStep = bTime;
284                 fr->bTime = bTime;
285                 do
286                 {
287                     bFinished = (fgets2(line, STRLEN, fp) == NULL);
288                 }
289                 while (!bFinished && (line[0] == '#'));
290                 sscanf(line, "%15d%15lf", &(fr->step), &db1);
291                 fr->time = db1;
292             }
293             else
294             {
295                 bFinished = TRUE;
296             }
297         }
298         if (bPos)
299         {
300             if (!fr->bX)
301             {
302                 fr->bAtoms = bAtoms;
303                 fr->bX     = bPos;
304                 natoms     = read_g96_pos(line, symtab, fp, infile, fr);
305             }
306             else
307             {
308                 bFinished = TRUE;
309             }
310         }
311         if (fr->v && bVel)
312         {
313             fr->bV = bVel;
314             natoms = read_g96_vel(line, fp, infile, fr);
315         }
316         if (bBox)
317         {
318             fr->bBox = bBox;
319             clear_mat(fr->box);
320             bEnd = FALSE;
321             while (!bEnd && fgets2(line, STRLEN, fp))
322             {
323                 bEnd = (strncmp(line, "END", 3) == 0);
324                 if (!bEnd && (line[0] != '#'))
325                 {
326                     nbp = sscanf(line, "%15lf%15lf%15lf%15lf%15lf%15lf%15lf%15lf%15lf",
327                                  &db1, &db2, &db3, &db4, &db5, &db6, &db7, &db8, &db9);
328                     if (nbp < 3)
329                     {
330                         gmx_fatal(FARGS, "Found a BOX line, but no box in %s", infile);
331                     }
332                     fr->box[XX][XX] = db1;
333                     fr->box[YY][YY] = db2;
334                     fr->box[ZZ][ZZ] = db3;
335                     if (nbp == 9)
336                     {
337                         fr->box[XX][YY] = db4;
338                         fr->box[XX][ZZ] = db5;
339                         fr->box[YY][XX] = db6;
340                         fr->box[YY][ZZ] = db7;
341                         fr->box[ZZ][XX] = db8;
342                         fr->box[ZZ][YY] = db9;
343                     }
344                 }
345             }
346             bFinished = TRUE;
347         }
348     }
349     while (!bFinished && fgets2(line, STRLEN, fp));
350
351     free_symtab(symtab);
352
353     fr->natoms = natoms;
354
355     return natoms;
356 }
357
358 void write_g96_conf(FILE *out, t_trxframe *fr,
359                     int nindex, const atom_id *index)
360 {
361     t_atoms *atoms;
362     int      nout, i, a;
363
364     atoms = fr->atoms;
365
366     if (index)
367     {
368         nout = nindex;
369     }
370     else
371     {
372         nout = fr->natoms;
373     }
374
375     if (fr->bTitle)
376     {
377         fprintf(out, "TITLE\n%s\nEND\n", fr->title);
378     }
379     if (fr->bStep || fr->bTime)
380     {
381         /* Officially the time format is %15.9, which is not enough for 10 ns */
382         fprintf(out, "TIMESTEP\n%15d%15.6f\nEND\n", fr->step, fr->time);
383     }
384     if (fr->bX)
385     {
386         if (fr->bAtoms)
387         {
388             fprintf(out, "POSITION\n");
389             for (i = 0; i < nout; i++)
390             {
391                 if (index)
392                 {
393                     a = index[i];
394                 }
395                 else
396                 {
397                     a = i;
398                 }
399                 fprintf(out, "%5d %-5s %-5s%7d%15.9f%15.9f%15.9f\n",
400                         (atoms->resinfo[atoms->atom[a].resind].nr) % 100000,
401                         *atoms->resinfo[atoms->atom[a].resind].name,
402                         *atoms->atomname[a], (i+1) % 10000000,
403                         fr->x[a][XX], fr->x[a][YY], fr->x[a][ZZ]);
404             }
405         }
406         else
407         {
408             fprintf(out, "POSITIONRED\n");
409             for (i = 0; i < nout; i++)
410             {
411                 if (index)
412                 {
413                     a = index[i];
414                 }
415                 else
416                 {
417                     a = i;
418                 }
419                 fprintf(out, "%15.9f%15.9f%15.9f\n",
420                         fr->x[a][XX], fr->x[a][YY], fr->x[a][ZZ]);
421             }
422         }
423         fprintf(out, "END\n");
424     }
425     if (fr->bV)
426     {
427         if (fr->bAtoms)
428         {
429             fprintf(out, "VELOCITY\n");
430             for (i = 0; i < nout; i++)
431             {
432                 if (index)
433                 {
434                     a = index[i];
435                 }
436                 else
437                 {
438                     a = i;
439                 }
440                 fprintf(out, "%5d %-5s %-5s%7d%15.9f%15.9f%15.9f\n",
441                         (atoms->resinfo[atoms->atom[a].resind].nr) % 100000,
442                         *atoms->resinfo[atoms->atom[a].resind].name,
443                         *atoms->atomname[a], (i+1) % 10000000,
444                         fr->v[a][XX], fr->v[a][YY], fr->v[a][ZZ]);
445             }
446         }
447         else
448         {
449             fprintf(out, "VELOCITYRED\n");
450             for (i = 0; i < nout; i++)
451             {
452                 if (index)
453                 {
454                     a = index[i];
455                 }
456                 else
457                 {
458                     a = i;
459                 }
460                 fprintf(out, "%15.9f%15.9f%15.9f\n",
461                         fr->v[a][XX], fr->v[a][YY], fr->v[a][ZZ]);
462             }
463         }
464         fprintf(out, "END\n");
465     }
466     if (fr->bBox)
467     {
468         fprintf(out, "BOX\n");
469         fprintf(out, "%15.9f%15.9f%15.9f",
470                 fr->box[XX][XX], fr->box[YY][YY], fr->box[ZZ][ZZ]);
471         if (fr->box[XX][YY] || fr->box[XX][ZZ] || fr->box[YY][XX] ||
472             fr->box[YY][ZZ] || fr->box[ZZ][XX] || fr->box[ZZ][YY])
473         {
474             fprintf(out, "%15.9f%15.9f%15.9f%15.9f%15.9f%15.9f",
475                     fr->box[XX][YY], fr->box[XX][ZZ], fr->box[YY][XX],
476                     fr->box[YY][ZZ], fr->box[ZZ][XX], fr->box[ZZ][YY]);
477         }
478         fprintf(out, "\n");
479         fprintf(out, "END\n");
480     }
481 }
482
483 static int get_espresso_word(FILE *fp, char word[])
484 {
485     int  ret, nc, i;
486
487     ret = 0;
488     nc  = 0;
489
490     do
491     {
492         i = fgetc(fp);
493         if (i != EOF)
494         {
495             if (i == ' ' || i == '\n' || i == '\t')
496             {
497                 if (nc > 0)
498                 {
499                     ret = 1;
500                 }
501             }
502             else if (i == '{')
503             {
504                 if (nc == 0)
505                 {
506                     word[nc++] = '{';
507                 }
508                 ret = 2;
509             }
510             else if (i == '}')
511             {
512                 if (nc == 0)
513                 {
514                     word[nc++] = '}';
515                 }
516                 ret = 3;
517             }
518             else
519             {
520                 word[nc++] = (char)i;
521             }
522         }
523     }
524     while (i != EOF && ret == 0);
525
526     word[nc] = '\0';
527
528     /*  printf("'%s'\n",word); */
529
530     return ret;
531 }
532
533 static int check_open_parenthesis(FILE *fp, int r,
534                                   const char *infile, const char *keyword)
535 {
536     int  level_inc;
537     char word[STRLEN];
538
539     level_inc = 0;
540     if (r == 2)
541     {
542         level_inc++;
543     }
544     else
545     {
546         r = get_espresso_word(fp, word);
547         if (r == 2)
548         {
549             level_inc++;
550         }
551         else
552         {
553             gmx_fatal(FARGS, "Expected '{' after '%s' in file '%s'",
554                       keyword, infile);
555         }
556     }
557
558     return level_inc;
559 }
560
561 static int check_close_parenthesis(FILE *fp, int r,
562                                    const char *infile, const char *keyword)
563 {
564     int  level_inc;
565     char word[STRLEN];
566
567     level_inc = 0;
568     if (r == 3)
569     {
570         level_inc--;
571     }
572     else
573     {
574         r = get_espresso_word(fp, word);
575         if (r == 3)
576         {
577             level_inc--;
578         }
579         else
580         {
581             gmx_fatal(FARGS, "Expected '}' after section '%s' in file '%s'",
582                       keyword, infile);
583         }
584     }
585
586     return level_inc;
587 }
588
589 enum {
590     espID, espPOS, espTYPE, espQ, espV, espF, espMOLECULE, espNR
591 };
592 const char *esp_prop[espNR] = {
593     "id", "pos", "type", "q", "v", "f",
594     "molecule"
595 };
596
597 static void read_espresso_conf(const char *infile,
598                                t_atoms *atoms, rvec x[], rvec *v, matrix box)
599 {
600     t_symtab *symtab = NULL;
601     FILE     *fp;
602     char      word[STRLEN], buf[STRLEN];
603     int       natoms, level, npar, r, nprop, p, i, m, molnr;
604     int       prop[32];
605     double    d;
606     gmx_bool  bFoundParticles, bFoundProp, bFoundVariable, bMol;
607
608     if (!symtab)
609     {
610         snew(symtab, 1);
611         open_symtab(symtab);
612     }
613
614     clear_mat(box);
615
616     fp = gmx_fio_fopen(infile, "r");
617
618     bFoundParticles = FALSE;
619     bFoundVariable  = FALSE;
620     bMol            = FALSE;
621     level           = 0;
622     while ((r = get_espresso_word(fp, word)))
623     {
624         if (level == 1 && strcmp(word, "particles") == 0 && !bFoundParticles)
625         {
626             bFoundParticles = TRUE;
627             level          += check_open_parenthesis(fp, r, infile, "particles");
628             nprop           = 0;
629             while (level == 2 && (r = get_espresso_word(fp, word)))
630             {
631                 bFoundProp = FALSE;
632                 for (p = 0; p < espNR; p++)
633                 {
634                     if (strcmp(word, esp_prop[p]) == 0)
635                     {
636                         bFoundProp    = TRUE;
637                         prop[nprop++] = p;
638                         /* printf("  prop[%d] = %s\n",nprop-1,esp_prop[prop[nprop-1]]); */
639                     }
640                 }
641                 if (!bFoundProp && word[0] != '}')
642                 {
643                     gmx_fatal(FARGS, "Can not read Espresso files with particle property '%s'", word);
644                 }
645                 if (bFoundProp && p == espMOLECULE)
646                 {
647                     bMol = TRUE;
648                 }
649                 if (r == 3)
650                 {
651                     level--;
652                 }
653             }
654
655             i = 0;
656             while (level > 0 && (r = get_espresso_word(fp, word)))
657             {
658                 if (r == 2)
659                 {
660                     level++;
661                 }
662                 else if (r == 3)
663                 {
664                     level--;
665                 }
666                 if (level == 2)
667                 {
668                     for (p = 0; p < nprop; p++)
669                     {
670                         switch (prop[p])
671                         {
672                             case espID:
673                                 r = get_espresso_word(fp, word);
674                                 /* Not used */
675                                 break;
676                             case espPOS:
677                                 for (m = 0; m < 3; m++)
678                                 {
679                                     r = get_espresso_word(fp, word);
680                                     sscanf(word, "%lf", &d);
681                                     x[i][m] = d;
682                                 }
683                                 break;
684                             case espTYPE:
685                                 r                   = get_espresso_word(fp, word);
686                                 atoms->atom[i].type = strtol(word, NULL, 10);
687                                 break;
688                             case espQ:
689                                 r = get_espresso_word(fp, word);
690                                 sscanf(word, "%lf", &d);
691                                 atoms->atom[i].q = d;
692                                 break;
693                             case espV:
694                                 for (m = 0; m < 3; m++)
695                                 {
696                                     r = get_espresso_word(fp, word);
697                                     sscanf(word, "%lf", &d);
698                                     v[i][m] = d;
699                                 }
700                                 break;
701                             case espF:
702                                 for (m = 0; m < 3; m++)
703                                 {
704                                     r = get_espresso_word(fp, word);
705                                     /* not used */
706                                 }
707                                 break;
708                             case espMOLECULE:
709                                 r     = get_espresso_word(fp, word);
710                                 molnr = strtol(word, NULL, 10);
711                                 if (i == 0 ||
712                                     atoms->resinfo[atoms->atom[i-1].resind].nr != molnr)
713                                 {
714                                     atoms->atom[i].resind =
715                                         (i == 0 ? 0 : atoms->atom[i-1].resind+1);
716                                     atoms->resinfo[atoms->atom[i].resind].nr       = molnr;
717                                     atoms->resinfo[atoms->atom[i].resind].ic       = ' ';
718                                     atoms->resinfo[atoms->atom[i].resind].chainid  = ' ';
719                                     atoms->resinfo[atoms->atom[i].resind].chainnum = molnr; /* Not sure if this is right? */
720                                 }
721                                 else
722                                 {
723                                     atoms->atom[i].resind = atoms->atom[i-1].resind;
724                                 }
725                                 break;
726                         }
727                     }
728                     /* Generate an atom name from the particle type */
729                     sprintf(buf, "T%d", atoms->atom[i].type);
730                     atoms->atomname[i] = put_symtab(symtab, buf);
731                     if (bMol)
732                     {
733                         if (i == 0 || atoms->atom[i].resind != atoms->atom[i-1].resind)
734                         {
735                             atoms->resinfo[atoms->atom[i].resind].name =
736                                 put_symtab(symtab, "MOL");
737                         }
738                     }
739                     else
740                     {
741                         /* Residue number is the atom number */
742                         atoms->atom[i].resind = i;
743                         /* Generate an residue name from the particle type */
744                         if (atoms->atom[i].type < 26)
745                         {
746                             sprintf(buf, "T%c", 'A'+atoms->atom[i].type);
747                         }
748                         else
749                         {
750                             sprintf(buf, "T%c%c",
751                                     'A'+atoms->atom[i].type/26, 'A'+atoms->atom[i].type%26);
752                         }
753                         t_atoms_set_resinfo(atoms, i, symtab, buf, i, ' ', 0, ' ');
754                     }
755
756                     if (r == 3)
757                     {
758                         level--;
759                     }
760                     i++;
761                 }
762             }
763             atoms->nres = atoms->nr;
764
765             if (i != atoms->nr)
766             {
767                 gmx_fatal(FARGS, "Internal inconsistency in Espresso routines, read %d atoms, expected %d atoms", i, atoms->nr);
768             }
769         }
770         else if (level == 1 && strcmp(word, "variable") == 0 && !bFoundVariable)
771         {
772             bFoundVariable = TRUE;
773             level         += check_open_parenthesis(fp, r, infile, "variable");
774             while (level == 2 && (r = get_espresso_word(fp, word)))
775             {
776                 if (level == 2 && strcmp(word, "box_l") == 0)
777                 {
778                     for (m = 0; m < 3; m++)
779                     {
780                         r = get_espresso_word(fp, word);
781                         sscanf(word, "%lf", &d);
782                         box[m][m] = d;
783                     }
784                     level += check_close_parenthesis(fp, r, infile, "box_l");
785                 }
786             }
787         }
788         else if (r == 2)
789         {
790             level++;
791         }
792         else if (r == 3)
793         {
794             level--;
795         }
796     }
797
798     if (!bFoundParticles)
799     {
800         fprintf(stderr, "Did not find a particles section in Espresso file '%s'\n",
801                 infile);
802     }
803
804     gmx_fio_fclose(fp);
805 }
806
807 static int get_espresso_coordnum(const char *infile)
808 {
809     FILE    *fp;
810     char     word[STRLEN];
811     int      natoms, level, r;
812     gmx_bool bFoundParticles;
813
814     natoms = 0;
815
816     fp = gmx_fio_fopen(infile, "r");
817
818     bFoundParticles = FALSE;
819     level           = 0;
820     while ((r = get_espresso_word(fp, word)) && !bFoundParticles)
821     {
822         if (level == 1 && strcmp(word, "particles") == 0 && !bFoundParticles)
823         {
824             bFoundParticles = TRUE;
825             level          += check_open_parenthesis(fp, r, infile, "particles");
826             while (level > 0 && (r = get_espresso_word(fp, word)))
827             {
828                 if (r == 2)
829                 {
830                     level++;
831                     if (level == 2)
832                     {
833                         natoms++;
834                     }
835                 }
836                 else if (r == 3)
837                 {
838                     level--;
839                 }
840             }
841         }
842         else if (r == 2)
843         {
844             level++;
845         }
846         else if (r == 3)
847         {
848             level--;
849         }
850     }
851     if (!bFoundParticles)
852     {
853         fprintf(stderr, "Did not find a particles section in Espresso file '%s'\n",
854                 infile);
855     }
856
857     gmx_fio_fclose(fp);
858
859     return natoms;
860 }
861
862 static void write_espresso_conf_indexed(FILE *out, const char *title,
863                                         t_atoms *atoms, int nx, atom_id *index,
864                                         rvec *x, rvec *v, matrix box)
865 {
866     int i, j;
867
868     fprintf(out, "# %s\n", title);
869     if (TRICLINIC(box))
870     {
871         gmx_warning("The Espresso format does not support triclinic unit-cells");
872     }
873     fprintf(out, "{variable {box_l %f %f %f}}\n", box[0][0], box[1][1], box[2][2]);
874
875     fprintf(out, "{particles {id pos type q%s}\n", v ? " v" : "");
876     for (i = 0; i < nx; i++)
877     {
878         if (index)
879         {
880             j = index[i];
881         }
882         else
883         {
884             j = i;
885         }
886         fprintf(out, "\t{%d %f %f %f %d %g",
887                 j, x[j][XX], x[j][YY], x[j][ZZ],
888                 atoms->atom[j].type, atoms->atom[j].q);
889         if (v)
890         {
891             fprintf(out, " %f %f %f", v[j][XX], v[j][YY], v[j][ZZ]);
892         }
893         fprintf(out, "}\n");
894     }
895     fprintf(out, "}\n");
896 }
897
898 static void get_coordnum_fp (FILE *in, char *title, int *natoms)
899 {
900     char line[STRLEN+1];
901
902     fgets2 (title, STRLEN, in);
903     fgets2 (line, STRLEN, in);
904     if (sscanf (line, "%d", natoms) != 1)
905     {
906         gmx_fatal(FARGS, "gro file does not have the number of atoms on the second line");
907     }
908 }
909
910 static void get_coordnum (const char *infile, int *natoms)
911 {
912     FILE *in;
913     char  title[STRLEN];
914
915     in = gmx_fio_fopen(infile, "r");
916     get_coordnum_fp(in, title, natoms);
917     gmx_fio_fclose (in);
918 }
919
920 static gmx_bool get_w_conf(FILE *in, const char *infile, char *title,
921                            t_symtab *symtab, t_atoms *atoms, int *ndec,
922                            rvec x[], rvec *v, matrix box)
923 {
924     char       name[6];
925     char       line[STRLEN+1], *ptr;
926     char       buf[256];
927     double     x1, y1, z1, x2, y2, z2;
928     rvec       xmin, xmax;
929     int        natoms, i, m, resnr, newres, oldres, ddist, c;
930     gmx_bool   bFirst, bVel;
931     char      *p1, *p2, *p3;
932
933     newres  = -1;
934     oldres  = NOTSET; /* Unlikely number for the first residue! */
935     ddist   = 0;
936
937     /* Read the title and number of atoms */
938     get_coordnum_fp(in, title, &natoms);
939
940     if (natoms > atoms->nr)
941     {
942         gmx_fatal(FARGS, "gro file contains more atoms (%d) than expected (%d)",
943                   natoms, atoms->nr);
944     }
945     else if (natoms <  atoms->nr)
946     {
947         fprintf(stderr, "Warning: gro file contains less atoms (%d) than expected"
948                 " (%d)\n", natoms, atoms->nr);
949     }
950
951     bFirst = TRUE;
952
953     bVel = FALSE;
954
955     /* just pray the arrays are big enough */
956     for (i = 0; (i < natoms); i++)
957     {
958         if ((fgets2 (line, STRLEN, in)) == NULL)
959         {
960             gmx_fatal(FARGS, "Unexpected end of file in file %s at line %d",
961                       infile, i+2);
962         }
963         if (strlen(line) < 39)
964         {
965             gmx_fatal(FARGS, "Invalid line in %s for atom %d:\n%s", infile, i+1, line);
966         }
967
968         /* determine read precision from distance between periods
969            (decimal points) */
970         if (bFirst)
971         {
972             bFirst = FALSE;
973             p1     = strchr(line, '.');
974             if (p1 == NULL)
975             {
976                 gmx_fatal(FARGS, "A coordinate in file %s does not contain a '.'", infile);
977             }
978             p2 = strchr(&p1[1], '.');
979             if (p2 == NULL)
980             {
981                 gmx_fatal(FARGS, "A coordinate in file %s does not contain a '.'", infile);
982             }
983             ddist = p2 - p1;
984             *ndec = ddist - 5;
985
986             p3 = strchr(&p2[1], '.');
987             if (p3 == NULL)
988             {
989                 gmx_fatal(FARGS, "A coordinate in file %s does not contain a '.'", infile);
990             }
991
992             if (p3 - p2 != ddist)
993             {
994                 gmx_fatal(FARGS, "The spacing of the decimal points in file %s is not consistent for x, y and z", infile);
995             }
996         }
997
998         /* residue number*/
999         memcpy(name, line, 5);
1000         name[5] = '\0';
1001         sscanf(name, "%d", &resnr);
1002         memcpy(name, line+5, 5);
1003         name[5] = '\0';
1004         if (resnr != oldres)
1005         {
1006             oldres = resnr;
1007             newres++;
1008             if (newres >= natoms)
1009             {
1010                 gmx_fatal(FARGS, "More residues than atoms in %s (natoms = %d)",
1011                           infile, natoms);
1012             }
1013             atoms->atom[i].resind = newres;
1014             t_atoms_set_resinfo(atoms, i, symtab, name, resnr, ' ', 0, ' ');
1015         }
1016         else
1017         {
1018             atoms->atom[i].resind = newres;
1019         }
1020
1021         /* atomname */
1022         memcpy(name, line+10, 5);
1023         atoms->atomname[i] = put_symtab(symtab, name);
1024
1025         /* eventueel controle atomnumber met i+1 */
1026
1027         /* coordinates (start after residue data) */
1028         ptr = line + 20;
1029         /* Read fixed format */
1030         for (m = 0; m < DIM; m++)
1031         {
1032             for (c = 0; (c < ddist && ptr[0]); c++)
1033             {
1034                 buf[c] = ptr[0];
1035                 ptr++;
1036             }
1037             buf[c] = '\0';
1038             if (sscanf (buf, "%lf %lf", &x1, &x2) != 1)
1039             {
1040                 gmx_fatal(FARGS, "Something is wrong in the coordinate formatting of file %s. Note that gro is fixed format (see the manual)", infile);
1041             }
1042             else
1043             {
1044                 x[i][m] = x1;
1045             }
1046         }
1047
1048         /* velocities (start after residues and coordinates) */
1049         if (v)
1050         {
1051             /* Read fixed format */
1052             for (m = 0; m < DIM; m++)
1053             {
1054                 for (c = 0; (c < ddist && ptr[0]); c++)
1055                 {
1056                     buf[c] = ptr[0];
1057                     ptr++;
1058                 }
1059                 buf[c] = '\0';
1060                 if (sscanf (buf, "%lf", &x1) != 1)
1061                 {
1062                     v[i][m] = 0;
1063                 }
1064                 else
1065                 {
1066                     v[i][m] = x1;
1067                     bVel    = TRUE;
1068                 }
1069             }
1070         }
1071     }
1072     atoms->nres = newres + 1;
1073
1074     /* box */
1075     fgets2 (line, STRLEN, in);
1076     if (sscanf (line, "%lf%lf%lf", &x1, &y1, &z1) != 3)
1077     {
1078         gmx_warning("Bad box in file %s", infile);
1079
1080         /* Generate a cubic box */
1081         for (m = 0; (m < DIM); m++)
1082         {
1083             xmin[m] = xmax[m] = x[0][m];
1084         }
1085         for (i = 1; (i < atoms->nr); i++)
1086         {
1087             for (m = 0; (m < DIM); m++)
1088             {
1089                 xmin[m] = min(xmin[m], x[i][m]);
1090                 xmax[m] = max(xmax[m], x[i][m]);
1091             }
1092         }
1093         for (i = 0; i < DIM; i++)
1094         {
1095             for (m = 0; m < DIM; m++)
1096             {
1097                 box[i][m] = 0.0;
1098             }
1099         }
1100         for (m = 0; (m < DIM); m++)
1101         {
1102             box[m][m] = (xmax[m]-xmin[m]);
1103         }
1104         fprintf(stderr, "Generated a cubic box %8.3f x %8.3f x %8.3f\n",
1105                 box[XX][XX], box[YY][YY], box[ZZ][ZZ]);
1106     }
1107     else
1108     {
1109         /* We found the first three values, the diagonal elements */
1110         box[XX][XX] = x1;
1111         box[YY][YY] = y1;
1112         box[ZZ][ZZ] = z1;
1113         if (sscanf (line, "%*f%*f%*f%lf%lf%lf%lf%lf%lf",
1114                     &x1, &y1, &z1, &x2, &y2, &z2) != 6)
1115         {
1116             x1 = y1 = z1 = x2 = y2 = z2 = 0.0;
1117         }
1118         box[XX][YY] = x1;
1119         box[XX][ZZ] = y1;
1120         box[YY][XX] = z1;
1121         box[YY][ZZ] = x2;
1122         box[ZZ][XX] = y2;
1123         box[ZZ][YY] = z2;
1124     }
1125
1126     return bVel;
1127 }
1128
1129 static void read_whole_conf(const char *infile, char *title,
1130                             t_atoms *atoms, rvec x[], rvec *v, matrix box)
1131 {
1132     FILE    *in;
1133     int      ndec;
1134     t_symtab symtab;
1135
1136     /* open file */
1137     in = gmx_fio_fopen(infile, "r");
1138
1139     open_symtab(&symtab);
1140     get_w_conf(in, infile, title, &symtab, atoms, &ndec, x, v, box);
1141     /* We can't free the symbols, as they are still used in atoms, so
1142      * the only choice is to leak them. */
1143     free_symtab(&symtab);
1144
1145     gmx_fio_fclose(in);
1146 }
1147
1148 gmx_bool gro_next_x_or_v(FILE *status, t_trxframe *fr)
1149 {
1150     t_atoms  atoms;
1151     t_symtab symtab;
1152     char     title[STRLEN], *p;
1153     double   tt;
1154     int      ndec = 0, i;
1155
1156     if (gmx_eof(status))
1157     {
1158         return FALSE;
1159     }
1160
1161     open_symtab(&symtab);
1162     atoms.nr = fr->natoms;
1163     snew(atoms.atom, fr->natoms);
1164     atoms.nres = fr->natoms;
1165     snew(atoms.resinfo, fr->natoms);
1166     snew(atoms.atomname, fr->natoms);
1167
1168     fr->bV    = get_w_conf(status, title, title, &symtab, &atoms, &ndec, fr->x, fr->v, fr->box);
1169     fr->bPrec = TRUE;
1170     fr->prec  = 1;
1171     /* prec = 10^ndec: */
1172     for (i = 0; i < ndec; i++)
1173     {
1174         fr->prec *= 10;
1175     }
1176     fr->title  = title;
1177     fr->bTitle = TRUE;
1178     fr->bX     = TRUE;
1179     fr->bBox   = TRUE;
1180
1181     sfree(atoms.atom);
1182     sfree(atoms.resinfo);
1183     sfree(atoms.atomname);
1184     done_symtab(&symtab);
1185
1186     if ((p = strstr(title, "t=")) != NULL)
1187     {
1188         p += 2;
1189         if (sscanf(p, "%lf", &tt) == 1)
1190         {
1191             fr->time  = tt;
1192             fr->bTime = TRUE;
1193         }
1194         else
1195         {
1196             fr->time  = 0;
1197             fr->bTime = FALSE;
1198         }
1199     }
1200
1201     if (atoms.nr != fr->natoms)
1202     {
1203         gmx_fatal(FARGS, "Number of atoms in gro frame (%d) doesn't match the number in the previous frame (%d)", atoms.nr, fr->natoms);
1204     }
1205
1206     return TRUE;
1207 }
1208
1209 int gro_first_x_or_v(FILE *status, t_trxframe *fr)
1210 {
1211     char title[STRLEN];
1212
1213     frewind(status);
1214     fprintf(stderr, "Reading frames from gro file");
1215     get_coordnum_fp(status, title, &fr->natoms);
1216     frewind(status);
1217     fprintf(stderr, " '%s', %d atoms.\n", title, fr->natoms);
1218     fr->bTitle = TRUE;
1219     fr->title  = title;
1220     if (fr->natoms == 0)
1221     {
1222         gmx_file("No coordinates in gro file");
1223     }
1224
1225     snew(fr->x, fr->natoms);
1226     snew(fr->v, fr->natoms);
1227     gro_next_x_or_v(status, fr);
1228
1229     return fr->natoms;
1230 }
1231
1232 static void make_hconf_format(int pr, gmx_bool bVel, char format[])
1233 {
1234     int l, vpr;
1235
1236     /* build format string for printing,
1237        something like "%8.3f" for x and "%8.4f" for v */
1238     if (pr < 0)
1239     {
1240         pr = 0;
1241     }
1242     if (pr > 30)
1243     {
1244         pr = 30;
1245     }
1246     l   = pr+5;
1247     vpr = pr+1;
1248     if (bVel)
1249     {
1250         sprintf(format, "%%%d.%df%%%d.%df%%%d.%df%%%d.%df%%%d.%df%%%d.%df\n",
1251                 l, pr, l, pr, l, pr, l, vpr, l, vpr, l, vpr);
1252     }
1253     else
1254     {
1255         sprintf(format, "%%%d.%df%%%d.%df%%%d.%df\n", l, pr, l, pr, l, pr);
1256     }
1257
1258 }
1259
1260 static void write_hconf_box(FILE *out, int pr, matrix box)
1261 {
1262     char format[100];
1263     int  l;
1264
1265     if (pr < 5)
1266     {
1267         pr = 5;
1268     }
1269     l = pr+5;
1270
1271     if (box[XX][YY] || box[XX][ZZ] || box[YY][XX] || box[YY][ZZ] ||
1272         box[ZZ][XX] || box[ZZ][YY])
1273     {
1274         sprintf(format, "%%%d.%df%%%d.%df%%%d.%df"
1275                 "%%%d.%df%%%d.%df%%%d.%df%%%d.%df%%%d.%df%%%d.%df\n",
1276                 l, pr, l, pr, l, pr, l, pr, l, pr, l, pr, l, pr, l, pr, l, pr);
1277         fprintf(out, format,
1278                 box[XX][XX], box[YY][YY], box[ZZ][ZZ],
1279                 box[XX][YY], box[XX][ZZ], box[YY][XX],
1280                 box[YY][ZZ], box[ZZ][XX], box[ZZ][YY]);
1281     }
1282     else
1283     {
1284         sprintf(format, "%%%d.%df%%%d.%df%%%d.%df\n", l, pr, l, pr, l, pr);
1285         fprintf(out, format,
1286                 box[XX][XX], box[YY][YY], box[ZZ][ZZ]);
1287     }
1288 }
1289
1290 void write_hconf_indexed_p(FILE *out, const char *title, t_atoms *atoms,
1291                            int nx, const atom_id index[], int pr,
1292                            rvec *x, rvec *v, matrix box)
1293 {
1294     char resnm[6], nm[6], format[100];
1295     int  ai, i, resind, resnr;
1296
1297     bromacs(format, 99);
1298     fprintf (out, "%s\n", (title && title[0]) ? title : format);
1299     fprintf (out, "%5d\n", nx);
1300
1301     make_hconf_format(pr, v != NULL, format);
1302
1303     for (i = 0; (i < nx); i++)
1304     {
1305         ai = index[i];
1306
1307         resind = atoms->atom[ai].resind;
1308         strncpy(resnm, " ??? ", sizeof(resnm)-1);
1309         if (resind < atoms->nres)
1310         {
1311             strncpy(resnm, *atoms->resinfo[resind].name, sizeof(resnm)-1);
1312             resnr = atoms->resinfo[resind].nr;
1313         }
1314         else
1315         {
1316             strncpy(resnm, " ??? ", sizeof(resnm)-1);
1317             resnr = resind + 1;
1318         }
1319
1320         if (atoms->atom)
1321         {
1322             strncpy(nm, *atoms->atomname[ai], sizeof(nm)-1);
1323         }
1324         else
1325         {
1326             strncpy(nm, " ??? ", sizeof(nm)-1);
1327         }
1328
1329         fprintf(out, "%5d%-5.5s%5.5s%5d", resnr%100000, resnm, nm, (ai+1)%100000);
1330         /* next fprintf uses built format string */
1331         if (v)
1332         {
1333             fprintf(out, format,
1334                     x[ai][XX], x[ai][YY], x[ai][ZZ], v[ai][XX], v[ai][YY], v[ai][ZZ]);
1335         }
1336         else
1337         {
1338             fprintf(out, format,
1339                     x[ai][XX], x[ai][YY], x[ai][ZZ]);
1340         }
1341     }
1342
1343     write_hconf_box(out, pr, box);
1344
1345     fflush(out);
1346 }
1347
1348 static void write_hconf_mtop(FILE *out, const char *title, gmx_mtop_t *mtop,
1349                              int pr,
1350                              rvec *x, rvec *v, matrix box)
1351 {
1352     char                    format[100];
1353     int                     i, resnr;
1354     gmx_mtop_atomloop_all_t aloop;
1355     t_atom                 *atom;
1356     char                   *atomname, *resname;
1357
1358     bromacs(format, 99);
1359     fprintf (out, "%s\n", (title && title[0]) ? title : format);
1360     fprintf (out, "%5d\n", mtop->natoms);
1361
1362     make_hconf_format(pr, v != NULL, format);
1363
1364     aloop = gmx_mtop_atomloop_all_init(mtop);
1365     while (gmx_mtop_atomloop_all_next(aloop, &i, &atom))
1366     {
1367         gmx_mtop_atomloop_all_names(aloop, &atomname, &resnr, &resname);
1368
1369         fprintf(out, "%5d%-5.5s%5.5s%5d",
1370                 resnr%100000, resname, atomname, (i+1)%100000);
1371         /* next fprintf uses built format string */
1372         if (v)
1373         {
1374             fprintf(out, format,
1375                     x[i][XX], x[i][YY], x[i][ZZ], v[i][XX], v[i][YY], v[i][ZZ]);
1376         }
1377         else
1378         {
1379             fprintf(out, format,
1380                     x[i][XX], x[i][YY], x[i][ZZ]);
1381         }
1382     }
1383
1384     write_hconf_box(out, pr, box);
1385
1386     fflush(out);
1387 }
1388
1389 void write_hconf_p(FILE *out, const char *title, t_atoms *atoms, int pr,
1390                    rvec *x, rvec *v, matrix box)
1391 {
1392     atom_id *aa;
1393     int      i;
1394
1395     snew(aa, atoms->nr);
1396     for (i = 0; (i < atoms->nr); i++)
1397     {
1398         aa[i] = i;
1399     }
1400     write_hconf_indexed_p(out, title, atoms, atoms->nr, aa, pr, x, v, box);
1401     sfree(aa);
1402 }
1403
1404 void write_conf_p(const char *outfile, const char *title,
1405                   t_atoms *atoms, int pr,
1406                   rvec *x, rvec *v, matrix box)
1407 {
1408     FILE *out;
1409
1410     out = gmx_fio_fopen(outfile, "w");
1411     write_hconf_p(out, title, atoms, pr, x, v, box);
1412
1413     gmx_fio_fclose (out);
1414 }
1415
1416 static void write_conf(const char *outfile, const char *title, t_atoms *atoms,
1417                        rvec *x, rvec *v, matrix box)
1418 {
1419     write_conf_p(outfile, title, atoms, 3, x, v, box);
1420 }
1421
1422 void write_sto_conf_indexed(const char *outfile, const char *title,
1423                             t_atoms *atoms,
1424                             rvec x[], rvec *v, int ePBC, matrix box,
1425                             atom_id nindex, atom_id index[])
1426 {
1427     FILE       *out;
1428     int         ftp;
1429     t_trxframe  fr;
1430
1431     ftp = fn2ftp(outfile);
1432     switch (ftp)
1433     {
1434         case efGRO:
1435             out = gmx_fio_fopen(outfile, "w");
1436             write_hconf_indexed_p(out, title, atoms, nindex, index, 3, x, v, box);
1437             gmx_fio_fclose(out);
1438             break;
1439         case efG96:
1440             clear_trxframe(&fr, TRUE);
1441             fr.bTitle = TRUE;
1442             fr.title  = title;
1443             fr.natoms = atoms->nr;
1444             fr.bAtoms = TRUE;
1445             fr.atoms  = atoms;
1446             fr.bX     = TRUE;
1447             fr.x      = x;
1448             if (v)
1449             {
1450                 fr.bV = TRUE;
1451                 fr.v  = v;
1452             }
1453             fr.bBox = TRUE;
1454             copy_mat(box, fr.box);
1455             out = gmx_fio_fopen(outfile, "w");
1456             write_g96_conf(out, &fr, nindex, index);
1457             gmx_fio_fclose(out);
1458             break;
1459         case efPDB:
1460         case efBRK:
1461         case efENT:
1462         case efPQR:
1463             out = gmx_fio_fopen(outfile, "w");
1464             write_pdbfile_indexed(out, title, atoms, x, ePBC, box, ' ', -1, nindex, index, NULL, TRUE);
1465             gmx_fio_fclose(out);
1466             break;
1467         case efESP:
1468             out = gmx_fio_fopen(outfile, "w");
1469             write_espresso_conf_indexed(out, title, atoms, nindex, index, x, v, box);
1470             gmx_fio_fclose(out);
1471             break;
1472         case efTPR:
1473         case efTPB:
1474         case efTPA:
1475             gmx_fatal(FARGS, "Sorry, can not write a topology to %s", outfile);
1476             break;
1477         default:
1478             gmx_incons("Not supported in write_sto_conf_indexed");
1479     }
1480 }
1481
1482 void write_sto_conf(const char *outfile, const char *title, t_atoms *atoms,
1483                     rvec x[], rvec *v, int ePBC, matrix box)
1484 {
1485     FILE       *out;
1486     int         ftp;
1487     t_trxframe  fr;
1488
1489     ftp = fn2ftp(outfile);
1490     switch (ftp)
1491     {
1492         case efGRO:
1493             write_conf(outfile, title, atoms, x, v, box);
1494             break;
1495         case efG96:
1496             clear_trxframe(&fr, TRUE);
1497             fr.bTitle = TRUE;
1498             fr.title  = title;
1499             fr.natoms = atoms->nr;
1500             fr.bAtoms = TRUE;
1501             fr.atoms  = atoms;
1502             fr.bX     = TRUE;
1503             fr.x      = x;
1504             if (v)
1505             {
1506                 fr.bV = TRUE;
1507                 fr.v  = v;
1508             }
1509             fr.bBox = TRUE;
1510             copy_mat(box, fr.box);
1511             out = gmx_fio_fopen(outfile, "w");
1512             write_g96_conf(out, &fr, -1, NULL);
1513             gmx_fio_fclose(out);
1514             break;
1515         case efPDB:
1516         case efBRK:
1517         case efENT:
1518             out = gmx_fio_fopen(outfile, "w");
1519             write_pdbfile(out, title, atoms, x, ePBC, box, ' ', -1, NULL, TRUE);
1520             gmx_fio_fclose(out);
1521             break;
1522         case efESP:
1523             out = gmx_fio_fopen(outfile, "w");
1524             write_espresso_conf_indexed(out, title, atoms, atoms->nr, NULL, x, v, box);
1525             gmx_fio_fclose(out);
1526             break;
1527         case efTPR:
1528         case efTPB:
1529         case efTPA:
1530             gmx_fatal(FARGS, "Sorry, can not write a topology to %s", outfile);
1531             break;
1532         default:
1533             gmx_incons("Not supported in write_sto_conf");
1534     }
1535 }
1536
1537 void write_sto_conf_mtop(const char *outfile, const char *title,
1538                          gmx_mtop_t *mtop,
1539                          rvec x[], rvec *v, int ePBC, matrix box)
1540 {
1541     int     ftp;
1542     FILE   *out;
1543     t_atoms atoms;
1544
1545     ftp = fn2ftp(outfile);
1546     switch (ftp)
1547     {
1548         case efGRO:
1549             out = gmx_fio_fopen(outfile, "w");
1550             write_hconf_mtop(out, title, mtop, 3, x, v, box);
1551             gmx_fio_fclose(out);
1552             break;
1553         default:
1554             /* This is a brute force approach which requires a lot of memory.
1555              * We should implement mtop versions of all writing routines.
1556              */
1557             atoms = gmx_mtop_global_atoms(mtop);
1558
1559             write_sto_conf(outfile, title, &atoms, x, v, ePBC, box);
1560
1561             done_atom(&atoms);
1562             break;
1563     }
1564 }
1565
1566 void get_stx_coordnum(const char *infile, int *natoms)
1567 {
1568     FILE      *in;
1569     int        ftp, tpxver, tpxgen;
1570     t_trxframe fr;
1571     char       g96_line[STRLEN+1];
1572
1573     ftp = fn2ftp(infile);
1574     range_check(ftp, 0, efNR);
1575     switch (ftp)
1576     {
1577         case efGRO:
1578             get_coordnum(infile, natoms);
1579             break;
1580         case efG96:
1581             in        = gmx_fio_fopen(infile, "r");
1582             fr.title  = NULL;
1583             fr.natoms = -1;
1584             fr.atoms  = NULL;
1585             fr.x      = NULL;
1586             fr.v      = NULL;
1587             fr.f      = NULL;
1588             *natoms   = read_g96_conf(in, infile, &fr, g96_line);
1589             gmx_fio_fclose(in);
1590             break;
1591         case efPDB:
1592         case efBRK:
1593         case efENT:
1594             in = gmx_fio_fopen(infile, "r");
1595             get_pdb_coordnum(in, natoms);
1596             gmx_fio_fclose(in);
1597             break;
1598         case efESP:
1599             *natoms = get_espresso_coordnum(infile);
1600             break;
1601         case efTPA:
1602         case efTPB:
1603         case efTPR:
1604         {
1605             t_tpxheader tpx;
1606
1607             read_tpxheader(infile, &tpx, TRUE, &tpxver, &tpxgen);
1608             *natoms = tpx.natoms;
1609             break;
1610         }
1611         default:
1612             gmx_fatal(FARGS, "File type %s not supported in get_stx_coordnum",
1613                       ftp2ext(ftp));
1614     }
1615 }
1616
1617 void read_stx_conf(const char *infile, char *title, t_atoms *atoms,
1618                    rvec x[], rvec *v, int *ePBC, matrix box)
1619 {
1620     FILE       *in;
1621     char        buf[256];
1622     gmx_mtop_t *mtop;
1623     t_topology  top;
1624     t_trxframe  fr;
1625     int         i, ftp, natoms;
1626     real        d;
1627     char        g96_line[STRLEN+1];
1628
1629     if (atoms->nr == 0)
1630     {
1631         fprintf(stderr, "Warning: Number of atoms in %s is 0\n", infile);
1632     }
1633     else if (atoms->atom == NULL)
1634     {
1635         gmx_mem("Uninitialized array atom");
1636     }
1637
1638     if (ePBC)
1639     {
1640         *ePBC = -1;
1641     }
1642
1643     ftp = fn2ftp(infile);
1644     switch (ftp)
1645     {
1646         case efGRO:
1647             read_whole_conf(infile, title, atoms, x, v, box);
1648             break;
1649         case efG96:
1650             fr.title  = NULL;
1651             fr.natoms = atoms->nr;
1652             fr.atoms  = atoms;
1653             fr.x      = x;
1654             fr.v      = v;
1655             fr.f      = NULL;
1656             in        = gmx_fio_fopen(infile, "r");
1657             read_g96_conf(in, infile, &fr, g96_line);
1658             gmx_fio_fclose(in);
1659             copy_mat(fr.box, box);
1660             strncpy(title, fr.title, STRLEN);
1661             break;
1662         case efPDB:
1663         case efBRK:
1664         case efENT:
1665             read_pdb_conf(infile, title, atoms, x, ePBC, box, TRUE, NULL);
1666             break;
1667         case efESP:
1668             read_espresso_conf(infile, atoms, x, v, box);
1669             break;
1670         case efTPR:
1671         case efTPB:
1672         case efTPA:
1673             snew(mtop, 1);
1674             i = read_tpx(infile, NULL, box, &natoms, x, v, NULL, mtop);
1675             if (ePBC)
1676             {
1677                 *ePBC = i;
1678             }
1679
1680             strcpy(title, *(mtop->name));
1681
1682             /* Free possibly allocated memory */
1683             done_atom(atoms);
1684
1685             *atoms = gmx_mtop_global_atoms(mtop);
1686             top    = gmx_mtop_t_to_t_topology(mtop);
1687             tpx_make_chain_identifiers(atoms, &top.mols);
1688
1689             sfree(mtop);
1690             /* The strings in the symtab are still in use in the returned t_atoms
1691              * structure, so we should not free them. But there is no place to put the
1692              * symbols; the only choice is to leak the memory...
1693              * So we clear the symbol table before freeing the topology structure. */
1694             free_symtab(&top.symtab);
1695             done_top(&top);
1696
1697             break;
1698         default:
1699             gmx_incons("Not supported in read_stx_conf");
1700     }
1701 }