Skip to content

Conversation

@lymereJ
Copy link
Collaborator

@lymereJ lymereJ commented May 21, 2025

Pull request overview

Description of the purpose of this PR

The current cycling degradation result in a cycling ratio CR to be always 1.0. Additionally, CR is not calculated as shown in equation 11 here. This pull request address both of these issues.

Pull Request Author

  • Title of PR should be user-synopsis style (clearly understandable in a standalone changelog context)
  • Label the PR with at least one of: Defect, Refactoring, NewFeature, Performance, and/or DoNoPublish
  • Pull requests that impact EnergyPlus code must also include unit tests to cover enhancement or defect repair
  • Author should provide a "walkthrough" of relevant code changes using a GitHub code review comment process
  • If any diffs are expected, author must demonstrate they are justified using plots and descriptions
  • If changes fix a defect, the fix should be demonstrated in plots and descriptions

Reviewer

  • Perform a Code Review on GitHub
  • If branch is behind develop, merge develop and build locally to check for side effects of the merge
  • If defect, verify by running develop branch and reproducing defect, then running PR and reproducing fix
  • If feature, test running new feature, try creative ways to break it
  • CI status: all green or justified
  • Check that performance is not impacted (CI Linux results include performance check)
  • Run Unit Test(s) locally
  • Check any new function arguments for performance impacts
  • Verify IDF naming conventions and styles, memos and notes and defaults
  • If new idf included, locally check the err file and other outputs

@lymereJ lymereJ added this to the EnergyPlus 25.2 IO Freeze milestone May 21, 2025
@lymereJ lymereJ added the Defect Includes code to repair a defect in EnergyPlus label May 21, 2025
Copy link
Collaborator Author

@lymereJ lymereJ left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code walkthrough:

Comment on lines 75917 to 75921
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.
Copy link
Collaborator Author

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,
Copy link
Collaborator Author

@lymereJ lymereJ May 21, 2025

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) {
Copy link
Collaborator Author

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.

Comment on lines +3407 to +3424
// 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;
}

Copy link
Collaborator Author

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.

Comment on lines +4501 to +4519
{
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);
}
Copy link
Collaborator Author

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.

Comment on lines +3600 to +3606
SetupOutputVariable(state,
"Fuel-fired Absorption HeatPump Cycling Ratio Fraction",
Constant::Units::None,
this->cyclingRatioFraction,
OutputProcessor::TimeStepType::System,
OutputProcessor::StoreType::Average,
this->name);
Copy link
Collaborator Author

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);
Copy link
Collaborator Author

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.

Comment on lines +2806 to +2810
if (this->cycRatioCurveIndex > 0) {
CRF = Curve::CurveValue(state, this->cycRatioCurveIndex, CR);
} else {
CRF = CRF_Slope * CR + CRF_Intercept;
}
Copy link
Collaborator Author

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.

image

@lymereJ lymereJ marked this pull request as ready for review May 21, 2025 23:19
@github-actions
Copy link

⚠️ Regressions detected on macos-14 for commit c2ccaa8

Regression Summary
  • Audit: 1
  • RDD: 1

@github-actions
Copy link

⚠️ Regressions detected on macos-14 for commit 1313efb

Regression Summary
  • Audit: 1
  • RDD: 1

@github-actions
Copy link

⚠️ Regressions detected on macos-14 for commit ec4a0f9

Regression Summary
  • Table Big Diffs: 3
  • Audit: 1
  • RDD: 1

@github-actions
Copy link

⚠️ Regressions detected on macos-14 for commit 82e6d06

Regression Summary
  • Table Big Diffs: 3
  • Audit: 1
  • RDD: 1

Copy link
Contributor

@rraustad rraustad left a 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.

@Myoldmopar
Copy link
Member

@lymereJ this branch was conflicted, so I pulled develop in. It is all happy locally, but I'll let CI run before merging later.

@github-actions
Copy link

⚠️ Regressions detected on macos-14 for commit aff9d70

Regression Summary
  • Table Big Diffs: 3
  • Audit: 1
  • RDD: 1

@github-actions
Copy link

⚠️ Regressions detected on macos-14 for commit 6d20fda

Regression Summary
  • Table Big Diffs: 3
  • Audit: 1
  • RDD: 1

@github-actions
Copy link

⚠️ Regressions detected on macos-14 for commit 339e137

Regression Summary
  • Audit: 1
  • RDD: 1

@Myoldmopar
Copy link
Member

OK, dropping this in, looks good. Thanks @lymereJ

@Myoldmopar Myoldmopar merged commit 2552775 into develop May 31, 2025
9 checks passed
@Myoldmopar Myoldmopar deleted the gahp_fix_cyc branch May 31, 2025 18:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Defect Includes code to repair a defect in EnergyPlus

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Gas-Fired absorption heat pump cycling ratio calculation issue

6 participants