def test_off_surface_eval(ctx_factory, use_fmm, do_plot=False): logging.basicConfig(level=logging.INFO) cl_ctx = ctx_factory() queue = cl.CommandQueue(cl_ctx) # prevent cache 'splosion from sympy.core.cache import clear_cache clear_cache() nelements = 30 target_order = 8 qbx_order = 3 if use_fmm: fmm_order = qbx_order else: fmm_order = False mesh = make_curve_mesh(partial(ellipse, 3), 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=fmm_order, ).with_refinement() density_discr = qbx.density_discr from sumpy.kernel import LaplaceKernel op = sym.D(LaplaceKernel(2), sym.var("sigma"), qbx_forced_limit=-2) sigma = density_discr.zeros(queue) + 1 fplot = FieldPlotter(np.zeros(2), extent=0.54, npoints=30) from pytential.target import PointsTarget fld_in_vol = bind((qbx, PointsTarget(fplot.points)), op)(queue, sigma=sigma) err = cl.clmath.fabs(fld_in_vol - (-1)) linf_err = cl.array.max(err).get() print("l_inf error:", linf_err) if do_plot: fplot.show_scalar_in_matplotlib(fld_in_vol.get()) import matplotlib.pyplot as pt pt.colorbar() pt.show() assert linf_err < 1e-3
def test_off_surface_eval(actx_factory, use_fmm, visualize=False): logging.basicConfig(level=logging.INFO) actx = actx_factory() # prevent cache 'splosion from sympy.core.cache import clear_cache clear_cache() nelements = 30 target_order = 8 qbx_order = 3 if use_fmm: fmm_order = qbx_order else: fmm_order = False mesh = mgen.make_curve_mesh(partial(mgen.ellipse, 3), 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=fmm_order, ) from pytential.target import PointsTarget fplot = FieldPlotter(np.zeros(2), extent=0.54, npoints=30) targets = PointsTarget(actx.freeze(actx.from_numpy(fplot.points))) places = GeometryCollection((qbx, targets)) density_discr = places.get_discretization(places.auto_source.geometry) from sumpy.kernel import LaplaceKernel op = sym.D(LaplaceKernel(2), sym.var("sigma"), qbx_forced_limit=-2) sigma = density_discr.zeros(actx) + 1 fld_in_vol = bind(places, op)(actx, sigma=sigma) fld_in_vol_exact = -1 linf_err = actx.to_numpy( actx.np.linalg.norm(fld_in_vol - fld_in_vol_exact, ord=np.inf)) logger.info("l_inf error: %.12e", linf_err) if visualize: fplot.show_scalar_in_matplotlib(actx.to_numpy(fld_in_vol)) import matplotlib.pyplot as pt pt.colorbar() pt.show() assert linf_err < 1e-3
def main(): from sumpy.kernel import ( # noqa: F401 YukawaKernel, HelmholtzKernel, LaplaceKernel) tctx = t.ToyContext( cl.create_some_context(), #LaplaceKernel(2), YukawaKernel(2), extra_kernel_kwargs={"lam": 5}, #HelmholtzKernel(2), extra_kernel_kwargs={"k": 0.3}, ) pt_src = t.PointSources(tctx, np.random.rand(2, 50) - 0.5, np.ones(50)) fp = FieldPlotter([3, 0], extent=8) if 0 and plt is not None: t.logplot(fp, pt_src, cmap="jet") plt.colorbar() plt.show() mexp = t.multipole_expand(pt_src, [0, 0], 5) mexp2 = t.multipole_expand(mexp, [0, 0.25]) # noqa: F841 lexp = t.local_expand(mexp, [3, 0]) lexp2 = t.local_expand(lexp, [3, 1], 3) #diff = mexp - pt_src #diff = mexp2 - pt_src diff = lexp2 - pt_src print(t.l_inf(diff, 1.2, center=lexp2.center)) if 1 and plt is not None: t.logplot(fp, diff, cmap="jet", vmin=-3, vmax=0) plt.colorbar() plt.show()
def test_unregularized_off_surface_fmm_vs_direct(ctx_factory): cl_ctx = ctx_factory() queue = cl.CommandQueue(cl_ctx) actx = PyOpenCLArrayContext(queue) nelements = 300 target_order = 8 fmm_order = 4 # {{{ geometry mesh = make_curve_mesh(WobblyCircle.random(8, seed=30), np.linspace(0, 1, nelements+1), target_order) from pytential.unregularized import UnregularizedLayerPotentialSource from meshmode.discretization import Discretization from meshmode.discretization.poly_element import \ InterpolatoryQuadratureSimplexGroupFactory density_discr = Discretization( actx, mesh, InterpolatoryQuadratureSimplexGroupFactory(target_order)) direct = UnregularizedLayerPotentialSource( density_discr, fmm_order=False, ) fmm = direct.copy( fmm_level_to_order=lambda kernel, kernel_args, tree, level: fmm_order) sigma = density_discr.zeros(actx) + 1 fplot = FieldPlotter(np.zeros(2), extent=5, npoints=100) from pytential.target import PointsTarget ptarget = PointsTarget(fplot.points) from pytential import GeometryCollection places = GeometryCollection({ "unregularized_direct": direct, "unregularized_fmm": fmm, "targets": ptarget}) # }}} # {{{ check from sumpy.kernel import LaplaceKernel op = sym.D(LaplaceKernel(2), sym.var("sigma"), qbx_forced_limit=None) direct_fld_in_vol = bind(places, op, auto_where=("unregularized_direct", "targets"))( actx, sigma=sigma) fmm_fld_in_vol = bind(places, op, auto_where=("unregularized_fmm", "targets"))(actx, sigma=sigma) err = actx.np.fabs(fmm_fld_in_vol - direct_fld_in_vol) linf_err = actx.to_numpy(err).max() print("l_inf error:", linf_err) assert linf_err < 5e-3
def l_inf(psource, radius, center=None, npoints=100, debug=False): if center is None: center = psource.center restr = psource * OneOnBallPotential(psource.toy_ctx, center, radius) from sumpy.visualization import FieldPlotter fp = FieldPlotter(center, extent=2 * radius, npoints=npoints) z = restr.eval(fp.points) if debug: fp.show_scalar_in_matplotlib(np.log10(np.abs(z + 1e-15))) import matplotlib.pyplot as pt pt.colorbar() pt.show() return np.max(np.abs(z))
def l_inf(psource, radius, center=None, npoints=100, debug=False): if center is None: center = psource.center restr = psource * OneOnBallPotential(psource.toy_ctx, center, radius) from sumpy.visualization import FieldPlotter fp = FieldPlotter(center, extent=2*radius, npoints=npoints) z = restr.eval(fp.points) if debug: fp.show_scalar_in_matplotlib( np.log10(np.abs(z + 1e-15))) import matplotlib.pyplot as pt pt.colorbar() pt.show() return np.max(np.abs(z))
def test_unregularized_off_surface_fmm_vs_direct(ctx_factory): cl_ctx = ctx_factory() queue = cl.CommandQueue(cl_ctx) nelements = 300 target_order = 8 fmm_order = 4 mesh = make_curve_mesh(WobblyCircle.random(8, seed=30), np.linspace(0, 1, nelements + 1), target_order) from pytential.unregularized import UnregularizedLayerPotentialSource from meshmode.discretization import Discretization from meshmode.discretization.poly_element import \ InterpolatoryQuadratureSimplexGroupFactory density_discr = Discretization( cl_ctx, mesh, InterpolatoryQuadratureSimplexGroupFactory(target_order)) direct = UnregularizedLayerPotentialSource( density_discr, fmm_order=False, ) fmm = direct.copy( fmm_level_to_order=lambda kernel, kernel_args, tree, level: fmm_order) sigma = density_discr.zeros(queue) + 1 fplot = FieldPlotter(np.zeros(2), extent=5, npoints=100) from pytential.target import PointsTarget ptarget = PointsTarget(fplot.points) from sumpy.kernel import LaplaceKernel op = sym.D(LaplaceKernel(2), sym.var("sigma"), qbx_forced_limit=None) direct_fld_in_vol = bind((direct, ptarget), op)(queue, sigma=sigma) fmm_fld_in_vol = bind((fmm, ptarget), op)(queue, sigma=sigma) err = cl.clmath.fabs(fmm_fld_in_vol - direct_fld_in_vol) linf_err = cl.array.max(err).get() print("l_inf error:", linf_err) assert linf_err < 5e-3
def main(mesh_name="ellipsoid"): import logging logger = logging.getLogger(__name__) logging.basicConfig(level=logging.WARNING) # INFO for more progress info cl_ctx = cl.create_some_context() queue = cl.CommandQueue(cl_ctx) actx = PyOpenCLArrayContext(queue) if mesh_name == "ellipsoid": cad_file_name = "geometries/ellipsoid.step" h = 0.6 elif mesh_name == "two-cylinders": cad_file_name = "geometries/two-cylinders-smooth.step" h = 0.4 else: raise ValueError("unknown mesh name: %s" % mesh_name) from meshmode.mesh.io import generate_gmsh, FileSource mesh = generate_gmsh( FileSource(cad_file_name), 2, order=2, other_options=["-string", "Mesh.CharacteristicLengthMax = %g;" % h], target_unit="MM") from meshmode.mesh.processing import perform_flips # Flip elements--gmsh generates inside-out geometry. mesh = perform_flips(mesh, np.ones(mesh.nelements)) from meshmode.mesh.processing import find_bounding_box bbox_min, bbox_max = find_bounding_box(mesh) bbox_center = 0.5 * (bbox_min + bbox_max) bbox_size = max(bbox_max - bbox_min) / 2 logger.info("%d elements" % mesh.nelements) from pytential.qbx import QBXLayerPotentialSource from meshmode.discretization import Discretization from meshmode.discretization.poly_element import \ InterpolatoryQuadratureSimplexGroupFactory density_discr = Discretization( actx, mesh, InterpolatoryQuadratureSimplexGroupFactory(target_order)) qbx = QBXLayerPotentialSource(density_discr, 4 * target_order, qbx_order, fmm_order=qbx_order + 3, target_association_tolerance=0.15) from pytential.target import PointsTarget fplot = FieldPlotter(bbox_center, extent=3.5 * bbox_size, npoints=150) from pytential import GeometryCollection places = GeometryCollection( { "qbx": qbx, "targets": PointsTarget(fplot.points) }, auto_where="qbx") density_discr = places.get_discretization("qbx") nodes = thaw(actx, density_discr.nodes()) angle = actx.np.arctan2(nodes[1], nodes[0]) if k: kernel = HelmholtzKernel(3) else: kernel = LaplaceKernel(3) #op = sym.d_dx(sym.S(kernel, sym.var("sigma"), qbx_forced_limit=None)) op = sym.D(kernel, sym.var("sigma"), qbx_forced_limit=None) #op = sym.S(kernel, sym.var("sigma"), qbx_forced_limit=None) sigma = actx.np.cos(mode_nr * angle) if 0: from meshmode.dof_array import flatten, unflatten sigma = flatten(0 * angle) from random import randrange for i in range(5): sigma[randrange(len(sigma))] = 1 sigma = unflatten(actx, density_discr, sigma) if isinstance(kernel, HelmholtzKernel): for i, elem in np.ndenumerate(sigma): sigma[i] = elem.astype(np.complex128) fld_in_vol = actx.to_numpy( bind(places, op, auto_where=("qbx", "targets"))(actx, sigma=sigma, k=k)) #fplot.show_scalar_in_mayavi(fld_in_vol.real, max_val=5) fplot.write_vtk_file("layerpot-3d-potential.vts", [("potential", fld_in_vol)]) bdry_normals = bind(places, sym.normal( density_discr.ambient_dim))(actx).as_vector(dtype=object) from meshmode.discretization.visualization import make_visualizer bdry_vis = make_visualizer(actx, density_discr, target_order) bdry_vis.write_vtk_file("layerpot-3d-density.vtu", [ ("sigma", sigma), ("bdry_normals", bdry_normals), ])
def test_p2e2p(ctx_factory, base_knl, expn_class, order, with_source_derivative): #logging.basicConfig(level=logging.INFO) from sympy.core.cache import clear_cache clear_cache() ctx = ctx_factory() queue = cl.CommandQueue(ctx) np.random.seed(17) res = 100 nsources = 100 extra_kwargs = {} if isinstance(base_knl, HelmholtzKernel): if base_knl.allow_evanescent: extra_kwargs["k"] = 0.2 * (0.707 + 0.707j) else: extra_kwargs["k"] = 0.2 if isinstance(base_knl, StokesletKernel): extra_kwargs["mu"] = 0.2 if with_source_derivative: knl = DirectionalSourceDerivative(base_knl, "dir_vec") else: knl = base_knl out_kernels = [ knl, AxisTargetDerivative(0, knl), ] expn = expn_class(knl, order=order) from sumpy import P2EFromSingleBox, E2PFromSingleBox, P2P p2e = P2EFromSingleBox(ctx, expn, kernels=[knl]) e2p = E2PFromSingleBox(ctx, expn, kernels=out_kernels) p2p = P2P(ctx, out_kernels, exclude_self=False) from pytools.convergence import EOCRecorder eoc_rec_pot = EOCRecorder() eoc_rec_grad_x = EOCRecorder() from sumpy.expansion.local import LocalExpansionBase if issubclass(expn_class, LocalExpansionBase): h_values = [1 / 5, 1 / 7, 1 / 20] else: h_values = [1 / 2, 1 / 3, 1 / 5] center = np.array([2, 1, 0][:knl.dim], np.float64) sources = (0.7 * (-0.5 + np.random.rand(knl.dim, nsources).astype(np.float64)) + center[:, np.newaxis]) strengths = np.ones(nsources, dtype=np.float64) * (1 / nsources) source_boxes = np.array([0], dtype=np.int32) box_source_starts = np.array([0], dtype=np.int32) box_source_counts_nonchild = np.array([nsources], dtype=np.int32) extra_source_kwargs = extra_kwargs.copy() if isinstance(knl, DirectionalSourceDerivative): alpha = np.linspace(0, 2 * np.pi, nsources, np.float64) dir_vec = np.vstack([np.cos(alpha), np.sin(alpha)]) extra_source_kwargs["dir_vec"] = dir_vec from sumpy.visualization import FieldPlotter for h in h_values: if issubclass(expn_class, LocalExpansionBase): loc_center = np.array([5.5, 0.0, 0.0][:knl.dim]) + center centers = np.array(loc_center, dtype=np.float64).reshape(knl.dim, 1) fp = FieldPlotter(loc_center, extent=h, npoints=res) else: eval_center = np.array([1 / h, 0.0, 0.0][:knl.dim]) + center fp = FieldPlotter(eval_center, extent=0.1, npoints=res) centers = (np.array([0.0, 0.0, 0.0][:knl.dim], dtype=np.float64).reshape(knl.dim, 1) + center[:, np.newaxis]) targets = fp.points rscale = 0.5 # pick something non-1 # {{{ apply p2e evt, (mpoles, ) = p2e( queue, source_boxes=source_boxes, box_source_starts=box_source_starts, box_source_counts_nonchild=box_source_counts_nonchild, centers=centers, sources=sources, strengths=(strengths, ), nboxes=1, tgt_base_ibox=0, rscale=rscale, #flags="print_hl_cl", out_host=True, **extra_source_kwargs) # }}} # {{{ apply e2p ntargets = targets.shape[-1] box_target_starts = np.array([0], dtype=np.int32) box_target_counts_nonchild = np.array([ntargets], dtype=np.int32) evt, ( pot, grad_x, ) = e2p( queue, src_expansions=mpoles, src_base_ibox=0, target_boxes=source_boxes, box_target_starts=box_target_starts, box_target_counts_nonchild=box_target_counts_nonchild, centers=centers, targets=targets, rscale=rscale, #flags="print_hl_cl", out_host=True, **extra_kwargs) # }}} # {{{ compute (direct) reference solution evt, ( pot_direct, grad_x_direct, ) = p2p(queue, targets, sources, (strengths, ), out_host=True, **extra_source_kwargs) err_pot = la.norm((pot - pot_direct) / res**2) err_grad_x = la.norm((grad_x - grad_x_direct) / res**2) if 1: err_pot = err_pot / la.norm((pot_direct) / res**2) err_grad_x = err_grad_x / la.norm((grad_x_direct) / res**2) if 0: import matplotlib.pyplot as pt from matplotlib.colors import Normalize pt.subplot(131) im = fp.show_scalar_in_matplotlib(pot.real) im.set_norm(Normalize(vmin=-0.1, vmax=0.1)) pt.subplot(132) im = fp.show_scalar_in_matplotlib(pot_direct.real) im.set_norm(Normalize(vmin=-0.1, vmax=0.1)) pt.colorbar() pt.subplot(133) im = fp.show_scalar_in_matplotlib( np.log10(1e-15 + np.abs(pot - pot_direct))) im.set_norm(Normalize(vmin=-6, vmax=1)) pt.colorbar() pt.show() # }}} eoc_rec_pot.add_data_point(h, err_pot) eoc_rec_grad_x.add_data_point(h, err_grad_x) print(expn_class, knl, order) print("POTENTIAL:") print(eoc_rec_pot) print("X TARGET DERIVATIVE:") print(eoc_rec_grad_x) tgt_order = order + 1 if issubclass(expn_class, LocalExpansionBase): tgt_order_grad = tgt_order - 1 slack = 0.7 grad_slack = 0.5 else: tgt_order_grad = tgt_order + 1 slack = 0.5 grad_slack = 1 if order <= 2: slack += 1 grad_slack += 1 if isinstance(knl, DirectionalSourceDerivative): slack += 1 grad_slack += 2 if isinstance(base_knl, DirectionalSourceDerivative): slack += 1 grad_slack += 2 if isinstance(base_knl, HelmholtzKernel): if base_knl.allow_evanescent: slack += 0.5 grad_slack += 0.5 if issubclass(expn_class, VolumeTaylorMultipoleExpansionBase): slack += 0.3 grad_slack += 0.3 assert eoc_rec_pot.order_estimate() > tgt_order - slack assert eoc_rec_grad_x.order_estimate() > tgt_order_grad - grad_slack
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 generate_torus rout = 10 rin = 1 if 1: base_mesh = generate_torus(rout, rin, 40, 4, mesh_order) from meshmode.mesh.processing import affine_map, merge_disjoint_meshes # nx = 1 # ny = 1 nz = 1 dz = 0 meshes = [ affine_map(base_mesh, A=np.diag([1, 1, 1]), b=np.array([0, 0, iz * dz])) for iz in range(nz) ] mesh = merge_disjoint_meshes(meshes, single_group=True) if 0: from meshmode.mesh.visualization import draw_curve draw_curve(mesh) import matplotlib.pyplot as plt plt.show() pre_density_discr = Discretization( cl_ctx, mesh, InterpolatoryQuadratureSimplexGroupFactory(bdry_quad_order)) from pytential.qbx import (QBXLayerPotentialSource, QBXTargetAssociationFailedException) qbx, _ = QBXLayerPotentialSource( pre_density_discr, fine_order=bdry_ovsmp_quad_order, qbx_order=qbx_order, fmm_order=fmm_order, ).with_refinement() density_discr = qbx.density_discr # {{{ describe bvp from sumpy.kernel import LaplaceKernel kernel = LaplaceKernel(3) cse = sym.cse sigma_sym = sym.var("sigma") #sqrt_w = sym.sqrt_jac_q_weight(3) sqrt_w = 1 inv_sqrt_w_sigma = cse(sigma_sym / sqrt_w) # -1 for interior Dirichlet # +1 for exterior Dirichlet loc_sign = +1 bdry_op_sym = ( loc_sign * 0.5 * sigma_sym + sqrt_w * (sym.S(kernel, inv_sqrt_w_sigma) + sym.D(kernel, inv_sqrt_w_sigma))) # }}} bound_op = bind(qbx, bdry_op_sym) # {{{ fix rhs and solve nodes = density_discr.nodes().with_queue(queue) source = np.array([rout, 0, 0]) def u_incoming_func(x): # return 1/cl.clmath.sqrt( (x[0] - source[0])**2 # +(x[1] - source[1])**2 # +(x[2] - source[2])**2 ) return 1.0 / la.norm(x.get() - source[:, None], axis=0) bc = cl.array.to_device(queue, u_incoming_func(nodes)) bvp_rhs = bind(qbx, sqrt_w * sym.var("bc"))(queue, bc=bc) from pytential.solve import gmres gmres_result = gmres(bound_op.scipy_op(queue, "sigma", dtype=np.float64), bvp_rhs, tol=1e-14, progress=True, stall_iterations=0, hard_failure=True) sigma = bind(qbx, sym.var("sigma") / sqrt_w)(queue, sigma=gmres_result.solution) # }}} from meshmode.discretization.visualization import make_visualizer bdry_vis = make_visualizer(queue, density_discr, 20) bdry_vis.write_vtk_file("laplace.vtu", [ ("sigma", sigma), ]) # {{{ postprocess/visualize repr_kwargs = dict(qbx_forced_limit=None) representation_sym = (sym.S(kernel, inv_sqrt_w_sigma, **repr_kwargs) + sym.D(kernel, inv_sqrt_w_sigma, **repr_kwargs)) from sumpy.visualization import FieldPlotter fplot = FieldPlotter(np.zeros(3), extent=20, npoints=50) targets = cl.array.to_device(queue, fplot.points) qbx_stick_out = qbx.copy(target_stick_out_factor=0.2) try: fld_in_vol = bind((qbx_stick_out, PointsTarget(targets)), representation_sym)(queue, sigma=sigma).get() except QBXTargetAssociationFailedException as e: fplot.write_vtk_file("failed-targets.vts", [("failed", e.failed_target_flags.get(queue))]) raise #fplot.show_scalar_in_mayavi(fld_in_vol.real, max_val=5) fplot.write_vtk_file("potential-laplace-3d.vts", [ ("potential", fld_in_vol), ])
def run_test(cl_ctx, queue): q_order = 5 qbx_order = q_order fmm_backend = "sumpy" mesh = get_ellipse_mesh(20, 40, mesh_order=5) a = 1 b = 1 / 40 if 0: from meshmode.mesh.visualization import draw_curve import matplotlib.pyplot as plt draw_curve(mesh) plt.axes().set_aspect('equal') plt.show() 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(q_order)) refiner_extra_kwargs = { # "_expansion_disturbance_tolerance": 0.05, "_scaled_max_curvature_threshold": 1, "maxiter": 10, } qbx, _ = QBXLayerPotentialSource( pre_density_discr, fine_order=4 * q_order, qbx_order=qbx_order, fmm_backend=fmm_backend, fmm_order=qbx_order + 5, ).with_refinement(**refiner_extra_kwargs) if 1: 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) def reference_solu(rvec): # a harmonic function x, y = rvec return 2.1 * x * y + (x**2 - y**2) * 0.5 + x bvals = reference_solu(qbx.density_discr.nodes().with_queue(queue)) from pytential.symbolic.pde.scalar import DirichletOperator from sumpy.kernel import LaplaceKernel from pytential import sym, bind op = DirichletOperator(LaplaceKernel(2), -1) bound_op = bind(qbx.copy(target_association_tolerance=0.5), op.operator(sym.var('sigma'))) rhs = bind(qbx.density_discr, op.prepare_rhs(sym.var("bc")))(queue, bc=bvals) from pytential.solve import gmres gmres_result = gmres(bound_op.scipy_op(queue, "sigma", dtype=np.float64), rhs, tol=1e-12, progress=True, hard_failure=True, stall_iterations=50, no_progress_factor=1.05) from sumpy.visualization import FieldPlotter from pytential.target import PointsTarget pltsize = b * 1.5 fplot = FieldPlotter(np.array([-1 + pltsize * 0.5, 0]), extent=pltsize * 1.05, npoints=500) plt_targets = cl.array.to_device(queue, fplot.points) interior_pts = (fplot.points[0]**2 / a**2 + fplot.points[1]**2 / b**2) < 0.99 exact_vals = reference_solu(fplot.points) out_errs = [] for assotol in [0.05]: qbx_stick_out = qbx.copy(target_association_tolerance=0.05) vol_solution = bind((qbx_stick_out, PointsTarget(plt_targets)), op.representation(sym.var('sigma')))( queue, sigma=gmres_result.solution).get() interior_error_linf = ( np.linalg.norm(np.abs(vol_solution - exact_vals)[interior_pts], ord=np.inf) / np.linalg.norm(exact_vals[interior_pts], ord=np.inf)) interior_error_l2 = (np.linalg.norm( np.abs(vol_solution - exact_vals)[interior_pts], ord=2) / np.linalg.norm(exact_vals[interior_pts], ord=2)) print("\nassotol = %f" % assotol) print("L_inf Error = %e " % interior_error_linf) print("L_2 Error = %e " % interior_error_l2) out_errs.append( ("error-%f" % assotol, np.abs(vol_solution - exact_vals))) if 1: fplot.write_vtk_file("results.vts", out_errs)
def main(): logging.basicConfig(level=logging.INFO) nelements = 60 qbx_order = 3 k_fac = 4 k0 = 3*k_fac k1 = 2.9*k_fac mesh_order = 10 bdry_quad_order = mesh_order bdry_ovsmp_quad_order = bdry_quad_order * 4 fmm_order = qbx_order * 2 cl_ctx = cl.create_some_context() queue = cl.CommandQueue(cl_ctx) from meshmode.mesh.generation import ellipse, make_curve_mesh from functools import partial mesh = make_curve_mesh( partial(ellipse, 3), np.linspace(0, 1, nelements+1), mesh_order) density_discr = Discretization( cl_ctx, mesh, InterpolatoryQuadratureSimplexGroupFactory(bdry_quad_order)) logger.info("%d elements" % mesh.nelements) # from meshmode.discretization.visualization import make_visualizer # bdry_vis = make_visualizer(queue, density_discr, 20) # {{{ solve bvp from sumpy.kernel import HelmholtzKernel kernel = HelmholtzKernel(2) beta = 2.5*k_fac K0 = np.sqrt(k0**2-beta**2) K1 = np.sqrt(k1**2-beta**2) from pytential.symbolic.pde.scalar import DielectricSDRep2DBoundaryOperator pde_op = DielectricSDRep2DBoundaryOperator( mode='tm', k_vacuum=1, interfaces=((0, 1, sym.DEFAULT_SOURCE),), domain_k_exprs=(k0, k1), beta=beta) op_unknown_sym = pde_op.make_unknown("unknown") representation0_sym = pde_op.representation(op_unknown_sym, 0) representation1_sym = pde_op.representation(op_unknown_sym, 1) from pytential.qbx import QBXLayerPotentialSource qbx = QBXLayerPotentialSource( density_discr, fine_order=bdry_ovsmp_quad_order, qbx_order=qbx_order, fmm_order=fmm_order ) bound_pde_op = bind(qbx, pde_op.operator(op_unknown_sym)) # in inner domain sources_1 = make_obj_array(list(np.array([ [-1.5, 0.5] ]).T.copy())) strengths_1 = np.array([1]) from sumpy.p2p import P2P pot_p2p = P2P(cl_ctx, [kernel], exclude_self=False) _, (Einc,) = pot_p2p(queue, density_discr.nodes(), sources_1, [strengths_1], out_host=False, k=K0) sqrt_w = bind(density_discr, sym.sqrt_jac_q_weight())(queue) bvp_rhs = np.zeros(len(pde_op.bcs), dtype=np.object) for i_bc, terms in enumerate(pde_op.bcs): for term in terms: assert term.i_interface == 0 assert term.field_kind == pde_op.field_kind_e if term.direction == pde_op.dir_none: bvp_rhs[i_bc] += ( term.coeff_outer * (-Einc) ) elif term.direction == pde_op.dir_normal: # no jump in normal derivative bvp_rhs[i_bc] += 0*Einc else: raise NotImplementedError("direction spec in RHS") bvp_rhs[i_bc] *= sqrt_w from pytential.solve import gmres gmres_result = gmres( bound_pde_op.scipy_op(queue, "unknown", dtype=np.complex128, domains=[sym.DEFAULT_TARGET]*2, K0=K0, K1=K1), bvp_rhs, tol=1e-6, progress=True, hard_failure=True, stall_iterations=0) # }}} unknown = gmres_result.solution # {{{ visualize from pytential.qbx import QBXLayerPotentialSource lap_qbx = QBXLayerPotentialSource( density_discr, fine_order=bdry_ovsmp_quad_order, qbx_order=qbx_order, fmm_order=qbx_order ) from sumpy.visualization import FieldPlotter fplot = FieldPlotter(np.zeros(2), extent=5, npoints=300) from pytential.target import PointsTarget fld0 = bind( (qbx, PointsTarget(fplot.points)), representation0_sym)(queue, unknown=unknown, K0=K0).get() fld1 = bind( (qbx, PointsTarget(fplot.points)), representation1_sym)(queue, unknown=unknown, K1=K1).get() ones = cl.array.empty(queue, density_discr.nnodes, np.float64) dom1_indicator = -bind( (lap_qbx, PointsTarget(fplot.points)), sym.D(0, sym.var("sigma")))( queue, sigma=ones.fill(1)).get() _, (fld_inc_vol,) = pot_p2p(queue, fplot.points, sources_1, [strengths_1], out_host=True, k=K0) #fplot.show_scalar_in_mayavi(fld_in_vol.real, max_val=5) fplot.write_vtk_file( "potential.vts", [ ("fld0", fld0), ("fld1", fld1), ("fld_inc_vol", fld_inc_vol), ("fld_total", ( (fld_inc_vol + fld0)*(1-dom1_indicator) + fld1*dom1_indicator )), ("dom1_indicator", dom1_indicator), ] )
def main(): # cl.array.to_device(queue, numpy_array) from meshmode.mesh.io import generate_gmsh, FileSource mesh = generate_gmsh( FileSource("ellipsoid.step"), 2, order=2, other_options=["-string", "Mesh.CharacteristicLengthMax = %g;" % h]) from meshmode.mesh.processing import perform_flips # Flip elements--gmsh generates inside-out geometry. mesh = perform_flips(mesh, np.ones(mesh.nelements)) print("%d elements" % mesh.nelements) from meshmode.mesh.processing import find_bounding_box bbox_min, bbox_max = find_bounding_box(mesh) bbox_center = 0.5 * (bbox_min + bbox_max) bbox_size = max(bbox_max - bbox_min) / 2 logger.info("%d elements" % mesh.nelements) 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)) qbx = QBXLayerPotentialSource(density_discr, 4 * target_order, qbx_order, fmm_order=qbx_order + 10, fmm_backend="fmmlib") from pytential.symbolic.pde.maxwell import MuellerAugmentedMFIEOperator pde_op = MuellerAugmentedMFIEOperator( omega=0.4, epss=[1.4, 1.0], mus=[1.2, 1.0], ) from pytential import bind, sym unk = pde_op.make_unknown("sigma") sym_operator = pde_op.operator(unk) sym_rhs = pde_op.rhs(sym.make_sym_vector("Einc", 3), sym.make_sym_vector("Hinc", 3)) sym_repr = pde_op.representation(0, unk) if 1: expr = sym_repr print(sym.pretty(expr)) print("#" * 80) from pytential.target import PointsTarget tgt_points = np.zeros((3, 1)) tgt_points[0, 0] = 100 tgt_points[1, 0] = -200 tgt_points[2, 0] = 300 bound_op = bind((qbx, PointsTarget(tgt_points)), expr) print(bound_op.code) if 1: def green3e(x, y, z, source, strength, k): # electric field corresponding to dyadic green's function # due to monochromatic electric dipole located at "source". # "strength" is the the intensity of the dipole. # E = (I + Hess)(exp(ikr)/r) dot (strength) # dx = x - source[0] dy = y - source[1] dz = z - source[2] rr = np.sqrt(dx**2 + dy**2 + dz**2) fout = np.exp(1j * k * rr) / rr evec = fout * strength qmat = np.zeros((3, 3), dtype=np.complex128) qmat[0, 0] = (2 * dx**2 - dy**2 - dz**2) * (1 - 1j * k * rr) qmat[1, 1] = (2 * dy**2 - dz**2 - dx**2) * (1 - 1j * k * rr) qmat[2, 2] = (2 * dz**2 - dx**2 - dy**2) * (1 - 1j * k * rr) qmat[0, 0] = qmat[0, 0] + (-k**2 * dx**2 * rr**2) qmat[1, 1] = qmat[1, 1] + (-k**2 * dy**2 * rr**2) qmat[2, 2] = qmat[2, 2] + (-k**2 * dz**2 * rr**2) qmat[0, 1] = (3 - k**2 * rr**2 - 3 * 1j * k * rr) * (dx * dy) qmat[1, 2] = (3 - k**2 * rr**2 - 3 * 1j * k * rr) * (dy * dz) qmat[2, 0] = (3 - k**2 * rr**2 - 3 * 1j * k * rr) * (dz * dx) qmat[1, 0] = qmat[0, 1] qmat[2, 1] = qmat[1, 2] qmat[0, 2] = qmat[2, 0] fout = np.exp(1j * k * rr) / rr**5 / k**2 fvec = fout * np.dot(qmat, strength) evec = evec + fvec return evec def green3m(x, y, z, source, strength, k): # magnetic field corresponding to dyadic green's function # due to monochromatic electric dipole located at "source". # "strength" is the the intensity of the dipole. # H = curl((I + Hess)(exp(ikr)/r) dot (strength)) = # strength \cross \grad (exp(ikr)/r) # dx = x - source[0] dy = y - source[1] dz = z - source[2] rr = np.sqrt(dx**2 + dy**2 + dz**2) fout = (1 - 1j * k * rr) * np.exp(1j * k * rr) / rr**3 fvec = np.zeros(3, dtype=np.complex128) fvec[0] = fout * dx fvec[1] = fout * dy fvec[2] = fout * dz hvec = np.cross(strength, fvec) return hvec def dipole3e(x, y, z, source, strength, k): # # evalaute electric and magnetic field due # to monochromatic electric dipole located at "source" # with intensity "strength" evec = green3e(x, y, z, source, strength, k) evec = evec * 1j * k hvec = green3m(x, y, z, source, strength, k) return evec, hvec def dipole3m(x, y, z, source, strength, k): # # evalaute electric and magnetic field due # to monochromatic magnetic dipole located at "source" # with intensity "strength" evec = green3m(x, y, z, source, strength, k) hvec = green3e(x, y, z, source, strength, k) hvec = -hvec * 1j * k return evec, hvec def dipole3eall(x, y, z, sources, strengths, k): ns = len(strengths) evec = np.zeros(3, dtype=np.complex128) hvec = np.zeros(3, dtype=np.complex128) for i in range(ns): evect, hvect = dipole3e(x, y, z, sources[i], strengths[i], k) evec = evec + evect hvec = hvec + hvect nodes = density_discr.nodes().with_queue(queue).get() source = [0.01, -0.03, 0.02] # source = cl.array.to_device(queue,np.zeros(3)) # source[0] = 0.01 # source[1] =-0.03 # source[2] = 0.02 strength = np.ones(3) # evec = cl.array.to_device(queue,np.zeros((3,len(nodes[0])),dtype=np.complex128)) # hvec = cl.array.to_device(queue,np.zeros((3,len(nodes[0])),dtype=np.complex128)) evec = np.zeros((3, len(nodes[0])), dtype=np.complex128) hvec = np.zeros((3, len(nodes[0])), dtype=np.complex128) for i in range(len(nodes[0])): evec[:, i], hvec[:, i] = dipole3e(nodes[0][i], nodes[1][i], nodes[2][i], source, strength, k) print(np.shape(hvec)) print(type(evec)) print(type(hvec)) evec = cl.array.to_device(queue, evec) hvec = cl.array.to_device(queue, hvec) bvp_rhs = bind(qbx, sym_rhs)(queue, Einc=evec, Hinc=hvec) print(np.shape(bvp_rhs)) print(type(bvp_rhs)) # print(bvp_rhs) 1 / -1 bound_op = bind(qbx, sym_operator) from pytential.solve import gmres if 0: gmres_result = gmres(bound_op.scipy_op(queue, "sigma", dtype=np.complex128, k=k), bvp_rhs, tol=1e-8, progress=True, stall_iterations=0, hard_failure=True) sigma = gmres_result.solution fld_at_tgt = bind((qbx, PointsTarget(tgt_points)), sym_repr)(queue, sigma=bvp_rhs, k=k) fld_at_tgt = np.array([fi.get() for fi in fld_at_tgt]) print(fld_at_tgt) 1 / 0 # }}} #mlab.figure(bgcolor=(1, 1, 1)) if 1: from meshmode.discretization.visualization import make_visualizer bdry_vis = make_visualizer(queue, density_discr, target_order) bdry_normals = bind(density_discr, sym.normal(3))(queue)\ .as_vector(dtype=object) bdry_vis.write_vtk_file("source.vtu", [ ("sigma", sigma), ("bdry_normals", bdry_normals), ]) fplot = FieldPlotter(bbox_center, extent=2 * bbox_size, npoints=(150, 150, 1)) qbx_tgt_tol = qbx.copy(target_association_tolerance=0.1) from pytential.target import PointsTarget from pytential.qbx import QBXTargetAssociationFailedException rho_sym = sym.var("rho") try: fld_in_vol = bind((qbx_tgt_tol, PointsTarget(fplot.points)), sym.make_obj_array([ sym.S(pde_op.kernel, rho_sym, k=sym.var("k"), qbx_forced_limit=None), sym.d_dx( 3, sym.S(pde_op.kernel, rho_sym, k=sym.var("k"), qbx_forced_limit=None)), sym.d_dy( 3, sym.S(pde_op.kernel, rho_sym, k=sym.var("k"), qbx_forced_limit=None)), sym.d_dz( 3, sym.S(pde_op.kernel, rho_sym, k=sym.var("k"), qbx_forced_limit=None)), ]))(queue, jt=jt, rho=rho, k=k) except QBXTargetAssociationFailedException as e: fplot.write_vtk_file( "failed-targets.vts", [("failed_targets", e.failed_target_flags.get(queue))]) raise fld_in_vol = sym.make_obj_array([fiv.get() for fiv in fld_in_vol]) #fplot.show_scalar_in_mayavi(fld_in_vol.real, max_val=5) fplot.write_vtk_file("potential.vts", [ ("potential", fld_in_vol[0]), ("grad", fld_in_vol[1:]), ])
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) actx = PyOpenCLArrayContext(queue) target_order = 16 qbx_order = 3 nelements = 60 mode_nr = 0 k = 0 if k: kernel = HelmholtzKernel(2) else: kernel = LaplaceKernel(2) 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( actx, mesh, InterpolatoryQuadratureSimplexGroupFactory(target_order)) unaccel_qbx = QBXLayerPotentialSource( pre_density_discr, fine_order=2 * target_order, qbx_order=qbx_order, fmm_order=False, target_association_tolerance=.05, ) from pytential.target import PointsTarget fplot = FieldPlotter(np.zeros(2), extent=5, npoints=600) from pytential import GeometryCollection places = GeometryCollection({ "unaccel_qbx": unaccel_qbx, "qbx": unaccel_qbx.copy(fmm_order=10), "targets": PointsTarget(fplot.points) }) density_discr = places.get_discretization("unaccel_qbx") nodes = thaw(actx, density_discr.nodes()) angle = actx.np.arctan2(nodes[1], nodes[0]) from pytential import bind, sym if k: kernel_kwargs = {"k": sym.var("k")} else: kernel_kwargs = {} def get_op(): kwargs = dict(qbx_forced_limit=None) kwargs.update(kernel_kwargs) # return sym.d_dx(2, sym.S(kernel, sym.var("sigma"), **kwargs)) # return sym.D(kernel, sym.var("sigma"), **kwargs) return sym.S(kernel, sym.var("sigma"), **kwargs) op = get_op() sigma = actx.np.cos(mode_nr * angle) if isinstance(kernel, HelmholtzKernel): for i, elem in np.ndenumerate(sigma): sigma[i] = elem.astype(np.complex128) fld_in_vol = bind(places, op, auto_where=("unaccel_qbx", "targets"))(actx, sigma=sigma, k=k).get() fmm_fld_in_vol = bind(places, op, auto_where=("qbx", "targets"))(actx, sigma=sigma, k=k).get() err = fmm_fld_in_vol - fld_in_vol try: import matplotlib except ImportError: return matplotlib.use("Agg") im = fplot.show_scalar_in_matplotlib(np.log10(np.abs(err) + 1e-17)) from matplotlib.colors import Normalize im.set_norm(Normalize(vmin=-12, vmax=0)) import matplotlib.pyplot as pt from matplotlib.ticker import NullFormatter pt.gca().xaxis.set_major_formatter(NullFormatter()) pt.gca().yaxis.set_major_formatter(NullFormatter()) cb = pt.colorbar(shrink=0.9) cb.set_label(r"$\log_{10}(\mathrm{Error})$") pt.savefig("fmm-error-order-%d.pdf" % qbx_order)
angle = cl.clmath.atan2(nodes[1], nodes[0]) from pytential import bind, sym d = sym.Derivative() #op = d.nabla[0] * d(sym.S(kernel, sym.var("sigma"))) #op = sym.D(kernel, sym.var("sigma")) op = sym.S(kernel, sym.var("sigma")) sigma = cl.clmath.cos(mode_nr*angle) if isinstance(kernel, HelmholtzKernel): sigma = sigma.astype(np.complex128) bound_bdry_op = bind(qbx, op) fplot = FieldPlotter(np.zeros(2), extent=5, npoints=600) from pytential.target import PointsTarget fld_in_vol = bind( (slow_qbx, PointsTarget(fplot.points)), op)(queue, sigma=sigma, k=k).get() fmm_fld_in_vol = bind( (qbx, PointsTarget(fplot.points)), op)(queue, sigma=sigma, k=k).get() err = fmm_fld_in_vol-fld_in_vol im = fplot.show_scalar_in_matplotlib(np.log10(np.abs(err))) from matplotlib.colors import Normalize im.set_norm(Normalize(vmin=-6, vmax=0))
def main(mesh_name="torus", visualize=False): import logging logging.basicConfig(level=logging.WARNING) # INFO for more progress info cl_ctx = cl.create_some_context() queue = cl.CommandQueue(cl_ctx) actx = PyOpenCLArrayContext(queue) if mesh_name == "torus": rout = 10 rin = 1 from meshmode.mesh.generation import generate_torus base_mesh = generate_torus( rout, rin, 40, 4, mesh_order) from meshmode.mesh.processing import affine_map, merge_disjoint_meshes # nx = 1 # ny = 1 nz = 1 dz = 0 meshes = [ affine_map( base_mesh, A=np.diag([1, 1, 1]), b=np.array([0, 0, iz*dz])) for iz in range(nz)] mesh = merge_disjoint_meshes(meshes, single_group=True) if visualize: from meshmode.mesh.visualization import draw_curve draw_curve(mesh) import matplotlib.pyplot as plt plt.show() else: raise ValueError(f"unknown mesh name: {mesh_name}") pre_density_discr = Discretization( actx, mesh, InterpolatoryQuadratureSimplexGroupFactory(bdry_quad_order)) from pytential.qbx import ( QBXLayerPotentialSource, QBXTargetAssociationFailedException) qbx = QBXLayerPotentialSource( pre_density_discr, fine_order=bdry_ovsmp_quad_order, qbx_order=qbx_order, fmm_order=fmm_order, ) from sumpy.visualization import FieldPlotter fplot = FieldPlotter(np.zeros(3), extent=20, npoints=50) targets = actx.from_numpy(fplot.points) from pytential import GeometryCollection places = GeometryCollection({ "qbx": qbx, "qbx_target_assoc": qbx.copy(target_association_tolerance=0.2), "targets": PointsTarget(targets) }, auto_where="qbx") density_discr = places.get_discretization("qbx") # {{{ describe bvp from sumpy.kernel import LaplaceKernel kernel = LaplaceKernel(3) sigma_sym = sym.var("sigma") #sqrt_w = sym.sqrt_jac_q_weight(3) sqrt_w = 1 inv_sqrt_w_sigma = sym.cse(sigma_sym/sqrt_w) # -1 for interior Dirichlet # +1 for exterior Dirichlet loc_sign = +1 bdry_op_sym = (loc_sign*0.5*sigma_sym + sqrt_w*( sym.S(kernel, inv_sqrt_w_sigma, qbx_forced_limit=+1) + sym.D(kernel, inv_sqrt_w_sigma, qbx_forced_limit="avg") )) # }}} bound_op = bind(places, bdry_op_sym) # {{{ fix rhs and solve from meshmode.dof_array import thaw, flatten, unflatten nodes = thaw(actx, density_discr.nodes()) source = np.array([rout, 0, 0]) def u_incoming_func(x): from pytools.obj_array import obj_array_vectorize x = obj_array_vectorize(actx.to_numpy, flatten(x)) x = np.array(list(x)) # return 1/cl.clmath.sqrt( (x[0] - source[0])**2 # +(x[1] - source[1])**2 # +(x[2] - source[2])**2 ) return 1.0/la.norm(x - source[:, None], axis=0) bc = unflatten(actx, density_discr, actx.from_numpy(u_incoming_func(nodes))) bvp_rhs = bind(places, sqrt_w*sym.var("bc"))(actx, bc=bc) from pytential.solve import gmres gmres_result = gmres( bound_op.scipy_op(actx, "sigma", dtype=np.float64), bvp_rhs, tol=1e-14, progress=True, stall_iterations=0, hard_failure=True) sigma = bind(places, sym.var("sigma")/sqrt_w)( actx, sigma=gmres_result.solution) # }}} from meshmode.discretization.visualization import make_visualizer bdry_vis = make_visualizer(actx, density_discr, 20) bdry_vis.write_vtk_file("laplace.vtu", [ ("sigma", sigma), ]) # {{{ postprocess/visualize repr_kwargs = dict( source="qbx_target_assoc", target="targets", qbx_forced_limit=None) representation_sym = ( sym.S(kernel, inv_sqrt_w_sigma, **repr_kwargs) + sym.D(kernel, inv_sqrt_w_sigma, **repr_kwargs)) try: fld_in_vol = actx.to_numpy( bind(places, representation_sym)(actx, sigma=sigma)) except QBXTargetAssociationFailedException as e: fplot.write_vtk_file("laplace-dirichlet-3d-failed-targets.vts", [ ("failed", e.failed_target_flags.get(queue)), ]) raise #fplot.show_scalar_in_mayavi(fld_in_vol.real, max_val=5) fplot.write_vtk_file("laplace-dirichlet-3d-potential.vts", [ ("potential", fld_in_vol), ])
def timing_run(nx, ny): import logging logging.basicConfig(level=logging.WARNING) # INFO for more progress info cl_ctx = cl.create_some_context() queue = cl.CommandQueue(cl_ctx) mesh = make_mesh(nx=nx, ny=ny) density_discr = Discretization( cl_ctx, mesh, InterpolatoryQuadratureSimplexGroupFactory(bdry_quad_order)) from pytential.qbx import (QBXLayerPotentialSource, QBXTargetAssociationFailedException) qbx = QBXLayerPotentialSource(density_discr, fine_order=bdry_ovsmp_quad_order, qbx_order=qbx_order, fmm_order=fmm_order) # {{{ describe bvp from sumpy.kernel import HelmholtzKernel kernel = HelmholtzKernel(2) cse = sym.cse sigma_sym = sym.var("sigma") sqrt_w = sym.sqrt_jac_q_weight(2) inv_sqrt_w_sigma = cse(sigma_sym / sqrt_w) # Brakhage-Werner parameter alpha = 1j # -1 for interior Dirichlet # +1 for exterior Dirichlet loc_sign = +1 bdry_op_sym = (-loc_sign * 0.5 * sigma_sym + sqrt_w * (alpha * sym.S(kernel, inv_sqrt_w_sigma, k=sym.var("k")) - sym.D(kernel, inv_sqrt_w_sigma, k=sym.var("k")))) # }}} bound_op = bind(qbx, bdry_op_sym) # {{{ fix rhs and solve mode_nr = 3 nodes = density_discr.nodes().with_queue(queue) angle = cl.clmath.atan2(nodes[1], nodes[0]) sigma = cl.clmath.cos(mode_nr * angle) # }}} # {{{ postprocess/visualize repr_kwargs = dict(k=sym.var("k"), qbx_forced_limit=+1) sym_op = sym.S(kernel, sym.var("sigma"), **repr_kwargs) bound_op = bind(qbx, sym_op) print("FMM WARM-UP RUN 1: %d elements" % mesh.nelements) bound_op(queue, sigma=sigma, k=k) print("FMM WARM-UP RUN 2: %d elements" % mesh.nelements) bound_op(queue, sigma=sigma, k=k) queue.finish() print("FMM TIMING RUN: %d elements" % mesh.nelements) from time import time t_start = time() bound_op(queue, sigma=sigma, k=k) queue.finish() elapsed = time() - t_start print("FMM TIMING RUN DONE: %d elements -> %g s" % (mesh.nelements, elapsed)) return (mesh.nelements, elapsed) if 0: from sumpy.visualization import FieldPlotter fplot = FieldPlotter(np.zeros(2), extent=5, npoints=1500) targets = cl.array.to_device(queue, fplot.points) qbx_tgt_tol = qbx.copy(target_association_tolerance=0.05) indicator_qbx = qbx_tgt_tol.copy(fmm_level_to_order=lambda lev: 7, qbx_order=2) ones_density = density_discr.zeros(queue) ones_density.fill(1) indicator = bind((indicator_qbx, PointsTarget(targets)), sym_op)(queue, sigma=ones_density).get() qbx_stick_out = qbx.copy(target_stick_out_factor=0.1) try: fld_in_vol = bind((qbx_stick_out, PointsTarget(targets)), sym_op)(queue, sigma=sigma, k=k).get() except QBXTargetAssociationFailedException as e: fplot.write_vtk_file( "failed-targets.vts", [("failed", e.failed_target_flags.get(queue))]) raise #fplot.show_scalar_in_mayavi(fld_in_vol.real, max_val=5) fplot.write_vtk_file("potential-scaling.vts", [("potential", fld_in_vol), ("indicator", indicator)])
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) target_order = 16 qbx_order = 3 nelements = 60 mode_nr = 0 k = 0 if k: kernel = HelmholtzKernel(2) else: kernel = LaplaceKernel(2) #kernel = OneKernel() 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)) slow_qbx, _ = QBXLayerPotentialSource( pre_density_discr, fine_order=2 * target_order, qbx_order=qbx_order, fmm_order=False, target_association_tolerance=.05).with_refinement() qbx = slow_qbx.copy(fmm_order=10) density_discr = slow_qbx.density_discr nodes = density_discr.nodes().with_queue(queue) angle = cl.clmath.atan2(nodes[1], nodes[0]) from pytential import bind, sym #op = sym.d_dx(sym.S(kernel, sym.var("sigma")), qbx_forced_limit=None) #op = sym.D(kernel, sym.var("sigma"), qbx_forced_limit=None) op = sym.S(kernel, sym.var("sigma"), qbx_forced_limit=None) sigma = cl.clmath.cos(mode_nr * angle) if isinstance(kernel, HelmholtzKernel): sigma = sigma.astype(np.complex128) fplot = FieldPlotter(np.zeros(2), extent=5, npoints=600) from pytential.target import PointsTarget fld_in_vol = bind((slow_qbx, PointsTarget(fplot.points)), op)(queue, sigma=sigma, k=k).get() fmm_fld_in_vol = bind((qbx, PointsTarget(fplot.points)), op)(queue, sigma=sigma, k=k).get() err = fmm_fld_in_vol - fld_in_vol import matplotlib matplotlib.use('Agg') im = fplot.show_scalar_in_matplotlib(np.log10(np.abs(err) + 1e-17)) from matplotlib.colors import Normalize im.set_norm(Normalize(vmin=-12, vmax=0)) import matplotlib.pyplot as pt from matplotlib.ticker import NullFormatter pt.gca().xaxis.set_major_formatter(NullFormatter()) pt.gca().yaxis.set_major_formatter(NullFormatter()) cb = pt.colorbar(shrink=0.9) cb.set_label(r"$\log_{10}(\mathdefault{Error})$") pt.savefig("fmm-error-order-%d.pdf" % qbx_order)
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) target_order = 16 qbx_order = 3 nelements = 60 mode_nr = 0 k = 0 if k: kernel = HelmholtzKernel(2) else: kernel = LaplaceKernel(2) #kernel = OneKernel() 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)) slow_qbx, _ = QBXLayerPotentialSource( pre_density_discr, fine_order=2*target_order, qbx_order=qbx_order, fmm_order=False, target_association_tolerance=.05 ).with_refinement() qbx = slow_qbx.copy(fmm_order=10) density_discr = slow_qbx.density_discr nodes = density_discr.nodes().with_queue(queue) angle = cl.clmath.atan2(nodes[1], nodes[0]) from pytential import bind, sym #op = sym.d_dx(sym.S(kernel, sym.var("sigma")), qbx_forced_limit=None) #op = sym.D(kernel, sym.var("sigma"), qbx_forced_limit=None) op = sym.S(kernel, sym.var("sigma"), qbx_forced_limit=None) sigma = cl.clmath.cos(mode_nr*angle) if isinstance(kernel, HelmholtzKernel): sigma = sigma.astype(np.complex128) fplot = FieldPlotter(np.zeros(2), extent=5, npoints=600) from pytential.target import PointsTarget fld_in_vol = bind( (slow_qbx, PointsTarget(fplot.points)), op)(queue, sigma=sigma, k=k).get() fmm_fld_in_vol = bind( (qbx, PointsTarget(fplot.points)), op)(queue, sigma=sigma, k=k).get() err = fmm_fld_in_vol-fld_in_vol import matplotlib matplotlib.use('Agg') im = fplot.show_scalar_in_matplotlib(np.log10(np.abs(err) + 1e-17)) from matplotlib.colors import Normalize im.set_norm(Normalize(vmin=-12, vmax=0)) import matplotlib.pyplot as pt from matplotlib.ticker import NullFormatter pt.gca().xaxis.set_major_formatter(NullFormatter()) pt.gca().yaxis.set_major_formatter(NullFormatter()) cb = pt.colorbar(shrink=0.9) cb.set_label(r"$\log_{10}(\mathdefault{Error})$") pt.savefig("fmm-error-order-%d.pdf" % qbx_order)
def main(): import logging logging.basicConfig(level=logging.INFO) cl_ctx = cl.create_some_context() queue = cl.CommandQueue(cl_ctx) from meshmode.mesh.generation import ellipse, make_curve_mesh from functools import partial mesh = make_curve_mesh( partial(ellipse, 3), np.linspace(0, 1, nelements+1), mesh_order) density_discr = Discretization( cl_ctx, mesh, InterpolatoryQuadratureSimplexGroupFactory(bdry_quad_order)) from pytential.qbx import QBXLayerPotentialSource qbx = QBXLayerPotentialSource( density_discr, fine_order=bdry_ovsmp_quad_order, qbx_order=qbx_order, fmm_order=fmm_order ) # {{{ describe bvp from sumpy.kernel import HelmholtzKernel kernel = HelmholtzKernel(2) cse = sym.cse sigma_sym = sym.var("sigma") sqrt_w = sym.sqrt_jac_q_weight() inv_sqrt_w_sigma = cse(sigma_sym/sqrt_w) # Brakhage-Werner parameter alpha = 1j # -1 for interior Dirichlet # +1 for exterior Dirichlet loc_sign = -1 bdry_op_sym = (-loc_sign*0.5*sigma_sym + sqrt_w*( alpha*sym.S(kernel, inv_sqrt_w_sigma, k=sym.var("k")) - sym.D(kernel, inv_sqrt_w_sigma, k=sym.var("k")) )) # }}} bound_op = bind(qbx, bdry_op_sym) # {{{ fix rhs and solve mode_nr = 3 nodes = density_discr.nodes().with_queue(queue) angle = cl.clmath.atan2(nodes[1], nodes[0]) bc = cl.clmath.cos(mode_nr*angle) bvp_rhs = bind(qbx, sqrt_w*sym.var("bc"))(queue, bc=bc) from pytential.solve import gmres gmres_result = gmres( bound_op.scipy_op(queue, "sigma", k=k), bvp_rhs, tol=1e-14, progress=True, stall_iterations=0, hard_failure=True) # }}} # {{{ postprocess/visualize sigma = gmres_result.solution representation_sym = ( alpha*sym.S(kernel, inv_sqrt_w_sigma, k=sym.var("k")) - sym.D(kernel, inv_sqrt_w_sigma, k=sym.var("k"))) from sumpy.visualization import FieldPlotter fplot = FieldPlotter(np.zeros(2), extent=5, npoints=1500) from pytential.target import PointsTarget fld_in_vol = bind( (qbx, PointsTarget(fplot.points)), representation_sym)(queue, sigma=sigma, k=k).get() #fplot.show_scalar_in_mayavi(fld_in_vol.real, max_val=5) fplot.write_vtk_file( "potential.vts", [ ("potential", fld_in_vol) ] )
def main(): import logging logging.basicConfig(level=logging.INFO) cl_ctx = cl.create_some_context() queue = cl.CommandQueue(cl_ctx) from meshmode.mesh.generation import ellipse, make_curve_mesh from functools import partial mesh = make_curve_mesh( partial(ellipse, 2), np.linspace(0, 1, nelements+1), mesh_order) pre_density_discr = Discretization( cl_ctx, mesh, InterpolatoryQuadratureSimplexGroupFactory(bdry_quad_order)) from pytential.qbx import ( QBXLayerPotentialSource, QBXTargetAssociationFailedException) qbx, _ = QBXLayerPotentialSource( pre_density_discr, fine_order=bdry_ovsmp_quad_order, qbx_order=qbx_order, fmm_order=fmm_order, expansion_disks_in_tree_have_extent=True, ).with_refinement() density_discr = qbx.density_discr from pytential.symbolic.pde.cahn_hilliard import CahnHilliardOperator chop = CahnHilliardOperator( # FIXME: Constants? lambda1=1.5, lambda2=1.25, c=1) unk = chop.make_unknown("sigma") bound_op = bind(qbx, chop.operator(unk)) # {{{ fix rhs and solve nodes = density_discr.nodes().with_queue(queue) def g(xvec): x, y = xvec return cl.clmath.atan2(y, x) bc = sym.make_obj_array([ # FIXME: Realistic BC g(nodes), -g(nodes), ]) from pytential.solve import gmres gmres_result = gmres( bound_op.scipy_op(queue, "sigma", dtype=np.complex128), bc, tol=1e-8, progress=True, stall_iterations=0, hard_failure=True) # }}} # {{{ postprocess/visualize sigma = gmres_result.solution from sumpy.visualization import FieldPlotter fplot = FieldPlotter(np.zeros(2), extent=5, npoints=500) targets = cl.array.to_device(queue, fplot.points) qbx_stick_out = qbx.copy(target_association_tolerance=0.05) indicator_qbx = qbx_stick_out.copy(qbx_order=2) from sumpy.kernel import LaplaceKernel ones_density = density_discr.zeros(queue) ones_density.fill(1) indicator = bind( (indicator_qbx, PointsTarget(targets)), sym.D(LaplaceKernel(2), sym.var("sigma")))( queue, sigma=ones_density).get() try: fld_in_vol = bind( (qbx_stick_out, PointsTarget(targets)), chop.representation(unk))(queue, sigma=sigma).get() except QBXTargetAssociationFailedException as e: fplot.write_vtk_file( "failed-targets.vts", [ ("failed", e.failed_target_flags.get(queue)) ] ) raise #fplot.show_scalar_in_mayavi(fld_in_vol.real, max_val=5) fplot.write_vtk_file( "potential.vts", [ ("potential", fld_in_vol), ("indicator", indicator), ] )
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 generate_torus rout = 10 rin = 1 if 1: base_mesh = generate_torus( rout, rin, 40, 4, mesh_order) from meshmode.mesh.processing import affine_map, merge_disjoint_meshes # nx = 1 # ny = 1 nz = 1 dz = 0 meshes = [ affine_map( base_mesh, A=np.diag([1, 1, 1]), b=np.array([0, 0, iz*dz])) for iz in range(nz)] mesh = merge_disjoint_meshes(meshes, single_group=True) if 0: from meshmode.mesh.visualization import draw_curve draw_curve(mesh) import matplotlib.pyplot as plt plt.show() pre_density_discr = Discretization( cl_ctx, mesh, InterpolatoryQuadratureSimplexGroupFactory(bdry_quad_order)) from pytential.qbx import ( QBXLayerPotentialSource, QBXTargetAssociationFailedException) qbx, _ = QBXLayerPotentialSource( pre_density_discr, fine_order=bdry_ovsmp_quad_order, qbx_order=qbx_order, fmm_order=fmm_order ).with_refinement() density_discr = qbx.density_discr # {{{ describe bvp from sumpy.kernel import LaplaceKernel kernel = LaplaceKernel(3) cse = sym.cse sigma_sym = sym.var("sigma") #sqrt_w = sym.sqrt_jac_q_weight(3) sqrt_w = 1 inv_sqrt_w_sigma = cse(sigma_sym/sqrt_w) # -1 for interior Dirichlet # +1 for exterior Dirichlet loc_sign = +1 bdry_op_sym = (loc_sign*0.5*sigma_sym + sqrt_w*( sym.S(kernel, inv_sqrt_w_sigma) + sym.D(kernel, inv_sqrt_w_sigma) )) # }}} bound_op = bind(qbx, bdry_op_sym) # {{{ fix rhs and solve nodes = density_discr.nodes().with_queue(queue) source = np.array([rout, 0, 0]) def u_incoming_func(x): # return 1/cl.clmath.sqrt( (x[0] - source[0])**2 # +(x[1] - source[1])**2 # +(x[2] - source[2])**2 ) return 1.0/la.norm(x.get()-source[:, None], axis=0) bc = cl.array.to_device(queue, u_incoming_func(nodes)) bvp_rhs = bind(qbx, sqrt_w*sym.var("bc"))(queue, bc=bc) from pytential.solve import gmres gmres_result = gmres( bound_op.scipy_op(queue, "sigma", dtype=np.float64), bvp_rhs, tol=1e-14, progress=True, stall_iterations=0, hard_failure=True) sigma = bind(qbx, sym.var("sigma")/sqrt_w)(queue, sigma=gmres_result.solution) # }}} from meshmode.discretization.visualization import make_visualizer bdry_vis = make_visualizer(queue, density_discr, 20) bdry_vis.write_vtk_file("laplace.vtu", [ ("sigma", sigma), ]) # {{{ postprocess/visualize repr_kwargs = dict(qbx_forced_limit=None) representation_sym = ( sym.S(kernel, inv_sqrt_w_sigma, **repr_kwargs) + sym.D(kernel, inv_sqrt_w_sigma, **repr_kwargs)) from sumpy.visualization import FieldPlotter fplot = FieldPlotter(np.zeros(3), extent=20, npoints=50) targets = cl.array.to_device(queue, fplot.points) qbx_stick_out = qbx.copy(target_stick_out_factor=0.2) try: fld_in_vol = bind( (qbx_stick_out, PointsTarget(targets)), representation_sym)(queue, sigma=sigma).get() except QBXTargetAssociationFailedException as e: fplot.write_vtk_file( "failed-targets.vts", [ ("failed", e.failed_target_flags.get(queue)) ] ) raise #fplot.show_scalar_in_mayavi(fld_in_vol.real, max_val=5) fplot.write_vtk_file( "potential-laplace-3d.vts", [ ("potential", fld_in_vol), ] )
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 main(): logging.basicConfig(level=logging.INFO) nelements = 60 qbx_order = 3 k_fac = 4 k0 = 3 * k_fac k1 = 2.9 * k_fac mesh_order = 10 bdry_quad_order = mesh_order bdry_ovsmp_quad_order = bdry_quad_order * 4 fmm_order = qbx_order * 2 cl_ctx = cl.create_some_context() queue = cl.CommandQueue(cl_ctx) from meshmode.mesh.generation import ellipse, make_curve_mesh from functools import partial mesh = make_curve_mesh(partial(ellipse, 3), np.linspace(0, 1, nelements + 1), mesh_order) density_discr = Discretization( cl_ctx, mesh, InterpolatoryQuadratureSimplexGroupFactory(bdry_quad_order)) logger.info("%d elements" % mesh.nelements) # from meshmode.discretization.visualization import make_visualizer # bdry_vis = make_visualizer(queue, density_discr, 20) # {{{ solve bvp from sumpy.kernel import HelmholtzKernel kernel = HelmholtzKernel(2) beta = 2.5 * k_fac K0 = np.sqrt(k0**2 - beta**2) K1 = np.sqrt(k1**2 - beta**2) from pytential.symbolic.pde.scalar import DielectricSDRep2DBoundaryOperator pde_op = DielectricSDRep2DBoundaryOperator( mode='tm', k_vacuum=1, interfaces=((0, 1, sym.DEFAULT_SOURCE), ), domain_k_exprs=(k0, k1), beta=beta) op_unknown_sym = pde_op.make_unknown("unknown") representation0_sym = pde_op.representation(op_unknown_sym, 0) representation1_sym = pde_op.representation(op_unknown_sym, 1) from pytential.qbx import QBXLayerPotentialSource qbx = QBXLayerPotentialSource(density_discr, fine_order=bdry_ovsmp_quad_order, qbx_order=qbx_order, fmm_order=fmm_order) bound_pde_op = bind(qbx, pde_op.operator(op_unknown_sym)) # in inner domain sources_1 = make_obj_array(list(np.array([[-1.5, 0.5]]).T.copy())) strengths_1 = np.array([1]) from sumpy.p2p import P2P pot_p2p = P2P(cl_ctx, [kernel], exclude_self=False) _, (Einc, ) = pot_p2p(queue, density_discr.nodes(), sources_1, [strengths_1], out_host=False, k=K0) sqrt_w = bind(density_discr, sym.sqrt_jac_q_weight())(queue) bvp_rhs = np.zeros(len(pde_op.bcs), dtype=object) for i_bc, terms in enumerate(pde_op.bcs): for term in terms: assert term.i_interface == 0 assert term.field_kind == pde_op.field_kind_e if term.direction == pde_op.dir_none: bvp_rhs[i_bc] += (term.coeff_outer * (-Einc)) elif term.direction == pde_op.dir_normal: # no jump in normal derivative bvp_rhs[i_bc] += 0 * Einc else: raise NotImplementedError("direction spec in RHS") bvp_rhs[i_bc] *= sqrt_w from pytential.solve import gmres gmres_result = gmres(bound_pde_op.scipy_op(queue, "unknown", dtype=np.complex128, domains=[sym.DEFAULT_TARGET] * 2, K0=K0, K1=K1), bvp_rhs, tol=1e-6, progress=True, hard_failure=True, stall_iterations=0) # }}} unknown = gmres_result.solution # {{{ visualize from pytential.qbx import QBXLayerPotentialSource lap_qbx = QBXLayerPotentialSource(density_discr, fine_order=bdry_ovsmp_quad_order, qbx_order=qbx_order, fmm_order=qbx_order) from sumpy.visualization import FieldPlotter fplot = FieldPlotter(np.zeros(2), extent=5, npoints=300) from pytential.target import PointsTarget fld0 = bind((qbx, PointsTarget(fplot.points)), representation0_sym)(queue, unknown=unknown, K0=K0).get() fld1 = bind((qbx, PointsTarget(fplot.points)), representation1_sym)(queue, unknown=unknown, K1=K1).get() ones = cl.array.empty(queue, density_discr.nnodes, np.float64) dom1_indicator = -bind( (lap_qbx, PointsTarget(fplot.points)), sym.D(0, sym.var("sigma")))( queue, sigma=ones.fill(1)).get() _, (fld_inc_vol, ) = pot_p2p(queue, fplot.points, sources_1, [strengths_1], out_host=True, k=K0) #fplot.show_scalar_in_mayavi(fld_in_vol.real, max_val=5) fplot.write_vtk_file("potential.vts", [ ("fld0", fld0), ("fld1", fld1), ("fld_inc_vol", fld_inc_vol), ("fld_total", ((fld_inc_vol + fld0) * (1 - dom1_indicator) + fld1 * dom1_indicator)), ("dom1_indicator", dom1_indicator), ])
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()
def run_dielectric_test(cl_ctx, queue, nelements, qbx_order, op_class, mode, k0=3, k1=2.9, mesh_order=10, bdry_quad_order=None, bdry_ovsmp_quad_order=None, use_l2_weighting=False, fmm_order=None, visualize=False): if fmm_order is None: fmm_order = qbx_order * 2 if bdry_quad_order is None: bdry_quad_order = mesh_order if bdry_ovsmp_quad_order is None: bdry_ovsmp_quad_order = 4*bdry_quad_order from meshmode.mesh.generation import ellipse, make_curve_mesh from functools import partial mesh = make_curve_mesh( partial(ellipse, 3), np.linspace(0, 1, nelements+1), mesh_order) density_discr = Discretization( cl_ctx, mesh, InterpolatoryQuadratureSimplexGroupFactory(bdry_quad_order)) logger.info("%d elements" % mesh.nelements) # from meshmode.discretization.visualization import make_visualizer # bdry_vis = make_visualizer(queue, density_discr, 20) # {{{ solve bvp from sumpy.kernel import HelmholtzKernel, AxisTargetDerivative kernel = HelmholtzKernel(2) beta = 2.5 K0 = np.sqrt(k0**2-beta**2) # noqa K1 = np.sqrt(k1**2-beta**2) # noqa pde_op = op_class( mode, k_vacuum=1, interfaces=((0, 1, sym.DEFAULT_SOURCE),), domain_k_exprs=(k0, k1), beta=beta, use_l2_weighting=use_l2_weighting) op_unknown_sym = pde_op.make_unknown("unknown") representation0_sym = pde_op.representation(op_unknown_sym, 0) representation1_sym = pde_op.representation(op_unknown_sym, 1) from pytential.qbx import QBXLayerPotentialSource qbx = QBXLayerPotentialSource( density_discr, fine_order=bdry_ovsmp_quad_order, qbx_order=qbx_order, fmm_order=fmm_order ).with_refinement() #print(sym.pretty(pde_op.operator(op_unknown_sym))) #1/0 bound_pde_op = bind(qbx, pde_op.operator(op_unknown_sym)) e_factor = float(pde_op.ez_enabled) h_factor = float(pde_op.hz_enabled) e_sources_0 = make_obj_array(list(np.array([ [0.1, 0.2] ]).T.copy())) e_strengths_0 = np.array([1*e_factor]) e_sources_1 = make_obj_array(list(np.array([ [4, 4] ]).T.copy())) e_strengths_1 = np.array([1*e_factor]) h_sources_0 = make_obj_array(list(np.array([ [0.2, 0.1] ]).T.copy())) h_strengths_0 = np.array([1*h_factor]) h_sources_1 = make_obj_array(list(np.array([ [4, 5] ]).T.copy())) h_strengths_1 = np.array([1*h_factor]) kernel_grad = [ AxisTargetDerivative(i, kernel) for i in range(density_discr.ambient_dim)] from sumpy.p2p import P2P pot_p2p = P2P(cl_ctx, [kernel], exclude_self=False) pot_p2p_grad = P2P(cl_ctx, kernel_grad, exclude_self=False) normal = bind(density_discr, sym.normal())(queue).as_vector(np.object) tangent = bind( density_discr, sym.pseudoscalar()/sym.area_element())(queue).as_vector(np.object) _, (E0,) = pot_p2p(queue, density_discr.nodes(), e_sources_0, [e_strengths_0], out_host=False, k=K0) _, (E1,) = pot_p2p(queue, density_discr.nodes(), e_sources_1, [e_strengths_1], out_host=False, k=K1) _, (grad0_E0, grad1_E0) = pot_p2p_grad( queue, density_discr.nodes(), e_sources_0, [e_strengths_0], out_host=False, k=K0) _, (grad0_E1, grad1_E1) = pot_p2p_grad( queue, density_discr.nodes(), e_sources_1, [e_strengths_1], out_host=False, k=K1) _, (H0,) = pot_p2p(queue, density_discr.nodes(), h_sources_0, [h_strengths_0], out_host=False, k=K0) _, (H1,) = pot_p2p(queue, density_discr.nodes(), h_sources_1, [h_strengths_1], out_host=False, k=K1) _, (grad0_H0, grad1_H0) = pot_p2p_grad( queue, density_discr.nodes(), h_sources_0, [h_strengths_0], out_host=False, k=K0) _, (grad0_H1, grad1_H1) = pot_p2p_grad( queue, density_discr.nodes(), h_sources_1, [h_strengths_1], out_host=False, k=K1) E0_dntarget = (grad0_E0*normal[0] + grad1_E0*normal[1]) # noqa E1_dntarget = (grad0_E1*normal[0] + grad1_E1*normal[1]) # noqa H0_dntarget = (grad0_H0*normal[0] + grad1_H0*normal[1]) # noqa H1_dntarget = (grad0_H1*normal[0] + grad1_H1*normal[1]) # noqa E0_dttarget = (grad0_E0*tangent[0] + grad1_E0*tangent[1]) # noqa E1_dttarget = (grad0_E1*tangent[0] + grad1_E1*tangent[1]) # noqa H0_dttarget = (grad0_H0*tangent[0] + grad1_H0*tangent[1]) # noqa H1_dttarget = (grad0_H1*tangent[0] + grad1_H1*tangent[1]) # noqa sqrt_w = bind(density_discr, sym.sqrt_jac_q_weight())(queue) bvp_rhs = np.zeros(len(pde_op.bcs), dtype=np.object) for i_bc, terms in enumerate(pde_op.bcs): for term in terms: assert term.i_interface == 0 if term.field_kind == pde_op.field_kind_e: if term.direction == pde_op.dir_none: bvp_rhs[i_bc] += ( term.coeff_outer * E0 + term.coeff_inner * E1) elif term.direction == pde_op.dir_normal: bvp_rhs[i_bc] += ( term.coeff_outer * E0_dntarget + term.coeff_inner * E1_dntarget) elif term.direction == pde_op.dir_tangential: bvp_rhs[i_bc] += ( term.coeff_outer * E0_dttarget + term.coeff_inner * E1_dttarget) else: raise NotImplementedError("direction spec in RHS") elif term.field_kind == pde_op.field_kind_h: if term.direction == pde_op.dir_none: bvp_rhs[i_bc] += ( term.coeff_outer * H0 + term.coeff_inner * H1) elif term.direction == pde_op.dir_normal: bvp_rhs[i_bc] += ( term.coeff_outer * H0_dntarget + term.coeff_inner * H1_dntarget) elif term.direction == pde_op.dir_tangential: bvp_rhs[i_bc] += ( term.coeff_outer * H0_dttarget + term.coeff_inner * H1_dttarget) else: raise NotImplementedError("direction spec in RHS") if use_l2_weighting: bvp_rhs[i_bc] *= sqrt_w scipy_op = bound_pde_op.scipy_op(queue, "unknown", domains=[sym.DEFAULT_TARGET]*len(pde_op.bcs), K0=K0, K1=K1, dtype=np.complex128) if mode == "tem" or op_class is SRep: from sumpy.tools import vector_from_device, vector_to_device from pytential.solve import lu unknown = lu(scipy_op, vector_from_device(queue, bvp_rhs)) unknown = vector_to_device(queue, unknown) else: from pytential.solve import gmres gmres_result = gmres(scipy_op, bvp_rhs, tol=1e-14, progress=True, hard_failure=True, stall_iterations=0) unknown = gmres_result.solution # }}} targets_0 = make_obj_array(list(np.array([ [3.2 + t, -4] for t in [0, 0.5, 1] ]).T.copy())) targets_1 = make_obj_array(list(np.array([ [t*-0.3, t*-0.2] for t in [0, 0.5, 1] ]).T.copy())) from pytential.target import PointsTarget from sumpy.tools import vector_from_device F0_tgt = vector_from_device(queue, bind( # noqa (qbx, PointsTarget(targets_0)), representation0_sym)(queue, unknown=unknown, K0=K0, K1=K1)) F1_tgt = vector_from_device(queue, bind( # noqa (qbx, PointsTarget(targets_1)), representation1_sym)(queue, unknown=unknown, K0=K0, K1=K1)) _, (E0_tgt_true,) = pot_p2p(queue, targets_0, e_sources_0, [e_strengths_0], out_host=True, k=K0) _, (E1_tgt_true,) = pot_p2p(queue, targets_1, e_sources_1, [e_strengths_1], out_host=True, k=K1) _, (H0_tgt_true,) = pot_p2p(queue, targets_0, h_sources_0, [h_strengths_0], out_host=True, k=K0) _, (H1_tgt_true,) = pot_p2p(queue, targets_1, h_sources_1, [h_strengths_1], out_host=True, k=K1) err_F0_total = 0 # noqa err_F1_total = 0 # noqa i_field = 0 def vec_norm(ary): return la.norm(ary.reshape(-1)) def field_kind_to_string(field_kind): return {pde_op.field_kind_e: "E", pde_op.field_kind_h: "H"}[field_kind] for field_kind in pde_op.field_kinds: if not pde_op.is_field_present(field_kind): continue if field_kind == pde_op.field_kind_e: F0_tgt_true = E0_tgt_true # noqa F1_tgt_true = E1_tgt_true # noqa elif field_kind == pde_op.field_kind_h: F0_tgt_true = H0_tgt_true # noqa F1_tgt_true = H1_tgt_true # noqa else: assert False abs_err_F0 = vec_norm(F0_tgt[i_field] - F0_tgt_true) # noqa abs_err_F1 = vec_norm(F1_tgt[i_field] - F1_tgt_true) # noqa rel_err_F0 = abs_err_F0/vec_norm(F0_tgt_true) # noqa rel_err_F1 = abs_err_F1/vec_norm(F1_tgt_true) # noqa err_F0_total = max(rel_err_F0, err_F0_total) # noqa err_F1_total = max(rel_err_F1, err_F1_total) # noqa print("Abs Err %s0" % field_kind_to_string(field_kind), abs_err_F0) print("Abs Err %s1" % field_kind_to_string(field_kind), abs_err_F1) print("Rel Err %s0" % field_kind_to_string(field_kind), rel_err_F0) print("Rel Err %s1" % field_kind_to_string(field_kind), rel_err_F1) i_field += 1 if visualize: from sumpy.visualization import FieldPlotter fplot = FieldPlotter(np.zeros(2), extent=5, npoints=300) from pytential.target import PointsTarget fld0 = bind( (qbx, PointsTarget(fplot.points)), representation0_sym)(queue, unknown=unknown, K0=K0) fld1 = bind( (qbx, PointsTarget(fplot.points)), representation1_sym)(queue, unknown=unknown, K1=K1) comp_fields = [] i_field = 0 for field_kind in pde_op.field_kinds: if not pde_op.is_field_present(field_kind): continue fld_str = field_kind_to_string(field_kind) comp_fields.extend([ ("%s_fld0" % fld_str, fld0[i_field].get()), ("%s_fld1" % fld_str, fld1[i_field].get()), ]) i_field += 0 low_order_qbx = QBXLayerPotentialSource( density_discr, fine_order=bdry_ovsmp_quad_order, qbx_order=2, fmm_order=3).with_refinement() from sumpy.kernel import LaplaceKernel from pytential.target import PointsTarget ones = (cl.array.empty(queue, (density_discr.nnodes,), dtype=np.float64) .fill(1)) ind_func = - bind((low_order_qbx, PointsTarget(fplot.points)), sym.D(LaplaceKernel(2), sym.var("u")))( queue, u=ones).get() _, (e_fld0_true,) = pot_p2p( queue, fplot.points, e_sources_0, [e_strengths_0], out_host=True, k=K0) _, (e_fld1_true,) = pot_p2p( queue, fplot.points, e_sources_1, [e_strengths_1], out_host=True, k=K1) _, (h_fld0_true,) = pot_p2p( queue, fplot.points, h_sources_0, [h_strengths_0], out_host=True, k=K0) _, (h_fld1_true,) = pot_p2p( queue, fplot.points, h_sources_1, [h_strengths_1], out_host=True, k=K1) #fplot.show_scalar_in_mayavi(fld_in_vol.real, max_val=5) fplot.write_vtk_file( "potential-n%d.vts" % nelements, [ ("e_fld0_true", e_fld0_true), ("e_fld1_true", e_fld1_true), ("h_fld0_true", h_fld0_true), ("h_fld1_true", h_fld1_true), ("ind", ind_func), ] + comp_fields ) return err_F0_total, err_F1_total
def test_off_surface_eval(ctx_getter, use_fmm, do_plot=False): logging.basicConfig(level=logging.INFO) cl_ctx = ctx_getter() queue = cl.CommandQueue(cl_ctx) # prevent cache 'splosion from sympy.core.cache import clear_cache clear_cache() nelements = 30 target_order = 8 qbx_order = 3 if use_fmm: fmm_order = qbx_order else: fmm_order = False mesh = make_curve_mesh(partial(ellipse, 3), 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=fmm_order, ).with_refinement() density_discr = qbx.density_discr from sumpy.kernel import LaplaceKernel op = sym.D(LaplaceKernel(2), sym.var("sigma"), qbx_forced_limit=-2) sigma = density_discr.zeros(queue) + 1 fplot = FieldPlotter(np.zeros(2), extent=0.54, npoints=30) from pytential.target import PointsTarget fld_in_vol = bind( (qbx, PointsTarget(fplot.points)), op)(queue, sigma=sigma) err = cl.clmath.fabs(fld_in_vol - (-1)) linf_err = cl.array.max(err).get() print("l_inf error:", linf_err) if do_plot: fplot.show_scalar_in_matplotlib(fld_in_vol.get()) import matplotlib.pyplot as pt pt.colorbar() pt.show() assert linf_err < 1e-3
#op = sym.S(kernel, sym.var("sigma")) 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=1500) from pytential.target import PointsTarget fld_in_vol = bind( (qbx, PointsTarget(fplot.points)), op)(queue, sigma=sigma, k=k).get() #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):
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 ellipse, make_curve_mesh from functools import partial if 0: mesh = make_curve_mesh( partial(ellipse, 1), np.linspace(0, 1, nelements+1), mesh_order) else: base_mesh = make_curve_mesh( partial(ellipse, 1), np.linspace(0, 1, nelements+1), mesh_order) from meshmode.mesh.processing import affine_map, merge_disjoint_meshes nx = 2 ny = 2 dx = 2 / nx meshes = [ affine_map( base_mesh, A=np.diag([dx*0.25, dx*0.25]), b=np.array([dx*(ix-nx/2), dx*(iy-ny/2)])) for ix in range(nx) for iy in range(ny)] mesh = merge_disjoint_meshes(meshes, single_group=True) if 0: from meshmode.mesh.visualization import draw_curve draw_curve(mesh) import matplotlib.pyplot as plt plt.show() pre_density_discr = Discretization( cl_ctx, mesh, InterpolatoryQuadratureSimplexGroupFactory(bdry_quad_order)) from pytential.qbx import ( QBXLayerPotentialSource, QBXTargetAssociationFailedException) qbx, _ = QBXLayerPotentialSource( pre_density_discr, fine_order=bdry_ovsmp_quad_order, qbx_order=qbx_order, fmm_order=fmm_order ).with_refinement() density_discr = qbx.density_discr # {{{ describe bvp from sumpy.kernel import LaplaceKernel, HelmholtzKernel kernel = HelmholtzKernel(2) cse = sym.cse sigma_sym = sym.var("sigma") sqrt_w = sym.sqrt_jac_q_weight(2) inv_sqrt_w_sigma = cse(sigma_sym/sqrt_w) # Brakhage-Werner parameter alpha = 1j # -1 for interior Dirichlet # +1 for exterior Dirichlet loc_sign = +1 bdry_op_sym = (-loc_sign*0.5*sigma_sym + sqrt_w*( alpha*sym.S(kernel, inv_sqrt_w_sigma, k=sym.var("k"), qbx_forced_limit=+1) - sym.D(kernel, inv_sqrt_w_sigma, k=sym.var("k"), qbx_forced_limit="avg") )) # }}} bound_op = bind(qbx, bdry_op_sym) # {{{ fix rhs and solve nodes = density_discr.nodes().with_queue(queue) k_vec = np.array([2, 1]) k_vec = k * k_vec / la.norm(k_vec, 2) def u_incoming_func(x): return cl.clmath.exp( 1j * (x[0] * k_vec[0] + x[1] * k_vec[1])) bc = -u_incoming_func(nodes) bvp_rhs = bind(qbx, sqrt_w*sym.var("bc"))(queue, bc=bc) from pytential.solve import gmres gmres_result = gmres( bound_op.scipy_op(queue, "sigma", dtype=np.complex128, k=k), bvp_rhs, tol=1e-8, progress=True, stall_iterations=0, hard_failure=True) # }}} # {{{ postprocess/visualize sigma = gmres_result.solution repr_kwargs = dict(k=sym.var("k"), qbx_forced_limit=None) representation_sym = ( alpha*sym.S(kernel, inv_sqrt_w_sigma, **repr_kwargs) - sym.D(kernel, inv_sqrt_w_sigma, **repr_kwargs)) from sumpy.visualization import FieldPlotter fplot = FieldPlotter(np.zeros(2), extent=5, npoints=500) targets = cl.array.to_device(queue, fplot.points) u_incoming = u_incoming_func(targets) qbx_stick_out = qbx.copy(target_association_tolerance=0.05) ones_density = density_discr.zeros(queue) ones_density.fill(1) indicator = bind( (qbx_stick_out, PointsTarget(targets)), sym.D(LaplaceKernel(2), sym.var("sigma"), qbx_forced_limit=None))( queue, sigma=ones_density).get() try: fld_in_vol = bind( (qbx_stick_out, PointsTarget(targets)), representation_sym)(queue, sigma=sigma, k=k).get() except QBXTargetAssociationFailedException as e: fplot.write_vtk_file( "failed-targets.vts", [ ("failed", e.failed_target_flags.get(queue)) ] ) raise #fplot.show_scalar_in_mayavi(fld_in_vol.real, max_val=5) fplot.write_vtk_file( "potential-helm.vts", [ ("potential", fld_in_vol), ("indicator", indicator), ("u_incoming", u_incoming.get()), ] )
def run_exterior_stokes_2d(ctx_factory, nelements, mesh_order=4, target_order=4, qbx_order=4, fmm_order=10, mu=1, circle_rad=1.5, do_plot=False): # This program tests an exterior Stokes flow in 2D using the # compound representation given in Hsiao & Kress, # ``On an integral equation for the two-dimensional exterior Stokes problem,'' # Applied Numerical Mathematics 1 (1985). logging.basicConfig(level=logging.INFO) cl_ctx = cl.create_some_context() queue = cl.CommandQueue(cl_ctx) ovsmp_target_order = 4 * target_order from meshmode.mesh.generation import ( # noqa make_curve_mesh, starfish, ellipse, drop) mesh = make_curve_mesh(lambda t: circle_rad * ellipse(1, t), np.linspace(0, 1, nelements + 1), target_order) coarse_density_discr = Discretization( cl_ctx, mesh, InterpolatoryQuadratureSimplexGroupFactory(target_order)) from pytential.qbx import QBXLayerPotentialSource target_association_tolerance = 0.05 qbx, _ = QBXLayerPotentialSource( coarse_density_discr, fine_order=ovsmp_target_order, qbx_order=qbx_order, fmm_order=fmm_order, target_association_tolerance=target_association_tolerance, _expansions_in_tree_have_extent=True, ).with_refinement() density_discr = qbx.density_discr normal = bind(density_discr, sym.normal(2).as_vector())(queue) path_length = bind(density_discr, sym.integral(2, 1, 1))(queue) # {{{ describe bvp from pytential.symbolic.stokes import StressletWrapper, StokesletWrapper dim = 2 cse = sym.cse sigma_sym = sym.make_sym_vector("sigma", dim) meanless_sigma_sym = cse(sigma_sym - sym.mean(2, 1, sigma_sym)) int_sigma = sym.Ones() * sym.integral(2, 1, sigma_sym) nvec_sym = sym.make_sym_vector("normal", dim) mu_sym = sym.var("mu") # -1 for interior Dirichlet # +1 for exterior Dirichlet loc_sign = 1 stresslet_obj = StressletWrapper(dim=2) stokeslet_obj = StokesletWrapper(dim=2) bdry_op_sym = (-loc_sign * 0.5 * sigma_sym - stresslet_obj.apply( sigma_sym, nvec_sym, mu_sym, qbx_forced_limit='avg') + stokeslet_obj.apply( meanless_sigma_sym, mu_sym, qbx_forced_limit='avg') - (0.5 / np.pi) * int_sigma) # }}} bound_op = bind(qbx, bdry_op_sym) # {{{ fix rhs and solve def fund_soln(x, y, loc, strength): #with direction (1,0) for point source r = cl.clmath.sqrt((x - loc[0])**2 + (y - loc[1])**2) scaling = strength / (4 * np.pi * mu) xcomp = (-cl.clmath.log(r) + (x - loc[0])**2 / r**2) * scaling ycomp = ((x - loc[0]) * (y - loc[1]) / r**2) * scaling return [xcomp, ycomp] def rotlet_soln(x, y, loc): r = cl.clmath.sqrt((x - loc[0])**2 + (y - loc[1])**2) xcomp = -(y - loc[1]) / r**2 ycomp = (x - loc[0]) / r**2 return [xcomp, ycomp] def fund_and_rot_soln(x, y, loc, strength): #with direction (1,0) for point source r = cl.clmath.sqrt((x - loc[0])**2 + (y - loc[1])**2) scaling = strength / (4 * np.pi * mu) xcomp = ((-cl.clmath.log(r) + (x - loc[0])**2 / r**2) * scaling - (y - loc[1]) * strength * 0.125 / r**2 + 3.3) ycomp = (((x - loc[0]) * (y - loc[1]) / r**2) * scaling + (x - loc[0]) * strength * 0.125 / r**2 + 1.5) return [xcomp, ycomp] nodes = density_discr.nodes().with_queue(queue) fund_soln_loc = np.array([0.5, -0.2]) strength = 100. bc = fund_and_rot_soln(nodes[0], nodes[1], fund_soln_loc, strength) omega_sym = sym.make_sym_vector("omega", dim) u_A_sym_bdry = stokeslet_obj.apply( # noqa: N806 omega_sym, mu_sym, qbx_forced_limit=1) omega = [ cl.array.to_device(queue, (strength / path_length) * np.ones(len(nodes[0]))), cl.array.to_device(queue, np.zeros(len(nodes[0]))) ] bvp_rhs = bind(qbx, sym.make_sym_vector("bc", dim) + u_A_sym_bdry)(queue, bc=bc, mu=mu, omega=omega) gmres_result = gmres(bound_op.scipy_op(queue, "sigma", np.float64, mu=mu, normal=normal), bvp_rhs, x0=bvp_rhs, tol=1e-9, progress=True, stall_iterations=0, hard_failure=True) # }}} # {{{ postprocess/visualize sigma = gmres_result.solution sigma_int_val_sym = sym.make_sym_vector("sigma_int_val", 2) int_val = bind(qbx, sym.integral(2, 1, sigma_sym))(queue, sigma=sigma) int_val = -int_val / (2 * np.pi) print("int_val = ", int_val) u_A_sym_vol = stokeslet_obj.apply( # noqa: N806 omega_sym, mu_sym, qbx_forced_limit=2) representation_sym = ( -stresslet_obj.apply(sigma_sym, nvec_sym, mu_sym, qbx_forced_limit=2) + stokeslet_obj.apply(meanless_sigma_sym, mu_sym, qbx_forced_limit=2) - u_A_sym_vol + sigma_int_val_sym) nsamp = 30 eval_points_1d = np.linspace(-3., 3., nsamp) eval_points = np.zeros((2, len(eval_points_1d)**2)) eval_points[0, :] = np.tile(eval_points_1d, len(eval_points_1d)) eval_points[1, :] = np.repeat(eval_points_1d, len(eval_points_1d)) def circle_mask(test_points, radius): return (test_points[0, :]**2 + test_points[1, :]**2 > radius**2) def outside_circle(test_points, radius): mask = circle_mask(test_points, radius) return np.array([row[mask] for row in test_points]) eval_points = outside_circle(eval_points, radius=circle_rad) from pytential.target import PointsTarget vel = bind((qbx, PointsTarget(eval_points)), representation_sym)(queue, sigma=sigma, mu=mu, normal=normal, sigma_int_val=int_val, omega=omega) print("@@@@@@@@") fplot = FieldPlotter(np.zeros(2), extent=6, npoints=100) plot_pts = outside_circle(fplot.points, radius=circle_rad) plot_vel = bind((qbx, PointsTarget(plot_pts)), representation_sym)(queue, sigma=sigma, mu=mu, normal=normal, sigma_int_val=int_val, omega=omega) def get_obj_array(obj_array): return make_obj_array([ary.get() for ary in obj_array]) exact_soln = fund_and_rot_soln(cl.array.to_device(queue, eval_points[0]), cl.array.to_device(queue, eval_points[1]), fund_soln_loc, strength) vel = get_obj_array(vel) err = vel - get_obj_array(exact_soln) # FIXME: Pointwise relative errors don't make sense! rel_err = err / (get_obj_array(exact_soln)) if 0: print("@@@@@@@@") print("vel[0], err[0], rel_err[0] ***** vel[1], err[1], rel_err[1]: ") for i in range(len(vel[0])): print("%15.8e, %15.8e, %15.8e ***** %15.8e, %15.8e, %15.8e\n" % (vel[0][i], err[0][i], rel_err[0][i], vel[1][i], err[1][i], rel_err[1][i])) print("@@@@@@@@") l2_err = np.sqrt((6. / (nsamp - 1))**2 * np.sum(err[0] * err[0]) + (6. / (nsamp - 1))**2 * np.sum(err[1] * err[1])) l2_rel_err = np.sqrt((6. / (nsamp - 1))**2 * np.sum(rel_err[0] * rel_err[0]) + (6. / (nsamp - 1))**2 * np.sum(rel_err[1] * rel_err[1])) print("L2 error estimate: ", l2_err) print("L2 rel error estimate: ", l2_rel_err) print("max error at sampled points: ", max(abs(err[0])), max(abs(err[1]))) print("max rel error at sampled points: ", max(abs(rel_err[0])), max(abs(rel_err[1]))) if do_plot: import matplotlib matplotlib.use("Agg") import matplotlib.pyplot as plt full_pot = np.zeros_like(fplot.points) * float("nan") mask = circle_mask(fplot.points, radius=circle_rad) for i, vel in enumerate(plot_vel): full_pot[i, mask] = vel.get() plt.quiver(fplot.points[0], fplot.points[1], full_pot[0], full_pot[1], linewidth=0.1) plt.savefig("exterior-2d-field.pdf") # }}} h_max = bind(qbx, sym.h_max(qbx.ambient_dim))(queue) return h_max, l2_err
def timing_run(nx, ny): import logging logging.basicConfig(level=logging.WARNING) # INFO for more progress info cl_ctx = cl.create_some_context() queue = cl.CommandQueue(cl_ctx) mesh = make_mesh(nx=nx, ny=ny) density_discr = Discretization( cl_ctx, mesh, InterpolatoryQuadratureSimplexGroupFactory(bdry_quad_order)) from pytential.qbx import ( QBXLayerPotentialSource, QBXTargetAssociationFailedException) qbx = QBXLayerPotentialSource( density_discr, fine_order=bdry_ovsmp_quad_order, qbx_order=qbx_order, fmm_order=fmm_order ) # {{{ describe bvp from sumpy.kernel import HelmholtzKernel kernel = HelmholtzKernel(2) cse = sym.cse sigma_sym = sym.var("sigma") sqrt_w = sym.sqrt_jac_q_weight(2) inv_sqrt_w_sigma = cse(sigma_sym/sqrt_w) # Brakhage-Werner parameter alpha = 1j # -1 for interior Dirichlet # +1 for exterior Dirichlet loc_sign = +1 bdry_op_sym = (-loc_sign*0.5*sigma_sym + sqrt_w*( alpha*sym.S(kernel, inv_sqrt_w_sigma, k=sym.var("k")) - sym.D(kernel, inv_sqrt_w_sigma, k=sym.var("k")) )) # }}} bound_op = bind(qbx, bdry_op_sym) # {{{ fix rhs and solve mode_nr = 3 nodes = density_discr.nodes().with_queue(queue) angle = cl.clmath.atan2(nodes[1], nodes[0]) sigma = cl.clmath.cos(mode_nr*angle) # }}} # {{{ postprocess/visualize repr_kwargs = dict(k=sym.var("k"), qbx_forced_limit=+1) sym_op = sym.S(kernel, sym.var("sigma"), **repr_kwargs) bound_op = bind(qbx, sym_op) print("FMM WARM-UP RUN 1: %d elements" % mesh.nelements) bound_op(queue, sigma=sigma, k=k) print("FMM WARM-UP RUN 2: %d elements" % mesh.nelements) bound_op(queue, sigma=sigma, k=k) queue.finish() print("FMM TIMING RUN: %d elements" % mesh.nelements) from time import time t_start = time() bound_op(queue, sigma=sigma, k=k) queue.finish() elapsed = time()-t_start print("FMM TIMING RUN DONE: %d elements -> %g s" % (mesh.nelements, elapsed)) return (mesh.nelements, elapsed) if 0: from sumpy.visualization import FieldPlotter fplot = FieldPlotter(np.zeros(2), extent=5, npoints=1500) targets = cl.array.to_device(queue, fplot.points) qbx_tgt_tol = qbx.copy(target_association_tolerance=0.05) indicator_qbx = qbx_tgt_tol.copy( fmm_level_to_order=lambda lev: 7, qbx_order=2) ones_density = density_discr.zeros(queue) ones_density.fill(1) indicator = bind( (indicator_qbx, PointsTarget(targets)), sym_op)( queue, sigma=ones_density).get() qbx_stick_out = qbx.copy(target_stick_out_factor=0.1) try: fld_in_vol = bind( (qbx_stick_out, PointsTarget(targets)), sym_op)(queue, sigma=sigma, k=k).get() except QBXTargetAssociationFailedException as e: fplot.write_vtk_file( "failed-targets.vts", [ ("failed", e.failed_target_flags.get(queue)) ] ) raise #fplot.show_scalar_in_mayavi(fld_in_vol.real, max_val=5) fplot.write_vtk_file( "potential-scaling.vts", [ ("potential", fld_in_vol), ("indicator", indicator) ] )
def test_off_surface_eval_vs_direct(ctx_factory, do_plot=False): logging.basicConfig(level=logging.INFO) cl_ctx = ctx_factory() queue = cl.CommandQueue(cl_ctx) actx = PyOpenCLArrayContext(queue) # prevent cache 'splosion from sympy.core.cache import clear_cache clear_cache() nelements = 300 target_order = 8 qbx_order = 3 mesh = make_curve_mesh(WobblyCircle.random(8, seed=30), 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)) direct_qbx = QBXLayerPotentialSource( pre_density_discr, 4*target_order, qbx_order, fmm_order=False, target_association_tolerance=0.05, ) fmm_qbx = QBXLayerPotentialSource( pre_density_discr, 4*target_order, qbx_order, fmm_order=qbx_order + 3, _expansions_in_tree_have_extent=True, target_association_tolerance=0.05, ) fplot = FieldPlotter(np.zeros(2), extent=5, npoints=500) from pytential.target import PointsTarget ptarget = PointsTarget(fplot.points) from sumpy.kernel import LaplaceKernel places = GeometryCollection({ "direct_qbx": direct_qbx, "fmm_qbx": fmm_qbx, "target": ptarget}) direct_density_discr = places.get_discretization("direct_qbx") fmm_density_discr = places.get_discretization("fmm_qbx") from pytential.qbx import QBXTargetAssociationFailedException op = sym.D(LaplaceKernel(2), sym.var("sigma"), qbx_forced_limit=None) try: direct_sigma = direct_density_discr.zeros(actx) + 1 direct_fld_in_vol = bind(places, op, auto_where=("direct_qbx", "target"))( actx, sigma=direct_sigma) except QBXTargetAssociationFailedException as e: fplot.show_scalar_in_matplotlib( actx.to_numpy(actx.thaw(e.failed_target_flags))) import matplotlib.pyplot as pt pt.show() raise fmm_sigma = fmm_density_discr.zeros(actx) + 1 fmm_fld_in_vol = bind(places, op, auto_where=("fmm_qbx", "target"))( actx, sigma=fmm_sigma) err = actx.np.fabs(fmm_fld_in_vol - direct_fld_in_vol) linf_err = actx.to_numpy(err).max() print("l_inf error:", linf_err) if do_plot: #fplot.show_scalar_in_mayavi(0.1*.get(queue)) fplot.write_vtk_file("potential.vts", [ ("fmm_fld_in_vol", actx.to_numpy(fmm_fld_in_vol)), ("direct_fld_in_vol", actx.to_numpy(direct_fld_in_vol)) ]) assert linf_err < 1e-3
def test_p2e2p(ctx_getter, base_knl, expn_class, order, with_source_derivative): #logging.basicConfig(level=logging.INFO) from sympy.core.cache import clear_cache clear_cache() ctx = ctx_getter() queue = cl.CommandQueue(ctx) np.random.seed(17) res = 100 nsources = 100 extra_kwargs = {} if isinstance(base_knl, HelmholtzKernel): if base_knl.allow_evanescent: extra_kwargs["k"] = 0.2 * (0.707 + 0.707j) else: extra_kwargs["k"] = 0.2 if with_source_derivative: knl = DirectionalSourceDerivative(base_knl, "dir_vec") else: knl = base_knl out_kernels = [ knl, AxisTargetDerivative(0, knl), ] expn = expn_class(knl, order=order) from sumpy import P2EFromSingleBox, E2PFromSingleBox, P2P p2e = P2EFromSingleBox(ctx, expn, out_kernels) e2p = E2PFromSingleBox(ctx, expn, out_kernels) p2p = P2P(ctx, out_kernels, exclude_self=False) from pytools.convergence import EOCRecorder eoc_rec_pot = EOCRecorder() eoc_rec_grad_x = EOCRecorder() from sumpy.expansion.local import LocalExpansionBase if issubclass(expn_class, LocalExpansionBase): h_values = [1/5, 1/7, 1/20] else: h_values = [1/2, 1/3, 1/5] center = np.array([2, 1], np.float64) sources = (0.7*(-0.5+np.random.rand(knl.dim, nsources).astype(np.float64)) + center[:, np.newaxis]) strengths = np.ones(nsources, dtype=np.float64) * (1/nsources) source_boxes = np.array([0], dtype=np.int32) box_source_starts = np.array([0], dtype=np.int32) box_source_counts_nonchild = np.array([nsources], dtype=np.int32) extra_source_kwargs = extra_kwargs.copy() if with_source_derivative: alpha = np.linspace(0, 2*np.pi, nsources, np.float64) dir_vec = np.vstack([np.cos(alpha), np.sin(alpha)]) extra_source_kwargs["dir_vec"] = dir_vec from sumpy.visualization import FieldPlotter for h in h_values: if issubclass(expn_class, LocalExpansionBase): loc_center = np.array([5.5, 0.0]) + center centers = np.array(loc_center, dtype=np.float64).reshape(knl.dim, 1) fp = FieldPlotter(loc_center, extent=h, npoints=res) else: eval_center = np.array([1/h, 0.0]) + center fp = FieldPlotter(eval_center, extent=0.1, npoints=res) centers = ( np.array([0.0, 0.0], dtype=np.float64).reshape(knl.dim, 1) + center[:, np.newaxis]) targets = fp.points rscale = 0.5 # pick something non-1 # {{{ apply p2e evt, (mpoles,) = p2e(queue, source_boxes=source_boxes, box_source_starts=box_source_starts, box_source_counts_nonchild=box_source_counts_nonchild, centers=centers, sources=sources, strengths=strengths, nboxes=1, tgt_base_ibox=0, rscale=rscale, #flags="print_hl_cl", out_host=True, **extra_source_kwargs) # }}} # {{{ apply e2p ntargets = targets.shape[-1] box_target_starts = np.array([0], dtype=np.int32) box_target_counts_nonchild = np.array([ntargets], dtype=np.int32) evt, (pot, grad_x, ) = e2p( queue, src_expansions=mpoles, src_base_ibox=0, target_boxes=source_boxes, box_target_starts=box_target_starts, box_target_counts_nonchild=box_target_counts_nonchild, centers=centers, targets=targets, rscale=rscale, #flags="print_hl_cl", out_host=True, **extra_kwargs) # }}} # {{{ compute (direct) reference solution evt, (pot_direct, grad_x_direct, ) = p2p( queue, targets, sources, (strengths,), out_host=True, **extra_source_kwargs) err_pot = la.norm((pot - pot_direct)/res**2) err_grad_x = la.norm((grad_x - grad_x_direct)/res**2) if 1: err_pot = err_pot / la.norm((pot_direct)/res**2) err_grad_x = err_grad_x / la.norm((grad_x_direct)/res**2) if 0: import matplotlib.pyplot as pt from matplotlib.colors import Normalize pt.subplot(131) im = fp.show_scalar_in_matplotlib(pot.real) im.set_norm(Normalize(vmin=-0.1, vmax=0.1)) pt.subplot(132) im = fp.show_scalar_in_matplotlib(pot_direct.real) im.set_norm(Normalize(vmin=-0.1, vmax=0.1)) pt.colorbar() pt.subplot(133) im = fp.show_scalar_in_matplotlib(np.log10(1e-15+np.abs(pot-pot_direct))) im.set_norm(Normalize(vmin=-6, vmax=1)) pt.colorbar() pt.show() # }}} eoc_rec_pot.add_data_point(h, err_pot) eoc_rec_grad_x.add_data_point(h, err_grad_x) print(expn_class, knl, order) print("POTENTIAL:") print(eoc_rec_pot) print("X TARGET DERIVATIVE:") print(eoc_rec_grad_x) tgt_order = order + 1 if issubclass(expn_class, LocalExpansionBase): tgt_order_grad = tgt_order - 1 slack = 0.7 grad_slack = 0.5 else: tgt_order_grad = tgt_order + 1 slack = 0.5 grad_slack = 1 if order <= 2: slack += 1 grad_slack += 1 if isinstance(knl, DirectionalSourceDerivative): slack += 1 grad_slack += 2 if isinstance(base_knl, HelmholtzKernel): if base_knl.allow_evanescent: slack += 0.5 grad_slack += 0.5 if issubclass(expn_class, VolumeTaylorMultipoleExpansionBase): slack += 0.3 grad_slack += 0.3 assert eoc_rec_pot.order_estimate() > tgt_order - slack assert eoc_rec_grad_x.order_estimate() > tgt_order_grad - grad_slack
def test_off_surface_eval_vs_direct(ctx_getter, do_plot=False): logging.basicConfig(level=logging.INFO) cl_ctx = ctx_getter() queue = cl.CommandQueue(cl_ctx) # prevent cache 'splosion from sympy.core.cache import clear_cache clear_cache() nelements = 300 target_order = 8 qbx_order = 3 mesh = make_curve_mesh(WobblyCircle.random(8, seed=30), 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)) direct_qbx, _ = QBXLayerPotentialSource( pre_density_discr, 4*target_order, qbx_order, fmm_order=False, target_association_tolerance=0.05, ).with_refinement() fmm_qbx, _ = QBXLayerPotentialSource( pre_density_discr, 4*target_order, qbx_order, fmm_order=qbx_order + 3, _expansions_in_tree_have_extent=True, target_association_tolerance=0.05, ).with_refinement() fplot = FieldPlotter(np.zeros(2), extent=5, npoints=1000) from pytential.target import PointsTarget ptarget = PointsTarget(fplot.points) from sumpy.kernel import LaplaceKernel op = sym.D(LaplaceKernel(2), sym.var("sigma"), qbx_forced_limit=None) from pytential.qbx import QBXTargetAssociationFailedException try: direct_density_discr = direct_qbx.density_discr direct_sigma = direct_density_discr.zeros(queue) + 1 direct_fld_in_vol = bind((direct_qbx, ptarget), op)( queue, sigma=direct_sigma) except QBXTargetAssociationFailedException as e: fplot.show_scalar_in_matplotlib(e.failed_target_flags.get(queue)) import matplotlib.pyplot as pt pt.show() raise fmm_density_discr = fmm_qbx.density_discr fmm_sigma = fmm_density_discr.zeros(queue) + 1 fmm_fld_in_vol = bind((fmm_qbx, ptarget), op)(queue, sigma=fmm_sigma) err = cl.clmath.fabs(fmm_fld_in_vol - direct_fld_in_vol) linf_err = cl.array.max(err).get() print("l_inf error:", linf_err) if do_plot: #fplot.show_scalar_in_mayavi(0.1*.get(queue)) fplot.write_vtk_file("potential.vts", [ ("fmm_fld_in_vol", fmm_fld_in_vol.get(queue)), ("direct_fld_in_vol", direct_fld_in_vol.get(queue)) ]) assert linf_err < 1e-3
representation = sym.S(0, sym.var("sigma")) op = representation bc = cl.clmath.cos(mode_nr * angle) bound_op = bind(discr, op) from pytential.gmres import gmres gmres_result = gmres(bound_op.scipy_op(queue, "sigma"), bc, tol=1e-14, progress=True, hard_failure=True) import sys sys.exit() sigma = gmres_result.solution fplot = FieldPlotter(np.zeros(2), extent=5, npoints=500) from pytential.discretization.target import PointsTarget fld_in_vol = bind((discr, PointsTarget(fplot.points)), representation)(queue, sigma=sigma).get() fld_on_bdry = bound_op(queue, sigma=sigma).get() from mayavi import mlab fplot.show_scalar_in_mayavi(fld_in_vol.real, max_val=5) mlab.colorbar() mlab.show()
representation = sym.S(0, sym.var("sigma")) op = representation bc = cl.clmath.cos(mode_nr*angle) bound_op = bind(discr, op) from pytential.gmres import gmres gmres_result = gmres( bound_op.scipy_op(queue, "sigma"), bc, tol=1e-14, progress=True, hard_failure=True) import sys sys.exit() sigma = gmres_result.solution fplot = FieldPlotter(np.zeros(2), extent=5, npoints=500) from pytential.discretization.target import PointsTarget fld_in_vol = bind( (discr, PointsTarget(fplot.points)), representation)(queue, sigma=sigma).get() fld_on_bdry = bound_op(queue, sigma=sigma).get() from mayavi import mlab fplot.show_scalar_in_mayavi(fld_in_vol.real, max_val=5) mlab.colorbar() mlab.show()
def timing_run(nx, ny, visualize=False): import logging logging.basicConfig(level=logging.WARNING) # INFO for more progress info cl_ctx = cl.create_some_context() queue = cl.CommandQueue(cl_ctx) actx = PyOpenCLArrayContext(queue) mesh = make_mesh(nx=nx, ny=ny, visualize=visualize) density_discr = Discretization( actx, mesh, InterpolatoryQuadratureSimplexGroupFactory(bdry_quad_order)) from pytential.qbx import (QBXLayerPotentialSource, QBXTargetAssociationFailedException) qbx = QBXLayerPotentialSource(density_discr, fine_order=bdry_ovsmp_quad_order, qbx_order=qbx_order, fmm_order=fmm_order) places = {"qbx": qbx} if visualize: from sumpy.visualization import FieldPlotter fplot = FieldPlotter(np.zeros(2), extent=5, npoints=1500) targets = PointsTarget(actx.from_numpy(fplot.points)) places.update({ "plot-targets": targets, "qbx-indicator": qbx.copy(target_association_tolerance=0.05, fmm_level_to_order=lambda lev: 7, qbx_order=2), "qbx-target-assoc": qbx.copy(target_association_tolerance=0.1) }) from pytential import GeometryCollection places = GeometryCollection(places, auto_where="qbx") density_discr = places.get_discretization("qbx") # {{{ describe bvp from sumpy.kernel import HelmholtzKernel kernel = HelmholtzKernel(2) sigma_sym = sym.var("sigma") sqrt_w = sym.sqrt_jac_q_weight(2) inv_sqrt_w_sigma = sym.cse(sigma_sym / sqrt_w) # Brakhage-Werner parameter alpha = 1j # -1 for interior Dirichlet # +1 for exterior Dirichlet loc_sign = +1 k_sym = sym.var("k") S_sym = sym.S(kernel, inv_sqrt_w_sigma, k=k_sym, qbx_forced_limit=+1) D_sym = sym.D(kernel, inv_sqrt_w_sigma, k=k_sym, qbx_forced_limit="avg") bdry_op_sym = -loc_sign * 0.5 * sigma_sym + sqrt_w * (alpha * S_sym + D_sym) # }}} bound_op = bind(places, bdry_op_sym) # {{{ fix rhs and solve mode_nr = 3 from meshmode.dof_array import thaw nodes = thaw(actx, density_discr.nodes()) angle = actx.np.arctan2(nodes[1], nodes[0]) sigma = actx.np.cos(mode_nr * angle) # }}} # {{{ postprocess/visualize repr_kwargs = dict(k=sym.var("k"), qbx_forced_limit=+1) sym_op = sym.S(kernel, sym.var("sigma"), **repr_kwargs) bound_op = bind(places, sym_op) print("FMM WARM-UP RUN 1: %5d elements" % mesh.nelements) bound_op(actx, sigma=sigma, k=k) queue.finish() print("FMM WARM-UP RUN 2: %5d elements" % mesh.nelements) bound_op(actx, sigma=sigma, k=k) queue.finish() from time import time t_start = time() bound_op(actx, sigma=sigma, k=k) actx.queue.finish() elapsed = time() - t_start print("FMM TIMING RUN: %5d elements -> %g s" % (mesh.nelements, elapsed)) if visualize: ones_density = density_discr.zeros(queue) ones_density.fill(1) indicator = bind(places, sym_op, auto_where=("qbx-indicator", "plot-targets"))( queue, sigma=ones_density).get() try: fld_in_vol = bind(places, sym_op, auto_where=("qbx-target-assoc", "plot-targets"))(queue, sigma=sigma, k=k).get() except QBXTargetAssociationFailedException as e: fplot.write_vtk_file("scaling-study-failed-targets.vts", [ ("failed", e.failed_target_flags.get(queue)), ]) raise fplot.write_vtk_file("scaling-study-potential.vts", [ ("potential", fld_in_vol), ("indicator", indicator), ]) return (mesh.nelements, elapsed)
def main(): # cl.array.to_device(queue, numpy_array) from meshmode.mesh.io import generate_gmsh, FileSource mesh = generate_gmsh( FileSource("ellipsoid.step"), 2, order=2, other_options=["-string", "Mesh.CharacteristicLengthMax = %g;" % h]) from meshmode.mesh.processing import perform_flips # Flip elements--gmsh generates inside-out geometry. mesh = perform_flips(mesh, np.ones(mesh.nelements)) print("%d elements" % mesh.nelements) from meshmode.mesh.processing import find_bounding_box bbox_min, bbox_max = find_bounding_box(mesh) bbox_center = 0.5*(bbox_min+bbox_max) bbox_size = max(bbox_max-bbox_min) / 2 logger.info("%d elements" % mesh.nelements) 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)) qbx = QBXLayerPotentialSource(density_discr, 4*target_order, qbx_order, fmm_order=qbx_order + 10, fmm_backend="fmmlib") from pytential.symbolic.pde.maxwell import MuellerAugmentedMFIEOperator pde_op = MuellerAugmentedMFIEOperator( omega=0.4, epss=[1.4, 1.0], mus=[1.2, 1.0], ) from pytential import bind, sym unk = pde_op.make_unknown("sigma") sym_operator = pde_op.operator(unk) sym_rhs = pde_op.rhs( sym.make_sym_vector("Einc", 3), sym.make_sym_vector("Hinc", 3)) sym_repr = pde_op.representation(0, unk) if 1: expr = sym_repr print(sym.pretty(expr)) print("#"*80) from pytential.target import PointsTarget tgt_points=np.zeros((3,1)) tgt_points[0,0] = 100 tgt_points[1,0] = -200 tgt_points[2,0] = 300 bound_op = bind((qbx, PointsTarget(tgt_points)), expr) print(bound_op.code) if 1: def green3e(x,y,z,source,strength,k): # electric field corresponding to dyadic green's function # due to monochromatic electric dipole located at "source". # "strength" is the the intensity of the dipole. # E = (I + Hess)(exp(ikr)/r) dot (strength) # dx = x - source[0] dy = y - source[1] dz = z - source[2] rr = np.sqrt(dx**2 + dy**2 + dz**2) fout = np.exp(1j*k*rr)/rr evec = fout*strength qmat = np.zeros((3,3),dtype=np.complex128) qmat[0,0]=(2*dx**2-dy**2-dz**2)*(1-1j*k*rr) qmat[1,1]=(2*dy**2-dz**2-dx**2)*(1-1j*k*rr) qmat[2,2]=(2*dz**2-dx**2-dy**2)*(1-1j*k*rr) qmat[0,0]=qmat[0,0]+(-k**2*dx**2*rr**2) qmat[1,1]=qmat[1,1]+(-k**2*dy**2*rr**2) qmat[2,2]=qmat[2,2]+(-k**2*dz**2*rr**2) qmat[0,1]=(3-k**2*rr**2-3*1j*k*rr)*(dx*dy) qmat[1,2]=(3-k**2*rr**2-3*1j*k*rr)*(dy*dz) qmat[2,0]=(3-k**2*rr**2-3*1j*k*rr)*(dz*dx) qmat[1,0]=qmat[0,1] qmat[2,1]=qmat[1,2] qmat[0,2]=qmat[2,0] fout=np.exp(1j*k*rr)/rr**5/k**2 fvec = fout*np.dot(qmat,strength) evec = evec + fvec return evec def green3m(x,y,z,source,strength,k): # magnetic field corresponding to dyadic green's function # due to monochromatic electric dipole located at "source". # "strength" is the the intensity of the dipole. # H = curl((I + Hess)(exp(ikr)/r) dot (strength)) = # strength \cross \grad (exp(ikr)/r) # dx = x - source[0] dy = y - source[1] dz = z - source[2] rr = np.sqrt(dx**2 + dy**2 + dz**2) fout=(1-1j*k*rr)*np.exp(1j*k*rr)/rr**3 fvec = np.zeros(3,dtype=np.complex128) fvec[0] = fout*dx fvec[1] = fout*dy fvec[2] = fout*dz hvec = np.cross(strength,fvec) return hvec def dipole3e(x,y,z,source,strength,k): # # evalaute electric and magnetic field due # to monochromatic electric dipole located at "source" # with intensity "strength" evec = green3e(x,y,z,source,strength,k) evec = evec*1j*k hvec = green3m(x,y,z,source,strength,k) return evec,hvec def dipole3m(x,y,z,source,strength,k): # # evalaute electric and magnetic field due # to monochromatic magnetic dipole located at "source" # with intensity "strength" evec = green3m(x,y,z,source,strength,k) hvec = green3e(x,y,z,source,strength,k) hvec = -hvec*1j*k return evec,hvec def dipole3eall(x,y,z,sources,strengths,k): ns = len(strengths) evec = np.zeros(3,dtype=np.complex128) hvec = np.zeros(3,dtype=np.complex128) for i in range(ns): evect,hvect = dipole3e(x,y,z,sources[i],strengths[i],k) evec = evec + evect hvec = hvec + hvect nodes = density_discr.nodes().with_queue(queue).get() source = [0.01,-0.03,0.02] # source = cl.array.to_device(queue,np.zeros(3)) # source[0] = 0.01 # source[1] =-0.03 # source[2] = 0.02 strength = np.ones(3) # evec = cl.array.to_device(queue,np.zeros((3,len(nodes[0])),dtype=np.complex128)) # hvec = cl.array.to_device(queue,np.zeros((3,len(nodes[0])),dtype=np.complex128)) evec = np.zeros((3,len(nodes[0])),dtype=np.complex128) hvec = np.zeros((3,len(nodes[0])),dtype=np.complex128) for i in range(len(nodes[0])): evec[:,i],hvec[:,i] = dipole3e(nodes[0][i],nodes[1][i],nodes[2][i],source,strength,k) print(np.shape(hvec)) print(type(evec)) print(type(hvec)) evec = cl.array.to_device(queue,evec) hvec = cl.array.to_device(queue,hvec) bvp_rhs = bind(qbx, sym_rhs)(queue,Einc=evec,Hinc=hvec) print(np.shape(bvp_rhs)) print(type(bvp_rhs)) # print(bvp_rhs) 1/-1 bound_op = bind(qbx, sym_operator) from pytential.solve import gmres if 0: gmres_result = gmres( bound_op.scipy_op(queue, "sigma", dtype=np.complex128, k=k), bvp_rhs, tol=1e-8, progress=True, stall_iterations=0, hard_failure=True) sigma = gmres_result.solution fld_at_tgt = bind((qbx, PointsTarget(tgt_points)), sym_repr)(queue, sigma=bvp_rhs,k=k) fld_at_tgt = np.array([ fi.get() for fi in fld_at_tgt ]) print(fld_at_tgt) 1/0 # }}} #mlab.figure(bgcolor=(1, 1, 1)) if 1: from meshmode.discretization.visualization import make_visualizer bdry_vis = make_visualizer(queue, density_discr, target_order) bdry_normals = bind(density_discr, sym.normal(3))(queue)\ .as_vector(dtype=object) bdry_vis.write_vtk_file("source.vtu", [ ("sigma", sigma), ("bdry_normals", bdry_normals), ]) fplot = FieldPlotter(bbox_center, extent=2*bbox_size, npoints=(150, 150, 1)) qbx_tgt_tol = qbx.copy(target_association_tolerance=0.1) from pytential.target import PointsTarget from pytential.qbx import QBXTargetAssociationFailedException rho_sym = sym.var("rho") try: fld_in_vol = bind( (qbx_tgt_tol, PointsTarget(fplot.points)), sym.make_obj_array([ sym.S(pde_op.kernel, rho_sym, k=sym.var("k"), qbx_forced_limit=None), sym.d_dx(3, sym.S(pde_op.kernel, rho_sym, k=sym.var("k"), qbx_forced_limit=None)), sym.d_dy(3, sym.S(pde_op.kernel, rho_sym, k=sym.var("k"), qbx_forced_limit=None)), sym.d_dz(3, sym.S(pde_op.kernel, rho_sym, k=sym.var("k"), qbx_forced_limit=None)), ]) )(queue, jt=jt, rho=rho, k=k) except QBXTargetAssociationFailedException as e: fplot.write_vtk_file( "failed-targets.vts", [ ("failed_targets", e.failed_target_flags.get(queue)) ]) raise fld_in_vol = sym.make_obj_array( [fiv.get() for fiv in fld_in_vol]) #fplot.show_scalar_in_mayavi(fld_in_vol.real, max_val=5) fplot.write_vtk_file( "potential.vts", [ ("potential", fld_in_vol[0]), ("grad", fld_in_vol[1:]), ] )
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 test_sumpy_fmm(ctx_getter, knl, local_expn_class, mpole_expn_class): logging.basicConfig(level=logging.INFO) ctx = ctx_getter() queue = cl.CommandQueue(ctx) nsources = 1000 ntargets = 300 dtype = np.float64 from boxtree.tools import (make_normal_particle_array as p_normal) sources = p_normal(queue, nsources, knl.dim, dtype, seed=15) if 1: offset = np.zeros(knl.dim) offset[0] = 0.1 targets = (p_normal(queue, ntargets, knl.dim, dtype, seed=18) + offset) del offset else: from sumpy.visualization import FieldPlotter fp = FieldPlotter(np.array([0.5, 0]), extent=3, npoints=200) from pytools.obj_array import make_obj_array targets = make_obj_array([fp.points[i] for i in range(knl.dim)]) from boxtree import TreeBuilder tb = TreeBuilder(ctx) tree, _ = tb(queue, sources, targets=targets, max_particles_in_box=30, debug=True) from boxtree.traversal import FMMTraversalBuilder tbuild = FMMTraversalBuilder(ctx) trav, _ = tbuild(queue, tree, debug=True) # {{{ plot tree if 0: host_tree = tree.get() host_trav = trav.get() if 1: print("src_box", host_tree.find_box_nr_for_source(403)) print("tgt_box", host_tree.find_box_nr_for_target(28)) print(list(host_trav.target_or_target_parent_boxes).index(37)) print(host_trav.get_box_list("sep_bigger", 22)) from boxtree.visualization import TreePlotter plotter = TreePlotter(host_tree) plotter.draw_tree(fill=False, edgecolor="black", zorder=10) plotter.set_bounding_box() plotter.draw_box_numbers() import matplotlib.pyplot as pt pt.show() # }}} from pyopencl.clrandom import PhiloxGenerator rng = PhiloxGenerator(ctx, seed=44) weights = rng.uniform(queue, nsources, dtype=np.float64) logger.info("computing direct (reference) result") from pytools.convergence import PConvergenceVerifier pconv_verifier = PConvergenceVerifier() extra_kwargs = {} dtype = np.float64 order_values = [1, 2, 3] if isinstance(knl, HelmholtzKernel): extra_kwargs["k"] = 0.05 dtype = np.complex128 if knl.dim == 3: order_values = [1, 2] elif knl.dim == 2 and issubclass(local_expn_class, H2DLocalExpansion): order_values = [10, 12] elif isinstance(knl, YukawaKernel): extra_kwargs["lam"] = 2 dtype = np.complex128 if knl.dim == 3: order_values = [1, 2] elif knl.dim == 2 and issubclass(local_expn_class, Y2DLocalExpansion): order_values = [10, 12] from functools import partial for order in order_values: out_kernels = [knl] from sumpy.fmm import SumpyExpansionWranglerCodeContainer wcc = SumpyExpansionWranglerCodeContainer( ctx, partial(mpole_expn_class, knl), partial(local_expn_class, knl), out_kernels) wrangler = wcc.get_wrangler( queue, tree, dtype, fmm_level_to_order=lambda kernel, kernel_args, tree, lev: order, kernel_extra_kwargs=extra_kwargs) from boxtree.fmm import drive_fmm pot, = drive_fmm(trav, wrangler, weights) from sumpy import P2P p2p = P2P(ctx, out_kernels, exclude_self=False) evt, (ref_pot, ) = p2p(queue, targets, sources, (weights, ), **extra_kwargs) pot = pot.get() ref_pot = ref_pot.get() rel_err = la.norm(pot - ref_pot, np.inf) / la.norm(ref_pot, np.inf) logger.info("order %d -> relative l2 error: %g" % (order, rel_err)) pconv_verifier.add_data_point(order, rel_err) print(pconv_verifier) pconv_verifier()
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 test_translations(ctx_factory, knl, local_expn_class, mpole_expn_class): logging.basicConfig(level=logging.INFO) from sympy.core.cache import clear_cache clear_cache() ctx = ctx_factory() queue = cl.CommandQueue(ctx) np.random.seed(17) res = 20 nsources = 15 out_kernels = [knl] extra_kwargs = {} if isinstance(knl, HelmholtzKernel): extra_kwargs["k"] = 0.05 if isinstance(knl, StokesletKernel): extra_kwargs["mu"] = 0.05 # Just to make sure things also work away from the origin origin = np.array([2, 1, 0][:knl.dim], np.float64) sources = (0.7 * (-0.5 + np.random.rand(knl.dim, nsources).astype(np.float64)) + origin[:, np.newaxis]) strengths = np.ones(nsources, dtype=np.float64) * (1 / nsources) pconv_verifier_p2m2p = PConvergenceVerifier() pconv_verifier_p2m2m2p = PConvergenceVerifier() pconv_verifier_p2m2m2l2p = PConvergenceVerifier() pconv_verifier_full = PConvergenceVerifier() from sumpy.visualization import FieldPlotter eval_offset = np.array([5.5, 0.0, 0][:knl.dim]) centers = ( np.array( [ # box 0: particles, first mpole here [0, 0, 0][:knl.dim], # box 1: second mpole here np.array([-0.2, 0.1, 0][:knl.dim], np.float64), # box 2: first local here eval_offset + np.array([0.3, -0.2, 0][:knl.dim], np.float64), # box 3: second local and eval here eval_offset ], dtype=np.float64) + origin).T.copy() del eval_offset from sumpy.expansion import VolumeTaylorExpansionBase if isinstance(knl, HelmholtzKernel) and \ issubclass(local_expn_class, VolumeTaylorExpansionBase): # FIXME: Embarrassing--but we run out of memory for higher orders. orders = [2, 3] else: orders = [2, 3, 4] nboxes = centers.shape[-1] def eval_at(e2p, source_box_nr, rscale): e2p_target_boxes = np.array([source_box_nr], dtype=np.int32) # These are indexed by global box numbers. e2p_box_target_starts = np.array([0, 0, 0, 0], dtype=np.int32) e2p_box_target_counts_nonchild = np.array([0, 0, 0, 0], dtype=np.int32) e2p_box_target_counts_nonchild[source_box_nr] = ntargets evt, (pot, ) = e2p( queue, src_expansions=mpoles, src_base_ibox=0, target_boxes=e2p_target_boxes, box_target_starts=e2p_box_target_starts, box_target_counts_nonchild=e2p_box_target_counts_nonchild, centers=centers, targets=targets, rscale=rscale, out_host=True, **extra_kwargs) return pot for order in orders: m_expn = mpole_expn_class(knl, order=order) l_expn = local_expn_class(knl, order=order) from sumpy import P2EFromSingleBox, E2PFromSingleBox, P2P, E2EFromCSR p2m = P2EFromSingleBox(ctx, m_expn) m2m = E2EFromCSR(ctx, m_expn, m_expn) m2p = E2PFromSingleBox(ctx, m_expn, out_kernels) m2l = E2EFromCSR(ctx, m_expn, l_expn) l2l = E2EFromCSR(ctx, l_expn, l_expn) l2p = E2PFromSingleBox(ctx, l_expn, out_kernels) p2p = P2P(ctx, out_kernels, exclude_self=False) fp = FieldPlotter(centers[:, -1], extent=0.3, npoints=res) targets = fp.points # {{{ compute (direct) reference solution evt, (pot_direct, ) = p2p(queue, targets, sources, (strengths, ), out_host=True, **extra_kwargs) # }}} m1_rscale = 0.5 m2_rscale = 0.25 l1_rscale = 0.5 l2_rscale = 0.25 # {{{ apply P2M p2m_source_boxes = np.array([0], dtype=np.int32) # These are indexed by global box numbers. p2m_box_source_starts = np.array([0, 0, 0, 0], dtype=np.int32) p2m_box_source_counts_nonchild = np.array([nsources, 0, 0, 0], dtype=np.int32) evt, (mpoles, ) = p2m( queue, source_boxes=p2m_source_boxes, box_source_starts=p2m_box_source_starts, box_source_counts_nonchild=p2m_box_source_counts_nonchild, centers=centers, sources=sources, strengths=(strengths, ), nboxes=nboxes, rscale=m1_rscale, tgt_base_ibox=0, #flags="print_hl_wrapper", out_host=True, **extra_kwargs) # }}} ntargets = targets.shape[-1] pot = eval_at(m2p, 0, m1_rscale) err = la.norm((pot - pot_direct) / res**2) err = err / (la.norm(pot_direct) / res**2) pconv_verifier_p2m2p.add_data_point(order, err) # {{{ apply M2M m2m_target_boxes = np.array([1], dtype=np.int32) m2m_src_box_starts = np.array([0, 1], dtype=np.int32) m2m_src_box_lists = np.array([0], dtype=np.int32) evt, (mpoles, ) = m2m( queue, src_expansions=mpoles, src_base_ibox=0, tgt_base_ibox=0, ntgt_level_boxes=mpoles.shape[0], target_boxes=m2m_target_boxes, src_box_starts=m2m_src_box_starts, src_box_lists=m2m_src_box_lists, centers=centers, src_rscale=m1_rscale, tgt_rscale=m2_rscale, #flags="print_hl_cl", out_host=True, **extra_kwargs) # }}} pot = eval_at(m2p, 1, m2_rscale) err = la.norm((pot - pot_direct) / res**2) err = err / (la.norm(pot_direct) / res**2) pconv_verifier_p2m2m2p.add_data_point(order, err) # {{{ apply M2L m2l_target_boxes = np.array([2], dtype=np.int32) m2l_src_box_starts = np.array([0, 1], dtype=np.int32) m2l_src_box_lists = np.array([1], dtype=np.int32) evt, (mpoles, ) = m2l( queue, src_expansions=mpoles, src_base_ibox=0, tgt_base_ibox=0, ntgt_level_boxes=mpoles.shape[0], target_boxes=m2l_target_boxes, src_box_starts=m2l_src_box_starts, src_box_lists=m2l_src_box_lists, centers=centers, src_rscale=m2_rscale, tgt_rscale=l1_rscale, #flags="print_hl_cl", out_host=True, **extra_kwargs) # }}} pot = eval_at(l2p, 2, l1_rscale) err = la.norm((pot - pot_direct) / res**2) err = err / (la.norm(pot_direct) / res**2) pconv_verifier_p2m2m2l2p.add_data_point(order, err) # {{{ apply L2L l2l_target_boxes = np.array([3], dtype=np.int32) l2l_src_box_starts = np.array([0, 1], dtype=np.int32) l2l_src_box_lists = np.array([2], dtype=np.int32) evt, (mpoles, ) = l2l( queue, src_expansions=mpoles, src_base_ibox=0, tgt_base_ibox=0, ntgt_level_boxes=mpoles.shape[0], target_boxes=l2l_target_boxes, src_box_starts=l2l_src_box_starts, src_box_lists=l2l_src_box_lists, centers=centers, src_rscale=l1_rscale, tgt_rscale=l2_rscale, #flags="print_hl_wrapper", out_host=True, **extra_kwargs) # }}} pot = eval_at(l2p, 3, l2_rscale) err = la.norm((pot - pot_direct) / res**2) err = err / (la.norm(pot_direct) / res**2) pconv_verifier_full.add_data_point(order, err) for name, verifier in [ ("p2m2p", pconv_verifier_p2m2p), ("p2m2m2p", pconv_verifier_p2m2m2p), ("p2m2m2l2p", pconv_verifier_p2m2m2l2p), ("full", pconv_verifier_full), ]: print(30 * "-") print(name) print(30 * "-") print(verifier) print(30 * "-") verifier()
def run_dielectric_test(cl_ctx, queue, nelements, qbx_order, op_class, mode, k0=3, k1=2.9, mesh_order=10, bdry_quad_order=None, bdry_ovsmp_quad_order=None, use_l2_weighting=False, fmm_order=None, visualize=False): if fmm_order is None: fmm_order = qbx_order * 2 if bdry_quad_order is None: bdry_quad_order = mesh_order if bdry_ovsmp_quad_order is None: bdry_ovsmp_quad_order = 4 * bdry_quad_order from meshmode.mesh.generation import ellipse, make_curve_mesh from functools import partial mesh = make_curve_mesh(partial(ellipse, 3), np.linspace(0, 1, nelements + 1), mesh_order) density_discr = Discretization( cl_ctx, mesh, InterpolatoryQuadratureSimplexGroupFactory(bdry_quad_order)) logger.info("%d elements" % mesh.nelements) # from meshmode.discretization.visualization import make_visualizer # bdry_vis = make_visualizer(queue, density_discr, 20) # {{{ solve bvp from sumpy.kernel import HelmholtzKernel, AxisTargetDerivative kernel = HelmholtzKernel(2) beta = 2.5 K0 = np.sqrt(k0**2 - beta**2) # noqa K1 = np.sqrt(k1**2 - beta**2) # noqa pde_op = op_class(mode, k_vacuum=1, interfaces=((0, 1, sym.DEFAULT_SOURCE), ), domain_k_exprs=(k0, k1), beta=beta, use_l2_weighting=use_l2_weighting) op_unknown_sym = pde_op.make_unknown("unknown") representation0_sym = pde_op.representation(op_unknown_sym, 0) representation1_sym = pde_op.representation(op_unknown_sym, 1) from pytential.qbx import QBXLayerPotentialSource qbx = QBXLayerPotentialSource(density_discr, fine_order=bdry_ovsmp_quad_order, qbx_order=qbx_order, fmm_order=fmm_order).with_refinement() #print(sym.pretty(pde_op.operator(op_unknown_sym))) #1/0 bound_pde_op = bind(qbx, pde_op.operator(op_unknown_sym)) e_factor = float(pde_op.ez_enabled) h_factor = float(pde_op.hz_enabled) e_sources_0 = make_obj_array(list(np.array([[0.1, 0.2]]).T.copy())) e_strengths_0 = np.array([1 * e_factor]) e_sources_1 = make_obj_array(list(np.array([[4, 4]]).T.copy())) e_strengths_1 = np.array([1 * e_factor]) h_sources_0 = make_obj_array(list(np.array([[0.2, 0.1]]).T.copy())) h_strengths_0 = np.array([1 * h_factor]) h_sources_1 = make_obj_array(list(np.array([[4, 5]]).T.copy())) h_strengths_1 = np.array([1 * h_factor]) kernel_grad = [ AxisTargetDerivative(i, kernel) for i in range(density_discr.ambient_dim) ] from sumpy.p2p import P2P pot_p2p = P2P(cl_ctx, [kernel], exclude_self=False) pot_p2p_grad = P2P(cl_ctx, kernel_grad, exclude_self=False) normal = bind(density_discr, sym.normal())(queue).as_vector(np.object) tangent = bind(density_discr, sym.pseudoscalar() / sym.area_element())(queue).as_vector( np.object) _, (E0, ) = pot_p2p(queue, density_discr.nodes(), e_sources_0, [e_strengths_0], out_host=False, k=K0) _, (E1, ) = pot_p2p(queue, density_discr.nodes(), e_sources_1, [e_strengths_1], out_host=False, k=K1) _, (grad0_E0, grad1_E0) = pot_p2p_grad(queue, density_discr.nodes(), e_sources_0, [e_strengths_0], out_host=False, k=K0) _, (grad0_E1, grad1_E1) = pot_p2p_grad(queue, density_discr.nodes(), e_sources_1, [e_strengths_1], out_host=False, k=K1) _, (H0, ) = pot_p2p(queue, density_discr.nodes(), h_sources_0, [h_strengths_0], out_host=False, k=K0) _, (H1, ) = pot_p2p(queue, density_discr.nodes(), h_sources_1, [h_strengths_1], out_host=False, k=K1) _, (grad0_H0, grad1_H0) = pot_p2p_grad(queue, density_discr.nodes(), h_sources_0, [h_strengths_0], out_host=False, k=K0) _, (grad0_H1, grad1_H1) = pot_p2p_grad(queue, density_discr.nodes(), h_sources_1, [h_strengths_1], out_host=False, k=K1) E0_dntarget = (grad0_E0 * normal[0] + grad1_E0 * normal[1]) # noqa E1_dntarget = (grad0_E1 * normal[0] + grad1_E1 * normal[1]) # noqa H0_dntarget = (grad0_H0 * normal[0] + grad1_H0 * normal[1]) # noqa H1_dntarget = (grad0_H1 * normal[0] + grad1_H1 * normal[1]) # noqa E0_dttarget = (grad0_E0 * tangent[0] + grad1_E0 * tangent[1]) # noqa E1_dttarget = (grad0_E1 * tangent[0] + grad1_E1 * tangent[1]) # noqa H0_dttarget = (grad0_H0 * tangent[0] + grad1_H0 * tangent[1]) # noqa H1_dttarget = (grad0_H1 * tangent[0] + grad1_H1 * tangent[1]) # noqa sqrt_w = bind(density_discr, sym.sqrt_jac_q_weight())(queue) bvp_rhs = np.zeros(len(pde_op.bcs), dtype=np.object) for i_bc, terms in enumerate(pde_op.bcs): for term in terms: assert term.i_interface == 0 if term.field_kind == pde_op.field_kind_e: if term.direction == pde_op.dir_none: bvp_rhs[i_bc] += (term.coeff_outer * E0 + term.coeff_inner * E1) elif term.direction == pde_op.dir_normal: bvp_rhs[i_bc] += (term.coeff_outer * E0_dntarget + term.coeff_inner * E1_dntarget) elif term.direction == pde_op.dir_tangential: bvp_rhs[i_bc] += (term.coeff_outer * E0_dttarget + term.coeff_inner * E1_dttarget) else: raise NotImplementedError("direction spec in RHS") elif term.field_kind == pde_op.field_kind_h: if term.direction == pde_op.dir_none: bvp_rhs[i_bc] += (term.coeff_outer * H0 + term.coeff_inner * H1) elif term.direction == pde_op.dir_normal: bvp_rhs[i_bc] += (term.coeff_outer * H0_dntarget + term.coeff_inner * H1_dntarget) elif term.direction == pde_op.dir_tangential: bvp_rhs[i_bc] += (term.coeff_outer * H0_dttarget + term.coeff_inner * H1_dttarget) else: raise NotImplementedError("direction spec in RHS") if use_l2_weighting: bvp_rhs[i_bc] *= sqrt_w scipy_op = bound_pde_op.scipy_op(queue, "unknown", domains=[sym.DEFAULT_TARGET] * len(pde_op.bcs), K0=K0, K1=K1, dtype=np.complex128) if mode == "tem" or op_class is SRep: from sumpy.tools import vector_from_device, vector_to_device from pytential.solve import lu unknown = lu(scipy_op, vector_from_device(queue, bvp_rhs)) unknown = vector_to_device(queue, unknown) else: from pytential.solve import gmres gmres_result = gmres(scipy_op, bvp_rhs, tol=1e-14, progress=True, hard_failure=True, stall_iterations=0) unknown = gmres_result.solution # }}} targets_0 = make_obj_array( list(np.array([[3.2 + t, -4] for t in [0, 0.5, 1]]).T.copy())) targets_1 = make_obj_array( list(np.array([[t * -0.3, t * -0.2] for t in [0, 0.5, 1]]).T.copy())) from pytential.target import PointsTarget from sumpy.tools import vector_from_device F0_tgt = vector_from_device( queue, bind( # noqa (qbx, PointsTarget(targets_0)), representation0_sym)(queue, unknown=unknown, K0=K0, K1=K1)) F1_tgt = vector_from_device( queue, bind( # noqa (qbx, PointsTarget(targets_1)), representation1_sym)(queue, unknown=unknown, K0=K0, K1=K1)) _, (E0_tgt_true, ) = pot_p2p(queue, targets_0, e_sources_0, [e_strengths_0], out_host=True, k=K0) _, (E1_tgt_true, ) = pot_p2p(queue, targets_1, e_sources_1, [e_strengths_1], out_host=True, k=K1) _, (H0_tgt_true, ) = pot_p2p(queue, targets_0, h_sources_0, [h_strengths_0], out_host=True, k=K0) _, (H1_tgt_true, ) = pot_p2p(queue, targets_1, h_sources_1, [h_strengths_1], out_host=True, k=K1) err_F0_total = 0 # noqa err_F1_total = 0 # noqa i_field = 0 def vec_norm(ary): return la.norm(ary.reshape(-1)) def field_kind_to_string(field_kind): return {pde_op.field_kind_e: "E", pde_op.field_kind_h: "H"}[field_kind] for field_kind in pde_op.field_kinds: if not pde_op.is_field_present(field_kind): continue if field_kind == pde_op.field_kind_e: F0_tgt_true = E0_tgt_true # noqa F1_tgt_true = E1_tgt_true # noqa elif field_kind == pde_op.field_kind_h: F0_tgt_true = H0_tgt_true # noqa F1_tgt_true = H1_tgt_true # noqa else: assert False abs_err_F0 = vec_norm(F0_tgt[i_field] - F0_tgt_true) # noqa abs_err_F1 = vec_norm(F1_tgt[i_field] - F1_tgt_true) # noqa rel_err_F0 = abs_err_F0 / vec_norm(F0_tgt_true) # noqa rel_err_F1 = abs_err_F1 / vec_norm(F1_tgt_true) # noqa err_F0_total = max(rel_err_F0, err_F0_total) # noqa err_F1_total = max(rel_err_F1, err_F1_total) # noqa print("Abs Err %s0" % field_kind_to_string(field_kind), abs_err_F0) print("Abs Err %s1" % field_kind_to_string(field_kind), abs_err_F1) print("Rel Err %s0" % field_kind_to_string(field_kind), rel_err_F0) print("Rel Err %s1" % field_kind_to_string(field_kind), rel_err_F1) i_field += 1 if visualize: from sumpy.visualization import FieldPlotter fplot = FieldPlotter(np.zeros(2), extent=5, npoints=300) from pytential.target import PointsTarget fld0 = bind((qbx, PointsTarget(fplot.points)), representation0_sym)(queue, unknown=unknown, K0=K0) fld1 = bind((qbx, PointsTarget(fplot.points)), representation1_sym)(queue, unknown=unknown, K1=K1) comp_fields = [] i_field = 0 for field_kind in pde_op.field_kinds: if not pde_op.is_field_present(field_kind): continue fld_str = field_kind_to_string(field_kind) comp_fields.extend([ ("%s_fld0" % fld_str, fld0[i_field].get()), ("%s_fld1" % fld_str, fld1[i_field].get()), ]) i_field += 0 low_order_qbx = QBXLayerPotentialSource( density_discr, fine_order=bdry_ovsmp_quad_order, qbx_order=2, fmm_order=3).with_refinement() from sumpy.kernel import LaplaceKernel from pytential.target import PointsTarget ones = (cl.array.empty(queue, (density_discr.nnodes, ), dtype=np.float64).fill(1)) ind_func = -bind( (low_order_qbx, PointsTarget(fplot.points)), sym.D(LaplaceKernel(2), sym.var("u")))(queue, u=ones).get() _, (e_fld0_true, ) = pot_p2p(queue, fplot.points, e_sources_0, [e_strengths_0], out_host=True, k=K0) _, (e_fld1_true, ) = pot_p2p(queue, fplot.points, e_sources_1, [e_strengths_1], out_host=True, k=K1) _, (h_fld0_true, ) = pot_p2p(queue, fplot.points, h_sources_0, [h_strengths_0], out_host=True, k=K0) _, (h_fld1_true, ) = pot_p2p(queue, fplot.points, h_sources_1, [h_strengths_1], out_host=True, k=K1) #fplot.show_scalar_in_mayavi(fld_in_vol.real, max_val=5) fplot.write_vtk_file("potential-n%d.vts" % nelements, [ ("e_fld0_true", e_fld0_true), ("e_fld1_true", e_fld1_true), ("h_fld0_true", h_fld0_true), ("h_fld1_true", h_fld1_true), ("ind", ind_func), ] + comp_fields) return err_F0_total, err_F1_total
def main(mesh_name="ellipse", visualize=False): import logging logging.basicConfig(level=logging.INFO) # INFO for more progress info cl_ctx = cl.create_some_context() queue = cl.CommandQueue(cl_ctx) actx = PyOpenCLArrayContext(queue) from meshmode.mesh.generation import ellipse, make_curve_mesh from functools import partial if mesh_name == "ellipse": mesh = make_curve_mesh(partial(ellipse, 1), np.linspace(0, 1, nelements + 1), mesh_order) elif mesh_name == "ellipse_array": base_mesh = make_curve_mesh(partial(ellipse, 1), np.linspace(0, 1, nelements + 1), mesh_order) from meshmode.mesh.processing import affine_map, merge_disjoint_meshes nx = 2 ny = 2 dx = 2 / nx meshes = [ affine_map(base_mesh, A=np.diag([dx * 0.25, dx * 0.25]), b=np.array([dx * (ix - nx / 2), dx * (iy - ny / 2)])) for ix in range(nx) for iy in range(ny) ] mesh = merge_disjoint_meshes(meshes, single_group=True) if visualize: from meshmode.mesh.visualization import draw_curve draw_curve(mesh) import matplotlib.pyplot as plt plt.show() else: raise ValueError(f"unknown mesh name: {mesh_name}") pre_density_discr = Discretization( actx, mesh, InterpolatoryQuadratureSimplexGroupFactory(bdry_quad_order)) from pytential.qbx import (QBXLayerPotentialSource, QBXTargetAssociationFailedException) qbx = QBXLayerPotentialSource(pre_density_discr, fine_order=bdry_ovsmp_quad_order, qbx_order=qbx_order, fmm_order=fmm_order) from sumpy.visualization import FieldPlotter fplot = FieldPlotter(np.zeros(2), extent=5, npoints=500) targets = actx.from_numpy(fplot.points) from pytential import GeometryCollection places = GeometryCollection( { "qbx": qbx, "qbx_high_target_assoc_tol": qbx.copy(target_association_tolerance=0.05), "targets": PointsTarget(targets) }, auto_where="qbx") density_discr = places.get_discretization("qbx") # {{{ describe bvp from sumpy.kernel import LaplaceKernel, HelmholtzKernel kernel = HelmholtzKernel(2) sigma_sym = sym.var("sigma") sqrt_w = sym.sqrt_jac_q_weight(2) inv_sqrt_w_sigma = sym.cse(sigma_sym / sqrt_w) # Brakhage-Werner parameter alpha = 1j # -1 for interior Dirichlet # +1 for exterior Dirichlet loc_sign = +1 k_sym = sym.var("k") bdry_op_sym = ( -loc_sign * 0.5 * sigma_sym + sqrt_w * (alpha * sym.S(kernel, inv_sqrt_w_sigma, k=k_sym, qbx_forced_limit=+1) - sym.D(kernel, inv_sqrt_w_sigma, k=k_sym, qbx_forced_limit="avg"))) # }}} bound_op = bind(places, bdry_op_sym) # {{{ fix rhs and solve from meshmode.dof_array import thaw nodes = thaw(actx, density_discr.nodes()) k_vec = np.array([2, 1]) k_vec = k * k_vec / la.norm(k_vec, 2) def u_incoming_func(x): return actx.np.exp(1j * (x[0] * k_vec[0] + x[1] * k_vec[1])) bc = -u_incoming_func(nodes) bvp_rhs = bind(places, sqrt_w * sym.var("bc"))(actx, bc=bc) from pytential.solve import gmres gmres_result = gmres(bound_op.scipy_op(actx, sigma_sym.name, dtype=np.complex128, k=k), bvp_rhs, tol=1e-8, progress=True, stall_iterations=0, hard_failure=True) # }}} # {{{ postprocess/visualize repr_kwargs = dict(source="qbx_high_target_assoc_tol", target="targets", qbx_forced_limit=None) representation_sym = ( alpha * sym.S(kernel, inv_sqrt_w_sigma, k=k_sym, **repr_kwargs) - sym.D(kernel, inv_sqrt_w_sigma, k=k_sym, **repr_kwargs)) u_incoming = u_incoming_func(targets) ones_density = density_discr.zeros(actx) for elem in ones_density: elem.fill(1) indicator = actx.to_numpy( bind(places, sym.D(LaplaceKernel(2), sigma_sym, **repr_kwargs))(actx, sigma=ones_density)) try: fld_in_vol = actx.to_numpy( bind(places, representation_sym)(actx, sigma=gmres_result.solution, k=k)) except QBXTargetAssociationFailedException as e: fplot.write_vtk_file("helmholtz-dirichlet-failed-targets.vts", [("failed", e.failed_target_flags.get(queue))]) raise #fplot.show_scalar_in_mayavi(fld_in_vol.real, max_val=5) fplot.write_vtk_file("helmholtz-dirichlet-potential.vts", [ ("potential", fld_in_vol), ("indicator", indicator), ("u_incoming", actx.to_numpy(u_incoming)), ])
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 main(): import logging logger = logging.getLogger(__name__) logging.basicConfig(level=logging.WARNING) # INFO for more progress info from meshmode.mesh.io import generate_gmsh, FileSource mesh = generate_gmsh( FileSource(cad_file_name), 2, order=2, other_options=["-string", "Mesh.CharacteristicLengthMax = %g;" % h]) from meshmode.mesh.processing import perform_flips # Flip elements--gmsh generates inside-out geometry. mesh = perform_flips(mesh, np.ones(mesh.nelements)) from meshmode.mesh.processing import find_bounding_box bbox_min, bbox_max = find_bounding_box(mesh) bbox_center = 0.5*(bbox_min+bbox_max) bbox_size = max(bbox_max-bbox_min) / 2 logger.info("%d elements" % mesh.nelements) 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)) qbx, _ = QBXLayerPotentialSource(density_discr, 4*target_order, qbx_order, fmm_order=qbx_order + 3, target_association_tolerance=0.15).with_refinement() nodes = density_discr.nodes().with_queue(queue) angle = cl.clmath.atan2(nodes[1], nodes[0]) from pytential import bind, sym #op = sym.d_dx(sym.S(kernel, sym.var("sigma"), qbx_forced_limit=None)) op = sym.D(kernel, sym.var("sigma"), qbx_forced_limit=None) #op = sym.S(kernel, sym.var("sigma"), qbx_forced_limit=None) 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) fplot = FieldPlotter(bbox_center, extent=3.5*bbox_size, npoints=150) from pytential.target import PointsTarget fld_in_vol = bind( (qbx, PointsTarget(fplot.points)), op)(queue, sigma=sigma, k=k).get() #fplot.show_scalar_in_mayavi(fld_in_vol.real, max_val=5) fplot.write_vtk_file( "potential-3d.vts", [ ("potential", fld_in_vol) ] ) bdry_normals = bind( density_discr, sym.normal(density_discr.ambient_dim))(queue).as_vector(dtype=object) from meshmode.discretization.visualization import make_visualizer bdry_vis = make_visualizer(queue, density_discr, target_order) bdry_vis.write_vtk_file("source-3d.vtu", [ ("sigma", sigma), ("bdry_normals", bdry_normals), ])
def test_single_plus_double_with_single_fmm(actx_factory, do_plot=False): logging.basicConfig(level=logging.INFO) actx = actx_factory() # prevent cache 'splosion from sympy.core.cache import clear_cache clear_cache() nelements = 300 target_order = 8 qbx_order = 3 mesh = mgen.make_curve_mesh(mgen.WobblyCircle.random(8, seed=30), 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)) direct_qbx = QBXLayerPotentialSource( pre_density_discr, 4 * target_order, qbx_order, fmm_order=False, target_association_tolerance=0.05, ) fmm_qbx = QBXLayerPotentialSource( pre_density_discr, 4 * target_order, qbx_order, fmm_order=qbx_order + 3, _expansions_in_tree_have_extent=True, target_association_tolerance=0.05, ) fplot = FieldPlotter(np.zeros(2), extent=5, npoints=500) from pytential.target import PointsTarget ptarget = PointsTarget(actx.freeze(actx.from_numpy(fplot.points))) from sumpy.kernel import LaplaceKernel places = GeometryCollection( { "direct_qbx": direct_qbx, "fmm_qbx": fmm_qbx, "target": ptarget, }, auto_where=("fmm_qbx", "target")) direct_density_discr = places.get_discretization("direct_qbx") fmm_density_discr = places.get_discretization("fmm_qbx") knl = LaplaceKernel(2) from pytential.qbx import QBXTargetAssociationFailedException op_d = sym.D(knl, sym.var("sigma"), qbx_forced_limit=None) op_s = sym.S(knl, sym.var("sigma"), qbx_forced_limit=None) op = op_d + op_s * 0.5 try: direct_sigma = direct_density_discr.zeros(actx) + 1 direct_fld_in_vol = bind(places, op, auto_where=("direct_qbx", "target"))(actx, sigma=direct_sigma) except QBXTargetAssociationFailedException as e: fplot.show_scalar_in_matplotlib( actx.to_numpy(actx.thaw(e.failed_target_flags))) import matplotlib.pyplot as pt pt.show() raise fmm_sigma = fmm_density_discr.zeros(actx) + 1 fmm_bound_op = bind(places, op, auto_where=("fmm_qbx", "target")) print(fmm_bound_op.code) fmm_fld_in_vol = fmm_bound_op(actx, sigma=fmm_sigma) err = actx.np.fabs(fmm_fld_in_vol - direct_fld_in_vol) linf_err = actx.to_numpy(err).max() print("l_inf error:", linf_err) if do_plot: fplot.write_vtk_file( "potential.vts", [("fmm_fld_in_vol", actx.to_numpy(fmm_fld_in_vol)), ("direct_fld_in_vol", actx.to_numpy(direct_fld_in_vol))]) assert linf_err < 1e-3 # check that using one FMM works op = op_d.copy(source_kernels=op_d.source_kernels + (knl, ), densities=op_d.densities + (sym.var("sigma") * 0.5, )) single_fmm_bound_op = bind(places, op, auto_where=("fmm_qbx", "target")) print(single_fmm_bound_op.code) single_fmm_fld_in_vol = fmm_bound_op(actx, sigma=fmm_sigma) err = actx.np.fabs(fmm_fld_in_vol - single_fmm_fld_in_vol) linf_err = actx.to_numpy(err).max() print("l_inf error:", linf_err) assert linf_err < 1e-15