def main(): layers = { "layer%d" % i: ps.Line(ps.Point(0, a[i]), ps.Point(W, a[i])) for i in range(len(a)) } symbols_ell = { "l_%d" % i: ps.Text(r"$\ell_%d$" % i, ps.Point(-0.5, a[i])) for i in range(1, len(a) - 1) } for text in symbols_ell.values(): text.style.font_size = 24 symbols_a = { "a_%d" % i: ps.Text("$a_%d$" % i, ps.Point(W / 2, 0.5 * (a[i] + a[i + 1]))) for i in range(len(a) - 1) } for text in symbols_a.values(): text.style.font_size = 24 sides = { "left": ps.Line(ps.Point(0, 0), ps.Point(0, H)), "right": ps.Line(ps.Point(W, 0), ps.Point(W, H)), } d = sides.copy() d.update(layers) d.update(symbols_ell) d.update(symbols_a) model = ps.Composition(d) fig = ps.Figure(-1, W + 1, -1, H + 1, backend=MatplotlibBackend) fig.add(model) fig.show()
def main() -> None: d = make_dashpot(0) s = make_spring(0) M = ps.Rectangle(ps.Point(0, H), 4 * H, 4 * H).set_line_width(4) left_wall = ps.Rectangle(ps.Point(-L, 0), H / 10, L).set_fill_pattern( ps.Style.FillPattern.UP_LEFT_TO_RIGHT) ground = ps.Wall([ps.Point(-L / 2, 0), ps.Point(L, 0)], thickness=-H / 10) wheel1 = ps.Circle(ps.Point(H, H / 2), H / 2) wheel2 = wheel1.translate(ps.Point(2 * H, 0)) fontsize = 24 text_m = ps.Text("$m$", ps.Point(2 * H, H + 2 * H)) text_m.style.font_size = fontsize text_ku = ps.Text("$ku$", ps.Point(-L / 2, H + 4 * H)) text_ku.style.font_size = fontsize text_bv = ps.Text("$bu'$", ps.Point(-L / 2, H)) text_bv.style.font_size = fontsize x_axis = ps.Axis(ps.Point(2 * H, L), H, "$u(t)$") x_axis_start = ps.Line(ps.Point(2 * H, L - H / 4), ps.Point(2 * H, L + H / 4)).set_line_width(4) model = ps.Composition({ "spring": s, "mass": M, "left wall": left_wall, "ground": ground, "wheel1": wheel1, "wheel2": wheel2, "text_m": text_m, "text_ku": text_ku, "x_axis": x_axis, "x_axis_start": x_axis_start, }) fig = ps.Figure(-L, x_max, -1, L + H, backend=MatplotlibBackend) fig.add(model) damping = ps.Composition({"dashpot": d, "text_bv": text_bv}) # or fig = Composition(dict(fig=fig, dashpot=d, text_bv=text_bv)) fig.add(damping) fig.show()
def main() -> None: code = ps.Text("print 'Hello, World!'", ps.Point(2.5, 1.5)) code.style.fontsize = 24 code.style.font_family = ps.TextStyle.FontFamily.MONO code.style.fill_color = ps.TextStyle.Color.GREY fig = ps.Figure(0.0, 5.0, 0.0, 3.0, backend=MatplotlibBackend) fig.add(code) fig.show()
def main() -> None: fig = ps.Figure(-1, W + 1, -1, H + 1, backend=MatplotlibBackend) layers = { "layer%d" % i: ps.Line(ps.Point(0, a[i]), ps.Point(W, a[i])) for i in range(len(a)) } symbols_q = { "xi_%d" % i: ps.Text(r"$\xi_%d$" % i, ps.Point(W / 2, 0.5 * (a[i] + a[i + 1]))) for i in range(len(a) - 1) } symbols_q["xi_2"] = ps.Text(r"$\xi_2$", ps.Point(-0.5, a[1])) sides = { "left": ps.Line(ps.Point(0, 0), ps.Point(0, H)), "right": ps.Line(ps.Point(W, 0), ps.Point(W, H)), } d = sides.copy() d.update(layers) d.update(symbols_q) model = ps.Composition(d) fig.add(model) fig.show()
def main() -> None: wall = ps.Wall( [ ps.Point(x, gaussian(x)) for x in np.linspace(W + L, 0, 51, endpoint=False) ], 0.3, ) wall.style.line_color = ps.Style.Color.BROWN inlet_profile = ps.VelocityProfile(ps.Point(0, 0), H, velocity_profile, 5) inlet_profile.style.line_color = ps.Style.Color.BLUE symmetry_line = ps.Line(ps.Point(0, H), ps.Point(W + L, H)) symmetry_line.style.line_style = ps.Style.LineStyle.DASHED outlet = ps.Line(ps.Point(W + L, 0), ps.Point(W + L, H)) outlet.style.line_style = ps.Style.LineStyle.DASHED model = ps.Composition({ "bottom": wall, "inlet": inlet_profile, "symmetry line": symmetry_line, "outlet": outlet, }) velocity = velocity_profile(H / 2.0) line = ps.Line(ps.Point(W - 2.5 * sigma, 0), ps.Point(W + 2.5 * sigma, 0)) line.style.line_style = ps.Style.LineStyle.DASHED symbols = { "alpha": ps.LinearDimension(r"$\alpha$", ps.Point(W, 0), ps.Point(W, alpha)), "W": ps.LinearDimension(r"$W$", ps.Point(0, -0.5), ps.Point(W, -0.5)), "L": ps.LinearDimension(r"$L$", ps.Point(W, -0.5), ps.Point(W + L, -0.5)), "v(y)": ps.Text("$v(y)$ ", ps.Point(H / 2.0, velocity.x)), "dashed line": line, } symbols = ps.Composition(symbols) fig = ps.Figure(0, W + L + 1, -2, H + 1, backend=MatplotlibBackend) fig.add(model) fig.add(symbols) fig.show()
import pysketcher as ps from pysketcher.backend.matplotlib import MatplotlibBackend W = 10.0 H = 5.0 a = [0, 3.5, 5] fig = ps.Figure(-1, W + 1, -1, H + 1, backend=MatplotlibBackend) layers = { "layer%d" % i: ps.Line(ps.Point(0, a[i]), ps.Point(W, a[i])) for i in range(len(a)) } symbols_q = { "xi_%d" % i: ps.Text(r"$\xi_%d$" % i, ps.Point(W / 2, 0.5 * (a[i] + a[i + 1]))) for i in range(len(a) - 1) } symbols_q["xi_2"] = ps.Text(r"$\xi_2$", ps.Point(-0.5, a[1])) sides = { "left": ps.Line(ps.Point(0, 0), ps.Point(0, H)), "right": ps.Line(ps.Point(W, 0), ps.Point(W, H)), } d = sides.copy() d.update(layers) d.update(symbols_q) model = ps.Composition(d) fig.add(model) fig.show()
def pendulum(theta, S, mg, drag) -> ps.Composition: """Draw a free body animation of a pendulum. params: theta: the angle from the vertical at which the pendulum is. S: the force exerted toward the pivot. mg: the force owing to gravity. drag: the force acting against the motion of the pendulum. return: A composition of the pendulum """ a = theta P = ps.Point(W / 2, 0.9 * H) # rotation point path = ps.Arc(P, L, -ps.Angle(np.pi / 2), a) mass_pt = path.end rod = ps.Line(P, mass_pt) theta = ps.AngularDimension(r"$\theta$", P + ps.Point(0, -L / 4), P + (mass_pt - P).unit_vector * (L / 4), P) theta.extension_lines = False mass = ps.Circle(mass_pt, L / 30.0).set_fill_color(ps.Style.Color.BLUE) rod_vec = rod.end - rod.start length = ps.LinearDimension("$L$", mass_pt, P) # Displace length indication length = length.translate(ps.Point(-np.cos(a), -np.sin(a)) * (L / 15.0)) length.style.line_width = 0.1 gravity_start = ps.Point(0.8 * L, 0) gravity = ps.Gravity(P + gravity_start, L / 3) dashed_thin_black_line = ps.Style() dashed_thin_black_line.line_style = ps.Style.LineStyle.DASHED dashed_thin_black_line.line_color = ps.Style.Color.BLACK dashed_thin_black_line.line_width = 1.0 path.style = dashed_thin_black_line vertical = ps.Line(rod.start, rod.start + ps.Point(0, -L)) vertical.style = dashed_thin_black_line rod.style = dashed_thin_black_line comp = ps.Composition({ "body": mass, "rod": rod, "vertical": vertical, "theta": theta, "path": path, "g": gravity, # "L": length, }) magnitude = 1.2 * L / 6 # length of a unit force in figure force = mg # constant (scaled eq: about 1) force *= magnitude mg_force = (ps.Force( "$mg$", mass_pt, mass_pt + ps.Point(0, 1) * force, text_position=ps.TextPosition.END, ) if force != 0 else None) force = S force *= magnitude rod_force = (ps.Force( "S", mass_pt, mass_pt - rod_vec.unit_vector * force, text_position=ps.TextPosition.END, ) if force != 0 else None) force = drag force *= magnitude air_force = (ps.Force( "", mass_pt, mass_pt - rod_vec.normal * force, ) if force != 0 else None) x0y0 = ps.Text("$(x_0,y_0)$", P + ps.Point(-0.4, -0.1)) ir = ps.Force( r"$\mathbf{i}_r$", P, P + rod_vec.unit_vector * (L / 10), text_position=ps.TextPosition.END, # spacing=ps.Point(0.015, 0) ) ith = ps.Force( r"$\mathbf{i}_{\theta}$", P, P + rod_vec.normal * (L / 10), text_position=ps.TextPosition.END, # spacing=ps.Point(0.02, 0.005) ) body_diagram = ps.Composition({ "mg": mg_force, "S": rod_force, "air": air_force, "ir": ir, "ith": ith, "origin": x0y0, }) comp = comp.merge(body_diagram) return comp
import pysketcher as ps from pysketcher.backend.matplotlib import MatplotlibBackend W = 10.0 H = 10.0 a = [0, 5, 10] layers = { "layer%d" % i: ps.Line(ps.Point(0, a[i]), ps.Point(W, a[i])) for i in range(len(a)) } symbols_q = { "Omega_k%d" % i: ps.Text(r"$\Omega_%d$: $k_%d$" % (i, i), ps.Point(W / 2, 0.5 * (a[i] + a[i + 1]))) for i in range(len(a) - 1) } sides = { "left": ps.Line(ps.Point(0, 0), ps.Point(0, H)), "right": ps.Line(ps.Point(W, 0), ps.Point(W, H)), } d = sides.copy() d.update(layers) d.update(symbols_q) model = ps.Composition(d) fig = ps.Figure(-1, W + 1, 1, H + 1, backend=MatplotlibBackend) fig.add(model) fig.show()
u_min = -0.2 * u_max logging.info(u_max) r = 0.005 * (t_max - t_min) # radius of circles placed at mesh points # import random; random.seed(12) perturbations = [0, 0.1, 0.1, 0.2, -0.4, -0.1] u_points = {} u_values = [] for i, t in enumerate(t_mesh): u_value = u(t) + perturbations[i] u_values.append(u_value) circle = ps.Circle(ps.Point(t, u_value), r).set_fill_color(ps.Style.Color.BLACK) text = ps.Text( "$u^%d$" % i, ps.Point(t, u_value) + (ps.Point(0.0, 3 * r) if i > 0 else ps.Point(-3 * r, 0.0)), ) u_points[i] = ps.Composition({"circle": circle, "u_point": text}) u_discrete = ps.Composition(u_points) i_lines = {} for i in range(1, len(t_mesh)): i_lines[i] = ps.Line(ps.Point(t_mesh[i - 1], u_values[i - 1]), ps.Point(t_mesh[i], u_values[i])).set_line_width(1) interpolant = ps.Composition(i_lines) x_axis_extent: float = t_mesh[-1] + 0.2 * t_axis_extent logging.info(x_axis_extent) axes = ps.Composition({ "x":
def main() -> None: u = ps.SketchyFunc3() Nt = 5 t_mesh = np.linspace(0, 6, Nt + 1) # Add 20% space to the left and 30% to the right of the coordinate system t_axis_extent = t_mesh[-1] - t_mesh[0] logging.info(t_axis_extent) t_min = t_mesh[0] - 0.2 * t_axis_extent logging.info(t_min) t_max = t_mesh[-1] + 0.3 * t_axis_extent logging.info(t_max) u_max = 1.3 * max([u(t) for t in t_mesh]) logging.info(u_max) u_min = -0.2 * u_max logging.info(u_max) r = 0.005 * (t_max - t_min) # radius of circles placed at mesh points # import random; random.seed(12) perturbations = [0, 0.1, 0.1, 0.2, -0.4, -0.1] u_points = {} u_values = [] for i, t in enumerate(t_mesh): u_value = u(t) + perturbations[i] u_values.append(u_value) circle = ps.Circle(ps.Point(t, u_value), r).set_fill_color(ps.Style.Color.BLACK) text = ps.Text( "$u^%d$" % i, ps.Point(t, u_value) + (ps.Point(0.0, 3 * r) if i > 0 else ps.Point(-3 * r, 0.0)), ) u_points[i] = ps.Composition({"circle": circle, "u_point": text}) u_discrete = ps.Composition(u_points) i_lines = {} for i in range(1, len(t_mesh)): i_lines[i] = ps.Line(ps.Point(t_mesh[i - 1], u_values[i - 1]), ps.Point(t_mesh[i], u_values[i])).set_line_width(1) interpolant = ps.Composition(i_lines) x_axis_extent: float = t_mesh[-1] + 0.2 * t_axis_extent logging.info(x_axis_extent) axes = ps.Composition({ "x": ps.Axis( ps.Point(0.0, 0.0), x_axis_extent, "$t$", ), "y": ps.Axis(ps.Point(0.0, 0.0), 0.8 * u_max, "$u$", rotation_angle=np.pi / 2), }) h = 0.03 * u_max # tickmarks height i_nodes = {} for i, t in enumerate(t_mesh): i_nodes[i] = ps.Composition({ "node": ps.Line(ps.Point(t, h), ps.Point(t, -h)), "name": ps.Text("$t_%d$" % i, ps.Point(t, -3.5 * h)), }) nodes = ps.Composition(i_nodes) fig = ps.Figure(t_min, t_max, u_min, u_max, backend=MatplotlibBackend) # Draw t_mesh with discrete u points illustration = ps.Composition(dict( u=u_discrete, mesh=nodes, axes=axes, )) fig.erase() fig.add(illustration) fig.show() # Add exact u line (u is a Spline Shape that applies 500 intervals by default # for drawing the curve) exact = u.set_line_style(ps.Style.LineStyle.DASHED).set_line_width(1) fig.add(exact) fig.show() # Add linear interpolant fig.add(interpolant) fig.show() # Linear interpolant without exact, smooth line fig.erase() fig.add(illustration) fig.add(interpolant) fig.show()
"outlet": outlet, }) velocity = velocity_profile(H / 2.0) line = ps.Line(ps.Point(W - 2.5 * sigma, 0), ps.Point(W + 2.5 * sigma, 0)) line.style.line_style = ps.Style.LineStyle.DASHED symbols = { "alpha": ps.DistanceWithText(r"$\alpha$", ps.Point(W, 0), ps.Point(W, alpha)), "W": ps.DistanceWithText(r"$W$", ps.Point(0, -0.5), ps.Point(W, -0.5), spacing=-1.0 / 3), "L": ps.DistanceWithText(r"$L$", ps.Point(W, -0.5), ps.Point(W + L, -0.5), spacing=-1.0 / 3), "v(y)": ps.Text("$v(y)$ ", ps.Point(H / 2.0, velocity.x)), "dashed line": line, } symbols = ps.Composition(symbols) fig = ps.Figure(0, W + L + 1, -2, H + 1, backend=MatplotlibBackend) fig.add(model) fig.add(symbols) fig.show()
"""Minimialistic pysketcher example.""" import pysketcher as ps from pysketcher.backend.matplotlib import MatplotlibBackend code = ps.Text("print 'Hello, World!'", ps.Point(2.5, 1.5)) code.style.fontsize = 24 code.style.font_family = ps.TextStyle.FontFamily.MONO code.style.fill_color = ps.TextStyle.Color.GREY fig = ps.Figure(0.0, 5.0, 0.0, 3.0, backend=MatplotlibBackend) fig.add(code) fig.show()
def main(): u = ps.SketchyFunc3() t_mesh = np.linspace(0, 6, Nt + 1) t_mesh_staggered = np.linspace(0.5 * (t_mesh[0] + t_mesh[1]), 0.5 * (t_mesh[-2] + t_mesh[-1]), Nt) # Add 20% space to the left and 30% to the right of the coordinate system t_axis_extent = t_mesh[-1] - t_mesh[0] t_min = t_mesh[0] - 0.2 * t_axis_extent t_max = t_mesh[-1] + 0.3 * t_axis_extent u_max = 1.3 * max([u(t) for t in t_mesh]) u_min = -0.2 * u_max r = 0.005 * (t_max - t_min) # radius of circles placed at mesh Points u_discrete = ps.Composition({ i: ps.Composition( dict( circle=ps.Circle(ps.Point(t, u(t)), r).set_fill_color(ps.Style.Color.BLACK), u_Point=ps.Text( "$u_%d$" % i, ps.Point(t, u(t)) + (ps.Point(0, 5 * r) if i > 0 else ps.Point(-5 * r, 0)), ), )) for i, t in enumerate(t_mesh) }) # u' = v # v = u.smooth.derivative(n=1) v = ps.SketchyFunc4() v_discrete = ps.Composition({ i: ps.Composition( dict( circle=ps.Circle(ps.Point(t, v(t)), r).set_fill_color(ps.Style.Color.RED), v_Point=ps.Text( r"$v_{%d/2}$" % (2 * i + 1), ps.Point(t, v(t)) + (ps.Point(0, 5 * r)), ), )) for i, t in enumerate(t_mesh_staggered) }) axes = ps.Composition( dict( x=ps.Axis(ps.Point(0, 0), t_mesh[-1] + 0.2 * t_axis_extent, "$t$"), y=ps.Axis(ps.Point(0, 0), 0.8 * u_max, "$u,v$", rotation_angle=np.pi / 2), )) h = 0.03 * u_max # tickmarks height u_nodes = ps.Composition({ i: ps.Composition( dict( node=ps.Line(ps.Point(t, h), ps.Point(t, -h)), name=ps.Text("$t_%d$" % i, ps.Point(t, -3.5 * h)), )) for i, t in enumerate(t_mesh) }) v_nodes = ps.Composition({ i: ps.Composition( dict( node=ps.Line(ps.Point(t, h / 1.5), ps.Point( t, -h / 1.5)).set_line_color(ps.Style.Color.RED), name=ps.Text(r"$t_{%d/2}$" % (2 * i + 1), ps.Point(t, -3.5 * h)), )) for i, t in enumerate(t_mesh_staggered) }) illustration = ps.Composition( dict(u=u_discrete, v=v_discrete, u_mesh=u_nodes, v_mesh=v_nodes, axes=axes)) fig = ps.Figure(t_min, t_max, u_min, u_max, backend=MatplotlibBackend) # Staggered t mesh and u and v Points fig.add(illustration) fig.show() # Exact u line (u is a Spline Shape that applies 500 intervals by default # for drawing the curve) u_exact = u.set_line_style(ps.Style.LineStyle.DASHED).set_line_width(1) fig.add(u_exact) fig.show() # v = Curve(u.xcoor, v(u.xcoor)) t_mesh_staggered_fine = np.linspace(t_mesh_staggered[0], t_mesh_staggered[-1], 501) t_mesh_staggered_points = [ ps.Point(x, v(x)) for x in t_mesh_staggered_fine ] v_exact = (ps.Curve(t_mesh_staggered_points).set_line_style( ps.Style.LineStyle.DASHED).set_line_width(1)) fig.add(v_exact) fig.show()
return s d = make_dashpot(0) s = make_spring(0) M = ps.Rectangle(ps.Point(0, H), 4 * H, 4 * H).set_line_width(4) left_wall = ps.Rectangle(ps.Point(-L, 0), H / 10, L).set_fill_pattern( ps.Style.FillPattern.UP_LEFT_TO_RIGHT ) ground = ps.Wall([ps.Point(-L / 2, 0), ps.Point(L, 0)], thickness=-H / 10) wheel1 = ps.Circle(ps.Point(H, H / 2), H / 2) wheel2 = wheel1.translate(ps.Point(2 * H, 0)) fontsize = 24 text_m = ps.Text("$m$", ps.Point(2 * H, H + 2 * H)) text_m.style.font_size = fontsize text_ku = ps.Text("$ku$", ps.Point(-L / 2, H + 4 * H)) text_ku.style.font_size = fontsize text_bv = ps.Text("$bu'$", ps.Point(-L / 2, H)) text_bv.style.font_size = fontsize x_axis = ps.Axis(ps.Point(2 * H, L), H, "$u(t)$", label_spacing=(0.04, -0.01)) x_axis_start = ps.Line( ps.Point(2 * H, L - H / 4), ps.Point(2 * H, L + H / 4) ).set_line_width(4) model = ps.Composition( { "spring": s, "mass": M, "left wall": left_wall,
# Add 20% space to the left and 30% to the right of the coordinate system t_axis_extent = t_mesh[-1] - t_mesh[0] t_min = t_mesh[0] - 0.2 * t_axis_extent t_max = t_mesh[-1] + 0.3 * t_axis_extent u_max = 1.3 * max([u(t) for t in t_mesh]) u_min = -0.2 * u_max r = 0.005 * (t_max - t_min) # radius of circles placed at mesh Points u_discrete = ps.Composition({ i: ps.Composition( dict( circle=ps.Circle(ps.Point(t, u(t)), r).set_fill_color(ps.Style.Color.BLACK), u_Point=ps.Text( "$u_%d$" % i, ps.Point(t, u(t)) + (ps.Point(0, 5 * r) if i > 0 else ps.Point(-5 * r, 0)), ), )) for i, t in enumerate(t_mesh) }) # u' = v # v = u.smooth.derivative(n=1) v = ps.SketchyFunc4() v_discrete = ps.Composition({ i: ps.Composition( dict( circle=ps.Circle(ps.Point(t, v(t)), r).set_fill_color(ps.Style.Color.RED),
import pysketcher as ps from pysketcher.backend.matplotlib import MatplotlibBackend W = 10.0 H = 10.0 a = [0, 1.5, 3, 4.5, 6, 8.2, 10] layers = { "layer%d" % i: ps.Line(ps.Point(0, a[i]), ps.Point(W, a[i])) for i in range(len(a)) } symbols_ell = { "l_%d" % i: ps.Text(r"$\ell_%d$" % i, ps.Point(-0.5, a[i])) for i in range(1, len(a) - 1) } for text in symbols_ell.values(): text.style.font_size = 24 symbols_a = { "a_%d" % i: ps.Text("$a_%d$" % i, ps.Point(W / 2, 0.5 * (a[i] + a[i + 1]))) for i in range(len(a) - 1) } for text in symbols_a.values(): text.style.font_size = 24 sides = { "left": ps.Line(ps.Point(0, 0), ps.Point(0, H)),
path = ps.Arc(P, L, -np.pi / 2, a) theta = ps.ArcWithText(r"$\theta$", P, L / 4, -np.pi / 2, a, text_spacing=1 / 30.0) mass_pt = path.end rod = ps.Line(P, mass_pt) mass = ps.Circle(mass_pt, L / 20.0) rod_vec = rod.end - rod.start unit_rod_vec = rod_vec.unit_vector() mass_symbol = ps.Text("$m$", mass_pt + unit_rod_vec * (L / 10.0)) length = ps.DistanceWithText("$L$", P, mass_pt) # Displace length indication length = length.translate(rod_vec.normal() * (L / 15)) gravity = ps.Gravity(start=P + ps.Point(0.8 * L, 0), length=L / 3) def set_dashed_thin_blackline(*objects: ps.Shape): """Set linestyle of objects to dashed, black, width=1.""" for obj in objects: obj.set_line_style(ps.Style.LineStyle.DASHED) obj.set_line_color(ps.Style.Color.BLACK) obj.set_line_width(1)
"tick_m1": ps.Line(pf0 + ps.Point(0, tick), pf0 - ps.Point(0, tick)) .set_line_color(ps.Style.Color.BLACK) .set_line_width(1), "tick_n": ps.Line(p0 + ps.Point(0, tick), p0 - ps.Point(0, tick)) .set_line_color(ps.Style.Color.BLACK) .set_line_width(1), "tick_p1": ps.Line(pb0 + ps.Point(0, tick), pb0 - ps.Point(0, tick)) .set_line_color(ps.Style.Color.BLACK) .set_line_width(1), } ) # 1D mesh with three points mesh = ps.Composition( { "tnm1": ps.Text("$t_{n-1}$", pb0 - ps.Point(0, 0.3)), "tn": ps.Text("$t_{n}$", p0 - ps.Point(0, 0.3)), "tnp1": ps.Text("$t_{n+1}$", pf0 - ps.Point(0, 0.3)), "axis": axis, } ) # 1D mesh with three points for Crank-Nicolson mesh_cn = ps.Composition( { "tnm1": ps.Text("$t_{n}$", pb0 - ps.Point(0, 0.3)), "tn": ps.Text(r"$t_{n+\frac{1}{2}}$", p0 - ps.Point(0, 0.3)), "tnp1": ps.Text("$t_{n+1}$", pf0 - ps.Point(0, 0.3)), "axis": axis, } )