-
Notifications
You must be signed in to change notification settings - Fork 457
Fix #10831 - HeatPump:PlantLoop:EIR:Heating with Setpoint control not operating when no setpoint on component outlet node #11247
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
base: develop
Are you sure you want to change the base?
Conversation
|
I have a MCVE on DevSupport too, where I do see the new warning. |
| if (this->sysControlType == ControlType::Setpoint) { | ||
|
|
||
| // check if setpoint on outlet node | ||
| if ((state.dataLoopNodes->Node(this->loadSideNodes.outlet).TempSetPoint == DataLoopNode::SensedNodeFlagValue) && | ||
| (state.dataLoopNodes->Node(this->loadSideNodes.outlet).TempSetPointHi == DataLoopNode::SensedNodeFlagValue)) { | ||
| if (!state.dataGlobal->AnyEnergyManagementSystemInModel) { | ||
| if (!this->SetpointSetToLoopErrDone) { | ||
| ShowWarningError(state, | ||
| format("{}: Missing temperature setpoint for Setpoint Controlled {} name = \"{}\"", | ||
| routineName, | ||
| DataPlant::PlantEquipTypeNames[static_cast<int>(this->EIRHPType)], | ||
| this->name)); | ||
| ShowContinueError(state, " A temperature setpoint is needed at the load side outlet node, use a SetpointManager"); | ||
| ShowContinueError(state, " The overall loop setpoint will be assumed for the Heat Pump. The simulation continues ... "); | ||
| this->SetpointSetToLoopErrDone = true; | ||
| } | ||
| } else { | ||
| // need call to EMS to check node | ||
| bool fatalError = false; // but not really fatal yet, but should be. | ||
| EMSManager::CheckIfNodeSetPointManagedByEMS(state, this->loadSideNodes.outlet, HVAC::CtrlVarType::Temp, fatalError); | ||
| state.dataLoopNodes->NodeSetpointCheck(this->loadSideNodes.outlet).needsSetpointChecking = false; | ||
| if (fatalError) { | ||
| if (!this->SetpointSetToLoopErrDone) { | ||
| ShowWarningError(state, | ||
| format("{}: Missing temperature setpoint for Setpoint Controlled {} name = \"{}\"", | ||
| routineName, | ||
| DataPlant::PlantEquipTypeNames[static_cast<int>(this->EIRHPType)], | ||
| this->name)); | ||
| ShowContinueError(state, " A temperature setpoint is needed at the load side outlet node when ControlType = Setpoint"); | ||
| ShowContinueError(state, " use a Setpoint Manager to establish a setpoint at the outlet node "); | ||
| ShowContinueError(state, " or use an EMS actuator to establish a setpoint at the outlet node "); | ||
| ShowContinueError(state, " The overall loop setpoint will be assumed for the Heat Pump. The simulation continues ... "); | ||
| this->SetpointSetToLoopErrDone = true; | ||
| } | ||
| } | ||
| } | ||
| this->SetpointSetToLoop = true; | ||
| state.dataLoopNodes->Node(this->loadSideNodes.outlet).TempSetPoint = | ||
| state.dataLoopNodes->Node(this->loadSidePlantLoc.loop->TempSetPointNodeNum).TempSetPoint; | ||
| state.dataLoopNodes->Node(this->loadSideNodes.outlet).TempSetPointLo = | ||
| state.dataLoopNodes->Node(this->loadSidePlantLoc.loop->TempSetPointNodeNum).TempSetPointLo; | ||
| state.dataLoopNodes->Node(this->loadSideNodes.outlet).TempSetPointHi = | ||
| state.dataLoopNodes->Node(this->loadSidePlantLoc.loop->TempSetPointNodeNum).TempSetPointHi; | ||
| } | ||
| } |
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.
In oneTimeInit, when SetpointCOntrolled, we check if there's no setpoint, and assume the overall loop setpoint.
Error is dumped once only, and the "SetpointSetToLoop" is set to true.
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 surprised this model does not check for a valid set point since it's been around for quite some time. It points to a set point node but where is the check for DataLoopNode::SensedNodeFlagValue? Maybe at a higher level in the plant manager. Anyway, I think getLoadSideOutletSetPointTemp already handles where the set point is located. I think you just need to correct old line 142 to new line 155 and always call this function. Once you made that 1-line change you fixed it. The new warnings are nice but I have to believe someone has already thought of plant node set point temperatures and warnings for all the plant equipment that can be controlled to a set point, at the component outlet or loop outlet based on the control type scheme.
Real64 EIRPlantLoopHeatPump::getLoadSideOutletSetPointTemp(EnergyPlusData &state)
if (thisLoadPlantLoop.LoopDemandCalcScheme == DataPlant::LoopDemandCalcScheme::SingleSetPoint) {
if (thisLoadComp.CurOpSchemeType == DataPlant::OpScheme::CompSetPtBased) {
// there will be a valid set-point on outlet
return state.dataLoopNodes->Node(this->loadSideNodes.outlet).TempSetPoint;
} else { // use plant loop overall set-point
return state.dataLoopNodes->Node(thisLoadPlantLoop.TempSetPointNodeNum).TempSetPoint;
}
} else if (thisLoadPlantLoop.LoopDemandCalcScheme == DataPlant::LoopDemandCalcScheme::DualSetPointDeadBand) {
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.
PlantManager line 2483:
if (this->SupplyEnvrnFlag && state.dataGlobal->BeginEnvrnFlag) {
for (int LoopNum = 1; LoopNum <= this->plant->TotNumLoops; ++LoopNum) {
// check if setpoints being placed on node properly
if (this->plant->PlantLoop(LoopNum).LoopDemandCalcScheme == DataPlant::LoopDemandCalcScheme::DualSetPointDeadBand) {
if (state.dataLoopNodes->Node(this->plant->PlantLoop(LoopNum).TempSetPointNodeNum).TempSetPointHi == SensedNodeFlagValue) {
if (!state.dataGlobal->AnyEnergyManagementSystemInModel) {
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.
Note that the boiler and chillers use this as the equipment set point control node. I searched for TempSetPointNodeNum and it shows up in most/all plant equipment. Maybe that needs to be used instead of what getLoadSideOutletSetPointTemp does? This is weird, the EIR HP can be set point controlled while the plant can use other control types at the same time. If the EIR HP is SP controlled and has SPs at it's outlet node, and the plant is SP controlled and has SPs at the loop outlet node then which node has the priority for use as the SP? Maybe what you have done is more accurate for equipment that have a ControlType input field where the SP should be at the equipment outlet. I am, however, thinking it would be better to figure this out early and use a new this->setPointNodeNum variable that just points to the correct node and jetison copying node data each iteration. Maybe that would be a good follow up to this PR and fix all this hokeyness in the equipment models after thinking this through.
this->plant->PlantLoop(LoopNum).TempSetPointNodeNum
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.
Summary of what is needed to complete this work. If the EIR HP is set point controlled then a warning that the SP is missing at the outlet is fine. The plant does have a SP at the plant outlet node. But getLoadSideOutletSetPointTemp will only use that SP if the plant op scheme is NOT CompSetPtBased. I just don't like the idea of copying node data each iteration so I would rather find a different solution. What I would do is either fatal out if there is not SP at the EIR HP outlet node, or right here check if state.dataLoopNodes->Node(this->loadSideNodes.outlet).TempSetPoint == DataLoopNode::SensedNodeFlagValue and use the plant loop outlet node SP instead. @mjwitte ?
if (this->loadSidePlantLoc.comp->CurOpSchemeType == DataPlant::OpScheme::CompSetPtBased) {
// there will be a valid set-point on outlet
return state.dataLoopNodes->Node(this->loadSideNodes.outlet).TempSetPoint;
} else { // use plant loop overall set-point
return state.dataLoopNodes->Node(this->loadSidePlantLoc.loop->TempSetPointNodeNum).TempSetPoint;
}
I do like the idea of using this in the future, but for this issue what this change is doing is fine. setPointNodeNum would be set up early to point to the correct node, either the EIR HP outlet node or the plant loop outlet node.
return state.dataLoopNodes->Node(this->setPointNodeNum).TempSetPoint;
in getInput or Init choose either:
this->setPointNodeNum = this->loadSideNodes.outlet, or
this->setPointNodeNum = this->loadSidePlantLoc.loop->TempSetPointNodeNum
This would simplify the code in getLoadSideOutletSetPointTemp.
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.
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 creating a bunch of failed tests. Is it really worth pursuing?
| bool SetpointSetToLoop = false; // True if the setpoint is missing at the outlet node | ||
| bool SetpointSetToLoopErrDone = false; // True if setpoint warning issued |
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.
New state vars
| if (this->running) { | ||
| if (this->sysControlType == ControlType::Setpoint) { | ||
| Real64 leavingSetpoint = state.dataLoopNodes->Node(this->loadSideNodes.outlet).TempSetPoint; | ||
| if (this->SetpointSetToLoop) { | ||
| // Copy the overall loop setpoints to the Heat Pump outlet node | ||
| state.dataLoopNodes->Node(this->loadSideNodes.outlet).TempSetPoint = | ||
| state.dataLoopNodes->Node(this->loadSidePlantLoc.loop->TempSetPointNodeNum).TempSetPoint; | ||
| // Hi is used when (this->EIRHPType == DataPlant::PlantEquipmentType::HeatPumpEIRCooling) { | ||
| state.dataLoopNodes->Node(this->loadSideNodes.outlet).TempSetPointHi = | ||
| state.dataLoopNodes->Node(this->loadSidePlantLoc.loop->TempSetPointNodeNum).TempSetPointHi; | ||
| // Lo when HeatPumpEIRHeating | ||
| state.dataLoopNodes->Node(this->loadSideNodes.outlet).TempSetPointLo = | ||
| state.dataLoopNodes->Node(this->loadSidePlantLoc.loop->TempSetPointNodeNum).TempSetPointLo; | ||
| } |
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 SetpointSetToLoop is true, in simulate we just copy the plant overall setpoints onto the outlet node.
| // Call the helper so we handle SingleSetpoint versus DualSetpointDeadband instead of just grabbing TempSetPoint; | ||
| Real64 leavingSetpoint = this->getLoadSideOutletSetPointTemp(state); |
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 was prexisting as
Real64 leavingSetpoint = state.dataLoopNodes->Node(this->loadSideNodes.outlet).TempSetPoint;
But in case the Setpoint is actually DualSetpointWithDeadband, I don't think this is working as intended. So we call the helper instead.
I hope I got that right?
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 appears to be the right thing to do but looking at this function it checks the plant control type and I'm not sure the EIR HP Setpoint control type is meant to be this flexible (i.e., to allow multiple set point types at the equipment outlet node). It's as if the getLoadSideOutletSetPointTemp function should look to the equipment Node(this->loadSideNodes.outlet).TempSetpoint variable when using Setpoint control type and this function doesn't do that. In the case of the plant DualSetPointDeadBand control scheme the equipment outlet node would need to find the TempSetpointHi/Lo set points but who's to say that the user intended to control to set point based on the plant control scheme. I got the feeling that @mjwitte would have fatal'd out if the correct set point was not found and I don't disagree with that. i.e., if the user chooses Setpoint then there better be a set point of the correct type at the equipment outlet node. There needs to be more thought on when EIR HP Setpoint control is SingleSetPoint (cooling or heating plant) or DualSetPointDeadBand (mixed plant), I can see both being useful but now only SingleSetPoint is used. Maybe the defect file should not have been using Setpoint control in this case as there was no set point manager used for the EIR HP outlet node?
| EXPECT_NEAR(30.0, thisHeatingPLHP->getLoadSideOutletSetPointTemp(*state), 0.001); | ||
| EXPECT_NEAR(30.0, state->dataLoopNodes->Node(thisHeatingPLHP->loadSideNodes.outlet).TempSetPoint, 0.001); |
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.
before fix, -999...
| EXPECT_NEAR(10.0, thisHeatingPLHP->getLoadSideOutletSetPointTemp(*state), 0.001); | ||
| EXPECT_NEAR(DataLoopNode::SensedNodeFlagValue, state->dataLoopNodes->Node(thisHeatingPLHP->loadSideNodes.outlet).TempSetPoint, 0.001); | ||
| EXPECT_NEAR(30.0, state->dataLoopNodes->Node(thisHeatingPLHP->loadSideNodes.outlet).TempSetPointHi, 0.001); | ||
| EXPECT_NEAR(10.0, state->dataLoopNodes->Node(thisHeatingPLHP->loadSideNodes.outlet).TempSetPointLo, 0.001); |
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.
Same here, not 10.0 (or 30.0) but -999 before fix
|
|
cca3edc to
493d41f
Compare
|
|
|
|
||
| // check if setpoint on outlet node | ||
| if ((state.dataLoopNodes->Node(this->loadSideNodes.outlet).TempSetPoint == DataLoopNode::SensedNodeFlagValue) && | ||
| (state.dataLoopNodes->Node(this->loadSideNodes.outlet).TempSetPointHi == DataLoopNode::SensedNodeFlagValue)) { |
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'm not sure TempSetPointHi (or Lo) should be included here for the "equipment" setpoint control type. However, I haven't investigated this recently and am not sure which Node().TempSetPoint variables are used in the Setpoint control case.
HeatPump:PlantLoop:EIR:Cooling,
A13, \field Control Type
\note Heat pump can be controlled on leaving water temperature set point or plant load
\type choice
\key Setpoint
\key Load
\default Load
493d41f to
1031924
Compare
|
|
1031924 to
af6451d
Compare
|
|
…e=Setpoint and missing one at outlet
af6451d to
5c352d5
Compare
|
|


Pull request overview
Description of the purpose of this PR
Pull Request Author
Reviewer