fortran

93
Introduction to Fortran Doug Sondak SCV [email protected]

Upload: martin

Post on 01-Oct-2015

9 views

Category:

Documents


0 download

DESCRIPTION

tutorial of fortran

TRANSCRIPT

Fortran for Matlab Users

Introduction to FortranDoug [email protected] HistoryBasic syntaxmakefilesAdditional syntax GoalsTo be able to write simple Fortran programsTo be able to understand and modify existing Fortran codeTo be able to manage program projects using an editor and makefileIntroductionMatlab is great! Why do I need to learn a new language?!All codes must be translated to machine language Interpreted languageMatlab, Python, JavaTranslation is performed incrementally at run timeCompiled languageFortran, C, C++Translation is performed once, then executable is run

Introduction (contd)Compiled languages run fasterI translated a program from Matlab to C for a user, and it ran 7 times as fastLarge-scale computing is usually done with compiled languageSome convenient features of interpreted languages (e.g., no need to declare variables) result in performance and/or memory penaltiesEmacsProfessional programmers often work within a programming environmentWriting and editing codeRunning codeOn Unix systems, one typically uses an editor to write/modify codeEmacs and vi are most popularWe will talk about emacsIf you want to use vi, thats fineArguing about which is better makes the Thirty-Years' War look tameEmacs (contd)Emacs is a wonder tool!We will just scratch the surface.emacs file in home directory can be customizedCommands can be executed via menus or using the underlying character sequencesI like the latter, so thats what well doCopy the file junk from /scratch/sondakThis will be our example file for editing cp /scratch/sondak/junk .Emacs ExerciseType emacsAn emacs window will appearA built-in tutorial is availableType CTL-h tHold CTL while pressing h, release CTL, then press tWe wont do anything with the tutorial here, but its a good resourceThe META key in the tutorial is EscTo read a file CTL-x CTL-fYou will be prompted for file name at bottom of windowType junk and hit returnIf the file doesnt exist, emacs will create itEmacs Exercise (contd)You should now see file contents in windowTo move down CTL-n (next line)To move up CTL-p (previous line)To move forward CTL-f (forward)To move backward CTL-b (backward)You can also navigate by clicking on the desired locationClick on the 0 in 0.282Emacs Exercise (3)To delete a character CTL-dHit CTL-d 3 times to delete 0.2Type 1.3Youve now changed 0.282 to 1.382Highlight 0.288 with the mouseDont include spaces before or afterCTL-w will delete the highlighted charactersOh no, we made a mistake! CTL-x u undoes the previous command. Try it; 0.288 should reappear.another CTL-x u undoes the command previous to that, etc. Emacs Exercise (4)The point is the location on the left side of the cursor; i.e., between the character on which the cursor resides and the character to its left.The mark is similar to the point, but its location is set (i.e., doesnt move with cursor).Suppose we want to delete all the characters between (inclusively) 0.288 and 0.407.Emacs Exercise (5)Place the cursor on the 0 in 0.288.can simply click on the 0To set the mark, CTL-spacebarThe note Mark set will appear at the bottom of the screen.Move the cursor to the right of 0.407We place it to the right of the 7 rather than on it because the point is always to the left of the cursorEmacs Exercise (6)CTL-w will delete all characters between the mark and the pointFor now, lets put the characters back in by using CTL-x uMove the cursor to the start of the current line using CTL-a (CTL-e moves to end of current line)Delete (kill) the line with CTL-kAnother CTL-k deletes the newline characterEmacs Exercise (7)Meta key is the Esc keyWe will use M- here to indicate the Meta keyThe Meta key is hit prior to the subsequent key(s), not simultaneously as with CTLPlace the cursor at the top of the fileM-> will move the cursor to the bottom of the fileM-< will move it back to the topEmacs Exercise (8)Suppose we want to swap positions of 14.747 and 14.688Set the mark at the 1 in 14.747Place the cursor on the 1 in 14.688 to set the point to the left of the 1CTL-w will delete 14.747Place the cursor over the space to the left of the first 1 in 16.155CTL-y yanks the previously-deleted stringEmacs Exercise (9)Suppose we want to swap positions of the second and third columnsSet the mark after the last 0 in 0.000 in the 1st row of dataSet the point to the right of the 8 in 0.758 in column 2, last rowCTL-x r k (kill rectangle) deletes the columnPlace the point after the 8 in 37.578CTL-x r y (yank rectangle) inserts the columnEmacs Exercise (10)To save the modified file, CTL-x CTL-sA note will appear at the bottom of the window saying the file has been savedTo save it under a new name, CTL-x CTL-wYoull be prompted for the name at the bottom of the screenNote that when you get these kinds of prompts, you can edit them using emacs commandsType a file name and then move back and forth with CTL-b and CTL-fCTL-x CTL-c to quitPrevious version will appear with ~ suffix in working directoryFortran HistoryBefore Fortran, programs were written in assembly languageFortran was the first widely-used high-level computer language1957Developed by IBM for scientific applications

Fortran HistoryFortran 66 (1966)Fortran 77 (1978)Fortran 90 (1991)fairly modern (structures, etc.)Current workhorse FortranFortran 95 (minor tweaks to Fortran 90)Fortran 2003Gradually being implemented by compiler companiesObject-oriented supportInteroperability with C is in the standardyay!

What Language Should I Use?I usually suggest using the language you know bestMatlab is great, but is not a good choice for major number crunchingResearchers often write codes in Matlab, and they grow and grow (the codes, not the researchers) until they are much too slowThen a painful translation is often requiredWhat Language? (contd)Fortran is hard to beat for performanceC has the potential to be as fast as Fortran if you avoid aliasing issues and promise the optimizer your code wont screw up aliasingFortran doesnt have this issue due to the different nature of its pointersI have not written large C++ codes, but its to my understanding that object-oriented constructs tend to be slowSuggestion write computationally-intensive codes in Fortran or CCan parallelize using MPI and/or OpenMPFortran SyntaxSource lines are not ended with semicolons (as in C or Matlab)Ampersand at end of line tells compiler that statement is continued on next source lineNot case-sensitiveSpaces dont matter except within literal character stringsI use them liberally to make code easy to readComment character is !Fortran Syntax (contd)Declarations should declare each variable as being integer, real (floating point), character, etc.Integers and reals are stored differentlyInteger arithmetic will truncate resultIf i=3 and k=2, i/k=1, k/i=0Fortran Syntax (3)There are sometimes several ways to do the same thingFor backward compatibilityWe will only use modern constructsSource file suffix is compiler dependentUsually .f90Fortran Syntax (4)First statement in code is program statementFollowed by program nameI like to give the source file the same name as the programmyprog.f90 (name of source file)program myprog (first line in source code)Fortran Syntax (5)implicit noneDue to older versions of FortranHad implicit typingVariables did not have to be declaredIf names started with i-n, were automatically integersIf a-h,o-z, were automatically single-precision realsImplicit typing is considered bad programming practiceAlways use implicit noneoften next line after programImplicit none says that all variables must be declaredIf you use implicit none and dont declare all variables, compiler will yell at youFortran Syntax (6)A character string is enclosed by single quotesCharacters within the quotes will be taken literallyThis is my character string.print*list-directed outputLazy way to produce outputNo format requiredFollow by comma, then stuff to printprint*, This is my character string.

Fortran Syntax (7)At the end of the code is an end program statement, followed by program namePaired with program statement that starts the codeend program myprogExercise 1Write a hello world program in an editorProgram should print a string4 lines of codeSave it to a file name with a .f90 suffixsolutionCompilationA compiler is a program that reads source code and converts it to a form usable by the computerCode compiled for a given processor will not generally run on other processorsAMD and Intel are compatibleOn katana we have Portland Group compilers (pgf90) and GNU compilers (gfortran)Well use pgf90, since its usually fasterCompilation (contd)Compilers have huge numbers of optionsSee PGI compiler documentation at http://www.pgroup.com/doc/pgiug.pdfPGI Fortran reference is at http://www.pgroup.com/doc/pgifortref.pdfFor now, we will simply use the o option, which allows you to specify the name of the resulting executableCompilation (3)Can create a Unix window within emacs:CTL-x 2 will split the window horizontallyCTL-x o toggles between windowso stands for otherM-x will prompt for a command at the bottom of the windowType shell (no quotes) for the commandHalf of emacs window will now be a Unix shell, so you can do your compilation thereIn a normal Unix tcshell you can retrieve previous Unix commands with the up arrow; here its CTL up arrowIn a Unix window (in emacs or separate window):pgf90 o hello_world hello_world.f90

Compilation (4)Compile your codeIf it simply returns a Unix prompt it workedIf you get error messages, read them carefully and see if you can fix the source code and re-compileOnce it compiles correctly, type the executable name at a Unix prompt, and it will print your stringDeclarationsLists of variables with their associated typesPlaced in source code directly after implicit noneBasic types:IntegerRealCharacterlogicalDeclarations (contd)Examples:integer :: i, j, kreal :: xval, timecharacter(20) :: name, datelogical :: isitArithmetic+, -, *, /** indicates power 2.4**1.5Built-in functions such as sin, acos, exp, etc.Exponential notation indicated by letter e 4.2e5

More List-Directed i/oread* is list-directed read, analogous to print*Follow with comma, then comma-delimited list of variables you want to readread*, x, jOften use list-directed read and write togetherprint*, Enter a float and an integer:read*, x, jprint*, float = , x, integer = , jExercise 2Write program to prompt for a Celcius temperature, convert it to Fahrenheit, and print the result.make sure you declare all variablesits a good habit to use decimal points with all reals, even if theyre whole numbers, e.g., 3.0 F = (9/5)C + 32solutionArraysSpecify static dimensions in declaration:real, dimension(10,3,5) :: xCan also specify ranges of valuesinteger, dimension(3:11, -15:-2) :: ival, jvalArrays (contd)Dynamic allocationNeed to specify no. dimensions in declarationNeed to specify that its an allocatable arrayreal, dimension(:,:,:), allocatable :: x, yallocate function performs allocationallocate( x(ni,nj,nk), y(ldim,mdim,ndim) )When youre done with the variables, deallocate deallocate(x, y)not necessary at very end of code; Fortran will clean them up for you

ParametersIf variable has known, fixed value, declare as parameter and initialize in declarationinteger, parameter :: idim = 100, jdim = 200Compiler substitutes values wherever variables appear in codeEfficient, since there are no memory accessesOften used for declaring arraysinteger, parameter :: idim = 100, jdim = 200real, dimension(idim, jdim) :: xinteger, dimension(idim) :: iarray

Exercise 3Write program to prompt for 2 floating-point vectors of length 3, calculate the dot product, and print the resultDont name the code dot_product or dotFortran has a dot_product intrinsic functionthere is a unix command called dotIf x is an array, can use array name in list-directed read, and it will expect the appropriate number of values (dimension) separated by spaces

solution

ControlDo loop repeats calculation over range of indicesdo i = 1, 10 a(i) = sqrt( b(i)**2 + c(i)**2 )enddoCan use increment that is not equal to 1Goes at end of do statement, unlike Matlabdo i = 10, -10, -2

Exercise 4Modify dot product program to use a do loopsolution

If-Then-ElseConditional execution of block of source codeBased on relational operatorsgreater than==equal to=greater than or equal to/=not equal to.and..or.

If-Then-Else (contd)if( x > 0.0 .and. y > 0.0 ) then z = 1.0/(x+y)elseif ( x < 0.0 .and. y < 0.0) then z = -2.0/(x+y)else print*, Error conditionendifExercise 5In dot product code, check if the magnitude of the dot product is less than using the absolute value function abs. If it is, print a message. If not, calculate the reciprocal of the dot product and print the result.solution

Array SyntaxFortran will perform operations on entire arraysLike Matlab, unlike CTo add two arrays, simply usec = a + bCan also specify array sectionsc(-5:10) = a(0:15) + b(0:30:2)Here we use b(0), b(2), b(4), Array Syntax (contd)There are intrinsic functions to perform some operations on entire arrayssumsum(x) is the same as x(1) + x(2) + x(3) + productminvalmaxvalExercise 6Modify dot product code to use array syntax instead of do loopuse sum intrinsic to sum comnponentssolutionSubprogramsSubroutines and functionsFunction returns a single object (number, array, etc.), and usually does not alter the argumentsAltering arguments in a function, called side effects, is sometimes considered bad programming practiceSubroutine transfers calculated values (if any) through argumentsFunctionsDefinition starts with a return typeEnd with end function analogous to end programExample: distance between two vectorsreal function distfunc(a, b) real, dimension(3) :: a, b distfunc = sqrt( sum((b-a)**2) )end function distfuncUse:z = distfunc(x, y)Names of dummy arguments dont have to match actual namesdistfunc must be declared in calling routinereal :: distfuncSubroutinesEnd with end subroutine analogous to end programDistance subroutinesubroutine distsub(a, b, dist) real :: dist real, dimension(3) :: a, b dist = sqrt( sum((b-a)**2) )end subroutine distfuncUse:call distsub (x, y, d)As with function, names of dummy arguments dont have to match actual namesExercise 7Modify dot-product program to use a subroutine to compute the dot productThe subroutine definition may go before or after the main program in source codeDont forget to declare argumentssolutionBasics of Code ManagementLarge codes usually consist of multiple filesI usually create a separate file for each subprogramEasier to editCan recompile one subprogram at a timeFiles can be compiled, but not linked, using c option; then object files can be linkedpgf90 c mycode.f90pgf90 c myfunc.f90pgf90 o mycode mycode.o myfunc.o

Exercise 8Put dot-product subroutine and main program in separate filesGive main program same name you have been using for code, e.g., program dotprod and dotprod.f90Give subroutine same name you used for subroutine, e.g., subroutine dp and dp.f90Compile, link, and runsolution

MakefilesMake is a Unix utility to help manage codesWhen you make changes to files, it willAutomatically deduce which files need to be compiled and compile themLink latest object filesMakefile is a file that tells the make utility what to doDefault name of file is makefile or MakefileCan use other names if youd like

Makefiles (contd)Makefile contains different sections with different functionsThe sections are not executed in order!Comment character is #There are defaults for some values, but I like to define everything explicitlyMakefiles (3)example makefile:

### suffix rule.SUFFIXES:.SUFFIXES: .f90 .o.f90.o:$(F90) $(COMPFLAGS) $*.f90

### compilerF90 = pgf90COMMONFLAGS = -O3COMPFLAGS = -c $(COMMONFLAGS)LINKFLAGS = $(COMMONFLAGS)

### objectsOBJ = mymain.o sub1.o sub2.o fun1.o

### compile and linkmyexe: $(OBJ)$(F90) o $@ $(LINKFLAGS) $(OBJ)Makefiles (4)variablesSome character strings appear repeatedly in makefilesIts convenient to give them names so if they are changed, you only have to do it in one placeTo define variable: name = stringNo quotes are required for the stringString may contain spacesname is any name you wantVariable names are usually all capitalsTo continue line, use \ characterMakefiles (5)Variables (contd)To use variable, either of these work:$(name)${name}Example:Define compilerF90 = pgf90To use elsewhere in makefile:$(F90)Makefiles (6)Good practice to define compiler info in variablesF90 = pgf90COMMONFLAGS = -O3COMPFLAGS = -c $(COMMONFLAGS)LINKFLAGS = $(COMMONFLAGS)Makefiles (7)Have to define all file suffixes that may be encountered.SUFFIXES: .o .f90Just to be safe, delete any default suffixes first with a null .SUFFIXES: command.SUFFIXES:.SUFFIXES: .o .f90Makefiles (8)Have to tell how to create one file suffix from another with a suffix rule.f90.o:$(F90) $(COMPFLAGS) $*.f90The first line indicates that the rule tells how to create a .o file from a .f90 fileThe second line tells how to create the .o fileThe big space before $(F90) is a tab, and you must use it!*$ is automatically the root of the first fileMakefiles (9)Usually define variable with all object file namesOBJ = mymain.o sub1.o anothersub.o \ firstfunc.o func2.o

Makefiles (10)Finally, everything falls together with the definition of a ruletarget: prerequisitesrecipeThe target is any name you chooseOften use name of executablePrerequisites are files that are required by targete.g., executable requires object filesRecipe tells what you want the makefile to do

Makefiles (11)### suffix rule.SUFFIXES:.SUFFIXES: .f90 .o.f90.o:$(F90) $(COMPFLAGS) $*.f90

### compilerF90 = pgf90COMMONFLAGS = -O3COMPFLAGS = -c $(COMMONFLAGS)LINKFLAGS = $(COMMONFLAGS)

### objectsOBJ = mymain.o sub1.o sub2.o fun1.o

### compile and linkmyexe: $(OBJ)$(F90) o $@ $(LINKFLAGS) $(OBJ)Automatic variable for targetMakefiles (12)When you type make, it will look for a file called makefile or MakefileIt then searches for the first target in the fileIn our example (and the usual case) the object files are prerequisitesIt checks the suffix rule to see how to create an object fileIn our case, it sees that .o files depend on .f90 filesIt checks the time stamps on the associated .o and .f90 files to see if the .f90 is newerIf the .f90 file is newer it performs the suffix ruleIn our case, compiles the routineMakefiles (13)Once all the prerequisites are updated as required, it performs the recipeIn our case it links the object files and creates our executableMany makefiles have an additional target, clean, that removes .o and other filesclean:rm f *.oWhen there are multiple targets, specify desired target as argument to make commandmake cleanExercise 9Create a makefile for your dot product codeInclude two targetsexecutablecleanDelete your old object files using make cleanBuild your code using the makefilesolutionKindDeclarations of variables can be modified using kind parameterOften used for precision of realsIntrinsic function selected_real_kind(n) returns kind that will have at least n significant digits n = 6 will give you single precision n = 12 will give you double precisionKind (contd)integer, parameter :: rk = selected_real_kind(12)real(rk) :: x, y, zreal(rk), dimension(101,101,101) :: aIf you want to change precision, can easily be done by changing one line of codeExercise 10Modify dot-product code to use kinds to declare double-precision realsDont forget to modify all filesmake will automatically compile and linksolutionModulesProgram units that group variables and subprogramsGood for global variablesChecking of subprogram argumentsIf type or number is wrong, linker will yell at youCan be convenient to package variables and/or subprograms of a given type

Modules (contd)module module-nameimplicit none variable declarations contains subprogram definitions end module module-name

Modules (3)Only need contains if module contains subprogramsI usually name my modules (and associated files) with _mod in the name, e.g., solvers_mod, solvers_mod.f90In program unit that needs to access components of module use module-nameuse statement must be before implicit noneModules (4)use statement may specify specific components to access by using only qualifier:use solvers_mod, only: nvals, xA Fortran style suggestion:Group global variables in modules based on functionEmploy use only for all variables required in program unitAll variables then appear at top of program unit in declarations or use statements

Modules (5)When linking object files, modules must come first in the listIn my makefiles I create a MODS variable analogous to OBJSLink command then contains $(MODS) $(OBJS)Exercise 11Create module prec_modSeparate file called prec_mod.f90Parameter rkReal kind for double Use this module in dot-product program unitsModify makefile to compile moduleadd module list to dependencies and link recipesolutionDerived TypesAnalogous to structures in CCan package a number of variables under one nametype grid integer :: nvals real, dimension(100,100) :: x, y, jacobianend type gridDerived Types (contd)To declare a variable type(grid) :: grid1Components are accessed using %grid1%nvals = 20grid1%x = 0.0Handy way to transfer lots of data to a subprogramcall calc_jacobian(grid1)Exercise 12Create module with definition of rvec3 typeSize of vector nvals=3not a paremeter cant have parameter in derived typeReal 3-component vectorUse prec_modModify code to use rvec3Modify makefile to include new modulesolutioni/oList-directed output gives little controlwrite statement allows formatted outputwrite(unit, format) variablesUnit is a number indicating where you want to write dataThe number 6 is std out (write to screen)i/o (contd)imFor integersm is total number of characters in fieldi3 125amFor character stringsm is number of charactersa5 helloLeft-justifiesIf m isnt specified, writes number of characters in variable declaration

i/o (3)fm.nFor floating-point (real) numbersm is total number of characters in fieldn is number of decimal placesf5.3 1.234f5.2 -1.23If m is larger than required, right-justifiesem.nExponential notatione9.2 -0.23e-01Always zero left of decimali/o (4)esm.nscientific notationes9.2 -2.30e-02In format statement, put formats within ()Example write statementwrite(6, (a, f6.2, i5, es15.3)) answers are , x, j, yi/o (5)Suppose you want to write to a file?open statementopen(11, file=mydata.d)11 is unit numberDont use 5 or 6Reserved for std in, std outUse this unit in your write statementWhen youre finished writing, close the fileclose(11)i/o (6)Can also read from fileread rather than writeCan use * instead of format specifierread(11,*) j, x

Exercise 13Write your dot-product result to a filesolutionUnformatted i/oBinary data take much less disk space than ascii (formatted) dataData can be written in binary representationNot directly human-readableopen(199, file=unf.d, form=unformatted)write(199) x(1:100000), j1, j2read(199) x(1:100000), j1, j2Note that there is no format specificationFortran unformatted slightly different format than C binaryFortran unformatted contains record delimitersExercise 14Modify dot-product program to:Write result to unformatted filedont write character string, just numberAfter file is closed, open it back up and read resultPrint result to make sure it wrote/read correctlysolutionReferencesLots of books availableI have an older edition of Fortran 95/2003 Explained by Metcalf, Reid, and Cohen that I likePGICompiler http://www.pgroup.com/doc/pgiug.pdfFortran language reference http://www.pgroup.com/doc/pgifortref.pdfgfortranhttp://gcc.gnu.org/wiki/GFortran

SurveyPlease fill out the course survey athttp://scv.bu.edu/survey/fall10tut_survey.html