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-2008, The GROMACS development team.
6 * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, 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.
37 /* This file is completely threadsafe - keep it that way! */
48 #include "gromacs/fileio/confio.h"
49 #include "gromacs/gmxpreprocess/fflibutil.h"
50 #include "gromacs/gmxpreprocess/gpp_atomtype.h"
51 #include "gromacs/gmxpreprocess/gpp_nextnb.h"
52 #include "gromacs/gmxpreprocess/grompp_impl.h"
53 #include "gromacs/gmxpreprocess/notset.h"
54 #include "gromacs/gmxpreprocess/pdb2top.h"
55 #include "gromacs/gmxpreprocess/toppush.h"
56 #include "gromacs/math/utilities.h"
57 #include "gromacs/math/vec.h"
58 #include "gromacs/mdtypes/md_enums.h"
59 #include "gromacs/utility/cstringutil.h"
60 #include "gromacs/utility/fatalerror.h"
61 #include "gromacs/utility/futil.h"
62 #include "gromacs/utility/smalloc.h"
64 static void rd_nm2type_file(const std::string
&filename
, int *nnm
, t_nm2type
**nmp
)
68 char libfilename
[128];
69 char format
[128], f1
[128];
70 char buf
[1024], elem
[16], type
[16], nbbuf
[16], **newbuf
;
71 int i
, nb
, nnnm
, line
= 1;
73 t_nm2type
*nm2t
= nullptr;
75 fp
= fflib_open(filename
);
78 gmx_fatal(FARGS
, "Can not find %s in library directory", filename
.c_str());
85 /* Read a line from the file */
86 bCont
= (fgets2(buf
, 1023, fp
) != nullptr);
92 if (sscanf(buf
, "%s%s%lf%lf%d", elem
, type
, &qq
, &mm
, &nb
) == 5)
94 /* If we can read the first four, there probably is more */
96 snew(nm2t
[nnnm
].blen
, nb
);
100 strcpy(format
, "%*s%*s%*s%*s%*s");
101 for (i
= 0; (i
< nb
); i
++)
103 /* Complicated format statement */
106 if (sscanf(buf
, f1
, nbbuf
, &(nm2t
[nnnm
].blen
[i
])) != 2)
108 gmx_fatal(FARGS
, "Error on line %d of %s", line
, libfilename
);
110 newbuf
[i
] = gmx_strdup(nbbuf
);
111 strcat(format
, "%*s%*s");
118 nm2t
[nnnm
].elem
= gmx_strdup(elem
);
119 nm2t
[nnnm
].type
= gmx_strdup(type
);
122 nm2t
[nnnm
].nbonds
= nb
;
123 nm2t
[nnnm
].bond
= newbuf
;
136 t_nm2type
*rd_nm2type(const char *ffdir
, int *nnm
)
138 std::vector
<std::string
> ff
= fflib_search_file_end(ffdir
, ".n2t", FALSE
);
140 t_nm2type
*nm
= nullptr;
141 for (const auto &filename
: ff
)
143 rd_nm2type_file(filename
, nnm
, &nm
);
148 void dump_nm2type(FILE *fp
, int nnm
, t_nm2type nm2t
[])
152 fprintf(fp
, "; nm2type database\n");
153 for (i
= 0; (i
< nnm
); i
++)
155 fprintf(fp
, "%-8s %-8s %8.4f %8.4f %-4d",
156 nm2t
[i
].elem
, nm2t
[i
].type
,
157 nm2t
[i
].q
, nm2t
[i
].m
, nm2t
[i
].nbonds
);
158 for (j
= 0; (j
< nm2t
[i
].nbonds
); j
++)
160 fprintf(fp
, " %-5s %6.4f", nm2t
[i
].bond
[j
], nm2t
[i
].blen
[j
]);
167 ematchNone
, ematchWild
, ematchElem
, ematchExact
, ematchNR
170 static int match_str(const char *atom
, const char *template_string
)
172 if (!atom
|| !template_string
)
176 else if (gmx_strcasecmp(atom
, template_string
) == 0)
180 else if (atom
[0] == template_string
[0])
184 else if (strcmp(template_string
, "*") == 0)
194 int nm2type(int nnm
, t_nm2type nm2t
[], t_symtab
*tab
, t_atoms
*atoms
,
195 PreprocessingAtomTypes
*atype
, int *nbonds
, InteractionsOfType
*bonds
)
199 int nresolved
, nb
, maxbond
, nqual
[2][ematchNR
];
200 int *bbb
, *n_mask
, *m_mask
, **match
;
201 char *aname_i
, *aname_n
;
204 for (int i
= 0; (i
< atoms
->nr
); i
++)
206 maxbond
= std::max(maxbond
, nbonds
[i
]);
210 fprintf(debug
, "Max number of bonds per atom is %d\n", maxbond
);
213 snew(n_mask
, maxbond
);
214 snew(m_mask
, maxbond
);
215 snew(match
, maxbond
);
216 for (int i
= 0; (i
< maxbond
); i
++)
218 snew(match
[i
], maxbond
);
222 for (int i
= 0; (i
< atoms
->nr
); i
++)
224 aname_i
= *atoms
->atomname
[i
];
226 for (const auto &bond
: bonds
->interactionTypes
)
241 gmx_fatal(FARGS
, "Counting number of bonds nb = %d, nbonds[%d] = %d",
246 fprintf(debug
, "%4s has bonds to", aname_i
);
247 for (int j
= 0; (j
< nb
); j
++)
249 fprintf(debug
, " %4s", *atoms
->atomname
[bbb
[j
]]);
251 fprintf(debug
, "\n");
254 for (int k
= 0; (k
< ematchNR
); k
++)
259 /* First check for names */
260 for (int k
= 0; (k
< nnm
); k
++)
262 if (nm2t
[k
].nbonds
== nb
)
264 int im
= match_str(*atoms
->atomname
[i
], nm2t
[k
].elem
);
267 for (int j
= 0; (j
< ematchNR
); j
++)
272 /* Fill a matrix with matching quality */
273 for (int m
= 0; (m
< nb
); m
++)
275 const char *aname_m
= *atoms
->atomname
[bbb
[m
]];
276 for (int n
= 0; (n
< nb
); n
++)
278 aname_n
= nm2t
[k
].bond
[n
];
279 match
[m
][n
] = match_str(aname_m
, aname_n
);
282 /* Now pick the best matches */
283 for (int m
= 0; (m
< nb
); m
++)
288 for (int j
= ematchNR
-1; (j
> 0); j
--)
290 for (int m
= 0; (m
< nb
); m
++)
292 for (int n
= 0; (n
< nb
); n
++)
294 if ((n_mask
[n
] == 0) &&
305 if ((nqual
[cur
][ematchExact
]+
306 nqual
[cur
][ematchElem
]+
307 nqual
[cur
][ematchWild
]) == nb
)
309 if ((nqual
[cur
][ematchExact
] > nqual
[prev
][ematchExact
]) ||
311 ((nqual
[cur
][ematchExact
] == nqual
[prev
][ematchExact
]) &&
312 (nqual
[cur
][ematchElem
] > nqual
[prev
][ematchElem
])) ||
314 ((nqual
[cur
][ematchExact
] == nqual
[prev
][ematchExact
]) &&
315 (nqual
[cur
][ematchElem
] == nqual
[prev
][ematchElem
]) &&
316 (nqual
[cur
][ematchWild
] > nqual
[prev
][ematchWild
])))
330 double qq
= nm2t
[best
].q
;
331 double mm
= nm2t
[best
].m
;
332 const char *type
= nm2t
[best
].type
;
335 if ((k
= atype
->atomTypeFromName(type
)) == NOTSET
)
337 atoms
->atom
[i
].qB
= alpha
;
338 atoms
->atom
[i
].m
= atoms
->atom
[i
].mB
= mm
;
339 k
= atype
->addType(tab
, atoms
->atom
[i
], type
, InteractionOfType({}, {}),
340 atoms
->atom
[i
].type
, atomnr
);
342 atoms
->atom
[i
].type
= k
;
343 atoms
->atom
[i
].typeB
= k
;
344 atoms
->atom
[i
].q
= qq
;
345 atoms
->atom
[i
].qB
= qq
;
346 atoms
->atom
[i
].m
= mm
;
347 atoms
->atom
[i
].mB
= mm
;
352 fprintf(stderr
, "Can not find forcefield for atom %s-%d with %d bonds\n",
353 *atoms
->atomname
[i
], i
+1, nb
);