dimensions.json has 72 entries and none with the exponents L³T⁻². That is the standard gravitational parameter μ = GM — μ_Earth = 3.986004418×10¹⁴ m³/s² — which is the most-used constant in orbital mechanics. Today it can only be carried as a bare T, so the one number every orbital calculation multiplies by is the one number in the calculation with no dimension attached.
Two companions are missing for the same reason, and both are more interesting than μ, because they are name collisions on exponent vectors that already exist — the 72-over-63 situation the nominal layer is for:
| Proposed |
Exponents |
Already on that vector |
GravitationalParameter |
L³ T⁻² |
nothing — this would be a 64th vector |
SpecificEnergy |
L² T⁻² |
AbsorbedDose, EquivalentDose |
SpecificAngularMomentum |
L² T⁻¹ |
KinematicViscosity |
Specific orbital energy and absorbed radiation dose are dimensionally identical — both are joules per kilogram. That is a cleaner illustration of why exponents alone cannot carry meaning than any example currently in CLAUDE.md, and worth adding there alongside Torque/Energy and Area/NuclearCrossSection.
Design
GravitationalParameter — V0 only
A product of two positive quantities, never negative. physicalConstraints: { "minExclusive": "0" } is arguably right as well, since a body of zero mass has no orbit — same reasoning as Wavelength and Period.
Units: MeterCubedPerSecondSquared (base) and KilometerCubedPerSecondSquared (factor 1e9), the latter because every published value is quoted in km³/s².
SpecificEnergy — V1, not V0, and this is the one that matters
Specific orbital energy is ε = −μ/2a, which is negative for every bound orbit. A V0 base would run Vector0Guards.EnsureNonNegative and throw ArgumentException on the entirely ordinary case of a satellite in orbit.
So the base is a signed V1, with SpecificOrbitalEnergy as an overload. A V0 form can exist alongside for specific kinetic energy, which genuinely is non-negative.
Getting this backwards would ship a type that fails its own assertion on every real input — the same class of error dot(Force, Length) -> Energy was refused for, and the reason that refusal names "Energy needs a vector1 form" rather than guessing.
SpecificAngularMomentum — V0 base plus a V3 form
h = r × v is a vector, and the direction is what encodes the orbital plane, so the V3 form is not optional here.
Relationships
Each must survive the SEM008 exponent check:
GravitationalParameter / Area -> Acceleration — L³T⁻² / L² = L T⁻² ✓ (this is g = μ/r²)
GravitationalParameter / Length -> SpecificEnergy — L³T⁻² / L = L²T⁻² ✓
- on
Length, crossProducts: [{ "other": "Velocity", "result": "SpecificAngularMomentum", "forms": [3] }] — L · L T⁻¹ = L² T⁻¹ ✓
That last one carries the same hazard as the torque relationship already documented in CLAUDE.md: h = r × v, not v × r, and the exponents cannot tell the two apart, because a cross product and its negation have identical dimensions. It has to be declared on Length so the operands land in that order, and a test must pin the sign — position +x̂ with velocity +ŷ gives +ẑ, and the other order gives −ẑ. This is exactly how the Force-vs-Length declaration of torque went wrong before.
Also needed
- New entries in
units.json for the two μ units
conversions.json: KilometerCubedPerSecondSquaredToMeterCubedPerSecondSquared with value "1000000000"
- Regenerate, then run
pwsh scripts/Generate-AliasProps.ps1 — this change does add type names, so the alias props for all four storage packages change and verify-generated will fail the PR if they are not committed
- A
CLAUDE.md line recording the two new collisions
Method
#216 is the precedent worth following: Sensitivity's dimensional formula disagreed with its own availableUnits and with the relationship declared on it, and two witnesses against one settled it. Each formula proposed above should get the same treatment before it is trusted — check the exponents against the units the dimension would carry, and against the relationships it participates in, rather than against intuition.
dimensions.jsonhas 72 entries and none with the exponents L³T⁻². That is the standard gravitational parameter μ = GM — μ_Earth = 3.986004418×10¹⁴ m³/s² — which is the most-used constant in orbital mechanics. Today it can only be carried as a bareT, so the one number every orbital calculation multiplies by is the one number in the calculation with no dimension attached.Two companions are missing for the same reason, and both are more interesting than μ, because they are name collisions on exponent vectors that already exist — the 72-over-63 situation the nominal layer is for:
GravitationalParameterSpecificEnergyAbsorbedDose,EquivalentDoseSpecificAngularMomentumKinematicViscositySpecific orbital energy and absorbed radiation dose are dimensionally identical — both are joules per kilogram. That is a cleaner illustration of why exponents alone cannot carry meaning than any example currently in
CLAUDE.md, and worth adding there alongsideTorque/EnergyandArea/NuclearCrossSection.Design
GravitationalParameter— V0 onlyA product of two positive quantities, never negative.
physicalConstraints: { "minExclusive": "0" }is arguably right as well, since a body of zero mass has no orbit — same reasoning asWavelengthandPeriod.Units:
MeterCubedPerSecondSquared(base) andKilometerCubedPerSecondSquared(factor 1e9), the latter because every published value is quoted in km³/s².SpecificEnergy— V1, not V0, and this is the one that mattersSpecific orbital energy is ε = −μ/2a, which is negative for every bound orbit. A V0 base would run
Vector0Guards.EnsureNonNegativeand throwArgumentExceptionon the entirely ordinary case of a satellite in orbit.So the base is a signed V1, with
SpecificOrbitalEnergyas an overload. A V0 form can exist alongside for specific kinetic energy, which genuinely is non-negative.Getting this backwards would ship a type that fails its own assertion on every real input — the same class of error
dot(Force, Length) -> Energywas refused for, and the reason that refusal names "Energy needs a vector1 form" rather than guessing.SpecificAngularMomentum— V0 base plus a V3 formh = r × v is a vector, and the direction is what encodes the orbital plane, so the V3 form is not optional here.
Relationships
Each must survive the SEM008 exponent check:
GravitationalParameter / Area -> Acceleration— L³T⁻² / L² = L T⁻² ✓ (this is g = μ/r²)GravitationalParameter / Length -> SpecificEnergy— L³T⁻² / L = L²T⁻² ✓Length,crossProducts: [{ "other": "Velocity", "result": "SpecificAngularMomentum", "forms": [3] }]— L · L T⁻¹ = L² T⁻¹ ✓That last one carries the same hazard as the torque relationship already documented in
CLAUDE.md: h = r × v, not v × r, and the exponents cannot tell the two apart, because a cross product and its negation have identical dimensions. It has to be declared onLengthso the operands land in that order, and a test must pin the sign — position +x̂ with velocity +ŷ gives +ẑ, and the other order gives −ẑ. This is exactly how theForce-vs-Lengthdeclaration of torque went wrong before.Also needed
units.jsonfor the two μ unitsconversions.json:KilometerCubedPerSecondSquaredToMeterCubedPerSecondSquaredwith value"1000000000"pwsh scripts/Generate-AliasProps.ps1— this change does add type names, so the alias props for all four storage packages change andverify-generatedwill fail the PR if they are not committedCLAUDE.mdline recording the two new collisionsMethod
#216 is the precedent worth following:
Sensitivity's dimensional formula disagreed with its ownavailableUnitsand with the relationship declared on it, and two witnesses against one settled it. Each formula proposed above should get the same treatment before it is trusted — check the exponents against the units the dimension would carry, and against the relationships it participates in, rather than against intuition.