Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

problem with functions and subroutines that returns arrays 1

Status
Not open for further replies.

tesaoghost

Programmer
Jan 9, 2014
11
Hi everybody
I have a little problem with functions and subroutines in fortran! I want to write a program that takes one or more array in main program, then sends this arrays to a function or subroutine and return an array to main function again. For example consider a program that takes (a) and (b) arrays in main program, sends them to a function which returns multiple of a and b matrices as a 2D array. I wrote this program using internal function:

program Matrix_Operation
implicit none
real :: a(20,20),b(20,20),mult(20,20)
integer :: i,j,n

n = 2

read *,((a(i,j),i=1,n),j=1,n)
read *,((b(i,j),i=1,n),j=1,n)

mult = matrix_multiple(a,b,n)

print *,"A * B ="
Do i=1,n
print "(100(F10.4,TR3))",(mult(i,j),j=1,n)
End Do


!*****************************************
! Multiplier Function Definition
!*****************************************
contains
function matrix_multiple(x,y,n)
implicit none

real,intent(in) :: x(20,20),y(20,20)
integer,intent(in) :: n
real :: m(20,20),matrix_multiple(20,20)
integer :: i,j,k

Do i=1,n
Do j=1,n
Do k=1,n
m(i,j) = m(i,j)+x(i,k)*y(k,j)
End Do
End Do
End Do

matrix_multiple = m

End function matrix_multiple

!*****************************************
! End of Function Definition
!*****************************************

End program Matrix_Operation


but I want to know is there any way to write this program using external functions i.e. a function that its determination is after main program?
 
tesaoghost said:
...I want to know is there any way to write this program using external functions i.e. a function that its determination is after main program?
The function you use in example above is dafined with contains after the main program.
But you mean probably a function defined in a separate source file. If so it's possible. You have to compile all source files and link them together.
 
I think you using MODULE can save your life or better, something like this:
!*****************************************
! Multiplier Function Definition
!*****************************************
MODULE matrix_module
contains
function matrix_multiple(x,y,n)
implicit none

real,intent(in) :: x(20,20),y(20,20)
integer,intent(in) :: n
real :: m(20,20),matrix_multiple(20,20)
integer :: i,j,k

Do i=1,n
Do j=1,n
Do k=1,n
m(i,j) = m(i,j)+x(i,k)*y(k,j)
End Do
End Do
End Do

matrix_multiple = m

End function matrix_multiple
END MODULE matrix_module
!*****************************************
! End of Function Definition
!*****************************************


program Matrix_Operation
USE matrix_module
implicit none
real :: a(20,20),b(20,20),mult(20,20)
integer :: i,j,n

n = 2

read *,((a(i,j),i=1,n),j=1,n)
read *,((b(i,j),i=1,n),j=1,n)

mult = matrix_multiple(a,b,n)

print *,"A * B ="
Do i=1,n
print "(100(F10.4,TR3))",(mult(i,j),j=1,n)
End Do

End program Matrix_Operation
 
mikrom said:
The function you use in example above is dafined with contains after the main program.
Thanks a lot mikrom
No i meant a function that defined after:
Code:
program Matrix_Operation
.
.
.
End program Matrix_Operation

the program I wrote above is defined inside main program:

Code:
program Matrix_Operation
.
.
    contains
    function matrix_multiple(x,y,n)
    .
    .
    .
    End function matrix_multiple
    
End program Matrix_Operation
Is it possible to define a external function i.e after end program line that could return an array or not?
 
j0zn said:
I think you using MODULE can save your life or better, something like this:
Thanks a lot again
your code is working but there is a little problem. I have to send an array to a module, the array sends it to a function and then return answer. This process is time consuming in large matrices like those we deal with in mechanics!
It seems that there is no way!
:(

 
tesaoghost: "It seems that there is no way!"....really, tesaoghost? Fortran has been doing matrix manipulation for decades for engineers, physicists, astronomers and other scientists around the world...and you think Fortran is not good enough for you for a multiplication? please, have a little faith.

How do you know that your program is not fast enough?
Do you know that for a fact?
What's your measurement, your reference?

Before Fortran 90, this "not having to pass" a matrix around was solved with a common block.

In Fortran 90, there is a way to make it look like you are not having to pass a matrix around and that is by moving your matrix variable declarations line from the main program to the module...heck, if I remember correctly, I think in this case your matrix_multiple function could even be written to take no arguments whatsoever.

The things is that even your present program is not passing a matrix around since Fortran operates under the "pass by reference" principle; so, when you "pass" a matrix as an argument to a function, it is not passing a million numbers, it is simply passing one (or so) piece(s) of information. I do not say that when passing a matrix it is only one number (memory address) that is being pass because, many years ago, I run into something that make me realized (and then confirmed) that matrices in Fortran are not necessarily simple variables...they are a bit more than that and some extra information.



 

"Look, mom...no arguments"

Code:
!*****************************************
! Vector/Matrix Manipulation Module
!*****************************************
MODULE matrix_module

integer :: n
real :: a(20,20),b(20,20),mult(20,20)

contains

subroutine matrix_multiple()
    implicit none
    integer :: i,j,k

    Do i=1,n
        Do j=1,n
            Do k=1,n
                mult(i,j) = mult(i,j)+a(i,k)*b(k,j)
            End Do
        End Do
    End Do
End subroutine matrix_multiple

END MODULE matrix_module

!*****************************************
! Main Program
!*****************************************
program Matrix_Operation
USE matrix_module
implicit none
integer :: i,j

n = 2
read *,((a(i,j),i=1,n),j=1,n)
read *,((b(i,j),i=1,n),j=1,n)

call matrix_multiple()

print *,"A * B ="
Do i=1,n
print "(100(F10.4,TR3))",(mult(i,j),j=1,n)
End Do

End program Matrix_Operation
 
thanks for your attention again. I don't mean that fortran is not good or do not work well. i am one of the fans of fortran and I prefer fortarn to other new programming languages. This is not serious problem so I don't pay attention to it and i don't search enough to find the solution. So i can run my program in this case. And when I told you that sending a matrix to a module and then sending it to a matrix may be time consuming, (especially for matrices that I deal with and sometimes their dimension is about 5000*5000) but you say that there is not problem.
Thanks a lot for your help :)
And one another question, which version of fortran do you use? I used to use microsoft powerstation 4 but it is not compatible with windows 7 so now I have to use PGI visual fortran 2010. I want to know is it the only official version of fortran that is compatible with windows 7?
 
tesaoghost said:
sending a matrix to a module and then sending it to a matrix may be time consuming, (especially for matrices that I deal with and sometimes their dimension is about 5000*5000)
Don't worry - it's not true :) It doesn't matter if the Matrix is 5*5 or 5000*5000, because only memory address of the matrix will be passed to the subroutine/function (and maybe some other data - as Salgerman said). I thought that Fortran uses simply Call by reference, but after I read salgerman's post I found at wikipedia that it's special case of it - so called Call by copy-restore
 
Dear mikrom and salgerman
Thanks a lot for your Illustrations.
But now I have another problem! :(
My responsible professor told me that coding with fortran will be faster than any language especially matlab because other languages use more interfaces than what fortran used. For example if you want to write a code to inverse a huge matrix using matlab, matlab first compiles your data to C, Then the data is compiled into fortran interface, then it is compiled into assembly i.e the machine language and then it is processed. So if I use a language that is closer to the machine language It will be faster to perform calculations.
Because of this reason I choosed fortran for my calculations that is closest interface in to machine language. Now I have written about 2000 lines for my thesis and find out a really terrible fact!!!! Once I try to test the speed of my code and compare it with matlab, but unbelievably I understand that there is a giant difference between matlab and fortran speed. I have tried to inverse a 3000*3000 matrix using matlab and my code which used Gaussian elimination method. calculating inverse matrix by my code takes about 6 minute while matlab do it in only 6 seconds!!!! :0
I don't know that there is problem with my code or I am using a wrong version of fortran. I am using PGI visual fortran 2010 and I think that its visual interface delays calculation. Would you please guide me?
Thanks alot
 
tesaoghost said:
For example if you want to write a code to inverse a huge matrix using matlab, matlab first compiles your data to C, Then the data is compiled into fortran interface, then it is compiled into assembly i.e the machine language and then it is processed.
Maybe it's so, but don't forget that the compilation will be done only one time at the beginning and if matlab uses better algorithm then the execution could be faster.

tesaoghost said:
Once I try to test the speed of my code and compare it with matlab, but unbelievably I understand that there is a giant difference between matlab and fortran speed. I have tried to inverse a 3000*3000 matrix using matlab and my code which used Gaussian elimination method. calculating inverse matrix by my code takes about 6 minute while matlab do it in only 6 seconds!!!! :0
Well, it could have several causes - for examle:
1. Maybe Matlab uses better algorithm for computing the inverse. Be sure that your progrsm cannot so easy compete with speed and accuracy of professional optimized software. But try to find out which method for finding inverse they use in Matlab.

2. The speed of your program can depend of the options used by compilation. Compilers have several optimization options. For example gfortran support these Options That Control Optimization. Try to find out the optimization options for your compiler, try to recompile it and maybe you will see some difference. But I cannot believe that your program which uses basic numerical methods will be faster that the professional system like Matlab.
 

When I program a matrix inversion, I design my model and node numbering in a way that would produce a banded matrix, i.e., only 'nearby' (numbering point of view) nodes connect to each other; then, I use simple, specialized algorithm for storage and solution of the system...so, I know I am ignoring the entire part of the matrix outside the band (the majority of it).

A few random comments:

I have not used matlab in over 20 years; back then, matlab was not faster than a compiled language.

Matlab cold be faster than your code if you are programming your own...but, if you would take advantage of existing libraries that have been developed over a few years and put together by experts, "your own" program will become much faster.

One popular library is LAPACK.

On the fly code in matlab could very well be compiled but linear algebra operations are already compiled and guess what...matlab uses LAPACK behind the scenes...furthermore...guess what, LAPACK is written in Fortran 90.

So, you could download LAPACK and compiled your own fortran program taking advantage of one of the best linear algebra libraries around.








, thus reducing bandwidth
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top