Two chillers, a secondary loop and a fouled tower
Workbook exercise plant-chiller-multi · PNNL re-tuning chapter 8 · about 50 minutes
Goal
Judge a plant with more than one of everything. Find two chillers running when one would do, a secondary loop that runs warm while both chillers hold their setpoint, a chiller with a fouled condenser, and two fouled cooling towers: one pinned at full fan, one whose controller hides the fouling in its fan. Then look at a plant a little off everywhere that passes every check.
Learn more
Read these first (PNNL, free):
- Central Utility Plant Cooling Control, the re-tuning guide: chiller staging, the primary-secondary loop and the cooling tower are all in its questions.
- Chapter 8: Central Utility Plant of the re-tuning training.
Datasets and licence
synthetic-chw-plant-multi: a synthetic primary-secondary chilled-water plant that CAMBER generates on your computer: two equal chillers on constant primary flow, a decoupler, a variable-flow secondary loop and one cooling tower. Nothing is downloaded and no real building is behind it. It holds the outdoor dry-bulb and wet-bulb; each chiller's run status, power, leaving and entering water, and the condenser and evaporator approaches its controller reports; the secondary loop's supply, return, setpoint, flow, pump speed and pump power; and the tower's leaving and return water and fan speed. The data are every 15 minutes for three summer weeks, with a heat wave in the third. Licence Apache-2.0 (CAMBER's own; the data may be shared). About 1.7 MB. See synthetic datasets for how CAMBER generates it.
The same weather and the same building drive seven plants: well_run, over_staged,
reverse_mixing, fouled_condenser, tower_full_fan, tower_controlled and near_miss. Each
plant is four pieces of equipment in the facility ds-synthetic-chw-plant-multi: CH1__<plant>
and CH2__<plant> (the chillers), SECLOOP__<plant> (the secondary loop) and TOWER__<plant>.
The plant names say where to look; what is wrong, and which rule sees it, is the exercise.
Setup
In the lab
- Run
camber laband open the URL it prints (http://127.0.0.1:8765/lab?token=...). - Tick
synthetic-chw-plant-multi(its kind readssynthetic) and press Fetch & ingest. CAMBER generates the file instead of downloading it, then ingests it like any other dataset. - When the job is done, the row links to trends (the trend viewer) and to report, the audit report of the dataset's template at the trend's own 15-minute resolution. The fleet steps below use the command line.
On the command line
camber datasets fetch synthetic-chw-plant-multi
camber datasets ingest synthetic-chw-plant-multi --store lab_store
camber datasets config synthetic-chw-plant-multi --exercise plant-chiller-multi --store lab_store --out multi.json
camber run multi.json --out multi_out
camber datasets score synthetic-chw-plant-multi --store lab_store --findings multi_out/findings.json
The exercise's config (--exercise plant-chiller-multi) runs four rules at their defaults on the
15-minute trend: chiller_staging_fleet (over the whole facility, on purpose),
chw_supply_tracking, chiller_approach_fouling and cooling_tower_approach. Its drift
section adds the tower drift family with a declared reference:
cooling_tower_fan_effort_drift scores each tower's fan effort against TOWER__well_run,
fitted in memory on each run and never stored.
Three variants run chiller_staging_fleet on one plant's two chillers only:
plant-chiller-multi--well-run, plant-chiller-multi--over-staged and
plant-chiller-multi--near-miss. For the over-staged plant:
camber datasets config synthetic-chw-plant-multi --exercise plant-chiller-multi--over-staged --store lab_store --out fleet_over.json
camber run fleet_over.json --out fleet_over_out
Steps
- Look before you judge. In the trend viewer, open
CH1__well_runandCH2__well_runand plot both chillers' power over a week. When does the second chiller start? Do the same for the over-staged plant. Then plotSECLOOP__reverse_mixing's supply temperature with its setpoint, andCH1__reverse_mixing's leaving water. - Run the exercise's config (the commands above) and read the
chiller_staging_fleetlinecamber runprints. How many chillers does it count, and where does its finding sit? - One plant at a time. Run the three fleet variants and read
pct_overstaged,n_multi_samples(andmulti_hours),median_running_count,rep_capacity_kwandcapacity_sourcein eachfindings.json. - The secondary loop. Read
chw_supply_trackingfor everySECLOOP__<plant>and for the reverse-mixing plant's two chillers:above_pct,median_excess_above_f,chwst_median_f,deltaT_median_fandrun_source. - The condensers. Read
chiller_approach_foulingfor each chiller:cond_approach_f,evap_approach_fandworst_approach_ratio. - The towers. Read
cooling_tower_approachforTOWER__well_run,TOWER__tower_full_fanandTOWER__tower_controlled:approach_median_f,pct_hours_high_approach,n_operatingandn_low_effort_excluded. Then readcooling_tower_fan_effort_driftfor every tower:fan_effort_drift_pct, the summary and the caveats. Readcooling_tower_approach_drifttoo:tower_approach_drift_fandtower_approach_load_source. - Score. Run
camber datasets scoreand read the overall rates and each rule's.
Questions
- Over the whole facility, how many chillers does
chiller_staging_fleetcount, what does it leave out, and what does it conclude? Why is pooling seven plants on one clock still wrong, and what fixes it? - On one plant at a time, which plant over-stages? What capacity does the rule assume for a chiller, where does that figure come from, why does it read low on that plant, and what would you declare instead?
- Which plant's secondary loop misses its setpoint? Are its chillers at fault? What is the loop delta-T, and what is the water in the decoupler doing?
- Which chiller's condenser is fouled, and how far is its approach from design?
- Which tower does
cooling_tower_approachflag, and which does it pass? Both are fouled: what does the controlled tower do instead of widening its approach, and which rule sees that? cooling_tower_fan_effort_driftpasses the over-staged plant's tower, which a range-only match would have flagged. Why would two chillers' condenser water make a clean tower look harder-working, and which point prevents that?- What does the label score say for each rule, and for the plant as a whole? Which fault can no label score count, and why?
- The near-miss plant passes every check. What is a little off in it, and what would you watch?
What CAMBER shows
- Findings.
camber runprints one line per finding: one per rule and equipment, plus one<fleet>line forchiller_staging_fleet. - Fleet.
chiller_staging_fleettakes every chiller that carries a power point and puts them on one clock. A chilled-water loop (CHW_LOOP,SECLOOP) is left out (n_loops_excluded): its power is its pumps'. A sample is over-staged when two or more run and their total power would fit in one machine fewer at 90 % (redundancy_ceiling) of a chiller's capacity. That capacity (rep_capacity_kw) is the declared full-load power (capacity_kw) when given, else the median, across the chillers, of each one's own 95th percentile running power (capacity_source). It warns when 20 % of the multi-chiller samples are over-staged and faults at 50 %. The counts are samples (n_multi_samples), with their hours beside them (multi_hours). Its finding sits on<fleet>, not on a chiller. - Supply tracking.
chw_supply_trackingreports the share of running time with the supply more than 3 °F above its setpoint (above_pct): a warn at 10 %, a fault at 25 %. "Running" is the chiller's status when mapped, else its power (run_source). The secondary loop is a loop, so it is gated on its pumps: their status when mapped, else the loop flow (here,run_sourceisflow), else the pumps' power. - Approach.
chiller_approach_foulingcompares each chiller's median condenser and evaporator approach with 5 and 4 °F (worst_approach_ratio): a warn at 1.5 times design, a fault at 2. - Tower.
cooling_tower_approachjudges the approach (leaving water minus wet-bulb) only in samples with the fan at 90 % or more (n_operating; the rest aren_low_effort_excluded), against a 7 °F design: a warn when the median is 1.3 times design, a fault at 1.7.cooling_tower_fan_effort_driftreads the fan speed against the reference tower at matched condenser load and wet-bulb: a warn at 5 percentage points, a fault at 10. With a condenser flow (cw_flow) the load is the heat rejected, else the range, which assumes a constant condenser flow. These towers trend it (CW_GPM), so the load is the heat rejected (load_sourcecw_heat_rejection).cooling_tower_approach_driftreads the approach against the reference at matched load the same way (tower_approach_load_source). - Score.
camber datasets scoreprints the true- and false-positive rates, with 95 % intervals, for the entry's declared detectors and for the plant as a whole.

From this exercise's synthetic plants: each tower's approach (condenser water leaving minus wet-bulb) against its fan speed, every running sample. cooling_tower_approach judges only the samples right of the dashed 90 % line, and counts those above the dotted line (design 7 °F plus 3 °F) as high.
Caveats
- The data are synthetic: CAMBER's own model of one plant, built to show these faults. They show what the rules see, not how real plants behave; never cite them as evidence about a building.
- The approaches are the chiller controller's own refrigerant-side readings, generated directly. A real chiller reports them from its refrigerant pressures and temperatures, and not every controller trends them.
- In the heat wave, the badly fouled tower sends condenser water near 99 °F. A real chiller would trip on high head pressure before that.
- A 15-minute trend averages a chiller's start into its first sample. The fleet rule's counts are
of 15-minute samples (
n_multi_samples);multi_hoursgives their hours.
Going further
- Compare with the cooling tower exercise: its simulated tower is
controlled to the wet-bulb plus 8 °F, so its fouling shows only as fan effort, and
cooling_tower_approachscores no fouled run there. - Edit
fleet_over.jsonand setchiller_staging_fleet'sredundancy_ceilinglower and higher. How does the over-staged share move, and what would you set it from on a real plant? Then declarecapacity_kw(about 138 kW, a chiller's draw at full load here) and read the verdict again. - Run
camber rules params chw_supply_trackingandcamber rules params cooling_tower_approachto see where each default comes from.