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
51 real mol_dipole(int k0, int k1, rvec x[], real q[])
57 for (k = k0; (k < k1); k++)
59 for (m = 0; (m < DIM); m++)
61 mu[m] += q[k]*x[k][m];
64 return norm(mu); /* Dipole moment of this molecule in e nm */
67 real calc_mu_aver(t_commrec *cr, rvec x[], real q[], rvec mu,
68 t_block *mols, t_mdatoms *md, int gnx, atom_id grpindex[])
74 end = md->homenr + start;
78 for(i=start; (i<end); i++)
79 for(m=0; (m<DIM); m++)
80 mu[m] += q[i]*x[i][m];
85 /* I guess we have to parallelise this one! */
90 for (i = 0; (i < gnx); i++)
93 mu_ave += mol_dipole(mols->index[gi], mols->index[gi+1], x, q);
104 /* Lots of global variables! Yummy... */
107 void set_ffvars(t_ffscan *fff)
112 real cost(tensor P, real MSF, real E)
114 return (ff.fac_msf*MSF+ff.fac_epot*sqr(E-ff.epot)+ff.fac_pres*
115 (sqr(P[XX][XX]-ff.pres)+sqr(P[YY][YY]-ff.pres)+sqr(P[ZZ][ZZ]-ff.pres)));
119 static const char *esenm[eseNR] = { "SIG", "EPS", "BHAMA", "BHAMB", "BHAMC", "CELlX", "CELLY", "CELLZ" };
120 static int nparm = 0, *param_val = NULL;
121 static t_range *range = NULL;
122 static t_genalg *ga = NULL;
123 static rvec scale = { 1, 1, 1 };
125 static void init_range(t_range *r, int np, int atype, int ptype,
126 real rmin, real rmax)
130 gmx_fatal(FARGS, "rmin (%f) > rmax (%f)", rmin, rmax);
134 gmx_fatal(FARGS, "np (%d) should be > 0", np);
136 if ((rmax > rmin) && (np <= 1))
138 gmx_fatal(FARGS, "If rmax > rmin, np should be > 1");
140 if ((ptype < 0) || (ptype >= eseNR))
142 gmx_fatal(FARGS, "ptype (%d) should be < %d", ptype, eseNR);
150 r->dr = r->rmax - r->rmin;
153 static t_range *read_range(const char *db, int *nrange)
155 int nlines, nr, np, i;
161 nlines = get_file(db, &lines);
165 for (i = 0; (i < nlines); i++)
167 strip_comment(lines[i]);
168 if (sscanf(lines[i], "%d%d%d%lf%lf", &np, &atype, &ptype, &rmin, &rmax) == 5)
170 if (ff.bLogEps && (ptype == eseEPSILON) && (rmin <= 0))
172 gmx_fatal(FARGS, "When using logarithmic epsilon increments the minimum"
173 "value must be > 0");
175 init_range(&range[nr], np, atype, ptype, rmin, rmax);
179 fprintf(stderr, "found %d variables to iterate over\n", nr);
183 for (nr = 0; (nr < nlines); nr++)
192 static real value_range(t_range *r, int n)
194 real logrmin, logrmax;
196 if ((n < 0) || (n > r->np))
198 gmx_fatal(FARGS, "Value (%d) out of range for value_range (max %d)", n, r->np);
207 if ((r->ptype == eseEPSILON) && ff.bLogEps)
209 logrmin = log(r->rmin);
210 logrmax = log(r->rmax);
211 r->rval = exp(logrmin + (n*(logrmax-logrmin))/(r->np-1));
215 r->rval = r->rmin+(n*(r->dr))/(r->np-1);
221 real value_rand(t_range *r, int *seed)
223 real logrmin, logrmax;
233 if ((r->ptype == eseEPSILON) && ff.bLogEps)
235 logrmin = log(r->rmin);
236 logrmax = log(r->rmax);
237 r->rval = exp(logrmin + mr*(logrmax-logrmin));
241 r->rval = r->rmin + mr*(r->rmax-r->rmin);
246 fprintf(debug, "type: %s, value: %g\n", esenm[r->ptype], r->rval);
251 static void update_ff(t_forcerec *fr, int nparm, t_range range[], int param_val[])
253 static double *sigma = NULL, *eps = NULL, *c6 = NULL, *cn = NULL, *bhama = NULL, *bhamb = NULL, *bhamc = NULL;
264 assert(bhamb == NULL && bhamc == NULL);
274 assert(eps == NULL && c6 == NULL && cn == NULL);
281 /* Get current values for everything */
282 for (i = 0; (i < nparm); i++)
290 val = value_range(&range[i], param_val[i]);
294 fprintf(debug, "val = %g\n", val);
296 switch (range[i].ptype)
300 sigma[range[i].atype] = val;
304 eps[range[i].atype] = val;
308 bhama[range[i].atype] = val;
312 bhamb[range[i].atype] = val;
316 bhamc[range[i].atype] = val;
328 gmx_fatal(FARGS, "Unknown ptype");
333 for (i = 0; (i < atnr); i++)
335 for (j = 0; (j <= i); j++)
337 BHAMA(nbfp, atnr, i, j) = BHAMA(nbfp, atnr, j, i) = sqrt(bhama[i]*bhama[j]);
338 BHAMB(nbfp, atnr, i, j) = BHAMB(nbfp, atnr, j, i) = sqrt(bhamb[i]*bhamb[j]);
339 BHAMC(nbfp, atnr, i, j) = BHAMC(nbfp, atnr, j, i) = sqrt(bhamc[i]*bhamc[j]);
345 /* Now build a new matrix */
346 for (i = 0; (i < atnr); i++)
348 c6[i] = 4*eps[i]*pow(sigma[i], 6.0);
349 cn[i] = 4*eps[i]*pow(sigma[i], ff.npow);
351 for (i = 0; (i < atnr); i++)
353 for (j = 0; (j <= i); j++)
355 C6(nbfp, atnr, i, j) = C6(nbfp, atnr, j, i) = sqrt(c6[i]*c6[j]);
356 C12(nbfp, atnr, i, j) = C12(nbfp, atnr, j, i) = sqrt(cn[i]*cn[j]);
365 for (i = 0; (i < atnr); i++)
367 fprintf(debug, "atnr = %2d sigma = %8.4f eps = %8.4f\n", i, sigma[i], eps[i]);
370 for (i = 0; (i < atnr); i++)
372 for (j = 0; (j < atnr); j++)
376 fprintf(debug, "i: %2d j: %2d A: %10.5e B: %10.5e C: %10.5e\n", i, j,
377 BHAMA(nbfp, atnr, i, j), BHAMB(nbfp, atnr, i, j), BHAMC(nbfp, atnr, i, j));
381 fprintf(debug, "i: %2d j: %2d c6: %10.5e cn: %10.5e\n", i, j,
382 C6(nbfp, atnr, i, j), C12(nbfp, atnr, i, j));
389 static void scale_box(int natoms, rvec x[], matrix box)
393 if ((scale[XX] != 1.0) || (scale[YY] != 1.0) || (scale[ZZ] != 1.0))
397 fprintf(debug, "scale = %8.4f %8.4f %8.4f\n",
398 scale[XX], scale[YY], scale[ZZ]);
400 for (m = 0; (m < DIM); m++)
402 box[m][m] *= scale[m];
404 for (i = 0; (i < natoms); i++)
406 for (m = 0; (m < DIM); m++)
414 gmx_bool update_forcefield(FILE *fplog,
415 int nfile, const t_filenm fnm[], t_forcerec *fr,
416 int natoms, rvec x[], matrix box)
418 static int ntry, ntried;
422 /* First time around we have to read the parameters */
425 range = read_range(ftp2fn(efDAT, nfile, fnm), &nparm);
428 gmx_fatal(FARGS, "No correct parameter info in %s", ftp2fn(efDAT, nfile, fnm));
430 snew(param_val, nparm);
432 if (opt2bSet("-ga", nfile, fnm))
434 /* Genetic algorithm time */
435 ga = init_ga(fplog, opt2fn("-ga", nfile, fnm), nparm, range);
439 /* Determine the grid size */
441 for (i = 0; (i < nparm); i++)
447 fprintf(fplog, "Going to try %d different combinations of %d parameters\n",
453 update_ga(fplog, range, ga);
457 /* Increment the counter
458 * Non-trivial, since this is nparm nested loops in principle
460 for (i = 0; (i < nparm); i++)
462 if (param_val[i] < (range[i].np-1))
465 for (j = 0; (j < i); j++)
475 fprintf(fplog, "Finished with %d out of %d iterations\n", ntried+1, ntry);
480 /* Now do the real updating */
481 update_ff(fr, nparm, range, param_val);
483 /* Update box and coordinates if necessary */
484 scale_box(natoms, x, box);
489 static void print_range(FILE *fp, tensor P, real MSF, real energy)
493 fprintf(fp, "%8.3f %8.3f %8.3f %8.3f",
494 cost(P, MSF, energy), trace(P)/3, MSF, energy);
495 for (i = 0; (i < nparm); i++)
497 fprintf(fp, " %s %10g", esenm[range[i].ptype], range[i].rval);
499 fprintf(fp, " FF\n");
503 static real msf(int n, rvec f1[], rvec f2[])
509 for (i = 0; (i < n); )
512 for (j = 0; ((j < ff.molsize) && (i < n)); j++, i++)
514 rvec_inc(ff2, f1[i]);
517 rvec_inc(ff2, f2[i]);
520 msf1 += iprod(ff2, ff2);
526 static void print_grid(FILE *fp, real ener[], int natoms, rvec f[], rvec fshake[],
527 rvec x[], t_block *mols, real mass[], tensor pres)
529 static gmx_bool bFirst = TRUE;
530 static const char *desc[] = {
531 "------------------------------------------------------------------------",
532 "In the output from the forcefield scan we have the potential energy,",
533 "then the root mean square force on the atoms, and finally the parameters",
534 "in the order they appear in the input file.",
535 "------------------------------------------------------------------------"
542 for (i = 0; (i < asize(desc)); i++)
544 fprintf(fp, "%s\n", desc[i]);
549 if ((ff.tol == 0) || (fabs(ener[F_EPOT]/ff.nmol-ff.epot) < ff.tol))
551 msf1 = msf(natoms, f, fshake);
552 if ((ff.f_max == 0) || (msf1 < sqr(ff.f_max)))
554 print_range(fp, pres, msf1, ener[F_EPOT]/ff.nmol);
559 gmx_bool print_forcefield(FILE *fp, real ener[], int natoms, rvec f[], rvec fshake[],
560 rvec x[], t_block *mols, real mass[], tensor pres)
566 msf1 = msf(natoms, f, fshake);
569 fprintf(fp, "Pressure: %12g, RMSF: %12g, Energy-Epot: %12g, cost: %12g\n",
570 ener[F_PRES], sqrt(msf1), ener[F_EPOT]/ff.nmol-ff.epot,
571 cost(pres, msf1, ener[F_EPOT]/ff.nmol));
573 if (print_ga(fp, ga, msf1, pres, scale, (ener[F_EPOT]/ff.nmol), range, ff.tol))
581 print_grid(fp, ener, natoms, f, fshake, x, mols, mass, pres);