def __call__(self, y, exact=False, barycentric=False): """ Evaluates the spline function at point(s) y, either with Cartesian or with barycentric coordinates. :param y: set of points :return: f(y) """ if barycentric: b = y x = points_from_barycentric_coordinates(self.triangle, b) else: x = y b = barycentric_coordinates(self.triangle, x, exact=exact) k = determine_sub_triangle(b) if exact: return np.array([ self.polynomial_pieces[k[i]].subs({ 'X': x[i][0], 'Y': x[i][1] }) for i in range(len(x)) ], dtype=object) else: return np.array([ self.polynomial_pieces[k[i]].subs({ 'X': x[i][0], 'Y': x[i][1] }) for i in range(len(x)) ], dtype=np.float)
def test_coefficients_quadratic_single(): vertices = np.array([ [0, 0], [1, 0], [0, 1] ]) points = np.array([ [0, 0.25], [0, 0.5], [0.25, 0.25], [0.5, 0], ]) b = barycentric_coordinates(vertices, points) k = determine_sub_triangle(b) expected = np.array([ [0, 1, 2, 9, 10, 11], [6, 7, 8, 9, 10, 11], [1, 2, 3, 6, 10, 11], [1, 2, 3, 4, 5, 6] ]) for c, e in zip(k, expected): computed = coefficients_quadratic(c) np.testing.assert_almost_equal(computed, e)
def test_coefficients_linear_multiple(): vertices = np.array([ [0, 0], [1, 0], [0, 1] ]) points = np.array([ [0, 0.25], [0, 0.5], [0.25, 0.25], [0.5, 0], ]) b = barycentric_coordinates(vertices, points) k = determine_sub_triangle(b) expected = np.array([ [0, 5, 6], [2, 5, 8], [3, 6, 9], [1, 3, 7] ]) computed = coefficients_linear(k) np.testing.assert_almost_equal(computed, expected)
def test_derivative_evaluation_along_edge(): """ Test to see if the derivative matches that of the univariate quadratic spline along the bottom edge of unit simplex """ triangle = np.array([[0, 0], [1, 0], [0, 1]]) d = 2 r = 1 a = directional_coordinates(triangle, np.array([1, 0])) n = 1000 t_values_1 = np.linspace(0, 0.5, n, endpoint=False) t_values_2 = np.linspace(0.5, 1, n, endpoint=False) p1 = np.array([t_values_1, np.zeros(n)]).T b1 = barycentric_coordinates(triangle, p1) k1 = determine_sub_triangle(b1) expected_derivative_1 = np.array( [edge_1_derivative(t) for t in t_values_1]) computed_derivative_1 = evaluate_non_zero_basis_derivatives(d=d, r=r, k=k1, b=b1, a=a) np.testing.assert_almost_equal(expected_derivative_1, computed_derivative_1) p2 = np.array([t_values_2, np.zeros(n)]).T b2 = barycentric_coordinates(triangle, p2) k2 = determine_sub_triangle(b2) expected_derivative_2 = np.array( [edge_2_derivative(t) for t in t_values_2]) computed_derivative_2 = evaluate_non_zero_basis_derivatives(d=d, r=r, k=k2, b=b2, a=a) np.testing.assert_almost_equal(expected_derivative_2, computed_derivative_2)
def test_non_zero_splines_evaluation_multiple_quadratic(): """ Computes all the non-zero quadratic basis splines at a set of points, and asserts that for each point, the basis functions sum to one. """ triangle = np.array([[0, 0], [1, 0], [0, 1]]) d = 2 points = sample_triangle(triangle, 30) bary_coords = barycentric_coordinates(triangle, points) k = determine_sub_triangle(bary_coords) s = evaluate_non_zero_basis_splines(d, bary_coords, k) expected_sum = np.ones((len(points))) computed_sum = s.sum(axis=1) np.testing.assert_almost_equal(expected_sum, computed_sum)
def test_laplacian_quadratic_basis_functions(): X, Y = sy.symbols('X Y') triangle = np.array([[0, 0], [1, 0], [0, 1]]) S = SplineSpace(triangle, 2) points = sample_triangle(triangle, 10) for basis_num in range(12): b_num = S.basis()[basis_num] b_sym = polynomial_pieces(triangle, KNOT_MULTIPLICITIES_QUADRATIC[basis_num]) for p in points: b = barycentric_coordinates(triangle, p) k = determine_sub_triangle(b)[0] b_lapl = sy.diff(b_sym[k], X, X) + sy.diff(b_sym[k], Y, Y) num_b_sym = sy.lambdify([X, Y], b_lapl) np.testing.assert_almost_equal(b_num.lapl(p), num_b_sym(p[0], p[1]))
def test_determine_sub_triangle_multiple(): triangle = np.array([ [0, 0], [1, 0], [0, 1] ]) points = np.array([ [0, 0.25], [0, 0.5], [0.25, 0.25], [0.5, 0], ]) bary_coords = barycentric_coordinates(triangle, points) expected = np.array([ 0, 5, 7, 2 ]) computed = determine_sub_triangle(bary_coords) np.testing.assert_almost_equal(computed, expected) assert computed.dtype == np.int
def D(self, x, u, r): """ Evaluates the r'th directional derivative of the function at the point(s) x in direction u. :param x: set of points :param u: direction :param r: order of derivative :return: f^(r)(x) """ b = barycentric_coordinates(self.triangle, x) k = determine_sub_triangle(b) a = directional_coordinates(self.triangle, u) z = evaluate_non_zero_basis_derivatives(a=a, b=b, k=k, r=r, d=self.degree) c = self._non_zero_coefficients(k) return np.einsum( '...i,...i->...', z, c) # broadcast the dot product to compute all values at once.
def __call__(self, x, barycentric=False, exact=False): """ Evaluates the spline function at point(s) x. :param x: set of points :return: f(x) """ if barycentric: b = x else: b = barycentric_coordinates(self.triangle, x, exact=exact) k = determine_sub_triangle(b) z = evaluate_non_zero_basis_splines( b=b, d=self.degree, k=k, exact=exact, alternative_basis=self.alternative_basis) c = self._non_zero_coefficients(k) return np.einsum( '...i,...i->...', z, c) # broadcast the dot product to compute all values at once.