Skip to content
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

Chiller economizing using thermosiphon or fluid heat exchanger free cooling #10415

Merged
merged 30 commits into from
Aug 12, 2024

Conversation

rraustad
Copy link
Contributor

@rraustad rraustad commented Feb 27, 2024

Pull request overview

  • Fixes Chiller Refrigerant Migration free cooling #10179
  • Adds new features for:
  • New Feature for Chiller Thermosiphon (refrigerant migration without compressor operation)
  • Free Cooling in Air Cooled chillers
  • Integrated Water-Side Economizer with Air Cooled chiller (requires condenser loop)
  • Corrects an issue with the electric chillers where condenser inlet temperature uses the value from last time step. This should only affect heat recovery or chiller operating condition.

NOTE: ENHANCEMENTS MUST FOLLOW A SUBMISSION PROCESS INCLUDING A FEATURE PROPOSAL AND DESIGN DOCUMENT PRIOR TO SUBMITTING CODE

Pull Request Author

Add to this list or remove from it as applicable. This is a simple templated set of guidelines.

  • 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
  • If any defect files are updated to a more recent version, upload new versions here or on DevSupport
  • If IDD requires transition, transition source, rules, ExpandObjects, and IDFs must be updated, and add IDDChange label
  • If structural output changes, add to output rules file and add OutputChange label
  • If adding/removing any LaTeX docs or figures, update that document's CMakeLists file dependencies

Reviewer

This will not be exhaustively relevant to every PR.

  • 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

@rraustad rraustad added the NewFeature Includes code to add a new feature to EnergyPlus label Feb 27, 2024
@rraustad rraustad added this to the EnergyPlus 24.2 IOFreeze milestone Feb 27, 2024
@rraustad rraustad self-assigned this Feb 27, 2024
### Integrated water-side economizer with air-cooled chiller ###

Integrated water-side economizer with air-cooled chillers is likely possible with existing objects with minor additions to control of the water flow through the WWHX (HeatExchanger:FluidToFluid). One side of the WWHX would be connected to the supply side inlet node of the chiller evaporator (or other appropriate branch in the plant, i.e., pre-cool entire plant loop) while the other side of the WWHX would be connected to a demand side branch of the condenser loop. Activation of the condenser loop flow through the HX, to activate free cooling, would be accomplished through controls modification (2). The WWHX object already has inputs for Control Type, Heat Exchanger Setpoint Node Name, Minimum Temperature Difference to Activate Heat Exchanger, Operation Minimum Temperature Limit, and Operation Maximum Temperature Limit. I am unsure at this time which of these fields would be used for configuration as an integrated water-side economizer or if other inputs would be required. It may be as simple as adding a new Control Type = IntegratedWaterSideEconomizer to allow the proper controls. Investigation into the new control will include review of the Component Override Loop inputs (e.g., using chiller condenser inlet or evaporator outlet node temperature as a control point).

Copy link
Contributor

Choose a reason for hiding this comment

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

I suspect you won't need to add a new control type to the WWHX. It can use a CoolingSetpoint* method. The chiller in series downstream is controlled by component setpoint based operation instead of load-based dispatch and should just pick up the modified temperatures.

CoolingSetpointOnOffWithComponentOverride is intended for the "all or nothing" parallel configuration. May need some testing.


```
HeatPump:PlantLoop:EIR:Cooling,
A13, \field Refrigerant Migration Temperature Difference Curve Name
Copy link
Contributor

Choose a reason for hiding this comment

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

I sort of like the word Thermosiphon over Refrigerant Migration

@nrel-bot-2b
Copy link

@rraustad @Myoldmopar it has been 28 days since this pull request was last updated.

2 similar comments
@nrel-bot-2b
Copy link

@rraustad @Myoldmopar it has been 28 days since this pull request was last updated.

@nrel-bot-3
Copy link

@rraustad @Myoldmopar it has been 28 days since this pull request was last updated.

@rraustad rraustad added the IDDChange Code changes impact the IDD file (cannot be merged after IO freeze) label Jul 15, 2024
@rraustad rraustad added the OutputChange Code changes output in such a way that it cannot be merged after IO freeze label Jul 17, 2024
@@ -2464,6 +2462,9 @@ void ReformulatedEIRChillerSpecs::calculate(EnergyPlusData &state, Real64 &MyLoa

} // This is the end of the FlowLock Block

// set the module level variable used for reporting FRAC
this->ChillerCyclingRatio = FRAC;

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Unit tests showed this was not getting set correctly. Moved this equivalence outside the above IF block to capture the proper value regardless of FlowLock.

@@ -1528,6 +1528,7 @@ namespace PlantChillers {
} // End of the Air Cooled/Evap Cooled Logic block

Real64 condInletTemp = state.dataLoopNodes->Node(this->CondInletNodeNum).Temp;
this->CondInletTemp = condInletTemp; // needed if thermosiphon model is used
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The new function uses this->CondInletTemp in the calculation so need to set this before that new function is called.

if (this->thermosiphonDisabled(state)) {
this->Power = FracFullLoadPower * FullLoadPowerRat * AvailChillerCap / this->COP * FRAC;
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Moved power calculation after where evap outlet temp is calculated.

@@ -3465,13 +3479,42 @@ TEST_F(EnergyPlusFixture, TestOperatingFlowRates_FullyAutosized_AirSource)

// call with run flag ON, flow locked at nonzero both
state->dataPlnt->PlantLoop(1).LoopSide(DataPlant::LoopSideLocation::Supply).FlowLock = DataPlant::FlowLock::Locked;
state->dataLoopNodes->Node(thisCoolingPLHP->loadSideNodes.inlet).MassFlowRate = 0.14;
state->dataLoopNodes->Node(thisCoolingPLHP->loadSideNodes.inlet).MassFlowRate = 1.0;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated to avoid -24 C evap outlet temp.

@@ -73581,17 +73581,30 @@ Chiller:Electric:EIR,
\note PLR is the chilled water plant loop part load ratio (actual/design)
\type object-list
\object-list UnivariateFunctions
A20, \field Temperature Difference Across Condenser Schedule Name
A19, \field Temperature Difference Across Condenser Schedule Name
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not sure why but the idd had a mismatch with alpha field numbers in several chiller models.

return true;
}
}

Copy link
Contributor Author

@rraustad rraustad Jul 27, 2024

Choose a reason for hiding this comment

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

There is an issue here with this new function being in 4 different places. It would be better to locate this function somewhere so that there would only be 1 new function. And variable names would need to be unified. I should check to see if I made a mistake in Chiller:Electric.

    Real64 capFrac = this->ChillerPartLoadRatio * this->ChillerCyclingRatio; // Electric:EIR
    Real64 capFrac = this->ChillerPartLoadRatio * this->ChillerCyclingRatio; // ReformulatedEIR
    Real64 capFrac = this->CyclingRatio;                                     // PlantChillers, Chiller:Electric
    Real64 capFrac = this->partLoadRatio * this->cyclingRatio;               // PlantLoopHeatPump:Cooling:EIR

UPDATE: Yes, it looks like Chiller:Electric needs to track both PLR and cycling ratio.
UPDATE: added partLoadRatio to Chiller:Electric and unified what these mean

    Real64 capFrac = this->ChillerPartLoadRatio * this->ChillerCyclingRatio; // Electric:EIR
    Real64 capFrac = this->ChillerPartLoadRatio * this->ChillerCyclingRatio; // ReformulatedEIR
    Real64 capFrac = this->partLoadRatio * this->cyclingRatio;               // PlantChillers, Chiller:Electric
    Real64 capFrac = this->partLoadRatio * this->cyclingRatio;               // PlantLoopHeatPump:Cooling:EIR

UPDATE 7/27: added thermosiphon model to COP chiller.

    Real64 capFrac = this->partLoadRatio * this->cyclingRatio;               // Chiller:ConstantCOP

@rraustad
Copy link
Contributor Author

rraustad commented Jul 27, 2024

Documenting previous diffs before partLoadRatio change to Chiller:Electric:

NFP-Refrigerant-Migration-Decarbonization (rraustad) - x86_64-Linux-Ubuntu-22.04-gcc-11.4: OK (3589 of 3697 tests passed, 175 test warnings)

283 tests had: AUD diffs.
279 tests had: RDD diffs.
131 tests had: Table small diffs.
108 tests had: Table big diffs.
1 test had: ESO small diffs.
1 test had: MTR small diffs.
1 test had: MTD diffs.
1 test had: EIO diffs.
1 test had: ERR diffs.

NFP-Refrigerant-Migration-Decarbonization (rraustad) - x86_64-MacOS-10.18-clang-15.0.0: OK (3548 of 3656 tests passed, 175 test warnings)

283 tests had: AUD diffs.
279 tests had: RDD diffs.
131 tests had: Table small diffs.
108 tests had: Table big diffs.
1 test had: ESO small diffs.
1 test had: MTR small diffs.
1 test had: MTD diffs.
1 test had: EIO diffs.
1 test had: ERR diffs.

@rraustad
Copy link
Contributor Author

Results from new example file which has both the water-side economizer and the new thermosiphon model.

image

@rraustad
Copy link
Contributor Author

All diffs, except for the 1 eio file ASHRAE901_Hospital_STD2019_Denver:

image

@@ -1913,6 +1926,7 @@ void ElectricEIRChillerSpecs::calculate(EnergyPlusData &state, Real64 &MyLoad, b

// If not air or evap cooled then set to the condenser node that is attached to a cooling tower
Real64 condInletTemp = state.dataLoopNodes->Node(this->CondInletNodeNum).Temp;
this->CondInletTemp = condInletTemp; // needed for thermosiphon model
Copy link
Contributor Author

@rraustad rraustad Jul 28, 2024

Choose a reason for hiding this comment

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

If I revert (comment out) this change in the EIR and ReformulatedEIR chillers there are no eio or results diffs in example file ASHRAE901_Hospital_STD2019_Denver. This was verified through Binder plot results and diffing the eio files. The Binder script skips a plot if there are no diffs otherwise the script creates a plot.

This branch:

image

After revert of this line in 2 places:

image

Example diff from this branch for ASHRAE901_Hospital_STD2019_Denver:

image

format("Invalid Thermosiphon Capacity Fraction Curve Name = {}",
thermosiphonTempCurveName.value().get<std::string>()));
errorsFound = true;
}
Copy link
Contributor Author

@rraustad rraustad Jul 28, 2024

Choose a reason for hiding this comment

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

Test severe error using PlantLoopHeatPump_EIR_LargeOffice-2-AWHP-AuxBoiler-Pri-Sec-4PipeBeam:

** Severe  ** HeatPump:PlantLoop:EIR:Cooling ="AWHP_1 COOLING SIDE"
**   ~~~   ** Invalid Thermosiphon Capacity Fraction Curve Name = ThermosiphonCurve2
** Severe  ** HeatPump:PlantLoop:EIR:Cooling ="AWHP_2 COOLING SIDE"
**   ~~~   ** Invalid Thermosiphon Capacity Fraction Curve Name = ThermosiphonCurve3
**  Fatal  ** Previous EIR PLHP errors cause program termination

ShowContinueError(state,
format("Invalid {} = {}", state.dataIPShortCut->cAlphaFieldNames(9), state.dataIPShortCut->cAlphaArgs(9)));
ErrorsFound = true;
}
Copy link
Contributor Author

@rraustad rraustad Jul 28, 2024

Choose a reason for hiding this comment

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

Test severe error using FreeCoolingChiller_wWaterSideEconomizer:

** Severe  ** GetConstCOPChillerInput: Chiller:ConstantCOP="MAIN CHILLER"
**   ~~~   ** Invalid Thermosiphon Capacity Fraction Curve Name = THERMOCAPFRACCURVE2
**  Fatal  ** Errors found in processing input for Chiller:ConstantCOP

@rraustad rraustad changed the title New Feature Proposal for plant decarbonization Chiller free cooling using thermosiphon or fluid heat exchanger Jul 31, 2024
@rraustad rraustad changed the title Chiller free cooling using thermosiphon or fluid heat exchanger Chiller economizing using thermosiphon or fluid heat exchanger free cooling Jul 31, 2024
Copy link
Member

@Myoldmopar Myoldmopar left a comment

Choose a reason for hiding this comment

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

This is pretty impressive. High value addition for what appears to be like 2-3 hundred lines of code added. I'm going to play with this PR locally for a bit, but other than the repeated function, this is looking good from first inspection.

} else {
return true;
}
}
Copy link
Member

Choose a reason for hiding this comment

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

Yeah, this really shouldn't be repeated, right? Just add a reusable utility function somewhere accessible, add a few intent(inout) arguments, and call it anywhere it's needed. UtilityFunctions probably isn't the right spot, but neither is GeneralRoutines. Or maybe one of them is the right spot? I dunno, and also this doesn't have to hold up this PR, but it is a bit odd to have copies of the same routine to maintain.

Copy link
Contributor

Choose a reason for hiding this comment

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

I wonder if such a routine would work in the plant component base class?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I did consider moving this to a common location but wasn't sure I knew what I was doing. The calculation inside this function would require unification of variables names in the chillers.

Real64 capFrac = this->ChillerPartLoadRatio * this->ChillerCyclingRatio; // Electric:EIR
Real64 capFrac = this->ChillerPartLoadRatio * this->ChillerCyclingRatio; // ReformulatedEIR
Real64 capFrac = this->partLoadRatio * this->cyclingRatio;               // PlantChillers, Chiller:Electric
Real64 capFrac = this->partLoadRatio * this->cyclingRatio;               // PlantLoopHeatPump:Cooling:EIR
Real64 capFrac = this->partLoadRatio * this->cyclingRatio;               // Chiller:ConstantCOP

@Myoldmopar
Copy link
Member

This still works fine with develop pulled in, let's just merge this in. Thanks @rraustad and @EnergyArchmage !

@Myoldmopar Myoldmopar merged commit c89c5c9 into develop Aug 12, 2024
15 checks passed
@Myoldmopar Myoldmopar deleted the NFP-Refrigerant-Migration-Decarbonization branch August 12, 2024 19:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
IDDChange Code changes impact the IDD file (cannot be merged after IO freeze) NewFeature Includes code to add a new feature to EnergyPlus OutputChange Code changes output in such a way that it cannot be merged after IO freeze
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Chiller Refrigerant Migration free cooling
9 participants