def inhomogeneous_dirichlet(): start = time.time() bdy = (-np.pi / 2, np.pi / 2) bc = (-1.0, 1.0) # generate the centres N = 9 centres = np.linspace(bdy[0], bdy[1], N) # forcing term f = lambda r: 2 * np.sin(r) # use Gauss-Legendre quadrature to integrate: pts, weights = gauleg(30) # pick a value for delta delta = 0.7 # make the matrix system A_mat, rhs_vec = build_1d_dirichlet_problem(N, centres, pts, weights, f, delta, bdy=bdy, bc=(-1.0, 1.0)) A_mat_full = A_mat + A_mat.transpose() - np.diag(np.diag(A_mat)) # and solve the system c = np.linalg.solve(A_mat_full, rhs_vec) print('Condition number of stiffness matrix is {:.3E}'.format( np.linalg.cond(A_mat_full))) # exact solution lambda function u = lambda r: np.sin(r) # evaluate the solution at a set of test points test_pt_ct = 40 test_pts = np.linspace(bdy[0], bdy[1], test_pt_ct) exact_sol = u(test_pts) # evaluate the basis functions at the test points RBF_vals = rbf_1_mat(delta, test_pts, centres) numerical_sol = np.dot(RBF_vals, c) # find the error in the numerical solutions print('RMS Error = {:.6E}'.format( np.linalg.norm(exact_sol - numerical_sol, 2) / test_pt_ct)) print('Maximum Error = {:.6E}'.format( np.linalg.norm(exact_sol - numerical_sol, np.inf))) print('Total time taken was {:.3f} seconds'.format(time.time() - start)) plt.plot(test_pts, exact_sol) plt.plot(test_pts, numerical_sol) plt.show() return
def homogeneous_neumann(): start = time.time() bdy = [-1., 1., -1., 1.] # generate the centres -- this can easily be changed for different rectangular domains # needs more thought for non-rectangles! N = 17 xcentres, ycentres = np.meshgrid(np.linspace(-1, 1, N), np.linspace(-1, 1, N)) xcentres = xcentres.reshape(N * N, ) ycentres = ycentres.reshape(N * N, ) # forcing term f = lambda x, y: np.cos(np.pi * x) * np.cos(np.pi * y) # use Gauss-Legendre quadrature to integrate overlapping supports: # faster to generate the pts and weights just once and shift/scale as needed # could pick a different number of points depending on accuracy needed pts, weights = gauleg( 30) # number related to no. of basis funcs/support radius # rethink number of points as we do multilevel # pick a value for delta delta = 1.183 # make the full A A_mat, rhs_vec = build_2d_neumann_problem(N, xcentres, ycentres, pts, weights, f, delta) A_mat_full = A_mat + A_mat.transpose() - np.diag(np.diag(A_mat)) # and solve the linear system c = np.linalg.solve(A_mat_full, rhs_vec) print('Condition number of stiffness matrix is {:.3E}'.format( np.linalg.cond(A_mat_full))) # exact solution lambda function u = lambda x, y: np.cos(np.pi * x) * np.cos(np.pi * y) / (2 * np.pi**2 + 1 ) # vectorised # evaluate the solution at a set of points test_pt_ct = 40 x_test_pts_g, y_test_pts_g = np.meshgrid( np.linspace(bdy[0], bdy[1], test_pt_ct), np.linspace(bdy[2], bdy[3], test_pt_ct)) x_test_pts = x_test_pts_g.reshape(test_pt_ct**2, ) y_test_pts = y_test_pts_g.reshape(test_pt_ct**2, ) exact_sol = u(x_test_pts, y_test_pts).reshape((test_pt_ct**2, )) # evaluate the basis functions and numerical soln at the same set of points RBF_vals = rbf_2_mat(delta, x_test_pts, y_test_pts, xcentres.reshape((N * N, )), ycentres.reshape((N * N, ))) numerical_sol = np.dot(RBF_vals, c) rms_err = (exact_sol - numerical_sol) rms_err_m = rms_err.reshape((test_pt_ct, test_pt_ct)) # find the error in the numerical solutions print('RMS Error = {:.6E}'.format( np.linalg.norm(exact_sol - numerical_sol, 2) / test_pt_ct)) print('Maximum Error = {:.6E}'.format( np.linalg.norm(exact_sol - numerical_sol, np.inf))) print('Total time taken was {:.3f} seconds'.format(time.time() - start)) # should move the following to a plotting module fig = plt.figure() ax = fig.add_subplot(1, 2, 1, projection='3d') # plt.plot(xcentres, ycentres,[0]*N*N,'k*') surf = ax.plot_surface(x_test_pts_g, y_test_pts_g, numerical_sol.reshape((test_pt_ct, test_pt_ct)), cmap=cm.coolwarm, linewidth=0, antialiased=False) fig.colorbar(surf, shrink=0.5, aspect=5) ax = fig.add_subplot(1, 2, 2, projection='3d') errsurf = ax.plot_surface(x_test_pts_g, y_test_pts_g, rms_err.reshape((test_pt_ct, test_pt_ct)), cmap=cm.coolwarm, linewidth=0, antialiased=False) fig.colorbar(errsurf, shrink=0.5, aspect=5) plt.savefig('helmholtz_test.eps', format='eps', dpi=1000) plt.show() fig = plt.figure() ax = fig.add_subplot(1, 2, 2) ax.set_title('Error: Exact - Numerical') errconts = plt.contourf(x_test_pts_g, y_test_pts_g, rms_err_m, 15, cmap=cm.BrBG) fig.colorbar(errconts, shrink=0.5, aspect=5) ax = fig.add_subplot(1, 2, 1) ax.set_title('Numerical Solution') conts = plt.contourf(x_test_pts_g, y_test_pts_g, numerical_sol.reshape((test_pt_ct, test_pt_ct)), 15, cmap=cm.viridis) fig.colorbar(conts, shrink=0.5, aspect=5) plt.show() return
def homogeneous_neumann(): start = time.time() # first implement Algorithm 2 from (Wendland 1999) m = 3 # number of levels N = 5 # number of RBFs on the coarsest grid delta = 0.7 # RBF support on coarsest grid bdy = [-1.0, 1.0, -1.0, 1.0] # forcing term f = lambda x, y: np.cos(np.pi * x) * np.cos(np.pi * y) # quadrature points and weights pts, weights = gauleg(30) all_N = np.array([2**(i + 2) + 1 for i in range(m)]) # all the Ns needed # all the deltas needed -- dunno if this is even a good set of choices but YOLO all_delta = np.array([delta * 1.3**(i) for i in range(m)]) # to have a numerical soln we'll need to know where to evaluate the solution? # for the purposes of nailing down the algorithm, let's just pick something rn # exact solution lambda function u = lambda x, y: np.cos(np.pi * x) * np.cos(np.pi * y) / (2 * np.pi**2 + 1 ) # vectorised # evaluate the solution at a set of points test_pt_ct = 50 test_grid = np.linspace(-1, 1, test_pt_ct) x_test_pts_g, y_test_pts_g = np.meshgrid(test_grid, test_grid) x_test_pts = x_test_pts_g.reshape(test_pt_ct**2, ) y_test_pts = y_test_pts_g.reshape(test_pt_ct**2, ) exact_sol = u(x_test_pts, y_test_pts).reshape((test_pt_ct**2, )) # set v_0 = 0, storage for v_{k-1} num_sol = np.zeros(test_pt_ct * test_pt_ct) # old_num_sol = np.zeros(test_pt_ct *test_pt_ct) # A_km1 = 0 c_km1 = 0 for k in range(m): print('Currently on level {}'.format(k)) this_N = all_N[k] this_delta = all_delta[k] # generate the rbf centres for this level xcentres, ycentres = np.meshgrid(np.linspace(bdy[0], bdy[1], this_N), np.linspace(bdy[2], bdy[3], this_N)) xcentres = xcentres.reshape(this_N * this_N, ) ycentres = ycentres.reshape(this_N * this_N, ) # find uk in Vk with a(uk, v) = f(v) - a(v_{k-1}, v) forall v in Vk # i.e. solve c_k = A_k\(f_k - A_k-1*c_k-1) A_k, rhs_k = build_2d_neumann_problem(this_N, xcentres, ycentres, pts, weights, f, this_delta) A_k = A_k + A_k.transpose() - np.diag(np.diag(A_k)) if k >= 1: old_rect_A = non_square_2d_neumann_matrix(old_xcentres, old_ycentres, xcentres, ycentres, pts, weights, this_delta) else: old_rect_A = 0 c_k = np.linalg.solve(A_k, rhs_k - np.dot(old_rect_A, c_km1)) # now generate the numerical solution at the desired points RBF_vals_k = rbf_2_mat(delta, x_test_pts, y_test_pts, xcentres.reshape((this_N * this_N, )), ycentres.reshape((this_N * this_N, ))) u_k = np.dot(RBF_vals_k, c_k) # set vk = vkm1 + uk, update num_sol = num_sol + u_k c_km1 = c_k old_xcentres = xcentres old_ycentres = ycentres pass # RBF_vals = rbf_2_mat(delta, x_test_pts, y_test_pts, xcentres.reshape((N * N, )), ycentres.reshape((N * N, ))) # num_sol = np.dot(RBF_vals, c_k) rms_err = (exact_sol - num_sol) rms_err_m = rms_err.reshape((test_pt_ct, test_pt_ct)) # find the error in the numerical solutions print('RMS Error = {:.6E}'.format( np.linalg.norm(exact_sol - num_sol, 2) / test_pt_ct)) print('Maximum Error = {:.6E}'.format( np.linalg.norm(exact_sol - num_sol, np.inf))) print('Total time taken was {:.3f} seconds'.format(time.time() - start)) return