Beispiel #1
0
def adaptive_rk_method(tol):
    """
    The difference between the results of Euler's method
       y_e = y_n + h f(t_n, y_n)
    and Heun's method
       y_h = y_n + h / 2 (f(t_n, y_n), f(t_n + dt, y_e))
    can be used as an estimate of the high order error term in Euler's method.

    This allows us to adapt the time step so that the local error falls within a
    specified tolerance.
    """

    # Set up variables
    y = var("<state>y")
    g = var("<func>g")
    y_e = var("y_e")
    y_h = var("y_h")
    dt = var("<dt>")
    t = var("<t>")
    dt_old = var("dt_old")

    # Helpers for expression fragments
    def norm(val):
        return var("<builtin>norm_2")(val)

    def dt_scaling(tol, err):
        # Return a suitable scaling factor for dt.
        # Ensure to guard against excessive increase or divide-by-zero.
        from pymbolic.primitives import Max, Min
        return Min(((tol / Max((1.0e-16, norm(err))))**(1 / 2), 2.0))

    # Code for the main state
    with CodeBuilder("adaptrk") as cb:
        # Euler
        cb(y_e, y + dt * g(t, y))

        # Heun
        cb(y_h, y + dt / 2 * (g(t, y) + g(t + dt, y_e)))

        # Adaptation
        cb(dt_old, dt)
        cb(dt, dt * dt_scaling(tol, y_h - y_e))

        # Accept or reject step
        with cb.if_(norm(y_h - y_e), ">=", tol):
            cb.fail_step()
        with cb.else_():
            cb(y, y_h)
            cb(t, t + dt_old)

    return DAGCode.from_phases_list([cb.as_execution_phase("adaptrk")],
                                    "adaptrk")
Beispiel #2
0
    def generate(self, solver_hook):
        """Return code that implements the implicit Euler method for the single
        state component supported."""

        with CodeBuilder(name="primary") as cb:
            self._make_primary(cb)

        code = DAGCode.from_phases_list(
            [cb.as_execution_phase(next_phase="primary")],
            initial_phase="primary")

        from leap.implicit import replace_AssignImplicit

        return replace_AssignImplicit(code,
                                      {self.SOLVER_EXPRESSION_ID: solver_hook})
Beispiel #3
0
def test_CodeBuilder_restart_step(python_method_impl):
    with CodeBuilder("init") as builder_init:
        builder_init("<p>x", "0")

    with CodeBuilder("state1") as builder1:
        builder1("<p>x", "<p>x + 1")
        with builder1.if_("<p>x == 1"):
            builder1.restart_step()

    with CodeBuilder("state2") as builder2:
        builder2.yield_state(var("<p>x"), "x", 0, "final")

    phases = [
        builder_init.as_execution_phase(next_phase="state1"),
        builder1.as_execution_phase(next_phase="state2"),
        builder2.as_execution_phase(next_phase="state2")
    ]
    code = DAGCode.from_phases_list(phases, "init")

    result = execute_and_return_single_result(python_method_impl,
                                              code,
                                              max_steps=4)
    assert result == 2