def lu(op, rhs, show_spectrum=False): import numpy.linalg as la from sumpy.tools import build_matrix mat = build_matrix(op) print("condition number: %g" % la.cond(mat)) if show_spectrum: ev = la.eigvals(mat) import matplotlib.pyplot as pt pt.plot(ev.real, ev.imag, "o") pt.show() return la.solve(mat, rhs)
def lu(op, rhs, show_spectrum=False): import numpy.linalg as la from sumpy.tools import build_matrix mat = build_matrix(op) print("condition number: %g" % la.cond(mat)) if show_spectrum: ev = la.eigvals(mat) import matplotlib.pyplot as pt pt.plot(ev.real, ev.imag, "o") pt.show() chopper = VectorChopper(rhs) return chopper.chop( la.solve(mat, chopper.stack(rhs)))
def main(curve_fn=starfish, visualize=True): import logging logging.basicConfig(level=logging.WARNING) # INFO for more progress info import pyopencl as cl cl_ctx = cl.create_some_context() queue = cl.CommandQueue(cl_ctx) actx = PyOpenCLArrayContext(queue, force_device_scalars=True) from meshmode.mesh.generation import make_curve_mesh mesh = make_curve_mesh( curve_fn, np.linspace(0, 1, nelements+1), target_order) from pytential.qbx import QBXLayerPotentialSource from meshmode.discretization import Discretization from meshmode.discretization.poly_element import \ InterpolatoryQuadratureSimplexGroupFactory pre_density_discr = Discretization( actx, mesh, InterpolatoryQuadratureSimplexGroupFactory(target_order)) qbx = QBXLayerPotentialSource( pre_density_discr, 4*target_order, qbx_order, fmm_order=qbx_order+3, target_association_tolerance=0.005, #fmm_backend="fmmlib", ) from pytential.target import PointsTarget fplot = FieldPlotter(np.zeros(2), extent=5, npoints=1000) targets_dev = actx.from_numpy(fplot.points) from pytential import GeometryCollection places = GeometryCollection({ "qbx": qbx, "targets": PointsTarget(targets_dev), }, auto_where="qbx") density_discr = places.get_discretization("qbx") nodes = thaw(density_discr.nodes(), actx) angle = actx.np.arctan2(nodes[1], nodes[0]) if k: kernel = HelmholtzKernel(2) kernel_kwargs = {"k": sym.var("k")} else: kernel = LaplaceKernel(2) kernel_kwargs = {} def op(**kwargs): kwargs.update(kernel_kwargs) #op = sym.d_dx(sym.S(kernel, sym.var("sigma"), **kwargs)) return sym.D(kernel, sym.var("sigma"), **kwargs) #op = sym.S(kernel, sym.var("sigma"), qbx_forced_limit=None, **kwargs) if 0: from random import randrange sigma = actx.zeros(density_discr.ndofs, angle.entry_dtype) for _ in range(5): sigma[randrange(len(sigma))] = 1 from arraycontext import unflatten sigma = unflatten(angle, sigma, actx) else: sigma = actx.np.cos(mode_nr*angle) if isinstance(kernel, HelmholtzKernel): for i, elem in np.ndenumerate(sigma): sigma[i] = elem.astype(np.complex128) bound_bdry_op = bind(places, op()) if visualize: fld_in_vol = actx.to_numpy( bind(places, op( source="qbx", target="targets", qbx_forced_limit=None))(actx, sigma=sigma, k=k)) if enable_mayavi: fplot.show_scalar_in_mayavi(fld_in_vol.real, max_val=5) else: fplot.write_vtk_file("layerpot-potential.vts", [ ("potential", fld_in_vol) ]) if 0: apply_op = bound_bdry_op.scipy_op(actx, "sigma", np.float64, k=k) from sumpy.tools import build_matrix mat = build_matrix(apply_op) import matplotlib.pyplot as pt pt.imshow(mat) pt.colorbar() pt.show() if enable_mayavi: # {{{ plot boundary field from arraycontext import flatten fld_on_bdry = actx.to_numpy( flatten(bound_bdry_op(actx, sigma=sigma, k=k), actx)) nodes_host = actx.to_numpy( flatten(density_discr.nodes(), actx) ).reshape(density_discr.ambient_dim, -1) mlab.points3d(nodes_host[0], nodes_host[1], fld_on_bdry.real, scale_factor=0.03) mlab.colorbar() mlab.show()
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)
np.linspace(0, 1, nelements+1), target_order) from pytential.discretization.qbx import make_upsampling_qbx_discr discr = make_upsampling_qbx_discr( cl_ctx, mesh, target_order, qbx_order) nodes = discr.nodes().with_queue(queue) angle = cl.clmath.atan2(nodes[1], nodes[0]) from pytential import bind, sym representation = sym.S(0, sym.var("sigma")) op = representation bc = cl.clmath.cos(mode_nr*angle) bound_op = bind(discr, op) from sumpy.tools import build_matrix mat = build_matrix(bound_op.scipy_op(queue, "sigma")) w, v = la.eig(mat) import matplotlib.pyplot as pt pt.plot(w.real, w.imag, "x") pt.rc("font", size=20) pt.grid() pt.show()
def draw_pot_figure(aspect_ratio, nsrc=100, novsmp=None, helmholtz_k=0, what_operator="S", what_operator_lpot=None, order=4, ovsmp_center_exp=0.66, force_center_side=None): import logging logging.basicConfig(level=logging.INFO) if novsmp is None: novsmp = 4 * nsrc if what_operator_lpot is None: what_operator_lpot = what_operator ctx = cl.create_some_context() queue = cl.CommandQueue(ctx) # {{{ make plot targets center = np.asarray([0, 0], dtype=np.float64) from sumpy.visualization import FieldPlotter fp = FieldPlotter(center, npoints=1000, extent=6) # }}} # {{{ make p2p kernel calculator from sumpy.p2p import P2P from sumpy.kernel import LaplaceKernel, HelmholtzKernel from sumpy.expansion.local import H2DLocalExpansion, LineTaylorLocalExpansion if helmholtz_k: if isinstance(helmholtz_k, complex): knl = HelmholtzKernel(2, allow_evanescent=True) expn_class = H2DLocalExpansion knl_kwargs = {"k": helmholtz_k} else: knl = HelmholtzKernel(2) expn_class = H2DLocalExpansion knl_kwargs = {"k": helmholtz_k} else: knl = LaplaceKernel(2) expn_class = LineTaylorLocalExpansion knl_kwargs = {} vol_knl = process_kernel(knl, what_operator) p2p = P2P(ctx, [vol_knl], exclude_self=False, value_dtypes=np.complex128) lpot_knl = process_kernel(knl, what_operator_lpot) from sumpy.qbx import LayerPotential lpot = LayerPotential(ctx, [expn_class(lpot_knl, order=order)], value_dtypes=np.complex128) # }}} # {{{ set up geometry # r,a,b match the corresponding letters from G. J. Rodin and O. Steinbach, # Boundary Element Preconditioners for problems defined on slender domains. # http://dx.doi.org/10.1137/S1064827500372067 a = 1 b = 1 / aspect_ratio def map_to_curve(t): t = t * (2 * np.pi) x = a * np.cos(t) y = b * np.sin(t) w = (np.zeros_like(t) + 1) / len(t) return x, y, w from curve import CurveGrid native_t = np.linspace(0, 1, nsrc, endpoint=False) native_x, native_y, native_weights = map_to_curve(native_t) native_curve = CurveGrid(native_x, native_y) ovsmp_t = np.linspace(0, 1, novsmp, endpoint=False) ovsmp_x, ovsmp_y, ovsmp_weights = map_to_curve(ovsmp_t) ovsmp_curve = CurveGrid(ovsmp_x, ovsmp_y) curve_len = np.sum(ovsmp_weights * ovsmp_curve.speed) hovsmp = curve_len / novsmp center_dist = 5 * hovsmp if force_center_side is not None: center_side = force_center_side * np.ones(len(native_curve)) else: center_side = -np.sign(native_curve.mean_curvature) centers = (native_curve.pos + center_side[:, np.newaxis] * center_dist * native_curve.normal) #native_curve.plot() #pt.show() volpot_kwargs = knl_kwargs.copy() lpot_kwargs = knl_kwargs.copy() if what_operator == "D": volpot_kwargs["src_derivative_dir"] = native_curve.normal if what_operator_lpot == "D": lpot_kwargs["src_derivative_dir"] = ovsmp_curve.normal if what_operator_lpot == "S'": lpot_kwargs["tgt_derivative_dir"] = native_curve.normal # }}} if 0: # {{{ build matrix from fourier import make_fourier_interp_matrix fim = make_fourier_interp_matrix(novsmp, nsrc) from sumpy.tools import build_matrix from scipy.sparse.linalg import LinearOperator def apply_lpot(x): xovsmp = np.dot(fim, x) evt, (y, ) = lpot(queue, native_curve.pos, ovsmp_curve.pos, centers, [xovsmp * ovsmp_curve.speed * ovsmp_weights], expansion_radii=np.ones(centers.shape[1]), **lpot_kwargs) return y op = LinearOperator((nsrc, nsrc), apply_lpot) mat = build_matrix(op, dtype=np.complex128) w, v = la.eig(mat) pt.plot(w.real, "o-") #import sys; sys.exit(0) return # }}} # {{{ compute potentials mode_nr = 0 density = np.cos(mode_nr * 2 * np.pi * native_t).astype(np.complex128) ovsmp_density = np.cos(mode_nr * 2 * np.pi * ovsmp_t).astype(np.complex128) evt, (vol_pot, ) = p2p(queue, fp.points, native_curve.pos, [native_curve.speed * native_weights * density], **volpot_kwargs) evt, (curve_pot, ) = lpot( queue, native_curve.pos, ovsmp_curve.pos, centers, [ovsmp_density * ovsmp_curve.speed * ovsmp_weights], expansion_radii=np.ones(centers.shape[1]), **lpot_kwargs) # }}} if 0: # {{{ plot on-surface potential in 2D pt.plot(curve_pot, label="pot") pt.plot(density, label="dens") pt.legend() pt.show() # }}} fp.write_vtk_file("potential.vts", [("potential", vol_pot.real)]) if 0: # {{{ 2D false-color plot pt.clf() plotval = np.log10(1e-20 + np.abs(vol_pot)) im = fp.show_scalar_in_matplotlib(plotval.real) from matplotlib.colors import Normalize im.set_norm(Normalize(vmin=-2, vmax=1)) src = native_curve.pos pt.plot(src[:, 0], src[:, 1], "o-k") # close the curve pt.plot(src[-1::-len(src) + 1, 0], src[-1::-len(src) + 1, 1], "o-k") #pt.gca().set_aspect("equal", "datalim") cb = pt.colorbar(shrink=0.9) cb.set_label(r"$\log_{10}(\mathdefault{Error})$") #from matplotlib.ticker import NullFormatter #pt.gca().xaxis.set_major_formatter(NullFormatter()) #pt.gca().yaxis.set_major_formatter(NullFormatter()) fp.set_matplotlib_limits() # }}} else: # {{{ 3D plots plotval_vol = vol_pot.real plotval_c = curve_pot.real scale = 1 if 0: # crop singularities--doesn't work very well neighbors = [ np.roll(plotval_vol, 3, 0), np.roll(plotval_vol, -3, 0), np.roll(plotval_vol, 6, 0), np.roll(plotval_vol, -6, 0), ] avg = np.average(np.abs(plotval_vol)) outlier_flag = sum(np.abs(plotval_vol - nb) for nb in neighbors) > avg plotval_vol[outlier_flag] = sum( nb[outlier_flag] for nb in neighbors) / len(neighbors) fp.show_scalar_in_mayavi(scale * plotval_vol, max_val=1) from mayavi import mlab mlab.colorbar() if 1: mlab.points3d(native_curve.pos[0], native_curve.pos[1], scale * plotval_c, scale_factor=0.02) mlab.show()
def run_int_eq_test( cl_ctx, queue, curve_f, nelements, qbx_order, bc_type, loc_sign, k, target_order, source_order): mesh = make_curve_mesh(curve_f, np.linspace(0, 1, nelements+1), target_order) if 0: from pytential.visualization import show_mesh show_mesh(mesh) pt.gca().set_aspect("equal") pt.show() from pytential.qbx import QBXLayerPotentialSource from meshmode.discretization import Discretization from meshmode.discretization.poly_element import \ InterpolatoryQuadratureSimplexGroupFactory density_discr = Discretization( cl_ctx, mesh, InterpolatoryQuadratureSimplexGroupFactory(target_order)) if source_order is None: source_order = 4*target_order qbx = QBXLayerPotentialSource( density_discr, fine_order=source_order, qbx_order=qbx_order, # Don't use FMM for now fmm_order=False) # {{{ set up operator from pytential.symbolic.pde.scalar import ( DirichletOperator, NeumannOperator) from sumpy.kernel import LaplaceKernel, HelmholtzKernel, AxisTargetDerivative if k: knl = HelmholtzKernel(2) knl_kwargs = {"k": k} else: knl = LaplaceKernel(2) knl_kwargs = {} if knl.is_complex_valued: dtype = np.complex128 else: dtype = np.float64 if bc_type == "dirichlet": op = DirichletOperator((knl, knl_kwargs), loc_sign, use_l2_weighting=True) elif bc_type == "neumann": op = NeumannOperator((knl, knl_kwargs), loc_sign, use_l2_weighting=True, use_improved_operator=False) else: assert False op_u = op.operator(sym.var("u")) # }}} # {{{ set up test data inner_radius = 0.1 outer_radius = 2 if loc_sign < 0: test_src_geo_radius = outer_radius test_tgt_geo_radius = inner_radius else: test_src_geo_radius = inner_radius test_tgt_geo_radius = outer_radius point_sources = make_circular_point_group(10, test_src_geo_radius, func=lambda x: x**1.5) test_targets = make_circular_point_group(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 # }}} if 0: # 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())(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() # {{{ establish BCs from sumpy.p2p import P2P pot_p2p = P2P(cl_ctx, [knl], exclude_self=False, value_dtypes=dtype) evt, (test_direct,) = pot_p2p( queue, test_targets, point_sources, [source_charges], out_host=False, **knl_kwargs) nodes = density_discr.nodes() evt, (src_pot,) = pot_p2p( queue, nodes, point_sources, [source_charges], **knl_kwargs) grad_p2p = P2P(cl_ctx, [AxisTargetDerivative(0, knl), AxisTargetDerivative(1, knl)], exclude_self=False, value_dtypes=dtype) evt, (src_grad0, src_grad1) = grad_p2p( queue, nodes, point_sources, [source_charges], **knl_kwargs) if bc_type == "dirichlet": bc = src_pot elif bc_type == "neumann": normal = bind(density_discr, sym.normal())(queue).as_vector(np.object) bc = (src_grad0*normal[0] + src_grad1*normal[1]) # }}} # {{{ solve bound_op = bind(qbx, op_u) rhs = bind(density_discr, op.prepare_rhs(sym.var("bc")))(queue, bc=bc) from pytential.solve import gmres gmres_result = gmres( bound_op.scipy_op(queue, "u", k=k), rhs, tol=1e-14, progress=True, hard_failure=False) u = gmres_result.solution print("gmres state:", gmres_result.state) if 0: # {{{ build matrix for spectrum check from sumpy.tools import build_matrix mat = build_matrix(bound_op.scipy_op("u")) 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() # }}} # }}} # {{{ error check from pytential.target import PointsTarget bound_tgt_op = bind((qbx, PointsTarget(test_targets)), op.representation(sym.var("u"))) test_via_bdry = bound_tgt_op(queue, u=u, k=k) err = test_direct-test_via_bdry err = err.get() test_direct = test_direct.get() test_via_bdry = test_via_bdry.get() # {{{ remove effect of net source charge if k == 0 and 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)) # {{{ test tangential derivative bound_t_deriv_op = bind(qbx, op.representation( sym.var("u"), map_potentials=sym.tangential_derivative, qbx_forced_limit=loc_sign)) #print(bound_t_deriv_op.code) tang_deriv_from_src = bound_t_deriv_op(queue, u=u).as_scalar().get() tangent = bind( density_discr, sym.pseudoscalar()/sym.area_element())(queue).as_vector(np.object) tang_deriv_ref = (src_grad0 * tangent[0] + src_grad1 * tangent[1]).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) # }}} # {{{ plotting if 0: fplot = FieldPlotter(np.zeros(2), extent=1.25*2*max(test_src_geo_radius, test_tgt_geo_radius), npoints=200) #pt.plot(u) #pt.show() evt, (fld_from_src,) = pot_p2p( queue, fplot.points, point_sources, [source_charges], **knl_kwargs) fld_from_bdry = bind( (qbx, PointsTarget(fplot.points)), op.representation(sym.var("u")) )(queue, u=u, k=k) fld_from_src = fld_from_src.get() fld_from_bdry = fld_from_bdry.get() nodes = density_discr.nodes().get(queue=queue) def prep(): pt.plot(point_sources[0], point_sources[1], "o", label="Monopole 'Point Charges'") pt.plot(test_targets[0], test_targets[1], "v", label="Observation Points") pt.plot(nodes[0], nodes[1], "k-", label=r"$\Gamma$") from matplotlib.cm import get_cmap cmap = get_cmap() cmap._init() if 0: cmap._lut[(cmap.N*99)//100:, -1] = 0 # make last percent transparent? prep() if 1: pt.subplot(131) pt.title("Field error (loc_sign=%s)" % loc_sign) log_err = np.log10(1e-20+np.abs(fld_from_src-fld_from_bdry)) log_err = np.minimum(-3, log_err) fplot.show_scalar_in_matplotlib(log_err, cmap=cmap) #from matplotlib.colors import Normalize #im.set_norm(Normalize(vmin=-6, vmax=1)) cb = pt.colorbar(shrink=0.9) cb.set_label(r"$\log_{10}(\mathdefault{Error})$") if 1: pt.subplot(132) prep() pt.title("Source Field") fplot.show_scalar_in_matplotlib( fld_from_src.real, max_val=3) pt.colorbar(shrink=0.9) if 1: pt.subplot(133) prep() pt.title("Solved Field") fplot.show_scalar_in_matplotlib( fld_from_bdry.real, max_val=3) pt.colorbar(shrink=0.9) # total field #fplot.show_scalar_in_matplotlib( #fld_from_src.real+fld_from_bdry.real, max_val=0.1) #pt.colorbar() pt.legend(loc="best", prop=dict(size=15)) from matplotlib.ticker import NullFormatter pt.gca().xaxis.set_major_formatter(NullFormatter()) pt.gca().yaxis.set_major_formatter(NullFormatter()) pt.gca().set_aspect("equal") if 0: border_factor_top = 0.9 border_factor = 0.3 xl, xh = pt.xlim() xhsize = 0.5*(xh-xl) pt.xlim(xl-border_factor*xhsize, xh+border_factor*xhsize) yl, yh = pt.ylim() yhsize = 0.5*(yh-yl) pt.ylim(yl-border_factor_top*yhsize, yh+border_factor*yhsize) #pt.savefig("helmholtz.pdf", dpi=600) pt.show() # }}} class Result(Record): pass return Result( 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 draw_pot_figure(aspect_ratio, nsrc=100, novsmp=None, helmholtz_k=0, what_operator="S", what_operator_lpot=None, order=4, ovsmp_center_exp=0.66, force_center_side=None): import logging logging.basicConfig(level=logging.INFO) if novsmp is None: novsmp = 4*nsrc if what_operator_lpot is None: what_operator_lpot = what_operator ctx = cl.create_some_context() queue = cl.CommandQueue(ctx) # {{{ make plot targets center = np.asarray([0, 0], dtype=np.float64) from sumpy.visualization import FieldPlotter fp = FieldPlotter(center, npoints=1000, extent=6) # }}} # {{{ make p2p kernel calculator from sumpy.p2p import P2P from sumpy.kernel import LaplaceKernel, HelmholtzKernel from sumpy.expansion.local import H2DLocalExpansion, LineTaylorLocalExpansion if helmholtz_k: if isinstance(helmholtz_k, complex): knl = HelmholtzKernel(2, allow_evanescent=True) expn_class = H2DLocalExpansion knl_kwargs = {"k": helmholtz_k} else: knl = HelmholtzKernel(2) expn_class = H2DLocalExpansion knl_kwargs = {"k": helmholtz_k} else: knl = LaplaceKernel(2) expn_class = LineTaylorLocalExpansion knl_kwargs = {} vol_knl = process_kernel(knl, what_operator) p2p = P2P(ctx, [vol_knl], exclude_self=False, value_dtypes=np.complex128) lpot_knl = process_kernel(knl, what_operator_lpot) from sumpy.qbx import LayerPotential lpot = LayerPotential(ctx, [ expn_class(lpot_knl, order=order)], value_dtypes=np.complex128) # }}} # {{{ set up geometry # r,a,b match the corresponding letters from G. J. Rodin and O. Steinbach, # Boundary Element Preconditioners for problems defined on slender domains. # http://dx.doi.org/10.1137/S1064827500372067 a = 1 b = 1/aspect_ratio def map_to_curve(t): t = t*(2*np.pi) x = a*np.cos(t) y = b*np.sin(t) w = (np.zeros_like(t)+1)/len(t) return x, y, w from curve import CurveGrid native_t = np.linspace(0, 1, nsrc, endpoint=False) native_x, native_y, native_weights = map_to_curve(native_t) native_curve = CurveGrid(native_x, native_y) ovsmp_t = np.linspace(0, 1, novsmp, endpoint=False) ovsmp_x, ovsmp_y, ovsmp_weights = map_to_curve(ovsmp_t) ovsmp_curve = CurveGrid(ovsmp_x, ovsmp_y) curve_len = np.sum(ovsmp_weights * ovsmp_curve.speed) hovsmp = curve_len/novsmp center_dist = 5*hovsmp if force_center_side is not None: center_side = force_center_side*np.ones(len(native_curve)) else: center_side = -np.sign(native_curve.mean_curvature) centers = (native_curve.pos + center_side[:, np.newaxis] * center_dist*native_curve.normal) #native_curve.plot() #pt.show() volpot_kwargs = knl_kwargs.copy() lpot_kwargs = knl_kwargs.copy() if what_operator == "D": volpot_kwargs["src_derivative_dir"] = native_curve.normal if what_operator_lpot == "D": lpot_kwargs["src_derivative_dir"] = ovsmp_curve.normal if what_operator_lpot == "S'": lpot_kwargs["tgt_derivative_dir"] = native_curve.normal # }}} if 0: # {{{ build matrix from fourier import make_fourier_interp_matrix fim = make_fourier_interp_matrix(novsmp, nsrc) from sumpy.tools import build_matrix from scipy.sparse.linalg import LinearOperator def apply_lpot(x): xovsmp = np.dot(fim, x) evt, (y,) = lpot(queue, native_curve.pos, ovsmp_curve.pos, centers, [xovsmp * ovsmp_curve.speed * ovsmp_weights], expansion_radii=np.ones(centers.shape[1]), **lpot_kwargs) return y op = LinearOperator((nsrc, nsrc), apply_lpot) mat = build_matrix(op, dtype=np.complex128) w, v = la.eig(mat) pt.plot(w.real, "o-") #import sys; sys.exit(0) return # }}} # {{{ compute potentials mode_nr = 0 density = np.cos(mode_nr*2*np.pi*native_t).astype(np.complex128) ovsmp_density = np.cos(mode_nr*2*np.pi*ovsmp_t).astype(np.complex128) evt, (vol_pot,) = p2p(queue, fp.points, native_curve.pos, [native_curve.speed*native_weights*density], **volpot_kwargs) evt, (curve_pot,) = lpot(queue, native_curve.pos, ovsmp_curve.pos, centers, [ovsmp_density * ovsmp_curve.speed * ovsmp_weights], expansion_radii=np.ones(centers.shape[1]), **lpot_kwargs) # }}} if 0: # {{{ plot on-surface potential in 2D pt.plot(curve_pot, label="pot") pt.plot(density, label="dens") pt.legend() pt.show() # }}} fp.write_vtk_file("potential.vts", [ ("potential", vol_pot.real) ]) if 0: # {{{ 2D false-color plot pt.clf() plotval = np.log10(1e-20+np.abs(vol_pot)) im = fp.show_scalar_in_matplotlib(plotval.real) from matplotlib.colors import Normalize im.set_norm(Normalize(vmin=-2, vmax=1)) src = native_curve.pos pt.plot(src[:, 0], src[:, 1], "o-k") # close the curve pt.plot(src[-1::-len(src)+1, 0], src[-1::-len(src)+1, 1], "o-k") #pt.gca().set_aspect("equal", "datalim") cb = pt.colorbar(shrink=0.9) cb.set_label(r"$\log_{10}(\mathdefault{Error})$") #from matplotlib.ticker import NullFormatter #pt.gca().xaxis.set_major_formatter(NullFormatter()) #pt.gca().yaxis.set_major_formatter(NullFormatter()) fp.set_matplotlib_limits() # }}} else: # {{{ 3D plots plotval_vol = vol_pot.real plotval_c = curve_pot.real scale = 1 if 0: # crop singularities--doesn't work very well neighbors = [ np.roll(plotval_vol, 3, 0), np.roll(plotval_vol, -3, 0), np.roll(plotval_vol, 6, 0), np.roll(plotval_vol, -6, 0), ] avg = np.average(np.abs(plotval_vol)) outlier_flag = sum( np.abs(plotval_vol-nb) for nb in neighbors) > avg plotval_vol[outlier_flag] = sum( nb[outlier_flag] for nb in neighbors)/len(neighbors) fp.show_scalar_in_mayavi(scale*plotval_vol, max_val=1) from mayavi import mlab mlab.colorbar() if 1: mlab.points3d( native_curve.pos[0], native_curve.pos[1], scale*plotval_c, scale_factor=0.02) mlab.show()
#fplot.show_scalar_in_mayavi(fld_in_vol.real, max_val=5) fplot.write_vtk_file( "potential.vts", [ ("potential", fld_in_vol) ] ) if 0: def apply_op(density): return bound_bdry_op( queue, sigma=cl.array.to_device(queue, density), k=k).get() from sumpy.tools import build_matrix n = len(sigma) mat = build_matrix(apply_op, dtype=np.float64, shape=(n, n)) import matplotlib.pyplot as pt pt.imshow(mat) pt.colorbar() pt.show() if 0: # {{{ plot boundary field fld_on_bdry = bound_bdry_op(queue, sigma=sigma, k=k).get() nodes_host = density_discr.nodes().get(queue=queue) #mlab.points3d(nodes_host[0], nodes_host[1], fld_on_bdry.real, scale_factor=0.03) # }}}
("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, **concrete_knl_kwargs)) 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":
def main(): import logging logging.basicConfig(level=logging.WARNING) # INFO for more progress info cl_ctx = cl.create_some_context() queue = cl.CommandQueue(cl_ctx) from meshmode.mesh.generation import ( # noqa make_curve_mesh, starfish, ellipse, drop) mesh = make_curve_mesh( #lambda t: ellipse(1, t), starfish, np.linspace(0, 1, nelements+1), target_order) 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(target_order)) qbx, _ = QBXLayerPotentialSource(pre_density_discr, 4*target_order, qbx_order, fmm_order=qbx_order+3, target_association_tolerance=0.005).with_refinement() density_discr = qbx.density_discr nodes = density_discr.nodes().with_queue(queue) angle = cl.clmath.atan2(nodes[1], nodes[0]) def op(**kwargs): kwargs.update(kernel_kwargs) #op = sym.d_dx(sym.S(kernel, sym.var("sigma"), **kwargs)) return sym.D(kernel, sym.var("sigma"), **kwargs) #op = sym.S(kernel, sym.var("sigma"), qbx_forced_limit=None, **kwargs) sigma = cl.clmath.cos(mode_nr*angle) if 0: sigma = 0*angle from random import randrange for i in range(5): sigma[randrange(len(sigma))] = 1 if isinstance(kernel, HelmholtzKernel): sigma = sigma.astype(np.complex128) bound_bdry_op = bind(qbx, op()) #mlab.figure(bgcolor=(1, 1, 1)) if 1: fplot = FieldPlotter(np.zeros(2), extent=5, npoints=1000) from pytential.target import PointsTarget targets_dev = cl.array.to_device(queue, fplot.points) fld_in_vol = bind( (qbx, PointsTarget(targets_dev)), op(qbx_forced_limit=None))(queue, sigma=sigma, k=k).get() if enable_mayavi: fplot.show_scalar_in_mayavi(fld_in_vol.real, max_val=5) else: fplot.write_vtk_file( "potential-2d.vts", [ ("potential", fld_in_vol) ] ) if 0: def apply_op(density): return bound_bdry_op( queue, sigma=cl.array.to_device(queue, density), k=k).get() from sumpy.tools import build_matrix n = len(sigma) mat = build_matrix(apply_op, dtype=np.float64, shape=(n, n)) import matplotlib.pyplot as pt pt.imshow(mat) pt.colorbar() pt.show() if enable_mayavi: # {{{ plot boundary field fld_on_bdry = bound_bdry_op(queue, sigma=sigma, k=k).get() nodes_host = density_discr.nodes().get(queue=queue) mlab.points3d(nodes_host[0], nodes_host[1], fld_on_bdry.real, scale_factor=0.03) # }}} if enable_mayavi: mlab.colorbar() mlab.show()
def main(): import logging logging.basicConfig(level=logging.WARNING) # INFO for more progress info cl_ctx = cl.create_some_context() queue = cl.CommandQueue(cl_ctx) from meshmode.mesh.generation import ( # noqa make_curve_mesh, starfish, ellipse, drop) mesh = make_curve_mesh( #lambda t: ellipse(1, t), starfish, np.linspace(0, 1, nelements + 1), target_order) 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(target_order)) qbx, _ = QBXLayerPotentialSource( pre_density_discr, 4 * target_order, qbx_order, fmm_order=qbx_order + 3, target_association_tolerance=0.005).with_refinement() density_discr = qbx.density_discr nodes = density_discr.nodes().with_queue(queue) angle = cl.clmath.atan2(nodes[1], nodes[0]) def op(**kwargs): kwargs.update(kernel_kwargs) #op = sym.d_dx(sym.S(kernel, sym.var("sigma"), **kwargs)) return sym.D(kernel, sym.var("sigma"), **kwargs) #op = sym.S(kernel, sym.var("sigma"), qbx_forced_limit=None, **kwargs) sigma = cl.clmath.cos(mode_nr * angle) if 0: sigma = 0 * angle from random import randrange for i in range(5): sigma[randrange(len(sigma))] = 1 if isinstance(kernel, HelmholtzKernel): sigma = sigma.astype(np.complex128) bound_bdry_op = bind(qbx, op()) #mlab.figure(bgcolor=(1, 1, 1)) if 1: fplot = FieldPlotter(np.zeros(2), extent=5, npoints=1000) from pytential.target import PointsTarget targets_dev = cl.array.to_device(queue, fplot.points) fld_in_vol = bind((qbx, PointsTarget(targets_dev)), op(qbx_forced_limit=None))(queue, sigma=sigma, k=k).get() if enable_mayavi: fplot.show_scalar_in_mayavi(fld_in_vol.real, max_val=5) else: fplot.write_vtk_file("potential-2d.vts", [("potential", fld_in_vol)]) if 0: def apply_op(density): return bound_bdry_op(queue, sigma=cl.array.to_device(queue, density), k=k).get() from sumpy.tools import build_matrix n = len(sigma) mat = build_matrix(apply_op, dtype=np.float64, shape=(n, n)) import matplotlib.pyplot as pt pt.imshow(mat) pt.colorbar() pt.show() if enable_mayavi: # {{{ plot boundary field fld_on_bdry = bound_bdry_op(queue, sigma=sigma, k=k).get() nodes_host = density_discr.nodes().get(queue=queue) mlab.points3d(nodes_host[0], nodes_host[1], fld_on_bdry.real, scale_factor=0.03) # }}} if enable_mayavi: mlab.colorbar() mlab.show()