4 * This source code is part of
8 * GROningen MAchine for Chemical Simulations
12 * Copyright (c) 1991-1999
13 * BIOSON Research Institute, Dept. of Biophysical Chemistry
14 * University of Groningen, The Netherlands
17 * GROMACS: A message-passing parallel molecular dynamics implementation
18 * H.J.C. Berendsen, D. van der Spoel and R. van Drunen
19 * Comp. Phys. Comm. 91, 43-56 (1995)
21 * Also check out our WWW page:
22 * http://md.chem.rug.nl/~gmx
27 * GRowing Old MAkes el Chrono Sweat
29 static char *SRCID_x2top_c
= "$Id$";
55 int get_atype(char *nm
)
57 char atp
[6] = "HCNOSX";
58 #define NATP asize(atp)
61 for(i
=0; (i
<NATP
-1); i
++) {
62 if (nm
[0] == atp
[i
]) {
70 bool is_bond(int aai
,int aaj
,real len2
)
73 { 0.00, 0.108, 0.105, 0.10, 0.10, 0.10 },
74 { 0.108, 0.15, 0.14, 0.14, 0.16, 0.15 },
75 { 0.105, 0.14, 0.14, 0.14, 0.16, 0.15 },
76 { 0.10, 0.14, 0.14, 0.14, 0.17, 0.16 },
77 { 0.10, 0.16, 0.16, 0.17, 0.20, 0.20 },
78 { 0.10, 0.15, 0.15, 0.16, 0.20, 0.20 }
86 /* There is a bond when the deviation from ideal length is less than
89 bl
= blen
[aai
][aaj
]*1.1;
90 bIsBond
= (len2
< bl
*bl
);
94 fprintf(debug
,"ai: %5s aj: %5s len: %8.3f bond: %s\n",
95 ai
,aj
,len
,BOOL(bIsBond
));
100 real
get_amass(char *aname
,int nmass
,char **nm2mass
)
108 for(i
=0; (i
<nmass
); i
++) {
109 sscanf(nm2mass
[i
],"%s%lf",nmbuf
,&mass
);
111 if (strcmp(aname
,nmbuf
) == 0) {
119 void mk_bonds(t_atoms
*atoms
,rvec x
[],t_params
*bond
,int nbond
[],char *ff
)
123 char **nm2mass
=NULL
,buf
[128];
128 for(i
=0; (i
<MAXATOMLIST
); i
++)
130 for(i
=0; (i
<MAXFORCEPARAM
); i
++)
133 sprintf(buf
,"%s.atp",ff
);
134 nmass
= get_file(buf
,&nm2mass
);
135 fprintf(stderr
,"There are %d type to mass translations\n",nmass
);
137 for(i
=0; (i
<atoms
->nr
); i
++) {
138 atom
[i
].type
= get_atype(*atoms
->atomname
[i
]);
139 atom
[i
].m
= get_amass(*atoms
->atomname
[i
],nmass
,nm2mass
);
141 for(i
=0; (i
<atoms
->nr
); i
++) {
143 fprintf(stderr
,"\ratom %d",i
);
145 for(j
=i
+1; (j
<atoms
->nr
); j
++) {
146 rvec_sub(x
[i
],x
[j
],dx
);
148 if ((dx
[XX
] < 0.25) && (dx
[YY
] < 0.25) && (dx
[ZZ
] < 0.25)) {
151 if (is_bond(aai
,atom
[j
].type
,dx2
)) {
155 push_bondnow (bond
,&b
);
162 fprintf(stderr
,"\n");
165 int *set_cgnr(t_atoms
*atoms
)
171 snew(cgnr
,atoms
->nr
);
172 for(i
=0; (i
<atoms
->nr
); i
++) {
173 qt
+= atoms
->atom
[i
].q
;
183 t_atomtype
*set_atom_type(t_atoms
*atoms
,int nbonds
[],
184 int nnm
,t_nm2type nm2t
[])
186 static t_symtab symtab
;
191 open_symtab(&symtab
);
195 atype
->atomname
= NULL
;
197 for(i
=0; (i
<atoms
->nr
); i
++) {
198 if ((type
= nm2type(nnm
,nm2t
,*atoms
->atomname
[i
],nbonds
[i
])) == NULL
)
199 fatal_error(0,"No forcefield type for atom %s (%d) with %d bonds",
200 *atoms
->atomname
[i
],i
+1,nbonds
[i
]);
202 fprintf(debug
,"Selected atomtype %s for atom %s\n",
203 type
,*atoms
->atomname
[i
]);
204 for(k
=0; (k
<atype
->nr
); k
++) {
205 if (strcmp(type
,*atype
->atomname
[k
]) == 0) {
206 atoms
->atom
[i
].type
= k
;
207 atoms
->atom
[i
].typeB
= k
;
214 srenew(atype
->atomname
,atype
->nr
);
215 srenew(atype
->atom
,atype
->nr
);
216 atype
->atomname
[k
] = put_symtab(&symtab
,type
);
217 atype
->atom
[k
].type
= k
;
218 atoms
->atom
[i
].type
= k
;
219 atype
->atom
[k
].typeB
= k
;
220 atoms
->atom
[i
].typeB
= k
;
225 close_symtab(&symtab
);
227 fprintf(stderr
,"There are %d different atom types in your sample\n",
233 void lo_set_force_const(t_params
*plist
,real c
[],int nrfp
,bool bRound
)
239 for(i
=0; (i
<plist
->nr
); i
++) {
241 sprintf(buf
,"%.2e",plist
->param
[i
].c
[0]);
242 sscanf(buf
,"%lf",&cc
);
246 c
[0] = plist
->param
[i
].c
[0];
248 for(j
=0; (j
<nrfp
); j
++) {
249 plist
->param
[i
].c
[j
] = c
[j
];
250 plist
->param
[i
].c
[nrfp
+j
] = c
[j
];
252 plist
->param
[i
].s
= strdup("");
256 void set_force_const(t_params plist
[],real kb
,real kt
,real kp
,bool bRound
)
259 real c
[MAXFORCEPARAM
];
263 lo_set_force_const(&plist
[F_BONDS
],c
,2,bRound
);
265 lo_set_force_const(&plist
[F_ANGLES
],c
,2,bRound
);
268 lo_set_force_const(&plist
[F_PDIHS
],c
,3,bRound
);
271 void calc_angles_dihs(t_params
*ang
,t_params
*dih
,rvec x
[])
274 rvec r_ij
,r_kj
,r_kl
,m
,n
;
275 real sign
,th
,costh
,ph
,cosph
;
279 box
[XX
][XX
] = box
[YY
][YY
] = box
[ZZ
][ZZ
] = 1000;
280 for(i
=0; (i
<ang
->nr
); i
++) {
281 ai
= ang
->param
[i
].AI
;
282 aj
= ang
->param
[i
].AJ
;
283 ak
= ang
->param
[i
].AK
;
284 th
= RAD2DEG
*bond_angle(box
,x
[ai
],x
[aj
],x
[ak
],r_ij
,r_kj
,&costh
);
285 ang
->param
[i
].C0
= th
;
287 for(i
=0; (i
<dih
->nr
); i
++) {
288 ai
= dih
->param
[i
].AI
;
289 aj
= dih
->param
[i
].AJ
;
290 ak
= dih
->param
[i
].AK
;
291 al
= dih
->param
[i
].AL
;
292 ph
= RAD2DEG
*dih_angle(box
,x
[ai
],x
[aj
],x
[ak
],x
[al
],
293 r_ij
,r_kj
,r_kl
,m
,n
,&cosph
,&sign
);
294 dih
->param
[i
].C0
= ph
;
298 void dump_hybridization(FILE *fp
,t_atoms
*atoms
,int nbonds
[])
302 for(i
=0; (i
<atoms
->nr
); i
++) {
303 fprintf(fp
,"Atom %5s has %1d bonds\n",*atoms
->atomname
[i
],nbonds
[i
]);
307 int main(int argc
, char *argv
[])
309 static char *desc
[] = {
310 "x2top generates a primitive topology from a coordinate file.",
311 "The program assumes all hydrogens are present when defining",
312 "the hybridization from the atom name and the number of bonds."
314 static char *bugs
[] = {
315 "The atom type selection is primitive. Virtually no chemical knowledge is used",
316 "Periodic boundary conditions screw up the bonding",
317 "No improper dihedrals are generated",
318 "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."
321 t_params plist
[F_NRE
];
322 t_atoms
*atoms
; /* list with all atoms */
331 rvec
*x
; /* coordinates? */
333 int bts
[] = { 1,1,1,2 };
334 matrix box
; /* box length matrix */
335 int natoms
; /* number of atoms in one molecule */
336 int nres
; /* number of molecules? */
340 { efSTX
, "-f", "conf", ffREAD
},
341 { efTOP
, "-o", "out", ffWRITE
}
343 #define NFILE asize(fnm)
344 static real kb
= 4e5
,kt
= 400,kp
= 5;
345 static int nexcl
= 3;
346 static bool bH14
= FALSE
,bAllDih
= FALSE
,bRound
= TRUE
,bPairs
= TRUE
;
347 static char *molnm
= "ICE";
349 { "-kb", FALSE
, etREAL
, {&kb
},
350 "Bonded force constant (kJ/mol/nm^2)" },
351 { "-kt", FALSE
, etREAL
, {&kt
},
352 "Angle force constant (kJ/mol/rad^2)" },
353 { "-kp", FALSE
, etREAL
, {&kp
},
354 "Dihedral angle force constant (kJ/mol/rad^2)" },
355 { "-nexcl", FALSE
, etINT
, {&nexcl
},
356 "Number of exclusions" },
357 { "-H14", FALSE
, etBOOL
, {&bH14
},
358 "Use 3rd neighbour interactions for hydrogen atoms" },
359 { "-alldih", FALSE
, etBOOL
, {&bAllDih
},
360 "Generate all proper dihedrals" },
361 { "-round", FALSE
, etBOOL
, {&bRound
},
362 "Round off measured values" },
363 { "-pairs", FALSE
, etBOOL
, {&bPairs
},
364 "Output 1-4 interactions (pairs) in topology file" },
365 { "-name", FALSE
, etSTR
, {&molnm
},
366 "Name of your molecule" }
369 CopyRight(stdout
,argv
[0]);
371 parse_common_args(&argc
,argv
,0,FALSE
,NFILE
,fnm
,asize(pa
),pa
,
372 asize(desc
),desc
,asize(bugs
),bugs
);
374 mymol
.name
= strdup(molnm
);
377 /* Init lookup table for invsqrt */
378 init_lookup_table(stdout
);
380 /* Init parameter lists */
383 /* Read coordinates */
384 get_stx_coordnum(opt2fn("-f",NFILE
,fnm
),&natoms
);
387 /* make space for all the atoms */
388 init_t_atoms(atoms
,natoms
,FALSE
);
391 read_stx_conf(opt2fn("-f",NFILE
,fnm
),title
,atoms
,x
,NULL
,box
);
395 snew(nbonds
,atoms
->nr
);
397 printf("Generating bonds from distances...\n");
398 mk_bonds(atoms
,x
,&(plist
[F_BONDS
]),nbonds
,ff
);
400 nm2t
= rd_nm2type(ff
,&nnm
);
401 printf("There are %d name to type translations\n",nnm
);
403 dump_nm2type(debug
,nnm
,nm2t
);
404 atype
= set_atom_type(atoms
,nbonds
,nnm
,nm2t
);
406 /* Make Angles and Dihedrals */
407 printf("Generating angles and dihedrals from bonds...\n");
408 init_nnb(&nnb
,atoms
->nr
,4);
410 print_nnb(&nnb
,"NNB");
411 gen_pad(&nnb
,atoms
,bH14
,plist
,NULL
,bAllDih
);
415 plist
[F_LJ14
].nr
= 0;
417 "There are %4d dihedrals, %4d impropers, %4d angles\n"
418 " %4d pairs, %4d bonds and %4d atoms\n",
419 plist
[F_PDIHS
].nr
, plist
[F_IDIHS
].nr
, plist
[F_ANGLES
].nr
,
420 plist
[F_LJ14
].nr
, plist
[F_BONDS
].nr
,atoms
->nr
);
424 calc_angles_dihs(&plist
[F_ANGLES
],&plist
[F_PDIHS
],x
);
426 set_force_const(plist
,kb
,kt
,kp
,bRound
);
428 cgnr
= set_cgnr(atoms
);
430 fp
= ftp2FILE(efTOP
,NFILE
,fnm
,"w");
431 print_top_header(fp
,"Generated by x2top",TRUE
, ff
,1.0);
433 write_top(fp
,NULL
,mymol
.name
,atoms
,bts
,plist
,&excl
,atype
,cgnr
,nexcl
);
434 print_top_mols(fp
,mymol
.name
,0,NULL
,1,&mymol
);
439 dump_hybridization(debug
,atoms
,nbonds
);