Fortran Programming Tips - ATM 562 Fall 2018 Fovell

 
Some Fortran programming tips
 
ATM 562 Fall 2018
Fovell
 
(see also PDF file on class page)
 
1
 
Background
 
“Fortran” derived from “formula translation”, and
emphasizes letting “math look like math”.
Fortran is NOT case sensitive.
Variables assumed 
real
, unless the first letter of the
variable name starts with the 
letters I-N
, inclusive.
Then they're integers by default.
(Mnemonic device: I-N are INtegers).
Fortran 90+ permits free format.  Fortran 77 (F77)
statements start in column 7, with column 6 for
continuation markers, and cols 1-5 for labels.
Comment lines start with 
“C”, “c”, or 
“!”.  Anything
after “!”, wherever it appears, is not read.
 
2
 
Arrays
 
Arrays are indexed from 1, unless otherwise specified.
Array indices must be integers.
 
 
      parameter(nx=50,ny=40,nz=25)
      dimension pressure(nx,ny,nz),
height(0:nz)
 
      do k=1,nz
       do j=1,ny
        do i=1,nx
         pressure(i,j,k) = [do something here]
        enddo ! i
       enddo  ! j
      enddo   ! k
Fortran is 
column-major
, which means
  it’s more efficient to put 
leftmost
  index in 
innermost
 loop (as here).
C++ and Python (Numpy) are row-major
 
3
 
More on arrays
 
If arrays are the same shape, can manipulate entire
arrays outside of do loops
 
      parameter(nx=50,nz=40)
      dimension pi(nx,nz),temp(nx,nz),theta(nx,nz)
 
! This…
      do k=1,nz
       do i=1,nx
         temp(i,k)=theta(i,k)*pi(i,k)
       enddo
      enddo
 
! …is equivalent to this…
      temp=theta*pi
 
4
 
A sample Fortran program
(F77-ish syntax)
 
 
5
 
      program example       ! this is optional, actually
! 
non-executable statements go first
: this includes parameter, common,
!  dimension, data statements and statement functions
 
! parameter statements make array bookkeeping easy
      parameter(nx=100,nz=40)
 
! common blocks hold arrays, constants you want to use in
!  multiple program modules
      common/base/ub(nz),tb(nz),qb(nz),pib(nz),rhou(nz),rhow(nz)
      common/uwind/up(nx,nz),u(nx,nz),um(nx,nz)    ! wind at 3 times
      common/ptemp/thp(nx,nz),th(nx,nz),thm(nx,nz) ! temp at 3 times
      common/grids/dx,dz,dt,d2t,time               ! grid setup, etc
      common/grid2/zw(nz),zu(nz)                   ! heights
      common/consts/rd,g,cp,psl                    ! physical constants
 
! dimension statements for local arrays - used only in this program unit
      dimension crap(nx,nz)
! initialize constant values you will 
NOT
 change during execution
      data g/9.8/,dx/400./,dz/400./,dt/2.0/,cp/1004./,rd/287./
 
6
 
!------------------------------------------------------------------------
! executable statements go here
!------------------------------------------------------------------------
 
! a neat way of getting trigonometric ``PI'' to machine precision
      trigpi=4.0*atan(1.0)
 
! frequent divisions should be converted to multiplications where possible
!  ex: I need to divide rd by cp a lot, and also (dx**2) and (dz**2)
 
      xk=rd/cp
      rdx2=1./(dx*dx)
      rdz2=1./(dz**2)
 
! block DOs are easy to read when indented.
! every DO has an ENDDO
! float turns an integer into a real before multiplication
 
      do k=2,nz
       zw=(float(k-1)*dz)
      enddo
 
7
 
! block IFs may be simple or compound
      iflag=0
 
      do k=2,nz-1
       ztp = (float(k)-1.5)*dz
       if(k.eq.2) iflag=1
       if(ztp.gt.ztr)then
        tb(k)=thetatr*exp(9.8*(ztp-ztr)/(cp*ttr)
       else
        tb(k)=300.+43.*(ztp/ztr)**1.25
       endif
       if(k.le.20)then
         [do something here]
 
       else if(k.lt.nz-5)then
         [do something here]
 
       else
         [do something here]
 
       endif
      enddo
 
8
 
! F77 continuation marker is most any symbol placed in column 6
!   for multiline statements
 
! **
line up
** your statements for easy debugging and reading
 
      do k=2,nz-1
       do i=2,nx-1
        thp(i,k)=thm(i,k)
     1      -0.5*dtx*(u(i+1,k)*(th(i+1,k)+th(i,k))
     2               -u( i ,k)*(th(i-1,k)+th(i,k)))
       enddo
      enddo
 
 
! subroutine calls make program neater, more modular
!  you can avoid passing unnecessary arguments using common statements
 
      call setup
      call runmodel
      call cleanup
 
9
 
! Example of a formatted write statement
 
      write(6,1000) real,integer,real
1000  format(1x,f5.2,i6,e15.6)
 
! you can avoid format statements when you don't need them
 
      write(6,*) ' the real number is ',real
! write to the screen with 
print
, which is the same as write(6,*)
 
      print *,' the real number is ',real
      print 1000, real, integer, real
! open a file before you write to it
! this opens a NEW formatted file called output at unit number 12
! if this file exists, it will cause an 
ERROR
! AVOID unit numbers 5 and 6; those are standard input and output
 
      open(12,file='output',status='new',form='formatted')
! OR open the file with status 
UNKNOWN
 which will overwrite any old
!   file of same name without warning
 
      open(13,file='output2',status='unknown',form='formatted')
! write to the file using the designated unit number
      write(12,*) rd,g,cp
 
10
 
! program ends with ``stop'' and ``end'' statements
      stop
      end
! then your subroutines go here.  they terminate with ``return'' and
!  ``end'' statements
 
      subroutine setup
      [your parameter and common blocks repeated here]
      return
      end
 
11
 
Continuation markers: F77 vs. F90+
 
! Fortran 77 style (file name using .f suffix usually defaults to F77)
      trigpi2 =  4.0*atan(1.0)
     1                /2
! Fortran 90+ style (file name using .f90 suffix indicates F90)
      trigpi2 =  4.0*atan(1.0) &
                      /2
! ...which is the same as
      trigpi2 =  4.0*atan(1.0) &
              &       /2
 
12
 
Global declarations
 
      program example2
      include 'global'
      [etc.]
 
      stop
      end
      subroutine setup
      include 'global'
      [etc.]
      return
      end
 
The file 
global
 
contains your parameter
  and array declarations, named common
  blocks, defined constants, etc..
 
If you modify this file, you need to
  recompile your code
 
13
 
Some common problems
 
Using values before they have been initialized
Many Fortran compilers initialize all variables and
array elements to zero… but not all
Find the error in the code below
      parameter(nx=100,nz=25)
      dimension u(nx), h(nz)
      do i=1,nx
       h(i)=…
      enddo
Combining integers and reals in computations
IFIX converts real to integer; FLOAT converts integer to
real
 
14
 
Some more common problems
 
Treating a real variable as an integer (and vice-
versa) can result in unexpected behavior
You can force yourself to declare type of all
variables with 
implicit none 
added to
nonexecutable section of your program
Some compilers provide flags for identifying
array overruns, zero divides and/or overflows
(useful for debugging); can slow down code
gfortran: 
-fbounds-check, -ffpe-trap=zero
or
 
ffpe-trap=overflow
 
15
Slide Note
Embed
Share

Background on Fortran programming emphasizing math, rules for variable types, use of arrays, and a sample Fortran program structure, including tips and best practices.

  • Fortran Programming
  • Tips
  • Arrays
  • Fovell

Uploaded on Sep 30, 2024 | 0 Views


Download Presentation

Please find below an Image/Link to download the presentation.

The content on the website is provided AS IS for your information and personal use only. It may not be sold, licensed, or shared on other websites without obtaining consent from the author. Download presentation by click this link. If you encounter any issues during the download, it is possible that the publisher has removed the file from their server.

E N D

Presentation Transcript


  1. Some Fortran programming tips ATM 562 Fall 2018 Fovell (see also PDF file on class page) 1

  2. Background Fortran derived from formula translation , and emphasizes letting math look like math . Fortran is NOT case sensitive. Variables assumed real, unless the first letter of the variable name starts with the letters I-N, inclusive. Then they're integers by default. (Mnemonic device: I-N are INtegers). Fortran 90+ permits free format. Fortran 77 (F77) statements start in column 7, with column 6 for continuation markers, and cols 1-5 for labels. Comment lines start with C , c , or ! . Anything after ! , wherever it appears, is not read. 2

  3. Arrays Arrays are indexed from 1, unless otherwise specified. Array indices must be integers. parameter(nx=50,ny=40,nz=25) dimension pressure(nx,ny,nz),height(0:nz) do k=1,nz do j=1,ny do i=1,nx pressure(i,j,k) = [do something here] enddo ! i enddo ! j enddo ! k Fortran is column-major, which means it s more efficient to put leftmost index in innermost loop (as here). C++ and Python (Numpy) are row-major 3

  4. More on arrays If arrays are the same shape, can manipulate entire arrays outside of do loops parameter(nx=50,nz=40) dimension pi(nx,nz),temp(nx,nz),theta(nx,nz) ! This do k=1,nz do i=1,nx temp(i,k)=theta(i,k)*pi(i,k) enddo enddo ! is equivalent to this temp=theta*pi 4

  5. A sample Fortran program (F77-ish syntax) 5

  6. program example ! this is optional, actually ! non-executable statements go first: this includes parameter, common, ! dimension, data statements and statement functions ! parameter statements make array bookkeeping easy parameter(nx=100,nz=40) ! common blocks hold arrays, constants you want to use in ! multiple program modules common/base/ub(nz),tb(nz),qb(nz),pib(nz),rhou(nz),rhow(nz) common/uwind/up(nx,nz),u(nx,nz),um(nx,nz) ! wind at 3 times common/ptemp/thp(nx,nz),th(nx,nz),thm(nx,nz) ! temp at 3 times common/grids/dx,dz,dt,d2t,time ! grid setup, etc common/grid2/zw(nz),zu(nz) ! heights common/consts/rd,g,cp,psl ! physical constants ! dimension statements for local arrays - used only in this program unit dimension crap(nx,nz) ! initialize constant values you will NOT change during execution data g/9.8/,dx/400./,dz/400./,dt/2.0/,cp/1004./,rd/287./ 6

  7. !------------------------------------------------------------------------ ! executable statements go here !------------------------------------------------------------------------ ! a neat way of getting trigonometric ``PI'' to machine precision trigpi=4.0*atan(1.0) ! frequent divisions should be converted to multiplications where possible ! ex: I need to divide rd by cp a lot, and also (dx**2) and (dz**2) xk=rd/cp rdx2=1./(dx*dx) rdz2=1./(dz**2) ! block DOs are easy to read when indented. ! every DO has an ENDDO ! float turns an integer into a real before multiplication do k=2,nz zw=(float(k-1)*dz) enddo 7

  8. ! block IFs may be simple or compound iflag=0 do k=2,nz-1 ztp = (float(k)-1.5)*dz if(k.eq.2) iflag=1 if(ztp.gt.ztr)then tb(k)=thetatr*exp(9.8*(ztp-ztr)/(cp*ttr) else tb(k)=300.+43.*(ztp/ztr)**1.25 endif if(k.le.20)then [do something here] else if(k.lt.nz-5)then [do something here] else [do something here] endif enddo 8

  9. ! F77 continuation marker is most any symbol placed in column 6 ! for multiline statements ! **line up** your statements for easy debugging and reading do k=2,nz-1 do i=2,nx-1 thp(i,k)=thm(i,k) 1 -0.5*dtx*(u(i+1,k)*(th(i+1,k)+th(i,k)) 2 -u( i ,k)*(th(i-1,k)+th(i,k))) enddo enddo ! subroutine calls make program neater, more modular ! you can avoid passing unnecessary arguments using common statements call setup call runmodel call cleanup 9

  10. ! Example of a formatted write statement write(6,1000) real,integer,real 1000 format(1x,f5.2,i6,e15.6) ! you can avoid format statements when you don't need them write(6,*) ' the real number is ',real ! write to the screen with print, which is the same as write(6,*) print *,' the real number is ',real print 1000, real, integer, real ! open a file before you write to it ! this opens a NEW formatted file called output at unit number 12 ! if this file exists, it will cause an ERROR ! AVOID unit numbers 5 and 6; those are standard input and output open(12,file='output',status='new',form='formatted') ! OR open the file with status UNKNOWN which will overwrite any old ! file of same name without warning open(13,file='output2',status='unknown',form='formatted') ! write to the file using the designated unit number write(12,*) rd,g,cp 10

  11. ! program ends with ``stop'' and ``end'' statements stop end ! then your subroutines go here. they terminate with ``return'' and ! ``end'' statements subroutine setup [your parameter and common blocks repeated here] return end 11

  12. Continuation markers: F77 vs. F90+ ! Fortran 77 style (file name using .f suffix usually defaults to F77) trigpi2 = 4.0*atan(1.0) 1 /2 ! Fortran 90+ style (file name using .f90 suffix indicates F90) trigpi2 = 4.0*atan(1.0) & /2 ! ...which is the same as trigpi2 = 4.0*atan(1.0) & & /2 12

  13. Global declarations program example2 include 'global' [etc.] The file globalcontains your parameter and array declarations, named common blocks, defined constants, etc.. stop end subroutine setup include 'global' [etc.] return end If you modify this file, you need to recompile your code 13

  14. Some common problems Using values before they have been initialized Many Fortran compilers initialize all variables and array elements to zero but not all Find the error in the code below parameter(nx=100,nz=25) dimension u(nx), h(nz) do i=1,nx h(i)= enddo Combining integers and reals in computations IFIX converts real to integer; FLOAT converts integer to real 14

  15. Some more common problems Treating a real variable as an integer (and vice- versa) can result in unexpected behavior You can force yourself to declare type of all variables with implicit none added to nonexecutable section of your program Some compilers provide flags for identifying array overruns, zero divides and/or overflows (useful for debugging); can slow down code gfortran: -fbounds-check, -ffpe-trap=zero or ffpe-trap=overflow 15

More Related Content

giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#