-
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
Conversation
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.
Something about the logical flag wasn't what the custom check wanted. This is an attempt to fix that.
Unit test was added to exercise the new subroutine that is being used to allow condensers to factor in condenser loop operation schemes.
So what was happening before? The condenser plant was exceeding the set point temperature? Or was the condenser plant set point met because the tower was not turning off based on OAT? From the results this looks correct. Operating a tower on DB temp does not seem practical. @EnergyArchmage ? |
In the graph is does look like tower 2 is still on when the OAT rises above 27 C. Tower 2 operation is definitely different than shown in the issue description. |
@rraustad Yes, I agree--the graph makes it look like it is still operating when the ODB is above 27C. In hour 10, the ODB is 26.975C so both the first and second tower have a positive heat transfer rate. That's hard to see in the graph though because it is so close to 27C. In hour 11 when the ODB is well above 27C, the second tower is off and the first tower takes all of the load. I'll add the test file results here so you can see for yourself, but it is really hard to see on the graph. |
Well, they are not in series. There's no delta T across the second tower, but there's no reason why this is going through the second tower and not the bypass branch. The file in question here is out of the test suite: CoolingTowerDryBulbRangeOp.idf |
Corrected an issue with the fix where the mass flow rate when the load was zero was still positive in the defect idf when it should be zero. This is now corrected.
FYI: The non-zero flow rate when the load was zero problem has been corrected in the latest commit that was just made. |
if (std::abs(MyLoad) <= HVAC::SmallLoad) { | ||
// tower doesn't need to do anything | ||
this->OutletWaterTemp = state.dataLoopNodes->Node(this->WaterInletNodeNum).Temp; | ||
this->WaterMassFlowRate = 0.0; |
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 when there is a local change to plant flow rates, that change should be confirmed using this call. The point is, after the water flow is set to 0 here, there should be a call to the plant component flow control function SetComponentFlowRate. It is possible that the plant flow resolver would want flow through this branch (i.e., maybe there is no bypass and the pump is constant volume).
PlantUtilities::SetComponentFlowRate(state, this->WaterMassFlowRate, this->WaterInletNodeNum, this->WaterOutletNodeNum, this->plantLoc);
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.
Should the order of these conditionals be switched? line 6461 and line 6469. Why do this twice? This begs an else if.
@@ -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. |
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.
Is this comment still needed?
It is definitely a good idea to update these old models. In addition to .MyLoad ( or CurLoad here), the operation schemes also set a bool .ON (usually called RunFlag) for each component. In general nowadays, the plant simulate calls should include both MyLoad and RunFlag. To me, And yes, as @rraustad suggests, if the machine is not running it definitely needs to make a zero flow request via SetComponentFlowRate(). It may still have flow if in series with something else but that will at least make request for zero flow. I would plot these variables for the towers -- to see how plant flow rates are responding and make sure the tower fan is off.
|
Various review comments were received. These were all addressed in this commit.
Thanks, @rraustad and @EnergyArchmage, for your comments. I believe that I have addressed them all with the most recent commit (the one right before I merged in develop). Specifically:
I think that was everything to date. Did I miss anything or is there anything else that needs to be done here? |
@@ -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 comment
The 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 comment
The reason will be displayed to describe this comment to others. Learn more.
Not at all, @EnergyArchmage! Thanks for making that change.
This looks good to me! |
|
||
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 comment
The 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 comment
The 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.
@@ -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 comment
The 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 comment
The 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 comment
The 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).
|
||
bool returnFlagSet = false; | ||
this->checkMassFlowAndLoad(state, MyLoad, RunFlag, returnFlagSet); | ||
if (returnFlagSet) 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.
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?
I pulled develop and this is still happy. I'm going to mark this ready for merge, but hold off from actually merging while I await clean CI results on other branches. |
Pulled develop in and everything is happy, merging this. Thanks @RKStrand |
Pull request overview
Pull Request Author
Add to this list or remove from it as applicable. This is a simple templated set of guidelines.
Reviewer
This will not be exhaustively relevant to every PR.