def test_laplace_double_layer_evaluator(default_parameters, helpers, precision, device_interface): """Test dense evaluator for the Laplace dlp with p0 basis.""" from bempp.api import function_space from bempp.api.operators.boundary.laplace import double_layer grid = helpers.load_grid("sphere") space1 = function_space(grid, "DP", 0) space2 = function_space(grid, "DP", 0) discrete_op = double_layer( space1, space1, space2, assembler="dense_evaluator", parameters=default_parameters, device_interface=device_interface, precision=precision, ).weak_form() mat = double_layer( space1, space1, space2, assembler="dense", parameters=default_parameters, device_interface=device_interface, precision=precision, ).weak_form() x = _np.random.RandomState(0).rand(space1.global_dof_count) actual = discrete_op @ x expected = mat @ x
def laplace_multitrace_scaled(dirichl_space, neumann_space, scaling_factors, operator_assembler): A = bempp.api.BlockedOperator(2, 2) A[0, 0] = scaling_factors[0][0] * (-1.0) * laplace.double_layer( dirichl_space, dirichl_space, dirichl_space, assembler=operator_assembler) A[0, 1] = scaling_factors[0][1] * laplace.single_layer( neumann_space, dirichl_space, dirichl_space, assembler=operator_assembler) A[1, 0] = scaling_factors[1][0] * laplace.hypersingular( dirichl_space, neumann_space, neumann_space, assembler=operator_assembler) A[1, 1] = scaling_factors[1][1] * laplace.adjoint_double_layer( neumann_space, neumann_space, neumann_space, assembler=operator_assembler) return A
def derivative_ex(dirichl_space, neumann_space, ep_in, ep_ex, kappa, operator_assembler): """ Construct the system matrix and RHS grid functions using derivative formulation with interior values. """ phi_id = sparse.identity(dirichl_space, dirichl_space, dirichl_space) dph_id = sparse.identity(neumann_space, neumann_space, neumann_space) ep = ep_ex / ep_in dF = laplace.double_layer(dirichl_space, dirichl_space, dirichl_space, assembler=operator_assembler) dP = modified_helmholtz.double_layer(dirichl_space, dirichl_space, dirichl_space, kappa, assembler=operator_assembler) B = 1 / ep * dF - dP F = laplace.single_layer(neumann_space, dirichl_space, dirichl_space, assembler=operator_assembler) P = modified_helmholtz.single_layer(neumann_space, dirichl_space, dirichl_space, kappa, assembler=operator_assembler) A = F - P ddF = laplace.hypersingular(dirichl_space, neumann_space, neumann_space, assembler=operator_assembler) ddP = modified_helmholtz.hypersingular(dirichl_space, neumann_space, neumann_space, kappa, assembler=operator_assembler) D = 1 / ep * (ddP - ddF) dF0 = laplace.adjoint_double_layer(neumann_space, neumann_space, neumann_space, assembler=operator_assembler) dP0 = modified_helmholtz.adjoint_double_layer(neumann_space, neumann_space, neumann_space, kappa, assembler=operator_assembler) C = dF0 - 1.0 / ep * dP0 A_sys = bempp.api.BlockedOperator(2, 2) A_sys[0, 0] = (0.5 * (1.0 + (1.0 / ep)) * phi_id) + B A_sys[0, 1] = -A A_sys[1, 0] = D A_sys[1, 1] = (0.5 * (1.0 + (1.0 / ep)) * dph_id) - C return A_sys
def direct(dirichl_space, neumann_space, q, x_q, ep_in, ep_out, kappa): from bempp.api.operators.boundary import sparse, laplace, modified_helmholtz identity = sparse.identity(dirichl_space, dirichl_space, dirichl_space) slp_in = laplace.single_layer(neumann_space, dirichl_space, dirichl_space) dlp_in = laplace.double_layer(dirichl_space, dirichl_space, dirichl_space) slp_out = modified_helmholtz.single_layer(neumann_space, dirichl_space, dirichl_space, kappa) dlp_out = modified_helmholtz.double_layer(dirichl_space, dirichl_space, dirichl_space, kappa) # Matrix Assembly blocked = bempp.api.BlockedOperator(2, 2) blocked[0, 0] = 0.5*identity + dlp_in blocked[0, 1] = -slp_in blocked[1, 0] = 0.5*identity - dlp_out blocked[1, 1] = (ep_in/ep_out)*slp_out #A = blocked.strong_form() A = blocked @bempp.api.real_callable def charges_fun(x, n, domain_index, result): nrm = np.sqrt((x[0]-x_q[:,0])**2 + (x[1]-x_q[:,1])**2 + (x[2]-x_q[:,2])**2) aux = np.sum(q/nrm) result[0] = aux/(4*np.pi*ep_in) @bempp.api.real_callable def zero(x, n, domain_index, result): result[0] = 0 rhs_1 = bempp.api.GridFunction(dirichl_space, fun=charges_fun) rhs_2 = bempp.api.GridFunction(neumann_space, fun=zero) return A, rhs_1, rhs_2
def block_diagonal_precon_direct_external(dirichl_space, neumann_space, ep_in, ep_ex, kappa, permuted_rows=False): from scipy.sparse import diags, bmat from scipy.sparse.linalg import aslinearoperator from bempp.api.operators.boundary import sparse, laplace, modified_helmholtz # block-diagonal preconditioner identity = sparse.identity(dirichl_space, dirichl_space, dirichl_space) identity_diag = identity.weak_form().to_sparse().diagonal() slp_in_diag = laplace.single_layer( neumann_space, dirichl_space, dirichl_space, assembler="only_diagonal_part").weak_form().get_diagonal() dlp_in_diag = laplace.double_layer( dirichl_space, dirichl_space, dirichl_space, assembler="only_diagonal_part").weak_form().get_diagonal() slp_out_diag = modified_helmholtz.single_layer( neumann_space, dirichl_space, dirichl_space, kappa, assembler="only_diagonal_part").weak_form().get_diagonal() dlp_out_diag = modified_helmholtz.double_layer( neumann_space, dirichl_space, dirichl_space, kappa, assembler="only_diagonal_part").weak_form().get_diagonal() if permuted_rows: diag11 = 0.5 * identity_diag + dlp_in_diag diag12 = -(ep_ex / ep_in) * slp_in_diag diag21 = 0.5 * identity_diag - dlp_out_diag diag22 = slp_out_diag else: diag11 = 0.5 * identity_diag - dlp_out_diag diag12 = slp_out_diag diag21 = 0.5 * identity_diag + dlp_in_diag diag22 = -(ep_ex / ep_in) * slp_in_diag d_aux = 1 / (diag22 - diag21 * diag12 / diag11) diag11_inv = 1 / diag11 + 1 / diag11 * diag12 * d_aux * diag21 / diag11 diag12_inv = -1 / diag11 * diag12 * d_aux diag21_inv = -d_aux * diag21 / diag11 diag22_inv = d_aux block_mat_precond = bmat([[diags(diag11_inv), diags(diag12_inv)], [diags(diag21_inv), diags(diag22_inv)]]).tocsr() return aslinearoperator(block_mat_precond)
def alpha_beta_single_blocked_operator(dirichl_space, neumann_space, ep_in, ep_ex, kappa, alpha, beta, operator_assembler): dlp_in = laplace.double_layer(dirichl_space, dirichl_space, dirichl_space, assembler=operator_assembler) slp_in = laplace.single_layer(neumann_space, dirichl_space, dirichl_space, assembler=operator_assembler) hlp_in = laplace.hypersingular(dirichl_space, neumann_space, neumann_space, assembler=operator_assembler) adlp_in = laplace.adjoint_double_layer(neumann_space, neumann_space, neumann_space, assembler=operator_assembler) dlp_out = modified_helmholtz.double_layer(dirichl_space, dirichl_space, dirichl_space, kappa, assembler=operator_assembler) slp_out = modified_helmholtz.single_layer(neumann_space, dirichl_space, dirichl_space, kappa, assembler=operator_assembler) hlp_out = modified_helmholtz.hypersingular(dirichl_space, neumann_space, neumann_space, kappa, assembler=operator_assembler) adlp_out = modified_helmholtz.adjoint_double_layer( neumann_space, neumann_space, neumann_space, kappa, assembler=operator_assembler) phi_identity = sparse.identity(dirichl_space, dirichl_space, dirichl_space) dph_identity = sparse.identity(neumann_space, neumann_space, neumann_space) ep = ep_ex / ep_in A = bempp.api.BlockedOperator(2, 2) A[0, 0] = (-0.5 * (1 + alpha)) * phi_identity + (alpha * dlp_out) - dlp_in A[0, 1] = slp_in - ((alpha / ep) * slp_out) A[1, 0] = hlp_in - (beta * hlp_out) A[1, 1] = (-0.5 * (1 + (beta / ep))) * dph_identity + adlp_in - ((beta / ep) * adlp_out) return A
def juffer(dirichl_space, neumann_space, ep_in, ep_ex, kappa, operator_assembler): phi_id = sparse.identity(dirichl_space, dirichl_space, dirichl_space) dph_id = sparse.identity(neumann_space, neumann_space, neumann_space) ep = ep_ex / ep_in dF = laplace.double_layer(dirichl_space, dirichl_space, dirichl_space, assembler=operator_assembler) dP = modified_helmholtz.double_layer(dirichl_space, dirichl_space, dirichl_space, kappa, assembler=operator_assembler) L1 = (ep * dP) - dF F = laplace.single_layer(neumann_space, dirichl_space, dirichl_space, assembler=operator_assembler) P = modified_helmholtz.single_layer(neumann_space, dirichl_space, dirichl_space, kappa, assembler=operator_assembler) L2 = F - P ddF = laplace.hypersingular(dirichl_space, neumann_space, neumann_space, assembler=operator_assembler) ddP = modified_helmholtz.hypersingular(dirichl_space, neumann_space, neumann_space, kappa, assembler=operator_assembler) L3 = ddP - ddF dF0 = laplace.adjoint_double_layer(neumann_space, neumann_space, neumann_space, assembler=operator_assembler) dP0 = modified_helmholtz.adjoint_double_layer(neumann_space, neumann_space, neumann_space, kappa, assembler=operator_assembler) L4 = dF0 - ((1.0 / ep) * dP0) A = bempp.api.BlockedOperator(2, 2) A[0, 0] = (0.5 * (1.0 + ep) * phi_id) - L1 A[0, 1] = (-1.0) * L2 A[1, 0] = L3 # Sign change due to bempp definition A[1, 1] = (0.5 * (1.0 + (1.0 / ep)) * dph_id) - L4 return A
def laplaceMultitrace(dirichl_space, neumann_space): from bempp.api.operators.boundary import laplace A = bempp.api.BlockedOperator(2, 2) A[0, 0] = (-1.0)*laplace.double_layer(dirichl_space, dirichl_space, dirichl_space) A[0, 1] = laplace.single_layer(neumann_space, dirichl_space, dirichl_space) A[1, 0] = laplace.hypersingular(dirichl_space, neumann_space, neumann_space) A[1, 1] = laplace.adjoint_double_layer(neumann_space, neumann_space, neumann_space) return A
def lu(dirichl_space, neumann_space, ep_in, ep_ex, kappa, operator_assembler): dlp_in = laplace.double_layer(dirichl_space, dirichl_space, dirichl_space, assembler=operator_assembler) slp_in = laplace.single_layer(neumann_space, dirichl_space, dirichl_space, assembler=operator_assembler) hlp_in = laplace.hypersingular(dirichl_space, neumann_space, neumann_space, assembler=operator_assembler) adlp_in = laplace.adjoint_double_layer(neumann_space, neumann_space, neumann_space, assembler=operator_assembler) dlp_ex = modified_helmholtz.double_layer(dirichl_space, dirichl_space, dirichl_space, kappa, assembler=operator_assembler) slp_ex = modified_helmholtz.single_layer(neumann_space, dirichl_space, dirichl_space, kappa, assembler=operator_assembler) hlp_ex = modified_helmholtz.hypersingular(dirichl_space, neumann_space, neumann_space, kappa, assembler=operator_assembler) adlp_ex = modified_helmholtz.adjoint_double_layer( neumann_space, neumann_space, neumann_space, kappa, assembler=operator_assembler) phi_identity = sparse.identity(dirichl_space, dirichl_space, dirichl_space) dph_identity = sparse.identity(neumann_space, neumann_space, neumann_space) ep = ep_ex / ep_in A = bempp.api.BlockedOperator(2, 2) A[0, 0] = (0.5 * (1 + (1.0 / ep))) * phi_identity - dlp_ex + (1.0 / ep) * dlp_in A[0, 1] = slp_ex - slp_in A[1, 0] = (1.0 / ep) * hlp_ex - (1.0 / ep) * hlp_in A[1, 1] = (0.5 * (1 + (1.0 / ep))) * dph_identity + (1.0 / ep) * adlp_ex - adlp_in return A
def juffer(dirichl_space, neumann_space, q, x_q, ep_in, ep_ex, kappa): from bempp.api.operators.boundary import sparse, laplace, modified_helmholtz phi_id = sparse.identity(dirichl_space, dirichl_space, dirichl_space) dph_id = sparse.identity(neumann_space, neumann_space, neumann_space) ep = ep_ex / ep_in dF = laplace.double_layer(dirichl_space, dirichl_space, dirichl_space) dP = modified_helmholtz.double_layer(dirichl_space, dirichl_space, dirichl_space, kappa) L1 = (ep * dP) - dF F = laplace.single_layer(neumann_space, dirichl_space, dirichl_space) P = modified_helmholtz.single_layer(neumann_space, dirichl_space, dirichl_space, kappa) L2 = F - P ddF = laplace.hypersingular(dirichl_space, neumann_space, neumann_space) ddP = modified_helmholtz.hypersingular(dirichl_space, neumann_space, neumann_space, kappa) L3 = ddP - ddF dF0 = laplace.adjoint_double_layer(neumann_space, neumann_space, neumann_space) dP0 = modified_helmholtz.adjoint_double_layer(neumann_space, neumann_space, neumann_space, kappa) L4 = dF0 - ((1.0 / ep) * dP0) A = bempp.api.BlockedOperator(2, 2) A[0, 0] = (0.5 * (1.0 + ep) * phi_id) - L1 A[0, 1] = (-1.0) * L2 A[1, 0] = L3 # Cambio de signo por definicion de bempp A[1, 1] = (0.5 * (1.0 + (1.0 / ep)) * dph_id) - L4 @bempp.api.real_callable def d_green_func(x, n, domain_index, result): nrm = np.sqrt((x[0] - x_q[:, 0])**2 + (x[1] - x_q[:, 1])**2 + (x[2] - x_q[:, 2])**2) const = -1. / (4. * np.pi * ep_in) result[:] = const * np.sum(q * np.dot(x - x_q, n) / (nrm**3)) @bempp.api.real_callable def green_func(x, n, domain_index, result): nrm = np.sqrt((x[0] - x_q[:, 0])**2 + (x[1] - x_q[:, 1])**2 + (x[2] - x_q[:, 2])**2) result[:] = np.sum(q / nrm) / (4. * np.pi * ep_in) rhs_1 = bempp.api.GridFunction(dirichl_space, fun=green_func) rhs_2 = bempp.api.GridFunction(dirichl_space, fun=d_green_func) return A, rhs_1, rhs_2
def direct(dirichl_space, neumann_space, assembler, q, x_q): """ Construct the system matrix and RHS grid functions using direct formulation. """ ep_in = PARAMS.ep_in ep_ex = PARAMS.ep_ex kappa = PARAMS.kappa identity = sparse.identity(dirichl_space, dirichl_space, dirichl_space) slp_in = laplace.single_layer(neumann_space, dirichl_space, dirichl_space, assembler=assembler) dlp_in = laplace.double_layer(dirichl_space, dirichl_space, dirichl_space, assembler=assembler) slp_out = modified_helmholtz.single_layer(neumann_space, dirichl_space, dirichl_space, kappa, assembler=assembler) dlp_out = modified_helmholtz.double_layer(dirichl_space, dirichl_space, dirichl_space, kappa, assembler=assembler) A_sys = bempp.api.BlockedOperator(2, 2) A_sys[0, 0] = 0.5 * identity + dlp_in A_sys[0, 1] = -slp_in A_sys[1, 0] = 0.5 * identity - dlp_out A_sys[1, 1] = (ep_in / ep_ex) * slp_out @bempp.api.callable(vectorized=True) def rhs1_fun(x, n, domain_index, result): import exafmm.laplace as _laplace sources = _laplace.init_sources(x_q, q) targets = _laplace.init_targets(x.T) fmm = _laplace.LaplaceFmm(p=10, ncrit=500, filename='.rhs.tmp') tree = _laplace.setup(sources, targets, fmm) values = _laplace.evaluate(tree, fmm) os.remove('.rhs.tmp') result[:] = values[:, 0] / ep_in @bempp.api.real_callable def rhs2_fun(x, n, domain_index, result): result[0] = 0 rhs1 = bempp.api.GridFunction(dirichl_space, fun=rhs1_fun) rhs2 = bempp.api.GridFunction(neumann_space, fun=rhs2_fun) return A_sys, rhs1, rhs2
def muller_internal(dirichl_space, neumann_space, ep_in, ep_ex, kappa, operator_assembler): dlp_in = laplace.double_layer(dirichl_space, dirichl_space, dirichl_space, assembler=operator_assembler) slp_in = laplace.single_layer(neumann_space, dirichl_space, dirichl_space, assembler=operator_assembler) hlp_in = laplace.hypersingular(dirichl_space, neumann_space, neumann_space, assembler=operator_assembler) adlp_in = laplace.adjoint_double_layer(neumann_space, neumann_space, neumann_space, assembler=operator_assembler) dlp_ex = modified_helmholtz.double_layer(dirichl_space, dirichl_space, dirichl_space, kappa, assembler=operator_assembler) slp_ex = modified_helmholtz.single_layer(neumann_space, dirichl_space, dirichl_space, kappa, assembler=operator_assembler) hlp_ex = modified_helmholtz.hypersingular(dirichl_space, neumann_space, neumann_space, kappa, assembler=operator_assembler) adlp_ex = modified_helmholtz.adjoint_double_layer( neumann_space, neumann_space, neumann_space, kappa, assembler=operator_assembler) phi_identity = sparse.identity(dirichl_space, dirichl_space, dirichl_space) dph_identity = sparse.identity(neumann_space, neumann_space, neumann_space) ep = ep_ex / ep_in A = bempp.api.BlockedOperator(2, 2) A[0, 0] = phi_identity + dlp_in - dlp_ex A[0, 1] = -slp_in + ((1.0 / ep) * slp_ex) A[1, 0] = -hlp_in + (ep * hlp_ex) A[1, 1] = dph_identity - adlp_in + adlp_ex return A
def block_diagonal(dirichl_space, neumann_space, A): """ Compute the block-diagonal preconditioner for system matrix A. Suitable for direct formulation. """ ep_in = PARAMS.ep_in ep_ex = PARAMS.ep_ex kappa = PARAMS.kappa identity = sparse.identity(dirichl_space, dirichl_space, dirichl_space) identity_diag = identity.weak_form().A.diagonal() slp_in_diag = laplace.single_layer( neumann_space, dirichl_space, dirichl_space, assembler="only_diagonal_part").weak_form().A dlp_in_diag = laplace.double_layer( dirichl_space, dirichl_space, dirichl_space, assembler="only_diagonal_part").weak_form().A slp_out_diag = modified_helmholtz.single_layer( neumann_space, dirichl_space, dirichl_space, kappa, assembler="only_diagonal_part").weak_form().A dlp_out_diag = modified_helmholtz.double_layer( neumann_space, dirichl_space, dirichl_space, kappa, assembler="only_diagonal_part").weak_form().A diag11 = .5 * identity_diag + dlp_in_diag diag12 = -slp_in_diag diag21 = .5 * identity_diag - dlp_out_diag diag22 = (ep_in / ep_ex) * slp_out_diag d_aux = 1 / (diag22 - diag21 * diag12 / diag11) diag11_inv = 1 / diag11 + 1 / diag11 * diag12 * d_aux * diag21 / diag11 diag12_inv = -1 / diag11 * diag12 * d_aux diag21_inv = -d_aux * diag21 / diag11 diag22_inv = d_aux block_mat_precond = bmat([[diags(diag11_inv), diags(diag12_inv)], [diags(diag21_inv), diags(diag22_inv)]]).tocsr() return aslinearoperator(block_mat_precond)
def laplace_multitrace(dirichl_space, neumann_space, operator_assembler): A = bempp.api.BlockedOperator(2, 2) A[0, 0] = (-1.0) * laplace.double_layer(dirichl_space, dirichl_space, dirichl_space, assembler=operator_assembler) A[0, 1] = laplace.single_layer(neumann_space, dirichl_space, dirichl_space, assembler=operator_assembler) A[1, 0] = laplace.hypersingular(dirichl_space, neumann_space, neumann_space, assembler=operator_assembler) A[1, 1] = laplace.adjoint_double_layer(neumann_space, neumann_space, neumann_space, assembler=operator_assembler) return A
def direct(dirichl_space, neumann_space, ep_in, ep_out, kappa, operator_assembler, permute_rows=False): identity = sparse.identity(dirichl_space, dirichl_space, dirichl_space) slp_in = laplace.single_layer(neumann_space, dirichl_space, dirichl_space, assembler=operator_assembler) dlp_in = laplace.double_layer(dirichl_space, dirichl_space, dirichl_space, assembler=operator_assembler) slp_out = modified_helmholtz.single_layer(neumann_space, dirichl_space, dirichl_space, kappa, assembler=operator_assembler) dlp_out = modified_helmholtz.double_layer(dirichl_space, dirichl_space, dirichl_space, kappa, assembler=operator_assembler) A = bempp.api.BlockedOperator(2, 2) if permute_rows: #Use permuted rows formulation A[0, 0] = 0.5 * identity - dlp_out A[0, 1] = (ep_in / ep_out) * slp_out A[1, 0] = 0.5 * identity + dlp_in A[1, 1] = -slp_in else: #Normal direct formulation A[0, 0] = 0.5 * identity + dlp_in A[0, 1] = -slp_in A[1, 0] = 0.5 * identity - dlp_out A[1, 1] = (ep_in / ep_out) * slp_out return A
def test_laplace_double_layer_p1_cont(default_parameters, helpers, precision, device_interface): """Test dense assembler for the Laplace dlp with p1 basis.""" from bempp.api import function_space from bempp.api.operators.boundary.laplace import double_layer grid = helpers.load_grid("sphere") space = function_space(grid, "P", 1) discrete_op = double_layer( space, space, space, assembler="dense", precision=precision, device_interface=device_interface, parameters=default_parameters, ).weak_form() expected = helpers.load_npy_data("laplace_double_layer_boundary") _np.testing.assert_allclose(discrete_op.A, expected, rtol=helpers.default_tolerance(precision))
def derivative_in(dirichl_space, neumann_space, assembler, q, x_q): """ Construct the system matrix and RHS grid functions using derivative formulation with interior values. """ ep_in = PARAMS.ep_in ep_ex = PARAMS.ep_ex kappa = PARAMS.kappa phi_id = sparse.identity(dirichl_space, dirichl_space, dirichl_space) dph_id = sparse.identity(neumann_space, neumann_space, neumann_space) ep = ep_ex / ep_in dF = laplace.double_layer(dirichl_space, dirichl_space, dirichl_space, assembler=assembler) dP = modified_helmholtz.double_layer(dirichl_space, dirichl_space, dirichl_space, kappa, assembler=assembler) L1 = (ep * dP) - dF F = laplace.single_layer(neumann_space, dirichl_space, dirichl_space, assembler=assembler) P = modified_helmholtz.single_layer(neumann_space, dirichl_space, dirichl_space, kappa, assembler=assembler) L2 = F - P ddF = laplace.hypersingular(dirichl_space, neumann_space, neumann_space, assembler=assembler) ddP = modified_helmholtz.hypersingular(dirichl_space, neumann_space, neumann_space, kappa, assembler=assembler) L3 = ddP - ddF dF0 = laplace.adjoint_double_layer(neumann_space, neumann_space, neumann_space, assembler=assembler) dP0 = modified_helmholtz.adjoint_double_layer(neumann_space, neumann_space, neumann_space, kappa, assembler=assembler) L4 = dF0 - ((1.0 / ep) * dP0) A_sys = bempp.api.BlockedOperator(2, 2) A_sys[0, 0] = (0.5 * (1.0 + ep) * phi_id) - L1 A_sys[0, 1] = (-1.0) * L2 A_sys[1, 0] = L3 A_sys[1, 1] = (0.5 * (1.0 + (1.0 / ep)) * dph_id) - L4 @bempp.api.callable(vectorized=True) def rhs1_fun(x, n, domain_index, result): import exafmm.laplace as _laplace sources = _laplace.init_sources(x_q, q) targets = _laplace.init_targets(x.T) fmm = _laplace.LaplaceFmm(p=10, ncrit=500, filename='.rhs.tmp') tree = _laplace.setup(sources, targets, fmm) values = _laplace.evaluate(tree, fmm) os.remove('.rhs.tmp') result[:] = values[:, 0] / ep_in @bempp.api.callable(vectorized=True) def rhs2_fun(x, n, domain_index, result): import exafmm.laplace as _laplace sources = _laplace.init_sources(x_q, q) targets = _laplace.init_targets(x.T) fmm = _laplace.LaplaceFmm(p=10, ncrit=500, filename='.rhs.tmp') tree = _laplace.setup(sources, targets, fmm) values = _laplace.evaluate(tree, fmm) os.remove('.rhs.tmp') result[:] = np.sum(values[:, 1:] * n.T, axis=1) / ep_in rhs1 = bempp.api.GridFunction(dirichl_space, fun=rhs1_fun) rhs2 = bempp.api.GridFunction(neumann_space, fun=rhs2_fun) return A_sys, rhs1, rhs2
dirichl_space = bempp.api.function_space(grid, "DP", 0) neumann_space = bempp.api.function_space(grid, "DP", 0) dual_to_dir_s = bempp.api.function_space(grid, "DP", 0) # Se crea u_s y su derivada normal du_s en la frontera u_s = bempp.api.GridFunction(dirichl_space, fun=u_s_G) du_s = bempp.api.GridFunction(neumann_space, fun=du_s_G) # Se crean los operadores asociados al sistema, que dependen de los espacios de las soluciones # identity : I : matriz identidad # dlp_in : K_in : Double-Layer operator para la region interior # slp_in : V_in : Single-Layer operator para la region interior # _out : Mismos operadores pero para la región exterior, con k=kappa=0.125 identity = sparse.identity( dirichl_space, dirichl_space, dual_to_dir_s) slp_in = laplace.single_layer(neumann_space, dirichl_space, dual_to_dir_s) dlp_in = laplace.double_layer(dirichl_space, dirichl_space, dual_to_dir_s) slp_out = modified_helmholtz.single_layer(neumann_space, dirichl_space, dual_to_dir_s, k) dlp_out = modified_helmholtz.double_layer(dirichl_space, dirichl_space, dual_to_dir_s, k) # 4.1 Solución armónica --------------------------------------------------------------- # Dada por V_in du_s = (1/2+K_in)u_h = -(1/2+K_in)u_s (BC) sol, info,it_count = bempp.api.linalg.gmres( slp_in, -(dlp_in+0.5*identity)*u_s , return_iteration_count=True, tol=1e-4) print("The linear system for du_h was solved in {0} iterations".format(it_count)) u_h = -u_s du_h = sol
def block_diagonal_precon_alpha_beta(dirichl_space, neumann_space, ep_in, ep_ex, kappa, alpha, beta): from scipy.sparse import diags, bmat from scipy.sparse.linalg import factorized, LinearOperator from bempp.api.operators.boundary import sparse, laplace, modified_helmholtz slp_in_diag = laplace.single_layer( neumann_space, dirichl_space, dirichl_space, assembler="only_diagonal_part").weak_form().A dlp_in_diag = laplace.double_layer( dirichl_space, dirichl_space, dirichl_space, assembler="only_diagonal_part").weak_form().A hlp_in_diag = laplace.hypersingular( dirichl_space, neumann_space, neumann_space, assembler="only_diagonal_part").weak_form().A adlp_in_diag = laplace.adjoint_double_layer( neumann_space, neumann_space, neumann_space, assembler="only_diagonal_part").weak_form().A slp_out_diag = modified_helmholtz.single_layer( neumann_space, dirichl_space, dirichl_space, kappa, assembler="only_diagonal_part").weak_form().A dlp_out_diag = modified_helmholtz.double_layer( dirichl_space, dirichl_space, dirichl_space, kappa, assembler="only_diagonal_part").weak_form().A hlp_out_diag = modified_helmholtz.hypersingular( dirichl_space, neumann_space, neumann_space, kappa, assembler="only_diagonal_part").weak_form().A adlp_out_diag = modified_helmholtz.adjoint_double_layer( neumann_space, neumann_space, neumann_space, kappa, assembler="only_diagonal_part").weak_form().A phi_identity_diag = sparse.identity( dirichl_space, dirichl_space, dirichl_space).weak_form().A.diagonal() dph_identity_diag = sparse.identity( neumann_space, neumann_space, neumann_space).weak_form().A.diagonal() ep = ep_ex / ep_in diag11 = diags((-0.5 * (1 + alpha)) * phi_identity_diag + (alpha * dlp_out_diag) - dlp_in_diag) diag12 = diags(slp_in_diag - ((alpha / ep) * slp_out_diag)) diag21 = diags(hlp_in_diag - (beta * hlp_out_diag)) diag22 = diags((-0.5 * (1 + (beta / ep))) * dph_identity_diag + adlp_in_diag - ((beta / ep) * adlp_out_diag)) block_mat_precond = bmat([[diag11, diag12], [diag21, diag22]]).tocsr() # csr_matrix solve = factorized( block_mat_precond ) # a callable for solving a sparse linear system (treat it as an inverse) precond = LinearOperator(matvec=solve, dtype='float64', shape=block_mat_precond.shape) return precond
def stern_asc(neumann_space_in, dirichl_space_ex, neumann_space_ex, ep_in, ep_ex, q, x_q, kappa): # Functions to proyect the carges potential to the boundary with constants def d_green_func(x, n, domain_index, result): const = -1. / (4. * np.pi * ep_in) result[:] = const * np.sum(q * np.dot(x - x_q, n) / (np.linalg.norm(x - x_q, axis=1)**3)) print "\nProjecting charges over surface..." charged_grid_fun = bempp.api.GridFunction(neumann_space_in, fun=d_green_func) rhs = np.concatenate([ charged_grid_fun.coefficients, np.zeros(dirichl_space_ex.global_dof_count), np.zeros(neumann_space_ex.global_dof_count) ]) print "Defining operators..." # OPERATORS FOR INTERNAL SURFACE from bempp.api.operators.boundary import sparse, laplace, modified_helmholtz idn_in = sparse.identity(neumann_space_in, neumann_space_in, neumann_space_in) adj_1T1 = laplace.adjoint_double_layer(neumann_space_in, neumann_space_in, neumann_space_in) hyp_2T1 = laplace.hypersingular(dirichl_space_ex, neumann_space_in, neumann_space_in) adj_2T1 = laplace.adjoint_double_layer(neumann_space_ex, neumann_space_in, neumann_space_in) # OPERATORS FOR EXTERNAL SURFACE idn_ex = sparse.identity(dirichl_space_ex, dirichl_space_ex, dirichl_space_ex) slp_1T2 = laplace.single_layer(neumann_space_in, dirichl_space_ex, dirichl_space_ex) dlp_2T2 = laplace.double_layer(dirichl_space_ex, dirichl_space_ex, dirichl_space_ex) slp_2T2 = laplace.single_layer(neumann_space_ex, dirichl_space_ex, dirichl_space_ex) dlp_ex = modified_helmholtz.double_layer(dirichl_space_ex, dirichl_space_ex, dirichl_space_ex, kappa) slp_ex = modified_helmholtz.single_layer(neumann_space_ex, dirichl_space_ex, dirichl_space_ex, kappa) ep = (ep_in / ep_ex) print "Creating operators..." # Matrix Assemble blocked = bempp.api.BlockedOperator(3, 3) blocked[0, 0] = idn_in + (ep - 1.) * adj_1T1 blocked[0, 1] = -hyp_2T1 blocked[0, 2] = -adj_2T1 blocked[1, 0] = ep * slp_1T2 blocked[1, 1] = .5 * idn_ex + dlp_2T2 blocked[1, 2] = -slp_2T2 #blocked[2, 0] = 0 blocked[2, 1] = .5 * idn_ex - dlp_ex blocked[2, 2] = slp_ex A = blocked.weak_form() return A, rhs
def block_diagonal_precon_juffer(dirichl_space, neumann_space, ep_in, ep_ex, kappa): from scipy.sparse import diags, bmat from scipy.sparse.linalg import factorized, LinearOperator from bempp.api.operators.boundary import sparse, laplace, modified_helmholtz phi_id = sparse.identity(dirichl_space, dirichl_space, dirichl_space).weak_form().A.diagonal() dph_id = sparse.identity(neumann_space, neumann_space, neumann_space).weak_form().A.diagonal() ep = ep_ex / ep_in dF = laplace.double_layer(dirichl_space, dirichl_space, dirichl_space, assembler="only_diagonal_part").weak_form().A dP = modified_helmholtz.double_layer( dirichl_space, dirichl_space, dirichl_space, kappa, assembler="only_diagonal_part").weak_form().A L1 = (ep * dP) - dF F = laplace.single_layer(neumann_space, dirichl_space, dirichl_space, assembler="only_diagonal_part").weak_form().A P = modified_helmholtz.single_layer( neumann_space, dirichl_space, dirichl_space, kappa, assembler="only_diagonal_part").weak_form().A L2 = F - P ddF = laplace.hypersingular(dirichl_space, neumann_space, neumann_space, assembler="only_diagonal_part").weak_form().A ddP = modified_helmholtz.hypersingular( dirichl_space, neumann_space, neumann_space, kappa, assembler="only_diagonal_part").weak_form().A L3 = ddP - ddF dF0 = laplace.adjoint_double_layer( neumann_space, neumann_space, neumann_space, assembler="only_diagonal_part").weak_form().A dP0 = modified_helmholtz.adjoint_double_layer( neumann_space, neumann_space, neumann_space, kappa, assembler="only_diagonal_part").weak_form().A L4 = dF0 - ((1.0 / ep) * dP0) diag11 = diags((0.5 * (1.0 + ep) * phi_id) - L1) diag12 = diags((-1.0) * L2) diag21 = diags(L3) diag22 = diags((0.5 * (1.0 + (1.0 / ep)) * dph_id) - L4) block_mat_precond = bmat([[diag11, diag12], [diag21, diag22]]).tocsr() # csr_matrix solve = factorized( block_mat_precond ) # a callable for solving a sparse linear system (treat it as an inverse) precond = LinearOperator(matvec=solve, dtype='float64', shape=block_mat_precond.shape) return precond
def stern_formulation(dirichl_space_in, neumann_space_in, dirichl_space_ex, neumann_space_ex, ep_in, ep_ex, q, x_q, kappa): # Functions to proyect the carges potential to the boundary with constants def green_func(x, n, domain_index, result): result[:] = np.sum( q / np.linalg.norm(x - x_q, axis=1)) / (4. * np.pi * ep_in) print "\nProjecting charges over surface..." charged_grid_fun = bempp.api.GridFunction(dirichl_space_in, fun=green_func) rhs = np.concatenate([ charged_grid_fun.coefficients, np.zeros(neumann_space_in.global_dof_count), np.zeros(dirichl_space_ex.global_dof_count), np.zeros(neumann_space_ex.global_dof_count) ]) print "Defining operators..." # OPERATOR FOR INTERNAL SURFACE from bempp.api.operators.boundary import sparse, laplace, modified_helmholtz idn_in = sparse.identity(dirichl_space_in, dirichl_space_in, dirichl_space_in) # Ec 1 slp_in = laplace.single_layer(neumann_space_in, dirichl_space_in, dirichl_space_in) dlp_in = laplace.double_layer(dirichl_space_in, dirichl_space_in, dirichl_space_in) # Ec 2 # adj_1T1 = laplace.single_layer(neumann_space_in, dirichl_space_in, dirichl_space_in) # adj_1T1 = laplace.double_layer(dirichl_space_in, dirichl_space_in, dirichl_space_in) slp_2T1 = laplace.single_layer(neumann_space_ex, dirichl_space_in, dirichl_space_in) dlp_2T1 = laplace.double_layer(dirichl_space_ex, dirichl_space_in, dirichl_space_in) # OPERATOR FOR EXTERNAL SURFACE idn_ex = sparse.identity(dirichl_space_ex, dirichl_space_ex, dirichl_space_ex) # Internal Boudary slp_1T2 = laplace.single_layer(neumann_space_in, dirichl_space_ex, dirichl_space_ex) # dlp_1T2 = laplace.double_layer(dirichl_space_in, dirichl_space_ex, dirichl_space_ex) slp_2T2 = laplace.single_layer(neumann_space_ex, dirichl_space_ex, dirichl_space_ex) dlp_2T2 = laplace.double_layer(dirichl_space_ex, dirichl_space_ex, dirichl_space_ex) # External Boundary slp_ex = modified_helmholtz.single_layer(neumann_space_ex, dirichl_space_ex, dirichl_space_ex, kappa) dlp_ex = modified_helmholtz.double_layer(dirichl_space_ex, dirichl_space_ex, dirichl_space_ex, kappa) ep = (ep_in / ep_ex) print "Creating operators..." # Matrix Assemble blocked = bempp.api.BlockedOperator(4, 4) blocked[0, 0] = .5 * idn_in + dlp_in blocked[0, 1] = -slp_in # blocked[0, 2] = 0 # blocked[0, 3] = 0 # Original formulation blocked[1, 0] = .5 * idn_in - dlp_in # dlp_in = dlp_1T1 blocked[1, 1] = ep * slp_in # slp_in = slp_1T1 blocked[1, 2] = dlp_2T1 blocked[1, 3] = -slp_2T1 # blocked[2, 0] = -dlp_1T2 ## eliminar** blocked[2, 1] = ep * slp_1T2 blocked[2, 2] = .5 * idn_ex + dlp_2T2 blocked[2, 3] = -slp_2T2 # blocked[3, 0] = 0 # blocked[3, 1] = 0 blocked[3, 2] = .5 * idn_ex - dlp_ex blocked[3, 3] = slp_ex A = blocked.strong_form() return A, rhs
def first_kind_external(dirichl_space, neumann_space, ep_in, ep_ex, kappa, operator_assembler): dlp_in = laplace.double_layer(dirichl_space, dirichl_space, dirichl_space, assembler=operator_assembler) slp_in = laplace.single_layer(neumann_space, dirichl_space, dirichl_space, assembler=operator_assembler) hlp_in = laplace.hypersingular(dirichl_space, neumann_space, neumann_space, assembler=operator_assembler) adlp_in = laplace.adjoint_double_layer(neumann_space, neumann_space, neumann_space, assembler=operator_assembler) dlp_ex = modified_helmholtz.double_layer(dirichl_space, dirichl_space, dirichl_space, kappa, assembler=operator_assembler) slp_ex = modified_helmholtz.single_layer(neumann_space, dirichl_space, dirichl_space, kappa, assembler=operator_assembler) hlp_ex = modified_helmholtz.hypersingular(dirichl_space, neumann_space, neumann_space, kappa, assembler=operator_assembler) adlp_ex = modified_helmholtz.adjoint_double_layer( neumann_space, neumann_space, neumann_space, kappa, assembler=operator_assembler) ep = ep_ex / ep_in A = bempp.api.BlockedOperator(2, 2) A[0, 0] = (-1.0 * dlp_ex) - dlp_in A[0, 1] = slp_ex + (ep * slp_in) A[1, 0] = hlp_ex + ((1.0 / ep) * hlp_in) A[1, 1] = adlp_ex + adlp_in calderon_int_scal = bempp.api.BlockedOperator(2, 2) calderon_int_scal[0, 0] = -1.0 * dlp_in calderon_int_scal[0, 1] = ep * slp_in calderon_int_scal[1, 0] = (1.0 / ep) * hlp_in calderon_int_scal[1, 1] = adlp_in calderon_ext = bempp.api.BlockedOperator(2, 2) calderon_ext[0, 0] = -1.0 * dlp_ex calderon_ext[0, 1] = slp_ex calderon_ext[1, 0] = hlp_ex calderon_ext[1, 1] = adlp_ex return A, calderon_int_scal, calderon_ext