コード例 #1
0
ファイル: qbx.py プロジェクト: benSepanski/sumpy
    def get_loopy_insns_and_result_names(self):
        from sumpy.symbolic import make_sym_vector
        avec = make_sym_vector("a", self.dim)
        bvec = make_sym_vector("b", self.dim)

        from sumpy.assignment_collection import SymbolicAssignmentCollection
        sac = SymbolicAssignmentCollection()

        logger.info("compute expansion expressions: start")

        result_names = [
            expand(i, sac, expn, avec, bvec)
            for i, expn in enumerate(self.expansions)
        ]

        logger.info("compute expansion expressions: done")

        sac.run_global_cse()

        from sumpy.codegen import to_loopy_insns
        loopy_insns = to_loopy_insns(
            sac.assignments.items(),
            vector_names={"a", "b"},
            pymbolic_expr_maps=[
                expn.kernel.get_code_transformer() for expn in self.expansions
            ],
            retain_names=result_names,
            complex_dtype=np.complex128  # FIXME
        )

        return loopy_insns, result_names
コード例 #2
0
ファイル: qbx.py プロジェクト: inducer/sumpy
    def get_loopy_insns_and_result_names(self):
        from sumpy.symbolic import make_sym_vector
        avec = make_sym_vector("a", self.dim)
        bvec = make_sym_vector("b", self.dim)

        from sumpy.assignment_collection import SymbolicAssignmentCollection
        sac = SymbolicAssignmentCollection()

        logger.info("compute expansion expressions: start")

        result_names = [expand(i, sac, expn, avec, bvec)
                        for i, expn in enumerate(self.expansions)]

        logger.info("compute expansion expressions: done")

        sac.run_global_cse()

        from sumpy.codegen import to_loopy_insns
        loopy_insns = to_loopy_insns(
                six.iteritems(sac.assignments),
                vector_names=set(["a", "b"]),
                pymbolic_expr_maps=[
                    expn.kernel.get_code_transformer() for expn in self.expansions],
                retain_names=result_names,
                complex_dtype=np.complex128  # FIXME
                )

        return loopy_insns, result_names
コード例 #3
0
ファイル: test_codegen.py プロジェクト: inducer/sumpy
def test_line_taylor_coeff_growth():
    # Regression test for LineTaylorLocalExpansion.
    # See https://gitlab.tiker.net/inducer/pytential/merge_requests/12
    from sumpy.kernel import LaplaceKernel
    from sumpy.expansion.local import LineTaylorLocalExpansion
    from sumpy.symbolic import make_sym_vector, SympyToPymbolicMapper

    import numpy as np

    order = 10
    expn = LineTaylorLocalExpansion(LaplaceKernel(2), order)
    avec = make_sym_vector("a", 2)
    bvec = make_sym_vector("b", 2)
    coeffs = expn.coefficients_from_source(avec, bvec, rscale=1)

    sym2pymbolic = SympyToPymbolicMapper()
    coeffs_pymbolic = [sym2pymbolic(c) for c in coeffs]

    from pymbolic.mapper.flop_counter import FlopCounter
    flop_counter = FlopCounter()
    counts = [flop_counter(c) for c in coeffs_pymbolic]

    indices = np.arange(1, order + 2)
    max_order = 2
    assert np.polyfit(np.log(indices), np.log(counts), deg=1)[0] < max_order
コード例 #4
0
ファイル: test_codegen.py プロジェクト: jdoherty7/sumpy
def test_line_taylor_coeff_growth():
    # Regression test for LineTaylorLocalExpansion.
    # See https://gitlab.tiker.net/inducer/pytential/merge_requests/12
    from sumpy.kernel import LaplaceKernel
    from sumpy.expansion.local import LineTaylorLocalExpansion
    from sumpy.symbolic import make_sym_vector, SympyToPymbolicMapper

    import numpy as np

    order = 10
    expn = LineTaylorLocalExpansion(LaplaceKernel(2), order)
    avec = make_sym_vector("a", 2)
    bvec = make_sym_vector("b", 2)
    coeffs = expn.coefficients_from_source(avec, bvec, rscale=1)

    sym2pymbolic = SympyToPymbolicMapper()
    coeffs_pymbolic = [sym2pymbolic(c) for c in coeffs]

    from pymbolic.mapper.flop_counter import FlopCounter
    flop_counter = FlopCounter()
    counts = [flop_counter(c) for c in coeffs_pymbolic]

    indices = np.arange(1, order + 2)
    max_order = 2
    assert np.polyfit(np.log(indices), np.log(counts), deg=1)[0] < max_order
コード例 #5
0
ファイル: diff_op.py プロジェクト: benSepanski/sumpy
    def to_sym(self, fnames=None):
        from sumpy.symbolic import make_sym_vector, Function
        x = list(make_sym_vector("x", self.dim))
        x += list(make_sym_vector("t", self.total_dims - self.dim))

        if fnames is None:
            noutputs = 0
            for eq in self.eqs:
                for deriv_ident in eq.keys():
                    noutputs = max(noutputs, deriv_ident.vec_idx)
            fnames = [f"f{i}" for i in range(noutputs+1)]

        funcs = [Function(fname)(*x) for fname in fnames]

        res = []
        for eq in self.eqs:
            sym_eq = 0
            for deriv_ident, coeff in eq.items():
                expr = funcs[deriv_ident.vec_idx]
                for i, val in enumerate(deriv_ident.mi):
                    for j in range(val):
                        expr = expr.diff(x[i])
                sym_eq += expr * coeff
            res.append(sym_eq)
        return res
コード例 #6
0
ファイル: e2e.py プロジェクト: inducer/sumpy
    def get_translation_loopy_insns(self):
        from sumpy.symbolic import make_sym_vector
        dvec = make_sym_vector("d", self.dim)

        src_coeff_exprs = [sym.Symbol("src_coeff%d" % i)
                for i in range(len(self.src_expansion))]
        src_rscale = sym.Symbol("src_rscale")

        tgt_rscale = sym.Symbol("tgt_rscale")

        from sumpy.assignment_collection import SymbolicAssignmentCollection
        sac = SymbolicAssignmentCollection()
        tgt_coeff_names = [
                sac.assign_unique("coeff%d" % i, coeff_i)
                for i, coeff_i in enumerate(
                    self.tgt_expansion.translate_from(
                        self.src_expansion, src_coeff_exprs, src_rscale,
                        dvec, tgt_rscale))]

        sac.run_global_cse()

        from sumpy.codegen import to_loopy_insns
        return to_loopy_insns(
                six.iteritems(sac.assignments),
                vector_names=set(["d"]),
                pymbolic_expr_maps=[self.tgt_expansion.get_code_transformer()],
                retain_names=tgt_coeff_names,
                complex_dtype=np.complex128  # FIXME
                )
コード例 #7
0
ファイル: e2p.py プロジェクト: inducer/sumpy
    def get_loopy_insns_and_result_names(self):
        from sumpy.symbolic import make_sym_vector
        bvec = make_sym_vector("b", self.dim)

        import sumpy.symbolic as sp
        rscale = sp.Symbol("rscale")

        from sumpy.assignment_collection import SymbolicAssignmentCollection
        sac = SymbolicAssignmentCollection()

        coeff_exprs = [sym.Symbol("coeff%d" % i)
                for i in range(len(self.expansion.get_coefficient_identifiers()))]
        value = self.expansion.evaluate(coeff_exprs, bvec, rscale)

        result_names = [
            sac.assign_unique("result_%d_p" % i,
                knl.postprocess_at_target(value, bvec))
            for i, knl in enumerate(self.kernels)
            ]

        sac.run_global_cse()

        from sumpy.codegen import to_loopy_insns
        loopy_insns = to_loopy_insns(
                six.iteritems(sac.assignments),
                vector_names=set(["b"]),
                pymbolic_expr_maps=[self.expansion.get_code_transformer()],
                retain_names=result_names,
                complex_dtype=np.complex128  # FIXME
                )

        return loopy_insns, result_names
コード例 #8
0
    def get_loopy_instructions(self):
        from sumpy.symbolic import make_sym_vector
        avec = make_sym_vector("a", self.dim)

        import sumpy.symbolic as sp
        rscale = sp.Symbol("rscale")

        from sumpy.assignment_collection import SymbolicAssignmentCollection
        sac = SymbolicAssignmentCollection()

        coeff_names = [
                sac.assign_unique("coeff%d" % i, coeff_i)
                for i, coeff_i in enumerate(
                    self.expansion.coefficients_from_source(avec, None, rscale))]

        sac.run_global_cse()

        from sumpy.codegen import to_loopy_insns
        return to_loopy_insns(
                six.iteritems(sac.assignments),
                vector_names=set(["a"]),
                pymbolic_expr_maps=[self.expansion.get_code_transformer()],
                retain_names=coeff_names,
                complex_dtype=np.complex128  # FIXME
                )
コード例 #9
0
ファイル: p2p.py プロジェクト: stjordanis/sumpy
    def get_loopy_insns_and_result_names(self):
        from sumpy.symbolic import make_sym_vector
        dvec = make_sym_vector("d", self.dim)

        from sumpy.assignment_collection import SymbolicAssignmentCollection
        sac = SymbolicAssignmentCollection()

        result_names = [
            sac.assign_unique(
                "knl%d" % i,
                knl.postprocess_at_target(
                    knl.postprocess_at_source(knl.get_expression(dvec), dvec),
                    dvec)) for i, knl in enumerate(self.kernels)
        ]

        sac.run_global_cse()

        from sumpy.codegen import to_loopy_insns
        loopy_insns = to_loopy_insns(
            six.iteritems(sac.assignments),
            vector_names=set(["d"]),
            pymbolic_expr_maps=[
                knl.get_code_transformer() for knl in self.kernels
            ],
            retain_names=result_names,
            complex_dtype=np.complex128  # FIXME
        )

        return loopy_insns, result_names
コード例 #10
0
ファイル: p2p.py プロジェクト: inducer/sumpy
    def get_loopy_insns_and_result_names(self):
        from sumpy.symbolic import make_sym_vector
        dvec = make_sym_vector("d", self.dim)

        from sumpy.assignment_collection import SymbolicAssignmentCollection
        sac = SymbolicAssignmentCollection()

        result_names = [
                sac.assign_unique("knl%d" % i,
                    knl.postprocess_at_target(
                        knl.postprocess_at_source(
                            knl.get_expression(dvec),
                            dvec),
                        dvec)
                    )
                for i, knl in enumerate(self.kernels)]

        sac.run_global_cse()

        from sumpy.codegen import to_loopy_insns
        loopy_insns = to_loopy_insns(six.iteritems(sac.assignments),
                vector_names=set(["d"]),
                pymbolic_expr_maps=[
                        knl.get_code_transformer() for knl in self.kernels],
                retain_names=result_names,
                complex_dtype=np.complex128  # FIXME
                )

        return loopy_insns, result_names
コード例 #11
0
    def get_loopy_instructions(self):
        from sumpy.symbolic import make_sym_vector
        avec = make_sym_vector("a", self.dim)

        import sumpy.symbolic as sp
        rscale = sp.Symbol("rscale")

        from sumpy.assignment_collection import SymbolicAssignmentCollection
        sac = SymbolicAssignmentCollection()

        coeff_names = []
        for knl_idx, kernel in enumerate(self.kernels):
            for i, coeff_i in enumerate(
                    self.expansion.coefficients_from_source(
                        kernel, avec, None, rscale, sac)):
                sac.add_assignment(f"coeff{i}_{knl_idx}", coeff_i)
                coeff_names.append(f"coeff{i}_{knl_idx}")

        sac.run_global_cse()

        code_transformers = [self.expansion.get_code_transformer()] \
            + [kernel.get_code_transformer() for kernel in self.kernels]

        from sumpy.codegen import to_loopy_insns
        return to_loopy_insns(
            sac.assignments.items(),
            vector_names={"a"},
            pymbolic_expr_maps=code_transformers,
            retain_names=coeff_names,
            complex_dtype=np.complex128  # FIXME
        )
コード例 #12
0
    def get_translation_loopy_insns(self):
        from sumpy.symbolic import make_sym_vector
        dvec = make_sym_vector("d", self.dim)

        src_coeff_exprs = [sym.Symbol("src_coeff%d" % i)
                for i in range(len(self.src_expansion))]
        src_rscale = sym.Symbol("src_rscale")

        tgt_rscale = sym.Symbol("tgt_rscale")

        from sumpy.assignment_collection import SymbolicAssignmentCollection
        sac = SymbolicAssignmentCollection()
        tgt_coeff_names = [
                sac.assign_unique("coeff%d" % i, coeff_i)
                for i, coeff_i in enumerate(
                    self.tgt_expansion.translate_from(
                        self.src_expansion, src_coeff_exprs, src_rscale,
                        dvec, tgt_rscale, sac=sac))]

        sac.run_global_cse()

        from sumpy.codegen import to_loopy_insns
        return to_loopy_insns(
                six.iteritems(sac.assignments),
                vector_names=set(["d"]),
                pymbolic_expr_maps=[self.tgt_expansion.get_code_transformer()],
                retain_names=tgt_coeff_names,
                complex_dtype=np.complex128  # FIXME
                )
コード例 #13
0
ファイル: e2p.py プロジェクト: jdoherty7/sumpy
    def get_loopy_insns_and_result_names(self):
        from sumpy.symbolic import make_sym_vector
        bvec = make_sym_vector("b", self.dim)

        import sumpy.symbolic as sp
        rscale = sp.Symbol("rscale")

        from sumpy.assignment_collection import SymbolicAssignmentCollection
        sac = SymbolicAssignmentCollection()

        coeff_exprs = [
            sym.Symbol("coeff%d" % i)
            for i in range(len(self.expansion.get_coefficient_identifiers()))
        ]
        value = self.expansion.evaluate(coeff_exprs, bvec, rscale)

        result_names = [
            sac.assign_unique("result_%d_p" % i,
                              knl.postprocess_at_target(value, bvec))
            for i, knl in enumerate(self.kernels)
        ]

        sac.run_global_cse()

        from sumpy.codegen import to_loopy_insns
        loopy_insns = to_loopy_insns(
            six.iteritems(sac.assignments),
            vector_names=set(["b"]),
            pymbolic_expr_maps=[self.expansion.get_code_transformer()],
            retain_names=result_names,
            complex_dtype=np.complex128  # FIXME
        )

        return loopy_insns, result_names
コード例 #14
0
ファイル: multipole.py プロジェクト: xywei/sumpy
    def coefficients_from_source(self, avec, bvec, rscale, sac=None):
        from sumpy.kernel import DirectionalSourceDerivative
        kernel = self.kernel

        from sumpy.tools import mi_power, mi_factorial

        if not self.use_rscale:
            rscale = 1

        if isinstance(kernel, DirectionalSourceDerivative):
            from sumpy.symbolic import make_sym_vector

            dir_vecs = []
            tmp_kernel = kernel
            while isinstance(tmp_kernel, DirectionalSourceDerivative):
                dir_vecs.append(
                    make_sym_vector(tmp_kernel.dir_vec_name, kernel.dim))
                tmp_kernel = tmp_kernel.inner_kernel

            if kernel.get_base_kernel() is not tmp_kernel:
                raise NotImplementedError("Unknown kernel wrapper.")

            nderivs = len(dir_vecs)

            coeff_identifiers = self.get_full_coefficient_identifiers()
            result = [0] * len(coeff_identifiers)

            for i, mi in enumerate(coeff_identifiers):
                # One source derivative is the dot product of the gradient and
                # directional vector.
                # For multiple derivatives, gradient of gradients is taken.
                # For eg: in 3D, 2 source derivatives gives 9 terms and
                # cartesian_product below enumerates these 9 terms.
                for deriv_terms in cartesian_product(*[range(kernel.dim)] *
                                                     nderivs):
                    prod = 1
                    derivative_mi = list(mi)
                    for nderivative, deriv_dim in enumerate(deriv_terms):
                        prod *= -derivative_mi[deriv_dim]
                        prod *= dir_vecs[nderivative][deriv_dim]
                        derivative_mi[deriv_dim] -= 1
                    if any(v < 0 for v in derivative_mi):
                        continue
                    result[i] += mi_power(avec, derivative_mi) * prod

            for i, mi in enumerate(coeff_identifiers):
                result[i] /= (mi_factorial(mi) * rscale**sum(mi))
        else:
            avec = [sym.UnevaluatedExpr(a * rscale**-1) for a in avec]

            result = [
                mi_power(avec, mi) / mi_factorial(mi)
                for mi in self.get_full_coefficient_identifiers()
            ]
        return (self.expansion_terms_wrangler.
                get_stored_mpole_coefficients_from_full(result,
                                                        rscale,
                                                        sac=sac))
コード例 #15
0
ファイル: multipole.py プロジェクト: inducer/sumpy
    def coefficients_from_source(self, avec, bvec, rscale):
        from sumpy.kernel import DirectionalSourceDerivative
        kernel = self.kernel

        from sumpy.tools import mi_power, mi_factorial

        if not self.use_rscale:
            rscale = 1

        if isinstance(kernel, DirectionalSourceDerivative):
            if kernel.get_base_kernel() is not kernel.inner_kernel:
                raise NotImplementedError("more than one source derivative "
                        "not supported at present")

            from sumpy.symbolic import make_sym_vector
            dir_vec = make_sym_vector(kernel.dir_vec_name, kernel.dim)

            coeff_identifiers = self.get_full_coefficient_identifiers()
            result = [0] * len(coeff_identifiers)

            for idim in range(kernel.dim):
                for i, mi in enumerate(coeff_identifiers):
                    if mi[idim] == 0:
                        continue

                    derivative_mi = tuple(mi_i - 1 if iaxis == idim else mi_i
                            for iaxis, mi_i in enumerate(mi))

                    result[i] += (
                        - mi_power(avec, derivative_mi) * mi[idim]
                        * dir_vec[idim])
            for i, mi in enumerate(coeff_identifiers):
                result[i] /= (mi_factorial(mi) * rscale ** sum(mi))
        else:
            avec = [sym.UnevaluatedExpr(a * rscale**-1) for a in avec]

            result = [
                    mi_power(avec, mi) / mi_factorial(mi)
                    for mi in self.get_full_coefficient_identifiers()]
        return (
            self.derivative_wrangler.get_stored_mpole_coefficients_from_full(
                result, rscale))
コード例 #16
0
ファイル: multipole.py プロジェクト: jdoherty7/sumpy
    def coefficients_from_source(self, avec, bvec, rscale):
        from sumpy.kernel import DirectionalSourceDerivative
        kernel = self.kernel

        from sumpy.tools import mi_power, mi_factorial

        if not self.use_rscale:
            rscale = 1

        if isinstance(kernel, DirectionalSourceDerivative):
            if kernel.get_base_kernel() is not kernel.inner_kernel:
                raise NotImplementedError("more than one source derivative "
                        "not supported at present")

            from sumpy.symbolic import make_sym_vector
            dir_vec = make_sym_vector(kernel.dir_vec_name, kernel.dim)

            coeff_identifiers = self.get_full_coefficient_identifiers()
            result = [0] * len(coeff_identifiers)

            for idim in range(kernel.dim):
                for i, mi in enumerate(coeff_identifiers):
                    if mi[idim] == 0:
                        continue

                    derivative_mi = tuple(mi_i - 1 if iaxis == idim else mi_i
                            for iaxis, mi_i in enumerate(mi))

                    result[i] += (
                        - mi_power(avec, derivative_mi) * mi[idim]
                        * dir_vec[idim])
            for i, mi in enumerate(coeff_identifiers):
                result[i] /= (mi_factorial(mi) * rscale ** sum(mi))
        else:
            avec = avec * rscale**-1

            result = [
                    mi_power(avec, mi) / mi_factorial(mi)
                    for mi in self.get_full_coefficient_identifiers()]
        return (
            self.derivative_wrangler.get_stored_mpole_coefficients_from_full(
                result, rscale))
コード例 #17
0
ファイル: bench_translations.py プロジェクト: inducer/sumpy
    def track_m2l_op_count(self, param):
        knl = self.knl(param.dim)
        m_expn = self.mpole_expn_class(knl, order=param.order)
        l_expn = self.local_expn_class(knl, order=param.order)

        src_coeff_exprs = [sym.Symbol("src_coeff%d" % i)
                for i in range(len(m_expn))]
        dvec = sym.make_sym_vector("d", knl.dim)
        src_rscale = sym.Symbol("src_rscale")
        tgt_rscale = sym.Symbol("tgt_rscale")
        result = l_expn.translate_from(m_expn, src_coeff_exprs, src_rscale,
                                       dvec, tgt_rscale)
        sac = SymbolicAssignmentCollection()
        for i, expr in enumerate(result):
            sac.assign_unique("coeff%d" % i, expr)
        sac.run_global_cse()
        insns = to_loopy_insns(six.iteritems(sac.assignments))
        counter = pymbolic.mapper.flop_counter.CSEAwareFlopCounter()

        return sum([counter.rec(insn.expression)+1 for insn in insns])
コード例 #18
0
    def track_m2l_op_count(self, param):
        knl = self.knl(param.dim)
        m_expn = self.mpole_expn_class(knl, order=param.order)
        l_expn = self.local_expn_class(knl, order=param.order)

        src_coeff_exprs = [
            sym.Symbol("src_coeff%d" % i) for i in range(len(m_expn))
        ]
        dvec = sym.make_sym_vector("d", knl.dim)
        src_rscale = sym.Symbol("src_rscale")
        tgt_rscale = sym.Symbol("tgt_rscale")
        result = l_expn.translate_from(m_expn, src_coeff_exprs, src_rscale,
                                       dvec, tgt_rscale)
        sac = SymbolicAssignmentCollection()
        for i, expr in enumerate(result):
            sac.assign_unique("coeff%d" % i, expr)
        sac.run_global_cse()
        insns = to_loopy_insns(six.iteritems(sac.assignments))
        counter = pymbolic.mapper.flop_counter.CSEAwareFlopCounter()

        return sum([counter.rec(insn.expression) + 1 for insn in insns])
コード例 #19
0
    def get_kernel(self):
        from sumpy.symbolic import make_sym_vector

        avec = make_sym_vector("a", self.dim)
        bvec = make_sym_vector("b", self.dim)

        from sumpy.assignment_collection import SymbolicAssignmentCollection
        sac = SymbolicAssignmentCollection()

        logger.info("compute expansion expressions: start")

        result_names = [
            expand(i, sac, expn, avec, bvec)
            for i, expn in enumerate(self.expansions)
        ]

        logger.info("compute expansion expressions: done")

        sac.run_global_cse()

        from sumpy.codegen import to_loopy_insns
        loopy_insns = to_loopy_insns(
            six.iteritems(sac.assignments),
            vector_names=set(["a", "b"]),
            pymbolic_expr_maps=[
                expn.kernel.get_code_transformer() for expn in self.expansions
            ],
            retain_names=result_names,
            complex_dtype=np.complex128  # FIXME
        )

        isrc_sym = var("isrc")
        exprs = [
            var(name) * self.get_strength_or_not(isrc_sym, i)
            for i, name in enumerate(result_names)
        ]

        from sumpy.tools import gather_loopy_source_arguments
        arguments = (self.get_src_tgt_arguments() +
                     self.get_input_and_output_arguments() +
                     gather_loopy_source_arguments(self.kernels))

        loopy_knl = lp.make_kernel(
            "{[isrc,itgt,idim]: 0<=itgt<ntargets and 0<=isrc<nsources "
            "and 0<=idim<dim}",
            self.get_kernel_scaling_assignments() + ["for itgt, isrc"] +
            [self.get_compute_a_and_b_vecs()] + loopy_insns + [
                lp.Assignment(id=None,
                              assignee="pair_result_%d" % i,
                              expression=expr,
                              temp_var_type=lp.auto)
                for i, (expr,
                        dtype) in enumerate(zip(exprs, self.value_dtypes))
            ] + ["end"] + self.get_result_store_instructions(),
            arguments,
            name=self.name,
            assumptions="nsources>=1 and ntargets>=1",
            default_offset=lp.auto,
            silenced_warnings="write_race(write_lpot*)",
            fixed_parameters=dict(dim=self.dim))

        loopy_knl = lp.tag_inames(loopy_knl, "idim*:unr")

        for expn in self.expansions:
            loopy_knl = expn.prepare_loopy_kernel(loopy_knl)

        loopy_knl = lp.tag_array_axes(loopy_knl, "center", "sep,C")

        return loopy_knl
コード例 #20
0
ファイル: test_kernels.py プロジェクト: benSepanski/sumpy
def test_m2m_and_l2l_exprs_simpler(base_knl, local_expn_class,
                                   mpole_expn_class, order,
                                   with_source_derivative):

    from sympy.core.cache import clear_cache
    clear_cache()

    np.random.seed(17)

    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

    mpole_expn = mpole_expn_class(knl, order=order)
    local_expn = local_expn_class(knl, order=order)

    from sumpy.symbolic import make_sym_vector, Symbol, USE_SYMENGINE
    dvec = make_sym_vector("d", knl.dim)
    src_coeff_exprs = [
        Symbol("src_coeff%d" % i) for i in range(len(mpole_expn))
    ]

    src_rscale = 3
    tgt_rscale = 2

    faster_m2m = mpole_expn.translate_from(mpole_expn, src_coeff_exprs,
                                           src_rscale, dvec, tgt_rscale)
    slower_m2m = mpole_expn.translate_from(mpole_expn,
                                           src_coeff_exprs,
                                           src_rscale,
                                           dvec,
                                           tgt_rscale,
                                           _fast_version=False)

    def _check_equal(expr1, expr2):
        if USE_SYMENGINE:
            return float((expr1 - expr2).expand()) == 0.0
        else:
            # with sympy we are using UnevaluatedExpr and expand doesn't expand it
            # Running doit replaces UnevaluatedExpr with evaluated exprs
            return float((expr1 - expr2).doit().expand()) == 0.0

    for expr1, expr2 in zip(faster_m2m, slower_m2m):
        assert _check_equal(expr1, expr2)

    faster_l2l = local_expn.translate_from(local_expn, src_coeff_exprs,
                                           src_rscale, dvec, tgt_rscale)
    slower_l2l = local_expn.translate_from(local_expn,
                                           src_coeff_exprs,
                                           src_rscale,
                                           dvec,
                                           tgt_rscale,
                                           _fast_version=False)
    for expr1, expr2 in zip(faster_l2l, slower_l2l):
        assert _check_equal(expr1, expr2)