Beispiel #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]))
Beispiel #2
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)
Beispiel #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
Beispiel #4
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
Beispiel #5
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
Beispiel #6
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])
Beispiel #7
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])
Beispiel #8
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
Beispiel #9
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])
Beispiel #10
0
def test_dependent_state(order=3, step_ratio=3):
    # Solve
    # f' = f+s
    # s' = -f+s

    def true_f(t):
        return np.exp(t) * np.sin(t)

    def true_s(t):
        return np.exp(t) * np.cos(t)

    method = MultiRateMultiStepMethodBuilder(order, (
        (
            "dt",
            "fast",
            "=",
            MRHistory(1, "<func>f", (
                "two_fast",
                "slow",
            )),
        ),
        ("dt", "slow", "=", MRHistory(step_ratio, "<func>s",
                                      ("fast", "slow"))),
        (
            "two_fast",
            "=",
            MRHistory(step_ratio, "<func>twice", ("fast", )),
        ),
    ),
                                             static_dt=True)

    code = method.generate()
    print(code)

    from pytools.convergence import EOCRecorder
    eocrec = EOCRecorder()

    from dagrt.codegen import PythonCodeGenerator
    codegen = PythonCodeGenerator(class_name="Method")

    stepper_cls = codegen.get_class(code)

    for n in range(4, 7):
        t = 0
        dt = 2**(-n)
        final_t = 10

        stepper = stepper_cls(
            function_map={
                "<func>f": lambda t, two_fast, slow: 0.5 * two_fast + slow,
                "<func>s": lambda t, fast, slow: -fast + slow,
                "<func>twice": lambda t, fast: 2 * fast,
            })

        stepper.set_up(t_start=t,
                       dt_start=dt,
                       context={
                           "fast": true_f(t),
                           "slow": true_s(t),
                       })

        f_times = []
        f_values = []
        s_times = []
        s_values = []
        for event in stepper.run(t_end=final_t):
            if isinstance(event, stepper_cls.StateComputed):
                if event.component_id == "fast":
                    f_times.append(event.t)
                    f_values.append(event.state_component)
                elif event.component_id == "slow":
                    s_times.append(event.t)
                    s_values.append(event.state_component)
                else:
                    assert False, event.component_id

        f_times = np.array(f_times)
        s_times = np.array(s_times)
        f_values_true = true_f(f_times)
        s_values_true = true_s(s_times)

        f_err = f_values - f_values_true
        s_err = s_values - s_values_true

        error = (
            la.norm(f_err) / la.norm(f_values_true) +  # noqa: W504
            la.norm(s_err) / la.norm(s_values_true))

        eocrec.add_data_point(dt, error)

    print(eocrec.pretty_print())

    orderest = eocrec.estimate_order_of_convergence()[0, 1]
    assert orderest > 3 * 0.95
Beispiel #11
0
def main(show_dag=False, plot_solution=False):
    component_id = "y"
    method = ODE23Method(component_id, use_high_order=True)
    expected_order = 3

    # Use "DEBUG" to trace execution
    logging.basicConfig(level=logging.INFO)

    code = method.generate()

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

    from dagrt.exec_numpy import NumpyInterpreter

    def rhs(t, y):
        u, v = y
        return np.array([v, -u/t**2], dtype=np.float64)

    def soln(t):
        inner = np.sqrt(3)/2*np.log(t)
        return np.sqrt(t)*(
                5*np.sqrt(3)/3*np.sin(inner)
                + np.cos(inner)
                )

    from pytools.convergence import EOCRecorder
    eocrec = EOCRecorder()

    for n in range(4, 7):
        dt = 2**(-n)
        t = 1
        y = np.array([1, 3], dtype=np.float64)
        final_t = 10

        interp = NumpyInterpreter(code, function_map={"<func>" + component_id: rhs})
        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) < 1e-10

        times = np.array(times)

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

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

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

    orderest = eocrec.estimate_order_of_convergence()[0, 1]
    assert orderest > expected_order*0.95
Beispiel #12
0
def test_convergence_maxwell(ctx_factory, order):
    """Test whether 3D Maxwell's actually converges"""

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

    from pytools.convergence import EOCRecorder
    eoc_rec = EOCRecorder()

    dims = 3
    ns = [4, 6, 8]
    for n in ns:
        from meshmode.mesh.generation import generate_regular_rect_mesh
        mesh = generate_regular_rect_mesh(a=(0.0, ) * dims,
                                          b=(1.0, ) * dims,
                                          n=(n, ) * dims)

        discr = DGDiscretizationWithBoundaries(actx, mesh, order=order)

        epsilon = 1
        mu = 1

        from grudge.models.em import get_rectangular_cavity_mode
        sym_mode = get_rectangular_cavity_mode(1, (1, 2, 2))

        analytic_sol = bind(discr, sym_mode)
        fields = analytic_sol(actx, t=0, epsilon=epsilon, mu=mu)

        from grudge.models.em import MaxwellOperator
        op = MaxwellOperator(epsilon, mu, flux_type=0.5, dimensions=dims)
        op.check_bc_coverage(mesh)
        bound_op = bind(discr, op.sym_operator())

        def rhs(t, w):
            return bound_op(t=t, w=w)

        dt = 0.002
        final_t = dt * 5
        nsteps = int(final_t / dt)

        from grudge.shortcuts import set_up_rk4
        dt_stepper = set_up_rk4("w", dt, fields, rhs)

        logger.info("dt %.5e nsteps %5d", dt, nsteps)

        norm = bind(discr, sym.norm(2, sym.var("u")))

        step = 0
        for event in dt_stepper.run(t_end=final_t):
            if isinstance(event, dt_stepper.StateComputed):
                assert event.component_id == "w"
                esc = event.state_component

                step += 1
                logger.debug("[%04d] t = %.5e", step, event.t)

        sol = analytic_sol(actx, mu=mu, epsilon=epsilon, t=step * dt)
        vals = [norm(u=(esc[i] - sol[i])) / norm(u=sol[i])
                for i in range(5)]  # noqa E501
        total_error = sum(vals)
        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"))

    assert eoc_rec.order_estimate() > order
Beispiel #13
0
def test_convergence_advec(ctx_factory,
                           mesh_name,
                           mesh_pars,
                           op_type,
                           flux_type,
                           order,
                           visualize=False):
    """Test whether 2D advection actually converges"""

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

    from pytools.convergence import EOCRecorder
    eoc_rec = EOCRecorder()

    for mesh_par in mesh_pars:
        if mesh_name == "segment":
            from meshmode.mesh.generation import generate_box_mesh
            mesh = generate_box_mesh([np.linspace(-1.0, 1.0, mesh_par)],
                                     order=order)

            dim = 1
            dt_factor = 1.0
        elif mesh_name == "disk":
            pytest.importorskip("meshpy")

            from meshpy.geometry import make_circle, GeometryBuilder
            from meshpy.triangle import MeshInfo, build

            geob = GeometryBuilder()
            geob.add_geometry(*make_circle(1))
            mesh_info = MeshInfo()
            geob.set(mesh_info)

            mesh_info = build(mesh_info, max_volume=mesh_par)

            from meshmode.mesh.io import from_meshpy
            mesh = from_meshpy(mesh_info, order=1)
            dim = 2
            dt_factor = 4
        elif mesh_name.startswith("rect"):
            dim = int(mesh_name[4:])
            from meshmode.mesh.generation import generate_regular_rect_mesh
            mesh = generate_regular_rect_mesh(a=(-0.5, ) * dim,
                                              b=(0.5, ) * dim,
                                              n=(mesh_par, ) * dim,
                                              order=4)

            if dim == 2:
                dt_factor = 4
            elif dim == 3:
                dt_factor = 2
            else:
                raise ValueError("dt_factor not known for %dd" % dim)

        else:
            raise ValueError("invalid mesh name: " + mesh_name)

        v = np.array([0.27, 0.31, 0.1])[:dim]
        norm_v = la.norm(v)

        def f(x):
            return sym.sin(10 * x)

        def u_analytic(x):
            return f(-v.dot(x) / norm_v + sym.var("t", sym.DD_SCALAR) * norm_v)

        from grudge.models.advection import (StrongAdvectionOperator,
                                             WeakAdvectionOperator)
        discr = DGDiscretizationWithBoundaries(actx, mesh, order=order)
        op_class = {
            "strong": StrongAdvectionOperator,
            "weak": WeakAdvectionOperator,
        }[op_type]
        op = op_class(v,
                      inflow_u=u_analytic(sym.nodes(dim, sym.BTAG_ALL)),
                      flux_type=flux_type)

        bound_op = bind(discr, op.sym_operator())

        u = bind(discr, u_analytic(sym.nodes(dim)))(actx, t=0)

        def rhs(t, u):
            return bound_op(t=t, u=u)

        if dim == 3:
            final_time = 0.1
        else:
            final_time = 0.2

        h_max = bind(discr, sym.h_max_from_volume(discr.ambient_dim))(actx)
        dt = dt_factor * h_max / order**2
        nsteps = (final_time // dt) + 1
        dt = final_time / nsteps + 1e-15

        from grudge.shortcuts import set_up_rk4
        dt_stepper = set_up_rk4("u", dt, u, rhs)

        last_u = None

        from grudge.shortcuts import make_visualizer
        vis = make_visualizer(discr, vis_order=order)

        step = 0

        for event in dt_stepper.run(t_end=final_time):
            if isinstance(event, dt_stepper.StateComputed):
                step += 1
                logger.debug("[%04d] t = %.5f", step, event.t)

                last_t = event.t
                last_u = event.state_component

                if visualize:
                    vis.write_vtk_file("fld-%s-%04d.vtu" % (mesh_par, step),
                                       [("u", event.state_component)])

        error_l2 = bind(discr,
                        sym.norm(2,
                                 sym.var("u") - u_analytic(sym.nodes(dim))))(
                                     t=last_t, u=last_u)
        logger.info("h_max %.5e error %.5e", h_max, error_l2)
        eoc_rec.add_data_point(h_max, error_l2)

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

    assert eoc_rec.order_estimate() > order
Beispiel #14
0
        if not visualize:
            continue

        from meshmode.discretization.visualization import make_visualizer
        vis = make_visualizer(actx, density_discr, case.target_order)

        filename = f"beltrami_{case.name}_{solution.name}_{resolution}.vtu"
        vis.write_vtk_file(filename, [
            ("result", result),
            ("ref_result", ref_result),
            ("error", result - ref_result)
            ], overwrite=True)

    logger.info("\n%s", eoc.pretty_print(
        abscissa_format="%.8e",
        error_format="%.8e",
        eoc_format="%.2f"))

    # NOTE: expected order is `order - 2` because the formulation has two
    # additional target derivatives on the kernel
    order = min(case.target_order, case.qbx_order)
    assert eoc.order_estimate() > order - 2.5

# }}}


if __name__ == "__main__":
    import sys
    if len(sys.argv) > 1:
        exec(sys.argv[1])
    else:
Beispiel #15
0
def test_im_euler_accuracy(python_method_impl,
                           show_dag=False,
                           plot_solution=False):
    component_id = "y"

    from implicit_euler import ImplicitEulerMethod

    method = ImplicitEulerMethod(component_id)
    code = method.generate(solver_hook)

    expected_order = 1

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

    h = -0.5
    y_0 = 1.0

    def rhs(t, y):
        return h * y

    def soln(t):
        return y_0 * np.exp(h * t)

    from pytools.convergence import EOCRecorder
    eocrec = EOCRecorder()

    for n in range(1, 5):
        dt = 2**(-n)
        t = 0.0
        y = y_0
        final_t = 1

        from functools import partial
        interp = python_method_impl(code,
                                    function_map={
                                        method.rhs_func.name: rhs,
                                        "<func>solver": partial(solver, rhs)
                                    })

        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)
                times.append(event.t)

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

        times = np.array(times)

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

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

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

    orderest = eocrec.estimate_order_of_convergence()[0, 1]
    assert orderest > expected_order * 0.9
Beispiel #16
0
    # }}}


if __name__ == "__main__":
    grid_sizes = [
        (3, 3),
        (3, 4),
        (4, 4),
        (4, 5),
        (5, 5),
        (5, 6),
        (6, 6),
        (6, 7),
        (7, 7),
        (7, 8),
        (8, 8),
        (8, 9),
        (9, 9),
        (9, 10),
        (10, 10),
    ]

    from pytools.convergence import EOCRecorder
    eoc = EOCRecorder()

    for nx, ny in grid_sizes:
        npoints, t_elapsed = timing_run(nx, ny)
        eoc.add_data_point(npoints, t_elapsed)
    print(eoc.pretty_print(abscissa_label="Elements",
                           error_label="Timing (s)"))
Beispiel #17
0
def test_adaptive(python_method_impl, problem, method):
    pytest.importorskip("scipy")

    t_start = problem.t_start
    t_end = problem.t_end
    dt = 1.0e-1

    tols = [10.0**(-j) for j in range(1, 5)]

    from pytools.convergence import EOCRecorder
    eocrec = EOCRecorder()

    # Test that tightening the tolerance will decrease the overall error.
    for atol in tols:
        generator = method("y", atol=atol)
        code = generator.generate()

        #sgen = ScipySolverGenerator(*generator.implicit_expression())
        from leap.implicit import replace_AssignImplicit
        code = replace_AssignImplicit(code, {"solve": solver_hook})

        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": problem.initial()})

        times = []
        values = []

        new_times = []
        new_values = []

        for event in interp.run(t_end=t_end):
            clear_flag = False
            if isinstance(event, interp.StateComputed):
                assert event.component_id == "y"
                new_values.append(event.state_component)
                new_times.append(event.t)
            elif isinstance(event, interp.StepCompleted):
                values.extend(new_values)
                times.extend(new_times)
                clear_flag = True
            elif isinstance(event, interp.StepFailed):
                clear_flag = True
            if clear_flag:
                del new_times[:]
                del new_values[:]

        times = np.array(times)
        values = np.array(values)
        exact = problem.exact(times[-1])
        error = np.linalg.norm(values[-1] - exact)
        eocrec.add_data_point(atol, error)

    print("Error vs. tolerance")
    print(eocrec.pretty_print())
    order = eocrec.estimate_order_of_convergence()[0, 1]
    assert order > 0.9
Beispiel #18
0
def test_convergence_maxwell(actx_factory, order):
    """Test whether 3D Maxwell's actually converges"""

    actx = actx_factory()

    from pytools.convergence import EOCRecorder
    eoc_rec = EOCRecorder()

    dims = 3
    ns = [4, 6, 8]
    for n in ns:
        mesh = mgen.generate_regular_rect_mesh(a=(0.0, ) * dims,
                                               b=(1.0, ) * dims,
                                               nelements_per_axis=(n, ) * dims)

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

        epsilon = 1
        mu = 1

        from grudge.models.em import get_rectangular_cavity_mode

        def analytic_sol(x, t=0):
            return get_rectangular_cavity_mode(actx, x, t, 1, (1, 2, 2))

        nodes = thaw(dcoll.nodes(), actx)
        fields = analytic_sol(nodes, t=0)

        from grudge.models.em import MaxwellOperator

        maxwell_operator = MaxwellOperator(dcoll,
                                           epsilon,
                                           mu,
                                           flux_type=0.5,
                                           dimensions=dims)
        maxwell_operator.check_bc_coverage(mesh)

        def rhs(t, w):
            return maxwell_operator.operator(t, w)

        dt = maxwell_operator.estimate_rk4_timestep(actx, dcoll)
        final_t = dt * 5
        nsteps = int(final_t / dt)

        from grudge.shortcuts import set_up_rk4
        dt_stepper = set_up_rk4("w", dt, fields, rhs)

        logger.info("dt %.5e nsteps %5d", dt, nsteps)

        step = 0
        for event in dt_stepper.run(t_end=final_t):
            if isinstance(event, dt_stepper.StateComputed):
                assert event.component_id == "w"
                esc = event.state_component

                step += 1
                logger.debug("[%04d] t = %.5e", step, event.t)

        sol = analytic_sol(nodes, t=step * dt)
        total_error = op.norm(dcoll, esc - sol, 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"))

    assert eoc_rec.order_estimate() > order
Beispiel #19
0
def test_convergence_advec(actx_factory,
                           mesh_name,
                           mesh_pars,
                           op_type,
                           flux_type,
                           order,
                           visualize=False):
    """Test whether 2D advection actually converges"""

    actx = actx_factory()

    from pytools.convergence import EOCRecorder
    eoc_rec = EOCRecorder()

    for mesh_par in mesh_pars:
        if mesh_name == "segment":
            mesh = mgen.generate_box_mesh([np.linspace(-1.0, 1.0, mesh_par)],
                                          order=order)

            dim = 1
            dt_factor = 1.0
        elif mesh_name == "disk":
            pytest.importorskip("meshpy")

            from meshpy.geometry import make_circle, GeometryBuilder
            from meshpy.triangle import MeshInfo, build

            geob = GeometryBuilder()
            geob.add_geometry(*make_circle(1))
            mesh_info = MeshInfo()
            geob.set(mesh_info)

            mesh_info = build(mesh_info, max_volume=mesh_par)

            from meshmode.mesh.io import from_meshpy
            mesh = from_meshpy(mesh_info, order=1)
            dim = 2
            dt_factor = 4
        elif mesh_name.startswith("rect"):
            dim = int(mesh_name[-1:])
            mesh = mgen.generate_regular_rect_mesh(
                a=(-0.5, ) * dim,
                b=(0.5, ) * dim,
                nelements_per_axis=(mesh_par, ) * dim,
                order=4)

            if dim == 2:
                dt_factor = 4
            elif dim == 3:
                dt_factor = 2
            else:
                raise ValueError("dt_factor not known for %dd" % dim)
        elif mesh_name.startswith("warped"):
            dim = int(mesh_name[-1:])
            mesh = mgen.generate_warped_rect_mesh(dim,
                                                  order=order,
                                                  nelements_side=mesh_par)

            if dim == 2:
                dt_factor = 4
            elif dim == 3:
                dt_factor = 2
            else:
                raise ValueError("dt_factor not known for %dd" % dim)
        else:
            raise ValueError("invalid mesh name: " + mesh_name)

        v = np.array([0.27, 0.31, 0.1])[:dim]
        norm_v = la.norm(v)

        def f(x):
            return actx.np.sin(10 * x)

        def u_analytic(x, t=0):
            return f(-v.dot(x) / norm_v + t * norm_v)

        from grudge.models.advection import (StrongAdvectionOperator,
                                             WeakAdvectionOperator)
        from meshmode.mesh import BTAG_ALL

        dcoll = DiscretizationCollection(actx, mesh, order=order)
        op_class = {
            "strong": StrongAdvectionOperator,
            "weak": WeakAdvectionOperator
        }[op_type]
        adv_operator = op_class(dcoll,
                                v,
                                inflow_u=lambda t: u_analytic(
                                    thaw(dcoll.nodes(dd=BTAG_ALL), actx), t=t),
                                flux_type=flux_type)

        nodes = thaw(dcoll.nodes(), actx)
        u = u_analytic(nodes, t=0)

        def rhs(t, u):
            return adv_operator.operator(t, u)

        if dim == 3:
            final_time = 0.1
        else:
            final_time = 0.2

        from grudge.dt_utils import h_max_from_volume

        h_max = h_max_from_volume(dcoll, dim=dcoll.ambient_dim)
        dt = dt_factor * h_max / order**2
        nsteps = (final_time // dt) + 1
        dt = final_time / nsteps + 1e-15

        from grudge.shortcuts import set_up_rk4
        dt_stepper = set_up_rk4("u", dt, u, rhs)

        last_u = None

        from grudge.shortcuts import make_visualizer
        vis = make_visualizer(dcoll)

        step = 0

        for event in dt_stepper.run(t_end=final_time):
            if isinstance(event, dt_stepper.StateComputed):
                step += 1
                logger.debug("[%04d] t = %.5f", step, event.t)

                last_t = event.t
                last_u = event.state_component

                if visualize:
                    vis.write_vtk_file("fld-%s-%04d.vtu" % (mesh_par, step),
                                       [("u", event.state_component)])

        error_l2 = op.norm(dcoll, last_u - u_analytic(nodes, t=last_t), 2)
        logger.info("h_max %.5e error %.5e", h_max, error_l2)
        eoc_rec.add_data_point(h_max, actx.to_numpy(error_l2))

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

    if mesh_name.startswith("warped"):
        # NOTE: curvilinear meshes are hard
        assert eoc_rec.order_estimate() > order - 0.5
    else:
        assert eoc_rec.order_estimate() > order