Hello! This is a quick intro to programming in Python to help you hit the ground running with the 12 Steps to Navier-Stokes.
Python is a high-level open-source language. But the Python world is inhabited by many packages or libraries that provide useful things like array operations, plotting functions, and much more. We can import libraries of functions to expand the capabilities of Python in our programs.
OK! We'll start by importing a few libraries to help us out.
#comments in python are denoted by the pound sign
import numpy as np #numpy is a library we're importing that provides a bunch of useful matrix operations akin to MATLAB
import matplotlib.pyplot as plt #matplotlib is 2D plotting library which we will use to plot our results
So what's all of this import-as business? We are importing one library named numpy
and we are importing a sub-library of a big package called matplotlib
. Because the functions we want to use belong to these libraries, we have to tell Python to look at those libraries when we call a particular function. The two lines above have created shortcuts to those libraries named np
and plt
, respectively. So if we want to use the numpy function linspace
, for instance, we can call it by writing:
myarray = np.linspace(0, 5, 10)
myarray
array([ 0. , 0.55555556, 1.11111111, 1.66666667, 2.22222222, 2.77777778, 3.33333333, 3.88888889, 4.44444444, 5. ])
If we don't preface the linspace
function with np
, Python will throw an error.
myarray = linspace(0, 5, 10)
Sometimes, you'll see people importing a whole library without assigning a shortcut for it (like np
here for numpy
). This saves typing but is sloppy and can get you in trouble. Best to get into good habits from the beginning!
To learn new functions available to you, visit the NumPy Reference page. If you are a proficient Matlab
user, there is a wiki page that should prove helpful to you: NumPy for Matlab Users
Python doesn't require explicitly declared variable types like C and other languages.
a = 5 #a is an integer 5
b = 'five' #b is a string of the word 'five'
c = 5.0 #c is a floating point 5
type(a)
int
type(b)
str
type(c)
float
Pay special attention to assigning floating point values to variables or you may get values you do not expect in your programs.
14/a
2
14/c
2.8
If you divide an integer by an integer, it will return an answer rounded to the nearest integer. If you want a floating point answer, one of the numbers must be a float. Simply appending a decimal point will do the trick:
14./a
2.8
Python uses indents and whitespace to group statements together. To write a short loop in C, you might use:
for (i = 0, i < 5, i++){
printf("Hi! \n");
}
Python does not use curly braces like C, so the same program as above is written in Python as follows:
for i in range(5):
print "Hi \n"
Hi Hi Hi Hi Hi
If you have nested for-loops, there is a further indent for the inner loop.
for i in range(3):
for j in range(3):
print i, j
print "This statement is within the i-loop, but not the j-loop"
0 0 0 1 0 2 This statement is within the i-loop, but not the j-loop 1 0 1 1 1 2 This statement is within the i-loop, but not the j-loop 2 0 2 1 2 2 This statement is within the i-loop, but not the j-loop
In NumPy, you can look at portions of arrays in the same way as in Matlab
, with a few extra tricks thrown in. Let's take an array of values from 1 to 5.
myvals = np.array([1, 2, 3, 4, 5])
myvals
array([1, 2, 3, 4, 5])
Python uses a zero-based index, so let's look at the first and last element in the array myvals
myvals[0], myvals[4]
(1, 5)
There are 5 elements in the array myvals
, but if we try to look at myvals[5]
, Python will be unhappy, as myvals[5]
is actually calling the non-existant 6th element of that array.
myvals[5]
--------------------------------------------------------------------------- IndexError Traceback (most recent call last) <ipython-input-21-6cc4d3ae83cd> in <module>() ----> 1 myvals[5] IndexError: index out of bounds
Arrays can also be 'sliced', grabbing a range of values. Let's look at the first three elements
myvals[0:3]
array([1, 2, 3])
Note here, the slice is inclusive on the front end and exclusive on the back, so the above command gives us the values of myvals[0]
, myvals[1]
and myvals[2]
, but not myvals[3]
.
One of the strange little quirks/features in Python that often confuses people comes up when assigning and comparing arrays of values. Here is a quick example. Let's start by defining a 1-D array called $a$:
a = np.linspace(1,5,5)
a
array([ 1., 2., 3., 4., 5.])
OK, so we have an array $a$, with the values 1 through 5. I want to make a copy of that array, called $b$, so I'll try the following:
b = a
b
array([ 1., 2., 3., 4., 5.])
Great. So $a$ has the values 1 through 5 and now so does $b$. Now that I have a backup of $a$, I can change its values without worrying about losing data (or so I may think!).
a[2] = 17
a
array([ 1., 2., 17., 4., 5.])
Here, the 3rd element of $a$ has been changed to 17. Now let's check on $b$.
b
array([ 1., 2., 17., 4., 5.])
And that's how things go wrong! When you use a statement like $a = b$, rather than copying all the values of $a$ into a new array called $b$, Python just creates an alias (or a pointer) called $b$ and tells it to route us to $a$. So if we change a value in $a$ then $b$ will reflect that change (technically, this is called assignment by reference). If you want to make a true copy of the array, you have to tell Python to copy every element of $a$ into a new array. Let's call it $c$.
c[:] = a[:]
Unfortunately, if we want to make the true copy, the new array has to be defined first and has to have the correct number of elements. So it will be a two-step process. We can define an "empty" array that is the same size as $a$ by using the numpy function empty_like
:
c = np.empty_like(a)
len(c) #shows us how long c is
5
c[:]=a[:]
c
array([ 1., 2., 17., 4., 5.])
Now, we can try again to change a value in $a$ and see if the changes are also seen in $c$.
a[2] = 3
a
array([ 1., 2., 3., 4., 5.])
c
array([ 1., 2., 17., 4., 5.])
OK, it worked! If the difference between a = b
and a[:]=b[:]
is unclear, you should read through this again. This issue will come back to haunt you otherwise.
There are a lot of resources online to learn more about using NumPy and other libraries. Just for kicks, here we use IPython's feature for embedding videos to point you to a short video on YouTube on using NumPy arrays.
from IPython.display import YouTubeVideo
# a short video about using NumPy arrays, from Enthought
YouTubeVideo('vWkb7VahaXQ')
from IPython.core.display import HTML
def css_styling():
styles = open("../styles/custom.css", "r").read()
return HTML(styles)
css_styling()