Restore the order-39 Ahrens-Beylkin rule: it is 572 points, not 552 - #113
Open
susilehtola wants to merge 2 commits into
Open
Restore the order-39 Ahrens-Beylkin rule: it is 572 points, not 552#113susilehtola wants to merge 2 commits into
susilehtola wants to merge 2 commits into
Conversation
The generate() dispatch for all four S2 quadrature families was a chain
of if/else-if with no terminal else. Requesting a point count that is not
tabulated left the value-initialised containers untouched, so the caller
received a grid whose weights were all zero and which therefore
integrates every function to zero. No exception, assertion or warning was
raised, and the README claims the opposite ("will fail if the grid order
is incompatible").
Add a terminal else to each family that reports the requested size and
points at npts_by_algebraic_order().
Two data problems surfaced once the check was in place:
* lebedev_laikov_5294.hpp is shipped and included by the grids header but
had no dispatch branch and no entry in the algebraic order tables, so
the 5294-point Lebedev-Laikov grid was unreachable. Wire it up (order
125, between 4802/119 and 5810/131).
* The tabulated 552-point Ahrens-Beylkin grid is not a valid order-39
rule. Its weights sum to 0.9632 * 4pi, and after renormalisation it
still integrates degree-8 monomials to only 5.7e-02 relative accuracy,
while every neighbouring size is exact to machine precision. Withdraw
it from the dispatch and the order tables until the table can be
regenerated from the original Ahrens-Beylkin data; next_algebraic_order
now rounds order 39 up to 41.
The new test checks both directions: unsupported sizes must throw, and
every size advertised by the order tables must be dispatched and must
integrate even monomials exactly up to its claimed algebraic order. That
second check is what found the Ahrens-Beylkin defect; a sum-of-weights
check alone would not have, since the grid is exact at low order once
renormalised.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FDTFYJMQ76iujDFNHzZyXF
The 552-point table is not a valid order-39 rule -- its weights sum to
0.9632 * 4pi -- and the preceding commit withdrew it. The cause is now
known: it is missing its 20-point (dodecahedral vertex) orbit.
The 552 points decompose into ten icosahedral orbits, one of 12 and nine
of 60. The exactness conditions are linear in the weights, so the best
possible weights for a fixed point set follow from one least-squares
solve, and with AB-612 as a control:
AB-612 (known good) 8.3e-14, all positive
AB-552 2.4e-02, five negative weights
No weighting of those points works. Dividing the weight deficit by the
candidate orbit sizes points at exactly one plausible answer:
12-point orbit -> 0.038491454 (above the existing weight range)
20-point orbit -> 0.023094872 <-- at the top of it
30-point orbit -> 0.015396582 (below)
60-point orbit -> 0.007698291 (far below)
Adding the dodecahedral orbit gives 572 = 12 + 20 + 9*60, and the same
least-squares then reproduces the file's own ten weights exactly while
assigning the new orbit precisely deficit/20 -- 3.674e-13 with all
weights positive. That is not a fit finding a coincidence; it is the
missing orbit.
Refined against the full order-39 condition set the reconstruction
converges 1.529e-15 -> 8.862e-28 -> 7.905e-52, worst error 3.338e-51.
Emitted at double precision it integrates as well as its neighbours:
AB-492 shipped (control) order 37 8.331e-16
AB-572 new order 39 7.605e-16
AB-612 shipped (control) order 41 9.003e-16
npts_by_algebraic_order(39) now returns 572, algebraic_order_by_npts(572)
returns 39, and next_algebraic_order no longer skips 39. Asking for 552
still throws.
Note for provenance: the original file received from Beylkin,
qsph1-39-552DP.dat, has the same defect -- sum(w)/4pi = 0.963243369097
and 5.7e-02 relative error at degree 8. IntegratorXX's conversion was
faithful; the orbit was already missing upstream. Every other one of the
79 files in that set is exact to ~1e-16.
Worth confirming against the paper before this ships: all 56 other sizes
in the family are of the form 12 + k*60, so 572 = 12 + 20 + 9*60 is
structurally an exception. The reconstruction is a verified order-39
icosahedral rule either way; whether it is *the* published rule is the
open question.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FDTFYJMQ76iujDFNHzZyXF
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.
Fixes #108. Stacked on #101, which withdraws the broken 552-point table;
this restores order 39 with the correct rule.
The 552-point table is missing an orbit
Its weights sum to
0.9632 * 4pi, so it does not integrate a constantcorrectly, let alone anything else. Renormalising does not save it — degree 6
is still 0.75% off and degree 8 is 1.4% off, on a rule advertised as order 39.
The exactness conditions are linear in the weights, so the best possible
weights for a fixed point set follow from one least-squares solve. With AB-612
as a control:
So no weighting of those 552 points works: the point set itself is incomplete.
The 552 points form ten icosahedral orbits (one of 12, nine of 60). Dividing
the weight deficit, 0.461897446456399, by the candidate orbit sizes leaves one
plausible answer:
Adding the 20-point dodecahedral-vertex orbit gives 572 = 12 + 20 + 9*60,
and the same least-squares then reproduces the file's own ten weights exactly
while assigning the new orbit precisely
deficit / 20: 3.674e-13, all weightspositive. That is the missing orbit, not a coincidental fit.
Verification
Refined against the full order-39 condition set:
Emitted at double precision, in the same format as the other tables, it
integrates as well as its neighbours:
npts_by_algebraic_order(39)returns 572,algebraic_order_by_npts(572)returns 39,
next_algebraic_orderno longer skips 39, and asking for 552 stillthrows. The polynomial-exactness test added in #101 covers the new size
automatically. Library suite 9/9.
Provenance
The original file received from Beylkin,
qsph1-39-552DP.dat, has the samedefect:
sum(w)/4pi = 0.963243369097, 5.7e-02 relative error at degree 8. SoIntegratorXX's conversion was faithful and the orbit was already missing
upstream — worth reporting back. Every other one of the 79 files in that set is
exact to ~1e-16; order 39 is the only bad one.
Confirmed against the paper
Ahrens & Beylkin, Rotationally invariant quadratures for the sphere,
Proc. R. Soc. A 465, 3103 (2009), figure 3 caption:
which is exactly the reconstructed structure: 9x60 + 20 (face centre) + 12
(icosahedron vertices) = 572. So this configuration is a documented member of
the family, not an exception — my earlier concern that
572 = 12 + 20 + 9*60broke the
12 + k*60pattern of the other 56 tabulated sizes was unfounded;that pattern just reflects which templates happen to be tabulated.
The algebraic order is 39 exactly, matching the filename. Measured on the
refined rule at 60 digits:
🤖 Generated with Claude Code