Merge release-4-6 into master
[alexxy/gromacs.git] / src / gromacs / gmxpreprocess / gen_vsite.c
1 /*
2  * 
3  *                This source code is part of
4  * 
5  *                 G   R   O   M   A   C   S
6  * 
7  *          GROningen MAchine for Chemical Simulations
8  * 
9  *                        VERSION 3.2.0
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.
14
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.
19  * 
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.
26  * 
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.
29  * 
30  * For more info, check our website at http://www.gromacs.org
31  * 
32  * And Hey:
33  * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
34  */
35 #ifdef HAVE_CONFIG_H
36 #include <config.h>
37 #endif
38
39 #include "string2.h"
40 #include <stdio.h>
41 #include <math.h>
42 #include <string.h>
43 #include "gen_vsite.h"
44 #include "smalloc.h"
45 #include "resall.h"
46 #include "add_par.h"
47 #include "vec.h"
48 #include "toputil.h"
49 #include "physics.h"
50 #include "index.h"
51 #include "names.h"
52 #include "futil.h"
53 #include "gpp_atomtype.h"
54 #include "fflibutil.h"
55 #include "macros.h"
56
57 #define MAXNAME 32
58 #define OPENDIR         '['     /* starting sign for directive          */
59 #define CLOSEDIR        ']'     /* ending sign for directive            */
60
61 typedef struct {
62   char   atomtype[MAXNAME];      /* Type for the XH3/XH2 atom */
63   gmx_bool   isplanar;               /* If true, the atomtype above and the three connected
64                                   * ones are in a planar geometry. The two next entries
65                                   * are undefined in that case 
66                                   */
67   int    nhydrogens;             /* number of connected hydrogens */
68   char   nextheavytype[MAXNAME]; /* Type for the heavy atom bonded to XH2/XH3 */
69   char   dummymass[MAXNAME];     /* The type of MNH* or MCH3* dummy mass to use */
70 } t_vsiteconf;
71
72
73 /* Structure to represent average bond and angles values in vsite aromatic
74  * residues. Note that these are NOT necessarily the bonds and angles from the
75  * forcefield; many forcefields (like Amber, OPLS) have some inherent strain in
76  * 5-rings (i.e. the sum of angles is !=540, but impropers keep it planar)
77  */
78 typedef struct {
79   char resname[MAXNAME];
80   int nbonds;
81   int nangles;
82   struct vsitetop_bond {
83     char   atom1[MAXNAME];
84     char   atom2[MAXNAME];
85     float  value;
86   } *bond; /* list of bonds */
87   struct vsitetop_angle {
88     char   atom1[MAXNAME];
89     char   atom2[MAXNAME];
90     char   atom3[MAXNAME];
91     float  value;
92   } *angle; /* list of angles */
93 } t_vsitetop;
94
95
96 enum { DDB_CH3, DDB_NH3, DDB_NH2, DDB_PHE, DDB_TYR, 
97        DDB_TRP, DDB_HISA, DDB_HISB, DDB_HISH , DDB_DIR_NR };
98
99 typedef char t_dirname[STRLEN];
100
101 static const t_dirname ddb_dirnames[DDB_DIR_NR] = {
102   "CH3",
103   "NH3",
104   "NH2",
105   "PHE",
106   "TYR",
107   "TRP",
108   "HISA",
109   "HISB",
110   "HISH"
111 };
112
113 static int ddb_name2dir(char *name) 
114 {
115   /* Translate a directive name to the number of the directive.
116    * HID/HIE/HIP names are translated to the ones we use in Gromacs.
117    */
118
119   int i,index;
120
121   index=-1;
122
123   for(i=0;i<DDB_DIR_NR && index<0;i++)
124     if(!gmx_strcasecmp(name,ddb_dirnames[i]))
125       index=i;
126   
127   return index;
128 }
129
130
131 static void read_vsite_database(const char *ddbname,
132                                 t_vsiteconf **pvsiteconflist, int *nvsiteconf,
133                                 t_vsitetop **pvsitetoplist, int *nvsitetop)
134 {
135   /* This routine is a quick hack to fix the problem with hardcoded atomtypes
136    * and aromatic vsite parameters by reading them from a ff???.vsd file.
137    *
138    * The file can contain sections [ NH3 ], [ CH3 ], [ NH2 ], and ring residue names.
139    * For the NH3 and CH3 section each line has three fields. The first is the atomtype 
140    * (nb: not bonded type) of the N/C atom to be replaced, the second field is
141    * the type of the next heavy atom it is bonded to, and the third field the type
142    * of dummy mass that will be used for this group. 
143    * 
144    * If the NH2 group planar (sp2 N) a different vsite construct is used, so in this
145    * case the second field should just be the word planar.
146    */
147
148   FILE *ddb;
149   char dirstr[STRLEN];
150   char pline[STRLEN];
151   int i,j,n,k,nvsite,ntop,curdir,prevdir;
152   t_vsiteconf *vsiteconflist;
153   t_vsitetop *vsitetoplist;
154   char *ch;
155   char s1[MAXNAME],s2[MAXNAME],s3[MAXNAME],s4[MAXNAME];
156
157   ddb = libopen(ddbname);
158
159   nvsite        = *nvsiteconf;
160   vsiteconflist = *pvsiteconflist;
161   ntop          = *nvsitetop;
162   vsitetoplist  = *pvsitetoplist;
163
164   curdir=-1;
165   
166   snew(vsiteconflist,1);
167   snew(vsitetoplist,1);
168
169   while(fgets2(pline,STRLEN-2,ddb) != NULL) {
170     strip_comment(pline);
171     trim(pline);
172     if(strlen(pline)>0) {
173       if(pline[0] == OPENDIR ) {
174         strncpy(dirstr,pline+1,STRLEN-2);
175         if ((ch = strchr (dirstr,CLOSEDIR)) != NULL)
176           (*ch) = 0;
177         trim (dirstr);
178
179         if(!gmx_strcasecmp(dirstr,"HID") ||
180            !gmx_strcasecmp(dirstr,"HISD"))
181           sprintf(dirstr,"HISA");
182         else if(!gmx_strcasecmp(dirstr,"HIE") ||
183                 !gmx_strcasecmp(dirstr,"HISE"))
184           sprintf(dirstr,"HISB");
185         else if(!gmx_strcasecmp(dirstr,"HIP"))
186           sprintf(dirstr,"HISH");
187
188         curdir=ddb_name2dir(dirstr);
189         if (curdir < 0) {
190           gmx_fatal(FARGS,"Invalid directive %s in vsite database %s",
191                     dirstr,ddbname);
192         }
193       } else {
194         switch(curdir) {
195         case -1:
196           gmx_fatal(FARGS,"First entry in vsite database must be a directive.\n");
197           break;
198         case DDB_CH3:
199         case DDB_NH3:
200         case DDB_NH2:
201           n = sscanf(pline,"%s%s%s",s1,s2,s3);
202           if(n<3 && !gmx_strcasecmp(s2,"planar")) {
203             srenew(vsiteconflist,nvsite+1);
204             strncpy(vsiteconflist[nvsite].atomtype,s1,MAXNAME-1);
205             vsiteconflist[nvsite].isplanar=TRUE;
206             vsiteconflist[nvsite].nextheavytype[0]=0;
207             vsiteconflist[nvsite].dummymass[0]=0;
208             vsiteconflist[nvsite].nhydrogens=2;
209             nvsite++;
210           } else if(n==3) {
211             srenew(vsiteconflist,(nvsite+1));
212             strncpy(vsiteconflist[nvsite].atomtype,s1,MAXNAME-1);
213             vsiteconflist[nvsite].isplanar=FALSE;
214             strncpy(vsiteconflist[nvsite].nextheavytype,s2,MAXNAME-1);
215             strncpy(vsiteconflist[nvsite].dummymass,s3,MAXNAME-1);
216             if(curdir==DDB_NH2)
217               vsiteconflist[nvsite].nhydrogens=2;
218             else
219               vsiteconflist[nvsite].nhydrogens=3;
220             nvsite++;
221           } else {
222             gmx_fatal(FARGS,"Not enough directives in vsite database line: %s\n",pline);
223           }
224           break;
225         case DDB_PHE:
226         case DDB_TYR:
227         case DDB_TRP:
228         case DDB_HISA:
229         case DDB_HISB:
230         case DDB_HISH:
231           i=0;
232           while((i<ntop) && gmx_strcasecmp(dirstr,vsitetoplist[i].resname))
233             i++;
234           /* Allocate a new topology entry if this is a new residue */
235           if(i==ntop) {
236             srenew(vsitetoplist,ntop+1);            
237             ntop++; /* i still points to current vsite topology entry */
238             strncpy(vsitetoplist[i].resname,dirstr,MAXNAME-1);
239             vsitetoplist[i].nbonds=vsitetoplist[i].nangles=0;
240             snew(vsitetoplist[i].bond,1);
241             snew(vsitetoplist[i].angle,1);
242           }
243           n = sscanf(pline,"%s%s%s%s",s1,s2,s3,s4);
244           if(n==3) {
245             /* bond */
246             k=vsitetoplist[i].nbonds++;
247             srenew(vsitetoplist[i].bond,k+1);
248             strncpy(vsitetoplist[i].bond[k].atom1,s1,MAXNAME-1);
249             strncpy(vsitetoplist[i].bond[k].atom2,s2,MAXNAME-1);
250             vsitetoplist[i].bond[k].value=strtod(s3,NULL);
251           } else if (n==4) {
252             /* angle */
253             k=vsitetoplist[i].nangles++;
254             srenew(vsitetoplist[i].angle,k+1);
255             strncpy(vsitetoplist[i].angle[k].atom1,s1,MAXNAME-1);
256             strncpy(vsitetoplist[i].angle[k].atom2,s2,MAXNAME-1);
257             strncpy(vsitetoplist[i].angle[k].atom3,s3,MAXNAME-1);
258             vsitetoplist[i].angle[k].value=strtod(s4,NULL);
259           } else {
260             gmx_fatal(FARGS,"Need 3 or 4 values to specify bond/angle values in %s: %s\n",ddbname,pline);
261           }
262           break;
263         default:
264           gmx_fatal(FARGS,"Didnt find a case for directive %s in read_vsite_database\n",dirstr);
265         }
266       }
267     }
268   }
269
270   *pvsiteconflist=vsiteconflist;
271   *pvsitetoplist=vsitetoplist;
272   *nvsiteconf=nvsite;
273   *nvsitetop=ntop;
274   
275   ffclose(ddb);
276 }
277
278 static int nitrogen_is_planar(t_vsiteconf vsiteconflist[],int nvsiteconf,char atomtype[])
279 {
280   /* Return 1 if atomtype exists in database list and is planar, 0 if not,
281    * and -1 if not found.
282    */
283   int i,res;
284   gmx_bool found=FALSE;
285   for(i=0;i<nvsiteconf && !found;i++) {
286     found=(!gmx_strcasecmp(vsiteconflist[i].atomtype,atomtype) && (vsiteconflist[i].nhydrogens==2));
287   }
288   if(found)
289     res=(vsiteconflist[i-1].isplanar==TRUE);
290   else
291     res=-1;
292
293   return res;
294 }
295   
296 static char *get_dummymass_name(t_vsiteconf vsiteconflist[],int nvsiteconf,char atom[], char nextheavy[])
297 {
298   /* Return the dummy mass name if found, or NULL if not set in ddb database */
299   int i;
300   gmx_bool found=FALSE;
301   for(i=0;i<nvsiteconf && !found;i++) {
302     found=(!gmx_strcasecmp(vsiteconflist[i].atomtype,atom) &&
303            !gmx_strcasecmp(vsiteconflist[i].nextheavytype,nextheavy));
304   }
305   if(found)
306     return vsiteconflist[i-1].dummymass;
307   else
308     return NULL;
309 }
310   
311
312
313 static real get_ddb_bond(t_vsitetop *vsitetop, int nvsitetop,
314                          const char res[],
315                          const char atom1[], const char atom2[])
316 {
317   int i,j;
318   
319   i=0;
320   while(i<nvsitetop && gmx_strcasecmp(res,vsitetop[i].resname))
321     i++;
322   if(i==nvsitetop)
323     gmx_fatal(FARGS,"No vsite information for residue %s found in vsite database.\n",res);
324   j=0;
325   while(j<vsitetop[i].nbonds && 
326         ( strcmp(atom1,vsitetop[i].bond[j].atom1) || strcmp(atom2,vsitetop[i].bond[j].atom2)) &&
327         ( strcmp(atom2,vsitetop[i].bond[j].atom1) || strcmp(atom1,vsitetop[i].bond[j].atom2)))
328     j++;
329   if(j==vsitetop[i].nbonds)
330     gmx_fatal(FARGS,"Couldnt find bond %s-%s for residue %s in vsite database.\n",atom1,atom2,res);
331   
332   return vsitetop[i].bond[j].value;
333 }
334       
335
336 static real get_ddb_angle(t_vsitetop *vsitetop, int nvsitetop,
337                           const char res[], const char atom1[],
338                           const char atom2[], const char atom3[])
339 {
340   int i,j;
341   
342   i=0;
343   while(i<nvsitetop && gmx_strcasecmp(res,vsitetop[i].resname))
344     i++;
345   if(i==nvsitetop)
346     gmx_fatal(FARGS,"No vsite information for residue %s found in vsite database.\n",res);
347   j=0;
348   while(j<vsitetop[i].nangles && 
349         ( strcmp(atom1,vsitetop[i].angle[j].atom1) || 
350           strcmp(atom2,vsitetop[i].angle[j].atom2) || 
351           strcmp(atom3,vsitetop[i].angle[j].atom3)) &&
352         ( strcmp(atom3,vsitetop[i].angle[j].atom1) || 
353           strcmp(atom2,vsitetop[i].angle[j].atom2) || 
354           strcmp(atom1,vsitetop[i].angle[j].atom3)))
355     j++;
356   if(j==vsitetop[i].nangles)
357     gmx_fatal(FARGS,"Couldnt find angle %s-%s-%s for residue %s in vsite database.\n",atom1,atom2,atom3,res);
358   
359   return vsitetop[i].angle[j].value;
360 }
361       
362
363 static void count_bonds(int atom, t_params *psb, char ***atomname, 
364                         int *nrbonds, int *nrHatoms, int Hatoms[], int *Heavy,
365                         int *nrheavies, int heavies[])
366 {
367   int i,heavy,other,nrb,nrH,nrhv;
368   
369   /* find heavy atom bound to this hydrogen */
370   heavy=NOTSET;
371   for(i=0; (i<psb->nr) && (heavy==NOTSET); i++)
372     if (psb->param[i].AI==atom)
373       heavy=psb->param[i].AJ;
374     else if (psb->param[i].AJ==atom)
375       heavy=psb->param[i].AI;
376   if (heavy==NOTSET)
377     gmx_fatal(FARGS,"unbound hydrogen atom %d",atom+1);
378   /* find all atoms bound to heavy atom */
379   other=NOTSET;
380   nrb=0;
381   nrH=0;
382   nrhv=0;
383   for(i=0; i<psb->nr; i++) {
384     if (psb->param[i].AI==heavy)
385       other=psb->param[i].AJ;
386     else if (psb->param[i].AJ==heavy)
387       other=psb->param[i].AI;
388     if (other!=NOTSET) {
389       nrb++;
390       if (is_hydrogen(*(atomname[other]))) {
391         Hatoms[nrH]=other;
392         nrH++;
393       } else {
394         heavies[nrhv]=other;
395         nrhv++;
396       }
397       other=NOTSET;
398     }
399   }
400   *Heavy   =heavy;
401   *nrbonds =nrb;
402   *nrHatoms=nrH;
403   *nrheavies=nrhv;
404 }
405
406 static void print_bonds(FILE *fp, int o2n[],
407                         int nrHatoms, int Hatoms[], int Heavy,
408                         int nrheavies, int heavies[])
409 {
410   int i;
411   
412   fprintf(fp,"Found: %d Hatoms: ",nrHatoms);
413   for(i=0; i<nrHatoms; i++)
414     fprintf(fp," %d",o2n[Hatoms[i]]+1);
415   fprintf(fp,"; %d Heavy atoms: %d",nrheavies+1,o2n[Heavy]+1);
416   for(i=0; i<nrheavies; i++)
417     fprintf(fp," %d",o2n[heavies[i]]+1);
418   fprintf(fp,"\n");
419 }
420
421 static int get_atype(int atom, t_atoms *at, int nrtp, t_restp rtp[],
422                      gmx_residuetype_t rt)
423 {
424   int type;
425   gmx_bool bNterm;
426   int  j;
427   t_restp *rtpp;
428   
429   if (at->atom[atom].m)
430     type=at->atom[atom].type;
431   else {
432     /* get type from rtp */
433     rtpp = get_restp(*(at->resinfo[at->atom[atom].resind].name),nrtp,rtp);
434     bNterm = gmx_residuetype_is_protein(rt,*(at->resinfo[at->atom[atom].resind].name)) && 
435       (at->atom[atom].resind == 0);
436     j=search_jtype(rtpp,*(at->atomname[atom]),bNterm);
437     type=rtpp->atom[j].type;
438   }
439   return type;
440 }
441
442 static int vsite_nm2type(const char *name, gpp_atomtype_t atype)
443 {
444   int tp;
445   
446   tp = get_atomtype_type(name,atype);
447   if (tp == NOTSET)
448     gmx_fatal(FARGS,"Dummy mass type (%s) not found in atom type database",
449               name);
450               
451   return tp;
452 }
453
454 static real get_amass(int atom, t_atoms *at, int nrtp, t_restp rtp[],
455                       gmx_residuetype_t rt)
456 {
457   real mass;
458   gmx_bool bNterm;
459   int  j;
460   t_restp *rtpp;
461   
462   if (at->atom[atom].m)
463     mass=at->atom[atom].m;
464   else {
465     /* get mass from rtp */
466     rtpp = get_restp(*(at->resinfo[at->atom[atom].resind].name),nrtp,rtp);
467     bNterm = gmx_residuetype_is_protein(rt,*(at->resinfo[at->atom[atom].resind].name)) && 
468       (at->atom[atom].resind == 0);
469     j=search_jtype(rtpp,*(at->atomname[atom]),bNterm);
470     mass=rtpp->atom[j].m;
471   }
472   return mass;
473 }
474
475 static void my_add_param(t_params *plist, int ai, int aj, real b)
476 {
477   static real c[MAXFORCEPARAM] = 
478   { NOTSET, NOTSET, NOTSET, NOTSET, NOTSET, NOTSET };
479   
480   c[0]=b;
481   add_param(plist,ai,aj,c,NULL);
482 }
483
484 static void add_vsites(t_params plist[], int vsite_type[], 
485                        int Heavy, int nrHatoms, int Hatoms[], 
486                        int nrheavies, int heavies[])
487 {
488   int i,j,ftype,other,moreheavy,bb;
489   gmx_bool bSwapParity;
490   
491   for(i=0; i<nrHatoms; i++) {
492     ftype=vsite_type[Hatoms[i]];
493     /* Errors in setting the vsite_type should really be caugth earlier,
494      * because here it's not possible to print any useful error message.
495      * But it's still better to print a message than to segfault.
496      */
497     if (ftype == NOTSET) {
498       gmx_incons("Undetected error in setting up virtual sites");
499     }
500     bSwapParity = (ftype<0);
501     vsite_type[Hatoms[i]] = ftype = abs(ftype);
502     if (ftype == F_BONDS) {
503       if ( (nrheavies != 1) && (nrHatoms != 1) )
504         gmx_fatal(FARGS,"cannot make constraint in add_vsites for %d heavy "
505                     "atoms and %d hydrogen atoms",nrheavies,nrHatoms);
506       my_add_param(&(plist[F_CONSTRNC]),Hatoms[i],heavies[0],NOTSET);
507     } else {
508       switch (ftype) {
509       case F_VSITE3:
510       case F_VSITE3FD:
511       case F_VSITE3OUT:
512         if (nrheavies < 2) 
513           gmx_fatal(FARGS,"Not enough heavy atoms (%d) for %s (min 3)",
514                       nrheavies+1,
515                       interaction_function[vsite_type[Hatoms[i]]].name);
516         add_vsite3_atoms(&plist[ftype],Hatoms[i],Heavy,heavies[0],heavies[1],
517                        bSwapParity);
518         break;
519       case F_VSITE3FAD: {
520         if (nrheavies > 1)
521           moreheavy=heavies[1];
522         else {
523           /* find more heavy atoms */
524           other=moreheavy=NOTSET;
525           for(j=0; (j<plist[F_BONDS].nr) && (moreheavy==NOTSET); j++) {
526             if (plist[F_BONDS].param[j].AI==heavies[0])
527               other=plist[F_BONDS].param[j].AJ;
528             else if (plist[F_BONDS].param[j].AJ==heavies[0])
529               other=plist[F_BONDS].param[j].AI;
530             if ( (other != NOTSET) && (other != Heavy) ) 
531               moreheavy=other;
532           }
533           if (moreheavy==NOTSET)
534             gmx_fatal(FARGS,"Unbound molecule part %d-%d",Heavy+1,Hatoms[0]+1);
535         }
536         add_vsite3_atoms(&plist[ftype],Hatoms[i],Heavy,heavies[0],moreheavy,
537                        bSwapParity);
538         break;
539       }
540       case F_VSITE4FD: 
541       case F_VSITE4FDN:
542           if (nrheavies < 3) 
543           {
544               gmx_fatal(FARGS,"Not enough heavy atoms (%d) for %s (min 4)",
545                         nrheavies+1,
546                         interaction_function[vsite_type[Hatoms[i]]].name);
547           }
548           add_vsite4_atoms(&plist[ftype],  
549                            Hatoms[0], Heavy, heavies[0], heavies[1], heavies[2]);
550           break;
551       
552       default:
553         gmx_fatal(FARGS,"can't use add_vsites for interaction function %s",
554                     interaction_function[vsite_type[Hatoms[i]]].name);
555       } /* switch ftype */
556     } /* else */
557   } /* for i */
558 }
559
560 #define ANGLE_6RING (DEG2RAD*120)
561
562 /* cosine rule: a^2 = b^2 + c^2 - 2 b c cos(alpha) */
563 /* get a^2 when a, b and alpha are given: */
564 #define cosrule(b,c,alpha) ( sqr(b) + sqr(c) - 2*b*c*cos(alpha) )
565 /* get cos(alpha) when a, b and c are given: */
566 #define acosrule(a,b,c) ( (sqr(b)+sqr(c)-sqr(a))/(2*b*c) )
567
568 static int gen_vsites_6ring(t_atoms *at, int *vsite_type[], t_params plist[], 
569                           int nrfound, int *ats, real bond_cc, real bond_ch,
570                           real xcom, real ycom, gmx_bool bDoZ)
571 {
572   /* these MUST correspond to the atnms array in do_vsite_aromatics! */
573   enum { atCG, atCD1, atHD1, atCD2, atHD2, atCE1, atHE1, atCE2, atHE2, 
574          atCZ, atHZ, atNR };
575   
576   int i,nvsite;
577    real a,b,dCGCE,tmp1,tmp2,mtot,mG,mrest;
578    real xCG,yCG,xCE1,yCE1,xCE2,yCE2;
579   /* CG, CE1 and CE2 stay and each get a part of the total mass, 
580    * so the c-o-m stays the same.
581    */
582
583   if (bDoZ) {
584     if (atNR != nrfound)
585       gmx_incons("Generating vsites on 6-rings");
586   }
587
588   /* constraints between CG, CE1 and CE2: */
589   dCGCE = sqrt( cosrule(bond_cc,bond_cc,ANGLE_6RING) );
590   my_add_param(&(plist[F_CONSTRNC]),ats[atCG] ,ats[atCE1],dCGCE);
591   my_add_param(&(plist[F_CONSTRNC]),ats[atCG] ,ats[atCE2],dCGCE);
592   my_add_param(&(plist[F_CONSTRNC]),ats[atCE1],ats[atCE2],dCGCE);
593   
594   /* rest will be vsite3 */
595   mtot=0;
596   nvsite=0;
597   for(i=0; i<  (bDoZ ? atNR : atHZ) ; i++) {
598     mtot+=at->atom[ats[i]].m;
599     if ( i!=atCG && i!=atCE1 && i!=atCE2 && (bDoZ || (i!=atHZ && i!=atCZ) ) ) {
600       at->atom[ats[i]].m = at->atom[ats[i]].mB = 0;
601       (*vsite_type)[ats[i]]=F_VSITE3;
602       nvsite++;
603     }
604   }
605   /* Distribute mass so center-of-mass stays the same. 
606    * The center-of-mass in the call is defined with x=0 at
607    * the CE1-CE2 bond and y=0 at the line from CG to the middle of CE1-CE2 bond.
608    */
609   xCG=-bond_cc+bond_cc*cos(ANGLE_6RING);
610   yCG=0;
611   xCE1=0;
612   yCE1=bond_cc*sin(0.5*ANGLE_6RING);
613   xCE2=0;
614   yCE2=-bond_cc*sin(0.5*ANGLE_6RING);  
615   
616   mG = at->atom[ats[atCG]].m = at->atom[ats[atCG]].mB = xcom*mtot/xCG;
617   mrest=mtot-mG;
618   at->atom[ats[atCE1]].m = at->atom[ats[atCE1]].mB = 
619     at->atom[ats[atCE2]].m = at->atom[ats[atCE2]].mB = mrest / 2;
620   
621   /* vsite3 construction: r_d = r_i + a r_ij + b r_ik */
622   tmp1 = dCGCE*sin(ANGLE_6RING*0.5);
623   tmp2 = bond_cc*cos(0.5*ANGLE_6RING) + tmp1;
624   tmp1 *= 2;
625   a = b = - bond_ch / tmp1;
626   /* HE1 and HE2: */
627   add_vsite3_param(&plist[F_VSITE3],
628                  ats[atHE1],ats[atCE1],ats[atCE2],ats[atCG], a,b);
629   add_vsite3_param(&plist[F_VSITE3],
630                  ats[atHE2],ats[atCE2],ats[atCE1],ats[atCG], a,b);
631   /* CD1, CD2 and CZ: */
632   a = b = tmp2 / tmp1;
633   add_vsite3_param(&plist[F_VSITE3],
634                  ats[atCD1],ats[atCE2],ats[atCE1],ats[atCG], a,b);
635   add_vsite3_param(&plist[F_VSITE3],
636                  ats[atCD2],ats[atCE1],ats[atCE2],ats[atCG], a,b);
637   if (bDoZ)
638     add_vsite3_param(&plist[F_VSITE3],
639                    ats[atCZ], ats[atCG], ats[atCE1],ats[atCE2],a,b);
640   /* HD1, HD2 and HZ: */
641   a = b = ( bond_ch + tmp2 ) / tmp1;
642   add_vsite3_param(&plist[F_VSITE3],
643                  ats[atHD1],ats[atCE2],ats[atCE1],ats[atCG], a,b);
644   add_vsite3_param(&plist[F_VSITE3],
645                  ats[atHD2],ats[atCE1],ats[atCE2],ats[atCG], a,b);
646   if (bDoZ)
647     add_vsite3_param(&plist[F_VSITE3],
648                    ats[atHZ], ats[atCG], ats[atCE1],ats[atCE2],a,b);
649   
650   return nvsite;
651 }
652
653 static int gen_vsites_phe(t_atoms *at, int *vsite_type[], t_params plist[], 
654                          int nrfound, int *ats, t_vsitetop *vsitetop, int nvsitetop)
655 {
656   real bond_cc,bond_ch;
657   real xcom,ycom,mtot;
658   int i;
659   /* these MUST correspond to the atnms array in do_vsite_aromatics! */
660   enum { atCG, atCD1, atHD1, atCD2, atHD2, atCE1, atHE1, atCE2, atHE2, 
661          atCZ, atHZ, atNR };
662   real x[atNR],y[atNR];
663   /* Aromatic rings have 6-fold symmetry, so we only need one bond length.
664    * (angle is always 120 degrees).
665    */   
666   bond_cc=get_ddb_bond(vsitetop,nvsitetop,"PHE","CD1","CE1");
667   bond_ch=get_ddb_bond(vsitetop,nvsitetop,"PHE","CD1","HD1");
668   
669   x[atCG]=-bond_cc+bond_cc*cos(ANGLE_6RING);
670   y[atCG]=0;
671   x[atCD1]=-bond_cc;
672   y[atCD1]=bond_cc*sin(0.5*ANGLE_6RING);
673   x[atHD1]=x[atCD1]+bond_ch*cos(ANGLE_6RING);
674   y[atHD1]=y[atCD1]+bond_ch*sin(ANGLE_6RING);
675   x[atCE1]=0;
676   y[atCE1]=y[atCD1];
677   x[atHE1]=x[atCE1]-bond_ch*cos(ANGLE_6RING);
678   y[atHE1]=y[atCE1]+bond_ch*sin(ANGLE_6RING);
679   x[atCD2]=x[atCD1];
680   y[atCD2]=-y[atCD1];
681   x[atHD2]=x[atHD1];
682   y[atHD2]=-y[atHD1];
683   x[atCE2]=x[atCE1];
684   y[atCE2]=-y[atCE1];
685   x[atHE2]=x[atHE1];
686   y[atHE2]=-y[atHE1];
687   x[atCZ]=bond_cc*cos(0.5*ANGLE_6RING);
688   y[atCZ]=0;
689   x[atHZ]=x[atCZ]+bond_ch;
690   y[atHZ]=0;
691
692   xcom=ycom=mtot=0;
693   for(i=0;i<atNR;i++) {
694     xcom+=x[i]*at->atom[ats[i]].m;
695     ycom+=y[i]*at->atom[ats[i]].m;
696     mtot+=at->atom[ats[i]].m;
697   }
698   xcom/=mtot;
699   ycom/=mtot;
700
701   return gen_vsites_6ring(at, vsite_type, plist, nrfound, ats, bond_cc, bond_ch, xcom, ycom, TRUE);
702 }
703
704 static void calc_vsite3_param(real xd,real yd,real xi,real yi,real xj,real yj,
705                               real xk, real yk, real *a, real *b)
706 {
707   /* determine parameters by solving the equation system, since we know the
708    * virtual site coordinates here.
709    */
710   real dx_ij,dx_ik,dy_ij,dy_ik;
711   real b_ij,b_ik;
712
713   dx_ij=xj-xi;
714   dy_ij=yj-yi;
715   dx_ik=xk-xi;
716   dy_ik=yk-yi;
717   b_ij=sqrt(dx_ij*dx_ij+dy_ij*dy_ij);
718   b_ik=sqrt(dx_ik*dx_ik+dy_ik*dy_ik);
719
720   *a = ( (xd-xi)*dy_ik - dx_ik*(yd-yi) ) / (dx_ij*dy_ik - dx_ik*dy_ij);
721   *b = ( yd - yi - (*a)*dy_ij ) / dy_ik;
722 }
723
724
725 static int gen_vsites_trp(gpp_atomtype_t atype, rvec *newx[],
726                           t_atom *newatom[], char ***newatomname[], 
727                           int *o2n[], int *newvsite_type[], int *newcgnr[],
728                           t_symtab *symtab, int *nadd, rvec x[], int *cgnr[],
729                           t_atoms *at, int *vsite_type[], t_params plist[], 
730                           int nrfound, int *ats, int add_shift,
731                           t_vsitetop *vsitetop, int nvsitetop)
732 {
733 #define NMASS 2
734   /* these MUST correspond to the atnms array in do_vsite_aromatics! */
735   enum { 
736     atCB,  atCG,  atCD1, atHD1, atCD2, atNE1, atHE1, atCE2, atCE3, atHE3, 
737     atCZ2, atHZ2, atCZ3, atHZ3, atCH2, atHH2, atNR };
738   /* weights for determining the COM's of both rings (M1 and M2): */
739   real mw[NMASS][atNR] = {
740     {   0,     1,     1,     1,   0.5,     1,     1,   0.5,     0,     0,
741         0,     0,     0,     0,     0,     0 },
742     {   0,     0,     0,     0,   0.5,     0,     0,   0.5,     1,     1,
743         1,     1,     1,     1,     1,     1 }
744   };
745  
746   real xi[atNR],yi[atNR];
747   real xcom[NMASS],ycom[NMASS],I,alpha;
748   real lineA,lineB,dist;
749   real b_CD2_CE2,b_NE1_CE2,b_CG_CD2,b_CH2_HH2,b_CE2_CZ2;
750   real b_NE1_HE1,b_CD2_CE3,b_CE3_CZ3,b_CB_CG;
751   real b_CZ2_CH2,b_CZ2_HZ2,b_CD1_HD1,b_CE3_HE3;
752   real b_CG_CD1,b_CZ3_HZ3;
753   real a_NE1_CE2_CD2,a_CE2_CD2_CG,a_CB_CG_CD2,a_CE2_CD2_CE3;
754   real a_CB_CG_CD1,a_CD2_CG_CD1,a_CE2_CZ2_HZ2,a_CZ2_CH2_HH2;
755   real a_CD2_CE2_CZ2,a_CD2_CE3_CZ3,a_CE3_CZ3_HZ3,a_CG_CD1_HD1;
756   real a_CE2_CZ2_CH2,a_HE1_NE1_CE2,a_CD2_CE3_HE3;
757   real xM[NMASS];
758   int  atM[NMASS],tpM,i,i0,j,nvsite;
759   real mwtot,mtot,mM[NMASS],dCBM1,dCBM2,dM1M2;
760   real a,b,c[MAXFORCEPARAM];
761   rvec r_ij,r_ik,t1,t2;
762   char name[10];
763
764   if (atNR != nrfound)
765     gmx_incons("atom types in gen_vsites_trp");
766   /* Get geometry from database */
767   b_CD2_CE2=get_ddb_bond(vsitetop,nvsitetop,"TRP","CD2","CE2");
768   b_NE1_CE2=get_ddb_bond(vsitetop,nvsitetop,"TRP","NE1","CE2");
769   b_CG_CD1=get_ddb_bond(vsitetop,nvsitetop,"TRP","CG","CD1");
770   b_CG_CD2=get_ddb_bond(vsitetop,nvsitetop,"TRP","CG","CD2");
771   b_CB_CG=get_ddb_bond(vsitetop,nvsitetop,"TRP","CB","CG");
772   b_CE2_CZ2=get_ddb_bond(vsitetop,nvsitetop,"TRP","CE2","CZ2");
773   b_CD2_CE3=get_ddb_bond(vsitetop,nvsitetop,"TRP","CD2","CE3");
774   b_CE3_CZ3=get_ddb_bond(vsitetop,nvsitetop,"TRP","CE3","CZ3");
775   b_CZ2_CH2=get_ddb_bond(vsitetop,nvsitetop,"TRP","CZ2","CH2");
776
777   b_CD1_HD1=get_ddb_bond(vsitetop,nvsitetop,"TRP","CD1","HD1");
778   b_CZ2_HZ2=get_ddb_bond(vsitetop,nvsitetop,"TRP","CZ2","HZ2");
779   b_NE1_HE1=get_ddb_bond(vsitetop,nvsitetop,"TRP","NE1","HE1");
780   b_CH2_HH2=get_ddb_bond(vsitetop,nvsitetop,"TRP","CH2","HH2");
781   b_CE3_HE3=get_ddb_bond(vsitetop,nvsitetop,"TRP","CE3","HE3");
782   b_CZ3_HZ3=get_ddb_bond(vsitetop,nvsitetop,"TRP","CZ3","HZ3");
783
784   a_NE1_CE2_CD2=DEG2RAD*get_ddb_angle(vsitetop,nvsitetop,"TRP","NE1","CE2","CD2");
785   a_CE2_CD2_CG=DEG2RAD*get_ddb_angle(vsitetop,nvsitetop,"TRP","CE2","CD2","CG");
786   a_CB_CG_CD2=DEG2RAD*get_ddb_angle(vsitetop,nvsitetop,"TRP","CB","CG","CD2");
787   a_CD2_CG_CD1=DEG2RAD*get_ddb_angle(vsitetop,nvsitetop,"TRP","CD2","CG","CD1");
788   a_CB_CG_CD1=DEG2RAD*get_ddb_angle(vsitetop,nvsitetop,"TRP","CB","CG","CD1");
789  
790   a_CE2_CD2_CE3=DEG2RAD*get_ddb_angle(vsitetop,nvsitetop,"TRP","CE2","CD2","CE3");
791   a_CD2_CE2_CZ2=DEG2RAD*get_ddb_angle(vsitetop,nvsitetop,"TRP","CD2","CE2","CZ2");
792   a_CD2_CE3_CZ3=DEG2RAD*get_ddb_angle(vsitetop,nvsitetop,"TRP","CD2","CE3","CZ3");
793   a_CE3_CZ3_HZ3=DEG2RAD*get_ddb_angle(vsitetop,nvsitetop,"TRP","CE3","CZ3","HZ3");
794   a_CZ2_CH2_HH2=DEG2RAD*get_ddb_angle(vsitetop,nvsitetop,"TRP","CZ2","CH2","HH2");
795   a_CE2_CZ2_HZ2=DEG2RAD*get_ddb_angle(vsitetop,nvsitetop,"TRP","CE2","CZ2","HZ2");
796   a_CE2_CZ2_CH2=DEG2RAD*get_ddb_angle(vsitetop,nvsitetop,"TRP","CE2","CZ2","CH2");
797   a_CG_CD1_HD1=DEG2RAD*get_ddb_angle(vsitetop,nvsitetop,"TRP","CG","CD1","HD1");
798   a_HE1_NE1_CE2=DEG2RAD*get_ddb_angle(vsitetop,nvsitetop,"TRP","HE1","NE1","CE2");
799   a_CD2_CE3_HE3=DEG2RAD*get_ddb_angle(vsitetop,nvsitetop,"TRP","CD2","CE3","HE3");
800  
801   /* Calculate local coordinates.
802    * y-axis (x=0) is the bond CD2-CE2.
803    * x-axis (y=0) is perpendicular to the bond CD2-CE2 and
804    * intersects the middle of the bond.
805    */
806   xi[atCD2]=0;
807   yi[atCD2]=-0.5*b_CD2_CE2;
808   
809   xi[atCE2]=0;
810   yi[atCE2]=0.5*b_CD2_CE2;
811
812   xi[atNE1]=-b_NE1_CE2*sin(a_NE1_CE2_CD2);
813   yi[atNE1]=yi[atCE2]-b_NE1_CE2*cos(a_NE1_CE2_CD2);
814
815   xi[atCG]=-b_CG_CD2*sin(a_CE2_CD2_CG);
816   yi[atCG]=yi[atCD2]+b_CG_CD2*cos(a_CE2_CD2_CG);
817
818   alpha = a_CE2_CD2_CG + M_PI - a_CB_CG_CD2;
819   xi[atCB]=xi[atCG]-b_CB_CG*sin(alpha);
820   yi[atCB]=yi[atCG]+b_CB_CG*cos(alpha);
821
822   alpha = a_CE2_CD2_CG + a_CD2_CG_CD1 - M_PI;
823   xi[atCD1]=xi[atCG]-b_CG_CD1*sin(alpha);
824   yi[atCD1]=yi[atCG]+b_CG_CD1*cos(alpha);
825
826   xi[atCE3]=b_CD2_CE3*sin(a_CE2_CD2_CE3);
827   yi[atCE3]=yi[atCD2]+b_CD2_CE3*cos(a_CE2_CD2_CE3);
828
829   xi[atCZ2]=b_CE2_CZ2*sin(a_CD2_CE2_CZ2);
830   yi[atCZ2]=yi[atCE2]-b_CE2_CZ2*cos(a_CD2_CE2_CZ2);
831
832   alpha = a_CE2_CD2_CE3 + a_CD2_CE3_CZ3 - M_PI;
833   xi[atCZ3]=xi[atCE3]+b_CE3_CZ3*sin(alpha);
834   yi[atCZ3]=yi[atCE3]+b_CE3_CZ3*cos(alpha);
835
836   alpha = a_CD2_CE2_CZ2 + a_CE2_CZ2_CH2 - M_PI;
837   xi[atCH2]=xi[atCZ2]+b_CZ2_CH2*sin(alpha);
838   yi[atCH2]=yi[atCZ2]-b_CZ2_CH2*cos(alpha);
839
840   /* hydrogens */
841   alpha = a_CE2_CD2_CG + a_CD2_CG_CD1 - a_CG_CD1_HD1;
842   xi[atHD1]=xi[atCD1]-b_CD1_HD1*sin(alpha);
843   yi[atHD1]=yi[atCD1]+b_CD1_HD1*cos(alpha);
844
845   alpha = a_NE1_CE2_CD2 + M_PI - a_HE1_NE1_CE2;
846   xi[atHE1]=xi[atNE1]-b_NE1_HE1*sin(alpha);
847   yi[atHE1]=yi[atNE1]-b_NE1_HE1*cos(alpha);
848   
849   alpha = a_CE2_CD2_CE3 + M_PI - a_CD2_CE3_HE3;
850   xi[atHE3]=xi[atCE3]+b_CE3_HE3*sin(alpha);
851   yi[atHE3]=yi[atCE3]+b_CE3_HE3*cos(alpha);
852
853   alpha = a_CD2_CE2_CZ2 + M_PI - a_CE2_CZ2_HZ2;
854   xi[atHZ2]=xi[atCZ2]+b_CZ2_HZ2*sin(alpha);
855   yi[atHZ2]=yi[atCZ2]-b_CZ2_HZ2*cos(alpha);
856
857   alpha = a_CD2_CE2_CZ2 + a_CE2_CZ2_CH2 - a_CZ2_CH2_HH2;
858   xi[atHZ3]=xi[atCZ3]+b_CZ3_HZ3*sin(alpha);
859   yi[atHZ3]=yi[atCZ3]+b_CZ3_HZ3*cos(alpha);
860
861   alpha = a_CE2_CD2_CE3 + a_CD2_CE3_CZ3 - a_CE3_CZ3_HZ3;
862   xi[atHH2]=xi[atCH2]+b_CH2_HH2*sin(alpha);
863   yi[atHH2]=yi[atCH2]-b_CH2_HH2*cos(alpha);
864
865   /* Determine coeff. for the line CB-CG */
866   lineA=(yi[atCB]-yi[atCG])/(xi[atCB]-xi[atCG]);
867   lineB=yi[atCG]-lineA*xi[atCG];
868   
869   /* Calculate masses for each ring and put it on the dummy masses */
870   for(j=0; j<NMASS; j++)
871     mM[j]=xcom[j]=ycom[j]=0;
872   for(i=0; i<atNR; i++) {
873     if (i!=atCB) {
874       for(j=0; j<NMASS; j++) {
875          mM[j] += mw[j][i] * at->atom[ats[i]].m;
876          xcom[j] += xi[i] * mw[j][i] * at->atom[ats[i]].m;
877          ycom[j] += yi[i] * mw[j][i] * at->atom[ats[i]].m;
878       }  
879     }
880   }
881   for(j=0; j<NMASS; j++) {
882     xcom[j]/=mM[j];
883     ycom[j]/=mM[j];
884   }
885   
886   /* get dummy mass type */
887   tpM=vsite_nm2type("MW",atype);
888   /* make space for 2 masses: shift all atoms starting with CB */
889   i0=ats[atCB];
890   for(j=0; j<NMASS; j++)
891     atM[j]=i0+*nadd+j;
892   if (debug)
893      fprintf(stderr,"Inserting %d dummy masses at %d\n",NMASS,(*o2n)[i0]+1);
894   *nadd+=NMASS;
895   for(j=i0; j<at->nr; j++)
896     (*o2n)[j]=j+*nadd;
897   srenew(*newx,at->nr+*nadd);
898   srenew(*newatom,at->nr+*nadd);
899   srenew(*newatomname,at->nr+*nadd);
900   srenew(*newvsite_type,at->nr+*nadd);
901   srenew(*newcgnr,at->nr+*nadd);
902   for(j=0; j<NMASS; j++)
903     (*newatomname)[at->nr+*nadd-1-j]=NULL;
904   
905   /* Dummy masses will be placed at the center-of-mass in each ring. */
906
907   /* calc initial position for dummy masses in real (non-local) coordinates.
908    * Cheat by using the routine to calculate virtual site parameters. It is
909    * much easier when we have the coordinates expressed in terms of
910    * CB, CG, CD2.
911    */
912   rvec_sub(x[ats[atCB]],x[ats[atCG]],r_ij);
913   rvec_sub(x[ats[atCD2]],x[ats[atCG]],r_ik);
914   calc_vsite3_param(xcom[0],ycom[0],xi[atCG],yi[atCG],xi[atCB],yi[atCB],
915                     xi[atCD2],yi[atCD2],&a,&b);
916   svmul(a,r_ij,t1);
917   svmul(b,r_ik,t2);
918   rvec_add(t1,t2,t1);
919   rvec_add(t1,x[ats[atCG]],(*newx)[atM[0]]);
920   
921   calc_vsite3_param(xcom[1],ycom[1],xi[atCG],yi[atCG],xi[atCB],yi[atCB],
922                     xi[atCD2],yi[atCD2],&a,&b);
923   svmul(a,r_ij,t1);
924   svmul(b,r_ik,t2);
925   rvec_add(t1,t2,t1);
926   rvec_add(t1,x[ats[atCG]],(*newx)[atM[1]]);
927
928   /* set parameters for the masses */
929   for(j=0; j<NMASS; j++) {
930     sprintf(name,"MW%d",j+1);
931     (*newatomname)  [atM[j]]       = put_symtab(symtab,name);
932     (*newatom)      [atM[j]].m     = (*newatom)[atM[j]].mB    = mM[j];
933     (*newatom)      [atM[j]].q     = (*newatom)[atM[j]].qB    = 0.0;
934     (*newatom)      [atM[j]].type  = (*newatom)[atM[j]].typeB = tpM;
935     (*newatom)      [atM[j]].ptype = eptAtom;
936     (*newatom)      [atM[j]].resind= at->atom[i0].resind;
937     (*newvsite_type)[atM[j]]       = NOTSET;
938     (*newcgnr)      [atM[j]]       = (*cgnr)[i0];
939   }
940   /* renumber cgnr: */
941   for(i=i0; i<at->nr; i++)
942     (*cgnr)[i]++;
943
944   /* constraints between CB, M1 and M2 */
945   /* 'add_shift' says which atoms won't be renumbered afterwards */
946   dCBM1 = sqrt( sqr(xcom[0]-xi[atCB]) + sqr(ycom[0]-yi[atCB]) );
947   dM1M2 = sqrt( sqr(xcom[0]-xcom[1]) + sqr(ycom[0]-ycom[1]) );
948   dCBM2 = sqrt( sqr(xcom[1]-xi[atCB]) + sqr(ycom[1]-yi[atCB]) );
949   my_add_param(&(plist[F_CONSTRNC]),ats[atCB],       add_shift+atM[0],dCBM1);
950   my_add_param(&(plist[F_CONSTRNC]),ats[atCB],       add_shift+atM[1],dCBM2);
951   my_add_param(&(plist[F_CONSTRNC]),add_shift+atM[0],add_shift+atM[1],dM1M2);
952   
953   /* rest will be vsite3 */
954   nvsite=0;
955   for(i=0; i<atNR; i++)
956     if (i!=atCB) {
957       at->atom[ats[i]].m = at->atom[ats[i]].mB = 0;
958       (*vsite_type)[ats[i]] = F_VSITE3;
959       nvsite++;
960     }
961   
962   /* now define all vsites from M1, M2, CB, ie:
963      r_d = r_M1 + a r_M1_M2 + b r_M1_CB */
964   for(i=0; i<atNR; i++)
965     if ( (*vsite_type)[ats[i]] == F_VSITE3 ) {
966       calc_vsite3_param(xi[i],yi[i],xcom[0],ycom[0],xcom[1],ycom[1],xi[atCB],yi[atCB],&a,&b);
967       add_vsite3_param(&plist[F_VSITE3],
968                      ats[i],add_shift+atM[0],add_shift+atM[1],ats[atCB],a,b);
969     }
970   return nvsite;
971 #undef NMASS
972 }
973
974
975 static int gen_vsites_tyr(gpp_atomtype_t atype, rvec *newx[],
976                           t_atom *newatom[], char ***newatomname[], 
977                         int *o2n[], int *newvsite_type[], int *newcgnr[],
978                           t_symtab *symtab, int *nadd, rvec x[], int *cgnr[],
979                           t_atoms *at, int *vsite_type[], t_params plist[], 
980                           int nrfound, int *ats, int add_shift,
981                           t_vsitetop *vsitetop, int nvsitetop)
982 {
983   int nvsite,i,i0,j,atM,tpM;
984   real dCGCE,dCEOH,dCGM,tmp1,a,b;
985   real bond_cc,bond_ch,bond_co,bond_oh,angle_coh;
986   real xcom,ycom,mtot;
987   real vmass,vdist,mM;
988   rvec r1;
989   char name[10];
990
991   /* these MUST correspond to the atnms array in do_vsite_aromatics! */
992   enum { atCG, atCD1, atHD1, atCD2, atHD2, atCE1, atHE1, atCE2, atHE2, 
993          atCZ, atOH, atHH, atNR };
994   real xi[atNR],yi[atNR];
995   /* CG, CE1, CE2 (as in general 6-ring) and OH and HH stay, 
996      rest gets virtualized.
997      Now we have two linked triangles with one improper keeping them flat */
998   if (atNR != nrfound)
999     gmx_incons("Number of atom types in gen_vsites_tyr");
1000
1001   /* Aromatic rings have 6-fold symmetry, so we only need one bond length
1002    * for the ring part (angle is always 120 degrees).
1003    */
1004   bond_cc=get_ddb_bond(vsitetop,nvsitetop,"TYR","CD1","CE1");
1005   bond_ch=get_ddb_bond(vsitetop,nvsitetop,"TYR","CD1","HD1");
1006   bond_co=get_ddb_bond(vsitetop,nvsitetop,"TYR","CZ","OH");
1007   bond_oh=get_ddb_bond(vsitetop,nvsitetop,"TYR","OH","HH");
1008   angle_coh=DEG2RAD*get_ddb_angle(vsitetop,nvsitetop,"TYR","CZ","OH","HH");
1009   
1010   xi[atCG]=-bond_cc+bond_cc*cos(ANGLE_6RING);
1011   yi[atCG]=0;
1012   xi[atCD1]=-bond_cc;
1013   yi[atCD1]=bond_cc*sin(0.5*ANGLE_6RING);
1014   xi[atHD1]=xi[atCD1]+bond_ch*cos(ANGLE_6RING);
1015   yi[atHD1]=yi[atCD1]+bond_ch*sin(ANGLE_6RING);
1016   xi[atCE1]=0;
1017   yi[atCE1]=yi[atCD1];
1018   xi[atHE1]=xi[atCE1]-bond_ch*cos(ANGLE_6RING);
1019   yi[atHE1]=yi[atCE1]+bond_ch*sin(ANGLE_6RING);
1020   xi[atCD2]=xi[atCD1];
1021   yi[atCD2]=-yi[atCD1];
1022   xi[atHD2]=xi[atHD1];
1023   yi[atHD2]=-yi[atHD1];
1024   xi[atCE2]=xi[atCE1];
1025   yi[atCE2]=-yi[atCE1];
1026   xi[atHE2]=xi[atHE1];
1027   yi[atHE2]=-yi[atHE1];
1028   xi[atCZ]=bond_cc*cos(0.5*ANGLE_6RING);
1029   yi[atCZ]=0;
1030   xi[atOH]=xi[atCZ]+bond_co;
1031   yi[atOH]=0;
1032
1033   xcom=ycom=mtot=0;
1034   for(i=0;i<atOH;i++) {
1035     xcom+=xi[i]*at->atom[ats[i]].m;
1036     ycom+=yi[i]*at->atom[ats[i]].m;
1037     mtot+=at->atom[ats[i]].m;
1038   }
1039   xcom/=mtot;
1040   ycom/=mtot;
1041
1042   /* first do 6 ring as default, 
1043      except CZ (we'll do that different) and HZ (we don't have that): */
1044   nvsite = gen_vsites_6ring(at, vsite_type, plist, nrfound, ats, bond_cc, bond_ch, xcom, ycom, FALSE);
1045   
1046   /* then construct CZ from the 2nd triangle */
1047   /* vsite3 construction: r_d = r_i + a r_ij + b r_ik */
1048   a = b = 0.5 * bond_co / ( bond_co - bond_cc*cos(ANGLE_6RING) );
1049   add_vsite3_param(&plist[F_VSITE3],
1050                  ats[atCZ],ats[atOH],ats[atCE1],ats[atCE2],a,b);
1051   at->atom[ats[atCZ]].m = at->atom[ats[atCZ]].mB = 0;
1052   
1053   /* constraints between CE1, CE2 and OH */
1054   dCGCE = sqrt( cosrule(bond_cc,bond_cc,ANGLE_6RING) );
1055   dCEOH = sqrt( cosrule(bond_cc,bond_co,ANGLE_6RING) );
1056   my_add_param(&(plist[F_CONSTRNC]),ats[atCE1],ats[atOH],dCEOH);
1057   my_add_param(&(plist[F_CONSTRNC]),ats[atCE2],ats[atOH],dCEOH);
1058
1059   /* We also want to constrain the angle C-O-H, but since CZ is constructed
1060    * we need to introduce a constraint to CG.
1061    * CG is much further away, so that will lead to instabilities in LINCS
1062    * when we constrain both CG-HH and OH-HH distances. Instead of requiring
1063    * the use of lincs_order=8 we introduce a dummy mass three times further
1064    * away from OH than HH. The mass is accordingly a third, with the remaining
1065    * 2/3 moved to OH. This shouldnt cause any problems since the forces will
1066    * apply to the HH constructed atom and not directly on the virtual mass.
1067    */
1068
1069   vdist=2.0*bond_oh;
1070   mM=at->atom[ats[atHH]].m/2.0;
1071   at->atom[ats[atOH]].m+=mM;  /* add 1/2 of original H mass */
1072   at->atom[ats[atOH]].mB+=mM; /* add 1/2 of original H mass */
1073   at->atom[ats[atHH]].m=at->atom[ats[atHH]].mB=0;
1074   
1075   /* get dummy mass type */
1076   tpM=vsite_nm2type("MW",atype);
1077   /* make space for 1 mass: shift HH only */
1078   i0=ats[atHH];
1079   atM=i0+*nadd;
1080   if (debug)
1081      fprintf(stderr,"Inserting 1 dummy mass at %d\n",(*o2n)[i0]+1);
1082   (*nadd)++;
1083   for(j=i0; j<at->nr; j++)
1084     (*o2n)[j]=j+*nadd;
1085   srenew(*newx,at->nr+*nadd);
1086   srenew(*newatom,at->nr+*nadd);
1087   srenew(*newatomname,at->nr+*nadd);
1088   srenew(*newvsite_type,at->nr+*nadd);
1089   srenew(*newcgnr,at->nr+*nadd);
1090   (*newatomname)[at->nr+*nadd-1]=NULL; 
1091   
1092   /* Calc the dummy mass initial position */
1093   rvec_sub(x[ats[atHH]],x[ats[atOH]],r1);
1094   svmul(2.0,r1,r1);
1095   rvec_add(r1,x[ats[atHH]],(*newx)[atM]);
1096   
1097   strcpy(name,"MW1");
1098   (*newatomname)  [atM]       = put_symtab(symtab,name);
1099   (*newatom)      [atM].m     = (*newatom)[atM].mB    = mM;
1100   (*newatom)      [atM].q     = (*newatom)[atM].qB    = 0.0;
1101   (*newatom)      [atM].type  = (*newatom)[atM].typeB = tpM;
1102   (*newatom)      [atM].ptype = eptAtom;
1103   (*newatom)      [atM].resind= at->atom[i0].resind;
1104   (*newvsite_type)[atM]       = NOTSET;
1105   (*newcgnr)      [atM]       = (*cgnr)[i0]; 
1106   /* renumber cgnr: */
1107   for(i=i0; i<at->nr; i++)
1108     (*cgnr)[i]++;
1109
1110   (*vsite_type)[ats[atHH]] = F_VSITE2;
1111   nvsite++;
1112   /* assume we also want the COH angle constrained: */
1113   tmp1 = bond_cc*cos(0.5*ANGLE_6RING) + dCGCE*sin(ANGLE_6RING*0.5) + bond_co;
1114   dCGM = sqrt( cosrule(tmp1,vdist,angle_coh) );
1115   my_add_param(&(plist[F_CONSTRNC]),ats[atCG],add_shift+atM,dCGM);
1116   my_add_param(&(plist[F_CONSTRNC]),ats[atOH],add_shift+atM,vdist);
1117
1118   add_vsite2_param(&plist[F_VSITE2],
1119                  ats[atHH],ats[atOH],add_shift+atM,1.0/2.0);
1120   return nvsite;
1121 }
1122       
1123 static int gen_vsites_his(t_atoms *at, int *vsite_type[], t_params plist[], 
1124                         int nrfound, int *ats, t_vsitetop *vsitetop, int nvsitetop)
1125 {
1126   int nvsite,i;
1127   real a,b,alpha,dCGCE1,dCGNE2;
1128   real sinalpha,cosalpha;
1129   real xcom,ycom,mtot;
1130   real mG,mrest,mCE1,mNE2;
1131   real b_CG_ND1,b_ND1_CE1,b_CE1_NE2,b_CG_CD2,b_CD2_NE2;
1132   real b_ND1_HD1,b_NE2_HE2,b_CE1_HE1,b_CD2_HD2;
1133   real a_CG_ND1_CE1,a_CG_CD2_NE2,a_ND1_CE1_NE2,a_CE1_NE2_CD2;
1134   real a_NE2_CE1_HE1,a_NE2_CD2_HD2,a_CE1_ND1_HD1,a_CE1_NE2_HE2;
1135   char resname[10];
1136
1137   /* these MUST correspond to the atnms array in do_vsite_aromatics! */
1138   enum { atCG, atND1, atHD1, atCD2, atHD2, atCE1, atHE1, atNE2, atHE2, atNR };
1139   real x[atNR],y[atNR];
1140
1141   /* CG, CE1 and NE2 stay, each gets part of the total mass,
1142      rest gets virtualized */
1143   /* check number of atoms, 3 hydrogens may be missing: */
1144   /* assert( nrfound >= atNR-3 || nrfound <= atNR );
1145    * Don't understand the above logic. Shouldn't it be && rather than || ???
1146    */
1147   if ((nrfound < atNR-3) || (nrfound > atNR))
1148     gmx_incons("Generating vsites for HIS");
1149   
1150   /* avoid warnings about uninitialized variables */
1151   b_ND1_HD1=b_NE2_HE2=b_CE1_HE1=b_CD2_HD2=a_NE2_CE1_HE1=
1152     a_NE2_CD2_HD2=a_CE1_ND1_HD1=a_CE1_NE2_HE2=0;
1153
1154   if(ats[atHD1]!=NOTSET) {
1155     if(ats[atHE2]!=NOTSET) 
1156       sprintf(resname,"HISH");
1157     else 
1158       sprintf(resname,"HISA");
1159   } else {
1160     sprintf(resname,"HISB");
1161   }
1162   
1163   /* Get geometry from database */
1164   b_CG_ND1=get_ddb_bond(vsitetop,nvsitetop,resname,"CG","ND1");
1165   b_ND1_CE1=get_ddb_bond(vsitetop,nvsitetop,resname,"ND1","CE1");
1166   b_CE1_NE2=get_ddb_bond(vsitetop,nvsitetop,resname,"CE1","NE2");
1167   b_CG_CD2 =get_ddb_bond(vsitetop,nvsitetop,resname,"CG","CD2");
1168   b_CD2_NE2=get_ddb_bond(vsitetop,nvsitetop,resname,"CD2","NE2");
1169   a_CG_ND1_CE1=DEG2RAD*get_ddb_angle(vsitetop,nvsitetop,resname,"CG","ND1","CE1");
1170   a_CG_CD2_NE2=DEG2RAD*get_ddb_angle(vsitetop,nvsitetop,resname,"CG","CD2","NE2");
1171   a_ND1_CE1_NE2=DEG2RAD*get_ddb_angle(vsitetop,nvsitetop,resname,"ND1","CE1","NE2");
1172   a_CE1_NE2_CD2=DEG2RAD*get_ddb_angle(vsitetop,nvsitetop,resname,"CE1","NE2","CD2");
1173
1174   if(ats[atHD1]!=NOTSET) {
1175     b_ND1_HD1=get_ddb_bond(vsitetop,nvsitetop,resname,"ND1","HD1");
1176     a_CE1_ND1_HD1=DEG2RAD*get_ddb_angle(vsitetop,nvsitetop,resname,"CE1","ND1","HD1");
1177   }
1178   if(ats[atHE2]!=NOTSET) {
1179     b_NE2_HE2=get_ddb_bond(vsitetop,nvsitetop,resname,"NE2","HE2");
1180     a_CE1_NE2_HE2=DEG2RAD*get_ddb_angle(vsitetop,nvsitetop,resname,"CE1","NE2","HE2");
1181   }
1182   if(ats[atHD2]!=NOTSET) {
1183     b_CD2_HD2=get_ddb_bond(vsitetop,nvsitetop,resname,"CD2","HD2");
1184     a_NE2_CD2_HD2=DEG2RAD*get_ddb_angle(vsitetop,nvsitetop,resname,"NE2","CD2","HD2");
1185   }
1186   if(ats[atHE1]!=NOTSET) {
1187     b_CE1_HE1=get_ddb_bond(vsitetop,nvsitetop,resname,"CE1","HE1");
1188     a_NE2_CE1_HE1=DEG2RAD*get_ddb_angle(vsitetop,nvsitetop,resname,"NE2","CE1","HE1");
1189   }
1190
1191   /* constraints between CG, CE1 and NE1 */
1192   dCGCE1   = sqrt( cosrule(b_CG_ND1,b_ND1_CE1,a_CG_ND1_CE1) );
1193   dCGNE2   = sqrt( cosrule(b_CG_CD2,b_CD2_NE2,a_CG_CD2_NE2) );
1194
1195   my_add_param(&(plist[F_CONSTRNC]),ats[atCG] ,ats[atCE1],dCGCE1);
1196   my_add_param(&(plist[F_CONSTRNC]),ats[atCG] ,ats[atNE2],dCGNE2);
1197   /* we already have a constraint CE1-NE2, so we don't add it again */
1198   
1199   /* calculate the positions in a local frame of reference. 
1200    * The x-axis is the line from CG that makes a right angle
1201    * with the bond CE1-NE2, and the y-axis the bond CE1-NE2.
1202    */
1203   /* First calculate the x-axis intersection with y-axis (=yCE1).
1204    * Get cos(angle CG-CE1-NE2) :
1205    */
1206   cosalpha=acosrule(dCGNE2,dCGCE1,b_CE1_NE2);
1207   x[atCE1] = 0;
1208   y[atCE1] = cosalpha*dCGCE1;
1209   x[atNE2] = 0;
1210   y[atNE2] = y[atCE1]-b_CE1_NE2;
1211   sinalpha=sqrt(1-cosalpha*cosalpha);
1212   x[atCG]  = - sinalpha*dCGCE1;
1213   y[atCG]  = 0;
1214   x[atHE1] = x[atHE2] = x[atHD1] = x[atHD2] = 0;
1215   y[atHE1] = y[atHE2] = y[atHD1] = y[atHD2] = 0;
1216   
1217   /* calculate ND1 and CD2 positions from CE1 and NE2 */
1218
1219   x[atND1] = -b_ND1_CE1*sin(a_ND1_CE1_NE2);
1220   y[atND1] = y[atCE1]-b_ND1_CE1*cos(a_ND1_CE1_NE2);
1221
1222   x[atCD2] = -b_CD2_NE2*sin(a_CE1_NE2_CD2);
1223   y[atCD2] = y[atNE2]+b_CD2_NE2*cos(a_CE1_NE2_CD2);
1224
1225   /* And finally the hydrogen positions */
1226   if(ats[atHE1]!=NOTSET) {  
1227     x[atHE1] = x[atCE1] + b_CE1_HE1*sin(a_NE2_CE1_HE1);
1228     y[atHE1] = y[atCE1] - b_CE1_HE1*cos(a_NE2_CE1_HE1);
1229   }
1230   /* HD2 - first get (ccw) angle from (positive) y-axis */
1231   if(ats[atHD2]!=NOTSET) {  
1232     alpha = a_CE1_NE2_CD2 + M_PI - a_NE2_CD2_HD2;
1233     x[atHD2] = x[atCD2] - b_CD2_HD2*sin(alpha);
1234     y[atHD2] = y[atCD2] + b_CD2_HD2*cos(alpha);
1235   }
1236   if(ats[atHD1]!=NOTSET) {
1237     /* HD1 - first get (cw) angle from (positive) y-axis */
1238     alpha = a_ND1_CE1_NE2 + M_PI - a_CE1_ND1_HD1;
1239     x[atHD1] = x[atND1] - b_ND1_HD1*sin(alpha);
1240     y[atHD1] = y[atND1] - b_ND1_HD1*cos(alpha);
1241   }
1242   if(ats[atHE2]!=NOTSET) {
1243     x[atHE2] = x[atNE2] + b_NE2_HE2*sin(a_CE1_NE2_HE2);
1244     y[atHE2] = y[atNE2] + b_NE2_HE2*cos(a_CE1_NE2_HE2);
1245   }
1246   /* Have all coordinates now */
1247   
1248   /* calc center-of-mass; keep atoms CG, CE1, NE2 and
1249    * set the rest to vsite3
1250    */
1251   mtot=xcom=ycom=0;
1252   nvsite=0;
1253   for(i=0; i<atNR; i++) 
1254     if (ats[i]!=NOTSET) {
1255       mtot+=at->atom[ats[i]].m;
1256       xcom+=x[i]*at->atom[ats[i]].m;
1257       ycom+=y[i]*at->atom[ats[i]].m;
1258       if (i!=atCG && i!=atCE1 && i!=atNE2) {
1259         at->atom[ats[i]].m = at->atom[ats[i]].mB = 0;
1260         (*vsite_type)[ats[i]]=F_VSITE3;
1261         nvsite++;
1262       }
1263     } 
1264   if (nvsite+3 != nrfound)
1265     gmx_incons("Generating vsites for HIS");
1266
1267   xcom/=mtot;
1268   ycom/=mtot;
1269   
1270   /* distribute mass so that com stays the same */
1271   mG = xcom*mtot/x[atCG];
1272   mrest = mtot-mG;
1273   mCE1 = (ycom-y[atNE2])*mrest/(y[atCE1]-y[atNE2]);
1274   mNE2 = mrest-mCE1;
1275   
1276   at->atom[ats[atCG]].m = at->atom[ats[atCG]].mB = mG;
1277   at->atom[ats[atCE1]].m = at->atom[ats[atCE1]].mB = mCE1;
1278   at->atom[ats[atNE2]].m = at->atom[ats[atNE2]].mB = mNE2;
1279   
1280   /* HE1 */
1281   if (ats[atHE1]!=NOTSET) {
1282     calc_vsite3_param(x[atHE1],y[atHE1],x[atCE1],y[atCE1],x[atNE2],y[atNE2],
1283                       x[atCG],y[atCG],&a,&b);
1284     add_vsite3_param(&plist[F_VSITE3],
1285                    ats[atHE1],ats[atCE1],ats[atNE2],ats[atCG],a,b);
1286   }
1287   /* HE2 */
1288   if (ats[atHE2]!=NOTSET) {
1289     calc_vsite3_param(x[atHE2],y[atHE2],x[atNE2],y[atNE2],x[atCE1],y[atCE1],
1290                       x[atCG],y[atCG],&a,&b);
1291     add_vsite3_param(&plist[F_VSITE3],
1292                    ats[atHE2],ats[atNE2],ats[atCE1],ats[atCG],a,b);
1293   }
1294   
1295   /* ND1 */
1296   calc_vsite3_param(x[atND1],y[atND1],x[atNE2],y[atNE2],x[atCE1],y[atCE1],
1297                     x[atCG],y[atCG],&a,&b);
1298   add_vsite3_param(&plist[F_VSITE3],
1299                  ats[atND1],ats[atNE2],ats[atCE1],ats[atCG],a,b);
1300   
1301   /* CD2 */
1302   calc_vsite3_param(x[atCD2],y[atCD2],x[atCE1],y[atCE1],x[atNE2],y[atNE2],
1303                     x[atCG],y[atCG],&a,&b);
1304   add_vsite3_param(&plist[F_VSITE3],
1305                  ats[atCD2],ats[atCE1],ats[atNE2],ats[atCG],a,b);
1306   
1307   /* HD1 */
1308   if (ats[atHD1]!=NOTSET) {
1309     calc_vsite3_param(x[atHD1],y[atHD1],x[atNE2],y[atNE2],x[atCE1],y[atCE1],
1310                       x[atCG],y[atCG],&a,&b);
1311     add_vsite3_param(&plist[F_VSITE3],
1312                    ats[atHD1],ats[atNE2],ats[atCE1],ats[atCG],a,b);
1313   }
1314   /* HD2 */
1315   if (ats[atHD2]!=NOTSET) {
1316     calc_vsite3_param(x[atHD2],y[atHD2],x[atCE1],y[atCE1],x[atNE2],y[atNE2],
1317                       x[atCG],y[atCG],&a,&b);
1318     add_vsite3_param(&plist[F_VSITE3],
1319                    ats[atHD2],ats[atCE1],ats[atNE2],ats[atCG],a,b);
1320   }  
1321   return nvsite;
1322 }
1323
1324 static gmx_bool is_vsite(int vsite_type)
1325 {
1326   if (vsite_type == NOTSET)
1327     return FALSE;
1328   switch ( abs(vsite_type) ) {
1329   case F_VSITE3:
1330   case F_VSITE3FD:
1331   case F_VSITE3OUT:
1332   case F_VSITE3FAD:
1333   case F_VSITE4FD:
1334   case F_VSITE4FDN:
1335     return TRUE;
1336   default:
1337     return FALSE;
1338   }
1339 }
1340
1341 static char atomnamesuffix[] = "1234";
1342
1343 void do_vsites(int nrtp, t_restp rtp[], gpp_atomtype_t atype, 
1344                t_atoms *at, t_symtab *symtab, rvec *x[], 
1345                t_params plist[], int *vsite_type[], int *cgnr[], 
1346                real mHmult, gmx_bool bVsiteAromatics,
1347                const char *ffdir)
1348 {
1349 #define MAXATOMSPERRESIDUE 16
1350   int  i,j,k,m,i0,ni0,whatres,resind,add_shift,ftype,nvsite,nadd;
1351   int  ai,aj,ak,al;
1352   int  nrfound=0,needed,nrbonds,nrHatoms,Heavy,nrheavies,tpM,tpHeavy;
1353   int  Hatoms[4],heavies[4],bb;
1354   gmx_bool bWARNING,bAddVsiteParam,bFirstWater;
1355   matrix tmpmat;
1356   gmx_bool *bResProcessed;
1357   real mHtot,mtot,fact,fact2;
1358   rvec rpar,rperp,temp;
1359   char name[10],tpname[32],nexttpname[32],*ch;
1360   rvec *newx;
1361   int  *o2n,*newvsite_type,*newcgnr,ats[MAXATOMSPERRESIDUE];
1362   t_atom *newatom;
1363   t_params *params;
1364   char ***newatomname;
1365   char *resnm=NULL;
1366   int  ndb,f;
1367   char **db;
1368   int  nvsiteconf,nvsitetop,cmplength;
1369   gmx_bool isN,planarN,bFound;
1370   gmx_residuetype_t rt;
1371     
1372   t_vsiteconf *vsiteconflist; 
1373   /* pointer to a list of CH3/NH3/NH2 configuration entries.
1374    * See comments in read_vsite_database. It isnt beautiful,
1375    * but it had to be fixed, and I dont even want to try to 
1376    * maintain this part of the code...
1377    */
1378   t_vsitetop *vsitetop;       
1379   /* Pointer to a list of geometry (bond/angle) entries for
1380    * residues like PHE, TRP, TYR, HIS, etc., where we need
1381    * to know the geometry to construct vsite aromatics.
1382    * Note that equilibrium geometry isnt necessarily the same
1383    * as the individual bond and angle values given in the
1384    * force field (rings can be strained).
1385    */
1386
1387   /* if bVsiteAromatics=TRUE do_vsites will specifically convert atoms in 
1388      PHE, TRP, TYR and HIS to a construction of virtual sites */
1389   enum                    { resPHE, resTRP, resTYR, resHIS, resNR };
1390   const char *resnms[resNR]   = {   "PHE",  "TRP",  "TYR",  "HIS" };
1391         /* Amber03 alternative names for termini */
1392   const char *resnmsN[resNR]  = {  "NPHE", "NTRP", "NTYR", "NHIS" };
1393   const char *resnmsC[resNR]  = {  "CPHE", "CTRP", "CTYR", "CHIS" };
1394   /* HIS can be known as HISH, HIS1, HISA, HID, HIE, HIP, etc. too */
1395   gmx_bool bPartial[resNR]  = {  FALSE,  FALSE,  FALSE,   TRUE  };
1396   /* the atnms for every residue MUST correspond to the enums in the 
1397      gen_vsites_* (one for each residue) routines! */
1398   /* also the atom names in atnms MUST be in the same order as in the .rtp! */
1399   const char *atnms[resNR][MAXATOMSPERRESIDUE+1] = { 
1400     { "CG", /* PHE */
1401       "CD1", "HD1", "CD2", "HD2", 
1402       "CE1", "HE1", "CE2", "HE2", 
1403       "CZ", "HZ", NULL },
1404     { "CB", /* TRP */
1405       "CG",
1406       "CD1", "HD1", "CD2", 
1407       "NE1", "HE1", "CE2", "CE3", "HE3", 
1408       "CZ2", "HZ2", "CZ3", "HZ3", 
1409       "CH2", "HH2", NULL },
1410     { "CG", /* TYR */
1411       "CD1", "HD1", "CD2", "HD2", 
1412       "CE1", "HE1", "CE2", "HE2", 
1413       "CZ", "OH", "HH", NULL },
1414     { "CG", /* HIS */
1415       "ND1", "HD1", "CD2", "HD2",
1416       "CE1", "HE1", "NE2", "HE2", NULL }
1417   };
1418     
1419   if (debug) {
1420     printf("Searching for atoms to make virtual sites ...\n");
1421     fprintf(debug,"# # # VSITES # # #\n");
1422   }
1423
1424   ndb = fflib_search_file_end(ffdir,".vsd",FALSE,&db);
1425   nvsiteconf    = 0;
1426   vsiteconflist = NULL;
1427   nvsitetop     = 0;
1428   vsitetop      = NULL;
1429   for(f=0; f<ndb; f++) {
1430     read_vsite_database(db[f],&vsiteconflist,&nvsiteconf,&vsitetop,&nvsitetop);
1431     sfree(db[f]);
1432   }
1433   sfree(db);
1434   
1435   bFirstWater=TRUE;
1436   nvsite=0;
1437   nadd=0;
1438   /* we need a marker for which atoms should *not* be renumbered afterwards */
1439   add_shift = 10*at->nr;
1440   /* make arrays where masses can be inserted into */ 
1441   snew(newx,at->nr); 
1442   snew(newatom,at->nr);
1443   snew(newatomname,at->nr);
1444   snew(newvsite_type,at->nr);
1445   snew(newcgnr,at->nr);
1446   /* make index array to tell where the atoms go to when masses are inserted */
1447   snew(o2n,at->nr);
1448   for(i=0; i<at->nr; i++)
1449     o2n[i]=i;
1450   /* make index to tell which residues were already processed */
1451   snew(bResProcessed,at->nres);
1452     
1453   gmx_residuetype_init(&rt);
1454     
1455   /* generate vsite constructions */
1456   /* loop over all atoms */
1457   resind = -1;
1458   for(i=0; (i<at->nr); i++) {
1459     if (at->atom[i].resind != resind) {
1460       resind = at->atom[i].resind;
1461       resnm  = *(at->resinfo[resind].name);
1462     }
1463     /* first check for aromatics to virtualize */
1464     /* don't waste our effort on DNA, water etc. */
1465     /* Only do the vsite aromatic stuff when we reach the 
1466      * CA atom, since there might be an X2/X3 group on the
1467      * N-terminus that must be treated first.
1468      */
1469     if ( bVsiteAromatics &&
1470          !strcmp(*(at->atomname[i]),"CA") &&
1471          !bResProcessed[resind] &&
1472          gmx_residuetype_is_protein(rt,*(at->resinfo[resind].name)) ) {
1473       /* mark this residue */
1474       bResProcessed[resind] = TRUE;
1475       /* find out if this residue needs converting */
1476       whatres=NOTSET;
1477       for(j=0; j<resNR && whatres==NOTSET; j++) {
1478                   
1479         cmplength = bPartial[j] ? strlen(resnm)-1 : strlen(resnm);
1480         
1481         bFound = ((gmx_strncasecmp(resnm,resnms[j], cmplength)==0) ||
1482                   (gmx_strncasecmp(resnm,resnmsN[j],cmplength)==0) ||
1483                   (gmx_strncasecmp(resnm,resnmsC[j],cmplength)==0));
1484         
1485         if ( bFound ) {
1486           whatres=j;
1487           /* get atoms we will be needing for the conversion */
1488           nrfound=0;
1489           for (k=0; atnms[j][k]; k++) 
1490       {
1491             ats[k]=NOTSET;
1492           for(m=i; m<at->nr && at->atom[m].resind==resind && ats[k]==NOTSET;m++) 
1493         {
1494               if (gmx_strcasecmp(*(at->atomname[m]),atnms[j][k])==0) 
1495           {
1496               ats[k]=m;
1497               nrfound++;
1498               }
1499             }
1500           }
1501         
1502       /* now k is number of atom names in atnms[j] */
1503       if (j==resHIS)
1504       {
1505           needed = k-3;
1506       }
1507           else
1508           {
1509           needed = k;
1510       }
1511       if (nrfound<needed)
1512           {
1513           gmx_fatal(FARGS,"not enough atoms found (%d, need %d) in "
1514                     "residue %s %d while\n             "
1515                     "generating aromatics virtual site construction",
1516                     nrfound,needed,resnm,at->resinfo[resind].nr);
1517       }
1518       /* Advance overall atom counter */
1519       i++;
1520     }
1521       }
1522       /* the enums for every residue MUST correspond to atnms[residue] */
1523       switch (whatres) {
1524       case resPHE: 
1525         if (debug) fprintf(stderr,"PHE at %d\n",o2n[ats[0]]+1);
1526         nvsite+=gen_vsites_phe(at, vsite_type, plist, nrfound, ats, vsitetop, nvsitetop);
1527         break;
1528       case resTRP: 
1529         if (debug) fprintf(stderr,"TRP at %d\n",o2n[ats[0]]+1);
1530         nvsite+=gen_vsites_trp(atype, &newx, &newatom, &newatomname, &o2n, 
1531                            &newvsite_type, &newcgnr, symtab, &nadd, *x, cgnr,
1532                            at, vsite_type, plist, nrfound, ats, add_shift, vsitetop, nvsitetop);
1533         break;
1534       case resTYR: 
1535         if (debug) fprintf(stderr,"TYR at %d\n",o2n[ats[0]]+1);
1536         nvsite+=gen_vsites_tyr(atype, &newx, &newatom, &newatomname, &o2n, 
1537                            &newvsite_type, &newcgnr, symtab, &nadd, *x, cgnr,
1538                            at, vsite_type, plist, nrfound, ats, add_shift, vsitetop, nvsitetop);
1539         break;
1540       case resHIS: 
1541         if (debug) fprintf(stderr,"HIS at %d\n",o2n[ats[0]]+1);
1542         nvsite+=gen_vsites_his(at, vsite_type, plist, nrfound, ats, vsitetop, nvsitetop);
1543         break;
1544       case NOTSET:
1545         /* this means this residue won't be processed */
1546         break;
1547       default:
1548         gmx_fatal(FARGS,"DEATH HORROR in do_vsites (%s:%d)",
1549                     __FILE__,__LINE__);
1550       } /* switch whatres */
1551       /* skip back to beginning of residue */
1552       while(i>0 && at->atom[i-1].resind == resind)
1553         i--;
1554     } /* if bVsiteAromatics & is protein */
1555     
1556     /* now process the rest of the hydrogens */
1557     /* only process hydrogen atoms which are not already set */
1558     if ( ((*vsite_type)[i]==NOTSET) && is_hydrogen(*(at->atomname[i]))) {
1559       /* find heavy atom, count #bonds from it and #H atoms bound to it
1560          and return H atom numbers (Hatoms) and heavy atom numbers (heavies) */
1561       count_bonds(i, &plist[F_BONDS], at->atomname, 
1562                   &nrbonds, &nrHatoms, Hatoms, &Heavy, &nrheavies, heavies);
1563       /* get Heavy atom type */
1564       tpHeavy=get_atype(Heavy,at,nrtp,rtp,rt);
1565       strcpy(tpname,get_atomtype_name(tpHeavy,atype));
1566
1567       bWARNING=FALSE;
1568       bAddVsiteParam=TRUE;
1569       /* nested if's which check nrHatoms, nrbonds and atomname */
1570       if (nrHatoms == 1) {
1571         switch(nrbonds) {
1572         case 2: /* -O-H */
1573           (*vsite_type)[i]=F_BONDS;
1574           break;
1575         case 3: /* =CH-, -NH- or =NH+- */
1576           (*vsite_type)[i]=F_VSITE3FD;
1577           break;
1578         case 4: /* --CH- (tert) */
1579         /* The old type 4FD had stability issues, so 
1580          * all new constructs should use 4FDN
1581          */
1582           (*vsite_type)[i]=F_VSITE4FDN;
1583         
1584         /* Check parity of heavy atoms from coordinates */
1585         ai = Heavy;
1586         aj = heavies[0];
1587         ak = heavies[1];
1588         al = heavies[2];
1589         rvec_sub((*x)[aj],(*x)[ai],tmpmat[0]);
1590         rvec_sub((*x)[ak],(*x)[ai],tmpmat[1]);
1591         rvec_sub((*x)[al],(*x)[ai],tmpmat[2]);
1592         
1593         if(det(tmpmat)>0)
1594         {
1595             /* swap parity */
1596             heavies[1] = aj;
1597             heavies[0] = ak;
1598         }
1599         
1600           break;
1601         default: /* nrbonds != 2, 3 or 4 */
1602           bWARNING=TRUE;
1603         }
1604         
1605       } else if ( /*(nrHatoms == 2) && (nrbonds == 2) && REMOVED this test
1606                    DvdS 19-01-04 */
1607                   (gmx_strncasecmp(*at->atomname[Heavy],"OW",2)==0) ) {
1608         bAddVsiteParam=FALSE; /* this is water: skip these hydrogens */
1609         if (bFirstWater) {
1610           bFirstWater=FALSE;
1611           if (debug)
1612             fprintf(debug,
1613                     "Not converting hydrogens in water to virtual sites\n");
1614         }
1615       } else if ( (nrHatoms == 2) && (nrbonds == 4) ) {
1616         /* -CH2- , -NH2+- */
1617         (*vsite_type)[Hatoms[0]] = F_VSITE3OUT;
1618         (*vsite_type)[Hatoms[1]] =-F_VSITE3OUT;
1619       } else {
1620         /* 2 or 3 hydrogen atom, with 3 or 4 bonds in total to the heavy atom.
1621          * If it is a nitrogen, first check if it is planar.
1622          */
1623         isN=planarN=FALSE;
1624         if((nrHatoms == 2) && ((*at->atomname[Heavy])[0]=='N')) {
1625           isN=TRUE;
1626           j=nitrogen_is_planar(vsiteconflist,nvsiteconf,tpname);
1627           if(j<0) 
1628             gmx_fatal(FARGS,"No vsite database NH2 entry for type %s\n",tpname);
1629           planarN=(j==1);
1630         }
1631         if ( (nrHatoms == 2) && (nrbonds == 3) && ( !isN || planarN ) ) {
1632           /* =CH2 or, if it is a nitrogen NH2, it is a planar one */
1633           (*vsite_type)[Hatoms[0]] = F_VSITE3FAD;
1634           (*vsite_type)[Hatoms[1]] =-F_VSITE3FAD;
1635         } else if ( ( (nrHatoms == 2) && (nrbonds == 3) && 
1636                       ( isN && !planarN ) ) || 
1637                     ( (nrHatoms == 3) && (nrbonds == 4) ) ) {
1638           /* CH3, NH3 or non-planar NH2 group */
1639         int  Hat_vsite_type[3] = { F_VSITE3, F_VSITE3OUT, F_VSITE3OUT };
1640         gmx_bool Hat_SwapParity[3] = { FALSE,    TRUE,        FALSE };
1641         
1642         if (debug) fprintf(stderr,"-XH3 or nonplanar NH2 group at %d\n",i+1);
1643         bAddVsiteParam=FALSE; /* we'll do this ourselves! */
1644         /* -NH2 (umbrella), -NH3+ or -CH3 */
1645         (*vsite_type)[Heavy]       = F_VSITE3;
1646         for (j=0; j<nrHatoms; j++)
1647           (*vsite_type)[Hatoms[j]] = Hat_vsite_type[j];
1648         /* get dummy mass type from first char of heavy atom type (N or C) */
1649         
1650         strcpy(nexttpname,get_atomtype_name(get_atype(heavies[0],at,nrtp,rtp,rt),atype));
1651         ch=get_dummymass_name(vsiteconflist,nvsiteconf,tpname,nexttpname);
1652
1653         if (ch == NULL) {
1654           if (ndb > 0) {
1655             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);
1656           } else {
1657              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           }
1659         } else {
1660           strcpy(name,ch);
1661         }
1662
1663         tpM=vsite_nm2type(name,atype);
1664         /* make space for 2 masses: shift all atoms starting with 'Heavy' */
1665 #define NMASS 2
1666         i0=Heavy;
1667         ni0=i0+nadd;
1668         if (debug) 
1669           fprintf(stderr,"Inserting %d dummy masses at %d\n",NMASS,o2n[i0]+1);
1670         nadd+=NMASS;
1671         for(j=i0; j<at->nr; j++)
1672           o2n[j]=j+nadd; 
1673
1674         srenew(newx,at->nr+nadd);
1675         srenew(newatom,at->nr+nadd);
1676         srenew(newatomname,at->nr+nadd);
1677         srenew(newvsite_type,at->nr+nadd);
1678         srenew(newcgnr,at->nr+nadd);
1679
1680         for(j=0; j<NMASS; j++)
1681           newatomname[at->nr+nadd-1-j]=NULL;
1682
1683         /* calculate starting position for the masses */
1684         mHtot=0;
1685         /* get atom masses, and set Heavy and Hatoms mass to zero */
1686         for(j=0; j<nrHatoms; j++) {
1687           mHtot += get_amass(Hatoms[j],at,nrtp,rtp,rt);
1688           at->atom[Hatoms[j]].m = at->atom[Hatoms[j]].mB = 0;
1689         }
1690         mtot = mHtot + get_amass(Heavy,at,nrtp,rtp,rt);
1691         at->atom[Heavy].m = at->atom[Heavy].mB = 0;
1692         if (mHmult != 1.0)
1693           mHtot *= mHmult;
1694         fact2=mHtot/mtot;
1695         fact=sqrt(fact2);
1696         /* generate vectors parallel and perpendicular to rotational axis:
1697          * rpar  = Heavy -> Hcom
1698          * rperp = Hcom  -> H1   */
1699         clear_rvec(rpar);
1700         for(j=0; j<nrHatoms; j++)
1701           rvec_inc(rpar,(*x)[Hatoms[j]]);
1702         svmul(1.0/nrHatoms,rpar,rpar); /* rpar = ( H1+H2+H3 ) / 3 */
1703         rvec_dec(rpar,(*x)[Heavy]);    /*        - Heavy          */
1704         rvec_sub((*x)[Hatoms[0]],(*x)[Heavy],rperp);
1705         rvec_dec(rperp,rpar);          /* rperp = H1 - Heavy - rpar */
1706         /* calc mass positions */
1707         svmul(fact2,rpar,temp);
1708         for (j=0; (j<NMASS); j++) /* xM = xN + fact2 * rpar +/- fact * rperp */
1709           rvec_add((*x)[Heavy],temp,newx[ni0+j]);
1710         svmul(fact,rperp,temp);
1711         rvec_inc(newx[ni0  ],temp);
1712         rvec_dec(newx[ni0+1],temp);
1713         /* set atom parameters for the masses */
1714         for(j=0; (j<NMASS); j++) {
1715           /* make name: "M??#" or "M?#" (? is atomname, # is number) */
1716           name[0]='M';
1717           for(k=0; (*at->atomname[Heavy])[k] && ( k < NMASS ); k++ )
1718             name[k+1]=(*at->atomname[Heavy])[k];
1719           name[k+1]=atomnamesuffix[j];
1720           name[k+2]='\0';
1721           newatomname[ni0+j]   = put_symtab(symtab,name);
1722           newatom[ni0+j].m     = newatom[ni0+j].mB    = mtot/NMASS;
1723           newatom[ni0+j].q     = newatom[ni0+j].qB    = 0.0;
1724           newatom[ni0+j].type  = newatom[ni0+j].typeB = tpM;
1725           newatom[ni0+j].ptype = eptAtom;
1726           newatom[ni0+j].resind= at->atom[i0].resind;
1727           newvsite_type[ni0+j] = NOTSET;
1728           newcgnr[ni0+j]       = (*cgnr)[i0];
1729         }
1730         /* add constraints between dummy masses and to heavies[0] */
1731         /* 'add_shift' says which atoms won't be renumbered afterwards */
1732         my_add_param(&(plist[F_CONSTRNC]),heavies[0],  add_shift+ni0,  NOTSET);
1733         my_add_param(&(plist[F_CONSTRNC]),heavies[0],  add_shift+ni0+1,NOTSET);
1734         my_add_param(&(plist[F_CONSTRNC]),add_shift+ni0,add_shift+ni0+1,NOTSET);
1735         
1736         /* generate Heavy, H1, H2 and H3 from M1, M2 and heavies[0] */
1737         /* note that vsite_type cannot be NOTSET, because we just set it */
1738         add_vsite3_atoms  (&plist[(*vsite_type)[Heavy]],
1739                          Heavy,     heavies[0], add_shift+ni0, add_shift+ni0+1,
1740                          FALSE);
1741         for(j=0; j<nrHatoms; j++)
1742           add_vsite3_atoms(&plist[(*vsite_type)[Hatoms[j]]], 
1743                          Hatoms[j], heavies[0], add_shift+ni0, add_shift+ni0+1,
1744                          Hat_SwapParity[j]);
1745 #undef NMASS
1746         } else
1747           bWARNING=TRUE;
1748     
1749       }
1750       if (bWARNING)
1751         fprintf(stderr,
1752                 "Warning: cannot convert atom %d %s (bound to a heavy atom "
1753                 "%s with \n"
1754                 "         %d bonds and %d bound hydrogens atoms) to virtual site\n",
1755                 i+1,*(at->atomname[i]),tpname,nrbonds,nrHatoms);
1756       if (bAddVsiteParam) {
1757         /* add vsite parameters to topology, 
1758            also get rid of negative vsite_types */
1759         add_vsites(plist, (*vsite_type), Heavy, nrHatoms, Hatoms,
1760                    nrheavies, heavies);
1761         /* transfer mass of virtual site to Heavy atom */
1762         for(j=0; j<nrHatoms; j++) 
1763           if (is_vsite((*vsite_type)[Hatoms[j]])) {
1764             at->atom[Heavy].m += at->atom[Hatoms[j]].m;
1765             at->atom[Heavy].mB = at->atom[Heavy].m;
1766             at->atom[Hatoms[j]].m = at->atom[Hatoms[j]].mB = 0;
1767           }
1768       }
1769       nvsite+=nrHatoms;
1770       if (debug) {
1771         fprintf(debug,"atom %d: ",o2n[i]+1);
1772         print_bonds(debug,o2n,nrHatoms,Hatoms,Heavy,nrheavies,heavies);
1773       }
1774     } /* if vsite NOTSET & is hydrogen */
1775     
1776   } /* for i < at->nr */
1777
1778   gmx_residuetype_destroy(rt);
1779     
1780   if (debug) {
1781     fprintf(debug,"Before inserting new atoms:\n");
1782     for(i=0; i<at->nr; i++)
1783       fprintf(debug,"%4d %4d %4s %4d %4s %6d %-10s\n",i+1,o2n[i]+1,
1784               at->atomname[i]?*(at->atomname[i]):"(NULL)",
1785               at->resinfo[at->atom[i].resind].nr,
1786               at->resinfo[at->atom[i].resind].name ?
1787               *(at->resinfo[at->atom[i].resind].name):"(NULL)",
1788               (*cgnr)[i],
1789               ((*vsite_type)[i]==NOTSET) ? 
1790               "NOTSET" : interaction_function[(*vsite_type)[i]].name);
1791     fprintf(debug,"new atoms to be inserted:\n");
1792     for(i=0; i<at->nr+nadd; i++)
1793       if (newatomname[i])
1794         fprintf(debug,"%4d %4s %4d %6d %-10s\n",i+1,
1795                 newatomname[i]?*(newatomname[i]):"(NULL)",
1796                 newatom[i].resind,newcgnr[i],
1797                 (newvsite_type[i]==NOTSET) ? 
1798                 "NOTSET" : interaction_function[newvsite_type[i]].name);
1799   }
1800   
1801   /* add all original atoms to the new arrays, using o2n index array */
1802   for(i=0; i<at->nr; i++) {
1803     newatomname  [o2n[i]] = at->atomname [i];
1804     newatom      [o2n[i]] = at->atom     [i];
1805     newvsite_type[o2n[i]] = (*vsite_type)[i];
1806     newcgnr      [o2n[i]] = (*cgnr)      [i];
1807     copy_rvec((*x)[i],newx[o2n[i]]);
1808   }
1809   /* throw away old atoms */
1810   sfree(at->atom);
1811   sfree(at->atomname);
1812   sfree(*vsite_type);
1813   sfree(*cgnr);
1814   sfree(*x);
1815   /* put in the new ones */
1816   at->nr      += nadd;
1817   at->atom     = newatom;
1818   at->atomname = newatomname;
1819   *vsite_type  = newvsite_type;
1820   *cgnr        = newcgnr;
1821   *x           = newx;
1822   if (at->nr > add_shift)
1823     gmx_fatal(FARGS,"Added impossible amount of dummy masses "
1824                 "(%d on a total of %d atoms)\n",nadd,at->nr-nadd);
1825   
1826   if (debug) {
1827     fprintf(debug,"After inserting new atoms:\n");
1828     for(i=0; i<at->nr; i++)
1829       fprintf(debug,"%4d %4s %4d %4s %6d %-10s\n",i+1,
1830               at->atomname[i]?*(at->atomname[i]):"(NULL)",
1831               at->resinfo[at->atom[i].resind].nr, 
1832               at->resinfo[at->atom[i].resind].name ?
1833               *(at->resinfo[at->atom[i].resind].name):"(NULL)",
1834               (*cgnr)[i],
1835               ((*vsite_type)[i]==NOTSET) ? 
1836               "NOTSET" : interaction_function[(*vsite_type)[i]].name);
1837   }
1838   
1839   /* now renumber all the interactions because of the added atoms */
1840   for (ftype=0; ftype<F_NRE; ftype++) {
1841     params=&(plist[ftype]);
1842     if (debug)
1843       fprintf(debug,"Renumbering %d %s\n", params->nr,
1844               interaction_function[ftype].longname);
1845     for (i=0; i<params->nr; i++) {
1846       for (j=0; j<NRAL(ftype); j++)
1847         if (params->param[i].a[j]>=add_shift) {
1848           if (debug) fprintf(debug," [%u -> %u]",params->param[i].a[j],
1849                              params->param[i].a[j]-add_shift);
1850           params->param[i].a[j]=params->param[i].a[j]-add_shift;
1851         } else {
1852           if (debug) fprintf(debug," [%u -> %d]",params->param[i].a[j],
1853                              o2n[params->param[i].a[j]]);
1854           params->param[i].a[j]=o2n[params->param[i].a[j]];
1855         }
1856       if (debug) fprintf(debug,"\n");
1857     }
1858   }
1859   /* now check if atoms in the added constraints are in increasing order */
1860   params=&(plist[F_CONSTRNC]);
1861   for(i=0; i<params->nr; i++)
1862     if ( params->param[i].AI > params->param[i].AJ ) {
1863       j                   = params->param[i].AJ;
1864       params->param[i].AJ = params->param[i].AI;
1865       params->param[i].AI = j;
1866     }
1867   
1868   /* clean up */
1869   sfree(o2n);
1870   
1871   /* tell the user what we did */
1872   fprintf(stderr,"Marked %d virtual sites\n",nvsite);
1873   fprintf(stderr,"Added %d dummy masses\n",nadd);
1874   fprintf(stderr,"Added %d new constraints\n",plist[F_CONSTRNC].nr);
1875 }
1876   
1877 void do_h_mass(t_params *psb, int vsite_type[], t_atoms *at, real mHmult,
1878                gmx_bool bDeuterate)
1879 {
1880   int i,j,a;
1881   
1882   /* loop over all atoms */
1883   for (i=0; i<at->nr; i++)
1884     /* adjust masses if i is hydrogen and not a virtual site */
1885     if ( !is_vsite(vsite_type[i]) && is_hydrogen(*(at->atomname[i])) ) {
1886       /* find bonded heavy atom */
1887       a=NOTSET;
1888       for(j=0; (j<psb->nr) && (a==NOTSET); j++) {
1889         /* if other atom is not a virtual site, it is the one we want */
1890         if ( (psb->param[j].AI==i) && 
1891              !is_vsite(vsite_type[psb->param[j].AJ]) )
1892           a=psb->param[j].AJ;
1893         else if ( (psb->param[j].AJ==i) && 
1894                   !is_vsite(vsite_type[psb->param[j].AI]) )
1895           a=psb->param[j].AI;
1896       }
1897       if (a==NOTSET)
1898         gmx_fatal(FARGS,"Unbound hydrogen atom (%d) found while adjusting mass",
1899                     i+1);
1900       
1901       /* adjust mass of i (hydrogen) with mHmult
1902          and correct mass of a (bonded atom) with same amount */
1903       if (!bDeuterate) {
1904         at->atom[a].m -= (mHmult-1.0)*at->atom[i].m;
1905         at->atom[a].mB-= (mHmult-1.0)*at->atom[i].m;
1906       }
1907       at->atom[i].m *= mHmult;
1908       at->atom[i].mB*= mHmult;
1909     }
1910 }
1911