def test_bspline(control, knots): # SEEMS TO WORK? """ Test if Cubic Spline created from object CubicSpline equals the sum of the control points and basis functions as in section 1.5 """ cubsplin = CubicSpline(control, knots) size = 10000 bspline = zeros((size, 2)) basis_functions = array( [basis_function(size, knots, j) for j in range(len(knots) - 2)]) for u in range(size): bspline[u] = sum(control[i] * basis_functions[i, u] for i in range(len(basis_functions))) plt.plot(cubsplin.get_spline()[:, 0], cubsplin.get_spline()[:, 1], 'r', label="cubic spline") # spline plt.plot(bspline[:, 0], bspline[:, 1], 'b', label="bspline") # spline # plt.plot(control[:, 0], control[:, 1], '-.r', label="control polygon") # control polygon # plt.scatter(control[:, 0], control[:, 1], color='red') # de Boor points plt.title("B-Spline") plt.legend() plt.xlabel("x") plt.ylabel("y") plt.grid() plt.show()
def test_bspline(self): """ Test if Cubic Spline created from object CubicSpline equals the sum of the control points and basis functions as in section 1.5 """ cubsplin = CubicSpline(self.test_control, self.test_knots) size = 10000 bspline = zeros((size, 2)) basis_functions = array([basis_function(size, self.test_knots, j) for j in range(len(self.test_knots) - 2)]) for u in range(size): bspline[u] = sum(self.test_control[i] * basis_functions[i, u] for i in range(len(basis_functions))) assert_allclose(cubsplin.get_spline(), bspline)
def test_basis_functions(knots): """ Plot every basis function according to the given knots :param knots: (array) :return: None """ size = 1000 L = len(knots) - 3 first_knot = knots[0] last_knot = knots[-1] xspace = linspace(first_knot, last_knot, size) for j in range(L + 1): temp_base = basis_function(size, knots, j) plt.plot(xspace, temp_base) plt.title("Basis functions from {} to {}".format("$u_0$", "$u_{}$".format({L}))) plt.xlabel("u") plt.grid() plt.show()
def assemble_fem ( x_num, x, element_num, element_node, quad_num, t, k_fun, \ rhs_fun ): #*****************************************************************************80 # ## ASSEMBLE_FEM assembles the finite element stiffness matrix. # # Licensing: # # This code is distributed under the GNU LGPL license. # # Modified: # # 07 November 2014 # # Author: # # John Burkardt # # Parameters: # # Input, integer X_NUM, the number of nodes. # # Input, real X(X_NUM), the coordinates of nodes. # # Input, integer ELEMENT_NUM, the number of elements. # # Input, integer ELEMENT_NODE(2,ELEMENT_NUM); # ELEMENT_NODE(I,J) is the global index of local node I in element J. # # Input, integer QUAD_NUM, the number of quadrature points used in assembly. # # Input, real T, the current time. # # Input, real K_FUN(), a function to evaluate the heat conductivity. # # Input, real RHS_FUN(), a function to evaluate the right hand side. # # Output, sparse real A(X_NUM,X_NUM), the finite element stiffness matrix. # # Output, real B(X_NUM), the right hand side. # # Local parameters: # # Local, real BI, DBIDX, the value of some basis function # and its first derivative at a quadrature point. # # Local, real BJ, DBJDX, the value of another basis # function and its first derivative at a quadrature point. # from basis_function import basis_function from quadrature_set import quadrature_set from reference_to_physical import reference_to_physical import numpy as np # # Initialize the arrays. # b = np.zeros(x_num) a = np.zeros((x_num, x_num)) # # Get the quadrature weights and nodes. # reference_w, reference_q = quadrature_set(quad_num) # # Consider each ELEMENT. # for element in range(0, element_num): element_x = np.zeros(2) element_x[0] = x[element_node[0, element]] element_x[1] = x[element_node[1, element]] element_q = reference_to_physical ( element, element_node, x, quad_num, \ reference_q ) element_area = element_x[1] - element_x[0] element_w = np.zeros(quad_num) for quad in range(0, quad_num): element_w[quad] = (element_area / 2.0) * reference_w[quad] # # Consider the QUAD-th quadrature point in the element. # k_value = k_fun(quad_num, element_q, t) rhs_value = rhs_fun(quad_num, element_q, t) for quad in range(0, quad_num): # # Consider the TEST-th test function. # # We generate an integral for every node associated with an unknown. # for i in range(0, 2): test = element_node[i, element] bi, dbidx = basis_function(test, element, x, element_q[quad]) b[test] = b[test] + element_w[quad] * rhs_value[quad] * bi # # Consider the BASIS-th basis function, which is used to form the # value of the solution function. # for j in range(0, 2): basis = element_node[j, element] bj, dbjdx = basis_function(basis, element, x, element_q[quad]) a[test,basis] = a[test,basis] + element_w[quad] * ( \ + k_value[quad] * dbidx * dbjdx ) return a, b
def assemble_mass ( node_num, node_x, element_num, element_node, quad_num ): #*****************************************************************************80 # ## ASSEMBLE_MASS assembles the finite element mass matrix. # # Licensing: # # This code is distributed under the GNU LGPL license. # # Modified: # # 07 November 2014 # # Author: # # John Burkardt # # Parameters: # # Input, integer NODE_NUM, the number of nodes. # # Input, real NODE_X(NODE_NUM), the coordinates of nodes. # # Input, integer ELEMENT_NUM, the number of elements. # # Input, integer ELEMENT_NODE(2,ELEMENT_NUM); # ELEMENT_NODE(I,J) is the global index of local node I in element J. # # Input, integer QUAD_NUM, the number of quadrature points used in assembly. # # Output, sparse real C(NODE_NUM,NODE_NUM), the finite element mass matrix. # # Local parameters: # # Local, real BI, DBIDX, the value of some basis function # and its first derivative at a quadrature point. # # Local, real BJ, DBJDX, the value of another basis # function and its first derivative at a quadrature point. # from basis_function import basis_function from quadrature_set import quadrature_set from reference_to_physical import reference_to_physical import numpy as np # # Initialize the arrays. # c = np.zeros ( ( node_num, node_num ) ) # # Get the quadrature weights and nodes. # reference_w, reference_q = quadrature_set ( quad_num ) # # Consider each ELEMENT. # for element in range ( 0, element_num ): element_x = np.zeros ( 2 ) element_x[0] = node_x[element_node[0,element]] element_x[1] = node_x[element_node[1,element]] element_q = reference_to_physical ( element, element_node, node_x, \ quad_num, reference_q ) element_area = element_x[1] - element_x[0] element_w = np.zeros ( quad_num ) for quad in range ( 0, quad_num ): element_w[quad] = ( element_area / 2.0 ) * reference_w[quad] # # Consider the QUAD-th quadrature point in the element. # for quad in range ( 0, quad_num ): # # Consider the TEST-th test function. # # We generate an integral for every node associated with an unknown. # for i in range ( 0, 2 ): test = element_node[i,element] bi, dbidx = basis_function ( test, element, node_x, element_q[quad] ) # # Consider the BASIS-th basis function, which is used to form the # value of the solution function. # for j in range ( 0, 2 ): basis = element_node[j,element] bj, dbjdx = basis_function ( basis, element, node_x, element_q[quad] ) c[test,basis] = c[test,basis] + element_w[quad] * bi * bj return c
def assemble_fem ( x_num, x, element_num, element_node, quad_num, t, k_fun, \ rhs_fun ): #*****************************************************************************80 # ## ASSEMBLE_FEM assembles the finite element stiffness matrix. # # Licensing: # # This code is distributed under the GNU LGPL license. # # Modified: # # 07 November 2014 # # Author: # # John Burkardt # # Parameters: # # Input, integer X_NUM, the number of nodes. # # Input, real X(X_NUM), the coordinates of nodes. # # Input, integer ELEMENT_NUM, the number of elements. # # Input, integer ELEMENT_NODE(2,ELEMENT_NUM); # ELEMENT_NODE(I,J) is the global index of local node I in element J. # # Input, integer QUAD_NUM, the number of quadrature points used in assembly. # # Input, real T, the current time. # # Input, real K_FUN(), a function to evaluate the heat conductivity. # # Input, real RHS_FUN(), a function to evaluate the right hand side. # # Output, sparse real A(X_NUM,X_NUM), the finite element stiffness matrix. # # Output, real B(X_NUM), the right hand side. # # Local parameters: # # Local, real BI, DBIDX, the value of some basis function # and its first derivative at a quadrature point. # # Local, real BJ, DBJDX, the value of another basis # function and its first derivative at a quadrature point. # from basis_function import basis_function from quadrature_set import quadrature_set from reference_to_physical import reference_to_physical import numpy as np # # Initialize the arrays. # b = np.zeros ( x_num ) a = np.zeros ( ( x_num, x_num ) ) # # Get the quadrature weights and nodes. # reference_w, reference_q = quadrature_set ( quad_num ) # # Consider each ELEMENT. # for element in range ( 0, element_num ): element_x = np.zeros ( 2 ) element_x[0] = x[element_node[0,element]] element_x[1] = x[element_node[1,element]] element_q = reference_to_physical ( element, element_node, x, quad_num, \ reference_q ) element_area = element_x[1] - element_x[0] element_w = np.zeros ( quad_num ) for quad in range ( 0, quad_num ): element_w[quad] = ( element_area / 2.0 ) * reference_w[quad] # # Consider the QUAD-th quadrature point in the element. # k_value = k_fun ( quad_num, element_q, t ) rhs_value = rhs_fun ( quad_num, element_q, t ) for quad in range ( 0, quad_num ): # # Consider the TEST-th test function. # # We generate an integral for every node associated with an unknown. # for i in range ( 0, 2 ): test = element_node[i,element] bi, dbidx = basis_function ( test, element, x, element_q[quad] ) b[test] = b[test] + element_w[quad] * rhs_value[quad] * bi # # Consider the BASIS-th basis function, which is used to form the # value of the solution function. # for j in range ( 0, 2 ): basis = element_node[j,element] bj, dbjdx = basis_function ( basis, element, x, element_q[quad] ) a[test,basis] = a[test,basis] + element_w[quad] * ( \ + k_value[quad] * dbidx * dbjdx ) return a, b