如何在公共块和模块之间共享数据?

How to share data between a common block and a module?

如何以尽可能少的修改将新的 Fortran 90 模块与旧代码连接起来?这个想法是对子例程中的新代码使用 "module",同时尽可能少地修改旧代码(即保持公共块不变)。

为了演示我打算实现的目标,这里有一个简单的程序:

考虑一个简单的程序:

  module Bmod
     real*8 x
  end module Bmod

  program main
    use Bmod
    common /a/ x   ! old code                       
    do i=1, 5
       x=3.14159  ! do something with x in fortran77
       call B()   ! new f90 code
    enddo
  end program main

  ! new features added here   
  subroutine new_code()
    use Bmod
    write(*,*) 'x in B=', x
  end subroutine new_code

但是编译时出现错误:

 error #6401: The attributes of this name conflict with those made accessible by a USE statement.   [X]
    common /a/ x

一个简单的解决办法是乘坐common everywhere。但这在我的情况下是不允许的,因为它会修改旧代码。此外,旧代码包含数千个变量,分布在几个以旧样式编写的公共块上。

您可以将公共块定义放在模块中。在那种情况下,您可以将两者结合起来,但您必须小心访问它的方式。

您不能在任何已经通过模块访问它的单元中定义公共块。

  module Bmod
    real*8 x
    common /a/ x   ! old code                       
  end module Bmod

  program main
    real*8 x
    common /a/ x   ! old code                       
    do i=1, 5
       x=3.14159  ! do something with x in fortran77
       call new_code()   ! new f90 code
    enddo
  end program main

  ! new features added here   
  subroutine new_code()
    use Bmod
    write(*,*) 'x in B=', x
  end subroutine new_code

关于您的错误信息:

您显示的代码无效

您首先从模块

导入符号[=​​13=]
use Bmod !x is in Bmod

然后你说它在一个命名的公共块中

common /a/ x  

你可以选择其中之一,两者都没有任何意义。您有一个模块变量,或者一个来自公共块的变量。

您不必一次删除所有公共块。一次甚至没有一个完整的公共块。但是一旦你将一些变量移动到一个模块中,你就不能同时将它放在公共块中。你可以一次只处理一个变量,如果你想把它放在一个模块中,就把它从公共块中删除,然后把它放到一个模块中。

如果你想改变声明变量的方式,你必须始终如一地做到这一点。

我假设你有这样的事情:

program common
    implicit none
    real*8 x
    common /a/ x
    x = 3.0
    call mysub()
    print *, x
end program common

subroutine mysub()
    implicit none
    real*8 x
    common /a/ x
    x = 4.0
end subroutine mysub

如果您现在想将 x 的声明移动到一个单独的模块中(不错的选择!),您必须始终如一地进行。即不能在模块中声明x,然后在程序中将x部分做成一个公共块。

最好的解决方案是完全删除公共块:

module mymod
    implicit none
    real*8 x
end module mymod

program common
    use mymod
    implicit none
    x = 3.0
    call mysub()
    print *, x
end program common

subroutine mysub()
    use mymod
    implicit none
    x = 4.0
end subroutine mysub

但如果出于政治原因您必须保留 COMMON 块,则必须将其移至模块中:

module mymod
    implicit none
    real*8 x
    common /a/ x
end module mymod

program common
    use mymod
    implicit none
    x = 3.0
    call mysub()
    print *, x
end program common

subroutine mysub()
    implicit none
    real*8 x
    common /a/ x
    x = 4.0
end subroutine mysub

(我写这个感觉很脏...)

当然,如果模块和COMMON块中的两个x不一样,你可以随时在本地更改它们的名称:

use mymod, only: y => x

这将使模块的 x 可用作 y,同时保持通用 x 不变。