Skip to content

Commit

Permalink
Merge pull request #10226 from NREL/9845-history-terms
Browse files Browse the repository at this point in the history
Correct zone temperature history terms for ThirdOrderBackwardDifference heat balance equation
  • Loading branch information
Myoldmopar authored Jan 9, 2024
2 parents 4852b22 + c196cce commit 0c0cdaa
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 96 deletions.
156 changes: 69 additions & 87 deletions src/EnergyPlus/ZoneTempPredictorCorrector.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5025,114 +5025,96 @@ void DownInterpolate4HistoryValues(Real64 const OldTimeStep,
// The down step ratio, DSRatio = OldTimeStep/ NewTimeStep
// is expected to be roughly integer-valued and near 2.0 or 3.0 or 4.0 or more.

// first construct data on timestamps for interpolating with later
Real64 const oldTime0 = 0.0;
Real64 const oldTime1 = oldTime0 - OldTimeStep;

Real64 const newTime0 = 0.0;
Real64 const newTime1 = newTime0 - NewTimeStep;
Real64 const newTime2 = newTime1 - NewTimeStep;
Real64 const newTime3 = newTime2 - NewTimeStep;
Real64 const newTime4 = newTime3 - NewTimeStep;

// old math variables
// Real64 const oldTime0 = 0.0;
// Real64 const oldTime1 = oldTime0 - OldTimeStep;
// Real64 const newTime0 = 0.0;
// Real64 const newTime1 = newTime0 - NewTimeStep;
// Real64 const newTime2 = newTime1 - NewTimeStep;
// Real64 const newTime3 = newTime2 - NewTimeStep;
// Real64 const newTime4 = newTime3 - NewTimeStep;

Real64 constexpr realTWO = 2.0;
Real64 constexpr realTHREE = 3.0;
// first determine the ratio of system time step to zone time step
Real64 const DSRatio = OldTimeStep / NewTimeStep; // should pretty much be an integer value 2, 3, 4, etc.

newVal0 = oldVal0;

if (std::abs(DSRatio - 2.0) < 0.01) { // DSRatio = 2
if (std::abs(DSRatio - realTWO) < 0.01) { // DSRatio = 2
// when DSRatio = 2 the 1st point lies exactly between old points, and 2nd point is old 1st point
// first two points lie between oldVal0 and oldVal1
newVal1 = oldVal0 + (oldVal1 - oldVal0) * ((oldTime0 - newTime1) / (OldTimeStep));
newVal2 = oldVal0 + (oldVal1 - oldVal0) * ((oldTime0 - newTime2) / (OldTimeStep));
// old math example
// newVal1 = oldVal0 + (oldVal1 - oldVal0) * ((oldTime0 - newTime1) / (OldTimeStep));
// newVal2 = oldVal0 + (oldVal1 - oldVal0) * ((oldTime0 - newTime2) / (OldTimeStep));
newVal1 = (oldVal0 + oldVal1) / realTWO;
newVal2 = oldVal1;
// when DSRatio = 2 the 3rd point lies exactly between old points, and 4th point is old 2nd point
// last two points lie between oldVal1 and oldVal2
newVal3 = oldVal1 + (oldVal2 - oldVal1) * ((oldTime1 - newTime3) / (OldTimeStep));
newVal4 = oldVal1 + (oldVal2 - oldVal1) * ((oldTime1 - newTime4) / (OldTimeStep));
} else if (std::abs(DSRatio - 3.0) < 0.01) { // DSRatio = 3
// newVal3 = oldVal1 + (oldVal2 - oldVal1) * ((oldTime1 - newTime3) / (OldTimeStep));
// newVal4 = oldVal1 + (oldVal2 - oldVal1) * ((oldTime1 - newTime4) / (OldTimeStep));
newVal3 = (oldVal1 + oldVal2) / realTWO;
newVal4 = oldVal2;
} else if (std::abs(DSRatio - realTHREE) < 0.01) { // DSRatio = 3
// when DSRatio = 3 the 1st point lies 1/3 way between old points, and 2nd and 3rd points are 2/3 and 3/3 the way
// first three points lie between oldVal0 and oldVal1
newVal1 = oldVal0 + (oldVal1 - oldVal0) * ((oldTime0 - newTime1) / (OldTimeStep));
newVal2 = oldVal0 + (oldVal1 - oldVal0) * ((oldTime0 - newTime2) / (OldTimeStep));
newVal3 = oldVal0 + (oldVal1 - oldVal0) * ((oldTime0 - newTime3) / (OldTimeStep));
// last point lie between oldVal1 and oldVal2
newVal4 = oldVal1 + (oldVal2 - oldVal1) * ((oldTime1 - newTime4) / (OldTimeStep));
// newVal1 = oldVal0 + (oldVal1 - oldVal0) * ((oldTime0 - newTime1) / (OldTimeStep));
// newVal2 = oldVal0 + (oldVal1 - oldVal0) * ((oldTime0 - newTime2) / (OldTimeStep));
// newVal3 = oldVal0 + (oldVal1 - oldVal0) * ((oldTime0 - newTime3) / (OldTimeStep));
Real64 delta10 = (oldVal1 - oldVal0) / realTHREE;
newVal1 = oldVal0 + delta10;
newVal2 = newVal1 + delta10;
newVal3 = oldVal1;
// last point lies 1/3 way between oldVal1 and oldVal2
// newVal4 = oldVal1 + (oldVal2 - oldVal1) * ((oldTime1 - newTime4) / (OldTimeStep));
newVal4 = oldVal1 + (oldVal2 - oldVal1) / realTHREE;

} else { // DSRatio = 4 or more
// all new points lie between oldVal0 and oldVal1
newVal1 = oldVal0 + (oldVal1 - oldVal0) * ((oldTime0 - newTime1) / (OldTimeStep));
newVal2 = oldVal0 + (oldVal1 - oldVal0) * ((oldTime0 - newTime2) / (OldTimeStep));
newVal3 = oldVal0 + (oldVal1 - oldVal0) * ((oldTime0 - newTime3) / (OldTimeStep));
newVal4 = oldVal0 + (oldVal1 - oldVal0) * ((oldTime0 - newTime4) / (OldTimeStep));
// all new points lie between oldVal0 and oldVal1 (if DSRatio = 4, newVal4 = oldVal1)
// newVal1 = oldVal0 + (oldVal1 - oldVal0) * ((oldTime0 - newTime1) / (OldTimeStep));
// newVal2 = oldVal0 + (oldVal1 - oldVal0) * ((oldTime0 - newTime2) / (OldTimeStep));
// newVal3 = oldVal0 + (oldVal1 - oldVal0) * ((oldTime0 - newTime3) / (OldTimeStep));
// newVal4 = oldVal0 + (oldVal1 - oldVal0) * ((oldTime0 - newTime4) / (OldTimeStep));
Real64 delta10 = (oldVal1 - oldVal0) / DSRatio;
newVal1 = oldVal0 + delta10;
newVal2 = newVal1 + delta10;
newVal3 = newVal2 + delta10;
newVal4 = newVal3 + delta10;
}
}

Real64 DownInterpolate4HistoryValues(Real64 OldTimeStep, Real64 NewTimeStep, std::array<Real64, 4> const &oldVals, std::array<Real64, 4> &newVals)
{
// first construct data on timestamps for interpolating with later
Real64 const oldTime0 = 0.0;
Real64 const oldTime1 = oldTime0 - OldTimeStep;
Real64 constexpr realTWO = 2.0;
Real64 constexpr realTHREE = 3.0;
// first determine the ratio of system time step to zone time step
Real64 const DSRatio = OldTimeStep / NewTimeStep; // should pretty much be an integer value 2, 3, 4, etc.

Real64 const newTime0 = 0.0;
Real64 const newTime1 = newTime0 - NewTimeStep;
Real64 const newTime2 = newTime1 - NewTimeStep;
Real64 const newTime3 = newTime2 - NewTimeStep;
Real64 const newTime4 = newTime3 - NewTimeStep;
newVals[0] = oldVals[0];

Real64 const DSRatio = OldTimeStep / NewTimeStep; // should pretty much be an integer value 2, 3, 4, etc.
if (std::abs(DSRatio - realTWO) < 0.01) { // DSRatio = 2
// first point lies exactly between (oldVals[0] and oldVals[1])
newVals[1] = (oldVals[0] + oldVals[1]) / realTWO;
// 2nd point is oldVal[1] and last point lies exactly between (oldVals[1] and oldVals[2])
newVals[2] = oldVals[1];
newVals[3] = (oldVals[1] + oldVals[2]) / realTWO;

if (std::abs(DSRatio - 2.0) < 0.01) { // DSRatio = 2
// first two points lie between oldVals[0] and oldVals[1]
Real64 delta10 = oldVals[1] - oldVals[0];
newVals[0] = oldVals[0] + delta10 * ((oldTime0 - newTime1) / OldTimeStep);
newVals[1] = oldVals[0] + delta10 * ((oldTime0 - newTime2) / OldTimeStep);
// last two points lie between oldVals[1] and oldVals[2]
Real64 delta21 = oldVals[2] - oldVals[1];
newVals[2] = oldVals[1] + delta21 * ((oldTime1 - newTime3) / OldTimeStep);
newVals[3] = oldVals[1] + delta21 * ((oldTime1 - newTime4) / OldTimeStep);
} else if (std::abs(DSRatio - 3.0) < 0.01) { // DSRatio = 3
// first three points lie between oldVals[0] and oldVals[1]
Real64 delta10 = oldVals[1] - oldVals[0];
newVals[0] = oldVals[0] + delta10 * ((oldTime0 - newTime1) / OldTimeStep);
newVals[1] = oldVals[0] + delta10 * ((oldTime0 - newTime2) / OldTimeStep);
newVals[2] = oldVals[0] + delta10 * ((oldTime0 - newTime3) / OldTimeStep);
// last point lie between oldVals[1] and oldVals[2]
Real64 delta21 = (oldVals[2] - oldVals[1]) / OldTimeStep;
newVals[3] = oldVals[1] + delta21 * ((oldTime1 - newTime4) / OldTimeStep);
} else if (std::abs(DSRatio - realTHREE) < 0.01) { // DSRatio = 3
// first two points lie between (oldVals[0] and oldVals[1])
Real64 delta10 = (oldVals[1] - oldVals[0]) / realTHREE;
newVals[1] = oldVals[0] + delta10;
newVals[2] = newVals[1] + delta10;
// last point is oldVals[1]
newVals[3] = oldVals[1];

} else { // DSRatio = 4 or more
// all new points lie between oldVals[0] and oldVals[1]
Real64 delta10 = oldVals[1] - oldVals[0];
newVals[0] = oldVals[0] + delta10 * ((oldTime0 - newTime1) / OldTimeStep);
newVals[1] = oldVals[0] + delta10 * ((oldTime0 - newTime2) / OldTimeStep);
newVals[2] = oldVals[0] + delta10 * ((oldTime0 - newTime3) / OldTimeStep);
newVals[3] = oldVals[0] + delta10 * ((oldTime0 - newTime4) / OldTimeStep);
// all new points lie between (oldVals[0] and oldVals[1])
Real64 delta10 = (oldVals[1] - oldVals[0]) / DSRatio;
newVals[1] = oldVals[0] + delta10;
newVals[2] = newVals[1] + delta10;
newVals[3] = newVals[2] + delta10;
}
return oldVals[0];

// if (std::abs(DSRatio - 2.0) < 0.01) { // DSRatio = 2
// // first two points lie between oldVals[0] and oldVals[1]
// Real64 ratio10 = (oldVals[1] - oldVals[0]) / OldTimeStep;
// newVals[0] = oldVals[0] + ratio10 * (oldTime0 - newTime1);
// newVals[1] = oldVals[0] + ratio10 * (oldTime0 - newTime2);
// // last two points lie between oldVals[1] and oldVals[2]
// Real64 ratio21 = (oldVals[2] - oldVals[1]) / OldTimeStep;
// newVals[2] = oldVals[1] + ratio21 * (oldTime1 - newTime3);
// newVals[3] = oldVals[1] + ratio21 * (oldTime1 - newTime4);
// } else if (std::abs(DSRatio - 3.0) < 0.01) { // DSRatio = 3
// // first three points lie between oldVals[0] and oldVals[1]
// Real64 ratio10 = (oldVals[1] - oldVals[0]) / OldTimeStep;
// newVals[0] = oldVals[0] + ratio10 * (oldTime0 - newTime1);
// newVals[1] = oldVals[0] + ratio10 * (oldTime0 - newTime2);
// newVals[2] = oldVals[0] + ratio10 * (oldTime0 - newTime3);
// // last point lie between oldVals[1] and oldVals[2]
// Real64 ratio21 = (oldVals[2] - oldVals[1]) / OldTimeStep;
// newVals[3] = oldVals[1] + ratio21 * (oldTime1 - newTime4);

//} else { // DSRatio = 4 or more
// // all new points lie between oldVals[0] and oldVals[1]
// Real64 ratio10 = (oldVals[1] - oldVals[0]) / OldTimeStep;
// newVals[0] = oldVals[0] + ratio10 * (oldTime0 - newTime1);
// newVals[1] = oldVals[0] + ratio10 * (oldTime0 - newTime2);
// newVals[2] = oldVals[0] + ratio10 * (oldTime0 - newTime3);
// newVals[3] = oldVals[0] + ratio10 * (oldTime0 - newTime4);
//}
}
void InverseModelTemperature(EnergyPlusData &state,
int const ZoneNum, // Zone number
Expand Down
18 changes: 9 additions & 9 deletions tst/EnergyPlus/unit/UnitarySystem.unit.cc
Original file line number Diff line number Diff line change
Expand Up @@ -23684,7 +23684,7 @@ TEST_F(EnergyPlusFixture, UnitarySystemModel_MultiSpeedFanWSHP_Test)
latOut);
// first speed heating
EXPECT_NEAR(thisSys.m_SpeedRatio, 0.0, 0.0001);
EXPECT_NEAR(thisSys.m_CycRatio, 0.81485929, 0.0001);
EXPECT_NEAR(thisSys.m_CycRatio, 0.81485980, 0.0001);
EXPECT_EQ(thisSys.m_SpeedNum, 1);
EXPECT_NEAR(sensOut, 2000.0, 0.5);

Expand All @@ -23703,7 +23703,7 @@ TEST_F(EnergyPlusFixture, UnitarySystemModel_MultiSpeedFanWSHP_Test)
ZoneEquipment,
sensOut,
latOut);
EXPECT_NEAR(thisSys.m_SpeedRatio, 0.691837, 0.0001);
EXPECT_NEAR(thisSys.m_SpeedRatio, 0.691942, 0.0001);
EXPECT_NEAR(thisSys.m_CycRatio, 1.0, 0.0001);
EXPECT_EQ(thisSys.m_SpeedNum, 2);
EXPECT_NEAR(sensOut, 3000.0, 2);
Expand All @@ -23728,7 +23728,7 @@ TEST_F(EnergyPlusFixture, UnitarySystemModel_MultiSpeedFanWSHP_Test)
sensOut,
latOut);
EXPECT_NEAR(thisSys.m_SpeedRatio, 0.0, 0.0001);
EXPECT_NEAR(thisSys.m_CycRatio, 0.801813, 0.0001);
EXPECT_NEAR(thisSys.m_CycRatio, 0.809727, 0.0001);
EXPECT_EQ(thisSys.m_SpeedNum, 1);
EXPECT_NEAR(sensOut, -800.0, 2);
state->dataZoneEnergyDemand->ZoneSysEnergyDemand[0].RemainingOutputRequired = -1500.0;
Expand All @@ -23747,10 +23747,10 @@ TEST_F(EnergyPlusFixture, UnitarySystemModel_MultiSpeedFanWSHP_Test)
ZoneEquipment,
sensOut,
latOut);
EXPECT_NEAR(thisSys.m_SpeedRatio, 0.27708, 0.0001);
EXPECT_NEAR(thisSys.m_SpeedRatio, 0.27929, 0.0001);
EXPECT_NEAR(thisSys.m_CycRatio, 1.0, 0.0001);
EXPECT_EQ(thisSys.m_SpeedNum, 2);
EXPECT_NEAR(sensOut, -1500.0, 2);
EXPECT_NEAR(sensOut, -1501.3, 2);

// Variable speed water coil
state->dataZoneEnergyDemand->ZoneSysEnergyDemand[1].RemainingOutputRequired = -100.0;
Expand All @@ -23774,7 +23774,7 @@ TEST_F(EnergyPlusFixture, UnitarySystemModel_MultiSpeedFanWSHP_Test)
latOut);
// first speed cooling
EXPECT_NEAR(thisSys1.m_SpeedRatio, 0.0, 0.0001);
EXPECT_NEAR(thisSys1.m_CycRatio, 0.507924, 0.0001);
EXPECT_NEAR(thisSys1.m_CycRatio, 0.510465, 0.0001);
EXPECT_EQ(thisSys1.m_SpeedNum, 1);
EXPECT_NEAR(sensOut, -100.0, 2);

Expand All @@ -23794,7 +23794,7 @@ TEST_F(EnergyPlusFixture, UnitarySystemModel_MultiSpeedFanWSHP_Test)
sensOut,
latOut);
// Sixth speed cooling
EXPECT_NEAR(thisSys1.m_SpeedRatio, 0.361666, 0.0001);
EXPECT_NEAR(thisSys1.m_SpeedRatio, 0.392999, 0.0001);
EXPECT_NEAR(thisSys1.m_CycRatio, 1.0, 0.0001);
EXPECT_EQ(thisSys1.m_SpeedNum, 6);
EXPECT_NEAR(sensOut, -500.0, 2);
Expand All @@ -23820,7 +23820,7 @@ TEST_F(EnergyPlusFixture, UnitarySystemModel_MultiSpeedFanWSHP_Test)
latOut);
// First speed heating
EXPECT_NEAR(thisSys1.m_SpeedRatio, 0.0, 0.0001);
EXPECT_NEAR(thisSys1.m_CycRatio, 0.244636, 0.0001);
EXPECT_NEAR(thisSys1.m_CycRatio, 0.245589, 0.0001);
EXPECT_EQ(thisSys1.m_SpeedNum, 1);
EXPECT_NEAR(sensOut, 100.0, 2);
state->dataZoneEnergyDemand->ZoneSysEnergyDemand[1].RemainingOutputRequired = 500.0;
Expand All @@ -23839,7 +23839,7 @@ TEST_F(EnergyPlusFixture, UnitarySystemModel_MultiSpeedFanWSHP_Test)
sensOut,
latOut);
// Second speed heating
EXPECT_NEAR(thisSys1.m_SpeedRatio, 0.926240, 0.0001);
EXPECT_NEAR(thisSys1.m_SpeedRatio, 0.945581, 0.0001);
EXPECT_NEAR(thisSys1.m_CycRatio, 1.0, 0.0001);
EXPECT_EQ(thisSys1.m_SpeedNum, 2);
EXPECT_NEAR(sensOut, 500.0, 2);
Expand Down
13 changes: 13 additions & 0 deletions tst/EnergyPlus/unit/ZoneTempPredictorCorrector.unit.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1682,4 +1682,17 @@ TEST_F(EnergyPlusFixture, DownInterpolate4HistoryValues_Test)
EXPECT_NEAR(DSHistoryValue2, 2.0, 0.000001);
EXPECT_NEAR(DSHistoryValue3, 2.5, 0.000001);
EXPECT_NEAR(DSHistoryValue4, 3.0, 0.000001);

std::array<Real64, 4> newValue = {0.0, 0.0, 0.0, 0.0};
std::array<Real64, 4> oldValue = {DSHistoryValue1, DSHistoryValue2, DSHistoryValue3, DSHistoryValue4};
Real64 returnValue = DownInterpolate4HistoryValues(PriorTimeStep, state->dataHVACGlobal->TimeStepSys, oldValue, newValue);
EXPECT_NEAR(returnValue, oldValue[0], 0.000001); // setting up history terms for shortened time step simulation
EXPECT_NEAR(newValue[0], 1.5, 0.000001); // values are interpolated to provide history terms at the new time step
EXPECT_NEAR(newValue[1], 1.75, 0.000001);
EXPECT_NEAR(newValue[2], 2.0, 0.000001);
EXPECT_NEAR(newValue[3], 2.25, 0.000001);
EXPECT_NEAR(oldValue[0], DSHistoryValue1, 0.000001); // values are same as before
EXPECT_NEAR(oldValue[1], DSHistoryValue2, 0.000001);
EXPECT_NEAR(oldValue[2], DSHistoryValue3, 0.000001);
EXPECT_NEAR(oldValue[3], DSHistoryValue4, 0.000001);
}

12 comments on commit 0c0cdaa

@nrel-bot-2b
Copy link

Choose a reason for hiding this comment

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

develop (Myoldmopar) - x86_64-Linux-Ubuntu-22.04-gcc-11.4: OK (2780 of 2780 tests passed, 0 test warnings)

Build Badge Test Badge

@nrel-bot-3
Copy link

Choose a reason for hiding this comment

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

develop (Myoldmopar) - x86_64-MacOS-10.17-clang-14.0.0: OK (2759 of 2759 tests passed, 0 test warnings)

Build Badge Test Badge

@nrel-bot
Copy link

Choose a reason for hiding this comment

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

develop (Myoldmopar) - Win64-Windows-10-VisualStudio-16: OK (2758 of 2758 tests passed, 0 test warnings)

Build Badge Test Badge

@nrel-bot-2c
Copy link

Choose a reason for hiding this comment

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

develop (Myoldmopar) - x86_64-Linux-Ubuntu-22.04-gcc-11.4-IntegrationCoverage-Debug: OK (790 of 790 tests passed, 0 test warnings)

Build Badge Test Badge Coverage Badge

@nrel-bot-2
Copy link

Choose a reason for hiding this comment

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

develop (Myoldmopar) - x86_64-Linux-Ubuntu-22.04-gcc-11.4-UnitTestsCoverage-Debug: OK (1971 of 1971 tests passed, 0 test warnings)

Build Badge Test Badge Coverage Badge

@nrel-bot-2b
Copy link

Choose a reason for hiding this comment

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

10204-Add-more-object-types (Myoldmopar) - x86_64-Linux-Ubuntu-22.04-gcc-11.4: OK (3586 of 3586 tests passed, 0 test warnings)

Build Badge Test Badge

@nrel-bot
Copy link

Choose a reason for hiding this comment

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

10204-Add-more-object-types (Myoldmopar) - Win64-Windows-10-VisualStudio-16: OK (2758 of 2758 tests passed, 0 test warnings)

Build Badge Test Badge

@nrel-bot-2c
Copy link

Choose a reason for hiding this comment

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

10204-Add-more-object-types (Myoldmopar) - x86_64-Linux-Ubuntu-22.04-gcc-11.4-UnitTestsCoverage-Debug: OK (1971 of 1971 tests passed, 0 test warnings)

Build Badge Test Badge Coverage Badge

@nrel-bot-3
Copy link

Choose a reason for hiding this comment

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

10204-Add-more-object-types (Myoldmopar) - x86_64-MacOS-10.17-clang-14.0.0: OK (3545 of 3545 tests passed, 0 test warnings)

Build Badge Test Badge

@nrel-bot-2b
Copy link

Choose a reason for hiding this comment

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

10204-Add-more-object-types (Myoldmopar) - x86_64-Linux-Ubuntu-22.04-gcc-11.4-IntegrationCoverage-Debug: OK (790 of 790 tests passed, 0 test warnings)

Build Badge Test Badge Coverage Badge

@nrel-bot-3
Copy link

Choose a reason for hiding this comment

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

10204-Add-more-object-types (Myoldmopar) - x86_64-MacOS-10.18-clang-15.0.0: OK (3544 of 3545 tests passed, 0 test warnings)

Build Badge Test Badge

@nrel-bot-3
Copy link

Choose a reason for hiding this comment

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

develop (Myoldmopar) - x86_64-MacOS-10.18-clang-15.0.0: OK (2758 of 2759 tests passed, 0 test warnings)

Build Badge Test Badge

Please sign in to comment.