blockTableData2DLoadDepSHC
Information
This block provides the core implementation to model simultaneous heating and
cooling (SHC) systems, also referred to as multipipe polyvalent units or "Type A"
in Eurovent (2025).
Since the most recent versions of these systems are composed of multiple modules,
the implementation includes the staging logic for an arbitrary number of
modules nUni. Nevertheless, single-module systems can also be
appropriately represented by setting nUni = 1.
All kinds of capacity-modulation processes are supported, such as VFD-driven compressors, multiple on-off compressors, and single compressor cycling. The method used to interpolate capacity and power based on user-provided data is taken from Buildings.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.BaseClasses.TableData2DLoadDep. Users should be familiar with this latter block before continuing with this documentation.
The block implements the following functionalities:
- Ideal controls.
- Capacity and power calculation.
- Module staging.
- Load balancing between the HW and CHW side.
System and module operating mode
The block inputs onHea and onCoo allow switching between
three system operating modes.
- Heating-only: In this mode, all modules operate as heat pumps, tracking the HW temperature setpoint and sourcing heat from the ambient-side fluid.
- Cooling-only: In this mode, all modules operate as chillers, tracking the CHW temperature setpoint and rejecting heat to the ambient-side fluid.
- Simultaneous heating and cooling: In this mode, some modules operate as heat recovery chillers, sourcing heat from the CHW circuit and rejecting heat to the HW circuit. The system load balancing logic (see Section "Load balancing between the HW and CHW side") ensures that, on average, both the HW temperature setpoint and the CHW temperature setpoint are met by these modules. Additional modules may concurrently run in heating-only or cooling-only mode to match the residual load. In the extreme case where the system is only exposed to heating (resp. cooling) loads, all modules will run in heating-only (resp. cooling-only) mode.
Ideal controls
For each module operating mode, the block implements ideal controls by solving for the part load ratio required to meet the load (more precisely the minimum between the load and the actual capacity for the current source and sink temperatures). This is done by interpolating the PLR values along the heat flow rate values for a given load. As described in Section "Load balancing between the HW and CHW side", the part load ratio for modules in SHC mode is the maximum between the PLR values for the heating load and the cooling load.
The load is calculated based on the HW and CHW-side side variables and the temperature setpoint
provided as inputs. The setpoint either represents a leaving (supply) temperature setpoint if
use_TLoaLvgForCtl is true (default setting) or the entering (return)
temperature if use_TLoaLvgForCtl is false.
In contrast to the implementation in Buildings.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.BaseClasses.TableData2DLoadDep the current block does not expose the PLR value, and therefore does not support external modeling of equipment safeties.
Capacity and power calculation
The capacity and power calculation follows the same logic as the one described in
Buildings.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.BaseClasses.TableData2DLoadDep
except that the current block does not include compressor false loading, i.e., both the capacity
and power are linearly interpolated along PLR between 0 and min(PLR<Shc|Hea|Coo>Sup).
Performance data file and scaling
The performance data are read from external ASCII files that must meet the requirements specified in the documentation of Buildings.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.BaseClasses.TableData2DLoadDep.
A performance data file must be provided for each module operating mode:
heating-only, cooling-only and simultaneous heating and cooling.
It is expected that performance data be provided for a single module.
This is however a loose requirement as the scaling logic anyway ensures that
the nominal heat flow rates Q*_flow_nominal provided as parameters
match the values interpolated from the performance data, times the number of modules.
Note that for single-mode performance data, the ambient-side fluid temperature
must correspond to the entering temperature, while the model supports
choosing between entering or leaving temperature for the CHW and HW via
the parameters use_TEvaOutForTab and use_TConOutForTab,
respectively.
Module staging
First, the heating and cooling loads QHeaSet_flow and QCooSet_flow
are calculated from the block inputs (see Section "Ideal controls").
The staging logic uses time-averaged heating and cooling loads
QHeaSetMea_flow and QCooSetMea_flow.
An exponential moving average (dtMea * der(Q<Hea|Coo>SetMea_flow) =
Q<Hea|Coo>Set_flow - Q<Hea|Coo>SetMea_flow)
is used for computational efficiency.
Then the model evaluates the capacity of a single module in each mode, based on the current source and sink fluid temperature (see Section "Capacity and power calculation"). The number of modules required to run to meet the load is then calculated for each mode as follows.
-
Number of modules required to run in SHC mode to meet the heating load as
nUniHeaShcRaw = ceil(QHeaSetMea_flow / max(QHeaShcInt_flow) / SPLR),
wheremax(QHeaShcInt_flow)is the heating capacity of one module in SHC mode andSPLRis a parameter representing the staging part load ratio. Note that this parameter should be strictly lower than1because the number of staged modules ultimately conditions the opening of isolation valves and the staging of primary pumps. IfSPLR = 1it is likely that the mass flow rate will limit the load below the capacity of a single module, practically preventing the system from staging up until the return temperature exceeds the design value. -
Number of modules required to run in SHC mode to meet the cooling load as
nUniCooShcRaw = ceil(QCooSetMea_flow / min(QCooSHcInt_flow) / SPLR),
wheremin(QCooSHcInt_flow)is the cooling capacity of one module in SHC mode. -
Number of modules required to run in SHC mode as
nUniShcRaw = min(nUniCooShcRaw, nUniHeaShcRaw).
This condition means that the system stops staging modules in SHC mode when either the cooling load or the heating load is met. -
Number of modules required to run in heating mode as
nUniHeaRaw = ceil(QHeaSetResMea_flow / max(QHeaInt_flow) / SPLR),
whereQHeaSetResMea_flowis the residual heating load, calculated as the time-averaged heating load minus the heating output of modules in SHC mode, andmax(QHeaInt_flow)is the capacity of one module in heating-only mode. -
Number of modules required to run in cooling mode as
nUniCooRaw = ceil(QCooSetResMea_flow / min(QCooInt_flow) / SPLR),
whereQCooSetResMea_flowis the residual cooling load, calculated as the time-averaged cooling load minus the cooling output of modules in SHC mode, andmin(QCooInt_flow)is the capacity of one module in cooling-only mode.
Discrete-event logic is then used to calculate the actual number of modules in
each mode (nUniShc, nUniHea and nUniCoo)
considering the following requirements.
- Minimum stage runtime: The number of modules enabled in each mode must stay unchanged
for at least
dtRun. - Step-by-step staging: Only one module can be enabled or disabled on the HW side at the same time, and similarly for the CHW side. However, "hot swapping" is allowed, where one module can be enabled or disabled in SHC mode while one module is simultaneously being disabled or enabled in heating or cooling mode.
- Priority order: When the total number of modules required to run in each mode
(
nUniShcRaw + nUniHeaRaw + nUniCooRaw) exceeds the number of modules in the bank, the following priority applies where modules required in SHC mode are staged first and modules required in cooling mode are staged last.
Load balancing between the HW and CHW side
A fundamental assumption for load balancing is that the system is composed of equally sized modules that are hydronically balanced, connected in parallel arrangement and controlled at the same setpoint. This implies that each module connected to the HW (resp. CHW) loop handles an equal fraction of the total heating (resp. cooling) load, irrespective of whether the module operates in SHC or single mode. This assumption is strictly true on the dominant side. However, as explained below, it is only partially true on the non-dominant side where setpoint deviations occur in the modules with excess thermal output and in the compensating module.
Based on this assumption, on the dominant side, the heating or cooling load of each module in SHC mode can be calculated as
Q<Hea|Coo>SetUniShc_flow = Q<Hea|Coo>Set_flow / (nUniShc + nUni<Hea|Coo>).
In order to achieve load balancing between the CHW and HW sides for the subset of modules in SHC mode, the model assumes that these modules are loaded for the most demanding side, and that a single module can cycle between SHC and the corresponding single-mode operation. For example, in case of 90 % cooling load and 60 % heating load, the module will cycle between SHC at 90 % PLR during 2/3 of the time and cooling-only at 90 % PLR during 1/3 of the time. This logic is inspired from the sequence of operation of a multipipe heat pump system (Johnson Controls, 2024) where the last enabled circuit cycles between SHC and single-mode operation to balance the heating and cooling loads.
The part load ratio of each module in SHC mode to satisfy the most demanding side is
PLRShcLoa = min(PLRShcSup, max(fHeaShc-1(QHeaSetUniShc_flow),
fCooShc-1(QCooSetUniShc_flow))),
where f<Hea|Coo>Shc-1 is the linear interpolation of the part
load ratio along the module heating or cooling capacity at the actual source and sink temperature,
based on the performance data provided for SHC operation.
A demand limiting logic is implemented to prevent overcooling or overheating due to the stage
minimum runtime requirement and the possible flow variations resulting from modulating the primary
pump speed and/or the minimum flow bypass valve.
This logic uses a temperature deviation from setpoint dTSaf, which is converted to
limiting heat flow rates Q<Hea|Coo>Saf_flow.
The limiting part load ratio is calculated as
PLRShcSaf = min(fHeaShc-1(QHeaSaf_flow / (nUniShc + nUniHea)),
fCooShc-1(QCooSaf_flow / (nUniShc + nUniCoo))).
The effective part load ratio of each module in SHC mode is then the minimum of the load-based and safety-limited values
PLRShc = min(PLRShcLoa, PLRShcSaf).
The excess heating or cooling heat flow rate (non-dominant side) of the modules in SHC mode is then calculated as
Q<Hea|Coo>ShcExc_flow = nUniShc * (f<Hea|Coo>Shc(PLRShc) -
Q<Hea|Coo>SetUniShc_flow),
where f<Hea|Coo>Shc is the linear interpolation of the module heating or
cooling capacity along the part load ratio at the actual source and sink temperature,
based on the performance data provided for SHC operation.
This excess heat flow rate is compensated by cycling a single module, which gives theg expression of the cycling ratio for this module as
ratCycShc = 1 - min(1, max(QHeaShcExc_flow / fHeaShc(PLRShc), QCooShcExc_flow / fCooShc(PLRShc))),
where ratCycShc = 1 means perfect balance, i.e., the module does not cycle and
continuously runs in SHC mode, and ratCycShc = 0 means that the module continuously
runs in single mode.
The actual heating or cooling heat flow rate of the modules in SHC mode is
Q<Hea|Coo>Shc_flow = (nUniShc - 1 + ratCycShc) * f<Hea|Coo>Shc(PLRShc).
The residual load that the module which cycles between SHC and single-mode must handle is
Q<Hea|Coo>SetUniShc_flow * nUniShc - Q<Hea|Coo>Shc_flow,
which gives the part load ratio PLR<Hea|Coo>ShcCyc of this module while
it runs in single mode.
The corresponding heating or cooling heat flow rate is then
Q<Hea|Coo>ShcCyc_flow = (1 - ratCycShc) * f<Hea|Coo>(PLR<Hea|Coo>ShcCyc),
where f<Hea|Coo> is the linear interpolation of the module capacity along
the part load ratio at the actual source and sink temperature,
based on the performance data provided for single-mode operation.
The residual heating or cooling loads that the modules running in single mode must meet can now be calculated as
Q<Hea|Coo>SetRes_flow = Q<Hea|Coo>Set_flow -
(Q<Hea|Coo>Shc_flow + Q<Hea|Coo>ShcCyc_flow),
which ultimately allows calculating the PLR value of these modules and their contribution to the total heating and cooling output of the bank.
Implementation limitations
The load balancing logic relies on a subset of modules producing excess heat flow rate
while another module compensates for it.
The fundamental assumption of even load between modules therefore breaks down on
the non-dominant side.
In a real system where the modules are hydronically balanced, this load imbalance yields
varying leaving temperatures across modules.
In the worst case, the deviation from setpoint is ΔT⋅SPLR / 2,
where ΔT is the design temperature difference.
These temperature discrepancies are neglected in the model which "numerically absorbs" them by simply adjusting the load that each module must handle. This creates a modeling uncertainty that is deemed acceptable given the error magnitude and partial cancellation of opposing errors from modules that exhibit setpoint overshoot and modules that exhibit setpoint undershoot.
References
- Eurovent (2025). Technical certification rules (TCR) of the Eurovent certified performance mark liquid chilling packages and hydronic heat pumps (ECP - 3 LCPHP, Rev. 02-2025). https://www.eurovent-certification.com/media/images/c2c/031/c2c031f2dd38173a81e30a42f7d6f42a386f047c.pdf
- Johnson Controls, Inc. (2024). YMAE application guide - YMAE air-to-water inverter scroll heat pumps. YORK.
Parameters
| Type | Name | Default | Description |
|---|---|---|---|
| Integer | nUni | 1 | Number of modules |
| Boolean | use_TLoaLvgForCtl | true | Set to true for leaving temperature control, false for entering temperature control |
| Boolean | use_TEvaOutForTab | =true to use CHW temperature at outlet for table data, false for inlet | |
| Boolean | use_TConOutForTab | =true to use HW temperature at outlet for table data, false for inlet | |
| Modelica.Units.SI.DimensionlessRatio[:] | PLRHeaSup | PLR values at which heat flow rate and power data are provided - Heating | |
| Modelica.Units.SI.DimensionlessRatio[:] | PLRCooSup | PLR values at which heat flow rate and power data are provided - Cooling | |
| Modelica.Units.SI.DimensionlessRatio[:] | PLRShcSup | PLR values at which heat flow rate and power data are provided - SHC | |
| Modelica.Units.SI.DimensionlessRatio | PLRHeaCyc_min | min(PLRHeaSup) | Minimum PLR before cycling off the last compressor - Heating |
| Modelica.Units.SI.DimensionlessRatio | PLRCooCyc_min | min(PLRCooSup) | Minimum PLR before cycling off the last compressor - Cooling |
| Modelica.Units.SI.DimensionlessRatio | PLRShcCyc_min | min(PLRShcSup) | Minimum PLR before cycling off the last compressor - SHC |
| Modelica.Units.SI.Power | P_min | 0 | Remaining power when system is enabled with all compressors cycled off |
| Integer | nPLRHea | size(PLRHeaSup, 1) | Number of PLR support points - Heating |
| Integer | nPLRCoo | size(PLRCooSup, 1) | Number of PLR support points - Cooling |
| Integer | nPLRShc | size(PLRShcSup, 1) | Number of PLR support points - SHC |
| String | fileNameHea | File where performance data are stored - Heating (single module) | |
| String | fileNameCoo | File where performance data are stored - Cooling (single module) | |
| String | fileNameShc | File where performance data are stored - SHC (single module) | |
| Modelica.Blocks.Types.Smoothness | smoothness | Modelica.Blocks.Types.Smoothness.LinearSegments | Smoothness of table interpolation |
| Modelica.Blocks.Types.Extrapolation | extrapolation | Modelica.Blocks.Types.Extrapolation.HoldLastPoint | Extrapolation of data outside the definition range |
| Modelica.Units.SI.Power[nPLRHea] | PHeaInt_nominal | Power interpolated at nominal conditions, at each PLR - Heating, single module | |
| Modelica.Units.SI.HeatFlowRate[nPLRHea] | QHeaInt_flow_nominal | Heat flow rate interpolated at nominal conditions, at each PLR - Heating, single module | |
| Modelica.Units.SI.Power | PHeaInt1_nominal | Modelica.Math.Vectors.interpolate(PLRHeaSor, PHeaInt_nominal, 1) | Power interpolated at nominal conditions, at PLR=1 - Heating, single module |
| Modelica.Units.SI.HeatFlowRate | QHeaInt1_flow_nominal | Modelica.Math.Vectors.interpolate(PLRHeaSor, QHeaInt_flow_nominal, 1) | Heat flow rate interpolated at nominal conditions, at PLR=1 - Heating, single module |
| Modelica.Units.SI.Power[nPLRCoo] | PCooInt_nominal | Power interpolated at nominal conditions, at each PLR - Cooling, single module | |
| Modelica.Units.SI.HeatFlowRate[nPLRCoo] | QCooInt_flow_nominal | Heat flow rate interpolated at nominal conditions, at each PLR - Cooling, single module | |
| Modelica.Units.SI.Power | PCooInt1_nominal | Modelica.Math.Vectors.interpolate(PLRCooSor, PCooInt_nominal, 1) | Power interpolated at nominal conditions, at PLR=1 - Cooling, single module |
| Modelica.Units.SI.HeatFlowRate | QCooInt1_flow_nominal | Modelica.Math.Vectors.interpolate(PLRCooSor, QCooInt_flow_nominal, 1) | Heat flow rate interpolated at nominal conditions, at PLR=1 - Cooling, single module |
| Modelica.Units.SI.Power[nPLRShc] | PShcInt_nominal | Power interpolated at nominal conditions, at each PLR - SHC, single module | |
| Modelica.Units.SI.HeatFlowRate[nPLRShc] | QCooShcInt_flow_nominal | Cooling heat flow rate interpolated at nominal conditions, at each PLR - SHC, single module | |
| Modelica.Units.SI.Power | PShcInt1_nominal | Modelica.Math.Vectors.interpolate(PLRShcSor, PShcInt_nominal, 1) | Power interpolated at nominal conditions, at PLR=1 - SHC, single module |
| Modelica.Units.SI.HeatFlowRate | QCooShcInt1_flow_nominal | Modelica.Math.Vectors.interpolate(PLRShcSor, QCooShcInt_flow_nominal, 1) | Cooling heat flow rate interpolated at nominal conditions, at PLR=1 - SHC, single module |
| Modelica.Units.SI.HeatFlowRate | QHeaShcInt1_flow_nominal | PShcInt1_nominal - QCooShcInt1_flow_nominal | Heating heat flow rate at nominal conditions, at PLR=1 - SHC, single module |
| Real | scaFacHea | QHea_flow_nominal/(nUni*QHeaInt1_flow_nominal) | Scaling factor for interpolated heat flow rate and power - Heating |
| Real | scaFacCoo | QCoo_flow_nominal/(nUni*QCooInt1_flow_nominal) | Scaling factor for interpolated heat flow rate and power - Cooling |
| Real | scaFacCooShc | QCooShc_flow_nominal/(nUni*QCooShcInt1_flow_nominal) | Scaling factor for interpolated cooling heat flow rate and power - SHC |
| Real | scaFacHeaShc | QHeaShc_flow_nominal/(nUni*QHeaShcInt1_flow_nominal) | Scaling factor for interpolated heating heat flow rate - SHC |
| Modelica.Units.SI.Power | P_nominal | max({scaFacHea*PHeaInt1_nominal, scaFacCoo*PCooInt1_nominal, scaFacCooShc*PShcInt1_nominal}) | Maximum power at nominal conditions (external use) - All modes |
| Advanced | |||
| String[nPLRHea] | tabNamQHea | {"q@" + String(p, format = ".2f") for p in PLRHeaSor} | Table names with heat flow rate data - Heating |
| String[nPLRHea] | tabNamPHea | {"p@" + String(p, format = ".2f") for p in PLRHeaSor} | Table names with power data - Heating |
| String[nPLRCoo] | tabNamQCoo | {"q@" + String(p, format = ".2f") for p in PLRCooSor} | Table names with heat flow rate data - Cooling |
| String[nPLRCoo] | tabNamPCoo | {"p@" + String(p, format = ".2f") for p in PLRCooSor} | Table names with power data - Cooling |
| String[nPLRShc] | tabNamQShc | {"q@" + String(p, format = ".2f") for p in PLRShcSor} | Table names with cooling heat flow rate data - SHC |
| String[nPLRShc] | tabNamPShc | {"p@" + String(p, format = ".2f") for p in PLRShcSor} | Table names with power data - SHC |
| Nominal condition | |||
| Modelica.Units.SI.Temperature | THw_nominal | HW temperature — Entering or leaving depending on use_TConOutForTab | |
| Modelica.Units.SI.Temperature | TChw_nominal | CHW temperature — Entering or leaving depending on use_TEvaOutForTab | |
| Nominal condition - Heating | |||
| Modelica.Units.SI.Temperature | TAmbHea_nominal | Ambient-side fluid temperature — Entering | |
| Modelica.Units.SI.HeatFlowRate | QHea_flow_nominal | Heating heat flow rate - All modules | |
| Nominal condition - Cooling | |||
| Modelica.Units.SI.Temperature | TAmbCoo_nominal | Ambient-side fluid temperature — Entering | |
| Modelica.Units.SI.HeatFlowRate | QCoo_flow_nominal | Cooling heat flow rate - All modules | |
| Nominal condition - SHC | |||
| Modelica.Units.SI.HeatFlowRate | QHeaShc_flow_nominal | Heating heat flow rate - All modules | |
| Modelica.Units.SI.HeatFlowRate | QCooShc_flow_nominal | Cooling heat flow rate - All modules | |
| Advanced › Staging logic | |||
| Real | dtRun | 300 | Minimum stage runtime |
| Real | dtMea | 120 | Load averaging time window |
| Real | SPLR | 0.9 | Staging part load ratio |
| Advanced › Safeties | |||
| Modelica.Units.SI.TemperatureDifference | dTSaf | 2 | Maximum temperature deviation from setpoint before limiting demand for safety (>0) |
Connectors
Revisions
-
March 23, 2026, by Antoine Gautier:
Refactored with two separate connectors for heating and cooling on/off commands.
This is for #4507. -
July 1, 2025, by Antoine Gautier:
First implementation.