Example #1
0
    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)
Example #2
0
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)
Example #3
0
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.