1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
//! Typed index wrappers for species, elements, phases, and reactions.
//!
//! # Purpose
//!
//! This module provides **type-safe index wrappers** that prevent confusion
//! between different kinds of indices in the equilibrium calculation. Instead
//! of passing raw `usize` values (where a species index could be mistaken for
//! an element index), these wrappers enforce correctness at the type level.
//!
//! # Key Structures
//!
//! | Type | Wraps | Purpose |
//! |------|-------|---------|
//! | [`SpeciesId`] | `usize` | Index into species arrays |
//! | [`ElementId`] | `usize` | Index into element arrays |
//! | [`PhaseIndex`] | `usize` | Index into phase arrays |
//! | [`ReactionId`] | `usize` | Index into reaction arrays |
//!
//! All four types are generated by the [`typed_id!`] macro, which provides:
//!
//! - `new(index, upper_bound) -> Result<Self, ReactionExtentError>` — bounds-checked constructor.
//! - `index(self) -> usize` — unwrap to raw index.
//! - `From<X> for usize` — conversion trait.
//!
//! # Dataflow
//!
//! ```text
//! External code (phase_layout, problem builder)
//! │
//! ├── SpeciesId::new(i, n_species) ──> species array index
//! ├── ElementId::new(j, n_elements) ──> element array index
//! ├── PhaseIndex::new(k, n_phases) ──> phase array index
//! └── ReactionId::new(r, n_rxns) ──> reaction array index
//! │
//! v
//! Used in: EquilibriumProblem, EquilibriumComponentDescriptor,
//! PhaseSet, PhaseManager, equilibrium_workflows
//! ```
//!
//! # Examples
//!
//! ```rust
//! use KiThe::Thermodynamics::ChemEquilibrium::equilibrium_ids::SpeciesId;
//!
//! let species = SpeciesId::new(0, 5).unwrap();
//! assert_eq!(species.index(), 0);
//!
//! // Out-of-bounds returns an error
//! assert!(SpeciesId::new(5, 5).is_err());
//! ```
//!
//! # Non-obvious Details
//!
//! - These IDs are **dense ordered indices**, not semantic identifiers. For
//! semantic phase identity (e.g., "gas phase" vs "condensed phase"), use
//! [`PhaseId`](crate::Thermodynamics::phase_layout::PhaseId) from the
//! `phase_layout` module.
//! - The bounds check in `new()` uses **exclusive upper bound** (like array
//! indexing), so `SpeciesId::new(5, 5)` is out of bounds for a 5-element array.
//! - The `From<X> for usize` conversion enables ergonomic use with nalgebra
//! matrix indexing and other `usize`-based APIs.
//!
//! # Related Modules
//!
//! - [`equilibrium_problem`](super::equilibrium_problem) — uses these IDs in problem definition
//! - [`equilibrium_component`](super::equilibrium_component) — component descriptors with typed IDs
//! - [`equilibrium_workflows`](super::equilibrium_workflows) — phase management with PhaseIndex
//!
use crateReactionExtentError;
/// Typed index for a species in the prepared equilibrium ordering.
;
/// Typed index for a chemical element in the prepared equilibrium ordering.
;
/// Typed dense index for a physical phase in equilibrium-owned arrays.
///
/// This is deliberately named `PhaseIndex`: semantic phase identity belongs
/// to `Thermodynamics::phase_layout::PhaseId` and must survive at the bridge
/// boundary instead of being replaced by an integer.
;
/// Typed index for an independent reaction row.
;
typed_id!;
typed_id!;
typed_id!;
typed_id!;