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-2004, 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 * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
50 real mol_dipole(int k0,int k1,rvec x[],real q[])
56 for(k=k0; (k<k1); k++) {
57 for(m=0; (m<DIM); m++)
58 mu[m] += q[k]*x[k][m];
60 return norm(mu); /* Dipole moment of this molecule in e nm */
63 real calc_mu_aver(t_commrec *cr,rvec x[],real q[],rvec mu,
64 t_block *mols,t_mdatoms *md,int gnx,atom_id grpindex[])
70 end = md->homenr + start;
74 for(i=start; (i<end); i++)
75 for(m=0; (m<DIM); m++)
76 mu[m] += q[i]*x[i][m];
81 /* I guess we have to parallelise this one! */
85 for(i=0; (i<gnx); i++) {
87 mu_ave += mol_dipole(mols->index[gi],mols->index[gi+1],x,q);
96 /* Lots of global variables! Yummy... */
99 void set_ffvars(t_ffscan *fff)
104 real cost(tensor P,real MSF,real E)
106 return (ff.fac_msf*MSF+ff.fac_epot*sqr(E-ff.epot)+ff.fac_pres*
107 (sqr(P[XX][XX]-ff.pres)+sqr(P[YY][YY]-ff.pres)+sqr(P[ZZ][ZZ]-ff.pres)));
111 static const char *esenm[eseNR] = { "SIG", "EPS", "BHAMA", "BHAMB", "BHAMC", "CELlX", "CELLY", "CELLZ" };
112 static int nparm=0,*param_val=NULL;
113 static t_range *range=NULL;
114 static t_genalg *ga=NULL;
115 static rvec scale = { 1,1,1 };
117 static void init_range(t_range *r,int np,int atype,int ptype,
121 gmx_fatal(FARGS,"rmin (%f) > rmax (%f)",rmin,rmax);
123 gmx_fatal(FARGS,"np (%d) should be > 0",np);
124 if ((rmax > rmin) && (np <= 1))
125 gmx_fatal(FARGS,"If rmax > rmin, np should be > 1");
126 if ((ptype < 0) || (ptype >= eseNR))
127 gmx_fatal(FARGS,"ptype (%d) should be < %d",ptype,eseNR);
134 r->dr = r->rmax - r->rmin;
137 static t_range *read_range(const char *db,int *nrange)
145 nlines = get_file(db,&lines);
149 for(i=0; (i < nlines); i++) {
150 strip_comment(lines[i]);
151 if (sscanf(lines[i],"%d%d%d%lf%lf",&np,&atype,&ptype,&rmin,&rmax) == 5) {
152 if (ff.bLogEps && (ptype == eseEPSILON) && (rmin <= 0))
153 gmx_fatal(FARGS,"When using logarithmic epsilon increments the minimum"
154 "value must be > 0");
155 init_range(&range[nr],np,atype,ptype,rmin,rmax);
159 fprintf(stderr,"found %d variables to iterate over\n",nr);
163 for(nr=0; (nr < nlines); nr++)
170 static real value_range(t_range *r,int n)
172 real logrmin,logrmax;
174 if ((n < 0) || (n > r->np))
175 gmx_fatal(FARGS,"Value (%d) out of range for value_range (max %d)",n,r->np);
180 if ((r->ptype == eseEPSILON) && ff.bLogEps) {
181 logrmin = log(r->rmin);
182 logrmax = log(r->rmax);
183 r->rval = exp(logrmin + (n*(logrmax-logrmin))/(r->np-1));
186 r->rval = r->rmin+(n*(r->dr))/(r->np-1);
191 real value_rand(t_range *r,int *seed)
193 real logrmin,logrmax;
200 if ((r->ptype == eseEPSILON) && ff.bLogEps) {
201 logrmin = log(r->rmin);
202 logrmax = log(r->rmax);
203 r->rval = exp(logrmin + mr*(logrmax-logrmin));
206 r->rval = r->rmin + mr*(r->rmax-r->rmin);
209 fprintf(debug,"type: %s, value: %g\n",esenm[r->ptype],r->rval);
213 static void update_ff(t_forcerec *fr,int nparm,t_range range[],int param_val[])
215 static double *sigma=NULL,*eps=NULL,*c6=NULL,*cn=NULL,*bhama=NULL,*bhamb=NULL,*bhamc=NULL;
224 assert(bhamb==NULL && bhamc==NULL);
232 assert(eps==NULL && c6==NULL && cn==NULL);
239 /* Get current values for everything */
240 for(i=0; (i<nparm); i++) {
244 val = value_range(&range[i],param_val[i]);
246 fprintf(debug,"val = %g\n",val);
247 switch (range[i].ptype) {
250 sigma[range[i].atype] = val;
254 eps[range[i].atype] = val;
258 bhama[range[i].atype] = val;
262 bhamb[range[i].atype] = val;
266 bhamc[range[i].atype] = val;
278 gmx_fatal(FARGS,"Unknown ptype");
282 for(i=0; (i<atnr); i++) {
283 for(j=0; (j<=i); j++) {
284 BHAMA(nbfp,atnr,i,j) = BHAMA(nbfp,atnr,j,i) = sqrt(bhama[i]*bhama[j]);
285 BHAMB(nbfp,atnr,i,j) = BHAMB(nbfp,atnr,j,i) = sqrt(bhamb[i]*bhamb[j]);
286 BHAMC(nbfp,atnr,i,j) = BHAMC(nbfp,atnr,j,i) = sqrt(bhamc[i]*bhamc[j]);
291 /* Now build a new matrix */
292 for(i=0; (i<atnr); i++) {
293 c6[i] = 4*eps[i]*pow(sigma[i],6.0);
294 cn[i] = 4*eps[i]*pow(sigma[i],ff.npow);
296 for(i=0; (i<atnr); i++) {
297 for(j=0; (j<=i); j++) {
298 C6(nbfp,atnr,i,j) = C6(nbfp,atnr,j,i) = sqrt(c6[i]*c6[j]);
299 C12(nbfp,atnr,i,j) = C12(nbfp,atnr,j,i) = sqrt(cn[i]*cn[j]);
306 for(i=0; (i<atnr); i++)
307 fprintf(debug,"atnr = %2d sigma = %8.4f eps = %8.4f\n",i,sigma[i],eps[i]);
308 for(i=0; (i<atnr); i++) {
309 for(j=0; (j<atnr); j++) {
311 fprintf(debug,"i: %2d j: %2d A: %10.5e B: %10.5e C: %10.5e\n",i,j,
312 BHAMA(nbfp,atnr,i,j),BHAMB(nbfp,atnr,i,j),BHAMC(nbfp,atnr,i,j));
314 fprintf(debug,"i: %2d j: %2d c6: %10.5e cn: %10.5e\n",i,j,
315 C6(nbfp,atnr,i,j),C12(nbfp,atnr,i,j));
321 static void scale_box(int natoms,rvec x[],matrix box)
325 if ((scale[XX] != 1.0) || (scale[YY] != 1.0) || (scale[ZZ] != 1.0)) {
327 fprintf(debug,"scale = %8.4f %8.4f %8.4f\n",
328 scale[XX],scale[YY],scale[ZZ]);
329 for(m=0; (m<DIM); m++)
330 box[m][m] *= scale[m];
331 for(i=0; (i<natoms); i++)
332 for(m=0; (m<DIM); m++)
337 gmx_bool update_forcefield(FILE *fplog,
338 int nfile,const t_filenm fnm[],t_forcerec *fr,
339 int natoms,rvec x[],matrix box)
341 static int ntry,ntried;
345 /* First time around we have to read the parameters */
347 range = read_range(ftp2fn(efDAT,nfile,fnm),&nparm);
349 gmx_fatal(FARGS,"No correct parameter info in %s",ftp2fn(efDAT,nfile,fnm));
350 snew(param_val,nparm);
352 if (opt2bSet("-ga",nfile,fnm)) {
353 /* Genetic algorithm time */
354 ga = init_ga(fplog,opt2fn("-ga",nfile,fnm),nparm,range);
357 /* Determine the grid size */
359 for(i=0; (i<nparm); i++)
363 fprintf(fplog,"Going to try %d different combinations of %d parameters\n",
368 update_ga(fplog,range,ga);
371 /* Increment the counter
372 * Non-trivial, since this is nparm nested loops in principle
374 for(i=0; (i<nparm); i++) {
375 if (param_val[i] < (range[i].np-1)) {
384 fprintf(fplog,"Finished with %d out of %d iterations\n",ntried+1,ntry);
389 /* Now do the real updating */
390 update_ff(fr,nparm,range,param_val);
392 /* Update box and coordinates if necessary */
393 scale_box(natoms,x,box);
398 static void print_range(FILE *fp,tensor P,real MSF,real energy)
402 fprintf(fp,"%8.3f %8.3f %8.3f %8.3f",
403 cost(P,MSF,energy),trace(P)/3,MSF,energy);
404 for(i=0; (i<nparm); i++)
405 fprintf(fp," %s %10g",esenm[range[i].ptype],range[i].rval);
410 static real msf(int n,rvec f1[],rvec f2[])
418 for(j=0; ((j<ff.molsize) && (i<n)); j++,i++) {
423 msf1 += iprod(ff2,ff2);
429 static void print_grid(FILE *fp,real ener[],int natoms,rvec f[],rvec fshake[],
430 rvec x[],t_block *mols,real mass[],tensor pres)
432 static gmx_bool bFirst = TRUE;
433 static const char *desc[] = {
434 "------------------------------------------------------------------------",
435 "In the output from the forcefield scan we have the potential energy,",
436 "then the root mean square force on the atoms, and finally the parameters",
437 "in the order they appear in the input file.",
438 "------------------------------------------------------------------------"
444 for(i=0; (i<asize(desc)); i++)
445 fprintf(fp,"%s\n",desc[i]);
449 if ((ff.tol == 0) || (fabs(ener[F_EPOT]/ff.nmol-ff.epot) < ff.tol)) {
450 msf1 = msf(natoms,f,fshake);
451 if ((ff.f_max == 0) || (msf1 < sqr(ff.f_max)))
452 print_range(fp,pres,msf1,ener[F_EPOT]/ff.nmol);
456 gmx_bool print_forcefield(FILE *fp,real ener[],int natoms,rvec f[],rvec fshake[],
457 rvec x[],t_block *mols,real mass[],tensor pres)
462 msf1 = msf(natoms,f,fshake);
464 fprintf(fp,"Pressure: %12g, RMSF: %12g, Energy-Epot: %12g, cost: %12g\n",
465 ener[F_PRES],sqrt(msf1),ener[F_EPOT]/ff.nmol-ff.epot,
466 cost(pres,msf1,ener[F_EPOT]/ff.nmol));
467 if (print_ga(fp,ga,msf1,pres,scale,(ener[F_EPOT]/ff.nmol),range,ff.tol)) {
473 print_grid(fp,ener,natoms,f,fshake,x,mols,mass,pres);