-1

Is it good practice to store state within a subroutines using static variables? I have in mind something like the following:

subroutine somesub()
logical, save :: first_call = .true.


if (first_call) then
! do some stuff

first_call = .false.
end if

! ... perform standard work

end subroutine somesub

Examples of "some stuff" include:

  1. Allocating work arrays. This is probably best done by automatic arrays.
  2. Initializing physical/mathematical constants which require some sort of runtime evaluation. A good example is pi = datan(1.0)*4d0.
  3. Reading in some parameters and physical contants from a namelist or text file.

According to this question, using static variables to store such state is frowned upon in instances with multithreading. Would this be an issue with openmp or mpi in a typical fortran physics simulation code?

What alternative do you recommend for dealing with physical constants and user modifiable parameters which are specific to specific subroutine?

Community
  • 1
  • 1
nbren12
  • 634
  • 1
  • 7
  • 11
  • 3
    This seems quite opinion based to me. I suggest using modules or derived types and store the data there. And use a separate initialization or configuration procedure. – Vladimir F Героям слава Jun 29 '16 at 20:11
  • Seconded. As you hint at this style can become a right royal pain when parallelising with OpenMP, it's just asking for race conditions; have a separate initialisation routine and stick it in a module. Oh, and datan is Fortran 66 style, atan is fine, and you can stick that expression in a parameter statement nowadays. – Ian Bush Jun 30 '16 at 06:39
  • are you strictly talking about fixed parameters? Using the term "state" makes me think the sub might change its values (after the initial call) – agentp Jun 30 '16 at 11:53

1 Answers1

2

This is too long and too instructive to be a comment, so I am putting it as an answer. It elaborates the comments of VladimirF.

If a subroutine is specific enough to have its own set of parameters that are not accessible to any other part of the program, create a module for that subroutine. Add the parameters of the subroutine as private entity of the module, add the subroutine itself (only the standard work) and add an initialization subroutine and eventually a finalization subroutine.

Make sure your program calls the initialization subroutine and eventually the finalization subroutine. To me, this is a best practice that applies elegantly to the general case that you might have in the future. For example, if it is necessary to save the state of the subroutine or free some system resources, the finalization is the best place.

This will work very well in MPI environment where each instance might have its own set of parameters for the subroutine. It will also be convenient with openmp as long as you know when to call the initialization.

Your module might look like this:

module some_mod
implicit none
    private
    ! declare all the stuff that are private to your module here
    public somesub, init_somesub, finalize_somesub
contains

    subroutine somesub()
        !
        ! perform only the standard work, nothing else
        !
    end subroutine somesub

    subroutine init_somesub()
        !
        ! do only the initialization here
        !
    end subroutine init_somesub

    subroutine finalize_somesub()
        !
        ! do some stuff here to finalize if necessary
        !
    end subroutine finalize_somesub

end module some_mod
innoSPG
  • 4,588
  • 1
  • 29
  • 42
  • is there a way to enforce a rule that says `somesub` can not modify the module scope variables? – agentp Jun 30 '16 at 12:04
  • If you want to hide some variables from `somesub`, just put them in another `module` as private variables or do not `use` that `module` in the `module` that defines `somesub`. To the extend that I know, all module variables are accessible to all the procedures defined in that module. In the first place, the goal of this `module` was to get ride of the saved variable in `somesub` and make them `private` `module` variables that are accessible only to `somesub` and the initialization and the finilization procedure. – innoSPG Jun 30 '16 at 12:51
  • 1
    this does seem like the best practice. It is kind of like using modules as singleton classes in c++. – nbren12 Jun 30 '16 at 17:30