Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

variable rank of dummy argument

Pietro_P_
Beginner
555 Views

hope the title describes the problem at hand:

a code like the following compiles fine, but when i debug i cannot step into the subroutine (though it gives right results).i

program main
real(8), dimension(3) :: f
integer :: ni,nj

ni=1
nj=1
call sbrtn(ni,nj,f)

endprogram main

subroutine sbrtn(nni,nnj,ff)
integer, intent(in) :: nni,nnj
real(8), dimension(3,nni,nnj), intent(out) ff

ff=1.0d0 
endsubroutine sbrtn

is it correct to pass a rank 1 array to the subroutine which instead expects a rank 3 array? This could be in theory pushed to the point where i could pass a scalar instead of an array. thanks

 

0 Kudos
10 Replies
Arjen_Markus
Honored Contributor I
555 Views

Up to FORTRAN 77 it was quite usual to do so. With the advent of Fortran 90 the compiler has enough information - if you choose so - to detect such mismatches. But it so happens that, if the subroutine works element-wise, as you suggest in the example, you can use so-called elemental procedures to do this completely within the standard:

module my_elemental_subroutines
elemental subroutine sbrtn( var )
real :: var

var = 0.0'
end subroutine
end module my_elemental_subroutines

Such subroutines work element-wise, so the rank is no longer an issue. They have restrictions though - the interface must be explicit, hence the module  - and the subroutine may only work on one element at a time. But then you can pass a scalar or a ran-n array with no problem at all.

0 Kudos
TimP
Honored Contributor III
555 Views

These rank equivancies are ok architecturally on intel hardware but violate language standard, and should be flagged by gen-interfaces. Passing a scalar to an array element did fail on the machine I learned on, even though the compiler didn't check.

0 Kudos
Steven_L_Intel1
Employee
555 Views

Note though that passing a scalar to an array dummy argument is forbidden. (With the exception of the Fortran 2015 "assumed rank" declaration which you probably don't want.)

As Arjen says, passing an array of the wrong rank to an array dummy argument is allowed if the interface is implicit, the actual argument is a whole array and is not a pointer. The rules for sequence association must be followed.

0 Kudos
Pietro_P_
Beginner
555 Views

thanks. 

Is this the reason why the debugger cannot step into the subroutine?

Is there a way of doing it in a more correct way?

 

0 Kudos
Pietro_P_
Beginner
555 Views

Arjen Markus wrote:

Up to FORTRAN 77 it was quite usual to do so. With the advent of Fortran 90 the compiler has enough information - if you choose so - to detect such mismatches. But it so happens that, if the subroutine works element-wise, as you suggest in the example, you can use so-called elemental procedures to do this completely within the standard:

module my_elemental_subroutines
elemental subroutine sbrtn( var )
real :: var

var = 0.0'
end subroutine
end module my_elemental_subroutines

Such subroutines work element-wise, so the rank is no longer an issue. They have restrictions though - the interface must be explicit, hence the module  - and the subroutine may only work on one element at a time. But then you can pass a scalar or a ran-n array with no problem at all.

hi, sorry my example was misleading: the actual subroutine accesses each elements of the array and does different things on each of them...so i think it could not be called an "elemental" function.

0 Kudos
Steven_L_Intel1
Employee
555 Views

No, that's not the reason. After I corrected the syntax errors in the code you posted, it debugged just fine. Make sure you are using a Debug configuration and did not enable optimization.

0 Kudos
Arjen_Markus
Honored Contributor I
555 Views

No, that definitely makes it unsuitable for "elemental". Such subroutines or functions are the user-defined equivalence to, say, sin() or exp(), which can also be applied to arrays or scalars alike.

The thing is that they get one element at a time and you cannot rely on the order. Which also means you cannot include side effects.

0 Kudos
JohnNichols
Valued Contributor III
555 Views

Would a better way be to overload the operator - so you have an operation let us call it Steve or ST for short, assume ST can be performed on a real

call ST(a real)

a complex

call ST(a complex)

a vector

call ST(Vector)

an array

call ST(array)

you have the advantage that in 20 years when some poor person like me wants to use the code you are not taking the code apart trying to find out what has been done with the strange calls.

TABS had really interesting calls that I am still sorting out.

assume ST takes the inverse sqrt of the log of the pi raised to the eth power equivalent in the 23 dimension whilst acting on a projection in the 22 dimension - it returns an error otherwise.

0 Kudos
Pietro_P_
Beginner
555 Views

i did like this:

program main
real(8), dimension(3) :: f

real(8), dimension(3,1,1) :: f_arr
integer :: ni,nj

ni=1
nj=1
call sbrtn(ni,nj,f_arr)

f=f_arr(1:3,1,1,1)

endprogram main

subroutine sbrtn(nni,nnj,ff)
integer, intent(in) :: nni,nnj
real(8), dimension(3,nni,nnj), intent(out) ff

ff=1.0d0 
endsubroutine sbrtn

 

is it dirty enough? ;-) 

 

PS apparently this solved also the debugger strange behavior! great

0 Kudos
JohnNichols
Valued Contributor III
555 Views

 

Pietro P. wrote:

i did like this:

program main
real(8), dimension(3) :: f

real(8), dimension(3,1,1) :: f_arr
integer :: ni,nj

ni=1
nj=1
call sbrtn(ni,nj,f_arr)

f=f_arr(1:3,1,1,1)

endprogram main

subroutine sbrtn(nni,nnj,ff)
integer, intent(in) :: nni,nnj
real(8), dimension(3,nni,nnj), intent(out) ff

ff=1.0d0 
endsubroutine sbrtn

 

is it dirty enough? ;-) 

 

PS apparently this solved also the debugger strange behavior! great

Rather::

0 Kudos
Reply