.. _hadros-channel-spaces: Channel Spaces ============== A channel space is the ordered set of resolved asymptotic labels used for matrix rows and columns in downstream spectrum and amplitude calculations. Threshold compositions are used to organize the output, but they are not sufficient channel labels. One-Hadron Channels ------------------- ``OneHadronChannel`` is a thin channel-space view of one catalog ``Hadron``. It inherits the hadron's spin-parity and flavor, uses the catalog name as its structured identity, and has a threshold equal to the hadron mass. The wrapper allows single-hadron states to use the same stable-key and indexed ``ChannelBasis`` machinery as multi-hadron channels without changing the meaning of a catalog entry. This type represents a catalog hadron in a target sector. It does not represent a dynamically reconstructed bound-state pole. Pole positions, Riemann sheets, and residues belong to the amplitude package; a later pole-spectator channel may adapt that information to particle-like kinematics without making it catalog metadata. Two-Hadron Channels ------------------- ``TwoHadronChannel`` contains: * two catalog hadrons; * a ``PartialWave`` describing their :math:`LSJ` coupling; * total ``SpinParity``; and * total ``Flavor``. Construction validates spin and isospin triangle rules, total parity, additive flavor, identical-particle exchange symmetry, and G parity whenever it is defined. The channel threshold is the sum of its two hadron masses. Channel XML records the complete ``twoS``, ``L``, ``twoJ`` partial wave. Although its ``twoJ`` repeats the enclosing target value, requiring it keeps the individual entry readable as a complete :math:`^{2S+1}L_J` label and lets the loader diagnose disagreement at the XML boundary. ``TwoHadronPairKey`` identifies only the unordered particle content. ``TwoHadronChannelKey`` adds the partial wave and total quantum numbers. The former is useful for threshold grouping; the latter is the structured identity of a resolved channel. For downstream relativistic normalization, every channel derives: .. math:: \xi_2 = \begin{cases} 1/2, & \text{identical pair},\\ 1, & \text{otherwise}. \end{cases} This symmetry factor comes from particle content and is not stored as an independent XML field. Kinematics and amplitude code therefore receive one authoritative value through ``two_body_symmetry_factor()``. Pair-Spectator Channels ----------------------- ``PairSpectatorChannel`` is the principal three-body label. It stores: * a resolved ``TwoHadronChannel`` for the interacting pair; * the spectator ``Hadron``; * a relative ``PartialWave`` coupling the pair to the spectator; * total three-body ``SpinParity``; and * total three-body ``Flavor``. The pair wave and relative wave are separate. For example, changing the pair isospin or pair orbital angular momentum changes the channel even when the three particle names and total target are unchanged. Both waves carry a complete ``twoS``, ``L``, ``twoJ`` specification. The pair ``twoJ`` is an intermediate angular momentum, whereas the relative-wave ``twoJ`` must equal the enclosing three-body target. The pair and spectator names define a species-level channel. Numbered particle slots are deliberately absent. Thus ``pi:pi`` plus a ``pi`` spectator appears once, and the two equivalent ``eta:pi`` pairings in ``eta:pi:pi`` collapse to one label. A later symmetrization package may generate and combine the required particle permutations without making them separate asymptotic channel keys. ``ThreeHadronCompositionKey`` strips this coupling information down to the unordered three-particle content. It is useful for threshold grouping. ``PairSpectatorChannelKey`` retains the full resolved identity needed for lookup and matrix construction. G-Parity Projection ------------------- A ``PairSpectatorChannel`` is an unprojected label and therefore carries ``G=0``. For a target with definite G parity, enumeration acts with G on the channel label: .. math:: G\lvert a\rangle = \eta_a\lvert \bar a\rangle . ``g_parity_action`` returns the partner label and phase. Enumeration retains compatible self-mapping labels and one canonical representative from each two-label conjugation orbit; the containing basis records the target G sign. This supplies the information needed to reconstruct projected combinations without pretending that an individual unprojected pair-spectator label has a definite G parity. Catalogs used for this operation must contain conjugate partners. The command-line tools complete them automatically before enumeration. Channel Bases ------------- ``ChannelBasis`` associates all selected channels for one cut-free ``TargetQuantumNumbers`` identity with two complementary identifiers: ``index`` A contiguous, zero-based position local to the target basis. This is the matrix row or column index. ``id`` A stable string derived from the complete structured channel content. This is appropriate for XML, diagnostics, and cross-package lookup. The public aliases are ``OneHadronChannelBasis``, ``TwoHadronChannelBasis``, and ``PairSpectatorChannelBasis``. ``ChannelSpace`` collects all three bases under one target. Missing XML sections load as empty bases. Neither indices nor stable IDs are serialized. XML ```` order establishes the local matrix order, and stable IDs are reconstructed from channel content after loading. Energy and angular-momentum generation cuts remain in ``targets.xml`` and are not part of a loaded basis. Changing the explicit selection or ordering changes local indices, which is why reviewed spaces should be compared and validated. Construction and Lookup ----------------------- Construct bases directly from C++: .. code-block:: cpp auto two_bases = hadros::make_two_hadron_channel_bases(catalog, targets); auto one_basis = hadros::make_one_hadron_channel_basis(catalog, target); auto three_basis = hadros::make_pair_spectator_channel_basis(catalog, target); const auto& two_basis = two_bases.front(); auto index = hadros::find_channel_index(two_basis, channel.key()); Or load generated XML in the context of its catalog: .. code-block:: cpp auto catalog = hadros::load_hadron_catalog("hadrons.xml").with_conjugates(); auto spaces = hadros::load_channels("channels.xml", catalog); const auto& two_basis = spaces.front().two_body(); const auto& three_basis = spaces.front().three_body(); ``load_channels`` accepts any combination of optional one-, two-, and three-body sections. It validates the schema, reconstructs all omitted quantities from the catalog and target identity, rejects duplicate or impossible entries, checks the root-level flavor basis against the catalog, and assigns local indices from document order. The body-specific ``load_two_hadron_channel_bases`` and ``load_pair_spectator_channel_bases`` conveniences return the corresponding explicit selections without regenerating them from target cuts. Each indexed entry exposes its local matrix index, stable ID, and resolved channel object. Downstream code can therefore allocate matrices from the basis size and retain human-readable labels for diagnostics. Stable Channel Identity ----------------------- The structured ``OneHadronChannelKey``, ``TwoHadronChannelKey``, and ``PairSpectatorChannelKey`` objects are the source of truth for identity. Hadros converts every key to an unambiguous canonical byte representation and exposes its full SHA-256 digest with a body-specific prefix, for example ``h2:sha256:...``. Field names and text values are length-prefixed, so punctuation inside a hadron name cannot be confused with an ID separator. The canonical representation carries its own schema version. This makes an intentional future identity change visible instead of silently changing the meaning of an existing digest. Hadron masses and derived thresholds are not part of the key: changing a catalog mass leaves the physical channel ID alone, while its reconstructed threshold follows the catalog supplied at load time. IDs and readable labels are generated in memory and do not appear in ``channels.xml``. Basis construction rejects duplicate digests, guarding against repeated entries and any unexpected collision. Generation and Validation ------------------------- The generator enumerates every target in input order and serializes one space per target. ``--n-particle=N`` writes exactly the selected multiplicity; omitting it writes a combined database: .. code-block:: console $ ./build/generate_channels \ hadrons.xml targets.xml two_channels.xml --n-particle=2 $ ./build/generate_channels \ hadrons.xml targets.xml three_channels.xml --n-particle=3 $ ./build/generate_channels \ hadrons.xml targets.xml channels.xml Omit the output path to preview the detailed basis without writing a file. Add ``--summary`` with or without an output path to print only per-target counts. ``validate_channels`` loads all present sections and checks the embedded target order against the source target database. Particle names, angular couplings, flavor, parity, cutoffs, duplicates, and XML order are checked while loading. Thresholds, labels, IDs, counts, and indices are derived rather than trusted serialized fields. Current Boundary ---------------- The channel classes provide validated labels and deterministic bases. They do not construct K matrices, amplitudes, finite-volume irreps, integral-equation kernels, or complete three-particle symmetrization. Those operations should consume these labels while remaining in their own physics packages.