Dismiss Notice
Join Physics Forums Today!
The friendliest, high quality science and math community on the planet! Everyone who loves science is here!

Fortran: variables in the list of arguments for Subroutines

  1. Sep 23, 2013 #1
    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
     
  2. jcsd
  3. Sep 23, 2013 #2

    DrClaude

    User Avatar

    Staff: Mentor

    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.
     
  4. Sep 23, 2013 #3

    phinds

    User Avatar
    Gold Member
    2016 Award

    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).
     
  5. Sep 23, 2013 #4

    DrClaude

    User Avatar

    Staff: Mentor

    Fortran is strictly pass by reference.
     
  6. Sep 23, 2013 #5
    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
     
  7. Sep 23, 2013 #6

    DrClaude

    User Avatar

    Staff: Mentor

    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.
     
  8. Sep 23, 2013 #7
    Can you elaborate on this?

    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
     
  9. Sep 23, 2013 #8

    DrClaude

    User Avatar

    Staff: Mentor

    Code (Text):
    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 (Text):

    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 (Text):

    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 (Text):

    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
     
     
  10. Sep 23, 2013 #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
     
  11. Sep 23, 2013 #10

    DrClaude

    User Avatar

    Staff: Mentor

    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.
     
  12. Sep 23, 2013 #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
     
  13. Sep 23, 2013 #12

    Mark44

    Staff: Mentor

    For the simple example above I would have written the adder routine as a function. The code would look something like this:
    Code (Text):
    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.
     
  14. Sep 23, 2013 #13

    SteamKing

    User Avatar
    Staff Emeritus
    Science Advisor
    Homework Helper

    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.
     
  15. Sep 23, 2013 #14

    AlephZero

    User Avatar
    Science Advisor
    Homework Helper

    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.
     
  16. Sep 23, 2013 #15
    Thank you guys for all your advice!

    Lam
     
Know someone interested in this topic? Share this thread via Reddit, Google+, Twitter, or Facebook




Similar Discussions: Fortran: variables in the list of arguments for Subroutines
Loading...