Merge branch 'release-4-6'
[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, 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 "smalloc.h"
45 #include "sysstuff.h"
46 #include <errno.h>
47 #include "macros.h"
48 #include "string2.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             unexpected_eof(infile, i+2);
961         }
962         if (strlen(line) < 39)
963         {
964             gmx_fatal(FARGS, "Invalid line in %s for atom %d:\n%s", infile, i+1, line);
965         }
966
967         /* determine read precision from distance between periods
968            (decimal points) */
969         if (bFirst)
970         {
971             bFirst = FALSE;
972             p1     = strchr(line, '.');
973             if (p1 == NULL)
974             {
975                 gmx_fatal(FARGS, "A coordinate in file %s does not contain a '.'", infile);
976             }
977             p2 = strchr(&p1[1], '.');
978             if (p2 == NULL)
979             {
980                 gmx_fatal(FARGS, "A coordinate in file %s does not contain a '.'", infile);
981             }
982             ddist = p2 - p1;
983             *ndec = ddist - 5;
984
985             p3 = strchr(&p2[1], '.');
986             if (p3 == NULL)
987             {
988                 gmx_fatal(FARGS, "A coordinate in file %s does not contain a '.'", infile);
989             }
990
991             if (p3 - p2 != ddist)
992             {
993                 gmx_fatal(FARGS, "The spacing of the decimal points in file %s is not consistent for x, y and z", infile);
994             }
995         }
996
997         /* residue number*/
998         memcpy(name, line, 5);
999         name[5] = '\0';
1000         sscanf(name, "%d", &resnr);
1001         memcpy(name, line+5, 5);
1002         name[5] = '\0';
1003         if (resnr != oldres)
1004         {
1005             oldres = resnr;
1006             newres++;
1007             if (newres >= natoms)
1008             {
1009                 gmx_fatal(FARGS, "More residues than atoms in %s (natoms = %d)",
1010                           infile, natoms);
1011             }
1012             atoms->atom[i].resind = newres;
1013             t_atoms_set_resinfo(atoms, i, symtab, name, resnr, ' ', 0, ' ');
1014         }
1015         else
1016         {
1017             atoms->atom[i].resind = newres;
1018         }
1019
1020         /* atomname */
1021         memcpy(name, line+10, 5);
1022         atoms->atomname[i] = put_symtab(symtab, name);
1023
1024         /* eventueel controle atomnumber met i+1 */
1025
1026         /* coordinates (start after residue shit) */
1027         ptr = line + 20;
1028         /* Read fixed format */
1029         for (m = 0; m < DIM; m++)
1030         {
1031             for (c = 0; (c < ddist && ptr[0]); c++)
1032             {
1033                 buf[c] = ptr[0];
1034                 ptr++;
1035             }
1036             buf[c] = '\0';
1037             if (sscanf (buf, "%lf %lf", &x1, &x2) != 1)
1038             {
1039                 gmx_fatal(FARGS, "Something is wrong in the coordinate formatting of file %s. Note that gro is fixed format (see the manual)", infile);
1040             }
1041             else
1042             {
1043                 x[i][m] = x1;
1044             }
1045         }
1046
1047         /* velocities (start after residues and coordinates) */
1048         if (v)
1049         {
1050             /* Read fixed format */
1051             for (m = 0; m < DIM; m++)
1052             {
1053                 for (c = 0; (c < ddist && ptr[0]); c++)
1054                 {
1055                     buf[c] = ptr[0];
1056                     ptr++;
1057                 }
1058                 buf[c] = '\0';
1059                 if (sscanf (buf, "%lf", &x1) != 1)
1060                 {
1061                     v[i][m] = 0;
1062                 }
1063                 else
1064                 {
1065                     v[i][m] = x1;
1066                     bVel    = TRUE;
1067                 }
1068             }
1069         }
1070     }
1071     atoms->nres = newres + 1;
1072
1073     /* box */
1074     fgets2 (line, STRLEN, in);
1075     if (sscanf (line, "%lf%lf%lf", &x1, &y1, &z1) != 3)
1076     {
1077         gmx_warning("Bad box in file %s", infile);
1078
1079         /* Generate a cubic box */
1080         for (m = 0; (m < DIM); m++)
1081         {
1082             xmin[m] = xmax[m] = x[0][m];
1083         }
1084         for (i = 1; (i < atoms->nr); i++)
1085         {
1086             for (m = 0; (m < DIM); m++)
1087             {
1088                 xmin[m] = min(xmin[m], x[i][m]);
1089                 xmax[m] = max(xmax[m], x[i][m]);
1090             }
1091         }
1092         for (i = 0; i < DIM; i++)
1093         {
1094             for (m = 0; m < DIM; m++)
1095             {
1096                 box[i][m] = 0.0;
1097             }
1098         }
1099         for (m = 0; (m < DIM); m++)
1100         {
1101             box[m][m] = (xmax[m]-xmin[m]);
1102         }
1103         fprintf(stderr, "Generated a cubic box %8.3f x %8.3f x %8.3f\n",
1104                 box[XX][XX], box[YY][YY], box[ZZ][ZZ]);
1105     }
1106     else
1107     {
1108         /* We found the first three values, the diagonal elements */
1109         box[XX][XX] = x1;
1110         box[YY][YY] = y1;
1111         box[ZZ][ZZ] = z1;
1112         if (sscanf (line, "%*f%*f%*f%lf%lf%lf%lf%lf%lf",
1113                     &x1, &y1, &z1, &x2, &y2, &z2) != 6)
1114         {
1115             x1 = y1 = z1 = x2 = y2 = z2 = 0.0;
1116         }
1117         box[XX][YY] = x1;
1118         box[XX][ZZ] = y1;
1119         box[YY][XX] = z1;
1120         box[YY][ZZ] = x2;
1121         box[ZZ][XX] = y2;
1122         box[ZZ][YY] = z2;
1123     }
1124
1125     return bVel;
1126 }
1127
1128 static void read_whole_conf(const char *infile, char *title,
1129                             t_atoms *atoms, rvec x[], rvec *v, matrix box)
1130 {
1131     FILE    *in;
1132     int      ndec;
1133     t_symtab symtab;
1134
1135     /* open file */
1136     in = gmx_fio_fopen(infile, "r");
1137
1138     open_symtab(&symtab);
1139     get_w_conf(in, infile, title, &symtab, atoms, &ndec, x, v, box);
1140     /* We can't free the symbols, as they are still used in atoms, so
1141      * the only choice is to leak them. */
1142     free_symtab(&symtab);
1143
1144     gmx_fio_fclose(in);
1145 }
1146
1147 gmx_bool gro_next_x_or_v(FILE *status, t_trxframe *fr)
1148 {
1149     t_atoms  atoms;
1150     t_symtab symtab;
1151     char     title[STRLEN], *p;
1152     double   tt;
1153     int      ndec = 0, i;
1154
1155     if (gmx_eof(status))
1156     {
1157         return FALSE;
1158     }
1159
1160     open_symtab(&symtab);
1161     atoms.nr = fr->natoms;
1162     snew(atoms.atom, fr->natoms);
1163     atoms.nres = fr->natoms;
1164     snew(atoms.resinfo, fr->natoms);
1165     snew(atoms.atomname, fr->natoms);
1166
1167     fr->bV    = get_w_conf(status, title, title, &symtab, &atoms, &ndec, fr->x, fr->v, fr->box);
1168     fr->bPrec = TRUE;
1169     fr->prec  = 1;
1170     /* prec = 10^ndec: */
1171     for (i = 0; i < ndec; i++)
1172     {
1173         fr->prec *= 10;
1174     }
1175     fr->title  = title;
1176     fr->bTitle = TRUE;
1177     fr->bX     = TRUE;
1178     fr->bBox   = TRUE;
1179
1180     sfree(atoms.atom);
1181     sfree(atoms.resinfo);
1182     sfree(atoms.atomname);
1183     done_symtab(&symtab);
1184
1185     if ((p = strstr(title, "t=")) != NULL)
1186     {
1187         p += 2;
1188         if (sscanf(p, "%lf", &tt) == 1)
1189         {
1190             fr->time  = tt;
1191             fr->bTime = TRUE;
1192         }
1193         else
1194         {
1195             fr->time  = 0;
1196             fr->bTime = FALSE;
1197         }
1198     }
1199
1200     if (atoms.nr != fr->natoms)
1201     {
1202         gmx_fatal(FARGS, "Number of atoms in gro frame (%d) doesn't match the number in the previous frame (%d)", atoms.nr, fr->natoms);
1203     }
1204
1205     return TRUE;
1206 }
1207
1208 int gro_first_x_or_v(FILE *status, t_trxframe *fr)
1209 {
1210     char title[STRLEN];
1211
1212     frewind(status);
1213     fprintf(stderr, "Reading frames from gro file");
1214     get_coordnum_fp(status, title, &fr->natoms);
1215     frewind(status);
1216     fprintf(stderr, " '%s', %d atoms.\n", title, fr->natoms);
1217     fr->bTitle = TRUE;
1218     fr->title  = title;
1219     if (fr->natoms == 0)
1220     {
1221         gmx_file("No coordinates in gro file");
1222     }
1223
1224     snew(fr->x, fr->natoms);
1225     snew(fr->v, fr->natoms);
1226     gro_next_x_or_v(status, fr);
1227
1228     return fr->natoms;
1229 }
1230
1231 static void make_hconf_format(int pr, gmx_bool bVel, char format[])
1232 {
1233     int l, vpr;
1234
1235     /* build format string for printing,
1236        something like "%8.3f" for x and "%8.4f" for v */
1237     if (pr < 0)
1238     {
1239         pr = 0;
1240     }
1241     if (pr > 30)
1242     {
1243         pr = 30;
1244     }
1245     l   = pr+5;
1246     vpr = pr+1;
1247     if (bVel)
1248     {
1249         sprintf(format, "%%%d.%df%%%d.%df%%%d.%df%%%d.%df%%%d.%df%%%d.%df\n",
1250                 l, pr, l, pr, l, pr, l, vpr, l, vpr, l, vpr);
1251     }
1252     else
1253     {
1254         sprintf(format, "%%%d.%df%%%d.%df%%%d.%df\n", l, pr, l, pr, l, pr);
1255     }
1256
1257 }
1258
1259 static void write_hconf_box(FILE *out, int pr, matrix box)
1260 {
1261     char format[100];
1262     int  l;
1263
1264     if (pr < 5)
1265     {
1266         pr = 5;
1267     }
1268     l = pr+5;
1269
1270     if (box[XX][YY] || box[XX][ZZ] || box[YY][XX] || box[YY][ZZ] ||
1271         box[ZZ][XX] || box[ZZ][YY])
1272     {
1273         sprintf(format, "%%%d.%df%%%d.%df%%%d.%df"
1274                 "%%%d.%df%%%d.%df%%%d.%df%%%d.%df%%%d.%df%%%d.%df\n",
1275                 l, pr, l, pr, l, pr, l, pr, l, pr, l, pr, l, pr, l, pr, l, pr);
1276         fprintf(out, format,
1277                 box[XX][XX], box[YY][YY], box[ZZ][ZZ],
1278                 box[XX][YY], box[XX][ZZ], box[YY][XX],
1279                 box[YY][ZZ], box[ZZ][XX], box[ZZ][YY]);
1280     }
1281     else
1282     {
1283         sprintf(format, "%%%d.%df%%%d.%df%%%d.%df\n", l, pr, l, pr, l, pr);
1284         fprintf(out, format,
1285                 box[XX][XX], box[YY][YY], box[ZZ][ZZ]);
1286     }
1287 }
1288
1289 void write_hconf_indexed_p(FILE *out, const char *title, t_atoms *atoms,
1290                            int nx, const atom_id index[], int pr,
1291                            rvec *x, rvec *v, matrix box)
1292 {
1293     char resnm[6], nm[6], format[100];
1294     int  ai, i, resind, resnr;
1295
1296     bromacs(format, 99);
1297     fprintf (out, "%s\n", (title && title[0]) ? title : format);
1298     fprintf (out, "%5d\n", nx);
1299
1300     make_hconf_format(pr, v != NULL, format);
1301
1302     for (i = 0; (i < nx); i++)
1303     {
1304         ai = index[i];
1305
1306         resind = atoms->atom[ai].resind;
1307         strncpy(resnm, " ??? ", sizeof(resnm)-1);
1308         if (resind < atoms->nres)
1309         {
1310             strncpy(resnm, *atoms->resinfo[resind].name, sizeof(resnm)-1);
1311             resnr = atoms->resinfo[resind].nr;
1312         }
1313         else
1314         {
1315             strncpy(resnm, " ??? ", sizeof(resnm)-1);
1316             resnr = resind + 1;
1317         }
1318
1319         if (atoms->atom)
1320         {
1321             strncpy(nm, *atoms->atomname[ai], sizeof(nm)-1);
1322         }
1323         else
1324         {
1325             strncpy(nm, " ??? ", sizeof(nm)-1);
1326         }
1327
1328         fprintf(out, "%5d%-5.5s%5.5s%5d", resnr%100000, resnm, nm, (ai+1)%100000);
1329         /* next fprintf uses built format string */
1330         if (v)
1331         {
1332             fprintf(out, format,
1333                     x[ai][XX], x[ai][YY], x[ai][ZZ], v[ai][XX], v[ai][YY], v[ai][ZZ]);
1334         }
1335         else
1336         {
1337             fprintf(out, format,
1338                     x[ai][XX], x[ai][YY], x[ai][ZZ]);
1339         }
1340     }
1341
1342     write_hconf_box(out, pr, box);
1343
1344     fflush(out);
1345 }
1346
1347 static void write_hconf_mtop(FILE *out, const char *title, gmx_mtop_t *mtop,
1348                              int pr,
1349                              rvec *x, rvec *v, matrix box)
1350 {
1351     char                    format[100];
1352     int                     i, resnr;
1353     gmx_mtop_atomloop_all_t aloop;
1354     t_atom                 *atom;
1355     char                   *atomname, *resname;
1356
1357     bromacs(format, 99);
1358     fprintf (out, "%s\n", (title && title[0]) ? title : format);
1359     fprintf (out, "%5d\n", mtop->natoms);
1360
1361     make_hconf_format(pr, v != NULL, format);
1362
1363     aloop = gmx_mtop_atomloop_all_init(mtop);
1364     while (gmx_mtop_atomloop_all_next(aloop, &i, &atom))
1365     {
1366         gmx_mtop_atomloop_all_names(aloop, &atomname, &resnr, &resname);
1367
1368         fprintf(out, "%5d%-5.5s%5.5s%5d",
1369                 resnr%100000, resname, atomname, (i+1)%100000);
1370         /* next fprintf uses built format string */
1371         if (v)
1372         {
1373             fprintf(out, format,
1374                     x[i][XX], x[i][YY], x[i][ZZ], v[i][XX], v[i][YY], v[i][ZZ]);
1375         }
1376         else
1377         {
1378             fprintf(out, format,
1379                     x[i][XX], x[i][YY], x[i][ZZ]);
1380         }
1381     }
1382
1383     write_hconf_box(out, pr, box);
1384
1385     fflush(out);
1386 }
1387
1388 void write_hconf_p(FILE *out, const char *title, t_atoms *atoms, int pr,
1389                    rvec *x, rvec *v, matrix box)
1390 {
1391     atom_id *aa;
1392     int      i;
1393
1394     snew(aa, atoms->nr);
1395     for (i = 0; (i < atoms->nr); i++)
1396     {
1397         aa[i] = i;
1398     }
1399     write_hconf_indexed_p(out, title, atoms, atoms->nr, aa, pr, x, v, box);
1400     sfree(aa);
1401 }
1402
1403 void write_conf_p(const char *outfile, const char *title,
1404                   t_atoms *atoms, int pr,
1405                   rvec *x, rvec *v, matrix box)
1406 {
1407     FILE *out;
1408
1409     out = gmx_fio_fopen(outfile, "w");
1410     write_hconf_p(out, title, atoms, pr, x, v, box);
1411
1412     gmx_fio_fclose (out);
1413 }
1414
1415 static void write_conf(const char *outfile, const char *title, t_atoms *atoms,
1416                        rvec *x, rvec *v, matrix box)
1417 {
1418     write_conf_p(outfile, title, atoms, 3, x, v, box);
1419 }
1420
1421 void write_sto_conf_indexed(const char *outfile, const char *title,
1422                             t_atoms *atoms,
1423                             rvec x[], rvec *v, int ePBC, matrix box,
1424                             atom_id nindex, atom_id index[])
1425 {
1426     FILE       *out;
1427     int         ftp;
1428     t_trxframe  fr;
1429
1430     ftp = fn2ftp(outfile);
1431     switch (ftp)
1432     {
1433         case efGRO:
1434             out = gmx_fio_fopen(outfile, "w");
1435             write_hconf_indexed_p(out, title, atoms, nindex, index, 3, x, v, box);
1436             gmx_fio_fclose(out);
1437             break;
1438         case efG96:
1439             clear_trxframe(&fr, TRUE);
1440             fr.bTitle = TRUE;
1441             fr.title  = title;
1442             fr.natoms = atoms->nr;
1443             fr.bAtoms = TRUE;
1444             fr.atoms  = atoms;
1445             fr.bX     = TRUE;
1446             fr.x      = x;
1447             if (v)
1448             {
1449                 fr.bV = TRUE;
1450                 fr.v  = v;
1451             }
1452             fr.bBox = TRUE;
1453             copy_mat(box, fr.box);
1454             out = gmx_fio_fopen(outfile, "w");
1455             write_g96_conf(out, &fr, nindex, index);
1456             gmx_fio_fclose(out);
1457             break;
1458         case efPDB:
1459         case efBRK:
1460         case efENT:
1461         case efPQR:
1462             out = gmx_fio_fopen(outfile, "w");
1463             write_pdbfile_indexed(out, title, atoms, x, ePBC, box, ' ', -1, nindex, index, NULL, TRUE);
1464             gmx_fio_fclose(out);
1465             break;
1466         case efESP:
1467             out = gmx_fio_fopen(outfile, "w");
1468             write_espresso_conf_indexed(out, title, atoms, nindex, index, x, v, box);
1469             gmx_fio_fclose(out);
1470             break;
1471         case efTPR:
1472         case efTPB:
1473         case efTPA:
1474             gmx_fatal(FARGS, "Sorry, can not write a topology to %s", outfile);
1475             break;
1476         default:
1477             gmx_incons("Not supported in write_sto_conf_indexed");
1478     }
1479 }
1480
1481 static void write_xyz_conf(const char *outfile, const char *title,
1482                            t_atoms *atoms, rvec *x)
1483 {
1484     FILE          *fp;
1485     int            i, anr;
1486     real           value;
1487     char          *ptr, *name;
1488     gmx_atomprop_t aps = gmx_atomprop_init();
1489
1490     fp = gmx_fio_fopen(outfile, "w");
1491     fprintf(fp, "%3d\n", atoms->nr);
1492     fprintf(fp, "%s\n", title);
1493     for (i = 0; (i < atoms->nr); i++)
1494     {
1495         anr  = atoms->atom[i].atomnumber;
1496         name = *atoms->atomname[i];
1497         if (anr == NOTSET)
1498         {
1499             if (gmx_atomprop_query(aps, epropElement, "???", name, &value))
1500             {
1501                 anr = gmx_nint(value);
1502             }
1503         }
1504         if ((ptr = gmx_atomprop_element(aps, anr)) == NULL)
1505         {
1506             ptr = name;
1507         }
1508         fprintf(fp, "%3s%10.5f%10.5f%10.5f\n", ptr,
1509                 10*x[i][XX], 10*x[i][YY], 10*x[i][ZZ]);
1510     }
1511     gmx_fio_fclose(fp);
1512     gmx_atomprop_destroy(aps);
1513 }
1514
1515 void write_sto_conf(const char *outfile, const char *title, t_atoms *atoms,
1516                     rvec x[], rvec *v, int ePBC, matrix box)
1517 {
1518     FILE       *out;
1519     int         ftp;
1520     t_trxframe  fr;
1521
1522     ftp = fn2ftp(outfile);
1523     switch (ftp)
1524     {
1525         case efGRO:
1526             write_conf(outfile, title, atoms, x, v, box);
1527             break;
1528         case efG96:
1529             clear_trxframe(&fr, TRUE);
1530             fr.bTitle = TRUE;
1531             fr.title  = title;
1532             fr.natoms = atoms->nr;
1533             fr.bAtoms = TRUE;
1534             fr.atoms  = atoms;
1535             fr.bX     = TRUE;
1536             fr.x      = x;
1537             if (v)
1538             {
1539                 fr.bV = TRUE;
1540                 fr.v  = v;
1541             }
1542             fr.bBox = TRUE;
1543             copy_mat(box, fr.box);
1544             out = gmx_fio_fopen(outfile, "w");
1545             write_g96_conf(out, &fr, -1, NULL);
1546             gmx_fio_fclose(out);
1547             break;
1548         case efXYZ:
1549             write_xyz_conf(outfile, (strlen(title) > 0) ? title : outfile, atoms, x);
1550             break;
1551         case efPDB:
1552         case efBRK:
1553         case efENT:
1554             out = gmx_fio_fopen(outfile, "w");
1555             write_pdbfile(out, title, atoms, x, ePBC, box, ' ', -1, NULL, TRUE);
1556             gmx_fio_fclose(out);
1557             break;
1558         case efESP:
1559             out = gmx_fio_fopen(outfile, "w");
1560             write_espresso_conf_indexed(out, title, atoms, atoms->nr, NULL, x, v, box);
1561             gmx_fio_fclose(out);
1562             break;
1563         case efTPR:
1564         case efTPB:
1565         case efTPA:
1566             gmx_fatal(FARGS, "Sorry, can not write a topology to %s", outfile);
1567             break;
1568         default:
1569             gmx_incons("Not supported in write_sto_conf");
1570     }
1571 }
1572
1573 void write_sto_conf_mtop(const char *outfile, const char *title,
1574                          gmx_mtop_t *mtop,
1575                          rvec x[], rvec *v, int ePBC, matrix box)
1576 {
1577     int     ftp;
1578     FILE   *out;
1579     t_atoms atoms;
1580
1581     ftp = fn2ftp(outfile);
1582     switch (ftp)
1583     {
1584         case efGRO:
1585             out = gmx_fio_fopen(outfile, "w");
1586             write_hconf_mtop(out, title, mtop, 3, x, v, box);
1587             gmx_fio_fclose(out);
1588             break;
1589         default:
1590             /* This is a brute force approach which requires a lot of memory.
1591              * We should implement mtop versions of all writing routines.
1592              */
1593             atoms = gmx_mtop_global_atoms(mtop);
1594
1595             write_sto_conf(outfile, title, &atoms, x, v, ePBC, box);
1596
1597             done_atom(&atoms);
1598             break;
1599     }
1600 }
1601
1602 static int get_xyz_coordnum(const char *infile)
1603 {
1604     FILE *fp;
1605     int   n;
1606
1607     fp = gmx_fio_fopen(infile, "r");
1608     if (fscanf(fp, "%d", &n) != 1)
1609     {
1610         gmx_fatal(FARGS, "Can not read number of atoms from %s", infile);
1611     }
1612     gmx_fio_fclose(fp);
1613
1614     return n;
1615 }
1616
1617 static void read_xyz_conf(const char *infile, char *title,
1618                           t_atoms *atoms, rvec *x)
1619 {
1620     FILE     *fp;
1621     int       i, n;
1622     double    xx, yy, zz;
1623     t_symtab *tab;
1624     char      atomnm[32], buf[STRLEN];
1625
1626     snew(tab, 1);
1627     fp = gmx_fio_fopen(infile, "r");
1628     fgets2(buf, STRLEN-1, fp);
1629     if (sscanf(buf, "%d", &n) != 1)
1630     {
1631         gmx_fatal(FARGS, "Can not read number of atoms from %s", infile);
1632     }
1633     fgets2(buf, STRLEN-1, fp);
1634     strcpy(title, buf);
1635     for (i = 0; (i < n); i++)
1636     {
1637         fgets2(buf, STRLEN-1, fp);
1638         if (sscanf(buf, "%s%lf%lf%lf", atomnm, &xx, &yy, &zz) != 4)
1639         {
1640             gmx_fatal(FARGS, "Can not read coordinates from %s", infile);
1641         }
1642         atoms->atomname[i] = put_symtab(tab, atomnm);
1643         x[i][XX]           = xx*0.1;
1644         x[i][YY]           = yy*0.1;
1645         x[i][ZZ]           = zz*0.1;
1646     }
1647     gmx_fio_fclose(fp);
1648 }
1649
1650 void get_stx_coordnum(const char *infile, int *natoms)
1651 {
1652     FILE      *in;
1653     int        ftp, tpxver, tpxgen;
1654     t_trxframe fr;
1655     char       g96_line[STRLEN+1];
1656
1657     ftp = fn2ftp(infile);
1658     range_check(ftp, 0, efNR);
1659     switch (ftp)
1660     {
1661         case efGRO:
1662             get_coordnum(infile, natoms);
1663             break;
1664         case efG96:
1665             in        = gmx_fio_fopen(infile, "r");
1666             fr.title  = NULL;
1667             fr.natoms = -1;
1668             fr.atoms  = NULL;
1669             fr.x      = NULL;
1670             fr.v      = NULL;
1671             fr.f      = NULL;
1672             *natoms   = read_g96_conf(in, infile, &fr, g96_line);
1673             gmx_fio_fclose(in);
1674             break;
1675         case efXYZ:
1676             *natoms = get_xyz_coordnum(infile);
1677             break;
1678         case efPDB:
1679         case efBRK:
1680         case efENT:
1681             in = gmx_fio_fopen(infile, "r");
1682             get_pdb_coordnum(in, natoms);
1683             gmx_fio_fclose(in);
1684             break;
1685         case efESP:
1686             *natoms = get_espresso_coordnum(infile);
1687             break;
1688         case efTPA:
1689         case efTPB:
1690         case efTPR:
1691         {
1692             t_tpxheader tpx;
1693
1694             read_tpxheader(infile, &tpx, TRUE, &tpxver, &tpxgen);
1695             *natoms = tpx.natoms;
1696             break;
1697         }
1698         default:
1699             gmx_fatal(FARGS, "File type %s not supported in get_stx_coordnum",
1700                       ftp2ext(ftp));
1701     }
1702 }
1703
1704 void read_stx_conf(const char *infile, char *title, t_atoms *atoms,
1705                    rvec x[], rvec *v, int *ePBC, matrix box)
1706 {
1707     FILE       *in;
1708     char        buf[256];
1709     gmx_mtop_t *mtop;
1710     t_topology  top;
1711     t_trxframe  fr;
1712     int         i, ftp, natoms;
1713     real        d;
1714     char        g96_line[STRLEN+1];
1715
1716     if (atoms->nr == 0)
1717     {
1718         fprintf(stderr, "Warning: Number of atoms in %s is 0\n", infile);
1719     }
1720     else if (atoms->atom == NULL)
1721     {
1722         gmx_mem("Uninitialized array atom");
1723     }
1724
1725     if (ePBC)
1726     {
1727         *ePBC = -1;
1728     }
1729
1730     ftp = fn2ftp(infile);
1731     switch (ftp)
1732     {
1733         case efGRO:
1734             read_whole_conf(infile, title, atoms, x, v, box);
1735             break;
1736         case efXYZ:
1737             read_xyz_conf(infile, title, atoms, x);
1738             break;
1739         case efG96:
1740             fr.title  = NULL;
1741             fr.natoms = atoms->nr;
1742             fr.atoms  = atoms;
1743             fr.x      = x;
1744             fr.v      = v;
1745             fr.f      = NULL;
1746             in        = gmx_fio_fopen(infile, "r");
1747             read_g96_conf(in, infile, &fr, g96_line);
1748             gmx_fio_fclose(in);
1749             copy_mat(fr.box, box);
1750             strncpy(title, fr.title, STRLEN);
1751             break;
1752         case efPDB:
1753         case efBRK:
1754         case efENT:
1755             read_pdb_conf(infile, title, atoms, x, ePBC, box, TRUE, NULL);
1756             break;
1757         case efESP:
1758             read_espresso_conf(infile, atoms, x, v, box);
1759             break;
1760         case efTPR:
1761         case efTPB:
1762         case efTPA:
1763             snew(mtop, 1);
1764             i = read_tpx(infile, NULL, box, &natoms, x, v, NULL, mtop);
1765             if (ePBC)
1766             {
1767                 *ePBC = i;
1768             }
1769
1770             strcpy(title, *(mtop->name));
1771
1772             /* Free possibly allocated memory */
1773             done_atom(atoms);
1774
1775             *atoms = gmx_mtop_global_atoms(mtop);
1776             top    = gmx_mtop_t_to_t_topology(mtop);
1777             tpx_make_chain_identifiers(atoms, &top.mols);
1778
1779             sfree(mtop);
1780             /* The strings in the symtab are still in use in the returned t_atoms
1781              * structure, so we should not free them. But there is no place to put the
1782              * symbols; the only choice is to leak the memory...
1783              * So we clear the symbol table before freeing the topology structure. */
1784             free_symtab(&top.symtab);
1785             done_top(&top);
1786
1787             break;
1788         default:
1789             gmx_incons("Not supported in read_stx_conf");
1790     }
1791 }