I want to know if it's possible to declare a variable and have declaration carry over to another subroutine or program (hence become global)
For example
program main
implicit none
call mysub
print *, x
end program main
subroutine mysub
implicit none
integer, parameter :: x = 1
end subroutine mysub
Would print "1"
Is this possible? I want to do this because a program I'm working on has large sets of variables that I would rather avoid copying unless necessary.
The most straightforward way to do this in modern Fortran is with modules.
Consider
module globals
implicit none
integer :: x
end module globals
program main
use globals
implicit none
call mysub
print *,x
end program main
subroutine mysub
use globals
implicit none
x = 1
end subroutine mysub
In this paradigm you specify your "global" variables within the module and use that module everywhere you want access to them.
If you are just using this to declare contants (parameters) you can simplify this to:
module globals
implicit none
integer, parameter :: x=1
end module globals
program main
use globals
implicit none
print *,x
end program main
The older method to accomplish this involved common blocks and includeing files that declared them every procedure that accessed them. If you find a tutorial dealing with the common block method I advise you to ignore them and avoid their use in new code.
Related
I have the following module with an allocatable variable which is defined in the module, allocated in a subroutine, and then also used in a second subroutine called by the first subroutine. In this situation do I have to pass the variable to the second subroutine and declare INTENT(inout)? Or since it's a global variable it doesn't need to be passed as an argument?
MODULE test
IMPLICIT NONE
SAVE
REAL,ALLOCATABLE,DIMENSION(:,:,:) :: total
CONTAINS
!--- 1st subroutine
SUBROUTINE my_subr1(n,m,z)
IMPLICIT NONE
INTEGER,INTENT(in) :: n,m,z
ALLOCATE(total (n,m,z))
total=.9
CALL my_subr2(n)
END SUBROUTINE my_subr1
!-- 2nd subroutine
SUBROUTINE my_subr2(n)
IMPLICIT NONE
INTEGER,INTENT(in) :: n
total(n,:,:)=total(n-1,:,:)
END SUBROUTINE my_subr2
END MODULE test
do I have to pass the variable to the second subroutine and declare INTENT(inout)?
No, you don't. Any variable decalred in the body of the module has the save attribute by default. You must, though, ensure that the second subroutine is only called after the first was executed, or else the program will fail because total would not be initialized yet.
All functions and subroutines declared in the module will have access to total by host association.
By the way, there are some issues you should address in your code, as mentioned by #PierredeBuyl in the comments:
Variables declared in the module body are saved by default; you should remove the SAVE statement.
Procedures declared in a module inherit the IMPLICIT directive from the module scope, there is no need to redeclare it in the subroutine if you won't change it.
You are missing the declaration of the arguments in my_subr1.
I am new to Fortran and trying to understand if the following is possible. My idea to structure the program is to declare the precision and variable types in one module. Then make use of those variables without declaring again the type in other modules or the main program.
module pre
implicit none
INTEGER, PARAMETER :: sp=SELECTED_REAL_KIND(6,37)
INTEGER, PARAMETER :: dp=SELECTED_REAL_KIND(15,307)
INTEGER, PARAMETER :: qp=SELECTED_REAL_KIND(33,4931)
REAL(dp), PARAMETER :: pi = 4.*ATAN(1.)
REAL(dp) :: H
REAL(dp) :: M
REAL(dp) :: KR
end module pre
Now I want to make use of all the variables in another module that contains one or more functions, such as:
module hon
use pre
implicit none
contains
function KE(H,M) result(KR)
KR = 2*PI/H/M
end function KE
end module hon
Then I use gfortran in this order:
gfortran -c mod_pre.f90
gfortran -c mod_hon.f90
Since 'module pre' is part of 'module hon' I compile in order, but gfortran shows an error.
With the code above I understand the variable types and parameters should have been included by USE; But the message I get from gfortran is that none of my variables have IMPLICIT type when I try to compile 'module hon'.
Could somebody clarify the problem or suggest a solution? I would like to avoid having my variables scattered in multiple modules.
Thanks!
In the function statement, the result(kr) says that the function result has name kr. This function result is not the same thing as the module variable kr. In particular, this function result makes inaccessible the module variable.
The function result is specific to the function itself and its properties must be declared within the function subprogram.
Similarly, the dummy arguments of the function, H and M, are distinct from the module variables and need to be declared in the function subprogram.
Beyond that, you perhaps have similar concerns to this other question.
To be clear, it isn't possible to say something like "all function results called kr and all dummy arguments called H or M have these characteristics". Each individual object must be given the properties.
However, although I don't recommend this, this is a situation where literal text inclusion (using a preprocessor or include file) could help you:
function ke(H, M) result (kr)
include 'resdummydecls'
...
end function
where the file has the declarations.
Are there any "general rules" as to when one is preferable to the other?
The context of this question is: I asked a different question regarding host association yesterday (link) and in the comments, I was advised to use host association with caution. The reason being that through host association, it is easy to inadvertently modify variables since the subroutines have unrestricted access to all variables that are declared in the module.
To illustrate this, I will use the following code example:
module mod
implicit none
real :: x
contains
subroutine sub(y)
use other_mod, only: a
real, intent(out) :: y
y = a + x
a = a + 1.
x = x + 1.
end subroutine sub
end module mod
Both aand x are modified in sub. But for x, I need to go through all the code to see this. That a is used in sub (and possibly modified) can be seen easily by looking at the declaration part of sub.
In this sense, it seems preferable to have two kinds of modules:
A module or modules only containing variable declarations (which are then used when needed)
Modules that only contain procedures and possibly parameter declarations but no variable declarations
This gets rid of host association for variables altogether.
But this doesn't seem practical for a number of reasons:
I might have a dozen subroutines using (and modifying) the same variables in one module. Having to use these variables everytime clutters the code, especially if there are a lot of them (say a few hundred).
Seperating the declaration of a variable from where it is actually used seems to make the code less comprehensible:
Either, one creates one giant control file containing all the declarations. This could be quite confusing if the code is large and uses many variables.
Or, one creates a seperate control file for every module (or group of modules, if they depend on the same content). This would make the code itself better comprehensible, since using the variables immediately shows where they are coming from. But it would complicate the structure of the code, creating a vastly more complicated file structure (and accompanying dependency structure).
In the end, all of this boils down to: When is it more sensible to put the declaration of variables in the same module in which they are used (so that they are used by host association) and when is it more sensible to outsource the declaration to a seperate module (so that the variables will be used via use association when they are needed)?
Are there any general guidelines or should this be decided on a case by case basis? And if it is case by case, what are the reasons to go for one over the other?
Fortran provides several ways to create, store, use, and pass data between different "program units": the main program, external procedures, and modules.1 As you know, each program unit can contain internal procedures - which, through host association, have access to any variable or procedure contained within the host. This is often seen as an advantage. As mentioned already by #HighPerformanceMark in his comment, the general guideline for when to use host-association or use-association is:
use host-association when variables are only (or mainly) used by routines declared in the same module, and use use-association when you want to define variables to be used in many modules
From your comments, it sounds like most or all of the host variables in your main program are accessed by each internal procedure (about a dozen or so subroutines). If that's the case, then host-association seems like a very reasonable option, and there's really no need to pass in arguments to each subroutine explicitly. On the other hand, if each subroutine actually uses only a subset of the variables, then it might be reasonable to get more explicit about it.
Like you, I am generally uncomfortable with using variables within a procedure that haven't been declared in an argument list. This is partly because I like how the list of args is self-documenting, and it helps me to reason about the code and how data is manipulated within it. This is even more true when collaborating with other workers, or if I've spent some time away from the code and my memory of it has faded. However, I've discovered there is little reason to avoid host association altogether, as long as you are aware of how it works and have a strategy.
In fact, I tend to use internal procedures and host-association quite often, especially for short functions/subroutines. I find it helpful to loosely think of the host as the "object", its variables as "attributes", and any internal procedures very much like the object's "methods" that do the work. Of course, that's simplifying things, but that's really the point.
For more complex programs I reduce the amount of host-association from the "main" program itself, which then exists primarily to call the various subroutines in the proper order and context. In this case, we can take advantage of use-association and choose to use module entities (such as procedures, variables, types, parameters) directly within the program unit that needs them. We can further restrict access to only those module entities that are needed with only:. This aids readability, the data flow is clearly indicated, and I find that updating the code later is more straightforward. You know, inheritance, encapsulation, and whatnot...but Fortran style. Which is actually pretty good.
Here's an example program structure that works for me and the moderately-sized projects I've worked on in Fortran. I like to keep my widely-used (static) parameters in a separate module (or modules, if grouped according to function). I keep derived types and type-bound procedures in another separate module(s). If it's useful, I make certain module entities private, so that they are not accessible from other program units. And I guess that's it.
module params
implicit none
public !! All items public/accessible by default.
integer, parameter :: dp = kind(0.d0)
integer, parameter :: nrows = 3
real(dp), parameter :: one=1.0_dp, two=2.0_dp
...
end module params
module types
use params, only: dp, nrows
implicit none
public !! Public by default.
private :: dim2
...
integer, parameter :: dim2 = 3
...
type :: A
integer :: id
real(dp), dimension(nrows,dim2) :: data
contains
procedure, pass :: init
end type A
...
contains
subroutine init(self, ...)
...
end subroutine init
...
end module types
module utils
implicit none
private !! Private by default.
public :: workSub1, workSub2, subErr
...
integer,save :: count=0 !! Accessible only to entities in this module.
...
contains
subroutine workSub1(...)
...
end subroutine workSub1
subroutine workSub2(...)
...
end subroutine workSub2
subroutine subErr(...)
...
end subroutine subErr
end module utils
program main
!! An example program structure.
use params, only: dp
implicit none
real(dp) :: xvar, yvar, zvar
integer :: n, i
logical :: rc
call execute_work_subroutines()
contains !! Internal procs inherit all vars declared or USEd.
subroutine execute_work_subroutines()
use types, only: A
type(A) :: DataSet
!! begin
call DataSet%init(i)
do i = 1,n
call workSub1(xvar,yvar,zvar,A,i,rc)
if (rc) call subErr(rc)
call workSub2(A,rc)
if (rc) call subErr(rc)
enddo
end subroutine execute_work_subroutines
end program main
1There are also submodules, but I am not familiar with them and don't want to give misleading info. They do seem useful for logically separating large modules.
I am trying to add access restrictions to some of the variables (using private attribute) in a module but I need to use those variables in subsequent invocations of routines within that module:
module MyMod
private
integer,allocatable :: A(:)
public :: init,calc
contains
subroutine init()
! allocating and initializing A
end subroutine init
subroutine calc()
! Using A
end subroutine
end module
Questions:
Is this true that the private variable will not be in the scope of the program which uses this module.
If the answer to 1 is yes, then I would think that I can use save attribute for this variable. Please correct me if I am wrong?
Is this the proper way to perform this task?
Yes, if you put a private statement into your module without any further specification, you set the default accessibility to private.
For the first question, the Fortran 2008 Standard (Cl. 4.5.2.2 §3) states that:
If a type definition is private, then the type name, and thus the structure constructor (4.5.10) for the type, are accessible only within the module containing the definition, and within its descendants.
So A will not be accessible from anywhere outside the module or submodule (descendant).
For the second question, yes - you can use save here. (This is not related to the accessibility attribute). In fact, starting with Fortran 2008, this is implied for module variables, see for the Fortran 2008 Standard (Cl. 5.3.16 §4) [thanks #francescalus]:
A variable, common block, or procedure pointer declared in the scoping unit of a main program, module, or submodule implicitly has the SAVE attribute, which may be confirmed by explicit specification [...]
If I understood your third question correctly, it is related to the initialization. You could realize this with a function/subroutine to which you pass an array for initialization:
module MyMod
! ...
contains
! ...
subroutine init( A_in )
implicit none
integer, intent(in) :: A_in(:)
! allocating and initializing A
allocate( A(size(A_in)) )
A = A_in
end subroutine
end module
Inside init() you create a copy of A_in which is only accessible within the module. As long as calc() is part of the module (or a submodule thereof), it has full access to A.
To add to the answer by Alexander Vogt an implication of the save attribute.
This attribute gives precisely the effect you seem to be after (from F2008 5.3.16):
The SAVE attribute specifies that a local variable of a program unit or subprogram retains its association status, allocation status, definition status, and value after execution of a RETURN or END statement unless [something not applicable here]
In your example, A is a local variable of the module (and so a program unit) MyMod.
This means that, after the call to init which, presumably, allocates A and sets values that status is retained after the subroutine returns. Those values are then available come the call to calc. Both init and calc, of course, refer to the same A through host association.
You mention Fortran 90, so there is a subtle change (again as mentioned in that other answer). Before Fortran 2008 module variables would require the save attribute explicitly giving in some circumstances for this effect to come about. There's no harm in giving the save attribute explicitly if you aren't sure how your compiler treats the code (and some would say it's good practice, anyway).
This is another way of accomplishing what you want to do while avoiding the 'save'.
module MyMod
private
public :: myType, init
type myType
private
integer, allocatable :: A(:)
end type myType
contains
subroutine init(obj, n)
type(myType), intent(inout) :: obj
integer, intent(in) :: n
allocate(obj%A(n), source=-9999999)
end subroutine init
end module MyMod
program test
use MyMod, only: myType, init
type(myType) :: m ! m is an opaque object
call init(m, 10)
end program test
In this example, m is an opaque object - I can create the object, pass it around, but not access its contents (the array A in this case). This way, I am hiding my data. As long as my object m is in scope, I can operate on the data hidden in the object through routines contained in the module myMod.
If you have access to a modern compiler that supports Fortran 2003, you can rewrite the module as
module MyMod
private
public :: myType
type myType
private
integer, allocatable :: A(:)
contains
procedure, public :: init
end type myType
contains
subroutine init(obj, n)
class(myType), intent(inout) :: obj
integer, intent(in) :: n
allocate(obj%A(n), source=-9999999)
end subroutine init
end module MyMod
program test
use MyMod, only: myType
type(myType) :: m ! m is an opaque object
call m%init(10)
end program test
Suppose I have a module which defines some basic constants such as
integer, parameter :: i8 = selected_int_kind(8)
If I include this in my main program and I also include a module which does some other things (call this module functions) but functions also uses constants, then am I essentially including constants twice in my main program?
If so, is this bad? Can it be dangerous at all to include a module too many times in a program?
No, it is fine to do this. All you are doing with the use statement is providing access to the variables and functions defined in your module via use association. It is not like declaring variables each time they are use'd (they are in fact redeclared however).
The only thing to be wary of are circular dependencies, where module A uses module B and module B uses module A. This is not allowed.
Edit: From Metcalf et al. Fortran 95/2003 explained, pg. 72:
A module may contain use statements that access other modules. It must not access itself directly or indirectly through a chain of use statements, for example a accessing b and b accessing a.
Whilst this quote doesn't directly answer your question, it reiterates that really the only thing you can't do is have a circular dependency. So the following is perfectly valid:
module one_def
implicit none
integer, parameter :: one=1
end module one_def
module two_def
use one_def, only : one
implicit none
integer, parameter :: two=one+one
end module two_def
program test
use one_def, only : one
use two_def, only : two
implicit none
print*, two == one+one ! This prints .True.
end program