2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5 * Copyright (c) 2001-2004, The GROMACS development team,
6 * check out http://www.gromacs.org for more information.
7 * Copyright (c) 2012, by the GROMACS development team, led by
8 * David van der Spoel, Berk Hess, Erik Lindahl, and including many
9 * others, as listed in the AUTHORS file in the top-level source
10 * directory and at http://www.gromacs.org.
12 * GROMACS is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public License
14 * as published by the Free Software Foundation; either version 2.1
15 * of the License, or (at your option) any later version.
17 * GROMACS is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with GROMACS; if not, see
24 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
25 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 * If you want to redistribute modifications to GROMACS, please
28 * consider that scientific software is very special. Version
29 * control is crucial - bugs must be traceable. We will be happy to
30 * consider code for inclusion in the official distribution, but
31 * derived work must not be called official GROMACS. Details are found
32 * in the README & COPYING files - if they are missing, get the
33 * official version at http://www.gromacs.org.
35 * To help us fund GROMACS development, we humbly ask that you cite
36 * the research papers on the package. Check out http://www.gromacs.org.
48 #include "gmx_fatal.h"
67 typedef struct gmx_atomprop {
69 aprop_t prop[epropNR];
70 gmx_residuetype_t restype;
75 /* NOTFOUND should be smallest, others larger in increasing priority */
76 enum { NOTFOUND=-4, WILDCARD, WILDPROT, PROTEIN };
78 /* return number of matching characters,
79 or NOTFOUND if not at least all characters in char *database match */
80 static int dbcmp_len(char *search, char *database)
85 while(search[i] && database[i] && (search[i]==database[i]) )
93 static int get_prop_index(aprop_t *ap,gmx_residuetype_t restype,
94 char *resnm,char *atomnm,
100 gmx_bool bProtein,bProtWild;
102 bProtein = gmx_residuetype_is_protein(restype,resnm);
103 bProtWild = (strcmp(resnm,"AAA")==0);
106 for(i=0; (i<ap->nprop); i++) {
107 rlen = dbcmp_len(resnm, ap->resnm[i]);
108 if (rlen == NOTFOUND) {
109 if ( (strcmp(ap->resnm[i],"*")==0) ||
110 (strcmp(ap->resnm[i],"???")==0) )
112 else if (strcmp(ap->resnm[i],"AAA")==0)
115 alen = dbcmp_len(atomnm, ap->atomnm[i]);
116 if ( (alen > NOTFOUND) && (rlen > NOTFOUND)) {
117 if ( ( (alen > malen) && (rlen >= mrlen)) ||
118 ( (rlen > mrlen) && (alen >= malen) ) ) {
126 *bExact = ((malen == (long int)strlen(atomnm)) &&
127 ((mrlen == (long int)strlen(resnm)) ||
128 ((mrlen == WILDPROT) && bProtWild) ||
129 ((mrlen == WILDCARD) && !bProtein && !bProtWild)));
132 fprintf(debug,"searching residue: %4s atom: %4s\n",resnm,atomnm);
134 fprintf(debug," not successful\n");
136 fprintf(debug," match: %4s %4s\n",ap->resnm[j],ap->atomnm[j]);
141 static void add_prop(aprop_t *ap,gmx_residuetype_t restype,
142 char *resnm,char *atomnm,
148 j = get_prop_index(ap,restype,resnm,atomnm,&bExact);
151 if (ap->nprop >= ap->maxprop) {
153 srenew(ap->resnm,ap->maxprop);
154 srenew(ap->atomnm,ap->maxprop);
155 srenew(ap->value,ap->maxprop);
156 srenew(ap->bAvail,ap->maxprop);
157 for(i=ap->nprop; (i<ap->maxprop); i++) {
158 ap->atomnm[i] = NULL;
161 ap->bAvail[i] = FALSE;
166 ap->atomnm[ap->nprop] = strdup(atomnm);
167 ap->resnm[ap->nprop] = strdup(resnm);
172 if (ap->value[j] == p)
173 fprintf(stderr,"Warning double identical entries for %s %s %g on line %d in file %s\n",
174 resnm,atomnm,p,line,ap->db);
176 fprintf(stderr,"Warning double different entries %s %s %g and %g on line %d in file %s\n"
177 "Using last entry (%g)\n",
178 resnm,atomnm,p,ap->value[j],line,ap->db,p);
183 ap->bAvail[j] = TRUE;
188 static void read_prop(gmx_atomprop_t aps,int eprop,double factor)
190 gmx_atomprop *ap2 = (gmx_atomprop*) aps;
192 char line[STRLEN],resnm[32],atomnm[32];
197 ap = &ap2->prop[eprop];
199 fp = libopen(ap->db);
201 while(get_a_line(fp,line,STRLEN)) {
203 if (sscanf(line,"%s %s %lf",resnm,atomnm,&pp) == 3) {
205 add_prop(ap,aps->restype,resnm,atomnm,pp,line_no);
208 fprintf(stderr,"WARNING: Error in file %s at line %d ignored\n",
212 /* for libraries we can use the low-level close routines */
218 static void set_prop(gmx_atomprop_t aps,int eprop)
220 gmx_atomprop *ap2 = (gmx_atomprop*) aps;
221 const char *fns[epropNR] = { "atommass.dat", "vdwradii.dat", "dgsolv.dat", "electroneg.dat", "elements.dat" };
222 double fac[epropNR] = { 1.0, 1.0, 418.4, 1.0, 1.0 };
223 double def[epropNR] = { 12.011, 0.14, 0.0, 2.2, -1 };
226 ap = &ap2->prop[eprop];
228 ap->db = strdup(fns[eprop]);
229 ap->def = def[eprop];
230 read_prop(aps,eprop,fac[eprop]);
233 fprintf(debug,"Entries in %s: %d\n",ap->db,ap->nprop);
235 if ( ( (!aps->bWarned) && (eprop == epropMass) ) || (eprop == epropVDW)) {
237 "WARNING: Masses and atomic (Van der Waals) radii will be guessed\n"
238 " based on residue and atom names, since they could not be\n"
239 " definitively assigned from the information in your input\n"
240 " files. These guessed numbers might deviate from the mass\n"
241 " and radius of the atom type. Please check the output\n"
242 " files if necessary.\n\n");
248 gmx_atomprop_t gmx_atomprop_init(void)
255 gmx_residuetype_init(&aps->restype);
256 aps->bWarned = FALSE;
258 return (gmx_atomprop_t)aps;
261 static void destroy_prop(aprop_t *ap)
268 for(i=0; i<ap->nprop; i++) {
269 sfree(ap->atomnm[i]);
279 void gmx_atomprop_destroy(gmx_atomprop_t aps)
281 gmx_atomprop *ap = (gmx_atomprop*) aps;
285 printf("\nWARNING: gmx_atomprop_destroy called with a NULL pointer\n\n");
289 for(p=0; p<epropNR; p++) {
290 destroy_prop(&ap->prop[p]);
293 gmx_residuetype_destroy(ap->restype);
298 gmx_bool gmx_atomprop_query(gmx_atomprop_t aps,
299 int eprop,const char *resnm,const char *atomnm,
302 gmx_atomprop *ap = (gmx_atomprop*) aps;
306 char atomname[MAXQ],resname[MAXQ];
310 if ((strlen(atomnm) > MAXQ-1) || (strlen(resnm) > MAXQ-1)) {
312 fprintf(debug,"WARNING: will only compare first %d characters\n",
315 if (isdigit(atomnm[0])) {
316 /* put digit after atomname */
317 for (i=1; (i<min(MAXQ-1,strlen(atomnm))); i++)
318 atomname[i-1] = atomnm[i];
319 atomname[i-1] = atomnm[0];
323 strncpy(atomname,atomnm,MAXQ-1);
326 strncpy(resname,resnm,MAXQ-1);
329 j = get_prop_index(&(ap->prop[eprop]),ap->restype,resname,
333 *value = ap->prop[eprop].value[j];
337 *value = ap->prop[eprop].def;
342 char *gmx_atomprop_element(gmx_atomprop_t aps,int atomnumber)
344 gmx_atomprop *ap = (gmx_atomprop*) aps;
347 set_prop(aps,epropElement);
348 for(i=0; (i<ap->prop[epropElement].nprop); i++) {
349 if (gmx_nint(ap->prop[epropElement].value[i]) == atomnumber) {
350 return ap->prop[epropElement].atomnm[i];
356 int gmx_atomprop_atomnumber(gmx_atomprop_t aps,const char *elem)
358 gmx_atomprop *ap = (gmx_atomprop*) aps;
361 set_prop(aps,epropElement);
362 for(i=0; (i<ap->prop[epropElement].nprop); i++) {
363 if (gmx_strcasecmp(ap->prop[epropElement].atomnm[i],elem) == 0) {
364 return gmx_nint(ap->prop[epropElement].value[i]);