def test_displacement_discontinuity_derivative(): bf = basis_from_degree(1) msh = simple_line_mesh(2) qs = QuadStrategy(msh, 10, 10, 10, 10) apply_to_elements(msh, "basis", bf, non_gen = True) apply_to_elements(msh, "continuous", True, non_gen = True) apply_to_elements(msh, "qs", qs, non_gen = True) init_dofs(msh) k_rh = RegularizedHypersingularKernel(1.0, 0.25) # basis function should be equal to x_hat k = 1 i = 1 qi = qs.get_simple() strength = ConstantBasis([1.0, 1.0]) k_rh.set_interior_data(np.array([-2.0, 0.0]), np.array([0.0, 1.0])) basis = bf.get_gradient_basis() result = single_integral(msh.elements[k].mapping.eval, k_rh, strength, basis, qi, 0, i) np.testing.assert_almost_equal(result[1][1], 0.193011, 4) np.testing.assert_almost_equal(result[0][0], -0.0191957, 4) i = 0 result = single_integral(msh.elements[k].mapping.eval, k_rh, strength, basis, qi, 0, i) np.testing.assert_almost_equal(result[1][1], -0.193011, 4) np.testing.assert_almost_equal(result[0][0], 0.0191957, 4) strlocnorm = [((1.0, 0.0), np.array([-2.0, 0.0]), np.zeros(2))] rhs = point_source_rhs(msh, strlocnorm, k_rh)
def test_improved_hypersingular(): mesh = simple_line_mesh(1, (0, 0), (1, 0)) mapping = PolynomialMapping(mesh.elements[0]) degree = 7 bf = gll_basis(degree) one = ConstantBasis(np.ones(2)) quad_info_exact = gauss(100) a = 0.01 b = 0.05 mapped_ay = map_singular_pt(a, 0.0, 1.0) mapped_by = map_distance_to_interval(b, 0.0, 1.0) quad_deg = degree + 4 moments_xa0_r0 = legendre.legendre_integrals(quad_deg) moments_xa0_r2 = modify_divide_r2( quad_deg, moments_xa0_r0, mapped_ay, mapped_by, mu_2_0(mapped_ay, mapped_by), mu_2_1(mapped_ay, mapped_by) ) moments_xa0_r4 = modify_divide_r2( quad_deg, moments_xa0_r2, mapped_ay, mapped_by, mu_4_0(mapped_ay, mapped_by), mu_4_1(mapped_ay, mapped_by) ) moments_xa0_r6 = modify_divide_r2( quad_deg, moments_xa0_r4, mapped_ay, mapped_by, mu_6_0(mapped_ay, mapped_by), mu_6_1(mapped_ay, mapped_by) ) moments_xa1_r6 = modify_times_x_minus_a(len(moments_xa0_r6) - 2, moments_xa0_r6, mapped_ay) moments_xa2_r6 = modify_times_x_minus_a(len(moments_xa1_r6) - 2, moments_xa1_r6, mapped_ay) moments_xa3_r6 = modify_times_x_minus_a(len(moments_xa2_r6) - 2, moments_xa2_r6, mapped_ay) moments_xa4_r6 = modify_times_x_minus_a(len(moments_xa3_r6) - 2, moments_xa3_r6, mapped_ay) est = [[0, 0], [0, 0]] x, w = recursive_quad(moments_xa0_r6[: degree + 1]) x, w = map_pts_wts(x, w, 0.0, 1.0) w = map_weights_by_inv_power(w, 6.0, 0.0, 1.0) * ((-b / 2) ** 2) * ((-2 * b) ** 2) est[1][1] = w[0] x, w = recursive_quad(moments_xa1_r6[: degree + 1]) x, w = map_pts_wts(x, w, 0.0, 1.0) w = map_weights_by_inv_power(w, 6.0, 0.0, 1.0) * ((-b / 2) ** 2) * ((-2 * b) ** 1) est[0][1] = w[0] est[1][0] = w[0] x, w = recursive_quad(moments_xa2_r6[: degree + 1]) x, w = map_pts_wts(x, w, 0.0, 1.0) w = map_weights_by_inv_power(w, 6.0, 0.0, 1.0) * ((-b / 2) ** 2) * ((-2 * b) ** 0) est[0][0] = w[0] # qi = QuadratureInfo(a, x, w) kernelv1 = HypersingularPart1V1() kernelv2 = HypersingularPart1V2() pt = [a, b] normal = [0.0, 1.0] kernelv1.set_interior_data(pt, normal) kernelv2.set_interior_data(pt, normal) integrate = lambda qi, k: single_integral(mapping.eval, k, one, bf, qi, 0, 0) exact = integrate(quad_info_exact, kernelv1) np.testing.assert_almost_equal(np.array(exact), np.array(est), 10)
def single_integral_wrapper(map_eval, kernel, basis, quad_info, which_fnc): """ A wrapper so that single integral has the interface expected by the interior point computation functions. """ return single_integral(map_eval, kernel, one, basis, quad_info, 0, which_fnc)
def test_M_integral_diff_dof(): msh = simple_line_mesh(2) q = quadrature.gauss(2) bf = basis_funcs.basis_from_degree(1) kernel = MassMatrixKernel(0, 0) M_local = single_integral(msh.elements[0].mapping.eval, kernel, bf, bf, q, 0, 1) # integral of (1-x)*x from 0 to 1 np.testing.assert_almost_equal(M_local[0][0], 1.0 / 6.0)
def test_M_integral_same_dof_with_jacobian(): msh = simple_line_mesh(4) q = quadrature.gauss(2) bf = basis_funcs.basis_from_degree(1) kernel = MassMatrixKernel(0, 0) M_local = single_integral(msh.elements[0].mapping.eval, kernel, bf, bf, q, 0, 0) # Element size divided by two so the M value should be divided by two np.testing.assert_almost_equal(M_local[0][0], 1.0 / 6.0)
def test_telles_quad_strategy(): msh = simple_line_mesh(4) tqs = TellesQuadStrategy(4) qi = tqs.get_interior_quadrature(msh.elements[3], [0.0, 0.0]) kernel = TractionKernel(1.0, 0.25) one = ConstantBasis((1.0, 1.0)) est = single_integral(msh.elements[3].mapping.eval, kernel, one, one, qi, 0, 0) exact = -0.0367726 np.testing.assert_almost_equal(exact, est[0][1])
def test_plot_single_integral_kernel(): msh = simple_line_mesh(2) x = np.linspace(0.0, 1, 1000) kernel = TractionKernel(1.0, 0.25) bf = basis_funcs.basis_from_degree(8) bf1 = ConstantBasis((1.0, 1.0)) k = np.zeros_like(x) k_int = np.zeros_like(x) for (i, x_val) in enumerate(x): q = quadrature.piessens(16, x_val, 16) kernel.set_interior_data([x_val, 0.0], [0.0,1.0]) kd = kernel.get_interior_integral_data([1.0, 0.0], [0.0, 1.0]) k[i] = kernel._call(kd, 0, 1) k_int[i] = single_integral(msh.elements[1].mapping.eval, kernel, bf1, bf, q, 0, 4)[0][1]
def test_fast_lobatto(): N = 15 mesh = simple_line_mesh(1, (0, 0), (1, 0)) mapping = PolynomialMapping(mesh.elements[0]) kernel = TractionKernel(1.0, 0.25) bf = gll_basis(N) one = ConstantBasis(np.ones(2)) quad_info_old = lobatto(N + 1) pt = [0.0, -5.0] normal = [0.0, 1.0] kernel.set_interior_data(pt, normal) est_slow = single_integral(mapping.eval, kernel, one, bf, quad_info_old, 0, 0) est_fast = aligned_single_integral(mapping.eval, kernel, bf, quad_info_old, 0) np.testing.assert_almost_equal(np.array(est_slow), np.array(est_fast))
def _element_mass(matrix, e_k): # Because the term is identical (just replace u by t) for both # integral equations, this function does not care about the BC type bc_basis = e_k.bc.basis if type(bc_basis) is ZeroBasis: return q_info = e_k.qs.get_nonsingular_minpts() kernel = MassMatrixKernel(0, 0) for i in range(e_k.basis.n_fncs): for j in range(bc_basis.n_fncs): M_local = single_integral(e_k.mapping.eval, kernel, e_k.basis, bc_basis, q_info, i, j) matrix[e_k.dofs[0, i], e_k.dofs[0, j]] += M_local[0][0] matrix[e_k.dofs[1, i], e_k.dofs[1, j]] += M_local[1][1]
def test_gauss_displacement_xy(): mesh = simple_line_mesh(1, (0, 0), (1, 0)) mapping = PolynomialMapping(mesh.elements[0]) kernel = TractionKernel(1.0, 0.25) degree = 4 bf = gll_basis(degree) one = ConstantBasis(np.ones(2)) quad_info_exact = gauss(100) quad_info = lobatto(degree + 1) # Testing GLL basis and quadrature combination on the nonsingular part # of the displacement kernel. pt = [0.5, 1000.0] normal = [0.0, 1.0] kernel.set_interior_data(pt, normal) integrate = lambda qi: single_integral(mapping.eval, kernel, one, bf, qi, 0, 0) exact = integrate(quad_info_exact) est = integrate(quad_info) np.testing.assert_almost_equal(exact[0][1], est[0][1], 16)
def test_rl_integral(): mesh = simple_line_mesh(1, (0, 0), (1, 0)) mapping = PolynomialMapping(mesh.elements[0]) kernel = TractionKernel(1.0, 0.25) bf = gll_basis(4) one = ConstantBasis(np.ones(2)) quad_info_old = lobatto(5) x_bf = np.array(bf.nodes) x_q = np.array(quad_info_old.x) distance = 5.0 quad_info_new = rl_quad(5, 0.0, distance) # This one is comparing lobatto quadrature and recursive legendre quadrature # on the TractionKernel which is 1/r singular. pt = [0.0, -distance] normal = [0.0, 1.0] # exact = 0.2473475767 exact = 0.00053055607635 integrate = lambda qi: single_integral(mapping.eval, kernel, one, bf, qi, 0, 0) aligned_integrate = lambda qi: aligned_single_integral(mapping.eval, kernel, bf, qi, 0) kernel.set_interior_data(pt, normal) est_gauss = integrate(quad_info_old) np.testing.assert_almost_equal(est_gauss[0][0], exact) est_gauss_fast = aligned_integrate(quad_info_old) np.testing.assert_almost_equal(est_gauss_fast[0][0], exact) # This stuff doesn't work yet est_new = integrate(quad_info_new) np.testing.assert_almost_equal(est_new[0][0], exact, 6) est_new_fast = aligned_integrate(quad_info_new) np.testing.assert_almost_equal(est_new_fast[0][0], exact, 6)
def _element_pair(matrix, e_k, e_l, which_kernels, rhs_or_matrix): # Determine whether to use the boundary condition or the solution basis # as the inner basis function if rhs_or_matrix == "rhs": init_e_l_basis = e_l.bc.basis else: init_e_l_basis = e_l.basis # If either of the bases are the zero basis, then don't compute # anything if type(e_k.basis) is ZeroBasis or \ type(init_e_l_basis) is ZeroBasis: return # Determine which kernel and which bases to use kernel, factor = which_kernels[e_k.bc.type][e_l.bc.type][rhs_or_matrix] if kernel is None: return # Decide whether to use the basis or its gradient e_k_basis, e_k_pt_srcs = _choose_basis(e_k.basis, kernel.test_gradient) e_l_basis, e_l_pt_srcs = _choose_basis(init_e_l_basis, kernel.soln_gradient) # Now that we might have taken a derivative, check for ZeroBases again. if type(e_k_basis) is ZeroBasis: return # Determine what quadrature formula to use quad_outer, quad_inner = e_k.qs.get_quadrature( kernel.singularity_type, e_k, e_l) # Handle point sources # Filter out the point sources that we can safely ignore # many of these will be ignored because there will be an equal and # opposite point source contribution from the adjacent element. # TODO! # Currently, I ignore all point source on the test function side # of the problem, because these should be handled by the continuity # of the displacement field. I should probably think about this # a bit more... e_k_pt_srcs = [[],[]] # This probably explains some of the problems I was having with the # constant traction crack problem. # I also ignore all point source if we are dealing if rhs_or_matrix == "matrix": e_l_pt_srcs = [[],[]] # Loop over point sources and integrate! # All cross multiplications are necessary. # the pt sources are tuples like ((node, str_x, str_y), local_dof) # for e_k_pt in e_k_pt_srcs: # phys_pt_k = e_k.mapping.get_physical_point(e_k_pt[0][0]) # kernel.set_interior_data(phys_pt_k, # for j in range(e_l.basis.n_fncs): # pass # for e_l_pt in e_k_pt_srcs: # phys_pt_l = e_l.mapping.get_physical_point(e_l_pt[0][0]) e_l_pt_left = None e_l_pt_right = None if e_l_pt_srcs != [[],[]] and (e_l.neighbors_left == [] or e_l.neighbors_left[0].bc.type != 'traction'): e_l_pt_left = e_l_pt_srcs[0][0] if e_l_pt_srcs != [[],[]] and (e_l.neighbors_right == [] or e_l.neighbors_right[0].bc.type != 'traction'): e_l_pt_right = e_l_pt_srcs[0][1] for i in range(e_k.basis.n_fncs): for pt_src_idx, e_l_pt in enumerate([e_l_pt_left, e_l_pt_right]): if e_l_pt is None: continue e_l_dof = e_l_pt_srcs[1][pt_src_idx] phys_pt_l = e_l.mapping.get_physical_point(e_l_pt[0]) normal_l = e_l.mapping.get_normal(e_l_pt[0]) strength = ConstantBasis([e_l_pt[1], e_l_pt[2]]) kernel.set_interior_data(phys_pt_l, normal_l) integral = single_integral(e_k.mapping.eval, kernel, e_k_basis, strength, quad_outer, i, 0) for idx1 in range(2): for idx2 in range(2): matrix[e_k.dofs[idx1, i], e_l.dofs[idx2, e_l_dof]] += \ factor * integral[idx1][idx2] if type(e_l_basis) is ZeroBasis: return # Handle the integration of pairs of basis functions for i in range(e_k.basis.n_fncs): for j in range(e_l.basis.n_fncs): integral = \ double_integral(e_k.mapping.eval, e_l.mapping.eval, kernel, e_k_basis, e_l_basis, quad_outer, quad_inner, i, j) # Add the integrated term in the appropriate location for idx1 in range(2): for idx2 in range(2): matrix[e_k.dofs[idx1, i], e_l.dofs[idx2, j]] +=\ factor * integral[idx1][idx2]