Parse stderr of tuning runs to catch fatal errors which do not appear in md.log
[gromacs.git] / src / kernel / xutils.c
blob2e3df5c88345420f052aa20d6bb3ff3efa090825
1 /*
2 *
3 * This source code is part of
4 *
5 * G R O M A C S
6 *
7 * GROningen MAchine for Chemical Simulations
8 *
9 * VERSION 3.2.0
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
32 * And Hey:
33 * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
35 #ifdef HAVE_CONFIG_H
36 #include <config.h>
37 #endif
39 #include "typedefs.h"
40 #include "smalloc.h"
41 #include "strdb.h"
42 #include "string2.h"
43 #include "xmdrun.h"
44 #include "vec.h"
45 #include "genalg.h"
46 #include "random.h"
48 real mol_dipole(int k0,int k1,rvec x[],real q[])
50 int k,m;
51 rvec mu;
53 clear_rvec(mu);
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[])
64 int i,start,end;
65 real mu_ave;
67 start = md->start;
68 end = md->homenr + start;
71 clear_rvec(mu);
72 for(i=start; (i<end); i++)
73 for(m=0; (m<DIM); m++)
74 mu[m] += q[i]*x[i][m];
75 if (PAR(cr)) {
76 gmx_sum(DIM,mu,cr);
79 /* I guess we have to parallelise this one! */
81 if (gnx > 0) {
82 mu_ave = 0.0;
83 for(i=0; (i<gnx); i++) {
84 int gi = grpindex[i];
85 mu_ave += mol_dipole(mols->index[gi],mols->index[gi+1],x,q);
88 return(mu_ave/gnx);
90 else
91 return 0;
94 /* Lots of global variables! Yummy... */
95 static t_ffscan ff;
97 void set_ffvars(t_ffscan *fff)
99 ff = *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,
116 real rmin,real rmax)
118 if (rmin > rmax)
119 gmx_fatal(FARGS,"rmin (%f) > rmax (%f)",rmin,rmax);
120 if (np <= 0)
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);
126 r->np = np;
127 r->atype = atype;
128 r->ptype = ptype;
129 r->rmin = rmin;
130 r->rmax = rmax;
131 r->rval = rmin;
132 r->dr = r->rmax - r->rmin;
135 static t_range *read_range(const char *db,int *nrange)
137 int nlines,nr,np,i;
138 char **lines=NULL;
139 t_range *range;
140 int atype,ptype;
141 double rmin,rmax;
143 nlines = get_file(db,&lines);
144 snew(range,nlines);
146 nr=0;
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);
154 nr++;
157 fprintf(stderr,"found %d variables to iterate over\n",nr);
159 *nrange = nr;
161 for(nr=0; (nr < nlines); nr++)
162 sfree(lines[nr]);
163 sfree(lines);
165 return range;
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);
175 if (r->np == 1)
176 r->rval = r->rmin;
177 else {
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));
183 else
184 r->rval = r->rmin+(n*(r->dr))/(r->np-1);
186 return r->rval;
189 real value_rand(t_range *r,int *seed)
191 real logrmin,logrmax;
192 real mr;
194 if (r->np == 1)
195 r->rval = r->rmin;
196 else {
197 mr = rando(seed);
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));
203 else
204 r->rval = r->rmin + mr*(r->rmax-r->rmin);
206 if (debug)
207 fprintf(debug,"type: %s, value: %g\n",esenm[r->ptype],r->rval);
208 return 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;
214 real val,*nbfp;
215 int i,j,atnr;
217 atnr = fr->ntype;
218 nbfp = fr->nbfp;
220 if (fr->bBHAM) {
221 if (bhama == NULL) {
222 snew(bhama,atnr);
223 snew(bhamb,atnr);
224 snew(bhamc,atnr);
227 else {
228 if (sigma == NULL) {
229 snew(sigma,atnr);
230 snew(eps,atnr);
231 snew(c6,atnr);
232 snew(cn,atnr);
235 /* Get current values for everything */
236 for(i=0; (i<nparm); i++) {
237 if (ga)
238 val = range[i].rval;
239 else
240 val = value_range(&range[i],param_val[i]);
241 if(debug)
242 fprintf(debug,"val = %g\n",val);
243 switch (range[i].ptype) {
244 case eseSIGMA:
245 sigma[range[i].atype] = val;
246 break;
247 case eseEPSILON:
248 eps[range[i].atype] = val;
249 break;
250 case eseBHAMA:
251 bhama[range[i].atype] = val;
252 break;
253 case eseBHAMB:
254 bhamb[range[i].atype] = val;
255 break;
256 case eseBHAMC:
257 bhamc[range[i].atype] = val;
258 break;
259 case eseCELLX:
260 scale[XX] = val;
261 break;
262 case eseCELLY:
263 scale[YY] = val;
264 break;
265 case eseCELLZ:
266 scale[ZZ] = val;
267 break;
268 default:
269 gmx_fatal(FARGS,"Unknown ptype");
272 if (fr->bBHAM) {
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]);
281 else {
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]);
295 if (debug) {
296 if (!fr->bBHAM)
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++) {
301 if (fr->bBHAM)
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));
304 else
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)
314 int i,m;
316 if ((scale[XX] != 1.0) || (scale[YY] != 1.0) || (scale[ZZ] != 1.0)) {
317 if (debug)
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++)
324 x[i][m] *= scale[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;
333 int i,j;
334 bool bDone;
336 /* First time around we have to read the parameters */
337 if (nparm == 0) {
338 range = read_range(ftp2fn(efDAT,nfile,fnm),&nparm);
339 if (nparm == 0)
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);
347 else {
348 /* Determine the grid size */
349 ntry = 1;
350 for(i=0; (i<nparm); i++)
351 ntry *= range[i].np;
352 ntried = 0;
354 fprintf(fplog,"Going to try %d different combinations of %d parameters\n",
355 ntry,nparm);
358 if (ga) {
359 update_ga(fplog,range,ga);
361 else {
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)) {
367 param_val[i]++;
368 for(j=0; (j<i); j++)
369 param_val[j] = 0;
370 ntried++;
371 break;
374 if (i == nparm) {
375 fprintf(fplog,"Finished with %d out of %d iterations\n",ntried+1,ntry);
376 return TRUE;
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);
386 return FALSE;
389 static void print_range(FILE *fp,tensor P,real MSF,real energy)
391 int i;
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);
397 fprintf(fp," FF\n");
398 fflush(fp);
401 static real msf(int n,rvec f1[],rvec f2[])
403 int i,j;
404 rvec ff2;
405 real msf1=0;
407 for(i=0; (i<n); ) {
408 clear_rvec(ff2);
409 for(j=0; ((j<ff.molsize) && (i<n)); j++,i++) {
410 rvec_inc(ff2,f1[i]);
411 if (f2)
412 rvec_inc(ff2,f2[i]);
414 msf1 += iprod(ff2,ff2);
417 return msf1/n;
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 "------------------------------------------------------------------------"
431 real msf1;
432 int i;
434 if (bFirst) {
435 for(i=0; (i<asize(desc)); i++)
436 fprintf(fp,"%s\n",desc[i]);
437 fflush(fp);
438 bFirst = FALSE;
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)
450 real msf1;
452 if (ga) {
453 msf1 = msf(natoms,f,fshake);
454 if (debug)
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)) {
459 return TRUE;
461 fflush(fp);
463 else
464 print_grid(fp,ener,natoms,f,fshake,x,mols,mass,pres);
465 return FALSE;