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 * Great Red Oystrich Makes All Chemists Sane
29 static char *SRCID_mkice_c
= "$Id$";
51 #define DCONS 0.117265878
57 static char *watname
[] = { "OW ", "HW1", "HW2", "DW", "SW" };
58 static char *diamname
[] = { "C1", "H2", "H3", "H4", "H5", "H2", "H3", "H4", "H5" };
59 static real qspc
[] = { -0.82, 0.41, 0.41 };
60 static real qyaw
[] = { 1.24588, 0.62134, 0.62134, 0.0, -2.48856 };
61 static real spc_lj
[3][6] = {
62 { 2.6171e-3, 2.6331e-6, 0, 0, 0, 0 },
69 static real yaw_lj
[5][10] = {
70 { 0, 0, 0, 0, 0, 0, 0, 0, 0, COS
},
71 { 0, 0, 0, CHH
, 0, CHH
, 0, 0, 0, CHS
},
72 { 0, 0, 0, CHH
, 0, CHH
, 0, 0, 0, CHS
},
73 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
74 { 0, COS
, 0, CHS
, 0, CHS
, 0, 0, 2.6e-3, 0 }
77 void unitcell(rvec x
[],rvec box
,bool bYaw
,real odist
)
81 #define cy2 0.94280904
86 { 0, 0, 1 }, /* H relative to Oxygen */
88 { cx
, cy
, -cz
}, /* O2 */
89 { 0, 0, -1 }, /* H relative to Oxygen */
91 { cx
, cy
+cy2
, 0 }, /* O3 */
92 { -cx
, cy
, -cz
}, /* H relative to Oxygen */
94 { 0, 2*cy
+cy2
, -cz
}, /* O4 */
95 {-cx
,-cy
, +cz
}, /* H relative to Oxygen */
98 {-cx
, cy
, +cz
}, /* H relative to Oxygen */
100 { cx
, cy
, 1+cz
}, /* O6 */
101 { -cx
, -cy
, -cz
}, /* H relative to Oxygen */
103 { cx
, cy
+cy2
, 1 }, /* O7 */
104 { 0, 0, -1 }, /* H relative to Oxygen */
106 { 0, 2*cy
+cy2
,1+cz
}, /* O8 */
107 { 0, 0, 1 }, /* H relative to Oxygen */
114 for(i
=0; (i
<8); i
++) {
120 svmul(odist
,xx
[iin
],x
[iout
]);
121 svmul(-0.82,x
[iout
],t2
);
123 for(j
=1; (j
<=2); j
++) {
124 svmul(HDIST
,xx
[iin
+j
],tmp
);
125 rvec_add(x
[iout
],tmp
,x
[iout
+j
]);
126 svmul(0.41,x
[iout
+j
],t2
);
130 for(m
=0; (m
<DIM
); m
++)
131 x
[iout
+3][m
] = x
[iout
+4][m
] =
132 (1-2*DCONS
)*x
[iout
][m
]+DCONS
*(x
[iout
+1][m
]+x
[iout
+2][m
]);
136 box
[YY
] = 2*(cy2
+cy
);
138 for(i
=0; (i
<DIM
); i
++)
141 printf("Unitcell: %10.5f %10.5f %10.5f\n",box
[XX
],box
[YY
],box
[ZZ
]);
142 printf("Dipole: %10.5f %10.5f %10.5f (e nm)\n",dip
[XX
],dip
[YY
],dip
[ZZ
]);
145 void unitcell_d(rvec x
[],rvec box
,real odist
)
148 { 0, 0, 0 }, /* C1 */
149 { cx
, cy
, -cz
}, /* C2 */
150 { cx
, cy
+cy2
, 0 }, /* C3 */
151 { 0, 2*cy
+cy2
, -cz
}, /* C4 */
152 { 0, 0, 1 }, /* C5 */
153 { cx
, cy
, 1+cz
}, /* C6 */
154 { cx
, cy
+cy2
, 1 }, /* C7 */
155 { 0, 2*cy
+cy2
,1+cz
}, /* C8 */
158 { 0, 0, 1 }, /* H relative to C */
167 for(i
=0; (i
<8); i
++) {
170 svmul(odist
,cc
[iin
],x
[iout
]);
173 box
[YY
] = 2*(cy2
+cy
);
175 for(i
=0; (i
<DIM
); i
++)
178 printf("Unitcell: %10.5f %10.5f %10.5f\n",box
[XX
],box
[YY
],box
[ZZ
]);
181 static t_bbb
*mk_bonds(int natoms
,rvec x
[],real odist
)
183 real od2
= odist
*odist
+1e-5;
189 for(i
=0; (i
<natoms
); i
++) {
190 for(j
=i
+1; (j
<natoms
); j
++) {
191 rvec_sub(x
[i
],x
[j
],dx
);
192 if (iprod(dx
,dx
) <= od2
) {
193 bbb
[i
].aa
[bbb
[i
].n
++] = j
;
194 bbb
[j
].aa
[bbb
[j
].n
++] = i
;
199 #define PRB(nn) (bbb[(i)].n >= (nn)) ? bbb[i].aa[nn-1] : -1
200 for(i
=0; (i
<natoms
); i
++)
201 fprintf(debug
,"bonds from %3d: %d %d %d %d\n",
202 i
,PRB(1),PRB(2),PRB(3),PRB(4));
207 static void mk_diamond(t_atoms
*a
,rvec x
[],real odist
,t_symtab
*symtab
)
210 int i
,ib
,j
,k
,l
,m
,nrm
=0;
217 bbb
= mk_bonds(a
->nr
,x
,odist
);
219 for(i
=0; (i
<a
->nr
); i
++) {
221 for(k
=0; (k
<bbb
[i
].n
); k
++) {
223 for(j
=0; (j
<bbb
[ib
].n
); j
++)
224 if (bbb
[ib
].aa
[j
] == i
)
227 fatal_error(0,"Bond inconsistency (%d not in list of %d)!\n",i
,ib
);
228 for( ; (j
<bbb
[ib
].n
-1); j
++)
229 bbb
[ib
].aa
[j
] = bbb
[ib
].aa
[j
+1];
237 for(i
=j
=0; (i
<a
->nr
); i
++) {
239 copy_rvec(x
[i
],x
[j
]);
243 fprintf(stderr
,"Kicking out %d carbon atoms (out of %d)\n",
249 bbb
= mk_bonds(a
->nr
,x
,odist
);
250 for(i
=0; (i
<a
->nr
); i
++) {
253 a
->atomname
[i
] = put_symtab(symtab
,"C");
256 a
->atomname
[i
] = put_symtab(symtab
,"CH1");
259 a
->atomname
[i
] = put_symtab(symtab
,"CH2");
262 fatal_error(0,"This atom (%d) has %d bonds only",i
,bbb
[i
].n
);
268 static real
calc_ener(real c6
,real c12
,rvec dx
,tensor vir
)
274 e
= c12
*pow(r
,-12.0) - c6
*pow(r
,-6.0);
275 f
= 12*c12
*pow(r
,-14.0) - 6*c6
*pow(r
,-8.0);
276 for(m
=0; (m
<DIM
); m
++)
277 for(n
=0; (n
<DIM
); n
++)
278 vir
[m
][n
] -= 0.5*f
*dx
[m
]*dx
[n
];
283 void virial(FILE *fp
,bool bFull
,int nmol
,rvec x
[],matrix box
,real rcut
,
284 bool bYaw
,real q
[],bool bLJ
)
286 int i
,j
,im
,jm
,natmol
,ik
,jk
,m
,ninter
;
287 rvec dx
,f
,ftot
,dvir
,vir
,pres
,xcmi
,xcmj
,*force
;
288 real dx6
,dx2
,dx1
,fscal
,c6
,c12
,vcoul
,v12
,v6
,vctot
,v12tot
,v6tot
;
291 /* Initiate the periodic boundary conditions. Set bTruncOct to
292 * TRUE when using a truncated octahedron box.
294 fprintf(fp
,"%3s - %3s: %6s %6s %6s %6s %8s %8s %8s\n",
295 "ai","aj","dx","dy","dz","|d|","virx","viry","virz");
302 natmol
= bYaw
? 5 : 3;
303 snew(force
,nmol
*natmol
);
305 for(i
=0; (i
<nmol
); i
++) {
307 /* Center of geometry */
309 for(ik
=0; (ik
<natmol
); ik
++)
310 rvec_inc(xcmi
,x
[im
+ik
]);
311 for(m
=0; (m
<DIM
); m
++)
314 for(j
=i
+1; (j
<nmol
); j
++) {
316 /* Center of geometry */
318 for(jk
=0; (jk
<natmol
); jk
++)
319 rvec_inc(xcmj
,x
[jm
+jk
]);
320 for(m
=0; (m
<DIM
); m
++)
323 /* First check COM-COM distance */
324 pbc_dx(xcmi
,xcmj
,dx
);
325 if (norm(dx
) < rcut
) {
327 /* Neirest neighbour molecules! */
329 for(ik
=0; (ik
<natmol
); ik
++) {
330 for(jk
=0; (jk
<natmol
); jk
++) {
331 pbc_dx(x
[im
+ik
],x
[jm
+jk
],dx
);
334 vcoul
= q
[ik
]*q
[jk
]*ONE_4PI_EPS0
/dx1
;
339 c6
= yaw_lj
[ik
][2*jk
];
340 c12
= yaw_lj
[ik
][2*jk
+1];
343 c6
= spc_lj
[ik
][2*jk
];
344 c12
= spc_lj
[ik
][2*jk
+1];
351 fscal
= (vcoul
+12*v12
-6*v6
)/dx2
;
355 for(m
=0; (m
<DIM
); m
++) {
357 dvir
[m
] -= 0.5*dx
[m
]*f
[m
];
359 rvec_inc(force
[ik
+im
],f
);
360 rvec_dec(force
[jk
+jm
],f
);
362 fprintf(fp,"%3s%4d-%3s%4d: %6.3f %6.3f %6.3f %6.3f"
363 " %8.3f %8.3f %8.3f\n",
364 watname[ik],im+ik,watname[jk],jm+jk,
365 dx[XX],dx[YY],dx[ZZ],norm(dx),
366 dvir[XX],dvir[YY],dvir[ZZ]);*/
370 fprintf(fp
,"%3s%4d-%3s%4d: "
371 " %8.3f %8.3f %8.3f\n",
372 "SOL",i
,"SOL",j
,dvir
[XX
],dvir
[YY
],dvir
[ZZ
]);
377 fprintf(fp
,"There were %d interactions between the %d molecules (%.2f %%)\n",
378 ninter
,nmol
,(real
)ninter
/(0.5*nmol
*(nmol
-1)));
379 fprintf(fp
,"Vcoul: %10.4e V12: %10.4e V6: %10.4e Vtot: %10.4e (kJ/mol)\n",
380 vctot
/nmol
,v12tot
/nmol
,v6tot
/nmol
,(vctot
+v12tot
+v6tot
)/nmol
);
381 pr_rvec(fp
,0,"vir ",vir
,DIM
);
383 for(m
=0; (m
<DIM
); m
++)
384 pres
[m
] = -2*PRESFAC
/(det(box
))*vir
[m
];
385 pr_rvec(fp
,0,"pres",pres
,DIM
);
386 pr_rvecs(fp
,0,"force",force
,natmol
*nmol
);
390 int main(int argc
,char *argv
[])
392 static char *desc
[] = {
393 "mkice generates an ice crystal in the Ih crystal form which is the",
394 "most stable form. The rectangular unitcell contains eight molecules",
395 "and all oxygens are tetrahedrally coordinated."
397 static int nx
=1,ny
=1,nz
=1;
398 static bool bYaw
=FALSE
,bLJ
=TRUE
,bFull
=TRUE
,bSeries
=FALSE
,bDiamond
=FALSE
;
399 static real rcut
=0.3,odist
=0.274;
401 { "-nx", FALSE
, etINT
, {&nx
}, "nx" },
402 { "-ny", FALSE
, etINT
, {&ny
}, "ny" },
403 { "-nz", FALSE
, etINT
, {&nz
}, "nz" },
404 { "-yaw", FALSE
, etBOOL
, {&bYaw
},
405 "Generate dummies and shell positions" },
406 { "-lj", FALSE
, etBOOL
, {&bLJ
},
407 "Use LJ as well as coulomb for virial calculation" },
408 { "-rcut", FALSE
,etREAL
, {&rcut
},"Cut-off for virial calculations" },
409 { "-full", FALSE
,etBOOL
, {&bFull
},"Full virial output" },
410 { "-odist", FALSE
, etREAL
, {&odist
}, "Distance between oxygens" },
411 { "-diamond",FALSE
,etBOOL
, {&bDiamond
}, "Make a diamond instead" },
412 { "-series",FALSE
, etBOOL
, {&bSeries
},
413 "Do a series of virial calculations with different cut-off (from 0.3 up till the specified one)" }
416 { efPDB
, "-p", "ice", ffWRITE
},
417 { efSTO
, "-c", NULL
, ffOPTRD
},
418 { efTRN
, "-o", "ice", ffOPTWR
}
420 #define NFILE asize(fnm)
423 int i
,j
,k
,n
,nmax
,m
,natom
,natmol
;
430 CopyRight(stdout
,argv
[0]);
431 parse_common_args(&argc
,argv
,0,FALSE
,NFILE
,fnm
,asize(pa
),pa
,asize(desc
),
434 fprintf(debug
,"nx = %3d, ny = %3d, nz = %3d\n",nx
,ny
,nz
);
435 fprintf(debug
,"YAW = %3s, LJ = %3s, rcut = %g\n",yesno_names
[bYaw
],
436 yesno_names
[bLJ
],rcut
);
446 nmax
= natom
*nx
*ny
*nz
;
449 init_t_atoms(pdba
,nmax
,TRUE
);
451 open_symtab(&symtab
);
452 for(n
=0; (n
<nmax
); n
++) {
453 pdba
->pdbinfo
[n
].type
= epdbATOM
;
454 pdba
->pdbinfo
[n
].atomnr
= n
;
455 pdba
->atom
[n
].resnr
= n
/natmol
;
456 pdba
->atomname
[n
] = put_symtab(&symtab
,
457 bDiamond
? diamname
[(n
% natmol
)] : watname
[(n
% natmol
)]);
459 pdba
->resname
[n
] = put_symtab(&symtab
,"DIA");
461 pdba
->resname
[n
] = put_symtab(&symtab
,"SOL");
462 sprintf(pdba
->pdbinfo
[n
].pdbresnr
,"%d",n
);
463 pdba
->atom
[n
].chain
= ' ';
466 /* Generate the unit cell */
468 unitcell_d(xx
,box
,odist
);
470 unitcell(xx
,box
,bYaw
,odist
);
473 boxje
[XX
][XX
] = box
[XX
];
474 boxje
[YY
][YY
] = box
[YY
];
475 boxje
[ZZ
][ZZ
] = box
[ZZ
];
478 for(i
=0; (i
<nx
); i
++) {
480 for(j
=0; (j
<ny
); j
++) {
482 for(k
=0; (k
<nz
); k
++) {
484 for(m
=0; (m
<natom
); m
++,n
++) {
485 rvec_add(xx
[n
% natom
],tmp
,xx
[n
]);
492 boxje
[XX
][XX
] = box
[XX
]*nx
;
493 boxje
[YY
][YY
] = box
[YY
]*ny
;
494 boxje
[ZZ
][ZZ
] = box
[ZZ
]*nz
;
496 printf("Crystal: %10.5f %10.5f %10.5f\n",
497 nx
*box
[XX
],ny
*box
[YY
],nz
*box
[ZZ
]);
499 if (debug
&& !bDiamond
) {
501 for(i
=3; (i
<=10*rcut
); i
++) {
502 fprintf(debug
,"This is with rcut = %g\n",i
*0.1);
503 virial(debug
,bFull
,nmax
/natmol
,xx
,boxje
,
504 0.1*i
,bYaw
,bYaw
? qyaw
: qspc
,bLJ
);
507 virial(debug
,bFull
,nmax
/natmol
,xx
,boxje
,
508 rcut
,bYaw
,bYaw
? qyaw
: qspc
,bLJ
);
512 mk_diamond(pdba
,xx
,odist
,&symtab
);
514 fp
= ftp2FILE(efPDB
,NFILE
,fnm
,"w");
516 fprintf(fp
,"HEADER This is a *diamond*\n");
518 fprintf(fp
,"HEADER A beautifil Ice Ih crystal\n");
519 fprintf(fp
,"REMARK Generated by mkice with the following options:\n"
520 "REMARK nx = %d, ny = %d, nz = %d, odist = %g\n",nx
,ny
,nz
,odist
);
521 write_pdbfile(fp
,bromacs(),pdba
,xx
,boxje
,' ',FALSE
);
524 if (ftp2bSet(efTRN
,NFILE
,fnm
))
525 write_trn(ftp2fn(efTRN
,NFILE
,fnm
),0,0,0,boxje
,nmax
,xx
,NULL
,NULL
);