Я построил подпрограмму в Фортране, и она работает нормально и правильно, но на это уходит больше времени, чем нужно.
Есть идеи, как мне улучшить эту подпрограмму? Может быть, изменение способа объявления параметров или удаление некоторых ненужных do
.
ZGESV
и ZGEEV
являются подпрограммами от Лапака для решения линейных сложных систем (например: A * x = B).
Subroutine arnoldi(m,n,A,B,sigma,eig,INFO)
implicit none
integer, intent(in) :: n, m
integer, intent(out) :: INFO
complex(8), intent(in) :: sigma
complex(8), dimension(m), intent(out) :: eig
complex(8), dimension(n,n), intent(in) :: A,B
! Argumentos
integer :: i, j, LDVL, LDVR, one
integer :: LWORK
integer, dimension(n) :: IPIV
complex(8), dimension(n) :: r, q
complex(8), dimension(n,n) :: C
complex(8), dimension (m,m) :: VL,VR
complex(8), dimension(6*(m+1)) :: WORK
complex(8), dimension(m+1,m) :: h
complex(8), dimension(n,m+1) :: v
complex(8), dimension(m,m) :: hh
real(8), dimension(8*(m+1)) :: RWORK
character :: JOBVL, JOBVR
! Lapack
JOBVL = 'N'
JOBVR = 'N'
LWORK = 6*(m+1)
LDVL = 2*(m+1)
LDVR = 2*(m+1)
one = 1
! Arnoldi
q = dcmplx(1.0d0,0.0d0)
q = q/norm2(zabs(q))
v(:,1) = q
C = A - sigma*B
do i = 1,m
r = Matmul(B,v(:,i))
CALL ZGESV(n,one,C,n,IPIV,r,n,INFO)
do j = 1,i
h(j,i) = dot_product(v(:,j),r)
r = r - v(:,j)*h(j,i)
end do
if (i.lt.n) then
h(i+1,i) = norm2(zabs(r))
if (zabs(h(i+1,i)).lt.1.0d-7) exit
v(:,i+1) = r/h(i+1,i)
end if
end do
do i = 1,m
do j = 1,m
HH(i,j) = h(i,j)
end do
end do
CALL ZGEEV(JOBVL,JOBVR,m,HH,m,eig,VL,LDVL,VR,LDVR,WORK,LWORK,RWORK,INFO)
! Autovalores
do i=1,m
eig(i) = dcmplx(1.0d0,0.0d0)/eig(i) + sigma
end do
end subroutine