2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5 * Copyright (c) 2001-2004, The GROMACS development team.
6 * Copyright (c) 2013,2014,2015, by the GROMACS development team, led by
7 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
8 * and including many others, as listed in the AUTHORS file in the
9 * top-level source directory and at http://www.gromacs.org.
11 * GROMACS is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public License
13 * as published by the Free Software Foundation; either version 2.1
14 * of the License, or (at your option) any later version.
16 * GROMACS is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with GROMACS; if not, see
23 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
24 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 * If you want to redistribute modifications to GROMACS, please
27 * consider that scientific software is very special. Version
28 * control is crucial - bugs must be traceable. We will be happy to
29 * consider code for inclusion in the official distribution, but
30 * derived work must not be called official GROMACS. Details are found
31 * in the README & COPYING files - if they are missing, get the
32 * official version at http://www.gromacs.org.
34 * To help us fund GROMACS development, we humbly ask that you cite
35 * the research papers on the package. Check out http://www.gromacs.org.
46 #include "gromacs/fileio/copyrite.h"
47 #include "gromacs/fileio/gmxfio.h"
48 #include "gromacs/fileio/trx.h"
49 #include "gromacs/topology/atoms.h"
50 #include "gromacs/topology/mtop_util.h"
51 #include "gromacs/topology/symtab.h"
52 #include "gromacs/topology/topology.h"
53 #include "gromacs/utility/cstringutil.h"
54 #include "gromacs/utility/fatalerror.h"
55 #include "gromacs/utility/futil.h"
56 #include "gromacs/utility/smalloc.h"
58 static void get_coordnum_fp(FILE *in
, char *title
, int *natoms
)
62 fgets2(title
, STRLEN
, in
);
63 fgets2(line
, STRLEN
, in
);
64 if (sscanf(line
, "%d", natoms
) != 1)
66 gmx_fatal(FARGS
, "gro file does not have the number of atoms on the second line");
70 void get_coordnum(const char *infile
, int *natoms
)
75 in
= gmx_fio_fopen(infile
, "r");
76 get_coordnum_fp(in
, title
, natoms
);
80 static gmx_bool
get_w_conf(FILE *in
, const char *infile
, char *title
,
81 t_symtab
*symtab
, t_atoms
*atoms
, int *ndec
,
82 rvec x
[], rvec
*v
, matrix box
)
85 char resname
[6], oldresname
[6];
86 char line
[STRLEN
+1], *ptr
;
88 double x1
, y1
, z1
, x2
, y2
, z2
;
90 int natoms
, i
, m
, resnr
, newres
, oldres
, ddist
, c
;
91 gmx_bool bFirst
, bVel
, oldResFirst
;
99 /* Read the title and number of atoms */
100 get_coordnum_fp(in
, title
, &natoms
);
102 if (natoms
> atoms
->nr
)
104 gmx_fatal(FARGS
, "gro file contains more atoms (%d) than expected (%d)",
107 else if (natoms
< atoms
->nr
)
109 fprintf(stderr
, "Warning: gro file contains less atoms (%d) than expected"
110 " (%d)\n", natoms
, atoms
->nr
);
118 oldresname
[0] = '\0';
120 /* just pray the arrays are big enough */
121 for (i
= 0; (i
< natoms
); i
++)
123 if ((fgets2(line
, STRLEN
, in
)) == NULL
)
125 gmx_fatal(FARGS
, "Unexpected end of file in file %s at line %d",
128 if (strlen(line
) < 39)
130 gmx_fatal(FARGS
, "Invalid line in %s for atom %d:\n%s", infile
, i
+1, line
);
133 /* determine read precision from distance between periods
138 p1
= strchr(line
, '.');
141 gmx_fatal(FARGS
, "A coordinate in file %s does not contain a '.'", infile
);
143 p2
= strchr(&p1
[1], '.');
146 gmx_fatal(FARGS
, "A coordinate in file %s does not contain a '.'", infile
);
151 p3
= strchr(&p2
[1], '.');
154 gmx_fatal(FARGS
, "A coordinate in file %s does not contain a '.'", infile
);
157 if (p3
- p2
!= ddist
)
159 gmx_fatal(FARGS
, "The spacing of the decimal points in file %s is not consistent for x, y and z", infile
);
164 memcpy(name
, line
, 5);
166 sscanf(name
, "%d", &resnr
);
167 sscanf(line
+5, "%5s", resname
);
169 if (!oldResFirst
|| oldres
!= resnr
|| strncmp(resname
, oldresname
, sizeof(resname
)))
174 if (newres
>= natoms
)
176 gmx_fatal(FARGS
, "More residues than atoms in %s (natoms = %d)",
179 atoms
->atom
[i
].resind
= newres
;
180 t_atoms_set_resinfo(atoms
, i
, symtab
, resname
, resnr
, ' ', 0, ' ');
184 atoms
->atom
[i
].resind
= newres
;
188 std::memcpy(name
, line
+10, 5);
189 atoms
->atomname
[i
] = put_symtab(symtab
, name
);
191 /* Copy resname to oldresname after we are done with the sanity check above */
192 std::strncpy(oldresname
, resname
, sizeof(oldresname
));
194 /* eventueel controle atomnumber met i+1 */
196 /* coordinates (start after residue data) */
198 /* Read fixed format */
199 for (m
= 0; m
< DIM
; m
++)
201 for (c
= 0; (c
< ddist
&& ptr
[0]); c
++)
207 if (sscanf(buf
, "%lf %lf", &x1
, &x2
) != 1)
209 gmx_fatal(FARGS
, "Something is wrong in the coordinate formatting of file %s. Note that gro is fixed format (see the manual)", infile
);
217 /* velocities (start after residues and coordinates) */
220 /* Read fixed format */
221 for (m
= 0; m
< DIM
; m
++)
223 for (c
= 0; (c
< ddist
&& ptr
[0]); c
++)
229 if (sscanf(buf
, "%lf", &x1
) != 1)
241 atoms
->nres
= newres
+ 1;
244 fgets2(line
, STRLEN
, in
);
245 if (sscanf(line
, "%lf%lf%lf", &x1
, &y1
, &z1
) != 3)
247 gmx_warning("Bad box in file %s", infile
);
249 /* Generate a cubic box */
250 for (m
= 0; (m
< DIM
); m
++)
252 xmin
[m
] = xmax
[m
] = x
[0][m
];
254 for (i
= 1; (i
< atoms
->nr
); i
++)
256 for (m
= 0; (m
< DIM
); m
++)
258 xmin
[m
] = std::min(xmin
[m
], x
[i
][m
]);
259 xmax
[m
] = std::max(xmax
[m
], x
[i
][m
]);
262 for (i
= 0; i
< DIM
; i
++)
264 for (m
= 0; m
< DIM
; m
++)
269 for (m
= 0; (m
< DIM
); m
++)
271 box
[m
][m
] = (xmax
[m
]-xmin
[m
]);
273 fprintf(stderr
, "Generated a cubic box %8.3f x %8.3f x %8.3f\n",
274 box
[XX
][XX
], box
[YY
][YY
], box
[ZZ
][ZZ
]);
278 /* We found the first three values, the diagonal elements */
282 if (sscanf (line
, "%*f%*f%*f%lf%lf%lf%lf%lf%lf",
283 &x1
, &y1
, &z1
, &x2
, &y2
, &z2
) != 6)
285 x1
= y1
= z1
= x2
= y2
= z2
= 0.0;
298 void gmx_gro_read_conf(const char *infile
,
299 t_topology
*top
, rvec x
[], rvec
*v
, matrix box
)
301 FILE *in
= gmx_fio_fopen(infile
, "r");
304 get_w_conf(in
, infile
, title
, &top
->symtab
, &top
->atoms
, &ndec
, x
, v
, box
);
305 top
->name
= put_symtab(&top
->symtab
, title
);
309 static gmx_bool
gmx_one_before_eof(FILE *fp
)
314 if ((beof
= fread(data
, 1, 1, fp
)) == 1)
316 gmx_fseek(fp
, -1, SEEK_CUR
);
321 gmx_bool
gro_next_x_or_v(FILE *status
, t_trxframe
*fr
)
325 char title
[STRLEN
], *p
;
329 if (gmx_one_before_eof(status
))
334 open_symtab(&symtab
);
335 atoms
.nr
= fr
->natoms
;
336 snew(atoms
.atom
, fr
->natoms
);
337 atoms
.nres
= fr
->natoms
;
338 snew(atoms
.resinfo
, fr
->natoms
);
339 snew(atoms
.atomname
, fr
->natoms
);
341 fr
->bV
= get_w_conf(status
, title
, title
, &symtab
, &atoms
, &ndec
, fr
->x
, fr
->v
, fr
->box
);
344 /* prec = 10^ndec: */
345 for (i
= 0; i
< ndec
; i
++)
355 sfree(atoms
.resinfo
);
356 sfree(atoms
.atomname
);
357 done_symtab(&symtab
);
359 if ((p
= strstr(title
, "t=")) != NULL
)
362 if (sscanf(p
, "%lf", &tt
) == 1)
374 if (atoms
.nr
!= fr
->natoms
)
376 gmx_fatal(FARGS
, "Number of atoms in gro frame (%d) doesn't match the number in the previous frame (%d)", atoms
.nr
, fr
->natoms
);
382 int gro_first_x_or_v(FILE *status
, t_trxframe
*fr
)
387 fprintf(stderr
, "Reading frames from gro file");
388 get_coordnum_fp(status
, title
, &fr
->natoms
);
390 fprintf(stderr
, " '%s', %d atoms.\n", title
, fr
->natoms
);
395 gmx_file("No coordinates in gro file");
398 snew(fr
->x
, fr
->natoms
);
399 snew(fr
->v
, fr
->natoms
);
400 gro_next_x_or_v(status
, fr
);
405 static void make_hconf_format(int pr
, gmx_bool bVel
, char format
[])
409 /* build format string for printing,
410 something like "%8.3f" for x and "%8.4f" for v */
423 sprintf(format
, "%%%d.%df%%%d.%df%%%d.%df%%%d.%df%%%d.%df%%%d.%df\n",
424 l
, pr
, l
, pr
, l
, pr
, l
, vpr
, l
, vpr
, l
, vpr
);
428 sprintf(format
, "%%%d.%df%%%d.%df%%%d.%df\n", l
, pr
, l
, pr
, l
, pr
);
433 static void write_hconf_box(FILE *out
, int pr
, matrix box
)
444 if (box
[XX
][YY
] || box
[XX
][ZZ
] || box
[YY
][XX
] || box
[YY
][ZZ
] ||
445 box
[ZZ
][XX
] || box
[ZZ
][YY
])
447 sprintf(format
, "%%%d.%df%%%d.%df%%%d.%df"
448 "%%%d.%df%%%d.%df%%%d.%df%%%d.%df%%%d.%df%%%d.%df\n",
449 l
, pr
, l
, pr
, l
, pr
, l
, pr
, l
, pr
, l
, pr
, l
, pr
, l
, pr
, l
, pr
);
451 box
[XX
][XX
], box
[YY
][YY
], box
[ZZ
][ZZ
],
452 box
[XX
][YY
], box
[XX
][ZZ
], box
[YY
][XX
],
453 box
[YY
][ZZ
], box
[ZZ
][XX
], box
[ZZ
][YY
]);
457 sprintf(format
, "%%%d.%df%%%d.%df%%%d.%df\n", l
, pr
, l
, pr
, l
, pr
);
459 box
[XX
][XX
], box
[YY
][YY
], box
[ZZ
][ZZ
]);
463 void write_hconf_indexed_p(FILE *out
, const char *title
, t_atoms
*atoms
,
464 int nx
, const atom_id index
[], int pr
,
465 rvec
*x
, rvec
*v
, matrix box
)
467 char resnm
[6], nm
[6], format
[100];
468 int ai
, i
, resind
, resnr
;
471 fprintf(out
, "%s\n", (title
&& title
[0]) ? title
: format
);
472 fprintf(out
, "%5d\n", nx
);
474 make_hconf_format(pr
, v
!= NULL
, format
);
476 for (i
= 0; (i
< nx
); i
++)
480 resind
= atoms
->atom
[ai
].resind
;
481 std::strncpy(resnm
, " ??? ", sizeof(resnm
)-1);
482 if (resind
< atoms
->nres
)
484 std::strncpy(resnm
, *atoms
->resinfo
[resind
].name
, sizeof(resnm
)-1);
485 resnr
= atoms
->resinfo
[resind
].nr
;
489 std::strncpy(resnm
, " ??? ", sizeof(resnm
)-1);
495 std::strncpy(nm
, *atoms
->atomname
[ai
], sizeof(nm
)-1);
499 std::strncpy(nm
, " ??? ", sizeof(nm
)-1);
502 fprintf(out
, "%5d%-5.5s%5.5s%5d", resnr
%100000, resnm
, nm
, (ai
+1)%100000);
503 /* next fprintf uses built format string */
507 x
[ai
][XX
], x
[ai
][YY
], x
[ai
][ZZ
], v
[ai
][XX
], v
[ai
][YY
], v
[ai
][ZZ
]);
512 x
[ai
][XX
], x
[ai
][YY
], x
[ai
][ZZ
]);
516 write_hconf_box(out
, pr
, box
);
521 void write_hconf_mtop(FILE *out
, const char *title
, gmx_mtop_t
*mtop
, int pr
,
522 rvec
*x
, rvec
*v
, matrix box
)
526 gmx_mtop_atomloop_all_t aloop
;
528 char *atomname
, *resname
;
531 fprintf(out
, "%s\n", (title
&& title
[0]) ? title
: format
);
532 fprintf(out
, "%5d\n", mtop
->natoms
);
534 make_hconf_format(pr
, v
!= NULL
, format
);
536 aloop
= gmx_mtop_atomloop_all_init(mtop
);
537 while (gmx_mtop_atomloop_all_next(aloop
, &i
, &atom
))
539 gmx_mtop_atomloop_all_names(aloop
, &atomname
, &resnr
, &resname
);
541 fprintf(out
, "%5d%-5.5s%5.5s%5d",
542 resnr
%100000, resname
, atomname
, (i
+1)%100000);
543 /* next fprintf uses built format string */
547 x
[i
][XX
], x
[i
][YY
], x
[i
][ZZ
], v
[i
][XX
], v
[i
][YY
], v
[i
][ZZ
]);
552 x
[i
][XX
], x
[i
][YY
], x
[i
][ZZ
]);
556 write_hconf_box(out
, pr
, box
);
561 void write_hconf_p(FILE *out
, const char *title
, t_atoms
*atoms
, int pr
,
562 rvec
*x
, rvec
*v
, matrix box
)
568 for (i
= 0; (i
< atoms
->nr
); i
++)
572 write_hconf_indexed_p(out
, title
, atoms
, atoms
->nr
, aa
, pr
, x
, v
, box
);
576 void write_conf_p(const char *outfile
, const char *title
,
577 t_atoms
*atoms
, int pr
,
578 rvec
*x
, rvec
*v
, matrix box
)
582 out
= gmx_fio_fopen(outfile
, "w");
583 write_hconf_p(out
, title
, atoms
, pr
, x
, v
, box
);