Merge branch 'master' of git://git.gromacs.org/gromacs
[gromacs/adressmacs.git] / src / kernel / g_x2top.c
blobd02d5cd54ca7c72ded4dac904be1118d87de8b17
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.3.3
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-2008, The GROMACS development team,
13 * check out http://www.gromacs.org for more information.
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * If you want to redistribute modifications, please consider that
21 * scientific software is very special. Version control is crucial -
22 * bugs must be traceable. We will be happy to consider code for
23 * inclusion in the official distribution, but derived work must not
24 * be called official GROMACS. Details are found in the README & COPYING
25 * files - if they are missing, get the official version at www.gromacs.org.
27 * To help us fund GROMACS development, we humbly ask that you cite
28 * the papers on the package - you can find them in the top README file.
30 * For more info, check our website at http://www.gromacs.org
32 * And Hey:
33 * Groningen Machine for Chemical Simulation
35 #ifdef HAVE_CONFIG_H
36 #include <config.h>
37 #endif
39 #include "maths.h"
40 #include "macros.h"
41 #include "copyrite.h"
42 #include "bondf.h"
43 #include "gmxfio.h"
44 #include "string2.h"
45 #include "smalloc.h"
46 #include "strdb.h"
47 #include "sysstuff.h"
48 #include "confio.h"
49 #include "physics.h"
50 #include "statutil.h"
51 #include "vec.h"
52 #include "random.h"
53 #include "3dview.h"
54 #include "txtdump.h"
55 #include "readinp.h"
56 #include "names.h"
57 #include "toppush.h"
58 #include "pdb2top.h"
59 #include "gen_ad.h"
60 #include "gpp_nextnb.h"
61 #include "vec.h"
62 #include "g_x2top.h"
63 #include "atomprop.h"
65 char atp[7] = "HCNOSX";
66 #define NATP (asize(atp)-1)
68 real blen[NATP][NATP] = {
69 { 0.00, 0.108, 0.105, 0.10, 0.10, 0.10 },
70 { 0.108, 0.15, 0.14, 0.14, 0.16, 0.14 },
71 { 0.105, 0.14, 0.14, 0.14, 0.16, 0.14 },
72 { 0.10, 0.14, 0.14, 0.14, 0.17, 0.14 },
73 { 0.10, 0.16, 0.16, 0.17, 0.20, 0.17 },
74 { 0.10, 0.14, 0.14, 0.14, 0.17, 0.17 }
77 #define MARGIN_FAC 1.1
79 static real set_x_blen(real scale)
81 real maxlen;
82 int i,j;
84 for(i=0; i<NATP-1; i++) {
85 blen[NATP-1][i] *= scale;
86 blen[i][NATP-1] *= scale;
88 blen[NATP-1][NATP-1] *= scale;
90 maxlen = 0;
91 for(i=0; i<NATP; i++)
92 for(j=0; j<NATP; j++)
93 if (blen[i][j] > maxlen)
94 maxlen = blen[i][j];
96 return maxlen*MARGIN_FAC;
99 static gmx_bool is_bond(int nnm,t_nm2type nmt[],char *ai,char *aj,real blen)
101 int i,j;
103 for(i=0; (i<nnm); i++) {
104 for(j=0; (j<nmt[i].nbonds); j++) {
105 if ((((gmx_strncasecmp(ai,nmt[i].elem,1) == 0) &&
106 (gmx_strncasecmp(aj,nmt[i].bond[j],1) == 0)) ||
107 ((gmx_strncasecmp(ai,nmt[i].bond[j],1) == 0) &&
108 (gmx_strncasecmp(aj,nmt[i].elem,1) == 0))) &&
109 (fabs(blen-nmt[i].blen[j]) <= 0.1*nmt[i].blen[j]))
110 return TRUE;
113 return FALSE;
116 static int get_atype(char *nm)
118 int i,aai=NATP-1;
120 for(i=0; (i<NATP-1); i++) {
121 if (nm[0] == atp[i]) {
122 aai=i;
123 break;
126 return aai;
129 void mk_bonds(int nnm,t_nm2type nmt[],
130 t_atoms *atoms,rvec x[],t_params *bond,int nbond[],char *ff,
131 gmx_bool bPBC,matrix box,gmx_atomprop_t aps)
133 t_param b;
134 int i,j;
135 t_pbc pbc;
136 rvec dx;
137 real dx2;
139 for(i=0; (i<MAXATOMLIST); i++)
140 b.a[i] = -1;
141 for(i=0; (i<MAXFORCEPARAM); i++)
142 b.c[i] = 0.0;
144 if (bPBC)
145 set_pbc(&pbc,-1,box);
146 for(i=0; (i<atoms->nr); i++) {
147 if ((i % 10) == 0)
148 fprintf(stderr,"\ratom %d",i);
149 for(j=i+1; (j<atoms->nr); j++) {
150 if (bPBC)
151 pbc_dx(&pbc,x[i],x[j],dx);
152 else
153 rvec_sub(x[i],x[j],dx);
155 dx2 = iprod(dx,dx);
156 if (is_bond(nnm,nmt,*atoms->atomname[i],*atoms->atomname[j],
157 sqrt(dx2))) {
158 b.AI = i;
159 b.AJ = j;
160 b.C0 = sqrt(dx2);
161 add_param_to_list (bond,&b);
162 nbond[i]++;
163 nbond[j]++;
164 if (debug)
165 fprintf(debug,"Bonding atoms %s-%d and %s-%d\n",
166 *atoms->atomname[i],i+1,*atoms->atomname[j],j+1);
170 fprintf(stderr,"\ratom %d\n",i);
173 int *set_cgnr(t_atoms *atoms,gmx_bool bUsePDBcharge,real *qtot,real *mtot)
175 int i,n=1;
176 int *cgnr;
177 double qt=0,mt=0;
179 *qtot = *mtot = 0;
180 snew(cgnr,atoms->nr);
181 for(i=0; (i<atoms->nr); i++) {
182 if (atoms->pdbinfo && bUsePDBcharge)
183 atoms->atom[i].q = atoms->pdbinfo[i].bfac;
184 qt += atoms->atom[i].q;
185 *qtot += atoms->atom[i].q;
186 *mtot += atoms->atom[i].m;
187 cgnr[i] = n;
188 if (is_int(qt)) {
189 n++;
190 qt=0;
193 return cgnr;
196 gpp_atomtype_t set_atom_type(t_symtab *tab,t_atoms *atoms,t_params *bonds,
197 int *nbonds,int nnm,t_nm2type nm2t[])
199 gpp_atomtype_t atype;
200 int nresolved;
202 atype = init_atomtype();
203 snew(atoms->atomtype,atoms->nr);
204 nresolved = nm2type(nnm,nm2t,tab,atoms,atype,nbonds,bonds);
205 if (nresolved != atoms->nr)
206 gmx_fatal(FARGS,"Could only find a forcefield type for %d out of %d atoms",
207 nresolved,atoms->nr);
209 fprintf(stderr,"There are %d different atom types in your sample\n",
210 get_atomtype_ntypes(atype));
212 return atype;
215 void lo_set_force_const(t_params *plist,real c[],int nrfp,gmx_bool bRound,
216 gmx_bool bDih,gmx_bool bParam)
218 int i,j;
219 double cc;
220 char buf[32];
222 for(i=0; (i<plist->nr); i++) {
223 if (!bParam)
224 for(j=0; j<nrfp; j++)
225 c[j] = NOTSET;
226 else {
227 if (bRound) {
228 sprintf(buf,"%.2e",plist->param[i].c[0]);
229 sscanf(buf,"%lf",&cc);
230 c[0] = cc;
232 else
233 c[0] = plist->param[i].c[0];
234 if (bDih) {
235 c[0] *= c[2];
236 c[0] = ((int)(c[0] + 3600)) % 360;
237 if (c[0] > 180)
238 c[0] -= 360;
239 /* To put the minimum at the current angle rather than the maximum */
240 c[0] += 180;
243 for(j=0; (j<nrfp); j++) {
244 plist->param[i].c[j] = c[j];
245 plist->param[i].c[nrfp+j] = c[j];
247 set_p_string(&(plist->param[i]),"");
251 void set_force_const(t_params plist[],real kb,real kt,real kp,gmx_bool bRound,
252 gmx_bool bParam)
254 int i;
255 real c[MAXFORCEPARAM];
257 c[0] = 0;
258 c[1] = kb;
259 lo_set_force_const(&plist[F_BONDS],c,2,bRound,FALSE,bParam);
260 c[1] = kt;
261 lo_set_force_const(&plist[F_ANGLES],c,2,bRound,FALSE,bParam);
262 c[1] = kp;
263 c[2] = 3;
264 lo_set_force_const(&plist[F_PDIHS],c,3,bRound,TRUE,bParam);
267 void calc_angles_dihs(t_params *ang,t_params *dih,rvec x[],gmx_bool bPBC,
268 matrix box)
270 int i,ai,aj,ak,al,t1,t2,t3;
271 rvec r_ij,r_kj,r_kl,m,n;
272 real sign,th,costh,ph;
273 t_pbc pbc;
275 if (bPBC)
276 set_pbc(&pbc,epbcXYZ,box);
277 if (debug)
278 pr_rvecs(debug,0,"X2TOP",box,DIM);
279 for(i=0; (i<ang->nr); i++) {
280 ai = ang->param[i].AI;
281 aj = ang->param[i].AJ;
282 ak = ang->param[i].AK;
283 th = RAD2DEG*bond_angle(x[ai],x[aj],x[ak],bPBC ? &pbc : NULL,
284 r_ij,r_kj,&costh,&t1,&t2);
285 if (debug)
286 fprintf(debug,"X2TOP: ai=%3d aj=%3d ak=%3d r_ij=%8.3f r_kj=%8.3f th=%8.3f\n",
287 ai,aj,ak,norm(r_ij),norm(r_kj),th);
288 ang->param[i].C0 = th;
290 for(i=0; (i<dih->nr); i++) {
291 ai = dih->param[i].AI;
292 aj = dih->param[i].AJ;
293 ak = dih->param[i].AK;
294 al = dih->param[i].AL;
295 ph = RAD2DEG*dih_angle(x[ai],x[aj],x[ak],x[al],bPBC ? & pbc : NULL,
296 r_ij,r_kj,r_kl,m,n,&sign,&t1,&t2,&t3);
297 if (debug)
298 fprintf(debug,"X2TOP: ai=%3d aj=%3d ak=%3d al=%3d r_ij=%8.3f r_kj=%8.3f r_kl=%8.3f ph=%8.3f\n",
299 ai,aj,ak,al,norm(r_ij),norm(r_kj),norm(r_kl),ph);
300 dih->param[i].C0 = ph;
304 static void dump_hybridization(FILE *fp,t_atoms *atoms,int nbonds[])
306 int i;
308 for(i=0; (i<atoms->nr); i++) {
309 fprintf(fp,"Atom %5s has %1d bonds\n",*atoms->atomname[i],nbonds[i]);
313 static void print_pl(FILE *fp,t_params plist[],int ftp,const char *name,
314 char ***atomname)
316 int i,j,nral,nrfp;
318 if (plist[ftp].nr > 0) {
319 fprintf(fp,"\n");
320 fprintf(fp,"[ %s ]\n",name);
321 nral = interaction_function[ftp].nratoms;
322 nrfp = interaction_function[ftp].nrfpA;
323 for(i=0; (i<plist[ftp].nr); i++) {
324 for(j=0; (j<nral); j++)
325 fprintf(fp," %5s",*atomname[plist[ftp].param[i].a[j]]);
326 for(j=0; (j<nrfp); j++) {
327 if (plist[ftp].param[i].c[j] != NOTSET)
328 fprintf(fp," %10.3e",plist[ftp].param[i].c[j]);
330 fprintf(fp,"\n");
335 static void print_rtp(const char *filenm,const char *title,t_atoms *atoms,
336 t_params plist[],gpp_atomtype_t atype,int cgnr[],
337 int nbts,int bts[])
339 FILE *fp;
340 int i,tp;
341 char *tpnm;
343 fp = gmx_fio_fopen(filenm,"w");
344 fprintf(fp,"; %s\n",title);
345 fprintf(fp,"\n");
346 fprintf(fp,"[ %s ]\n",*atoms->resinfo[0].name);
347 fprintf(fp,"\n");
348 fprintf(fp,"[ atoms ]\n");
349 for(i=0; (i<atoms->nr); i++) {
350 tp = atoms->atom[i].type;
351 if ((tpnm = get_atomtype_name(tp,atype)) == NULL)
352 gmx_fatal(FARGS,"tp = %d, i = %d in print_rtp",tp,i);
353 fprintf(fp,"%-8s %12s %8.4f %5d\n",
354 *atoms->atomname[i],tpnm,
355 atoms->atom[i].q,cgnr[i]);
357 print_pl(fp,plist,F_BONDS,"bonds",atoms->atomname);
358 print_pl(fp,plist,F_ANGLES,"angles",atoms->atomname);
359 print_pl(fp,plist,F_PDIHS,"dihedrals",atoms->atomname);
360 print_pl(fp,plist,F_IDIHS,"impropers",atoms->atomname);
362 gmx_fio_fclose(fp);
365 int main(int argc, char *argv[])
367 const char *desc[] = {
368 "x2top generates a primitive topology from a coordinate file.",
369 "The program assumes all hydrogens are present when defining",
370 "the hybridization from the atom name and the number of bonds.",
371 "The program can also make an rtp entry, which you can then add",
372 "to the rtp database.[PAR]",
373 "When [TT]-param[tt] is set, equilibrium distances and angles",
374 "and force constants will be printed in the topology for all",
375 "interactions. The equilibrium distances and angles are taken",
376 "from the input coordinates, the force constant are set with",
377 "command line options.",
378 "The force fields somewhat supported currently are:[PAR]",
379 "G53a5 GROMOS96 53a5 Forcefield (official distribution)[PAR]",
380 "oplsaa OPLS-AA/L all-atom force field (2001 aminoacid dihedrals)[PAR]",
381 "The corresponding data files can be found in the library directory",
382 "with name atomname2type.n2t. Check chapter 5 of the manual for more",
383 "information about file formats. By default the forcefield selection",
384 "is interactive, but you can use the [TT]-ff[tt] option to specify",
385 "one of the short names above on the command line instead. In that",
386 "case pdb2gmx just looks for the corresponding file.[PAR]",
388 const char *bugs[] = {
389 "The atom type selection is primitive. Virtually no chemical knowledge is used",
390 "Periodic boundary conditions screw up the bonding",
391 "No improper dihedrals are generated",
392 "The atoms to atomtype translation table is incomplete (atomname2type.n2t files in the data directory). Please extend it and send the results back to the GROMACS crew."
394 FILE *fp;
395 t_params plist[F_NRE];
396 t_excls *excls;
397 t_atoms *atoms; /* list with all atoms */
398 gpp_atomtype_t atype;
399 t_nextnb nnb;
400 t_nm2type *nm2t;
401 t_mols mymol;
402 gmx_atomprop_t aps;
403 int nnm;
404 char title[STRLEN],forcefield[32],ffdir[STRLEN];
405 rvec *x; /* coordinates? */
406 int *nbonds,*cgnr;
407 int bts[] = { 1,1,1,2 };
408 matrix box; /* box length matrix */
409 int natoms; /* number of atoms in one molecule */
410 int nres; /* number of molecules? */
411 int i,j,k,l,m,ndih;
412 int epbc;
413 gmx_bool bRTP,bTOP,bOPLS;
414 t_symtab symtab;
415 real cutoff,qtot,mtot;
416 char n2t[STRLEN];
417 output_env_t oenv;
419 t_filenm fnm[] = {
420 { efSTX, "-f", "conf", ffREAD },
421 { efTOP, "-o", "out", ffOPTWR },
422 { efRTP, "-r", "out", ffOPTWR }
424 #define NFILE asize(fnm)
425 static real scale = 1.1, kb = 4e5,kt = 400,kp = 5;
426 static int nexcl = 3;
427 static gmx_bool bRemoveDih = FALSE;
428 static gmx_bool bParam = TRUE, bH14 = TRUE,bAllDih = FALSE,bRound = TRUE;
429 static gmx_bool bPairs = TRUE, bPBC = TRUE;
430 static gmx_bool bUsePDBcharge = FALSE,bVerbose=FALSE;
431 static const char *molnm = "ICE";
432 static const char *ff = "oplsaa";
433 t_pargs pa[] = {
434 { "-ff", FALSE, etSTR, {&ff},
435 "Force field for your simulation. Type \"select\" for interactive selection." },
436 { "-v", FALSE, etBOOL, {&bVerbose},
437 "Generate verbose output in the top file." },
438 { "-nexcl", FALSE, etINT, {&nexcl},
439 "Number of exclusions" },
440 { "-H14", FALSE, etBOOL, {&bH14},
441 "Use 3rd neighbour interactions for hydrogen atoms" },
442 { "-alldih", FALSE, etBOOL, {&bAllDih},
443 "Generate all proper dihedrals" },
444 { "-remdih", FALSE, etBOOL, {&bRemoveDih},
445 "Remove dihedrals on the same bond as an improper" },
446 { "-pairs", FALSE, etBOOL, {&bPairs},
447 "Output 1-4 interactions (pairs) in topology file" },
448 { "-name", FALSE, etSTR, {&molnm},
449 "Name of your molecule" },
450 { "-pbc", FALSE, etBOOL, {&bPBC},
451 "Use periodic boundary conditions." },
452 { "-pdbq", FALSE, etBOOL, {&bUsePDBcharge},
453 "Use the B-factor supplied in a pdb file for the atomic charges" },
454 { "-param", FALSE, etBOOL, {&bParam},
455 "Print parameters in the output" },
456 { "-round", FALSE, etBOOL, {&bRound},
457 "Round off measured values" },
458 { "-kb", FALSE, etREAL, {&kb},
459 "Bonded force constant (kJ/mol/nm^2)" },
460 { "-kt", FALSE, etREAL, {&kt},
461 "Angle force constant (kJ/mol/rad^2)" },
462 { "-kp", FALSE, etREAL, {&kp},
463 "Dihedral angle force constant (kJ/mol/rad^2)" }
466 CopyRight(stdout,argv[0]);
468 parse_common_args(&argc,argv,0,NFILE,fnm,asize(pa),pa,
469 asize(desc),desc,asize(bugs),bugs,&oenv);
470 bRTP = opt2bSet("-r",NFILE,fnm);
471 bTOP = opt2bSet("-o",NFILE,fnm);
473 if (!bRTP && !bTOP)
474 gmx_fatal(FARGS,"Specify at least one output file");
476 aps = gmx_atomprop_init();
478 /* Force field selection, interactive or direct */
479 choose_ff(strcmp(ff,"select") == 0 ? NULL : ff,
480 forcefield,sizeof(forcefield),
481 ffdir,sizeof(ffdir));
483 bOPLS = (strcmp(forcefield,"oplsaa") == 0);
486 mymol.name = strdup(molnm);
487 mymol.nr = 1;
489 /* Init parameter lists */
490 init_plist(plist);
492 /* Read coordinates */
493 get_stx_coordnum(opt2fn("-f",NFILE,fnm),&natoms);
494 snew(atoms,1);
496 /* make space for all the atoms */
497 init_t_atoms(atoms,natoms,TRUE);
498 snew(x,natoms);
500 read_stx_conf(opt2fn("-f",NFILE,fnm),title,atoms,x,NULL,&epbc,box);
502 sprintf(n2t,"%s",ffdir);
503 nm2t = rd_nm2type(n2t,&nnm);
504 if (nnm == 0)
505 gmx_fatal(FARGS,"No or incorrect atomname2type.n2t file found (looking for %s)",
506 n2t);
507 else
508 printf("There are %d name to type translations in file %s\n",nnm,n2t);
509 if (debug)
510 dump_nm2type(debug,nnm,nm2t);
511 printf("Generating bonds from distances...\n");
512 snew(nbonds,atoms->nr);
513 mk_bonds(nnm,nm2t,atoms,x,&(plist[F_BONDS]),nbonds,forcefield,
514 bPBC,box,aps);
516 open_symtab(&symtab);
517 atype = set_atom_type(&symtab,atoms,&(plist[F_BONDS]),nbonds,nnm,nm2t);
519 /* Make Angles and Dihedrals */
520 snew(excls,atoms->nr);
521 printf("Generating angles and dihedrals from bonds...\n");
522 init_nnb(&nnb,atoms->nr,4);
523 gen_nnb(&nnb,plist);
524 print_nnb(&nnb,"NNB");
525 gen_pad(&nnb,atoms,bH14,nexcl,plist,excls,NULL,bAllDih,bRemoveDih,TRUE);
526 done_nnb(&nnb);
528 if (!bPairs)
529 plist[F_LJ14].nr = 0;
530 fprintf(stderr,
531 "There are %4d %s dihedrals, %4d impropers, %4d angles\n"
532 " %4d pairs, %4d bonds and %4d atoms\n",
533 plist[F_PDIHS].nr,
534 bOPLS ? "Ryckaert-Bellemans" : "proper",
535 plist[F_IDIHS].nr, plist[F_ANGLES].nr,
536 plist[F_LJ14].nr, plist[F_BONDS].nr,atoms->nr);
538 calc_angles_dihs(&plist[F_ANGLES],&plist[F_PDIHS],x,bPBC,box);
540 set_force_const(plist,kb,kt,kp,bRound,bParam);
542 cgnr = set_cgnr(atoms,bUsePDBcharge,&qtot,&mtot);
543 printf("Total charge is %g, total mass is %g\n",qtot,mtot);
544 if (bOPLS) {
545 bts[2] = 3;
546 bts[3] = 1;
549 if (bTOP) {
550 fp = ftp2FILE(efTOP,NFILE,fnm,"w");
551 print_top_header(fp,ftp2fn(efTOP,NFILE,fnm),
552 "Generated by x2top",TRUE,ffdir,1.0);
554 write_top(fp,NULL,mymol.name,atoms,FALSE,bts,plist,excls,atype,
555 cgnr,nexcl);
556 print_top_mols(fp,mymol.name,ffdir,NULL,0,NULL,1,&mymol);
558 ffclose(fp);
560 if (bRTP)
561 print_rtp(ftp2fn(efRTP,NFILE,fnm),"Generated by x2top",
562 atoms,plist,atype,cgnr,asize(bts),bts);
564 if (debug) {
565 dump_hybridization(debug,atoms,nbonds);
567 close_symtab(&symtab);
569 printf("\nWARNING: topologies generated by %s can not be trusted at face value.\n",Program());
570 printf(" Please verify atomtypes and charges by comparison to other\n");
571 printf(" topologies.\n");
573 thanx(stderr);
575 return 0;