[WIP] ABLASTR: reuse the IGF Green's function - #7178
Open
ax3l wants to merge 1 commit into
Open
Conversation
This was referenced Aug 19, 2026
ax3l
force-pushed
the
topic-igf-greens-cache
branch
2 times, most recently
from
August 27, 2026 22:39
7b6177e to
cd27215
Compare
computePhiIGF rebuilt and re-transformed its Green's function on every call, which dominates the solver: on CPU it costs 3 to 5 times the solve itself and about three quarters of the runtime. The Green's function depends on the grid only through the cell size, so remember which grid the one in the solver was built for and skip the rebuild while that has not changed. Keep further ones in a small least-recently-used store, moved in and out with std::swap so nothing is copied, for callers whose grid returns to a size it has had before. The integrated Green's function is homogeneous of degree two, so an entry also serves any scale reached by an exact power of two, applied to phi afterwards. Controlled by ablastr.igf_cache_max_entries, igf_cache_max_bytes and igf_cache_verbose, with igf_rebuild_always to restore the old behavior. This also puts the two-d mode and the FFT process count into the key identifying the solver, which were missing before. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
ax3l
force-pushed
the
topic-igf-greens-cache
branch
from
August 27, 2026 22:55
cd27215 to
f9d6ffe
Compare
ax3l
added a commit
to AMReX-Codes/amrex
that referenced
this pull request
Aug 28, 2026
`OpenBCSolver` rebuilds its spectral Green's function whenever `setGreensFunction()` is called, and there is no way to hand it one that was built earlier. Add `greensFunctionFFT()` accessors so a caller can keep its own set and move them into and out of the solver with `std::swap` rather than recomputing. `solve()` only reads the spectral Green's function, and `prepare_openbc()` concerns the R2C plans rather than the Green's function values, so one moved in this way needs no further preparation. The one caveat, documented at the accessor: in 2D, `m_G_fft` is an alias of the Green's function R2C's spectral data, which a later `setGreensFunction()` writes into. Callers may write through the reference there, but must not swap or otherwise re-seat it. Additive only, so nothing changes for existing users. Exercised downstream in BLAST-WarpX/warpx#7178 & BLAST-ImpactX/impactx#1621, where reusing Green's functions this way reproduces rebuilding them bit for bit, and where it takes an accelerating beam simulation from 100 Green's function builds to 10. - [x] 🤖 Generated with [Claude Code](https://claude.com/claude-code) - [x] tested with ABLASTR/WarpX and ImpactX - [x] manually self-reviewed --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.
computePhiIGFrebuilt and re-transformed its Green's function on every call. That dominates the solver: measured per call on a 128^3 grid, building costs 390 ms against an 84 ms solve on CPU, roughly three quarters of the runtime, and it does not shrink with particle count. The Green's function depends on the grid only through the cell size, so this remembers which grid the one in the solver was built for and skips the rebuild while that has not changed, keeping further ones in a small least-recently-used store for callers whose grid comes back to a size it has had before.Green's functions move in and out of the store with
std::swap, so nothing is copied. The integrated Green's function is homogeneous of degree two, verified againstSumOfIntegratedPotential3Dto 2.8e-13, so an entry also serves any scale reached by an exact power of two, applied tophiafterwards. Two-d mode copies rather than swaps, since therem_G_fftaliases the Green's function R2C's spectral data. Controls areablastr.igf_cache_max_entries,igf_cache_max_bytes,igf_cache_toleranceandigf_cache_verbose, withigf_rebuild_alwaysrestoring the old behavior, all documented in the parameter list.Who benefits depends on how steady the cell size is, and the relativistic electrostatic solver is not steady by default. It derives the longitudinal stretch from a velocity, and reconstructing it costs about$\epsilon\gamma^2$ , which is a few ulp at $\gamma$ of a thousand but 1e-5 at 125 GeV; the velocity is also re-measured from the particles every step and carries sampling noise of its own. $64\epsilon$ , so nothing changes silently. Depends on AMReX-Codes/amrex#5627 for the accessor, and is exercised from ImpactX in BLAST-ImpactX/impactx#1621.
igf_cache_toleranceexists for exactly that case and defaults toMeasurements
beam_beam_collisionon the IGF solver, which needswarpx.poisson_solver=fftand open field boundaries, 5 steps, 4 threads. At the default tolerance it reuses nothing, because of the two effects above. Raising it trades a bounded error for reuse:igf_cache_toleranceigf_rebuild_alwaysThe comparison is on
ColliderRelevant_beam1_beam2, single threaded so it means something;ParticleNumberis identical at both settings. Build counts vary by about two between runs, since QED secondary production is thread-order dependent.Tested through ImpactX, where the grid is chosen to repeat and the default tolerance suffices. Runs are compared against
igf_rebuild_always=1and required to agree exactly on all beam moments: with the store disabled and enabled, with a mesh fitted to the beam and with a quantized one, and on an accelerating lattice where the reference energy triples. On a constant-focusing channel with a static grid that took Green's function builds from 50 to 1 and runtime from 1.53 s to 0.37 s, and on an accelerating beam from 100 to 10 and 0.95 s to 0.41 s, byte-identically.Two things for review. The key must never miss a change in the Green's function, since a stale one is a wrong answer rather than a slow one, so it is derived inside
computePhiIGFfrom the cell size and the solver identity rather than accepted from callers. Andtwod_modeand the FFT process count are now part of the identity that decides whether the solver is rebuilt, which they were not before.🤖 Generated with Claude Code