Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/fem/src/LinearAlgebra.F90
5215 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
! * Authors: Juha Ruokolainen
27
! * Email: [email protected]
28
! * Web: http://www.csc.fi/elmer
29
! * Address: CSC - IT Center for Science Ltd.
30
! * Keilaranta 14
31
! * 02101 Espoo, Finland
32
! *
33
! * Original Date: 01 Oct 1996
34
! *
35
! *****************************************************************************/
36
37
!> \ingroup ElmerLib
38
!> \{
39
40
!------------------------------------------------------------------------------
41
!> Linear Algebra: LU-decomposition & matrix inverse & nonsymmetric full
42
!> matrix eigenvalues (don't use this for anything big, use for example
43
!> LAPACK routines instead...)
44
!------------------------------------------------------------------------------
45
46
#include "../config.h"
47
48
MODULE LinearAlgebra
49
50
USE Types
51
IMPLICIT NONE
52
53
CONTAINS
54
55
SUBROUTINE InvertMatrix( A,n )
56
57
INTEGER :: n
58
REAL(KIND=dp) :: A(:,:)
59
60
REAL(KIND=dp) :: s
61
INTEGER :: i,j,k
62
INTEGER :: pivot(n)
63
LOGICAL :: erroneous
64
65
! /*
66
! * AP = LU
67
! */
68
CALL LUDecomp( a,n,pivot,erroneous )
69
70
IF (erroneous) CALL Fatal('InvertMatrix', 'inversion needs successful LU-decomposition')
71
72
! /*
73
! * INV(U)
74
! */
75
DO i=N-1,1,-1
76
DO j=N,i+1,-1
77
s = -A(i,j)
78
DO k=i+1,j-1
79
s = s - A(i,k)*A(k,j)
80
END DO
81
A(i,j) = s
82
END DO
83
END DO
84
85
! /*
86
! * INV(L)
87
! */
88
DO i=n-1,1,-1
89
DO j=n,i+1,-1
90
s = 0.D00
91
DO k=i+1,j
92
s = s - A(j,k)*A(k,i)
93
END DO
94
A(j,i) = A(i,i)*s
95
END DO
96
END DO
97
98
! /*
99
! * A = INV(AP)
100
! */
101
DO i=1,n
102
DO j=1,n
103
s = 0.0D0
104
DO k=MAX(i,j),n
105
IF ( k /= i ) THEN
106
s = s + A(i,k)*A(k,j)
107
ELSE
108
s = s + A(k,j)
109
END IF
110
END DO
111
A(i,j) = s
112
END DO
113
END DO
114
115
! /*
116
! * A = INV(A) (at last)
117
! */
118
DO i=n,1,-1
119
IF ( pivot(i) /= i ) THEN
120
DO j = 1,n
121
s = A(i,j)
122
A(i,j) = A(pivot(i),j)
123
A(pivot(i),j) = s
124
END DO
125
END IF
126
END DO
127
128
END SUBROUTINE InvertMatrix
129
130
131
SUBROUTINE LUSolve( n,A,x,pivot_in )
132
REAL(KIND=dp) :: A(:,:)
133
REAL(KIND=dp) :: x(n)
134
INTEGER :: n
135
INTEGER, OPTIONAL :: pivot_in(:)
136
137
REAL(KIND=dp) :: s
138
INTEGER :: i,j
139
INTEGER :: pivot(n)
140
LOGICAL :: erroneous
141
142
! /*
143
! * AP = LU
144
! */
145
IF(PRESENT(pivot_in)) THEN
146
Pivot(1:n) = Pivot_in(1:n)
147
ELSE
148
CALL LUDecomp( A,n,pivot,erroneous )
149
IF (erroneous) CALL Fatal('LUSolve', 'LU-decomposition fails')
150
END IF
151
152
! Forward substitute
153
DO i=1,n
154
s = x(i)
155
DO j=1,i-1
156
s = s - A(i,j) * x(j)
157
END DO
158
x(i) = A(i,i) * s
159
END DO
160
161
!
162
! Backward substitute (solve x from Ux = z)
163
DO i=n,1,-1
164
s = x(i)
165
DO j=i+1,n
166
s = s - A(i,j) * x(j)
167
END DO
168
x(i) = s
169
END DO
170
171
DO i=n,1,-1
172
IF ( pivot(i) /= i ) THEN
173
s = x(i)
174
x(i) = x(pivot(i))
175
x(pivot(i)) = s
176
END IF
177
END DO
178
179
END SUBROUTINE LUSolve
180
181
182
!----------------------------------------------------------------------
183
!> LU- decomposition by gaussian elimination. Row pivoting is used.
184
!
185
!> result : AP = L'U ; L' = LD; pivot[i] is the swapped column number
186
!> for column i.
187
!
188
!> Result is stored in place of original matrix.
189
!----------------------------------------------------------------------
190
SUBROUTINE LUDecomp( a,n,pivot,erroneous )
191
192
REAL(KIND=dp), DIMENSION (:,:) :: a
193
INTEGER :: n
194
INTEGER, DIMENSION (:) :: pivot
195
LOGICAL, OPTIONAL :: erroneous
196
197
INTEGER :: i,j,k,l
198
REAL(KIND=dp) :: swap
199
200
IF (PRESENT(erroneous)) erroneous = .FALSE.
201
202
DO i=1,n
203
j = i
204
DO k=i+1,n
205
IF ( ABS(A(i,k)) > ABS(A(i,j)) ) j = k
206
END DO
207
208
IF ( ABS(A(i,j)) == 0.0d0) THEN
209
CALL Error( 'LUDecomp', 'Matrix is singular.' )
210
IF (PRESENT(erroneous)) erroneous = .TRUE.
211
RETURN
212
END IF
213
214
pivot(i) = j
215
216
IF ( j /= i ) THEN
217
DO k=1,i
218
swap = A(k,j)
219
A(k,j) = A(k,i)
220
A(k,i) = swap
221
END DO
222
END IF
223
224
DO k=i+1,n
225
A(i,k) = A(i,k) / A(i,i)
226
END DO
227
228
DO k=i+1,n
229
IF ( j /= i ) THEN
230
swap = A(k,i)
231
A(k,i) = A(k,j)
232
A(k,j) = swap
233
END IF
234
235
DO l=i+1,n
236
A(k,l) = A(k,l) - A(k,i) * A(i,l)
237
END DO
238
END DO
239
END DO
240
241
pivot(n) = n
242
IF ( ABS(A(n,n)) == 0.0d0 ) THEN
243
CALL Error( 'LUDecomp', 'Matrix is (at least almost) singular.' )
244
END IF
245
246
DO i=1,n
247
IF ( ABS(A(i,i)) == 0.0d0 ) THEN
248
CALL Error( 'LUSolve', 'Matrix is singular.' )
249
IF (PRESENT(erroneous)) erroneous = .TRUE.
250
RETURN
251
END IF
252
A(i,i) = 1.0_dp / A(i,i)
253
END DO
254
255
END SUBROUTINE LUDecomp
256
257
258
259
SUBROUTINE ComplexInvertMatrix( A,n )
260
261
COMPLEX(KIND=dp), DIMENSION(:,:) :: A
262
INTEGER :: n
263
264
COMPLEX(KIND=dp) :: s
265
INTEGER :: i,j,k
266
INTEGER :: pivot(n)
267
LOGICAL :: erroneous
268
269
! /*
270
! * AP = LU
271
! */
272
CALL ComplexLUDecomp( a,n,pivot,erroneous )
273
274
IF (erroneous) CALL Fatal('ComplexInvertMatrix', 'inversion needs successful LU-decomposition')
275
276
DO i=1,n
277
IF ( ABS(A(i,i))==0.0d0 ) THEN
278
CALL Error( 'ComplexInvertMatrix', 'Matrix is singular.' )
279
RETURN
280
END IF
281
A(i,i) = 1.0D0/A(i,i)
282
END DO
283
284
! /*
285
! * INV(U)
286
! */
287
DO i=N-1,1,-1
288
DO j=N,i+1,-1
289
s = -A(i,j)
290
DO k=i+1,j-1
291
s = s - A(i,k)*A(k,j)
292
END DO
293
A(i,j) = s
294
END DO
295
END DO
296
297
! /*
298
! * INV(L)
299
! */
300
DO i=n-1,1,-1
301
DO j=n,i+1,-1
302
s = 0.D00
303
DO k=i+1,j
304
s = s - A(j,k)*A(k,i)
305
END DO
306
A(j,i) = A(i,i)*s
307
END DO
308
END DO
309
310
! /*
311
! * A = INV(AP)
312
! */
313
DO i=1,n
314
DO j=1,n
315
s = 0.0D0
316
DO k=MAX(i,j),n
317
IF ( k /= i ) THEN
318
s = s + A(i,k)*A(k,j)
319
ELSE
320
s = s + A(k,j)
321
END IF
322
END DO
323
A(i,j) = s
324
END DO
325
END DO
326
327
! /*
328
! * A = INV(A) (at last)
329
! */
330
DO i=n,1,-1
331
IF ( pivot(i) /= i ) THEN
332
DO j = 1,n
333
s = A(i,j)
334
A(i,j) = A(pivot(i),j)
335
A(pivot(i),j) = s
336
END DO
337
END IF
338
END DO
339
340
END SUBROUTINE ComplexInvertMatrix
341
342
!-------------------------------------------------------------------------
343
!> LU- decomposition by gaussian elimination for complex valued linear system.
344
!> Row pivoting is used.
345
!
346
!> result : AP = L'U ; L' = LD; pivot[i] is the swapped column number
347
!> for column i.
348
!
349
!> Result is stored in place of original matrix.
350
!-------------------------------------------------------------------------
351
352
SUBROUTINE ComplexLUDecomp( a,n,pivot,erroneous )
353
354
COMPLEX(KIND=dp), DIMENSION (:,:) :: a
355
INTEGER :: n
356
INTEGER, DIMENSION (:) :: pivot
357
LOGICAL, OPTIONAL :: erroneous
358
359
INTEGER :: i,j,k,l
360
COMPLEX(KIND=dp) :: swap
361
362
IF (PRESENT(erroneous)) erroneous = .FALSE.
363
364
DO i=1,n
365
j = i
366
DO k=i+1,n
367
IF ( ABS(A(i,k)) > ABS(A(i,j)) ) j = k
368
END DO
369
370
IF ( ABS(A(i,j))==0.0d0 ) THEN
371
CALL Error( 'ComplexLUDecomp', 'Matrix is singular.' )
372
IF (PRESENT(erroneous)) erroneous = .TRUE.
373
RETURN
374
END IF
375
376
pivot(i) = j
377
378
IF ( j /= i ) THEN
379
DO k=1,i
380
swap = A(k,j)
381
A(k,j) = A(k,i)
382
A(k,i) = swap
383
END DO
384
END IF
385
386
DO k=i+1,n
387
A(i,k) = A(i,k) / A(i,i)
388
END DO
389
390
DO k=i+1,n
391
IF ( j /= i ) THEN
392
swap = A(k,i)
393
A(k,i) = A(k,j)
394
A(k,j) = swap
395
END IF
396
397
DO l=i+1,n
398
A(k,l) = A(k,l) - A(k,i) * A(i,l)
399
END DO
400
END DO
401
END DO
402
403
pivot(n) = n
404
IF ( ABS(A(n,n))==0.0d0 ) THEN
405
CALL Error( 'ComplexLUDecomp', 'Matrix is (at least almost) singular.' )
406
END IF
407
END SUBROUTINE ComplexLUDecomp
408
409
410
!------------------------------------------------------------------------------
411
!> Solves a 2 x 2 linear system.
412
!------------------------------------------------------------------------------
413
SUBROUTINE SolveLinSys2x2( A, x, b )
414
!------------------------------------------------------------------------------
415
REAL(KIND=dp), INTENT(out) :: x(:)
416
REAL(KIND=dp), INTENT(in) :: A(:,:),b(:)
417
!------------------------------------------------------------------------------
418
REAL(KIND=dp) :: detA
419
!------------------------------------------------------------------------------
420
detA = A(1,1) * A(2,2) - A(1,2) * A(2,1)
421
422
IF ( detA == 0.0d0 ) THEN
423
WRITE( Message, * ) 'Singular matrix, sorry!'
424
CALL Error( 'SolveLinSys2x2', Message )
425
RETURN
426
END IF
427
428
detA = 1.0d0 / detA
429
x(1) = detA * (A(2,2) * b(1) - A(1,2) * b(2))
430
x(2) = detA * (A(1,1) * b(2) - A(2,1) * b(1))
431
!------------------------------------------------------------------------------
432
END SUBROUTINE SolveLinSys2x2
433
!------------------------------------------------------------------------------
434
435
436
!------------------------------------------------------------------------------
437
!> Solves a 3 x 3 linear system.
438
!------------------------------------------------------------------------------
439
SUBROUTINE SolveLinSys3x3( A, x, b )
440
!------------------------------------------------------------------------------
441
REAL(KIND=dp), INTENT(out) :: x(:)
442
REAL(KIND=dp), INTENT(in) :: A(:,:),b(:)
443
!------------------------------------------------------------------------------
444
REAL(KIND=dp) :: C(2,2),y(2),g(2),s,t,q
445
!------------------------------------------------------------------------------
446
447
IF ( ABS(A(1,1))>ABS(A(1,2)) .AND. ABS(A(1,1))>ABS(A(1,3)) ) THEN
448
q = 1.0d0 / A(1,1)
449
s = q * A(2,1)
450
t = q * A(3,1)
451
C(1,1) = A(2,2) - s * A(1,2)
452
C(1,2) = A(2,3) - s * A(1,3)
453
C(2,1) = A(3,2) - t * A(1,2)
454
C(2,2) = A(3,3) - t * A(1,3)
455
456
g(1) = b(2) - s * b(1)
457
g(2) = b(3) - t * b(1)
458
CALL SolveLinSys2x2( C,y,g )
459
460
x(2) = y(1)
461
x(3) = y(2)
462
x(1) = q * ( b(1) - A(1,2) * x(2) - A(1,3) * x(3) )
463
ELSE IF ( ABS(A(1,2)) > ABS(A(1,3)) ) THEN
464
q = 1.0d0 / A(1,2)
465
s = q * A(2,2)
466
t = q * A(3,2)
467
C(1,1) = A(2,1) - s * A(1,1)
468
C(1,2) = A(2,3) - s * A(1,3)
469
C(2,1) = A(3,1) - t * A(1,1)
470
C(2,2) = A(3,3) - t * A(1,3)
471
472
g(1) = b(2) - s * b(1)
473
g(2) = b(3) - t * b(1)
474
CALL SolveLinSys2x2( C,y,g )
475
476
x(1) = y(1)
477
x(3) = y(2)
478
x(2) = q * ( b(1) - A(1,1) * x(1) - A(1,3) * x(3) )
479
ELSE
480
q = 1.0d0 / A(1,3)
481
s = q * A(2,3)
482
t = q * A(3,3)
483
C(1,1) = A(2,1) - s * A(1,1)
484
C(1,2) = A(2,2) - s * A(1,2)
485
C(2,1) = A(3,1) - t * A(1,1)
486
C(2,2) = A(3,2) - t * A(1,2)
487
488
g(1) = b(2) - s * b(1)
489
g(2) = b(3) - t * b(1)
490
CALL SolveLinSys2x2( C,y,g )
491
492
x(1) = y(1)
493
x(2) = y(2)
494
x(3) = q * ( b(1) - A(1,1) * x(1) - A(1,2) * x(2) )
495
END IF
496
!------------------------------------------------------------------------------
497
END SUBROUTINE SolveLinSys3x3
498
!------------------------------------------------------------------------------
499
500
501
!> Solves a small dense linear system using Lapack routines
502
!------------------------------------------------------------------------------
503
SUBROUTINE SolveLinSys( A, x, n )
504
!------------------------------------------------------------------------------
505
INTEGER :: n
506
REAL(KIND=dp) :: A(n,n), x(n), b(n)
507
508
INTERFACE
509
SUBROUTINE SolveLapack( N,A,x )
510
INTEGER N
511
DOUBLE PRECISION A(n*n),x(n)
512
END SUBROUTINE
513
END INTERFACE
514
515
!------------------------------------------------------------------------------
516
SELECT CASE(n)
517
CASE(1)
518
x(1) = x(1) / A(1,1)
519
CASE(2)
520
b = x
521
CALL SolveLinSys2x2(A,x,b)
522
CASE(3)
523
b = x
524
CALL SolveLinSys3x3(A,x,b)
525
CASE DEFAULT
526
CALL SolveLapack(n,A,x)
527
END SELECT
528
!------------------------------------------------------------------------------
529
END SUBROUTINE SolveLinSys
530
!------------------------------------------------------------------------------
531
532
533
!------------------------------------------------------------------------------
534
SUBROUTINE InvertMatrix3x3( G,GI,detG )
535
!------------------------------------------------------------------------------
536
REAL(KIND=dp) :: G(3,3),GI(3,3)
537
REAL(KIND=dp) :: detG, s
538
!------------------------------------------------------------------------------
539
s = 1.0 / DetG
540
541
GI(1,1) = s * (G(2,2)*G(3,3) - G(3,2)*G(2,3));
542
GI(2,1) = -s * (G(2,1)*G(3,3) - G(3,1)*G(2,3));
543
GI(3,1) = s * (G(2,1)*G(3,2) - G(3,1)*G(2,2));
544
545
GI(1,2) = -s * (G(1,2)*G(3,3) - G(3,2)*G(1,3));
546
GI(2,2) = s * (G(1,1)*G(3,3) - G(3,1)*G(1,3));
547
GI(3,2) = -s * (G(1,1)*G(3,2) - G(3,1)*G(1,2));
548
549
GI(1,3) = s * (G(1,2)*G(2,3) - G(2,2)*G(1,3));
550
GI(2,3) = -s * (G(1,1)*G(2,3) - G(2,1)*G(1,3));
551
GI(3,3) = s * (G(1,1)*G(2,2) - G(2,1)*G(1,2));
552
!------------------------------------------------------------------------------
553
END SUBROUTINE InvertMatrix3x3
554
!------------------------------------------------------------------------------
555
556
#ifdef HAVE_QP
557
!------------------------------------------------------------------------------
558
! Quadratic precision version of the previous routine!
559
!------------------------------------------------------------------------------
560
SUBROUTINE InvertMatrix3x3QP( G,GI,detG )
561
!------------------------------------------------------------------------------
562
INTEGER, PARAMETER :: qp = SELECTED_REAL_KIND(24)
563
REAL(KIND=qp) :: G(3,3),GI(3,3)
564
REAL(KIND=qp) :: detG, s
565
!------------------------------------------------------------------------------
566
s = 1.0 / DetG
567
568
GI(1,1) = s * (G(2,2)*G(3,3) - G(3,2)*G(2,3));
569
GI(2,1) = -s * (G(2,1)*G(3,3) - G(3,1)*G(2,3));
570
GI(3,1) = s * (G(2,1)*G(3,2) - G(3,1)*G(2,2));
571
572
GI(1,2) = -s * (G(1,2)*G(3,3) - G(3,2)*G(1,3));
573
GI(2,2) = s * (G(1,1)*G(3,3) - G(3,1)*G(1,3));
574
GI(3,2) = -s * (G(1,1)*G(3,2) - G(3,1)*G(1,2));
575
576
GI(1,3) = s * (G(1,2)*G(2,3) - G(2,2)*G(1,3));
577
GI(2,3) = -s * (G(1,1)*G(2,3) - G(2,1)*G(1,3));
578
GI(3,3) = s * (G(1,1)*G(2,2) - G(2,1)*G(1,2));
579
!------------------------------------------------------------------------------
580
END SUBROUTINE InvertMatrix3x3QP
581
!------------------------------------------------------------------------------
582
#endif
583
584
!------------------------------------------------------------------------------
585
!> Compute the value of 3x3 determinant
586
!------------------------------------------------------------------------------
587
FUNCTION Det3x3( A ) RESULT ( val )
588
!------------------------------------------------------------------------------
589
REAL(KIND=dp) :: A(3,3)
590
REAL(KIND=dp) :: val
591
592
val = A(1,1) * ( A(2,2) * A(3,3) - A(2,3) * A(3,2) ) &
593
- A(1,2) * ( A(2,1) * A(3,3) - A(2,3) * A(3,1) ) &
594
+ A(1,3) * ( A(2,1) * A(3,2) - A(2,2) * A(3,1) )
595
!------------------------------------------------------------------------------
596
END FUNCTION Det3x3
597
!------------------------------------------------------------------------------
598
599
! --------------------------------------------------
600
!> Solve eigenvalues of a nonsymmetric matrix A(n,n)
601
!> The matrix is modified in the process.
602
! --------------------------------------------------
603
SUBROUTINE EigenValues( A, n, Vals )
604
IMPLICIT NONE
605
REAL(KIND=dp) :: A(:,:)
606
INTEGER :: n
607
COMPLEX(KIND=dp) :: Vals(:)
608
609
INTEGER :: iter, i, j, k
610
REAL(KIND=dp) :: b, s, t
611
612
IF (n==1 ) THEN
613
Vals(1) = A(1,1)
614
RETURN
615
END IF
616
617
CALL Hesse(A, n)
618
619
DO iter=1,1000
620
DO i=1,n-1
621
s = AEPS * ( ABS(A(i,i))+ABS(A(i+1,i+1)) )
622
IF ( ABS(A(i+1,i)) < s ) A(i+1,i) = 0.0
623
END DO
624
625
i = 1
626
DO WHILE( .TRUE. )
627
DO j=i,n-1
628
IF (A(j+1,j) /= 0 ) EXIT
629
END DO
630
631
DO k=j,n-1
632
IF (A(k+1,k) == 0 ) EXIT
633
END DO
634
i = k;
635
IF ( i >= n .OR. k-j+1 >= 3 ) EXIT
636
END DO
637
638
IF (k-j+1 < 3) EXIT
639
CALL Francis(A(j:,j:), k-j+1);
640
END DO
641
642
j = 0
643
i = 1
644
DO WHILE( i<n )
645
IF (A(i+1,i) == 0) THEN
646
j = j + 1
647
Vals(j) = A(i,i)
648
ELSE
649
b = ( A(i,i)+A(i+1,i+1) ); s=b*b
650
t = A(i,i)*A(i+1,i+1) - A(i,i+1)*A(i+1,i)
651
s = s - 4*t
652
IF (s >= 0) THEN
653
s = SQRT(s)
654
j = j + 1
655
IF ( b>0 ) THEN
656
Vals(j) = (b+s)/2
657
ELSE
658
Vals(j) = 2*t/(b-s)
659
END IF
660
j = j + 1
661
IF ( b > 0 ) THEN
662
Vals(j) = 2*t/(b+s)
663
ELSE
664
Vals(j) = (b-s)/2
665
END IF
666
ELSE
667
j = j + 1
668
Vals(j) = CMPLX(b, SQRT(-s),KIND=dp)/2
669
j = j + 1
670
Vals(j) = CMPLX(b,-SQRT(-s),KIND=dp)/2
671
END IF
672
i = i + 1
673
END IF
674
i = i + 1
675
END DO
676
677
IF (A(n, n-1) == 0) THEN
678
j = j + 1
679
Vals(j) = A(n,n)
680
END IF
681
682
CONTAINS
683
684
SUBROUTINE vbcalc( x,v,b,beg,end )
685
IMPLICIT NONE
686
REAL(KIND=dp) :: x(:),v(:),b
687
INTEGER :: beg, end
688
689
REAL(KIND=dp) :: alpha,m
690
INTEGER :: i
691
692
m = MAXVAL( ABS(x(beg:end)) )
693
694
IF ( m == 0 ) THEN
695
v(beg:end) = 0
696
ELSE
697
alpha = 0
698
m = 1 / m
699
DO i=beg,end
700
v(i) = m*x(i)
701
alpha = alpha+v(i)*v(i)
702
END DO
703
alpha = SQRT(alpha)
704
b = 1/(alpha*(alpha+ABS(v(beg))))
705
IF ( v(beg) < 0 ) THEN
706
v(beg) = v(beg) - alpha
707
ELSE
708
v(beg) = v(beg) + alpha
709
END IF
710
END IF
711
END SUBROUTINE vbcalc
712
713
714
SUBROUTINE Hesse(H, dim)
715
IMPLICIT NONE
716
INTEGER :: dim
717
REAL(KIND=dp) :: H(:,:)
718
719
REAL(KIND=dp) :: b, s
720
INTEGER :: i, j, k;
721
REAL(KIND=dp), ALLOCATABLE :: v(:), x(:)
722
723
ALLOCATE( x(dim), v(dim) )
724
725
DO i=1,dim-1
726
DO j=i+1,dim
727
x(j) = H(j,i)
728
END DO
729
730
CALL vbcalc(x, v, b, i+1, dim )
731
732
IF (v(i+1) == 0) EXIT
733
734
DO j=i+2, dim
735
x(j) = v(j)/v(i+1)
736
v(j) = b*v(i+1)*v(j)
737
END DO
738
v(i+1) = b*v(i+1)*v(i+1)
739
740
DO j=1,dim
741
s = 0.0
742
DO k=i+1,dim
743
s = s + H(j,k)*v(k)
744
END DO
745
H(j,i+1) = H(j,i+1) - s
746
DO k=i+2,dim
747
H(j,k) = H(j,k) - s*x(k)
748
END DO
749
END DO
750
751
DO j=1,dim
752
s = H(i+1,j)
753
DO k=i+2,dim
754
s = s + H(k,j)*x(k)
755
END DO
756
DO k=i+1,dim
757
H(k,j) = H(k,j) - s*v(k)
758
END DO
759
END DO
760
H(i+2:dim,i) = 0
761
END DO
762
763
DEALLOCATE( x, v )
764
END SUBROUTINE Hesse
765
766
767
SUBROUTINE Francis( H, dim )
768
IMPLICIT NONE
769
INTEGER :: dim
770
REAL(KIND=dp) :: H(:,:)
771
772
INTEGER :: i, i1, j, k, m, n, end
773
REAL(KIND=dp) :: x(3), v(3), b, s, t, v0i
774
775
n = dim; m = n-1
776
777
t = H(m,m)*H(n,n) - H(m,n)*H(n,m)
778
s = H(m,m)+H(n,n)
779
780
x(1) = H(1,1)*H(1,1)+H(1,2)*H(2,1)-s*H(1,1)+t
781
x(2) = H(2,1)*(H(1,1)+H(2,2)-s)
782
x(3) = H(2,1)*H(3,2);
783
784
CALL vbcalc(x, v, b, 1, 3)
785
786
IF (v(1) == 0) RETURN
787
788
! DO i=2,3
789
! x(i) = v(i)/v(1);
790
! v(i) = b * v(1) * v(i);
791
! END DO
792
x(2) = v(2)/v(1)
793
v(2) = b*v(1)*v(2)
794
x(3) = v(3)/v(1)
795
v(3) = b*v(1)*v(3)
796
x(1) = 1; v(1) = b*v(1)*v(1)
797
798
DO i=1,dim
799
! DO j=1,3
800
! s = s + H(i,j) * v(j)
801
! END DO
802
s = H(i,1)*v(1) + H(i,2)*v(2) + H(i,3)*v(3)
803
804
! DO j=1,3
805
! H(i,j) = H(i,j) - s * x(j)
806
! END DO
807
H(i,1) = H(i,1) - s
808
H(i,2) = H(i,2) - s*x(2)
809
H(i,3) = H(i,3) - s*x(3)
810
END DO
811
812
DO i=1,dim
813
! s = 0.0d0
814
! DO j=1,3
815
! s = s + H(j,i) * x(j)
816
! END DO
817
s = h(1,i) + H(2,i)*x(2) + H(3,i)*x(3)
818
819
! DO j=1,3
820
! H(j,i) = H(j,i) - s * v(j)
821
! END DO
822
H(1,i) = H(1,i) - s*v(1)
823
H(2,i) = H(2,i) - s*v(2)
824
H(3,i) = H(3,i) - s*v(3)
825
END DO
826
827
DO i=1,dim-1
828
end = MIN(2, dim-i-1)
829
DO j=1,end+1
830
x(j) = H(i+j,i)
831
END DO
832
833
CALL vbcalc(x, v, b, 1, end+1)
834
835
IF (v(1) == 0) EXIT
836
837
DO j=2,end+1
838
x(j) = v(j)/v(1);
839
v(j) = b*v(1)*v(j)
840
END DO
841
x(1) = 1; v(1) = b*v(1)*v(1)
842
843
DO j=1,dim
844
s = 0.0
845
DO k=1,end+1
846
s = s + H(j,i+k)*v(k)
847
END DO
848
DO k=1,end+1
849
H(j,i+k) = H(j,i+k) - s*x(k)
850
END DO
851
END DO
852
853
DO j=1,dim
854
s = H(i+1,j)
855
DO k=2,end+1
856
s = s + H(i+k,j)*x(k)
857
END DO
858
DO k=1,end+1
859
H(i+k,j) = H(i+k,j) - s*v(k)
860
END DO
861
END DO
862
H(i+2:dim,i) = 0
863
END DO
864
END SUBROUTINE Francis
865
END SUBROUTINE EigenValues
866
867
END MODULE LinearAlgebra
868
869
!> \} ElmerLib
870
871