PharmFlux 0.1.0 documentation

Units: implemented subset and lowering contract

Status: M0 draft. This describes the implemented Rust unit and expression checker. The full serialized ModelIR, text grammar, unit-bearing run request, and output schema remain separate work.

Codes and dimensions

Unit codes follow a restricted case-sensitive subset of UCUM. This is not a complete UCUM implementation. Multiplication uses ., division uses /, and integer exponents attach to symbols or groups: mg.kg-1.d-1, mg/(kg.d), cm2. Multiplication and division have equal precedence and associate left to right. Parentheses disambiguate compound denominators. Whitespace, ^, annotations, affine units, non-integer numeric scale factors, and implicit multiplication are rejected. Positive decimal integer factors are supported: 1000000000/L, 1000.mg. A dot always means multiplication (1.5 means 1 times 5); decimal and scientific-notation literals are not unit factors. Numeric factors must fit u128 and be nonzero. Bare numeric powers such as 2+10 are outside this subset; grouped powers such as (1000)-1 are supported.

Supported atoms:

Family Codes
Dimensionless 1, %, rad, sr
Mass kg, g, mg, ug, ng, pg, fg
Length m, cm, mm, um, nm
Volume L, l, dL, mL, uL, nL, pL
Time s, ms, us, ns, min, h, d, wk, a
Amount of substance mol, mmol, umol, nmol, pmol, fmol
International activity [iU], [IU]
Other base units K, A, cd
Derived SI units Hz, Bq, N, Pa, J, W, C, V, Ohm, S, F, Wb, T, H, lm, lx, Gy, Sv, kat

Use nmol/L, not the unsupported alias nM; use ASCII ug, not µg. Cel and the bare spelling IU are unsupported. International activity uses the explicit bracketed codes [iU] or [IU]; prefixed spellings are not yet supported (use exact integer factors, such as (1000).[iU]). An unknown code returns unknown_unit; incompatible dimensions return unit.

Internally the seven SI dimensions use kg, m, s, mol, K, A, cd. An eighth, opaque international-activity exponent prevents accidental conversion of IU to dimensionless, mass, amount, or catalytic activity quantities. IU is not an SI dimension; this is a stricter internal compatibility rule for procedure-defined units. Ratios of matching activity units cancel and volume/time scale changes remain exact. The model author must ensure activity quantities refer to the same substance and assay: the type checker does not encode assay identity or establish cross-substance equivalence. No automatic conversion to kat or umol/min is provided. See UCUM biomedical units. This is an internal normalization basis, not a claim that UCUM uses the same base-unit convention. Unit scales and conversion ratios are reduced positive rational numbers with 128-bit numerator and denominator. Overflow returns an error. There is no fallback to approximate metadata. Runtime values and inserted conversion constants use finite f64, so numerical results use tolerance comparisons.

Codes are bounded to 256 ASCII bytes, nesting to 16, explicit exponents to ±32, and resulting dimension exponents to ±128. Intermediate rational overflow can reject an otherwise algebraically reducible expression. These are current resource limits, not physical restrictions.

Expression rules

Allometric clearance uses tv_cl * (wt / wt_ref)^0.75 with wt_ref carrying a weight unit. wt / 70 cannot replace a unit-bearing weight reference.

Lowering inserts conversions at symbol loads inside the original expression branches, performs arithmetic in the internal basis, and converts the result to its requested unit. Source limits and dynamic-switch restrictions are checked before lowering. Inserted conversions receive a bounded expanded compiler budget; user expressions cannot opt into that budget. Generated Jacobians differentiate the normalized numeric equations, retaining primal domain checks.

Model binding

UnitCompiledModel is an in-memory lowering API, not the public ModelIR.

The current lower-level Protocol still contains raw numbers. Callers must use model time units, each target's declared dose unit, and state units for absolute error tolerances. The scalar absolute tolerance is a current limitation for heterogeneous state units. A unit-bearing protocol and per-state tolerance contract must be completed before this API becomes the full public model execution surface.

Evidence

Native tests cover exact conversion ratios, dimensional expression failures, explicit molar-mass conversion, allometric scaling, analytic one-compartment bolus/infusion solutions, changed time/state/dose units, bounds, and atomic rebinding. Chrome and Firefox conformance use the same unit-aware expression compiler in WASM. Browser expression checks alone do not qualify unit-bearing ODE model authoring, which still needs the public IR and browser model wrapper.

a denotes the fixed Julian year of exactly 365.25 days (31,557,600 seconds), following the UCUM year definition. It is a duration unit, not a calendar-date operation. Gregorian/tropical years remain outside this implemented subset.