beginning fortran

45
Beginning Fortran Fortran (77) Advanced 29 October 2009 text on white background provided for easy printing

Upload: ion

Post on 14-Jan-2016

84 views

Category:

Documents


1 download

DESCRIPTION

*Black text on white background provided for easy printing. Beginning Fortran. Fortran (77) Advanced 29 October 2009. Example Code. Write a program to read in five values of temperature in Fahrenheit and convert to degrees Celsius OR Kelvin OR both. Your Typical Program. c234567 - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Beginning Fortran

Beginning Fortran

Fortran (77) Advanced29 October 2009

*Black text on white background provided for easy printing

Page 2: Beginning Fortran

Example Code

• Write a program to read in five values of temperature in Fahrenheit and convert to degrees Celsius OR Kelvin OR both.

Page 3: Beginning Fortran

Your Typical Programc234567 PROGRAM MYPROGRAM

STOP END

Program OptionsProgram Options

Declaration of VariablesDeclaration of Variables

MAIN CODEMAIN CODE

Page 4: Beginning Fortran

Program Start

Options/Variable Declaration

Main Code

Program End

c234567 PROGRAM CONVERTF IMPLICIT NONE PARAMETER NT = 5 REAL F(NT) REAL K(NT) REAL C(NT) LOGICAL DOC LOGICAL DOK INTEGER I DO I = 1, NT READ(*,*) F(I) ENDDO WRITE(*,*) ‘Convert to C?’ READ(*,*) DOC WRITE(*,*) ‘Convert to K?’ READ(*,*) DOK DO I = 1, NT C(I) = (5./9.)*(F(I)-32.) ENDDO IF (DOK .EQV. .TRUE.) THEN DO I = 1, NT K(I) = C(I) + 273.15 ENDDO ENDIF IF ((DOC .EQV. .TRUE.) .AND. (DOK .EQV. .FALSE.)) THEN DO I = 1, NT WRITE(*,*) F(I), ‘F = ‘, C(I), ‘C’ ENDDO ENDIFc IF ((DOC .EQV. .FALSE.) .AND. (DOK .EQV. .TRUE.)) THEN DO I = 1, NT WRITE(*,*) F(I), ‘F = ‘, K(I), ‘K’ ENDDO ENDIFc IF ((DOC .EQV. .TRUE.) .AND. (DOK .EQV. .TRUE.)) THEN DO I = 1, NT WRITE(*,*) F(I), ‘F = ‘, C(I), ‘C ’, K(I), ‘K’ ENDDO ENDIF STOP END

Page 5: Beginning Fortran

c234567 PROGRAM CONVERTF IMPLICIT NONE PARAMETER NT = 5 REAL F(NT) REAL K(NT) REAL C(NT) LOGICAL DOC LOGICAL DOK INTEGER I DO I = 1, NT READ(*,*) F(I) ENDDO WRITE(*,*) ‘Convert to C?’ READ(*,*) DOC WRITE(*,*) ‘Convert to K?’ READ(*,*) DOK DO I = 1, NT C(I) = (5./9.)*(F(I)-32.) ENDDO IF (DOK .EQV. .TRUE.) THEN DO I = 1, NT K(I) = C(I) + 273.15 ENDDO ENDIF IF ((DOC .EQV. .TRUE.) .AND. (DOK .EQV. .FALSE.)) THEN DO I = 1, NT WRITE(*,*) F(I), ‘F = ‘, C(I), ‘C’ ENDDO ENDIFc IF ((DOC .EQV. .FALSE.) .AND. (DOK .EQV. .TRUE.)) THEN DO I = 1, NT WRITE(*,*) F(I), ‘F = ‘, K(I), ‘K’ ENDDO ENDIFc IF ((DOC .EQV. .TRUE.) .AND. (DOK .EQV. .TRUE.)) THEN DO I = 1, NT WRITE(*,*) F(I), ‘F = ‘, C(I), ‘C ’, K(I), ‘K’ ENDDO ENDIF STOP END

This program is not particularly useful:-What if we want to calculate 3 temperatures? Or 30?-Open source code, change NT, recompile, re-run …

-We are primarily restricted because of the necessity of declaring the value of NT: it is a parameter that has to be set in the code before anything else is done.

Page 6: Beginning Fortran

Subroutines

• Mini-programs that are run inside of a larger program (or subroutine):

Main Program

CodeCodeCodeCALL SUBROUTINE(a,b,c)CodeCodeSTOPEND

INTEGER a, b, c

Page 7: Beginning Fortran

Subroutines

• Subroutine is called, with variables a, b, and c passed to it. Those same variables, at their current values, now exist in subroutine.

Main Program

CodeCodeCodeCALL SUBROUTINE(a,b,c)CodeCodeSTOPEND

INTEGER a, b, c

Subroutine(a,b,c)

INTEGER a, b, c

Page 8: Beginning Fortran

Subroutines

• Subroutine is called, with variables a, b, and c passed to it. Those same variables, at their current values, now exist in subroutine.

Main Program

CodeCodeCodeCALL SUBROUTINE(a,b,c)CodeCodeSTOPEND

INTEGER a, b, c

Subroutine(a,b,c)

INTEGER a, b, c

Page 9: Beginning Fortran

Subroutines

• Additional variables can be declared within the subroutine. These exist only in the subroutine, and will be destroyed when the routine is done.

Main Program

CodeCodeCodeCALL SUBROUTINE(a,b,c)CodeCodeSTOPEND

INTEGER a, b, c

Subroutine(a,b,c)

INTEGER a, b, cINTEGER d, e, f

Page 10: Beginning Fortran

Subroutines

• Lines of code manipulating variables are processed in the subroutine, possibly changing the values of a, b, and c.

Main Program

CodeCodeCodeCALL SUBROUTINE(a,b,c)CodeCodeSTOPEND

INTEGER a, b, c

Subroutine(a,b,c)

INTEGER a, b, cINTEGER d, e, fCodeCodeCode

Page 11: Beginning Fortran

Subroutines

• At RETURN, code returns to main program after subroutine was called. Variables a, b, and c now have NEW values depending on subroutine.

Main Program

CodeCodeCodeCALL SUBROUTINE(a,b,c)CodeCodeSTOPEND

INTEGER a, b, c

Subroutine(a,b,c)

INTEGER a, b, cINTEGER d, e, fCodeCodeCodeRETURNEND

Page 12: Beginning Fortran

Subroutines

• Main program continues on after the subroutine call with new values for a, b, and c.

Main Program

CodeCodeCodeCALL SUBROUTINE(a,b,c)CodeCodeSTOPEND

INTEGER a, b, c

Subroutine(a,b,c)

INTEGER a, b, cINTEGER d, e, fCodeCodeCodeRETURNEND

Page 13: Beginning Fortran

Subroutines

• When calling a subroutine, the main program is basically saying:

“Given these variables at their current values, do some stuff and then give me my variables back. Don’t worry; I’ll wait.”

Page 14: Beginning Fortran

Subroutines

• When calling a subroutine, the main program is basically saying:

“Given these variables at their current values, do some stuff and then give me my variables back. Don’t worry; I’ll wait.”

CALL <subroutine name>(arg1,arg2,arg3,…)

“input arguments”

Page 15: Beginning Fortran

Input Arguments

• Any variables that the main program wants the subroutine to make use of have to be passed to the subroutine as input arguments.

• These appear as a list of the names of the variables in parentheses after the name of the subroutine being called.

CALL AVERAGE(X1,X2,AVG)

Page 16: Beginning Fortran

Input Arguments

• Any variables that the main program wants the subroutine to make use of have to be passed to the subroutine as input arguments.

• These appear as a list of the names of the variables in parentheses after the name of the subroutine being called.

CALL AVERAGE(X1,X2,AVG)

Subroutine AVERAGE takes in three variables: two numbers (X1 and X2) and a variable that will represent the average of them (AVG).

Page 17: Beginning Fortran

Input Arguments

• In the subroutine, these variables are re-declared so that they now exist simultaneously in the main program and in the subroutine:

C234567 SUBROUTINE AVERAGE(X1,X2,AVG) IMPLICIT NONE REAL X1 REAL X2 REAL AVG

Page 18: Beginning Fortran

Input Arguments

• In the subroutine, these variables are re-declared so that they now exist simultaneously in the main program and in the subroutine:

C234567 SUBROUTINE AVERAGE(X1,X2,AVG) IMPLICIT NONE REAL X1 REAL X2 REAL AVG NOTE: These variables must be

declared as the same type as they are declared in the main program.

Page 19: Beginning Fortran

Input Arguments

• Now we can write code in the subroutine to compute AVG from X1 and X2:

C234567 SUBROUTINE AVERAGE(X1,X2,AVG) IMPLICIT NONE REAL X1 REAL X2 REAL AVGc AVG = (X1 + X2)/2. RETURN END

Page 20: Beginning Fortran

Input Arguments

• Any of the input arguments that were changed in the subroutine will now have new values in the main program.

X1 = 3.0X2 = 8.0AVG = -9999.0CALL AVERAGE(X1,X2,AVG)WRITE(*,*) AVG

AVG = (X1 + X2)/2.RETURNEND

Main Program AVERAGE(X1,X2,AVG)

Page 21: Beginning Fortran

Input Arguments

• Any of the input arguments that were changed in the subroutine will now have new values in the main program.

X1 = 3.0X2 = 8.0AVG = -9999.0CALL AVERAGE(X1,X2,AVG)WRITE(*,*) AVG

AVG = (X1 + X2)/2.RETURNEND

Main Program AVERAGE(X1,X2,AVG)

AVG is sent to subroutine with value of -9999.0

Page 22: Beginning Fortran

Input Arguments

• Any of the input arguments that were changed in the subroutine will now have new values in the main program.

X1 = 3.0X2 = 8.0AVG = -9999.0CALL AVERAGE(X1,X2,AVG)WRITE(*,*) AVG

AVG = (X1 + X2)/2.RETURNEND

Main Program AVERAGE(X1,X2,AVG)

Subroutine changes value of AVG to 5.5

Page 23: Beginning Fortran

Input Arguments

• Any of the input arguments that were changed in the subroutine will now have new values in the main program.

X1 = 3.0X2 = 8.0AVG = -9999.0CALL AVERAGE(X1,X2,AVG)WRITE(*,*) AVG

AVG = (X1 + X2)/2.RETURNEND

Main Program AVERAGE(X1,X2,AVG)

At RETURN, we return to the main program, where AVG now has a value of 5.5

Page 24: Beginning Fortran

Passing Arrays

• You can also pass arrays to a subroutine:– Pass the array dimensions as INTEGERs first, then

pass the array itself

PROGRAM MAINPARAMETER NX = 360PARAMETER NY = 181REAL TEMPS(NX,NY)CALL ZILCH(NX,NY,TEMPS)STOPEND

SUBROUTINE ZILCH(NX,NY,VAR)INTEGER NXINTEGER NYREAL VAR(NX,NY)INTEGER IINTEGER JDO J = 1, NY DO I = 1, NX VAR(I,J) = 0. ENDDOENDDORETURNEND

Page 25: Beginning Fortran

Passing Arrays

• Notice how the same variable can have different names in the main program and the subroutine.

PROGRAM MAINPARAMETER NX = 360PARAMETER NY = 181REAL TEMPS(NX,NY)CALL ZILCH(NX,NY,TEMPS)STOPEND

SUBROUTINE ZILCH(NX,NY,VAR)INTEGER NXINTEGER NYREAL VAR(NX,NY)INTEGER IINTEGER JDO J = 1, NY DO I = 1, NX VAR(I,J) = 0. ENDDOENDDORETURNEND

Page 26: Beginning Fortran

Passing ArraysSUBROUTINE ZILCH(NX,NY,VAR)INTEGER NXINTEGER NYREAL VAR(NX,NY)INTEGER IINTEGER JDO J = 1, NY DO I = 1, NX VAR(I,J) = 0. ENDDOENDDORETURNEND

Notice something interesting here:-We took in values from the main program for NX and NY, then created a variable VAR based on those dimensions.-We can do this, because input arguments are special

Page 27: Beginning Fortran

Rules of Subroutines

• Subroutines are basically small programs built inside of a larger program

• Input arguments are handed down to the subroutine from its parent program – the subroutine is constructed with a priori knowledge of these variables and their present value

• “Given a, b, and c, do something and then give me a, b, and c back.”

Page 28: Beginning Fortran

Rules of Subroutines

• Since the subroutine is built with the input arguments already known, we can make an array inside of the subroutine based on variables passed into it.

PROGRAM MAININTEGER NXINTEGER NYREAD(*,*) NX, NYCALL MAKEARRAY(NX,NY)STOPEND

SUBROUTINE MAKEARRAY(NX,NY)INTEGER NXINTEGER NYREAL VAR(NX,NY)…RETURNEND

Page 29: Beginning Fortran

Rules of Subroutines

• Since the subroutine is built with the input arguments already known, we can make an array inside of the subroutine based on variables passed into it.

PROGRAM MAININTEGER NXINTEGER NYREAD(*,*) NX, NYCALL MAKEARRAY(NX,NY)STOPEND

SUBROUTINE MAKEARRAY(NX,NY)INTEGER NXINTEGER NYREAL VAR(NX,NY)…RETURNEND

NX, NY read from user into MAIN NX, NY handed to MAKEARRAY to make VAR

Page 30: Beginning Fortran

Rules of Subroutines

• This is something we couldn’t do before – CONVERTF was not particularly useful because we couldn’t ask the user for the dimensions of array “F” and then make an array, we had to use a parameter.

• However, we can ask for the dimensions of the array and create an array inside of a subroutine with those dimensions, because for the subroutine, that variable is passed in as a priori knowledge.

Page 31: Beginning Fortran

CONVERTF

VARIABLE DECLARATION:PARAMETER NX = 5

<Declare Variables based on NX>

VARIABLE DECLARATION:PARAMETER NX = 5

<Declare Variables based on NX>

MAIN CODE:<Read in F, DOC, DOK>

<Compute C, K><Output F, K, C>

STOPEND

MAIN CODE:<Read in F, DOC, DOK>

<Compute C, K><Output F, K, C>

STOPEND

CONVERTF2

VARIABLE DECLARATION:INTEGER NX

VARIABLE DECLARATION:INTEGER NX

MAIN CODE:<Read in NX>CALL SUB(NX)

STOPEND

MAIN CODE:<Read in NX>CALL SUB(NX)

STOPEND

SUB(NX)VARIABLE

DECLARATION:INTEGER NX

<Declare Vars. Based on NX>

VARIABLE DECLARATION:

INTEGER NX<Declare Vars. Based

on NX>

MAIN CODE:<Read in F, DOC, DOK>

<Compute C, K><Output F, K, C>

RETURNEND

MAIN CODE:<Read in F, DOC, DOK>

<Compute C, K><Output F, K, C>

RETURNEND

Page 32: Beginning Fortran

Using Subroutines

• You can write subroutines in two different ways:– You can write the subroutine directly within the

parent program– You can write the subroutine in a separate *.f file

and compile it along with the parent program

Page 33: Beginning Fortran

Using Subroutines

STOP

END

SUBROUTINE MYSUBROUTINE(X1,X2,X3,…)

IMPLICIT NONE

REAL X1

REAL X2

Page 34: Beginning Fortran

Compiling With Subroutines

• Compile external subroutines separately using the following syntax:

• pgf77 –c <filename>.f <options>• Then compile the parent program with the

subroutine *.o files attached:

pgf77 <sub1.o> <sub2.o> … -o <exec. name> <source file>.f <options>

Page 35: Beginning Fortran

Proper Coding Technique

• There are some simple rules to follow to make sure that your code is readable and is robust – you can do a lot with it without having to write new source code.

Page 36: Beginning Fortran

Write in CAPITAL LETTERS

• This isn’t required, but writing code in capital letters and comments in lower-case makes it easier to distinguish the two from each other.

Page 37: Beginning Fortran

Use Subroutines Often

• If you find yourself having to code the same thing in over and over in your program, it is better to block that code off into a subroutine and call the subroutine every time you need to perform that function.

Page 38: Beginning Fortran

Proper Subroutine Usage

Main ProgramMain Program

Driver SubroutineDriver Subroutine

Sub 1Sub 1

Sub 4Sub 4

Sub 2Sub 2

Sub 3Sub 3

Page 39: Beginning Fortran

Proper Subroutine Usage

Main ProgramMain Program

Driver SubroutineDriver Subroutine

Sub 1Sub 1

Sub 4Sub 4

Sub 2Sub 2

Sub 3Sub 3

Main Program essentially just reads in necessary information to begin program (array sizes, etc). Passes all of that information to the Driver Subroutine.

Page 40: Beginning Fortran

Proper Subroutine Usage

Main ProgramMain Program

Driver SubroutineDriver Subroutine

Sub 1Sub 1

Sub 4Sub 4

Sub 2Sub 2

Sub 3Sub 3

Most of the main functions of the program are completed in the Driver Subroutine, where variables are declared based on information passed in from the Main Program.

Page 41: Beginning Fortran

Proper Subroutine Usage

Main ProgramMain Program

Driver SubroutineDriver Subroutine

Sub 1Sub 1

Sub 4Sub 4

Sub 2Sub 2

Sub 3Sub 3

Individual functions that need to be completed (some multiple times) are written in different subroutines, which are called from the Driver Subroutine.

Page 42: Beginning Fortran

Proper Subroutine Usage

Main ProgramMain Program

Driver SubroutineDriver Subroutine

Sub 1Sub 1

Sub 4Sub 4

Sub 2Sub 2

Sub 3Sub 3

You will find that most, if not all, professional code is written in this format.

Page 43: Beginning Fortran

Make Compilation Clear

• Programs can have complicated compilations, especially when you start attaching multiple subroutines with different options.

• If the compilation can be completed on a single line, put a comment in the code somewhere near the top containing the compilation line.

• If it’s more complex than that, make a script that compiles the program for you.

Page 44: Beginning Fortran

Use Source Directories

• Rather than keeping your source code, your subroutines, and your compiled programs all in the same directory, create a ‘source’ subdirectory where you keep your source code.

• This will prevent you from accidentally deleting, replacing, or otherwise ruining the code you’ve worked on.

Page 45: Beginning Fortran

Don’t Re-Invent The Wheel

• If you write your subroutines in separate files, you’ll find yourself using them in multiple programs – there’s no need to rewrite it.

• Use professional subroutine packages where possible – e.g. spherepack.