Recordar:
La discretización en este caso es la misma que para el caso clásico de Poisson con condiciones de Dirichlet, solo que ahora debemos tener cuidado a la hora de elegir qué tipo de diferencias finitas queremos usar para $u_x$.
Normalmente usamos aproximaciones de primer orden. Una ventaja de esto es que podemos mantener la forma general de resolver este sistema $Au=b$, pero por otra parte las diferencias de primer orden llevan a un error mayor que las diferencias de segundo orden usadas para aproximar las segundas derivadas.
In [403]:
import numpy as np
from scipy.integrate import fixed_quad
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
%matplotlib notebook
In [481]:
def poisson_equation(xl, xr, yb, yt, M, N):
"""
Solving Poisson Equation with Neumann Conditions over two boundaries.
Args:
[xl, xr]: Space interval X
[yb, yt]: Space interval Y
M, N: Space and time steps
f: Condition imposed for \Delta u = f
g1, g2, g3, g4: Boundary conditions for y=yb, x=xl, y=yt and x=xr
Notice that g2 and g4 are Neumann Conditions
"""
# Step sizes
h, k = (xr-xl)/M, (yt-yb)/N
m, n = M+1, N+1
xx = np.linspace(xl, xr, m)
yy = np.linspace(yb, yt, n)
# Boundary conditions, it's easier for me to modify inside the solver
# Notice g2 and g4 are Neumann Conditions
f = lambda x, y: 0
g1 = lambda x: 1
g2 = lambda y: -5
g3 = lambda x: -1
g4 = lambda y: -5
# Finite differences matrix
A = np.zeros((m*n, m*n))
b = np.zeros((m*n, 1))
# Define global indexing, useful for linearize the matrix
idx = lambda i, j: i + j*m
for i in range(m):
for j in range(n):
r = idx(i,j)
if j == 0:
A[r,r] = 1.
b[r] = g1(xx[i])
elif i == M:
A[r,r] = 1.
A[r,r-1]=-1
b[r] = h*g2(yy[j])
elif j == N:
A[r,r] = 1.
b[r] = g3(xx[i])
elif i == 0:
A[r,r] = 1.
A[r,r+1]=-1
b[r] = h*g4(yy[j])
else:
A[r,r] = -2./h**2 - 2./k**2
A[r,idx(i+1,j)] = 1./h**2
A[r,idx(i-1,j)] = 1./h**2
A[r,idx(i,j-1)] = 1./k**2
A[r,idx(i,j+1)] = 1./k**2
b[r] = f(xx[i], yy[j])
print("Cond(A)=%f" % (np.linalg.cond(A)))
W = np.linalg.solve(A,b)
print("System solved.")
return (xx, yy, W.reshape(m, n))
In [482]:
xl, xr, yb, yt = 0., 1., 0., 1.
M, N = 40,40
xx, yy, W = poisson_equation(xl, xr, yb, yt, M, N)
[X, Y] = np.meshgrid(xx, yy)
# Plot results
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.set_xlabel("$x$", fontsize=20)
ax.set_ylabel("$y$", fontsize=20)
ax.set_zlabel("$u(x,y)$", fontsize=20)
ax.set_title("Poisson Equation")
surface = ax.plot_surface(X, Y, W, cmap=cm.jet, linewidth=0, antialiased=True, rstride=1, cstride=1)
fig.colorbar(surface)
plt.tight_layout()
plt.draw()
El presente notebook ha sido creado para el curso ILI286 - Computación Científica 2, del Departamento de Informática, Universidad Técnica Federico Santa María. El material ha sido creado por Alejandro Sazo (asazo@alumnos.inf.utfsm.cl). En caso de encontrar un error, por favor no dude en contactar al email especificado. Puede encontrar la última versión del código en https://github.com/asazo/CC2
In [ ]: