- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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_subroutinesSuch 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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Pietro P. wrote:
i did like this:
program main
real(8), dimension(3) :: freal(8), dimension(3,1,1) :: f_arr
integer :: ni,njni=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) ffff=1.0d0
endsubroutine sbrtn
is it dirty enough? ;-)
PS apparently this solved also the debugger strange behavior! great
Rather::
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page