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()
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()
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
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
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
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()
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()
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()
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)
def get_regular_gradient_component_matrix(field: Field, finite_element: FiniteElement, cell: Shape, faces: List[Shape], _i: int, _j: int) -> ndarray: _d = field.euclidean_dimension _dx = field.field_dimension _cl = finite_element.cell_basis_l.dimension _ck = finite_element.cell_basis_k.dimension _fk = finite_element.face_basis_k.dimension _nf = len(faces) _es = _dx * (_cl + _nf * _fk) _io = finite_element.construction_integration_order # --- CELL ENVIRONMENT _c_is = cell.get_quadrature_size(_io) cell_quadrature_points = cell.get_quadrature_points(_io) cell_quadrature_weights = cell.get_quadrature_weights(_io) x_c = cell.get_centroid() h_c = cell.get_diameter() local_grad_matric = np.zeros((_ck, _es), dtype=real) m_mas = np.zeros((_ck, _ck), dtype=real) m_adv_j = np.zeros((_ck, _cl), dtype=real) for qc in range(_c_is): x_q_c = cell_quadrature_points[:, qc] w_q_c = cell_quadrature_weights[qc] phi_k = finite_element.cell_basis_k.evaluate_function(x_q_c, x_c, h_c) d_phi_l_j = finite_element.cell_basis_l.evaluate_derivative( x_q_c, x_c, h_c, _j) m_adv_j += w_q_c * np.tensordot(phi_k, d_phi_l_j, axes=0) m_mas += w_q_c * np.tensordot(phi_k, phi_k, axes=0) m_mas_inv = np.linalg.inv(m_mas) _c0 = _i * _cl _c1 = (_i + 1) * _cl local_grad_matric[:, _c0:_c1] += m_adv_j for _f, face in enumerate(faces): # --- FACE ENVIRONMENT _f_is = face.get_quadrature_size(_io) face_quadrature_points = face.get_quadrature_points(_io) face_quadrature_weights = face.get_quadrature_weights(_io) h_f = face.get_diameter() x_f = face.get_centroid() # face_rotation_matrix = get_rotation_matrix(face.type, face.vertices) face_rotation_matrix = face.get_rotation_matrix() dist_in_face = (face_rotation_matrix @ (x_f - x_c))[-1] if dist_in_face > 0: normal_vector_component_j = face_rotation_matrix[-1, _j] else: normal_vector_component_j = -face_rotation_matrix[-1, _j] m_mas_f = np.zeros((_ck, _cl), dtype=real) m_hyb_f = np.zeros((_ck, _fk), dtype=real) for qf in range(_f_is): x_q_f = face_quadrature_points[:, qf] # x_q_f_prime = face.mapping_matrix @ face.quadrature_points[:, qf] w_q_f = face_quadrature_weights[qf] s_f = (face_rotation_matrix @ x_f)[:-1] s_q_f = (face_rotation_matrix @ x_q_f)[:-1] phi_k = finite_element.cell_basis_k.evaluate_function( x_q_f, x_c, h_c) phi_l = finite_element.cell_basis_l.evaluate_function( x_q_f, x_c, h_c) # phi_k = cell_basis_k.get_phi_vector(x_q_f_prime, x_c, h_c) # phi_l = cell_basis_l.get_phi_vector(x_q_f_prime, x_c, h_c) psi_k = finite_element.face_basis_k.evaluate_function( s_q_f, s_f, h_f) m_mas_f += w_q_f * np.tensordot(phi_k, phi_l, axes=0) m_hyb_f += w_q_f * np.tensordot(phi_k, psi_k, axes=0) _c0 = _i * _cl _c1 = (_i + 1) * _cl local_grad_matric[:, _c0:_c1] -= m_mas_f * normal_vector_component_j _c0 = _dx * _cl + _f * _dx * _fk + _i * _fk _c1 = _dx * _cl + _f * _dx * _fk + (_i + 1) * _fk local_grad_matric[:, _c0:_c1] += m_hyb_f * normal_vector_component_j local_grad_matric2 = m_mas_inv @ local_grad_matric return local_grad_matric2
def 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)