Fortran - Module Subroutine Argument Intent Confusion- INOUT vs OUT - module

Lets say there is a vector:
REAL(KIND=dp), DIMENSION(maxn) :: rho
which is allocated values in an initial subroutine (along with dp and maxn) and is called from the main program.
The main program then calls a module which contains a (different) subroutine to evolve rho. The subroutine argument for rho is defined as:
SUBROUTINE sum_density(a, b, c, ....., rho)
In this subroutine rho is declared as:
REAL(KIND=dp), DIMENSION(maxn), INTENT(OUT) :: rho
Yet the code contains the following line, prior to any values being associated with rho:
foo1= foo2*foo3(i)/rho(i)
I would have thought that the module subroutine would not have had access to the rho defined in the main program. I expected the compiler to complain and require the intent to be changed to (INOUT) or say something like rho is undefined. Even if I do change it to (INOUT) there is no difference in the results. The module subroutine must be accessing the value of rho in the main program and using it even though the intent is declared as OUT.
My question is - In this scenario what is the difference between using in INTENT(OUT) and the INTENT(INOUT)?

With the INTENT(OUT) the program is not standard conforming, because it accesses the array which has an undefined value.
However, the software implementation is likely to work, because of the way explicit shape arrays are usually implemented - by passing the address of the array. If the array you passed was non-contiguous, let's say
rho(::2)
the compiler is likely to create a copy, which is passed and you are likely to encounter a problem, because the array may contain garbage with intent(out).
Regarding the warning, they are not obligatory but compilers do warn about this if you use flags such as -warn or -Wall.
For intent(in) the difference comes out when you try to modify rho. If you try that the compiler has to issue an error.
About the scope:
It is not really correct to talk about the scope here, the original rho is definitely not in the scope of the subroutine, only the dummy argument is. The re-use of the same name is perhaps confusing. Imagine they are actually called rho1 in the program and rho2 in the subroutine. Then it is clear that rho1 is not in the scope of the subroutine, but rho2 is.
Now, rho2 is not guaranteed to have the same value as rho1 at the start of the subroutine with intent(out), but it is guaranteed to have it with intent(inout). The reason is that the argument passing may be implemented using copy-in and copy-out and the copy-in can be omitted for intent(out).
Consider this code:
module m
contains
subroutine sub(a2)
real, intent(out) :: a2(4)
print *,a2
a2 = 2
end subroutine
end
use m
real :: a1(8)
a1 = 1
call sub(a1(::2))
end
With some compiler it prints 4 times one, as one might expect, but with others or with some compiler parameters it prints garbage:
sunf90 intent2.f90
./a.out
5.879759E-39 0.0E+0 0.0E+0 0.0E+0

Related

Polymorphic assignment with subroutine possibly causing data corruption in Fortran [duplicate]

I am trying to implement a polynomial class with fortran 2003, with overloaded arithmetic operations and assignments. The derived type maintains allocatable list of term definitions and coefficients, like this
type polynomial
private
type(monomial),dimension(:),allocatable :: term
double precision,dimension(:),allocatable :: coef
integer :: nterms=0
contains
...
end type polynomial
interface assignment(=)
module procedure :: polynomial_assignment
end interface
...
contains
elemental subroutine polyn_assignment(lhs,rhs)
implicit none
type(polynomial),intent(???) :: lhs
type(polynomial),intent(in) :: rhs
...
I had to make it elemental because this is intended to be used as matrices of polynomials. That does work, for the most cases at least. However, I somehow got myself into concerns about self-assignment here. One can simply check the pointers to see if things are the same in C++, but it doesn't seem to be an option in Fortran. However the compiler do detect the self-assignment and gave me a warning. (gfortran 4.9.0)
When I have intent(out) for lhs, the allocatable entries for both lhs and rhs appeared to be deallocated on entry to the subroutine, which made sense since they were both p, and an intent(out) argument would first be finalized.
Then I tried to avoid the deallocation with an intent(inout), and check self-assignment by modifying one field in the lhs output
elemental subroutine polyn_assignment(lhs,rhs)
implicit none
type(polynomial),intent(inout) :: lhs
type(polynomial),intent(in) :: rhs
lhs%nterms=rhs%nterms-5
if(lhs%nterms==rhs%nterms)then
lhs%nterms=rhs%nterms+5
return
end if
lhs%nterms=rhs%nterms
Well, now this is what surprised me. When i do
p=p
It didn't make the test and proceeded, giving me a polynomial with 0 terms but no memory violations. Confused, I printed lhs%nterms and rhs%nterms inside the assignment, only to find that they are different!
What is even more confusing is that when I did the same thing with
call polyn_assignment(p,p)
It works perfectly and detected that both arguments are the same. I am puzzled how an interface of a subroutine can run differently from the subroutine itself.
Is there something special about assignment in Fortran 2003 that I've missed?
(First time to ask a question here. Please correct me if i didn't do it right.)
If you have a statement a = b that invokes defined assignment via a subroutine sub, the assignment statement is equivalent to call sub(a, (b)). Note the parentheses - the right hand side argument is the result of evaluating a parenthesised expression and is therefore not conceptually the same object as b. See F2008 12.4.3.4.3 for details.
Consequently, a = a is equivalent to call sub(a, (a)). The two arguments are not aliased. It is different from call sub(a,a), the latter may (depending on the specifics of the internals of sub, including dummy argument attributes) break Fortran's argument aliasing rules (e.g. in your example, a statement such as call polyn_subroutine(a,a) is illegal).

Passing an object from one module into a subroutine of another module

I have two module files mod1.f95 and mod2.f95. Mod1 has mathematical functions such as rk4 and interpolation methods, and I have been trying to keep it general so that I can reuse the module for other projects. Mod2 has a class structure defined within it, Obj1, and is meant to be specific to this project. The issue is that a subroutine defined in mod1 now needs an object definition passed something along the lines as
subroutine driver(x1, x2, func, this)
real(kind=8) :: x1, x2
external :: func, this ! this is the Object
! ...
end subroutine driver
The error I get from this is
Type mismatch in argument 'this' at (1); passed TYPE(Obj1) to UNKOWN
I had a feeling this would happen, since the external keyword is meant for functions and subroutines, but I would like to pass an Object to the subroutine without having to hard code my mod2 into mod1 (i.e. using use mod2)
I tired this change
subroutine driver(x1, x2, func, this)
real(kind=8) :: x1, x2
class(Object) :: this
external :: func
! ...
end subroutine driver
but got Derived type 'object' at (1) is being used before it is defined.
I also tried type(Object) :: this with the same error produced.
To reiterate, I would like to see if there is a way to initialize an Object in a "general" sense so that other modules and files I create can just be linked this mod1 without having to change the code inside. Any advice would be appreciated!

Structure of a fortran program with modules and subroutines

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).
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

Private, Save attributes for variables in Fortran 90 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

Fortran tips in large modules

I have a module that consists of many small subroutines and one main subroutine, which is the only one that is public. The rest of the subroutines are private and called by the main subroutine or within them. The main subroutine has to take all the necessary arguments to perform its work, but often when it delivers a task to a private subroutine, it has to pass again some of the arguments. I would like to avoid this when dealing with arrays. With scalar numbers I can simply define a module wide variable and assign it the corresponding value in the main subroutine:
module test
integer, private :: m, n
private :: foo
public :: main
contains
subroutine main(matrixA, m0, n0)
integer, intent(in) :: m0, n0
real, intent(inout) :: matrixA(m0,n0)
!assign values to module variables m & n
m = m0
n = n0
...
!no need to pass m0 & n0
call foo(matrixA)
end subroutine
subroutine foo(matrixA)
real, intent(inout) :: matrixA(m,n)
...
end subroutine
end module
I would like to also not need to pass matrixA at all. What is the best way to do this? By best, I mean giving the best performance.
I can't comment on the "best" way, but there are some things to say. And now the question has been edited to point "best" in the direction of performance I'll add something else.
The question appears to be made under the premise that arrays cannot be module variables. They can be, even allocatable/pointer (deferred-shape) ones.
In the examples that follow I'll make the assumption that the array dummy argument in main will be assumed-shape. This is just to make things simpler in the form; changing to explicit-shape is a simple extension.
First, just like we set m and n in the question, we can set a module array variable.
module test
private ! Have this as default
public main ! But we do want a way in
integer m, n
real, allocatable :: matrixA(:,:)
contains
! In this subroutine we're making an assumption that the person asking isn't
! wholly correct in not wanting to assume shape. But we can change that if
! required. It's just a more natural thing if one can.
subroutine main(matrix) ! Note, not passing m, n
real, intent(inout) :: matrix(:,:) ! It's assumed shape
m = SIZE(matrix,1)
n = SIZE(matrix,2)
matrixA = matrix ! Copy in to the module's matrixA
call foo()
! .... etc.
matrix = matrixA ! Copy back out to the dummy
end subroutine main
subroutine foo
! Here we have access to the module's matrixA
! And we do our stuff
end subroutine foo
end module test
Note the use of the assumed-shape dummy argument and the discussion above. To avoid copying in this example, one could think about whether using a pointer is a suitable thing.
With the copy, that's not going to be good performance (assuming the array is biiig). So:
module test
implicit none
private
integer m, n ! If we want these we'll have to set them somehow
real, allocatable, public :: matrixA(:,:)
public main
contains
subroutine main()
! Stuff with matrixA host-associated
end subroutine main
end module test
program hello
use test, only : matrixA, main
implicit none
matrixA = ... ! Set this: it's matrixA from the module
call main
end program hello
As we care about "performance" rather than "encapsulation" that seems like a reasonable thing. However, having encapsulation, performance and reduced-argument passing, we could consider, rather than using a module variable for matrixA, having the work subroutines internal to main.
module test
contains
subroutine main(matrixA)
real, intent(inout) :: matrixA(:,:)
call foo
contains
subroutine foo
! Here we have access to matrixA under host association
end subroutine foo
end subroutine main
end module test
In many circumstances I prefer this last, but wouldn't say it's best, or even preferred under all circumstances. Note, in particular, that if foo already has an internal subprogram we'll start to wonder about life.
I feel the first is rather extreme just to avoid passing as an argument.