3 * This source code is part of
7 * GROningen MAchine for Chemical Simulations
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
33 * Groningen Machine for Chemical Simulation
60 #include "gpp_nextnb.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
)
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
;
93 if (blen
[i
][j
] > maxlen
)
96 return maxlen
*MARGIN_FAC
;
99 static gmx_bool
is_bond(int nnm
,t_nm2type nmt
[],char *ai
,char *aj
,real blen
)
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
]))
116 static int get_atype(char *nm
)
120 for(i
=0; (i
<NATP
-1); i
++) {
121 if (nm
[0] == atp
[i
]) {
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
)
139 for(i
=0; (i
<MAXATOMLIST
); i
++)
141 for(i
=0; (i
<MAXFORCEPARAM
); i
++)
145 set_pbc(&pbc
,-1,box
);
146 for(i
=0; (i
<atoms
->nr
); i
++) {
148 fprintf(stderr
,"\ratom %d",i
);
149 for(j
=i
+1; (j
<atoms
->nr
); j
++) {
151 pbc_dx(&pbc
,x
[i
],x
[j
],dx
);
153 rvec_sub(x
[i
],x
[j
],dx
);
156 if (is_bond(nnm
,nmt
,*atoms
->atomname
[i
],*atoms
->atomname
[j
],
161 add_param_to_list (bond
,&b
);
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
)
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
;
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
;
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
));
215 void lo_set_force_const(t_params
*plist
,real c
[],int nrfp
,gmx_bool bRound
,
216 gmx_bool bDih
,gmx_bool bParam
)
222 for(i
=0; (i
<plist
->nr
); i
++) {
224 for(j
=0; j
<nrfp
; j
++)
228 sprintf(buf
,"%.2e",plist
->param
[i
].c
[0]);
229 sscanf(buf
,"%lf",&cc
);
233 c
[0] = plist
->param
[i
].c
[0];
236 c
[0] = ((int)(c
[0] + 3600)) % 360;
239 /* To put the minimum at the current angle rather than the maximum */
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
,
255 real c
[MAXFORCEPARAM
];
259 lo_set_force_const(&plist
[F_BONDS
],c
,2,bRound
,FALSE
,bParam
);
261 lo_set_force_const(&plist
[F_ANGLES
],c
,2,bRound
,FALSE
,bParam
);
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
,
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
;
276 set_pbc(&pbc
,epbcXYZ
,box
);
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
);
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
);
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
[])
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
,
318 if (plist
[ftp
].nr
> 0) {
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
]);
335 static void print_rtp(const char *filenm
,const char *title
,t_atoms
*atoms
,
336 t_params plist
[],gpp_atomtype_t atype
,int cgnr
[],
343 fp
= gmx_fio_fopen(filenm
,"w");
344 fprintf(fp
,"; %s\n",title
);
346 fprintf(fp
,"[ %s ]\n",*atoms
->resinfo
[0].name
);
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
);
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."
395 t_params plist
[F_NRE
];
397 t_atoms
*atoms
; /* list with all atoms */
398 gpp_atomtype_t atype
;
404 char title
[STRLEN
],forcefield
[32],ffdir
[STRLEN
];
405 rvec
*x
; /* coordinates? */
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? */
413 gmx_bool bRTP
,bTOP
,bOPLS
;
415 real cutoff
,qtot
,mtot
;
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";
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
);
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
);
489 /* Init parameter lists */
492 /* Read coordinates */
493 get_stx_coordnum(opt2fn("-f",NFILE
,fnm
),&natoms
);
496 /* make space for all the atoms */
497 init_t_atoms(atoms
,natoms
,TRUE
);
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
);
505 gmx_fatal(FARGS
,"No or incorrect atomname2type.n2t file found (looking for %s)",
508 printf("There are %d name to type translations in file %s\n",nnm
,n2t
);
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
,
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);
524 print_nnb(&nnb
,"NNB");
525 gen_pad(&nnb
,atoms
,bH14
,nexcl
,plist
,excls
,NULL
,bAllDih
,bRemoveDih
,TRUE
);
529 plist
[F_LJ14
].nr
= 0;
531 "There are %4d %s dihedrals, %4d impropers, %4d angles\n"
532 " %4d pairs, %4d bonds and %4d atoms\n",
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
);
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
,
556 print_top_mols(fp
,mymol
.name
,ffdir
,NULL
,0,NULL
,1,&mymol
);
561 print_rtp(ftp2fn(efRTP
,NFILE
,fnm
),"Generated by x2top",
562 atoms
,plist
,atype
,cgnr
,asize(bts
),bts
);
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");