Version: dev

FireHeatFlux

Sensible and latent heat flux density released by burning fuel, per Eqs. 4–5 of Mandel et al. (2011). Migrated from WildlandFire.jl@126976f2 src/level_set_fire_spread.jl:295 (`FireHeatFlux` @component). Observed-only: fuel_burn_rate, w_l, h_fuel, M_f are inputs (parameters); phi_h and phi_q are algebraic outputs.

.esm schema
1.0.0
Source
components/wildland_fire/level_set/fire_heat_flux.esm

Description

Sensible and latent heat flux density released by burning fuel, per Eqs. 4–5 of Mandel et al. (2011). Migrated from WildlandFire.jl@126976f2 src/level_set_fire_spread.jl:295 (FireHeatFlux @component). Observed-only: fuel_burn_rate, w_l, h_fuel, M_f are inputs (parameters); phi_h and phi_q are algebraic outputs.

Reference

_source_ref: WildlandFire.jl@126976f2508ceacca6c486b21ae6da5b168c6f46:src/level_set_fire_spread.jl:295 Upstream FireHeatFlux is an MTK @component whose three driving inputs (w_l, h_fuel, M_f) are @parameters, whose fuel_burn_rate(t) is a @variables driven externally (in the parent system, the FuelConsumption component supplies it as is_burning*F/T_f, the magnitude of -dF/dt), and whose two outputs (phi_h, phi_q) are time-indexed @variables defined by the two algebraic equations. The standalone .esm here folds fuel_burn_rate into the parameter set so the component is well-posed without a parent — matching the pattern used elsewhere in the rig (see components/aerosol/aq_eq/water.esm and components/wildland_fire/rothermel/live_fuel_moisture_extinction.esm) where externally-driven @variables and @constants are unified into ESM parameter declarations. The three upstream @constants (one=1.0, water_combustion_ratio=0.56, L_water=2.5e6) are likewise preserved as parameters with the upstream defaults.

The equations are the Mandel et al. (2011) closed-form sensible/latent heat flux densities: phi_h = fuel_burn_rate * w_l * h_fuel / (one + M_f) (Eq. 4) phi_q = fuel_burn_rate * (M_f + water_combustion_ratio) / (one + M_f) * L_water * w_l (Eq. 5) — preserved verbatim (the ordering of the multiplications inside phi_q matches the upstream Julia source so float64 roundoff is bit-identical).

Tolerance rationale (model-level rel=1e-12): observed-only algebraic system (no ODE integration); both equations are short chains of multiply/divide on hardware-supported intrinsics, so float64 roundoff is at the ULP level (~1e-15). 1e-12 is comfortably above that and below any plausible physical-discrimination scale on heat-flux quantities (the hand-computed tests span ~1e2 to ~1e5 W/m^2; the fire_behavior cells below reach ~1.7e6 W/m^2). The four fire_behavior_* tests override this with a test-level rel=1e-5, because their expected values were written by a single-precision (real32) Fortran build; re-evaluating eqs 4-5 in float64 on the same real32 inputs reproduces them to within 8e-7 relative.

fire_behavior_* tests (shared provenance). Reference: NCAR’s Community Fire Behavior Model (fire_behavior, develop @ eb77580, the WRF-Fire/SFIRE physics of WRF 4.8’s phys/fire_behavior submodule; default real32 build, gfortran 13.3 -O2), running its own tests/test7 case (real Colorado domain, 80x80 fire cells of 25 m, dt = 0.5 s, num_tiles = 1). Values were dumped in-model by the ctessum-claude/fire_behavior fork (branch earthsciml-instrumented, c9dda02, -DESM_DUMP=ON; the instrumented run’s summary output is bit-identical to the uninstrumented build). Calc_fire_fluxes (physics/fire_physics_mod.F90) computes grnhft = (dmass/dt)(1 - bmst) CMBCNST and grnqft = (bmst + (1 - bmst) 0.56)(dmass/dt) XLV with dmass = fuel_load_g fuel_frac_burnt_dt and bmst = M/(1 + M). Since 1 - bmst = 1/(1 + M_f) and bmst + (1 - bmst) 0.56 = (M_f + 0.56)/(1 + M_f), these are algebraically identical to eqs 4-5 as written here, with fuel_burn_rate = fuel_frac_burnt_dt/dt, w_l = fuel_load_g (the Anderson category load), h_fuel = CMBCNST = 1.7433e7 J/kg (fire_behavior’s value, not this component’s 1.8608e7 default), M_f = fmc_g, water_combustion_ratio = 0.56 and L_water = XLV = 2.5e6 J/kg; the overrides carry the real32 values as stored. test7 has a uniform fmc_g = 0.08, so every dumped cell has the same phi_q/phi_h = (M_f + 0.56) L_water / h_fuel = 0.0918; the dumped cells therefore check the product fuel_burn_rate * w_l and the constants, and fire_behavior_constants_moist_fuel holds the moisture dependence under fire_behavior’s constants. fire_behavior is the WRF-Fire physics used by EqWeFiC (https://github.com/EarthSciML/EqWeFiC) , whose PLAN.md item 1.3 added these tests._

Parameters

NameUnitsDefaultDescription
fuel_burn_rate1/s0.0Rate of fuel consumption (-dF/dt); driven externally by FuelConsumption in the coupled system
w_lkg/m^20.166Total fuel load (Anderson fuel model 1 default)
h_fuelJ/kg18608000.0Heat content of dry fuel (Anderson 1982 / WRF-SFIRE Table 1: 8000 BTU/lb = 1.8608e7 J/kg)
M_f10.08Fuel moisture content (dimensionless mass fraction)
one11.0Unity dimensionless constant (preserved from upstream MTK @constants for unit-balancing)
water_combustion_ratio10.56Estimated mass ratio of water output from combustion to dry fuel (Mandel et al. 2011)
L_waterJ/kg2500000.0Latent heat of condensation of water at 0°C (Mandel et al. 2011)

Observed

NameUnitsDefaultDescription
phi_hW/m^2Sensible heat flux density
phi_qW/m^2Latent heat (moisture) flux density

Observed expressions

$$ phi_{h} = \frac{fuel_{burn\,rate} \cdot w_{l} \cdot h_{fuel}}{one + M_{f}} $$

Sensible heat flux density

$$ phi_{q} = fuel_{burn\,rate} \cdot \frac{M_{f} + water_{combustion\,ratio}}{one + M_{f}} \cdot L_{water} \cdot w_{l} $$

Latent heat (moisture) flux density

Analyses

phi_h_vs_M_f_sweep

Sweep M_f over the realistic atmospheric range (0 to 0.5) at fixed fuel_burn_rate, w_l, h_fuel. Surfaces the (1 + M_f)⁻¹ damping of the sensible heat flux as fuel moisture rises — the dominant qualitative feature of Mandel et al. (2011) Eq. 4.

Time span: 0.0 → 1.0

Swept over: M_f

Sensible heat flux as a function of fuel moisture content.

Latent heat flux as a function of fuel moisture content — increases with M_f because the (M_f + 0.56) numerator dominates over the (1 + M_f) denominator at low M_f.

phi_h_heatmap_burn_rate_w_l

Two-dimensional sweep over (fuel_burn_rate, w_l) at fixed h_fuel and M_f. Both fluxes are bilinear in (fbr, w_l), so the surface should be a smooth product map — useful for visual sanity-checking the equation structure.

Time span: 0.0 → 1.0

Swept over: fuel_burn_rate, w_l

Sensible heat flux as a function of fuel burn rate and fuel load.

Raw .esm

Raw .esm JSON (this component)
{
  "reference": {
    "notes": "source_ref: WildlandFire.jl@126976f2508ceacca6c486b21ae6da5b168c6f46:src/level_set_fire_spread.jl:295\nUpstream `FireHeatFlux` is an MTK `@component` whose three driving inputs (w_l, h_fuel, M_f) are `@parameters`, whose `fuel_burn_rate(t)` is a `@variables` driven externally (in the parent system, the FuelConsumption component supplies it as is_burning*F/T_f, the magnitude of -dF/dt), and whose two outputs (phi_h, phi_q) are time-indexed `@variables` defined by the two algebraic equations. The standalone .esm here folds `fuel_burn_rate` into the parameter set so the component is well-posed without a parent — matching the pattern used elsewhere in the rig (see components/aerosol/aq_eq/water.esm and components/wildland_fire/rothermel/live_fuel_moisture_extinction.esm) where externally-driven `@variables` and `@constants` are unified into ESM `parameter` declarations. The three upstream `@constants` (one=1.0, water_combustion_ratio=0.56, L_water=2.5e6) are likewise preserved as parameters with the upstream defaults.\n\nThe equations are the Mandel et al. (2011) closed-form sensible/latent heat flux densities:\n  phi_h = fuel_burn_rate * w_l * h_fuel / (one + M_f)             (Eq. 4)\n  phi_q = fuel_burn_rate * (M_f + water_combustion_ratio) / (one + M_f) * L_water * w_l   (Eq. 5)\n— preserved verbatim (the ordering of the multiplications inside phi_q matches the upstream Julia source so float64 roundoff is bit-identical).\n\nTolerance rationale (model-level rel=1e-12): observed-only algebraic system (no ODE integration); both equations are short chains of multiply/divide on hardware-supported intrinsics, so float64 roundoff is at the ULP level (~1e-15). 1e-12 is comfortably above that and below any plausible physical-discrimination scale on heat-flux quantities (the hand-computed tests span ~1e2 to ~1e5 W/m^2; the fire_behavior cells below reach ~1.7e6 W/m^2). The four fire_behavior_* tests override this with a test-level rel=1e-5, because their expected values were written by a single-precision (real32) Fortran build; re-evaluating eqs 4-5 in float64 on the same real32 inputs reproduces them to within 8e-7 relative.\n\nfire_behavior_* tests (shared provenance). Reference: NCAR's Community Fire Behavior Model (fire_behavior, develop @ eb77580, the WRF-Fire/SFIRE physics of WRF 4.8's phys/fire_behavior submodule; default real32 build, gfortran 13.3 -O2), running its own tests/test7 case (real Colorado domain, 80x80 fire cells of 25 m, dt = 0.5 s, num_tiles = 1). Values were dumped in-model by the ctessum-claude/fire_behavior fork (branch earthsciml-instrumented, c9dda02, -DESM_DUMP=ON; the instrumented run's summary output is bit-identical to the uninstrumented build). Calc_fire_fluxes (physics/fire_physics_mod.F90) computes grnhft = (dmass/dt)(1 - bmst) CMBCNST and grnqft = (bmst + (1 - bmst) 0.56)(dmass/dt) XLV with dmass = fuel_load_g fuel_frac_burnt_dt and bmst = M/(1 + M). Since 1 - bmst = 1/(1 + M_f) and bmst + (1 - bmst) 0.56 = (M_f + 0.56)/(1 + M_f), these are algebraically identical to eqs 4-5 as written here, with fuel_burn_rate = fuel_frac_burnt_dt/dt, w_l = fuel_load_g (the Anderson category load), h_fuel = CMBCNST = 1.7433e7 J/kg (fire_behavior's value, not this component's 1.8608e7 default), M_f = fmc_g, water_combustion_ratio = 0.56 and L_water = XLV = 2.5e6 J/kg; the overrides carry the real32 values as stored. test7 has a uniform fmc_g = 0.08, so every dumped cell has the same phi_q/phi_h = (M_f + 0.56) L_water / h_fuel = 0.0918; the dumped cells therefore check the product fuel_burn_rate * w_l and the constants, and fire_behavior_constants_moist_fuel holds the moisture dependence under fire_behavior's constants. fire_behavior is the WRF-Fire physics used by EqWeFiC (https://github.com/EarthSciML/EqWeFiC), whose PLAN.md item 1.3 added these tests."
  },
  "tolerance": {
    "rel": 1e-12
  },
  "variables": {
    "fuel_burn_rate": {
      "type": "parameter",
      "units": "1/s",
      "default": 0.0,
      "description": "Rate of fuel consumption (-dF/dt); driven externally by FuelConsumption in the coupled system"
    },
    "w_l": {
      "type": "parameter",
      "units": "kg/m^2",
      "default": 0.166,
      "description": "Total fuel load (Anderson fuel model 1 default)"
    },
    "h_fuel": {
      "type": "parameter",
      "units": "J/kg",
      "default": 18608000.0,
      "description": "Heat content of dry fuel (Anderson 1982 / WRF-SFIRE Table 1: 8000 BTU/lb = 1.8608e7 J/kg)"
    },
    "M_f": {
      "type": "parameter",
      "units": "1",
      "default": 0.08,
      "description": "Fuel moisture content (dimensionless mass fraction)"
    },
    "one": {
      "type": "parameter",
      "units": "1",
      "default": 1.0,
      "description": "Unity dimensionless constant (preserved from upstream MTK @constants for unit-balancing)"
    },
    "water_combustion_ratio": {
      "type": "parameter",
      "units": "1",
      "default": 0.56,
      "description": "Estimated mass ratio of water output from combustion to dry fuel (Mandel et al. 2011)"
    },
    "L_water": {
      "type": "parameter",
      "units": "J/kg",
      "default": 2500000.0,
      "description": "Latent heat of condensation of water at 0°C (Mandel et al. 2011)"
    },
    "phi_h": {
      "type": "unknown",
      "units": "W/m^2",
      "description": "Sensible heat flux density"
    },
    "phi_q": {
      "type": "unknown",
      "units": "W/m^2",
      "description": "Latent heat (moisture) flux density"
    }
  },
  "equations": [
    {
      "lhs": "phi_h",
      "rhs": {
        "op": "/",
        "args": [
          {
            "op": "*",
            "args": [
              "fuel_burn_rate",
              "w_l",
              "h_fuel"
            ]
          },
          {
            "op": "+",
            "args": [
              "one",
              "M_f"
            ]
          }
        ]
      }
    },
    {
      "lhs": "phi_q",
      "rhs": {
        "op": "*",
        "args": [
          "fuel_burn_rate",
          {
            "op": "/",
            "args": [
              {
                "op": "+",
                "args": [
                  "M_f",
                  "water_combustion_ratio"
                ]
              },
              {
                "op": "+",
                "args": [
                  "one",
                  "M_f"
                ]
              }
            ]
          },
          "L_water",
          "w_l"
        ]
      }
    }
  ],
  "tests": [
    {
      "id": "zero_burn_rate",
      "description": "No fuel burning (fuel_burn_rate = 0). Both fluxes vanish independent of w_l, h_fuel, M_f. Sanity check that the algebraic prefactor is correctly multiplicative.",
      "parameter_overrides": {
        "fuel_burn_rate": 0.0,
        "w_l": 0.5,
        "h_fuel": 18600000.0,
        "M_f": 0.08
      },
      "time_span": {
        "start": 0.0,
        "end": 1.0
      },
      "assertions": [
        {
          "variable": "phi_h",
          "time": 0.0,
          "expected": 0.0,
          "tolerance": {
            "abs": 1e-15
          }
        },
        {
          "variable": "phi_q",
          "time": 0.0,
          "expected": 0.0,
          "tolerance": {
            "abs": 1e-15
          }
        }
      ]
    },
    {
      "id": "dry_fuel_M_f_zero",
      "description": "Dry fuel (M_f = 0). Eq. 4 simplifies to phi_h = fuel_burn_rate * w_l * h_fuel; Eq. 5 to phi_q = fuel_burn_rate * water_combustion_ratio * L_water * w_l. fbr=1e-3, w_l=1, h=1.86e7 → phi_h = 18600, phi_q = 0.56 * 2.5e6 * 1e-3 = 1400.",
      "parameter_overrides": {
        "fuel_burn_rate": 0.001,
        "w_l": 1.0,
        "h_fuel": 18600000.0,
        "M_f": 0.0
      },
      "time_span": {
        "start": 0.0,
        "end": 1.0
      },
      "assertions": [
        {
          "variable": "phi_h",
          "time": 0.0,
          "expected": 18600.0
        },
        {
          "variable": "phi_q",
          "time": 0.0,
          "expected": 1400.0000000000002
        }
      ]
    },
    {
      "id": "moist_fuel_clean_arithmetic",
      "description": "Moderate moisture (M_f = 0.1) with fbr=2e-3, w_l=2, h=1.86e7. phi_h = 2e-3·2·1.86e7 / 1.1 = 74400 / 1.1 = 67636.36…; phi_q = 2e-3·0.66/1.1·2.5e6·2 = 6600/1.1 = 6000 (exact rational).",
      "parameter_overrides": {
        "fuel_burn_rate": 0.002,
        "w_l": 2.0,
        "h_fuel": 18600000.0,
        "M_f": 0.1
      },
      "time_span": {
        "start": 0.0,
        "end": 1.0
      },
      "assertions": [
        {
          "variable": "phi_h",
          "time": 0.0,
          "expected": 67636.36363636363
        },
        {
          "variable": "phi_q",
          "time": 0.0,
          "expected": 5999.999999999999
        }
      ]
    },
    {
      "id": "saturated_moisture_M_f_one",
      "description": "Saturated fuel (M_f = 1.0). The (one + M_f) denominator becomes 2; phi_h is halved relative to the dry case. fbr=1e-3, w_l=1, h=2e7 → phi_h = 1e-3·1·2e7/2 = 10000; phi_q = 1e-3·1.56/2·2.5e6·1 = 1950.",
      "parameter_overrides": {
        "fuel_burn_rate": 0.001,
        "w_l": 1.0,
        "h_fuel": 20000000.0,
        "M_f": 1.0
      },
      "time_span": {
        "start": 0.0,
        "end": 1.0
      },
      "assertions": [
        {
          "variable": "phi_h",
          "time": 0.0,
          "expected": 10000.0
        },
        {
          "variable": "phi_q",
          "time": 0.0,
          "expected": 1950.0000000000002
        }
      ]
    },
    {
      "id": "low_load_high_burn",
      "description": "Low fuel load (w_l=0.5) with fast burn rate (fbr=5e-3), light moisture (M_f=0.05), reduced heat content (h=1.0e7). phi_h = 5e-3·0.5·1.0e7/1.05 = 25000/1.05 = 23809.52…; phi_q = 5e-3·0.61/1.05·2.5e6·0.5 = 3812.5/1.05 = 3630.95….",
      "parameter_overrides": {
        "fuel_burn_rate": 0.005,
        "w_l": 0.5,
        "h_fuel": 10000000.0,
        "M_f": 0.05
      },
      "time_span": {
        "start": 0.0,
        "end": 1.0
      },
      "assertions": [
        {
          "variable": "phi_h",
          "time": 0.0,
          "expected": 23809.52380952381
        },
        {
          "variable": "phi_q",
          "time": 0.0,
          "expected": 3630.9523809523816
        }
      ]
    },
    {
      "id": "anderson_fuel_1_grass",
      "description": "Representative grass-fuel scenario per Anderson (1982) fuel model 1 / Mandel et al. (2011) Table 1: w_l=0.166 kg/m², h=1.8608e7 J/kg (8000 BTU/lb), M_f=0.08 (8% moisture), fbr=1/119 s⁻¹ (T_f=119 s, F=1, is_burning=1). phi_h = (1/119)·0.166·1.8608e7/1.08 ≈ 24034.6 W/m²; phi_q ≈ 2066.6 W/m² — order of magnitude matches Mandel et al. (2011) §3.2.",
      "parameter_overrides": {
        "fuel_burn_rate": 0.008403361344537815,
        "w_l": 0.166,
        "h_fuel": 18608000.0,
        "M_f": 0.08
      },
      "time_span": {
        "start": 0.0,
        "end": 1.0
      },
      "assertions": [
        {
          "variable": "phi_h",
          "time": 0.0,
          "expected": 24034.60939931528
        },
        {
          "variable": "phi_q",
          "time": 0.0,
          "expected": 2066.604419545596
        }
      ]
    },
    {
      "id": "ratio_phi_q_over_phi_h",
      "description": "Cross-check the Mandel et al. (2011) ratio identity: phi_q / phi_h = (M_f + water_combustion_ratio) * L_water / h_fuel — independent of fuel_burn_rate and w_l. Pick fbr=4e-3, w_l=1.5, h=1.5e7, M_f=0.2. phi_h = 4e-3·1.5·1.5e7/1.2 = 90000/1.2 = 75000 exact; phi_q = 4e-3·0.76/1.2·2.5e6·1.5 = 11400/1.2 = 9500 exact; ratio = 9500/75000 = 0.7600/6.0 = 0.12666… = 0.76·2.5e6/1.5e7 ✓.",
      "parameter_overrides": {
        "fuel_burn_rate": 0.004,
        "w_l": 1.5,
        "h_fuel": 15000000.0,
        "M_f": 0.2
      },
      "time_span": {
        "start": 0.0,
        "end": 1.0
      },
      "assertions": [
        {
          "variable": "phi_h",
          "time": 0.0,
          "expected": 75000.0
        },
        {
          "variable": "phi_q",
          "time": 0.0,
          "expected": 9500.000000000002
        }
      ]
    },
    {
      "id": "fire_behavior_step20_strongest_cell_cat2",
      "description": "Strongest burning cell of the dump: (i,j) = (17, 62) at step 20, fuel category 2 (w_l = 0.896 kg/m^2). Expected phi_h, phi_q are fire_behavior's grnhft, grnqft at that cell (real32, hence rel 1e-5); provenance and the eqs 4-5 identity are in the model reference notes.",
      "parameter_overrides": {
        "fuel_burn_rate": 0.11735081672668457,
        "w_l": 0.8960000276565552,
        "h_fuel": 17433000.0,
        "M_f": 0.07999999821186066,
        "L_water": 2500000.0,
        "water_combustion_ratio": 0.5600000023841858
      },
      "time_span": {
        "start": 0.0,
        "end": 1.0
      },
      "tolerance": {
        "rel": 1e-05
      },
      "assertions": [
        {
          "variable": "phi_h",
          "time": 0.0,
          "expected": 1697237.0
        },
        {
          "variable": "phi_q",
          "time": 0.0,
          "expected": 155772.34375
        }
      ]
    },
    {
      "id": "fire_behavior_step20_cat2_cell",
      "description": "A second fuel-category-2 cell (w_l = 0.896 kg/m^2): (i,j) = (18, 64) at step 20. Expected phi_h, phi_q are fire_behavior's grnhft, grnqft at that cell (real32, hence rel 1e-5); provenance and the eqs 4-5 identity are in the model reference notes.",
      "parameter_overrides": {
        "fuel_burn_rate": 0.10704100131988525,
        "w_l": 0.8960000276565552,
        "h_fuel": 17433000.0,
        "M_f": 0.07999999821186066,
        "L_water": 2500000.0,
        "water_combustion_ratio": 0.5600000023841858
      },
      "time_span": {
        "start": 0.0,
        "end": 1.0
      },
      "tolerance": {
        "rel": 1e-05
      },
      "assertions": [
        {
          "variable": "phi_h",
          "time": 0.0,
          "expected": 1548126.875
        },
        {
          "variable": "phi_q",
          "time": 0.0,
          "expected": 142087.03125
        }
      ]
    },
    {
      "id": "fire_behavior_step20_weak_edge_cell_cat1",
      "description": "Weakly burning cell at the fire edge, fuel category 1 (w_l = 0.166 kg/m^2): (i,j) = (26, 64) at step 20. Expected phi_h, phi_q are fire_behavior's grnhft, grnqft at that cell (real32, hence rel 1e-5); provenance and the eqs 4-5 identity are in the model reference notes.",
      "parameter_overrides": {
        "fuel_burn_rate": 0.0007721185684204102,
        "w_l": 0.16599999368190765,
        "h_fuel": 17433000.0,
        "M_f": 0.07999999821186066,
        "L_water": 2500000.0,
        "water_combustion_ratio": 0.5600000023841858
      },
      "time_span": {
        "start": 0.0,
        "end": 1.0
      },
      "tolerance": {
        "rel": 1e-05
      },
      "assertions": [
        {
          "variable": "phi_h",
          "time": 0.0,
          "expected": 2068.904541015625
        },
        {
          "variable": "phi_q",
          "time": 0.0,
          "expected": 189.88397216796875
        }
      ]
    },
    {
      "id": "fire_behavior_step10_early_cell_cat1",
      "description": "Early burning cell, fuel category 1 (w_l = 0.166 kg/m^2): (i,j) = (19, 61) at step 10. Expected phi_h, phi_q are fire_behavior's grnhft, grnqft at that cell (real32, hence rel 1e-5); provenance and the eqs 4-5 identity are in the model reference notes.",
      "parameter_overrides": {
        "fuel_burn_rate": 0.0662459135055542,
        "w_l": 0.16599999368190765,
        "h_fuel": 17433000.0,
        "M_f": 0.07999999821186066,
        "L_water": 2500000.0,
        "water_combustion_ratio": 0.5600000023841858
      },
      "time_span": {
        "start": 0.0,
        "end": 1.0
      },
      "tolerance": {
        "rel": 1e-05
      },
      "assertions": [
        {
          "variable": "phi_h",
          "time": 0.0,
          "expected": 177507.015625
        },
        {
          "variable": "phi_q",
          "time": 0.0,
          "expected": 16291.5869140625
        }
      ]
    },
    {
      "id": "fire_behavior_constants_moist_fuel",
      "description": "Moisture dependence under fire_behavior's constants, which the dumped cells cannot check (test7's fmc_g is uniformly 0.08). Same inputs as fire_behavior_step20_strongest_cell_cat2 but M_f = 0.3, evaluated in float64 from fire_behavior's own form: bmst = 0.3/1.3, grnhft = fbr w_l (1 - bmst) CMBCNST = 1410012.353 W/m^2, grnqft = (bmst + (1 - bmst) 0.56) fbr w_l XLV = 173895.8623 W/m^2. Against the M_f = 0.08 cell, phi_h falls by 1.08/1.3 and phi_q/phi_h rises from 0.0918 to (0.3 + 0.56) 2.5e6/1.7433e7 = 0.1233; a regression in either moisture term (the 1/(1 + M_f) damping or the M_f + 0.56 numerator) fails here.",
      "parameter_overrides": {
        "fuel_burn_rate": 0.11735081672668457,
        "w_l": 0.8960000276565552,
        "h_fuel": 17433000.0,
        "M_f": 0.3,
        "L_water": 2500000.0,
        "water_combustion_ratio": 0.5600000023841858
      },
      "time_span": {
        "start": 0.0,
        "end": 1.0
      },
      "assertions": [
        {
          "variable": "phi_h",
          "time": 0.0,
          "expected": 1410012.352787551
        },
        {
          "variable": "phi_q",
          "time": 0.0,
          "expected": 173895.8622668252
        }
      ]
    }
  ],
  "analyses": [
    {
      "id": "phi_h_vs_M_f_sweep",
      "description": "Sweep M_f over the realistic atmospheric range (0 to 0.5) at fixed fuel_burn_rate, w_l, h_fuel. Surfaces the (1 + M_f)⁻¹ damping of the sensible heat flux as fuel moisture rises — the dominant qualitative feature of Mandel et al. (2011) Eq. 4.",
      "initial_state": {},
      "parameters": {
        "fuel_burn_rate": 0.01,
        "w_l": 0.166,
        "h_fuel": 18608000.0
      },
      "time_span": {
        "start": 0.0,
        "end": 1.0
      },
      "parameter_sweep": {
        "type": "cartesian",
        "dimensions": [
          {
            "parameter": "M_f",
            "range": {
              "start": 0.0,
              "stop": 0.5,
              "count": 26,
              "scale": "linear"
            }
          }
        ]
      },
      "plots": [
        {
          "id": "phi_h_curve",
          "type": "line",
          "description": "Sensible heat flux as a function of fuel moisture content.",
          "x": {
            "variable": "M_f",
            "label": "M_f (mass fraction)"
          },
          "y": {
            "variable": "phi_h",
            "label": "phi_h (W/m²)"
          }
        },
        {
          "id": "phi_q_curve",
          "type": "line",
          "description": "Latent heat flux as a function of fuel moisture content — increases with M_f because the (M_f + 0.56) numerator dominates over the (1 + M_f) denominator at low M_f.",
          "x": {
            "variable": "M_f",
            "label": "M_f (mass fraction)"
          },
          "y": {
            "variable": "phi_q",
            "label": "phi_q (W/m²)"
          }
        }
      ]
    },
    {
      "id": "phi_h_heatmap_burn_rate_w_l",
      "description": "Two-dimensional sweep over (fuel_burn_rate, w_l) at fixed h_fuel and M_f. Both fluxes are bilinear in (fbr, w_l), so the surface should be a smooth product map — useful for visual sanity-checking the equation structure.",
      "initial_state": {},
      "parameters": {
        "h_fuel": 18608000.0,
        "M_f": 0.08
      },
      "time_span": {
        "start": 0.0,
        "end": 1.0
      },
      "parameter_sweep": {
        "type": "cartesian",
        "dimensions": [
          {
            "parameter": "fuel_burn_rate",
            "range": {
              "start": 0.0,
              "stop": 0.02,
              "count": 21,
              "scale": "linear"
            }
          },
          {
            "parameter": "w_l",
            "range": {
              "start": 0.1,
              "stop": 3.0,
              "count": 21,
              "scale": "linear"
            }
          }
        ]
      },
      "plots": [
        {
          "id": "phi_h_surface",
          "type": "heatmap",
          "description": "Sensible heat flux as a function of fuel burn rate and fuel load.",
          "x": {
            "variable": "fuel_burn_rate",
            "label": "fuel_burn_rate (1/s)"
          },
          "y": {
            "variable": "w_l",
            "label": "w_l (kg/m²)"
          },
          "value": {
            "variable": "phi_h",
            "reduce": "final"
          }
        }
      ]
    }
  ]
}