During the last few years, I have been creating several modules with subroutines that I then use for different projects. I am having problems when I define parameter variables in one of those project-specific files that conflict with a variable name defined within those modules. Is it possible to make those names subroutine-private or module-private?
Here is an example. Suppose I have the following module:
module mymod
implicit none
contains
subroutine test1(x)
real, intent(in) :: x(:)
print *, x**2.0
end subroutine test1
end module mymod
This module is then called by the main program
program main
use mymod
implicit none
real :: y
real,dimension(2,1),parameter :: x = [1.0,2.0]
y = 3.0
call test1(y)
end program main
In this case, given that x in the main program is defined as a parameter with different dimensions to the x in subroutine test1, there will be problems when compiling (shape matching rules violated). Is there any way of making x in module mymod private within the module?
I know an option could be to use "non-common" variable names in my modules or have a list of forbidden names, but that seems complicated at this point (requires editing too many files and lose consistency of notation with books/papers where these procedures are outlined), and would make collaboration with colleagues more difficult.
Two different questions in one:
Why is the example program failing to compile:
This has nothing to do with public or private, or x being defined in the program itself.
It has everything to do with the fact that in the module, x as a parameter is defined as a 1-d array, and in the main program, y is a scalar.
Try it, remove the declaration of x in the main program and it will still fail.
(In fact, the declaration doesn't work like that anyway, you declare x as a 2-d array (shape 2, 1), but then give it a 1-d array. You'd have to do something like:
real, dimension(2, 1), parameter x = reshape([1.0, 2.0], [2, 1])
But to get rid of the error you describe, you either need to change the subroutine interface by removing the (:) behind the real, intent(in) :: x, or change the call to call test1([y]).
What can you do when 2 modules import different variables of the same name:
It would be different if you were to say have this:
module modA
implicit none
real, parameter :: x = 2.0
contains
subroutine subA(k)
real, intent(in) :: k
print *, k*x
end subroutine subA
end module modA
module modB
implicit none
real :: x(3)
end module modB
program progtest
use modA
use modB
implicit none
call subA(x(1))
end program progtest
In this example, it would try to import the variable x from both modules.
Ways to avoid it:
Make one x private:
implicit none
real, parameter, private :: x = 2.0
or
real, parameter :: x = 2.0
private :: x
or
implicit none
private
real, parameter :: x = 2.0
public :: subA
Only import the parts that you need:
program progtest
use modA, only: subA
use modB
implicit none
...
Rename one or both of the x:
use modA
use modB, only: xB => x
...
call subA(xB(1))
Related
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!
Hello I am trying to learn Object Oriented Programming using Fortran (all my codes are written in Fortran 90), I partially know C++ but I want to carry on using Fortran.
In Fortran you make classes employing modules. I am facing compiling errors when writing the integer, parameter :: dp = selected_real_kind(15,307) statement. Here goes my academic code. Its a short code that uses Abstract classes
module class_Rectangle
implicit none
integer, parameter :: dp = selected_real_kind(15,307)
type Rectangle
real(dp) :: a,b
end type Rectangle
contains
subroutine area_rectangle(area,info)
implicit none
real(dp), intent(out) :: area
type(Rectangle), intent(in) :: info
area = info%a * info%b
end subroutine area_rectangle
end module class_Rectangle
program Main
use class_Rectangle
use class_Circle
implicit none
integer, parameter :: dp = selected_real_kind(15,307)
interface compute_area
module procedure area_rectangle, area_circle
end interface compute_area
type(Rectangle) :: geoA
type(Circle) :: geoB
real(dp) :: area
geoA = Rectangle(2.0d0,4.0d0)
call area_rectangle(area,geoA)
write(*,*) 'Rectangle area:', area
geoB = Circle(1.0d0)
call area_circle(area,geoB)
write(*,*) 'Circle area:',area
end program Main
The message that the compiler returns me is the following:
integer, parameter :: dp = selected_real_kind(15,307)
1
Error: Name 'dp' at (1) is an ambiguous reference to 'dp' from module 'class_rectangle'
Main.f90:81.13:
real(dp) :: area
1
Error: Name 'dp' at (1) is an ambiguous reference to 'dp' from module 'class_rectangle'
Main.f90:84.30:
Any hint or advice is welcome.
Always try to use USE statement with ONLY. If you do so, you will not encounter the ambiguity error you get. In addition, you will know exactly what is being used in your code from each module, just by a quick look at the top lines of your code. Therefore, your main program header could look like this:
program Main
use class_Rectangle, only: Rectangle, area_rectangle
use class_Circle, only: Circle, area_circle
implicit none
integer, parameter :: dp = selected_real_kind(15,307)
interface compute_area
module procedure area_rectangle, area_circle
end interface
type(Rectangle) :: geoA
type(Circle) :: geoB
real(dp) :: area
geoA = Rectangle(2.0d0,4.0d0)
call area_rectangle(area,geoA)
write(*,*) 'Rectangle area:', area
geoB = Circle(1.0d0)
call area_circle(area,geoB)
write(*,*) 'Circle area:',area
end program Main
For a good tutorial on OOP programming in Fortran with some good examples, see the book "Modern Fortran Explained" by Metcalf et al.
Depending on your compiler, you should get pretty helpful messages
module a
end module a
program b
implicit none
use a
end program b
And compile:
$ gfortran mod_test.F90
mod_test.F90:6:9:
implicit none
2
use a
1
Error: USE statement at (1) cannot follow IMPLICIT NONE statement at (2)
Just omit: integer, parameter :: dp = selected_real_kind(15,307)
in the main program! By USEing class_Rectangle the main program it
shares this variable with the module (except you declare it private,
which is not what you want here I guess).
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
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.
I have a question regarding assigning Fortran90 derived types and pointers at runtime. I want to pass a derived variable type to a subroutine after the code reads an input file. So depending on the input I pass the appropriate data type. Let me explain:
I have two modules:
Module A_mod and Module B_mod. Each has it's own unique data type and subroutines. For example:
Module A_mod
type A
real :: x, y
end type
contains
subroutine FunA(me)
type (A), intent(in) :: me
<do stuff>
end subroutine
End module A_mod
Module B_mod is a mirror of the above with B replacing A (also the data type B has x and y defined as integers).
I also have a third module that has this interface:
interface fun
modular procedure funA, funB
end interface
Here is my problem. The user via an input file determines which module subroutine to use. How can I make a generic pointer that gets associated at runtime? Or something similar that doesn't require pointers.
For example:
type (?) :: pt
Call fun(pt)
where after the program reads the input file it picks the correct data type to be sent to the interfaced subroutine "fun". So the type is unknown until runtime.
If Fortran would let me declare a variable in my execution portion of code it would look like this for example
IF(input.EQ."A") THEN
type(A) :: pt
ELSE
type(B) :: pt
END IF
CALL fun(pt)
Any suggestion would be appreciated !!
Thank you
This is difficult to do cleanly in Fortran 90. It is straight forward in Fortran 2003.
Resolution of the procedure to call when the generic reference fun is encountered (in CALL fun(pt)) is done at compile time, based on the declared type of pt.
If you are limited to Fortran 90, then effectively you will need to maintain a flag of some sort that indicates at runtime which particular derived type you want to work with, have a named object for each of type A and type B, and everytime you want to reference fun have an IF construct that selects the correctly named argument.
(If the size of the objects is significant you can arrange for them to have common storage.)
Something like:
TYPE(A) :: pt_A
TYPE(B) :: pt_B
...
IF (input .EQ. 'A') THEN
CALL fun(pt_A)
ELSE
CALL fun(pt_B)
END IF
In F2003, you would define a common parent type, that had a specific binding named fun. pt would then be a polymorphic allocatable object, allocated based on input to either type A or type B as appropriate.
TYPE :: Parent
CONTAINS
PROCEDURE(parent_Fun), DEFERRED :: Fun
END TYPE Parent
ABSTRACT INTERFACE
SUBROUTINE parent_Fun(obj)
IMPORT :: Parent
IMPLICIT NONE
CLASS(Parent), INTENT(IN) :: obj
END SUBROUTINE parent_Fun
END INTERFACE
TYPE, EXTENDS(Parent) :: A
REAL :: x, y
CONTAINS
PROCEDURE :: A => A_Fun
END TYPE A
TYPE, EXTENDS(Parent) :: B
INTEGER :: x, y
CONTAINS
PROCEDURE :: B => B_Fun
END TYPE B
CLASS(Parent), ALLOCATABLE :: pt
...
IF (input .EQ. 'A') THEN
ALLOCATE(A:: pt)
ELSE
ALLOCATE(B:: pt)
END IF
...
CALL pt%Fun()