def apply_pressure(self, density_vec_sym, dir_vec_sym, mu_sym, qbx_forced_limit): """Symbolic expression for pressure field associated with the Stresslet.""" import itertools from pytential.symbolic.mappers import DerivativeTaker kernel = LaplaceKernel(dim=self.dim) factor = (2. * mu_sym) for i, j in itertools.product(range(self.dim), range(self.dim)): if i + j < 1: sym_expr = factor * DerivativeTaker(i).map_int_g( DerivativeTaker(j).map_int_g( sym.int_g_vec(kernel, density_vec_sym[i] * dir_vec_sym[j], qbx_forced_limit=qbx_forced_limit))) else: sym_expr = sym_expr + (factor * DerivativeTaker(i).map_int_g( DerivativeTaker(j).map_int_g( sym.int_g_vec(kernel, density_vec_sym[i] * dir_vec_sym[j], qbx_forced_limit=qbx_forced_limit)))) return sym_expr
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.int32) 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.int_g_vec( 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.int_g_vec(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* 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.int32) 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.int_g_vec(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.int_g_vec(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.int32) 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.int_g_vec( 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.int_g_vec( self.kernel_dict[ctr_key], density_vec_sym[i], qbx_forced_limit=qbx_forced_limit, mu=mu_sym) return sym_expr
def apply_pressure(self, density_vec_sym, mu_sym, qbx_forced_limit): """Symbolic expression for pressure field associated with the Stokeslet.""" from pytential.symbolic.mappers import DerivativeTaker kernel = LaplaceKernel(dim=self.dim) for i in range(self.dim): if i < 1: sym_expr = DerivativeTaker(i).map_int_g( sym.int_g_vec(kernel, density_vec_sym[i], qbx_forced_limit=qbx_forced_limit)) else: sym_expr = sym_expr + (DerivativeTaker(i).map_int_g( sym.int_g_vec(kernel, density_vec_sym[i], qbx_forced_limit=qbx_forced_limit))) 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.int_g_vec(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)
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.int_g_vec( # 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,