3 * This source code is part of
7 * GROningen MAchine for Chemical Simulations
10 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
11 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
12 * Copyright (c) 2001-2004, The GROMACS development team,
13 * check out http://www.gromacs.org for more information.
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * If you want to redistribute modifications, please consider that
21 * scientific software is very special. Version control is crucial -
22 * bugs must be traceable. We will be happy to consider code for
23 * inclusion in the official distribution, but derived work must not
24 * be called official GROMACS. Details are found in the README & COPYING
25 * files - if they are missing, get the official version at www.gromacs.org.
27 * To help us fund GROMACS development, we humbly ask that you cite
28 * the papers on the package - you can find them in the top README file.
30 * For more info, check our website at http://www.gromacs.org
33 * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
43 #include "gen_vsite.h"
53 #include "gpp_atomtype.h"
54 #include "fflibutil.h"
57 #define OPENDIR '[' /* starting sign for directive */
58 #define CLOSEDIR ']' /* ending sign for directive */
61 char atomtype
[MAXNAME
]; /* Type for the XH3/XH2 atom */
62 bool isplanar
; /* If true, the atomtype above and the three connected
63 * ones are in a planar geometry. The two next entries
64 * are undefined in that case
66 int nhydrogens
; /* number of connected hydrogens */
67 char nextheavytype
[MAXNAME
]; /* Type for the heavy atom bonded to XH2/XH3 */
68 char dummymass
[MAXNAME
]; /* The type of MNH* or MCH3* dummy mass to use */
72 /* Structure to represent average bond and angles values in vsite aromatic
73 * residues. Note that these are NOT necessarily the bonds and angles from the
74 * forcefield; many forcefields (like Amber, OPLS) have some inherent strain in
75 * 5-rings (i.e. the sum of angles is !=540, but impropers keep it planar)
78 char resname
[MAXNAME
];
81 struct vsitetop_bond
{
85 } *bond
; /* list of bonds */
86 struct vsitetop_angle
{
91 } *angle
; /* list of angles */
95 enum { DDB_CH3
, DDB_NH3
, DDB_NH2
, DDB_PHE
, DDB_TYR
,
96 DDB_TRP
, DDB_HISA
, DDB_HISB
, DDB_HISH
, DDB_DIR_NR
};
98 typedef char t_dirname
[STRLEN
];
100 static const t_dirname ddb_dirnames
[DDB_DIR_NR
] = {
112 static int ddb_name2dir(char *name
)
114 /* Translate a directive name to the number of the directive.
115 * HID/HIE/HIP names are translated to the ones we use in Gromacs.
122 for(i
=0;i
<DDB_DIR_NR
&& index
<0;i
++)
123 if(!strcasecmp(name
,ddb_dirnames
[i
]))
130 static void read_vsite_database(const char *ddbname
,
131 t_vsiteconf
**pvsiteconflist
, int *nvsiteconf
,
132 t_vsitetop
**pvsitetoplist
, int *nvsitetop
)
134 /* This routine is a quick hack to fix the problem with hardcoded atomtypes
135 * and aromatic vsite parameters by reading them from a ff???.vsd file.
137 * The file can contain sections [ NH3 ], [ CH3 ], [ NH2 ], and ring residue names.
138 * For the NH3 and CH3 section each line has three fields. The first is the atomtype
139 * (nb: not bonded type) of the N/C atom to be replaced, the second field is
140 * the type of the next heavy atom it is bonded to, and the third field the type
141 * of dummy mass that will be used for this group.
143 * If the NH2 group planar (sp2 N) a different vsite construct is used, so in this
144 * case the second field should just be the word planar.
150 int i
,j
,n
,k
,nvsite
,ntop
,curdir
,prevdir
;
151 t_vsiteconf
*vsiteconflist
;
152 t_vsitetop
*vsitetoplist
;
154 char s1
[MAXNAME
],s2
[MAXNAME
],s3
[MAXNAME
],s4
[MAXNAME
];
156 ddb
= libopen(ddbname
);
158 nvsite
= *nvsiteconf
;
159 vsiteconflist
= *pvsiteconflist
;
161 vsitetoplist
= *pvsitetoplist
;
165 snew(vsiteconflist
,1);
166 snew(vsitetoplist
,1);
168 while(fgets2(pline
,STRLEN
-2,ddb
) != NULL
) {
169 strip_comment(pline
);
171 if(strlen(pline
)>0) {
172 if(pline
[0] == OPENDIR
) {
173 strncpy(dirstr
,pline
+1,STRLEN
-2);
174 if ((ch
= strchr (dirstr
,CLOSEDIR
)) != NULL
)
178 if(!strcasecmp(dirstr
,"HID"))
179 sprintf(dirstr
,"HISA");
180 else if(!strcasecmp(dirstr
,"HIE"))
181 sprintf(dirstr
,"HISB");
182 else if(!strcasecmp(dirstr
,"HIP"))
183 sprintf(dirstr
,"HISH");
185 curdir
=ddb_name2dir(dirstr
);
187 gmx_fatal(FARGS
,"Invalid directive %s in vsite database %s",
193 gmx_fatal(FARGS
,"First entry in vsite database must be a directive.\n");
198 n
= sscanf(pline
,"%s%s%s",s1
,s2
,s3
);
199 if(n
<3 && !strcasecmp(s2
,"planar")) {
200 srenew(vsiteconflist
,nvsite
+1);
201 strncpy(vsiteconflist
[nvsite
].atomtype
,s1
,MAXNAME
-1);
202 vsiteconflist
[nvsite
].isplanar
=TRUE
;
203 vsiteconflist
[nvsite
].nextheavytype
[0]=0;
204 vsiteconflist
[nvsite
].dummymass
[0]=0;
205 vsiteconflist
[nvsite
].nhydrogens
=2;
208 srenew(vsiteconflist
,(nvsite
+1));
209 strncpy(vsiteconflist
[nvsite
].atomtype
,s1
,MAXNAME
-1);
210 vsiteconflist
[nvsite
].isplanar
=FALSE
;
211 strncpy(vsiteconflist
[nvsite
].nextheavytype
,s2
,MAXNAME
-1);
212 strncpy(vsiteconflist
[nvsite
].dummymass
,s3
,MAXNAME
-1);
214 vsiteconflist
[nvsite
].nhydrogens
=2;
216 vsiteconflist
[nvsite
].nhydrogens
=3;
219 gmx_fatal(FARGS
,"Not enough directives in vsite database line: %s\n",pline
);
229 while((i
<ntop
) && strcasecmp(dirstr
,vsitetoplist
[i
].resname
))
231 /* Allocate a new topology entry if this is a new residue */
233 srenew(vsitetoplist
,ntop
+1);
234 ntop
++; /* i still points to current vsite topology entry */
235 strncpy(vsitetoplist
[i
].resname
,dirstr
,MAXNAME
-1);
236 vsitetoplist
[i
].nbonds
=vsitetoplist
[i
].nangles
=0;
237 snew(vsitetoplist
[i
].bond
,1);
238 snew(vsitetoplist
[i
].angle
,1);
240 n
= sscanf(pline
,"%s%s%s%s",s1
,s2
,s3
,s4
);
243 k
=vsitetoplist
[i
].nbonds
++;
244 srenew(vsitetoplist
[i
].bond
,k
+1);
245 strncpy(vsitetoplist
[i
].bond
[k
].atom1
,s1
,MAXNAME
-1);
246 strncpy(vsitetoplist
[i
].bond
[k
].atom2
,s2
,MAXNAME
-1);
247 vsitetoplist
[i
].bond
[k
].value
=strtod(s3
,NULL
);
250 k
=vsitetoplist
[i
].nangles
++;
251 srenew(vsitetoplist
[i
].angle
,k
+1);
252 strncpy(vsitetoplist
[i
].angle
[k
].atom1
,s1
,MAXNAME
-1);
253 strncpy(vsitetoplist
[i
].angle
[k
].atom2
,s2
,MAXNAME
-1);
254 strncpy(vsitetoplist
[i
].angle
[k
].atom3
,s3
,MAXNAME
-1);
255 vsitetoplist
[i
].angle
[k
].value
=strtod(s4
,NULL
);
257 gmx_fatal(FARGS
,"Need 3 or 4 values to specify bond/angle values in %s: %s\n",ddbname
,pline
);
261 gmx_fatal(FARGS
,"Didnt find a case for directive %s in read_vsite_database\n",dirstr
);
267 *pvsiteconflist
=vsiteconflist
;
268 *pvsitetoplist
=vsitetoplist
;
275 static int nitrogen_is_planar(t_vsiteconf vsiteconflist
[],int nvsiteconf
,char atomtype
[])
277 /* Return 1 if atomtype exists in database list and is planar, 0 if not,
278 * and -1 if not found.
282 for(i
=0;i
<nvsiteconf
&& !found
;i
++) {
283 found
=(!strcasecmp(vsiteconflist
[i
].atomtype
,atomtype
) && (vsiteconflist
[i
].nhydrogens
==2));
286 res
=(vsiteconflist
[i
-1].isplanar
==TRUE
);
293 static char *get_dummymass_name(t_vsiteconf vsiteconflist
[],int nvsiteconf
,char atom
[], char nextheavy
[])
295 /* Return the dummy mass name if found, or NULL if not set in ddb database */
298 for(i
=0;i
<nvsiteconf
&& !found
;i
++) {
299 found
=(!strcasecmp(vsiteconflist
[i
].atomtype
,atom
) &&
300 !strcasecmp(vsiteconflist
[i
].nextheavytype
,nextheavy
));
303 return vsiteconflist
[i
-1].dummymass
;
310 static real
get_ddb_bond(t_vsitetop
*vsitetop
, int nvsitetop
,
312 const char atom1
[], const char atom2
[])
317 while(i
<nvsitetop
&& strcasecmp(res
,vsitetop
[i
].resname
))
320 gmx_fatal(FARGS
,"No vsite information for residue %s found in vsite database.\n",res
);
322 while(j
<vsitetop
[i
].nbonds
&&
323 ( strcmp(atom1
,vsitetop
[i
].bond
[j
].atom1
) || strcmp(atom2
,vsitetop
[i
].bond
[j
].atom2
)) &&
324 ( strcmp(atom2
,vsitetop
[i
].bond
[j
].atom1
) || strcmp(atom1
,vsitetop
[i
].bond
[j
].atom2
)))
326 if(j
==vsitetop
[i
].nbonds
)
327 gmx_fatal(FARGS
,"Couldnt find bond %s-%s for residue %s in vsite database.\n",atom1
,atom2
,res
);
329 return vsitetop
[i
].bond
[j
].value
;
333 static real
get_ddb_angle(t_vsitetop
*vsitetop
, int nvsitetop
,
334 const char res
[], const char atom1
[],
335 const char atom2
[], const char atom3
[])
340 while(i
<nvsitetop
&& strcasecmp(res
,vsitetop
[i
].resname
))
343 gmx_fatal(FARGS
,"No vsite information for residue %s found in vsite database.\n",res
);
345 while(j
<vsitetop
[i
].nangles
&&
346 ( strcmp(atom1
,vsitetop
[i
].angle
[j
].atom1
) ||
347 strcmp(atom2
,vsitetop
[i
].angle
[j
].atom2
) ||
348 strcmp(atom3
,vsitetop
[i
].angle
[j
].atom3
)) &&
349 ( strcmp(atom3
,vsitetop
[i
].angle
[j
].atom1
) ||
350 strcmp(atom2
,vsitetop
[i
].angle
[j
].atom2
) ||
351 strcmp(atom1
,vsitetop
[i
].angle
[j
].atom3
)))
353 if(j
==vsitetop
[i
].nangles
)
354 gmx_fatal(FARGS
,"Couldnt find angle %s-%s-%s for residue %s in vsite database.\n",atom1
,atom2
,atom3
,res
);
356 return vsitetop
[i
].angle
[j
].value
;
360 static void count_bonds(int atom
, t_params
*psb
, char ***atomname
,
361 int *nrbonds
, int *nrHatoms
, int Hatoms
[], int *Heavy
,
362 int *nrheavies
, int heavies
[])
364 int i
,heavy
,other
,nrb
,nrH
,nrhv
;
366 /* find heavy atom bound to this hydrogen */
368 for(i
=0; (i
<psb
->nr
) && (heavy
==NOTSET
); i
++)
369 if (psb
->param
[i
].AI
==atom
)
370 heavy
=psb
->param
[i
].AJ
;
371 else if (psb
->param
[i
].AJ
==atom
)
372 heavy
=psb
->param
[i
].AI
;
374 gmx_fatal(FARGS
,"unbound hydrogen atom %d",atom
+1);
375 /* find all atoms bound to heavy atom */
380 for(i
=0; i
<psb
->nr
; i
++) {
381 if (psb
->param
[i
].AI
==heavy
)
382 other
=psb
->param
[i
].AJ
;
383 else if (psb
->param
[i
].AJ
==heavy
)
384 other
=psb
->param
[i
].AI
;
387 if (is_hydrogen(*(atomname
[other
]))) {
403 static void print_bonds(FILE *fp
, int o2n
[],
404 int nrHatoms
, int Hatoms
[], int Heavy
,
405 int nrheavies
, int heavies
[])
409 fprintf(fp
,"Found: %d Hatoms: ",nrHatoms
);
410 for(i
=0; i
<nrHatoms
; i
++)
411 fprintf(fp
," %d",o2n
[Hatoms
[i
]]+1);
412 fprintf(fp
,"; %d Heavy atoms: %d",nrheavies
+1,o2n
[Heavy
]+1);
413 for(i
=0; i
<nrheavies
; i
++)
414 fprintf(fp
," %d",o2n
[heavies
[i
]]+1);
418 static int get_atype(int atom
, t_atoms
*at
, int nrtp
, t_restp rtp
[],
426 if (at
->atom
[atom
].m
)
427 type
=at
->atom
[atom
].type
;
429 /* get type from rtp */
430 rtpp
= search_rtp(*(at
->resinfo
[at
->atom
[atom
].resind
].name
),nrtp
,rtp
);
431 bNterm
= is_protein(aan
,*(at
->resinfo
[at
->atom
[atom
].resind
].name
)) &&
432 (at
->atom
[atom
].resind
== 0);
433 j
=search_jtype(rtpp
,*(at
->atomname
[atom
]),bNterm
);
434 type
=rtpp
->atom
[j
].type
;
439 static int vsite_nm2type(const char *name
, gpp_atomtype_t atype
)
443 tp
= get_atomtype_type(name
,atype
);
445 gmx_fatal(FARGS
,"Dummy mass type (%s) not found in atom type database",
451 static real
get_amass(int atom
, t_atoms
*at
, int nrtp
, t_restp rtp
[],
459 if (at
->atom
[atom
].m
)
460 mass
=at
->atom
[atom
].m
;
462 /* get mass from rtp */
463 rtpp
= search_rtp(*(at
->resinfo
[at
->atom
[atom
].resind
].name
),nrtp
,rtp
);
464 bNterm
= is_protein(aan
,*(at
->resinfo
[at
->atom
[atom
].resind
].name
)) &&
465 (at
->atom
[atom
].resind
== 0);
466 j
=search_jtype(rtpp
,*(at
->atomname
[atom
]),bNterm
);
467 mass
=rtpp
->atom
[j
].m
;
472 static void my_add_param(t_params
*plist
, int ai
, int aj
, real b
)
474 static real c
[MAXFORCEPARAM
] =
475 { NOTSET
, NOTSET
, NOTSET
, NOTSET
, NOTSET
, NOTSET
};
478 add_param(plist
,ai
,aj
,c
,NULL
);
481 static void add_vsites(t_params plist
[], int vsite_type
[],
482 int Heavy
, int nrHatoms
, int Hatoms
[],
483 int nrheavies
, int heavies
[])
485 int i
,j
,ftype
,other
,moreheavy
,bb
;
488 for(i
=0; i
<nrHatoms
; i
++) {
489 ftype
=vsite_type
[Hatoms
[i
]];
490 bSwapParity
= (ftype
<0);
491 vsite_type
[Hatoms
[i
]] = ftype
= abs(ftype
);
492 if (ftype
== F_BONDS
) {
493 if ( (nrheavies
!= 1) && (nrHatoms
!= 1) )
494 gmx_fatal(FARGS
,"cannot make constraint in add_vsites for %d heavy "
495 "atoms and %d hydrogen atoms",nrheavies
,nrHatoms
);
496 my_add_param(&(plist
[F_CONSTRNC
]),Hatoms
[i
],heavies
[0],NOTSET
);
503 gmx_fatal(FARGS
,"Not enough heavy atoms (%d) for %s (min 3)",
505 interaction_function
[vsite_type
[Hatoms
[i
]]].name
);
506 add_vsite3_atoms(&plist
[ftype
],Hatoms
[i
],Heavy
,heavies
[0],heavies
[1],
511 moreheavy
=heavies
[1];
513 /* find more heavy atoms */
514 other
=moreheavy
=NOTSET
;
515 for(j
=0; (j
<plist
[F_BONDS
].nr
) && (moreheavy
==NOTSET
); j
++) {
516 if (plist
[F_BONDS
].param
[j
].AI
==heavies
[0])
517 other
=plist
[F_BONDS
].param
[j
].AJ
;
518 else if (plist
[F_BONDS
].param
[j
].AJ
==heavies
[0])
519 other
=plist
[F_BONDS
].param
[j
].AI
;
520 if ( (other
!= NOTSET
) && (other
!= Heavy
) )
523 if (moreheavy
==NOTSET
)
524 gmx_fatal(FARGS
,"Unbound molecule part %d-%d",Heavy
+1,Hatoms
[0]+1);
526 add_vsite3_atoms(&plist
[ftype
],Hatoms
[i
],Heavy
,heavies
[0],moreheavy
,
534 gmx_fatal(FARGS
,"Not enough heavy atoms (%d) for %s (min 4)",
536 interaction_function
[vsite_type
[Hatoms
[i
]]].name
);
538 add_vsite4_atoms(&plist
[ftype
],
539 Hatoms
[0], Heavy
, heavies
[0], heavies
[1], heavies
[2]);
543 gmx_fatal(FARGS
,"can't use add_vsites for interaction function %s",
544 interaction_function
[vsite_type
[Hatoms
[i
]]].name
);
550 #define ANGLE_6RING (DEG2RAD*120)
552 /* cosine rule: a^2 = b^2 + c^2 - 2 b c cos(alpha) */
553 /* get a^2 when a, b and alpha are given: */
554 #define cosrule(b,c,alpha) ( sqr(b) + sqr(c) - 2*b*c*cos(alpha) )
555 /* get cos(alpha) when a, b and c are given: */
556 #define acosrule(a,b,c) ( (sqr(b)+sqr(c)-sqr(a))/(2*b*c) )
558 static int gen_vsites_6ring(t_atoms
*at
, int *vsite_type
[], t_params plist
[],
559 int nrfound
, int *ats
, real bond_cc
, real bond_ch
,
560 real xcom
, real ycom
, bool bDoZ
)
562 /* these MUST correspond to the atnms array in do_vsite_aromatics! */
563 enum { atCG
, atCD1
, atHD1
, atCD2
, atHD2
, atCE1
, atHE1
, atCE2
, atHE2
,
567 real a
,b
,dCGCE
,tmp1
,tmp2
,mtot
,mG
,mrest
;
568 real xCG
,yCG
,xCE1
,yCE1
,xCE2
,yCE2
;
569 /* CG, CE1 and CE2 stay and each get a part of the total mass,
570 * so the c-o-m stays the same.
575 gmx_incons("Generating vsites on 6-rings");
578 /* constraints between CG, CE1 and CE2: */
579 dCGCE
= sqrt( cosrule(bond_cc
,bond_cc
,ANGLE_6RING
) );
580 my_add_param(&(plist
[F_CONSTRNC
]),ats
[atCG
] ,ats
[atCE1
],dCGCE
);
581 my_add_param(&(plist
[F_CONSTRNC
]),ats
[atCG
] ,ats
[atCE2
],dCGCE
);
582 my_add_param(&(plist
[F_CONSTRNC
]),ats
[atCE1
],ats
[atCE2
],dCGCE
);
584 /* rest will be vsite3 */
587 for(i
=0; i
< (bDoZ
? atNR
: atHZ
) ; i
++) {
588 mtot
+=at
->atom
[ats
[i
]].m
;
589 if ( i
!=atCG
&& i
!=atCE1
&& i
!=atCE2
&& (bDoZ
|| (i
!=atHZ
&& i
!=atCZ
) ) ) {
590 at
->atom
[ats
[i
]].m
= at
->atom
[ats
[i
]].mB
= 0;
591 (*vsite_type
)[ats
[i
]]=F_VSITE3
;
595 /* Distribute mass so center-of-mass stays the same.
596 * The center-of-mass in the call is defined with x=0 at
597 * the CE1-CE2 bond and y=0 at the line from CG to the middle of CE1-CE2 bond.
599 xCG
=-bond_cc
+bond_cc
*cos(ANGLE_6RING
);
602 yCE1
=bond_cc
*sin(0.5*ANGLE_6RING
);
604 yCE2
=-bond_cc
*sin(0.5*ANGLE_6RING
);
606 mG
= at
->atom
[ats
[atCG
]].m
= at
->atom
[ats
[atCG
]].mB
= xcom
*mtot
/xCG
;
608 at
->atom
[ats
[atCE1
]].m
= at
->atom
[ats
[atCE1
]].mB
=
609 at
->atom
[ats
[atCE2
]].m
= at
->atom
[ats
[atCE2
]].mB
= mrest
/ 2;
611 /* vsite3 construction: r_d = r_i + a r_ij + b r_ik */
612 tmp1
= dCGCE
*sin(ANGLE_6RING
*0.5);
613 tmp2
= bond_cc
*cos(0.5*ANGLE_6RING
) + tmp1
;
615 a
= b
= - bond_ch
/ tmp1
;
617 add_vsite3_param(&plist
[F_VSITE3
],
618 ats
[atHE1
],ats
[atCE1
],ats
[atCE2
],ats
[atCG
], a
,b
);
619 add_vsite3_param(&plist
[F_VSITE3
],
620 ats
[atHE2
],ats
[atCE2
],ats
[atCE1
],ats
[atCG
], a
,b
);
621 /* CD1, CD2 and CZ: */
623 add_vsite3_param(&plist
[F_VSITE3
],
624 ats
[atCD1
],ats
[atCE2
],ats
[atCE1
],ats
[atCG
], a
,b
);
625 add_vsite3_param(&plist
[F_VSITE3
],
626 ats
[atCD2
],ats
[atCE1
],ats
[atCE2
],ats
[atCG
], a
,b
);
628 add_vsite3_param(&plist
[F_VSITE3
],
629 ats
[atCZ
], ats
[atCG
], ats
[atCE1
],ats
[atCE2
],a
,b
);
630 /* HD1, HD2 and HZ: */
631 a
= b
= ( bond_ch
+ tmp2
) / tmp1
;
632 add_vsite3_param(&plist
[F_VSITE3
],
633 ats
[atHD1
],ats
[atCE2
],ats
[atCE1
],ats
[atCG
], a
,b
);
634 add_vsite3_param(&plist
[F_VSITE3
],
635 ats
[atHD2
],ats
[atCE1
],ats
[atCE2
],ats
[atCG
], a
,b
);
637 add_vsite3_param(&plist
[F_VSITE3
],
638 ats
[atHZ
], ats
[atCG
], ats
[atCE1
],ats
[atCE2
],a
,b
);
643 static int gen_vsites_phe(t_atoms
*at
, int *vsite_type
[], t_params plist
[],
644 int nrfound
, int *ats
, t_vsitetop
*vsitetop
, int nvsitetop
)
646 real bond_cc
,bond_ch
;
649 /* these MUST correspond to the atnms array in do_vsite_aromatics! */
650 enum { atCG
, atCD1
, atHD1
, atCD2
, atHD2
, atCE1
, atHE1
, atCE2
, atHE2
,
652 real x
[atNR
],y
[atNR
];
653 /* Aromatic rings have 6-fold symmetry, so we only need one bond length.
654 * (angle is always 120 degrees).
656 bond_cc
=get_ddb_bond(vsitetop
,nvsitetop
,"PHE","CD1","CE1");
657 bond_ch
=get_ddb_bond(vsitetop
,nvsitetop
,"PHE","CD1","HD1");
659 x
[atCG
]=-bond_cc
+bond_cc
*cos(ANGLE_6RING
);
662 y
[atCD1
]=bond_cc
*sin(0.5*ANGLE_6RING
);
663 x
[atHD1
]=x
[atCD1
]+bond_ch
*cos(ANGLE_6RING
);
664 y
[atHD1
]=y
[atCD1
]+bond_ch
*sin(ANGLE_6RING
);
667 x
[atHE1
]=x
[atCE1
]-bond_ch
*cos(ANGLE_6RING
);
668 y
[atHE1
]=y
[atCE1
]+bond_ch
*sin(ANGLE_6RING
);
677 x
[atCZ
]=bond_cc
*cos(0.5*ANGLE_6RING
);
679 x
[atHZ
]=x
[atCZ
]+bond_ch
;
683 for(i
=0;i
<atNR
;i
++) {
684 xcom
+=x
[i
]*at
->atom
[ats
[i
]].m
;
685 ycom
+=y
[i
]*at
->atom
[ats
[i
]].m
;
686 mtot
+=at
->atom
[ats
[i
]].m
;
691 return gen_vsites_6ring(at
, vsite_type
, plist
, nrfound
, ats
, bond_cc
, bond_ch
, xcom
, ycom
, TRUE
);
694 static void calc_vsite3_param(real xd
,real yd
,real xi
,real yi
,real xj
,real yj
,
695 real xk
, real yk
, real
*a
, real
*b
)
697 /* determine parameters by solving the equation system, since we know the
698 * virtual site coordinates here.
700 real dx_ij
,dx_ik
,dy_ij
,dy_ik
;
707 b_ij
=sqrt(dx_ij
*dx_ij
+dy_ij
*dy_ij
);
708 b_ik
=sqrt(dx_ik
*dx_ik
+dy_ik
*dy_ik
);
710 *a
= ( (xd
-xi
)*dy_ik
- dx_ik
*(yd
-yi
) ) / (dx_ij
*dy_ik
- dx_ik
*dy_ij
);
711 *b
= ( yd
- yi
- (*a
)*dy_ij
) / dy_ik
;
715 static int gen_vsites_trp(gpp_atomtype_t atype
, rvec
*newx
[],
716 t_atom
*newatom
[], char ***newatomname
[],
717 int *o2n
[], int *newvsite_type
[], int *newcgnr
[],
718 t_symtab
*symtab
, int *nadd
, rvec x
[], int *cgnr
[],
719 t_atoms
*at
, int *vsite_type
[], t_params plist
[],
720 int nrfound
, int *ats
, int add_shift
,
721 t_vsitetop
*vsitetop
, int nvsitetop
)
724 /* these MUST correspond to the atnms array in do_vsite_aromatics! */
726 atCB
, atCG
, atCD1
, atHD1
, atCD2
, atNE1
, atHE1
, atCE2
, atCE3
, atHE3
,
727 atCZ2
, atHZ2
, atCZ3
, atHZ3
, atCH2
, atHH2
, atNR
};
728 /* weights for determining the COM's of both rings (M1 and M2): */
729 real mw
[NMASS
][atNR
] = {
730 { 0, 1, 1, 1, 0.5, 1, 1, 0.5, 0, 0,
732 { 0, 0, 0, 0, 0.5, 0, 0, 0.5, 1, 1,
736 real xi
[atNR
],yi
[atNR
];
737 real xcom
[NMASS
],ycom
[NMASS
],I
,alpha
;
738 real lineA
,lineB
,dist
;
739 real b_CD2_CE2
,b_NE1_CE2
,b_CG_CD2
,b_CH2_HH2
,b_CE2_CZ2
;
740 real b_NE1_HE1
,b_CD2_CE3
,b_CE3_CZ3
,b_CB_CG
;
741 real b_CZ2_CH2
,b_CZ2_HZ2
,b_CD1_HD1
,b_CE3_HE3
;
742 real b_CG_CD1
,b_CZ3_HZ3
;
743 real a_NE1_CE2_CD2
,a_CE2_CD2_CG
,a_CB_CG_CD2
,a_CE2_CD2_CE3
;
744 real a_CB_CG_CD1
,a_CD2_CG_CD1
,a_CE2_CZ2_HZ2
,a_CZ2_CH2_HH2
;
745 real a_CD2_CE2_CZ2
,a_CD2_CE3_CZ3
,a_CE3_CZ3_HZ3
,a_CG_CD1_HD1
;
746 real a_CE2_CZ2_CH2
,a_HE1_NE1_CE2
,a_CD2_CE3_HE3
;
748 int atM
[NMASS
],tpM
,i
,i0
,j
,nvsite
;
749 real mwtot
,mtot
,mM
[NMASS
],dCBM1
,dCBM2
,dM1M2
;
750 real a
,b
,c
[MAXFORCEPARAM
];
751 rvec r_ij
,r_ik
,t1
,t2
;
755 gmx_incons("atom types in gen_vsites_trp");
756 /* Get geometry from database */
757 b_CD2_CE2
=get_ddb_bond(vsitetop
,nvsitetop
,"TRP","CD2","CE2");
758 b_NE1_CE2
=get_ddb_bond(vsitetop
,nvsitetop
,"TRP","NE1","CE2");
759 b_CG_CD1
=get_ddb_bond(vsitetop
,nvsitetop
,"TRP","CG","CD1");
760 b_CG_CD2
=get_ddb_bond(vsitetop
,nvsitetop
,"TRP","CG","CD2");
761 b_CB_CG
=get_ddb_bond(vsitetop
,nvsitetop
,"TRP","CB","CG");
762 b_CE2_CZ2
=get_ddb_bond(vsitetop
,nvsitetop
,"TRP","CE2","CZ2");
763 b_CD2_CE3
=get_ddb_bond(vsitetop
,nvsitetop
,"TRP","CD2","CE3");
764 b_CE3_CZ3
=get_ddb_bond(vsitetop
,nvsitetop
,"TRP","CE3","CZ3");
765 b_CZ2_CH2
=get_ddb_bond(vsitetop
,nvsitetop
,"TRP","CZ2","CH2");
767 b_CD1_HD1
=get_ddb_bond(vsitetop
,nvsitetop
,"TRP","CD1","HD1");
768 b_CZ2_HZ2
=get_ddb_bond(vsitetop
,nvsitetop
,"TRP","CZ2","HZ2");
769 b_NE1_HE1
=get_ddb_bond(vsitetop
,nvsitetop
,"TRP","NE1","HE1");
770 b_CH2_HH2
=get_ddb_bond(vsitetop
,nvsitetop
,"TRP","CH2","HH2");
771 b_CE3_HE3
=get_ddb_bond(vsitetop
,nvsitetop
,"TRP","CE3","HE3");
772 b_CZ3_HZ3
=get_ddb_bond(vsitetop
,nvsitetop
,"TRP","CZ3","HZ3");
774 a_NE1_CE2_CD2
=DEG2RAD
*get_ddb_angle(vsitetop
,nvsitetop
,"TRP","NE1","CE2","CD2");
775 a_CE2_CD2_CG
=DEG2RAD
*get_ddb_angle(vsitetop
,nvsitetop
,"TRP","CE2","CD2","CG");
776 a_CB_CG_CD2
=DEG2RAD
*get_ddb_angle(vsitetop
,nvsitetop
,"TRP","CB","CG","CD2");
777 a_CD2_CG_CD1
=DEG2RAD
*get_ddb_angle(vsitetop
,nvsitetop
,"TRP","CD2","CG","CD1");
778 a_CB_CG_CD1
=DEG2RAD
*get_ddb_angle(vsitetop
,nvsitetop
,"TRP","CB","CG","CD1");
780 a_CE2_CD2_CE3
=DEG2RAD
*get_ddb_angle(vsitetop
,nvsitetop
,"TRP","CE2","CD2","CE3");
781 a_CD2_CE2_CZ2
=DEG2RAD
*get_ddb_angle(vsitetop
,nvsitetop
,"TRP","CD2","CE2","CZ2");
782 a_CD2_CE3_CZ3
=DEG2RAD
*get_ddb_angle(vsitetop
,nvsitetop
,"TRP","CD2","CE3","CZ3");
783 a_CE3_CZ3_HZ3
=DEG2RAD
*get_ddb_angle(vsitetop
,nvsitetop
,"TRP","CE3","CZ3","HZ3");
784 a_CZ2_CH2_HH2
=DEG2RAD
*get_ddb_angle(vsitetop
,nvsitetop
,"TRP","CZ2","CH2","HH2");
785 a_CE2_CZ2_HZ2
=DEG2RAD
*get_ddb_angle(vsitetop
,nvsitetop
,"TRP","CE2","CZ2","HZ2");
786 a_CE2_CZ2_CH2
=DEG2RAD
*get_ddb_angle(vsitetop
,nvsitetop
,"TRP","CE2","CZ2","CH2");
787 a_CG_CD1_HD1
=DEG2RAD
*get_ddb_angle(vsitetop
,nvsitetop
,"TRP","CG","CD1","HD1");
788 a_HE1_NE1_CE2
=DEG2RAD
*get_ddb_angle(vsitetop
,nvsitetop
,"TRP","HE1","NE1","CE2");
789 a_CD2_CE3_HE3
=DEG2RAD
*get_ddb_angle(vsitetop
,nvsitetop
,"TRP","CD2","CE3","HE3");
791 /* Calculate local coordinates.
792 * y-axis (x=0) is the bond CD2-CE2.
793 * x-axis (y=0) is perpendicular to the bond CD2-CE2 and
794 * intersects the middle of the bond.
797 yi
[atCD2
]=-0.5*b_CD2_CE2
;
800 yi
[atCE2
]=0.5*b_CD2_CE2
;
802 xi
[atNE1
]=-b_NE1_CE2
*sin(a_NE1_CE2_CD2
);
803 yi
[atNE1
]=yi
[atCE2
]-b_NE1_CE2
*cos(a_NE1_CE2_CD2
);
805 xi
[atCG
]=-b_CG_CD2
*sin(a_CE2_CD2_CG
);
806 yi
[atCG
]=yi
[atCD2
]+b_CG_CD2
*cos(a_CE2_CD2_CG
);
808 alpha
= a_CE2_CD2_CG
+ M_PI
- a_CB_CG_CD2
;
809 xi
[atCB
]=xi
[atCG
]-b_CB_CG
*sin(alpha
);
810 yi
[atCB
]=yi
[atCG
]+b_CB_CG
*cos(alpha
);
812 alpha
= a_CE2_CD2_CG
+ a_CD2_CG_CD1
- M_PI
;
813 xi
[atCD1
]=xi
[atCG
]-b_CG_CD1
*sin(alpha
);
814 yi
[atCD1
]=yi
[atCG
]+b_CG_CD1
*cos(alpha
);
816 xi
[atCE3
]=b_CD2_CE3
*sin(a_CE2_CD2_CE3
);
817 yi
[atCE3
]=yi
[atCD2
]+b_CD2_CE3
*cos(a_CE2_CD2_CE3
);
819 xi
[atCZ2
]=b_CE2_CZ2
*sin(a_CD2_CE2_CZ2
);
820 yi
[atCZ2
]=yi
[atCE2
]-b_CE2_CZ2
*cos(a_CD2_CE2_CZ2
);
822 alpha
= a_CE2_CD2_CE3
+ a_CD2_CE3_CZ3
- M_PI
;
823 xi
[atCZ3
]=xi
[atCE3
]+b_CE3_CZ3
*sin(alpha
);
824 yi
[atCZ3
]=yi
[atCE3
]+b_CE3_CZ3
*cos(alpha
);
826 alpha
= a_CD2_CE2_CZ2
+ a_CE2_CZ2_CH2
- M_PI
;
827 xi
[atCH2
]=xi
[atCZ2
]+b_CZ2_CH2
*sin(alpha
);
828 yi
[atCH2
]=yi
[atCZ2
]-b_CZ2_CH2
*cos(alpha
);
831 alpha
= a_CE2_CD2_CG
+ a_CD2_CG_CD1
- a_CG_CD1_HD1
;
832 xi
[atHD1
]=xi
[atCD1
]-b_CD1_HD1
*sin(alpha
);
833 yi
[atHD1
]=yi
[atCD1
]+b_CD1_HD1
*cos(alpha
);
835 alpha
= a_NE1_CE2_CD2
+ M_PI
- a_HE1_NE1_CE2
;
836 xi
[atHE1
]=xi
[atNE1
]-b_NE1_HE1
*sin(alpha
);
837 yi
[atHE1
]=yi
[atNE1
]-b_NE1_HE1
*cos(alpha
);
839 alpha
= a_CE2_CD2_CE3
+ M_PI
- a_CD2_CE3_HE3
;
840 xi
[atHE3
]=xi
[atCE3
]+b_CE3_HE3
*sin(alpha
);
841 yi
[atHE3
]=yi
[atCE3
]+b_CE3_HE3
*cos(alpha
);
843 alpha
= a_CD2_CE2_CZ2
+ M_PI
- a_CE2_CZ2_HZ2
;
844 xi
[atHZ2
]=xi
[atCZ2
]+b_CZ2_HZ2
*sin(alpha
);
845 yi
[atHZ2
]=yi
[atCZ2
]-b_CZ2_HZ2
*cos(alpha
);
847 alpha
= a_CD2_CE2_CZ2
+ a_CE2_CZ2_CH2
- a_CZ2_CH2_HH2
;
848 xi
[atHZ3
]=xi
[atCZ3
]+b_CZ3_HZ3
*sin(alpha
);
849 yi
[atHZ3
]=yi
[atCZ3
]+b_CZ3_HZ3
*cos(alpha
);
851 alpha
= a_CE2_CD2_CE3
+ a_CD2_CE3_CZ3
- a_CE3_CZ3_HZ3
;
852 xi
[atHH2
]=xi
[atCH2
]+b_CH2_HH2
*sin(alpha
);
853 yi
[atHH2
]=yi
[atCH2
]-b_CH2_HH2
*cos(alpha
);
855 /* Determine coeff. for the line CB-CG */
856 lineA
=(yi
[atCB
]-yi
[atCG
])/(xi
[atCB
]-xi
[atCG
]);
857 lineB
=yi
[atCG
]-lineA
*xi
[atCG
];
859 /* Calculate masses for each ring and put it on the dummy masses */
860 for(j
=0; j
<NMASS
; j
++)
861 mM
[j
]=xcom
[j
]=ycom
[j
]=0;
862 for(i
=0; i
<atNR
; i
++) {
864 for(j
=0; j
<NMASS
; j
++) {
865 mM
[j
] += mw
[j
][i
] * at
->atom
[ats
[i
]].m
;
866 xcom
[j
] += xi
[i
] * mw
[j
][i
] * at
->atom
[ats
[i
]].m
;
867 ycom
[j
] += yi
[i
] * mw
[j
][i
] * at
->atom
[ats
[i
]].m
;
871 for(j
=0; j
<NMASS
; j
++) {
876 /* get dummy mass type */
877 tpM
=vsite_nm2type("MW",atype
);
878 /* make space for 2 masses: shift all atoms starting with CB */
880 for(j
=0; j
<NMASS
; j
++)
883 fprintf(stderr
,"Inserting %d dummy masses at %d\n",NMASS
,(*o2n
)[i0
]+1);
885 for(j
=i0
; j
<at
->nr
; j
++)
887 srenew(*newx
,at
->nr
+*nadd
);
888 srenew(*newatom
,at
->nr
+*nadd
);
889 srenew(*newatomname
,at
->nr
+*nadd
);
890 srenew(*newvsite_type
,at
->nr
+*nadd
);
891 srenew(*newcgnr
,at
->nr
+*nadd
);
892 for(j
=0; j
<NMASS
; j
++)
893 (*newatomname
)[at
->nr
+*nadd
-1-j
]=NULL
;
895 /* Dummy masses will be placed at the center-of-mass in each ring. */
897 /* calc initial position for dummy masses in real (non-local) coordinates.
898 * Cheat by using the routine to calculate virtual site parameters. It is
899 * much easier when we have the coordinates expressed in terms of
902 rvec_sub(x
[ats
[atCB
]],x
[ats
[atCG
]],r_ij
);
903 rvec_sub(x
[ats
[atCD2
]],x
[ats
[atCG
]],r_ik
);
904 calc_vsite3_param(xcom
[0],ycom
[0],xi
[atCG
],yi
[atCG
],xi
[atCB
],yi
[atCB
],
905 xi
[atCD2
],yi
[atCD2
],&a
,&b
);
909 rvec_add(t1
,x
[ats
[atCG
]],(*newx
)[atM
[0]]);
911 calc_vsite3_param(xcom
[1],ycom
[1],xi
[atCG
],yi
[atCG
],xi
[atCB
],yi
[atCB
],
912 xi
[atCD2
],yi
[atCD2
],&a
,&b
);
916 rvec_add(t1
,x
[ats
[atCG
]],(*newx
)[atM
[1]]);
918 /* set parameters for the masses */
919 for(j
=0; j
<NMASS
; j
++) {
920 sprintf(name
,"MW%d",j
+1);
921 (*newatomname
) [atM
[j
]] = put_symtab(symtab
,name
);
922 (*newatom
) [atM
[j
]].m
= (*newatom
)[atM
[j
]].mB
= mM
[j
];
923 (*newatom
) [atM
[j
]].q
= (*newatom
)[atM
[j
]].qB
= 0.0;
924 (*newatom
) [atM
[j
]].type
= (*newatom
)[atM
[j
]].typeB
= tpM
;
925 (*newatom
) [atM
[j
]].ptype
= eptAtom
;
926 (*newatom
) [atM
[j
]].resind
= at
->atom
[i0
].resind
;
927 (*newvsite_type
)[atM
[j
]] = NOTSET
;
928 (*newcgnr
) [atM
[j
]] = (*cgnr
)[i0
];
931 for(i
=i0
; i
<at
->nr
; i
++)
934 /* constraints between CB, M1 and M2 */
935 /* 'add_shift' says which atoms won't be renumbered afterwards */
936 dCBM1
= sqrt( sqr(xcom
[0]-xi
[atCB
]) + sqr(ycom
[0]-yi
[atCB
]) );
937 dM1M2
= sqrt( sqr(xcom
[0]-xcom
[1]) + sqr(ycom
[0]-ycom
[1]) );
938 dCBM2
= sqrt( sqr(xcom
[1]-xi
[atCB
]) + sqr(ycom
[1]-yi
[atCB
]) );
939 my_add_param(&(plist
[F_CONSTRNC
]),ats
[atCB
], add_shift
+atM
[0],dCBM1
);
940 my_add_param(&(plist
[F_CONSTRNC
]),ats
[atCB
], add_shift
+atM
[1],dCBM2
);
941 my_add_param(&(plist
[F_CONSTRNC
]),add_shift
+atM
[0],add_shift
+atM
[1],dM1M2
);
943 /* rest will be vsite3 */
945 for(i
=0; i
<atNR
; i
++)
947 at
->atom
[ats
[i
]].m
= at
->atom
[ats
[i
]].mB
= 0;
948 (*vsite_type
)[ats
[i
]] = F_VSITE3
;
952 /* now define all vsites from M1, M2, CB, ie:
953 r_d = r_M1 + a r_M1_M2 + b r_M1_CB */
954 for(i
=0; i
<atNR
; i
++)
955 if ( (*vsite_type
)[ats
[i
]] == F_VSITE3
) {
956 calc_vsite3_param(xi
[i
],yi
[i
],xcom
[0],ycom
[0],xcom
[1],ycom
[1],xi
[atCB
],yi
[atCB
],&a
,&b
);
957 add_vsite3_param(&plist
[F_VSITE3
],
958 ats
[i
],add_shift
+atM
[0],add_shift
+atM
[1],ats
[atCB
],a
,b
);
965 static int gen_vsites_tyr(gpp_atomtype_t atype
, rvec
*newx
[],
966 t_atom
*newatom
[], char ***newatomname
[],
967 int *o2n
[], int *newvsite_type
[], int *newcgnr
[],
968 t_symtab
*symtab
, int *nadd
, rvec x
[], int *cgnr
[],
969 t_atoms
*at
, int *vsite_type
[], t_params plist
[],
970 int nrfound
, int *ats
, int add_shift
,
971 t_vsitetop
*vsitetop
, int nvsitetop
)
973 int nvsite
,i
,i0
,j
,atM
,tpM
;
974 real dCGCE
,dCEOH
,dCGM
,tmp1
,a
,b
;
975 real bond_cc
,bond_ch
,bond_co
,bond_oh
,angle_coh
;
981 /* these MUST correspond to the atnms array in do_vsite_aromatics! */
982 enum { atCG
, atCD1
, atHD1
, atCD2
, atHD2
, atCE1
, atHE1
, atCE2
, atHE2
,
983 atCZ
, atOH
, atHH
, atNR
};
984 real xi
[atNR
],yi
[atNR
];
985 /* CG, CE1, CE2 (as in general 6-ring) and OH and HH stay,
986 rest gets virtualized.
987 Now we have two linked triangles with one improper keeping them flat */
989 gmx_incons("Number of atom types in gen_vsites_tyr");
991 /* Aromatic rings have 6-fold symmetry, so we only need one bond length
992 * for the ring part (angle is always 120 degrees).
994 bond_cc
=get_ddb_bond(vsitetop
,nvsitetop
,"TYR","CD1","CE1");
995 bond_ch
=get_ddb_bond(vsitetop
,nvsitetop
,"TYR","CD1","HD1");
996 bond_co
=get_ddb_bond(vsitetop
,nvsitetop
,"TYR","CZ","OH");
997 bond_oh
=get_ddb_bond(vsitetop
,nvsitetop
,"TYR","OH","HH");
998 angle_coh
=DEG2RAD
*get_ddb_angle(vsitetop
,nvsitetop
,"TYR","CZ","OH","HH");
1000 xi
[atCG
]=-bond_cc
+bond_cc
*cos(ANGLE_6RING
);
1003 yi
[atCD1
]=bond_cc
*sin(0.5*ANGLE_6RING
);
1004 xi
[atHD1
]=xi
[atCD1
]+bond_ch
*cos(ANGLE_6RING
);
1005 yi
[atHD1
]=yi
[atCD1
]+bond_ch
*sin(ANGLE_6RING
);
1007 yi
[atCE1
]=yi
[atCD1
];
1008 xi
[atHE1
]=xi
[atCE1
]-bond_ch
*cos(ANGLE_6RING
);
1009 yi
[atHE1
]=yi
[atCE1
]+bond_ch
*sin(ANGLE_6RING
);
1010 xi
[atCD2
]=xi
[atCD1
];
1011 yi
[atCD2
]=-yi
[atCD1
];
1012 xi
[atHD2
]=xi
[atHD1
];
1013 yi
[atHD2
]=-yi
[atHD1
];
1014 xi
[atCE2
]=xi
[atCE1
];
1015 yi
[atCE2
]=-yi
[atCE1
];
1016 xi
[atHE2
]=xi
[atHE1
];
1017 yi
[atHE2
]=-yi
[atHE1
];
1018 xi
[atCZ
]=bond_cc
*cos(0.5*ANGLE_6RING
);
1020 xi
[atOH
]=xi
[atCZ
]+bond_co
;
1024 for(i
=0;i
<atOH
;i
++) {
1025 xcom
+=xi
[i
]*at
->atom
[ats
[i
]].m
;
1026 ycom
+=yi
[i
]*at
->atom
[ats
[i
]].m
;
1027 mtot
+=at
->atom
[ats
[i
]].m
;
1032 /* first do 6 ring as default,
1033 except CZ (we'll do that different) and HZ (we don't have that): */
1034 nvsite
= gen_vsites_6ring(at
, vsite_type
, plist
, nrfound
, ats
, bond_cc
, bond_ch
, xcom
, ycom
, FALSE
);
1036 /* then construct CZ from the 2nd triangle */
1037 /* vsite3 construction: r_d = r_i + a r_ij + b r_ik */
1038 a
= b
= 0.5 * bond_co
/ ( bond_co
- bond_cc
*cos(ANGLE_6RING
) );
1039 add_vsite3_param(&plist
[F_VSITE3
],
1040 ats
[atCZ
],ats
[atOH
],ats
[atCE1
],ats
[atCE2
],a
,b
);
1041 at
->atom
[ats
[atCZ
]].m
= at
->atom
[ats
[atCZ
]].mB
= 0;
1043 /* constraints between CE1, CE2 and OH */
1044 dCGCE
= sqrt( cosrule(bond_cc
,bond_cc
,ANGLE_6RING
) );
1045 dCEOH
= sqrt( cosrule(bond_cc
,bond_co
,ANGLE_6RING
) );
1046 my_add_param(&(plist
[F_CONSTRNC
]),ats
[atCE1
],ats
[atOH
],dCEOH
);
1047 my_add_param(&(plist
[F_CONSTRNC
]),ats
[atCE2
],ats
[atOH
],dCEOH
);
1049 /* We also want to constrain the angle C-O-H, but since CZ is constructed
1050 * we need to introduce a constraint to CG.
1051 * CG is much further away, so that will lead to instabilities in LINCS
1052 * when we constrain both CG-HH and OH-HH distances. Instead of requiring
1053 * the use of lincs_order=8 we introduce a dummy mass three times further
1054 * away from OH than HH. The mass is accordingly a third, with the remaining
1055 * 2/3 moved to OH. This shouldnt cause any problems since the forces will
1056 * apply to the HH constructed atom and not directly on the virtual mass.
1060 mM
=at
->atom
[ats
[atHH
]].m
/2.0;
1061 at
->atom
[ats
[atOH
]].m
+=mM
; /* add 1/2 of original H mass */
1062 at
->atom
[ats
[atOH
]].mB
+=mM
; /* add 1/2 of original H mass */
1063 at
->atom
[ats
[atHH
]].m
=at
->atom
[ats
[atHH
]].mB
=0;
1065 /* get dummy mass type */
1066 tpM
=vsite_nm2type("MW",atype
);
1067 /* make space for 1 mass: shift HH only */
1071 fprintf(stderr
,"Inserting 1 dummy mass at %d\n",(*o2n
)[i0
]+1);
1073 for(j
=i0
; j
<at
->nr
; j
++)
1075 srenew(*newx
,at
->nr
+*nadd
);
1076 srenew(*newatom
,at
->nr
+*nadd
);
1077 srenew(*newatomname
,at
->nr
+*nadd
);
1078 srenew(*newvsite_type
,at
->nr
+*nadd
);
1079 srenew(*newcgnr
,at
->nr
+*nadd
);
1080 (*newatomname
)[at
->nr
+*nadd
-1]=NULL
;
1082 /* Calc the dummy mass initial position */
1083 rvec_sub(x
[ats
[atHH
]],x
[ats
[atOH
]],r1
);
1085 rvec_add(r1
,x
[ats
[atHH
]],(*newx
)[atM
]);
1088 (*newatomname
) [atM
] = put_symtab(symtab
,name
);
1089 (*newatom
) [atM
].m
= (*newatom
)[atM
].mB
= mM
;
1090 (*newatom
) [atM
].q
= (*newatom
)[atM
].qB
= 0.0;
1091 (*newatom
) [atM
].type
= (*newatom
)[atM
].typeB
= tpM
;
1092 (*newatom
) [atM
].ptype
= eptAtom
;
1093 (*newatom
) [atM
].resind
= at
->atom
[i0
].resind
;
1094 (*newvsite_type
)[atM
] = NOTSET
;
1095 (*newcgnr
) [atM
] = (*cgnr
)[i0
];
1096 /* renumber cgnr: */
1097 for(i
=i0
; i
<at
->nr
; i
++)
1100 (*vsite_type
)[ats
[atHH
]] = F_VSITE2
;
1102 /* assume we also want the COH angle constrained: */
1103 tmp1
= bond_cc
*cos(0.5*ANGLE_6RING
) + dCGCE
*sin(ANGLE_6RING
*0.5) + bond_co
;
1104 dCGM
= sqrt( cosrule(tmp1
,vdist
,angle_coh
) );
1105 my_add_param(&(plist
[F_CONSTRNC
]),ats
[atCG
],add_shift
+atM
,dCGM
);
1106 my_add_param(&(plist
[F_CONSTRNC
]),ats
[atOH
],add_shift
+atM
,vdist
);
1108 add_vsite2_param(&plist
[F_VSITE2
],
1109 ats
[atHH
],ats
[atOH
],add_shift
+atM
,1.0/2.0);
1113 static int gen_vsites_his(t_atoms
*at
, int *vsite_type
[], t_params plist
[],
1114 int nrfound
, int *ats
, t_vsitetop
*vsitetop
, int nvsitetop
)
1117 real a
,b
,alpha
,dCGCE1
,dCGNE2
;
1118 real sinalpha
,cosalpha
;
1119 real xcom
,ycom
,mtot
;
1120 real mG
,mrest
,mCE1
,mNE2
;
1121 real b_CG_ND1
,b_ND1_CE1
,b_CE1_NE2
,b_CG_CD2
,b_CD2_NE2
;
1122 real b_ND1_HD1
,b_NE2_HE2
,b_CE1_HE1
,b_CD2_HD2
;
1123 real a_CG_ND1_CE1
,a_CG_CD2_NE2
,a_ND1_CE1_NE2
,a_CE1_NE2_CD2
;
1124 real a_NE2_CE1_HE1
,a_NE2_CD2_HD2
,a_CE1_ND1_HD1
,a_CE1_NE2_HE2
;
1127 /* these MUST correspond to the atnms array in do_vsite_aromatics! */
1128 enum { atCG
, atND1
, atHD1
, atCD2
, atHD2
, atCE1
, atHE1
, atNE2
, atHE2
, atNR
};
1129 real x
[atNR
],y
[atNR
];
1131 /* CG, CE1 and NE2 stay, each gets part of the total mass,
1132 rest gets virtualized */
1133 /* check number of atoms, 3 hydrogens may be missing: */
1134 /* assert( nrfound >= atNR-3 || nrfound <= atNR );
1135 * Don't understand the above logic. Shouldn't it be && rather than || ???
1137 if ((nrfound
< atNR
-3) || (nrfound
> atNR
))
1138 gmx_incons("Generating vsites for HIS");
1140 /* avoid warnings about uninitialized variables */
1141 b_ND1_HD1
=b_NE2_HE2
=b_CE1_HE1
=b_CD2_HD2
=a_NE2_CE1_HE1
=
1142 a_NE2_CD2_HD2
=a_CE1_ND1_HD1
=a_CE1_NE2_HE2
=0;
1144 if(ats
[atHD1
]!=NOTSET
) {
1145 if(ats
[atHE2
]!=NOTSET
)
1146 sprintf(resname
,"HISH");
1148 sprintf(resname
,"HISA");
1150 sprintf(resname
,"HISB");
1153 /* Get geometry from database */
1154 b_CG_ND1
=get_ddb_bond(vsitetop
,nvsitetop
,resname
,"CG","ND1");
1155 b_ND1_CE1
=get_ddb_bond(vsitetop
,nvsitetop
,resname
,"ND1","CE1");
1156 b_CE1_NE2
=get_ddb_bond(vsitetop
,nvsitetop
,resname
,"CE1","NE2");
1157 b_CG_CD2
=get_ddb_bond(vsitetop
,nvsitetop
,resname
,"CG","CD2");
1158 b_CD2_NE2
=get_ddb_bond(vsitetop
,nvsitetop
,resname
,"CD2","NE2");
1159 a_CG_ND1_CE1
=DEG2RAD
*get_ddb_angle(vsitetop
,nvsitetop
,resname
,"CG","ND1","CE1");
1160 a_CG_CD2_NE2
=DEG2RAD
*get_ddb_angle(vsitetop
,nvsitetop
,resname
,"CG","CD2","NE2");
1161 a_ND1_CE1_NE2
=DEG2RAD
*get_ddb_angle(vsitetop
,nvsitetop
,resname
,"ND1","CE1","NE2");
1162 a_CE1_NE2_CD2
=DEG2RAD
*get_ddb_angle(vsitetop
,nvsitetop
,resname
,"CE1","NE2","CD2");
1164 if(ats
[atHD1
]!=NOTSET
) {
1165 b_ND1_HD1
=get_ddb_bond(vsitetop
,nvsitetop
,resname
,"ND1","HD1");
1166 a_CE1_ND1_HD1
=DEG2RAD
*get_ddb_angle(vsitetop
,nvsitetop
,resname
,"CE1","ND1","HD1");
1168 if(ats
[atHE2
]!=NOTSET
) {
1169 b_NE2_HE2
=get_ddb_bond(vsitetop
,nvsitetop
,resname
,"NE2","HE2");
1170 a_CE1_NE2_HE2
=DEG2RAD
*get_ddb_angle(vsitetop
,nvsitetop
,resname
,"CE1","NE2","HE2");
1172 if(ats
[atHD2
]!=NOTSET
) {
1173 b_CD2_HD2
=get_ddb_bond(vsitetop
,nvsitetop
,resname
,"CD2","HD2");
1174 a_NE2_CD2_HD2
=DEG2RAD
*get_ddb_angle(vsitetop
,nvsitetop
,resname
,"NE2","CD2","HD2");
1176 if(ats
[atHE1
]!=NOTSET
) {
1177 b_CE1_HE1
=get_ddb_bond(vsitetop
,nvsitetop
,resname
,"CE1","HE1");
1178 a_NE2_CE1_HE1
=DEG2RAD
*get_ddb_angle(vsitetop
,nvsitetop
,resname
,"NE2","CE1","HE1");
1181 /* constraints between CG, CE1 and NE1 */
1182 dCGCE1
= sqrt( cosrule(b_CG_ND1
,b_ND1_CE1
,a_CG_ND1_CE1
) );
1183 dCGNE2
= sqrt( cosrule(b_CG_CD2
,b_CD2_NE2
,a_CG_CD2_NE2
) );
1185 my_add_param(&(plist
[F_CONSTRNC
]),ats
[atCG
] ,ats
[atCE1
],dCGCE1
);
1186 my_add_param(&(plist
[F_CONSTRNC
]),ats
[atCG
] ,ats
[atNE2
],dCGNE2
);
1187 /* we already have a constraint CE1-NE2, so we don't add it again */
1189 /* calculate the positions in a local frame of reference.
1190 * The x-axis is the line from CG that makes a right angle
1191 * with the bond CE1-NE2, and the y-axis the bond CE1-NE2.
1193 /* First calculate the x-axis intersection with y-axis (=yCE1).
1194 * Get cos(angle CG-CE1-NE2) :
1196 cosalpha
=acosrule(dCGNE2
,dCGCE1
,b_CE1_NE2
);
1198 y
[atCE1
] = cosalpha
*dCGCE1
;
1200 y
[atNE2
] = y
[atCE1
]-b_CE1_NE2
;
1201 sinalpha
=sqrt(1-cosalpha
*cosalpha
);
1202 x
[atCG
] = - sinalpha
*dCGCE1
;
1205 /* calculate ND1 and CD2 positions from CE1 and NE2 */
1207 x
[atND1
] = -b_ND1_CE1
*sin(a_ND1_CE1_NE2
);
1208 y
[atND1
] = y
[atCE1
]-b_ND1_CE1
*cos(a_ND1_CE1_NE2
);
1210 x
[atCD2
] = -b_CD2_NE2
*sin(a_CE1_NE2_CD2
);
1211 y
[atCD2
] = y
[atNE2
]+b_CD2_NE2
*cos(a_CE1_NE2_CD2
);
1213 /* And finally the hydrogen positions */
1214 if(ats
[atHE1
]!=NOTSET
) {
1215 x
[atHE1
] = x
[atCE1
] + b_CE1_HE1
*sin(a_NE2_CE1_HE1
);
1216 y
[atHE1
] = y
[atCE1
] - b_CE1_HE1
*cos(a_NE2_CE1_HE1
);
1218 /* HD2 - first get (ccw) angle from (positive) y-axis */
1219 if(ats
[atHD2
]!=NOTSET
) {
1220 alpha
= a_CE1_NE2_CD2
+ M_PI
- a_NE2_CD2_HD2
;
1221 x
[atHD2
] = x
[atCD2
] - b_CD2_HD2
*sin(alpha
);
1222 y
[atHD2
] = y
[atCD2
] + b_CD2_HD2
*cos(alpha
);
1224 if(ats
[atHD1
]!=NOTSET
) {
1225 /* HD1 - first get (cw) angle from (positive) y-axis */
1226 alpha
= a_ND1_CE1_NE2
+ M_PI
- a_CE1_ND1_HD1
;
1227 x
[atHD1
] = x
[atND1
] - b_ND1_HD1
*sin(alpha
);
1228 y
[atHD1
] = y
[atND1
] - b_ND1_HD1
*cos(alpha
);
1230 if(ats
[atHE2
]!=NOTSET
) {
1231 x
[atHE2
] = x
[atNE2
] + b_NE2_HE2
*sin(a_CE1_NE2_HE2
);
1232 y
[atHE2
] = y
[atNE2
] + b_NE2_HE2
*cos(a_CE1_NE2_HE2
);
1234 /* Have all coordinates now */
1236 /* calc center-of-mass; keep atoms CG, CE1, NE2 and
1237 * set the rest to vsite3
1241 for(i
=0; i
<atNR
; i
++)
1242 if (ats
[i
]!=NOTSET
) {
1243 mtot
+=at
->atom
[ats
[i
]].m
;
1244 xcom
+=x
[i
]*at
->atom
[ats
[i
]].m
;
1245 ycom
+=y
[i
]*at
->atom
[ats
[i
]].m
;
1246 if (i
!=atCG
&& i
!=atCE1
&& i
!=atNE2
) {
1247 at
->atom
[ats
[i
]].m
= at
->atom
[ats
[i
]].mB
= 0;
1248 (*vsite_type
)[ats
[i
]]=F_VSITE3
;
1252 if (nvsite
+3 != nrfound
)
1253 gmx_incons("Generating vsites for HIS");
1258 /* distribute mass so that com stays the same */
1259 mG
= xcom
*mtot
/x
[atCG
];
1261 mCE1
= (ycom
-y
[atNE2
])*mrest
/(y
[atCE1
]-y
[atNE2
]);
1264 at
->atom
[ats
[atCG
]].m
= at
->atom
[ats
[atCG
]].mB
= mG
;
1265 at
->atom
[ats
[atCE1
]].m
= at
->atom
[ats
[atCE1
]].mB
= mCE1
;
1266 at
->atom
[ats
[atNE2
]].m
= at
->atom
[ats
[atNE2
]].mB
= mNE2
;
1269 if (ats
[atHE1
]!=NOTSET
) {
1270 calc_vsite3_param(x
[atHE1
],y
[atHE1
],x
[atCE1
],y
[atCE1
],x
[atNE2
],y
[atNE2
],
1271 x
[atCG
],y
[atCG
],&a
,&b
);
1272 add_vsite3_param(&plist
[F_VSITE3
],
1273 ats
[atHE1
],ats
[atCE1
],ats
[atNE2
],ats
[atCG
],a
,b
);
1276 if (ats
[atHE2
]!=NOTSET
) {
1277 calc_vsite3_param(x
[atHE2
],y
[atHE2
],x
[atNE2
],y
[atNE2
],x
[atCE1
],y
[atCE1
],
1278 x
[atCG
],y
[atCG
],&a
,&b
);
1279 add_vsite3_param(&plist
[F_VSITE3
],
1280 ats
[atHE2
],ats
[atNE2
],ats
[atCE1
],ats
[atCG
],a
,b
);
1284 calc_vsite3_param(x
[atND1
],y
[atND1
],x
[atNE2
],y
[atNE2
],x
[atCE1
],y
[atCE1
],
1285 x
[atCG
],y
[atCG
],&a
,&b
);
1286 add_vsite3_param(&plist
[F_VSITE3
],
1287 ats
[atND1
],ats
[atNE2
],ats
[atCE1
],ats
[atCG
],a
,b
);
1290 calc_vsite3_param(x
[atCD2
],y
[atCD2
],x
[atCE1
],y
[atCE1
],x
[atNE2
],y
[atNE2
],
1291 x
[atCG
],y
[atCG
],&a
,&b
);
1292 add_vsite3_param(&plist
[F_VSITE3
],
1293 ats
[atCD2
],ats
[atCE1
],ats
[atNE2
],ats
[atCG
],a
,b
);
1296 if (ats
[atHD1
]!=NOTSET
) {
1297 calc_vsite3_param(x
[atHD1
],y
[atHD1
],x
[atNE2
],y
[atNE2
],x
[atCE1
],y
[atCE1
],
1298 x
[atCG
],y
[atCG
],&a
,&b
);
1299 add_vsite3_param(&plist
[F_VSITE3
],
1300 ats
[atHD1
],ats
[atNE2
],ats
[atCE1
],ats
[atCG
],a
,b
);
1303 if (ats
[atHD2
]!=NOTSET
) {
1304 calc_vsite3_param(x
[atHD2
],y
[atHD2
],x
[atCE1
],y
[atCE1
],x
[atNE2
],y
[atNE2
],
1305 x
[atCG
],y
[atCG
],&a
,&b
);
1306 add_vsite3_param(&plist
[F_VSITE3
],
1307 ats
[atHD2
],ats
[atCE1
],ats
[atNE2
],ats
[atCG
],a
,b
);
1312 static bool is_vsite(int vsite_type
)
1314 if (vsite_type
== NOTSET
)
1316 switch ( abs(vsite_type
) ) {
1329 static char atomnamesuffix
[] = "1234";
1331 void do_vsites(int nrtp
, t_restp rtp
[], gpp_atomtype_t atype
,
1332 t_atoms
*at
, t_symtab
*symtab
, rvec
*x
[],
1333 t_params plist
[], int *vsite_type
[], int *cgnr
[],
1334 real mHmult
, bool bVsiteAromatics
,
1337 #define MAXATOMSPERRESIDUE 16
1338 int i
,j
,k
,i0
,ni0
,whatres
,resind
,add_shift
,ftype
,nvsite
,nadd
;
1340 int nrfound
=0,needed
,nrbonds
,nrHatoms
,Heavy
,nrheavies
,tpM
,tpHeavy
;
1341 int Hatoms
[4],heavies
[4],bb
;
1342 bool bWARNING
,bAddVsiteParam
,bFirstWater
;
1344 bool *bResProcessed
;
1345 real mHtot
,mtot
,fact
,fact2
;
1346 rvec rpar
,rperp
,temp
;
1347 char name
[10],tpname
[32],nexttpname
[32],*ch
;
1349 int *o2n
,*newvsite_type
,*newcgnr
,ats
[MAXATOMSPERRESIDUE
];
1352 char ***newatomname
;
1356 int nvsiteconf
,nvsitetop
,cmplength
;
1357 bool isN
,planarN
,bFound
;
1359 t_vsiteconf
*vsiteconflist
;
1360 /* pointer to a list of CH3/NH3/NH2 configuration entries.
1361 * See comments in read_vsite_database. It isnt beautiful,
1362 * but it had to be fixed, and I dont even want to try to
1363 * maintain this part of the code...
1365 t_vsitetop
*vsitetop
;
1366 /* Pointer to a list of geometry (bond/angle) entries for
1367 * residues like PHE, TRP, TYR, HIS, etc., where we need
1368 * to know the geometry to construct vsite aromatics.
1369 * Note that equilibrium geometry isnt necessarily the same
1370 * as the individual bond and angle values given in the
1371 * force field (rings can be strained).
1374 /* if bVsiteAromatics=TRUE do_vsites will specifically convert atoms in
1375 PHE, TRP, TYR and HIS to a construction of virtual sites */
1376 enum { resPHE
, resTRP
, resTYR
, resHIS
, resNR
};
1377 const char *resnms
[resNR
] = { "PHE", "TRP", "TYR", "HIS" };
1378 /* Amber03 alternative names for termini */
1379 const char *resnmsN
[resNR
] = { "NPHE", "NTRP", "NTYR", "NHIS" };
1380 const char *resnmsC
[resNR
] = { "CPHE", "CTRP", "CTYR", "CHIS" };
1381 /* HIS can be known as HISH, HIS1, HISA, HID, HIE, HIP, etc. too */
1382 bool bPartial
[resNR
] = { FALSE
, FALSE
, FALSE
, TRUE
};
1383 /* the atnms for every residue MUST correspond to the enums in the
1384 gen_vsites_* (one for each residue) routines! */
1385 /* also the atom names in atnms MUST be in the same order as in the .rtp! */
1386 const char *atnms
[resNR
][MAXATOMSPERRESIDUE
+1] = {
1388 "CD1", "HD1", "CD2", "HD2",
1389 "CE1", "HE1", "CE2", "HE2",
1393 "CD1", "HD1", "CD2",
1394 "NE1", "HE1", "CE2", "CE3", "HE3",
1395 "CZ2", "HZ2", "CZ3", "HZ3",
1396 "CH2", "HH2", NULL
},
1398 "CD1", "HD1", "CD2", "HD2",
1399 "CE1", "HE1", "CE2", "HE2",
1400 "CZ", "OH", "HH", NULL
},
1402 "ND1", "HD1", "CD2", "HD2",
1403 "CE1", "HE1", "NE2", "HE2", NULL
}
1407 printf("Searching for atoms to make virtual sites ...\n");
1408 fprintf(debug
,"# # # VSITES # # #\n");
1411 ndb
= fflib_search_file_end(ffdir
,".vsd",FALSE
,&db
);
1413 vsiteconflist
= NULL
;
1416 for(f
=0; f
<ndb
; f
++) {
1417 read_vsite_database(db
[f
],&vsiteconflist
,&nvsiteconf
,&vsitetop
,&nvsitetop
);
1425 /* we need a marker for which atoms should *not* be renumbered afterwards */
1426 add_shift
= 10*at
->nr
;
1427 /* make arrays where masses can be inserted into */
1429 snew(newatom
,at
->nr
);
1430 snew(newatomname
,at
->nr
);
1431 snew(newvsite_type
,at
->nr
);
1432 snew(newcgnr
,at
->nr
);
1433 /* make index array to tell where the atoms go to when masses are inserted */
1435 for(i
=0; i
<at
->nr
; i
++)
1437 /* make index to tell which residues were already processed */
1438 snew(bResProcessed
,at
->nres
);
1440 aan
= get_aa_names();
1442 /* generate vsite constructions */
1443 /* loop over all atoms */
1445 for(i
=0; (i
<at
->nr
); i
++) {
1446 if (at
->atom
[i
].resind
!= resind
) {
1447 resind
= at
->atom
[i
].resind
;
1448 resnm
= *(at
->resinfo
[resind
].name
);
1450 /* first check for aromatics to virtualize */
1451 /* don't waste our effort on DNA, water etc. */
1452 /* Only do the vsite aromatic stuff when we reach the
1453 * CA atom, since there might be an X2/X3 group on the
1454 * N-terminus that must be treated first.
1456 if ( bVsiteAromatics
&&
1457 !strcmp(*(at
->atomname
[i
]),"CA") &&
1458 !bResProcessed
[resind
] &&
1459 is_protein(aan
,*(at
->resinfo
[resind
].name
)) ) {
1460 /* mark this residue */
1461 bResProcessed
[resind
] = TRUE
;
1462 /* find out if this residue needs converting */
1464 for(j
=0; j
<resNR
&& whatres
==NOTSET
; j
++) {
1466 cmplength
= bPartial
[j
] ? strlen(resnm
)-1 : strlen(resnm
);
1468 bFound
= ((strncasecmp(resnm
,resnms
[j
], cmplength
)==0) ||
1469 (strncasecmp(resnm
,resnmsN
[j
],cmplength
)==0) ||
1470 (strncasecmp(resnm
,resnmsC
[j
],cmplength
)==0));
1474 /* get atoms we will be needing for the conversion */
1476 for (k
=0; atnms
[j
][k
]; k
++) {
1479 while (i
<at
->nr
&& at
->atom
[i
].resind
==resind
&& ats
[k
]==NOTSET
) {
1480 if (strcasecmp(*(at
->atomname
[i
]),atnms
[j
][k
])==0) {
1486 /* if nothing found, search next atom from same point */
1490 /* now k is number of atom names in atnms[j] */
1496 gmx_fatal(FARGS
,"not enough atoms found (%d, need %d) in "
1497 "residue %s %d while\n "
1498 "generating aromatics virtual site construction",
1499 nrfound
,needed
,resnm
,at
->resinfo
[resind
].nr
);
1502 /* the enums for every residue MUST correspond to atnms[residue] */
1505 if (debug
) fprintf(stderr
,"PHE at %d\n",o2n
[ats
[0]]+1);
1506 nvsite
+=gen_vsites_phe(at
, vsite_type
, plist
, nrfound
, ats
, vsitetop
, nvsitetop
);
1509 if (debug
) fprintf(stderr
,"TRP at %d\n",o2n
[ats
[0]]+1);
1510 nvsite
+=gen_vsites_trp(atype
, &newx
, &newatom
, &newatomname
, &o2n
,
1511 &newvsite_type
, &newcgnr
, symtab
, &nadd
, *x
, cgnr
,
1512 at
, vsite_type
, plist
, nrfound
, ats
, add_shift
, vsitetop
, nvsitetop
);
1515 if (debug
) fprintf(stderr
,"TYR at %d\n",o2n
[ats
[0]]+1);
1516 nvsite
+=gen_vsites_tyr(atype
, &newx
, &newatom
, &newatomname
, &o2n
,
1517 &newvsite_type
, &newcgnr
, symtab
, &nadd
, *x
, cgnr
,
1518 at
, vsite_type
, plist
, nrfound
, ats
, add_shift
, vsitetop
, nvsitetop
);
1521 if (debug
) fprintf(stderr
,"HIS at %d\n",o2n
[ats
[0]]+1);
1522 nvsite
+=gen_vsites_his(at
, vsite_type
, plist
, nrfound
, ats
, vsitetop
, nvsitetop
);
1525 /* this means this residue won't be processed */
1528 gmx_fatal(FARGS
,"DEATH HORROR in do_vsites (%s:%d)",
1530 } /* switch whatres */
1531 /* skip back to beginning of residue */
1532 while(i
>0 && at
->atom
[i
-1].resind
== resind
)
1534 } /* if bVsiteAromatics & is protein */
1536 /* now process the rest of the hydrogens */
1537 /* only process hydrogen atoms which are not already set */
1538 if ( ((*vsite_type
)[i
]==NOTSET
) && is_hydrogen(*(at
->atomname
[i
]))) {
1539 /* find heavy atom, count #bonds from it and #H atoms bound to it
1540 and return H atom numbers (Hatoms) and heavy atom numbers (heavies) */
1541 count_bonds(i
, &plist
[F_BONDS
], at
->atomname
,
1542 &nrbonds
, &nrHatoms
, Hatoms
, &Heavy
, &nrheavies
, heavies
);
1543 /* get Heavy atom type */
1544 tpHeavy
=get_atype(Heavy
,at
,nrtp
,rtp
,aan
);
1545 strcpy(tpname
,get_atomtype_name(tpHeavy
,atype
));
1548 bAddVsiteParam
=TRUE
;
1549 /* nested if's which check nrHatoms, nrbonds and atomname */
1550 if (nrHatoms
== 1) {
1553 (*vsite_type
)[i
]=F_BONDS
;
1555 case 3: /* =CH-, -NH- or =NH+- */
1556 (*vsite_type
)[i
]=F_VSITE3FD
;
1558 case 4: /* --CH- (tert) */
1559 /* The old type 4FD had stability issues, so
1560 * all new constructs should use 4FDN
1562 (*vsite_type
)[i
]=F_VSITE4FDN
;
1564 /* Check parity of heavy atoms from coordinates */
1569 rvec_sub((*x
)[aj
],(*x
)[ai
],tmpmat
[0]);
1570 rvec_sub((*x
)[ak
],(*x
)[ai
],tmpmat
[1]);
1571 rvec_sub((*x
)[al
],(*x
)[ai
],tmpmat
[2]);
1581 default: /* nrbonds != 2, 3 or 4 */
1585 } else if ( /*(nrHatoms == 2) && (nrbonds == 2) && REMOVED this test
1587 (strncasecmp(*at
->atomname
[Heavy
],"OW",2)==0) ) {
1588 bAddVsiteParam
=FALSE
; /* this is water: skip these hydrogens */
1593 "Not converting hydrogens in water to virtual sites\n");
1595 } else if ( (nrHatoms
== 2) && (nrbonds
== 4) ) {
1596 /* -CH2- , -NH2+- */
1597 (*vsite_type
)[Hatoms
[0]] = F_VSITE3OUT
;
1598 (*vsite_type
)[Hatoms
[1]] =-F_VSITE3OUT
;
1600 /* 2 or 3 hydrogen atom, with 3 or 4 bonds in total to the heavy atom.
1601 * If it is a nitrogen, first check if it is planar.
1604 if((nrHatoms
== 2) && ((*at
->atomname
[Heavy
])[0]=='N')) {
1606 j
=nitrogen_is_planar(vsiteconflist
,nvsiteconf
,tpname
);
1608 gmx_fatal(FARGS
,"No vsite database NH2 entry for type %s\n",tpname
);
1611 if ( (nrHatoms
== 2) && (nrbonds
== 3) && ( !isN
|| planarN
) ) {
1612 /* =CH2 or, if it is a nitrogen NH2, it is a planar one */
1613 (*vsite_type
)[Hatoms
[0]] = F_VSITE3FAD
;
1614 (*vsite_type
)[Hatoms
[1]] =-F_VSITE3FAD
;
1615 } else if ( ( (nrHatoms
== 2) && (nrbonds
== 3) &&
1616 ( isN
&& !planarN
) ) ||
1617 ( (nrHatoms
== 3) && (nrbonds
== 4) ) ) {
1618 /* CH3, NH3 or non-planar NH2 group */
1619 int Hat_vsite_type
[3] = { F_VSITE3
, F_VSITE3OUT
, F_VSITE3OUT
};
1620 bool Hat_SwapParity
[3] = { FALSE
, TRUE
, FALSE
};
1622 if (debug
) fprintf(stderr
,"-XH3 or nonplanar NH2 group at %d\n",i
+1);
1623 bAddVsiteParam
=FALSE
; /* we'll do this ourselves! */
1624 /* -NH2 (umbrella), -NH3+ or -CH3 */
1625 (*vsite_type
)[Heavy
] = F_VSITE3
;
1626 for (j
=0; j
<nrHatoms
; j
++)
1627 (*vsite_type
)[Hatoms
[j
]] = Hat_vsite_type
[j
];
1628 /* get dummy mass type from first char of heavy atom type (N or C) */
1630 strcpy(nexttpname
,get_atomtype_name(get_atype(heavies
[0],at
,nrtp
,rtp
,aan
),atype
));
1631 ch
=get_dummymass_name(vsiteconflist
,nvsiteconf
,tpname
,nexttpname
);
1635 gmx_fatal(FARGS
,"Can't find dummy mass for type %s bonded to type %s in the virtual site database (.vsd files). Add it to the database!\n",tpname
,nexttpname
);
1637 gmx_fatal(FARGS
,"A dummy mass for type %s bonded to type %s is required, but no virtual site database (.vsd) files where found.\n",tpname
,nexttpname
);
1643 tpM
=vsite_nm2type(name
,atype
);
1644 /* make space for 2 masses: shift all atoms starting with 'Heavy' */
1649 fprintf(stderr
,"Inserting %d dummy masses at %d\n",NMASS
,o2n
[i0
]+1);
1651 for(j
=i0
; j
<at
->nr
; j
++)
1654 srenew(newx
,at
->nr
+nadd
);
1655 srenew(newatom
,at
->nr
+nadd
);
1656 srenew(newatomname
,at
->nr
+nadd
);
1657 srenew(newvsite_type
,at
->nr
+nadd
);
1658 srenew(newcgnr
,at
->nr
+nadd
);
1660 for(j
=0; j
<NMASS
; j
++)
1661 newatomname
[at
->nr
+nadd
-1-j
]=NULL
;
1663 /* calculate starting position for the masses */
1665 /* get atom masses, and set Heavy and Hatoms mass to zero */
1666 for(j
=0; j
<nrHatoms
; j
++) {
1667 mHtot
+= get_amass(Hatoms
[j
],at
,nrtp
,rtp
,aan
);
1668 at
->atom
[Hatoms
[j
]].m
= at
->atom
[Hatoms
[j
]].mB
= 0;
1670 mtot
= mHtot
+ get_amass(Heavy
,at
,nrtp
,rtp
,aan
);
1671 at
->atom
[Heavy
].m
= at
->atom
[Heavy
].mB
= 0;
1676 /* generate vectors parallel and perpendicular to rotational axis:
1677 * rpar = Heavy -> Hcom
1678 * rperp = Hcom -> H1 */
1680 for(j
=0; j
<nrHatoms
; j
++)
1681 rvec_inc(rpar
,(*x
)[Hatoms
[j
]]);
1682 svmul(1.0/nrHatoms
,rpar
,rpar
); /* rpar = ( H1+H2+H3 ) / 3 */
1683 rvec_dec(rpar
,(*x
)[Heavy
]); /* - Heavy */
1684 rvec_sub((*x
)[Hatoms
[0]],(*x
)[Heavy
],rperp
);
1685 rvec_dec(rperp
,rpar
); /* rperp = H1 - Heavy - rpar */
1686 /* calc mass positions */
1687 svmul(fact2
,rpar
,temp
);
1688 for (j
=0; (j
<NMASS
); j
++) /* xM = xN + fact2 * rpar +/- fact * rperp */
1689 rvec_add((*x
)[Heavy
],temp
,newx
[ni0
+j
]);
1690 svmul(fact
,rperp
,temp
);
1691 rvec_inc(newx
[ni0
],temp
);
1692 rvec_dec(newx
[ni0
+1],temp
);
1693 /* set atom parameters for the masses */
1694 for(j
=0; (j
<NMASS
); j
++) {
1695 /* make name: "M??#" or "M?#" (? is atomname, # is number) */
1697 for(k
=0; (*at
->atomname
[Heavy
])[k
] && ( k
< NMASS
); k
++ )
1698 name
[k
+1]=(*at
->atomname
[Heavy
])[k
];
1699 name
[k
+1]=atomnamesuffix
[j
];
1701 newatomname
[ni0
+j
] = put_symtab(symtab
,name
);
1702 newatom
[ni0
+j
].m
= newatom
[ni0
+j
].mB
= mtot
/NMASS
;
1703 newatom
[ni0
+j
].q
= newatom
[ni0
+j
].qB
= 0.0;
1704 newatom
[ni0
+j
].type
= newatom
[ni0
+j
].typeB
= tpM
;
1705 newatom
[ni0
+j
].ptype
= eptAtom
;
1706 newatom
[ni0
+j
].resind
= at
->atom
[i0
].resind
;
1707 newvsite_type
[ni0
+j
] = NOTSET
;
1708 newcgnr
[ni0
+j
] = (*cgnr
)[i0
];
1710 /* add constraints between dummy masses and to heavies[0] */
1711 /* 'add_shift' says which atoms won't be renumbered afterwards */
1712 my_add_param(&(plist
[F_CONSTRNC
]),heavies
[0], add_shift
+ni0
, NOTSET
);
1713 my_add_param(&(plist
[F_CONSTRNC
]),heavies
[0], add_shift
+ni0
+1,NOTSET
);
1714 my_add_param(&(plist
[F_CONSTRNC
]),add_shift
+ni0
,add_shift
+ni0
+1,NOTSET
);
1716 /* generate Heavy, H1, H2 and H3 from M1, M2 and heavies[0] */
1717 /* note that vsite_type cannot be NOTSET, because we just set it */
1718 add_vsite3_atoms (&plist
[(*vsite_type
)[Heavy
]],
1719 Heavy
, heavies
[0], add_shift
+ni0
, add_shift
+ni0
+1,
1721 for(j
=0; j
<nrHatoms
; j
++)
1722 add_vsite3_atoms(&plist
[(*vsite_type
)[Hatoms
[j
]]],
1723 Hatoms
[j
], heavies
[0], add_shift
+ni0
, add_shift
+ni0
+1,
1732 "Warning: cannot convert atom %d %s (bound to a heavy atom "
1734 " %d bonds and %d bound hydrogens atoms) to virtual site\n",
1735 i
+1,*(at
->atomname
[i
]),tpname
,nrbonds
,nrHatoms
);
1736 if (bAddVsiteParam
) {
1737 /* add vsite parameters to topology,
1738 also get rid of negative vsite_types */
1739 add_vsites(plist
, (*vsite_type
), Heavy
, nrHatoms
, Hatoms
,
1740 nrheavies
, heavies
);
1741 /* transfer mass of virtual site to Heavy atom */
1742 for(j
=0; j
<nrHatoms
; j
++)
1743 if (is_vsite((*vsite_type
)[Hatoms
[j
]])) {
1744 at
->atom
[Heavy
].m
+= at
->atom
[Hatoms
[j
]].m
;
1745 at
->atom
[Heavy
].mB
= at
->atom
[Heavy
].m
;
1746 at
->atom
[Hatoms
[j
]].m
= at
->atom
[Hatoms
[j
]].mB
= 0;
1751 fprintf(debug
,"atom %d: ",o2n
[i
]+1);
1752 print_bonds(debug
,o2n
,nrHatoms
,Hatoms
,Heavy
,nrheavies
,heavies
);
1754 } /* if vsite NOTSET & is hydrogen */
1756 } /* for i < at->nr */
1758 done_aa_names(&aan
);
1761 fprintf(debug
,"Before inserting new atoms:\n");
1762 for(i
=0; i
<at
->nr
; i
++)
1763 fprintf(debug
,"%4d %4d %4s %4d %4s %6d %-10s\n",i
+1,o2n
[i
]+1,
1764 at
->atomname
[i
]?*(at
->atomname
[i
]):"(NULL)",
1765 at
->resinfo
[at
->atom
[i
].resind
].nr
,
1766 at
->resinfo
[at
->atom
[i
].resind
].name
?
1767 *(at
->resinfo
[at
->atom
[i
].resind
].name
):"(NULL)",
1769 ((*vsite_type
)[i
]==NOTSET
) ?
1770 "NOTSET" : interaction_function
[(*vsite_type
)[i
]].name
);
1771 fprintf(debug
,"new atoms to be inserted:\n");
1772 for(i
=0; i
<at
->nr
+nadd
; i
++)
1774 fprintf(debug
,"%4d %4s %4d %6d %-10s\n",i
+1,
1775 newatomname
[i
]?*(newatomname
[i
]):"(NULL)",
1776 newatom
[i
].resind
,newcgnr
[i
],
1777 (newvsite_type
[i
]==NOTSET
) ?
1778 "NOTSET" : interaction_function
[newvsite_type
[i
]].name
);
1781 /* add all original atoms to the new arrays, using o2n index array */
1782 for(i
=0; i
<at
->nr
; i
++) {
1783 newatomname
[o2n
[i
]] = at
->atomname
[i
];
1784 newatom
[o2n
[i
]] = at
->atom
[i
];
1785 newvsite_type
[o2n
[i
]] = (*vsite_type
)[i
];
1786 newcgnr
[o2n
[i
]] = (*cgnr
) [i
];
1787 copy_rvec((*x
)[i
],newx
[o2n
[i
]]);
1789 /* throw away old atoms */
1791 sfree(at
->atomname
);
1795 /* put in the new ones */
1798 at
->atomname
= newatomname
;
1799 *vsite_type
= newvsite_type
;
1802 if (at
->nr
> add_shift
)
1803 gmx_fatal(FARGS
,"Added impossible amount of dummy masses "
1804 "(%d on a total of %d atoms)\n",nadd
,at
->nr
-nadd
);
1807 fprintf(debug
,"After inserting new atoms:\n");
1808 for(i
=0; i
<at
->nr
; i
++)
1809 fprintf(debug
,"%4d %4s %4d %4s %6d %-10s\n",i
+1,
1810 at
->atomname
[i
]?*(at
->atomname
[i
]):"(NULL)",
1811 at
->resinfo
[at
->atom
[i
].resind
].nr
,
1812 at
->resinfo
[at
->atom
[i
].resind
].name
?
1813 *(at
->resinfo
[at
->atom
[i
].resind
].name
):"(NULL)",
1815 ((*vsite_type
)[i
]==NOTSET
) ?
1816 "NOTSET" : interaction_function
[(*vsite_type
)[i
]].name
);
1819 /* now renumber all the interactions because of the added atoms */
1820 for (ftype
=0; ftype
<F_NRE
; ftype
++) {
1821 params
=&(plist
[ftype
]);
1823 fprintf(debug
,"Renumbering %d %s\n", params
->nr
,
1824 interaction_function
[ftype
].longname
);
1825 for (i
=0; i
<params
->nr
; i
++) {
1826 for (j
=0; j
<NRAL(ftype
); j
++)
1827 if (params
->param
[i
].a
[j
]>=add_shift
) {
1828 if (debug
) fprintf(debug
," [%u -> %u]",params
->param
[i
].a
[j
],
1829 params
->param
[i
].a
[j
]-add_shift
);
1830 params
->param
[i
].a
[j
]=params
->param
[i
].a
[j
]-add_shift
;
1832 if (debug
) fprintf(debug
," [%u -> %d]",params
->param
[i
].a
[j
],
1833 o2n
[params
->param
[i
].a
[j
]]);
1834 params
->param
[i
].a
[j
]=o2n
[params
->param
[i
].a
[j
]];
1836 if (debug
) fprintf(debug
,"\n");
1839 /* now check if atoms in the added constraints are in increasing order */
1840 params
=&(plist
[F_CONSTRNC
]);
1841 for(i
=0; i
<params
->nr
; i
++)
1842 if ( params
->param
[i
].AI
> params
->param
[i
].AJ
) {
1843 j
= params
->param
[i
].AJ
;
1844 params
->param
[i
].AJ
= params
->param
[i
].AI
;
1845 params
->param
[i
].AI
= j
;
1851 /* tell the user what we did */
1852 fprintf(stderr
,"Marked %d virtual sites\n",nvsite
);
1853 fprintf(stderr
,"Added %d dummy masses\n",nadd
);
1854 fprintf(stderr
,"Added %d new constraints\n",plist
[F_CONSTRNC
].nr
);
1857 void do_h_mass(t_params
*psb
, int vsite_type
[], t_atoms
*at
, real mHmult
,
1862 /* loop over all atoms */
1863 for (i
=0; i
<at
->nr
; i
++)
1864 /* adjust masses if i is hydrogen and not a virtual site */
1865 if ( !is_vsite(vsite_type
[i
]) && is_hydrogen(*(at
->atomname
[i
])) ) {
1866 /* find bonded heavy atom */
1868 for(j
=0; (j
<psb
->nr
) && (a
==NOTSET
); j
++) {
1869 /* if other atom is not a virtual site, it is the one we want */
1870 if ( (psb
->param
[j
].AI
==i
) &&
1871 !is_vsite(vsite_type
[psb
->param
[j
].AJ
]) )
1873 else if ( (psb
->param
[j
].AJ
==i
) &&
1874 !is_vsite(vsite_type
[psb
->param
[j
].AI
]) )
1878 gmx_fatal(FARGS
,"Unbound hydrogen atom (%d) found while adjusting mass",
1881 /* adjust mass of i (hydrogen) with mHmult
1882 and correct mass of a (bonded atom) with same amount */
1884 at
->atom
[a
].m
-= (mHmult
-1.0)*at
->atom
[i
].m
;
1885 at
->atom
[a
].mB
-= (mHmult
-1.0)*at
->atom
[i
].m
;
1887 at
->atom
[i
].m
*= mHmult
;
1888 at
->atom
[i
].mB
*= mHmult
;