OpenMM: added combination rule check, disabled restraint check for now as it's buggy
[gromacs/qmmm-gamess-us.git] / src / kernel / x2top.c
blob36f79464e75807f51a6b7be0b1b9acb89b0030c1
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 "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 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 ((((strncasecmp(ai,nmt[i].elem,1) == 0) &&
106 (strncasecmp(aj,nmt[i].bond[j],1) == 0)) ||
107 ((strncasecmp(ai,nmt[i].bond[j],1) == 0) &&
108 (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 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,epbcXYZ,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,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,bool bRound,
216 bool bDih,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,bool bRound,
252 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[],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 supported currently are:[PAR]",
379 "G43a1 GROMOS96 43a1 Forcefield (official distribution)[PAR]",
380 "oplsaa OPLS-AA/L all-atom force field (2001 aminoacid dihedrals)[PAR]",
381 "G43b1 GROMOS96 43b1 Vacuum Forcefield (official distribution)[PAR]",
382 "gmx Gromacs Forcefield (a modified GROMOS87, see manual)[PAR]",
383 "G43a2 GROMOS96 43a2 Forcefield (development) (improved alkane dihedrals)[PAR]",
384 "The corresponding data files can be found in the library directory",
385 "with names like ffXXXX.YYY. Check chapter 5 of the manual for more",
386 "information about file formats. By default the forcefield selection",
387 "is interactive, but you can use the [TT]-ff[tt] option to specify",
388 "one of the short names above on the command line instead. In that",
389 "case pdb2gmx just looks for the corresponding file.[PAR]",
391 const char *bugs[] = {
392 "The atom type selection is primitive. Virtually no chemical knowledge is used",
393 "Periodic boundary conditions screw up the bonding",
394 "No improper dihedrals are generated",
395 "The atoms to atomtype translation table is incomplete (ffG43a1.n2t file in the $GMXLIB directory). Please extend it and send the results back to the GROMACS crew."
397 FILE *fp;
398 t_params plist[F_NRE];
399 t_excls *excls;
400 t_atoms *atoms; /* list with all atoms */
401 gpp_atomtype_t atype;
402 t_nextnb nnb;
403 t_nm2type *nm2t;
404 t_mols mymol;
405 gmx_atomprop_t aps;
406 int nnm;
407 char title[STRLEN],forcefield[32],ffdir[STRLEN];
408 rvec *x; /* coordinates? */
409 int *nbonds,*cgnr;
410 int bts[] = { 1,1,1,2 };
411 matrix box; /* box length matrix */
412 int natoms; /* number of atoms in one molecule */
413 int nres; /* number of molecules? */
414 int i,j,k,l,m,ndih;
415 int epbc;
416 bool bRTP,bTOP,bOPLS;
417 t_symtab symtab;
418 real cutoff,qtot,mtot;
419 output_env_t oenv;
421 t_filenm fnm[] = {
422 { efSTX, "-f", "conf", ffREAD },
423 { efTOP, "-o", "out", ffOPTWR },
424 { efRTP, "-r", "out", ffOPTWR }
426 #define NFILE asize(fnm)
427 static real scale = 1.1, kb = 4e5,kt = 400,kp = 5;
428 static int nexcl = 3;
429 static bool bRemoveDih = FALSE;
430 static bool bParam = TRUE, bH14 = TRUE,bAllDih = FALSE,bRound = TRUE;
431 static bool bPairs = TRUE, bPBC = TRUE;
432 static bool bUsePDBcharge = FALSE,bVerbose=FALSE;
433 static const char *molnm = "ICE";
434 static const char *ff = "oplsaa";
435 t_pargs pa[] = {
436 { "-ff", FALSE, etSTR, {&ff},
437 "Force field for your simulation. Type \"select\" for interactive selcection." },
438 { "-v", FALSE, etBOOL, {&bVerbose},
439 "Generate verbose output in the top file." },
440 { "-nexcl", FALSE, etINT, {&nexcl},
441 "Number of exclusions" },
442 { "-H14", FALSE, etBOOL, {&bH14},
443 "Use 3rd neighbour interactions for hydrogen atoms" },
444 { "-alldih", FALSE, etBOOL, {&bAllDih},
445 "Generate all proper dihedrals" },
446 { "-remdih", FALSE, etBOOL, {&bRemoveDih},
447 "Remove dihedrals on the same bond as an improper" },
448 { "-pairs", FALSE, etBOOL, {&bPairs},
449 "Output 1-4 interactions (pairs) in topology file" },
450 { "-name", FALSE, etSTR, {&molnm},
451 "Name of your molecule" },
452 { "-pbc", FALSE, etBOOL, {&bPBC},
453 "Use periodic boundary conditions." },
454 { "-pdbq", FALSE, etBOOL, {&bUsePDBcharge},
455 "Use the B-factor supplied in a pdb file for the atomic charges" },
456 { "-param", FALSE, etBOOL, {&bParam},
457 "Print parameters in the output" },
458 { "-round", FALSE, etBOOL, {&bRound},
459 "Round off measured values" },
460 { "-kb", FALSE, etREAL, {&kb},
461 "Bonded force constant (kJ/mol/nm^2)" },
462 { "-kt", FALSE, etREAL, {&kt},
463 "Angle force constant (kJ/mol/rad^2)" },
464 { "-kp", FALSE, etREAL, {&kp},
465 "Dihedral angle force constant (kJ/mol/rad^2)" }
468 CopyRight(stdout,argv[0]);
470 parse_common_args(&argc,argv,0,NFILE,fnm,asize(pa),pa,
471 asize(desc),desc,asize(bugs),bugs,&oenv);
472 bRTP = opt2bSet("-r",NFILE,fnm);
473 bTOP = opt2bSet("-o",NFILE,fnm);
475 if (!bRTP && !bTOP)
476 gmx_fatal(FARGS,"Specify at least one output file");
478 aps = gmx_atomprop_init();
480 /* Force field selection, interactive or direct */
481 choose_ff(strcmp(ff,"select") == 0 ? NULL : ff,
482 forcefield,sizeof(forcefield),
483 ffdir,sizeof(ffdir));
485 bOPLS = (strcmp(forcefield,"ffoplsaa") == 0);
488 mymol.name = strdup(molnm);
489 mymol.nr = 1;
491 /* Init parameter lists */
492 init_plist(plist);
494 /* Read coordinates */
495 get_stx_coordnum(opt2fn("-f",NFILE,fnm),&natoms);
496 snew(atoms,1);
498 /* make space for all the atoms */
499 init_t_atoms(atoms,natoms,TRUE);
500 snew(x,natoms);
502 read_stx_conf(opt2fn("-f",NFILE,fnm),title,atoms,x,NULL,&epbc,box);
504 nm2t = rd_nm2type(ffdir,&nnm);
505 printf("There are %d name to type translations\n",nnm);
506 if (debug)
507 dump_nm2type(debug,nnm,nm2t);
509 printf("Generating bonds from distances...\n");
510 snew(nbonds,atoms->nr);
511 mk_bonds(nnm,nm2t,atoms,x,&(plist[F_BONDS]),nbonds,forcefield,
512 bPBC,box,aps);
514 open_symtab(&symtab);
515 atype = set_atom_type(&symtab,atoms,&(plist[F_BONDS]),nbonds,nnm,nm2t);
517 /* Make Angles and Dihedrals */
518 snew(excls,atoms->nr);
519 printf("Generating angles and dihedrals from bonds...\n");
520 init_nnb(&nnb,atoms->nr,4);
521 gen_nnb(&nnb,plist);
522 print_nnb(&nnb,"NNB");
523 gen_pad(&nnb,atoms,bH14,nexcl,plist,excls,NULL,bAllDih,bRemoveDih,TRUE);
524 done_nnb(&nnb);
526 if (!bPairs)
527 plist[F_LJ14].nr = 0;
528 fprintf(stderr,
529 "There are %4d %s dihedrals, %4d impropers, %4d angles\n"
530 " %4d pairs, %4d bonds and %4d atoms\n",
531 plist[F_PDIHS].nr,
532 bOPLS ? "Ryckaert-Bellemans" : "proper",
533 plist[F_IDIHS].nr, plist[F_ANGLES].nr,
534 plist[F_LJ14].nr, plist[F_BONDS].nr,atoms->nr);
536 calc_angles_dihs(&plist[F_ANGLES],&plist[F_PDIHS],x,bPBC,box);
538 set_force_const(plist,kb,kt,kp,bRound,bParam);
540 cgnr = set_cgnr(atoms,bUsePDBcharge,&qtot,&mtot);
541 printf("Total charge is %g, total mass is %g\n",qtot,mtot);
542 if (bOPLS) {
543 bts[2] = 3;
544 bts[3] = 1;
547 if (bTOP) {
548 fp = ftp2FILE(efTOP,NFILE,fnm,"w");
549 print_top_header(fp,ftp2fn(efTOP,NFILE,fnm),
550 "Generated by x2top",TRUE,ffdir,1.0);
552 write_top(fp,NULL,mymol.name,atoms,FALSE,bts,plist,excls,atype,
553 cgnr,nexcl);
554 print_top_mols(fp,mymol.name,ffdir,NULL,0,NULL,1,&mymol);
556 ffclose(fp);
558 if (bRTP)
559 print_rtp(ftp2fn(efRTP,NFILE,fnm),"Generated by x2top",
560 atoms,plist,atype,cgnr,asize(bts),bts);
562 if (debug) {
563 dump_hybridization(debug,atoms,nbonds);
565 close_symtab(&symtab);
567 printf("\nWARNING: topologies generated by %s can not be trusted at face value.\n",Program());
568 printf(" Please verify atomtypes and charges by comparison to other\n");
569 printf(" topologies.\n");
571 thanx(stderr);
573 return 0;