A sample code is below to indicate the problem I am having. This is as minimal/complete I can make it in order to reproduce the problem I'm having. My problem is that the same print statement, three lines apart, is yielding two different results. The first print statement yields the correct result while the second one yields the wrong result. Am I re-writing the variable definitions within these 3 lines? How come when I move the print statment down 3 lines I get a different, incorrect result? The print statements are shown below. Since the variables are somehow being changed, this causes a lot of problems in the expected results later on in my code. However I just want to understand whats going on with these print statements. Thanks.
Module Sample
integer :: n,m
contains
subroutine Sub1(localf0)
implicit none
complex, dimension(-10:10,-10:10), intent(inout) :: localf0
complex, dimension(-10:10,-10:10) :: localf1
complex, dimension(-10:10,-10:10) :: Deriv0, Deriv1
Deriv0 = Deriv(localf0)
do while (norm2(abs(Deriv0)) > 0.000001)
print*, abs(localf1(1,1))-abs(localf0(1,1))
localf1 = localf0 +1.0*Deriv(localf0)
Deriv0 = Deriv(localf0)
Deriv1 = Deriv(localf1)
print*, abs(localf1(1,1))-abs(localf0(1,1))
end do
end subroutine Sub1
function Deriv(func)
implicit none
real :: x, y
complex, dimension(-10:10,-10:10), intent(in) :: func
complex, dimension(-10:10,-10:10) :: localf,Deriv
localf = func
do m=-9,9
do n=-9,9
x = real(n)*0.1
y = real(m)*0.1
localf(n,m)= cmplx(z1(x,y),z2(x,y))
end do
end do
do m=-9,9
do n=-9,9
Deriv(n,m) = (localf(n+1,m)+localf(n-1,m)+localf(n,m+1)+localf(n,m-1)-4*localf(n,m))/0.01
end do
end do
end function Deriv
End Module Sample
program MyProgram
use Sample
implicit none
complex, dimension(-10:10,-10:10) :: localf0,localf1
do m=-10,10
do n=-10,10
localf0(n,m) = cmplx(z1(real(n)*0.1,real(m)*0.1) , z2(real(n)*0.1,real(m)*0.1))
localf1 = localf0 + 1.0*Deriv(localf0)
end do
end do
call Sub1(localf0)
end program
Now that I've run it there is a insidious thing here that I frankly think the compiler should throw an error on. (Why I made this an answer rather than comment)
You have made n,m module variables, effectively making them global variables and you use the same n,m in the main program loop and in the loops inside the function.
Your function deriv changes the values of n and m. (They return as the end value of its last loop) so that the main program loop does not complete.
You can see this if you put in the main loop:
print*,m,n
localf1 = localf0 + 1.0*deriv(localf0)
print*,m,n
you get :
-10 -10
10 10
and the loop exits.. ( the 10,10 is one more than the the loop limit of 9,9 inside the function.. )
What you should do is remove the integer n,m from the module. Declare n,m integers where needed (That is declare individually in deriv and in MyProgram )
You may note also there is no reason for localf1 to be assigned inside the main program loop in the first place (or set at all for that matter since you never use it ). Removing that assignment would fix the issue as well, but I'd still recommend changing the n,m declarations to local.
Note with that fixed you still have the problem that nothing changes with each iteration of the while loop so it loops indefinitely printing the same values. I guess you want to update localf0=localf1 at the end of the loop.
Related
This question is based on an answer to the post Fortran intent(inout) versus omitting intent, namely the one by user Vladimyr, #Vladimyr.
He says that "<...> Fortran copies that data into a contiguous section of memory, and passes the new address to the routine. Upon returning, the data is copied back into its original location. By specifying INTENT, the compiler can know to skip one of the copying operations."
I did not know this at all, I thought Fortran passes by reference exactly as C.
The first question is, why would Fortran do so, what is the rationale behind this choice?
As a second point, I put this behaviour to the test. If I understood correctly, use of INTENT(IN) would save the time spent in copying back the data to th original location, as the compiler is sure the data has not been changed.
I tried this little piece of code
function funco(inp) result(j)
!! integer, dimension(:), intent (in) :: inp
integer, dimension(:):: inp
integer, dimension(SIZE(inp)) :: j ! output
j = 0.0 !! clear whole vector
N = size(inp)
DO i = 1, N
j(i) = inp(i)
END DO
end function
program main
implicit none
interface
function funco(inp) result(j)
!! integer, dimension(:), intent (in) :: inp
integer, dimension(:) :: inp
integer, dimension(SIZE(inp)) :: j ! output
end function
end interface
integer, dimension(3000) :: inp , j
!! integer, dimension(3000) :: funco
integer :: cr, cm , c1, c2, m
real :: rate, t1, t2
! Initialize the system_clock
CALL system_clock(count_rate=cr)
CALL system_clock(count_max=cm)
CALL CPU_TIME(t1)
rate = REAL(cr)
WRITE(*,*) "system_clock rate ",rate
inp = 2
DO m = 1,1000000
j = funco(inp) + 1
END DO
CALL SYSTEM_CLOCK(c2)
CALL CPU_TIME(t2)
WRITE(*,*) "system_clock : ",(c2 - c1)/rate
WRITE(*,*) "cpu_time : ",(t2-t1)
end program
The function copies an array, and in the main body this is repeated many times.
According to the claim above, the time spent in copying back the array should somehow show up.
system_clock rate 1000.00000
system_clock : 2068.07910
cpu_time : 9.70935345
but the results are pretty much the same independently from whether INTENT is use or not.
Could anybody share some light on these two points, why does Fortran performs an additional copy (which seems ineffective at first, efficiency-wise) instead of passing by reference, and does really INTENT save the time of a copying operation?
The answer you are referring to speaks about passing some specific type of subsection, not of the whole array. In that case a temporary copy might be necessary, depending on the function. Your function uses and assumed shape array and a temporary array will not be necessary even if you try quite hard.
An example of what the author (it wasn't me) might have had in mind is
module functions
implicit none
contains
function fun(a, n) result(res)
real :: res
! note the explicit shape !!!
integer, intent(in) :: n
real, intent(in) :: a(n, n)
integer :: i, j
do j = 1, n
do i = 1, n
res = res + a(i,j) *i + j
end do
end do
end function
end module
program main
use functions
implicit none
real, allocatable :: array(:,:)
real :: x, t1, t2
integer :: fulln
fulln = 400
allocate(array(1:fulln,1:fulln))
call random_number(array)
call cpu_time(t1)
x = fun(array(::2,::2),(fulln/2))
call cpu_time(t2)
print *,x
print *, t2-t1
end program
This program is somewhat faster with intent(in) when compared to intent(inout) in Gfortran (not so much in Intel). However, it is even much faster with an assumed shape array a(:,:). Then no copy is performed.
I am also getting some strange uninitialized accesses in gfortran when running without runtime checks. I do not understand why.
Of course this is a contrived example and there are real cases in production programs where array copies are made and then intent(in) can make a difference.
In the program below, there are two methods presented for passing an array:
program main
integer, dimension(4) :: x = [9, 8, 7, 6]
call print_x(x(2:3)) ! Method 1
call print_x(x(2)) ! Method 2
end program
subroutine print_x(x)
integer, dimension(2), intent(in) :: x
print *, x
end subroutine
Both methods produce the same result: the numbers 8 and 7 are printed. Personally, I would never code this using Method 2 because it looks like a single value is being passed rather than an array.
Can you give an example of when Method 2 MUST be used instead of Method 1?
Consider the program
implicit none
integer :: x(2,2)=0
call set(x(2,1))
print*, x
contains
subroutine set(y)
integer y(2)
y = [1,2]
end subroutine set
end program
The dummy argument y in this subroutine call is argument associated with the elements x(2,1) and x(1,2). There is no array section of x which consists of exactly these two elements.
I always assumed that giving values in automatic sized dummy arguments within subroutine definitions has some benefit in error detection, when the routine is defined inside a module that gives an explicit interface. But following example shows that there is not really a checking of array bounds:
module test_mod
Implicit none
contains
!> Testing routine that has an automatic array arr of length n. The integer n is also given.
!> It is included in a module and has an explicit interface.
subroutine print_array(n, arr)
Integer, intent(in) :: n !< Size of arr
Integer, Dimension(n), intent(in) :: arr !< A test array that should be of size n
Integer :: i
do i = 1, n
print *, 'number:', i, arr(i)
enddo
End Subroutine print_array
end module test_mod
program playground
use test_mod, only : print_array
! Call print_array with an array smaller than 3 elements
Call print_array(3, [8, 9])
end program playground
arr is created with the dimension of n in subroutine print_array, but it is not checked if the dimension of the given array is correct. In my example the output is:
number: 1 8
number: 2 9
number: 3 -858993460
So the 3rd value is taken outside of arr bounds and in my case -858993460 is printed. I understand that such behaviour can not generally be catched at compile time. But even using ifort with /check:bounds option doesn't give an error message at run time.
Therefore, I would like to ask if it is good practice to specify arr with Dimension(n) or is it even better to define it with Dimension(:). What is the advantage of giving the dimension in such way?
Let A and B be matrices of size 1 times n and n times 1, respectively.
Then the multiplication of A with B is a 1 times 1 matrix.
Which is the better way to assign the value of MATMUL(A,B) to a real number x?
I would like to write:
x=MATMUL(A,B) ! <<--- but this is wrong.
The above expression is wrong because I'm trying to assign a 1 times 1 matrix to a real number.
My solution is to define a 1 times 1 matrix C and with this:
C=MATMUL(A,B)
x=C(1,1) ! <--- this solution is ok, but is too long
But, there exists a better way to assign MATMUL(A,B) to the real number x?
The entire code with my question is as follow:
PROGRAM testing
!
IMPLICIT NONE
REAL :: A(1,2),B(2,1),C(1,1),x
!
A(1,1)=1.0; A(1,2)=3.5
B(1,1)=2.0; B(2,1)=5.0
C=MATMUL(A,B) ! it is ok
x=MATMUL(A,B) ! it is wrong
x=C(1,1) ! it is ok <--- exists a better way ??
!
END PROGRAM testing
You have noticed that it is not possible to do intrinsic assignment of an array to a scalar (and C is a rank-2 array of size 1). x=C(1,1) is the correct way to do such assignment from the single element of C to the scalar x.
There are other ways to abstract that correct assignment statement, but probably little value in doing so.
In your specific case, however, there is alternative. Rather than matmul, consider dot_product.
x = DOT_PRODUCT(A(1,:), B(:,1)) ! Scalar result, intrinsic assignment allowed.
per my comment, you can write a very simple function to extract the first element of an array:
real function first(matrix) !return the (1,1,1,..) element of an array
real, intent(in) :: matrix(*)
first=matrix(1)
end function
simply use as:
real :: a(1,2),b(2,1),x
...
x=first(matmul(a,b))
note if you want to make sure this is only used for a dimension(1,1) array you need to use an explicit interface and do:
real function first(matrix)
real, intent(in) :: matrix(:,:)
if(.not.all(shape(matrix).eq.[1,1]))reporterror()
first=matrix(1,1)
end function
I am trying to get a better understanding of the kind specification, so I wrote the following program.
program main
implicit none
real(kind = selected_real_kind(1)) :: a1
real(kind = selected_real_kind(2)) :: a2
print *, "Kind = ", kind(a1), "Range = ", range(a1)
print *, "Kind = ", kind(a2), "Range = ", range(a2)
end program main
The program runs great. However, my question is not about kind. My question is about using a do loop. I would like to make the program bigger, but I don't want to write out declaration and print statements over and over.
I don't think I have much choice on the declarations. I think I will have to write them out one at a time. Is that correct?
However, I do think there is a way to use a do loop for the print statements. Maybe something like this:
program main
implicit none
integer :: i
real(kind = selected_real_kind(1)) :: a1
real(kind = selected_real_kind(2)) :: a2
do i = 1, 2
print *, "Kind = ", kind(ai), "Range = ", range(ai)
end do
end program main
Any suggestions?
You are going to come up against one problem with the loop approach: a kind selector when you use one must be a constant expression. I'm going to ignore the fact that you can't do dynamic variable selection, like construct ai as you have it to be a1 then a2: you'll find other questions about that.
A tempting approach for this is to use an array for the kind parameters. This is fine to an extent:
integer, parameter :: kinds(2) = [.., ..]
real(kinds(1)) :: a1
real(kinds(2)) :: a2
That is, you can use an element of a named constant (parameter) array as a kind parameter.
For those inquiry functions, as we're not selecting a1 and a2 in a loop, let's look at unnamed things (it's only the type and parameters that matter, after all).
do i=1, 2
print *, "Kind = ", kinds(i) ! KIND(ai) is just kinds(i)
end do
However, this works because of that relationship that kind(real(1,i)) is just i, when i is a valid kind selector.
In the more general looping case where it isn't just the kind numbers you want, but properties of the types with those kind parameters, you want to loopily construct an object of each kind. You'd like something with real(1,kinds(i)) and this is a problem. kinds(i) is not a constant expression, because i isn't, and so is not a valid kind selector.
Equally, you can't have a literal that looks like 1._kinds(i).
In summary, intuitively you're wanting to inquire about properties that are known at compile time, but using a loop to save on code. That loop though is inherently an executable thing.