def apply_stress(self, density_vec_sym, dir_vec_sym, mu_sym, qbx_forced_limit): r"""Symbolic expression for viscous stress applied to a direction. Returns a vector of symbolic expressions for the force resulting from the viscous stress .. math:: -p \delta_{ij} + \mu (\nabla_i u_j + \nabla_j u_i) applied in the direction of *dir_vec_sym*. Note that this computation is very similar to computing a double-layer potential with the Stresslet kernel in :class:`StressletWrapper`. The difference is that here the direction vector is applied at the target points, while in the Stresslet the direction is applied at the source points. :arg density_vec_sym: a symbolic vector variable for the density vector. :arg dir_vec_sym: a symbolic vector for the application direction. :arg mu_sym: a symbolic variable for the viscosity. :arg qbx_forced_limit: the *qbx_forced_limit* argument to be passed on to :class:`~pytential.symbolic.primitives.IntG`. """ import itertools sym_expr = np.empty((self.dim,), dtype=object) stresslet_obj = StressletWrapper(dim=self.dim) for comp in range(self.dim): # Start variable count for kernel with 1 for the requested result # component base_count = np.zeros(self.dim, dtype=np.int) base_count[comp] += 1 for i, j in itertools.product(range(self.dim), range(self.dim)): var_ctr = base_count.copy() var_ctr[i] += 1 var_ctr[j] += 1 ctr_key = tuple(var_ctr) if i + j < 1: sym_expr[comp] = dir_vec_sym[i] * sym.IntG( stresslet_obj.kernel_dict[ctr_key], density_vec_sym[j], qbx_forced_limit=qbx_forced_limit, mu=mu_sym) else: sym_expr[comp] = sym_expr[comp] + dir_vec_sym[i] * sym.IntG( stresslet_obj.kernel_dict[ctr_key], density_vec_sym[j], qbx_forced_limit=qbx_forced_limit, mu=mu_sym) return sym_expr
def apply_derivative(self, deriv_dir, density_vec_sym, dir_vec_sym, mu_sym, qbx_forced_limit): """ Symbolic derivative of velocity from stresslet. Returns an object array of symbolic expressions for the vector resulting from integrating the *deriv_dir* derivative of the dyadic stresslet kernel (wrt target, not source) with variable *density_vec_sym* and source direction vectors *dir_vec_sym*. :arg deriv_dir: which derivative we want: 0, 1, or 2 for x, y, z :arg density_vec_sym: a symbolic vector variable for the density vector :arg dir_vec_sym: a symbolic vector variable for the normal direction :arg mu_sym: a symbolic variable for the viscosity :arg qbx_forced_limit: the qbx_forced_limit argument to be passed on to IntG. +/-1 for exterior/interior one-sided boundary limit, +/-2 for exterior/interior off-boundary evaluation, and 'avg' for the average of the two one-sided boundary limits. """ import itertools from pytential.symbolic.mappers import DerivativeTaker sym_expr = np.empty((self.dim, ), dtype=object) for comp in range(self.dim): # Start variable count for kernel with 1 for the requested result # component base_count = np.zeros(self.dim, dtype=np.int) base_count[comp] += 1 for i, j in itertools.product(range(self.dim), range(self.dim)): var_ctr = base_count.copy() var_ctr[i] += 1 var_ctr[j] += 1 ctr_key = tuple(var_ctr) if i + j < 1: sym_expr[comp] = DerivativeTaker(deriv_dir).map_int_g( sym.IntG(self.kernel_dict[ctr_key], dir_vec_sym[i] * density_vec_sym[j], qbx_forced_limit=qbx_forced_limit, mu=mu_sym)) else: sym_expr[comp] = sym_expr[comp] + DerivativeTaker( deriv_dir).map_int_g( sym.IntG(self.kernel_dict[ctr_key], dir_vec_sym[i] * density_vec_sym[j], qbx_forced_limit=qbx_forced_limit, mu=mu_sym)) return sym_expr
def apply_derivative(self, deriv_dir, density_vec_sym, dir_vec_sym, mu_sym, qbx_forced_limit): """Symbolic derivative of velocity from stresslet. Returns an object array of symbolic expressions for the vector resulting from integrating the *deriv_dir* target derivative of the dyadic Stresslet kernel with variable *density_vec_sym* and source direction vectors *dir_vec_sym*. :arg deriv_dir: integer denoting the axis direction for the derivative. :arg density_vec_sym: a symbolic vector variable for the density vector. :arg dir_vec_sym: a symbolic vector variable for the normal direction. :arg mu_sym: a symbolic variable for the viscosity. :arg qbx_forced_limit: the *qbx_forced_limit* argument to be passed on to :class:`~pytential.symbolic.primitives.IntG`. """ import itertools from pytential.symbolic.mappers import DerivativeTaker sym_expr = np.empty((self.dim,), dtype=object) for comp in range(self.dim): # Start variable count for kernel with 1 for the requested result # component base_count = np.zeros(self.dim, dtype=np.int) base_count[comp] += 1 for i, j in itertools.product(range(self.dim), range(self.dim)): var_ctr = base_count.copy() var_ctr[i] += 1 var_ctr[j] += 1 ctr_key = tuple(var_ctr) if i + j < 1: sym_expr[comp] = DerivativeTaker(deriv_dir).map_int_g( sym.IntG(self.kernel_dict[ctr_key], dir_vec_sym[i] * density_vec_sym[j], qbx_forced_limit=qbx_forced_limit, mu=mu_sym)) else: sym_expr[comp] = sym_expr[comp] + DerivativeTaker( deriv_dir).map_int_g( sym.IntG(self.kernel_dict[ctr_key], dir_vec_sym[i] * density_vec_sym[j], qbx_forced_limit=qbx_forced_limit, mu=mu_sym)) return sym_expr
def apply(self, density_vec_sym, dir_vec_sym, mu_sym, qbx_forced_limit): """ Symbolic expressions for integrating stresslet kernel Returns an object array of symbolic expressions for the vector resulting from integrating the dyadic stresslet kernel with variable *density_vec_sym* and source direction vectors *dir_vec_sym*. :arg density_vec_sym: a symbolic vector variable for the density vector :arg dir_vec_sym: a symbolic vector variable for the direction vector :arg mu_sym: a symbolic variable for the viscosity :arg qbx_forced_limit: the qbx_forced_limit argument to be passed on to IntG. +/-1 for exterior/interior one-sided boundary limit, +/-2 for exterior/interior off-boundary evaluation, and 'avg' for the average of the two one-sided boundary limits. """ import itertools sym_expr = np.empty((self.dim, ), dtype=object) for comp in range(self.dim): # Start variable count for kernel with 1 for the requested result # component base_count = np.zeros(self.dim, dtype=np.int) base_count[comp] += 1 for i, j in itertools.product(range(self.dim), range(self.dim)): var_ctr = base_count.copy() var_ctr[i] += 1 var_ctr[j] += 1 ctr_key = tuple(var_ctr) if i + j < 1: sym_expr[comp] = sym.IntG( self.kernel_dict[ctr_key], dir_vec_sym[i] * density_vec_sym[j], qbx_forced_limit=qbx_forced_limit, mu=mu_sym) else: sym_expr[comp] = sym_expr[comp] + sym.IntG( self.kernel_dict[ctr_key], dir_vec_sym[i] * density_vec_sym[j], qbx_forced_limit=qbx_forced_limit, mu=mu_sym) return sym_expr
def apply(self, density_vec_sym, mu_sym, qbx_forced_limit): """Symbolic expressions for integrating Stokeslet kernel. Returns an object array of symbolic expressions for the vector resulting from integrating the dyadic Stokeslet kernel with variable *density_vec_sym*. :arg density_vec_sym: a symbolic vector variable for the density vector. :arg mu_sym: a symbolic variable for the viscosity. :arg qbx_forced_limit: the *qbx_forced_limit* argument to be passed on to :class:`~pytential.symbolic.primitives.IntG`. """ sym_expr = np.empty((self.dim,), dtype=object) for comp in range(self.dim): # Start variable count for kernel with 1 for the requested result # component base_count = np.zeros(self.dim, dtype=np.int) base_count[comp] += 1 for i in range(self.dim): var_ctr = base_count.copy() var_ctr[i] += 1 ctr_key = tuple(var_ctr) if i < 1: sym_expr[comp] = sym.IntG( self.kernel_dict[ctr_key], density_vec_sym[i], qbx_forced_limit=qbx_forced_limit, mu=mu_sym) else: sym_expr[comp] = sym_expr[comp] + sym.IntG( self.kernel_dict[ctr_key], density_vec_sym[i], qbx_forced_limit=qbx_forced_limit, mu=mu_sym) return sym_expr
def test_unregularized_with_ones_kernel(ctx_factory): cl_ctx = ctx_factory() queue = cl.CommandQueue(cl_ctx) actx = PyOpenCLArrayContext(queue) nelements = 10 order = 8 mesh = make_curve_mesh(partial(ellipse, 1), np.linspace(0, 1, nelements+1), order) from meshmode.discretization import Discretization from meshmode.discretization.poly_element import \ InterpolatoryQuadratureSimplexGroupFactory discr = Discretization(actx, mesh, InterpolatoryQuadratureSimplexGroupFactory(order)) from pytential.unregularized import UnregularizedLayerPotentialSource lpot_source = UnregularizedLayerPotentialSource(discr) from pytential.target import PointsTarget targets = PointsTarget(np.zeros((2, 1), dtype=float)) places = GeometryCollection({ sym.DEFAULT_SOURCE: lpot_source, sym.DEFAULT_TARGET: lpot_source, "target_non_self": targets}) from sumpy.kernel import one_kernel_2d sigma_sym = sym.var("sigma") op = sym.IntG(one_kernel_2d, sigma_sym, qbx_forced_limit=None) sigma = discr.zeros(actx) + 1 result_self = bind(places, op, auto_where=places.auto_where)( actx, sigma=sigma) result_nonself = bind(places, op, auto_where=(places.auto_source, "target_non_self"))( actx, sigma=sigma) from meshmode.dof_array import flatten assert np.allclose(actx.to_numpy(flatten(result_self)), 2 * np.pi) assert np.allclose(actx.to_numpy(result_nonself), 2 * np.pi)
def test_unregularized_with_ones_kernel(ctx_factory): cl_ctx = ctx_factory() queue = cl.CommandQueue(cl_ctx) nelements = 10 order = 8 mesh = make_curve_mesh(partial(ellipse, 1), np.linspace(0, 1, nelements + 1), order) from meshmode.discretization import Discretization from meshmode.discretization.poly_element import \ InterpolatoryQuadratureSimplexGroupFactory discr = Discretization(cl_ctx, mesh, InterpolatoryQuadratureSimplexGroupFactory(order)) from pytential.unregularized import UnregularizedLayerPotentialSource lpot_src = UnregularizedLayerPotentialSource(discr) from sumpy.kernel import one_kernel_2d expr = sym.IntG(one_kernel_2d, sym.var("sigma"), qbx_forced_limit=None) from pytential.target import PointsTarget op_self = bind(lpot_src, expr) op_nonself = bind((lpot_src, PointsTarget(np.zeros((2, 1), dtype=float))), expr) with cl.CommandQueue(cl_ctx) as queue: sigma = cl.array.zeros(queue, discr.nnodes, dtype=float) sigma.fill(1) sigma.finish() result_self = op_self(queue, sigma=sigma) result_nonself = op_nonself(queue, sigma=sigma) assert np.allclose(result_self.get(), 2 * np.pi) assert np.allclose(result_nonself.get(), 2 * np.pi)
assert np.sum(source_charges) < 1e-15 source_charges_dev = cl.array.to_device(queue, source_charges) # }}} # {{{ establish BCs from pytential.source import PointPotentialSource from pytential.target import PointsTarget point_source = PointPotentialSource(cl_ctx, point_sources) pot_src = sym.IntG( # FIXME: qbx_forced_limit--really? knl, sym.var("charges"), qbx_forced_limit=None, **knl_kwargs) test_direct = bind((point_source, PointsTarget(test_targets)), pot_src)(queue, charges=source_charges_dev, **concrete_knl_kwargs) if case.bc_type == "dirichlet": bc = bind((point_source, density_discr), pot_src)(queue, charges=source_charges_dev, **concrete_knl_kwargs) elif case.bc_type == "neumann":
def apply_stress(self, density_vec_sym, dir_vec_sym, mu_sym, qbx_forced_limit): """ Symbolic expression for viscous stress applied to direction Returns a vector of symbolic expressions for the force resulting from the viscous stress: -pressure * I + mu * ( grad U + (grad U).T)), applied in the direction of *dir_vec_sym*. Note that this computation is very similar to computing a double-layer potential with the stresslet kernel. The difference is that here the direction vector is the direction applied to the stress tensor and is applied outside of the integration, whereas the stresslet calculation uses the normal vectors at every source point. As such, the length of the argument passed in for the stresslet velocity calculation (after binding) is the same length as the number of source points/nodes; when calling this routine, the number of direction vectors should be the same as the number of targets. :arg density_vec_sym: a symbolic vector variable for the density vector :arg dir_vec_sym: a symbolic vector for the application direction :arg mu_sym: a symbolic variable for the viscosity :arg qbx_forced_limit: the qbx_forced_limit argument to be passed on to IntG. +/-1 for exterior/interior one-sided boundary limit, +/-2 for exterior/interior off-boundary evaluation, and 'avg' for the average of the two one-sided boundary limits. """ import itertools sym_expr = np.empty((self.dim,), dtype=object) stresslet_obj = StressletWrapper(dim=self.dim) for comp in range(self.dim): # Start variable count for kernel with 1 for the requested result # component base_count = np.zeros(self.dim, dtype=np.int) base_count[comp] += 1 for i, j in itertools.product(range(self.dim), range(self.dim)): var_ctr = base_count.copy() var_ctr[i] += 1 var_ctr[j] += 1 ctr_key = tuple(var_ctr) if i + j < 1: sym_expr[comp] = dir_vec_sym[i] * sym.IntG( stresslet_obj.kernel_dict[ctr_key], density_vec_sym[j], qbx_forced_limit=qbx_forced_limit, mu=mu_sym) else: sym_expr[comp] = sym_expr[comp] + dir_vec_sym[i] * sym.IntG( stresslet_obj.kernel_dict[ctr_key], density_vec_sym[j], qbx_forced_limit=qbx_forced_limit, mu=mu_sym) return sym_expr
def get_bvp_error(lpot_source, fmm_order, qbx_order, k=0): # This returns a tuple (err_l2, err_linf, nit). queue = cl.CommandQueue(lpot_source.cl_context) lpot_source = lpot_source.copy( qbx_order=qbx_order, fmm_level_to_order=(False if fmm_order is False else lambda *args: fmm_order)) d = lpot_source.ambient_dim assert k == 0 # Helmholtz would require a different representation from sumpy.kernel import LaplaceKernel, HelmholtzKernel lap_k_sym = LaplaceKernel(d) if k == 0: k_sym = lap_k_sym knl_kwargs = {} else: k_sym = HelmholtzKernel(d) knl_kwargs = {"k": sym.var("k")} density_discr = lpot_source.density_discr # {{{ find source and target points source_angles = (np.pi / 2 + np.linspace(0, 2 * np.pi * BVP_EXPERIMENT_N_ARMS, BVP_EXPERIMENT_N_ARMS, endpoint=False)) / BVP_EXPERIMENT_N_ARMS source_points = 0.75 * np.array([ np.cos(source_angles), np.sin(source_angles), ]) target_angles = (np.pi + np.pi / 2 + np.linspace(0, 2 * np.pi * BVP_EXPERIMENT_N_ARMS, BVP_EXPERIMENT_N_ARMS, endpoint=False)) / BVP_EXPERIMENT_N_ARMS target_points = 1.5 * np.array([ np.cos(target_angles), np.sin(target_angles), ]) np.random.seed(17) source_charges = np.random.randn(BVP_EXPERIMENT_N_ARMS) source_points_dev = cl.array.to_device(queue, source_points) target_points_dev = cl.array.to_device(queue, target_points) source_charges_dev = cl.array.to_device(queue, source_charges) from pytential.source import PointPotentialSource from pytential.target import PointsTarget point_source = PointPotentialSource(lpot_source.cl_context, source_points_dev) pot_src = sym.IntG( # FIXME: qbx_forced_limit--really? k_sym, sym.var("charges"), qbx_forced_limit=None, **knl_kwargs) ref_direct = bind((point_source, PointsTarget(target_points_dev)), pot_src)(queue, charges=source_charges_dev, **knl_kwargs).get() sym_sqrt_j = sym.sqrt_jac_q_weight(density_discr.ambient_dim) bc = bind((point_source, density_discr), sym.normal_derivative(density_discr.ambient_dim, pot_src, where=sym.DEFAULT_TARGET))( queue, charges=source_charges_dev, **knl_kwargs) rhs = bind(density_discr, sym.var("bc") * sym_sqrt_j)(queue, bc=bc) # }}} # {{{ solve bound_op = bind( lpot_source, -0.5 * sym.var("u") + sym_sqrt_j * sym.Sp(k_sym, sym.var("u") / sym_sqrt_j, qbx_forced_limit="avg", **knl_kwargs)) from pytential.solve import gmres gmres_result = gmres(bound_op.scipy_op(queue, "u", np.float64, **knl_kwargs), rhs, tol=1e-10, stall_iterations=100, progress=True, hard_failure=True) u = gmres_result.solution # }}} points_target = PointsTarget(target_points_dev) bound_tgt_op = bind((lpot_source, points_target), sym.S(k_sym, sym.var("u") / sym_sqrt_j, qbx_forced_limit=None)) test_via_bdry = bound_tgt_op(queue, u=u).get() err = ref_direct - test_via_bdry err_l2 = la.norm(err, 2) / la.norm(ref_direct, 2) err_linf = la.norm(err, np.inf) / la.norm(ref_direct, np.inf) return err_l2, err_linf, gmres_result.iteration_count
def compute_biharmonic_extension(queue, target_discr, qbx, density_discr, f, fx, fy, target_association_tolerance=0.05): """Biharmoc extension. Currently only support interior domains in 2D (i.e., extension is on the exterior). """ # pylint: disable=invalid-unary-operand-type dim = 2 queue = setup_command_queue(queue=queue) qbx_forced_limit = 1 normal = get_normal_vectors(queue, density_discr, loc_sign=1) bdry_op_sym = get_extension_bie_symbolic_operator(loc_sign=1) bound_op = bind(qbx, bdry_op_sym) bc = [fy, -fx] bvp_rhs = bind(qbx, sym.make_sym_vector("bc", dim))(queue, bc=bc) gmres_result = gmres(bound_op.scipy_op(queue, "sigma", np.float64, mu=1., normal=normal), bvp_rhs, tol=1e-9, progress=True, stall_iterations=0, hard_failure=True) mu = gmres_result.solution arclength_parametrization_derivatives_sym = sym.make_sym_vector( "arclength_parametrization_derivatives", dim) density_mu_sym = sym.make_sym_vector("mu", dim) dxids_sym = arclength_parametrization_derivatives_sym[0] + \ 1j * arclength_parametrization_derivatives_sym[1] dxids_conj_sym = arclength_parametrization_derivatives_sym[0] - \ 1j * arclength_parametrization_derivatives_sym[1] density_rho_sym = density_mu_sym[1] - 1j * density_mu_sym[0] density_conj_rho_sym = density_mu_sym[1] + 1j * density_mu_sym[0] # convolutions GS1 = sym.IntG( # noqa: N806 ComplexLinearLogKernel(dim), density_rho_sym, qbx_forced_limit=None) GS2 = sym.IntG( # noqa: N806 ComplexLinearKernel(dim), density_conj_rho_sym, qbx_forced_limit=None) GD1 = sym.IntG( # noqa: N806 ComplexFractionalKernel(dim), density_rho_sym * dxids_sym, qbx_forced_limit=None) GD2 = [ sym.IntG( # noqa: N806 AxisTargetDerivative(iaxis, ComplexLogKernel(dim)), density_conj_rho_sym * dxids_sym + density_rho_sym * dxids_conj_sym, qbx_forced_limit=qbx_forced_limit) for iaxis in range(dim) ] GS1_bdry = sym.IntG( # noqa: N806 ComplexLinearLogKernel(dim), density_rho_sym, qbx_forced_limit=qbx_forced_limit) GS2_bdry = sym.IntG( # noqa: N806 ComplexLinearKernel(dim), density_conj_rho_sym, qbx_forced_limit=qbx_forced_limit) GD1_bdry = sym.IntG( # noqa: N806 ComplexFractionalKernel(dim), density_rho_sym * dxids_sym, qbx_forced_limit=qbx_forced_limit) xp, yp = get_arclength_parametrization_derivative(queue, density_discr) xp = -xp yp = -yp tangent = get_tangent_vectors(queue, density_discr, loc_sign=qbx_forced_limit) # check and fix the direction of parametrization # logger.info("Fix all negative signs in:" + # str(xp * tangent[0] + yp * tangent[1])) grad_v2 = [ bind(qbx, GD2[iaxis])(queue, mu=mu, arclength_parametrization_derivatives=make_obj_array( [xp, yp])).real for iaxis in range(dim) ] v2_tangent_der = sum(tangent[iaxis] * grad_v2[iaxis] for iaxis in range(dim)) from pytential.symbolic.pde.scalar import NeumannOperator from sumpy.kernel import LaplaceKernel operator_v1 = NeumannOperator(LaplaceKernel(dim), loc_sign=qbx_forced_limit) bound_op_v1 = bind(qbx, operator_v1.operator(var("sigma"))) # FIXME: the positive sign works here rhs_v1 = operator_v1.prepare_rhs(1 * v2_tangent_der) gmres_result = gmres(bound_op_v1.scipy_op(queue, "sigma", dtype=np.float64), rhs_v1, tol=1e-9, progress=True, stall_iterations=0, hard_failure=True) sigma = gmres_result.solution qbx_stick_out = qbx.copy( target_association_tolerance=target_association_tolerance) v1 = bind((qbx_stick_out, target_discr), operator_v1.representation(var("sigma"), qbx_forced_limit=None))(queue, sigma=sigma) grad_v1 = bind( (qbx_stick_out, target_discr), operator_v1.representation( var("sigma"), qbx_forced_limit=None, map_potentials=lambda pot: sym.grad(dim, pot)))(queue, sigma=sigma) v1_bdry = bind( qbx, operator_v1.representation(var("sigma"), qbx_forced_limit=qbx_forced_limit))( queue, sigma=sigma) z_conj = target_discr.nodes()[0] - 1j * target_discr.nodes()[1] z_conj_bdry = density_discr.nodes().with_queue(queue)[0] \ - 1j * density_discr.nodes().with_queue(queue)[1] int_rho = 1 / (8 * np.pi) * bind( qbx, sym.integral(dim, dim - 1, density_rho_sym))(queue, mu=mu) omega_S1 = bind( # noqa: N806 (qbx_stick_out, target_discr), GS1)(queue, mu=mu).real omega_S2 = -1 * bind( # noqa: N806 (qbx_stick_out, target_discr), GS2)(queue, mu=mu).real omega_S3 = (z_conj * int_rho).real # noqa: N806 omega_S = -(omega_S1 + omega_S2 + omega_S3) # noqa: N806 grad_omega_S1 = bind( # noqa: N806 (qbx_stick_out, target_discr), sym.grad(dim, GS1))(queue, mu=mu).real grad_omega_S2 = -1 * bind( # noqa: N806 (qbx_stick_out, target_discr), sym.grad(dim, GS2))(queue, mu=mu).real grad_omega_S3 = (int_rho * make_obj_array([1., -1.])).real # noqa: N806 grad_omega_S = -(grad_omega_S1 + grad_omega_S2 + grad_omega_S3 ) # noqa: N806 omega_S1_bdry = bind(qbx, GS1_bdry)(queue, mu=mu).real # noqa: N806 omega_S2_bdry = -1 * bind(qbx, GS2_bdry)(queue, mu=mu).real # noqa: N806 omega_S3_bdry = (z_conj_bdry * int_rho).real # noqa: N806 omega_S_bdry = -(omega_S1_bdry + omega_S2_bdry + omega_S3_bdry ) # noqa: N806 omega_D1 = bind( # noqa: N806 (qbx_stick_out, target_discr), GD1)(queue, mu=mu, arclength_parametrization_derivatives=make_obj_array([xp, yp])).real omega_D = (omega_D1 + v1) # noqa: N806 grad_omega_D1 = bind( # noqa: N806 (qbx_stick_out, target_discr), sym.grad(dim, GD1))( queue, mu=mu, arclength_parametrization_derivatives=make_obj_array([xp, yp])).real grad_omega_D = grad_omega_D1 + grad_v1 # noqa: N806 omega_D1_bdry = bind( # noqa: N806 qbx, GD1_bdry)(queue, mu=mu, arclength_parametrization_derivatives=make_obj_array( [xp, yp])).real omega_D_bdry = (omega_D1_bdry + v1_bdry) # noqa: N806 int_bdry_mu = bind( qbx, sym.integral(dim, dim - 1, sym.make_sym_vector("mu", dim)))(queue, mu=mu) omega_W = ( # noqa: N806 int_bdry_mu[0] * target_discr.nodes()[1] - int_bdry_mu[1] * target_discr.nodes()[0]) grad_omega_W = make_obj_array( # noqa: N806 [-int_bdry_mu[1], int_bdry_mu[0]]) omega_W_bdry = ( # noqa: N806 int_bdry_mu[0] * density_discr.nodes().with_queue(queue)[1] - int_bdry_mu[1] * density_discr.nodes().with_queue(queue)[0]) int_bdry = bind(qbx, sym.integral(dim, dim - 1, var("integrand")))( queue, integrand=omega_S_bdry + omega_D_bdry + omega_W_bdry) debugging_info = {} debugging_info['omega_S'] = omega_S debugging_info['omega_D'] = omega_D debugging_info['omega_W'] = omega_W debugging_info['omega_v1'] = v1 debugging_info['omega_D1'] = omega_D1 int_interior_func_bdry = bind(qbx, sym.integral(2, 1, var("integrand")))(queue, integrand=f) path_length = get_path_length(queue, density_discr) ext_f = omega_S + omega_D + omega_W + (int_interior_func_bdry - int_bdry) / path_length grad_f = grad_omega_S + grad_omega_D + grad_omega_W return ext_f, grad_f[0], grad_f[1], debugging_info
np.random.seed(22) source_charges = np.random.randn(point_source.ndofs) source_charges[-1] = -np.sum(source_charges[:-1]) source_charges = source_charges.astype(dtype) assert np.sum(source_charges) < 1.0e-15 source_charges_dev = actx.from_numpy(source_charges) # }}} # {{{ establish BCs pot_src = sym.IntG( # FIXME: qbx_forced_limit--really? knl, sym_charges, qbx_forced_limit=None, **case.knl_sym_kwargs) test_direct = bind(places, pot_src, auto_where=("point_source", "point_target"))(actx, charges=source_charges_dev, **case.knl_concrete_kwargs) if case.bc_type == "dirichlet": bc = bind(places, pot_src, auto_where=("point_source", case.name))(actx, charges=source_charges_dev,