%global pypi_name emerge Name: python-%{pypi_name} # Hertzon pins emerge==2.8.9 exactly; move the two together. Version: 2.8.9 Release: 1%{?dist} Summary: Open-source 3D full-wave electromagnetic FEM simulator in Python # LICENSE: GPL v2 or later with the original Gmsh additional permission (the # source headers say "or (at your option) any later version"). License: GPL-2.0-or-later WITH Gmsh-exception URL: https://github.com/FennisRobert/EMerge Source0: %{pypi_source %{pypi_name}} BuildArch: noarch BuildRequires: python3-devel BuildRequires: pyproject-rpm-macros %global _description %{expand: EMerge is a frequency-domain finite-element solver for 3D electromagnetics: geometry and meshing through gmsh/OpenCASCADE, 2nd-order Nedelec elements, wave, lumped, Floquet and user-defined ports, PEC/PMC, impedance, absorbing and periodic boundaries, S-parameter sweeps, eigenmodes, near and far fields and PyVista field display. The element kernels are compiled with numba on first use. It is the solver underneath the Hertzon GUI.} %description %_description %package -n python3-%{pypi_name} Summary: %{summary} # Faster direct solve when present; EMerge falls back to SciPy SuperLU. Recommends: python3dist(scikit-umfpack) # DXF import/export (emerge.beta.dxf) Suggests: python3dist(ezdxf) %description -n python3-%{pypi_name} %_description %prep %autosetup -n %{pypi_name}-%{version} # Upstream caps are release pins, not known breakage. Fedora 44 has # Python 3.14, gmsh 4.15 and numpy 2.4; Fedora 45 numpy 2.5. # mkl (x86_64 only, proprietary) is optional: EMerge uses PARDISO only when # it can load it. sed -i \ -e 's/requires-python = ">=3.10, <3.14"/requires-python = ">=3.10"/' \ -e 's/"gmsh>=4.13.0, <4.15"/"gmsh>=4.13.0"/' \ -e 's/"numpy>=2.2, <2.5"/"numpy>=2.2"/' \ -e '/"mkl!=2024.0;/d' \ pyproject.toml %generate_buildrequires %pyproject_buildrequires %build %pyproject_wheel %install %pyproject_install %pyproject_save_files %{pypi_name} emerge_config %check # The optional extras: beta.gerber needs pygerber (not packaged), beta.dxf # needs ezdxf. The cuDSS/PARDISO/UMFPACK solve interfaces import lazily. %pyproject_check_import -e 'emerge.beta.gerber' -e 'emerge.beta._gerber*' -e 'emerge.beta.dxf' -e 'emerge._emerge.geo.pcb_tools.dxf' # A parallel-plate (TEM) line, 50 mm long at 10 GHz, PEC top and bottom and # PMC sides, between two user-defined ports: it must pass almost everything # with the phase of free space. mkdir -p %{_builddir}/emerge-check && cd %{_builddir}/emerge-check export NUMBA_CACHE_DIR=$PWD/numba-cache MPLBACKEND=Agg %{py3_test_envvars} %{python3} - <<'PYEOF' import numpy as np import emerge as em mm = 1e-3 model = em.Simulation("ParallelPlates") box = em.geo.Box(20 * mm, 20 * mm, 50 * mm, position=(-10 * mm, -10 * mm, 0)) model.commit_geometry() model.mw.set_frequency(10e9) model.generate_mesh() Ey = lambda k0, x, y, z: np.ones_like(x) model.mw.bc.UserDefinedPort(box.bottom, 1, Ey=Ey) model.mw.bc.UserDefinedPort(box.top, 2, Ey=Ey) model.mw.bc.PMC(box.left + box.right) data = model.mw.run_sweep() g = data.scalar.grid s11, s21 = complex(np.ravel(g.S(1, 1))[0]), complex(np.ravel(g.S(2, 1))[0]) k0 = 2 * np.pi * 10e9 / 299792458 dphi = np.angle(s21 * np.exp(1j * k0 * 50 * mm)) print("S11 %.4f |S21| %.4f phase error %.2f deg" % (abs(s11), abs(s21), np.degrees(dphi))) assert abs(s11) < 0.05 and abs(s21) > 0.99, (s11, s21) assert abs(np.degrees(dphi)) < 3, np.degrees(dphi) PYEOF # A kernel compiled during the solve can still land beside its source. find %{buildroot}%{python3_sitelib} -name '*.nb[ci]' -delete %files -n python3-%{pypi_name} -f %{pyproject_files} %license LICENSE THIRD_PARTY_LICENSES.md %doc README.md %{_bindir}/emerge %changelog * Wed Oct 21 2026 Morgan Hough - 2.8.9-1 - Initial package (the solver underneath Hertzon).