forums.silverfrost.com Forum Index forums.silverfrost.com
Welcome to the Silverfrost forums
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Passing subroutine or array-valued function name as argument

 
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> General
View previous topic :: View next topic  
Author Message
Neo



Joined: 08 Mar 2007
Posts: 19

PostPosted: Wed Aug 22, 2007 8:05 am    Post subject: Passing subroutine or array-valued function name as argument Reply with quote

Esteemed FTN Gurus,

Both of My FTN 95 books are unclear on how to pass as
arguments the names of (i) array-valued functions, and
(ii) subroutines. Perhaps someone can help. Question

A short sample program is appended at the end of this query
to illustrate the problem. For a scalar-valued function, everything
works. But with the array-valued function, passing its name as an
argument bombs out ("floating point stack fault...") while running
- although it does not generate any compile errors.

1.) Do I need the INTENT(IN) attribute in the REAL, EXTERNAL
declaration of function FUNC_1D?

2.) What is the trick to getting the name of an array-valued
function to work when passed as an argument?

3.) How do I pass the name of a subroutine as an argument?

With many thanks Very Happy,
Ludwig

!############################################
module subroutine_library
contains
!-------------------------------------------------
subroutine tabulate_function_1d (func)
implicit none
integer :: i
real :: x
real, external, intent(in) :: func
do i = 1, 10
x = real(i)
print 100, x, func(x)
end do
100 format ('x = ', f12.7, 3x, 'f = ', f12.7)
end subroutine tabulate_function_1d
!-------------------------------------------------
subroutine tabulate_function_2d (func)
implicit none
integer :: i, j
real, dimension(2) :: x, f
real, external, intent(in) :: func
do i = 1, 3
do j = 1, 3
x = (/ real(i), real(j) /)
f = func(x)
print 100, x(1), x(2), f(1), f(2)
end do
end do
100 format ('x1 = ', f12.7, 1x, 'x2 = ', f12.7, 1x, / &
'f1 = ', f12.7, 1x, 'f2 = ', f12.7)
end subroutine tabulate_function_2d
!-------------------------------------------------
end module subroutine_library
!############################################
module function_library
contains
!-------------------------------------------------
function func_1d (x) result (f)
implicit none
real, intent(in) :: x
real :: f
f = x**2
end function func_1d
!-------------------------------------------------
function func_2d (x) result (f)
implicit none
real, dimension(2), intent(in) :: x
real, dimension(2) :: f
f(1) = x(1) + x(2)
f(2) = x(1)**2 + x(2)**2
end function func_2d
!-------------------------------------------------
end module function_library
!############################################
program try
use subroutine_library
use function_library
call tabulate_function_1d (func_1d)
call tabulate_function_2d (func_2d)
end program try
!############################################
Back to top
View user's profile Send private message
JohnCampbell



Joined: 16 Feb 2006
Posts: 2554
Location: Sydney

PostPosted: Sat Aug 25, 2007 5:50 am    Post subject: Reply with quote

Ludwig,

I must admit it is a long tome since I even had to pass a function as an argument. My preference is to pass an option variable which identifies the function and then provide all the functions in a select case structure. The receiving routine is then limited to the functions it has coded, but has always provided me with sufficient flexibility.

eg

subroutine tabulate_function (func_id)
integer funct_id
..
select case (func_id)
case (1) ! function 1 is sin(x)
case (2) ! function 2 is sqrt(x)

You can then also manage array functions much easier.

As for subroutines, I don't think it makes sence to transfer them as an external. Convert them to an integer function.

It's not somthing I would normally try. I suggest KISS

Good luck,
John
Back to top
View user's profile Send private message
Neo



Joined: 08 Mar 2007
Posts: 19

PostPosted: Sun Aug 26, 2007 9:48 am    Post subject: Thanks for the advice Reply with quote

Greetings John,

Thanks for your comments - much appreciated.

Best regards,
Ludwig
Back to top
View user's profile Send private message
DrTip



Joined: 01 Aug 2006
Posts: 74
Location: Manchester

PostPosted: Mon Aug 27, 2007 9:48 pm    Post subject: array valued functions interface bugs/quirks ????? Reply with quote

Hi Ludwig and Paul

Your question piqued my interest. I actually thought you couldn't do array valued functions at all until I saw your question and looked it up, in the circumstances I would require them for I normally use subroutines with predefined arrays

in this sort of way :

!_____________________________!
subroutine twiddle(arr)
real arr(5)
! set array to 4.0

arr = 4.0

end subroutine

!____________________________!

program subcall

real arr(5)


arr = 0.0

write(*,*) arr


call twiddle(arr)

write(*,*) arr

end program
!_________________________________!

the sub changes the array from 0.0 to 4.0


Anyway I started to play about with the compiler and I think I may have uncovered some compiler bugs in subroutine interfaces or alternatively in my interpretation of the ftn95 documentation and metcalf and reid

I think the following code should be OK according the the documentation on assumed shape arrays
!______________________!
subroutine twiddle(arr)
implicit none

real arr(Smile
write(*,*) size(arr)
arr = 4

end subroutine
!_______________________!
program subcall
implicit none
real arr(5)


arr = 0

write(*,*) arr


call twiddle(arr)

write(*,*) arr


end program
!_______________________!


however the write statement in the subroutine suggests that the array has
13433 elements

I guess in a real example I would code round this somehow passing the size of the array dimensions explicitly or whatever, but I thouht the compiler should handle this without any messing about seting up an interfaces for the call in the program

which finally brings me to array valued functions

the *only* way I could get an array valued function of variable length to work was by using an interface in the calling program thus


!________________________________!
real function arval ()

real arval(5)

arval = 5.0


end function

!_________________________________!
program fnccall
implicit none
real arr(5)


interface
real function arval()
real arval(1)
end function
end interface

arr = 0

write(*,*) arr

arr = arval()

write(*,*) arr

end program
!______________________________________!


now the thing is that the dimension in the return type requires a value but seems to be only there to get the code to compile I was kind of expecting to code

real arval(Smile

in the interface

but this won't compile and the fixed value looks perverse in terms of readability if nothign else

Now I am not a full time fortran guy so apologies if these seem obvious or
trivial.

I guess I am surprised I have to define an interface to get something to work since I have never seen one used in any of the code I have to maintain at work which is on the whole admittedly quite old.

apologies for over long post

Carl
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> General All times are GMT + 1 Hour
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group