Fortran: variables in the list of arguments for Subroutines

In summary, the problem is that you lose flexibility by using a module. If you need to reuse the 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), using a module can be a good choice. But it can make programs more difficult to read and debug.
  • #1
nguyenthanhlam
9
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
  • #2
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.
 
  • #3
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).
 
  • #4
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.
 
  • #5
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
 
  • #6
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.
 
  • #7
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
 
  • #8
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
 
  • #9
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 1 person
  • #15
Thank you guys for all your advice!

Lam
 

FAQ: Fortran: variables in the list of arguments for Subroutines

What is the purpose of using variables in the list of arguments for Fortran subroutines?

Variables in the list of arguments for Fortran subroutines allow for passing data between the main program and the subroutine. This allows for the subroutine to manipulate the data and return the results to the main program.

How are variables declared in the list of arguments for Fortran subroutines?

Variables in the list of arguments for Fortran subroutines are declared using the "intent" keyword, followed by the type of variable and its name. For example, "intent(in) :: variable_name" would declare a variable as an input parameter.

Can variables in the list of arguments be modified within the Fortran subroutine?

Yes, variables in the list of arguments can be modified within the Fortran subroutine. However, the "intent" keyword must be specified to indicate whether the variable is an input or output parameter. If a variable is declared as "intent(in)", it cannot be modified within the subroutine.

How many variables can be included in the list of arguments for a Fortran subroutine?

There is no limit to the number of variables that can be included in the list of arguments for a Fortran subroutine. However, care should be taken to ensure that the subroutine is not too complex and that the variables are used efficiently.

Can arrays be used as variables in the list of arguments for Fortran subroutines?

Yes, arrays can be used as variables in the list of arguments for Fortran subroutines. They can be declared in the same way as other variables, using the "intent" keyword and specifying the size and type of the array.

Similar threads

Replies
2
Views
2K
Replies
59
Views
10K
Replies
3
Views
2K
Replies
8
Views
4K
Replies
25
Views
2K
Replies
4
Views
2K
Replies
14
Views
2K
Back
Top