# FEBio links 12 module .so into a private libdir; debug_package nil keeps the # first packaging simple (the build is Release with force-include GCC15 fixes). %global debug_package %{nil} %global febiolibdir %{_libdir}/febio Name: febio Version: 4.12 Release: 5%{?dist} Summary: Finite element solver for biomechanics and biophysics License: MIT URL: https://febio.org/ Source0: https://github.com/febiosoftware/FEBio/archive/refs/tags/v%{version}.tar.gz#/FEBio-%{version}.tar.gz # Our own %%check model (upstream's source ships none; its TestSuite has no licence). Source1: febio-check-uniaxial.feb # Upstream b91fda7 (in v4.13): Logfile::printbox passed 1024 as the size to every # snprintf into a buffer it had already partly filled, so _FORTIFY_SOURCE aborted # ("buffer overflow detected") the first time a solver printed a box -- i.e. # every static/quasi-static model died in FENewtonSolver::Init. Patch0: febio-logfile-printbox-fortify.patch # Without MKL the default solver is Skyline, which is symmetric-only, so every # biphasic/fluid/FSI/solute/multiphasic (and nonsymmetric solid) model failed at # the first solve: 168 of the 548 TestSuite problems. Default to SuperLU_MT # (Fedora's SuperLUMT) when it is built in. Patch1: febio-default-solver-superlu-mt.patch BuildRequires: gcc-c++ BuildRequires: gcc BuildRequires: cmake BuildRequires: ninja-build BuildRequires: chrpath BuildRequires: libomp-devel # Optional-feature libraries, all from Fedora (MKL is proprietary and omitted -> # FEBio falls back to its built-in Skyline direct solver): BuildRequires: hypre-devel BuildRequires: levmar-devel BuildRequires: fftw-devel BuildRequires: zlib-ng-compat-devel # MMG adaptive mesh refinement: the component headers/libs live in the per-engine # subpackages (mmg-devel alone ships only the umbrella libmmg.h, which #includes # them). FEBio uses the mmg3d engine; pull in the components it needs. BuildRequires: mmg-devel BuildRequires: mmg3d-devel BuildRequires: mmgs-devel # Sparse LU for nonsymmetric systems (Patch1 makes it the default solver). BuildRequires: SuperLUMT-devel %description FEBio (Finite Elements for Biomechanics) is a nonlinear finite element solver developed at the University of Utah (SCI Institute / Musculoskeletal Research Laboratories) for problems in computational biomechanics and biophysics: large- deformation solid mechanics, biphasic/multiphasic (poroelastic) tissue, fluid and FSI, reactive transport, and parameter optimization. This package provides the `febio4` command-line solver with the HYPRE BoomerAMG iterative solver, MMG adaptive mesh refinement, FFTW, zlib plot compression, and levmar parameter optimization. It is built without Intel MKL (proprietary), so the Pardiso/iterative MKL solvers are unavailable and FEBio uses its built-in Skyline direct solver by default; the HYPRE iterative solver remains available. %prep %autosetup -p1 -n FEBio-%{version} %build # -D__OPENMP: Fedora's SuperLUMT is the OpenMP build; its headers pick their lock # type from this macro. # GCC 15 no longer transitively includes these; FEBio uses strcpy/uint*/etc. # without the explicit headers -> force-include. MKL off (proprietary) -> Skyline. # Static stdlibs off (Fedora policy). Optional libs (incl. MMG, via the mmg3d/mmgs # component packages) wired to their Fedora system paths. # SuperLUMT 4.0.2 (F45+) ships one libsuperlu_mt.so; 4.0.1 split it per precision. slu=%{_libdir}/libsuperlu_mt.so; [ -e "$slu" ] || slu=%{_libdir}/libsuperlumt_d.so cmake -S . -B cbuild -GNinja \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_CXX_FLAGS="%{optflags} -include cstring -include cstdint -include cstdlib -D__OPENMP" \ -DUSE_MKL=OFF \ -DUSE_STATIC_STDLIBS=OFF \ -DUSE_ZLIB=ON -DZLIB_LIBRARY_RELEASE=%{_libdir}/libz.so -DZLIB_INCLUDE_DIR=%{_includedir} \ -DUSE_FFTW=ON -DFFTW_LIB=%{_libdir}/libfftw3.so -DFFTW_INC=%{_includedir} \ -DUSE_HYPRE=ON -DHYPRE_LIB=%{_libdir}/libHYPRE.so -DHYPRE_INC=%{_includedir}/hypre \ -DUSE_LEVMAR=ON -DLEVMAR_LIB=%{_libdir}/liblevmar.so -DLEVMAR_INC=%{_includedir} \ -DUSE_MMG=ON -DMMG_LIB=%{_libdir}/libmmg3d.so -DMMGS_LIB=%{_libdir}/libmmgs.so -DMMG_INC=%{_includedir} \ -DUSE_SUPERLU_MT=ON -DSUPERLU_MT_LIB="$slu" -DSUPERLU_MT_INC=%{_includedir}/SuperLUMT cmake --build cbuild %{?_smp_mflags} %install # FEBio has no install rules. Co-locate febio4 + its module libs in a private dir # with $ORIGIN RPATH, and expose febio4 on PATH via a symlink. install -d %{buildroot}%{febiolibdir} install -m 0755 cbuild/bin/febio4 %{buildroot}%{febiolibdir}/febio4 install -m 0755 cbuild/lib/*.so %{buildroot}%{febiolibdir}/ # Drop the build-dir RPATH leak; point everything at its own directory. for f in %{buildroot}%{febiolibdir}/febio4 %{buildroot}%{febiolibdir}/*.so; do chrpath -r '$ORIGIN' "$f" done install -d %{buildroot}%{_bindir} ln -s ../%{_lib}/febio/febio4 %{buildroot}%{_bindir}/febio4 # febio4 reads febio.xml from its own directory. Ship one that loads every plugin # package's .so from %%{_libdir}/febio/plugins (febio-chem, febio-heat, ...). It sets # no default_linear_solver, so Patch1's SuperLU_MT default stands. The folder must # exist: import_folder throws on a missing directory. install -d %{buildroot}%{febiolibdir}/plugins %{buildroot}%{_sysconfdir}/febio cat > %{buildroot}%{_sysconfdir}/febio/febio.xml <<'EOF' %{febiolibdir}/plugins EOF ln -s %{_sysconfdir}/febio/febio.xml %{buildroot}%{febiolibdir}/febio.xml # --- febio-devel SDK --------------------------------------------------------- # Install the module headers (namespaced under %%{_includedir}/febio, included as # etc.) plus a CMake config exposing one imported target per module, # so FEBio Studio and FEBio plugins can find_package(FEBio). for mod in FECore NumCore FEBioLib FEBioMech FEBioMix FEBioFluid FEBioRVE \ FEBioPlot FEBioXML FEAMR FEBioOpt FEImgLib; do find "$mod" -name '*.h' -o -name '*.hpp' | while read -r h; do install -D -m 0644 "$h" "%{buildroot}%{_includedir}/febio/$h" done done install -d %{buildroot}%{_libdir}/cmake/FEBio cat > %{buildroot}%{_libdir}/cmake/FEBio/FEBioConfig.cmake <<'EOF' # Fedora febio-devel: FEBio SDK config exposing one imported target per module. # (Replaces upstream's in-tree/build-dir config with explicit installed paths.) set(FEBIO_INCLUDE_DIR "%{_includedir}/febio") set(_febio_map FECore:fecore FEBioMech:febiomech FEBioMix:febiomix FEBioFluid:febiofluid FEBioRVE:febiorve FEBioPlot:febioplot FEBioXML:febioxml FEBioLib:febiolib FEAMR:feamr FEBioOpt:febioopt FEImgLib:feimglib NumCore:numcore) foreach(pair IN LISTS _febio_map) string(REPLACE ":" ";" _parts ${pair}) list(GET _parts 0 _tgt) list(GET _parts 1 _lib) if(NOT TARGET FEBio::${_tgt}) add_library(FEBio::${_tgt} SHARED IMPORTED) set_target_properties(FEBio::${_tgt} PROPERTIES IMPORTED_LOCATION "%{febiolibdir}/lib${_lib}.so" INTERFACE_INCLUDE_DIRECTORIES "${FEBIO_INCLUDE_DIR}") endif() endforeach() set(FEBio_FOUND TRUE) EOF %package devel Summary: FEBio SDK: headers and CMake config for FEBio plugins and FEBio Studio Requires: %{name}%{?_isa} = %{version}-%{release} %description devel Development files (module headers and a CMake package configuration exposing the FEBio:: imported targets) for building FEBio plugins or applications that link the FEBio libraries, such as FEBio Studio. %check # Solve a one-element uniaxial stretch with the just-built solver and compare to # the small-strain answer: corner contracts by v*eps = 3e-5, axial 1e-4. This is # what would have caught the printbox abort above. # The second run assembles it as non-symmetric, which Skyline could not solve. # -noconfig: the build tree has a CMake-written febio.xml forcing skyline; the # installed package has none, so this is what users run. mkdir -p check cp -p %{SOURCE1} check/sym.feb sed 's|symmetric<|non-symmetric<|' %{SOURCE1} > check/nonsym.feb grep -q 'non-symmetric' check/nonsym.feb for m in sym nonsym; do rm -f check/corner.txt (cd check && OMP_NUM_THREADS=1 ../cbuild/bin/febio4 -noconfig -i $m.feb -silent) grep -q 'N O R M A L T E R M I N A T I O N' check/$m.log tail -n 1 check/corner.txt | awk -v m=$m ' function a(x) { return x < 0 ? -x : x } { print m, "corner u =", $2, $3, $4 exit !(a($2 + 3e-5) < 3e-7 && a($3 + 3e-5) < 3e-7 && a($4 - 1e-4) < 1e-9) }' done grep -q 'superlu_mt' check/nonsym.log # The shipped config, pointed at an empty plugin folder, must load and keep SuperLU_MT. mkdir -p check/plugins sed 's|%{febiolibdir}/plugins|'"$PWD"'/check/plugins|' %{buildroot}%{_sysconfdir}/febio/febio.xml > check/febio.xml (cd check && OMP_NUM_THREADS=1 ../cbuild/bin/febio4 -config febio.xml -i sym.feb -silent) grep -q 'superlu_mt' check/sym.log %files %license LICENSE %doc README.md %dir %{febiolibdir} %{febiolibdir}/febio4 %{febiolibdir}/*.so %dir %{febiolibdir}/plugins %{febiolibdir}/febio.xml %dir %{_sysconfdir}/febio %config(noreplace) %{_sysconfdir}/febio/febio.xml %{_bindir}/febio4 %files devel %{_includedir}/febio/ %{_libdir}/cmake/FEBio/ %changelog * Fri Oct 09 2026 Morgan Hough - 4.12-5 - Ship /etc/febio/febio.xml (linked from %%{_libdir}/febio) importing every plugin in %%{_libdir}/febio/plugins, for the febio-chem/heat/erd/warp packages. * Fri Oct 09 2026 Morgan Hough - 4.12-4 - Build the SuperLU_MT solver (Fedora SuperLUMT) and make it the default: Skyline is symmetric-only, so biphasic, fluid, FSI, solute and multiphasic models all failed at the first solve. - %%check also solves the model with a non-symmetric stiffness matrix. * Fri Oct 09 2026 Morgan Hough - 4.12-3 - Backport upstream b91fda7: febio4 aborted with "buffer overflow detected" (_FORTIFY_SOURCE, Logfile::printbox) on every static model. - Add %%check: solve a one-element uniaxial model and check it against the small-strain answer. * Sun Jun 21 2026 Morgan Hough - 4.12-2 - Add febio-devel SDK subpackage (module headers + FEBioConfig.cmake with the FEBio:: imported targets), required to build FEBio Studio and plugins. * Sun Jun 21 2026 Morgan Hough - 4.12-1 - Initial package: FEBio 4.12 finite element solver (febio4). Built with system HYPRE/levmar/FFTW/zlib and MMG adaptive mesh refinement (via the mmg3d-devel + mmgs-devel component packages); MKL omitted (proprietary -> Skyline solver). GCC15 force-include fixes; module libs in a private %%{_libdir}/febio with $ORIGIN RPATH. FEBio Studio (GUI) not included.