FAILURE MAP
← Case archive

FA-70946 / Weather index computation / Open access

Shade apparent temperature: wind cooling sign · case 01

Stronger wind makes it feel warmer.

Verified by executionVariant 1 · 8 checks per implementationDownload source bundle ↓JSON ↗

ROOT CAUSE

The wind term is added rather than subtracted.

VERIFIED REPAIR

Subtract 0.70 times wind speed in m/s.

Unsuccessful approach: Restoring the sign but using 0.07 removes most of the wind cooling.

Case contract

Input air temperature degC, RH percent, wind in km/h measured at 10 m. e = RH/100*6.105*exp(17.27*Ta/(237.7+Ta)) hPa; wind in m/s = km/h / 3.6; AT = Ta + 0.33e - 0.70ws - 4.00 rounded to 0.1.

Why this case matters

Feels-like temperature on consumer forecasts uses this non-radiative apparent temperature.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(ta, rh, wind_kmh):
    e = rh / 100.0 * 6.105 * math.exp(17.27 * ta / (237.7 + ta))
    ws = wind_kmh / 3.6
    at = ta + 0.33 * e + 0.70 * ws - 4.00
    return round(at, 1)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['-5 C 10% RH wind 0 km/h', [-5, 10, 0], -8.9], ['-5 C 10% RH wind 10 km/h', [-5, 10, 10], -10.8], ['-5 C 10% RH wind 36 km/h', [-5, 10, 36], -15.9], ['-5 C 10% RH wind 72 km/h', [-5, 10, 72], -22.9], ['-5 C 50% RH wind 0 km/h', [-5, 50, 0], -8.3], ['-5 C 50% RH wind 10 km/h', [-5, 50, 10], -10.2], ['-5 C 50% RH wind 36 km/h', [-5, 50, 36], -15.3], ['-5 C 50% RH wind 72 km/h', [-5, 50, 72], -22.3]], [['-5 C 50% RH wind 10 km/h', [-5, 50, 10], -10.2], ['-5 C 50% RH wind 72 km/h', [-5, 50, 72], -22.3], ['-5 C 90% RH wind 0 km/h', [-5, 90, 0], -7.7], ['-5 C 90% RH wind 10 km/h', [-5, 90, 10], -9.7], ['-5 C 90% RH wind 36 km/h', [-5, 90, 36], -14.7], ['-5 C 90% RH wind 72 km/h', [-5, 90, 72], -21.7], ['0 C 10% RH wind 0 km/h', [0, 10, 0], -3.8], ['0 C 10% RH wind 10 km/h', [0, 10, 10], -5.7]], [['-5 C 90% RH wind 10 km/h', [-5, 90, 10], -9.7], ['0 C 10% RH wind 36 km/h', [0, 10, 36], -10.8], ['0 C 10% RH wind 72 km/h', [0, 10, 72], -17.8], ['0 C 50% RH wind 0 km/h', [0, 50, 0], -3.0], ['0 C 50% RH wind 10 km/h', [0, 50, 10], -4.9], ['0 C 50% RH wind 36 km/h', [0, 50, 36], -10.0], ['0 C 50% RH wind 72 km/h', [0, 50, 72], -17.0], ['0 C 90% RH wind 0 km/h', [0, 90, 0], -2.2]], [['0 C 10% RH wind 10 km/h', [0, 10, 10], -5.7], ['0 C 90% RH wind 10 km/h', [0, 90, 10], -4.1], ['0 C 90% RH wind 36 km/h', [0, 90, 36], -9.2], ['0 C 90% RH wind 72 km/h', [0, 90, 72], -16.2], ['12 C 10% RH wind 0 km/h', [12, 10, 0], 8.5], ['12 C 10% RH wind 10 km/h', [12, 10, 10], 6.5], ['12 C 10% RH wind 36 km/h', [12, 10, 36], 1.5], ['12 C 10% RH wind 72 km/h', [12, 10, 72], -5.5]], [['0 C 50% RH wind 10 km/h', [0, 50, 10], -4.9], ['12 C 50% RH wind 0 km/h', [12, 50, 0], 10.3], ['12 C 50% RH wind 10 km/h', [12, 50, 10], 8.4], ['12 C 50% RH wind 36 km/h', [12, 50, 36], 3.3], ['12 C 50% RH wind 72 km/h', [12, 50, 72], -3.7], ['12 C 90% RH wind 0 km/h', [12, 90, 0], 12.2], ['12 C 90% RH wind 10 km/h', [12, 90, 10], 10.2], ['12 C 90% RH wind 36 km/h', [12, 90, 36], 5.2]]]
for label, args, expected in fixtures[N - 1]:
    check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
-5 C 10% RH wind 0 km/h-8.9-8.9Passed
-5 C 10% RH wind 10 km/h-6.9-10.8Failed
-5 C 10% RH wind 36 km/h-1.9-15.9Failed
-5 C 10% RH wind 72 km/h5.1-22.9Failed
-5 C 50% RH wind 0 km/h-8.3-8.3Passed
-5 C 50% RH wind 10 km/h-6.4-10.2Failed
-5 C 50% RH wind 36 km/h-1.3-15.3Failed
-5 C 50% RH wind 72 km/h5.7-22.3Failed

SHA-256 / 79edee94ef4cc6670293a38aebf3ca05c5e202b4143899f37bdb4f195169f426

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(ta, rh, wind_kmh):
    e = rh / 100.0 * 6.105 * math.exp(17.27 * ta / (237.7 + ta))
    ws = wind_kmh / 3.6
    at = ta + 0.33 * e - 0.07 * ws - 4.00
    return round(at, 1)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['-5 C 10% RH wind 0 km/h', [-5, 10, 0], -8.9], ['-5 C 10% RH wind 10 km/h', [-5, 10, 10], -10.8], ['-5 C 10% RH wind 36 km/h', [-5, 10, 36], -15.9], ['-5 C 10% RH wind 72 km/h', [-5, 10, 72], -22.9], ['-5 C 50% RH wind 0 km/h', [-5, 50, 0], -8.3], ['-5 C 50% RH wind 10 km/h', [-5, 50, 10], -10.2], ['-5 C 50% RH wind 36 km/h', [-5, 50, 36], -15.3], ['-5 C 50% RH wind 72 km/h', [-5, 50, 72], -22.3]], [['-5 C 50% RH wind 10 km/h', [-5, 50, 10], -10.2], ['-5 C 50% RH wind 72 km/h', [-5, 50, 72], -22.3], ['-5 C 90% RH wind 0 km/h', [-5, 90, 0], -7.7], ['-5 C 90% RH wind 10 km/h', [-5, 90, 10], -9.7], ['-5 C 90% RH wind 36 km/h', [-5, 90, 36], -14.7], ['-5 C 90% RH wind 72 km/h', [-5, 90, 72], -21.7], ['0 C 10% RH wind 0 km/h', [0, 10, 0], -3.8], ['0 C 10% RH wind 10 km/h', [0, 10, 10], -5.7]], [['-5 C 90% RH wind 10 km/h', [-5, 90, 10], -9.7], ['0 C 10% RH wind 36 km/h', [0, 10, 36], -10.8], ['0 C 10% RH wind 72 km/h', [0, 10, 72], -17.8], ['0 C 50% RH wind 0 km/h', [0, 50, 0], -3.0], ['0 C 50% RH wind 10 km/h', [0, 50, 10], -4.9], ['0 C 50% RH wind 36 km/h', [0, 50, 36], -10.0], ['0 C 50% RH wind 72 km/h', [0, 50, 72], -17.0], ['0 C 90% RH wind 0 km/h', [0, 90, 0], -2.2]], [['0 C 10% RH wind 10 km/h', [0, 10, 10], -5.7], ['0 C 90% RH wind 10 km/h', [0, 90, 10], -4.1], ['0 C 90% RH wind 36 km/h', [0, 90, 36], -9.2], ['0 C 90% RH wind 72 km/h', [0, 90, 72], -16.2], ['12 C 10% RH wind 0 km/h', [12, 10, 0], 8.5], ['12 C 10% RH wind 10 km/h', [12, 10, 10], 6.5], ['12 C 10% RH wind 36 km/h', [12, 10, 36], 1.5], ['12 C 10% RH wind 72 km/h', [12, 10, 72], -5.5]], [['0 C 50% RH wind 10 km/h', [0, 50, 10], -4.9], ['12 C 50% RH wind 0 km/h', [12, 50, 0], 10.3], ['12 C 50% RH wind 10 km/h', [12, 50, 10], 8.4], ['12 C 50% RH wind 36 km/h', [12, 50, 36], 3.3], ['12 C 50% RH wind 72 km/h', [12, 50, 72], -3.7], ['12 C 90% RH wind 0 km/h', [12, 90, 0], 12.2], ['12 C 90% RH wind 10 km/h', [12, 90, 10], 10.2], ['12 C 90% RH wind 36 km/h', [12, 90, 36], 5.2]]]
for label, args, expected in fixtures[N - 1]:
    check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
-5 C 10% RH wind 0 km/h-8.9-8.9Passed
-5 C 10% RH wind 10 km/h-9.1-10.8Failed
-5 C 10% RH wind 36 km/h-9.6-15.9Failed
-5 C 10% RH wind 72 km/h-10.3-22.9Failed
-5 C 50% RH wind 0 km/h-8.3-8.3Passed
-5 C 50% RH wind 10 km/h-8.5-10.2Failed
-5 C 50% RH wind 36 km/h-9.0-15.3Failed
-5 C 50% RH wind 72 km/h-9.7-22.3Failed

SHA-256 / c230e8f821cb49e6921d958716f47db47d88bcff49a4265b232a9ef17f482e3f

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(ta, rh, wind_kmh):
    e = rh / 100.0 * 6.105 * math.exp(17.27 * ta / (237.7 + ta))
    ws = wind_kmh / 3.6
    at = ta + 0.33 * e - 0.70 * ws - 4.00
    return round(at, 1)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['-5 C 10% RH wind 0 km/h', [-5, 10, 0], -8.9], ['-5 C 10% RH wind 10 km/h', [-5, 10, 10], -10.8], ['-5 C 10% RH wind 36 km/h', [-5, 10, 36], -15.9], ['-5 C 10% RH wind 72 km/h', [-5, 10, 72], -22.9], ['-5 C 50% RH wind 0 km/h', [-5, 50, 0], -8.3], ['-5 C 50% RH wind 10 km/h', [-5, 50, 10], -10.2], ['-5 C 50% RH wind 36 km/h', [-5, 50, 36], -15.3], ['-5 C 50% RH wind 72 km/h', [-5, 50, 72], -22.3]], [['-5 C 50% RH wind 10 km/h', [-5, 50, 10], -10.2], ['-5 C 50% RH wind 72 km/h', [-5, 50, 72], -22.3], ['-5 C 90% RH wind 0 km/h', [-5, 90, 0], -7.7], ['-5 C 90% RH wind 10 km/h', [-5, 90, 10], -9.7], ['-5 C 90% RH wind 36 km/h', [-5, 90, 36], -14.7], ['-5 C 90% RH wind 72 km/h', [-5, 90, 72], -21.7], ['0 C 10% RH wind 0 km/h', [0, 10, 0], -3.8], ['0 C 10% RH wind 10 km/h', [0, 10, 10], -5.7]], [['-5 C 90% RH wind 10 km/h', [-5, 90, 10], -9.7], ['0 C 10% RH wind 36 km/h', [0, 10, 36], -10.8], ['0 C 10% RH wind 72 km/h', [0, 10, 72], -17.8], ['0 C 50% RH wind 0 km/h', [0, 50, 0], -3.0], ['0 C 50% RH wind 10 km/h', [0, 50, 10], -4.9], ['0 C 50% RH wind 36 km/h', [0, 50, 36], -10.0], ['0 C 50% RH wind 72 km/h', [0, 50, 72], -17.0], ['0 C 90% RH wind 0 km/h', [0, 90, 0], -2.2]], [['0 C 10% RH wind 10 km/h', [0, 10, 10], -5.7], ['0 C 90% RH wind 10 km/h', [0, 90, 10], -4.1], ['0 C 90% RH wind 36 km/h', [0, 90, 36], -9.2], ['0 C 90% RH wind 72 km/h', [0, 90, 72], -16.2], ['12 C 10% RH wind 0 km/h', [12, 10, 0], 8.5], ['12 C 10% RH wind 10 km/h', [12, 10, 10], 6.5], ['12 C 10% RH wind 36 km/h', [12, 10, 36], 1.5], ['12 C 10% RH wind 72 km/h', [12, 10, 72], -5.5]], [['0 C 50% RH wind 10 km/h', [0, 50, 10], -4.9], ['12 C 50% RH wind 0 km/h', [12, 50, 0], 10.3], ['12 C 50% RH wind 10 km/h', [12, 50, 10], 8.4], ['12 C 50% RH wind 36 km/h', [12, 50, 36], 3.3], ['12 C 50% RH wind 72 km/h', [12, 50, 72], -3.7], ['12 C 90% RH wind 0 km/h', [12, 90, 0], 12.2], ['12 C 90% RH wind 10 km/h', [12, 90, 10], 10.2], ['12 C 90% RH wind 36 km/h', [12, 90, 36], 5.2]]]
for label, args, expected in fixtures[N - 1]:
    check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
-5 C 10% RH wind 0 km/h-8.9-8.9Passed
-5 C 10% RH wind 10 km/h-10.8-10.8Passed
-5 C 10% RH wind 36 km/h-15.9-15.9Passed
-5 C 10% RH wind 72 km/h-22.9-22.9Passed
-5 C 50% RH wind 0 km/h-8.3-8.3Passed
-5 C 50% RH wind 10 km/h-10.2-10.2Passed
-5 C 50% RH wind 36 km/h-15.3-15.3Passed
-5 C 50% RH wind 72 km/h-22.3-22.3Passed

SHA-256 / 2c5326c695f0a4664a65b5a92f56ba4ee02630b275fd0ca145c11a792a09feb5

Verification & scope

Stipulated deterministic teaching model of an operational weather index; coefficients and thresholds are fixed by the contract and no claim of standards conformance is made. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.

Observations recorded using Python 3.12.14 at 2026-09-29T14:48:25.360598+00:00.

Case digest / 23bf7057befce9211e758957bd734166c1209184c3194cb6909b92d1bb88dbca