Exemplo n.º 1
0
def test_quad_gauss_degree():
    """
    check gaussian quadrature degree
    """
    x0, x1 = 0, 1

    max_degree = 8

    for deg in range(2, max_degree):
        p = Monome(deg)
        y0 = p[x0, x1]

        max_node_count = range(2, 6)
        Y = [
            quad_gauss(p, x0, x1, node_count) for node_count in max_node_count
        ]
        accuracy = get_log_error(Y, y0 * np.ones_like(Y))
        accuracy[np.isinf(accuracy)] = 17

        # check accuracy is good enough
        for node_count, acc in zip(max_node_count, accuracy):
            if 2 * node_count >= deg + 1:
                assert acc > 6

        plt.plot(max_node_count, accuracy, '.:', label=f'x^{deg}')

    plt.legend()
    plt.ylabel('accuracy')
    plt.xlabel('node count')
    plt.suptitle(f'test quad gauss')
    plt.show()
Exemplo n.º 2
0
def test_quad_degree():
    """
    check quadrature degree
    Q: why in some cases x^n integrated perfectly with only n nodes?
    """
    x0, x1 = 0, 1

    max_degree = 7

    for deg in range(1, max_degree):
        p = Monome(deg)
        y0 = p[x0, x1]

        max_node_count = range(1, max_degree + 1)

        Y = [
            quad(p, x0, x1, np.linspace(x0, x1, node_count))
            for node_count in max_node_count
        ]
        # Y = [quad(p, x0, x1, x0 + (x1-x0) * np.random.random(node_count)) for node_count in max_node_count]
        accuracy = get_log_error(Y, y0 * np.ones_like(Y))
        accuracy[np.isinf(accuracy)] = 17

        # check accuracy is good enough
        for node_count, acc in zip(max_node_count, accuracy):
            if node_count >= deg + 1:
                assert acc > 6

        plt.plot(max_node_count, accuracy, '.:', label=f'x^{deg}')

    plt.legend()
    plt.ylabel('accuracy')
    plt.xlabel('node_count')
    plt.suptitle(f'test quad')
    plt.show()
Exemplo n.º 3
0
def test_composite_quad_degree(v):
    """
    Q: convergence maybe somewhat between 3 and 4, why?
    """
    from variants import params

    plt.figure()
    a, b, alpha, beta, f = params(v)
    x0, x1 = a, b
    # a, b = -10, 10
    exact = sp_quad(lambda x: f(x) / (x - a)**alpha / (b - x)**beta, x0, x1)[0]

    # plot weights
    xs = np.linspace(x0, x1, 101)[1:-1]
    ys = 1 / ((xs - a)**alpha * (b - xs)**beta)

    #my addition
    # for x in xs:
    #     if (x-a)**alpha * (b-x)**beta:
    #         print("HERE")
    # print(ys)
    #

    plt.subplot(1, 2, 1)
    plt.plot(xs, ys, label='weights')
    ax = list(plt.axis())
    ax[2] = 0.
    plt.axis(ax)
    plt.xlabel('x')
    plt.ylabel('p(x)')
    plt.legend()

    L = 2
    n_intervals = [L**q for q in range(2, 10)]
    n_nodes = 3
    Y = [
        composite_quad(f,
                       x0,
                       x1,
                       n_intervals=n,
                       n_nodes=n_nodes,
                       a=a,
                       b=b,
                       alpha=alpha,
                       beta=beta) for n in n_intervals
    ]
    accuracy = get_log_error(Y, exact * np.ones_like(Y))
    x = np.log10(n_intervals)
    aitken_degree = aitken(*Y[5:8], L)

    # plot acc
    plt.subplot(1, 2, 2)
    plt.plot(x, accuracy, 'kh')
    plt.xlabel('log10(node count)')
    plt.ylabel('accuracy')
    plt.suptitle(f'variant #{v} (alpha={alpha:4.2f}, beta={beta:4.2f})\n'
                 f'aitken estimation: {aitken_degree:.2f}')
    plt.show()
Exemplo n.º 4
0
def test_multi_step():
    """
    test Adams method
    Q: compare the right plot for both cases and explain the difference
    """
    y0 = np.array([0., 1.])
    t0 = 0
    t1 = 1.
    dt = 0.1

    f = Harmonic(y0, 1, 1)
    ts = np.arange(t0, t1 + dt, dt)
    exact = f[ts].T
    #print('exact')
    #print(exact)

    for one_step_method in [
            RungeKuttaMethod(collection.rk4_coeffs),
            ExplicitEulerMethod(),
    ]:
        plt.figure()
        plt.subplot(1, 2, 1), plt.plot(ts, [e[0] for e in exact],
                                       'k',
                                       label='Exact')
        for p, c in adams_coeffs.items():
            t_adams, y_adams = adams(f,
                                     y0,
                                     ts,
                                     c,
                                     one_step_method=one_step_method)
            #print(y_adams)
            print(f'Function calls: {f.get_call_counter()}')

            err = get_log_error(exact, y_adams)

            label = f"Adams's order {p}"
            plt.subplot(1, 2, 1), plt.plot(t_adams, [y[0] for y in y_adams],
                                           '.--',
                                           label=label)
            plt.subplot(1, 2, 2), plt.plot(t_adams, err, '.--', label=label)

        plt.subplot(1, 2, 1), plt.xlabel('t'), plt.ylabel('y'), plt.legend()
        plt.subplot(1, 2,
                    2), plt.xlabel('t'), plt.ylabel('accuracy'), plt.legend()
        plt.suptitle(
            f'test_multi_step\none step method: {one_step_method.name}')
    plt.show()


#test_multi_step()
Exemplo n.º 5
0
def test_composite_quad(n_nodes):
    """
    test composite 2-, 3-, 5-node quads
    Q: explain converge speed for each case
    """
    plt.figure()

    x0, x1 = 0, 1
    L = 2
    n_intervals = [L**q for q in range(0, 8)]

    for i, degree in enumerate((5, 6)):
        p = Monome(degree)
        Y = [
            composite_quad(p, x0, x1, n_intervals=n, n_nodes=n_nodes)
            for n in n_intervals
        ]
        accuracy = get_log_error(Y, p[x0, x1] * np.ones_like(Y))
        x = np.log10(n_intervals)

        # check convergence
        ind = np.isfinite(x) & np.isfinite(accuracy)
        k, b = np.polyfit(x[ind], accuracy[ind], 1)
        aitken_degree = aitken(*Y[0:6:2], L**2)

        plt.subplot(1, 2, i + 1)
        plt.title(f'{n_nodes}-node CQ for x^{degree}')
        plt.plot(x, k * x + b, 'b:', label=f'{k:.2f}*x+{b:.2f}')
        plt.plot(x,
                 aitken_degree * x + b,
                 'm:',
                 label=f'aitken ({aitken_degree:.2f})')
        plt.plot(x, accuracy, 'kh', label=f'accuracy for x^{degree}')
        plt.xlabel('log10(node count)')
        plt.ylabel('accuracy')
        plt.legend()

        if n_nodes < degree:
            assert np.abs(aitken_degree - k) < 0.5, \
                f'Aitken estimation {aitken_degree:.2f} is too far from actual {k:.2f}'

    plt.show()
Exemplo n.º 6
0
def test_one_step():
    """
    test Euler and RK methods
    """
    y0 = np.array([0., 1.])
    t0 = 0
    t1 = np.pi / 2
    dt = 0.1

    f = Harmonic(y0, 1, 1)
    ts = np.arange(t0, t1 + dt, dt)

    exact = f[ts].T
    plt.figure()
    plt.subplot(1, 2, 1)
    plt.plot(ts, [e[0] for e in exact], 'k', label='Exact')

    colors = 'rgbcmyk'
    for i, method in enumerate([
            ExplicitEulerMethod(),
            RungeKuttaMethod(collection.rk4_coeffs),
            RungeKuttaMethod(collection.dopri_coeffs),
    ]):
        _, y = fix_step_integration(method, f, y0, ts)
        print(f'len(Y): {len(y)}')
        print(f'Function calls: {f.get_call_counter()}')

        plt.subplot(1, 2, 1), plt.plot(ts, [_y[0] for _y in y],
                                       f'{colors[i]}.--',
                                       label=method.name)
        plt.subplot(1, 2, 2), plt.plot(ts,
                                       get_log_error(exact, y),
                                       f'{colors[i]}.--',
                                       label=method.name)

    plt.subplot(1, 2, 1), plt.xlabel('t'), plt.ylabel('y'), plt.legend()
    plt.subplot(1, 2, 2), plt.xlabel('t'), plt.ylabel('accuracy'), plt.legend()
    plt.suptitle('test_one_step')
    plt.show()
Exemplo n.º 7
0
def test_adaptive(f, y0):
    """
    test adaptive step algorithms
    """
    t0, t1 = 0, 4 * np.pi

    atol = 1e-6
    rtol = 1e-3

    tss = []
    yss = []

    methods = (
        (ExplicitEulerMethod(), AdaptType.RUNGE),
        (RungeKuttaMethod(coeffs=collection.rk4_coeffs), AdaptType.RUNGE),
        (EmbeddedRungeKuttaMethod(coeffs=collection.dopri_coeffs),
         AdaptType.EMBEDDED),
    )

    for method, adapt_type in methods:
        f.clear_call_counter()
        ts, ys = adaptive_step_integration(method=method,
                                           func=f,
                                           y_start=y0,
                                           t_span=(t0, t1),
                                           adapt_type=adapt_type,
                                           atol=atol,
                                           rtol=rtol)
        print(f'{method.name} took {f.get_call_counter()} function calls')

        tss.append(np.array(ts))
        yss.append(ys)

    ts = np.array(sorted([t for ts in tss for t in ts]))
    exact = f[ts].T
    y0 = np.array([y[0] for y in exact])

    # plots
    plt.figure('y(t)'), plt.suptitle('test_adaptive: y(t)'), plt.xlabel(
        't'), plt.ylabel('y')
    plt.plot(ts, y0, 'ko-', label='exact')

    plt.figure('dt(t)'), plt.suptitle('test_adaptive: step sizes'), plt.xlabel(
        't'), plt.ylabel('dt')
    plt.figure('dy(t)'), plt.suptitle('test_adaptive: accuracies'), plt.xlabel(
        't'), plt.ylabel('accuracy')

    for (m, _), ts, ys in zip(methods, tss, yss):
        plt.figure('y(t)'), plt.plot(ts, [y[0] for y in ys], '.', label=m.name)
        plt.figure('dt(t)'), plt.plot(ts[:-1],
                                      ts[1:] - ts[:-1],
                                      '.-',
                                      label=m.name)
        plt.figure('dy(t)'), plt.plot(ts,
                                      get_log_error(f[ts].T, ys),
                                      '.-',
                                      label=m.name)

    plt.figure('y(t)'), plt.legend()
    plt.figure('dt(t)'), plt.legend()
    plt.figure('dy(t)'), plt.legend()

    plt.show()