Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 4 additions & 8 deletions src/EnergyPlus/PlantLoopHeatPumpEIR.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2677,7 +2677,7 @@ void EIRFuelFiredHeatPump::doPhysics(EnergyPlusData &state, Real64 currentLoad)
}

// evaluate capacity modifier curve and determine load side heat transfer
Real64 capacityModifierFuncTemp = Curve::CurveValue(state, this->capFuncTempCurveIndex, waterTempforCurve, oaTempforCurve);
Real64 capacityModifierFuncTemp = Curve::CurveValue(state, this->capFuncTempCurveIndex, oaTempforCurve, waterTempforCurve);
Copy link
Collaborator

@rraustad rraustad May 20, 2025

Choose a reason for hiding this comment

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

I think I would have voted for a change in documentation since all other models use Tamb as the second independent variable. It doesn't really matter except for consistency across models. I do see that the paper used Tamb as the first independent variable but when calculating biquadratic regression coefficients that order is subjective. It just means that the paper's coefficient a and b would become c and d in E+. Does the example file use these same coefficients? @mjwitte what are your thoughts on independent variable order for performance curves?

image

EIR HP:
capacityModifierFuncTemp = Curve::CurveValue(state, this->capFuncTempCurveIndex, loadSideOutletSetpointTemp, this->sourceSideInletTemp);

DXCoils:
TotCapTempModFac = CurveValue(state, thisDXCoil.CCapFTemp(Mode), InletAirWetBulbC, CondInletTemp);

Copy link
Contributor

Choose a reason for hiding this comment

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

@rraustad My initial advice was to follow the paper, but I didn't think about how other similar curves are done in EnergyPlus.
@lymereJ I don't see any changes here to the example file. Can you tell which variable order was used in those curves?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@mjwitte - The example file includes curves with only a constant coefficient:

  Curve:Biquadratic,
    EIRCurveFuncTemp,        !- Name
    1.0,                     !- Coefficient1 Constant
    0.0,                     !- Coefficient2 x
    0.0,                     !- Coefficient3 x**2
    0.0,                     !- Coefficient4 y
    0.0,                     !- Coefficient5 y**2
    0.0,                     !- Coefficient6 x*y
    5.0,                     !- Minimum Value of x
    10.0,                    !- Maximum Value of x
    24.0,                    !- Minimum Value of y
    35.0,                    !- Maximum Value of y
    ,                        !- Minimum Curve Output
    ,                        !- Maximum Curve Output
    Temperature,             !- Input Unit Type for X
    Temperature,             !- Input Unit Type for Y
    Dimensionless;           !- Output Unit Type

  Curve:Biquadratic,
    CapCurveFuncTemp,        !- Name
    1.0,                     !- Coefficient1 Constant
    0.0,                     !- Coefficient2 x
    0.0,                     !- Coefficient3 x**2
    0.0,                     !- Coefficient4 y
    0.0,                     !- Coefficient5 y**2
    0.0,                     !- Coefficient6 x*y
    5.0,                     !- Minimum Value of x
    10.0,                    !- Maximum Value of x
    24.0,                    !- Minimum Value of y
    35.0,                    !- Maximum Value of y
    ,                        !- Minimum Curve Output
    ,                        !- Maximum Curve Output
    Temperature,             !- Input Unit Type for X
    Temperature,             !- Input Unit Type for Y
    Dimensionless;           !- Output Unit Type

So, should I revert these changes and make the changes in the documentation? Here's perhaps another argument for modifying the documentation instead of the code: the EIR-f-T curves in the paper have to be renormalized because they describe not just a EIR modifier but the change in rated EIR as a function of the temperature. Please, let me know what you think is best.

Copy link
Contributor

Choose a reason for hiding this comment

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

I guess changing the documentation (and replacing these constant curves) is the better option. Sorry to send you down the wrong path.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Got it, no worries.


if (capacityModifierFuncTemp < 0.0) {
if (this->capModFTErrorIndex == 0) {
Expand Down Expand Up @@ -2717,11 +2717,7 @@ void EIRFuelFiredHeatPump::doPhysics(EnergyPlusData &state, Real64 currentLoad)
this->loadSideOutletTemp = this->calcLoadOutletTemp(this->loadSideInletTemp, this->loadSideHeatTransfer / loadMCp);

// calculate power usage from EIR curves
Real64 eirModifierFuncTemp = Curve::CurveValue(state,
this->powerRatioFuncTempCurveIndex,
waterTempforCurve,
oaTempforCurve); // CurveManager::CurveValue(state, this->powerRatioFuncTempCurveIndex,
// this->loadSideOutletTemp, this->sourceSideInletTemp);
Real64 eirModifierFuncTemp = Curve::CurveValue(state, this->powerRatioFuncTempCurveIndex, oaTempforCurve, waterTempforCurve);

if (eirModifierFuncTemp < 0.0) {
if (this->eirModFTErrorIndex == 0) {
Expand Down Expand Up @@ -2815,7 +2811,7 @@ void EIRFuelFiredHeatPump::doPhysics(EnergyPlusData &state, Real64 currentLoad)
// aux elec
Real64 eirAuxElecFuncTemp = 0.0;
if (this->auxElecEIRFoTempCurveIndex > 0) {
eirAuxElecFuncTemp = Curve::CurveValue(state, this->auxElecEIRFoTempCurveIndex, waterTempforCurve, oaTempforCurve);
eirAuxElecFuncTemp = Curve::CurveValue(state, this->auxElecEIRFoTempCurveIndex, oaTempforCurve, waterTempforCurve);
}

if (eirAuxElecFuncTemp < 0.0) {
Expand Down Expand Up @@ -3724,7 +3720,7 @@ Real64 EIRFuelFiredHeatPump::getDynamicMaxCapacity(EnergyPlusData &state)
}

// evaluate capacity modifier curve and determine load side heat transfer
Real64 capacityModifierFuncTemp = Curve::CurveValue(state, this->capFuncTempCurveIndex, waterTempforCurve, oaTempforCurve);
Real64 capacityModifierFuncTemp = Curve::CurveValue(state, this->capFuncTempCurveIndex, oaTempforCurve, waterTempforCurve);
return this->referenceCapacity * capacityModifierFuncTemp;
}

Expand Down
58 changes: 29 additions & 29 deletions tst/EnergyPlus/unit/PlantLoopHeatPumpEIR.unit.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4541,10 +4541,10 @@ TEST_F(EnergyPlusFixture, GAHP_HeatingSimulate_AirSource_with_Defrost)
" 0.0,",
" 0.0,",
" 0.0,",
" 5.0,",
" 10.0,",
" 24.0,",
" 35.0,",
" 5.0,",
" 10.0,",
" ,",
" ,",
" Temperature,",
Expand All @@ -4553,15 +4553,15 @@ TEST_F(EnergyPlusFixture, GAHP_HeatingSimulate_AirSource_with_Defrost)
"Curve:Biquadratic,",
" EIRCurveFuncTemp,",
" 1.0,",
" 1.0,",
" 0.0,",
" 0.0,",
" 1.0,",
" 0.0,",
" 0.0,",
" 5.0,",
" 10.0,",
" 24.0,",
" 35.0,",
" 5.0,",
" 10.0,",
" ,",
" ,",
" Temperature,",
Expand Down Expand Up @@ -5639,10 +5639,10 @@ TEST_F(EnergyPlusFixture, GAHP_AirSource_CurveEval)
" 0, !- Coefficient4 y",
" 0, !- Coefficient5 y**2",
" 0, !- Coefficient6 x*y",
" 5, !- Minimum Value of x {BasedOnField A2}",
" 10, !- Maximum Value of x {BasedOnField A2}",
" 24, !- Minimum Value of y {BasedOnField A3}",
" 35, !- Maximum Value of y {BasedOnField A3}",
" 24, !- Minimum Value of x {BasedOnField A2}",
" 35, !- Maximum Value of x {BasedOnField A2}",
" 5, !- Minimum Value of y {BasedOnField A3}",
" 10, !- Maximum Value of y {BasedOnField A3}",
" , !- Minimum Curve Output {BasedOnField A4}",
" , !- Maximum Curve Output {BasedOnField A4}",
" Temperature, !- Input Unit Type for X",
Expand All @@ -5656,10 +5656,10 @@ TEST_F(EnergyPlusFixture, GAHP_AirSource_CurveEval)
" 0, !- Coefficient4 y",
" 0, !- Coefficient5 y**2",
" 0, !- Coefficient6 x*y",
" 5, !- Minimum Value of x {BasedOnField A2}",
" 10, !- Maximum Value of x {BasedOnField A2}",
" 24, !- Minimum Value of y {BasedOnField A3}",
" 35, !- Maximum Value of y {BasedOnField A3}",
" 24, !- Minimum Value of x {BasedOnField A2}",
" 35, !- Maximum Value of x {BasedOnField A2}",
" 5, !- Minimum Value of y {BasedOnField A3}",
" 10, !- Maximum Value of y {BasedOnField A3}",
" , !- Minimum Curve Output {BasedOnField A4}",
" , !- Maximum Curve Output {BasedOnField A4}",
" Temperature, !- Input Unit Type for X",
Expand Down Expand Up @@ -5811,16 +5811,16 @@ TEST_F(EnergyPlusFixture, GAHP_AirSource_CurveEval)
{
ASSERT_GT(thisHeatingPLHP->capFuncTempCurveIndex, 0);
auto const *thisCurve = state->dataCurveManager->curves(thisHeatingPLHP->capFuncTempCurveIndex);
Real64 const waterTempforCurve = thisCurve->inputs[0];
Real64 const oaTempforCurve = thisCurve->inputs[1];
Real64 const waterTempforCurve = thisCurve->inputs[1];
Real64 const oaTempforCurve = thisCurve->inputs[0];
EXPECT_EQ(calculatedLoadInletTemp, waterTempforCurve);
EXPECT_EQ(oaTemp, oaTempforCurve);
}
{
ASSERT_GT(thisHeatingPLHP->powerRatioFuncTempCurveIndex, 0);
auto const *thisCurve = state->dataCurveManager->curves(thisHeatingPLHP->powerRatioFuncTempCurveIndex);
Real64 const waterTempforCurve = thisCurve->inputs[0];
Real64 const oaTempforCurve = thisCurve->inputs[1];
Real64 const waterTempforCurve = thisCurve->inputs[1];
Real64 const oaTempforCurve = thisCurve->inputs[0];
EXPECT_EQ(calculatedLoadInletTemp, waterTempforCurve);
EXPECT_EQ(oaTemp, oaTempforCurve);
}
Expand Down Expand Up @@ -5854,16 +5854,16 @@ TEST_F(EnergyPlusFixture, GAHP_AirSource_CurveEval)
{
ASSERT_GT(thisCoolingPLHP->powerRatioFuncTempCurveIndex, 0);
auto const *thisCurve = state->dataCurveManager->curves(thisCoolingPLHP->capFuncTempCurveIndex);
Real64 const waterTempforCurve = thisCurve->inputs[0];
Real64 const oaTempforCurve = thisCurve->inputs[1];
Real64 const waterTempforCurve = thisCurve->inputs[1];
Real64 const oaTempforCurve = thisCurve->inputs[0];
EXPECT_EQ(calculatedLoadInletTemp, waterTempforCurve);
EXPECT_EQ(oaTemp, oaTempforCurve);
}
{
ASSERT_GT(thisCoolingPLHP->powerRatioFuncTempCurveIndex, 0);
auto const *thisCurve = state->dataCurveManager->curves(thisCoolingPLHP->powerRatioFuncTempCurveIndex);
Real64 const waterTempforCurve = thisCurve->inputs[0];
Real64 const oaTempforCurve = thisCurve->inputs[1];
Real64 const waterTempforCurve = thisCurve->inputs[1];
Real64 const oaTempforCurve = thisCurve->inputs[0];
EXPECT_EQ(calculatedLoadInletTemp, waterTempforCurve);
EXPECT_EQ(oaTemp, oaTempforCurve);
}
Expand Down Expand Up @@ -5897,16 +5897,16 @@ TEST_F(EnergyPlusFixture, GAHP_AirSource_CurveEval)
{
ASSERT_GT(thisHeatingPLHP->capFuncTempCurveIndex, 0);
auto const *thisCurve = state->dataCurveManager->curves(thisHeatingPLHP->capFuncTempCurveIndex);
Real64 const waterTempforCurve = thisCurve->inputs[0];
Real64 const oaTempforCurve = thisCurve->inputs[1];
Real64 const waterTempforCurve = thisCurve->inputs[1];
Real64 const oaTempforCurve = thisCurve->inputs[0];
EXPECT_EQ(ori_loadSideOutletTemp, waterTempforCurve);
EXPECT_EQ(oaWetbulb, oaTempforCurve);
}
{
ASSERT_GT(thisHeatingPLHP->powerRatioFuncTempCurveIndex, 0);
auto const *thisCurve = state->dataCurveManager->curves(thisHeatingPLHP->powerRatioFuncTempCurveIndex);
Real64 const waterTempforCurve = thisCurve->inputs[0];
Real64 const oaTempforCurve = thisCurve->inputs[1];
Real64 const waterTempforCurve = thisCurve->inputs[1];
Real64 const oaTempforCurve = thisCurve->inputs[0];
EXPECT_EQ(ori_loadSideOutletTemp, waterTempforCurve);
EXPECT_EQ(oaWetbulb, oaTempforCurve);
}
Expand Down Expand Up @@ -5939,16 +5939,16 @@ TEST_F(EnergyPlusFixture, GAHP_AirSource_CurveEval)
{
ASSERT_GT(thisCoolingPLHP->powerRatioFuncTempCurveIndex, 0);
auto const *thisCurve = state->dataCurveManager->curves(thisCoolingPLHP->capFuncTempCurveIndex);
Real64 const waterTempforCurve = thisCurve->inputs[0];
Real64 const oaTempforCurve = thisCurve->inputs[1];
Real64 const waterTempforCurve = thisCurve->inputs[1];
Real64 const oaTempforCurve = thisCurve->inputs[0];
EXPECT_EQ(ori_loadSideOutletTemp, waterTempforCurve);
EXPECT_EQ(oaWetbulb, oaTempforCurve);
}
{
ASSERT_GT(thisCoolingPLHP->powerRatioFuncTempCurveIndex, 0);
auto const *thisCurve = state->dataCurveManager->curves(thisCoolingPLHP->powerRatioFuncTempCurveIndex);
Real64 const waterTempforCurve = thisCurve->inputs[0];
Real64 const oaTempforCurve = thisCurve->inputs[1];
Real64 const waterTempforCurve = thisCurve->inputs[1];
Real64 const oaTempforCurve = thisCurve->inputs[0];
EXPECT_EQ(ori_loadSideOutletTemp, waterTempforCurve);
EXPECT_EQ(oaWetbulb, oaTempforCurve);
}
Expand Down