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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
//! Canonical phase-qualified identity for equilibrium solver components.
//!
//! A component is not merely a substance name: `gas::H2O` and `liquid::H2O`
//! are distinct unknowns with potentially different standard-state records.
//! This module is deliberately independent from bridge construction and from
//! nonlinear solvers so both layers share one identity contract.
use crate::Thermodynamics::ChemEquilibrium::equilibrium_activity::PhaseActivityModel;
use crate::Thermodynamics::ChemEquilibrium::equilibrium_ids::PhaseIndex;
use crate::Thermodynamics::User_PhaseOrSolution::PhaseModel;
use crate::Thermodynamics::phase_layout::{PhaseComponentId, PhaseId};
use crate::Thermodynamics::physical_state::PhysicalState;
use std::ops::Range;
/// Solver-facing identity and thermodynamic interpretation of one component.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct EquilibriumComponentDescriptor {
id: PhaseComponentId,
physical_state: PhysicalState,
phase_model: PhaseModel,
activity_model: PhaseActivityModel,
}
impl EquilibriumComponentDescriptor {
/// Creates one fully qualified equilibrium component.
pub fn new(
id: PhaseComponentId,
physical_state: PhysicalState,
phase_model: PhaseModel,
activity_model: PhaseActivityModel,
) -> Self {
Self {
id,
physical_state,
phase_model,
activity_model,
}
}
/// Phase-qualified component identity in canonical solver order.
pub fn id(&self) -> &PhaseComponentId {
&self.id
}
/// Bare substance name used for thermochemical record lookup.
pub fn substance(&self) -> &str {
&self.id.substance
}
/// Stable user-facing label that remains unique across phases.
pub fn label(&self) -> String {
self.id.label()
}
/// Physical state selected during thermochemical lookup.
pub fn physical_state(&self) -> PhysicalState {
self.physical_state
}
/// Domain-level phase model declared by the data subsystem.
pub fn phase_model(&self) -> PhaseModel {
self.phase_model
}
/// Canonical activity law consumed by equilibrium residuals.
pub fn activity_model(&self) -> PhaseActivityModel {
self.activity_model
}
}
/// Compatibility conversion for existing one-phase gas callers.
///
/// New multiphase code must construct [`EquilibriumComponentDescriptor`]
/// explicitly. A bare string is projected into the anonymous single gas phase
/// only so old one-phase tests and examples keep a well-defined identity while
/// they migrate.
impl From<String> for EquilibriumComponentDescriptor {
fn from(substance: String) -> Self {
Self::new(
PhaseComponentId::new(PhaseId::new(None), substance),
PhysicalState::Gas,
PhaseModel::IdealGas,
PhaseActivityModel::IdealGas,
)
}
}
/// Ordered semantic description of one equilibrium phase.
///
/// Its component range is the canonical phase-to-component mapping. Numeric
/// `Phase { kind, species }` values exist only as a derived projection for
/// residual and Jacobian implementations that have not yet migrated.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct EquilibriumPhaseDescriptor {
id: PhaseId,
index: PhaseIndex,
physical_state: PhysicalState,
phase_model: PhaseModel,
activity_model: PhaseActivityModel,
component_range: Range<usize>,
}
impl EquilibriumPhaseDescriptor {
/// Creates a fully qualified phase descriptor in canonical phase order.
pub fn new(
id: PhaseId,
index: PhaseIndex,
physical_state: PhysicalState,
phase_model: PhaseModel,
activity_model: PhaseActivityModel,
component_range: Range<usize>,
) -> Self {
Self {
id,
index,
physical_state,
phase_model,
activity_model,
component_range,
}
}
/// Semantic phase identity retained through lookup, solve, and reporting.
pub fn id(&self) -> &PhaseId {
&self.id
}
/// Dense numeric phase coordinate derived from canonical order.
pub fn index(&self) -> PhaseIndex {
self.index
}
/// Physical state selected for thermochemical record lookup.
pub fn physical_state(&self) -> PhysicalState {
self.physical_state
}
/// Domain-level phase model.
pub fn phase_model(&self) -> PhaseModel {
self.phase_model
}
/// Canonical activity law used by the numerical formulation.
pub fn activity_model(&self) -> PhaseActivityModel {
self.activity_model
}
/// Contiguous component range in canonical component order.
pub fn component_range(&self) -> Range<usize> {
self.component_range.clone()
}
}