0423d7028b00144fce0833eae4adc6f0855845a2
[alexxy/gromacs.git] / src / tools / geminate.c
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 4.5
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.
14  
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.
19  * 
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.
26  * 
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.
29  * 
30  * For more info, check our website at http://www.gromacs.org
31  * 
32  * And Hey:
33  * Green Red Orange Magenta Azure Cyan Skyblue
34  */
35 #ifdef HAVE_CONFIG_H
36 #include <config.h>
37 #endif
38
39 #ifdef HAVE_LIBGSL
40 #include <gsl/gsl_rng.h>
41 #include <gsl/gsl_randist.h>
42 #include <gsl/gsl_vector.h>
43 #include <gsl/gsl_blas.h>
44 #include <gsl/gsl_multimin.h>
45 #include <gsl/gsl_multifit_nlin.h>
46 #include <gsl/gsl_sf.h>
47 #include <gsl/gsl_version.h>
48 #endif
49
50 #include <math.h>
51 #include "typedefs.h"
52 #include "smalloc.h"
53 #include "vec.h"
54 #include "geminate.h"
55
56 #ifdef DOUSEOPENMP
57 #define HAVE_OPENMP
58 #endif
59 #ifdef HAVE_OPENMP
60 #include <omp.h>
61 #endif
62
63 /* The first few sections of this file contain functions that were adopted,
64  * and to some extent modified, by Erik Marklund (erikm[aT]xray.bmc.uu.se,
65  * http://folding.bmc.uu.se) from code written by Omer Markovitch (email, url).
66  * This is also the case with the function eq10v2().
67  * 
68  * The parts menetioned in the previous paragraph were contributed under the BSD license.
69  */
70
71
72 /* This first part is from complex.c which I recieved from Omer Markowitch.
73  * - Erik Marklund
74  *
75  * ------------- from complex.c ------------- */
76
77 /* Complexation of a paired number (r,i)                                     */
78 static gem_complex gem_cmplx(double r, double i)
79 {
80   gem_complex value;
81   value.r = r;
82   value.i=i;
83   return value;
84 }
85
86 /* Complexation of a real number, x */
87 static gem_complex gem_c(double x)
88 {
89   gem_complex value;
90   value.r=x;
91   value.i=0;
92   return value;
93 }
94
95 /* Magnitude of a complex number z                                           */
96 static double gem_cx_abs(gem_complex z) { return (sqrt(z.r*z.r+z.i*z.i)); }
97
98 /* Addition of two complex numbers z1 and z2                                 */
99 static gem_complex gem_cxadd(gem_complex z1, gem_complex z2)
100 {
101   gem_complex value;
102   value.r=z1.r+z2.r;
103   value.i=z1.i+z2.i;
104   return value;
105 }
106
107 /* Addition of a complex number z1 and a real number r */
108 static gem_complex gem_cxradd(gem_complex z, double r)
109 {
110   gem_complex value;
111   value.r = z.r + r;
112   value.i = z.i;
113   return value;
114 }
115
116 /* Subtraction of two complex numbers z1 and z2                              */
117 static gem_complex gem_cxsub(gem_complex z1, gem_complex z2)
118 {
119   gem_complex value;
120   value.r=z1.r-z2.r;
121   value.i=z1.i-z2.i;
122   return value;
123 }
124
125 /* Multiplication of two complex numbers z1 and z2                           */
126 static gem_complex gem_cxmul(gem_complex z1, gem_complex z2)
127 {
128   gem_complex value;
129   value.r = z1.r*z2.r-z1.i*z2.i;
130   value.i = z1.r*z2.i+z1.i*z2.r;
131   return value;
132 }
133
134 /* Square of a complex number z                                              */
135 static gem_complex gem_cxsq(gem_complex z)
136 {
137   gem_complex value;
138   value.r = z.r*z.r-z.i*z.i;
139   value.i = z.r*z.i*2.;
140   return value;
141 }
142
143 /* multiplication of a complex number z and a real number r */
144 static gem_complex gem_cxrmul(gem_complex z, double r)
145 {
146   gem_complex value;
147   value.r = z.r*r;
148   value.i= z.i*r;
149   return value;
150 }
151
152 /* Division of two complex numbers z1 and z2                                 */
153 static gem_complex gem_cxdiv(gem_complex z1, gem_complex z2)
154 {
155   gem_complex value;
156   double num;
157   num = z2.r*z2.r+z2.i*z2.i;
158   if(num == 0.)
159     {
160       fprintf(stderr, "ERROR in gem_cxdiv function\n");
161     }
162   value.r = (z1.r*z2.r+z1.i*z2.i)/num; value.i = (z1.i*z2.r-z1.r*z2.i)/num;
163   return value;
164 }
165
166 /* division of a complex z number by a real number x */
167 static gem_complex gem_cxrdiv(gem_complex z, double r)
168 {
169   gem_complex value;
170   value.r = z.r/r;
171   value.i = z.i/r;
172   return value;
173 }
174
175 /* division of a real number r by a complex number x */
176 static gem_complex gem_rxcdiv(double r, gem_complex z)
177 {
178   gem_complex value;
179   double f;
180   f = r/(z.r*z.r+z.i*z.i);
181   value.r = f*z.r;
182   value.i = -f*z.i;
183   return value;
184 }
185
186 /* Exponential of a complex number-- exp (z)=|exp(z.r)|*{cos(z.i)+I*sin(z.i)}*/
187 static gem_complex gem_cxdexp(gem_complex z)
188 {
189   gem_complex value;
190   double exp_z_r;
191   exp_z_r = exp(z.r);
192   value.r = exp_z_r*cos(z.i);
193   value.i = exp_z_r*sin(z.i);
194   return value;
195 }
196
197 /* Logarithm of a complex number -- log(z)=log|z|+I*Arg(z),                  */
198 /*                                  where -PI < Arg(z) < PI                  */ 
199 static gem_complex gem_cxlog(gem_complex z)
200 {
201   gem_complex value;
202   double mag2;
203   mag2 = z.r*z.r+z.i*z.i;
204   if(mag2 < 0.) {
205     fprintf(stderr, "ERROR in gem_cxlog func\n");
206   }
207   value.r = log(sqrt(mag2));
208   if(z.r == 0.) {
209     value.i = PI/2.;
210     if(z.i <0.) {
211       value.i = -value.i;
212     }
213   } else {
214     value.i = atan2(z.i, z.r);
215   }
216   return value;
217 }
218
219 /* Square root of a complex number z = |z| exp(I*the) -- z^(1/2)             */
220 /*                               z^(1/2)=|z|^(1/2)*[cos(the/2)+I*sin(the/2)] */
221 /*                               where 0 < the < 2*PI                        */
222 static gem_complex gem_cxdsqrt(gem_complex z)
223 {
224   gem_complex value;
225   double sq;
226   sq = gem_cx_abs(z);
227   value.r = sqrt(fabs((sq+z.r)*0.5)); /* z'.r={|z|*[1+cos(the)]/2}^(1/2) */
228   value.i = sqrt(fabs((sq-z.r)*0.5)); /* z'.i={|z|*[1-cos(the)]/2}^(1/2) */
229   if(z.i < 0.) {
230     value.r = -value.r;
231   }
232   return value;
233 }
234
235 /* Complex power of a complex number z1^z2                                   */
236 static gem_complex gem_cxdpow(gem_complex z1, gem_complex z2)
237 {
238   gem_complex value;
239   value=gem_cxdexp(gem_cxmul(gem_cxlog(z1),z2));
240   return value;
241 }
242
243 /* ------------ end of complex.c ------------ */
244
245 /* This next part was derived from cubic.c, also received from Omer Markovitch.
246  * ------------- from cubic.c ------------- */
247
248 /* Solver for a cubic equation: x^3-a*x^2+b*x-c=0                            */
249 static void gem_solve(gem_complex *al, gem_complex *be, gem_complex *gam,
250                   double a, double b, double c)
251 {
252   double t1, t2, two_3, temp;
253   gem_complex ctemp, ct3;
254   
255   two_3=pow(2., 1./3.); t1 = -a*a+3.*b; t2 = 2.*a*a*a-9.*a*b+27.*c;
256   temp = 4.*t1*t1*t1+t2*t2;
257   
258   ctemp = gem_cmplx(temp,0.);   ctemp = gem_cxadd(gem_cmplx(t2,0.),gem_cxdsqrt(ctemp));
259   ct3 = gem_cxdpow(ctemp, gem_cmplx(1./3.,0.));
260   
261   ctemp = gem_rxcdiv(-two_3*t1/3., ct3);
262   ctemp = gem_cxadd(ctemp, gem_cxrdiv(ct3, 3.*two_3));
263         
264   *gam = gem_cxadd(gem_cmplx(a/3.,0.), ctemp);
265   
266   ctemp=gem_cxmul(gem_cxsq(*gam), gem_cxsq(gem_cxsub(*gam, gem_cmplx(a,0.))));
267   ctemp=gem_cxadd(ctemp, gem_cxmul(gem_cmplx(-4.*c,0.), *gam));
268   ctemp = gem_cxdiv(gem_cxdsqrt(ctemp), *gam);
269   *al = gem_cxrmul(gem_cxsub(gem_cxsub(gem_cmplx(a,0.), *gam),ctemp),0.5);
270   *be = gem_cxrmul(gem_cxadd(gem_cxsub(gem_cmplx(a,0.), *gam),ctemp),0.5);
271 }
272
273 /* ------------ end of cubic.c ------------ */
274
275 /* This next part was derived from cerror.c and rerror.c, also received from Omer Markovitch.
276  * ------------- from [cr]error.c ------------- */
277
278 /************************************************************/
279 /* Real valued error function and related functions         */
280 /* x, y     : real variables                                */
281 /* erf(x)   : error function                                */
282 /* erfc(x)  : complementary error function                  */
283 /* omega(x) : exp(x*x)*erfc(x)                              */
284 /* W(x,y)   : exp(-x*x)*omega(x+y)=exp(2*x*y+y^2)*erfc(x+y) */
285 /************************************************************/
286
287 /*---------------------------------------------------------------------------*/
288 /* Utilzed the series approximation of erf(x)                                */
289 /* Relative error=|err(x)|/erf(x)<EPS                                        */
290 /* Handbook of Mathematical functions, Abramowitz, p 297                     */
291 /* Note: When x>=6 series sum deteriorates -> Asymptotic series used instead */
292 /*---------------------------------------------------------------------------*/
293 /*  This gives erfc(z) correctly only upto >10-15 */
294
295 static double gem_erf(double x)
296 {
297   double n,sum,temp,exp2,xm,x2,x4,x6,x8,x10,x12;
298   temp = x;
299   sum  = temp;
300   xm   = 26.;
301   x2   = x*x;
302   x4   = x2*x2;
303   x6   = x4*x2;
304   x8   = x6*x2;
305   x10  = x8*x2;
306   x12 = x10*x2;
307   exp2 = exp(-x2);
308   if(x <= xm)
309     {
310       for(n=1.; n<=2000.; n+=1.){
311         temp *= 2.*x2/(2.*n+1.);
312         sum  += temp;
313         if(fabs(temp/sum)<1.E-16)
314           break;
315       }
316       
317       if(n >= 2000.)
318         fprintf(stderr, "In Erf calc - iteration exceeds %lg\n",n);
319       sum *= 2./sPI*exp2;
320     }
321   else
322     {
323       /* from the asymptotic expansion of experfc(x) */
324       sum = (1. - 0.5/x2 + 0.75/x4
325              - 1.875/x6 + 6.5625/x8
326              - 29.53125/x10 + 162.421875/x12)
327         / sPI/x;
328       sum*=exp2; /* now sum is erfc(x) */
329       sum=-sum+1.;
330     }
331   return x>=0.0 ? sum : -sum;
332 }
333
334 /* Result --> Alex's code for erfc and experfc behaves better than this      */
335 /* complementray error function.                Returns 1.-erf(x)            */
336 static double gem_erfc(double x)
337 {
338   double t,z,ans;
339   z = fabs(x);
340   t = 1.0/(1.0+0.5*z);
341   
342   ans = t * exp(-z*z - 1.26551223 +
343                 t*(1.00002368 +
344                    t*(0.37409196 +
345                       t*(0.09678418 +
346                          t*(-0.18628806 +
347                             t*(0.27886807 +
348                                t*(-1.13520398 +
349                                   t*(1.48851587 +
350                                      t*(-0.82215223 +
351                                         t*0.17087277)))))))));
352         
353   return  x>=0.0 ? ans : 2.0-ans;
354 }
355
356 /* omega(x)=exp(x^2)erfc(x)                                                  */
357 static double gem_omega(double x)
358 {
359   double xm, ans, xx, x4, x6, x8, x10, x12;
360   xm = 26;
361   xx=x*x;
362   x4=xx*xx;
363   x6=x4*xx;
364   x8=x6*xx;
365   x10=x8*xx;
366   x12=x10*xx;
367
368   if(x <= xm) {
369     ans = exp(xx)*gem_erfc(x);
370   } else {
371     /* Asymptotic expansion */
372     ans = (1. - 0.5/xx + 0.75/x4 - 1.875/x6 + 6.5625/x8 - 29.53125/x10 + 162.421875/x12) / sPI/x;
373   }
374   return ans;
375 }
376
377 /*---------------------------------------------------------------------------*/
378 /* Utilzed the series approximation of erf(z=x+iy)                           */
379 /* Relative error=|err(z)|/|erf(z)|<EPS                                      */
380 /* Handbook of Mathematical functions, Abramowitz, p 299                     */
381 /* comega(z=x+iy)=cexp(z^2)*cerfc(z)                                         */
382 /*---------------------------------------------------------------------------*/
383 static gem_complex gem_comega(gem_complex z)
384 {
385   gem_complex value;
386   double x,y;
387   double sumr,sumi,n,n2,f,temp,temp1;
388   double x2, y2,cos_2xy,sin_2xy,cosh_2xy,sinh_2xy,cosh_ny,sinh_ny,exp_y2;
389
390   x        = z.r;
391   y        = z.i;
392   x2       = x*x;
393   y2       = y*y;
394   sumr     = 0.;
395   sumi     = 0.;
396   cos_2xy  = cos(2.*x*y);
397   sin_2xy  = sin(2.*x*y);
398   cosh_2xy = cosh(2.*x*y);
399   sinh_2xy = sinh(2.*x*y);
400   exp_y2   = exp(-y2);
401
402   for(n=1.0, temp=0.; n<=2000.; n+=1.0){
403     n2      = n*n;
404     cosh_ny = cosh(n*y);
405     sinh_ny = sinh(n*y);
406     f       = exp(-n2/4.)/(n2+4.*x2);
407     /* if(f<1.E-200) break; */
408     sumr += (2.*x - 2.*x*cosh_ny*cos_2xy + n*sinh_ny*sin_2xy)*f;
409     sumi += (2.*x*cosh_ny*sin_2xy + n*sinh_ny*cos_2xy)*f;
410     temp1 = sqrt(sumr*sumr+sumi*sumi);
411     if(fabs((temp1-temp)/temp1)<1.E-16) {
412       break;
413     }
414     temp=temp1;
415   }
416   if(n==2000.) {
417     fprintf(stderr, "iteration exceeds %lg\n",n);
418   }
419   sumr *= 2./PI;
420   sumi *= 2./PI;
421
422   if(x!=0.) {
423     f = 1./2./PI/x;
424   } else {
425     f = 0.;
426   }
427   value.r = gem_omega(x)-(f*(1.-cos_2xy)+sumr);
428   value.i = -(f*sin_2xy+sumi);
429   value   = gem_cxmul(value,gem_cmplx(exp_y2*cos_2xy,exp_y2*sin_2xy));
430   return (value);
431 }
432
433 /* ------------ end of [cr]error.c ------------ */
434
435 /*_ REVERSIBLE GEMINATE RECOMBINATION
436  *
437  * Here are the functions for reversible geminate recombination. */
438
439 /* Changes the unit from square cm per s to square Ã…ngström per ps,
440  * since Omers code uses the latter units while g_mds outputs the former.
441  * g_hbond expects a diffusion coefficent given in square cm per s. */
442 static double sqcm_per_s_to_sqA_per_ps (real D) {
443   fprintf(stdout, "Diffusion coefficient is %f A^2/ps\n", D*1e4);
444   return (double)(D*1e4);
445 }
446
447
448 static double eq10v2(double theoryCt[], double time[], int manytimes,
449                      double ka, double kd, t_gemParams *params)
450 {
451   /* Finding the 3 roots */
452   int i;
453   double kD, D, r, a, b, c, tsqrt, sumimaginary;
454   gem_complex
455     alpha, beta, gamma,
456     c1, c2, c3, c4,
457     oma, omb, omc,
458     part1, part2, part3, part4;
459
460   kD = params->kD;
461   D  = params->D;
462   r  = params->sigma;
463   a = (1.0 + ka/kD) * sqrt(D)/r;
464   b = kd;
465   c = kd * sqrt(D)/r;
466
467   gem_solve(&alpha, &beta, &gamma, a, b, c);
468   /* Finding the 3 roots */
469
470   sumimaginary = 0;
471   part1 = gem_cxmul(alpha, gem_cxmul(gem_cxadd(beta,  gamma), gem_cxsub(beta,  gamma))); /* 1(2+3)(2-3) */
472   part2 = gem_cxmul(beta,  gem_cxmul(gem_cxadd(gamma, alpha), gem_cxsub(gamma, alpha))); /* 2(3+1)(3-1) */
473   part3 = gem_cxmul(gamma, gem_cxmul(gem_cxadd(alpha, beta) , gem_cxsub(alpha, beta)));  /* 3(1+2)(1-2) */
474   part4 = gem_cxmul(gem_cxsub(gamma, alpha), gem_cxmul(gem_cxsub(alpha, beta), gem_cxsub(beta, gamma))); /* (3-1)(1-2)(2-3) */
475
476 #ifdef HAVE_OPENMP
477 #pragma omp parallel for                                \
478   private(i, tsqrt, oma, omb, omc, c1, c2, c3, c4),     \
479   reduction(+:sumimaginary),                            \
480   default(shared),                                      \
481   schedule(guided)
482 #endif
483   for (i=0; i<manytimes; i++){
484     tsqrt = sqrt(time[i]);
485     oma   = gem_comega(gem_cxrmul(alpha, tsqrt));
486     c1    = gem_cxmul(oma, gem_cxdiv(part1, part4));
487     omb   = gem_comega(gem_cxrmul(beta, tsqrt));
488     c2    = gem_cxmul(omb, gem_cxdiv(part2, part4));
489     omc   = gem_comega(gem_cxrmul(gamma, tsqrt));
490     c3    = gem_cxmul(omc, gem_cxdiv(part3, part4));
491     c4.r  = c1.r+c2.r+c3.r;
492     c4.i  = c1.i+c2.i+c3.i;
493     theoryCt[i]  = c4.r;
494     sumimaginary += c4.i * c4.i;
495   }
496
497   return sumimaginary;
498
499 } /* eq10v2 */
500
501 /* This returns the real-valued index(!) to an ACF, equidistant on a log scale. */
502 static double getLogIndex(const int i, const t_gemParams *params)
503 {
504   return (exp(((double)(i)) * params->logQuota) -1);
505 }
506
507 extern t_gemParams *init_gemParams(const double sigma, const double D,
508                                    const real *t, const int len, const int nFitPoints,
509                                    const real begFit, const real endFit,
510                                    const real ballistic, const int nBalExp, const gmx_bool bDt)
511 {
512   double tDelta;
513   t_gemParams *p;
514
515   snew(p,1);
516
517   /* A few hardcoded things here. For now anyway. */
518 /*   p->ka_min   = 0; */
519 /*   p->ka_max   = 100; */
520 /*   p->dka      = 10; */
521 /*   p->kd_min   = 0; */
522 /*   p->kd_max   = 2; */
523 /*   p->dkd      = 0.2; */
524   p->ka       = 0;
525   p->kd       = 0;
526 /*   p->lsq      = -1; */
527 /*   p->lifetime = 0; */
528   p->sigma    = sigma*10; /* Omer uses Ã…, not nm */
529 /*   p->lsq_old  = 99999; */
530   p->D        = sqcm_per_s_to_sqA_per_ps(D);
531   p->kD       = 4*acos(-1.0)*sigma*p->D;
532
533
534   /* Parameters used by calcsquare(). Better to calculate them
535    * here than in calcsquare every time it's called. */
536   p->len = len;
537 /*   p->logAfterTime = logAfterTime; */
538   tDelta       = (t[len-1]-t[0]) / len;
539   if (tDelta <= 0) {
540     gmx_fatal(FARGS, "Time between frames is non-positive!");
541   } else {
542     p->tDelta = tDelta;
543   }
544
545   p->nExpFit      = nBalExp;
546 /*   p->nLin         = logAfterTime / tDelta; */
547   p->nFitPoints   = nFitPoints;
548   p->begFit       = begFit;
549   p->endFit       = endFit;
550   p->logQuota     = (double)(log(p->len))/(p->nFitPoints-1);
551 /*   if (p->nLin <= 0) { */
552 /*     fprintf(stderr, "Number of data points in the linear regime is non-positive!\n"); */
553 /*     sfree(p); */
554 /*     return NULL; */
555 /*   } */
556   /* We want the same number of data points in the log regime. Not crucial, but seems like a good idea. */
557   /* p->logDelta = log(((float)len)/p->nFitPoints) / p->nFitPoints;/\* log(((float)len)/p->nLin) / p->nLin; *\/ */
558 /*   p->logPF    = p->nFitPoints*p->nFitPoints/(float)len; /\* p->nLin*p->nLin/(float)len; *\/ */
559   /* logPF and logDelta are stitched together with the macro GETLOGINDEX defined in geminate.h */
560   
561 /*   p->logMult      = pow((float)len, 1.0/nLin);/\* pow(t[len-1]-t[0], 1.0/p->nLin); *\/ */
562   p->ballistic    =  ballistic;
563   return p;
564 }
565
566 /* There was a misunderstanding regarding the fitting. From our
567  * recent correspondence it appears that Omer's code require
568  * the ACF data on a log-scale and does not operate on the raw data.
569  * This needs to be redone in gemFunc_residual() as well as in the
570  * t_gemParams structure. */
571 #ifdef HAVE_LIBGSL
572 static double gemFunc_residual2(const gsl_vector *p, void *data)
573 {
574   gemFitData *GD;
575   int i, iLog, nLin, nFitPoints, nData;
576   double r, residual2, *ctTheory, *y;
577
578   GD         = (gemFitData *)data;
579   nLin       = GD->params->nLin;
580   nFitPoints = GD->params->nFitPoints;
581   nData      = GD->nData;
582   residual2  = 0;
583   ctTheory  = GD->ctTheory;
584   y         = GD->y;
585
586   /* Now, we'd save a lot of time by not calculating eq10v2 for all
587    * time points, but only those that we sample to calculate the mse.
588    */
589
590   eq10v2(GD->ctTheory, GD->doubleLogTime/* GD->time */, nFitPoints/* GD->nData */,
591          gsl_vector_get(p, 0), gsl_vector_get(p, 1),
592          GD->params);
593   
594   fixGemACF(GD->ctTheory, nFitPoints);
595
596   /* Removing a bunch of points from the log-part. */
597 #ifdef HAVE_OPENMP
598 #pragma omp parallel for schedule(dynamic)      \
599   firstprivate(nData, ctTheory, y, nFitPoints)  \
600   private (i, iLog, r)                  \
601   reduction(+:residual2)                        \
602   default(shared)
603 #endif
604   for(i=0; i<nFitPoints; i++)
605     {
606       iLog = GD->logtime[i];
607       r = log(ctTheory[i /* iLog */]);
608       residual2 += sqr(r-log(y[iLog]));
609     }
610   residual2 /= nFitPoints; /* Not really necessary for the fitting, but gives more meaning to the returned data. */
611   /* printf("ka=%3.5f\tkd=%3.5f\trmse=%3.5f\n", gsl_vector_get(p,0), gsl_vector_get(p,1), residual2); */
612   return residual2;
613
614 /*   for (i=0; i<nLin; i++) { */
615 /*     /\* Linear part ----------*\/ */
616 /*     r = ctTheory[i]; */
617 /*     residual2 += sqr(r-y[i]); */
618 /*     /\* Log part -------------*\/ */
619 /*     iLog = GETLOGINDEX(i, GD->params); */
620 /*     if (iLog >= nData) */
621 /*       gmx_fatal(FARGS, "log index out of bounds: %i", iLog); */
622 /*     r = ctTheory[iLog]; */
623 /*     residual2 += sqr(r-y[iLog]); */
624
625 /*   } */
626 /*   residual2 /= GD->n; */
627 /*   return residual2; */
628 }
629 #endif
630
631 static real* d2r(const double *d, const int nn);
632
633 extern real fitGemRecomb(double *ct, double *time, double **ctFit,
634                         const int nData, t_gemParams *params)
635 {
636
637   int    nThreads, i, iter, status, maxiter;
638   real   size, d2, tol, *dumpdata;
639   size_t p, n;
640   gemFitData *GD;
641   char *dumpstr, dumpname[128];
642
643   /* nmsimplex2 had convergence problems prior to gsl v1.14,
644    * but it's O(N) instead of O(N) operations, so let's use it if v >= 1.14 */
645 #ifdef HAVE_LIBGSL
646   gsl_multimin_fminimizer *s;
647   gsl_vector *x,*dx;             /* parameters and initial step size */
648   gsl_multimin_function fitFunc;
649 #ifdef GSL_MAJOR_VERSION
650 #ifdef GSL_MINOR_VERSION
651 #if ((GSL_MAJOR_VERSION == 1 && GSL_MINOR_VERSION >= 14) || \
652   (GSL_MAJOR_VERSION > 1))
653     const gsl_multimin_fminimizer_type *T = gsl_multimin_fminimizer_nmsimplex2;
654 #else
655   const gsl_multimin_fminimizer_type *T = gsl_multimin_fminimizer_nmsimplex;
656 #endif /* #if ... */
657 #endif /* GSL_MINOR_VERSION */
658 #else
659   const gsl_multimin_fminimizer_type *T = gsl_multimin_fminimizer_nmsimplex;
660 #endif /* GSL_MAJOR_VERSION */
661   fprintf(stdout, "Will fit ka and kd to the ACF according to the reversible geminate recombination model.\n");
662 #else  /* HAVE_LIBGSL */
663   fprintf(stderr, "Sorry, can't do reversible geminate recombination without gsl. "
664          "Recompile using --with-gsl.\n");
665   return -1;
666 #endif /* HAVE_LIBGSL */
667
668 #ifdef HAVE_LIBGSL
669 #ifdef HAVE_OPENMP
670   nThreads = omp_get_num_procs();
671   omp_set_num_threads(nThreads);
672   fprintf(stdout, "We will be using %i threads.\n", nThreads);
673 #endif
674
675   iter    = 0;
676   status  = 0;
677   maxiter = 100;
678   tol     = 1e-10;
679
680   p = 2;                  /* Number of parameters to fit. ka and kd.  */
681   n = params->nFitPoints; /* params->nLin*2 */;       /* Number of points in the reduced dataset  */
682
683   if (params->D <= 0)
684     {
685       fprintf(stderr, "Fitting of D is not implemented yet. It must be provided on the command line.\n");
686       return -1;
687     }
688   
689 /*   if (nData<n) { */
690 /*     fprintf(stderr, "Reduced data set larger than the complete data set!\n"); */
691 /*     n=nData; */
692 /*   } */
693   snew(dumpdata, nData);
694   snew(GD,1);
695
696   GD->n = n;
697   GD->y = ct;
698   GD->ctTheory=NULL;
699   snew(GD->ctTheory, nData);
700   GD->LinLog=NULL;
701   snew(GD->LinLog, n);
702   GD->time = time;
703   GD->ka = 0;
704   GD->kd = 0;
705   GD->tDelta = time[1]-time[0];
706   GD->nData = nData;
707   GD->params = params;
708   snew(GD->logtime,params->nFitPoints);
709   snew(GD->doubleLogTime,params->nFitPoints);
710
711   for (i=0; i<params->nFitPoints; i++)
712     {
713       GD->doubleLogTime[i] = (double)(getLogIndex(i, params));
714       GD->logtime[i] = (int)(GD->doubleLogTime[i]);
715       GD->doubleLogTime[i]*=GD->tDelta;
716
717       if (GD->logtime[i] >= nData)
718         {
719           fprintf(stderr, "Ayay. It seems we're indexing out of bounds.\n");
720           params->nFitPoints = i;
721         }      
722     }
723
724   fitFunc.f = &gemFunc_residual2;
725   fitFunc.n = 2;
726   fitFunc.params = (void*)GD;
727
728   x  = gsl_vector_alloc (fitFunc.n);
729   dx = gsl_vector_alloc (fitFunc.n);
730   gsl_vector_set (x,  0, 25);
731   gsl_vector_set (x,  1, 0.5);
732   gsl_vector_set (dx, 0, 0.1);
733   gsl_vector_set (dx, 1, 0.01);
734   
735   
736   s = gsl_multimin_fminimizer_alloc (T, fitFunc.n);
737   gsl_multimin_fminimizer_set (s, &fitFunc, x, dx);
738   gsl_vector_free (x);
739   gsl_vector_free (dx);
740
741   do  {
742     iter++;
743     status = gsl_multimin_fminimizer_iterate (s);
744     
745     if (status != 0)
746       gmx_fatal(FARGS,"Something went wrong in the iteration in minimizer %s:\n \"%s\"\n",
747                 gsl_multimin_fminimizer_name(s), gsl_strerror(status));
748     
749     d2     = gsl_multimin_fminimizer_minimum(s);
750     size   = gsl_multimin_fminimizer_size(s);
751     params->ka = gsl_vector_get (s->x, 0);
752     params->kd = gsl_vector_get (s->x, 1);
753     
754     if (status)
755       {
756         fprintf(stderr, "%s\n", gsl_strerror(status));
757         break;
758       }
759
760     status = gsl_multimin_test_size(size,tol);
761
762     if (status == GSL_SUCCESS) {
763       fprintf(stdout, "Converged to minimum at\n");
764     }
765
766     printf ("iter %5d: ka = %2.5f  kd = %2.5f  f() = %7.3f  size = %.3f  chi2 = %2.5f\n",
767             iter,
768             params->ka,
769             params->kd,
770             s->fval, size, d2);
771
772     if (iter%1 == 0)
773       {
774         eq10v2(GD->ctTheory, time, nData, params->ka, params->kd, params);
775         /* fixGemACF(GD->ctTheory, nFitPoints); */
776         sprintf(dumpname, "Iter_%i.xvg", iter);
777         for(i=0; i<GD->nData; i++)
778           {
779             dumpdata[i] = (real)(GD->ctTheory[i]);
780             if (!gmx_isfinite(dumpdata[i]))
781               {
782                 gmx_fatal(FARGS, "Non-finite value in acf.");
783               }
784           }
785         dumpN(dumpdata, GD->nData, dumpname);
786       }
787   }
788   while ((status == GSL_CONTINUE) && (iter < maxiter));
789
790   /*   /\* Calculate the theoretical ACF from the parameters one last time. *\/ */
791   eq10v2(GD->ctTheory, time, nData, params->ka, params->kd, params);
792   *ctFit = GD->ctTheory;
793
794   sfree(GD);
795   gsl_multimin_fminimizer_free (s);
796
797
798   return d2;
799
800 #endif /* HAVE_LIBGSL */
801 }
802
803 #ifdef HAVE_LIBGSL
804 static int balFunc_f(const gsl_vector *x, void *data, gsl_vector *f)
805 {
806   /* C + sum{ A_i * exp(-B_i * t) }*/
807
808   balData *BD;
809   int n, i,j, nexp;
810   double *y, *A, *B, C,        /* There are the parameters to be optimized. */
811     t, ct;
812
813   BD   = (balData *)data;
814   n    = BD->n;
815   nexp = BD->nexp;
816   y    = BD->y,
817   snew(A, nexp);
818   snew(B, nexp);
819   
820   for (i = 0; i<nexp; i++)
821     {
822       A[i] = gsl_vector_get(x, i*2);
823       B[i] = gsl_vector_get(x, i*2+1);
824     }
825   C = gsl_vector_get(x, nexp*2);
826
827   for (i=0; i<n; i++)
828     {
829       t = i*BD->tDelta;
830       ct = 0;
831       for (j=0; j<nexp; j++) {
832         ct += A[j] * exp(B[j] * t);
833       }
834       ct += C;
835       gsl_vector_set (f, i, ct - y[i]);
836     }
837   return GSL_SUCCESS;
838 }
839
840 /* The derivative stored in jacobian form (J)*/
841 static int balFunc_df(const gsl_vector *params, void *data, gsl_matrix *J)
842 {
843   balData *BD;
844   size_t n,i,j;
845   double *y, *A, *B, C, /* There are the parameters. */
846     t;
847   int nexp;
848
849   BD   = (balData*)data;
850   n    = BD->n;
851   y    = BD->y;
852   nexp = BD->nexp;
853
854   snew(A, nexp);
855   snew(B, nexp);
856
857   for (i=0; i<nexp; i++)
858     {
859       A[i] = gsl_vector_get(params, i*2);
860       B[i] = gsl_vector_get(params, i*2+1);
861     }
862   C = gsl_vector_get(params, nexp*2);
863   for (i=0; i<n; i++)
864     {
865       t = i*BD->tDelta;
866       for (j=0; j<nexp; j++)
867         {
868           gsl_matrix_set (J, i, j*2,   exp(B[j]*t));        /* df(t)/dA_j */
869           gsl_matrix_set (J, i, j*2+1, A[j]*t*exp(B[j]*t)); /* df(t)/dB_j */
870         }
871       gsl_matrix_set (J, i, nexp*2, 1); /* df(t)/dC */
872     }
873   return GSL_SUCCESS;
874 }
875
876 /* Calculation of the function and its derivative */
877 static int balFunc_fdf(const gsl_vector *params, void *data,
878                        gsl_vector *f, gsl_matrix *J)
879 {
880   balFunc_f(params, data, f);
881   balFunc_df(params, data, J);
882   return GSL_SUCCESS;
883 }
884 #endif /* HAVE_LIBGSL */
885
886 /* Removes the ballistic term from the beginning of the ACF,
887  * just like in Omer's paper.
888  */
889 extern void takeAwayBallistic(double *ct, double *t, int len, real tMax, int nexp, gmx_bool bDerivative)
890 {
891
892   /* Use nonlinear regression with GSL instead.
893    * Fit with 4 exponentials and one constant term,
894    * subtract the fatest exponential. */
895
896   int nData,i,status, iter;
897   balData *BD;
898   double *guess,              /* Initial guess. */
899     *A,                       /* The fitted parameters. (A1, B1, A2, B2,... C) */
900     a[2],
901     ddt[2];
902   gmx_bool sorted;
903   size_t n;
904   size_t p;
905
906   nData = 0;
907   do {
908     nData++;
909   } while (t[nData]<tMax+t[0] && nData<len);
910
911   p = nexp*2+1;              /* Number of parameters. */
912
913 #ifdef HAVE_LIBGSL
914   const gsl_multifit_fdfsolver_type *T
915     = gsl_multifit_fdfsolver_lmsder;
916
917   gsl_multifit_fdfsolver *s;              /* The solver itself. */
918   gsl_multifit_function_fdf fitFunction;  /* The function to be fitted. */
919   gsl_matrix *covar;  /* Covariance matrix for the parameters.
920                        * We'll not use the result, though. */
921   gsl_vector_view theParams;
922
923   nData = 0;
924   do {
925     nData++;
926   } while (t[nData]<tMax+t[0] && nData<len);
927
928   guess = NULL;
929   n = nData;
930
931   snew(guess, p);
932   snew(A, p);
933   covar = gsl_matrix_alloc (p, p);
934
935   /* Set up an initial gess for the parameters.
936    * The solver is somewhat sensitive to the initial guess,
937    * but this worked fine for a TIP3P box with -geminate dd
938    * EDIT: In fact, this seems like a good starting pont for other watermodels too. */
939   for (i=0; i<nexp; i++)
940     {
941       guess[i*2] = 0.1;
942       guess[i*2+1] = -0.5 + (((double)i)/nexp - 0.5)*0.3;
943     }
944   guess[nexp * 2] = 0.01;
945
946   theParams = gsl_vector_view_array(guess, p);
947
948   snew(BD,1);
949   BD->n     = n;
950   BD->y     = ct;
951   BD->tDelta = t[1]-t[0];
952   BD->nexp = nexp;
953
954   fitFunction.f      =  &balFunc_f;
955   fitFunction.df     =  &balFunc_df;
956   fitFunction.fdf    =  &balFunc_fdf;
957   fitFunction.n      =  nData;
958   fitFunction.p      =  p;
959   fitFunction.params =  BD;
960
961   s = gsl_multifit_fdfsolver_alloc (T, nData, p);
962   if (s==NULL)
963     gmx_fatal(FARGS, "Could not set up the nonlinear solver.");
964
965   gsl_multifit_fdfsolver_set(s, &fitFunction, &theParams.vector);
966
967   /* \=============================================/ */
968
969   iter = 0;
970   do
971     {
972       iter++;
973       status = gsl_multifit_fdfsolver_iterate (s);
974       
975       if (status)
976         break;
977       status = gsl_multifit_test_delta (s->dx, s->x, 1e-4, 1e-4);
978     }
979   while (iter < 5000 && status == GSL_CONTINUE);
980
981   if (iter == 5000)
982     {
983       fprintf(stderr, "The non-linear fitting did not converge in 5000 steps.\n"
984              "Check the quality of the fit!\n");
985     }
986   else
987     {
988       fprintf(stderr, "Non-linear fitting of ballistic term converged in %d steps.\n\n", (int)iter);
989     }
990   for (i=0; i<nexp; i++) {
991     fprintf(stdout, "%c * exp(%c * t) + ", 'A'+(char)i*2, 'B'+(char)i*2);
992   }
993
994   fprintf(stdout, "%c\n", 'A'+(char)nexp*2);
995   fprintf(stdout, "Here are the actual numbers for A-%c:\n", 'A'+nexp*2);
996
997   for (i=0; i<nexp; i++)
998     {
999       A[i*2]  = gsl_vector_get(s->x, i*2);
1000       A[i*2+1] = gsl_vector_get(s->x, i*2+1);
1001       fprintf(stdout, " %g*exp(%g * x) +", A[i*2], A[i*2+1]);
1002     }
1003   A[i*2] = gsl_vector_get(s->x, i*2);          /* The last and constant term */
1004   fprintf(stdout, " %g\n", A[i*2]);
1005
1006   fflush(stdout);
1007
1008   /* Implement some check for parameter quality */
1009   for (i=0; i<nexp; i++)
1010     {
1011       if (A[i*2]<0 || A[i*2]>1) {
1012         fprintf(stderr, "WARNING: ----------------------------------\n"
1013                " | A coefficient does not lie within [0,1].\n"
1014                " | This may or may not be a problem.\n"
1015                " | Double check the quality of the fit!\n");
1016       }
1017       if (A[i*2+1]>0) {
1018         fprintf(stderr, "WARNING: ----------------------------------\n"
1019                " | One factor in the exponent is positive.\n"
1020                " | This could be a problem if the coefficient\n"
1021                " | is large. Double check the quality of the fit!\n");
1022       }
1023     }
1024   if (A[i*2]<0 || A[i*2]>1) {
1025     fprintf(stderr, "WARNING: ----------------------------------\n"
1026            " | The constant term does not lie within [0,1].\n"
1027            " | This may or may not be a problem.\n"
1028            " | Double check the quality of the fit!\n");
1029   }
1030
1031   /* Sort the terms */
1032   sorted = (nexp > 1) ?  FALSE : TRUE;
1033   while (!sorted)
1034     {
1035       sorted = TRUE;
1036       for (i=0;i<nexp-1;i++)
1037         {
1038           ddt[0] = A[i*2] * A[i*2+1];
1039           ddt[1] =A[i*2+2] * A[i*2+3];
1040           
1041           if ((bDerivative && (ddt[0]<0 && ddt[1]<0 && ddt[0]>ddt[1])) || /* Compare derivative at t=0... */
1042               (!bDerivative && (A[i*2+1] > A[i*2+3])))                    /* Or just the coefficient in the exponent */
1043             {
1044               sorted = FALSE;
1045               a[0] = A[i*2];  /* coefficient */
1046               a[1] = A[i*2+1]; /* parameter in the exponent */
1047               
1048               A[i*2] = A[i*2+2];
1049               A[i*2+1] = A[i*2+3];
1050               
1051               A[i*2+2] = a[0];
1052               A[i*2+3] = a[1];
1053             }
1054         }
1055     }
1056
1057   /* Subtract the fastest component */
1058   fprintf(stdout, "Fastest component is %g * exp(%g * t)\n"
1059          "Subtracting fastest component from ACF.\n", A[0], A[1]);
1060
1061   for (i=0; i<len; i++) {
1062     ct[i] = (ct[i] - A[0] * exp(A[1] * i*BD->tDelta)) / (1-A[0]);
1063   }
1064
1065   sfree(guess);
1066   sfree(A);
1067
1068   gsl_multifit_fdfsolver_free(s);
1069   gsl_matrix_free(covar);
1070   fflush(stdout);
1071
1072 #else
1073   /* We have no gsl. */
1074   fprintf(stderr, "Sorry, can't take away ballistic component without gsl. "
1075          "Recompile using --with-gsl.\n");
1076   return;
1077 #endif /* HAVE_LIBGSL */
1078
1079 }
1080
1081 extern void dumpN(const real *e, const int nn, char *fn)
1082 {
1083   /* For debugging only */
1084   int i;
1085   FILE *f;
1086   char standardName[] = "Nt.xvg";
1087   if (fn == NULL) {
1088     fn = standardName;
1089   }
1090
1091   f = fopen(fn, "w");
1092   fprintf(f,
1093           "@ type XY\n"
1094           "@ xaxis label \"Frame\"\n"
1095           "@ yaxis label \"N\"\n"
1096           "@ s0 line type 3\n");
1097
1098   for (i=0; i<nn; i++) {
1099     fprintf(f, "%-10i %-g\n", i, e[i]);
1100   }
1101
1102   fclose(f);
1103 }
1104
1105 static real* d2r(const double *d, const int nn)
1106 {
1107   real *r;
1108   int i;
1109   
1110   snew(r, nn);
1111   for (i=0; i<nn; i++)
1112     r[i] = (real)d[i];
1113
1114   return r;
1115 }
1116
1117 static void _patchBad(double *ct, int n, double dy)
1118 {
1119   /* Just do lin. interpolation for now. */
1120   int i;
1121
1122   for (i=1; i<n; i++)
1123     {
1124       ct[i] = ct[0]+i*dy;
1125     }
1126 }
1127
1128 static void patchBadPart(double *ct, int n)
1129 {
1130   _patchBad(ct,n,(ct[n] - ct[0])/n);
1131 }
1132
1133 static void patchBadTail(double *ct, int n)
1134 {
1135   _patchBad(ct+1,n-1,ct[1]-ct[0]);
1136
1137 }
1138
1139 extern void fixGemACF(double *ct, int len)
1140 {
1141   int i, j, b, e;
1142   gmx_bool bBad;
1143
1144   /* Let's separate two things:
1145    * - identification of bad parts
1146    * - patching of bad parts.
1147    */
1148   
1149   b = 0; /* Start of a bad stretch */
1150   e = 0; /* End of a bad stretch */
1151   bBad = FALSE;
1152
1153   /* An acf of binary data must be one at t=0. */
1154   if (abs(ct[0]-1.0) > 1e-6)
1155     {
1156       ct[0] = 1.0;
1157       fprintf(stderr, "|ct[0]-1.0| = %1.6d. Setting ct[0] to 1.0.\n", abs(ct[0]-1.0));
1158     }
1159
1160   for (i=0; i<len; i++)
1161     {
1162       
1163 #ifdef HAS_ISFINITE
1164       if (isfinite(ct[i]))
1165 #elif defined(HAS__ISFINITE)
1166       if (_isfinite(ct[i]))
1167 #else
1168       if(1)
1169 #endif
1170         {
1171           if (!bBad)
1172             {
1173               /* Still on a good stretch. Proceed.*/
1174               continue;
1175             }
1176
1177           /* Patch up preceding bad stretch. */
1178           if (i == (len-1))
1179             {
1180               /* It's the tail */
1181               if (b <= 1)
1182                 {
1183                   gmx_fatal(FARGS, "The ACF is mostly NaN or Inf. Aborting.");
1184                 }
1185               patchBadTail(&(ct[b-2]), (len-b)+1);
1186             }
1187
1188           e = i;
1189           patchBadPart(&(ct[b-1]), (e-b)+1);
1190           bBad = FALSE;
1191         }
1192       else
1193         {
1194           if (!bBad)
1195             {
1196               b = i;
1197           
1198               bBad = TRUE;
1199             }
1200         }
1201     }
1202 }