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

Clear a variable in fortran subroutine

  1. Jan 28, 2015 #1
    Hello,

    I am trying to figure out how to clear a variable inside a subroutine from a calling function. The variable in the subroutine acts as a persistent(MATLAB) or static(C), but once in so many calls I want it to be reset to empty as if the subroutine is being called for the first time.

    I can do this in MATLAB by calling the subroutine in a for loop. On the kth run, clear functions, call subroutine. The subroutine is now called with persistent variables cleared:

    function y = foo(a)
    n = 6;
    k = 3;
    for ii = 1:n
    if ii == k
    clear functions​
    end
    x(ii) = subfoo(a)​
    end

    Any help would be appreciated,

    Candice
     
  2. jcsd
  3. Jan 28, 2015 #2
    Go ahead and post your Fortran code to get a better understanding of what you mean and are trying to do.

    Other than that, you could write your function in a way that takes an additional argument, say, of logical type...if it is set to true, the function behaves as if it was the very first time is being called; if it is false, it does not.

    Alternately, you could write a module with its set of variables and a couple of functions, one you call to perform something, the other one to reset variables to their initial values.
     
  4. Jan 28, 2015 #3
    Hi gsal, thank you for your response.

    Unfortunately, I cannot post my code, and I cannot modify the subroutine in any way (I am unit testing it).

    If I write a module with its set of variables to reset to initial values, can I call that from my parent function? Or are those variable names only pointing to the correct place in memory while in the subroutine? I cannot reset the variables inside my subroutine as I cannot modify my subroutine.
     
  5. Jan 28, 2015 #4
    I was thinking something like this
    Code (Text):

    module bla
    integer :: b = 0
    contains
    subroutine bla_reset()
       b = 0
    end subroutine bla_reset()
    function bla_do()
       b = b + 3
       return b
    end function bla_do()
    end module bla
     
    Then, in reference to your matlab code that you posted above, instead of "clear functions" you do "call bla_reset()" and instead of "x(ii) = subfoo(a)" you do "x(ii) = bla_do(a).
     
  6. Jan 28, 2015 #5
    will this work if the variable b belongs solely to (and is not returned by) bla_do? In my subroutine (bla_do), it is declared equal to 1. Like this:
    Code (Text):

    module bla
    integer  b
    contains
    subroutine bla_reset()
       b = 1
    end subroutine bla_reset()
    function bla_do()
    integer  b \1\
       b = b + 3
    end function bla_do()
    end module bla
     
    I'm learning on-the-fly how fortran's "workspace" (for lack of a better term) is available between functions.
     
  7. Jan 28, 2015 #6
    I would remove the integer declaration inside bla_do...otherwise, it looks like you keep re-initailizing it every call...instead, let it keep increasing by 3 every time you call ...then, once in a while, you call bla_reset...

    ...if I understand what you are trying to do
     
  8. Jan 28, 2015 #7
    Because I am testing bla_do(), I can't modify it. So I can't remove the declaration in the beginning. But I am certain that the way the fortran is set up in my real code, that variable is declared equal to 1 only on the first iteration ; thereafter it takes on the last value when the function was called previously.

    My intention, is to (at some point inside a forloop that calls bla_do) reset that variable so when bla_do() is called, it acts as it would the first time it is called. It's a weird thing to need; it is an artifact of testing bla_do rather than developing.

    Code (Text):

    module bla
    integer  b
    for i = 1:100
    if i = 50
       CALL bla_reset() //reset b back to 1 at iteration 50
    endif
    CALL bla_do() // do whatever blah does
    end module bla

    subroutine bla_reset()
       b = 1
    end subroutine bla_reset()
    subroutine  bla_do()
    integer  b \1\ //this syntax should set b = 1 only on first call; otherwise b retains value from last call (or hopefully from when it is set to 1 in bla_reset)
       b = b + 3
    end subroutine bla_do()

     
    I'm curious that b can be reset in the separate subroutine bla_reset and it is felt by bla_do, even when bla_reset and bla_do don't have b as input or output arguments.
     
  9. Jan 28, 2015 #8
    This thing about bla_reset and bla_do not needing to declare b, yet being aware of it, is a benefit of using modules...but I see in your latest post that you have messed things up :-(

    First, you have kicked bla_reset and bla_do out of the module...you should go back and review how I did it...inside the module but after the "contains" keyword.

    Also, a module is not a main program...you should take the code you have in the module (latest post) and make it a separate main procedure, like
    Code (Text):

    module bla
    .
    .
    .
    end module bla

    program main
       use bla
       for i = 1:100
       if i = 50
          CALL bla_reset() //reset b back to 1 at iteration 50
       endif
       CALL bla_do() // do whatever bla does
    end program main
     
     
  10. Jan 29, 2015 #9
    Ah, I see. Unfortunately bla_do() is a subroutine, and I can't touch it (I must view it as a black box), so I can't change it into a module. I think because of this problem, I can't use the method you are suggesting.
     
  11. Jan 31, 2015 #10

    FactChecker

    User Avatar
    Science Advisor
    Gold Member

    If the persistent variables are in a global common block, you can easily include them and clear them using another subroutine. Otherwise, you may have to get the address of the persistent variables by finding the addresses in the binary or compiler outputs and write a subroutine that pokes initial values into those addresses. The first situation is not a difficult task for any programmer, but the second situation will require a more expert programmer. I'm afraid that your code is probably the second situation.

    You may be better off with a script or program that will terminate the program under test and restart it clean. That is the best way to do a series of formal tests anyway.
     
  12. Feb 2, 2015 #11
    Hi FactChecker; thank you for your response. Yes it now seems that I will run the unit tests under several use-cases and try to merge the profiling results.
     
Know someone interested in this topic? Share this thread via Reddit, Google+, Twitter, or Facebook