MoDeNa  1.0
Software framework facilitating sequential multi-scale modelling
matrix_inversion2.f90
1 !WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
2 ! SOLVING A LINEAR MATRIX SYSTEM AX = B with Gauss-Jordan method using full
3 ! pivoting at each step. During the process, original A and B matrices are
4 ! destroyed to spare storage location.
5 
6 ! INPUTS: A MATRIX N*N
7 ! B MATRIX N*M
8 
9 ! OUTPUS: A INVERSE OF A N*N
10 ! DET DETERMINANT OF A
11 ! B SOLUTION MATRIX N*M
12 
13 ! NOTA - If M=0 inversion of A matrix only.
14 !WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
15 
16 subroutine matinv ( N, M, AA, BB, DET )
17 
18  implicit none
19  !-----------------------------------------------------------------------------
20  integer, intent(in) :: n
21  integer, intent(in) :: m
22  real, dimension(N,N), intent(in out) :: aa
23  real, dimension(N,M), intent(in out) :: bb
24  real, intent(out) :: det
25 
26  !-----------------------------------------------------------------------------
27  integer :: i, j, k, ik, jk
28  real, PARAMETER :: epsmach = 2.e-16
29  real :: pv, pav, tt
30  integer, allocatable :: pc(:), pl(:)
31  real, allocatable :: cs(:)
32  !-----------------------------------------------------------------------------
33 
34 
35  !-----------------------------------------------------------------------------
36  ! Initializations
37  !-----------------------------------------------------------------------------
38  allocate( pc(1:n) )
39  allocate( pl(1:n) )
40  allocate( cs(1:n) )
41  det = 1.0
42  do i = 1, n
43  pc(i) = 0
44  pl(i) = 0
45  cs(i) = 0.0
46  end do
47 
48  !-----------------------------------------------------------------------------
49  ! main loop
50  !-----------------------------------------------------------------------------
51  do k = 1, n
52  !Searching greatest pivot
53  pv = aa(k,k)
54  ik = k
55  jk = k
56  pav = abs(pv)
57  do i = k, n
58  do j = k, n
59  if ( abs(aa(i,j)) > pav ) then
60  pv = aa(i,j)
61  pav = abs(pv)
62  ik = i
63  jk = j
64  end if
65  end do
66  end do
67 
68  !--------------------------------------------------------------------------
69  ! Search terminated, the pivot is in location I=IK, J=JK.
70  ! Memorizing pivot location:
71  !--------------------------------------------------------------------------
72  pc(k) = jk
73  pl(k) = ik
74 
75  !--------------------------------------------------------------------------
76  ! Determinant DET is actualised
77  ! If DET=0, ERROR MESSAGE and STOP
78  ! Machine dependant EPSMACH equals here 1.DE-20
79  !--------------------------------------------------------------------------
80 
81  if ( ik /= k ) det = -det
82  if ( jk /= k ) det = -det
83  det = det * pv
84  if ( abs(det) < epsmach ) then
85  !Error message and Stop
86  write (*,*) ' DETERMINANT EQUALS ZERO, NO SOLUTION!'
87  stop
88  end if
89 
90  !--------------------------------------------------------------------------
91  ! POSITIONNING PIVOT IN K,K
92  !--------------------------------------------------------------------------
93  if ( ik /= k ) then
94  do i=1,n
95  !EXCHANGE LINES IK and K
96  tt=aa(ik,i)
97  aa(ik,i)=aa(k,i)
98  aa(k,i)=tt
99  end do
100  end if
101  if (m /= 0) then
102  do i = 1, m
103  tt=bb(ik,i)
104  bb(ik,i)=bb(k,i)
105  bb(k,i)=tt
106  end do
107  end if
108 
109  !--------------------------------------------------------------------------
110  ! Pivot is at correct line
111  !--------------------------------------------------------------------------
112  if (jk /= k) then
113  do i = 1, n
114  !Exchange columns JK and K of matrix AA
115  tt = aa(i,jk)
116  aa(i,jk) = aa(i,k)
117  aa(i,k) = tt
118  end do
119  end if
120 
121  !--------------------------------------------------------------------------
122  ! Pivot is at correct column and located in K,K
123  !--------------------------------------------------------------------------
124  ! Store column K in vector CS
125  ! then set column K to zero
126  !--------------------------------------------------------------------------
127  do i = 1, n
128  cs(i) = aa(i,k)
129  aa(i,k) = 0.0
130  end do
131 
132  cs(k) = 0.0
133  aa(k,k) = 1.0
134  !--------------------------------------------------------------------------
135  ! Modify line K
136  !--------------------------------------------------------------------------
137  if (abs(pv) < epsmach) then
138  WRITE(*,*) ' PIVOT TOO SMALL - STOP'
139  stop
140  end if
141  do i = 1, n
142  aa(k,i) = aa(k,i) / pv
143  end do
144  if (m /= 0) then
145  do i = 1, m
146  bb(k,i) = bb(k,i) / pv
147  end do
148  end if
149  !--------------------------------------------------------------------------
150  ! Modify other lines of matrix AA
151  !--------------------------------------------------------------------------
152  do j = 1, n
153  if ( j == k ) CONTINUE
154  do i = 1, n
155  !Modify line J of matrix AA
156  aa(j,i) = aa(j,i) - cs(j) * aa(k,i)
157  end do
158  if ( m /= 0 ) then
159  do i = 1, m
160  bb(j,i) = bb(j,i) - cs(j) * bb(k,i)
161  end do
162  end if
163  end do
164  !Line K is ready
165  end do
166  !End of K loop
167 
168  !-----------------------------------------------------------------------------
169  ! The matrix AA is inverted - Rearrange AA
170  !-----------------------------------------------------------------------------
171 
172  !-----------------------------------------------------------------------------
173  !Exchange lines
174  !-----------------------------------------------------------------------------
175  do i = n, 1, -1
176  ik = pc(i)
177  if ( ik == i ) CONTINUE
178  !EXCHANGE LINES I AND PC(I) OF AA
179  do j = 1, n
180  tt = aa(i,j)
181  aa(i,j) = aa(ik,j)
182  aa(ik,j) = tt
183  end do
184  if ( m /= 0 ) then
185  do j = 1, m
186  tt = bb(i,j)
187  bb(i,j) = bb(ik,j)
188  bb(ik,j) = tt
189  end do
190  end if
191  !NO MORE EXCHANGE NEEDED
192  !GO TO NEXT LINE
193  end do
194 
195 
196  !-----------------------------------------------------------------------------
197  ! EXCHANGE COLUMNS
198  !-----------------------------------------------------------------------------
199  do j = n, 1, -1
200  jk = pl(j)
201  if ( jk == j ) CONTINUE
202  !EXCHANGE COLUMNS J AND PL(J) OF AA
203  do i = 1, n
204  tt = aa(i,j)
205  aa(i,j) = aa(i,jk)
206  aa(i,jk) = tt
207  end do
208  !NO MORE EXCHANGE NEEDED
209  !GO TO NEXT COLUMN
210  end do
211 
212  deallocate( pc, pl, cs )
213 
214 end subroutine matinv
215 
216 !WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
217 ! subroutine jacobi_eigenvalue
218 !
219 ! This function computes the eigenvalues and eigenvectors of a real symmetric
220 ! matrix, using Rutishauser's modfications of the classical Jacobi rotation
221 ! method with threshold pivoting.
222 !
223 ! input:
224 ! n order of the matrix
225 ! a(n,n) matrix, which must be square, real, and symmetric
226 ! it_max maximum number of iterations
227 !
228 ! output:
229 ! v(n,n) matrix of eigenvectors
230 ! d(n) eigenvalues, in descending order
231 ! it_num total number of iterations
232 ! rot_num total number of rotations
233 !WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
234 
235 subroutine jacobi_eigenvalue ( n, a, it_max, v, d, it_num, rot_num )
236 
237  implicit none
238  !-----------------------------------------------------------------------------
239  integer, intent(in) :: n
240  real, dimension(n,n), intent(in out) :: a
241  integer, intent(in) :: it_max
242  real, dimension(n,n), intent(out) :: v
243  real, dimension(n), intent(out) :: d
244  integer, intent(out) :: it_num
245  integer, intent(out) :: rot_num
246  !-----------------------------------------------------------------------------
247 
248  integer :: i, j, k, l, m, p, q
249  real :: c
250  real :: g
251  real :: gapq
252  real :: h
253  real :: s
254  real :: t
255  real :: tau
256  real :: term
257  real :: termp
258  real :: termq
259  real :: theta
260  real :: thresh
261  real, dimension(n) :: bw
262  real, dimension(n) :: w, zw
263  !-----------------------------------------------------------------------------
264 
265  do j = 1, n
266  do i = 1, n
267  v(i,j) = 0.0
268  end do
269  v(j,j) = 1.0
270  end do
271 
272  do i = 1, n
273  d(i) = a(i,i)
274  end do
275 
276  bw(1:n) = d(1:n)
277  zw(1:n) = 0.0
278  it_num = 0
279  rot_num = 0
280 
281  do while ( it_num < it_max )
282 
283  it_num = it_num + 1
284  !--------------------------------------------------------------------------
285  ! The convergence threshold is based on the size of the elements in
286  ! the strict upper triangle of the matrix.
287  !--------------------------------------------------------------------------
288  thresh = 0.0
289  do j = 1, n
290  do i = 1, j - 1
291  thresh = thresh + a(i,j) ** 2
292  end do
293  end do
294 
295  thresh = sqrt( thresh ) / real( 4 * n, kind = 8 )
296 
297  if ( thresh == 0.0 ) then
298  exit
299  end if
300 
301  do p = 1, n
302  do q = p + 1, n
303 
304  gapq = 10.0 * abs( a(p,q) )
305  termp = gapq + abs( d(p) )
306  termq = gapq + abs( d(q) )
307  !--------------------------------------------------------------------
308  ! Annihilate tiny offdiagonal elements.
309  !--------------------------------------------------------------------
310  if ( 4 < it_num .and. termp == abs( d(p) ) .and. termq == abs( d(q) ) ) then
311 
312  a(p,q) = 0.0
313  !-----------------------------------------------------------------
314  ! Otherwise, apply a rotation.
315  !-----------------------------------------------------------------
316  else if ( thresh <= abs( a(p,q) ) ) then
317 
318  h = d(q) - d(p)
319  term = abs( h ) + gapq
320 
321  if ( term == abs( h ) ) then
322  t = a(p,q) / h
323  else
324  theta = 0.5 * h / a(p,q)
325  t = 1.0 / ( abs( theta ) + sqrt( 1.0 + theta * theta ) )
326  if ( theta < 0.0 ) then
327  t = - t
328  end if
329  end if
330 
331  c = 1.0 / sqrt( 1.0 + t * t )
332  s = t * c
333  tau = s / ( 1.0 + c )
334  h = t * a(p,q)
335  !-----------------------------------------------------------------
336  ! Accumulate corrections to diagonal elements.
337  !-----------------------------------------------------------------
338  zw(p) = zw(p) - h
339  zw(q) = zw(q) + h
340  d(p) = d(p) - h
341  d(q) = d(q) + h
342 
343  a(p,q) = 0.0
344  !-----------------------------------------------------------------
345  ! Rotate, using information from the upper triangle of A only.
346  !-----------------------------------------------------------------
347  do j = 1, p - 1
348  g = a(j,p)
349  h = a(j,q)
350  a(j,p) = g - s * ( h + g * tau )
351  a(j,q) = h + s * ( g - h * tau )
352  end do
353 
354  do j = p + 1, q - 1
355  g = a(p,j)
356  h = a(j,q)
357  a(p,j) = g - s * ( h + g * tau )
358  a(j,q) = h + s * ( g - h * tau )
359  end do
360 
361  do j = q + 1, n
362  g = a(p,j)
363  h = a(q,j)
364  a(p,j) = g - s * ( h + g * tau )
365  a(q,j) = h + s * ( g - h * tau )
366  end do
367  !-----------------------------------------------------------------
368  ! Accumulate information in the eigenvector matrix.
369  !-----------------------------------------------------------------
370  do j = 1, n
371  g = v(j,p)
372  h = v(j,q)
373  v(j,p) = g - s * ( h + g * tau )
374  v(j,q) = h + s * ( g - h * tau )
375  end do
376 
377  rot_num = rot_num + 1
378 
379  end if
380 
381  end do
382  end do
383 
384  bw(1:n) = bw(1:n) + zw(1:n)
385  d(1:n) = bw(1:n)
386  zw(1:n) = 0.0
387 
388  end do
389  !-----------------------------------------------------------------------------
390  ! Restore upper triangle of input matrix.
391  !-----------------------------------------------------------------------------
392  do j = 1, n
393  do i = 1, j - 1
394  a(i,j) = a(j,i)
395  end do
396  end do
397  !-----------------------------------------------------------------------------
398  ! Ascending sort the eigenvalues and eigenvectors.
399  !-----------------------------------------------------------------------------
400  do k = 1, n - 1
401 
402  m = k
403 
404  do l = k + 1, n
405  if ( d(l) < d(m) ) then
406  m = l
407  end if
408  end do
409 
410  if ( m /= k ) then
411 
412  t = d(m)
413  d(m) = d(k)
414  d(k) = t
415 
416  w(1:n) = v(1:n,m)
417  v(1:n,m) = v(1:n,k)
418  v(1:n,k) = w(1:n)
419 
420  end if
421 
422  end do
423 
424 end subroutine jacobi_eigenvalue
425 
426 
427 !WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
428 ! subroutine eigenvalues ( n, a, x )
429 !
430 ! evaluates eigenvalues and eigenvectors of a real symmetric matrix
431 ! a(n,n): a*x = lambda*x
432 ! method: Jacoby method for symmetric matrices, Alex G. (December 2009)
433 !
434 ! input:
435 ! a(n,n) - array of coefficients for matrix A
436 ! n - number of equations
437 ! abserr - abs tolerance [sum of (off-diagonal elements)^2]
438 ! output:
439 ! a(i,i) - eigenvalues
440 ! x(i,j) - eigenvectors
441 !WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
442 
443 !!$subroutine eigenvalues ( n, a, x )
444 !!$
445 !!$ implicit none
446 !!$ !-----------------------------------------------------------------------------
447 !!$ integer, intent(in) :: n
448 !!$ real, dimension(n,n), intent(in out) :: a
449 !!$ real, dimension(n,n), intent(out) :: x
450 !!$ !-----------------------------------------------------------------------------
451 !!$ integer :: i, j, k
452 !!$ real :: b2, bar
453 !!$ real :: beta, coeff, c, s, cs, sc
454 !!$ real, parameter :: abserr = 1.E-08
455 !!$ !-----------------------------------------------------------------------------
456 !!$ write (*,*) 'enter eigenvalues'
457 !!$ !-----------------------------------------------------------------------------
458 !!$ ! initialize x(i,j)=0, x(i,i)=1
459 !!$ !-----------------------------------------------------------------------------
460 !!$ x = 0.0
461 !!$ do i = 1, n
462 !!$ x(i,i) = 1.0
463 !!$ end do
464 !!$
465 !!$ !-----------------------------------------------------------------------------
466 !!$ ! find the sum of all off-diagonal elements (squared)
467 !!$ !-----------------------------------------------------------------------------
468 !!$ b2 = 0.0
469 !!$ do i = 1, n
470 !!$ do j = 1, n
471 !!$ if ( i /= j ) b2 = b2 + a(i,j)**2
472 !!$ end do
473 !!$ end do
474 !!$
475 !!$ if ( b2 <= abserr ) return
476 !!$
477 !!$ !-----------------------------------------------------------------------------
478 !!$ ! average for off-diagonal elements /2
479 !!$ !-----------------------------------------------------------------------------
480 !!$ bar = 0.5 * b2 / float(n*n)
481 !!$
482 !!$ do while ( b2 > abserr )
483 !!$ do i = 1, n-1
484 !!$ do j = i+1, n
485 !!$ if ( a(j,i)**2 <= bar ) cycle ! do not touch small elements
486 !!$ b2 = b2 - 2.0*a(j,i)**2
487 !!$ bar = 0.5 * b2 / float(n*n)
488 !!$ !--------------------------------------------------------------------
489 !!$ ! calculate coefficient c and s for Givens matrix
490 !!$ !--------------------------------------------------------------------
491 !!$ beta = ( a(j,j) - a(i,i) ) / ( 2.0 * a(j,i) )
492 !!$ coeff = 0.5 * beta / sqrt( 1.0+beta**2 )
493 !!$ s = sqrt(max(0.5+coeff,0.0))
494 !!$ c = sqrt(max(0.5-coeff,0.0))
495 !!$ !--------------------------------------------------------------------
496 !!$ ! recalculate rows i and j
497 !!$ !--------------------------------------------------------------------
498 !!$ do k = 1, n
499 !!$ cs = c * a(i,k) + s * a(j,k)
500 !!$ sc = -s * a(i,k) + c * a(j,k)
501 !!$ a(i,k) = cs
502 !!$ a(j,k) = sc
503 !!$ end do
504 !!$ !--------------------------------------------------------------------
505 !!$ ! new matrix a_{k+1} from a_{k}, and eigenvectors
506 !!$ !--------------------------------------------------------------------
507 !!$ do k = 1, n
508 !!$ cs = c * a(k,i) + s * a(k,j)
509 !!$ sc = -s * a(k,i) + c * a(k,j)
510 !!$ a(k,i) = cs
511 !!$ a(k,j) = sc
512 !!$ cs = c * x(k,i) + s * x(k,j)
513 !!$ sc = -s * x(k,i) + c * x(k,j)
514 !!$ x(k,i) = cs
515 !!$ x(k,j) = sc
516 !!$ end do
517 !!$ end do
518 !!$ end do
519 !!$ end do
520 !!$ write (*,*) 'exit eigenvalues'
521 !!$end subroutine eigenvalues
522 
523 
524