def test_evaluate_failure(self):
        c = [1.0, 1.0]
        p = tl.MVP2D(c)
        with self.assertRaises(tl.TriangularException):
            p.evaluate(0.0, 0.0)

        c = [1.0, 1.0, 1.0, 0.0]
        p = tl.MVP2D(c)
        with self.assertRaises(tl.TriangularException):
            p.evaluate(-42.6733, -27.0083)

        c = [1.0, 1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 1.0]
        p = tl.MVP2D(c)
        with self.assertRaises(tl.TriangularException):
            p.evaluate(-42.6733, -27.0083)
    def test_augmented_line_integral_4(self):
        '''MVP2D.augmented_line_integral: parabollic prism with pos and neg integrate to zero'''
        for trial in range(100):

            # generate coefs of parabolic prism that ensure positve and negative regions
            a0 = np.random.uniform(-10, 10)
            a3 = np.random.uniform(-10, 10)
            a3 = -a3 if np.sign(a3) == np.sign(a0) else a3

            # randomly assign prism along x or y axis
            if np.random.rand() > 0.5:
                coefs = np.array([a0, 0.0, 0.0, a3, 0.0, 0])
            else:
                coefs = np.array([a0, 0.0, 0.0, a3, 0.0, 0])
            mvp = tl.MVP2D(coefs)

            # form square region of integration
            b = np.sqrt(-3.0 * a0 / a3)
            verts = [(-b, -b), (b, -b), (b, b), (-b, b)]

            # perform integral and test it is approximately 0
            I = 0.0
            for i, _ in enumerate(verts[:-1]):
                I += mvp.augmented_line_integral(verts[i], verts[i + 1])
            I += mvp.augmented_line_integral(verts[-1], verts[0])

            self.assertAlmostEqual(I, 0.0)
 def test_evaluate_3(self):
     # polynomial = 1
     c = [1.0]
     p = tl.MVP2D(c)
     self.assertAlmostEqual(p.evaluate(0.0, 0.0), 1.0)
     self.assertAlmostEqual(p.evaluate(1.0, 0.0), 1.0)
     self.assertAlmostEqual(p.evaluate(-1.0, 1.0), 1.0)
     self.assertAlmostEqual(p.evaluate(0.0, 1.0), 1.0)
     self.assertAlmostEqual(p.evaluate(-42.6733, -27.0083), 1.0)
 def test_evaluate_2(self):
     # polynomial = 1 + x + y + x^2 + x*y + y^2
     c = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0]
     p = tl.MVP2D(c)
     self.assertAlmostEqual(p.evaluate(0.0, 0.0), 1.0)
     self.assertAlmostEqual(p.evaluate(1.0, 0.0), 3.0)
     self.assertAlmostEqual(p.evaluate(-1.0, 1.0), 2.0)
     self.assertAlmostEqual(p.evaluate(0.0, 1.0), 3.0)
     self.assertAlmostEqual(p.evaluate(-42.6733, -27.0083),
                            3634.310490169999)
 def test_evaluate_1(self):
     # polynomial = x^2 + y^2
     c = [0.0, 0.0, 0.0, 1.0, 0.0, 1.0]
     p = tl.MVP2D(c)
     self.assertAlmostEqual(p.evaluate(0.0, 0.0), 0.0)
     self.assertAlmostEqual(p.evaluate(1.0, 0.0), 1.0)
     self.assertAlmostEqual(p.evaluate(-1.0, 1.0), 2.0)
     self.assertAlmostEqual(p.evaluate(0.0, 1.0), 1.0)
     self.assertAlmostEqual(p.evaluate(-42.6733, -27.0083),
                            2550.4588017799997)
    def test_augmented_line_integral_2(self):
        '''MVP2D.augmented_line_integral: square region under parabolic dome'''
        coefs = np.array([1.0, 0.0, 0.0, -1.0, 0.0, -1.0])
        mvp = tl.MVP2D(coefs)
        b = np.sqrt(2.0) / 2.0
        verts = [(-b, -b), (b, -b), (b, b), (-b, b)]
        expected_integral = 4.0 * b**2 - 8.0 / 3.0 * b**4

        I = 0.0
        for i, _ in enumerate(verts[:-1]):
            I += mvp.augmented_line_integral(verts[i], verts[i + 1])
        I += mvp.augmented_line_integral(verts[-1], verts[0])

        self.assertAlmostEqual(I, expected_integral)
 def test_evaluate_4(self):
     # polynomial = (randomly generated coefs)
     c = [
         4.9888785066963, -2.6072258560952, 2.6480911731013,
         1.9870246909498, 4.6454780151348, 2.2809308451977,
         -9.5205873062464, 0.850583925308, 9.0531745362343, -9.9005566723182
     ]
     p = tl.MVP2D(c)
     self.assertAlmostEqual(p.evaluate(0.0, 0.0), 4.9888785066963)
     self.assertAlmostEqual(p.evaluate(1.0, 0.0), -5.1519099646955)
     self.assertAlmostEqual(p.evaluate(-1.0, 1.0), 1.2841130799074048)
     self.assertAlmostEqual(p.evaluate(0.0, 1.0), 0.017343852677100813)
     self.assertAlmostEqual(p.evaluate(-42.6733, -27.0083),
                            621923.6139074472)
    def test_convex_hull_integral_2(self):
        '''MVP2D.convex_hull_integral: integral over parabolic dome with random internal points'''

        coefs = np.array([1.0, 0.0, 0.0, -1.0, 0.0, -1.0])
        mvp = tl.MVP2D(coefs)
        b = np.sqrt(2.0) / 2.0
        ext_verts = np.asarray([(-b, -b), (b, -b), (b, b), (-b, b)])
        expected_integral = 4.0 * b**2 - 8.0 / 3.0 * b**4

        for trial in range(100):

            points = np.concatenate(
                (ext_verts, np.random.rand(30, 2) * 2 * b - b))
            np.random.shuffle(points)
            I = mvp.convex_hull_integral(points)
            self.assertAlmostEqual(I, expected_integral)
    def test_convex_hull_integral_3(self):
        '''MVP2D.convex_hull_integral: integral over degenerate hull with random mvp'''

        for trial in range(100):

            coefs = np.random.rand(6) * 10.0 - 5.0
            mvp = tl.MVP2D(coefs)
            rand_vert_0 = tuple(np.random.rand(2) * 20.0 - 10.0)
            rand_vert_1 = tuple(np.random.rand(2) * 20.0 - 10.0)
            collinear_vert = tuple(
                np.random.rand(1) * 10.0 * np.array([
                    rand_vert_1[0] - rand_vert_0[0], rand_vert_1[1] -
                    rand_vert_0[1]
                ]) + rand_vert_0)
            points = np.array([rand_vert_0, rand_vert_1, collinear_vert])
            np.random.shuffle(points)
            I = mvp.convex_hull_integral(points)
            self.assertAlmostEqual(I, 0.0)
    def test_convex_hull_integral_1(self):
        '''MVP2D.convex_hull_integral: integral over unit cube with shuffled vertices'''

        points = [(0, 0), (1, 0), (1, 1), (0, 1)]
        for trial in range(100):

            random.shuffle(points)

            # generate random heigh of uniform curce
            a0 = np.random.uniform(-10, 10)

            # generate random length coefficient mvp
            coef_len = random.choice([1, 3, 6, 10, 15, 21])
            coefs = np.concatenate(([a0], np.zeros(coef_len - 1)))
            mvp = tl.MVP2D(coefs)

            I = mvp.convex_hull_integral(points)

            self.assertAlmostEqual(I, a0)
    def test_augmented_line_integral_3(self):
        '''MVP2D.augmented_line_integral: ramp through origin integrates to zero over symmetric bounds'''
        for trial in range(100):

            # generate coefs of 2D ramp through origin
            a1 = np.random.uniform(-10, 10)
            a2 = np.random.uniform(-10, 10)
            coefs = np.array([0.0, a1, a2])
            mvp = tl.MVP2D(coefs)

            # form rectangular region centered on zero
            xc = np.random.uniform(0, 10)
            yc = np.random.uniform(0, 10)
            verts = [(-xc, -yc), (xc, -yc), (xc, yc), (-xc, yc)]

            # perform integral and test it is approximately 0
            I = 0.0
            for i, _ in enumerate(verts[:-1]):
                I += mvp.augmented_line_integral(verts[i], verts[i + 1])
            I += mvp.augmented_line_integral(verts[-1], verts[0])

            self.assertAlmostEqual(I, 0.0)
    def test_augmented_line_integral_1(self):
        '''MVP2D.augmented_line_integral: test integral of unit cube'''
        c = [1.0]
        mvp = tl.MVP2D(c)

        # test full cube
        verts = [(0, 0), (1, 0), (1, 1), (0, 1)]
        I = 0.0
        for i, _ in enumerate(verts[:-1]):
            I += mvp.augmented_line_integral(verts[i], verts[i + 1])

        I += mvp.augmented_line_integral(verts[-1], verts[0])
        self.assertAlmostEqual(I, 1.0)

        # test half cube
        verts = [(0, 0), (1, 0), (1, 1)]
        I = 0.0
        for i, _ in enumerate(verts[:-1]):
            I += mvp.augmented_line_integral(verts[i], verts[i + 1])

        I += mvp.augmented_line_integral(verts[-1], verts[0])
        self.assertAlmostEqual(I, 0.5)
    def test_augmented_line_integral_5(self):
        '''MVP2D.augmented_line_integral: random triangular region under uniform curve with random length coeffs'''
        for trial in range(100):

            # generate random heigh of uniform curce
            a0 = np.random.uniform(-10, 10)

            # generate random length coefficient mvp
            coef_len = random.choice([1, 3, 6, 10, 15, 21])
            coefs = np.concatenate(([a0], np.zeros(coef_len - 1)))
            mvp = tl.MVP2D(coefs)

            # form random triangular path with positive orientation
            p1 = np.random.uniform(-10, 10, 2)
            p2 = np.random.uniform(-10, 10, 2)
            p3 = np.random.uniform(-10, 10, 2)
            verts = [p1, p2, p3]
            if tl.vertex_orientation_2d(verts)[0] < 0:
                verts = [p1, p3, p2]

            # find area of triangle region
            v12 = p2 - p1
            v13 = p3 - p1
            l12 = np.linalg.norm(v12)
            l13 = np.linalg.norm(v13)
            gamma = np.arccos(np.dot(v12, v13) / (l12 * l13))
            height = l13 * np.sin(gamma)
            area = 0.5 * l12 * height

            # perform integral and test it is approximately area * a0
            I = 0.0
            for i, _ in enumerate(verts[:-1]):
                I += mvp.augmented_line_integral(verts[i], verts[i + 1])
            I += mvp.augmented_line_integral(verts[-1], verts[0])

            self.assertAlmostEqual(I, a0 * area)