intro: computational physics

54
Intro: Computational Physics Nov 16, 2020

Upload: others

Post on 30-Nov-2021

15 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Intro: Computational Physics

Intro: Computational Physics

Nov 16, 2020

Page 2: Intro: Computational Physics
Page 3: Intro: Computational Physics

Python

1 About the course 3

2 Important links and info 5

3 Topics 7

4 A very quick introduction 9

5 Main references 11

6 Table of contents 13

i

Page 4: Intro: Computational Physics

ii

Page 5: Intro: Computational Physics

Intro: Computational Physics

Prof. Dr. Gerson J. FerreiraInstitute of Physics, Federal University of Uberlândiagjferreira.wordpress.com

Python 1

Page 6: Intro: Computational Physics

Intro: Computational Physics

2 Python

Page 7: Intro: Computational Physics

CHAPTER 1

About the course

These are the class notes for the course Computational Physics, lectured to the students of Bacharelado em Física,Física Médica, and Licenciatura em Física from the Instituto de Física, Universidade Federal de Uberlândia (UFU).Since this is an optional class intended for students with diverse knowledge and interest in Computational Physicsand computer languages, I choose to discuss selected topics superficially with practical examples that may interest thestudents. Advanced topics are proposed as home projects to the students accordingly to their interest.

Note: Initially, I had written a book draft with examples in Julia, but since then this language has changed a lot (im-proved, actually!). The idea of this new webpage is to move the content of the book here and write examples in manylanguages (Julia, Python, and C). This will be a long process and I’ll start with Python because its documentation ismore accessible to new students. Later I’ll add examples in Julia and C, these will show up as in this Hello, world!example:

Python

print("Hello, world!")

Julia

println("Hello world!")

C

#include <stdio.h>

int main() {printf("Hello, world!\n");return(0);

}

Warning: TO DO! I have skipped, but we need to discuss:

3

Page 8: Intro: Computational Physics

Intro: Computational Physics

• Read/save files and string manipulation

• Plot images / matrices with: plt.imshow(. . . ) or plt.pcolormesh(. . . )

• 3D plot with matplotlib

• Basic calculus: contents sent by PDF, I’ll update this page as soon as possible

4 Chapter 1. About the course

Page 9: Intro: Computational Physics

CHAPTER 2

Important links and info

To access the class on MS Teams, use the code igor2v3. All classes are recorded and available at the MS StreamChannel Intro Fis Comp 2020

5

Page 10: Intro: Computational Physics

Intro: Computational Physics

6 Chapter 2. Important links and info

Page 11: Intro: Computational Physics

CHAPTER 3

Topics

Since this is an introductory course, we’ll focus on simple topics that are useful to solve physics problems. Namely:

1. Introduction to the computer language

2. Plotting beautiful figures

3. Numerical calculus: integrals, derivatives, root finding, . . .

4. Linear algebra: system of eqs., eigenvalues, . . .

5. Differential equations: initial value problems and boundary value problems

6. Fourier transforms

7. Random numbers and statistics

8. Machine / Deep learning (soon)

All these topics will be applied to solve physics problems in exercies along the course.

7

Page 12: Intro: Computational Physics

Intro: Computational Physics

8 Chapter 3. Topics

Page 13: Intro: Computational Physics

CHAPTER 4

A very quick introduction

Let’s start with a very short introduction. In computational physics a lot of things work by dropping the limits:

𝜕𝑓(𝑥)

𝜕𝑥= lim

Δ𝑥→0

𝑓(𝑥 + ∆𝑥) − 𝑓(𝑥)

∆𝑥≈ 𝑓(𝑥 + ∆𝑥) − 𝑓(𝑥)

∆𝑥(4.1)∫︁

𝑓(𝑥)𝑑𝑥 = limΔ𝑥→0

∑︁𝑛

𝑓(𝑥0 + 𝑛∆𝑥)∆𝑥 ≈∑︁𝑛

𝑓(𝑥0 + 𝑛∆𝑥)∆𝑥(4.2)

That’s it. Everything else is variations of these approximations. Now, let’s go into the details.

9

Page 14: Intro: Computational Physics

Intro: Computational Physics

10 Chapter 4. A very quick introduction

Page 15: Intro: Computational Physics

CHAPTER 5

Main references

Let’s split the main references into online tutorials, links to examples and books. I’ll add more general references hereas I write about each topic, while each topic will have specific references in the text.

Online tutorials, documentation and useful links

1. Python at Tutorial’s point: [python], [numpy], [matplotlib]

2. Official documentation for [numpy - scipy - matplotlib]

3. Python’s Anaconda distribution

Books

About computational physics and related:

1. Nicholas J. Giordano & Hisao Nakanishi - Computational Physics

2. Tao Pang – An Introduction to Computational Physics

3. Jos Thijssen – Computational Physics

4. Philipp O. J. Scherer – Computational Physics: Simulation of Classical and Quantum Systems

5. Cláudio Scherer – Métodos Computacionais da Física

6. Páez & Bordeianu – Computational Physics – Problem Solving with Python

7. Saul Teukolsky, William H. Press, and William T. Vetterling - Numerical Recipes

Numerical calculus:

1. Neide B. Franco - Cálculo numérico

2. Selma Arenales, Artur Darezzo - Cálculo numérico: aprendizagem com apoio de software

3. John C. Butcher - Numerical methods for ordinary differential equations

11

Page 16: Intro: Computational Physics

Intro: Computational Physics

12 Chapter 5. Main references

Page 17: Intro: Computational Physics

CHAPTER 6

Table of contents

6.1 Introduction to python

print("Hello, world!")

Python is one of the most used computer languages nowadays. It’s an interpreted language, but highly efficient sinceits libraries typically call Fortran or C codes on their backend. Its Wikipedia article has a bit of its history and links tointeresting texts and books.

Here I’ll give a brief introduction to essential features of the language and how to use it. I suggest we use the Anacondadistribution, since it runs equally well in Linux, Windows and Mac. Also, besides my introduction below, check alsothese tutorials:

1. Python at Tutorial’s point: [python], [numpy], [matplotlib]

2. Official documentation for [numpy - scipy - matplotlib]

3. Official documentation: how to install Anaconda

4. Youtube video (in Portuguese) Como instalar Anaconda em Windows e Linux

6.1.1 The IDEs

The Integrated Development Environments (IDEs) are the softwares that we use to edit / debug / run our codes. Here,I’ll suggest we start with these two that are already installed with Anaconda:

• Jupyter: is a web-based IDE that runs in your browser. It runs the code in cells and allows you to use markdownand Latex to document your code. Since jupyter integrates code, documentation and images, I recommend westart with this one. The name jupyter refers to the three initial languages it was design to support: julia, python,and R.

• Spyder IDE: is a traditional IDE with the text editor and dedicated panels for the output and figures. The nameSpyder means Scientific Python Development Environment. The figure below shows how it looks like.

13

Page 18: Intro: Computational Physics

Intro: Computational Physics

The images below show how these IDE look like, click to zoom.

The Jupyter IDE The Spyder IDE

Other very interesting IDEs are the PyCharm and VS Code. I actually use VS Code for everything: python, C, andeven for writting this webpage. But if you are a beginner, I recommend you first try Spyder or Jupyter.

Note: Jupyter vs Spyder: Both are great IDEs, however, they are quite different from each other. Their main prosand cons are:

• Jupyter

– (pro) Saves in a single notebook the code, markdown/latex notes, and the figures/plots;

– (pro) Run code in cell blocks that allow you to split calculations and plots;

– (con) The notebook (.ipynb) is not a simple text file, but a json file;

– (con) There’s no structure for debugging.

• Spyder

– (pro) Saves the code as simple text (.py);

– (pro) It has a native debugging structure;

– (pro) Allows you to run individual cells (similar to jupyter);

– (con) Figures must be saved into files for storage.

Using the IDEs

More details will be covered in the first class with simple examples, but here are the most important things to remember.

• Jupyter: The code runs in blocks called cells. To run a cell type SHIFT+ENTER. The jupyter codes aresaved in a json format (extension .ipynb) and are called ipython notebooks, which allows you to save the code,markdown and images in a single file.

Warning: Evidently, you can run the cells out of order while developing, but the final code should be organizedto run cell-by-cell in order.

The following keyboard shortcuts run in Command mode, which is activated by pressing ESC. A full list of shortcutscan be seen by pressing ESC+H. To add a cell, type ESC+A to add above or ESC+B to add below. To delete a celltype ESC+D+D.

14 Chapter 6. Table of contents

Page 19: Intro: Computational Physics

Intro: Computational Physics

To change a cell type check the buttons bar at the top of the window you see a list of cell types. The most importantones are code and markdown. In the markdown mode you can write formatted text and Latex equations, which is quiteuseful to document your code and present the results. You can also change the cell to markdown mode by callingESC+M, and back to code mode with ESC+Y.

• Spyder: This IDE works with simple text files (extension .py). To run the (entire) code you press F5. Spydercan also work with cells, which are defined by # %% Cell Name. The Cell Name is optional, but helps withthe organization of the code. To run only the current cell and advance to the next, you press Shift + Enter.

Warning: It might be important to check the workspace directory on the top right corner of the window, as itdefines the relative path to read and save files.

Spyder allows you to choose how to show the plots/images. To find the options go to Tools > Preferences >IPython console > Graphics > Backend. To capture the plots into the Spyder panel, choose inline, andto plot as a separate window, choose automatic.

6.1.2 Variables, data types and operations

For those used to C and Fortran, it seems weird that variables don’t need to be declared. Their type is inferred bythe assignment, which can be checked using the type(...) call. Try running these examples

Listing 1: Example: Assignment and data types

1 # These will all be integers2 a = 33 b = 44 c = a**2 + b**25 print('type of a is', type(a))6 print('type of b is', type(b))7 print('type of c is', type(c), ' and its value is', c)8

9 # These are floats (floating point, real numbers)10 x = 1/311 y = 4.212 z = a/b13 Na = 6.022e23 # here 1e23 = 1023

14 print('x =', x, ' has type', type(x))15 print('y =', y, ' has type', type(y))16 print('z =', z, ' has type', type(z))17 print('Na =', Na, ' has type', type(Na))18

19 # For complex numbers, use j instead if i20 c = 4.5 + 3.1j21 d = 2 + 3j22 print('c =', c, 'has type', type(c))23 print('d =', d, 'has type', type(d))24

25 # Strings26 s = 'hello world!'27 print(s, 'is a ', type(s))28

29 # Mixing strings and numbers with the str(...) cast30 # 1st, using an integer to label a file31 n = 8

(continues on next page)

6.1. Introduction to python 15

Page 20: Intro: Computational Physics

Intro: Computational Physics

(continued from previous page)

32 myfile = 'somefile' + str(n) + '.txt'33 print('File name:', myfile)34 # 2nd, now using a float, but rounding it up35 x = 1/336 myfile = 'somefile' + str(round(x, 2)) + '.txt'37 print('File name:', myfile)

In the last lines above we use the str(...) call to cast its argument into a string. You can also use casting to integerswith int(...) or floats with float(...). Try it! Above we use round(..., n) to trim a number up to ndigits.

Arithmetic operations

Check these examples:

Listing 2: Example: arithmetic operations

1 # let's start assigning numbers to x and y2 x = 53 y = 24

5 # and now let's operate and print the results6 print('addition: ', x + y)7 print('subtraction: ', x - y)8 print('multiplication: ', x * y)9 print('division: ', x / y)

10 print('exponentiation: ', x**y)11 print('remainder: ', x % y)

Besides the simple assignments, python allows for increments. For instance, x += 2 is the same as x = x + 2.Try these examples:

Listing 3: Example: assignment with increments

1 # let's start with a simple assignment2 x = 23 # and apply the increments4

5 x += 5 # the same as x = x + 56 print('now x =', x)7

8 x -= 5 # the same as x = x - 59 print('now x =', x)

10

11 x /= 2 # the same as x = x / 212 print('now x =', x)13

14 x *= 2 # the same as x = x * 215 print('now x =', x)

Notice in the example above that the type of x has changed at some point. Why?

16 Chapter 6. Table of contents

Page 21: Intro: Computational Physics

Intro: Computational Physics

Comparisons and logical operations

Comparisons operations are simple ==, >, < and etc. The logical operations act on True or False values bycombining it with and, or, not operations. We’ll see how to use comparisons with if and loops later. For now, let’scheck the examples:

Listing 4: Example: Comparisons and logical operations

1 x = 32 y = 43 z = 34

5 # simple comparisons6 print('is x larger than y?', x > y)7 print('is y larger than z?', y > z)8 print('is x larger or equal to z?', x >= z)9 print('is x different than z?', x != z)

10 print('is z equal to z?', x == z)11

12 # composed comparisons13 print('is x larger than both y and z?', x > y and x > z)14 print('is x larger or equal to z?', x > z or x == z) # the same as x >= z15 print('is x between 1 and 7?', 1 <= x <= 7)

Comparisons and floats: BE VERY CAREFUL! You should NEVER use == to check equivalence between floats,and this example shows why:

Listing 5: Example: Error comparing floats

1 x = 0.12 y = 3 * x3 z = 0.34

5 # should both questions be True?6 print('obviously z == 0.3 by definition, right?', z == 0.3)7 print('and y is also 0.3, right?', y == z)8

9 # let's check the values10 # the format call allows you to specify the number of digits11 print('x = ', format(x, '0.30f'))12 print('y = ', format(y, '0.30f'))13 print('z = ', format(z, '0.30f'))

What’s happening there? Shouldn’t both be 0.3???? While 0.1 and 0.3 are exact in base 10, in binary they are repeatingfractions: (0.3)10 = (0.0[1001])2, and (0.1)10 = (0.0[0011])2. The numbers between [. . . ] are the repeating pattern.Since numbers are stored in memory with 64 bits (typically), it requires a truncation. For instance, if you truncate afterthree repetitions, the 0.1 becomes (0.0001100110011)2 = (0.0999755859375)10, and the 0.3 is (0.0100110011001)2 =(0.2999267578125)10.

Lists and dictionaries

A list in python is indeed a list of whatever elements. You can mix oranges and bananas. . . and numbers as well. Thisis different from an array, which is a structure with a well defined type and we’ll discuss within the numpy section.Let’s focus on generic lists for now, check the example:

6.1. Introduction to python 17

Page 22: Intro: Computational Physics

Intro: Computational Physics

Listing 6: Example: lists and operations on lists

1 # using only strings for now2 cart = ['banana', 'oranges'] # init list with two items3 cart.append('apple') # add an item4 cart.sort() # sort alphabetically5

6 print('Number of elements:', len(cart)) # len from length7 print('The first item: ', cart[0]) # indexes start from 08 print('The last item: ', cart[-1]) # and you can count backwards9 print('Is there bananas?', 'banana' in cart) # a membership comparison

Above we have used in, which is a membership comparison and be used with if and loops below.

Now let’s start with an empty list and mix types as we add to the list:

Listing 7: Example: mixing types

1 mylist = [] # start empty2 mylist.append(2) # add an integer3 mylist.append(2.0) # and an float4 mylist.append('two') # add an string5

6 print('The list:', mylist)

Warning: A list is not a mathematical vector, it does not support mathematical operations. For instance, the codex = [1, 2, 3] and y = 2*x WILL NOT GIVE [2, 4, 6], instead, it repeats the list twice to give [1,2, 3, 1, 2, 3]. This is useful to create long lists with a repeated pattern.

The mathematical vectors will be defined within the numpy package as x = np.array([1, 2, 3]). In thiscase the call y = 2*x will return [2, 4, 6].

Dictionaries

It can be useful to use a list of mixed types to store different parameters for your code. But it’s even better to usedictionaries. It basically works like a list, but instead of using integers 0, 1, . . . as indexes, it uses strings or integers.Let’s check:

Listing 8: Example: using dictionaries to store parameters

1 pars = {} # init an empty dictionary2

3 pars['T'] = 273 # K4 pars['P'] = 1.013e5 # Pa5 pars['V'] = 22.4 # L6 pars['filename'] = 'myfile.txt'7 pars[5] = 'five' # useless example as an example8

9 # let's change a value10 pars['T'] = 30011

12 # and print all13 print('Temperature is', pars['T'])14 print('Pressure is', pars['P'])

(continues on next page)

18 Chapter 6. Table of contents

Page 23: Intro: Computational Physics

Intro: Computational Physics

(continued from previous page)

15 print('Volume is', pars['V'])16 print('Store in file: ', pars['filename'])17 print('Element 5 is: ', pars[5])

Notice above that we can use an integer 5 as the index, but it is not as useful as using strings. The idea is to use itwhen your code has many parameters, and it’s easier to pass it around as a dictionary instead of using many. . . manyarguments on each function. Use it wisely!

6.1.3 Decision making: if / else / etc. . .

Using if/else is as simple as in any other language. We just need to check the syntax. But remember that we can usethe simple comparisons >, <, >=, <=, !=, the logical operators and, or, not and membership operatorsin, not in. Let’s check it:

Listing 9: Example: if / else and comparisons

1 # let's start with a simple one2 a = 33 b = 44 if a > b:5 print('a is larger than b')6 elif a < b:7 print('b is larger than a')8 else:9 print('they are equal')

10

11 # now let's check a membership comparison with lists12 cart = ['apple', 'banana', 'orange']13

14 if 'grape' in cart:15 print('yes, we have grapes')16 else:17 print('no, we need grapes')

Notice that the structure has no termination. The segment is delimited by the indentation.

6.1.4 Loops: for / while and comprehensions

The loop for is usually used when it runs over a predefined list of elements, while the while uses a less predictabletermination point. Let’s start with the for:

Listing 10: Example: using a for loop over lists

1 # let's use our fruits again2 cart = ['apple', 'banana', 'orange']3 for fruit in cart:4 print('we have:', fruit)5

6 # similarly, you could also do7 for i in range(len(cart)):8 print('item', i, ' is', cart[i])

So you can loop over the elements of a list using the membership operator in, or you can use an integer i to loopover the indexes. In this case we use len(cart) to get the number of elements in the list (3) and the command

6.1. Introduction to python 19

Page 24: Intro: Computational Physics

Intro: Computational Physics

range(...) to create a list of integers. Let’s check how range works in this example:

Listing 11: Example: using range

1 # range(n) = 0..n-12 for i in range(10):3 print(i)4

5 # range(ni, nf) = n1..nf-16 for i in range(3, 15):7 print(i)8

9 # range(n1, nf, step) takes steps instead of increasing by 110 for i in range(1, 15, 2):11 print(i)

Warning: Notice that range defines an interval closed at the left side and open at the right side.

range(init, end, step) goes from init to end-1 in steps of step

You can use any type of lists or arrays (numpy) to delimit the for loop.

Now let’s check a while example:

Listing 12: Example: using while to sum 1 + 1/2 + 1/4 + 1/8. . . until thenew element is small enough

1 x = 1 # init x2 s = 0 # and init the sum3 # loop until x is small enough4 while x > 1e-5:5 s += x # add to the sum6 x /= 2 # update x7

8 # print the results9 print('the final x =', x)

10 print('the sum s =', s)

Above we are not specifying the number of loops, but looping until x gets small enough.

A compact for loop can be used to define lists as comprehensions. Check this example:

20 Chapter 6. Table of contents

Page 25: Intro: Computational Physics

Intro: Computational Physics

Listing 13: Example: comprehensions

1 # let's start with a list for the example2 x = [0, 2, 4, 5, 9]3

4 # and define y using a comprehension:5 y = [xi**2 for xi in x]6

7 print('x = ', x)8 print('y = ', y)

The comprehension executes the code before the for for each element in the list.

6.1.5 Functions and scope of variables

As usual, functions take arguments and returns something. The main differences from C/Fortran is that a function canreturn more than one object. Also, there’s a compact form for inline functions called lambda functions. Let’s checkthe examples:

Listing 14: Example: simple functions

1 # import the square root from the complex math library2 from cmath import sqrt3

4 # define the function5 # here c has a default value6 def bhaskara(a, b, c=0):7 d = sqrt(b**2 - 4*a*c)8 x1 = (-b+d)/(2*a)9 x2 = (-b-d)/(2*a)

10 return x1, x211

12 # calling the function13 s1, s2 = bhaskara(1, 2, -15)14 print('sols:', s1, 'and', s2)15

16 # let's call again with different numbers17 x1, x2 = bhaskara(1, 5, 0)18 print('sols:', x1, 'and', x2)19

20 # above, we could have omitted c21 x1, x2 = bhaskara(1, 5)22 print('sols:', x1, 'and', x2)23

24 # a final example25 x1, x2 = bhaskara(1, 2, 2)26 print('sols:', x1, 'and', x2)

Above we are importing the sqrt from the cmath library to allow for complex numbers.

The function bhaskara receives three parameters, but the third one has a default keyword argument. If not informed,it’s assumed to be zero as indicated. At the end, the function returns two values, x1 and x2, which are attributed to twovariables on the calls that follow.

6.1. Introduction to python 21

Page 26: Intro: Computational Physics

Intro: Computational Physics

The scope

Notice above that we have variables x1 and x2 within the function bhaskara, and also outside the function. These arenot the same variables. The (x1,x2) variables within bhaskara have the same name but are not the same variables asthose (x1,x2) outside. To make it clear, let’s try this other example, which you could run in debug mode to follow thevalues of the variables.

Listing 15: Example: scope of a variable

1 # some random function2 def f(x):3 a = 104 s = a * x**25 return s6

7 # let's call it directly8 print('the value of f(10) is', f(10))9

10 # is x, a, or s defined?11 print('x =', x)12 print('a =', a)13 print('s =', s)14

15 # let's try again16 a = 017 print('is f(10) now zero?', f(10))18

19 # let's define x20 x = 521 print('x is now = ', x)22 print('for this x we have f(x)=', f(x))23

24 # let's call f(10) again25 print('the value of f(10) is', f(10))26 print('did it change the value of x? x=', x)

We have to understand the local scope of each variable:

Within the function f(x), its argument x and the inner variables a and s are local variables, their value and definitionare set only within the function and are not accessible outside unless you return their values. On the outside, the aand x defined in lines 16 and 20 are on the global scope.

The lambda functions

A lambda function is simple a short notation for short functions:

Listing 16: Example: the lambda functions

1 # let's start by defining a very simple function2 def f(x, y):3 return x**y4

5 # which can be defined also as a lambda function6 g = lambda x, y: x**y7

8 # let's compare:

(continues on next page)

22 Chapter 6. Table of contents

Page 27: Intro: Computational Physics

Intro: Computational Physics

(continued from previous page)

9 print('calling f:', f(2, 10))10 print('calling g:', g(2, 10))

The lambda function is defined such that the arguments follow the keyword lambda and the direct return follows afterthe :

6.1.6 Importing libraries

The core of python comes with many functionalities, but it always need to be complemented with external librariesusing import as shown above for cmath. There are many ways to import a library.

You should avoid importing like this:

Listing 17: Example: causing a conflict with BAD IMPORTS

1 # this imports only the sqrt command from math2 from cmath import sqrt3

4 # this imports sqrt from math (non-complex math library)5 from math import sqrt6

7 # you could, but shouldn't import everything as well8 from math import *

Warning: Notice that by calling from math import * or the other examples above you may cause conflictssince the sqrt function exists in more than one library. The correct way is shown next.

The proper way to import a library is:

Listing 18: Example: safe import

1 import math as rm2 import cmath as cm3 # the import alias do not have to be rm and cm, you can choose whatever (?) you want4

5 # using the real math library6 print('The square root of 2 is: ', rm.sqrt(2))7

8 # using the complex math library9 print('The square root of +2 is: ', cm.sqrt(+2))

10 print('The square root of -2 is: ', cm.sqrt(-2))

It’s a pain to carry the objects rm. or cm. up and down the code, but that’s the safe way and you should use it!

Above we use rm and cm as alias to make the calls shorter, but you could have also used simply import mathwithout an alias. In this case the calls would be math.sqrt(2) and so on.

In practice, always try to use common alias for the libraries, for instance, we’ll use these a lot:

Listing 19: Example: common libraries and their alias

1 import numpy as np2 import scipy as sp3 import matplotlib.pyplot as plt

6.1. Introduction to python 23

Page 28: Intro: Computational Physics

Intro: Computational Physics

6.1.7 Reading/saving files and string manipulation

To save data files it might be better use the numpy package. The discussion here will be more useful to read or savestructured files. An important example would be to read a file with parameters for your code.

Commands to discuss:

• open and close, using with

• read / readline

• write / writelines

• print(data, file=open(filename, 'w'))

• find / replace

• split into list

• . . .

6.2 Introduction to matplotlib

Matplotlib is the main library for plots in python. Check its webpage for the main documentation, tutorials andexamples. There’s also a good discussion on Tutorial’s point.

6.2.1 How to organized data for a simple plot?

To plot something we need the data. Typically this means using numpy, which we will discuss in details on the nextchapter. For now, let’s check only a few numpy commands to help us organize the data and make plots.

Just like in your first lab classes, to plot something on a graph paper (papel milimetrado in Portuguese), you need aset of (x,y) points on a table, for instance:

t(s) S(cm)0.8 4.02.2 6.02.8 7.5. . . . . .

The data on the table is then used to draw the points in the graph paper, as in this figure.

24 Chapter 6. Table of contents

Page 29: Intro: Computational Physics

Intro: Computational Physics

A first example

So, to prepare the data we need a list of points organized as the x and y coordinates. For instance, consider this firstexample:

Listing 20: Plot the data

1 import matplotlib.pyplot as plt2

3 # define the points as lists4 x = [ 0.8, 2.2, 2.8, 3.8, 5.2, 6.3, 7.3, 7.9, 9.4, 10.0 ]5 y = [ 4.0, 6.0, 7.5, 12, 15, 17.5, 22, 23, 27, 30 ]6

7 # plot as points8 plt.scatter(x, y, color='black')9 # add elements to the the figure

10 plt.xlabel('t (s)')11 plt.ylabel('S (cm)')12 plt.grid()13 # finish the plot14 plt.show()

This code will give you a plot similar to the paper graph example above.

Let’s understand the code:

• x and y are simple lists of points, where each pair of numbers form a point (x,y) just like in the table shownabove. Instead of lists, these could also be numpy arrays.

• we have imported the pyplot sublibrary with the alias plt, which is the object that now controls our plots.

• the scatter command make plots with points. It takes as required arguments the list of x and y points. Optionally,you may inform the color of for the points and many other options that we’ll discuss later.

• the xlabel or ylabel commands define the labels for the axes from the string arguments. You can also use Latexcommands as we’ll se below.

• the grid command adds the vertical and horizontal grids. It’s not necessary, but sometimes makes the plot easierto read.

• the show command finishes the plot and show the results. It’s not always needed, but I strongly recommendthat you always finish the plot calling the show command for safety.

But it is missing the red line that fits the data! Let’s add it using numpy as in this next example:

6.2. Introduction to matplotlib 25

Page 30: Intro: Computational Physics

Intro: Computational Physics

Listing 21: Plot the data and fit with a polynomial

1 import matplotlib.pyplot as plt2 import numpy as np3

4 # now we need x and y to be numpy arrays5 x = np.array([ 0.8, 2.2, 2.8, 3.8, 5.2, 6.3, 7.3, 7.9, 9.4, 10.0 ])6 y = np.array([ 4.0, 6.0, 7.5, 12, 15, 17.5, 22, 23, 27, 30 ])7

8 # fit the data as a polynomial of order 1: y = c0*x1 + c1

9 c = np.polyfit(x, y, 1)10 # apply fit on x to get the fitted yf11 yf = c[0]*x + c[1]12

13 # plot the points14 plt.scatter(x, y, color='black')15 # and plot the fitted line16 plt.plot(x, yf, color='red')17 # add elements18 plt.xlabel('t (s)')19 plt.ylabel('S (cm)')20 plt.grid()21 # and finish the plot22 plt.show()

The figure now looks quite similar to the graph paper example above.

Table 1: Pyplot figure matching the example above with points and fit

Let’s discuss the new elements in the second example above.

• instead of lists, now x and y are defined as numpy arrays so we can operate on them as mathematical vectors.

• the polyfit command from numpy returns the coefficients of fitted polynomial, the parameter 1 at the end indi-cates the order of the polynomial. For instance, if we had fitted for a polynomial or order n=2, the coefficientswould represent 𝑦 = 𝑐0𝑥

2 + 𝑐1𝑥 + 𝑐2. . . notice that the indexes of the coefficients go from 0 to n, while thepowers of x go from n to 0. . . it’s awful, but blame the numpy devs, not me! At line 11 we define yf as an arraycomposed by 𝑦𝑓 = 𝑐0𝑥 + 𝑐1.

• while the scatter command plot points, the plot command plots lines connecting the points defined by the listsor arrays (x, yf), and now we choose the color red to match the paper graph example.

Note: Here I’m using the polyfit from numpy because it is quite simple to use. However, for more complicated fits it

26 Chapter 6. Table of contents

Page 31: Intro: Computational Physics

Intro: Computational Physics

is better to use the curve_fit command from scipy.

Adding error bars

Since the example above deals with uncertain data and a fit for the best curve, it’s also interesting to add error bars.So, let’s consider the yerr as uncertainties in the y data to plot this next example.

Error bars

1 import matplotlib.pyplot as plt2 import numpy as np3

4 # now we need x and y to be numpy arrays5 x = np.array([ 0.8, 2.2, 2.8, 3.8, 5.2, 6.3, 7.3, 7.9, 9.4, 10.0 ])6 y = np.array([ 4.0, 6.0, 7.5, 12, 15, 17.5, 22, 23, 27, 30 ])7 yerr = np.array([2, 3, 3, 2, 1, 4, 2, 3, 2, 3])8

9 # fit the data as a polynomial of order 1: y = c0*x1 + c1

10 c = np.polyfit(x, y, 1)11 # apply fit on x to get the fitted yf12 yf = c[0]*x + c[1]13

14 # plot the points with error bars15 plt.errorbar(x, y, yerr=yerr, color='black', fmt='o')16 # and plot the fitted line17 plt.plot(x, yf, color='red')18 # add elements19 plt.xlabel('t (s)')20 plt.ylabel('S (cm)')21 plt.grid()22 # and finish the plot23 plt.show()

The plot

6.2. Introduction to matplotlib 27

Page 32: Intro: Computational Physics

Intro: Computational Physics

About the code

Here we have replaced the scatter with the errobar call, where now we inform the yerr parameter with the list ofuncertainties for each point, and the option fmt=’o’ selects the scatter-type of plot with circles as symbols.

6.2.2 Make it look good!

Now let’s check another example using trigonometric functions that will allow us to discuss many details on how toimprove the plot. Let’s start small with a very simple plot.

The code

1 import numpy as np2 import matplotlib.pyplot as plt3

4 x = np.linspace(0, 2*np.pi, 100)5 y1 = np.sin(x)6 y2 = np.cos(x)7

8 plt.plot(x, y1)9 plt.plot(x, y2)

10 plt.show()

The plot

About the code

• np.linspace(x0, xf, xpts) creates an array of xpts from x0 to xf.

• np.sin / np.cos not only calculates the trigonometric functions, but does it for all points in the array x. This iscalled a broadcast and it is one of the main advantages of using numpy, as we’ll see in more details on the nextchapter.

How can we improve it?

• make the fonts larger;

• add labels using Latex to get greek symbols like 𝜃;

28 Chapter 6. Table of contents

Page 33: Intro: Computational Physics

Intro: Computational Physics

• add legends;

• change the line style;

• save the figure;

• . . .

Let’s try one by one. First let’s increase the font size.

Font size

1 import numpy as np2 import matplotlib.pyplot as plt3

4 plt.rcParams.update({'font.size': 16})5

6 x = np.linspace(0, 2*np.pi, 100)7 y1 = np.sin(x)8 y2 = np.cos(x)9

10 plt.plot(x, y1)11 plt.plot(x, y2)12 plt.ylabel('Trigonometric functions', fontsize=18)13 plt.show()14

15 # extra: check default rc parameters file at:16 import matplotlib17 print(matplotlib.matplotlib_fname())

The plot

About the code

the rcParams define the matplotlib configuration and can be updated as shown in the example using dictionaries withthe parameter names and values. There, the ‘font.size’ parameter will apply to all text in the plot. Alternatively, youcan also specify the ‘fontsize’ in specific elements of the plot, as in the ylabel line.

The default parameters are set in a text file. The last lines, after extra prints the location of this textfile. For more

6.2. Introduction to matplotlib 29

Page 34: Intro: Computational Physics

Intro: Computational Physics

information, check the matplotlibrc file documentation. The link has a sample of the default matplotlibrc file with thedefault parameters.

Warning: You should never edith the matplotlibrc default file, as it gets overwritten if you reinstall or updatematplotlib. Instead, always make a copy to the user location.

On windows: c:/users/<nameoftheuser>/.matplotlib/matplotlibrc

On Linux: ~/.config/matplotlib/matplotlibrc

Now let’s use Latex on the labels and add legends.

Labels and legends with Latex

1 import numpy as np2 import matplotlib.pyplot as plt3 plt.rcParams.update({'font.size': 20})4 plt.rcParams.update({'text.usetex': True})5

6 x = np.linspace(0, 2*np.pi, 100)7 y1 = np.sin(x)8 y2 = np.cos(x)9

10 plt.plot(x, y1, label=R'$\sin\theta$')11 plt.plot(x, y2, label=R'$\cos\theta$')12 plt.legend(fontsize=15)13 plt.xlabel(R'$\theta$ [rad]')14 plt.ylabel(R'Trigonometric functions')15 plt.tight_layout()16 plt.show()

The plot

About the code

• Now we are updating the rcParams to set the option text.usetex = True.

30 Chapter 6. Table of contents

Page 35: Intro: Computational Physics

Intro: Computational Physics

• On the plot commands, we add the option label that will be used by the command plt.legend() to create thelegends.

• On all labels we add an R before the strings to inform that the string should be read as it is (raw). This is neededto pass their values correctly to Latex.

Notice in the figure above that now all fonts are set to the Computer Modern font from Latex.

Now let’s make it look good!

Full example

1 import numpy as np2 import matplotlib.pyplot as plt3 plt.rcParams.update({'font.size': 20})4 plt.rcParams.update({'text.usetex': True})5 plt.rcParams.update({'text.latex.preamble' : r'\usepackage{amsmath}'})6

7 x = np.linspace(0, 2*np.pi, 100)8 y1 = np.sin(x)9 y2 = np.cos(x)

10 y3 = np.tan(x)11

12 plt.figure(figsize=(6, 5))13 plt.plot(x, y1, label=R'$\sin\theta$')14 plt.plot(x, y2, label=R'$\cos\theta$', ls='--')15 plt.plot(x, y3, label=R'$\tan\theta$', ls='-.')16 plt.legend(fontsize=15, loc=(0, 1.05), ncol=3)17 plt.xlabel(R'$\theta$ [rad]')18 plt.ylabel(R'Trigonometric functions')19 plt.xticks([0, np.pi/2, np.pi, 3*np.pi/2, 2*np.pi], ["0", R"$\dfrac{\pi}{2}$", R"$\pi$

→˓", R"$\dfrac{3\pi}{2}$", R"$2\pi$"])20 plt.xlim(0, 2*np.pi)21 plt.ylim(-2, 2)22 plt.grid()23 plt.tight_layout()24 plt.savefig('ex2-step4.png', dpi=300)25 plt.show()

The plot

6.2. Introduction to matplotlib 31

Page 36: Intro: Computational Physics

Intro: Computational Physics

About the code

• rcParams allow you to inform a Latex preamble, where you can import your Latex packages;

• the line style parameter (ls) in plt.plot allows you to choose between solid (‘-‘), dashed (‘–’), dash-dot (‘-.’), anddotted (‘:’). For more, check the plot documentation and this more advanced example;

• now the legend is specified with a location (loc) and number of columns (ncol). For more options, check thelegend documentation;

• the x ticks are now explicitly set on the most relevant points, and the numbers are replaced by labels using Latex.Notice that the first parameter is a list of points and the second a list of strings replacing those points. The samecould be applied for the y ticks;

• The xlim and ylim define the ranges of the plot. It’s needed now because the tangent diverges at pi and 2pi.

• The tight_layout() command is really important! It makes small adjustments to fit the figure into the boundingbox, otherwise the figure could be cropped. It’s even more important when using subplots (see below).

• The last command saves the figure into a file. The file type is set by the extension (png, jpg, svg, pdf, . . . ).Additionally, I’m setting the dpi to improve the resolution of the pnf file. Another interesting parameter tocheck is transparent = True, try it!

6.2.3 Panels (subplots) and insets

Let’s see examples how to break your figure into panels and insets. We’ll use the plt.text command to place labels (a),(b), . . .

Insets are a figure within another. Let’s use it to plot the damped oscillations in a large and small scales.

Using insets

32 Chapter 6. Table of contents

Page 37: Intro: Computational Physics

Intro: Computational Physics

1 import numpy as np2 import matplotlib.pyplot as plt3 plt.rcParams.update({'font.size': 20})4 plt.rcParams.update({'text.usetex': True})5 plt.rcParams.update({'text.latex.preamble' : r'\usepackage{amsmath}'})6

7 x = np.linspace(0, 5, 2000)8 y = np.sin(200*x) * np.exp(-x)9

10 plt.figure()11

12 plt.plot(x, y)13 plt.xlabel(R'$t$')14 plt.ylabel(R'$y(t)$')15

16 # get the main axes17 ax = plt.gca()18 # define the inset axes19 ins = ax.inset_axes([0.6, 0.6, 0.37, 0.37])20

21 # plot whathever you need as a sub-range of the main plot22 ins.plot(x, y)23 ins.set_xlim(1.5, 1.7)24 ins.set_ylim(-0.3, 0.3)25 ins.set_xticklabels('')26 ins.set_yticklabels('')27

28 # draws the zoom box29 ax.indicate_inset_zoom(ins)30

31 plt.tight_layout()32 plt.show()

The plot

About the code

6.2. Introduction to matplotlib 33

Page 38: Intro: Computational Physics

Intro: Computational Physics

• plt.gca() gets the current axes. This object is needed when dealing with multiple axes.

• inset_axes([x0, y0, dx, dy]) defines the axes location at (x0,y0) with size (dx,dy). These numbers are specifiedwith resect to the parent axes and range from 0 to 1.

• when acting on the axes object, we need to use set_xlim instead of xlim as in the previous examples. We havealso set set_xticklabels to blank.

• the last command indicate_inset_zoom is optional, but awesome for this kind of inset that represents a zoom.It draws the zoom box by connecting the ranges of the main axes and the inset axes.

Another useful structure is to break your plot into panels, as in the example below.

Subplots on simple grid

1 import numpy as np2 import matplotlib.pyplot as plt3 plt.rcParams.update({'font.size': 20})4 plt.rcParams.update({'text.usetex': True})5 plt.rcParams.update({'text.latex.preamble' : r'\usepackage{amsmath}'})6

7 x = np.linspace(-10, 10, 100)8 y1 = np.sin(x)/x9 y2 = np.exp(-x**2)

10 y3 = np.tanh(x)11 y4 = x**212

13 plt.figure(figsize=(8,5))14

15 plt.subplot(2, 2, 1)16 plt.plot(x, y1)17 plt.xlabel(R'$x$')18 plt.ylabel(R'$\sin(x)/x$')19 plt.text(0.05, 0.75, R'(a)', transform=plt.gca().transAxes)20

21 plt.subplot(2, 2, 2)22 plt.plot(x, y2)23 plt.xlabel(R'$x$')24 plt.ylabel(R'$g(x)$')25 plt.text(0.05, 0.75, R'(b)', transform=plt.gca().transAxes)26

27 plt.subplot(2, 2, 3)28 plt.plot(x, y3)29 plt.xlabel(R'$x$')30 plt.ylabel(R'$\tanh(x)/x$')31 plt.text(0.05, 0.75, R'(c)', transform=plt.gca().transAxes)32

33 plt.subplot(2, 2, 4)34 plt.plot(x, y4)35 plt.xlabel(R'$x$')36 plt.ylabel(R'$x^2$')37 plt.text(0.15, 0.75, R'(d)', transform=plt.gca().transAxes)38

39 plt.tight_layout()40 plt.show()

The plot

34 Chapter 6. Table of contents

Page 39: Intro: Computational Physics

Intro: Computational Physics

About the code

• the plt.text(x, y, s) command places the label s at the point (x, y). By default it uses the data coordinates, but itis usually better to the use the panel coordinates (from 0 to 1) by specifying transform=plt.gca().transAxes.

• the plt.subplot(nl, nc, i) defines the subplots with nl lines and nc cols. The last parameter i selects the currentaxes following a Z-shape indexation.

For more information and other forms to arrange the subplots, please check the docs.

6.2.4 Animations

To make an animation we need a code that draws each frame of the video. Here we’ll check a very simple example.We draw a sine function, and at each frame i we put a red dot at the point (𝑥𝑖, 𝑦𝑖).

Subplots on simple grid

1 import matplotlib.pyplot as plt2 import matplotlib.animation as animation3 import numpy as np4

5 # data to plot6 x = np.linspace(0, 4*np.pi, 200)7 y = np.sin(x)8

9 # the function takes the frame i as a parameter10 # and plot it11 def animate(i):12 plt.clf()13 # plot the main lines14 plt.plot(x, y, color='black')15 # and a dot at the (x[i], y[i])16 plt.scatter(x[i], y[i], color='red')17 # organize the range to keep if fixed18 plt.xlim(0, 4*np.pi)19 plt.ylim(-1, 1)20

(continues on next page)

6.2. Introduction to matplotlib 35

Page 40: Intro: Computational Physics

Intro: Computational Physics

(continued from previous page)

21 # creates the animation22 ani = animation.FuncAnimation(23 fig=plt.figure(), # init the figure24 func=animate, # function call on each frame25 frames=len(x), # number of rames26 interval=20 # interval between frames in ms, the fps = 1000/interval27 )28

29 # save as gif: there are other options, mp4, ...30 ani.save(saveto + 'ex5-animation.gif', dpi=90)

The plot

About the code

• the function animate takes the frame index i and plots the function and a red dot using the frame index i to getthe element i of the x and y arrays. The plt.clf() clears the figure before each frame.

• the FuncAnimation defines the animation properties. The first parameter is the initial figure, then we set thefunction to call on each frame, the number of frames and the frame interval in miliseconds. For interval = 20,the fps = 1000/20 = 50.

• the last line saves the animation as a gif.

6.3 Introduction to numpy

First of all, we’ll always import numpy as np, so all numpy commands start with np..

These are good tutorials to complement our discussion:

• https://numpy.org/devdocs/user/quickstart.html

• https://www.w3schools.com/python/numpy_intro.asp

• https://www.tutorialspoint.com/numpy/index.htm

Together with scipy, numpy is one of the most essential libraries in python scientific computing, as it provides

• N-dimensional arrays (lists / matrices / tensors)

• Easy broadcasting of functions over lists

• Linear Algebra

• Fourier transforms

• Random numbers and matrices

• . . .

6.3.1 Numpy documentation

Always check the official numpy documentation, I’ll list useful links here:

• Mathematical functions: trigonometric, hyperbolic, sums, products, gradient, dot and cross products, exponen-tial and log, mod/remainder, real, imag and conjugate, . . .

• Array creation and array manipulation to create and manipulate lists, vectors and matrices.

36 Chapter 6. Table of contents

Page 41: Intro: Computational Physics

Intro: Computational Physics

• The fast Fourier transform.

• The linear algebra module with eigenvalues/eigenvectors, linear systems, matrix decompositions, . . .

• Random number generators

• . . .

6.3.2 Broadcasting

This term refers to the action of the numpy functions over lists and arrays. Check this example:

Listing 22: Example: broadcasting arrays

1 import numpy as np2

3 # define two arrays for the example4 x = np.array([0, 1, 2, 3, 4])5 y = np.array([5, 6, 7, 8, 9])6

7 # let's test some broadcasting8 print('result 1 =', x * y)9 print('result 1 =', x / y)

10 print('result 1 =', np.sin(x))11 print('result 1 =', np.exp(x) * np.log(y))

In all cases above, notice that the operations and functions act on all elements of the arrays element-wise. For instance,the code z = x * y would be equivalent to this cumbersome C-like code:

Listing 23: Example: element-wise operation without broadcasting

1 import numpy as np2

3 # define two arrays for the example4 x = np.array([0, 1, 2, 3, 4])5 y = np.array([5, 6, 7, 8, 9])6

7 # init z as a 5-element array with zeros8 z = np.zeros(5)9

10 # loop over the elements to apply z = x * y11 for i in range(5):12 z[i] = x[i] * y[i]13

14 # print the result and compare with the broadcasting15 print('without broadcasting: ', z)16 print(' with broadcasting: ', x * y)

So, the broadcasting makes the code easier to read, avoiding the unnecessary for loop. But that’s not all! The mostimportant feature here is that the broadcasting is fast! Since python is an interpreted language, loops are slow(typically), so we should always try to avoid loops and favor broadcasts. The trick here is that the broadcast isefficiently implemented within the numpy code.

Broadcasting with user defined functions

What about the functions that we implement? Will they also run broadcasts? That depends. If the function operationonly uses numpy arrays and numpy calls, it will probably allow for broadcast. Check this example:

6.3. Introduction to numpy 37

Page 42: Intro: Computational Physics

Intro: Computational Physics

Listing 24: Example: broadcast with user defined function

1 import numpy as np2 import matplotlib.pyplot as plt3

4 # sums the n first terms of the geometric geometric_series5 # for f = 1/(1-x) for |x| < 16 def geometric_series(x, n):7 f = 0*x # init as zero8 for i in range(n):9 f += x**i # sum each term

10 # return the sum11 return f12

13 # define an x array14 x = np.linspace(-0.99, 0.99, 100)15

16 # sum up to order 1017 fa = geometric_series(x, 4)18

19 # exact result for comparison20 fe = 1/(1-x)21

22 # plot results to compare23 plt.figure()24 plt.plot(x, fa, label='approximation')25 plt.plot(x, fe, label='exact')26 plt.legend()27 plt.grid()28 plt.ylim(0,3)29 plt.xlabel('x')30 plt.ylabel('f(x)')31 plt.tight_layout()32 plt.show()

Above, our geometric_series(x, n) works fine and broadcasts the calculation over the array x, but n has to bean integer. If you try to call geometric_series(x, [3,4]) passing a list on the second argument for n, it willfail because within our function n is explicitly used as an integer, while x is always compatible with a numpy array.

VECTORIZING A FUNCTION

It’s possible to convert an incompatible function into a version that accepts broadcasting. But let’s use it only in simplecases. Here I’ll reproduce one great example from the numpy documentation:

Listing 25: Example: vectorizing a function

1 import numpy as np2

3 def difforsum(a, b):4 # return a-b if a>b, otherwise return a+b5 if a > b:6 return a - b7 else:8 return a + b9

10 # vectorize the function11 vdifforsum = np.vectorize(difforsum)12

(continues on next page)

38 Chapter 6. Table of contents

Page 43: Intro: Computational Physics

Intro: Computational Physics

(continued from previous page)

13 print("this works: ", vdifforsum([1, 2, 3, 4], 2))14 print("this works: ", vdifforsum(2, [1, 2, 3, 4]))15 print("this works: ", vdifforsum([1, 2, 3, 4], [1, 2, 3, 4]))16 print("this fails: ", difforsum([1, 2, 3, 4], 2))

Notice that the vectorized function will work if: (i) one argument is an array/list and the other a scalar (int or float); or(ii) both arguments are arrays/lists with the same number of elements.

6.3.3 Arrays, vectors and matrices

A vector is a 1D array, for instance �⃗� = (𝑥, 𝑦, 𝑧) is a vector with components x = r[0], y = r[1] and z =r[2], which require only one index r[i]. A matrix is a 2D array (it has lines and columns), thus it requires twoindices: for a matrix M, the i-th line and j-th column is indexed by M[i, j]. Remember that indexes start from 0.So, the first component of the vector r is r[0] and the M matrix element in line 3 column 5 is M[2,4]. Be careful!

There are many ways to define a vector:

Listing 26: Example: different forms of defining the same vector

1 import numpy as np2

3 # explicit definition4 x = np.array([0, 1, 2, 3, 4])5

6 # using arange (initial, final not included, step)7 y = np.arange(0, 5, 1)8

9 # using linspace (initial, final included, number of elements)10 z = np.linspace(0, 4, 5)11

12 # check if they match13 print('x =', x)14 print('y =', y)15 print('z =', z)

ACCESS THE ELEMENTS OR PART OF THE ARRAY

As shown above, to access the i-th element of an array you call x[i-1]. But you can also refer to section of anarray using the form x[i:f:s], where i refers to the initial index, f the final index and s the step. If you omit s, it’sassumed s=1, and similarly the default values for the other indexes are i=0 and f=-1, which refers to the first and lastelements. See how these work in this example:

Listing 27: Example: access elements of an array

1 import numpy as np2

3 x = np.linspace(15, 30, 61)4

5 print('first 10 elements: ', x[0:10])6 print('first 10 elements: ', x[:10])7

8 print('the last element: ', x[-1])9

10 print('the last 10 elements: ', x[-10:])11

(continues on next page)

6.3. Introduction to numpy 39

Page 44: Intro: Computational Physics

Intro: Computational Physics

(continued from previous page)

12 print('every 4 elements: ', x[::4])13

14 print('some from the middle: ', x[10:15])15

16 print('all elements: ', x)17 print('all elements: ', x[:])

MATRICES

Matrices are similar to arrays, but with two indices for the lines and columns. There are many functions to help youbuild matrices, we’ll check these later. For now, let’s define a simple matrix and check how to access its elements inthis example:

Listing 28: Example: defining and accessing matrix elements

1 import numpy as np2

3 # define a matrix explicitly4 m = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])5 print('the matrix is: \n', m)6

7 print('the second line is: ', m[1, :])8

9 print('the third column is: ', m[:, 2])10

11 print('the last column is: ', m[:, -1])12

13 print('the element at the center is: ', m[1,1])14

15 print('extracting a 2x2 block: \n', m[1:3, 1:3] )16

17 print('or the same as: \n', m[1:, 1:] )

Useful functions to build arrays, vectors and matrices

Always check documentation on array creation for more details. Here I’ll list the methods that I believe to be moreuseful:

• np.eye(N, k): builds an NxN matrix with 1 all over the k-th diagonal. Try to run np.eye(5) and np.eye(5, k=3) to check how it works.

• np.ones(shape): returns a matrix or array fill with 1. Try running np.ones(3), np.ones([3, 5])and np.ones([3,3]).

• np.zeros(shape): exactly like ones above, but fills with zeros.

• np.arange(start, stop, step): we have seen this one above. If omitted, the default values arestart=0 and step=1. Remember that at the end stop is not included, the interval is [start, stop).

• np.linspace(start, stop, num): as seen above, in this case stop is included! Here the last argumentis the number of elements instead of the step between elements as in arange.

There are many other methods, please check the full numpy reference for more information. Later, as we solve physicsproblems we may discuss other useful calls.

40 Chapter 6. Table of contents

Page 45: Intro: Computational Physics

Intro: Computational Physics

6.3.4 Linear Algebra

The numpy linear algebra documentation has a lot of useful tools. We’ll discuss only a few here.

Vector and matrix operations

Besides adding and multiplying arrays via broadcasting, we need to know how to operate with mathematical tools like:dot and cross products, matrix-vector multiplication, matrix-matrix multiplication, etc.

VECTOR-VECTOR OPERATIONS

Let’s jump straight into an example:

Listing 29: Example: vector operations

1 import numpy as np2

3 x = np.array([1, 0, 0])4 y = np.array([0, 1, 0])5

6 z = np.cross(x, y)7 print('the cross product is:', z)8

9 d = np.dot(x, y)10 print('the dot product is:', d)11

12 p = x * y13 print('this is a element-wise multiplication: ', p)

Warning: Notice above that the mathematical cross product �⃗� = �⃗�× �⃗� and dot product 𝑑 = �⃗� · �⃗� requires a propercall to np.cross or np.dot, while a simple array multiplication x * y is simply an element-wise broadcast.

The same happens with matrices, as we see below.

Additionally, in quantum mechanics or it is important to define the scalar dot product as 𝑛 = ⟨𝑎|𝑏⟩ =∑︀

𝑖 𝑎*𝑖 𝑏𝑖,

where the * refers to complex conjugation. In this case the correct call is n = np.vdot(a, b), since the vectordot product conjugates a for you.

MATRIX-MATRIX OPERATIONS

If A and B are matrices, we may want to calculate 𝐶 = 𝐴 · 𝐵, where the matrix product here is the usual line timescolumn multiplication. But we must be careful because A * B means an element-wise multiplication. Let’s check theseand other examples:

Listing 30: Example: matrix operations

1 import numpy as np2

3 # let's use simple 2x2 matrices4 A = np.array([[0, 1], [1, 0]])5 B = np.array([[1, 2], [3, 4]])6

7 print('the matrix product is: \n', np.dot(A, B))8

9 print('which can be written as: \n', A @ B)

(continues on next page)

6.3. Introduction to numpy 41

Page 46: Intro: Computational Physics

Intro: Computational Physics

(continued from previous page)

10

11 print('while this is an element-wise multiplication: \n', A * B)

Similarly, A**2 is an element-wise power of the elements of A, while the actual matrix power is set by np.linalg.matrix_power(A, 2).

Listing 31: Example: matrix operations

1 import numpy as np2

3 # let's use simple 2x2 matrices4 A = np.array([[0, 1], [1, 0]])5

6 print('the element-wise power is: \n', A**2)7

8 print('the actual matrix power is: \n', np.linalg.matrix_power(A, 2))9

10 print('the determinant is: ', np.linalg.det(A))11

12 print('the inverse is: \n', np.linalg.inv(A))13

14 # the matrix power call is long, so let's use an alias15 from numpy.linalg import matrix_power as mpow16

17 print('now the matrix power is: \n', mpow(A, 2))

One of the most important matrix operations are the eigen-problems. Let’s check it:

Listing 32: Example: matrix operations

1 import numpy as np2

3 # let's use simple 2x2 matrices4 A = np.array([[0, 1], [1, 0]])5

6 # calculate only eigenvalues7 evals = np.linalg.eigvalsh(A)8 print('the eigenvalues are: ', evals)9

10 # calculate both eigenvalues and eigenvectors11 evals, evecs = np.linalg.eigh(A)12 print('the eigenvalues are: ', evals)13 print('the first eigenvector: ', evecs[:,0])14 print('the second eigenvector: ', evecs[:,1])

Above A is an Hermitian matrix (𝐴† = 𝐴), we use call eigvalsh and eigh, which are optimized for Hermitian matrices.Otherwise we would have to call eigvals or eig. The matrix in the example has two eigenvalues: +1 and -1, and thecorresponding eigenvectors are shown above. Notice that the eigenvectors are returned as a matrix evecs such that thei-th eigenvector is on the i-th row: evecs[:,i].

MATRIX-VECTOR OPERATIONS

A typical example is the solution of the problem 𝐴 · 𝑋 = 𝐵, where A is a matrix, B a vector and X an unknownvector. If A is non-singular, the solution is 𝑋 = 𝐴−1 · 𝐵. But in practice, for large matrices, it is better to call thelinear system solver as shown below Here I’ll use the example from numpy’s webpage. Consider the linear system

42 Chapter 6. Table of contents

Page 47: Intro: Computational Physics

Intro: Computational Physics

of equations

3𝑥0 + 𝑥1 = 9,

2𝑥1 + 𝑥0 = 8,

and rewrite it as (︂3 11 2

)︂(︂𝑥0

𝑥1

)︂=

(︂98

)︂The code below solves the problem with two approaches.

Listing 33: Example: linear system of equations

1 import numpy as np2

3 A = np.array([[3, 1], [1, 2]])4 B = np.array([9, 8])5

6 # solve using the linear system solver7 X = np.linalg.solve(A, B)8 print('the solution is:', X)9

10 # is the same as applying the inverse11 X = np.linalg.inv(A) @ B12 print('the solution is:', X)

The solution with the inverse or with the solve method match. But the solve method is more efficient for largematrices. Notice that we use @ for the matrix-vector multiplication, but we could’ve used X = np.dot( np.linalg.inv(A), B) instead, its the same.

In quantum mechanics we often need to calculate expected values of operators like 𝑎 = ⟨𝑋|𝐴|𝑌 ⟩, where X andY are state vectors, and A is a matrix representing some operator. The correct call here is a bit cumbersome: a =np.vdot(X, np.dot(A, Y)).

6.3.5 Random numbers

The generation of (pseudo-)random numbers is essential in computational physics. It’s the roots of Monte Carlointegrations and random walks codes. We’ll see more details about how to use random numbers in the next chapters.For now, let’s simply check how to generate them.

A random number is defined by its distribution. For instance, an uniform random number generator in the domain[0,1) must return random numbers in this interval with equal probability. Let’s check it by plotting an histogram:

Histogram for uniform distribution

6.3. Introduction to numpy 43

Page 48: Intro: Computational Physics

Intro: Computational Physics

The code

1 import numpy as np2 import numpy.random as rng3 import matplotlib.pyplot as plt4 plt.rcParams.update({'font.size': 16})5

6 # generates a list with 1000 random numbers7 n = 10008 x = rng.rand(n)9

10 plt.figure(figsize=(8,4))11

12 # plot the samples13 plt.subplot(121)14 plt.plot(x, 'o')15 plt.xlabel('sample')16 plt.ylabel('random number')17

18 # and its histogram19 plt.subplot(122)20 plt.hist(x, rwidth=0.8)21 plt.xlabel('random number')22 plt.ylabel('occurences')23

24 plt.tight_layout()25 plt.show()

Above the command rng.rand(n) generates n random numbers with an uniform distribution in the interval [0,1),and the matplotlib commmand plt.hist(x) automatically generates the histogram counting how many numbersfall into each interval. Try increasing or decreasing the number of samples n.

At the random documentation you’ll find other distributions, like the ones below:

Exponential distribution

44 Chapter 6. Table of contents

Page 49: Intro: Computational Physics

Intro: Computational Physics

Normal/gaussian distribution

Poisson distribution

You can also randomize lists with the rng.shuffle command, or select a random element from a list with therng.choice or rng.permutation. Try using these!

6.3. Introduction to numpy 45

Page 50: Intro: Computational Physics

Intro: Computational Physics

6.3.6 Save and read data from files

TO DO:

• np.savetxt and np.loadtxt for readable files

• np.save and np.load for binary files

6.4 Other libraries

6.4.1 SciPy

The Scientific Python (SciPy) library is similar, but complements numpy. For now, check this tutorial

6.4.2 SymPy

The Symbolic Python (SymPy) allows for symbolic calculation in python. This means using symbols instead ofnumbers to do analytical calculations like Mathematica or Maple. The SymPy is great, but not perfect yet. Be careful.For now, check this tutorial

6.4.3 Others

• tqdm: interesting to track the progress and remaining time of a long loop;

• opencv: image and video manipulation;

• plotly: beautiful and interactive plots in jupyter

6.5 Interpolation

Interpolation is a technique to infer information from a discrete and limited set of data. For instance, it is the rootof numerical integration schemes, where one infer the shape of the curve between discrete points following someinterpolation pattern.

Here we’ll discuss simple interpolation schemes: linear and quadratic interpolation; and an introduction to quadraticspline interpolation. For more information, please check the book by Tao Pang and the Wikipedia: Interpolation.

As a simple example, we’ll consider this figure of sine function with only 5 points in all cases below.

46 Chapter 6. Table of contents

Page 51: Intro: Computational Physics

Intro: Computational Physics

6.5.1 Linear interpolation

A linear interpolation considers a straight line connecting each pair of consecutive points. The set of 5 discrete pointsabove are (𝑥𝑖, 𝑦𝑖), with i=0..4. To interpolate we must fine the equation of aline connecting the dots. This is verysimple, but let’s do it in details, since the same approach can be used for more complex interpolations.

We want to find the coefficients from 𝑦(𝑥) = 𝑎𝑥 + 𝑏 within the domain [𝑥𝑖, 𝑥𝑖+1]. We use the known points to writethe equations

𝑦𝑖 = 𝑎𝑥𝑖 + 𝑏 (6.1)𝑦𝑖+1 = 𝑎𝑥𝑖+1 + 𝑏(6.2)

These equations can be casted in a matrix form(︂𝑥𝑖 1

𝑥𝑖+1 1

)︂(︂𝑎𝑏

)︂=

(︂𝑦𝑖

𝑦𝑖+1

)︂This is a very simple equation that can be solved by hand, but for more complex cases you could usednp.linalg.solve(. . . ) to solve the linear system of equations. You’ll find

𝑎 =𝑦𝑖+1 − 𝑦𝑖𝑥𝑖+1 − 𝑥𝑖

(6.3)

𝑏 =𝑦𝑖𝑥𝑖+1 − 𝑦𝑖+1𝑥𝑖

𝑥𝑖+1 − 𝑥𝑖(6.4)

Applying this linear interpolation to the sine function above, we get this figure below.

Linear interpolation

The code

1 import numpy as np2 import matplotlib.pyplot as plt3 plt.rcParams.update({'font.size': 25})4

5 #----------------------------6 # my linear interp function7 #----------------------------8 def linear_interp(x, y, npts):9 # init arrays

10 xs = np.linspace(x[0], x[-1], npts)11 ys = np.zeros_like(xs)12 # init first point13 ys[0] = y[0]

(continues on next page)

6.5. Interpolation 47

Page 52: Intro: Computational Physics

Intro: Computational Physics

(continued from previous page)

14

15 # loop over sections set by original points16 for i0 in range(len(x)-1):17 # init line equation at this section18 a = (y[i0+1]-y[i0])/(x[i0+1]-x[i0])19 b = (y[i0]*x[i0+1]-y[i0+1]*x[i0])/(x[i0+1]-x[i0])20 # extract xs indexes within x-section range21 # i.e., points where x[i0] < xs < x[i0+1]22 js = np.argwhere((xs > x[i0]) & (xs <= x[i0+1]))[:,0]23 # apply linear interpolation over this range24 ys [js] = a*xs[js] + b25 # return results26 return xs, ys27

28 # generate original points29 x = np.linspace(0, 2*np.pi, 5)30 y = np.sin(x)# + np.random.normal(0, 0.2, 7)31 # exact sine with a lot of points as a reference32 xe = np.linspace(0, 2*np.pi, 100)33 ye = np.sin(xe)34 # my interpolation over the 5 points above35 x1, y1 = linear_interp(x, y, 25)36

37 # plot all38 plt.plot(xe, ye, ls=':', c='lightgray')39 plt.scatter(x, y, c='black', s=100)40 plt.scatter(x1, y1, c='red')41 plt.xlabel(R'$\theta$ [rad]')42 plt.ylabel(R'$\sin\theta$')43 plt.xticks([0, np.pi/2, np.pi, 3*np.pi/2, 2*np.pi], ["0", R"$\dfrac{\pi}{2}$", R"$\pi$

→˓", R"$\dfrac{3\pi}{2}$", R"$2\pi$"])44 plt.grid()45 plt.tight_layout()46 plt.show()

6.5.2 Quadratic interpolation

TO DO

6.5.3 Quadratic spline

TO DO

For more details check:

• Quadratic Spline Interpolation, Surendra Singh Rana, J. Approx. Theory 57, 300 (1989)

• Wikipedia: Spline interpolation

6.5.4 Numpy and scipy methods

TO DO

48 Chapter 6. Table of contents

Page 53: Intro: Computational Physics

Intro: Computational Physics

6.6 Root finding

TO DO

6.6.1 Bisection method

TO DO

6.6.2 Newton–Raphson method

TO DO

6.6.3 Numpy and scipy methods

TO DO

6.6. Root finding 49

Page 54: Intro: Computational Physics

Intro: Computational Physics

6.7 Numerical quadrature / integrals

6.7.1 Simple sum

6.7.2 Trapezoidal rule

6.7.3 Simpson’s rule

6.7.4 Numpy / scipy libraries

6.8 Numerical derivatives

6.8.1 Finite differences

6.8.2 Numpy / Scipy libraries

6.9 Initial value problems

6.9.1 The Euler method

6.9.2 The Runge-Kutta methods

6.9.3 The Verlet method

6.10 Boundary value problems

6.10.1 Transmission

6.10.2 Eigenvalue problems

6.11 Fourier transforms

50 Chapter 6. Table of contents