0

This is part of a main program

PROGRAM program1
USE method
USE variables
IMPLICIT NONE
:
CALL method_init(A,a1end,C)
:
END PROGRAM program1

The call to method_init, contained in the module method, "initializes" a method in that it builds arrays a1end and C form the array A (other calls to other procedures contained in the module should follow). Arrays a1end and C are part of the method, so they are both declared in the method module; the array A is not part of the method (it could be "solved" with another method), so it is declared in the module variables.

The arrays C and a1end could be used by subroutines not contained in the method module, so they must be declared before the CONTAINS statement. So, the subroutine contained in the method module could use these variables without using them as input/output variables, but this would make unclear the role of the subroutine (the call would be simply CALL method_init, so "How does this subroutine operate? Which arrays does it use? And which modify? ..."), so I prefer to have the call as CALL method_init(A,a1end,C).

This means that the module method is like this

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

I'd like to know if this is a correct way of programming. Is it just a matter of taste?

EDIT The question, in short, is: Is a correct way of programming to use variables defined in a module as input/output arguments of procedure contained in the module itself? Or it is better to write subroutines with no arguments? Or everything is just a matter of taste?

The questions/answers linked by @Vladimir F make me think that yes, it' a matter of taste. Nevertheless none of these question touches the specific point I'm interested into (i.e. procedures that are in a module and use a variable defined in the module as input/output arguments).

Enlico
  • 23,259
  • 6
  • 48
  • 102
  • It's been an long time since I've looked at FORTRAN. It hurts my eyes. Please read the FAQ on what questions are appropriate on SO. Opinion based questions are not, because it's not a discussion board. – duffymo Apr 13 '16 at 12:17
  • 1
    I can't clearly follow what you write in the time I have available, but is your question about the idea of scope: local dummy variables and module variables? – francescalus Apr 13 '16 at 12:53
  • 2
    Related/duplicates? http://stackoverflow.com/questions/8412834/correct-use-of-modules-subroutines-and-functions-in-fortran http://stackoverflow.com/questions/11953087/proper-use-of-modules-in-fortran http://stackoverflow.com/questions/1240510/how-do-you-use-fortran-90-module-data – Vladimir F Героям слава Apr 13 '16 at 13:09
  • 1
    I wouldn't do it that way and probably rather use a derived datatype with the actual variable directly declared in the program, but your code is legal Fortran. – haraldkl Apr 14 '16 at 04:05

1 Answers1

2

My answer would be that you did the right choice as I would always recommend to write procedures with all its parameters and avoid using global variables (like C and a1end in your example).

However, many people in Fortran use to use global variables and would not bother passing these arguments, sometimes for wrong reason (like "it's faster to write"). But it is still totally correct to use global variable in a module if you imagine the latter as being a box containing its own specific and unique set of parameters. Maybe then you would want to specify them as Fortran parameter (with the associated keyword).

When you question yourself about passing arguments or using global variables for a function/subroutine, a simple choice would be whether or not your function is bound to be called/reused with other different parameters somewhere else in your code, or sometime later in your development process. This is particularly true when you think of your module as a box that you can unplug and give to a mate for his own needs, then you might want your method_init to be more flexible, thus expliciting the arguments.

Note: in your example, I would recommend to name your subroutine arguments differently than your module's variables in order to avoid any confusion in the code and be able to use them without any conflict:

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
  • 2
    Sorry, that was a bit ambiguous, I was referring to variables defined outside subroutines/functions, here in a module, and thus accessible anywhere in the code through the `use module`. – Mathieu Coquerelle Apr 14 '16 at 13:30
  • @francescalus This will depend on your choice of definition for "global variable" (it not being a Fortran term), but I call publicly accessible unprotected module variables "global variables" (and likewise objects in common blocks too). Because they can be trivially accessed and varied from anywhere in the program, they are part of the global state of the program (multiple images aside) and are hence subject to the downsides typically quoted for use of global variables. The identifier isn't global, but the identifier isn't the variable, it is an identifier for the variable. – IanH Apr 14 '16 at 20:53
  • @IanH (and Mathieu Coquerelle) I'll happily accept "global" to mean such variables in a module. It's just that I'm perhaps scarred by common blocks being meant by an unqualified "global". [Which is admittedly ludicrous given the context: I'll delete my unhelpful comment.] – francescalus Apr 14 '16 at 21:11