2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5 * Copyright (c) 2001-2004, The GROMACS development team.
6 * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
7 * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
8 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
9 * and including many others, as listed in the AUTHORS file in the
10 * top-level source directory and at http://www.gromacs.org.
12 * GROMACS is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public License
14 * as published by the Free Software Foundation; either version 2.1
15 * of the License, or (at your option) any later version.
17 * GROMACS is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with GROMACS; if not, see
24 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
25 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 * If you want to redistribute modifications to GROMACS, please
28 * consider that scientific software is very special. Version
29 * control is crucial - bugs must be traceable. We will be happy to
30 * consider code for inclusion in the official distribution, but
31 * derived work must not be called official GROMACS. Details are found
32 * in the README & COPYING files - if they are missing, get the
33 * official version at http://www.gromacs.org.
35 * To help us fund GROMACS development, we humbly ask that you cite
36 * the research papers on the package. Check out http://www.gromacs.org.
45 #include "gromacs/fileio/trxio.h"
46 #include "gromacs/math/vec.h"
47 #include "gromacs/topology/atoms.h"
48 #include "gromacs/topology/symtab.h"
49 #include "gromacs/trajectory/trajectoryframe.h"
50 #include "gromacs/utility/cstringutil.h"
51 #include "gromacs/utility/fatalerror.h"
52 #include "gromacs/utility/gmxassert.h"
53 #include "gromacs/utility/smalloc.h"
57 static int read_g96_pos(char line[], t_symtab* symtab, FILE* fp, const char* infile, t_trxframe* fr)
61 int nwanted, natoms, atnr, resnr = 0, oldres, newres, shift;
62 char anm[STRLEN], resnm[STRLEN];
68 if (fr->atoms != nullptr)
70 GMX_RELEASE_ASSERT(symtab != nullptr,
71 "Reading a conformation from a g96 format with atom data requires a "
72 "valid symbol table");
77 atoms->haveMass = FALSE;
78 atoms->haveCharge = FALSE;
79 atoms->haveType = FALSE;
80 atoms->haveBState = FALSE;
81 atoms->havePdbInfo = FALSE;
97 oldres = -666; /* Unlikely number for the first residue! */
99 while (!bEnd && fgets2(line, STRLEN, fp))
101 bEnd = (std::strncmp(line, "END", 3) == 0);
102 if (!bEnd && (line[0] != '#'))
104 if (sscanf(line + shift, "%15lf%15lf%15lf", &db1, &db2, &db3) != 3)
106 gmx_fatal(FARGS, "Did not find 3 coordinates for atom %d in %s\n", natoms + 1, infile);
108 if ((nwanted != -1) && (natoms >= nwanted))
110 gmx_fatal(FARGS, "Found more coordinates (%d) in %s than expected %d\n", natoms, infile, nwanted);
115 && (sscanf(line, "%5d%c%5s%c%5s%7d", &resnr, &c1, resnm, &c2, anm, &atnr) != 6))
124 strncpy(resnm, "???", sizeof(resnm) - 1);
126 strncpy(anm, "???", sizeof(anm) - 1);
128 atoms->atomname[natoms] = put_symtab(symtab, anm);
133 if (newres >= atoms->nr)
135 gmx_fatal(FARGS, "More residues than atoms in %s (natoms = %d)", infile, atoms->nr);
137 atoms->atom[natoms].resind = newres;
138 if (newres + 1 > atoms->nres)
140 atoms->nres = newres + 1;
142 t_atoms_set_resinfo(atoms, natoms, symtab, resnm, resnr, ' ', 0, ' ');
146 atoms->atom[natoms].resind = newres;
151 fr->x[natoms][0] = db1;
152 fr->x[natoms][1] = db2;
153 fr->x[natoms][2] = db3;
158 if ((nwanted != -1) && natoms != nwanted)
160 fprintf(stderr, "Warning: found less coordinates (%d) in %s than expected %d\n", natoms, infile, nwanted);
169 static int read_g96_vel(char line[], FILE* fp, const char* infile, t_trxframe* fr)
172 int nwanted, natoms = -1, shift;
173 double db1, db2, db3;
175 nwanted = fr->natoms;
179 if (strcmp(line, "VELOCITYRED") == 0)
189 while (!bEnd && fgets2(line, STRLEN, fp))
191 bEnd = (strncmp(line, "END", 3) == 0);
192 if (!bEnd && (line[0] != '#'))
194 if (sscanf(line + shift, "%15lf%15lf%15lf", &db1, &db2, &db3) != 3)
196 gmx_fatal(FARGS, "Did not find 3 velocities for atom %d in %s", natoms + 1, infile);
198 if ((nwanted != -1) && (natoms >= nwanted))
200 gmx_fatal(FARGS, "Found more velocities (%d) in %s than expected %d\n", natoms, infile, nwanted);
204 fr->v[natoms][0] = db1;
205 fr->v[natoms][1] = db2;
206 fr->v[natoms][2] = db3;
211 if ((nwanted != -1) && (natoms != nwanted))
213 fprintf(stderr, "Warning: found less velocities (%d) in %s than expected %d\n", natoms, infile, nwanted);
220 int read_g96_conf(FILE* fp, const char* infile, char** name, t_trxframe* fr, t_symtab* symtab, char* line)
222 gmx_bool bAtStart, bTime, bAtoms, bPos, bVel, bBox, bEnd, bFinished;
224 double db1, db2, db3, db4, db5, db6, db7, db8, db9;
226 bAtStart = (ftell(fp) == 0);
228 clear_trxframe(fr, FALSE);
234 bool foundTitle = false;
235 while (!foundTitle && fgets2(line, STRLEN, fp))
237 foundTitle = (std::strcmp(line, "TITLE") == 0);
239 fgets2(line, STRLEN, fp);
242 *name = gmx_strdup(line);
245 while (!bEnd && fgets2(line, STRLEN, fp))
247 bEnd = (std::strcmp(line, "END") == 0);
249 fgets2(line, STRLEN, fp);
252 /* Do not get a line if we are not at the start of the file, *
253 * because without a parameter file we don't know what is in *
254 * the trajectory and we have already read the line in the *
255 * previous call (VERY DIRTY). */
259 bTime = (std::strcmp(line, "TIMESTEP") == 0);
260 bAtoms = (std::strcmp(line, "POSITION") == 0);
261 bPos = (bAtoms || (strcmp(line, "POSITIONRED") == 0));
262 bVel = (std::strncmp(line, "VELOCITY", 8) == 0);
263 bBox = (std::strcmp(line, "BOX") == 0);
266 if (!fr->bTime && !fr->bX)
272 bFinished = (fgets2(line, STRLEN, fp) == nullptr);
273 } while (!bFinished && (line[0] == '#'));
274 sscanf(line, "%15" SCNd64 "%15lf", &(fr->step), &db1);
288 natoms = read_g96_pos(line, symtab, fp, infile, fr);
298 natoms = read_g96_vel(line, fp, infile, fr);
305 while (!bEnd && fgets2(line, STRLEN, fp))
307 bEnd = (strncmp(line, "END", 3) == 0);
308 if (!bEnd && (line[0] != '#'))
311 "%15lf%15lf%15lf%15lf%15lf%15lf%15lf%15lf%15lf",
323 gmx_fatal(FARGS, "Found a BOX line, but no box in %s", infile);
325 fr->box[XX][XX] = db1;
326 fr->box[YY][YY] = db2;
327 fr->box[ZZ][ZZ] = db3;
330 fr->box[XX][YY] = db4;
331 fr->box[XX][ZZ] = db5;
332 fr->box[YY][XX] = db6;
333 fr->box[YY][ZZ] = db7;
334 fr->box[ZZ][XX] = db8;
335 fr->box[ZZ][YY] = db9;
341 } while (!bFinished && (fgets2(line, STRLEN, fp) != nullptr));
348 void write_g96_conf(FILE* out, const char* title, const t_trxframe* fr, int nindex, const int* index)
364 fprintf(out, "TITLE\n%s\nEND\n", title);
365 if (fr->bStep || fr->bTime)
367 /* Officially the time format is %15.9, which is not enough for 10 ns */
368 fprintf(out, "TIMESTEP\n%15" PRId64 "%15.6f\nEND\n", fr->step, fr->time);
374 fprintf(out, "POSITION\n");
375 for (i = 0; i < nout; i++)
386 "%5d %-5s %-5s%7d%15.9f%15.9f%15.9f\n",
387 (atoms->resinfo[atoms->atom[a].resind].nr) % 100000,
388 *atoms->resinfo[atoms->atom[a].resind].name,
398 fprintf(out, "POSITIONRED\n");
399 for (i = 0; i < nout; i++)
409 fprintf(out, "%15.9f%15.9f%15.9f\n", fr->x[a][XX], fr->x[a][YY], fr->x[a][ZZ]);
412 fprintf(out, "END\n");
418 fprintf(out, "VELOCITY\n");
419 for (i = 0; i < nout; i++)
430 "%5d %-5s %-5s%7d%15.9f%15.9f%15.9f\n",
431 (atoms->resinfo[atoms->atom[a].resind].nr) % 100000,
432 *atoms->resinfo[atoms->atom[a].resind].name,
442 fprintf(out, "VELOCITYRED\n");
443 for (i = 0; i < nout; i++)
453 fprintf(out, "%15.9f%15.9f%15.9f\n", fr->v[a][XX], fr->v[a][YY], fr->v[a][ZZ]);
456 fprintf(out, "END\n");
460 fprintf(out, "BOX\n");
461 fprintf(out, "%15.9f%15.9f%15.9f", fr->box[XX][XX], fr->box[YY][YY], fr->box[ZZ][ZZ]);
462 if ((fr->box[XX][YY] != 0.0F) || (fr->box[XX][ZZ] != 0.0F) || (fr->box[YY][XX] != 0.0F)
463 || (fr->box[YY][ZZ] != 0.0F) || (fr->box[ZZ][XX] != 0.0F) || (fr->box[ZZ][YY] != 0.0F))
466 "%15.9f%15.9f%15.9f%15.9f%15.9f%15.9f",
475 fprintf(out, "END\n");