.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "tutorials/plot_15_dipole_farfield.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_15_dipole_farfield.py: Antenna symmetry: a half-wave dipole as a half model ==================================================== The microstrip tutorial cut a model in half with a *magnetic* symmetry plane through the substrate. Antennas offer the electric counterpart: a center-fed dipole is mirror-symmetric about the plane through its feed, and because the current flows *through* that plane, the mirror is an electric wall — the same image theory that turned the monopole tutorial's ground plane into a virtual dipole, now used deliberately to halve the computation. Three things meet in this model: the symmetry declaration, a lumped feed sitting exactly on the symmetry plane, and the far-field monitor reconstructing the full-sphere radiation pattern from the half that was solved. .. GENERATED FROM PYTHON SOURCE LINES 18-20 .. code-block:: Python :dedent: 1 .. GENERATED FROM PYTHON SOURCE LINES 22-38 The geometry: declared whole, meshed half ----------------------------------------- Everything is declared in full-model coordinates — both dipole arms, the full air volume, the feed crossing z = 0. The single declaration ``"zmin": "SymmetryPEC"`` states that the plane at z = 0 is an electric mirror; the mesher then simply never meshes the lower half. Deleting the lower arm by hand would change nothing but the room for error. The feed deserves a closer look. Its endpoints straddle the symmetry plane, its reference impedance is the full dipole's 73 Ω. Internally the solver keeps the meshed half of the device — half the gap in series with half the impedance — and reports every quantity at full-model scale, exactly as the port impedances of the microstrip tutorial did. Declared watts stay full-model watts. .. GENERATED FROM PYTHON SOURCE LINES 38-94 .. code-block:: Python import matplotlib.pyplot as plt import numpy as np import magnelio as mio from magnelio import geo, monitors, plots, ports h_arm = 27.3e-3 # arm length incl. half the feed gap (trimmed; ~0.45 lambda total) gap = 2.0e-3 # feed gap a_wire = 0.5e-3 # wire radius pad = 50.0e-3 # clearance antenna -> absorbing boundary air = mio.Material.air() model = mio.GeometryModel( boundary_conditions={ "zmin": "SymmetryPEC", # electric mirror through the feed "xmin": "CPML", "xmax": "CPML", "ymin": "CPML", "ymax": "CPML", "zmax": "CPML", } ) model.add( geo.Brick( origin=(-pad, -pad, -(h_arm + pad)), size=(2 * pad, 2 * pad, 2 * (h_arm + pad)), material=air, ) ) model.add( geo.ThinWire( geo.Curve.polyline([(0.0, 0.0, gap / 2), (0.0, 0.0, h_arm)]), radius=a_wire, name="arm_up", ) ) model.add( geo.ThinWire( geo.Curve.polyline([(0.0, 0.0, -h_arm), (0.0, 0.0, -gap / 2)]), radius=a_wire, name="arm_down", ) ) model.add_port( ports.PortLumped( name="feed", start=(0.0, 0.0, -gap / 2), end=(0.0, 0.0, gap / 2), Z0=73.0, ) ) fig, ax = plots.plot_cross_section(model, "y", 0.0, title="full model (meshed: z > 0 only)") .. image-sg:: /tutorials/images/sphx_glr_plot_15_dipole_farfield_001.png :alt: full model (meshed: z > 0 only) :srcset: /tutorials/images/sphx_glr_plot_15_dipole_farfield_001.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 95-103 Mesh, monitors, run ------------------- The mesh shows the declaration at work: the grid starts at z = 0. The far-field monitor needs no target frequency band of its own — one frequency is enough for a pattern — and no geometry: it places its recording box inside the free-space region and books the symmetry plane automatically. .. GENERATED FROM PYTHON SOURCE LINES 103-126 .. code-block:: Python f_min, f_max = 1.0e9, 4.0e9 f0 = 2.45e9 mesh = mio.Mesh.from_geometry( model, mio.MeshControl(min_nodes_per_wavelength=20), f_max=f_max, ) print(f"grid: {mesh.Nx} x {mesh.Ny} x {mesh.Nz} cells, z from {mesh.grid.z[0] * 1e3:.0f} mm") farfield = monitors.MonitorFarField(freqs=[f0], name="farfield") analysis = mio.AnalysisScatteringTD( mesh=mesh, f_min=f_min, f_max=f_max, monitors=(farfield,), verbose=False, ) f_axis = np.linspace(f_min, f_max, 301) result = analysis.run(f_axis=f_axis, excited=["feed"]) .. rst-class:: sphx-glr-script-out .. code-block:: none grid: 46 x 46 x 55 cells, z from 0 mm .. GENERATED FROM PYTHON SOURCE LINES 127-135 Full-model electrical results from half a model ----------------------------------------------- The input impedance derived from S11 lands at the *dipole's* textbook values — resonance where the total length is a bit under half a wavelength, feed resistance near 73 Ω. A missing factor of two here would be the monopole reading; the symmetry accounting is what keeps it away. .. GENERATED FROM PYTHON SOURCE LINES 135-158 .. code-block:: Python s11 = result.S("feed", "feed") zin = 73.0 * (1 + s11) / (1 - s11) im = zin.imag i = int(np.nonzero((im[:-1] < 0) & (im[1:] >= 0))[0][0]) f_res = f_axis[i] - im[i] * (f_axis[i + 1] - f_axis[i]) / (im[i + 1] - im[i]) r_res = float(np.interp(f_res, f_axis, zin.real)) print(f"resonance (Im Zin = 0): {f_res / 1e9:.2f} GHz") print(f"feed resistance there: {r_res:.1f} Ohm (thin-dipole textbook: ~73)") fig, ax = plt.subplots(figsize=(7, 4.2)) ax.plot(f_axis / 1e9, zin.real, label="R (real part)") ax.plot(f_axis / 1e9, zin.imag, label="X (imaginary part)") ax.axhline(0.0, color="gray", lw=0.8) ax.axvline(f_res / 1e9, color="gray", lw=0.8, ls="--") ax.set_xlabel("frequency [GHz]") ax.set_ylabel(r"$Z_\mathrm{in}$ [$\Omega$]") ax.set_ylim(-300, 400) ax.legend() ax.set_title("dipole input impedance from the half model") fig.tight_layout() .. image-sg:: /tutorials/images/sphx_glr_plot_15_dipole_farfield_002.png :alt: dipole input impedance from the half model :srcset: /tutorials/images/sphx_glr_plot_15_dipole_farfield_002.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none resonance (Im Zin = 0): 2.45 GHz feed resistance there: 75.4 Ohm (thin-dipole textbook: ~73) .. GENERATED FROM PYTHON SOURCE LINES 159-166 The full-sphere pattern ----------------------- Unlike the monopole's ground plane, a symmetry plane is bookkeeping, not physics: the mirror half of the world exists, so the pattern covers the whole sphere. The elevation cut shows the dipole donut — and the peak lands at the half-wave dipole's 2.15 dBi. .. GENERATED FROM PYTHON SOURCE LINES 166-178 .. code-block:: Python pattern = farfield.result(f0) fig, axes = plt.subplots(1, 2, figsize=(11.0, 4.6), subplot_kw={"projection": "polar"}) pattern.plot_cut(plane="phi", angle=0.0, ax=axes[0], title="elevation cut (E-plane)") pattern.plot_cut(plane="theta", angle=np.pi / 2, ax=axes[1], title="azimuth cut (H-plane)") fig.tight_layout() print(f"peak directivity: {10 * np.log10(pattern.directivity.max()):.2f} dBi") print(f"peak realized gain: {10 * np.log10(pattern.realized_gain.max()):.2f} dBi") print(f"radiated power: {pattern.P_rad:.3f} W per incident W") .. image-sg:: /tutorials/images/sphx_glr_plot_15_dipole_farfield_003.png :alt: elevation cut (E-plane), azimuth cut (H-plane) :srcset: /tutorials/images/sphx_glr_plot_15_dipole_farfield_003.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none peak directivity: 2.15 dBi peak realized gain: 2.07 dBi radiated power: 0.982 W per incident W .. GENERATED FROM PYTHON SOURCE LINES 179-183 The elevation cut carries the shape; the azimuth cut is the circle every wire antenna owes its users. The 3D surface puts both into one picture — the radius is the gain in dB above the floor, so the axial nulls show as pinch points. .. GENERATED FROM PYTHON SOURCE LINES 183-186 .. code-block:: Python fig, ax = pattern.plot_3d(title="dipole radiation surface (dB radius)") .. image-sg:: /tutorials/images/sphx_glr_plot_15_dipole_farfield_004.png :alt: dipole radiation surface (dB radius) :srcset: /tutorials/images/sphx_glr_plot_15_dipole_farfield_004.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 187-197 Where to go next ---------------- New in this tutorial: an electric symmetry plane halving an antenna problem, a lumped feed declared across the symmetry plane in full-model coordinates, the full-sphere far field reconstructed from a half model, and pattern cuts plus the 3D radiation surface. The same three ingredients carry over unchanged to patch antennas and arrays — declare the full structure, state its symmetry, and read full-model answers. .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 27.286 seconds) .. _sphx_glr_download_tutorials_plot_15_dipole_farfield.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_15_dipole_farfield.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_15_dipole_farfield.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_15_dipole_farfield.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_