Ejemplo n.º 1
0
def sym_wave(dim, sym_phi):
    """Return symbolic expressions for the wave equation system given a desired
    solution. (Note: In order to support manufactured solutions, we modify the wave
    equation to add a source term (f). If the solution is exact, this term should
    be 0.)
    """

    sym_c = pmbl.var("c")
    sym_coords = prim.make_sym_vector("x", dim)
    sym_t = pmbl.var("t")

    # f = phi_tt - c^2 * div(grad(phi))
    sym_f = sym.diff(sym_t)(sym.diff(sym_t)(sym_phi)) - sym_c**2\
                * sym.div(sym.grad(dim, sym_phi))

    # u = phi_t
    sym_u = sym.diff(sym_t)(sym_phi)

    # v = c*grad(phi)
    sym_v = [sym_c * sym.diff(sym_coords[i])(sym_phi) for i in range(dim)]

    # rhs(u part) = c*div(v) + f
    # rhs(v part) = c*grad(u)
    sym_rhs = flat_obj_array(sym_c * sym.div(sym_v) + sym_f,
                             make_obj_array([sym_c]) * sym.grad(dim, sym_u))

    return sym_u, sym_v, sym_f, sym_rhs
Ejemplo n.º 2
0
def sym_grad(dim, expr):
    if isinstance(expr, ConservedVars):
        return make_conserved(dim, q=sym_grad(dim, expr.join()))
    elif isinstance(expr, np.ndarray):
        return np.stack(obj_array_vectorize(lambda e: sym.grad(dim, e), expr))
    else:
        return sym.grad(dim, expr)
Ejemplo n.º 3
0
    def get_boundaries(discr, actx, t):
        nodes = thaw(actx, discr.nodes())

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

        exact_u = sym_eval(sym_u)
        exact_grad_u = make_obj_array(sym_eval(sym.grad(dim, sym_u)))

        boundaries = {}

        for i in range(dim - 1):
            lower_btag = DTAG_BOUNDARY("-" + str(i))
            upper_btag = DTAG_BOUNDARY("+" + str(i))
            upper_grad_u = discr.project("vol", upper_btag, exact_grad_u)
            normal = thaw(actx, discr.normal(upper_btag))
            upper_grad_u_dot_n = np.dot(upper_grad_u, normal)
            boundaries[lower_btag] = NeumannDiffusionBoundary(0.)
            boundaries[upper_btag] = NeumannDiffusionBoundary(
                upper_grad_u_dot_n)

        lower_btag = DTAG_BOUNDARY("-" + str(dim - 1))
        upper_btag = DTAG_BOUNDARY("+" + str(dim - 1))
        upper_u = discr.project("vol", upper_btag, exact_u)
        boundaries[lower_btag] = DirichletDiffusionBoundary(0.)
        boundaries[upper_btag] = DirichletDiffusionBoundary(upper_u)

        return boundaries
Ejemplo n.º 4
0
    def get_boundaries(self, discr, actx, t):
        nodes = thaw(actx, discr.nodes())

        sym_exact_u = self.get_solution(pmbl.make_sym_vector("x", self.dim),
                                        pmbl.var("t"))

        exact_u = _sym_eval(sym_exact_u, x=nodes, t=t)
        exact_grad_u = _sym_eval(sym.grad(self.dim, sym_exact_u), x=nodes, t=t)

        boundaries = {}

        for i in range(self.dim - 1):
            lower_btag = DTAG_BOUNDARY("-" + str(i))
            upper_btag = DTAG_BOUNDARY("+" + str(i))
            upper_grad_u = discr.project("vol", upper_btag, exact_grad_u)
            normal = thaw(actx, discr.normal(upper_btag))
            upper_grad_u_dot_n = np.dot(upper_grad_u, normal)
            boundaries[lower_btag] = NeumannDiffusionBoundary(0.)
            boundaries[upper_btag] = NeumannDiffusionBoundary(
                upper_grad_u_dot_n)
        lower_btag = DTAG_BOUNDARY("-" + str(self.dim - 1))
        upper_btag = DTAG_BOUNDARY("+" + str(self.dim - 1))
        upper_u = discr.project("vol", upper_btag, exact_u)
        boundaries[lower_btag] = DirichletDiffusionBoundary(0.)
        boundaries[upper_btag] = DirichletDiffusionBoundary(upper_u)

        return boundaries
Ejemplo n.º 5
0
def test_symbolic_grad():
    """
    Compute the symbolic gradient of an expression and compare it to an expected
    result.
    """
    sym_coords = pmbl.make_sym_vector("x", 3)
    sym_x = sym_coords[0]
    sym_y = sym_coords[1]

    sym_f = sym_x**2 * sym_y

    sym_grad_f = sym.grad(3, sym_f)
    expected_sym_grad_f = make_obj_array([sym_y * 2 * sym_x, sym_x**2, 0])
    assert (sym_grad_f == expected_sym_grad_f).all()
Ejemplo n.º 6
0
    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)
        }
Ejemplo n.º 7
0
def sym_diffusion(dim, sym_alpha, sym_u):
    """Return a symbolic expression for the diffusion operator applied to a function.
    """
    return sym.div([sym_alpha * grad_i for grad_i in sym.grad(dim, sym_u)])
Ejemplo n.º 8
0
def sym_diffusion(dim, alpha, sym_u):
    """Return a symbolic expression for the diffusion operator applied to a function.
    """
    return alpha * sym.div(sym.grad(dim, sym_u))