Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Fortran 90, PUBLIC subroutines, and "local" variables within subroutines 3

Status
Not open for further replies.

billgray1234

Programmer
Mar 14, 2011
39
i'm using Fortran 90. i use lots of subroutines (each of which are given the PUBLIC attribute). in most of these subroutines i'm using ALLOCATABLE matrices -- which are "locally within" each subroutine.

for ease of programming, i've thought of a "universal" way of naming INTEGER variables relating to the dimensions of these matrices. i'm currently using the "same naming of INTEGER variables" in all such subroutines. for example, in 2 different subroutines, i might have :-

.......SUBROUTINE SUB_1

.......INTEGER :: IB1 , JB1
.......INTEGER :: IB2
.......INTEGER :: IB3 , JB3
.......REAL ,ALLOCATABLE ,DIMENSION :),:) :: MAT_1
.......REAL ,ALLOCATABLE ,DIMENSION :)) :: MAT_2
.......REAL ,ALLOCATABLE ,DIMENSION :),:) :: MAT_3

.......IB1 = ??
.......JB1 = ??
.......IB2 = ??
.......IB3 = ??
.......JB3 = ??
.......ALLOCATE ( MAT_1 ( IB1 , JB1 ) )
.......ALLOCATE ( MAT_2 ( IB2 ) )
.......ALLOCATE ( MAT_3 ( IB3 , JB3 ) )

.......END SUBROUTINE SUB_1

---------------------------

.......SUBROUTINE SUB_2

.......INTEGER :: IB1 , JB1
.......INTEGER :: IB2
.......INTEGER :: IB3 , JB3
.......REAL ,ALLOCATABLE ,DIMENSION :),:) :: MAT_10
.......REAL ,ALLOCATABLE ,DIMENSION :)) :: MAT_11
.......REAL ,ALLOCATABLE ,DIMENSION :),:) :: MAT_12

.......IB1 = ??
.......JB1 = ??
.......IB2 = ??
.......IB3 = ??
.......JB3 = ??
.......ALLOCATE ( MAT_10 ( IB1 , JB1 ) )
.......ALLOCATE ( MAT_11 ( IB2 ) )
.......ALLOCATE ( MAT_12 ( IB3 , JB3 ) )

.......END SUBROUTINE SUB_2
---------------------------

note that the emphasis is on the INTEGER variables IB1, JB1, IB2, etc (and not the matrices).

my question is :-
if :-

a) 2 or more of these subroutines are called by the same calling code (SUBROUTINE CALL_SUBS, say), and

b) as noted above, the subroutines being called (i.e. SUB_1 and SUB_2) are declared as being PUBLIC. to my understanding, this means that each of the subroutines being called (and all variables that are "locally within" each subroutine being called) are "available" to the code that calls each subroutine. please correct me if i'm wrong here.

then is it valid to use the above universal "same names for all INTEGER variables" system ? because, does this mean that these "same names for all INTEGER variables" would be "available" to the code that calls each subroutine (and, therefore, would effectively be declared more than once, in the calling code).

my only thought is :- if it is NOT valid (for the reason i've stated), then can i instead make it valid by declaring the "local" INTEGER variables as being PRIVATE ? for example, can i change :-

.......INTEGER :: IB1 , JB1
.......INTEGER :: IB2
.......INTEGER :: IB3 , JB3

to

.......INTEGER ,PRIVATE :: IB1 , JB1
.......INTEGER ,PRIVATE :: IB2
.......INTEGER ,PRIVATE :: IB3 , JB3
 
PRIVATE attribute regulates visibility of names declared in MODULE scope. It does not relate to the life span of declared variables.

All your allocatable arrays (and integer variables) are locals in its own subroutines. These names are not directly accessible out of subroutine scope(s). You can't declare these names as PUBLIC or PRIVATE in subroutine bodies.

Moreover: if you don't deallocate array variables (w/o SAVE attribute) before return, you will get classical memory leaks.
 
If you want to define some data once and for all to be used throughout your prog you can use modules. Your code would be something like

Code:
module general_data          ! define module
    integer :: IB1, JB1
    integer :: IB2 = 10      ! you can initialise your variables in the module as well by such a statement.
    integer :: IB3, JB3
end module

subroutine sub_1
    use general_data         ! make the module's data available to your subroutine
    ...
    IB1 = ??                 ! set the data once and for all in the subroutine that is called first
    IB2 = ??
    ...
end subroutine

subroutine sub_2
    use general_data
    ...
    allocate (mat_1 (IB1, JB1), stat = irslt     ! the data are available whereever you use the module

    deallocate (mat_1)
end subroutine

Please note, that (standard-) Fortran90/95 - I do not know about later versions - does not have the PUBLIC variables like in C. In Fortran all variables are local to the program unit they are declared in, unless you explicitly share them by putting them into modules and make them available to other program units that need them.

In Fortran you use PUBLIC and PRIVATE attributes in modules only. By default once you make a module available to a routine, this routine may access all the variables within the module. But Fortran allows to put procedures in modules as well. If such a procedure is to use a variable you may declare it in the module as well, but you can prevent the outside routine from using this variable by declaring it PRIVATE. This way you can assure that the procedure in the module does not modify data in the outside routine and vice versa.

Allocatable arrays:
I do not know if this is dpending on what compiler you use, but mine (COMPAQ) deallocates arrays once execution of the routine wherin they got allocated is terminated by RETURN (or END) unless you specified the SAVE attribute in your data declaration. But I am with ArkM that it is good programming practice to deallocate your arrays manually, just to know where you are.

Norbert

The optimist believes we live in the best of all possible worlds - the pessimist fears this might be true.
 
Remark:
As far as I know, automatic deallocations some kinds of local allocatable arrays was introduced in Fortran 95 and later...
 
thanks for your replies.


first, i'll just go back a step, and explain one detail i left out of my original post. i said my subroutines have the attribute PUBLIC. by this i mean:- a) each subroutine is stored in it's own module, b) each module contains one (and only one) subroutine, c) in each module, the contained subroutine is declared as being PUBLIC, and everything else is PRIVATE. for example :-

MODULE SOME_MODULE
......USE MODULE_A
......USE MODULE_B

......PRIVATE
......PUBLIC :: SUBROUTINE SUB_1

......CONTAINS
........SUBROUTINE SUB_1

........END SUBROUTINE SUB_1
END MODULE SOME_MODULE




second, my confusion (regarding the local variables IB1, IB2, etc) comes from my understanding of the definition of the word PUBLIC. in my example above, PUBLIC means that the subroutine is PUBLIC (i.e. accessible outside of the module). but, does it also mean that the local variables within the subroutine (i.e. IB1, IB2, etc) are also PUBLIC (i.e. accessible outside of the module) ? or is it only the subroutine that is PUBLIC ?



gummibaer :- about the your suggestion to store the variables IB1 / IB2 / etc in a global module. yes, that is also an option. but, for the present program that i'm writing, i'd prefer to use local variables (in each subroutine) -- mainly so that i can keep track of which variables i'm using (and where i'm using them). but, thanks anyway for your suggestion. actually, in the same program i'm writing, i have actually used your approach with some other "global" variables -- in order to avoid having to declare them over and over again in various subroutines that "use" them. i've done just as you suggested -- i've stored them in a single module, and i "USE" that module.


finally, about deallocation of allocatable variables :-

1) i've previously been advised that all such variables that have been allocated are automatically deallocated when control is returned to the calling code.

2) like you said, whether or not to manually deallocate allocated variables is personal choice -- there is no "right" or "wrong" way. but, i personally prefer not to do manual deallocation, for the following reason :- if i have a subroutine that contains literally 100's of allocated arrays, then i would have to manually deallocate literally all such arrays. if i happen to "miss" deallocating a few, then, despite the code appearing to be "incomplete", the code WILL still work fine -- coz, as said above, all allocated variables that have been allocated are automatically deallocated when control is returned to the calling code
 
The problem is that Fortran 90 Standard did not define clearly if locally declared allocatable arrays are deallocated automatically when they go out of scope. Only Fortran 95 Standard guarantees this feature explicitly.
 
billgray,

First, things may be a little different if you use gfortran 90/95, for this may include features of later fortran standards that I do not know anything about. So things may be a little different in your environment if you use this compiler.

What I know is, that the default of all items in a module is PUBLIC so if you do not specify anything, then the item can be accessed from the routine that uses this module. Second, a routine, that uses a module would access any variable directly not by way of the procedure that might be included in the module. Consequence:

- any variable you do not declare as PRIVATE in your module is public and may be accessed by your routine
- any variable you declare PRIVATE cannot be accessed by outward routines, only by procedures within the module - which will be public, if not declared otherwise.

Hope this makes it clear.

And with the deallocation - well, you are right, there is no right or wrong, it is just a question what suits you most. For me, I am doing a windows application. Any procedure that handles a window is frequently left by a return and recalled later. So most of my allocatables have the SAVE-attribute or are decalared in a module. So I developed the habit of deallocating all my allocatables. Ju checking if any allocate - statement has a deallocate - statement to prevent memory leaks. You could almost put it to a philosophy of life: I like to have redundancies - but I do not rely on them to be present all the time.

Norbert



The optimist believes we live in the best of all possible worlds - the pessimist fears this might be true.
 
billgray1234 said:
second, my confusion (regarding the local variables IB1, IB2, etc) comes from my understanding of the definition of the word PUBLIC. in my example above, PUBLIC means that the subroutine is PUBLIC (i.e. accessible outside of the module). but, does it also mean that the local variables within the subroutine (i.e. IB1, IB2, etc) are also PUBLIC (i.e. accessible outside of the module) ? or is it only the subroutine that is PUBLIC ?

No !

François Jacq
 
Norbert (and others) :- i'm not using gfortran. i'm using intel visual fortran composer xe.

FJacq :- by "no" do you mean that only a subroutine is made PUBLIC, and it's local variables are not ALSO made PUBLIC ?

Norbert (and others) :- about the automatic deallocation of allocatable arrays. as i mentioned, one reason i've chosen (so far) to not manually deallocate arrays is ensuring my program "looks" complete. but, as you mentioned, one good reason to manually deallocate arrays is to avoid possible memory leaks. so yeah, i might try manual deallocation, but by using your suggestion of first checking an array's allocation status -- such that

...IF ( ALLOCATED ( A ) ) DEALLOCATE ( A )

so, thanks for that advice. my main concern is doing this when there are alternate RETURN statements -- but, even with these, i'm sure manual deallocation is manageable.
 
a quick note to all of you that replied.

sorry if i haven't given you all of you a star (as a thanks). i did try to give you all a star, but, i don't think it worked properly, so maybe it only worked for a few of you. but yeah -- i did try to give everyone a star.
 
FJacq :- by "no" do you mean that only a subroutine is made PUBLIC, and it's local variables are not ALSO made PUBLIC ?

Only the subroutine is made PUBLIC, never its local variables.


François Jacq
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top