/* matrix inversion */ /* cf Numerical Recipes LU Method for equations numbers */ /* GCCM */ /* similaire a inv (GP) */ /* la matrice a est inversee seulement sur le bloc [n0;n1][n0;n1] */ #include "titan.h" void solve( double ***aa, int m, int n0, int n1 ) { int i,ii,imax,j,k,l,ll; double **a,aamax,dum,*indx,sum,**vv,tmp; FILE *out; indx = dm1d( n0, n1 ); vv = dm2d( n0, n1, n0, n1 ); a = dm2d( n0, n1, n0, n1 ); imax = n0; for( i = n0; i <= n1; i++ ) for( j = n0; j <= n1; j++ ) a[i][j]=aa[m][i][j]; for( i = n0; i <= n1; i++ ) { aamax = 0.0e0; for( k = n0; k <= n1; k++ ) if( (tmp=fabs(a[i][k])) > aamax ) aamax = tmp; if( aamax < 1.0e-20 ) { out = fopen( "err.log", "a" ); fprintf( out, "Singular matrix. n0=%ld k=%ld aamax=%le\n", n0,k,aamax); fclose( out ); exit(0); /* aamax = 1.e-30; */ } vv[i][1] = 1.0e0 / aamax; /* Save the scaling */ /* if( (aamax > 1.0e100)||(aamax < 1.0e-100) ) { out = fopen( "err.log", "a" ); fprintf( out, "ATTENTION aamax = %le\n", aamax ); fclose( out ); exit( 0 ); } */ } for( k = n0; k <= n1; k++ ) { for( i = n0; i < k; i++ ) /* This is equation 2.3.12 except for i = j */ { sum = a[i][k]; for( l = n0; l < i; l++ ) sum -= ( a[i][l] * a[l][k] ); a[i][k] = sum; } aamax = 0.0e0; /* Initialize for the search for largest pivot element */ for( i = k; i <= n1; i++ ) /* This is i = j of equation 2.3.12 and */ { sum = a[i][k]; /* i = J + 1,...,N of equation 2.3.13 */ for( l = n0; l < k; l++ ) sum -= ( a[i][l] * a[l][k] ); a[i][k] = sum; dum = vv[i][1] * fabs(sum); /* Figure of merit for the pivot */ if( dum >= aamax ) /* Is it better than the best so far ? */ { imax = i; aamax = dum; } } if( k != imax ) /* Do we need to interchange rows ? */ { for( l = n0; l <= n1; l++ ) /* Yes, do so... */ { dum = a[imax][l]; a[imax][l] = a[k][l]; a[k][l] = dum; } vv[imax][1] = vv[k][1]; /* Also interchange the scale factor */ } indx[k] = imax; if( fabs(a[k][k]) < 1.0e-20 ) { out = fopen( "err.log", "a" ); fprintf( out, "Pivot too small. n0=%ld k=%ld fabs(a[k][k])=%le\n", n0,k,fabs(a[k][k]) ); fclose( out ); exit(0); /* a[k][k] = 1.e-20; */ } if( k != n1 ) /* If the pivot element is less than 1.0d-20 we */ { /* assume that the matrix is singular */ dum = a[k][k]; /* ( at least to the precision of the algorithm and the machine ) */ for( i = k+1; i <= n1; i++ ) /* Now, finally devide by the pivot element */ a[i][k] /= dum; } } /* Go back to the next column in the reduction */ for( i = n0; i <= n1; i++ ) { for( k = n0; k <= n1; k++ ) vv[i][k] = 0.0e0; vv[i][i] = 1.0e0; } for( l = n0; l <= n1; l++ ) { ii = n0-1; for( i = n0; i <= n1; i++ ) { ll = indx[i]; sum = vv[ll][l]; vv[ll][l] = vv[i][l]; if( ii != (n0-1) ) for( k = ii; k < i; k++ ) sum -= ( a[i][k] * vv[k][l] ); else if( sum != 0.0e0 ) ii = i; vv[i][l] = sum; } for( i = n1; i >= n0; i-- ) { sum = vv[i][l]; if( i < n1 ) for( k = i+1; k <= n1; k++ ) sum -= ( a[i][k] * vv[k][l] ); vv[i][l] = sum / a[i][i]; } } for( i = n0; i <= n1; i++ ) for( l = n0; l <= n1; l++ ) aa[m][i][l]=vv[i][l]; fdm1d( indx, n0 ); fdm2d( vv, n0, n1, n0 ); fdm2d( a, n0, n1, n0 ); }