# plane wave return bind( tgt, get_sym_maxwell_plane_wave(amplitude_vec=np.array([1, 1, 1]), v=np.array([1, 0, 0]), omega=case.k))(queue) else: # point source return bind((test_source, tgt), get_sym_maxwell_point_source(mfie.kernel, j_sym, mfie.k))(queue, j=src_j, k=case.k) pde_test_inc = EHField( vector_from_device(queue, eval_inc_field_at(calc_patch_tgt))) source_maxwell_resids = [ calc_patch.norm(x, np.inf) / calc_patch.norm(pde_test_inc.e, np.inf) for x in frequency_domain_maxwell(calc_patch, pde_test_inc.e, pde_test_inc.h, case.k) ] print("Source Maxwell residuals:", source_maxwell_resids) assert max(source_maxwell_resids) < 1e-6 # }}} loc_sign = -1 if case.is_interior else +1 from pytools.convergence import EOCRecorder
places.update({ "qbx_target_tol": qbx_tgt_tol, "plot_targets": fplot_tgt, }) from pytential import GeometryCollection places = GeometryCollection(places) density_discr = places.get_discretization(places.auto_source.geometry) # {{{ system solve h_max = bind(places, sym.h_max(qbx.ambient_dim))(actx) pde_test_inc = EHField( vector_from_device( actx.queue, eval_inc_field_at(places, target="patch_target"))) source_maxwell_resids = [ calc_patch.norm(x, np.inf) / calc_patch.norm(pde_test_inc.e, np.inf) for x in frequency_domain_maxwell(calc_patch, pde_test_inc.e, pde_test_inc.h, case.k) ] print("Source Maxwell residuals:", source_maxwell_resids) assert max(source_maxwell_resids) < 1e-6 inc_field_scat = EHField(eval_inc_field_at(places, target="scat_discr")) inc_field_obs = EHField(eval_inc_field_at(places, target="obs_discr")) inc_xyz_sym = EHField(sym.make_sym_vector("inc_fld", 6))
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 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_matrix_build(ctx_factory, k, curve_f, lpot_id, visualize=False): cl_ctx = ctx_factory() queue = cl.CommandQueue(cl_ctx) # prevent cache 'splosion from sympy.core.cache import clear_cache clear_cache() target_order = 7 qbx_order = 4 nelements = 30 mesh = make_curve_mesh(curve_f, np.linspace(0, 1, nelements + 1), target_order) from meshmode.discretization import Discretization from meshmode.discretization.poly_element import \ InterpolatoryQuadratureSimplexGroupFactory pre_density_discr = Discretization( cl_ctx, mesh, InterpolatoryQuadratureSimplexGroupFactory(target_order)) from pytential.qbx import QBXLayerPotentialSource qbx, _ = QBXLayerPotentialSource(pre_density_discr, 4 * target_order, qbx_order, # Don't use FMM for now fmm_order=False).with_refinement() density_discr = qbx.density_discr op, u_sym, knl_kwargs = _build_op(lpot_id, k=k) bound_op = bind(qbx, op) from pytential.symbolic.execution import build_matrix mat = build_matrix(queue, qbx, op, u_sym).get() if visualize: from sumpy.tools import build_matrix as build_matrix_via_matvec mat2 = bound_op.scipy_op(queue, "u", dtype=mat.dtype, **knl_kwargs) mat2 = build_matrix_via_matvec(mat2) print(la.norm((mat - mat2).real, "fro") / la.norm(mat2.real, "fro"), la.norm((mat - mat2).imag, "fro") / la.norm(mat2.imag, "fro")) import matplotlib.pyplot as pt pt.subplot(121) pt.imshow(np.log10(np.abs(1.0e-20 + (mat - mat2).real))) pt.colorbar() pt.subplot(122) pt.imshow(np.log10(np.abs(1.0e-20 + (mat - mat2).imag))) pt.colorbar() pt.show() if visualize: import matplotlib.pyplot as pt pt.subplot(121) pt.imshow(mat.real) pt.colorbar() pt.subplot(122) pt.imshow(mat.imag) pt.colorbar() pt.show() from sumpy.tools import vector_to_device, vector_from_device np.random.seed(12) for i in range(5): if is_obj_array(u_sym): u = make_obj_array([ np.random.randn(density_discr.nnodes) for _ in range(len(u_sym)) ]) else: u = np.random.randn(density_discr.nnodes) u_dev = vector_to_device(queue, u) res_matvec = np.hstack( list(vector_from_device( queue, bound_op(queue, u=u_dev)))) res_mat = mat.dot(np.hstack(list(u))) abs_err = la.norm(res_mat - res_matvec, np.inf) rel_err = abs_err / la.norm(res_matvec, np.inf) print("AbsErr {:.5e} RelErr {:.5e}".format(abs_err, rel_err)) assert rel_err < 1e-13
def test_pec_mfie_extinction(ctx_getter, case, visualize=False): """For (say) is_interior=False (the 'exterior' MFIE), this test verifies extinction of the combined (incoming + scattered) field on the interior of the scatterer. """ logging.basicConfig(level=logging.INFO) cl_ctx = ctx_getter() queue = cl.CommandQueue(cl_ctx) np.random.seed(12) knl_kwargs = {"k": case.k} # {{{ come up with a solution to Maxwell's equations j_sym = sym.make_sym_vector("j", 3) jt_sym = sym.make_sym_vector("jt", 2) rho_sym = sym.var("rho") from pytential.symbolic.pde.maxwell import ( PECChargeCurrentMFIEOperator, get_sym_maxwell_point_source, get_sym_maxwell_plane_wave) mfie = PECChargeCurrentMFIEOperator() test_source = case.get_source(queue) calc_patch = CalculusPatch(np.array([-3, 0, 0]), h=0.01) calc_patch_tgt = PointsTarget(cl.array.to_device(queue, calc_patch.points)) rng = cl.clrandom.PhiloxGenerator(cl_ctx, seed=12) src_j = rng.normal(queue, (3, test_source.nnodes), dtype=np.float64) def eval_inc_field_at(tgt): if 0: # plane wave return bind( tgt, get_sym_maxwell_plane_wave( amplitude_vec=np.array([1, 1, 1]), v=np.array([1, 0, 0]), omega=case.k) )(queue) else: # point source return bind( (test_source, tgt), get_sym_maxwell_point_source(mfie.kernel, j_sym, mfie.k) )(queue, j=src_j, k=case.k) pde_test_inc = EHField( vector_from_device(queue, eval_inc_field_at(calc_patch_tgt))) source_maxwell_resids = [ calc_patch.norm(x, np.inf) / calc_patch.norm(pde_test_inc.e, np.inf) for x in frequency_domain_maxwell( calc_patch, pde_test_inc.e, pde_test_inc.h, case.k)] print("Source Maxwell residuals:", source_maxwell_resids) assert max(source_maxwell_resids) < 1e-6 # }}} loc_sign = -1 if case.is_interior else +1 from pytools.convergence import EOCRecorder eoc_rec_repr_maxwell = EOCRecorder() eoc_pec_bc = EOCRecorder() eoc_rec_e = EOCRecorder() eoc_rec_h = EOCRecorder() from pytential.qbx import QBXLayerPotentialSource from meshmode.discretization import Discretization from meshmode.discretization.poly_element import \ InterpolatoryQuadratureSimplexGroupFactory from sumpy.expansion.level_to_order import SimpleExpansionOrderFinder for resolution in case.resolutions: scat_mesh = case.get_mesh(resolution, case.target_order) observation_mesh = case.get_observation_mesh(case.target_order) pre_scat_discr = Discretization( cl_ctx, scat_mesh, InterpolatoryQuadratureSimplexGroupFactory(case.target_order)) qbx, _ = QBXLayerPotentialSource( pre_scat_discr, fine_order=4*case.target_order, qbx_order=case.qbx_order, fmm_level_to_order=SimpleExpansionOrderFinder( case.fmm_tolerance), fmm_backend=case.fmm_backend ).with_refinement(_expansion_disturbance_tolerance=0.05) h_max = qbx.h_max scat_discr = qbx.density_discr obs_discr = Discretization( cl_ctx, observation_mesh, InterpolatoryQuadratureSimplexGroupFactory(case.target_order)) inc_field_scat = EHField(eval_inc_field_at(scat_discr)) inc_field_obs = EHField(eval_inc_field_at(obs_discr)) # {{{ system solve inc_xyz_sym = EHField(sym.make_sym_vector("inc_fld", 6)) bound_j_op = bind(qbx, mfie.j_operator(loc_sign, jt_sym)) j_rhs = bind(qbx, mfie.j_rhs(inc_xyz_sym.h))( queue, inc_fld=inc_field_scat.field, **knl_kwargs) gmres_settings = dict( tol=case.gmres_tol, progress=True, hard_failure=True, stall_iterations=50, no_progress_factor=1.05) from pytential.solve import gmres gmres_result = gmres( bound_j_op.scipy_op(queue, "jt", np.complex128, **knl_kwargs), j_rhs, **gmres_settings) jt = gmres_result.solution bound_rho_op = bind(qbx, mfie.rho_operator(loc_sign, rho_sym)) rho_rhs = bind(qbx, mfie.rho_rhs(jt_sym, inc_xyz_sym.e))( queue, jt=jt, inc_fld=inc_field_scat.field, **knl_kwargs) gmres_result = gmres( bound_rho_op.scipy_op(queue, "rho", np.complex128, **knl_kwargs), rho_rhs, **gmres_settings) rho = gmres_result.solution # }}} jxyz = bind(qbx, sym.tangential_to_xyz(jt_sym))(queue, jt=jt) # {{{ volume eval sym_repr = mfie.scattered_volume_field(jt_sym, rho_sym) def eval_repr_at(tgt, source=None): if source is None: source = qbx return bind((source, tgt), sym_repr)(queue, jt=jt, rho=rho, **knl_kwargs) pde_test_repr = EHField( vector_from_device(queue, eval_repr_at(calc_patch_tgt))) maxwell_residuals = [ calc_patch.norm(x, np.inf) / calc_patch.norm(pde_test_repr.e, np.inf) for x in frequency_domain_maxwell( calc_patch, pde_test_repr.e, pde_test_repr.h, case.k)] print("Maxwell residuals:", maxwell_residuals) eoc_rec_repr_maxwell.add_data_point(h_max, max(maxwell_residuals)) # }}} # {{{ check PEC BC on total field bc_repr = EHField(mfie.scattered_volume_field( jt_sym, rho_sym, qbx_forced_limit=loc_sign)) pec_bc_e = sym.n_cross(bc_repr.e + inc_xyz_sym.e) pec_bc_h = sym.normal(3).as_vector().dot(bc_repr.h + inc_xyz_sym.h) eh_bc_values = bind(qbx, sym.join_fields(pec_bc_e, pec_bc_h))( queue, jt=jt, rho=rho, inc_fld=inc_field_scat.field, **knl_kwargs) def scat_norm(f): return norm(qbx, queue, f, p=np.inf) e_bc_residual = scat_norm(eh_bc_values[:3]) / scat_norm(inc_field_scat.e) h_bc_residual = scat_norm(eh_bc_values[3]) / scat_norm(inc_field_scat.h) print("E/H PEC BC residuals:", h_max, e_bc_residual, h_bc_residual) eoc_pec_bc.add_data_point(h_max, max(e_bc_residual, h_bc_residual)) # }}} # {{{ visualization if visualize: from meshmode.discretization.visualization import make_visualizer bdry_vis = make_visualizer(queue, scat_discr, case.target_order+3) bdry_normals = bind(scat_discr, sym.normal(3))(queue)\ .as_vector(dtype=object) bdry_vis.write_vtk_file("source-%s.vtu" % resolution, [ ("j", jxyz), ("rho", rho), ("Einc", inc_field_scat.e), ("Hinc", inc_field_scat.h), ("bdry_normals", bdry_normals), ("e_bc_residual", eh_bc_values[:3]), ("h_bc_residual", eh_bc_values[3]), ]) fplot = make_field_plotter_from_bbox( find_bounding_box(scat_discr.mesh), h=(0.05, 0.05, 0.3), extend_factor=0.3) from pytential.qbx import QBXTargetAssociationFailedException qbx_tgt_tol = qbx.copy(target_association_tolerance=0.2) fplot_tgt = PointsTarget(cl.array.to_device(queue, fplot.points)) try: fplot_repr = eval_repr_at(fplot_tgt, source=qbx_tgt_tol) except QBXTargetAssociationFailedException as e: fplot.write_vtk_file( "failed-targets.vts", [ ("failed_targets", e.failed_target_flags.get(queue)) ]) raise fplot_repr = EHField(vector_from_device(queue, fplot_repr)) fplot_inc = EHField( vector_from_device(queue, eval_inc_field_at(fplot_tgt))) fplot.write_vtk_file( "potential-%s.vts" % resolution, [ ("E", fplot_repr.e), ("H", fplot_repr.h), ("Einc", fplot_inc.e), ("Hinc", fplot_inc.h), ] ) # }}} # {{{ error in E, H obs_repr = EHField(eval_repr_at(obs_discr)) def obs_norm(f): return norm(obs_discr, queue, f, p=np.inf) rel_err_e = (obs_norm(inc_field_obs.e + obs_repr.e) / obs_norm(inc_field_obs.e)) rel_err_h = (obs_norm(inc_field_obs.h + obs_repr.h) / obs_norm(inc_field_obs.h)) # }}} print("ERR", h_max, rel_err_h, rel_err_e) eoc_rec_h.add_data_point(h_max, rel_err_h) eoc_rec_e.add_data_point(h_max, rel_err_e) print("--------------------------------------------------------") print("is_interior=%s" % case.is_interior) print("--------------------------------------------------------") good = True for which_eoc, eoc_rec, order_tol in [ ("maxwell", eoc_rec_repr_maxwell, 1.5), ("PEC BC", eoc_pec_bc, 1.5), ("H", eoc_rec_h, 1.5), ("E", eoc_rec_e, 1.5)]: print(which_eoc) print(eoc_rec.pretty_print()) if len(eoc_rec.history) > 1: if eoc_rec.order_estimate() < case.qbx_order - order_tol: good = False assert good