2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5 * Copyright (c) 2001-2004, The GROMACS development team,
6 * check out http://www.gromacs.org for more information.
7 * Copyright (c) 2012, by the GROMACS development team, led by
8 * David van der Spoel, Berk Hess, Erik Lindahl, and including many
9 * others, as listed in the AUTHORS file in the top-level source
10 * directory and at http://www.gromacs.org.
12 * GROMACS is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public License
14 * as published by the Free Software Foundation; either version 2.1
15 * of the License, or (at your option) any later version.
17 * GROMACS is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with GROMACS; if not, see
24 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
25 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 * If you want to redistribute modifications to GROMACS, please
28 * consider that scientific software is very special. Version
29 * control is crucial - bugs must be traceable. We will be happy to
30 * consider code for inclusion in the official distribution, but
31 * derived work must not be called official GROMACS. Details are found
32 * in the README & COPYING files - if they are missing, get the
33 * official version at http://www.gromacs.org.
35 * To help us fund GROMACS development, we humbly ask that you cite
36 * the research papers on the package. Check out http://www.gromacs.org.
53 real mol_dipole(int k0,int k1,rvec x[],real q[])
59 for(k=k0; (k<k1); k++) {
60 for(m=0; (m<DIM); m++)
61 mu[m] += q[k]*x[k][m];
63 return norm(mu); /* Dipole moment of this molecule in e nm */
66 real calc_mu_aver(t_commrec *cr,rvec x[],real q[],rvec mu,
67 t_block *mols,t_mdatoms *md,int gnx,atom_id grpindex[])
73 end = md->homenr + start;
77 for(i=start; (i<end); i++)
78 for(m=0; (m<DIM); m++)
79 mu[m] += q[i]*x[i][m];
84 /* I guess we have to parallelise this one! */
88 for(i=0; (i<gnx); i++) {
90 mu_ave += mol_dipole(mols->index[gi],mols->index[gi+1],x,q);
99 /* Lots of global variables! Yummy... */
102 void set_ffvars(t_ffscan *fff)
107 real cost(tensor P,real MSF,real E)
109 return (ff.fac_msf*MSF+ff.fac_epot*sqr(E-ff.epot)+ff.fac_pres*
110 (sqr(P[XX][XX]-ff.pres)+sqr(P[YY][YY]-ff.pres)+sqr(P[ZZ][ZZ]-ff.pres)));
114 static const char *esenm[eseNR] = { "SIG", "EPS", "BHAMA", "BHAMB", "BHAMC", "CELlX", "CELLY", "CELLZ" };
115 static int nparm=0,*param_val=NULL;
116 static t_range *range=NULL;
117 static t_genalg *ga=NULL;
118 static rvec scale = { 1,1,1 };
120 static void init_range(t_range *r,int np,int atype,int ptype,
124 gmx_fatal(FARGS,"rmin (%f) > rmax (%f)",rmin,rmax);
126 gmx_fatal(FARGS,"np (%d) should be > 0",np);
127 if ((rmax > rmin) && (np <= 1))
128 gmx_fatal(FARGS,"If rmax > rmin, np should be > 1");
129 if ((ptype < 0) || (ptype >= eseNR))
130 gmx_fatal(FARGS,"ptype (%d) should be < %d",ptype,eseNR);
137 r->dr = r->rmax - r->rmin;
140 static t_range *read_range(const char *db,int *nrange)
148 nlines = get_file(db,&lines);
152 for(i=0; (i < nlines); i++) {
153 strip_comment(lines[i]);
154 if (sscanf(lines[i],"%d%d%d%lf%lf",&np,&atype,&ptype,&rmin,&rmax) == 5) {
155 if (ff.bLogEps && (ptype == eseEPSILON) && (rmin <= 0))
156 gmx_fatal(FARGS,"When using logarithmic epsilon increments the minimum"
157 "value must be > 0");
158 init_range(&range[nr],np,atype,ptype,rmin,rmax);
162 fprintf(stderr,"found %d variables to iterate over\n",nr);
166 for(nr=0; (nr < nlines); nr++)
173 static real value_range(t_range *r,int n)
175 real logrmin,logrmax;
177 if ((n < 0) || (n > r->np))
178 gmx_fatal(FARGS,"Value (%d) out of range for value_range (max %d)",n,r->np);
183 if ((r->ptype == eseEPSILON) && ff.bLogEps) {
184 logrmin = log(r->rmin);
185 logrmax = log(r->rmax);
186 r->rval = exp(logrmin + (n*(logrmax-logrmin))/(r->np-1));
189 r->rval = r->rmin+(n*(r->dr))/(r->np-1);
194 real value_rand(t_range *r,int *seed)
196 real logrmin,logrmax;
203 if ((r->ptype == eseEPSILON) && ff.bLogEps) {
204 logrmin = log(r->rmin);
205 logrmax = log(r->rmax);
206 r->rval = exp(logrmin + mr*(logrmax-logrmin));
209 r->rval = r->rmin + mr*(r->rmax-r->rmin);
212 fprintf(debug,"type: %s, value: %g\n",esenm[r->ptype],r->rval);
216 static void update_ff(t_forcerec *fr,int nparm,t_range range[],int param_val[])
218 static double *sigma=NULL,*eps=NULL,*c6=NULL,*cn=NULL,*bhama=NULL,*bhamb=NULL,*bhamc=NULL;
227 assert(bhamb==NULL && bhamc==NULL);
235 assert(eps==NULL && c6==NULL && cn==NULL);
242 /* Get current values for everything */
243 for(i=0; (i<nparm); i++) {
247 val = value_range(&range[i],param_val[i]);
249 fprintf(debug,"val = %g\n",val);
250 switch (range[i].ptype) {
253 sigma[range[i].atype] = val;
257 eps[range[i].atype] = val;
261 bhama[range[i].atype] = val;
265 bhamb[range[i].atype] = val;
269 bhamc[range[i].atype] = val;
281 gmx_fatal(FARGS,"Unknown ptype");
285 for(i=0; (i<atnr); i++) {
286 for(j=0; (j<=i); j++) {
287 BHAMA(nbfp,atnr,i,j) = BHAMA(nbfp,atnr,j,i) = sqrt(bhama[i]*bhama[j]);
288 BHAMB(nbfp,atnr,i,j) = BHAMB(nbfp,atnr,j,i) = sqrt(bhamb[i]*bhamb[j]);
289 BHAMC(nbfp,atnr,i,j) = BHAMC(nbfp,atnr,j,i) = sqrt(bhamc[i]*bhamc[j]);
294 /* Now build a new matrix */
295 for(i=0; (i<atnr); i++) {
296 c6[i] = 4*eps[i]*pow(sigma[i],6.0);
297 cn[i] = 4*eps[i]*pow(sigma[i],ff.npow);
299 for(i=0; (i<atnr); i++) {
300 for(j=0; (j<=i); j++) {
301 C6(nbfp,atnr,i,j) = C6(nbfp,atnr,j,i) = sqrt(c6[i]*c6[j]);
302 C12(nbfp,atnr,i,j) = C12(nbfp,atnr,j,i) = sqrt(cn[i]*cn[j]);
309 for(i=0; (i<atnr); i++)
310 fprintf(debug,"atnr = %2d sigma = %8.4f eps = %8.4f\n",i,sigma[i],eps[i]);
311 for(i=0; (i<atnr); i++) {
312 for(j=0; (j<atnr); j++) {
314 fprintf(debug,"i: %2d j: %2d A: %10.5e B: %10.5e C: %10.5e\n",i,j,
315 BHAMA(nbfp,atnr,i,j),BHAMB(nbfp,atnr,i,j),BHAMC(nbfp,atnr,i,j));
317 fprintf(debug,"i: %2d j: %2d c6: %10.5e cn: %10.5e\n",i,j,
318 C6(nbfp,atnr,i,j),C12(nbfp,atnr,i,j));
324 static void scale_box(int natoms,rvec x[],matrix box)
328 if ((scale[XX] != 1.0) || (scale[YY] != 1.0) || (scale[ZZ] != 1.0)) {
330 fprintf(debug,"scale = %8.4f %8.4f %8.4f\n",
331 scale[XX],scale[YY],scale[ZZ]);
332 for(m=0; (m<DIM); m++)
333 box[m][m] *= scale[m];
334 for(i=0; (i<natoms); i++)
335 for(m=0; (m<DIM); m++)
340 gmx_bool update_forcefield(FILE *fplog,
341 int nfile,const t_filenm fnm[],t_forcerec *fr,
342 int natoms,rvec x[],matrix box)
344 static int ntry,ntried;
348 /* First time around we have to read the parameters */
350 range = read_range(ftp2fn(efDAT,nfile,fnm),&nparm);
352 gmx_fatal(FARGS,"No correct parameter info in %s",ftp2fn(efDAT,nfile,fnm));
353 snew(param_val,nparm);
355 if (opt2bSet("-ga",nfile,fnm)) {
356 /* Genetic algorithm time */
357 ga = init_ga(fplog,opt2fn("-ga",nfile,fnm),nparm,range);
360 /* Determine the grid size */
362 for(i=0; (i<nparm); i++)
366 fprintf(fplog,"Going to try %d different combinations of %d parameters\n",
371 update_ga(fplog,range,ga);
374 /* Increment the counter
375 * Non-trivial, since this is nparm nested loops in principle
377 for(i=0; (i<nparm); i++) {
378 if (param_val[i] < (range[i].np-1)) {
387 fprintf(fplog,"Finished with %d out of %d iterations\n",ntried+1,ntry);
392 /* Now do the real updating */
393 update_ff(fr,nparm,range,param_val);
395 /* Update box and coordinates if necessary */
396 scale_box(natoms,x,box);
401 static void print_range(FILE *fp,tensor P,real MSF,real energy)
405 fprintf(fp,"%8.3f %8.3f %8.3f %8.3f",
406 cost(P,MSF,energy),trace(P)/3,MSF,energy);
407 for(i=0; (i<nparm); i++)
408 fprintf(fp," %s %10g",esenm[range[i].ptype],range[i].rval);
413 static real msf(int n,rvec f1[],rvec f2[])
421 for(j=0; ((j<ff.molsize) && (i<n)); j++,i++) {
426 msf1 += iprod(ff2,ff2);
432 static void print_grid(FILE *fp,real ener[],int natoms,rvec f[],rvec fshake[],
433 rvec x[],t_block *mols,real mass[],tensor pres)
435 static gmx_bool bFirst = TRUE;
436 static const char *desc[] = {
437 "------------------------------------------------------------------------",
438 "In the output from the forcefield scan we have the potential energy,",
439 "then the root mean square force on the atoms, and finally the parameters",
440 "in the order they appear in the input file.",
441 "------------------------------------------------------------------------"
447 for(i=0; (i<asize(desc)); i++)
448 fprintf(fp,"%s\n",desc[i]);
452 if ((ff.tol == 0) || (fabs(ener[F_EPOT]/ff.nmol-ff.epot) < ff.tol)) {
453 msf1 = msf(natoms,f,fshake);
454 if ((ff.f_max == 0) || (msf1 < sqr(ff.f_max)))
455 print_range(fp,pres,msf1,ener[F_EPOT]/ff.nmol);
459 gmx_bool print_forcefield(FILE *fp,real ener[],int natoms,rvec f[],rvec fshake[],
460 rvec x[],t_block *mols,real mass[],tensor pres)
465 msf1 = msf(natoms,f,fshake);
467 fprintf(fp,"Pressure: %12g, RMSF: %12g, Energy-Epot: %12g, cost: %12g\n",
468 ener[F_PRES],sqrt(msf1),ener[F_EPOT]/ff.nmol-ff.epot,
469 cost(pres,msf1,ener[F_EPOT]/ff.nmol));
470 if (print_ga(fp,ga,msf1,pres,scale,(ener[F_EPOT]/ff.nmol),range,ff.tol)) {
476 print_grid(fp,ener,natoms,f,fshake,x,mols,mass,pres);