-
Notifications
You must be signed in to change notification settings - Fork 389
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Correction of Condensers Not Operating Based on Operation Scheme #10653
Changes from all commits
c95600b
8f7c5de
712f23f
eb0559c
92134b5
c8531d1
4d61594
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -137,16 +137,16 @@ namespace CondenserLoopTowers { | |
this->initialize(state); | ||
switch (this->TowerType) { | ||
case DataPlant::PlantEquipmentType::CoolingTower_SingleSpd: | ||
this->calculateSingleSpeedTower(state); | ||
this->calculateSingleSpeedTower(state, CurLoad, RunFlag); | ||
break; | ||
case DataPlant::PlantEquipmentType::CoolingTower_TwoSpd: | ||
this->calculateTwoSpeedTower(state); | ||
this->calculateTwoSpeedTower(state, CurLoad, RunFlag); | ||
break; | ||
case DataPlant::PlantEquipmentType::CoolingTower_VarSpd: | ||
this->calculateVariableSpeedTower(state); | ||
this->calculateVariableSpeedTower(state, CurLoad, RunFlag); | ||
break; | ||
case DataPlant::PlantEquipmentType::CoolingTower_VarSpdMerkel: | ||
this->calculateMerkelVariableSpeedTower(state, CurLoad); | ||
this->calculateMerkelVariableSpeedTower(state, CurLoad, RunFlag); | ||
break; | ||
default: | ||
ShowFatalError(state, format("Plant Equipment Type specified for {} is not a Cooling Tower.", this->Name)); | ||
|
@@ -4535,7 +4535,7 @@ namespace CondenserLoopTowers { | |
} | ||
} // namespace CondenserLoopTowers | ||
|
||
void CoolingTower::calculateSingleSpeedTower(EnergyPlusData &state) | ||
void CoolingTower::calculateSingleSpeedTower(EnergyPlusData &state, Real64 &MyLoad, bool RunFlag) | ||
{ | ||
|
||
// 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 = false; | ||
this->checkMassFlowAndLoad(state, MyLoad, RunFlag, 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, bool RunFlag) | ||
{ | ||
|
||
// 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 = false; | ||
this->checkMassFlowAndLoad(state, MyLoad, RunFlag, 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, bool RunFlag) | ||
{ | ||
|
||
// 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 = false; | ||
this->checkMassFlowAndLoad(state, MyLoad, RunFlag, 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; | ||
|
@@ -5427,7 +5418,7 @@ namespace CondenserLoopTowers { | |
} | ||
} | ||
|
||
void CoolingTower::calculateMerkelVariableSpeedTower(EnergyPlusData &state, Real64 &MyLoad) | ||
void CoolingTower::calculateMerkelVariableSpeedTower(EnergyPlusData &state, Real64 &MyLoad, bool RunFlag) | ||
{ | ||
|
||
// SUBROUTINE INFORMATION: | ||
|
@@ -5512,15 +5503,8 @@ 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 | ||
CalcBasinHeaterPower( | ||
state, this->BasinHeaterPowerFTempDiff, this->BasinHeaterSchedulePtr, this->BasinHeaterSetPointTemp, this->BasinHeaterPower); | ||
return; | ||
} | ||
|
||
if (std::abs(MyLoad) <= HVAC::SmallLoad) { | ||
if ((std::abs(MyLoad) <= HVAC::SmallLoad) || !RunFlag) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am wondering if just !RunFlag would meet the intent. I would think RunFlag would be false if (std::abs(MyLoad) <= HVAC::SmallLoad) but then I am not sure. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wasn't sure either and given that the Merkel model already used MyLoad, I felt like having both would be "safer". My guess is that both of these flags will probably trip this IF at the same time, but I didn't see anything wrong with doing it this way which seemed like it would catch all conditions. |
||
// tower doesn't need to do anything | ||
this->OutletWaterTemp = state.dataLoopNodes->Node(this->WaterInletNodeNum).Temp; | ||
this->FanPower = 0.0; | ||
|
@@ -5529,6 +5513,11 @@ namespace CondenserLoopTowers { | |
CalcBasinHeaterPower( | ||
state, this->BasinHeaterPowerFTempDiff, this->BasinHeaterSchedulePtr, this->BasinHeaterSetPointTemp, this->BasinHeaterPower); | ||
return; | ||
} else if (this->WaterMassFlowRate <= DataBranchAirLoopPlant::MassFlowTolerance || (MyLoad > HVAC::SmallLoad)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is interesting. If this conditional is checked then the tower is running. I can't be sure if the water mass flow rate could really be this small if the tower is running but then you have the plant resolver making that determination. Also not sure of the load check. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I noticed that there was a basin heater check in checkMassFlowAndLoad similar to this. Does that make this new code unnecessary? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I left this alone because it was the one that was identified as working properly before the defect was logged. I'll admit, I did not see why it did this check (seemed confusing). However, I left it alone in the Merkel model because I didn't see a compelling reason to fix something that wasn't broken. You'll notice that the code here is slightly different than the code in checkMassFlowAndLoad--intentionally so because I trust the logic in checkMassFlowAndLoad and it makes more logical sense. So, I don't think the new code is unnecessary. It was somewhat based on what was done here in the Merkel model, with changes to the logic (by me and then improved with your suggestions). |
||
// for multiple cells, we assume that it's a common basin | ||
CalcBasinHeaterPower( | ||
state, this->BasinHeaterPowerFTempDiff, this->BasinHeaterSchedulePtr, this->BasinHeaterSetPointTemp, this->BasinHeaterPower); | ||
return; | ||
} | ||
|
||
// first find free convection cooling rate | ||
|
@@ -6355,6 +6344,7 @@ namespace CondenserLoopTowers { | |
// This subroutine is for passing results to the outlet water node. | ||
|
||
// set node information | ||
PlantUtilities::SafeCopyPlantNode(state, this->WaterInletNodeNum, this->WaterOutletNodeNum); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @RKStrand hope you don't mind me jumping in here. When components are in series, this is needed to pass data down the branch to the next component. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not at all, @EnergyArchmage! Thanks for making that change. |
||
state.dataLoopNodes->Node(this->WaterOutletNodeNum).Temp = this->OutletWaterTemp; | ||
|
||
if (state.dataPlnt->PlantLoop(this->plantLoc.loopNum).LoopSide(this->plantLoc.loopSideNum).FlowLock == DataPlant::FlowLock::Unlocked || | ||
|
@@ -6463,6 +6453,27 @@ namespace CondenserLoopTowers { | |
} | ||
} | ||
|
||
void CoolingTower::checkMassFlowAndLoad(EnergyPlusData &state, Real64 const MyLoad, bool RunFlag, bool &returnFlagSet) | ||
{ | ||
if ((MyLoad > -HVAC::SmallLoad) || !RunFlag) { | ||
// 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; | ||
this->WaterMassFlowRate = 0.0; | ||
PlantUtilities::SetComponentFlowRate(state, this->WaterMassFlowRate, this->WaterInletNodeNum, this->WaterOutletNodeNum, this->plantLoc); | ||
CalcBasinHeaterPower( | ||
state, this->BasinHeaterPowerFTempDiff, this->BasinHeaterSchedulePtr, this->BasinHeaterSetPointTemp, this->BasinHeaterPower); | ||
returnFlagSet = true; | ||
} else 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; | ||
} | ||
} | ||
|
||
} // namespace CondenserLoopTowers | ||
|
||
} // namespace EnergyPlus |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you made this function a bool it would just be
if (this->checkMassFlowAndLoad(state, MyLoad, RunFlag) return;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I was concerned that a function would then be setting other parameters and calling other routines, not just getting a bool result. I felt like that was a violation of some standard, but I'll admit that I don't know whether that is an E+ standard or something that I simply picked up over the years that maybe isn't completely true. @Myoldmopar, any thoughts on this?