Repository navigation
Declare bound_inclusive on every primitive quadrature - #119
wavefunction91 merged 3 commits into
Conversation
RadialTransformQuadrature reads base_quad_traits::bound_inclusive to decide
whether to generate two extra nodes and drop the endpoints, but only
gausschebyshev2 and uniform declared it. The other five failed to compile
when used as a radial base:
error: 'bound_inclusive' is not a member of 'base_quad_traits'
So a radial transform could be composed only with those two, although the
README describes radial quadratures as convolutions of a primitive with a
transformation, which reads as a composition matrix.
The value is whether the rule places nodes on the interval endpoints:
false for the open rules -- gausschebyshev1, gausschebyshev2modified,
gausschebyshev3 and gausslegendre -- and true for gausslobatto, which
includes both endpoints by construction. gausslobatto is the one that
matters beyond bookkeeping: it is the only primitive here whose value is
true, and the natural base for a Gauss-Lobatto x uniform-phi product
sphere rule.
All 28 primitive-transform pairs now compile. The domain-matched ones
integrate r^2 exp(-r) over (0, inf) correctly, for instance at 120 points:
GaussChebyshev2Modified x Becke 0.00e+00
GaussChebyshev2Modified x TreutlerAhlrichs 6.66e-16
GaussLegendre x Becke 0.00e+00
GaussLobatto x Becke 0.00e+00
GaussChebyshev3 x MurrayHandyLaming 8.88e-16
The mismatched pairs compile but are meaningless, since Becke and
Treutler-Ahlrichs map from (-1,1) while Mura-Knowles and
Murray-Handy-Laming map from (0,1); the traits member says nothing about
domain, only about endpoints.
Behaviour-neutral for everything shipped: the four radial quadratures are
bit-identical to master over 392 node and weight values, since the two
primitives they use already declared the member.
Fixes wavefunction91#116.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FDTFYJMQ76iujDFNHzZyXF
|
|
||
| /// Whether the rule places nodes on the interval endpoints. | ||
| /// Lobatto includes both endpoints by construction. | ||
| inline static constexpr bool bound_inclusive = true; |
There was a problem hiding this comment.
The check in the description (all 28 pairs compiling, r²e⁻ʳ on the domain-matched ones) is exactly the regression guard for #116, but it isn't in the suite. Nothing currently instantiates RadialTransformQuadrature over any of these five primitives. Could we add a case to test/1d_quadratures.cxx next to the Becke/MHL tests, e.g. test_quadrature<RadialGaussian> on RadialTransformQuadrature<GaussLobatto<double,double>, BeckeRadialTraits> and on GaussLegendre × Becke? Lobatto is the only true among them, so it would also exercise the endpoint-dropping path.
There was a problem hiding this comment.
Added in 00061bc, as a new "Radial transforms over the primitive rules" case: r^2 exp(-r) on Gauss-Lobatto x Becke and Gauss-Legendre x Becke, plus the full 28-pair instantiation sweep from the description. Against master's primitives the sweep fails with "bound_inclusive is not a member of base_quad_traits", so it guards exactly this. Lobatto covers the endpoint-dropping path as you note.
One wrinkle worth recording: MurrayHandyLamingRadialTraits is templated on the exponent, so the sweep pins it at <2>.
| using point_container = std::vector<point_type>; | ||
| using weight_container = std::vector<weight_type>; | ||
|
|
||
| /// Whether the rule places nodes on the interval endpoints. |
There was a problem hiding this comment.
The two existing declarations (gausschebyshev2.hpp:61, uniform.hpp:46) are bare inline static constexpr bool bound_inclusive = ...; lines, while this adds the same two-line /// comment to each of the five new ones. Could we match the existing ones and drop these? The reason for each value is already visible in generate() just below.
There was a problem hiding this comment.
Dropped from all five, so they now match the existing bare declarations.
The declarations now read like the two that were already in the tree
(gausschebyshev2.hpp, uniform.hpp): bare one-liners, with the reason for
each value left to generate() just below.
The check from the PR description was not in the suite. Nothing instantiated
RadialTransformQuadrature over any of these primitives, since the named
radial grids are all fixed aliases over GaussChebyshev2, so the capability
this unblocks was untested. Add the full 28-pair sweep, which fails to
compile without the declarations ("bound_inclusive is not a member of
base_quad_traits"), plus r^2 exp(-r) on Gauss-Lobatto x Becke and
Gauss-Legendre x Becke. Lobatto is the only bound_inclusive rule among
them, so it also exercises the endpoint-dropping path.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FDTFYJMQ76iujDFNHzZyXF
|
|
||
| TEST_CASE( "Radial transforms over the primitive rules", "[1d-quad]" ) { | ||
|
|
||
| // The named radial grids are all fixed aliases over GaussChebyshev2, so |
There was a problem hiding this comment.
Mura-Knowles and MHL are aliases over UniformTrapezoid, not GaussChebyshev2, and UniformTrapezoid is bound_inclusive too (uniform.hpp:46), so the existing MK/MHL tests already exercise endpoint dropping; Lobatto is the only bound-inclusive Gauss rule.
There was a problem hiding this comment.
Right on both counts — MuraKnowles and MurrayHandyLaming are RadialTransformQuadrature<UniformTrapezoid<...>, ...>, only Becke and Treutler-Ahlrichs go through GaussChebyshev2, and uniform.hpp:46 does declare bound_inclusive = true. So endpoint dropping was already covered and Lobatto is the only bound-inclusive Gauss rule.
Corrected in ef50142, comments only. The commit message on 00061bc carries the same wrong claim, which I have left alone rather than rewrite the branch.
Becke and Treutler-Ahlrichs are aliases over GaussChebyshev2, but Mura-Knowles and MHL are over UniformTrapezoid, which is bound_inclusive itself, so the existing MK and MHL cases already exercise endpoint dropping. Lobatto is the only bound_inclusive Gauss rule, not the only bound_inclusive primitive. Comments only; the cases are unchanged. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FDTFYJMQ76iujDFNHzZyXF
Fixes #116.
RadialTransformQuadraturereadsbase_quad_traits::bound_inclusiveto decidewhether to generate two extra nodes and drop the endpoints, but only
gausschebyshev2anduniformdeclared it. The other five failed to compilewhen used as a radial base:
so a radial transform could be composed only with those two, although the
README describes radial quadratures as convolutions of a primitive with a
transformation — which reads as a composition matrix.
The value is whether the rule places nodes on the interval endpoints:
falsefor the open rules (
gausschebyshev1,gausschebyshev2modified,gausschebyshev3,gausslegendre) andtrueforgausslobatto, whichincludes both by construction.
gausslobattois the one that matters beyondbookkeeping — the only primitive here whose value is
true, and the naturalbase for a Gauss-Lobatto x uniform-phi product sphere rule.
Verified
All 28 primitive-transform pairs compile. The domain-matched ones integrate
r^2 exp(-r)over(0, inf)correctly at 120 points, e.g.The mismatched pairs compile but are meaningless — Becke and
Treutler-Ahlrichs map from
(-1,1)while Mura-Knowles andMurray-Handy-Laming map from
(0,1). The traits member says nothing aboutdomain, only about endpoints, so this PR does not make every pair valid, only
every pair expressible. Guarding the domain would be a separate change.
Behaviour-neutral for everything shipped: the four radial quadratures are
bit-identical to master across 392 node and weight values, since the two
primitives they use already declared the member. Suite 9/9.
Not done here
The requirement is duck-typed: a new primitive fails only when someone tries to
compose it. A defaulted member in a traits base, or a
static_assertwith adetection idiom in
RadialTransformQuadrature, would stop this recurring. Ileft that out as a separate design question rather than bundling it.
🤖 Generated with Claude Code
https://claude.ai/code/session_01FDTFYJMQ76iujDFNHzZyXF