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
48 real
mol_dipole(int k0
,int k1
,rvec x
[],real q
[])
54 for(k
=k0
; (k
<k1
); k
++) {
55 for(m
=0; (m
<DIM
); m
++)
56 mu
[m
] += q
[k
]*x
[k
][m
];
58 return norm(mu
); /* Dipole moment of this molecule in e nm */
61 real
calc_mu_aver(t_commrec
*cr
,rvec x
[],real q
[],rvec mu
,
62 t_block
*mols
,t_mdatoms
*md
,int gnx
,atom_id grpindex
[])
68 end
= md
->homenr
+ start
;
72 for(i=start; (i<end); i++)
73 for(m=0; (m<DIM); m++)
74 mu[m] += q[i]*x[i][m];
79 /* I guess we have to parallelise this one! */
83 for(i
=0; (i
<gnx
); i
++) {
85 mu_ave
+= mol_dipole(mols
->index
[gi
],mols
->index
[gi
+1],x
,q
);
94 /* Lots of global variables! Yummy... */
97 void set_ffvars(t_ffscan
*fff
)
102 real
cost(tensor P
,real MSF
,real E
)
104 return (ff
.fac_msf
*MSF
+ff
.fac_epot
*sqr(E
-ff
.epot
)+ff
.fac_pres
*
105 (sqr(P
[XX
][XX
]-ff
.pres
)+sqr(P
[YY
][YY
]-ff
.pres
)+sqr(P
[ZZ
][ZZ
]-ff
.pres
)));
109 static const char *esenm
[eseNR
] = { "SIG", "EPS", "BHAMA", "BHAMB", "BHAMC", "CELlX", "CELLY", "CELLZ" };
110 static int nparm
=0,*param_val
=NULL
;
111 static t_range
*range
=NULL
;
112 static t_genalg
*ga
=NULL
;
113 static rvec scale
= { 1,1,1 };
115 static void init_range(t_range
*r
,int np
,int atype
,int ptype
,
119 gmx_fatal(FARGS
,"rmin (%f) > rmax (%f)",rmin
,rmax
);
121 gmx_fatal(FARGS
,"np (%d) should be > 0",np
);
122 if ((rmax
> rmin
) && (np
<= 1))
123 gmx_fatal(FARGS
,"If rmax > rmin, np should be > 1");
124 if ((ptype
< 0) || (ptype
>= eseNR
))
125 gmx_fatal(FARGS
,"ptype (%d) should be < %d",ptype
,eseNR
);
132 r
->dr
= r
->rmax
- r
->rmin
;
135 static t_range
*read_range(const char *db
,int *nrange
)
143 nlines
= get_file(db
,&lines
);
147 for(i
=0; (i
< nlines
); i
++) {
148 strip_comment(lines
[i
]);
149 if (sscanf(lines
[i
],"%d%d%d%lf%lf",&np
,&atype
,&ptype
,&rmin
,&rmax
) == 5) {
150 if (ff
.bLogEps
&& (ptype
== eseEPSILON
) && (rmin
<= 0))
151 gmx_fatal(FARGS
,"When using logarithmic epsilon increments the minimum"
152 "value must be > 0");
153 init_range(&range
[nr
],np
,atype
,ptype
,rmin
,rmax
);
157 fprintf(stderr
,"found %d variables to iterate over\n",nr
);
161 for(nr
=0; (nr
< nlines
); nr
++)
168 static real
value_range(t_range
*r
,int n
)
170 real logrmin
,logrmax
;
172 if ((n
< 0) || (n
> r
->np
))
173 gmx_fatal(FARGS
,"Value (%d) out of range for value_range (max %d)",n
,r
->np
);
178 if ((r
->ptype
== eseEPSILON
) && ff
.bLogEps
) {
179 logrmin
= log(r
->rmin
);
180 logrmax
= log(r
->rmax
);
181 r
->rval
= exp(logrmin
+ (n
*(logrmax
-logrmin
))/(r
->np
-1));
184 r
->rval
= r
->rmin
+(n
*(r
->dr
))/(r
->np
-1);
189 real
value_rand(t_range
*r
,int *seed
)
191 real logrmin
,logrmax
;
198 if ((r
->ptype
== eseEPSILON
) && ff
.bLogEps
) {
199 logrmin
= log(r
->rmin
);
200 logrmax
= log(r
->rmax
);
201 r
->rval
= exp(logrmin
+ mr
*(logrmax
-logrmin
));
204 r
->rval
= r
->rmin
+ mr
*(r
->rmax
-r
->rmin
);
207 fprintf(debug
,"type: %s, value: %g\n",esenm
[r
->ptype
],r
->rval
);
211 static void update_ff(t_forcerec
*fr
,int nparm
,t_range range
[],int param_val
[])
213 static double *sigma
=NULL
,*eps
=NULL
,*c6
=NULL
,*cn
=NULL
,*bhama
=NULL
,*bhamb
=NULL
,*bhamc
=NULL
;
235 /* Get current values for everything */
236 for(i
=0; (i
<nparm
); i
++) {
240 val
= value_range(&range
[i
],param_val
[i
]);
242 fprintf(debug
,"val = %g\n",val
);
243 switch (range
[i
].ptype
) {
245 sigma
[range
[i
].atype
] = val
;
248 eps
[range
[i
].atype
] = val
;
251 bhama
[range
[i
].atype
] = val
;
254 bhamb
[range
[i
].atype
] = val
;
257 bhamc
[range
[i
].atype
] = val
;
269 gmx_fatal(FARGS
,"Unknown ptype");
273 for(i
=0; (i
<atnr
); i
++) {
274 for(j
=0; (j
<=i
); j
++) {
275 BHAMA(nbfp
,atnr
,i
,j
) = BHAMA(nbfp
,atnr
,j
,i
) = sqrt(bhama
[i
]*bhama
[j
]);
276 BHAMB(nbfp
,atnr
,i
,j
) = BHAMB(nbfp
,atnr
,j
,i
) = sqrt(bhamb
[i
]*bhamb
[j
]);
277 BHAMC(nbfp
,atnr
,i
,j
) = BHAMC(nbfp
,atnr
,j
,i
) = sqrt(bhamc
[i
]*bhamc
[j
]);
282 /* Now build a new matrix */
283 for(i
=0; (i
<atnr
); i
++) {
284 c6
[i
] = 4*eps
[i
]*pow(sigma
[i
],6.0);
285 cn
[i
] = 4*eps
[i
]*pow(sigma
[i
],ff
.npow
);
287 for(i
=0; (i
<atnr
); i
++) {
288 for(j
=0; (j
<=i
); j
++) {
289 C6(nbfp
,atnr
,i
,j
) = C6(nbfp
,atnr
,j
,i
) = sqrt(c6
[i
]*c6
[j
]);
290 C12(nbfp
,atnr
,i
,j
) = C12(nbfp
,atnr
,j
,i
) = sqrt(cn
[i
]*cn
[j
]);
297 for(i
=0; (i
<atnr
); i
++)
298 fprintf(debug
,"atnr = %2d sigma = %8.4f eps = %8.4f\n",i
,sigma
[i
],eps
[i
]);
299 for(i
=0; (i
<atnr
); i
++) {
300 for(j
=0; (j
<atnr
); j
++) {
302 fprintf(debug
,"i: %2d j: %2d A: %10.5e B: %10.5e C: %10.5e\n",i
,j
,
303 BHAMA(nbfp
,atnr
,i
,j
),BHAMB(nbfp
,atnr
,i
,j
),BHAMC(nbfp
,atnr
,i
,j
));
305 fprintf(debug
,"i: %2d j: %2d c6: %10.5e cn: %10.5e\n",i
,j
,
306 C6(nbfp
,atnr
,i
,j
),C12(nbfp
,atnr
,i
,j
));
312 static void scale_box(int natoms
,rvec x
[],matrix box
)
316 if ((scale
[XX
] != 1.0) || (scale
[YY
] != 1.0) || (scale
[ZZ
] != 1.0)) {
318 fprintf(debug
,"scale = %8.4f %8.4f %8.4f\n",
319 scale
[XX
],scale
[YY
],scale
[ZZ
]);
320 for(m
=0; (m
<DIM
); m
++)
321 box
[m
][m
] *= scale
[m
];
322 for(i
=0; (i
<natoms
); i
++)
323 for(m
=0; (m
<DIM
); m
++)
328 bool update_forcefield(FILE *fplog
,
329 int nfile
,const t_filenm fnm
[],t_forcerec
*fr
,
330 int natoms
,rvec x
[],matrix box
)
332 static int ntry
,ntried
;
336 /* First time around we have to read the parameters */
338 range
= read_range(ftp2fn(efDAT
,nfile
,fnm
),&nparm
);
340 gmx_fatal(FARGS
,"No correct parameter info in %s",ftp2fn(efDAT
,nfile
,fnm
));
341 snew(param_val
,nparm
);
343 if (opt2bSet("-ga",nfile
,fnm
)) {
344 /* Genetic algorithm time */
345 ga
= init_ga(fplog
,opt2fn("-ga",nfile
,fnm
),nparm
,range
);
348 /* Determine the grid size */
350 for(i
=0; (i
<nparm
); i
++)
354 fprintf(fplog
,"Going to try %d different combinations of %d parameters\n",
359 update_ga(fplog
,range
,ga
);
362 /* Increment the counter
363 * Non-trivial, since this is nparm nested loops in principle
365 for(i
=0; (i
<nparm
); i
++) {
366 if (param_val
[i
] < (range
[i
].np
-1)) {
375 fprintf(fplog
,"Finished with %d out of %d iterations\n",ntried
+1,ntry
);
380 /* Now do the real updating */
381 update_ff(fr
,nparm
,range
,param_val
);
383 /* Update box and coordinates if necessary */
384 scale_box(natoms
,x
,box
);
389 static void print_range(FILE *fp
,tensor P
,real MSF
,real energy
)
393 fprintf(fp
,"%8.3f %8.3f %8.3f %8.3f",
394 cost(P
,MSF
,energy
),trace(P
)/3,MSF
,energy
);
395 for(i
=0; (i
<nparm
); i
++)
396 fprintf(fp
," %s %10g",esenm
[range
[i
].ptype
],range
[i
].rval
);
401 static real
msf(int n
,rvec f1
[],rvec f2
[])
409 for(j
=0; ((j
<ff
.molsize
) && (i
<n
)); j
++,i
++) {
414 msf1
+= iprod(ff2
,ff2
);
420 static void print_grid(FILE *fp
,real ener
[],int natoms
,rvec f
[],rvec fshake
[],
421 rvec x
[],t_block
*mols
,real mass
[],tensor pres
)
423 static bool bFirst
= TRUE
;
424 static const char *desc
[] = {
425 "------------------------------------------------------------------------",
426 "In the output from the forcefield scan we have the potential energy,",
427 "then the root mean square force on the atoms, and finally the parameters",
428 "in the order they appear in the input file.",
429 "------------------------------------------------------------------------"
435 for(i
=0; (i
<asize(desc
)); i
++)
436 fprintf(fp
,"%s\n",desc
[i
]);
440 if ((ff
.tol
== 0) || (fabs(ener
[F_EPOT
]/ff
.nmol
-ff
.epot
) < ff
.tol
)) {
441 msf1
= msf(natoms
,f
,fshake
);
442 if ((ff
.f_max
== 0) || (msf1
< sqr(ff
.f_max
)))
443 print_range(fp
,pres
,msf1
,ener
[F_EPOT
]/ff
.nmol
);
447 bool print_forcefield(FILE *fp
,real ener
[],int natoms
,rvec f
[],rvec fshake
[],
448 rvec x
[],t_block
*mols
,real mass
[],tensor pres
)
453 msf1
= msf(natoms
,f
,fshake
);
455 fprintf(fp
,"Pressure: %12g, RMSF: %12g, Energy-Epot: %12g, cost: %12g\n",
456 ener
[F_PRES
],sqrt(msf1
),ener
[F_EPOT
]/ff
.nmol
-ff
.epot
,
457 cost(pres
,msf1
,ener
[F_EPOT
]/ff
.nmol
));
458 if (print_ga(fp
,ga
,msf1
,pres
,scale
,(ener
[F_EPOT
]/ff
.nmol
),range
,ff
.tol
)) {
464 print_grid(fp
,ener
,natoms
,f
,fshake
,x
,mols
,mass
,pres
);