4 * This source code is part of
8 * GROningen MAchine for Chemical Simulations
11 * Copyright (c) 1991-2001, University of Groningen, The Netherlands
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * If you want to redistribute modifications, please consider that
18 * scientific software is very special. Version control is crucial -
19 * bugs must be traceable. We will be happy to consider code for
20 * inclusion in the official distribution, but derived work must not
21 * be called official GROMACS. Details are found in the README & COPYING
22 * files - if they are missing, get the official version at www.gromacs.org.
24 * To help us fund GROMACS development, we humbly ask that you cite
25 * the papers on the package - you can find them in the top README file.
27 * For more info, check our website at http://www.gromacs.org
30 * Gromacs Runs One Microsecond At Cannonball Speeds
57 char atp
[6] = "HCNOSX";
58 #define NATP asize(atp)
60 real blen
[NATP
][NATP
] = {
61 { 0.00, 0.108, 0.105, 0.10, 0.10, 0.10 },
62 { 0.108, 0.15, 0.14, 0.14, 0.16, 0.14 },
63 { 0.105, 0.14, 0.14, 0.14, 0.16, 0.14 },
64 { 0.10, 0.14, 0.14, 0.14, 0.17, 0.14 },
65 { 0.10, 0.16, 0.16, 0.17, 0.20, 0.17 },
66 { 0.10, 0.14, 0.14, 0.14, 0.17, 0.17 }
69 #define MARGIN_FAC 1.1
71 static real
set_x_blen(real scale
)
76 for(i
=0; i
<NATP
-1; i
++) {
77 blen
[NATP
-1][i
] *= scale
;
78 blen
[i
][NATP
-1] *= scale
;
80 blen
[NATP
-1][NATP
-1] *= scale
;
85 if (blen
[i
][j
] > maxlen
)
88 return maxlen
*MARGIN_FAC
;
91 static int get_atype(char *nm
)
95 for(i
=0; (i
<NATP
-1); i
++) {
96 if (nm
[0] == atp
[i
]) {
104 static bool is_bond(int aai
,int aaj
,real len2
)
112 /* There is a bond when the deviation from ideal length is less than
115 bl
= blen
[aai
][aaj
]*MARGIN_FAC
;
117 bIsBond
= (len2
< bl
*bl
);
121 fprintf(debug
,"ai: %5s aj: %5s len: %8.3f bond: %s\n",
122 ai
,aj
,len
,BOOL(bIsBond
));
127 real
get_amass(char *aname
,int nmass
,char **nm2mass
)
135 for(i
=0; (i
<nmass
); i
++) {
136 sscanf(nm2mass
[i
],"%s%lf",nmbuf
,&mass
);
138 if (strcmp(aname
,nmbuf
) == 0) {
146 void mk_bonds(t_atoms
*atoms
,rvec x
[],t_params
*bond
,int nbond
[],char *ff
,
147 real cutoff
,bool bPBC
,matrix box
)
151 char **nm2mass
=NULL
,buf
[128];
156 for(i
=0; (i
<MAXATOMLIST
); i
++)
158 for(i
=0; (i
<MAXFORCEPARAM
); i
++)
161 sprintf(buf
,"%s.atp",ff
);
162 nmass
= get_file(buf
,&nm2mass
);
163 fprintf(stderr
,"There are %d type to mass translations\n",nmass
);
165 for(i
=0; (i
<atoms
->nr
); i
++) {
166 atom
[i
].type
= get_atype(*atoms
->atomname
[i
]);
167 atom
[i
].m
= get_amass(*atoms
->atomname
[i
],nmass
,nm2mass
);
172 for(i
=0; (i
<atoms
->nr
); i
++) {
174 fprintf(stderr
,"\ratom %d",i
);
176 for(j
=i
+1; (j
<atoms
->nr
); j
++) {
178 pbc_dx(x
[i
],x
[j
],dx
);
180 rvec_sub(x
[i
],x
[j
],dx
);
183 if ((dx2
< c2
) && (is_bond(aai
,atom
[j
].type
,dx2
))) {
187 push_bondnow (bond
,&b
);
193 fprintf(stderr
,"\ratom %d\n",i
);
196 int *set_cgnr(t_atoms
*atoms
)
202 snew(cgnr
,atoms
->nr
);
203 for(i
=0; (i
<atoms
->nr
); i
++) {
204 qt
+= atoms
->atom
[i
].q
;
214 t_atomtype
*set_atom_type(t_atoms
*atoms
,int nbonds
[],
215 int nnm
,t_nm2type nm2t
[])
217 static t_symtab symtab
;
222 open_symtab(&symtab
);
226 atype
->atomname
= NULL
;
227 atype
->bondatomtype
= NULL
;
229 for(i
=0; (i
<atoms
->nr
); i
++) {
230 if ((type
= nm2type(nnm
,nm2t
,*atoms
->atomname
[i
],nbonds
[i
])) == NULL
)
231 fatal_error(0,"No forcefield type for atom %s (%d) with %d bonds",
232 *atoms
->atomname
[i
],i
+1,nbonds
[i
]);
234 fprintf(debug
,"Selected atomtype %s for atom %s\n",
235 type
,*atoms
->atomname
[i
]);
236 for(k
=0; (k
<atype
->nr
); k
++) {
237 if (strcmp(type
,*atype
->atomname
[k
]) == 0) {
238 atoms
->atom
[i
].type
= k
;
239 atoms
->atom
[i
].typeB
= k
;
246 srenew(atype
->atomname
,atype
->nr
);
247 srenew(atype
->atom
,atype
->nr
);
248 srenew(atype
->bondatomtype
,atype
->nr
);
249 atype
->atomname
[k
] = put_symtab(&symtab
,type
);
250 atype
->bondatomtype
[k
] = k
; /* Set bond_atomtype identical to atomtype */
251 atype
->atom
[k
].type
= k
;
252 atoms
->atom
[i
].type
= k
;
253 atype
->atom
[k
].typeB
= k
;
254 atoms
->atom
[i
].typeB
= k
;
259 close_symtab(&symtab
);
261 fprintf(stderr
,"There are %d different atom types in your sample\n",
267 void lo_set_force_const(t_params
*plist
,real c
[],int nrfp
,bool bRound
,
268 bool bDih
,bool bParam
)
274 for(i
=0; (i
<plist
->nr
); i
++) {
276 for(j
=0; j
<nrfp
; j
++)
280 sprintf(buf
,"%.2e",plist
->param
[i
].c
[0]);
281 sscanf(buf
,"%lf",&cc
);
285 c
[0] = plist
->param
[i
].c
[0];
288 c
[0] = ((int)(c
[0] + 3600)) % 360;
291 /* To put the minimum at the current angle rather than the maximum */
295 for(j
=0; (j
<nrfp
); j
++) {
296 plist
->param
[i
].c
[j
] = c
[j
];
297 plist
->param
[i
].c
[nrfp
+j
] = c
[j
];
299 set_p_string(&(plist
->param
[i
]),"");
303 void set_force_const(t_params plist
[],real kb
,real kt
,real kp
,bool bRound
,
307 real c
[MAXFORCEPARAM
];
311 lo_set_force_const(&plist
[F_BONDS
],c
,2,bRound
,FALSE
,bParam
);
313 lo_set_force_const(&plist
[F_ANGLES
],c
,2,bRound
,FALSE
,bParam
);
316 lo_set_force_const(&plist
[F_PDIHS
],c
,3,bRound
,TRUE
,bParam
);
319 void calc_angles_dihs(t_params
*ang
,t_params
*dih
,rvec x
[],bool bPBC
,
323 rvec r_ij
,r_kj
,r_kl
,m
,n
;
324 real sign
,th
,costh
,ph
,cosph
;
327 box
[XX
][XX
] = box
[YY
][YY
] = box
[ZZ
][ZZ
] = 1000;
329 pr_rvecs(debug
,0,"X2TOP",box
,DIM
);
330 for(i
=0; (i
<ang
->nr
); i
++) {
331 ai
= ang
->param
[i
].AI
;
332 aj
= ang
->param
[i
].AJ
;
333 ak
= ang
->param
[i
].AK
;
334 th
= RAD2DEG
*bond_angle(box
,x
[ai
],x
[aj
],x
[ak
],r_ij
,r_kj
,&costh
);
336 fprintf(debug
,"X2TOP: ai=%3d aj=%3d ak=%3d r_ij=%8.3f r_kj=%8.3f th=%8.3f\n",
337 ai
,aj
,ak
,norm(r_ij
),norm(r_kj
),th
);
338 ang
->param
[i
].C0
= th
;
340 for(i
=0; (i
<dih
->nr
); i
++) {
341 ai
= dih
->param
[i
].AI
;
342 aj
= dih
->param
[i
].AJ
;
343 ak
= dih
->param
[i
].AK
;
344 al
= dih
->param
[i
].AL
;
345 ph
= RAD2DEG
*dih_angle(box
,x
[ai
],x
[aj
],x
[ak
],x
[al
],
346 r_ij
,r_kj
,r_kl
,m
,n
,&cosph
,&sign
);
348 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",
349 ai
,aj
,ak
,al
,norm(r_ij
),norm(r_kj
),norm(r_kl
),ph
);
350 dih
->param
[i
].C0
= ph
;
354 static void dump_hybridization(FILE *fp
,t_atoms
*atoms
,int nbonds
[])
358 for(i
=0; (i
<atoms
->nr
); i
++) {
359 fprintf(fp
,"Atom %5s has %1d bonds\n",*atoms
->atomname
[i
],nbonds
[i
]);
363 static void print_rtp(char *filenm
,char *title
,char *name
,t_atoms
*atoms
,
364 t_params plist
[],t_atomtype
*atype
,int cgnr
[])
369 int main(int argc
, char *argv
[])
371 static char *desc
[] = {
372 "x2top generates a primitive topology from a coordinate file.",
373 "The program assumes all hydrogens are present when defining",
374 "the hybridization from the atom name and the number of bonds.",
375 "The program can also make an rtp entry, which you can then add",
376 "to the rtp database.[PAR]",
377 "When [TT]-param[tt] is set, equilibrium distances and angles",
378 "and force constants will be printed in the topology for all",
379 "interactions. The equilibrium distances and angles are taken",
380 "from the input coordinates, the force constant are set with",
381 "command line options."
383 static char *bugs
[] = {
384 "The atom type selection is primitive. Virtually no chemical knowledge is used",
385 "Periodic boundary conditions screw up the bonding",
386 "No improper dihedrals are generated",
387 "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."
390 t_params plist
[F_NRE
];
392 t_atoms
*atoms
; /* list with all atoms */
400 rvec
*x
; /* coordinates? */
402 int bts
[] = { 1,1,1,2 };
403 matrix box
; /* box length matrix */
404 int natoms
; /* number of atoms in one molecule */
405 int nres
; /* number of molecules? */
411 { efSTX
, "-f", "conf", ffREAD
},
412 { efTOP
, "-o", "out", ffOPTWR
},
413 { efRTP
, "-r", "out", ffOPTWR
}
415 #define NFILE asize(fnm)
416 static real scale
= 1.1, kb
= 4e5
,kt
= 400,kp
= 5;
417 static int nexcl
= 3;
418 static bool bParam
= FALSE
,bH14
= FALSE
,bAllDih
= FALSE
,bRound
= TRUE
;
419 static bool bPairs
= TRUE
, bPBC
= TRUE
;
420 static char *molnm
= "ICE";
422 { "-scale", FALSE
, etREAL
, {&scale
},
423 "Scaling factor for bonds with unknown atom types relative to atom type O" },
424 { "-nexcl", FALSE
, etINT
, {&nexcl
},
425 "Number of exclusions" },
426 { "-H14", FALSE
, etBOOL
, {&bH14
},
427 "Use 3rd neighbour interactions for hydrogen atoms" },
428 { "-alldih", FALSE
, etBOOL
, {&bAllDih
},
429 "Generate all proper dihedrals" },
430 { "-pairs", FALSE
, etBOOL
, {&bPairs
},
431 "Output 1-4 interactions (pairs) in topology file" },
432 { "-name", FALSE
, etSTR
, {&molnm
},
433 "Name of your molecule" },
434 { "-pbc", FALSE
, etBOOL
, {&bPBC
},
435 "Use periodic boundary conditions. Please set the GMXFULLPBC environment variable as well." },
436 { "-param", FALSE
, etBOOL
, {&bParam
},
437 "Print parameters in the output" },
438 { "-round", FALSE
, etBOOL
, {&bRound
},
439 "Round off measured values" },
440 { "-kb", FALSE
, etREAL
, {&kb
},
441 "Bonded force constant (kJ/mol/nm^2)" },
442 { "-kt", FALSE
, etREAL
, {&kt
},
443 "Angle force constant (kJ/mol/rad^2)" },
444 { "-kp", FALSE
, etREAL
, {&kp
},
445 "Dihedral angle force constant (kJ/mol/rad^2)" }
448 CopyRight(stdout
,argv
[0]);
450 parse_common_args(&argc
,argv
,0,NFILE
,fnm
,asize(pa
),pa
,
451 asize(desc
),desc
,asize(bugs
),bugs
);
452 bRTP
= opt2bSet("-r",NFILE
,fnm
);
453 bTOP
= opt2bSet("-o",NFILE
,fnm
);
455 fatal_error(0,"Specify at least one output file");
457 cutoff
= set_x_blen(scale
);
460 set_gmx_full_pbc(stdout
);
462 mymol
.name
= strdup(molnm
);
465 /* Init parameter lists */
468 /* Read coordinates */
469 get_stx_coordnum(opt2fn("-f",NFILE
,fnm
),&natoms
);
472 /* make space for all the atoms */
473 init_t_atoms(atoms
,natoms
,FALSE
);
476 read_stx_conf(opt2fn("-f",NFILE
,fnm
),title
,atoms
,x
,NULL
,box
);
480 snew(nbonds
,atoms
->nr
);
482 printf("Generating bonds from distances...\n");
483 mk_bonds(atoms
,x
,&(plist
[F_BONDS
]),nbonds
,ff
,cutoff
,bPBC
,box
);
485 nm2t
= rd_nm2type(ff
,&nnm
);
486 printf("There are %d name to type translations\n",nnm
);
488 dump_nm2type(debug
,nnm
,nm2t
);
489 atype
= set_atom_type(atoms
,nbonds
,nnm
,nm2t
);
491 /* Make Angles and Dihedrals */
492 snew(excls
,atoms
->nr
);
493 printf("Generating angles and dihedrals from bonds...\n");
494 init_nnb(&nnb
,atoms
->nr
,4);
496 print_nnb(&nnb
,"NNB");
497 gen_pad(&nnb
,atoms
,bH14
,nexcl
,plist
,excls
,NULL
,bAllDih
);
501 plist
[F_LJ14
].nr
= 0;
503 "There are %4d dihedrals, %4d impropers, %4d angles\n"
504 " %4d pairs, %4d bonds and %4d atoms\n",
505 plist
[F_PDIHS
].nr
, plist
[F_IDIHS
].nr
, plist
[F_ANGLES
].nr
,
506 plist
[F_LJ14
].nr
, plist
[F_BONDS
].nr
,atoms
->nr
);
508 calc_angles_dihs(&plist
[F_ANGLES
],&plist
[F_PDIHS
],x
,bPBC
,box
);
510 set_force_const(plist
,kb
,kt
,kp
,bRound
,bParam
);
512 cgnr
= set_cgnr(atoms
);
515 fp
= ftp2FILE(efTOP
,NFILE
,fnm
,"w");
516 print_top_header(fp
,ftp2fn(efTOP
,NFILE
,fnm
),
517 "Generated by x2top",TRUE
, ff
,1.0);
519 write_top(fp
,NULL
,mymol
.name
,atoms
,bts
,plist
,excls
,atype
,cgnr
,nexcl
);
520 print_top_mols(fp
,mymol
.name
,0,NULL
,1,&mymol
);
525 print_rtp(ftp2fn(efRTP
,NFILE
,fnm
),"Generated by x2top",
526 mymol
.name
,atoms
,plist
,atype
,cgnr
);
529 dump_hybridization(debug
,atoms
,nbonds
);