-
Notifications
You must be signed in to change notification settings - Fork 460
Fix cycling degradation calculation for GAHP #11077
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
Conversation
lymereJ
left a comment
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.
Code walkthrough:
| N14; \field Minimum Unloading Ratio | ||
| \minimum 0 | ||
| \maximum 1 | ||
| \default 0.25 | ||
| \note Minimum modulation level of the gas-fired heat pump. Typically less than 1.0 and slightly higher than the minimum part load ratio. |
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.
The paper used as the basis for the development of this object specifies that the GAHP that was tested has a minimum PLR of 0.2. That value corresponds to the product of the minimum modulation level and the minimum cycle time. In the paper, the minimum modulation level is 0.25. This is what this input describes. The name of the input was chosen to be aligned with inputs for some of the chiller objects.
| // Cycling Ratio | ||
| constexpr Real64 CR_min = 0.0; | ||
| constexpr Real64 CR_max = 1.0; | ||
| Real64 CR = std::clamp(max(this->minPLR, partLoadRatio) / miniPLR_mod, |
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 always equal to 1.0 because miniPLR_mod = this->minPLR and if partLoadRatio > this->minPLR, partLoadRatio / miniPLR_mod > 1 and gets "clamped" to a value of 1.0.
| Real64 CRF = CRF_Slope * CR + CRF_Intercept; // Use the the fixed eqn in the paper as the default curve (or maybe choose constant 1 as default) | ||
| if (this->cycRatioCurveIndex > 0) { | ||
| CRF = Curve::CurveValue(state, this->cycRatioCurveIndex, CR); | ||
| if (partLoadRatio < this->minimumUnloadingRatio) { |
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.
Assume no degradation above the minimumUnloadingRatio.
| // N14 minimum unloading ratio | ||
| auto minimumUnloadingRatio = fields.find("minimum_unloading_ratio"); | ||
| if (minimumUnloadingRatio != fields.end()) { | ||
| thisPLHP.minimumUnloadingRatio = minimumUnloadingRatio.value().get<Real64>(); | ||
| } else { | ||
| Real64 defaultVal = 0.25; | ||
| if (!state.dataInputProcessing->inputProcessor->getDefaultValue(state, cCurrentModuleObject, "minimum_unloading_ratio", defaultVal)) { | ||
| ShowSevereError(state, "EIR FFHP: minimum unload ratio not entered and could not get default value."); | ||
| errorsFound = true; | ||
| } else { | ||
| thisPLHP.minimumUnloadingRatio = defaultVal; | ||
| } | ||
| } | ||
| if (thisPLHP.minimumUnloadingRatio < thisPLHP.minPLR) { | ||
| ShowSevereError(state, "EIR FFHP: the minimum unloading ratio cannot be lower than the minimum part load ratio."); | ||
| errorsFound = 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.
Input validation for the new input field.
| { | ||
| bool firstHVAC = true; | ||
| Real64 curLoad = 500.0; | ||
| bool runFlag = true; | ||
| Real64 constexpr expectedLoadMassFlowRate = 0.09999; | ||
| Real64 constexpr expectedCp = 4180; | ||
| Real64 constexpr specifiedLoadSetpoint = 45; | ||
| Real64 const calculatedLoadInletTemp = specifiedLoadSetpoint - curLoad / (expectedLoadMassFlowRate * expectedCp); | ||
| state->dataLoopNodes->Node(thisHeatingPLHP->loadSideNodes.outlet).TempSetPoint = specifiedLoadSetpoint; | ||
| state->dataLoopNodes->Node(thisHeatingPLHP->loadSideNodes.inlet).Temp = calculatedLoadInletTemp; | ||
| state->dataLoopNodes->Node(thisHeatingPLHP->sourceSideNodes.inlet).Temp = 30; | ||
| // Use user specified curve | ||
| thisHeatingPLHP->simulate(*state, myLoadLocation, firstHVAC, curLoad, runFlag); | ||
| EXPECT_NEAR(1.0, thisHeatingPLHP->cyclingRatioFraction, 0.001); | ||
| // Use default assumptions | ||
| thisHeatingPLHP->cycRatioCurveIndex = 0; | ||
| thisHeatingPLHP->simulate(*state, myLoadLocation, firstHVAC, curLoad, runFlag); | ||
| EXPECT_NEAR(0.861, thisHeatingPLHP->cyclingRatioFraction, 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.
New unit test to make sure that CRF is calculated correctly.
| SetupOutputVariable(state, | ||
| "Fuel-fired Absorption HeatPump Cycling Ratio Fraction", | ||
| Constant::Units::None, | ||
| this->cyclingRatioFraction, | ||
| OutputProcessor::TimeStepType::System, | ||
| OutputProcessor::StoreType::Average, | ||
| this->name); |
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.
Add new output to facilitate debugging and also be more transparent with users.
| if (this->cycRatioCurveIndex > 0) { | ||
| CRF = Curve::CurveValue(state, this->cycRatioCurveIndex, CR); | ||
| if (partLoadRatio < this->minimumUnloadingRatio) { | ||
| Real64 CR = std::clamp(partLoadRatio / this->minimumUnloadingRatio, 0.0, 1.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.
CR is calculated according to equation 11 the paper.
| if (this->cycRatioCurveIndex > 0) { | ||
| CRF = Curve::CurveValue(state, this->cycRatioCurveIndex, CR); | ||
| } else { | ||
| CRF = CRF_Slope * CR + CRF_Intercept; | ||
| } |
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.
Here, we're using the same approach as before: If we have a user specified curve, we use it, otherwise we use the default assumption introduced here.
The above reference shows that the cycling degradation is only applied when 0.2 <= PLR <= 0.25. The unit is turned off for PLR values less than 0.2. We don't control equipment like that in EnergyPlus, we let it run to meet the load and apply a cycling correction. The proposed changes assume that we can extrapolate the cycling degradation curve to PLR values less than 0.2.
CRF is analogous to a RTF used to the DX coils. For DX coils we have:
Power = Q * EIR * RTF where RTF = PLR / PLF since PLR = Load / Q then Power = EIR * Load / PLF
For GAHP we have:
Fuel Usage = Load * EIR * EIRfPLR / CRF so we can say that PLR * EIRfPLR / CRF is similar to a RTF
With that considered here is a plot with RTFs calculated: (1) from the default CRF assumptions, (2) from the default CRF assumption but assuming that the PLR used to calculate CR doesn't go below 0.2, (3) using PLF = 0.7 + 0.3 * PLR which would correspond to a DX coil with relatively bad cycling degradation, and (4) using PLF = 0.9 + 0.1 * PLR which would correspond to a DX coil with relatively good cycling degradation. The results seem to show that the proposed approach (1) is very similar to (4), (2) is even more in line with (4). This is to show that extrapolating the default cycling degradation assumption appears to be reasonable.
|
|
|
|
rraustad
left a comment
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 don't see any issues with these changes.
|
@lymereJ this branch was conflicted, so I pulled develop in. It is all happy locally, but I'll let CI run before merging later. |
|
|
|
|
OK, dropping this in, looks good. Thanks @lymereJ |

Pull request overview
Description of the purpose of this PR
The current cycling degradation result in a cycling ratio
CRto be always 1.0. Additionally,CRis not calculated as shown in equation 11 here. This pull request address both of these issues.Pull Request Author
Reviewer