.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "auto_examples/plot_circle.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_auto_examples_plot_circle.py: Meshing a Circle ================ .. currentmodule:: rmsh This example shows how a simple circular mesh can be created using ``rmsh``. It is also intended to show what incorrect usage may lead to in hopes of being useful when trying to identify errors. .. GENERATED FROM PYTHON SOURCE LINES 13-20 The Setup --------- First the common setup for plotting has to be made. For this case, it will be done using the :mod:`matplotlib` module, using :class:`matplotlib.collections.LineCollection` to plot cell boundaries. .. GENERATED FROM PYTHON SOURCE LINES 21-60 .. code-block:: Python from time import perf_counter import numpy as np from matplotlib import pyplot as plt from matplotlib.collections import LineCollection from rmsh import ( BoundaryBlock, BoundaryCurve, BoundaryId, Mesh2D, MeshBlock, SolverConfig, create_elliptical_mesh, ) def plot_mesh(m: Mesh2D) -> None: """Show the mesh using matplotlib.""" x = m.pos_x y = m.pos_y line_indices = m.lines xb = x[line_indices[:, 0]] xe = x[line_indices[:, 1]] yb = y[line_indices[:, 0]] ye = y[line_indices[:, 1]] rb = np.stack((xb, yb), axis=1) re = np.stack((xe, ye), axis=1) c = LineCollection(np.stack((rb, re), axis=1)) plt.scatter(x, y, s=8, color="red") # for idx in range(line_indices.shape[0]): # plt.plot((xb[idx], xe[idx]), (yb[idx], ye[idx])) plt.gca().add_collection(c) plt.gca().set_aspect("equal") plt.xlim(-1.1, +1.1) plt.ylim(-1.1, +1.1) plt.show() .. GENERATED FROM PYTHON SOURCE LINES 61-67 Simplest -------- First is the most basic approach. In this case, only a single block is used, with its boundaries being the circumference of the circle that we want to mesh. .. GENERATED FROM PYTHON SOURCE LINES 68-99 .. code-block:: Python def one_block_only(n1: int, n2: int) -> Mesh2D: """Mesh a circle with a single block.""" angle_l = np.linspace(+0 * np.pi / 2, +1 * np.pi / 2, n1) angle_b = np.linspace(+1 * np.pi / 2, +2 * np.pi / 2, n2) angle_r = np.linspace(+2 * np.pi / 2, +3 * np.pi / 2, n1) angle_t = np.linspace(+3 * np.pi / 2, +4 * np.pi / 2, n2) cl = BoundaryCurve(np.cos(angle_l), np.sin(angle_l)) cr = BoundaryCurve(np.cos(angle_r), np.sin(angle_r)) ct = BoundaryCurve(np.cos(angle_t), np.sin(angle_t)) cb = BoundaryCurve(np.cos(angle_b), np.sin(angle_b)) block = MeshBlock( "only one", { BoundaryId.BoundaryWest: cl, BoundaryId.BoundaryEast: cr, BoundaryId.BoundaryNorth: ct, BoundaryId.BoundarySouth: cb, }, ) t0 = perf_counter() m, _, _ = create_elliptical_mesh([block]) t1 = perf_counter() print(f"Meshed in {t1 - t0:g} seconds.") return m # Now let's show it! .. GENERATED FROM PYTHON SOURCE LINES 100-101 .. code-block:: Python plot_mesh(one_block_only(2, 2)) .. image-sg:: /auto_examples/images/sphx_glr_plot_circle_001.png :alt: plot circle :srcset: /auto_examples/images/sphx_glr_plot_circle_001.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none Meshed in 0.00049365 seconds. .. GENERATED FROM PYTHON SOURCE LINES 102-103 .. code-block:: Python plot_mesh(one_block_only(10, 10)) .. image-sg:: /auto_examples/images/sphx_glr_plot_circle_002.png :alt: plot circle :srcset: /auto_examples/images/sphx_glr_plot_circle_002.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none Meshed in 0.000499351 seconds. .. GENERATED FROM PYTHON SOURCE LINES 104-106 .. code-block:: Python plot_mesh(one_block_only(50, 50)) .. image-sg:: /auto_examples/images/sphx_glr_plot_circle_003.png :alt: plot circle :srcset: /auto_examples/images/sphx_glr_plot_circle_003.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none Meshed in 0.00807735 seconds. .. GENERATED FROM PYTHON SOURCE LINES 107-119 Almost the Worst ---------------- Next is one worst possible things you can make while meshing: a pair of boundaries, which at no point have a connection with a curve. In this case, the left and right boundaries only need to connect to one another and have no requirement on their position. Top and bottom boundaries each cover half of a circle. The resulting mesh is very overlapping and very silly looking. If you obtain such a mesh from your meshing, consider checking how you've defined the boundaries defined by :class:`BoundaryBlock` objects. .. GENERATED FROM PYTHON SOURCE LINES 120-151 .. code-block:: Python def self_closed_mesh(n1: int, n2: int) -> Mesh2D: """Mesh a circle by self connecting two opposing boundaries.""" angle_b = np.linspace(-np.pi, 0, n2) angle_t = np.linspace(0, +np.pi, n2) ct = BoundaryCurve(np.cos(angle_t), np.sin(angle_t)) cb = BoundaryCurve(np.cos(angle_b), np.sin(angle_b)) bl = BoundaryBlock("only one", BoundaryId.BoundaryEast, n1) br = BoundaryBlock("only one", BoundaryId.BoundaryWest, n1) block = MeshBlock( "only one", { BoundaryId.BoundaryWest: bl, BoundaryId.BoundaryEast: br, BoundaryId.BoundaryNorth: ct, BoundaryId.BoundarySouth: cb, }, ) t0 = perf_counter() m, _, _ = create_elliptical_mesh([block]) t1 = perf_counter() print(f"Meshed in {t1 - t0:g} seconds.") return m # Now let's show it! .. GENERATED FROM PYTHON SOURCE LINES 152-153 .. code-block:: Python plot_mesh(self_closed_mesh(2, 2)) .. image-sg:: /auto_examples/images/sphx_glr_plot_circle_004.png :alt: plot circle :srcset: /auto_examples/images/sphx_glr_plot_circle_004.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none Meshed in 3.8422e-05 seconds. .. GENERATED FROM PYTHON SOURCE LINES 154-155 .. code-block:: Python plot_mesh(self_closed_mesh(10, 10)) .. image-sg:: /auto_examples/images/sphx_glr_plot_circle_005.png :alt: plot circle :srcset: /auto_examples/images/sphx_glr_plot_circle_005.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none Meshed in 0.000170168 seconds. .. GENERATED FROM PYTHON SOURCE LINES 156-158 .. code-block:: Python plot_mesh(self_closed_mesh(50, 50)) .. image-sg:: /auto_examples/images/sphx_glr_plot_circle_006.png :alt: plot circle :srcset: /auto_examples/images/sphx_glr_plot_circle_006.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none Meshed in 0.0102777 seconds. .. GENERATED FROM PYTHON SOURCE LINES 159-165 Doing it Wrong -------------- A way to make the initial circular mesh better would be to mesh with five blocks, rather than five. However if they are connected incorrectly, the result will be significantly worse. .. GENERATED FROM PYTHON SOURCE LINES 166-234 .. code-block:: Python def four_wierdly_connected_ones(n1: int, n2: int) -> Mesh2D: """Mesh in a weird way, where four blocks are used, but weirdly connected.""" angle_l = np.linspace(+0 * np.pi / 2, +1 * np.pi / 2, n1) angle_b = np.linspace(+1 * np.pi / 2, +2 * np.pi / 2, n2) angle_r = np.linspace(+2 * np.pi / 2, +3 * np.pi / 2, n1) angle_t = np.linspace(+3 * np.pi / 2, +4 * np.pi / 2, n2) cl = BoundaryCurve(np.cos(angle_l), np.sin(angle_l)) cr = BoundaryCurve(np.cos(angle_r), np.sin(angle_r)) ct = BoundaryCurve(np.cos(angle_t), np.sin(angle_t)) cb = BoundaryCurve(np.cos(angle_b), np.sin(angle_b)) blockwest = MeshBlock( "left", { BoundaryId.BoundaryWest: cl, BoundaryId.BoundaryEast: BoundaryBlock("right", BoundaryId.BoundaryWest, n1), BoundaryId.BoundaryNorth: BoundaryBlock("top", BoundaryId.BoundaryWest, n2), BoundaryId.BoundarySouth: BoundaryBlock( "bottom", BoundaryId.BoundaryWest, n2 ), }, ) blockeast = MeshBlock( "right", { BoundaryId.BoundaryWest: BoundaryBlock("left", BoundaryId.BoundaryEast, n1), BoundaryId.BoundaryEast: cr, BoundaryId.BoundaryNorth: BoundaryBlock("top", BoundaryId.BoundaryEast, n2), BoundaryId.BoundarySouth: BoundaryBlock( "bottom", BoundaryId.BoundaryEast, n2 ), }, ) blocknorth = MeshBlock( "top", { BoundaryId.BoundaryWest: BoundaryBlock("left", BoundaryId.BoundaryNorth, n1), BoundaryId.BoundaryEast: BoundaryBlock("right", BoundaryId.BoundaryNorth, n1), BoundaryId.BoundaryNorth: ct, BoundaryId.BoundarySouth: BoundaryBlock( "bottom", BoundaryId.BoundaryNorth, n2 ), }, ) blocksouth = MeshBlock( "bottom", { BoundaryId.BoundaryWest: BoundaryBlock("left", BoundaryId.BoundarySouth, n1), BoundaryId.BoundaryEast: BoundaryBlock("right", BoundaryId.BoundarySouth, n1), BoundaryId.BoundaryNorth: BoundaryBlock("top", BoundaryId.BoundarySouth, n2), BoundaryId.BoundarySouth: cb, }, ) t0 = perf_counter() m, _, _ = create_elliptical_mesh( [blockwest, blockeast, blocknorth, blocksouth], verbose=False, solver_cfg=SolverConfig(smoother_rounds=0, max_iterations=64), ) t1 = perf_counter() print(f"Meshed in {t1 - t0:g} seconds.") return m # Now let's show it! .. GENERATED FROM PYTHON SOURCE LINES 235-236 .. code-block:: Python plot_mesh(four_wierdly_connected_ones(2, 2)) .. image-sg:: /auto_examples/images/sphx_glr_plot_circle_007.png :alt: plot circle :srcset: /auto_examples/images/sphx_glr_plot_circle_007.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none Meshed in 6.6404e-05 seconds. .. GENERATED FROM PYTHON SOURCE LINES 237-238 .. code-block:: Python plot_mesh(four_wierdly_connected_ones(10, 10)) .. image-sg:: /auto_examples/images/sphx_glr_plot_circle_008.png :alt: plot circle :srcset: /auto_examples/images/sphx_glr_plot_circle_008.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none Meshed in 0.000726724 seconds. .. GENERATED FROM PYTHON SOURCE LINES 239-241 .. code-block:: Python plot_mesh(four_wierdly_connected_ones(50, 50)) .. image-sg:: /auto_examples/images/sphx_glr_plot_circle_009.png :alt: plot circle :srcset: /auto_examples/images/sphx_glr_plot_circle_009.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none Meshed in 0.134927 seconds. .. GENERATED FROM PYTHON SOURCE LINES 242-248 Doing it Right -------------- Probably the best way to mesh the circle is using five blocks, so that a quarter of the boundary is take care of by one block each, then they're all connected together using a central block with no numerical boundaries. .. GENERATED FROM PYTHON SOURCE LINES 249-332 .. code-block:: Python def as_god_intended(n1: int, n2: int, n3: int) -> Mesh2D: """Mesh the circle the way God intended.""" angle_l = np.linspace(+0 * np.pi / 2, +1 * np.pi / 2, n1) angle_b = np.linspace(+1 * np.pi / 2, +2 * np.pi / 2, n2) angle_r = np.linspace(+2 * np.pi / 2, +3 * np.pi / 2, n1) angle_t = np.linspace(+3 * np.pi / 2, +4 * np.pi / 2, n2) cl = BoundaryCurve(np.cos(angle_l), np.sin(angle_l)) cr = BoundaryCurve(np.cos(angle_r), np.sin(angle_r)) ct = BoundaryCurve(np.cos(angle_t), np.sin(angle_t)) cb = BoundaryCurve(np.cos(angle_b), np.sin(angle_b)) blockwest = MeshBlock( "left", { BoundaryId.BoundaryWest: cl, BoundaryId.BoundaryEast: BoundaryBlock("center", BoundaryId.BoundaryWest, n1), BoundaryId.BoundaryNorth: BoundaryBlock("top", BoundaryId.BoundaryWest, n3), BoundaryId.BoundarySouth: BoundaryBlock( "bottom", BoundaryId.BoundaryWest, n3 ), }, ) blockeast = MeshBlock( "right", { BoundaryId.BoundaryWest: BoundaryBlock("center", BoundaryId.BoundaryEast, n1), BoundaryId.BoundaryEast: cr, BoundaryId.BoundaryNorth: BoundaryBlock("top", BoundaryId.BoundaryEast, n3), BoundaryId.BoundarySouth: BoundaryBlock( "bottom", BoundaryId.BoundaryEast, n3 ), }, ) blocknorth = MeshBlock( "top", { BoundaryId.BoundaryWest: BoundaryBlock("left", BoundaryId.BoundaryNorth, n3), BoundaryId.BoundaryEast: BoundaryBlock("right", BoundaryId.BoundaryNorth, n3), BoundaryId.BoundaryNorth: ct, BoundaryId.BoundarySouth: BoundaryBlock( "center", BoundaryId.BoundaryNorth, n2 ), }, ) blocksouth = MeshBlock( "bottom", { BoundaryId.BoundaryWest: BoundaryBlock("left", BoundaryId.BoundarySouth, n3), BoundaryId.BoundaryEast: BoundaryBlock("right", BoundaryId.BoundarySouth, n3), BoundaryId.BoundaryNorth: BoundaryBlock( "center", BoundaryId.BoundarySouth, n2 ), BoundaryId.BoundarySouth: cb, }, ) blockmiddle = MeshBlock( "center", { BoundaryId.BoundaryWest: BoundaryBlock("left", BoundaryId.BoundaryEast, n1), BoundaryId.BoundaryEast: BoundaryBlock("right", BoundaryId.BoundaryWest, n1), BoundaryId.BoundaryNorth: BoundaryBlock("top", BoundaryId.BoundarySouth, n2), BoundaryId.BoundarySouth: BoundaryBlock( "bottom", BoundaryId.BoundaryNorth, n2 ), }, ) t0 = perf_counter() m, _, _ = create_elliptical_mesh( [blockwest, blockeast, blocknorth, blocksouth, blockmiddle], verbose=False, solver_cfg=SolverConfig( smoother_rounds=0, max_iterations=64, tolerance=5e-6, force_direct=False ), ) t1 = perf_counter() print(f"Meshed in {t1 - t0:g} seconds.") return m .. GENERATED FROM PYTHON SOURCE LINES 333-334 .. code-block:: Python plot_mesh(as_god_intended(2, 2, 2)) .. image-sg:: /auto_examples/images/sphx_glr_plot_circle_010.png :alt: plot circle :srcset: /auto_examples/images/sphx_glr_plot_circle_010.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none Meshed in 8.061e-05 seconds. .. GENERATED FROM PYTHON SOURCE LINES 335-336 .. code-block:: Python plot_mesh(as_god_intended(5, 5, 5)) .. image-sg:: /auto_examples/images/sphx_glr_plot_circle_011.png :alt: plot circle :srcset: /auto_examples/images/sphx_glr_plot_circle_011.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none Meshed in 0.000360712 seconds. .. GENERATED FROM PYTHON SOURCE LINES 337-339 .. code-block:: Python plot_mesh(as_god_intended(25, 25, 25)) .. image-sg:: /auto_examples/images/sphx_glr_plot_circle_012.png :alt: plot circle :srcset: /auto_examples/images/sphx_glr_plot_circle_012.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none Meshed in 0.0188475 seconds. .. GENERATED FROM PYTHON SOURCE LINES 340-346 No Boundaries ------------- If you decide to define a mesh which has no numerical boundaries, it is technically possible, however, the solver will just place all points in the origin, though the topology will still remain correct. .. GENERATED FROM PYTHON SOURCE LINES 347-376 .. code-block:: Python def ungodly(n1: int, n2: int) -> Mesh2D: """Mesh with no hard boundaries.""" blockmiddle = MeshBlock( "center", { BoundaryId.BoundaryWest: BoundaryBlock("center", BoundaryId.BoundaryEast, n1), BoundaryId.BoundaryEast: BoundaryBlock("center", BoundaryId.BoundaryWest, n1), BoundaryId.BoundaryNorth: BoundaryBlock( "center", BoundaryId.BoundarySouth, n2 ), BoundaryId.BoundarySouth: BoundaryBlock( "center", BoundaryId.BoundaryNorth, n2 ), }, ) t0 = perf_counter() m, _, _ = create_elliptical_mesh( [blockmiddle], verbose=False, solver_cfg=SolverConfig(smoother_rounds=0, max_iterations=64), ) t1 = perf_counter() print(f"Meshed in {t1 - t0:g} seconds.") return m .. GENERATED FROM PYTHON SOURCE LINES 377-378 .. code-block:: Python plot_mesh(ungodly(2, 2)) .. image-sg:: /auto_examples/images/sphx_glr_plot_circle_013.png :alt: plot circle :srcset: /auto_examples/images/sphx_glr_plot_circle_013.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none Meshed in 2.8743e-05 seconds. .. GENERATED FROM PYTHON SOURCE LINES 379-380 .. code-block:: Python plot_mesh(ungodly(5, 5)) .. image-sg:: /auto_examples/images/sphx_glr_plot_circle_014.png :alt: plot circle :srcset: /auto_examples/images/sphx_glr_plot_circle_014.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none Meshed in 4.2429e-05 seconds. .. GENERATED FROM PYTHON SOURCE LINES 381-383 .. code-block:: Python plot_mesh(ungodly(25, 25)) .. image-sg:: /auto_examples/images/sphx_glr_plot_circle_015.png :alt: plot circle :srcset: /auto_examples/images/sphx_glr_plot_circle_015.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none Meshed in 0.000329073 seconds. .. GENERATED FROM PYTHON SOURCE LINES 384-389 Mixing Up Boundaries -------------------- Once, again, mixing up boundaries will inevitably result in a self-overlapping mesh. This example here does so with four different blocks. .. GENERATED FROM PYTHON SOURCE LINES 390-452 .. code-block:: Python def four_weirder(n: int) -> Mesh2D: """Outer boundary's correct, but the rest is not.""" angle_l = np.linspace(+0 * np.pi / 2, +1 * np.pi / 2, n) angle_b = np.linspace(+1 * np.pi / 2, +2 * np.pi / 2, n) angle_r = np.linspace(+2 * np.pi / 2, +3 * np.pi / 2, n) angle_t = np.linspace(+3 * np.pi / 2, +4 * np.pi / 2, n) cl = BoundaryCurve(np.cos(angle_l), np.sin(angle_l)) cr = BoundaryCurve(np.cos(angle_r), np.sin(angle_r)) ct = BoundaryCurve(np.cos(angle_t), np.sin(angle_t)) cb = BoundaryCurve(np.cos(angle_b), np.sin(angle_b)) blockwest = MeshBlock( "left", { BoundaryId.BoundaryWest: cl, BoundaryId.BoundaryEast: BoundaryBlock("bottom", BoundaryId.BoundaryWest), BoundaryId.BoundaryNorth: BoundaryBlock("top", BoundaryId.BoundarySouth), BoundaryId.BoundarySouth: BoundaryBlock("right", BoundaryId.BoundaryNorth), }, ) blockeast = MeshBlock( "right", { BoundaryId.BoundaryWest: BoundaryBlock("top", BoundaryId.BoundaryEast), BoundaryId.BoundaryEast: cr, BoundaryId.BoundaryNorth: BoundaryBlock("left", BoundaryId.BoundarySouth), BoundaryId.BoundarySouth: BoundaryBlock("bottom", BoundaryId.BoundaryNorth), }, ) blocknorth = MeshBlock( "top", { BoundaryId.BoundaryWest: BoundaryBlock("bottom", BoundaryId.BoundaryEast), BoundaryId.BoundaryEast: BoundaryBlock("right", BoundaryId.BoundaryWest), BoundaryId.BoundaryNorth: ct, BoundaryId.BoundarySouth: BoundaryBlock("left", BoundaryId.BoundaryNorth), }, ) blocksouth = MeshBlock( "bottom", { BoundaryId.BoundaryWest: BoundaryBlock("left", BoundaryId.BoundaryEast), BoundaryId.BoundaryEast: BoundaryBlock("top", BoundaryId.BoundaryWest), BoundaryId.BoundaryNorth: BoundaryBlock("right", BoundaryId.BoundarySouth), BoundaryId.BoundarySouth: cb, }, ) t0 = perf_counter() m, _, _ = create_elliptical_mesh( [blockwest, blockeast, blocknorth, blocksouth], verbose=False, solver_cfg=SolverConfig(smoother_rounds=0, max_iterations=64), ) t1 = perf_counter() print(f"Meshed in {t1 - t0:g} seconds.") return m .. GENERATED FROM PYTHON SOURCE LINES 453-454 .. code-block:: Python plot_mesh(four_weirder(2)) .. image-sg:: /auto_examples/images/sphx_glr_plot_circle_016.png :alt: plot circle :srcset: /auto_examples/images/sphx_glr_plot_circle_016.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none Meshed in 9.4667e-05 seconds. .. GENERATED FROM PYTHON SOURCE LINES 455-456 .. code-block:: Python plot_mesh(four_weirder(10)) .. image-sg:: /auto_examples/images/sphx_glr_plot_circle_017.png :alt: plot circle :srcset: /auto_examples/images/sphx_glr_plot_circle_017.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none Meshed in 0.000762533 seconds. .. GENERATED FROM PYTHON SOURCE LINES 457-458 .. code-block:: Python plot_mesh(four_weirder(50)) .. image-sg:: /auto_examples/images/sphx_glr_plot_circle_018.png :alt: plot circle :srcset: /auto_examples/images/sphx_glr_plot_circle_018.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none Meshed in 0.0690637 seconds. .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 1.740 seconds) .. _sphx_glr_download_auto_examples_plot_circle.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_circle.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_circle.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_circle.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_