def test_reference_hexahedron_quadrature(self, verbose=True):
        """

        Args:
            verbose:
        """
        v0 = np.array([0.0, 0.0, 0.0], dtype=real)
        v1 = np.array([1.0, 0.0, 0.0], dtype=real)
        v2 = np.array([1.0, 1.0, 0.0], dtype=real)
        v3 = np.array([0.0, 1.0, 0.0], dtype=real)
        v4 = np.array([0.0, 0.0, 1.0], dtype=real)
        v5 = np.array([1.0, 0.0, 1.0], dtype=real)
        v6 = np.array([1.0, 1.0, 1.0], dtype=real)
        v7 = np.array([0.0, 1.0, 1.0], dtype=real)
        vertices = np.array([v0, v1, v2, v3, v4, v5, v6, v7], dtype=real).T
        shape = Shape(ShapeType.HEXAHEDRON, vertices)
        for _io in range(1, 9):
            # --- DECLARE FUNCTION
            f = lambda x: np.exp(x[0]) * np.sin(x[0] * x[1] / (x[2] + 0.003)
                                                ) + x[1] * x[2] + 3.0
            f_scipy = lambda x, y, z: np.exp(x) * np.sin(x * y / (z + 0.003)
                                                         ) + y * z + 3.0
            # --- GET QUADPY ESTIMATION
            scheme = quadpy.c3.get_good_scheme(_io)
            val = scheme.integrate(
                f, [[[v0, v4], [v3, v7]], [[v1, v5], [v2, v6]]])
            # --- GET H20 ESTIMATION
            val_num = 0.0
            shape_quadrature_points = shape.get_quadrature_points(_io)
            shape_quadrature_weights = shape.get_quadrature_weights(_io)
            shape_quadrature_size = shape.get_quadrature_size(_io)
            for _qc in range(shape_quadrature_size):
                x_qc = shape_quadrature_points[:, _qc]
                w_qc = shape_quadrature_weights[_qc]
                val_num += w_qc * f(x_qc)
            # --- GET SCIPY ESTIMATION
            # val_scp = integrate.tplquad(
            #     f_scipy, 0.0, 1.0, lambda x: 0.0, lambda x: 1.0, lambda x, y: 0.0, lambda x, y: 1.0
            # )
            if verbose:
                print("-- integration order : {}".format(_io))
                print("val_h2O : {}".format(val_num))
                print("val_qud : {}".format(val))
                # print("val_scp : {}".format(val_scp))
                x_c = shape.get_centroid()
                fig = plt.figure()
                ax = fig.add_subplot(111, projection="3d")
                ax.scatter(x_c[0], x_c[1], x_c[2], c="b", marker="o")
                for i in range(vertices.shape[1]):
                    ax.scatter(vertices[0, i],
                               vertices[1, i],
                               vertices[2, i],
                               c="b",
                               marker="o")
                for _qc in range(shape_quadrature_size):
                    _x_qc = shape_quadrature_points[:, _qc]
                    ax.scatter(_x_qc[0], _x_qc[1], _x_qc[2], c="g")
                plt.show()
 def get_element_projection_vector(cell: Shape, faces: List[Shape], function: List[Callable]):
     _d = euclidean_dimension
     _dx = field.field_dimension
     _cl = cell_basis_l.dimension
     _fk = face_basis_k.dimension
     _nf = len(faces)
     _es = _dx * (_cl + _nf * _fk)
     #
     x_c = cell.centroid
     h_c = cell.diameter
     _io = finite_element.construction_integration_order
     cell_quadrature_points = cell.get_quadrature_points(_io)
     cell_quadrature_weights = cell.get_quadrature_weights(_io)
     cell_quadrature_size = cell.get_quadrature_size(_io)
     matrix = np.zeros((_es, _es), dtype=real)
     vector = np.zeros((_es,), dtype=real)
     for _dir in range(_dx):
         m_mas = np.zeros((_cl, _cl), dtype=real)
         vc = np.zeros((_cl,), dtype=real)
         for qc in range(cell_quadrature_size):
             x_q_c = cell_quadrature_points[:, qc]
             w_q_c = cell_quadrature_weights[qc]
             phi_l = cell_basis_l.evaluate_function(x_q_c, x_c, h_c)
             m_mas += w_q_c * np.tensordot(phi_l, phi_l, axes=0)
             vc += w_q_c * phi_l * function[_dir](x_q_c)
         _i = _cl * _dir
         _j = _cl * (_dir + 1)
         matrix[_i:_j, _i:_j] += m_mas
         vector[_i:_j] += vc
     for _f, face in enumerate(faces):
         face_rotation_matrix = get_rotation_matrix(face.type, face.vertices)
         x_f = face.centroid
         h_f = face.diameter
         # --- PROJECT ON HYPERPLANE
         s_f = (face_rotation_matrix @ x_f)[:-1]
         _io = finite_element.construction_integration_order
         face_quadrature_points = face.get_quadrature_points(_io)
         face_quadrature_weights = face.get_quadrature_weights(_io)
         face_quadrature_size = face.get_quadrature_size(_io)
         for _dir in range(_dx):
             m_mas_f = np.zeros((_fk, _fk), dtype=real)
             vf = np.zeros((_fk,), dtype=real)
             for qf in range(face_quadrature_size):
                 x_q_f = face_quadrature_points[:, qf]
                 w_q_f = face_quadrature_weights[qf]
                 # s_f = (face_rotation_matrix @ x_f)[:-1]
                 s_q_f = (face_rotation_matrix @ x_q_f)[:-1]
                 psi_k = face_basis_k.evaluate_function(s_q_f, s_f, h_f)
                 m_mas_f += w_q_f * np.tensordot(psi_k, psi_k, axes=0)
                 vf += w_q_f * psi_k * function[_dir](x_q_f)
             _i = _cl * _dx + _f * _fk * _dx + _dir * _fk
             _j = _cl * _dx + _f * _fk * _dx + (_dir + 1) * _fk
             matrix[_i:_j, _i:_j] += m_mas_f
             vector[_i:_j] += vf
     projection_vector = np.linalg.solve(matrix, vector)
     return projection_vector
    def test_quadrangle_quadrature_cell(self, verbose=True):
        """

        Args:
            verbose:
        """
        v0 = np.array([0.0, 0.0], dtype=real)
        v1 = np.array([1.0, 0.0], dtype=real)
        v2 = np.array([1.0, 1.0], dtype=real)
        v3 = np.array([0.0, 1.0], dtype=real)
        quadrangle_vertices = np.array([v0, v1, v2, v3], dtype=real).T
        cell_triangle = Shape(ShapeType.QUADRANGLE, quadrangle_vertices)
        for _io in range(1, 9):
            # --- DECLARE FUNCTION
            f = lambda x: np.exp(x[0]) * np.sin(x[0] * x[1]) + x[1] + 3.
            f_scipy = lambda x, y: np.exp(x) * np.sin(x * y) + y + 3.
            # --- GET QUADPY ESTIMATION
            scheme = quadpy.c2.get_good_scheme(_io)
            val = scheme.integrate(
                f,
                [[v0, v1], [v3, v2]],
            )
            # --- GET H20 ESTIMATION
            val_num = 0.0
            triangle_quadrature_points = cell_triangle.get_quadrature_points(
                _io)
            triangle_quadrature_weights = cell_triangle.get_quadrature_weights(
                _io)
            triangle_quadrature_size = cell_triangle.get_quadrature_size(_io)
            for _qc in range(triangle_quadrature_size):
                x_qc = triangle_quadrature_points[:, _qc]
                w_qc = triangle_quadrature_weights[_qc]
                val_num += w_qc * f(x_qc)
            # --- GET SCIPY ESTIMATION
            val_scp = integrate.dblquad(f_scipy, 0.0, 1.0, lambda x: 0.0,
                                        lambda x: 1.0)
            if verbose:
                print("-- integration order : {}".format(_io))
                print("val_h2O : {}".format(val_num))
                print("val_qud : {}".format(val))
                print("val_scp : {}".format(val_scp))
                x_c = cell_triangle.get_centroid()
                plt.scatter(x_c[0], x_c[1], c="b")
                for i in range(4):
                    plt.scatter(quadrangle_vertices[0, i],
                                quadrangle_vertices[1, i],
                                c="b")
                for _qc in range(triangle_quadrature_size):
                    _x_qc = triangle_quadrature_points[:, _qc]
                    plt.scatter(_x_qc[0], _x_qc[1], c="g")
                plt.show()
    def test_reference_triangle_quadrature(self, verbose=True):
        """

        Args:
            verbose:
        """
        # v0 = np.array([0.00000000000000E+00, 0.28725932709342E-01], dtype=real)
        # v1 = np.array([0.00000000000000E+00, 0.30000000000000E-01], dtype=real)
        # v2 = np.array([0.20769230769231E-03, 0.30000000000000E-01], dtype=real)
        v0 = np.array([+.30000000000000E-02, +.00000000000000E+00], dtype=real)
        v1 = np.array([+.30038156151383E-02, +.21394584067090E-03], dtype=real)
        v2 = np.array([+.28882842453253E-02, +.21394584067090E-03], dtype=real)
        vertices = np.array([v0, v1, v2], dtype=real).T
        shape = Shape(ShapeType.TRIANGLE, vertices)
        for _io in range(1, 9):
            # --- DECLARE FUNCTION
            f = lambda x: np.exp(x[0]) * np.sin(x[0] * x[1]) + x[1] + 3.
            # --- GET QUADPY ESTIMATION
            scheme = quadpy.t2.get_good_scheme(_io)
            val = scheme.integrate(
                f,
                [v0, v1, v2],
            )
            # --- GET H20 ESTIMATION
            val_num = 0.0
            shape_quadrature_points = shape.get_quadrature_points(_io)
            shape_quadrature_weights = shape.get_quadrature_weights(_io)
            shape_quadrature_size = shape.get_quadrature_size(_io)
            print("-- QUAD_WGTS")
            print(shape_quadrature_weights)
            for _qc in range(shape_quadrature_size):
                x_qc = shape_quadrature_points[:, _qc]
                w_qc = shape_quadrature_weights[_qc]
                val_num += w_qc * f(x_qc)
            # --- GET SCIPY ESTIMATION
            if verbose:
                print("-- integration order : {}".format(_io))
                print("val_h2O : {}".format(val_num))
                print("val_qud : {}".format(val))
                x_c = shape.get_centroid()
                plt.scatter(v0[0], v0[1], c="b")
                plt.scatter(v1[0], v1[1], c="b")
                plt.scatter(v2[0], v2[1], c="b")
                plt.scatter(x_c[0], x_c[1], c="b")
                for _qc in range(shape_quadrature_size):
                    _x_qc = shape_quadrature_points[:, _qc]
                    plt.scatter(_x_qc[0], _x_qc[1], c="g")
                plt.show()
示例#5
0
    def test_reference_triangle_quadrature(self, verbose=True):
        """

        Args:
            verbose:
        """
        v0 = np.array([0.0, 0.0], dtype=real)
        v1 = np.array([1.0, 0.0], dtype=real)
        v2 = np.array([0.0, 1.0], dtype=real)
        vertices = np.array([v0, v1, v2], dtype=real).T
        shape = Shape(ShapeType.TRIANGLE, vertices)
        for _io in range(1, 9):
            # --- DECLARE FUNCTION
            f = lambda x: np.exp(x[0]) * np.sin(x[0] * x[1]) + x[1] + 3.
            f_scipy = lambda x, y: np.exp(x) * np.sin(x * y) + y + 3.
            # --- GET QUADPY ESTIMATION
            scheme = quadpy.t2.get_good_scheme(_io)
            val = scheme.integrate(
                f,
                [v0, v1, v2],
            )
            # --- GET H20 ESTIMATION
            val_num = 0.0
            shape_quadrature_points = shape.get_quadrature_points(_io)
            shape_quadrature_weights = shape.get_quadrature_weights(_io)
            shape_quadrature_size = shape.get_quadrature_size(_io)
            for _qc in range(shape_quadrature_size):
                x_qc = shape_quadrature_points[:, _qc]
                w_qc = shape_quadrature_weights[_qc]
                val_num += w_qc * f(x_qc)
            # --- GET SCIPY ESTIMATION
            val_scp = integrate.dblquad(f_scipy, 0.0, 1.0, lambda x: 0.0,
                                        lambda x: 1.0 - x)
            if verbose:
                print("-- integration order : {}".format(_io))
                print("val_h2O : {}".format(val_num))
                print("val_qud : {}".format(val))
                print("val_scp : {}".format(val_scp))
                x_c = shape.get_centroid()
                plt.scatter(v0[0], v0[1], c="b")
                plt.scatter(v1[0], v1[1], c="b")
                plt.scatter(v2[0], v2[1], c="b")
                plt.scatter(x_c[0], x_c[1], c="b")
                for _qc in range(shape_quadrature_size):
                    _x_qc = shape_quadrature_points[:, _qc]
                    plt.scatter(_x_qc[0], _x_qc[1], c="g")
                plt.show()
示例#6
0
    def test_reference_segment_quadrature_face(self, verbose=True):
        """

        Args:
            verbose:
        """
        v0 = np.array([0.0, 0.0], dtype=real)
        v1 = np.array([1.0, 0.7], dtype=real)
        vertices = np.array([v0, v1], dtype=real).T
        shape = Shape(ShapeType.SEGMENT, vertices)
        for _io in range(1, 9):
            # --- DECLARE FUNCTION
            f = lambda x: np.exp(x[0]) * np.sin(x[0]) + 3.0
            f_quadpy = lambda x: np.exp(np.array(x)) * np.sin(np.array(x)) + 3.0
            f_scipy = lambda x: np.exp(x) * np.sin(x) + 3.0
            # --- GET H20 ESTIMATION
            val_num = 0.0
            shape_quadrature_points = shape.get_quadrature_points(_io)
            shape_quadrature_weights = shape.get_quadrature_weights(_io)
            shape_quadrature_size = shape.get_quadrature_size(_io)
            for _qc in range(shape_quadrature_size):
                x_qc = shape_quadrature_points[:, _qc]
                w_qc = shape_quadrature_weights[_qc]
                s_qc = (shape.get_rotation_matrix() @ x_qc)[:-1]
                val_num += w_qc * f(s_qc)
            vertices_p = (shape.get_rotation_matrix() @ vertices)[:-1]
            # --- GET QUADPY ESTIMATION
            scheme = quadpy.c1.gauss_legendre(_io)
            val = scheme.integrate(f_quadpy, [vertices_p[0, 0], vertices_p[0, 1]])
            # --- GET SCIPY ESTIMATION
            val_scp = integrate.quad(f_scipy, vertices_p[0, 0], vertices_p[0, 1])
            if verbose:
                print("-- integration order : {}".format(_io))
                print("val_h2O : {}".format(val_num))
                print("val_qud : {}".format(val))
                print("val_scp : {}".format(val_scp))
                x_c = shape.get_centroid()
                plt.scatter(x_c[0], x_c[1], c="b")
                for i in range(2):
                    plt.scatter(vertices[0, i], vertices[1, i], c="b")
                for _qc in range(shape_quadrature_size):
                    _x_qc = shape_quadrature_points[:, _qc]
                    plt.scatter(_x_qc[0], _x_qc[1], c="g")
                plt.show()
 def get_gradient_projection_vector(cell: Shape, function: Callable):
     _d = euclidean_dimension
     _dx = field.field_dimension
     _ck = cell_basis_k.dimension
     #
     x_c = cell.centroid
     h_c = cell.diameter
     _io = finite_element.construction_integration_order
     cell_quadrature_points = cell.get_quadrature_points(_io)
     cell_quadrature_weights = cell.get_quadrature_weights(_io)
     cell_quadrature_size = cell.get_quadrature_size(_io)
     matrix = np.zeros((_ck, _ck), dtype=real)
     vector = np.zeros((_ck,), dtype=real)
     for qc in range(cell_quadrature_size):
         x_q_c = cell_quadrature_points[:, qc]
         w_q_c = cell_quadrature_weights[qc]
         phi_k = cell_basis_k.evaluate_function(x_q_c, x_c, h_c)
         matrix += w_q_c * np.tensordot(phi_k, phi_k, axes=0)
         vector += w_q_c * phi_k * function(x_q_c)
     projection_vector = np.linalg.solve(matrix, vector)
     return projection_vector
示例#8
0
    def test_reference_triangle_face(self, verbose=True):
        """

        Args:
            verbose:

        Returns:

        """
        euclidean_dimension = 2
        polynomial_orders = [1, 2, 3]
        element_types = [ElementType.HDG_LOW, ElementType.HDG_EQUAL, ElementType.HDG_HIGH]
        for polynomial_order in polynomial_orders:
            for element_type in element_types:
                # --- DEFINE POLYNOMIAL ORDER AND INTEGRATION ORDER
                finite_element = FiniteElement(
                    element_type=element_type,
                    polynomial_order=polynomial_order,
                    euclidean_dimension=euclidean_dimension,
                )

                # --- DEFINE POLYNOMIAL BASIS
                cell_basis_k = finite_element.cell_basis_k
                cell_basis_l = finite_element.cell_basis_l

                # --- DEFINE RANDOM POLYNOMIAL COEFFICIENTS
                range_min = -3.0
                range_max = +3.0
                coefficients_k = np.array([uniform(range_min, range_max) for _i in range(cell_basis_k.dimension)])
                coefficients_l = np.array([uniform(range_min, range_max) for _i in range(cell_basis_l.dimension)])
                if verbose:
                    print("COEFS_K : \n{}".format(coefficients_k))
                    print("COEFS_L : \n{}".format(coefficients_l))

                # --- DEFINE MONOMIAL VALUES COMPUTATION
                def test_function(
                    polynomial_ord: int, point: ndarray, centroid: ndarray, diameter: float, coefficients: ndarray
                ) -> float:
                    basis = Monomial(polynomial_ord, euclidean_dimension)
                    value = 0.0
                    for _i, _exponent in enumerate(basis.exponents):
                        prod = 1.0
                        for _x_dir in range(basis.exponents.shape[1]):
                            prod *= ((point[_x_dir] - centroid[_x_dir]) / diameter) ** _exponent[_x_dir]
                        prod *= coefficients[_i]
                        value += prod
                    return value

                def test_function_derivative(
                    polynomial_ord: int,
                    point: ndarray,
                    centroid: ndarray,
                    diameter: float,
                    direction: int,
                    coefficients: ndarray,
                ) -> float:
                    basis = Monomial(polynomial_ord, euclidean_dimension)
                    value = 0.0
                    for _i, _exponent in enumerate(basis.exponents):
                        prod = 1.0
                        for _x_dir in range(basis.exponents.shape[1]):
                            if _x_dir == direction:
                                _pt0 = point[_x_dir] - centroid[_x_dir]
                                _pt1 = _pt0 / diameter
                                if _exponent[_x_dir] == 0:
                                    _exp = _exponent[_x_dir]
                                else:
                                    _exp = _exponent[_x_dir] - 1
                                _pt2 = _pt1 ** _exp
                                # prod *= (_exponent[_x_dir] / diameter) * (
                                #         ((point[_x_dir] - centroid[_x_dir]) / diameter) ** (_exponent[_x_dir] - 1)
                                # )
                                prod *= (_exponent[_x_dir] / diameter) * _pt2
                            else:
                                prod *= ((point[_x_dir] - centroid[_x_dir]) / diameter) ** _exponent[_x_dir]
                        prod *= coefficients[_i]
                        value += prod
                    return value

                # --- DEFINE TRIANGLE COORDINATES
                v0 = np.array([0.0, 0.0], dtype=real)
                v1 = np.array([1.0, 0.0], dtype=real)
                v2 = np.array([0.0, 1.0], dtype=real)
                triangle_vertices = np.array([v0, v1, v2], dtype=real).T

                # --- BUILD CELL
                cell_triangle = Shape(ShapeType.TRIANGLE, triangle_vertices)
                x_c = cell_triangle.get_centroid()
                h_c = cell_triangle.get_diameter()
                _io = finite_element.construction_integration_order
                cell_quadrature_points = cell_triangle.get_quadrature_points(_io)
                cell_quadrature_weights = cell_triangle.get_quadrature_weights(_io)
                cell_quadrature_size = cell_triangle.get_quadrature_size(_io)

                # --- CHECK INTEGRATION IN CELL
                bases = [cell_basis_k, cell_basis_l]
                # orders = [face_polynomial_order, cell_polynomial_order]
                coefs = [coefficients_k, coefficients_l]
                # scheme = quadpy.t2.get_good_scheme(2 * finite_element.construction_integration_order)
                scheme = quadpy.t2.get_good_scheme(finite_element.construction_integration_order)
                for basis_0, coef_0 in zip(bases, coefs):
                    order_0 = basis_0.polynomial_order
                    for basis_1, coef_1 in zip(bases, coefs):
                        order_1 = basis_1.polynomial_order
                        for _i in range(euclidean_dimension):
                            for _j in range(euclidean_dimension):
                                mass_mat = np.zeros((basis_0.dimension, basis_1.dimension), dtype=real)
                                stif_mat = np.zeros((basis_0.dimension, basis_1.dimension), dtype=real)
                                advc_mat = np.zeros((basis_0.dimension, basis_1.dimension), dtype=real)
                                for _qc in range(cell_quadrature_size):
                                    _x_qc = cell_quadrature_points[:, _qc]
                                    _w_qc = cell_quadrature_weights[_qc]
                                    phi_0 = basis_0.evaluate_function(_x_qc, x_c, h_c)
                                    phi_1 = basis_1.evaluate_function(_x_qc, x_c, h_c)
                                    d_phi_0_i = basis_0.evaluate_derivative(_x_qc, x_c, h_c, _i)
                                    d_phi_1_j = basis_1.evaluate_derivative(_x_qc, x_c, h_c, _j)
                                    mass_mat += _w_qc * np.tensordot(phi_0, phi_1, axes=0)
                                    stif_mat += _w_qc * np.tensordot(d_phi_0_i, d_phi_1_j, axes=0)
                                    advc_mat += _w_qc * np.tensordot(phi_0, d_phi_1_j, axes=0)
                                mass_integral = coef_0 @ mass_mat @ coef_1
                                stif_integral = coef_0 @ stif_mat @ coef_1
                                advc_integral = coef_0 @ advc_mat @ coef_1
                                f_mass_check = lambda x: test_function(order_0, x, x_c, h_c, coef_0) * test_function(
                                    order_1, x, x_c, h_c, coef_1
                                )
                                f_stif_check = lambda x: test_function_derivative(
                                    order_0, x, x_c, h_c, _i, coef_0
                                ) * test_function_derivative(order_1, x, x_c, h_c, _j, coef_1)
                                f_advc_check = lambda x: test_function(
                                    order_0, x, x_c, h_c, coef_0
                                ) * test_function_derivative(order_1, x, x_c, h_c, _j, coef_1)
                                mass_integral_check = scheme.integrate(f_mass_check, triangle_vertices.T)
                                stif_integral_check = scheme.integrate(f_stif_check, triangle_vertices.T)
                                advc_integral_check = scheme.integrate(f_advc_check, triangle_vertices.T)
                                rtol = 1.0e-15
                                atol = 1.0e-15
                                if verbose:
                                    print(
                                        "MASS INTEGRAL CHECK | ORDER : {} | ELEM : {}".format(
                                            polynomial_order, element_type
                                        )
                                    )
                                    print("- QUADPY : {}".format(mass_integral_check))
                                    print("- H2O : {}".format(mass_integral))
                                    print(
                                        "STIFFNESS INTEGRAL CHECK | ORDER : {} | ELEM : {}".format(
                                            polynomial_order, element_type
                                        )
                                    )
                                    print("- QUADPY : {}".format(stif_integral_check))
                                    print("- H2O : {}".format(stif_integral))
                                    print(
                                        "ADVECTION INTEGRAL CHECK | ORDER : {} | ELEM : {}".format(
                                            polynomial_order, element_type
                                        )
                                    )
                                    print("- QUADPY : {}".format(advc_integral_check))
                                    print("- H2O : {}".format(advc_integral))
                                np.testing.assert_allclose(mass_integral_check, mass_integral, rtol=rtol, atol=atol)
                                np.testing.assert_allclose(stif_integral_check, stif_integral, rtol=rtol, atol=atol)
                                np.testing.assert_allclose(advc_integral_check, advc_integral, rtol=rtol, atol=atol)
示例#9
0
def get_regular_gradient_component_matrix(field: Field,
                                          finite_element: FiniteElement,
                                          cell: Shape, faces: List[Shape],
                                          _i: int, _j: int) -> ndarray:
    _d = field.euclidean_dimension
    _dx = field.field_dimension
    _cl = finite_element.cell_basis_l.dimension
    _ck = finite_element.cell_basis_k.dimension
    _fk = finite_element.face_basis_k.dimension
    _nf = len(faces)
    _es = _dx * (_cl + _nf * _fk)
    _io = finite_element.construction_integration_order
    # --- CELL ENVIRONMENT
    _c_is = cell.get_quadrature_size(_io)
    cell_quadrature_points = cell.get_quadrature_points(_io)
    cell_quadrature_weights = cell.get_quadrature_weights(_io)
    x_c = cell.get_centroid()
    h_c = cell.get_diameter()
    local_grad_matric = np.zeros((_ck, _es), dtype=real)
    m_mas = np.zeros((_ck, _ck), dtype=real)
    m_adv_j = np.zeros((_ck, _cl), dtype=real)
    for qc in range(_c_is):
        x_q_c = cell_quadrature_points[:, qc]
        w_q_c = cell_quadrature_weights[qc]
        phi_k = finite_element.cell_basis_k.evaluate_function(x_q_c, x_c, h_c)
        d_phi_l_j = finite_element.cell_basis_l.evaluate_derivative(
            x_q_c, x_c, h_c, _j)
        m_adv_j += w_q_c * np.tensordot(phi_k, d_phi_l_j, axes=0)
        m_mas += w_q_c * np.tensordot(phi_k, phi_k, axes=0)
    m_mas_inv = np.linalg.inv(m_mas)
    _c0 = _i * _cl
    _c1 = (_i + 1) * _cl
    local_grad_matric[:, _c0:_c1] += m_adv_j
    for _f, face in enumerate(faces):
        # --- FACE ENVIRONMENT
        _f_is = face.get_quadrature_size(_io)
        face_quadrature_points = face.get_quadrature_points(_io)
        face_quadrature_weights = face.get_quadrature_weights(_io)
        h_f = face.get_diameter()
        x_f = face.get_centroid()
        # face_rotation_matrix = get_rotation_matrix(face.type, face.vertices)
        face_rotation_matrix = face.get_rotation_matrix()
        dist_in_face = (face_rotation_matrix @ (x_f - x_c))[-1]
        if dist_in_face > 0:
            normal_vector_component_j = face_rotation_matrix[-1, _j]
        else:
            normal_vector_component_j = -face_rotation_matrix[-1, _j]
        m_mas_f = np.zeros((_ck, _cl), dtype=real)
        m_hyb_f = np.zeros((_ck, _fk), dtype=real)
        for qf in range(_f_is):
            x_q_f = face_quadrature_points[:, qf]
            # x_q_f_prime = face.mapping_matrix @ face.quadrature_points[:, qf]
            w_q_f = face_quadrature_weights[qf]
            s_f = (face_rotation_matrix @ x_f)[:-1]
            s_q_f = (face_rotation_matrix @ x_q_f)[:-1]
            phi_k = finite_element.cell_basis_k.evaluate_function(
                x_q_f, x_c, h_c)
            phi_l = finite_element.cell_basis_l.evaluate_function(
                x_q_f, x_c, h_c)
            # phi_k = cell_basis_k.get_phi_vector(x_q_f_prime, x_c, h_c)
            # phi_l = cell_basis_l.get_phi_vector(x_q_f_prime, x_c, h_c)
            psi_k = finite_element.face_basis_k.evaluate_function(
                s_q_f, s_f, h_f)
            m_mas_f += w_q_f * np.tensordot(phi_k, phi_l, axes=0)
            m_hyb_f += w_q_f * np.tensordot(phi_k, psi_k, axes=0)
        _c0 = _i * _cl
        _c1 = (_i + 1) * _cl
        local_grad_matric[:, _c0:_c1] -= m_mas_f * normal_vector_component_j
        _c0 = _dx * _cl + _f * _dx * _fk + _i * _fk
        _c1 = _dx * _cl + _f * _dx * _fk + (_i + 1) * _fk
        local_grad_matric[:, _c0:_c1] += m_hyb_f * normal_vector_component_j
    local_grad_matric2 = m_mas_inv @ local_grad_matric
    return local_grad_matric2
    def test_reference_polyhedron_quadrature(self, verbose=True):
        """

          V8  o_______________o V7
             /|     V6       /|
            / |     o       / |
        V4 o_______________o V5
           |  |            |  |
        V3 |  o___________ |__o V2              Z
           | /             | /                  ^ Y
           |/              |/                   |/
        V0 o_______________o V1                 0---> X

        Args:
            verbose:
        """
        v0 = np.array([0.0, 0.0, 0.0], dtype=real)
        v1 = np.array([1.0, 0.0, 0.0], dtype=real)
        v2 = np.array([1.0, 1.0, 0.0], dtype=real)
        v3 = np.array([0.0, 1.0, 0.0], dtype=real)
        v4 = np.array([0.0, 0.0, 1.0], dtype=real)
        v5 = np.array([1.0, 0.0, 1.0], dtype=real)
        v6 = np.array([0.5, 0.5, 1.0], dtype=real)
        v7 = np.array([1.0, 1.0, 1.0], dtype=real)
        v8 = np.array([0.0, 1.0, 1.0], dtype=real)
        vertices = np.array([v0, v1, v2, v3, v4, v5, v6, v7, v8], dtype=real).T
        # --- CONNECTIVITY, COUNTER CLOCK WISE
        # connectivity = [
        #     [0, 3, 2, 1],
        #     [0, 1, 5, 4],
        #     [1, 2, 7, 5],
        #     [2, 3, 8, 7],
        #     [3, 0, 4, 8],
        #     [4, 5, 6],
        #     [5, 7, 6],
        #     [7, 8, 6],
        #     [8, 4, 6],
        # ]
        # --- CONNECTIVIY, CLOCK WISE
        connectivity = [
            [0, 1, 2, 3],
            [0, 4, 5, 1],
            [1, 5, 7, 2],
            [2, 7, 8, 3],
            [3, 8, 4, 0],
            [6, 5, 4],
            [6, 7, 5],
            [6, 8, 7],
            [6, 4, 8],
        ]
        shape = Shape(ShapeType.POLYHEDRON,
                      vertices,
                      connectivity=connectivity)
        for _io in range(1, 9):
            # --- DECLARE FUNCTION
            f = lambda x: np.exp(x[0]) * np.sin(x[0] * x[1] / (x[2] + 0.003)
                                                ) + x[1] * x[2] + 3.0
            f_scipy = lambda x, y, z: np.exp(x) * np.sin(x * y / (z + 0.003)
                                                         ) + y * z + 3.0
            # --- GET QUADPY ESTIMATION
            scheme = quadpy.c3.get_good_scheme(_io)
            val = scheme.integrate(
                f, [[[v0, v4], [v3, v8]], [[v1, v5], [v2, v7]]])
            # --- GET H20 ESTIMATION
            val_num = 0.0
            shape_quadrature_points = shape.get_quadrature_points(_io)
            shape_quadrature_weights = shape.get_quadrature_weights(_io)
            shape_quadrature_size = shape.get_quadrature_size(_io)
            for _qc in range(shape_quadrature_size):
                x_qc = shape_quadrature_points[:, _qc]
                w_qc = shape_quadrature_weights[_qc]
                val_num += w_qc * f(x_qc)
            # --- GET SCIPY ESTIMATION
            # val_scp = integrate.tplquad(
            #     f_scipy, 0.0, 1.0, lambda x: 0.0, lambda x: 1.0, lambda x, y: 0.0, lambda x, y: 1.0
            # )
            if verbose:
                print("-- integration order : {}".format(_io))
                print("val_h2O : {}".format(val_num))
                print("val_qud : {}".format(val))
                # print("val_scp : {}".format(val_scp))
                x_c = shape.get_centroid()
                fig = plt.figure()
                ax = fig.add_subplot(111, projection="3d")
                ax.scatter(x_c[0], x_c[1], x_c[2], c="b", marker="o")
                for i in range(vertices.shape[1]):
                    ax.scatter(vertices[0, i],
                               vertices[1, i],
                               vertices[2, i],
                               c="b",
                               marker="o")
                for _qc in range(shape_quadrature_size):
                    _x_qc = shape_quadrature_points[:, _qc]
                    ax.scatter(_x_qc[0], _x_qc[1], _x_qc[2], c="g")
                plt.show()
    def test_reference_polyhedron_cell(self, verbose=True):
        """

             V3 o________________o V2
               /|               /|
              / |              / |
             /  |             /  |                Y
            /   |            /   |                ^
        V7 o________________o V6 |                |
           |    |           |    |                0---> X
           | V0 o___________|____o V1            /
           |   /            |   /                Z
           |  /             |  /
           | /              | /
           |/               |/
        V4 o________________o V5


             V3 o________________o V2
               /|               /|
              / |              / |
             /  |             /  |                Y
            /   |            /   |                ^
        V8 o________________o V7 |                |
           |    |           |    |                0---> X
           | V0 o___________|____o V1            /
           |   /            |   /                Z
           |  /    o V6     |  /
           | /              | /
           |/               |/
        V4 o________________o V5


            V2 o
               |\..
               |   \..
               |      \..
               |         \..
               |            \..
               |               \
               o_V0_____________o V1
          |   /           ..../
             /       ..../
          / /   ..../
          :/.../
        V2 o


        Args:
            verbose:

        Returns:

        """
        euclidean_dimension = 3
        polynomial_orders = [1, 2, 3]
        element_types = [
            ElementType.HDG_LOW, ElementType.HDG_EQUAL, ElementType.HDG_HIGH
        ]
        for polynomial_order in polynomial_orders:
            for element_type in element_types:
                # --- DEFINE POLYNOMIAL ORDER AND INTEGRATION ORDER
                finite_element = FiniteElement(
                    element_type=element_type,
                    polynomial_order=polynomial_order,
                    euclidean_dimension=euclidean_dimension,
                )

                # --- DEFINE POLYNOMIAL BASIS
                cell_basis_k = finite_element.cell_basis_k
                cell_basis_l = finite_element.cell_basis_l

                # --- DEFINE RANDOM POLYNOMIAL COEFFICIENTS
                range_min = -3.0
                range_max = +3.0
                coefficients_k = np.array([
                    uniform(range_min, range_max)
                    for _i in range(cell_basis_k.dimension)
                ])
                coefficients_l = np.array([
                    uniform(range_min, range_max)
                    for _i in range(cell_basis_l.dimension)
                ])
                if verbose:
                    print("COEFS_K : \n{}".format(coefficients_k))
                    print("COEFS_L : \n{}".format(coefficients_l))

                # --- DEFINE MONOMIAL VALUES COMPUTATION
                def test_function(polynomial_ord: int, point: ndarray,
                                  centroid: ndarray, diameter: float,
                                  coefficients: ndarray) -> float:
                    basis = Monomial(polynomial_ord, euclidean_dimension)
                    value = 0.0
                    for _i, _exponent in enumerate(basis.exponents):
                        prod = 1.0
                        for _x_dir in range(basis.exponents.shape[1]):
                            prod *= ((point[_x_dir] - centroid[_x_dir]) /
                                     diameter)**_exponent[_x_dir]
                        prod *= coefficients[_i]
                        value += prod
                    return value

                def test_function_derivative(
                    polynomial_ord: int,
                    point: ndarray,
                    centroid: ndarray,
                    diameter: float,
                    direction: int,
                    coefficients: ndarray,
                ) -> float:
                    basis = Monomial(polynomial_ord, euclidean_dimension)
                    value = 0.0
                    for _i, _exponent in enumerate(basis.exponents):
                        prod = 1.0
                        for _x_dir in range(basis.exponents.shape[1]):
                            if _x_dir == direction:
                                # _pt0 = point[_x_dir] - centroid[_x_dir]
                                # _pt1 = _pt0 / diameter
                                # if _exponent[_x_dir] == 0:
                                #     _exp = _exponent[_x_dir]
                                # else:
                                #     _exp = _exponent[_x_dir] - 1
                                # _pt2 = _pt1 ** _exp
                                if _exponent[_x_dir] != 0:
                                    prod *= (_exponent[_x_dir] / diameter) * (
                                        ((point[_x_dir] - centroid[_x_dir]) /
                                         diameter)**(_exponent[_x_dir] - 1))
                                else:
                                    prod *= 0.0
                                # prod *= (_exponent[_x_dir] / diameter) * _pt2
                            else:
                                prod *= ((point[_x_dir] - centroid[_x_dir]) /
                                         diameter)**_exponent[_x_dir]
                        prod *= coefficients[_i]
                        value += prod
                    return value

                # --- DEFINE TRIANGLE COORDINATES
                v0 = np.array([0.0, 0.0, 0.0], dtype=real)
                v1 = np.array([1.0, 0.0, 0.0], dtype=real)
                v2 = np.array([1.0, 1.0, 0.0], dtype=real)
                v3 = np.array([0.0, 1.0, 0.0], dtype=real)
                v4 = np.array([0.0, 0.0, 1.0], dtype=real)
                v5 = np.array([1.0, 0.0, 1.0], dtype=real)
                v6 = np.array([0.5, 0.5, 1.0], dtype=real)
                v7 = np.array([1.0, 1.0, 1.0], dtype=real)
                v8 = np.array([0.0, 1.0, 1.0], dtype=real)
                vertices = np.array([v0, v1, v2, v3, v4, v5, v6, v7, v8],
                                    dtype=real).T
                # --- CONNECTIVITY, COUNTER CLOCK WISE
                # connectivity = [
                #     [0, 3, 2, 1],
                #     [0, 1, 5, 4],
                #     [1, 2, 7, 5],
                #     [2, 3, 8, 7],
                #     [3, 0, 4, 8],
                #     [4, 5, 6],
                #     [5, 7, 6],
                #     [7, 8, 6],
                #     [8, 4, 6],
                # ]
                # --- CONNECTIVIY, CLOCK WISE
                connectivity = [
                    [0, 1, 2, 3],
                    [0, 4, 5, 1],
                    [1, 5, 7, 2],
                    [2, 7, 8, 3],
                    [3, 8, 4, 0],
                    [6, 5, 4],
                    [6, 7, 5],
                    [6, 8, 7],
                    [6, 4, 8],
                ]
                # --- BUILD CELL
                shape = Shape(ShapeType.POLYHEDRON,
                              vertices,
                              connectivity=connectivity)
                x_c = shape.get_centroid()
                h_c = shape.get_diameter()
                _io = finite_element.construction_integration_order
                cell_quadrature_points = shape.get_quadrature_points(_io)
                cell_quadrature_weights = shape.get_quadrature_weights(_io)
                cell_quadrature_size = shape.get_quadrature_size(_io)

                # --- CHECK INTEGRATION IN CELL
                bases = [cell_basis_k, cell_basis_l]
                # orders = [face_polynomial_order, cell_polynomial_order]
                coefs = [coefficients_k, coefficients_l]
                # scheme = quadpy.t2.get_good_scheme(2 * finite_element.construction_integration_order)
                scheme = quadpy.c3.get_good_scheme(
                    finite_element.construction_integration_order)
                for basis_0, coef_0 in zip(bases, coefs):
                    order_0 = basis_0.polynomial_order
                    for basis_1, coef_1 in zip(bases, coefs):
                        order_1 = basis_1.polynomial_order
                        for _i in range(euclidean_dimension):
                            for _j in range(euclidean_dimension):
                                mass_mat = np.zeros(
                                    (basis_0.dimension, basis_1.dimension),
                                    dtype=real)
                                stif_mat = np.zeros(
                                    (basis_0.dimension, basis_1.dimension),
                                    dtype=real)
                                advc_mat = np.zeros(
                                    (basis_0.dimension, basis_1.dimension),
                                    dtype=real)
                                for _qc in range(cell_quadrature_size):
                                    _x_qc = cell_quadrature_points[:, _qc]
                                    _w_qc = cell_quadrature_weights[_qc]
                                    phi_0 = basis_0.evaluate_function(
                                        _x_qc, x_c, h_c)
                                    phi_1 = basis_1.evaluate_function(
                                        _x_qc, x_c, h_c)
                                    d_phi_0_i = basis_0.evaluate_derivative(
                                        _x_qc, x_c, h_c, _i)
                                    d_phi_1_j = basis_1.evaluate_derivative(
                                        _x_qc, x_c, h_c, _j)
                                    mass_mat += _w_qc * np.tensordot(
                                        phi_0, phi_1, axes=0)
                                    stif_mat += _w_qc * np.tensordot(
                                        d_phi_0_i, d_phi_1_j, axes=0)
                                    advc_mat += _w_qc * np.tensordot(
                                        phi_0, d_phi_1_j, axes=0)
                                mass_integral = coef_0 @ mass_mat @ coef_1
                                stif_integral = coef_0 @ stif_mat @ coef_1
                                advc_integral = coef_0 @ advc_mat @ coef_1
                                f_mass_check = lambda x: test_function(
                                    order_0, x, x_c, h_c, coef_0
                                ) * test_function(order_1, x, x_c, h_c, coef_1)
                                f_stif_check = lambda x: test_function_derivative(
                                    order_0, x, x_c, h_c, _i, coef_0
                                ) * test_function_derivative(
                                    order_1, x, x_c, h_c, _j, coef_1)
                                f_advc_check = lambda x: test_function(
                                    order_0, x, x_c, h_c, coef_0
                                ) * test_function_derivative(
                                    order_1, x, x_c, h_c, _j, coef_1)
                                mass_integral_check = scheme.integrate(
                                    f_mass_check, [[[v0, v4], [v3, v8]],
                                                   [[v1, v5], [v2, v7]]])
                                stif_integral_check = scheme.integrate(
                                    f_stif_check, [[[v0, v4], [v3, v8]],
                                                   [[v1, v5], [v2, v7]]])
                                advc_integral_check = scheme.integrate(
                                    f_advc_check, [[[v0, v4], [v3, v8]],
                                                   [[v1, v5], [v2, v7]]])
                                rtol = 1.0e-12
                                atol = 1.0e-12
                                if verbose:
                                    print(
                                        "MASS INTEGRAL CHECK | ORDER : {} | ELEM : {} | dir {}, {}, | order {}, {}"
                                        .format(polynomial_order, element_type,
                                                _i, _j, order_0, order_1))
                                    print("- QUADPY : {}".format(
                                        mass_integral_check))
                                    print("- H2O : {}".format(mass_integral))
                                    print(
                                        "STIFFNESS INTEGRAL CHECK | ORDER : {} | ELEM : {} | dir {}, {} | order {}, {}"
                                        .format(polynomial_order, element_type,
                                                _i, _j, order_0, order_1))
                                    print("- QUADPY : {}".format(
                                        stif_integral_check))
                                    print("- H2O : {}".format(stif_integral))
                                    print(
                                        "ADVECTION INTEGRAL CHECK | ORDER : {} | ELEM : {} | dir {}, {} | order {}, {}"
                                        .format(polynomial_order, element_type,
                                                _i, _j, order_0, order_1))
                                    print("- QUADPY : {}".format(
                                        advc_integral_check))
                                    print("- H2O : {}".format(advc_integral))
                                np.testing.assert_allclose(mass_integral_check,
                                                           mass_integral,
                                                           rtol=rtol,
                                                           atol=atol)
                                np.testing.assert_allclose(stif_integral_check,
                                                           stif_integral,
                                                           rtol=rtol,
                                                           atol=atol)
                                np.testing.assert_allclose(advc_integral_check,
                                                           advc_integral,
                                                           rtol=rtol,
                                                           atol=atol)