Fortran子程序dsygv返回无穷大

时间:2015-07-04 18:24:53

标签: fortran lapack

我遇到了解决广义特征问题的子程序的问题:

  

A * x = lambda * B * x,

其中A和B应该是对称矩阵,B是正定的。我正在尝试解决以下测试用例2x2

    program prog

      implicit none
      integer, parameter :: n=2
      integer :: work,lwork,info
      real(8) :: a(n,n), b(n,n), e(n)

      a(1,1) = -3
      a(1,2) = 4
      a(2,2) = 3
      b(1,1) = 1
      b(1,2) = 0
      b(2,2) = 1

      call dsygv(1, 'v', 'u', n, a, n, b, n, e, WORK, LWORK, INFO)

      write(6,*) info
      write(6,*) e
      write(6,*) a

   end program

并获得以下输出:

    0
    -5.0000000000000000        5.0000000000000000     
    -Infinity  0.44721359549995793  Infinity  0.89442719099991586

特征值是正确的,其中一个eivenvector是正确的,但我无法避免无穷大并获得另一个特征向量。

2 个答案:

答案 0 :(得分:1)

worklwork应该是数组(双精度和整数),并且必须根据手册正确调整大小。否则,LAPACK将使用一些不应该使用的内存部分,一切都会爆炸。

也可能有其他错误的论点。请参阅源代码并附上说明:http://www.netlib.org/lapack/lapack-3.1.1/html/dsygv.f.html

对Fortran初学者的建议:

不要使用write(6,*),而是使用write(*,*)并且不要使用real(8),而real(dp) dp是一个具有正确值的整数常量(使用selected_real_kind()或其他方法获取值,或者如果你坚持,只需将其设置为8。

答案 1 :(得分:1)

下面我建议更新您的代码,其中包括:

  • 使用便携式双精度类型值(wp);
  • 使用Print;
  • 显示您的输出
  • 使用LAPACK推荐的查询机制设置(双精度)工作区work

下面:

Program prog
  Implicit None
  Integer, Parameter :: n = 2
  Integer, Parameter :: wp = kind(0.0D0)
  Integer :: info, lwork
  Real (Kind=wp) :: a(n, n), b(n, n), dummy_work(1), e(n)
  Real (Kind=wp), Allocatable :: work(:)
  External :: dsygv
  Intrinsic :: int, kind, max

  ! Workspace query:
  lwork = -1
  Call dsygv(1, 'v', 'u', n, a, n, b, n, e, dummy_work, lwork, info)
  lwork = int(dummy_work(1))
  Allocate (work(max(1,lwork)))

  a(1, 1) = -3
  a(1, 2) = 4
  a(2, 2) = 3
  b(1, 1) = 1
  b(1, 2) = 0
  b(2, 2) = 1

  Call dsygv(1, 'v', 'u', n, a, n, b, n, e, work, lwork, info)

  Print *, 'info: ', info
  If (info==0) then
    Print *, 'e: ', e
    Print *, 'a: ', a
  end If

End Program

使用我的编译器,我得到了输出

 info:  0
 e:   -5.0000000000000000   5.0000000000000000
 a:   -0.8944271909999159   0.4472135954999579   0.4472135954999579   0.8944271909999159

请注意,某些供应商为LAPACK(和BLAS)例程提供显式接口。如果可用,您应该始终使用它们。 (这样做可能会在编译时诊断出错误输入的工作空间数组。)