示例#1
0
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
示例#3
0
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