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 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 ((((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
]))
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 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
,epbcXYZ
,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
,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
,bool bRound
,
216 bool bDih
,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
,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
[],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 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."
398 t_params plist
[F_NRE
];
400 t_atoms
*atoms
; /* list with all atoms */
401 gpp_atomtype_t atype
;
407 char title
[STRLEN
],forcefield
[32],ffdir
[STRLEN
];
408 rvec
*x
; /* coordinates? */
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? */
416 bool bRTP
,bTOP
,bOPLS
;
418 real cutoff
,qtot
,mtot
;
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";
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
);
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
);
491 /* Init parameter lists */
494 /* Read coordinates */
495 get_stx_coordnum(opt2fn("-f",NFILE
,fnm
),&natoms
);
498 /* make space for all the atoms */
499 init_t_atoms(atoms
,natoms
,TRUE
);
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
);
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
,
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);
522 print_nnb(&nnb
,"NNB");
523 gen_pad(&nnb
,atoms
,bH14
,nexcl
,plist
,excls
,NULL
,bAllDih
,bRemoveDih
,TRUE
);
527 plist
[F_LJ14
].nr
= 0;
529 "There are %4d %s dihedrals, %4d impropers, %4d angles\n"
530 " %4d pairs, %4d bonds and %4d atoms\n",
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
);
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
,
554 print_top_mols(fp
,mymol
.name
,ffdir
,NULL
,0,NULL
,1,&mymol
);
559 print_rtp(ftp2fn(efRTP
,NFILE
,fnm
),"Generated by x2top",
560 atoms
,plist
,atype
,cgnr
,asize(bts
),bts
);
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");