Repository navigation
Exact Hermite free-streaming integrating factor for LawsonSolver (stacked on #82) - #83
Open
rogeriojorge wants to merge 8 commits into
Open
rogeriojorge wants to merge 8 commits into
rogeriojorge wants to merge 8 commits into
Conversation
…rcollision damping; simulation(integrating_factor=)
…eigh), optional Strang-composed diagonal rate; simulation(integrating_factor='streaming'|'streaming+diagonal')
…ts from the state)
rogeriojorge
added a commit
that referenced
this pull request
Oct 20, 2026
… into the integration lineage
…s a lower-level option, measured harmful at large h|G| r); README section
rogeriojorge
marked this pull request as ready for review
October 20, 2026 13:30
… (Lawson 1967, Hochbruck-Ostermann 2010)
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.
Exact Hermite free-streaming integrating factor for
LawsonSolver(stacked on #82)Stacking. Targets
mainso CI runs, but the branch contains the #82 commit; review only the last two commits (git log origin/agent/lawson-main..) =spectrax/_lawson_streaming.py, a few lines in_lawson.py/_simulation.py, README section, tests. Merge #82 first (then this PR reduces to the streaming files). The older integration-lineage version is merged intointegration/dark-baselineonly.What it is
LawsonSolver(solver, factor_fn=...)generalizes the diagonal rate of #82 to an arbitrary smooth integrating factorPhi(tau),Phi(0) = I.hermite_streaming_factorbuilds the factor for the free streaming of the Hermite-Fourier system, andsimulation(..., integrating_factor="streaming")uses it (defaultFalsestays bitwise unchanged;Trueis #82).Derivation (details in the
spectrax/_lawson_streaming.pydocstring)G = -i k (a T + u I)(k = 2 pi index / L,awidth,udrift,Tthe symmetric tridiagonalT[j, j+1] = sqrt((j+1)/2)). The three axes act on different tensor factors, so they commute andexp(tau G)is a product.T = V diag(lam) V^T(one realeigh;lamthe Gauss-Hermite nodes over sqrt 2,Vthe nodal transform) givesexp(tau G_ax) = exp(-i tau k u) V diag(exp(-i tau k a lam)) V^T: unitary, exact for any step,Vshared by everyk, species, width and drift (only the phases depend on them). Cost: twoNn x Nnproducts per Hermite axis per stage.w = Phi^{-1} ygives the exact identityw' = Phi^{-1}(f(Phi w) - Phi' w), so the wrapped RK tableau applies towfor any smoothPhi(the choice ofPhionly changes what is left inw'). Order statement (corrected): per Lawson (1967, SIAM J. Numer. Anal. 4, 372-380) the order of the underlying RK method is retained for a fixed linear part as h -> 0 (here the rate is the step-start rate, Lawson's re-evaluated-A form). No stiff-order claim is made when r h >> 1: per Hochbruck and Ostermann (2010, Acta Numerica 19, 209-286; Thm 2.17, Ex. 2.32, Table 2.2) the stiff order of Lawson methods drops (to 1 for Lawson-Runge) when ||hA|| is large. Empirical support is measured agreement with plain Dopri8 records (5e-10 in H05 c=64).Phi = B):w' = B^{-1} f(B w) - G w, i.e.N = f - G yis what the RK method sees.r(does not commute withG): Strang productPhi = A(h/2) B(h) A(h/2),A = exp(-r .); withz = A w,u = B z,y = A u:w' = A^{-1} B^{-1}[A^{-1} f(y) + (r/2) u] - A^{-1} G z + (r/2) w, oneBand oneB^{-1}per stage; reduces to Lawson (integrating-factor) wrapper for the diagonal hypercollision damping (opt-in) #82 forG = 0. The symmetric BCH expansion shows the factor equalsexp(tau (G - r) + O(tau^3 [G,[G,r]])), so what remains explicit isO((h |G|)^2 |r|). A stiff diagonal rate is therefore removed completely only whileh |G| = h k a sqrt(2 Nn)is small. A joint exponential ofG - Rperkwould need a non-Hermitianeigper step (rate changes every step;jnp.linalg.eigis CPU-only): not built.hermite_streaming_factor(basis_fn=...)takes(a, u)from the state at the step start (used in the integration lineage for the pump frame); the basis change over the step stays inN.y(t) = Phi(t - t0) w(t); oscillations are removed fromw, which is smooth).Measured
All on a laptop CPU (2 threads), after warm-up,
simulationdefault two-stream,t_max = 20, 2 species,nu = 3:Nx,NnCk/Fkvs plainCost per Runge-Kutta step: plain 3.5 ms,
integrating_factor=True4.6 ms,"streaming"about 12 ms (3.5x plain) atNx 64, Nn 128. The streaming factor wins when the explicit step is stability-limited by streaming (h k a sqrt(2 Nn) < ~3.7) and the dynamics is smooth; it loses on small or accuracy-limited problems.Decisive stiff-closure benchmark (Dark-SPECTRAX, gates declared in a committed script before any run; numbers in its
docs/results.md): H05v_q/v_te = 0.1,Nx 64, Nn 128, field-scaled closure (#66) with streaming plus the closure rate inside the factor, against the same-session closure-only Lawson (#82) and the plain record:c = 64tot = 500: 9606 steps (closure-only Lawson) vs 9652 (streaming): streaming was not what limited the step; wall 52 s vs 130 s (2.5x slower; per-step cost 2.7x). Accuracy vs the plain CPU record: dK_e 3.4e-10, W_ext 2.7e-11; ledger 3.7e-12.c = 4: identical tot = 400; then the run ends att = 456.5on the step budget (201 927 steps in one chunk, closure-only: 5 444 for the same chunk): the Strang leftoverO((h|G|)^2 |r|)is stiff inw.nu = 100): closure-only 25 845 steps; streaming plus rate hits the 400 000-step budget.c = 4; S2 (accuracy) passed. Verdict as declared: streaming does not earn its place in this regime. Consequentlysimulationexposes"streaming"only (the rate-inside-the-factor combination remains available throughhermite_streaming_factor(rate_fn=...)and is documented as harmful at largeh|G|and|r|).Literature (read / not read)
b dt < C dv, withbthe advection speed; exact exponential for Fourier/semi-Lagrangian streaming). This is the precedent for exponentiating streaming; their numerical tests are Vlasov-Poisson and drift-kinetic, not Hermite.Tests (
tests/test_lawson_streaming.py, 7, all pass; full suite 25 passed locally)Gequals the streaming part of the real RHS (Fk = 0,nu = 0): 3-D, drifts, unequal widths,Nm, Np > 1;Bunitary, group property, equalsscipy.linalg.expm,V diag(lam) V^T = T;c_n = (-i x)^n / sqrt(n!) exp(-x^2/2)to 1e-12 in one step at 13x the Dopri8 imaginary-axis step (plain solver gives |c| > 50 at that step);simulationagrees with plain at the solver tolerance,k = 0density preserved to round-off, default bitwise unchanged;basis_fnoverrides the argument basis.Limitations
knot implemented (non-Hermitianeig).Merge recommendation
Do not merge unless you want an opt-in exact-streaming integrator for large
Nx x Nnsmooth runs. It is correct, tested, and bitwise off, but the measured benefit is narrow and it does not help the stiff-closure regime that motivated it. #82 is the one with demonstrated value. If merged, merge after #82.