【问题标题】:Fortran 90 called with implicit interface when passing procedure as argument将过程作为参数传递时使用隐式接口调用 Fortran 90
【发布时间】:2017-11-02 18:41:12
【问题描述】:

我想使用牛顿求解器来求解一些方程。这些方程的一些参数在这个过程中发生了变化。我想将方程作为函数传递给牛顿函数,如下所示: http://faculty.washington.edu/rjl/classes/am583s2013/notes/fortran_newton.html

但我收到了我不明白的警告。

我列出了一个简化的例子:

    module a
      use b
      ! module parameters:
      implicit none
    contains
      subroutine newton_method(f, fp, x0, x, iters, debug)
        implicit none
        real(kind=8), intent(in) :: x0
        real(kind=8), external :: f, fp
        logical, intent(in) :: debug
        real(kind=8), intent(out) :: x
        integer, intent(out) :: iters
        ! Declare any local variables:
        real(kind=8) :: deltax, fx, fxprime
        integer :: k
        fx = f(x)
        fxprime = fp(x)
        deltax = fx/fxprime
        return
      end subroutine newton_method
    end module a

   module b
     type, public::b_argument
        real(kind = 8)::d
        real(kind = 8)::e
        real(kind = 8)::f
     end type b_argument
     type(b_argument):: b_argu
   contains
     function gx( x )    result(gx_out)
       implicit none
       real(kind = 8)::x
       real(kind = 8)::gx_out
       real(kind = 8)::d, e, f
       d= b_argu%d
       e= b_argu%e
       f= b_argu%f
       gx_out = d * x * x + e * x + f
       return
     end function gx
     function gx_prime( x )  result(gx_prime_out)
       implicit none
       real(kind = 8)::x
       real(kind = 8)::gx_prime_out
       real(kind = 8)::d, e
       d= b_argu%d
       e= b_argu%e
       gx_prime_out = 2 * d * x + e
       return
     end function gx_prime
   end module b

   program c
     use a
     use b
     implicit none
     real(kind = 8):: x, x0
     integer :: iters
     logical :: debug ! set to .true. or .false.
     x0 = 1.0 !guess
     !change argument every time
     b_argu%d = 3
     b_argu%e = 4
     b_argu%f = 5
     call newton_method(gx, gx_prime, x0, x, iters, debug)
   end program c

制作文件:

    f90comp = gfortran
    FFLAGS_DEBUG = -Wall -Wextra -Wimplicit-interface -fPIC -fmax-errors=1 -ggdb -fcheck=all -fbacktrace
    FFLAGS_OPT = -ggdb -O3 -fdefault-real-8 -fdefault-double-8 -ffree-line-length-none -Wuninitialized
    exe_file = c
    objects = a.o \
        b.o \
        c.o 
    mods = a.mod \
        b.mod \
        c.mod
    .PHONY: clean
    $(exe_file): $(objects) 
        @$(f90comp) $(FFLAGS_DEBUG) $(objects) -o $(exe_file)
        @echo "Code is now linking..."
    %.o: %.f90
        $(f90comp) $(FFLAGS_DEBUG) -c $<
    clean:
        @rm -rf $(objects) $(exe_file)
        @rm -rf $(mods)
    debug: FFLAGS_OPT = $(FFLAGS_DEBUG)
    debug: $(exe_file)
    a.o: b.o
    c.o: a.o b.o     

我收到的警告是:

   make
   gfortran -Wall -Wextra -Wimplicit-interface -fPIC -fmax-errors=1 -ggdb -fcheck=all -fbacktrace -c b.f90
   gfortran -Wall -Wextra -Wimplicit-interface -fPIC -fmax-errors=1 -ggdb -fcheck=all -fbacktrace -c a.f90
   a.f90:16:17:

                fx = f(x)
                    1
   Warning: Procedure 'f' called with an implicit interface at (1) [-Wimplicit-interface]
   a.f90:17:22:

                fxprime = fp(x)
                         1
   Warning: Procedure 'fp' called with an implicit interface at (1) [-Wimplicit-interface]
   a.f90:6:61:

              subroutine newton_method(f, fp, x0, x, iters, debug)
                                                                1
   Warning: Unused dummy argument 'debug' at (1) [-Wunused-dummy-argument]
   a.f90:6:54:

              subroutine newton_method(f, fp, x0, x, iters, debug)
                                                         1
   Warning: Dummy argument 'iters' at (1) was declared INTENT(OUT) but was not set [-Wunused-dummy-argument]
   a.f90:15:24:

                integer :: k
                           1
   Warning: Unused variable 'k' declared at (1) [-Wunused-variable]
   a.f90:6:44:

              subroutine newton_method(f, fp, x0, x, iters, debug)
                                               1
   Warning: Unused dummy argument 'x0' at (1) [-Wunused-dummy-argument]
   gfortran -Wall -Wextra -Wimplicit-interface -fPIC -fmax-errors=1 -ggdb -fcheck=all -fbacktrace -c c.f90
   Code is now linking...

那么为什么 ffp 调用是隐式的?它们作为参数传入?它们都在模块中定义,所以我不能再使用接口了。

【问题讨论】:

  • 事实证明,每当一个过程(定义在另一个模块中)作为参数传递时,都会触发这个警告。
  • 请注意,real(kind=8) 很丑陋,不可移植,而且过于冗长。这并不意味着 8 字节,在几个编译器中没有种类 8,尽管它们确实有 8 字节实数。对 Fortran 类型使用命名常量,而不是魔术常量,它们不可移植。并且对于复杂的变量也可能会造成混淆。最近我们有两个用户对复数感到困惑,他们的代码返回了错误的答案。

标签: fortran newtons-method


【解决方案1】:

在 newton_method 中,伪参数 f 和 fp 的接口是隐式的。您说的是外部,而不是使用 INTERFACE 块声明它们。您使用的编译器有一个可选的诊断功能,当您对具有隐式接口的过程进行任何调用时会向您发出警告,这是一件好事。您启用了此警告,编译器完成了它的工作。

解决此问题的方法是使用 INTERFACE 或 PROCEDURE(abstract_interface) 来声明 f 和 fp 而不是 EXTERNAL。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-15
    • 2011-12-04
    • 1970-01-01
    • 2020-12-20
    相关资源
    最近更新 更多