- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi everybody,
I have a problem when passing an external function which has an array as an output argument. In its host module, the size of this array is defined. However, when I pass it as an argument to a procedure in a different module, I cannot define its output size in the interface block.
To illustrate, this is a example code that doesn't work.
If I compile this with ifort, it compiles but I get segmentation fault during runtime.
I usually fix this by passing an additional argument to the function which will specify its output length, but this is normally unnecessary information on the side of the actual function.
So, this code works fine.
Is there any way of doing this with without passing this additional argument?
Thanks a lot!
Grgur
I have a problem when passing an external function which has an array as an output argument. In its host module, the size of this array is defined. However, when I pass it as an argument to a procedure in a different module, I cannot define its output size in the interface block.
To illustrate, this is a example code that doesn't work.
[plain]module solver_mod
implicit none
integer :: nx,ny
contains
subroutine do_something(func)
implicit none
interface
subroutine func(x,y)
implicit none
real,intent(in) :: x(:)
real,intent(out) :: y(:)
end subroutine func
end interface
real,allocatable :: x(:),y(:)
integer :: i
allocate(x(nx),y(ny))
forall (i = 1:nx) x(i) = 1.2*i
call func(x,y)
print *,' do_something: x = ',x
print *,' do_something: y = ',y
end subroutine do_something
end module solver_mod
!------------------------------
! MAIN PROGRAM
!------------------------------
program test_func_passing
use solver_mod
implicit none
real,allocatable :: x(:),y(:)
integer :: i
nx = 3
ny = 2
allocate(x(nx),y(ny))
forall (i = 1:nx) x(i) = 1.2*i
call test_problem(x,y)
print *,' x = ',x
print *,' y = ',y
call do_something(test_problem)
contains
subroutine test_problem(x,y)
implicit none
real,intent(in) :: x(:)
real,intent(out) :: y(ny)
integer :: i
forall (i = 1:ny) y(i) = i*sum(x)
print *,' test_problem: calculated y = ',y
end subroutine test_problem
end program test_func_passing [/plain]
If I compile this with ifort, it compiles but I get segmentation fault during runtime.
I usually fix this by passing an additional argument to the function which will specify its output length, but this is normally unnecessary information on the side of the actual function.
So, this code works fine.
[plain]module solver_mod
implicit none
integer :: nx,ny
contains
subroutine do_something(func)
implicit none
interface
subroutine func(x,ny,y)
implicit none
real,intent(in) :: x(:)
integer,intent(in) :: ny
real,allocatable,intent(out) :: y(:)
end subroutine func
end interface
real,allocatable :: x(:),y(:)
integer :: i
allocate(x(nx),y(ny))
forall (i = 1:nx) x(i) = 1.2*i
call func(x,ny,y)
print *,' do_something: x = ',x
print *,' do_something: y = ',y
end subroutine do_something
end module solver_mod
!-----------------------------
! MAIN PROGRAM
!-----------------------------
program test_func_passing
use solver_mod
implicit none
real,allocatable :: x(:),y(:)
integer :: i
nx = 3
ny = 2
allocate(x(nx),y(ny))
forall (i = 1:nx) x(i) = 1.2*i
call test_problem(x,ny,y)
print *,' x = ',x
print *,' y = ',y
call do_something(test_problem)
contains
subroutine test_problem(x,ny,y)
implicit none
real,intent(in) :: x(:)
integer,intent(in) :: ny
real,allocatable,intent(out) :: y(:)
integer :: i
allocate(y(ny))
forall (i = 1:ny) y(i) = i*sum(x)
print *,' test_problem: calculated y = ',y
end subroutine test_problem
end program test_func_passing [/plain]
Is there any way of doing this with without passing this additional argument?
Thanks a lot!
Grgur
Link Copied
4 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Quoting - gtokic
[plain] subroutine test_problem(x,y)
implicit none
real,intent(in) :: x(:)
real,intent(out) :: y(ny)
integer :: i
forall (i = 1:ny) y(i) = i*sum(x)
print *,' test_problem: calculated y = ',y
end subroutine test_problem
end program test_func_passing [/plain]
in the first piece of code (above), you have
[plain]real,intent(out) :: y(ny)[/plain]
instead of just "real,intent(out) :: y(:)"
and then you use "ny" again but I don't see how the subroutine knows about it. Am I overlooking something?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Quoting - rreis
in the first piece of code (above), you have
[plain]real,intent(out) :: y(ny)[/plain]
instead of just "real,intent(out) :: y(:)"
and then you use "ny" again but I don't see how the subroutine knows about it. Am I overlooking something?
Hi Ricardo,
I'm not sure whether you're overlooking something or am I. The subroutine test_problem knows about ny since it's internal subroutine of the main program where ny is defined. Or at least that's my understanding. But since it doesn't work that way, I'm probably wrong. So any ideas would be really helpful.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Quoting - gtokic
Hi Ricardo,
I'm not sure whether you're overlooking something or am I. The subroutine test_problem knows about ny since it's internal subroutine of the main program where ny is defined. Or at least that's my understanding. But since it doesn't work that way, I'm probably wrong. So any ideas would be really helpful.
Yes, but think about when test_problem is COMPILED - what is the value of NY at compile-time? It's undefined.
I'm surprised the compiler didn't flag an error for this, as the value of NY must be defined at compile time (as in a PARAMETER statement) OR NY has to be passed as an parameter so the compiler knows to resolve the array at runtime.
And as Ricardo pointed out, the fix is to simply say
real, intent(out) :: y(:)
so the compiler knows that this array is resolved at runtime.
I'll get a bug report on this, as an error message from the compiler would have helped.
ron
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Quoting - Ronald Green (Intel)
Yes, but think about when test_problem is COMPILED - what is the value of NY at compile-time? It's undefined.
I'm surprised the compiler didn't flag an error for this, as the value of NY must be defined at compile time (as in a PARAMETER statement) OR NY has to be passed as an parameter so the compiler knows to resolve the array at runtime.
And as Ricardo pointed out, the fix is to simply say
real, intent(out) :: y(:)
so the compiler knows that this array is resolved at runtime.
I'll get a bug report on this, as an error message from the compiler would have helped.
ron
Thanks, I just realized what you're both saying. I thought I have to assign output size of the array, I didn't think it can take the size from the actual argument. Now that I run it with real,intent(out) :: y(:) it works.
Thanks a lot!
Grgur
Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page