-
Notifications
You must be signed in to change notification settings - Fork 393
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
Change EquationFit coils to reference curves #8464
Conversation
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.
Overall I think this is a great plan. I prefer to have quint-linear be added as a new object, but am curious what others think.
I noted what looks like an ugly defect (hope I'm wrong) in the curve manager but it's not anything wrong with your proposal here.
### Add quint-linear curve object? ### | ||
As described above, both quad-linear and quint-linear curves are needed for Coil:Cooling:WaterToAirHeatPump:EquationFit, while other coils only require quad-linear curves. In order to satisfy Coil:Cooling:WaterToAirHeatPump:EquationFit curve specifications, we can either: | ||
- Add quint-linear curves so that the curve type of every curve referred can be explicitly specified. This is a more straightforward path to move forward to. | ||
- Change quad-linear curves to be more general as "multi-linear" or simply replace it by quint-linear curves, regarding to the similarity between quad-linear and quint linear curves. Users can simply add 0 coefficients to whatever variables that are not important or E+ can only read specific number of coefficients for specific input. Notice that there's no tri-linear or bi-linear curve types in Energyplus which might imply some preference to this approach in its first place (Is that true? Any example of using quad-linear curve type to read in tri-linear curves?). |
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.
My preference would be to have targeted curve types for each set of coefficients.
Right now the CurveValue function takes 1 required independent variable and 5 Objexx::Optional
arguments. Then inside the function the values are passed into a curve worker function that then does operations to check if the arguments are present or not and override them with zeroes, then finally hit a big IF block on the curve type for evaluating the proper output.
The CurveValue function could eventually be refactored into individual functions that would reduce the amount of logic in each one and hopefully increase performance, especially considering how often curves are evaluated. With that in mind, I think it would be better then to keep each curve type separate.
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.
Now here's an interesting aside.
The CurveValue function has 6 total possible independent variable arguments. 1 is required and 5 are optional. Inside that function, it switches depending on whether you are looking the value up in a table or evaluating a curve. If you are using a table, it passes all 6 arguments. However, if you are evaluating a curve, it only passes the first 3! Am I missing something?!
The condenser setpoint manager definitely uses a quad linear curve and calls CurveValue with 4 independent variables expecting them to be used....is the 4th just ignored?
Really though, am I missing something here @mjwitte @mitchute ?
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.
Yeah, this looks like a bug to me. However, even if it were passed, it looks like the only thing the fourth variable is used for in PerformanceCurveObject
is to do bounds checking.
EnergyPlus/src/EnergyPlus/CurveManager.cc
Line 2286 in 6163e5b
Real64 const V4(Var4.present() ? max(min(Var4, Curve.Var4Max), Curve.Var4Min) : 0.0); // 4th independent variable after limits imposed |
V4
doesn't appear in any of the CurveType
equations.
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.
Nevermind, it does appear in the QuadLinear
curve. So, yes, this is a bug.
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.
@Myoldmopar Um, no, it appears that's been broken since Curve:Quadlinear was first added - long, long, ago. A quick series of unit tests of curve types should verify that.
There are a couple of rudimentary curve unit tests that don't even check the returned curve value, and this one has zero for the last two coefficients.
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.
Fantastic 🤦
OK, so @yzhou601, for this feature to work, you'll need to modify the CurveValue
logic to pass in more arguments. There could be unintended consequences (performance) to this, so it's worth discussing how you want to handle this. Do you want to open a separate issue and look at it yourself? Open a separate issue and request someone else on the team address it? Just address it as you work on this feature?
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.
Oops, a stray click marked this all as resolved for a bit. Sorry about that. The last time I was in there, I think I fixed one of the other less commonly used curves and it caused diffs. Maybe that won't happen this time, but it is a real possibility.
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.
@Myoldmopar Thanks, Edwin. As far as I know from the conversation, it doesn't sound like something complicated to address. I can try resolving it when I work on this feature, if I find any extra complication, I can try reaching out to one of you for some help. Does it sound good?
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 happy to take a look at this separately if needed.
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.
…ationfitcoil-curve
if (NumNums > 14) { | ||
if (!DataIPShortCuts::lNumericFieldBlanks(15)) { | ||
GSHP(GSHPNum).refCOP = DataIPShortCuts::rNumericArgs(15); | ||
GSHP(GSHPNum).CoolCapCurveIndex = GetCurveIndex(state, DataIPShortCuts::cAlphaArgs(6)); |
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.
@yzhou601 The selected curves should be validated using CurveManager::CheckCurveDims
. Here's an example in VRF. Also, I'm not sure if these curves are supposed to equal 1.0 with a certain set of inputs or not. If so, also use checkCurveIsNormalizedToOne
to check and throw a warnings if it's not.
…ationfitcoil-curve
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.
Some code walkthrough to help review.
No numerical diffs to justify on CI. CI only shows diffs on AUD, RDD and Table, table are different on object counts (curve objects added), RDD shows more input variables to look at, AUD shows more NumOfRVariable and numEMSActuatorsAvailable (not quite sure whether they're expected, can these be caused by new curve type that is actuable?).
EXPECT_EQ(expected_value, CurveManager::CurveValue(*state, 1, var1, var2, var3, var4)); | ||
} | ||
|
||
TEST_F(EnergyPlusFixture, QuintLinearCurve) |
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.
Unit test for new curve type
|
||
double var1 = 1, var2 = 0.1, var3 = 20, var4 = 10; | ||
double expected_value = -3.3333 + (0.1*1) + (38.9*0.1) + (0.1*20) + (0.5 * 10); | ||
EXPECT_EQ(expected_value, CurveManager::CurveValue(*state, 1, var1, var2, var3, var4)); |
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 curve value check for quad-linear curve bugfix (where 4th variable is ignored in calculations)
@@ -306,7 +306,7 @@ TEST_F(EnergyPlusFixture, SetPointManager_DefineCondEntSetPointManager) | |||
"Dimensionless; !- Input Unit Type for z", | |||
"Curve:QuadLinear,", | |||
"OptCondEntCurveName, !- Name", | |||
"12.2711, !- Coefficient1 Constant", | |||
"13.2711, !- Coefficient1 Constant", |
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.
Unit test broke after the curve bugfix. Adjusted the constant to make it passing.
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.
👍
@@ -200,7 +201,7 @@ namespace CurveManager { | |||
{ | |||
auto const SELECT_CASE_var(state.dataCurveManager->PerfCurve(CurveIndex).InterpolationType); | |||
if (SELECT_CASE_var == InterpTypeEnum::EvaluateCurveToLimits) { | |||
CurveValue = PerformanceCurveObject(state, CurveIndex, Var1, Var2, Var3); | |||
CurveValue = PerformanceCurveObject(state, CurveIndex, Var1, Var2, Var3, Var4, Var5, Var6); |
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.
Bugfix here.
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.
Looks good.
@@ -269,6 +270,7 @@ namespace CurveManager { | |||
int NumQuadLinear; // Number of quadratic linear curve objects in the input data file | |||
int NumCubicLinear; // Number of cubic linear curve objects in the input file | |||
int NumQLinear; // Number of quad linear curve objects in the input data file | |||
int NumQuintLinear; // Number of quint linear curve objects in the input data file |
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 quint-linear new curve type
ErrorsFound = true; | ||
const int NumVar = 4; | ||
std::string VarNames[NumVar] = {"w", "x", "y", "z"}; | ||
for (int i = 1; i <= NumVar; ++i) { |
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.
Refactor to simplify input checks when number of variables are large.
@@ -291,20 +293,30 @@ namespace EnergyPlus::HeatPumpWaterToWaterSimple { | |||
if (state.dataHPWaterToWaterSimple->GSHP(GSHPNum).RatedPowerCool == DataSizing::AutoSize) { | |||
state.dataHPWaterToWaterSimple->GSHP(GSHPNum).ratedPowerCoolWasAutoSized = true; | |||
} | |||
state.dataHPWaterToWaterSimple->GSHP(GSHPNum).CoolCap1 = DataIPShortCuts::rNumericArgs(5); |
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.
Change watertowater equationfit coils to reference curves.
@@ -363,24 +365,39 @@ namespace WaterToAirHeatPumpSimple { | |||
state.dataWaterToAirHeatPumpSimple->SimpleWatertoAirHP(HPNum).RatedCapCoolTotal = NumArray(3); | |||
state.dataWaterToAirHeatPumpSimple->SimpleWatertoAirHP(HPNum).RatedCapCoolSens = NumArray(4); | |||
state.dataWaterToAirHeatPumpSimple->SimpleWatertoAirHP(HPNum).RatedCOPCool = NumArray(5); | |||
state.dataWaterToAirHeatPumpSimple->SimpleWatertoAirHP(HPNum).TotalCoolCap1 = NumArray(6); |
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.
Change watertoair equationfit coils to reference curves.
src/ExpandObjects/epfilter.f90
Outdated
@@ -17061,24 +17061,62 @@ SUBROUTINE CreateNewUnitary | |||
StringToReal(FldVal(base + ussCoolCoilSHROff))) | |||
ENDIF | |||
CALL AddToObjFld('Rated Cooling Coefficient of Performance',base + ussCoolCoilCOPOff,'') | |||
CALL AddToObjStr('Total Cooling Capacity Coefficient 1','-9.149069561') |
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.
Change expand object structures of water-to-air equationfit coils
@@ -398,6 +402,97 @@ SUBROUTINE CreateNewIDFUsingRules(EndOfFile,DiffOnly,InLfn,AskForInput,InputFile | |||
' Radiant Exchange Method option IRTSurface is no longer valid. '// & | |||
'The air boundary will be modeled using the GroupedZones method.') | |||
END IF | |||
|
|||
CASE('COIL:COOLING:WATERTOAIRHEATPUMP:EQUATIONFIT') |
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.
Transition of equationfit coil structure change from v9.4 to v9.5.
Well, from a first glance, this has a new build warning. It's super minor, but also annoying and won't be merged with a warning in it. I'm looking over the code changes again now. |
The other CI issues are all fine, minor diffs about output variables. |
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 looks good, I'll build and test the transition rules.
idd/Energy+.idd.in
Outdated
N21, \field Cooling Power Consumption Coefficient 5 | ||
\type object-list | ||
\object-list QuintvariateFunctions | ||
A8, \field Cooling Power Consumption Curve 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.
Yes, yes. Lots better here.
Optional<Real64 const> Var4 = _ // 4th independent variable | ||
Optional<Real64 const> Var4 = _, // 4th independent variable | ||
Optional<Real64 const> Var5 = _, // 5th independent variable | ||
Optional<Real64 const> Var6 = _ // 6th independent variable |
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.
👍
@@ -200,7 +201,7 @@ namespace CurveManager { | |||
{ | |||
auto const SELECT_CASE_var(state.dataCurveManager->PerfCurve(CurveIndex).InterpolationType); | |||
if (SELECT_CASE_var == InterpTypeEnum::EvaluateCurveToLimits) { | |||
CurveValue = PerformanceCurveObject(state, CurveIndex, Var1, Var2, Var3); | |||
CurveValue = PerformanceCurveObject(state, CurveIndex, Var1, Var2, Var3, Var4, Var5, Var6); |
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.
Looks good.
|
||
Power = CoolPowerRated * | ||
(CoolPowerCoeff1 + (func1 * CoolPowerCoeff2) + (func2 * CoolPowerCoeff3) + (func3 * CoolPowerCoeff4) + (func4 * CoolPowerCoeff5)); | ||
Power = CoolPowerRated * CurveValue(state, this->CoolPowCurveIndex, func1, func2, func3, func4); |
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.
👍
@@ -306,7 +306,7 @@ TEST_F(EnergyPlusFixture, SetPointManager_DefineCondEntSetPointManager) | |||
"Dimensionless; !- Input Unit Type for z", | |||
"Curve:QuadLinear,", | |||
"OptCondEntCurveName, !- Name", | |||
"12.2711, !- Coefficient1 Constant", | |||
"13.2711, !- Coefficient1 Constant", |
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.
👍
OK, built this locally no problem. I cleaned up the unused variable warning, which led to the Var6 argument being unused, so I marked it as @yzhou601 please check out the change I made to the PerformanceCurveObject function, if Var6 really isn't ever used then it shouldn't be passed in as an argument. If Var6 is supposed to be used, then something is wrong in the function logic. Open a follow-up issue as needed and address it in a separate PR. |
(I pushed, merged and deleted very quickly so it is certainly possible that some of the github action CI tests will show weird failures) |
@Myoldmopar Currently, there's no type of curve that utilizes 6 variables, so Var6 can only be possible to be used in the future. Didn't seem any issue for now. |
In that case, can you open a followup issue to remove that extra argument for now? We don't want any runtime performance penalty from having that extra Optional argument in there if it really isn't ever used. Thanks! |
Pull request overview
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.
Reviewer
This will not be exhaustively relevant to every PR.