def test_reference_hexahedron_quadrature(self, verbose=True): """ Args: verbose: """ v0 = np.array([0.0, 0.0, 0.0], dtype=real) v1 = np.array([1.0, 0.0, 0.0], dtype=real) v2 = np.array([1.0, 1.0, 0.0], dtype=real) v3 = np.array([0.0, 1.0, 0.0], dtype=real) v4 = np.array([0.0, 0.0, 1.0], dtype=real) v5 = np.array([1.0, 0.0, 1.0], dtype=real) v6 = np.array([1.0, 1.0, 1.0], dtype=real) v7 = np.array([0.0, 1.0, 1.0], dtype=real) vertices = np.array([v0, v1, v2, v3, v4, v5, v6, v7], dtype=real).T shape = Shape(ShapeType.HEXAHEDRON, vertices) for _io in range(1, 9): # --- DECLARE FUNCTION f = lambda x: np.exp(x[0]) * np.sin(x[0] * x[1] / (x[2] + 0.003) ) + x[1] * x[2] + 3.0 f_scipy = lambda x, y, z: np.exp(x) * np.sin(x * y / (z + 0.003) ) + y * z + 3.0 # --- GET QUADPY ESTIMATION scheme = quadpy.c3.get_good_scheme(_io) val = scheme.integrate( f, [[[v0, v4], [v3, v7]], [[v1, v5], [v2, v6]]]) # --- GET H20 ESTIMATION val_num = 0.0 shape_quadrature_points = shape.get_quadrature_points(_io) shape_quadrature_weights = shape.get_quadrature_weights(_io) shape_quadrature_size = shape.get_quadrature_size(_io) for _qc in range(shape_quadrature_size): x_qc = shape_quadrature_points[:, _qc] w_qc = shape_quadrature_weights[_qc] val_num += w_qc * f(x_qc) # --- GET SCIPY ESTIMATION # val_scp = integrate.tplquad( # f_scipy, 0.0, 1.0, lambda x: 0.0, lambda x: 1.0, lambda x, y: 0.0, lambda x, y: 1.0 # ) if verbose: print("-- integration order : {}".format(_io)) print("val_h2O : {}".format(val_num)) print("val_qud : {}".format(val)) # print("val_scp : {}".format(val_scp)) x_c = shape.get_centroid() fig = plt.figure() ax = fig.add_subplot(111, projection="3d") ax.scatter(x_c[0], x_c[1], x_c[2], c="b", marker="o") for i in range(vertices.shape[1]): ax.scatter(vertices[0, i], vertices[1, i], vertices[2, i], c="b", marker="o") for _qc in range(shape_quadrature_size): _x_qc = shape_quadrature_points[:, _qc] ax.scatter(_x_qc[0], _x_qc[1], _x_qc[2], c="g") plt.show()
def get_element_projection_vector(cell: Shape, faces: List[Shape], function: List[Callable]): _d = euclidean_dimension _dx = field.field_dimension _cl = cell_basis_l.dimension _fk = face_basis_k.dimension _nf = len(faces) _es = _dx * (_cl + _nf * _fk) # x_c = cell.centroid h_c = cell.diameter _io = finite_element.construction_integration_order cell_quadrature_points = cell.get_quadrature_points(_io) cell_quadrature_weights = cell.get_quadrature_weights(_io) cell_quadrature_size = cell.get_quadrature_size(_io) matrix = np.zeros((_es, _es), dtype=real) vector = np.zeros((_es,), dtype=real) for _dir in range(_dx): m_mas = np.zeros((_cl, _cl), dtype=real) vc = np.zeros((_cl,), dtype=real) for qc in range(cell_quadrature_size): x_q_c = cell_quadrature_points[:, qc] w_q_c = cell_quadrature_weights[qc] phi_l = cell_basis_l.evaluate_function(x_q_c, x_c, h_c) m_mas += w_q_c * np.tensordot(phi_l, phi_l, axes=0) vc += w_q_c * phi_l * function[_dir](x_q_c) _i = _cl * _dir _j = _cl * (_dir + 1) matrix[_i:_j, _i:_j] += m_mas vector[_i:_j] += vc for _f, face in enumerate(faces): face_rotation_matrix = get_rotation_matrix(face.type, face.vertices) x_f = face.centroid h_f = face.diameter # --- PROJECT ON HYPERPLANE s_f = (face_rotation_matrix @ x_f)[:-1] _io = finite_element.construction_integration_order face_quadrature_points = face.get_quadrature_points(_io) face_quadrature_weights = face.get_quadrature_weights(_io) face_quadrature_size = face.get_quadrature_size(_io) for _dir in range(_dx): m_mas_f = np.zeros((_fk, _fk), dtype=real) vf = np.zeros((_fk,), dtype=real) for qf in range(face_quadrature_size): x_q_f = face_quadrature_points[:, qf] w_q_f = face_quadrature_weights[qf] # s_f = (face_rotation_matrix @ x_f)[:-1] s_q_f = (face_rotation_matrix @ x_q_f)[:-1] psi_k = face_basis_k.evaluate_function(s_q_f, s_f, h_f) m_mas_f += w_q_f * np.tensordot(psi_k, psi_k, axes=0) vf += w_q_f * psi_k * function[_dir](x_q_f) _i = _cl * _dx + _f * _fk * _dx + _dir * _fk _j = _cl * _dx + _f * _fk * _dx + (_dir + 1) * _fk matrix[_i:_j, _i:_j] += m_mas_f vector[_i:_j] += vf projection_vector = np.linalg.solve(matrix, vector) return projection_vector
def test_quadrangle_quadrature_cell(self, verbose=True): """ Args: verbose: """ v0 = np.array([0.0, 0.0], dtype=real) v1 = np.array([1.0, 0.0], dtype=real) v2 = np.array([1.0, 1.0], dtype=real) v3 = np.array([0.0, 1.0], dtype=real) quadrangle_vertices = np.array([v0, v1, v2, v3], dtype=real).T cell_triangle = Shape(ShapeType.QUADRANGLE, quadrangle_vertices) for _io in range(1, 9): # --- DECLARE FUNCTION f = lambda x: np.exp(x[0]) * np.sin(x[0] * x[1]) + x[1] + 3. f_scipy = lambda x, y: np.exp(x) * np.sin(x * y) + y + 3. # --- GET QUADPY ESTIMATION scheme = quadpy.c2.get_good_scheme(_io) val = scheme.integrate( f, [[v0, v1], [v3, v2]], ) # --- GET H20 ESTIMATION val_num = 0.0 triangle_quadrature_points = cell_triangle.get_quadrature_points( _io) triangle_quadrature_weights = cell_triangle.get_quadrature_weights( _io) triangle_quadrature_size = cell_triangle.get_quadrature_size(_io) for _qc in range(triangle_quadrature_size): x_qc = triangle_quadrature_points[:, _qc] w_qc = triangle_quadrature_weights[_qc] val_num += w_qc * f(x_qc) # --- GET SCIPY ESTIMATION val_scp = integrate.dblquad(f_scipy, 0.0, 1.0, lambda x: 0.0, lambda x: 1.0) if verbose: print("-- integration order : {}".format(_io)) print("val_h2O : {}".format(val_num)) print("val_qud : {}".format(val)) print("val_scp : {}".format(val_scp)) x_c = cell_triangle.get_centroid() plt.scatter(x_c[0], x_c[1], c="b") for i in range(4): plt.scatter(quadrangle_vertices[0, i], quadrangle_vertices[1, i], c="b") for _qc in range(triangle_quadrature_size): _x_qc = triangle_quadrature_points[:, _qc] plt.scatter(_x_qc[0], _x_qc[1], c="g") plt.show()
def test_reference_triangle_quadrature(self, verbose=True): """ Args: verbose: """ # v0 = np.array([0.00000000000000E+00, 0.28725932709342E-01], dtype=real) # v1 = np.array([0.00000000000000E+00, 0.30000000000000E-01], dtype=real) # v2 = np.array([0.20769230769231E-03, 0.30000000000000E-01], dtype=real) v0 = np.array([+.30000000000000E-02, +.00000000000000E+00], dtype=real) v1 = np.array([+.30038156151383E-02, +.21394584067090E-03], dtype=real) v2 = np.array([+.28882842453253E-02, +.21394584067090E-03], dtype=real) vertices = np.array([v0, v1, v2], dtype=real).T shape = Shape(ShapeType.TRIANGLE, vertices) for _io in range(1, 9): # --- DECLARE FUNCTION f = lambda x: np.exp(x[0]) * np.sin(x[0] * x[1]) + x[1] + 3. # --- GET QUADPY ESTIMATION scheme = quadpy.t2.get_good_scheme(_io) val = scheme.integrate( f, [v0, v1, v2], ) # --- GET H20 ESTIMATION val_num = 0.0 shape_quadrature_points = shape.get_quadrature_points(_io) shape_quadrature_weights = shape.get_quadrature_weights(_io) shape_quadrature_size = shape.get_quadrature_size(_io) print("-- QUAD_WGTS") print(shape_quadrature_weights) for _qc in range(shape_quadrature_size): x_qc = shape_quadrature_points[:, _qc] w_qc = shape_quadrature_weights[_qc] val_num += w_qc * f(x_qc) # --- GET SCIPY ESTIMATION if verbose: print("-- integration order : {}".format(_io)) print("val_h2O : {}".format(val_num)) print("val_qud : {}".format(val)) x_c = shape.get_centroid() plt.scatter(v0[0], v0[1], c="b") plt.scatter(v1[0], v1[1], c="b") plt.scatter(v2[0], v2[1], c="b") plt.scatter(x_c[0], x_c[1], c="b") for _qc in range(shape_quadrature_size): _x_qc = shape_quadrature_points[:, _qc] plt.scatter(_x_qc[0], _x_qc[1], c="g") plt.show()
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 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 test_reference_segment_quadrature_face(self, verbose=True): """ Args: verbose: """ v0 = np.array([0.0, 0.0], dtype=real) v1 = np.array([1.0, 0.7], dtype=real) vertices = np.array([v0, v1], dtype=real).T shape = Shape(ShapeType.SEGMENT, vertices) for _io in range(1, 9): # --- DECLARE FUNCTION f = lambda x: np.exp(x[0]) * np.sin(x[0]) + 3.0 f_quadpy = lambda x: np.exp(np.array(x)) * np.sin(np.array(x)) + 3.0 f_scipy = lambda x: np.exp(x) * np.sin(x) + 3.0 # --- GET H20 ESTIMATION val_num = 0.0 shape_quadrature_points = shape.get_quadrature_points(_io) shape_quadrature_weights = shape.get_quadrature_weights(_io) shape_quadrature_size = shape.get_quadrature_size(_io) for _qc in range(shape_quadrature_size): x_qc = shape_quadrature_points[:, _qc] w_qc = shape_quadrature_weights[_qc] s_qc = (shape.get_rotation_matrix() @ x_qc)[:-1] val_num += w_qc * f(s_qc) vertices_p = (shape.get_rotation_matrix() @ vertices)[:-1] # --- GET QUADPY ESTIMATION scheme = quadpy.c1.gauss_legendre(_io) val = scheme.integrate(f_quadpy, [vertices_p[0, 0], vertices_p[0, 1]]) # --- GET SCIPY ESTIMATION val_scp = integrate.quad(f_scipy, vertices_p[0, 0], vertices_p[0, 1]) if verbose: print("-- integration order : {}".format(_io)) print("val_h2O : {}".format(val_num)) print("val_qud : {}".format(val)) print("val_scp : {}".format(val_scp)) x_c = shape.get_centroid() plt.scatter(x_c[0], x_c[1], c="b") for i in range(2): plt.scatter(vertices[0, i], vertices[1, i], c="b") for _qc in range(shape_quadrature_size): _x_qc = shape_quadrature_points[:, _qc] plt.scatter(_x_qc[0], _x_qc[1], c="g") plt.show()
def get_gradient_projection_vector(cell: Shape, function: Callable): _d = euclidean_dimension _dx = field.field_dimension _ck = cell_basis_k.dimension # x_c = cell.centroid h_c = cell.diameter _io = finite_element.construction_integration_order cell_quadrature_points = cell.get_quadrature_points(_io) cell_quadrature_weights = cell.get_quadrature_weights(_io) cell_quadrature_size = cell.get_quadrature_size(_io) matrix = np.zeros((_ck, _ck), dtype=real) vector = np.zeros((_ck,), dtype=real) for qc in range(cell_quadrature_size): x_q_c = cell_quadrature_points[:, qc] w_q_c = cell_quadrature_weights[qc] phi_k = cell_basis_k.evaluate_function(x_q_c, x_c, h_c) matrix += w_q_c * np.tensordot(phi_k, phi_k, axes=0) vector += w_q_c * phi_k * function(x_q_c) projection_vector = np.linalg.solve(matrix, vector) return projection_vector
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 test_reference_polyhedron_quadrature(self, verbose=True): """ V8 o_______________o V7 /| V6 /| / | o / | V4 o_______________o V5 | | | | V3 | o___________ |__o V2 Z | / | / ^ Y |/ |/ |/ V0 o_______________o V1 0---> X Args: verbose: """ v0 = np.array([0.0, 0.0, 0.0], dtype=real) v1 = np.array([1.0, 0.0, 0.0], dtype=real) v2 = np.array([1.0, 1.0, 0.0], dtype=real) v3 = np.array([0.0, 1.0, 0.0], dtype=real) v4 = np.array([0.0, 0.0, 1.0], dtype=real) v5 = np.array([1.0, 0.0, 1.0], dtype=real) v6 = np.array([0.5, 0.5, 1.0], dtype=real) v7 = np.array([1.0, 1.0, 1.0], dtype=real) v8 = np.array([0.0, 1.0, 1.0], dtype=real) vertices = np.array([v0, v1, v2, v3, v4, v5, v6, v7, v8], dtype=real).T # --- CONNECTIVITY, COUNTER CLOCK WISE # connectivity = [ # [0, 3, 2, 1], # [0, 1, 5, 4], # [1, 2, 7, 5], # [2, 3, 8, 7], # [3, 0, 4, 8], # [4, 5, 6], # [5, 7, 6], # [7, 8, 6], # [8, 4, 6], # ] # --- CONNECTIVIY, CLOCK WISE connectivity = [ [0, 1, 2, 3], [0, 4, 5, 1], [1, 5, 7, 2], [2, 7, 8, 3], [3, 8, 4, 0], [6, 5, 4], [6, 7, 5], [6, 8, 7], [6, 4, 8], ] shape = Shape(ShapeType.POLYHEDRON, vertices, connectivity=connectivity) for _io in range(1, 9): # --- DECLARE FUNCTION f = lambda x: np.exp(x[0]) * np.sin(x[0] * x[1] / (x[2] + 0.003) ) + x[1] * x[2] + 3.0 f_scipy = lambda x, y, z: np.exp(x) * np.sin(x * y / (z + 0.003) ) + y * z + 3.0 # --- GET QUADPY ESTIMATION scheme = quadpy.c3.get_good_scheme(_io) val = scheme.integrate( f, [[[v0, v4], [v3, v8]], [[v1, v5], [v2, v7]]]) # --- GET H20 ESTIMATION val_num = 0.0 shape_quadrature_points = shape.get_quadrature_points(_io) shape_quadrature_weights = shape.get_quadrature_weights(_io) shape_quadrature_size = shape.get_quadrature_size(_io) for _qc in range(shape_quadrature_size): x_qc = shape_quadrature_points[:, _qc] w_qc = shape_quadrature_weights[_qc] val_num += w_qc * f(x_qc) # --- GET SCIPY ESTIMATION # val_scp = integrate.tplquad( # f_scipy, 0.0, 1.0, lambda x: 0.0, lambda x: 1.0, lambda x, y: 0.0, lambda x, y: 1.0 # ) if verbose: print("-- integration order : {}".format(_io)) print("val_h2O : {}".format(val_num)) print("val_qud : {}".format(val)) # print("val_scp : {}".format(val_scp)) x_c = shape.get_centroid() fig = plt.figure() ax = fig.add_subplot(111, projection="3d") ax.scatter(x_c[0], x_c[1], x_c[2], c="b", marker="o") for i in range(vertices.shape[1]): ax.scatter(vertices[0, i], vertices[1, i], vertices[2, i], c="b", marker="o") for _qc in range(shape_quadrature_size): _x_qc = shape_quadrature_points[:, _qc] ax.scatter(_x_qc[0], _x_qc[1], _x_qc[2], c="g") plt.show()
def test_reference_polyhedron_cell(self, verbose=True): """ V3 o________________o V2 /| /| / | / | / | / | Y / | / | ^ V7 o________________o V6 | | | | | | 0---> X | V0 o___________|____o V1 / | / | / Z | / | / | / | / |/ |/ V4 o________________o V5 V3 o________________o V2 /| /| / | / | / | / | Y / | / | ^ V8 o________________o V7 | | | | | | 0---> X | V0 o___________|____o V1 / | / | / Z | / o V6 | / | / | / |/ |/ V4 o________________o V5 V2 o |\.. | \.. | \.. | \.. | \.. | \ o_V0_____________o V1 | / ..../ / ..../ / / ..../ :/.../ V2 o Args: verbose: Returns: """ euclidean_dimension = 3 polynomial_orders = [1, 2, 3] element_types = [ ElementType.HDG_LOW, ElementType.HDG_EQUAL, ElementType.HDG_HIGH ] for polynomial_order in polynomial_orders: for element_type in element_types: # --- DEFINE POLYNOMIAL ORDER AND INTEGRATION ORDER finite_element = FiniteElement( element_type=element_type, polynomial_order=polynomial_order, euclidean_dimension=euclidean_dimension, ) # --- DEFINE POLYNOMIAL BASIS cell_basis_k = finite_element.cell_basis_k cell_basis_l = finite_element.cell_basis_l # --- DEFINE RANDOM POLYNOMIAL COEFFICIENTS range_min = -3.0 range_max = +3.0 coefficients_k = np.array([ uniform(range_min, range_max) for _i in range(cell_basis_k.dimension) ]) coefficients_l = np.array([ uniform(range_min, range_max) for _i in range(cell_basis_l.dimension) ]) if verbose: print("COEFS_K : \n{}".format(coefficients_k)) print("COEFS_L : \n{}".format(coefficients_l)) # --- DEFINE MONOMIAL VALUES COMPUTATION def test_function(polynomial_ord: int, point: ndarray, centroid: ndarray, diameter: float, coefficients: ndarray) -> float: basis = Monomial(polynomial_ord, euclidean_dimension) value = 0.0 for _i, _exponent in enumerate(basis.exponents): prod = 1.0 for _x_dir in range(basis.exponents.shape[1]): prod *= ((point[_x_dir] - centroid[_x_dir]) / diameter)**_exponent[_x_dir] prod *= coefficients[_i] value += prod return value def test_function_derivative( polynomial_ord: int, point: ndarray, centroid: ndarray, diameter: float, direction: int, coefficients: ndarray, ) -> float: basis = Monomial(polynomial_ord, euclidean_dimension) value = 0.0 for _i, _exponent in enumerate(basis.exponents): prod = 1.0 for _x_dir in range(basis.exponents.shape[1]): if _x_dir == direction: # _pt0 = point[_x_dir] - centroid[_x_dir] # _pt1 = _pt0 / diameter # if _exponent[_x_dir] == 0: # _exp = _exponent[_x_dir] # else: # _exp = _exponent[_x_dir] - 1 # _pt2 = _pt1 ** _exp if _exponent[_x_dir] != 0: prod *= (_exponent[_x_dir] / diameter) * ( ((point[_x_dir] - centroid[_x_dir]) / diameter)**(_exponent[_x_dir] - 1)) else: prod *= 0.0 # prod *= (_exponent[_x_dir] / diameter) * _pt2 else: prod *= ((point[_x_dir] - centroid[_x_dir]) / diameter)**_exponent[_x_dir] prod *= coefficients[_i] value += prod return value # --- DEFINE TRIANGLE COORDINATES v0 = np.array([0.0, 0.0, 0.0], dtype=real) v1 = np.array([1.0, 0.0, 0.0], dtype=real) v2 = np.array([1.0, 1.0, 0.0], dtype=real) v3 = np.array([0.0, 1.0, 0.0], dtype=real) v4 = np.array([0.0, 0.0, 1.0], dtype=real) v5 = np.array([1.0, 0.0, 1.0], dtype=real) v6 = np.array([0.5, 0.5, 1.0], dtype=real) v7 = np.array([1.0, 1.0, 1.0], dtype=real) v8 = np.array([0.0, 1.0, 1.0], dtype=real) vertices = np.array([v0, v1, v2, v3, v4, v5, v6, v7, v8], dtype=real).T # --- CONNECTIVITY, COUNTER CLOCK WISE # connectivity = [ # [0, 3, 2, 1], # [0, 1, 5, 4], # [1, 2, 7, 5], # [2, 3, 8, 7], # [3, 0, 4, 8], # [4, 5, 6], # [5, 7, 6], # [7, 8, 6], # [8, 4, 6], # ] # --- CONNECTIVIY, CLOCK WISE connectivity = [ [0, 1, 2, 3], [0, 4, 5, 1], [1, 5, 7, 2], [2, 7, 8, 3], [3, 8, 4, 0], [6, 5, 4], [6, 7, 5], [6, 8, 7], [6, 4, 8], ] # --- BUILD CELL shape = Shape(ShapeType.POLYHEDRON, vertices, connectivity=connectivity) x_c = shape.get_centroid() h_c = shape.get_diameter() _io = finite_element.construction_integration_order cell_quadrature_points = shape.get_quadrature_points(_io) cell_quadrature_weights = shape.get_quadrature_weights(_io) cell_quadrature_size = shape.get_quadrature_size(_io) # --- CHECK INTEGRATION IN CELL bases = [cell_basis_k, cell_basis_l] # orders = [face_polynomial_order, cell_polynomial_order] coefs = [coefficients_k, coefficients_l] # scheme = quadpy.t2.get_good_scheme(2 * finite_element.construction_integration_order) scheme = quadpy.c3.get_good_scheme( finite_element.construction_integration_order) for basis_0, coef_0 in zip(bases, coefs): order_0 = basis_0.polynomial_order for basis_1, coef_1 in zip(bases, coefs): order_1 = basis_1.polynomial_order for _i in range(euclidean_dimension): for _j in range(euclidean_dimension): mass_mat = np.zeros( (basis_0.dimension, basis_1.dimension), dtype=real) stif_mat = np.zeros( (basis_0.dimension, basis_1.dimension), dtype=real) advc_mat = np.zeros( (basis_0.dimension, basis_1.dimension), dtype=real) for _qc in range(cell_quadrature_size): _x_qc = cell_quadrature_points[:, _qc] _w_qc = cell_quadrature_weights[_qc] phi_0 = basis_0.evaluate_function( _x_qc, x_c, h_c) phi_1 = basis_1.evaluate_function( _x_qc, x_c, h_c) d_phi_0_i = basis_0.evaluate_derivative( _x_qc, x_c, h_c, _i) d_phi_1_j = basis_1.evaluate_derivative( _x_qc, x_c, h_c, _j) mass_mat += _w_qc * np.tensordot( phi_0, phi_1, axes=0) stif_mat += _w_qc * np.tensordot( d_phi_0_i, d_phi_1_j, axes=0) advc_mat += _w_qc * np.tensordot( phi_0, d_phi_1_j, axes=0) mass_integral = coef_0 @ mass_mat @ coef_1 stif_integral = coef_0 @ stif_mat @ coef_1 advc_integral = coef_0 @ advc_mat @ coef_1 f_mass_check = lambda x: test_function( order_0, x, x_c, h_c, coef_0 ) * test_function(order_1, x, x_c, h_c, coef_1) f_stif_check = lambda x: test_function_derivative( order_0, x, x_c, h_c, _i, coef_0 ) * test_function_derivative( order_1, x, x_c, h_c, _j, coef_1) f_advc_check = lambda x: test_function( order_0, x, x_c, h_c, coef_0 ) * test_function_derivative( order_1, x, x_c, h_c, _j, coef_1) mass_integral_check = scheme.integrate( f_mass_check, [[[v0, v4], [v3, v8]], [[v1, v5], [v2, v7]]]) stif_integral_check = scheme.integrate( f_stif_check, [[[v0, v4], [v3, v8]], [[v1, v5], [v2, v7]]]) advc_integral_check = scheme.integrate( f_advc_check, [[[v0, v4], [v3, v8]], [[v1, v5], [v2, v7]]]) rtol = 1.0e-12 atol = 1.0e-12 if verbose: print( "MASS INTEGRAL CHECK | ORDER : {} | ELEM : {} | dir {}, {}, | order {}, {}" .format(polynomial_order, element_type, _i, _j, order_0, order_1)) print("- QUADPY : {}".format( mass_integral_check)) print("- H2O : {}".format(mass_integral)) print( "STIFFNESS INTEGRAL CHECK | ORDER : {} | ELEM : {} | dir {}, {} | order {}, {}" .format(polynomial_order, element_type, _i, _j, order_0, order_1)) print("- QUADPY : {}".format( stif_integral_check)) print("- H2O : {}".format(stif_integral)) print( "ADVECTION INTEGRAL CHECK | ORDER : {} | ELEM : {} | dir {}, {} | order {}, {}" .format(polynomial_order, element_type, _i, _j, order_0, order_1)) print("- QUADPY : {}".format( advc_integral_check)) print("- H2O : {}".format(advc_integral)) np.testing.assert_allclose(mass_integral_check, mass_integral, rtol=rtol, atol=atol) np.testing.assert_allclose(stif_integral_check, stif_integral, rtol=rtol, atol=atol) np.testing.assert_allclose(advc_integral_check, advc_integral, rtol=rtol, atol=atol)