Move ifunc.* to topology/
[gromacs.git] / src / gromacs / gmxpreprocess / vsite_parm.cpp
blob5a6332d1785109d2f6fd4f0465a080cbbafeb220
1 /*
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, 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 #include "gmxpre.h"
39 #include "vsite_parm.h"
41 #include <stdio.h>
42 #include <string.h>
44 #include <cmath>
46 #include <algorithm>
48 #include "gromacs/gmxpreprocess/add_par.h"
49 #include "gromacs/gmxpreprocess/notset.h"
50 #include "gromacs/gmxpreprocess/resall.h"
51 #include "gromacs/gmxpreprocess/toputil.h"
52 #include "gromacs/math/units.h"
53 #include "gromacs/math/vec.h"
54 #include "gromacs/mdtypes/md_enums.h"
55 #include "gromacs/topology/ifunc.h"
56 #include "gromacs/topology/topology.h"
57 #include "gromacs/utility/cstringutil.h"
58 #include "gromacs/utility/fatalerror.h"
59 #include "gromacs/utility/gmxassert.h"
60 #include "gromacs/utility/smalloc.h"
61 #include "gromacs/utility/stringutil.h"
63 typedef struct {
64 t_iatom a[4];
65 real c;
66 t_iatom &ai() { return a[0]; }
67 t_iatom &aj() { return a[1]; }
68 t_iatom &ak() { return a[2]; }
69 t_iatom &al() { return a[3]; }
70 } t_mybonded;
72 typedef struct {
73 int ftype;
74 t_param *param;
75 } vsitebondparam_t;
77 typedef struct {
78 int nr;
79 int ftype;
80 vsitebondparam_t *vsbp;
81 } at2vsitebond_t;
83 typedef struct {
84 int nr;
85 int *aj;
86 } at2vsitecon_t;
88 static int vsite_bond_nrcheck(int ftype)
90 int nrcheck;
92 if ((interaction_function[ftype].flags & (IF_BTYPE | IF_CONSTRAINT | IF_ATYPE)) || (ftype == F_IDIHS))
94 nrcheck = NRAL(ftype);
96 else
98 nrcheck = 0;
101 return nrcheck;
104 static void enter_bonded(int nratoms, int *nrbonded, t_mybonded **bondeds,
105 t_param *param)
107 int j;
109 srenew(*bondeds, *nrbonded+1);
111 /* copy atom numbers */
112 for (j = 0; j < nratoms; j++)
114 (*bondeds)[*nrbonded].a[j] = param->a[j];
116 /* copy parameter */
117 (*bondeds)[*nrbonded].c = param->c0();
119 (*nrbonded)++;
122 static void get_bondeds(int nrat, t_iatom atoms[],
123 at2vsitebond_t *at2vb,
124 int *nrbond, t_mybonded **bonds,
125 int *nrang, t_mybonded **angles,
126 int *nridih, t_mybonded **idihs )
128 int k, i, ftype, nrcheck;
129 t_param *param;
131 for (k = 0; k < nrat; k++)
133 for (i = 0; i < at2vb[atoms[k]].nr; i++)
135 ftype = at2vb[atoms[k]].vsbp[i].ftype;
136 param = at2vb[atoms[k]].vsbp[i].param;
137 nrcheck = vsite_bond_nrcheck(ftype);
138 /* abuse nrcheck to see if we're adding bond, angle or idih */
139 switch (nrcheck)
141 case 2: enter_bonded(nrcheck, nrbond, bonds, param); break;
142 case 3: enter_bonded(nrcheck, nrang, angles, param); break;
143 case 4: enter_bonded(nrcheck, nridih, idihs, param); break;
149 static at2vsitebond_t *make_at2vsitebond(int natoms, t_params plist[])
151 gmx_bool *bVSI;
152 int ftype, i, j, nrcheck, nr;
153 t_iatom *aa;
154 at2vsitebond_t *at2vb;
156 snew(at2vb, natoms);
158 snew(bVSI, natoms);
159 for (ftype = 0; (ftype < F_NRE); ftype++)
161 if ((interaction_function[ftype].flags & IF_VSITE) && ftype != F_VSITEN)
163 for (i = 0; (i < plist[ftype].nr); i++)
165 for (j = 0; j < NRAL(ftype); j++)
167 bVSI[plist[ftype].param[i].a[j]] = TRUE;
173 for (ftype = 0; (ftype < F_NRE); ftype++)
175 nrcheck = vsite_bond_nrcheck(ftype);
176 if (nrcheck > 0)
178 for (i = 0; (i < plist[ftype].nr); i++)
180 aa = plist[ftype].param[i].a;
181 for (j = 0; j < nrcheck; j++)
183 if (bVSI[aa[j]])
185 nr = at2vb[aa[j]].nr;
186 if (nr % 10 == 0)
188 srenew(at2vb[aa[j]].vsbp, nr+10);
190 at2vb[aa[j]].vsbp[nr].ftype = ftype;
191 at2vb[aa[j]].vsbp[nr].param = &plist[ftype].param[i];
192 at2vb[aa[j]].nr++;
198 sfree(bVSI);
200 return at2vb;
203 static void done_at2vsitebond(int natoms, at2vsitebond_t *at2vb)
205 int i;
207 for (i = 0; i < natoms; i++)
209 if (at2vb[i].nr)
211 sfree(at2vb[i].vsbp);
214 sfree(at2vb);
217 static at2vsitecon_t *make_at2vsitecon(int natoms, t_params plist[])
219 gmx_bool *bVSI;
220 int ftype, i, j, ai, aj, nr;
221 at2vsitecon_t *at2vc;
223 snew(at2vc, natoms);
225 snew(bVSI, natoms);
226 for (ftype = 0; (ftype < F_NRE); ftype++)
228 if ((interaction_function[ftype].flags & IF_VSITE) && ftype != F_VSITEN)
230 for (i = 0; (i < plist[ftype].nr); i++)
232 for (j = 0; j < NRAL(ftype); j++)
234 bVSI[plist[ftype].param[i].a[j]] = TRUE;
240 for (ftype = 0; (ftype < F_NRE); ftype++)
242 if (interaction_function[ftype].flags & IF_CONSTRAINT)
244 for (i = 0; (i < plist[ftype].nr); i++)
246 ai = plist[ftype].param[i].ai();
247 aj = plist[ftype].param[i].aj();
248 if (bVSI[ai] && bVSI[aj])
250 /* Store forward direction */
251 nr = at2vc[ai].nr;
252 if (nr % 10 == 0)
254 srenew(at2vc[ai].aj, nr+10);
256 at2vc[ai].aj[nr] = aj;
257 at2vc[ai].nr++;
258 /* Store backward direction */
259 nr = at2vc[aj].nr;
260 if (nr % 10 == 0)
262 srenew(at2vc[aj].aj, nr+10);
264 at2vc[aj].aj[nr] = ai;
265 at2vc[aj].nr++;
270 sfree(bVSI);
272 return at2vc;
275 static void done_at2vsitecon(int natoms, at2vsitecon_t *at2vc)
277 int i;
279 for (i = 0; i < natoms; i++)
281 if (at2vc[i].nr)
283 sfree(at2vc[i].aj);
286 sfree(at2vc);
289 /* for debug */
290 static void print_bad(FILE *fp,
291 int nrbond, t_mybonded *bonds,
292 int nrang, t_mybonded *angles,
293 int nridih, t_mybonded *idihs )
295 int i;
297 if (nrbond)
299 fprintf(fp, "bonds:");
300 for (i = 0; i < nrbond; i++)
302 fprintf(fp, " %d-%d (%g)",
303 bonds[i].ai()+1, bonds[i].aj()+1, bonds[i].c);
305 fprintf(fp, "\n");
307 if (nrang)
309 fprintf(fp, "angles:");
310 for (i = 0; i < nrang; i++)
312 fprintf(fp, " %d-%d-%d (%g)",
313 angles[i].ai()+1, angles[i].aj()+1,
314 angles[i].ak()+1, angles[i].c);
316 fprintf(fp, "\n");
318 if (nridih)
320 fprintf(fp, "idihs:");
321 for (i = 0; i < nridih; i++)
323 fprintf(fp, " %d-%d-%d-%d (%g)",
324 idihs[i].ai()+1, idihs[i].aj()+1,
325 idihs[i].ak()+1, idihs[i].al()+1, idihs[i].c);
327 fprintf(fp, "\n");
331 static void print_param(FILE *fp, int ftype, int i, t_param *param)
333 static int pass = 0;
334 static int prev_ftype = NOTSET;
335 static int prev_i = NOTSET;
336 int j;
338 if ( (ftype != prev_ftype) || (i != prev_i) )
340 pass = 0;
341 prev_ftype = ftype;
342 prev_i = i;
344 fprintf(fp, "(%d) plist[%s].param[%d]",
345 pass, interaction_function[ftype].name, i);
346 for (j = 0; j < NRFP(ftype); j++)
348 fprintf(fp, ".c[%d]=%g ", j, param->c[j]);
350 fprintf(fp, "\n");
351 pass++;
354 static real get_bond_length(int nrbond, t_mybonded bonds[],
355 t_iatom ai, t_iatom aj)
357 int i;
358 real bondlen;
360 bondlen = NOTSET;
361 for (i = 0; i < nrbond && (bondlen == NOTSET); i++)
363 /* check both ways */
364 if ( ( (ai == bonds[i].ai()) && (aj == bonds[i].aj()) ) ||
365 ( (ai == bonds[i].aj()) && (aj == bonds[i].ai()) ) )
367 bondlen = bonds[i].c; /* note: bonds[i].c might be NOTSET */
370 return bondlen;
373 static real get_angle(int nrang, t_mybonded angles[],
374 t_iatom ai, t_iatom aj, t_iatom ak)
376 int i;
377 real angle;
379 angle = NOTSET;
380 for (i = 0; i < nrang && (angle == NOTSET); i++)
382 /* check both ways */
383 if ( ( (ai == angles[i].ai()) && (aj == angles[i].aj()) && (ak == angles[i].ak()) ) ||
384 ( (ai == angles[i].ak()) && (aj == angles[i].aj()) && (ak == angles[i].ai()) ) )
386 angle = DEG2RAD*angles[i].c;
389 return angle;
392 static char *get_atomtype_name_AB(t_atom *atom, gpp_atomtype_t atype)
394 char *name;
396 name = get_atomtype_name(atom->type, atype);
398 /* When using the decoupling option, atom types are changed
399 * to decoupled for the non-bonded interactions, but the virtual
400 * sites constructions should be based on the "normal" interactions.
401 * So we return the state B atom type name if the state A atom
402 * type is the decoupled one. We should actually check for the atom
403 * type number, but that's not passed here. So we check for
404 * the decoupled atom type name. This should not cause trouble
405 * as this code is only used for topologies with v-sites without
406 * parameters generated by pdb2gmx.
408 if (strcmp(name, "decoupled") == 0)
410 name = get_atomtype_name(atom->typeB, atype);
413 return name;
416 static gmx_bool calc_vsite3_param(gpp_atomtype_t atype,
417 t_param *param, t_atoms *at,
418 int nrbond, t_mybonded *bonds,
419 int nrang, t_mybonded *angles )
421 /* i = virtual site | ,k
422 * j = 1st bonded heavy atom | i-j
423 * k,l = 2nd bonded atoms | `l
426 gmx_bool bXH3, bError;
427 real bjk, bjl, a = -1, b = -1;
428 /* check if this is part of a NH3 , NH2-umbrella or CH3 group,
429 * i.e. if atom k and l are dummy masses (MNH* or MCH3*) */
430 if (debug)
432 int i;
433 for (i = 0; i < 4; i++)
435 fprintf(debug, "atom %d type %s ",
436 param->a[i]+1,
437 get_atomtype_name_AB(&at->atom[param->a[i]], atype));
439 fprintf(debug, "\n");
441 bXH3 =
442 ( (gmx_strncasecmp(get_atomtype_name_AB(&at->atom[param->ak()], atype), "MNH", 3) == 0) &&
443 (gmx_strncasecmp(get_atomtype_name_AB(&at->atom[param->al()], atype), "MNH", 3) == 0) ) ||
444 ( (gmx_strncasecmp(get_atomtype_name_AB(&at->atom[param->ak()], atype), "MCH3", 4) == 0) &&
445 (gmx_strncasecmp(get_atomtype_name_AB(&at->atom[param->al()], atype), "MCH3", 4) == 0) );
447 bjk = get_bond_length(nrbond, bonds, param->aj(), param->ak());
448 bjl = get_bond_length(nrbond, bonds, param->aj(), param->al());
449 bError = (bjk == NOTSET) || (bjl == NOTSET);
450 if (bXH3)
452 /* now we get some XH2/XH3 group specific construction */
453 /* note: we call the heavy atom 'C' and the X atom 'N' */
454 real bMM, bCM, bCN, bNH, aCNH, dH, rH, dM, rM;
455 int aN;
457 /* check if bonds from heavy atom (j) to dummy masses (k,l) are equal: */
458 bError = bError || (bjk != bjl);
460 /* the X atom (C or N) in the XH2/XH3 group is the first after the masses: */
461 aN = std::max(param->ak(), param->al())+1;
463 /* get common bonds */
464 bMM = get_bond_length(nrbond, bonds, param->ak(), param->al());
465 bCM = bjk;
466 bCN = get_bond_length(nrbond, bonds, param->aj(), aN);
467 bError = bError || (bMM == NOTSET) || (bCN == NOTSET);
469 /* calculate common things */
470 rM = 0.5*bMM;
471 dM = std::sqrt( sqr(bCM) - sqr(rM) );
473 /* are we dealing with the X atom? */
474 if (param->ai() == aN)
476 /* this is trivial */
477 a = b = 0.5 * bCN/dM;
480 else
482 /* get other bondlengths and angles: */
483 bNH = get_bond_length(nrbond, bonds, aN, param->ai());
484 aCNH = get_angle (nrang, angles, param->aj(), aN, param->ai());
485 bError = bError || (bNH == NOTSET) || (aCNH == NOTSET);
487 /* calculate */
488 dH = bCN - bNH * cos(aCNH);
489 rH = bNH * sin(aCNH);
491 a = 0.5 * ( dH/dM + rH/rM );
492 b = 0.5 * ( dH/dM - rH/rM );
495 else
497 gmx_fatal(FARGS, "calc_vsite3_param not implemented for the general case "
498 "(atom %d)", param->ai()+1);
501 param->c0() = a;
502 param->c1() = b;
504 if (debug)
506 fprintf(debug, "params for vsite3 %d: %g %g\n",
507 param->ai()+1, param->c0(), param->c1());
510 return bError;
513 static gmx_bool calc_vsite3fd_param(t_param *param,
514 int nrbond, t_mybonded *bonds,
515 int nrang, t_mybonded *angles)
517 /* i = virtual site | ,k
518 * j = 1st bonded heavy atom | i-j
519 * k,l = 2nd bonded atoms | `l
522 gmx_bool bError;
523 real bij, bjk, bjl, aijk, aijl, rk, rl;
525 bij = get_bond_length(nrbond, bonds, param->ai(), param->aj());
526 bjk = get_bond_length(nrbond, bonds, param->aj(), param->ak());
527 bjl = get_bond_length(nrbond, bonds, param->aj(), param->al());
528 aijk = get_angle (nrang, angles, param->ai(), param->aj(), param->ak());
529 aijl = get_angle (nrang, angles, param->ai(), param->aj(), param->al());
530 bError = (bij == NOTSET) || (bjk == NOTSET) || (bjl == NOTSET) ||
531 (aijk == NOTSET) || (aijl == NOTSET);
533 rk = bjk * sin(aijk);
534 rl = bjl * sin(aijl);
535 param->c0() = rk / (rk + rl);
536 param->c1() = -bij; /* 'bond'-length for fixed distance vsite */
538 if (debug)
540 fprintf(debug, "params for vsite3fd %d: %g %g\n",
541 param->ai()+1, param->c0(), param->c1());
543 return bError;
546 static gmx_bool calc_vsite3fad_param(t_param *param,
547 int nrbond, t_mybonded *bonds,
548 int nrang, t_mybonded *angles)
550 /* i = virtual site |
551 * j = 1st bonded heavy atom | i-j
552 * k = 2nd bonded heavy atom | `k-l
553 * l = 3d bonded heavy atom |
556 gmx_bool bSwapParity, bError;
557 real bij, aijk;
559 bSwapParity = ( param->c1() == -1 );
561 bij = get_bond_length(nrbond, bonds, param->ai(), param->aj());
562 aijk = get_angle (nrang, angles, param->ai(), param->aj(), param->ak());
563 bError = (bij == NOTSET) || (aijk == NOTSET);
565 param->c1() = bij; /* 'bond'-length for fixed distance vsite */
566 param->c0() = RAD2DEG*aijk; /* 'bond'-angle for fixed angle vsite */
568 if (bSwapParity)
570 param->c0() = 360 - param->c0();
573 if (debug)
575 fprintf(debug, "params for vsite3fad %d: %g %g\n",
576 param->ai()+1, param->c0(), param->c1());
578 return bError;
581 static gmx_bool calc_vsite3out_param(gpp_atomtype_t atype,
582 t_param *param, t_atoms *at,
583 int nrbond, t_mybonded *bonds,
584 int nrang, t_mybonded *angles)
586 /* i = virtual site | ,k
587 * j = 1st bonded heavy atom | i-j
588 * k,l = 2nd bonded atoms | `l
589 * NOTE: i is out of the j-k-l plane!
592 gmx_bool bXH3, bError, bSwapParity;
593 real bij, bjk, bjl, aijk, aijl, akjl, pijk, pijl, a, b, c;
595 /* check if this is part of a NH2-umbrella, NH3 or CH3 group,
596 * i.e. if atom k and l are dummy masses (MNH* or MCH3*) */
597 if (debug)
599 int i;
600 for (i = 0; i < 4; i++)
602 fprintf(debug, "atom %d type %s ",
603 param->a[i]+1, get_atomtype_name_AB(&at->atom[param->a[i]], atype));
605 fprintf(debug, "\n");
607 bXH3 =
608 ( (gmx_strncasecmp(get_atomtype_name_AB(&at->atom[param->ak()], atype), "MNH", 3) == 0) &&
609 (gmx_strncasecmp(get_atomtype_name_AB(&at->atom[param->al()], atype), "MNH", 3) == 0) ) ||
610 ( (gmx_strncasecmp(get_atomtype_name_AB(&at->atom[param->ak()], atype), "MCH3", 4) == 0) &&
611 (gmx_strncasecmp(get_atomtype_name_AB(&at->atom[param->al()], atype), "MCH3", 4) == 0) );
613 /* check if construction parity must be swapped */
614 bSwapParity = ( param->c1() == -1 );
616 bjk = get_bond_length(nrbond, bonds, param->aj(), param->ak());
617 bjl = get_bond_length(nrbond, bonds, param->aj(), param->al());
618 bError = (bjk == NOTSET) || (bjl == NOTSET);
619 if (bXH3)
621 /* now we get some XH3 group specific construction */
622 /* note: we call the heavy atom 'C' and the X atom 'N' */
623 real bMM, bCM, bCN, bNH, aCNH, dH, rH, rHx, rHy, dM, rM;
624 int aN;
626 /* check if bonds from heavy atom (j) to dummy masses (k,l) are equal: */
627 bError = bError || (bjk != bjl);
629 /* the X atom (C or N) in the XH3 group is the first after the masses: */
630 aN = std::max(param->ak(), param->al())+1;
632 /* get all bondlengths and angles: */
633 bMM = get_bond_length(nrbond, bonds, param->ak(), param->al());
634 bCM = bjk;
635 bCN = get_bond_length(nrbond, bonds, param->aj(), aN);
636 bNH = get_bond_length(nrbond, bonds, aN, param->ai());
637 aCNH = get_angle (nrang, angles, param->aj(), aN, param->ai());
638 bError = bError ||
639 (bMM == NOTSET) || (bCN == NOTSET) || (bNH == NOTSET) || (aCNH == NOTSET);
641 /* calculate */
642 dH = bCN - bNH * cos(aCNH);
643 rH = bNH * sin(aCNH);
644 /* we assume the H's are symmetrically distributed */
645 rHx = rH*cos(DEG2RAD*30);
646 rHy = rH*sin(DEG2RAD*30);
647 rM = 0.5*bMM;
648 dM = std::sqrt( sqr(bCM) - sqr(rM) );
649 a = 0.5*( (dH/dM) - (rHy/rM) );
650 b = 0.5*( (dH/dM) + (rHy/rM) );
651 c = rHx / (2*dM*rM);
654 else
656 /* this is the general construction */
658 bij = get_bond_length(nrbond, bonds, param->ai(), param->aj());
659 aijk = get_angle (nrang, angles, param->ai(), param->aj(), param->ak());
660 aijl = get_angle (nrang, angles, param->ai(), param->aj(), param->al());
661 akjl = get_angle (nrang, angles, param->ak(), param->aj(), param->al());
662 bError = bError ||
663 (bij == NOTSET) || (aijk == NOTSET) || (aijl == NOTSET) || (akjl == NOTSET);
665 pijk = cos(aijk)*bij;
666 pijl = cos(aijl)*bij;
667 a = ( pijk + (pijk*cos(akjl)-pijl) * cos(akjl) / sqr(sin(akjl)) ) / bjk;
668 b = ( pijl + (pijl*cos(akjl)-pijk) * cos(akjl) / sqr(sin(akjl)) ) / bjl;
669 c = -std::sqrt( sqr(bij) -
670 ( sqr(pijk) - 2*pijk*pijl*cos(akjl) + sqr(pijl) )
671 / sqr(sin(akjl)) )
672 / ( bjk*bjl*sin(akjl) );
675 param->c0() = a;
676 param->c1() = b;
677 if (bSwapParity)
679 param->c2() = -c;
681 else
683 param->c2() = c;
685 if (debug)
687 fprintf(debug, "params for vsite3out %d: %g %g %g\n",
688 param->ai()+1, param->c0(), param->c1(), param->c2());
690 return bError;
693 static gmx_bool calc_vsite4fd_param(t_param *param,
694 int nrbond, t_mybonded *bonds,
695 int nrang, t_mybonded *angles)
697 /* i = virtual site | ,k
698 * j = 1st bonded heavy atom | i-j-m
699 * k,l,m = 2nd bonded atoms | `l
702 gmx_bool bError;
703 real bij, bjk, bjl, bjm, aijk, aijl, aijm, akjm, akjl;
704 real pk, pl, pm, cosakl, cosakm, sinakl, sinakm, cl, cm;
706 bij = get_bond_length(nrbond, bonds, param->ai(), param->aj());
707 bjk = get_bond_length(nrbond, bonds, param->aj(), param->ak());
708 bjl = get_bond_length(nrbond, bonds, param->aj(), param->al());
709 bjm = get_bond_length(nrbond, bonds, param->aj(), param->am());
710 aijk = get_angle (nrang, angles, param->ai(), param->aj(), param->ak());
711 aijl = get_angle (nrang, angles, param->ai(), param->aj(), param->al());
712 aijm = get_angle (nrang, angles, param->ai(), param->aj(), param->am());
713 akjm = get_angle (nrang, angles, param->ak(), param->aj(), param->am());
714 akjl = get_angle (nrang, angles, param->ak(), param->aj(), param->al());
715 bError = (bij == NOTSET) || (bjk == NOTSET) || (bjl == NOTSET) || (bjm == NOTSET) ||
716 (aijk == NOTSET) || (aijl == NOTSET) || (aijm == NOTSET) || (akjm == NOTSET) ||
717 (akjl == NOTSET);
719 if (!bError)
721 pk = bjk*sin(aijk);
722 pl = bjl*sin(aijl);
723 pm = bjm*sin(aijm);
724 cosakl = (cos(akjl) - cos(aijk)*cos(aijl)) / (sin(aijk)*sin(aijl));
725 cosakm = (cos(akjm) - cos(aijk)*cos(aijm)) / (sin(aijk)*sin(aijm));
726 if (cosakl < -1 || cosakl > 1 || cosakm < -1 || cosakm > 1)
728 fprintf(stderr, "virtual site %d: angle ijk = %f, angle ijl = %f, angle ijm = %f\n",
729 param->ai()+1, RAD2DEG*aijk, RAD2DEG*aijl, RAD2DEG*aijm);
730 gmx_fatal(FARGS, "invalid construction in calc_vsite4fd for atom %d: "
731 "cosakl=%f, cosakm=%f\n", param->ai()+1, cosakl, cosakm);
733 sinakl = std::sqrt(1-sqr(cosakl));
734 sinakm = std::sqrt(1-sqr(cosakm));
736 /* note: there is a '+' because of the way the sines are calculated */
737 cl = -pk / ( pl*cosakl - pk + pl*sinakl*(pm*cosakm-pk)/(pm*sinakm) );
738 cm = -pk / ( pm*cosakm - pk + pm*sinakm*(pl*cosakl-pk)/(pl*sinakl) );
740 param->c0() = cl;
741 param->c1() = cm;
742 param->c2() = -bij;
743 if (debug)
745 fprintf(debug, "params for vsite4fd %d: %g %g %g\n",
746 param->ai()+1, param->c0(), param->c1(), param->c2());
750 return bError;
754 static gmx_bool
755 calc_vsite4fdn_param(t_param *param,
756 int nrbond, t_mybonded *bonds,
757 int nrang, t_mybonded *angles)
759 /* i = virtual site | ,k
760 * j = 1st bonded heavy atom | i-j-m
761 * k,l,m = 2nd bonded atoms | `l
764 gmx_bool bError;
765 real bij, bjk, bjl, bjm, aijk, aijl, aijm;
766 real pk, pl, pm, a, b;
768 bij = get_bond_length(nrbond, bonds, param->ai(), param->aj());
769 bjk = get_bond_length(nrbond, bonds, param->aj(), param->ak());
770 bjl = get_bond_length(nrbond, bonds, param->aj(), param->al());
771 bjm = get_bond_length(nrbond, bonds, param->aj(), param->am());
772 aijk = get_angle (nrang, angles, param->ai(), param->aj(), param->ak());
773 aijl = get_angle (nrang, angles, param->ai(), param->aj(), param->al());
774 aijm = get_angle (nrang, angles, param->ai(), param->aj(), param->am());
776 bError = (bij == NOTSET) || (bjk == NOTSET) || (bjl == NOTSET) || (bjm == NOTSET) ||
777 (aijk == NOTSET) || (aijl == NOTSET) || (aijm == NOTSET);
779 if (!bError)
782 /* Calculate component of bond j-k along the direction i-j */
783 pk = -bjk*cos(aijk);
785 /* Calculate component of bond j-l along the direction i-j */
786 pl = -bjl*cos(aijl);
788 /* Calculate component of bond j-m along the direction i-j */
789 pm = -bjm*cos(aijm);
791 if (fabs(pl) < 1000*GMX_REAL_MIN || fabs(pm) < 1000*GMX_REAL_MIN)
793 fprintf(stderr, "virtual site %d: angle ijk = %f, angle ijl = %f, angle ijm = %f\n",
794 param->ai()+1, RAD2DEG*aijk, RAD2DEG*aijl, RAD2DEG*aijm);
795 gmx_fatal(FARGS, "invalid construction in calc_vsite4fdn for atom %d: "
796 "pl=%f, pm=%f\n", param->ai()+1, pl, pm);
799 a = pk/pl;
800 b = pk/pm;
802 param->c0() = a;
803 param->c1() = b;
804 param->c2() = bij;
806 if (debug)
808 fprintf(debug, "params for vsite4fdn %d: %g %g %g\n",
809 param->ai()+1, param->c0(), param->c1(), param->c2());
813 return bError;
818 int set_vsites(gmx_bool bVerbose, t_atoms *atoms, gpp_atomtype_t atype,
819 t_params plist[])
821 int i, j, ftype;
822 int nvsite, nrbond, nrang, nridih, nrset;
823 gmx_bool bFirst, bSet, bERROR;
824 at2vsitebond_t *at2vb;
825 t_mybonded *bonds;
826 t_mybonded *angles;
827 t_mybonded *idihs;
829 bFirst = TRUE;
830 nvsite = 0;
831 if (debug)
833 fprintf(debug, "\nCalculating parameters for virtual sites\n");
836 /* Make a reverse list to avoid ninteractions^2 operations */
837 at2vb = make_at2vsitebond(atoms->nr, plist);
839 for (ftype = 0; (ftype < F_NRE); ftype++)
841 if (interaction_function[ftype].flags & IF_VSITE)
843 nvsite += plist[ftype].nr;
845 if (ftype == F_VSITEN)
847 /* We don't calculate parameters for VSITEN */
848 continue;
851 nrset = 0;
852 for (i = 0; (i < plist[ftype].nr); i++)
854 /* check if all parameters are set */
855 bSet = TRUE;
856 for (j = 0; j < NRFP(ftype) && bSet; j++)
858 bSet = plist[ftype].param[i].c[j] != NOTSET;
861 if (debug)
863 fprintf(debug, "bSet=%s ", gmx::boolToString(bSet));
864 print_param(debug, ftype, i, &plist[ftype].param[i]);
866 if (!bSet)
868 if (bVerbose && bFirst)
870 fprintf(stderr, "Calculating parameters for virtual sites\n");
871 bFirst = FALSE;
874 nrbond = nrang = nridih = 0;
875 bonds = NULL;
876 angles = NULL;
877 idihs = NULL;
878 nrset++;
879 /* now set the vsite parameters: */
880 get_bondeds(NRAL(ftype), plist[ftype].param[i].a, at2vb,
881 &nrbond, &bonds, &nrang, &angles, &nridih, &idihs);
882 if (debug)
884 fprintf(debug, "Found %d bonds, %d angles and %d idihs "
885 "for virtual site %d (%s)\n", nrbond, nrang, nridih,
886 plist[ftype].param[i].ai()+1,
887 interaction_function[ftype].longname);
888 print_bad(debug, nrbond, bonds, nrang, angles, nridih, idihs);
889 } /* debug */
890 switch (ftype)
892 case F_VSITE3:
893 bERROR =
894 calc_vsite3_param(atype, &(plist[ftype].param[i]), atoms,
895 nrbond, bonds, nrang, angles);
896 break;
897 case F_VSITE3FD:
898 bERROR =
899 calc_vsite3fd_param(&(plist[ftype].param[i]),
900 nrbond, bonds, nrang, angles);
901 break;
902 case F_VSITE3FAD:
903 bERROR =
904 calc_vsite3fad_param(&(plist[ftype].param[i]),
905 nrbond, bonds, nrang, angles);
906 break;
907 case F_VSITE3OUT:
908 bERROR =
909 calc_vsite3out_param(atype, &(plist[ftype].param[i]), atoms,
910 nrbond, bonds, nrang, angles);
911 break;
912 case F_VSITE4FD:
913 bERROR =
914 calc_vsite4fd_param(&(plist[ftype].param[i]),
915 nrbond, bonds, nrang, angles);
916 break;
917 case F_VSITE4FDN:
918 bERROR =
919 calc_vsite4fdn_param(&(plist[ftype].param[i]),
920 nrbond, bonds, nrang, angles);
921 break;
922 default:
923 gmx_fatal(FARGS, "Automatic parameter generation not supported "
924 "for %s atom %d",
925 interaction_function[ftype].longname,
926 plist[ftype].param[i].ai()+1);
927 bERROR = TRUE;
928 } /* switch */
929 if (bERROR)
931 gmx_fatal(FARGS, "Automatic parameter generation not supported "
932 "for %s atom %d for this bonding configuration",
933 interaction_function[ftype].longname,
934 plist[ftype].param[i].ai()+1);
936 sfree(bonds);
937 sfree(angles);
938 sfree(idihs);
939 } /* if bSet */
940 } /* for i */
941 if (debug && plist[ftype].nr)
943 fprintf(stderr, "Calculated parameters for %d out of %d %s atoms\n",
944 nrset, plist[ftype].nr, interaction_function[ftype].longname);
946 } /* if IF_VSITE */
949 done_at2vsitebond(atoms->nr, at2vb);
951 return nvsite;
954 void set_vsites_ptype(gmx_bool bVerbose, gmx_moltype_t *molt)
956 int ftype, i;
957 int nra, nrd;
958 t_ilist *il;
959 t_iatom *ia, avsite;
961 if (bVerbose)
963 fprintf(stderr, "Setting particle type to V for virtual sites\n");
965 if (debug)
967 fprintf(stderr, "checking %d functypes\n", F_NRE);
969 for (ftype = 0; ftype < F_NRE; ftype++)
971 il = &molt->ilist[ftype];
972 if (interaction_function[ftype].flags & IF_VSITE)
974 nra = interaction_function[ftype].nratoms;
975 nrd = il->nr;
976 ia = il->iatoms;
978 if (debug && nrd)
980 fprintf(stderr, "doing %d %s virtual sites\n",
981 (nrd / (nra+1)), interaction_function[ftype].longname);
984 for (i = 0; (i < nrd); )
986 /* The virtual site */
987 avsite = ia[1];
988 molt->atoms.atom[avsite].ptype = eptVSite;
990 i += nra+1;
991 ia += nra+1;
998 typedef struct {
999 int ftype, parnr;
1000 } t_pindex;
1002 static void check_vsite_constraints(t_params *plist,
1003 int cftype, int vsite_type[])
1005 int i, k, n;
1006 int atom;
1007 t_params *ps;
1009 n = 0;
1010 ps = &(plist[cftype]);
1011 for (i = 0; (i < ps->nr); i++)
1013 for (k = 0; k < 2; k++)
1015 atom = ps->param[i].a[k];
1016 if (vsite_type[atom] != NOTSET)
1018 fprintf(stderr, "ERROR: Cannot have constraint (%d-%d) with virtual site (%d)\n",
1019 ps->param[i].ai()+1, ps->param[i].aj()+1, atom+1);
1020 n++;
1024 if (n)
1026 gmx_fatal(FARGS, "There were %d virtual sites involved in constraints", n);
1030 static void clean_vsite_bonds(t_params *plist, t_pindex pindex[],
1031 int cftype, int vsite_type[])
1033 int ftype, i, j, k, m, n, nvsite, nOut, kept_i;
1034 int nconverted, nremoved;
1035 int atom, oatom, at1, at2;
1036 gmx_bool bKeep, bRemove, bUsed, bPresent, bThisFD, bThisOUT, bAllFD, bFirstTwo;
1037 t_params *ps;
1039 if (cftype == F_CONNBONDS)
1041 return;
1044 ps = &(plist[cftype]);
1045 kept_i = 0;
1046 nconverted = 0;
1047 nremoved = 0;
1048 nOut = 0;
1049 for (i = 0; (i < ps->nr); i++) /* for all bonds in the plist */
1051 int vsnral = 0;
1052 const int *first_atoms = NULL;
1054 bKeep = FALSE;
1055 bRemove = FALSE;
1056 bAllFD = TRUE;
1057 /* check if all virtual sites are constructed from the same atoms */
1058 nvsite = 0;
1059 if (debug)
1061 fprintf(debug, "constr %d %d:", ps->param[i].ai()+1, ps->param[i].aj()+1);
1063 for (k = 0; (k < 2) && !bKeep && !bRemove; k++)
1065 /* for all atoms in the bond */
1066 atom = ps->param[i].a[k];
1067 if (vsite_type[atom] != NOTSET && vsite_type[atom] != F_VSITEN)
1069 nvsite++;
1070 bThisFD = ( (pindex[atom].ftype == F_VSITE3FD ) ||
1071 (pindex[atom].ftype == F_VSITE3FAD) ||
1072 (pindex[atom].ftype == F_VSITE4FD ) ||
1073 (pindex[atom].ftype == F_VSITE4FDN ) );
1074 bThisOUT = ( (pindex[atom].ftype == F_VSITE3OUT) &&
1075 (interaction_function[cftype].flags & IF_CONSTRAINT) );
1076 bAllFD = bAllFD && bThisFD;
1077 if (bThisFD || bThisOUT)
1079 if (debug)
1081 fprintf(debug, " %s", bThisOUT ? "out" : "fd");
1083 oatom = ps->param[i].a[1-k]; /* the other atom */
1084 if (vsite_type[oatom] == NOTSET &&
1085 vsite_type[oatom] != F_VSITEN &&
1086 oatom == plist[pindex[atom].ftype].param[pindex[atom].parnr].aj())
1088 /* if the other atom isn't a vsite, and it is AI */
1089 bRemove = TRUE;
1090 if (bThisOUT)
1092 nOut++;
1094 if (debug)
1096 fprintf(debug, " D-AI");
1100 if (!bRemove)
1102 /* TODO This fragment, and corresponding logic in
1103 clean_vsite_angles and clean_vsite_dihs should
1104 be refactored into a common function */
1105 if (nvsite == 1)
1107 /* if this is the first vsite we encounter then
1108 store construction atoms */
1109 /* TODO This would be nicer to implement with
1110 a C++ "vector view" class" with an
1111 STL-container-like interface. */
1112 vsnral = NRAL(pindex[atom].ftype) - 1;
1113 first_atoms = plist[pindex[atom].ftype].param[pindex[atom].parnr].a + 1;
1115 else
1117 GMX_ASSERT(vsnral != 0, "nvsite > 1 must have vsnral != 0");
1118 GMX_ASSERT(first_atoms != NULL, "nvsite > 1 must have first_atoms != NULL");
1119 /* if it is not the first then
1120 check if this vsite is constructed from the same atoms */
1121 if (vsnral == NRAL(pindex[atom].ftype)-1)
1123 for (m = 0; (m < vsnral) && !bKeep; m++)
1125 const int *atoms;
1127 bPresent = FALSE;
1128 atoms = plist[pindex[atom].ftype].param[pindex[atom].parnr].a + 1;
1129 for (n = 0; (n < vsnral) && !bPresent; n++)
1131 if (atoms[m] == first_atoms[n])
1133 bPresent = TRUE;
1136 if (!bPresent)
1138 bKeep = TRUE;
1139 if (debug)
1141 fprintf(debug, " !present");
1146 else
1148 bKeep = TRUE;
1149 if (debug)
1151 fprintf(debug, " !same#at");
1159 if (bRemove)
1161 bKeep = FALSE;
1163 else
1165 /* if we have no virtual sites in this bond, keep it */
1166 if (nvsite == 0)
1168 if (debug)
1170 fprintf(debug, " no vsite");
1172 bKeep = TRUE;
1175 /* TODO This loop and the corresponding loop in
1176 check_vsite_angles should be refactored into a common
1177 function */
1178 /* check if all non-vsite atoms are used in construction: */
1179 bFirstTwo = TRUE;
1180 for (k = 0; (k < 2) && !bKeep; k++) /* for all atoms in the bond */
1182 atom = ps->param[i].a[k];
1183 if (vsite_type[atom] == NOTSET && vsite_type[atom] != F_VSITEN)
1185 bUsed = FALSE;
1186 for (m = 0; (m < vsnral) && !bUsed; m++)
1188 GMX_ASSERT(first_atoms != NULL, "If we've seen a vsite before, we know what its first atom index was");
1190 if (atom == first_atoms[m])
1192 bUsed = TRUE;
1193 bFirstTwo = bFirstTwo && m < 2;
1196 if (!bUsed)
1198 bKeep = TRUE;
1199 if (debug)
1201 fprintf(debug, " !used");
1207 if (!( bAllFD && bFirstTwo ) )
1209 /* Two atom bonded interactions include constraints.
1210 * We need to remove constraints between vsite pairs that have
1211 * a fixed distance due to being constructed from the same
1212 * atoms, since this can be numerically unstable.
1214 for (m = 0; m < vsnral && !bKeep; m++) /* all constr. atoms */
1216 at1 = first_atoms[m];
1217 at2 = first_atoms[(m+1) % vsnral];
1218 bPresent = FALSE;
1219 for (ftype = 0; ftype < F_NRE; ftype++)
1221 if (interaction_function[ftype].flags & IF_CONSTRAINT)
1223 for (j = 0; (j < plist[ftype].nr) && !bPresent; j++)
1225 /* all constraints until one matches */
1226 bPresent = ( ( (plist[ftype].param[j].ai() == at1) &&
1227 (plist[ftype].param[j].aj() == at2) ) ||
1228 ( (plist[ftype].param[j].ai() == at2) &&
1229 (plist[ftype].param[j].aj() == at1) ) );
1233 if (!bPresent)
1235 bKeep = TRUE;
1236 if (debug)
1238 fprintf(debug, " !bonded");
1245 if (bKeep)
1247 if (debug)
1249 fprintf(debug, " keeping");
1251 /* now copy the bond to the new array */
1252 ps->param[kept_i] = ps->param[i];
1253 kept_i++;
1255 else if (IS_CHEMBOND(cftype))
1257 srenew(plist[F_CONNBONDS].param, plist[F_CONNBONDS].nr+1);
1258 plist[F_CONNBONDS].param[plist[F_CONNBONDS].nr] = ps->param[i];
1259 plist[F_CONNBONDS].nr++;
1260 nconverted++;
1262 else
1264 nremoved++;
1266 if (debug)
1268 fprintf(debug, "\n");
1272 if (nremoved)
1274 fprintf(stderr, "Removed %4d %15ss with virtual sites, %5d left\n",
1275 nremoved, interaction_function[cftype].longname, kept_i);
1277 if (nconverted)
1279 fprintf(stderr, "Converted %4d %15ss with virtual sites to connections, %5d left\n",
1280 nconverted, interaction_function[cftype].longname, kept_i);
1282 if (nOut)
1284 fprintf(stderr, "Warning: removed %d %ss with vsite with %s construction\n"
1285 " This vsite construction does not guarantee constant "
1286 "bond-length\n"
1287 " If the constructions were generated by pdb2gmx ignore "
1288 "this warning\n",
1289 nOut, interaction_function[cftype].longname,
1290 interaction_function[F_VSITE3OUT].longname );
1292 ps->nr = kept_i;
1295 static void clean_vsite_angles(t_params *plist, t_pindex pindex[],
1296 int cftype, int vsite_type[],
1297 at2vsitecon_t *at2vc)
1299 int i, j, k, m, n, nvsite, kept_i;
1300 int atom, at1, at2;
1301 gmx_bool bKeep, bUsed, bPresent, bAll3FAD, bFirstTwo;
1302 t_params *ps;
1304 ps = &(plist[cftype]);
1305 kept_i = 0;
1306 for (i = 0; (i < ps->nr); i++) /* for all angles in the plist */
1308 int vsnral = 0;
1309 const int *first_atoms = NULL;
1311 bKeep = FALSE;
1312 bAll3FAD = TRUE;
1313 /* check if all virtual sites are constructed from the same atoms */
1314 nvsite = 0;
1315 for (k = 0; (k < 3) && !bKeep; k++) /* for all atoms in the angle */
1317 atom = ps->param[i].a[k];
1318 if (vsite_type[atom] != NOTSET && vsite_type[atom] != F_VSITEN)
1320 nvsite++;
1321 bAll3FAD = bAll3FAD && (pindex[atom].ftype == F_VSITE3FAD);
1322 if (nvsite == 1)
1324 /* store construction atoms of first vsite */
1325 vsnral = NRAL(pindex[atom].ftype) - 1;
1326 first_atoms = plist[pindex[atom].ftype].param[pindex[atom].parnr].a + 1;
1328 else
1330 GMX_ASSERT(vsnral != 0, "If we've seen a vsite before, we know how many constructing atoms it had");
1331 GMX_ASSERT(first_atoms != NULL, "If we've seen a vsite before, we know what its first atom index was");
1332 /* check if this vsite is constructed from the same atoms */
1333 if (vsnral == NRAL(pindex[atom].ftype)-1)
1335 for (m = 0; (m < vsnral) && !bKeep; m++)
1337 const int *atoms;
1339 bPresent = FALSE;
1340 atoms = plist[pindex[atom].ftype].param[pindex[atom].parnr].a + 1;
1341 for (n = 0; (n < vsnral) && !bPresent; n++)
1343 if (atoms[m] == first_atoms[n])
1345 bPresent = TRUE;
1348 if (!bPresent)
1350 bKeep = TRUE;
1354 else
1356 bKeep = TRUE;
1362 /* keep all angles with no virtual sites in them or
1363 with virtual sites with more than 3 constr. atoms */
1364 if (nvsite == 0 && vsnral > 3)
1366 bKeep = TRUE;
1369 /* check if all non-vsite atoms are used in construction: */
1370 bFirstTwo = TRUE;
1371 for (k = 0; (k < 3) && !bKeep; k++) /* for all atoms in the angle */
1373 atom = ps->param[i].a[k];
1374 if (vsite_type[atom] == NOTSET && vsite_type[atom] != F_VSITEN)
1376 bUsed = FALSE;
1377 for (m = 0; (m < vsnral) && !bUsed; m++)
1379 GMX_ASSERT(first_atoms != NULL, "If we've seen a vsite before, we know what its first atom index was");
1381 if (atom == first_atoms[m])
1383 bUsed = TRUE;
1384 bFirstTwo = bFirstTwo && m < 2;
1387 if (!bUsed)
1389 bKeep = TRUE;
1394 if (!( bAll3FAD && bFirstTwo ) )
1396 /* check if all constructing atoms are constrained together */
1397 for (m = 0; m < vsnral && !bKeep; m++) /* all constr. atoms */
1399 at1 = first_atoms[m];
1400 at2 = first_atoms[(m+1) % vsnral];
1401 bPresent = FALSE;
1402 for (j = 0; j < at2vc[at1].nr; j++)
1404 if (at2vc[at1].aj[j] == at2)
1406 bPresent = TRUE;
1409 if (!bPresent)
1411 bKeep = TRUE;
1416 if (bKeep)
1418 /* now copy the angle to the new array */
1419 ps->param[kept_i] = ps->param[i];
1420 kept_i++;
1424 if (ps->nr != kept_i)
1426 fprintf(stderr, "Removed %4d %15ss with virtual sites, %5d left\n",
1427 ps->nr-kept_i, interaction_function[cftype].longname, kept_i);
1429 ps->nr = kept_i;
1432 static void clean_vsite_dihs(t_params *plist, t_pindex pindex[],
1433 int cftype, int vsite_type[])
1435 int i, kept_i;
1436 t_params *ps;
1438 ps = &(plist[cftype]);
1440 kept_i = 0;
1441 for (i = 0; (i < ps->nr); i++) /* for all dihedrals in the plist */
1443 int k, m, n, nvsite;
1444 int vsnral = 0;
1445 const int *first_atoms = NULL;
1446 int atom;
1447 gmx_bool bKeep, bUsed, bPresent;
1450 bKeep = FALSE;
1451 /* check if all virtual sites are constructed from the same atoms */
1452 nvsite = 0;
1453 for (k = 0; (k < 4) && !bKeep; k++) /* for all atoms in the dihedral */
1455 atom = ps->param[i].a[k];
1456 if (vsite_type[atom] != NOTSET && vsite_type[atom] != F_VSITEN)
1458 if (nvsite == 0)
1460 /* store construction atoms of first vsite */
1461 vsnral = NRAL(pindex[atom].ftype) - 1;
1462 first_atoms = plist[pindex[atom].ftype].param[pindex[atom].parnr].a + 1;
1463 if (debug)
1465 fprintf(debug, "dih w. vsite: %d %d %d %d\n",
1466 ps->param[i].ai()+1, ps->param[i].aj()+1,
1467 ps->param[i].ak()+1, ps->param[i].al()+1);
1468 fprintf(debug, "vsite %d from: %d %d %d\n",
1469 atom+1, first_atoms[0]+1, first_atoms[1]+1, first_atoms[2]+1);
1472 else
1474 GMX_ASSERT(vsnral != 0, "If we've seen a vsite before, we know how many constructing atoms it had");
1475 GMX_ASSERT(first_atoms != NULL, "If we've seen a vsite before, we know what its first atom index was");
1476 /* check if this vsite is constructed from the same atoms */
1477 if (vsnral == NRAL(pindex[atom].ftype)-1)
1479 for (m = 0; (m < vsnral) && !bKeep; m++)
1481 const int *atoms;
1483 bPresent = FALSE;
1484 atoms = plist[pindex[atom].ftype].param[pindex[atom].parnr].a + 1;
1485 for (n = 0; (n < vsnral) && !bPresent; n++)
1487 if (atoms[m] == first_atoms[n])
1489 bPresent = TRUE;
1492 if (!bPresent)
1494 bKeep = TRUE;
1499 /* TODO clean_site_bonds and _angles do this increment
1500 at the top of the loop. Refactor this for
1501 consistency */
1502 nvsite++;
1506 /* keep all dihedrals with no virtual sites in them */
1507 if (nvsite == 0)
1509 bKeep = TRUE;
1512 /* check if all atoms in dihedral are either virtual sites, or used in
1513 construction of virtual sites. If so, keep it, if not throw away: */
1514 for (k = 0; (k < 4) && !bKeep; k++) /* for all atoms in the dihedral */
1516 GMX_ASSERT(vsnral != 0, "If we've seen a vsite before, we know how many constructing atoms it had");
1517 GMX_ASSERT(first_atoms != NULL, "If we've seen a vsite before, we know what its first atom index was");
1518 atom = ps->param[i].a[k];
1519 if (vsite_type[atom] == NOTSET && vsite_type[atom] != F_VSITEN)
1521 /* vsnral will be set here, we don't get here with nvsite==0 */
1522 bUsed = FALSE;
1523 for (m = 0; (m < vsnral) && !bUsed; m++)
1525 if (atom == first_atoms[m])
1527 bUsed = TRUE;
1530 if (!bUsed)
1532 bKeep = TRUE;
1533 if (debug)
1535 fprintf(debug, "unused atom in dih: %d\n", atom+1);
1541 if (bKeep)
1543 ps->param[kept_i] = ps->param[i];
1544 kept_i++;
1548 if (ps->nr != kept_i)
1550 fprintf(stderr, "Removed %4d %15ss with virtual sites, %5d left\n",
1551 ps->nr-kept_i, interaction_function[cftype].longname, kept_i);
1553 ps->nr = kept_i;
1556 void clean_vsite_bondeds(t_params *plist, int natoms, gmx_bool bRmVSiteBds)
1558 int i, k, nvsite, ftype, vsite, parnr;
1559 int *vsite_type;
1560 t_pindex *pindex;
1561 at2vsitecon_t *at2vc;
1563 pindex = 0; /* avoid warnings */
1564 /* make vsite_type array */
1565 snew(vsite_type, natoms);
1566 for (i = 0; i < natoms; i++)
1568 vsite_type[i] = NOTSET;
1570 nvsite = 0;
1571 for (ftype = 0; ftype < F_NRE; ftype++)
1573 if (interaction_function[ftype].flags & IF_VSITE)
1575 nvsite += plist[ftype].nr;
1576 i = 0;
1577 while (i < plist[ftype].nr)
1579 vsite = plist[ftype].param[i].ai();
1580 if (vsite_type[vsite] == NOTSET)
1582 vsite_type[vsite] = ftype;
1584 else
1586 gmx_fatal(FARGS, "multiple vsite constructions for atom %d", vsite+1);
1588 if (ftype == F_VSITEN)
1590 while (i < plist[ftype].nr && plist[ftype].param[i].ai() == vsite)
1592 i++;
1595 else
1597 i++;
1603 /* the rest only if we have virtual sites: */
1604 if (nvsite)
1606 fprintf(stderr, "Cleaning up constraints %swith virtual sites\n",
1607 bRmVSiteBds ? "and constant bonded interactions " : "");
1609 /* Make a reverse list to avoid ninteractions^2 operations */
1610 at2vc = make_at2vsitecon(natoms, plist);
1612 snew(pindex, natoms);
1613 for (ftype = 0; ftype < F_NRE; ftype++)
1615 /* Here we skip VSITEN. In neary all practical use cases this
1616 * is not an issue, since VSITEN is intended for constructing
1617 * additional interaction sites, not for replacing normal atoms
1618 * with bonded interactions. Thus we do not expect constant
1619 * bonded interactions. If VSITEN does get used with constant
1620 * bonded interactions, these are not removed which only leads
1621 * to very minor extra computation and constant energy.
1622 * The only problematic case is onstraints between VSITEN
1623 * constructions with fixed distance (which is anyhow useless).
1624 * This will generate a fatal error in check_vsite_constraints.
1626 if ((interaction_function[ftype].flags & IF_VSITE) &&
1627 ftype != F_VSITEN)
1629 for (parnr = 0; (parnr < plist[ftype].nr); parnr++)
1631 k = plist[ftype].param[parnr].ai();
1632 pindex[k].ftype = ftype;
1633 pindex[k].parnr = parnr;
1638 if (debug)
1640 for (i = 0; i < natoms; i++)
1642 fprintf(debug, "atom %d vsite_type %s\n", i,
1643 vsite_type[i] == NOTSET ? "NOTSET" :
1644 interaction_function[vsite_type[i]].name);
1648 /* remove interactions that include virtual sites */
1649 for (ftype = 0; ftype < F_NRE; ftype++)
1651 if ( ( ( interaction_function[ftype].flags & IF_BOND ) && bRmVSiteBds ) ||
1652 ( interaction_function[ftype].flags & IF_CONSTRAINT ) )
1654 if (interaction_function[ftype].flags & (IF_BTYPE | IF_CONSTRAINT) )
1656 clean_vsite_bonds (plist, pindex, ftype, vsite_type);
1658 else if (interaction_function[ftype].flags & IF_ATYPE)
1660 clean_vsite_angles(plist, pindex, ftype, vsite_type, at2vc);
1662 else if ( (ftype == F_PDIHS) || (ftype == F_IDIHS) )
1664 clean_vsite_dihs (plist, pindex, ftype, vsite_type);
1668 /* check that no remaining constraints include virtual sites */
1669 for (ftype = 0; ftype < F_NRE; ftype++)
1671 if (interaction_function[ftype].flags & IF_CONSTRAINT)
1673 check_vsite_constraints(plist, ftype, vsite_type);
1677 done_at2vsitecon(natoms, at2vc);
1679 sfree(pindex);
1680 sfree(vsite_type);