def test_quasiGalerkin(basis): N = 40 T = FunctionSpace(N, 'C') S = FunctionSpace(N, 'C', basis=basis) u = TrialFunction(S) v = TestFunction(T) A = inner(v, div(grad(u))) B = inner(v, u) Q = chebyshev.quasi.QIGmat(N) A = Q*A B = Q*B M = B-A sol = la.Solve(M, S) f_hat = inner(v, Array(T, buffer=fe)) f_hat[:-2] = Q.diags('csc')*f_hat[:-2] u_hat = Function(S) u_hat = sol(f_hat, u_hat) uj = u_hat.backward() ua = Array(S, buffer=ue) bb = Q*np.ones(N) assert abs(np.sum(bb[:8])) < 1e-8 if S.boundary_condition().lower() == 'neumann': xj, wj = S.points_and_weights() ua -= np.sum(ua*wj)/np.pi # normalize uj -= np.sum(uj*wj)/np.pi # normalize assert np.sqrt(inner(1, (uj-ua)**2)) < 1e-5
def test_PDMA(quad): SB = FunctionSpace(N, 'C', bc=(0, 0, 0, 0), quad=quad) u = TrialFunction(SB) v = TestFunction(SB) points, weights = SB.points_and_weights(N) fj = Array(SB, buffer=np.random.randn(N)) f_hat = Function(SB) f_hat = inner(v, fj, output_array=f_hat) A = inner(v, div(grad(u))) B = inner(v, u) s = SB.slice() H = A + B P = PDMA(A, B, A.scale, B.scale, solver='cython') u_hat = Function(SB) u_hat[s] = solve(H.diags().toarray()[s, s], f_hat[s]) u_hat2 = Function(SB) u_hat2 = P(u_hat2, f_hat) assert np.allclose(u_hat2, u_hat)
def test_TwoDMA(): N = 12 SD = FunctionSpace(N, 'C', basis='ShenDirichlet') HH = FunctionSpace(N, 'C', basis='Heinrichs') u = TrialFunction(HH) v = TestFunction(SD) points, weights = SD.points_and_weights(N) fj = Array(SD, buffer=np.random.randn(N)) f_hat = Function(SD) f_hat = inner(v, fj, output_array=f_hat) A = inner(v, div(grad(u))) sol = TwoDMA(A) u_hat = Function(HH) u_hat = sol(f_hat, u_hat) sol2 = la.Solve(A, HH) u_hat2 = Function(HH) u_hat2 = sol2(f_hat, u_hat2) assert np.allclose(u_hat2, u_hat)
def test_quasiTau(bc): N = 40 T = FunctionSpace(N, 'C') u = TrialFunction(T) v = TestFunction(T) A = inner(v, div(grad(u))) B = inner(v, u) Q = chebyshev.quasi.QITmat(N) A = Q*A B = Q*B bb = Q*np.ones(N) assert abs(np.sum(bb[:8])) < 1e-8 M = B-A M0 = M.diags().tolil() if bc == 'Dirichlet': M0[0] = np.ones(N) nn = np.ones(N) nn[1::2] = -1 M0[1] = nn elif bc == 'Neumann': nn = np.arange(N)**2 M0[0] = nn.copy() nn[1::2] *= -1 M0[1] = nn M0 = M0.tocsc() f_hat = inner(v, Array(T, buffer=fe)) gh = Q.diags('csc')*f_hat gh[:2] = 0 u_hat = Function(T) u_hat[:] = scp.linalg.spsolve(M0, gh) uj = u_hat.backward() ua = Array(T, buffer=ue) if bc == 'Neumann': xj, wj = T.points_and_weights() ua -= np.sum(ua*wj)/np.pi # normalize uj -= np.sum(uj*wj)/np.pi # normalize assert np.sqrt(inner(1, (uj-ua)**2)) < 1e-5
def main(N, dt=0.005, end_time=2, dealias_initial=True, plot_result=False): SD = FunctionSpace(N, 'F', dtype='D') X = SD.points_and_weights()[0] v = TestFunction(SD) U = Array(SD) dU = Function(SD) U_hat = Function(SD) U_hat0 = Function(SD) U_hat1 = Function(SD) w0 = Function(SD) a = [1. / 6., 1. / 3., 1. / 3., 1. / 6.] # Runge-Kutta parameter b = [0.5, 0.5, 1.] # Runge-Kutta parameter nu = 0.2 k = SD.wavenumbers().astype(float) # initialize U[:] = 3. / (5. - 4. * np.cos(X)) if not dealias_initial: U_hat = SD.forward(U, U_hat) else: U_hat[:] = 2**(-abs(k)) def compute_rhs(rhs, u_hat, w0): rhs.fill(0) w0.fill(0) rhs = inner(v, nu * div(grad(u_hat)), output_array=rhs) rhs -= inner(v, grad(u_hat), output_array=w0) return rhs # Integrate using a 4th order Rung-Kutta method t = 0.0 tstep = 0 if plot_result is True: im = plt.figure() ca = im.gca() ca.plot(X, U.real, 'b') plt.draw() plt.pause(1e-6) while t < end_time - 1e-8: t += dt tstep += 1 U_hat1[:] = U_hat0[:] = U_hat for rk in range(4): dU = compute_rhs(dU, U_hat, w0) if rk < 3: U_hat[:] = U_hat0 + b[rk] * dt * dU U_hat1 += a[rk] * dt * dU U_hat[:] = U_hat1 if tstep % (200) == 0 and plot_result is True: ca.plot(X, U.real) plt.pause(1e-6) #plt.savefig('Ginzburg_Landau_pad_{}_real_{}.png'.format(N[0], int(np.round(t)))) U = SD.backward(U_hat, U) Ue = np.zeros_like(U) for k in range(-100, 101): Ue += 2**(-abs(k)) * np.exp(1j * k * (X - t) - nu * k**2 * t) err = np.sqrt(2 * np.pi / N * np.linalg.norm(U - Ue.real)**2) return 1. / N, err