예제 #1
0
def compensated_residual(s, coeffs1, t, coeffs2):
    x1, dx1 = de_casteljau._compensated_k(s, coeffs1[0, :], 2)
    y1, dy1 = de_casteljau._compensated_k(s, coeffs1[1, :], 2)
    x2, dx2 = de_casteljau._compensated_k(t, coeffs2[0, :], 2)
    y2, dy2 = de_casteljau._compensated_k(t, coeffs2[1, :], 2)

    dx, sigma = eft.add_eft(x1, -x2)
    tau = (dx1 - dx2) + sigma
    dx += tau
    dy, sigma = eft.add_eft(y1, -y2)
    tau = (dy1 - dy2) + sigma
    dy += tau

    return np.array([[dx], [dy]])
예제 #2
0
def main(filename=None):
    s_vals = np.linspace(ROOT - DELTA_S, ROOT + DELTA_S, NUM_POINTS)

    evaluated1 = []
    evaluated2 = []
    evaluated3 = []

    for s in s_vals:
        b, db, d2b = de_casteljau._compensated_k(s, BEZIER_COEFFS, 3)
        evaluated1.append(b)
        b2 = b + db
        evaluated2.append(b2)
        b3 = b2 + d2b
        evaluated3.append(b3)

    figure, (ax1, ax2, ax3) = plt.subplots(1, 3, sharex=True)
    ax1.plot(s_vals, evaluated1)
    ax2.plot(s_vals, evaluated2)
    ax3.plot(s_vals, evaluated3)

    # Since ``sharex=True``, ticks only need to be set once.
    ax1.set_xticks(
        [
            ROOT - DELTA_S,
            ROOT - 0.5 * DELTA_S,
            ROOT,
            ROOT + 0.5 * DELTA_S,
            ROOT + DELTA_S,
        ]
    )

    ax1.set_title(r"$\mathtt{DeCasteljau}$")
    ax2.set_title(r"$\mathtt{CompDeCasteljau}$")
    ax3.set_title(r"$\mathtt{CompDeCasteljau3}$")

    if filename is None:
        plt.show()
    else:
        figure.set_size_inches(13.65, 6.41)
        figure.subplots_adjust(
            left=0.04,
            bottom=0.10,
            right=0.97,
            top=0.95,
            wspace=0.15,
            hspace=0.19,
        )
        path = plot_utils.get_path(filename)
        figure.savefig(path, bbox_inches="tight")
        print("Saved {}".format(filename))
        plt.close(figure)
예제 #3
0
def _main():
    s_vals = np.linspace(ROOT - DELTA_S, ROOT + DELTA_S, NUM_POINTS)

    evaluated1 = []
    evaluated2 = []
    evaluated3 = []

    for s in s_vals:
        b, db, d2b = de_casteljau._compensated_k(s, BEZIER_COEFFS, 3)
        evaluated1.append(b)
        b2 = b + db
        evaluated2.append(b2)
        b3 = b2 + d2b
        evaluated3.append(b3)

    figure, (ax1, ax2, ax3) = plt.subplots(1, 3, sharex=True)
    ax1.plot(s_vals, evaluated1)
    ax2.plot(s_vals, evaluated2)
    ax3.plot(s_vals, evaluated3)

    # Since ``sharex=True``, ticks only need to be set once.
    ax1.set_xticks([ROOT - 0.8 * DELTA_S, ROOT, ROOT + 0.8 * DELTA_S])

    ax1.set_title(r"$\mathtt{DeCasteljau}$",
                  fontsize=plot_utils.TEXT_SIZE,
                  pad=16.0)
    ax2.set_title(r"$\mathtt{CompDeCasteljau}$",
                  fontsize=plot_utils.TEXT_SIZE,
                  pad=16.0)
    ax3.set_title(r"$\mathtt{CompDeCasteljau3}$",
                  fontsize=plot_utils.TEXT_SIZE,
                  pad=16.0)

    filename = "de_casteljau_smooth_drawing.pdf"
    figure.set_size_inches(6.0, 3.0)
    figure.subplots_adjust(left=0.07,
                           bottom=0.13,
                           right=0.98,
                           top=0.87,
                           wspace=0.21,
                           hspace=0.2)
    path = plot_utils.get_path("k-compensated", filename)
    figure.savefig(path)
    print("Saved {}".format(filename))
    plt.close(figure)
예제 #4
0
def main():
    n = 8
    gamma2n = (2 * n * U) / (1 - 2 * n * U)
    bound_coeff1 = float(gamma2n)
    bound_coeff2 = 3 * n * (3 * n + 7) * U ** 2 / 2
    bound_coeff2 = float(bound_coeff2)
    bound_coeff3 = 3 * n * (3 * n ** 2 + 36 * n + 61) * U ** 3 / 2
    bound_coeff3 = float(bound_coeff3)
    bound_coeff4 = (
        9 * n * (3 * n ** 3 + 102 * n ** 2 + 773 * n + 1122) * U ** 4 / 8
    )
    bound_coeff4 = float(bound_coeff4)

    cond_nums = []
    forward_errs1 = []
    forward_errs2 = []
    forward_errs3 = []
    forward_errs4 = []
    for j in range(-5, -90 - 1, -1):
        s = ROOT - POWER_VAL ** j
        exact_s = F(s)

        # Compute the condition number.
        exact_p = (exact_s - 1) * (4 * exact_s - 3) ** 7 / 16384
        # p_tilde(s) = SUM_j |b_j| B_{j, 8}(s) = (s - 1) (s/2 - 3/4)^7
        exact_p_tilde = (exact_s - 1) * (2 * exact_s - 3) ** 7 / 16384
        exact_cond = abs(exact_p_tilde / exact_p)
        cond_nums.append(float(exact_cond))

        # Compute the forward error for uncompensated de Casteljau.
        b, db, d2b, d3b = de_casteljau._compensated_k(s, BEZIER_COEFFS, 4)
        exact_b1 = F(b)
        exact_forward_err1 = abs((exact_b1 - exact_p) / exact_p)
        forward_errs1.append(float(exact_forward_err1))

        # Compute the forward error for compensated de Casteljau.
        b2 = b + db
        exact_b2 = F(b2)
        exact_forward_err2 = abs((exact_b2 - exact_p) / exact_p)
        forward_errs2.append(float(exact_forward_err2))

        # Compute the forward error for K-compensated de Casteljau (K=3).
        b3 = b2 + d2b
        exact_b3 = F(b3)
        exact_forward_err3 = abs((exact_b3 - exact_p) / exact_p)
        forward_errs3.append(float(exact_forward_err3))

        # Compute the forward error for K-compensated de Casteljau (K=3).
        b4 = b3 + d3b
        exact_b4 = F(b4)
        exact_forward_err4 = abs((exact_b4 - exact_p) / exact_p)
        forward_errs4.append(float(exact_forward_err4))

    # Set a tight ``x``-limit.
    min_exp = np.log(min(cond_nums))
    max_exp = np.log(max(cond_nums))
    delta_exp = max_exp - min_exp
    min_x = np.exp(min_exp - 0.01 * delta_exp)
    max_x = np.exp(max_exp + 0.01 * delta_exp)

    figure = plt.figure()
    ax = figure.gca()
    ax.loglog(
        cond_nums,
        forward_errs1,
        marker="v",
        linestyle="none",
        zorder=2,
        label=r"$\mathtt{DeCasteljau}$",
        color=plot_utils.BLUE,
    )
    ax.loglog(
        cond_nums,
        forward_errs2,
        marker="d",
        linestyle="none",
        zorder=2,
        label=r"$\mathtt{CompDeCasteljau}$",
        color=plot_utils.GREEN,
    )
    ax.loglog(
        cond_nums,
        forward_errs3,
        marker="P",
        linestyle="none",
        zorder=1.5,  # Beneath ``K=2``.
        label=r"$\mathtt{CompDeCasteljau3}$",
        color=plot_utils.RED,
    )
    ax.loglog(
        cond_nums,
        forward_errs4,
        marker="o",
        linestyle="none",
        zorder=1.25,  # Beneath ``K=2, 3``.
        label=r"$\mathtt{CompDeCasteljau4}$",
        color=plot_utils.PURPLE,
    )
    # Figure out the bounds before adding the bounding lines.
    min_y, max_y = ax.get_ylim()
    # Plot the lines of the a priori error bounds.
    ax.loglog(
        [min_x, max_x],
        [bound_coeff1 * min_x, bound_coeff1 * max_x],
        color="black",
        alpha=ALPHA,
        zorder=1,
    )
    ax.loglog(
        [min_x, max_x],
        [bound_coeff2 * min_x, bound_coeff2 * max_x],
        color="black",
        alpha=ALPHA,
        zorder=1,
    )
    ax.loglog(
        [min_x, max_x],
        [bound_coeff3 * min_x, bound_coeff3 * max_x],
        color="black",
        alpha=ALPHA,
        zorder=1,
    )
    ax.loglog(
        [min_x, max_x],
        [bound_coeff4 * min_x, bound_coeff4 * max_x],
        color="black",
        alpha=ALPHA,
        zorder=1,
    )
    # Add the ``x = 1/u^k`` vertical lines.
    delta_y = max_y - min_y
    for exponent in (1, 2, 3, 4):
        u_inv = 1.0 / float(U) ** exponent
        ax.loglog(
            [u_inv, u_inv],
            [min_y - 0.05 * delta_y, max_y + 0.05 * delta_y],
            color="black",
            linestyle="dashed",
            alpha=ALPHA,
            zorder=1,
        )
    # Add the ``y = u`` horizontal lines.
    ax.loglog(
        [min_x, max_x],
        [float(U), float(U)],
        color="black",
        linestyle="dashed",
        alpha=ALPHA,
        zorder=1,
    )

    # Make sure the ``y``-limit stays set (the bounds lines exceed).
    ax.set_ylim(min_y, 1.0)
    ax.set_xlim(min_x, max_x)
    # Add the legend.
    ax.legend(
        loc="lower right",
        framealpha=1.0,
        frameon=True,
        fontsize=plot_utils.TEXT_SIZE,
    )
    # Set "nice" ticks.
    ax.set_xticks([10.0 ** n for n in range(5, 65 + 10, 10)])
    ax.set_yticks([10.0 ** n for n in range(-18, 0 + 2, 2)])
    # Set special ``xticks`` for ``1/u^k``.
    u_xticks = []
    u_xticklabels = []
    for exponent in (1, 2, 3, 4):
        u_xticks.append(1.0 / float(U) ** exponent)
        if exponent == 1:
            u_xticklabels.append(r"$1/\mathbf{u}$")
        else:
            u_xticklabels.append(r"$1/\mathbf{{u}}^{}$".format(exponent))

    ax.set_xticks(u_xticks, minor=True)
    ax.set_xticklabels(u_xticklabels, minor=True)
    ax.tick_params(
        axis="x",
        which="minor",
        direction="out",
        top=1,
        bottom=0,
        labelbottom=0,
        labeltop=1,
    )
    # Set special ``yticks`` for ``u``.
    ax.set_yticks([float(U)], minor=True)
    ax.set_yticklabels([r"$\mathbf{u}$"], minor=True)
    ax.tick_params(
        axis="y",
        which="minor",
        direction="out",
        left=0,
        right=1,
        labelleft=0,
        labelright=1,
    )
    # Label the axes.
    ax.set_xlabel("Condition Number", fontsize=plot_utils.TEXT_SIZE)
    ax.set_ylabel("Relative Forward Error", fontsize=plot_utils.TEXT_SIZE)

    ax.tick_params(labelsize=plot_utils.TICK_SIZE)
    ax.tick_params(labelsize=plot_utils.TEXT_SIZE, which="minor")

    figure.set_size_inches(5.2, 3.9)
    figure.subplots_adjust(
        left=0.12, bottom=0.11, right=0.95, top=0.92, wspace=0.2, hspace=0.2
    )
    filename = "de_casteljau_rel_error.pdf"
    path = plot_utils.get_path("k-compensated", filename)
    figure.savefig(path)
    print("Saved {}".format(filename))
    plt.close(figure)
예제 #5
0
def main_jlcs10():
    """This recreates the plot from `JLCS10`_.

    .. _JLCS10: https://doi.org/10.1016/j.camwa.2010.05.021

    Note that it is essentially a copy of :func:`main` (and much of the
    code could be shared, but it isn't worth the effort).

    This seeks to recreate the plot from the original paper, but to show
    what happens as the exponent on ``POWER_VAL`` decreases from ``-44`` down
    to ``-64``. In particular, it shows that the compensated de Casteljau
    algorithm produces exactly zero.
    """
    n = 8
    gamma2n = (2 * n * U) / (1 - 2 * n * U)
    bound_coeff1 = float(gamma2n)
    bound_coeff2 = 3 * n * (3 * n + 7) * U ** 2 / 2
    bound_coeff2 = float(bound_coeff2)

    cond_nums = []
    forward_errs1 = []
    forward_errs2 = []
    for j in range(-5, -64 - 1, -1):
        s = ROOT - POWER_VAL ** j
        exact_s = F(s)

        # Compute the condition number.
        exact_p = (exact_s - 1) * (4 * exact_s - 3) ** 7 / 16384
        # p_tilde(s) = SUM_j |b_j| B_{j, 8}(s) = (s - 1) (s/2 - 3/4)^7
        exact_p_tilde = (exact_s - 1) * (2 * exact_s - 3) ** 7 / 16384
        exact_cond = abs(exact_p_tilde / exact_p)
        cond_nums.append(float(exact_cond))

        # Compute the forward error for uncompensated de Casteljau.
        b, db = de_casteljau._compensated_k(s, BEZIER_COEFFS, 2)
        exact_b1 = F(b)
        exact_forward_err1 = abs((exact_b1 - exact_p) / exact_p)
        forward_errs1.append(float(exact_forward_err1))

        # Compute the forward error for compensated de Casteljau.
        b2 = b + db
        exact_b2 = F(b2)
        exact_forward_err2 = abs((exact_b2 - exact_p) / exact_p)
        forward_errs2.append(float(exact_forward_err2))

    # Set a tight ``x``-limit.
    min_exp = np.log(min(cond_nums))
    max_exp = np.log(max(cond_nums))
    delta_exp = max_exp - min_exp
    min_x = np.exp(min_exp - 0.01 * delta_exp)
    max_x = np.exp(max_exp + 0.01 * delta_exp)

    figure = plt.figure()
    ax = figure.gca()
    ax.loglog(
        cond_nums,
        forward_errs1,
        marker="v",
        linestyle="none",
        zorder=2,
        label=r"$\mathtt{DeCasteljau}$",
        color=plot_utils.BLUE,
    )
    ax.loglog(
        cond_nums,
        forward_errs2,
        marker="d",
        linestyle="none",
        zorder=2,
        label=r"$\mathtt{CompDeCasteljau}$",
        color=plot_utils.GREEN,
    )
    # Figure out the bounds before adding the bounding lines.
    min_y, max_y = ax.get_ylim()
    # Plot the lines of the a priori error bounds.
    ax.loglog(
        [min_x, max_x],
        [bound_coeff1 * min_x, bound_coeff1 * max_x],
        color="black",
        alpha=ALPHA,
        zorder=1,
    )
    ax.loglog(
        [min_x, max_x],
        [bound_coeff2 * min_x, bound_coeff2 * max_x],
        color="black",
        alpha=ALPHA,
        zorder=1,
    )
    # Add the ``x = 1/u^k`` vertical lines.
    delta_y = max_y - min_y
    for exponent in (1, 2):
        u_inv = 1.0 / float(U) ** exponent
        ax.loglog(
            [u_inv, u_inv],
            [min_y - 0.05 * delta_y, max_y + 0.05 * delta_y],
            color="black",
            linestyle="dashed",
            alpha=ALPHA,
            zorder=1,
        )
    # Add the ``y = u`` and ``y = 1`` horizontal lines.
    ax.loglog(
        [min_x, max_x],
        [float(U), float(U)],
        color="black",
        linestyle="dashed",
        alpha=ALPHA,
        zorder=1,
    )
    ax.loglog(
        [min_x, max_x],
        [1.0, 1.0],
        color="black",
        linestyle="dashed",
        alpha=ALPHA,
        zorder=1,
    )

    # Make sure the ``y``-limit stays set (the bounds lines exceed).
    ax.set_ylim(min_y, 10.0 ** 18)
    ax.set_xlim(min_x, max_x)
    # Add the legend.
    ax.legend(
        loc="lower right",
        framealpha=1.0,
        frameon=True,
        fontsize=plot_utils.TEXT_SIZE,
    )
    # Set "nice" ticks.
    ax.set_xticks([10.0 ** n for n in range(5, 45 + 5, 5)])
    ax.set_yticks([10.0 ** n for n in range(-18, 14 + 4, 4)])
    # Set special ``xticks`` for ``1/u`` and ``1/u^2``.
    ax.set_xticks([1.0 / float(U), 1.0 / float(U) ** 2], minor=True)
    ax.set_xticklabels([r"$1/\mathbf{u}$", r"$1/\mathbf{u}^2$"], minor=True)
    ax.tick_params(
        axis="x",
        which="minor",
        direction="out",
        top=1,
        bottom=0,
        labelbottom=0,
        labeltop=1,
    )
    # Set special ``yticks`` for ``u`` and ``1``.
    ax.set_yticks([float(U), 1.0], minor=True)
    ax.set_yticklabels([r"$\mathbf{u}$", "$1$"], minor=True)
    ax.tick_params(
        axis="y",
        which="minor",
        direction="out",
        left=0,
        right=1,
        labelleft=0,
        labelright=1,
    )
    # Label the axes.
    ax.set_xlabel("Condition Number", fontsize=plot_utils.TEXT_SIZE)
    ax.set_ylabel("Relative Forward Error", fontsize=plot_utils.TEXT_SIZE)
    # Make sure the ticks are sized appropriately.
    ax.tick_params(labelsize=plot_utils.TICK_SIZE)
    ax.tick_params(labelsize=plot_utils.TEXT_SIZE, which="minor")

    figure.set_size_inches(5.2, 3.9)
    figure.subplots_adjust(
        left=0.12, bottom=0.11, right=0.95, top=0.92, wspace=0.2, hspace=0.2
    )
    filename = "jlcs10_plot.pdf"
    path = plot_utils.get_path("k-compensated", filename)
    figure.savefig(path)
    print("Saved {}".format(filename))
    plt.close(figure)