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) 2011,2014, 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! */
41 #include "hackblock.h"
42 #include "gromacs/utility/smalloc.h"
43 #include "gromacs/math/vec.h"
46 /* these MUST correspond to the enum in hackblock.h */
47 const char *btsNames[ebtsNR] = { "bonds", "angles", "dihedrals", "impropers", "exclusions", "cmap" };
48 const int btsNiatoms[ebtsNR] = { 2, 3, 4, 4, 2, 5 };
50 static void free_t_bonded(t_rbonded *rb)
54 for (i = 0; i < MAXATOMLIST; i++)
61 static void free_t_bondeds(t_rbondeds *rbs)
65 for (i = 0; i < rbs->nb; i++)
67 free_t_bonded(&rbs->b[i]);
74 void free_t_restp(int nrtp, t_restp **rtp)
78 for (i = 0; i < nrtp; i++)
80 sfree((*rtp)[i].resname);
81 sfree((*rtp)[i].atom);
82 for (j = 0; j < (*rtp)[i].natom; j++)
84 sfree(*(*rtp)[i].atomname[j]);
85 sfree((*rtp)[i].atomname[j]);
87 sfree((*rtp)[i].atomname);
88 sfree((*rtp)[i].cgnr);
89 for (j = 0; j < ebtsNR; j++)
91 free_t_bondeds(&(*rtp)[i].rb[j]);
97 void free_t_hack(int nh, t_hack **h)
101 for (i = 0; i < nh; i++)
103 sfree((*h)[i].oname);
104 sfree((*h)[i].nname);
106 for (j = 0; j < 4; j++)
115 void free_t_hackblock(int nhb, t_hackblock **hb)
119 for (i = 0; i < nhb; i++)
121 sfree((*hb)[i].name);
122 free_t_hack((*hb)[i].nhack, &(*hb)[i].hack);
123 for (j = 0; j < ebtsNR; j++)
125 free_t_bondeds(&(*hb)[i].rb[j]);
131 void clear_t_hackblock(t_hackblock *hb)
139 for (i = 0; i < ebtsNR; i++)
146 void clear_t_hack(t_hack *hack)
157 for (i = 0; i < 4; i++)
161 for (i = 0; i < DIM; i++)
163 hack->newx[i] = NOTSET;
167 #define safe_strdup(str) ((str != NULL) ? strdup(str) : NULL)
169 static void copy_t_rbonded(t_rbonded *s, t_rbonded *d)
173 for (i = 0; i < MAXATOMLIST; i++)
175 d->a[i] = safe_strdup(s->a[i]);
177 d->s = safe_strdup(s->s);
181 static gmx_bool contains_char(t_rbonded *s, char c)
187 for (i = 0; i < MAXATOMLIST; i++)
189 if (s->a[i] && s->a[i][0] == c)
198 gmx_bool rbonded_atoms_exist_in_list(t_rbonded *b, t_rbonded blist[], int nlist, int natoms)
201 gmx_bool matchFound = FALSE;
204 for (i = 0; i < nlist && !matchFound; i++)
207 for (k = 0; k < natoms && atomsMatch; k++)
209 atomsMatch = atomsMatch && !strcmp(b->a[k], blist[i].a[k]);
211 /* Try reverse if forward match did not work */
215 for (k = 0; k < natoms && atomsMatch; k++)
217 atomsMatch = atomsMatch && !strcmp(b->a[k], blist[i].a[natoms-1-k]);
220 matchFound = atomsMatch;
225 gmx_bool merge_t_bondeds(t_rbondeds s[], t_rbondeds d[], gmx_bool bMin, gmx_bool bPlus)
228 gmx_bool bBondsRemoved;
230 bBondsRemoved = FALSE;
231 for (i = 0; i < ebtsNR; i++)
236 srenew(d[i].b, d[i].nb + s[i].nb);
237 for (j = 0; j < s[i].nb; j++)
239 /* Check if this bonded string already exists before adding.
240 * We are merging from the main rtp to the hackblocks, so this
241 * will mean the hackblocks overwrite the man rtp, as intended.
243 if (!rbonded_atoms_exist_in_list(&s[i].b[j], d[i].b, d[i].nb, btsNiatoms[i]))
245 if (!(bMin && contains_char(&s[i].b[j], '-'))
246 && !(bPlus && contains_char(&s[i].b[j], '+')))
248 copy_t_rbonded(&s[i].b[j], &d[i].b[ d[i].nb ]);
251 else if (i == ebtsBONDS)
253 bBondsRemoved = TRUE;
259 return bBondsRemoved;
262 void copy_t_restp(t_restp *s, t_restp *d)
267 d->resname = safe_strdup(s->resname);
268 snew(d->atom, s->natom);
269 for (i = 0; i < s->natom; i++)
271 d->atom[i] = s->atom[i];
273 snew(d->atomname, s->natom);
274 for (i = 0; i < s->natom; i++)
276 snew(d->atomname[i], 1);
277 *d->atomname[i] = safe_strdup(*s->atomname[i]);
279 snew(d->cgnr, s->natom);
280 for (i = 0; i < s->natom; i++)
282 d->cgnr[i] = s->cgnr[i];
284 for (i = 0; i < ebtsNR; i++)
286 d->rb[i].type = s->rb[i].type;
290 merge_t_bondeds(s->rb, d->rb, FALSE, FALSE);
293 void copy_t_hack(t_hack *s, t_hack *d)
298 d->oname = safe_strdup(s->oname);
299 d->nname = safe_strdup(s->nname);
303 *(d->atom) = *(s->atom);
309 for (i = 0; i < 4; i++)
311 d->a[i] = safe_strdup(s->a[i]);
313 copy_rvec(s->newx, d->newx);
316 void merge_hacks_lo(int ns, t_hack *s, int *nd, t_hack **d)
322 srenew(*d, *nd + ns);
323 for (i = 0; i < ns; i++)
325 copy_t_hack(&s[i], &(*d)[*nd + i]);
331 void merge_hacks(t_hackblock *s, t_hackblock *d)
333 merge_hacks_lo(s->nhack, s->hack, &d->nhack, &d->hack);
336 void merge_t_hackblock(t_hackblock *s, t_hackblock *d)
339 merge_t_bondeds(s->rb, d->rb, FALSE, FALSE);
342 void copy_t_hackblock(t_hackblock *s, t_hackblock *d)
347 d->name = safe_strdup(s->name);
350 for (i = 0; i < ebtsNR; i++)
355 merge_t_hackblock(s, d);
360 void dump_hb(FILE *out, int nres, t_hackblock hb[])
364 #define SS(s) (s) ? (s) : "-"
365 #define SA(s) (s) ? "+" : ""
366 fprintf(out, "t_hackblock\n");
367 for (i = 0; i < nres; i++)
369 fprintf(out, "%3d %4s %2d %2d\n",
370 i, SS(hb[i].name), hb[i].nhack, hb[i].maxhack);
373 for (j = 0; j < hb[i].nhack; j++)
375 fprintf(out, "%d: %d %4s %4s %1s %2d %d %4s %4s %4s %4s\n",
377 SS(hb[i].hack[j].oname), SS(hb[i].hack[j].nname),
378 SA(hb[i].hack[j].atom), hb[i].hack[j].tp, hb[i].hack[j].cgnr,
379 SS(hb[i].hack[j].AI), SS(hb[i].hack[j].AJ),
380 SS(hb[i].hack[j].AK), SS(hb[i].hack[j].AL) );
383 for (j = 0; j < ebtsNR; j++)
387 fprintf(out, " %c %d:", btsNames[j][0], hb[i].rb[j].nb);
388 for (k = 0; k < hb[i].rb[j].nb; k++)
391 for (l = 0; l < btsNiatoms[j]; l++)
393 fprintf(out, " %s", hb[i].rb[j].b[k].a[l]);
395 fprintf(out, " %s]", SS(hb[i].rb[j].b[k].s));
397 fprintf(out, " Entry matched: %s\n", yesno_names[hb[i].rb[j].b[k].match]);
406 void init_t_protonate(t_protonate *protonate)
408 protonate->bInit = FALSE;