Drop GSL dependency from collision_freqs#286
Closed
krystophny wants to merge 1 commit into
Closed
Conversation
GSL is GPLv3 and was linked PUBLIC, propagating the GPL obligation to every MIT-licensed downstream consumer. Replace gsl_sf_gamma with the Fortran 2008 intrinsic gamma() and gsl_sf_gamma_inc_P with an in-tree regularized lower incomplete gamma: DLMF 8.11.4 series for x < a + 1, DLMF 8.9.2 continued fraction otherwise. GSL remains an optional test oracle. When CMake finds it, test_incomplete_gamma_gsl_oracle.x checks the in-tree function against GSL at 1944 points (a in [0.25, 6], x in [1e-8, 100]) with relative tolerance 1e-12. A reference-value test against 32 mpmath values covers systems without GSL. Closes #285
Member
Author
|
@marjohma this is high prio, as it affects licensing of all our codes. As soon as they link to GSL, they must all be distributed under GPL (it is not a catastrophe if we distribute them under MIT, so not an immediate legal problem, but the GPL conditions automatically convert this to GPL per definition if you link GPL software to it, and I prefer to keep MIT). |
This was referenced Jun 9, 2026
This was referenced Jun 9, 2026
Member
Author
|
Superseded by #316, which routes the collision_freqs lower incomplete gamma to the shared fortnum core ( |
Member
Author
krystophny
added a commit
that referenced
this pull request
Jun 15, 2026
## Merge order Merge sequence: #316 -> #317 -> #318. Each PR is based on `main` individually, so each diff is cumulative against `main` and the three share code. Merge them in order. Once a predecessor merges, the next PR's diff shrinks to its own increment. `collision_freqs` linked GPLv3 GSL for one routine: the unnormalized lower incomplete gamma in the Chandrasekhar function. The GPL obligation reached every MIT-licensed downstream consumer (SIMPLE, NEO-2, NEO-RT, MEPHIT, KAMEL, rabe), including SIMPLE's published binary wheels. This routes that single math call to the fortnum numerical core instead of a libneo-internal replacement. Consumers depend on fortnum directly. `lower_incomplete_gamma` returned `gsl_sf_gamma_inc_P(a, x) * gsl_sf_gamma(a)`, the unnormalized lower incomplete gamma. That product is fortnum `gamma_lower(a, x)`, a pure function with the same domain (`error stop` on `a <= 0` or `x < 0`, per fortnum `docs/migration_libneo.md`). The public interface of `lower_incomplete_gamma` is unchanged, so callers compile without edits. Changes: - Replace the two `bind(c)` GSL interfaces and the line-160 product with a single `use fortnum_special, only: gamma_lower`. The now-dead `iso_c_binding` import is removed. - Drop `find_package(GSL REQUIRED)` and the `GSL::gsl` link from `src/collisions/CMakeLists.txt`; link the fortnum Fortran target instead. - Fetch fortnum via `FetchContent` from `git@github.com:lazy-fortran/fortnum.git` at `main`, guarded by `if(NOT TARGET fortnum)` so a repo that also pulls fortnum transitively via libneo does not double-declare the target. This mirrors how NEO-2 PR #90 wires fortnum. This was libneo's only GSL site (no FGSL/SLATEC/AMOS/C-GSL elsewhere), so GSL is fully dropped. Supersedes #286: that PR dropped GSL with a libneo-internal reimplementation; this one routes the same call to the shared fortnum core. ## Verification Environment: gfortran, system HDF5 2.1.1, NetCDF, FFTW, OpenBLAS, fortnum fetched fresh from `lazy-fortran/fortnum` `main` (`8f4c71c`). Configure (fortnum fetched and built): ``` $ cmake -S . -B build -G Ninja -DLIBNEO_BUILD_TESTING=ON ... -- Performing Test FORTNUM_HAVE_HEAP_TRAMPOLINES - Success ... -- Configuring done (7.5s) -- Generating done (0.2s) configure exit: 0 ``` Full build: ``` $ cmake --build build -j$(nproc) [362/362] Linking Fortran shared module _efit_to_boozer.cpython-314-x86_64-linux-gnu.so full build exit: 0 ``` GSL appears on no link line in the generated build: ``` $ grep -ri "gsl" build/build.ninja | grep -iE "link|gsl::" (no output) ``` The migrated routine is exercised by `test_collision_freqs` (`calc_perp_coll_freq` -> `psi_of_x` -> `lower_incomplete_gamma` -> `gamma_lower`), whose expected values were produced by the prior GSL-backed implementation. They pass unchanged: ``` $ ctest -R "test_collision_freqs|test_transport" --output-on-failure Start 19: test_collision_freqs 1/2 Test #19: test_collision_freqs ............. Passed 0.07 sec Start 20: test_transport 2/2 Test #20: test_transport ................... Passed 0.06 sec 100% tests passed, 0 tests failed out of 2 ``` Full suite: 57/69 pass. The 12 failures (chartmap / map2disc / vector conversion / refcoords) come from a missing optional `map2disc` Python module (`ModuleNotFoundError: No module named 'map2disc'`) and the chartmap fixtures that depend on it. They fail identically on unmodified `origin/main` built in the same environment: ``` $ diff <main failed set> <branch failed set> IDENTICAL FAILURE SETS branch count: 12 main count: 12 ``` None of the 12 touch `collision_freqs`, `species`, `transport`, or `fortnum`. Note: fortnum pin updated to current main (92de6e9) after a fortnum history rewrite; old shas no longer resolve.
krystophny
added a commit
that referenced
this pull request
Jun 15, 2026
Stacked on #286. Adds `THIRD_PARTY.md` and a README license section; no code changes. The repository labels itself MIT in `LICENSE`, `fpm.toml`, and the pyproject classifier, but the tree contains and links code under other licenses. This PR documents the actual state: - `src/transport/gen_laguerre_rule.f90` is John Burkardt's LGPL Fortran 90 version of IQPACK (ACM TOMS Algorithm 655), compiled into the `transport` static library. The entry states the LGPL relink obligation for binary distributors; replacement with an MIT implementation is filed as #288. - FFTW3 (GPL-2.0-or-later) is linked into `magfie`: the same MIT/GPL conflict as the GSL link removed in #286. Removal is filed as #287. - `python/scripts/ninja_syntax.py` (Apache-2.0, Google) and `cmake/Modules/findFFTW/` (BSD-3-Clause) are build tooling; neither is in the installed wheel. - The optional GSL test oracle from #286: the test source is MIT (GPL-compatible); the linked test executable is a combined work under GPL terms, but GPL obligations attach on conveyance and the executable is never installed or distributed, so none arise and nothing GSL-related reaches shipped artifacts. - Permissive linked libraries (HDF5, NetCDF, OpenBLAS/LAPACK), the GCC runtimes (GPL with Runtime Library Exception, no copyleft effect), and the separately installed Python dependencies including LGPL f90wrap. ## Verification Before: no third-party license documentation existed and the README had no license section. ``` $ git show drop-gsl-collision-freqs:THIRD_PARTY.md fatal: path 'THIRD_PARTY.md' exists on disk, but not in 'drop-gsl-collision-freqs' $ git grep -i -n "license" drop-gsl-collision-freqs -- README.md (no output) ``` Facts checked against the tree: ``` $ rg -n "GNU LGPL" src/transport/gen_laguerre_rule.f90 | head -1 18:! This code is distributed under the GNU LGPL license. $ rg -n "FFTW::" src/magfie/CMakeLists.txt 30: FFTW::DoubleThreads 31: FFTW::Double $ rg -A2 "tool.scikit-build.wheel.packages" pyproject.toml [tool.scikit-build.wheel.packages] libneo = "python/libneo" efit_to_boozer = "python/efit_to_boozer" ``` After: prose passes the writing checker; docs-only diff, build unaffected.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #285.
collision_freqslinked GPLv3 GSL withPUBLICvisibility for one routine, thelower incomplete gamma in the Chandrasekhar function. The GPL obligation reached
every MIT-licensed downstream consumer (SIMPLE, NEO-2, NEO-RT, MEPHIT, KAMEL,
rabe), including SIMPLE's published binary wheels.
Changes:
gsl_sf_gammareplaced by the Fortran 2008 intrinsicgamma().gsl_sf_gamma_inc_Preplaced by an in-tree regularized lower incompletegamma, written from scratch: DLMF 8.11.4 series for
x < a + 1, DLMF 8.9.2continued fraction (modified Lentz) otherwise.
find_package(GSL REQUIRED)andGSL::gslremoved fromsrc/collisions/CMakeLists.txt;libgsl-devremoved from CI andsetup/debian.sh;gslremoved fromflake.nix.find_package(GSL QUIET)found,test_incomplete_gamma_gsl_oracle.xcompares the in-tree function againstgsl_sf_gamma_inc_P * gsl_sf_gammaat 1944 points (ain [0.25, 6],xin[1e-8, 100]) with relative tolerance 1e-12. Without GSL the test is skipped
and nothing links it.
test_collision_freqs.xgains a reference-value test forlower_incomplete_gammaagainst 32 mpmath values (40-digit precision),relative tolerance 1e-12, so the function is verified on systems without GSL.
The existing
calc_perp_coll_freqexpected values, produced by the GSL-backedimplementation, pass unchanged.
Verification
Before (main): configure without GSL fails.
After (this branch): same configuration succeeds, build and tests pass without
GSL.
After, with GSL present (Homebrew GSL 2.8): oracle agrees with the in-tree
implementation.
GSL appears on no link line except the optional oracle test:
Full suite: 56/70 pass; the 14 failures (chartmap/map2disc, tilted_coil) fail
identically on unmodified
origin/mainin this environment (missing optionalmap2discPython module) and are unrelated to this change.