units
analysis.units
Dimensional analysis of a model’s equations.
The symbolic layer knows a quantity is real. This is what lets it know a quantity is a voltage: units travel beside the expression, as a map from the scope’s own symbols to the unit each was declared in, and propagate through the equation rather than being multiplied into it.
Beside, not inside, for three reasons. 87% of quantities in the curated database declare no unit, so an expression carrying Quantity factors would be inconsistent by construction for almost every model; every consumer of the symbolic layer would have to strip those factors before printing; and the frozen codegen corpus would move. None of that buys anything a separate map does not.
The verdict is three-valued — consistent, inconsistent, underdetermined — because “I cannot tell” is a different claim from “this is wrong”, and collapsing them is how a checker becomes noise. An undeclared quantity is the common case, and treating it as dimensionless silently corrupts the answer: hhcell_1 declares units for 92% of its symbols and reports dv/dt as 1/capacitance — not voltage over time — purely because its one undeclared symbol was assumed dimensionless.
Two strictnesses over one map (U2). dimensional compares base-dimension vectors, so mV/ms and V/s agree; exact compares the full quantity, so they do not, and the disagreement is reported as the exact rational ratio 1 vs 1000. The ratio is the part that names the bug — a boolean does not.
Attributes
| Name | Description |
|---|---|
| CONSISTENT | |
| INCONSISTENT | |
| UNDERDETERMINED |
Classes
| Name | Description |
|---|---|
| DimensionalClash | Two quantities that must agree dimensionally do not. |
| Term | One addend of an equation, with the unit propagation assigned to it. |
| Verdict | The dimensional standing of one equation. |
DimensionalClash
analysis.units.DimensionalClash()Two quantities that must agree dimensionally do not.
Term
analysis.units.Term(expression, unit=None, unknown=None)One addend of an equation, with the unit propagation assigned to it.
Verdict
analysis.units.Verdict(
name,
equation,
status,
detail='',
unit=None,
ratios=dict(),
inferred=dict(),
undeclared=(),
)The dimensional standing of one equation.
Functions
| Name | Description |
|---|---|
| check_units | Per-equation dimensional verdicts for model. |
| declared_units | The third projection of the symbolic layer: {scope symbol: declared unit}. |
| dimension_exponents | ISO 80000-1 base-dimension exponents of a declared unit, for reporting (U25). |
| quantity_name | The name of the quantity expression stands for. |
check_units
analysis.units.check_units(model, strictness='dimensional', time_unit=None)Per-equation dimensional verdicts for model.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| model | A Dynamics, read through its symbolic projection. |
required | |
| strictness | str | "dimensional" compares base-dimension vectors, so mV/ms and V/s agree. "exact" compares the whole quantity, so they do not, and the ratio is reported. |
'dimensional' |
| time_unit | str | None | The scope’s time unit; resolved via time_unit_of when omitted. |
None |
Returns
| Name | Type | Description |
|---|---|---|
| list[Verdict] | One Verdict per state equation, each consistent, inconsistent or |
|
| list[Verdict] | underdetermined, carrying the derived unit, any inferred units, and the exact |
|
| list[Verdict] | ratios of any disagreement. |
declared_units
analysis.units.declared_units(model, scope=None)The third projection of the symbolic layer: {scope symbol: declared unit}.
Keyed by the scope’s own symbols, like Dynamics.symbolic["parameters"] — rebuilt keys look identical, compare unequal, and would silently match nothing. A caller that already holds the analysis scope passes it, so the map is keyed by the very table its equations were parsed against rather than by whichever one the model resolves to.
dimension_exponents
analysis.units.dimension_exponents(unit)ISO 80000-1 base-dimension exponents of a declared unit, for reporting (U25).
dim Q = L²MT⁻³I⁻¹ is what makes an inconsistency legible: L²MT⁻³I⁻¹ against L²MT⁻⁴I⁻¹ shows where the discrepancy is, where “voltage vs something else” does not.
quantity_name
analysis.units.quantity_name(expression)The name of the quantity expression stands for.
y0 for all of y0, y0(t) and Derivative(y0(t), t) — a quantity is the same quantity however the notation renders it, and every caller (a verdict’s label, a report row keyed by parameter name) wants that one name.