def simple_rhs_assemble(mesh, f_grabber, kernel): rhs = np.zeros(mesh.total_dofs) for e_k in mesh: rhs_k_basis = (e_k.basis if not kernel.test_gradient else e_k.basis.get_gradient_basis()) for i in range(e_k.basis.n_fncs): for e_l in mesh: rhs_l_basis = f_grabber(e_l) rhs_l_basis = (rhs_l_basis if not kernel.soln_gradient else rhs_l_basis.get_gradient_basis()) (quad_outer, quad_inner) = e_k.qs.get_quadrature( kernel.singularity_type, e_k, e_l) for j in range(e_l.basis.n_fncs): value = fl.double_integral( e_k.mapping.eval, e_l.mapping.eval, kernel, rhs_k_basis, rhs_l_basis, quad_outer, quad_inner, i, j) rhs[e_k.dofs[0, i]] += value[0][0] rhs[e_k.dofs[0, i]] += value[0][1] rhs[e_k.dofs[1, i]] += value[1][0] rhs[e_k.dofs[1, i]] += value[1][1] return rhs
def test_realistic_double_integral_symmetry(): msh = simple_line_mesh(2) bf = basis_funcs.basis_from_degree(1) qs = quad_strategy.QuadStrategy(msh, 10, 10, 10, 10) kernel = DisplacementKernel(1.0, 0.25) # fnc = lambda r, n: 1 / r[0] one = double_integral(msh.elements[1].mapping.eval, msh.elements[1].mapping.eval, kernel, bf, bf, qs.get_simple(), qs.quad_logr, 0, 1) two = double_integral(msh.elements[1].mapping.eval, msh.elements[1].mapping.eval, kernel, bf, bf, qs.get_simple(), qs.quad_logr, 1, 0) one = np.array(one) two = np.array(two) np.testing.assert_almost_equal(one, two)
def test_exact_dbl_integrals_H_same_element(): msh = simple_line_mesh(1) qs = quad_strategy.QuadStrategy(msh, 10, 10, 10, 10) qo = qs.get_simple() qi = qs.quad_oneoverr bf = basis_funcs.basis_from_degree(1) kernel = TractionKernel(1.0, 0.25) H_00 = double_integral(msh.elements[0].mapping.eval, msh.elements[0].mapping.eval, kernel, bf, bf, qo, qi, 0, 0) np.testing.assert_almost_equal(H_00, np.zeros((2, 2)), 3) H_11 = double_integral(msh.elements[0].mapping.eval, msh.elements[0].mapping.eval, kernel, bf, bf, qo, qi, 1, 1) np.testing.assert_almost_equal(H_11, np.zeros((2, 2)), 3) H_01 = double_integral(msh.elements[0].mapping.eval, msh.elements[0].mapping.eval, kernel, bf, bf, qo, qi, 0, 1) H_01_exact = np.array([[0.0, 1 / (6 * np.pi)], [-1 / (6 * np.pi), 0.0]]) np.testing.assert_almost_equal(H_01, H_01_exact, 3) H_10 = double_integral(msh.elements[0].mapping.eval, msh.elements[0].mapping.eval, kernel, bf, bf, qo, qi, 1, 0) H_10_exact = np.array([[0.0, -1 / (6 * np.pi)], [1 / (6 * np.pi), 0.0]]) np.testing.assert_almost_equal(H_10, H_10_exact, 3)
def test_exact_dbl_integrals_G_different_element(): msh = simple_line_mesh(2) bf = basis_funcs.basis_from_degree(1) qs = quad_strategy.QuadStrategy(msh, 10, 10, 10, 10) qo = qs.get_simple() qi = qs.quad_logr kernel = DisplacementKernel(1.0, 0.25) G_00 = double_integral(msh.elements[0].mapping.eval, msh.elements[1].mapping.eval, kernel, bf, bf, qo, qi, 0, 0) G_10 = double_integral(msh.elements[0].mapping.eval, msh.elements[1].mapping.eval, kernel, bf, bf, qo, qi, 1, 0) G_01 = double_integral(msh.elements[0].mapping.eval, msh.elements[1].mapping.eval, kernel, bf, bf, qo, qi, 0, 1) G_11 = double_integral(msh.elements[0].mapping.eval, msh.elements[1].mapping.eval, kernel, bf, bf, qo, qi, 1, 1) np.testing.assert_almost_equal(G_10, [[0.02833119, 0], [0, 0.01506828]], 4) np.testing.assert_almost_equal(G_01, [[0.00663146, 0], [0, -0.00663146]], 4) np.testing.assert_almost_equal(G_00, [[0.0150739, 0], [0, 0.00181103]], 4) np.testing.assert_almost_equal(G_11, [[0.0150739, 0], [0, 0.00181103]], 4)
def test_exact_dbl_integrals_G_same_element(): msh = simple_line_mesh(1) bf = basis_funcs.basis_from_degree(1) qs = quad_strategy.QuadStrategy(msh, 10, 10, 10, 10) qo = qs.get_simple() qi = qs.quad_logr kernel = DisplacementKernel(1.0, 0.25) G_00 = double_integral(msh.elements[0].mapping.eval, msh.elements[0].mapping.eval, kernel, bf, bf, qo, qi, 0, 0) np.testing.assert_almost_equal(G_00, [[0.165187, 0], [0, 0.112136]], 4) G_10 = double_integral(msh.elements[0].mapping.eval, msh.elements[0].mapping.eval, kernel, bf, bf, qo, qi, 1, 0) np.testing.assert_almost_equal(G_10, [[0.112136, 0], [0, 0.0590839]], 4) G_01 = double_integral(msh.elements[0].mapping.eval, msh.elements[0].mapping.eval, kernel, bf, bf, qo, qi, 0, 1) np.testing.assert_almost_equal(G_01, [[0.112136, 0], [0, 0.0590839]], 4) G_11 = double_integral(msh.elements[0].mapping.eval, msh.elements[0].mapping.eval, kernel, bf, bf, qo, qi, 1, 1) np.testing.assert_almost_equal(G_11, [[0.165187, 0], [0, 0.112136]], 4)
def test_hypersingular_vs_regularized_across_elements(): # The regularization is only valid for a continuous basis, so the # integrations will not be equal unless I account for both elements. k_rh = RegularizedHypersingularKernel(1.0, 0.25) k_sh = SemiRegularizedHypersingularKernel(1.0, 0.25) k_h = HypersingularKernel(1.0, 0.25) K = 30 mesh = circular_mesh(K, 2.0) bf = basis_from_degree(2) grad_bf = bf.get_gradient_basis() qs = QuadStrategy(mesh, 10, 10, 10, 10) apply_to_elements(mesh, "basis", bf, non_gen = True) apply_to_elements(mesh, "continuous", True, non_gen = True) init_dofs(mesh) el1a = 15 el1b = 14 el2a = 25 el2b = 26 o_q, i_q = qs.get_quadrature('logr', mesh.elements[el1a], mesh.elements[el2a]) o_q = o_q # Four integrals for this matrix term. Two choices of source element # and two choices of solution element. a1 = double_integral(mesh.elements[el1a].mapping.eval, mesh.elements[el2a].mapping.eval, k_rh, grad_bf, grad_bf, o_q, i_q, 0, 2) a2 = double_integral(mesh.elements[el1a].mapping.eval, mesh.elements[el2b].mapping.eval, k_rh, grad_bf, grad_bf, o_q, i_q, 0, 0) a3 = double_integral(mesh.elements[el1b].mapping.eval, mesh.elements[el2a].mapping.eval, k_rh, grad_bf, grad_bf, o_q, i_q, 2, 2) a4 = double_integral(mesh.elements[el1b].mapping.eval , mesh.elements[el2b].mapping.eval, k_rh, grad_bf, grad_bf, o_q, i_q, 2, 0) b1 = double_integral(mesh.elements[el1a].mapping.eval , mesh.elements[el2a].mapping.eval, k_h, bf, bf, o_q, i_q, 0, 2) b2 = double_integral(mesh.elements[el1a].mapping.eval , mesh.elements[el2b].mapping.eval, k_h, bf, bf, o_q, i_q, 0, 0) b3 = double_integral(mesh.elements[el1b].mapping.eval , mesh.elements[el2a].mapping.eval, k_h, bf, bf, o_q, i_q, 2, 2) b4 = double_integral(mesh.elements[el1b].mapping.eval , mesh.elements[el2b].mapping.eval, k_h, bf, bf, o_q, i_q, 2, 0) c1 = double_integral(mesh.elements[el1a].mapping.eval , mesh.elements[el2a].mapping.eval, k_sh, grad_bf, bf, o_q, i_q, 0, 2) c2 = double_integral(mesh.elements[el1a].mapping.eval , mesh.elements[el2b].mapping.eval, k_sh, grad_bf, bf, o_q, i_q, 0, 0) c3 = double_integral(mesh.elements[el1b].mapping.eval , mesh.elements[el2a].mapping.eval, k_sh, grad_bf, bf, o_q, i_q, 2, 2) c4 = double_integral(mesh.elements[el1b].mapping.eval , mesh.elements[el2b].mapping.eval, k_sh, grad_bf, bf, o_q, i_q, 2, 0) a = np.array(a1) + np.array(a2) + np.array(a3) + np.array(a4) b = np.array(b1) + np.array(b2) + np.array(b3) + np.array(b4) c = np.array(c1) + np.array(c2) + np.array(c3) + np.array(c4) np.testing.assert_almost_equal(a, b) np.testing.assert_almost_equal(b, c) np.testing.assert_almost_equal(a, c)
def test_hypersingular_vs_regularized(): # By the regularization of the hypersingular integral, these two # integrations should give the same result. # I've left # LOTS OF DETECTIVE WORK! # in this function, because I had a fun (awful?) time figuring out # how to get these two integrations to match up... Took three (four?) # full days... # The integrations are only equal for an interior basis function. If # the basis function's support crosses two elements, the point n - 1 # dimensional term in the integration by parts still influences the # result k_rh = RegularizedHypersingularKernel(1.0, 0.25) k_sh = SemiRegularizedHypersingularKernel(1.0, 0.25) k_h = HypersingularKernel(1.0, 0.25) K = 30 mesh = circular_mesh(K, 2.0) bf = basis_from_degree(2) grad_bf = bf.get_gradient_basis() qs = QuadStrategy(mesh, 10, 10, 10, 10) apply_to_elements(mesh, "basis", bf, non_gen = True) apply_to_elements(mesh, "continuous", True, non_gen = True) init_dofs(mesh) el1 = 15 # pp0 = mesh.get_physical_point(el1, 0.5) # m = mesh.get_normal(el1, 0.5) a = np.zeros((K, 2, 2)) b = np.zeros((K, 2, 2)) c = np.zeros((K, 2, 2)) # qq = np.zeros((K, 2, 2)) # cr1 = np.zeros(K) # cr2 = np.zeros(K) # n2x = np.zeros(K) # n2y = np.zeros(K) # grad2x = np.zeros(K) # grad2y = np.zeros(K) # k_rh_val = np.zeros((K, 2, 2)) # k_h_val = np.zeros((K, 2, 2)) for el2 in range(K): if np.abs(el2 - el1) < 2.5: continue i = 1 j = 1 o_q, i_q = qs.get_quadrature('logr', mesh.elements[el1], mesh.elements[el2]) o_q = o_q a[el2, :, :] = double_integral(mesh.elements[el1].mapping.eval, mesh.elements[el2].mapping.eval, k_rh, grad_bf, grad_bf, o_q, i_q, i, j) b[el2, :, :] = double_integral(mesh.elements[el1].mapping.eval, mesh.elements[el2].mapping.eval, k_h, bf, bf, o_q, i_q, i, j) c[el2, :, :] = double_integral(mesh.elements[el1].mapping.eval, mesh.elements[el2].mapping.eval, k_sh, grad_bf, bf, o_q, i_q, i, j) # qq[el2, :, :] = double_integral(mesh, k_rh, bf, bf, # o_q, i_q, el1, 1, el2, 1) # # cr1[el2] = grad_bf.chain_rule(el1, 0.5)[0] # n2x[el2], n2y[el2] = mesh.get_normal(el2, 0.5) # grad2x[el2], grad2y[el2] = _get_deriv_point(mesh.basis_fncs.derivs, # mesh.coefficients, # el2, # 0.5) # cr2[el2] = -n2x[el2] * grad2y[el2] + n2y[el2] * grad2x[el2] # pp = mesh.get_physical_point(el2, 0.5) # k_rh_val[el2, :, :] = \ # k_rh.call(pp - pp0, m, np.array([n2x[el2], n2y[el2]])) # k_h_val[el2, :, :] = \ # k_h.call(pp - pp0, m, np.array([n2x[el2], n2y[el2]])) # #easiest comparison # from matplotlib import pyplot as plt # plt.plot(range(K), a[:, 1, 1], label='ayy') # plt.plot(range(K), b[:, 1, 1], label='byy') # plt.plot(range(K), c[:, 1, 1], label='cyy') # plt.plot(cr1 / 100.0) # plt.figure() # plt.plot(range(K), a[:, 1, 1, 0, 0], label='axx') # plt.plot(range(K), a[:, 0, 1], label='axy') # plt.plot(range(K), b[:, 1, 1, 0, 0], label='bxx') # plt.plot(range(K), b[:, 0, 1], label='bxy') # plt.plot(range(K), qq[:, 0, 0], label='other') # plt.plot(grad2x * n2x + grad2y ** 2) # plt.legend() # plt.figure() # plt.plot(a[:, 0, 0] / (1.0 * b[:, 0, 0])) # plt.plot(a[:, 1, 1] / (1.0 * b[:, 1, 1])) # plt.plot(a[:, 0, 1] / (1.0 * b[:, 0, 1])) # plt.ylim([-1.5, 1.5]) # # plt.plot(grad2x, label='gradx') # # plt.plot(grad2y, label='grady') # # plt.plot(n2y, label='normal') # plt.figure() # # plt.plot(k_rh_val[:, 0, 0], label='regularized') # # plt.plot(k_h_val[:, 0, 0], label='hyp') # plt.plot(k_h_val[:, 0, 0] / k_rh_val[:, 0, 0], label='divided') # plt.legend() # plt.figure() # plt.plot(n2y, label='normal') # plt.plot(cr2, label='cr') # plt.legend() # plt.show() np.testing.assert_almost_equal(a, b, 2) np.testing.assert_almost_equal(a, c, 2) np.testing.assert_almost_equal(b, c, 2)
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]
def time_dbl_integral(): for i in range(10000): a = fp.double_integral(msh.elements[0].mapping.eval, msh.elements[4].mapping.eval, k_d, bf, bf, o_q, i_q, 0, 0)