Module 带有模块和子程序的fortran程序结构

Module 带有模块和子程序的fortran程序结构,module,scope,fortran,subroutine,Module,Scope,Fortran,Subroutine,这是主程序的一部分 PROGRAM program1 USE method USE variables IMPLICIT NONE : CALL method_init(A,a1end,C) : END PROGRAM program1 对方法模块中包含的方法的调用“初始化”了一个方法,因为它构建了数组aEnd和C构成数组a(应该遵循对模块中包含的其他过程的其他调用)。 数组a1end和C是方法的一部分,因此它们都在方法模块中声明;数组A不是方法的一部分(可以用另一种方法“求解”),因此它在模

这是主程序的一部分

PROGRAM program1
USE method
USE variables
IMPLICIT NONE
:
CALL method_init(A,a1end,C)
:
END PROGRAM program1
方法
模块中包含的
方法
的调用“初始化”了一个方法,因为它构建了数组
aEnd
C
构成数组
a
(应该遵循对模块中包含的其他过程的其他调用)。 数组
a1end
C
是方法的一部分,因此它们都在
方法
模块中声明;数组
A
不是方法的一部分(可以用另一种方法“求解”),因此它在模块
变量中声明

数组
C
a1end
可由
方法
模块中未包含的子例程使用,因此必须在
包含
语句之前声明它们。 因此,
方法
模块中包含的子例程可以使用这些变量,而不使用它们作为输入/输出变量,但这会使子例程的角色变得不明确(调用将只是
调用方法_init
,因此“该子例程如何运行?它使用哪些数组?哪些修改?…),因此我更喜欢将调用作为
callmethod\u init(A,a1end,C)

这意味着模块
方法
如下

MODULE method
    IMPLICIT NONE
    REAL, DIMENSION(:,:), ALLOCATABLE :: C     ! declared here to be used...
    REAL, DIMENSION(:,:), ALLOCATABLE :: a1end ! ...by procedures outside this module
    :
CONTAINS
    SUBROUTINE method_init(A,a1end,C)
    IMPLICIT NONE
    REAL, DIMENSION(:,:), ALLOCATABLE, INTENT(IN) :: A ! deferred shape (it's allocated elsewhere in the main program)j
    REAL, DIMENSION(:,:), ALLOCATABLE, INTENT(OUT) :: C     ! declared here to be used...
    REAL, DIMENSION(:,:), ALLOCATABLE, INTENT(OUT) :: a1end ! ...as input/output variables
    :
    ALLOCATE(C(  ),a1end(   ))
    :
    END SUBROUTINE method_init
END MODULE method
我想知道这是否是一种正确的编程方式。这只是口味的问题吗

编辑简而言之,问题是: 使用模块中定义的变量作为模块本身包含的过程的输入/输出参数是正确的编程方式吗?或者编写没有参数的子例程更好?还是一切都只是品味的问题?


由@Vladimir F链接的问题/答案让我觉得是的,这是一个品味的问题。尽管如此,这些问题都没有触及我感兴趣的特定点(即模块中的过程,并使用模块中定义的变量作为输入/输出参数).

我的答案是,您做了正确的选择,因为我总是建议您编写包含所有参数的过程,并避免使用全局变量(例如您的示例中的
C
a1end

然而,Fortran中的许多人使用全局变量,并且不会费心传递这些参数,有时是因为错误的原因(比如“写起来更快”)。 但是,如果您将模块中的全局变量想象成一个包含自己特定且唯一的参数集的框,那么在模块中使用全局变量仍然是完全正确的。然后,您可能希望将它们指定为Fortran
参数
(带有相关关键字)

当您询问自己有关传递参数或使用函数/子例程的全局变量的问题时,一个简单的选择是,您的函数是否会在代码中的其他地方或稍后的开发过程中被其他不同的参数调用/重用。 尤其是当你认为你的模块是一个盒子,你可以把它拔掉,交给一个配偶来满足他自己的需要,那么你可能希望你的
方法更加灵活,从而明确参数

注意:在您的示例中,我建议您将子例程参数命名为与模块变量不同的名称,以避免代码中出现任何混乱,并能够使用它们而不会产生任何冲突:

MODULE method
    IMPLICIT NONE
    REAL, DIMENSION(:,:), ALLOCATABLE :: C
    REAL, DIMENSION(:,:), ALLOCATABLE :: a1end 

CONTAINS

    SUBROUTINE method_init(A,my_a1end,my_C)
    IMPLICIT NONE ! Already specified above
    REAL, DIMENSION(:,:), ALLOCATABLE, INTENT(IN) :: A
    REAL, DIMENSION(:,:), ALLOCATABLE, INTENT(OUT) :: my_C
    REAL, DIMENSION(:,:), ALLOCATABLE, INTENT(OUT) :: my_a1end
    ALLOCATE(my_C(  ),my_a1end(   ))
    ! Here you can work with module's C and a1end
    ! Given that they have been effectively allocated
    ! You can also test whether C and my_C are the same object or not (pointerwise speaking)
    END SUBROUTINE method_init
END MODULE method

我的答案是,您的选择是正确的,因为我总是建议您编写包含所有参数的过程,并避免使用全局变量(例如示例中的
C
a1end

然而,Fortran中的许多人使用全局变量,并且不会费心传递这些参数,有时是因为错误的原因(比如“写起来更快”)。 但是,如果您将模块中的全局变量想象成一个包含自己特定且唯一的参数集的框,那么在模块中使用全局变量仍然是完全正确的。然后,您可能希望将它们指定为Fortran
参数
(带有相关关键字)

当您询问自己有关传递参数或使用函数/子例程的全局变量的问题时,一个简单的选择是,您的函数是否会在代码中的其他地方或稍后的开发过程中被其他不同的参数调用/重用。 尤其是当你认为你的模块是一个盒子,你可以把它拔掉,交给一个配偶来满足他自己的需要,那么你可能希望你的
方法更加灵活,从而明确参数

注意:在您的示例中,我建议您将子例程参数命名为与模块变量不同的名称,以避免代码中出现任何混乱,并能够使用它们而不会产生任何冲突:

MODULE method
    IMPLICIT NONE
    REAL, DIMENSION(:,:), ALLOCATABLE :: C
    REAL, DIMENSION(:,:), ALLOCATABLE :: a1end 

CONTAINS

    SUBROUTINE method_init(A,my_a1end,my_C)
    IMPLICIT NONE ! Already specified above
    REAL, DIMENSION(:,:), ALLOCATABLE, INTENT(IN) :: A
    REAL, DIMENSION(:,:), ALLOCATABLE, INTENT(OUT) :: my_C
    REAL, DIMENSION(:,:), ALLOCATABLE, INTENT(OUT) :: my_a1end
    ALLOCATE(my_C(  ),my_a1end(   ))
    ! Here you can work with module's C and a1end
    ! Given that they have been effectively allocated
    ! You can also test whether C and my_C are the same object or not (pointerwise speaking)
    END SUBROUTINE method_init
END MODULE method

我已经很久没有看FORTRAN了。我的眼睛疼。请阅读常见问题解答,了解哪些问题适用于SO。基于意见的问题不是,因为它不是一个讨论板。我不能在我有时间的时候清楚地理解你写的内容,但是你关于范围概念的问题:局部虚拟变量和模块变量?相关/重复?我不会这样做,可能更愿意使用派生数据类型,并在程序中直接声明实际变量,但您的代码是合法的Fortran。我已经很久没有看过Fortran了。我的眼睛疼。请阅读常见问题解答,了解哪些问题适用于SO。基于意见的问题不是,因为它不是一个讨论板。我不能在我有时间的时候清楚地理解你写的内容,但是你关于范围概念的问题:局部虚拟变量和模块变量?相关/重复?我不会这样做,可能更愿意使用派生数据类型,并在程序中直接声明实际变量,但您的代码是合法的Fortran。对不起,这有点含糊不清,我指的是定义的变量