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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
// JEOD_INV: TS.01 — `<SelfRef>` / `<SelfPlanet>` are runtime-resolved storage-boundary wildcards; see `docs/JEOD_invariants.md` row TS.01 and the lint at `tests/self_ref_self_planet_discipline.rs`.
//! Custom quantity dimensions not already present in `uom::si`.
//!
//! Dimensions are compile-time 7-tuples of `typenum` integers indexing
//! `ISQ<L, M, T, I, Th, N, J>`. Each alias below names a physical quantity
//! used by orbital mechanics that `uom::si` does not predefine.
//!
//! The `*Dim` aliases can be used as the dimension parameter of `Qty3<D, F>`;
//! the companion scalar aliases (`SpecificAngMom`, …) model the
//! corresponding `Quantity<_, SI<f64>, f64>` values used in scalar math.
//!
//! # Planet-tagged gravitational parameter
//!
//! [`GravParam<P>`] is the planet-phantom-tagged gravitational parameter:
//! `GravParam<Earth>` and `GravParam<Sun>` are distinct types. Mixing them
//! across a planet boundary is a compile error. The witness-gated
//! constructor pattern mirrors [`crate::BodyAttitude<V>`]: callers reach
//! the type only through factories that fix the planet (e.g.
//! `f64.m3_per_s2_for::<Earth>()`, `mu_ggm05c()` returning
//! `GravParam<Earth>`).
use PhantomData;
use ;
use ;
use crate;
/// Gravitational parameter μ = GM (L³T⁻²). Base SI unit: m³/s².
pub type GravParamDim = ;
/// Specific angular momentum h = |r × v| / m (L²T⁻¹). Base SI unit: m²/s.
pub type SpecificAngMomDim = ;
/// Specific energy ε (L²T⁻²). Base SI unit: J/kg = m²/s².
pub type SpecificEnergyDim = ;
/// Mass flow rate ṁ (MT⁻¹). Base SI unit: kg/s.
pub type MassFlowRateDim = ;
// --- Scalar `Quantity` aliases -----------------------------------------------
/// Scalar specific angular momentum.
pub type SpecificAngMom = ;
/// Scalar specific energy.
pub type SpecificEnergy = ;
/// Scalar mass-flow rate.
pub type MassFlowRate = ;
// --- Planet-tagged gravitational parameter -----------------------------------
/// Gravitational parameter μ = GM tagged with the source planet `P`.
///
/// `GravParam<Earth>` and `GravParam<Sun>` are distinct types so the
/// compiler refuses to silently feed `μ_Sun` into a function expecting
/// `μ_Earth`. The numeric value is stored in SI base units (m³/s²) and
/// reachable via [`GravParam::value`] (also a public field for the
/// kernel-level call sites that already do `mu.value`).
///
/// ## Construction
///
/// Mission code constructs a `GravParam<P>` through the inferred-planet
/// factory `f64::m3_per_s2()` (planet `<P>` inferred from the
/// expected-type context at the call site — see
/// [`crate::ext::F64Ext::m3_per_s2`] for the full story; a bare
/// `let mu = 1.0.m3_per_s2();` with no expected-type context fails to
/// compile), the explicit-planet factory `f64::m3_per_s2_for::<P>()`, or
/// one of the curated `mu_*()` constants in
/// `astrodyn::recipes::constants`. Calling a typed consumer with a
/// [`SelfPlanet`]-tagged μ in a planet-pinned slot is rejected at compile
/// time, so a planet-erased μ only flows through `SelfPlanet`-typed
/// surfaces (the registry-side boundary code, `GravitySource`, etc.).
///
/// ```
/// use astrodyn_quantities::prelude::*;
///
/// // Planet-pinned construction (Earth):
/// let mu_earth: GravParam<Earth> = 3.986_004_415e14_f64.m3_per_s2_for::<Earth>();
/// // Type ascription supplies the inference context for `<P>`:
/// let mu_sun: GravParam<Sun> = 1.327_124_400_18e20_f64.m3_per_s2();
/// // The numeric SI value in m³/s² is reachable via `.value`:
/// assert!(mu_earth.value > 0.0);
/// assert!(mu_sun.value > 0.0);
/// ```
///
/// ## Compile-fail: cross-planet construction is rejected
///
/// Building a planet-pinned `GravParam<Earth>` directly from a
/// `GravParam<Sun>` is a type error — the compiler refuses the
/// assignment.
///
/// ```compile_fail
/// use astrodyn_quantities::prelude::*;
/// let mu_sun: GravParam<Sun> = 1.327e20.m3_per_s2_for::<Sun>();
/// let _bad: GravParam<Earth> = mu_sun; // planet phantom mismatch
/// ```
///
/// A planet-erased `GravParam<SelfPlanet>` cannot be assigned to a
/// planet-pinned slot either — `SelfPlanet` is not `Earth`:
///
/// ```compile_fail
/// use astrodyn_quantities::prelude::*;
/// let mu_any: GravParam<SelfPlanet> = 3.986e14.m3_per_s2();
/// let _bad: GravParam<Earth> = mu_any; // SelfPlanet vs Earth mismatch
/// ```
///
/// ## Compile-fail: there is no `<P = SelfPlanet>` default
///
/// `GravParam<P>` carries no default planet — every call site must
/// commit to a planet via turbofish, type ascription, or argument
/// inference. A bare `GravParam::from_si(...)` with no inference
/// context is rejected. There is deliberately no `<P = SelfPlanet>`
/// fallback: a default would silently relax to `<SelfPlanet>` whenever
/// inference had no constraint, hiding missing planet-pinning
/// decisions. The type system is meant to surface those at compile
/// time, not satisfy them with a wildcard:
///
/// ```compile_fail
/// use astrodyn_quantities::prelude::*;
/// // No type context for `<P>`, no turbofish, no default — type
/// // annotations needed.
/// let _mu = GravParam::from_si(3.986_004_415e14);
/// ```
///
/// The fix is to commit to a planet at the call site:
///
/// ```
/// use astrodyn_quantities::prelude::*;
/// let _mu = GravParam::<Earth>::from_si(3.986_004_415e14);
/// ```
// Manual impls — the derive macros would demand `P: Default`/`P: Copy`/...
// which is wrong for a phantom-only type parameter.