98
94
end subroutine mat_invert
100
97
recursive subroutine mat_invert_recursive(M, zwork, no, ierr)
101
98
use intrinsic_missing, only : EYE
102
99
integer, intent(in) :: no ! Size of problem
103
100
complex(dp), target :: M(no*no), zwork(no*no)
104
101
integer, intent(out), optional :: ierr
103
! The maximum dimensionality of the problem before we turn to a direct inversion algorithm
104
integer, parameter :: N_MAX = 64
106
106
complex(dp), pointer :: A1(:), C2(:), B1(:), A2(:)
107
107
complex(dp), pointer :: t1(:), t2(:)
108
108
integer :: sA1, eA1, sC2, eC2
337
337
end subroutine mat_invert_recursive
340
recursive subroutine mat_invert_recursive(M, zwork, no, ierr)
341
use intrinsic_missing, only : EYE
342
integer, intent(in) :: no ! Size of problem
343
complex(dp), target :: M(no*no), zwork(no*no)
344
integer, intent(out), optional :: ierr
346
! The maximum dimensionality of the problem before we turn to a direct inversion algorithm
347
integer, parameter :: N_MAX = 64
348
integer, parameter :: sA1 = 1
350
complex(dp), pointer :: A1(:), C2(:), B1(:), A2(:)
351
integer :: sC2, sB1, sA2
352
integer :: n1, n2, i, j
354
! M is the matrix we wish to invert using the tri-diagonal
356
! This will enable us to half no in order to "faster"
359
if ( no <= N_MAX ) then
360
call mat_invert(M,zwork,no, method = MI_IN_PLACE_LAPACK , ierr=ierr)
364
if ( present(ierr) ) ierr = 0
366
! Calculate the partition sizes of the matrix problem
370
if ( Npiv < max(n1,n2) ) then
371
call die('Error in initialization of the pivoting &
375
! Point to the partitions
384
! Copy over everything to preserve values for inversion
385
!$OMP parallel do default(shared), private(i)
389
!$OMP end parallel do
392
call zgesv(n1,n2,A1(1),no,ipiv,C2(1),no,i)
394
if ( present(ierr) ) then
398
call die('Error on inverting Y2/B1')
403
call zgesv(n2,n1,A2(1),no,ipiv,B1(1),no,i)
405
if ( present(ierr) ) then
409
call die('Error on inverting X1/C2')
413
! Calculate the diagonal inverted matrix
421
zm1,M(sC2),no,B1(1),no,z1,M(sA1),no)
430
zm1,M(sB1),no,C2(1),no,z1,M(sA2),no)
432
call zgetrf(n1, n1, M(sA1), no, ipiv, i )
434
if ( present(ierr) ) then
438
call die('Error on LU-decomposition A1')
442
call zgetrf(n2, n2, M(sA2), no, ipiv, i )
444
if ( present(ierr) ) then
448
call die('Error on LU-decomposition A2')
452
! Now before we use A1 as work array we will copy
454
! because they are used to calculate the off-diagonal
455
! Note it has to be done in this order
456
! A1, B1, C2, A2 is the order of matrices in the array
457
call copy(n1,n2,zwork(1),zwork(sB1),no)
458
call copy(n1,n2,zwork(n1*n2+1),zwork(sC2),no)
461
call zgetri(n1, M(1), no, ipiv, zwork(j), no**2-j, i)
463
if ( present(ierr) ) then
467
call die('Error on inverting A1')
471
call zgetri(n2, M(sA2), no, ipiv, zwork(j), no**2-j, i)
473
if ( present(ierr) ) then
477
call die('Error on inverting A2')
481
! Calculate the off-diagonal arrays
482
! Do matrix-multiplication
483
! Calculate: X1/C2 * M11
490
zm1, zwork(1),n2,M(sA1),no,z0, M(sB1),no)
492
! Calculate the off-diagonal arrays
493
! Do matrix-multiplication
494
! Calculate: Y2/B1 * M22
501
zm1, zwork(n1*n2+1),n1,M(sA2),no,z0, M(sC2),no)
505
subroutine copy(n1,n2,A,B,LDB)
506
integer, intent(in) :: n1, n2, LDB
507
complex(dp), intent(inout) :: A(n1,n2)
508
complex(dp), intent(in) :: B(LDB,n2)
520
end subroutine mat_invert_recursive
339
522
end module m_mat_invert