University of Leicester
Department of Physics and Astronomy
Second Year Computing Workshop
Modular Programming in Fortran 90
Prof. R. Willingale
October 2, 2012
1
University of LeicesterDepartment of Physics and AstronomyFirst Year Computing WorkshopModular Programming in Fortran 90
Document: modular f90Issue: 3.1Date: October 2, 2012Page: 2
Contents
1 Introduction 4
2 Books and reference 4
3 Getting started 5
3.1 Logging on . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
3.2 Creating and running a F90 program . . . . . . . . . . . . . . . . . . . . . 6
4 A pendulum problem 6
5 Modular Programming 8
5.1 The F90 function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
5.2 Task 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
5.3 The F90 module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
5.4 Task 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
5.5 The F90 subroutine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
5.6 Task 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
6 Integrating the equations of motion 14
6.1 Task 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
6.2 Task 5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
6.3 Task 6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
6.4 Task 7 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
University of LeicesterDepartment of Physics and AstronomyFirst Year Computing WorkshopModular Programming in Fortran 90
Document: modular f90Issue: 3.1Date: October 2, 2012Page: 3
7 Plotting the motion of the pendulum 16
7.1 Task 8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
7.2 Task 9 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
8 More about arrays 18
9 The F90 case construct 19
10 Exploring the complexities of the motion 20
10.1 Task 10 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
10.2 Task 11 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
10.3 Task 12 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
11 Further investigation 22
11.1 Task 13 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
12 Further F90 22
13 Quick Fortran 90 reference 23
13.1 Character set, statements, literals and variable names . . . . . . . . . . . . 23
13.2 Declarations, dynamic allocation . . . . . . . . . . . . . . . . . . . . . . . . 23
13.3 Formatted input and output . . . . . . . . . . . . . . . . . . . . . . . . . . 24
13.4 Arithmetic and assignment . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
13.5 Decision structures, definite and indefinite loops . . . . . . . . . . . . . . . 26
13.6 Intrinsic functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
13.7 Types of code module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
University of LeicesterDepartment of Physics and AstronomyFirst Year Computing WorkshopModular Programming in Fortran 90
Document: modular f90Issue: 3.1Date: October 2, 2012Page: 4
1 Introduction
In the first year you had your first taste of computing and programming. This workshop isdesigned to give you more practice and experience in using Fortran 90. Before you startplease read this script carefully. It is important that you attempt the programmingindividually, not in pairs or as a consortium. You can only become proficient atprogramming by doing it yourself, not by watching someone else. The workshop is nota race and you must not worry if you seem to be falling behind others. The personwho completes first will almost certainly have made mistakes or cut a few corners. YouMUST keep a record of what you do in your laboratory workbook, obtain listings of allyour programs and retain the program source files on your directory at the end of the 4laboratory sessions so that your work can be accessed.
You use the UoL IT Windows machines to access the SPECTRE system in the same wayas described in the 1st year script.
2 Books and reference
There are many good books on Fortran 90. Notes on the syntax were provided lastyear and are extended below but they are not intended to be a comprehensive text incompetition with published material. You don’t have to buy a book but the followingbooks are recommended. Whichever book you choose make sure it is up to date andcovers the 1990 standard. Most books on Fortran 90 do contain a description of the 77standard but be warned there are significant differences between f77 and f90. Do notpurchase a book which only covers the 77 standard.
• Fortran 90 Programming, T.M.R. Ellis, I.R.Philips, T.M. Lahey, Addison Wesley,1994
• Fortran 90 Explained, M. Metcalf and J. Reid, Oxford University Press, 1990
The script for this workshop, the scripts for other workshops, useful references on Fortran90, documentation on the subroutine library PGPLOT and a guide to using Irix and Wordcan all be found on the World Wide Web at URL:
http://www.star.le.ac.uk/~rw/compshop/
University of LeicesterDepartment of Physics and AstronomyFirst Year Computing WorkshopModular Programming in Fortran 90
Document: modular f90Issue: 3.1Date: October 2, 2012Page: 5
3 Getting started
3.1 Logging on
You must first log on to UoL IT Windows. To login into SPECTRE you must use theX-terminal client called NX. To install NX (only need to do this once) use
Programs-->Program Installer-->NX Client (click)
To login to SPECTRE use
Programs-->NX Client (click) SPECTRE (click)
Type it your UoL IT username and password.
Start a Terminal command line window using
Applications-->Accessories-->Terminal (click)
When the terminal window starts up you should get a system prompt like
[zrw@spectre02~]$
You type commands in response to this prompt.
To logout use
System--Log Out (click)
Please don’t leave your terminal logged on and unattended.
University of LeicesterDepartment of Physics and AstronomyFirst Year Computing WorkshopModular Programming in Fortran 90
Document: modular f90Issue: 3.1Date: October 2, 2012Page: 6
3.2 Creating and running a F90 program
This is fully explained in the first year workshop. If you have forgotten how to do thisnow is the time to look it up.
To summarise, use the following commands to create and run a program
$ nedit <name>.f90 &
$ gfortran <name>.f90 -o <name>
$ ./<name>
If you want to find more about the UNIX operating system you can browse through thehelp manual using the man command.
$ man -k text
$ man command
This uses the command more to give pages of information. The -k option allows you tosearch the manual for specific text sequences. Otherwise you must search for a specificcommand.
4 A pendulum problem
We are going to use a dynamics problem involving a magnetically perturbed pendulumas a vehicle to introduce the scope and power of F90. The problem cannot be solvedanalytically and exhibits complicated chaotic behaviour as well as simpler regular motion.
The magnetically perturbed pendulum in question is similar to some executive toys youcan buy to adorn your desk and distract you when the going gets tough. It consists of amagnetic bob suspended on a wire or string which lies along the z-axis when the wire isvertical. The bob is free to move in both x and y and we will only consider the motionof the bob in the horizontal xy plane. To make the motion more interesting the bob isperturbed by a magnet which can be placed in the xy plane just underneath the swingingpendulum. When the bob passes near to the magnet the path is deflected violently andmakes the pendulum swing in a random way. The geometry of the pendulum is illustratedin figure 1.
The motion is described by 2 simple coupled differential equations:
University of LeicesterDepartment of Physics and AstronomyFirst Year Computing WorkshopModular Programming in Fortran 90
Document: modular f90Issue: 3.1Date: October 2, 2012Page: 7
magnet
bobzy
x Y
Z
X
xm
zmym
Figure 1: The magnetically perturbed pendulum
d2x/dt2 = −gx−m(x− xm)/r8
m − d dx/dt
d2y/dt2 = −gy −m(y − ym)/r8
m − d dy/dt
In each case the 3 terms on the right correspond to gravity, the magnetic perturbationand air drag. The constants g, m and d depend on the mass of the bob, the strengthof the magnet and the viscocity of air. The fixed magnet is at position (xm, ym, zm)and rm = ((x − xm)
2 + (y − ym)2 + (z − zm)
2)1/2. Actually these equations are onlyan approximation to the real state of affairs but as you will be able to demonstrate foryourselves this doesn’t matter.
If m and d are zero then the pendulum executes simple harmonic motion in x and yand the bob follows an elliptical path in the xy plane. If d is zero then the motion isconservative (no energy loss) and we can express the force using a potential energy:
V = g r2/2−m/6r6m
University of LeicesterDepartment of Physics and AstronomyFirst Year Computing WorkshopModular Programming in Fortran 90
Document: modular f90Issue: 3.1Date: October 2, 2012Page: 8
where r = (x2 + y2)1/2. The forces in x and y (not including drag) are then given by thegradients:
fx = −dV/dx
fy = −dV/dy
The kinetic energy is given by:
T = ((dx/dt)2 + (dy/dt)2)/2
The state of the bob at any time is specified by 4 numbers ( x, y, dx/dt , dy/dt). Thesedefine what is called a phase space for the system. As time progresses the bob will traceout a path in phase space. If we take a particular starting position for the bob in phasespace we can calculate the path by integrating the differential equations. There we haveit. The problem is to integrate the differential equations given g, m , d, and a startingposition and to find the path of the bob in phase space.
In the context of Fortran programming we will represent the position in phase space byan array of 4 numbers, P(4) where P(1) and P(2) are the position in xy and P(3) andP(4) are the corresponding velocities.
In the following script the tasks you are expected to do are described in subsectionsentitled Task n.
5 Modular Programming
Last year you learnt how to write a simple PROGRAM section. This year you will beexposed to the full power of F90; in particular we are going to use Modular Programminginvolving MODULEs, SUBROUTINEs and FUNCTIONs. Correct use of these makes thecode easier to write, easier to maintain and alter and in many cases more efficient.
5.1 The F90 function
We will start with functions. These are just like the intrinsic functions SIN, COS and soforth but you define what is required and how to calculate the answers.
University of LeicesterDepartment of Physics and AstronomyFirst Year Computing WorkshopModular Programming in Fortran 90
Document: modular f90Issue: 3.1Date: October 2, 2012Page: 9
Suppose we have the position of the pendulum bob in phase space and want a functionto return the kinetic energy. The code for the function might look like the following:
FUNCTION PEND_KE(P)
! Return the kinetic energy of pendulum
IMPLICIT NONE
INTEGER, PARAMETER :: DOUB_PREC=SELECTED_REAL_KIND(P=10,R=30)
REAL(DOUB_PREC) :: PEND_KE,P(4)
! Calculate kinetic energy using velocities
PEND_KE=0.5*(P(3)**2+P(4)**2)
END FUNCTION PEND_KE
The first line starts the definition of the function. It defines the name, in this casePEND KE, and then defines the argument list, in this case just one variable P. The linestarting INTEGER, PARAMETER defines a parameter DOUB PREC which is used inthe declarations of the REAL variables. We will say more of this later. Notice that thefunction name PEND KE and the array P(4) are both declared REAL(DOUB PREC).This is because the answer is returned in the name of the function as shown in theassignment line. Finally the line starting END completes the definition of the newfunction.
In order to use the function we must evoke it in a program:
PROGRAM TEST_FUN
IMPLICIT NONE
INTEGER, PARAMETER :: DOUB_PREC=SELECTED_REAL_KIND(P=10,R=30)
REAL(DOUB_PREC) :: PEND_KE,P(4),A
! Read in position in phase space
PRINT *,"type position x,y,vx,vy"
READ *,P
A=PEND_KE(P)
PRINT *,"Kinetic energy",A
END PROGRAM TEST_FUN
5.2 Task 1
Type in the function and the test program which uses it into the same source file. Compileand run the program and check that the result is correct by using simple numbers or usinga calculator. Note that it is not necessary for P to have the same name in the functionand the calling program. Verify this by changing the name in one or the other. The only
University of LeicesterDepartment of Physics and AstronomyFirst Year Computing WorkshopModular Programming in Fortran 90
Document: modular f90Issue: 3.1Date: October 2, 2012Page: 10
requirement is that the type of the argument used in the calling routine is the same asdeclared within the function.
5.3 The F90 module
In the above you had to type the definition line for the DOUB PREC parameter in boththe function and the program module. It is often the case that the same declarationlines are required to appear in a large number of places. Furthermore it is often useful todefine some variables as global between a number of routines rather than passing them asarguments. The MODULE provides a clean and uniform way to achieve these and otherfunctions.
The following module defines various things which will be useful in the programmingsolution to our pendulum problem.
MODULE PEND_DEF
! Definitions for magnetic pendulum
IMPLICIT NONE
SAVE
! Select precision for real numbers
INTEGER, PARAMETER :: DOUB_PREC=SELECTED_REAL_KIND(P=10,R=30)
INTEGER, PARAMETER :: SING_PREC=SELECTED_REAL_KIND(P=6,R=30)
! Definition of data type for pendulum parameters
TYPE PEND_PARAM
! Position of fixed magnet
REAL(DOUB_PREC), DIMENSION(3) :: POS
! Force constants for magnet, gravity and drag
REAL(DOUB_PREC) :: FMAG,FGRA,FDRA
END TYPE PEND_PARAM
! Declare global for magnet parameters
TYPE(PEND_PARAM) :: G ! parameters of fixed magnet etc.
END MODULE PEND_DEF
The first line starts the definition and gives the module a name and the last linestarting with END completes the definition. The IMPLICIT NONE and SAVE linesare recommended in all modules since they ensure that every variable is defined and isnon- volatile. The INTEGER declarations define two integer constants which refer toREAL types of a specified precision (P=) and range (R=). These are required becausesingle precision (P=6 decimal digits) is insufficient to give adequate precision for thesolution to our problem. However when we come to plot the results later we mustuse single precision variables for the plotting routines. So all variables which are used
University of LeicesterDepartment of Physics and AstronomyFirst Year Computing WorkshopModular Programming in Fortran 90
Document: modular f90Issue: 3.1Date: October 2, 2012Page: 11
in calculation will be declared REAL(DOUB PREC) while plotting variables must bedeclared REAL(SING PREC). The remaining lines in the MODULE PEND DEF defineand declare a new data type. In Fortran 90 new data types can be defined in termof existing data types. In this case a new type called PEND PARAM consisting of aposition for the fixed magnet (an array P(3)) and three constants FMAG, FGRA andFDRA (corresponding to m, g, d above). The lines between TYPE PEND PARAM andEND TYPE perform this definition. The new data type is then used to declare a (global)variable G which will hold all the required information about the pendulum.
That completes the definition of the module. To include the definitions provided by themodule in a PROGRAM or FUNCTION (or SUBROUTINE, see later) you must putUSE name as the first line after the start of the new routine.
As an example of this we are now going to produce a FUNCTION which returns thepotential energy of the pendulum. If you refer back to the pendulum equations you willsee this requires the constants m and g (FMAG and FGRA components of G). You cansee below how the MODULE PEND DEF is included into the FUNCTION PEND PEand how the components of G are referred to using the syntax G%FMAG to pick out thevalue of m and G%POS(1) to pick out the x position of the magnet.
FUNCTION PEND_PE(P)
! Return the potential energy of pendulum
USE PEND_DEF
IMPLICIT NONE
REAL(DOUB_PREC) :: PEND_PE,P(4)
! Local variables
REAL(DOUB_PREC) :: R2,RM2,XM,YM,RMZ2
! Calculate radial coordinates
XM=P(1)-G%POS(1)
YM=P(2)-G%POS(2)
R2=P(1)**2+P(2)**2
RM2=XM**2+YM**2
RMZ2=RM2+G%POS(3)**2
! Calculate potential
PEND_PE=0.5*G%FGRA*R2-G%FMAG/(RMZ2**3)/6.0
END FUNCTION PEND_PE
5.4 Task 2
Type the PEND DEF module and the PEND PE function into your source file whichcontains the PEND KE function and the TEST program. Modify the function PEND KE
University of LeicesterDepartment of Physics and AstronomyFirst Year Computing WorkshopModular Programming in Fortran 90
Document: modular f90Issue: 3.1Date: October 2, 2012Page: 12
so that the definition of the parameter DOUB PREC is included from the PEND DEFmodule (i.e. put USE PEND DEF into the function PEND KE). Finally we need tomodify the test program to USE PEND KE and to initialize the values of the magnetconstants and test both functions. The start of the program will look like:
PROGRAM TEST
USE PEND_DEF
IMPLICIT NONE
REAL(DOUB_PREC) :: PEND_KE,P(4),A
! Get magnet parameters
PRINT *, "x,y,z,mag,grav,drag"
READ *, G
...
Your source file should now contain the MODULE PEND DEF, the FUNCTIONPEND KE, the FUNCTION PEND PE and the PROGRAM TEST.
The program should read in the magnet parameters and the position of the bob in phasespace and then test the two functions.
5.5 The F90 subroutine
In order to solve the coupled differential equations of our pendulum problem we need totranslate the equations into Fortran. This is best done using a SUBROUTINE which isthe last form of module supported by F90. Unlike a FUNCTION all the information toand from a SUBROUTINE is passed as arguments. In general some arguments will bepurely input, some will be input, modified by the routine and then output and others willbe just output. We want a routine which will calculate the derivatives of the position inphase space given the position and time. The following subroutine does this:
SUBROUTINE PEND_EQM(T,P,PDOT)
! Differential equations of motion for the magnetic pendulum
USE PEND_DEF
IMPLICIT NONE
REAL(DOUB_PREC) :: T ! time
REAL(DOUB_PREC) :: P(4) ! position in phase space
REAL(DOUB_PREC) :: PDOT(4) ! returned derivatives
! Local variables
REAL(DOUB_PREC) :: XM,YM,RMZ,FM
! Calculate radius from fixed magnet
University of LeicesterDepartment of Physics and AstronomyFirst Year Computing WorkshopModular Programming in Fortran 90
Document: modular f90Issue: 3.1Date: October 2, 2012Page: 13
XM=P(1)-G%POS(1)
YM=P(2)-G%POS(2)
RMZ=SQRT(XM**2+YM**2+G%POS(3)**2)
! Calculate magnetic force
FM=G%FMAG/(RMZ**8)
! Calculate derivatives
PDOT(1)=P(3)
PDOT(2)=P(4)
PDOT(3)=-G%FGRA*P(1)-FM*XM-P(3)*G%FDRA
PDOT(4)=-G%FGRA*P(2)-FM*YM-P(4)*G%FDRA
END SUBROUTINE PEND_EQM
Read this carefully and convince yourself that it faithfully reproduces the requiredequations. The arguments T and P are the time and position (input arguments) andPDOT holds the output values of the derivatives. Like the functions we defined abovethe new routine uses the module PEND DEF to provide definitions of DOUB PREC andthe global variable G.
5.6 Task 3
Type the PEND EQM routine into your source file. In order to use the SUBROUTINEyou must CALL it. The extra lines you need in the TEST FUN program are declarationsfor T and PDOT (to be put with all the other definitions before any executable code):
REAL(DOUB_PREC) :: T ! time
REAL(DOUB_PREC) :: PDOT(4) ! returned derivatives
a print and read to get the time:
PRINT *,"Type time"
READ *,T
and the call to the subroutine followed by a print to list the result:
CALL PEND_EQM(T,P,PDOT)
PRINT *,"derivatives",PDOT
University of LeicesterDepartment of Physics and AstronomyFirst Year Computing WorkshopModular Programming in Fortran 90
Document: modular f90Issue: 3.1Date: October 2, 2012Page: 14
6 Integrating the equations of motion
In order to perform the integration another subroutine is required. This routine starts asfollows:
SUBROUTINE RUNKUT(DT,F,TIME,NV,P)
The routine performs an integration step by the fourth order Runge-Kutta method. Youdon’t need to know what this is , you just need to know how to call the routine. Thearguments of the routine are as follows:
REAL(DOUB_PREC) :: DT ! The time step
EXTERNAL F ! The subroutine to return derivatives
REAL(DOUB_PREC) :: TIME ! The time
INTEGER :: NV ! The number of variables
REAL(DOUB_PREC) :: P(NV) ! The new position in phase space
For the present application F will be the subroutine PEND EQM and NV=4. RUNKUTwill use subroutine PEND EQM to predict the new position of the pendulum at timeTIME+DT. The routine updates the TIME and P variables every call.
6.1 Task 4
Copy the source for this routine from file /home/z/zrw/under/runkut.f90 and append itto your source file using the commands:
$ cp /home/z/zrw/under/runkut.f90 .
$ cat runkut.f90 your.f90 > your_new.f90
If you look at the routine you will see that variable names are not the same as above.This doesn’t matter since variable names are only local to each routine unless they appearin a MODULE. In fact the RUNKUT subroutine has no connection with the pendulumproblem other than it provides a method of solving ordinary differential equations. Allthe information about the problem is passed to the routine in the arguments F and NV.
The program required to integrate the pendulum equations must do the following:
University of LeicesterDepartment of Physics and AstronomyFirst Year Computing WorkshopModular Programming in Fortran 90
Document: modular f90Issue: 3.1Date: October 2, 2012Page: 15
• Read in the magnet parameters. Your test program should already do this.
• Read in an initial position for the bob. Again the test program should do this.
• Read in a time step size (a value for DT) and a number of steps (NSTEP say).
• Loop calling RUNKUT on each pass to increment the time and calculate the newposition. Print the position and velocity of the bob for each pass of the loop.
6.2 Task 5
Modify the new source program to integrate the equations. If you can’t remember howDO loops work refer to last year’s notes.
In order to test the program is working you should calculate the answer in cases whenyou know the expected results. For example if d=0 and m=0 then the bob should executesimple harmonic motion. If g=1 what is the frequency? Choose the time increment DTsuch that you get several tens of samples for each complete cycle. Make sure that themotion gives the frequency as expected if g is altered.
6.3 Task 6
If you set g=1 then (xm, ym, zm) = (1, 0,−1) and m=300 will define a magnet that givesthe bob a reasonable perturbation. In this case you will need DT=0.005 or smaller togive reliable results. If the time increment is too large then the Runge-Kutta method mayintroduce a small error that will accumulate if a very large number of steps is taken. Ifd=0 then the energy of the system should be conserved. You can check this by using theKE and PE functions we looked at earlier. Try running the program with different valuesof DT and many steps (10000 say) and check that the energy remains constant. If youuse a large number of steps you won’t want to print out the position for every pass. Youcan use the intrinsic MOD() function to select every nth pass for printing.
DO J=1,NSTEPS
...
IF(MOD(J,100).EQ.0) THEN
... print stuff out every 100th pass
ENDIF
ENDDO
University of LeicesterDepartment of Physics and AstronomyFirst Year Computing WorkshopModular Programming in Fortran 90
Document: modular f90Issue: 3.1Date: October 2, 2012Page: 16
6.4 Task 7
Now try introducing some air drag and see what happens. Does the program behave asexpected? Can you find a stable point for the pendulum bob in phase space? Is thispoint where you expect it to be? What happens if you make m (the force constant of themagnet) negative?
7 Plotting the motion of the pendulum
The best way of presenting many results is to plot a graph. If you plot x as a function of tas calculated above it should be easy to see if your results are sensible or not. If you plotx vs. y or x vs. vx then it is easier to visualize the path of the pendulum in phase space.In order to do this you need to use some form of graphics software. This is provided inthis workshop by a package of subroutines called PGPLOT. A manual describing this setof subroutines and how to use them can be borrowed from the Laboratory PreparationRoom or you can use the links on the World Wide Web page:
http://www.star.le.ac.uk/~rw/compshop/
7.1 Task 8
To use the PGPLOT routines the results need to be stored in single precision arrays. Todo this you will need to add the following into your program:
REAL(SING_PREC), ALLOCATABLE, DIMENSION(:) :: X,Y,VX,VY,T,PE,KE
This is a declaration of allocatable arrays which must appear before the executablestatements. You will notice that the dimension of the arrays is not specified (:). Inour program we do not know the number of time steps required until it is typed in by theuser therefore we don’t know beforehand how large the arrays need to be. After the linewhich reads in NSTEP we can actually allocate the array space using:
ALLOCATE(X(NSTEP),Y(NSTEP),VX(NSTEP),VY(NSTEP),T(NSTEP))
ALLOCATE(PE(NSTEP),KE(NSTEP))
The loop which performs the calculation should then be modified as follows:
University of LeicesterDepartment of Physics and AstronomyFirst Year Computing WorkshopModular Programming in Fortran 90
Document: modular f90Issue: 3.1Date: October 2, 2012Page: 17
TIME=0.0
X(1)=P(1)
Y(1)=P(2)
VX(1)=P(3)
VY(1)=P(4)
T(1)=TIME
PE(1)=PEND_PE(P)
KE(1)=PEND_KE(P)
DO J=2,NSTEP
CALL RUNKUT(DT,PEND_EQM,TIME,NV,P)
X(J)=P(1)
Y(J)=P(2)
VX(J)=P(3)
VY(J)=P(4)
T(J)=TIME
PE(J)=PEND_PE(P)
KE(J)=PEND_KE(P)
ENDDO
The PGPLOT calls needed to plot the results are:
! Open plotting device
CALL PGBEGIN(0,"?",1,1)
! Define environment (XMIN and XMAX must be declared SING_PREC)
XMIN=MINVAL(X)
XMAX=MAXVAL(X)
XRANG=XMAX-XMIN
XMIN=XMIN-XRANG*0.05
XMAX=XMAX+XRANG*0.05
CALL PGENV(T(1),T(NSTEP),XMIN,XMAX,0,1)
! Draw axes and border with labels
CALL PGLABEL("time","X","Pendulum displacement vs. time")
! Draw curve
CALL PGLINE(NSTEP,T,X)
! Clear up and end plotting
CALL PGEND
The library of subroutines must be made available to your program when you use thecompiler/linker and the commands you will need to produce a plot are as follows.
$ source /home/z/zrw/under/pgplot_f90
University of LeicesterDepartment of Physics and AstronomyFirst Year Computing WorkshopModular Programming in Fortran 90
Document: modular f90Issue: 3.1Date: October 2, 2012Page: 18
$ gfortran <name>.f90 ‘pgplot_f90_link‘ -o <name>
$ ./<name>
The first line (starting with source) is only required once during a session. The‘pgplot_f90_link‘ (use the single quotes at the top left of the keyboard) includes thenecessary object libraries into the gfortran command. When you run the program thePGBEGIN routine will prompt for a device name. The device type you should use on theX-terminals is /XS Hardcopy can be obtained using /PS (landscape) and /VPS (portrait).These create a Postscript text file called pgplot.ps which can be copied to your Windowsmachine for printed etc.
Open Explorer in Windows and enter the URL
\\spectre01.rcs.le.ac.uk\username
This will connect you to your home disk on SPECTRE. Locate the pgplot.ps file and thendrag it from the Explorer window onto the Desktop. If you then double-click on the fileit will open a print facility. Select the PostScript Driver and you can print the file. If youset the destination to be CutePDF Write then the print facility with create a PDF file ofthe plot.
7.2 Task 9
If you call PGENV again (before CALL PGEND) plotting will advance to the next page,panel or screen and prepare for another graph. You can split up a single screen into panelsusing the last 2 arguments of PGBEGIN. These specify the number of panels across anddown the full screen. Each subsequent call to PGENV will then advance to the nextpanel and more than 1 plot can be displayed on a single screen. Add further code to yourprogram to plot x vs. y and x vs. vx.
8 More about arrays
A few more words about arrays are in order. In the functions PEND PE and PEND KEthe dimension of the array P(4) was declared in both the calling program and the functionand there was no mention of the size in the argument list. In this context, where thenumber of elements was fixed by the problem (the dimension of the phase space of thependulum), this was reasonable. However in general it is a good idea to pass the size of
University of LeicesterDepartment of Physics and AstronomyFirst Year Computing WorkshopModular Programming in Fortran 90
Document: modular f90Issue: 3.1Date: October 2, 2012Page: 19
array dimensions as INTEGER arguments to the FUNCTION or SUBROUTINE. Thestart of the RUNKUT routine illustrates this.
SUBROUTINE RUNKUT(H,F,X,N,Y)
! Fourth order Runge-Kutta
IMPLICIT NONE
INTEGER, PARAMETER :: DOUB_PREC=SELECTED_REAL_KIND(P=10,R=30)
INTEGER :: N ! number of y’s
REAL(DOUB_PREC) :: H,X,Y(N) ! x step size, x, y’s
EXTERNAL F ! subroutine F(X,Y,YPRIME)
! F returns derivatives wrt x in yprime
! Author Dick Willingale 1996-Jul-25
! Local automatic arrays for workspace
REAL(DOUB_PREC) :: F1(N),F2(N),F3(N),F4(N)
REAL(DOUB_PREC) :: Y1(N),Y2(N),Y3(N),Y4(N)
REAL(DOUB_PREC) :: K1(N),K2(N),K3(N),K4(N)
REAL(DOUB_PREC) :: X1,X2,X3,X4
INTEGER :: J ! local index
...
The N is passed as an argument along with Y and the declaration is of the form Y(N).These arguments are called dummy arguments. The actual location of N and Y is in thecalling routine not within RUNKUT. The advantage of this is that the routine can beused for any dimension of y (number of variables in the equations), not just the problemin hand for which N=4 and of course N is available for use within the routine as well.
This routine also demonstrates another useful way of declaring arrays in SUBROUTINEsand FUNCTIONs. In the last few declaration lines a number of local arrays are declaredusing the argument N (e.g. F1(N)). These are called automatic arrays and can bedeclared in this manner to create workspace for the calculations inside a SUBROUTINEor FUNCTION.
9 The F90 case construct
There is another way of controlling the flow of the execution of statements in F90 calledthe CASE construct. It is designed specifically for use by character strings or integersand works for logicals. It has the form:
SELECT CASE(expression_select)
University of LeicesterDepartment of Physics and AstronomyFirst Year Computing WorkshopModular Programming in Fortran 90
Document: modular f90Issue: 3.1Date: October 2, 2012Page: 20
CASE(expression1)
F90 statements
CASE(expression2)
F90 statements
CASE DEFAULT
F90 statements
END SELECT
The expression select is a character string (or integer) which will determine which of thefollowing cases is executed. If none of the expression1 etc. is satisified then the DEFAULTwill be used. The expressions use must not be REAL. To control flow with REAL valuesthey must be converted to INTEGER or LOGICAL (using some expression) and used inCASE or IF constructs.
10 Exploring the complexities of the motion
If you play about with the starting point of the pendulum bob (initial position andvelocity) you will soon discover that the motion of the pendulum can be very complicatedwith no apparent structure or regular behaviour. It is very difficult to make sense of whatis going on by plotting the path as described above.
A more useful view of the motion is provided by what is known as the Poincare Section,particularly if the air drag (energy loss) is zero (d=0). If you define a plane in phasespace, for example the y=0 plane, then, as the pendulum swings about, the path in phasespace will cross the plane on a regular basis. Every time the path crosses the plane itdefines a point (which can be plotted). Actually we should restrict the points to those forwhich the path is travelling from y<0 to y> 0 (or the other way around). The section ofthe path between such points then defines what is called an orbit in phase space. If themotion is allowed to continue then the plotted points gradually build up a picture of thePoincare Section of the motion.
If the motion is periodic then the path will eventually return to a point already plottedand the sequence will start again. Indeed, if the motion is particularly simple then thepicture may consist of just one point! If the motion is chaotic then the bob never returnsto the same position in phase space and the Poincare Section picture will consist of aninfinite number of points covering some area of the plane. Somewhere in between thesimple regular picture and chaos there are some rather complicated patterns as you willsee.
The next task is to modify your program to plot a Poincare Section. The changes areremarkably simple. You must now control an outer loop by the number of section points
University of LeicesterDepartment of Physics and AstronomyFirst Year Computing WorkshopModular Programming in Fortran 90
Document: modular f90Issue: 3.1Date: October 2, 2012Page: 21
required rather than the number of steps. An inner loop must be indefinite since you nolonger know how many integration steps are required. If the number of points requestedis NP then the loops will look something like:
TIME=0.0
DO J=1,NP
DO
POLD=P
CALL RUNKUT(TINC,PEND_EQM,TIME,NV,P)
IF(P(4)>0.0.AND.POLD(2)<0.0.AND.P(2)>=0.0) THEN
EXIT
ENDIF
ENDDO
X(J)=POLD(1)
Y(J)=POLD(2)
VX(J)=POLD(3)
VY(J)=POLD(4)
PE(J)=PEND_PE(POLD)
KE(J)=PEND_KE(POLD)
T(J)=TIME
ENDDO
An array POLD(4) is used to save the position before RUNKUT is called. The inner loopkeeps running until the path crosses the y=0 plane going in the positive direction. Sincethe motion of the pendulum is bounded this is going to happen sooner or later. The outerloop saves NP points of the section.
10.1 Task 10
Modify your program so that it can calculate either the path or the section of the motionusing a CASE construct controlled by a character variable.
You can plot out the points using:
CALL PGPOINT(NP,X,VX,ICHAR)
where ICHAR=1 (type INTEGER) gives a point. To plot other symbols use higher valuesof ICHAR. For example ICHAR=2 gives + and ICHAR=3 gives *.
University of LeicesterDepartment of Physics and AstronomyFirst Year Computing WorkshopModular Programming in Fortran 90
Document: modular f90Issue: 3.1Date: October 2, 2012Page: 22
10.2 Task 11
The above is only an approximation since the actual intersection with the plane issomewhere between POLD and P. Now’s your chance to write a SUBROUTINE fromscratch. Try producing a routine which estimates the intersection point by linearinterpolation, i.e. using a straight line to join POLD to P. Before you start typing anycode, work out exactly what the required calculation is. Then, decide on the subroutineinterface required and finally write the code. Before you introduce it into the pendulumprogram test that it is working correctly using a simple test program.
10.3 Task 12
You can now use your program to explore the motion of the pendulum. See if you can findstarting values (with d=0) which lead to regular (periodic) and chaotic motion. Can youfind a motion in which the points in the Poincare section form loops? This correspondsto motion on a toroid in phase space and is a form of quasi-periodic motion.
11 Further investigation
11.1 Task 13
The form of the motion depends on the the total energy of the system. If you set theair drag to a very small value the pendulum will gradually drift through different typesof motion. It is possible to draw sections corresponding to a range of energies by turningthe drag off and on as the calculation proceeds. See if you can modify your program todo this. The resulting pictures can be astonishingly complicated, amply demonstratingthat relatively simple differential equations can lead to extremely complicated behaviour.
12 Further F90
The first and second year Fortran Workshops have introduced most of the importantfeatures of F90. However there are a few topics which have been omitted. F90 can handlepointers to data rather than using conventional variables. These are most useful when thedata base is dynamic, for example in real-time control and analysis. The power and scopeof I/O has been ignored. In particular we have not mentioned unformatted input/outputand have only touched apon FORMAT statements for contolling formatted I/O. There
University of LeicesterDepartment of Physics and AstronomyFirst Year Computing WorkshopModular Programming in Fortran 90
Document: modular f90Issue: 3.1Date: October 2, 2012Page: 23
are a very large number of intrinsic procedures (FUNCTIONs like SIN, MAXVAL etc.)which provide many facilities. Before embarking on writing a new program you shouldcheck that F90 doesn’t already provide a way of doing exactly what you want.
13 Quick Fortran 90 reference
13.1 Character set, statements, literals and variable names
26 letters of the alphabet A-Z
uppercase only (Fortran compilers ignore case)
10 decimal digits 0-9
4 arithmetic symbols + - * / (note ** for raise to the power)
18 other symbols ( ) . = , ’ $ : space ! " % & ; < > ?
; semi-colon is used to separate statements on a line
! exclamation indicates the start of comment (rest of line ignored)
& ampersand at end of line indicates continuation on next line
Integer constants 1 411 -34 +18
Real constants 1.35 44.33 -0.0123 1.3E-3
Character strings "This is a character string"
variable names up to 31 characters alphabetic, underscore or numeric
first character must be alphabetic
without IMPLICIT NONE or some other IMPLICIT declaration then:
if first character I,J,K,L,M,N then type INTEGER
otherwise type REAL
13.2 Declarations, dynamic allocation
All declarations within a code module must appear before any executable statements.
IMPLICIT NONE ! no name convension for type
INTEGER :: I,IFLAG ! declare integer variables
INTEGER, PARAMETER :: INUM=100 ! declare integer parameter (constant)
INTEGER, PARAMETER :: D_P=SELECTED_REAL_KIND(P=10,R=30)
University of LeicesterDepartment of Physics and AstronomyFirst Year Computing WorkshopModular Programming in Fortran 90
Document: modular f90Issue: 3.1Date: October 2, 2012Page: 24
! define precision parameter
REAL :: RR, ZZ ! declare real variables
REAL(D_P) :: DD,FF ! real variables with precision
REAL, DIMENSION(3) :: POS ! array dimension
REAL :: TIM(3) ! array dimension declaration
LOGICAL :: FLAG ! logical variable (true or false)
CHARACTER(LEN=40) :: BLURB ! character variable
CHARACTER(LEN=10), DIMENSION(3) :: TARR
! character array of 3 elements
! each element 10 characters
REAL, ALLOCATABLE, DIMENSION(:) :: X,Y
! dynamically allocatable arrays
REAL :: A=1.45 ! declare a real with initial value
REAL, DIMENSION(2) :: B=(/ 1.23,3.45 /)
! initial array element values
REAL, DIMENSION(50) :: C=(/ (0,I=1,50) /)
REAL, DIMENSION(40) :: D=0.0 ! implied/implicit loops for initial values
The actual allocation of memory for dynamically allocatable arrays must be done withinthe executable code after the declarations:
...
NSTEP=1000
...
ALLOCATE(X(NSTEP),Y(NSTEP)) ! allocate array space as executable
...
I=?? ! get integer subscript from somewhere
X(I)=5.0 ! reference array element using integer
Y(I)=X(I)+10.0
13.3 Formatted input and output
READ *, R1,R2 ! use the default input stream
PRINT *, "The sum is ",SUM ! use the default output stream
OPEN(UNIT=1,FILE="flight.dat",STATUS="OLD") ! open an existing file
University of LeicesterDepartment of Physics and AstronomyFirst Year Computing WorkshopModular Programming in Fortran 90
Document: modular f90Issue: 3.1Date: October 2, 2012Page: 25
READ(UNIT=1,FMT=*) T,H ! read from a unit number
...
OPEN(UNIT=2,FILE="output.dat",STATUS="NEW") ! open a new file
WRITE(UNIT=2,FMT=*) T,H ! write to a unit number
...
CLOSE(UNIT=1) ! close a unit number
PRINT 10, II,RR ! format specified by a labelled statement
10 FORMAT(5X,I3,1X,F10.3)
WRITE(2,"(5X,I3,1X,F10.3)") II,RR ! format specified in-line
The following field descriptors are available:
nX n spaces
Fn.m REAL number, fixed point, m digits after point
En.m REAL number with exponent, m digits after the point
In INTEGER
An CHARACTER string
13.4 Arithmetic and assignment
Arithmetic operators:
( ) parentheses to dictate the order of operations
** exponentiation ( raising to a power)
* or / multiplication or division
+ or - addition or subtraction
INTEGER :: J
REAL : X,Y,A,B
...
X=A+B ! set variable X equal to A+B
J=J-1 ! decrement variable J by 1
Y=X**2 ! set variable Y to X squared
INTEGER :: I,L,II
REAL : A,R,R1,R2
University of LeicesterDepartment of Physics and AstronomyFirst Year Computing WorkshopModular Programming in Fortran 90
Document: modular f90Issue: 3.1Date: October 2, 2012Page: 26
...
I=R+35.3 ! The REAL result is truncated before assignment to INTEGER
A=I/L ! The result is truncated to an INTEGER and assigned to REAL
R2=R1+II ! The result of mixed arithmetic is REAL
13.5 Decision structures, definite and indefinite loops
The following relational operators are available:
== or .EQ. equals
/= or .NE. not equals
> or .GT. greater than
< or .LT. less than
>= or .GE. greater or equal
<= or .LE. less or equal
The following logical operators are available:
.NOT. invert logical value
.AND. logical and
.OR. logical or
.EQV. logical equivalence
.NEQV. logical non-equivalence
Decision structures:
IF(A<3.0) THEN ! start of an IF structure
...
ELSE IF(A>10.0) THEN ! continue IF structure
...
ELSE ! final clause of IF structure
...
END IF ! end of IF structure
SELECT CASE(expression_select) ! start of a CASE structure
CASE(expression1) ! expression CHARACTER or INTEGER
! do something
University of LeicesterDepartment of Physics and AstronomyFirst Year Computing WorkshopModular Programming in Fortran 90
Document: modular f90Issue: 3.1Date: October 2, 2012Page: 27
CASE(expression2)
! do something else
CASE DEFAULT
! some default
END SELECT ! end of CASE structure
Definite loops:
DO J=1,10 ! start a definite loop with counter J
! within loop J will be 1,2,....9,10
END DO
DO K=1,13,2 ! start definite loop with increment 2
! within loop K will be 1,3,5....9,11,13
END DO
Indefinite loops:
NMAX=100 ! set upper limit
NMIN=-100 ! set lower limit
DO ! start indefinite loop
J=?? ! get J from somewhere, somehow!
IF((J>NMAX).OR.(J<NMIN)) THEN ! test for exit
EXIT ! jump to after END DO
ELSE
! keep going
ENDIF
END DO
...
Implied loops:
REAL , DIMENSION(10) :: A
...
READ(UNIT=1,FMT=*) (A(K),K=1,10) ! implied loop on input
implicit loops for arrays:
University of LeicesterDepartment of Physics and AstronomyFirst Year Computing WorkshopModular Programming in Fortran 90
Document: modular f90Issue: 3.1Date: October 2, 2012Page: 28
REAL, DIMENSION(100) :: A,B,C
...
A=1.4 ! set all elements of array A to a scalar
B=A+4.0 ! add 4.0 to all elements of A
C=A*B ! multiply elements of A by elements of B
D=SIN(C) ! take the SIN of each element of C
13.6 Intrinsic functions
ABS absolute value
SQRT square root
SIN sine (argument radians)
COS cosine (argument radians)
TAN tangent (argument radians)
ASIN arcsine (returns radians)
ACOS arccosine (returns radians)
ATAN arctangent (returns radians)
ATAN2(X,Y) arctangent Y/X (returns radians)
ALOG10 logarithm base 10
EXP raise e to power
INT truncate REAL to INTEGER
NINT fix REAL to nearest INTEGER
REAL float INTEGER to a REAL
MOD remainder of A1/A2
13.7 Types of code module
A single PROGRAM module provides the entry point from the operating system:
PROGRAM progname
...
END PROGRAM progname
SUBROUTINEs can be called from within PROGRAM or other SUBROUTINEs orFUNCTIONs:
SUBROUTINE subname(dummy argument list)
...
END SUBROUTINE subname
University of LeicesterDepartment of Physics and AstronomyFirst Year Computing WorkshopModular Programming in Fortran 90
Document: modular f90Issue: 3.1Date: October 2, 2012Page: 29
FUNCTIONs can be used within PROGRAM, SUBROUTINEs, or other FUNCTIONs:
FUNCTION funname(dummy argument list)
...
END FUNCTION subname
A MODULE is used for the declaration of variables and parameters that are to be shared(global) between PROGRAM, SUBROUTINEs and FUNCTIONs:
MODULE modname
declarations...
END MODULE modname
SUBROUTINE whatever
USE modname ! use declarations in a MODULE
...
Calling subroutines and using functions:
SUBROUTINE DOIT(A,B)
IMPLICIT NONE
REAL :: A,B ! declare dummy arguments
internal declarations
executable instructions
END SUBROUTINE DOIT
FUNCTION ZAP(C)
IMPLICIT NONE
REAL :: ZAP,C !declare function and dummy arguments
internal declarations
executable instructions
ZAP=expression !assign value to function before return
END FUNCTION ZAP
PROGRAM TRY
REAL :: X,Y,Z
X=4.0
CALL DOIT(X,Y)
Z=ZAP(X)
PRINT *, X,Y,Z
END PROGRAM TRY
University of LeicesterDepartment of Physics and AstronomyFirst Year Computing WorkshopModular Programming in Fortran 90
Document: modular f90Issue: 3.1Date: October 2, 2012Page: 30
A safe way of passing arrays as arguments:
SUBROUTINE THINGY(N,A,B)
IMPLICIT NONE
INTEGER :: N
REAL, DIMENSION(N) :: A
REAL :: B
...
END SUBROUTINE THINGY
PROGRAM TRYIT
INTEGER, PARAMETER :: NEL=10
REAL :: X(NEL),Y(NEL)
...
CALL THINGY(NEL,X,Y)
...
END PROGRAM TRYIT