def make_source_and_target_points(side, inner_radius, outer_radius, ambient_dim, nsources=10, ntargets=20): if side == -1: test_src_geo_radius = outer_radius test_tgt_geo_radius = inner_radius elif side == +1: test_src_geo_radius = inner_radius test_tgt_geo_radius = outer_radius elif side == "scat": test_src_geo_radius = outer_radius test_tgt_geo_radius = outer_radius else: raise ValueError(f"unknown side: {side}") from pytential.source import PointPotentialSource point_sources = make_circular_point_group(ambient_dim, nsources, test_src_geo_radius, func=lambda x: x**1.5) point_source = PointPotentialSource(point_sources) from pytential.target import PointsTarget test_targets = make_circular_point_group(ambient_dim, ntargets, test_tgt_geo_radius) point_target = PointsTarget(test_targets) return point_source, point_target
def get_source(self, actx): if self.is_interior: source_ctr = np.array([[0.35, 0.1, 0.15]]).T else: source_ctr = np.array([[5, 0.1, 0.15]]).T source_rad = 0.3 sources = source_ctr + source_rad * 2 * (np.random.rand(3, 10) - 0.5) from pytential.source import PointPotentialSource return PointPotentialSource(actx.from_numpy(sources))
def get_source(self, queue): if self.is_interior: source_ctr = np.array([[0.35, 0.1, 0.15]]).T else: source_ctr = np.array([[5, 0.1, 0.15]]).T source_rad = 0.3 sources = source_ctr + source_rad * 2 * (np.random.rand(3, 10) - 0.5) from pytential.source import PointPotentialSource return PointPotentialSource(queue.context, cl.array.to_device(queue, sources))
np.random.seed(22) source_charges = np.random.randn(point_sources.shape[1]) source_charges[-1] = -np.sum(source_charges[:-1]) source_charges = source_charges.astype(dtype) assert np.sum(source_charges) < 1e-15 source_charges_dev = cl.array.to_device(queue, source_charges) # }}} # {{{ establish BCs from pytential.source import PointPotentialSource from pytential.target import PointsTarget point_source = PointPotentialSource(cl_ctx, point_sources) pot_src = sym.IntG( # FIXME: qbx_forced_limit--really? knl, sym.var("charges"), qbx_forced_limit=None, **knl_kwargs) test_direct = bind((point_source, PointsTarget(test_targets)), pot_src)(queue, charges=source_charges_dev, **concrete_knl_kwargs) if case.bc_type == "dirichlet": bc = bind((point_source, density_discr),
def get_bvp_error(lpot_source, fmm_order, qbx_order, k=0): # This returns a tuple (err_l2, err_linf, nit). queue = cl.CommandQueue(lpot_source.cl_context) lpot_source = lpot_source.copy( qbx_order=qbx_order, fmm_level_to_order=(False if fmm_order is False else lambda *args: fmm_order)) d = lpot_source.ambient_dim assert k == 0 # Helmholtz would require a different representation from sumpy.kernel import LaplaceKernel, HelmholtzKernel lap_k_sym = LaplaceKernel(d) if k == 0: k_sym = lap_k_sym knl_kwargs = {} else: k_sym = HelmholtzKernel(d) knl_kwargs = {"k": sym.var("k")} density_discr = lpot_source.density_discr # {{{ find source and target points source_angles = (np.pi / 2 + np.linspace(0, 2 * np.pi * BVP_EXPERIMENT_N_ARMS, BVP_EXPERIMENT_N_ARMS, endpoint=False)) / BVP_EXPERIMENT_N_ARMS source_points = 0.75 * np.array([ np.cos(source_angles), np.sin(source_angles), ]) target_angles = (np.pi + np.pi / 2 + np.linspace(0, 2 * np.pi * BVP_EXPERIMENT_N_ARMS, BVP_EXPERIMENT_N_ARMS, endpoint=False)) / BVP_EXPERIMENT_N_ARMS target_points = 1.5 * np.array([ np.cos(target_angles), np.sin(target_angles), ]) np.random.seed(17) source_charges = np.random.randn(BVP_EXPERIMENT_N_ARMS) source_points_dev = cl.array.to_device(queue, source_points) target_points_dev = cl.array.to_device(queue, target_points) source_charges_dev = cl.array.to_device(queue, source_charges) from pytential.source import PointPotentialSource from pytential.target import PointsTarget point_source = PointPotentialSource(lpot_source.cl_context, source_points_dev) pot_src = sym.IntG( # FIXME: qbx_forced_limit--really? k_sym, sym.var("charges"), qbx_forced_limit=None, **knl_kwargs) ref_direct = bind((point_source, PointsTarget(target_points_dev)), pot_src)(queue, charges=source_charges_dev, **knl_kwargs).get() sym_sqrt_j = sym.sqrt_jac_q_weight(density_discr.ambient_dim) bc = bind((point_source, density_discr), sym.normal_derivative(density_discr.ambient_dim, pot_src, where=sym.DEFAULT_TARGET))( queue, charges=source_charges_dev, **knl_kwargs) rhs = bind(density_discr, sym.var("bc") * sym_sqrt_j)(queue, bc=bc) # }}} # {{{ solve bound_op = bind( lpot_source, -0.5 * sym.var("u") + sym_sqrt_j * sym.Sp(k_sym, sym.var("u") / sym_sqrt_j, qbx_forced_limit="avg", **knl_kwargs)) from pytential.solve import gmres gmres_result = gmres(bound_op.scipy_op(queue, "u", np.float64, **knl_kwargs), rhs, tol=1e-10, stall_iterations=100, progress=True, hard_failure=True) u = gmres_result.solution # }}} points_target = PointsTarget(target_points_dev) bound_tgt_op = bind((lpot_source, points_target), sym.S(k_sym, sym.var("u") / sym_sqrt_j, qbx_forced_limit=None)) test_via_bdry = bound_tgt_op(queue, u=u).get() err = ref_direct - test_via_bdry err_l2 = la.norm(err, 2) / la.norm(ref_direct, 2) err_linf = la.norm(err, np.inf) / la.norm(ref_direct, np.inf) return err_l2, err_linf, gmres_result.iteration_count