Fixed a bug in the pdb-writing code.
[gromacs.git] / src / tools / levenmar.c
blob6348a4d5cf3b0f0ca4f88eba1ee441249f6e8465
1 /*
2 * $Id$
3 *
4 * This source code is part of
5 *
6 * G R O M A C S
7 *
8 * GROningen MAchine for Chemical Simulations
9 *
10 * VERSION 3.1
11 * Copyright (c) 1991-2001, University of Groningen, The Netherlands
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * If you want to redistribute modifications, please consider that
18 * scientific software is very special. Version control is crucial -
19 * bugs must be traceable. We will be happy to consider code for
20 * inclusion in the official distribution, but derived work must not
21 * be called official GROMACS. Details are found in the README & COPYING
22 * files - if they are missing, get the official version at www.gromacs.org.
24 * To help us fund GROMACS development, we humbly ask that you cite
25 * the papers on the package - you can find them in the top README file.
27 * For more info, check our website at http://www.gromacs.org
29 * And Hey:
30 * GROtesk MACabre and Sinister
32 static char *SRCID_levenmar_c = "$Id$";
33 #include <math.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include "types/simple.h"
38 static void nrerror(char error_text[], bool bExit)
40 fprintf(stderr,"Numerical Recipes run-time error...\n");
41 fprintf(stderr,"%s\n",error_text);
42 if (bExit) {
43 fprintf(stderr,"...now exiting to system...\n");
44 exit(1);
48 /* dont use the keyword vector - it will clash with the
49 * altivec extensions used for powerpc processors.
52 static real *rvector(int nl,int nh)
54 real *v;
56 v=(real *)malloc((unsigned) (nh-nl+1)*sizeof(real));
57 if (!v) nrerror("allocation failure in rvector()", TRUE);
58 return v-nl;
61 static int *ivector(int nl, int nh)
63 int *v;
65 v=(int *)malloc((unsigned) (nh-nl+1)*sizeof(int));
66 if (!v) nrerror("allocation failure in ivector()", TRUE);
67 return v-nl;
70 static double *dvector(int nl, int nh)
72 double *v;
74 v=(double *)malloc((unsigned) (nh-nl+1)*sizeof(double));
75 if (!v) nrerror("allocation failure in dvector()", TRUE);
76 return v-nl;
81 static real **matrix1(int nrl, int nrh, int ncl, int nch)
83 int i;
84 real **m;
86 m=(real **) malloc((unsigned) (nrh-nrl+1)*sizeof(real*));
87 if (!m) nrerror("allocation failure 1 in matrix1()", TRUE);
88 m -= nrl;
90 for(i=nrl;i<=nrh;i++) {
91 m[i]=(real *) malloc((unsigned) (nch-ncl+1)*sizeof(real));
92 if (!m[i]) nrerror("allocation failure 2 in matrix1()", TRUE);
93 m[i] -= ncl;
95 return m;
98 static double **dmatrix(int nrl, int nrh, int ncl, int nch)
100 int i;
101 double **m;
103 m=(double **) malloc((unsigned) (nrh-nrl+1)*sizeof(double*));
104 if (!m) nrerror("allocation failure 1 in dmatrix()", TRUE);
105 m -= nrl;
107 for(i=nrl;i<=nrh;i++) {
108 m[i]=(double *) malloc((unsigned) (nch-ncl+1)*sizeof(double));
109 if (!m[i]) nrerror("allocation failure 2 in dmatrix()", TRUE);
110 m[i] -= ncl;
112 return m;
115 static int **imatrix1(int nrl, int nrh, int ncl, int nch)
117 int i,**m;
119 m=(int **)malloc((unsigned) (nrh-nrl+1)*sizeof(int*));
120 if (!m) nrerror("allocation failure 1 in imatrix1()", TRUE);
121 m -= nrl;
123 for(i=nrl;i<=nrh;i++) {
124 m[i]=(int *)malloc((unsigned) (nch-ncl+1)*sizeof(int));
125 if (!m[i]) nrerror("allocation failure 2 in imatrix1()", TRUE);
126 m[i] -= ncl;
128 return m;
133 static real **submatrix(real **a, int oldrl, int oldrh, int oldcl,
134 int newrl, int newcl)
136 int i,j;
137 real **m;
139 m=(real **) malloc((unsigned) (oldrh-oldrl+1)*sizeof(real*));
140 if (!m) nrerror("allocation failure in submatrix()", TRUE);
141 m -= newrl;
143 for(i=oldrl,j=newrl;i<=oldrh;i++,j++) m[j]=a[i]+oldcl-newcl;
145 return m;
150 static void free_vector(real *v, int nl)
152 free((char*) (v+nl));
155 static void free_ivector(int *v, int nl)
157 free((char*) (v+nl));
160 static void free_dvector(int *v, int nl)
162 free((char*) (v+nl));
167 static void free_matrix(real **m, int nrl, int nrh, int ncl)
169 int i;
171 for(i=nrh;i>=nrl;i--) free((char*) (m[i]+ncl));
172 free((char*) (m+nrl));
175 static void free_dmatrix(double **m, int nrl, int nrh, int ncl)
177 int i;
179 for(i=nrh;i>=nrl;i--) free((char*) (m[i]+ncl));
180 free((char*) (m+nrl));
183 static void free_imatrix(int **m, int nrl, int nrh, int ncl)
185 int i;
187 for(i=nrh;i>=nrl;i--) free((char*) (m[i]+ncl));
188 free((char*) (m+nrl));
193 static void free_submatrix(real **b, int nrl)
195 free((char*) (b+nrl));
200 static real **convert_matrix(real *a, int nrl, int nrh, int ncl, int nch)
202 int i,j,nrow,ncol;
203 real **m;
205 nrow=nrh-nrl+1;
206 ncol=nch-ncl+1;
207 m = (real **) malloc((unsigned) (nrow)*sizeof(real*));
208 if (!m) nrerror("allocation failure in convert_matrix()", TRUE);
209 m -= nrl;
210 for(i=0,j=nrl;i<=nrow-1;i++,j++) m[j]=a+ncol*i-ncl;
211 return m;
216 static void free_convert_matrix(real **b, int nrl)
218 free((char*) (b+nrl));
221 #define SWAP(a,b) {real temp=(a);(a)=(b);(b)=temp;}
223 static void dump_mat(int n,real **a)
225 int i,j;
227 for(i=1; (i<=n); i++) {
228 for(j=1; (j<=n); j++)
229 fprintf(stderr," %10.3f",a[i][j]);
230 fprintf(stderr,"\n");
234 bool gaussj(real **a, int n, real **b, int m)
236 int *indxc,*indxr,*ipiv;
237 int i,icol=0,irow=0,j,k,l,ll;
238 real big,dum,pivinv;
240 indxc=ivector(1,n);
241 indxr=ivector(1,n);
242 ipiv=ivector(1,n);
243 for (j=1;j<=n;j++) ipiv[j]=0;
244 for (i=1;i<=n;i++) {
245 big=0.0;
246 for (j=1;j<=n;j++)
247 if (ipiv[j] != 1)
248 for (k=1;k<=n;k++) {
249 if (ipiv[k] == 0) {
250 if (fabs(a[j][k]) >= big) {
251 big=fabs(a[j][k]);
252 irow=j;
253 icol=k;
255 } else if (ipiv[k] > 1) {
256 nrerror("GAUSSJ: Singular Matrix-1", FALSE);
257 return FALSE;
260 ++(ipiv[icol]);
261 if (irow != icol) {
262 for (l=1;l<=n;l++) SWAP(a[irow][l],a[icol][l])
263 for (l=1;l<=m;l++) SWAP(b[irow][l],b[icol][l])
265 indxr[i]=irow;
266 indxc[i]=icol;
267 if (a[icol][icol] == 0.0) {
268 fprintf(stderr,"irow = %d, icol = %d\n",irow,icol);
269 dump_mat(n,a);
270 nrerror("GAUSSJ: Singular Matrix-2", FALSE);
271 return FALSE;
273 pivinv=1.0/a[icol][icol];
274 a[icol][icol]=1.0;
275 for (l=1;l<=n;l++) a[icol][l] *= pivinv;
276 for (l=1;l<=m;l++) b[icol][l] *= pivinv;
277 for (ll=1;ll<=n;ll++)
278 if (ll != icol) {
279 dum=a[ll][icol];
280 a[ll][icol]=0.0;
281 for (l=1;l<=n;l++) a[ll][l] -= a[icol][l]*dum;
282 for (l=1;l<=m;l++) b[ll][l] -= b[icol][l]*dum;
285 for (l=n;l>=1;l--) {
286 if (indxr[l] != indxc[l])
287 for (k=1;k<=n;k++)
288 SWAP(a[k][indxr[l]],a[k][indxc[l]]);
290 free_ivector(ipiv,1);
291 free_ivector(indxr,1);
292 free_ivector(indxc,1);
294 return TRUE;
297 #undef SWAP
300 static void covsrt(real **covar, int ma, int lista[], int mfit)
302 int i,j;
303 real swap;
305 for (j=1;j<ma;j++)
306 for (i=j+1;i<=ma;i++) covar[i][j]=0.0;
307 for (i=1;i<mfit;i++)
308 for (j=i+1;j<=mfit;j++) {
309 if (lista[j] > lista[i])
310 covar[lista[j]][lista[i]]=covar[i][j];
311 else
312 covar[lista[i]][lista[j]]=covar[i][j];
314 swap=covar[1][1];
315 for (j=1;j<=ma;j++) {
316 covar[1][j]=covar[j][j];
317 covar[j][j]=0.0;
319 covar[lista[1]][lista[1]]=swap;
320 for (j=2;j<=mfit;j++) covar[lista[j]][lista[j]]=covar[1][j];
321 for (j=2;j<=ma;j++)
322 for (i=1;i<=j-1;i++) covar[i][j]=covar[j][i];
325 #define SWAP(a,b) {swap=(a);(a)=(b);(b)=swap;}
327 static void covsrt_new(real **covar,int ma, int ia[], int mfit)
328 /* Expand in storage the covariance matrix covar, so as to take
329 * into account parameters that are being held fixed. (For the
330 * latter, return zero covariances.)
333 int i,j,k;
334 real swap;
335 for (i=mfit+1;i<=ma;i++)
336 for (j=1;j<=i;j++) covar[i][j]=covar[j][i]=0.0;
337 k=mfit;
338 for (j=ma;j>=1;j--) {
339 if (ia[j]) {
340 for (i=1;i<=ma;i++) SWAP(covar[i][k],covar[i][j])
341 for (i=1;i<=ma;i++) SWAP(covar[k][i],covar[j][i])
342 k--;
346 #undef SWAP
348 static void mrqcof(real x[], real y[], real sig[], int ndata, real a[],
349 int ma, int lista[], int mfit,
350 real **alpha, real beta[], real *chisq,
351 void (*funcs)(real,real *,real *,real *))
353 int k,j,i;
354 real ymod,wt,sig2i,dy,*dyda;
356 dyda=rvector(1,ma);
357 for (j=1;j<=mfit;j++) {
358 for (k=1;k<=j;k++) alpha[j][k]=0.0;
359 beta[j]=0.0;
361 *chisq=0.0;
362 for (i=1;i<=ndata;i++) {
363 (*funcs)(x[i],a,&ymod,dyda);
364 sig2i=1.0/(sig[i]*sig[i]);
365 dy=y[i]-ymod;
366 for (j=1;j<=mfit;j++) {
367 wt=dyda[lista[j]]*sig2i;
368 for (k=1;k<=j;k++)
369 alpha[j][k] += wt*dyda[lista[k]];
370 beta[j] += dy*wt;
372 (*chisq) += dy*dy*sig2i;
374 for (j=2;j<=mfit;j++)
375 for (k=1;k<=j-1;k++) alpha[k][j]=alpha[j][k];
376 free_vector(dyda,1);
380 bool mrqmin(real x[], real y[], real sig[], int ndata, real a[],
381 int ma, int lista[], int mfit,
382 real **covar, real **alpha, real *chisq,
383 void (*funcs)(real,real *,real *,real *),
384 real *alamda)
386 int k,kk,j,ihit;
387 static real *da,*atry,**oneda,*beta,ochisq;
389 if (*alamda < 0.0) {
390 oneda=matrix1(1,mfit,1,1);
391 atry=rvector(1,ma);
392 da=rvector(1,ma);
393 beta=rvector(1,ma);
394 kk=mfit+1;
395 for (j=1;j<=ma;j++) {
396 ihit=0;
397 for (k=1;k<=mfit;k++)
398 if (lista[k] == j) ihit++;
399 if (ihit == 0)
400 lista[kk++]=j;
401 else if (ihit > 1) {
402 nrerror("Bad LISTA permutation in MRQMIN-1", FALSE);
403 return FALSE;
406 if (kk != ma+1) {
407 nrerror("Bad LISTA permutation in MRQMIN-2", FALSE);
408 return FALSE;
410 *alamda=0.001;
411 mrqcof(x,y,sig,ndata,a,ma,lista,mfit,alpha,beta,chisq,funcs);
412 ochisq=(*chisq);
414 for (j=1;j<=mfit;j++) {
415 for (k=1;k<=mfit;k++) covar[j][k]=alpha[j][k];
416 covar[j][j]=alpha[j][j]*(1.0+(*alamda));
417 oneda[j][1]=beta[j];
419 if (!gaussj(covar,mfit,oneda,1))
420 return FALSE;
421 for (j=1;j<=mfit;j++)
422 da[j]=oneda[j][1];
423 if (*alamda == 0.0) {
424 covsrt(covar,ma,lista,mfit);
425 free_vector(beta,1);
426 free_vector(da,1);
427 free_vector(atry,1);
428 free_matrix(oneda,1,mfit,1);
429 return TRUE;
431 for (j=1;j<=ma;j++) atry[j]=a[j];
432 for (j=1;j<=mfit;j++)
433 atry[lista[j]] = a[lista[j]]+da[j];
434 mrqcof(x,y,sig,ndata,atry,ma,lista,mfit,covar,da,chisq,funcs);
435 if (*chisq < ochisq) {
436 *alamda *= 0.1;
437 ochisq=(*chisq);
438 for (j=1;j<=mfit;j++) {
439 for (k=1;k<=mfit;k++) alpha[j][k]=covar[j][k];
440 beta[j]=da[j];
441 a[lista[j]]=atry[lista[j]];
443 } else {
444 *alamda *= 10.0;
445 *chisq=ochisq;
447 return TRUE;
451 bool mrqmin_new(real x[],real y[],real sig[],int ndata,real a[],
452 int ia[],int ma,real **covar,real **alpha,real *chisq,
453 void (*funcs)(real, real [], real *, real []),
454 real *alamda)
455 /* Levenberg-Marquardt method, attempting to reduce the value Chi^2
456 * of a fit between a set of data points x[1..ndata], y[1..ndata]
457 * with individual standard deviations sig[1..ndata], and a nonlinear
458 * function dependent on ma coefficients a[1..ma]. The input array
459 * ia[1..ma] indicates by nonzero entries those components of a that
460 * should be fitted for, and by zero entries those components that
461 * should be held fixed at their input values. The program returns
462 * current best-fit values for the parameters a[1..ma], and
463 * Chi^2 = chisq. The arrays covar[1..ma][1..ma], alpha[1..ma][1..ma]
464 * are used as working space during most iterations. Supply a routine
465 * funcs(x,a,yfit,dyda,ma) that evaluates the fitting function yfit,
466 * and its derivatives dyda[1..ma] with respect to the fitting
467 * parameters a at x. On the first call provide an initial guess for
468 * the parameters a, and set alamda < 0 for initialization (which then
469 * sets alamda=.001). If a step succeeds chisq becomes smaller and
470 * alamda de-creases by a factor of 10. If a step fails alamda grows by
471 * a factor of 10. You must call this routine repeatedly until
472 * convergence is achieved. Then, make one final call with alamda=0,
473 * so that covar[1..ma][1..ma] returns the covariance matrix, and alpha
474 * the curvature matrix.
475 * (Parameters held fixed will return zero covariances.)
478 void covsrt(real **covar, int ma, int ia[], int mfit);
479 bool gaussj(real **a, int n, real **b,int m);
480 void mrqcof_new(real x[], real y[], real sig[], int ndata, real a[],
481 int ia[], int ma, real **alpha, real beta[], real *chisq,
482 void (*funcs)(real, real [], real *, real []));
483 int j,k,l;
484 static int mfit;
485 static real ochisq,*atry,*beta,*da,**oneda;
487 if (*alamda < 0.0) { /* Initialization. */
488 atry=rvector(1,ma);
489 beta=rvector(1,ma);
490 da=rvector(1,ma);
491 for (mfit=0,j=1;j<=ma;j++)
492 if (ia[j]) mfit++;
493 oneda=matrix1(1,mfit,1,1);
494 *alamda=0.001;
495 mrqcof_new(x,y,sig,ndata,a,ia,ma,alpha,beta,chisq,funcs);
496 ochisq=(*chisq);
497 for (j=1;j<=ma;j++)
498 atry[j]=a[j];
500 for (j=1;j<=mfit;j++) { /* Alter linearized fitting matrix, by augmenting. */
501 for (k=1;k<=mfit;k++)
502 covar[j][k]=alpha[j][k]; /* diagonal elements. */
503 covar[j][j]=alpha[j][j]*(1.0+(*alamda));
504 oneda[j][1]=beta[j];
506 if (!gaussj(covar,mfit,oneda,1)) /* Matrix solution. */
507 return FALSE;
508 for (j=1;j<=mfit;j++)
509 da[j]=oneda[j][1];
510 if (*alamda == 0.0) { /* Once converged, evaluate covariance matrix. */
511 covsrt_new(covar,ma,ia,mfit);
512 free_matrix(oneda,1,mfit,1);
513 free_vector(da,1);
514 free_vector(beta,1);
515 free_vector(atry,1);
516 return TRUE;
518 for (j=0,l=1;l<=ma;l++) /* Did the trial succeed? */
519 if (ia[l]) atry[l]=a[l]+da[++j];
520 mrqcof_new(x,y,sig,ndata,atry,ia,ma,covar,da,chisq,funcs);
521 if (*chisq < ochisq) {
522 /* Success, accept the new solution. */
523 *alamda *= 0.1;
524 ochisq=(*chisq);
525 for (j=1;j<=mfit;j++) {
526 for (k=1;k<=mfit;k++) alpha[j][k]=covar[j][k];
527 beta[j]=da[j];
529 for (l=1;l<=ma;l++) a[l]=atry[l];
530 } else { /* Failure, increase alamda and return. */
531 *alamda *= 10.0;
532 *chisq=ochisq;
534 return TRUE;
537 void mrqcof_new(real x[], real y[], real sig[], int ndata, real a[],
538 int ia[], int ma, real **alpha, real beta[], real *chisq,
539 void (*funcs)(real, real [], real *, real[]))
540 /* Used by mrqmin to evaluate the linearized fitting matrix alpha, and
541 * vector beta as in (15.5.8), and calculate Chi^2.
544 int i,j,k,l,m,mfit=0;
545 real ymod,wt,sig2i,dy,*dyda;
547 dyda=rvector(1,ma);
548 for (j=1;j<=ma;j++)
549 if (ia[j]) mfit++;
550 for (j=1;j<=mfit;j++) { /* Initialize (symmetric) alpha), beta. */
551 for (k=1;k<=j;k++) alpha[j][k]=0.0;
552 beta[j]=0.0;
554 *chisq=0.0;
555 for (i=1;i<=ndata;i++) { /* Summation loop over all data. */
556 (*funcs)(x[i],a,&ymod,dyda);
557 sig2i=1.0/(sig[i]*sig[i]);
558 dy=y[i]-ymod;
559 for (j=0,l=1;l<=ma;l++) {
560 if (ia[l]) {
561 wt=dyda[l]*sig2i;
562 for (j++,k=0,m=1;m<=l;m++)
563 if (ia[m]) alpha[j][++k] += wt*dyda[m];
564 beta[j] += dy*wt;
567 *chisq += dy*dy*sig2i; /* And find Chi^2. */
569 for (j=2;j<=mfit;j++) /* Fill in the symmetric side. */
570 for (k=1;k<j;k++) alpha[k][j]=alpha[j][k];
571 free_vector(dyda,1);