Skip to content

MultiplicationOperator never compares its coefficient's space to its ends — a field on an alien space is admitted silently (SN/diffusion paths) #458

Description

@deOliveira-R

The hole

MultiplicationOperator (orpheus/transport/operators/multiplication_operator.py) is built from a CrossSectionField coefficient and two ends (domain, codomain), and it never compares the coefficient's space to its ends:

  • [M] 2026-09-08 (CS4c coda verification plan, scratch/_step6/test_architect_verification_plan_coda.md O-6): grep -c 'coefficient\.space' orpheus/ = 0.
  • Consequence, measured on the pre-coda tree: the homogeneous solver's σ_t field was minted on a fabricated one-cell carrier's bulk_space and consumed by an operator whose ends were the mixture-minted pose — two spaces that happened to compare == (same axes, same weights) — and nothing on the path would have refused them had they differed. tests/homogeneous/test_coda_anchors.py (pre-C1 version, aef9ad8f) recorded eight "alien carrier" rows exploiting exactly this: a field born on a width-2 carrier's space was accepted by an operator posed on the counting point.

The CS4c coda made the disagreement unspellable on the homogeneous path only: HomogeneousProblem (C1 5caad3d6) births every field on the pose and binds every operator's ends to the same object, and the fabricated carrier retired (C2 39e7f32f). The SN and diffusion paths keep the hole — every MultiplicationOperator(coefficient=<field>, domain=<space>, codomain=<space>) construction admits a field on an alien space silently.

What "fixed" looks like

Per coding-elegance Pattern 4 the target is not a guard but a construction that cannot be misused: the coefficient field and the operator's ends should be ONE object's data — the field's space IS the operator's domain (a diagonal multiplication is an endomorphism of the field's own space), so MultiplicationOperator.from_field(field) with no separately-passed ends is the honest constructor, and the two-ends signature is the debt. If a transitional guard lands first, it carries ELEGANCE-DEBT[guard] #<this issue> and names this construction as what retires it (coding-standards, "A guard is elegance debt").

Blast radius to census before touching it (§6b, the bare-argument and polymorphic spellings included): every MultiplicationOperator( / .from_mesh( / .from_field( site in orpheus/ and tests/; the IsotropicScattering/IsotropicN2N/IsotropicFission siblings share the shape (assert_energy_extent_conforms covers only the ENERGY extent — see the 2026-08-21 battery note in .claude/rules/vv-testing.md/vv-principles #17 on the C site keying on self.coefficient.values.shape[0]).

Provenance

CS4c coda (plan .claude/plans/cs4c_binding_design.md §26); filed after gh issue list --search "MultiplicationOperator coefficient space" returned only the unrelated closed #257.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    module:sn02.Discrete.Ordinatestype:improvementEnhancement to existing functionality

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions