computational physics icphaskell

71
Introduction to Computational Physics Scott N. Walck April 23, 2012 Contents 1 The Haskell Programming Language 3 2 Using GHCi as a Calculator 4 3 Types and Functions 6 3.1 Constants, Functions, and Types ................ 6 3.2 How we talk about Functions .................. 8 3.3 Functions with Parameters .................... 10 4 Lists 12 5 Quick Plotting 13 6 Types and Literals 15 7 Tuples 19 7.1 Pairs ................................ 19 7.2 Functions of two variables .................... 21 8 List Comprehensions 22 9 Presentation Plotting 23 9.1 Title and Axis Labels ....................... 23 9.2 Other Labels ........................... 24 9.3 Printing .............................. 24 9.3.1 Filling an entire page ................... 24 1

Upload: alberto-gomez-corona

Post on 08-Nov-2014

82 views

Category:

Documents


2 download

DESCRIPTION

Computational Physics in Haskell

TRANSCRIPT

Page 1: Computational Physics IcpHaskell

Introduction to Computational Physics

Scott N. Walck

April 23, 2012

Contents

1 The Haskell Programming Language 3

2 Using GHCi as a Calculator 4

3 Types and Functions 6

3.1 Constants, Functions, and Types . . . . . . . . . . . . . . . . 63.2 How we talk about Functions . . . . . . . . . . . . . . . . . . 83.3 Functions with Parameters . . . . . . . . . . . . . . . . . . . . 10

4 Lists 12

5 Quick Plotting 13

6 Types and Literals 15

7 Tuples 19

7.1 Pairs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197.2 Functions of two variables . . . . . . . . . . . . . . . . . . . . 21

8 List Comprehensions 22

9 Presentation Plotting 23

9.1 Title and Axis Labels . . . . . . . . . . . . . . . . . . . . . . . 239.2 Other Labels . . . . . . . . . . . . . . . . . . . . . . . . . . . 249.3 Printing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

9.3.1 Filling an entire page . . . . . . . . . . . . . . . . . . . 24

1

Page 2: Computational Physics IcpHaskell

9.3.2 Making a graph to include in another document . . . . 259.4 Plotting Data . . . . . . . . . . . . . . . . . . . . . . . . . . . 269.5 Multiple Curves on One Set of Axes . . . . . . . . . . . . . . . 269.6 Controlling the Plot Ranges . . . . . . . . . . . . . . . . . . . 27

10 Good Coding Practice 28

10.1 Give Every Function a Type Signature . . . . . . . . . . . . . 2810.2 Put Comments in your Code . . . . . . . . . . . . . . . . . . . 2810.3 Put information in one place . . . . . . . . . . . . . . . . . . . 3110.4 Write modular code . . . . . . . . . . . . . . . . . . . . . . . . 3110.5 Use types that reflect the way you think about the problem . . 31

11 Euler Method for First-Order Differential Equations 32

11.1 Why is Newton’s second law a second-order differential equation? 3211.2 Euler Method . . . . . . . . . . . . . . . . . . . . . . . . . . . 33

12 Mechanics in One Dimension 38

12.1 Basic Setup . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3812.2 Euler Method for Second-Order Differential Equations . . . . 3912.3 Units . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42

13 Air Resistance 43

13.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4313.2 Collision Model . . . . . . . . . . . . . . . . . . . . . . . . . . 43

14 Improvements to the Euler Method 44

14.1 Euler-Cromer Method for Second-Order Differential Equations 44

15 Mechanics in Three Dimensions 46

15.1 Vectors in Haskell . . . . . . . . . . . . . . . . . . . . . . . . . 4615.2 Euler Method with Vectors . . . . . . . . . . . . . . . . . . . . 49

16 Animation with Gloss 52

17 Multiple Objects in Three Dimensions 54

18 Waves on a Flexible String 55

2

Page 3: Computational Physics IcpHaskell

19 Numerical Integration 57

19.1 The Trapezoidal Rule . . . . . . . . . . . . . . . . . . . . . . . 57

20 Abstract Vectors 60

21 Electric Field produced by a Line Segment of Charge 61

22 Magnetic Field of a Circular Current Loop 63

23 Free Particle in Quantum Mechanics 64

24 Animation 66

24.1 Color . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6724.2 Material . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67

25 Root Finding 69

26 Quantum Mechanics 69

26.1 The Finite Square Well . . . . . . . . . . . . . . . . . . . . . . 69

1 The Haskell Programming Language

In this course, we will use the Haskell programming language to describecalculations that we want the computer to do for us. Haskell is a lovely, deeplanguage, and we will use only a small subset of the language. Studying thelanguage and using it for physics will clarify your thinking and make you asmarter person.

Haskell is a functional programming language, meaning that computationsare built out of functions. It encourages a style of programming that is quitedifferent from “imperative” languages like C, C++, Java, Python, and others.As there are no programming prerequisites for this course, we will not spendany more time comparing Haskell to other programming languages. We willjust jump in and start learning Haskell.

The Haskell compiler that we will use in this course is the Glasgow HaskellCompiler (GHC). There is an interactive version of the compiler that will beof great use to us called GHCi. We begin by exploring some basic things wecan do with GHCi.

3

Page 4: Computational Physics IcpHaskell

2 Using GHCi as a Calculator

In these notes, I assume that you are using the GNU/Linux operating system,and that you have access to a “shell prompt” in a terminal window. Aterminal window is simply a window on the computer into which you cantype commands, and a shell prompt is the character (usually % or # or $)that sits just before the place where you type. We will use % to indicate theshell prompt in these notes.

To start GHCi, open up a terminal window and simply type ghci.

% ghci

When you do this, the GHCi program starts (GHCi is the interactiveversion of the Glasgow Haskell Compiler), and gives you a GHCi prompt.The first prompt you get from GHCi is

Prelude>

This prompt changes as you do different things. To make things simplerin this exposition, we will write the GHCi prompt as

ghci>

GHCi is now waiting for you to type something. You can use GHCi as acalculator. Try this. (You just type the 2/3.)

ghci> 2/3

GHCi has built-in functions to do many of the things that you expectcalculators to be able to do.

ghci> log(2)

This is the natural logarithm.Actually, the Haskell language does not need parentheses to apply a func-

tion, so we can type the following.

ghci> log 2

GHCi knows π.

ghci> pi

4

Page 5: Computational Physics IcpHaskell

Here is a trigonometric function.

ghci> cos pi

Notice that GHCi assumes the argument is expressed in radians.How about this?

ghci> cos pi/2

What is cos π2? Can you picture the graph of cosine in your head? Always

carry the graph of cosine in your head. The computer did not give us whatwe expect here. The reason is that function application in Haskell has higherprecedence than division, so Haskell interprets what we typed as

(cos pi)/2

rather than dividing π by two first and then taking the cosine. We can getwhat we want by supplying parentheses.

ghci> cos (pi/2)

Is the result the computer gave cos π2? Not exactly. Here we see an example

of an approximately computed result. My computer gave something times10−17, which is as close to zero as the computer can get here. It’s good toremember that the computer (like your calculator) is not giving us exactresults most of the time. It is giving us approximate results. We need tobe vigilant in making sure that the results it gives are valuable to us byinterpreting them correctly.

To learn more about the Haskell programming language (of which GHCiis a popular implementation), you can visit the web site

http://www.haskell.org/

The haskell.org web site has links to a number of online and paper sourcesfor learning the language. Some particularly good ones are Learn You a

Haskell for Great Good

http://learnyouahaskell.com/

and Real World Haskell

http://book.realworldhaskell.org/

5

Page 6: Computational Physics IcpHaskell

To leave GHCi and return to the shell prompt, type :quit.

ghci> :quit

Commands that start with a colon do not belong to the Haskell program-ming language proper, but rather to the GHCi interactive compiler. We willsee more of these commands that start with colons later. You can use :q asshorthand for :quit.

3 Types and Functions

Programming in Haskell is a process of defining functions that express tothe computer how to calculate something we want. There is a way to definefunctions inside GHCi, but since most functions that we define we will wantto use again another day, it is better to define our functions in a file, andload that file into GHCi.

We need a text editor to create such a file. My favorite text editor isGNU Emacs. If you have a different editor that you like, you are welcometo use it. From a terminal window (the % symbol below represents the shellprompt), type emacs &.

% emacs &

The & character tells the operating system to run Emacs in the back-ground, so that it won’t tie up the terminal window and you can still typeother commands there.

3.1 Constants, Functions, and Types

Using a text editor, create a file named first.hs for your first program.(The .hs extension indicates a Haskell program.) Put the following lines inthe file.

e :: Double

e = exp 1

square :: Double -> Double

square x = x**2

6

Page 7: Computational Physics IcpHaskell

This program file defines a constant and a function. The first two linesof the file define the constant e, the base of natural logarithms. Unlike π,GHCi does not define e for us by default. This is an example of how we candefine a constant for ourselves. The first line,

e :: Double

declares the type of e to be Double. A Double is an approximation to a realnumber, sometimes called a floating point number. The name Double is usedfor historical reasons to mean a double precision floating point number. Thistype of number is capable of about 15 decimal digits of precision, comparedwith single precision numbers that are capable of about 7 decimal digitsof precision. The difference for the computer is the number of bits usedto represent the number inside the computer. Haskell has a type Float forsingle precision numbers. Unless there is a compelling reason to do otherwise,we will always use type Double for our floating point numbers.

In addition to Double, there are a number of other types that we mightwant to use. Haskell has a type Int for small integers (up to at least a fewbillion), and a type Integer for arbitrary size integers.

Let’s get back to our first.hs program file. As we said above, the firstline of the file declares the type of the name e to be Double. This kind ofline, with a name followed by a double colon followed by a type, is called atype signature. The second line of the file actually defines e. Here, we usethe built-in function exp applied to the number 1 to produce the constante. Remember that we don’t need parentheses to apply a function to anargument.

Next, we have a type signature for the function square. The type ofsquare is declared to be Double -> Double. A type with an arrow in themiddle is a function type. It says that square is a function that takes aDouble as input and produces a Double as output. The last line defines thefunction square. Note the ** operator used for exponentiation.

To load this program file into GHCi, use GHCi’s :load command.

ghci> :load first.hs

(You can use :l as shorthand for :load.)You now have access to the constants and functions defined in the file.

Let’s try them out.

ghci> e

7

Page 8: Computational Physics IcpHaskell

ghci> square 7

ghci> square e

If you forget or don’t know the type of something, you can ask GHCi forthe type with the :type command (:t for short).

ghci> :type square

Activity: Consider throwing a rock straight upward from the ground at30 m/s. Ignoring air resistance, find an expression y(t) for the height of therock as a function of time.

Add on to your program file first.hs by writing a function

yRock30 :: Double -> Double

that accepts as input the time (after the rock was thrown) in seconds andgives as output the height of the rock in meters.

Activity: Continuing with the rock example, write a function

vRock30 :: Double -> Double

that accepts as input the time (after the rock was thrown) in seconds andgives as output the upward velocity of the rock in meters per second. (Adownward velocity should be returned as a negative number.)

3.2 How we talk about Functions

Suppose we define a function f by f(x) = x2 − 3x + 2. It is common inmathematics and physics to speak of “the function f(x).” Haskell invites usto think a bit more carefully and precisely about this bad habit. (Well, itreally requires us to think more carefully about it, but it’s always nicer to beinvited than required, no?) Instead of saying “the function f(x),” we shouldsay one of the following, depending on what we mean.

• the function f

• the value f(x)

• given a number x, the value of the function f at x

8

Page 9: Computational Physics IcpHaskell

The second and third bullet points are two ways of saying the same thing.The first bullet point is saying something different from the second and third.

What is wrong with saying “the function f(x)?” It is common in math-ematics and physics to use “the function f” and “the function f(x)” inter-changeably, the second expression merely indicating explicitly that f dependson x. We think of mathematical notation as being a precise representation ofan idea, but this is a case where the commonly used notation is not precise.

When we use Haskell we make a trade off. We agree to use languagein a precise and careful way (the compiler is going to check us on this)and in exchange, we will be able to say things in the language that (1) arerather complex, (2) are difficult to say in a language that accommodatesimprecision, and (3) expose the essential structure of a physical theory likeNewtonian mechanics.

One reason for shunning the language “the function f(x)” is that if f(x) =x2 − 3x + 2, then f(y) = y2 − 3y + 2. The letter x really has nothing todo with the function f . Granted, we need some letter to use to make thedefinition, but it doesn’t matter which one.

In Haskell, we say f(x) when we wish to evaluate the function f usingthe input x. We say f when we wish to speak about the function itself,not evaluating it (not giving it any input). What else is there to do witha function except give it an input? Well, you could integrate the functionbetween given limits. You could differentiate the function to obtain anotherfunction. You could, in some cases, apply the function twice. In short, thereare many things we might want to do with a function other than evaluatingit.

Haskell’s type system helps us understand the key distinction between fand f(x). The variable x is a number, so has a type like Double. Now f isa function, so has a type like Double -> Double. Finally, f(x) means thefunction f evaluated at the number x, so f(x) has type Double. Things thathave type Double -> Double are functions. Things that have type Double

are values (or numbers). The table below summarizes these distinctions.

Math notation Haskell notation Haskell typef f Double -> Double

f(3) f 3 Double

f(x) f x Double

Computers are notorious for being inflexible in understanding what a per-son means. Computers look at exactly what you said, and give warnings and

9

Page 10: Computational Physics IcpHaskell

errors if your input doesn’t meet its requirements for format and interpreta-tion. Much of the time, this is a pain in the neck. We would like to have anassistant that understanding what we mean, and does what we want.

In the case of types and functions, however, Haskell’s inflexibility is agreat teaching aid. Haskell is helping us to organize our thinking, so that wewill be prepared to do more complex things in a structured and organizedway. Section 3.3 on higher-order functions is an example of how carefulthinking about types and functions allows us to encode more complex ideassimply and easily.

3.3 Functions with Parameters

Consider the force of a linear spring with spring constant k. We usually writethis as

Fspring = −kx

where the negative sign indicates that the force acts in the direction oppositethe displacement.

Suppose we wish to write a Haskell function to give the force in Newtonsproduced by a spring with spring constant 5,500 N/m. We could write

springForce5500 :: Double -> Double

springForce5500 x = -5500 * x

This is a fine function, but it only handles the force produced by a springwith a spring constant of 5500 N/m. It would be nicer to have a functionthat could handle a spring with any spring constant. Consider this function.

springForce :: Double -> Double -> Double

springForce k x = -k * x

Take a look at the type for this function: Double -> Double -> Double

This is equivalent to

Double -> (Double -> Double)

meaning that if we send the springForce function a Double (the springconstant), it will return to us a function with type Double -> Double. Thislatter function wants a Double as input (the position), and will give a Doubleas output (the force).

10

Page 11: Computational Physics IcpHaskell

We can look at the types of these functions using GHCi’s :type command.Assuming that we have defined the springForce function in our first.hsfile, try the following.

ghci> :l first.hs

ghci> :t springForce

The springForce function should have type Double -> Double -> Double.Next, let’s look at the function springForce 2200.

ghci> :t springForce 2200

This should have type Double -> Double. The function springForce 2200

represents the force function (input: position, output: force) for a springwith spring constant 2200 N/m. Finally, look at the type of springForce2200 0.4.

ghci> :t springForce 2200 0.4

This is not a function, but just a Double, representing the force exerted by aspring with spring constant 2200 N/m when extended by a distance of 0.4 m.

The function springForce is called a higher-order function, because itreturns a function as its result. In Haskell, we can also make higher-orderfunctions that accept a function as input. We will see examples of this in thenot-too-distant future.

Higher-order functions give us a convenient way to define a function thattakes one or more parameters (like the spring constant) in addition to its“actual” input parameters (like the distance).

Activity: Let us return to the example of throwing a rock straight upward.Perhaps we don’t want to throw it upward at 30 m/s, but would like to beable to throw it upward with whatever initial velocity we choose. Write afunction

yRock :: Double -> Double -> Double

that takes as input an initial velocity and returns as output a function thattakes as input a time and returns as output a height. Also, write a function

vRock :: Double -> Double -> Double

that takes as input an initial velocity and returns as output a function thattakes as input a time and returns as output a velocity.

11

Page 12: Computational Physics IcpHaskell

4 Lists

A very important data type in Haskell is the list. Here is one example of alist.

velocities :: [Double]

velocities = [0,-9.8,-19.6,-29.4]

The type [Double] indicates that velocities is a list of Doubles. Squarebrackets denote the list. A list with type [Double] can have any number ofitems (including zero), but each item must have type Double.

There are some convenient shortcuts to making certain kinds of lists.

ns :: [Int]

ns = [0..10]

The list ns contains the integers from 0 to 10. I chose the name ns becauseit looks like the plural of the name n, which seems like a good name for aninteger. It is a common style in Haskell programs to use names that end ins for lists, but it is by no means necessary.

Let’s play with lists in GHCi.

ghci> [0,2,5]

If we give GHCi a list, it gives it back to us.

ghci> [0..10]

Here we see that GHCi expands this list out for us. Now, we didn’t giveGHCi any type information about the previous list. Let’s ask GHCi whattype it assigned.

ghci> :t it

The identifier it refers to the last expression that GHCi evaluated. Mycomputer reports [Integer] for the list [0..10], indicating that GHCi chosethe type Integer for these integers, rather than Int, which I chose above.(The only difference is that an Integer can be arbitrarily large, while anInt is faster and takes up less space, as long as the integer is smaller than afew billion.)

Here’s another shortcut.

12

Page 13: Computational Physics IcpHaskell

ghci> [-5,-4.5..5]

If I ask for the type,

ghci> :t it

I get [Double].You can even do a decreasing list.

ghci> [10,9.5..0]

The empty list is denoted [].For any type (Int, Integer, Double, etc.) you can make a list of things

with that type. You can even make a list of functions. If your yRock30 andyRock functions are in the same program file, you could define the followinglist.

funcs :: [Double -> Double]

funcs = [cos,yRock30,sin,yRock 20]

Why would you want a list of functions? That is an excellent questionthat we will come back to later.

5 Quick Plotting

There are times when you want to make a quick plot to see what a functionlooks like. Here is an example of how to do this using GHCi.

ghci> :m Graphics.Gnuplot.Simple

ghci> plotFunc [] [0,0.1..10] cos

The first command loads a graphics module that can make graphs. (TheGHCi command :m is short for :module, which loads a module of predefinedfunctions.) The second command plots the function cos from 0 to 10 inincrements of 0.1. This is carried out by the plotFunc function, which isone of the functions loaded in the Graphics.Gnuplot.Simple module. TheplotFunc function takes a list of attributes (in this case, the empty list []),a list of values at which to compute the function (in this case, [0,0.1..10],which is a list of 101 numbers from 0 to 10 in increments of 0.1), and afunction to plot (in this case, cos).

13

Page 14: Computational Physics IcpHaskell

A hundred points is usually enough points to get a nice smooth graph. Ifit’s not smooth enough for you, you could use 500 points or more. If you useonly 4 points, you won’t get a smooth graph (try it and see what happens).You can press the key q to make the plot window disappear.

In a later section, we’ll learn how to make a nice plot with a title andaxis labels for a presentation or an assignment.

Activity: Make a plot of sin(x) from x = −10 to x = 10. You do not needto hand this in, but please show me that you have done it.

If you wish to plot a function that is defined in a program file, you havea few choices.

Method 1: Put only the function to be plotted in the program file.

Suppose, for example, we want to plot the square function that we definedin our first.hs program file from x = −3 to x = 3. We could issue thefollowing sequence of commands.

ghci> :m Graphics.Gnuplot.Simple

ghci> :l first.hs

ghci> plotFunc [] [-3,-2.99..3] square

Method 2: Use the program file to define the function to be plotted

and to load the graphing module.

If we know that a program file contains a function or functions that we willwant to plot, we can import the Graphics.Gnuplot.Simple module in theprogram file so that we don’t have to do it at the GHCi command line.Instead of typing the :m Graphics.Gnuplot.Simple line into GHCi, we canput the following line at the top of our program file.

import Graphics.Gnuplot.Simple

Now in GHCi we do

ghci> :l first.hs

ghci> plotFunc [] [-3,-2.99..3] square

14

Page 15: Computational Physics IcpHaskell

Method 3: Use the program file to load the graphing module, to

define the function to be plotted, and to define the plot.

If we know in advance what plot we want, we can include the plotting com-mands in the program file itself. In our program file, we can define the plot

plot1 = plotFunc [] [-3,-2.99..3] square

Now to make our plot, we only need to issue the following commands inGHCi.

ghci> :l first.hs

ghci> plot1

Activity: Make a plot of your yRock30 function from t = 0 to t = 6 s. Youdo not need to hand this in. Please show me that you have done it.

Activity: Make a plot of your yRock 20 function from t = 0 to t = 4 s.You will need to enclose yRock 20 in parentheses when you use it as anargument to plotFunc. You do not need to hand this in. Please show methat you have done it.

6 Types and Literals

Haskell is an extremely powerful programming language, in the sense that itgives an amazing amount of expressiveness and control to the programmerwho has mastered the language. As with most powerful tools, this extremepower comes at a cost of making the language harder to learn and moreconfusing for the beginner. In this section, we will talk briefly about someissues that are not our main interest (because we do not have time in thiscourse to learn the full power of the language), but which we will inevitablystumble upon sooner or later.

Let us begin by asking GHCi about the type of the number 4.

ghci> :t 4

The number 4 is an example of a literal expression in Haskell. This is indistinction from an expression composed of one or more names, or identifiers,such as e, square, or yRock. It would be entirely reasonable to expect thetype of the number 4 to be Int or Integer. But the designers of the Haskell

15

Page 16: Computational Physics IcpHaskell

language wanted a number like 4 to be able to be an Int, an Integer, aDouble, or even a few other types, depending on the programmer’s needs.For this reason (and other, more compelling reasons), they invented the ideaof type classes. A type class is like a club that a type can belong to. Whenyou ask GHCi for the type of the number 4, it says the following.

4 :: (Num t) => t

This says that the number 4 can have any type t as long as t belongs to thetype class Num (short for number). The letter t is a type variable in this typesignature. It can stand for any type. The stuff to the left of => are type classconstraints. In the type signature above, there is one type class constraint,Num t. This says that t must belong to type class Num.

The types Int, Integer, and Double are all instances (which is to saymembers) of the type class Num. So, the line 4 :: (Num t) => t can beread “as long as t is an instance of type class Num, the item 4 has type t.”

Basically, GHCi hasn’t committed to a particular type for the number 4yet. But this noncommittal attitude about the type of 4 can’t go on forever.At some point, the Haskell compiler will demand that every item have a well-defined type. The lack of a well-defined type for something can be a sourceof trouble. GHCi has some type-defaulting rules to make our life easier. Forexample, if you put the line

x = 4

into a program file (with a .hs extension), giving x no type signature, loadit into GHCi, and then ask for the type of x, GHCi will tell you that x hastype Integer. So, here GHCi has committed to a particular type withoutour specifying the type.

There are other situations, and you will come across them soon enough,where GHCi feels unable to assign a type, and you will need to help it out.As an example, create a new program file called typeTrouble.hs with thefollowing code.

import Graphics.Gnuplot.Simple

plot1 = plotFunc [] [0,0.01..10] cos

When I try to load this file into GHCi, I get the following horrible-lookingerror message.

16

Page 17: Computational Physics IcpHaskell

typeTrouble.hs:3:8:

Ambiguous type variable ‘t’ in the constraints:

‘Graphics.Gnuplot.Value.Tuple.C t’

arising from a use of ‘plotFunc’ at typeTrouble.hs:3:8-35

‘Graphics.Gnuplot.Value.Atom.C t’

arising from a use of ‘plotFunc’ at typeTrouble.hs:3:8-35

‘Floating t’ arising from a use of ‘cos’ at typeTrouble.hs:3:33-35

‘Enum t’

arising from the arithmetic sequence ‘0, 1.0e-2 .. 10’

at typeTrouble.hs:3:20-31

Probable fix: add a type signature that fixes these type variable(s)

First of all, don’t panic. This error message contains much more informationthan we need to solve the problem. The most useful parts of the message arethe first and last lines. The first line tells where the problem is in the code(line 3, column 8). At line 3, column 8 of our code is the function plotFunc.Let’s look at the type of plotFunc.

ghci> :t plotFunc

Hmmm. Life just got worse. I get an error like this.

<interactive>:1:0: Not in scope: ‘plotFunc’

Now, this latter error is an easy one. “Not in scope” means that GHCiclaims no knowledge of this function. That makes sense, actually, becauseit’s not included in the Prelude (the collection of built-in functions that areloaded automatically when we start up GHCi), and GHCi refused to load ourtypeTrouble.hs file because it had a problem with it. So, at the moment, ithas no knowledge of plotFunc. Function plotFunc is defined in the moduleGraphics.Gnuplot.Simple. We can get access to plotFunc by loading theplotting module manually, like we first did to make a quick plot.

ghci> :m Graphics.Gnuplot.Simple

Now, let’s ask again for the type of plotFunc

ghci> :t plotFunc

Here’s what I get.

17

Page 18: Computational Physics IcpHaskell

plotFunc

:: (Graphics.Gnuplot.Value.Atom.C a,

Graphics.Gnuplot.Value.Tuple.C a) =>

[Attribute] -> [a] -> (a -> a) -> IO ()

There are a couple of type class constraints to the left of the =>. I don’tknow what those type classes are, but as long as a (a type variable) belongsto those two type classes, the type of plotFunc is

[Attribute] -> [a] -> (a -> a) -> IO ()

In other words, plotFunc needs a list of Attributes (we have given an emptylist in our examples so far), a list of as, and a function that takes an a asinput and gives back an a as output. If we give plotFunc all this stuff, itwill give us back an IO (), which is a way of saying that it will actually do

something for us (make a plot). Now, we would be perfectly happy if thetype of plotFunc was

[Attribute] -> [Double] -> (Double -> Double) -> IO ()

without those crazy type class constraints.Let’s return to the horrible-looking error message and focus on the last

line.

Probable fix: add a type signature that fixes these type variable(s)

This tells us that the Haskell compiler would like more help figuring out thetypes of things. In particular, it can’t figure out the types of [0,0.01..10]and cos. Let’s ask GHCi about the types of these two.

ghci> :t [0,0.01..10]

I get

[0,0.01..10] :: (Fractional t, Enum t) => [t]

containing more type class gobbledygook. For

ghci> :t cos

I get

cos :: (Floating a) => a -> a

18

Page 19: Computational Physics IcpHaskell

which also is type-class-constraint-laden.One solution to the problem is to give the list [0,0.01..10] a name and

a type signature. Make a program file typeTrouble2.hs with the followinglines.

import Graphics.Gnuplot.Simple

xRange :: [Double]

xRange = [0,0.01..10]

plot2 = plotFunc [] xRange cos

This program file should load fine and give you a nice plot when you typeplot2. Try it and see.

Another solution is to specify the type of the list [0,0.01..10] on the linewhere it’s used. Make a program file typeTrouble3.hs with the followinglines.

import Graphics.Gnuplot.Simple

plot3 = plotFunc [] ([0,0.01..10] :: [Double]) cos

Yet another solution is to tell the compiler that the final element of thelist, 10, has type Double. This implies that all of the elements in the listhave type Double.

import Graphics.Gnuplot.Simple

plot4 = plotFunc [] [0,0.01..10 :: Double] cos

The moral of the story is that you should include type signatures for allof the functions you define, and you should be prepared to add more typesignatures if the compiler complains.

7 Tuples

7.1 Pairs

Another important data type in Haskell is the tuple. The simplest tuple isthe pair. A pair is just a combination of two values that already have types.

Here is a simple, but not very useful, example.

19

Page 20: Computational Physics IcpHaskell

pr :: (Integer,Double)

pr = (4, -6.7)

You see that the first component of a pair needs to have a well-definedtype, and the second component of a pair also needs a type, but they neednot be the same type.

Let’s write a function pythag1 that computes the hypotenuse of a righttriangle from the lengths of the two sides. We’ll pass the two side lengths tothe function using a pair. Here is one way to write this function.

pythag1 :: (Double,Double) -> Double

pythag1 (a,b) = sqrt (a**2 + b**2)

The type signature above shows us that pythag1 expects a pair of twoDoubles as input, and produces a Double as output.

There are a couple of built-in functions (made available in the Prelude)to deal with pairs. The fst function takes a pair as input and returns thefirst component of the pair as output. The snd function takes a pair as inputand returns the second component of the pair as output. We can test thisbehavior in GHCi.

ghci> fst (4,7.8)

These two helper functions allow us to write an alternative version of pythag1that does the same thing.

pythag1’ :: (Double,Double) -> Double

pythag1’ pr = sqrt ((fst pr)**2 + (snd pr)**2)

Activity: Write a function

polarToCart :: (Double,Double) -> (Double,Double)

that takes as input polar coordinates (r, θ), with θ in radians, and returns asoutput a pair (x, y) of Cartesian coordinates. Put a copy of this short codein my drop box. If your name is Elvis, please call the file something likeElvisPolarToCart.hs.

In addition to pairs, you can make triples, or tuples with even morecomponents.

20

Page 21: Computational Physics IcpHaskell

7.2 Functions of two variables

All Haskell functions have one input and one output. How then could wewrite a function of two variables, like

f(x, y) =√

x2 + y2?

There are two ways to do this. One way is to use a tuple (a pair) as theinput.

f :: (Double,Double) -> Double

f (x,y) = sqrt (x**2 + y**2)

Haskell regards a tuple as one thing, so Haskell thinks that the function f

has one input (a (Double,Double)) and one output (a Double). Let’s callthis the tuple form of a function of two variables.

A second way to make a function of two variables is to use the ideas fromSection 3.3. In this way, we would encode the function

g(x, y) =√

x2 + y2

as

g :: Double -> Double -> Double

g x y = sqrt (x**2 + y**2)

In this case, Haskell thinks that the one input to g is a Double, and that theone output of g is a Double -> Double (that is, a function from Double toDouble). But you can think of g as a function of two variables, that acceptstwo Doubles and returns a Double. Let’s call this the curried form of afunction of two variables.

These two ways of encoding a function of two variables (the tuple formand the curried form) are mutually exclusive. You need to pick one or theother for a particular function; you can’t use both. Notice that the tupleform requires the use of parentheses and a comma around the two arguments.That’s because you need to have a tuple as input! Notice that the curriedform has no parentheses and no comma. It’s not that the comma is optional;it must not be present.

Sometimes you might use one form, and realize later on that you wish youhad used the other form. Haskell provides two functions to let you convertfrom one form to the other and back. To convert from tuple form to curried

21

Page 22: Computational Physics IcpHaskell

form, Haskell provides the function curry. We could write curry f and thiswould be exactly the same function as the g that we defined above. We canalso write uncurry g, and this is the same as the function f. It does notmake sense to write curry g or uncurry f; these constructions will producetype errors when the compiler tries to read them.

Take a look at the types for curry and uncurry. They might look likenonsense the first time you see them, but it’s worth spending time to under-stand why they have the types they have. See if you can explain to yourselfwhy they have the types they do.

8 List Comprehensions

Haskell offers a powerful way to make new lists out of old lists. Suppose youhave a list of times (in seconds) and you want to have a list of positions fora rock that you threw up in the air at 30 m/s, each position correspondingto one of the times in the original list. You could do the following.

ts :: [Double]

ts = [0,0.1..6]

xs :: [Double]

xs = [yRock30 t | t <- ts]

The expression [yRock30 t | t <- ts] is an example of a list comprehen-

sion. It says that for each t in ts, it will compute yRock30 t and form alist of the resulting values. The list xs of positions will be the same lengthas the original list ts of times.

We will find use for the list comprehension in forming lists of pairs (x, y) ofnumbers we want to plot. In the next section, we will meet a plotting functionplotPath that takes as input a list of pairs of numbers (for us, usually[(Double,Double)]) and produces a plot. We can use list comprehensionsto transform our data into a form suitable for plotting. If we wanted to plotposition as a function of time, we could form a list of time-position pairs asfollows.

ts :: [Double]

ts = [0,0.1..6]

22

Page 23: Computational Physics IcpHaskell

txPairs :: [(Double,Double)]

txPairs = [(t,yRock30 t) | t <- ts]

9 Presentation Plotting

When you make a graph for a formal report, you want to have titles, axislabels, and perhaps other features that will help the reader understand whatyou are trying to say.

9.1 Title and Axis Labels

Put the following code in a new program file, say niceGraph.hs.

import Graphics.Gnuplot.Simple

xRange :: [Double]

xRange = [0,0.01..10]

plot1 = plotFunc [Title "Cosine Wave"

,XLabel "Time (ms)"

,YLabel "Velocity of Car (m/s)"

] xRange cos

When you load this into GHCi and ask for the plot1 function, you shouldget a plot with a title and axis labels.

Recall that plotFunc has type

[Attribute] -> [a] -> (a -> a) -> IO ()

where a is a type in some specialized type classes. The Attribute type isdefined in the Graphics.Gnuplot.Simple module. If you type

ghci> :i Attribute

(:i is short for :info) you’ll see some options for what you can do withthese Attributes. Function plotFunc takes a list of Attributes, and weare putting items in this list to produce the title and axis labels.

23

Page 24: Computational Physics IcpHaskell

9.2 Other Labels

You may want to put other labels on a plot. At the very least, you will wantto put your name on your plot. Here is how you can do this.

import Graphics.Gnuplot.Simple

xRange :: [Double]

xRange = [0,0.01..10]

plot1 = plotFunc [Title "Cosine Wave"

,XLabel "Time (ms)"

,YLabel "Velocity of Car (m/s)"

,Custom "label" ["\"Albert Einstein\" at 2,0.8"]

] xRange cos

Note the Custom attribute that we added. The backslash in front of thequotes is because we need to pass quotes inside of quotes. The coordinates2,0.8 are the horizontal and vertical coordinates on the graph where we wantthe label to appear.

9.3 Printing

At some point, you’ll want to print your graph on paper.

9.3.1 Filling an entire page

If you want your graph on a sheet of paper by itself in landscape mode, youcan make a postscript file and then send the postscript file to the printer. Tomake a postscript file (instead of a graphics window on the screen), includethe two Attributes

Custom "term" ["postscript"]

and

Custom "output" ["\"nice.ps\""]

in the list of Attributes for your plotFunc function, where nice.ps is thename of the postscript output file (you could choose any name with a .ps

extension). The modified use of the plotFunc command would be as follows.

24

Page 25: Computational Physics IcpHaskell

plot1 = plotFunc [Title "Cosine Wave"

,XLabel "Time (ms)"

,YLabel "Velocity of Car (m/s)"

,Custom "label" ["\"Albert Einstein\" at 2,0.8"]

,Custom "term" ["postscript"]

,Custom "output" ["\"nice.ps\""]

] xRange cos

When you ask GHCi to run the plot1 function, it will create a file callednice.ps. To send this file to the printer, issue the following command fromthe GNU/Linux shell prompt (not the GHCi prompt).

% lpr nice.ps

The graph should come sailing out of the printer.

9.3.2 Making a graph to include in another document

If you want to make a graph that can be included in another document, youcan make an encapsulated postscript (.eps) file. For this, the Attribute

you want is

EPS "nice1.eps"

so that the plotFunc function would look something like the following.

plot2 = plotFunc [Title "Cosine Wave"

,XLabel "Time (ms)"

,YLabel "Velocity of Car (m/s)"

,Custom "label" ["\"Albert Einstein\" at 2,0.8"]

,EPS "nice1.eps"

] xRange cos

You can still send the encapsulated postscript file to the printer, but it comesout as a small graph at the bottom of the page. We’ll talk about how toinclude the graph in another document later.

If you have a use for portable network graphics, there is an Attribute toproduce a .png graphics file.

Activity: Make a plot of y = x2 from x = −3 to x = 3 with a title, axislabels (although I admit that these are a little silly in this case) and yourname. Print it out and turn it in to me. You do not need to put any Haskellcode in my drop box.

25

Page 26: Computational Physics IcpHaskell

9.4 Plotting Data

There will be times when we want to plot points of (x, y) pairs ratherthan functions. We can use the plotPath function for this (also definedin Graphics.Gnuplot.Simple).

Activity: Take a look at the type signature for plotPath, and figure outhow to plot the list of points txPairs defined earlier and repeated below.

ts :: [Double]

ts = [0,0.1..6]

txPairs :: [(Double,Double)]

txPairs = [(t,yRock30 t) | t <- ts]

By default, plotPath will connect the points with lines and not plot individ-ual marks where the points occur on the graph. This is fine for our purposes.(There is a way to plot the actual points, as would be appropriate for exper-imental data.) You don’t need to turn this in. Just make sure you can do it,and ask for help if you need it.

9.5 Multiple Curves on One Set of Axes

You can plot multiple curves on a single set of axes. This is particularly usefulif you want to compare two functions that have the same independent anddependent variables. Let’s make a new program file called multiGraph.hs.

import Graphics.Gnuplot.Simple

plot2 = plotFuncs [] [0,0.1..10] [cos,sin]

Try to load this into GHCi.

Activity: Add one or more type signatures to this program so that it cor-rectly loads and makes a plot. Put a copy of this short code in my drop box.If your name is Elvis, please call the file something like ElvisMultiGraph.hs.

Notice that the plotFuncs function takes a list of functions as one of itsarguments. We found a use for a list of functions!

The range of x-values does not have to be the same for the two plots. Con-sider the following example, which introduces the new function plotPaths.Can you see how plotPaths differs from plotPath?

26

Page 27: Computational Physics IcpHaskell

import Graphics.Gnuplot.Simple

xs1, xs2 :: [Double]

xs1 = [0,0.1..10]

xs2 = [-5,-4.9..5]

xys1, xys2 :: [(Double,Double)]

xys1 = [(x,cos x) | x <- xs1]

xys2 = [(x,sin x) | x <- xs2]

plot2 = plotPaths [] [xys1,xys2]

You can plot three things at the same time if you like.

import Graphics.Gnuplot.Simple

xRange :: [Double]

xRange = [0,0.02..10]

f3 :: Double -> Double

f3 x = exp (-x)

plot3 = plotFuncs [] xRange [cos,sin,f3]

9.6 Controlling the Plot Ranges

By default, Gnuplot (the program that is making the graphs behind thescenes) will make plots based on the x-ranges that you provide, and thecorresponding y-ranges that are calculated. Sometimes, you may want morecontrol over the x-range or the y-range.

Revisiting the previous example of three plots, try the following.

import Graphics.Gnuplot.Simple

xRange :: [Double]

xRange = [0,0.02..10]

f3 :: Double -> Double

27

Page 28: Computational Physics IcpHaskell

f3 x = exp (-x)

plot3 = plotFuncs [ XRange (-2,8)

, YRange (-0.2,1)

] xRange [cos,sin,f3]

Notice the funny stylistic way in which I made the list [XRange (-2,8),

YRange (-0.2,1)]. People who code in Haskell sometimes do this (puttingthe comma first on the second line of the list), but you don’t have to. Youcould put this all on one line, or put the comma at the end of the line. It’sa matter of style.

10 Good Coding Practice

10.1 Give Every Function a Type Signature

In Haskell, it is good practice to give every function that you define in yourprogram file a type signature. We have been doing this all along.

10.2 Put Comments in your Code

All respectable programming languages have a way for programmers to putcomments in their code. Comments are pieces of the code that the computerignores, that are present only for the benefit of human readers of the code.You can use comments to remind yourself of what the code does.

A double hyphen -- is used in Haskell to make a comment. Haskell willignore anything written after -- until the end of the line. The followingprogram shows some examples of comments.

{-# OPTIONS_GHC -Wall #-}

module Arrow where

import Graphics.Gloss

import Graphics.Gloss.Geometry.Angle

-- positive x is to the right in Translate

-- positive y is up in Translate (this is good)

28

Page 29: Computational Physics IcpHaskell

basicArrow100 :: Picture

basicArrow100 = Pictures [Line [(0,0),(100,0)],Polygon [(75,5),(100,0),(75,-5)]]

-- assumes radians coming in

polarToCart :: (Float,Float) -> (Float,Float)

polarToCart (r,theta) = (r * cos theta,r * sin theta)

-- theta=0 is positive x axis

-- output angle in radians

cartToPolar :: (Float,Float) -> (Float,Float)

cartToPolar (x,y) = (sqrt (x**2+y**2),atan2 y x)

arrow :: Point -- location of base of arrow

-> Point -- displacement vector

-> Picture

arrow (x,y) val = Translate x y $ originArrow val

-- Rotate takes its angle in degrees, and rotates clockwise.

originArrow :: Point -- displacement vector

-> Picture

originArrow (x,y)

= Rotate (-radToDeg theta) $ Scale (r/100) (r/100) basicArrow100

where

(r,theta) = cartToPolar (x,y)

Don’t worry too much about the details of this piece of code. It uses anumber of ideas that we haven’t discussed yet. Focus on the use of comments.I used comments in this code to remind myself of conventions that I mightforget (for example, that positive is upward for the Translate function).Also note that comments can start in the middle of a line and go to the endof the line.

Haskell also provides a long comment, which starts with the symbol {-and ends with the symbol -}. A long comment does not end at the end ofthe line, so it is good if you have a paragraph that you want to write. Hereis an example.

{-

29

Page 30: Computational Physics IcpHaskell

This is a long comment.

It spans multiple lines.

The main purpose of this code is to define the three functions

label, postscript, and psFile.

This code might be useful to you if you are making plots for presentation.

The syntax required in some of the options is so wacky that no one

could possibly remember it. You can use these functions instead of the

wacky syntax. See the examples below to see how to use them.

-}

module Label where

import Graphics.Gnuplot.Simple

label :: String -> (Double,Double) -> Attribute

label name (x,y)

= Custom "label" [show name ++ " at " ++ show x ++ "," ++ show y]

postscript :: Attribute

postscript = Custom "term" ["postscript"]

psFile :: String -> Attribute

psFile file = Custom "output" [show file]

examplePlot1 = plotFunc [Title "Cosine Wave"

,XLabel "Time (ms)"

,YLabel "Velocity"

,label "Albert Einstein" (2,0.8)

] [0,0.01..10::Double] cos

examplePlot2 = plotFunc [Title "Cosine Wave"

,XLabel "Time (ms)"

,YLabel "Velocity of Car"

,label "Albert Einstein" (2,0.8)

,postscript

,psFile "post1.ps"

30

Page 31: Computational Physics IcpHaskell

] [0,0.01..10::Double] cos

You could use a long comment in code that you submit to my drop box.In the long comment, you could explain what your code is doing, or writeanything else that needs to be written, but should not be interpreted asHaskell code.

As a rule, you should include enough comments in your code that youwould be able to look at it in one year and make sense of what you did.

10.3 Put information in one place

If you need to set a time step, or a number of points in your program, usea name to hold this information, and then use the name at every place thatneeds, say, the time step. Do not “hard code” the number 0.01 as your timestep at two or more places in the code, because there will come a time whenyou want to change it, and you might change it in one place and forget tochange it in another place.

10.4 Write modular code

Write modular code that can be reused in other situations. Write functionsthat are small enough to be understood, and can be combined to make morecomplex and powerful things. Don’t write one big complex powerful function.It probably won’t work.

10.5 Use types that reflect the way you think about

the problem

Use a vector type for a vector rather than three numbers. This makes forcleaner, more understandable code. Use a function for magnetic field.

Activity: Write a function

approxsin :: Double -> Double

that approximates the sine function by the first four terms in its Taylorexpansion,

x−x3

3!+x5

5!−x7

7!.

31

Page 32: Computational Physics IcpHaskell

(Depending on how you do this, you may or may not run into the issue thatyou cannot divide a Double by an Int or an Integer in Haskell. You canonly divide a numeric type by the same numeric type. If you run into thisproblem, you can use the function fromIntegral to convert an Int or anInteger to some other type, like Double.)

Test your function by trying the following commands.

ghci> plotFuncs [] [-4,-3.99..4] [sin,approxsin]

Make a nice version of this plot (with a title, axis labels, your name typed,labels to indicate which curve is which, etc.) and hand it in.

11 Euler Method for First-Order Differential

Equations

We want to use the computer to solve physics problems. Our first classof physics problems are problems in mechanics, where Newton’s second lawgoverns the dynamics. Newton’s second law is a second-order differentialequation, so we need to learn how to solve differential equations on the com-puter. In this section, we learn to solve first-order differential equations.Later, we will generalize our method to second-order differential equations.

11.1 Why is Newton’s second law a second-order dif-

ferential equation?

Above, I mentioned in passing that Newton’s second law is a second-orderdifferential equation. In case this fact is not familiar to you, let’s look intoit a bit. Newton’s second law says (in one spatial dimension, for simplicity)

Fnet = ma

where Fnet is the net force acting on some object, m is the mass of theobject, and a is the acceleration of the object. Now, acceleration is thesecond derivative of position with respect to time,

a =d2x

dt2,

32

Page 33: Computational Physics IcpHaskell

and the net force could depend on the position x of the object, the velocitydx/dt of the object, as well as the time t itself. So, Newton’s second lawbecomes

md2x

dt2= Fnet

(

x,dx

dt, t

)

ord2x

dt2=

1

mFnet

(

x,dx

dt, t

)

.

Once we know more about the problem (like what the forces are), and wecan specify how the function Fnet

(

x, dxdt, t)

depends on x, etc., we have asecond-order ordinary (meaning one independent variable, time) differentialequation. Our goal is to solve this differential equation to obtain the positionx(t) as a function of time.

11.2 Euler Method

Most first-order differential equations can be written in the following form.

dy

dt= f(y, t) (1)

A solution to this differential equation is a function y that satisfies the dif-ferential equation.

We imagine that the independent variable t represents time. However,in this section on the Euler method for first-order differential equations, weimagine ourselves to be doing mathematics rather than physics, and so weshall not assign units to the variable t. When we do mathematics, our vari-ables represent pure numbers without units, but when we do physics, ourvariables represent physical quantities and consequently have units associ-ated with them.

A solution to differential equation (1) is a function y. How shall werepresent a function like this on the computer? The answer is that we aregoing to discretize time. That is, we are going to make time discrete bychopping it up into tiny intervals. Suppose that ti is the earliest time thatwe care about and that tf is the latest time that we care about. We’ll chopthe time interval tf − ti into N little intervals, each lasting

∆t =tf − tiN

.

33

Page 34: Computational Physics IcpHaskell

We will confine our attention to the N + 1 points in time

ti, ti +∆t, ti + 2∆t, . . . , ti + (N − 1)∆t, ti +N∆t = tf

and we will not keep track of anything that happens between these points intime. In order for this method to be useful, we must choose ∆t small enoughthat nothing “interesting” happens between points in time separated by ∆t.

Haskell offers us several options in representing this function y. We coulduse a list of doubles, [Double], and just keep track of the N + 1 values ofy that we care about. A second option is to use a list of pairs of doubles,[(Double,Double)], which would allow us to keep track of the values of tright along side of the values of y. I am going to recommend this secondoption.

We approximate our differential equation by a difference equation

∆y

∆t≈ f(y, t)

meaningy(t+∆t)− y(t)

∆t≈ f(y, t).

We expect this to be a good approximation if the time interval ∆t is chosento be reasonably small. Solving for y(t+∆t), we get

y(t+∆t) ≈ y(t) + f(y(t), t)∆t. (2)

The Euler method consists of using (2) to find the value y(t+∆t) at timet + ∆t if we know the value y(t) at time t and we know the rate of change(the function f).

Suppose also that we have the initial condition

y(ti) = yi,

Where yi is given. (Such a problem is called an initial value problem.) Thenwe can find y(ti +∆t) because we know the value of y(ti).

y(ti +∆t) ≈ y(ti) + f(y(ti), ti)∆t = yi + f(yi, ti)∆t (3)

Next, we find y(ti + 2∆t), since we now know y(ti +∆t).

y(ti + 2∆t) ≈ y(ti +∆t) + f(y(ti +∆t), ti +∆t)∆t (4)

Continuing in this way, applying (2) again and again, we can move forwardstep by step through time, calculating the values of the function y at each ofthe points in time.

34

Page 35: Computational Physics IcpHaskell

Example: Use the Euler method to solve the differential equation

dy

dt= ye−16t

with the initial conditiony(0) = 4.

Use a step size of ∆t = 0.01.Solution: To find y(0.01), apply the Euler method.

y(0.01) = y(0) +dy

dt

t=0

∆t

= y(0) + y(0)e0 ·∆t

= 4 + 4(0.01)

= 4.04

We can put our calculations so far into a little table.

t y0 40.01 4.040.02

To find y(0.02), we apply another Euler step.

y(0.02) = y(0.01) +dy

dt

t=0.01

∆t

= y(0.01) + y(0.01)e−0.16 ·∆t

= 4.04 + (4.04)(0.85214)(0.01)

= 4.0744

Now we have

t y0 40.01 4.040.02 4.0744

and we could continue as long as we like.

35

Page 36: Computational Physics IcpHaskell

Activity: (Euler method by hand 1) To deepen our understanding of theEuler method, we’ll do a calculation by hand (using only a calculator, andnot the computer).

Consider the differential equation

dx

dt= −3x+ 4 cos 2t

for the function x, along with the initial condition

x(0) = 2.

Use the Euler method with a step size of ∆t = 0.1 to approximate the valueof x(0.3).

Keep at least four figures after the decimal point in your calculations.Show your calculations in a small table.

Let (t, y) be a pair of values representing the independent (t) and depen-dent (y) variables at a moment in time. Let us call this pair a state tuple,because it encapsulates the state of the system at a moment in time. Ahelpful way of thinking about a single step of the Euler method is that ittakes a state tuple (t, y) as input and gives as output a new state tuple (t′, y′)representing the variables at a later point in time (the step size ∆t later intime).

(t, y) → (t′, y′)

The Euler method prescribes that the new values are related to the old valuesby

t′ = t+∆t

y′ = y + f(y, t)∆t

where f is the function from equation (1) that gives the slope.

Activity: (Euler method by computer 1) Write a Haskell function

eulerStep1 :: (Double,Double) -> (Double,Double)

that takes a pair (t, x) and returns a pair (t′, x′) for a single step of the Eulermethod for the differential equation

dx

dt= −3x+ 4 cos 2t

36

Page 37: Computational Physics IcpHaskell

with a step size of ∆t = 0.1.Show how to use the function eulerStep1 to calculate the value x(0.3)

that you calculated by hand before.Turn in a copy of your function eulerStep1, an explanation of how you

used it to calculate x(0.3) (as a long comment), and the result you obtained.Please include all of this as part of a loadable .hs file and put it in my dropbox.

Now is a good time to investigate the library function iterate. AskGHCi for the type of this function. Try to understand what iterate doesby thinking about the type and looking at the output of the command

ghci> take 7 $ iterate (*2) 4

This is the same as

ghci> take 7 (iterate (*2) 4)

but with fewer parentheses. What happens if you do the following?

ghci> iterate (*2) 4

Why does it do that? Do you see how iterate could be useful to us inapplying the Euler method?

Activity: Generalize your eulerStep1 function above to allow it to takeany function for the slope and any time step. In particular, define a function

oneEulerStep :: (Double -> Double -> Double)

-> Double

-> (Double,Double) -> (Double,Double)

that takes as input a function f :: Double -> Double -> Double for f(y, t)in equation (1), a time step ∆t, and a state tuple (t, y), and returns a newstate tuple (t′, y′). Note that we are using curried form for the function f , asdescribed in section 7.2. Also note that in the function f, the first argumentis the value of y (unlike the state tuple pairs, which have t in the first slot).

Test this function with the differential equation and time step from thelast activity to confirm that it is working properly.

37

Page 38: Computational Physics IcpHaskell

Activity: Consider the differential equation

dy

dt= −y

subject to the initial condition y(0) = 8. Solve this initial value problemover the time interval 0 ≤ t ≤ 10 using the Euler method. Plot the resultingfunction y(t) to see what it looks like. Compare your results to the exactsolution of the differential equation (You can solve this differential equationexactly by guessing or some other method.) Try out different time steps tosee what happens when the time step gets too big.

Find a time step that is small enough so that the Euler solution and theexact solution overlap precisely on a plot. Find another time step that is bigenough so that you can see the difference between the Euler solution and theexact solution on a plot.

Make a nice plot (with title, axis labels, etc.) with these three solutionson a single graph (bad Euler, good Euler, and exact). Label the Euler resultswith the time step you used, and label the exact result “Exact”. Put yourname on the plot (using the label commands we learned) and hand it in.

Activity: Consider the differential equation

dy

dt= cos(t+ y)

subject to the initial condition y(0) = 0. You cannot solve this differentialequation by hand. (Why not?) Use the Euler method with a step size of∆t = 0.01 to find y(t) over the interval 0 ≤ t ≤ 3. Make a nice plot of theresulting function, and include on your plot (using a label command) thevalue y(3) to five significant figures. Put your name on the plot (using alabel command), and hand it in.

12 Mechanics in One Dimension

12.1 Basic Setup

Mechanics is easiest in one spatial dimension, because quantities like position,velocity, acceleration, force, and momentum can be represented by numbersrather than by vectors.

38

Page 39: Computational Physics IcpHaskell

Newton’s second law gives rise to a second-order differential equation forthe position of an object as a function of time. This is because accelerationis the second derivative of position with respect to time. The net forcecan depend on the position x of the object (for example, the force from alinear spring is F = −kx), it can depend on the velocity dx/dt of the object(for example, the force from air resistance), or it can depend explicitly ontime t (for example, an external time-dependent force). In one-dimensionalmechanics, Newton’s second law can be written as follows.

md2x

dt2= Fnet

(

x,dx

dt, t

)

(5)

12.2 Euler Method for Second-Order Differential Equa-

tions

We are interested in Newton’s second law, which is a second-order differentialequation for the position of an object as a function of time. In this section,we explore how we can extend Euler’s method to second-order differentialequations.

The general form for a second-order differential equation is

d2x

dt2= a

(

x,dx

dt, t

)

. (6)

If you like, you can think of x as being position, and a as being a functionthat gives acceleration based on position, velocity, and time.

Our first task is to decompose this second-order differential equation intotwo first-order differential equations. For this purpose, let us introduce afunction v:

v(t) =dx

dt.

Then we can write our original second-order differential equation as

dv

dt= a(x, v, t). (7)

So, we can replace the second-order differential equation (6) with the set oftwo coupled first-order differential equations

dv

dt= a(x, v, t) (8)

dx

dt= v. (9)

39

Page 40: Computational Physics IcpHaskell

These equations are coupled because we cannot solve for x(t) without know-ing v(t) and (usually) we cannot solve for v(t) without knowing x(t).

However, the fact that these equations are coupled does not bother us.We can use the Euler method.

v(t+∆t) = v(t) + a(x(t), v(t), t)∆t (10)

x(t+∆t) = x(t) + v(t)∆t (11)

Compare these equations to (2). I have dropped the approximate equality (≈)notation at this point. We understand that we are computing approximatesolutions.

Activity: (Euler method by hand 2) Consider the differential equation

d2x

dt2= −3x+ 4 cos 2t− 2

dx

dt

for the function x(t), along with the initial conditions

x(0) = 2

anddx

dt(0) = 1.

Use the Euler method with a step size of ∆t = 0.1 to approximate the valueof x(0.3).

Keep at least four figures after the decimal point in your calculations.Show your calculations in a small table. (The table will have three columnsnow, for t, x, and dx/dt.)

Our state tuple for the Euler method for second order differential equa-tions will be a triple (t, x, v) instead of a pair. The Euler method prescribesthat the new values are related to the old values by

t′ = t+∆t

x′ = x+ v∆t

v′ = v + a(x, v, t)∆t

where a is the function from equation (6).

40

Page 41: Computational Physics IcpHaskell

Activity: (Euler method by computer 2) Write a Haskell function

eulerStep2 :: (Double,Double,Double) -> (Double,Double,Double)

that takes a pair (t, x, v) and returns a pair (t′, x′, v′) for a single step of theEuler method for the differential equation

d2x

dt2= −3x+ 4 cos 2t− 2

dx

dt

with a step size of ∆t = 0.1, and initial conditions as above.Show how to use the function eulerStep2 to calculate the value x(0.3)

that you calculated by hand before.Turn in a copy of your function eulerStep2, an explanation of how you

used it to calculate x(0.3), and the result you obtained. Please include all ofthis as part of a loadable .hs file and put it in my drop box.

Activity: Generalize your eulerStep2 function above for use in one-dimensional Newtonian mechanics. Suppose we define the following typesynonyms.

type Time = Double

type TimeStep = Double

type Mass = Double

type Position1D = Double

type Velocity1D = Double

type Acceleration1D = Double

type Force1D = Double

type StateTuple1D = (Time,Position1D,Velocity1D)

type AccelerationFunction1D = StateTuple1D -> Acceleration1D

Define a function

eulerStep :: TimeStep

-> AccelerationFunction1D

-> StateTuple1D -> StateTuple1D

that accepts (1) a time step and (2) a function for the acceleration and returnsa function that can produce a new state tuple from an old state tuple.

41

Page 42: Computational Physics IcpHaskell

Activity: Let’s warm up with a basic projectile motion problem where weknow what the answer should look like. Suppose a ball is thrown from theground straight up into the air with an initial velocity of 10 m/s. Ignoring airresistance, use the Euler method to find the height of the ball as a functionof time. Make a plot of height as a function of time just to convince yourselfthat things are working as they should. You don’t need to hand this in.

Activity: Consider a 3-kg mass connected by a linear spring with springconstant 100,000 N/m to a wall. If the spring is extended by 0.01 m andreleased, what does the subsequent motion look like? Investigate this motionover several cycles of oscillation. Compare your results to the exact solution.Find a time step that is small enough so that the Euler solution and theexact solution overlap precisely on a plot. Find another time step that is bigenough so that you can see the difference between the Euler solution and theexact solution on a plot.

Make a nice plot (with title, axis labels, etc.) with these three solutionson a single graph (bad Euler, good Euler, and exact). Label the Euler resultswith the time step you used, and label the exact result “Exact”. Put yourname on the plot (using the label commands we learned) and hand it in.

12.3 Units

Another issue that we must consider is the choice of units. All of our physicalquantities have units associated with them, but the computer only under-stands numbers, and not units. In many problems, we can use the standardSI units (kilograms, meters, seconds, etc.) and in such a case we just re-member that the numbers that are coming out of our calculations are in thestandard SI units. But, suppose you are doing a calculation of the Earth’sposition as it revolves about the Sun. Meters might not be the best units touse, because you would always be dealing with numbers in the billions. For aproblem like this, it makes sense to choose a bigger unit of length (maybe theastronomical unit AU), so that you can work with numbers that are withina few orders of magnitude of 1.

The same issues are true for microscopic problems in physics. If you areinterested in the energy of an atom, it makes little sense to choose Joulesas your unit of energy, because then you are always looking at tiny tinynumbers. Maybe electron volts (eV) or milli-electron volts (meV) would bebetter.

42

Page 43: Computational Physics IcpHaskell

13 Air Resistance

13.1 Introduction

When studying topics like projectile motion in an introductory physics class,we usually ignore air resistance.

Air resistance is the force an object feels as it moves through the air. Itcomes from the molecules of air slamming into the object.

In fact, air resistance is just one example of the larger subject of fluidflow. Air is a fluid (fluids are liquids and gases) that flows around an object.Fluids like air can exert forces on objects.

The study of fluid flow around solid objects is very complex. If a personwanted to design a good wing cross-section for an airplane, she would needto have a good understanding of this subject. Our aims are more modest.We don’t really care what happens to the air as it flows around an object.We just want a decent model for the force that the air exerts on an object.

There is one thing that we can say right away. The direction of the forceof air resistance on an object is opposite the motion of the object (in otherwords, opposite the velocity of the object).

13.2 Collision Model

Let us think of the interaction between an object and the air around it asa collision. Suppose the object is moving with velocity v. Let the cross-sectional area of the object be A. Let the density of air be ρ.

We assume that the initial velocity of the air is zero, and that the finalvelocity of the air is v (in other words, after the collision, the air is travelingat the same speed as the object).

The distance the object travels in time dt is vdt. The volume of air sweptout by the object in time dt is Avdt. The mass of air disturbed by the objectin time dt is

ρAvdt.

The momentum imparted to the air by the object in time dt is

ρAv2dt.

The force felt by the object from the air is

Fair = −ρAv2.

43

Page 44: Computational Physics IcpHaskell

Our derivation was really quite approximate, since we don’t know that theair molecules really end up with velocity v, and we haven’t even tried to takeinto account the forces of air molecules on each other as the air compresses.Nevertheless, the form of our result is quite useful and approximately correct.Objects with different shapes respond a bit differently, however, and so it isuseful to introduce a drag coefficient C to account for these differences. Thedrag coefficient is a dimensionless constant that is a property of the objectthat is trying to fly through the air. Our final expression for the magnitudeof air resistance is

Fair = −CρAv2.

Activity: Let’s investigate dropping things from large heights. In partic-ular, let’s look at a ping-pong ball and a bowling ball. In each case, takeC = 1/2. You will need to find out good approximations for things like thesize and mass of these balls. Let’s drop them from 100 m and 500 m. Makegraphs of velocity as a function of time and velocity as a function of verticalposition. What fraction of terminal velocity is achieved in each case? As-semble your results in some meaningful and understandable way and turnthem in.

14 Improvements to the Euler Method

14.1 Euler-Cromer Method for Second-Order Differ-

ential Equations

For second-order differential equations, there is a slight modification that wecan make to the Euler method which improves the results in a number ofcases. Recall that we wish to solve the differential equation

d2x

dt2=

1

mFnet

(

x,dx

dt, t

)

. (12)

By introducing v = dx/dt, this second-order differential equation is equiva-lent to the two first-order differential equations

dv

dt=

1

mFnet(x, v, t) (13)

dx

dt= v. (14)

44

Page 45: Computational Physics IcpHaskell

The Euler method prescribes that we find the values of x and v at a latertime t+∆t from their values at the earlier time t in the following way.

v(t+∆t) = v(t) +1

mFnet(x(t), v(t), t)∆t

x(t+∆t) = x(t) + v(t)∆t

The Euler-Cromer method seeks a solution to the same differential equa-tion(s), and the prescription is only slightly different.

v(t+∆t) = v(t) +1

mFnet(x(t), v(t), t)∆t (15)

x(t+∆t) = x(t) + v(t+∆t)∆t (16)

Question: In the Euler method, we update the state tuple (t, x, v) →(t′, x′, v′) by

t′ = t+∆t

x′ = x+ v∆t

v′ = v +1

mFnet(x, v, t)∆t

Write similar update equations for the Euler-Cromer method.

Answer:

Activity: Return to the harmonic oscillator problem that we did earlier.Compare the Euler and Euler-Cromer solutions to the exact solution for atime step of 0.001 s (you will recall that this is not a very good time step forthe Euler method). Plot the displacement of the mass as a function of timefor the first 0.1 s of motion. Plot Euler, Euler-Cromer, and exact solutionson one set of axes. Also give the value of the position of the mass (to foursignificant figures) at t = 0.1 s for each of the three solutions. Please handin the physical plots, and put a copy of your code in my drop box.

45

Page 46: Computational Physics IcpHaskell

15 Mechanics in Three Dimensions

To do mechanics in three dimensions, we must use vectors rather than num-bers for position, velocity, acceleration, and force.

15.1 Vectors in Haskell

Haskell does not come with a built-in type for vectors, so we have to definethem ourselves. I have done this in the module SimpleVec.hs, which youcan copy and use.

If you are working from one of the machines in the Computational PhysicsLab, the following commands at the GNU/Linux shell will copy the filesSimpleVec.hs and CommonVec.hs into your current directory. (The dot atthe end represents the current directory. The module SimpleVec.hs callsthe module CommonVec.hs, so you need both.)

cp /home/walck/public/SimpleVec.hs .

cp /home/walck/public/CommonVec.hs .

If you are working from a laptop, or some other machine, try the follow-ing commands instead, replacing adg002 with your LVC email address andphylab-05 with the name of a machine in the Computational Physics Labthat is currently running GNU/Linux.

scp adg002@phylab-05:/home/walck/public/SimpleVec.hs .

scp adg002@phylab-05:/home/walck/public/CommonVec.hs .

Once you successfully copy these files, we can start playing with theSimpleVec.hs module. Start up GHCi and load this file.

ghci> :l SimpleVec

You can make a vector with the vec function by giving its three components.

ghci> vec 3.2 0 (-6.4)

If you ask for the type of this expression,

ghci> :t vec 3.2 0 (-6.4)

46

Page 47: Computational Physics IcpHaskell

GHCi will report that it has type Vec, which is our new vector type.What can we do with Vecs? We can add them to other Vecs and we can

scale them with Doubles. To add Vecs, we will not use the + operator thatwe use with numbers, but rather a new vector addition operator named ^+^.

ghci> vec 1 2 3 ^+^ vec 4 5 6

You can think of the carrot on each side of the plus as a reminder that thereis a vector on the left and a vector on the right. To scale a vector, we canuse the *^ operator.

ghci> 5 *^ vec 1 2 3

Notice that the carrot goes on the right of the asterisk, because the vector ison the right. You can multiply a Vec by a Double on the right with the ^*

operator.

ghci> vec 1 2 3 ^* 5

Since the vector is on the left, the carrot is on the left. We can divide by aDouble with the ^/ operator.

ghci> vec 1 2 3 ^/ 5

You can subtract Vecs with the ^-^ operator.

ghci> vec 1 2 3 ^-^ vec 4 5 6

You can take the dot product of two Vecs with the <.> operator.

ghci> vec 1 2 3 <.> vec 4 5 6

You can take the cross product of two Vecs with the >< operator (it’s sup-posed to look like a cross product).

ghci> vec 1 2 3 >< vec 4 5 6

You can take the magnitude of a vector.

ghci> magnitude (vec 1 2 3)

If you need the components of a vector, you can get them with the xCompfunction.

47

Page 48: Computational Physics IcpHaskell

ghci> xComp $ vec 1 2 3 >< vec 4 5 6

ghci> xComp (vec 1 2 3 >< vec 4 5 6)

There are also functions yComp and zComp. The zero vector is called zeroV.

ghci> zeroV

You can negate a vector with negateV.

ghci> negateV $ vec 1 2 3 >< vec 4 5 6

The unit vectors ihat, jhat, khat, xhat, yhat, and zhat are defined.

ghci> jhat

Activity: Try to guess the types of the following expressions. Then checkyour answers using GHCi. Please turn in a hand-written version of your finalanswers. (You can type your answers if you simply can’t stand to write, butplease don’t turn in a transcript of GHCi’s responses. I really want you tothink about why these expressions have the types they have.)

(a) xComp

(b) (^+^)

(c) (^-^)

(d) (*^)

(e) (^*)

(f) (^/)

(g) (<.>)

(h) (><)

(i) magnitude

(j) zeroV

(k) negateV

(l) xhat

(m) vec

48

Page 49: Computational Physics IcpHaskell

15.2 Euler Method with Vectors

Now that we have a vector type Vec, we need versions of our Euler methodand Euler-Cromer method functions that work with vectors.

For any code in which we want to use the Vec type and the associatedoperations, we must include

import SimpleVec

at the top of the file.

Activity: Suppose we define the following type synonyms.

type Time = Double

type TimeStep = Double

type Mass = Double

type Position = Vec

type Velocity = Vec

type Acceleration = Vec

type Force = Vec

type StateTuple = (Time,Position,Velocity)

type AccelerationFunction = StateTuple -> Acceleration

Define functions

eulerStep :: TimeStep

-> AccelerationFunction

-> StateTuple -> StateTuple

and

eulerCromerStep :: TimeStep

-> AccelerationFunction

-> StateTuple -> StateTuple

that accept a time step and a function for the acceleration, and return afunction that can produce a new state tuple from an old state tuple, usingthe Euler (or Euler-Cromer) method.

49

Page 50: Computational Physics IcpHaskell

We are now in a wonderful position. All we need to do to solve anyone-body problem in mechanics is give the computer

• a time step,

• the body’s acceleration as a function of its current state,

• and the body’s initial state.

Of course, to find the acceleration of the body, we will generally need to addup the forces that act on the body to get the net force, and divide by thebody’s mass. The computer will then calculate the position and velocity ofthe particle at later points in time, for as long as we like.

Let’s make our technology even easier to use. Our function eulerCromerStepadvances the scene by one time step, and we need to use the iterate functionto move forward in time by many time steps. The function eulerCromerSolutionreturns an infinite list of StateTuples, which can then be further processedfor plotting or other purposes.

eulerCromerSolution :: TimeStep

-> AccelerationFunction

-> StateTuple -> [StateTuple]

eulerCromerSolution dt a = iterate $ eulerCromerStep dt a

Since Haskell is a lazy language, it will not actually calculate the entire infi-nite list (an impossible task in any case). It will only calculate the minimumamount of the list necessary to do what you ask of it.

Below is an example of how we might use our new Euler-Cromer vectortechnology for a simple projectile motion problem.

trajectory :: [StateTuple] -> [(Double,Double)]

trajectory tups = [(xComp r,yComp r) | (_,r,_) <- tups]

-- vertical direction is y direction

earthSurfaceGravity :: AccelerationFunction

earthSurfaceGravity _state = vec 0 (-g) 0

g :: Double

g = 9.81

50

Page 51: Computational Physics IcpHaskell

projectileTuples :: Double -> Double -> [StateTuple]

projectileTuples v0 theta

= eulerCromerSolution 0.01 earthSurfaceGravity

(0,vec 0 0 0,vec vx0 vy0 0)

where

vx0 = v0 * cos theta

vy0 = v0 * sin theta

plotTuples :: [StateTuple]

plotTuples = takeWhile (\(_,r,_) -> yComp r >= 0)

$ projectileTuples 30 (pi/3)

plot1 :: IO ()

plot1 = plotPath [] $ trajectory plotTuples

Activity: Let us treat the Earth as being fixed at the origin of our coordi-nate system. Consider the gravitational force on a satellite of mass m, initialposition r0, and initial velocity v0. Since the motion of the satellite will takeplace in a plane, we can use vectors that lie in the xy plane. Plot trajectoriesof orbits resulting from various initial conditions. Choose some values forinitial conditions that give nearly circular orbits and some others that giveelliptical orbits. You will find that the Euler method produces orbits thatdon’t close on themselves. Hand in one plot comparing the Euler and Euler-Cromer methods for one orbit that you like (elliptical or circular). Indicatethe step size that you used for the Euler and Euler-Cromer methods, as wellas your choice of initial conditions.

Question: The Lorentz force law describes the force exerted on a particlewith charge q and velocity v by an electric field E and a magnetic field B.Write down this force.

Answer:

51

Page 52: Computational Physics IcpHaskell

Activity: Consider a uniform magnetic field in the z-direction. You mayalready know that a charged particle with initial velocity in the x-directionwill go in circles in this magnetic field. Choose some values for the strengthof the magnetic field, the charge of the particle, the mass of the particle, andthe initial velocity. Confirm, using the Euler method, that the particle doesindeed go in circles. Plot y vs. x for different time steps. Make some niceplots and hand these in.

16 Animation with Gloss

We are going to use a two-dimensional graphics library called Gloss. To in-stall gloss, try issuing the following command from the Linux shell commandline:

cabal install gloss

Take a look at the documentation for the gloss library.Here is an example program using gloss to animate projectile motion.

{-# OPTIONS_GHC -Wall #-}

-- Use Gloss’s simulate function to animate projectile motion

-- using the Euler method

import Graphics.Gloss

import Graphics.Gloss.Interface.Simulate

import EulerCromer

import SimpleVec

-- positive x is to the right in Translate

-- positive y is up in Translate (this is good)

-- This function defines a disk in terms of Gloss’s ThickCircle

disk :: Float -> Picture

disk radius = ThickCircle (radius/2) radius

-- A red disk will represent the projectile

redDisk :: Picture

52

Page 53: Computational Physics IcpHaskell

redDisk = Color red (disk 50)

-- initial time

t0 :: Double

t0 = 0

-- initial position

r0 :: Vec

r0 = vec 0 0 0

-- given a speed and angle, produce a velocity vector

velFromSpeedAngle :: Double -> Double -> Vec

velFromSpeedAngle v theta = vec (v * cos theta) (v * sin theta) 0

-- initial velocity

v0 :: Vec

v0 = velFromSpeedAngle 100 (35 * pi / 180)

-- Gloss’s idea of "world" is the same as our idea of state,

-- that is, the information required to express the current "state of affairs"

-- of our system.

-- The initial world is the initial StateTuple.

worldInitial :: StateTuple

worldInitial = (t0,r0,v0)

-- This function tells what the picture should look like for a given

-- state of affairs.

worldToPicture :: StateTuple -> Picture

worldToPicture (_t,r,_v) = scale 0.2 0.2 $ translate xFloat yFloat redDisk

where

xFloat = realToFrac (xComp r)

yFloat = realToFrac (yComp r)

-- By default, gloss will attempt to do the simulation in real time.

-- If we’re animating the orbit of the moon around the Earth, we

-- don’t want to watch the computer for one month to see one orbit.

-- A number greater than one here is a speedup factor.

-- A number less than one is a slow-down factor.

53

Page 54: Computational Physics IcpHaskell

timeScale :: Double

timeScale = 3

-- The rule for updating the "world" is just to take one Euler step!

simStep :: ViewPort -> Float -> StateTuple -> StateTuple

simStep _ dt = eulerCromerStep dtScaled (const $ vec 0 (-9.8) 0)

where

dtScaled = timeScale * realToFrac dt

-- The main program creates a window and does our animation.

-- We need to give it an initial "world" (worldInitial),

-- a function to translate from world to picture (worldToPicture),

-- and an update rule (simStep).

main :: IO ()

main = simulate (InWindow "Projectile Motion" (600, 600) (10, 10))

white 20 worldInitial worldToPicture simStep

Activity: Return to the satellite orbiting the Earth. Write a Haskellprogram to animate your satellite’s motion around the Earth. Show that byusing different initial conditions, you can achieve circular orbits and ellipticalorbits. Please show me that your program works. Also, please place a copyof your program in my drop box so that I can look at it. Give your programa name that identifies who you are and what the program does. If your nameis Elvis, you could name the program ElvisSatelliteAnimation.hs.

17 Multiple Objects in Three Dimensions

If we are interested in the motion of more than one particle in three dimen-sions, we need to keep track of the position and velocity for each particle.

Download the file sunEarthMoonTemplate.hs with the following com-mand.

wget http://quantum.lvc.edu/walck/phy261/sunEarthMoonTemplate.hs

Take a look at this code to get an idea for how we might represent multipleobjects in Haskell. The code has some undefined functions that need to befilled in before it will run.

54

Page 55: Computational Physics IcpHaskell

Activity: Using realistic initial conditions, program an animation for thesun, earth, and moon mutually interacting though gravity. Fix the sun at theorigin. Take into account the gravitational force of the moon on the earth,the earth on the moon, the sun on the earth, and the sun on the moon. Theactual earth-sun separation is about 500 times the earth-moon separation, soyou won’t be able to resolve the earth and moon as separate objects on thescreen. In order to be able to see where the moon is relative to the earth, Isuggest the following.

Instead of displaying the moon at the position you calculate, display themoon at a “fake” position that has the correct orientation, but is 50 times asfar from the Earth as you calculate. Here is an equation to use to calculatea fake moon position:

rFM = rE + A(rM − rE)

where rFM is the position of the fake moon, rM is the position of the (real)moon, rE is the position of the earth, and A is a magnification factor thatartificially magnifies the vector from earth to moon for display purposes. TryA = 50 and see what happens. This fake moon is only for display purposes.Its position should not show up in any of the actual physics equations. Showme that your program works, and place a copy in my drop box.

18 Waves on a Flexible String

Imagine a flexible string, like a rubber band or a guitar string, with sometension in it. The ends of the string are located at x = 0 and x = L, and areheld fixed at y = 0. The rest of the string is allowed to move.

We will view this string as being made up of N + 1 little pieces of mass,with neighboring pieces connected by a linear spring with spring constant k.The force on the jth little piece of mass is composed of two parts. There isa force from the neighbor on the left and a force from the neighbor on theright. The vector sum of these two forces is

Fj = −k(rj − rj−1)− k(rj − rj+1).

We are going to ignore any effects of gravity in this string vibration. (Weimagine that the elastic forces are much larger that the force of gravity wouldbe.) The expression above is appropriate when 1 ≤ j ≤ N − 1, that is, forall of the little pieces of mass except the ones on each end. The pieces of

55

Page 56: Computational Physics IcpHaskell

mass on the ends are held fixed. In other words, there is some other forcepresent (from whatever is constraining the end of the string to stay fixed) sothat the net force on the pieces of mass at the ends is zero.

F0 = 0

FN = 0

Putting all of this together, the net force on the jth piece of mass is givenby the following expression.

Fj =

{

0 , j = 0 or j = N−k(rj − rj−1)− k(rj − rj+1) , 1 ≤ j ≤ N − 1

How do we talk about the initial conditions (or initial state) of the string?There are a number of ways we could do this. In general, the string couldhave both initial stretching (position) as well as initial velocity. Let’s confineour attention to situations in which the initial velocity is zero. (So that weimagine pulling the string back into a certain shape and letting go of it.) Oneway to describe the initial configuration of the string is to give the vertical(y) position as a function of the horizontal (x) position. This is the methodwe use in the activity below.

Activity: Animate a wave on a string. Use the force equation given aboveto determine the motion of each little piece of the string. Try a number ofinitial conditions on the string to make different kinds of waves.

1. Use the initial conditions

y(x) = y0 sinπx

Lv(x) = 0.

What would you call this wave?

2. Use the initial condition

y(x) = y0 sin2πx

Lv(x) = 0.

What would you call this wave?

56

Page 57: Computational Physics IcpHaskell

3. Use the initial condition

y(x) =

{

y0 sin4πxL

, 0 ≤ x ≤ L/40 , x > L/4

v(x) = 0.

How would you describe this wave in words?

You may choose whatever values you like for the constants that show up inthis problem (k, L, y0, etc.).

To get started, you may download the file WaveOnStringTemplate.hs

with the following command and use it as a template for your program.

wget http://quantum.lvc.edu/walck/phy261/WaveOnStringTemplate.hs

Show me when you have your string animation working, and put a copyin my drop box. The program you submit should include all three initialconditions, with two of them commented out so that only one is “active”,but that either of the other two could be easily substituted to be the activeinitial condition.

19 Numerical Integration

There are many times when we need to compute integrals numerically. Whenwe talk about numerical integration, we mean computing the value of adefinite integral of some given function over some given limits. What wewould like to be able to do is to give the computer a function f , give thecomputer limits a and b, and ask it to compute the number

∫ b

a

f(x) dx.

First, we have to decide what algorithm to use to do the numerical inte-gration. There are many to choose from, but we’ll start with a simple andintuitively reasonable one.

19.1 The Trapezoidal Rule

In the trapezoidal rule, we approximate the area under a curve by the sumof the areas of a bunch of trapezoids, as shown in figure 1.

57

Page 58: Computational Physics IcpHaskell

x x+∆x x+ 2∆x x+ 3∆x x+ 4∆x

Figure 1: The trapezoidal rule.

For the example in the figure, the area of the first trapezoid is

1

2[f(x) + f(x+∆x)]∆x.

The area of all four trapezoids in the figure is

(

1

2f(x) + f(x+∆x) + f(x+ 2∆x) + f(x+ 3∆x) +

1

2f(x+ 4∆x)

)

∆x

Activity: Write a definition for the function

trapIntegrate :: Int

-> (Double -> Double)

-> Double

-> Double

-> Double

that takes a number of trapezoids, a function, and two limits as its argu-ments and gives back (an approximation to) the definite integral, using thetrapezoidal rule. Test your integrator on the following integrals, and see howclose you can get to the correct values.

∫ 1

0

x3 dx = 0.25

58

Page 59: Computational Physics IcpHaskell

∫ 10−6

0

x3 dx = 2.5× 10−25

∫ 1

0

e−x2

dx ≈ 0.7468

Put a copy of your program in my drop box.

59

Page 60: Computational Physics IcpHaskell

20 Abstract Vectors

It is an irritation that we need to use different notation when adding numbersand when adding vectors. This irritation is amplified when we think aboutthe numerical integrator we just wrote. If we wanted to have a numericalintegrator that integrated vector functions instead of scalar functions, wewould need to rewrite our integrator, replacing + with ^+^ and so on. Buteven after writing a new integrator for vector functions, we couldn’t use thenew integrator with scalar functions.

It would be better to have a single numerical integrator that could beused with either scalar functions or vector functions. We can do this, butthere is a little bit of a cost.

To get started, please download the file CarrotVec.hs with the followingcommand.

wget http://quantum.lvc.edu/walck/phy261/CarrotVec.hs

Let’s play around with this CarrotVec module.In GHCi, load the CarrotVec module.

:l CarrotVec.hs

First, notice that vectors still add correctly.

vec 1 2 3 ^+^ vec 4 5 6

Next, notice that the vector addition operator ^+^ can now add numbersas well.

3 ^+^ 6

In effect, numbers are now regarded as a kind of abstract vector. Theoperator ^+^ now adds not just things of type Vec, but any thing that canbe regarded as an abstract vector. The generalization in the type of things^+^ can add is reflected in its type signature.

:t (^+^)

I get

(^+^) :: AdditiveGroup v => v -> v -> v

60

Page 61: Computational Physics IcpHaskell

when I ask for the type of ^+^. This says that as long as v is a type in typeclass AdditiveGroup, we can add things of that type with ^+^. The typeclass AdditiveGroup is playing the role of “abstract vector”.

Which types are in AdditiveGroup?

:i AdditiveGroup

There is a long list. In particular, both Vec and Double are instances ofAdditiveGroup.

To summarize, we can work with numbers and vectors in a uniform wayif we import the CarrotVec module instead of the SimpleVec module. Thecost is in the readability of the types of the various vector operators. Thetypes of the operators are now filled with type class constraints.

21 Electric Field produced by a Line Seg-

ment of Charge

Imagine a line segment of charge, with linear charge density λ. Let us placethis line segment on the x axis from x = −L/2 to x = L/2. We wish to findthe electric field produced by this line segment at some point r = xi+ yj.

The electric field at point r = xi+ yj is given by

E(x, y) =

∫ L/2

−L/2

1

4πǫ0

λdx′

[(x− x′)2 + y2]3/2

[

(x− x′)i+ yj]

.

You should be able to derive this expression. If it is not clear how thisexpression comes about, you should look in an introductory physics textbookor ask me.

To find the electric field, we will do numerical integration. We can usethe numerical integrator that we wrote in the last section.

Activity: Write a program to show the electric field produced by a linesegment of charge. You may restrict your attention to the xy plane. Plot theelectric field vectors that you calculate with numerical integration in red.

The electric field produced by a line segment of charge is an exactlysolvable problem in physics. Find the exact solution in an introductoryphysics textbook. (Or do the integral above yourself, if you like.) Plot theelectric field vectors obtained from the exact solution in blue. If you have

61

Page 62: Computational Physics IcpHaskell

a good numerical integrator, you should get good agreement between thenumerical (red) and exact (blue) electric field vectors.

To get started, you can download a module to make arrows, and a tem-plate for the electric field project.

wget http://quantum.lvc.edu/walck/phy261/Arrow.hs

wget http://quantum.lvc.edu/walck/phy261/eFieldFromLineTemplate.hs

Note that the template is set up to show only one set of arrows (for example,the exactly calculated arrows, but not the numerically integrated arrows).You will need to extend it to display both sets of arrows.

62

Page 63: Computational Physics IcpHaskell

22 Magnetic Field of a Circular Current Loop

One of the simplest and most natural ways to produce a magnetic field iswith a circular loop of current. A circular loop of current is also a nicemodel of a magnetic dipole, which is a fundamental source of magnetic field.Surprisingly, there is no analytical solution for the magnetic field producedby a circular current loop. However, we can get a good approximate solutionusing numerical integration.

Consider a circular loop in the xz plane, centered at the origin, withradius R. This loop carries a current I in a counter-clockwise direction whenviewed from the positive y axis.

Question: Use the Biot-Savart law to come up with an integral that givesthe magnetic field at a point r = xi + yj. Feel free to check this result withme before proceeding.

Answer:

Activity: Write a program to show the magnetic field produced by acircular current loop. You may restrict your attention to calculating themagnetic field at points in the xy plane.

You will need to make some design decisions, such as how to scale themagnetic field vectors and at which points to plot the magnetic field.

63

Page 64: Computational Physics IcpHaskell

23 Free Particle in Quantum Mechanics

One of the very simplest problems in classical mechanics is the motion of aparticle that experiences no forces. A particle that experiences no forces iscalled a free particle. Newton’s first law gives us the answer to this problem.It tells us that a free particle moves with constant velocity in a straight line.This project investigates the analogous behavior of a particle with no forcesacting on it using the laws of quantum mechanics rather than the laws ofclassical mechanics. As you might imagine, the result is not as simple as it isin classical mechanics. Nevertheless, there is some relationship between thetwo.

In one-dimensional wave mechanics, the Schrodinger equation for a singleparticle with mass m is

ih∂

∂tψ(x, t) = −

h2

2m

∂2

∂x2ψ(x, t) + V (x)ψ(x, t)

where V (x) is the potential energy function for the particle, and ψ(x, t) is thewave function for the particle. In the case of a free particle, there is no forceon the particle, so we may take the potential energy to be zero everywhere.For a free particle then, we have V (x) = 0, and the Schrodinger equationbecomes

ih∂

∂tψ(x, t) = −

h2

2m

∂2

∂x2ψ(x, t)

If we have an initial wave function ψ(x, 0), the Schrodinger equation al-lows us to find the wave function ψ(x, t) at any later time t.

To implement the Schrodinger equation on a computer, we will want touse numerical derivatives. Imagine that we have discretized space into pointsseparated by a length ∆x. Imagine that we have some function f(x) definedon these points. The right numerical derivative approximates the derivativeat x by using the values of the function at x and the point to the right,x+∆x.

d

dxf(x) ≈

f(x+∆x)− f(x)

∆x

Similarly, the left numerical derivative approximates the derivative at x byusing the values of the function at x and the point to the left, x−∆x.

d

dxf(x) ≈

f(x)− f(x−∆x)

∆x

64

Page 65: Computational Physics IcpHaskell

A very nice way to do a numerical second derivative is to take the leftnumerical derivative of the right numerical derivative. The reason that thisis nice is that it is the same as the right numerical derivative of the leftnumerical derivative. You can show that both of these give the followingexpression for the second derivative.

d2

dx2f(x) ≈

f(x+∆x)− 2f(x) + f(x−∆x)

(∆x)2

Recall that the squared magnitude of the wave function

|ψ(x, t)|2

gives the probability density (probability per unit length) for finding theparticle at position x.

Activity: Use the Euler method in time to solve the Schrodinger equation.For the second derivative with respect space, use a numerical second deriva-tive. Plot the squared magnitude of the wave function as it evolves in time.(The reason we plot the squared magnitude is that the wave function itselfis complex, so it’s hard to plot.) For an initial wave function, try

ψ(x, 0) = e−x2/a2+imv0x/h

where v0 is the initial velocity of the wave packet, m is the mass of theparticle, and a is the width of the initial wave packet. You can choosewhatever values you want for these parameters.

65

Page 66: Computational Physics IcpHaskell

24 Animation

In addition to making graphs, another way to visualize the results of ourcalculations is to produce an animation.

I have written a small number of helping functions in the file BasicAnimation.hs.Please get a copy of this from my public directory in the same way that yougot SimpleVec.hs.

The file BasicAnimation.hs defines the following functions.

aSphere :: Double -> Position -> Geometry3

arrow :: Double -> Double -> Position -> Vec -> Geometry3

animate :: Double -> (Time -> Geometry3) -> Anim3

The function aSphere takes as input a radius and a Position (a type syn-onym for Vec) and produces an object with type Geometry3, which is somekind of a 3-dimensional picture.

The function arrow takes as input a radius for the cylinder that formsthe stem of the arrow, a height of the cone part of the arrow, a position, anda vector describing the direction and magnitude of the arrow.

The function animate takes a rate and a function Time -> Geometry3,and returns an object of type Anim3, which is a 3-dimensional animation.

The following code shows an example use of these functions.

import BasicAnimation

import SimpleVec

import Graphics.FieldTrip

import FRP.Reactive.FieldTrip

movie :: Time -> Geometry3

movie t = arrow 0.2 0.5 zeroV (vec (cos t) (sin t) 0)

main :: IO ()

--main = anim3 $ animate 0.4 movie

main = anim3 $ animate 1.4 sphereMovie

sphereMovie :: Time -> Geometry3

sphereMovie t = aSphere 0.2 (vec (cos t) (sin t) 0)

I encourage you to type in the code above, or something like it, and tryit out. Try modifying parts of it and see what happens.

66

Page 67: Computational Physics IcpHaskell

24.1 Color

We can control the color of our graphical objects. Here is a list of predefinedcolors.

transparent :: Col

black :: Col

white :: Col

red :: Col

green :: Col

blue :: Col

yellow :: Col

purple :: Col

The type Col is the type of a color. You can create your own colors (andgive them names, if you want to) with the function rgba. It takes as inputfour numbers (red, green, blue, and brightness) and returns a color.

24.2 Material

To use the colors, we need to specify a surface material along with the color.There are two basic choices; plastic is a function that takes a color andreturns a shiny Material, flat is a function that takes a color and returnsa non-shiny Material.

plastic :: Col -> Material

flat :: Col -> Material

So, for example, plastic blue is a Material.We use the function materialG to modify the material of an object of

type Geometry3.

materialG :: Material -> Geometry3 -> Geometry3

For example, we could do the following.

flatBlueSphereMovie :: Time -> Geometry3

flatBlueSphereMovie t

= materialG (flat blue) $ aSphere 0.2 (vec (cos t) (sin t) 0)

If we could form a trajectory function

67

Page 68: Computational Physics IcpHaskell

trajFunc :: Time -> Position

from the results of our Euler or Euler-Cromer method, then we could ani-mate these little spheres to follow our calculated trajectory. It could looksomething like the following.

projectileMovie :: Time -> Geometry3

projectileMovie t

= materialG (flat blue) $ aSphere 0.2 (trajFunc t)

68

Page 69: Computational Physics IcpHaskell

The output of our Euler method has been a list of state tuples.

Activity: Make an animation of a physical pendulum. Use a cylinder

or box object for the arm of the pendulum and a sphere object for themass at the end of the arm. (Recall that a physical pendulum is not just aharmonic oscillator. The period increases with amplitude. If you have thecorrect equations of motion, this should happen automatically.) Write yourprogram so that your physical pendulum can swing all the way around if ithas enough initial speed. Use the Euler-Cromer method. You will probablywant to use θ and ω as your two dynamical variables. Show me that yourprogram works, and place a copy in my drop box.

25 Root Finding

A numerical technique that is commonly needed is that of finding a root ofa function. That is, given a function f(x), we wish to find a value of x, sayx = x0, so that f(x0) = 0. In numerical work, such as we are doing, we donot endeavor to find an exact root, but rather a numerical approximation atsome desired level of accuracy.

26 Quantum Mechanics

26.1 The Finite Square Well

A classic problem in quantum mechanics is to find the energies and stationarywavefunctions for a particle in a one-dimensional potential well. Suppose wehave a particle of mass m in a square well potential, where the potentialenergy function is given by

V (x) =

{

0 if |x| > L2

−V0 if −L2≤ x ≤ L

2

,

where V0 is a positive constant with units of energy. Figure 2 shows thepotential energy function for the finite square well.

We wish to solve the equation

−h2

2m

d2ψ

dx2+ V (x)ψ(x) = Eψ(x). (17)

69

Page 70: Computational Physics IcpHaskell

V (x)

x

L/2−L/2

−V0

Figure 2: The potential energy function for the finite square well.

In other words, we wish to find energies E and wavefunctions ψ(x) thatsatisfy this equation.

In the region |x| > L/2 (outside the well), we have V (x) = 0, and so (17)reduces to

−h2

2m

d2ψout

dx2= Eψout(x),

ord2ψout

dx2+

2mE

h2ψout(x) = 0.

We are interested in solutions with E < 0.

Question: What are the solutions to this differential equation?

Answer:

70

Page 71: Computational Physics IcpHaskell

In the region |x| ≤ L/2 (inside the well), we have V (x) = −V0, and so(17) reduces to

−h2

2m

d2ψin

dx2− V0ψin(x) = Eψin(x),

ord2ψin

dx2+

2m(E + V0)

h2ψin(x) = 0.

We are interested in solutions with E + V0 > 0.

Question: What are the solutions to this differential equation?

Answer:

We expect a wavefunction ψ(x) to be

ψ(x) =

{

ψout(x), |x| > L/2ψin(x), |x| ≤ L/2

To get the full solutions ψ(x) , we need to match

71