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

Fortran functions query

  1. Oct 28, 2015 #1
    Hi all

    Just to start with I should highlight my general ineptitude with programming, so I apologize if my question is totally basic.

    I have a program written (by someone else) in fortran 77. Contained within it is a call to a function which acts on a number of variables. My curiosity is about the fact that passed to the function is a variable 'F' which is not defined anywhere in the program. The function (called VA04A), calls a subroutine; CALCFX, to which it passes this variable F. F is then just defined as zero within the subroutine CALCFX, before being calculated as something else.

    My question is generally how variables are passed around using functions and subroutines in fortran 77? It seems strange to me (having only worked properly with MATLAB before) that I can pass a variable to a function without defining it, for that function to then pass it to a subroutine, for that subroutine to then define it as zero anyway. Is there anywhere I can seek guidance/information on this specifically?

    I've put the program and subroutine below, although I don't expect anyone to really go scouring through it.

    Code (Fortran):
          PROGRAM R55TG1
    C     Fits production and decay of activity in R55 to total counts per
    C      second in series of HPGe spectra
    C     Written to help analyse HPGe spectra (#33 - #60) recorded on R55
    C      South Balcony in September 2015
    C     One half-life for all radionuclides, only TS-1 beam current
    C      considered
          CHARACTER PRGNAM*6,EMIT*8,ETAD*9,A11DT*11,BET*17,ADT*23,FLNMBC*132
          DOUBLE PRECISION DMJDN,DBET
          DIMENSION ADT(100000),AI1(100000),AI2(100000),DMJDN(100000),
         1          BET(2,100),DBET(2,100),IBET(2,100),TCPS(100),
         2          TCPSFT(100),
         3          XVAR(2),EACC(2),WORK(10)
          COMMON WORK,NCLL
          COMMON/R5TG1C/AI1,NT,NL,DBET,IBET,DT,TCPS,DCPS,TCPSFT
          DATA PRGNAM,NPARAM/'R55TG1',2/
    C
          CALL DATE(ETAD)
          CALL TIME(EMIT)
          OPEN(1,FILE='r55tg1-ip.txt',READONLY)
          READ(1,103) (XVAR(I),I=1,NPARAM)
    C     Starting values for fit
    C     XVAR(1)  Rate of production of radionuclides (per second per µA)
    C     XVAR(2)  Half-life of radionuclides (minutes)
      103 FORMAT(2F10.4)
          READ(1,103) (EACC(I),I=1,NPARAM)
    C     Accuracies to which parameters to be found
          READ(1,104) ESCALE,IPRINT,ICONV,MAXIT
    C     VA04A parameters
      104 FORMAT(F10.4,3I10)
          READ(1,103) DCPS
    C     'Uncertainty' in total counts per second
          READ(1,101) FLNMBC
    C     Name of file containing TS-1 and TS-2 beam currents as function
    C      of time
      101 FORMAT(A132)
          READ(1,105) LBSTRN
    C     Run number of first HPGe spectrum considered - assumed numbered
    C      consecutively thereafter
      105 FORMAT(I10)
          J=1
        1 READ(1,102,END=2) BET(1,J),BET(2,J),TCPS(J)
    C     HPGe run beginning and end times and total counts per second
    C     In A17,3X,A17 format, A17 = dd mm yy hh mm ss
      102 FORMAT(A17,3X,A17,3X,F10.4)
          J=J+1
          GO TO 1
        2 NT=J-1
    C     Number of HPGe runs
          CLOSE(1)
    C
          OPEN(2,FILE=FLNMBC,READONLY)
          I=1
        3 READ(2,*,END=4) ADT(I),AI1(I),AI2(I)
    C     Date-and-time string, TS-1 current, TS-2 current
    C     Formatted as '13-SEP-2015 23:55:44.88'    153.609    39.8766
          I=I+1
          GO TO 3
        4 NL=I-1
    C     Number of lines in beam currents file
          CLOSE(2)
    C
          DO 5 I=1,NL
          DECODE(23,1001,ADT(I)) A11DT,IHOUR,IMIN,SEC
    1001 FORMAT(A11,1X,I2,1X,I2,1X,F5.2)
          CALL DT3JCI(A11DT,IDAY,IMONTH,IYEAR)
          CALL DMYTMJ(IDAY,IMONTH,IYEAR,MJDN)
        5 DMJDN(I)=DFLOAT(MJDN)+DFLOAT(IHOUR)/2.4D1
         1                     +DFLOAT(IMIN)/1.44D3+DBLE(SEC)/8.64D4
    C     Modified Julian day number for each line of beam current file
          DO 6 J=1,NT
          DO 6 K=1,2
          DECODE(17,1002,BET(K,J)) ID,IMNTH,IY,IH,IMIN,IS
    1002 FORMAT(I2,1X,I2,1X,I2,1X,I2,1X,I2,1X,I2)
          CALL DMYTMJ(ID,IMNTH,IY+2000,MJDN)
          DBET(K,J)=DFLOAT(MJDN)+DFLOAT(IH)/2.4D1
         1                      +DFLOAT(IMIN)/1.44D3+DFLOAT(IS)/8.64D4
    C     Beginning and end times of HPGe spectra as mod. Jul. day no.
        6 IBET(K,J)=IRYNDD(DMJDN,NL,DBET(K,J))
    C     Indexes of beginning and end times in beam current array
          DT=SNGL(8.64D4*(DMJDN(NL)-DMJDN(1))/DFLOAT(NL-1))
    C     Step length (seconds)
    C     Lines of beam current values assumed equally spaced in time
    C
          OPEN(3,FILE='r55tg1-op.txt')
          WRITE(3,301) PRGNAM,ETAD,EMIT
      301 FORMAT(A6,4X,A9,4X,A8/)
          WRITE(3,305) (XVAR(I),I=1,NPARAM)
      305 FORMAT(2F10.4)
          WRITE(3,305) (EACC(I),I=1,NPARAM)
          WRITE(3,306) ESCALE,IPRINT,ICONV,MAXIT
      306 FORMAT(F10.2,3I10)
          WRITE(3,305) DCPS
          WRITE(3,302) NL
      302 FORMAT(/2I10)
          WRITE(3,310) FLNMBC
      310 FORMAT(A132)
          WRITE(3,304) (ADT(I),AI1(I),AI2(I),DMJDN(I),I=1,10)
      304 FORMAT(A23,2X,2F10.2,F20.6)
          WRITE(3,308)
      308 FORMAT(9X,'[first and last ten lines]')
          WRITE(3,304) (ADT(I),AI1(I),AI2(I),DMJDN(I),I=NL-9,NL)
          WRITE(3,302) NT,LBSTRN
          WRITE(3,303) (BET(1,J),BET(2,J),DBET(1,J),DBET(2,J),TCPS(J),
         1              J=1,NT)
      303 FORMAT('dd mm yy hh mm ss   dd mm yy hh mm ss   ',
         1'  Mod Jul day #  Mod Jul day #',
         2'   Tot cps'/(A17,3X,A17,3X,2F15.6,F10.2))
    C
          NCLL=0
          CALL VA04A(XVAR,EACC,NPARAM,F,ESCALE,IPRINT,ICONV,MAXIT)
    C
          WRITE(3,307) NCLL,F
      307 FORMAT(/I10,F10.2)
          WRITE(3,305) (XVAR(I),I=1,NPARAM)
          WRITE(3,309) (LBSTRN+J-1,TCPS(J),TCPSFT(J),J=1,NT)
      309 FORMAT(/(I10,2F10.2))
    C
          STOP
          END
    C
          SUBROUTINE CALCFX(N,X,F)
          DOUBLE PRECISION DBET
          DIMENSION X(2),WORK(10),
         1          AI1(100000),AN1(100000),
         2          DBET(2,100),IBET(2,100),TCPS(100),TCPSFT(100)
          COMMON WORK,NCLL
          COMMON/R5TG1C/AI1,NT,NL,DBET,IBET,DT,TCPS,DCPS,TCPSFT
    C     X(1)  Rate of production of radionuclides (per second per µA)
    C     X(2)  Half-life of radionuclides (minutes)
          ALMBD=ALOG(2.)/(60.*X(2))
    C     Decay constant (per second)
          AN1(1)=0.
    C     Initial value of zero assumed
          DO 1 I=2,NL
          DAN1=(X(1)*AI1(I-1)-ALMBD*AN1(I-1))*DT
    C     dN = (production rate - decay rate) * dt
        1 AN1(I)=AN1(I-1)+DAN1
          F=0.
          DO 2 J=1,NT
          S=0.
          DO 3 I=IBET(1,J),IBET(2,J)
        3 S=S+ALMBD*AN1(I)
    C     ALMBD * AN1 is activity as function of time
          TCPSFT(J)=S/SNGL((DBET(2,J)-DBET(1,J))*8.64D3)
    C     SNGL((DBET(2,J)-DBET(1,J))*8.64D3) is number of seconds between
    C      beginning and end of HPGe run J
        2 F=F+(TCPS(J)-TCPSFT(J))**2/DCPS**2
          F=F/FLOAT(NT-N)
          NCLL=NCLL+1
          RETURN
          END


    Many thanks, I hope the question is clear.

    Matt
     
  2. jcsd
  3. Oct 28, 2015 #2
    For better or for worse, there is a feature in Fortran that allows you not having to declare (ahead of time) every single variable you use. Varirable F that you mentioned is not the only variable not declared ahead of time; for example, "Accuracies to which parameters to be found" preceeds a READ statement that reads values into variables ESCALE, IPRINT, ICONV and MAXIT...none of which has been prevsiously declared, either.

    When using implicit typing like this, variables that start with the letters I through N are INteger; otherwise, they are REAL.

    Variable F in CALCFX is not just set to zero; rather, it is initialized to zero, before being used to accumulate some sum inside the do-loop.

    Anyway, nothing illegal, there; they are using implicit typing.
     
  4. Oct 29, 2015 #3
    Thanks for the answer, qsal. Very informative.

    Although I do then have a couple of follow up questions.

    I'm assuming that if you don't declare a variable ahead of time, the variable does still need to be declared somewhere in the program? Would FORTRAN77 throw up an error if you did not do this? (I know I should test this stuff out myself, but I haven't got a fortran77 compiler yet).

    I see what you mean with F being initialized to zero. That's what I was trying to say with my poor terminology. So that leads me to ask why the variable F is passed to CALCFX at all? Is there a reason to pass that variable, or would it simply be the same if CALCFX only took the two other variables as inputs? I can't see the need for F being passed to CALCFX at all.

    Thanks again.
     
  5. Oct 29, 2015 #4

    jtbell

    User Avatar

    Staff: Mentor

    No, if you don't declare a variable yourself, Fortran "implicitly" declares it for you. As gsal said, in that case, if the name begins with I through N, the variable is implicitly INTEGER; otherwise it's implicitly REAL.

    You can turn off this behavior by putting an IMPLICIT NONE statement at the beginning of each program or subprogram. This makes Fortran behave like C, C++ etc. and throw up an error message when you don't declare a variable. I started doing this myself, about 35 years ago, in order to catch typographical errors and misspelled variable names.
     
  6. Oct 29, 2015 #5

    SteamKing

    User Avatar
    Staff Emeritus
    Science Advisor
    Homework Helper

    CALCFX is not a function, in the sense that Fortran uses that term. It is a subroutine, and although functions and subroutines share some similarities in Fortran, they also are different in some respects.

    Both functions and subroutines can have a list of variables which are supplied when each routine is called. There may be variables which have their values set by the statements contained in the subroutine, which values are then returned to the calling program, like so:

    CALL SUB (X1, Y1, Z1, FOUT)

    The variables X1, Y1, and Z1 may be defined and initialized when SUB is CALLed, but FOUT may be initialized somewhere within SUB and then returned to the CALLing program.

    A subroutine does not necessarily need to be called with any variables stated,

    CALL SUB2

    The subroutine SUB2 may execute some code and then return to the CALLing program when it is finished.

    A Fortran FUNCTION is slightly different in concept from a Subroutine. A FUNCTION is a special kind of subroutine which expects to be supplied with some sort of data list and it returns a single value when it is finished, much like a mathematical function, f(x,y) will return a result when supplied with values of x and y.

    FUNCTIONS are typed (REAL, INTEGER, etc.) just like variables, usually according to the TYPE of data returned.

    The calling convention for a Fortran FUNCTION is also specialized:

    YCALC = FUNC1 (X)

    FUNC1 is a Fortran function which takes one data input, the variable X, does some calculations, and returns a single result, which in this case is stored in the variable YCALC. FUNCTIONS do not have to be supplied with input, but the form of this statement still must be maintained, so that the compiler doesn't get confused.

    For example:

    XCALC = FUNC2 ( )

    FUNC2 does not need any variables passed to it in order to execute, but a set of empty parentheses is required so that the Fortran compiler doesn't confuse the identifier FUNC2 with an ordinary variable with that same name. Whatever result is calculated by FUNC2 is returned and stored in the variable XCALC.
     
  7. Oct 29, 2015 #6

    DrClaude

    User Avatar

    Staff: Mentor

    To add to the good answers already given, it is good to know that fortran uses the "pass by reference" paradigm. Every time you pas an argument to a subroutine or a function, you are actually passing a pointer to that argument; in other words, you are giving the subroutine access to the variable, not just its content.

    This is contrast, for example, to C, where by default arguments are "pass by value", where the value of the variable is given to the function. To pass by reference, you need to pass explicitly the pointer to the variable.

    To summarize, in your code, at the moment of
    Code (Fortran):

          CALL VA04A(XVAR,EACC,NPARAM,F,ESCALE,IPRINT,ICONV,MAXIT)
     
    the value of F is undefined. There are 4 bytes (a REAL) in memory for F, but we have no idea what the content can be, since F hasn't been initialized.

    Then, inside VA04A (for which you haven't given the code), I guess there is a
    Code (Fortran):

    CALCFX(N,X,F)
     
    and the value of F is still undefined.

    Then, inside CALCFX the value of F is set. Since this is the same variable, meaning it occupies the same memory space, upon return, the value of F will be available inside VA04A, and upon return again F in the main program still contains the value as set in CALCFX. So the next statement,
    Code (Fortran):

    WRITE(3,307) NCLL,F
     
    will print out the value of F as calculated by CALCFX.
     
  8. Nov 4, 2015 #7
    Excellent answers. I can't thank you all enough! As I say, I'm new to the FORTRAN business but everyone has been perfectly explanatory and helpful.

    I'll have to come back here more often :)
     
Know someone interested in this topic? Share this thread via Reddit, Google+, Twitter, or Facebook




Similar Discussions: Fortran functions query
  1. Fortran - Functions (Replies: 0)

Loading...