<<

University of Leicester Department of Physics and Astronomy Second Year Computing Workshop Modular Programming in 90

Prof. . Willingale

October 2, 2012

1 University of Leicester Document: modular f90 Department of Physics and Astronomy Issue: 3.1 First Year Computing Workshop Date: October2,2012 Modular Programming in Fortran 90 Page: 2

Contents

1 Introduction 4

2 Books and reference 4

3 Getting started 5

3.1 Loggingon...... 5

3.2 CreatingandrunningaF90program ...... 6

4 A pendulum problem 6

5 Modular Programming 8

5.1 TheF90function ...... 8

5.2 Task1...... 9

5.3 TheF90module...... 10

5.4 Task2...... 11

5.5 TheF90subroutine...... 12

5.6 Task3...... 13

6 Integrating the equations of motion 14

6.1 Task4...... 14

6.2 Task5...... 15

6.3 Task6...... 15

6.4 Task7...... 16 University of Leicester Document: modular f90 Department of Physics and Astronomy Issue: 3.1 First Year Computing Workshop Date: October2,2012 Modular Programming in Fortran 90 Page: 3

7 Plotting the motion of the pendulum 16

7.1 Task8...... 16

7.2 Task9...... 18

8 More about arrays 18

9 The F90 case construct 19

10 Exploring the complexities of the motion 20

10.1Task10 ...... 21

10.2Task11 ...... 22

10.3Task12 ...... 22

11 Further investigation 22

11.1Task13 ...... 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 Formattedinputandoutput ...... 24

13.4 Arithmeticandassignment...... 25

13.5 Decision structures, definite and indefinite loops ...... 26

13.6Intrinsicfunctions...... 28

13.7Typesofcodemodule ...... 28 University of Leicester Document: modular f90 Department of Physics and Astronomy Issue: 3.1 First Year Computing Workshop Date: October2,2012 Modular Programming in Fortran 90 Page: 4

1 Introduction

In the first year you had your first taste of computing and programming. This workshop is designed to give you more practice and experience in using Fortran 90. Before you start please read this script carefully. It is important that you attempt the programming individually, not in pairs or as a consortium. You can only become proficient at programming by doing it yourself, not by watching someone else. The workshop is not a race and you must not worry if you seem to be falling behind others. The person who completes first will almost certainly have made mistakes or cut a few corners. You MUST keep a record of what you do in your laboratory workbook, obtain listings of all your programs and retain the program source files on your directory at the end of the 4 laboratory sessions so that your work can be accessed.

You use the UoL IT Windows machines to access the SPECTRE system in the same way as described in the 1st year script.

2 Books and reference

There are many good books on Fortran 90. Notes on the syntax were provided last year and are extended below but they are not intended to be a comprehensive text in competition with published material. You don’t have to buy a book but the following books are recommended. Whichever book you choose make sure it is up to date and covers the 1990 standard. Most books on Fortran 90 do contain a description of the 77 standard but be warned there are significant differences between f77 and f90. Do not purchase 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 Fortran 90, documentation on the PGPLOT and a guide to using Irix and Word can all be found on the World Wide Web at URL: http://www.star.le.ac.uk/~rw/compshop/ University of Leicester Document: modular f90 Department of Physics and Astronomy Issue: 3.1 First Year Computing Workshop Date: October2,2012 Modular Programming in Fortran 90 Page: 5

3 Getting started

3.1 Logging on

You must first log on to UoL IT Windows. To login into SPECTRE you must use the X-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 Leicester Document: modular f90 Department of Physics and Astronomy Issue: 3.1 First Year Computing Workshop Date: October2,2012 Modular Programming in Fortran 90 Page: 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 this now is the time to look it up.

To summarise, use the following commands to create and run a program

$ nedit .f90 & $ gfortran .f90 -o $ ./

If you want to find more about the you can browse through the help 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 to search the manual for specific text sequences. Otherwise you must search for a specific command.

4 A pendulum problem

We are going to use a dynamics problem involving a magnetically perturbed pendulum as a vehicle to introduce the and power of F90. The problem cannot be solved analytically and exhibits complicated chaotic behaviour as well as simpler regular motion.

The magnetically perturbed pendulum in question is similar to some executive toys you can buy to adorn your desk and distract you when the going gets tough. It consists of a magnetic bob suspended on a wire or string which lies along the z-axis when the wire is vertical. The bob is free to move in both x and y and we will only consider the motion of the bob in the horizontal xy plane. To make the motion more interesting the bob is perturbed by a magnet which can be placed in the xy plane just underneath the swinging pendulum. When the bob passes near to the magnet the path is deflected violently and makes the pendulum swing in a random way. The geometry of the pendulum is illustrated in figure 1.

The motion is described by 2 simple coupled differential equations: University of Leicester Document: modular f90 Department of Physics and Astronomy Issue: 3.1 First Year Computing Workshop Date: October2,2012 Modular Programming in Fortran 90 Page: 7

Z

bob y z x Y

xm ym zm

X magnet

Figure 1: The magnetically perturbed pendulum

2 2 − − − 8 − x/dt = gx m(x xm)/rm d dx/dt

2 2 − − − 8 − d y/dt = gy m(y ym)/rm d dy/dt

In each case the 3 terms on the right correspond to gravity, the magnetic perturbation and air drag. The constants g, m and d depend on the mass of the bob, the strength of the magnet and the viscocity of air. The fixed magnet is at position (xm,ym, zm) 2 2 2 1/2 and rm = ((x − xm) +(y − ym) +(z − zm) ) . Actually these equations are only an approximation to the real state of affairs but as you will be able to demonstrate for yourselves this doesn’t matter.

If m and d are zero then the pendulum executes simple harmonic motion in x and y and the bob follows an elliptical path in the xy plane. If d is zero then the motion is conservative (no energy loss) and we can express the force using a potential energy:

2 − 6 V = gr /2 m/6rm University of Leicester Document: modular f90 Department of Physics and Astronomy Issue: 3.1 First Year Computing Workshop Date: October2,2012 Modular Programming in Fortran 90 Page: 8 where r =(x2 + y2)1/2. The forces in x and y (not including drag) are then given by the gradients:

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). These define what is called a phase space for the system. As time progresses the bob will trace out a path in phase space. If we take a particular starting position for the bob in phase space we can calculate the path by integrating the differential equations. There we have it. The problem is to integrate the differential equations given g, m , d, and a starting position 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 by an array of 4 numbers, P(4) where P(1) and P(2) are the position in xy and P(3) and P(4) are the corresponding velocities.

In the following script the tasks you are expected to do are described in subsections entitled Task n.

5 Modular Programming

Last year you learnt how to write a simple PROGRAM section. This year you will be exposed to the full power of F90; in particular we are going to use Modular Programming involving MODULEs, and FUNCTIONs. Correct use of these makes the code 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 so forth but you define what is required and how to calculate the answers. University of Leicester Document: modular f90 Department of Physics and Astronomy Issue: 3.1 First Year Computing Workshop Date: October2,2012 Modular Programming in Fortran 90 Page: 9

Suppose we have the position of the pendulum bob in phase space and want a function to 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 case PEND KE, and then defines the argument list, in this case just one variable P. The line starting INTEGER, PARAMETER defines a parameter DOUB PREC which is used in the declarations of the REAL variables. We will say more of this later. Notice that the function 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 the assignment line. Finally the line starting END completes the definition of the new function.

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. Compile and run the program and check that the result is correct by using simple numbers or using a calculator. Note that it is not necessary for P to have the same name in the function and the calling program. Verify this by changing the name in one or the other. The only University of Leicester Document: modular f90 Department of Physics and Astronomy Issue: 3.1 First Year Computing Workshop Date: October2,2012 Modular Programming in Fortran 90 Page: 10 requirement is that the type of the argument used in the calling routine is the same as declared within the function.

5.3 The F90 module

In the above you had to type the definition line for the DOUB PREC parameter in both the function and the program module. It is often the case that the same declaration lines are required to appear in a large number of places. Furthermore it is often useful to define some variables as global between a number of routines rather than passing them as arguments. The MODULE provides a clean and uniform way to achieve these and other functions.

The following module defines various things which will be useful in the programming solution 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 line starting with END completes the definition. The IMPLICIT NONE and SAVE lines are recommended in all modules since they ensure that every variable is defined and is non- volatile. The INTEGER declarations define two integer constants which refer to REAL types of a specified precision (P=) and range (R=). These are required because single precision (P=6 decimal digits) is insufficient to give adequate precision for the solution to our problem. However when we come to plot the results later we must use single precision variables for the plotting routines. So all variables which are used University of Leicester Document: modular f90 Department of Physics and Astronomy Issue: 3.1 First Year Computing Workshop Date: October2,2012 Modular Programming in Fortran 90 Page: 11 in calculation will be declared REAL(DOUB PREC) while plotting variables must be declared REAL(SING PREC). The remaining lines in the MODULE PEND DEF define and declare a new data type. In Fortran 90 new data types can be defined in term of existing data types. In this case a new type called PEND PARAM consisting of a position for the fixed magnet (an array P(3)) and three constants FMAG, FGRA and FDRA (corresponding to m, g, d above). The lines between TYPE PEND PARAM and END 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 the module in a PROGRAM or FUNCTION (or SUBROUTINE, see later) you must put USE 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 the potential energy of the pendulum. If you refer back to the pendulum equations you will see this requires the constants m and g (FMAG and FGRA components of G). You can see below how the MODULE PEND DEF is included into the FUNCTION PEND PE and how the components of G are referred to using the syntax G%FMAG to pick out the value 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 which contains the PEND KE function and the TEST program. Modify the function PEND KE University of Leicester Document: modular f90 Department of Physics and Astronomy Issue: 3.1 First Year Computing Workshop Date: October2,2012 Modular Programming in Fortran 90 Page: 12 so that the definition of the parameter DOUB PREC is included from the PEND DEF module (i.e. put USE PEND DEF into the function PEND KE). Finally we need to modify the test program to USE PEND KE and to initialize the values of the magnet constants 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 FUNCTION PEND KE, the FUNCTION PEND PE and the PROGRAM TEST.

The program should read in the magnet parameters and the position of the bob in phase space 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 to translate the equations into Fortran. This is best done using a SUBROUTINE which is the last form of module supported by F90. Unlike a FUNCTION all the information to and from a SUBROUTINE is passed as arguments. In general some arguments will be purely input, some will be input, modified by the routine and then output and others will be just output. We want a routine which will calculate the derivatives of the position in phase 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 Leicester Document: modular f90 Department of Physics and Astronomy Issue: 3.1 First Year Computing Workshop Date: October2,2012 Modular Programming in Fortran 90 Page: 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 required equations. The arguments T and P are the time and position (input arguments) and PDOT holds the output values of the derivatives. Like the functions we defined above the new routine uses the module PEND DEF to provide definitions of DOUB PREC and the G.

5.6 Task 3

Type the PEND EQM routine into your source file. In order to use the SUBROUTINE you must CALL it. The extra lines you need in the TEST FUN program are declarations for 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 Leicester Document: modular f90 Department of Physics and Astronomy Issue: 3.1 First Year Computing Workshop Date: October2,2012 Modular Programming in Fortran 90 Page: 14

6 Integrating the equations of motion

In order to perform the integration another subroutine is required. This routine starts as follows:

SUBROUTINE RUNKUT(DT,,TIME,NV,P)

The routine performs an integration step by the fourth order Runge-Kutta method. You don’t need to know what this is , you just need to know how to call the routine. The arguments 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. RUNKUT will use subroutine PEND EQM to predict the new position of the pendulum at time TIME+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 it to 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 appear in a MODULE. In fact the RUNKUT subroutine has no connection with the pendulum problem other than it provides a method of solving ordinary differential equations. All the 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 Leicester Document: modular f90 Department of Physics and Astronomy Issue: 3.1 First Year Computing Workshop Date: October2,2012 Modular Programming in Fortran 90 Page: 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 new position. 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 how DO loops work refer to last year’s notes.

In order to test the program is working you should calculate the answer in cases when you know the expected results. For example if d=0 and m=0 then the bob should execute simple harmonic motion. If g=1 what is the frequency? Choose the time increment DT such that you get several tens of samples for each complete cycle. Make sure that the motion 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 gives the bob a reasonable perturbation. In this case you will need DT=0.005 or smaller to give reliable results. If the time increment is too large then the Runge-Kutta method may introduce a small error that will accumulate if a very large number of steps is taken. If d=0 then the energy of the system should be conserved. You can check this by using the KE and PE functions we looked at earlier. Try running the program with different values of DT and many steps (10000 say) and check that the energy remains constant. If you use a large number of steps you won’t want to print out the position for every pass. You can 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 Leicester Document: modular f90 Department of Physics and Astronomy Issue: 3.1 First Year Computing Workshop Date: October2,2012 Modular Programming in Fortran 90 Page: 16

6.4 Task 7

Now try introducing some air drag and see what happens. Does the program behave as expected? Can you find a stable point for the pendulum bob in phase space? Is this point where you expect it to be? What happens if you make m (the force constant of the magnet) 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 t as calculated above it should be easy to see if your results are sensible or not. If you plot x 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 in this workshop by a package of subroutines called PGPLOT. A manual describing this set of subroutines and how to use them can be borrowed from the Laboratory Preparation Room 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. To do 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 executable statements. You will notice that the dimension of the arrays is not specified (:). In our program we do not know the number of time steps required until it is typed in by the user therefore we don’t know beforehand how large the arrays need to be. After the line which 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 Leicester Document: modular f90 Department of Physics and Astronomy Issue: 3.1 First Year Computing Workshop Date: October2,2012 Modular Programming in Fortran 90 Page: 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 the /linker and the commands you will need to produce a plot are as follows.

$ source /home/z/zrw/under/pgplot_f90 University of Leicester Document: modular f90 Department of Physics and Astronomy Issue: 3.1 First Year Computing Workshop Date: October2,2012 Modular Programming in Fortran 90 Page: 18

$ gfortran .f90 ‘pgplot_f90_link‘ -o $ ./

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 the necessary object libraries into the gfortran command. When you run the program the PGBEGIN routine will prompt for a device name. The device type you should use on the X-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 Windows machine 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 then drag it from the Explorer window onto the Desktop. If you then double-click on the file it will open a print facility. Select the PostScript Driver and you can print the file. If you set the destination to be CutePDF Write then the print facility with create a PDF file of the 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 panels using the last 2 arguments of PGBEGIN. These specify the number of panels across and down the full screen. Each subsequent call to PGENV will then advance to the next panel and more than 1 plot can be displayed on a single screen. Add further code to your program 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 KE the dimension of the array P(4) was declared in both the calling program and the function and there was no mention of the size in the argument list. In this context, where the number of elements was fixed by the problem (the dimension of the phase space of the pendulum), this was reasonable. However in general it is a good idea to pass the size of University of Leicester Document: modular f90 Department of Physics and Astronomy Issue: 3.1 First Year Computing Workshop Date: October2,2012 Modular Programming in Fortran 90 Page: 19 array dimensions as INTEGER arguments to the FUNCTION or SUBROUTINE. The start 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 the calling routine not within RUNKUT. The advantage of this is that the routine can be used for any dimension of y (number of variables in the equations), not just the problem in 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 SUBROUTINEs and FUNCTIONs. In the last few declaration lines a number of local arrays are declared using the argument N (e.g. F1(N)). These are called automatic arrays and can be declared in this manner to create workspace for the calculations inside a SUBROUTINE or FUNCTION.

9 The F90 case construct

There is another way of controlling the flow of the execution of statements in F90 called the CASE construct. It is designed specifically for use by character strings or integers and works for logicals. It has the form:

SELECT CASE(expression_select) University of Leicester Document: modular f90 Department of Physics and Astronomy Issue: 3.1 First Year Computing Workshop Date: October2,2012 Modular Programming in Fortran 90 Page: 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 the following cases is executed. If none of the expression1 etc. is satisified then the DEFAULT will be used. The expressions use must not be REAL. To control flow with REAL values they must be converted to INTEGER or LOGICAL (using some expression) and used in CASE or IF constructs.

10 Exploring the complexities of the motion

If you play about with the starting point of the pendulum bob (initial position and velocity) you will soon discover that the motion of the pendulum can be very complicated with no apparent structure or regular behaviour. It is very difficult to make sense of what is going on by plotting the path as described above.

A more useful view of the motion is provided by what is known as the Poincar´eSection, particularly if the air drag (energy loss) is zero (d=0). If you define a plane in phase space, for example the y=0 plane, then, as the pendulum swings about, the path in phase space will cross the plane on a regular basis. Every time the path crosses the plane it defines a point (which can be plotted). Actually we should restrict the points to those for which the path is travelling from y<0 to y> 0 (or the other way around). The section of the path between such points then defines what is called an orbit in phase space. If the motion is allowed to continue then the plotted points gradually build up a picture of the Poincar´eSection of the motion.

If the motion is periodic then the path will eventually return to a point already plotted and the sequence will start again. Indeed, if the motion is particularly simple then the picture may consist of just one point! If the motion is chaotic then the bob never returns to the same position in phase space and the Poincar´eSection picture will consist of an infinite number of points covering some area of the plane. Somewhere in between the simple regular picture and chaos there are some rather complicated patterns as you will see.

The next task is to modify your program to plot a Poincar´eSection. The changes are remarkably simple. You must now control an outer loop by the number of section points University of Leicester Document: modular f90 Department of Physics and Astronomy Issue: 3.1 First Year Computing Workshop Date: October2,2012 Modular Programming in Fortran 90 Page: 21 required rather than the number of steps. An inner loop must be indefinite since you no longer know how many integration steps are required. If the number of points requested is 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 loop keeps running until the path crosses the y=0 plane going in the positive direction. Since the motion of the pendulum is bounded this is going to happen sooner or later. The outer loop 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 motion using 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 values of ICHAR. For example ICHAR=2 gives + and ICHAR=3 gives *. University of Leicester Document: modular f90 Department of Physics and Astronomy Issue: 3.1 First Year Computing Workshop Date: October2,2012 Modular Programming in Fortran 90 Page: 22

10.2 Task 11

The above is only an approximation since the actual intersection with the plane is somewhere between POLD and P. Now’s your chance to write a SUBROUTINE from scratch. Try producing a routine which estimates the intersection point by linear interpolation, i.e. using a straight line to join POLD to P. Before you start typing any code, work out exactly what the required calculation is. Then, decide on the subroutine required and finally write the code. Before you introduce it into the pendulum program 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 find starting values (with d=0) which lead to regular (periodic) and chaotic motion. Can you find a motion in which the points in the Poincar´esection form loops? This corresponds to 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 the air drag to a very small value the pendulum will gradually drift through different types of motion. It is possible to draw sections corresponding to a range of energies by turning the drag off and on as the calculation proceeds. See if you can modify your program to do this. The resulting pictures can be astonishingly complicated, amply demonstrating that 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 important features of F90. However there are a few topics which have been omitted. F90 can handle pointers to data rather than using conventional variables. These are most useful when the data base is dynamic, for example in real-time control and analysis. The power and scope of I/O has been ignored. In particular we have not mentioned unformatted input/output and have only touched apon FORMAT statements for contolling formatted I/O. There University of Leicester Document: modular f90 Department of Physics and Astronomy Issue: 3.1 First Year Computing Workshop Date: October2,2012 Modular Programming in Fortran 90 Page: 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 should check 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 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 Leicester Document: modular f90 Department of Physics and Astronomy Issue: 3.1 First Year Computing Workshop Date: October2,2012 Modular Programming in Fortran 90 Page: 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) :: =(/ (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 within the 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 Leicester Document: modular f90 Department of Physics and Astronomy Issue: 3.1 First Year Computing Workshop Date: October2,2012 Modular Programming in Fortran 90 Page: 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 Leicester Document: modular f90 Department of Physics and Astronomy Issue: 3.1 First Year Computing Workshop Date: October2,2012 Modular Programming in Fortran 90 Page: 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 Leicester Document: modular f90 Department of Physics and Astronomy Issue: 3.1 First Year Computing Workshop Date: October2,2012 Modular Programming in Fortran 90 Page: 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

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 Leicester Document: modular f90 Department of Physics and Astronomy Issue: 3.1 First Year Computing Workshop Date: October2,2012 Modular Programming in Fortran 90 Page: 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 or FUNCTIONs:

SUBROUTINE subname(dummy argument list) ... END SUBROUTINE subname University of Leicester Document: modular f90 Department of Physics and Astronomy Issue: 3.1 First Year Computing Workshop Date: October2,2012 Modular Programming in Fortran 90 Page: 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 Leicester Document: modular f90 Department of Physics and Astronomy Issue: 3.1 First Year Computing Workshop Date: October2,2012 Modular Programming in Fortran 90 Page: 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