Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/matc/src/eig.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
* The eigenvalue/eigenvector extraction routines.
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
| EIG.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: eig.c,v 1.1.1.1 2005/04/14 13:29:14 vierinen Exp $
70
*
71
* $Log: eig.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:33 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
#define MAXITER 1000
87
#define EPS 1e-16
88
89
VARIABLE *mtr_hesse(VARIABLE *var)
90
{
91
VARIABLE *res;
92
93
double *a;
94
95
int n;
96
97
if (NCOL(var) != NROW(var))
98
{
99
error( "hesse: matrix must be square, current dimensions: [%d,%d]\n", NROW(var), NCOL(var) );
100
}
101
102
res = var_temp_copy(var);
103
104
a = MATR(res); n = NROW(res);
105
if (NROW(res) == 1) return res;
106
107
hesse(a, n, n);
108
109
return res;
110
}
111
112
VARIABLE *mtr_eig(VARIABLE *var)
113
{
114
VARIABLE *ptr, *res;
115
116
int iter, i, j, k, n;
117
double *a, b, s, t;
118
119
if (NCOL(var) != NROW(var))
120
{
121
error("eig: matrix must be square, current dimensions: [%d,%d]\n", NROW(var), NCOL(var));
122
}
123
124
ptr = var_temp_copy(var);
125
126
a = MATR(ptr); n = NROW(ptr);
127
128
if (NROW(ptr) == 1) return ptr;
129
130
hesse(a, n, n);
131
132
for(iter = 0; iter < MAXITER; iter++)
133
{
134
135
for (i = 0; i < n - 1; i++)
136
{
137
s = EPS*(abs(A(i,i))+abs(A(i+1,i+1)));
138
if (abs(A(i+1,i)) < s) A(i+1,i) = 0.0;
139
}
140
141
i = 0;
142
do
143
{
144
for(j = i; j < n - 1; j++)
145
if (A(j+1,j) != 0) break;
146
147
for(k = j; k < n - 1; k++)
148
if (A(k+1,k) == 0) break;
149
150
i = k;
151
152
} while(i < n - 1 && k - j + 1 < 3);
153
154
if (k - j + 1 < 3) break;
155
156
francis(&A(j,j), k - j + 1, n);
157
}
158
159
res = var_temp_new(TYPE_DOUBLE, n, 2);
160
161
for(i = 0, j = 0; i < n - 1; i++)
162
if (A(i+1,i) == 0)
163
M(res,j++,0) = A(i,i);
164
else
165
{
166
b = A(i,i) + A(i+1,i+1); s = b * b;
167
t = A(i,i) * A(i+1,i+1) - A(i,i+1)*A(i+1,i);
168
s = s - 4 * t;
169
if (s < 0)
170
{
171
M(res,j, 0) = b / 2;
172
M(res,j++, 1) = sqrt(-s) / 2;
173
M(res,j, 0) = b / 2;
174
M(res,j++,1) = -sqrt(-s) / 2;
175
}
176
else
177
{
178
M(res,j++, 0) = b / 2 + sqrt(s) / 2;
179
M(res,j++, 0) = b / 2 - sqrt(s) / 2;
180
}
181
i++;
182
}
183
184
if (A(n-1, n-2) == 0) M(res,j,0) = A(n-1, n-1);
185
186
var_delete_temp(ptr);
187
188
return res;
189
}
190
191
void vbcalc(double x[], double v[], double *b, int beg, int end)
192
{
193
double alpha,m,mp1;
194
int i;
195
196
m = abs(x[beg]);
197
for(i = beg + 1; i <= end; i++)
198
m = max(m,abs(x[i]));
199
200
if (m < EPS)
201
{
202
/*
203
* for(i = beg; i <= end; i++) v[i] = 0;
204
*/
205
memset(&v[beg], 0, (end-beg+1)<<3);
206
}
207
else
208
{
209
alpha = 0;
210
mp1 = 1 / m;
211
for(i = beg; i <= end; i++)
212
{
213
v[i] = x[i] * mp1;
214
alpha = alpha + v[i]*v[i];
215
}
216
alpha = sqrt(alpha);
217
*b = 1 / (alpha * (alpha + abs(v[beg])));
218
v[beg] = v[beg] + sign(v[beg]) * alpha;
219
}
220
return;
221
}
222
223
#define H(i,j) h[(i) * N + (j)]
224
225
void hesse(double *h, int DIM, int N)
226
{
227
double *v, *x, b, s;
228
int i, j, k;
229
230
x = (double *)ALLOCMEM(DIM * sizeof(double));
231
v = (double *)ALLOCMEM(DIM * sizeof(double));
232
233
for (i = 0; i < DIM - 2; i++)
234
{
235
236
for(j = i + 1; j < DIM; j++) x[j] = H(j,i);
237
238
vbcalc(x, v, &b, i + 1, DIM - 1);
239
240
if (v[i+1] == 0) break;
241
242
for(j = i + 2; j < DIM; j++)
243
{
244
x[j] = v[j]/v[i+1];
245
v[j] = b * v[i+1] * v[j];
246
}
247
v[i+1] = b * v[i+1] * v[i+1];
248
249
for(j = 0; j < DIM; j++)
250
{
251
s = 0.0;
252
for(k = i + 1; k < DIM; k++)
253
s = s + H(j,k) * v[k];
254
H(j,i+1) = H(j,i+1) - s;
255
for(k = i + 2; k < DIM; k++)
256
H(j,k) = H(j,k) - s * x[k];
257
}
258
259
for(j = 0; j < DIM; j++)
260
{
261
s = H(i+1,j);
262
for(k = i + 2; k < DIM; k++)
263
s = s + H(k,j) * x[k];
264
for(k = i + 1; k < DIM; k++)
265
H(k,j) = H(k,j) - s * v[k];
266
}
267
268
for(j = i + 2; j < DIM; j++) H(j,i) = 0;
269
}
270
FREEMEM((char *)x); FREEMEM((char *)v);
271
272
return;
273
}
274
275
276
void francis(double *h, int DIM, int N)
277
{
278
double x[3], v[3], b, s, t, bv, v0i;
279
int i, i1, j, k, n, m, end;
280
281
n = DIM - 1; m = n - 1;
282
283
t = H(m,m) * H(n,n) - H(m,n) * H(n,m);
284
s = H(m,m) + H(n,n);
285
286
x[0] = H(0,0)*H(0,0)+H(0,1)*H(1,0)-s*H(0,0)+t;
287
x[1] = H(1,0) * (H(0,0) + H(1,1) - s);
288
x[2] = H(1,0) * H(2,1);
289
290
vbcalc(x, v, &b, 0, 2);
291
292
if (v[0] == 0) return;
293
294
295
296
/*
297
* for(i = 1; i < 3; i++)
298
* {
299
* x[i] = v[i]/v[0];
300
* v[i] = b * v[0] * v[i];
301
* }
302
*/
303
bv = b * v[0];
304
305
x[1] = v[1] / v[0];
306
v[1] = bv * v[1];
307
308
x[2] = v[2] / v[0];
309
v[2] = bv * v[2];
310
311
312
313
x[0] = 1; v[0] = b * v[0] * v[0];
314
315
for(i = 0; i < DIM; i++)
316
{
317
/*
318
* s = 0.0;
319
* for(j = 0; j < 3; j++)
320
* s = s + H(i,j) * v[j];
321
*/
322
i1 = i * N;
323
s = h[i1] * v[0] + h[i1+1]*v[1] + h[i1+2]*v[2];
324
325
326
H(i,0) = H(i,0) - s;
327
/*
328
* for(j = 1; j < 3; j++)
329
* H(i,j) = H(i,j) - s * x[j];
330
*/
331
h[i1+1] = h[i1+1] - s * x[1];
332
h[i1+2] = h[i1+2] - s * x[2];
333
}
334
335
for(i = 0; i < DIM; i++)
336
{
337
/*
338
* s = H(0,i);
339
* for(j = 1; j < 3; j++)
340
* s = s + H(j,i) * x[j];
341
*/
342
s = h[i] + h[N+i]*x[1] + h[(N<<1)+i]*x[2];
343
/*
344
* for(j = 0; j < 3; j++)
345
* H(j,i) = H(j,i) - s * v[j];
346
*/
347
h[i] = h[i] - s * v[0];
348
h[N+i] = h[N+i] - s * v[1];
349
h[(N<<1)+i] = h[(N<<1)+i] - s * v[2];
350
}
351
352
for (i = 0; i < DIM - 2; i++)
353
{
354
355
end = min(2, DIM - i - 2);
356
for(j = 0; j <= end; j++) x[j] = H(i+j+1,i);
357
358
vbcalc(x, v, &b, 0, end);
359
360
if (v[0] == 0) break;
361
362
for(j = 1; j <= end; j++)
363
{
364
x[j] = v[j]/v[0];
365
v[j] = b * v[0] * v[j];
366
}
367
x[0] = 1; v[0] = b * v[0] * v[0];
368
369
for(j = 0; j < DIM; j++)
370
{
371
s = 0.0;
372
for(k = 0; k <= end; k++)
373
s = s + H(j,i+k+1) * v[k];
374
H(j,i+1) = H(j,i+1) - s;
375
for(k = 1; k <= end; k++)
376
H(j,i+k+1) = H(j,i+k+1) - s * x[k];
377
}
378
379
for(j = 0; j < DIM; j++)
380
{
381
s = H(i+1,j);
382
for(k = 1; k <= end; k++)
383
s = s + H(i+k+1,j) * x[k];
384
for(k = 0; k <= end; k++)
385
H(i+k+1,j) = H(i+k+1,j) - s * v[k];
386
}
387
388
for(j = i + 2; j < DIM; j++) H(j,i) = 0;
389
}
390
return;
391
}
392
393