如何在整个模块中将子例程名称作为参数传递?

时间:2017-06-10 23:23:24

标签: fortran arguments subroutine fortran95

我想使用一个变量子程序名称,我希望这个名称可以在整个模块中使用,而不只是在一个子程序中。

作为参数传递的变量子例程名称是一种数据。它存放在哪里?我该如何访问它?

这里有更多解释。 G是非线性拟合程序。 H使用G但是使用参数分组(迭代一次移动一个组)。 G使用一般的正向模型子例程,其名称作为参数传递。我希望H保持这种普遍性。

以下是使用硬编码子程序名称的变通方法的测试程序:

  module G_MOD
  implicit none
  character(len=30)::message='Good Morning'

  contains

  subroutine G(Sub)
  external::Sub
  call Sub
  end subroutine G

  end module G_MOD

  module H_MOD
  use G_MOD
  implicit none

  contains

  subroutine H(sub)
  external:: sub
  call G(LocalSub)
  end subroutine H

  subroutine LocalSub
  external:: MySub
  message='Good Afternoon'
  call G(MySub) ! the subroutine name "MySub" is hardcoded
                ! I would like it to be argument sub
  end subroutine LocalSub

  end module H_MOD

  program test
  use H_MOD
  implicit none
  external MySub
  call H(MySub)
  end program test

  subroutine MySub
  use G_MOD,only:message
  write(*,*)trim(Message)
  end subroutine MySub

1 个答案:

答案 0 :(得分:1)

解决方案1 ​​

如果您在LocalSub内部H,则无需存储任何内容:

  subroutine H(sub)
    external:: sub
    call G(LocalSub)
  contains
    subroutine LocalSub
      message='Good Afternoon'
      call G(sub)
    end subroutine LocalSub
  end subroutine H

它需要Fortran 2008.

通过一些清理,缩进以提高可读性,使用抽象接口删除丑陋的外部(Fortran 2003,但external即使在使用接口块的Fortran 90中也可以避免)代码是:

  module G_MOD
    implicit none
    character(len=30)::message='Good Morning'

    abstract interface
      subroutine sub_interface
      end subroutine
    end interface

  contains

    subroutine G(Sub)
      procedure(sub_interface) :: sub
      call Sub
    end subroutine G

  end module G_MOD

  module H_MOD
    use G_MOD
    implicit none

  contains

    subroutine H(sub)
      procedure(sub_interface) :: sub
      call G(LocalSub)
    contains
      subroutine LocalSub

        message='Good Afternoon'
        call G(sub) 
      end subroutine LocalSub
    end subroutine H

  end module H_MOD

  program test
    use H_MOD
    implicit none


    call H(MySub)
  contains
    subroutine MySub
      use G_MOD,only:message
      write(*,*)trim(Message)
    end subroutine MySub
  end program test

解决方案2

如果您真的想在模块中存储对过程的引用,则可以,但请记住全局变量是。如果您想并行多次调用优化怎么办?

因此,您可以在procedure pointer中存储过程的地址(而不是名称)。这些需要Fortran 2003.代码的最小更改是

  module H_MOD
    use G_MOD
    implicit none

    procedure, pointer :: stored_sub => null()

  contains

    subroutine H(sub)
      external:: sub
      stored_sub => sub
      call G(LocalSub)
    end subroutine H

    subroutine LocalSub
      message='Good Afternoon'
      call G(stored_sub)
    end subroutine LocalSub

  end module H_MOD

但更好的现代代码是:

  module G_MOD
    implicit none
    character(len=30)::message='Good Morning'

    abstract interface
      subroutine sub_interface
      end subroutine
    end interface

  contains

    subroutine G(Sub)
      procedure(sub_interface) :: sub
      call Sub
    end subroutine G

  end module G_MOD

  module H_MOD
    use G_MOD
    implicit none

    procedure(sub_interface), pointer :: stored_sub => null()

  contains

    subroutine H(sub)
      procedure(sub_interface) :: sub
      stored_sub => sub
      call G(LocalSub)

    end subroutine H

    subroutine LocalSub

      message='Good Afternoon'
      call G(stored_sub) 
    end subroutine LocalSub

  end module H_MOD


  module MySub_module
  contains
    subroutine MySub
      use G_MOD,only:message
      write(*,*)trim(Message)
    end subroutine MySub
  end module MySub_module

  program test
    use H_MOD
    use MySub_module
    implicit none


    call H(MySub)
  end program test

尽管如此,我肯定更喜欢使用内部程序的变体。

请记住,使用缩进,这对于可读代码至关重要。