Ch. 5 Scientific
Last update: Thu Nov 19 17:17:30 2020 -0600 (f99c21d)
R
library(reticulate)
reticulate::use_condaenv("r-python")
5.1 Solve Computational Physics Problems
Python
# https://www.codeproject.com/Articles/1087025/Using-Python-to-Solve-Computational-Physics-Proble
import numpy as np
import matplotlib.pyplot as plt
# Set maximum iteration
= 500
maxIter
# Set Dimension and delta
= lenY = 20 #we set it rectangular
lenX = 1
delta
# Boundary condition
= 100
Ttop = 0
Tbottom = 0
Tleft = 30
Tright
# Initial guess of interior grid
= 30
Tguess
# Set colour interpolation and colour map.
# You can try set it to 10, or 100 to see the difference
# You can also try: colourMap = plt.cm.coolwarm
= 50
colorinterpolation = plt.cm.jet
colourMap
# Set meshgrid
= np.meshgrid(np.arange(0, lenX), np.arange(0, lenY))
X, Y
# Set array size and set the interior value with Tguess
= np.empty((lenX, lenY))
T
T.fill(Tguess)
# Set Boundary condition
-1):, :] = Ttop
T[(lenY1, :] = Tbottom
T[:-1):] = Tright
T[:, (lenX1] = Tleft
T[:, :
# Iteration (We assume that the iteration is convergence in maxIter = 500)
print("Please wait for a moment")
for iteration in range(0, maxIter):
for i in range(1, lenX-1, delta):
for j in range(1, lenY-1, delta):
= 0.25 * (T[i+1][j] + T[i-1][j] + T[i][j+1] + T[i][j-1])
T[i, j]
print("Iteration finished")
# Configure the contour
"Contour of Temperature")
plt.title(=colourMap)
plt.contourf(X, Y, T, colorinterpolation, cmap
# Set Colorbar
plt.colorbar()
# Show the result in the plot window
plt.show()
5.2 Find electric potential in a square wire
Python
# https://www.eidos.ic.i.u-tokyo.ac.jp/~tau/lecture/computational_physics/docs/computational_physics.pdf
# Page 404. Figure 17.1
# Solve Laplace equation
from numpy import *
import matplotlib.pylab as lab
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
print("Initializing")
= 100; Niter = 70; V = zeros((Nmax, Nmax), float) # float maybe Float
Nmax
print("Working hard, wait for the figure while I count to 60")
for k in range(0, Nmax-1): V[k,0] = 100.0 # line at 100V
for iter in range(Niter): # iterations over algorithm
if iter % 10 == 0: print(iter)
for i in range(1, Nmax-2):
for j in range(1,Nmax-2): V[i,j] = 0.25 * (V[i+1,j] + V[i-1,j] + V[i,j+1] + V[i,j-1])
= range(0, Nmax-1, 2); y = range(0, 50, 2) # plot every other point
x = lab.meshgrid(x, y)
X, Y
def functz(V): # Function returns V(x, y)
= V[X,Y]
z return z
= functz(V)
Z = lab.figure() # Create figures
fig = Axes3D(fig) # plot axes
ax = 'r') # red wireframe
ax.plot_wireframe(X, Y, Z, color 'X') # label axes
ax.set_xlabel('Y')
ax.set_ylabel('Potential')
ax.set_zlabel(# display fig, close shell to quit lab.show()
5.3 Eigenvalue problems
-
lobpcg
(Locally Optimal Block Preconditioned Conjugate Gradient Method) * works very well in combination withPyAMG
(example by Nathan Bell)
Python
# http://scipy-lectures.org/_downloads/ScipyLectures-simple.pdf
# Page 348
# Compute eigenvectors and eigenvalues using a preconditioned eigensolver
# ========================================================================
# In this example Smoothed Aggregation (SA) is used to precondition
# the LOBPCG eigensolver on a two-dimensional Poisson problem with
# Dirichlet boundary conditions.
import scipy
from scipy.sparse.linalg import lobpcg
import matplotlib.pyplot as plt
from pyamg import smoothed_aggregation_solver
from pyamg.gallery import poisson
= 100
N = 9
K = poisson((N,N), format='csr')
A # create the AMG hierarchy
= smoothed_aggregation_solver(A)
ml # initial approximation to the K eigenvectors
= scipy.rand(A.shape[0], K)
X # preconditioner based on ml
= ml.aspreconditioner()
M # compute eigenvalues and eigenvectors with LOBPCG
= lobpcg(A, X, M=M, tol=1e-8, largest=False)
W,V
=(9,9))
plt.figure(figsize# iterate through the subplots adding data points
for i in range(K):
3, 3, i+1)
plt.subplot('Eigenvector%d'% i)
plt.title(
plt.pcolor(V[:,i].reshape(N,N))'equal')
plt.axis('off')
plt.axis( plt.show()
5.4 Computational Physics
Python
# Plot of the Lorenz Attractor based on Edward Lorenz's 1963 "Deterministic
# Nonperiodic Flow" publication.
# http://journals.ametsoc.org/doi/abs/10.1175/1520-0469%281963%29020%3C0130%3ADNF%3E2.0.CO%3B2
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
def lorenz(x, y, z, s=10, r=28, b=2.667):
= s*(y - x)
x_dot = r*x - y - x*z
y_dot = x*y - b*z
z_dot return x_dot, y_dot, z_dot
# parameters
= 0.01
dt = 10000
stepCnt # Need one more for the initial values
= np.empty((stepCnt + 1,))
xs = np.empty((stepCnt + 1,))
ys = np.empty((stepCnt + 1,))
zs # Setting initial values
0], ys[0], zs[0] = (0., 1., 1.05)
xs[# Stepping through "time".
for i in range(stepCnt):
# Derivatives of the X, Y, Z state
= lorenz(xs[i], ys[i], zs[i])
x_dot, y_dot, z_dot + 1] = xs[i] + (x_dot * dt)
xs[i + 1] = ys[i] + (y_dot * dt)
ys[i + 1] = zs[i] + (z_dot * dt)
zs[i
= plt.figure()
fig = fig.gca(projection='3d')
ax
=0.5)
ax.plot(xs, ys, zs, lw"X Axis")
ax.set_xlabel("Y Axis")
ax.set_ylabel("Z Axis")
ax.set_zlabel("Lorenz Attractor")
ax.set_title(
plt.show()
Python
# https://matplotlib.org/gallery/images_contours_and_fields/contour_image.html#sphx-glr-gallery-images-contours-and-fields-contour-image-py
import matplotlib.pyplot as plt
import numpy as np
from matplotlib import cm
# Default delta is large because that makes it fast, and it illustrates
# the correct registration between image and contours.
= 0.5
delta
= (-3, 4, -4, 3)
extent
= np.arange(-3.0, 4.001, delta)
x = np.arange(-4.0, 3.001, delta)
y = np.meshgrid(x, y)
X, Y = np.exp(-X**2 - Y**2)
Z1 = np.exp(-(X - 1)**2 - (Y - 1)**2)
Z2 = (Z1 - Z2) * 2
Z
# Boost the upper limit to avoid truncation errors.
= np.arange(-2.0, 1.601, 0.4)
levels
= cm.colors.Normalize(vmax=abs(Z).max(), vmin=-abs(Z).max())
norm = cm.PRGn
cmap
= plt.subplots(nrows=2, ncols=2)
fig, _axs =0.3)
fig.subplots_adjust(hspace= _axs.flatten()
axs
= axs[0].contourf(X, Y, Z, levels, norm=norm,
cset1 =cm.get_cmap(cmap, len(levels) - 1))
cmap# It is not necessary, but for the colormap, we need only the
# number of levels minus 1. To avoid discretization error, use
# either this number or a large number such as the default (256).
# If we want lines as well as filled regions, we need to call
# contour separately; don't try to change the edgecolor or edgewidth
# of the polygons in the collections returned by contourf.
# Use levels output from previous call to guarantee they are the same.
= axs[0].contour(X, Y, Z, cset1.levels, colors='k')
cset2
# We don't really need dashed contour lines to indicate negative
# regions, so let's turn them off.
for c in cset2.collections:
'solid')
c.set_linestyle(
# It is easier here to make a separate call to contour than
# to set up an array of colors and linewidths.
# We are making a thick green line as a zero contour.
# Specify the zero level as a tuple with only 0 in it.
= axs[0].contour(X, Y, Z, (0,), colors='g', linewidths=2)
cset3 0].set_title('Filled contours')
axs[=axs[0])
fig.colorbar(cset1, ax1].imshow(Z, extent=extent, cmap=cmap, norm=norm)
axs[1].contour(Z, levels, colors='k', origin='upper', extent=extent)
axs[1].set_title("Image, origin 'upper'")
axs[
2].imshow(Z, origin='lower', extent=extent, cmap=cmap, norm=norm)
axs[2].contour(Z, levels, colors='k', origin='lower', extent=extent)
axs[2].set_title("Image, origin 'lower'")
axs[
# We will use the interpolation "nearest" here to show the actual
# image pixels.
# Note that the contour lines don't extend to the edge of the box.
# This is intentional. The Z values are defined at the center of each
# image pixel (each color block on the following subplot), so the
# domain that is contoured does not extend beyond these pixel centers.
= axs[3].imshow(Z, interpolation='nearest', extent=extent,
im =cmap, norm=norm)
cmap3].contour(Z, levels, colors='k', origin='image', extent=extent)
axs[= axs[3].get_ylim()
ylim 3].set_ylim(ylim[::-1])
axs[3].set_title("Origin from rc, reversed y-axis")
axs[=axs[3])
fig.colorbar(im, ax
fig.tight_layout() plt.show()
Python
# https://matplotlib.org/gallery/images_contours_and_fields/irregulardatagrid.html#sphx-glr-gallery-images-contours-and-fields-irregulardatagrid-py
import matplotlib.pyplot as plt
import matplotlib.tri as tri
import numpy as np
19680801)
np.random.seed(= 200
npts = 100
ngridx = 200
ngridy = np.random.uniform(-2, 2, npts)
x = np.random.uniform(-2, 2, npts)
y = x * np.exp(-x**2 - y**2)
z
= plt.subplots(nrows=2)
fig, (ax1, ax2)
# -----------------------
# Interpolation on a grid
# -----------------------
# A contour plot of irregularly spaced data coordinates
# via interpolation on a grid.
# Create grid values first.
= np.linspace(-2.1, 2.1, ngridx)
xi = np.linspace(-2.1, 2.1, ngridy)
yi
# Perform linear interpolation of the data (x,y)
# on a grid defined by (xi,yi)
= tri.Triangulation(x, y)
triang = tri.LinearTriInterpolator(triang, z)
interpolator = np.meshgrid(xi, yi)
Xi, Yi = interpolator(Xi, Yi)
zi
# Note that scipy.interpolate provides means to interpolate data on a grid
# as well. The following would be an alternative to the four lines above:
#from scipy.interpolate import griddata
#zi = griddata((x, y), z, (xi[None,:], yi[:,None]), method='linear')
14, linewidths=0.5, colors='k')
ax1.contour(xi, yi, zi, = ax1.contourf(xi, yi, zi, 14, cmap="RdBu_r")
cntr1
=ax1)
fig.colorbar(cntr1, ax'ko', ms=3)
ax1.plot(x, y, -2, 2, -2, 2))
ax1.axis(('grid and contour (%d points, %d grid points)' %
ax1.set_title(* ngridy))
(npts, ngridx # ----------
# Tricontour
# ----------
# Directly supply the unordered, irregularly spaced coordinates
# to tricontour.
14, linewidths=0.5, colors='k')
ax2.tricontour(x, y, z, = ax2.tricontourf(x, y, z, 14, cmap="RdBu_r")
cntr2
=ax2)
fig.colorbar(cntr2, ax'ko', ms=3)
ax2.plot(x, y, -2, 2, -2, 2))
ax2.axis(('tricontour (%d points)' % npts)
ax2.set_title(
=0.5)
plt.subplots_adjust(hspace plt.show()
5.5 Triangulation and Delauney maps
Python
from matplotlib.tri import Triangulation, TriAnalyzer, UniformTriRefiner
import matplotlib.pyplot as plt
import matplotlib.cm as cm
import numpy as np
#-----------------------------------------------------------------------------
# Analytical test function
#-----------------------------------------------------------------------------
def experiment_res(x, y):
""" An analytic function representing experiment results """
= 2. * x
x = np.sqrt((0.5 - x)**2 + (0.5 - y)**2)
r1 = np.arctan2(0.5 - x, 0.5 - y)
theta1 = np.sqrt((-x - 0.2)**2 + (-y - 0.2)**2)
r2 = np.arctan2(-x - 0.2, -y - 0.2)
theta2 = (4 * (np.exp((r1 / 10)**2) - 1) * 30. * np.cos(3 * theta1) +
z / 10)**2) - 1) * 30. * np.cos(5 * theta2) +
(np.exp((r2 2 * (x**2 + y**2))
return (np.max(z) - z) / (np.max(z) - np.min(z))
#-----------------------------------------------------------------------------
# Generating the initial data test points and triangulation for the demo
#-----------------------------------------------------------------------------
# User parameters for data test points
= 200 # Number of test data points, tested from 3 to 5000 for subdiv=3
n_test
= 3 # Number of recursive subdivisions of the initial mesh for smooth
subdiv # plots. Values >3 might result in a very high number of triangles
# for the refine mesh: new triangles numbering = (4**subdiv)*ntri
= 0.0 # Float > 0. adjusting the proportion of
init_mask_frac # (invalid) initial triangles which will be masked
# out. Enter 0 for no mask.
= .01 # Minimum circle ratio - border triangles with circle
min_circle_ratio # ratio below this will be masked if they touch a
# border. Suggested value 0.01; use -1 to keep
# all triangles.
# Random points
= np.random.RandomState(seed=19680801)
random_gen = random_gen.uniform(-1., 1., size=n_test)
x_test = random_gen.uniform(-1., 1., size=n_test)
y_test = experiment_res(x_test, y_test)
z_test # meshing with Delaunay triangulation
= Triangulation(x_test, y_test)
tri = tri.triangles.shape[0]
ntri # Some invalid data are masked out
= np.zeros(ntri, dtype=bool)
mask_init = random_gen.randint(0, ntri, int(ntri * init_mask_frac))
masked_tri = True
mask_init[masked_tri]
tri.set_mask(mask_init)#-----------------------------------------------------------------------------
# Improving the triangulation before high-res plots: removing flat triangles
#-----------------------------------------------------------------------------
# masking badly shaped triangles at the border of the triangular mesh.
= TriAnalyzer(tri).get_flat_tri_mask(min_circle_ratio)
mask
tri.set_mask(mask)# refining the data
= UniformTriRefiner(tri)
refiner = refiner.refine_field(z_test, subdiv=subdiv)
tri_refi, z_test_refi # analytical 'results' for comparison
= experiment_res(tri_refi.x, tri_refi.y)
z_expected # for the demo: loading the 'flat' triangles for plot
= Triangulation(x_test, y_test)
flat_tri ~mask)
flat_tri.set_mask(#-----------------------------------------------------------------------------
# Now the plots
#-----------------------------------------------------------------------------
# User options for plots
= True # plot of base triangulation
plot_tri = True # plot of excessively flat excluded triangles
plot_masked_tri = False # plot of refined triangulation
plot_refi_tri = False # plot of analytical function values for comparison
plot_expected
# Graphical options for tricontouring
= np.arange(0., 1., 0.025)
levels = cm.get_cmap(name='Blues', lut=None)
cmap
= plt.subplots()
fig, ax 'equal')
ax.set_aspect("Filtering a Delaunay mesh\n" +
ax.set_title("(application to high-resolution tricontouring)")
# 1) plot of the refined (computed) data contours:
=levels, cmap=cmap,
ax.tricontour(tri_refi, z_test_refi, levels=[2.0, 0.5, 1.0, 0.5])
linewidths# 2) plot of the expected (analytical) data contours (dashed):
if plot_expected:
=levels, cmap=cmap,
ax.tricontour(tri_refi, z_expected, levels='--')
linestyles# 3) plot of the fine mesh on which interpolation was done:
if plot_refi_tri:
='0.97')
ax.triplot(tri_refi, color# 4) plot of the initial 'coarse' mesh:
if plot_tri:
='0.7')
ax.triplot(tri, color# 4) plot of the unvalidated triangles from naive Delaunay Triangulation:
if plot_masked_tri:
='red')
ax.triplot(flat_tri, color plt.show()
Python
# https://matplotlib.org/gallery/images_contours_and_fields/triinterp_demo.html#sphx-glr-gallery-images-contours-and-fields-triinterp-demo-py
import matplotlib.pyplot as plt
import matplotlib.tri as mtri
import numpy as np
# Create triangulation.
= np.asarray([0, 1, 2, 3, 0.5, 1.5, 2.5, 1, 2, 1.5])
x = np.asarray([0, 0, 0, 0, 1.0, 1.0, 1.0, 2, 2, 3.0])
y = [[0, 1, 4], [1, 2, 5], [2, 3, 6], [1, 5, 4], [2, 6, 5], [4, 5, 7],
triangles 5, 6, 8], [5, 8, 7], [7, 8, 9]]
[= mtri.Triangulation(x, y, triangles)
triang
# Interpolate to regularly-spaced quad grid.
= np.cos(1.5 * x) * np.cos(1.5 * y)
z = np.meshgrid(np.linspace(0, 3, 20), np.linspace(0, 3, 20))
xi, yi
= mtri.LinearTriInterpolator(triang, z)
interp_lin = interp_lin(xi, yi)
zi_lin
= mtri.CubicTriInterpolator(triang, z, kind='geom')
interp_cubic_geom = interp_cubic_geom(xi, yi)
zi_cubic_geom
= mtri.CubicTriInterpolator(triang, z, kind='min_E')
interp_cubic_min_E = interp_cubic_min_E(xi, yi)
zi_cubic_min_E
# Set up the figure
= plt.subplots(nrows=2, ncols=2)
fig, axs = axs.flatten()
axs
# Plot the triangulation.
0].tricontourf(triang, z)
axs[0].triplot(triang, 'ko-')
axs[0].set_title('Triangular grid')
axs[
# Plot linear interpolation to quad grid.
1].contourf(xi, yi, zi_lin)
axs[1].plot(xi, yi, 'k-', lw=0.5, alpha=0.5)
axs[1].plot(xi.T, yi.T, 'k-', lw=0.5, alpha=0.5)
axs[1].set_title("Linear interpolation")
axs[
# Plot cubic interpolation to quad grid, kind=geom
2].contourf(xi, yi, zi_cubic_geom)
axs[2].plot(xi, yi, 'k-', lw=0.5, alpha=0.5)
axs[2].plot(xi.T, yi.T, 'k-', lw=0.5, alpha=0.5)
axs[2].set_title("Cubic interpolation,\nkind='geom'")
axs[
# Plot cubic interpolation to quad grid, kind=min_E
3].contourf(xi, yi, zi_cubic_min_E)
axs[3].plot(xi, yi, 'k-', lw=0.5, alpha=0.5)
axs[3].plot(xi.T, yi.T, 'k-', lw=0.5, alpha=0.5)
axs[3].set_title("Cubic interpolation,\nkind='min_E'")
axs[
fig.tight_layout() plt.show()
5.6 Contour maps
Python
# http://www.scipy-lectures.org/intro/matplotlib/auto_examples/plot_contour_ex.html
import matplotlib.pyplot as plt
import numpy as np
def f(x, y):
return (1 - x / 2 + x ** 5 + y ** 3) * np.exp(-x ** 2 -y ** 2)
= 256
n = np.linspace(-3, 3, n)
x = np.linspace(-3, 3, n)
y = np.meshgrid(x, y)
X,Y
0.025, 0.025, 0.95, 0.95])
plt.axes([
8, alpha=.75, cmap=plt.cm.hot)
plt.contourf(X, Y, f(X, Y), = plt.contour(X, Y, f(X, Y), 8, colors='black', linewidth=.5)
C =1, fontsize=10)
plt.clabel(C, inline
plt.xticks(())
plt.yticks(()) plt.show()
5.7 Real time
Python
# https://matplotlib.org/gallery/lines_bars_and_markers/cohere.html#sphx-glr-gallery-lines-bars-and-markers-cohere-py
import numpy as np
import matplotlib.pyplot as plt
# Fixing random state for reproducibility
19680801)
np.random.seed(
= 0.01
dt = np.arange(0, 30, dt)
t = np.random.randn(len(t)) # white noise 1
nse1 = np.random.randn(len(t)) # white noise 2
nse2
# Two signals with a coherent part at 10Hz and a random part
= np.sin(2 * np.pi * 10 * t) + nse1
s1 = np.sin(2 * np.pi * 10 * t) + nse2
s2
= plt.subplots(2, 1)
fig, axs 0].plot(t, s1, t, s2)
axs[0].set_xlim(0, 2)
axs[0].set_xlabel('time')
axs[0].set_ylabel('s1 and s2')
axs[0].grid(True)
axs[
= axs[1].cohere(s1, s2, 256, 1. / dt)
cxy, f 1].set_ylabel('coherence')
axs[
fig.tight_layout() plt.show()
Python
# https://matplotlib.org/gallery/scales/symlog_demo.html#sphx-glr-gallery-scales-symlog-demo-py
import matplotlib.pyplot as plt
import numpy as np
= 0.01
dt = np.arange(-50.0, 50.0, dt)
x = np.arange(0, 100.0, dt)
y
311)
plt.subplot(
plt.plot(x, y)'symlog')
plt.xscale('symlogx')
plt.ylabel(True)
plt.grid(True, which='minor') # minor grid on too
plt.gca().xaxis.grid(
312)
plt.subplot(
plt.plot(y, x)'symlog')
plt.yscale('symlogy')
plt.ylabel(
313)
plt.subplot(/ 3.0))
plt.plot(x, np.sin(x 'symlog')
plt.xscale('symlog', linthreshy=0.015)
plt.yscale(True)
plt.grid('symlog both')
plt.ylabel(
plt.tight_layout() plt.show()
Python
# https://matplotlib.org/gallery/lines_bars_and_markers/step_demo.html#sphx-glr-gallery-lines-bars-and-markers-step-demo-py
import numpy as np
from numpy import ma
import matplotlib.pyplot as plt
= np.arange(1, 7, 0.4)
x = np.sin(x)
y0 = y0.copy() + 2.5
y
='pre (default)')
plt.step(x, y, label
-= 0.5
y ='mid', label='mid')
plt.step(x, y, where
-= 0.5
y ='post', label='post')
plt.step(x, y, where
= ma.masked_where((y0 > -0.15) & (y0 < 0.15), y - 0.5)
y ='masked (pre)')
plt.step(x, y, label
plt.legend()
0, 7)
plt.xlim(-0.5, 4)
plt.ylim( plt.show()
5.8 Density plots
Python
# https://blogs.umass.edu/candela/computational-physics-in-python/
# Visualize the interference from two point sources, vectorized version.
import numpy as np
import matplotlib.pyplot as plt
from numpy import pi,sqrt,sin
= 5e-2 # wavelength (m) (this is 5cm as in Newman)
wavelength = 2*pi/wavelength # wavenumber (m^-1)
k = 1.0 # amplitude of the waves (arb. units)
aa0 = 20e-2 # separation of centers (m)
separation = 100e-2 # side of the square (m)
side = 500 # number of grid points along each side
points
# Calculate the positions of the centers of the circles
= side/2 + separation/2
x1 = side/2
y1 = side/2 - separation/2
x2 = side/2
y2
# Calculate an array aas with the sum of the two waves at a grid of points
= np.linspace(0,side,points) # row vector of x's
xs = np.linspace(0,side,points)[:,np.newaxis] # column vector of y's
ys = sqrt((xs-x1)**2+(ys-y1)**2)
r1s = sqrt((xs-x2)**2+(ys-y2)**2)
r2s = aa0*sin(k*r1s) + aa0*sin(k*r2s)
aas
# Make the plot
=(9,6))
plt.figure(figsize='lower',extent=[0,side,0,side])
plt.imshow(aas,origin'x (m)')
plt.xlabel('y (m)')
plt.ylabel(# plt.gray()
plt.colorbar() plt.show()