Split espresso I/O routines from confio.cpp
[alexxy/gromacs.git] / src / gromacs / fileio / confio.cpp
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,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.
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 #include "gmxpre.h"
38
39 #include "confio.h"
40
41 #include <cstdio>
42 #include <cstring>
43
44 #include "gromacs/fileio/espio.h"
45 #include "gromacs/fileio/filenm.h"
46 #include "gromacs/fileio/g96io.h"
47 #include "gromacs/fileio/gmxfio.h"
48 #include "gromacs/fileio/groio.h"
49 #include "gromacs/fileio/pdbio.h"
50 #include "gromacs/fileio/tpxio.h"
51 #include "gromacs/fileio/trx.h"
52 #include "gromacs/fileio/trxio.h"
53 #include "gromacs/math/vec.h"
54 #include "gromacs/topology/atomprop.h"
55 #include "gromacs/topology/atoms.h"
56 #include "gromacs/topology/block.h"
57 #include "gromacs/topology/mtop_util.h"
58 #include "gromacs/topology/symtab.h"
59 #include "gromacs/topology/topology.h"
60 #include "gromacs/utility/cstringutil.h"
61 #include "gromacs/utility/fatalerror.h"
62 #include "gromacs/utility/smalloc.h"
63
64 void write_sto_conf_indexed(const char *outfile, const char *title,
65                             t_atoms *atoms,
66                             rvec x[], rvec *v, int ePBC, matrix box,
67                             atom_id nindex, atom_id index[])
68 {
69     FILE       *out;
70     int         ftp;
71     t_trxframe  fr;
72
73     ftp = fn2ftp(outfile);
74     switch (ftp)
75     {
76         case efGRO:
77             out = gmx_fio_fopen(outfile, "w");
78             write_hconf_indexed_p(out, title, atoms, nindex, index, 3, x, v, box);
79             gmx_fio_fclose(out);
80             break;
81         case efG96:
82             clear_trxframe(&fr, TRUE);
83             fr.bTitle = TRUE;
84             fr.title  = title;
85             fr.natoms = atoms->nr;
86             fr.bAtoms = TRUE;
87             fr.atoms  = atoms;
88             fr.bX     = TRUE;
89             fr.x      = x;
90             if (v)
91             {
92                 fr.bV = TRUE;
93                 fr.v  = v;
94             }
95             fr.bBox = TRUE;
96             copy_mat(box, fr.box);
97             out = gmx_fio_fopen(outfile, "w");
98             write_g96_conf(out, &fr, nindex, index);
99             gmx_fio_fclose(out);
100             break;
101         case efPDB:
102         case efBRK:
103         case efENT:
104         case efPQR:
105             out = gmx_fio_fopen(outfile, "w");
106             write_pdbfile_indexed(out, title, atoms, x, ePBC, box, ' ', -1, nindex, index, NULL, TRUE);
107             gmx_fio_fclose(out);
108             break;
109         case efESP:
110             out = gmx_fio_fopen(outfile, "w");
111             write_espresso_conf_indexed(out, title, atoms, nindex, index, x, v, box);
112             gmx_fio_fclose(out);
113             break;
114         case efTPR:
115             gmx_fatal(FARGS, "Sorry, can not write a topology to %s", outfile);
116             break;
117         default:
118             gmx_incons("Not supported in write_sto_conf_indexed");
119     }
120 }
121
122 void write_sto_conf(const char *outfile, const char *title, t_atoms *atoms,
123                     rvec x[], rvec *v, int ePBC, matrix box)
124 {
125     FILE       *out;
126     int         ftp;
127     t_trxframe  fr;
128
129     ftp = fn2ftp(outfile);
130     switch (ftp)
131     {
132         case efGRO:
133             write_conf_p(outfile, title, atoms, 3, x, v, box);
134             break;
135         case efG96:
136             clear_trxframe(&fr, TRUE);
137             fr.bTitle = TRUE;
138             fr.title  = title;
139             fr.natoms = atoms->nr;
140             fr.bAtoms = TRUE;
141             fr.atoms  = atoms;
142             fr.bX     = TRUE;
143             fr.x      = x;
144             if (v)
145             {
146                 fr.bV = TRUE;
147                 fr.v  = v;
148             }
149             fr.bBox = TRUE;
150             copy_mat(box, fr.box);
151             out = gmx_fio_fopen(outfile, "w");
152             write_g96_conf(out, &fr, -1, NULL);
153             gmx_fio_fclose(out);
154             break;
155         case efPDB:
156         case efBRK:
157         case efENT:
158             out = gmx_fio_fopen(outfile, "w");
159             write_pdbfile(out, title, atoms, x, ePBC, box, ' ', -1, NULL, TRUE);
160             gmx_fio_fclose(out);
161             break;
162         case efESP:
163             out = gmx_fio_fopen(outfile, "w");
164             write_espresso_conf_indexed(out, title, atoms, atoms->nr, NULL, x, v, box);
165             gmx_fio_fclose(out);
166             break;
167         case efTPR:
168             gmx_fatal(FARGS, "Sorry, can not write a topology to %s", outfile);
169             break;
170         default:
171             gmx_incons("Not supported in write_sto_conf");
172     }
173 }
174
175 void write_sto_conf_mtop(const char *outfile, const char *title,
176                          gmx_mtop_t *mtop,
177                          rvec x[], rvec *v, int ePBC, matrix box)
178 {
179     int     ftp;
180     FILE   *out;
181     t_atoms atoms;
182
183     ftp = fn2ftp(outfile);
184     switch (ftp)
185     {
186         case efGRO:
187             out = gmx_fio_fopen(outfile, "w");
188             write_hconf_mtop(out, title, mtop, 3, x, v, box);
189             gmx_fio_fclose(out);
190             break;
191         default:
192             /* This is a brute force approach which requires a lot of memory.
193              * We should implement mtop versions of all writing routines.
194              */
195             atoms = gmx_mtop_global_atoms(mtop);
196
197             write_sto_conf(outfile, title, &atoms, x, v, ePBC, box);
198
199             done_atom(&atoms);
200             break;
201     }
202 }
203
204 void get_stx_coordnum(const char *infile, int *natoms)
205 {
206     FILE      *in;
207     int        ftp, tpxver, tpxgen;
208     t_trxframe fr;
209     char       g96_line[STRLEN+1];
210
211     ftp = fn2ftp(infile);
212     range_check(ftp, 0, efNR);
213     switch (ftp)
214     {
215         case efGRO:
216             get_coordnum(infile, natoms);
217             break;
218         case efG96:
219             in        = gmx_fio_fopen(infile, "r");
220             fr.title  = NULL;
221             fr.natoms = -1;
222             fr.atoms  = NULL;
223             fr.x      = NULL;
224             fr.v      = NULL;
225             fr.f      = NULL;
226             *natoms   = read_g96_conf(in, infile, &fr, g96_line);
227             gmx_fio_fclose(in);
228             break;
229         case efPDB:
230         case efBRK:
231         case efENT:
232             in = gmx_fio_fopen(infile, "r");
233             get_pdb_coordnum(in, natoms);
234             gmx_fio_fclose(in);
235             break;
236         case efESP:
237             *natoms = get_espresso_coordnum(infile);
238             break;
239         case efTPR:
240         {
241             t_tpxheader tpx;
242
243             read_tpxheader(infile, &tpx, TRUE, &tpxver, &tpxgen);
244             *natoms = tpx.natoms;
245             break;
246         }
247         default:
248             gmx_fatal(FARGS, "File type %s not supported in get_stx_coordnum",
249                       ftp2ext(ftp));
250     }
251 }
252
253 static void tpx_make_chain_identifiers(t_atoms *atoms, t_block *mols)
254 {
255     int  m, a, a0, a1, r;
256     char c, chainid;
257     int  chainnum;
258
259     /* We always assign a new chain number, but save the chain id characters
260      * for larger molecules.
261      */
262 #define CHAIN_MIN_ATOMS 15
263
264     chainnum = 0;
265     chainid  = 'A';
266     for (m = 0; m < mols->nr; m++)
267     {
268         a0 = mols->index[m];
269         a1 = mols->index[m+1];
270         if ((a1-a0 >= CHAIN_MIN_ATOMS) && (chainid <= 'Z'))
271         {
272             c = chainid;
273             chainid++;
274         }
275         else
276         {
277             c = ' ';
278         }
279         for (a = a0; a < a1; a++)
280         {
281             atoms->resinfo[atoms->atom[a].resind].chainnum = chainnum;
282             atoms->resinfo[atoms->atom[a].resind].chainid  = c;
283         }
284         chainnum++;
285     }
286
287     /* Blank out the chain id if there was only one chain */
288     if (chainid == 'B')
289     {
290         for (r = 0; r < atoms->nres; r++)
291         {
292             atoms->resinfo[r].chainid = ' ';
293         }
294     }
295 }
296
297 void read_stx_conf(const char *infile, char *title, t_atoms *atoms,
298                    rvec x[], rvec *v, int *ePBC, matrix box)
299 {
300     FILE       *in;
301     gmx_mtop_t *mtop;
302     t_topology  top;
303     t_trxframe  fr;
304     int         i, ftp, natoms;
305     char        g96_line[STRLEN+1];
306
307     if (atoms->nr == 0)
308     {
309         fprintf(stderr, "Warning: Number of atoms in %s is 0\n", infile);
310     }
311     else if (atoms->atom == NULL)
312     {
313         gmx_mem("Uninitialized array atom");
314     }
315
316     if (ePBC)
317     {
318         *ePBC = -1;
319     }
320
321     ftp = fn2ftp(infile);
322     switch (ftp)
323     {
324         case efGRO:
325             read_whole_conf(infile, title, atoms, x, v, box);
326             break;
327         case efG96:
328             fr.title  = NULL;
329             fr.natoms = atoms->nr;
330             fr.atoms  = atoms;
331             fr.x      = x;
332             fr.v      = v;
333             fr.f      = NULL;
334             in        = gmx_fio_fopen(infile, "r");
335             read_g96_conf(in, infile, &fr, g96_line);
336             gmx_fio_fclose(in);
337             copy_mat(fr.box, box);
338             std::strncpy(title, fr.title, STRLEN);
339             break;
340         case efPDB:
341         case efBRK:
342         case efENT:
343             read_pdb_conf(infile, title, atoms, x, ePBC, box, TRUE, NULL);
344             break;
345         case efESP:
346             read_espresso_conf(infile, title, atoms, x, v, box);
347             break;
348         case efTPR:
349             snew(mtop, 1);
350             i = read_tpx(infile, NULL, box, &natoms, x, v, NULL, mtop);
351             if (ePBC)
352             {
353                 *ePBC = i;
354             }
355
356             strcpy(title, *(mtop->name));
357
358             /* Free possibly allocated memory */
359             done_atom(atoms);
360
361             *atoms = gmx_mtop_global_atoms(mtop);
362             top    = gmx_mtop_t_to_t_topology(mtop);
363             tpx_make_chain_identifiers(atoms, &top.mols);
364
365             sfree(mtop);
366             /* The strings in the symtab are still in use in the returned t_atoms
367              * structure, so we should not free them. But there is no place to put the
368              * symbols; the only choice is to leak the memory...
369              * So we clear the symbol table before freeing the topology structure. */
370             free_symtab(&top.symtab);
371             done_top(&top);
372
373             break;
374         default:
375             gmx_incons("Not supported in read_stx_conf");
376     }
377 }
378
379 static void done_gmx_groups_t(gmx_groups_t *g)
380 {
381     int i;
382
383     for (i = 0; (i < egcNR); i++)
384     {
385         if (NULL != g->grps[i].nm_ind)
386         {
387             sfree(g->grps[i].nm_ind);
388             g->grps[i].nm_ind = NULL;
389         }
390         if (NULL != g->grpnr[i])
391         {
392             sfree(g->grpnr[i]);
393             g->grpnr[i] = NULL;
394         }
395     }
396     /* The contents of this array is in symtab, don't free it here */
397     sfree(g->grpname);
398 }
399
400 gmx_bool read_tps_conf(const char *infile, char *title, t_topology *top, int *ePBC,
401                        rvec **x, rvec **v, matrix box, gmx_bool bMass)
402 {
403     t_tpxheader      header;
404     int              natoms, i, version, generation;
405     gmx_bool         bTop, bXNULL = FALSE;
406     gmx_mtop_t      *mtop;
407     gmx_atomprop_t   aps;
408
409     bTop  = fn2bTPX(infile);
410     *ePBC = -1;
411     if (bTop)
412     {
413         read_tpxheader(infile, &header, TRUE, &version, &generation);
414         if (x)
415         {
416             snew(*x, header.natoms);
417         }
418         if (v)
419         {
420             snew(*v, header.natoms);
421         }
422         snew(mtop, 1);
423         *ePBC = read_tpx(infile, NULL, box, &natoms,
424                          (x == NULL) ? NULL : *x, (v == NULL) ? NULL : *v, NULL, mtop);
425         *top = gmx_mtop_t_to_t_topology(mtop);
426         /* In this case we need to throw away the group data too */
427         done_gmx_groups_t(&mtop->groups);
428         sfree(mtop);
429         std::strcpy(title, *top->name);
430         tpx_make_chain_identifiers(&top->atoms, &top->mols);
431     }
432     else
433     {
434         get_stx_coordnum(infile, &natoms);
435         init_t_atoms(&top->atoms, natoms, (fn2ftp(infile) == efPDB));
436         if (x == NULL)
437         {
438             snew(x, 1);
439             bXNULL = TRUE;
440         }
441         snew(*x, natoms);
442         if (v)
443         {
444             snew(*v, natoms);
445         }
446         read_stx_conf(infile, title, &top->atoms, *x, (v == NULL) ? NULL : *v, ePBC, box);
447         if (bXNULL)
448         {
449             sfree(*x);
450             sfree(x);
451         }
452         if (bMass)
453         {
454             aps = gmx_atomprop_init();
455             for (i = 0; (i < natoms); i++)
456             {
457                 if (!gmx_atomprop_query(aps, epropMass,
458                                         *top->atoms.resinfo[top->atoms.atom[i].resind].name,
459                                         *top->atoms.atomname[i],
460                                         &(top->atoms.atom[i].m)))
461                 {
462                     if (debug)
463                     {
464                         fprintf(debug, "Can not find mass for atom %s %d %s, setting to 1\n",
465                                 *top->atoms.resinfo[top->atoms.atom[i].resind].name,
466                                 top->atoms.resinfo[top->atoms.atom[i].resind].nr,
467                                 *top->atoms.atomname[i]);
468                     }
469                 }
470             }
471             gmx_atomprop_destroy(aps);
472         }
473         top->idef.ntypes = -1;
474     }
475
476     return bTop;
477 }