在Mac OS X上链接Fortran中的LAPACK

Jon*_*ann 5 macos linker fortran gfortran lapack

我认为这是一个标准的菜鸟问题,但在整个上午搜索网络后,我决定不管怎么说.我在Mac OS 10.9上,我想从Fortran程序中调用LAPACK特征值例程.我有幸在昨天被介绍给Fortran,所以请原谅任何愚蠢的错误.

这是我想要运行的最小例子:

program eigtest
    complex A(3,3)
    real eigs(3)
    A(1,1) = cmplx(1,0)
    A(1,2) = cmplx(0,2)
    A(1,3) = cmplx(3,0)
    A(2,1) = cmplx(0,-2)
    A(2,2) = cmplx(5,0)
    A(2,3) = cmplx(1,-1)
    A(3,1) = cmplx(3,0)
    A(3,2) = cmplx(1,1)
    A(3,3) = cmplx(7,0)
    call heevd(A, eigs)
    write(*,*) eigs
end
Run Code Online (Sandbox Code Playgroud)

我了解到在OS X上,LAPACK是Accelerate框架的一部分,所以我尝试了以下方法:

gfortran -o eigtest -framework accelerate eigtest.f95
Run Code Online (Sandbox Code Playgroud)

但链接器抱怨:

Undefined symbols for architecture x86_64:
  "_heevd_", referenced from:
      _MAIN__ in ccleuVFO.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud)

Dem*_*ian 4

我不确定 Accelerate 框架是否有对 heevd(A, eigs) 的良好 fortran95 调用。下面,我总结了 zheevd lapack 子例程(及其所有工作区变量),以保持调用的良好和紧凑。您可以将这种丑陋的内容存储在外部模块中,以便您可以在程序中加载。我认为intel MKL拥有大部分lapack95接口,并且可能还有其他更好的方式与os x框架配合。下面的代码编译为:

gfortran -o eigtest -framework Accelerate eigtest.f95    

program eigtest
    complex(kind=8),allocatable :: A(:,:), eigs(:), vecs(:,:)
    integer                     :: ierr

    allocate(A(3,3),stat=ierr)
    if (ierr /= 0) STOP "*** not enough memory ***"

    A(1,1) = cmplx(1,0)
    A(1,2) = cmplx(0,2)
    A(1,3) = cmplx(3,0)
    A(2,1) = cmplx(0,-2)
    A(2,2) = cmplx(5,0)
    A(2,3) = cmplx(1,-1)
    A(3,1) = cmplx(3,0)
    A(3,2) = cmplx(1,1)
    A(3,3) = cmplx(7,0)
    !call heevd(A, eigs)
    call wrapped_zheevd(A, eigs,vecs)
    write(*,*) eigs

    contains

subroutine wrapped_zheevd (matin, &
                         zvals,zvecs )
    integer                                  :: ndim
    complex(kind=8),intent(in),  allocatable :: matin(:,:)
    complex(kind=8),intent(out), allocatable :: zvals(:),zvecs(:,:)
    character*1                              :: jobz='V',uplo='U'
    integer                                  :: info,lda,liwork,lrwork,lwork,n
    integer,                     allocatable :: iwork(:)
    real(kind=8),                allocatable :: rwork(:), w(:)
    complex(kind=8),             allocatable :: A(:,:),   work(:)
    integer                                  :: ierr

    ndim=size(matin(1,:))

    if (allocated(zvecs)) deallocate(zvecs)
    if (allocated(zvals)) deallocate(zvals)
    allocate(zvecs(ndim,ndim),zvals(ndim),stat=ierr)
    if (ierr /= 0) STOP "*** not enough memory ***"

    n=ndim
    lda=n

    lwork  = 2*n+n**2
    lrwork = 1+5*n+2*n**2
    liwork = 3+5*n

    allocate(a(ndim,ndim),w(ndim),work(lwork),&
             rwork(lrwork),iwork(liwork),stat=ierr)
    if (ierr /= 0) STOP "*** not enough memory ***"

    a=matin

    call zheevd(jobz,uplo,n,a,lda,w,work,lwork,rwork,lrwork,iwork,liwork,info)

    zvals=w
    zvecs=a

    deallocate(a,w,rwork,iwork,work)

end subroutine

end
Run Code Online (Sandbox Code Playgroud)