예제 #1
0
def test_2rab_scheme_explainers(method_name,
                                order=3,
                                step_ratio=3,
                                explainer=TextualSchemeExplainer()):
    method = TwoRateAdamsBashforthMethodBuilder(method_name,
                                                order=order,
                                                step_ratio=step_ratio)

    method.generate(explainer=explainer)
    print(explainer)
예제 #2
0
def test_dot(order=3, step_ratio=3, method_name="F", show=False):
    method = TwoRateAdamsBashforthMethodBuilder(
        method_name,
        order=order,
        step_ratio=step_ratio,
        hist_consistency_threshold=1e-8)
    code = method.generate()

    from dagrt.language import get_dot_dependency_graph
    print(get_dot_dependency_graph(code))

    if show:
        from dagrt.language import show_dependency_graph
        show_dependency_graph(code)
예제 #3
0
    def get_code(self, dt):
        method = TwoRateAdamsBashforthMethodBuilder(
            self.method,
            self.order,
            self.step_ratio,
            static_dt=self.static_dt,
            hist_consistency_threshold=1e-8,
            early_hist_consistency_threshold=dt**self.order,
            hist_length_slow=self.hist_length,
            hist_length_fast=self.hist_length)

        # Early consistency threshold checked for convergence
        # with timestep change - C. Mikida, 2/6/18 (commit hash 2e6ca077)

        # With method 4-Ss (limiting case), the following maximum relative
        # errors were observed:
        # for dt = 0.015625: 3.11E-09
        # for dt = 0.0078125: 1.04e-10
        # Corresponding EOC: 4.90

        # Reported relative errors show that no constant factor is needed on
        # early consistency threshold

        return method.generate()
예제 #4
0
def make_multirate_method(f2f, s2f, f2s, s2s, ratio=2, order=3):
    """Return the object that drives the multirate method for the given
    parameters."""
    FastestFirst = "Fq"
    code = TwoRateAdamsBashforthMethodBuilder(FastestFirst, order,
                                              ratio).generate()
    MRABMethod = PythonCodeGenerator(class_name='MRABMethod').get_class(code)

    rhs_map = {
        '<func>f2f': f2f,
        '<func>s2f': s2f,
        '<func>f2s': f2s,
        '<func>s2s': s2s
    }

    return MRABMethod(rhs_map)
예제 #5
0
def test_multirate_squarewave(min_order, hist_length, method_name):
    stepper = TwoRateAdamsBashforthMethodBuilder(method_name, min_order, 4,
                hist_consistency_threshold=1e-8,
                early_hist_consistency_threshold="3.5e3 * <dt>**%d" % min_order,
                hist_length_slow=hist_length, hist_length_fast=hist_length)

    # Early consistency threshold checked for convergence
    # with timestep change - C. Mikida, 2/6/18 (commit hash 0fb6148)

    # With method 3-4-Ss (limiting case), the following maximum relative
    # errors were observed:
    # for dt = 0.0011: 6.96E-08
    # for dt = 0.00073: 5.90E-09

    # Reported relative errors motivate constant factor of 3.5e3 for early
    # consistency threshold

    code = stepper.generate()

    from dagrt.function_registry import (
            base_function_registry, register_ode_rhs)

    freg = base_function_registry
    for func_name in [
            "<func>s2s",
            "<func>f2s",
            "<func>s2f",
            "<func>f2f",
            ]:
        component_id = {
                "s": "slow",
                "f": "fast",
                }[func_name[-1]]
        freg = register_ode_rhs(freg, identifier=func_name,
                output_type_id=component_id,
                input_type_ids=("slow", "fast"),
                input_names=("s", "f"))

    freg = freg.register_codegen("<func>s2f", "fortran",
        f.CallCode("""
            ${result} = (sin(2*${t}) - 1)*${s}
            """))
    freg = freg.register_codegen("<func>f2s", "fortran",
      f.CallCode("""
          ${result} = (sin(2*${t}) + 1)*${f}
          """))
    freg = freg.register_codegen("<func>f2f", "fortran",
      f.CallCode("""
          ${result} = cos(2*${t})*${f}
          """))
    freg = freg.register_codegen("<func>s2s", "fortran",
      f.CallCode("""
          ${result} = -cos(2*${t})*${s}
          """))

    codegen = f.CodeGenerator(
            "MRAB",
            user_type_map={
                "slow": f.ArrayType(
                    (1,),
                    f.BuiltinType('real (kind=8)'),
                    ),
                "fast": f.ArrayType(
                    (1,),
                    f.BuiltinType('real (kind=8)'),
                    )
                },
            function_registry=freg,
            module_preamble="""
            ! lines copied to the start of the module, e.g. to say:
            ! use ModStuff
            """)

    code_str = codegen(code)

    # Build in conditionals to alter the timestep based on order such that all
    # tests pass

    if min_order == 2:
        fac = 200
    elif min_order == 3:
        fac = 100
    else:
        fac = 12
    num_trips_one = 100*fac
    num_trips_two = 150*fac

    run_fortran([
        ("abmethod.f90", code_str),
        ("test_mrab_squarewave.f90", (
            read_file("test_mrab_squarewave.f90")
            .replace("MIN_ORDER", str(min_order - 0.3)+"d0")
            .replace("NUM_TRIPS_ONE", str(num_trips_one))
            .replace("NUM_TRIPS_TWO", str(num_trips_two)))),
        ],
        fortran_libraries=["lapack", "blas"])
예제 #6
0
def test_multirate_codegen(min_order, method_name):
    from leap.multistep.multirate import TwoRateAdamsBashforthMethodBuilder

    stepper = TwoRateAdamsBashforthMethodBuilder(
            method_name, min_order, 4,
            slow_state_filter_name="slow_filt",
            fast_state_filter_name="fast_filt",
            # should pass with either, let's alternate by order
            # static_dt=True is 'more finnicky', so use that at min_order=5.
            static_dt=True if min_order % 2 == 1 else False,
            hist_consistency_threshold=1e-8,
            early_hist_consistency_threshold="1.25e3 * <dt>**%d" % min_order)

    # Early consistency threshold checked for convergence
    # with timestep change - C. Mikida, 2/6/18 (commit hash 2e6ca077)

    # With method 5-Fqs (limiting case), the following maximum relative
    # errors were observed:
    # for dt = 0.0384: 1.03E-04
    # for dt = 0.0128: 5.43E-08

    # Reported relative errors motivate constant factor of 1.25e3 for early
    # consistency threshold

    code = stepper.generate()

    from dagrt.function_registry import (
            base_function_registry, register_ode_rhs,
            UserType, register_function)

    freg = base_function_registry
    for func_name in [
            "<func>s2s",
            "<func>f2s",
            "<func>s2f",
            "<func>f2f",
            ]:
        component_id = {
                "s": "slow",
                "f": "fast",
                }[func_name[-1]]
        freg = register_ode_rhs(freg, identifier=func_name,
                output_type_id=component_id,
                input_type_ids=("slow", "fast"),
                input_names=("s", "f"))

    freg = freg.register_codegen("<func>s2f", "fortran",
        f.CallCode("""
            ${result} = (sin(2d0*${t}) - 1d0)*${s}
            """))
    freg = freg.register_codegen("<func>f2s", "fortran",
      f.CallCode("""
          ${result} = (sin(2d0*${t}) + 1d0)*${f}
          """))
    freg = freg.register_codegen("<func>f2f", "fortran",
      f.CallCode("""
          ${result} = cos(2d0*${t})*${f}
          """))
    freg = freg.register_codegen("<func>s2s", "fortran",
      f.CallCode("""
          ${result} = -cos(2d0*${t})*${s}
          """))

    freg = register_function(freg, "<func>slow_filt", ("arg",),
            result_names=("result",), result_kinds=(UserType("slow"),))
    freg = freg.register_codegen("<func>slow_filt", "fortran",
            f.CallCode("""
                ! mess with state
                ${result} = ${arg}
                """))

    freg = register_function(freg, "<func>fast_filt", ("arg",),
            result_names=("result",), result_kinds=(UserType("fast"),))
    freg = freg.register_codegen("<func>fast_filt", "fortran",
            f.CallCode("""
                ! mess with state
                ${result} = ${arg}
                """))

    codegen = f.CodeGenerator(
            "MRAB",
            user_type_map={
                "slow": f.ArrayType(
                    (1,),
                    f.BuiltinType('real (kind=8)'),
                    ),
                "fast": f.ArrayType(
                    (1,),
                    f.BuiltinType('real (kind=8)'),
                    )
                },
            function_registry=freg,
            module_preamble="""
            ! lines copied to the start of the module, e.g. to say:
            ! use ModStuff
            """)

    code_str = codegen(code)

    if 0:
        with open("abmethod.f90", "wt") as outf:
            outf.write(code_str)

    fac = 130
    if min_order == 5 and method_name in ["Srs", "Ss"]:
        pytest.xfail("Srs,Ss do not achieve fifth order convergence")

    num_trips_one = 10*fac
    num_trips_two = 30*fac

    run_fortran([
        ("abmethod.f90", code_str),
        ("test_mrab.f90", (
            read_file("test_mrab.f90")
            .replace("MIN_ORDER", str(min_order - 0.3)+"d0")
            .replace("NUM_TRIPS_ONE", str(num_trips_one))
            .replace("NUM_TRIPS_TWO", str(num_trips_two)))),
        ],
        fortran_libraries=["lapack", "blas"])
예제 #7
0
def main():
    from leap.step_matrix import StepMatrixFinder

    from pymbolic import var

    speed_factor = 10
    step_ratio = 7
    method_name = "Fq"
    order = 3

    print("speed factor: %g - step ratio: %g - method: %s "
          "- order: %d" % (speed_factor, step_ratio, method_name, order))

    method = TwoRateAdamsBashforthMethodBuilder(method=method_name,
                                                order=order,
                                                step_ratio=step_ratio,
                                                static_dt=True)

    code = method.generate()

    finder = StepMatrixFinder(code,
                              function_map={
                                  "<func>f2f": lambda t, f, s: var("f2f") * f,
                                  "<func>s2f": lambda t, f, s: var("s2f") * s,
                                  "<func>f2s": lambda t, f, s: var("f2s") * f,
                                  "<func>s2s": lambda t, f, s: var("s2s") * s,
                              },
                              exclude_variables=["<p>bootstrap_step"])

    mat = finder.get_phase_step_matrix("primary")

    if 0:
        print("Variables: %s" % finder.variables)
        np.set_printoptions(formatter={"all": str})
        print(mat)

    tol = 1e-8

    from leap.step_matrix import fast_evaluator
    evaluate_mat = fast_evaluator(mat)

    def is_stable(direction, dt):
        smat = evaluate_mat({
            "<dt>": dt,
            "f2f": direction,
            "s2f": 1 / speed_factor,
            "f2s": 1 / speed_factor,
            "s2s": direction * 1 / speed_factor,
        })

        eigvals = la.eigvals(smat)

        return (np.abs(eigvals) <= 1 + tol).all()

    from leap.stability import find_truth_bdry
    from functools import partial

    prec = 1e-5
    print("stable imaginary timestep:",
          find_truth_bdry(partial(is_stable, 1j), prec=prec))
    print("stable neg real timestep:",
          find_truth_bdry(partial(is_stable, -1), prec=prec))
예제 #8
0
def main():
    from leap.step_matrix import StepMatrixFinder

    from pymbolic import var

    speed_factor = 10
    method_name = "Fq"
    order = 3
    tol = 1e-8
    prec = 1e-5

    angles = np.linspace(0, 2*np.pi, 100, endpoint=False)

    for step_ratio in [1, 2, 3, 4, 5, 6]:
        print("speed factor: %g - step ratio: %g - method: %s "
                "- order: %d"
                % (speed_factor, step_ratio, method_name, order))

        method = TwoRateAdamsBashforthMethodBuilder(
                method=method_name, order=order, step_ratio=step_ratio,
                static_dt=True)

        code = method.generate()

        finder = StepMatrixFinder(code,
                function_map={
                    "<func>f2f": lambda t, f, s: var("f2f") * f,
                    "<func>s2f": lambda t, f, s: var("s2f") * s,
                    "<func>f2s": lambda t, f, s: var("f2s") * f,
                    "<func>s2s": lambda t, f, s: var("s2s") * s,
                    },
                exclude_variables=["<p>bootstrap_step"])

        mat = finder.get_phase_step_matrix("primary")

        if 0:
            print('Variables: %s' % finder.variables)
            np.set_printoptions(formatter={"all": str})
            print(mat)

        from leap.step_matrix import fast_evaluator
        evaluate = fast_evaluator(mat)

        def is_stable(major_eigval, dt):
            smat = evaluate({
                        "<dt>": dt,
                        "f2f": major_eigval,
                        "s2f": 1/speed_factor,
                        "f2s": 1/speed_factor,
                        "s2s": major_eigval*1/speed_factor,
                        })

            eigvals = la.eigvals(smat)

            return (np.abs(eigvals) <= 1 + tol).all()

        from leap.stability import find_truth_bdry
        from functools import partial

        points = []

        for angle in angles:
            eigval = np.exp(1j*angle)

            max_dt = find_truth_bdry(partial(is_stable, eigval), prec=prec)

            stable_fake_eigval = eigval*max_dt

            points.append([stable_fake_eigval.real, stable_fake_eigval.imag])

        points = np.array(points).T

        pt.plot(points[0], points[1], "x", label="steprat: %d" % step_ratio)

    pt.legend(loc="best")
    pt.grid()

    outfile = "mr-stability-diagram.pdf"
    pt.savefig(outfile)
    print("Output written to %s" % outfile)
예제 #9
0
def main():
    from leap.step_matrix import StepMatrixFinder

    from pymbolic import var

    speed_factor = 10
    method_name = "Fq"
    order = 3
    step_ratio = 3
    prec = 1e-5

    method = TwoRateAdamsBashforthMethodBuilder(
            method=method_name, order=order, step_ratio=step_ratio,
            static_dt=True)

    code = method.generate()

    finder = StepMatrixFinder(code,
            function_map={
                "<func>f2f": lambda t, f, s: var("f2f") * f,
                "<func>s2f": lambda t, f, s: var("s2f") * s,
                "<func>f2s": lambda t, f, s: var("f2s") * f,
                "<func>s2s": lambda t, f, s: var("s2s") * s,
                },
            exclude_variables=["<p>bootstrap_step"])

    mat = finder.get_phase_step_matrix("primary")

    left = -3
    right = 1
    bottom = -4
    top = 4
    res = 200

    points = np.mgrid[left:right:res*1j, bottom:top:res*1j]
    eigvals = points[0] + 1j*points[1]
    eigvals_flat = eigvals.reshape(-1)

    from multiprocessing import Pool
    pool = Pool()

    from leap.step_matrix import fast_evaluator
    evaluate_mat = fast_evaluator(mat)

    stable_dts_list = pool.map(
            partial(process_eigval, evaluate_mat, speed_factor, prec), eigvals_flat)

    max_eigvals = np.zeros(eigvals.shape)
    max_eigvals.reshape(-1)[:] = stable_dts_list

    pt.title("speed factor: %g - step ratio: %g - method: %s "
            "- order: %d"
            % (speed_factor, step_ratio, method_name, order))

    log_max_eigvals = np.log10(1e-15+max_eigvals.T)
    pt.imshow(log_max_eigvals, extent=(left, right, bottom, top), cmap="viridis")
    pt.colorbar()
    pt.contour(eigvals.real, eigvals.imag, log_max_eigvals.T, [0], zorder=10)
    pt.gca().set_aspect("equal")
    pt.grid()

    outfile = "mr-max-eigvals.pdf"
    pt.savefig(outfile)

    print("Output written to %s" % outfile)