Fortran: variables in the list of arguments for Subroutines

  • Context: Fortran 
  • Thread starter Thread starter nguyenthanhlam
  • Start date Start date
  • Tags Tags
    Fortran List Variables
Click For Summary
SUMMARY

This discussion focuses on the handling of variables in Fortran subroutines, specifically the implications of including or excluding variables in the argument list. It is established that Fortran uses "pass by reference," meaning that omitting a variable from the argument list does not incur performance penalties due to copying values. The consensus is to prefer explicit argument lists for clarity and maintainability, especially in complex programs. Additionally, using modules can reduce flexibility and complicate debugging, so they should be used judiciously.

PREREQUISITES
  • Understanding of Fortran programming language syntax
  • Knowledge of subroutine and module structures in Fortran
  • Familiarity with "pass by reference" and "pass by value" concepts
  • Experience with variable scope and lifetime in programming
NEXT STEPS
  • Research Fortran subroutine argument passing techniques
  • Learn about the implications of using modules in Fortran
  • Explore best practices for variable scope management in Fortran
  • Investigate compiler optimizations for Fortran programs
USEFUL FOR

Fortran developers, software engineers working on scientific computing, and anyone interested in optimizing Fortran code structure and performance.

nguyenthanhlam
Messages
9
Reaction score
0
Hi all,

Suppose I declare X in the main program.

Then in the following subroutine:

Call example(list of arguments)

------------------------------------
subroutine example(list of arguments)

x=y+z

end subroutine
-------------------------------------

I have two options:
(a) including X in the list of argument, then I have to declare X within the subroutine.
(b) not including X in the list of argument, then I do not have to declare X within the subroutine.

I don't know the advantages of one over the other.

Which method should I use?

Thanks,

Lam
 
Technology news on Phys.org
nguyenthanhlam said:
(b) not including X in the list of argument, then I do not have to declare X within the subroutine.
Assuming that you want to know the result of x=y+z in the main program, that won't work. In that case, the x in the main program is not the same variable as in the subroutine.
 
You need to study "pass by reference" and "pass by value". I don't know the FORTRAN conventions for those (or even if it allows both, though I assume it must).
 
phinds said:
You need to study "pass by reference" and "pass by value". I don't know the FORTRAN conventions for those (or even if it allows both, though I assume it must).
Fortran is strictly pass by reference.
 
DrClaude said:
Assuming that you want to know the result of x=y+z in the main program, that won't work. In that case, the x in the main program is not the same variable as in the subroutine.

Here is my test:

=======================
program test
use examp
implicit none

y=1.
z=2.

call calx

print*,'x=',x

end

======================
module examp

implicit none
real x,y,z
contains

subroutine calx

x=y+z

end subroutine

end

=======================

And I got x =3 out in the main program.

Lam
 
Ah, you are using a module. The problem with that approach is that you lose in flexibility. What if you wanted to add w and z instead?

In some cases, where the number of arguments would be too big, passing variables through a module is worth it. But it can make programs more difficult to read and debug. I would suggest avoiding it when possible and passing arguments instead.
 
DrClaude said:
Ah, you are using a module. The problem with that approach is that you lose in flexibility. What if you wanted to add w and z instead?

Can you elaborate on this?

In some cases, where the number of arguments would be too big, passing variables through a module is worth it. But it can make programs more difficult to read and debug. I would suggest avoiding it when possible and passing arguments instead.

Yes, I have quite a lot of arguments for different subroutines. What I did was, I put all the needed arguments in the brackets. Now I want to test, without putting arguments in the brackets would I have the same results, same performance, etc.

Thanks,

Lam
 
nguyenthanhlam said:
Can you elaborate on this?

Code:
program test

real :: w,x,y,z

x = 1.0
y = 3.0

call adder(x,y,z)

! later in the program

w = 10.1 ! (but still y = 1.0)

call adder(x,w,z)

end program test


subroutine adder(a,b,c)

real, intent(in) :: a,b
real, intent(out) :: c

c = a+b

end subroutine adder

To give another example, imagine you want to create a subroutine to perform a Gaussian quadrature (integration) on regularly spaced data. You can write
Code:
subroutine gauss(n,f,dx,gauss_quad)

integer, intent(in) :: n
real, dimension(n), intent(in) :: f
real, intent(in) :: dx
real, intent(out) :: gauss_quad

gauss_quad = (0.5 * (f(1) + f(n)) + sum(f(2:n-1))) * dx

return
end subroutine gauss_quad
which is very flexible: you can reuse to same function in many programs, or in the same program where sometimes you integrate along x (with certain values nx and dx), and sometimes along y (with different values ny and dy).

The disadvantage is if the values of n and dx never change, and you call gauss_quad from within other subroutines, you always have to pass dx to that intermediate subroutine, even if it doesn't need that value:
Code:
subroutine do_something(n,a,b,c,d,f,dx)
...
call gauss_quad(n,a,dx,int_a)
call gauss_quad(n,f,dx,int_f)
...
end subroutine do_something
In that case, it might be best not to carry the dx everywhere and use something like
need that value:
Code:
module gauss_quad_mod
integer :: n
real :: dx
end module gauss_quad_mod


program test
use gauss_quad_mod
...
n = 1024
dx = (x2-x1)/(n-1)
...
call do_something(n,a,b,c,d,f)
...
end program test


subroutine do_something(n,a,b,c,d,f)
...
call gauss_quad(a,int_a)
call gauss_quad(f,int_f)
...
end subroutine do_something


subroutine gauss(f,gauss_quad)
use gauss_quad_mod

real, dimension(n), intent(in) :: f
real, intent(out) :: gauss_quad

gauss_quad = (0.5 * (f(1) + f(n)) + sum(f(2:n-1))) * dx

return
end subroutine gauss_quad
 
Thanks DrClaude,

I see your point.

In my case I have a program structured like this:

===============================

do n=1,100000000

call sub1(list_of_arg_1)

call sub2(list_of_arg_2)

...

end do

============================

List 1 is used for Sub1, list2 is used for sub2, etc. This is the main theme in my program.

I just have few steps using different lists of arguments for the same subroutine, something like in your example:

call thesamesub(list_of_arg_1)

call thesamesub(list_of_arg_2)

So I wonder, for those many subroutines which always use the same lists of arguments, if I omit the list of arguments would I gain speed in running my program?

Thanks,

Lam
 
  • #10
nguyenthanhlam said:
So I wonder, for those many subroutines which always use the same lists of arguments, if I omit the list of arguments would I gain speed in running my program?
Most probably not. As I posted earlier, all variables are passed by reference, which means that there is no overhead with copying values in memory. Compiler optimization (in particular inlining) will take care of eliminating most other performance costs in such a situtation, as far as I know.
 
  • #11
Thanks,

If so, I should have explicit lists of arguments then. Actually, I don't have to change anything to my program, it's already been that way :)).

Lam
 
  • #12
DrClaude said:
Code:
program test

real :: w,x,y,z

x = 1.0
y = 3.0

call adder(x,y,z)

! later in the program

w = 10.1 ! (but still y = 1.0)

call adder(x,w,z)

end program test


subroutine adder(a,b,c)

real, intent(in) :: a,b
real, intent(out) :: c

c = a+b

end subroutine adder

For the simple example above I would have written the adder routine as a function. The code would look something like this:
Code:
program test

  real :: w, x, y, z, sum

  x = 1.0
  y = 3.0

  z = sum(x, y)
  [STRIKE]call adder(x,y,z)[/STRIKE]

  ! later in the program

  w = 10.1 ! (but still y = 1.0)

  z = sum(x, w)
  [STRIKE]call adder(x,w,z)[/STRIKE]
end program test


function sum(a, b)

  real, intent(in) :: a, b

  return a + b

end function adder
Caveat: This code probably compiles and runs correctly, but I haven't had a Fortran compiler for a number of years, so haven't tested it.
 
  • #13
It used to be that, if you had a program with subroutines which required the use of a large number of variables, instead of passing the variables to the subroutine using argument lists, you would create static data areas using a COMMON statement or statements and include the COMMON statements in the subroutine. This worked especially well when large programs had to be overlaid due to small computer memories.
 
  • #14
Your option (b) of putting making "all" your variables accessible everywhere is a very bad idea. The main problem is that one day you will forget you were already using a variable named something like X, and use it again for something else. Your code will compile and run, but it won't give the right answers!

If you are just starting to learn programming, get into the good habit of only using variables that are "local" to each subroutine, and passing all the information that a subroutine needs through the parameter list.

Eventually, (e.g. when you are working on programs that are 100,000 lines long rather than 100 lines) you might find some good reasons to declare variables inside a module (for example, to make them available to all the subroutines in the module, but to hide them from everything outside of it). But using language options like that "just because you can" is usually a bad idea.
 
  • Like
Likes   Reactions: 1 person
  • #15
Thank you guys for all your advice!

Lam
 

Similar threads

  • · Replies 20 ·
Replies
20
Views
3K
  • · Replies 2 ·
Replies
2
Views
2K
  • · Replies 59 ·
2
Replies
59
Views
11K
  • · Replies 8 ·
Replies
8
Views
2K
  • · Replies 3 ·
Replies
3
Views
2K
  • · Replies 8 ·
Replies
8
Views
4K
  • · Replies 25 ·
Replies
25
Views
3K
  • · Replies 2 ·
Replies
2
Views
3K
  • · Replies 4 ·
Replies
4
Views
3K
  • · Replies 14 ·
Replies
14
Views
3K