Merge release-4-6 into master
[alexxy/gromacs.git] / src / gromacs / gmxpreprocess / h_db.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 /* This file is completely threadsafe - keep it that way! */
36 #ifdef HAVE_CONFIG_H
37 #include <config.h>
38 #endif
39
40 #include <string.h>
41 #include "string2.h"
42 #include "sysstuff.h"
43 #include "smalloc.h"
44 #include "futil.h"
45 #include "symtab.h"
46 #include "h_db.h"
47 #include "gmxfio.h"
48 #include "fflibutil.h"
49 #include "gmx_fatal.h"
50 #include "macros.h"
51
52 /* There are 11 types of adding hydrogens, numbered from
53  * 1 thru 11. Each of these has a specific number of
54  * control atoms, that determine how the hydrogens are added.
55  * Here these number are given. Because arrays start at 0 an
56  * extra dummy for index 0 is added 
57  */
58 const int ncontrol[] = { -1, 3, 3, 3, 3, 4, 3, 1, 3, 3, 1, 1 };
59 #define maxcontrol asize(ncontrol)
60
61 int compaddh(const void *a,const void *b)
62 {
63   t_hackblock *ah,*bh;
64
65   ah=(t_hackblock *)a;
66   bh=(t_hackblock *)b;
67   return gmx_strcasecmp(ah->name,bh->name);
68 }
69
70 void print_ab(FILE *out,t_hack *hack,char *nname)
71 {
72   int i;
73
74   fprintf(out,"%d\t%d\t%s",hack->nr,hack->tp,nname);
75   for(i=0; (i < hack->nctl); i++)
76     fprintf(out,"\t%s",hack->a[i]);
77   fprintf(out,"\n");
78 }
79
80
81 void read_ab(char *line,const char *fn,t_hack *hack)
82 {
83   int  i,nh,tp,ns;
84   char a[4][12];
85   char hn[32];
86   
87   ns = sscanf(line,"%d%d%s%s%s%s%s",&nh,&tp,hn,a[0],a[1],a[2],a[3]);
88   if (ns < 4)
89     gmx_fatal(FARGS,"wrong format in input file %s on line\n%s\n",fn,line);
90   
91   hack->nr=nh;
92   hack->tp=tp;
93   if ((tp < 1) || (tp >= maxcontrol)) 
94     gmx_fatal(FARGS,"Error in hdb file %s:\nH-type should be in 1-%d. Offending line:\n%s",fn,maxcontrol-1,line);
95   
96   hack->nctl = ns - 3;
97   if ((hack->nctl != ncontrol[hack->tp]) && (ncontrol[hack->tp] != -1))
98     gmx_fatal(FARGS,"Error in hdb file %s:\nWrong number of control atoms (%d iso %d) on line:\n%s\n",fn,hack->nctl,ncontrol[hack->tp],line);
99   for(i=0; (i<hack->nctl); i++) {
100     hack->a[i]=strdup(a[i]);
101   }
102   for(   ; i<4; i++) {
103     hack->a[i]=NULL;
104   }
105   hack->oname=NULL;
106   hack->nname=strdup(hn);
107   hack->atom=NULL;
108   hack->cgnr=NOTSET;
109   hack->bXSet=FALSE;
110   for(i=0; i<DIM; i++)
111     hack->newx[i]=NOTSET;
112 }
113
114 static void read_h_db_file(const char *hfn,int *nahptr,t_hackblock **ah)
115 {       
116   FILE   *in;
117   char   filebase[STRLEN],line[STRLEN], buf[STRLEN];
118   int    i, n, nab, nah;
119   t_hackblock *aah;
120
121   if (debug) fprintf(debug,"Hydrogen Database (%s):\n",hfn);
122
123   fflib_filename_base(hfn,filebase,STRLEN);
124   /* Currently filebase is read and set, but not used.
125    * hdb entries from any hdb file and be applied to rtp entries
126    * in any rtp file.
127    */
128
129   in = fflib_open(hfn);
130
131   nah = *nahptr;
132   aah = *ah;
133   while (fgets2(line,STRLEN-1,in)) {
134     if (sscanf(line,"%s%n",buf,&n) != 1) {
135       fprintf(stderr,"Error in hdb file: nah = %d\nline = '%s'\n",
136               nah,line);
137       break;
138     }
139     if (debug) fprintf(debug,"%s",buf);
140     srenew(aah,nah+1);
141     clear_t_hackblock(&aah[nah]);
142     aah[nah].name     = strdup(buf);
143     aah[nah].filebase = strdup(filebase);
144     
145     if (sscanf(line+n,"%d",&nab) == 1) {
146       if (debug) fprintf(debug,"  %d\n",nab);
147       snew(aah[nah].hack,nab);
148       aah[nah].nhack = nab;
149       for(i=0; (i<nab); i++) {
150         if (feof(in))
151           gmx_fatal(FARGS, "Expected %d lines of hydrogens, found only %d "
152                       "while reading Hydrogen Database %s residue %s",
153                       nab, i-1, aah[nah].name, hfn);
154         if(NULL==fgets(buf, STRLEN, in))
155         {
156           gmx_fatal(FARGS,"Error reading from file %s",hfn);
157         }
158         read_ab(buf,hfn,&(aah[nah].hack[i]));
159       }
160     }
161     nah++;
162   }
163   ffclose(in);
164   
165   /* Sort the list (necessary to be able to use bsearch */
166   qsort(aah,nah,(size_t)sizeof(**ah),compaddh);
167
168   /*
169   if (debug)
170     dump_h_db(hfn,nah,aah);
171   */
172   
173   *nahptr = nah;
174   *ah     = aah;
175 }
176
177 int read_h_db(const char *ffdir,t_hackblock **ah)
178 {
179   int  nhdbf,f;
180   char **hdbf;
181   int  nah;
182   FILE *fp;
183
184   /* Read the hydrogen database file(s).
185    * Do not generate an error when no files are found.
186    */
187   nhdbf = fflib_search_file_end(ffdir,".hdb",FALSE,&hdbf);
188   nah = 0;
189   *ah = NULL;
190   for(f=0; f<nhdbf; f++) {
191     read_h_db_file(hdbf[f],&nah,ah);
192     sfree(hdbf[f]);
193   }
194   sfree(hdbf);
195
196   return nah;
197 }
198
199 t_hackblock *search_h_db(int nh,t_hackblock ah[],char *key)
200 {
201   t_hackblock ahkey,*result;
202
203   if (nh <= 0)
204     return NULL;
205   
206   ahkey.name=key;
207
208   result=(t_hackblock *)bsearch(&ahkey,ah,nh,(size_t)sizeof(ah[0]),compaddh);
209   
210   return result;
211 }