1 | /* matrix inversion */ |
---|
2 | /* cf Numerical Recipes LU Method for equations numbers */ |
---|
3 | /* GCCM */ |
---|
4 | /* une seule cellule concernee */ |
---|
5 | /* la matrice a est inversee seulement sur le bloc [n0;n1][n0;n1] */ |
---|
6 | /* la matrice f ressort les dy */ |
---|
7 | |
---|
8 | #include "titan.h" |
---|
9 | |
---|
10 | void solve( double **a, double *f, int n0, int n1 ) |
---|
11 | { |
---|
12 | int i,ii,imax,k,l,ll; |
---|
13 | double aamax,dum,*indx,sum,*vv,tmp; |
---|
14 | FILE *out; |
---|
15 | |
---|
16 | indx = dm1d( n0, n1 ); |
---|
17 | vv = dm1d( n0, n1 ); |
---|
18 | imax = n0; |
---|
19 | |
---|
20 | for( i = n0; i <= n1; i++ ) |
---|
21 | { |
---|
22 | aamax = 0.0e0; |
---|
23 | for( k = n0; k <= n1; k++ ) |
---|
24 | if( (tmp=fabs(a[i][k])) > aamax ) aamax = tmp; |
---|
25 | if( aamax < 1.0e-20 ) |
---|
26 | { |
---|
27 | out = fopen( "err.log", "a" ); |
---|
28 | fprintf( out, "Singular matrix. n0=%ld k=%ld aamax=%le\n", |
---|
29 | n0,k,aamax); |
---|
30 | fclose( out ); |
---|
31 | exit(0); |
---|
32 | /* aamax = 1.e-30; */ |
---|
33 | } |
---|
34 | vv[i] = 1.0e0 / aamax; /* Save the scaling */ |
---|
35 | /* |
---|
36 | if( (aamax > 1.0e100)||(aamax < 1.0e-100) ) |
---|
37 | { |
---|
38 | out = fopen( "err.log", "a" ); |
---|
39 | fprintf( out, "ATTENTION aamax = %le\n", aamax ); |
---|
40 | fclose( out ); |
---|
41 | exit( 0 ); |
---|
42 | } |
---|
43 | */ |
---|
44 | } |
---|
45 | for( k = n0; k <= n1; k++ ) |
---|
46 | { |
---|
47 | for( i = n0; i < k; i++ ) /* This is equation 2.3.12 except for i = j */ |
---|
48 | { |
---|
49 | sum = a[i][k]; |
---|
50 | for( l = n0; l < i; l++ ) |
---|
51 | sum -= ( a[i][l] * a[l][k] ); |
---|
52 | a[i][k] = sum; |
---|
53 | } |
---|
54 | aamax = 0.0e0; /* Initialize for the search for largest pivot element */ |
---|
55 | for( i = k; i <= n1; i++ ) /* This is i = j of equation 2.3.12 and */ |
---|
56 | { |
---|
57 | sum = a[i][k]; /* i = J + 1,...,N of equation 2.3.13 */ |
---|
58 | for( l = n0; l < k; l++ ) |
---|
59 | sum -= ( a[i][l] * a[l][k] ); |
---|
60 | a[i][k] = sum; |
---|
61 | dum = vv[i] * fabs(sum); /* Figure of merit for the pivot */ |
---|
62 | if( dum >= aamax ) /* Is it better than the best so far ? */ |
---|
63 | { |
---|
64 | imax = i; |
---|
65 | aamax = dum; |
---|
66 | } |
---|
67 | } |
---|
68 | if( k != imax ) /* Do we need to interchange rows ? */ |
---|
69 | { |
---|
70 | for( l = n0; l <= n1; l++ ) /* Yes, do so... */ |
---|
71 | { |
---|
72 | dum = a[imax][l]; |
---|
73 | a[imax][l] = a[k][l]; |
---|
74 | a[k][l] = dum; |
---|
75 | } |
---|
76 | vv[imax] = vv[k]; /* Also interchange the scale factor */ |
---|
77 | } |
---|
78 | indx[k] = imax; |
---|
79 | if( fabs(a[k][k]) < 1.0e-20 ) |
---|
80 | { |
---|
81 | out = fopen( "err.log", "a" ); |
---|
82 | fprintf( out, "Pivot too small. n0=%ld k=%ld fabs(a[k][k])=%le\n", |
---|
83 | n0,k,fabs(a[k][k]) ); |
---|
84 | fclose( out ); |
---|
85 | exit(0); |
---|
86 | /* a[k][k] = 1.e-20; */ |
---|
87 | } |
---|
88 | if( k != n1 ) /* If the pivot element is less than 1.0d-20 we */ |
---|
89 | { /* assume that the matrix is singular */ |
---|
90 | dum = a[k][k]; /* ( at least to the precision of the algorithm and the machine ) */ |
---|
91 | for( i = k+1; i <= n1; i++ ) /* Now, finally devide by the pivot element */ |
---|
92 | a[i][k] /= dum; |
---|
93 | } |
---|
94 | } /* Go back to the next column in the reduction */ |
---|
95 | |
---|
96 | ii = n0-1; |
---|
97 | for( i = n0; i <= n1; i++ ) |
---|
98 | { |
---|
99 | ll = indx[i]; |
---|
100 | sum = f[ll]; |
---|
101 | f[ll] = f[i]; |
---|
102 | if( ii != (n0-1) ) |
---|
103 | for( k = ii; k < i; k++ ) |
---|
104 | sum -= ( a[i][k] * f[k] ); |
---|
105 | else if( sum != 0.0e0 ) ii = i; |
---|
106 | f[i] = sum; |
---|
107 | } |
---|
108 | for( i = n1; i >= n0; i-- ) |
---|
109 | { |
---|
110 | sum = f[i]; |
---|
111 | if( i < n1 ) |
---|
112 | for( k = i+1; k <= n1; k++ ) |
---|
113 | sum -= ( a[i][k] * f[k] ); |
---|
114 | f[i] = sum / a[i][i]; |
---|
115 | } |
---|
116 | |
---|
117 | fdm1d( indx, n0 ); |
---|
118 | fdm1d( vv, n0 ); |
---|
119 | } |
---|