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 test_symbolic_diff(sym_f, expected_sym_df):
    """
    Compute the symbolic derivative of an expression and compare it to an
    expected result.
    """
    sym_df = sym.diff(pmbl.var("x"))(sym_f)
    assert sym_df == expected_sym_df
Ejemplo n.º 3
0
def test_diffusion_accuracy(actx_factory,
                            problem,
                            nsteps,
                            dt,
                            scales,
                            order,
                            visualize=False):
    """
    Checks the accuracy of the diffusion operator by solving the heat equation for a
    given problem setup.
    """
    actx = actx_factory()

    p = problem

    sym_diffusion_u = sym_diffusion(p.dim, p.sym_alpha, p.sym_u)

    # In order to support manufactured solutions, we modify the heat equation
    # to add a source term f. If the solution is exact, this term should be 0.
    sym_t = pmbl.var("t")
    sym_f = sym.diff(sym_t)(p.sym_u) - sym_diffusion_u

    from pytools.convergence import EOCRecorder
    eoc_rec = EOCRecorder()

    for n in scales:
        mesh = p.get_mesh(n)

        from grudge.eager import EagerDGDiscretization
        from meshmode.discretization.poly_element import \
                QuadratureSimplexGroupFactory, \
                PolynomialWarpAndBlendGroupFactory
        discr = EagerDGDiscretization(
            actx,
            mesh,
            discr_tag_to_group_factory={
                DISCR_TAG_BASE: PolynomialWarpAndBlendGroupFactory(order),
                DISCR_TAG_QUAD: QuadratureSimplexGroupFactory(3 * order),
            })

        nodes = thaw(actx, discr.nodes())

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

        alpha = sym_eval(p.sym_alpha, 0.)

        if isinstance(alpha, DOFArray):
            discr_tag = DISCR_TAG_QUAD
        else:
            discr_tag = DISCR_TAG_BASE

        def get_rhs(t, u):
            return (
                diffusion_operator(discr,
                                   quad_tag=discr_tag,
                                   alpha=alpha,
                                   boundaries=p.get_boundaries(discr, actx, t),
                                   u=u) + sym_eval(sym_f, t))

        t = 0.

        u = sym_eval(p.sym_u, t)

        from mirgecom.integrators import rk4_step

        for _ in range(nsteps):
            u = rk4_step(u, t, dt, get_rhs)
            t += dt

        expected_u = sym_eval(p.sym_u, t)

        rel_linf_err = (discr.norm(u - expected_u, np.inf) /
                        discr.norm(expected_u, np.inf))
        eoc_rec.add_data_point(1. / n, rel_linf_err)

        if visualize:
            from grudge.shortcuts import make_visualizer
            vis = make_visualizer(discr, discr.order + 3)
            vis.write_vtk_file(
                "diffusion_accuracy_{order}_{n}.vtu".format(order=order, n=n),
                [
                    ("u", u),
                    ("expected_u", expected_u),
                ])

    print("L^inf error:")
    print(eoc_rec)
    # Expected convergence rates from Hesthaven/Warburton book
    expected_order = order + 1 if order % 2 == 0 else order
    assert (eoc_rec.order_estimate() >= expected_order - 0.5
            or eoc_rec.max_error() < 1e-11)