def lpot_source_from_mesh(queue, mesh, lpot_kwargs=None): from meshmode.discretization import Discretization from meshmode.discretization.poly_element import ( InterpolatoryQuadratureSimplexGroupFactory) target_order = TARGET_ORDER pre_density_discr = Discretization( queue.context, mesh, InterpolatoryQuadratureSimplexGroupFactory(target_order)) refiner_extra_kwargs = { "_force_stage2_uniform_refinement_rounds": (FORCE_STAGE2_UNIFORM_REFINEMENT_ROUNDS), "_scaled_max_curvature_threshold": (SCALED_MAX_CURVATURE_THRESHOLD), } if lpot_kwargs is None: lpot_kwargs = DEFAULT_LPOT_KWARGS from pytential.qbx import QBXLayerPotentialSource lpot_source = QBXLayerPotentialSource( pre_density_discr, OVSMP_FACTOR * target_order, **lpot_kwargs, ) lpot_source, _ = lpot_source.with_refinement(**refiner_extra_kwargs) return lpot_source
def starfish_lpot_source(queue, n_arms): from meshmode.discretization import Discretization from meshmode.discretization.poly_element import ( InterpolatoryQuadratureSimplexGroupFactory) from meshmode.mesh.generation import make_curve_mesh, NArmedStarfish mesh = make_curve_mesh(NArmedStarfish(n_arms, 0.8), np.linspace(0, 1, 1 + PANELS_PER_ARM * n_arms), TARGET_ORDER) pre_density_discr = Discretization( queue.context, mesh, InterpolatoryQuadratureSimplexGroupFactory(TARGET_ORDER)) lpot_kwargs = DEFAULT_LPOT_KWARGS.copy() lpot_kwargs.update(target_association_tolerance=0.025, _expansion_stick_out_factor=TCF, fmm_order=FMM_ORDER, qbx_order=QBX_ORDER, fmm_backend="fmmlib") from pytential.qbx import QBXLayerPotentialSource lpot_source = QBXLayerPotentialSource(pre_density_discr, OVSMP_FACTOR * TARGET_ORDER, **lpot_kwargs) lpot_source, _ = lpot_source.with_refinement() return lpot_source
def get_lpot_source(queue, mesh_getter, nelements, stickout_factor, well_sep_is_n_away, with_extents, max_leaf_refine_weight, k=0, fmm_backend="sumpy", from_sep_smaller_threshold=None): from meshmode.discretization import Discretization from meshmode.discretization.poly_element import ( InterpolatoryQuadratureSimplexGroupFactory) target_order = TARGET_ORDER mesh = mesh_getter(nelements, target_order) pre_density_discr = Discretization( queue.context, mesh, InterpolatoryQuadratureSimplexGroupFactory(target_order)) refiner_extra_kwargs = {} if k != 0: refiner_extra_kwargs["kernel_length_scale"] = 5 / k from pytential.qbx import QBXLayerPotentialSource lpot_source = QBXLayerPotentialSource( pre_density_discr, OVSMP_FACTOR * target_order, fmm_backend=fmm_backend, _well_sep_is_n_away=well_sep_is_n_away, _expansions_in_tree_have_extent=with_extents, _expansion_stick_out_factor=stickout_factor, _max_leaf_refine_weight=max_leaf_refine_weight, target_association_tolerance=1e-3, fmm_order=10, qbx_order=10, _from_sep_smaller_min_nsources_cumul=from_sep_smaller_threshold, _from_sep_smaller_crit="static_linf", _box_extent_norm="linf", ) lpot_source, _ = lpot_source.with_refinement(**refiner_extra_kwargs) return lpot_source
def get_sphere_lpot_source(queue): from meshmode.discretization import Discretization from meshmode.discretization.poly_element import ( InterpolatoryQuadratureSimplexGroupFactory) target_order = 8 from meshmode.mesh.generation import generate_icosphere mesh = generate_icosphere(1, target_order) pre_density_discr = Discretization( queue.context, mesh, InterpolatoryQuadratureSimplexGroupFactory(target_order)) from pytential.qbx import QBXLayerPotentialSource lpot_source = QBXLayerPotentialSource(pre_density_discr, qbx_order=5, fmm_order=10, fine_order=4 * target_order, fmm_backend="fmmlib") lpot_source, _ = lpot_source.with_refinement() return lpot_source
def get_lpot_source(queue, dim): from meshmode.discretization import Discretization from meshmode.discretization.poly_element import ( InterpolatoryQuadratureSimplexGroupFactory) target_order = TARGET_ORDER if dim == 2: from meshmode.mesh.generation import starfish, make_curve_mesh mesh = make_curve_mesh(starfish, np.linspace(0, 1, 50), order=target_order) elif dim == 3: from meshmode.mesh.generation import generate_torus mesh = generate_torus(2, 1, order=target_order) else: raise ValueError("unsupported dimension: %d" % dim) pre_density_discr = Discretization( queue.context, mesh, InterpolatoryQuadratureSimplexGroupFactory(target_order)) lpot_kwargs = DEFAULT_LPOT_KWARGS.copy() lpot_kwargs.update( _expansion_stick_out_factor=TCF, fmm_order=FMM_ORDER, qbx_order=QBX_ORDER, fmm_backend="fmmlib", ) from pytential.qbx import QBXLayerPotentialSource lpot_source = QBXLayerPotentialSource(pre_density_discr, OVSMP_FACTOR * target_order, **lpot_kwargs) lpot_source, _ = lpot_source.with_refinement() return lpot_source
def get_qbx(self, **kwargs): """ Return a :class:`QBXLayerPotentialSource` to bind to an operator """ qbx = QBXLayerPotentialSource(self._discr, **kwargs) # {{{ If refining, refine and store connection (possibly composed with bdy # connection if self._refine: self._refine = False from meshmode.discretization.connection import \ ChainedDiscretizationConnection qbx, refinement_connection = qbx.with_refinement() if self._connection: connections = [self._connection, refinement_connection] self._connection = ChainedDiscretizationConnection(connections) else: self._connection = refinement_connection # }}} return qbx
def run_int_eq_test(cl_ctx, queue, case, resolution, visualize): mesh = case.get_mesh(resolution, case.target_order) print("%d elements" % mesh.nelements) from pytential.qbx import QBXLayerPotentialSource from meshmode.discretization import Discretization from meshmode.discretization.poly_element import \ InterpolatoryQuadratureSimplexGroupFactory pre_density_discr = Discretization( cl_ctx, mesh, InterpolatoryQuadratureSimplexGroupFactory(case.target_order)) source_order = 4*case.target_order refiner_extra_kwargs = {} qbx_lpot_kwargs = {} if case.fmm_backend is None: qbx_lpot_kwargs["fmm_order"] = False else: if hasattr(case, "fmm_tol"): from sumpy.expansion.level_to_order import SimpleExpansionOrderFinder qbx_lpot_kwargs["fmm_level_to_order"] = SimpleExpansionOrderFinder( case.fmm_tol) elif hasattr(case, "fmm_order"): qbx_lpot_kwargs["fmm_order"] = case.fmm_order else: qbx_lpot_kwargs["fmm_order"] = case.qbx_order + 5 qbx = QBXLayerPotentialSource( pre_density_discr, fine_order=source_order, qbx_order=case.qbx_order, _box_extent_norm=getattr(case, "box_extent_norm", None), _from_sep_smaller_crit=getattr(case, "from_sep_smaller_crit", None), _from_sep_smaller_min_nsources_cumul=30, fmm_backend=case.fmm_backend, **qbx_lpot_kwargs) if case.use_refinement: if case.k != 0 and getattr(case, "refine_on_helmholtz_k", True): refiner_extra_kwargs["kernel_length_scale"] = 5/case.k if hasattr(case, "scaled_max_curvature_threshold"): refiner_extra_kwargs["_scaled_max_curvature_threshold"] = \ case.scaled_max_curvature_threshold if hasattr(case, "expansion_disturbance_tolerance"): refiner_extra_kwargs["_expansion_disturbance_tolerance"] = \ case.expansion_disturbance_tolerance if hasattr(case, "refinement_maxiter"): refiner_extra_kwargs["maxiter"] = case.refinement_maxiter #refiner_extra_kwargs["visualize"] = True print("%d elements before refinement" % pre_density_discr.mesh.nelements) qbx, _ = qbx.with_refinement(**refiner_extra_kwargs) print("%d stage-1 elements after refinement" % qbx.density_discr.mesh.nelements) print("%d stage-2 elements after refinement" % qbx.stage2_density_discr.mesh.nelements) print("quad stage-2 elements have %d nodes" % qbx.quad_stage2_density_discr.groups[0].nunit_nodes) density_discr = qbx.density_discr if hasattr(case, "visualize_geometry") and case.visualize_geometry: bdry_normals = bind( density_discr, sym.normal(mesh.ambient_dim) )(queue).as_vector(dtype=object) bdry_vis = make_visualizer(queue, density_discr, case.target_order) bdry_vis.write_vtk_file("geometry.vtu", [ ("normals", bdry_normals) ]) # {{{ plot geometry if 0: if mesh.ambient_dim == 2: # show geometry, centers, normals nodes_h = density_discr.nodes().get(queue=queue) pt.plot(nodes_h[0], nodes_h[1], "x-") normal = bind(density_discr, sym.normal(2))(queue).as_vector(np.object) pt.quiver(nodes_h[0], nodes_h[1], normal[0].get(queue), normal[1].get(queue)) pt.gca().set_aspect("equal") pt.show() elif mesh.ambient_dim == 3: bdry_vis = make_visualizer(queue, density_discr, case.target_order+3) bdry_normals = bind(density_discr, sym.normal(3))(queue)\ .as_vector(dtype=object) bdry_vis.write_vtk_file("pre-solve-source-%s.vtu" % resolution, [ ("bdry_normals", bdry_normals), ]) else: raise ValueError("invalid mesh dim") # }}} # {{{ set up operator from pytential.symbolic.pde.scalar import ( DirichletOperator, NeumannOperator) from sumpy.kernel import LaplaceKernel, HelmholtzKernel if case.k: knl = HelmholtzKernel(mesh.ambient_dim) knl_kwargs = {"k": sym.var("k")} concrete_knl_kwargs = {"k": case.k} else: knl = LaplaceKernel(mesh.ambient_dim) knl_kwargs = {} concrete_knl_kwargs = {} if knl.is_complex_valued: dtype = np.complex128 else: dtype = np.float64 loc_sign = +1 if case.prob_side in [+1, "scat"] else -1 if case.bc_type == "dirichlet": op = DirichletOperator(knl, loc_sign, use_l2_weighting=True, kernel_arguments=knl_kwargs) elif case.bc_type == "neumann": op = NeumannOperator(knl, loc_sign, use_l2_weighting=True, use_improved_operator=False, kernel_arguments=knl_kwargs) else: assert False op_u = op.operator(sym.var("u")) # }}} # {{{ set up test data if case.prob_side == -1: test_src_geo_radius = case.outer_radius test_tgt_geo_radius = case.inner_radius elif case.prob_side == +1: test_src_geo_radius = case.inner_radius test_tgt_geo_radius = case.outer_radius elif case.prob_side == "scat": test_src_geo_radius = case.outer_radius test_tgt_geo_radius = case.outer_radius else: raise ValueError("unknown problem_side") point_sources = make_circular_point_group( mesh.ambient_dim, 10, test_src_geo_radius, func=lambda x: x**1.5) test_targets = make_circular_point_group( mesh.ambient_dim, 20, test_tgt_geo_radius) 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), pot_src)( queue, charges=source_charges_dev, **concrete_knl_kwargs) elif case.bc_type == "neumann": bc = bind( (point_source, density_discr), sym.normal_derivative( qbx.ambient_dim, pot_src, where=sym.DEFAULT_TARGET) )(queue, charges=source_charges_dev, **concrete_knl_kwargs) # }}} # {{{ solve bound_op = bind(qbx, op_u) rhs = bind(density_discr, op.prepare_rhs(sym.var("bc")))(queue, bc=bc) try: from pytential.solve import gmres gmres_result = gmres( bound_op.scipy_op(queue, "u", dtype, **concrete_knl_kwargs), rhs, tol=case.gmres_tol, progress=True, hard_failure=True, stall_iterations=50, no_progress_factor=1.05) except QBXTargetAssociationFailedException as e: bdry_vis = make_visualizer(queue, density_discr, case.target_order+3) bdry_vis.write_vtk_file("failed-targets-%s.vtu" % resolution, [ ("failed_targets", e.failed_target_flags), ]) raise print("gmres state:", gmres_result.state) weighted_u = gmres_result.solution # }}} # {{{ build matrix for spectrum check if 0: from sumpy.tools import build_matrix mat = build_matrix( bound_op.scipy_op( queue, arg_name="u", dtype=dtype, k=case.k)) w, v = la.eig(mat) if 0: pt.imshow(np.log10(1e-20+np.abs(mat))) pt.colorbar() pt.show() #assert abs(s[-1]) < 1e-13, "h #assert abs(s[-2]) > 1e-7 #from pudb import set_trace; set_trace() # }}} if case.prob_side != "scat": # {{{ error check points_target = PointsTarget(test_targets) bound_tgt_op = bind((qbx, points_target), op.representation(sym.var("u"))) test_via_bdry = bound_tgt_op(queue, u=weighted_u, k=case.k) err = test_via_bdry - test_direct err = err.get() test_direct = test_direct.get() test_via_bdry = test_via_bdry.get() # {{{ remove effect of net source charge if case.k == 0 and case.bc_type == "neumann" and loc_sign == -1: # remove constant offset in interior Laplace Neumann error tgt_ones = np.ones_like(test_direct) tgt_ones = tgt_ones/la.norm(tgt_ones) err = err - np.vdot(tgt_ones, err)*tgt_ones # }}} rel_err_2 = la.norm(err)/la.norm(test_direct) rel_err_inf = la.norm(err, np.inf)/la.norm(test_direct, np.inf) # }}} print("rel_err_2: %g rel_err_inf: %g" % (rel_err_2, rel_err_inf)) else: rel_err_2 = None rel_err_inf = None # {{{ test gradient if case.check_gradient and case.prob_side != "scat": bound_grad_op = bind((qbx, points_target), op.representation( sym.var("u"), map_potentials=lambda pot: sym.grad(mesh.ambient_dim, pot), qbx_forced_limit=None)) #print(bound_t_deriv_op.code) grad_from_src = bound_grad_op( queue, u=weighted_u, **concrete_knl_kwargs) grad_ref = (bind( (point_source, points_target), sym.grad(mesh.ambient_dim, pot_src) )(queue, charges=source_charges_dev, **concrete_knl_kwargs) ) grad_err = (grad_from_src - grad_ref) rel_grad_err_inf = ( la.norm(grad_err[0].get(), np.inf) / la.norm(grad_ref[0].get(), np.inf)) print("rel_grad_err_inf: %g" % rel_grad_err_inf) # }}} # {{{ test tangential derivative if case.check_tangential_deriv and case.prob_side != "scat": bound_t_deriv_op = bind(qbx, op.representation( sym.var("u"), map_potentials=lambda pot: sym.tangential_derivative(2, pot), qbx_forced_limit=loc_sign)) #print(bound_t_deriv_op.code) tang_deriv_from_src = bound_t_deriv_op( queue, u=weighted_u, **concrete_knl_kwargs).as_scalar().get() tang_deriv_ref = (bind( (point_source, density_discr), sym.tangential_derivative(2, pot_src) )(queue, charges=source_charges_dev, **concrete_knl_kwargs) .as_scalar().get()) if 0: pt.plot(tang_deriv_ref.real) pt.plot(tang_deriv_from_src.real) pt.show() td_err = (tang_deriv_from_src - tang_deriv_ref) rel_td_err_inf = la.norm(td_err, np.inf)/la.norm(tang_deriv_ref, np.inf) print("rel_td_err_inf: %g" % rel_td_err_inf) else: rel_td_err_inf = None # }}} # {{{ any-D file plotting if visualize: bdry_vis = make_visualizer(queue, density_discr, case.target_order+3) bdry_normals = bind(density_discr, sym.normal(qbx.ambient_dim))(queue)\ .as_vector(dtype=object) sym_sqrt_j = sym.sqrt_jac_q_weight(density_discr.ambient_dim) u = bind(density_discr, sym.var("u")/sym_sqrt_j)(queue, u=weighted_u) bdry_vis.write_vtk_file("source-%s.vtu" % resolution, [ ("u", u), ("bc", bc), #("bdry_normals", bdry_normals), ]) from sumpy.visualization import make_field_plotter_from_bbox # noqa from meshmode.mesh.processing import find_bounding_box vis_grid_spacing = (0.1, 0.1, 0.1)[:qbx.ambient_dim] if hasattr(case, "vis_grid_spacing"): vis_grid_spacing = case.vis_grid_spacing vis_extend_factor = 0.2 if hasattr(case, "vis_extend_factor"): vis_grid_spacing = case.vis_grid_spacing fplot = make_field_plotter_from_bbox( find_bounding_box(mesh), h=vis_grid_spacing, extend_factor=vis_extend_factor) qbx_tgt_tol = qbx.copy(target_association_tolerance=0.15) from pytential.target import PointsTarget try: solved_pot = bind( (qbx_tgt_tol, PointsTarget(fplot.points)), op.representation(sym.var("u")) )(queue, u=weighted_u, k=case.k) except QBXTargetAssociationFailedException as e: fplot.write_vtk_file( "failed-targets.vts", [ ("failed_targets", e.failed_target_flags.get(queue)) ]) raise from sumpy.kernel import LaplaceKernel ones_density = density_discr.zeros(queue) ones_density.fill(1) indicator = bind( (qbx_tgt_tol, PointsTarget(fplot.points)), -sym.D(LaplaceKernel(density_discr.ambient_dim), sym.var("sigma"), qbx_forced_limit=None))( queue, sigma=ones_density).get() solved_pot = solved_pot.get() true_pot = bind((point_source, PointsTarget(fplot.points)), pot_src)( queue, charges=source_charges_dev, **concrete_knl_kwargs).get() #fplot.show_scalar_in_mayavi(solved_pot.real, max_val=5) if case.prob_side == "scat": fplot.write_vtk_file( "potential-%s.vts" % resolution, [ ("pot_scattered", solved_pot), ("pot_incoming", -true_pot), ("indicator", indicator), ] ) else: fplot.write_vtk_file( "potential-%s.vts" % resolution, [ ("solved_pot", solved_pot), ("true_pot", true_pot), ("indicator", indicator), ] ) # }}} class Result(Record): pass return Result( h_max=qbx.h_max, rel_err_2=rel_err_2, rel_err_inf=rel_err_inf, rel_td_err_inf=rel_td_err_inf, gmres_result=gmres_result)
def test_perf_data_gathering(ctx_getter, n_arms=5): cl_ctx = ctx_getter() queue = cl.CommandQueue(cl_ctx) # prevent cache 'splosion from sympy.core.cache import clear_cache clear_cache() target_order = 8 starfish_func = NArmedStarfish(n_arms, 0.8) mesh = make_curve_mesh( starfish_func, np.linspace(0, 1, n_arms * 30), target_order) sigma_sym = sym.var("sigma") # The kernel doesn't really matter here from sumpy.kernel import LaplaceKernel k_sym = LaplaceKernel(mesh.ambient_dim) sym_op = sym.S(k_sym, sigma_sym, qbx_forced_limit=+1) from meshmode.discretization import Discretization from meshmode.discretization.poly_element import ( InterpolatoryQuadratureSimplexGroupFactory) pre_density_discr = Discretization( queue.context, mesh, InterpolatoryQuadratureSimplexGroupFactory(target_order)) results = [] def inspect_geo_data(insn, bound_expr, geo_data): from pytential.qbx.fmm import assemble_performance_data perf_data = assemble_performance_data(geo_data, uses_pde_expansions=True) results.append(perf_data) return False # no need to do the actual FMM from pytential.qbx import QBXLayerPotentialSource lpot_source = QBXLayerPotentialSource( pre_density_discr, 4*target_order, # qbx order and fmm order don't really matter 10, fmm_order=10, _expansions_in_tree_have_extent=True, _expansion_stick_out_factor=0.5, geometry_data_inspector=inspect_geo_data, target_association_tolerance=1e-10, ) lpot_source, _ = lpot_source.with_refinement() density_discr = lpot_source.density_discr if 0: from meshmode.discretization.visualization import draw_curve draw_curve(density_discr) import matplotlib.pyplot as plt plt.show() nodes = density_discr.nodes().with_queue(queue) sigma = cl.clmath.sin(10 * nodes[0]) bind(lpot_source, sym_op)(queue, sigma=sigma)