Power & Resistance Measurement: a Metrology Walkthrough
This tutorial is a full metrological worked example of measuring the electrical power dissipated in a precision resistor and assessing conformity of the resistor against its nominal value. It ties GUM methodology (JCGM 100:2008) to VIM vocabulary (JCGM 200:2012) and shows how the SymbolicUncertainties.jl API fits the calibration-certificate workflow end-to-end.
Unlike the single-section summaries in Worked Examples, this page walks through a complete uncertainty budget, coverage-interval construction, conformity assessment, and reporting — the sequence a calibration lab would follow in practice.
VIM terms used in this tutorial
| VIM § | Term | Role here |
|---|---|---|
| 2.3 | Measurand | The quantities we want — R (resistance of the device under test) and P (power dissipated). |
| 2.10 | Measured quantity value | The numerical result of the measurement — R_meas, P_meas. |
| 2.11 | Nominal quantity value | The rated / stamped value R₀ = 100 Ω (E96 series). |
| 2.16 | Measurement error | R_meas − R₀ (unknown exactly; bounded by uncertainty). |
| 2.26 | Measurement uncertainty u(y) | Standard uncertainty on the result. |
| 2.35 | Coverage probability | Here p = 0.95, i.e. 95 % confidence. |
| 2.36 | Coverage interval | The interval y ± U, where U = k · u(y). |
| 2.37 | Coverage factor | k = 2 for p ≈ 0.95 under a normal distribution (GUM §6.3.3). |
| 4.17 | Conformity assessment | Decision: is the device within its specification limits? |
| 4.18 | Calibration certificate | The reporting artifact — see final section. |
For full VIM definitions see JCGM 200:2012; this tutorial paraphrases only.
Scenario
A calibration lab receives a precision resistor rated at R₀ = 100 Ω (an E96 series value) with a manufacturer tolerance of ±0.1 %. The lab applies a stable voltage source and measures both voltage across and current through the resistor using calibrated instruments:
- Voltmeter across the resistor — reading
V = 10.000 VwithσV = 0.001 V(1 mV standard uncertainty). - Ammeter in series — reading
I = 0.100 02 AwithσI = 1.0 × 10⁻⁵ A(10 μA standard uncertainty).
The lab needs to deliver:
P— power dissipated, with uncertaintyu(P).R_meas— resistance inferred from Ohm's law, with uncertaintyu(R).- A conformity assessment — is
R_measconsistent withR₀ = 100 Ωat 95 % coverage?
Inputs are treated as independent (no correlated drift between the voltmeter and ammeter readings) — a standard JCGM 100:2008 §5.1.2 eq (10) setup.
Build the measurement models
using SymbolicUncertainties
using SymbolicUncertainties: ±
using Symbolics
using DynamicQuantities
# Symbolic inputs — values and standard uncertainties
@variables V I σV σI
# Model 1: power P = V · I
P = propagate((v, i) -> v * i, [V ± σV, I ± σI])
# P.val = V * I
# P.err = sqrt((I·σV)² + (V·σI)²) — uncorrelated-inputs form
# Model 2: resistance R = V / I
R = propagate((v, i) -> v / i, [V ± σV, I ± σI])
# R.val = V / I
# R.err = sqrt((σV/I)² + (V·σI/I²)²)\[V / I \pm sqrt(((1 / I)^2)*(σV^2) + (((-V) / (I^2))^2)*(σI^2))\]
propagate is used (rather than the binary * / / operators) because the underlying sensitivity analysis is explicit and the result is guaranteed to collapse repeated symbolic-variable occurrences — see Sensitivity Analysis.
Power budget
P_rows = uncertainty_budget(P, [V, I], [σV, σI])
# An UncertaintyBudget of 2 rows — one per input.
# Columns: variable, sigma, sensitivity, contribution,
# relative (fraction of variance).Uncertainty budget (EA-4/02 §7.3) for y = I*V
V: u = σV c = I |c|u = abs(I)*σV
I: u = σI c = V |c|u = abs(V)*σI
u_c = sqrt((I^2)*(σV^2) + (V^2)*(σI^2))Each row follows the GUM §5.1.6 / EA-4/02 §7.3 schema. Substituting numerics:
readings = Dict(
V => 10.000us"V", σV => 1e-3us"V",
I => 0.10002us"A", σI => 1e-5us"A",
)
# Several calls below rank or substitute plain numbers, so the same
# readings are also kept stripped.
dict = Dict(k => ustrip(v) for (k, v) in readings)
# The unit of the answer is derived from the model, not asserted:
# volts times amperes is watts, and nothing here had to say so.
evaluate(P, readings)(val = 1.0002 A V, err = 0.0001414354990799693 A V)Dominant source:
dominant = dominant_source(P, [V, I], [σV, σI];
values = dict)
# → returns `V` or `I`; in this setup they contribute
# nearly equally (1.00e-8 each), so the dominant source
# depends on tie-breaking.(index = 1, variable = V, contribution = abs(I)*σV, ranked_by = :numeric)This is a balanced budget — a deliberate choice in the scenario design. Real calibration work usually reveals one dominant source on which to focus improvements.
Resistance budget
R_rows = uncertainty_budget(R, [V, I], [σV, σI])
# Volts over amperes is ohms — again derived, not stated:
evaluate(R, readings)(val = 99.98000399920016 A⁻¹ V, err = 0.014137894184807242 A⁻¹ V)Coverage interval (VIM §2.36)
Expand u(R) to a coverage interval with k = 2 (p ≈ 0.95, assuming approximate normality per GUM §6.3.3):
R_expanded = expanded_uncertainty(R, 2)
# R_expanded.val = R.val (unchanged)
# R_expanded.U = 2 · R.err
R_exp_num = Symbolics.substitute(R_expanded, dict)
# R_exp_num.val ≈ 99.98 Ω
# R_exp_num.U ≈ 2 · 14 mΩ ≈ 28 mΩV / I ± 2sqrt(((1 / I)^2)*(σV^2) + (((-V) / (I^2))^2)*(σI^2)) (k = 2)The coverage interval is therefore [99.98 − 0.028, 99.98 + 0.028] Ω = [99.952, 100.008] Ω.
Conformity assessment (VIM §4.17)
Question: is R_meas = 99.98 Ω consistent with R₀ = 100 Ω at 95 % coverage?
R₀ = 100.0
lower = R_exp_num.val - R_exp_num.U
upper = R_exp_num.val + R_exp_num.U
pass = lower ≤ R₀ ≤ upper
# → true : R₀ = 100 ∈ [99.952, 100.008] ✓Result: R₀ lies inside the 95 % coverage interval, so the resistor is consistent with its nominal value at the 95 % level. The calibration certificate reports R = 99.98 Ω ± 0.028 Ω (k = 2, p ≈ 0.95) and the conformity status PASS.
Counter-example — a failing conformity check
Suppose instead the ammeter reading had been I = 0.10050 A (a 0.48 % drift):
dict_fail = Dict(k => ustrip(v) for (k, v) in Dict(
V => 10.000us"V", σV => 1e-3us"V",
I => 0.10050us"A", σI => 1e-5us"A",
))
R_fail = Symbolics.substitute(R_expanded, dict_fail)
# R_fail.val ≈ 99.502 Ω
# R_fail.U ≈ 28 mΩ (roughly unchanged)
# coverage interval: [99.474, 99.530]
lower_f = R_fail.val - R_fail.U
upper_f = R_fail.val + R_fail.U
pass_f = lower_f ≤ R₀ ≤ upper_f
# → false : R₀ = 100 ∉ [99.474, 99.530] ✗Result: the measured resistance is inconsistent with the nominal value at 95 % coverage. The certificate reports NON-CONFORM and the device is tagged for adjustment or rejection.
Reporting (GUM §7 + VIM §4.18)
A calibration-certificate-ready summary block:
function report(label, m, k)
v = Symbolics.value(Symbolics.substitute(m.val, Dict()))
u = Symbolics.value(Symbolics.substitute(m.err, Dict()))
# (in practice m is already fully substituted — the
# `substitute(_, Dict())` round-trip is just defensive)
println(label, " = ", round(v, sigdigits = 5),
" ± ", round(k*u, sigdigits = 3),
" (k = ", k, ", coverage ≈ ",
k == 2 ? "95 %" : "…", ")")
end
report("P", P_num, 2)
# P = 1.0002 ± 2.83e-4 (k = 2, coverage ≈ 95 %)
report("R", R_num, 2)
# R = 99.98 ± 2.83e-2 (k = 2, coverage ≈ 95 %)Certificate excerpt (human-readable):
Device under test: precision resistor, nominal
R₀ = 100.000 Ω(E96 series).Conditions:
T = 23.0 °C, applied voltageV_applied ≈ 10 V.Result:
R = 99.98 Ω ± 0.028 Ω(k = 2, coverage ≈ 95 %).P = 1.0002 W ± 0.00028 W(k = 2, coverage ≈ 95 %).Dominant uncertainty sources: voltmeter reading and ammeter reading contribute approximately equally (~50 % each).
Conformity: PASS —
R₀ = 100 Ωlies within the 95 % coverage interval[99.952, 100.008] Ω.Method: JCGM 100:2008 §5.1.2 eq (10), uncorrelated inputs; software implementation:
SymbolicUncertainties.jlv0.10.0.
What this tutorial demonstrates
- Symbolic propagation is calibration-ready. Every intermediate expression in this walkthrough is symbolic until the final
Symbolics.substitute, giving the lab a traceable derivation of the final number. - VIM vocabulary maps cleanly to the API: measurand →
SymbolicMeasurement.val, measurement uncertainty →.err, coverage interval →expanded_uncertainty(m, k), dominant source →dominant_source(...). - Conformity assessment is a downstream consumer of the coverage interval — the library provides the interval; the decision logic (
R₀ ∈ [y-U, y+U]) is two lines of user code. - Paraphrase-only — no normative JCGM / VIM text is reproduced in the library or this tutorial. Section numbers are cited to anchor the methodology; the authoritative document is JCGM 100:2008 / JCGM 200:2012 itself.
References
- JCGM 100:2008 — Evaluation of measurement data — Guide to the expression of uncertainty in measurement (GUM). BIPM. See
CITATION.bibat the repository root for the BibTeX entry. - JCGM 200:2012 — International vocabulary of metrology — Basic and general concepts and associated terms (VIM), 3rd edition. BIPM.
- EA-4/02 M:2022 — Evaluation of the Uncertainty of Measurement in Calibration. European co-operation for Accreditation.
- For the full methodology reference of every
SymbolicUncertainties.jlexport, see Methodology Reference. - For the six quick worked examples (Ohm, voltage divider, RC time constant, dissipated power, RLC resonance, RC-charge ODE), see Worked Examples.