+ All Categories
Home > Documents > Fortran Learning Cambridge University

Fortran Learning Cambridge University

Date post: 12-Nov-2014
Category:
Upload: hossienhossieni
View: 984 times
Download: 5 times
Share this document with a friend
Description:
this document is useful for learning fortran
499
Introduction to Programming with Fortran 90 See next foil for copyright information Nick Maclaren Computing Service [email protected], ext. 34761 November 2007 Introduction to Programming with Fortran 90 – p. 1/??
Transcript

Introduction to Programming withFortran 90

See next foil for copyright information

Nick Maclaren

Computing Service

[email protected], ext. 34761

November 2007

Introduction to Programming with Fortran 90 – p. 1/??

Acknowledgement

Derived from the course written and owned by

Dr. Steve MorganComputing Services DepartmentThe University of Liverpool

The Copyright is joint between the authorsPermission is required before copying it

Please ask if you want to do that

Introduction to Programming with Fortran 90 – p. 2/??

Important!

There is a lot of material in the courseAnd there is even more in extra slides ...

Some people will already know some FortranSome will be programmers in other languagesSome people will be complete newcomers

The course is intended for all of those people

• Please tell me if I am going too fastNot afterwards, but as soon as you have trouble

Introduction to Programming with Fortran 90 – p. 3/??

Beyond the Course (1)

Email escience-support@ucs for advice

http://www-uxsup.csx.cam.ac.uk/courses/. . .

. . ./Fortran . . ./OldFortran

. . ./Arithmetic etc.

Programming in Fortran 90/95by Steve Morgan and Lawrie Schonfelder(Fortran Market, PDF, $15)http://www.fortran.com/

Also Fortran 90 version of that

Introduction to Programming with Fortran 90 – p. 4/??

Beyond the Course (2)

Fortran 95/2003 Explainedby Michael Metcalf, John Reid andMalcolm Cohen

Also Fortran 90 version of that

Fortran 90 Programmingby Miles Ellis, Ivor Phillips andThomas Lahey

Introduction to Programming with Fortran 90 – p. 5/??

Beyond the Course (3)

SC22WG5 (ISO Fortran standard committee)http://www.nag.co.uk/sc22wg5/

http://www.fortran.com/fortran/⇒ ‘Information’, ‘Standards Documents’

Liverpool Coursehttp://www.liv.ac.uk/HPC/HTMLFrontPageF90.html

A real, live (well coded) Fortran 95 applicationhttp://www.wannier.org

Introduction to Programming with Fortran 90 – p. 6/??

Practicals

These will be delayed until after second lectureThen there will be two practicals to do

One is using the compiler and diagnosticsJust to see what happens in various cases

The other is questions about the basic rules

Full instructions will be given thenIncluding your identifiers and passwords

Introduction to Programming with Fortran 90 – p. 7/??

History

FORmula TRANslation invented 1954–8by John Backus and his team at IBM

FORTRAN 66 (ISO Standard 1972)FORTRAN 77 (1980)Fortran 90 (1991)Fortran 95 (1996)Fortran 2003 (2004)Fortran 2008 (ongoing)

The “Old Fortran” slides have more detail

Introduction to Programming with Fortran 90 – p. 8/??

Hardware and Software

A system is built from hardware and software

The hardware is the physical medium, e.g.• CPU, memory, keyboard, display• disks, ethernet interfaces etc.

The software is a set of computer programs, e.g.• operating system, compilers, editors• Fortran 90 programs

Introduction to Programming with Fortran 90 – p. 9/??

Programs (1)

A CPU executes instructions coded in binarySuch instructions might look like:

011100100001001011101000001010

These could represent instructions likeLoad contents of location 96 into register 1Add contents of register 1 to register 3

A file of such data makes an executable program

Introduction to Programming with Fortran 90 – p. 10/??

Programs (2)

High-level languages allow an easier notationEnglish-like words and math-like expressions

Y = X + 3PRINT *, Y

Fortran 90 is a high-level languageSometimes called “third-generation” or 3GL

Compilers translate into machine instructionsA linker then creates an executable programThe operating system runs the executable

Introduction to Programming with Fortran 90 – p. 11/??

Fortran Programming Model

Memory

pigeonholes)

into a series of

(organised

CPU

Program

Files, keyboard,

display etc.

Introduction to Programming with Fortran 90 – p. 12/??

Algorithms and Models

An algorithm is a set of instructionsThey are executed in a defined orderDoing that carries out a specific task

The above is procedural programmingFortran 90 is a procedural language

Object-orientation is still proceduralFortran 90 has object-oriented facilities

Introduction to Programming with Fortran 90 – p. 13/??

An Example of a Problem

Write a program to convert a time in hours,minutes and seconds to one in seconds

Algorithm:1. Multiply the hours by 602. Add the minutes to the result3. Multiply the result by 604. Add the seconds to the result

Introduction to Programming with Fortran 90 – p. 14/??

Logical Structure

1. Start of program2. Reserve memory for data3. Write prompt to display4. Read the time in hours, minutes and seconds5. Convert the time into seconds6. Write out the number of seconds7. End of program

Introduction to Programming with Fortran 90 – p. 15/??

The Program

PROGRAM example1! Comments start with an exclamation mark

IMPLICIT NONEINTEGER :: hours, mins, secs, tempPRINT *, ’Type the hours, minutes and seconds’READ *, hours, mins, secstemp = 60*( hours*60 + mins) + secsPRINT *, ’Time in seconds =’, temp

END PROGRAM example1

Introduction to Programming with Fortran 90 – p. 16/??

High Level Structure

1. Start of program (or procedure)PROGRAM example1

2. Followed by the specification partdeclare types and sizes of data

3–6. Followed by the execution partall of the ‘action’ statements

7. End of program (or procedure)END PROGRAM example1

Comments do nothing and can occur anywhere! Comments start with an exclamation mark

Introduction to Programming with Fortran 90 – p. 17/??

Program and File Names

• The program and file names are not relatedPROGRAM QES can be in file QuadSolver.f90Similarly for most other Fortran components

Some implementations like the same namesSometimes converted to lower- or upper-case

The compiler documentation should tell youIt is sometimes in the system documentationPlease ask for help, but it is outside this course

Introduction to Programming with Fortran 90 – p. 18/??

The Specification Part

2. Reserve memory for dataINTEGER :: hours, mins, secs, temp

INTEGER is the type of the variables

hours, mins, secs are used to hold inputThe values read in are called the input datatemp is called a workspace variable

also called a temporary variable etc.The output data are ’Time . . . =’ and tempThey can be any expression, not just a variable

Introduction to Programming with Fortran 90 – p. 19/??

The Execution Part

3. Write prompt to displayPRINT *, ’Type the hours, . . .’

4. Read the time in hours, minutes and secondsREAD *, hours, mins, secs

5. Convert the time into secondstemp = 60*( hours*60 + mins) + secs

6. Write out the number of secondsPRINT *, ’Time in seconds =’, temp

Introduction to Programming with Fortran 90 – p. 20/??

Assignment and Expressions

temp = 60*( hours*60 + mins) + secs

The RHS is a pseudo-mathematical expressionIt calculates the value to be stored

• Expressions are very like A-level formulaeFortran is FORmula TRANslation – remember?We will come to the detailed rules later

• temp = stores the value in the variableA variable is a memory cell in Fortran’s model

Introduction to Programming with Fortran 90 – p. 21/??

Really Basic I/O

READ *, <variable list> reads from stdinPRINT *, <expression list> writes to stdout

Both do input/output as human-readable textEach I/O statement reads/writes on a new line

A list is items separated by commas (‘,’)Variables are anything that can store valuesExpressions are anything that deliver a value

Everything else will be explained later

Introduction to Programming with Fortran 90 – p. 22/??

Sequences and Conditionals

Simple algorithms are just sequencesA simple algorithm for charging could be:

1. Calculate the bill2. Print the invoice

Whereas it probably should have been:1. Calculate the bill2. If the bill exceeds minimum

2.1 Then print the invoice2.2 Else add bill to customer’s account

Introduction to Programming with Fortran 90 – p. 23/??

Repeated Instructions

The previous program handled only one valueA more flexible one would be:

1. Start of program2. Reserve memory for data3. Repeat this until end of file

3.1 Read the value of seconds3.2 Convert to minutes and seconds3.3 Write out the result

4. End of Program

Introduction to Programming with Fortran 90 – p. 24/??

Summary

There are three basic control structures:• A simple sequence• A conditional choice of sequences• A repeated sequence

All algorithms can be expressed using theseIn practice, other structures are convenient

Almost always need to split into simpler tasksEven Fortran II had subroutines and functions!

Introduction to Programming with Fortran 90 – p. 25/??

Developing a Computer Program

There are four main steps:1. Specify the problem2. Analyse and subdivide into tasks3. Write the Fortran 90 code4. Compile and run (i.e. test)

Each step may require several iterationsYou may need to restart from an earlier step

• The testing phase is very important

Introduction to Programming with Fortran 90 – p. 26/??

Errors

• If the syntax is incorrect, the compiler says soFor example: INTEGER :: ,mins, secs

• If the action is invalid, things are messierFor example: X/Y when Y is zero/ represents division, because of the lack of ÷

You may get an error message at run-timeThe program may crash, just stop or hangIt may produce nonsense values or go haywire

Introduction to Programming with Fortran 90 – p. 27/??

Introduction to Programming withFortran 90

Fortran Language Rules

Nick Maclaren

Computing Service

[email protected], ext. 34761

November 2007

Introduction to Programming with Fortran 90 – p. 1/??

Coverage

This course is modern, free-format source onlyThe same applies to features covered later

Almost all old Fortran remains legalAvoid using it, as modern Fortran is betterThis mentions old Fortran only in passing

See the OldFortran course for those aspectsIt describes fixed-format and conversionOr ask questions or for help on such things, too

Introduction to Programming with Fortran 90 – p. 2/??

Important Warning

Fortran’s syntax is verbose and horribleIt can fairly be described as a historical messIts semantics are fairly clean and consistent

Its verbosity causes problems for examplesMany of them use poor style, to be readableAnd they mostly omit essential error checking

• Do what I say, don’t do what I do

Sorry about that . . .

Introduction to Programming with Fortran 90 – p. 3/??

Correctness

Humans understad linguage quite well even when itisnt stroctly correc

Computers (i.e. compilers) are not so forgiving• Programs must follow the rules to the letter

• Fortran compilers will flag all syntax errorsGood compilers will detect more than is required

But your error may just change the meaningOr do something invalid (“undefined behaviour”)

Introduction to Programming with Fortran 90 – p. 4/??

Examples of Errors

Consider (N*M/1024+5)

If you mistype the ‘0’ as a ‘)’: (N*M/1)24+5)You will get an error message when compilingIt may be confusing, but will point out a problem

If you mistype the ‘0’ as a ‘–’: (N*M/1–24+5)You will simply evaluate a different formulaAnd get wrong answers with no error message

And if you mistype ‘*’ as ‘8’?

Introduction to Programming with Fortran 90 – p. 5/??

Character Set

Letters (A to Z and a to z) and digits (0 to 9)Letters are matched ignoring their case

And the following special characters_ = + – */ ( ) , . ’ : ! " % & ; < > ? $Plus space (i.e. a blank), but not tabThe end-of-line indicator is not a character

Any character allowed in comments and strings• Case is significant in strings, and only there

Introduction to Programming with Fortran 90 – p. 6/??

Special Characters

_ = + – */ ( ) , . ’ : ! " % & ; < > ? $

slash (/) is also used for dividehyphen (–) is also used for minusasterisk (*) is also used for multiplyapostrophe (’) is used for single quoteperiod (.) is also used for decimal point

The others are described when we use them

Introduction to Programming with Fortran 90 – p. 7/??

Layout

• Do not use tab, form-feed etc. in your sourceUse no positioning except space and line breaks

Compilers do bizarre things with anything elseWill work with some compilers but not othersAnd can produce some very strange output

Even in C, using them is a recipe for confusionThe really masochistic should ask me offline

Introduction to Programming with Fortran 90 – p. 8/??

Source Form (1)

Spaces are not allowed in keywords or namesINTEGER is not the same as INT EGER

HOURS is the same as hoURs or hoursBut not HO URS – that means HO and URS

• Some keywords can have two formsE.g. END DO is the same as ENDDOBut EN DDO is treated as EN and DDO

Introduction to Programming with Fortran 90 – p. 9/??

Source Form (2)

• Do not run keywords and names togetherINTEGERI,J,K – illegalINTEGER I,J,K – allowed

• You can use spaces liberally for clarityINTEGER I , J , K

Exactly where you use them is a matter of taste

• Blank lines can be used in the same wayOr lines consisting only of comments

Introduction to Programming with Fortran 90 – p. 10/??

Double Colons

For descriptive names use underscorelargest_of, maximum_value or P12_56

• Best to use a double colon in declarationsSeparates type specification from names

INTEGER :: I, J, K

This form is essential where attributes are usedINTEGER, INTENT(IN) :: I, J, K

Introduction to Programming with Fortran 90 – p. 11/??

Lines and Comments

A line is a sequence of up to 132 characters

A comment is from ! to the end of lineThe whole of a comment is totally ignored

A = A+1 ! These characters are ignored! That applies to !, & and ; too

Blank lines are completely ignored!! Including ones that are just comments!

Introduction to Programming with Fortran 90 – p. 12/??

Use of Layout

Well laid-out programs are much more readableYou are less likely to make trivial mistakesAnd much more likely to spot them!

This also applies to low-level formats, tooE.g. 1.0e6 is clearer than 1.e6 or .1e7

• None of this is Fortran-specific

Introduction to Programming with Fortran 90 – p. 13/??

Use of Comments

Appropriate commenting is very importantThis course does not cover that topicAnd, often, comments are omitted for brevity

“How to Help Programs Debug Themselves”Gives guidelines on how best to use comments

• This isn’t Fortran-specific, either

Introduction to Programming with Fortran 90 – p. 14/??

Use of Case

• Now, this IS Fortran-specific!

It doesn’t matter what case convention you use• But DO be moderately† consistent!Very important for clarity and editing/searching

For example:UPPER case for keywords, lower for namesYou may prefer Capitalised names

† A foolish consistency is the hobgoblin of little minds

Introduction to Programming with Fortran 90 – p. 15/??

Statements and Continuation

• A program is a sequence of statementsUsed to build high-level constructsStatements are made up out of lines

• Statements are continued by appending &A = B + C + D + E + &

F + G + HIs equivalent to

A = B + C + D + E + F + G + H

Introduction to Programming with Fortran 90 – p. 16/??

Other Rules (1)

Statements can start at any position• Use indentation to clarify your code

IF (a > 1.0) THENb = 3.0

ELSEb = 2.0

END IF

• A number starting a statement is a label10 A = B + C

The use of labels is described later

Introduction to Programming with Fortran 90 – p. 17/??

Other Rules (2)

You can put multiple statements on a linea = 3 ; b = 4 ; c = 5

Overusing that can make a program unreadableBut it can clarify your code in some cases

Avoid mixing continuation with that or commentsIt works, but can make code very hard to read

a = b + c ; d = e + f + &g + h

a = b + c + & ! More coming ...d = e + f + g + h

Introduction to Programming with Fortran 90 – p. 18/??

Breaking Character Strings

• Continuation lines can start with an &Preceding spaces and the & are suppressed

The following works and allows indentation:PRINT ’Assume that this string &

&is far too long and complic&&ated to fit on a single line’

The initial & avoids including excess spaces

This may also be used to continue any line

Introduction to Programming with Fortran 90 – p. 19/??

Names

Up to 31 letters, digits and underscores• Names must start with a letter

Upper and lower case are equivalentDEPTH, Depth and depth are the same name

The following are valid Fortran names

A, AA, aaa, Tax, INCOME, Num1, NUM2, NUM333,N12MO5, atmospheric_pressure, Line_Colour,R2D2, A_21_173_5a

Introduction to Programming with Fortran 90 – p. 20/??

Invalid Names

The following are invalid names

1A does not begin with a letter_B does not begin with a letterDepth$0 contains an illegal character ‘$’A-3 would be interpreted as subtract 3 from AB.5: illegal characters ‘.’ and ‘:’

A_name_made_up_of_more_than_31_letterstoo long, 38 characters

Introduction to Programming with Fortran 90 – p. 21/??

Compiling and Testing

We shall use the NAG Fortran 95 under LinuxPWF Windows does not have Fortran installedUsing any Fortran compiler is much the same

Please ask about anything you don’t understandFeel free to bring problems with other FortransFeel free to use gdb if you know it

Solutions to exercises will be available from:http://www-uxsup.csx.cam.ac.uk/courses/Fortran

Introduction to Programming with Fortran 90 – p. 22/??

Instructions

If running Microsoft Windows, CTRL-ALT-DELSelect Restart and then LinuxLog into Linux and start a shell and an editorCreate programs called prog.f90, fred.f90 etc.

• Run by typing commands likef95 -C=all -o fred fred.f90./fred

• Analyse what went wrong• Fix bugs and retry

Introduction to Programming with Fortran 90 – p. 23/??

Introduction to Programming withFortran 90

Data Types and Basic Calculation

Nick Maclaren

Computing Service

[email protected], ext. 34761

November 2007

Introduction to Programming with Fortran 90 – p. 1/??

Data Types (1)

• INTEGER for exact whole numberse.g. 1, 100, 534, -18, -654321 etc.

In maths, an approximation to the ring Z

• REAL for approximate, fractional numberse.g. 1.1, 3.0, 23.565, π, exp(1), etc.

In maths, an approximation to the field R

• COMPLEX for complex, fractional numberse.g. (1.1, -23.565), etc.

In maths, an approximation to the field C

Introduction to Programming with Fortran 90 – p. 2/??

Data Types (2)

• LOGICAL for truth valuesThese may have only values true or false

e.g. .TRUE. , .FALSE.These are often called boolean values

• CHARACTER for strings of characterse.g. ‘?’, ‘Albert Einstein’, ‘X + Y = ’, etc.

The string length is part of the type in FortranThere is more on this later

Introduction to Programming with Fortran 90 – p. 3/??

Integers (1)

• Integers are restricted to lie in a finite range

Typically ±2147483647 (-231 to 231-1)

Sometimes ±9.23 × 1017 (-263 to 2

63-1)

A compiler may allow you to select the rangeOften including ±32768 (−2

15 to 215-1)

Older and future systems may have other rangesThere is more on the arithmetic and errors later

Introduction to Programming with Fortran 90 – p. 4/??

Integers (2)

Fortran uses integers for:• Loop counts and loop limits• An index into an array or a position in a list• An index of a character in a string• As error codes, type categories etc.

Also use them for purely integral valuesE.g. calculations involving counts (or money)They can even be used for bit masks (see later)

Introduction to Programming with Fortran 90 – p. 5/??

Integer Constants

Usually, an optional sign and one or more digitse.g. 0, 123, -45, +67, 00012345

E.g. ‘60’ in minutes = minutes + 60*hours

Also allowed in binary, octal and hexadecimale.g. B’011001’, O’35201’, Z’a12bd’

• As with names, the case is irrelevant

There is a little more, which is covered later

Introduction to Programming with Fortran 90 – p. 6/??

Reals

• Reals are held as floating-point valuesThese also have a finite range and precision

It is essential to use floating-point appropriately• Much of the Web is misleading about thisThis course will mention only the bare minimumSee “How Computers Handle Numbers”

Reals are used for continuously varying valuesEssentially just as you were taught at A-level

Introduction to Programming with Fortran 90 – p. 7/??

IEEE 754

You can assume a variant of IEEE 754You should almost always use IEEE 754 64-bitThere is information on how to select it later

IEEE 754 32–, 64– and 128–bit formats are:10

−38 to 10+38 and 6–7 decimal places

10−308 to 10

+308 and 15–16 decimal places10

−4932 to 10+4932 and 33–34 decimal places

Older and future systems may be differentYou may see some other values in use by 2010

Introduction to Programming with Fortran 90 – p. 8/??

Real Constants

• Real constants must contain a decimal pointThey can have an optional sign, just like integersThe basic fixed-point form is anything like:

123.456, -123.0, +0.0123, 123., .01230012.3, 0.0, 000., .000

• Optionally followed E or D and an exponent1.0E6, 123.0D-3, .0123e+5, 123.d+06, .0e0

• But 1E6 is not a valid Fortran real constantIt can be read in as data, though (see later)

Introduction to Programming with Fortran 90 – p. 9/??

Complex Numbers

This course will generally ignore themIf you don’t know what they are, don’t worry

These are (real, imaginary) pairs of REALsI.e. Cartesian notation, as at A-level

Constants are pairs of reals in parenthesesE.g. (1.23, -4.56) or (-1.0e-3, 0.987)

Introduction to Programming with Fortran 90 – p. 10/??

Declaring Numeric Variables

Variables hold values of different typesINTEGER :: count, income, markREAL :: width, depth, height

You can get all undeclared variables diagnosedAdd the statement IMPLICIT NONE at the start

of every program, subroutine, function etc.

If not, variables are declared implicitly by useNames starting with I–N are INTEGEROnes with A–H and O–Z are REAL

Introduction to Programming with Fortran 90 – p. 11/??

Implicit Declaration

• This is a common source of errorsREAL :: metres, inchesinch3s = meters*30.48

The effects can be even worse for function callsAsk offline if you want to know the details

• Also the default REAL type is a disasterToo inaccurate for practical use (see later)

• You should always use IMPLICIT NONE

Introduction to Programming with Fortran 90 – p. 12/??

Important Warning!

• I shall NOT do that myself

I warned you about this in the previous lectureThe problem is fitting all the text onto a slideI shall often rely on implicit typing :-(

• Do what I say, don’t do what I do

If I omit it in example files, it is a BUG

Introduction to Programming with Fortran 90 – p. 13/??

Assignment Statements

The general form is<variable> = <expression>

This is actually very powerful (see later)

This evaluates the expression on the RHSIt stores the result in the variable on the LHSIt replaces whatever value was there before

For example:Sum = Term1 + Term2 + (Eps * Err)Max = 2 * Min

Introduction to Programming with Fortran 90 – p. 14/??

Arithmetic Operators

There are five built-in numeric operations+ addition– subtraction

* multiplication/ division

** exponentiation (i.e. raise to the power of)

• Exponents can be any arithmetic type:INTEGER, REAL or COMPLEX

Generally, it is best to use them in that order

Introduction to Programming with Fortran 90 – p. 15/??

Examples

Some examples of arithmetic expressions areA*B-CA + C1 - D2X + Y/7.02**KA**B + CA*B-C(A + C1) - D2A + (C1 - D2)P**3/((X+Y*Z)/7.0-52.0)

Introduction to Programming with Fortran 90 – p. 16/??

Operator Precedence

Fortran uses normal mathematical conventions• Operators bind according to precedence• And then generally, from left to right

The precedence from highest to lowest is

** exponentiation

*/ multiplication and division+ – addition and subtraction

• Parentheses (‘(’ and ‘)’) are used to control it

Introduction to Programming with Fortran 90 – p. 17/??

Examples

X + Y * Z is equivalent to X + (Y * Z)X + Y / 7.0 is equivalent to X + (Y / 7.0)A – B + C is equivalent to (A – B) + CA + B ** C is equivalent to A + (B ** C)– A ** 2 is equivalent to – (A ** 2)A – ((( B + C))) is equivalent to A – (B + C)

• You can force any order you like(X + Y) * Z

Adds X to Y and then multiplies by Z

Introduction to Programming with Fortran 90 – p. 18/??

Precedence Problems

Mathematical conventions vary in some aspectsA / B * C – is it A / (B * C) or (A / B) * C?A ** B ** C – is it A ** (B ** C) or (A ** B) ** C?

Fortran specifies that:A / B * C is equivalent to (A / B) * CA ** B ** C is equivalent to A ** (B ** C)

• Yes, ** binds from right to left!

Introduction to Programming with Fortran 90 – p. 19/??

Parenthesis Problems

Always use parentheses in ambiguous casesIf only to imply “Yes, I really meant that”

And to help readers used to different rulesProgramming languages vary in what they do

Be careful of over-doing it – what does this do?(((A+(P*R+B)/2+B**3)/(4/Y)*C+D))+E)

• Several, simpler statements is better style

Introduction to Programming with Fortran 90 – p. 20/??

Integer Expressions

I.e. ones of integer constants and variables

INTEGER :: K, L, MN = K*(L+2)/M**3-N

These are evaluated in integer arithmetic

• Division always truncates towards zero

If K = 4 and L = 5, then K+L/2 is 6(-7)/3 and 7/(-3) are both -2

Introduction to Programming with Fortran 90 – p. 21/??

Mixed Expressions

INTEGER and REAL is evaluated as REALEither and COMPLEX goes to COMPLEX

Be careful with this, as it can be deceptive

INTEGER :: K = 5REAL :: X = 1.3X = X+K/2

That will add 2.0 to X, not 2.5K/2 is still an INTEGER expression

Introduction to Programming with Fortran 90 – p. 22/??

Conversions

There are several ways to force conversion• Intrinsic functions INT, REAL and COMPLEX

X = X+REAL(K)/2N = 100*INT(X/1.25)+25

You can use appropriate constantsYou can even add zero or multiply by one

X = X+K/2.0X = X+(K+0.0)/2

The last isn’t very nice, but works well enoughAnd see later about KIND and precision

Introduction to Programming with Fortran 90 – p. 23/??

Mixed-type Assignment

<real variable> = <integer expression>

• The RHS is converted to REALJust as in a mixed-type expression

<integer variable> = <real expression>

• The RHS is truncated to INTEGERIt is always truncated towards zero

Similar remarks apply to COMPLEX• The imaginary part is discarded, quietly

Introduction to Programming with Fortran 90 – p. 24/??

Examples

INTEGER :: K = 9, L = 5, M = 3, NREAL :: X, Y, ZX = K ; Y = L ; Z = MN = (K/L)*MN = (X/Y)*Z

N will be 3 and 5 in the two cases

(-7)/3 = 7/(-3) = -2 and 7/3 = (-7)/(-3) = 2

Introduction to Programming with Fortran 90 – p. 25/??

Numeric Errors

See “How Computers Handle Numbers”This a a very minimal summary

• Overflowing the range is a serious errorAs is dividing by zero (e.g. 123/0 or 0.0/0.0)Fortran does not define what those cases do

• Each numeric type may behave differentlyEven different compiler options will, too• And do not assume results are predictable

Introduction to Programming with Fortran 90 – p. 26/??

Examples

Assume the INTEGER range is ±2147483647

And the REAL range is ±1038

• Do you know what this is defined to do?

INTEGER :: K = 1000000REAL :: X = 1.0e20PRINT *, (K*K)/K, (X*X)/X

• The answer is “anything” – and it means itCompilers optimise on the basis of no errorsNumeric errors can cause logical errors

Introduction to Programming with Fortran 90 – p. 27/??

Numeric Non-Errors (1)

• Conversion to a lesser type loses informationYou will get no warning of this, unfortunately

REAL ⇒ INTEGER truncates towards zeroCOMPLEX ⇒ REAL drops the imaginary partCOMPLEX ⇒ INTEGER does both of them

That also applies when dropping in precisionE.g. assigning a 64-bit real to a 32-bit one

Introduction to Programming with Fortran 90 – p. 28/??

Numeric Non-Errors (2)

Fortran does NOT specify the followingBut it is true on all systems you will use

Results too small to represent are not errors• They will be replaced by zero if necessary

• Inexact results round to the nearest valueThat also applies when dropping in precision

Introduction to Programming with Fortran 90 – p. 29/??

Intrinsic Functions

Built-in functions that are always available• No declaration is needed – just use them

For example:Y = SQRT(X)PI = 4.0 * ATAN(1.0)Z = EXP(3.0*Y)X = REAL(N)N = INT(X)Y = SQRT(-2.0*LOG(X))

Introduction to Programming with Fortran 90 – p. 30/??

Intrinsic Numeric Functions

REAL(n) ! Converts its argument n to REALINT(x) ! Truncates x to INTEGER (to zero)AINT(x) ! The result remains REALNINT(x) ! Converts x to the nearest INTEGERANINT(x) ! The result remains REALABS(x) ! The absolute value of its argument! Can be used for INTEGER, REAL or COMPLEXMAX(x,y,...) ! The maximum of its argumentsMIN(x,y,...) ! The minimum of its argumentsMOD(x,y) ! Returns x modulo y

And there are more – some are mentioned later

Introduction to Programming with Fortran 90 – p. 31/??

Intrinsic Mathematical Functions

SQRT(x) ! The square root of xEXP(x) ! e raised to the power xLOG(x) ! The natural logarithm of xLOG10(x) ! The base 10 logarithm of x

SIN(x) ! The sine of x, where x is in radiansCOS(x) ! The cosine of x, where x is in radiansTAN(x) ! The tangent of x, where x is in radiansASIN(x) ! The arc sine of x in radiansACOS(x) ! The arc cosine of x in radiansATAN(x) ! The arc tangent of x in radians

And there are more – see the references

Introduction to Programming with Fortran 90 – p. 32/??

Bit Masks

As in C etc., integers are used for theseUse is by weirdly-named functions (historical)

Bit indices start at zeroBit K has value 2

K (little-endian)As usual, stick to non-negative integers

• A little tedious, but very easy to use

Introduction to Programming with Fortran 90 – p. 33/??

Bit Intrinsics

BIT_SIZE(x) ! The number of bits in xBTEST(x, n) ! Test bit n of xIBSET(x, n) ! Set bit n of xIBCLR(x, n) ! Clear bit n of xIBITS(x, m, n) ! Extract n bitsNOT(x) ! NOT xIAND(x, y) ! x AND yIOR(x, y) ! x OR yIEOR(x, y) ! x (exclusive or) yISHFT(x, n) ! Logical shiftISHFTC(x, n, [k]) ! Circular shift

Introduction to Programming with Fortran 90 – p. 34/??

Logical Type

These can take only two values: true or false.TRUE. and .FALSE.

• Their type is LOGICAL (not BOOL)

LOGICAL :: red, amber, green

IF (red) THENPRINT *, ’Stop’red = .False. ; amber = .True. ; green = .False.

ELSIF (red .AND. amber) THEN. . .

Introduction to Programming with Fortran 90 – p. 35/??

Relational Operators

• Relations create LOGICAL valuesThese can be used on any other built-in type

== (or .EQ.) equal to/= (or .NE.) not equal to

These can be used only on INTEGER and REAL< (or .LT.) less than<= (or .LE.) less than or equal> (or .GT.) greater than>= (or .GE.) greater than or equal

See “Computer Arithmetic” for more on REAL

Introduction to Programming with Fortran 90 – p. 36/??

Logical Expressions

Can be as complicated as you like

Start with .TRUE., .FALSE. and relationsCan use parentheses as for numeric ones

.NOT., .AND. and .OR.

.EQV. must be used instead of ==

.NEQV. must be used instead of /=

• Fortran is not like C-derived languagesLOGICAL is not a sort of INTEGER

Introduction to Programming with Fortran 90 – p. 37/??

Character Type

Used when strings of characters are requiredNames, descriptions, headings, etc.

• Fortran’s basic type is a fixed-length stringUnlike almost all more recent languages

• Character constants are quoted stringsPRINT *, ’This is a title’PRINT *, "And so is this"

The characters between quotes are the value

Introduction to Programming with Fortran 90 – p. 38/??

Character Data

• The case of letters is significant in themMultiple spaces are not equivalent to one spaceAny representable character may be used

The only Fortran syntax where the above is soRemember the line joining method?

In ’Timeˆˆ=ˆˆ13:15’, with ‘ˆ’ being a spaceThe character string is of length 15Character 1 is T, 8 is a space, 10 is 1 etc.

Introduction to Programming with Fortran 90 – p. 39/??

Character Constants"This has UPPER, lower and MiXed cases"’This has a double quote (") character’"Apostrophe (’) is used for single quote""Quotes ("") are escaped by doubling"’Apostrophes (’’) are escaped by doubling’’ASCII ‘, |, ~, ^, @, # and \ are allowed here’

"Implementations may do non-standard things"’Backslash (\) MAY need to be doubled’"Avoid newlines, tabs etc. for your own sanity"

Introduction to Programming with Fortran 90 – p. 40/??

Character Variables

CHARACTER :: answer, marital_statusCHARACTER(LEN=10) :: name, dept, facultyCHARACTER(LEN=32) :: address

answer and marital_status are each of length 1They hold precisely one character eachanswer might be blank, or hold ’Y’ or ’N’

name, dept and faculty are of length 10And address is of length 32

Introduction to Programming with Fortran 90 – p. 41/??

Another Form

CHARACTER ::answer*1, &marital_status*1, name*10, &dept*10, faculty*10, address*32

While this form is historical, it is more compact

• Don’t mix the forms – this is an abominationCHARACTER(LEN=10) :: dept, faculty, addr*32

• For obscure reasons, using LEN= is cleanerIt avoids some arcane syntactic “gotchas”

Introduction to Programming with Fortran 90 – p. 42/??

Character Assignment

CHARACTER(LEN=6) :: forename, surnameforename = ’Nick’surname = ’Maclaren’

forename is padded with spaces (’Nickˆˆ’)surname is truncated to fit (’Maclar’)

• Unfortunately, you won’t get toldBut at least it won’t overwrite something else

Introduction to Programming with Fortran 90 – p. 43/??

Character Concatenation

Values may be joined using the // operator

CHARACTER(LEN=6) :: identity, A, B, Zidentity = ’TH’ // ’OMAS’A = ’TH’ ; B = ’OMAS’Z = A // B

Sets identity to ’THOMAS’But Z is set to ’TH’ – why?

// does not remove trailing spacesIt uses the whole length of its inputs

Introduction to Programming with Fortran 90 – p. 44/??

Substrings

If Name has length 9 and holds ’Marmaduke’Name(1:1) would refer to ’M’Name(2:4) would refer to ’arm’Name(6:) would refer to ’duke’ – note the form!

We could therefore write statements such as

CHARACTER :: name*20, surname*18, title*4name = ’Dame Edna Everage’title = name(1:4)surname = name(11:)

Introduction to Programming with Fortran 90 – p. 45/??

Example

This is not an example of good style!

PROGRAM messageIMPLICIT NONECHARACTER :: mess*72, date*14, name*40mess = ’Program run on’mess(30:) = ’by’READ *, date, namemess(16:29) = datemess(33:) = namePRINT *, mess

ENDPROGRAM message

Introduction to Programming with Fortran 90 – p. 46/??

Warning – a “Gotcha”

CHARACTER substrings look like array sectionsBut there is no equivalent of array indexing

CHARACTER :: name*20, temp*1temp = name(10)

• name(10) is an implicit function callUse name(10:10) to get the tenth character

CHARACTER variables come in various lengthsname is not made up of 20 variables of length 1

Introduction to Programming with Fortran 90 – p. 47/??

Character Intrinsics

LEN(c) ! The STORAGE length of cTRIM(c) ! c without trailing blanksADJUSTL(C) ! With leading blanks removedINDEX(str,sub) ! Position of sub in strSCAN(str,set) ! Position of any character in setREPEAT(str,num) ! num copies of str, joined

And there are more – see the references

Introduction to Programming with Fortran 90 – p. 48/??

Examples

name = ’ Bloggs ’newname = TRIM(ADJUSTL(name))

newname would contain ’Bloggs’

CHARACTER(LEN=6) :: A, B, ZA = ’TH’ ; B = ’OMAS’Z = TRIM(A) // B

Now Z gets set to ’THOMAS’ correctly!

Introduction to Programming with Fortran 90 – p. 49/??

Collation Sequence

This controls whether "ffred" < "Fred" or not

• Fortran is not a locale-based languageIt specifies only the following

’A’ < ’B’ < ... < ’Y’ < ’Z’ | These ranges’a’ < ’b’ < ... < ’y’ < ’z’ | will not’0’ < ’1’ < ... < ’8’ < ’9’ | overlap’ ’ is less than all of ’A’, ’a’ and ’0’

A shorter operand is extended with blanks (’ ’)

Introduction to Programming with Fortran 90 – p. 50/??

Named Constants (1)

• These have the PARAMETER attribute

REAL, PARAMETER :: pi = 3.14159INTEGER, PARAMETER :: maxlen = 100

They can be used anywhere a constant can be

CHARACTER(LEN=maxlen) :: stringcircum = pi * diamIF (nchars < maxlen) THEN

. . .

Introduction to Programming with Fortran 90 – p. 51/??

Named Constants (2)

Why are these important?

They reduce mistyping errors in long numbersIs 3.14159265358979323846D0 correct?

They can make formulae etc. much clearerMuch clearer which constant is being used

They make it easier to modify the program laterINTEGER, PARAMETER :: MAX_DIMENSION = 10000

Introduction to Programming with Fortran 90 – p. 52/??

Named Character Constants

CHARACTER(LEN=*), PARAMETER :: &author = ’Dickens’, title = ’A Tale of Two Cities’

LEN=* takes the length from the data

It is permitted to define the length of a constantThe data will be padded or truncated if needed

• But the above form is generally the best

Introduction to Programming with Fortran 90 – p. 53/??

Named Constants (3)

• Expressions are allowed in constant values

REAL, PARAMETER :: pi = 3.14135, &pi_by_4 = pi/4, two_pi = 2*pi

CHARACTER(LEN=*), PARAMETER :: &all_names = ’Pip, Squeak, Wilfred’, &squeak = all_names[6:11]

Generally, anything reasonable is allowed• It must be determinable at compile time

Introduction to Programming with Fortran 90 – p. 54/??

Initialisation

• Variables start with undefined valuesThey often vary from run to run, too

• Initialisation is very like defining constantsWithout the PARAMETER attribute

INTEGER :: count = 0, I = 5, J = 100REAL :: inc = 1.0E5, max = 10.0E5, min = -10.0E5CHARACTER(LEN=10) :: light = ’Amber’LOGICAL :: red = .TRUE., blue = .FALSE., &

green = .FALSE.

Introduction to Programming with Fortran 90 – p. 55/??

Information for Practicals

A program has the following basic structure:

PROGRAM nameDeclarationsOther statementsEND PROGRAM name

Read and write data from the terminal using:

READ *, variable [ , variable ]...PRINT *, expression [ , expression ]...

Introduction to Programming with Fortran 90 – p. 56/??

Introduction to Programming withFortran 90

Control Constructs

Nick Maclaren

Computing Service

[email protected], ext. 34761

November 2007

Introduction to Programming with Fortran 90 – p. 1/??

Control Constructs

These change the sequential execution orderWe cover the main constructs in some detailWe shall cover procedure call later

The main ones are:Conditionals (IF etc.)Loops (DO etc.)Switches (SELECT/CASE etc.)Branches (GOTO etc.)

Loops are by far the most complicated

Introduction to Programming with Fortran 90 – p. 2/??

Single Statement IF

Oldest and simplest is the single statement IFIF (logical expression) simple statement

If the LHS is .True., the RHS is executedIf not, the whole statement has no effect

IF (MOD(count,1000) == 0) &PRINT *, ’Reached’, count

IF (X < A) X = A

Unsuitable for anything complicated• Only action statements can be on the RHSNo IFs or statements containing blocks

Introduction to Programming with Fortran 90 – p. 3/??

Block IF Statement

A block IF statement is more flexibleThe following is the most traditional form of it

IF (logical expression) THENthen block of statements

ELSEelse block of statements

ENDIF

If the expr. is .True., the first block is executedIf not, the second one is executed

ENDIF can be spelled END IF

Introduction to Programming with Fortran 90 – p. 4/??

Example

LOGICAL :: flip

IF (flip .AND. X /= 0.0) THENPRINT *, ’Using the inverted form’X = 1.0/AY = EXP(-A)

ELSEX = AY = EXP(A)

END IF

Introduction to Programming with Fortran 90 – p. 5/??

Omitting the ELSE

The ELSE and its block can be omitted

IF (X > Maximum) THENX = Maximum

END IF

IF (name(1:4) == "Miss" .OR. &name(1:4) == "Mrs.") THEN

name(1:3) = "Ms."name(4:) = name(5:)

ENDIF

Introduction to Programming with Fortran 90 – p. 6/??

Including ELSEIF Blocks (1)

ELSEIF functions much like ELSE and IF

IF (X < 0.0) THEN ! This is tried firstX = A

ELSEIF (X < 2.0) THEN ! This secondX = A + (B-A)*(X-1.0)

ELSEIF (X < 3.0) THEN ! And this thirdX = B + (C-B)*(X-2.0)

ELSE ! This is used if none succeedX = C

END IF

Introduction to Programming with Fortran 90 – p. 7/??

Including ELSEIF Blocks (2)

You can have as many ELSEIFs as you likeThere is only one ENDIF for the whole block

All ELSEIFs must come before any ELSEChecked in order, and the first success is taken

You can omit the ELSE in such constructs

ELSEIF can be spelled ELSE IF

Introduction to Programming with Fortran 90 – p. 8/??

Named IF Statements (1)

The IF can be preceded by <name> :And the ENDIF followed by <name> – note!And any ELSEIF/THENand ELSE may be

gnole : IF (X < 0.0) THENX = A

ELSEIF (X < 2.0) THEN gnoleX = A + (B-A)*(X-1.0)

ELSE gnoleX = C

END IF gnole

Introduction to Programming with Fortran 90 – p. 9/??

Named IF Statements (2)

The loop name must match and be distinctA great help for checking and clarity• You should name at least all long IFs

If you don’t nest IFs much, this style is fine

gnole : IF (X < 0.0) THENX = A

ELSEIF (X < 2.0) THENX = A + (B-A)*(X-1.0)

ELSEX = C

END IF gnole

Introduction to Programming with Fortran 90 – p. 10/??

Block Contents

• Almost any executable statements are OKBoth kinds of IF, complete loops etc.You may never notice the few restrictions

That applies to all of the block statementsIF, DO, SELECT etc.

And all of the blocks within an IF statement

• Avoid deep levels and very long blocksPurely because they will confuse human readers

Introduction to Programming with Fortran 90 – p. 11/??

Example

phasetest: IF (state == 1) THENIF (phase < pi_by_2) THEN

. . .ELSE

. . .END IF

ELSEIF (state == 2) THEN phasetestIF (phase > pi) PRINT *, ’A bit odd here’

ELSE phasetestIF (phase < pi) THEN

. . .END IF

END IF phasetest

Introduction to Programming with Fortran 90 – p. 12/??

Basic Loops (1)

• A single loop construct, with variationsThe basic syntax is:

[ loop name : ] DO [ [ , ] loop control ]block

ENDDO [ loop name ]

loop name and loop control are optionalWith no loop control, it loops indefinitely

ENDDO can be spelled END DOThe comma after DO is entirely a matter of taste

Introduction to Programming with Fortran 90 – p. 13/??

Basic Loops (2)

DO ! Implement the Unix ’yes’ commandPRINT *, ’y’

ENDDO

yes: DOPRINT *, ’y’

ENDDO yes

The loop name must match and be distinct• You should name at least all long loopsA great help for checking and clarityOther of it uses are described later

Introduction to Programming with Fortran 90 – p. 14/??

Indexed Loop Control

The loop control has the following form<integer variable> = <LWB> , <UPB>

The bounds can be any integer expressions

The variable starts at the lower boundA: If it exceeds the upper bound, the loop exits

The loop body is executed †

The variable is incremented by oneThe loop starts again from A

† See later about EXIT and CYCLE

Introduction to Programming with Fortran 90 – p. 15/??

Examples

DO I = 1 , 3PRINT *, 7*I-3

ENDDO

Prints 3 lines containing 4, 10 and 17

DO I = 3 , 1PRINT *, 7*I-3

ENDDO

Does nothing

Introduction to Programming with Fortran 90 – p. 16/??

Using an increment

The general form is<var> = <start> , <finish> , <step>

<var> is set to <start>, as before<var> is incremented by <step>, not oneUntil it exceeds <finish> (if <step> is positive)Or is smaller than <finish> (if <step> is negative)

• The direction depends on the sign of <step>The loop is invalid if <step> is zero, of course

Introduction to Programming with Fortran 90 – p. 17/??

Examples

DO I = 1 , 20 , 7PRINT *, I

ENDDO

Prints 3 lines containing 1, 8 and 15

DO I = 20 , 1 , 7PRINT *, I

ENDDO

Does nothing

Introduction to Programming with Fortran 90 – p. 18/??

Examples

DO I = 20 , 1 , -7PRINT *, I

ENDDO

Prints 3 lines containing 20, 13 and 6

DO I = 1 , 20 , -7PRINT *, I

ENDDO

Does nothing

Introduction to Programming with Fortran 90 – p. 19/??

Mainly for C Programmers

The control expressions are calculated on entry• Changing their variables has no effect

• It is illegal to assign to the loop variable

DO index = i*j, n**21, kn = 0; k = -1 ! Does not affect the loopindex = index+1 ! Is forbidden

ENDDO

Introduction to Programming with Fortran 90 – p. 20/??

Loop Control Statements

EXIT leaves the innermost loopCYCLE skips to the next iterationEXIT/CYCLE name is for the loop named nameThese are usually used in single-statement IFs

DOx = read_number()IF (x < 0.0) EXITcount = count+1; total = total+xIF (x == 0.0) CYCLE. . .

ENDDO

Introduction to Programming with Fortran 90 – p. 21/??

Example

INTEGER :: state(right), table(left , right)FirstMatch = 0outer: DO i = 1 , right

IF (state(right) /= OK) CYCLEDO j = 1 , left

IF (found(table(j,i)) THENFirstMatch = iEXIT outer

ENDIFENDDO

ENDDO outer

Introduction to Programming with Fortran 90 – p. 22/??

WHILE Loop Control

The loop control has the following formWHILE ( <logical expression> )

The expression is reevaluated for each cycleThe loop exits as soon as it becomes .FALSE.The following are equivalent:

DO WHILE ( <logical expression> )

DOIF (.NOT. ( <logical expression> )) EXIT

Introduction to Programming with Fortran 90 – p. 23/??

RETURN and STOP

RETURN returns from a procedure• It does not return a resultHow to do that is covered under procedures

STOP halts the program cleanly• Do not spread it throughout your codeCall a procedure to tidy up and finish off

Introduction to Programming with Fortran 90 – p. 24/??

Multi-way IFs

IF (expr == val1) THEN. . .

ELSEIF (expr >= val2 .AND. expr <= val3) THEN. . .

ELSEIF (expr == val4) THEN. . .

ELSE. . .

ENDIF

Very commonly, expr is always the sameAnd all of the vals are constant expressionsThen there is another way of coding it

Introduction to Programming with Fortran 90 – p. 25/??

SELECT CASE (1)

PRINT *, ’Happy Birthday’SELECT CASE (age)CASE(18)

PRINT *, ’You can now vote’CASE(40)

PRINT *, ’And life begins again’CASE(60)

PRINT *, ’And free prescriptions’CASE(100)

PRINT *, ’And greetings from the Queen’CASE DEFAULT

PRINT *, ’It’’s just another birthday’END SELECT

Introduction to Programming with Fortran 90 – p. 26/??

SELECT CASE (2)

• The CASE clauses are statementsTo put on one line, use ‘CASE(18) ; <statement>’

The values must be initialisation expressionsINTEGER, CHARACTER or LOGICALYou can specify ranges for the first two

CASE (-42:42) ! -42 to 42 inclusiveCASE (42:) ! 42 or aboveCASE (:42) ! Up to and including 42

Be careful with CHARACTER ranges

Introduction to Programming with Fortran 90 – p. 27/??

SELECT CASE (3)

SELECT CASE can be spelled SELECTCASEEND SELECT can be spelled ENDSELECT• CASE DEFAULT but NOT CASEDEFAULT

SELECT and CASE can be named, like IF

• It is an error for the ranges to overlap

It is not an error for ranges to be emptyEmpty ranges don’t overlap with anythingIt is not an error for the default to be unreachable

Introduction to Programming with Fortran 90 – p. 28/??

Labels and GOTO

Warning: this area gets seriously religious!

Most executable statements can be labelledGOTO <label> branches directly to the label

In old Fortran, you needed to use a lot of these• Now, you should almost never use themIf you think you need to, consider redesigning

• Named loops, EXIT and CYCLE are better

Introduction to Programming with Fortran 90 – p. 29/??

Remaining uses of GOTO

• Useful for branching to clean-up codeE.g. diagnostics, undoing partial updates etc.This is by FAR the main remaining use

Fortran does not have any cleaner mechanismsE.g. it has no exception handling constructs

• They make a few esoteric algorithms clearerE.g. certain finite-state machine modelsI have seen such code 3–4 times in 40+ years

Introduction to Programming with Fortran 90 – p. 30/??

Using for Clean-up Code

SUBROUTINE FredDO . . .

CALL SUBR (arg1 , arg2 , . . . , argn , ifail)IF (ifail /= 0) GOTO 999

ENDDO. . . lots more similar code . . .RETURN

999 SELECT CASE (ifail)CASE(1) ! Code for ifail = 1

. . .CASE(2) ! Code for ifail = 2

. . .END SUBROUTINE Fred

Introduction to Programming with Fortran 90 – p. 31/??

Introduction to Programming withFortran 90

Array Concepts

Nick Maclaren

Computing Service

[email protected], ext. 34761

November 2007

Introduction to Programming with Fortran 90 – p. 1/??

Array Declarations

Fortran is the array-handling languageApplications like Matlab descend from it

You can do almost everything you want to• Provided that your arrays are rectangularIrregular arrays are possible via pointers

• Start by using the simplest features onlyWhen you need more, check what Fortran has

We will cover the basics and a bit more

Introduction to Programming with Fortran 90 – p. 2/??

Array Declarations

Attributes qualify the type in declarationsImmediately following, separated by a comma

The DIMENSION attribute declares arraysIt has the form DIMENSION(<dimensions>)Each <dimension> is <lwb>:<upb>

For example:

INTEGER, DIMENSION(0:99) :: tableREAL, DIMENSION(-10:10, -10:10) :: values

Introduction to Programming with Fortran 90 – p. 3/??

Examples of Declarations

Some examples of array declarations:

INTEGER, DIMENSION(0:99) :: arr1, arr2, arr3INTEGER, DIMENSION(1:12) :: days_in_month

CHARACTER(LEN=10), DIMENSION(1:250) :: namesCHARACTER(LEN=3), DIMENSION(1:12) :: monthsREAL, DIMENSION(1:350) :: box_locationsREAL, DIMENSION(-10:10, -10:10) :: pos1, pos2REAL, DIMENSION(0:5, 1:7, 2:9, 1:4, -5:-2) :: bizarre

Introduction to Programming with Fortran 90 – p. 4/??

Lower Bounds of One

Lower bounds of one (1:) can be omitted

INTEGER, DIMENSION(12) :: days_in_monthCHARACTER(LEN=10), DIMENSION(250) :: namesCHARACTER(LEN=3), DIMENSION(12) :: monthsREAL, DIMENSION(350) :: box_locationsREAL, DIMENSION(0:5, 7, 2:9, 4, -5:-2) :: bizarre

It is entirely a matter of taste whether you do

• C/C++/Python users note ONE not ZERO

Introduction to Programming with Fortran 90 – p. 5/??

Alternative Form

The same base type but different bounds

INTEGER :: arr1(0:99), arr2(0:99), arr3(0:99), &days_in_month(1:12)

REAL :: box_locations(1:350), pos1(-10:10, -10:10), &pos2(-10:10, -10:10), bizarre(0:5, 1:7, 2:9, 1:4, -5:-2)

But this is thoroughly confusing:

INTEGER, DIMENSION(0:99) :: arr1, arr2, arr3, &days_in_month(1:12), extra_array, &days_in_leap_year(1:12)

Introduction to Programming with Fortran 90 – p. 6/??

Terminology (1)

REAL :: A(0:99), B(3, 6:9, 5)

The rank is the number of dimensionsA has rank 1 and B has rank 3

The bounds are the upper and lower limitsA has bounds 0:99 and B has 1:3, 6:9 and 1:5

A dimension’s extent is the UPB-LWB+1A has extent 100 and B has extents 3, 4 and 5

Introduction to Programming with Fortran 90 – p. 7/??

Terminology (2)

REAL :: A(0:99), B(3, 6:9, 5)

The size is the total number of elementsA has size 100 and B has size 60

The shape is its rank and extentsA has shape (100) and B has shape (3,4,5)

Arrays are conformable if they share a shape• The bounds do not have to be the same

Introduction to Programming with Fortran 90 – p. 8/??

Array Element References

An array index can be any integer expressionE.g. months(J), selects the Jth month

INTEGER, DIMENSION(-50:50) :: markDO I = -50, 50

mark(I) = 2*IEND DO

Sets mark to –100, –98, . . ., 98, 100

Introduction to Programming with Fortran 90 – p. 9/??

Index Expressions

INTEGER, DIMENSION(1:80) :: seriesDO K = 1, 40

series(2*K) = 2*K-1series(2*K-1) = 2*K

ENDDO

Sets the even elements to the odd indicesAnd vice versa

You can go completely overboard, tooseries(int(1.0+80.0*cos(123.456))) = 42

Introduction to Programming with Fortran 90 – p. 10/??

Example of Arrays – Sorting

Sort a list of numbers into ascending orderThe top-level algorithm is:

1. Read the numbers and store them in an array.2. Sort them into ascending order of magnitude.3. Print them out in sorted order.

Introduction to Programming with Fortran 90 – p. 11/??

Selection Sort

This is NOT how to write a general sortIt takes O(N 2) time – compared to O(Nlog(N))

For each location J from 1 to N–1For each location K from J+1 to N

If the value at J exceeds that at KThen swap them

End of loopEnd of loop

Introduction to Programming with Fortran 90 – p. 12/??

Selection Sort (1)PROGRAM sort10

INTEGER, DIMENSION(1:10) :: numsINTEGER :: temp, J, K

! --- Read in the dataPRINT *, ’Type ten integers each on a new line’DO J = 1, 10

READ *, nums(J)ENDDO

! --- Sort the numbers into ascending order of magnitude. . .

! --- Write out the sorted listDO J = 1, 10

PRINT *, ’Rank ’, J, ’ Value is ’, nums(J)ENDDO

END PROGRAM sort10Introduction to Programming with Fortran 90 – p. 13/??

Selection Sort (2)

! --- Sort the numbers into ascending order of magnitudeL1: DO J = 1, 9L2: DO K = J+1, 10

IF(nums(J) > nums(K)) THENtemp = nums(K)nums(K) = nums(J)nums(J) = temp

ENDIFENDDO L2

ENDDO L1

Introduction to Programming with Fortran 90 – p. 14/??

Valid Array Bounds

The bounds can be any constant expressionsThere are two ways to use run-time bounds

• ALLOCATABLE arrays – see later• When allocating them in proceduresWe will discuss the following under procedures

SUBROUTINE workspace (size)INTEGER :: sizeREAL, DIMENSION(1:size*(size+1)) :: array

. . .

Introduction to Programming with Fortran 90 – p. 15/??

Using Arrays as Objects (1)

Arrays can be handled as compound objectsSections allow access as groups of elementsThere are a large number of intrinsic procedures

Simple use handles all elements “in parallel”• Scalar values are expanded as needed

Set all elements of an array to a single value

INTEGER, DIMENSION(1:50) :: markmark = 0

Introduction to Programming with Fortran 90 – p. 16/??

Using Arrays as Objects (2)

You can use whole arrays as simple variablesProvided that they are all conformable

REAL, DIMENSION(1:200) :: arr1, arr2, arr3. . .arr1 = arr2+1.23*exp(arr3/4.56)

• I really do mean “as simple variables”

The RHS and any LHS indices are evaluatedAnd then the RHS is assigned to the LHS

Introduction to Programming with Fortran 90 – p. 17/??

Array Sections

Array sections create an aliased subarrayIt is a simple variable with a value

INTEGER :: arr1(1:100), arr2(1:50), arr3(1:100)

arr1(1:63) = 5 ; arr1(64:100) = 7arr2 = arr1(1:50)+arr3(51:100)

• Even this is legal, but forces a copy

arr1(26:75) = arr1(1:50)+arr1(51:100)

Introduction to Programming with Fortran 90 – p. 18/??

Array Sections

A(1:3,1:4)A(2:5,7)

A(1:6,1:8)

Introduction to Programming with Fortran 90 – p. 19/??

Short Form

Existing array bounds may be omittedEspecially useful for multidimensional arrays

If we have REAL, DIMENSION(1:6, 1:8) :: AA(3:, :4) is the same as A(3:6, 1:4)A, A(:, :) and A(1:6, 1:8) are all the same

A(6, :) is the 6th row as a 1-D vectorA(:, 3) is the 3rd column as a 1-D vectorA(6:6, :) is the 6th row as a 1×8 matrixA(:, 3:3) is the 3rd column as a 6×1 matrix

Introduction to Programming with Fortran 90 – p. 20/??

Conformability of Sections

The conformability rule applies to sections, too

REAL :: A(1:6, 1:8), B(0:3, -5:5), C(0:10)

A(2:5, 1:7) = B(:, -3:3) ! both have shape (4, 7)A(4, 2:5) = B(:, 0) + C(7:) ! all have shape (4)C(:) = B(2, :) ! both have shape (11)

But these would be illegal

A(1:5, 1:7) = B(:, -3:3) ! shapes (5,7) and (4,7)A(1:1, 1:3) = B(1, 1:3) ! shapes (1,3) and (3)

Introduction to Programming with Fortran 90 – p. 21/??

Array Bounds

Subscripts/sections must be within boundsThe following are invalid (undefined behaviour)

REAL :: A(1:6, 1:8), B(0:3, -5:5), C(0:10)A(2:5, 1:7) = B(:, -6:3)A(7, 2:5) = B(:, 0)C(:11) = B(2, :)

NAG will usually check; most others won’tErrors lead to overwriting etc. and CHAOSEven NAG will not check old-style Fortran

Introduction to Programming with Fortran 90 – p. 22/??

Sections with Strides

Array sections need not be contiguousAny uniform progression is allowed

This is exactly like a more compact DO-loopNegative strides are allowed, too

INTEGER :: arr1(1:100), arr2(1:50), arr3(1:50)arr1(1:100:2) = arr2 ! Sets every odd elementarr1(100:1:-2) = arr3 ! Even elements, reversed

arr1 = arr1(100:1:-1) ! Reverses the order of arr1

Introduction to Programming with Fortran 90 – p. 23/??

Elemental Operations

We have seen operations and intrinsic functionsMost built-in operators/functions are elementalThey act element-by-element on arrays

REAL, DIMENSION(1:200) :: arr1, arr2, arr3arr1 = arr2+1.23*exp(arr3/4.56)

Comparisons and logical operations, too

REAL, DIMENSION(1:200) :: arr1, arr2, arr3LOGICAL, DIMENSION(1:200) :: flagsflags = (arr1 > exp(arr2) .OR. arr3 < 0.0)

Introduction to Programming with Fortran 90 – p. 24/??

Array Intrinsic Functions (1)

There are over 20 useful intrinsic proceduresThey can save a lot of coding and debugging

SIZE(x [, n]) ! The size of xSHAPE(x [, n]) ! The shape of xLBOUND(x [, n]) ! The nth lower bound of xUBOUND(x [, n]) ! The nth upper bound of xMINVAL(x) ! The minimum of all elements of xMINLOC(x) ! The index of the minimumMAXVAL(x) ! The maximum of all elements of xMAXLOC(x) ! The index of the maximum

Introduction to Programming with Fortran 90 – p. 25/??

Array Intrinsic Functions (2)

SUM(x [, n]) ! The sum of all elements of xPRODUCT(x [, n]) ! The product of all elements of xTRANSPOSE(x) ! The transposition of xDOT_PRODUCT(x, y) ! The dot product of x and yMATMUL(x, y) ! Matrix multiplication

These also have some features not mentionedThere are more (especially for reshaping)There are ones for array masking (see later)

Look at the references for the details

Introduction to Programming with Fortran 90 – p. 26/??

Reminder

TRANSPOSE(X) means Xij ⇒ Xji

It must have two dimensions, but needn’t be square

DOT_PRODUCT(X, Y) means∑

iXi . Yi ⇒ Z

Two vectors, both of the same length and type

MATMUL(X, Y) means∑

kXik . Ykj ⇒ Zij

Second dimension of X must match the first of YThe matrices need not be the same shape

Either of X or Y may be a vector in MATMUL

Introduction to Programming with Fortran 90 – p. 27/??

Array Element Order (1)

This is also called “storage order”

Traditional term is “column-major order”But Fortran arrays are not laid out in columns!Much clearer: “first index varies fastest”

REAL :: A(1:3, 1:4)

The elements of A are stored in the order

A(1,1), A(2,1), A(3,1), A(1,2), A(2,2), A(3,2), A(1,3),A(2,3), A(3,3), A(1,4), A(2,4), A(3,4)

Introduction to Programming with Fortran 90 – p. 28/??

Array Element Order (2)

Opposite to C, Matlab, Mathematica etc.

You don’t often need to know the storage orderThree important cases where you do:

• I/O of arrays, especially unformatted• Array constructors and array constants• Optimisation (caching and locality)

There are more cases in old-style FortranAvoid that, and you need not learn them

Introduction to Programming with Fortran 90 – p. 29/??

Simple I/O of Arrays (1)

Arrays and sections can be included in I/OThese are expanded in array element order

REAL, DIMENSION(3, 2) :: oxoREAD *, oxo

This is exactly equivalent to:

REAL, DIMENSION(3, 2) :: oxoREAD *, oxo(1, 1), oxo(2, 1), oxo(3, 1), &

oxo(1, 2), oxo(2, 2), oxo(3, 2)

Introduction to Programming with Fortran 90 – p. 30/??

Simple I/O of Arrays (2)

Array sections can also be used

REAL, DIMENSION(100) :: numsREAD *, nums(30:50)

REAL, DIMENSION(3, 3) :: oxoREAD *, oxo(:, 3)

The last statement is equivalent to

READ *, oxo(1, 3), oxo(2, 3), oxo(3, 3)

Introduction to Programming with Fortran 90 – p. 31/??

Simple I/O of Arrays (3)

A useful and fairly common construction

INTEGER :: NAREAL, DIMENSION(1:100) :: AREAD *, NA, A(1:NA)

Fortran evaluates a transfer list as it executes it

• We will see why this is so useful under I/O

Introduction to Programming with Fortran 90 – p. 32/??

Array Constructors (1)

An array constructor creates a temporary array• Commonly used for assigning array values

INTEGER :: marks(1:6)marks = (/ 10, 25, 32, 54, 54, 60 /)

Constructs an array with elements10, 25, 32, 54, 54, 60

And then copies that array into marks

A good compiler will optimise that!

Introduction to Programming with Fortran 90 – p. 33/??

Array Constructors (2)

• Variable expressions are OK in constructors

(/ x, 2.0*y, SIN(t*w/3.0),... etc. /)

They can be used anywhere an array can beExcept where you might assign to them!

• All expressions must be the same typeThis can be relaxed in Fortran 2003

Introduction to Programming with Fortran 90 – p. 34/??

Array Constructors (3)

Arrays can be used in the value listThey are flattened into array element order

Implied DO-loops (as in I/O) allow sequences

If n has the value 7

(/ 0.0, (k/10.0, k = 2, n), 1.0 /)

Is equivalent to:

(/ 0.0, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 1.0 /)

Introduction to Programming with Fortran 90 – p. 35/??

Constants and Initialisation (1)

Array constructors are very useful for thisAll elements must be initialisation expressionsI.e. ones that can be evaluated at compile time

For rank one arrays, just use a constructor

REAL, PARAMETER :: a(1:3) = (/ 1.23, 4.56, 7.89 /)

REAL :: b(3) = (/ 1.2, 3.4, 5.6 /)b = exp(b)

Introduction to Programming with Fortran 90 – p. 36/??

Constants and Initialisation (2)

Other types can be initialised in the same way

CHARACTER(LEN=4), DIMENSION(1:5) :: names = &(/ ’Fred’, ’Joe’, ’Bill’, ’Bert’, ’Alf’ /)

Initialisation expressions are allowed

INTEGER, PARAMETER :: N = 3, M = 6, P = 12INTEGER :: arr(1:3) = (/ N, (M/N), (P/N) /)

But NOT:

REAL :: arr(1:3) = (/ 1.0, exp(1.0), exp(2.0) /)

Introduction to Programming with Fortran 90 – p. 37/??

Constants and Initialisation (3)

That is for Fortran 90, however

Fortran 2003 allows MUCH moreNot just almost all intrinsic functions

REAL :: arr(1:3) = (/ 1.0, exp(1.0), exp(2.0) /)

But things that I had difficulty believing!

Introduction to Programming with Fortran 90 – p. 38/??

Multiple Dimensions

Constructors cannot be nested – e.g. NOT:

REAL, DIMENSION(3, 4) :: array = &(/ (/ 1.1, 2.1, 3.1 /), (/ 1.2, 2.2, 3.2 /), &

(/ 1.3, 2.3, 3.3 /), (/ 1.4, 2.4, 3.4 /) /)

They construct only rank one arrays

• Construct higher ranks using RESHAPEThis is covered in the extra slides on arrays

Introduction to Programming with Fortran 90 – p. 39/??

Allocatable Arrays (1)

Arrays can be declared with an unknown shapeAttempting to use them in that state will fail

INTEGER, DIMENSION(:), ALLOCATABLE :: countsREAL, DIMENSION(:, :, :), ALLOCATABLE :: values

They become defined when space is allocated

ALLOCATE (counts(1:1000000))ALLOCATE (value(0:N, -5:5, M:2*N+1))

Introduction to Programming with Fortran 90 – p. 40/??

Allocatable Arrays (2)

Failure will terminate the programYou can trap most allocation failures

INTEGER :: istatALLOCATE (arr(0:100, -5:5, 7:14), STAT=istat)IF (istat /= 0) THEN

. . .ENDIF

Arrays can be deallocated usingDEALLOCATE (nums)

There are more features in Fortran 2003

Introduction to Programming with Fortran 90 – p. 41/??

Example

INTEGER, DIMENSION(:), ALLOCATABLE :: countsINTEGER :: size, code

! --- Ask the user how many counts he hasPRINT *, ’Type in the number of counts’READ *, size

! --- Allocate memory for the arrayALLOCATE (counts(1:size), STAT=code)IF (code /= 0) THEN

. . .ENDIF

Introduction to Programming with Fortran 90 – p. 42/??

Allocation and Fortran 2003

Fortran 95 constrains ALLOCATABLE objectsCannot be arguments, results or in derived typesI.e. local to procedures or in modules only

Fortran 2003 allows them almost everywhereMost compilers already include those features

• Most restrictions are likely to be temporary

Ask if you hit problems and want to check

Introduction to Programming with Fortran 90 – p. 43/??

Reminder

The above is all many programmers needThere is a lot more, but skip it for now

At this point, let’s see a real exampleCholesky decomposition following LAPACKWith all error checking omitted, for clarity

It isn’t pretty, but it is like the mathematics• And that really helps to reduce errorsE.g. coding up a published algorithm

Introduction to Programming with Fortran 90 – p. 44/??

Cholesky Decomposition

To solve A = LLT , in tensor notation:

Ljj =

Ajj −

j−1∑

k=1

L2jk

∀i>j, Lij = (Aij −

j−1∑

k=1

LikLjk)/Ljj

Most of the Web uses i and j the other way round

Introduction to Programming with Fortran 90 – p. 45/??

Cholesky Decomposition

SUBROUTINE CHOLESKY ( A )IMPLICIT NONEINTEGER :: J, NREAL :: A (:, :)N = UBOUND (A, 1)DO J = 1, N

A(J, J) = SQRT ( A(J, J) - &DOT_PRODUCT ( A(J, :J-1), A(J, :J-1) ) )

IF (J < N) &A(J+1:, J) = ( A(J+1:, J) - &

MATMUL ( A(J+1:, :J-1), A(J, :J-1) ) ) / A(J, J)ENDDO

END SUBROUTINE CHOLESKY

Introduction to Programming with Fortran 90 – p. 46/??

Other Important Features

These have been omitted for simplicityThere are extra slides giving an overview

• Constructing higher rank array constants• Using integer vectors as indices• Masked assignment and WHERE• Memory locality and performance• Avoiding unnecessary array copying

Introduction to Programming with Fortran 90 – p. 47/??

Introduction to Programming withFortran 90Procedures

Nick Maclaren

Computing Service

[email protected], ext. 34761

November 2007

Introduction to Programming with Fortran 90 – p. 1/??

Sub-Dividing The Problem

• Most programs are thousands of linesFew people can grasp all the details

• You often use similar code in several places

• You often want to test parts of the code

• Designs often break up naturally into steps

Hence, all sane programmers use procedures

Introduction to Programming with Fortran 90 – p. 2/??

What Fortran Provides

There must be a single main programThere are subroutines and functionsAll are collectively called procedures

A subroutine is some out-of-line codeThere are very few restrictions on what it can doIt is always called exactly where it is coded

A function’s purpose is to return a resultThere are some restrictions on what it can doIt is called only when its result is needed

Introduction to Programming with Fortran 90 – p. 3/??

Example – Cholesky (1)

We saw this when considering arraysIt is a very typical, simple subroutine

SUBROUTINE CHOLESKY (A)IMPLICIT NONEINTEGER :: J, NREAL :: A(:, :), XN = UBOUND(A, 1)DO J = 1, N

. . .ENDDO

END SUBROUTINE CHOLESKY

Introduction to Programming with Fortran 90 – p. 4/??

Example – Cholesky (2)

And this is how it is called

PROGRAM MAINIMPLICIT NONEREAL, DIMENSION(5, 5) :: A = 0.0REAL, DIMENSION(5) :: Z

. . .CALL CHOLESKY (A)

. . .END PROGRAM MAIN

We shall see how to declare it later

Introduction to Programming with Fortran 90 – p. 5/??

Example – Variance

FUNCTION Variance (Array)IMPLICIT NONEREAL :: Variance, XREAL, INTENT(IN), DIMENSION(:) :: ArrayX = SUM(Array)/SIZE(Array)Variance = SUM((Array-X)**2)/SIZE(Array)

END FUNCTION Variance

REAL, DIMENSION(1000) :: data. . .

Z = Variance(data)

We shall see how to declare it later

Introduction to Programming with Fortran 90 – p. 6/??

Example – Sorting (1)

This was the harness of the selection sortReplace the actual sorting code by a call

PROGRAM sort10IMPLICIT NONEINTEGER, DIMENSION(1:10) :: nums. . .

! --- Sort the numbers into ascending order of magnitudeCALL SORTIT (nums, 10)

! --- Write out the sorted list. . .

END PROGRAM sort10

Introduction to Programming with Fortran 90 – p. 7/??

Example – Sorting (2)

SUBROUTINE SORTIT (array, size)IMPLICIT NONEINTEGER :: size, temp, array(size), J, K

L1: DO J = 1, size-1L2: DO K = J+1, size

IF(nums(J) > nums(K)) THENtemp = nums(K)nums(K) = nums(J)nums(J) = temp

ENDIFENDDO L2

ENDDO L1END SUBROUTINE SORTIT

Introduction to Programming with Fortran 90 – p. 8/??

CALL Statement

The CALL statement evaluates its argumentsThe following is an over-simplified description

• Variables and array sections define memory• Expressions are stored in a hidden variable

It then transfers control to the subroutinePassing the locations of the actual arguments

Upon return, the next statement is executed

Introduction to Programming with Fortran 90 – p. 9/??

SUBROUTINE Statement

Declares the procedure and its argumentsThese are called dummy arguments in Fortran

The subroutine’s interface is defined by:• The SUBROUTINE statement itself• The declarations of its dummy arguments

SUBROUTINE SORTIT (array, size)INTEGER :: size, [ temp, ] array(size) [ , J, K ]

Introduction to Programming with Fortran 90 – p. 10/??

Statement Order

A SUBROUTINE statement starts a subroutineAny USE statements must come nextThen IMPLICIT NONE, when you use itThen the rest of the declarationsThen the executable statementsIt ends at an END SUBROUTINE statement

PROGRAM and FUNCTION are similar

There are other rules, but you may ignore them

Introduction to Programming with Fortran 90 – p. 11/??

Dummy Arguments

• Their names exist only in the procedureThey are declared much like local variables

Any actual argument names are irrelevantOr any other names outside the procedure

• The dummy arguments are associatedwith the actual arguments

Think of association as a bit like aliasing

Introduction to Programming with Fortran 90 – p. 12/??

Argument Matching

Dummy and actual argument lists must matchThe number of arguments must be the sameAnd each argument must match in type

The size of the dummy array must not exceedthe size of the actual array argument

We shall come back to array arguments later

Introduction to Programming with Fortran 90 – p. 13/??

Example (1)

We have a subroutine with an interface like:

SUBROUTINE Normalise (array, size)INTEGER :: sizeREAL, DIMENSION(size) :: array

The following calls are correct:

REAL, DIMENSION(1:10) :: data

CALL Normalise (data, 10)CALL Normalise (data(2:5), SIZE(data(2:5)))

Introduction to Programming with Fortran 90 – p. 14/??

Example (2)

SUBROUTINE Normalise (array, size)INTEGER :: sizeREAL, DIMENSION(size) :: array

The following calls are not correct:

INTEGER, DIMENSION(1:10) :: indicesREAL :: var, data(10)

CALL Normalise (indices, 10) ! wrong base typeCALL Normalise (var, 1) ! not an arrayCALL Normalise (data, 10.0) ! wrong typeCALL Normalise (data, 20) ! dummy array too big

Introduction to Programming with Fortran 90 – p. 15/??

Functions

Often the required result is a single valueIt is easier to write a FUNCTION subprogram

E.g. to find the largest of three values:• Find the largest of the first and second• Find the largest of that and the third

The function name defines a local variable• Its value on return is the result returnedThe RETURN statement does not take a value

Introduction to Programming with Fortran 90 – p. 16/??

Example (1)

FUNCTION largest_of (first, second, third)IMPLICIT NONEINTEGER :: largest_ofINTEGER :: first, second, thirdIF (first > second) THEN

largest_of = firstELSE

largest_of = secondENDIFIF (third > largest_of) largest_of = third

END FUNCTION largest_of

Introduction to Programming with Fortran 90 – p. 17/??

Example (2)

INTEGER :: trial1, trial2 ,trial3, total, counttotal = 0 ; count = 0DO

PRINT *, ’Type three trial values:’READ *, trial1, trial2, trial3IF (MIN(trial1, trial2, trial3) < 0) EXIT

count = count + 1total = total + &

largest_of(trial1, trial2, trial3)ENDDOPRINT *, ’Number of trial sets = ’, count, &

’ Total of best of 3 = ’,total

Introduction to Programming with Fortran 90 – p. 18/??

INTENT (1)

You can make arguments read-only

SUBROUTINE Summarise (array, size)INTEGER, INTENT(IN) :: sizeREAL, DIMENSION(size) :: array

That will prevent you writing to it by accidentOr calling another procedure that does thatIt may also help the compiler to optimise

• Strongly recommended for read-only args

Introduction to Programming with Fortran 90 – p. 19/??

INTENT (2)

You can also make them write-onlyLess useful, but still very worthwhile

SUBROUTINE Init (array, value)IMPLICIT NONEREAL, DIMENSION(:), INTENT(OUT) :: arrayREAL, INTENT(IN) :: valuearray = value

END SUBROUTINE Init

As useful for optimisation as INTENT(IN)

Introduction to Programming with Fortran 90 – p. 20/??

INTENT (3)

The default is effectively INTENT(INOUT)

• But specifying INTENT(INOUT) is usefulIt will trap the following nasty error

SUBROUTINE Munge (value)REAL, INTENT(INOUT) :: valuevalue = 100.0*valuePRINT *, value

END SUBROUTINE Munge

CALL Munge(1.23)

Introduction to Programming with Fortran 90 – p. 21/??

Example

SUBROUTINE expsum(n, k, x, sum)IMPLICIT NONEINTEGER, INTENT(IN) :: nREAL, INTENT(IN) :: k, xREAL, INTENT(OUT) :: sumINTEGER :: isum = 0.0DO i = 1, n

sum = sum + exp(-i*k*x)ENDDO

END SUBROUTINE expsum

Introduction to Programming with Fortran 90 – p. 22/??

Overlapping

INTENT does not protect against all errors

• If arguments overlap, weird things happenAlso applies to arguments and global data

Fortran doesn’t have any way to trap thatNor do any other current languages – sorry

• Be careful when using array argumentsIncluding using array elements as arguments

Introduction to Programming with Fortran 90 – p. 23/??

Using Modules (1)

We will return to these in more detail laterThis is how to compile procedures separatelyFirst create a file (e.g. mymod.f90) like:

MODULE mymodCONTAINS

FUNCTION Variance (Array)REAL, INTENT(IN), DIMENSION(:) :: ArrayX = SUM(Array)/SIZE(Array)Variance = SUM((Array-X)**2)/SIZE(Array)

END FUNCTION VarianceEND MODULE mymod

Introduction to Programming with Fortran 90 – p. 24/??

Using Modules (2)

The module name need not be the file nameDoing that is strongly recommended, though

• You can include any number of procedures

You now compile it, but don’t link itf95 -C=all -c mymod.f90

It will create files like mymod.mod and mymod.oThey contain the interface and the code

Introduction to Programming with Fortran 90 – p. 25/??

Using Modules (3)

You use it in the following way• You can use any number of modules

PROGRAM mainUSE mymodREAL, DIMENSION(10) :: arrayPRINT *, ’Type 10 values’READ *, arrayPRINT *, ’Variance = ’, Variance(array)

END PROGRAM main

f95 -C=all -o main main.f90 mymod.o

Introduction to Programming with Fortran 90 – p. 26/??

Internal Procedures

PROGRAM, SUBROUTINE or FUNCTIONCan use CONTAINS much like a module

Included procedures are internal subprogramsMost useful for small, private auxiliary ones• You can include any number of procedures

Visible in the outer procedure onlyInternal subprograms may not contain their own

internal subprograms

Introduction to Programming with Fortran 90 – p. 27/??

Internal Procedures

PROGRAM mainREAL, DIMENSION(10) :: arrayPRINT *, ’Type 10 values’READ *, arrayPRINT *, ’Variance = ’, Variance(array)

CONTAINSFUNCTION Variance (Array)

REAL, INTENT(IN), DIMENSION(:) :: ArrayX = SUM(Array)/SIZE(Array)Variance = SUM((Array-X)**2)/SIZE(Array)

END FUNCTION VarianceEND PROGRAM main

Introduction to Programming with Fortran 90 – p. 28/??

Using Procedures

Use either technique for solving test problems

• They are the best techniques for real codeSimplest, and give full access to functionalityWe will cover some other ones later

• Note that, if a procedure is in a moduleit may still have internal subprograms

Introduction to Programming with Fortran 90 – p. 29/??

Example

MODULE mymodCONTAINS

SUBROUTINE Sorter (array, flags). . .

CONTAINSFUNCTION Compare (value1, value2, flags)

. . .END FUNCTION CompareSUBROUTINE Swap (loc1, loc2)

. . .END FUNCTION Swap

END SUBROUTINE SorterEND MODULE mymod

Introduction to Programming with Fortran 90 – p. 30/??

FUNCTION Result Variable

The function name defines the result variableYou can change this if you prefer

FUNCTION Variance_of_an_array (Array) RESULT(var)REAL :: varREAL, INTENT(IN), DIMENSION(:) :: Arrayvar = SUM(Array)/SIZE(Array)var = SUM((Array-var)**2)/SIZE(Array)

END FUNCTION Variance_of_an_array

REAL, DIMENSION(1000) :: data. . .

Z = Variance_of_an_array(data)

Introduction to Programming with Fortran 90 – p. 31/??

Keyword Arguments (1)

SUBROUTINE AXIS (X0, Y0, Length, Min, Max, Intervals)REAL, INTENT(IN) :: X0, Y0, Length, Min, MaxINTEGER, INTENT(IN) :: Intervals

END SUBROUTINE AXIS

CALL AXIS(0.0, 0.0, 100.0, 0.1, 1.0, 10)

• Error prone to write and unclear to read

And it can be a lot worse than that!

Introduction to Programming with Fortran 90 – p. 32/??

Keyword Arguments (2)

Dummy arg. names can be used as keywordsYou don’t have to remember their order

SUBROUTINE AXIS (X0, Y0, Length, Min, Max, Intervals). . .

CALL AXIS(Intervals=10, Length=100.0, &Min=0.1, Max=1.0, X0=0.0, Y0=0.0)

• The argument order now doesn’t matterThe keywords identify the dummy arguments

Introduction to Programming with Fortran 90 – p. 33/??

Keyword Arguments (3)

Keywords args. can follow positionalThe following is allowed

SUBROUTINE AXIS (X0, Y0, Length, Min, Max, Intervals). . .

CALL AXIS(0.0, 0.0, Intervals=10, Length=100.0, &Min=0.1, Max=1.0)

• Remember that the best code is the clearestUse whichever convention feels most natural

Introduction to Programming with Fortran 90 – p. 34/??

Keyword Reminder

Keywords are not names in the calling proc.They are used only to map to dummy argumentsThe following works, but is somewhat confusing

SUBROUTINE Nuts (X, Y, Z)REAL, DIMENSION(:) :: XINTEGER :: Y, Z

END SUBROUTINE Nuts

INTEGER :: XREAL, DIMENSION(100) :: Y, ZCALL Nuts (Y=X, Z=1, X=Y)

Introduction to Programming with Fortran 90 – p. 35/??

Explicit Array Bounds

In procedures, they are more flexibleAny reasonable integer expression is allowed

Essentially, you can use any ordinary formulaUsing only constants and integer variablesFew programmers will ever hit the restrictions

The most common use is for workspaceBut it applies to all array declarations

Introduction to Programming with Fortran 90 – p. 36/??

Assumed Shape Arrays (1)

• The best way to declare array argumentsYou must declare procedures as above

• Specify all bounds as simply a colon (‘:’)The rank must match the actual argumentThe lower bounds default to one (1)The upper bounds are taken from the extents

REAL, DIMENSION(:) :: vectorREAL, DIMENSION(:, :) :: matrixREAL, DIMENSION(:, :, :) :: tensor

Introduction to Programming with Fortran 90 – p. 37/??

Example

SUBROUTINE Peculiar (vector, matrix)REAL, DIMENSION(:), INTENT(INOUT) :: vectorREAL, DIMENSION(:, :), INTENT(IN) :: matrix. . .

END SUBROUTINE Peculiar

REAL, DIMENSION(1000), :: oneREAL, DIMENSION(100, 100) :: twoCALL Peculiar (one(101:200), two(21:, 26:75) )

vector will be DIMENSION(1:100)matrix will be DIMENSION(1:80, 1:50)

Introduction to Programming with Fortran 90 – p. 38/??

Assumed Shape Arrays (2)

Query functions were described earlierSIZE, SHAPE, LBOUND and UBOUND

So you can write completely generic procedures

SUBROUTINE Init (matrix, scale)REAL, DIMENSION(:, :), INTENT(OUT) :: matrixINTEGER, INTENT(IN) :: scale, M, NDO N = 1, UBOUND(matrix,2)

DO M = 1, UBOUND(matrix,1)matrix(M, N) = scale*M + N

END DOEND DO

END SUBROUTINE Init

Introduction to Programming with Fortran 90 – p. 39/??

Cholesky Decomposition

SUBROUTINE CHOLESKY(A)IMPLICIT NONEINTEGER :: J, NREAL :: A(:, :), XN = UBOUND(A, 1)IF (N < 1 .OR. UBOUND(A, 2) /= N)

CALL Error("Invalid array passed to CHOLESKY")DO J = 1, N

. . .ENDDO

END SUBROUTINE CHOLESKY

Now I have added appropriate checking

Introduction to Programming with Fortran 90 – p. 40/??

Setting Lower Bounds

Even when using assumed shape arraysyou can set any lower bounds you want

• You do that in the called procedure

SUBROUTINE Orrible (vector, matrix, n)REAL, DIMENSION(2*n+1:) :: vectorREAL, DIMENSION(0:, 0:) :: matrix. . .

END SUBROUTINE Orrible

Introduction to Programming with Fortran 90 – p. 41/??

Automatic Arrays (1)

Local arrays with run-time bounds are calledautomatic arrays

Bounds may be taken from an argumentOr a constant or variable in a module

SUBROUTINE aardvark (size)USE sizemod ! This defines worksizeINTEGER, INTENT(IN) :: size

REAL, DIMENSION(1:worksize) :: array_1REAL, DIMENSION(1:size*(size+1)) :: array_2

Introduction to Programming with Fortran 90 – p. 42/??

Automatic Arrays (2)

Another very common use is a ‘shadow’ arrayi.e. one the same shape as an argument

SUBROUTINE pard (matrix)REAL, DIMENSION(:, :) :: matrix

REAL, DIMENSION(UBOUND(matrix, 1), &UBOUND(matrix, 2)) :: &

matrix_2, matrix_3

And so on – automatic arrays are very flexible

Introduction to Programming with Fortran 90 – p. 43/??

Explicit Shape Array Args (1)

We cover these because of their importanceThey were the only mechanism in Fortran 77• But, generally, they should be avoided

In this form, all bounds are explicitThey are declared just like automatic arraysThe dummy should match the actual argument

• Only the very simplest uses are coveredThere are more details in the extra slides

Introduction to Programming with Fortran 90 – p. 44/??

Explicit Shape Array Args (2)

You can use constants

SUBROUTINE Orace (matrix, array)INTEGER, PARAMETER :: M = 5, N = 10REAL, DIMENSION(1:M, 1:N) :: matrixREAL, DIMENSION(1000) :: array. . .

END SUBROUTINE Orace

INTEGER, PARAMETER :: M = 5, N = 10REAL, DIMENSION(1:M, 1:N) :: tableREAL, DIMENSION(1000) :: workspaceCALL Orace(table, workspace)

Introduction to Programming with Fortran 90 – p. 45/??

Explicit Shape Array Args (3)

It is common to pass the bounds as arguments

SUBROUTINE Weeble (matrix, m, n)INTEGER, INTENT(IN) :: m, nREAL, DIMENSION(1:m, 1:n) :: matrix. . .

END SUBROUTINE Weeble

You can use expressions, of course• But it is not really recommendedPurely on the grounds of human confusion

Introduction to Programming with Fortran 90 – p. 46/??

Explicit Shape Array Args (4)

You can define the bounds in a moduleEither as a constant or in a variable

SUBROUTINE Wobble (matrix)USE sizemod ! This defines m and nREAL, DIMENSION(1:m, 1:n) :: matrix. . .

END SUBROUTINE Weeble

• The same remarks about expressions apply

Introduction to Programming with Fortran 90 – p. 47/??

Assumed Length CHARACTER

A CHARACTER length can be assumedThe length is taken from the actual argument

You use an asterisk (*) for the lengthIt acts very like an assumed shape array

Note that it is a property of the typeIt is independent of any array dimensions

Introduction to Programming with Fortran 90 – p. 48/??

Example (1)

FUNCTION is_palindrome (word)LOGICAL :: is_palindromeCHARACTER(LEN=*), INTENT(IN) :: wordINTEGER :: N, I

is_palindrome = .False.N = LEN(word)

comp: DO I = 1, (N-1)/2IF (word(I:I) /= word(N+1-I:N+1-I)) THEN

RETURNENDIF

ENDDO compis_palindrome = .True.

END FUNCTION is_palindrome

Introduction to Programming with Fortran 90 – p. 49/??

Example (2)

Such arguments do not have to be read-only

SUBROUTINE reverse_word (word)CHARACTER(LEN=*), INTENT(INOUT) :: wordCHARACTER(LEN=1) :: cN = LEN(word)DO I = 1, (N-1)/2

c = word(I:I)word(I:I) = word(N+1-I:N+1-I)word(N+1-I:N+1-I) = c

ENDDOEND SUBROUTINE reverse_word

Introduction to Programming with Fortran 90 – p. 50/??

Explicit Length Character (1)

You can use an explicit length, tooThe dummy should match the actual argumentIt is best to declare it as an integer constant

SUBROUTINE sorter (list)CHARACTER(LEN=8), DIMENSION(:) :: list. . .

END FUNCTION sorter

CHARACTER(LEN=8), DIMENSION(1000) :: data. . .CALL sorter(data)

Introduction to Programming with Fortran 90 – p. 51/??

Explicit Length Character (2)

Similar rules as for explicit shape arraysAlso applies to automatic variablesLength from argument, constant or variable

SUBROUTINE grockle (value, size)INTEGER, INTENT(IN) :: sizeCHARACTER(LEN=size) :: value, workspace. . .

END FUNCTION grockle

CHARACTER(LEN=125) :: bufferCALL grockle(buffer, 125)

Introduction to Programming with Fortran 90 – p. 52/??

Character Valued Functions (1)

Functions can return CHARACTER valuesFixed-length ones are the simplest

FUNCTION truth (value)IMPLICIT NONECHARACTER(LEN=8) :: truthLOGICAL, INTENT(IN) :: valueIF (value) THEN

truth = ’.True.’ELSE

truth = ’.False.’ENDIF

END FUNCTION truth

Introduction to Programming with Fortran 90 – p. 53/??

Character Valued Functions (2)

The result length can be taken from an argument

FUNCTION reverse_word (word)IMPLICIT NONECHARACTER(LEN=*), INTENT(IN) :: wordCHARACTER(LEN=LEN(word)) :: reverse_wordINTEGER :: I, NN = LEN(word)DO I = 1, N

reverse_word(I:I) = word(N+1-I:N+1-I)ENDDO

END FUNCTION reverse_word

Introduction to Programming with Fortran 90 – p. 54/??

PURE Functions

You can declare a function to be PURE

All data arguments must specify INTENT(IN)It must not modify any global dataIt must not do I/O (except with internal files)It must call only PURE proceduresSome restrictions on more advanced features

Generally overkill – but good practiceMost built-in procedures are PURE

Introduction to Programming with Fortran 90 – p. 55/??

Example

This is the cleanest way to define a function

PURE FUNCTION Variance (Array)IMPLICIT NONEREAL :: Variance, XREAL, INTENT(IN), DIMENSION(:) :: ArrayX = SUM(Array)/SIZE(Array)Variance = SUM((Array-X)**2)/SIZE(Array)

END FUNCTION Variance

Most safety, and best possible optimisation

Introduction to Programming with Fortran 90 – p. 56/??

ELEMENTAL Functions

Functions can be declared as ELEMENTALLike PURE, but arguments must be scalar

You can use them on arrays and in WHEREThey apply to each element, like built-in SIN

ELEMENTAL FUNCTION Scale (arg1, arg2)REAL, INTENT(IN) :: arg1, arg2Scale = arg1/sqrt(arg1**2+arg2**2)

END FUNCTION Scale

REAL, DIMENSION(100) :: arr1, arr2array = Scale(arr1, arr2)

Introduction to Programming with Fortran 90 – p. 57/??

Static Data

Sometimes you need to store values locallyUse a value in the next call of the procedure

• You do this with the SAVE attributeInitialised variables get that automaticallyIt is good practice to specify it anyway

The best style avoids most such useIt can cause trouble with parallel programmingBut it works, and lots of programs rely on it

Introduction to Programming with Fortran 90 – p. 58/??

Example

This is a futile example, but shows the feature

SUBROUTINE Factorial (result)IMPLICIT NONEREAL, INTENT(OUT) :: resultREAL, SAVE :: mult = 1.0, value = 1.0mult = mult+1.0value = value*multresult = value

END SUBROUTINE Factorial

Introduction to Programming with Fortran 90 – p. 59/??

Warning

Omitting SAVE will usually appear to workBut even a new compiler version may break itAs will increasing the level of optimisation

• Decide which variables need it during design

• Always use SAVE if you want itAnd preferably never when you don’t!

• Never assume it without specifying it

Introduction to Programming with Fortran 90 – p. 60/??

Global Data

Sometimes you need to share global data

It’s trivial, and can be done very cleanly

• We shall cover that later, under modules

Introduction to Programming with Fortran 90 – p. 61/??

Procedure Arguments

Procedures can be passed as argumentsThis is a very important facility for some people

• However, internal procedures can’t beAsk if you want to know why – it’s technical

For historical reasons, this is a bit messyWe will return to it, also under modules

It just happens to be simplest that way!

Introduction to Programming with Fortran 90 – p. 62/??

Other Features

There is a lot that we haven’t coveredWe will return to some of it later

• The above covers the absolute basicsPlus some other features you need to know

• Be a bit cautious when using other featuresSome have been omitted because of “gotchas”

• And I have over-simplified a few areas

Introduction to Programming with Fortran 90 – p. 63/??

Extra Slides

Topics covered in more slides on procedures

• Argument association and updating• The semantics of function calls• Optional arguments• Array- and character-valued functions• Assumed-size arrays• Mixing Explicit and assumed shape arrays• Array arguments and sequence association• Miscellaneous other points

Introduction to Programming with Fortran 90 – p. 64/??

Introduction to Programming withFortran 90

KIND, Precision and COMPLEX

Nick Maclaren

Computing Service

[email protected], ext. 34761

November 2007

Introduction to Programming with Fortran 90 – p. 1/??

Warning: Time Warp

Unfortunately, we need to define a moduleWe shall cover those quite a lot later

The one we shall define is trivialJust use it, and don’t worry about the details

Everything you need to know will be explained

Introduction to Programming with Fortran 90 – p. 2/??

The Basic Problem

REAL must be same size as INTEGERThis is for historical reasons – ask if you care

32 bits allows integers of up to 2147483647Usually plenty for individual array indices

But floating-point precision is only 6 digitsAnd its range is only 10

−38− 10

+38

Index values are not exact in floating-pointAnd there are many, serious numerical problems

Introduction to Programming with Fortran 90 – p. 3/??

Example

REAL, DIMENSION(20000000) :: AREAL :: XX = SIZE(A)-1PRINT *, X

Prints 20000000.0 – which is not rightThat code needs only 80 MB to go wrong

See “How Computers Handle Numbers”Mainly on the numerical aspects

Introduction to Programming with Fortran 90 – p. 4/??

KIND Values

Implementation-dependent integer valuesselecting the type (e.g. a specific REAL)

• Don’t use integer constants directly

You can get the KIND of any expression

KIND(var) is the KIND value of varKIND(0.0) is the KIND value of REALKIND(0.0D0) is that of DOUBLE PRECISION

Introduction to Programming with Fortran 90 – p. 5/??

SELECTED_REAL_KIND

You can request a minimum precision and rangeBoth are specified in decimal

SELECTED_REAL_KIND ( Prec [ , Range ] )

This gives at least Prec decimal placesand range 10

−Range− 10

+Range

E.g. SELECTED_REAL_KIND(12)at least 12 decimal places

Introduction to Programming with Fortran 90 – p. 6/??

Using KIND (1)

You should write and compile a module

MODULE doubleINTEGER, PARAMETER :: DP = KIND(0.0D0)

END MODULE double

At the start of every procedure statementI.e. PROGRAM, SUBROUTINE or FUNCTION

USE doubleIMPLICIT NONE

Introduction to Programming with Fortran 90 – p. 7/??

Using KIND (2)

Declaring variables etc. is easy

REAL(KIND=DP) :: a, b, cREAL(KIND=DP), DIMENSION(10) :: x, y, z

Using constants is more tedious, but easy

0.0_DP, 7.0_DP, 0.25_DP, 1.23_DP, 1.23E12_DP,0.1_DP, 1.0E-1_DP, 3.141592653589793_DP

That’s really all you need to know . . .

Introduction to Programming with Fortran 90 – p. 8/??

Using KIND (3)

Note that the above makes it trivial to changeALL you need is to change the module

MODULE doubleINTEGER, PARAMETER :: DP = &

SELECTED_REAL_KIND(12, 100)END MODULE double

(15, 300) requires IEEE 754 double or better

SELECTED_REAL_KIND(25, 1000)Or even:

Introduction to Programming with Fortran 90 – p. 9/??

DOUBLE PRECISION

Most older code uses this for IEEE 64-bitCurrently works on all systems except Cray

REAL(KIND=KIND(0.0D0)) :: a, b, c

DOUBLE PRECISION, DIMENSION(10) :: x, y, z

0.0D0, 7.0D0, 0.25D0, 1.23D0, 1.23D12,0.1D0, 1.0D-1, 3.141592653589793D0

Generic code is more portable and future-proofAdvisable if you may want to use HECToR

Introduction to Programming with Fortran 90 – p. 10/??

Ordinary REAL Constants

These will often do what you expect• But they will very often lose precision

0.0, 7.0, 0.25, 1.23, 1.23E12,0.1, 1.0E-1, 3.141592653589793

Only the first three will do what you expect

• In old Fortran constructs, can cause chaosE.g. as arguments to external libraries

Introduction to Programming with Fortran 90 – p. 11/??

Using Procedures

Almost all intrinsics ‘just work’ (i.e. are generic)IMPLICIT NONE removes most common traps

• Avoid specific (old) names for proceduresAMAX0, DMIN1, DSQRT, FLOAT, IFIX etc.

• DPROD is also not generic – use a library

• Don’t use the INTRINSIC statement

• Don’t pass intrinsic functions as arguments

Introduction to Programming with Fortran 90 – p. 12/??

Type Conversion (1)

This is the main “gotcha” – you should use

REAL(KIND=DP) :: xx = REAL(<integer expression>, KIND=DP)

Omitting the KIND=DP may lose precision• With no warning from the compiler

Automatic conversion is actually safer!

x = <integer expression>

Introduction to Programming with Fortran 90 – p. 13/??

Type Conversion (2)

There is a legacy intrinsic functionIf you are using explicit DOUBLE PRECISION

x = DBLE(<integer expression>)

All other “gotchas” are for COMPLEX

Introduction to Programming with Fortran 90 – p. 14/??

Old Fortran Libraries

Be very careful with external libraries

• Make sure argument types are rightAutomatic conversion does not happen

Any procedure with no explicit interfaceI did say that using old Fortran was more painful

Introduction to Programming with Fortran 90 – p. 15/??

INTEGER KIND

You can choose different sizes of integer

INTEGER, PARAMETER :: big = &SELECTED_INT_KIND(12)

INTEGER(KIND=big) :: bignum

bignum can hold values of up to at least 1012

Few users will need this – mainly for OpenMP

Some compilers may allocate smaller integersE.g. by using SELECTED_INT_KIND(4)

Introduction to Programming with Fortran 90 – p. 16/??

CHARACTER KIND

It can be used to select the encodingIt is mainly a Fortran 2003 feature

Can select default, ASCII or ISO 10646ISO 10646 is effectively Unicode

It is not covered in this course

Introduction to Programming with Fortran 90 – p. 17/??

Complex Arithmetic

Fortran is the answer – what was the question?

Has always been supported, and well integrated

COMPLEX is a (real, imaginary) pair of REALIt uses the same KIND as underlying reals

COMPLEX(KIND=DP) :: cc = (1.23_DP,4.56_DP)

Full range of operations, intrinsic functions etc.

Introduction to Programming with Fortran 90 – p. 18/??

Example

COMPLEX(KIND=DP) :: c, d, e, f

c = (1.23_DP,4.56_DP)*CONJG(d)+SIN(f*g)e = EXP(d+c/f)*ABS(LOG(e))

The functions are the complex formsE.g. ABS is

√re2 + im2

CONJG is complex conjugate, of course

Using COMPLEX really IS that simple!

Introduction to Programming with Fortran 90 – p. 19/??

Worst “Gotcha”

• Must specify KIND in conversion function

c = CMPLX(<X-expr>, KIND=DP)c = CMPLX(<X-expr>, <Y-expr>, KIND=DP)

This will not work – KIND is default REALUsually with no warning from the compiler

c = CMPLX(1.0_DP,2.0_DP)

Introduction to Programming with Fortran 90 – p. 20/??

Conversion to REAL

REAL(KIND=DP) :: xCOMPLEX(KIND=DP) :: c

. . . lots of statements . . .x = x+cc = 2.0_DP*x

Loses the imaginary part, without warningAlmost all modern languages do the same

Introduction to Programming with Fortran 90 – p. 21/??

A Warning for Old Code

C = DCMPLX(0.1_DP, 0.1_DP)

That is often seen in Fortran IV legacy codeIt doesn’t work in standard (modern) Fortran

• It will be caught by IMPLICIT NONE

Introduction to Programming with Fortran 90 – p. 22/??

Complex I/O

The form of I/O we have used is list-directedCOMPLEX does what you would expect

COMPLEX(KIND=DP) :: c = (1.23_DP,4.56_DP)WRITE (*, *) C

Prints “(1.23,4.56)”And similarly for input

There is some more on COMPLEX I/O later

Introduction to Programming with Fortran 90 – p. 23/??

Exceptions

Complex exceptions are mathematically hard• Overflow often does what you won’t expectFortran, unfortunately, is no exception to this

See “How Computers Handle Numbers”

• Don’t cause them in the first place

• Use the techniques described to detect them

Introduction to Programming with Fortran 90 – p. 24/??

Introduction to Programming withFortran 90

Modules and Interfaces

Nick Maclaren

Computing Service

[email protected], ext. 34761

November 2007

Introduction to Programming with Fortran 90 – p. 1/??

Module Summary

• Similar to same term in other languagesAs usual, modules fulfil multiple purposes

• For shared declarations (i.e. “headers”)

• Defining global data (old COMMON)

• Defining procedure interfaces

• Semantic extension (described later)

And more ...

Introduction to Programming with Fortran 90 – p. 2/??

Use Of Modules

• Think of a module as a high-level interfaceCollects <whatevers> into a coherent unit

• Design your modules carefullyAs the ultimate top-level program structurePerhaps only a few, perhaps dozens

• Good place for high-level commentsPlease document purpose and interfaces

Introduction to Programming with Fortran 90 – p. 3/??

Module Structure

MODULE <name>Static (often exported) data definitions

CONTAINSProcedure definitions and interfaces

END MODULE <name>

Files may contain several modulesModules may be split across many files

• For simplest use, keep them 1≡1

Introduction to Programming with Fortran 90 – p. 4/??

IMPLICIT NONE

Add MODULE to the places where you use this

MODULE doubleIMPLICIT NONEINTEGER, PARAMETER :: DP = KIND(0.0D0)

END MODULE double

MODULE parametersUSE doubleIMPLICIT NONEREAL(KIND=DP), PARAMETER :: one = 1.0_DP

END MODULE parameters

Introduction to Programming with Fortran 90 – p. 5/??

Reminder

I do not always do it, because of space

Introduction to Programming with Fortran 90 – p. 6/??

Module Interactions

Modules can USE other modulesDependency graph shows visibility/usage

• Modules may not depend on themselvesLanguages that allow that are very confusing

Can do anything you are likely to get to work

• If you need to do more, ask for advice

Introduction to Programming with Fortran 90 – p. 7/??

Example (1)

MODULE doubleINTEGER, PARAMETER :: DP = KIND(0.0D0)

END MODULE double

MODULE parametersUSE doubleREAL(KIND=DP), PARAMETER :: one = 1.0_DPINTEGER, PARAMETER :: NX = 10, NY = 20

END MODULE parameters

MODULE workspaceUSE double ; USE parameters

REAL(KIND=DP), DIMENSION(NX, NY) :: now, thenEND MODULE workspace

Introduction to Programming with Fortran 90 – p. 8/??

Example (2)

The main program might use them like this

PROGRAM mainUSE doubleUSE parametersUSE workspace. . .

END PROGRAM main

• Could omit the USE double and USE parametersThey would be inherited through USE workspace

Introduction to Programming with Fortran 90 – p. 9/??

Module Dependencies

double

workspace

parameters

MainProgram

Introduction to Programming with Fortran 90 – p. 10/??

Module Dependencies

Program

Introduction to Programming with Fortran 90 – p. 11/??

Compiling Modules

The module name need not be the file nameDoing that is strongly recommended, though

• You can include any number of whatevers

You now compile it, but don’t link itf95 -C=all -c mymod.f90

It will create files like mymod.mod and mymod.oThey contain the interface and the code

Introduction to Programming with Fortran 90 – p. 12/??

Warning (1)

The following names are global identifiersAll module namesAll external procedure names

I.e. not in a module or internal

• They must all be distinctAnd remember their case is not significant

• Avoid using any built-in procedure namesThat works, but it is too easy to make errors

Introduction to Programming with Fortran 90 – p. 13/??

Warning (2)

Avoid file names like fred.f90 ANDexternal names like FRED

Unless FRED is inside fred.f90

• It also helps a lot when hunting for FRED

This has nothing at all to do with FortranIt is something that implementations get wrongEspecially the fancier sort of debuggers

Introduction to Programming with Fortran 90 – p. 14/??

Shared Constants

We have already seen and used this:

MODULE doubleINTEGER, PARAMETER :: DP = KIND(0.0D0)

END MODULE double

You can do a great deal of that sort of thing

• Greatly improves clarity and maintainabilityThe larger the program, the more it helps

Introduction to Programming with Fortran 90 – p. 15/??

Example

MODULE hotchpotchINTEGER, PARAMETER :: DP = KIND(0.0D0)REAL(KIND=DP), PARAMETER :: &

pi = 3.141592653589793_DP, &e = 2.718281828459045_DP

CHARACTER(LEN=*), PARAMETER :: &messages(3) = &

(\ "Hello", "Goodbye", "Oh, no!" \)INTEGER, PARAMETER :: stdin = 5, stdout = 6REAL(KIND=DP), PARAMETER, &

DIMENSION(0:100, -1:25, 1:4) :: table = &RESHAPE( (/ . . . /), (/ 101, 27, 4 /) )

END MODULE hotchpotch

Introduction to Programming with Fortran 90 – p. 16/??

Derived Type Definitions

We shall cover these later:

MODULE BicycleREAL, PARAMETER :: pi = 3.141592TYPE Wheel

INTEGER :: spokesREAL :: diameter, widthCHARACTER(LEN=15) :: material

ENDTYPE WheelEND MODULE Bicycle

USE BicycleTYPE(Wheel) :: w1

Introduction to Programming with Fortran 90 – p. 17/??

Global Data

Variables in modules define global dataThese can be fixed-size or allocatable arrays

• You need to specify the SAVE attributeSet automatically for initialised variablesBut it is good practice to do it explicitly

A simple SAVE statement saves everything• That isn’t always the best thing to do

Introduction to Programming with Fortran 90 – p. 18/??

Example (1)

MODULE state_variablesINTEGER, PARAMETER :: nx=100, ny=100REAL, DIMENSION(NX, NY), SAVE :: &

current, increment, valuesREAL, SAVE :: time = 0.0

ENDMODULE state_variables

USE state_variablesIMPLICIT NONEDO

current = current + incrementCALL next_step(current, values)

ENDDO

Introduction to Programming with Fortran 90 – p. 19/??

Example (2)

This is equivalent to the previous example

MODULE state_variablesIMPLICIT NONESAVEINTEGER, PARAMETER :: nx=100, ny=100REAL, DIMENSION(NX, NY) :: &

current, increment, valuesREAL :: time = 0.0

ENDMODULE state_variables

Introduction to Programming with Fortran 90 – p. 20/??

Example (3)

The sizes do not have to be fixed

MODULE state_variablesREAL, DIMENSION(:, :), ALLOCATABLE, &

SAVE :: current, increment, valuesENDMODULE state_variables

USE state_variablesIMPLICIT NONEINTEGER :: NX, NYREAD *, NX, NYALLOCATE (current(NX, NY), increment(NX, NY), &

values(NX, NY))

Introduction to Programming with Fortran 90 – p. 21/??

Use of SAVE

If a variable is set in one procedureand then it is used in another

• You must specify the SAVE attribute

• If not, very strange things may happenIf will usually “work”, under most compilersA new version will appear, and then it won’t

• Applies if the association is via the moduleNot when it is passed as an argument

Introduction to Programming with Fortran 90 – p. 22/??

Example (1)

MODULE statusREAL, DIMENSION :: state

ENDMODULE status

SUBROUTINE joeUSE statusstate = 0.0

END SUBROUTINE joe

SUBROUTINE alf (arg)REAL :: argarg = 0.0

END SUBROUTINE alf

Introduction to Programming with Fortran 90 – p. 23/??

Example (2)

SUBROUTINE fredUSE status

CALL joePRINT *, state ! this is UNDEFINED

CALL alf(state)PRINT *, state ! this is defined to be 0.0

END SUBROUTINE fred

Introduction to Programming with Fortran 90 – p. 24/??

Shared Workspace

Shared scratch space can be useful for HPCIt can avoid excessive memory fragmentation

You can omit SAVE for simple scratch spaceThis can be significantly more efficient

• Design your data use carefullySeparate global scratch space from storageAnd use them consistently and correctly

• This is good practice in any case

Introduction to Programming with Fortran 90 – p. 25/??

Explicit Interfaces

Procedures now need explicit interfacesE.g. for assumed-shape or keywordsWithout them, must use Fortran 77 interfaces

• Modules are the primary way of doing thisWe will come to the secondary one later

Simplest to include the procedures in modulesThe procedure code goes after CONTAINSThis is what we described earlier

Introduction to Programming with Fortran 90 – p. 26/??

Example

MODULE mymodCONTAINS

FUNCTION Variance (Array)REAL, INTENT(IN), DIMENSION(:) :: ArrayX = SUM(Array)/SIZE(Array)Variance = SUM((Array-X)**2)/SIZE(Array)

END FUNCTION VarianceEND MODULE mymod

PROGRAM mainUSE mymod. . .PRINT *, ’Variance = ’, Variance(array)

Introduction to Programming with Fortran 90 – p. 27/??

Procedures in Modules

That is including all procedures in modulesWorks very well in almost all programs

• There really isn’t much more to it

It doesn’t handle very large modules wellTry to avoid designing those, if possible

It also doesn’t handle procedure arguments

Introduction to Programming with Fortran 90 – p. 28/??

Interfaces in Modules

The module can define just the interfaceThe procedure code is supplied elsewhereThe interface block comes before CONTAINS

• You had better get them consistent!The interface and code are not checked

• Extract interfaces from procedure codeNAGWare and f2f90 can do it automatically

Introduction to Programming with Fortran 90 – p. 29/??

Cholesky Decomposition

SUBROUTINE CHOLESKY(A)USE double ! note that this has been addedINTEGER :: J, NREAL(KIND=dp) :: A(:, :), XN = UBOUND(A, 1)DO J = 1, N

X = SQRT(A(J, J) - &DOT_PRODUCT(A(J, :J-1), A(J, :J-1)))A(J,J) = XIF (J < N) &

A(J+1:, J) = (A(J+1:, J) - &MATMUL(A(J+1:, :J-1), A(J, :J-1))) / X

ENDDOEND SUBROUTINE CHOLESKY

Introduction to Programming with Fortran 90 – p. 30/??

The Interface Module

MODULE MYLAPACKINTERFACE

SUBROUTINE CHOLESKY(A)USE double ! part of the interfaceIMPLICIT NONEREAL(KIND=dp) :: A(:, :)

END SUBROUTINE CHOLESKYEND INTERFACE

! This is where CONTAINS would go if neededEND MODULE MYLAPACK

Introduction to Programming with Fortran 90 – p. 31/??

The Main ProgramPROGRAM MAIN

USE doubleUSE MYLAPACKREAL(KIND=dp), DIMENSION :: A(5,5) = 0.0, Z(5)DO N = 1,10

CALL RANDOM_NUMBER(Z)DO I = 1,5 ; A(:,I) = A(:,I)+Z*Z(I) ; END DO

END DOCALL CHOLESKY(A)DO I = 1,5 ; A(:I-1,I) = 0.0 ; END DOWRITE (*, ’(5(1X,5F10.6/))’) A

END PROGRAM MAIN

Introduction to Programming with Fortran 90 – p. 32/??

What Are Interfaces?

The FUNCTION or SUBROUTINE statementAnd everything directly connected to thatUSE double needed in argument declaration

Strictly, the argument names are not part of itYou are strongly advised to keep them the sameWhich keywords if the interface and code differ?

Actually, it’s the ones in the interface

Introduction to Programming with Fortran 90 – p. 33/??

Example

SUBROUTINE CHOLESKY(A) ! this is part of itUSE errors ! this ISN’T part of itUSE double ! this is, because of AIMPLICIT NONE ! this ISN’T part of itINTEGER :: J, N ! this ISN’T part of itREAL(KIND=dp) :: A(:, :), X ! A is but not X. . .

END SUBROUTINE CHOLESKY

Introduction to Programming with Fortran 90 – p. 34/??

Interfaces In Procedures

Can use an interface block as a declarationProvides an explicit interface for a procedure

Can be used for ordinary procedure callsBut using modules is almost always better

• It is essential for procedure argumentsCan’t put a dummy argument name in a module!

Introduction to Programming with Fortran 90 – p. 35/??

Example (1)

Assume this is in module application

FUNCTION apply (arr, func)REAL :: apply, arr(:)INTERFACE

FUNCTION func (val)REAL :: func, val

END FUNCTIONEND INTERFACEapply = 0.0DO I = 1,UBOUND(arr, 1)

apply = apply + func(val = arr(i))END DO

END FUNCTION apply

Introduction to Programming with Fortran 90 – p. 36/??

Example (2)

And these are in module functions

FUNCTION square (arg)REAL :: square, argsquare = arg**2

END FUNCTION square

FUNCTION cube (arg)REAL :: cube, argcube = arg**3

END FUNCTION cube

Introduction to Programming with Fortran 90 – p. 37/??

Example (3)

PROGRAM mainUSE applicationUSE functionsREAL, DIMENSION(5) :: A = (/ 1.0, 2.0, 3.0, 4.0, 5.0 /)PRINT *, apply(A,square)PRINT *, apply(A,cube)

END PROGRAM main

Will produce something like:

55.00000002.2500000E+02

Introduction to Programming with Fortran 90 – p. 38/??

Accessibility (1)

Can separate exported from hidden definitions

Fairly easy to use in simple cases• Worth considering when designing modules

PRIVATE names accessible only in moduleI.e. in module procedures after CONTAINS

PUBLIC names are accessible by USEThis is commonly called exporting them

Introduction to Programming with Fortran 90 – p. 39/??

Accessibility (2)

They are just another attribute of declarations

MODULE fredREAL, PRIVATE :: array(100)REAL, PUBLIC :: totalINTEGER, PRIVATE :: error_countCHARACTER(LEN=50), PUBLIC :: excuse

CONTAINS. . .

END MODULE fred

Introduction to Programming with Fortran 90 – p. 40/??

Accessibility (3)

PUBLIC/PRIVATE statement sets the defaultThe default default is PUBLIC

MODULE fredPRIVATEREAL :: array(100)REAL, PUBLIC :: total

CONTAINS. . .

END MODULE fred

Only TOTAL is accessible by USE

Introduction to Programming with Fortran 90 – p. 41/??

Accessibility (4)

You can specify names in the statementEspecially useful for included names

MODULE workspaceUSE doublePRIVATE :: DPREAL(KIND=DP), DIMENSION(1000) :: scratch

END MODULE workspace

DP is no longer exported via workspace

Introduction to Programming with Fortran 90 – p. 42/??

Partial Inclusion (1)

You can include only some names in USE

USE bigmodule, ONLY : errors, invert

Makes only errors and invert visibleHowever many names bigmodule exports

Using ONLY is good practiceMakes it easier to keep track of uses

Can find out what is used where with grep

Introduction to Programming with Fortran 90 – p. 43/??

Partial Inclusion (2)

• One case when it is strongly recommendedWhen using USE in modules

• All included names are exportedUnless you explicitly mark them PRIVATE

• Ideally, use both ONLY and PRIVATEAlmost always, use at least one of them

• Another case when it is almost essentialIs if you don’t use IMPLICIT NONE religiously

Introduction to Programming with Fortran 90 – p. 44/??

Partial Inclusion (3)

If you don’t restrict exporting and importing:

A typing error could trash a module variable

Or forget that you had already used the nameIn another file far, far away ...

• The resulting chaos is almost unfindableFrom bitter experience – in Fortran and C!

Introduction to Programming with Fortran 90 – p. 45/??

Example (1)

MODULE settingsINTEGER, PARAMETER :: DP = KIND(0.0D0)REAL(KIND=DP) :: Z = 1.0_DP

END MODULE settings

MODULE workspaceUSE settingsREAL(KIND=DP), DIMENSION(1000) :: scratch

END MODULE workspace

Introduction to Programming with Fortran 90 – p. 46/??

Example (2)

PROGRAM mainUSE workspaceZ = 1.23. . .

END PROGRAM main

• DP is inherited, which is OK

• Did you mean to update Z in settings?

No problem if workspace had used ONLY : DP

Introduction to Programming with Fortran 90 – p. 47/??

Example (3)

The following are better and best

MODULE workspaceUSE settings, ONLY : DPREAL(KIND=DP), DIMENSION(1000) :: scratch

END MODULE workspace

MODULE workspaceUSE settings, ONLY : DPPRIVATE :: DPREAL(KIND=DP), DIMENSION(1000) :: scratch

END MODULE workspace

Introduction to Programming with Fortran 90 – p. 48/??

Renaming Inclusion (1)

You can rename a name when you include it

WARNING: this is footgun territory[ i.e. point gun at foot; pull trigger ]

This technique is sometimes incredibly useful• But is always incredibly dangerous

Use it only when you really need toAnd even then as little as possible

Introduction to Programming with Fortran 90 – p. 49/??

Renaming Inclusion (2)

MODULE cornerREAL, DIMENSION(100) :: pooh

END MODULE corner

PROGRAM houseUSE corner, sanders => poohINTEGER, DIMENSION(20) :: pooh. . .

END PROGRAM house

pooh is accessible under the name sandersThe name pooh is the local array

Introduction to Programming with Fortran 90 – p. 50/??

Why Is This Lethal?

MODULE oneREAL :: X

END MODULE one

MODULE twoUSE one, Y => XREAL :: Z

END MODULE two

PROGRAM threeUSE one ; USE two! Both X and Y refer to the same variable

END PROGRAM three

Introduction to Programming with Fortran 90 – p. 51/??

Introduction to Programming withFortran 90Derived Types

Nick Maclaren

Computing Service

[email protected], ext. 34761

November 2007

Introduction to Programming with Fortran 90 – p. 1/??

Summary

There is one important new feature to cover

It is not complicated, as we shall do it• But we won’t cover it in great depth

Doing it fully would be a course in itselfThe same applies in other languages, too

Introduction to Programming with Fortran 90 – p. 2/??

What Are Derived Types?

As usual, a hybrid of two, unrelated conceptsC++, Python etc. are very similar

• One is structures – i.e. composite objectsArbitrary types, statically indexed by name

• The other is user-defined typesOften called semantic extensionThis is where object orientation comes in

• This course will describe only the former

Introduction to Programming with Fortran 90 – p. 3/??

Why Am I Wimping Out?

Fortran 2003 has really changed thisfull object orientationsemantic extensionpolymorphism (abstract types)and lots more

The course was already getting too bigAnd, yes, I was getting sick of writing it!

This area justifies a separate courseAbout one day or two afternoons, not three daysPlease ask if you would like it written

Introduction to Programming with Fortran 90 – p. 4/??

Simple Derived Types

TYPE WheelINTEGER :: spokesREAL :: diameter, widthCHARACTER(LEN=15) :: material

ENDTYPE Wheel

That defines a derived type WheelUsing derived types needs a special syntax

TYPE(Wheel) :: w1

Introduction to Programming with Fortran 90 – p. 5/??

More Complicated Ones

You can include almost anything in there

TYPE BicycleCHARACTER(LEN=80) :: description(100)TYPE(Wheel) :: front, backREAL, ALLOCATABLE, DIMENSION(:) :: timesINTEGER, DIMENSION(100) :: codes

ENDTYPE Bicycle

And so on ...

Introduction to Programming with Fortran 90 – p. 6/??

Fortran 95 Restrictions

Fortran 95 was much more restrictiveYou couldn’t have ALLOCATABLE arraysYou had to use pointers instead

Fortran 2003 removed that restrictionMost (all?) current compilers have been updated

PWF NAG still gives an obsolete warningIt’s nowhere near the current release

• So don’t feel constrained by that!

Introduction to Programming with Fortran 90 – p. 7/??

Component Selection

The selector ‘%’ is used for thisFollowed by a component of the derived type

It delivers whatever type that field isYou can then subscript or select it

TYPE(Bicycle) :: mine

mine%times(52:53) = (/ 123.4, 98.7 /)PRINT *, mine%front%spokes

Introduction to Programming with Fortran 90 – p. 8/??

Selecting from Arrays

You can select from arrays and array sectionsIt produces an array of that component alone

TYPE :: RabbitCHARACTER(LEN=16) :: varietyREAL :: weight, lengthINTEGER :: age

ENDTYPE RabbitTYPE(Rabbit), DIMENSION(100) :: exhibitsREAL, DIMENSION(50) :: fattest

fattest = exhibits(51:)%weight

Introduction to Programming with Fortran 90 – p. 9/??

Assignment (1)

You can assign complete derived typesThat copies the value element-by-element

TYPE(Bicycle) :: mine, yours

yours = minemine%front = yours%back

Assignment is the only intrinsic operation

You can redefine that or define other operationsBut they are some of the topics I am omitting

Introduction to Programming with Fortran 90 – p. 10/??

Assignment (2)

Each derived type is a separate typeYou cannot assign between different ones

TYPE FredREAL :: x

END TYPE FredTYPE Joe

REAL :: xEND TYPE JoeTYPE(Fred) :: aTYPE(Joe) :: ba = b ! This is erroneous

Introduction to Programming with Fortran 90 – p. 11/??

Constructors

A constructor creates a derived type value

TYPE CircleREAL :: X, Y, radiusLOGICAL :: filled

END TYPE Circle

TYPE(Circle) :: aa = Circle(1.23, 4.56, 2.0, .False.)

Fortran 2003 will allow keywords (components)

a = Circle(X = 1.23, Y = 4.56, radius = 2.0, filled = .False.)

Introduction to Programming with Fortran 90 – p. 12/??

Default Initialisation

You can specify default initial values

TYPE CircleREAL :: X = 0.0, Y = 0.0, radius = 1.0LOGICAL :: filled = .False.

END TYPE Circle

TYPE(Circle) :: a, b, ca = Circle(1.23, 4.56, 2.0, .True.)

This becomes much more useful in Fortran 2003

Introduction to Programming with Fortran 90 – p. 13/??

I/O on Derived Types

Can do normal I/O with the ultimate componentsA derived type is flattened much like an array

[ recursively, if it includes derived types ]

TYPE(Circle) :: a, b, ca = Circle(1.23, 4.56, 2.0, .True.)PRINT *, a ; PRINT *, b ; PRINT *, c

1.2300000 4.5599999 2.0000000 T0.0000000E+00 0.0000000E+00 1.0000000 F0.0000000E+00 0.0000000E+00 1.0000000 F

Introduction to Programming with Fortran 90 – p. 14/??

Private Derived Types

When you define them in modules

A derived type can be wholly privateI.e. accessible only to module procedures

Or its components can be hiddenI.e. it’s visible as an opaque type

Both useful, even without semantic extension

Introduction to Programming with Fortran 90 – p. 15/??

Wholly Private Types

MODULE MarsupialTYPE, PRIVATE :: Wombat

REAL :: weight, lengthENDTYPE WombatREAL, PRIVATE :: Koala

CONTAINS. . .

END MODULE Marsupial

Wombat is not exported from MarsupialNo more than the variable Koala is

Introduction to Programming with Fortran 90 – p. 16/??

Hidden Components (1)

MODULE MarsupialTYPE :: Wombat

PRIVATEREAL :: weight, length

ENDTYPE WombatCONTAINS

. . .END MODULE Marsupial

Wombat IS exported from MarsupialBut its components (weight, length) are not

Introduction to Programming with Fortran 90 – p. 17/??

Hidden Components (2)

Hidden components allow opaque typesThe module procedures use them normally

• Users of the module can’t look inside themThey can assign them like variablesThey can pass them as argumentsOr call the module procedures to work on them

An important software engineering techniqueUsually called data encapsulation

Introduction to Programming with Fortran 90 – p. 18/??

Introduction to Programming withFortran 90I/O and Files

Nick Maclaren

Computing Service

[email protected], ext. 34761

November 2007

Introduction to Programming with Fortran 90 – p. 1/??

I/O Generally

Most descriptions of I/O are only half-truthsThose work most of the time – until they blow upMost modern language standards are like that

Fortran is rather better, but there are downsidesComplexity and restrictions being two of them

• Fortran is much easier to use than it seems• This is about what you can rely on in practice

We will start with the basic principles

Introduction to Programming with Fortran 90 – p. 2/??

Some ‘Recent’ History

Fortran I/O (1950s) predates even mainframesOPEN and filenames was a CC† of c. 1975

Unix/C spread through CS depts 1975–1985ISO C’s I/O model was a CC† of 1985–1988Modern languages use the C/POSIX I/O modelEven Microsoft systems are like Unix here

• The I/O models have little in common

† CC = committee compromise

Introduction to Programming with Fortran 90 – p. 3/??

Important Warning

It is often better than C/C++ and often worseBut it is very different at all levels

• It is critical not to think in C-like termsTrivial C/C++ tasks may be infeasible in Fortran

As always, use the simplest code that worksFew people have much trouble if they do that

• Ask for help with any problems here

Introduction to Programming with Fortran 90 – p. 4/??

Fortran’s Sequential I/O Model

A Unix file is a sequence of characters (bytes)A Fortran file is a sequence of records (lines)

For simple, text use, these are almost equivalent

In both Fortran and C/Unix:• Keep text records short (say, < 250 chars)• Use only printing characters and space• Terminate all lines with a plain newline• Trailing spaces can appear and disappear

Introduction to Programming with Fortran 90 – p. 5/??

What We Have Used So Far

To remind you what you have been doing so far:

PRINT *, can be written WRITE (*,*)

READ *, can be written READ (*,*)

READ/WRITE (*,*) is shorthand forREAD/WRITE (UNIT=*, FMT=*)

READ *, ... and PRINT *, ... are legaciesTheir syntax is historical and exceptional

Introduction to Programming with Fortran 90 – p. 6/??

Record-based I/O

• Each READ and WRITE uses 1+ recordsAny unread characters are skipped for READWRITE ends by writing an end-of-line indicator

• Think in terms of units of whole linesA WRITE builds one or more whole linesA READ consumes one or more whole lines

Fortran 2003 relaxes this, to some extent

Introduction to Programming with Fortran 90 – p. 7/??

Fortran’s I/O Primitives

All Fortran I/O is done with special statementsAny I/O procedure is a compiler extension

Except as above, all of these have the syntax:<statement> (<control list>) <transfer list>

The <transfer list> is only for READ and WRITE

The <control list> items have the syntax:<specifier>=<value>

Introduction to Programming with Fortran 90 – p. 8/??

Specifier Values (1)

All specifier values can be expressionsIf they return values, they must be variables

• Except for * in UNIT=* or FMT=*

Even lunatic code like this is permitted

INTEGER, DIMENSION(20) :: NCHARACTER(LEN=50) :: C

WRITE (UNIT = (123*K)/56+2, FMT = C(3:7)//’)’, &IOSTAT=N(J**5-15))

Introduction to Programming with Fortran 90 – p. 9/??

Specifier Values (2)

The examples will usually use explicit constants

OPEN (23, FILE=’trace.out’, RECL=250)

• But you are advised to parameterise unitsAnd anything else that is system dependentOr you might need to change later

INTEGER, PARAMETER :: tracing = 23, tracelen = 250CHARACTER(LEN=*), PARAMETER :: &

tracefile = ’trace.out’

OPEN (tracing, FILE=tracefile, RECL=tracelen)

Introduction to Programming with Fortran 90 – p. 10/??

Basics of READ and WRITE

READ/WRITE (<control list>) <transfer list>

Control items have form <specifier> = <value>UNIT is the only compulsory control itemThe UNIT= can be omitted if the unit comes first

The unit is an integer identifying the connectionIt can be a variable or an expression

UNIT=* is an exceptional syntaxIt usually means stdin and stdout

Introduction to Programming with Fortran 90 – p. 11/??

Transfer Lists

A list is a comma-separated sequence of itemsThe list may be empty (READ and WRITE)

• A basic output item is an expression• A basic input item is a variable

Arrays and array expressions are allowed• They are expanded in array element order

Fancy expressions will often cause a copyArray sections should not cause a copy

Introduction to Programming with Fortran 90 – p. 12/??

Example

INTEGER :: N(3) = (/ 3, 1, 2 /)REAL :: X(3)READ *, X(N)PRINT *, X*1000.0

1.23 4.56 7.89

Produces a result like:

4.5600000E+03 7.8900000E+03 1.2300000E+03

Introduction to Programming with Fortran 90 – p. 13/??

Empty Transfer Lists

These are allowed, defined and meaningful

READ (*, *) skips the next line

WRITE (*, *) prints a blank line

WRITE (*, FORMAT) prints any text in FORMAT

That may print several lines

Introduction to Programming with Fortran 90 – p. 14/??

Implied DO-loops

There is an alternative to array expressionsEquivalent, but older and often more convenient

Items may be ( <list> , <indexed loop control> )This repeats in the loop order (just like DO)

( ( A(I,J) , J = 1,3 ) , B(I), I = 6,2,-2 )

A(6,1), A(6,2), A(6,3), B(6), A(4,1), A(4,2),A(4,3), B(4), A(2,1), A(2,2), A(2,3), B(2)

Introduction to Programming with Fortran 90 – p. 15/??

Programming Notes

You can do I/O of arrays in three ways:• You can write a DO-loop around the I/O• Array expressions for selecting and ordering• You can use implied DO-loops

Use whichever is most convenient and clearestThere are no problems with combining themMore examples of their use will be shown later

There isn’t a general ranking of efficiency

Introduction to Programming with Fortran 90 – p. 16/??

The UNIT Specifier

• A unit is an integer valueExcept for UNIT=*, described aboveIt identifies the connection to a file

• UNIT= can be omitted if the unit is first

A unit must be connected to a file before useGenerally use values in the range 10–99

• That’s all you need to know for now

Introduction to Programming with Fortran 90 – p. 17/??

The FMT Specifier

This sets the type of I/O and must match the file

• FMT= can be omitted if the format is secondand the first item is the unit

• FMT=* indicates list-directed I/O• FMT=<format> indicates formatted I/OThese can be interleaved on formatted files

• No FMT specifier indicates unformatted I/O

Introduction to Programming with Fortran 90 – p. 18/??

Example

These are formatted I/O statementsWRITE (UNIT = *, FMT = ’(2F5.2)’) cREAD (99, ’(F5.0)’) xWRITE (*, FMT = myformat) p, q, r

These are list-directed I/O statementsWRITE (UNIT = *, FMT = *) cREAD (99, *) x

These are unformatted I/O statementsWRITE (UNIT = 64) cREAD (99) x

Introduction to Programming with Fortran 90 – p. 19/??

List-Directed Output (1)

What you have been doing with ‘PRINT *,’

The transfer list is split into basic elementsEach element is then formatted appropriatelyIt is separated by spaces and/or a comma

• Except for adjacent CHARACTER itemsWrite spaces explicitly if you want them

The format and layout are compiler-dependent

Introduction to Programming with Fortran 90 – p. 20/??

Example

REAL :: z(3) = (/4.56, 4.56, 4.56/)CHARACTER(LEN=1) :: c = ’a’PRINT *, 1.23, ’Oh dear’, z, c, ’"’, c, ’ ’, c, c

Produces (under one compiler):

1.2300000 Oh dear 4.5599999 4.55999994.5599999 a"a aa

Introduction to Programming with Fortran 90 – p. 21/??

List-Directed Output (2)

You can cause character strings to be quotedVery useful if writing data for reinputUse the DELIM specifier in the OPEN

OPEN (1, FILE=’fred’, DELIM=’quote’)WRITE (11, *) ’Kilroy was here’

"Kilroy was here"

Also DELIM=’apostrophe’ and DELIM=’none’Fortran 2003 allows them in the WRITE, too

Introduction to Programming with Fortran 90 – p. 22/??

List-Directed Input (1)

What you have been doing with ‘READ *,’

This does the reverse of ‘PRINT *,’The closest Fortran comes to free-format input

• It automatically checks the data type

• OK for lists of numbers and similarNot much good for genuinely free-format

Introduction to Programming with Fortran 90 – p. 23/??

List-Directed Input (2)

Strings may be quoted, or notUsing either quote (") or apostrophe (’)

• Quote all strings containing the following:, / " ’ * space end-of-line

For the reasons why, read the specificationList-directed input is actually quite powerfulBut very unlike all other modern languages

Introduction to Programming with Fortran 90 – p. 24/??

Example

REAL :: a, b, cCHARACTER(LEN=8) :: p, qREAD *, a, p, b, q, cPRINT *, a, p, b, q, c

123e-2 abcdefghijkl -003 "P""Q’R" 4.56

Produces (under one compiler):

1.2300000 abcdefgh -3.0000000 P"Q’R4.5599999

Introduction to Programming with Fortran 90 – p. 25/??

Free-Format

Free-format I/O is not traditional in Fortran

Formatted output is far more flexibleFortran 2003 adds some free-format support

Free-format input can be very tricky in FortranBut it isn’t hard to read lists of numbers

There is some more on this in extra slides

Introduction to Programming with Fortran 90 – p. 26/??

Unformatted I/O is Simple

Very few users have any trouble with it

• It is NOT like C binary I/O

• It is unlike anything in C

Most problems come from “thinking in C”

Introduction to Programming with Fortran 90 – p. 27/??

Unformatted I/O (1)

• It is what you use for saving data in filesE.g. writing your own checkpoint/restartOr transferring bulk data between programs

• No formatting/decoding makes it a lot faster100+ times less CPU time has been observed

• Assume same hardware and same systemIf not, see other courses and ask for help

Introduction to Programming with Fortran 90 – p. 28/??

Unformatted I/O (2)

Just reads and writes data as stored in memory• You must read back into the same types

• Each transfer uses exactly one recordWith extra control data for record boundariesYou don’t need to know what it looks like

• Specify FORM=’unformatted’ in OPENstdin, stdout and terminals are not suitable

That’s ALL that you absolutely need to know!

Introduction to Programming with Fortran 90 – p. 29/??

ExampleINTEGER, DIMENSION(1000) :: indexREAL, DIMENSION(1000000) :: array

OPEN (1, FILE=’fred’, FORM=’unformatted’)

DO k = 1,...WRITE (1) k, m, n, index(:m), array(:n)

ENDDO

In another run of the program, or after rewinding:

DO k = 1,...READ (1) k, m, n, index(:m), array(:n)

ENDDO

Introduction to Programming with Fortran 90 – p. 30/??

Programming Notes

• Make each record (i.e. transfer) quite largeBut don’t go over 2 GB per record

• I/O with whole arrays is generally fastestINTEGER :: N(1000000)READ (9) N

Array sections should be comparably fast• Remember about checking for copying

• Implied DO-loops should be avoidedAt least for large loop counts

Introduction to Programming with Fortran 90 – p. 31/??

Formatted I/O

READ or WRITE with an explicit formatA format is just a character stringIt can be specified in any one of three ways:

• A CHARACTER expression

• A CHARACTER arrayConcatenated in array element order

• The label of a FORMAT statementOld-fashioned, and best avoided

Introduction to Programming with Fortran 90 – p. 32/??

Formats (1)

A format is items inside parenthesesBlanks are ignored, except in strings

‘ ( i3,f 5 . 2) ’ ≡ ‘(i3,f5.2)’

We will see why this is so useful later

Almost any item may have a repeat count

‘(3 i3, 2 f5.2)’ ≡ ‘(i3, i3, i3, f5.2, f5.2)’

Introduction to Programming with Fortran 90 – p. 33/??

Formats (2)

A group of items is itself an itemGroups are enclosed in parentheses

E.g. ‘( 3 (2 i3, f5.2 ) )’ expands into:‘(i3, i3, f5.2, i3, i3, f5.2, i3, i3, f5.2)’

Often used with arrays and implied DO-loops

Nesting them deeply can be confusing

Introduction to Programming with Fortran 90 – p. 34/??

Example

REAL, DIMENSION(2, 3) :: coordsINTEGER, DIMENSION(3) :: index

WRITE (29, ’( 3 ( i3, 2 f5.2 ) )}’) &( index(i), coords(:, i), i = 1,3)

This is how to use a CHARACTER constant:

CHARACTER(LEN=*), PARAMETER :: &format = ’( 3 ( i3, 2 f5.2 ) )’

WRITE (29, format) ( index(i), coords(:, i), i = 1,3)

Introduction to Programming with Fortran 90 – p. 35/??

Transfer Lists And Formats

Logically, both are expanded into flat listsI.e. sequences of basic items and descriptors

The transfer list is the primary oneBasic items are taken from it one by oneEach then matches the next edit descriptor

The item and descriptor must be compatibleE.g. REAL vars must match REAL descs

Introduction to Programming with Fortran 90 – p. 36/??

Input Versus Output

We shall mainly describe formatted outputThis is rather simpler and more general

Unless mentioned, all descriptions apply to inputIt’s actually much easier to use than outputBut it is rather oriented to form-filling

More on flexible and free-format input later

Introduction to Programming with Fortran 90 – p. 37/??

Integer Descriptors

In (i.e. letter i) displays in decimalRight-justified in a field of width nIn.m displays at least m digits

WRITE (*, ’( I7 )’) 123 ⇒ ‘ 123’WRITE (*, ’( I7.5 )’) 123 ⇒ ‘ 00123’

You can replace the I by B, O and ZFor binary, octal and hexadecimal

Introduction to Programming with Fortran 90 – p. 38/??

Example

WRITE (*, ’( I7, I7 )’) 123, -123WRITE (*, ’( I7.5, I7.5 )’) 123, -123

123 -12300123 -00123

WRITE (*, ’( B10, B15.10 )’) 123, 123WRITE (*, ’( O7, O7.5 )’) 123, 123WRITE (*, ’( Z7, Z7.5 )’) 123, 123

1111011 0001111011173 001737B 0007B

Introduction to Programming with Fortran 90 – p. 39/??

Values Too Large

This is field overflow on outputThe whole field is replaced by asterisks

Putting 1234 into i4 gives 1234Putting 12345 into i4 gives ****Putting -123 into i4 gives –123Putting -1234 into i4 gives ****

This applies to all numeric descriptorsBoth REAL and INTEGER

Introduction to Programming with Fortran 90 – p. 40/??

Fixed-Format REAL

Fn.m displays to m decimal placesRight-justified in a field of width n

WRITE (*, ’( F9.3 )’) 1.23 ⇒ ‘ 1.230’WRITE (*, ’( F9.5 )’) 0.123e-4 ⇒ ‘ 0.00001’

You may assume correct roundingNot required, but traditional in Fortran• Compilers may round exact halves differently

Introduction to Programming with Fortran 90 – p. 41/??

Widths of Zero

For output a width of zero may be usedBut only for formats I, B, O, Z and FIt prints the value without any leading spaces

write (*, ’("/",i0,"/",f0.3)’) 12345, 987.654321

Prints

/12345/987.65

Introduction to Programming with Fortran 90 – p. 42/??

Exponential Format (1)

There are four descriptors: E, ES, EN and DWith the forms En.m, ESn.m, ENn.m and Dn.m

All of them use m digits after the decimal pointRight-justified in a field of width n

D is historical – you should avoid itLargely equivalent to E, but displays D

For now, just use ESn.m – more on this later

Introduction to Programming with Fortran 90 – p. 43/??

Exponential Format (2)

The details are complicated and messyYou don’t usually need to know them in detailHere are the two basic rules for safety

• In ESn.m, make n ≥ m+7That’s a good rule for other languages, too

• Very large or small exponents display oddlyI.e. exponents outside the range –99 to +99Reread using Fortran formatted input only

Introduction to Programming with Fortran 90 – p. 44/??

Numeric Input

F, E, ES, EN and D are similar

• You should use only Fn.0 (e.g. F8.0)For extremely complicated reasons

• Any reasonable format is accepted

There are more details given later

Introduction to Programming with Fortran 90 – p. 45/??

CHARACTER Descriptor

An displays in a field with width nPlain A uses the width of the CHARACTER item

On output, if the field is too small:The leftmost characters are used

Otherwise:The text is right-justified

On input, if the variable is too small:The rightmost characters are used

Otherwise:The text is left-justified

Introduction to Programming with Fortran 90 – p. 46/??

Output Example

WRITE (*,’(a3)’) ’a’WRITE (*,’(a3)’) ’abcdefgh’

Will display:

aabc

Introduction to Programming with Fortran 90 – p. 47/??

Input Example

CHARACTER(LEN=3) :: a

READ (b,’(a8)’) a ; WRITE (*,’(a)’) aREAD (c,’(a1)’) a ; WRITE (*,’(a)’) a

With input:abcdefgha

Will display:fgha

Introduction to Programming with Fortran 90 – p. 48/??

LOGICAL Descriptor

Ln displays either T or FRight-justified in a field of width n

On input, the following is doneAny leading spaces are ignoredAn optional decimal point is ignoredThe next char. must be T (or t) or F (or f)Any remaining characters are ignored

E.g. ‘.true.’ and ‘.false.’ are acceptable

Introduction to Programming with Fortran 90 – p. 49/??

The G Descriptor

The G stands for generalizedIt has the forms Gn.m [or Gn.mEk]It behaves according to the item type

INTEGER behaves like InCHARACTER behaves like AnLOGICAL behaves like LnREAL behaves like Fn.m, En.m [or En.mEk]

depending on the size of the value

The rules for REAL are fairly sensible

Introduction to Programming with Fortran 90 – p. 50/??

Other Types of Descriptor

All of the above are data edit descriptorsEach of them matches an item in the transfer listAs mentioned, they must match its type

There are some other types of descriptorThese do not match a transfer list itemThey are executed, and the next item is matched

Introduction to Programming with Fortran 90 – p. 51/??

Text Literal Descriptor

A string literal stands for itself, as textIt is displayed just as it is, for outputIt is not allowed in a FORMAT for input

Using both quotes and apostrophes helpsThe following are all equivalent

WRITE (29, ’( "Hello" )’)WRITE (29, "( ’Hello’ )")WRITE (29, ’( ’ ’Hello’ ’ )’)WRITE (29, "( ""Hello"" )")

Introduction to Programming with Fortran 90 – p. 52/??

Spacing Descriptor

X displays a single blank (i.e. a space)It has no width, but may be repeated

On input, it skips over exactly one character

READ (*, ’(i1, 3x, i1)’) m, nWRITE (*, ’(i1, x, i1, 4x, a)’) m, n, ’!’

7 9

Produces ‘7 9 !’

Introduction to Programming with Fortran 90 – p. 53/??

Newline Descriptor (1)

/ displays a single newline (in effect)It has no width, but may be repeated

It can be used as a separator (like a comma)Only if it has no repeat count, of course

WRITE (*, ’(i1/i1, 2/, a)’) 7, 9, ’!’

79

!

Introduction to Programming with Fortran 90 – p. 54/??

Newline Descriptor (2)

On input, it skips the rest of the current line

READ (*, ’(i1/i1, 2/, i1)’) l, m, nWRITE (*, ’(i1, 1x, i1, 1x, i1)’) l, m, n

1 1 1 12 2 2 23 3 3 34 4 4 4

Produces “1 2 4”

Introduction to Programming with Fortran 90 – p. 55/??

Item-Free FORMATs

You can print multi-line text on its own

WRITE (*, ’("Hello" / "Goodbye")’)

HelloGoodbye

And skip as many lines as you like

READ (*, ’(////)’)

Introduction to Programming with Fortran 90 – p. 56/??

Generalising That

That is a special case of a general ruleFORMATs are interpreted as far as possible

WRITE (*, ’(I5, " cubits", F5.2)’) 123

123 cubits

This reads 42 and skips the following three lines

READ (*, ’(I3///)’) n

42

Introduction to Programming with Fortran 90 – p. 57/??

Complex Numbers

For list-directed I/O, these are basic typesE.g. read and displayed like “(1.23,4.56)”

For formatted and unformatted I/OCOMPLEX numbers are treated as two REALsLike an extra dimension of extent two

COMPLEX :: c = (1.23, 4.56)WRITE (*, ’(2F5.2)’) c

1.23 4.56

Introduction to Programming with Fortran 90 – p. 58/??

Exceptions and IOSTAT (1)

By default, I/O exceptions halt the programThese include an unexpected end-of-file

You trap by providing the IOSTAT specifier

INTEGER :: ioerr

OPEN (1, FILE=’fred’, IOSTAT=ioerr)

WRITE (1, IOSTAT=ioerr) array

CLOSE (1, IOSTAT=ioerr)

Introduction to Programming with Fortran 90 – p. 59/??

Error Handling and IOSTAT (2)

IOSTAT specifies an integer variable

Zero means success, or no detected error

Positive means some sort of I/O errorAn implementation should describe the codes

Negative means end-of-file (but see later)In Fortran 2003, this value is IOSTAT_EOF

Introduction to Programming with Fortran 90 – p. 60/??

What Is Trapped? (1)

The following are NOT errorsFortran defines all of this behaviour

• Formatted READ beyond end-of-recordPadded with spaces to match the format

Fortran 2003 allows a little control of that

• Writing a value too large for a numeric fieldIt is filled with asterisks (*****)

Introduction to Programming with Fortran 90 – p. 61/??

What Is Trapped? (2)

The following are NOT errors

• Writing too long a CHARACTER stringThe leftmost characters are used

• Reading too much CHARACTER dataThe rightmost characters are used

Introduction to Programming with Fortran 90 – p. 62/??

What Is Trapped? (3)

The following is what you can usually rely on

• End-of-file

• Unformatted READ beyond end-of-recordIOSTAT may be positive OR negative

• Most format errors (syntactically bad values)E.g. 12t8 being read as an integer

That is roughly the same as C and C++

Introduction to Programming with Fortran 90 – p. 63/??

What Is Trapped? (4)

The following are sometimes trappedThe same applies to most other languages

• Numeric overflow (integer or floating-point)Floating-point overflow may just deliver infinityInteger overflow may wrap modulo 2

N

Or there may be even less helpful effects

• ‘Real’ (hardware or system) I/O errorsE.g. no space on writing, file server crashingAnything may happen, and chaos is normal

Introduction to Programming with Fortran 90 – p. 64/??

OPEN

Files are connected to units using OPEN

OPEN (UNIT=11, FILE=’fred’, IOSTAT=ioerr)

That will open a sequential, formatted fileYou can then use it for either input or output

You can do better, using optional specifiersOther types of file always need one or more

Introduction to Programming with Fortran 90 – p. 65/??

Choice of Unit Number

Unit numbers are non-negative integer valuesThe valid range is system-dependentYou can usually assume that 1–99 are safe

Some may be in use (e.g. for stdin and stdout)They are often (not always) 5 and 6

It is best to use unit numbers 10–99Most codes just do that, and have little trouble

Introduction to Programming with Fortran 90 – p. 66/??

ACCESS and FORM Specifiers

These specify the type of I/O and file

‘sequential’ (default) or ‘direct’‘formatted’ (default) or ‘unformatted’

OPEN (UNIT=11, FILE=’fred’, ACCESS=’direct’, &FORM=’unformatted’, IOSTAT=ioerr)

That will open a direct-access, unformatted fileYou can then use it for either input or output

Introduction to Programming with Fortran 90 – p. 67/??

Scratch Files

OPEN (UNIT=11, STATUS=’scratch’, &FORM=’unformatted’, IOSTAT=ioerr)

That will open a scratch (temporary) fileIt will be deleted when it is closed

It will be sequential and unformattedThat is the most common type of scratch fileBut all other types and specifiers are allowed

• Except for the FILE specifier

Introduction to Programming with Fortran 90 – p. 68/??

The ACTION Specifier

• This isn’t needed, but is strongly advisedIt helps to protect against mistakesIt enables the reading of read-only files

OPEN (UNIT=11, FILE=’fred’, ACTION=’read’, &IOSTAT=ioerr)

Also ‘write’, useful for pure output files

The default, ‘readwrite’, allows both

Introduction to Programming with Fortran 90 – p. 69/??

Example (1)

Opening a text file for reading data from

OPEN (UNIT=11, FILE=’fred’, ACTION=’read’, &IOSTAT=ioerr)

Opening a text file for writing data or results to

OPEN (UNIT=22, FILE=’fred’, ACTION=’write’, &IOSTAT=ioerr)

OPEN (UNIT=33, FILE=’fred’, ACTION=’write’, &RECL=80, DELIM=’quote’, IOSTAT=ioerr)

Introduction to Programming with Fortran 90 – p. 70/??

Example (2)

Opening an unformatted file for reading from

OPEN (UNIT=11, FILE=’fred’, ACTION=’read’, &FORM=’unformatted’, IOSTAT=ioerr)

Opening an unformatted file for writing to

OPEN (UNIT=22, FILE=’fred’, ACTION=’write’, &FORM=’unformatted’, IOSTAT=ioerr)

Introduction to Programming with Fortran 90 – p. 71/??

Example (3)

Opening an unformatted workspace fileIt is your choice whether it is temporary

OPEN (UNIT=22, STATUS=’scratch’, &FORM=’unformatted’, IOSTAT=ioerr)

OPEN (UNIT=11, FILE=’fred’, &FORM=’unformatted’, IOSTAT=ioerr)

See extra slides for direct-access examples

Introduction to Programming with Fortran 90 – p. 72/??

Omitted For Sanity

These are in the extra slides

Techniques for reading free-format dataSome more detail on formatted I/OInternal files and dynamic formatsMore on OPEN, CLOSE, positioning etc.Direct-access I/O

There are extra, extra slides on some details

Introduction to Programming with Fortran 90 – p. 73/??

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/practical_01.txt

Introduction to Programming with Fortran----------------------------------------

Practical Exercise 1 (Compilation and Editing)----------------------------------------------

Question 1----------

The following program reads in a number and prints its inverse:

PROGRAM INVERT IMPLICIT NONE REAL :: Value, Inverse PRINT *, "Type in a value to invert" READ *, Value Inverse = 1.0/Value PRINT *, "Value", Value, " Inverse", Inverse END PROGRAM INVERT

1.1 Using an editor, type the above program into a file called somethinglike `invert.f90'.

1.2 Compile and run the program. Verify the correctness of the code bysupplying the following test data (each value needs a separate run):

1.0 3.0 -20.0 1000.0 1.0e-30

1.3 Save a copy of this program in another file (say `invert.safe').

1.4 See what happens when you supply the following data (each valueneeds a separate run):

0.0 1.0e-38 1.0e-40 weeble

1.5 Edit the file, change the occurrence of `Value' to `Vole' in the

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/practical_01.txt (1 of 2)9/19/2009 4:21:48 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/practical_01.txt

`READ' statement, and see what happens when you compile it.

1.6 Restore the file from the safe copy, change the `READ' to `RODE',and see what happens when you compile it.

1.7 Restore the file from the safe copy, change the first `INVERT' to`invert', the first `Value' to `valUE', and the `Type' to `TYPE'. Nowsee what happens when you compile and run it with the input `1.0'.

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/practical_01.txt (2 of 2)9/19/2009 4:21:48 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/practical_02.txt

Introduction to Programming with Fortran----------------------------------------

Practical Exercise 2--------------------

Question 1----------

Are the following statements true or false?

1.1 All Fortran 90 statements start in column 7.1.2 % (percent sign) has no special meaning in Fortran.1.3 In free source form spaces are allowed anywhere.1.4 Colons must be used to separate keywords from names.1.5 A line in Fortran can be any length.1.6 Only one Fortran statement can appear on a line.

1.7 Which of the following are valid Fortran names:

v1, V1, 1v, 1V, v_1, _v1, v%1

Question 2----------

When IMPLICIT NONE is used at the start of a program all variable namesbeginning with I, J, K, L, M, N are assumed to be INTEGER. Is this trueor false?

Question 3----------

The following program has been badly laid out. Reformat it so it isneat and readable but performs exactly the same function,

PROGRAM MAIN;INTEGER::degreesfahrenheit& ,degreescentigrade;READ*,& degreesfahrenheit;degreescentigrade& =5*(degreesfahrenheit-32)/9;PRINT*,&

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/practical_02.txt (1 of 2)9/19/2009 4:21:48 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/practical_02.txt

degreesCENtiGrAde;END

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/practical_02.txt (2 of 2)9/19/2009 4:21:48 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/practical_03.txt

Introduction to Programming with Fortran----------------------------------------

Practical Exercise 3--------------------

Question 1----------

1.1 Evaluate the following when A = 6, B = 2 and C = 3. A, B and C areall integer variables.

A/B*C A*B/C 3*A**B B+A/C A/B+C

1.2 Evaluate the above expressions when A = 3, B = 5 and C = 4.

1.3 Write a program to check that your Fortran compiler gives theresults you have given.

Question 2----------

2.1 What value does the real variable A take in the following statementswhen I = 5 and J = 4 (I and J are INTEGER)?

A = I*J A = I/J A = J/I

2.2 What value does the INTEGER I take in the following statements whenA = 5.0, B = 4.0 (A and B are REAL)?

I = A*B

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/practical_03.txt (1 of 4)9/19/2009 4:21:48 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/practical_03.txt

I = A/B I = B/A

Question 3----------

On a particular computer the range for reals is 10-38 to 10+38.

3.1 What value does the expression (A/B) have when A = 1.0, B = 0.0?3.2 What value does the expression (5.3E+25 * 6.4E+28) have?3.3 What value does the expression (5.3E-50 * 6.4E-35) have?

Question 4----------

Why are named constants useful?

Question 5----------

What is the difference between

REAL, PARAMETER :: pi = 22.0/3.0and

REAL :: pi = 22.0/3.0

Question 6----------

Is the following program fragment allowed?

INTEGER, PARAMETER :: ZERO = 0 ZERO = 1

Question 7----------

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/practical_03.txt (2 of 4)9/19/2009 4:21:48 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/practical_03.txt

Is the following program fragment allowed?

INTEGER :: ONE = 1 ONE = 0

Question 8----------

Which of the following are incorrect declarations and why? If you thinka declaration may be correct in a given situation then say what thesituation would be.

8.1 ReAl :: x8.2 CHARACTER :: name8.3 CHARACTER(LEN=10) :: name8.4 REAL :: var-18.5 INTEGER :: 1a8.6 INTEGRAL :: loji8.7 CHARACTER(LEN=5) :: town = "Glasgow"8.8 CHARACTER(LEN=*), PARAMETER :: city = "Glasgow"8.9 INTEGER :: pi = +22/78.10 CHARACTER(LEN=*), PARAMETER :: "Bognor"8.11 REAL, PARAMETER :: pye = 22.0/7.08.12 REAL, PARAMETER :: two_pie = pye*28.13 REAL :: a = 1., b = 28.14 CHARACTER(LEN=6) :: you_know = 'y'know"8.15 CHARACTER(LEN=6) :: you_know = "y'know"8.16 INTEGER :: ia ib ic id 8.17 REAL :: poie = 4.*atan(1.)

Question 9----------

Declare the following objects:

9.1 feet an integer variable9.2 miles a real variable9.3 Town a character variable of up to 20 letters9.4 home_town a constant with value to LIVERPOOL9.5 sin_half a constant with value sin(0.5) = 0.47942554

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/practical_03.txt (3 of 4)9/19/2009 4:21:48 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/practical_03.txt

Question 10-----------

Add parentheses to the following expression to indicate the order ofevaluation.

-a*b-c/d**e/f+g**h+1-j/k

Question 11-----------

11.1 Write a program that reads in a person's name and date of birth (inthe form `dd.mm.yy') and prints out a sentence such as:

dd.mm.yy is the birthday of Joe Bloggs

11.2 Modify the program to print the sentence in the form:

Joe Bloggs was born on dd.mm.yy

Question 12-----------

Write a simple program to read in a radius and calculate the area of thecorresponding circle and volume of the corresponding sphere.Demonstrate its correctness by calculating the area and volume usingradii of 2, 5, 10 and -1.

The area of a circle is pi times the radius squared, and pi may be takenas 3.14159. The volume of a sphere is 4/3 pi times the radius cubed.

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/practical_03.txt (4 of 4)9/19/2009 4:21:48 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/practical_04.txt

Introduction to Programming with Fortran----------------------------------------

Practical Exercise 4--------------------

Question 1----------

How many times are the loops, defined by the following statements,executed:

DO I = 2, N/2, 3 DO I = 1, N, 4 DO I= 3, N**2, 5

when N is

1.1 21.2 15

Question 2----------

Write a program to read in a vector defined by a length and an angle indegrees, which prints out the corresponding Cartesian (x, y)co-ordinates. Recall that arguments to trigonometric functions are inradians.

Demonstrate correctness by giving the Cartesian co-ordinates for thefollowing vectors:

length angle2.1 12 772.2 1000 02.3 1000 902.4 20 1002.5 12 437

Question 3

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/practical_04.txt (1 of 3)9/19/2009 4:21:48 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/practical_04.txt

----------

Write a Fortran program to count how many of a set of ten integerstyped in at the keyboard are multiples of five. Ignore any negativenumbers. Each number is input on a separate line.

Question 4----------

Write a program to accept three integer lengths and report back onwhether these lengths could define an equilateral, isoceles or scalenetriangle (3, 2 or 0 equal length sides), or whether they cannot form atriangle.

Demonstrate that the program works by classifying the following:

4.1 1 1 14.2 2 2 14.3 1 1 04.4 3 4 54.5 3 2 14.6 1 2 4

Hint: if three lengths form a triangle then 2 times the longest sidemust be less than the sum of all three sides. In Fortran 90 terms, thefollowing must be true:

2*MAX(sidel,side2,side3) < sidel+side2+side3

Question 5----------

If you take a positive integer, halve it if it is even or triple it andadd one if it is odd, and repeat, then the number will eventually becomeone. Warning: it may take a long time!

Set up a loop containing a statement to read in a number (inputterminated by zero) and to print out the sequence obtained from eachinput. The number 13 is considered to be very unlucky and if it isobtained as part of the sequence then execution should immediatelyterminate with an appropriate message.

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/practical_04.txt (2 of 3)9/19/2009 4:21:48 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/practical_04.txt

Demonstrate that your program works by outputting the sequencesgenerated by the following two sets of numbers (each number goes ona separate line):

5.1 7 0

5.2 106 46 3 0

Question 6----------

Write a program that will read a sequence of colours input as names,'red', 'green', 'blue', 'yellow', 'black', 'white' or something else.Stop the program if a colour 'blank' is read. Count the number ofoccurrences of each colour, including the unspecified colours and printout the totals for each colour before terminating the program.

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/practical_04.txt (3 of 3)9/19/2009 4:21:48 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/practical_05.txt

Introduction to Programming with Fortran----------------------------------------

Practical Exercise 5--------------------

Question 1: Rank, Extents etc.------------------------------

Give the rank, bounds, size and shape of the arrays defined as follows:

1.1 REAL, DIMENSION(10) :: ONE1.2 REAL, DIMENSION(2, 0:2) :: TWO1.3 INTEGER, DIMENSION(-1:1, 3 , 2) :: THREE1.4 REAL, DIMENSION(0:1, 3) :: FOUR

Question 2: Conformance-----------------------

Given:

2.1 REAL, DIMENSION(1:10) :: ONE2.2 REAL, DIMENSION(2, O:2) :: TWO2.3 INTEGER, DIMENSION(-1:1, 3, 2) :: THREE2.4 REAL, DIMENSION(0:1, 3) :: FOUR

Which two of the arrays are conformable?

Question 3: Hotel Array-----------------------

3.1 Declare an array of rank 3 which might be suitable for representinga hotel with 8 floors and 16 rooms on each floor and 2 beds in eachroom.

3.2 How would the 2nd bed in the 5th room on floor 7 be referenced?

Question 4: Array References----------------------------

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/practical_05.txt (1 of 4)9/19/2009 4:21:48 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/practical_05.txt

Given:

INTEGER :: i = 3, j = 7 REAL, DIMENSION(1:20) :: A

which of the following are valid array references for the array:

4.1 A(12)4.2 A(21)4.3 A(I*J-1)4.4 A(3.0)4.5 A(I*J) 4.6 A(1+INT(4.0*ATAN(1.0))) [ Hint: 4.0*ATAN(1.0) is pi ]

Question 5: Array Element Ordering----------------------------------

Given:

REAL, DIMENSION(1:10) :: ONE REAL, DIMENSION(2, 0:2) :: TWO INTEGER, DIMENSION(-1:1, 3, 2) :: THREE REAL, DIMENSION(0:1, 3) :: FOUR

write down the array element order of each array.

Question 6: Array Sections--------------------------

Declare an array which would be suitable for representing draughtsboard. Write two assignments to set all the white squares to zero andthe black squares to unity. [ A draughts board is 8 x 8 with alternateblack and white squares, in both directions. ]

Question 7: Array Constructor-----------------------------

Write an array constructor for the rank one 5 element array BOXES

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/practical_05.txt (2 of 4)9/19/2009 4:21:48 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/practical_05.txt

containing the values 1, 4, 6, 12, 23.

Question 8: MATMUL Intrinsic----------------------------

For the declarations:

REAL, DIMENSION(100, 100) :: A, B, C REAL, DIMENSION(100, 500) :: P, Q, R REAL, DIMENSION(500, 100) :: T

8.1 What is the difference between C = MATMUL(A,B) and C = A*B?

8.2 Which of the following are correct?

8.2.1 A = MATMUL(P,T)8.2.2 P = MATMUL(Q,R)8.2.3 A = P*T8.2.4 P = Q*R8.2.5 T = MATMUL(T,A)

Question 9: MATMUL By Hand--------------------------

In this question, you may assume that there are no errors and omit allchecking. That is not good practice, but considerably simplifies thecoding. You should not assume the matrices are square.

The harness for a sort of MATMUL could be:

SUBROUTINE MyMatmul (result, left, right) IMPLICIT NONE REAL, DIMENSION :: result, left, right . . . END SUBROUTINE MyMatmul

9.1 Replace the ". . ." by the statements needed to calculate the matrix(not elementwise) product `result = left*right' using basic scalaroperations only.

9.2 Replace the ". . ." by the statements needed to calculate the matrix

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/practical_05.txt (3 of 4)9/19/2009 4:21:48 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/practical_05.txt

(not elementwise) product result = left*right using the SUM intrinsic.

Question 10: ALLOCATABLE Arrays-------------------------------

10.1 You have a subroutine like the following:

SUBROUTINE OPERATE (ARG) IMPLICIT NONE REAL :: ARG(:, :) . . . END SUBROUTINE OPERATE

Replace the ". . ." by the statements needed to allocate an arraywith the same shape as ARG. Do this using automatic arrays, notusing ALLOCATE.

10.2 Repeat 10.1 but use ALLOCATE, not automatic arrays.

Question 11: Actual Coding--------------------------

You have a subroutine like the following:

SUBROUTINE OPERATE (ARG, N, ICODE) IMPLICIT NONE REAL :: ARG(:, :) INTEGER :: N, ICODE . . . END SUBROUTINE OPERATE

Replace the ". . ." by the statements needed to do all of thefollowing: check that N is positive or zero check that the matrix has at least one element check that the matrix is square allocate an array with the same shape as ARG using ALLOCATE replace ARG by ARG**N, but using matrix multiplication (i.e. MATMUL)and not element-wise multiplication

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/practical_05.txt (4 of 4)9/19/2009 4:21:48 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/practical_06.txt

Introduction to Programming with Fortran----------------------------------------

Practical Exercise 6--------------------

Question 1: Simple Example of Subroutine----------------------------------------

1.1 Write a main program and internal subroutine that takes three REALarguments and returns, as its first argument, the third argumentsubtracted from the second. Keep the code as simple as possible. Testthis by including calls to add the following pairs of numbers:

1.23 4.56 -7.89 3.42 4.29 -0.98

1.2 Add INTENT to the above code and check that it works.

1.3 Change the call to using keywords and change the order of thearguments; check that this does not change the results. Save thiscode in a file.

Question 2: Simple example of a Function----------------------------------------

2.1 Write a main program and an internal function that takes two REALarguments and returns the second argument subtracted from the first.Keep the code as simple as possible. Test this by including calls to addthe following pairs of numbers:

1.23 4.56 -7.89 3.42 4.29 -0.98

2.2 Add INTENT and ELEMENTAL to the above code and check that it works.

2.3 Change the call to using keywords and reverse the order of thearguments; check that this does not change the results.

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/practical_06.txt (1 of 4)9/19/2009 4:21:48 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/practical_06.txt

Question 3: Random Number Generation------------------------------------

3.1 Write a module containing function which simulates a throw of twodice and returns the total score, and compile it. The following codefragment will set Z to a pseudo-random number uniformly distributedbetween 0 and 1:

REAL :: Z CALL RANDOM_NUMBER(Z)

3.2 Write a main program that uses that module, and prints out theresult of the throw of two dice 10 times. Compile and run it.

Question 4: Arrays------------------

4.1 Write a program with an internal subroutine that takes two assumedshape 2-dimensional REAL array arguments, with INTENT(OUT) andINTENT(IN), checks that their shapes are compatible, and allocates two1-dimensional REAL arrays the same size as the first and seconddimensions.

4.2 Add the code to set the two automatic arrays to the row and columnaverages, and shift the rows and columns so that all row and columntotals are zero. To do this, set the first argument to the value of thesecond with the relevant row and column averages subtracted from it andthe overall average added to it. Test this by providing it with thematrix:

2.35 2.82 4.55 7.83 3.97 6.75 7.62 8.36 8.97 0.74 2.70 2.49

Question 5: CHARACTER Arguments-------------------------------

Write a program with an internal subroutine that takes one INTEGER andthree assumed size CHARACTER arguments, prints out each of the CHARACTER

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/practical_06.txt (2 of 4)9/19/2009 4:21:48 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/practical_06.txt

ones on a separate line, and sets the integer argument to the sum oftheir lengths. Use the following data to test it:

'Kilroy' 'was' 'here'

Question 6: CHARACTER Functions-------------------------------

Write a program with an internal function that takes one assumed sizeCHARACTER argument, and returns the value argument with leading andtrailing spaces removed and padded to the same length as its argumentwith '.'s. Test this with the following strings:

'How, now, brown cow?' ' Spaced out ' [ 3 leading and 5 trailing spaces ]

Question 7: Save Attribute--------------------------

Write a subroutine with one INTEGER argument that returns 7 the firsttime it is called, 8 the next time, 9 the next time, and so on. Declarethe argument INTENT(OUT). Test it however you prefer.

Question 8: Newton-Raphson--------------------------

8.1 Write a module containing a subroutine and two functions; you canput both of them after the module's CONTAINS at the same level (i.e. thefunctions need not be internal procedures of the subroutine).

The subroutine should accept a value of X*LOG(X) greater than 1.0 andprint the corresponding value of X, by calling the functions and usingNewton-Raphson iteration.

The first function should return the value of X*LOG(X), where x is itsargument.

The second function should return the value of LOG(X)+1.0, where x is itsargument [LOG(X)+1.0 is the first derivative of X*LOG(X)].

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/practical_06.txt (3 of 4)9/19/2009 4:21:48 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/practical_06.txt

8.2 Write a program that calls that subroutine, and test it with thefollowing values:

1.23 456.7 8.9e5

[ Hint 1: Newton-Raphson solution of F(X) = A takes an approximatesolution X0 and improves it by calculating X1 = X0 - (F(X0)-A)/F'(X0) ]

[ Hint 2: use the function value as the initial guess at X ]

[ Hint 3: stop when the solution is the same as either itspredecessor or the one before that ]

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/practical_06.txt (4 of 4)9/19/2009 4:21:48 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/practical_07.txt

Introduction to Programming with Fortran----------------------------------------

Practical Exercise 7:---------------------

Question 1:-----------

Take a copy of the program `Inaccuracy.f90' and its data`inaccuracy.data', compile it, run it and save the results.

Create a file called `double.f90' containing the following code:

MODULE double INTEGER, PARAMETER :: DP = KIND(0.0D0) END MODULE double

Compile it to create a module file with the command:

f95 -C=all -c double.f90

Change every occurrence of `REAL' to `REAL(KIND=DP)' in`Inaccuracy.f90', add `_DP' to the end of every floating-point constant,and insert a `USE double' statement immediately before every`IMPLICIT NONE' statement and save the source.

Now compile `Inaccuracy.f90' normally, run it and save the results.

Compare the two sets of results, and note the much increased accuracy inthe second set. Inspect them and the source carefully, and check thatyou understand why that is.

Question 2:-----------

2.1 Copy the program `CubeRoot.f90' and run it interactively, puttingin as many floating-point values (positive, negative or zero) as youfeel like.

2.2 Change all occurrences of `REAL' to `COMPLEX', compile it, run it

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/practical_07.txt (1 of 2)9/19/2009 4:21:48 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/practical_07.txt

interactively, putting in as many complex values as you feel like.Remember that list-directed input takes numbers in the same format asconstants, but without any `_DP'.

Question 3:-----------

3.1 Copy the double precision source of the program `Inaccuracy.f90'(created in question 1) to another file, remove all occurrences of `_DP'(thus changing only the declarations and not the constants to doubleprecision), compile it and run it. What goes wrong and why?

3.2 Fix the errors that are flagged by the compiler and try again. Whathas gone wrong now, and why?

Question 4:-----------

[ This question is really a justification of the next lecture. ]

Copy the correct (created in question 1) double precision source of theprogram `Inaccuracy.f90', remove everything from the `MODULE double'statement to the `END MODULE double' statement, all the `IMPLICIT NONE 'statements and the `USE double' statement. Now repeat question 3, andnote how much harder it is to detect errors. No answer is provided forthis question, as it is intended only to show how using `old Fortran' issignificantly more error-prone than using `modern Fortran', but pleaseask about any error messages or other problems that you don'tunderstand.

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/practical_07.txt (2 of 2)9/19/2009 4:21:48 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/practical_08.txt

Introduction to Programming with Fortran----------------------------------------

Practical Exercise 08---------------------

Question 1----------

1.1 Write a module that defines the following:

an INTEGER constant `maxlength' with value 100

a CHARACTER constant `message' with the value 'Kilroy was here'

an INTEGER variable `errors' initialised to zero

an ALLOCATABLE REAL array `totals'

Remember to use SAVE appropriately. Compile that to create a modulefile.

1.2 Write a main program that uses the module, reads in an integer,checks that it is positive and no greater than `maxlength', allocates`totals' to be of that length, and print out the exception status and`message'. Check that the program compiles and runs (it doesn't doanything useful).

Question 2----------

2.1 Write a module that defines the following:

three REAL variables, `one', `two' and `three', initialised to zero

and contains:

a subroutine with no arguments `A' that adds 1.23 to `one'

a subroutine with no arguments `B' that sets `two' to `one+0.7'

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/practical_08.txt (1 of 4)9/19/2009 4:21:48 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/practical_08.txt

a subroutine with no arguments `C' that sets `three' to `one+two'

a subroutine with no arguments `D' that prints the value of `three'

2.2 Write a main program that uses that module and calls `A', `B',`A', `B',`A', `A', `C' and `D'. Compile and test it.

2.3 Change the module to declare the variables PRIVATE, recompile it,and recompile and test the main program.

2.4 Remove the PRIVATE, take out the code for `A', `B', `C' and `D' andcreate four other modules, each containing one subroutine. When using theoriginal module, import only the variables that they need. Recompile allmodules.

2.5 Change the main program to import only the modules containing `A',`B', `C' and `D' and not the one containing the variables. Compile andtest it. Note that this shows one way of sharing data betweenprocedures, but not exporting it to users of those procedures.

Question 3----------

3.1 Compile the file `Programs/double.f90' to create a module. Take thefile `Programs/CubeRoot.f90', and create a separate file out of thefunctions (NOT a module - just the two functions, end-to-end). Compilethat but do not link it.

3.2 Take the rest of the file `Programs/CubeRoot.f90' (i.e. with thefunctions removed) and produce an interface declaration for those twofunctions. Now compile and link that, togther with the compiled code ofthe functions, and test it.

Question 4----------

This question is easy to code, but tricky to understand. It showswhat is going on with name inheritance. It is very important tounderstand the `why' and not just observe what happens.

4.1 Compile the file `Programs/double.f90' to create a module. Take

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/practical_08.txt (2 of 4)9/19/2009 4:21:48 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/practical_08.txt

`Programs/Cholesky.f90', and put the subroutine `CHOLESK4' into a module`Lapack' in a separate file. Compile that to create a module file.

4.2 Create a main program that contains just the main program from`Programs/Cholesky.f90'and uses module `Lapack'. Compile and link thatand check that it works.

4.3 Remove the `USE double' from the main program, recompile it and testit. What goes wrong and why?

4.4 Move the `USE double' in module `Lapack' from subroutine `CHOLESK4'to immediately after the MODULE statement, recompile it and thenrecompile and test the main program. Why does it work again?

4.5 Now put the `USE double' back into the main program (i.e. undo whatyou did in 4.3), recompile it and test it. Check that it still works.

4.6 Now replace the `USE double' in module `Lapack' by its source form

INTEGER, PARAMETER :: dp = SELECTED_REAL_KIND(12)

Recompile it and then recompile and test the main program. What goeswrong and why? And why did 4.5 work if this didn't?

Question 5----------

This question is easy to code, but tricky to understand. It shows whatis going on with name inheritance and PRIVATE. It is very important tounderstand the `why' and not just observe what happens.

5.1 Restart question 4 at 4.4, but declare `dp' as `PRIVATE'. I.e.the module now starts:

MODULE Lapack USE double PRIVATE :: dp

and the main program does NOT have a `USE double'. Why does this notwork when 4.4 did?

5.2 Now put the `USE double' back into the main program. Check that it

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/practical_08.txt (3 of 4)9/19/2009 4:21:48 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/practical_08.txt

now works again. Why is this?

5.3 Now replace the `USE double' in module `Lapack' by its source form

INTEGER, PARAMETER :: dp = SELECTED_REAL_KIND(12)

Recompile it and then recompile and test the main program. Why doesthis work if 4.6 didn't?

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/practical_08.txt (4 of 4)9/19/2009 4:21:48 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/practical_09.txt

Introduction to Programming with Fortran----------------------------------------

Practical Exercise 09---------------------

Question 1----------

1.1 Write a module that defines a derived type My_complex containing twoINTEGERs (note), and contains a function to add two My_complex values(as if they were complex numbers) and return the result.

1.2 Write a program to define two My_complex variables, set them to(123, 456) and (432, 876) using constructors, copy the first one toa third variable, and print out the value of that.

1.3 Extend the program to create a fourth variable by multiplying thesecond variable by -i (i.e. reversing the order of its components) andprint out the value of the sum of the first third and fourth variablesby calling the module's function. Save the source of the program andmodule.

Question 2----------

2.1 File `Midden.data' contains data in the following format:

'Leechford' 5 13.17 42.62 46.24 5.51 23.23

The first line is a quoted string and an integer, which gives the countof the number of reals on the next line.

Write a module that defines a derived type `Midden' containing aCHARACTER variable of length 16, and an ALLOCATABLE array, andcontains a function and a subroutine.

The function takes an assumed length CHARACTER argument and anassumed shape REAL array and returns a value of type `Midden'.

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/practical_09.txt (1 of 2)9/19/2009 4:21:49 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/practical_09.txt

The subroutine takes a value of type Midden and prints its contents(you need not quote the string). If the name and array are bothnull, it prints a message saying so.

2.2 Write a program to allocate an array of type `Midden', read in`Midden.data' and call the function to initialise it, and then thesubroutine to print it. You may assume that there are never more than100 real values per entry. Unused elements should be set to a `Midden'with a null name and empty array. Save the source of the program andmodule.

Question 3----------

Add PRIVATE to hide the components of the derived type used in question2 and check that the program and module still work. Do so to the oneused in question 1 and see what fails.

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/practical_09.txt (2 of 2)9/19/2009 4:21:49 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_01.txt

Introduction to Programming with Fortran----------------------------------------

Practical Exercise 1 (Compilation and Editing): Solutions---------------------------------------------------------

Question 1----------

The following program reads in a number and prints its inverse:

PROGRAM INVERT IMPLICIT NONE REAL :: Value, Inverse PRINT *, "Type in a value to invert" READ *, Value Inverse = 1.0/Value PRINT *, "Value", Value, " Inverse", Inverse END PROGRAM INVERT

1.1 Using an editor, type the above program into a file called somethinglike `invert.f90'.

1.2 Compile and run the program. Verify the correctness of the code bysupplying the following test data (each value needs a separate run):

1.0 3.0 -20.0 1000.0 1.0e-30

Example output:

Type in a value to invert Value 1.0000000 Inverse 1.0000000

Type in a value to invert Value 3.0000000 Inverse 0.3333333

Type in a value to invert Value -20.0000000 Inverse -5.0000001E-02

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_01.txt (1 of 3)9/19/2009 4:21:49 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_01.txt

Type in a value to invert Value 1.0000000E+03 Inverse 1.0000000E-03

Type in a value to invert Value 1.0000000E-30 Inverse 1.0000000E+30

1.3 Save a copy of this program in another file (say `invert.safe').

1.4 See what happens when you supply the following data (each valueneeds a separate run):

0.0 1.0e-38 1.0e-40 weeble

Example output:

Type in a value to invert *** Arithmetic exception: Floating divide by zero - aborting Abort - core dumped

Type in a value to invert Value 9.9999994E-39 Inverse 1.0000001E+38 Warning: Floating underflow occurred during execution

Type in a value to invert *** Arithmetic exception: Floating overflow - aborting Abort - core dumped

Type in a value to invert Invalid input for real editing Program terminated by fatal I/O error Abort - core dumped

1.5 Edit the file, change the occurrence of `Value' to `Vole' in the`READ' statement, and see what happens when you compile it.

Example output:

Error: invert.f90, line 5: Implicit type for VALUE detected at VALUE@<end-of-statement> Warning: invert.f90, line 8: Unused symbol VOLE

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_01.txt (2 of 3)9/19/2009 4:21:49 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_01.txt

detected at INVERT@<end-of-statement> [f90 terminated - errors found by pass 1]

1.6 Restore the file from the safe copy, change the `READ' to `RODE',and see what happens when you compile it.

Example output:

Error: invert.f90, line 5: Unrecognised statement Error: invert.f90, line 5: Implicit type for RODE Error: invert.f90, line 5: syntax error ***Malformed statement Error: invert.f90, line 8: Symbol VALUE referenced but never set detected at INVERT@<end-of-statement> [f90 terminated - errors found by pass 1]

1.7 Restore the file from the safe copy, change the first `INVERT' to`invert', the first `Value' to `valUE', and the `Type' to `TYPE'. Nowsee what happens when you compile and run it with the input `1.0'.

Example output:

TYPE in a value to invert 1.0 Value 1.0000000 Inverse 1.0000000

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_01.txt (3 of 3)9/19/2009 4:21:49 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_02.txt

Introduction to Programming with Fortran----------------------------------------

Practical Exercise 2: Solutions-------------------------------

Question 1----------

Are the following statements true or false?

1.1 All Fortran 90 statements start in column 7.1.2 % (percent sign) has no special meaning in Fortran.1.3 In free source form spaces are allowed anywhere.1.4 Colons must be used to separate keywords from names.1.5 A line in Fortran can be any length.1.6 Only one Fortran statement can appear on a line.

1.7 Which of the following are valid Fortran names:

v1, V1, 1v, 1V, v_1, _v1, v%1

Answers-------

1.1 False. Only when using fixed source form.1.2 False. It is used as a selector for an object of derived type.1.3 False. They are not allowed for example in variable names, or in keywords.1.4 False. They are not mandatory but it is good practice to use them.1.5 False. The maximum line length is 132.1.6 False. Semi-colons can be used to separate statements on the same line.

1.7 `v1' and `V1' are valid, `1v' and `1V' are not valid (they startwith a number), `v_1' is valid, `_v1' is not valid (it must start with aletter), `v%1' is not valid (all characters must be alphanumeric orunderscore).

Question 2

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_02.txt (1 of 2)9/19/2009 4:21:49 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_02.txt

----------

When IMPLICIT NONE is used at the start of a program all variable namesbeginning with I, J, K, L, M, N are assumed to be INTEGER. Is this trueor false?

False. IMPLICIT NONE forces all variables to be declared in typestatements.

Question 3----------

The following program has been badly laid out. Reformat it so it isneat and readable but performs exactly the same function.

PROGRAM MAIN;INTEGER::degreesfahrenheit& ,degreescentigrade;READ*,& degreesfahrenheit;degreescentigrade& =5*(degreesfahrenheit-32)/9;PRINT*,& degreesCENtiGrAde;END

One Possible Answer-------------------

PROGRAM MAIN IMPLICIT NONE INTEGER :: degrees_fahrenheit, degrees_centigrade

READ *, degrees_fahrenheit degrees_centigrade = 5*(degrees_fahrenheit-32)/9 PRINT *, degrees_centigrade END

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_02.txt (2 of 2)9/19/2009 4:21:49 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_03.txt

Introduction to Programming with Fortran----------------------------------------

Practical Exercise 3: Solutions-------------------------------

Question 1----------

1.1 Evaluate the following when A = 6, B = 2 and C = 3. A, B and C areall integer variables.

A/B*C A*B/C 3*A**B B+A/C A/B+C

Answers: 9, 4, 108, 4 and 6.

1.2 Evaluate the above expressions when A = 3, B = 5 and C = 4.

Answers: 0, 3, 729, 5 and 4.

1.3 Write a program to check that your Fortran compiler gives theresults you have given.

Specimen Answer---------------

PROGRAM Trivial INTEGER :: A, B, C A = 6 B = 2 C = 3 PRINT *, A/B*C, A*B/C, 3*A**B, B+A/C, A/B+C A = 3 B = 5 C = 4

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_03.txt (1 of 7)9/19/2009 4:21:49 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_03.txt

PRINT *, A/B*C, A*B/C, 3*A**B, B+A/C, A/B+CEND PROGRAM Trivial

Question 2----------

2.1 What value does the real variable A take in the following statementswhen I = 5 and J = 4 (I and J are INTEGER)?

A = I*J A = I/J A = J/I

Answers: 20.0, 1.0 and 0.0.

2.2 What value does the INTEGER I take in the following statements whenA = 5.0, B = 4.0 (A and B are REAL)?

I = A*B I = A/B I = B/A

Answers: 20, 1 and 0.

Question 3----------

On a particular computer the range for reals is 10-38 to 10+38.

3.1 What value does the expression (A/B) have when A = 1.0, B = 0.0?3.2 What value does the expression (5.3E+25 * 6.4E+28) have?3.3 What value does the expression (5.3E-50 * 6.4E-35) have?

Answers-------

3.1 Overflow.3.2 Overflow.3.3 Underflow.

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_03.txt (2 of 7)9/19/2009 4:21:49 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_03.txt

Programs containing such expressions may crash, may deliver a specialvalue or may otherwise misbehave. In general, underflow will cause theresult to be quietly replaced by zero, but that is not required by theFortran standard.

Question 4----------

Why are named constants useful?

Answer: They reduce mistyping errors, they makes it clearer whichconstant is being used and they make it easier to modify the programlater.

Question 5----------

What is the difference between

REAL, PARAMETER :: pi = 22.0/3.0and

REAL :: pi = 22.0/3.0

Answer: The first defines a named constant pi with value 22.0/3.0, thesecond declares a variable named pi initialised to 22.0/3.0.

Question 6----------

Is the following program fragment allowed?

INTEGER, PARAMETER :: ZERO = 0 ZERO = 1

Answer: No, because ZERO is a constant and cannot be changed.

Question 7----------

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_03.txt (3 of 7)9/19/2009 4:21:49 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_03.txt

Is the following program fragment allowed?

INTEGER :: ONE = 1 ONE = 0

Answer: Yes, since ONE is a variable. It can have any value.

Question 8----------

Which of the following are incorrect declarations and why? If you thinka declaration may be correct in a given situation then say what thesituation would be.

8.1 ReAl :: x Correct, but quirky8.2 CHARACTER :: name Correct8.3 CHARACTER(LEN=10) :: name Correct8.4 REAL :: var-1 INCORRECT - can't declare an expression8.5 INTEGER :: 1a INCORRECT - names must start with a letter8.6 INTEGRAL :: loji INCORRECT - no such statement8.7 CHARACTER(LEN=5) :: town = "Glasgow" Correct, but town will contain "Glasg"8.8 CHARACTER(LEN=*), PARAMETER :: city = "Glasgow" Correct8.9 INTEGER :: pi = +22/7 Correct, but not useful - value of pi will be 38.10 CHARACTER(LEN=*), PARAMETER :: "Bognor" INCORRECT - no constant name given8.11 REAL, PARAMETER :: pye = 22.0/7.0 Correct8.12 REAL, PARAMETER :: two_pie = pye*2 Correct, provided pye is defined previously8.13 REAL :: a = 1., b = 2 Correct, but not good practice

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_03.txt (4 of 7)9/19/2009 4:21:49 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_03.txt

8.14 CHARACTER(LEN=6) :: you_know = 'y'know" INCORRECT - mangled character constant8.15 CHARACTER(LEN=6) :: you_know = "y'know" Correct8.16 INTEGER :: ia ib ic id INCORRECT - can't separate list by spaces8.17 REAL :: poie = 4.*atan(1.) INCORRECT - atan is not allowed in initialisation

Question 9----------

Declare the following objects:

9.1 feet an integer variable INTEGER :: feet9.2 miles a real variable REAL :: miles9.3 Town a character variable of up to 20 letters CHARACTER(LEN=20) :: Town9.4 home_town a constant with value to LIVERPOOL CHARACTER(LEN=*) :: home_town = "LIVERPOOL"9.5 sin_half a constant with value sin(0.5) = 0.47942554 REAL, PARAMETER :: sin_half = 0.47942554

Question 10-----------

Add parentheses to the following expression to indicate the order ofevaluation.

-a*b-c/d**e/f+g**h+1-j/k

Answer: ( ( ( (-(a*b)) - (c/(d**e))/f ) + (g**h) ) + 1 ) - (j/k) 3 2 1 x x y y 1 2 3

Question 11-----------

11.1 Write a program that reads in a person's name and date of birth (in

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_03.txt (5 of 7)9/19/2009 4:21:49 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_03.txt

the form `dd.mm.yy') and prints out a sentence such as:

dd.mm.yy is the birthday of Joe Bloggs

Specimen Answer---------------

PROGRAM sample IMPLICIT NONE CHARACTER(LEN=40) :: name CHARACTER(LEN=8) :: date PRINT *, 'Type name' READ *, name PRINT *, 'Type date' READ *, date PRINT *, date // ' is the birthday of ' // trim(name) END PROGRAM sample

11.2 Modify the program to print the sentence in the form:

Joe Bloggs was born on dd.mm.yy

Specimen Answer---------------

PROGRAM sample IMPLICIT NONE CHARACTER(LEN=40) :: name CHARACTER(LEN=8) :: date PRINT *, 'Type name' READ *, name PRINT *, 'Type date' READ *, date PRINT *, trim(name) // ' was born on ' // date END PROGRAM sample

Question 12-----------

Write a simple program to read in a radius and calculate the area of thecorresponding circle and volume of the corresponding sphere.

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_03.txt (6 of 7)9/19/2009 4:21:49 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_03.txt

Demonstrate its correctness by calculating the area and volume usingradii of 2, 5, 10 and -1.

The area of a circle is pi times the radius squared, and pi may be takenas 3.14159. The volume of a sphere is 4/3 pi times the radius cubed.

Specimen Answer---------------

PROGRAM Area IMPLICIT NONE REAL :: radius PRINT *, "Type in the radius" READ *, radius PRINT *, "Area of circle with radius ", & radius, " is ", 3.14159*radius**2 PRINT *, "Volume of sphere with radius ", & radius, " is ", (4.0/3.0)*3.14159*radius**3 END PROGRAM Area

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_03.txt (7 of 7)9/19/2009 4:21:49 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_04.txt

Introduction to Programming with Fortran----------------------------------------

Practical Exercise 4: Solutions-------------------------------

Question 1----------

How many times are the loops, defined by the following statements,executed:

DO I = 2, N/2, 3 DO I = 1, N, 4 DO I= 3, N**2, 5

when N is

1.1 21.2 15

Answers:

1.1 0, 1, 11.2 2, 4, 45

Question 2----------

Write a program to read in a vector defined by a length and an angle indegrees, which prints out the corresponding Cartesian (i.e. (x, y))co-ordinates. Recall that arguments to trigonometric functions are inradians.

Demonstrate correctness by giving the Cartesian co-ordinates for thefollowing vectors:

length angle2.1 12 772.2 1000 02.3 1000 90

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_04.txt (1 of 6)9/19/2009 4:21:49 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_04.txt

2.4 20 1002.5 12 437

Specimen Answer---------------

PROGRAM Cartesian IMPLICIT NONE REAL :: pi, length, angle, angle_in_radians pi = ATAN(1.0)*4.0 PRINT *, "Type in length and angle (in degrees)" READ *, length, angle angle_in_radians = (angle/180.0)*pi PRINT *, "(x, y) is (", length*COS(angle_in_radians), & ",", length*SIN(angle_in_radians), " )" END PROGRAM Cartesian

The results are (under one compiler):2.1 (x, y) is ( 2.6994126 , 11.6924410 )2.2 (x, y) is ( 1.0000000E+03 , 0.0000000E+00 )2.3 (x, y) is ( -4.3711389E-05 , 1.0000000E+03 )2.4 (x, y) is ( -3.4729660 , 19.6961555 )2.5 (x, y) is ( 2.6994104 , 11.6924419 )

Question 3----------

Write a Fortran program to count how many of a set of ten integerstyped in at the keyboard are multiples of five. Ignore any negativenumbers. Each number is input on a separate line.

Specimen Answer---------------

PROGRAM Multiples_of_Five IMPLICIT NONE INTEGER :: i, num, N = 0 DO i = 1,10 READ *, num IF (num < 0) CYCLE IF (MOD(num,5) == 0) N = N+1 ! MOD is an intrinsic function ENDDO

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_04.txt (2 of 6)9/19/2009 4:21:49 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_04.txt

PRINT *, N, ' of the numbers are multiples of 5' END PROGRAM Multiples_of_Five

Question 4----------

Write a program to accept three integer lengths and report back onwhether these lengths could define an equilateral, isoceles or scalenetriangle (3, 2 or 0 equal length sides), or whether they cannot form atriangle.

Demonstrate that the program works by classifying the following:

4.1 1 1 14.2 2 2 14.3 1 1 04.4 3 4 54.5 3 2 14.6 1 2 4

Hint: if three lengths form a triangle then 2 times the longest sidemust be less than the sum of all three sides. In Fortran 90 terms, thefollowing must be true:

2*MAX(sidel,side2,side3) < sidel+side2+side3

Specimen Answer---------------

PROGRAM Triangle IMPLICIT NONE LOGICAL :: L1, L2 INTEGER :: side1, side2, side3 PRINT *, "Type in the three sides:" READ *, side1, side2, side3 IF (2*MAX(side1, side2, side3) >= side1+side2+side3) THEN PRINT *, "Not a Triangle" ELSE L1 = (side1 == side2) L2 = (side2 == side3) IF (L1 .AND. L2) THEN PRINT *, "Equilateral"

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_04.txt (3 of 6)9/19/2009 4:21:49 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_04.txt

ELSEIF (L1 .OR. L2 .OR. side1 == side3) THEN PRINT *, "Isoceles" ELSE PRINT *, "Scalene" ENDIF ENDIF END PROGRAM Triangle

The results are:

4.1 1 1 1 Equilateral4.2 2 2 1 Isoceles4.3 1 1 0 Not a Triangle4.4 3 4 5 Scalene4.5 3 2 1 Not a Triangle [ a straight line ]4.6 1 2 4 Not a Triangle

Question 5----------

If you take a positive integer, halve it if it is even or triple it andadd one if it is odd, and repeat, then the number will eventually becomeone. Warning: it may take a long time!

Set up a loop containing a statement to read in a number (inputterminated by zero) and to print out the sequence obtained from eachinput. The number 13 is considered to be very unlucky and if it isobtained as part of the sequence then execution should immediatelyterminate with an appropriate message.

Demonstrate that your program works by outputting the sequencesgenerated by the following two sets of numbers (each number goes ona separate line):

5.1 7 0

5.2 106 46 3 0

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_04.txt (4 of 6)9/19/2009 4:21:49 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_04.txt

Specimen Answer---------------

PROGRAM Math_Magic IMPLICIT NONE INTEGER :: num, tnumouter: DO PRINT *, "Type in your number (0 terminates)" READ *, num IF (num .LE. 0) EXITinner: DO tnum = num/2 IF (2*tnum .EQ. num) THEN ! num is even num = tnum ELSE ! num is odd num = 3*num+1 END IF PRINT *, num IF (num == 1) THEN PRINT *, "Sequence finishes nicely" EXIT ELSE IF (num == 13) THEN PRINT *, "Yoiks, extreme bad luck encountered" EXIT outer END IF END DO inner END DO outer END PROGRAM Math_Magic

The results are (with lines concatenated):

5.1 22 11 34 17 52 26 13 Yoiks, extreme bad luck encountered

5.2 53 160 80 40 20 10 5 16 8 4 2 1 Sequence finishes nicely 23 70 35 106 53 160 80 40 20 10 5 16 8 4 2 1 Sequence finishes nicely 10 5 16 8 4 2 1 Sequence finishes nicely

Question 6----------

Write a program that will read a sequence of colours input as names,

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_04.txt (5 of 6)9/19/2009 4:21:49 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_04.txt

'red', 'green', 'blue', 'yellow', 'black', 'white' or something else.Stop the program if a colour 'end' is read. Count the number ofoccurrences of each colour, including the unspecified colours and printout the totals for each colour before terminating the program.

Specimen Answer---------------

PROGRAM colours IMPLICIT NONE CHARACTER(LEN=10) :: colour INTEGER :: nred = 0, ngreen = 0, nblue = 0, nyellow = 0, & nblack = 0, nwhite = 0, nother = 0

DO READ *, colour colour = TRIM(ADJUSTL(colour)) ! gets rid of leading ! and trailing spaces IF (colour == 'red') THEN nred = nred+1 ELSEIF (colour == 'green') THEN ngreen = ngreen + 1 ELSEIF (colour == 'blue') THEN nblue = nblue + 1 ELSEIF (colour == 'yellow') THEN nyellow = nyellow + 1 ELSEIF (colour == 'black') THEN nblack = nblack + 1 ELSEIF (colour == 'white') THEN nwhite = nwhite + 1 ELSEIF (colour == 'end') THEN EXIT ELSE nother = nother+1 ENDIF ENDDO PRINT *, 'red =', nred, ' green =', ngreen, & ' blue =', nblue, ' yellow =', nyellow, & ' black =', nblack, ' white =', nwhite, & ' other =', nother END PROGRAM colours

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_04.txt (6 of 6)9/19/2009 4:21:49 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_05.txt

Introduction to Programming with Fortran----------------------------------------

Practical Exercise 5: Solutions-------------------------------

Question 1: Rank, Extents etc.------------------------------

Give the rank, bounds, size and shape of the arrays defined as follows:

1.1 REAL, DIMENSION(10) :: ONE1.2 REAL, DIMENSION(2, 0:2) :: TWO1.3 INTEGER, DIMENSION(-1:1, 3 , 2) :: THREE1.4 REAL, DIMENSION(0:1, 3) :: FOUR

Answer: rank bounds size shape1.1 1 1:10 10 (10)1.2 2 1:2, 0:2 6 (2, 3)1.3 3 -1:1, 1:3, 1:2 18 (3, 2, 3)1.4 2 0:1, 1:3 6 (2, 3)

Question 2: Conformance-----------------------

Given:

2.1 REAL, DIMENSION(1:10) :: ONE2.2 REAL, DIMENSION(2, O:2) :: TWO2.3 INTEGER, DIMENSION(-1:1, 3, 2) :: THREE2.4 REAL, DIMENSION(0:1, 3) :: FOUR

Which two of the arrays are conformable?

Answer: TWO and FOUR (note that they have the same rank, size andshape, but their bounds differ)

Question 3: Hotel Array-----------------------

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_05.txt (1 of 8)9/19/2009 4:21:49 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_05.txt

3.1 Declare an array of rank 3 which might be suitable for representinga hotel with 8 floors and 16 rooms on each floor and 2 beds in eachroom.

3.2 How would the 2nd bed in the 5th room on floor 7 be referenced?

Answer:

3.1 INTEGER, DIMENSION(8, 16, 2) :: Hotel

3.2 Hotel(7, 5, 2)

[ or any permutation of the three indices, provided that both thedeclaration and reference are permuted compatibly ]

Question 4: Array References----------------------------

Given:

INTEGER :: i = 3, j = 7 REAL, DIMENSION(1:20) :: A

which of the following are valid array references for the array:

4.1 A(12)4.2 A(21)4.3 A(I*J-1)4.4 A(3.0)4.5 A(I*J)4.6 A(1+INT(4.0*ATAN(1.0))) [ Hint: 4.0*ATAN(1.0) is pi ]

Answer:

4.1 Yes4.2 No (out of bounds)4.3 Yes - it is A(20)4.4 No (wrong type of subscript)4.5 No (out of bounds - I*J is 21)4.6 Yes - it is A(4)

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_05.txt (2 of 8)9/19/2009 4:21:49 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_05.txt

Question 5: Array Element Ordering----------------------------------

Given:

5.1 REAL, DIMENSION(1:10) :: ONE5.2 REAL, DIMENSION(2, 0:2) :: TWO5.3 INTEGER, DIMENSION(-1:1, 3, 2) :: THREE5.4 REAL, DIMENSION(0:1, 3) :: FOUR

write down the array element order of each array.

Answer:

5.1 ONE(1), ONE(2), ..., ONE(9), ONE(10)5.2 TWO(1,0), TWO(2,0), TWO(1,1), TWO(2,1), TWO(1,2), TWO(2,2)5.3 THREE(-1,1,1), THREE(0,1,1), THREE(1,1,1), THREE(-1,2,1), THREE(0,2,1), THREE(1,2,1), THREE(-1,3,1), THREE(0,3,1), THREE (1,3,1), THREE(-1,1,2), THREE(0,1,2), THREE(1,1,2), THREE(-1,2,2), THREE(0,2,2), THREE(1,2,2), THREE(-1,3,2), THREE(0,3,2), THREE(1,3,2)5.4 FOUR(0,1), FOUR(1,1), FOUR(0,2), FOUR(1,2), FOUR(0,3), FOUR(1,3)

Question 6: Array Sections--------------------------

Declare an array which would be suitable for representing draughtsboard, and initialise it to zero. Write two assignments to set all theblack squares to unity. [ A draughts board is 8 x 8 with alternateblack and white squares, in both directions. ]

Answer:

INTEGER, DIMENSION(8,8) :: Board = 0 Board(1:8:2, 1:8:2) = 1 Board(2:8:2, 2:8:2) = 1

Question 7: Array Constructor-----------------------------

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_05.txt (3 of 8)9/19/2009 4:21:49 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_05.txt

Write an array constructor for the rank one 5 element array BOXEScontaining the values 1, 4, 6, 12, 23.

Answer: BOXES = (/ 1, 4, 6, 12, 23 /)

Question 8: MATMUL Intrinsic----------------------------

For the declarations:

REAL, DIMENSION(100, 100) :: A, B, C

8.1 What is the difference between C = MATMUL(A,B) and C = A*B?

Answer: MATMUL(A,B) gives the matrix multiplication, C = A*B multipliescorresponding elements of the two arrays to give C.

8.2 Which of the following are correct?

8.2.1 A = MATMUL(P,T)8.2.2 P = MATMUL(Q,R)8.2.3 A = P*T8.2.4 P = Q*R8.2.5 T = MATMUL(T,A)

Answer:

8.2.1 Yes8.2.2 No8.2.3 No8.2.4 Yes8.2.5 Yes

Question 9: MATMUL By Hand--------------------------

In this question, you may assume that there are no errors and omit allchecking. That is not good practice, but considerably simplifies thecoding. You should not assume the matrices are square.

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_05.txt (4 of 8)9/19/2009 4:21:49 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_05.txt

The harness for a sort of MATMUL could be:

SUBROUTINE MyMatmul (result, left, right) IMPLICIT NONE REAL, DIMENSION :: result, left, right . . . END SUBROUTINE MyMatmul

9.1 Replace the ". . ." by the statements needed to calculate the matrix(not elementwise) product `result = left*right' using basic scalaroperations only.

9.2 Replace the ". . ." by the statements needed to calculate the matrix(not elementwise) product result = left*right using the SUM intrinsic.

Specimen Answer:----------------

9.1

SUBROUTINE MyMatmul (result, left, right) IMPLICIT NONE REAL, DIMENSION(:,:) :: result, left, right INTEGER :: I, J, K REAL :: X DO K = 1,UBOUND(result,2) DO J = 1,UBOUND(result,1) X = 0.0 DO I = 1,UBOUND(left,2) X = X+left(J,I)*right(I,K) ENDDO result(J,K) = X ENDDO ENDDO END SUBROUTINE MyMatmul

9.2

SUBROUTINE MyMatmul (result, left, right) IMPLICIT NONE REAL, DIMENSION(:,:) :: result, left, right INTEGER :: J, K DO K = 1,UBOUND(result,2)

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_05.txt (5 of 8)9/19/2009 4:21:49 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_05.txt

DO J = 1,UBOUND(result,1) result(J,K) = SUM(left(J,:)*right(:,K)) ENDDO ENDDO END SUBROUTINE MyMatmul

Question 10: ALLOCATABLE arrays-------------------------------

10.1 You have a subroutine like the following:

SUBROUTINE OPERATE (ARG) IMPLICIT NONE REAL, DIMENSION(:, :) :: ARG . . . END SUBROUTINE OPERATE

Replace the ". . ." by the statements needed to allocate an arraywith the same shape as ARG. Do this using automatic arrays, notusing ALLOCATE.

10.2 Repeat 10.1 but use ALLOCATE, not automatic arrays.

Specimen Answer:----------------

10.1 Code:

SUBROUTINE OPERATE (ARG) IMPLICIT NONE REAL, DIMENSION(:, :) :: ARG REAL, DIMENSION(UBOUND(ARG, 1), UBOUND(ARG, 2)) :: TEMP END SUBROUTINE OPERATE

10.2 Code:

SUBROUTINE OPERATE (ARG) IMPLICIT NONE REAL, DIMENSION(:, :) :: ARG REAL, DIMENSION(:, :), ALLOCATABLE :: TEMP ALLOCATE(TEMP(UBOUND(ARG, 1), UBOUND(ARG, 2))) END SUBROUTINE OPERATE

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_05.txt (6 of 8)9/19/2009 4:21:49 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_05.txt

Question 11: Actual Coding--------------------------

You have a subroutine like the following:

SUBROUTINE OPERATE (ARG, N, ICODE) IMPLICIT NONE REAL :: ARG(:, :) INTEGER :: N, ICODE . . . END SUBROUTINE OPERATE

Replace the ". . ." by the statements needed to do all of thefollowing: check that N is positive or zero check that the matrix has at least one element check that the matrix is square allocate an array with the same shape as ARG using ALLOCATE replace ARG by ARG**N, but using matrix multiplication (i.e. MATMUL)and not element-wise multiplication set ICODE to 0 if the subroutine works and 1 otherwise

Specimen Answer:----------------

SUBROUTINE OPERATE (ARG, N, ICODE) IMPLICIT NONE REAL, DIMENSION(:, :) :: ARG REAL, DIMENSION(:, :), ALLOCATABLE :: TEMP INTEGER :: N, ICODE, I

IF (N < 0 .OR. UBOUND(ARG, 1) <= 0 .OR. UBOUND(ARG, 2) <= 0 .OR. & UBOUND(ARG, 1) /= UBOUND(ARG, 2)) THEN ICODE = 1 RETURN ENDIF ALLOCATE(TEMP(UBOUND(ARG, 1), UBOUND(ARG, 2)), STAT=ICODE) IF (ICODE /= 0) RETURN IF (N == 0) THEN ARG = 0.0

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_05.txt (7 of 8)9/19/2009 4:21:49 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_05.txt

DO I = 1, UBOUND(ARG, 1) ARG(I,I) = 1.0 ENDDO ELSE TEMP = ARG DO I = 1, N-1 ARG = MATMUL(ARG,TEMP) ENDDO ENDIF END SUBROUTINE OPERATE

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_05.txt (8 of 8)9/19/2009 4:21:49 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_06.txt

Introduction to Programming with Fortran----------------------------------------

Practical Exercise 6: Solutions-------------------------------

Question 1: Simple Example of Subroutine----------------------------------------

1.1 Write a main program and internal subroutine that takes three REALarguments and returns, as its first argument, the third argumentsubtracted from the second. Keep the code as simple as possible. Testthis by including calls to add the following pairs of numbers:

1.23 4.56 -7.89 3.42 4.29 -0.98

1.2 Add INTENT to the above code and check that it works.

1.3 Change the call to using keywords and change the order of thearguments; check that this does not change the results. Save thiscode in a file.

Specimen Answer---------------

1.1 Code:

PROGRAM main IMPLICIT NONE REAL :: X

CALL diff (X, 1.23, 4.56) PRINT *, X CALL diff (X, -7.89, 3.42) PRINT *, X CALL diff (X, 4.29, -0.98) PRINT *, X

CONTAINS

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_06.txt (1 of 12)9/19/2009 4:21:50 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_06.txt

SUBROUTINE diff (P, Q, R) IMPLICIT NONE REAL :: P, Q, R P = Q-R END SUBROUTINE diff

END PROGRAM main

Results:

-3.3299999 -11.3099995 5.2700000

1.2 Subroutine `diff' becomes something like:

SUBROUTINE diff (P, Q, R) IMPLICIT NONE REAL, INTENT(OUT) :: P REAL, INTENT(IN) :: Q, R P = Q-R END SUBROUTINE diff

1.3 The executable statements of the main program become something like:

CALL diff (R=4.56, Q=1.23, P=X) PRINT *, X CALL diff (Q=-7.89, P=X, R=3.42) PRINT *, X CALL diff (R=-0.98, P=X, Q=4.29) PRINT *, X

Question 2: Simple example of a Function----------------------------------------

2.1 Write a main program and an internal function that takes two REALarguments and returns the second argument subtracted from the first.Keep the code as simple as possible. Test this by including calls to addthe following pairs of numbers:

1.23 4.56

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_06.txt (2 of 12)9/19/2009 4:21:50 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_06.txt

-7.89 3.42 4.29 -0.98

2.2 Add INTENT and ELEMENTAL to the above code and check that it works.

2.3 Change the call to using keywords and reverse the order of thearguments; check that this does not change the results.

Specimen Answer---------------

2.1 Code:

PROGRAM main IMPLICIT NONE REAL :: X

X = diff(1.23, 4.56) PRINT *, X X = diff(-7.89, 3.42) PRINT *, X X = diff(4.29, -0.98) PRINT *, X

CONTAINS

FUNCTION diff (A, B) IMPLICIT NONE REAL :: diff, A, B diff = A-B END FUNCTION diff

END PROGRAM main

Results:

-3.3299999 -11.3099995 5.2700000

2.2 Function `diff' becomes something like:

ELEMENTAL FUNCTION diff (A, B)

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_06.txt (3 of 12)9/19/2009 4:21:50 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_06.txt

IMPLICIT NONE REAL :: diff REAL, INTENT(IN) :: A, B diff = A-B END FUNCTION diff

2.3 The executable statements of the main program become something like:

X = diff(B=4.56, A=1.23) PRINT *, X X = diff(B=3.42, A=-7.89) PRINT *, X X = diff(B=-0.98, A=4.29) PRINT *, X

Question 3: Random Number Generation------------------------------------

3.1 Write a module containing function which simulates a throw of twodice and returns the total score, and compile it. The following codefragment will set Z to a pseudo-random number uniformly distributedbetween 0 and 1:

REAL :: Z CALL RANDOM_NUMBER(Z)

3.2 Write a main program that uses that module, and prints out theresult of the throw of two dice 10 times. Compile and run it.

Specimen Answer---------------

3.1 Code:

MODULE rollem CONTAINS FUNCTION twodice () IMPLICIT NONE INTEGER :: twodice REAL :: temp

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_06.txt (4 of 12)9/19/2009 4:21:50 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_06.txt

CALL RANDOM_NUMBER(temp) twodice = INT(6.0*temp+1.0) CALL RANDOM_NUMBER(temp) twodice = twodice+INT(6.0*temp+1.0) END FUNCTION twodice END MODULE rollem

3.2 Code:

PROGRAM throw USE rollem IMPLICIT NONE INTEGER :: k, n

DO k = 1,10 n = twodice() PRINT *, n ENDDO END PROGRAM throw

Results:

These will change for each run, and all be in the range 2-12 inclusive.2 and 12 should be rare, and 3 and 11 not frequent.

Comment: there is a slight catch to this one. If you declare thefunction as PURE, it won't work - try it, if you have not done so.RANDOM_NUMBER is one of the few impure intrinsic procedures.

Question 4: Arrays------------------

4.1 Write a program with an internal subroutine that takes two assumedshape 2-dimensional REAL array arguments, with INTENT(OUT) andINTENT(IN), checks that their shapes are compatible, and allocates two1-dimensional REAL arrays the same size as the first and seconddimensions.

4.2 Add the code to set the two automatic arrays to the row and columnaverages, and shift the rows and columns so that all row and columntotals are zero. To do this, set the first argument to the value of thesecond with the relevant row and column averages subtracted from it and

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_06.txt (5 of 12)9/19/2009 4:21:50 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_06.txt

the overall average added to it. Test this by providing it with thematrix:

2.35 2.82 4.55 7.83 3.97 6.75 7.62 8.36 8.97 0.74 2.70 2.49

Specimen Answer---------------

4.1 Code:

PROGRAM array

CONTAINS

SUBROUTINE scaler (arg1, arg2) IMPLICIT NONE REAL, DIMENSION(:, :) :: arg1, arg2 REAL, DIMENSION(:), ALLOCATABLE :: temp1, temp2 INTEGER :: m, n m = UBOUND(arg1, 1) n = UBOUND(arg1, 2) IF (m /= UBOUND(arg2, 1) .OR. n /= UBOUND(arg2, 2)) THEN PRINT *, 'The arrays are incompatible' STOP ENDIF ALLOCATE(temp1(1:UBOUND(arg1, 1))) ALLOCATE(temp2(1:UBOUND(arg1, 2))) END SUBROUTINE scaler

END PROGRAM array

4.2 Code:

PROGRAM array IMPLICIT NONE REAL, DIMENSION(3, 4) :: work1, work2

work2(1, :) = (/ 2.35, 2.82, 4.55, 7.83 /) work2(2, :) = (/ 3.97, 6.75, 7.62, 8.36 /) work2(3, :) = (/ 8.97, 0.74, 2.70, 2.49 /)

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_06.txt (6 of 12)9/19/2009 4:21:50 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_06.txt

CALL scaler(work1, work2) PRINT *, work1(1, :) PRINT *, work1(2, :) PRINT *, work1(3, :) PRINT *, SUM(work1(1, :)), SUM(work1(2, :)), & SUM(work1(3, :)), SUM(work1(:, 1)) & SUM(work1(:, 2)), SUM(work1(:, 3))

CONTAINS

SUBROUTINE scaler (arg1, arg2) IMPLICIT NONE REAL, DIMENSION(:, :), INTENT(OUT) :: arg1 REAL, DIMENSION(:, :), INTENT(IN) :: arg2 REAL, DIMENSION(:), ALLOCATABLE :: temp1, temp2 INTEGER :: j, k, m, n m = UBOUND(arg1, 1) n = UBOUND(arg1, 2) IF (m /= UBOUND(arg2, 1) .OR. n /= UBOUND(arg2, 2)) THEN PRINT *, 'The arrays are incompatible' STOP ENDIF ALLOCATE(temp1(1:UBOUND(arg1, 1))) ALLOCATE(temp2(1:UBOUND(arg1, 2))) DO j = 1, m temp1(j) = sum(arg2(j, :))/n ENDDO DO k = 1, n temp2(k) = sum(arg2(:, k))/m ENDDO DO j = 1, n DO k = 1, m arg1(k, j) = arg2(k, j) - temp1(k) - & temp2(j) + sum(temp1)/m ENDDO ENDDO END SUBROUTINE scaler

END PROGRAM array

Results:

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_06.txt (7 of 12)9/19/2009 4:21:50 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_06.txt

-2.2049999 -7.4999809E-02 0.1350007 2.1450009 -2.8725004 1.5675001 0.9175000 0.3875003 5.0775003 -1.4924994 -1.0524998 -2.5324993

Question 5: CHARACTER Arguments-------------------------------

Write a program with an internal subroutine that takes one INTEGER andthree assumed size CHARACTER arguments, prints out each of the CHARACTERones on a separate line, and sets the integer argument to the sum oftheir lengths. Use the following data to test it:

'Kilroy' 'was' 'here'

Specimen Answer---------------

PROGRAM trivial IMPLICIT NONE INTEGER :: n

CALL chars(n, 'Kilroy', 'was', 'here') PRINT *, n

CONTAINS

SUBROUTINE chars (count, str1, str2, str3) IMPLICIT NONE INTEGER, INTENT(OUT) :: count CHARACTER(LEN=*), INTENT(IN) :: str1, str2, str3

PRINT *, str1 PRINT *, str2 PRINT *, str3 count = LEN(str1)+LEN(str2)+LEN(str3) END SUBROUTINE chars

END PROGRAM trivial

Results:

Kilroy

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_06.txt (8 of 12)9/19/2009 4:21:50 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_06.txt

was here 13

Question 6: CHARACTER Functions-------------------------------

Write a program with an internal function that takes one assumed sizeCHARACTER argument, and returns the value argument with leading andtrailing spaces removed and padded to the same length as its argumentwith '.'s. Test this with the following strings:

'How, now, brown cow?' ' Spaced out ' [ 3 leading and 5 trailing spaces ]

Specimen Answer---------------

PROGRAM trivial IMPLICIT NONE

PRINT *, dotit('How, now, brown cow?') PRINT *, dotit(' Spaced out ')

CONTAINS

PURE FUNCTION dotit (string) IMPLICIT NONE CHARACTER(LEN=*), INTENT(IN) :: string CHARACTER(LEN=LEN(STRING)) :: dotit

dotit = TRIM(ADJUSTL(string)) // REPEAT('.', LEN(string)) END FUNCTION dotit

END PROGRAM trivial

Results:

How, now, brown cow? Spaced out........

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_06.txt (9 of 12)9/19/2009 4:21:50 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_06.txt

Question 7: Save Attribute--------------------------

Write a subroutine with one INTEGER argument that returns 7 the firsttime it is called, 8 the next time, 9 the next time, and so on. Declarethe argument INTENT(OUT). Test it however you prefer.

Specimen Answer---------------

SUBROUTINE counter (count) IMPLICIT NONE INTEGER, INTENT(OUT) :: count INTEGER, SAVE :: state = 7

count = state state = state+1 END SUBROUTINE counter

Question 8: Newton-Raphson--------------------------

8.1 Write a module containing a subroutine and two functions; you canput both of them after the module's CONTAINS at the same level (i.e. thefunctions need not be internal procedures of the subroutine).

The subroutine should accept a value of X*LOG(X) greater than 1.0 andprint the corresponding value of X, by calling the functions and usingNewton-Raphson iteration.

The first function should return the value of X*LOG(X), where x is itsargument.

The second function should return the value of LOG(X)+1.0, where x is itsargument [LOG(X)+1.0 is the first derivative of X*LOG(X)].

8.2 Write a program that calls that subroutine, and test it with thefollowing values:

1.23 456.7 8.9e5

[ Hint 1: Newton-Raphson solution of F(X) = A takes an approximate

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_06.txt (10 of 12)9/19/2009 4:21:50 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_06.txt

solution X0 and improves it by calculating X1 = X0 - (F(X0)-A)/F'(X0) ]

[ Hint 2: use the function value as the initial guess at X ]

[ Hint 3: stop when the solution is the same as either itspredecessor or the one before that ]

Specimen Answer---------------

Module:

MODULE Solver CONTAINS

SUBROUTINE Newton (value) IMPLICIT NONE REAL, INTENT(IN) :: value REAL :: solution, last, previous

IF ( value < 1.0) THEN PRINT *, 'Value of X*LOG(X) out of range' RETURN END IF solution = value last = 2.0*value previous = 3.0*value DO solution = solution - & (Fn1(solution) - value) / Fn2(solution) IF (solution == last .OR. solution == previous) EXIT previous = last last = solution ENDDO PRINT *, 'X*LOG(X) =', value, ' X =', solution END SUBROUTINE Newton

PURE FUNCTION Fn1 (arg) IMPLICIT NONE REAL :: Fn1 REAL, INTENT(IN) :: arg

Fn1 = arg*LOG(arg)

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_06.txt (11 of 12)9/19/2009 4:21:50 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_06.txt

END FUNCTION Fn1

PURE FUNCTION Fn2 (arg) IMPLICIT NONE REAL :: Fn2 REAL, INTENT(IN) :: arg

Fn2 = LOG(arg)+1.0 END FUNCTION Fn2

END MODULE Solver

Program:

PROGRAM Tester USE Solver IMPLICIT NONE

CALL Newton(1.23) CALL Newton(456.7) CALL Newton(8.9e5) END PROGRAM Tester

Results:

X*LOG(X) = 1.2300000 X = 1.9063751 X*LOG(X) = 4.5670001E+02 X = 99.3186035 X*LOG(X) = 8.9000000E+05 X = 7.8926766E+04

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_06.txt (12 of 12)9/19/2009 4:21:50 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_07.txt

Introduction to Programming with Fortran----------------------------------------

Practical Exercise 7: Solutions-------------------------------

Question 1:-----------

Take a copy of the program `Inaccuracy.f90' and its data`inaccuracy.data', compile it, run it and save the results.

Create a file called `double.f90' containing the following code:

MODULE double INTEGER, PARAMETER :: DP = KIND(0.0D0) END MODULE double

Compile it to create a module file with the command:

f95 -C=all -c double.f90

Change every occurrence of `REAL' to `REAL(KIND=DP)' in`Inaccuracy.f90', add `_DP' to the end of every floating-point constant,and insert a `USE double' statement immediately before every`IMPLICIT NONE' statement and save the source.

Now compile `Inaccuracy.f90' normally, run it and save the results.

Compare the two sets of results, and note the much increased accuracy inthe second set. Inspect them and the source carefully, and check thatyou understand why that is.

Answer:

The results are (placed side by side for convenience):

3.14159265358979323846 3.14159265358979323846 314159.265358979323846 314159.265358979323846 3.14159274101257324219 3.14159265358979311600 314159.250000000000000 314159.265358979348093

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_07.txt (1 of 4)9/19/2009 4:21:50 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_07.txt

314159.281250000000000 314159.265358979289886 3.14159274101257324219 3.14159265358979311600 314159.250000000000000 314159.265358979348093 314159.281250000000000 314159.265358979289886 3.14159274101257324219 3.14159265358979311600 314159.250000000000000 314159.265358979348093 314159.281250000000000 314159.265358979289886 3.14159274101257324219 3.14159265358979311600 3.14159274101257324219 3.14159265358979311600 314159.281250000000000 314159.265358979289886 3.14159274101257324219 3.14159265358979311600 314159.250000000000000 314159.265358979348093 3.14159274101257324219 3.14159265358979311600 3.14159274101257324219 3.14159265358979311600 3.14159464836120605469 3.14159265358979622462 314159.375000000000000 314159.265358979522716 3.14138388633728027344 3.14159264457621567601

Note that single precision is accurate to about 6-7 significant figures,but double precision is to about 15. Also note that even a small amountof calculation loses 1-2 significant figures and the series summationloses 4-7. That is why it is essential to use double precision for anyrealistic programming.

Question 2:-----------

2.1 Copy the program `CubeRoot.f90' and run it interactively, putting inas many floating-point values (positive, negative or zero) as you feellike.

2.2 Change all occurrences of `REAL' to `COMPLEX', compile it, run itinteractively, putting in as many complex values as you feel like.Remember that list-directed input takes numbers in the same format asconstants, but without any `_DP'.

Answer:

Do you really need one? Yes, it really is that easy to use complexarithmetic in Fortran!

You are recommended to experiment with formatted I/O and using built-in

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_07.txt (2 of 4)9/19/2009 4:21:50 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_07.txt

functions, but they aren't significantly harder.

Question 3:-----------

3.1 Copy the double precision source of the program `Inaccuracy.f90'(created in question 1) to another file, remove all occurrences of `_DP'(thus changing only the declarations and not the constants to doubleprecision), compile it and run it. What goes wrong and why?

3.2 Fix the errors that are flagged by the compiler and try again. Whathas gone wrong now, and why?

Answer:

1. The two calls of the 'copy' function with constant (literal)arguments are flagged as having invalid types for their argument,because the constants are single precision and the function was declaredas having a double precision argument. The simplest fix is to add `_DP'to the end of each constant, but you could also convert the argument byusing the `DBLE' function.

2. Most (but not all) results are either the same as the singleprecision ones or of comparable accuracy. This is mostly because theconstants have been translated to single precision before being storedby the compiler, and promoted to double precision when they are used.However, the calls to `atan' with a constant argument have calculated itin single precision, because it is a generic function and uses the typeof its argument to select its precision. This is why it is safest toconvert all constants, even ones that can be represented exactly insingle precision.

Question 4:-----------

[ This question is really a justification of the next lecture. ]

Copy the correct (created in question 1) double precision source of theprogram `Inaccuracy.f90', remove everything from the `MODULE double'statement to the `END MODULE double' statement, all the `IMPLICIT NONE 'statements and the `USE double' statement. Now repeat question 3, and

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_07.txt (3 of 4)9/19/2009 4:21:50 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_07.txt

note how much harder it is to detect errors. No answer is provided forthis question, as it is intended only to show how using `old Fortran' issignificantly more error-prone than using `modern Fortran', but pleaseask about any error messages or other problems that you don'tunderstand.

No answer is provided for this, as it is an exercise in debugging.It is intended to show how errors do not always cause diagnostics orcrashes, but very often cause wrong or inaccurate answers, and thoseare usually even harder to track down than crashes.

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_07.txt (4 of 4)9/19/2009 4:21:50 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_08.txt

Introduction to Programming with Fortran----------------------------------------

Practical Exercise 08: Solutions--------------------------------

Question 1----------

1.1 Write a module that defines the following:

an INTEGER constant `maxlength' with value 100

a CHARACTER constant `message' with the value 'Kilroy was here'

an INTEGER variable `errors' initialised to zero

an ALLOCATABLE REAL array `totals'

Remember to use SAVE appropriately. Compile that to create a modulefile.

1.2 Write a main program that uses the module, reads in an integer,checks that it is positive and no greater than `maxlength', allocates`totals' to be of that length, and print out the exception status and`message'. Check that the program compiles and runs (it doesn't doanything useful).

Specimen Answer---------------

1.1 Code:

MODULE Junk IMPLICIT NONE INTEGER, PARAMETER :: maxlength = 100 CHARACTER(LEN=*),PARAMETER :: message = 'Kilroy was here' INTEGER, SAVE :: errors = 0 REAL, ALLOCATABLE, DIMENSION(:) :: totals END MODULE Junk

1.2 Code:

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_08.txt (1 of 11)9/19/2009 4:21:50 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_08.txt

PROGRAM Futile USE JUNK IMPLICIT NONE INTEGER :: size, err Print *, 'Type an integer' READ *, size IF (size <= 0 .OR. size > maxlength) STOP ALLOCATE(totals(size), STAT=err) PRINT *, err PRINT *, message END PROGRAM Futile

Results:

0 Kilroy was here

Question 2----------

2.1 Write a module that defines the following:

three REAL variables, `one', `two' and `three', initialised to zero

and contains:

a subroutine with no arguments `A' that adds 1.23 to `one'

a subroutine with no arguments `B' that sets `two' to `one+0.7'

a subroutine with no arguments `C' that sets `three' to `one+two'

a subroutine with no arguments `D' that prints the value of `three'

2.2 Write a main program that uses that module and calls `A', `B',`A', `B',`A', `A', `C' and `D'. Compile and test it.

2.3 Change the module to declare the variables PRIVATE, recompile it,and recompile and test the main program.

2.4 Remove the PRIVATE, take out the code for `A', `B', `C' and `D' and

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_08.txt (2 of 11)9/19/2009 4:21:50 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_08.txt

create four other modules, each containing one subroutine. When using theoriginal module, import only the variables that they need. Recompile allmodules.

2.5 Change the main program to import only the modules containing `A',`B', `C' and `D' and not the one containing the variables. Compile andtest it. Note that this shows one way of sharing data betweenprocedures, but not exporting it to users of those procedures.

Specimen Answer---------------

2.1 Code:

MODULE Summer IMPLICIT NONE REAL, SAVE :: one = 0.0, two = 0.0, three = 0.0 CONTAINS SUBROUTINE A IMPLICIT NONE one = one+1.23 END SUBROUTINE A SUBROUTINE B IMPLICIT NONE two = one+0.7 END SUBROUTINE B SUBROUTINE C IMPLICIT NONE three = one+two END SUBROUTINE C SUBROUTINE D IMPLICIT NONE PRINT *, three END SUBROUTINE D END MODULE Summer

2.2 Code:

PROGRAM Main USE Summer IMPLICIT NONE CALL A CALL B

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_08.txt (3 of 11)9/19/2009 4:21:50 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_08.txt

CALL A CALL B CALL A CALL A CALL C CALL D END PROGRAM Main

Results:

8.0799999

2.3 The declaration of the variables becomes:

REAL, SAVE, PRIVATE :: one = 0.0, two = 0.0, three = 0.0

You can't just put a PRIVATE statement, or the procedures becomeprivate, too. You could do the following - check that it works!

PRIVATE REAL, SAVE :: one = 0.0, two = 0.0, three = 0.0 PUBLIC :: a, b, c, d

2.4 Codes:

MODULE Summer IMPLICIT NONE REAL, SAVE :: one = 0.0, two = 0.0, three = 0.0 END MODULE Summer

MODULE Summer_A CONTAINS SUBROUTINE A USE Summer, ONLY : one IMPLICIT NONE one = one+1.23 END SUBROUTINE A END MODULE Summer_A

MODULE Summer_B CONTAINS SUBROUTINE B USE Summer, ONLY : one, two

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_08.txt (4 of 11)9/19/2009 4:21:50 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_08.txt

IMPLICIT NONE two = one+0.7 END SUBROUTINE B END MODULE Summer_B

MODULE Summer_C CONTAINS SUBROUTINE C USE Summer, ONLY : one, two, three IMPLICIT NONE three = one+two END SUBROUTINE C END MODULE Summer_C

MODULE Summer_D CONTAINS SUBROUTINE D USE Summer, ONLY : three IMPLICIT NONE PRINT *, three END SUBROUTINE D END MODULE Summer_D

2.5 Code:

PROGRAM Main USE Summer_A USE Summer_B USE Summer_C USE Summer_D IMPLICIT NONE CALL A CALL B CALL A CALL B CALL A CALL A CALL C CALL D END PROGRAM Main

Question 3

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_08.txt (5 of 11)9/19/2009 4:21:50 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_08.txt

----------

3.1 Compile the file `Programs/double.f90' to create a module. Take thefile `Programs/CubeRoot.f90', and create a separate file out of thefunctions (NOT a module - just the two functions, end-to-end). Compilethat but do not link it.

3.2 Take the rest of the file `Programs/CubeRoot.f90' (i.e. with thefunctions removed) and produce an interface declaration for those twofunctions. Now compile and link that, togther with the compiled code ofthe functions, and test it.

Specimen Answer---------------

3.1 Code:

FUNCTION value (arg, targ) USE double IMPLICIT NONE REAL(KIND=DP) :: value, arg, targ value = arg**3-targ END FUNCTION value

FUNCTION derivative (arg) USE double IMPLICIT NONE REAL(KIND=DP) :: derivative, arg derivative = 3*arg**2 END FUNCTION derivative

3.2 Code:

PROGRAM Newton USE double IMPLICIT NONE INTERFACE FUNCTION value (arg, targ) USE double IMPLICIT NONE REAL(KIND=DP) :: value, arg, targ END FUNCTION value FUNCTION derivative (arg)

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_08.txt (6 of 11)9/19/2009 4:21:50 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_08.txt

USE double IMPLICIT NONE REAL(KIND=DP) :: derivative, arg END FUNCTION derivative END INTERFACE REAL(KIND=DP) :: target, current REAL(KIND=DP), DIMENSION(5) :: previous INTEGER :: i, kmainloop: DO PRINT *, 'Type in a real number' READ (*, *, IOSTAT=k) target IF (k < 0) THEN STOP ELSEIF (k > 0) THEN PRINT *, 'Some sort of horrible I/O error' STOP ENDIF IF (target .EQ. 0.0_DP) THEN PRINT *, 'The cube root of zero is, er, zero' CYCLE END IF!! This is cheating, but the hardest part of Newton-Raphson solution of! Nth roots is getting the starting value, and doing so properly would! merely be confusing. So use a horrible hack to get an approximation.! current = 1.1*CMPLX(target)**0.3 DO i = 1,5 previous(i) = 0.0_DP END DOloop: DO current = current - &

value(current,target)/derivative(current) PRINT *, current DO i = 1,5 if (current .EQ. previous(i)) EXIT loop END DO DO i = 1,4 previous(i+1) = previous(i) END DO previous(1) = current END DO loop

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_08.txt (7 of 11)9/19/2009 4:21:50 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_08.txt

PRINT *, current**3, current**3.0_DP END DO mainloop END PROGRAM Newton

Question 4----------

This question is easy to code, but tricky to understand. It showswhat is going on with name inheritance. It is very important tounderstand the `why' and not just observe what happens.

4.1 Compile the file `Programs/double.f90' to create a module. Take`Programs/Cholesky.f90', and put the subroutine `CHOLESK4' into a module`Lapack' in a separate file. Compile that to create a module file.

4.2 Create a main program that contains just the main program from`Programs/Cholesky.f90'and uses module `Lapack'. Compile and link thatand check that it works.

4.3 Remove the `USE double' from the main program, recompile it and testit. What goes wrong and why?

4.4 Move the `USE double' in module `Lapack' from subroutine `CHOLESK4'to immediately after the MODULE statement, recompile it and thenrecompile and test the main program. Why does it work again?

4.5 Now put the `USE double' back into the main program (i.e. undo whatyou did in 4.3), recompile it and test it. Check that it still works.

4.6 Now replace the `USE double' in module `Lapack' by its source form

INTEGER, PARAMETER :: dp = SELECTED_REAL_KIND(12)

Recompile it and then recompile and test the main program. What goeswrong and why? And why did 4.5 work if this didn't?

Specimen Answer---------------

4.1 Code:

MODULE Lapack

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_08.txt (8 of 11)9/19/2009 4:21:50 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_08.txt

CONTAINS

SUBROUTINE CHOLESKY(A) USE double IMPLICIT NONE INTEGER :: J, N REAL(KIND=dp) :: A(:, :), X N = UBOUND(A,1) DO J = 1, N X = SQRT(A(J,J)-DOT_PRODUCT(A(J, :J-1), A(J, :J-1))) A(J,J) = X IF (J < N) & A(J+1:, J) = (A(J+1:, J) - & MATMUL(A(J+1:, :J-1), A(J,: J-1))) / X ENDDO END SUBROUTINE CHOLESKY END MODULE Lapack

4.2 Code:

PROGRAM MAIN USE double USE Lapack IMPLICIT NONE REAL(KIND=dp), DIMENSION(5, 5) :: A = 0.0 REAL(KIND=dp), DIMENSION(5) :: Z INTEGER :: I, N DO N = 1,10 CALL RANDOM_NUMBER(Z) DO I = 1,5 A(:, I) = A(:, I) + Z*Z(I) END DO END DO WRITE (*,'(5(1X,5F10.6/))') A CALL CHOLESKY(A) DO I = 1,5 A(:I-1,I) = 0.0 END DO WRITE (*, '(5(1X,5F10.6/))') A WRITE (*, '(5(1X,5F10.6/))') MATMUL(A, TRANSPOSE(A)) END PROGRAM MAIN

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_08.txt (9 of 11)9/19/2009 4:21:50 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_08.txt

Results:

2.883802 2.829877 1.923918 2.635450 2.466341 2.829877 4.155829 2.785000 3.820228 3.064393 1.923918 2.785000 2.997863 2.877412 2.509375 2.635450 3.820228 2.877412 4.852614 3.607078 2.466341 3.064393 2.509375 3.607078 3.264468 1.698176 1.666421 1.132932 1.551930 1.452347 0.000000 1.174252 0.763940 1.050932 0.548580 0.000000 0.000000 1.063355 0.297485 0.418377 0.000000 0.000000 0.000000 1.118558 0.583033 0.000000 0.000000 0.000000 0.000000 0.582452 2.883802 2.829877 1.923918 2.635450 2.466341 2.829877 4.155829 2.785000 3.820228 3.064393 1.923918 2.785000 2.997863 2.877412 2.509375 2.635450 3.820228 2.877412 4.852614 3.607078 2.466341 3.064393 2.509375 3.607078 3.264468

4.3 It objects that symbol DP has not been declared. This is because ithas not been declared in module `Lapack' with module scope.

4.4 Because `dp' is now exported from `Lapack' and so is availablefor use by the main program.

4.5 See 4.6.

4.6 It objects that symbol `dp' is found both in module `double' and inmodule 'Lapack'. 4ou can't import two different symbols of the samename, even if they are functionally identical.

The reason that 4.5 worked is that it is the same symbol. Importinga name from a module doesn't create a new instance of a symbol, ora new variable.

Question 5----------

This question is easy to code, but tricky to understand. It shows whatis going on with name inheritance and PRIVATE. It is very important to

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_08.txt (10 of 11)9/19/2009 4:21:50 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_08.txt

understand the `why' and not just observe what happens.

5.1 Restart question 4 at 4.4, but declare `dp' as `PRIVATE'. I.e.the module now starts:

MODULE Lapack USE double PRIVATE :: dp

and the main program does NOT have a `USE double'. Why does this notwork when 4.4 did?

5.2 Now put the `USE double' back into the main program. Check that itnow works again. Why is this?

5.3 Now replace the `USE double' in module `Lapack' by its source form

INTEGER, PARAMETER :: dp = SELECTED_REAL_KIND(12)

Recompile it and then recompile and test the main program. Why doesthis work if 4.6 didn't?

Answers:

5.1 Because `dp' is now PRIVATE, it is not exported from `Lapack' andso not imported into the main program.

5.2 Because the main program now imports `dp' directly from module`double' and not at all from module `Lapack'.

5.3 Because `dp' is now PRIVATE, it is not exported from `Lapack' and sonot imported into the main program. Care should be taken doing thissort of thing, because the declarations of `dp' had better befunctionally identical or chaos will ensue.

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_08.txt (11 of 11)9/19/2009 4:21:50 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_09.txt

Introduction to Programming with Fortran----------------------------------------

Practical Exercise 09: Solutions--------------------------------

Question 1----------

1.1 Write a module that defines a derived type My_complex containing twoINTEGERs (note), and contains a function to add two My_complex values(as if they were complex numbers) and return the result.

1.2 Write a program to define two My_complex variables, set them to(123, 456) and (432, 876) using constructors, copy the first one toa third variable, and print out the value of that.

1.3 Extend the program to create a fourth variable by multiplying thesecond variable by -i (i.e. reversing the order of its components) andprint out the value of the sum of the first third and fourth variablesby calling the module's function. Save the source of the program andmodule.

Specimen Answer---------------

1.1 Code:

MODULE Demo IMPLICIT NONE TYPE My_complex INTEGER :: real, imaginary END TYPE My_complex

CONTAINS

PURE FUNCTION add (X, Y) IMPLICIT NONE TYPE(My_complex) :: add TYPE(My_complex), INTENT(IN) :: X, Y

add%real = X%real+Y%real

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_09.txt (1 of 5)9/19/2009 4:21:50 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_09.txt

add%imaginary = X%imaginary+Y%imaginary END FUNCTION add

END MODULE Demo

1.2 Code:

PROGRAM Run USE Demo IMPLICIT NONE TYPE(My_complex) :: one = My_complex(123, 456), & two = My_complex(432, 876), three

three = one WRITE (*, '("( ", I0, " , ", I0, " )")') three END PROGRAM Run

Results:

( 123 , 456 )

1.3 Code:

PROGRAM Run USE Demo IMPLICIT NONE TYPE(My_complex) :: one = My_complex(123, 456), & two = My_complex(432, 876), three, four

three = one four%imaginary = two%real four%real = two%imaginary WRITE (*, '("( ", I0, " , ", I0, " )")') add(three, four) END PROGRAM Run

Results:

( 999 , 888 )

Question 2----------

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_09.txt (2 of 5)9/19/2009 4:21:50 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_09.txt

2.1 File `Midden.data' contains data in the following format:

'Leechford' 5 13.17 42.62 46.24 5.51 23.23

The first line is a quoted string and an integer, which gives the countof the number of reals on the next line.

Write a module that defines a derived type `Midden' containing aCHARACTER variable of length 16, and an ALLOCATABLE array, andcontains a function and a subroutine.

The function takes an assumed length CHARACTER argument and anassumed shape REAL array and returns a value of type `Midden'.

The subroutine takes a value of type Midden and prints its contents(you need not quote the string). If the name and array are bothnull, it prints a message saying so.

2.2 Write a program to allocate an array of type `Midden', read in`Midden.data' and call the function to initialise it, and then thesubroutine to print it. You may assume that there are never more than100 real values per entry. Unused elements should be set to a `Midden'with a null name and empty array. Save the source of the program andmodule.

Specimen Answer---------------

2.1 Code:

MODULE Midden_mod IMPLICIT NONE TYPE Midden CHARACTER(LEN=16) :: location REAL, DIMENSION(:), ALLOCATABLE :: data END TYPE Midden

CONTAINS

PURE FUNCTION create (name, values) IMPLICIT NONE TYPE(Midden) :: create

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_09.txt (3 of 5)9/19/2009 4:21:50 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_09.txt

CHARACTER(LEN=*), INTENT(IN) :: name REAL, DIMENSION(:), INTENT(IN) :: values

create%location = name ALLOCATE(create%data(1:UBOUND(values, 1))) create%data = values END FUNCTION create

SUBROUTINE print (entry) IMPLICIT NONE TYPE(Midden) :: entry

IF (entry%location /= '' .OR. UBOUND(entry%data, 1) > 0) THEN PRINT *, entry%location, entry%data ELSE PRINT *, 'Null entry' ENDIF END SUBROUTINE print

END MODULE Midden_mod

2.2 Code:

PROGRAM Run USE Midden_mod IMPLICIT NONE TYPE(Midden), DIMENSION(10) :: data CHARACTER(LEN=25) :: name REAL, DIMENSION(100) :: temp INTEGER :: K, N, err LOGICAL :: OK = .True. OPEN (10, FILE='Midden.data') DO N = 1, 10 IF (OK) READ (10, *, IOSTAT=err) name, K, temp(:K) IF (err /= 0) OK = .False. IF (OK) THEN data(N) = create(name, temp(:K)) ELSE data(N) = create('', temp(:0)) ENDIF ENDDO CLOSE (10)

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_09.txt (4 of 5)9/19/2009 4:21:50 AM

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_09.txt

DO N = 1, 10 CALL print(data(N)) ENDDO END PROGRAM Run

Note that the exception handling in the I/O is not best practice.

Results:

Leechford 13.1700001 42.6199989 46.2400017 5.5100002 23.2299995 Much Wittering 60.0699997 54.9399986 0.5800000 50.7700005 98.5899963 72.3099976 23.2199993 34.8800011 Trollbridge 9.5100002 61.6399994 44.0499992 35.9900017 Nether Wallop 38.3300018 28.0599995 82.3399963 1.7800000 1.1700000 51.0299988 43.6100006 Loose Chippings 0.4200000 74.9899979 73.3099976 Null entry Null entry Null entry Null entry Null entry

Question 3----------

Add PRIVATE to hide the components of the derived type used in question2 and check that the program and module still work. Do so to the oneused in question 1 and see what fails.

Answer:

The compiler objects to both the use of a constructor and accessing thecomponents (i.e. using `%'), but not to the simple assignment. Derivedtypes with private components are most simply treated as purely opaquetypes.

file:///C|/Documents%20and%20Settings/kawa/Desktop/fortran/solutions_09.txt (5 of 5)9/19/2009 4:21:50 AM


Recommended