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