Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/post/src/LUDecomp.c
3196 views
1
#include <stdio.h>
2
#include <stdlib.h>
3
#include <math.h>
4
/* #include <malloc.h> */
5
6
#define MAX(x,y) ( (x) > (y) ? (x) : (y) )
7
#define MIN(x,y) ( (x) > (y) ? (y) : (x) )
8
#define ABS(x) ( (x) > 0 ? (x) : ( -(x) ) )
9
10
#define AEPS 1.0e-15
11
12
#define ALLOCMEM( s ) malloc( s )
13
#define FREEMEM( p ) free( p )
14
15
#define A( i, j ) a[n * ( i ) + ( j )]
16
17
static void ludecomp( double *, int, int * );
18
19
void lu_mtrinv( double *a, int n )
20
{
21
int i,j,k;
22
int *pivot;
23
24
double s;
25
26
pivot = (int *)ALLOCMEM(n*sizeof(int));
27
28
/*
29
* AP = LU
30
*/
31
ludecomp( a,n,pivot );
32
33
for( i=0; i<n; i++ )
34
{
35
if ( ABS(A(i,i))<AEPS )
36
{
37
fprintf( stderr, "Inv: Matrix is singular.\n" );
38
return;
39
}
40
A(i,i) = 1.0/A(i,i);
41
}
42
43
/*
44
* INV(U)
45
*/
46
for( i=n-2; i>=0; i-- )
47
for( j=n-1; j>i; j-- )
48
{
49
s = -A(i,j);
50
for( k=i+1; k<j; k++ ) s -= A(i,k)*A(k,j);
51
A(i,j) = s;
52
}
53
54
/*
55
* INV(L)
56
*/
57
for( i=n-2; i>=0; i-- )
58
for( j=n-1; j>i; j-- )
59
{
60
s = 0.0;
61
for( k=i+1; k<=j; k++ ) s -= A(j,k)*A(k,i);
62
A(j,i) = A(i,i)*s;
63
}
64
65
/*
66
* A = INV(AP)
67
*/
68
for( i=0; i<n; i++ )
69
for( j=0; j<n; j++ )
70
{
71
s = 0.0;
72
for( k=MAX(i,j); k<n; k++ )
73
{
74
if ( k!=i )
75
s += A(i,k)*A(k,j);
76
else
77
s += A(k,j);
78
79
A(i,j) = s;
80
}
81
}
82
83
/*
84
* A = INV(A) (at last)
85
*/
86
for( i=n-1; i>=0; i-- )
87
if ( pivot[i]!=i )
88
for( j=0; j<n; j++ )
89
{
90
s = A(i,j);
91
A(i,j) = A(pivot[i],j);
92
A(pivot[i],j) = s;
93
}
94
95
FREEMEM((char *)pivot);
96
}
97
98
/*
99
* LU- decomposition by gaussian elimination. Row pivoting is used.
100
*
101
* result: AP = L'U; L' = LD; pviot[i] is the swapped column number
102
* for column i.
103
*
104
* Result is stored in place of original matrix.
105
*
106
*/
107
static void ludecomp( double *a, int n, int *pivot )
108
{
109
double swap;
110
int i,j,k,l;
111
112
for( i=0; i<n-1; i++ )
113
{
114
j = i;
115
for( k=i+1; k<n; k++ ) if ( ABS(A(i,k)) > ABS(A(i,j)) ) j = k;
116
117
if ( ABS(A(i,j)) < AEPS )
118
{
119
fprintf( stderr, "LUDecomp: Matrix is (at least almost) singular, %d %d.\n", i, j );
120
return;
121
}
122
123
pivot[i] = j;
124
125
if ( j != i )
126
for( k=0; k<=i; k++ )
127
{
128
swap = A(k,j);
129
A(k,j) = A(k,i);
130
A(k,i) = swap;
131
}
132
133
for( k=i+1; k<n; k++ ) A(i,k) /= A(i,i);
134
135
for( k=i+1; k<n; k++ )
136
{
137
if ( j != i )
138
{
139
swap = A(k,i);
140
A(k,i) = A(k,j);
141
A(k,j) = swap;
142
}
143
144
for( l=i+1; l<n; l++ ) A(k,l) -= A(k,i) * A(i,l);
145
}
146
}
147
148
pivot[n-1] = n-1;
149
if ( ABS(A(n-1,n-1))<AEPS )
150
{
151
fprintf( stderr, "LUDecomp: Matrix is (at least almost) singular.\n" );
152
}
153
}
154
155