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 gmx_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(!gmx_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(!gmx_strcasecmp(dirstr
,"HID"))
179 sprintf(dirstr
,"HISA");
180 else if(!gmx_strcasecmp(dirstr
,"HIE"))
181 sprintf(dirstr
,"HISB");
182 else if(!gmx_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 && !gmx_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
) && gmx_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.
281 gmx_bool found
=FALSE
;
282 for(i
=0;i
<nvsiteconf
&& !found
;i
++) {
283 found
=(!gmx_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 */
297 gmx_bool found
=FALSE
;
298 for(i
=0;i
<nvsiteconf
&& !found
;i
++) {
299 found
=(!gmx_strcasecmp(vsiteconflist
[i
].atomtype
,atom
) &&
300 !gmx_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
&& gmx_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
&& gmx_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
[],
419 gmx_residuetype_t rt
)
426 if (at
->atom
[atom
].m
)
427 type
=at
->atom
[atom
].type
;
429 /* get type from rtp */
430 rtpp
= get_restp(*(at
->resinfo
[at
->atom
[atom
].resind
].name
),nrtp
,rtp
);
431 bNterm
= gmx_residuetype_is_protein(rt
,*(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
[],
452 gmx_residuetype_t rt
)
459 if (at
->atom
[atom
].m
)
460 mass
=at
->atom
[atom
].m
;
462 /* get mass from rtp */
463 rtpp
= get_restp(*(at
->resinfo
[at
->atom
[atom
].resind
].name
),nrtp
,rtp
);
464 bNterm
= gmx_residuetype_is_protein(rt
,*(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
;
486 gmx_bool bSwapParity
;
488 for(i
=0; i
<nrHatoms
; i
++) {
489 ftype
=vsite_type
[Hatoms
[i
]];
490 /* Errors in setting the vsite_type should really be caugth earlier,
491 * because here it's not possible to print any useful error message.
492 * But it's still better to print a message than to segfault.
494 if (ftype
== NOTSET
) {
495 gmx_incons("Undetected error in setting up virtual sites");
497 bSwapParity
= (ftype
<0);
498 vsite_type
[Hatoms
[i
]] = ftype
= abs(ftype
);
499 if (ftype
== F_BONDS
) {
500 if ( (nrheavies
!= 1) && (nrHatoms
!= 1) )
501 gmx_fatal(FARGS
,"cannot make constraint in add_vsites for %d heavy "
502 "atoms and %d hydrogen atoms",nrheavies
,nrHatoms
);
503 my_add_param(&(plist
[F_CONSTRNC
]),Hatoms
[i
],heavies
[0],NOTSET
);
510 gmx_fatal(FARGS
,"Not enough heavy atoms (%d) for %s (min 3)",
512 interaction_function
[vsite_type
[Hatoms
[i
]]].name
);
513 add_vsite3_atoms(&plist
[ftype
],Hatoms
[i
],Heavy
,heavies
[0],heavies
[1],
518 moreheavy
=heavies
[1];
520 /* find more heavy atoms */
521 other
=moreheavy
=NOTSET
;
522 for(j
=0; (j
<plist
[F_BONDS
].nr
) && (moreheavy
==NOTSET
); j
++) {
523 if (plist
[F_BONDS
].param
[j
].AI
==heavies
[0])
524 other
=plist
[F_BONDS
].param
[j
].AJ
;
525 else if (plist
[F_BONDS
].param
[j
].AJ
==heavies
[0])
526 other
=plist
[F_BONDS
].param
[j
].AI
;
527 if ( (other
!= NOTSET
) && (other
!= Heavy
) )
530 if (moreheavy
==NOTSET
)
531 gmx_fatal(FARGS
,"Unbound molecule part %d-%d",Heavy
+1,Hatoms
[0]+1);
533 add_vsite3_atoms(&plist
[ftype
],Hatoms
[i
],Heavy
,heavies
[0],moreheavy
,
541 gmx_fatal(FARGS
,"Not enough heavy atoms (%d) for %s (min 4)",
543 interaction_function
[vsite_type
[Hatoms
[i
]]].name
);
545 add_vsite4_atoms(&plist
[ftype
],
546 Hatoms
[0], Heavy
, heavies
[0], heavies
[1], heavies
[2]);
550 gmx_fatal(FARGS
,"can't use add_vsites for interaction function %s",
551 interaction_function
[vsite_type
[Hatoms
[i
]]].name
);
557 #define ANGLE_6RING (DEG2RAD*120)
559 /* cosine rule: a^2 = b^2 + c^2 - 2 b c cos(alpha) */
560 /* get a^2 when a, b and alpha are given: */
561 #define cosrule(b,c,alpha) ( sqr(b) + sqr(c) - 2*b*c*cos(alpha) )
562 /* get cos(alpha) when a, b and c are given: */
563 #define acosrule(a,b,c) ( (sqr(b)+sqr(c)-sqr(a))/(2*b*c) )
565 static int gen_vsites_6ring(t_atoms
*at
, int *vsite_type
[], t_params plist
[],
566 int nrfound
, int *ats
, real bond_cc
, real bond_ch
,
567 real xcom
, real ycom
, gmx_bool bDoZ
)
569 /* these MUST correspond to the atnms array in do_vsite_aromatics! */
570 enum { atCG
, atCD1
, atHD1
, atCD2
, atHD2
, atCE1
, atHE1
, atCE2
, atHE2
,
574 real a
,b
,dCGCE
,tmp1
,tmp2
,mtot
,mG
,mrest
;
575 real xCG
,yCG
,xCE1
,yCE1
,xCE2
,yCE2
;
576 /* CG, CE1 and CE2 stay and each get a part of the total mass,
577 * so the c-o-m stays the same.
582 gmx_incons("Generating vsites on 6-rings");
585 /* constraints between CG, CE1 and CE2: */
586 dCGCE
= sqrt( cosrule(bond_cc
,bond_cc
,ANGLE_6RING
) );
587 my_add_param(&(plist
[F_CONSTRNC
]),ats
[atCG
] ,ats
[atCE1
],dCGCE
);
588 my_add_param(&(plist
[F_CONSTRNC
]),ats
[atCG
] ,ats
[atCE2
],dCGCE
);
589 my_add_param(&(plist
[F_CONSTRNC
]),ats
[atCE1
],ats
[atCE2
],dCGCE
);
591 /* rest will be vsite3 */
594 for(i
=0; i
< (bDoZ
? atNR
: atHZ
) ; i
++) {
595 mtot
+=at
->atom
[ats
[i
]].m
;
596 if ( i
!=atCG
&& i
!=atCE1
&& i
!=atCE2
&& (bDoZ
|| (i
!=atHZ
&& i
!=atCZ
) ) ) {
597 at
->atom
[ats
[i
]].m
= at
->atom
[ats
[i
]].mB
= 0;
598 (*vsite_type
)[ats
[i
]]=F_VSITE3
;
602 /* Distribute mass so center-of-mass stays the same.
603 * The center-of-mass in the call is defined with x=0 at
604 * the CE1-CE2 bond and y=0 at the line from CG to the middle of CE1-CE2 bond.
606 xCG
=-bond_cc
+bond_cc
*cos(ANGLE_6RING
);
609 yCE1
=bond_cc
*sin(0.5*ANGLE_6RING
);
611 yCE2
=-bond_cc
*sin(0.5*ANGLE_6RING
);
613 mG
= at
->atom
[ats
[atCG
]].m
= at
->atom
[ats
[atCG
]].mB
= xcom
*mtot
/xCG
;
615 at
->atom
[ats
[atCE1
]].m
= at
->atom
[ats
[atCE1
]].mB
=
616 at
->atom
[ats
[atCE2
]].m
= at
->atom
[ats
[atCE2
]].mB
= mrest
/ 2;
618 /* vsite3 construction: r_d = r_i + a r_ij + b r_ik */
619 tmp1
= dCGCE
*sin(ANGLE_6RING
*0.5);
620 tmp2
= bond_cc
*cos(0.5*ANGLE_6RING
) + tmp1
;
622 a
= b
= - bond_ch
/ tmp1
;
624 add_vsite3_param(&plist
[F_VSITE3
],
625 ats
[atHE1
],ats
[atCE1
],ats
[atCE2
],ats
[atCG
], a
,b
);
626 add_vsite3_param(&plist
[F_VSITE3
],
627 ats
[atHE2
],ats
[atCE2
],ats
[atCE1
],ats
[atCG
], a
,b
);
628 /* CD1, CD2 and CZ: */
630 add_vsite3_param(&plist
[F_VSITE3
],
631 ats
[atCD1
],ats
[atCE2
],ats
[atCE1
],ats
[atCG
], a
,b
);
632 add_vsite3_param(&plist
[F_VSITE3
],
633 ats
[atCD2
],ats
[atCE1
],ats
[atCE2
],ats
[atCG
], a
,b
);
635 add_vsite3_param(&plist
[F_VSITE3
],
636 ats
[atCZ
], ats
[atCG
], ats
[atCE1
],ats
[atCE2
],a
,b
);
637 /* HD1, HD2 and HZ: */
638 a
= b
= ( bond_ch
+ tmp2
) / tmp1
;
639 add_vsite3_param(&plist
[F_VSITE3
],
640 ats
[atHD1
],ats
[atCE2
],ats
[atCE1
],ats
[atCG
], a
,b
);
641 add_vsite3_param(&plist
[F_VSITE3
],
642 ats
[atHD2
],ats
[atCE1
],ats
[atCE2
],ats
[atCG
], a
,b
);
644 add_vsite3_param(&plist
[F_VSITE3
],
645 ats
[atHZ
], ats
[atCG
], ats
[atCE1
],ats
[atCE2
],a
,b
);
650 static int gen_vsites_phe(t_atoms
*at
, int *vsite_type
[], t_params plist
[],
651 int nrfound
, int *ats
, t_vsitetop
*vsitetop
, int nvsitetop
)
653 real bond_cc
,bond_ch
;
656 /* these MUST correspond to the atnms array in do_vsite_aromatics! */
657 enum { atCG
, atCD1
, atHD1
, atCD2
, atHD2
, atCE1
, atHE1
, atCE2
, atHE2
,
659 real x
[atNR
],y
[atNR
];
660 /* Aromatic rings have 6-fold symmetry, so we only need one bond length.
661 * (angle is always 120 degrees).
663 bond_cc
=get_ddb_bond(vsitetop
,nvsitetop
,"PHE","CD1","CE1");
664 bond_ch
=get_ddb_bond(vsitetop
,nvsitetop
,"PHE","CD1","HD1");
666 x
[atCG
]=-bond_cc
+bond_cc
*cos(ANGLE_6RING
);
669 y
[atCD1
]=bond_cc
*sin(0.5*ANGLE_6RING
);
670 x
[atHD1
]=x
[atCD1
]+bond_ch
*cos(ANGLE_6RING
);
671 y
[atHD1
]=y
[atCD1
]+bond_ch
*sin(ANGLE_6RING
);
674 x
[atHE1
]=x
[atCE1
]-bond_ch
*cos(ANGLE_6RING
);
675 y
[atHE1
]=y
[atCE1
]+bond_ch
*sin(ANGLE_6RING
);
684 x
[atCZ
]=bond_cc
*cos(0.5*ANGLE_6RING
);
686 x
[atHZ
]=x
[atCZ
]+bond_ch
;
690 for(i
=0;i
<atNR
;i
++) {
691 xcom
+=x
[i
]*at
->atom
[ats
[i
]].m
;
692 ycom
+=y
[i
]*at
->atom
[ats
[i
]].m
;
693 mtot
+=at
->atom
[ats
[i
]].m
;
698 return gen_vsites_6ring(at
, vsite_type
, plist
, nrfound
, ats
, bond_cc
, bond_ch
, xcom
, ycom
, TRUE
);
701 static void calc_vsite3_param(real xd
,real yd
,real xi
,real yi
,real xj
,real yj
,
702 real xk
, real yk
, real
*a
, real
*b
)
704 /* determine parameters by solving the equation system, since we know the
705 * virtual site coordinates here.
707 real dx_ij
,dx_ik
,dy_ij
,dy_ik
;
714 b_ij
=sqrt(dx_ij
*dx_ij
+dy_ij
*dy_ij
);
715 b_ik
=sqrt(dx_ik
*dx_ik
+dy_ik
*dy_ik
);
717 *a
= ( (xd
-xi
)*dy_ik
- dx_ik
*(yd
-yi
) ) / (dx_ij
*dy_ik
- dx_ik
*dy_ij
);
718 *b
= ( yd
- yi
- (*a
)*dy_ij
) / dy_ik
;
722 static int gen_vsites_trp(gpp_atomtype_t atype
, rvec
*newx
[],
723 t_atom
*newatom
[], char ***newatomname
[],
724 int *o2n
[], int *newvsite_type
[], int *newcgnr
[],
725 t_symtab
*symtab
, int *nadd
, rvec x
[], int *cgnr
[],
726 t_atoms
*at
, int *vsite_type
[], t_params plist
[],
727 int nrfound
, int *ats
, int add_shift
,
728 t_vsitetop
*vsitetop
, int nvsitetop
)
731 /* these MUST correspond to the atnms array in do_vsite_aromatics! */
733 atCB
, atCG
, atCD1
, atHD1
, atCD2
, atNE1
, atHE1
, atCE2
, atCE3
, atHE3
,
734 atCZ2
, atHZ2
, atCZ3
, atHZ3
, atCH2
, atHH2
, atNR
};
735 /* weights for determining the COM's of both rings (M1 and M2): */
736 real mw
[NMASS
][atNR
] = {
737 { 0, 1, 1, 1, 0.5, 1, 1, 0.5, 0, 0,
739 { 0, 0, 0, 0, 0.5, 0, 0, 0.5, 1, 1,
743 real xi
[atNR
],yi
[atNR
];
744 real xcom
[NMASS
],ycom
[NMASS
],I
,alpha
;
745 real lineA
,lineB
,dist
;
746 real b_CD2_CE2
,b_NE1_CE2
,b_CG_CD2
,b_CH2_HH2
,b_CE2_CZ2
;
747 real b_NE1_HE1
,b_CD2_CE3
,b_CE3_CZ3
,b_CB_CG
;
748 real b_CZ2_CH2
,b_CZ2_HZ2
,b_CD1_HD1
,b_CE3_HE3
;
749 real b_CG_CD1
,b_CZ3_HZ3
;
750 real a_NE1_CE2_CD2
,a_CE2_CD2_CG
,a_CB_CG_CD2
,a_CE2_CD2_CE3
;
751 real a_CB_CG_CD1
,a_CD2_CG_CD1
,a_CE2_CZ2_HZ2
,a_CZ2_CH2_HH2
;
752 real a_CD2_CE2_CZ2
,a_CD2_CE3_CZ3
,a_CE3_CZ3_HZ3
,a_CG_CD1_HD1
;
753 real a_CE2_CZ2_CH2
,a_HE1_NE1_CE2
,a_CD2_CE3_HE3
;
755 int atM
[NMASS
],tpM
,i
,i0
,j
,nvsite
;
756 real mwtot
,mtot
,mM
[NMASS
],dCBM1
,dCBM2
,dM1M2
;
757 real a
,b
,c
[MAXFORCEPARAM
];
758 rvec r_ij
,r_ik
,t1
,t2
;
762 gmx_incons("atom types in gen_vsites_trp");
763 /* Get geometry from database */
764 b_CD2_CE2
=get_ddb_bond(vsitetop
,nvsitetop
,"TRP","CD2","CE2");
765 b_NE1_CE2
=get_ddb_bond(vsitetop
,nvsitetop
,"TRP","NE1","CE2");
766 b_CG_CD1
=get_ddb_bond(vsitetop
,nvsitetop
,"TRP","CG","CD1");
767 b_CG_CD2
=get_ddb_bond(vsitetop
,nvsitetop
,"TRP","CG","CD2");
768 b_CB_CG
=get_ddb_bond(vsitetop
,nvsitetop
,"TRP","CB","CG");
769 b_CE2_CZ2
=get_ddb_bond(vsitetop
,nvsitetop
,"TRP","CE2","CZ2");
770 b_CD2_CE3
=get_ddb_bond(vsitetop
,nvsitetop
,"TRP","CD2","CE3");
771 b_CE3_CZ3
=get_ddb_bond(vsitetop
,nvsitetop
,"TRP","CE3","CZ3");
772 b_CZ2_CH2
=get_ddb_bond(vsitetop
,nvsitetop
,"TRP","CZ2","CH2");
774 b_CD1_HD1
=get_ddb_bond(vsitetop
,nvsitetop
,"TRP","CD1","HD1");
775 b_CZ2_HZ2
=get_ddb_bond(vsitetop
,nvsitetop
,"TRP","CZ2","HZ2");
776 b_NE1_HE1
=get_ddb_bond(vsitetop
,nvsitetop
,"TRP","NE1","HE1");
777 b_CH2_HH2
=get_ddb_bond(vsitetop
,nvsitetop
,"TRP","CH2","HH2");
778 b_CE3_HE3
=get_ddb_bond(vsitetop
,nvsitetop
,"TRP","CE3","HE3");
779 b_CZ3_HZ3
=get_ddb_bond(vsitetop
,nvsitetop
,"TRP","CZ3","HZ3");
781 a_NE1_CE2_CD2
=DEG2RAD
*get_ddb_angle(vsitetop
,nvsitetop
,"TRP","NE1","CE2","CD2");
782 a_CE2_CD2_CG
=DEG2RAD
*get_ddb_angle(vsitetop
,nvsitetop
,"TRP","CE2","CD2","CG");
783 a_CB_CG_CD2
=DEG2RAD
*get_ddb_angle(vsitetop
,nvsitetop
,"TRP","CB","CG","CD2");
784 a_CD2_CG_CD1
=DEG2RAD
*get_ddb_angle(vsitetop
,nvsitetop
,"TRP","CD2","CG","CD1");
785 a_CB_CG_CD1
=DEG2RAD
*get_ddb_angle(vsitetop
,nvsitetop
,"TRP","CB","CG","CD1");
787 a_CE2_CD2_CE3
=DEG2RAD
*get_ddb_angle(vsitetop
,nvsitetop
,"TRP","CE2","CD2","CE3");
788 a_CD2_CE2_CZ2
=DEG2RAD
*get_ddb_angle(vsitetop
,nvsitetop
,"TRP","CD2","CE2","CZ2");
789 a_CD2_CE3_CZ3
=DEG2RAD
*get_ddb_angle(vsitetop
,nvsitetop
,"TRP","CD2","CE3","CZ3");
790 a_CE3_CZ3_HZ3
=DEG2RAD
*get_ddb_angle(vsitetop
,nvsitetop
,"TRP","CE3","CZ3","HZ3");
791 a_CZ2_CH2_HH2
=DEG2RAD
*get_ddb_angle(vsitetop
,nvsitetop
,"TRP","CZ2","CH2","HH2");
792 a_CE2_CZ2_HZ2
=DEG2RAD
*get_ddb_angle(vsitetop
,nvsitetop
,"TRP","CE2","CZ2","HZ2");
793 a_CE2_CZ2_CH2
=DEG2RAD
*get_ddb_angle(vsitetop
,nvsitetop
,"TRP","CE2","CZ2","CH2");
794 a_CG_CD1_HD1
=DEG2RAD
*get_ddb_angle(vsitetop
,nvsitetop
,"TRP","CG","CD1","HD1");
795 a_HE1_NE1_CE2
=DEG2RAD
*get_ddb_angle(vsitetop
,nvsitetop
,"TRP","HE1","NE1","CE2");
796 a_CD2_CE3_HE3
=DEG2RAD
*get_ddb_angle(vsitetop
,nvsitetop
,"TRP","CD2","CE3","HE3");
798 /* Calculate local coordinates.
799 * y-axis (x=0) is the bond CD2-CE2.
800 * x-axis (y=0) is perpendicular to the bond CD2-CE2 and
801 * intersects the middle of the bond.
804 yi
[atCD2
]=-0.5*b_CD2_CE2
;
807 yi
[atCE2
]=0.5*b_CD2_CE2
;
809 xi
[atNE1
]=-b_NE1_CE2
*sin(a_NE1_CE2_CD2
);
810 yi
[atNE1
]=yi
[atCE2
]-b_NE1_CE2
*cos(a_NE1_CE2_CD2
);
812 xi
[atCG
]=-b_CG_CD2
*sin(a_CE2_CD2_CG
);
813 yi
[atCG
]=yi
[atCD2
]+b_CG_CD2
*cos(a_CE2_CD2_CG
);
815 alpha
= a_CE2_CD2_CG
+ M_PI
- a_CB_CG_CD2
;
816 xi
[atCB
]=xi
[atCG
]-b_CB_CG
*sin(alpha
);
817 yi
[atCB
]=yi
[atCG
]+b_CB_CG
*cos(alpha
);
819 alpha
= a_CE2_CD2_CG
+ a_CD2_CG_CD1
- M_PI
;
820 xi
[atCD1
]=xi
[atCG
]-b_CG_CD1
*sin(alpha
);
821 yi
[atCD1
]=yi
[atCG
]+b_CG_CD1
*cos(alpha
);
823 xi
[atCE3
]=b_CD2_CE3
*sin(a_CE2_CD2_CE3
);
824 yi
[atCE3
]=yi
[atCD2
]+b_CD2_CE3
*cos(a_CE2_CD2_CE3
);
826 xi
[atCZ2
]=b_CE2_CZ2
*sin(a_CD2_CE2_CZ2
);
827 yi
[atCZ2
]=yi
[atCE2
]-b_CE2_CZ2
*cos(a_CD2_CE2_CZ2
);
829 alpha
= a_CE2_CD2_CE3
+ a_CD2_CE3_CZ3
- M_PI
;
830 xi
[atCZ3
]=xi
[atCE3
]+b_CE3_CZ3
*sin(alpha
);
831 yi
[atCZ3
]=yi
[atCE3
]+b_CE3_CZ3
*cos(alpha
);
833 alpha
= a_CD2_CE2_CZ2
+ a_CE2_CZ2_CH2
- M_PI
;
834 xi
[atCH2
]=xi
[atCZ2
]+b_CZ2_CH2
*sin(alpha
);
835 yi
[atCH2
]=yi
[atCZ2
]-b_CZ2_CH2
*cos(alpha
);
838 alpha
= a_CE2_CD2_CG
+ a_CD2_CG_CD1
- a_CG_CD1_HD1
;
839 xi
[atHD1
]=xi
[atCD1
]-b_CD1_HD1
*sin(alpha
);
840 yi
[atHD1
]=yi
[atCD1
]+b_CD1_HD1
*cos(alpha
);
842 alpha
= a_NE1_CE2_CD2
+ M_PI
- a_HE1_NE1_CE2
;
843 xi
[atHE1
]=xi
[atNE1
]-b_NE1_HE1
*sin(alpha
);
844 yi
[atHE1
]=yi
[atNE1
]-b_NE1_HE1
*cos(alpha
);
846 alpha
= a_CE2_CD2_CE3
+ M_PI
- a_CD2_CE3_HE3
;
847 xi
[atHE3
]=xi
[atCE3
]+b_CE3_HE3
*sin(alpha
);
848 yi
[atHE3
]=yi
[atCE3
]+b_CE3_HE3
*cos(alpha
);
850 alpha
= a_CD2_CE2_CZ2
+ M_PI
- a_CE2_CZ2_HZ2
;
851 xi
[atHZ2
]=xi
[atCZ2
]+b_CZ2_HZ2
*sin(alpha
);
852 yi
[atHZ2
]=yi
[atCZ2
]-b_CZ2_HZ2
*cos(alpha
);
854 alpha
= a_CD2_CE2_CZ2
+ a_CE2_CZ2_CH2
- a_CZ2_CH2_HH2
;
855 xi
[atHZ3
]=xi
[atCZ3
]+b_CZ3_HZ3
*sin(alpha
);
856 yi
[atHZ3
]=yi
[atCZ3
]+b_CZ3_HZ3
*cos(alpha
);
858 alpha
= a_CE2_CD2_CE3
+ a_CD2_CE3_CZ3
- a_CE3_CZ3_HZ3
;
859 xi
[atHH2
]=xi
[atCH2
]+b_CH2_HH2
*sin(alpha
);
860 yi
[atHH2
]=yi
[atCH2
]-b_CH2_HH2
*cos(alpha
);
862 /* Determine coeff. for the line CB-CG */
863 lineA
=(yi
[atCB
]-yi
[atCG
])/(xi
[atCB
]-xi
[atCG
]);
864 lineB
=yi
[atCG
]-lineA
*xi
[atCG
];
866 /* Calculate masses for each ring and put it on the dummy masses */
867 for(j
=0; j
<NMASS
; j
++)
868 mM
[j
]=xcom
[j
]=ycom
[j
]=0;
869 for(i
=0; i
<atNR
; i
++) {
871 for(j
=0; j
<NMASS
; j
++) {
872 mM
[j
] += mw
[j
][i
] * at
->atom
[ats
[i
]].m
;
873 xcom
[j
] += xi
[i
] * mw
[j
][i
] * at
->atom
[ats
[i
]].m
;
874 ycom
[j
] += yi
[i
] * mw
[j
][i
] * at
->atom
[ats
[i
]].m
;
878 for(j
=0; j
<NMASS
; j
++) {
883 /* get dummy mass type */
884 tpM
=vsite_nm2type("MW",atype
);
885 /* make space for 2 masses: shift all atoms starting with CB */
887 for(j
=0; j
<NMASS
; j
++)
890 fprintf(stderr
,"Inserting %d dummy masses at %d\n",NMASS
,(*o2n
)[i0
]+1);
892 for(j
=i0
; j
<at
->nr
; j
++)
894 srenew(*newx
,at
->nr
+*nadd
);
895 srenew(*newatom
,at
->nr
+*nadd
);
896 srenew(*newatomname
,at
->nr
+*nadd
);
897 srenew(*newvsite_type
,at
->nr
+*nadd
);
898 srenew(*newcgnr
,at
->nr
+*nadd
);
899 for(j
=0; j
<NMASS
; j
++)
900 (*newatomname
)[at
->nr
+*nadd
-1-j
]=NULL
;
902 /* Dummy masses will be placed at the center-of-mass in each ring. */
904 /* calc initial position for dummy masses in real (non-local) coordinates.
905 * Cheat by using the routine to calculate virtual site parameters. It is
906 * much easier when we have the coordinates expressed in terms of
909 rvec_sub(x
[ats
[atCB
]],x
[ats
[atCG
]],r_ij
);
910 rvec_sub(x
[ats
[atCD2
]],x
[ats
[atCG
]],r_ik
);
911 calc_vsite3_param(xcom
[0],ycom
[0],xi
[atCG
],yi
[atCG
],xi
[atCB
],yi
[atCB
],
912 xi
[atCD2
],yi
[atCD2
],&a
,&b
);
916 rvec_add(t1
,x
[ats
[atCG
]],(*newx
)[atM
[0]]);
918 calc_vsite3_param(xcom
[1],ycom
[1],xi
[atCG
],yi
[atCG
],xi
[atCB
],yi
[atCB
],
919 xi
[atCD2
],yi
[atCD2
],&a
,&b
);
923 rvec_add(t1
,x
[ats
[atCG
]],(*newx
)[atM
[1]]);
925 /* set parameters for the masses */
926 for(j
=0; j
<NMASS
; j
++) {
927 sprintf(name
,"MW%d",j
+1);
928 (*newatomname
) [atM
[j
]] = put_symtab(symtab
,name
);
929 (*newatom
) [atM
[j
]].m
= (*newatom
)[atM
[j
]].mB
= mM
[j
];
930 (*newatom
) [atM
[j
]].q
= (*newatom
)[atM
[j
]].qB
= 0.0;
931 (*newatom
) [atM
[j
]].type
= (*newatom
)[atM
[j
]].typeB
= tpM
;
932 (*newatom
) [atM
[j
]].ptype
= eptAtom
;
933 (*newatom
) [atM
[j
]].resind
= at
->atom
[i0
].resind
;
934 (*newvsite_type
)[atM
[j
]] = NOTSET
;
935 (*newcgnr
) [atM
[j
]] = (*cgnr
)[i0
];
938 for(i
=i0
; i
<at
->nr
; i
++)
941 /* constraints between CB, M1 and M2 */
942 /* 'add_shift' says which atoms won't be renumbered afterwards */
943 dCBM1
= sqrt( sqr(xcom
[0]-xi
[atCB
]) + sqr(ycom
[0]-yi
[atCB
]) );
944 dM1M2
= sqrt( sqr(xcom
[0]-xcom
[1]) + sqr(ycom
[0]-ycom
[1]) );
945 dCBM2
= sqrt( sqr(xcom
[1]-xi
[atCB
]) + sqr(ycom
[1]-yi
[atCB
]) );
946 my_add_param(&(plist
[F_CONSTRNC
]),ats
[atCB
], add_shift
+atM
[0],dCBM1
);
947 my_add_param(&(plist
[F_CONSTRNC
]),ats
[atCB
], add_shift
+atM
[1],dCBM2
);
948 my_add_param(&(plist
[F_CONSTRNC
]),add_shift
+atM
[0],add_shift
+atM
[1],dM1M2
);
950 /* rest will be vsite3 */
952 for(i
=0; i
<atNR
; i
++)
954 at
->atom
[ats
[i
]].m
= at
->atom
[ats
[i
]].mB
= 0;
955 (*vsite_type
)[ats
[i
]] = F_VSITE3
;
959 /* now define all vsites from M1, M2, CB, ie:
960 r_d = r_M1 + a r_M1_M2 + b r_M1_CB */
961 for(i
=0; i
<atNR
; i
++)
962 if ( (*vsite_type
)[ats
[i
]] == F_VSITE3
) {
963 calc_vsite3_param(xi
[i
],yi
[i
],xcom
[0],ycom
[0],xcom
[1],ycom
[1],xi
[atCB
],yi
[atCB
],&a
,&b
);
964 add_vsite3_param(&plist
[F_VSITE3
],
965 ats
[i
],add_shift
+atM
[0],add_shift
+atM
[1],ats
[atCB
],a
,b
);
972 static int gen_vsites_tyr(gpp_atomtype_t atype
, rvec
*newx
[],
973 t_atom
*newatom
[], char ***newatomname
[],
974 int *o2n
[], int *newvsite_type
[], int *newcgnr
[],
975 t_symtab
*symtab
, int *nadd
, rvec x
[], int *cgnr
[],
976 t_atoms
*at
, int *vsite_type
[], t_params plist
[],
977 int nrfound
, int *ats
, int add_shift
,
978 t_vsitetop
*vsitetop
, int nvsitetop
)
980 int nvsite
,i
,i0
,j
,atM
,tpM
;
981 real dCGCE
,dCEOH
,dCGM
,tmp1
,a
,b
;
982 real bond_cc
,bond_ch
,bond_co
,bond_oh
,angle_coh
;
988 /* these MUST correspond to the atnms array in do_vsite_aromatics! */
989 enum { atCG
, atCD1
, atHD1
, atCD2
, atHD2
, atCE1
, atHE1
, atCE2
, atHE2
,
990 atCZ
, atOH
, atHH
, atNR
};
991 real xi
[atNR
],yi
[atNR
];
992 /* CG, CE1, CE2 (as in general 6-ring) and OH and HH stay,
993 rest gets virtualized.
994 Now we have two linked triangles with one improper keeping them flat */
996 gmx_incons("Number of atom types in gen_vsites_tyr");
998 /* Aromatic rings have 6-fold symmetry, so we only need one bond length
999 * for the ring part (angle is always 120 degrees).
1001 bond_cc
=get_ddb_bond(vsitetop
,nvsitetop
,"TYR","CD1","CE1");
1002 bond_ch
=get_ddb_bond(vsitetop
,nvsitetop
,"TYR","CD1","HD1");
1003 bond_co
=get_ddb_bond(vsitetop
,nvsitetop
,"TYR","CZ","OH");
1004 bond_oh
=get_ddb_bond(vsitetop
,nvsitetop
,"TYR","OH","HH");
1005 angle_coh
=DEG2RAD
*get_ddb_angle(vsitetop
,nvsitetop
,"TYR","CZ","OH","HH");
1007 xi
[atCG
]=-bond_cc
+bond_cc
*cos(ANGLE_6RING
);
1010 yi
[atCD1
]=bond_cc
*sin(0.5*ANGLE_6RING
);
1011 xi
[atHD1
]=xi
[atCD1
]+bond_ch
*cos(ANGLE_6RING
);
1012 yi
[atHD1
]=yi
[atCD1
]+bond_ch
*sin(ANGLE_6RING
);
1014 yi
[atCE1
]=yi
[atCD1
];
1015 xi
[atHE1
]=xi
[atCE1
]-bond_ch
*cos(ANGLE_6RING
);
1016 yi
[atHE1
]=yi
[atCE1
]+bond_ch
*sin(ANGLE_6RING
);
1017 xi
[atCD2
]=xi
[atCD1
];
1018 yi
[atCD2
]=-yi
[atCD1
];
1019 xi
[atHD2
]=xi
[atHD1
];
1020 yi
[atHD2
]=-yi
[atHD1
];
1021 xi
[atCE2
]=xi
[atCE1
];
1022 yi
[atCE2
]=-yi
[atCE1
];
1023 xi
[atHE2
]=xi
[atHE1
];
1024 yi
[atHE2
]=-yi
[atHE1
];
1025 xi
[atCZ
]=bond_cc
*cos(0.5*ANGLE_6RING
);
1027 xi
[atOH
]=xi
[atCZ
]+bond_co
;
1031 for(i
=0;i
<atOH
;i
++) {
1032 xcom
+=xi
[i
]*at
->atom
[ats
[i
]].m
;
1033 ycom
+=yi
[i
]*at
->atom
[ats
[i
]].m
;
1034 mtot
+=at
->atom
[ats
[i
]].m
;
1039 /* first do 6 ring as default,
1040 except CZ (we'll do that different) and HZ (we don't have that): */
1041 nvsite
= gen_vsites_6ring(at
, vsite_type
, plist
, nrfound
, ats
, bond_cc
, bond_ch
, xcom
, ycom
, FALSE
);
1043 /* then construct CZ from the 2nd triangle */
1044 /* vsite3 construction: r_d = r_i + a r_ij + b r_ik */
1045 a
= b
= 0.5 * bond_co
/ ( bond_co
- bond_cc
*cos(ANGLE_6RING
) );
1046 add_vsite3_param(&plist
[F_VSITE3
],
1047 ats
[atCZ
],ats
[atOH
],ats
[atCE1
],ats
[atCE2
],a
,b
);
1048 at
->atom
[ats
[atCZ
]].m
= at
->atom
[ats
[atCZ
]].mB
= 0;
1050 /* constraints between CE1, CE2 and OH */
1051 dCGCE
= sqrt( cosrule(bond_cc
,bond_cc
,ANGLE_6RING
) );
1052 dCEOH
= sqrt( cosrule(bond_cc
,bond_co
,ANGLE_6RING
) );
1053 my_add_param(&(plist
[F_CONSTRNC
]),ats
[atCE1
],ats
[atOH
],dCEOH
);
1054 my_add_param(&(plist
[F_CONSTRNC
]),ats
[atCE2
],ats
[atOH
],dCEOH
);
1056 /* We also want to constrain the angle C-O-H, but since CZ is constructed
1057 * we need to introduce a constraint to CG.
1058 * CG is much further away, so that will lead to instabilities in LINCS
1059 * when we constrain both CG-HH and OH-HH distances. Instead of requiring
1060 * the use of lincs_order=8 we introduce a dummy mass three times further
1061 * away from OH than HH. The mass is accordingly a third, with the remaining
1062 * 2/3 moved to OH. This shouldnt cause any problems since the forces will
1063 * apply to the HH constructed atom and not directly on the virtual mass.
1067 mM
=at
->atom
[ats
[atHH
]].m
/2.0;
1068 at
->atom
[ats
[atOH
]].m
+=mM
; /* add 1/2 of original H mass */
1069 at
->atom
[ats
[atOH
]].mB
+=mM
; /* add 1/2 of original H mass */
1070 at
->atom
[ats
[atHH
]].m
=at
->atom
[ats
[atHH
]].mB
=0;
1072 /* get dummy mass type */
1073 tpM
=vsite_nm2type("MW",atype
);
1074 /* make space for 1 mass: shift HH only */
1078 fprintf(stderr
,"Inserting 1 dummy mass at %d\n",(*o2n
)[i0
]+1);
1080 for(j
=i0
; j
<at
->nr
; j
++)
1082 srenew(*newx
,at
->nr
+*nadd
);
1083 srenew(*newatom
,at
->nr
+*nadd
);
1084 srenew(*newatomname
,at
->nr
+*nadd
);
1085 srenew(*newvsite_type
,at
->nr
+*nadd
);
1086 srenew(*newcgnr
,at
->nr
+*nadd
);
1087 (*newatomname
)[at
->nr
+*nadd
-1]=NULL
;
1089 /* Calc the dummy mass initial position */
1090 rvec_sub(x
[ats
[atHH
]],x
[ats
[atOH
]],r1
);
1092 rvec_add(r1
,x
[ats
[atHH
]],(*newx
)[atM
]);
1095 (*newatomname
) [atM
] = put_symtab(symtab
,name
);
1096 (*newatom
) [atM
].m
= (*newatom
)[atM
].mB
= mM
;
1097 (*newatom
) [atM
].q
= (*newatom
)[atM
].qB
= 0.0;
1098 (*newatom
) [atM
].type
= (*newatom
)[atM
].typeB
= tpM
;
1099 (*newatom
) [atM
].ptype
= eptAtom
;
1100 (*newatom
) [atM
].resind
= at
->atom
[i0
].resind
;
1101 (*newvsite_type
)[atM
] = NOTSET
;
1102 (*newcgnr
) [atM
] = (*cgnr
)[i0
];
1103 /* renumber cgnr: */
1104 for(i
=i0
; i
<at
->nr
; i
++)
1107 (*vsite_type
)[ats
[atHH
]] = F_VSITE2
;
1109 /* assume we also want the COH angle constrained: */
1110 tmp1
= bond_cc
*cos(0.5*ANGLE_6RING
) + dCGCE
*sin(ANGLE_6RING
*0.5) + bond_co
;
1111 dCGM
= sqrt( cosrule(tmp1
,vdist
,angle_coh
) );
1112 my_add_param(&(plist
[F_CONSTRNC
]),ats
[atCG
],add_shift
+atM
,dCGM
);
1113 my_add_param(&(plist
[F_CONSTRNC
]),ats
[atOH
],add_shift
+atM
,vdist
);
1115 add_vsite2_param(&plist
[F_VSITE2
],
1116 ats
[atHH
],ats
[atOH
],add_shift
+atM
,1.0/2.0);
1120 static int gen_vsites_his(t_atoms
*at
, int *vsite_type
[], t_params plist
[],
1121 int nrfound
, int *ats
, t_vsitetop
*vsitetop
, int nvsitetop
)
1124 real a
,b
,alpha
,dCGCE1
,dCGNE2
;
1125 real sinalpha
,cosalpha
;
1126 real xcom
,ycom
,mtot
;
1127 real mG
,mrest
,mCE1
,mNE2
;
1128 real b_CG_ND1
,b_ND1_CE1
,b_CE1_NE2
,b_CG_CD2
,b_CD2_NE2
;
1129 real b_ND1_HD1
,b_NE2_HE2
,b_CE1_HE1
,b_CD2_HD2
;
1130 real a_CG_ND1_CE1
,a_CG_CD2_NE2
,a_ND1_CE1_NE2
,a_CE1_NE2_CD2
;
1131 real a_NE2_CE1_HE1
,a_NE2_CD2_HD2
,a_CE1_ND1_HD1
,a_CE1_NE2_HE2
;
1134 /* these MUST correspond to the atnms array in do_vsite_aromatics! */
1135 enum { atCG
, atND1
, atHD1
, atCD2
, atHD2
, atCE1
, atHE1
, atNE2
, atHE2
, atNR
};
1136 real x
[atNR
],y
[atNR
];
1138 /* CG, CE1 and NE2 stay, each gets part of the total mass,
1139 rest gets virtualized */
1140 /* check number of atoms, 3 hydrogens may be missing: */
1141 /* assert( nrfound >= atNR-3 || nrfound <= atNR );
1142 * Don't understand the above logic. Shouldn't it be && rather than || ???
1144 if ((nrfound
< atNR
-3) || (nrfound
> atNR
))
1145 gmx_incons("Generating vsites for HIS");
1147 /* avoid warnings about uninitialized variables */
1148 b_ND1_HD1
=b_NE2_HE2
=b_CE1_HE1
=b_CD2_HD2
=a_NE2_CE1_HE1
=
1149 a_NE2_CD2_HD2
=a_CE1_ND1_HD1
=a_CE1_NE2_HE2
=0;
1151 if(ats
[atHD1
]!=NOTSET
) {
1152 if(ats
[atHE2
]!=NOTSET
)
1153 sprintf(resname
,"HISH");
1155 sprintf(resname
,"HISA");
1157 sprintf(resname
,"HISB");
1160 /* Get geometry from database */
1161 b_CG_ND1
=get_ddb_bond(vsitetop
,nvsitetop
,resname
,"CG","ND1");
1162 b_ND1_CE1
=get_ddb_bond(vsitetop
,nvsitetop
,resname
,"ND1","CE1");
1163 b_CE1_NE2
=get_ddb_bond(vsitetop
,nvsitetop
,resname
,"CE1","NE2");
1164 b_CG_CD2
=get_ddb_bond(vsitetop
,nvsitetop
,resname
,"CG","CD2");
1165 b_CD2_NE2
=get_ddb_bond(vsitetop
,nvsitetop
,resname
,"CD2","NE2");
1166 a_CG_ND1_CE1
=DEG2RAD
*get_ddb_angle(vsitetop
,nvsitetop
,resname
,"CG","ND1","CE1");
1167 a_CG_CD2_NE2
=DEG2RAD
*get_ddb_angle(vsitetop
,nvsitetop
,resname
,"CG","CD2","NE2");
1168 a_ND1_CE1_NE2
=DEG2RAD
*get_ddb_angle(vsitetop
,nvsitetop
,resname
,"ND1","CE1","NE2");
1169 a_CE1_NE2_CD2
=DEG2RAD
*get_ddb_angle(vsitetop
,nvsitetop
,resname
,"CE1","NE2","CD2");
1171 if(ats
[atHD1
]!=NOTSET
) {
1172 b_ND1_HD1
=get_ddb_bond(vsitetop
,nvsitetop
,resname
,"ND1","HD1");
1173 a_CE1_ND1_HD1
=DEG2RAD
*get_ddb_angle(vsitetop
,nvsitetop
,resname
,"CE1","ND1","HD1");
1175 if(ats
[atHE2
]!=NOTSET
) {
1176 b_NE2_HE2
=get_ddb_bond(vsitetop
,nvsitetop
,resname
,"NE2","HE2");
1177 a_CE1_NE2_HE2
=DEG2RAD
*get_ddb_angle(vsitetop
,nvsitetop
,resname
,"CE1","NE2","HE2");
1179 if(ats
[atHD2
]!=NOTSET
) {
1180 b_CD2_HD2
=get_ddb_bond(vsitetop
,nvsitetop
,resname
,"CD2","HD2");
1181 a_NE2_CD2_HD2
=DEG2RAD
*get_ddb_angle(vsitetop
,nvsitetop
,resname
,"NE2","CD2","HD2");
1183 if(ats
[atHE1
]!=NOTSET
) {
1184 b_CE1_HE1
=get_ddb_bond(vsitetop
,nvsitetop
,resname
,"CE1","HE1");
1185 a_NE2_CE1_HE1
=DEG2RAD
*get_ddb_angle(vsitetop
,nvsitetop
,resname
,"NE2","CE1","HE1");
1188 /* constraints between CG, CE1 and NE1 */
1189 dCGCE1
= sqrt( cosrule(b_CG_ND1
,b_ND1_CE1
,a_CG_ND1_CE1
) );
1190 dCGNE2
= sqrt( cosrule(b_CG_CD2
,b_CD2_NE2
,a_CG_CD2_NE2
) );
1192 my_add_param(&(plist
[F_CONSTRNC
]),ats
[atCG
] ,ats
[atCE1
],dCGCE1
);
1193 my_add_param(&(plist
[F_CONSTRNC
]),ats
[atCG
] ,ats
[atNE2
],dCGNE2
);
1194 /* we already have a constraint CE1-NE2, so we don't add it again */
1196 /* calculate the positions in a local frame of reference.
1197 * The x-axis is the line from CG that makes a right angle
1198 * with the bond CE1-NE2, and the y-axis the bond CE1-NE2.
1200 /* First calculate the x-axis intersection with y-axis (=yCE1).
1201 * Get cos(angle CG-CE1-NE2) :
1203 cosalpha
=acosrule(dCGNE2
,dCGCE1
,b_CE1_NE2
);
1205 y
[atCE1
] = cosalpha
*dCGCE1
;
1207 y
[atNE2
] = y
[atCE1
]-b_CE1_NE2
;
1208 sinalpha
=sqrt(1-cosalpha
*cosalpha
);
1209 x
[atCG
] = - sinalpha
*dCGCE1
;
1212 /* calculate ND1 and CD2 positions from CE1 and NE2 */
1214 x
[atND1
] = -b_ND1_CE1
*sin(a_ND1_CE1_NE2
);
1215 y
[atND1
] = y
[atCE1
]-b_ND1_CE1
*cos(a_ND1_CE1_NE2
);
1217 x
[atCD2
] = -b_CD2_NE2
*sin(a_CE1_NE2_CD2
);
1218 y
[atCD2
] = y
[atNE2
]+b_CD2_NE2
*cos(a_CE1_NE2_CD2
);
1220 /* And finally the hydrogen positions */
1221 if(ats
[atHE1
]!=NOTSET
) {
1222 x
[atHE1
] = x
[atCE1
] + b_CE1_HE1
*sin(a_NE2_CE1_HE1
);
1223 y
[atHE1
] = y
[atCE1
] - b_CE1_HE1
*cos(a_NE2_CE1_HE1
);
1225 /* HD2 - first get (ccw) angle from (positive) y-axis */
1226 if(ats
[atHD2
]!=NOTSET
) {
1227 alpha
= a_CE1_NE2_CD2
+ M_PI
- a_NE2_CD2_HD2
;
1228 x
[atHD2
] = x
[atCD2
] - b_CD2_HD2
*sin(alpha
);
1229 y
[atHD2
] = y
[atCD2
] + b_CD2_HD2
*cos(alpha
);
1231 if(ats
[atHD1
]!=NOTSET
) {
1232 /* HD1 - first get (cw) angle from (positive) y-axis */
1233 alpha
= a_ND1_CE1_NE2
+ M_PI
- a_CE1_ND1_HD1
;
1234 x
[atHD1
] = x
[atND1
] - b_ND1_HD1
*sin(alpha
);
1235 y
[atHD1
] = y
[atND1
] - b_ND1_HD1
*cos(alpha
);
1237 if(ats
[atHE2
]!=NOTSET
) {
1238 x
[atHE2
] = x
[atNE2
] + b_NE2_HE2
*sin(a_CE1_NE2_HE2
);
1239 y
[atHE2
] = y
[atNE2
] + b_NE2_HE2
*cos(a_CE1_NE2_HE2
);
1241 /* Have all coordinates now */
1243 /* calc center-of-mass; keep atoms CG, CE1, NE2 and
1244 * set the rest to vsite3
1248 for(i
=0; i
<atNR
; i
++)
1249 if (ats
[i
]!=NOTSET
) {
1250 mtot
+=at
->atom
[ats
[i
]].m
;
1251 xcom
+=x
[i
]*at
->atom
[ats
[i
]].m
;
1252 ycom
+=y
[i
]*at
->atom
[ats
[i
]].m
;
1253 if (i
!=atCG
&& i
!=atCE1
&& i
!=atNE2
) {
1254 at
->atom
[ats
[i
]].m
= at
->atom
[ats
[i
]].mB
= 0;
1255 (*vsite_type
)[ats
[i
]]=F_VSITE3
;
1259 if (nvsite
+3 != nrfound
)
1260 gmx_incons("Generating vsites for HIS");
1265 /* distribute mass so that com stays the same */
1266 mG
= xcom
*mtot
/x
[atCG
];
1268 mCE1
= (ycom
-y
[atNE2
])*mrest
/(y
[atCE1
]-y
[atNE2
]);
1271 at
->atom
[ats
[atCG
]].m
= at
->atom
[ats
[atCG
]].mB
= mG
;
1272 at
->atom
[ats
[atCE1
]].m
= at
->atom
[ats
[atCE1
]].mB
= mCE1
;
1273 at
->atom
[ats
[atNE2
]].m
= at
->atom
[ats
[atNE2
]].mB
= mNE2
;
1276 if (ats
[atHE1
]!=NOTSET
) {
1277 calc_vsite3_param(x
[atHE1
],y
[atHE1
],x
[atCE1
],y
[atCE1
],x
[atNE2
],y
[atNE2
],
1278 x
[atCG
],y
[atCG
],&a
,&b
);
1279 add_vsite3_param(&plist
[F_VSITE3
],
1280 ats
[atHE1
],ats
[atCE1
],ats
[atNE2
],ats
[atCG
],a
,b
);
1283 if (ats
[atHE2
]!=NOTSET
) {
1284 calc_vsite3_param(x
[atHE2
],y
[atHE2
],x
[atNE2
],y
[atNE2
],x
[atCE1
],y
[atCE1
],
1285 x
[atCG
],y
[atCG
],&a
,&b
);
1286 add_vsite3_param(&plist
[F_VSITE3
],
1287 ats
[atHE2
],ats
[atNE2
],ats
[atCE1
],ats
[atCG
],a
,b
);
1291 calc_vsite3_param(x
[atND1
],y
[atND1
],x
[atNE2
],y
[atNE2
],x
[atCE1
],y
[atCE1
],
1292 x
[atCG
],y
[atCG
],&a
,&b
);
1293 add_vsite3_param(&plist
[F_VSITE3
],
1294 ats
[atND1
],ats
[atNE2
],ats
[atCE1
],ats
[atCG
],a
,b
);
1297 calc_vsite3_param(x
[atCD2
],y
[atCD2
],x
[atCE1
],y
[atCE1
],x
[atNE2
],y
[atNE2
],
1298 x
[atCG
],y
[atCG
],&a
,&b
);
1299 add_vsite3_param(&plist
[F_VSITE3
],
1300 ats
[atCD2
],ats
[atCE1
],ats
[atNE2
],ats
[atCG
],a
,b
);
1303 if (ats
[atHD1
]!=NOTSET
) {
1304 calc_vsite3_param(x
[atHD1
],y
[atHD1
],x
[atNE2
],y
[atNE2
],x
[atCE1
],y
[atCE1
],
1305 x
[atCG
],y
[atCG
],&a
,&b
);
1306 add_vsite3_param(&plist
[F_VSITE3
],
1307 ats
[atHD1
],ats
[atNE2
],ats
[atCE1
],ats
[atCG
],a
,b
);
1310 if (ats
[atHD2
]!=NOTSET
) {
1311 calc_vsite3_param(x
[atHD2
],y
[atHD2
],x
[atCE1
],y
[atCE1
],x
[atNE2
],y
[atNE2
],
1312 x
[atCG
],y
[atCG
],&a
,&b
);
1313 add_vsite3_param(&plist
[F_VSITE3
],
1314 ats
[atHD2
],ats
[atCE1
],ats
[atNE2
],ats
[atCG
],a
,b
);
1319 static gmx_bool
is_vsite(int vsite_type
)
1321 if (vsite_type
== NOTSET
)
1323 switch ( abs(vsite_type
) ) {
1336 static char atomnamesuffix
[] = "1234";
1338 void do_vsites(int nrtp
, t_restp rtp
[], gpp_atomtype_t atype
,
1339 t_atoms
*at
, t_symtab
*symtab
, rvec
*x
[],
1340 t_params plist
[], int *vsite_type
[], int *cgnr
[],
1341 real mHmult
, gmx_bool bVsiteAromatics
,
1344 #define MAXATOMSPERRESIDUE 16
1345 int i
,j
,k
,m
,i0
,ni0
,whatres
,resind
,add_shift
,ftype
,nvsite
,nadd
;
1347 int nrfound
=0,needed
,nrbonds
,nrHatoms
,Heavy
,nrheavies
,tpM
,tpHeavy
;
1348 int Hatoms
[4],heavies
[4],bb
;
1349 gmx_bool bWARNING
,bAddVsiteParam
,bFirstWater
;
1351 gmx_bool
*bResProcessed
;
1352 real mHtot
,mtot
,fact
,fact2
;
1353 rvec rpar
,rperp
,temp
;
1354 char name
[10],tpname
[32],nexttpname
[32],*ch
;
1356 int *o2n
,*newvsite_type
,*newcgnr
,ats
[MAXATOMSPERRESIDUE
];
1359 char ***newatomname
;
1363 int nvsiteconf
,nvsitetop
,cmplength
;
1364 gmx_bool isN
,planarN
,bFound
;
1365 gmx_residuetype_t rt
;
1367 t_vsiteconf
*vsiteconflist
;
1368 /* pointer to a list of CH3/NH3/NH2 configuration entries.
1369 * See comments in read_vsite_database. It isnt beautiful,
1370 * but it had to be fixed, and I dont even want to try to
1371 * maintain this part of the code...
1373 t_vsitetop
*vsitetop
;
1374 /* Pointer to a list of geometry (bond/angle) entries for
1375 * residues like PHE, TRP, TYR, HIS, etc., where we need
1376 * to know the geometry to construct vsite aromatics.
1377 * Note that equilibrium geometry isnt necessarily the same
1378 * as the individual bond and angle values given in the
1379 * force field (rings can be strained).
1382 /* if bVsiteAromatics=TRUE do_vsites will specifically convert atoms in
1383 PHE, TRP, TYR and HIS to a construction of virtual sites */
1384 enum { resPHE
, resTRP
, resTYR
, resHIS
, resNR
};
1385 const char *resnms
[resNR
] = { "PHE", "TRP", "TYR", "HIS" };
1386 /* Amber03 alternative names for termini */
1387 const char *resnmsN
[resNR
] = { "NPHE", "NTRP", "NTYR", "NHIS" };
1388 const char *resnmsC
[resNR
] = { "CPHE", "CTRP", "CTYR", "CHIS" };
1389 /* HIS can be known as HISH, HIS1, HISA, HID, HIE, HIP, etc. too */
1390 gmx_bool bPartial
[resNR
] = { FALSE
, FALSE
, FALSE
, TRUE
};
1391 /* the atnms for every residue MUST correspond to the enums in the
1392 gen_vsites_* (one for each residue) routines! */
1393 /* also the atom names in atnms MUST be in the same order as in the .rtp! */
1394 const char *atnms
[resNR
][MAXATOMSPERRESIDUE
+1] = {
1396 "CD1", "HD1", "CD2", "HD2",
1397 "CE1", "HE1", "CE2", "HE2",
1401 "CD1", "HD1", "CD2",
1402 "NE1", "HE1", "CE2", "CE3", "HE3",
1403 "CZ2", "HZ2", "CZ3", "HZ3",
1404 "CH2", "HH2", NULL
},
1406 "CD1", "HD1", "CD2", "HD2",
1407 "CE1", "HE1", "CE2", "HE2",
1408 "CZ", "OH", "HH", NULL
},
1410 "ND1", "HD1", "CD2", "HD2",
1411 "CE1", "HE1", "NE2", "HE2", NULL
}
1415 printf("Searching for atoms to make virtual sites ...\n");
1416 fprintf(debug
,"# # # VSITES # # #\n");
1419 ndb
= fflib_search_file_end(ffdir
,".vsd",FALSE
,&db
);
1421 vsiteconflist
= NULL
;
1424 for(f
=0; f
<ndb
; f
++) {
1425 read_vsite_database(db
[f
],&vsiteconflist
,&nvsiteconf
,&vsitetop
,&nvsitetop
);
1433 /* we need a marker for which atoms should *not* be renumbered afterwards */
1434 add_shift
= 10*at
->nr
;
1435 /* make arrays where masses can be inserted into */
1437 snew(newatom
,at
->nr
);
1438 snew(newatomname
,at
->nr
);
1439 snew(newvsite_type
,at
->nr
);
1440 snew(newcgnr
,at
->nr
);
1441 /* make index array to tell where the atoms go to when masses are inserted */
1443 for(i
=0; i
<at
->nr
; i
++)
1445 /* make index to tell which residues were already processed */
1446 snew(bResProcessed
,at
->nres
);
1448 gmx_residuetype_init(&rt
);
1450 /* generate vsite constructions */
1451 /* loop over all atoms */
1453 for(i
=0; (i
<at
->nr
); i
++) {
1454 if (at
->atom
[i
].resind
!= resind
) {
1455 resind
= at
->atom
[i
].resind
;
1456 resnm
= *(at
->resinfo
[resind
].name
);
1458 /* first check for aromatics to virtualize */
1459 /* don't waste our effort on DNA, water etc. */
1460 /* Only do the vsite aromatic stuff when we reach the
1461 * CA atom, since there might be an X2/X3 group on the
1462 * N-terminus that must be treated first.
1464 if ( bVsiteAromatics
&&
1465 !strcmp(*(at
->atomname
[i
]),"CA") &&
1466 !bResProcessed
[resind
] &&
1467 gmx_residuetype_is_protein(rt
,*(at
->resinfo
[resind
].name
)) ) {
1468 /* mark this residue */
1469 bResProcessed
[resind
] = TRUE
;
1470 /* find out if this residue needs converting */
1472 for(j
=0; j
<resNR
&& whatres
==NOTSET
; j
++) {
1474 cmplength
= bPartial
[j
] ? strlen(resnm
)-1 : strlen(resnm
);
1476 bFound
= ((gmx_strncasecmp(resnm
,resnms
[j
], cmplength
)==0) ||
1477 (gmx_strncasecmp(resnm
,resnmsN
[j
],cmplength
)==0) ||
1478 (gmx_strncasecmp(resnm
,resnmsC
[j
],cmplength
)==0));
1482 /* get atoms we will be needing for the conversion */
1484 for (k
=0; atnms
[j
][k
]; k
++)
1487 for(m
=i
; m
<at
->nr
&& at
->atom
[m
].resind
==resind
&& ats
[k
]==NOTSET
;m
++)
1489 if (gmx_strcasecmp(*(at
->atomname
[m
]),atnms
[j
][k
])==0)
1497 /* now k is number of atom names in atnms[j] */
1508 gmx_fatal(FARGS
,"not enough atoms found (%d, need %d) in "
1509 "residue %s %d while\n "
1510 "generating aromatics virtual site construction",
1511 nrfound
,needed
,resnm
,at
->resinfo
[resind
].nr
);
1513 /* Advance overall atom counter */
1517 /* the enums for every residue MUST correspond to atnms[residue] */
1520 if (debug
) fprintf(stderr
,"PHE at %d\n",o2n
[ats
[0]]+1);
1521 nvsite
+=gen_vsites_phe(at
, vsite_type
, plist
, nrfound
, ats
, vsitetop
, nvsitetop
);
1524 if (debug
) fprintf(stderr
,"TRP at %d\n",o2n
[ats
[0]]+1);
1525 nvsite
+=gen_vsites_trp(atype
, &newx
, &newatom
, &newatomname
, &o2n
,
1526 &newvsite_type
, &newcgnr
, symtab
, &nadd
, *x
, cgnr
,
1527 at
, vsite_type
, plist
, nrfound
, ats
, add_shift
, vsitetop
, nvsitetop
);
1530 if (debug
) fprintf(stderr
,"TYR at %d\n",o2n
[ats
[0]]+1);
1531 nvsite
+=gen_vsites_tyr(atype
, &newx
, &newatom
, &newatomname
, &o2n
,
1532 &newvsite_type
, &newcgnr
, symtab
, &nadd
, *x
, cgnr
,
1533 at
, vsite_type
, plist
, nrfound
, ats
, add_shift
, vsitetop
, nvsitetop
);
1536 if (debug
) fprintf(stderr
,"HIS at %d\n",o2n
[ats
[0]]+1);
1537 nvsite
+=gen_vsites_his(at
, vsite_type
, plist
, nrfound
, ats
, vsitetop
, nvsitetop
);
1540 /* this means this residue won't be processed */
1543 gmx_fatal(FARGS
,"DEATH HORROR in do_vsites (%s:%d)",
1545 } /* switch whatres */
1546 /* skip back to beginning of residue */
1547 while(i
>0 && at
->atom
[i
-1].resind
== resind
)
1549 } /* if bVsiteAromatics & is protein */
1551 /* now process the rest of the hydrogens */
1552 /* only process hydrogen atoms which are not already set */
1553 if ( ((*vsite_type
)[i
]==NOTSET
) && is_hydrogen(*(at
->atomname
[i
]))) {
1554 /* find heavy atom, count #bonds from it and #H atoms bound to it
1555 and return H atom numbers (Hatoms) and heavy atom numbers (heavies) */
1556 count_bonds(i
, &plist
[F_BONDS
], at
->atomname
,
1557 &nrbonds
, &nrHatoms
, Hatoms
, &Heavy
, &nrheavies
, heavies
);
1558 /* get Heavy atom type */
1559 tpHeavy
=get_atype(Heavy
,at
,nrtp
,rtp
,rt
);
1560 strcpy(tpname
,get_atomtype_name(tpHeavy
,atype
));
1563 bAddVsiteParam
=TRUE
;
1564 /* nested if's which check nrHatoms, nrbonds and atomname */
1565 if (nrHatoms
== 1) {
1568 (*vsite_type
)[i
]=F_BONDS
;
1570 case 3: /* =CH-, -NH- or =NH+- */
1571 (*vsite_type
)[i
]=F_VSITE3FD
;
1573 case 4: /* --CH- (tert) */
1574 /* The old type 4FD had stability issues, so
1575 * all new constructs should use 4FDN
1577 (*vsite_type
)[i
]=F_VSITE4FDN
;
1579 /* Check parity of heavy atoms from coordinates */
1584 rvec_sub((*x
)[aj
],(*x
)[ai
],tmpmat
[0]);
1585 rvec_sub((*x
)[ak
],(*x
)[ai
],tmpmat
[1]);
1586 rvec_sub((*x
)[al
],(*x
)[ai
],tmpmat
[2]);
1596 default: /* nrbonds != 2, 3 or 4 */
1600 } else if ( /*(nrHatoms == 2) && (nrbonds == 2) && REMOVED this test
1602 (gmx_strncasecmp(*at
->atomname
[Heavy
],"OW",2)==0) ) {
1603 bAddVsiteParam
=FALSE
; /* this is water: skip these hydrogens */
1608 "Not converting hydrogens in water to virtual sites\n");
1610 } else if ( (nrHatoms
== 2) && (nrbonds
== 4) ) {
1611 /* -CH2- , -NH2+- */
1612 (*vsite_type
)[Hatoms
[0]] = F_VSITE3OUT
;
1613 (*vsite_type
)[Hatoms
[1]] =-F_VSITE3OUT
;
1615 /* 2 or 3 hydrogen atom, with 3 or 4 bonds in total to the heavy atom.
1616 * If it is a nitrogen, first check if it is planar.
1619 if((nrHatoms
== 2) && ((*at
->atomname
[Heavy
])[0]=='N')) {
1621 j
=nitrogen_is_planar(vsiteconflist
,nvsiteconf
,tpname
);
1623 gmx_fatal(FARGS
,"No vsite database NH2 entry for type %s\n",tpname
);
1626 if ( (nrHatoms
== 2) && (nrbonds
== 3) && ( !isN
|| planarN
) ) {
1627 /* =CH2 or, if it is a nitrogen NH2, it is a planar one */
1628 (*vsite_type
)[Hatoms
[0]] = F_VSITE3FAD
;
1629 (*vsite_type
)[Hatoms
[1]] =-F_VSITE3FAD
;
1630 } else if ( ( (nrHatoms
== 2) && (nrbonds
== 3) &&
1631 ( isN
&& !planarN
) ) ||
1632 ( (nrHatoms
== 3) && (nrbonds
== 4) ) ) {
1633 /* CH3, NH3 or non-planar NH2 group */
1634 int Hat_vsite_type
[3] = { F_VSITE3
, F_VSITE3OUT
, F_VSITE3OUT
};
1635 gmx_bool Hat_SwapParity
[3] = { FALSE
, TRUE
, FALSE
};
1637 if (debug
) fprintf(stderr
,"-XH3 or nonplanar NH2 group at %d\n",i
+1);
1638 bAddVsiteParam
=FALSE
; /* we'll do this ourselves! */
1639 /* -NH2 (umbrella), -NH3+ or -CH3 */
1640 (*vsite_type
)[Heavy
] = F_VSITE3
;
1641 for (j
=0; j
<nrHatoms
; j
++)
1642 (*vsite_type
)[Hatoms
[j
]] = Hat_vsite_type
[j
];
1643 /* get dummy mass type from first char of heavy atom type (N or C) */
1645 strcpy(nexttpname
,get_atomtype_name(get_atype(heavies
[0],at
,nrtp
,rtp
,rt
),atype
));
1646 ch
=get_dummymass_name(vsiteconflist
,nvsiteconf
,tpname
,nexttpname
);
1650 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
);
1652 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
);
1658 tpM
=vsite_nm2type(name
,atype
);
1659 /* make space for 2 masses: shift all atoms starting with 'Heavy' */
1664 fprintf(stderr
,"Inserting %d dummy masses at %d\n",NMASS
,o2n
[i0
]+1);
1666 for(j
=i0
; j
<at
->nr
; j
++)
1669 srenew(newx
,at
->nr
+nadd
);
1670 srenew(newatom
,at
->nr
+nadd
);
1671 srenew(newatomname
,at
->nr
+nadd
);
1672 srenew(newvsite_type
,at
->nr
+nadd
);
1673 srenew(newcgnr
,at
->nr
+nadd
);
1675 for(j
=0; j
<NMASS
; j
++)
1676 newatomname
[at
->nr
+nadd
-1-j
]=NULL
;
1678 /* calculate starting position for the masses */
1680 /* get atom masses, and set Heavy and Hatoms mass to zero */
1681 for(j
=0; j
<nrHatoms
; j
++) {
1682 mHtot
+= get_amass(Hatoms
[j
],at
,nrtp
,rtp
,rt
);
1683 at
->atom
[Hatoms
[j
]].m
= at
->atom
[Hatoms
[j
]].mB
= 0;
1685 mtot
= mHtot
+ get_amass(Heavy
,at
,nrtp
,rtp
,rt
);
1686 at
->atom
[Heavy
].m
= at
->atom
[Heavy
].mB
= 0;
1691 /* generate vectors parallel and perpendicular to rotational axis:
1692 * rpar = Heavy -> Hcom
1693 * rperp = Hcom -> H1 */
1695 for(j
=0; j
<nrHatoms
; j
++)
1696 rvec_inc(rpar
,(*x
)[Hatoms
[j
]]);
1697 svmul(1.0/nrHatoms
,rpar
,rpar
); /* rpar = ( H1+H2+H3 ) / 3 */
1698 rvec_dec(rpar
,(*x
)[Heavy
]); /* - Heavy */
1699 rvec_sub((*x
)[Hatoms
[0]],(*x
)[Heavy
],rperp
);
1700 rvec_dec(rperp
,rpar
); /* rperp = H1 - Heavy - rpar */
1701 /* calc mass positions */
1702 svmul(fact2
,rpar
,temp
);
1703 for (j
=0; (j
<NMASS
); j
++) /* xM = xN + fact2 * rpar +/- fact * rperp */
1704 rvec_add((*x
)[Heavy
],temp
,newx
[ni0
+j
]);
1705 svmul(fact
,rperp
,temp
);
1706 rvec_inc(newx
[ni0
],temp
);
1707 rvec_dec(newx
[ni0
+1],temp
);
1708 /* set atom parameters for the masses */
1709 for(j
=0; (j
<NMASS
); j
++) {
1710 /* make name: "M??#" or "M?#" (? is atomname, # is number) */
1712 for(k
=0; (*at
->atomname
[Heavy
])[k
] && ( k
< NMASS
); k
++ )
1713 name
[k
+1]=(*at
->atomname
[Heavy
])[k
];
1714 name
[k
+1]=atomnamesuffix
[j
];
1716 newatomname
[ni0
+j
] = put_symtab(symtab
,name
);
1717 newatom
[ni0
+j
].m
= newatom
[ni0
+j
].mB
= mtot
/NMASS
;
1718 newatom
[ni0
+j
].q
= newatom
[ni0
+j
].qB
= 0.0;
1719 newatom
[ni0
+j
].type
= newatom
[ni0
+j
].typeB
= tpM
;
1720 newatom
[ni0
+j
].ptype
= eptAtom
;
1721 newatom
[ni0
+j
].resind
= at
->atom
[i0
].resind
;
1722 newvsite_type
[ni0
+j
] = NOTSET
;
1723 newcgnr
[ni0
+j
] = (*cgnr
)[i0
];
1725 /* add constraints between dummy masses and to heavies[0] */
1726 /* 'add_shift' says which atoms won't be renumbered afterwards */
1727 my_add_param(&(plist
[F_CONSTRNC
]),heavies
[0], add_shift
+ni0
, NOTSET
);
1728 my_add_param(&(plist
[F_CONSTRNC
]),heavies
[0], add_shift
+ni0
+1,NOTSET
);
1729 my_add_param(&(plist
[F_CONSTRNC
]),add_shift
+ni0
,add_shift
+ni0
+1,NOTSET
);
1731 /* generate Heavy, H1, H2 and H3 from M1, M2 and heavies[0] */
1732 /* note that vsite_type cannot be NOTSET, because we just set it */
1733 add_vsite3_atoms (&plist
[(*vsite_type
)[Heavy
]],
1734 Heavy
, heavies
[0], add_shift
+ni0
, add_shift
+ni0
+1,
1736 for(j
=0; j
<nrHatoms
; j
++)
1737 add_vsite3_atoms(&plist
[(*vsite_type
)[Hatoms
[j
]]],
1738 Hatoms
[j
], heavies
[0], add_shift
+ni0
, add_shift
+ni0
+1,
1747 "Warning: cannot convert atom %d %s (bound to a heavy atom "
1749 " %d bonds and %d bound hydrogens atoms) to virtual site\n",
1750 i
+1,*(at
->atomname
[i
]),tpname
,nrbonds
,nrHatoms
);
1751 if (bAddVsiteParam
) {
1752 /* add vsite parameters to topology,
1753 also get rid of negative vsite_types */
1754 add_vsites(plist
, (*vsite_type
), Heavy
, nrHatoms
, Hatoms
,
1755 nrheavies
, heavies
);
1756 /* transfer mass of virtual site to Heavy atom */
1757 for(j
=0; j
<nrHatoms
; j
++)
1758 if (is_vsite((*vsite_type
)[Hatoms
[j
]])) {
1759 at
->atom
[Heavy
].m
+= at
->atom
[Hatoms
[j
]].m
;
1760 at
->atom
[Heavy
].mB
= at
->atom
[Heavy
].m
;
1761 at
->atom
[Hatoms
[j
]].m
= at
->atom
[Hatoms
[j
]].mB
= 0;
1766 fprintf(debug
,"atom %d: ",o2n
[i
]+1);
1767 print_bonds(debug
,o2n
,nrHatoms
,Hatoms
,Heavy
,nrheavies
,heavies
);
1769 } /* if vsite NOTSET & is hydrogen */
1771 } /* for i < at->nr */
1773 gmx_residuetype_destroy(rt
);
1776 fprintf(debug
,"Before inserting new atoms:\n");
1777 for(i
=0; i
<at
->nr
; i
++)
1778 fprintf(debug
,"%4d %4d %4s %4d %4s %6d %-10s\n",i
+1,o2n
[i
]+1,
1779 at
->atomname
[i
]?*(at
->atomname
[i
]):"(NULL)",
1780 at
->resinfo
[at
->atom
[i
].resind
].nr
,
1781 at
->resinfo
[at
->atom
[i
].resind
].name
?
1782 *(at
->resinfo
[at
->atom
[i
].resind
].name
):"(NULL)",
1784 ((*vsite_type
)[i
]==NOTSET
) ?
1785 "NOTSET" : interaction_function
[(*vsite_type
)[i
]].name
);
1786 fprintf(debug
,"new atoms to be inserted:\n");
1787 for(i
=0; i
<at
->nr
+nadd
; i
++)
1789 fprintf(debug
,"%4d %4s %4d %6d %-10s\n",i
+1,
1790 newatomname
[i
]?*(newatomname
[i
]):"(NULL)",
1791 newatom
[i
].resind
,newcgnr
[i
],
1792 (newvsite_type
[i
]==NOTSET
) ?
1793 "NOTSET" : interaction_function
[newvsite_type
[i
]].name
);
1796 /* add all original atoms to the new arrays, using o2n index array */
1797 for(i
=0; i
<at
->nr
; i
++) {
1798 newatomname
[o2n
[i
]] = at
->atomname
[i
];
1799 newatom
[o2n
[i
]] = at
->atom
[i
];
1800 newvsite_type
[o2n
[i
]] = (*vsite_type
)[i
];
1801 newcgnr
[o2n
[i
]] = (*cgnr
) [i
];
1802 copy_rvec((*x
)[i
],newx
[o2n
[i
]]);
1804 /* throw away old atoms */
1806 sfree(at
->atomname
);
1810 /* put in the new ones */
1813 at
->atomname
= newatomname
;
1814 *vsite_type
= newvsite_type
;
1817 if (at
->nr
> add_shift
)
1818 gmx_fatal(FARGS
,"Added impossible amount of dummy masses "
1819 "(%d on a total of %d atoms)\n",nadd
,at
->nr
-nadd
);
1822 fprintf(debug
,"After inserting new atoms:\n");
1823 for(i
=0; i
<at
->nr
; i
++)
1824 fprintf(debug
,"%4d %4s %4d %4s %6d %-10s\n",i
+1,
1825 at
->atomname
[i
]?*(at
->atomname
[i
]):"(NULL)",
1826 at
->resinfo
[at
->atom
[i
].resind
].nr
,
1827 at
->resinfo
[at
->atom
[i
].resind
].name
?
1828 *(at
->resinfo
[at
->atom
[i
].resind
].name
):"(NULL)",
1830 ((*vsite_type
)[i
]==NOTSET
) ?
1831 "NOTSET" : interaction_function
[(*vsite_type
)[i
]].name
);
1834 /* now renumber all the interactions because of the added atoms */
1835 for (ftype
=0; ftype
<F_NRE
; ftype
++) {
1836 params
=&(plist
[ftype
]);
1838 fprintf(debug
,"Renumbering %d %s\n", params
->nr
,
1839 interaction_function
[ftype
].longname
);
1840 for (i
=0; i
<params
->nr
; i
++) {
1841 for (j
=0; j
<NRAL(ftype
); j
++)
1842 if (params
->param
[i
].a
[j
]>=add_shift
) {
1843 if (debug
) fprintf(debug
," [%u -> %u]",params
->param
[i
].a
[j
],
1844 params
->param
[i
].a
[j
]-add_shift
);
1845 params
->param
[i
].a
[j
]=params
->param
[i
].a
[j
]-add_shift
;
1847 if (debug
) fprintf(debug
," [%u -> %d]",params
->param
[i
].a
[j
],
1848 o2n
[params
->param
[i
].a
[j
]]);
1849 params
->param
[i
].a
[j
]=o2n
[params
->param
[i
].a
[j
]];
1851 if (debug
) fprintf(debug
,"\n");
1854 /* now check if atoms in the added constraints are in increasing order */
1855 params
=&(plist
[F_CONSTRNC
]);
1856 for(i
=0; i
<params
->nr
; i
++)
1857 if ( params
->param
[i
].AI
> params
->param
[i
].AJ
) {
1858 j
= params
->param
[i
].AJ
;
1859 params
->param
[i
].AJ
= params
->param
[i
].AI
;
1860 params
->param
[i
].AI
= j
;
1866 /* tell the user what we did */
1867 fprintf(stderr
,"Marked %d virtual sites\n",nvsite
);
1868 fprintf(stderr
,"Added %d dummy masses\n",nadd
);
1869 fprintf(stderr
,"Added %d new constraints\n",plist
[F_CONSTRNC
].nr
);
1872 void do_h_mass(t_params
*psb
, int vsite_type
[], t_atoms
*at
, real mHmult
,
1873 gmx_bool bDeuterate
)
1877 /* loop over all atoms */
1878 for (i
=0; i
<at
->nr
; i
++)
1879 /* adjust masses if i is hydrogen and not a virtual site */
1880 if ( !is_vsite(vsite_type
[i
]) && is_hydrogen(*(at
->atomname
[i
])) ) {
1881 /* find bonded heavy atom */
1883 for(j
=0; (j
<psb
->nr
) && (a
==NOTSET
); j
++) {
1884 /* if other atom is not a virtual site, it is the one we want */
1885 if ( (psb
->param
[j
].AI
==i
) &&
1886 !is_vsite(vsite_type
[psb
->param
[j
].AJ
]) )
1888 else if ( (psb
->param
[j
].AJ
==i
) &&
1889 !is_vsite(vsite_type
[psb
->param
[j
].AI
]) )
1893 gmx_fatal(FARGS
,"Unbound hydrogen atom (%d) found while adjusting mass",
1896 /* adjust mass of i (hydrogen) with mHmult
1897 and correct mass of a (bonded atom) with same amount */
1899 at
->atom
[a
].m
-= (mHmult
-1.0)*at
->atom
[i
].m
;
1900 at
->atom
[a
].mB
-= (mHmult
-1.0)*at
->atom
[i
].m
;
1902 at
->atom
[i
].m
*= mHmult
;
1903 at
->atom
[i
].mB
*= mHmult
;