예제 #1
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
예제 #2
0
파일: utils.py 프로젝트: mattwala/leap
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
예제 #3
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
예제 #4
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
예제 #5
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
예제 #6
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
예제 #7
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
예제 #8
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