Skip to content
FlowScript templates

Operations — energy balance for a production line

An energy balance over one hour of steady production, written so that the closure error is visible rather than absorbed. Typed FlowScript for supply chains. Keywords: supply chain, logistics, network, supplier.

Template previewFlowScript
Conversion funnel6 steps · base n = 1,308Energy into the oven — gas and electrical1,308100.0% of baseAfter the flue loss92470.6% of base▲ 70.6% step convAfter extraction and end-seal losses74657.0% of base▲ 80.7% step convAfter wall and roof losses65049.7% of base▲ 87.1% step convAfter heat recovered to the proofer52840.4% of base▲ 81.2% step convInto the product — the 16 kW gap is the closure error51239.1% of base▲ 97.0% step conv

Make it your own.

// An energy balance over one hour of steady production, written so that
// the closure error is visible rather than absorbed.
//
// The line is a bread plant tunnel oven. Gas and electrical inputs are
// metered; the outputs are the heat that actually goes into the product,
// the flue, the extraction air, the walls, and the heat recovered to the
// proofer. What does not close is 16 kW, or 1.2% of the input, which is
// inside the 5% an accepted balance is normally allowed and is stated
// rather than quietly shared out among the measured streams.
//
// Specific energy is the number the site is actually judged on. It comes
// out at 0.363 kW.h per kilogramme of dough, against a best-practice
// benchmark of 0.310 — a gap of 17%, most of which is sitting in the flue.

energy_balance tunnel_oven {
  title: "Tunnel oven energy balance — bread plant line 2"
  boundary: "Oven inlet to cooler inlet. The proofer is outside the boundary; heat sent to it counts as an output."
  basis: "One hour at steady state, 3600 kg of dough in, 92 C core at exit"
  method: "Gas meter and sub-metered electrical panel; flue loss from oxygen and temperature; wall loss from an infrared survey at 24 points"
  measured: "2026-01-29, 06:00 to 07:00, mid-run"
  throughput: 3600 kg
  benchmark_specific_energy: 0.310 kW*h/kg source "Carbon Trust industrial bakery benchmark, plant bread"
}

energy_input gas_burners {
  of: tunnel_oven
  title: "Natural gas to the burners, net calorific value"
  power: 1240 kW
  instrument: "Rotary gas meter, corrected for temperature and pressure"
}

energy_input electrical_drives {
  of: tunnel_oven
  title: "Circulation fans, conveyor drives and extraction"
  power: 68 kW
  instrument: "Panel sub-meter, one-minute averages"
}

energy_output product_heat {
  of: tunnel_oven
  title: "Into the product — sensible heat plus water evaporated from the dough"
  power: 512 kW
  basis: "Mass loss 11.4% at 2257 kJ/kg latent, plus sensible heat to 92 C"
}

energy_output flue_loss {
  of: tunnel_oven
  title: "Flue gas to atmosphere at 214 C, 6.1% oxygen"
  power: 384 kW
  basis: "Siegert calculation from flue temperature and oxygen"
}

energy_output extraction_loss {
  of: tunnel_oven
  title: "Extraction air and end-seal air ingress"
  power: 178 kW
  basis: "Measured extraction volume and temperature rise"
}

energy_output wall_loss {
  of: tunnel_oven
  title: "Wall, roof and end losses"
  power: 96 kW
  basis: "Infrared survey, 24 points, natural convection correlation"
}

energy_output recovered_to_proofer {
  of: tunnel_oven
  title: "Recovered to the proofer through the flue heat exchanger"
  power: 122 kW
  basis: "Water-side flow and temperature rise on the recovery circuit"
}

balance_result oven_balance {
  of: tunnel_oven
  total_input: = sum(kind:energy_input, "power") * 1[kW]
  total_output: = sum(kind:energy_output, "power") * 1[kW]
  closure_error: = total_input - total_output
  closure_percent: = pct(closure_error, total_input)
  // Efficiency on the product alone, and again with the recovered heat
  // credited — both are quoted in the trade and they differ by nine points.
  thermal_efficiency: = pct(product_heat.power, total_input)
  efficiency_with_recovery: = pct(product_heat.power + recovered_to_proofer.power, total_input)
  flue_share: = pct(flue_loss.power, total_input)
  energy_per_hour: = total_input * 1[h]
  specific_energy: = energy_per_hour / tunnel_oven.throughput
  gap_to_benchmark: = pct(specific_energy - tunnel_oven.benchmark_specific_energy, tunnel_oven.benchmark_specific_energy)
  annual_hours: 6200
  annual_energy: = total_input * 6200[h]
}

saving_option flue_economiser {
  of: oven_balance
  label: "Second economiser on the flue, raising recovery to 210 kW"
  additional_recovery: 88 kW
  gas_displaced_per_hour: = additional_recovery * 1[h]
  hours_per_year: 6200
  // The proofer cannot take the full recovered duty all year, so the
  // derate is a factor in the chain rather than a sentence under it.
  // This block used to compute the payback on 88 kW for all 6200 h and
  // then caveat that it "assumes 78% utilisation" — a business case that
  // reads as though the derate is already in it, when it is not, and so
  // prints a payback 22% shorter than the plant can deliver. If the
  // seasonal profile is remeasured, change this one number and every
  // figure below it moves with it.
  heat_utilisation: 0.78 source "Proofer demand profile 2025 — share of production hours able to absorb the full recovered duty"
  annual_gas_saved: = additional_recovery * 6200[h] * heat_utilisation
  gas_price_per_kwh: 0.061
  currency: "GBP"
  annual_saving: = (annual_gas_saved / 1[kW*h]) * gas_price_per_kwh
  capital_cost: 74000
  payback_years: = capital_cost / annual_saving
  caveat: "The proofer cannot absorb 210 kW in summer, so the duty is seasonal. heat_utilisation carries that into the arithmetic, so annual_gas_saved, annual_saving and payback_years above are all derated figures; undo the factor and the payback would read about seven months shorter than the plant can deliver."
}

saving_option seal_and_insulate {
  of: oven_balance
  label: "End-seal replacement and 60 mm additional roof insulation"
  wall_loss_reduction: 34 kW
  extraction_reduction: 22 kW
  total_reduction: = wall_loss_reduction + extraction_reduction
  annual_gas_saved: = total_reduction * 6200[h]
  annual_saving: = (annual_gas_saved / 1[kW*h]) * 0.061
  capital_cost: 21000
  payback_years: = capital_cost / annual_saving
}

funnel_step energy_in {
  n: = oven_balance.total_input
  title: "Energy into the oven — gas and electrical"
}

funnel_step after_flue {
  n: = energy_in.n - flue_loss.power
  from: energy_in
  title: "After the flue loss"
}

funnel_step after_extraction {
  n: = after_flue.n - extraction_loss.power
  from: after_flue
  title: "After extraction and end-seal losses"
}

funnel_step after_walls {
  n: = after_extraction.n - wall_loss.power
  from: after_extraction
  title: "After wall and roof losses"
}

funnel_step after_recovery {
  n: = after_walls.n - recovered_to_proofer.power
  from: after_walls
  title: "After heat recovered to the proofer"
}

funnel_step into_product {
  n: = product_heat.power
  from: after_recovery
  title: "Into the product — the 16 kW gap is the closure error"
}

note closure_discipline {
  text: "An energy balance that closes to zero has usually been made to. The honest move is to measure what can be measured, compute the rest, and print the difference: 16 kW here, which is smaller than the uncertainty on the flue calculation alone and therefore not worth chasing further."
  anchor: oven_balance
}

view cascade: funnel(energy_in)

caption cascade_caption {
  of: cascade
  title: "Where the oven's energy goes"
  text: "One hour at steady state. Each step subtracts one measured loss, so the width of a step is the loss it removes; the final gap between the last step and the heat into the product is the closure error."
  n_statement: "Basis: 3600 kg of dough per hour, 1308 kW in."
  style: journal
}