How to use allocatable arrays in Fortran subroutines? - fortran

Let me just preface this by saying that I am very new to Fortran but familiar with Python. My research project however requires me to use some pre-written Fortran code, which at this moment wont compile on my pc. I am trying to understand why.
The actual code I am trying to compile is very long and probably not very illuminating, but I think I have managed to come up with a minimal example of where I think the issue is. Let's say I have a very simple module and subroutine as follows,
module arraycheck
implicit none
real*8, allocatable, dimension(:) :: x
contains
subroutine fillx
real*8, allocatable, dimension(:) :: x
allocate(x(5))
x(1) = 1
x(2) = 2
x(3) = 3
x(4) = 4
x(5) = 5
print*, x
end subroutine fillx
end module arraycheck
which I expect to simply create an array x, which when the subroutine fillx is called fills the array with the integers 1 to 5. My actual source contains something conceptually similar to this. Now I also have a main program as follows,
program main
use arraycheck
print*, x
call fillx
print*,x
end
My idea here would be that on the first print statement the variable x is still unallocated, so print returns nothing, and then on the second print statement x has been filled, so it should return the filled array.
However on both print statements nothing is returned. Now in my original source code something similar happens, which causes runtime to throw an error that an unallocated array was passed somewhere as an actual argument, which should have been allocated. It seems like the exact same thing happens as in my small example here.
So my question is, is the behaviour that I observe in my example here expected? And if it is, how can I alter the code to make it work in the way that I would want it to? If I know this I might better understand why the actual source doesn't work.
Just in case it is relevant, I am using gfortran on ubuntu.
Thanks!

You have too different xs. They do not have anything in common. One a module array and one array local to the subroutine. When you allocate the local array in the subroutine, it does not do anything to the other array in the module.
Also, you cannot print array that is not allocated. That is not standard conforming (undefined behaviour). Anything can happen. You should definitely enable all compiler checks when diagnosing problems. The compiler should complain about your code with those checks.
Remove the local array declaration and avoid referencing unallocated variables. Module procedures have access to module variables through host association.
module arraycheck
implicit none
real*8, allocatable, dimension(:) :: x
contains
subroutine fillx
allocate(x(5))
x(1) = 1
x(2) = 2
x(3) = 3
x(4) = 4
x(5) = 5
print*, x
end subroutine fillx
end module arraycheck
program main
use arraycheck
call fillx
print*,x
end
Also, real*8 is not standard Fortran, it is a non-standard extension. Fortran 90 and later uses the kind system instead.

Here are some other things which might be helpful - shown in UPPERCASE.
module arraycheck
USE ISO_C_BINDING, ONLY : C_Int32_t, C_DOUBLE
implicit none
PRIVATE
real(KIND=C_DOUBLE), allocatable, dimension(:), PUBLIC :: x
PUBLIC Creation_X, Destruction_X, FillX
contains
subroutine Creation_X(n)
USE ISO_C_BINDING, ONLY : C_Int32_t
IMPLICIT NONE
INTEGER(KIND=C_Int32_t), INTENT(IN) :: n
allocate(x(n))
RETURN
end subroutine Creation_X
subroutine Destruction_X
USE ISO_C_BINDING, ONLY : C_Int32_t
IMPLICIT NONE
IF(ALLOCATED(X)) DEALLOCATE(X)
RETURN
end subroutine Destruction_X
subroutine fillx
USE ISO_C_BINDING, ONLY : C_Int32_t
IMPLICIT NONE
INTEGER(KIND=C_Int32_t) :: N
DO I= 1, SIZE(x)
x(I) = I
ENDDO
RETURN
end subroutine fillx
end module arraycheck
program main
use arraycheck
CALL Creation_X(5)
call fillx
print*,x
CALL Destruction_X
end

Related

How can I protect a module variable that should only be readable through a pointer in fortran?

I have an example program that looks like this:
module important_module
integer, dimension(5), protected, target :: important_array
contains
function testFunction() result(important_array_pointer)
integer, dimension(:), pointer :: important_array_pointer
integer :: i
do i = 1, size(important_array)
important_array(i) = 0
end do
important_array_pointer=>important_array
end function testFunction
end module important_module
Program TEST
use important_module
integer, dimension(:), pointer :: important_array_pointer
important_array_pointer=>testFunction()
print *, important_array_pointer(1) ! prints 0
important_array_pointer(1) = 1
print *, important_array_pointer(1) ! prints 1
End Program TEST
I would like important_array to only be writable from within the important_module module, hence the protected definition. This is because this array is used in conjunction with the fortran FFTW interface and holds information where a fourier transform is performed on, and it's suboptimal to have the input- or output arrays of these operations be public or be accessible from anywhere outside of this module. This example simplifies this as a 1d integer array.
If I generate a pointer to this array, it still becomes writable from the outside, even though I expected some kind of violation error.
Is there a way to ensure that this variable is actually protected and cannot be written to from anywhere outside of the corresponding module?
To start, I agree with #francescalus about pointer usage in Modern Fortran. To me, it is still not clear why you are using a pointer to that important variable you want to protect, approach you clearly noticed, it does not protect your variable as you'd like.
If possible, I would remove the target attribute.
But in the case you have to keep it, then the only (to my knowledge) way is to build an interface layer on top of it:
module important_module
implicit none
private
public :: testfun
integer, parameter :: array_size = 5
integer, target :: important_array(array_size)
contains
function testfun() result(important_array_pointer)
integer, dimension(:), pointer :: important_array_pointer
integer :: i
do i = 1, array_size
important_array(i) = i
end do
important_array_pointer => important_array
end function
end module important_module
module interfmodule
use important_module
implicit none
public
integer, pointer, protected :: var_interf(:)
contains
subroutine setVarPtr()
var_interf => testfun()
end subroutine
end module
Program TEST
use interfmodule
implicit none
call setVarPtr()
print *, var_interf(3)
print *, var_interf(4)
! ! Trying to write gives error !
! var_interf(2) = 10
End Program TEST

How to make a generic procedure pointer in Fortran?

I am a low level Fortran programmer. I am trying to make subroutines as generic as possible and I wonder if I can send an information of which subroutine another subroutine should acces from a given information in the main program. For instance, if I have:
program main
use test
implicit none
real(8) X
end program main
And:
module test
contains
subroutine A (X)
real(8) X
X = 2*X
end subroutine A
subroutine B (X)
real(8) X
X = 3*X
end subroutine B
end module test
I would like to, given the subroutine name 'A' or 'B' in the main program, transfer this to a third subroutine C inside the module test, which in turn would make some calculations and use the transferred name to choose between A and B in its calculations.
I know if I build the calculations of that subroutine C inside the main program, I can use a procedure pointer to access either A or B subroutines. However, I need to have the subroutine C. So I guess I will have a subroutine C with built in procedure pointer and it will take the name given in the main program as an argument. But I do not know how to do that. Neither if it is possible. If it is not, is there any other way? I do not know, maybe the subroutine C reading a txt file associating the read name to the procedure pointer. But, how?
Thank you, in advance!
I think that what you want is this: you first define subroutines A and B
module ab_m
implicit none
contains
subroutine A(X)
real, intent(inout) :: X
X = 2 * X
end subroutine A
subroutine B(X)
real, intent(inout) :: X
X = 3 * X
end subroutine B
end module ab_m
Then subroutine C uses a dummy procedure, specified by an interface,
module c_m
implicit none
contains
subroutine C(sub,y)
interface
subroutine sub(p)
implicit none
real, intent(inout) :: p
end subroutine sub
end interface
real, intent(inout) :: y
y = y + 1
call sub(y)
end subroutine C
end module c_m
and the main program chooses what procedure to use in C:
program p
use ab_m
use c_m
implicit none
real :: z(2)
z = 1.0
call C(B, z(1))
call C(A, z(2))
write(*,*) z ! writes 6.0, 4.0 [ (1+1)*3, (1+1)*2) ]
end program p

Wrong result when using a global variable in Fortran

I'm learning the basics of Fortran. I created a simple subroutine initializing a matrix:
program test
integer, parameter :: n = 1024
real :: a(n, n)
call init(a)
write (*, *) a(1, 1)
end program
subroutine init(a)
real :: a(n, n)
a(:, :) = 3.0
end subroutine
Then the output is 0.0 instead of expected 3.0. Apart from that, valgrind says that:
==7006== Conditional jump or move depends on uninitialised value(s)
==7006== at 0x400754: init_ (in /home/marcin/proj/mimuw/fortran/test)
==7006== by 0x4007A4: MAIN__ (in /home/marcin/proj/mimuw/fortran/test)
==7006== by 0x40083B: main (in /home/marcin/proj/mimuw/fortran/test)
Why? The n parameter is correctly recognized by the compiler and should be a global one.
I compiled the program with gfortran 6.3.1
n is not a global variable, it is a local variable of the main program.
The subroutine is a completely independent compilation unit from the main program and they do not share any information.
A subroutine can "see" other variables of the parent module, if it is a module procedure, or variables of a parent (host) procedure or program if it is an internal procedure.
Be sure to read about the structure of Fortran programs and use modules as much as possible. Prefer modules over internal procedures. You will see how to put the subroutine into a module or how to make it internal to the main program in the link.
I did not mention common blocks, just don't use them, they are obsolete. And rember to use implicit none in every compilation unit.
Assuming that you want it everywhere, then one uses a COMMON block in the f77 era, and a MODULE now.
I CAPITALISED most of the changes. And if there is no error gives a few ways to consider understanding N in the SUBROUTINE, and an ELEMENTAL FUNCTION would likely be worthwhile to try here too.
MODULE MyMODULE
integer, parameter :: n = 1024
END MODULE MyMODULE
!%%%%%%%%%%
program test
USE MyModule
IMPLICIT NONE
! done up in ˆmoduleˆ...! integer, parameter :: n = 1024
REAL, DIMENSION(n,n) :: A
CALL Alternative_Init(A, 3.3)
WRITE (*,*) a(1, 1)
CALL Alternative2_Init(A, n, 1.23)
WRITE (*,*) a(1, 1)
call init(a)
write (*, *) a(1, 1)
END PROGRAM TEST
!%%%%%%%%%%
subroutine init(a)
USE MyModule
IMPLICIT NONE
real :: a(n, n)
a(:, :) = 3.0
RETURN
END SUBROUTINE init
!%%%%%%%%%%
SUBROUTINE Alternative_Init(a, Val4A)
USE MyModule
IMPLICIT NONE
REAL, DIMENSION(:,:) , INTENT(INOUT) :: a
REAL , INTENT(IN ) :: Val4A
a(:, :) = Val4A
! or just... A = Val4A ! which does them all too.
RETURN
END SUBROUTINE Alternative_Init
!%%%%%%%%%%
SUBROUTINE Alternative2_Init(a, n, Val4A)
!!!! USE MyModule
IMPLICIT NONE
INTEGER , INTENT(IN ) :: n
REAL, DIMENSION(n,n) , INTENT( OUT) :: a
REAL , INTENT(IN ) :: Val4A
A = Val4A
RETURN
END SUBROUTINE Alternative2_Init

Keyword OPTIONAL in TYPE in Fortran does not work

I try the following codes, and find the OPTIONAL keyword does not work. The compile is ok, but the runtime error will prompt.
I know usually the INTERFACE should be used in the module to provide enough information for the routines. I also try that, but failed to finish the compile no matter where I put the INTERFACE.
I have read some codes which use OPTIONAL in the TYPE declaration. https://www.pgroup.com/lit/articles/insider/v3n1a3.htm
Now I am using intel visual fortran, so is there any difference?
module testA_m
implicit none
type :: onion_c
contains
procedure :: testA
end type
contains
subroutine testA(this, a,b)
implicit none
class(onion_c) :: this
real*8 :: a
real*8, optional :: b
write(*,*) a,b
end subroutine
end module
program main
call testIt()
end program
subroutine testIt()
use testA_m
implicit none
type(onion_c) :: onion
real*8 :: c1
real*8 :: c2
c1 = 1.0d0
c2 = 2.0d0
call onion.testA(c1)
end subroutine
Well, you are trying to print b, which is not passed to the subroutine. Hence the access violation.
You should check for b first:
subroutine testA(this, a,b)
implicit none
class(onion_c) :: this
real*8 :: a
real*8, optional :: b
if ( present(b) ) then
write(*,*) a,b
else
write(*,*) a
endif
end subroutine
Maybe I need another variable for the real operation. Like the following.
I am still looking forward the better solution to use b directly.
subroutine testA(this, a,b)
implicit none
class(onion_c) :: this
real*8 :: a
real*8, optional :: b
real*8 :: bUsed
if ( present(b) ) then
bUsed = b
write(*,*) a,bUsed
else
bUsed = 2.00d0
write(*,*) a,bUsed
endif
end subroutine
Because Fortran does not support a program like
subroutine testA( this, a, b=10.0d0 )
I usually define a macro like the following in a common header file
#define _optval_(x,xopt,default) x = default; if (present(xopt)) x = xopt
and then use it at the top of a subroutine like
subroutine testA(this, a,b_)
class(onion_c) :: this
real*8 :: a
real*8, optional :: b_
real*8 b
_optval_( b, b_, 10.0d0 ) !! use only b from here on
Although this is not essentially different from writing several IF constructs, I feel it is a bit more convenient (at least for simple variables) because no need to worry about whether b is optional or not in the subsequent code. (But frankly, I hope Fortran2020 or so will support a syntax like the first example...)

Allocate matrix in subroutine fortran

I'm new to Fortran (more experienced in C), and am trying to allocate memory for a matrix of values using the allocate command. The code is:
module SMS
contains
subroutine readSMS(elem)
real, dimension(:,:), allocatable :: elem
allocate( elem(3792, 3) ) ! this will be a variable later on, for now I've
! hard-coded the number of elements in my test case
end subroutine
end module
When running, the code always crashes on the allocate line, with the error: Program exception - access violation. This program, however, works fine if elem is a local variable as opposed to one passed in to the subroutine. In C, I would use something like:
double **elem;
readSMS(&elem); //pass in a pointer to elem so that memory can be allocated
Is there a similar method in Fortran that I can use to allocate memory in a subroutine?
Here is the call to the function:
program main
use SMS
implicit none
include 'mpif.h'
! Variables
integer ierr,num_procs,my_id
integer num_elem,num_regions
real, dimension(:,:), allocatable :: elem
real, dimension(:,:), allocatable :: regions
! Body of main
call MPI_INIT(ierr)
call MPI_COMM_RANK(MPI_COMM_WORLD,my_id,ierr)
call MPI_COMM_SIZE(MPI_COMM_WORLD,num_procs,ierr)
call readSMS(elem)
deallocate(elem)
call MPI_FINALIZE(ierr)
end program main
At the moment, this is the entirety of the program (as you can see, I'm just getting started).
#francescalus I think the subroutine readSMS is in the module, so the explicit interface is not the problem. #wolfPack88 look at the link provided by #Jonathan and you will be able to figure out the solution.
update:
module SMS
contains
subroutine readSMS(elem)
real, dimension(:,:), allocatable :: elem
allocate( elem(10, 3) )
elem=10
end subroutine
end module
program main
use SMS
implicit none
real, dimension(:,:), allocatable :: elem
call readSMS(elem)
print *, elem
deallocate(elem)
end program main
This code works in ifort without any issue...