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_optwat_c
= "$Id$";
43 real
ener(matrix P
,real e
,real e0
,int nmol
,real kp
,real ke
,bool bPScal
)
46 return (kp
*(sqr(P
[XX
][XX
]+P
[YY
][YY
]+P
[ZZ
][ZZ
]-3))+
49 return (kp
*(sqr(P
[XX
][XX
]-1)+sqr(P
[YY
][YY
]-1)+sqr(P
[ZZ
][ZZ
]-1)+
50 sqr(P
[XX
][YY
])+sqr(P
[XX
][ZZ
])+sqr(P
[YY
][ZZ
])) +
54 void do_sim(char *enx
,
55 t_topology
*top
,rvec
*x
,rvec
*v
,t_inputrec
*ir
,matrix box
)
57 char *tpx
= "optwat.tpr";
60 write_tpx(tpx
,0,0.0,0.0,ir
,box
,top
->atoms
.nr
,x
,v
,NULL
,top
);
61 sprintf(buf
,"xmdrun -s %s -e %s >& /dev/null",tpx
,enx
);
65 void get_results(char *enx
,real P
[],real
*epot
,int pindex
,int eindex
)
73 fp_ene
= open_enx(enx
,"r");
75 do_enxnms(fp_ene
,&nre
,&nms
);
78 /* Read until the last frame */
79 while (do_enx(fp_ene
,&t
,&step
,&nre
,ener
,&ndr
,NULL
));
83 *epot
= ener
[eindex
].e
;
84 for(i
=pindex
; (i
<pindex
+9); i
++)
85 P
[i
-pindex
] = ener
[i
].e
;
90 void copy_iparams(int nr
,t_iparams dest
[],t_iparams src
[])
92 memcpy(dest
,src
,nr
*sizeof(dest
[0]));
95 void rand_step(FILE *fp
,int nr
,t_iparams ip
[],int *seed
,real frac
)
101 i
= (int) (rando(seed
)*nr
);
102 } while (ip
[i
].lj
.c12
== 0.0);
105 ff
= frac
*rando(seed
);
108 if (rando(seed
) > 0.5) {
109 ip
[i
].lj
.c12
*= 1.0+ff
;
110 fprintf(fp
,"Increasing c12[%d] by %g%% to %g\n",i
,100*ff
,ip
[i
].lj
.c12
);
113 ip
[i
].lj
.c12
*= 1.0-ff
;
114 fprintf(fp
,"Decreasing c12[%d] by %g%% to %g\n",i
,100*ff
,ip
[i
].lj
.c12
);
118 void pr_progress(FILE *fp
,int nit
,tensor P
,real epot
,real eFF
,
119 double mc_crit
,bool bConv
,bool bAccept
)
121 fprintf(fp
,"Iter %3d, eFF = %g, Converged = %s, Accepted = %s\n",
122 nit
,eFF
,yesno_names
[bConv
],yesno_names
[bAccept
]);
123 fprintf(fp
,"Epot = %g Pscal = %g, mc_crit = %g\n",epot
,
125 pr_rvecs(fp
,0,"Pres",P
,DIM
);
126 fprintf(fp
,"-----------------------------------------------------\n");
130 int main(int argc
,char *argv
[])
132 static char *desc
[] = {
133 "optwat optimizes the force field parameter set of a molecular crystal",
134 "to reproduce the pressure tensor and experimental energy.[PAR]",
135 "Note that for good results the tpx file must contain input for a",
136 "simulated annealing run, or a single point energy calculation at 0 K"
139 { efTPX
, NULL
, NULL
, ffREAD
},
140 { efENX
, "-e", NULL
, ffRW
},
141 { efLOG
, "-g", NULL
, ffWRITE
}
143 #define NFILE asize(fnm)
145 static real epot0
= -57, tol
= 1, kT
= 0.0;
146 static real kp
= 1, ke
= 100, frac
= 0.1;
147 static int maxnit
= 100, eindex
= 5, pindex
= 19;
148 static int seed
= 1993;
149 static bool bPScal
= FALSE
;
150 static t_pargs pa
[] = {
151 { "-epot0", FALSE
, etREAL
, {&epot0
},
152 "Potential energy in kJ/mol" },
153 { "-tol", FALSE
, etREAL
, {&tol
},
154 "Tolerance for converging" },
155 { "-nit", FALSE
, etINT
, {&maxnit
},
156 "Max number of iterations" },
157 { "-seed", FALSE
, etINT
, {&seed
},
158 "Random seed for MC steps" },
159 { "-frac", FALSE
, etREAL
, {&frac
},
160 "Maximum fraction by which to change parameters. Actual fraction is random between 0 and this parameter" },
161 { "-pindex", FALSE
, etINT
, {&pindex
},
162 "Index of P[X][X] in the energy file (check with g_energy and subtract 1)" },
163 { "-eindex", FALSE
, etINT
, {&pindex
},
164 "Index of Epot in the energy file (check with g_energy and subtract 1)" },
165 { "-kp", FALSE
, etREAL
, {&kp
},
166 "Force constant for pressure components"},
167 { "-ke", FALSE
, etREAL
, {&ke
},
168 "Force constant for energy component"},
169 { "-kT", FALSE
, etREAL
, {&kT
},
170 "Boltzmann Energy for Monte Carlo" },
171 { "-pscal", FALSE
, etBOOL
, {&bPScal
},
172 "Optimize params for scalar pressure, instead of tensor" }
184 int i
,step
,natoms
,nmol
,nit
,atnr2
;
185 real t
,lambda
,epot
,eFF
[2];
187 bool bConverged
,bAccept
;
190 CopyRight(stdout
,argv
[0]);
191 parse_common_args(&argc
,argv
,0,FALSE
,NFILE
,fnm
,asize(pa
),pa
,
192 asize(desc
),desc
,0,NULL
);
194 /* Read initial topology and coordaintes etc. */
195 read_tpxheader(ftp2fn(efTPX
,NFILE
,fnm
),&sh
);
198 read_tpx(ftp2fn(efTPX
,NFILE
,fnm
),&step
,&t
,&lambda
,&ir
,box
,&natoms
,
201 /* Open log file and print options */
202 fp
= ftp2FILE(efLOG
,NFILE
,fnm
,"w");
203 fprintf(fp
,"%s started with the following parameters\n",argv
[0]);
204 fprintf(fp
,"epot = %8g ke = %8g kp = %8g\n",epot0
,ke
,kp
);
205 fprintf(fp
,"maxnit = %8d tol = %8g seed = %8d\n",maxnit
,tol
,seed
);
206 fprintf(fp
,"frac = %8g pindex = %8d eindex = %8d\n",frac
,pindex
,eindex
);
207 fprintf(fp
,"kT = %8g pscal = %8s\n",kT
,bool_names
[bPScal
]);
209 /* Unpack some topology numbers */
210 nmol
= top
.blocks
[ebMOLS
].nr
;
211 atnr2
= top
.idef
.atnr
*top
.idef
.atnr
;
213 /* Copy input params */
215 snew(ip
[next
],atnr2
);
216 copy_iparams(atnr2
,ip
[cur
],top
.idef
.iparams
);
217 copy_iparams(atnr2
,ip
[next
],top
.idef
.iparams
);
219 /* Loop over iterations */
224 rand_step(fp
,atnr2
,ip
[next
],&seed
,frac
);
225 copy_iparams(atnr2
,top
.idef
.iparams
,ip
[next
]);
227 do_sim(ftp2fn(efENX
,NFILE
,fnm
),&top
,xx
,vv
,&ir
,box
);
229 get_results(ftp2fn(efENX
,NFILE
,fnm
),P
[0],&epot
,pindex
,eindex
);
231 /* Calculate penalty */
232 eFF
[(nit
> 0) ? next
: cur
] = ener(P
,epot
,epot0
,nmol
,kp
,ke
,bPScal
);
234 bConverged
= (eFF
[(nit
> 0) ? next
: cur
] < tol
);
237 /* Do Metropolis criterium */
239 mc_crit
= exp(-(eFF
[next
]-eFF
[cur
])/kT
);
240 bAccept
= ((eFF
[next
] < eFF
[cur
]) ||
241 ((kT
> 0) && (mc_crit
> rando(&seed
))));
242 pr_progress(fp
,nit
,P
,epot
/nmol
,eFF
[next
],mc_crit
,
249 /* Restore old parameters */
250 copy_iparams(atnr2
,ip
[next
],ip
[cur
]);
254 pr_progress(fp
,nit
,P
,epot
/nmol
,eFF
[cur
],mc_crit
,bConverged
,FALSE
);
257 } while (!bConverged
&& (nit
< maxnit
));
259 for(i
=0; (i
<atnr2
); i
++)
260 pr_iparams(fp
,F_LJ
,&ip
[cur
][i
]);