Skip to content

Commit

Permalink
Eval first-hour rating.
Browse files Browse the repository at this point in the history
  • Loading branch information
Phil Ahrenkiel authored and Phil Ahrenkiel committed Jan 8, 2024
1 parent 6d38643 commit 8a1c251
Show file tree
Hide file tree
Showing 3 changed files with 240 additions and 47 deletions.
203 changes: 180 additions & 23 deletions src/HPWH.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5400,30 +5400,186 @@ int HPWH::HPWHinit_file(string configFile)
}
#endif

HPWH::Usage HPWH::findUsageFromFirstHourRating() { return Usage::Medium; }

HPWH::Usage HPWH::findUsageFromMaximumGPM_Rating()
bool HPWH::findUsageFromFirstHourRating(HPWH::Usage& usage, const double setpointT_C /* = 51.7 */)
{
// Assume flow rate unlimited for heat-exchange models
if (hasHeatExchanger)
double flowRate_Lper_min = GAL_TO_L(3.);
if (tankVolume_L < GAL_TO_L(20.))
flowRate_Lper_min = GAL_TO_L(1.5);

constexpr double inletT_C = 14.4; // p. 40433
constexpr double ambientT_C = 19.7; // p. 40435
constexpr double externalT_C = 19.7;
constexpr DRMODES drMode = DR_ALLOW;
if (!isSetpointFixed())
{
if (setSetpoint(setpointT_C, UNITS_C) == HPWH_ABORT)
{
return false;
}
}

double maxT_C = getTankTemp_C();
double prevMinT_C = getTankTemp_C();
double tolT_C = dF_TO_dC(0.); // tolerance

double drawVolume_L = 0.;
double lastPassDrawVolume_L = 0.;
int testTime_min = 0;
int drawOnTime = 0;
int prevDrawOffTime_min = 0;
bool heatersAreOn = false;
bool isDrawing = false;
bool testIsRunning = true;
int testStage = 1;
bool lastDrawSucceeded = false;
while (testIsRunning)
{
heatersAreOn = false;
for (auto& heatSource : heatSources)
{
heatersAreOn |= heatSource.isEngaged();
}
double tankT_C = getTankTemp_C();

switch (testStage)
{
case 1:
{
if (!heatersAreOn)
{
isDrawing = true;
drawOnTime = testTime_min;
testStage = 2;
}
break;
}

case 2:
{
if (heatersAreOn)
{
isDrawing = false;
prevDrawOffTime_min = testTime_min;
maxT_C = tankT_C;
testStage = 3;
}
break;
}

case 3:
{
if (isDrawing)
{
double targetT_C = maxT_C - dF_TO_dC(15.) - tolT_C;
if (outletTemp_C < targetT_C) // outletT has dropped by 15 degF below max T
{
prevMinT_C = outletTemp_C;
maxT_C = tankT_C; // initialize for next pass
isDrawing = false;
prevDrawOffTime_min = testTime_min;
}
}
else
{
if (tankT_C > maxT_C) // has not reached max T
{
maxT_C = tankT_C + tolT_C;
if (testTime_min >= 60) // start a final draw
{
isDrawing = true;
drawOnTime = testTime_min;
testStage = 4;
}
}
else {
if (testTime_min >= 60)
{
testIsRunning = false;
}
else
{
isDrawing = true;
drawOnTime = testTime_min;
}
}
}
break;
}

case 4:
{
if (testTime_min > drawOnTime)
{
if (outletTemp_C > prevMinT_C - tolT_C)
{
lastDrawSucceeded = true;
}
}
if (outletTemp_C <= prevMinT_C + tolT_C)
{
testIsRunning = false;
}
}
}

// limit draw-volume increment to tank volume
double incrementalDrawVolume_L = isDrawing ? flowRate_Lper_min * (1.) : 0.;
if (incrementalDrawVolume_L > tankVolume_L)
{
incrementalDrawVolume_L = tankVolume_L;
}

if (runOneStep(inletT_C, // inlet water temperature (C)
incrementalDrawVolume_L, // draw volume (L)
ambientT_C, // ambient Temp (C)
externalT_C, // external Temp (C)
drMode, // DDR Status
0., // inlet-2 volume (L)
inletT_C, // inlet-2 Temp (C)
NULL) // no extra heat
== HPWH_ABORT)
{
return false;
}

// std::cout << preTime_min << ": " << getTankTemp_C() << ", " << (heatersAreOn? "On":
// "Off") << "\n";
if (testStage == 4)
{
lastPassDrawVolume_L += incrementalDrawVolume_L;
}
else
{
drawVolume_L += incrementalDrawVolume_L;
}

++testTime_min;
}

if (lastDrawSucceeded)
{
return Usage::High;
drawVolume_L += lastPassDrawVolume_L;
}

// Assume max. flow rate = tankVolume / (1 min)
else if (tankVolume_L < L_TO_GAL(1.7))
//
if (drawVolume_L < GAL_TO_L(18.))
{
return Usage::VerySmall;
usage = Usage::VerySmall;
}
else if (tankVolume_L < L_TO_GAL(2.8))
else if (drawVolume_L < GAL_TO_L(51.))
{
return Usage::Low;
usage = Usage::Low;
}
else if (tankVolume_L < L_TO_GAL(4.))
else if (drawVolume_L < GAL_TO_L(75.))
{
return Usage::Medium;
usage = Usage::Medium;
}
return Usage::High;
else
{
usage = Usage::High;
}

return true;
}

//-----------------------------------------------------------------------------
Expand All @@ -5433,7 +5589,9 @@ HPWH::Usage HPWH::findUsageFromMaximumGPM_Rating()
/// @param[out] UEF Result of calculation
/// @return true (success), false (failure).
//-----------------------------------------------------------------------------
bool HPWH::runDailyTest(const Usage usage, DailyTestSummary& dailyTestSummary)
bool HPWH::runDailyTest(const Usage usage,
DailyTestSummary& dailyTestSummary,
const double setpointT_C /* = 51.7 */)
{
// select the draw pattern based on usage
DrawPattern* drawPattern = nullptr;
Expand Down Expand Up @@ -5465,21 +5623,18 @@ bool HPWH::runDailyTest(const Usage usage, DailyTestSummary& dailyTestSummary)
return false;
}

const double inletT_C = 14.4; // p. 40433
const double ambientT_C = 19.7; // p. 40435
const double externalT_C = 19.7;
const DRMODES drMode = DR_ALLOW;
constexpr double inletT_C = 14.4; // p. 40433
constexpr double ambientT_C = 19.7; // p. 40435
constexpr double externalT_C = 19.7;
constexpr DRMODES drMode = DR_ALLOW;

/*
constexpr double setpointT_C = 51.7; //
if (!isSetpointFixed())
{
if (setSetpoint(setpointT_C, UNITS_C) == HPWH_ABORT)
{
return false;
}
}
*/

int preTime_min = 0;
bool heatersAreOn = false;
Expand Down Expand Up @@ -5523,6 +5678,7 @@ bool HPWH::runDailyTest(const Usage usage, DailyTestSummary& dailyTestSummary)
bool isFirstRecoveryPeriod = true;
double firstRecoveryUsedEnergy_kJ = 0.;
double recoveryHeatingEnergy_kJ = 0.;
bool hasHeated = false;

int runTime_min = 0;
for (auto& draw : *drawPattern)
Expand Down Expand Up @@ -5602,7 +5758,8 @@ bool HPWH::runDailyTest(const Usage usage, DailyTestSummary& dailyTestSummary)
{
heatersAreOn |= heatSource.isEngaged();
}
if (!heatersAreOn)
hasHeated |= heatersAreOn;
if (hasHeated && (!heatersAreOn))
{
isFirstRecoveryPeriod = false;

Expand Down
7 changes: 2 additions & 5 deletions src/HPWH.hh
Original file line number Diff line number Diff line change
Expand Up @@ -957,10 +957,7 @@ class HPWH
};

/// Determine usage using the first-hour rating method
Usage findUsageFromFirstHourRating();

/// Determine usage using the maximum GPM rating method
Usage findUsageFromMaximumGPM_Rating();
bool findUsageFromFirstHourRating(HPWH::Usage &usage,const double setpointT_C = 51.7);

struct DailyTestSummary
{
Expand All @@ -976,7 +973,7 @@ class HPWH
};

/// run 24-hr draw pattern
bool runDailyTest(const Usage usage, DailyTestSummary& dailyTestSummary);
bool runDailyTest(const Usage usage, DailyTestSummary& dailyTestSummary, const double setpointT_C = 51.7);

struct Draw
{
Expand Down
77 changes: 58 additions & 19 deletions test/testCalcUEF.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
#include <string>

/* Evaluate UEF based on simulations using standard profiles */
static bool testCalcMetrics(const std::string& sModelName, HPWH::DailyTestSummary& dailyTestSummary)
static bool testCalcMetrics(const std::string& sModelName,
HPWH::Usage& usage,
HPWH::DailyTestSummary& dailyTestSummary)
{
HPWH hpwh;

Expand All @@ -17,11 +19,16 @@ static bool testCalcMetrics(const std::string& sModelName, HPWH::DailyTestSummar
return false;
}

return hpwh.runDailyTest(hpwh.findUsageFromMaximumGPM_Rating(), dailyTestSummary);
if (!hpwh.findUsageFromFirstHourRating(usage))
return false;

return hpwh.runDailyTest(usage, dailyTestSummary);
}

int main(int argc, char* argv[])
{
HPWH::Usage usage;
HPWH::DailyTestSummary dailyTestSummary;
bool validNumArgs = false;
bool runUnitTests = false;

Expand All @@ -48,13 +55,13 @@ int main(int argc, char* argv[])

if (runUnitTests)
{
HPWH::DailyTestSummary dailyTestSummary;
ASSERTTRUE(testCalcMetrics("AquaThermAire", usage, dailyTestSummary));
ASSERTTRUE(usage == HPWH::Usage::High);
ASSERTTRUE(cmpd(dailyTestSummary.UEF, 3.2797));

ASSERTTRUE(testCalcMetrics("AquaThermAire", dailyTestSummary));
ASSERTTRUE(cmpd(dailyTestSummary.UEF, 2.8258));

ASSERTTRUE(testCalcMetrics("AOSmithHPTS50", dailyTestSummary));
ASSERTTRUE(cmpd(dailyTestSummary.UEF, 4.8021));
ASSERTTRUE(testCalcMetrics("AOSmithHPTS50", usage, dailyTestSummary));
ASSERTTRUE(usage == HPWH::Usage::Medium);
ASSERTTRUE(cmpd(dailyTestSummary.UEF, 4.8246));

return 0;
}
Expand Down Expand Up @@ -104,21 +111,53 @@ int main(int argc, char* argv[])
std::cout << "Spec type: " << sPresetOrFile << "\n";
std::cout << "Model name: " << sModelName << "\n";

HPWH::DailyTestSummary dailyTestSummary;
if (hpwh.runDailyTest(hpwh.findUsageFromMaximumGPM_Rating(), dailyTestSummary))
if (hpwh.findUsageFromFirstHourRating(usage))
{
std::cout << "\tRecovery Efficiency: " << dailyTestSummary.recoveryEfficiency << "\n";
std::cout << "\tAdjusted Daily Water Heating Energy Consumption (kJ): "
<< dailyTestSummary.adjustedDailyWaterHeatingEnergyConsumption_kJ << "\n";
std::cout << "\tUEF: " << dailyTestSummary.UEF << "\n";
std::cout << "\tAnnual Electrical Energy Consumption (kJ): "
<< dailyTestSummary.annualElectricalEnergyConsumption_kJ << "\n";
std::cout << "\tAnnual Energy Consumption (kJ): "
<< dailyTestSummary.annualEnergyConsumption_kJ << "\n";
std::string sUsage = "";
switch (usage)
{
case HPWH::Usage::VerySmall:
{
sUsage = "Very Small";
break;
}
case HPWH::Usage::Low:
{
sUsage = "Low";
break;
}
case HPWH::Usage::Medium:
{
sUsage = "Medium";
break;
}
case HPWH::Usage::High:
{
sUsage = "High";
break;
}
}
std::cout << "\tUsage: " << sUsage << "\n";

if (hpwh.runDailyTest(usage, dailyTestSummary))
{
std::cout << "\tRecovery Efficiency: " << dailyTestSummary.recoveryEfficiency << "\n";
std::cout << "\tUEF: " << dailyTestSummary.UEF << "\n";
std::cout << "\tAdjusted Daily Water Heating Energy Consumption (kWh): "
<< KJ_TO_KWH(dailyTestSummary.adjustedDailyWaterHeatingEnergyConsumption_kJ) << "\n";
std::cout << "\tAnnual Electrical Energy Consumption (kWh): "
<< KJ_TO_KWH(dailyTestSummary.annualElectricalEnergyConsumption_kJ) << "\n";
std::cout << "\tAnnual Energy Consumption (kWh): "
<< KJ_TO_KWH(dailyTestSummary.annualEnergyConsumption_kJ) << "\n";
}
else
{
std::cout << "Unable to determine efficiency metrics.\n";
}
}
else
{
std::cout << "Unable to determine efficiency metrics.\n";
std::cout << "Unable to determine first-hour rating.\n";
}

return 0;
Expand Down

0 comments on commit 8a1c251

Please sign in to comment.