Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
100% found this document useful (1 vote)
48 views27 pages

Python Numpy (1) : Intro To Multi-Dimensional Array & Numerical Linear Algebra

Download as pdf or txt
Download as pdf or txt
Download as pdf or txt
You are on page 1/ 27

Python Numpy (1)

Intro to multi-dimensional array & numerical linear


algebra

Harry Lee
January 29, 2018
CEE 696
Table of contents

1. Introduction

2. Linear Algebra

1
Introduction
From the last lecture

import numpy as np
ibound = np.ones((NLAY,NROW,NCOL),dtype=np.int32)

We have used numpy package and its array objects for MODFLOW
model setup. Let’s dig into them.

2
Why Numpy?

• the core library for scientific computing in Python.


• multi-dimensional array object
• math tools for working with these arrays
• interfaces to standard math libraries coded in a compiled
language (written in C++ or Fortran) for speed

3
Have you used MATLAB or R?

Numpy for matlab users:


http://www.numpy.org/devdocs/user/
numpy-for-matlab-users.html

4
Next slides..

• Array creation
• Array access/slicing
• Array operations

5
Numpy Example

import numpy as np

a = np.array([1, 2, 3, 4]) # Create a "rank" 1 array


print(type(a)) # <class 'numpy.ndarray'>
print(a.shape) # "(4,)"
print(a[0], a[1], a[2], a[3]) # "1 2 3 4"
a[1] = 4 # Change an element
print(a) # "[1, 4, 3, 4]"

b = np.array([[1,2],[3,4]]) # a rank 2 array


print(b.shape) # "(2, 2)"
print(b[0, 0], b[0, 1], b[1, 0]) # "1 2 3"

Note that “rank” in python means the number of dimensions of an


array while “rank” in linear algebra is the maximum number of
linearly independent columns of a 2D matrix.
6
Anatomy of Numpy Array

Figure 1: http://pages.physics.cornell.edu/~myers/teaching/
ComputationalMethods/python/arrays.html

7
Numpy Array (1) - Creation

a = np.zeros((2,2)) # all zeros


print(a) # [[ 0. 0.]
# [ 0. 0.]]

b = np.ones((1,2)) # all ones


print(b) # [[ 1. 1.]]

c = np.full((2,2), 3.) # constant array


print(c) # [[ 3. 3.]
# [ 3. 3.]]

d = np.eye(2) # identity matrix


print(d) # [[ 1. 0.]
# [ 0. 1.]]

e = np.random.random((2,2)) # random array


8
print(e)
Numpy Array (2) - Data Type

x = np.array([1, 2]) # numpy will choose its datatype


print(x.dtype) # datatype = int64

x = np.array([1.0, 2.0])
print(x.dtype) # datatype = float64

# for single-precision MODFLOW (see available executable


IBOUND = np.array([1, 2], dtype=np.int32)
print(x.dtype)

# one can use dtype = "d" for double-precision


# i.e, np.float64
HK = np.ones((100,100),'d')

9
Numpy Array (3) - Modification

a = np.array([[1,2],[3,4]])
b = np.array(a) # create a new array
c = a # referencing
print(a)
print(b)
print(c)

a[0,0] = 10
print(a)
print(b)
print(c) # this is easy.. wait, what?

10
Reference/Shallow Copy vs. Deep Copy

This is one of the most confusing aspects for beginners. Be careful!


a = [1,2,3] # type(a) : list
b = a
c = a[:] # NOT for list with nested structure and np.arr
b[1] = 10
print(id(a),a)
print(id(b),b)
print(id(c),c)

x = np.array([1, 2, 3])
y = x
z = np.copy(x)
x[0] = 10
print(id(x),x)
print(id(y),y)
print(id(z),z)
11
Numpy Array (4) - Slice Notation CON’T

We use ”slicing” to pull out the sub-array

a[start:end]
a[start:end:step]

Make sure the [:end] value represents the first value that is not in
the selected slice.

# create an array
a = np.array([1,2,3,4,5,6,7,8,9,10])
a[:] # a copy of the whole array
a[0:10] # = a[0:] = a[:10] = a[:] = a[::]
a[0:10:2] # = a[:10:2] = a[::2]

a[-1] # last item in the array


a[-2:] # last two items in the array 12
a[:-2] # everything except the last two items
Numpy Arrays (5) - Slice Notation CON’T

# create an array
a = np.array([[1,2,3], [4,5,6], [7,8,9]])

b = a[:2, 1:3]

# This is IMPORTANT!!
print(a)
b[0, 0] = 10 # b[0, 0] from a[0, 1]
print(a) # print it.. wait, what?

A slice of an array is a “view” into a part of the original array. Thus,


modifying it will change the original array as before. Be careful!

13
Numpy Array (6) - Slice Notation CON’T

a = np.array([[1,2,3], [4,5,6], [7,8,9]])


# integer index + slicing for lower dimensional array
row1 = a[1, :] # Rank 1 view of the second row of a
# slicing for the same dimension
row2 = a[1:2, :] # Rank 2 view of the second row of a

print(row1, row1.shape, row1.ndim)


print(row2, row2.shape, row2.ndim)

Make sure the dimension of your array is consistent with what you
thought!

14
Numpy Array (7) - Element Access

# create a new array from which we will select elements


a = np.array([[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]])

print(a)

# an array of indices (for each row)


b = np.array([2, 1, 0, 1])

# print element from each row of a using the indices in


print(a[np.arange(4), b])

# even we can modify the values


a[np.arange(4), b] = a[np.arange(4), b] + 5

15
Numpy Array (8) - Element Access

a = np.array([[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]])

idx = (a > 2) # find element > 2


# return booleans

print(idx)

print(a[idx]) # return values greater than 2


# with booleans

# in a single statement
print(a[a > 2])

16
Arrays (6) - Operations (1)

x = np.array([[1,2],[3,4]])
y = np.array([[5,6],[7,8]])
print(x+y)
print(np.add(x, y))

print(x-y)
print(np.subtract(x, y))

# make sure this is element-wise product


print(x*y)
print(np.multiply(x, y))

# make sure this is element-wise division


print(x/y)
print(np.divide(x, y))

17
print(np.sqrt(x))
Arrays (6) - operations (2)

x = np.array([[1,2],[3,4]])
y = np.array([[5,6],[7,8]])

v = np.array([9,10])
w = np.array([11, 12])

# Inner product of vectors


print(v.dot(w))
print(np.dot(v, w))

# Matrix-vector product
print(x.dot(v))
print(np.dot(x, v))

# Matrix-matrix product
print(x.dot(y))
18
print(np.dot(x, y))
Linear Algebra
Solution to linear system

Ax = b
A is n by n matrix
b is n × 1 vector
x is n × 1 vector to solve

• numerical solution to PDE (partial differential equation) ex)


MODFLOW
• optimization ex) quadratic programming

19
MODFLOW - Numerical Modeling (1)

In MODFLOW, water mass balance is enforced by summing the water


fluxes Qi,j,k across each side of the cell and internal source/sinks:

Qi,j,k = 0 (for steady state condition, i.e., no time-related term)

Figure 2: cell (i,j,k) configuration for mass balance equation (from Fig. 2-2
Harbaugh [2005]) 20
MODFLOW - Numerical Modeling (2)

With Darcy’s law,


(ϕi,j−1,k − ϕi,j,k )
qi,j−1/2,k = Ki,j−1/2,k ∆ci ∆vk
∆rj−1/2

Figure 3: Flow into cell i,j,k from cell i,j-1,k (from Fig. 2-3 Harbaugh [2005])


Combining with mass balance equation Qi = 0 (for steady stead)
for every cell will lead to the system of linear equations
Aϕ = f 21
numpy.linalg.inv

# from FVM with K=1, dr,dc,dz = 1


# const. head = 10 m at the left
# no flow at the right
A = np.array([[1., 0., 0.],[-1., 2., -1.],[0., -1., 1.]]
f = np.array([[10],[0],[0]])

# inverse of A to compute h = np.dot(inv(A),f)


# NEVER do this in practice! because
# 1) it's expensive O(n^3)
# 2) poor numerical accuracy
invA = np.linalg.inv(A)
h = np.dot(invA,f)

print(h) # what do you expect?


print(invA) #
print(np.dot(A,invA)) # is this np.eye?
22
print(np.dot(A,h) - f) # satisfy mass balance?
numpy.linalg.solve

# so-called stiffness matrix


A = np.array([[1., 0., 0.],[-1., 2., -1.],[0., 1., -1.]]
# force/load vector
f = np.array([[10],[0],[0]])

# solution of Ah = f
h = np.linalg.solve(A,f)

print(h) # what do you expect?


print(np.dot(A,h) - f) # satisfy mass balance?
# how about constant head boundaries at both ends?

We will discuss advanced materials later (i.e., iterative approach as


in PCG module of MODFLOW and eigen-decomposition)

23
Connection to Quadratic Function Optimization

1
f(x) = xT Ax − bxT
2

• Ax⋆ − b = 0 for necessary condition to optimal (local) solution


x⋆ to min/max f(x)
• Quadratic function is related to some energy. In fact, nature acts
so as to minimize energy
• If a physical system is in a stable state of equilibrium, then the
energy in that state should be minimal
• Thus, no wonder linear algebra is related to optimization!

24

You might also like