Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/matc/src/lu.c
3196 views
1
/*****************************************************************************
2
*
3
* Elmer, A Finite Element Software for Multiphysical Problems
4
*
5
* Copyright 1st April 1995 - , CSC - IT Center for Science Ltd., Finland
6
*
7
* This library is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU Lesser General Public
9
* License as published by the Free Software Foundation; either
10
* version 2.1 of the License, or (at your option) any later version.
11
*
12
* This library is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
* Lesser General Public License for more details.
16
*
17
* You should have received a copy of the GNU Lesser General Public
18
* License along with this library (in file ../LGPL-2.1); if not, write
19
* to the Free Software Foundation, Inc., 51 Franklin Street,
20
* Fifth Floor, Boston, MA 02110-1301 USA
21
*
22
*****************************************************************************/
23
24
/*******************************************************************************
25
*
26
* LU decomposition.
27
*
28
*******************************************************************************
29
*
30
* Author: Juha Ruokolainen
31
*
32
* Address: CSC - IT Center for Science Ltd.
33
* Keilaranta 14, P.O. BOX 405
34
* 02101 Espoo, Finland
35
* Tel. +358 0 457 2723
36
* Telefax: +358 0 457 2302
37
* EMail: [email protected]
38
*
39
* Date: 30 May 1996
40
*
41
* Modified by:
42
*
43
* Date of modification:
44
*
45
******************************************************************************/
46
/***********************************************************************
47
|
48
| LU.C - Last Edited 8. 8. 1988
49
|
50
***********************************************************************/
51
52
/*======================================================================
53
|Syntax of the manual pages:
54
|
55
|FUNCTION NAME(...) params ...
56
|
57
$ usage of the function and type of the parameters
58
? explain the effects of the function
59
= return value and the type of value if not of type int
60
@ globals effected directly by this routine
61
! current known bugs or limitations
62
& functions called by this function
63
~ these functions may interest you as an alternative function or
64
| because they control this function somehow
65
^=====================================================================*/
66
67
68
/*
69
* $Id: lu.c,v 1.1.1.1 2005/04/14 13:29:14 vierinen Exp $
70
*
71
* $Log: lu.c,v $
72
* Revision 1.1.1.1 2005/04/14 13:29:14 vierinen
73
* initial matc automake package
74
*
75
* Revision 1.2 1998/08/01 12:34:45 jpr
76
*
77
* Added Id, started Log.
78
*
79
*
80
*/
81
82
#include "elmer/matc.h"
83
84
#define A(i,j) a[n * (i) + (j)]
85
86
VARIABLE *mtr_LUD(VARIABLE *var)
87
{
88
VARIABLE *res;
89
int i, n, *pivot;
90
double *a;
91
92
if (NCOL(var) != NROW(var))
93
{
94
error("LUD: Matrix must be square.\n");
95
}
96
97
res = var_temp_copy(var);
98
a = MATR(res); n = NROW(res);
99
100
pivot = (int *)ALLOCMEM(n * sizeof(int));
101
102
LUDecomp(a, n, pivot);
103
104
FREEMEM((char *)pivot);
105
106
return res;
107
}
108
109
VARIABLE *mtr_det(VARIABLE *var)
110
{
111
VARIABLE *tmp, *res;
112
int i, n, *pivot;
113
double det, *a;
114
115
if (NCOL(var) != NROW(var))
116
{
117
error("Det: Matrix must be square.\n");
118
}
119
120
tmp = var_temp_copy(var);
121
122
a = MATR(tmp); n = NROW(tmp);
123
124
pivot = (int *)ALLOCMEM(n * sizeof(int));
125
126
LUDecomp(a, n, pivot);
127
128
det = 1.0;
129
for(i = 0; i < n; i++)
130
{
131
det *= A(i,i);
132
if (pivot[i] != i) det = -det;
133
}
134
135
FREEMEM((char *)pivot); var_delete_temp(tmp);
136
137
res = var_temp_new(TYPE_DOUBLE,1,1);
138
139
M(res,0,0) = det;
140
141
return res;
142
}
143
144
VARIABLE *mtr_inv(VARIABLE *var)
145
{
146
VARIABLE *ptr;
147
148
int i, j , k, n, *pivot;
149
double s, *a;
150
151
if (NCOL(var) != NROW(var))
152
{
153
error("Inv: Matrix must be square.\n");
154
}
155
156
ptr = var_temp_copy(var);
157
158
a = MATR(ptr); n = NROW(ptr);
159
160
pivot = (int *)ALLOCMEM(n * sizeof(int));
161
162
/*
163
* AP = LU
164
*/
165
LUDecomp(a, n, pivot);
166
for(i = 0; i < n; i++)
167
{
168
if (A(i,i) == 0)
169
error("Inv: Matrix is singular.\n");
170
A(i,i) = 1.0 / A(i,i);
171
}
172
173
/*
174
* INV(U)
175
*/
176
for(i = n - 2; i >= 0; i--)
177
for(j = n - 1; j > i; j--)
178
{
179
s = -A(i,j);
180
for(k = i+1; k<j; k++)
181
s = s - A(i,k) * A(k,j);
182
A(i,j) = s;
183
}
184
185
/*
186
* INV(L)
187
*/
188
for(i = n - 2; i >= 0; i--)
189
for(j = n - 1; j > i; j--)
190
{
191
s = 0.0;
192
for(k = i + 1; k <= j; k++)
193
s = s - A(j,k) * A(k,i);
194
A(j,i) = A(i,i) * s;
195
}
196
197
/*
198
* A = INV(AP)
199
*/
200
for(i = 0; i < n; i++)
201
for(j = 0; j < n; j++)
202
{
203
s = 0.0;
204
for(k = max(i,j); k < n; k++)
205
if (k != i)
206
s += A(i,k) * A(k,j);
207
else
208
s += A(k,j);
209
A(i,j) = s;
210
}
211
212
/*
213
* A = INV(A) (at last)
214
*/
215
for(i = n-1; i >= 0; i--)
216
if (pivot[i] != i)
217
for(j = 0; j < n; j++)
218
{
219
s = A(i,j);
220
A(i,j) = A(pivot[i],j);
221
A(pivot[i],j) = s;
222
}
223
224
225
FREEMEM((char *)pivot);
226
227
return ptr;
228
}
229
230
/*
231
* LU- decomposition by gaussian elimination. Row pivoting is used.
232
*
233
* result : AP = L'U ; L' = LD; pivot[i] is the swapped column
234
* number for column i (for pivoting).
235
*
236
* Result is stored in place of original matrix.
237
*
238
*/
239
void LUDecomp(double *a, int n, int pivot[])
240
{
241
double swap;
242
int i, j, k, l;
243
244
for (i = 0; i<n; i++)
245
{
246
j = i;
247
for(k=i+1; k<n; k++)
248
if (abs(A(i,k)) > abs(A(i,j))) j = k;
249
250
if (A(i,j) == 0.0)
251
{
252
error("LUDecomp: Matrix is singular.\n");
253
}
254
255
pivot[i] = j;
256
257
if (j != i)
258
{
259
for(k=0; k<=i; k++ )
260
{
261
swap = A(k,i);
262
A(k,i) = A(k,j);
263
A(k,j) = swap;
264
}
265
}
266
267
for(k = i + 1; k < n; k++)
268
A(i,k) = A(i,k) / A(i,i);
269
270
for(k = i+1; k<n; k++)
271
{
272
if (j != i)
273
{
274
swap = A(k,i);
275
A(k,i) = A(k,j);
276
A(k,j) = swap;
277
}
278
for(l = i + 1; l < n; l++)
279
A(k,l) = A(k,l) - A(i,l) * A(k,i);
280
}
281
}
282
283
pivot[n - 1] = n - 1;
284
if ( A(n-1,n-1) == 0.0)
285
{
286
error("LUDecomp: Matrix is singular.\n");
287
}
288
}
289
290