a9b6b312eb4042bf74c9d2a6bdc37fad619f531b
[alexxy/gromacs.git] / src / gromacs / topology / topology.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,2016,2017,2018, 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 "topology.h"
40
41 #include <cstdio>
42
43 #include <algorithm>
44
45 #include "gromacs/math/vecdump.h"
46 #include "gromacs/topology/atoms.h"
47 #include "gromacs/topology/idef.h"
48 #include "gromacs/topology/ifunc.h"
49 #include "gromacs/topology/symtab.h"
50 #include "gromacs/utility/compare.h"
51 #include "gromacs/utility/smalloc.h"
52 #include "gromacs/utility/strconvert.h"
53 #include "gromacs/utility/txtdump.h"
54
55 const char *gtypes[egcNR+1] = {
56     "T-Coupling", "Energy Mon.", "Acceleration", "Freeze",
57     "User1", "User2", "VCM", "Compressed X", "Or. Res. Fit", "QMMM", nullptr
58 };
59
60 static void init_groups(gmx_groups_t *groups)
61 {
62     groups->ngrpname = 0;
63     groups->grpname  = nullptr;
64     for (int g = 0; g < egcNR; g++)
65     {
66         groups->grps[g].nm_ind = nullptr;
67         groups->ngrpnr[g]      = 0;
68         groups->grpnr[g]       = nullptr;
69     }
70
71 }
72
73 void init_mtop(gmx_mtop_t *mtop)
74 {
75     mtop->name         = nullptr;
76     mtop->nmoltype     = 0;
77     mtop->moltype      = nullptr;
78     mtop->nmolblock    = 0;
79     mtop->molblock     = nullptr;
80     mtop->maxres_renum = 0;
81     mtop->maxresnr     = -1;
82     init_groups(&mtop->groups);
83     open_symtab(&mtop->symtab);
84 }
85
86 void init_top(t_topology *top)
87 {
88     top->name = nullptr;
89     init_atom(&(top->atoms));
90     init_atomtypes(&(top->atomtypes));
91     init_block(&top->cgs);
92     init_block(&top->mols);
93     init_blocka(&top->excls);
94     open_symtab(&top->symtab);
95 }
96
97
98 void done_moltype(gmx_moltype_t *molt)
99 {
100     done_atom(&molt->atoms);
101     done_block(&molt->cgs);
102     done_blocka(&molt->excls);
103
104     for (int f = 0; f < F_NRE; f++)
105     {
106         sfree(molt->ilist[f].iatoms);
107         molt->ilist[f].nalloc = 0;
108     }
109 }
110
111 void done_molblock(gmx_molblock_t *molb)
112 {
113     if (molb->nposres_xA > 0)
114     {
115         molb->nposres_xA = 0;
116         sfree(molb->posres_xA);
117     }
118     if (molb->nposres_xB > 0)
119     {
120         molb->nposres_xB = 0;
121         sfree(molb->posres_xB);
122     }
123 }
124
125 void done_gmx_groups_t(gmx_groups_t *g)
126 {
127     int i;
128
129     for (i = 0; (i < egcNR); i++)
130     {
131         if (nullptr != g->grps[i].nm_ind)
132         {
133             sfree(g->grps[i].nm_ind);
134             g->grps[i].nm_ind = nullptr;
135         }
136         if (nullptr != g->grpnr[i])
137         {
138             sfree(g->grpnr[i]);
139             g->grpnr[i] = nullptr;
140         }
141     }
142     /* The contents of this array is in symtab, don't free it here */
143     sfree(g->grpname);
144 }
145
146 void done_mtop(gmx_mtop_t *mtop)
147 {
148     done_symtab(&mtop->symtab);
149
150     sfree(mtop->ffparams.functype);
151     sfree(mtop->ffparams.iparams);
152     for (int i = 0; i < mtop->ffparams.cmap_grid.ngrid; i++)
153     {
154         sfree(mtop->ffparams.cmap_grid.cmapdata[i].cmap);
155     }
156     sfree(mtop->ffparams.cmap_grid.cmapdata);
157
158     for (int i = 0; i < mtop->nmoltype; i++)
159     {
160         done_moltype(&mtop->moltype[i]);
161     }
162     sfree(mtop->moltype);
163     for (int i = 0; i < mtop->nmolblock; i++)
164     {
165         done_molblock(&mtop->molblock[i]);
166     }
167     sfree(mtop->molblock);
168     done_atomtypes(&mtop->atomtypes);
169     done_gmx_groups_t(&mtop->groups);
170 }
171
172 void done_top(t_topology *top)
173 {
174     sfree(top->idef.functype);
175     sfree(top->idef.iparams);
176     for (int f = 0; f < F_NRE; ++f)
177     {
178         sfree(top->idef.il[f].iatoms);
179         top->idef.il[f].iatoms = nullptr;
180         top->idef.il[f].nalloc = 0;
181     }
182
183     done_atom(&(top->atoms));
184
185     /* For GB */
186     done_atomtypes(&(top->atomtypes));
187
188     done_symtab(&(top->symtab));
189     done_block(&(top->cgs));
190     done_block(&(top->mols));
191     done_blocka(&(top->excls));
192 }
193
194 void done_top_mtop(t_topology *top, gmx_mtop_t *mtop)
195 {
196     if (mtop != nullptr)
197     {
198         if (top != nullptr)
199         {
200             for (int f = 0; f < F_NRE; ++f)
201             {
202                 sfree(top->idef.il[f].iatoms);
203                 top->idef.il[f].iatoms = nullptr;
204                 top->idef.il[f].nalloc = 0;
205             }
206             done_atom(&top->atoms);
207             done_block(&top->cgs);
208             done_blocka(&top->excls);
209             done_block(&top->mols);
210             done_symtab(&top->symtab);
211             open_symtab(&mtop->symtab);
212         }
213         done_mtop(mtop);
214     }
215 }
216
217 bool gmx_mtop_has_masses(const gmx_mtop_t *mtop)
218 {
219     if (mtop == nullptr)
220     {
221         return false;
222     }
223     return mtop->nmoltype == 0 || mtop->moltype[0].atoms.haveMass;
224 }
225
226 bool gmx_mtop_has_charges(const gmx_mtop_t *mtop)
227 {
228     if (mtop == nullptr)
229     {
230         return false;
231     }
232     return mtop->nmoltype == 0 || mtop->moltype[0].atoms.haveCharge;
233 }
234
235 bool gmx_mtop_has_atomtypes(const gmx_mtop_t *mtop)
236 {
237     if (mtop == nullptr)
238     {
239         return false;
240     }
241     return mtop->nmoltype == 0 || mtop->moltype[0].atoms.haveType;
242 }
243
244 bool gmx_mtop_has_pdbinfo(const gmx_mtop_t *mtop)
245 {
246     if (mtop == nullptr)
247     {
248         return false;
249     }
250     return mtop->nmoltype == 0 || mtop->moltype[0].atoms.havePdbInfo;
251 }
252
253 static void pr_grps(FILE *fp, const char *title, const t_grps grps[], char **grpname[])
254 {
255     int i, j;
256
257     for (i = 0; (i < egcNR); i++)
258     {
259         fprintf(fp, "%s[%-12s] nr=%d, name=[", title, gtypes[i], grps[i].nr);
260         for (j = 0; (j < grps[i].nr); j++)
261         {
262             fprintf(fp, " %s", *(grpname[grps[i].nm_ind[j]]));
263         }
264         fprintf(fp, "]\n");
265     }
266 }
267
268 static void pr_groups(FILE *fp, int indent,
269                       const gmx_groups_t *groups,
270                       gmx_bool bShowNumbers)
271 {
272     int nat_max, i, g;
273
274     pr_grps(fp, "grp", groups->grps, groups->grpname);
275     pr_strings(fp, indent, "grpname", groups->grpname, groups->ngrpname, bShowNumbers);
276
277     pr_indent(fp, indent);
278     fprintf(fp, "groups          ");
279     for (g = 0; g < egcNR; g++)
280     {
281         printf(" %5.5s", gtypes[g]);
282     }
283     printf("\n");
284
285     pr_indent(fp, indent);
286     fprintf(fp, "allocated       ");
287     nat_max = 0;
288     for (g = 0; g < egcNR; g++)
289     {
290         printf(" %5d", groups->ngrpnr[g]);
291         nat_max = std::max(nat_max, groups->ngrpnr[g]);
292     }
293     printf("\n");
294
295     if (nat_max == 0)
296     {
297         pr_indent(fp, indent);
298         fprintf(fp, "groupnr[%5s] =", "*");
299         for (g = 0; g < egcNR; g++)
300         {
301             fprintf(fp, "  %3d ", 0);
302         }
303         fprintf(fp, "\n");
304     }
305     else
306     {
307         for (i = 0; i < nat_max; i++)
308         {
309             pr_indent(fp, indent);
310             fprintf(fp, "groupnr[%5d] =", i);
311             for (g = 0; g < egcNR; g++)
312             {
313                 fprintf(fp, "  %3d ",
314                         groups->grpnr[g] ? groups->grpnr[g][i] : 0);
315             }
316             fprintf(fp, "\n");
317         }
318     }
319 }
320
321 static void pr_moltype(FILE *fp, int indent, const char *title,
322                        const gmx_moltype_t *molt, int n,
323                        const gmx_ffparams_t *ffparams,
324                        gmx_bool bShowNumbers, gmx_bool bShowParameters)
325 {
326     int j;
327
328     indent = pr_title_n(fp, indent, title, n);
329     pr_indent(fp, indent);
330     fprintf(fp, "name=\"%s\"\n", *(molt->name));
331     pr_atoms(fp, indent, "atoms", &(molt->atoms), bShowNumbers);
332     pr_block(fp, indent, "cgs", &molt->cgs, bShowNumbers);
333     pr_blocka(fp, indent, "excls", &molt->excls, bShowNumbers);
334     for (j = 0; (j < F_NRE); j++)
335     {
336         pr_ilist(fp, indent, interaction_function[j].longname,
337                  ffparams->functype, &molt->ilist[j],
338                  bShowNumbers, bShowParameters, ffparams->iparams);
339     }
340 }
341
342 static void pr_molblock(FILE *fp, int indent, const char *title,
343                         const gmx_molblock_t *molb, int n,
344                         const gmx_moltype_t *molt)
345 {
346     indent = pr_title_n(fp, indent, title, n);
347     pr_indent(fp, indent);
348     fprintf(fp, "%-20s = %d \"%s\"\n",
349             "moltype", molb->type, *(molt[molb->type].name));
350     pr_int(fp, indent, "#molecules", molb->nmol);
351     pr_int(fp, indent, "#atoms_mol", molb->natoms_mol);
352     pr_int(fp, indent, "#posres_xA", molb->nposres_xA);
353     if (molb->nposres_xA > 0)
354     {
355         pr_rvecs(fp, indent, "posres_xA", molb->posres_xA, molb->nposres_xA);
356     }
357     pr_int(fp, indent, "#posres_xB", molb->nposres_xB);
358     if (molb->nposres_xB > 0)
359     {
360         pr_rvecs(fp, indent, "posres_xB", molb->posres_xB, molb->nposres_xB);
361     }
362 }
363
364 void pr_mtop(FILE *fp, int indent, const char *title, const gmx_mtop_t *mtop,
365              gmx_bool bShowNumbers, gmx_bool bShowParameters)
366 {
367     int mt, mb, j;
368
369     if (available(fp, mtop, indent, title))
370     {
371         indent = pr_title(fp, indent, title);
372         pr_indent(fp, indent);
373         fprintf(fp, "name=\"%s\"\n", *(mtop->name));
374         pr_int(fp, indent, "#atoms", mtop->natoms);
375         pr_int(fp, indent, "#molblock", mtop->nmolblock);
376         for (mb = 0; mb < mtop->nmolblock; mb++)
377         {
378             pr_molblock(fp, indent, "molblock", &mtop->molblock[mb], mb, mtop->moltype);
379         }
380         pr_str(fp, indent, "bIntermolecularInteractions",
381                gmx::boolToString(mtop->bIntermolecularInteractions));
382         if (mtop->bIntermolecularInteractions)
383         {
384             for (j = 0; (j < F_NRE); j++)
385             {
386                 pr_ilist(fp, indent, interaction_function[j].longname,
387                          mtop->ffparams.functype,
388                          &mtop->intermolecular_ilist[j],
389                          bShowNumbers, bShowParameters, mtop->ffparams.iparams);
390             }
391         }
392         pr_ffparams(fp, indent, "ffparams", &(mtop->ffparams), bShowNumbers);
393         pr_atomtypes(fp, indent, "atomtypes", &(mtop->atomtypes), bShowNumbers);
394         for (mt = 0; mt < mtop->nmoltype; mt++)
395         {
396             pr_moltype(fp, indent, "moltype", &mtop->moltype[mt], mt,
397                        &mtop->ffparams, bShowNumbers, bShowParameters);
398         }
399         pr_groups(fp, indent, &mtop->groups, bShowNumbers);
400     }
401 }
402
403 void pr_top(FILE *fp, int indent, const char *title, const t_topology *top,
404             gmx_bool bShowNumbers, gmx_bool bShowParameters)
405 {
406     if (available(fp, top, indent, title))
407     {
408         indent = pr_title(fp, indent, title);
409         pr_indent(fp, indent);
410         fprintf(fp, "name=\"%s\"\n", *(top->name));
411         pr_atoms(fp, indent, "atoms", &(top->atoms), bShowNumbers);
412         pr_atomtypes(fp, indent, "atomtypes", &(top->atomtypes), bShowNumbers);
413         pr_block(fp, indent, "cgs", &top->cgs, bShowNumbers);
414         pr_block(fp, indent, "mols", &top->mols, bShowNumbers);
415         pr_str(fp, indent, "bIntermolecularInteractions",
416                gmx::boolToString(top->bIntermolecularInteractions));
417         pr_blocka(fp, indent, "excls", &top->excls, bShowNumbers);
418         pr_idef(fp, indent, "idef", &top->idef, bShowNumbers, bShowParameters);
419     }
420 }
421
422 static void cmp_ilist(FILE *fp, int ftype, const t_ilist *il1, const t_ilist *il2)
423 {
424     int  i;
425     char buf[256];
426
427     fprintf(fp, "comparing ilist %s\n", interaction_function[ftype].name);
428     sprintf(buf, "%s->nr", interaction_function[ftype].name);
429     cmp_int(fp, buf, -1, il1->nr, il2->nr);
430     sprintf(buf, "%s->iatoms", interaction_function[ftype].name);
431     if (((il1->nr > 0) && (!il1->iatoms)) ||
432         ((il2->nr > 0) && (!il2->iatoms)) ||
433         ((il1->nr != il2->nr)))
434     {
435         fprintf(fp, "Comparing radically different topologies - %s is different\n",
436                 buf);
437     }
438     else
439     {
440         for (i = 0; (i < il1->nr); i++)
441         {
442             cmp_int(fp, buf, i, il1->iatoms[i], il2->iatoms[i]);
443         }
444     }
445 }
446
447 static void cmp_iparm(FILE *fp, const char *s, t_functype ft,
448                       const t_iparams &ip1, const t_iparams &ip2, real ftol, real abstol)
449 {
450     int      i;
451     gmx_bool bDiff;
452
453     bDiff = FALSE;
454     for (i = 0; i < MAXFORCEPARAM && !bDiff; i++)
455     {
456         bDiff = !equal_real(ip1.generic.buf[i], ip2.generic.buf[i], ftol, abstol);
457     }
458     if (bDiff)
459     {
460         fprintf(fp, "%s1: ", s);
461         pr_iparams(fp, ft, &ip1);
462         fprintf(fp, "%s2: ", s);
463         pr_iparams(fp, ft, &ip2);
464     }
465 }
466
467 static void cmp_iparm_AB(FILE *fp, const char *s, t_functype ft,
468                          const t_iparams &ip1, real ftol, real abstol)
469 {
470     int      nrfpA, nrfpB, p0, i;
471     gmx_bool bDiff;
472
473     /* Normally the first parameter is perturbable */
474     p0    = 0;
475     nrfpA = interaction_function[ft].nrfpA;
476     nrfpB = interaction_function[ft].nrfpB;
477     if (ft == F_PDIHS)
478     {
479         nrfpB = 2;
480     }
481     else if (interaction_function[ft].flags & IF_TABULATED)
482     {
483         /* For tabulated interactions only the second parameter is perturbable */
484         p0    = 1;
485         nrfpB = 1;
486     }
487     bDiff = FALSE;
488     for (i = 0; i < nrfpB && !bDiff; i++)
489     {
490         bDiff = !equal_real(ip1.generic.buf[p0+i], ip1.generic.buf[nrfpA+i], ftol, abstol);
491     }
492     if (bDiff)
493     {
494         fprintf(fp, "%s: ", s);
495         pr_iparams(fp, ft, &ip1);
496     }
497 }
498
499 static void cmp_cmap(FILE *fp, const gmx_cmap_t *cmap1, const gmx_cmap_t *cmap2, real ftol, real abstol)
500 {
501     cmp_int(fp, "cmap ngrid", -1, cmap1->ngrid, cmap2->ngrid);
502     cmp_int(fp, "cmap grid_spacing", -1, cmap1->grid_spacing, cmap2->grid_spacing);
503     if (cmap1->ngrid == cmap2->ngrid &&
504         cmap1->grid_spacing == cmap2->grid_spacing)
505     {
506         int g;
507
508         for (g = 0; g < cmap1->ngrid; g++)
509         {
510             int i;
511
512             fprintf(fp, "comparing cmap %d\n", g);
513
514             for (i = 0; i < 4*cmap1->grid_spacing*cmap1->grid_spacing; i++)
515             {
516                 cmp_real(fp, "", i, cmap1->cmapdata[g].cmap[i], cmap2->cmapdata[g].cmap[i], ftol, abstol);
517             }
518         }
519     }
520 }
521
522 static void cmp_idef(FILE *fp, const t_idef *id1, const t_idef *id2, real ftol, real abstol)
523 {
524     int  i;
525     char buf1[64], buf2[64];
526
527     fprintf(fp, "comparing idef\n");
528     if (id2)
529     {
530         cmp_int(fp, "idef->ntypes", -1, id1->ntypes, id2->ntypes);
531         cmp_int(fp, "idef->atnr",  -1, id1->atnr, id2->atnr);
532         for (i = 0; (i < std::min(id1->ntypes, id2->ntypes)); i++)
533         {
534             sprintf(buf1, "idef->functype[%d]", i);
535             sprintf(buf2, "idef->iparam[%d]", i);
536             cmp_int(fp, buf1, i, (int)id1->functype[i], (int)id2->functype[i]);
537             cmp_iparm(fp, buf2, id1->functype[i],
538                       id1->iparams[i], id2->iparams[i], ftol, abstol);
539         }
540         cmp_real(fp, "fudgeQQ", -1, id1->fudgeQQ, id2->fudgeQQ, ftol, abstol);
541         cmp_cmap(fp, &id1->cmap_grid, &id2->cmap_grid, ftol, abstol);
542         for (i = 0; (i < F_NRE); i++)
543         {
544             cmp_ilist(fp, i, &(id1->il[i]), &(id2->il[i]));
545         }
546     }
547     else
548     {
549         for (i = 0; (i < id1->ntypes); i++)
550         {
551             cmp_iparm_AB(fp, "idef->iparam", id1->functype[i], id1->iparams[i], ftol, abstol);
552         }
553     }
554 }
555
556 static void cmp_block(FILE *fp, const t_block *b1, const t_block *b2, const char *s)
557 {
558     char buf[32];
559
560     fprintf(fp, "comparing block %s\n", s);
561     sprintf(buf, "%s.nr", s);
562     cmp_int(fp, buf, -1, b1->nr, b2->nr);
563 }
564
565 static void cmp_blocka(FILE *fp, const t_blocka *b1, const t_blocka *b2, const char *s)
566 {
567     char buf[32];
568
569     fprintf(fp, "comparing blocka %s\n", s);
570     sprintf(buf, "%s.nr", s);
571     cmp_int(fp, buf, -1, b1->nr, b2->nr);
572     sprintf(buf, "%s.nra", s);
573     cmp_int(fp, buf, -1, b1->nra, b2->nra);
574 }
575
576 void cmp_top(FILE *fp, const t_topology *t1, const t_topology *t2, real ftol, real abstol)
577 {
578     fprintf(fp, "comparing top\n");
579     if (t2)
580     {
581         cmp_idef(fp, &(t1->idef), &(t2->idef), ftol, abstol);
582         cmp_atoms(fp, &(t1->atoms), &(t2->atoms), ftol, abstol);
583         cmp_block(fp, &t1->cgs, &t2->cgs, "cgs");
584         cmp_block(fp, &t1->mols, &t2->mols, "mols");
585         cmp_bool(fp, "bIntermolecularInteractions", -1, t1->bIntermolecularInteractions, t2->bIntermolecularInteractions);
586         cmp_blocka(fp, &t1->excls, &t2->excls, "excls");
587     }
588     else
589     {
590         cmp_idef(fp, &(t1->idef), nullptr, ftol, abstol);
591         cmp_atoms(fp, &(t1->atoms), nullptr, ftol, abstol);
592     }
593 }
594
595 void cmp_groups(FILE *fp, const gmx_groups_t *g0, const gmx_groups_t *g1,
596                 int natoms0, int natoms1)
597 {
598     int  i, j;
599     char buf[32];
600
601     fprintf(fp, "comparing groups\n");
602
603     for (i = 0; i < egcNR; i++)
604     {
605         sprintf(buf, "grps[%d].nr", i);
606         cmp_int(fp, buf, -1, g0->grps[i].nr, g1->grps[i].nr);
607         if (g0->grps[i].nr == g1->grps[i].nr)
608         {
609             for (j = 0; j < g0->grps[i].nr; j++)
610             {
611                 sprintf(buf, "grps[%d].name[%d]", i, j);
612                 cmp_str(fp, buf, -1,
613                         *g0->grpname[g0->grps[i].nm_ind[j]],
614                         *g1->grpname[g1->grps[i].nm_ind[j]]);
615             }
616         }
617         cmp_int(fp, "ngrpnr", i, g0->ngrpnr[i], g1->ngrpnr[i]);
618         if (g0->ngrpnr[i] == g1->ngrpnr[i] && natoms0 == natoms1 &&
619             (g0->grpnr[i] != nullptr || g1->grpnr[i] != nullptr))
620         {
621             for (j = 0; j < natoms0; j++)
622             {
623                 cmp_int(fp, gtypes[i], j, ggrpnr(g0, i, j), ggrpnr(g1, i, j));
624             }
625         }
626     }
627     /* We have compared the names in the groups lists,
628      * so we can skip the grpname list comparison.
629      */
630 }