Example #1
0
    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
Example #2
0
    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
Example #3
0
    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
Example #4
0
    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
Example #5
0
    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
Example #6
0
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,