From c95600bd4f2492445d4d773e440424fb9f381d29 Mon Sep 17 00:00:00 2001 From: Rick Strand Date: Fri, 9 Aug 2024 13:05:21 -0500 Subject: [PATCH] 10634 Fix of Condenser Operation Issue This commit includes the fix to the problem for both condensers operating even when the operation scheme said that one of them should not be operating. It fixes this for all of the cooling tower models that were not set up to look at this. Results now should that the towers are operating when they are supposed to. --- src/EnergyPlus/CondenserLoopTowers.cc | 68 ++++++++++++------- src/EnergyPlus/CondenserLoopTowers.hh | 8 ++- .../unit/CondenserLoopTowers.unit.cc | 12 ++-- 3 files changed, 54 insertions(+), 34 deletions(-) diff --git a/src/EnergyPlus/CondenserLoopTowers.cc b/src/EnergyPlus/CondenserLoopTowers.cc index dfd6f8f7b5b..8460b789753 100644 --- a/src/EnergyPlus/CondenserLoopTowers.cc +++ b/src/EnergyPlus/CondenserLoopTowers.cc @@ -137,13 +137,13 @@ namespace CondenserLoopTowers { this->initialize(state); switch (this->TowerType) { case DataPlant::PlantEquipmentType::CoolingTower_SingleSpd: - this->calculateSingleSpeedTower(state); + this->calculateSingleSpeedTower(state, CurLoad); break; case DataPlant::PlantEquipmentType::CoolingTower_TwoSpd: - this->calculateTwoSpeedTower(state); + this->calculateTwoSpeedTower(state, CurLoad); break; case DataPlant::PlantEquipmentType::CoolingTower_VarSpd: - this->calculateVariableSpeedTower(state); + this->calculateVariableSpeedTower(state, CurLoad); break; case DataPlant::PlantEquipmentType::CoolingTower_VarSpdMerkel: this->calculateMerkelVariableSpeedTower(state, CurLoad); @@ -4535,7 +4535,7 @@ namespace CondenserLoopTowers { } } // namespace CondenserLoopTowers - void CoolingTower::calculateSingleSpeedTower(EnergyPlusData &state) + void CoolingTower::calculateSingleSpeedTower(EnergyPlusData &state, Real64 &MyLoad) { // SUBROUTINE INFORMATION: @@ -4695,13 +4695,9 @@ namespace CondenserLoopTowers { // Do not RETURN here if flow rate is less than SmallMassFlow. Check basin heater and then RETURN. - // MassFlowTolerance is a parameter to indicate a no flow condition - if (this->WaterMassFlowRate <= DataBranchAirLoopPlant::MassFlowTolerance) { - // for multiple cells, we assume that it's a common basin - CalcBasinHeaterPower( - state, this->BasinHeaterPowerFTempDiff, this->BasinHeaterSchedulePtr, this->BasinHeaterSetPointTemp, this->BasinHeaterPower); - return; - } + bool returnFlagSet; + this->checkMassFlowAndLoad(state, MyLoad, returnFlagSet); + if (returnFlagSet) return; bool IncrNumCellFlag = true; // determine if yes or no we increase the number of cells // set value to true to enter in the loop @@ -4847,7 +4843,7 @@ namespace CondenserLoopTowers { this->airFlowRateRatio = (AirFlowRate * this->NumCell) / this->HighSpeedAirFlowRate; } - void CoolingTower::calculateTwoSpeedTower(EnergyPlusData &state) + void CoolingTower::calculateTwoSpeedTower(EnergyPlusData &state, Real64 &MyLoad) { // SUBROUTINE INFORMATION: @@ -4974,12 +4970,9 @@ namespace CondenserLoopTowers { // Do not RETURN here if flow rate is less than SmallMassFlow. Check basin heater and then RETURN. if (state.dataPlnt->PlantLoop(this->plantLoc.loopNum).LoopSide(this->plantLoc.loopSideNum).FlowLock == DataPlant::FlowLock::Unlocked) return; // TODO: WTF - // MassFlowTolerance is a parameter to indicate a no flow condition - if (this->WaterMassFlowRate <= DataBranchAirLoopPlant::MassFlowTolerance) { - CalcBasinHeaterPower( - state, this->BasinHeaterPowerFTempDiff, this->BasinHeaterSchedulePtr, this->BasinHeaterSetPointTemp, this->BasinHeaterPower); - return; - } + bool returnFlagSet; + this->checkMassFlowAndLoad(state, MyLoad, returnFlagSet); + if (returnFlagSet) return; // Added for multi-cell. Determine the number of cells operating Real64 WaterMassFlowRatePerCellMin = 0.0; @@ -5089,7 +5082,7 @@ namespace CondenserLoopTowers { this->airFlowRateRatio = (AirFlowRate * this->NumCell) / this->HighSpeedAirFlowRate; } - void CoolingTower::calculateVariableSpeedTower(EnergyPlusData &state) + void CoolingTower::calculateVariableSpeedTower(EnergyPlusData &state, Real64 &MyLoad) { // SUBROUTINE INFORMATION: @@ -5209,12 +5202,10 @@ namespace CondenserLoopTowers { // Do not RETURN here if flow rate is less than MassFlowTolerance. Check basin heater and then RETURN. if (state.dataPlnt->PlantLoop(this->plantLoc.loopNum).LoopSide(this->plantLoc.loopSideNum).FlowLock == DataPlant::FlowLock::Unlocked) return; // TODO: WTF - // MassFlowTolerance is a parameter to indicate a no flow condition - if (this->WaterMassFlowRate <= DataBranchAirLoopPlant::MassFlowTolerance) { - CalcBasinHeaterPower( - state, this->BasinHeaterPowerFTempDiff, this->BasinHeaterSchedulePtr, this->BasinHeaterSetPointTemp, this->BasinHeaterPower); - return; - } + + bool returnFlagSet; + this->checkMassFlowAndLoad(state, MyLoad, returnFlagSet); + if (returnFlagSet) return; // loop to increment NumCell if we cannot meet the setpoint with the actual number of cells calculated above bool IncrNumCellFlag = true; @@ -5512,9 +5503,10 @@ namespace CondenserLoopTowers { } WaterMassFlowRatePerCell = this->WaterMassFlowRate / this->NumCellOn; + // MassFlowTolerance is a parameter to indicate a no flow condition if (this->WaterMassFlowRate <= DataBranchAirLoopPlant::MassFlowTolerance || (MyLoad > HVAC::SmallLoad)) { - // for multiple cells, we assume that it's a common bassin + // for multiple cells, we assume that it's a common basin CalcBasinHeaterPower( state, this->BasinHeaterPowerFTempDiff, this->BasinHeaterSchedulePtr, this->BasinHeaterSetPointTemp, this->BasinHeaterPower); return; @@ -6463,6 +6455,30 @@ namespace CondenserLoopTowers { } } + void CoolingTower::checkMassFlowAndLoad(EnergyPlusData &state, Real64 const MyLoad, bool &returnFlagSet) + { + returnFlagSet = false; + // MassFlowTolerance is a parameter to indicate a no flow condition + if (this->WaterMassFlowRate <= DataBranchAirLoopPlant::MassFlowTolerance) { + // for multiple cells, we assume that it's a common basin + CalcBasinHeaterPower( + state, this->BasinHeaterPowerFTempDiff, this->BasinHeaterSchedulePtr, this->BasinHeaterSetPointTemp, this->BasinHeaterPower); + returnFlagSet = true; + } + + // Also check to see if the tower is not running (zero MyLoad) + if (std::abs(MyLoad) <= HVAC::SmallLoad) { + // tower doesn't need to do anything + this->OutletWaterTemp = state.dataLoopNodes->Node(this->WaterInletNodeNum).Temp; + this->FanPower = 0.0; + this->airFlowRateRatio = 0.0; + this->Qactual = 0.0; + CalcBasinHeaterPower( + state, this->BasinHeaterPowerFTempDiff, this->BasinHeaterSchedulePtr, this->BasinHeaterSetPointTemp, this->BasinHeaterPower); + returnFlagSet = true; + } + } + } // namespace CondenserLoopTowers } // namespace EnergyPlus diff --git a/src/EnergyPlus/CondenserLoopTowers.hh b/src/EnergyPlus/CondenserLoopTowers.hh index d1f128674ce..ef2da0f931a 100644 --- a/src/EnergyPlus/CondenserLoopTowers.hh +++ b/src/EnergyPlus/CondenserLoopTowers.hh @@ -387,13 +387,13 @@ namespace CondenserLoopTowers { void SizeVSMerkelTower(EnergyPlusData &state); - void calculateSingleSpeedTower(EnergyPlusData &state); + void calculateSingleSpeedTower(EnergyPlusData &state, Real64 &MyLoad); - void calculateTwoSpeedTower(EnergyPlusData &state); + void calculateTwoSpeedTower(EnergyPlusData &state, Real64 &MyLoad); void calculateMerkelVariableSpeedTower(EnergyPlusData &state, Real64 &MyLoad); - void calculateVariableSpeedTower(EnergyPlusData &state); + void calculateVariableSpeedTower(EnergyPlusData &state, Real64 &MyLoad); Real64 calculateSimpleTowerOutletTemp(EnergyPlusData &state, Real64 waterMassFlowRate, Real64 AirFlowRate, Real64 UAdesign); @@ -427,6 +427,8 @@ namespace CondenserLoopTowers { void report(EnergyPlusData &state, bool RunFlag); + void checkMassFlowAndLoad(EnergyPlusData &state, Real64 MyLoad, bool &returnFlagSet); + static CoolingTower *factory(EnergyPlusData &state, std::string_view objectName); }; diff --git a/tst/EnergyPlus/unit/CondenserLoopTowers.unit.cc b/tst/EnergyPlus/unit/CondenserLoopTowers.unit.cc index 99aac875025..76b9fc1f407 100644 --- a/tst/EnergyPlus/unit/CondenserLoopTowers.unit.cc +++ b/tst/EnergyPlus/unit/CondenserLoopTowers.unit.cc @@ -904,10 +904,11 @@ TEST_F(EnergyPlusFixture, CondenserLoopTowers_SingleSpeedSizing) SimulationManager::SetupSimulation(*state, ErrorsFound); CondenserLoopTowers::GetTowerInput(*state); + Real64 MyLoad = 0.0; state->dataCondenserLoopTowers->towers(1).initialize(*state); state->dataCondenserLoopTowers->towers(1).SizeTower(*state); state->dataCondenserLoopTowers->towers(1).initialize(*state); - state->dataCondenserLoopTowers->towers(1).calculateSingleSpeedTower(*state); + state->dataCondenserLoopTowers->towers(1).calculateSingleSpeedTower(*state, MyLoad); state->dataCondenserLoopTowers->towers(1).update(*state); state->dataCondenserLoopTowers->towers(1).report(*state, true); @@ -927,8 +928,8 @@ TEST_F(EnergyPlusFixture, CondenserLoopTowers_SingleSpeedSizing) outletNodeIndex = std::distance(state->dataLoopNodes->NodeID.begin(), outletNode); } // TODO: FIXME: This is failing. Actual is -10.409381032746095, expected is 30. - EXPECT_GT(state->dataLoopNodes->Node(inletNodeIndex).Temp, 30.0); // inlet node temperature - EXPECT_DOUBLE_EQ(30.0, state->dataLoopNodes->Node(outletNodeIndex).Temp); // outlet node temperature + EXPECT_GT(state->dataLoopNodes->Node(inletNodeIndex).Temp, 30.0); // inlet node temperature + EXPECT_DOUBLE_EQ(state->dataLoopNodes->Node(inletNodeIndex).Temp, state->dataLoopNodes->Node(outletNodeIndex).Temp); // outlet node temperature // input not needed for sizing (WasAutoSized = false) using NominalCapacity method but this variable should still size EXPECT_FALSE(state->dataCondenserLoopTowers->towers(1).HighSpeedTowerUAWasAutoSized); @@ -3967,7 +3968,8 @@ TEST_F(EnergyPlusFixture, VSCoolingTowers_WaterOutletTempTest) state->dataPlnt->PlantLoop(VSTower.plantLoc.loopNum).LoopSide(VSTower.plantLoc.loopSideNum).TempSetPoint = 30.0; VSTower.WaterMassFlowRate = VSTower.DesWaterMassFlowRate * WaterFlowRateRatio; - VSTower.calculateVariableSpeedTower(*state); + Real64 myLoad = 1000.0; + VSTower.calculateVariableSpeedTower(*state, myLoad); EXPECT_DOUBLE_EQ(30.0, VSTower.OutletWaterTemp); EXPECT_DOUBLE_EQ(1.0, VSTower.FanCyclingRatio); Real64 TowerOutletWaterTemp = VSTower.calculateVariableTowerOutletTemp(*state, WaterFlowRateRatio, VSTower.airFlowRateRatio, AirWetBulbTemp); @@ -3985,7 +3987,7 @@ TEST_F(EnergyPlusFixture, VSCoolingTowers_WaterOutletTempTest) VSTower.AirWetBulb = state->dataEnvrn->OutWetBulbTemp; VSTower.AirHumRat = state->dataEnvrn->OutHumRat; - VSTower.calculateVariableSpeedTower(*state); + VSTower.calculateVariableSpeedTower(*state, myLoad); EXPECT_DOUBLE_EQ(30.0, VSTower.OutletWaterTemp); EXPECT_NEAR(0.5424, VSTower.FanCyclingRatio, 0.0001); // outside air condition is favorable that fan only needs to cycle at min flow to meet the setpoint