PaceWise Calculators Get the app

The PaceWise race projection model

Every algorithm PaceWise uses to turn a runner's results into projected race times, age grades, splits and pacing plans, in mathematical terms, with the constants and the sources.

Edition 1, June 2026. Published here 16 September 2026. Open for review.

Most race predictors take one result and one textbook curve. The PaceWise model (section 3) blends every result a runner has logged, each with its distance, time and date, into a personal projection band at the target distance: it fits the runner's own fatigue exponent, weights each result by how recent it is and how close its distance sits to the target, and widens the band when the evidence disagrees or has to stretch far. It is closed-form, deterministic, runs offline, and reduces to Riegel when the data can only support that.

The classical single-result models (section 2), the pacing curve (section 4) and WMA age grading (section 5) are specified alongside it so the whole calculation surface can be checked as one. This page is written for a reader with a sports-science or applied-maths background who wants to check the formulas against the literature. Corrections are welcome: support@doughworks.dev.

Notation. Times are in seconds (t), distances in metres (d), pace in seconds per metre. ln is the natural logarithm. All models are pure, deterministic and offline. Non-positive or non-finite inputs raise a typed error rather than returning NaN or infinity (section 6).

Contents

  1. Foundations: the pace identity
  2. Classical race-equivalence models
  3. The PaceWise model
  4. Pacing-plan curve
  5. WMA age grading
  6. Numerical-safety contract
  7. How it is checked
  8. Constants at a glance
  9. The goal-readiness verdict

1Foundations: the pace identity

All elementary conversions are the single identity

t = p · d          p = t / d          d = t / p          v = 1 / p

with t seconds, d metres, p seconds per metre and v metres per second. Display units (min/km, min/mile) are applied at the surface; the core is unit-free canonical SI. There is nothing to validate here beyond dimensional consistency and the guard rails of section 6. It is listed because every higher model reduces to it.

Session aggregate. For segments (ti, di) the total is T = Σti, D = Σdi, average pace T/D. Each segment must be individually positive: a negative leg is rejected, never allowed to cancel another into a plausible total.

2Classical race-equivalence models

Given one known performance (t₁, d₁), predict the time t₂ at a target distance d₂. PaceWise offers three textbook models so a runner can cross-check; they are also the fallback whenever only a single result exists. A fourth option (2.4) applies the same single-result form with the runner's own fitted exponent. It belongs in this section rather than section 3 because it too is a pure function of one performance. The race time predictor runs the three textbook models side by side.

2.1Riegel power law

Peter Riegel's endurance model (Riegel, American Scientist, 1981):

t₂ = t₁ · (d₂ / d₁)^k

k is the fatigue exponent. k = 1 would mean pace is independent of distance; real endurance running has k > 1 because sustainable pace fades as distance grows. The literature value, and the default here, is k = 1.06: the canonical exponent for roughly 1.5 km to 42.2 km and the constant behind most public race predictors.

Cross-check. A 20:00 5K (1200 s) to 10K gives 1200 · 2^1.06 = 2502 s = 41:42, matching Omnicalculator's race predictor and The Running Genie to the second.

2.2Cameron model

David Cameron's fitted model is steadier than Riegel over long extrapolations. With distances in miles (d̃ = d / 1609.344):

t₂ = (t₁ / d̃₁) · d̃₂ · a(d̃₁) / a(d̃₂)
a(x) = 13.49681 − 0.048865·x + 2.438936 / x^0.7905

a(x) is an empirical per-mile cost curve. It crosses zero near 277 miles (about 446 km); beyond that the fit is meaningless, so the model rejects the target rather than return a negative or spuriously positive time.

Cross-check. 20:00 5K to 10K under Cameron is 2499.66 s (about 41:40), within half a second of the closed-form value, and within 5% of Riegel on a one-octave extrapolation.

2.3Daniels & Gilbert VDOT

A VO₂-based physiological model (Daniels & Gilbert, 1979). For a race of d metres in t seconds, let m = t/60 minutes and velocity v = d/m in metres per minute:

VO₂(v)        = −4.60 + 0.182258·v + 0.000104·v²        (oxygen cost of pace)
%sustainable  = 0.8 + 0.1894393·e^(−0.012778·m)
                    + 0.2989558·e^(−0.1932605·m)        (fraction of VO₂max held)
VDOT(d, t)    = VO₂(v) / %sustainable

The runner's VDOT is fixed by the known race. The equivalent time at the target is the t₂ that reproduces that same VDOT. VDOT(d₂, ·) is monotonically decreasing in time over the positive-VO₂ region. VO₂(v) goes negative below about 25 m/min (a 6.7-hour 10K), so strict global monotonicity fails only at implausibly slow paces well outside any real target. Within the region every real target occupies the root is unique, so it is found by bisection over [1 s, 86 400 s]: 100 halvings, far below the 1 µs tolerance. A target whose equivalent falls outside the 24-hour bracket is rejected rather than silently saturated. The VDOT calculator shows both equations with a worked example.

Cross-checks. From a 22:00 5K (VDOT about 45, per Jack Daniels' tables): 10K about 45:40 (2740 s, ±15 s), half marathon about 1:40:30 (6030 s, ±60 s), marathon about 3:30:00 (12 600 s, ±30 s).

2.4PaceWise per-result equivalence

The equivalent-times surface offers the PaceWise model in the same single-result form as the three textbook models: the plain power law

t₂ = t₁ · (d₂ / d₁)^k

with k the runner's fitted, trust-shrunk fatigue exponent of 3.1, fitted once from the full per-distance frontier and then applied to the one result being converted. A runner with fewer than two distinct distances gets the Riegel default k = 1.06, so the option degrades to 2.1 exactly. Unlike the three formulas, the conversion carries a band: the stance α ∈ [−1, +1] sweeps

t₂(α) = t₂ · exp(−α · σ),     σ = min( σ_min + β · |ln(d₂/d₁)|,  σ_max )

which is the 3.4 width with the variance term identically zero. A single result cannot disagree with itself, so only the extrapolation floor (σ_min = 0.01, β = 0.015, capped at σ_max = 0.10) contributes, and the band is log-symmetric exactly as in 3.4.

The proven-best floor of 3.5 is deliberately absent here. Equivalence describes one result: what that run is worth at another distance, a pure function of it. The floor's job is to keep a projection of the runner from contradicting proof. Flooring the equivalence would re-couple every result's table to the whole stored history, exactly the blending this per-result form exists to avoid. When the runner's stored best at the target already beats the conversion, the apps draw the comparison beside the number (a "Your PB" badge) instead of folding it in.

The supplied exponent is rejected if non-finite, never silently defaulted, then defensively clamped to the physiological [1.02, 1.15] range of 3.1.

Validation. From the device-reported fixture of 3.1 (5K 1331 s, 10K 2733 s, half 6594 s, aged 61, 61 and 75 days) the fit gives k ≈ 1.0677, and the half converts to a 10K of 2971.6 s, about 49:32 (stance ±1 gives 48:29 and 50:35). Deliberately not floored at the stored 45:33 10K. The test suite also pins that k = 1.06 reproduces 2.1 verbatim, that the band is log-symmetric (t(−1)·t(+1) = t(0)²), the single-result fallback, the exponent clamp, the band ceiling under extreme stretch, and the section 6 rejection cases.

Reviewer note. The three textbook models are intentionally redundant; the suite asserts they sit within 5% of one another on a one-octave extrapolation. Divergence grows with extrapolation distance, which is exactly the motivation for the PaceWise model.

3The PaceWise model

The contribution. Where section 2 extrapolates from a single performance, PaceWise blends every result a runner has logged, each with its distance, time and optional date, into a personalised projection band at the target, swept by an aggressiveness stance. It is fully closed-form (no iteration), deterministic, and reduces gracefully to Riegel when the data can only support that.

Inputs: a set of results {(ti, di, ai)}, where ai is the result's age in days before the reference date (ai < 0 means undated); a target distance D; and an aggressiveness stance α ∈ [−1, +1]. Output: a projected time at D.

The model has three stages, plus a proven-best floor on the output (3.5).

3.1Stage 1: the personal fatigue exponent

Rather than assume Riegel's k = 1.06, PaceWise fits the runner's own k from the slope of ln t against ln d. Taking logs of the power law t = c·d^k gives the linear relation

ln t = ln c + k · ln d,

so k is the slope of a least-squares line through the runner's results in log-log space. Two refinements:

  1. Per-distance frontier. Only each distinct distance's fastest result is fitted (group by rounded metres, keep the minimum time), so slow repeats of one distance do not masquerade as fatigue.
  2. Recency weighting. Each frontier point carries the fit weight wifit = r(ai), the recency decay of 3.2, so the slope tracks current fitness. Stages 2 and 3 use a different weight wiblend, recency × proximity; the two are kept distinct deliberately.

The weighted least-squares slope is

        Σ wᵢ^fit (xᵢ − x̄)(yᵢ − ȳ)
k =  ──────────────────────────────  ,   xᵢ = ln dᵢ,  yᵢ = ln tᵢ,
            Σ wᵢ^fit (xᵢ − x̄)²

with weighted means x̄ = Σwᵢ^fit·xᵢ / Σwᵢ^fit and ȳ = Σwᵢ^fit·yᵢ / Σwᵢ^fit.

Fallbacks and clamps.

Fit-quality shrinkage. A slope that survives the guards above is still only trusted as far as the frontier actually agrees on it. Let k_ls be the raw least-squares slope (before the clamp) and define the fit's weighted residual variance in log-time,

v = Σ wᵢ^fit · ( (yᵢ − ȳ) − k_ls·(xᵢ − x̄) )² / Σ wᵢ^fit ,

the scatter of the frontier about the line the fit actually drew. The clamped slope is then shrunk toward the Riegel default in proportion to that scatter:

trust = τ / (τ + v),        τ = 10⁻⁴,
k     = 1.06 + trust · ( clamp(k_ls, 1.02, 1.15) − 1.06 ).

τ is the residual variance at which the personal slope earns exactly half trust; in log-time, v = 10⁻⁴ corresponds to residual scatter of about 1% in time. No re-clamp is needed: the result interpolates two values already inside [1.02, 1.15]. Three properties matter for review:

The motivation: wᵢ^fit is recency-only, so unlike the blend, whose proximity factor (3.3) halves a far result's vote per distance-doubling, a lone far-distance result enters the slope fit at nearly full weight, and because the exponent is shared by every candidate it can drag the entire blend, unopposed. In the device-reported case that motivated the mechanism, one weak half marathon beside a consistent 5K and 10K steepened k to 1.112 and pushed the raw 10K blend 61 s slower than the runner's proven 10K. Under shrinkage that frontier's scatter (v ≈ 5.8·10⁻⁴) earns the fitted slope only 0.15 trust, k settles at 1.068, and the projection recovers a usable band (the 3.5 floor still pins the likely time at the proven best).

The fitted exponent is also exposed on its own, the identical value the blend fits internally, so the per-result equivalence of 2.4 converts through the same personal profile the projection uses.

Validation. Three results placed exactly on a k = 1.10 law project a fourth distance back onto that law to a relative error below 10⁻⁹ (an exact law has v ≈ 0, so shrinkage leaves it alone). Separate cases exercise the implausible exponent clamp, the repeats-of-one-distance and near-identical-distance fallbacks, and the scale-invariant variance threshold. The shrinkage is pinned by the device-reported shape above (a lone weak outlier no longer collapses the same-distance band), by two-distance frontiers keeping full trust, by a lone strong outlier still speeding the projection (the correction is symmetric, not slow-biased), and by the trust decision surviving a common ageing of the results.

3.2Recency weighting

A result's vote decays exponentially with age, half-life H = 180 days:

r(a) = exp(−ln2 · a / H),     a = aᵢ if aᵢ ≥ 0 and finite, else H.

So a six-month-old result counts half as much as today's. An undated result is pinned at exactly one half-life: kept as evidence at half a vote, but unable to outvote a fresh dated result. The aᵢ ≥ 0 guard folds a future-dated result (negative age relative to the reference date) into the same undated bucket; the two are indistinguishable to the model, which is acceptable since a future race date is not a meaningful input here.

Why 180 and not 365. Fitness moves on a months-to-seasons timescale, but a one-year half-life let evidence a runner had visibly outgrown keep a third to a half of the blend. A 17-month-old half marathon still held 36% of the vote at its own distance, and a runner mid-breakthrough had months of gains averaged against the form they started with. Halving H corrects those without touching a runner whose results agree with each other, and it strengthens the mirror case: where a fresh same-distance result genuinely is the best evidence, its share rises from 69% to 78%. Reweighting by distance instead was measured and rejected.

Why not shorter. Below roughly 120 days the model begins projecting long races from short-distance speed alone while simultaneously narrowing the band, because a dominant single candidate has nothing left to disagree with it. A sharp 5K and 10K pair six months on from a real 3:45 marathon projects 2:58 at a 60-day half-life: 47 minutes faster than the runner has ever raced, in a band 20 minutes tighter than the current one. That is the confident-nonsense failure the σ_min + β·s̄ floor (3.4) exists to prevent, and the half-life must not undo it. 180 days sits with room on both sides.

3.3Stage 2: evidence blending (the likely time)

Every result is projected to the target D through the personal power law, in log-time space, where race times compose multiplicatively, so the natural average is geometric and the band is symmetric. Define each candidate's log-time and its weight:

sᵢ = ln(D / dᵢ)                        (the "stretch": log-distance to target)
ŷᵢ = ln tᵢ + k · sᵢ                    (result i's projection of D, in log-time)
wᵢ^blend = r(aᵢ) · exp(−|sᵢ|)          (recency × distance-proximity)

This blend weight is distinct from the fit weight wᵢ^fit of 3.1: the fit tracks fitness over time (recency only), while the blend additionally trusts nearby races more. The proximity factor exp(−|sᵢ|) means a result one distance-doubling away carries half the vote of one at the target distance. Near evidence dominates far evidence. The likely log-time is the weighted mean

μ = Σ wᵢ^blend·ŷᵢ / Σ wᵢ^blend,

and the likely time is exp(μ): a recency- and proximity-weighted geometric mean of the individual projections.

Sanity. A single result at the target returns itself exactly; a single result off target reduces to plain Riegel at 1.06. Recency dominance, the reduced vote of undated results, and proximity dominance are each pinned by a test.

3.4Stage 3: the stance band

The weighted spread of the candidates measures how much the runner's own evidence disagrees about D:

σ² = Σ wᵢ^blend·(ŷᵢ − μ)² / Σ wᵢ^blend     (weighted variance of the log-projections)

This is floored by an uncertainty that grows with how far the evidence had to extrapolate, and capped so a wildly disagreeing set still yields a usable band:

s̄ = Σ wᵢ^blend·|sᵢ| / Σ wᵢ^blend          (mean stretch)
σ = min( max( √σ²,  σ_min + β · s̄ ),  σ_max )    (floor first, then ceiling)
σ_min = 0.01   (±1 % floor at zero extrapolation)
β     = 0.015  (extra half-width per unit of |ln(D/d)|)
σ_max = 0.10   (±10 % ceiling)

The floor-then-ceiling order is load-bearing. Past s̄ = (σ_max − σ_min)/β = 6, reachable only by extreme extrapolation (a 100 m result projected to the marathon has s̄ = ln(421.95) ≈ 6.05), the floor σ_min + β·s̄ exceeds the ceiling σ_max, and the outer min pins σ to σ_max. A three-argument clamp(value, lo, hi) with lo > hi is undefined (it would throw), so an implementation must apply the ceiling last, not nest the two bounds.

The stance α sweeps the band log-symmetrically:

t(α) = exp( μ − α · σ ),     α ∈ [−1, +1]  (clamped; non-finite ⇒ 0).

α = 0 is the likely time, α = −1 conservative (slower), α = +1 aggressive (faster). Because the sweep is linear in log-time, the band is symmetric in the multiplicative sense:

t(−1) · t(+1) = t(0)²              (conservative × aggressive = likely²)

Validation. The identity above is pinned to relative 10⁻⁶. Further cases pin that conservative is slower and aggressive faster, that the stance clamps beyond the band, that a non-finite stance reads as likely, that the band widens with extrapolation (5K to marathon wider than 5K to 10K), and the floor-versus-ceiling inversion at extreme extrapolation (100 m to marathon). The log-symmetry identity holds while the proven-best floor (3.5) is slack; when the floor binds it wins.

3.5The proven-best floor

The blend can produce a projection at a distance the runner has already raced that is slower than their own supplied best at that distance. A fresh 10K PB beside a comparatively weak half marathon drags the blended 10K projection below the proof. The fit-quality shrinkage of 3.1 bounds the exponent channel of that drag; the direct blend pull of the weak result remains, so the floored case still arises. Mathematically defensible (the other evidence genuinely argues current endurance is worse), but as a product number it undermines trust: "you'll likely run 49:49" under a just-logged 49:16 reads as a bug, not a nuance. So the model floors its output at the fastest supplied result at the target distance:

t_final(α) = min( t(α),  min{ tᵢ : |ln(D / dᵢ)| ≤ 10⁻⁴ } )

Properties:

Downstream the floor is a projection concept: the goal-readiness verdict (Appendix B) grades against the floored likely time, and the race surfaces publish the floored blend. The equivalent-times table does not consume the blend. It converts the single result on screen (2.4) and is deliberately unfloored there, the cross-result comparison being the UI's badge to draw. The pacing-plan curve (section 4) is untouched: it shapes a chosen goal time and never consumes the projection.

Validation. Tests pin the headline case (blend slower than a fresh 10K PB returns the PB), the slack direction (a slower same-distance best leaves the blend untouched), no off-distance leakage, the conservative edge of the band, and the 21 097.5 versus 21 098 m match.

3.6Design rationale

ChoiceWhy
Log-time space throughoutRace times scale multiplicatively; a geometric mean and a log-symmetric band are the natural, scale-invariant operations.
Personal k, clamped and trust-shrunkHonours the runner's own fatigue signature when the data supports it, never leaves the physiological envelope or trusts an ill-conditioned fit, and hands a scattered fit back toward Riegel rather than letting one off-line result steepen every candidate.
Recency half-life 180 daysFitness drifts on a months-to-seasons timescale. Half a season keeps stale PBs as weak priors without letting them dominate, and is short enough that evidence a runner has outgrown actually fades (3.2).
Proximity exp(−|s|)A 5K is weak evidence for a marathon. Weighting by log-distance encodes "trust nearby races more" without a hard cutoff.
Variance-driven band, floored by extrapolationThe band should widen both when the runner's results disagree and when the model extrapolates far, capturing both kinds of uncertainty in one width.

Known limitations and open questions for review.

4Pacing-plan curve

A pacing plan distributes a goal time T across the race with a signed bias s (negative split versus positive split). With f the fraction of distance covered, the fraction of goal time elapsed is

E(f, s) = f · (1 + s · (1 − f)),     s ∈ [−0.06, +0.06].

Properties the maths guarantees, for any |s| < 1:

s is clamped to ±0.06 (±6% peak deviation from even pace) so a generated plan stays physically sensible. Cumulative split times are T · E(dm/D, s) at each marker dm; the final row lands on T by construction. The pace band generator prints this curve.

5WMA age grading

Age grading normalises a performance against the world-best standard for the athlete's age and sex, using the World Masters Athletics (WMA) 2020 factor tables (compiled by Alan Jones; encoded by the Runalyze age-grade project, CC BY 4.0). For a time t over distance d by an athlete of given age and sex, with age factor φ ≤ 1 and open-class standard S (both read from the tables, linearly interpolated across the 28 standard distances):

age-graded time  = t · φ            (the open-class-equivalent "aged-up" time)
age-grade %      = (S / φ) / t · 100.

S/φ is the age standard: the world-best time expected at that age. Ages outside the table's 5 to 100 range are clamped; distances outside the table's columns use the nearest column outright (no extrapolation). The factor tables are machine-generated for every platform from one upstream fetch, so the apps and the age grade calculator cannot drift.

This section is strictly descriptive (it reports against a published standard). The only thing to validate is faithful table reproduction and correct interpolation, both unit-tested against published values.

6Numerical-safety contract

Every entry point enforces the same discipline, which a reviewer can rely on:

7How it is checked

The numbers quoted in the cross-check and validation boxes above are not illustrations. Each is a case in the core's test suite, which runs on every change on both the JVM and native targets. The apps call the same core, and the web calculators on this site run a line-by-line port of it that a build check re-tests against the core's own cases before anything deploys. A formula on this page, the number in the app, and the number in the browser cannot disagree without that check failing.

If you find a formula, constant or citation here that is wrong, or a case the model handles badly, email support@doughworks.dev. The core and its tests are the authoritative reference; this page follows them, and a correction that lands there will be reflected here with a new edition line.

AConstants at a glance

SymbolValueMeaning
k (default)1.06Riegel fatigue exponent, and the PaceWise fallback
k range[1.02, 1.15]physiological clamp on the fitted exponent
H180 daysrecency half-life (and the assumed age of undated results)
σ_min0.01band half-width floor (about ±1%)†
β0.015extra band half-width per unit of log-distance extrapolated
σ_max0.10band half-width ceiling (about ±10%)†
min weighted log-variance10⁻⁴below this (distances within about 2%) the exponent fit is abandoned
τ (exponent fit trust)10⁻⁴weighted residual variance of ln t at which the fitted exponent earns half trust (shrunk toward 1.06)
same-distance tolerance10⁻⁴|ln(D/d)| within this counts as the distance for the proven-best floor
pacing bias s[−0.06, +0.06]±6% peak deviation from even pace
VDOT bracket[1 s, 86 400 s], 100 stepsbisection domain and precision
Cameron domaina(x) > 0 (below about 277 mi)fitted-curve validity

† The ±x% gloss is a first-order reading of the log-space half-width σ. The band is exactly symmetric multiplicatively, not linearly: σ = 0.10 spans exp(±0.10), which is +10.5% / −9.5%, not a literal ±10%. The percentages are a convenient linear approximation for small σ.

BThe goal-readiness verdict

A small helper grades a goal against the model's likely projection. Both are first rounded to whole seconds, the precision every surface displays, so the verdict cannot contradict the shown numbers:

likely ≤ goal              → achievable
goal < likely ≤ goal·1.05  → ambitious   (within 5 %)
likely > goal·1.05         → stretch

Citing this page

doughworks (2026). The PaceWise race projection model, edition 1. https://pacewise.doughworks.dev/model. The formulas and constants are free to reproduce with a link back; the WMA factor tables carry their own CC BY 4.0 attribution to Alan Jones and the Runalyze project.

The model, running on your results

PaceWise is the free app this maths was built for. Log your races and it projects every distance from all of them, with the band and the stance described above. Offline, no account.

Get PaceWise for iPhone