我想使用 lapack 找出所有特征值和相关的右特征向量。但是,代码只能在小矩阵大小下工作。虽然我的矩阵的大小超过了 300 之类的特定数字,但它崩溃了,我得到的只是分段错误(核心转储)。我检查了我的代码几次,仍然无法找出问题所在。以下是我的代码。
program Eigenvalue
! finding the eigenvalues of a complex matrix using LAPACK
! http://www.netlib.org/lapack/complex16/zgeev.f
!find out the inverse complex matrix in fortran
Implicit none
!matrix dimension
integer, parameter::N=300
integer,parameter::M=3*(N-1)
! declarations, notice double precision
! A and B are matrices with given value while inver is inverse matrix of A
! S is to check whether inverse matrix is right or not
real*8,allocatable,dimension(:,:)::A
real*8,allocatable,dimension(:,:)::Inver
real*8,allocatable,dimension(:,:)::B
real*8,allocatable,dimension(:,:)::S
!Mul is the matrix to be calculated in the subroutine and its values are
!product of inverse matrix and B
!eigval represents eigenvalues while Vec are eigenvectors
complex*16,allocatable,dimension(:,:):: Mul,DUMMY,Vec
complex*16,allocatable,dimension(:)::eigval,WORK1
double precision::WORK2(2*M)
integer i,j,ok,temp,error
!specific parameters in this case to define A and B
real*8 ky,k,lb,ln,kz,ni,to
real*8 x,dx
real*8::x0=-30.d0,x1=30.d0
real*8 co1,co2,co3,co4
allocate(A(M,M),B(M,M),Inver(M,M),S(M,M),stat=error)
if (error.ne.0)then
print *,"error:not enough memory"
stop
end if
allocate(Mul(M,M),DUMMY(M,M),Vec(M,M),eigval(M),WORK1(2*M),stat=error)
if (error.ne.0)then
print *,"error:not enough memory"
stop
end if
!values of parameters
ni=5
to=1
ln=10.d0
lb=50.d0
ky=0.4d0
kz=0.002d0
k=(1.d0+ni)/to
dx=(x1-x0)/N
x=x1-dx
co1=(1+ky*ky)*dx*dx-2
co2=ky*(-2*k+(1-k*ky*ky)*dx*dx)
co3=dx*dx*(kz-ky*(x/lb)**2)
co4=ky*k
call mkl_set_num_threads( 2 )
!definition of the initial matrix A
do i=1,M
do j=1,N-1
if(j.eq.i)then
A(i,j)=-2+(1+ky*ky)*dx*dx
else if (j.eq.(i+1)) then
A(i,j)=-1
else if (j.eq.(i-1).and.j.ne.(N-1)) then
A(i,j)=-1
else if(j.eq.(i-1).and.j.eq.(N-1))then
A(i,j)=0
else
A(i,j)=(0,0)
end if
end do
do j=N,M
if(j.eq.i)then
A(i,j)=1
else
A(i,j)=0
end if
end do
end do
call inverse(A,Inver,M)
!definition of matrix B and the multiplication Mul
do i=1,M
do j=1,N-1
if(j.eq.i)then
B(i,j)=ky*((1-k*ky*ky)*dx*dx-2*k)
else if (j.eq.(i+1)) then
B(i,j)=ky*k
else if (j.eq.(i-1).and.j.ne.(N-1)) then
B(i,j)=ky*k
else if (j.eq.(i-1).and.j.eq.(N-1))then
B(i,j)=0
else if(j.eq.(i-N+1)) then
B(i,j)=kz-((x0+j*dx)**2)*ky/(lb*lb)
else if (j.eq.(i-2*N+2)) then
B(i,j)=k*ky
else
B(i,j)=0
end if
end do
do j=N,2*(N-1)
if(j.eq.(i+N-1))then
B(i,j)=(kz-((x0+i*dx)**2)*ky/(lb*lb))*dx*dx
else
B(i,j)=0
end if
end do
do j=2*N-1,M
if(j.eq.(i+N-1)) then
B(i,j)=kz-((x0+(i-N+1)*dx)**2)*ky/(lb*lb)
else
B(i,j)=0
end if
end do
end do
Mul=matmul(Inver,B)
call ZGEEV('N', 'V', M,Mul, M, eigval, DUMMY, M, Vec, M, WORK1, 2*M, WORK2, ok)
deallocate(A,B,Inver,S,stat=error)
if (error.ne.0)then
print *,"error:fail to release"
stop
end if
deallocate(Mul,DUMMY,Vec,eigval,WORK1,stat=error)
if (error.ne.0)then
print *,"error:failed to release"
stop
end if
end
subroutine inverse(a,c,n)
!============================================================
! Inverse matrix
! Method: Based on Doolittle LU factorization for Ax=b
! Alex G. December 2009
!this is for real numbers
!-----------------------------------------------------------
! input ...
! a(n,n) - array of coefficients for matrix A
! n - dimension
! output ...
! c(n,n) - inverse matrix of A
! comments ...
! the original matrix a(n,n) will be destroyed
! during the calculation
!===========================================================
implicit none
integer n
double precision a(n,n), c(n,n)
double precision,allocatable,dimension(:,:):: L, U
double precision,allocatable,dimension(:):: b, d, x
double precision coeff
integer i, j, k,error
allocate(L(n,n),U(n,n),b(n),d(n),x(n),stat=error)
if (error.ne.0)then
print *,"error:not enough memory"
stop
end if
! step 0: initialization for matrices L and U and b
! Fortran 90/95 allows such operations on matrices
L=0.0
U=0.0
b=0.0
! step 1: forward elimination
do k=1, n-1
do i=k+1,n
coeff=a(i,k)/a(k,k)
L(i,k) = coeff
do j=k+1,n
a(i,j) = a(i,j)-coeff*a(k,j)
end do
end do
end do
! Step 2: prepare L and U matrices
! L matrix is a matrix of the elimination coefficient
! + the diagonal elements are 1.0
do i=1,n
L(i,i) = 1.0
end do
! U matrix is the upper triangular part of A
do j=1,n
do i=1,j
U(i,j) = a(i,j)
end do
end do
! Step 3: compute columns of the inverse matrix C
do k=1,n
b(k)=1.0
d(1) = b(1)
! Step 3a: Solve Ld=b using the forward substitution
do i=2,n
d(i)=b(i)
do j=1,i-1
d(i) = d(i) - L(i,j)*d(j)
end do
end do
! Step 3b: Solve Ux=d using the back substitution
x(n)=d(n)/U(n,n)
do i = n-1,1,-1
x(i) = d(i)
do j=n,i+1,-1
x(i)=x(i)-U(i,j)*x(j)
end do
x(i) = x(i)/u(i,i)
end do
! Step 3c: fill the solutions x(n) into column k of C
do i=1,n
c(i,k) = x(i)
end do
b(k)=0.0
end do
deallocate(L,U,b,d,x,stat=error)
if (error.ne.0)then
print *,"error:failed to deallocate"
stop
end if
end subroutine inverse
希望有人能给我一个提示或建议,说明为什么当 N 超过 300 时会发生分段错误。