Repository navigation
STRIDE: banded LU for the Δ′ boundary value problem - #351
Merged
matt-pharr merged 2 commits intoOct 23, 2026
Merged
matt-pharr merged 2 commits into
matt-pharr merged 2 commits into
Conversation
…elta' BVP The Delta' BVP matrix is block-banded except for the 2*msing big solution rows, which the dense solve puts last. With dprime_banded=t each surface keeps its two big solution rows in its block, so the matrix is banded with kl = ku = 3*mpert-1 and is solved with ZGBTRF/ZGBTRS (residual check from the sparse entries). Default f keeps the dense solve unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…prime_banded option The banded LU gives bit-identical Delta' to the dense one, so it replaces it: the dprime_banded namelist key, the dense path and the stride.in line go. Each singular surface's two big solution rows sit at the end of its block of 2*m2 rows, the matrix is factored and solved with ZGBTRF/ZGBCON/ZGBTRS (kl = ku = 3*mpert-1), and the residual check uses the sparse entries. The printed condition number now uses the norm of the matrix itself, as ZGBCON expects (the dense path took the norm after factorization). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
StuartBenjamin
marked this pull request as ready for review
October 23, 2026 03:56
matt-pharr
approved these changes
Oct 23, 2026
matt-pharr
left a comment
Collaborator
There was a problem hiding this comment.
Ran this myself and can confirm the positive claims of this PR. We mostly have been moving away from banded matrices, but that only applies to the regions where banded matrices are an approximation; they are exact here and can save quite a bit of runtime for higher
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.
STRIDE solves the Δ′ boundary value problem as a dense matrix of size nMat = (2 + 4 msing) mpert. It factors it with ZGETRF and keeps two dense copies (M and MInv). Time grows as nMat³ and memory as nMat², so at high n with many rational surfaces this one step dominates STRIDE. On the DIII-D resistive example at n = 8 it takes 632 s of the 750 s run and most of the 5.1 GiB peak. The matrix is block-banded, though: each surface's block couples only to its neighbours.
This PR solves it as a banded matrix. Each singular surface's rows now end with that surface's two big-solution rows, instead of all big-solution rows sitting at the end of the matrix. That makes the matrix banded with kl = ku = 3 mpert − 1. It is factored and solved with ZGBTRF / ZGBCON / ZGBTRS, and the residual check uses the sparse entries, so no dense matrix is formed. The change is in
stride/ode.Fonly. The printed condition number now uses the norm of the matrix itself, as ZGBCON expects (develop took the norm after factorization).Δ′ is identical to the bit with develop in every run below (reference LAPACK). GPEC examples, same machine, 2 threads, develop → this PR:
We also ran 28 reconstructed DIII-D equilibria at n = 1–4 (112 runs) on our GPEC branch with and without this change. Δ′ was bit-identical in all 112. At n = 4 the Δ′ step went from 215 s median (947 s max) to 2.4 s (5.8 s), and the largest STRIDE peak memory went from 7.3 to 1.8 GiB. The attached plot shows both sets against nMat. The zip holds the script that runs the examples (
run_demo.sh DEVELOP_DIR PR_DIR OUT), the plotting script and the two tables.stride_banded_dprime_demo.zip
Review check, on this PR merged onto current develop (with #325's axis-interval split, #328 and the EQUIL fixes), against current develop, DIII-D resistive example:
delta_prime.outis byte-identical at n = 1, 2 and 4 on both Linux (glibc 2.39, reference LAPACK, Ubuntu 24.04 container) and macOS (Apple Accelerate).On the branch's original base, which predates #325, n = 4 was not bit-identical (median 7e-5 relative on the Δ′ diagonal, up to 5% on the innermost surface), because there all 38 driven solves failed the big-solution residual check and the result was dominated by roundoff. With #325 only 2 fail, at about 1e-6, and the banded and dense solves agree to the bit.
🤖 Generated with Claude Code