def plot_distorted(): figure, all_axes = plt.subplots(2, 3, sharex=True, sharey=True) all_axes = all_axes.flatten() for index in range(6): ax = all_axes[index] t = index / 5.0 xt, yt = point_on_characteristic(NODES_X, NODES_Y, t) ax.triplot(xt, yt, TRIANGLES, color=plot_utils.BLUE) title = get_title(t) ax.set_title(title, fontsize=FONT_SIZE) # Set the axis. ax.axis("scaled") ax.set_xlim(-1.35, 3.6) ax.set_ylim(-1.35, 2.35) for ax in all_axes: ax.tick_params(labelsize=LABEL_SIZE, which="both") all_axes[0].set_yticks([-1.0, 0.5, 2.0]) all_axes[0].set_xticks([-1.0, 1.0, 3.0]) all_axes[0].set_xticklabels(["$-1.0$", "$1.0$", "$3.0$"]) figure.set_size_inches(8.74, 4.8) figure.subplots_adjust(left=0.06, bottom=0.06, right=0.99, top=0.93, wspace=0.0, hspace=0.2) filename = "mesh_distortion.pdf" path = plot_utils.get_path("slides", filename) figure.savefig(path) print("Saved {}".format(filename)) plt.close(figure)
def plot_distorted(): figure, all_axes = plt.subplots(1, 5, sharex=True, sharey=True) all_axes = all_axes.flatten() for index in range(5): ax = all_axes[index] t = index / 4.0 xt, yt = point_on_characteristic(NODES_X, NODES_Y, t) ax.triplot(xt, yt, TRIANGLES, color=plot_utils.BLUE, linewidth=0.9) title = get_title(t) ax.set_title(title, fontsize=plot_utils.TEXT_SIZE) # Set the axis. ax.axis("scaled") ax.set_xlim(-1.35, 3.6) ax.set_ylim(-1.35, 2.35) all_axes[0].yaxis.set_tick_params(labelsize=plot_utils.TICK_SIZE) for ax in all_axes: ax.xaxis.set_tick_params(labelsize=plot_utils.TICK_SIZE) all_axes[0].set_yticks([-1.0, 0.5, 2.0]) all_axes[0].set_xticks([-1.0, 1.0, 3.0]) all_axes[0].set_xticklabels(["$-1.0$", "$1.0$", "$3.0$"]) figure.set_size_inches(6.4, 1.45) figure.subplots_adjust(left=0.07, bottom=0.02, right=0.99, top=0.98, wspace=0.07, hspace=0.2) filename = "mesh_distortion.pdf" path = plot_utils.get_path("solution-transfer", filename) figure.savefig(path) print("Saved {}".format(filename)) plt.close(figure)
def image1(): figure = plt.figure() ax = figure.gca() curve1 = bezier.Curve(COEFFS1, degree=2, _copy=False) curve2 = bezier.Curve(COEFFS2, degree=2, _copy=False) curve1.plot(256, ax=ax, color=plot_utils.BLUE) ax.lines[-1].set_label("$b_0(s)$") curve2.plot(256, ax=ax, color=plot_utils.GREEN) ax.lines[-1].set_label("$b_1(t)$") ax.plot( [0.0], [1.0], marker="o", markersize=4.0, color="black", linestyle="none", ) ax.legend(fontsize=plot_utils.TEXT_SIZE) ax.tick_params(labelsize=plot_utils.TICK_SIZE) ax.axis("scaled") figure.set_size_inches(5.4, 1.6) figure.subplots_adjust( left=0.05, bottom=0.09, right=0.99, top=0.99, wspace=0.2, hspace=0.2 ) filename = "tangent_intersection.pdf" path = plot_utils.get_path("slides", filename) figure.savefig(path) print("Saved {}".format(filename)) plt.close(figure)
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)
def image3(): figure, (ax1, ax2, ax3) = plt.subplots(1, 3) control_pts1a = np.asfortranarray([[0.0, 0.375, 1.0], [0.0, 0.5, 0.125]]) curve1a = bezier.Curve(control_pts1a, degree=2) control_pts1b = np.asfortranarray([[0.25, -0.125, 0.5], [-0.125, 0.375, 1.0]]) curve1b = bezier.Curve(control_pts1b, degree=2) plot_with_bbox(curve1a, ax1, plot_utils.BLUE) plot_with_bbox(curve1b, ax1, plot_utils.GREEN) control_pts2a = np.asfortranarray([[0.0, 0.75, 1.0], [1.0, 0.75, 0.0]]) curve2a = bezier.Curve(control_pts2a, degree=2) control_pts2b = np.asfortranarray([[0.375, 0.625, 1.375], [1.375, 0.625, 0.375]]) curve2b = bezier.Curve(control_pts2b, degree=2) plot_with_bbox(curve2a, ax2, plot_utils.BLUE) plot_with_bbox(curve2b, ax2, plot_utils.GREEN) control_pts3a = np.asfortranarray([[0.0, 0.25, 1.0], [-0.25, 0.25, -0.75]]) curve3a = bezier.Curve(control_pts3a, degree=2) control_pts3b = np.asfortranarray([[1.0, 1.5, 2.0], [-1.0, -1.5, -1.0]]) curve3b = bezier.Curve(control_pts3b, degree=2) plot_with_bbox(curve3a, ax3, plot_utils.BLUE) plot_with_bbox(curve3b, ax3, plot_utils.GREEN) for ax in (ax1, ax2, ax3): simple_axis(ax) ax1.set_xlim(-0.2, 1.1) ax1.set_ylim(-0.2, 1.1) ax1.set_title("MAYBE", fontsize=plot_utils.TEXT_SIZE) ax2.set_xlim(-0.1, 1.5) ax2.set_ylim(-0.1, 1.5) ax2.set_title("MAYBE", fontsize=plot_utils.TEXT_SIZE) ax3.set_xlim(-0.1, 2.1) ax3.set_ylim(-1.7, 0.5) ax3.set_title("NO", fontsize=plot_utils.TEXT_SIZE) figure.set_size_inches(6.0, 2.2) figure.subplots_adjust(left=0.01, bottom=0.01, right=0.99, top=0.9, wspace=0.04, hspace=0.2) filename = "bbox_check.pdf" path = plot_utils.get_path("bezier-intersection", filename) figure.savefig(path) print("Saved {}".format(filename)) plt.close(figure)
def image1(): figure, (ax1, ax2, ax3) = plt.subplots(1, 3, sharex=True, sharey=True) nodes = np.asfortranarray([[0.0, 1.0, 2.0, 4.0], [0.0, 4.0, 0.0, 3.0]]) curve = bezier.Curve(nodes, degree=2) left, right = curve.subdivide() curve.plot(256, ax=ax1, alpha=0.25, color="black") left.plot(256, ax=ax1) curve.plot(256, ax=ax2) curve.plot(256, ax=ax3, alpha=0.25, color="black") right.plot(256, ax=ax3) ax1.text( 2.5, 0.25, r"$\left[0, \frac{1}{2}\right]$", horizontalalignment="center", verticalalignment="center", fontsize=plot_utils.TEXT_SIZE, ) ax2.text( 2.5, 0.25, r"$\left[0, 1\right]$", horizontalalignment="center", verticalalignment="center", fontsize=plot_utils.TEXT_SIZE, ) ax3.text( 2.5, 0.25, r"$\left[\frac{1}{2}, 1\right]$", horizontalalignment="center", verticalalignment="center", fontsize=plot_utils.TEXT_SIZE, ) for ax in (ax1, ax2, ax3): simple_axis(ax) figure.set_size_inches(6.0, 1.5) figure.subplots_adjust(left=0.01, bottom=0.01, right=0.99, top=0.99, wspace=0.04, hspace=0.2) filename = "subdivide_curve.pdf" path = plot_utils.get_path("bezier-intersection", filename) figure.savefig(path) print("Saved {}".format(filename)) plt.close(figure)
def image4(): figure, all_axes = plt.subplots(2, 7) all_axes = all_axes.flatten() nodes15 = np.asfortranarray([[0.25, 0.625, 1.0], [0.625, 0.25, 1.0]]) curve15 = bezier.Curve(nodes15, degree=2) nodes25 = np.asfortranarray([[0.0, 0.25, 0.75, 1.0], [0.5, 1.0, 1.5, 0.5]]) curve25 = bezier.Curve(nodes25, degree=3) color1 = plot_utils.BLUE curve15.plot(256, ax=all_axes[0], color=color1) color2 = plot_utils.GREEN curve25.plot(256, ax=all_axes[0], color=color2) choices1 = [1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1] choices2 = [1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1] first = curve15 second = curve25 for i in range(13): ax = all_axes[i + 1] index1 = choices1[i] index2 = choices2[i] first = first.subdivide()[index1] second = second.subdivide()[index2] first.plot(256, ax=ax, color=color1) second.plot(256, ax=ax, color=color2) # After splitting, put the bounding box on the previous axis. prev_ax = all_axes[i] add_patch(first, prev_ax, color1) add_patch(second, prev_ax, color2) for ax in all_axes: ax.axis("equal") ax.set_xticklabels([]) ax.set_yticklabels([]) figure.set_size_inches(6.4, 2.4) figure.subplots_adjust(left=0.01, bottom=0.01, right=0.99, top=0.99, wspace=0.06, hspace=0.04) filename = "subdivision_linearized.pdf" path = plot_utils.get_path("bezier-intersection", filename) figure.savefig(path) print("Saved {}".format(filename)) plt.close(figure)
def _main(): s_vals = np.linspace(ROOT - DELTA_S, ROOT + DELTA_S, NUM_POINTS) de_casteljau2 = [] exact = [] for s in s_vals: de_casteljau2.append(de_casteljau.compensated(s, BEZIER_COEFFS)) exact_s = F(s) exact_p = (2 * exact_s - 1)**3 * (exact_s - 1) exact.append(float(exact_p)) figure, (ax1, ax2) = plt.subplots(1, 2, sharex=True, sharey=True) ax1.plot(s_vals, de_casteljau2) ax2.plot(s_vals, exact) # 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{CompDeCasteljau}$", fontsize=plot_utils.TEXT_SIZE) ax2.set_title("$p(s)$", fontsize=plot_utils.TEXT_SIZE) ax1.tick_params(labelsize=plot_utils.TICK_SIZE, which="both") ax2.tick_params(labelsize=plot_utils.TICK_SIZE, which="both") filename = "compensated_insufficient.pdf" # NOTE: These are (intended to be) the same settings used in # ``horner_inferior.py``, so they should probably be # kept in sync. figure.set_size_inches(6.0, 2.9) figure.subplots_adjust(left=0.07, bottom=0.13, right=0.97, top=0.92, wspace=0.13, hspace=0.20) path = plot_utils.get_path("k-compensated", filename) figure.savefig(path) print("Saved {}".format(filename)) plt.close(figure)
def main(): # u_t + u_x = 0 # u(x, t) = u(x - t, 0) min_x = -1.5 max_x = 3.5 x_vals = np.linspace(min_x, max_x, 2048 + 1) # u(x, 0) = x^3 u0 = x_vals * x_vals * x_vals u2 = (x_vals - 2.0) * (x_vals - 2.0) * (x_vals - 2.0) figure = plt.figure() ax = figure.gca() ax.plot(x_vals, u0, label="$u(x, 0)$", color=plot_utils.BLUE) ax.plot(x_vals, u2, label="$u(x, 2)$", color=plot_utils.GREEN) ax.annotate( "", xy=(2.875, 0.75), xytext=(1.0, 0.75), arrowprops={ "arrowstyle": "->", "linewidth": 2.0, "color": "black" }, ) ax.legend(loc="upper left", fontsize=plot_utils.TEXT_SIZE) ax.axis("scaled") ax.set_xlim(min_x, max_x) ax.set_ylim(-1.1, 1.1) ax.set_xlabel("$x$", fontsize=plot_utils.TEXT_SIZE) ax.set_ylabel("$u$", rotation=0, fontsize=plot_utils.TEXT_SIZE) ax.xaxis.set_tick_params(labelsize=plot_utils.TICK_SIZE) ax.yaxis.set_tick_params(labelsize=plot_utils.TICK_SIZE) figure.set_size_inches(4.8, 2.4) figure.subplots_adjust(left=0.12, bottom=0.1, right=0.99, top=1.04, wspace=0.2, hspace=0.2) filename = "simple_transport.pdf" path = plot_utils.get_path("solution-transfer", filename) figure.savefig(path) print("Saved {}".format(filename)) plt.close(figure)
def image1(): nodes = np.asfortranarray([[0.0, 1.5, 3.0, 0.75, 2.25, 0.0], [0.0, -0.5, 0.0, 1.0, 1.5, 2.0]]) triangle = bezier.Surface(nodes, degree=2, _copy=False) point = triangle.evaluate_cartesian(0.25, 0.125) xv, yv = point.flatten() sub_triangles = triangle.subdivide() edges = triangle.edges figure, all_axes = plt.subplots(2, 2, sharex=True, sharey=True) all_axes = all_axes.flatten() for ax, sub_triangle in zip(all_axes, sub_triangles): # Add the bounding box for the sub triangle. add_patch(sub_triangle, ax, plot_utils.GREEN) # Add the triangle boundary to each subplot. for edge in edges: edge.plot(256, ax=ax, color=plot_utils.BLUE) # Add the sub triangle. sub_triangle.plot(256, ax=ax, color=plot_utils.BLUE) # Add the point to be found. ax.plot( [xv], [yv], color="black", marker="o", markersize=3, linestyle="none", ) for ax in all_axes: ax.set_aspect("equal") # One axis sets all axis all_axes[0].set_xticklabels([]) all_axes[0].set_yticklabels([]) figure.set_size_inches(4.0, 3.0) figure.subplots_adjust(left=0.01, bottom=0.01, right=0.99, top=0.99, wspace=0.03, hspace=0.04) filename = "locate_in_triangle.pdf" path = plot_utils.get_path("bezier-intersection", filename) figure.savefig(path) print("Saved {}".format(filename)) plt.close(figure)
def image2(): nodes15 = np.asfortranarray([[0.25, 0.625, 1.0], [0.625, 0.25, 1.0]]) curve15 = bezier.Curve(nodes15, degree=2) nodes25 = np.asfortranarray([[0.0, 0.25, 0.75, 1.0], [0.5, 1.0, 1.5, 0.5]]) curve25 = bezier.Curve(nodes25, degree=3) figure, all_axes = plt.subplots(2, 3, sharex=True, sharey=True) ax1, ax2, ax3, ax4, ax5, ax6 = all_axes.flatten() color1 = plot_utils.BLUE color2 = plot_utils.GREEN plot_with_bbox(curve15, ax1, color1) plot_with_bbox(curve25, ax1, color2) left, right = refine_candidates([curve15], [curve25]) for curve in left: plot_with_bbox(curve, ax2, color1) for curve in right: plot_with_bbox(curve, ax2, color2) for ax in (ax3, ax4, ax5, ax6): left, right = refine_candidates(left, right) curve15.plot(256, color=color1, alpha=0.5, ax=ax) for curve in left: plot_with_bbox(curve, ax, color=color1) curve25.plot(256, color=color2, alpha=0.5, ax=ax) for curve in right: plot_with_bbox(curve, ax, color2) for ax in (ax1, ax2, ax3, ax4, ax5, ax6): simple_axis(ax) ax.set_xlim(-0.05, 1.05) ax.set_ylim(0.4, 1.15) figure.set_size_inches(6.0, 2.8) figure.subplots_adjust(left=0.01, bottom=0.01, right=0.99, top=0.99, wspace=0.04, hspace=0.04) filename = "subdivision_process.pdf" path = plot_utils.get_path("bezier-intersection", filename) figure.savefig(path) print("Saved {}".format(filename)) plt.close(figure)
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)
def main(filename=None): s_vals = np.linspace(ROOT - DELTA_S, ROOT + DELTA_S, NUM_POINTS) horner1 = [] de_casteljau1 = [] for s in s_vals: horner1.append(horner.basic(s, POLY_COEFFS)) de_casteljau1.append(de_casteljau.basic(s, BEZIER_COEFFS)) figure, (ax1, ax2) = plt.subplots(1, 2, sharex=True, sharey=True) ax1.plot(s_vals, horner1) ax2.plot(s_vals, de_casteljau1) # 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{Horner}$") ax2.set_title(r"$\mathtt{DeCasteljau}$") if filename is None: plt.show() else: figure.set_size_inches(9.87, 4.8) figure.subplots_adjust( left=0.06, bottom=0.12, right=0.97, top=0.92, wspace=0.13, hspace=0.20, ) path = plot_utils.get_path(filename) figure.savefig(path, bbox_inches="tight") print("Saved {}".format(filename)) plt.close(figure)
def image2(): figure, (ax1, ax2) = plt.subplots(1, 2) nodes1a = np.asfortranarray([[0.0, 1.0, 0.0], [0.0, 0.0, 1.0]]) nodes2a = np.asfortranarray([[-0.125, 1.0, 0.125], [-0.0625, 0.5, 0.375]]) nodes1b = np.asfortranarray([[0.0, 0.375, 1.0, 0.25, 0.75, 0.5], [0.0, 0.375, 0.0, 0.5, 0.5, 1.0]]) nodes2b = np.asfortranarray([ [1.0, 0.625, 0.0, 0.75, 0.25, 0.5], [0.375, -0.125, 0.375, -0.1875, -0.1875, -0.75], ]) info = ((nodes1a, nodes2a, ax1), (nodes1b, nodes2b, ax2)) for nodes1, nodes2, ax in info: triangle1 = bezier.Surface.from_nodes(nodes1) triangle2 = bezier.Surface.from_nodes(nodes2) intersections = triangle1.intersect(triangle2) triangle1.plot(256, ax=ax, color=plot_utils.BLUE) triangle2.plot(256, ax=ax, color=plot_utils.GREEN) for intersection in intersections: intersection.plot(256, ax=ax, color=plot_utils.RED) for ax in (ax1, ax2): ax.tick_params(labelsize=LABEL_SIZE, which="both") ax.axis("equal") ax1.set_title("Convex Intersection", fontsize=FONT_SIZE) ax2.set_title("Multiple Intersections", fontsize=FONT_SIZE) figure.set_size_inches(8.74, 4.8) figure.subplots_adjust(left=0.06, bottom=0.06, right=0.99, top=0.93, wspace=0.18, hspace=0.2) filename = "split_intersection.pdf" path = plot_utils.get_path("slides", filename) figure.savefig(path) print("Saved {}".format(filename)) plt.close(figure)
def image1(): figure, (ax1, ax2) = plt.subplots(1, 2) nodes1 = np.asfortranarray([[0.0, 3.0, 7.0], [5.0, 0.0, 8.0]]) triangle1 = bezier.Surface(nodes1, degree=1) triangle1.plot(256, ax=ax1) nodes2 = np.asfortranarray([[0.0, 1.0, 2.0, 2.0, 2.0, 0.0], [0.0, 0.0, 0.0, 1.0, 2.0, 2.0]]) triangle2 = bezier.Surface(nodes2, degree=2) triangle2.plot(256, ax=ax2) params = np.asfortranarray([[0.125, 0.125], [0.125, 0.75]]) points1 = triangle1.evaluate_cartesian_multi(params) ax1.plot(points1[0, :], points1[1, :], marker="o", color="black") points2 = triangle2.evaluate_cartesian_multi(params) ax2.plot(points2[0, :], points2[1, :], marker="o", color="black") for ax in (ax1, ax2): ax.tick_params(labelsize=LABEL_SIZE, which="both") ax.axis("equal") ax1.set_title("Convex", fontsize=FONT_SIZE) ax2.set_title("Not (Necessarily) Convex", fontsize=FONT_SIZE) figure.set_size_inches(8.74, 4.8) figure.subplots_adjust(left=0.05, bottom=0.06, right=0.99, top=0.93, wspace=0.12, hspace=0.2) filename = "not_convex.pdf" path = plot_utils.get_path("slides", filename) figure.savefig(path) print("Saved {}".format(filename)) plt.close(figure)
def main(): figure, (ax1, ax2, ax3) = plt.subplots(1, 3) ctx = mpmath.MPContext() ctx.prec = 500 add_plot(ax1, ctx, 5, 30) add_plot(ax2, ctx, 15, 30) add_plot(ax3, ctx, 25, 30) for ax in (ax1, ax2, ax3): ax.tick_params(labelsize=plot_utils.TICK_SIZE) filename = "root_plots.pdf" figure.set_size_inches(6.4, 2.4) figure.subplots_adjust(left=0.08, bottom=0.11, right=0.99, top=0.92, wspace=0.29, hspace=0.2) path = plot_utils.get_path("compensated-newton", filename) figure.savefig(path) print("Saved {}".format(filename)) plt.close(figure)
def distort_cubic_tri(num_columns): node1 = np.array([-0.75, 0.0]) node2 = np.array([2.25, -1.5]) node3 = np.array([1.5, 1.5]) control_points = np.array([ node1, 0.5 * (node1 + node2), node2, 0.5 * (node1 + node3), 0.5 * (node2 + node3), node3, ]) figure, all_axes = plt.subplots(2, 3, sharex=True, sharey=True) min_y = -1.65 max_y = 2.8 control_x = control_points[:, 0] control_y = control_points[:, 1] bezier_nodes = np.empty((2, len(control_x)), order="F") # First add characteristic curves to the top row of axes. for i, xv in enumerate(control_x): yv = control_y[i] min_t = min_y - yv max_t = max_y - yv t_vals = np.linspace(min_t, max_t, 100) to_plot = point_on_characteristic(xv, yv, t_vals) for index, ax in enumerate(all_axes[0, :]): if index == num_columns: break ax.plot(to_plot[0], to_plot[1], color=plot_utils.GREEN, alpha=ALPHA) for index, ax_top in enumerate(all_axes[0, :]): if index == num_columns: break t = 0.5 * index xt, yt = point_on_characteristic(control_x, control_y, t) corner_x = xt[(0, 2, 5, 0), ] corner_y = yt[(0, 2, 5, 0), ] ax_top.plot(corner_x, corner_y) title = get_title(t) ax_top.set_title(title, fontsize=plot_utils.TEXT_SIZE) # Now plot the curved element in the "below" axis". ax_below = all_axes[1, index] # NOTE: This assumes quadratic nodes. bezier_nodes[:, 0] = xt[0], yt[0] bezier_nodes[:, 1] = ( 2.0 * xt[1] - 0.5 * xt[0] - 0.5 * xt[2], 2.0 * yt[1] - 0.5 * yt[0] - 0.5 * yt[2], ) bezier_nodes[:, 2] = xt[2], yt[2] bezier_nodes[:, 3] = ( 2.0 * xt[3] - 0.5 * xt[0] - 0.5 * xt[5], 2.0 * yt[3] - 0.5 * yt[0] - 0.5 * yt[5], ) bezier_nodes[:, 4] = ( 2.0 * xt[4] - 0.5 * xt[2] - 0.5 * xt[5], 2.0 * yt[4] - 0.5 * yt[2] - 0.5 * yt[5], ) bezier_nodes[:, 5] = xt[5], yt[5] surface = bezier.Surface.from_nodes(bezier_nodes) surface.plot(256, ax=ax_below) # Add "nodes" to both plots. for ax in (ax_top, ax_below): ax.plot( xt, yt, color="black", marker="o", linestyle="none", markersize=4, ) # Add shadow "nodes" to top row for "next" plots. for next_index in range(index + 1, 3): if next_index == num_columns: break ax = all_axes[0, next_index] ax.plot( xt, yt, color="black", alpha=0.5 - 0.25 * (next_index - index - 1), marker="o", linestyle="none", markersize=4, ) for ax in all_axes.flatten(): ax.axis("scaled") # One axis, all axes (since sharex/sharey). ax1 = all_axes[0, 0] ax1.set_xlim(-1.0, 5.9) ax1.set_ylim(min_y, max_y) ax1.set_xticks([0.0, 1.0, 2.0, 3.0, 4.0, 5.0]) ax1.set_xticklabels(["$0.0$", "$1.0$", "$2.0$", "$3.0$", "$4.0$", "$5.0$"]) ax1.set_yticks([-1.5, -0.5, 0.5, 1.5, 2.5]) ax1.set_yticklabels(["$-1.5$", "$-0.5$", "$0.5$", "$1.5$", "$2.5$"]) ax1.yaxis.set_tick_params(labelsize=plot_utils.TICK_SIZE) all_axes[1, 0].yaxis.set_tick_params(labelsize=plot_utils.TICK_SIZE) for ax in all_axes[1, :]: ax.xaxis.set_tick_params(labelsize=plot_utils.TICK_SIZE) for ax in all_axes[:, num_columns:].flatten(): ax.axis("off") figure.set_size_inches(6.0, 2.9) figure.subplots_adjust(left=0.07, bottom=0.05, right=0.99, top=0.97, wspace=0.04, hspace=-0.1) filename = "element_distortion{}.pdf".format(num_columns) path = plot_utils.get_path("slides", filename) figure.savefig(path) print("Saved {}".format(filename)) plt.close(figure)
def error_plot(slide_num, data): cond_nums, rel_errors_basic, rel_errors_accurate, rel_errors_full = data figure = plt.figure() ax = figure.gca() ax.loglog( cond_nums, rel_errors_basic, marker="d", linestyle="none", markersize=7, color=plot_utils.BLUE, zorder=2, label=r"$\mathtt{DNewtonBasic}$", ) line2, = ax.loglog( cond_nums, rel_errors_accurate, marker="o", linestyle="none", markersize=3, color="black", zorder=2, label=r"$\mathtt{DNewtonAccurate}$", ) # H/T: (http://widu.tumblr.com/post/43624348228/ # making-unfilled-hollow-markers-in-matplotlib) line3, = ax.loglog( cond_nums, rel_errors_full, marker="o", linestyle="none", markersize=6, markeredgewidth=1, markerfacecolor="none", color=plot_utils.GREEN, zorder=2, label=r"$\mathtt{DNewtonFull}$", ) # Add the error lines. ax.loglog( [1e-3, 1e30], [U * 1e-3, U * 1e30], color="black", linestyle="dashed", alpha=ALPHA, zorder=1, ) ax.loglog( [1e10, 1e40], [U ** 2 * 1e10, U ** 2 * 1e40], color="black", linestyle="dashed", alpha=ALPHA, zorder=1, ) # Add the ``x = 1/u^k`` vertical lines. min_x, max_x = get_bounds(cond_nums) min_y, max_y = get_bounds( rel_errors_basic + rel_errors_accurate + rel_errors_full ) delta_y = max_y - min_y for exponent in (1, 2, 3): 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 = 1`` and ``y = u`` horizontal lines. for exponent in (0, 1): u_pow = float(U) ** exponent ax.loglog( [min_x, max_x], [u_pow, u_pow], color="black", linestyle="dashed", alpha=ALPHA, zorder=1, ) # Set the axis limits. ax.set_xlim(min_x, max_x) ax.set_ylim(min_y, max_y) # Set "nice" ticks. ax.set_xticks([10.0 ** n for n in range(0, 50 + 10, 10)]) ax.set_yticks([10.0 ** n for n in range(-16, 0 + 4, 4)]) # Set special ``xticks`` for ``1/u^k``. u_xticks = [1.0 / float(U), 1.0 / float(U) ** 2, 1.0 / float(U) ** 3] u_xticklabels = [ r"$1/\mathbf{u}$", r"$1/\mathbf{u}^2$", r"$1/\mathbf{u}^3$", ] 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`` 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) if slide_num < 2: line2.set_visible(False) # This is to fool the legend. line2.set_alpha(0.0) if slide_num < 3: line3.set_visible(False) # This is to fool the legend. line3.set_alpha(0.0) # Add the legend. legend = ax.legend( loc="lower right", framealpha=1.0, frameon=True, fontsize=plot_utils.TEXT_SIZE, ) # Leave the text intact but make it "invisible". if slide_num < 2: _, text2, _ = legend.get_texts() text2.set_alpha(0.0) if slide_num < 3: _, _, text3 = legend.get_texts() text3.set_alpha(0.0) ax.tick_params(labelsize=plot_utils.TICK_SIZE) ax.tick_params(labelsize=plot_utils.TEXT_SIZE, which="minor") figure.set_size_inches(5.4, 4.0) figure.subplots_adjust( left=0.12, bottom=0.11, right=0.95, top=0.92, wspace=0.2, hspace=0.2 ) filename = "newton_de_casteljau{}.pdf".format(slide_num) path = plot_utils.get_path("slides", filename) figure.savefig(path) print("Saved {}".format(filename)) plt.close(figure)
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)
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)
def intersection_area(): # NOTE: These are surfaces 30Q and 31Q from the ``bezier`` project. nodes1 = np.asfortranarray([ [-0.25, 0.1875, 0.625, -0.25, 0.1875, -0.25], [-0.25, -0.25, -0.25, 0.1875, 0.1875, 0.625], ]) surface1 = bezier.Surface.from_nodes(nodes1) edge11, edge12, edge13 = surface1.edges nodes2 = np.asfortranarray([ [0.0, 0.5, 1.0, 0.0625, 0.4375, -0.125], [-1.0, -0.5, 0.0, -0.5, 0.0, 0.0], ]) surface2 = bezier.Surface.from_nodes(nodes2) edge21, edge22, edge23 = surface2.edges exact_area = F(7, 48) figure, all_axes = plt.subplots(2, 3) all_axes = all_axes.flatten() ax = all_axes[0] intersection, = surface1.intersect(surface2) surface1.plot(256, ax=ax, color=plot_utils.BLUE) surface2.plot(256, ax=ax, color=plot_utils.GREEN) intersection.plot(256, ax=ax, color=plot_utils.RED) ax.set_title("Curved", fontsize=plot_utils.TEXT_SIZE) error_vals = [] for n in range(1, 20 + 1): N = 2**n s_vals = np.linspace(0.0, 1.0, N + 1)[:-1] polygon_nodes1 = edges_to_polygon(edge11, edge12, edge13, s_vals) polygon1 = shapely.geometry.Polygon(polygon_nodes1.T) polygon_nodes2 = edges_to_polygon(edge21, edge22, edge23, s_vals) polygon2 = shapely.geometry.Polygon(polygon_nodes2.T) poly_intersect = polygon1.intersection(polygon2) if not isinstance(poly_intersect, shapely.geometry.Polygon): raise TypeError(poly_intersect) # Compute the relative error. approximate_area = F(poly_intersect.area) rel_error = abs(approximate_area - exact_area) / exact_area error_vals.append((N, float(rel_error))) # Plot the "approximate" surfaces as well as their # polygonal intersection. if n in (1, 2, 3, 4): ax = all_axes[n] for polygon_nodes, color in ( (polygon_nodes1, plot_utils.BLUE), (polygon_nodes2, plot_utils.GREEN), ): # Wrap-around the first node so the polygon is closed. polygon_nodes = np.hstack( [polygon_nodes, polygon_nodes[:, :1]]) patch = matplotlib.patches.PathPatch( matplotlib.path.Path(polygon_nodes.T), alpha=0.625, color=color, ) ax.add_patch(patch) ax.plot( polygon_nodes[0, :], polygon_nodes[1, :], color=color, marker="o", markersize=4, ) boundary_x, boundary_y = poly_intersect.exterior.coords.xy boundary = np.empty((len(boundary_x), 2)) boundary[:, 0] = boundary_x boundary[:, 1] = boundary_y patch = matplotlib.patches.PathPatch( matplotlib.path.Path(boundary), alpha=0.625, color=plot_utils.RED, ) new_nodes = [] for i, node in enumerate(boundary): if not (contains_column(node, polygon_nodes1) or contains_column(node, polygon_nodes2)): new_nodes.append(i) if new_nodes: ax.plot( boundary[new_nodes, 0], boundary[new_nodes, 1], color=plot_utils.RED, marker="o", markersize=4, linestyle="none", ) ax.plot( boundary[:-1, 0], boundary[:-1, 1], color=plot_utils.RED, marker="o", markersize=4, markeredgewidth=1, markerfacecolor="none", linestyle="none", ) ax.add_patch(patch) ax.set_title("$N = {:d}$".format(N), fontsize=plot_utils.TEXT_SIZE) for ax in all_axes[:5]: ax.axis("equal") ax.set_xlim(-0.3125, 1.0625) ax.set_ylim(-1.08125, 0.70625) for ax in all_axes[:3]: ax.set_xticklabels([]) for ax in all_axes[(1, 2, 4), ]: ax.set_yticklabels([]) error_vals = np.array(error_vals) ax = all_axes[5] ax.loglog( error_vals[:, 0], error_vals[:, 1], basex=2, marker="o", markersize=4, label="Polygonal", ) curved_poly_area = F(compute_area(*intersection._edges)) curved_rel_error = float(abs(exact_area - curved_poly_area) / exact_area) ax.loglog( [error_vals[0, 0], error_vals[-1, 0]], [curved_rel_error, curved_rel_error], basex=2, color="black", linestyle="dashed", label="Curved", ) ax.legend(loc="lower left", fontsize=plot_utils.TEXT_SIZE) ax.set_title("Intersection Area Estimates", fontsize=plot_utils.TEXT_SIZE) ax.set_xlabel("Line Segments per Side ($N$)", fontsize=plot_utils.TEXT_SIZE) ax.set_ylabel("Relative Error", fontsize=plot_utils.TEXT_SIZE) ax.yaxis.tick_right() ax.yaxis.set_label_position("right") all_axes[0].yaxis.set_tick_params(labelsize=plot_utils.TICK_SIZE) all_axes[3].yaxis.set_tick_params(labelsize=plot_utils.TICK_SIZE) all_axes[5].yaxis.set_tick_params(labelsize=plot_utils.TICK_SIZE) all_axes[3].xaxis.set_tick_params(labelsize=plot_utils.TICK_SIZE) all_axes[4].xaxis.set_tick_params(labelsize=plot_utils.TICK_SIZE) all_axes[5].xaxis.set_tick_params(labelsize=plot_utils.TICK_SIZE) all_axes[3].set_xticks([-0.4, 0.1, 0.6, 1.1]) all_axes[4].set_xticks([-0.4, 0.1, 0.6, 1.1]) all_axes[5].set_xticks([2.0**4, 2.0**8, 2.0**12, 2.0**16, 2.0**20]) figure.set_size_inches(6.0, 4.2) figure.subplots_adjust(left=0.08, bottom=0.11, right=0.9, top=0.95, wspace=0.03, hspace=0.15) filename = "polygon_vs_curved_intersection.pdf" path = plot_utils.get_path("solution-transfer", filename) figure.savefig(path) print("Saved {}".format(filename)) plt.close(figure)
def main(): ctx = mpmath.MPContext() ctx.prec = 500 s0 = 1.0 t0 = 1.0 cond_nums = np.empty((24, )) rel_errors1 = np.empty((24, )) rel_errors2 = np.empty((24, )) for n in range(3, 49 + 2, 2): r = 0.5**n r_inv = 1.0 / r cond_num = kappa(r, ctx) # Compute the coefficients. coeffs1 = np.asfortranarray([[-2.0 - r, -2.0 - r, 6.0 - r], [2.0 + r_inv, r_inv, 2.0 + r_inv]]) coeffs2 = np.asfortranarray([[-4.0, -4.0, 12.0], [5.0 + r_inv, -3.0 + r_inv, 5.0 + r_inv]]) # Use Newton's method to find the intersection. iterates1 = newton_bezier.newton(s0, coeffs1, t0, coeffs2, newton_bezier.standard_residual) iterates2 = newton_bezier.newton(s0, coeffs1, t0, coeffs2, newton_bezier.compensated_residual) # Just keep the final iterate and discard the rest. s1, t1 = iterates1[-1] s2, t2 = iterates2[-1] # Compute the relative error in the 2-norm. sqrt_r = ctx.sqrt(r) alpha = 0.5 * (1 + sqrt_r) beta = 0.25 * (2 + sqrt_r) size = ctx.norm([alpha, beta], p=2) rel_error1 = ctx.norm([alpha - s1, beta - t1], p=2) / size rel_error2 = ctx.norm([alpha - s2, beta - t2], p=2) / size # Convert the errors to floats and store. cond_nums[(n - 3) // 2] = plot_utils.to_float(cond_num) rel_errors1[(n - 3) // 2] = plot_utils.to_float(rel_error1) rel_errors2[(n - 3) // 2] = plot_utils.to_float(rel_error2) # Make sure all of the non-compensated errors are non-zero and # at least one of the compensated errors is zero. if rel_errors1.min() <= 0.0: raise ValueError("Unexpected minimum error (non-compensated).") if rel_errors2.min() <= 0.0: raise ValueError("Unexpected minimum error (compensated).") figure = plt.figure() ax = figure.gca() # Add all of the non-compensated errors. ax.loglog( cond_nums, rel_errors1, marker="v", linestyle="none", color=plot_utils.BLUE, label="Standard", ) # Add all of the compensated errors. ax.loglog( cond_nums, rel_errors2, marker="d", linestyle="none", color=plot_utils.GREEN, label="Compensated", ) # Plot the lines of the a priori error bounds. min_x = 1.5 max_x = 5.0e+32 for coeff in (U, U**2): start_x = min_x start_y = coeff * start_x ax.loglog( [start_x, max_x], [start_y, coeff * max_x], color="black", alpha=ALPHA, zorder=1, ) # Add the ``x = 1/U`` and ``x = 1/U^2`` vertical lines. min_y = 1e-18 max_y = 5.0 for x_val in (1.0 / U, 1.0 / U**2): ax.loglog( [x_val, x_val], [min_y, max_y], color="black", linestyle="dashed", alpha=ALPHA, zorder=1, ) # Add the ``y = u`` and ``y = 1`` horizontal lines. for y_val in (U, 1.0): ax.loglog( [min_x, max_x], [y_val, y_val], color="black", linestyle="dashed", alpha=ALPHA, zorder=1, ) # Set "nice" ticks. ax.set_xticks([10.0**n for n in range(4, 28 + 8, 8)]) ax.set_yticks([10.0**n for n in range(-16, 0 + 4, 4)]) # Set special ``xticks`` for ``1/u`` and ``1/u^2``. ax.set_xticks([1.0 / U, 1.0 / 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([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") # Set axis limits. ax.set_xlim(min_x, max_x) ax.set_ylim(min_y, max_y) # Add the legend. ax.legend( loc="upper left", framealpha=1.0, frameon=True, fontsize=plot_utils.TEXT_SIZE, ) figure.set_size_inches(6.0, 4.5) figure.subplots_adjust(left=0.11, bottom=0.09, right=0.96, top=0.94, wspace=0.2, hspace=0.2) filename = "almost_tangent.pdf" path = plot_utils.get_path("compensated-newton", filename) figure.savefig(path) print("Saved {}".format(filename)) plt.close(figure)
def boundary_leak(slide_num): bez_triangle = bezier.Surface(NODES, degree=2, _copy=False) figure, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2, sharex=True, sharey=True) # Add reference triangle to both top subplots. for ax in (ax1, ax2): if slide_num == 1: ax.plot([0, 1], [0, 0], color=plot_utils.BLUE) ax.plot([1, 0], [0, 1], color="black", alpha=ALPHA) ax.plot([0, 0], [1, 0], color="black", alpha=ALPHA) elif slide_num == 2: ax.plot([0, 1], [0, 0], color="black", alpha=ALPHA) ax.plot([1, 0], [0, 1], color=plot_utils.BLUE) ax.plot([0, 0], [1, 0], color="black", alpha=ALPHA) elif slide_num == 3: ax.plot([0, 1], [0, 0], color="black", alpha=ALPHA) ax.plot([1, 0], [0, 1], color="black", alpha=ALPHA) ax.plot([0, 0], [1, 0], color=plot_utils.BLUE) else: ax.plot([0, 1], [0, 0], color="black", alpha=ALPHA) ax.plot([1, 0], [0, 1], color="black", alpha=ALPHA) ax.plot([0, 0], [1, 0], color="black", alpha=ALPHA) # Add the "wrong" triangle to both bottom subplots. edge1, edge2, edge3 = bez_triangle.edges for ax in (ax3, ax4): bez_triangle.plot(256, ax=ax, color="black") ax.patches[-1].set_alpha(ALPHA) # Remove the black boundary and add colored. ax.lines.pop() if slide_num == 1: edge1.plot(256, ax=ax, color=plot_utils.BLUE) elif slide_num == 2: edge2.plot(256, ax=ax, color=plot_utils.BLUE) elif slide_num == 3: edge3.plot(256, ax=ax, color=plot_utils.BLUE) # det(J) = 4[t^2 + (s - 1) t + (s - s^2)] sv = np.linspace(0.0, 1.0 / 5.0, 250) sqrt_part = np.sqrt((1.0 - sv) * (1.0 - 5.0 * sv)) jacobian_zero = np.empty((499, 2)) jacobian_zero[:250, 0] = sv jacobian_zero[:250, 1] = 0.5 * (1.0 - sv - sqrt_part) jacobian_zero[250:, 0] = sv[-2::-1] jacobian_zero[250:, 1] = 0.5 * (1.0 - sv[-2::-1] + sqrt_part[-2::-1]) ax2.plot( jacobian_zero[:, 0], jacobian_zero[:, 1], color="black", linestyle="dashed", ) # Now, compute the image of the det(J) = 0 curve under b(s, t). poly4 = np.empty((598, 2)) sv = jacobian_zero[::-1, 0] tv = jacobian_zero[::-1, 1] poly4[:499, 0] = (1.0 - sv - tv) * (1.0 - sv - tv) + sv * sv poly4[:499, 1] = sv * sv + tv * tv ax4.plot(poly4[:499, 0], poly4[:499, 1], color="black", linestyle="dashed") # Combine this with the image b(0, t) tv = np.linspace(0.0, 1.0, 100)[1:] poly4[499:, 0] = (1.0 - tv) * (1.0 - tv) poly4[499:, 1] = tv * tv if slide_num == 6: patch = matplotlib.patches.PathPatch(matplotlib.path.Path(poly4), color="black", alpha=1.5 * ALPHA) ax4.add_patch(patch) for ax in (ax1, ax2, ax3, ax4): ax.set_aspect("equal") # One axis sets all axis ax1.set_xticklabels([]) ax1.set_yticklabels([]) if slide_num < 5: ax4.set_visible(False) if slide_num < 4: ax2.set_visible(False) figure.set_size_inches(3.2, 3.3) figure.subplots_adjust(left=0.01, bottom=0.01, right=0.99, top=0.99, wspace=0.04, hspace=0.0) filename = "boundary_leak{}.pdf".format(slide_num) path = plot_utils.get_path("slides", filename) figure.savefig(path) print("Saved {}".format(filename)) plt.close(figure)
def remesh(): figure, (ax1, ax2, ax3) = plt.subplots(1, 3, sharex=True, sharey=True) # Update to 1-second ahead in time. xt, yt = point_on_characteristic(NODES_X, NODES_Y, 1.0) nodes = np.empty((len(NODES_X), 2)) nodes[:, 0] = xt nodes[:, 1] = yt for ax in (ax1, ax2): ax.triplot( nodes[:, 0], nodes[:, 1], TRIANGLES, color=plot_utils.BLUE, linewidth=1.0, ) # Do a Delaunay triangulation and discard exterior triangles. tessellation = scipy.spatial.qhull.Delaunay(nodes) polygon1 = shapely.geometry.Polygon(nodes[BOUNDARY_INDICES, :]) to_keep = [] for i, tri in enumerate(tessellation.simplices): polygon2 = shapely.geometry.Polygon(nodes[tri, :]) intersection = polygon1.intersection(polygon2) int_area = intersection.area if int_area == polygon2.area: to_keep.append(i) elif int_area != 0: raise NotImplementedError triangles_new = tessellation.simplices[to_keep, :] for ax in (ax2, ax3): ax.triplot( nodes[:, 0], nodes[:, 1], triangles_new, color=plot_utils.GREEN, linewidth=1.0, ) ax1.set_yticks([-0.5, 1.0, 2.5]) for ax in (ax1, ax2, ax3): ax.axis("scaled") ax.set_xlim(-1.3, 3.6) ax.set_ylim(-0.75, 2.75) ax.set_xticks([-1.0, 1.0, 3.0]) ax.set_xticklabels(["$-1.0$", "$1.0$", "$3.0$"]) ax.xaxis.set_tick_params(labelsize=plot_utils.TICK_SIZE) ax.yaxis.set_tick_params(labelsize=plot_utils.TICK_SIZE) ax1.set_title("Before Remeshing", fontsize=plot_utils.TEXT_SIZE) ax3.set_title("After Remeshing", fontsize=plot_utils.TEXT_SIZE) figure.set_size_inches(6.0, 1.8) figure.subplots_adjust(left=0.06, bottom=0.01, right=0.99, top=1.0, wspace=0.04, hspace=0.2) filename = "distortion_remesh.pdf" path = plot_utils.get_path("solution-transfer", filename) figure.savefig(path) print("Saved {}".format(filename)) plt.close(figure)
def main(): nodes = np.asfortranarray( [[1.0, 0.0, 1.0, 0.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0, 0.0, 1.0]] ) bez_triangle = bezier.Surface(nodes, degree=2, _copy=False) # b(s, t) = [(1 - s - t)^2 + t^2, s^2 + t^2] figure, ((ax1, ax2, ax3), (ax4, ax5, ax6)) = plt.subplots( 2, 3, sharex=True, sharey=True ) for ax in (ax1, ax2, ax3): ax.plot([0, 1, 0, 0], [0, 0, 1, 0], color="black") # The "left" edge b(0, t) = [(1 - t)^2 + t^2, t^2] lies on the algebraic # curve 4x = (1 + x - y)^2. Plugging b(s, t) into this algebraic curve # we find interior points as well. sv = np.linspace(0.0, 2.0 / 5.0, 250) sqrt_part = np.sqrt((2.0 - 5.0 * sv) / (2.0 - sv)) poly1 = np.empty((501, 2)) poly1[:250, 0] = sv poly1[:250, 1] = 0.5 * (1.0 - sv + sqrt_part) poly1[250:499, 0] = sv[-2::-1] poly1[250:499, 1] = 0.5 * (1.0 - sv[-2::-1] - sqrt_part[-2::-1]) poly1[499, :] = 1.0, 0.0 poly1[500, :] = 0.0, 1.0 patch = matplotlib.patches.PathPatch( matplotlib.path.Path(poly1), color=plot_utils.GREEN ) ax1.add_patch(patch) for ax in (ax2, ax3): patch = matplotlib.patches.PathPatch( matplotlib.path.Path(poly1), color=plot_utils.GREEN, alpha=ALPHA ) ax.add_patch(patch) for ax in (ax4, ax5, ax6): bez_triangle.plot(256, ax=ax, color=plot_utils.GREEN) for edge in bez_triangle.edges: edge.plot(256, ax=ax, color="black") ax4.patches[-1].set_alpha(1.0) ax5.patches[-1].set_alpha(ALPHA) ax6.patches[-1].set_alpha(ALPHA) # det(J) = 4[t^2 + (s - 1) t + (s - s^2)] sv = np.linspace(0.0, 1.0 / 5.0, 250) sqrt_part = np.sqrt((1.0 - sv) * (1.0 - 5.0 * sv)) poly2 = np.empty((500, 2)) poly2[:250, 0] = sv poly2[:250, 1] = 0.5 * (1.0 - sv - sqrt_part) poly2[250:499, 0] = sv[-2::-1] poly2[250:499, 1] = 0.5 * (1.0 - sv[-2::-1] + sqrt_part[-2::-1]) poly2[499, :] = 0.0, 0.0 for ax in (ax1, ax2, ax3): ax.plot( poly2[:499, 0], poly2[:499, 1], color="black", linestyle="dashed" ) patch = matplotlib.patches.PathPatch( matplotlib.path.Path(poly2), color=plot_utils.RED ) ax3.add_patch(patch) for ax in (ax1, ax2): patch = matplotlib.patches.PathPatch( matplotlib.path.Path(poly2), color="black", alpha=ALPHA ) ax.add_patch(patch) # Shared slice in between two curves. poly3 = np.empty((997, 2)) poly3[:499, :] = poly2[498::-1, :] poly3[499:, :] = poly1[497::-1, :] patch = matplotlib.patches.PathPatch( matplotlib.path.Path(poly3), color=plot_utils.BLUE ) ax2.add_patch(patch) for ax in (ax1, ax3): patch = matplotlib.patches.PathPatch( matplotlib.path.Path(poly3), color="black", alpha=ALPHA ) ax.add_patch(patch) # Now, compute the image of the det(J) = 0 curve under b(s, t). poly4 = np.empty((598, 2)) sv = poly2[:499, 0][::-1] tv = poly2[:499, 1][::-1] poly4[:499, 0] = (1.0 - sv - tv) * (1.0 - sv - tv) + sv * sv poly4[:499, 1] = sv * sv + tv * tv for ax in (ax4, ax5, ax6): ax.plot( poly4[:499, 0], poly4[:499, 1], color="black", linestyle="dashed" ) # Combine this with the image b(0, t) tv = np.linspace(0.0, 1.0, 100)[1:] poly4[499:, 0] = (1.0 - tv) * (1.0 - tv) poly4[499:, 1] = tv * tv patch = matplotlib.patches.PathPatch( matplotlib.path.Path(poly4), color="black", alpha=ALPHA ) ax4.add_patch(patch) for ax, color in ((ax5, plot_utils.BLUE), (ax6, plot_utils.RED)): patch = matplotlib.patches.PathPatch( matplotlib.path.Path(poly4), color=color ) ax.add_patch(patch) for ax in (ax1, ax2, ax3, ax4, ax5, ax6): ax.set_aspect("equal") # One axis sets all axis ax1.set_xticklabels([]) ax1.set_yticklabels([]) ax2.text( 0.3, 0.35, r"$+$", horizontalalignment="center", verticalalignment="center", fontsize=16, fontweight="bold", color="black", ) ax2.add_patch( matplotlib.patches.Circle( (0.3, 0.35), radius=0.06, fill=False, edgecolor="black", linewidth=1.0, ) ) ax3.text( 0.1, 0.42, r"$-$", horizontalalignment="center", verticalalignment="center", fontsize=16, fontweight="bold", color="black", ) ax3.add_patch( matplotlib.patches.Circle( (0.1, 0.422), radius=0.06, fill=False, edgecolor="black", linewidth=1.0, ) ) figure.set_size_inches(4.8, 3.3) figure.subplots_adjust( left=0.01, bottom=0.01, right=0.99, top=0.99, wspace=0.04, hspace=0.0 ) filename = "inverted_element.pdf" path = plot_utils.get_path("preliminaries", filename) figure.savefig(path) print("Saved {}".format(filename)) plt.close(figure)
def bezier_triangle_area(slide_num): nodes = np.asfortranarray([ [0.0, 0.5, 1.0, 0.125, 0.375, 0.25], [0.0, 0.0, 0.25, 0.5, 0.375, 1.0], ]) surface = bezier.Surface.from_nodes(nodes) exact_area = F(37, 96) edge1, edge2, edge3 = surface.edges figure, all_axes = plt.subplots(2, 3) all_axes = all_axes.flatten() surface.plot(256, ax=all_axes[0]) all_axes[0].set_title("Curved", fontsize=plot_utils.TEXT_SIZE) error_vals = [] for n in range(1, 20 + 1): N = 2**n s_vals = np.linspace(0.0, 1.0, N + 1)[:-1] polygon_nodes = edges_to_polygon(edge1, edge2, edge3, s_vals) polygon = shapely.geometry.Polygon(polygon_nodes.T) # Compute the relative error. poly_area = F(polygon.area) rel_error = abs(poly_area - exact_area) / exact_area error_vals.append((N, float(rel_error))) if n in (1, 2, 3, 4): ax = all_axes[n] # Wrap-around the first node so the polygon is closed. polygon_nodes = np.hstack([polygon_nodes, polygon_nodes[:, :1]]) patch = matplotlib.patches.PathPatch(matplotlib.path.Path( polygon_nodes.T), alpha=0.625) ax.add_patch(patch) ax.plot( polygon_nodes[0, :], polygon_nodes[1, :], marker="o", markersize=4, ) ax.set_title("$N = {:d}$".format(N), fontsize=plot_utils.TEXT_SIZE) for ax in all_axes[:5]: ax.axis("equal") ax.set_xlim(-0.05, 1.05) ax.set_ylim(-0.05, 1.05) for ax in all_axes[:3]: ax.set_xticklabels([]) for ax in all_axes[(1, 2, 4), ]: ax.set_yticklabels([]) error_vals = np.array(error_vals) ax = all_axes[5] line1, = ax.loglog( error_vals[:, 0], error_vals[:, 1], basex=2, color=plot_utils.BLUE, marker="o", markersize=4, label="Polygonal", ) if slide_num < 5: line1.set_visible(False) ax.loglog( error_vals[:slide_num, 0], error_vals[:slide_num, 1], basex=2, color=plot_utils.BLUE, marker="o", markersize=4, label="Polygonal", ) surface_area = F(compute_area(edge1, edge2, edge3)) curved_rel_error = float(abs(exact_area - surface_area) / exact_area) line2, = ax.loglog( [error_vals[0, 0], error_vals[-1, 0]], [curved_rel_error, curved_rel_error], basex=2, color="black", linestyle="dashed", label="Curved", ) if slide_num != 6: line2.set_visible(False) ax.set_title("Area Estimates", fontsize=plot_utils.TEXT_SIZE) ax.set_xlabel("Line Segments per Side ($N$)", fontsize=plot_utils.TEXT_SIZE) ax.set_ylabel("Relative Error", fontsize=plot_utils.TEXT_SIZE) ax.yaxis.tick_right() ax.yaxis.set_label_position("right") all_axes[0].yaxis.set_tick_params(labelsize=plot_utils.TICK_SIZE) all_axes[3].yaxis.set_tick_params(labelsize=plot_utils.TICK_SIZE) all_axes[5].yaxis.set_tick_params(labelsize=plot_utils.TICK_SIZE) all_axes[3].xaxis.set_tick_params(labelsize=plot_utils.TICK_SIZE) all_axes[4].xaxis.set_tick_params(labelsize=plot_utils.TICK_SIZE) all_axes[5].xaxis.set_tick_params(labelsize=plot_utils.TICK_SIZE) all_axes[3].set_xticks([0.1, 0.5, 0.9]) all_axes[4].set_xticks([0.1, 0.5, 0.9]) all_axes[5].set_xticks([2.0**4, 2.0**8, 2.0**12, 2.0**16, 2.0**20]) if slide_num < 6: all_axes[0].set_visible(False) if slide_num < 4: all_axes[4].set_visible(False) if slide_num < 3: all_axes[3].set_visible(False) if slide_num < 2: all_axes[2].set_visible(False) figure.set_size_inches(6.0, 4.2) figure.subplots_adjust(left=0.06, bottom=0.11, right=0.9, top=0.95, wspace=0.03, hspace=0.15) filename = "polygon_vs_curved{}.pdf".format(slide_num) path = plot_utils.get_path("slides", filename) figure.savefig(path) print("Saved {}".format(filename)) plt.close(figure)
def image2(): expected_s = 0.5 expected_t = 0.5 s0 = 1.0 - 0.5**40 t0 = 0.75 + 0.5**20 iterates1 = newton_bezier.newton(s0, COEFFS1, t0, COEFFS2, newton_bezier.standard_residual) iterates2 = newton_bezier.newton(s0, COEFFS1, t0, COEFFS2, newton_bezier.compensated_residual) errors1 = [] errors2 = [] for iterates, errors in ((iterates1, errors1), (iterates2, errors2)): for n, (s_val, t_val) in enumerate(iterates): rel_error_s = F(s_val) / F(expected_s) - 1 if rel_error_s <= 0: raise ValueError(s_val, rel_error_s) rel_error_t = F(t_val) / F(expected_t) - 1 if rel_error_t <= 0: raise ValueError(t_val, rel_error_t) errors.append((n, float(rel_error_s), float(rel_error_t))) figure, (ax1, ax2) = plt.subplots(1, 2, sharex=True, sharey=True) min_x = -2.0 max_x = 51.0 errors1 = np.array(errors1) errors2 = np.array(errors2) for index, ax in ((1, ax1), (2, ax2)): ax.semilogy( errors1[:, 0], errors1[:, index], marker="o", linestyle="none", markersize=7, markeredgewidth=1, markerfacecolor="none", label="Standard", ) ax.semilogy( errors2[:, 0], errors2[:, index], color="black", marker="o", linestyle="none", markersize=3, label="Compensated", ) ax.semilogy( [min_x, max_x], [np.cbrt(U), np.cbrt(U)], linestyle="dashed", color="black", ) ax.semilogy( [min_x, max_x], [np.cbrt(U * U), np.cbrt(U * U)], linestyle="dashed", color="black", ) ax.set_yscale("log", basey=2) ax.set_xlabel("Iteration", fontsize=plot_utils.TEXT_SIZE) ax1.set_ylabel("Relative Error", fontsize=plot_utils.TEXT_SIZE) ax1.set_title("$s$", fontsize=plot_utils.TEXT_SIZE) ax1.set_xlim(min_x, max_x) ax2.set_title("$t$", fontsize=plot_utils.TEXT_SIZE) ax2.legend(loc="upper right", fontsize=plot_utils.TEXT_SIZE) ax2.set_yticks([np.cbrt(U), np.cbrt(U * U)], minor=True) ax2.set_yticklabels( [r"$\sqrt[3]{\mathbf{u}}$", r"$\sqrt[3]{\mathbf{u}^2}$"], minor=True) plt.setp(ax1.get_yticklabels(minor=True), visible=False) ax2.tick_params( axis="y", which="minor", direction="out", left=0, right=1, labelleft=0, labelright=1, ) ax1.tick_params(labelsize=plot_utils.TICK_SIZE) ax2.tick_params(labelsize=plot_utils.TICK_SIZE) ax2.tick_params(labelsize=plot_utils.TEXT_SIZE, which="minor") figure.set_size_inches(6.4, 2.6) figure.subplots_adjust(left=0.09, bottom=0.16, right=0.93, top=0.9, wspace=0.04, hspace=0.2) filename = "newton_linear_converge.pdf" path = plot_utils.get_path("compensated-newton", filename) figure.savefig(path) print("Saved {}".format(filename)) plt.close(figure)
def main(filename=None): cond_nums = [] rel_errors_basic = [] rel_errors_accurate = [] rel_errors_full = [] bounds_vals1 = [] bounds_vals2 = [] for n in range(2, 55 + 1): cond, rel_error1, rel_error2, rel_error3 = root_info(n) cond_nums.append(cond) rel_errors_basic.append(rel_error1) rel_errors_accurate.append(rel_error2) rel_errors_full.append(rel_error3) gamma2n = (2 * n * U) / (1 - 2 * n * U) bounds_vals1.append(float(10 * gamma2n * cond)) bounds_vals2.append(float(6 * gamma2n**2 * cond)) figure = plt.figure() ax = figure.gca() ax.loglog( cond_nums, rel_errors_basic, marker="d", linestyle="none", markersize=7, color=plot_utils.BLUE, zorder=2, label=r"$\mathtt{HNewtonBasic}$", ) ax.loglog( cond_nums, rel_errors_accurate, marker="o", linestyle="none", markersize=3, color="black", zorder=2, label=r"$\mathtt{HNewtonAccurate}$", ) # H/T: (http://widu.tumblr.com/post/43624348228/ # making-unfilled-hollow-markers-in-matplotlib) ax.loglog( cond_nums, rel_errors_full, marker="o", linestyle="none", markersize=6, markeredgewidth=1, markerfacecolor="none", color=plot_utils.GREEN, zorder=2, label=r"$\mathtt{HNewtonFull}$", ) # Add the error lines. ax.loglog( cond_nums, bounds_vals1, color="black", linestyle="dashed", alpha=ALPHA, zorder=1, ) ax.loglog( cond_nums, bounds_vals2, color="black", linestyle="dashed", alpha=ALPHA, zorder=1, ) # Add the ``x = 1/u^k`` vertical lines. min_x, max_x = 1e4, 1e33 min_y, max_y = 1e-19, 1e2 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 = 1`` and ``y = u`` horizontal lines. for exponent in (0, 1): u_pow = float(U)**exponent ax.loglog( [min_x, max_x], [u_pow, u_pow], color="black", linestyle="dashed", alpha=ALPHA, zorder=1, ) # Set the axis limits. ax.set_xlim(min_x, max_x) ax.set_ylim(min_y, max_y) # Set the major x- and y-ticks. ax.set_xticks([1e5, 1e10, 1e15, 1e20, 1e25, 1e30]) ax.set_yticks( [1e-18, 1e-16, 1e-14, 1e-12, 1e-10, 1e-8, 1e-6, 1e-4, 1e-2, 1]) # Set special ``xticks`` for ``1/u`` and ``1/u^2``. u_xticks = [1.0 / float(U), 1.0 / float(U)**2] u_xticklabels = [r"$1/\mathbf{u}$", r"$1/\mathbf{u}^2$"] 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`` 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) # Add the legend. ax.legend( loc="lower right", framealpha=1.0, frameon=True, 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.4, 4.0) figure.subplots_adjust(left=0.12, bottom=0.11, right=0.95, top=0.92, wspace=0.2, hspace=0.2) filename = "newton_jghplus13.pdf" path = plot_utils.get_path("compensated-newton", filename) figure.savefig(path) print("Saved {}".format(filename)) plt.close(figure)