Skip to content

Instantly share code, notes, and snippets.

@amkatrutsa
Created May 8, 2015 18:49
Show Gist options
  • Select an option

  • Save amkatrutsa/29cf7c808bf40daa0590 to your computer and use it in GitHub Desktop.

Select an option

Save amkatrutsa/29cf7c808bf40daa0590 to your computer and use it in GitHub Desktop.
def get_P(n):
val = [1, 2, 1] * (n / 2)
col = []
for i in xrange(n / 2):
col += 3*[i]
row = []
for j in xrange((n-1)/2):
row += range(2*j, 2*j + 3)
P = scsp.csr_matrix((val, (row, col)), shape=(n, (n-1)/2))
return 0.5 * P
def MG_V_1d(l, u_old, rhs, A):
if (l == 0):
u_new = scspla.spsolve(A, rhs)
else:
u = u_old.copy()
P = get_P(u.shape[0])
R = 0.5 * P.T
ev1, _ = scspla.eigs(A, k=3, which='LR')
ev2, _ = scspla.eigs(A, k=3, which='SR')
lam_max = ev1[0]
lam_min = ev2[0]
tau_opt = np.real(2.0/(lam_max + lam_min))
# tau_opt = -3 * 1e-5
print "Start smoother with tau", tau_opt
for it in xrange(5):
rr = A.dot(u) - rhs
print np.linalg.norm(rr)
u = u - tau_opt * rr
res = R.dot(A.dot(u) - rhs)
A = R.dot(A.dot(P))
e = np.zeros(u.shape[0] / 2)
for i in xrange(1):
e = MG_V_1d(l - 1, e, res, A)
u_new = u - P.dot(e)
return u_new
N = 128
x = np.linspace(1.0 / N, 1, N - 1, endpoint=False)
f = -np.pi**2 * np.sin(np.pi * x)
ex = np.ones(N-1);
A = N**2 * scsp.spdiags(np.vstack((ex, -2*ex, ex)), [-1, 0, 1], N-1, N-1, 'csr');
u0 = np.zeros(N-1)
u = MG_V_1d(5, u0, f, A)
print u.shape
print np.linalg.norm(np.sin(np.pi * x) - u)
plt.plot(x, np.sin(np.pi * x))
plt.plot(x, u)
plt.legend(["Exact", r"Approx"])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment