.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "tutorials/plot_05_eigenmode_sphere.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_tutorials_plot_05_eigenmode_sphere.py: Eigenmode analysis: a spherical cavity ====================================== All previous tutorials solved *driven* problems: a port launches a wave, the solver computes what scatters where. This one introduces the second analysis type. A closed cavity has no ports and no excitation — it has *eigenmodes*: the discrete set of field patterns and resonant frequencies the geometry supports on its own. :class:`~magnelio.AnalysisEigenmode` computes them directly. The perfect benchmark is a sphere: its resonances are known in closed form from the zeros of spherical Bessel functions, so every computed frequency can be checked to a fraction of a percent — including the degeneracies that the spherical symmetry dictates. .. GENERATED FROM PYTHON SOURCE LINES 19-41 The problem ----------- A perfectly conducting spherical shell of radius :math:`R` encloses vacuum. Its resonant frequencies are :math:`f = k R \cdot c_0 / (2 \pi R)` with :math:`kR` a root of a spherical Bessel condition. The three lowest levels: ========= =========== ========== mode :math:`kR` degeneracy ========= =========== ========== TM (n=1) 2.74371 3 TM (n=2) 3.87024 5 TE (n=1) 4.49341 3 ========= =========== ========== The degeneracies follow from symmetry — the lowest TM mode is a dipole-like pattern that exists in three independent orientations, so the spectrum contains that frequency three times. With :math:`R = 20` mm the first two levels sit at 6.546 GHz and 9.233 GHz; the eight lowest eigenmodes are exactly these two clusters (3 + 5). .. GENERATED FROM PYTHON SOURCE LINES 41-56 .. code-block:: Python import math import matplotlib.pyplot as plt import magnelio as mio from magnelio import geo from magnelio.constants import * R = 20e-3 # cavity radius [m] levels = [("TM n=1", 2.743707, 3), ("TM n=2", 3.870239, 5)] for name, kr, g in levels: print(f"{name}: {kr * C0 / (2 * math.pi * R) / 1e9:.4f} GHz (x{g})") .. rst-class:: sphx-glr-script-out .. code-block:: none TM n=1: 6.5456 GHz (x3) TM n=2: 9.2331 GHz (x5) .. GENERATED FROM PYTHON SOURCE LINES 57-68 Model and mesh -------------- The cavity is literally a hole in metal: a PEC background with an air-filled :class:`~magnelio.geo.Sphere` carved into it — the same trick that gave the coax tutorials their shield for free. No ports, no boundary declaration (the default all-PEC closure is exactly the cavity wall). The curved wall cuts through the rectangular grid; the partially filled cells are handled by the conformal boundary treatment, which is what makes sub-percent accuracy possible at this modest resolution. .. GENERATED FROM PYTHON SOURCE LINES 68-78 .. code-block:: Python pec = mio.Material.pec() air = mio.Material.air() model = mio.GeometryModel(background=pec) model.add(geo.Sphere(center=(0, 0, 0), radius=R, material=air)) mesh = mio.Mesh.from_geometry(model, mio.MeshControl(max_cell_size=1.5e-3), f_max=11e9) print(f"grid: {mesh.Nx} x {mesh.Ny} x {mesh.Nz} cells") .. rst-class:: sphx-glr-script-out .. code-block:: none grid: 30 x 30 x 30 cells .. GENERATED FROM PYTHON SOURCE LINES 79-85 Solving for the eigenmodes -------------------------- ``n_modes`` asks for the eight lowest physical modes — the two complete degenerate clusters. The result carries the resonant frequencies and the full 3D field pattern of every mode. .. GENERATED FROM PYTHON SOURCE LINES 85-91 .. code-block:: Python result = mio.AnalysisEigenmode(mesh=mesh, n_modes=8, verbose=False).run() for i, fi in enumerate(result.frequencies): print(f"mode {i}: {fi / 1e9:.4f} GHz") .. rst-class:: sphx-glr-script-out .. code-block:: none mode 0: 6.5461 GHz mode 1: 6.5461 GHz mode 2: 6.5472 GHz mode 3: 9.2116 GHz mode 4: 9.2120 GHz mode 5: 9.2131 GHz mode 6: 9.2403 GHz mode 7: 9.2423 GHz .. GENERATED FROM PYTHON SOURCE LINES 92-94 The spectrum shows exactly the predicted structure — a triplet and a quintet: .. GENERATED FROM PYTHON SOURCE LINES 94-104 .. code-block:: Python for name, kr, g in levels: f_ana = kr * C0 / (2 * math.pi * R) cluster = [fi for fi in result.frequencies if abs(fi / f_ana - 1) < 0.02] errs = [100 * (fi / f_ana - 1) for fi in cluster] print( f"{name}: analytic {f_ana / 1e9:.4f} GHz, found {len(cluster)} modes, " f"deviations {min(errs):+.3f} % .. {max(errs):+.3f} %" ) .. rst-class:: sphx-glr-script-out .. code-block:: none TM n=1: analytic 6.5456 GHz, found 3 modes, deviations +0.008 % .. +0.025 % TM n=2: analytic 9.2331 GHz, found 5 modes, deviations -0.233 % .. +0.100 % .. GENERATED FROM PYTHON SOURCE LINES 105-123 The triplet lands within 0.03 % of the Bessel value, the quintet within 0.25 %. On the ideal sphere each cluster would be exactly degenerate; the rectangular grid breaks the symmetry weakly, so the computed cluster is split by that same small amount — the split is a discretisation fingerprint, not physics. Looking at a mode ----------------- ``result.plot()`` draws any mode on an axis-aligned slice through the cavity: ``normal`` and ``position`` select the plane, ``component`` the field quantity, and ``plot_type`` switches between colour map, contours, and arrows. The mode fields live on the staggered simulation grid; the plot interpolates them onto a common set of points internally, so a picture is one call. Amplitudes are in arbitrary units — an eigenmode has no absolute scale, only a shape. Passing the geometry model overlays its cross-section: the dashed circle is the cavity wall, sliced from the actual model: .. GENERATED FROM PYTHON SOURCE LINES 123-131 .. code-block:: Python fig, axes = plt.subplots(1, 2, figsize=(11, 4.6)) for ax, m in zip(axes, (0, 3)): result.plot( mode=m, component="E", normal="y", position=0.0, plot_type="color", geometry=model, ax=ax ) fig.tight_layout() .. image-sg:: /tutorials/images/sphx_glr_plot_05_eigenmode_sphere_001.png :alt: Mode 0 (6.546 GHz) — |E|, y=0.667 mm, Mode 3 (9.212 GHz) — |E|, y=0.667 mm :srcset: /tutorials/images/sphx_glr_plot_05_eigenmode_sphere_001.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 132-148 Mode 0 shows the dipole-like pattern of the lowest TM resonance; mode 3, the first member of the quintet, already carries the richer angular structure of the :math:`n = 2` level. ``plot_type="vector"`` shows the field *direction*. Arrows draw the in-plane part of the field; where the field pierces the slice plane instead — tilted so far out of the plane that a projected arrow would be unreadable — a circle marker appears: ⊙ pointing towards the positive normal axis, ⊗ towards the negative one, coloured by the field magnitude like the arrows. The quintet mode from above shows both at once, and a piece of physics with them. On this slice its **E** field lies entirely *in* the plane (left). **H** is everywhere perpendicular to E, so it pierces the slice (right): outward and inward in alternating sectors, separated by the blank node lines of the pattern — a sign structure the ⊙/⊗ markers resolve and a magnitude plot would hide: .. GENERATED FROM PYTHON SOURCE LINES 148-162 .. code-block:: Python fig, axes = plt.subplots(1, 2, figsize=(11, 4.6)) for ax, comp in zip(axes, ("E", "H")): result.plot( mode=3, component=comp, normal="x", position=0.0, plot_type="vector", geometry=model, ax=ax, ) fig.tight_layout() .. image-sg:: /tutorials/images/sphx_glr_plot_05_eigenmode_sphere_002.png :alt: Mode 3 (9.212 GHz) — E-field, x=0.667 mm, Mode 3 (9.212 GHz) — H-field, x=0.667 mm :srcset: /tutorials/images/sphx_glr_plot_05_eigenmode_sphere_002.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 163-176 (Which sector carries ⊙ and which ⊗ is not meaningful — the overall sign of an eigenmode is arbitrary, and inside a degenerate cluster the same holds for the mode's *orientation*.) Where to go next ---------------- New in this tutorial: the eigenmode analysis type, degenerate mode clusters as a symmetry statement (and their weak splitting as a discretisation fingerprint), and mode field plots on slice planes through the cavity. The next tutorials turn to the toolbox around the solvers — starting with field monitors, which record fields *during* a driven simulation. .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 31.520 seconds) .. _sphx_glr_download_tutorials_plot_05_eigenmode_sphere.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_05_eigenmode_sphere.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_05_eigenmode_sphere.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_05_eigenmode_sphere.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_