changed reading hint
[gromacs/adressmacs.git] / src / kernel / opls2rtp.c
blob344e3513f8ce53f16e14f0704198c0a4b60c4da4
1 /*
2 * $Id$
3 *
4 * This source code is part of
5 *
6 * G R O M A C S
7 *
8 * GROningen MAchine for Chemical Simulations
9 *
10 * VERSION 2.0
12 * Copyright (c) 1991-1999
13 * BIOSON Research Institute, Dept. of Biophysical Chemistry
14 * University of Groningen, The Netherlands
16 * Please refer to:
17 * GROMACS: A message-passing parallel molecular dynamics implementation
18 * H.J.C. Berendsen, D. van der Spoel and R. van Drunen
19 * Comp. Phys. Comm. 91, 43-56 (1995)
21 * Also check out our WWW page:
22 * http://md.chem.rug.nl/~gmx
23 * or e-mail to:
24 * gromacs@chem.rug.nl
26 * And Hey:
27 * GRowing Old MAkes el Chrono Sweat
29 static char *SRCID_opls2rtp_c = "$Id$";
31 /**********************************************************************
32 * Program: opls2rtp.c *
33 * Usage: opls2rtp *
34 * input files: opls-parameters -> a file with OPLS forcefield *
35 * parameters in the form: *
36 * TYPE ATOMNUMBER ATOMTYPE CHARGE SIGMA EPSILON COMMENT *
37 * No comments are allowed in the file. sigma and epsilon are in A and*
38 * kcal/mol. They will be converted to nm and kJ/mol *
39 * : opls.rtp -> a file with residue dbase *
40 * entries in gromacs format, except that the types have *
41 * been substituted by OPLS numbers, bonds, dihedrals, charges, and *
42 * chargegroups have been left out. (`hacked' rtp file) *
43 * *
44 * *
45 * output files: opls.atp with entries OPLSTYPE MASS ; COMMENT *
46 * opls-rtp.rtp the residue dbase file *
47 * opls-nb.itp the nonbonded interaction file *
48 * the file opls.hdb has to be modified outside this program, and *
49 * opls-bon.itp has to be created using the table opls2gromacs.tab *
50 * and a seperate Perl script. *
51 **********************************************************************
52 * author: Peter Tieleman. tieleman@chem.rug.nl September 1994 *
53 **********************************************************************/
54 #define ATP_FILE "opls.atp"
55 #define ITP_NB_FILE "opls-nb.itp"
56 #define OPLS_FILE "opls-parameters"
58 #include <string.h>
59 #include <stdio.h>
60 #include "symtab.h"
61 #include "string2.h"
62 #include "topio.h"
63 #include "smalloc.h" /* mem-allocation routines like snew */
64 #include "resall.h" /* routines for working with residue dbase files */
65 #include "copyrite.h" /* copyright message and such */
66 #include "futil.h" /* Gromacs file utils, ffopen and such */
67 #include <math.h> /* for fabs in the function modify_atoms */
68 #include <stdlib.h>
70 typedef struct { /* struct for atoms in residue dbase. Name, OPLS-code */
71 char *aname; /* the 'official name' of the atom */
72 int op_code; /* the OPLS-code (int between 1 and 300something) */
73 } t_opatom;
75 typedef struct { /* struct for one residue in residue dbase file */
76 char *resname; /* name of the residue (ex. ARG, ALA, LYS) */
77 int nat; /* number of atoms in residue */
78 t_opatom *op; /* array of atoms. op[i].op_code and op[i].aname */
79 } t_opres;
81 struct opls_entry {
82 int opls_nr; /* atom type. This is an atom number in the OPLS system */
83 int atom_number; /* atom number in periodic system of elements */
84 char opls_type[10]; /* type in OPLS system */
85 float opls_charge; /* charge in opls_system */
86 float opls_sigma; /* LJ-parameter sigma (in Angstrom) */
87 float opls_epsilon; /* LJ-parameter epsilon */
88 char *opls_comment; /* comment in opls-parameters file */
91 struct opls_entry_list{
92 struct opls_entry opls_data_entry;
93 struct opls_entry_list *next_entry_ptr;
96 struct opls_entry_list *first_entry_ptr = NULL;
97 /* pointer to first element of opls-data struct from input file */
99 /***********************************************************************
100 * read_opatoms: reads a hacked residue dbase file. *
101 * arguments: *fn: name of hacked residue dbase file to be read *
102 * **opa: array for residues (contains residues after the *
103 * function is done *
104 **********************************************************************/
105 int read_opatoms(char *fn,t_opres **opa)
107 FILE *in; /* input file */
108 char buf[STRLEN+1]; /* buffer for one line from the input file */
109 char resnm[20]; /* name of residue */
110 char anm[20]; /* 'official' atomname */
111 t_opres *opr; /* pointer to residue */
112 int nopa,nat,type; /* number of residues, number of atoms, OPLS-type */
113 int i,j; /* useless indices */
115 in=ffopen(fn,"r"); /* Gromacs version of ffopen. Performs some checks */
116 fgets2(buf,STRLEN,in); /* Gromacs version of fgets. Performs some checks */
117 sscanf(buf,"%d",&nopa); /* number of residues in hacked dbase file */
118 snew((*opa),nopa); /* allocate nopa * sizeof(*opa) using calloc */
119 for(i=0; (i<nopa); i++) { /* iterate over all residues */
120 opr=&((*opa)[i]); /* opr points to the i-th element of the res.array*/
121 fgets2(buf,STRLEN,in); /* get next line */
122 sscanf(buf,"%s",resnm); /* get name of residue */
123 opr->resname=strdup(resnm); /* put name of residue in residue structure */
124 fgets2(buf,STRLEN,in); /* get number of atoms */
125 sscanf(buf,"%d",&nat);
126 opr->nat=nat; /* put number of atoms in residue structure */
127 snew(opr->op,nat); /* allocate memory for all atoms */
128 for(j=0; (j<nat); j++) {
129 fgets2(buf,STRLEN,in); /* for each atom, read name and number */
130 sscanf(buf,"%s%d",anm,&type);
131 opr->op[j].aname=strdup(anm); /* put this data in residue structure */
132 opr->op[j].op_code=type;
136 fclose(in); /* close file */
138 return nopa; /* return number of residues read */
142 /*****************************************************************
143 * pr_atoms: Prints the array read in with read_opatoms *
144 ****************************************************************/
145 void pr_opatoms(FILE *out,int nopa,t_opres opa[])
147 int i,j;
149 fprintf(out,"%d\n",nopa);
150 for(i=0; (i<nopa); i++) {
151 fprintf(out,"%s\n%5d\n",opa[i].resname,opa[i].nat);
152 for(j=0; (j<opa[i].nat); j++)
153 fprintf(out,"%10s %5d\n",opa[i].op[j].aname,opa[i].op[j].op_code);
158 /*****************************************************************
159 * modify_atoms: modifies the atoms from the origal rtp file, *
160 * putting the modified residues in a new array with residues, *
161 * *opls_rtp. It returns this array *
162 ******************************************************************/
163 t_restp * modify_atoms(int nres,t_restp rtp[], int *nwnres)
165 int find_res_in_opls();
167 int nopres; /* number of residues in opls.rtp */
168 int i,j;
169 int opls_set = 0; /* if 1, don't put residue in the new array with mod. res*/
170 t_opres *opa; /* array with opls residues */
171 float nwcharge; /* OPLS-charge */
172 float total_charge; /* total charge for chargegroup. Must add up to -1,0,1 */
173 int charge_group; /* the new chargegroup for an atom */
174 int nwtype; /* OPLS type */
175 int status; /* 1: res,atom found, 0: res,atom not found */
176 t_restp *opls_rtp; /* array with the new opls-residues */
178 snew(opls_rtp,nres); /* allocate memory for opls-rtp.rtp */
179 nopres=read_opatoms("opls.rtp",&opa);
180 for(i=0;i<nres;i++){ /* loop over all residues */
181 total_charge = 0;
182 charge_group = 0;
183 opls_set = 0;
185 for(j=0;j<rtp[i].natom;j++){ /* loop over all atoms in residue */
186 status = find_res_in_opls(rtp[i].resname,
187 *(rtp[i].atomname[j]),
188 &nwcharge,&nwtype,opa,nopres);
189 if(status){
190 rtp[i].atom[j].type = nwtype-1; /* assign atom OPLS type */
191 rtp[i].atom[j].q = nwcharge;/* assign atom OPLS charge */
192 rtp[i].cgnr[j] = charge_group; /*charge_group;*/
193 total_charge = total_charge + nwcharge;
194 if((fabs(total_charge - 0) < 1E-5)
195 || (fabs(total_charge - 1) < 1E-5)
196 || (fabs(total_charge + 1) < 1E-5)){
197 charge_group++; total_charge = 0;
199 if(!opls_set) { /* add residue to the new array with mod. residues */
200 opls_rtp[i] = rtp[i];
201 opls_set = 1; /* only add a residue once, not once for each atom */
203 } /* endif status */
206 *nwnres = nres;
207 pr_opatoms(stdout,nopres,opa);
208 return opls_rtp;
211 /*****************************************************************
212 * find_res_in_opls: Searches for 'atom_name' in residue *
213 * 'residue_name' in the hacked rtp file (*opa). If it finds it, *
214 * it changes the type and charge to the opls values and return1 *
215 ******************************************************************/
216 int find_res_in_opls(char *residue_name,
217 char *atom_name,
218 float *charge,
219 int *nwtype,
220 t_opres opa[],
221 int numres){
223 int i = 0; int j = 0;
224 float find_opls_charge();
225 /* fprintf(stdout,"looking for %s and %s\n",residue_name,atom_name); */
226 while(i<numres){
227 if (!strcmp(opa[i].resname,residue_name)) {
228 fprintf(stdout,"found residue %s and atom %s in opls file\n",opa[i].resname,atom_name);
229 for(j=0;j<opa[i].nat;j++){
230 if(strcmp(opa[i].op[j].aname,atom_name)==0){
231 *nwtype = opa[i].op[j].op_code;
232 *charge = find_opls_charge(opa[i].op[j].op_code);
233 return 1;
237 i++;
239 printf("Couldn't find residue %s\n",residue_name);
240 return 0;
243 /*****************************************************************
244 * find_opls_charge: given a opls_code, get the corresponding *
245 * charge. This information is available in the linked list of *
246 * entries from the opls-parameters file *
247 ******************************************************************/
248 float find_opls_charge(int opls_code){
249 struct opls_entry_list *search_entry_ptr;
250 struct opls_entry entry_to_search;
252 search_entry_ptr = first_entry_ptr;
253 while(search_entry_ptr != NULL){
254 entry_to_search = search_entry_ptr->opls_data_entry;
255 if(opls_code == entry_to_search.opls_nr){
256 return entry_to_search.opls_charge;
258 search_entry_ptr = search_entry_ptr->next_entry_ptr;
260 fprintf(stderr,"Error: could not find opls-charge. Send hatemail to spoel@chem.rug.nl\n");
261 return 10; /* nice high charge, will draw attention when looked at */
264 /*****************************************************************
265 * read_opls_file: Read the file opls-parameters and build a list*
266 * of the entries in that file. *
267 ******************************************************************/
268 void read_opls_file(){
269 FILE *input_file;
270 char line[100];
271 char *eof_ptr;
272 char *comment_ptr;
273 int offset = 43; /* comments start at 43 */
274 struct opls_entry opls_line;
275 struct opls_entry_list *new_entry_ptr = NULL;
276 struct opls_entry_list *previous_entry_ptr = NULL;
277 int scan_count,i;
279 input_file = fopen(OPLS_FILE, "r");
280 while(1){
281 eof_ptr = fgets2(line, sizeof(line), input_file);
282 if(eof_ptr == NULL) break;
283 scan_count = sscanf(line,"%d %d %s %f %f %f", &opls_line.opls_nr, \
284 &opls_line.atom_number, opls_line.opls_type, \
285 &opls_line.opls_charge, &opls_line.opls_sigma, \
286 &opls_line.opls_epsilon);
287 comment_ptr = line + offset;
288 opls_line.opls_comment = strdup(comment_ptr);
289 for(i=0;i<80;i++)line[i]=' ';
290 new_entry_ptr = (struct opls_entry_list *)malloc(sizeof(struct opls_entry_list));
291 new_entry_ptr->opls_data_entry = opls_line;
292 if (first_entry_ptr == NULL) {
293 first_entry_ptr = new_entry_ptr;
294 previous_entry_ptr = first_entry_ptr;
296 previous_entry_ptr->next_entry_ptr = new_entry_ptr;
297 previous_entry_ptr = new_entry_ptr;
301 /*****************************************************************
302 * print_opls_file: Print out the list of entries from the opls- *
303 * parameter file as read in by read_opls_file *
304 *****************************************************************/
305 void print_opls_file(){
306 struct opls_entry_list *print_entry_ptr;
307 struct opls_entry entry_to_print;
308 print_entry_ptr = first_entry_ptr;
309 while(print_entry_ptr != NULL){
310 entry_to_print = print_entry_ptr->opls_data_entry;
311 printf("type: %d number: %d\n", entry_to_print.opls_nr
312 , entry_to_print.atom_number);
313 print_entry_ptr = print_entry_ptr->next_entry_ptr;
317 /*****************************************************************
318 * write_atom_type_file: make the files opls.atp and opls-nb.itp *
319 * and write them to disk. *
320 *****************************************************************/
321 void write_atomtype_file(int nr_atom){
322 struct opls_entry_list *print_entry_ptr;
323 struct opls_entry entry_to_print;
324 FILE *output_file; /* the atomic type file */
325 FILE *nb_itp_file; /* the nonbonded interaction file */
326 int nr=0;
327 float sigma; /* sigma in nm, calculated from opls_sigma in angstrom */
328 float epsilon; /* epsilon in kJ/mol, from opls_epsilon in kCal/mol */
330 float atomic_weights[] = {0, 1.00800, 4.0260, 6.941, 9.01218, 10.81,
331 12.011, 14.0067, 15.9994, 18.998403, 20.179, 22.98977, 24.305,
332 26.98154, 28.0855, 30.97376, 32.06, 35.453, 39.948, 39.0983,
333 40.08, 44.9559, 47.88, 50.9415, 51.996, 54.9380, 55.847, 58.9332,
334 58.69, 63.546, 65.38, 69.72, 72.59, 74.9216, 78.96, 79.904, 83.80,
335 85.4678, 87.62, 88.9059, 91.22, 92.9064, 95.94, 98, 101.07, 102.9055,
336 106.42, 107.8682, 112.41, 114.82, 118.69, 121.75, 127.60, 126.9045, 131.29,
337 132.9054,137.33};
339 output_file = fopen(ATP_FILE,"w");
340 nb_itp_file = fopen(ITP_NB_FILE,"w");
342 print_entry_ptr = first_entry_ptr;
344 fprintf(nb_itp_file,"[ atomtypes ]\n");
345 fprintf(nb_itp_file,";type\tmass\t\tcharge\t\tsigma(nm)\tepsilon(kj/mol)\tcomment\n");
346 fprintf(output_file,"%d ;Type\tMass\tComment\n",nr_atom);
348 while(print_entry_ptr != NULL){
349 entry_to_print = print_entry_ptr->opls_data_entry;
350 nr = entry_to_print.atom_number;
351 if((nr<1) || (nr>56)){
352 fprintf(stdout,"Error: atomic number too high: %d. Skipping entry\n",nr);
353 } else {
354 fprintf(output_file,"OP%d\t %f\t; %s\n", entry_to_print.opls_nr
355 , atomic_weights[entry_to_print.atom_number], entry_to_print.opls_comment);
356 sigma = entry_to_print.opls_sigma / 10;
357 epsilon = entry_to_print.opls_epsilon * 4.1868;
358 fprintf(nb_itp_file,"OP%d\t%f\t%f\t%f\t%f ;%s\n",entry_to_print.opls_nr,
359 atomic_weights[entry_to_print.atom_number],
360 entry_to_print.opls_charge,sigma,epsilon,entry_to_print.opls_comment);
363 print_entry_ptr = print_entry_ptr->next_entry_ptr;
365 fclose(nb_itp_file);
366 fclose(output_file);
369 /*****************************************************************
370 * main *
371 *****************************************************************/
372 int main(int argc,char *argv[])
374 int nres;
375 t_restp *rtp;
376 t_resbond *rb;
377 t_resang *ra;
378 t_idihres *ires;
379 t_atomtype *atype,*atype_opls;
380 t_symtab tab;
381 char *ff="rt37AM";
382 int nr_atoms; /* number of atoms in the atp-file */
383 t_restp *opls_rtp; /* the new array with opls-residues */
384 int nwnres; /* number of residues in array with opls-residues */
385 FILE *aa;
387 aa = ffopen("opls-rtp.rtp","w");
388 CopyRight(stdout,argv[0]);
389 open_symtab(&tab);
390 atype=read_atype(ff,&tab);
391 atype_opls=read_atype("opls",&tab); /* get opls.atp for print_resall */
392 nr_atoms = atype_opls->nr;
393 nres=read_resall(ff,&rtp,&rb,&ra,&ires,atype,&tab);
394 read_opls_file();
395 #ifdef DEBUG
396 print_opls_file();
397 #endif
398 write_atomtype_file(nr_atoms);
399 opls_rtp = modify_atoms(nres,rtp, &nwnres);
400 printf("Number of residues in new rtp file: %d",nwnres);
401 print_resall(aa,nwnres,opls_rtp,rb,ra,ires,atype_opls);
402 fclose(aa);
403 thanx(stdout);
405 printf("hallo! Don't Panic!\n");
407 return 0;