Skip to content

Commit

Permalink
Add support for VRF terminals and zonal unitary systems (PTHP, PTAC, …
Browse files Browse the repository at this point in the history
…WAHP). Missing unit test for the latter.
  • Loading branch information
lymereJ committed Jul 26, 2024
1 parent 15f6491 commit f57c2fb
Show file tree
Hide file tree
Showing 6 changed files with 258 additions and 14 deletions.
41 changes: 35 additions & 6 deletions src/EnergyPlus/AirflowNetwork/src/Solver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@
#include <EnergyPlus/GlobalNames.hh>
#include <EnergyPlus/HVACHXAssistedCoolingCoil.hh>
#include <EnergyPlus/HVACStandAloneERV.hh>
#include <EnergyPlus/HVACVariableRefrigerantFlow.hh>
#include <EnergyPlus/HeatingCoils.hh>
#include <EnergyPlus/InputProcessing/InputProcessor.hh>
#include <EnergyPlus/MixedAir.hh>
Expand All @@ -100,6 +101,7 @@
#include <EnergyPlus/SingleDuct.hh>
#include <EnergyPlus/SplitterComponent.hh>
#include <EnergyPlus/ThermalComfort.hh>
#include <EnergyPlus/UnitarySystem.hh>
#include <EnergyPlus/UtilityRoutines.hh>
#include <EnergyPlus/WaterThermalTanks.hh>
#include <EnergyPlus/ZoneDehumidifier.hh>
Expand Down Expand Up @@ -10159,8 +10161,11 @@ namespace AirflowNetwork {
EPVector<DataLoopNode::ConnectionType> NodeConnectionType; // Specifies the type of node connection
std::string CurrentModuleObject;

bool HPWHFound(false); // Flag for HPWH identification
bool StandaloneERVFound(false); // Flag for Standalone ERV (ZoneHVAC:EnergyRecoveryVentilator) identification
bool hpwhFound(false); // Flag for HPWH identification
bool standaloneERVFound(false); // Flag for Standalone ERV (ZoneHVAC:EnergyRecoveryVentilator) identification
bool packagedUnitaryFound(false); // Flag for packaged unitary systems (ZoneHVAC:PackagedTerminalAirConditioner,
// ZoneHVAC:PackagedTerminalHeatPump, ZoneHVAC:WaterToAirHeatPump) identification
bool vrfTUFound(false);

// Validate supply and return connections
NodeFound.dimension(m_state.dataLoopNodes->NumOfNodes, false);
Expand Down Expand Up @@ -10265,13 +10270,25 @@ namespace AirflowNetwork {
// Skip HPWH nodes that don't have to be included in the AFN
if (GetHeatPumpWaterHeaterNodeNumber(m_state, i)) {
NodeFound(i) = true;
HPWHFound = true;
hpwhFound = true;
}

// Skip Standalone ERV nodes that don't have to be included in the AFN
if (GetStandAloneERVNodeNumber(m_state, i)) {
NodeFound(i) = true;
StandaloneERVFound = true;
standaloneERVFound = true;
}

// Skip zonal unitary system based nodes that don't have to be included in the AFN
if (UnitarySystems::getUnitarySystemNodeNumber(m_state, i)) {
NodeFound(i) = true;
packagedUnitaryFound = true;
}

// Skip zonal vrf terminal nodes that don't have to be included in the AFN
if (HVACVariableRefrigerantFlow::getVRFTUNodeNumber(m_state, i)) {
NodeFound(i) = true;
vrfTUFound = true;
}
}

Expand Down Expand Up @@ -10403,16 +10420,28 @@ namespace AirflowNetwork {
}
}
}
if (HPWHFound) {
if (hpwhFound) {
ShowWarningError(m_state,
format(RoutineName) + "Heat pump water heater is simulated along with an AirflowNetwork but is not included in "
"the AirflowNetwork.");
}
if (StandaloneERVFound) {
if (standaloneERVFound) {
ShowWarningError(m_state,
format(RoutineName) + "A ZoneHVAC:EnergyRecoveryVentilator is simulated along with an AirflowNetwork but is not "
"included in the AirflowNetwork.");
}
if (packagedUnitaryFound) {
ShowWarningError(m_state,
format(RoutineName) + "A ZoneHVAC:PackagedTerminalAirConditioner, ZoneHVAC:PackagedTerminalHeatPump, or "
"ZoneHVAC:WaterToAirHeatPump is simulated along with an AirflowNetwork but is not "
"included in the AirflowNetwork.");
}
if (vrfTUFound) {
ShowWarningError(m_state,
format(RoutineName) +
"A ZoneHVAC:TerminalUnit:VariableRefrigerantFlow is simulated along with an AirflowNetwork but is not "
"included in the AirflowNetwork.");
}
NodeFound.deallocate();

// Assign AirLoop Number to every node and linkage
Expand Down
22 changes: 22 additions & 0 deletions src/EnergyPlus/HVACVariableRefrigerantFlow.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10822,6 +10822,28 @@ void getVRFTUZoneLoad(
}
}

bool getVRFTUNodeNumber(EnergyPlusData &state, int const nodeNumber)
{
for (int vrfTUIndex = 1; vrfTUIndex <= state.dataHVACVarRefFlow->NumVRFTU; ++vrfTUIndex) {
auto &vrfTU = state.dataHVACVarRefFlow->VRFTU(vrfTUIndex);

bool vrfTUOutdoorAir = false;
if (vrfTU.CoolOutAirVolFlow == 0 && vrfTU.HeatOutAirVolFlow == 0 && vrfTU.NoCoolHeatOutAirVolFlow == 0) {
vrfTUOutdoorAir = true;
}

if (vrfTUOutdoorAir &&
(nodeNumber == vrfTU.VRFTUInletNodeNum || nodeNumber == vrfTU.VRFTUOutletNodeNum || nodeNumber == vrfTU.fanInletNode ||
nodeNumber == vrfTU.fanOutletNode || nodeNumber == vrfTU.heatCoilAirOutNode || nodeNumber == vrfTU.coolCoilAirOutNode ||
nodeNumber == vrfTU.VRFTUOAMixerOANodeNum || nodeNumber == vrfTU.VRFTUOAMixerRelNodeNum || nodeNumber == vrfTU.VRFTUOAMixerRetNodeNum ||
nodeNumber == vrfTU.VRFTUOAMixerMixedNodeNum || nodeNumber == vrfTU.SuppHeatCoilAirInletNode ||
nodeNumber == vrfTU.SuppHeatCoilAirOutletNode)) {
return true;
}
return false;
}
}

void VRFCondenserEquipment::CalcVRFIUTeTc_FluidTCtrl(EnergyPlusData &state)
{
// SUBROUTINE INFORMATION:
Expand Down
2 changes: 2 additions & 0 deletions src/EnergyPlus/HVACVariableRefrigerantFlow.hh
Original file line number Diff line number Diff line change
Expand Up @@ -929,6 +929,8 @@ namespace HVACVariableRefrigerantFlow {
void getVRFTUZoneLoad(
EnergyPlusData &state, int const VRFTUNum, Real64 &zoneLoad, Real64 &LoadToHeatingSP, Real64 &LoadToCoolingSP, bool const InitFlag);

bool getVRFTUNodeNumber(EnergyPlusData &state, int const nodeNumber);

void ReportVRFTerminalUnit(EnergyPlusData &state, int VRFTUNum); // index to VRF terminal unit

void ReportVRFCondenser(EnergyPlusData &state, int VRFCond); // index to VRF condensing unit
Expand Down
51 changes: 43 additions & 8 deletions src/EnergyPlus/UnitarySystem.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10149,7 +10149,8 @@ namespace UnitarySystems {
Real64 TotalOutputDelta = 0.0; // delta total output rate, {W}
int ZoneInNode = this->m_ZoneInletNode;
Real64 MassFlowRate = state.dataLoopNodes->Node(ZoneInNode).MassFlowRate / this->ControlZoneMassFlowFrac;
if (state.afn->distribution_simulated) {
if (state.afn->distribution_simulated && this->m_sysType != SysType::PackagedAC && this->m_sysType != SysType::PackagedHP &&
this->m_sysType != SysType::PackagedWSHP) {
DeltaMassRate = state.dataLoopNodes->Node(this->AirOutNode).MassFlowRate -
state.dataLoopNodes->Node(ZoneInNode).MassFlowRate / this->ControlZoneMassFlowFrac;
if (DeltaMassRate < 0.0) DeltaMassRate = 0.0;
Expand Down Expand Up @@ -12143,7 +12144,8 @@ namespace UnitarySystems {
Real64 DesOutHumRat = this->m_DesiredOutletHumRat;
int CoilType_Num = this->m_CoolingCoilType_Num;
Real64 LoopDXCoilMaxRTFSave = 0.0;
if (state.afn->distribution_simulated) {
if (state.afn->distribution_simulated && this->m_sysType != SysType::PackagedAC && this->m_sysType != SysType::PackagedHP &&
this->m_sysType != SysType::PackagedWSHP) {
LoopDXCoilMaxRTFSave = state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).AFNLoopDXCoilRTF;
state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).AFNLoopDXCoilRTF = 0.0;
}
Expand Down Expand Up @@ -13897,7 +13899,8 @@ namespace UnitarySystems {
this->m_CoolingCycRatio = CycRatio;
this->m_DehumidificationMode = DehumidMode;

if (state.afn->distribution_simulated) {
if (state.afn->distribution_simulated && this->m_sysType != SysType::PackagedAC && this->m_sysType != SysType::PackagedHP &&
this->m_sysType != SysType::PackagedWSHP) {
state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).AFNLoopDXCoilRTF =
max(state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).AFNLoopDXCoilRTF, LoopDXCoilMaxRTFSave);
}
Expand Down Expand Up @@ -13952,7 +13955,8 @@ namespace UnitarySystems {

Real64 LoopHeatingCoilMaxRTFSave = 0.0;
Real64 LoopDXCoilMaxRTFSave = 0.0;
if (state.afn->distribution_simulated) {
if (state.afn->distribution_simulated && this->m_sysType != SysType::PackagedAC && this->m_sysType != SysType::PackagedHP &&
this->m_sysType != SysType::PackagedWSHP) {
LoopHeatingCoilMaxRTFSave = state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).AFNLoopHeatingCoilMaxRTF;
state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).AFNLoopHeatingCoilMaxRTF = 0.0;
LoopDXCoilMaxRTFSave = state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).AFNLoopDXCoilRTF;
Expand Down Expand Up @@ -14571,7 +14575,8 @@ namespace UnitarySystems {
this->m_HeatingCycRatio = CycRatio;
HeatCoilLoad = ReqOutput;

if (state.afn->distribution_simulated) {
if (state.afn->distribution_simulated && this->m_sysType != SysType::PackagedAC && this->m_sysType != SysType::PackagedHP &&
this->m_sysType != SysType::PackagedWSHP) {
state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).AFNLoopHeatingCoilMaxRTF =
max(state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).AFNLoopHeatingCoilMaxRTF, LoopHeatingCoilMaxRTFSave);
state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).AFNLoopDXCoilRTF =
Expand Down Expand Up @@ -14622,7 +14627,8 @@ namespace UnitarySystems {

Real64 LoopHeatingCoilMaxRTFSave = 0.0;
Real64 LoopDXCoilMaxRTFSave = 0.0;
if (state.afn->distribution_simulated) {
if (state.afn->distribution_simulated && this->m_sysType != SysType::PackagedAC && this->m_sysType != SysType::PackagedHP &&
this->m_sysType != SysType::PackagedWSHP) {
auto &afnInfo = state.dataAirLoop->AirLoopAFNInfo(AirLoopNum);
LoopHeatingCoilMaxRTFSave = afnInfo.AFNLoopHeatingCoilMaxRTF;
afnInfo.AFNLoopHeatingCoilMaxRTF = 0.0;
Expand Down Expand Up @@ -14975,7 +14981,8 @@ namespace UnitarySystems {
} // IF((GetCurrentScheduleValue(state, UnitarySystem(UnitarySysNum)%m_SysAvailSchedPtr) > 0.0d0) .AND. &

// LoopHeatingCoilMaxRTF used for AirflowNetwork gets set in child components (gas and fuel)
if (state.afn->distribution_simulated) {
if (state.afn->distribution_simulated && this->m_sysType != SysType::PackagedAC && this->m_sysType != SysType::PackagedHP &&
this->m_sysType != SysType::PackagedWSHP) {
auto &afnInfo = state.dataAirLoop->AirLoopAFNInfo(AirLoopNum);
afnInfo.AFNLoopHeatingCoilMaxRTF = max(afnInfo.AFNLoopHeatingCoilMaxRTF, LoopHeatingCoilMaxRTFSave);
afnInfo.AFNLoopDXCoilRTF = max(afnInfo.AFNLoopDXCoilRTF, LoopDXCoilMaxRTFSave);
Expand Down Expand Up @@ -15664,7 +15671,8 @@ namespace UnitarySystems {
this->m_ElecPower = locFanElecPower + elecCoolingPower + elecHeatingPower + suppHeatingPower + defrostElecPower + this->m_TotalAuxElecPower;
this->m_ElecPowerConsumption = this->m_ElecPower * ReportingConstant;

if (state.afn->distribution_simulated) {
if (state.afn->distribution_simulated && this->m_sysType != SysType::PackagedAC && this->m_sysType != SysType::PackagedHP &&
this->m_sysType != SysType::PackagedWSHP) {
state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).LoopSystemOnMassFlowrate = state.dataUnitarySystems->CompOnMassFlow;
state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).LoopSystemOffMassFlowrate = state.dataUnitarySystems->CompOffMassFlow;
state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).LoopFanOperationMode = this->m_FanOpMode;
Expand Down Expand Up @@ -16718,6 +16726,33 @@ namespace UnitarySystems {
return false;
}

bool getUnitarySystemNodeNumber(EnergyPlusData &state, int const nodeNumber)
{
for (int unitarySysIndex = 0; unitarySysIndex <= state.dataUnitarySystems->numUnitarySystems - 1; ++unitarySysIndex) {
auto &unitarySys = state.dataUnitarySystems->unitarySys[unitarySysIndex];

int FanInletNodeIndex = state.dataFans->fans(unitarySys.m_FanIndex)->inletNodeNum;
int FanOutletNodeIndex = state.dataFans->fans(unitarySys.m_FanIndex)->outletNodeNum;

bool unitarySysOutdoorAir = false;
if (unitarySys.m_CoolOutAirVolFlow == 0 && unitarySys.m_HeatOutAirVolFlow == 0 && unitarySys.m_NoCoolHeatOutAirVolFlow == 0) {
unitarySysOutdoorAir = true;
}

if (unitarySys.m_sysType == UnitarySys::SysType::PackagedWSHP || unitarySys.m_sysType == UnitarySys::SysType::PackagedAC ||
unitarySys.m_sysType == UnitarySys::SysType::PackagedHP) {
if (unitarySysOutdoorAir && (nodeNumber == FanInletNodeIndex || nodeNumber == FanOutletNodeIndex ||
nodeNumber == unitarySys.AirInNode || nodeNumber == unitarySys.m_OAMixerNodes[0] ||
nodeNumber == unitarySys.m_OAMixerNodes[1] || nodeNumber == unitarySys.m_OAMixerNodes[2]) ||
nodeNumber == unitarySys.m_OAMixerNodes[3] || nodeNumber == unitarySys.CoolCoilOutletNodeNum ||
nodeNumber == unitarySys.HeatCoilOutletNodeNum) {
return true;
}
}
}
return false;
}

void setupAllOutputVars(EnergyPlusData &state, int const numAllSystemTypes)
{
// setup reports only once
Expand Down
1 change: 1 addition & 0 deletions src/EnergyPlus/UnitarySystem.hh
Original file line number Diff line number Diff line change
Expand Up @@ -952,6 +952,7 @@ namespace UnitarySystems {

int getDesignSpecMSHPIndex(EnergyPlusData &state, std::string_view objectName);
int getUnitarySystemIndex(EnergyPlusData &state, std::string_view objectName);
bool getUnitarySystemNodeNumber(EnergyPlusData &state, int const nodeNumber);

bool searchZoneInletNodes(EnergyPlusData &state, int nodeToFind, int &ZoneEquipConfigIndex, int &InletNodeIndex);
bool searchZoneInletNodesByEquipmentIndex(EnergyPlusData &state, int nodeToFind, int zoneEquipmentIndex);
Expand Down
Loading

5 comments on commit f57c2fb

@nrel-bot-2b
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

allow_wahp_afn (lymereJ) - x86_64-Linux-Ubuntu-22.04-gcc-11.4: OK (3634 of 3686 tests passed, 750 test warnings)

Messages:\n

  • 789 tests had: EIO diffs.
  • 227 tests had: ESO small diffs.
  • 196 tests had: MTR small diffs.
  • 149 tests had: Table small diffs.
  • 12 tests had: Table big diffs.
  • 35 tests had: Table string diffs.
  • 41 tests had: ERR diffs.
  • 8 tests had: ESO big diffs.
  • 2 tests had: EDD diffs.
  • 1 test had: JSON big diffs.
  • 1 test had: MTR big diffs.

Failures:\n

EnergyPlusFixture Test Summary

  • Passed: 1563
  • SEGFAULT: 5

integration Test Summary

  • Passed: 795
  • Failed: 2

regression Test Summary

  • Passed: 766
  • Failed: 45

Build Badge Test Badge

@nrel-bot
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

allow_wahp_afn (lymereJ) - Win64-Windows-10-VisualStudio-16: OK (2849 of 2853 tests passed, 0 test warnings)

Failures:\n

EnergyPlusFixture Test Summary

  • Passed: 1562
  • Failed: 4

Build Badge Test Badge

@nrel-bot-3
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

allow_wahp_afn (lymereJ) - x86_64-MacOS-10.18-clang-15.0.0: OK (3601 of 3645 tests passed, 747 test warnings)

Messages:\n

  • 787 tests had: EIO diffs.
  • 219 tests had: ESO small diffs.
  • 34 tests had: Table string diffs.
  • 194 tests had: MTR small diffs.
  • 143 tests had: Table small diffs.
  • 1 test had: JSON small diffs.
  • 12 tests had: Table big diffs.
  • 43 tests had: ERR diffs.
  • 9 tests had: ESO big diffs.
  • 2 tests had: EDD diffs.
  • 1 test had: JSON big diffs.
  • 1 test had: MTR big diffs.

Failures:\n

regression Test Summary

  • Passed: 747
  • Failed: 44

Build Badge Test Badge

@nrel-bot-2b
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

allow_wahp_afn (lymereJ) - x86_64-Linux-Ubuntu-22.04-gcc-11.4-IntegrationCoverage-Debug: OK (795 of 795 tests passed, 0 test warnings)

Build Badge Test Badge Coverage Badge

@nrel-bot-2c
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

allow_wahp_afn (lymereJ) - x86_64-Linux-Ubuntu-22.04-gcc-11.4-UnitTestsCoverage-Debug: OK (2061 of 2061 tests passed, 0 test warnings)

Build Badge Test Badge Coverage Badge

Please sign in to comment.