# SLEPc tracks PETSc release-for-release (SLEPc 3.N needs PETSc 3.N), so like # python-petsc4py the version follows whatever PETSc each Fedora release ships: # f43 petsc 3.23.6 -> slepc 3.23.3 # f44 petsc 3.24.6 -> slepc 3.24.3 # f45 petsc 3.25.x -> slepc 3.25.2 # f46 petsc 3.26.0 -> slepc 3.26.0 # Only the Open MPI flavour for now: it is the one fenics-dolfinx builds against. %global ver_f43 3.23.3 %global ver_f44 3.24.3 %global ver_f45 3.25.2 %global ver_f46 3.26.0 # The PETSc each release ships (its build-support files are carried, see below) %global petsc_f43 3.23.6 %global petsc_f44 3.24.6 %global petsc_f45 3.25.5 %global petsc_f46 3.26.0 %if 0%{?fedora} >= 46 %global srcnum 3 %global petsc_series 3.26 %global petsc_ver %{petsc_f46} %elif 0%{?fedora} == 45 %global srcnum 2 %global petsc_series 3.25 %global petsc_ver %{petsc_f45} %elif 0%{?fedora} == 43 %global srcnum 0 %global petsc_series 3.23 %global petsc_ver %{petsc_f43} %else %global srcnum 1 %global petsc_series 3.24 %global petsc_ver %{petsc_f44} %endif # SLEPc's configure (and slepc4py's) want a PETSc prefix laid out as # $PETSC_DIR/include + $PETSC_DIR/lib/petsc/conf; Fedora's Open MPI PETSc keeps # headers in %%{_includedir}/openmpi-%%{_arch}/petsc. Present that shape with a # symlink farm (the same approach as python-petsc4py). %global petscroot %{_builddir}/petscroot-openmpi Name: slepc %if 0%{?fedora} >= 46 Version: %{ver_f46} %elif 0%{?fedora} == 45 Version: %{ver_f45} %elif 0%{?fedora} == 43 Version: %{ver_f43} %else Version: %{ver_f44} %endif Release: 2%{?dist} Summary: Scalable Library for Eigenvalue Problem Computations License: BSD-2-Clause URL: https://slepc.upv.es/ # All four are listed so the SRPM (built before %%{fedora} is known) carries # each; %%prep unpacks the one for this release. Source0: https://slepc.upv.es/download/distrib/slepc-%{ver_f43}.tar.gz Source1: https://slepc.upv.es/download/distrib/slepc-%{ver_f44}.tar.gz Source2: https://slepc.upv.es/download/distrib/slepc-%{ver_f45}.tar.gz Source3: https://slepc.upv.es/download/distrib/slepc-%{ver_f46}.tar.gz # PETSc build-support files that Fedora's petsc packages do not ship but SLEPc's # build needs: conf/rules includes rules_doc.mk, SLEPc's rules include # rules_util.mk, and its library makefile is generated by gmakegen.py. Taken # from the PETSc release each Fedora version ships (BSD-2-Clause, as PETSc). %global petsc_raw https://gitlab.com/petsc/petsc/-/raw Source10: %{petsc_raw}/v%{petsc_f43}/config/gmakegen.py#/petsc-%{petsc_f43}-gmakegen.py Source11: %{petsc_raw}/v%{petsc_f43}/lib/petsc/conf/rules_util.mk#/petsc-%{petsc_f43}-rules_util.mk Source12: %{petsc_raw}/v%{petsc_f43}/lib/petsc/conf/rules_doc.mk#/petsc-%{petsc_f43}-rules_doc.mk Source13: %{petsc_raw}/v%{petsc_f44}/config/gmakegen.py#/petsc-%{petsc_f44}-gmakegen.py Source14: %{petsc_raw}/v%{petsc_f44}/lib/petsc/conf/rules_util.mk#/petsc-%{petsc_f44}-rules_util.mk Source15: %{petsc_raw}/v%{petsc_f44}/lib/petsc/conf/rules_doc.mk#/petsc-%{petsc_f44}-rules_doc.mk Source16: %{petsc_raw}/v%{petsc_f45}/config/gmakegen.py#/petsc-%{petsc_f45}-gmakegen.py Source17: %{petsc_raw}/v%{petsc_f45}/lib/petsc/conf/rules_util.mk#/petsc-%{petsc_f45}-rules_util.mk Source18: %{petsc_raw}/v%{petsc_f45}/lib/petsc/conf/rules_doc.mk#/petsc-%{petsc_f45}-rules_doc.mk Source19: %{petsc_raw}/v%{petsc_f46}/config/gmakegen.py#/petsc-%{petsc_f46}-gmakegen.py Source20: %{petsc_raw}/v%{petsc_f46}/lib/petsc/conf/rules_util.mk#/petsc-%{petsc_f46}-rules_util.mk Source21: %{petsc_raw}/v%{petsc_f46}/lib/petsc/conf/rules_doc.mk#/petsc-%{petsc_f46}-rules_doc.mk BuildRequires: gcc BuildRequires: gcc-c++ BuildRequires: make BuildRequires: python3-devel BuildRequires: openmpi-devel BuildRequires: petsc-openmpi-devel >= %{petsc_series} BuildRequires: petsc-openmpi-devel < %{petsc_series}.999 BuildRequires: python3-petsc-openmpi # Fedora's petscvariables link line names every PETSc dependency (-lHYPRE, # -ldmumps, -lscalapack, -lsuperlu_dist, -lflexiblas, -lptscotch, -lmetis, ...) # but petsc-openmpi-devel requires none of their -devel packages, so SLEPc's # configure link test fails without them. BuildRequires: hypre-openmpi-devel BuildRequires: MUMPS-openmpi-devel BuildRequires: scalapack-openmpi-devel BuildRequires: superlu_dist-openmpi-devel BuildRequires: flexiblas-devel BuildRequires: ptscotch-openmpi-devel BuildRequires: metis-devel BuildRequires: hdf5-openmpi-devel BuildRequires: libX11-devel BuildRequires: gcc-gfortran %if 0%{?fedora} >= 45 # f45+ PETSc is also built with CGNS and TetGen and names them on the link line BuildRequires: cgnslib-openmpi-devel BuildRequires: tetgen-devel %endif BuildRequires: python3-mpi4py-openmpi BuildRequires: python3-numpy BuildRequires: python3-Cython BuildRequires: python3-setuptools BuildRequires: python3-pip BuildRequires: python3-wheel BuildRequires: patchelf %global _description %{expand: SLEPc is a library for the solution of large scale sparse eigenvalue problems on parallel computers, built on PETSc. It provides eigensolvers (EPS), singular value (SVD), polynomial (PEP) and nonlinear (NEP) eigensolvers, and matrix functions (MFN), with Krylov-Schur, Davidson, LOBPCG and other methods.} %description %_description %package openmpi Summary: SLEPc built against Open MPI Requires: petsc-openmpi%{?_isa} %description openmpi %_description This package contains the Open MPI build. %package openmpi-devel Summary: Development files for SLEPc (Open MPI) Requires: %{name}-openmpi%{?_isa} = %{version}-%{release} Requires: petsc-openmpi-devel%{?_isa} %description openmpi-devel Headers, pkg-config file, makefile fragments and library link for SLEPc built against Open MPI. %package -n python3-slepc-openmpi Summary: Python bindings for SLEPc (slepc4py, Open MPI) Requires: %{name}-openmpi%{?_isa} = %{version}-%{release} Requires: python3-petsc-openmpi%{?_isa} Provides: slepc4py-openmpi = %{version}-%{release} %description -n python3-slepc-openmpi slepc4py, the Python bindings for SLEPc, built against Open MPI. Installed in the Open MPI Python path, alongside python3-petsc-openmpi's petsc4py. %prep %setup -q -c -T tar -xzf %{_sourcedir}/slepc-%{version}.tar.gz --strip-components=1 test -f include/slepcversion.h grep -q "SLEPC_VERSION_MINOR *$(echo %{version} | cut -d. -f2)" include/slepcversion.h # From 3.25 SLEPc generates its Fortran bindings with PETSc's # lib/petsc/bin/generatefortranbindings.py, which needs getAPI.py and the # classes.data PETSc writes during its own build; Fedora ships none of them # (configure: "No module named 'generatefortranbindings'", f45/rawhide). Build # without Fortran bindings there by not taking PETSC_USE_FORTRAN_BINDINGS from # petscconf.h. C, C++ and Python (slepc4py) are unaffected. if grep -q "import generatefortranbindings" config/configure.py; then sed -i "s/l\[1\]=='PETSC_USE_FORTRAN_BINDINGS' and l\[2\]=='1':/l[1]=='PETSC_USE_FORTRAN_BINDINGS' and l[2]=='1' and False:/" config/packages/petsc.py grep -q "PETSC_USE_FORTRAN_BINDINGS' and l\[2\]=='1' and False:" config/packages/petsc.py fi %build %{_openmpi_load} rm -rf %{petscroot}; mkdir -p %{petscroot}/lib/petsc/conf ln -s %{_includedir}/openmpi-%{_arch}/petsc %{petscroot}/include for f in ${MPI_LIB}/*; do [ "$(basename $f)" = petsc ] || ln -s $f %{petscroot}/lib/; done for f in ${MPI_LIB}/petsc/conf/*; do ln -s $f %{petscroot}/lib/petsc/conf/; done # Fedora's petsc-openmpi-devel ships conf/rules and variables but not the # build-support files they and SLEPc's build use (see Source10-21). Install the # copies matching this release's PETSc into the farm, unless Fedora ships them. for f in rules_util.mk rules_doc.mk; do [ -e %{petscroot}/lib/petsc/conf/$f ] || cp -p %{_sourcedir}/petsc-%{petsc_ver}-$f %{petscroot}/lib/petsc/conf/$f done mkdir -p %{petscroot}/share/petsc/examples/config cp -p %{_sourcedir}/petsc-%{petsc_ver}-gmakegen.py %{petscroot}/share/petsc/examples/config/gmakegen.py # With Fortran bindings off (see %%prep, SLEPc >= 3.25) the library makefile # must not list the ftn-mod Fortran modules either; gmakegen takes that from # PETSc's PETSC_USE_FORTRAN_BINDINGS, so override it in this copy. if grep -q "PETSC_USE_FORTRAN_BINDINGS' and l\[2\]=='1' and False:" config/packages/petsc.py; then sed -i "s/self.have_fortran = int(self.conf.get('PETSC_USE_FORTRAN_BINDINGS', '0'))/self.have_fortran = 0/" \ %{petscroot}/share/petsc/examples/config/gmakegen.py grep -q "self.have_fortran = 0" %{petscroot}/share/petsc/examples/config/gmakegen.py fi test "$(rpm -q --qf '%%{version}' petsc-openmpi-devel)" = %{petsc_ver} || \ echo "warning: petsc-openmpi-devel is $(rpm -q --qf '%%{version}' petsc-openmpi-devel), support files are from %{petsc_ver}" # An installed PETSc has no PETSC_ARCH; configure records its own arch # directory name as PETSC_ARCH in slepcvariables, so make must not override it, # and ${PETSC_DIR}/${PETSC_ARCH}/... has to resolve back to the farm. unset PETSC_ARCH export PETSC_DIR=%{petscroot} SLEPC_DIR=$PWD ./configure --prefix=%{_builddir}/stage arch=$(sed -n 's/^PETSC_ARCH *= *//p' lib/slepc/conf/slepcvariables | head -1) test -n "$arch" ln -sfn . %{petscroot}/$arch make SLEPC_DIR=$PWD PETSC_DIR=%{petscroot} MAKE_NP=%{_smp_build_ncpus} make SLEPC_DIR=$PWD PETSC_DIR=%{petscroot} install %{_openmpi_unload} %install %{_openmpi_load} # Staged prefix -> Fedora MPI layout: libraries and makefile fragments under # ${MPI_LIB}, headers under ${MPI_INCLUDE}/slepc. st=%{_builddir}/stage mkdir -p %{buildroot}${MPI_LIB} %{buildroot}${MPI_INCLUDE}/slepc cp -a $st/lib/libslepc.so* %{buildroot}${MPI_LIB}/ cp -a $st/include/. %{buildroot}${MPI_INCLUDE}/slepc/ mkdir -p %{buildroot}${MPI_LIB}/slepc %{buildroot}${MPI_LIB}/pkgconfig cp -a $st/lib/slepc/conf %{buildroot}${MPI_LIB}/slepc/ # uninstall.py lists staging paths and is meaningless in an RPM rm -f %{buildroot}${MPI_LIB}/slepc/conf/uninstall.py sed -e "s|^includedir=.*|includedir=${MPI_INCLUDE}/slepc|" \ -e "s|^libdir=.*|libdir=${MPI_LIB}|" \ -e "s|^prefix=.*|prefix=${MPI_HOME}|" \ $st/lib/pkgconfig/slepc.pc > %{buildroot}${MPI_LIB}/pkgconfig/slepc.pc # The installed slepcvariables point at the staging prefix; repoint them. find %{buildroot}${MPI_LIB}/slepc/conf -type f -exec \ sed -i -e "s|$st/include|${MPI_INCLUDE}/slepc|g" -e "s|$st/lib|${MPI_LIB}|g" -e "s|$st|${MPI_HOME}|g" \ -e "s|%{petscroot}/lib/petsc/conf|${MPI_LIB}/petsc/conf|g" {} + ! grep -rl "%{_builddir}" %{buildroot}${MPI_LIB}/slepc %{buildroot}${MPI_LIB}/pkgconfig || exit 1 # slepc4py, against the staged SLEPc and Fedora's Open MPI petsc4py pushd src/binding/slepc4py unset PETSC_ARCH export PETSC_DIR=%{petscroot} SLEPC_DIR=$st export LDFLAGS="%{build_ldflags} -Wl,-rpath,${MPI_LIB}" %{python3} -m pip install --no-deps --no-build-isolation --no-index \ --root %{buildroot} --prefix %{_prefix} -v . popd # Fedora MPI guidelines: MPI-flavoured Python modules live under # %%{python3_sitearch}/openmpi (as petsc4py and mpi4py do). mkdir -p %{buildroot}%{python3_sitearch}/openmpi mv %{buildroot}%{python3_sitearch}/slepc4py %{buildroot}%{python3_sitearch}/slepc4py-*.dist-info \ %{buildroot}%{python3_sitearch}/openmpi/ # slepc4py imports petsc4py's extension for the arch named in slepc4py's own # slepc.cfg, and its own from lib//. Fedora's petsc4py is built with # --with-petsc-arch=%%{_arch} (lib/x86_64/PETSc*.so, petsc.cfg PETSC_ARCH = x86_64) # while slepc4py installs to lib/ with an empty arch, so slepc4py.init() failed # with "'NoneType' object has no attribute 'loader'". Match petsc4py's layout, # and record installed paths rather than the build tree in slepc.cfg. sl=%{buildroot}%{python3_sitearch}/openmpi/slepc4py/lib parch=$(sed -n 's/^PETSC_ARCH *= *//p' %{python3_sitearch}/openmpi/petsc4py/lib/petsc.cfg) test -n "$parch" mkdir -p $sl/$parch mv $sl/SLEPc*.so $sl/$parch/ printf 'SLEPC_DIR = %%s\nPETSC_DIR = %%s\nPETSC_ARCH = %%s\n' ${MPI_HOME} ${MPI_HOME} $parch > $sl/slepc.cfg # slepc4py links against the staged SLEPc and records its directory in the # RUNPATH; point it at the installed location instead. (A `! cmd` inside a loop # does not trip set -e, so the check below uses an explicit exit.) for so in $(find %{buildroot}%{python3_sitearch}/openmpi/slepc4py -name '*.so'); do patchelf --set-rpath ${MPI_LIB} "$so" if readelf -d "$so" | grep -E 'R(UN)?PATH' | grep -q "%{_builddir}"; then exit 1; fi done %{_openmpi_unload} %check %{_openmpi_load} export LD_LIBRARY_PATH=%{buildroot}${MPI_LIB}${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH} export OMPI_MCA_rmaps_base_oversubscribe=1 export PRTE_MCA_rmaps_default_mapping_policy=:oversubscribe # 1-D Dirichlet Laplacian, n = 100: the smallest eigenvalues are known exactly, # 2 - 2 cos(k pi / (n + 1)). Solve in C (2 ranks) and in Python (2 ranks). cat > eps.c <<'C' #include #include int main(int argc, char **argv) { Mat A; EPS eps; PetscInt n = 100, Istart, Iend, i, nconv; PetscScalar kr; PetscCall(SlepcInitialize(&argc, &argv, NULL, NULL)); PetscCall(MatCreate(PETSC_COMM_WORLD, &A)); PetscCall(MatSetSizes(A, PETSC_DECIDE, PETSC_DECIDE, n, n)); PetscCall(MatSetFromOptions(A)); PetscCall(MatGetOwnershipRange(A, &Istart, &Iend)); for (i = Istart; i < Iend; i++) { if (i > 0) PetscCall(MatSetValue(A, i, i - 1, -1.0, INSERT_VALUES)); if (i < n - 1) PetscCall(MatSetValue(A, i, i + 1, -1.0, INSERT_VALUES)); PetscCall(MatSetValue(A, i, i, 2.0, INSERT_VALUES)); } PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); PetscCall(EPSCreate(PETSC_COMM_WORLD, &eps)); PetscCall(EPSSetOperators(eps, A, NULL)); PetscCall(EPSSetProblemType(eps, EPS_HEP)); PetscCall(EPSSetWhichEigenpairs(eps, EPS_SMALLEST_REAL)); PetscCall(EPSSetDimensions(eps, 3, PETSC_DEFAULT, PETSC_DEFAULT)); PetscCall(EPSSetTolerances(eps, 1e-10, 1000)); PetscCall(EPSSolve(eps)); PetscCall(EPSGetConverged(eps, &nconv)); PetscCheck(nconv >= 3, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "only %d converged", (int)nconv); for (i = 0; i < 3; i++) { double exact = 2.0 - 2.0 * cos((i + 1) * M_PI / (n + 1)); PetscCall(EPSGetEigenvalue(eps, i, &kr, NULL)); PetscCheck(fabs(PetscRealPart(kr) - exact) < 1e-8, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "eigenvalue %d: %g != %g", (int)i, (double)PetscRealPart(kr), exact); } PetscCall(PetscPrintf(PETSC_COMM_WORLD, "SLEPc C check OK: %d converged\n", (int)nconv)); PetscCall(EPSDestroy(&eps)); PetscCall(MatDestroy(&A)); PetscCall(SlepcFinalize()); return 0; } C mpicc -o eps eps.c -I%{buildroot}${MPI_INCLUDE}/slepc -I${MPI_INCLUDE}/petsc \ -L%{buildroot}${MPI_LIB} -lslepc -L${MPI_LIB} -lpetsc -lm mpiexec -n 2 ./eps cat > eps.py <<'PY' import math, sys import slepc4py; slepc4py.init(sys.argv) from petsc4py import PETSc from slepc4py import SLEPc n = 100 A = PETSc.Mat().createAIJ([n, n], nnz=3) s, e = A.getOwnershipRange() for i in range(s, e): if i > 0: A[i, i - 1] = -1.0 if i < n - 1: A[i, i + 1] = -1.0 A[i, i] = 2.0 A.assemble() E = SLEPc.EPS().create() E.setOperators(A); E.setProblemType(SLEPc.EPS.ProblemType.HEP) E.setWhichEigenpairs(SLEPc.EPS.Which.SMALLEST_REAL); E.setDimensions(3) E.setTolerances(1e-10, 1000); E.solve() assert E.getConverged() >= 3, E.getConverged() for k in range(3): exact = 2 - 2 * math.cos((k + 1) * math.pi / (n + 1)) assert abs(E.getEigenvalue(k).real - exact) < 1e-8, (k, E.getEigenvalue(k), exact) PETSc.Sys.Print("slepc4py", slepc4py.__version__, "check OK") PY PYTHONPATH=%{buildroot}%{python3_sitearch}/openmpi:${PYTHONPATH} mpiexec -n 2 %{python3} eps.py %{_openmpi_unload} %files openmpi %license LICENSE.md %doc README.md %{_libdir}/openmpi/lib/libslepc.so.* %files openmpi-devel %{_libdir}/openmpi/lib/libslepc.so %{_includedir}/openmpi-%{_arch}/slepc/ %{_libdir}/openmpi/lib/slepc/ %{_libdir}/openmpi/lib/pkgconfig/slepc.pc %files -n python3-slepc-openmpi %license src/binding/slepc4py/LICENSE.rst %{python3_sitearch}/openmpi/slepc4py/ %{python3_sitearch}/openmpi/slepc4py-*.dist-info/ %changelog * Fri Nov 06 2026 Morgan Hough - 3.24.3-2 - Rebuild in mhough/scientific: math and computational-physics packages move out of mhough/neurofedora * Sun Oct 25 2026 Morgan Hough - 3.24.3-1 - New package: SLEPc and slepc4py (Open MPI), version matched to each Fedora release's PETSc. For DOLFINx eigenproblems (DOLFINX_ENABLE_SLEPC) and MFEM. %%check solves a 1-D Laplacian eigenproblem with known eigenvalues in C and in Python on 2 MPI ranks.