InnerLayer (GGJ) - NEW - rotated-ray collocation backend (:ray), robust to |Q| ~ 500#323
InnerLayer (GGJ) - NEW - rotated-ray collocation backend (:ray), robust to |Q| ~ 500#323matt-pharr wants to merge 1 commit into
Conversation
…location method implementation of GGJ that avoids Delta poles on the imaginary Q axis and can solve for Delta_even adn Delta_odd up to very high (at least ~500) |Q|
|
@logan-nc @d-burg this is something I have been working on with claude for a few weeks. It has a number of advantages over the galerkin GGJ solver. It uses collocation which is also a finite element method, but I learned that the reason that the galerkin solver sometimes freaks out is because there are poles to the GGJ solutions in Q space, and when you get near those poles the solutions become super oscillatory on the real axis. However, since we are solving this in a complex domain, you can show that the GGJ solutions should be entire in the complex plane, so the mercier terms in the large |X| limit are the same polynomial + coefficient even off of the real-axis (which is where the physically-relevant part of the solution lies). So you can get a much cleaner/quicker exponential decay of the non-limiting terms if you integrate on a ray that is rotated off of the real axis. This also gives way to an entirely different numerical stability check, which is to re-integrate for multiple rotation angles and see that you get the same Delta_even and Delta_odd. Overall this method is far superior to the galerkin one in all of my testing so far, and can safely go up to Q ~ 500i with a maximum error in the final Delta of ~1e-4 which is pretty good for this problem. Error stays ~1e-7 for more reasonable Q. This enables scanning to lower resistivities (Q ~ 1/eta^1/3) and higher rotation rates (or to absurd growth rates). It also makes the solve more robust for lower |Q|. I will do some more testing on this branch before I merge but I am opening it for review now. |
Summary
Adds a third interchangeable solver to the GGJ inner-layer model —
GGJModel{:ray}— and makes it the default. It returns the same parity-projected matching data(Δ₁, Δ₂)in the same deltac convention as:galerkinand:shooting, but remains accurate far into the regime where both existing backends fail: validated to Q = 500i, the territory resistivity scans (|Q| ∝ η^(−1/3)) and rotation physics actually visit.Method (one paragraph)
The layer equations are continued analytically onto the complex ray x = e^{iθ}s with θ = arg(Q)/4, which makes the parabolic-cylinder WKB exponent exactly real (no oscillation along the contour) and moves the coefficient pseudo-resonance x² ≈ −Q²(G+KF) — which sits on the real axis for imaginary Q — off the path. Δ is an analytic invariant of the contour angle within the Stokes sector, which doubles as a built-in error diagnostic (outward θ-consistency check). On [0, s_m] a global Chebyshev spectral-element collocation BVP is solved in plain variables with parity conditions at the origin and (Δ, c₁, c₂) as bordered unknowns of one sparse LU per parity (rank-3 Woodbury correction for the second parity). The far-field condition reuses the existing, validated inps Wasow kernel (
InnerAsymptotics.jl) — evaluated at complex x via new methods inRayAsymptotics.jl, construction untouched — applied at the series radius S and transported inward by an L-stable 2-stage Radau IIA march in the quotient modulo the decaying exponential pair. The damped-zone march arithmetic runs inComplex{Double64}: at large S the near-parallel power-pair geometry amplifies the structured backward error of the ill-conditioned implicit solves into Δ-mixing ~1e-4 at |Q| = 500 in Float64 (a floor generic to any inps-based method handed to double-precision linear algebra at large S).Validation
Developed and validated in a standalone package before porting; highlights:
:galerkincross-check at moderate Q: 1e-5–1e-9.test/runtests_innerlayer.jlgains a:raytestset (agreement with:galerkinat the GW2020 Eq. 55 paper point; q4 pins at 500i; θ-invariance). 19/19 pass.Default backend change
GGJModel()now defaults to:ray. Blast radius checked: there are no bareGGJModel()call sites in the repo — all 17 benchmark uses and the regression harness passsolver=:galerkinexplicitly. The backends take different numerical-knob keywords, so any stale galerkin-knob call fails loudly rather than returning a silently wrong Δ.Dependencies
Random(stdlib, zero footprint) promoted from test-extras to[deps]— seeds the decaying-pair extraction (provably Δ-neutral; kept fixed for bit-reproducibility).DoubleFloatswas already a project dependency; only theusingline is new.Files
src/InnerLayer/GGJ/RayAsymptotics.jl(new) — complex-x evaluation methods for the existing inps kernel.src/InnerLayer/GGJ/Ray.jl(new) — ODE system, WKB-graded mesh, decaying-pair extraction, Radau march, bordered collocation solve, refinement,delta_convergenceerror-bar battery, profile reconstruction, and thesolve_inner(::GGJModel{:ray}, …)interface method.GGJ.jl/InnerLayer.jl— backend registration, exports, docs.A complete replication-grade methods write-up (strong form, cell-by-cell matrix assembly, march schedule derivation, finite-precision floor analysis) exists and will accompany the paper in preparation.
🤖 Generated with Claude Code