diff --git a/src/EnergyPlus/BranchInputManager.cc b/src/EnergyPlus/BranchInputManager.cc index 2aa847a6bfa..bcae4bea6b9 100644 --- a/src/EnergyPlus/BranchInputManager.cc +++ b/src/EnergyPlus/BranchInputManager.cc @@ -2636,6 +2636,7 @@ namespace BranchInputManager { MatchNode = state.dataBranchInputManager->Branch(Found).Component(1).InletNode; MatchNodeName = state.dataBranchInputManager->Branch(Found).Component(1).InletNodeName; BranchInletNodeName = state.dataBranchInputManager->Branch(Found).Component(1).InletNodeName; + CheckBranchEquipInZoneHVACEquipList(state, Found, ErrFound); } else { ShowWarningError(state, std::format("Branch has no components={}", state.dataBranchInputManager->Branch(Found).Name)); } diff --git a/src/EnergyPlus/GeneralRoutines.cc b/src/EnergyPlus/GeneralRoutines.cc index 6713d7f2f40..8f3e77909a8 100644 --- a/src/EnergyPlus/GeneralRoutines.cc +++ b/src/EnergyPlus/GeneralRoutines.cc @@ -59,6 +59,7 @@ // EnergyPlus Headers #include +#include #include #include #include @@ -1686,4 +1687,50 @@ Real64 calcZoneSensibleOutput(Real64 const MassFlow, // air mass flow rate, {kg/ } return sensibleOutput; } + +void CheckBranchEquipInZoneHVACEquipList(EnergyPlusData &state, int const branchNum, bool &errorsFound) +{ + // #4787 only interested in zone equipment connected to plant loop. Assumes other ZoneHVAC equipment types will have less criptic errors. + for (int comp = 1; comp <= state.dataBranchInputManager->Branch(branchNum).NumOfComponents; ++comp) { + bool found = false; + DataZoneEquipment::ZoneEquipType eqType = static_cast( + getEnumValue(DataZoneEquipment::zoneEquipTypeNamesUC, state.dataBranchInputManager->Branch(branchNum).Component(comp).CType)); + switch (eqType) { + case DataZoneEquipment::ZoneEquipType::BaseboardConvectiveWater: + case DataZoneEquipment::ZoneEquipType::BaseboardSteam: + case DataZoneEquipment::ZoneEquipType::BaseboardWater: + case DataZoneEquipment::ZoneEquipType::LowTemperatureRadiantConstFlow: + case DataZoneEquipment::ZoneEquipType::LowTemperatureRadiantVarFlow: + case DataZoneEquipment::ZoneEquipType::CoolingPanel: + for (int eqList = 1; eqList <= static_cast(state.dataZoneEquip->ZoneEquipList.size()); ++eqList) { + for (int eqNum = 1; eqNum <= state.dataZoneEquip->ZoneEquipList(eqList).NumOfEquipTypes; ++eqNum) { + // search name string first as it is more likely to be unique + if (Util::SameString(state.dataBranchInputManager->Branch(branchNum).Component(comp).Name, + state.dataZoneEquip->ZoneEquipList(eqList).EquipName(eqNum))) { + if (Util::SameString(state.dataBranchInputManager->Branch(branchNum).Component(comp).CType, + state.dataZoneEquip->ZoneEquipList(eqList).EquipTypeName(eqNum))) { + found = true; + break; + } + } + } + if (found) { + break; + } + } + if (!found) { + ShowSevereError(state, + std::format("CheckBranchEquipInZoneHVACEquipList: Branch = {}, contains a component of type {} with name = {}", + state.dataBranchInputManager->Branch(branchNum).Name, + state.dataBranchInputManager->Branch(branchNum).Component(comp).CType, + state.dataBranchInputManager->Branch(branchNum).Component(comp).Name)); + ShowContinueError(state, "but that component is not listed in any ZoneHVAC:EquipmentList."); + errorsFound = true; + } + break; + default: + continue; + } + } +} } // namespace EnergyPlus diff --git a/src/EnergyPlus/GeneralRoutines.hh b/src/EnergyPlus/GeneralRoutines.hh index b1d1304a64c..425e319635e 100644 --- a/src/EnergyPlus/GeneralRoutines.hh +++ b/src/EnergyPlus/GeneralRoutines.hh @@ -215,6 +215,8 @@ Real64 calcZoneSensibleOutput(Real64 const MassFlow, // air mass flow rate, {kg/ Real64 const TDBZone, // dry-bulb temperature at zone air node {C} Real64 const WZone); +void CheckBranchEquipInZoneHVACEquipList(EnergyPlusData &state, int const branchNum, bool &errorsFound); + struct GeneralRoutinesData : BaseGlobalStruct { diff --git a/tst/EnergyPlus/unit/BranchInputManager.unit.cc b/tst/EnergyPlus/unit/BranchInputManager.unit.cc index 753bbfa4916..fabcb3ad768 100644 --- a/tst/EnergyPlus/unit/BranchInputManager.unit.cc +++ b/tst/EnergyPlus/unit/BranchInputManager.unit.cc @@ -611,4 +611,54 @@ TEST_F(EnergyPlusFixture, BranchInputManager_OrphanObjects) compare_err_stream(expected_error, true); } +TEST_F(EnergyPlusFixture, BranchInputManager_OrphanBaseboard) +{ + // Branch + state->dataBranchInputManager->clear_state(); + state->dataErrTracking->TotalSevereErrors = 0; + std::string idf_objects = delimited_string({ + "BranchList,", + " Baseboard Heating Branches, !- Name", + " Baseboard Heating Branch; !- Branch 1 Name", + + "Branch,", + " Baseboard Heating Branch, !- Name", + " , !- Pressure Drop Curve Name", + " ZoneHVAC:Baseboard:Convective:Water, !- Component 1 Object Type", + " Baseboard Heater, !- Component 1 Name", + " Baseboard Water Inlet Node, !- Component 1 Inlet Node Name", + " Baseboard Water Outlet Node; !- Component 1 Outlet Node Name", + + "ZoneHVAC:Baseboard:Convective:Water,", + " Baseboard Heater, !-Name", + " , !-Availability Schedule Name", + " Baseboard Water Inlet Node, !-Inlet Node Name", + " Baseboard Water Outlet Node, !-Outlet Node Name", + " HeatingDesignCapacity, !-Heating Design Capacity Method", + " Autosize, !-Heating Design Capacity{W}", + " , !-Heating Design Capacity Per Floor Area{W/m2}", + " , !-Fraction of Autosized Heating Design Capacity", + " Autosize, !-U - Factor Times Area Value{W/K}", + " Autosize; !-Maximum Water Flow Rate {m3/s}", + + }); + ASSERT_TRUE(process_idf(idf_objects)); + EXPECT_NO_THROW(ManageBranchInput(*state)); + + std::string expected_error = ""; + compare_err_stream(expected_error, true); + + bool ErrFound = false; + BranchInputManager::TestBranchIntegrity(*state, ErrFound); + + expected_error = delimited_string({ + " ************* Testing Individual Branch Integrity", + " ** Severe ** CheckBranchEquipInZoneHVACEquipList: Branch = BASEBOARD HEATING BRANCH, contains a component of type " + "ZONEHVAC:BASEBOARD:CONVECTIVE:WATER with name = BASEBOARD HEATER", + " ** ~~~ ** but that component is not listed in any ZoneHVAC:EquipmentList.", + " ** Severe ** Branch(es) did not pass integrity testing", + }); + compare_err_stream(expected_error, true); +} + } // namespace EnergyPlus