{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"# Introduction to Jupyter with Python \n",
"\n",
" \n",
"**Anne Kværnø**\n",
"\n",
"Date: **Oct 9, 2018**\n",
"\n",
"# Introduction\n",
"In the numerics part of TMA4125/30/35 Mathematics 4N/D all material will be made\n",
"available in the form of Jupyter notebooks. This is a web-based system, making it\n",
"possible to combine written text and executable code in one document. And this is quite convenient for a course in Numerical methods, as implementation is a crucial element of the topic. \n",
"But implementing code is as you probably have experienced exhaustingly time-consuming. In the notebooks of this course the algorithms are already implemented, and they can be used immediatly. But you are supposed to be able to do your own tests, and also to make minor changes and improvements to the already implemented algorithms.\n",
"\n",
"However, please note that you will not learn programming in this course. In fact, you are expected to be able to read, understand and modify simple codes. Some knowledge of Python or Matlab is a prerequisite. This note gives you a very short introduction to the most important constructions for the use of Python for numerical simulations. For those of you who are only familiar with MATLAB, take a look at [NumPy for Matlab users](https://docs.scipy.org/doc/numpy/user/numpy-for-matlab-users.html).\n",
"\n",
"All the course notes can be downloaded from the course [wiki-pages](https://wiki.math.ntnu.no/tma4135/2018h/jupyter_notes) and then used on your own computer. See [How to install and use Anaconda](https://wiki.math.ntnu.no/anaconda/start). \n",
"\n",
"All the course notes can also be downloaded from the course [wiki-pages](https://wiki.math.ntnu.no/tma4135/2018h/jupyter_notes) and then used on your own computer. See [How to install and use Anaconda](https://wiki.math.ntnu.no/anaconda/start) if you would like to try this option. \n",
"\n",
"For more advanced programmers, there will also be pdf-versions of the documents (not this one), with the python code available in a separate file. These can be found on the wiki-page. But as all figures and tables are generated using the python codes, these are most useful if you run the code in parallell with your reading.\n",
"\n",
"# How to use a Jupyter notebook\n",
"A Jupyter notebook is composed of cells. These can contain either text (like this one) or code (as demonstrated below). As soon as you have copied the Jupyter note file to your own domain, you are free to use it and change it as you like. You are encouraged to experiment with the codes. You can not make any harm, if your note is completely messed up, just make a new copy.\n",
"\n",
"As soon as your first notebook is open, we recommend that you to make yourself more familiar with the Jupyter environment. \n",
"Take a look at the tool menu, and see what is available. There are also many keyboard shortcuts (see Help -> Keyboard Shortcuts), learning some of those will make your work faster\n",
"\n",
"Let us start: Below, you will find a short example of code. You can run this either by pressing **shift+enter**, or using `Run` from the menu."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"a = 2\n",
"b = 6\n",
"c = a+b\n",
"print(c)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"When a cell has been executed, the data are stored and can be used later."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(a, b)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**NB!** New cells can be inserted from the menu (`Insert`) or by pressing `Esc b`. This is useful if you just want to try something without making changes in the existing code. \n",
"\n",
"The code cells are executed in the sequence you choose. There is a number to the left of each cell helping you to keep track of this. \n",
"So if you go back and re-execute one of the first cells, data from previous executed cells are still available. This may sometimes cause strange errors. So once in a while it may be useful to restart completely, which can be done from `Kernel` in the menu. \n",
"\n",
"# Numerical computations in Python\n",
"The implementation of numerical methods is not necessarily very complicated,\n",
"most of the time we can rely on the following constructions: \n",
"\n",
"* Functions\n",
"\n",
"* Loops and control statements\n",
"\n",
"* Vectors and matrices\n",
"\n",
"* Plots and visualization\n",
"\n",
"The use of those will be demonstrated later in this introductory note. \n",
"\n",
"Our computations will heavily rely on two modules: \n",
"* \"Numpy:\": \"(http://www.numpy.org)\": Arrays (vectors and matrices), and all the standard mathematical functions.\n",
"\n",
"* \"Matplotlib:\": \"(https://matplotlib.org)\": Graphs and figures. \n",
"\n",
"In this course, the first cell will always be something similar to the next one below. All required modules and functions are imported, and Jupyter is made ready for showing plots inside the the document. \n",
"*This cell should always be executed first!*"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%matplotlib inline\n",
"\n",
"# Import required modules.\n",
"from numpy import * \n",
"from numpy.linalg import solve # To solve Ax=b\n",
"from matplotlib.pyplot import * \n",
"\n",
"# For plotting. \n",
"newparams = {'figure.figsize': (8.0, 4.0), 'axes.grid': True,\n",
" 'lines.markersize': 8, 'lines.linewidth': 2,\n",
" 'font.size': 16}\n",
"rcParams.update(newparams)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You may change the parameters in `newparams` to your own preferences. Then make your first plot:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"x = linspace(0,1,101)\n",
"plot(x, cos(2*pi*x))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The function `linspace` deserves closer attention, since we will be using it extensively throughout the course.\n",
" `x = linspace(a,b,n+1)` generates an array of $n+1$ equidistributed points, that is"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"$$\n",
"x = [x_0, x_1, \\dotsc, x_n], \\qquad x_i=a+ih, \\quad h=(b-a)/n, \\quad i=0,1,\\dotsc,n.\n",
"$$"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"So `x = linspace(-1,3,5)` generates the array $[-1,0,1,2,3]$. Try it yourself:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Insert your code here"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Functions defined on some intervals are only computed on discrete points $x_i$, and plots are made as straight lines between those. If the intervals between the points are small, it will look like a continuous function. In the preceeding notes, we always will represent the $x$-values of a certain interval $(a,b)$ by `x = linspace(a,b,n+1)`, with `n` large (typically 100). The function will also be used whenever a uniform distribution of points is requested. \n",
"\n",
"\n",
"## Numpy:\n",
"Numpy is the Python module handling vectors and matrices and all different kind of linear algebra. \n",
"Vectors and matrices are considered as 1- and 2-dimensional arrays. Contrary to MATLAB, there is no distinction between row- and column vectors. \n",
"\n",
"The following demonstrates some use of this module. Let $A$ and $b$ be given by"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"$$\n",
"A = \\left(\\begin{array}{rrr} 1.4 & 2.2 & -1.0 \\\\ 1.6 & -2.7 & 1.2 \\\\ -3.2 & 1.2 &-1.8 \\end{array} \\right),\n",
"\\qquad\n",
"\\mathbf{x} = \\left(\\begin{array}{r} 1.0 \\\\ -2.0 \\\\ 3.0 \\end{array}\\right)\n",
"$$"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In Python, these are represented by"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"A = array([[1.4, 2.2, -1.0], # A: A 2-dimensional array \n",
" [ 1.6, -2.7, 1.2],\n",
" [ -3.2, 1.2, -1.8]]) \n",
"x = array([1.0, -2.0, 3.0]) # x: A 1-dimensional array\n",
"print('A = \\n', A)\n",
"print('\\nx = ', x)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Notice that the index starts with 0 in Python, but usually with 1 in mathematics. \n",
"Thus $x_3$ in mathematics corresponds to `x[2]` in Python, and $a_{21}$ to `A[1,0]`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(A[1,0])\n",
"print(x[2])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If `a` and `b` are two arrays of the same dimension, standard operations as `+`, `-`, `*` and `/` are always element by element operations. The same is the case for `a**p`, returning each element of `a` in the power of `p`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"a = array([1, 2, 3])\n",
"b = array([3, 4, 5])\n",
"print('a*b = ', a*b)\n",
"print('a**2 = ', a**2)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The usual matrix-vector product is done by the command `A@x` or `dot(A,x)`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"y = A@x\n",
"print(y)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"And here is a list of quite useful linear algebra functions: \n",
"* `solve(A,b)` : Solves a linear system $ A \\mathbf{x} = \\mathbf{b} $. Needs to be imported from `numpy.linalg`. \n",
"\n",
"* `ones(n)` : returns $[1,1,\\dotsc,1]\\in\\mathbb{R}^n$\n",
"\n",
"* `zeros(n)` : returns $[0,0,\\dotsc,0]\\in\\mathbb{R}^n$\n",
"\n",
"* `len(x)` : The length of an array\n",
"\n",
"* `shape(A)` : The size of an array. Returns $(n, m)$ if $A\\in \\mathbb{R}^{n\\times m}$\n",
"\n",
"* `eye(n)` : The $ n \\times n$ identity matrix $I_n$. \n",
"\n",
"Test them out, and make yourself familiar with them."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Insert your code here"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Matplotlib\n",
"\n",
"Matplotlib is the module taking care of plots. \n",
"\n",
"**Example:**\n",
"Make a plot of the function\n",
"\n",
"$$ f(x) = x^2 + 2x, \\qquad \\qquad g(x) = 2x\\sin(2\\pi x) \\text{ and } h(x)=x^3 $$\n",
"\n",
"on the interval $-1 \\leq x \\leq 1$."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"x = linspace(-1, 1, 101) # The x-values of the interval (-1,1)\n",
"f = x**2 + 2*x # Notice the element by element operations.\n",
"g = 2*x*sin(2*pi*x)\n",
"h = x**3\n",
"plot(x, f, 'r--') # Plot f, red stapled line\n",
"plot(x, g, 'b-.') # Plot g, blue line\n",
"plot(x, h, 'g-') # Plot g, blue line\n",
"xlabel('x')\n",
"ylabel('y')\n",
"title('A nice plot of the functions f,g and h')\n",
"legend(['f(x)', 'g(x)','h(x)'])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You may notice that there is some output before the plot. If you find this annoying, it can be removed by adding a semicolon `;` after the last command in the cell (try it). \n",
"\n",
"\n",
"## Loops and control statements\n",
"Contrary to most other programming languages, MATLAB included, there are no `end` type expression in Python. Blocks to be executed within a loop or similar have to be indented, and the length of the indentation must be consistent (in these notes we use 4spaces). A block ends when the indentation ends.\n",
"\n",
"In the following, some loop and control structures are demonstrated. \n",
"\n",
"**For loop:**\n",
"The aim of this program is to make a nice formatted output of the element of an array."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"x = array([1.3, 4.6, 2.1, -5.8, 2.3, -3.2]) # The array\n",
"n = len(x) # The length of the array\n",
"for i in range(n): # Start of the loop\n",
" print('i = {:2d}, x = {:6.2f}'.format(i, x[i])) # Formatted output \n",
"print('\\nAnd this concludes the loop') # End of the loop"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Notice that \n",
"`for i in range(n)` corresponds to $i=0,1,\\dotsc,n-1$. \n",
"\n",
"Now write every second term, starting with the second one:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"for i in range(1,n,2): # Loops over i=1,3,5\n",
" print('i = {:2d}, x = {:6.2f}'.format(i, x[i])) # Formatted output"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**While loop:**\n",
"Alternatively, you could use a while loop:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"i = 0\n",
"while (i= 1: # Break the loop if i >= 1. \n",
" break"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Functions\n",
"\n",
"Let us present an example from physics. Throw a ball straight up in the air. Ignore the air resistance. Let the initial velocity be $v_0$. The position (height) of the ball and its velocity as a function of time $t$ is given by"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"$$\n",
"\\begin{align*}\n",
" y(t) &= v_0t - \\frac{1}{2} g t^2 && \\text{position} \\\\ \n",
" v(t) &= v_0 - gt && \\text{velocity}\n",
"\\end{align*}\n",
"$$"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"where $g=9.81\\, m/s^2$ is the gravitational constant. The function below takes time, initial velocity and gravitational constant as inputs, \n",
"and returns the velocity and the position. Notice that the initial velocity and the gravitational constant are given default values."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def ball(t, v0=0, g=9.81):\n",
" y = v0*t - 0.5*g*t**2\n",
" v = v0 - g*t\n",
" return y, v"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The function can be used to answer some questions, e.g.:\n",
"* What is the velocity and the position after 2 seconds if the initial velocity is 0 m/s?"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"t = 2.0\n",
"y1, v1 = ball(t) \n",
"print('v0=',0.0,', t=', t, ', y=', y1, ', v=', v1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"* What is the velocity and the position after 2 seconds if the initial velocity is 1 m/s?"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"v_start = 1.0\n",
"y2, v2 = ball(t, v0=v_start) \n",
"print('v0=', v_start,', t=', t, ', y=', y2, ', v=', v2)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"* What is the velocity and the position after 2 seconds if the initial velocity is 1 m/s and the ball is thrown on the moon ($g=1.625 \\\\, m/s^2$)?"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"y3, v3 = ball(t, v0=v_start, g=1.625) \n",
"print('v0=', 1.0,', t=', t, ', y=', y3, ', v=', v3, ' on the moon.')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Whenever possible, write your functions such that if the input is an array, so is the output. \n",
"This is the case here, and it makes it easy to generate a graph of the function, e.g., the position as a function of time when the initial velocity is 10 m/s."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"t = linspace(0,2,101)\n",
"v_start = 10\n",
"y, v = ball(t, v0=v_start)\n",
"plot(t,y)\n",
"xlabel('t')\n",
"ylabel('y')\n",
"title('Position of the ball when v0 = {} m/s'.format(v_start));"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Help!\n",
"This note provides only a very short introduction to some useful functions and constructions in Python. More will be used throughout the course. We hope that most of it will be understandable or explained along the course, but if there are functions or structures you do not understand, please look them up yourself, for instance by \n",
"\n",
"* Write `?function`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"?linspace"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"* Or look it up in Google or something similar.\n",
"\n",
"## Further reading\n",
"For a nice introduction for scientific computing in Pyhton, we can recommend\n",
"* Hans Petter Langtangen: [A Primer on Scientific Programming with Python](https://link.springer.com/book/10.1007/978-3-662-49887-3), Springer Verlag, 2016."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.4"
}
},
"nbformat": 4,
"nbformat_minor": 2
}