How can I properly use function calls in Fortran 90?

In summary, JellyKing's code uses a six-dimensional real (REAL(6)) function with a rank (1) intent, but when he tries to call the function, he gets an error. JellyKing has worked around the function call by using routines, so instead of a line like output = rk(input,parameters) he uses CALL rk(input,parameters,output) to get around the error. He also includes an interface block which might be better for his case.
  • #1
JellyKing
2
0
Hi all,

I'm new to Physics Forums, but not to physics, since I'm now doing my MSc. I've had a persistent problem in a segment of my Fortran code that I've worked around, but would like to fix.

The long and short is that I'm integrating a six-dimensional ODE with a fourth-order Runge-Kutta method.* I've tried to do it with function calls as follows. In the main program body, there will be a line to iterate the solution one step, using some function I call rk. I'd like the line of code to be something like
Code:
output = rk(input, parameters)
Sure enough, after the END program, I have the function, initiated by
Code:
FUNCTION rk(inputx,parametersx)
REAL(6) :: rk,...
...
rk = ...
END FUNCTION
In the opening lines, I'll declare that rk is a six-dimensional real (REAL(6)). That's fine. However, when I try to call it as above, I get an error like

Error: FUNCTION 'rk' is of rank (1) at {function declaration} and rank (0) and {function call}.

Okay, so I figure I need to tell the program that rk is going to be a REAL(6). But now the compiler tries to parse the arguments as array indices, so I'll get an error like


v = rk(w,E,L,Q,a,dtau)
...1
Error: Array index at (1) must be of INTEGER type


I haven't had this problem with functions that return scalars. For now, I've worked around the function calls by using routines, so that instead of a line like

Code:
output = rk(input,parameters)

I use

Code:
CALL rk(input,parameters,output)

Sorry this is a long post, and if there are any other details that will help find a solution just ask. Thanks in advance for any help you can provide. This has been bugging me for a while.

JK

*I can't for the life of me work out how one is supposed to import other people's modules, but that's another story.
 
Technology news on Phys.org
  • #2
Hi JellyKing,

There's not much program in your code to go on, but I guess my first question is do you have an explicit interface to the function? That could be the source of the error.

If not, probably the easiest thing is to show you a working case in case it's helpful; here is a trivial program that uses an array-valued function as an internal procedure (just takes an array and adds 1 to each element):

Code:
PROGRAM array_valued_functions
implicit none
integer::i
integer,dimension(5)::a,b

b=(/ (i,i=1,5) /)
a=addone(b)
print*,a

contains

function addone(x)
implicit none
integer,dimension(:),intent(in)::x
integer,dimension(size(x))::addone

addone=x+1
end function addone

end program array_valued_functions

Here is the same example with an interface block which might be better for your case:

Code:
PROGRAM array_valued_functions
implicit none
integer::i
integer,dimension(5)::a,b


interface
function addone(x)
integer,dimension(:),intent(in)::x
integer,dimension(size(x))::addone
end function addone
end interface


b=(/ (i,i=1,5) /)
a=addone(b)
print*,a

end program array_valued_functions


function addone(x)
implicit none
integer,dimension(:),intent(in)::x
integer,dimension(size(x))::addone

addone=x+1
end function addone


If you still have trouble, could you perhaps write a toy program that shows the behavior you're talking about and post it here?
 
  • #3
Okay, here's something that reproduces the error.

Code:
PROGRAM toy
	REAL, DIMENSION(2) :: z
	
	z(1) = 1
	z(2) = 2
	
	z = array_valued_function(z)
	PRINT *, z
	
END PROGRAM toy

FUNCTION array_valued_function(x)
	REAL, DIMENSION(2) :: array_valued_function,x
	
	array_valued_function = x+1
END FUNCTION

I already notice you making use of a couple of structures I had no idea about. I've never seen interface or contains before. I am fairly new to Fortran, from a smattering of Java, C++, a bit more Python, and a lot of MATLAB. If I include IMPLICIT NONE, I'm told array_valued_function has no implicit type. If I supplant

Code:
REAL :: array_valued_function(2)

I get back to my error of the compiler wanting the argument of the function to be an index of the array (described in my first post).

I'll look up those interface and contains structures when I get back to this particular problem. Thanks for the help though! :)

JK
 
  • #4
Then that would be the error; array-valued function require an explicit interface, which can be given in three ways: putting the function in a module and using a corresponding USE statement, making the function an internal subprogram with a CONTAINS statement, or using an interface block in the main (calling) program.

To get your toy program running you might use:

Code:
PROGRAM toy
	REAL, DIMENSION(2) :: z

interface
     FUNCTION array_valued_function(x)
     implicit none
     REAL, DIMENSION(2) :: array_valued_function,x
     end function array_valued_function
end interface


	
	z(1) = 1
	z(2) = 2
	
	z = array_valued_function(z)
	PRINT *, z
	
END PROGRAM toy

FUNCTION array_valued_function(x)
	REAL, DIMENSION(2) :: array_valued_function,x
	
	array_valued_function = x+1
END FUNCTION
 
Last edited:
  • #5
Hello and thanks for your info about use of INTERFACE in fortran.

I have a question:

I have a main code within which I have used an external extrinsic function. I have coped and pasted both here:
THIS IS THE MAIN CODE
program matrix
implicit none
double precision, dimension(3,3) :: A
double precision, dimension(3,1) :: B
double precision :: X(3)

integer :: m ! SEE HERE PLEASE

interface
function X_Part_Piv(A,B,n)
double precision, allocatable :: AUG(:,:),AUGP(:,:),AUX1(:,:),AUX2(:,:)
integer :: n,p,k,r,m,o,s
double precision :: big,factor,matrmultip,X_Part_Piv(n),A(n,n),B(n,1)
end function X_Part_Piv
end interface

A(1,1)=9
A(1,2)=33
A(1,3)=-3
A(2,1)=0
A(2,2)=9
A(2,3)=11
A(3,1)=.2
A(3,2)=23
A(3,3)=15
B(1,1)=0
B(2,1)=4
B(3,1)=6

m=size(A,2)! SEE HERE PLEASE

X=X_Part_Piv(A,B,m)

end program matrix

THIS IS THE FUNCTION

function X_Part_Piv(A,B,n)
implicit none

double precision, allocatable :: AUG(:,:),AUGP(:,:),AUX1(:,:),AUX2(:,:)
integer :: n,p,k,r,m,o,s
double precision :: big,factor,matrmultip,X_Part_Piv(n),A(n,n),B(n,1)

n=size(A,2)
p=n+1
allocate (AUG(n,n+1))
do m=1,n
AUG(m,n+1)=B(m,1)
do o=1,n
AUG(m,o)=A(m,o)
end do
end do

allocate (AUGP(n,n+1))

do k=1,n-1

big=maxval(abs(AUG(k:n,k)))
s=maxloc(abs(AUG(k:n,k)),dim=1)!dim=1 enforces the max loc of a an (n,1) matrix to be found
r=s+k-1

if (r/=k) then
AUGP=AUG
AUG(k,:)=AUGP(r,:)
AUG(r,:)=AUGP(k,:)
end if

do m=k+1,n

factor=AUG(m,k)/AUG(k,k)
AUG(m,k:p)=AUG(m,k:p)-factor*AUG(k,k:p)

end do

end do

X_Part_Piv(n)=AUG(n,p)/AUG(n,n)

do m=n-1,1,-1
allocate (AUX1(1,n-m))
allocate (AUX2(n-m,1))
AUX1(1,1:n-m)=AUG(m,m+1:n)
AUX2(1:n-m,1)=X_Part_Piv(m+1:n)
matrmultip=0
do o=1,n-m
matrmultip=matrmultip+AUX1(1,o)*AUX2(o,1)
end do
X_Part_Piv(m)=(AUG(m,p)-matrmultip)/AUG(m,m)
deallocate(AUX1)
deallocate(AUX2)
end do
end function X_Part_Piv


My function has three arguments A,B, and n. n is basically the size of A, so it depends on A.

I cannot omit n from my function`s argument. I have done many try and errors to be able to have X_Part_Piv(A,B) instead of X_Part_Piv(A,B,n)

Can anybody help me with that?
 

1. What is a function call in Fortran 90?

A function call in Fortran 90 is a statement that invokes a specific function in a program. It allows the program to pass arguments to the function and receive a return value from the function.

2. How do you declare and define a function in Fortran 90?

To declare a function in Fortran 90, you use the FUNCTION statement, which specifies the name, arguments, and return type of the function. To define the function, you use the END FUNCTION statement after the function body.

3. Can a Fortran 90 function have multiple return values?

Yes, a Fortran 90 function can have multiple return values, but they must be declared using the RESULT keyword in the function declaration. This allows the function to return multiple values through its arguments.

4. How do you pass arguments to a function in Fortran 90?

Arguments can be passed to a function in Fortran 90 either by value or by reference. By value means that the value of the argument is passed to the function, while by reference means that the address of the argument is passed to the function.

5. Can a Fortran 90 function call itself recursively?

Yes, a Fortran 90 function can call itself recursively, as long as it has a condition that will eventually terminate the recursion. However, excessive use of recursive function calls can lead to performance issues and should be used with caution.

Similar threads

  • Programming and Computer Science
Replies
4
Views
589
  • Programming and Computer Science
Replies
4
Views
1K
  • Programming and Computer Science
Replies
20
Views
1K
  • Programming and Computer Science
Replies
29
Views
1K
  • Programming and Computer Science
Replies
15
Views
2K
  • Programming and Computer Science
Replies
8
Views
1K
  • Programming and Computer Science
Replies
8
Views
3K
  • Programming and Computer Science
Replies
3
Views
1K
  • Programming and Computer Science
Replies
2
Views
680
  • Programming and Computer Science
Replies
12
Views
2K
Back
Top