G-003 · REV 2 · CHECKED 2026-10-09 · MODEL v1.0.2 ▾
Drafted with AI assistance. Numbers computed by model v1.0.2 or sourced. Human review: pending (BayHeat editorial desk). Licensed review: not applicable.
Technical review: no page-specific licensed approval recorded.
M measured · C computed · S spec · R reference · E estimate
Methodology
Every number the planner shows traces back to one of the formulas on this page. There's no sales pressure here — no buy links, no product picks — just the load calculation, the warm-up model, the grade formula and the circuit-sizing rule, worked on BayHeat's standard example: a 24×24 ft attached two-car garage in Chicago, R-13 walls, one uninsulated steel door, average drafts, held at 55°F.
The load calculation: conduction
Walls, garage doors, windows and the service door each lose heat by conduction: assembly U-value (BTU/h per ft² per °F) times area times the indoor/outdoor temperature difference (ΔT). At Chicago's Computed by our engineEXAMPLE_A_STATION.h99Report a problem 99%-design temperature and a 55°F target, ΔT is Computed by our engineheatLossDesign(EXAMPLE_A_INPUT) — lib/planner/heatLoss.tsReport a problem. The garage door alone, at U-1.15 for an uninsulated steel door, accounts for Computed by our engineheatLossDesign(EXAMPLE_A_INPUT).items — lib/planner/heatLoss.tsReport a problem of the design load.
Infiltration
Air leaking through gaps around doors, windows and the building envelope follows Q = 0.018 × V × ACH × ΔT, where V is the garage's volume in ft³ and ACH is the design-condition air changes per hour for its tightness class (Computed by our engineTIGHTNESS_ACH.tight — lib/planner/constants.tsReport a problem tight to Computed by our engineTIGHTNESS_ACH.very_leaky — lib/planner/constants.tsReport a problem very leaky). The constant also carries an altitude correction, since colder, denser air at sea level infiltrates at a different rate than the same volumetric flow at elevation — Chicago's Computed by our engineEXAMPLE_A_STATION.elevFtReport a problem gives a factor of Computed by our enginealtitudeFactor(elevationFt) — lib/planner/climate.tsReport a problem (1.0 at sea level; Denver's 5,414 ft works out to about 0.82). At "average" tightness, this garage's infiltration load comes to Computed by our engineheatLossDesign(EXAMPLE_A_INPUT).itemsReport a problem.
The ceiling: attic as a series resistance
A vented attic doesn't sit at either the indoor or the outdoor temperature. It floats in between, set by the ceiling's insulation on one side and the roof deck plus attic ventilation on the other. The model treats this as two resistances in series: the ceiling's own UA (insulation) and the attic-to- outdoors UA (roof deck conduction plus Computed by our engineATTIC_VENT_ACH — lib/planner/constants.tsReport a problem of attic air changes per hour), combined as UA_ceiling_eff = 1 / (1/UA_ceiling + 1/UA_attic-out). That combined UA times ΔT gives the ceiling load — for this garage, Computed by our engineheatLossDesign(EXAMPLE_A_INPUT).itemsReport a problem, the single largest line on the chart above. The same calculation yields an intermediate attic temperature — Computed by our engineheatLossDesign(EXAMPLE_A_INPUT).atticTempFReport a problem on this garage's design day — that a flat, non-series model can't produce, and that a blown-in ceiling upgrade changes directly.
Slab-edge loss
Heat leaving through an uninsulated slab doesn't scale with floor area. It scales with the exposed perimeter, because the loss concentrates at the edge where the slab meets outdoor air. The model uses an F-factor (BTU/h per linear ft of edge per °F), not a U-value times area: Q = F × L_ext × ΔT. L_ext is the exterior perimeter, with any common (house) wall excluded. An uninsulated edge runs about F = Computed by our engineSLAB_F.none — lib/planner/constants.tsReport a problem; edge insulation (R-10 to R-20, 24-48 in deep) roughly cuts that F-factor in half or better.
Warm-up: thermal capacitance and a 1-minute simulation
"How long until it hits 55°F" is a different question from the design load. It needs a different model: a lightweight thermal-capacitance simulation, not a steady-state formula. The garage's light mass — framing, drywall, the air itself, plus whatever's stored inside — is lumped into one capacitance figure — Computed by our enginelightCapacitance(EXAMPLE_A_INPUT, elevationFt) — lib/planner/warmup.tsReport a problem for this garage — and the slab is modeled separately as a semi-infinite solid that only slowly gives up or absorbs heat at its exposed surface. The simulation steps forward in 1-minute increments (an explicit Euler step), each minute adding the heater's output and subtracting the current heat loss, divided by the capacitance, to get the next minute's temperature. Starting from this garage's free-float temperature on an average January day — Computed by our enginefreeFloatTemp(EXAMPLE_A_INPUT, envelope, tJan, ...) — lib/planner/heatLoss.tsReport a problem — a 10 kW class heater reaches 55°F in about Computed by our enginesimulateSession() — lib/planner/warmup.tsReport a problem.
BayGrade: a climate-independent envelope score
BayGrade answers a different question than the design load does: not "how much heat does this garage lose in Chicago," but "how leaky is this envelope, independent of climate." It's the exterior-coupled UA (every term except the house-wall coupling) divided by floor area — UA_ext / A_floor — evaluated at any single ΔT, since UA itself doesn't depend on temperature. This garage comes out to Computed by our engineheatLossDesign(EXAMPLE_A_INPUT).uaExtPerFt2 — gradeFor() in lib/planner/heatLoss.tsReport a problem, which lands in grade Computed by our enginegradeFor(uaExtPerFt2)Report a problem.
- Grade A: UA_ext/A_floor ≤ 0.38
- Grade B: ≤ 0.62
- Grade C: ≤ 0.90
- Grade D: ≤ 1.25
- Grade F: above 1.25
Sizing margin
The recommended capacity (qSize) is the design load (qDesign) times a Computed by our engineSIZING_MARGIN — lib/planner/constants.tsReport a problem margin — Computed by our engineheatLossDesign(EXAMPLE_A_INPUT).qDesignReport a problem becomes Computed by our engineheatLossDesign(EXAMPLE_A_INPUT).qSizeReport a problem (Computed by our engineheatLossDesign(EXAMPLE_A_INPUT).kwSizeReport a problem) — so the heater isn't sized to its exact worst-case load with zero headroom.
Circuit sizing (NEC)
A fixed electric heater is a continuous load under A code or reference citationNFPA 70, National Electrical Code, 2023 · checked 2026-09-25Report a problem, so the conductors and breaker are sized at 125% of the heater's running current, not the bare nameplate current. A 10 kW class heater at 240V draws about Computed by our enginecircuitFor(watts, 240, 240) — lib/planner/electrical.tsReport a problem running, Computed by our enginecircuitFor(watts, 240, 240)Report a problem at 125%, which rounds up to the next standard breaker: Computed by our enginecircuitFor(watts, 240, 240)Report a problem with 4 AWG copper (NM) or 6 AWG copper (THHN in conduit). A cord-and-plug heater on a shared receptacle circuit follows a different rule instead — A code or reference citationNFPA 70, National Electrical Code, 2023 · checked 2026-09-25Report a problem caps it at 80% of the branch rating. Your electrician and your local code edition govern.
Try it on your garage
Every formula above runs the same way on your own dimensions, insulation and local design temperature — not just the worked example on this page.
Related
Planner
A ZIP code and five taps give you the heat load, the heater that fits, the breaker it needs, the cost per hour and the warm-up time — with every formula shown.
Shop heaters
Compare 240V electric, vented gas and diesel shop heaters by circuit, vent and CO rule, and see why a torpedo heater doesn't belong in a closed shop.
Can I Run It?
Pick your heater and your situation. Get a GO, GO-IF or NO-GO verdict with the exact code section behind it — not a guess.
The Lab
Pre-registered tests, each with its prediction published before we measure. No claimed test without a published log.
Sources
- [1] NFPA 70, National Electrical Code, 2023, NFPA. Retrieved 2026-09-25.