I am looking at some code and there is this:
BLOCK
...lines of code...
END BLOCK
What is the purpose of BLOCK? I tried to google it, but all I found was something about BLOCK DATA and COMMON blocks. I'm not sure whether they are related.
From the Fortran 2008 standard:
The BLOCK construct is an executable construct that may contain declarations.
It is not related to common blocks or to block data program units.
So, the main use is this "containing declarations".
As scoping units we have things like
integer i
block
integer j ! A local integer
integer i ! Another i
save i ! ... which can even be SAVEd
end block
which affords locality of declarations:
! ... lots of code
block
integer something
read *, something
end block
! ... lots more code
These scoping blocks allow automatic objects:
integer i
i = 5
block
real x(i)
end block
As executable constructs, they also have useful flow control:
this_block: block
if (something) exit this_block
! ... lots of code
end block
They also have finalization control:
type(t) x
block
type(t) y
end block ! y is finalized
end ! x is not finalized
for x and y of finalizable type.
Oh, and let's not forget how you can confuse people with implicit typing.
I have composed a few more fun examples. What if you want to invoke an assumed length function with different lengths in the same instance of a subprogram? You need a specification statement to tell the compiler the length you want, so a BLOCK construct can do this for you
function F(x)
implicit none
character(*) F
character x(:)
integer i
do i = 1, len(F)
F(i:i) = x(1)
end do
end function F
program blox1
implicit none
integer i
character c
do i = 1, 7
c = achar(65+modulo(i**4+6*i**2+1,26))
block
character(2*i+1), external :: F
call blox1a(F)
end block
end do
contains
subroutine blox1a(F)
interface
function F(x)
import
implicit none
character(2*i+1) F
character x(:)
end function F
end interface
write(*,'(a)') F([c])
end subroutine blox1a
end program blox1
Output with gfortran:
III
PPPPP
GGGGGGG
PPPPPPPPP
WWWWWWWWWWW
FFFFFFFFFFFFF
SSSSSSSSSSSSSSS
Or how about when you need the appropriate KIND for a REAL literal? This requires a named constant and the KIND might be given in the specification statements of another MODULE and may even be given as an expression. In that case you might try defining a named constant with the value of that expression, but if an unlucky choice is made that name might override another host associated name. A BLOCK construct makes it all OK:
module mytypes
use ISO_FORTRAN_ENV
implicit none
type T(KIND)
integer, kind :: KIND
real(KIND) x
end type T
interface assignment(=)
module procedure assign8, assign4
end interface assignment(=)
contains
subroutine assign8(x,y)
real(REAL64), intent(in) :: y
type(T(kind(y))), intent(out) :: x
x%x = y
end subroutine assign8
subroutine assign4(x,y)
real(REAL32), intent(in) :: y
type(T(kind(y))), intent(out) :: x
x%x = y
end subroutine assign4
end module mytypes
program blox2
use mytypes
implicit none
type(T(REAL32)) x
BLOCK
! integer, parameter :: rk = x%KIND ! Not allowed
integer, parameter :: rk = kind(x%x)
x = 0.0072973525664_rk
write(*,'(g0)') x%x
END BLOCK -1 is too small
12! = 479001600
13 is too big
BLOCK
type(T(REAL64)) x
BLOCK
! integer, parameter :: rk = x%KIND ! Not allowed
integer, parameter :: rk = kind(x%x)
x = 0.0072973525664_rk
write(*,'(g0)') x%x
END BLOCK
END BLOCK
end program blox2
Output with gfortran:
0.729735242E-02
0.72973525663999998E-002
It can be tricky to get a Fortran pointer to a C string because there is no syntax to tell C_F_POINTER what the length of the target of a deferred length pointer should be. BLOCK to the rescue!
program blox3
use ISO_C_BINDING
implicit none
character(len=:,kind=C_CHAR), allocatable, target :: x
type(C_PTR) c_hello
integer(C_INTPTR_T) address
character(kind=C_CHAR), pointer :: nul_address
character(len=:,kind=C_CHAR), pointer :: f_hello
integer i
x = 'Hello, world'//achar(0)
c_hello = C_LOC(x(1:1))
address = transfer(c_hello,address)
i = 0
do
call C_F_POINTER(transfer(address+i,C_NULL_PTR),nul_address)
if(nul_address == C_NULL_CHAR) exit
i = i+1
end do
BLOCK
character(len=i,kind=C_CHAR), pointer :: temp
call C_F_POINTER(c_hello,temp)
f_hello => temp
END BLOCK
write(*,'(i0,1x,a)') len(f_hello), f_hello
end program blox3
Output with gfortran:
12 Hello, world
Not to mention that a named BLOCK construct gives us a label to hang our spaghetti code on:
program blox4
implicit none
integer i
integer j(3)
integer k
j = [-1,12,13]
do i = 1, size(j)
factorial: BLOCK
if(j(i) < 0) then
write(*,'(*(g0))') j(i),' is too small'
EXIT factorial
end if
if(j(i) > 12) then
write(*,'(*(g0))') j(i),' is too big'
EXIT factorial
end if
write(*,'(*(g0))') j(i),'! = ',product([(k,k=1,j(i))])
END BLOCK factorial
end do
end program blox4
Output with gfortran:
-1 is too small
12! = 479001600
13 is too big
The block construct allows you to declare entities such as variables, types, external procedures, etc which are locally known to the block but have no effect to any variables outside of the block.
Example 1:
IF (swapxy) THEN
BLOCK
REAL (KIND (x)) tmp
tmp = x
x = y
y = tmp
END BLOCK
END IF
Here the variable tmp is locally defined to help out with the swap of two variables. Outside of the block, the variable tmp is unknown or back its original form if it was defined outside of the block (see next example).
Example 2:
F = 254E-2
BLOCK
REAL F
F = 39.37
END BLOCK
! F is still equal to 254E-2.
The variable F is redefined locally to the block but has no effect outside of it.
These kinds of blocks are used to make the code more readable and easier to understand as you don't need to look to the entire subprogram to understand what the locally defined entities are. Furthermore, the compiler knows that these entities are locally defined, so it might do some more optimization.
Related
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
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
I am looking at some code and there is this:
BLOCK
...lines of code...
END BLOCK
What is the purpose of BLOCK? I tried to google it, but all I found was something about BLOCK DATA and COMMON blocks. I'm not sure whether they are related.
From the Fortran 2008 standard:
The BLOCK construct is an executable construct that may contain declarations.
It is not related to common blocks or to block data program units.
So, the main use is this "containing declarations".
As scoping units we have things like
integer i
block
integer j ! A local integer
integer i ! Another i
save i ! ... which can even be SAVEd
end block
which affords locality of declarations:
! ... lots of code
block
integer something
read *, something
end block
! ... lots more code
These scoping blocks allow automatic objects:
integer i
i = 5
block
real x(i)
end block
As executable constructs, they also have useful flow control:
this_block: block
if (something) exit this_block
! ... lots of code
end block
They also have finalization control:
type(t) x
block
type(t) y
end block ! y is finalized
end ! x is not finalized
for x and y of finalizable type.
Oh, and let's not forget how you can confuse people with implicit typing.
I have composed a few more fun examples. What if you want to invoke an assumed length function with different lengths in the same instance of a subprogram? You need a specification statement to tell the compiler the length you want, so a BLOCK construct can do this for you
function F(x)
implicit none
character(*) F
character x(:)
integer i
do i = 1, len(F)
F(i:i) = x(1)
end do
end function F
program blox1
implicit none
integer i
character c
do i = 1, 7
c = achar(65+modulo(i**4+6*i**2+1,26))
block
character(2*i+1), external :: F
call blox1a(F)
end block
end do
contains
subroutine blox1a(F)
interface
function F(x)
import
implicit none
character(2*i+1) F
character x(:)
end function F
end interface
write(*,'(a)') F([c])
end subroutine blox1a
end program blox1
Output with gfortran:
III
PPPPP
GGGGGGG
PPPPPPPPP
WWWWWWWWWWW
FFFFFFFFFFFFF
SSSSSSSSSSSSSSS
Or how about when you need the appropriate KIND for a REAL literal? This requires a named constant and the KIND might be given in the specification statements of another MODULE and may even be given as an expression. In that case you might try defining a named constant with the value of that expression, but if an unlucky choice is made that name might override another host associated name. A BLOCK construct makes it all OK:
module mytypes
use ISO_FORTRAN_ENV
implicit none
type T(KIND)
integer, kind :: KIND
real(KIND) x
end type T
interface assignment(=)
module procedure assign8, assign4
end interface assignment(=)
contains
subroutine assign8(x,y)
real(REAL64), intent(in) :: y
type(T(kind(y))), intent(out) :: x
x%x = y
end subroutine assign8
subroutine assign4(x,y)
real(REAL32), intent(in) :: y
type(T(kind(y))), intent(out) :: x
x%x = y
end subroutine assign4
end module mytypes
program blox2
use mytypes
implicit none
type(T(REAL32)) x
BLOCK
! integer, parameter :: rk = x%KIND ! Not allowed
integer, parameter :: rk = kind(x%x)
x = 0.0072973525664_rk
write(*,'(g0)') x%x
END BLOCK -1 is too small
12! = 479001600
13 is too big
BLOCK
type(T(REAL64)) x
BLOCK
! integer, parameter :: rk = x%KIND ! Not allowed
integer, parameter :: rk = kind(x%x)
x = 0.0072973525664_rk
write(*,'(g0)') x%x
END BLOCK
END BLOCK
end program blox2
Output with gfortran:
0.729735242E-02
0.72973525663999998E-002
It can be tricky to get a Fortran pointer to a C string because there is no syntax to tell C_F_POINTER what the length of the target of a deferred length pointer should be. BLOCK to the rescue!
program blox3
use ISO_C_BINDING
implicit none
character(len=:,kind=C_CHAR), allocatable, target :: x
type(C_PTR) c_hello
integer(C_INTPTR_T) address
character(kind=C_CHAR), pointer :: nul_address
character(len=:,kind=C_CHAR), pointer :: f_hello
integer i
x = 'Hello, world'//achar(0)
c_hello = C_LOC(x(1:1))
address = transfer(c_hello,address)
i = 0
do
call C_F_POINTER(transfer(address+i,C_NULL_PTR),nul_address)
if(nul_address == C_NULL_CHAR) exit
i = i+1
end do
BLOCK
character(len=i,kind=C_CHAR), pointer :: temp
call C_F_POINTER(c_hello,temp)
f_hello => temp
END BLOCK
write(*,'(i0,1x,a)') len(f_hello), f_hello
end program blox3
Output with gfortran:
12 Hello, world
Not to mention that a named BLOCK construct gives us a label to hang our spaghetti code on:
program blox4
implicit none
integer i
integer j(3)
integer k
j = [-1,12,13]
do i = 1, size(j)
factorial: BLOCK
if(j(i) < 0) then
write(*,'(*(g0))') j(i),' is too small'
EXIT factorial
end if
if(j(i) > 12) then
write(*,'(*(g0))') j(i),' is too big'
EXIT factorial
end if
write(*,'(*(g0))') j(i),'! = ',product([(k,k=1,j(i))])
END BLOCK factorial
end do
end program blox4
Output with gfortran:
-1 is too small
12! = 479001600
13 is too big
The block construct allows you to declare entities such as variables, types, external procedures, etc which are locally known to the block but have no effect to any variables outside of the block.
Example 1:
IF (swapxy) THEN
BLOCK
REAL (KIND (x)) tmp
tmp = x
x = y
y = tmp
END BLOCK
END IF
Here the variable tmp is locally defined to help out with the swap of two variables. Outside of the block, the variable tmp is unknown or back its original form if it was defined outside of the block (see next example).
Example 2:
F = 254E-2
BLOCK
REAL F
F = 39.37
END BLOCK
! F is still equal to 254E-2.
The variable F is redefined locally to the block but has no effect outside of it.
These kinds of blocks are used to make the code more readable and easier to understand as you don't need to look to the entire subprogram to understand what the locally defined entities are. Furthermore, the compiler knows that these entities are locally defined, so it might do some more optimization.
I have a small code declaring a pointer to array of derived type which has a field that is an allocatable array of another derived type having a real variable as a field.
Using gnu fortran (8.2) I obtain different results for each location in the array or as a vector.
Using intel fortran (2019.4) compiler succeeded.
program test
implicit none
integer, parameter :: length = 2
real(8), dimension(length) :: a, b
integer :: i
type point
real(8) :: x
end type point
type stored
type(point), dimension(:), allocatable :: np
end type stored
type(stored), dimension(:), pointer :: std=>null()
allocate(std(1))
allocate(std(1)%np(length))
std(1)%np(1)%x = 0.3d0
std(1)%np(2)%x = 0.3555d0
do i = 1, length
write(*, "('std(1)%np(',i1,')%x = ',1e22.14)") i, std(1)%np(i)%x
end do
do i = 1, length
write(*, "('std(1)%np(1:',i1,') = ',2e22.14)") i, std(1)%np(1:i)%x
end do
a = std(1)%np(1:2)%x
b = [std(1)%np(1)%x, std(1)%np(2)%x]
if (norm2(a - b) .gt. 1d-3) then
write(*,*) 'failure'
else
write(*, *) 'success'
end if
end program test
the code terminates successfully, but using gfortran one obtains 'failure' on screen and inconsistent prints above and using Intel compiler one obtains 'success' on screen and consistent prints above.
It's not clear to me what your question is, unless it's the title. If so, no, pointers to derived types are fine. Your program correctly allocates std as an extent-1 array and then allocates std(1)%np(2). It then assigns to the x subcomponents of both np elements. Looks fine to me.
There are several things that could potentially cause "failure" - you should run the gfortran code in the debugger to see what is going wrong.
The problem presented in the code above was resolved in the following [link] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91077
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