# openEMS is a free FDTD electromagnetic field solver (openems.de), used for MRI RF-coil design: B1 field maps, # SAR, loop and birdcage coils at 1.5 T/3 T/7 T (python/Tutorials/MRI_Loop_Coil.py, matlab/Tutorials/MRI_*). Second # of the four openEMS packages (CSXCAD -> openEMS -> QCSXCAD -> AppCSXCAD). The bundled three-layer head and body # phantoms (resources/phantoms, IT'IS tissue values at 128/298 MHz) make the MRI tutorial runnable without the # Virtual Family voxel models, which IT'IS licenses and which cannot be redistributed. # # 0.37.0 is CPU-only (multithreaded SSE engine). Upstream's main branch has since added a HIP/CUDA GPU engine # (--engine=gpu); when a release carries it, it needs a CUDA or ROCm compiler the free project cannot carry # (docs/CUDA-RPM-FUSION.md), so it will have to be switched off here or built in the nonfree repo. %global libsuffix %(echo %{_lib} | sed 's/^lib//') Name: openEMS Version: 0.37.0 Release: 2%{?dist} Summary: Electromagnetic field solver (FDTD) with MRI coil, antenna and SAR tooling License: GPL-3.0-or-later URL: https://github.com/thliebig/openEMS Source0: %{url}/archive/v%{version}/openEMS-%{version}.tar.gz # python: build against the installed python3-CSXCAD instead of adding a git+https URL to the build requirements, # and search /lib64 rather than /lib/64 (same code as CSXCAD-python-lib64.patch). To report upstream. Patch0: openEMS-python-system-csxcad.patch BuildRequires: gcc-c++ BuildRequires: cmake BuildRequires: ninja-build BuildRequires: chrpath BuildRequires: CSXCAD-devel = 0.7.0 BuildRequires: fparser-devel BuildRequires: tinyxml-devel BuildRequires: hdf5-devel BuildRequires: boost-devel BuildRequires: zlib-devel BuildRequires: vtk-devel # Defines %%vtk_abi on Fedora's vtk (via vtk-abi-compat); our vtk provides it itself. BuildRequires: vtk(abi) # VTK cmake config pulls these at find_package time. BuildRequires: freetype-devel pugixml-devel fmt-devel utf8cpp-devel BuildRequires: PEGTL-devel jsoncpp-devel nlohmann-json-devel BuildRequires: double-conversion-devel expat-devel glew-devel lz4-devel BuildRequires: libxml2-devel libtiff-devel libjpeg-turbo-devel libpng-devel BuildRequires: mesa-libGL-devel # python3-openEMS BuildRequires: python3-devel BuildRequires: pyproject-rpm-macros BuildRequires: python3-Cython BuildRequires: python3-numpy BuildRequires: python3-h5py BuildRequires: python3-matplotlib BuildRequires: python3-CSXCAD # Pin the exact VTK ABI this package was built against. VTK freezes its soname at # libvtk*.so.1 across all of 9.x, so rpm cannot tell 9.5 from 9.6 from 9.7: a consumer # built against one installs cleanly against another and fails at LOAD with undefined # symbols. %%vtk_abi comes from vtk-devel's macros.vtk; the %%build test catches a # buildroot without it (see 3dslicer-igt.spec for why the check is not at parse time). Requires: vtk(abi) = %{?vtk_abi}%{!?vtk_abi:UNSET} %description openEMS is a free and open electromagnetic field solver using the FDTD method, with a Cartesian and a cylindrical mesh, lumped elements, ports, field probes, dumps (VTK, HDF5), SAR calculation and a near-field to far-field transform (nf2ff). Geometry comes from CSXCAD. The interfaces are Python (python3-openEMS) and Octave/MATLAB (openEMS-octave). Shipped tutorials include a 7 T MRI loop coil over a head phantom, a dipole SAR study, and the antenna and waveguide classics. %package devel Summary: Headers and development files for openEMS Requires: %{name}%{?_isa} = %{version}-%{release} Requires: CSXCAD-devel%{?_isa} %description devel Headers and the unversioned shared library links (libopenEMS, libnf2ff) for embedding the solver. %package -n python3-openEMS Summary: Python interface to the openEMS FDTD solver Requires: %{name}%{?_isa} = %{version}-%{release} # the Tutorials plot with matplotlib; python3-CSXCAD, numpy and h5py come from the metadata Requires: python3-matplotlib %py_provides python3-openems %description -n python3-openEMS Python (Cython) bindings for openEMS: set up excitation, boundaries, ports, probes and dumps, run the solver, read SAR and field dumps, and the nf2ff transform. The upstream tutorials (MRI_Loop_Coil.py, Dipole_SAR.py, antennas, waveguides) are installed under %{_datadir}/openEMS/python/Tutorials. %package octave Summary: Octave/MATLAB interface to openEMS BuildArch: noarch Requires: CSXCAD-octave = 0.7.0 Requires: %{name} = %{version}-%{release} Suggests: octave %description octave The openEMS .m interface (simulation setup, ports, nf2ff, SAR, VTK and HDF5 readers, tutorials incl. MRI_Loop_Coil.m and MRI_LP_Birdcage.m) for GNU Octave or MATLAB. Add %{_datadir}/openEMS/matlab and %{_datadir}/CSXCAD/matlab to the path. %prep %autosetup -p1 -n openEMS-%{version} %generate_buildrequires cd python # setup.py runs here too and insists on a prefix; none is needed for the metadata. export, not a prefix: the # macro expands to several commands and a prefix would reach only the first. export OPENEMS_NOSCM=1 OPENEMS_INSTALL_PATH_IGNORE=1 %pyproject_buildrequires %build test -n "%{?vtk_abi}" || { echo "ERROR: vtk_abi undefined - add 'BuildRequires: vtk-devel'" >&2; exit 1; } # FDTD/operator.cpp includes ; Fedora ships it in %%{_includedir}/fparser and openEMS only adds # ${FPARSER_ROOT_DIR}/include (fparser.pc says -I%%{_includedir} too). CSXCAD's own CMake searches the subdir. export CXXFLAGS="%{build_cxxflags} -I%{_includedir}/fparser" %cmake -G Ninja \ -DLIB_SUFFIX=%{libsuffix} \ -DENABLE_RPATH=OFF %cmake_build # The Python extensions compile against the headers and link libopenEMS/libnf2ff as installed. Stage that # layout under the build directory: a buildroot path compiled into the extensions trips check-buildroot. DESTDIR=$PWD/stage cmake --install %{_vpath_builddir} STAGE=$PWD/stage cd python export OPENEMS_NOSCM=1 OPENEMS_INSTALL_PATH_IGNORE=1 export CFLAGS="%{build_cflags} -I$STAGE%{_includedir}" CXXFLAGS="%{build_cxxflags} -I$STAGE%{_includedir} -I%{_includedir}/fparser" export LDFLAGS="%{build_ldflags} -L$STAGE%{_libdir}" %pyproject_wheel %install %cmake_install # openEMS.sh clears LD_LIBRARY_PATH and execs the binary next to itself: a relocatable-tarball helper. rm -f %{buildroot}%{_bindir}/openEMS.sh cd python %pyproject_install %pyproject_save_files openEMS cd .. # setup.py puts /usr/local/lib{,64} into the extensions' RPATH for so in %{buildroot}%{python3_sitearch}/openEMS/*.so; do chrpath --delete "$so"; done %check export LD_LIBRARY_PATH=%{buildroot}%{_libdir} # The solver and nf2ff print their banner and usage with no arguments (non-zero exit). %{buildroot}%{_bindir}/openEMS 2>&1 | grep -q 'openEMS' %{buildroot}%{_bindir}/nf2ff 2>&1 | grep -qi 'nf2ff' %pyproject_check_import # The phantoms the MRI tutorial falls back to must be inside the Python package (get_resource_path). test -s %{buildroot}%{python3_sitearch}/openEMS/resources/phantoms/phantom_head_298MHz.h5 %files %license COPYING %doc README.md CHANGELOG.md %{_bindir}/openEMS %{_bindir}/nf2ff %{_bindir}/sar_calc %{_libdir}/libopenEMS.so.0 %{_libdir}/libopenEMS.so.%{version} %{_libdir}/libnf2ff.so.0 # nf2ff keeps its own library version %{_libdir}/libnf2ff.so.0.1.0 %dir %{_datadir}/openEMS %{_datadir}/openEMS/resources/ %files devel %{_includedir}/openEMS/ %{_libdir}/libopenEMS.so %{_libdir}/libnf2ff.so %files -n python3-openEMS -f %{pyproject_files} %doc python/README.md %dir %{_datadir}/openEMS/python %{_datadir}/openEMS/python/Tutorials/ %files octave %license COPYING %{_datadir}/openEMS/matlab/ %changelog * Fri Oct 30 2026 Morgan Hough - 0.37.0-2 - Rebuild against Fedora's vtk 9.7.0 on rawhide. No spec change was needed: the mock build was clean and no binary needs libjava, libjvm or libvtkJava. * Fri Oct 23 2026 Morgan Hough - 0.37.0-1 - Initial package: openEMS 0.37.0 (solver, nf2ff, sar_calc, headers, python3-openEMS with the upstream tutorials incl. the 7 T MRI loop coil and dipole SAR, Octave scripts), on CSXCAD 0.7.0 and the project's VTK 9.7 (vtk(abi) pin). CPU engine only (0.37.0 has no GPU engine). The bundled head/body phantoms ship inside the Python package so MRI_Loop_Coil.py runs without the (non-redistributable) Virtual Family models. - Patch0: the PEP 517 backend demanded CSXCAD from git+https even with python3-CSXCAD installed, and setup.py searched /lib/64 (to report upstream). Extension RPATHs stripped with chrpath.