260 likes | 301 Views
Explore the power of Fortran 90/95 with efficient compiler tips, program structuring, data types, and module usage for advanced applications. Learn to pass arguments and work with conditional statements and DO loops in Fortran.
E N D
Fortran 90/95 ProgrammingVictor Anisimov, NCSA FIU / SSERCA / XSEDE Workshop, Apr 4-5, 2013, Miami, FL
Few facts about Fortran • Fortran is a modern powerful programming language for scientific applications • Fortran standard is actively evolving yet maintaining unbeatable backward compatibility and portability • Fortran code is easy to read • Fortran compiler produces the most optimized binary code • Fortran offers specific language constructs for scientific computations which are not available in other languages Fortran 90 / 95 Programming
Fortran Compiler Efficiency ! compute vector product a(m,n) = b(m,n) * c(m,n) a = b * c ! FORTRAN-90 code has one line index = 0; /* C code requires four lines */ for ( i=1; i<=m*n; i++ ) { index++; a(index) = b(index) * c(index); } Fortran 90 / 95 Programming
Fortran basics • Compilers: gfortran, pgf90, ifort, crayftn, etc. • File extensions: .f .F .f90 .F90 • lower case (.f .f90) no preprocessor will be invoked • upper case (.F .F90) preprocessor will be invoked • without number (.f .F) used with old F77 standard • with number (.f90 .F90) to stress on F90 standard • Fortran-90 compiler is fully backward compatible and allows mixing of different standards in the code • Recommended extension .F90 gfortran -c prog.F90 ! Compiling produces object prog.o gfortran -o prog.xprog.o ! Linking produced binary prog.x Fortran 90 / 95 Programming
Fortran Program Structure program program-name ! only one main program is defined implicit none [declaration part] [execution part] end program program-name subroutine subroutine-name ! contains commonly executed pieces of code implicit none [declaration part] [execution part] end subroutine subroutine-name Integer function function-name ! same as subroutine but used differently implicit none [declaration part] [execution part] end function function-name Fortran 90 / 95 Programming
Fortran Data Type Operators • fortranlanguage is case-insensitive • combine lower and upper case to improve readability • please use meaningful variable names • type declaration operators do not zero-initialize the variables integer :: counter double precision :: pi=3.14159265358d0 character (len=80) :: string integer, parameter :: nRows=5, nColumns=6 real :: array(nRows,nColumns) logical :: completedSuccessfully = .False. double complex :: phase = (4.0d0, 3.4d0) Tip:Unintialized variable contains machine garbage Fortran 90 / 95 Programming
Passing Arguments to / from Procedures a = function-name() ! By return value Subroutines and Functions have a special mechanism to declare argument intent subroutine subroutine-name ( arg1, arg2, arg3 ) implicitnone integer, intent (in) :: arg1 ! Argument is read-only double precision, intent(out) :: arg2 ! Placeholder for return value character (len=80), intent(inout) :: arg3 ! Argument is for reading and writing [execution part] end subroutine subroutine-name Purpose: • Clarity • Protection against programming bugs Presentation Title
Fortran Modules Modules are Data and Function (subroutine) placeholders we will design module loan (loan.F90) module module-name ! Define data scope implicit none character (len=80), private :: string ! Local variable accessible within this module only double precision, public :: currentBalance public :: Interest, Payment contains double precision function Interest() ! can be called from outside the module end function Interest double precision function Payment() ! can be called from outside the module end function Payment double precision function RoundToCents( amount ) ! Not visible from outside end function RoundToCents end module module-name Fortran 90 / 95 Programming
Fortran Modules in Use program LoanSimulator ! Use module loan defined in loan.F90; note the use of variables and functions use loan, only : currentBalance, Interest, Payment implicit none ! .. local variables .. integer :: month ! .. executable statement .. ! read input parameters ! execute while-loop until the loan is paid of ! in each loop iteration ! apply interest ! update balance ! determine payment amount ! apply payment end program LoanSimulator Fortran 90 / 95 Programming
Fortran Conditional Statements if ( a > b ) then [execution part] elseif ( a .eq. b ) then [execution part] else ! a < b [execution part] end if Example if ( (a > b .and. b <= z) .or. .not. finishedSuccessfully ) then [execution part] end if Tip: Use indentation to improve readability of the code conditional operators .lt. .le. .eq. .ne. .ge. .gt. < <= == /= >= > .and. .or. .not. Fortran 90 / 95 Programming
Fortran DO loops Formal definition of DO loop: do index = indexFrom, indexTo, indexIncrement [execution part] end do Example-1: do i = 1, 10 ! Loop starts from i=1; at the “end do” i=i+1; last loop i=10 [execution part] end do Example-2: do i = -5, 10, 2 ! Loop starts from i=-5; at the “end do” i=i+2; last loop i=9 [execution part] end do Example-3: do i = 10, 1, -1 ! Loop starts from i=10; at the “end do” i=i-1; last loop i=1 [execution part] end do Fortran 90 / 95 Programming
Fortran DO and WHILE loops Example-4: a = 5; b = 4; c = 1 do i = a, b, c ! Attention: Loop will be skipped [execution part] end do Rule: Fortran checks the loop exit condition (a <= b) before starting the iteration do while (a < b) ! Loop will be continued as long as the condition is true [execution part] end do do i = a, b, c [execution part -1] if ( x == y ) cycle ! If satisfied, skip part of the loop after this point if ( m .ne. n ) exit ! If satisfied, exit the loop [execution part-2] end do Fortran 90 / 95 Programming
Fortran Arrays program arrays implicit none integer,parameter :: nRows = 5, nColumns = 3 integer :: allocStat double precision :: a(nRows, nColumns) ! Static array double precision, allocatable :: b(:,:) ! Dynamic array character (len=80) :: string = “text” allocate( b(nRows, nColumns), stat=allocStat) ! Allocate memory if (allocStat .ne. 0) stop ‘Error in memory allocation’ ! Check for allocation error a = 1.0d0 ! Assign 1.0d0 to each element of the array b = a ! Copy array a to b b(1,2) = 3.1d0 ! Access specific array element deallocate ( b, stat=allocStat ) ! Free the memory for other uses string(3:3) = “s” ! String is a special type of array ! continue computation and perform new cycles of allocation and deallocation, if necessary end program arrays Fortran 90 / 95 Programming
Fortran Input / Output: Files integer, parameter :: inputUnit = 10 character (len=512) :: fname = “input.txt” open (unit=inpUnit, file=fname, status='old', form='formatted’, access=‘sequential’) ! .. do some work on the file here .. close (inpUnit) unit - can be any number except system reserved ones; number >= 10 should be fine status - ‘old’ requires existing file fname, otherwise error ‘new’ new file will be created ‘unknown’ open existing file or new file will be created if one does not exist form - ‘formatted’ text file; can be ‘unformatted’ (binary file) access - ‘sequential’ default; can be ‘direct’ (for random access) Fortran 90 / 95 Programming
Fortran Input / Output: Read and Write Synopsis: read(unit, format) list-of-variable write(unit, format) list-of-variables Sample input string (for visual clarity, we use underscore to represent white space): Hydrogen _ _1 _ _ 1.35 _ _ 2.60 _ -1.24 ! _ will be used instead of white-space character program ReadFormattedText implicit none character (len=20) :: label integer :: index double precision :: x, y, z read(*,’(a8, i3, 3f6.2)’) label, index, x, y, z ! Read from standard input (console) write(*,’(a8, i3, 3f6.2)’) label, index, x, y, z ! Write to standard input endprogram ReadFormattedText Question: what will the result of write(*,’(a,i0)’) label, index Fortran 90 / 95 Programming
Fortran: Reading Command-Line Arguments program ReadArguments implicit none character (len=512) :: prgName, string integer :: nArgs double precision :: startingBalance nArgs = command_argument_count() ! Get the number of command-line arguments call getarg(0, prgName) ! 0-th argument is the program name if (nArgs < 3) then write(*,'(a,a,a)') "Usage: ", trim(prgName), & " startingBalance annualInterestRate minPaymentRate [fixedMinimum]" stop endif call getarg(1, string) read (string,*) startingBalance write (*,'(/a,f10.2)') "Starting balance = $", startingBalance end program ReadArgument Fortran 90 / 95 Programming
Fortran Intrinsic Functions Mathematical functions: sin, cos, tan, log, log10, exp, sqrt Presentation Title
Exercise: Sum up Even and Odd Numbers integer :: i, sumEven=0, sumOdd=0 ! Naive implementation do i = 1, 10 if (mod(i,2) == 0) then sumEven = sumEven + i else sumOdd = sumOdd + I endif eddo ! High-performance implementation do i = 1, 10 sumEven = sumEven + mod(i+1,2) * i sumOdd = sumOdd + mod(i,2) * i enndo Fortran 90 / 95 Programming
Fortran Compiler Efficiency Which code is faster? do i = 1, n a(i) = b(i+1) c(i) = b(i+1) end do The code on the left side performs one less addition. Would it help? do i = 1, n i1 = i+1 a(i) = b(i1) c(i) = b(i1) end do Fortran 90 / 95 Programming
Fortran Compiler Efficiency Which code is faster? do i = 1, n a(i) = b(i+1) c(i) = b(i+1) end do The code on the left side performs one less addition. Would it help? Answer: Both codes have the same speed, because fortran compiler automatically eliminates redundant operations. But, code on the left is easier to read. Thus, it represents the best coding practice. do i = 1, n i1 = i+1 a(i) = b(i1) c(i) = b(i1) end do Fortran 90 / 95 Programming
Index Computation We are doing a(i,j) = b(i,j) * 2.0d0, but “a” is a one-dimensional array index = 0 do j = 1, jSize do i = 1, iSize index = index + 1 a(index) = b(i,j) * 2.0d0 end do end do Which code is better? do j = 1, jSize do i = 1, iSize index = (j-1)*iSize + i a(index) = i * j end do end do Fortran 90 / 95 Programming
Index Computation We are doing a(i,j) = b(i,j) * 2.0d0, but “a” is a one-dimensional array index = 0 do j = 1, jSize do i = 1, iSize index = index + 1 a(index) = b(i,j) * 2.0d0 end do end do Which code is better? Better for serial computation Better for parallel computation do j = 1, jSize do i = 1, iSize index = (j-1)*iSize + i a(index) = i * j end do end do Fortran 90 / 95 Programming
Exercise: Compile Loan Simulator ls –l Makefile loan.F90 main.F90 read.F90 Type in the command-line: module add make make ./loan.x 1000 7.2 1.0 200.0 Fortran 90 / 95 Programming
User Defined Data Type type fmmcub ! Declare new data type “fmmcube” integer :: parent integer :: xyz(3) integer :: atomStart, nAtoms double complex, allocatable :: multipoleExpansion(:) endtype fmmcube integer :: nBoxes = 8, allocStat, nSzExpansion=10 type (fmmcube), allocatable :: box(:) ! Declare variable box using type fmmcube ! Perform two-level memory allocation allocate(box(0:nBoxes), stat=allocStat) do iBox = 1, nBoxes allocate(box(iBox)%multipoleExpansion(0:nSzExpansion), stat=allocStat) box(iBox)%multipoleExpansion = (0.0d0, 0.0d0) enddo Fortran 90 / 95 Programming
Useful Internet Resources • Fortran 90 intrinsic functions http://www.nsc.liu.se/~boein/f77to90/a5.html • Fortran 90 tutorial https://www.cac.cornell.edu/VW/Fintro/default.aspx • More just Goooooogle Fortran 90 / 95 Programming
Let us know your opinion http://www.bitly.com/fiuworkshop Thank you !!! Presentation Title