矩阵对角化的错误结果

时间:2016-09-09 20:42:54

标签: fortran

我尝试对齐矩阵:

enter image description here

在我的分析中,我设置$ \ hbar = 1 $。代码是:

    MODULE FUNCTION_CONTAINER
    IMPLICIT NONE
    SAVE

    INTEGER, PARAMETER :: DBL = SELECTED_REAL_KIND(P = 15,R = 200)

    COMPLEX(KIND = DBL), PARAMETER :: IMU = (0.0D0, 1.0D0)

    REAL(KIND = DBL), PARAMETER :: S = 1.0D0

    INTEGER, PARAMETER :: TEMP1 =  NINT((2.0D0 * S) + 1.0D0)

    INTEGER, PARAMETER :: DIMJ = TEMP1

    INTEGER, PARAMETER :: TEMP2 =  TEMP1*TEMP1

    INTEGER, PARAMETER :: DIMMAT = TEMP2

    CONTAINS

    INTEGER FUNCTION KRONDELTAR(K,L)
    IMPLICIT NONE
    REAL(KIND = DBL), INTENT(IN)::K,L
    REAL(KIND = DBL) :: TEMP
    TEMP = DABS(K - L)
    IF (TEMP < 0.000001D0) THEN
    KRONDELTAR = 1
    ELSE
    KRONDELTAR = 0
    END IF
    END FUNCTION KRONDELTAR

    SUBROUTINE MATJplus(MATOUT)
    IMPLICIT NONE
    COMPLEX(KIND = DBL),DIMENSION(DIMJ,DIMJ),INTENT(OUT)::MATOUT
    INTEGER::K,L
    REAL(KIND = DBL)::M,MP
    DO K = 1,DIMJ
    DO L = 1,DIMJ
    MP = (S + 1.0D0) - L
    M = (S + 1.0D0) - K
    MATOUT(K,L) = DSQRT(S * (S + 1.0D0) - M * (M + 1.0D0)) * KRONDELTAR(MP,M   + 1)
   END DO
   END DO
   END SUBROUTINE MATJplus

  SUBROUTINE MATJminus(MATOUT)
  IMPLICIT NONE
  COMPLEX(KIND = DBL),DIMENSION(DIMJ,DIMJ),INTENT(OUT)::MATOUT
  INTEGER::K,L
  REAL(KIND = DBL)::MP,M
  DO K = 1,DIMJ
  DO L = 1,DIMJ
  MP = (S + 1) - L
  M = (S + 1) - K
  MATOUT(K,L) = DSQRT(S* (S + 1.0D0) - M * (M - 1.0D0)) * KRONDELTAR(MP,M - 1)
  END DO
  END DO
  END SUBROUTINE MATJminus

  SUBROUTINE MATJy(MATOUT)
  IMPLICIT NONE
  COMPLEX(KIND = DBL),DIMENSION(DIMJ,DIMJ),INTENT(OUT)::MATOUT
  COMPLEX(KIND = DBL),DIMENSION(DIMJ,DIMJ)::Jp,Jm
  CALL MATJplus(Jp)
  CALL MATJminus(Jm)
  MATOUT = (Jp - Jm)/(2.0D0 * IMU)
  END SUBROUTINE MATJy


  SUBROUTINE DIAGONALIZEJy(EIGENSTATESJy,EIGENVALUESJY)
  IMPLICIT NONE
  COMPLEX(KIND = DBL),DIMENSION(DIMJ,DIMJ),INTENT(OUT)::EIGENSTATESJy
  REAL(KIND = DBL), DIMENSION(DIMJ),INTENT(OUT)::EIGENVALUESJY
  COMPLEX(KIND = DBL),DIMENSION(DIMJ,DIMJ)::JyTEMP,Jy
  COMPLEX(KIND = DBL),DIMENSION(2*DIMJ)::D1
  REAL(KIND = DBL),DIMENSION(3*DIMJ - 2)::D2
  INTEGER::D3
  CALL MATJy(Jy)
  JyTEMP = Jy
  CALL ZHEEV('V','U',DIMJ,JyTEMP,DIMJ,EIGENVALUESJy,D1,2*DIMJ,D2,D3)
  EIGENSTATESJy = JyTEMP
  END SUBROUTINE DIAGONALIZEJy

  END MODULE FUNCTION_CONTAINER


    PROGRAM TEST
    USE FUNCTION_CONTAINER

    IMPLICIT NONE

    COMPLEX(KIND = DBL), DIMENSION(DIMJ,DIMJ) :: EIGENSTATESJy, MatrixJy
  REAL(KIND = DBL), DIMENSION(DIMJ) :: EIGENVALUESJy

    CALL DIAGONALIZEJy(EIGENSTATESJy,EIGENVALUESJY)

    CALL MATJy(MatrixJy)


    OPEN(1, FILE = 'EIGENVALUESJy.DAT')

    OPEN(2, FILE = 'EIGENSTATESJyREAL.DAT')

    OPEN(3,FILE = 'EIGENSTATESJyCOMPLEX.DAT')

    WRITE (1,*) EIGENVALUESJy
    WRITE (2,*) REAL(EIGENSTATESJy)
    WRITE (3,*) AIMAG(EIGENSTATESJy)

  CLOSE(1)

    CLOSE(2)

    CLOSE(3)

  END PROGRAM TEST

直到子程序DIAGONALIZEJy,我只是构建上述矩阵。通过简单地编写子例程MatJy.的结果,我可以很容易地检查Fortran构造。我将数据传输到 Mathematica。结果是:

 {{-1., -9.19403*10^-17, 1.}}

这是特征值列表。特征向量列表是:

 {{-0.5 + 0. I, 0. - 0.707107 I, 0.5 + 0. I}, {0.707107 + 0. I, 
  0. + 1.04083*10^-16 I, 0.707107 + 0. I}, {-0.5 + 0. I, 
   0. + 0.707107 I, 0.5 + 0. I}}

第一个特征向量对应于第一个特征值(至少是我从EigenvectorsJy逐个打印列向量得到的)。

显然,结果是错误的。见:

http://www.wolframalpha.com/widgets/view.jsp?id=9aa01caf50c9307e9dabe159c9068c41

我希望该链接显示使用小部件完成的特征值问题的结果。特征值是正确的,但所有特征向量都是偏离的。

另外,当我只运行在我的主程序中对矩阵进行对角化的子程序时,该子程序包含许多其他东西,结果是:

 {{0.885212, 0., -0.920222}}

 {{0.0439691 + 0. I, -0.388918 + 0. I, 0.5 + 0. I}, {0.707107 + 0. I, 
  0. + 1.04083*10^-16 I, 0.707107 + 0. I}, {-0.5 + 0. I, 
   0. + 0.707107 I, 0.5 + 0. I}}

正如您所看到的,非零特征值有点偏离,特征向量也是(并且仍然不正确)。为什么主程序会产生不同的结果,perhaph会加剧错误?另外,首先(最小的例子,见上文),为什么我得到错误的答案?

修改:显然,该链接未显示结果,因此这是一个片段:

enter image description here

1 个答案:

答案 0 :(得分:0)

简而言之,代码中的Jy矩阵似乎是所需内容的复杂共轭(即问题中发布的图像),这导致特征向量与正确的共轭结合。

上述错误似乎源于OP的假设,即列表导向输出(如write(*,*) A)打印&#34; row-major&#34;中的矩阵元素。订单,而实际上它们是打印在&#34;列专业&#34;订单(见下面的评论)。通过注意这一点并相应地更正程序,我认为该程序将按预期工作。

更具体地说,添加以下实用程序例程来打印矩阵

  subroutine printmat( msg, mat )
      implicit none
      character(*), intent(in) :: msg
      complex(DBL), intent(in) :: mat( dimJ, dimJ )
      integer i1, i2
      print *
      print *, msg
      do i1 = 1, dimJ
          print "(3('(',f10.6,',',f10.6,' ) '))", ( mat( i1, i2 ), i2 = 1,dimJ )
      enddo
  end subroutine

并检查子例程Jp

JmJyMATJy()的值
 Jp:
(  0.000000,  0.000000 ) (  0.000000,  0.000000 ) (  0.000000,  0.000000 ) 
(  1.414214,  0.000000 ) (  0.000000,  0.000000 ) (  0.000000,  0.000000 ) 
(  0.000000,  0.000000 ) (  1.414214,  0.000000 ) (  0.000000,  0.000000 ) 

 Jm:
(  0.000000,  0.000000 ) (  1.414214,  0.000000 ) (  0.000000,  0.000000 ) 
(  0.000000,  0.000000 ) (  0.000000,  0.000000 ) (  1.414214,  0.000000 ) 
(  0.000000,  0.000000 ) (  0.000000,  0.000000 ) (  0.000000,  0.000000 ) 

 Jy * sqrt(2):
(  0.000000,  0.000000 ) (  0.000000,  1.000000 ) (  0.000000,  0.000000 ) 
(  0.000000, -1.000000 ) (  0.000000,  0.000000 ) (  0.000000,  1.000000 ) 
(  0.000000,  0.000000 ) (  0.000000, -1.000000 ) (  0.000000,  0.000000 ) 

eigenvaluesJy(1) =  -1.000000
   eigvec:
    ( -0.500000,  0.000000 )
    (  0.000000, -0.707107 )
    (  0.500000,  0.000000 )
eigenvaluesJy(2) =  -0.000000
   eigvec:
    (  0.707107,  0.000000 )
    (  0.000000,  0.000000 )
    (  0.707107,  0.000000 )
eigenvaluesJy(3) =   1.000000
   eigvec:
    ( -0.500000,  0.000000 )
    (  0.000000,  0.707107 )
    (  0.500000,  0.000000 )

我们看到上面的Jy矩阵是所需矩阵的复共轭(在问题中作为图像给出)。原因似乎是JpJm矩阵作为正确矩阵的转置给出(根据thisthis等一些页面。例如,如果我们将其索引更改为

    SUBROUTINE MATJplus(MATOUT)
    IMPLICIT NONE
    COMPLEX(KIND = DBL),DIMENSION(DIMJ,DIMJ),INTENT(OUT)::MATOUT
    INTEGER::K,L
    REAL(KIND = DBL)::M,MP

    DO K = 1,DIMJ
    DO L = 1,DIMJ
    MP = (S + 1.0D0) - L     !! 1, 0, -1  ("m_prime")
    M = (S + 1.0D0) - K      !! 1, 0, -1  ("m")

    !>>> Here, we swap the indices K and L in the LHS
    !!  MATOUT(K,L) = DSQRT(S * (S + 1.0D0) - M * (M + 1.0D0)) * KRONDELTAR(MP, M + 1)
        MATOUT(L,K) = DSQRT(S * (S + 1.0D0) - M * (M + 1.0D0)) * KRONDELTAR(MP, M + 1)

   END DO
   END DO 
   call printmat( "Jplus:", matout )
   END SUBROUTINE

(并且类似地修改MATJminus()),我们获得了预期的结果:

 Jp:
(  0.000000,  0.000000 ) (  1.414214,  0.000000 ) (  0.000000,  0.000000 ) 
(  0.000000,  0.000000 ) (  0.000000,  0.000000 ) (  1.414214,  0.000000 ) 
(  0.000000,  0.000000 ) (  0.000000,  0.000000 ) (  0.000000,  0.000000 ) 

 Jm:
(  0.000000,  0.000000 ) (  0.000000,  0.000000 ) (  0.000000,  0.000000 ) 
(  1.414214,  0.000000 ) (  0.000000,  0.000000 ) (  0.000000,  0.000000 ) 
(  0.000000,  0.000000 ) (  1.414214,  0.000000 ) (  0.000000,  0.000000 ) 

 Jy * sqrt(2):
(  0.000000,  0.000000 ) (  0.000000, -1.000000 ) (  0.000000,  0.000000 ) 
(  0.000000,  1.000000 ) (  0.000000,  0.000000 ) (  0.000000, -1.000000 ) 
(  0.000000,  0.000000 ) (  0.000000,  1.000000 ) (  0.000000,  0.000000 ) 

eigenvaluesJy(1) =  -1.000000
   eigvec:
    ( -0.500000,  0.000000 )
    (  0.000000,  0.707107 )
    (  0.500000,  0.000000 )
eigenvaluesJy(2) =  -0.000000
   eigvec:
    (  0.707107,  0.000000 )
    (  0.000000, -0.000000 )
    (  0.707107,  0.000000 )
eigenvaluesJy(3) =   1.000000
   eigvec:
    ( -0.500000,  0.000000 )
    (  0.000000, -0.707107 )
    (  0.500000,  0.000000 )

为方便起见,以下是从以上页面中获取的一些矩阵(可以直接与上述JpJmJy进行比较):

Lxyz

Lpm