Ejemplo n.º 1
0
def test_eoc():
    np = pytest.importorskip("numpy")

    from pytools.convergence import EOCRecorder
    eoc = EOCRecorder()

    # {{{ test pretty_print

    for i in range(1, 8):
        eoc.add_data_point(1.0 / i, 10**(-i))

    p = eoc.pretty_print()
    print(p)
    print()

    p = eoc.pretty_print(abscissa_format="%.5e",
                         error_format="%.5e",
                         eoc_format="%5.2f")
    print(p)

    # }}}

    # {{{ test merging

    from pytools.convergence import stringify_eocs
    p = stringify_eocs(eoc, eoc, eoc, names=("First", "Second", "Third"))
    print(p)

    # }}}

    # {{{ test invalid inputs

    import numpy as np

    eoc = EOCRecorder()

    # scalar inputs are fine
    eoc.add_data_point(1, 1)
    eoc.add_data_point(1.0, 1.0)
    eoc.add_data_point(np.float32(1.0), 1.0)
    eoc.add_data_point(np.array(3), 1.0)
    eoc.add_data_point(1.0, np.array(3))

    # non-scalar inputs are not fine though
    with pytest.raises(TypeError):
        eoc.add_data_point(np.array([3]), 1.0)

    with pytest.raises(TypeError):
        eoc.add_data_point(1.0, np.array([3]))
Ejemplo n.º 2
0
def test_integration_order(integrator, method_order):
    """Test that time integrators have correct order."""
    def exact_soln(t):
        return np.exp(-t)

    def rhs(t, state):
        return -np.exp(-t)

    from pytools.convergence import EOCRecorder
    integrator_eoc = EOCRecorder()

    dt = 1.0
    for refine in [1, 2, 4, 8]:
        dt = dt / refine
        t = 0
        state = exact_soln(t)

        while t < 4:
            state = integrator(state, t, dt, rhs)
            t = t + dt

        error = np.abs(state - exact_soln(t)) / exact_soln(t)
        integrator_eoc.add_data_point(dt, error)

    logger.info(f"Time Integrator EOC:\n = {integrator_eoc}")
    assert integrator_eoc.order_estimate() >= method_order - .01
Ejemplo n.º 3
0
def test_strang_splitting(plot_solution=False):
    from leap.rk import LSRK4Method

    method1 = LSRK4Method("y", rhs_func_name="<func>y1")
    method2 = LSRK4Method("y", rhs_func_name="<func>y2")

    code1 = method1.generate()
    code2 = method2.generate()

    from leap.transform import strang_splitting

    code = strang_splitting(code1, code2, "primary")
    print(code)

    from utils import python_method_impl_codegen

    def exact(t):
        return np.exp(3j * t)

    from pytools.convergence import EOCRecorder
    eocrec = EOCRecorder()

    for dt in 2**-np.array(range(4, 7), dtype=np.float64):  # noqa pylint:disable=invalid-unary-operand-type
        interp = python_method_impl_codegen(code,
                                            function_map={
                                                "<func>y1":
                                                lambda t, y: 1j * y,
                                                "<func>y2":
                                                lambda t, y: 2j * y,
                                            })
        interp.set_up(t_start=0, dt_start=dt, context={"y": 1})

        final_t = 4
        times = []
        values = []
        for event in interp.run(t_end=final_t):
            if isinstance(event, interp.StateComputed):
                values.append(event.state_component)
                times.append(event.t)

        assert abs(times[-1] - final_t) / final_t < 0.1

        times = np.array(times)

        # Check that the timestep is preserved.
        assert np.allclose(np.diff(times), dt)

        if plot_solution:
            import matplotlib.pyplot as pt
            pt.plot(times, values, label="comp")
            pt.plot(times, exact(times), label="true")
            pt.show()

        error = abs(values[-1] - exact(final_t))
        eocrec.add_data_point(dt, error)

    print(eocrec.pretty_print())

    orderest = eocrec.estimate_order_of_convergence()[0, 1]
    assert orderest > 2 * 0.9
Ejemplo n.º 4
0
    def test_leapgen_integration_order(method, method_order):
        """Test that time integrators have correct order."""
        def exact_soln(t):
            return np.exp(-t)

        def rhs(t, y):
            return -np.exp(-t)

        from pytools.convergence import EOCRecorder
        integrator_eoc = EOCRecorder()

        dt = 1.0
        for refine in [1, 2, 4, 8]:
            dt = dt / refine
            t = 0
            state = exact_soln(t)

            t_final = 4
            step = 0

            (step, t, state) = \
                advance_state(rhs=rhs, timestepper=method, dt=dt,
                              state=state, t=t, t_final=t_final,
                              component_id="y")

            error = np.abs(state - exact_soln(t)) / exact_soln(t)
            integrator_eoc.add_data_point(dt, error)

        logger.info(f"Time Integrator EOC:\n = {integrator_eoc}")
        assert integrator_eoc.order_estimate() >= method_order - .1
Ejemplo n.º 5
0
def test_dielectric(ctx_factory, qbx_order, op_class, mode, visualize=False):
    cl_ctx = ctx_factory()
    queue = cl.CommandQueue(cl_ctx)

    import logging
    logging.basicConfig(level=logging.INFO)

    from pytools.convergence import EOCRecorder
    eoc_rec = EOCRecorder()

    for nelements in [30, 50, 70]:
        # prevent sympy cache 'splosion
        from sympy.core.cache import clear_cache
        clear_cache()

        errs = run_dielectric_test(cl_ctx,
                                   queue,
                                   nelements=nelements,
                                   qbx_order=qbx_order,
                                   op_class=op_class,
                                   mode=mode,
                                   visualize=visualize)

        eoc_rec.add_data_point(1 / nelements, la.norm(list(errs), np.inf))

    print(eoc_rec)
    assert eoc_rec.order_estimate() > qbx_order - 0.5
Ejemplo n.º 6
0
def get_convergence_data(method_class, problem, dts=_default_dts):
    from pytools.convergence import EOCRecorder

    eocrec = EOCRecorder()

    component_id = "y"

    for dt in dts:
        t = problem.t_start
        y = problem.initial()
        final_t = problem.t_end

        interp = method_class(function_map={
            "<func>f": problem,
        })
        interp.set_up(t_start=t, dt_start=dt, context={component_id: y})

        times = []
        values = []
        for event in interp.run(t_end=final_t):
            if isinstance(event, interp.StateComputed):
                assert event.component_id == component_id
                values.append(event.state_component[0])
                times.append(event.t)

        assert abs(times[-1] - final_t) / final_t < 0.1
        times = np.array(times)

        error = abs(values[-1] - problem.exact(final_t)[0])
        eocrec.add_data_point(dt, error)

    return eocrec
Ejemplo n.º 7
0
def test_exterior_stokes(ctx_factory, ambient_dim, visualize=False):
    if visualize:
        logging.basicConfig(level=logging.INFO)

    from pytools.convergence import EOCRecorder
    eoc = EOCRecorder()

    target_order = 3
    qbx_order = 3

    print(ambient_dim)
    if ambient_dim == 2:
        resolutions = [20, 35, 50]
    elif ambient_dim == 3:
        resolutions = [0, 1, 2]
    else:
        raise ValueError(f"unsupported dimension: {ambient_dim}")

    for resolution in resolutions:
        h_max, err = run_exterior_stokes(ctx_factory,
                                         ambient_dim=ambient_dim,
                                         target_order=target_order,
                                         qbx_order=qbx_order,
                                         resolution=resolution,
                                         visualize=visualize)

        eoc.add_data_point(h_max, err)

    print(eoc)

    # This convergence data is not as clean as it could be. See
    # https://github.com/inducer/pytential/pull/32
    # for some discussion.
    assert eoc.order_estimate() > target_order - 0.5
Ejemplo n.º 8
0
def test_mass_operator_inverse(actx_factory, name):
    actx = actx_factory()

    # {{{ cases

    import mesh_data
    if name == "2-1-ellipse":
        # curve
        builder = mesh_data.EllipseMeshBuilder(radius=3.1, aspect_ratio=2.0)
    elif name == "spheroid":
        # surface
        builder = mesh_data.SpheroidMeshBuilder()
    elif name.startswith("warped_rect"):
        builder = mesh_data.WarpedRectMeshBuilder(dim=int(name[-1]))

    else:
        raise ValueError("unknown geometry name: %s" % name)

    # }}}

    # {{{ inv(m) @ m == id

    from pytools.convergence import EOCRecorder
    eoc = EOCRecorder()

    for resolution in builder.resolutions:
        mesh = builder.get_mesh(resolution, builder.mesh_order)
        dcoll = DiscretizationCollection(actx, mesh, order=builder.order)
        volume_discr = dcoll.discr_from_dd(dof_desc.DD_VOLUME)

        logger.info("ndofs:     %d", volume_discr.ndofs)
        logger.info("nelements: %d", volume_discr.mesh.nelements)

        # {{{ compute inverse mass

        def f(x):
            return actx.np.cos(4.0 * x[0])

        dd = dof_desc.DD_VOLUME
        x_volm = thaw(volume_discr.nodes(), actx)
        f_volm = f(x_volm)
        f_inv = op.inverse_mass(dcoll, op.mass(dcoll, dd, f_volm))

        inv_error = actx.to_numpy(
            op.norm(dcoll, f_volm - f_inv, 2) / op.norm(dcoll, f_volm, 2))

        # }}}

        # compute max element size
        from grudge.dt_utils import h_max_from_volume

        h_max = h_max_from_volume(dcoll)

        eoc.add_data_point(h_max, inv_error)

    logger.info("inverse mass error\n%s", str(eoc))

    # NOTE: both cases give 1.0e-16-ish at the moment, but just to be on the
    # safe side, choose a slightly larger tolerance
    assert eoc.max_error() < 1.0e-14
Ejemplo n.º 9
0
def test_surface_mass_operator_inverse(actx_factory, name):
    actx = actx_factory()

    # {{{ cases

    if name == "2-1-ellipse":
        from mesh_data import EllipseMeshBuilder
        builder = EllipseMeshBuilder(radius=3.1, aspect_ratio=2.0)
    elif name == "spheroid":
        from mesh_data import SpheroidMeshBuilder
        builder = SpheroidMeshBuilder()
    else:
        raise ValueError("unknown geometry name: %s" % name)

    # }}}

    # {{{ convergence

    from pytools.convergence import EOCRecorder
    eoc = EOCRecorder()

    for resolution in builder.resolutions:
        mesh = builder.get_mesh(resolution, builder.mesh_order)
        discr = DiscretizationCollection(actx, mesh, order=builder.order)
        volume_discr = discr.discr_from_dd(dof_desc.DD_VOLUME)

        logger.info("ndofs:     %d", volume_discr.ndofs)
        logger.info("nelements: %d", volume_discr.mesh.nelements)

        # {{{ compute inverse mass

        dd = dof_desc.DD_VOLUME
        sym_f = sym.cos(4.0 * sym.nodes(mesh.ambient_dim, dd)[0])
        sym_op = sym.InverseMassOperator(dd, dd)(sym.MassOperator(dd, dd)(
            sym.var("f")))

        f = bind(discr, sym_f)(actx)
        f_inv = bind(discr, sym_op)(actx, f=f)

        inv_error = bind(
            discr,
            sym.norm(2,
                     sym.var("x") - sym.var("y")) / sym.norm(2, sym.var("y")))(
                         actx, x=f_inv, y=f)

        # }}}

        h_max = bind(
            discr,
            sym.h_max_from_volume(discr.ambient_dim, dim=discr.dim,
                                  dd=dd))(actx)
        eoc.add_data_point(h_max, inv_error)

    # }}}

    logger.info("inverse mass error\n%s", str(eoc))

    # NOTE: both cases give 1.0e-16-ish at the moment, but just to be on the
    # safe side, choose a slightly larger tolerance
    assert eoc.max_error() < 1.0e-14
Ejemplo n.º 10
0
def test_stresslet_identity(actx_factory, cls, visualize=False):
    if visualize:
        logging.basicConfig(level=logging.INFO)

    source_ovsmp = 4 if cls.func.ambient_dim == 2 else 8
    case = cls(fmm_backend=None,
            target_order=5, qbx_order=3, source_ovsmp=source_ovsmp)
    identity = StressletIdentity(case.ambient_dim)
    logger.info("\n%s", str(case))

    from pytools.convergence import EOCRecorder
    eocs = [EOCRecorder() for _ in range(case.ambient_dim)]

    for resolution in case.resolutions:
        h_max, errors = run_stokes_identity(
                actx_factory, case, identity,
                resolution=resolution,
                visualize=visualize)

        for eoc, e in zip(eocs, errors):
            eoc.add_data_point(h_max, e)

    for eoc in eocs:
        print(eoc.pretty_print(
            abscissa_format="%.8e",
            error_format="%.8e",
            eoc_format="%.2f"))

    for eoc in eocs:
        order = min(case.target_order, case.qbx_order)
        assert eoc.order_estimate() > order - 1.0
Ejemplo n.º 11
0
def test_mean_curvature(ctx_factory,
                        discr_name,
                        resolutions,
                        discr_and_ref_mean_curvature_getter,
                        visualize=False):
    ctx = ctx_factory()
    queue = cl.CommandQueue(ctx)
    actx = PyOpenCLArrayContext(queue)

    from pytools.convergence import EOCRecorder
    eoc = EOCRecorder()

    for r in resolutions:
        discr, ref_mean_curvature = \
                discr_and_ref_mean_curvature_getter(actx, r)
        mean_curvature = bind(discr,
                              sym.mean_curvature(discr.ambient_dim))(actx)

        h = 1.0 / r
        from meshmode.dof_array import flat_norm
        h_error = flat_norm(mean_curvature - ref_mean_curvature, np.inf)
        eoc.add_data_point(h, h_error)
    print(eoc)

    order = min([g.order for g in discr.groups])
    assert eoc.order_estimate() > order - 1.1
Ejemplo n.º 12
0
def test_reversed_chained_connection(actx_factory, ndim, mesh_name):
    actx = actx_factory()

    def run(nelements, order):
        discr = create_discretization(actx,
                                      ndim,
                                      nelements=nelements,
                                      order=order,
                                      mesh_name=mesh_name)

        threshold = 1.0
        connections = []
        conn = create_refined_connection(actx, discr, threshold=threshold)
        connections.append(conn)
        if ndim == 2:
            # NOTE: additional refinement makes the 3D meshes explode in size
            conn = create_refined_connection(actx,
                                             conn.to_discr,
                                             threshold=threshold)
            connections.append(conn)
            conn = create_refined_connection(actx,
                                             conn.to_discr,
                                             threshold=threshold)
            connections.append(conn)

        from meshmode.discretization.connection import \
                ChainedDiscretizationConnection
        chained = ChainedDiscretizationConnection(connections)
        from meshmode.discretization.connection import \
                L2ProjectionInverseDiscretizationConnection
        reverse = L2ProjectionInverseDiscretizationConnection(chained)

        # create test vector
        from_nodes = thaw(chained.from_discr.nodes(), actx)
        to_nodes = thaw(chained.to_discr.nodes(), actx)

        from_x = 0
        to_x = 0
        for d in range(ndim):
            from_x = from_x + actx.np.cos(from_nodes[d])**(d + 1)
            to_x = to_x + actx.np.cos(to_nodes[d])**(d + 1)

        from_interp = reverse(to_x)

        return (1.0 / nelements, flat_norm(from_interp - from_x, np.inf) /
                flat_norm(from_x, np.inf))

    from pytools.convergence import EOCRecorder
    eoc = EOCRecorder()

    order = 4
    mesh_sizes = [16, 32, 48, 64, 96, 128]

    for n in mesh_sizes:
        h, error = run(n, order)
        eoc.add_data_point(h, error)

    print(eoc)

    assert eoc.order_estimate() > (order + 1 - 0.5)
Ejemplo n.º 13
0
def test_pde_check_kernels(ctx_factory, knl_info, order=5):
    dim = knl_info.kernel.dim
    tctx = t.ToyContext(ctx_factory(), knl_info.kernel,
            extra_source_kwargs=knl_info.extra_kwargs)

    pt_src = t.PointSources(
            tctx,
            np.random.rand(dim, 50) - 0.5,
            np.ones(50))

    from pytools.convergence import EOCRecorder
    from sumpy.point_calculus import CalculusPatch
    eoc_rec = EOCRecorder()

    for h in [0.1, 0.05, 0.025]:
        cp = CalculusPatch(np.array([1, 0, 0])[:dim], h=h, order=order)
        pot = pt_src.eval(cp.points)

        pde = knl_info.pde_func(cp, pot)

        err = la.norm(pde)
        eoc_rec.add_data_point(h, err)

    print(eoc_rec)
    assert eoc_rec.order_estimate() > order - knl_info.nderivs + 1 - 0.1
Ejemplo n.º 14
0
def test_isentropic_vortex(actx_factory, order):
    """Advance the 2D isentropic vortex case in time with non-zero velocities
    using an RK4 timestepping scheme. Check the advanced field values against
    the exact/analytic expressions.

    This tests all parts of the Euler module working together, with results
    converging at the expected rates vs. the order.
    """
    actx = actx_factory()

    dim = 2

    from pytools.convergence import EOCRecorder

    eoc_rec = EOCRecorder()

    for nel_1d in [16, 32, 64]:
        from meshmode.mesh.generation import (
            generate_regular_rect_mesh, )

        mesh = generate_regular_rect_mesh(a=(-5.0, ) * dim,
                                          b=(5.0, ) * dim,
                                          nelements_per_axis=(nel_1d, ) * dim)

        exittol = 1.0
        t_final = 0.001
        cfl = 1.0
        vel = np.zeros(shape=(dim, ))
        orig = np.zeros(shape=(dim, ))
        vel[:dim] = 1.0
        dt = .0001
        initializer = Vortex2D(center=orig, velocity=vel)
        casename = "Vortex"
        boundaries = {BTAG_ALL: PrescribedBoundary(initializer)}
        eos = IdealSingleGas()
        t = 0
        flowparams = {
            "dim": dim,
            "dt": dt,
            "order": order,
            "time": t,
            "boundaries": boundaries,
            "initializer": initializer,
            "eos": eos,
            "casename": casename,
            "mesh": mesh,
            "tfinal": t_final,
            "exittol": exittol,
            "cfl": cfl,
            "constantcfl": False,
            "nstatus": 0
        }
        maxerr = _euler_flow_stepper(actx, flowparams)
        eoc_rec.add_data_point(1.0 / nel_1d, maxerr)

    logger.info(f"Error for (dim,order) = ({dim},{order}):\n" f"{eoc_rec}")

    assert (eoc_rec.order_estimate() >= order - 0.5
            or eoc_rec.max_error() < 1e-11)
Ejemplo n.º 15
0
def check_simple_convergence(method,
                             method_impl,
                             expected_order,
                             problem=DefaultProblem(),
                             dts=_default_dts,
                             show_dag=False,
                             plot_solution=False):
    component_id = method.component_id
    code = method.generate()
    print(code)

    if show_dag:
        from dagrt.language import show_dependency_graph
        show_dependency_graph(code)

    from pytools.convergence import EOCRecorder
    eocrec = EOCRecorder()

    for dt in dts:
        t = problem.t_start
        y = problem.initial()
        final_t = problem.t_end

        interp = method_impl(code,
                             function_map={
                                 "<func>" + component_id: problem,
                             })
        interp.set_up(t_start=t, dt_start=dt, context={component_id: y})

        times = []
        values = []
        for event in interp.run(t_end=final_t):
            if isinstance(event, interp.StateComputed):
                assert event.component_id == component_id
                values.append(event.state_component[0])
                times.append(event.t)

        assert abs(times[-1] - final_t) / final_t < 0.1

        times = np.array(times)

        if plot_solution:
            import matplotlib.pyplot as pt
            pt.plot(times, values, label="comp")
            pt.plot(times, problem.exact(times), label="true")
            pt.show()

        error = abs(values[-1] - problem.exact(final_t))
        eocrec.add_data_point(dt, error)

    print("------------------------------------------------------")
    print("%s: expected order %d" %
          (method.__class__.__name__, expected_order))
    print("------------------------------------------------------")
    print(eocrec.pretty_print())

    orderest = eocrec.estimate_order_of_convergence()[0, 1]
    assert orderest > expected_order * 0.9
Ejemplo n.º 16
0
def test_direct(ctx_factory):
    # This evaluates a single layer potential on a circle.
    logging.basicConfig(level=logging.INFO)

    ctx = ctx_factory()
    queue = cl.CommandQueue(ctx)

    from sumpy.kernel import LaplaceKernel
    lknl = LaplaceKernel(2)

    order = 12

    from sumpy.qbx import LayerPotential
    from sumpy.expansion.local import LineTaylorLocalExpansion

    lpot = LayerPotential(ctx, [LineTaylorLocalExpansion(lknl, order)])

    mode_nr = 25

    from pytools.convergence import EOCRecorder

    eocrec = EOCRecorder()

    for n in [200, 300, 400]:
        t = np.linspace(0, 2 * np.pi, n, endpoint=False)
        unit_circle = np.exp(1j * t)
        unit_circle = np.array([unit_circle.real, unit_circle.imag])

        sigma = np.cos(mode_nr * t)
        eigval = 1 / (2 * mode_nr)

        result_ref = eigval * sigma

        h = 2 * np.pi / n

        targets = unit_circle
        sources = unit_circle

        radius = 7 * h
        centers = unit_circle * (1 - radius)

        expansion_radii = np.ones(n) * radius

        strengths = (sigma * h, )
        evt, (result_qbx, ) = lpot(queue,
                                   targets,
                                   sources,
                                   centers,
                                   strengths,
                                   expansion_radii=expansion_radii)

        eocrec.add_data_point(h, np.max(np.abs(result_ref - result_qbx)))

    print(eocrec)

    slack = 1.5
    assert eocrec.order_estimate() > order - slack
Ejemplo n.º 17
0
def test_wave_accuracy(actx_factory, problem, order, visualize=False):
    """Checks accuracy of the wave operator for a given problem setup.
    """
    actx = actx_factory()

    p = problem

    sym_u, sym_v, sym_f, sym_rhs = sym_wave(p.dim, p.sym_phi)

    from pytools.convergence import EOCRecorder
    eoc_rec = EOCRecorder()

    for n in [8, 10, 12] if p.dim == 3 else [8, 12, 16]:
        mesh = p.mesh_factory(n)

        from grudge.eager import EagerDGDiscretization
        discr = EagerDGDiscretization(actx, mesh, order=order)

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

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

        t_check = 1.23456789

        u = sym_eval(sym_u, t_check)
        v = sym_eval(sym_v, t_check)

        fields = flat_obj_array(u, v)

        rhs = wave_operator(discr, c=p.c, w=fields)
        rhs[0] = rhs[0] + sym_eval(sym_f, t_check)

        expected_rhs = sym_eval(sym_rhs, t_check)

        rel_linf_err = actx.to_numpy(
            discr.norm(rhs - expected_rhs, np.inf) /
            discr.norm(expected_rhs, 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)
            vis.write_vtk_file(
                "wave_accuracy_{order}_{n}.vtu".format(order=order, n=n), [
                    ("u", fields[0]),
                    ("v", fields[1:]),
                    ("rhs_u_actual", rhs[0]),
                    ("rhs_v_actual", rhs[1:]),
                    ("rhs_u_expected", expected_rhs[0]),
                    ("rhs_v_expected", expected_rhs[1:]),
                ])

    print("Approximation error:")
    print(eoc_rec)
    assert (eoc_rec.order_estimate() >= order - 0.5
            or eoc_rec.max_error() < 1e-11)
Ejemplo n.º 18
0
def test_convergence(python_method_impl, problem, method, expected_order):
    pytest.importorskip("scipy")

    code = method.generate()

    from leap.implicit import replace_AssignImplicit
    code = replace_AssignImplicit(code, {"solve": solver_hook})

    from pytools.convergence import EOCRecorder
    eocrec = EOCRecorder()

    for n in range(2, 7):
        dt = 2**(-n)

        y_0 = problem.initial()
        t_start = problem.t_start
        t_end = problem.t_end

        from functools import partial
        interp = python_method_impl(code,
                                    function_map={
                                        "<func>expl_y":
                                        problem.nonstiff,
                                        "<func>impl_y":
                                        problem.stiff,
                                        "<func>solver":
                                        partial(solver, problem.stiff),
                                    })

        interp.set_up(t_start=t_start, dt_start=dt, context={"y": y_0})

        times = []
        values = []

        for event in interp.run(t_end=t_end):
            if isinstance(event, interp.StateComputed):
                values.append(event.state_component)
                times.append(event.t)

        times = np.array(times)
        values = np.array(values)

        assert abs(times[-1] - t_end) < 1e-10

        times = np.array(times)

        error = np.linalg.norm(values[-1] - problem.exact(t_end))
        eocrec.add_data_point(dt, error)

    print("------------------------------------------------------")
    print("expected order %d" % expected_order)
    print("------------------------------------------------------")
    print(eocrec.pretty_print())

    orderest = eocrec.estimate_order_of_convergence()[0, 1]
    assert orderest > 0.9 * expected_order
Ejemplo n.º 19
0
def test_lump_rhs(actx_factory, dim, order):
    """Test the inviscid rhs using the non-trivial mass lump case.

    The case is tested against the analytic expressions of the RHS.
    Checks several different orders and refinement levels to check error behavior.
    """
    actx = actx_factory()

    tolerance = 1e-10
    maxxerr = 0.0

    from pytools.convergence import EOCRecorder

    eoc_rec = EOCRecorder()

    for nel_1d in [4, 8, 12]:
        from meshmode.mesh.generation import (
            generate_regular_rect_mesh, )

        mesh = generate_regular_rect_mesh(
            a=(-5, ) * dim,
            b=(5, ) * dim,
            nelements_per_axis=(nel_1d, ) * dim,
        )

        logger.info(f"Number of elements: {mesh.nelements}")

        discr = EagerDGDiscretization(actx, mesh, order=order)
        nodes = thaw(actx, discr.nodes())

        # Init soln with Lump and expected RHS = 0
        center = np.zeros(shape=(dim, ))
        velocity = np.zeros(shape=(dim, ))
        lump = Lump(dim=dim, center=center, velocity=velocity)
        lump_soln = lump(nodes)
        boundaries = {
            BTAG_ALL: PrescribedInviscidBoundary(fluid_solution_func=lump)
        }
        inviscid_rhs = euler_operator(discr,
                                      eos=IdealSingleGas(),
                                      boundaries=boundaries,
                                      cv=lump_soln,
                                      time=0.0)
        expected_rhs = lump.exact_rhs(discr, cv=lump_soln, time=0)

        err_max = discr.norm((inviscid_rhs - expected_rhs).join(), np.inf)
        if err_max > maxxerr:
            maxxerr = err_max

        eoc_rec.add_data_point(1.0 / nel_1d, err_max)
    logger.info(f"Max error: {maxxerr}")

    logger.info(f"Error for (dim,order) = ({dim},{order}):\n" f"{eoc_rec}")

    assert (eoc_rec.order_estimate() >= order - 0.5
            or eoc_rec.max_error() < tolerance)
Ejemplo n.º 20
0
def test_exterior_stokes_2d(ctx_factory, qbx_order=3):
    from pytools.convergence import EOCRecorder
    eoc_rec = EOCRecorder()

    for nelements in [20, 50]:
        h_max, l2_err = run_exterior_stokes_2d(ctx_factory, nelements)
        eoc_rec.add_data_point(h_max, l2_err)

    print(eoc_rec)
    assert eoc_rec.order_estimate() >= qbx_order - 1
Ejemplo n.º 21
0
    def conv_test(descr, use_quad):
        logger.info("-" * 75)
        logger.info(descr)
        logger.info("-" * 75)
        eoc_rec = EOCRecorder()

        if use_quad:
            qtag = dof_desc.DISCR_TAG_QUAD
        else:
            qtag = None

        ns = [20, 25]
        for n in ns:
            mesh = mgen.generate_regular_rect_mesh(a=(-0.5, ) * dims,
                                                   b=(0.5, ) * dims,
                                                   nelements_per_axis=(n, ) *
                                                   dims,
                                                   order=order)

            if use_quad:
                discr_tag_to_group_factory = {
                    qtag: QuadratureSimplexGroupFactory(order=4 * order)
                }
            else:
                discr_tag_to_group_factory = {}

            dcoll = DiscretizationCollection(
                actx,
                mesh,
                order=order,
                discr_tag_to_group_factory=discr_tag_to_group_factory)

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

            def zero_inflow(dtag, t=0):
                dd = dof_desc.DOFDesc(dtag, qtag)
                return dcoll.discr_from_dd(dd).zeros(actx)

            adv_op = VariableCoefficientAdvectionOperator(
                dcoll,
                flat_obj_array(-1 * nodes[1], nodes[0]),
                inflow_u=lambda t: zero_inflow(BTAG_ALL, t=t),
                flux_type="upwind",
                quad_tag=qtag)

            total_error = op.norm(dcoll,
                                  adv_op.operator(0, gaussian_mode(nodes)), 2)
            eoc_rec.add_data_point(1.0 / n, actx.to_numpy(total_error))

        logger.info(
            "\n%s",
            eoc_rec.pretty_print(abscissa_label="h", error_label="L2 Error"))

        return eoc_rec.order_estimate(), np.array(
            [x[1] for x in eoc_rec.history])
Ejemplo n.º 22
0
def test_velocity_gradient_eoc(actx_factory, dim):
    """Test that the velocity gradient converges at the proper rate."""
    from mirgecom.fluid import velocity_gradient
    actx = actx_factory()

    order = 3

    from pytools.convergence import EOCRecorder
    eoc = EOCRecorder()

    nel_1d_0 = 4
    for hn1 in [1, 2, 3, 4]:

        nel_1d = hn1 * nel_1d_0
        h = 1/nel_1d

        from meshmode.mesh.generation import generate_regular_rect_mesh
        mesh = generate_regular_rect_mesh(
            a=(1.0,) * dim, b=(2.0,) * dim, nelements_per_axis=(nel_1d,) * dim
        )

        discr = EagerDGDiscretization(actx, mesh, order=order)
        nodes = thaw(actx, discr.nodes())
        zeros = discr.zeros(actx)
        energy = zeros + 2.5

        mass = nodes[dim-1]*nodes[dim-1]
        velocity = make_obj_array([actx.np.cos(nodes[i]) for i in range(dim)])
        mom = mass*velocity

        q = join_conserved(dim, mass=mass, energy=energy, momentum=mom)
        cv = split_conserved(dim, q)

        grad_q = obj_array_vectorize(discr.grad, q)
        grad_cv = split_conserved(dim, grad_q)

        grad_v = velocity_gradient(discr, cv, grad_cv)

        def exact_grad_row(xdata, gdim, dim):
            exact_grad_row = make_obj_array([zeros for _ in range(dim)])
            exact_grad_row[gdim] = -actx.np.sin(xdata)
            return exact_grad_row

        comp_err = make_obj_array([
            discr.norm(grad_v[i] - exact_grad_row(nodes[i], i, dim), np.inf)
            for i in range(dim)])
        err_max = comp_err.max()
        eoc.add_data_point(h, err_max)

    logger.info(eoc)
    assert (
        eoc.order_estimate() >= order - 0.5
        or eoc.max_error() < 1e-9
    )
Ejemplo n.º 23
0
def test_eoc():
    from pytools.convergence import EOCRecorder
    eoc = EOCRecorder()

    for i in range(1, 8):
        eoc.add_data_point(1.0 / i, 10**(-i))

    p = eoc.pretty_print()
    print(p)
    print()

    p = eoc.pretty_print(abscissa_format="%.5e",
                         error_format="%.5e",
                         eoc_format="%5.2f")
    print(p)
Ejemplo n.º 24
0
def test_vortex_rhs(actx_factory, order):
    """Tests the inviscid rhs using the non-trivial
    2D isentropic vortex case configured to yield
    rhs = 0. Checks several different orders
    and refinement levels to check error
    behavior.
    """
    actx = actx_factory()

    dim = 2

    from pytools.convergence import EOCRecorder
    eoc_rec = EOCRecorder()

    from meshmode.mesh.generation import generate_regular_rect_mesh

    for nel_1d in [16, 32, 64]:

        mesh = generate_regular_rect_mesh(
            a=(-5, ) * dim,
            b=(5, ) * dim,
            n=(nel_1d, ) * dim,
        )

        logger.info(f"Number of {dim}d elements:  {mesh.nelements}")

        discr = EagerDGDiscretization(actx, mesh, order=order)
        nodes = thaw(actx, discr.nodes())

        # Init soln with Vortex and expected RHS = 0
        vortex = Vortex2D(center=[0, 0], velocity=[0, 0])
        vortex_soln = vortex(0, nodes)
        boundaries = {BTAG_ALL: PrescribedBoundary(vortex)}

        inviscid_rhs = inviscid_operator(discr,
                                         eos=IdealSingleGas(),
                                         boundaries=boundaries,
                                         q=vortex_soln,
                                         t=0.0)

        err_max = discr.norm(inviscid_rhs, np.inf)
        eoc_rec.add_data_point(1.0 / nel_1d, err_max)

    message = (f"Error for (dim,order) = ({dim},{order}):\n" f"{eoc_rec}")
    logger.info(message)

    assert (eoc_rec.order_estimate() >= order - 0.5
            or eoc_rec.max_error() < 1e-11)
Ejemplo n.º 25
0
def test_pde_check(dim, order=4):
    from sumpy.point_calculus import CalculusPatch
    from pytools.convergence import EOCRecorder

    for iaxis in range(dim):
        eoc_rec = EOCRecorder()
        for h in [0.1, 0.01, 0.001]:
            cp = CalculusPatch(np.array([3, 0, 0])[:dim], h=h, order=order)
            df_num = cp.diff(iaxis, np.sin(10 * cp.points[iaxis]))
            df_true = 10 * np.cos(10 * cp.points[iaxis])

            err = la.norm(df_num - df_true)
            eoc_rec.add_data_point(h, err)

        print(eoc_rec)
        assert eoc_rec.order_estimate() > order - 2 - 0.1
Ejemplo n.º 26
0
def test_exterior_stokes(actx_factory, ambient_dim, visualize=False):
    if visualize:
        logging.basicConfig(level=logging.INFO)

    from pytools.convergence import EOCRecorder
    eocs = [EOCRecorder() for _ in range(ambient_dim)]

    target_order = 5
    source_ovsmp = 4
    qbx_order = 3

    if ambient_dim == 2:
        resolutions = [20, 35, 50]
    elif ambient_dim == 3:
        resolutions = [0, 1, 2]
    else:
        raise ValueError(f"unsupported dimension: {ambient_dim}")

    for resolution in resolutions:
        h_max, errors = run_exterior_stokes(actx_factory,
                ambient_dim=ambient_dim,
                target_order=target_order,
                qbx_order=qbx_order,
                source_ovsmp=source_ovsmp,
                resolution=resolution,
                visualize=visualize)

        for eoc, e in zip(eocs, errors):
            eoc.add_data_point(h_max, e)

    for eoc in eocs:
        print(eoc.pretty_print(
            abscissa_format="%.8e",
            error_format="%.8e",
            eoc_format="%.2f"))

    for eoc in eocs:
        # This convergence data is not as clean as it could be. See
        # https://github.com/inducer/pytential/pull/32
        # for some discussion.
        order = min(target_order, qbx_order)
        assert eoc.order_estimate() > order - 0.5
Ejemplo n.º 27
0
    def conv_test(descr, use_quad):
        logger.info("-" * 75)
        logger.info(descr)
        logger.info("-" * 75)
        eoc_rec = EOCRecorder()

        ns = [20, 25]
        for n in ns:
            mesh = mgen.generate_regular_rect_mesh(a=(-0.5, ) * dims,
                                                   b=(0.5, ) * dims,
                                                   nelements_per_axis=(n, ) *
                                                   dims,
                                                   order=order)

            if use_quad:
                discr_tag_to_group_factory = {
                    "product": QuadratureSimplexGroupFactory(order=4 * order)
                }
            else:
                discr_tag_to_group_factory = {"product": None}

            discr = DiscretizationCollection(
                actx,
                mesh,
                order=order,
                discr_tag_to_group_factory=discr_tag_to_group_factory)

            bound_op = bind(discr, op.sym_operator())
            fields = bind(discr, gaussian_mode())(actx, t=0)
            norm = bind(discr, sym.norm(2, sym.var("u")))

            esc = bound_op(u=fields)
            total_error = norm(u=esc)
            eoc_rec.add_data_point(1.0 / n, total_error)

        logger.info(
            "\n%s",
            eoc_rec.pretty_print(abscissa_label="h", error_label="L2 Error"))

        return eoc_rec.order_estimate(), np.array(
            [x[1] for x in eoc_rec.history])
Ejemplo n.º 28
0
    def __call__(self):
        """Run the test and output the estimated the order of convergence."""

        from pytools.convergence import EOCRecorder

        if self.display_dag:
            self.show_dag()

        eocrec = EOCRecorder()
        for n in range(6, 8):
            dt = 2**(-n)
            error = self.get_error(dt, "mrab-%d.dat" % self.order)
            eocrec.add_data_point(dt, error)

        print("------------------------------------------------------")
        print("ORDER %d" % self.order)
        print("------------------------------------------------------")
        print(eocrec.pretty_print())

        orderest = eocrec.estimate_order_of_convergence()[0, 1]
        assert orderest > self.order * 0.70
Ejemplo n.º 29
0
def test_tri_diff_mat(ctx_factory, dim, order=4):
    """Check differentiation matrix along the coordinate axes on a disk

    Uses sines as the function to differentiate.
    """

    cl_ctx = ctx_factory()
    queue = cl.CommandQueue(cl_ctx)
    actx = PyOpenCLArrayContext(queue)

    from meshmode.mesh.generation import generate_regular_rect_mesh

    from pytools.convergence import EOCRecorder
    axis_eoc_recs = [EOCRecorder() for axis in range(dim)]

    for n in [10, 20]:
        mesh = generate_regular_rect_mesh(a=(-0.5, ) * dim,
                                          b=(0.5, ) * dim,
                                          n=(n, ) * dim,
                                          order=4)

        discr = DGDiscretizationWithBoundaries(actx, mesh, order=4)
        nabla = sym.nabla(dim)

        for axis in range(dim):
            x = sym.nodes(dim)

            f = bind(discr, sym.sin(3 * x[axis]))(actx)
            df = bind(discr, 3 * sym.cos(3 * x[axis]))(actx)

            sym_op = nabla[axis](sym.var("f"))
            bound_op = bind(discr, sym_op)
            df_num = bound_op(f=f)

            linf_error = flat_norm(df_num - df, np.Inf)
            axis_eoc_recs[axis].add_data_point(1 / n, linf_error)

    for axis, eoc_rec in enumerate(axis_eoc_recs):
        logger.info("axis %d\n%s", axis, eoc_rec)
        assert eoc_rec.order_estimate() >= order
Ejemplo n.º 30
0
    def conv_test(descr, use_quad):
        print("-" * 75)
        print(descr)
        print("-" * 75)
        eoc_rec = EOCRecorder()

        ns = [20, 25]
        for n in ns:
            mesh = generate_regular_rect_mesh(a=(-0.5, ) * dims,
                                              b=(0.5, ) * dims,
                                              n=(n, ) * dims,
                                              order=order)

            if use_quad:
                quad_tag_to_group_factory = {
                    "product": QuadratureSimplexGroupFactory(order=4 * order)
                }
            else:
                quad_tag_to_group_factory = {"product": None}

            discr = DGDiscretizationWithBoundaries(
                cl_ctx,
                mesh,
                order=order,
                quad_tag_to_group_factory=quad_tag_to_group_factory)

            bound_op = bind(discr, op.sym_operator())
            fields = bind(discr, gaussian_mode())(queue, t=0)
            norm = bind(discr, sym.norm(2, sym.var("u")))

            esc = bound_op(queue, u=fields)
            total_error = norm(queue, u=esc)
            eoc_rec.add_data_point(1.0 / n, total_error)

        print(
            eoc_rec.pretty_print(abscissa_label="h", error_label="LInf Error"))

        return eoc_rec.order_estimate(), np.array(
            [x[1] for x in eoc_rec.history])