Beispiel #1
0
    def __init__(self, dim=None, helmholtz_k_name="k",
            allow_evanescent=False):
        """
        :arg helmholtz_k_name: The argument name to use for the Helmholtz
            parameter when generating functions to evaluate this kernel.
        """
        k = var(helmholtz_k_name)

        # Guard against code using the old positional interface.
        assert isinstance(allow_evanescent, bool)

        if dim == 2:
            r = pymbolic_real_norm_2(make_sym_vector("d", dim))
            expr = var("hankel_1")(0, k*r)
            scaling = var("I")/4
        elif dim == 3:
            r = pymbolic_real_norm_2(make_sym_vector("d", dim))
            expr = var("exp")(var("I")*k*r)/r
            scaling = 1/(4*var("pi"))
        elif dim is None:
            expr = None
            scaling = None
        else:
            raise RuntimeError("unsupported dimensionality")

        ExpressionKernel.__init__(
                self,
                dim,
                expression=expr,
                scaling=scaling,
                is_complex_valued=True)

        self.helmholtz_k_name = helmholtz_k_name
        self.allow_evanescent = allow_evanescent
Beispiel #2
0
    def __init__(self, dim=None, icomp=None, jcomp=None, viscosity_mu_name="mu",
                        stresslet_vector_name="stresslet_vec"):
        """
        :arg viscosity_mu_name: The argument name to use for
                dynamic viscosity :math:`\mu` the then generating functions to
                evaluate this kernel.
        """
        # Mu is unused but kept for consistency with the stokeslet.

        if dim == 2:
            d = make_sym_vector("d", dim)
            n = make_sym_vector(stresslet_vector_name, dim)
            r = pymbolic_real_norm_2(d)
            expr = (
                sum(n[axis]*d[axis] for axis in range(dim))
                *
                d[icomp]*d[jcomp]/r**4
                )
            scaling = 1/(var("pi"))

        elif dim == 3:
            d = make_sym_vector("d", dim)
            n = make_sym_vector(stresslet_vector_name, dim)
            r = pymbolic_real_norm_2(d)
            expr = (
                sum(n[axis]*d[axis] for axis in range(dim))
                *
                d[icomp]*d[jcomp]/r**5
                )
            scaling = -3/(4*var("pi"))

        elif dim is None:
            expr = None
            scaling = None
        else:
            raise RuntimeError("unsupported dimensionality")

        self.viscosity_mu_name = viscosity_mu_name
        self.stresslet_vector_name = stresslet_vector_name
        self.icomp = icomp
        self.jcomp = jcomp

        ExpressionKernel.__init__(
                self,
                dim,
                expression=expr,
                scaling=scaling,
                is_complex_valued=False)
Beispiel #3
0
    def get_kernel():
        from sumpy.symbolic import pymbolic_real_norm_2
        from pymbolic.primitives import make_sym_vector
        from pymbolic import var

        d = make_sym_vector("d", 3)
        r = pymbolic_real_norm_2(d[:-1])
        # r3d = pymbolic_real_norm_2(d)
        #expr = var("log")(r3d)

        log = var("log")
        sqrt = var("sqrt")

        a = d[-1]

        expr = log(r)
        expr = log(sqrt(r**2 + a**2))
        expr = log(sqrt(r + a**2))
        #expr = log(sqrt(r**2 + a**2))-a**2/2/(r**2+a**2)
        #expr = 2*log(sqrt(r**2 + a**2))

        scaling = 1/(2*var("pi"))

        from sumpy.kernel import ExpressionKernel
        return ExpressionKernel(
                dim=3,
                expression=expr,
                global_scaling_const=scaling,
                is_complex_valued=False)
Beispiel #4
0
    def __init__(self, dim=None, yukawa_lambda_name="lam"):
        """
        :arg yukawa_lambda_name: The argument name to use for the Yukawa
            parameter when generating functions to evaluate this kernel.
        """
        lam = var(yukawa_lambda_name)

        if dim == 2:
            r = pymbolic_real_norm_2(make_sym_vector("d", dim))

            # http://dlmf.nist.gov/10.27#E8
            expr = var("hankel_1")(0, var("I")*lam*r)
            scaling_for_K0 = 1/2*var("pi")*var("I")  # noqa: N806

            scaling = -1/(2*var("pi")) * scaling_for_K0
        else:
            raise RuntimeError("unsupported dimensionality")

        super(YukawaKernel, self).__init__(
                dim,
                expression=expr,
                global_scaling_const=scaling,
                is_complex_valued=True)

        self.yukawa_lambda_name = yukawa_lambda_name
Beispiel #5
0
    def __init__(self, dim=None):
        # See (Kress LIE, Thm 6.2) for scaling
        if dim == 2:
            r = pymbolic_real_norm_2(make_sym_vector("d", dim))
            expr = var("log")(r)
            scaling = 1/(-2*var("pi"))
        elif dim == 3:
            r = pymbolic_real_norm_2(make_sym_vector("d", dim))
            expr = 1/r
            scaling = 1/(4*var("pi"))
        else:
            raise NotImplementedError("unsupported dimensionality")

        super(LaplaceKernel, self).__init__(
                dim,
                expression=expr,
                global_scaling_const=scaling,
                is_complex_valued=False)
Beispiel #6
0
    def __init__(self, dim, icomp, jcomp, viscosity_mu_name="mu"):
        """
        :arg viscosity_mu_name: The argument name to use for
                dynamic viscosity :math:`\mu` the then generating functions to
                evaluate this kernel.
        """
        mu = var(viscosity_mu_name)

        if dim == 2:
            d = make_sym_vector("d", dim)
            r = pymbolic_real_norm_2(d)
            expr = (
                -var("log")(r)*(1 if icomp == jcomp else 0)
                +
                d[icomp]*d[jcomp]/r**2
                )
            scaling = 1/(4*var("pi")*mu)

        elif dim == 3:
            d = make_sym_vector("d", dim)
            r = pymbolic_real_norm_2(d)
            expr = (
                (1/r)*(1 if icomp == jcomp else 0)
                +
                d[icomp]*d[jcomp]/r**3
                )
            scaling = -1/(8*var("pi")*mu)

        elif dim is None:
            expr = None
            scaling = None
        else:
            raise RuntimeError("unsupported dimensionality")

        self.viscosity_mu_name = viscosity_mu_name
        self.icomp = icomp
        self.jcomp = jcomp

        ExpressionKernel.__init__(
                self,
                dim,
                expression=expr,
                scaling=scaling,
                is_complex_valued=False)
Beispiel #7
0
def _norm_inf_op(discr, num_components):
    from pytential import sym, bind
    if num_components is not None:
        from pymbolic.primitives import make_sym_vector
        v = make_sym_vector("arg", num_components)
        max_arg = sym.abs(v)
    else:
        max_arg = sym.abs(sym.var("arg"))

    return bind(discr, sym.NodeMax(max_arg))
Beispiel #8
0
def _norm_op(discr, num_components):
    from pytential import sym, bind
    if num_components is not None:
        from pymbolic.primitives import make_sym_vector
        v = make_sym_vector("integrand", num_components)
        integrand = sym.real(np.dot(sym.conj(v), v))
    else:
        integrand = sym.abs(sym.var("integrand"))**2

    return bind(discr, sym.integral(integrand))
Beispiel #9
0
    def __init__(self, dim=None, icomp=None, jcomp=None, kcomp=None,
                        viscosity_mu_name="mu"):
        r"""
        :arg viscosity_mu_name: The argument name to use for
                dynamic viscosity :math:`\mu` the then generating functions to
                evaluate this kernel.
        """
        # Mu is unused but kept for consistency with the stokeslet.

        if dim == 2:
            d = make_sym_vector("d", dim)
            r = pymbolic_real_norm_2(d)
            expr = (
                d[icomp]*d[jcomp]*d[kcomp]/r**4
                )
            scaling = 1/(var("pi"))

        elif dim == 3:
            d = make_sym_vector("d", dim)
            r = pymbolic_real_norm_2(d)
            expr = (
                d[icomp]*d[jcomp]*d[kcomp]/r**5
                )
            scaling = 3/(4*var("pi"))

        elif dim is None:
            expr = None
            scaling = None
        else:
            raise RuntimeError("unsupported dimensionality")

        self.viscosity_mu_name = viscosity_mu_name
        self.icomp = icomp
        self.jcomp = jcomp
        self.kcomp = kcomp

        super(StressletKernel, self).__init__(
                dim,
                expression=expr,
                global_scaling_const=scaling,
                is_complex_valued=False)
Beispiel #10
0
    def __init__(self, dim=None):
        # See (Kress LIE, Thm 6.2) for scaling
        if dim == 2:
            r = pymbolic_real_norm_2(make_sym_vector("d", dim))
            expr = var("log")(r)
            scaling = 1/(-2*var("pi"))
        elif dim == 3:
            r = pymbolic_real_norm_2(make_sym_vector("d", dim))
            expr = 1/r
            scaling = 1/(4*var("pi"))
        elif dim is None:
            expr = None
            scaling = None
        else:
            raise RuntimeError("unsupported dimensionality")

        ExpressionKernel.__init__(
                self,
                dim,
                expression=expr,
                scaling=scaling,
                is_complex_valued=False)
Beispiel #11
0
    def get_kernel():
        from sumpy.symbolic import pymbolic_real_norm_2
        from pymbolic.primitives import (make_sym_vector, Variable as var)

        r = pymbolic_real_norm_2(make_sym_vector("d", 3))
        expr = var("log")(r)
        scaling = 1/(2*var("pi"))

        from sumpy.kernel import ExpressionKernel
        return ExpressionKernel(
                dim=3,
                expression=expr,
                scaling=scaling,
                is_complex_valued=False)
Beispiel #12
0
    def __init__(self, dim=None):
        r = pymbolic_real_norm_2(make_sym_vector("d", dim))
        if dim == 2:
            expr = r**2 * var("log")(r)
            scaling = 1/(8*var("pi"))
        elif dim == 3:
            expr = r
            scaling = 1  # FIXME: Unknown
        else:
            raise RuntimeError("unsupported dimensionality")

        super(BiharmonicKernel, self).__init__(
                dim,
                expression=expr,
                global_scaling_const=scaling,
                is_complex_valued=False)
Beispiel #13
0
def get_decaying_trig(dim, alpha):
    # 1D: u(x,t) = exp(-alpha*t)*cos(x)
    # 2D: u(x,y,t) = exp(-2*alpha*t)*sin(x)*cos(y)
    # 3D: u(x,y,z,t) = exp(-3*alpha*t)*sin(x)*sin(y)*cos(z)
    # on [-pi/2, pi/2]^{#dims}
    def get_mesh(n):
        dim_names = ["x", "y", "z"]
        neumann_boundaries = []
        for i in range(dim - 1):
            neumann_boundaries += ["+" + dim_names[i], "-" + dim_names[i]]
        dirichlet_boundaries = [
            "+" + dim_names[dim - 1], "-" + dim_names[dim - 1]
        ]
        from meshmode.mesh.generation import generate_regular_rect_mesh
        return generate_regular_rect_mesh(a=(-0.5 * np.pi, ) * dim,
                                          b=(0.5 * np.pi, ) * dim,
                                          n=(n, ) * dim,
                                          boundary_tag_to_face={
                                              "dirichlet":
                                              dirichlet_boundaries,
                                              "neumann": neumann_boundaries
                                          })

    sym_coords = prim.make_sym_vector("x", dim)
    sym_t = pmbl.var("t")
    sym_cos = pmbl.var("cos")
    sym_sin = pmbl.var("sin")
    sym_exp = pmbl.var("exp")
    sym_u = sym_exp(-dim * alpha * sym_t)
    for i in range(dim - 1):
        sym_u *= sym_sin(sym_coords[i])
    sym_u *= sym_cos(sym_coords[dim - 1])

    def get_boundaries(discr, actx, t):
        return {
            grudge_sym.DTAG_BOUNDARY("dirichlet"):
            DirichletDiffusionBoundary(0.),
            grudge_sym.DTAG_BOUNDARY("neumann"): NeumannDiffusionBoundary(0.),
        }

    return HeatProblem(dim, alpha, get_mesh, sym_u, get_boundaries)
Beispiel #14
0
    def __init__(self, dim=None, yukawa_lambda_name="lam"):
        """
        :arg yukawa_lambda_name: The argument name to use for the Yukawa
            parameter when generating functions to evaluate this kernel.
        """
        lam = var(yukawa_lambda_name)

        # NOTE: The Yukawa kernel is given by [1]
        #   -1/(2 pi)**(n/2) * (lam/r)**(n/2-1) * K(n/2-1, lam r)
        # where K is a modified Bessel function of the second kind.
        #
        # [1] https://en.wikipedia.org/wiki/Green%27s_function
        # [2] http://dlmf.nist.gov/10.27#E8
        # [3] https://dlmf.nist.gov/10.47#E2
        # [4] https://dlmf.nist.gov/10.49

        r = pymbolic_real_norm_2(make_sym_vector("d", dim))
        if dim == 2:
            # NOTE: transform K(0, lam r) into a Hankel function using [2]
            expr = var("hankel_1")(0, var("I")*lam*r)
            scaling_for_K0 = var("pi")/2*var("I")       # noqa: N806

            scaling = -1/(2*var("pi")) * scaling_for_K0
        elif dim == 3:
            # NOTE: to get the expression, we do the following and simplify
            # 1. express K(1/2, lam r) as a modified spherical Bessel function
            #   k(0, lam r) using [3] and use expression for k(0, lam r) from [4]
            # 2. or use (AS 10.2.17) directly
            expr = var("exp")(-lam*r) / r

            scaling = -1/(4 * var("pi")**2)
        else:
            raise RuntimeError("unsupported dimensionality")

        super(YukawaKernel, self).__init__(
                dim,
                expression=expr,
                global_scaling_const=scaling,
                is_complex_valued=True)

        self.yukawa_lambda_name = yukawa_lambda_name
Beispiel #15
0
    def __init__(self, dim=None):
        r = pymbolic_real_norm_2(make_sym_vector("d", dim))
        if dim == 2:
            # Ref: Farkas, Peter. Mathematical foundations for fast algorithms
            # for the biharmonic equation. Technical Report 765,
            # Department of Computer Science, Yale University, 1990.
            expr = r**2 * var("log")(r)
            scaling = 1 / (8 * var("pi"))
        elif dim == 3:
            # Ref: Jiang, Shidong, Bo Ren, Paul Tsuji, and Lexing Ying.
            # "Second kind integral equations for the first kind Dirichlet problem
            #  of the biharmonic equation in three dimensions."
            # Journal of Computational Physics 230, no. 19 (2011): 7488-7501.
            expr = r
            scaling = -1 / (8 * var("pi"))
        else:
            raise RuntimeError("unsupported dimensionality")

        super().__init__(dim,
                         expression=expr,
                         global_scaling_const=scaling,
                         is_complex_valued=False)
Beispiel #16
0
    def run_symbolic_step(self, phase_name, shapes=None):
        """
        `shapes` maps variable names to vector lengths.
        """
        if shapes is None:
            shapes = {}
        phase = self.code.phases[phase_name]

        from pymbolic import var

        self.context.clear()
        from pymbolic.primitives import make_sym_vector

        # Includes variables expanded into vector components
        components = []
        # Initial values, as variables / subscripts. Matched with "components"
        initial_vals = []
        for vname in self.variables:
            if vname in shapes and shapes[vname] > 1:
                ival = make_sym_vector(vname+"_0", shapes[vname])
                initial_vals.extend(ival)
                names = [self.VectorComponent(vname, i) for i in range(len(ival))]
                components.extend(names)
            else:
                ival = var(vname+"_0")
                initial_vals.append(ival)
                components.append(vname)
            self.context[vname] = ival

        self.context["<dt>"] = var("<dt>")
        self.context["<t>"] = 0

        self.exec_controller.reset()
        self.exec_controller.update_plan(phase, phase.depends_on)
        for _event in self.exec_controller(phase, self):
            pass

        return components, initial_vals
Beispiel #17
0
def get_static_trig_var_diff(dim):
    def get_mesh(n):
        return get_box_mesh(dim, -0.5 * np.pi, 0.5 * np.pi, n)

    sym_coords = prim.make_sym_vector("x", dim)
    sym_cos = pmbl.var("cos")
    sym_sin = pmbl.var("sin")

    sym_alpha = 1
    for i in range(dim):
        sym_alpha *= sym_cos(3. * sym_coords[i])
    sym_alpha = 1 + 0.2 * sym_alpha

    sym_u = 1
    for i in range(dim - 1):
        sym_u *= sym_sin(sym_coords[i])
    sym_u *= sym_cos(sym_coords[dim - 1])

    def get_boundaries(discr, actx, t):
        boundaries = {}

        for i in range(dim - 1):
            boundaries[DTAG_BOUNDARY("-" +
                                     str(i))] = NeumannDiffusionBoundary(0.)
            boundaries[DTAG_BOUNDARY("+" +
                                     str(i))] = NeumannDiffusionBoundary(0.)

        boundaries[DTAG_BOUNDARY("-" +
                                 str(dim -
                                     1))] = DirichletDiffusionBoundary(0.)
        boundaries[DTAG_BOUNDARY("+" +
                                 str(dim -
                                     1))] = DirichletDiffusionBoundary(0.)

        return boundaries

    return HeatProblem(dim, get_mesh, sym_alpha, sym_u, get_boundaries)
Beispiel #18
0
    def __init__(self, dim=None, yukawa_lambda_name="lam"):
        """
        :arg yukawa_lambda_name: The argument name to use for the Yukawa
            parameter when generating functions to evaluate this kernel.
        """
        lam = var(yukawa_lambda_name)

        if dim == 2:
            r = pymbolic_real_norm_2(make_sym_vector("d", dim))

            # http://dlmf.nist.gov/10.27#E8
            expr = var("hankel_1")(0, var("I") * lam * r)
            scaling_for_K0 = 1 / 2 * var("pi") * var("I")  # noqa: N806

            scaling = -1 / (2 * var("pi")) * scaling_for_K0
        else:
            raise RuntimeError("unsupported dimensionality")

        super(YukawaKernel, self).__init__(dim,
                                           expression=expr,
                                           global_scaling_const=scaling,
                                           is_complex_valued=True)

        self.yukawa_lambda_name = yukawa_lambda_name
Beispiel #19
0
 def map_multivector_field(self, expr):
     from pymbolic.primitives import make_sym_vector
     return MultiVector(
             make_sym_vector(
                 expr.name, self.ambient_dim,
                 var_class=p.Field))
Beispiel #20
0
 def map_multivector_variable(self, expr):
     from pymbolic.primitives import make_sym_vector
     return MultiVector(
         make_sym_vector(expr.name,
                         self.ambient_dim,
                         var_factory=type(expr)))
Beispiel #21
0
def grad(dim, func):
    """Return the symbolic *dim*-dimensional gradient of *func*."""
    coords = prim.make_sym_vector("x", dim)
    return [diff(coords[i])(func) for i in range(dim)]
Beispiel #22
0
def get_decaying_trig_truncated_domain(dim, alpha):
    # 1D: u(x,t) = exp(-alpha*t)*cos(x)
    # 2D: u(x,y,t) = exp(-2*alpha*t)*sin(x)*cos(y)
    # 3D: u(x,y,z,t) = exp(-3*alpha*t)*sin(x)*sin(y)*cos(z)
    # on [-pi/2, pi/4]^{#dims}
    def get_mesh(n):
        dim_names = ["x", "y", "z"]
        neumann_lower_boundaries = ["-" + dim_names[i] for i in range(dim - 1)]
        neumann_upper_boundaries = ["+" + dim_names[i] for i in range(dim - 1)]
        dirichlet_lower_boundaries = ["-" + dim_names[dim - 1]]
        dirichlet_upper_boundaries = ["+" + dim_names[dim - 1]]
        from meshmode.mesh.generation import generate_regular_rect_mesh
        return generate_regular_rect_mesh(a=(-0.5 * np.pi, ) * dim,
                                          b=(0.25 * np.pi, ) * dim,
                                          n=(n, ) * dim,
                                          boundary_tag_to_face={
                                              "dirichlet_lower":
                                              dirichlet_lower_boundaries,
                                              "dirichlet_upper":
                                              dirichlet_upper_boundaries,
                                              "neumann_lower":
                                              neumann_lower_boundaries,
                                              "neumann_upper":
                                              neumann_upper_boundaries
                                          })

    sym_coords = prim.make_sym_vector("x", dim)
    sym_t = pmbl.var("t")
    sym_cos = pmbl.var("cos")
    sym_sin = pmbl.var("sin")
    sym_exp = pmbl.var("exp")
    sym_u = sym_exp(-dim * alpha * sym_t)
    for i in range(dim - 1):
        sym_u *= sym_sin(sym_coords[i])
    sym_u *= sym_cos(sym_coords[dim - 1])

    def get_boundaries(discr, actx, t):
        nodes = thaw(actx, discr.nodes())

        def sym_eval(expr):
            return sym.EvaluationMapper({"x": nodes, "t": t})(expr)

        dirichlet_lower_btag = grudge_sym.DTAG_BOUNDARY("dirichlet_lower")
        dirichlet_upper_btag = grudge_sym.DTAG_BOUNDARY("dirichlet_upper")
        neumann_lower_btag = grudge_sym.DTAG_BOUNDARY("neumann_lower")
        neumann_upper_btag = grudge_sym.DTAG_BOUNDARY("neumann_upper")
        exact_u = sym_eval(sym_u)
        exact_grad_u = make_obj_array(sym_eval(sym.grad(dim, sym_u)))
        upper_u = discr.project("vol", dirichlet_upper_btag, exact_u)
        upper_grad_u = discr.project("vol", neumann_upper_btag, exact_grad_u)
        normal = thaw(actx, discr.normal(neumann_upper_btag))
        upper_grad_u_dot_n = np.dot(upper_grad_u, normal)

        return {
            dirichlet_lower_btag: DirichletDiffusionBoundary(0.),
            dirichlet_upper_btag: DirichletDiffusionBoundary(upper_u),
            neumann_lower_btag: NeumannDiffusionBoundary(0.),
            neumann_upper_btag: NeumannDiffusionBoundary(upper_grad_u_dot_n)
        }

    return HeatProblem(dim, alpha, get_mesh, sym_u, get_boundaries)
Beispiel #23
0
 def map_multivector_variable(self, expr):
     from pymbolic.primitives import make_sym_vector
     return MultiVector(
             make_sym_vector(expr.name, self.ambient_dim,
                 var_factory=type(expr)))
Beispiel #24
0
def make_sym_mv(name, num_components):
    return MultiVector(make_sym_vector(name, num_components))