【问题标题】:Subroutine ignores type declaration above in module子例程忽略模块中的上述类型声明
【发布时间】:2016-11-21 15:00:21
【问题描述】:

我在模块中创建了一个类型model,然后声明了一个具有该类型的变量md。在模块中包含的子程序中,上面md的声明被忽略了,我必须再次显式声明。

在主程序中我不需要声明md 的类型,use 语句似乎可以工作。谁能解释一下为什么子程序会忽略md的类型声明?

这里是代码。我在 Linux 上使用 gfortran 编译器。

program main
  use struc_model
  call mod_gen(md)
  do i=1, md%ndof
    write(*,*) 'row =', i
    write(*,*) 'm=', md%m(i,:)
  end do  
end

module struc_model
  type model
    integer :: ndof
    real*8, allocatable, dimension(:,:) :: m
  end type
  type (model) :: md
  contains
  subroutine mod_gen(md)
  ! for some reason have to declare type of md again
  ! declaration above is ignored
    type (model) :: md  
    md%ndof=4
    allocate(md%m(md%ndof,md%ndof))
    md%m=0.d0
    do i=1, md%ndof
      md%m(i,i)=1.d0
    end do
  end subroutine
end module

【问题讨论】:

  • 子程序md 中的变量mod_gen 是一个伪参数,而不是模块变量。你打算发生什么?您希望子程序修改模块变量还是只修改虚拟变量?

标签: fortran


【解决方案1】:

这里有三个感兴趣的术语:使用关联、主机关联和参数关联。您可以通过其他资源详细了解这些内容,但我将在此处使用它们进行解释。

首先看模块。为了清楚起见,我将把你的变量设为整数类型。这是一个简单的程序

module mod
  implicit none
  integer i
end module mod

program prog
  use mod
  implicit none
  print *, i       ! i is use associated
end program prog

在这里,我们并不是说i 的类型通过模块的声明是已知的,我们说i 是模块中的变量(其类型由此而来)。

现在看一个简化的模块:

module mod
  implicit none
  integer i

contains

  subroutine sub(i)
    integer i
  end subroutine

end module mod

那么,为什么我需要在子程序sub 中声明integer i?那是因为在该子例程中的i,就像它在参数列表中一样,是一个虚拟参数。伪参数需要在其范围内指定其类型,即子例程。在子例程中,对i 的引用是对虚拟参数而不是对模块变量的引用:模块变量是不可访问的。

如果我的程序看起来像

  use mod
  call sub(i)
end program

我正在做的是将模块变量i---已使用关联---传递给子例程sub作为其虚拟参数(通过参数关联)。

现在,如果我想在模块的子例程中修改模块变量,我可以改用主机关联

module mod
  implicit none
  integer i

contains

  subroutine sub()  ! No dummy argument i, references in here are to the module's i
  end subroutine

end module mod

program prog
  use mod
  implicit none

  call sub   ! No argument for the module's own variable
end program prog

在该模块子程序中i 引用模块变量。

但我怀疑你的意思是在程序的范围内有一个变量,它被传递给子例程。回到你的术语:

module struc_model
  type model
    integer :: ndof
    real*8, allocatable, dimension(:,:) :: m
  end type
  contains
  subroutine mod_gen(md)
    type (model) :: md  
    md%ndof=4
    allocate(md%m(md%ndof,md%ndof))
    md%m=0.d0
    do i=1, md%ndof
      md%m(i,i)=1.d0
    end do
  end subroutine
end module

program main
  use struc_model
  type (model) :: md    ! A variable within the program's scope
  call mod_gen(md)      ! Argument associated with the subroutine's dummy
  do i=1, md%ndof
    write(*,*) 'row =', i
    write(*,*) 'm=', md%m(i,:)
  end do  
end

总结

module struc_model
  type model
    integer :: ndof
    real*8, allocatable, dimension(:,:) :: m
  end type
  type (model) :: md
end module

声明一个模块变量md,并没有说明所有名为md的变量都属于type(model)。

【讨论】:

  • 非常感谢您。写的很好,现在明白了。我想我的意图是使用子程序级别之上的模块中的声明。所以实际上我可以将 md 完全排除在参数列表之外,并使用模块声明,就像过去的常见块一样。这将是我的方法。
  • 很高兴它很有用。如果您想查看有关通用块替代方案的更多详细信息,那么您可能也会对this other question 的答案感兴趣。
猜你喜欢
  • 2019-03-21
  • 1970-01-01
  • 2017-03-06
  • 2017-03-07
  • 1970-01-01
  • 2016-03-19
  • 2020-11-10
  • 1970-01-01
  • 2018-01-02
相关资源
最近更新 更多