Reference

The exact shapes: every configuration field with its JSON, the REST endpoints and the MCP tools. For what the product does and why — and the component reference — read the documentation.

Configuration reference

The fields that need more than a tooltip, with the complete syntax where a JSON shape applies. Every field below is reachable three ways — the builder's sidebar, a supplier listing in the portal, and the MCP tools (solve_system, save_system, import_catalog_items) — and it is the same field in all three; the shapes here are what the API stores and returns. Defaults are the conservative reading of an unknown machine, never a placeholder: a compressor is fixed-speed until you say otherwise, a fan bank is independent sections, a tower is a fixed approach. Two limits are the engine's own and no plan's: a graph of at most 500 components once flattened, and a fan bank of at most 64 fans.

Control strategy

How a machine meets a part load, saved with the system (system tab → Control strategy) and inherited by every building block that uses it. The demand side — setpoints, loads, occupancy — comes from the rooms a simulation serves; what you declare here is what the machine is.

A chiller's pipeInPipe evaporator may declare freezeCutoutC, its low-limit stat on the leaving water (3 °C is typical for plain water). On a trickle of flow a chiller cycling at its floor would otherwise be modelled from an on-state that leaves water far below zero; with the cutout the on-state is the capacity that lands the water on the cutout, at an evaporating temperature the machine can run at.

{
  "roomSetpointC": 24,
  "load": { "baseKw": 0, "slopeKwPerK": 0, "balanceTempC": 18 },
  "supplyComponentId": "fan-1",
  "modulate": true,
  "selection": "minPower",
  "stages": [
    { "name": "ventilation", "enabled": ["fan-1"] },
    { "name": "evaporative", "enabled": ["fan-1", "pack-1", "pump-1"] },
    { "name": "mechanical",  "enabled": ["fan-1", "pack-1", "pump-1", "comp-1"] }
  ],
  "supplyControl": { "type": "szvav", "supplySetpointC": 13, "minFlowRatio": 0.4, "resetMaxC": 18 },
  "heating": {
    "roomSetpointC": 20,
    "load": { "baseKw": 0, "slopeKwPerK": 0, "balanceTempC": 16 },
    "stages": [
      { "name": "ventilation", "enabled": ["fan-1"] },
      { "name": "heatPump",    "enabled": ["fan-1", "comp-1"] },
      { "name": "heating",     "enabled": ["fan-1", "comp-1", "heater-1"] }
    ]
  },
  "unoccupiedSetpointC": 28,
  "occupiedHours": [false,false,false,false,false,false,false,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,false,false]
}
FieldMeaning
stagesOrdered enable-sets; the first stage whose supply temperature reaches the requirement runs the hour, the last runs with met:false when none does. Omitted = derived from the graph: ventilation (the fans on the air being served) → evaporative (+ wet packs, pumps, water coils) → mechanical (+ compressors); heating: ventilation → heat pump (+ compressors) → heating (+ heaters). A fan or pump on a heat-rejection stream is not ventilation: a condenser's fans, and a tower's fan with its condenser-water pump, join only the stages that run the compressor whose heat they reject — or, on a free-cooling plant, the stages that run the tower — so a fans-only or furnace hour draws the supply fan alone. A ladder you declare runs exactly as declared. A cooling-only design must exclude its compressors from the heating stages — every air-coil circuit is heat-pump capable by default.
selectionordered (default): first stage that meets. minPower: the lowest electrical power among the stages that meet.
modulateInverters ride their capacity down to the setpoint by bisection; fixed-speed machines cycle at full-load saturation temperatures and pay the AHRI 340/360 cycling degradation. Which one a compressor is comes from its own variableSpeed.
supplyControl{"type":"constantVolume"} (default) or {"type":"szvav", …}: single-zone VAV — the supply fan throttles toward minFlowRatio before the coil unloads, and resetMaxC (above the setpoint) lets the supply temperature float up as load falls. The measured worth on the example AHU: constant volume 12 841 kWh, SZVAV 7 773, SZVAV with reset 9 414.
unoccupiedSetpointC + occupiedHoursOutside occupancy the machine starts from off — the whole ladder stands behind it, the fans alone first where they can carry the load — and steers to the relaxed setpoint. Both halves or neither: relaxing the room's load while the control still holds the occupied setpoint costs 50 % more heating, measured. In a building run these come from the rooms' schedules and you do not set them.
fanAutoThe thermostat's fan switch. true is AUTO: on an hour with no cooling or heating call the machine starts from off, fans included, the way an unoccupied hour already does. false (default) is ON: the ventilation stage runs through occupancy whether or not there is a call — right for a machine that is the rooms' outside air, wrong for one that is not (an evaporative cooler beside a rooftop that ventilates). A building block can override it (fanAuto on the block).
dehumidifier (building block)Humidity-led control. The block is judged, modulated and cycled on its rooms' humidity ceilings alone, on every hour, and its supply temperature is never held against it: a dehumidifier reheats with its own condenser and can never meet a cooling requirement, which under the ordinary rule left it idle or flat out. Its sensible output is delivered to the room like any machine's — a follower behind it (the priority rule) is offered the remainder — and a room it serves hands its ceiling to no other machine. Needs a humidity ceiling on every room it serves.
hourlyLoadsKwOne value per weather hour, +cooling / −heating, on a room: a load calculated elsewhere, in place of the modelled one for every hour the array covers. It is read as the duty that holds the room on the setpoint it was calculated at — the cooling setpoint for a positive hour, the heating setpoint for a negative one. On that setpoint the room asks its machine for exactly the import; coasting inside its band it asks for less, and recovering for more; left unserved it drifts by the import over its envelope's conductance and settles there, where a bare heat rate would run away. The zone editor's CSV import writes it.

Compressor maps

A compressor is an AHRI 540 / EN 12900 rating: two (optionally three) ten-coefficient polynomials in evaporating and condensing temperature, published in watts (mass flow in kg/s), of the form

X = C1 + C2·te + C3·tc + C4·te² + C5·te·tc + C6·tc² + C7·te³ + C8·te²·tc + C9·te·tc² + C10·tc³

— the order selection software exports. The catalog carries some 4 800 manufacturer maps already; paste your own only for a machine that is not there.

{
  "model": "Danfoss VZH088CJ (R410A scroll, 50 Hz)",
  "refrigerant": "R410A",
  "capacityCoefficients": [49941.1, 1720.81, -63.2423, 26.7946, 0.00183626, -4.70348, 0.114679, -0.184863, -0.188105, -0.00503575],
  "powerCoefficients":    [5508.63, 168.934, 49.9583, 6.42313, -8.88073, 3.39995, 0.0898196, -0.158666, 0.0967435, -0.0140492],
  "massFlowCoefficients": [0.2413, 0.00812, -0.00031, 0.000131, 0.0000041, -0.0000228, 0.00000053, -0.00000091, -0.00000092, -0.000000024],
  "superheatRef": 10, "subcoolRef": 0,
  "superheat": 10,    "subcool": 5,
  "usefulSuperheat": 10,
  "heatRejectionFactor": 0.95,
  "variableSpeed": true, "minSpeedRatio": 0.25, "maxSpeedRatio": 1.2,
  "minCondensingC": 30,
  "setpointC": 62,
  "operatingEnvelope": { "vertices": [[-25,10],[-5,10],[25,40],[25,55],[15,68.5],[3.5,68.5],[-10,61],[-20,50],[-25,37.5]] },
  "steps": [
    { "speedRps": 25,  "capacityCoefficients": [ /* 10 */ ], "powerCoefficients": [ /* 10 */ ], "massFlowCoefficients": [ /* 10 */ ] },
    { "speedRps": 50,  "capacityCoefficients": [ /* 10 */ ], "powerCoefficients": [ /* 10 */ ] },
    { "speedRps": 100, "capacityCoefficients": [ /* 10 */ ], "powerCoefficients": [ /* 10 */ ] }
  ]
}

A bank — several machines on one circuit — is partners: each a machine of its own (a catalog pick, or a pasted map) sharing the lead's refrigerant, superheat and subcooling. A VRF outdoor unit with a fixed-speed scroll beside its inverter, a tandem of scrolls, a duplex condensing unit. One suction, one discharge, one evaporating and condensing temperature; the control sees one machine that modulates. Unloading: fixed-speed partners run flat out or not at all, switched on largest first as base load; the inverters trim the remainder on their own step curves; where no combination lands, the last-switched machine cycles between the two nearest states with the AHRI 210/240 degradation. The report lists each machine's share.

{
  "model": "Copeland JPV066AC (inverter)", "refrigerant": "R410A", "variableSpeed": true, "minSpeedRatio": 0.2,
  "capacityCoefficients": [ /* 10 */ ], "powerCoefficients": [ /* 10 */ ], "steps": [ /* 3 */ ],
  "partners": [
    { "catalogRef": "copeland-zp67kze-410a-50hz", "spec": { "model": "Copeland ZP67KZE-TFD", "refrigerant": "R410A", "capacityCoefficients": [ /* 10 */ ], "powerCoefficients": [ /* 10 */ ] } }
  ]
}
On a circuit with a reclaim stage the floor is held differently: a condenser inside the supply stream cannot give up air (it is the coil's air too), so the circuit condenses at the declared minimum as a flooded condenser does, the reclaim taking the larger share the higher temperature gives it, at the compressor power holding a head costs.
FieldMeaning
superheatRef / subcoolRefThe superheat and subcooling the map was rated at (EN 12900: 10 K / 0 K; the old ARI point: 20 °F superheat, 15 °F subcooling). Every solve corrects the map from there to the operating superheat/subcool through the refrigerant's properties. Subcooling is measured from the bubble point at the condensing pressure — the condensing temperature on a pure fluid, the glide under it on a zeotrope such as R-448A or R-455A. A superheat is not negative: it is measured up from the dew point and 0 K is saturated suction, so a negative superheat or superheatRef — a bank partner's too — is refused, naming the compressor and the field. And a correction is never silently one: where the refrigerant's property table does not reach the operating point — a condensing temperature past its top — the map is corrected with the factors of the nearest point the table resolves, and the solve carries a warning that names the compressor, the fluid and where the factors were taken.
usefulSuperheatThe part of the operating superheat gained in the coil — the refrigerating effect's share. Absent, all of it counts, which is how a map is rated (AHRI 540 capacity runs from the liquid line to the compressor inlet; Copeland rates its refrigeration scrolls at a 65 °F return gas on that basis). A freezer's suction line brings gas back near room temperature — 45 K over a −28 °C coil — and declaring only that credits the store with heat the plant room supplied. Put the compressor's superheat in superheat and the coil's here (a unit cooler's valve holds 5–10 K): capacity becomes the map's, corrected for the suction density the machine really breathes, times the coil's refrigerating effect over the compressor's. Power and mass flow are untouched — and so is the condenser's duty: the gas reaches the compressor carrying the suction line's heat whoever paid for it, so the condenser still rejects the whole of the map's capacity plus the compressor's heat. Zero or more; a negative one is refused by name, as a negative superheat is.
variableSpeedAn inverter. Default false, which costs real energy — a fixed-speed machine cycles and pays the degradation; an inverter modulates and earns a part-load COP hump. Set it only for a genuine variable-speed machine.
minSpeedRatio / maxSpeedRatioTurndown and boost as fractions of the rating point (25–100 rps is 0.25). Below the minimum the machine cycles at that speed; above 1 the machine can be driven past its rating, which changes sizing.
stepsAHRI 540 §5.3.3's published part-load ratings, each a full coefficient set at a speed. With three or more, power is read off the published curve between steps — interpolated against capacity, since that is what the control asks for. Fewer than three are ignored: a chord between a maximum and a minimum is worse than the flat scaling it would replace. Without steps a part load scales one map, which holds COP flat and over-states power by 7.5 % on average and 46 % at worst on the catalog's Danfoss VZH088. The fit_compressor_map MCP tool returns a ready steps[] from a rating table carrying speedRps.
operatingEnvelopeWhere the map may be trusted (AHRI 540 §3.15 forbids extrapolating past it). Either a rectangle {"teMin":-25,"teMax":25,"tcMin":10,"tcMax":68.5} or the polygon a datasheet actually draws, as [te, tc] vertices in either winding. A rectangle over-claims: the VZH088's bounding box asserts 68 °C condensing at −25 °C evaporating, a corner no scroll reaches, and an envelope that over-claims is a warning switched off exactly where extrapolating is most dangerous. A solve landing outside returns a warning and an outOfRange entry, never a refusal. The envelope is also a floor: its lower edge at the evaporating temperature is the least the circuit condenses at. Its values must be finite and within ±200 °C, and a rectangle's minimum under its maximum.
minCondensingCHead-pressure control: the condensing temperature the condenser section is held at or above by staging its airflow down. A constraint, not an economy — it costs the compressor more than it saves the fans, and without it a model reports a mild-weather efficiency the controller never allows. Held in a point solve too, with the envelope's lower edge and a 5 K lift as floors of their own; a floor at or above the fluid's critical point is refused.
setpointCA setpoint this circuit holds on its own, °C, read at its condenser — leaving water on a coaxial, leaving air on an air coil. Absent, the circuit follows the system's supply requirement, which is one scale across every circuit. Declare it where one drawing carries two machines doing different jobs — an air conditioner sharing a cascade plate with a water heater — where a single supply state cannot describe both and the whole stage would otherwise be held to the least flexible machine.
reversibletrue (default): the circuit runs backwards on heating hours — heat-pump heating on the same map, with the frost derate below 5 °C outside. false: a cooling-only circuit; heating stages leave it out and the heaters carry the heating, which is what a rooftop with a gas furnace does. Config, not catalog — a reversing valve is the system's. A circuit that condenses in an evaporative condenser is cooling-only whatever this says: a solve that names it in reversed, or pins its condensing-unit half to heat (refLoads.{id}.heating), is refused while the circuit runs, naming the compressor and the condenser; at a heating design point (mode: heating) it is staged off and the unit's heaters carry the point.
cyclingDegradationA measured CD; omit to use the AHRI 340/360-2022 Eq. 5 correlation.
pipeLengthMThe equivalent refrigerant-pipe length from this machine to the coil it feeds — on a multi-split, to the farthest indoor unit. Equivalent, so the straight run plus what each bend, branch and header stands for. A map is rated on a short line and a real installation is not: at 100 m a machine delivers about 91 % of its rated capacity, at 225 m about 82 %, on the makers' own published tables. Charged to capacity alone, which is what the makers do, so the COP falls in the same proportion. 0 — the default — is the undeclared run and costs nothing. There is deliberately no height field: across a maker's whole grid a hundred metres of level difference moves the factor by one point, and what the height really decides is which runs are buildable at all.
capacityFactorThe one field that is yours rather than the map's: a multiplier for N identical machines on one circuit, or a derate.

Fans and pumps

A fan's power is a curve, not an efficiency. With both curves present the operating point is found the way a selection program finds it — the published curve is one speed, a duty off it is reached by changing speed, and the fan laws give the power. The priority is powerCurve → efficiency → nameplate powerKw; a listing carrying only the last behaves as a fixed-power fan.

{
  "airFlowM3s": 3.75, "powerKw": 5.9, "heatToAirFraction": 1.0,
  "externalStaticPa": 950,
  "curve":      [[1.254, 1100], [1.877, 950], [2.542, 500], [3.043, 0]],
  "powerCurve": [[1.254, 2.604], [1.877, 2.950], [2.542, 2.585], [3.043, 1.868]],
  "stages": 2,
  "arrangement": "sharedFace"
}
FieldMeaning
airFlowM3sThe volume of the air entering the fan's duct run, wherever on the run the fan stands. A stream carries one mass flow: it is fixed where the air enters the model — an open inlet, or the cut of a recirculating loop — as that volume at the entering state's density, and carried unchanged through every coil; a merge adds its legs and a split divides by its shares. So a draw-through fan behind a cooling coil moves the mass that entered the coil, not its own volume again at the colder air's density. Behind a merge the fan is still the mover: the legs no fan of their own moves bring its volume between them in the shares of their design flows, and its turn-down reaches them. It must be above zero: a fan of no air, or of negative air, is refused by name.
curveThe manufacturer's pressure curve, [flow m³/s, static Pa] ascending, per fan. With stages > 1 every curve read divides the bank's flow by the count — a listing is one machine, the count is your installation.
powerCurveInput power along the same curve at the same speed, [flow, kW]. A constant efficiency mis-states ebm-papst's own published points by 19–100 %, and reads zero at free delivery where the fan draws 1.87 kW.
stagesHow many equal fans this is. A staged bank's power falls linearly with the air it moves (each running fan is still at full speed); only a single throttled fan gets the cube law. Airflow quantises to whole fans. A bank is at most 64; more is refused, naming the fan.
arrangementindependentSections (default; each fan its own coil section — AHRI 340/360 Example 8's measured arrangement) or sharedFace (one coil face, so a survivor rides out along its pressure curve when a neighbour stops: on two catalog RadiPacs the survivor delivers 69 % of the pair's air, not 50 %, and draws 2.52 kW against the staircase's 2.95). Needs curve; declared without one it keeps the staircase.
Pump curve / powerCurve / externalHeadKpaThe water-side twins: [kg/s, kPa] and [kg/s, kW] at one speed, plus the pipework head the model cannot see. The loop's head is summed from its coils' tube and header drops and reported as headKpa; a curve that cannot cover the loop warns rather than silently shifting the flow.
staticSetpointPaDuct static-pressure setpoint, Pa. A VAV handler holds a static at its duct sensor as the boxes throttle, so the fan does not ride the square law down: Δp is p_set + (Δp_design − p_set)·s² and power P_design·s·Δp/Δp_design (a power curve is read at that point through the fan laws). At a third of design air a fan holding half its design Δp draws about a fifth of design power rather than a twenty-seventh. Absent = square-law system; a static-pressure reset (90.1 §6.5.3.2.3) is a lower setpoint.

Heaters: electric, indirect gas, direct-fired

A heater holds its leaving air at targetC — the control steers that hour by hour — delivering the sensible duty that takes, up to capacityKw, and drawing duty ÷ efficiency as its input. What the input is, and what else reaches the air, is the burner's.

{
  "capacityKw": 204.1, "airFlowM3s": 1.65, "targetC": 71.1,
  "fuel": "gas", "efficiency": 0.901, "combustionWaterKgKwh": 0.146
}
FieldMeaning
fuelelectric (default) or gas. Electric books the input as electricity, gas as fuel — totals.fuelKw on a solve, fuelKw hourly and totalFuelKwh on a run, never inside the electricity. A gas furnace at 0.8 is the catalog's Reznor class.
combustionWaterKgKwhA direct-fired burner's water, kg per kWh of the heater's gross (higher-heating-value) input — the basis its efficiency is read on too, and so the fuel it books. A direct-fired heater fires into the air it heats, so its flue gas is its supply and the water its fuel makes leaves with the air: methane makes 0.146 kg per gross kWh, a pipeline gas a little less, propane 0.117. The leaving humidity ratio rises by the fuel × this ÷ 3600 ÷ the air's mass flow — about 4 g/kg at a 160 °F rise — and the duty stays the sensible heat, so heating, reheat and every total read as before; where saturated air below about −25 °C is handed more water than it can carry, the leaving air lands on the saturation line at the same enthalpy. The water's latent heat is the share of the input the efficiency leaves: methane's water carries 9.9 % of the gross input away, so a methane burner heats its air with at most 0.901 of what it burns, and an efficiency that with the water passes the input — 0.92 beside 0.146 puts 101.9 % of the gas into the air — is refused, naming the heater; so is a water on electric heat. A burner rated on nett input (the lower heating value, on which European standards rate a gas appliance) is entered on the gross basis: its nett efficiency × LHV/HHV — 0.901 on methane — beside its water per gross kWh. The nett heating value leaves the water's latent heat out of the input, so methane's nett figures, 0.162 kg per nett kWh beside an efficiency of 1, would put 111.0 % of the gas into the air against the gross ceiling and be refused, though the burner is the same. 0, the default, for an indirect furnace, whose flue takes its water outdoors, and for electric heat. The burner's, so a catalog pick brings it.

Radiators and hydronic emitters

A radiator, an underfloor loop, a convector or a chilled ceiling: heat that reaches a room through water rather than through a duct. It is rated the way its maker rates it — EN 442-2 — and has no geometry, because a radiator maker publishes an output, never a fin pitch.

{
  "nominalOutputKw": 2.0,
  "nominalDeltaTK": 50,
  "exponent": 1.3,
  "waterFlowKgs": 0.05,
  "airFlowM3s": 0.2
}

The law is the one printed in every European catalogue: φ = φn · (Δt/Δtn)^n, where Δt is the excess of the water over the room — the arithmetic mean of flow and return less the room temperature, or the logarithmic mean when the water gives up most of its excess crossing the emitter ((t_return − t_room)/(t_flow − t_room) < 0.7, which is the makers' own switching rule). The reference condition, 75/65/20 °C, is Δt 50 by that arithmetic, which is why 50 K is the number on the datasheet.

FieldMeaning
nominalOutputKwThe EN 442 output — the one number a radiator is sold on.
nominalDeltaTKThe excess it was rated at. 50 by default, which is 75/65/20 °C; underfloor loops are often published at 15.
exponentHow sharply the output falls as the water cools. Default 1.3. Measured across one maker's whole certified catalogue: 1.295 for a single panel, 1.30 for a double, 1.326 for a type 22, 1.336 for a type 33 — deeper and more convective, higher exponent. Underfloor is nearer 1.1, a convector up to 1.4.
waterFlowKgsWhat the circulator sends through this emitter. Fed from outside the graph (a boundary, or a coupled plant block) it unloads by its valve — a thermostatic head is that valve.
airFlowM3sThe convective plume, and it does not change the heat delivered: EN 442 rates against room air temperature, which is what enters this component. It only sets how warm the air leaves, so an emitter cannot be mis-sized by guessing it.
ratedLengthMThe length the nominal output was rated over, m — absent for a whole emitter, which is every EN 442 panel; 0.3048 for a US baseboard or panel rated per active foot. The output is then that much heat per ratedLengthM. Above zero, or refused.
lengthMThe active length installed, m, beside a rating over a length: a ten-foot run is 3.048, and the law reads nominalOutputKw × lengthM / ratedLengthM. Required there and refused anywhere else: a rating per foot with no length would heat nothing, and a length beside a whole emitter's rating would not be read. It is yours on a picked part, never the listing's.

US ratings: per foot, over 65 °F entering air. North American baseboard and panels are rated per active foot at an average water temperature over 65 °F entering air, at 1 gpm, under the I=B=R/AHRI baseboard code — and an I=B=R rating includes the code's 15 % heating-effect allowance, a comfort credit written into the figure rather than heat the water gives the air. A US listing therefore holds the maker's per-foot column ÷ 1.15 where the document says its ratings include the allowance (the printed figure where it does not), at nominalDeltaTK = the column's average water less 65 °F (180 °F → 63.9 K), with the exponent fitted on its printed columns over 65 °F — never on a starred column, which the code's factor generates, and the default 1.3 where a document generates every column but one — and ratedLengthM 0.3048. The model reads Δt over the air entering the part, which in a building is the room: a room warmer than 65 °F reads under the tested rating — at 180 °F average water and an exponent of 1.24, 3.2 % under in a 68 °F room and 5.4 % in a 70 °F one — which a first-party listing's page states. How much colder the floor runs than the room belongs to the room, not the baseboard, and no rating document prints it.

Picked from the catalog — a catalogRef naming a listed emitter — the four rating fields are the listing's, filled in from the server's own store at every solve whatever the request carries, and the two flows and the installed length stay yours. An emitter left with no output, by a reference nobody lists or a request that forgot it, is refused by name rather than solved as a radiator that heats nothing.

Put the room's air on its inlet. An emitter's airIn is the room, and its airOut goes back to the room — that is what makes Δt the excess over the room and what carries the duty into the zone. A chilled emitter is the same component with water below the room temperature; the exponent is then the heating rating applied symmetrically unless the product publishes its own, which a chilled ceiling's datasheet does.

Coils and fin form

Fin-and-tube geometry in catalog millimetres; the tube pattern is a preset and the fin form rides on it.

{ "faceHeightMm": 1473, "faceLengthMm": 1100, "rows": 4, "fpi": 12, "circuits": 12, "airFlowM3s": 4.0,
  "pattern": { "type": "threeEighthsIn", "finEnhancement": 1.2 } }

{ "pattern": { "type": "custom", "tubeInnerDiameterMm": 8.7, "tubeOuterDiameterMm": 9.52,
  "pitchLongitudinalMm": 22.0, "pitchTransverseMm": 25.4, "finThicknessMm": 0.115, "finAreaFactor": 1.0, "finEnhancement": 1.0 } }

finEnhancement multiplies the air-side coefficient: 1.0 plain (absent = plain, so every stored coil is unchanged), wavy/"configured" conventionally 1.1–1.3 (the sidebar's wavy is 1.2, the value that reconciles Colmac's and Carrier's published selections), louvered about 1.75. The model itself is anchored on Carrier's 36-point rating matrix within 1.03 % RMS and a measured dry coil within 0.14 % on UA; geometry stops discriminating as the air reaches saturation, so rows and fin spacing matter and the tube preset barely does (0.1 % of duty).

A custom pattern has to be a coil. Its dimensions are typed by hand, and they are held to each other before anything is solved: every one above zero, a tube wall (the outer diameter larger than the inner), the transverse pitch larger than the tube over its fin collars so the tubes clear each other along the face, the two pitches leaving fin around the tube, and a fin thinner than the fin pitch. A pattern that fails one is refused, naming the coil and the field.

Evaporative packs and cooling towers

{ "faceHeightMm": 1200, "faceLengthMm": 1200, "depthM": 0.15, "airFlowM3s": 4.0,
  "effectivenessCurve": [[1.0, 0.92], [2.0, 0.87], [3.0, 0.81]],
  "waterFlowKgs": 4.0, "waterSideEffectiveness": 0.7,
  "rated": { "hotWaterC": 35, "coldWaterC": 29.4, "wetBulbC": 25.6,
             "waterFlowKgs": 4.0, "airFlowM3s": 4.0 } }
FieldMeaning
effectivenessCurveThe media's saturation effectiveness against face velocity, [m/s, ε]; absent = the EnergyPlus CelDek polynomial, which under-reads real media by 3–13 points against Munters' own sheets. A named catalog pad carries its maker's curve.
Water ports openAdiabatic: constant wet bulb, the dry bulb approaches it with the effectiveness. No water fields matter.
In a water loop, no ratedThe legacy water cooler: the loop water approaches the entering wet bulb by the fixed waterSideEffectiveness, blind to airflow and L/G.
ratedThe tower's certified point — hot water, cold water, wet bulb — and the flows it was taken at. Present, the loop pass becomes Merkel's enthalpy balance, integrated along the fill rather than linearised, with the NTU derived once from this point and following water loading by (ṁw/ṁa)^0.3 — or by the fill's own exponent, below; anchored on Marley's 615-point and EVAPCO's 856-point performance tables within 0.23 and 0.064 K RMS. An impossible rating (cold at or under the wet bulb, hot not above cold, or beyond what an infinite tower could do at these flows) is ignored and the legacy model stands.
rated.waterFlowKgs, rated.airFlowM3sThe flows the maker certified at; absent, the spec's own. They are separate fields because the spec's flows are the installation's — what a pump imposes and a fan moves — so reading a maker's number at the installation's flow is a figure nobody rated. Both the NTU derivation and the loading law measure against this pair.
closedCircuitA closed-circuit cooler: the loop fluid runs inside a coil under a recirculating spray and never touches the air. With rated the pass becomes the evaporative wet-coil model — the air exchanging enthalpy with the spray film, the fluid exchanging heat with it, the film's one temperature closed by the balance (Parker & Treybal, Mizushina) — the two conductances derived from the rating at an equal split, which is where Baltimore Aircoil's own 169-machine range reads coherently (their implied conductance follows the printed coil volume to the power 1.00). Without a rating the flag changes nothing. One point per model, so modelled and not validated; a rating within 0.1 K of the uniform-film ceiling derives at the ceiling.
sprayFlowKgsThe machine's own recirculating spray flow over the coil, kg/s — its spray pump, not the loop's flow. Declared on a closed-circuit cooler, the film varies along the coil instead of sitting at one temperature: the falling spray, the air against it, and the process fluid against the air, solved exactly under the same saturation-chord linearisation the tower uses. That is the arrangement the makers draw, and the one their certified ratings pick out — with the fluid co-current with the air the answer collapses back to a uniform film, which cannot reach 73 of Baltimore Aircoil's 632 certified closed-circuit ratings while the gradient reaches every one and reads each rating back exactly. The makers print the spray flow: BAC's European engineering data gives it beside the airflow for each range, and the listings carry their range's own figure. Absent, the uniform film answers as before. Catalog-owned.
maxEnteringWaterCThe hottest entering water the machine is built to take, °C. A solve whose water enters hotter warns and solves as before. Baltimore Aircoil's handbook gives 48.9 °C for an open tower on standard fill and 82.2 °C for a closed-circuit cooler, and the listings carry it. Catalog-owned.
fillExponentAn open tower fill's own loading exponent n: the NTU follows water loading as (ṁw/ṁa)^(1+n). How a fill's transfer moves with loading is a property of the fill, and a maker who prints the flow handled at many conditions has measured it: Baltimore Aircoil's CTI tables give −0.9 (FXT, PT2), −1.0 (Series V) and −1.2 to −1.3 (the crossflow Series 1500 and 3000), each the same on either half of the range's models, where EVAPCO's table prefers −0.6. Absent, −0.6. Open towers only. Catalog-owned.
crossflowtrue when the air crosses the falling water rather than rising against it — a crossflow tower. The fill is then marched cell by cell across its face instead of read off the counterflow effectiveness, which over-states a crossflow fill of the same NTU: on BAC's crossflow tables the march reads 0.11–0.15 K RMS where counterflow reads 0.19–0.21 K at its own best exponent. Open towers only. Catalog-owned.
waterDpCurveA closed-circuit cooler's water pressure drop as its maker prints it: [[kg/s, kPa], …] ascending in flow — Baltimore Aircoil's CTI pressure-drop tables give three points a model, and 432 of its closed-circuit listings carry them. Read log–log between the points, on the first segment's slope below them (where a maker's rated flow often sits) and on the last segment's above them, with a warning there. The drop at the flow the coil runs at is reported on the cooler and added to the head a pump on the same water reports, the way a water coil's tube and header drops are. An open tower carrying one claims nothing: its water is not in a coil. Catalog-owned.
coilSplitA closed-circuit coil's two conductances at its rating, as the ratio of the fluid-to-film one to the air-side one. One rating point cannot fix two conductances; a maker's multi-condition table can, and Baltimore Aircoil's CTI tables pick 2 (FXV), 1 (PFi) and 4 (Series V closed circuit), the same on either half of each range's models. Absent, 2. Closed-circuit coolers only. Catalog-owned.
coilFluidExponentHow the coil's fluid-side NTU moves with the fluid's flow, NTU ∝ ṁf^n. The fluid-to-film conductance is the tube's inside film, which grows with the flow, in series with the spray film outside the tube, which does not, so n sits between −0.2 (the tube film alone) and −1: a tube-side calculation from the coil's printed volume and pressure drop puts BAC's coils at −0.5 to −0.8, and their CTI tables pick −0.8 (FXV, PFi) and −0.6 (Series V closed circuit). Absent, −0.6. Closed-circuit coolers only. Catalog-owned.
evaporative on a condenserAn evaporative condenser: { "rejectionKw", "condensingC", "wetBulbC", "airFlowM3s"? } — the maker's certified point, a heat rejection at a condensing temperature and an entering wet bulb. Present, the fin geometry is never read (a listing may leave it at zero) and the coil is the evaporative wet coil with an isothermal tube side: the spray film sits where the air can carry the rejection, and the condensing temperature the coil asks for is the film plus the drop across its conductance. Two conductances from one point, so the coil's share of the rated approach is a declaration (EVAP_CONDENSER_COIL_SHARE, 0.2 — the largest share at which a whole maker's range still derives, the air side dominating as it should under a thin spray). The rating's airFlowM3s is the air the maker certified it at; a rating with no air flow of its own is read at the condenser's airFlowM3s, which is the installation's, so a published listing must state it — and its rating must derive there. The circuit must not reverse: a condenser under a spray cannot run as an evaporator, so a circuit condensing in one runs cooling-only, its unit's heating carried by its heaters.
A catalogRef on a wet packNames one of two things. Evaporative media — a depth and a curve — or a cooling tower, which is the whole machine and whose rated point is its performance data, so the listing's rating replaces yours. Pick media and a declared rating is removed: that choice says the component is a pad, and a pad has nothing to certify. The installation's own airFlowM3s, waterFlowKgs and face are never touched either way.

Plate exchanger (waterside economiser)

{ "waterFlowKgs": 26, "waterFlowSecondaryKgs": 35, "economizer": true,
  "rated": { "primaryInC": 12, "primaryOutC": 7.5, "secondaryInC": 6, "secondaryOutC": 9.35 } }
FieldMeaning
PortswaterIn/waterOut is the primary stream, waterInSecondary/waterOutSecondary the secondary — two water streams and no air. Counterflow; heat flows from the warmer stream to the colder, whichever side it is on. An open waterInSecondary takes its boundary as waterInlets["id:waterInSecondary"].
ratedThe datasheet's four temperatures at this spec's own flows; the UA is derived from them through the counterflow LMTD. A point whose two sides do not balance within 10 %, or whose streams cross, is no rating and uaKwK answers instead. A plate with neither is refused.
uaKwKThe conductance a listing would carry, used without a rating.
economizerThe changeover valves of a free-cooling plant: transfer only when the secondary is colder than the primary. Off (the default, a plain exchanger) the plate exchanges either way — which on a summer day warms the chilled return with tower water.
In a building runA block holding a leaving-water setpoint whose graph carries a plate gets a free cooling stage — everything but the compressors — ahead of its chiller stage; the first that meets the setpoint runs the hour. The example campus plant (New York) is arranged this way: the plate ahead of the evaporator on the chilled side and ahead of the condenser on the tower side, so it sees the coldest water and the chiller trims what is left.

Coaxial exchanger (pipe-in-pipe): rated point or geometry

{ "waterFlowKgs": 2.0, "freezeCutoutC": 3,
  "rated": { "waterInC": 12, "waterOutC": 7, "refrigerantSatC": 2, "waterFlowKgs": 1.0 } }
FieldMeaning
PortswaterIn/waterOut and refIn/refOut. Connect refIn to a compressor's discharge and it is a water-cooled condenser; connect refOut to a suction and it is a chiller's evaporator.
ratedThe maker's published point, flow and all: water in, water out, the refrigerant's saturation temperature there, and the flow it was rated at. Packless, Wieland and their kind print exactly this and never the coil's tube length, which the geometry below needs. The refrigerant side is isothermal, so the conductance follows from the model's own effectiveness read backwards — UA = −Cw·ln(b/a) with a and b the approaches at the water's inlet and outlet — and a rated exchanger reproduces its rated point exactly. A saturation temperature between the two water states, water that reaches or passes the refrigerant, or no flow is no rating, and what is declared below answers instead.
uaKwKThe overall conductance, kW/K, where a maker publishes one instead of a point. Used when there is no rated point.
pipeLengthM, outerDiameterMm, uoKwM2kThe geometric fallback, UA = uo·π·D·L — what every stored design has used so far. It is the last resort because the tube length is the one dimension a datasheet does not print.
waterFlowKgsYour installation's flow, which a pump on the loop or a partner block overrides. It never disturbs the rating: the rated point carries the flow it was taken at.
freezeCutoutCA chiller's low-limit stat on the leaving water. Cycling on a trickle, the on-state is the capacity that lands the water on the cutout rather than far below it.
a coax between the discharge and the condenserA heat-reclaim stage. A pipe-in-pipe wired from the compressor's discharge to a condenser's refIn — an air coil or another coax — takes its share of the rejection first: what its water carries at the circuit's condensing temperature, capped by the demand the control hands it, and the condenser rejects the rest. Its water is a boundary inlet (waterInlets): a pool, a tank. In a building, a block whose rooms hold a pool hands the stage the heat the water lost to evaporation last hour and the room is credited what it took (poolHeatRecoveredKwh); on its own the stage takes whatever its water carries. Reported as an exchanger of kind reclaim, on the totals as heatReclaimKw and on a run as reclaimKw / totalReclaimKwh. A reversed (heating) circuit reclaims nothing.

Liquid-cooled load: an immersion tank, a CDU, a process bath

{ "loadKw": 45, "waterFlowKgs": 2.0, "maxFluidC": 45,
  "rated": { "waterInC": 32, "waterOutC": 37.4, "fluidC": 42, "waterFlowKgs": 2.0 } }

Heat that enters a water loop with no air side at all — the water-side twin of a CRAH. An immersion cooling tank, a direct-to-chip cooling distribution unit, a process bath: servers or a process heat their own fluid, an exchanger in the tank hands that heat to facility water, and an outdoor cooler rejects it. Ports waterIn/waterOut only. Its load counts as cooling delivered on the totals, whatever loop the water is on.

In a building, a liquid load is a load of its own, beside the rooms (16 Sep 2026): liquidLoads: [{ "id", "name", "loadKw", "occupancy": [24 fractions], "hourlyLoadsKw": […], "waterFlowKgs", "maxFluidC", "rated", "uaKwK", "pumpKw" }]. A room's shape with none of a room's physics: a demand with a schedule (the occupancy profile, or an hourly CSV overriding it), a coolant ceiling, and a machine that serves it over a water pair — the block's waterTo onto the load's waterIn (the setpoint's home) and its waterFrom off the load's waterOut. The run compiles each load into a block of one liquidLoad component (and its circulator, where pumpKw is declared), so the pairs machinery is untouched; the results carry liquidLoads[] with the load's kilowatt-hours, the coolant's highest and mean temperature and the hours it sat over its limit. example-immersion-hall is one tank on one cooler.

FieldMeaning
loadKwThe heat the load puts into its fluid — the servers' IT load, the process load. Declared, never rated: a tank's sheet prints rack units and fluid volume, not what you put in it. The water carries all of it and leaves at t_in + Q/(ṁ·cp).
ratedThe maker's point for the exchanger between the load's own fluid and the water: water in, water out, the fluid temperature there, and the flow it was taken at. A pumped tank's dielectric is well mixed and sits at one temperature, so the exchanger is the coaxial condenser's Cr = 0 case with the fluid where the refrigerant was, and the conductance follows the same way — UA = −Cw·ln(b/a), a and b the fluid's excess over the water at its inlet and outlet. A fluid at or below the water, or water that reaches it, is no rating.
uaKwKThe exchanger's overall conductance, kW/K, where a maker publishes one instead of a point. Used when there is no rated point. With neither, the fluid temperature is not reported — a tank with no exchanger data cannot say how hot it runs, and the model does not pretend it sits at the leaving water.
maxFluidCThe servers' coolant limit, °C. A solve whose fluid settles above it warns; the solution carries the fluid temperature as exchangers[].fluidC either way.
waterFlowKgsYour installation's facility-water flow, which a pump on the loop or a partner block overrides. The rated point carries its own flow and is never re-read at yours.
where it sitsOn a closed loop with a tower, a dry cooler or a chiller's evaporator through a plate exchanger (a CDU is exactly that), or fed from outside the graph — a block coupled by water to a plant block, which is how a data-centre building draws it. A load on a chiller's own loop with nothing air-bearing between them wants the plate: the plate is always cut, and a loop of nothing but coaxials and pumps has nowhere to cut.

Cascade exchanger: one refrigerant circuit condensing into another

{ "rated": { "dutyKw": 12, "hotSatC": 48, "coldSatC": 10 } }

A refrigerant-to-refrigerant plate exchanger. One circuit condenses on its hot side (refIn/refOut); another evaporates on its cold side (refInSecondary/refOutSecondary). A heat-pump booster taking hot gas off an air conditioner's discharge to make hot water, or a cascade's condenser-evaporator. Both sides change phase at one temperature each, so the plate moves UA·(tc,hot − te,cold) — no new unknown: the duty is read off the two circuits' own saturation temperatures.

FieldMeaning
ratedThe maker's point: the duty in kW at a hot-side condensing and a cold-side evaporating temperature. The conductance is that duty over the difference. A point with no duty, or a cold side not colder, is no rating.
uaKwKThe plate's overall conductance, kW/K, where a maker publishes one. Used when there is no rated point. With neither the component is refused: a cascade with no conductance is a condenser nothing can reject into.
hot outlet back to the evaporatorThe circuit's condenser. compressor.discharge → refIn, refOut → evaporator.refIn: every kilowatt the circuit rejects goes to the cold circuit, and its condensing temperature is the cold side's evaporating temperature plus that duty over UA.
hot outlet on to a condenserA stage ahead of it. compressor.discharge → refIn, refOut → condenser.refIn (an air coil or a coax): the plate takes what the saturation difference drives, capped by the rejection, and the condenser rejects the rest — the heat-reclaim stage's arithmetic with a second circuit where the water was.
hot side on the liquid lineA subcooler. condenser.refOut → refIn, refOut → evaporator.refIn: the plate cools the liquid below the condenser's subcooling. The cold side evaporates at one temperature, so it takes ε·Cliq·(tliquid − te,cold) with Cliq the circuit's mass flow times the liquid's specific heat; that duty is capacity at the evaporator, and the condenser rejects what it would have.
the cold sideAlways the other circuit's evaporator. condenser.refOut → refInSecondary, refOutSecondary → compressor.suction. A plate between two circuits or nothing: wired to one side only it is refused by name.
what it reportsexchangers[] with kind cascadeExchanger, the duty, tSat (hot side) and lowSatC (cold side). The cold circuit's evaporating duty is not cooling anybody asked for and is not counted; its condenser's hot water, fed from outside the graph, is heat delivered.
not modelledDesuperheating and subcooling inside the plate when it condenses, refrigerant pressure drop, and the split of liquid between a booster's valve and the circuit's own (with both paths at one pressure the plate moves the same heat in parallel as in series). A cascade circuit does not run reversed.

Damper: merges and splits are wiring; the damper carries the policy

{ "airFlowM3s": 1.0,
  "economizer": true, "economizerHighLimitC": 24, "economizerEnthalpy": false,
  "occupiedFromHour": 7, "occupiedToHour": 21,
  "dcv": true, "dcvBaseFraction": 0.33 }

Two air streams merge where several connections land on one air inlet, and one divides where several leave one outlet — draw the wiring and the solver synthesises the junction; no component is needed. A split's shares are the branches' own design airflows, and a leg that lands straight on a merge takes the remainder, which is what a face-and-bypass is: the fan's outlet feeds the coil and the plenum behind it, the coil feeds the plenum, and the coil's airFlowM3s is its share. What the wiring cannot say is which leg is outside air and how its damper is driven, and that is the damper: one in, one out, on a leg. On the outside-air leg its flow is the minimum outside air and the fields below are the policy; a return damper carries only its flow and takes the remainder when the outside-air damper moves. Boundary entries go on the dampers' open inlets (airInlets["oa"], airInlets["ret"]), and a building's returnAir coupling on the return damper's airIn.

FieldMeaning
airFlowM3sThe leg's design flow: an outside-air damper's minimum position, never a starting point — free cooling is not a reason to stop ventilating.
economizerCooling hours only: the damper is placed by solving the ventilation stage shut and wide open and interpolating to the required supply temperature (mixing is exactly linear in position). Opens only when outside is below the changeover economizerHighLimitC (90.1 Table 6.5.1.1.3; default 24 °C) and better than the return — by dry bulb, or by total heat with economizerEnthalpy, read at the return damper's open inlet.
occupiedFromHour / occupiedToHourInclusive, wrapping. Outside the window the outside-air damper's minimum is zero (90.1 §6.4.3.4.1); an economiser can still open it, so a night purge is free. Default 0–23 is the damper that never shuts.
dcv + dcvBaseFractionDemand-controlled ventilation: the minimum position follows how full the served rooms are (90.1 §6.4.3.9, shaped by 62.1's Vbz = Rp·Pz + Ra·Az), falling to the per-area share dcvBaseFraction and no further.

A damper with none of the fields set is a leg with a flow — a return damper, a makeup-air damper open around the clock — and the controller leaves it alone. A merge takes one driven damper.

Mixing box and splitter (legacy)

Stored graphs that drew a mixingBox or a splitter still load and solve as they did; the two kinds are no longer offered, and a new drawing spells the same thing as wiring with a damper on the outside-air leg. The box's fields are the damper's, plus airFlowSecondaryM3s for the return leg and role (outsideAir or bypass).

The legacy box's JSON

{ "airFlowM3s": 4.0, "airFlowSecondaryM3s": 1.0,
  "role": "outsideAir",
  "economizer": true, "economizerHighLimitC": 24, "economizerEnthalpy": false,
  "occupiedFromHour": 7, "occupiedToHour": 21,
  "dcv": true, "dcvBaseFraction": 0.33 }
FieldMeaning
The two flowsPrimary (outside air on an outside-air box) and secondary (return). These are the damper's minimum position, never a starting point — free cooling is not a reason to stop ventilating.
roleoutsideAir (default: the box with a damper somebody drives) or bypass (the downstream half of a face-and-bypass pair — no damper; scheduling it shut would send every kilogram across an idle coil).
economizerCooling hours only: the damper is placed by solving the ventilation stage shut and wide open and interpolating to the required supply temperature (mixing is exactly linear in position). Opens only when outside is below the changeover economizerHighLimitC (90.1 Table 6.5.1.1.3; default 24 °C) and better than the return — by dry bulb, or by total heat with economizerEnthalpy, the device for a humid climate (22 °C at 95 % RH is cooler than a 26 °C room and carries more heat).
occupiedFromHour / occupiedToHourInclusive, wrapping. Outside the window the outside-air damper's minimum is zero (90.1 §6.4.3.4.1); an economiser can still open it, so a night purge is free. Default 0–23 is the damper that never shut. Note a room's dayEnd is exclusive, so the same closing time is written one hour apart in the two places.
dcv + dcvBaseFractionDemand-controlled ventilation: the minimum position follows how full the served rooms are (90.1 §6.4.3.9, shaped by 62.1's Vbz = Rp·Pz + Ra·Az), falling to the per-area share dcvBaseFraction and no further. Compute the fraction from 62.1 Table 6.2.2.1 over the rooms this box's machine serves: Σ Ra·Az / Σ (Rp·Pz + Ra·Az) — 0.33 for a dining-plus-retail mix, 0.12 for an auditorium. Worth 2.2 MWh of heating a year on the example mall.

Recovery devices

A heat pipe carries form — straight (the default: the air-to-air exchanger, one finned slab split by a partition, the two streams side by side) or wrapAround (two slabs either side of a cooling coil, joined by copper tubing over it); the physics is one dual-stream device either way, the field picks the drawing. Heat pipes and sensible cores carry minExhaustC: frost control as the lowest temperature the cooled side may leave at. The device derates — as a real core does, by bypassing part of itself — rather than blocking solid. Absent = unrestricted. It costs recovery (0.7 / 2.1 / 5.3 % of a Helsinki year's heating at 1 / 3 / 5 °C) and never binds in London.

A recovery core carries humidityEffectiveness — the humidity efficiency ηx of a moisture-transferring device (a sorption or hygroscopic rotary wheel, an enthalpy plate) as EN 308 and Eurovent's AARE programme define it: the share of the humidity difference between the two entering streams that the supply side picks up, at balanced flow. 0 (the default) is a plain plate or condensation wheel: sensible transfer, moisture only by condensation. Above zero the device runs as a sensible-and-latent exchanger — temperature by its face-velocity curve (effectivenessCurve, [m/s, ε]: every point above 0 and at most 1, an effectiveness being the share of what an infinite device would move; a curve with a point outside is refused by the core's name), humidity ratio by this figure, each on the smaller stream, the other stream by mass and energy balance — and a winter exhaust cooled past its dew point still sheds condensate. Eurovent 17/14 puts sorption rotors at 52–85 % and hygroscopic ones at 30–50 %, and calls a rotor sorption only above 0.7 of its temperature efficiency. Frost control derates both efficiencies together, as slowing a rotor does. Declare the season's figure: Eurovent's certified sorption rotors read 73 % in summer against 77 % in winter at 2 m/s (medians), enthalpy wheels 36 % against 52 %. A core declaring a humidity efficiency and no effectiveness curve takes the certified rotors' temperature curve (83.5 / 79.5 / 74.2 % at 1 / 2 / 3 m/s, the medians of 2 324 certified wheels) in place of the plate default; a condensation wheel declaring none keeps the plate curve, so give it that curve as its own. A wheel cannot sit inside an air loop the solver has to cut (a wrap-around arrangement): the cut carries heat alone, and the solve refuses it by name. The supermarket example's outside-air unit declares 0.65. It is a share, between 0 and 1; anything else is refused by the core's name, as an effectiveness curve's point outside (0, 1] is.

A wheel's maker prints its humidity efficiency falling with face velocity, as its temperature efficiency falls — DRI's AHRI-certified MS-200 media from 80 % at 1 m/s to 58 % at 5. humidityEffectivenessCurve carries it: [m/s, ηx] points in ascending face velocity, read at the face velocity the temperature curve is read at (the design flow over the face), in place of humidityEffectiveness, which a core with a curve leaves unread. Between points it is read as a straight line, past the ends as the end. Every point is above 0 and at most 1 — a core that moves no moisture declares no curve — and the points run in ascending velocity; a curve that is not one is refused by the core's name. A listed wheel brings both its curves with it (catalog-owned, like the face). Absent, the one figure is read at every velocity, as before.

{ "id": "wheel", "kind": "sensibleCore",
  "spec": { "faceHeightMm": 700, "faceLengthMm": 4200, "airFlowM3s": 2.7, "airFlowSecondaryM3s": 2.7,
            "humidityEffectiveness": 0.65, "minExhaustC": 1 } }
{ "id": "wheel", "kind": "sensibleCore",
  "spec": { "faceHeightMm": 1000, "faceLengthMm": 1000, "airFlowM3s": 2.5, "airFlowSecondaryM3s": 2.5,
            "effectivenessCurve": [[1.0, 0.83], [2.0, 0.78], [3.0, 0.73], [4.0, 0.69], [5.0, 0.64]],
            "humidityEffectivenessCurve": [[1.0, 0.80], [2.0, 0.75], [3.0, 0.69], [4.0, 0.63], [5.0, 0.58]] } }

Eurovent 6/12 energy efficiency class

Every point solve of an air handling unit carries its Eurovent 6/12 class — ahuClass on the solution, shown in the solve column and on the spec report. Eurovent Recommendation 6/12 (fourth edition, 2013; the class values are EN 13053's) grades a unit A to E on the velocity through its cross-section, the dry winter efficiency and pressure drop of its heat recovery device, and the mains power its fans draw against a reference fan power computed for a unit that would exactly meet the class. Thermal energy enters through the recovery efficiency, weighted against fan electricity by the recommendation's own climate factor; cooling energy is deliberately outside the method. There is nothing to configure: the reading comes from the graph and the solved point.

What it readsFrom
Cross-section velocityThe fan's flow over the largest face on its air chain. The recommendation reads the filter section; a model without filters has the coil or core face the unit is built around.
Fan staticThe chain's summed component pressure drops plus the fan's external static.
Heat recoveryThe dual-stream device on the chain: its dry efficiency at that side's own flow, and its pressure drop.
Mixing ratioThe return share at the outside-air damper's merge, capped at the recommendation's 85 %. A face-and-bypass re-merge is not a damper anybody drives and counts for nothing.
Subgroup1 when the unit takes outdoor air at 9 °C or below — evidenced by an outside-air box or a recovery device, since an open inlet alone could be a recirculating unit's own room. 2 for recirculation or a warmer point, 3 for extract only. Subgroups 2 and 3 are graded on velocity and fan power alone, so solve at a winter design point to see the recovery device counted; on a summer point the recommendation itself drops that half.
Electric reheaterAn electric heater downstream of the recovery device, which the method penalises.

What gets a class. A fan chain that treats supply or extract air — one carrying a water coil, a recovery device, a heater, a humidifier, an evaporative pad or a damper, or both a DX coil and a condenser (a dehumidifier cools the air and reheats it). Not graded, deliberately: a condenser and its fan, a cooling tower, an air-source heat pump's outdoor coil, and a bare DX coil and fan, which this model cannot tell from a refrigeration unit cooler. A machine with no air side at all — a chiller, a VRF outdoor unit, a radiator plant — has no class rather than a misleading letter. This is not a system energy label, and the recommendation says so of itself: it grades a unit's own fans and recovery, not the system around them.

Rooms

{ "id": "food-court", "name": "Food court", "areaM2": 900, "heightM": 4.5, "envelopeUaKwK": 1.8,
  "solarApertureM2": 40, "coolingSetC": 24, "heatingSetC": 20,
  "setbackCoolingC": 28, "setbackHeatingC": 15, "recoveryKPerHour": 1.5,
  "outdoorAirAch": 0.1, "ventCoolingAch": 3, "moistureCapacityMultiplier": 15, "humidityLimitKgkg": 0.012,
  "gains": { "dayKw": 45, "nightKw": 4, "latentDayKw": 12, "latentNightKw": 1, "dayStart": 7, "dayEnd": 21,
             "occupancy": [0,0,0,0,0,0,0,0.1,0.2,0.4,0.6,0.7,0.8,0.8,0.8,0.8,0.7,0.6,0.5,0.4,0.2,0,0,0] } }
FieldMeaning
gains.occupancy24 fractions. Present, it replaces the day window: dayKw/latentDayKw are the gains at full occupancy, nightKw at none, each hour lands between, and "occupied" means the fraction is above zero. Any length but 24 is refused. Shape alone moves annual cooling +44 % on the example mall against a step schedule carrying the same daily gain.
setbackHeatingC / setbackCoolingCThe unoccupied band; absent = held to the occupied band around the clock. Worth a quarter of the example mall's heating.
recoveryKPerHourOptimum start: a ramp that reaches the setpoint exactly at opening, spreading recovery over ΔT/gradient hours. 1.5 K/h costs 8 % of the mall's heating and takes its rooms' unmet hours from 342 to none; assuming 3 K/h is cheaper (5 %) and leaves 4, because a ramp that believes the machines recover twice as fast starts half as early.
outdoorAirAchThe room's own leakage, moisture only (the sensible side is inside envelopeUaKwK). Outside air a mixing box brings in is already in the supply — counting it here too ventilates the room twice.
thermalMassKjM2kHow much heat the room's structure holds, kJ per m² of floor — what decides how far it swings in a day. ISO 13790 §12.3.1.2 tabulates it by construction class: very light 80, light 110, medium 165, heavy 260, very heavy 370. A concrete block with plastered masonry is medium to heavy; a partitioned office with a raised floor and suspended ceiling is light, because the slab is hidden from the air on both sides. Omit it and the room keeps the model's original lumped figure — about 15.7 kJ/m²K at a 2.6 m ceiling, a fifth of that table's lightest class, which suits the partitioned commercial rooms most of the library is built from. Declare it for a dwelling, for masonry, or for any room with no cooling that rides a summer on its windows — there it is the number that decides the peak: on the apartment example it is the difference between 38 °C and 30 °C. Do not expect it to save energy: measured across every example building at ISO's light class, electricity moves by low single digits in both directions, and summer unmet hours rise — a heavy room banks the morning's gains and hands them back in the afternoon, when the machine is already at its peak. That is why the default stands (owner decision, 29 Aug 2026) and this is a field you set where the mass is the point.
solarOrientationDeg, solarTiltDegWhich way the glazing faces — a compass bearing (0 north, 90 east, 180 south, 270 west) and a tilt from the horizontal (90 a wall, the default once an orientation is declared; 0 a skylight). Declared, solarApertureM2 multiplies the irradiance on that plane — the sun's position, the beam/diffuse split (PVGIS's own beam and diffuse where the year carries them, Erbs's estimate otherwise) and an HDKR transposition anchored on PVGIS's plane-of-array series to +0.2 % over a year — so a south façade sees the low winter sun a north one never does, where the horizontal scalar gave both the same. Absent, the scalar every room had before. Needs a fetched year, which knows where it was recorded; on a synthetic or imported year the scalar answers whatever is declared.
poolA swimming pool in the room — {surfaceM2, waterTempC, activityFactor, airVelocityMs}. The surface evaporates into the room's air by the natatorium relation (ASHRAE Handbook — HVAC Applications, Places of Assembly): A·(p_w − p_a)·(0.089 + 0.0782·V)/Y kg/s, the saturation pressure at the water's temperature against the vapour pressure of the room's air, so a wet room evaporates less and a saturated one nothing; times the Handbook's activity factor (0.65 therapy, 0.8 hotel, 1.0 public or school, 1.5 a wave pool), which applies by the room's occupancy profile — an empty pool is the Handbook's unoccupied 0.5. The source sits in the room's moisture balance and in the ceiling's inversion, so a humidity ceiling on a pool hall asks its machine for what the pool adds. The room reports poolEvaporationKg and poolHeatKwh — the heat evaporation took from the water, what the pool heater must replace.
ventCoolingAchWhat an open window is worth, air changes an hour — the room's own free cooling. The machines have had an economiser from the beginning; the rooms had nothing, and a room with no cooling machine could only integrate a solar gain. Applied only when it helps: the room above its cooling setpoint and the outside below that setpoint, so a window is never opened onto air that cannot reach the band and then fed to a machine to remove again. It is a conductance, not a duty, so it can never cool a room below the outside air. Your declaration about your building: a few air changes for openable windows on one façade, several times that cross-ventilated, 0 — the default, and every example — for anything sealed.
moistureCapacityMultiplierHow much more vapour the room holds than its air (EnergyPlus's humidity capacity multiplier; NREL's effective moisture capacitance is 15). It moves no energy — buffering stores vapour and returns it — but hours above ASHRAE 55's 0.012 kg/kg collapse: 73 at ×1, 1 at ×8, 0 at ×15 on the example food court.
humidityLimitKgkgThe room's humidity ceiling, kg/kg (ASHRAE 55's 0.012 is the usual figure, the same bound the humid-hours count uses). When the room would end the hour above it, its machine is asked for a supply dry enough as well as cool enough: the stage is judged and modulated on both, a fixed-speed machine cycles to the drier of the two, and a heater downstream of the cooling coil is enabled as reheat with the sensible requirement as its target. Without a reheat heater the room over-cools within its band. Absent = no humidity control.
humidityFloorKgkgThe room's humidity floor, kg/kg (an operating suite's 30 % RH at 20 °C is 0.0044). When the room would end the hour under it, its machine's steam humidifier (the humidifier kind: capacityKgH, efficiency, fuel, and a design-point targetWKgkg the run overrides hourly) is steered to the supply humidity that lands the room on the bound, up to its capacity; the steam's energy is booked as electricity or gas. dryHours on the room counts the hours under the floor. Must sit under the ceiling. Absent = no floor.

VAV terminals

A VAV box per room, on the block that serves it (building tab → select the block → VAV boxes, then a room's supply link under Connections to set its box). The box is not part of the machine's graph — the graph is one machine with one supply state, and the rooms and their boxes are the building's. Declaring any box makes the block a multi-zone VAV handler: every served room gets one (an undeclared room a default box — its area share of the fan, 30 % minimum, no reheat), and each room is handed what its own box delivered instead of a demand-proportional share of the block's supply.

{ "id": "s1", "label": "AHU-1", "serves": ["food-court", "retail", "concourse"],
  "couplings": [{ "port": "fan:airOut", "role": "supplyAir" }],
  "supplyControl": { "type": "szvav", "supplySetpointC": 13, "minFlowRatio": 0.3, "resetMaxC": 18 },
  "terminals": [
    { "zone": "food-court", "maxFlowM3s": 1.6, "minFraction": 0.3, "reheat": { "kind": "hotWater", "maxKw": 12 } },
    { "zone": "retail",     "minFraction": 0.3, "reheat": { "kind": "hotWater", "maxKw": 8 } },
    { "zone": "concourse",  "minFraction": 0.3 } ] }
FieldMeaning
supplyControlThe handler's air-side strategy for this block, overriding the saved system's. Boxes need szvav: supplySetpointC is the coldest leaving air, resetMaxC the warmest the controller may reset to, minFlowRatio the fan's floor. The setpoint is reset from the critical zone (90.1 §6.5.3.5): as warm as the ceiling allows while the box that needs the most air still fits under its maximum — every degree warmer costs fan energy in that one room and saves reheat in all the others.
maxFlowM3sThe box's maximum. A room whose load needs more than this at the coldest setpoint is unmet by air, whatever the coil could do. Absent: the room's area share of the fan's design flow.
minFractionMinimum damper position as a fraction of the maximum — ventilation (90.1 Appendix G's 30 %). It holds while the building is occupied and on heating hours; an empty building's boxes shut.
reheatWhen the minimum carries more cooling than the room wants — or the room wants heat on a cooling hour — the box reheats the excess up to maxKw, and it counts as heat delivered either way; electric counts as the block's electricity as well (the way its duct heater does), hotWater does not. Absent = a cooling-only box, which over-cools at its minimum and reports the room below its band.
heating hoursA VAV handler heats through its boxes: every box at its minimum, the handler at a neutral supply (the reset ceiling), each box reheating its own room. A room whose box cannot reheat is carried by the handler instead — its supply rises to what that room needs at its minimum, and the other rooms over-heat, which is what a reheat-less terminal on a warm deck does.
what you get backPer room, reheatKwh; per block, an hourly reheatKw series and totalReheatKwh (inside the heating total as well, and the electricity total when electric). With one room and no reset ceiling the block reproduces single-zone VAV exactly.
the exampleRiverside Mall's AHU-1 runs boxes on its three rooms — 15 % minimums, a 13 °C deck reset to 16 °C, electric reheat, the fan holding 125 Pa of duct static — the configuration a sweep picked: a warmer reset gave the food court's humid hours back, a colder deck cost a third more electricity, higher minimums cost reheat on every count. Open it as a building tab to see the fields filled in.

Accessories and products

What a system names beside its components — valves, expansion joints, isolators, sensors, filters, insulation — is its accessories: graph.accessories, a list beside components. The solver never reads them, no token counts them and no part ceiling does; the report prints them as its accessory schedule, grouped by family, after the component schedule, and the schedule CSV as a second block.

An accessory is {id, category, name?, maker?, model?, catalogRef?, quantity?, per?, attributes?, at?, label?, notes?}. category is a listed category of the taxonomy (GET /api/taxonomy, MCP list_product_categories) — a modelled one is drawn as a component instead. quantity counts in per: each (the default), m, m2, kg or l. attributes are the category's, one value each where a listing states a range ({"pipeSizes": ["dn100"], "pressureClass": ["pn16"]}). at is the component (and port) it is installed at; deleting the component leaves the accessory on the system at that component’s id, which the app does not give a new component (the report prints no place for it). catalogRef names a supplier's product listing (MCP search_products): the report reads its supplier, name and model from the listing as published, and a listing withdrawn since prints as it was chosen, saying so. Every door that stores a system refuses an accessory that is not its category's, by name (422, code: "accessory"); at most 1 000 to a design.

Quotes. A listed accessory’s quote goes to its own supplier (the accessories window’s quote button, POST /api/rfq). A typed-in one is matched by its category: POST /api/rfq/match-accessories (MCP match_accessory_suppliers) names the suppliers who declare that product category on their capability profile or publish a product in it, in the regions asked, and /api/rfq/fanout-accessories (MCP request_accessory_quotes) sends each one a lead holding only its own lines — tagged as the report tags them, per system and in all for units systems. Nothing is solved or charged; sending is Starter and up, on the same daily allowance as a design’s quote request, and the same request twice in a day is refused as a copy. A nested system’s accessories are quoted from that system.

A product listing is kind: "product" with name, optional model, category, a plain-text description of 40 to 2 000 characters, the category's attributes (the ones it requires, when published) and an optional datasheetUrl. Its text carries no links, emails, phone numbers or messenger handles — quote requests reach you through its page. It counts against the same free published listings as a component listing.

Supplier listings and system offerings

What a supplier fills in, and what each field does on the public page and in quote routing. A component listing is one catalog item — its spec is exactly the component spec above for its kind — plus the fields below; a system offering is a snapshot of one of your saved systems, taken at publish (editing the saved system later does not move the offering; republish to refresh it).

Category. Every system offering carries a category — one of the fixed set (air handler, rooftop / packaged, split / VRF, chiller, condensing unit, fan coil / terminal, evaporative cooler, heat recovery / DOAS, plant / tower, unit cooler / refrigeration) or a label of your own, up to 40 characters. It is what the systems directory facets on and what + Open filters by; an offering without one shows as unassigned until you set it. Saved systems carry the same field (category on POST /api/systems and in the MCP save_system / update_saved_system tools).

Reuse. A saved system may nest other systems (a system of systems: a published offering or one of your own as a node whose open ports connect like a component's). Publishing such a design flattens it into the offering's snapshot — and a nested offering of another supplier's is only flattened in if that supplier has ticked allowReuse on it (default off; the platform's examples allow it). A design that references an offering without it is refused by the offering's name.

// import_catalog_items — one fan and one compressor
{ "items": [
  { "kind": "fan", "name": "RadiPac K3G450-AQ24-90", "published": true, "regions": ["EU"], "tags": ["EC", "plug fan"],
    "certification": "", "productUrl": "https://www.ebmpapst.com/…",
    "spec": { "airFlowM3s": 1.877, "powerKw": 2.95, "heatToAirFraction": 1.0, "externalStaticPa": 950,
              "curve": [[1.254, 1100], [1.877, 950], [2.542, 500], [3.043, 0]],
              "powerCurve": [[1.254, 2.604], [1.877, 2.950], [2.542, 2.585], [3.043, 1.868]] } },
  { "kind": "compressor", "published": true, "regions": [], "certification": "AHRI 540",
    "spec": { "model": "…", "refrigerant": "R32", "capacityCoefficients": [ /* 10 */ ], "powerCoefficients": [ /* 10 */ ],
              "superheatRef": 10, "subcoolRef": 0, "variableSpeed": false,
              "operatingEnvelope": { "teMin": -20, "teMax": 15, "tcMin": 20, "tcMax": 65 } } }
] }
FieldWhat it does
publishedDraft or live. The free supplier tier keeps at most three listings live at once; the supplier tier, which comes with the plans marked on the pricing table, lifts the cap. Publishing an identical payload twice is refused as a duplicate.
regionsMarkets served, as region codes (EU, UK, NA, LATAM, MEA, CN, IN, APAC, or your own). Empty means worldwide. They are the directory's market facet, they route a lead to the territory rep you named for that region, and they are one of the four things a fan-out quote request matches on.
tagsFree text for the directory's search; no other effect.
certificationThe programme the item is certified under (AHRI 540, Eurovent, CTI…), shown on the listing. Verified is a separate flag only a platform admin can set after checking the programme's public directory; the import tool refuses to set it.
productUrlYour own product page, linked from the listing. Carries rel="nofollow" until the account's plan includes the supplier tier.
imageDataUriA product photo as a data:image/…;base64,… URI — PNG, JPEG, WebP or GIF; anything else, an SVG included, is refused. The portal downscales to 1600 px before upload, 2 MB after. The company logo lives on the profile, not per item, under the same rule.
refrigerant (compressors)Chosen from what the property backend serves — every fluid CoolProp loads on the live deploy. A listing naming anything else cannot be solved, and is flagged as such.
spec.refrigerant (compressor)One of the refrigerants this deployment's property backend can solve — GET /api/catalog/refrigerants lists them (R410A, R32, R454B, R454C, R290, R1234ze(E)… under CoolProp; R410A alone without it). A listing naming anything else is refused, in the portal and through import_catalog_items alike: a map nobody can run is not a listing. The map is corrected from superheatRef/subcoolRef to the operating superheat and subcooling on that fluid.

A system offering adds:

FieldWhat it does
name, blurbThe public page's title and text. An empty blurb keeps the page out of search engines (noindex) — indexing is earned by a complete profile and a description.
capacityMinKw / capacityMaxKw, heatingCapacityMinKw / heatingCapacityMaxKw, showCooling / showHeatingThe range the offering is built for, per mode, and which modes the tile shows. They feed the directory's capacity bands, and the builder's "supplier systems that cover this duty" hint after a solve.
The snapshotGraph and boundary as saved at publish. Engineers open it in their builder as a local copy — your components stay attached by their catalog references, so a later data correction on a listing reaches every design that picked it (see strict resolution).

What routes a quote request to you (capability-routed RFQ): your declared capability kinds must cover the request's kinds; regions must overlap (empty on either side = worldwide; capability regions fall back to your listings' regions); the request's duty must fall inside your capacity envelope with a 20 % margin; refrigerants must overlap only when both sides declare any. An engineer's typed-in accessories route by product category instead: a line reaches you when you declare its category or publish a product in it, in a market you serve, with no kind or capacity asked — and you receive only the lines you cover. Leads arrive by email instantly on the supplier tier (part of the plans marked on the pricing table) and after 24 hours on the free tier, which also caps at 20 leads per rolling month; delivery mode (instant / daily digest / none) is yours to set.