无法从同一范围调用函数

时间:2015-03-25 21:43:30

标签: fortran fortran90 gfortran

我对范围感到困惑。我下载了一个Fortran文件,该文件在1个源文件中有1个主程序,1个子程序和1个函数。主程序不包含子程序,子程序调用该函数。它工作正常,但是当我使用" contains"修改主程序以包含这2个子程序时,它会产生编译错误,说明函数未定义。但是,如果我在同一个包含的部分中创建一个小函数并从子例程调用,它就不会出错。

这两个功能有什么区别?为什么我会收到错误?

我创建了一个具有相同结构的小程序,1个包含子程序和func的main程序并没有给出错误。

我的环境是ubuntu 14.04并使用gfortran编译器。


建筑目标:QRbasic 调用:GNU Fortran Linker gfortran -o" QRbasic" ./main.o
./main.o:在函数qrbasic': /*/QRbasic/Debug/../main.f95:79: undefined reference to ajnorm _' /home/kenji/workspace/QRbasic/Debug/../main.f95:104:未定义引用`ajnorm _' collect2:错误:ld返回1退出状态 make:*** [QRbasic]错误1


Program Main
!====================================================================
! QR basic method to find the eigenvalues
! of matrix A
!====================================================================
implicit none
integer, parameter :: n=3
double precision, parameter:: eps=1.0e-07
double precision :: a(n,n), e(n)
integer i, j, iter

! matrix A
!  data (a(1,i), i=1,3) /   8.0, -2.0, -2.0 /
!  data (a(2,i), i=1,3) /  -2.0,  4.0, -2.0 /
!  data (a(3,i), i=1,3) /  -2.0, -2.0, 13.0 /

  data (a(1,i), i=1,3) /   1.0,  2.0,  3.0 /
      data (a(2,i), i=1,3) /   2.0,  2.0, -2.0 /
  data (a(3,i), i=1,3) /   3.0, -2.0,  4.0 /


! print a header and the original matrix
  write (*,200)
  do i=1,n
     write (*,201) (a(i,j),j=1,n)
  end do
! print: guess vector x(i)
!  write (*,204)
!  write (*,201) (y(i),i=1,3)

  call QRbasic(a,e,eps,n,iter)

! print solutions
  write (*,202)
  write (*,201)  (e(i),i=1,n)
  write (*,205) iter

200 format (' QR basic method - eigenvalues for A(n,n)',/, &
            ' Matrix A')
201 format (6f12.6)
202 format (/,' The eigenvalues')
205 format (/,' iterations = ',i5)
!end program main

contains
subroutine QRbasic(a,e,eps,n,iter)
!==============================================================
! Compute all eigenvalues: real symmetric matrix a(n,n,)
! a*x = lambda*x
! method: the basic QR method
! Alex G. (January 2010)
!--------------------------------------------------------------
! input ...
! a(n,n) - array of coefficients for matrix A
! n      - dimension
! eps    - convergence tolerance
! output ...
! e(n)   - eigenvalues
! iter   - number of iterations to achieve the tolerance
! comments ...
! kmax   - max number of allowed iterations
!==============================================================
implicit none
integer n, iter
double precision a(n,n), e(n), eps
double precision q(n,n), r(n,n), w(n), an, Ajnorm, sum, e0,e1
integer k, i, j, m
integer, parameter::kmax=1000

! initialization
q = 0.0
r = 0.0
e0 = 0.0

do k=1,kmax              ! iterations

! step 1: compute Q(n,n) and R(n,n)
! column 1
  an = Ajnorm(a,n,1)
  r(1,1) = an
  do i=1,n
    q(i,1) = a(i,1)/an
  end do
! columns 2,...,n
  do j=2,n
    w = 0.0
    do m=1,j-1
! product q^T*a result = scalar
      sum = 0.0
      do i=1,n
        sum = sum + q(i,m)*a(i,j)
      end do
      r(m,j) = sum
! product (q^T*a)*q  result = vector w(n)
      do i=1,n
        w(i) = w(i) + sum*q(i,m)
      end do
    end do
! new a'(j)
    do i =1,n
      a(i,j) = a(i,j) - w(i)
    end do
! evaluate the norm for a'(j)
    an = Ajnorm(a,n,j)
    r(j,j) = an
! vector q(j)
    do i=1,n
      q(i,j) = a(i,j)/an
    end do
  end do

! step 2: compute A=R(n,n)*Q(n,n)
  a = matmul(r,q)
! egenvalues and the average eigenvale
  sum = 0.0
  do i=1,n
    e(i) = a(i,i)
    sum = sum+e(i)*e(i)
  end do
  e1 = sqrt(sum)

! print here eigenvalues
!  write (*,201)  (e(i),i=1,n)
!201 format (6f12.6)

! check for convergence
  if (abs(e1-e0) < eps) exit
! prepare for the next iteration
  e0 = e1
end do

iter = k
if(k == kmax) write (*,*)'The eigenvlue failed to converge'
 print *, func1()
end subroutine QRbasic

function Ajnorm(a,n,j)
implicit none
integer n, j, i
double precision a(n,n), Ajnorm
double precision sum

sum = 0.0
do i=1,n
  sum = sum + a(i,j)*a(i,j)
end do
Ajnorm = sqrt(sum)
end function Ajnorm

integer function func1()
print *, "dummy"
func1=1
end function

end program

原始程序不包含这两个程序。这是我收到错误的版本。

1 个答案:

答案 0 :(得分:2)

您的主程序包含函数类型Ajnorm()的声明。因此,当编译器找到要用作函数名的名称时,它会将其解释为外部函数。这在程序的原始形式中非常正确,函数被定义为一个独立的单元,但对于内部(包含)函数来说是错误的。一旦我删除了不需要的声明,你的程序就会为我编译干净。