def test_quadrangle_geometry_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_quadrangle = Shape(ShapeType.QUADRANGLE, quadrangle_vertices)
        x_c = cell_quadrangle.get_centroid()
        h_c = cell_quadrangle.get_diameter()
        v_c = cell_quadrangle.get_volume()
        if verbose:
            print("-- centroid :\n{}".format(x_c))
            print("-- diameter :\n{}".format(h_c))
            print("-- volume :\n{}".format(v_c))
            for i in range(4):
                plt.scatter(quadrangle_vertices[0, i],
                            quadrangle_vertices[1, i],
                            c="b")
            plt.scatter(x_c[0], x_c[1], c="b")
            plt.show()
Example #2
0
    def test_reference_tetrahedron_geometry_cell(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([0.0, 1.0, 0.0], dtype=real)
        v3 = np.array([0.0, 0.0, 1.0], dtype=real)
        vertices = np.array([v0, v1, v2, v3], dtype=real).T
        shape = Shape(ShapeType.TETRAHEDRON, vertices)
        x_c = shape.get_centroid()
        h_c = shape.get_diameter()
        v_c = shape.get_volume()
        if verbose:
            print("-- centroid :\n{}".format(x_c))
            print("-- diameter :\n{}".format(h_c))
            print("-- volume :\n{}".format(v_c))
            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")
            plt.show()
Example #3
0
    def test_polygon_geometry_cell(self, verbose=True):
        """

        Args:
            verbose:
        """
        v0 = np.array([0.0, 0.0], dtype=real)
        v1 = np.array([1.0, 0.0], dtype=real)
        v1p = np.array([1.0, 0.5], dtype=real)
        v2 = np.array([1.0, 1.0], dtype=real)
        v2p = np.array([0.5, 1.0], dtype=real)
        v3 = np.array([0.0, 1.0], dtype=real)
        polygon_vertices = np.array([v0, v1, v1p, v2, v2p, v3], dtype=real).T
        shape = Shape(ShapeType.POLYGON, polygon_vertices)
        x_c = shape.get_centroid()
        h_c = shape.get_diameter()
        v_c = shape.get_volume()
        if verbose:
            print("-- centroid :\n{}".format(x_c))
            print("-- diameter :\n{}".format(h_c))
            print("-- volume :\n{}".format(v_c))
            for i in range(6):
                plt.scatter(polygon_vertices[0, i],
                            polygon_vertices[1, i],
                            c="b")
            plt.scatter(x_c[0], x_c[1], c="b")
            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 get_stabilization_operator2(field: Field, finite_element: FiniteElement,
                                cell: Shape, faces: List[Shape]) -> ndarray:
    _dx = field.field_dimension
    _cl = finite_element.cell_basis_l.dimension
    _fk = finite_element.face_basis_k.dimension
    _nf = len(faces)
    _es = _dx * (_cl + _nf * _fk)
    _io = finite_element.construction_integration_order
    x_c = cell.get_centroid()
    h_c = cell.get_diameter()
    stabilization_operator = np.zeros((_es, _es), dtype=real)
    stabilization_op = np.zeros((_fk * _dx, _es), dtype=real)
    for _f, face in enumerate(faces):
        h_f = face.get_diameter()
        x_f = face.get_centroid()
        face_quadrature_points = face.get_quadrature_points(_io)
        face_quadrature_weights = face.get_quadrature_weights(_io)
        face_quadrature_size = face.get_quadrature_size(_io)
        face_rotation_matrix = get_rotation_matrix(face.type, face.vertices)
        m_mas_f = np.zeros((_fk, _fk), dtype=real)
        m_hyb_f = np.zeros((_fk, _cl), 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]
            x_q_f_p = face_rotation_matrix @ x_q_f
            x_c_p = face_rotation_matrix @ x_c
            phi_l = finite_element.cell_basis_l.evaluate_function(
                x_q_f, x_c, h_c)
            # phi_l = cell_basis_l.get_phi_vector(x_q_f_p, x_c_p, h_c)
            psi_k = finite_element.face_basis_k.evaluate_function(
                s_q_f, s_f, h_f)
            m_hyb_f += w_q_f * np.tensordot(psi_k, phi_l, axes=0)
            m_mas_f += w_q_f * np.tensordot(psi_k, psi_k, axes=0)
        m_mas_f_inv = np.linalg.inv(m_mas_f)
        proj_mat = m_mas_f_inv @ m_hyb_f
        m = np.eye(_fk, dtype=real)
        m_mas_f2 = np.zeros((_dx * _fk, _dx * _fk), dtype=real)
        for _i in range(_dx):
            _ri = _i * _fk
            _rj = (_i + 1) * _fk
            _ci = _i * _cl
            _cj = (_i + 1) * _cl
            stabilization_op[_ri:_rj, _ci:_cj] -= proj_mat
            _ci = _dx * _cl + _f * _dx * _fk + _i * _fk
            _cj = _dx * _cl + _f * _dx * _fk + (_i + 1) * _fk
            stabilization_op[_ri:_rj, _ci:_cj] += m
            m_mas_f2[_ri:_rj, _ri:_rj] += m_mas_f
        stabilization_operator += (
            1.0 / h_f) * stabilization_op.T @ m_mas_f2 @ stabilization_op
        # stabilization_operator += stabilization_op.T @ m_mas_f @ stabilization_op
    return stabilization_operator
Example #6
0
def get_gradient_operators(field: Field, finite_element: FiniteElement,
                           cell: Shape, faces: List[Shape]) -> ndarray:
    _gs = field.gradient_dimension
    _io = finite_element.construction_integration_order
    _c_is = cell.get_quadrature_size(_io)
    cell_quadrature_points = cell.get_quadrature_points(_io)
    _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)
    gradient_operators = np.zeros((_c_is, _gs, _es), dtype=real)
    h_c = cell.get_diameter()
    x_c = cell.get_centroid()
    for _qc in range(_c_is):
        x_qc = cell_quadrature_points[:, _qc]
        v_ck = finite_element.cell_basis_k.evaluate_function(x_qc, x_c, h_c)
        for key, val in field.voigt_data.items():
            _i = key[0]
            _j = key[1]
            voigt_indx = val[0]
            voigt_coef = val[1]
            if field.derivation_type == DerivationType.REGULAR:
                gradient_component_matrix = get_regular_gradient_component_matrix(
                    field=field,
                    finite_element=finite_element,
                    cell=cell,
                    faces=faces,
                    _i=_i,
                    _j=_j)
            elif field.derivation_type == DerivationType.SYMMETRIC:
                gradient_component_matrix = get_symmetric_gradient_component_matrix(
                    field=field,
                    finite_element=finite_element,
                    cell=cell,
                    faces=faces,
                    _i=_i,
                    _j=_j)
            else:
                raise KeyError
            gradient_operators[
                _qc,
                voigt_indx] = voigt_coef * v_ck @ gradient_component_matrix
    return gradient_operators
Example #7
0
    def get_elements(self):
        """

        Returns:

        """
        elements = []
        _fk = self.finite_element.face_basis_k.dimension
        _dx = self.field.field_dimension
        _cl = self.finite_element.cell_basis_l.dimension
        for cell_index in range(self.mesh.number_of_cells_in_mesh):
            cell_vertices_connectivity = self.mesh.cells_vertices_connectivity[cell_index]
            cell_faces_connectivity = self.mesh.cells_faces_connectivity[cell_index]
            cell_ordering = self.mesh.cells_ordering[cell_index]
            cell_shape_type = self.mesh.cells_shape_types[cell_index]
            cell_vertices = self.mesh.vertices[:, cell_vertices_connectivity]
            # element_cell = Cell(cell_shape_type, cell_vertices, integration_order, quadrature_type=quadrature_type)
            element_cell = Shape(cell_shape_type, cell_vertices, connectivity=cell_ordering)
            element_faces = []
            element_faces_indices = []
            for global_face_index in cell_faces_connectivity:
                element_faces_indices.append(global_face_index)
                face_vertices_indices = self.mesh.faces_vertices_connectivity[global_face_index]
                face_vertices = self.mesh.vertices[:, face_vertices_indices]
                face_shape_type = self.mesh.faces_shape_types[global_face_index]
                # print(global_face_index)
                # print(face_vertices)
                # print(cell_vertices)
                face = Shape(face_shape_type, face_vertices)
                element_faces.append(face)
            # print(cell_index)
            # print(cell_vertices)
            element = Element(
                self.field,
                self.finite_element,
                element_cell,
                element_faces,
                element_faces_indices,
            )
            elements.append(element)
            del element_cell
            del element_faces
        return elements
Example #8
0
    def test_reference_segment_geometry_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)
        x_c = shape.get_centroid()
        h_c = shape.get_diameter()
        v_c = shape.get_volume()
        if verbose:
            print("-- centroid :\n{}".format(x_c))
            print("-- diameter :\n{}".format(h_c))
            print("-- volume :\n{}".format(v_c))
            for i in range(2):
                plt.scatter(vertices[0, i], vertices[1, i], c="b")
            plt.scatter(x_c[0], x_c[1], c="b")
            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
    def test_reference_triangle_geometry_cell(self, verbose=True):
        """

        Args:
            verbose:
        """
        v0 = np.array([+.00000000000000E+00, +.28725932709342E-01], dtype=real)
        v1 = np.array([+.00000000000000E+00, +.30000000000000E-01], dtype=real)
        v2 = np.array([+.20769230769231E-03, +.30000000000000E-01], dtype=real)
        vertices = np.array([v0, v1, v2], dtype=real).T
        shape = Shape(ShapeType.TRIANGLE, vertices)
        x_c = shape.get_centroid()
        h_c = shape.get_diameter()
        v_c = shape.get_volume()
        if verbose:
            print("-- centroid :\n{}".format(x_c))
            print("-- diameter :\n{}".format(h_c))
            print("-- volume :\n{}".format(v_c))
            for i in range(3):
                plt.scatter(vertices[0, i], vertices[1, i], c="b")
            plt.scatter(x_c[0], x_c[1], c="b")
            plt.show()
    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()
Example #12
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 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()
Example #15
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()
Example #16
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)
Example #17
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
Example #18
0
def get_stab_test(field: Field, finite_element: FiniteElement, cell: Shape,
                  faces: List[Shape]) -> ndarray:
    _dx = field.field_dimension
    _cl = finite_element.cell_basis_l.dimension
    _fk = finite_element.face_basis_k.dimension
    _nf = len(faces)
    _es = _dx * (_cl + _nf * _fk)
    stabilization_operator = np.zeros((_es, _es), dtype=real)
    h_c = cell.get_diameter()
    x_c = cell.get_centroid()
    for _f, face in enumerate(faces):
        face_stabilization_operator = np.zeros((_es, _es), dtype=real)
        stabilization_vector_operator = np.zeros((_dx, _es), dtype=real)
        x_f = face.get_centroid()
        h_f = face.get_diameter()
        m_mas_f = np.zeros((_fk, _fk), dtype=real)
        m_hyb_f = np.zeros((_fk, _cl), dtype=real)
        # m_prj_f = np.zeros((_fk, _cl))
        face_rotation_matrix = face.get_rotation_matrix()
        face_quadrature_size = face.get_quadrature_size(
            finite_element.construction_integration_order)
        face_quadrature_points = face.get_quadrature_points(
            finite_element.construction_integration_order)
        face_quadrature_weights = face.get_quadrature_weights(
            finite_element.construction_integration_order)
        # for qf in range(len(face.quadrature_weights)):
        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 = w_q_f * finite_element.face_basis_k.evaluate_function(
                s_q_f, s_f, h_f)
            phi_l = w_q_f * finite_element.cell_basis_l.evaluate_function(
                x_q_f, x_c, h_c)
            m_mas_f += np.tensordot(psi_k, psi_k, axes=0)
            m_hyb_f += np.tensordot(psi_k, phi_l, axes=0)
            # m_mas_f += get_face_mass_matrix_in_face(
            #     face, finite_element.face_basis_k, finite_element.face_basis_k, x_q_f, w_q_f
            # )
            # m_hyb_f += get_test_mass_matrix_in_face(
            #     cell, face, finite_element.cell_basis_l, finite_element.face_basis_k, x_q_f, w_q_f
            # )
        m_mas_f_inv = np.linalg.inv(m_mas_f)
        # if  == DebugMode.LIGHT:
        #     print("FACE MASS MATRIX IN STABILIZATION COND :")
        #     print("{}".format(np.linalg.cond(m_mas_f)))
        m_prj_f = m_mas_f_inv @ m_hyb_f
        m_eye_f = np.eye(_fk, dtype=real)
        for _x in range(_dx):
            stabilization_vector_component_op = np.zeros((_fk, _es),
                                                         dtype=real)
            c0 = _x * _cl
            c1 = (_x + 1) * _cl
            stabilization_vector_component_op[:, c0:c1] -= m_prj_f
            c0 = _dx * _cl + _f * _dx * _fk + _x * _fk
            c1 = _dx * _cl + _f * _dx * _fk + (_x + 1) * _fk
            stabilization_vector_component_op[:, c0:c1] += m_eye_f
            # for qf in range(len(face.quadrature_weights)):
            for qf in range(face_quadrature_size):
                x_q_f = face_quadrature_points[:, qf]
                w_q_f = face_quadrature_weights[qf]
                s_q_f = (face_rotation_matrix @ x_q_f)[:-1]
                s_f = (face_rotation_matrix @ x_f)[:-1]
                v_face = finite_element.face_basis_k.evaluate_function(
                    s_q_f, s_f, h_f)
                # stabilization_vector_component_at_quad = v_face @ stabilization_vector_component_op
                stabilization_vector_operator[
                    _x, :] += v_face @ stabilization_vector_component_op
        # for qf in range(len(face.quadrature_weights)):
        for qf in range(face_quadrature_size):
            x_q_f = face_quadrature_points[:, qf]
            w_q_f = face_quadrature_weights[qf]
            m_eye_tan = np.eye(_dx, dtype=real)
            face_stabilization_operator += w_q_f * stabilization_vector_operator.T @ m_eye_tan @ stabilization_vector_operator
        weighted_face_stabilization_operator = (
            1.0 / h_f) * face_stabilization_operator
        stabilization_operator += weighted_face_stabilization_operator
    return stabilization_operator
    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_geometry_cell(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)
        x_c = shape.get_centroid()
        h_c = shape.get_diameter()
        v_c = shape.get_volume()
        if verbose:
            print("-- centroid :\n{}".format(x_c))
            print("-- diameter :\n{}".format(h_c))
            print("-- volume :\n{}".format(v_c))
            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")
            plt.show()
    def test_operators_triangle(self):
        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,
                )

                field = Field("TEST", FieldType.DISPLACEMENT_SMALL_STRAIN_PLANE_STRAIN)

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

                # --------------------------------------------------------------------------------------------------------------
                # DEFINE RANDOM POLYNOMIAL COEFFICIENTS
                # --------------------------------------------------------------------------------------------------------------
                range_min = -3.0
                range_max = +3.0
                coefficients_k_list = []
                coefficients_l_list = []
                coefficients_r_list = []
                for _i in range(field.field_dimension):
                    coefficients_k = np.array(
                        [uniform(range_min, range_max) for _iloc in range(cell_basis_k.dimension)]
                    )
                    coefficients_l = np.array(
                        [uniform(range_min, range_max) for _iloc in range(cell_basis_l.dimension)]
                    )
                    coefficients_r = np.array(
                        [uniform(range_min, range_max) for _iloc in range(cell_basis_r.dimension)]
                    )
                    coefficients_k_list.append(coefficients_k)
                    coefficients_l_list.append(coefficients_l)
                    coefficients_r_list.append(coefficients_r)
                # 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([1.0, 1.7], dtype=real)
                v1 = np.array([2.0, 1.6], dtype=real)
                v2 = np.array([1.9, 3.0], dtype=real)
                triangle_vertices = np.array([v0, v1, v2], dtype=real).T

                # --------------------------------------------------------------------------------------------------------------
                # BUILD CELL
                # --------------------------------------------------------------------------------------------------------------
                cell_triangle = Shape(ShapeType.TRIANGLE, triangle_vertices)

                # --------------------------------------------------------------------------------------------------------------
                # BUILD FACES
                # --------------------------------------------------------------------------------------------------------------
                faces_segment = [
                    Shape(ShapeType.SEGMENT, triangle_vertices[:, [0, 1]]),
                    Shape(ShapeType.SEGMENT, triangle_vertices[:, [1, 2]]),
                    Shape(ShapeType.SEGMENT, triangle_vertices[:, [2, 0]]),
                ]

                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 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

                # fun = [
                #     lambda x: test_function(
                #         finite_element.cell_basis_l.polynomial_order,
                #         x,
                #         cell_triangle.centroid,
                #         cell_triangle.diameter,
                #         coefficients_l_list[0],
                #     ),
                #     lambda x: test_function(
                #         finite_element.cell_basis_l.polynomial_order,
                #         x,
                #         cell_triangle.centroid,
                #         cell_triangle.diameter,
                #         coefficients_l_list[1],
                #     )
                # ]
                #
                # fun_grad_regular = [
                #     [
                #         lambda x: test_function_derivative(
                #             finite_element.cell_basis_l.polynomial_order,
                #             x,
                #             cell_triangle.centroid,
                #             cell_triangle.diameter,
                #             0,
                #             coefficients_l_list[0],
                #         ),
                #         lambda x: test_function_derivative(
                #             finite_element.cell_basis_l.polynomial_order,
                #             x,
                #             cell_triangle.centroid,
                #             cell_triangle.diameter,
                #             1,
                #             coefficients_l_list[0],
                #         ),
                #     ],
                #     [
                #         lambda x: test_function_derivative(
                #             finite_element.cell_basis_l.polynomial_order,
                #             x,
                #             cell_triangle.centroid,
                #             cell_triangle.diameter,
                #             0,
                #             coefficients_l_list[1],
                #         ),
                #         lambda x: test_function_derivative(
                #             finite_element.cell_basis_l.polynomial_order,
                #             x,
                #             cell_triangle.centroid,
                #             cell_triangle.diameter,
                #             1,
                #             coefficients_l_list[1],
                #         ),
                #     ],
                # ]
                #
                # fun_grad_symmetric = [
                #     [
                #         lambda x: (1.0 / 2.0)
                #         * (
                #             test_function_derivative(
                #                 finite_element.cell_basis_l.polynomial_order,
                #                 x,
                #                 cell_triangle.centroid,
                #                 cell_triangle.diameter,
                #                 0,
                #                 coefficients_l_list[0],
                #             )
                #             + test_function_derivative(
                #                 finite_element.cell_basis_l.polynomial_order,
                #                 x,
                #                 cell_triangle.centroid,
                #                 cell_triangle.diameter,
                #                 0,
                #                 coefficients_l_list[0],
                #             )
                #         ),
                #         lambda x: (1.0 / 2.0)
                #         * (
                #             test_function_derivative(
                #                 finite_element.cell_basis_l.polynomial_order,
                #                 x,
                #                 cell_triangle.centroid,
                #                 cell_triangle.diameter,
                #                 1,
                #                 coefficients_l_list[0],
                #             )
                #             + test_function_derivative(
                #                 finite_element.cell_basis_l.polynomial_order,
                #                 x,
                #                 cell_triangle.centroid,
                #                 cell_triangle.diameter,
                #                 0,
                #                 coefficients_l_list[1],
                #             )
                #         ),
                #     ],
                #     [
                #         lambda x: (1.0 / 2.0)
                #         * (
                #             test_function_derivative(
                #                 finite_element.cell_basis_l.polynomial_order,
                #                 x,
                #                 cell_triangle.centroid,
                #                 cell_triangle.diameter,
                #                 0,
                #                 coefficients_l_list[1],
                #             )
                #             + test_function_derivative(
                #                 finite_element.cell_basis_l.polynomial_order,
                #                 x,
                #                 cell_triangle.centroid,
                #                 cell_triangle.diameter,
                #                 1,
                #                 coefficients_l_list[0],
                #             )
                #         ),
                #         lambda x: (1.0 / 2.0)
                #         * (
                #             test_function_derivative(
                #                 finite_element.cell_basis_l.polynomial_order,
                #                 x,
                #                 cell_triangle.centroid,
                #                 cell_triangle.diameter,
                #                 1,
                #                 coefficients_l_list[1],
                #             )
                #             + test_function_derivative(
                #                 finite_element.cell_basis_l.polynomial_order,
                #                 x,
                #                 cell_triangle.centroid,
                #                 cell_triangle.diameter,
                #                 1,
                #                 coefficients_l_list[1],
                #             )
                #         ),
                #     ],
                # ]

                fun = [
                    lambda x: test_function(
                        finite_element.cell_basis_r.polynomial_order,
                        x,
                        cell_triangle.centroid,
                        cell_triangle.diameter,
                        coefficients_r_list[0],
                    ),
                    lambda x: test_function(
                        finite_element.cell_basis_r.polynomial_order,
                        x,
                        cell_triangle.centroid,
                        cell_triangle.diameter,
                        coefficients_r_list[1],
                    ),
                ]

                fun_grad_regular = [
                    [
                        lambda x: test_function_derivative(
                            finite_element.cell_basis_r.polynomial_order,
                            x,
                            cell_triangle.centroid,
                            cell_triangle.diameter,
                            0,
                            coefficients_r_list[0],
                        ),
                        lambda x: test_function_derivative(
                            finite_element.cell_basis_r.polynomial_order,
                            x,
                            cell_triangle.centroid,
                            cell_triangle.diameter,
                            1,
                            coefficients_r_list[0],
                        ),
                    ],
                    [
                        lambda x: test_function_derivative(
                            finite_element.cell_basis_r.polynomial_order,
                            x,
                            cell_triangle.centroid,
                            cell_triangle.diameter,
                            0,
                            coefficients_r_list[1],
                        ),
                        lambda x: test_function_derivative(
                            finite_element.cell_basis_r.polynomial_order,
                            x,
                            cell_triangle.centroid,
                            cell_triangle.diameter,
                            1,
                            coefficients_r_list[1],
                        ),
                    ],
                ]

                fun_grad_symmetric = [
                    [
                        lambda x: (1.0 / 2.0)
                        * (
                            test_function_derivative(
                                finite_element.cell_basis_r.polynomial_order,
                                x,
                                cell_triangle.centroid,
                                cell_triangle.diameter,
                                0,
                                coefficients_r_list[0],
                            )
                            + test_function_derivative(
                                finite_element.cell_basis_r.polynomial_order,
                                x,
                                cell_triangle.centroid,
                                cell_triangle.diameter,
                                0,
                                coefficients_r_list[0],
                            )
                        ),
                        lambda x: (1.0 / 2.0)
                        * (
                            test_function_derivative(
                                finite_element.cell_basis_r.polynomial_order,
                                x,
                                cell_triangle.centroid,
                                cell_triangle.diameter,
                                1,
                                coefficients_r_list[0],
                            )
                            + test_function_derivative(
                                finite_element.cell_basis_r.polynomial_order,
                                x,
                                cell_triangle.centroid,
                                cell_triangle.diameter,
                                0,
                                coefficients_r_list[1],
                            )
                        ),
                    ],
                    [
                        lambda x: (1.0 / 2.0)
                        * (
                            test_function_derivative(
                                finite_element.cell_basis_r.polynomial_order,
                                x,
                                cell_triangle.centroid,
                                cell_triangle.diameter,
                                0,
                                coefficients_r_list[1],
                            )
                            + test_function_derivative(
                                finite_element.cell_basis_r.polynomial_order,
                                x,
                                cell_triangle.centroid,
                                cell_triangle.diameter,
                                1,
                                coefficients_r_list[0],
                            )
                        ),
                        lambda x: (1.0 / 2.0)
                        * (
                            test_function_derivative(
                                finite_element.cell_basis_r.polynomial_order,
                                x,
                                cell_triangle.centroid,
                                cell_triangle.diameter,
                                1,
                                coefficients_r_list[1],
                            )
                            + test_function_derivative(
                                finite_element.cell_basis_r.polynomial_order,
                                x,
                                cell_triangle.centroid,
                                cell_triangle.diameter,
                                1,
                                coefficients_r_list[1],
                            )
                        ),
                    ],
                ]

                # --------------------------------------------------------------------------------------------------------------
                # BUILD AND TEST STABILIZATION
                # --------------------------------------------------------------------------------------------------------------

                fun_proj = get_element_projection_vector(cell_triangle, faces_segment, fun)
                # stab_matrix, stab_matrix_0, stab_matrix2 = get_stabilization_operator(cell_triangle, faces_segment)
                stabilization_operator = stabop.get_stabilization_operator2(
                    field, finite_element, cell_triangle, faces_segment
                )
                print(
                    "--- FUN PROJ | k : {} | l : {}".format(
                        cell_basis_k.polynomial_order, cell_basis_l.polynomial_order
                    )
                )
                print(fun_proj)
                print(
                    "--- STABILIZATION | k : {} | l : {}".format(
                        cell_basis_k.polynomial_order, cell_basis_l.polynomial_order
                    )
                )
                stab_val = fun_proj @ stabilization_operator @ fun_proj
                print(stab_val)
                rtol = 1000000.0
                atol = 1.0e-11
                # np.testing.assert_allclose(stab_val, 0.0, rtol=rtol, atol=atol)

                correspondance = {0: (0, 0), 1: (1, 1), 2: (0, 1), 3: (1, 0)}
                for key, val in correspondance.items():
                    dir_x = val[0]
                    dir_y = val[1]
                    # rtol = 1.0e-12
                    # rtol = 1.0e-3
                    rtol = 1000000.0
                    atol = 1.0e-11
                    print(
                        "--- SYMMETRIC GRADIENT | k : {} | l : {}".format(
                            cell_basis_k.polynomial_order, cell_basis_l.polynomial_order
                        )
                    )
                    fun_proj = get_element_projection_vector(cell_triangle, faces_segment, fun)
                    grad_comp = gradop.get_symmetric_gradient_component_matrix(
                        field, finite_element, cell_triangle, faces_segment, dir_x, dir_y
                    )
                    # fun_grad_proj = get_gradient_projection_vector(cell_triangle, fun_grad_sym[choice])
                    # fun_grad_proj = get_gradient_projection_vector(cell_triangle, fun_grad_symmetric[dir_x][dir_y])
                    fun_grad_proj = get_gradient_projection_vector(cell_triangle, fun_grad_symmetric[dir_y][dir_x])
                    grad_check = grad_comp @ fun_proj
                    print("- GRAD REC | {} | {}".format(dir_x, dir_y))
                    print(grad_check)
                    print("- GRAD PROJ | {} | {}".format(dir_x, dir_y))
                    print(fun_grad_proj)
                    np.testing.assert_allclose(grad_check, fun_grad_proj, rtol=rtol, atol=atol)
                    print(
                        "--- REGULAR GRADIENT | k : {} | l : {}".format(
                            cell_basis_k.polynomial_order, cell_basis_l.polynomial_order
                        )
                    )
                    fun_proj = get_element_projection_vector(cell_triangle, faces_segment, fun)
                    grad_comp = gradop.get_regular_gradient_component_matrix(
                        field, finite_element, cell_triangle, faces_segment, dir_x, dir_y
                    )
                    # fun_grad_proj = get_gradient_projection_vector(cell_triangle, fun_grad_sym[choice])
                    fun_grad_proj = get_gradient_projection_vector(cell_triangle, fun_grad_regular[dir_x][dir_y])
                    grad_check = grad_comp @ fun_proj
                    print("- GRAD REC | {} | {}".format(dir_x, dir_y))
                    print(grad_check)
                    print("- GRAD PROJ | {} | {}".format(dir_x, dir_y))
                    print(fun_grad_proj)
                    np.testing.assert_allclose(grad_check, fun_grad_proj, rtol=rtol, atol=atol)
    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)