Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

HP-0008 — Auxiliary heat active above lockout with compressor running

Statusverified — engine e2ff2f8, cxf:fnv1a128:8917cda230eb3df1fff05a46442b7cf9, 2026-08-20
Severity2
Methodrule
Phase2
CategoryEXCESS_CONSUMPTION
ConfidenceMEDIUM
EstimationPROXY_ESTIMATION
G36
Clusters
Suppresses
Suppressed by
RelatedHP-0001, HP-0002, HP-0007
Playbooksheat-pump-faults
SourceWinkler and Ramaraj, Field Validation of Air-Source Heat Pumps for Cold Climates, NREL/TP-5500-84745 (2023), Table 5 and note b, p.15 — auxiliary lockout is the maximum OAT for auxiliary operation; observed site values vary; NREL HPXML Data Dictionary v4.0, BackupHeatingLockoutTemperature — backup is disabled above the configured temperature and dual-fuel uses BackupHeatingSwitchoverTemperature; Library-authored executable combination of heating mode, configured OAT lockout, concurrent compressor/auxiliary proof, defrost exclusion, and persistence
Operating statesnormal automatic heat-pump heating when the configured strategy prohibits auxiliary heat above its site-specific lockout while the compressor runs

Preconditions (host-enforced): aux_heat_status must independently prove active heat production by an explicitly classified auxiliary electric, gas, or other source; do not bind demand, command echo, availability, crankcase heat, base-pan heat, or defrost heat. The 5 degC placeholder is adoption-blocking: replace it with the installed balance/lockout strategy for climate, tariff, and equipment. mode_command code 1 must mean heating; comp_status must prove the same applicable compressor scope. OAT must be valid and representative. Exclude defrost, emergency heat, compressor failure/lockout, demand response, commissioning, and explicit high-capacity recovery. On dual-fuel equipment instantiate only when simultaneous compressor/fuel operation above the configured switchover is prohibited. Unmet obligations are NO_EVAL, not healthy.

Points: aux_heat_status, oat, mode_command, defrost_status, comp_status

Outputs:

  • yFault — True after heating mode, above-lockout OAT, concurrent auxiliary/compressor proof, and no defrost persist for sustained_duration
  • yHeatingMode — Diagnostic sub-condition flag; true when mode_command equals heating_mode_code. False never means NO_EVAL
  • yAboveLockout — Diagnostic sub-condition flag; true when OAT is strictly above aux_heat_lockout_oat. False never means NO_EVAL
  • yConcurrentHeat — Diagnostic sub-condition flag; true when auxiliary heat and compressor proofs are both active. False never means NO_EVAL

Parameters:

NameDefaultUnitCXF pathDescription
heating_mode_code11kHeat.kLIBRARY_PRECEDENT host-mapped heating-mode integer. Rebind when the site enumeration differs.
aux_heat_lockout_oat5.0°CaboveLockout.tNO_PORTABLE_DEFAULT and adoption-blocking placeholder. Replace with the installed unit’s commissioned auxiliary lockout or dual-fuel switchover strategy; equality is clear.
sustained_duration300.0spersist.delayTimeADOPTED_TUNABLE continuous signature duration intended to reject brief staging transitions; commission against the OEM sequence.

Description

This rule detects a proven auxiliary heat source operating concurrently with the heat-pump compressor above the configured outdoor lockout in heating mode, outside defrost. It targets prohibited concurrent operation, not emergency heat, required low-temperature supplementation, or balance-point optimization.

Detection Logic

heating_mode   = mode_command == heating_mode_code
above_lockout  = oat > aux_heat_lockout_oat
concurrent_heat = aux_heat_status AND comp_status
candidate = heating_mode AND above_lockout AND concurrent_heat
            AND NOT defrost_status

yHeatingMode = heating_mode
yAboveLockout = above_lockout
yConcurrentHeat = concurrent_heat
yFault = candidate sustained for sustained_duration

HP-0008 block graph

The OAT comparison is strict. Diagnostic outputs are immediate; TrueDelay(delayOnInit=true) applies only to the complete signature. Any false candidate subcondition resets timing and clears a mature alarm.

Possible Diagnoses

  1. Auxiliary lockout or dual-fuel switchover misconfigured or disabled
  2. Staging/thermostat sequence energizes backup heat too early
  3. OAT sensor bias, bad location, stale value, or wrong unit conversion
  4. Auxiliary proof bound to command, availability, or a non-space-heating load
  5. Compressor-capacity fault causing an authorized recovery mode not host-gated
  6. Defrost, emergency, demand-response, or commissioning state omitted from gating

Energy Impact

Unnecessary resistance or fuel backup can displace more efficient compressor heating. Estimate only from verified auxiliary stage input during fault hours, after proving that the installed sequence did not require the extra capacity.

Emissions Impact

Scope 2 applies to electric auxiliary heat and compressor power; Scope 1 can apply to fuel backup. Use measured or nameplate stage input and appropriate time-varying electricity or fuel emissions factors.

Deviations

  • 5 °C is not a portable default. It is an adoption-blocking placeholder; the applicable value is the installed balance/lockout or switchover strategy.
  • Confidence is MEDIUM rather than the brief’s proposed HIGH. Auxiliary role/proof, dual-fuel behavior, site setpoint, and emergency/recovery modes must be established before concurrent operation is avoidable.
  • Auxiliary semantics are provisional. Brick and 223 provide generic heating/status patterns but no exact auxiliary role; topology and independent proof must identify the real supplemental source.
  • Defrost is encoded; other exceptions are host gates. Emergency, failure, demand-response, and recovery state semantics are site-specific.
  • No automatic suppression is added. HP-0007 direction should lead diagnosis, but unexpected compressor proof can leave this concurrent-energy signature valid.
  • No empirical FPR or TPR is claimed. Current datasets do not expose aligned auxiliary-production proof, defrost state, and the configured site lockout.

Test Vectors

14 scenarios, clock step 60 s over 720 s.

ScenarioDescription
cooling_modeConcurrent heat in the cooling code is diagnostically visible but outside the heating-mode candidate.
heating_below_lockoutAuxiliary support below the configured lockout is permitted by this rule.
heating_above_lockout_without_auxiliaryCompressor heating above lockout is healthy when the auxiliary source is inactive.
auxiliary_above_lockout_compressor_offAuxiliary heat without compressor proof may be emergency operation and is not this concurrent-energy signature.
concurrent_heat_above_lockout_sustainedThe complete avoidable-energy signature matures only after persistence.
concurrent_heat_during_defrostDefrost explicitly removes the alarm candidate while leaving diagnostic subconditions visible.
exact_oat_lockout_is_clearThe exact configured OAT threshold is clear under strict greater-than semantics.
unsupported_mode_codeAn unmapped integer mode cannot accidentally satisfy the heating-mode gate.
auxiliary_stage_ends_one_step_before_persistenceAn auxiliary stage ending one evaluator step before 300 s never matures.
mature_fault_recovers_when_auxiliary_clearsA mature alarm clears immediately when the auxiliary source stops producing heat.
two_short_auxiliary_episodes_resetTwo short stages separated by a reset do not accumulate timer age.
initialization_violation_serves_full_delaydelayOnInit prevents an immediate alarm when evaluation starts inside the complete signature.
defrost_interval_resets_candidateA defrost interval between two auxiliary stages resets persistence even though the other subconditions remain true.
emergency_or_recovery_raw_caseThe raw graph alarms on sustained concurrent recovery/emergency heat; the host must exclude an authorized mode.
vectors.json
{
  "schema": "cxf-library/vectors/v1",
  "clock": {
    "step_s": 60,
    "horizon_s": 720
  },
  "scenarios": [
    {
      "name": "cooling_mode",
      "description": "Concurrent heat in the cooling code is diagnostically visible but outside the heating-mode candidate.",
      "inputs": {
        "aux_heat_status": true,
        "oat": 6.0,
        "mode_command": 2,
        "defrost_status": false,
        "comp_status": true
      },
      "expect": [
        {
          "output": "yHeatingMode",
          "from_s": 0,
          "to_s": 720,
          "equals": false
        },
        {
          "output": "yAboveLockout",
          "from_s": 0,
          "to_s": 720,
          "equals": true
        },
        {
          "output": "yConcurrentHeat",
          "from_s": 0,
          "to_s": 720,
          "equals": true
        },
        {
          "output": "yFault",
          "from_s": 0,
          "to_s": 720,
          "equals": false
        }
      ]
    },
    {
      "name": "heating_below_lockout",
      "description": "Auxiliary support below the configured lockout is permitted by this rule.",
      "inputs": {
        "aux_heat_status": true,
        "oat": 4.9,
        "mode_command": 1,
        "defrost_status": false,
        "comp_status": true
      },
      "expect": [
        {
          "output": "yHeatingMode",
          "from_s": 0,
          "to_s": 720,
          "equals": true
        },
        {
          "output": "yAboveLockout",
          "from_s": 0,
          "to_s": 720,
          "equals": false
        },
        {
          "output": "yConcurrentHeat",
          "from_s": 0,
          "to_s": 720,
          "equals": true
        },
        {
          "output": "yFault",
          "from_s": 0,
          "to_s": 720,
          "equals": false
        }
      ]
    },
    {
      "name": "heating_above_lockout_without_auxiliary",
      "description": "Compressor heating above lockout is healthy when the auxiliary source is inactive.",
      "inputs": {
        "aux_heat_status": false,
        "oat": 6.0,
        "mode_command": 1,
        "defrost_status": false,
        "comp_status": true
      },
      "expect": [
        {
          "output": "yHeatingMode",
          "from_s": 0,
          "to_s": 720,
          "equals": true
        },
        {
          "output": "yAboveLockout",
          "from_s": 0,
          "to_s": 720,
          "equals": true
        },
        {
          "output": "yConcurrentHeat",
          "from_s": 0,
          "to_s": 720,
          "equals": false
        },
        {
          "output": "yFault",
          "from_s": 0,
          "to_s": 720,
          "equals": false
        }
      ]
    },
    {
      "name": "auxiliary_above_lockout_compressor_off",
      "description": "Auxiliary heat without compressor proof may be emergency operation and is not this concurrent-energy signature.",
      "inputs": {
        "aux_heat_status": true,
        "oat": 6.0,
        "mode_command": 1,
        "defrost_status": false,
        "comp_status": false
      },
      "expect": [
        {
          "output": "yHeatingMode",
          "from_s": 0,
          "to_s": 720,
          "equals": true
        },
        {
          "output": "yAboveLockout",
          "from_s": 0,
          "to_s": 720,
          "equals": true
        },
        {
          "output": "yConcurrentHeat",
          "from_s": 0,
          "to_s": 720,
          "equals": false
        },
        {
          "output": "yFault",
          "from_s": 0,
          "to_s": 720,
          "equals": false
        }
      ]
    },
    {
      "name": "concurrent_heat_above_lockout_sustained",
      "description": "The complete avoidable-energy signature matures only after persistence.",
      "inputs": {
        "aux_heat_status": true,
        "oat": 6.0,
        "mode_command": 1,
        "defrost_status": false,
        "comp_status": true
      },
      "expect": [
        {
          "output": "yHeatingMode",
          "from_s": 0,
          "to_s": 720,
          "equals": true
        },
        {
          "output": "yAboveLockout",
          "from_s": 0,
          "to_s": 720,
          "equals": true
        },
        {
          "output": "yConcurrentHeat",
          "from_s": 0,
          "to_s": 720,
          "equals": true
        },
        {
          "output": "yFault",
          "from_s": 0,
          "to_s": 240,
          "equals": false
        },
        {
          "output": "yFault",
          "from_s": 360,
          "to_s": 720,
          "equals": true
        }
      ]
    },
    {
      "name": "concurrent_heat_during_defrost",
      "description": "Defrost explicitly removes the alarm candidate while leaving diagnostic subconditions visible.",
      "inputs": {
        "aux_heat_status": true,
        "oat": 6.0,
        "mode_command": 1,
        "defrost_status": true,
        "comp_status": true
      },
      "expect": [
        {
          "output": "yHeatingMode",
          "from_s": 0,
          "to_s": 720,
          "equals": true
        },
        {
          "output": "yAboveLockout",
          "from_s": 0,
          "to_s": 720,
          "equals": true
        },
        {
          "output": "yConcurrentHeat",
          "from_s": 0,
          "to_s": 720,
          "equals": true
        },
        {
          "output": "yFault",
          "from_s": 0,
          "to_s": 720,
          "equals": false
        }
      ]
    },
    {
      "name": "exact_oat_lockout_is_clear",
      "description": "The exact configured OAT threshold is clear under strict greater-than semantics.",
      "inputs": {
        "aux_heat_status": true,
        "oat": 5.0,
        "mode_command": 1,
        "defrost_status": false,
        "comp_status": true
      },
      "expect": [
        {
          "output": "yHeatingMode",
          "from_s": 0,
          "to_s": 720,
          "equals": true
        },
        {
          "output": "yAboveLockout",
          "from_s": 0,
          "to_s": 720,
          "equals": false
        },
        {
          "output": "yConcurrentHeat",
          "from_s": 0,
          "to_s": 720,
          "equals": true
        },
        {
          "output": "yFault",
          "from_s": 0,
          "to_s": 720,
          "equals": false
        }
      ]
    },
    {
      "name": "unsupported_mode_code",
      "description": "An unmapped integer mode cannot accidentally satisfy the heating-mode gate.",
      "inputs": {
        "aux_heat_status": true,
        "oat": 6.0,
        "mode_command": 0,
        "defrost_status": false,
        "comp_status": true
      },
      "expect": [
        {
          "output": "yHeatingMode",
          "from_s": 0,
          "to_s": 720,
          "equals": false
        },
        {
          "output": "yAboveLockout",
          "from_s": 0,
          "to_s": 720,
          "equals": true
        },
        {
          "output": "yConcurrentHeat",
          "from_s": 0,
          "to_s": 720,
          "equals": true
        },
        {
          "output": "yFault",
          "from_s": 0,
          "to_s": 720,
          "equals": false
        }
      ]
    },
    {
      "name": "auxiliary_stage_ends_one_step_before_persistence",
      "description": "An auxiliary stage ending one evaluator step before 300 s never matures.",
      "inputs": {
        "aux_heat_status": [
          {
            "t": 0,
            "value": true
          },
          {
            "t": 240,
            "value": false
          }
        ],
        "oat": 6.0,
        "mode_command": 1,
        "defrost_status": false,
        "comp_status": true
      },
      "expect": [
        {
          "output": "yFault",
          "from_s": 0,
          "to_s": 720,
          "equals": false
        },
        {
          "output": "yConcurrentHeat",
          "from_s": 0,
          "to_s": 180,
          "equals": true
        },
        {
          "output": "yConcurrentHeat",
          "from_s": 240,
          "to_s": 720,
          "equals": false
        }
      ]
    },
    {
      "name": "mature_fault_recovers_when_auxiliary_clears",
      "description": "A mature alarm clears immediately when the auxiliary source stops producing heat.",
      "inputs": {
        "aux_heat_status": [
          {
            "t": 0,
            "value": true
          },
          {
            "t": 420,
            "value": false
          }
        ],
        "oat": 6.0,
        "mode_command": 1,
        "defrost_status": false,
        "comp_status": true
      },
      "expect": [
        {
          "output": "yFault",
          "from_s": 0,
          "to_s": 240,
          "equals": false
        },
        {
          "output": "yFault",
          "from_s": 360,
          "to_s": 360,
          "equals": true
        },
        {
          "output": "yFault",
          "from_s": 420,
          "to_s": 720,
          "equals": false
        },
        {
          "output": "yConcurrentHeat",
          "from_s": 0,
          "to_s": 360,
          "equals": true
        },
        {
          "output": "yConcurrentHeat",
          "from_s": 420,
          "to_s": 720,
          "equals": false
        }
      ]
    },
    {
      "name": "two_short_auxiliary_episodes_reset",
      "description": "Two short stages separated by a reset do not accumulate timer age.",
      "inputs": {
        "aux_heat_status": [
          {
            "t": 0,
            "value": true
          },
          {
            "t": 180,
            "value": false
          },
          {
            "t": 300,
            "value": true
          },
          {
            "t": 480,
            "value": false
          }
        ],
        "oat": 6.0,
        "mode_command": 1,
        "defrost_status": false,
        "comp_status": true
      },
      "expect": [
        {
          "output": "yFault",
          "from_s": 0,
          "to_s": 720,
          "equals": false
        }
      ]
    },
    {
      "name": "initialization_violation_serves_full_delay",
      "description": "delayOnInit prevents an immediate alarm when evaluation starts inside the complete signature.",
      "inputs": {
        "aux_heat_status": true,
        "oat": 6.0,
        "mode_command": 1,
        "defrost_status": false,
        "comp_status": true
      },
      "expect": [
        {
          "output": "yFault",
          "from_s": 0,
          "to_s": 240,
          "equals": false
        },
        {
          "output": "yFault",
          "from_s": 360,
          "to_s": 720,
          "equals": true
        },
        {
          "output": "yHeatingMode",
          "from_s": 0,
          "to_s": 720,
          "equals": true
        },
        {
          "output": "yAboveLockout",
          "from_s": 0,
          "to_s": 720,
          "equals": true
        },
        {
          "output": "yConcurrentHeat",
          "from_s": 0,
          "to_s": 720,
          "equals": true
        }
      ]
    },
    {
      "name": "defrost_interval_resets_candidate",
      "description": "A defrost interval between two auxiliary stages resets persistence even though the other subconditions remain true.",
      "inputs": {
        "aux_heat_status": true,
        "oat": 6.0,
        "mode_command": 1,
        "defrost_status": [
          {
            "t": 0,
            "value": false
          },
          {
            "t": 180,
            "value": true
          },
          {
            "t": 300,
            "value": false
          },
          {
            "t": 480,
            "value": true
          }
        ],
        "comp_status": true
      },
      "expect": [
        {
          "output": "yFault",
          "from_s": 0,
          "to_s": 720,
          "equals": false
        }
      ]
    },
    {
      "name": "emergency_or_recovery_raw_case",
      "description": "The raw graph alarms on sustained concurrent recovery/emergency heat; the host must exclude an authorized mode.",
      "inputs": {
        "aux_heat_status": true,
        "oat": 6.0,
        "mode_command": 1,
        "defrost_status": false,
        "comp_status": true
      },
      "expect": [
        {
          "output": "yFault",
          "from_s": 0,
          "to_s": 240,
          "equals": false
        },
        {
          "output": "yFault",
          "from_s": 360,
          "to_s": 720,
          "equals": true
        },
        {
          "output": "yHeatingMode",
          "from_s": 0,
          "to_s": 720,
          "equals": true
        },
        {
          "output": "yAboveLockout",
          "from_s": 0,
          "to_s": 720,
          "equals": true
        },
        {
          "output": "yConcurrentHeat",
          "from_s": 0,
          "to_s": 720,
          "equals": true
        }
      ]
    }
  ]
}