blockTableData2DLoadDepSHC

Modeling block for simultaneous heating and cooling systems based on load-dependent 2D table data

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.

  1. Heating-only: In this mode, all modules operate as heat pumps, tracking the HW temperature setpoint and sourcing heat from the ambient-side fluid.
  2. Cooling-only: In this mode, all modules operate as chillers, tracking the CHW temperature setpoint and rejecting heat to the ambient-side fluid.
  3. 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),
    where max(QHeaShcInt_flow) is the heating capacity of one module in SHC mode and SPLR is a parameter representing the staging part load ratio. Note that this parameter should be strictly lower than 1 because the number of staged modules ultimately conditions the opening of isolation valves and the staging of primary pumps. If SPLR = 1 it 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),
    where min(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),
    where QHeaSetResMea_flow is the residual heating load, calculated as the time-averaged heating load minus the heating output of modules in SHC mode, and max(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),
    where QCooSetResMea_flow is the residual cooling load, calculated as the time-averaged cooling load minus the cooling output of modules in SHC mode, and min(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

Parameters

TypeNameDefaultDescription
IntegernUni1Number of modules
Booleanuse_TLoaLvgForCtltrueSet to true for leaving temperature control, false for entering temperature control
Booleanuse_TEvaOutForTab=true to use CHW temperature at outlet for table data, false for inlet
Booleanuse_TConOutForTab=true to use HW temperature at outlet for table data, false for inlet
Modelica.Units.SI.DimensionlessRatio[:]PLRHeaSupPLR values at which heat flow rate and power data are provided - Heating
Modelica.Units.SI.DimensionlessRatio[:]PLRCooSupPLR values at which heat flow rate and power data are provided - Cooling
Modelica.Units.SI.DimensionlessRatio[:]PLRShcSupPLR values at which heat flow rate and power data are provided - SHC
Modelica.Units.SI.DimensionlessRatioPLRHeaCyc_minmin(PLRHeaSup)Minimum PLR before cycling off the last compressor - Heating
Modelica.Units.SI.DimensionlessRatioPLRCooCyc_minmin(PLRCooSup)Minimum PLR before cycling off the last compressor - Cooling
Modelica.Units.SI.DimensionlessRatioPLRShcCyc_minmin(PLRShcSup)Minimum PLR before cycling off the last compressor - SHC
Modelica.Units.SI.PowerP_min0Remaining power when system is enabled with all compressors cycled off
IntegernPLRHeasize(PLRHeaSup, 1)Number of PLR support points - Heating
IntegernPLRCoosize(PLRCooSup, 1)Number of PLR support points - Cooling
IntegernPLRShcsize(PLRShcSup, 1)Number of PLR support points - SHC
StringfileNameHeaFile where performance data are stored - Heating (single module)
StringfileNameCooFile where performance data are stored - Cooling (single module)
StringfileNameShcFile where performance data are stored - SHC (single module)
Modelica.Blocks.Types.SmoothnesssmoothnessModelica.Blocks.Types.Smoothness.LinearSegmentsSmoothness of table interpolation
Modelica.Blocks.Types.ExtrapolationextrapolationModelica.Blocks.Types.Extrapolation.HoldLastPointExtrapolation of data outside the definition range
Modelica.Units.SI.Power[nPLRHea]PHeaInt_nominalPower interpolated at nominal conditions, at each PLR - Heating, single module
Modelica.Units.SI.HeatFlowRate[nPLRHea]QHeaInt_flow_nominalHeat flow rate interpolated at nominal conditions, at each PLR - Heating, single module
Modelica.Units.SI.PowerPHeaInt1_nominalModelica.Math.Vectors.interpolate(PLRHeaSor, PHeaInt_nominal, 1)Power interpolated at nominal conditions, at PLR=1 - Heating, single module
Modelica.Units.SI.HeatFlowRateQHeaInt1_flow_nominalModelica.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_nominalPower interpolated at nominal conditions, at each PLR - Cooling, single module
Modelica.Units.SI.HeatFlowRate[nPLRCoo]QCooInt_flow_nominalHeat flow rate interpolated at nominal conditions, at each PLR - Cooling, single module
Modelica.Units.SI.PowerPCooInt1_nominalModelica.Math.Vectors.interpolate(PLRCooSor, PCooInt_nominal, 1)Power interpolated at nominal conditions, at PLR=1 - Cooling, single module
Modelica.Units.SI.HeatFlowRateQCooInt1_flow_nominalModelica.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_nominalPower interpolated at nominal conditions, at each PLR - SHC, single module
Modelica.Units.SI.HeatFlowRate[nPLRShc]QCooShcInt_flow_nominalCooling heat flow rate interpolated at nominal conditions, at each PLR - SHC, single module
Modelica.Units.SI.PowerPShcInt1_nominalModelica.Math.Vectors.interpolate(PLRShcSor, PShcInt_nominal, 1)Power interpolated at nominal conditions, at PLR=1 - SHC, single module
Modelica.Units.SI.HeatFlowRateQCooShcInt1_flow_nominalModelica.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.HeatFlowRateQHeaShcInt1_flow_nominalPShcInt1_nominal - QCooShcInt1_flow_nominalHeating heat flow rate at nominal conditions, at PLR=1 - SHC, single module
RealscaFacHeaQHea_flow_nominal/(nUni*QHeaInt1_flow_nominal)Scaling factor for interpolated heat flow rate and power - Heating
RealscaFacCooQCoo_flow_nominal/(nUni*QCooInt1_flow_nominal)Scaling factor for interpolated heat flow rate and power - Cooling
RealscaFacCooShcQCooShc_flow_nominal/(nUni*QCooShcInt1_flow_nominal)Scaling factor for interpolated cooling heat flow rate and power - SHC
RealscaFacHeaShcQHeaShc_flow_nominal/(nUni*QHeaShcInt1_flow_nominal)Scaling factor for interpolated heating heat flow rate - SHC
Modelica.Units.SI.PowerP_nominalmax({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.TemperatureTHw_nominalHW temperature — Entering or leaving depending on use_TConOutForTab
Modelica.Units.SI.TemperatureTChw_nominalCHW temperature — Entering or leaving depending on use_TEvaOutForTab
Nominal condition - Heating
Modelica.Units.SI.TemperatureTAmbHea_nominalAmbient-side fluid temperature — Entering
Modelica.Units.SI.HeatFlowRateQHea_flow_nominalHeating heat flow rate - All modules
Nominal condition - Cooling
Modelica.Units.SI.TemperatureTAmbCoo_nominalAmbient-side fluid temperature — Entering
Modelica.Units.SI.HeatFlowRateQCoo_flow_nominalCooling heat flow rate - All modules
Nominal condition - SHC
Modelica.Units.SI.HeatFlowRateQHeaShc_flow_nominalHeating heat flow rate - All modules
Modelica.Units.SI.HeatFlowRateQCooShc_flow_nominalCooling heat flow rate - All modules
Advanced › Staging logic
RealdtRun300Minimum stage runtime
RealdtMea120Load averaging time window
RealSPLR0.9Staging part load ratio
Advanced › Safeties
Modelica.Units.SI.TemperatureDifferencedTSaf2Maximum temperature deviation from setpoint before limiting demand for safety (>0)

Connectors

TypeNameDefaultDescription
Buildings.Controls.OBC.CDL.Interfaces.BooleanInputonHeaHeating on/off command
Buildings.Controls.OBC.CDL.Interfaces.BooleanInputonCooCooling on/off command
Buildings.Controls.OBC.CDL.Interfaces.RealInputTHwEntCondenser entering HW temperature
Buildings.Controls.OBC.CDL.Interfaces.RealInputTHwLvgCondenser leaving HW temperature
Buildings.Controls.OBC.CDL.Interfaces.RealInputTChwEntEvaporator entering CHW temperature
Buildings.Controls.OBC.CDL.Interfaces.RealInputTChwLvgEvaporator leaving CHW temperature
Buildings.Controls.OBC.CDL.Interfaces.RealInputTAmbEntEntering fluid temperature on ambient side
Buildings.Controls.OBC.CDL.Interfaces.RealInputcpHwHW specific heat capacity
Buildings.Controls.OBC.CDL.Interfaces.RealInputcpChwCHW specific heat capacity
Buildings.Controls.OBC.CDL.Interfaces.RealInputTChwSetCHW temperature setpoint
Buildings.Controls.OBC.CDL.Interfaces.RealInputTHwSetHW temperature setpoint
Buildings.Controls.OBC.CDL.Interfaces.RealInputmHw_flowHW mass flow rate
Buildings.Controls.OBC.CDL.Interfaces.RealInputmChw_flowCHW mass flow rate
Buildings.Controls.OBC.CDL.Interfaces.RealOutputPInput power
Buildings.Controls.OBC.CDL.Interfaces.RealOutputQHea_flowHeating heat flow rate
Buildings.Controls.OBC.CDL.Interfaces.RealOutputQCoo_flowCooling heat flow rate
Buildings.Controls.OBC.CDL.Interfaces.IntegerOutputnUniHeaNumber of modules in heating mode
Buildings.Controls.OBC.CDL.Interfaces.IntegerOutputnUniCooNumber of modules in cooling mode
Buildings.Controls.OBC.CDL.Interfaces.IntegerOutputnUniShcNumber of modules in SHC mode (may be cycling into single mode)

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.