diff --git a/CMakeLists.txt b/CMakeLists.txt index 49f3fa63..397ff9c5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,7 +46,7 @@ add_subdirectory(vendor) add_subdirectory(src) if (${PROJECT_NAME}_BUILD_TESTING) - add_subdirectory(test) + add_subdirectory(test) if (${PROJECT_NAME}_COVERAGE) coverage_evaluate() endif () diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 813e0481..3f342139 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -32,36 +32,36 @@ set(library_sources option(${PROJECT_NAME}_STATIC_LIB "Make ${PROJECT_NAME} a static library" ON) if (${PROJECT_NAME}_STATIC_LIB) - add_library(libHPWHsim STATIC ${library_sources}) # TODO: Change name to ${PROJECT_NAME} - set_target_properties(libHPWHsim PROPERTIES COMPILE_FLAGS "-D${PROJECT_NAME}_STATIC_DEFINE") + add_library(${PROJECT_NAME} STATIC ${library_sources}) # TODO: Change name to ${PROJECT_NAME} + set_target_properties(${PROJECT_NAME} PROPERTIES COMPILE_FLAGS "-D${PROJECT_NAME}_STATIC_DEFINE") else () set(CMAKE_MACOSX_RPATH 1) - add_library(libHPWHsim SHARED ${library_sources}) + add_library(${PROJECT_NAME} SHARED ${library_sources}) endif () -target_include_directories(libHPWHsim PUBLIC ${PROJECT_SOURCE_DIR}/src ${PROJECT_BINARY_DIR}/src) +target_include_directories(${PROJECT_NAME} PUBLIC ${PROJECT_BINARY_DIR}/src ${PROJECT_SOURCE_DIR}/src) -target_link_libraries(libHPWHsim PRIVATE ${PROJECT_NAME}_common_interface PUBLIC btwxt) -target_compile_features(libHPWHsim PRIVATE cxx_std_17) +target_link_libraries(${PROJECT_NAME} PRIVATE ${PROJECT_NAME}_common_interface PUBLIC btwxt) +target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_17) include(GenerateExportHeader) -generate_export_header(libHPWHsim) +generate_export_header(${PROJECT_NAME}) -add_dependencies(libHPWHsim ${PROJECT_NAME}_version_header) +add_dependencies(${PROJECT_NAME} ${PROJECT_NAME}_version_header) -set_target_properties(libHPWHsim PROPERTIES OUTPUT_NAME HPWHsim) -set_target_properties(libHPWHsim PROPERTIES PDB_NAME libHPWHsim) +set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME ${PROJECT_NAME}) +set_target_properties(${PROJECT_NAME} PROPERTIES PDB_NAME ${PROJECT_NAME}) # If MSVC_RUNTIME_LIBRARY is not by a parent project use the default. # It's not clear why this is needed, since documentation indicates it # should be happening with the CMP0091 policy set to NEW. -get_target_property(RTL libHPWHsim MSVC_RUNTIME_LIBRARY) +get_target_property(RTL ${PROJECT_NAME} MSVC_RUNTIME_LIBRARY) if ("${RTL}" STREQUAL "RTL-NOTFOUND") - set_target_properties(libHPWHsim PROPERTIES MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>DLL") + set_target_properties(${PROJECT_NAME} PROPERTIES MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>DLL") endif () if (${PROJECT_NAME}_COVERAGE) - add_coverage(libHPWHsim) + add_coverage(${PROJECT_NAME}) endif () diff --git a/src/HPWH.cc b/src/HPWH.cc index 410c3802..92a8c375 100644 --- a/src/HPWH.cc +++ b/src/HPWH.cc @@ -65,6 +65,8 @@ const double HPWH::MAXOUTLET_R410A = F_TO_C(140.); const double HPWH::MAXOUTLET_R744 = F_TO_C(190.); const double HPWH::MINSINGLEPASSLIFT = dF_TO_dC(15.); +const int HPWH::HPWH_ABORT = -274000; + //----------------------------------------------------------------------------- /// @brief Samples a std::vector to extract a single value spanning the fractional /// coordinate range from frac_begin to frac_end. @@ -315,6 +317,22 @@ void calcThermalDist(std::vector& thermalDist, } } +//----------------------------------------------------------------------------- +/// @brief Scales all values of a std::vector by a common factor. +/// @param[in/out] coeffs values to be scaled +/// @param[in] scaleFactor scaling factor +//----------------------------------------------------------------------------- +void scaleVector(std::vector& coeffs, const double scaleFactor) +{ + if (scaleFactor != 1.) + { + std::transform(coeffs.begin(), + coeffs.end(), + coeffs.begin(), + std::bind(std::multiplies(), std::placeholders::_1, scaleFactor)); + } +} + void HPWH::setMinutesPerStep(const double minutesPerStep_in) { minutesPerStep = minutesPerStep_in; @@ -1343,7 +1361,7 @@ bool HPWH::isNewSetpointPossible(double newSetpoint, } else if (lowestElementIndex == -1 && !hasACompressor()) { // There are no heat sources here! - if (hpwhModel == MODELS_StorageTank) + if (model == MODELS_StorageTank) { returnVal = true; // The one pass the storage tank doesn't have any heating elements // so sure change the setpoint it does nothing! @@ -2193,7 +2211,7 @@ std::shared_ptr HPWH::shutOffSoC(string desc, //----------------------------------------------------------------------------- /// @brief Builds a vector of logic node weights referred to a fixed number of -/// nodes given by LOGIC_NODE_SIZE. +/// nodes given by LOGIC_SIZE. /// @param[in] bottomFraction Lower bounding fraction (0 to 1) /// @param[in] topFraction Upper bounding fraction (0 to 1) /// @return vector of node weights @@ -2203,8 +2221,8 @@ std::vector HPWH::getNodeWeightRange(double bottomFraction, do std::vector nodeWeights; if (topFraction < bottomFraction) std::swap(bottomFraction, topFraction); - auto bottomIndex = static_cast(bottomFraction * LOGIC_NODE_SIZE); - auto topIndex = static_cast(topFraction * LOGIC_NODE_SIZE); + auto bottomIndex = static_cast(bottomFraction * LOGIC_SIZE); + auto topIndex = static_cast(topFraction * LOGIC_SIZE); for (auto index = bottomIndex; index < topIndex; ++index) { nodeWeights.emplace_back(static_cast(index) + 1); @@ -2319,7 +2337,7 @@ std::shared_ptr HPWH::bottomTwelfth(double decision std::shared_ptr HPWH::standby(double decisionPoint) { std::vector nodeWeights; - nodeWeights.emplace_back(LOGIC_NODE_SIZE + 1); // uses very top computation node + nodeWeights.emplace_back(LOGIC_SIZE + 1); // uses very top computation node return std::make_shared( "standby", nodeWeights, decisionPoint, this); } @@ -2327,7 +2345,7 @@ std::shared_ptr HPWH::standby(double decisionPoint) std::shared_ptr HPWH::topNodeMaxTemp(double decisionPoint) { std::vector nodeWeights; - nodeWeights.emplace_back(LOGIC_NODE_SIZE + 1); // uses very top computation node + nodeWeights.emplace_back(LOGIC_SIZE + 1); // uses very top computation node return std::make_shared( "top node", nodeWeights, decisionPoint, this, true, std::greater()); } @@ -2690,6 +2708,8 @@ int HPWH::isNthHeatSourceRunning(int N) const } } +int HPWH::isCompressorRunning() const { return isNthHeatSourceRunning(getCompressorIndex()); } + HPWH::HEATSOURCE_TYPE HPWH::getNthHeatSourceType(int N) const { if (N >= getNumHeatSources() || N < 0) @@ -2868,7 +2888,8 @@ double HPWH::getTankHeatContent_kJ() const double HPWH::getLocationTemp_C() const { return locationTemperature_C; } -int HPWH::getHPWHModel() const { return hpwhModel; } +int HPWH::getModel() const { return model; } + int HPWH::getCompressorCoilConfig() const { if (!hasACompressor()) @@ -2881,7 +2902,8 @@ int HPWH::getCompressorCoilConfig() const } return heatSources[compressorIndex].configuration; } -bool HPWH::isCompressorMultipass() const + +int HPWH::isCompressorMultipass() const { if (!hasACompressor()) { @@ -2891,9 +2913,10 @@ bool HPWH::isCompressorMultipass() const } return HPWH_ABORT; } - return heatSources[compressorIndex].isMultipass; + return static_cast(heatSources[compressorIndex].isMultipass); } -bool HPWH::isCompressoExternalMultipass() const + +int HPWH::isCompressorExternalMultipass() const { if (!hasACompressor()) { @@ -2903,7 +2926,7 @@ bool HPWH::isCompressoExternalMultipass() const } return HPWH_ABORT; } - return heatSources[compressorIndex].isExternalMultipass(); + return static_cast(heatSources[compressorIndex].isExternalMultipass()); } bool HPWH::hasACompressor() const { return compressorIndex >= 0; } @@ -2922,7 +2945,7 @@ bool HPWH::hasExternalHeatSource() const double HPWH::getExternalMPFlowRate(UNITS units /*=UNITS_GPM*/) const { - if (!isCompressoExternalMultipass()) + if (!isCompressorExternalMultipass()) { if (hpwhVerbosity >= VRB_reluctant) { @@ -3073,7 +3096,7 @@ int HPWH::getSizingFractions(double& aquaFract, double& useableFract) const bool HPWH::isHPWHScalable() const { return canScale; } -int HPWH::setScaleHPWHCapacityCOP(double scaleCapacity /*=1.0*/, double scaleCOP /*=1.0*/) +int HPWH::setScaleCapacityCOP(double scaleCapacity /*=1.0*/, double scaleCOP /*=1.0*/) { if (!isHPWHScalable()) { @@ -3102,21 +3125,8 @@ int HPWH::setScaleHPWHCapacityCOP(double scaleCapacity /*=1.0*/, double scaleCOP for (auto& perfP : heatSources[compressorIndex].perfMap) { - if (scaleCapacity != 1.) - { - std::transform( - perfP.inputPower_coeffs.begin(), - perfP.inputPower_coeffs.end(), - perfP.inputPower_coeffs.begin(), - std::bind(std::multiplies(), std::placeholders::_1, scaleCapacity)); - } - if (scaleCOP != 1.) - { - std::transform(perfP.COP_coeffs.begin(), - perfP.COP_coeffs.end(), - perfP.COP_coeffs.begin(), - std::bind(std::multiplies(), std::placeholders::_1, scaleCOP)); - } + scaleVector(perfP.inputPower_coeffs, scaleCapacity); + scaleVector(perfP.COP_coeffs, scaleCOP); } return 0; @@ -3137,7 +3147,7 @@ int HPWH::setCompressorOutputCapacity(double newCapacity, } double scale = newCapacity / oldCapacity; - return setScaleHPWHCapacityCOP(scale, 1.); // Scale the compressor capacity + return setScaleCapacityCOP(scale, 1.); // Scale the compressor capacity } int HPWH::setResistanceCapacity(double power, int which /*=-1*/, UNITS pwrUnit /*=UNITS_KW*/) @@ -3834,7 +3844,7 @@ double HPWH::tankAvg_C(const std::vector nodeWeights) const double sum = 0; double totWeight = 0; - std::vector resampledTankTemps(LOGIC_NODE_SIZE); + std::vector resampledTankTemps(LOGIC_SIZE); resample(resampledTankTemps, tankTemps_C); for (auto& nodeWeight : nodeWeights) @@ -3844,7 +3854,7 @@ double HPWH::tankAvg_C(const std::vector nodeWeights) const sum += tankTemps_C.front() * nodeWeight.weight; totWeight += nodeWeight.weight; } - else if (nodeWeight.nodeNum > LOGIC_NODE_SIZE) + else if (nodeWeight.nodeNum > LOGIC_SIZE) { // top node only sum += tankTemps_C.back() * nodeWeight.weight; totWeight += nodeWeight.weight; @@ -4048,13 +4058,443 @@ void HPWH::mapResRelativePosToHeatSources() }); } +bool HPWH::shouldDRLockOut(HEATSOURCE_TYPE hs, DRMODES DR_signal) const +{ + + if (hs == TYPE_compressor && (DR_signal & DR_LOC) != 0) + { + return true; + } + else if (hs == TYPE_resistance && (DR_signal & DR_LOR) != 0) + { + return true; + } + return false; +} + +void HPWH::resetTopOffTimer() { timerTOT = 0.; } + +//----------------------------------------------------------------------------- +/// @brief Checks whether energy is balanced during a simulation step. +/// @note Used in test/main.cc +/// @param[in] drawVol_L Water volume drawn during simulation step +/// @param[in] prevHeatContent_kJ Heat content of tank prior to simulation step +/// @param[in] fracEnergyTolerance Fractional tolerance for energy imbalance +/// @return true if balanced; false otherwise. +//----------------------------------------------------------------------------- +bool HPWH::isEnergyBalanced(const double drawVol_L, + const double prevHeatContent_kJ, + const double fracEnergyTolerance /* = 0.001 */) +{ + double drawCp_kJperC = + CPWATER_kJperkgC * DENSITYWATER_kgperL * drawVol_L; // heat capacity of draw + + // Check energy balancing. + double qInElectrical_kJ = 0.; + for (int iHS = 0; iHS < getNumHeatSources(); iHS++) + { + qInElectrical_kJ += getNthHeatSourceEnergyInput(iHS, UNITS_KJ); + } + + double qInExtra_kJ = KWH_TO_KJ(extraEnergyInput_kWh); + double qInHeatSourceEnviron_kJ = getEnergyRemovedFromEnvironment(UNITS_KJ); + double qOutTankEnviron_kJ = KWH_TO_KJ(standbyLosses_kWh); + double qOutWater_kJ = + drawCp_kJperC * (outletTemp_C - member_inletT_C); // assumes only one inlet + double expectedTankHeatContent_kJ = + prevHeatContent_kJ // previous heat content + + qInElectrical_kJ // electrical energy delivered to heat sources + + qInExtra_kJ // extra energy delivered to heat sources + + qInHeatSourceEnviron_kJ // heat extracted from environment by condenser + - qOutTankEnviron_kJ // heat released from tank to environment + - qOutWater_kJ; // heat expelled to outlet by water flow + + double qBal_kJ = getTankHeatContent_kJ() - expectedTankHeatContent_kJ; + double fracEnergyDiff = fabs(qBal_kJ) / std::max(prevHeatContent_kJ, 1.); + if (fracEnergyDiff > fracEnergyTolerance) + { + if (hpwhVerbosity >= VRB_reluctant) + { + msg("Energy-balance error: %f kJ, %f %% \n", qBal_kJ, 100. * fracEnergyDiff); + } + return false; + } + return true; +} + +bool compressorIsRunning(HPWH& hpwh) +{ + return (bool)hpwh.isNthHeatSourceRunning(hpwh.getCompressorIndex()); +} + +/* static */ bool HPWH::mapNameToPreset(const std::string& modelName, HPWH::MODELS& model) +{ + if (modelName == "Voltex60" || modelName == "AOSmithPHPT60") + { + model = HPWH::MODELS_AOSmithPHPT60; + } + else if (modelName == "Voltex80" || modelName == "AOSmith80") + { + model = HPWH::MODELS_AOSmithPHPT80; + } + else if (modelName == "GEred" || modelName == "GE") + { + model = HPWH::MODELS_GE2012; + } + else if (modelName == "SandenGAU" || modelName == "Sanden80" || modelName == "SandenGen3") + { + model = HPWH::MODELS_Sanden80; + } + else if (modelName == "Sanden120") + { + model = HPWH::MODELS_Sanden120; + } + else if (modelName == "SandenGES" || modelName == "Sanden40") + { + model = HPWH::MODELS_Sanden40; + } + else if (modelName == "AOSmithHPTU50") + { + model = HPWH::MODELS_AOSmithHPTU50; + } + else if (modelName == "AOSmithHPTU66") + { + model = HPWH::MODELS_AOSmithHPTU66; + } + else if (modelName == "AOSmithHPTU80") + { + model = HPWH::MODELS_AOSmithHPTU80; + } + else if (modelName == "AOSmithHPTS50") + { + model = HPWH::MODELS_AOSmithHPTS50; + } + else if (modelName == "AOSmithHPTS66") + { + model = HPWH::MODELS_AOSmithHPTS66; + } + else if (modelName == "AOSmithHPTS80") + { + model = HPWH::MODELS_AOSmithHPTS80; + } + else if (modelName == "AOSmithHPTU80DR") + { + model = HPWH::MODELS_AOSmithHPTU80_DR; + } + else if (modelName == "GE502014STDMode" || modelName == "GE2014STDMode") + { + model = HPWH::MODELS_GE2014STDMode; + } + else if (modelName == "GE502014" || modelName == "GE2014") + { + model = HPWH::MODELS_GE2014; + } + else if (modelName == "GE802014") + { + model = HPWH::MODELS_GE2014_80DR; + } + else if (modelName == "RheemHB50") + { + model = HPWH::MODELS_RheemHB50; + } + else if (modelName == "Stiebel220e" || modelName == "Stiebel220E") + { + model = HPWH::MODELS_Stiebel220E; + } + else if (modelName == "Generic1") + { + model = HPWH::MODELS_Generic1; + } + else if (modelName == "Generic2") + { + model = HPWH::MODELS_Generic2; + } + else if (modelName == "Generic3") + { + model = HPWH::MODELS_Generic3; + } + else if (modelName == "custom") + { + model = HPWH::MODELS_CustomFile; + } + else if (modelName == "restankRealistic") + { + model = HPWH::MODELS_restankRealistic; + } + else if (modelName == "StorageTank") + { + model = HPWH::MODELS_StorageTank; + } + else if (modelName == "BWC2020_65") + { + model = HPWH::MODELS_BWC2020_65; + } + // New Rheems + else if (modelName == "Rheem2020Prem40") + { + model = HPWH::MODELS_Rheem2020Prem40; + } + else if (modelName == "Rheem2020Prem50") + { + model = HPWH::MODELS_Rheem2020Prem50; + } + else if (modelName == "Rheem2020Prem65") + { + model = HPWH::MODELS_Rheem2020Prem65; + } + else if (modelName == "Rheem2020Prem80") + { + model = HPWH::MODELS_Rheem2020Prem80; + } + else if (modelName == "Rheem2020Build40") + { + model = HPWH::MODELS_Rheem2020Build40; + } + else if (modelName == "Rheem2020Build50") + { + model = HPWH::MODELS_Rheem2020Build50; + } + else if (modelName == "Rheem2020Build65") + { + model = HPWH::MODELS_Rheem2020Build65; + } + else if (modelName == "Rheem2020Build80") + { + model = HPWH::MODELS_Rheem2020Build80; + } + else if (modelName == "RheemPlugInDedicated40") + { + model = HPWH::MODELS_RheemPlugInDedicated40; + } + else if (modelName == "RheemPlugInDedicated50") + { + model = HPWH::MODELS_RheemPlugInDedicated50; + } + else if (modelName == "RheemPlugInShared40") + { + model = HPWH::MODELS_RheemPlugInShared40; + } + else if (modelName == "RheemPlugInShared50") + { + model = HPWH::MODELS_RheemPlugInShared50; + } + else if (modelName == "RheemPlugInShared65") + { + model = HPWH::MODELS_RheemPlugInShared65; + } + else if (modelName == "RheemPlugInShared80") + { + model = HPWH::MODELS_RheemPlugInShared80; + } + // Large HPWH's + else if (modelName == "AOSmithCAHP120") + { + model = HPWH::MODELS_AOSmithCAHP120; + } + else if (modelName == "ColmacCxV_5_SP") + { + model = HPWH::MODELS_ColmacCxV_5_SP; + } + else if (modelName == "ColmacCxA_10_SP") + { + model = HPWH::MODELS_ColmacCxA_10_SP; + } + else if (modelName == "ColmacCxA_15_SP") + { + model = HPWH::MODELS_ColmacCxA_15_SP; + } + else if (modelName == "ColmacCxA_20_SP") + { + model = HPWH::MODELS_ColmacCxA_20_SP; + } + else if (modelName == "ColmacCxA_25_SP") + { + model = HPWH::MODELS_ColmacCxA_25_SP; + } + else if (modelName == "ColmacCxA_30_SP") + { + model = HPWH::MODELS_ColmacCxA_30_SP; + } + + else if (modelName == "ColmacCxV_5_MP") + { + model = HPWH::MODELS_ColmacCxV_5_MP; + } + else if (modelName == "ColmacCxA_10_MP") + { + model = HPWH::MODELS_ColmacCxA_10_MP; + } + else if (modelName == "ColmacCxA_15_MP") + { + model = HPWH::MODELS_ColmacCxA_15_MP; + } + else if (modelName == "ColmacCxA_20_MP") + { + model = HPWH::MODELS_ColmacCxA_20_MP; + } + else if (modelName == "ColmacCxA_25_MP") + { + model = HPWH::MODELS_ColmacCxA_25_MP; + } + else if (modelName == "ColmacCxA_30_MP") + { + model = HPWH::MODELS_ColmacCxA_30_MP; + } + + else if (modelName == "RheemHPHD60") + { + model = HPWH::MODELS_RHEEM_HPHD60VNU_201_MP; + } + else if (modelName == "RheemHPHD135") + { + model = HPWH::MODELS_RHEEM_HPHD135VNU_483_MP; + } + // Nyle Single pass models + else if (modelName == "NyleC25A_SP") + { + model = HPWH::MODELS_NyleC25A_SP; + } + else if (modelName == "NyleC60A_SP") + { + model = HPWH::MODELS_NyleC60A_SP; + } + else if (modelName == "NyleC90A_SP") + { + model = HPWH::MODELS_NyleC90A_SP; + } + else if (modelName == "NyleC185A_SP") + { + model = HPWH::MODELS_NyleC185A_SP; + } + else if (modelName == "NyleC250A_SP") + { + model = HPWH::MODELS_NyleC250A_SP; + } + else if (modelName == "NyleC60A_C_SP") + { + model = HPWH::MODELS_NyleC60A_C_SP; + } + else if (modelName == "NyleC90A_C_SP") + { + model = HPWH::MODELS_NyleC90A_C_SP; + } + else if (modelName == "NyleC185A_C_SP") + { + model = HPWH::MODELS_NyleC185A_C_SP; + } + else if (modelName == "NyleC250A_C_SP") + { + model = HPWH::MODELS_NyleC250A_C_SP; + } + // Nyle MP models + else if (modelName == "NyleC60A_MP") + { + model = HPWH::MODELS_NyleC60A_MP; + } + else if (modelName == "NyleC90A_MP") + { + model = HPWH::MODELS_NyleC90A_MP; + } + else if (modelName == "NyleC125A_MP") + { + model = HPWH::MODELS_NyleC125A_MP; + } + else if (modelName == "NyleC185A_MP") + { + model = HPWH::MODELS_NyleC185A_MP; + } + else if (modelName == "NyleC250A_MP") + { + model = HPWH::MODELS_NyleC250A_MP; + } + else if (modelName == "NyleC60A_C_MP") + { + model = HPWH::MODELS_NyleC60A_C_MP; + } + else if (modelName == "NyleC90A_C_MP") + { + model = HPWH::MODELS_NyleC90A_C_MP; + } + else if (modelName == "NyleC125A_C_MP") + { + model = HPWH::MODELS_NyleC125A_C_MP; + } + else if (modelName == "NyleC185A_C_MP") + { + model = HPWH::MODELS_NyleC185A_C_MP; + } + else if (modelName == "NyleC250A_C_MP") + { + model = HPWH::MODELS_NyleC250A_C_MP; + } + else if (modelName == "QAHV_N136TAU_HPB_SP") + { + model = HPWH::MODELS_MITSUBISHI_QAHV_N136TAU_HPB_SP; + } + // Stack in a couple scalable models + else if (modelName == "TamScalable_SP") + { + model = HPWH::MODELS_TamScalable_SP; + } + else if (modelName == "TamScalable_SP_2X") + { + model = HPWH::MODELS_TamScalable_SP_2X; + } + else if (modelName == "TamScalable_SP_Half") + { + model = HPWH::MODELS_TamScalable_SP_Half; + } + else if (modelName == "Scalable_MP") + { + model = HPWH::MODELS_Scalable_MP; + } + else if (modelName == "AWHSTier3Generic40") + { + model = HPWH::MODELS_AWHSTier3Generic40; + } + else if (modelName == "AWHSTier3Generic50") + { + model = HPWH::MODELS_AWHSTier3Generic50; + } + else if (modelName == "AWHSTier3Generic65") + { + model = HPWH::MODELS_AWHSTier3Generic65; + } + else if (modelName == "AWHSTier3Generic80") + { + model = HPWH::MODELS_AWHSTier3Generic80; + } + else if (modelName == "AquaThermAire") + { + model = HPWH::MODELS_AquaThermAire; + } + else + { + model = HPWH::MODELS_basicIntegrated; + cout << "Couldn't find model " << modelName << ". Exiting...\n"; + return false; + } + return true; +} + +/// Initializes a preset from the modelName +int HPWH::initPreset(const std::string& modelName) +{ + HPWH::MODELS targetModel; + if (mapNameToPreset(modelName, targetModel)) + { + return initPreset(targetModel); + } + return HPWH_ABORT; +} + // Used to check a few inputs after the initialization of a tank model from a preset or a file. int HPWH::checkInputs() { int returnVal = 0; // use a returnVal so that all checks are processed and error messages written - if (getNumHeatSources() <= 0 && hpwhModel != MODELS_StorageTank) + if (getNumHeatSources() <= 0 && model != MODELS_StorageTank) { if (hpwhVerbosity >= VRB_reluctant) { @@ -4323,74 +4763,9 @@ int HPWH::checkInputs() return returnVal; } -bool HPWH::shouldDRLockOut(HEATSOURCE_TYPE hs, DRMODES DR_signal) const -{ - - if (hs == TYPE_compressor && (DR_signal & DR_LOC) != 0) - { - return true; - } - else if (hs == TYPE_resistance && (DR_signal & DR_LOR) != 0) - { - return true; - } - return false; -} - -void HPWH::resetTopOffTimer() { timerTOT = 0.; } - -//----------------------------------------------------------------------------- -/// @brief Checks whether energy is balanced during a simulation step. -/// @note Used in test/main.cc -/// @param[in] drawVol_L Water volume drawn during simulation step -/// @param[in] prevHeatContent_kJ Heat content of tank prior to simulation step -/// @param[in] fracEnergyTolerance Fractional tolerance for energy imbalance -/// @return true if balanced; false otherwise. -//----------------------------------------------------------------------------- -bool HPWH::isEnergyBalanced(const double drawVol_L, - const double prevHeatContent_kJ, - const double fracEnergyTolerance /* = 0.001 */) -{ - double drawCp_kJperC = - CPWATER_kJperkgC * DENSITYWATER_kgperL * drawVol_L; // heat capacity of draw - - // Check energy balancing. - double qInElectrical_kJ = 0.; - for (int iHS = 0; iHS < getNumHeatSources(); iHS++) - { - qInElectrical_kJ += getNthHeatSourceEnergyInput(iHS, UNITS_KJ); - } - - double qInExtra_kJ = KWH_TO_KJ(extraEnergyInput_kWh); - double qInHeatSourceEnviron_kJ = getEnergyRemovedFromEnvironment(UNITS_KJ); - double qOutTankEnviron_kJ = KWH_TO_KJ(standbyLosses_kWh); - double qOutWater_kJ = - drawCp_kJperC * (outletTemp_C - member_inletT_C); // assumes only one inlet - double expectedTankHeatContent_kJ = - prevHeatContent_kJ // previous heat content - + qInElectrical_kJ // electrical energy delivered to heat sources - + qInExtra_kJ // extra energy delivered to heat sources - + qInHeatSourceEnviron_kJ // heat extracted from environment by condenser - - qOutTankEnviron_kJ // heat released from tank to environment - - qOutWater_kJ; // heat expelled to outlet by water flow - - double qBal_kJ = getTankHeatContent_kJ() - expectedTankHeatContent_kJ; - double fracEnergyDiff = fabs(qBal_kJ) / std::max(prevHeatContent_kJ, 1.); - if (fracEnergyDiff > fracEnergyTolerance) - { - if (hpwhVerbosity >= VRB_reluctant) - { - msg("Energy-balance error: %f kJ, %f %% \n", qBal_kJ, 100. * fracEnergyDiff); - } - return false; - } - return true; -} - #ifndef HPWH_ABRIDGED -int HPWH::HPWHinit_file(string configFile) +int HPWH::initFromFile(string configFile) { - setAllDefaults(); // reset all defaults if you're re-initilizing // sets simHasFailed = true; this gets cleared on successful completion of init // return 0 on success, HPWH_ABORT for failure @@ -4723,7 +5098,7 @@ int HPWH::HPWHinit_file(string configFile) while (std::regex_match(nextToken, std::regex("\\d+"))) { int nodeNum = std::stoi(nextToken); - if (nodeNum > LOGIC_NODE_SIZE + 1 || nodeNum < 0) + if (nodeNum > LOGIC_SIZE + 1 || nodeNum < 0) { if (hpwhVerbosity >= VRB_reluctant) { @@ -4731,7 +5106,7 @@ int HPWH::HPWHinit_file(string configFile) "\n", heatsource, token.c_str(), - LOGIC_NODE_SIZE + 1); + LOGIC_SIZE + 1); } return HPWH_ABORT; } @@ -5290,7 +5665,7 @@ int HPWH::HPWHinit_file(string configFile) } // end while over lines // take care of the non-input processing - hpwhModel = MODELS_CustomFile; + model = MODELS_CustomFile; tankTemps_C.resize(num_nodes); diff --git a/src/HPWH.hh b/src/HPWH.hh index ce1cd03e..7e9b5eec 100644 --- a/src/HPWH.hh +++ b/src/HPWH.hh @@ -19,9 +19,8 @@ class RegularGridInterpolator; } // #define HPWH_ABRIDGED -/**< If HPWH_ABRIDGED is defined, then some function definitions will be - * excluded from compiling. This is done in order to reduce the size of the - * final compiled code. */ +/**< Definition of HPWH_ABRIDGED excludes some functions to reduce the size of the + * compiled library. */ #include "HPWHversion.hh" @@ -35,7 +34,7 @@ class HPWH static const int CONDENSITY_SIZE = 12; /**= the hpwh verbosity, - either pass your message out to the callback function or print it to cout + either pass your message out to the callback functtargetModelion or print it to cout otherwise do nothing */ void msg(const char* fmt, ...) const; void msgV(const char* fmt, va_list ap = NULL) const; @@ -1026,10 +1043,10 @@ class HPWH void* messageCallbackContextPtr; /**< caller context pointer for external message processing */ - MODELS hpwhModel; - /**< The hpwh should know which preset initialized it, or if it was from a fileget */ + MODELS model; + /**< The model id */ - // a std::vector containing the HeatSources, in order of priority + /// a std::vector containing the HeatSources, in order of priority std::vector heatSources; int compressorIndex; @@ -1502,12 +1519,14 @@ constexpr double BTUperKWH = 3412.14163312794; // https://www.rapidtables.com/convert/energy/kWh_to_BTU.html constexpr double FperC = 9. / 5.; // degF / degC constexpr double offsetF = 32.; // degF offset -constexpr double sec_per_min = 60.; // seconds / min +constexpr double sec_per_min = 60.; // s / min constexpr double min_per_hr = 60.; // min / hr -constexpr double sec_per_hr = sec_per_min * min_per_hr; // seconds / hr +constexpr double sec_per_hr = sec_per_min * min_per_hr; // s / hr constexpr double L_per_gal = 3.78541; // liters / gal -constexpr double ft_per_m = 3.2808; // feet / meter -constexpr double ft2_per_m2 = ft_per_m * ft_per_m; // feet / meter +constexpr double ft_per_m = 3.2808; // ft / m +constexpr double ft2_per_m2 = ft_per_m * ft_per_m; // ft^2 / m^2 +constexpr double BTUm2C_per_kWhft2F = + BTUperKWH / ft2_per_m2 / FperC; // BTU m^2 degC / kW h ft^2 degC // a few extra functions for unit conversion inline double dF_TO_dC(double temperature) { return (temperature / FperC); } @@ -1571,5 +1590,6 @@ void calcThermalDist(std::vector& thermalDist, const int lowestNode, const std::vector& nodeTemp_C, const double setpointT_C); +void scaleVector(std::vector& coeffs, const double scaleFactor); #endif diff --git a/src/HPWHHeatingLogics.cc b/src/HPWHHeatingLogics.cc index fbc0c375..e7383607 100644 --- a/src/HPWHHeatingLogics.cc +++ b/src/HPWHHeatingLogics.cc @@ -202,7 +202,7 @@ double HPWH::TempBasedHeatingLogic::nodeWeightAvgFract() return 1. / (double)hpwh->getNumNodes(); } // top calc node only - else if (nodeWeight.nodeNum == LOGIC_NODE_SIZE + 1) + else if (nodeWeight.nodeNum == LOGIC_SIZE + 1) { return 1.; } @@ -215,7 +215,7 @@ double HPWH::TempBasedHeatingLogic::nodeWeightAvgFract() logicNode = calcNodes / totWeight; - return logicNode / static_cast(LOGIC_NODE_SIZE); + return logicNode / static_cast(LOGIC_SIZE); } double HPWH::TempBasedHeatingLogic::getFractToMeetComparisonExternal() @@ -225,12 +225,12 @@ double HPWH::TempBasedHeatingLogic::getFractToMeetComparisonExternal() double sum = 0; double totWeight = 0; - std::vector resampledTankTemps(LOGIC_NODE_SIZE); + std::vector resampledTankTemps(LOGIC_SIZE); resample(resampledTankTemps, hpwh->tankTemps_C); double comparisonT_C = getComparisonValue() + HPWH::TOL_MINVALUE; // slightly over heat - double nodeDensity = static_cast(hpwh->getNumNodes()) / LOGIC_NODE_SIZE; - for (auto& nodeWeight : nodeWeights) + double nodeDensity = static_cast(hpwh->getNumNodes()) / LOGIC_SIZE; + for (auto nodeWeight : nodeWeights) { if (nodeWeight.nodeNum == 0) { // bottom-most tank node only @@ -239,7 +239,8 @@ double HPWH::TempBasedHeatingLogic::getFractToMeetComparisonExternal() sum = nodeT_C * nodeWeight.weight; totWeight = nodeWeight.weight; } - else if (nodeWeight.nodeNum == LOGIC_NODE_SIZE + 1) + // top calc node only + else if (nodeWeight.nodeNum == LOGIC_SIZE + 1) { // top-most tank node only firstNode = calcNode = hpwh->getNumNodes() - 1; double nodeT_C = hpwh->tankTemps_C.back(); diff --git a/src/HPWHpresets.cc b/src/HPWHpresets.cc index d1362a88..7648ff9c 100644 --- a/src/HPWHpresets.cc +++ b/src/HPWHpresets.cc @@ -7,15 +7,16 @@ File Containing all of the presets available in HPWHsim #include -int HPWH::HPWHinit_resTank() +int HPWH::initResistanceTank() { // a default resistance tank, nominal 50 gallons, 0.95 EF, standard double 4.5 kW elements - return this->HPWHinit_resTank(GAL_TO_L(47.5), 0.95, 4500, 4500); + return initResistanceTank(GAL_TO_L(47.5), 0.95, 4500, 4500); } -int HPWH::HPWHinit_resTank(double tankVol_L, - double energyFactor, - double upperPower_W, - double lowerPower_W) + +int HPWH::initResistanceTank(double tankVol_L, + double energyFactor, + double upperPower_W, + double lowerPower_W) { setAllDefaults(); // reset all defaults if you're re-initilizing @@ -54,10 +55,9 @@ int HPWH::HPWHinit_resTank(double tankVol_L, // use tank size setting function since it has bounds checking tankSizeFixed = false; - int failure = this->setTankSize(tankVol_L); - if (failure == HPWH_ABORT) + if (setTankSize(tankVol_L) == HPWH_ABORT) { - return failure; + return HPWH_ABORT; } setpoint_C = F_TO_C(127.0); @@ -118,7 +118,7 @@ int HPWH::HPWHinit_resTank(double tankVol_L, tankUA_kJperHrC = 0.0; } - hpwhModel = MODELS_CustomResTank; + model = MODELS_CustomResTank; // calculate oft-used derived values calcDerivedValues(); @@ -149,10 +149,10 @@ int HPWH::HPWHinit_resTank(double tankVol_L, return 0; // successful init returns 0 } -int HPWH::HPWHinit_resTankGeneric(double tankVol_L, - double rValue_M2KperW, - double upperPower_W, - double lowerPower_W) +int HPWH::initResistanceTankGeneric(double tankVol_L, + double rValue_m2KperW, + double upperPower_W, + double lowerPower_W) { setAllDefaults(); // reset all defaults if you're re-initilizing @@ -177,7 +177,7 @@ int HPWH::HPWHinit_resTankGeneric(double tankVol_L, } return HPWH_ABORT; } - if (rValue_M2KperW <= 0.) + if (rValue_m2KperW <= 0.) { if (hpwhVerbosity >= VRB_reluctant) { @@ -190,7 +190,7 @@ int HPWH::HPWHinit_resTankGeneric(double tankVol_L, // set tank size function has bounds checking tankSizeFixed = false; - if (this->setTankSize(tankVol_L) == HPWH_ABORT) + if (setTankSize(tankVol_L) == HPWH_ABORT) { return HPWH_ABORT; } @@ -236,8 +236,8 @@ int HPWH::HPWHinit_resTankGeneric(double tankVol_L, // Calc UA double SA_M2 = getTankSurfaceArea(tankVol_L, HPWH::UNITS_L, HPWH::UNITS_M2); - double tankUA_WperK = SA_M2 / rValue_M2KperW; - tankUA_kJperHrC = tankUA_WperK * 3.6; // 3.6 = 3600 S/Hr and 1/1000 kJ/J + double tankUA_WperK = SA_M2 / rValue_m2KperW; + tankUA_kJperHrC = tankUA_WperK * sec_per_hr / 1000.; // 1000 J/kJ if (tankUA_kJperHrC < 0.) { @@ -248,7 +248,7 @@ int HPWH::HPWHinit_resTankGeneric(double tankVol_L, tankUA_kJperHrC = 0.0; } - hpwhModel = HPWH::MODELS_CustomResTankGeneric; + model = HPWH::MODELS_CustomResTankGeneric; // calculate oft-used derived values calcDerivedValues(); @@ -279,7 +279,7 @@ int HPWH::HPWHinit_resTankGeneric(double tankVol_L, return 0; // successful init returns 0 } -int HPWH::HPWHinit_genericHPWH(double tankVol_L, double energyFactor, double resUse_C) +int HPWH::initGeneric(double tankVol_L, double energyFactor, double resUse_C) { setAllDefaults(); // reset all defaults if you're re-initilizing @@ -417,7 +417,7 @@ int HPWH::HPWHinit_genericHPWH(double tankVol_L, double energyFactor, double res // standard finishing up init, borrowed from init function - hpwhModel = MODELS_genericCustomUEF; + model = MODELS_genericCustomUEF; // calculate oft-used derived values calcDerivedValues(); @@ -447,13 +447,11 @@ int HPWH::HPWHinit_genericHPWH(double tankVol_L, double energyFactor, double res } simHasFailed = false; - return 0; } -int HPWH::HPWHinit_presets(MODELS presetNum) +int HPWH::initPreset(MODELS presetNum) { - setAllDefaults(); // reset all defaults if you're re-initilizing // sets simHasFailed = true; this gets cleared on successful completion of init // return 0 on success, HPWH_ABORT for failure @@ -4304,7 +4302,7 @@ int HPWH::HPWHinit_presets(MODELS presetNum) heatSources[1].followedByHeatSource = &heatSources[2]; } // If a the model is the TamOMatic, HotTam, Generic... This model is scalable. - else if (presetNum == MODELS_TamScalable_SP) + else if ((MODELS_TamScalable_SP <= presetNum) && (presetNum <= MODELS_TamScalable_SP_Half)) { setNumNodes(24); setpoint_C = F_TO_C(135.0); @@ -4339,17 +4337,17 @@ int HPWH::HPWHinit_presets(MODELS presetNum) // Perfmap for input power and COP made from data for poor preforming modeled to be scalled // for this model - std::vector inputPwr_coeffs = {13.6, - 0.00995, - -0.0342, - -0.014, - -0.000110, - 0.00026, - 0.000232, - 0.000195, - -0.00034, - 5.30E-06, - 2.3600E-06}; + std::vector inputPower_coeffs = {13.6, + 0.00995, + -0.0342, + -0.014, + -0.000110, + 0.00026, + 0.000232, + 0.000195, + -0.00034, + 5.30E-06, + 2.3600E-06}; std::vector COP_coeffs = {1.945, 0.0412, -0.0112, @@ -4362,10 +4360,24 @@ int HPWH::HPWHinit_presets(MODELS presetNum) 0.0000392, -3.52E-07}; + // Set model scale factor + double scaleFactor = 1.; + if (presetNum == MODELS_TamScalable_SP_2X) + { + scaleFactor = 2.; + } + else if (presetNum == MODELS_TamScalable_SP_Half) + { + scaleFactor = 0.5; + } + + // Scale the compressor capacity + scaleVector(inputPower_coeffs, scaleFactor); + compressor.perfMap.push_back({ - 105, // Temperature (T_F) - inputPwr_coeffs, // Input Power Coefficients (inputPower_coeffs - COP_coeffs // COP Coefficients (COP_coeffs) + 105, // Temperature (T_F) + inputPower_coeffs, // Input Power Coefficients (inputPower_coeffs + COP_coeffs // COP Coefficients (COP_coeffs) }); // logic conditions @@ -4384,8 +4396,10 @@ int HPWH::HPWHinit_presets(MODELS presetNum) "bottom node", nodeWeights1, dF_TO_dC(15.), this, false, std::greater(), true)); compressor.depressesTemperature = false; // no temp depression - resistiveElementBottom.setupAsResistiveElement(0, 30000); - resistiveElementTop.setupAsResistiveElement(9, 30000); + // Scale the resistance-element power + double elementPower_W = scaleFactor * 30000.; + resistiveElementBottom.setupAsResistiveElement(0, elementPower_W); + resistiveElementTop.setupAsResistiveElement(9, elementPower_W); // top resistor values // standard logic conditions @@ -4571,7 +4585,7 @@ int HPWH::HPWHinit_presets(MODELS presetNum) else // start tank off at setpoint resetTankToSetpoint(); - hpwhModel = presetNum; + model = presetNum; // calculate oft-used derived values calcDerivedValues(); diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 8023f63b..c17ce57f 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,57 +1,20 @@ + # Build test tool add_executable(testTool main.cc) -# TODO: Migrate to googletest framework -add_executable(testTankSizeFixed testTankSizeFixed.cc) -add_executable(testScaleHPWH testScaleHPWH.cc) -add_executable(testMaxSetpoint testMaxSetpoint.cc) -add_executable(testSizingFractions testSizingFractions.cc) -add_executable(testResistanceFcts testResistanceFcts.cc) -add_executable(testCompressorFcts testCompressorFcts.cc) -add_executable(testPerformanceMaps testPerformanceMaps.cc) -add_executable(testStateOfChargeFcts testStateOfChargeFcts.cc) -add_executable(testHeatingLogics testHeatingLogics.cc) -add_executable(testEnergyBalance testEnergyBalance.cc) - -set(libs libHPWHsim ${PROJECT_NAME}_common_interface) +set(libs ${PROJECT_NAME} ${PROJECT_NAME}_common_interface) target_link_libraries(testTool PRIVATE ${libs}) -target_link_libraries(testTankSizeFixed PRIVATE ${libs}) -target_link_libraries(testScaleHPWH PRIVATE ${libs}) -target_link_libraries(testMaxSetpoint PRIVATE ${libs}) -target_link_libraries(testSizingFractions PRIVATE ${libs}) -target_link_libraries(testResistanceFcts PRIVATE ${libs}) -target_link_libraries(testCompressorFcts PRIVATE ${libs}) -target_link_libraries(testPerformanceMaps PRIVATE ${libs}) -target_link_libraries(testStateOfChargeFcts PRIVATE ${libs}) -target_link_libraries(testHeatingLogics PRIVATE ${libs}) -target_link_libraries(testEnergyBalance PRIVATE ${libs}) target_compile_features(testTool PRIVATE cxx_std_17) +add_subdirectory(unit_tests) + # Add output directory for test results add_custom_target(results_directory ALL COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_CURRENT_BINARY_DIR}/output") -# Clear output file for yearly tests -#add_custom_target(do_always ALL COMMAND ${CMAKE_COMMAND} file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/output/DHW_YRLY.csv") ) add_test(NAME "Ready.Output.Files" COMMAND ${CMAKE_COMMAND} -E remove "${CMAKE_CURRENT_BINARY_DIR}/output/DHW_YRLY.csv") -# Run Unit tests -add_test(NAME "testScaleHPWH" COMMAND $ ${testArgs} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) -add_test(NAME "testMaxSetpoint" COMMAND $ ${testArgs} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) -add_test(NAME "testSizingFractions" COMMAND $ ${testArgs} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) -add_test(NAME "testResistanceFcts" COMMAND $ ${testArgs} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) -add_test(NAME "testCompressorFcts" COMMAND $ ${testArgs} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) -add_test(NAME "testPerformanceMaps" COMMAND $ ${testArgs} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) -add_test(NAME "testStateOfChargeFcts" COMMAND $ ${testArgs} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) -add_test(NAME "testHeatingLogics" COMMAND $ ${testArgs} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) -add_test(NAME "testEnergyBalance" COMMAND $ ${testArgs} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) - -#add_test(NAME "testREGoesTo99C.AOSmithCAHP120" COMMAND $ "Preset" "AOSmithCAHP120" "testREGoesTo99C" -#"${CMAKE_CURRENT_BINARY_DIR}/output" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) -#add_test(NAME "testREGoesTo99CCold.AOSmithCAHP120" COMMAND $ "Preset" "AOSmithCAHP120" "testREGoesTo99CCold" -#"${CMAKE_CURRENT_BINARY_DIR}/output" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) - # Run model tests and unit tests on models set(testNames test30 @@ -212,28 +175,6 @@ set(stateOfChargeCompressorNames list(APPEND extendedModelNames ${modelNames} ${heatExchangeModelNames}) list(REMOVE_DUPLICATES extendedModelNames) -# Unit tests -function(add_TankSizeFixed_test) - set(options) - set(oneValueArgs MODEL_NAME) - set(multValueArgs) - cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) - - set(testArgs "${ARG_MODEL_NAME}") - - set(TEST_TITLE "TankSizeFixed.${ARG_MODEL_NAME}") - - add_test(NAME "${TEST_TITLE}" COMMAND $ ${testArgs} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) -endfunction() - -foreach (model ${extendedModelNames}) - add_TankSizeFixed_test(MODEL_NAME "${model}") -endforeach (model) -foreach (model ${largeCompressorNames}) - add_TankSizeFixed_test(MODEL_NAME "${model}") -endforeach (model) - #Tests for successful runs function(add_model_test) set(options) diff --git a/test/main.cc b/test/main.cc index 4c284253..c6961f4f 100644 --- a/test/main.cc +++ b/test/main.cc @@ -9,7 +9,6 @@ * */ #include "HPWH.hh" -#include "testUtilityFcts.cc" #include #include #include @@ -137,13 +136,13 @@ int main(int argc, char* argv[]) { inputFile = ""; - if (getHPWHObject(hpwh, input2) == HPWH::HPWH_ABORT) + if (hpwh.initPreset(input2) != 0) { cout << "Error, preset model did not initialize.\n"; exit(1); } - model = static_cast(hpwh.getHPWHModel()); + model = static_cast(hpwh.getModel()); if (model == HPWH::MODELS_Sanden80 || model == HPWH::MODELS_Sanden40) { @@ -153,8 +152,11 @@ int main(int argc, char* argv[]) else if (input1 == "File") { inputFile = input2 + ".txt"; - if (hpwh.HPWHinit_file(inputFile) != 0) + if (hpwh.initFromFile(inputFile) != 0) + { + cout << "Error, file model did not initialize.\n"; exit(1); + } } else { @@ -284,19 +286,15 @@ int main(int argc, char* argv[]) if (!allSchedules[5].empty()) { hpwh.setSetpoint(allSchedules[5][0]); // expect this to fail sometimes - if (hasInitialTankTemp) - hpwh.setTankToTemperature(initialTankT_C); - else - hpwh.resetTankToSetpoint(); } else { hpwh.setSetpoint(newSetpoint); - if (hasInitialTankTemp) - hpwh.setTankToTemperature(initialTankT_C); - else - hpwh.resetTankToSetpoint(); } + if (hasInitialTankTemp) + hpwh.setTankToTemperature(initialTankT_C); + else + hpwh.resetTankToSetpoint(); } if (inletH > 0) { @@ -349,7 +347,7 @@ int main(int argc, char* argv[]) } string header = strHead; - if (hpwh.isCompressoExternalMultipass()) + if (hpwh.isCompressorExternalMultipass() == 1) { header += strHeadMP; } @@ -405,7 +403,7 @@ int main(int argc, char* argv[]) } // Mix down for yearly tests with large compressors - if (hpwh.getHPWHModel() >= 210 && minutesToRun > 500000.) + if (hpwh.getModel() >= 210 && minutesToRun > 500000.) { // Do a simple mix down of the draw for the cold water temperature if (hpwh.getSetpoint() <= 125.) @@ -445,7 +443,7 @@ int main(int argc, char* argv[]) } } // Check flow for external MP - if (hpwh.isCompressoExternalMultipass()) + if (hpwh.isCompressorExternalMultipass() == 1) { double volumeHeated_Gal = hpwh.getExternalVolumeHeated(HPWH::UNITS_GAL); double mpFlowVolume_Gal = hpwh.getExternalMPFlowRate(HPWH::UNITS_GPM) * @@ -471,7 +469,7 @@ int main(int argc, char* argv[]) std::to_string(allSchedules[0][i]) + ", " + std::to_string(allSchedules[1][i]) + ", "; // Add some more outputs for mp tests - if (hpwh.isCompressoExternalMultipass()) + if (hpwh.isCompressorExternalMultipass() == 1) { strPreamble += std::to_string(hpwh.getCondenserWaterInletTemp()) + ", " + std::to_string(hpwh.getCondenserWaterOutletTemp()) + ", " + diff --git a/test/testCompressorFcts.cc b/test/testCompressorFcts.cc deleted file mode 100644 index 622bb763..00000000 --- a/test/testCompressorFcts.cc +++ /dev/null @@ -1,154 +0,0 @@ - - -/*unit test for isTankSizeFixed() functionality - * - * - * - */ -#include "HPWH.hh" -#include "testUtilityFcts.cc" - -#include -#include - -using std::cout; -using std::string; - -void testHasACompressor(string input, bool expected) -{ - HPWH hpwh; - getHPWHObject(hpwh, input); // get preset model - ASSERTTRUE(hpwh.hasACompressor() == expected); -} - -void testGetCompCoilConfig(string input, int expected) -{ - HPWH hpwh; - getHPWHObject(hpwh, input); // get preset model - ASSERTTRUE(hpwh.getCompressorCoilConfig() == expected); -} - -void testIsCompressorMultipass(string input, bool expected) -{ - HPWH hpwh; - getHPWHObject(hpwh, input); // get preset model - ASSERTTRUE(hpwh.isCompressorMultipass() == expected); -} - -void testIsCompressoExternalMultipass(string input, bool expected) -{ - HPWH hpwh; - getHPWHObject(hpwh, input); // get preset model - ASSERTTRUE(hpwh.isCompressoExternalMultipass() == expected); -} - -void testGetMaxCompressorSetpoint(string input, double expected) -{ - HPWH hpwh; - getHPWHObject(hpwh, input); // get preset model - ASSERTTRUE(hpwh.getMaxCompressorSetpoint() == expected); -} - -void testGetMinOperatingTemp(string input, double expected) -{ - HPWH hpwh; - getHPWHObject(hpwh, input); // get preset model - ASSERTTRUE(hpwh.getMinOperatingTemp(HPWH::UNITS_F) == expected); -} - -int main(int, char**) -{ - - const int length = 14; - const string models[length] = {"AOSmithHPTU50", - "Stiebel220e", - "AOSmithCAHP120", - "Sanden80", - "ColmacCxV_5_SP", - "ColmacCxA_20_SP", - "TamScalable_SP", - "restankRealistic", - "StorageTank", - "ColmacCxA_20_MP", - "Scalable_MP", - "NyleC90A_MP", - "NyleC90A_C_MP", - "QAHV_N136TAU_HPB_SP"}; - const int hasComp[length] = { - true, true, true, true, true, true, true, false, false, true, true, true, true, true}; - const int coilConfig[length] = { - 1, 1, 1, 2, 2, 2, 2, HPWH::HPWH_ABORT, HPWH::HPWH_ABORT, 2, 2, 2, 2, 2}; // 1 Wrapped 2 - // External - const int heatCycle[length] = {true, - true, - true, - false, - false, - false, - false, - HPWH::HPWH_ABORT, - HPWH::HPWH_ABORT, - true, - true, - true, - true, - false}; // true single, false singlepass - const int isExtMP[length] = {false, - false, - false, - false, - false, - false, - false, - HPWH::HPWH_ABORT, - HPWH::HPWH_ABORT, - true, - true, - true, - true, - false}; - - const double maxStpt[length] = {HPWH::MAXOUTLET_R134A, - HPWH::MAXOUTLET_R134A, - HPWH::MAXOUTLET_R134A, - HPWH::MAXOUTLET_R744, - HPWH::MAXOUTLET_R410A, - HPWH::MAXOUTLET_R134A, - HPWH::MAXOUTLET_R134A, - HPWH::HPWH_ABORT, - HPWH::HPWH_ABORT, - HPWH::MAXOUTLET_R134A, - HPWH::MAXOUTLET_R134A, - F_TO_C(160.), - F_TO_C(160.), - F_TO_C(176.1)}; // deg C - - const double minTemp[length] = {42., - 32., - 47., - -25, - -4., - 40., - 40., - HPWH::HPWH_ABORT, - HPWH::HPWH_ABORT, - 40., - 40., - 40., - 35., - -13.}; // deg F - - for (int i = 0; i < length; i++) - { - testHasACompressor(models[i], hasComp[i]); - testGetCompCoilConfig(models[i], coilConfig[i]); - testIsCompressorMultipass(models[i], heatCycle[i]); - testIsCompressoExternalMultipass(models[i], isExtMP[i]); - - testGetMaxCompressorSetpoint(models[i], maxStpt[i]); - testGetMinOperatingTemp(models[i], minTemp[i]); - } - - // Made it through the gauntlet - return 0; -} diff --git a/test/testEnergyBalance.cc b/test/testEnergyBalance.cc deleted file mode 100644 index 9dfd7c4d..00000000 --- a/test/testEnergyBalance.cc +++ /dev/null @@ -1,81 +0,0 @@ -/* - * unit test for energy balancing - */ -#include "HPWH.hh" -#include "testUtilityFcts.cc" - -#include -#include - -/* Test energy balance for AOSmithHPTS50*/ -void testEnergyBalanceAOSmithHPTS50() -{ - - HPWH hpwh; - getHPWHObject(hpwh, "AOSmithHPTS50"); - - double maxDrawVol_L = 1.; - const double ambientT_C = 20.; - const double externalT_C = 20.; - - // - hpwh.setTankToTemperature(20.); - hpwh.setInletT(5.); - - const double Pi = 4. * atan(1.); - double testDuration_min = 60.; - for (int i_min = 0; i_min < testDuration_min; ++i_min) - { - double t_min = static_cast(i_min); - - double flowFac = sin(Pi * t_min / testDuration_min) - 0.5; - flowFac += fabs(flowFac); // semi-sinusoidal flow profile - double drawVol_L = flowFac * maxDrawVol_L; - - double prevHeatContent_kJ = hpwh.getTankHeatContent_kJ(); - hpwh.runOneStep(drawVol_L, ambientT_C, externalT_C, HPWH::DR_ALLOW); - ASSERTTRUE(hpwh.isEnergyBalanced(drawVol_L, prevHeatContent_kJ, 1.e-6)); - } -} - -/* Test energy balance for storage tank with extra heat (solar)*/ -void testEnergyBalanceSolar() -{ - - HPWH hpwh; - getHPWHObject(hpwh, "StorageTank"); - - double maxDrawVol_L = 1.; - const double ambientT_C = 20.; - const double externalT_C = 20.; - - std::vector nodePowerExtra_W = {1000.}; - // - hpwh.setUA(0.); - hpwh.setTankToTemperature(20.); - hpwh.setInletT(5.); - - const double Pi = 4. * atan(1.); - double testDuration_min = 60.; - for (int i_min = 0; i_min < testDuration_min; ++i_min) - { - double t_min = static_cast(i_min); - - double flowFac = sin(Pi * t_min / testDuration_min) - 0.5; - flowFac += fabs(flowFac); // semi-sinusoidal flow profile - double drawVol_L = flowFac * maxDrawVol_L; - - double prevHeatContent_kJ = hpwh.getTankHeatContent_kJ(); - hpwh.runOneStep( - drawVol_L, ambientT_C, externalT_C, HPWH::DR_ALLOW, 0., 0., &nodePowerExtra_W); - ASSERTTRUE(hpwh.isEnergyBalanced(drawVol_L, prevHeatContent_kJ, 1.e-6)); - } -} - -int main(int, char**) -{ - testEnergyBalanceAOSmithHPTS50(); - testEnergyBalanceSolar(); - - return 0; -} diff --git a/test/testHeatingLogics.cc b/test/testHeatingLogics.cc deleted file mode 100644 index f5a0cf4f..00000000 --- a/test/testHeatingLogics.cc +++ /dev/null @@ -1,352 +0,0 @@ -#include "HPWH.hh" -#include "testUtilityFcts.cc" - -#include -#include -#include - -using std::cout; -using std::string; - -void testHasEnteringWaterShutOff(string& input); -void testDoesNotHaveEnteringWaterShutOff(string& input); -void testSetEnteringWaterShuffOffOutOfBoundsIndex(string& input); -void testSetEnteringWaterShuffOffDeadbandToSmall(string& input); -void testCanNotSetEnteringWaterShutOff(string& input); -void testSetEnteringWaterHighTempShutOffAbsolute(string& input); -void testSetEnteringWaterHighTempShutOffRelative(string& input); - -void testChangeToStateofChargeControlled(string& input); -void testSetStateOfCharge(string& input); - -void testSetStateOfCharge(string& input, double coldWater_F, double minTUse_F, double tankTAt76SoC); -void testExtraHeat(); - -const std::vector hasHighShuttOffVectSP = {"Sanden80", - "QAHV_N136TAU_HPB_SP", - "ColmacCxA_20_SP", - "ColmacCxV_5_SP", - "NyleC60A_SP", - "NyleC60A_C_SP", - "NyleC185A_C_SP", - "TamScalable_SP"}; - -const std::vector noHighShuttOffVectMPExternal = {"Scalable_MP", - "ColmacCxA_20_MP", - "ColmacCxA_15_MP", - "ColmacCxV_5_MP", - "NyleC90A_MP", - "NyleC90A_C_MP", - "NyleC250A_MP", - "NyleC250A_C_MP"}; - -const std::vector noHighShuttOffVectIntegrated = {"AOSmithHPTU80", - "Rheem2020Build80", - "Stiebel220e", - "AOSmithCAHP120", - "AWHSTier3Generic80", - "Generic1", - "RheemPlugInDedicated50", - "RheemPlugInShared65", - "restankRealistic", - "StorageTank"}; - -int main(int, char**) -{ - double tempsForSetSoC[5][3] = { - {49, 99, 125}, {65, 110, 129}, {32, 120, 121}, {32, 33, 121}, {80, 81, 132.5}}; - - for (string hpwhStr : hasHighShuttOffVectSP) - { - testHasEnteringWaterShutOff(hpwhStr); - testSetEnteringWaterShuffOffOutOfBoundsIndex(hpwhStr); - testSetEnteringWaterShuffOffDeadbandToSmall(hpwhStr); - testSetEnteringWaterHighTempShutOffAbsolute(hpwhStr); - testSetEnteringWaterHighTempShutOffRelative(hpwhStr); - - testChangeToStateofChargeControlled(hpwhStr); - for (int i = 0; i < 5; i++) - { - testSetStateOfCharge( - hpwhStr, tempsForSetSoC[i][0], tempsForSetSoC[i][1], tempsForSetSoC[i][2]); - } - } - - for (string hpwhStr : noHighShuttOffVectMPExternal) - { - testDoesNotHaveEnteringWaterShutOff(hpwhStr); - testCanNotSetEnteringWaterShutOff(hpwhStr); - - testChangeToStateofChargeControlled(hpwhStr); - for (int i = 0; i < 5; i++) - { - testSetStateOfCharge( - hpwhStr, tempsForSetSoC[i][0], tempsForSetSoC[i][1], tempsForSetSoC[i][2]); - } - } - - for (string hpwhStr : noHighShuttOffVectIntegrated) - { - testDoesNotHaveEnteringWaterShutOff(hpwhStr); - testCanNotSetEnteringWaterShutOff(hpwhStr); - } - - testExtraHeat(); - return 0; -} - -void testHasEnteringWaterShutOff(string& input) -{ - HPWH hpwh; - getHPWHObject(hpwh, input); - int index = hpwh.getCompressorIndex() == -1 ? 0 : hpwh.getCompressorIndex(); - ASSERTTRUE(hpwh.hasEnteringWaterHighTempShutOff(index) == true); -} - -void testDoesNotHaveEnteringWaterShutOff(string& input) -{ - HPWH hpwh; - getHPWHObject(hpwh, input); - int index = hpwh.getCompressorIndex() == -1 ? 0 : hpwh.getCompressorIndex(); - ASSERTTRUE(hpwh.hasEnteringWaterHighTempShutOff(index) == false); -} - -void testCanNotSetEnteringWaterShutOff(string& input) -{ - HPWH hpwh; - getHPWHObject(hpwh, input); - int index = hpwh.getCompressorIndex() == -1 ? 0 : hpwh.getCompressorIndex(); - ASSERTTRUE(hpwh.setEnteringWaterHighTempShutOff(10., false, index) == HPWH::HPWH_ABORT); -} - -void testSetEnteringWaterShuffOffOutOfBoundsIndex(string& input) -{ - HPWH hpwh; - getHPWHObject(hpwh, input); - int index = -1; - ASSERTTRUE(hpwh.setEnteringWaterHighTempShutOff(10., false, index) == HPWH::HPWH_ABORT); - index = 15; - ASSERTTRUE(hpwh.setEnteringWaterHighTempShutOff(10., false, index) == HPWH::HPWH_ABORT); -} - -void testSetEnteringWaterShuffOffDeadbandToSmall(string& input) -{ - HPWH hpwh; - getHPWHObject(hpwh, input); - - double value = HPWH::MINSINGLEPASSLIFT - 1.; - ASSERTTRUE(hpwh.setEnteringWaterHighTempShutOff(value, false, hpwh.getCompressorIndex()) == - HPWH::HPWH_ABORT); - - value = HPWH::MINSINGLEPASSLIFT; - ASSERTTRUE(hpwh.setEnteringWaterHighTempShutOff(value, false, hpwh.getCompressorIndex()) == 0); - - value = hpwh.getSetpoint() - (HPWH::MINSINGLEPASSLIFT - 1); - ASSERTTRUE(hpwh.setEnteringWaterHighTempShutOff(value, true, hpwh.getCompressorIndex()) == - HPWH::HPWH_ABORT); - - value = hpwh.getSetpoint() - HPWH::MINSINGLEPASSLIFT; - ASSERTTRUE(hpwh.setEnteringWaterHighTempShutOff(value, true, hpwh.getCompressorIndex()) == 0); -} - -/* Tests we can set the entering water high temp shutt off with aboslute values and it works turns - * off and on as expected. */ -void testSetEnteringWaterHighTempShutOffAbsolute(string& input) -{ - const double drawVolume_L = 0.; - const double externalT_C = 20.; - const double delta = 2.; - const double highT_C = 20.; - const bool doAbsolute = true; - HPWH hpwh; - getHPWHObject(hpwh, input); - - // make tank cold to force on - hpwh.setTankToTemperature(highT_C); - - // run a step and check we're heating - hpwh.runOneStep(highT_C, drawVolume_L, externalT_C, externalT_C, HPWH::DR_ALLOW); - ASSERTTRUE(compressorIsRunning(hpwh)); - - // change entering water temp to below temp - ASSERTTRUE(hpwh.setEnteringWaterHighTempShutOff( - highT_C - delta, doAbsolute, hpwh.getCompressorIndex()) == 0); - - // run a step and check we're not heating. - hpwh.runOneStep(highT_C, drawVolume_L, externalT_C, externalT_C, HPWH::DR_ALLOW); - ASSERTFALSE(compressorIsRunning(hpwh)); - - // and reverse it - ASSERTTRUE(hpwh.setEnteringWaterHighTempShutOff( - highT_C + delta, doAbsolute, hpwh.getCompressorIndex()) == 0); - hpwh.runOneStep(highT_C, drawVolume_L, externalT_C, externalT_C, HPWH::DR_ALLOW); - ASSERTTRUE(compressorIsRunning(hpwh)); -} - -/* Tests we can set the entering water high temp shutt off with relative values and it works turns - * off and on as expected. */ -void testSetEnteringWaterHighTempShutOffRelative(string& input) -{ - const double drawVolume_L = 0.; - const double externalT_C = 20.; - const double delta = 2.; - const double highT_C = 20.; - const bool doAbsolute = false; - HPWH hpwh; - getHPWHObject(hpwh, input); - - const double relativeHighT_C = hpwh.getSetpoint() - highT_C; - // make tank cold to force on - hpwh.setTankToTemperature(highT_C); - - // run a step and check we're heating - hpwh.runOneStep(highT_C, drawVolume_L, externalT_C, externalT_C, HPWH::DR_ALLOW); - ASSERTTRUE(hpwh.isNthHeatSourceRunning(hpwh.getCompressorIndex()) == 1); - - // change entering water temp to below temp - ASSERTTRUE(hpwh.setEnteringWaterHighTempShutOff( - relativeHighT_C + delta, doAbsolute, hpwh.getCompressorIndex()) == 0); - - // run a step and check we're not heating. - hpwh.runOneStep(highT_C, drawVolume_L, externalT_C, externalT_C, HPWH::DR_ALLOW); - ASSERTTRUE(hpwh.isNthHeatSourceRunning(hpwh.getCompressorIndex()) == 0); - - // and reverse it - ASSERTTRUE(hpwh.setEnteringWaterHighTempShutOff( - relativeHighT_C - delta, doAbsolute, hpwh.getCompressorIndex()) == 0); - hpwh.runOneStep(highT_C, drawVolume_L, externalT_C, externalT_C, HPWH::DR_ALLOW); - ASSERTTRUE(hpwh.isNthHeatSourceRunning(hpwh.getCompressorIndex()) == 1); -} - -/* Test we can switch and the controls change as expected*/ -void testChangeToStateofChargeControlled(string& input) -{ - HPWH hpwh; - const double externalT_C = 20.; - const double setpointT_C = F_TO_C(149.); - - getHPWHObject(hpwh, input); - const bool originalHasHighTempShutOff = - hpwh.hasEnteringWaterHighTempShutOff(hpwh.getCompressorIndex()); - if (!hpwh.isSetpointFixed()) - { - double temp; - string tempStr; - if (!hpwh.isNewSetpointPossible(setpointT_C, temp, tempStr)) - { - return; // Numbers don't aline for this type - } - hpwh.setSetpoint(setpointT_C); - } - - // Just created so should be fasle - ASSERTFALSE(hpwh.isSoCControlled()); - - // change to SOC control; - hpwh.switchToSoCControls(.76, .05, 99, true, 49, HPWH::UNITS_F); - ASSERTTRUE(hpwh.isSoCControlled()); - - // check entering water high temp shut off controll unchanged - ASSERTTRUE(hpwh.hasEnteringWaterHighTempShutOff(hpwh.getCompressorIndex()) == - originalHasHighTempShutOff); - - // Test we can change the SoC and run a step and check we're heating - if (hpwh.hasEnteringWaterHighTempShutOff(hpwh.getCompressorIndex())) - { - ASSERTTRUE(hpwh.setEnteringWaterHighTempShutOff( - setpointT_C - HPWH::MINSINGLEPASSLIFT, true, hpwh.getCompressorIndex()) == - 0); // Force to ignore this part. - } - ASSERTTRUE(hpwh.setTankToTemperature(F_TO_C(100.)) == 0); // .51 - hpwh.runOneStep(0, externalT_C, externalT_C, HPWH::DR_ALLOW); - ASSERTTRUE(compressorIsRunning(hpwh)); - - // Test if we're on and in band stay on - hpwh.setTankToTemperature(F_TO_C(125)); // .76 (current target) - hpwh.runOneStep(0, externalT_C, externalT_C, HPWH::DR_ALLOW); - ASSERTTRUE(compressorIsRunning(hpwh)); - - // Test we can change the SoC and turn off - hpwh.setTankToTemperature(F_TO_C(133)); // .84 - hpwh.runOneStep(0, externalT_C, externalT_C, HPWH::DR_ALLOW); - ASSERTFALSE(compressorIsRunning(hpwh)); - - // Test if off and in band stay off - hpwh.setTankToTemperature(F_TO_C(125)); // .76 (current target) - hpwh.runOneStep(0, externalT_C, externalT_C, HPWH::DR_ALLOW); - ASSERTFALSE(compressorIsRunning(hpwh)); -} - -/*Test we can change the target and turn off and on*/ -void testSetStateOfCharge(string& input, double coldWater_F, double minTUse_F, double tankTAt76SoC) -{ - HPWH hpwh; - const double externalT_C = 20.; - const double setpointT_C = F_TO_C(149.); - - getHPWHObject(hpwh, input); - if (!hpwh.isSetpointFixed()) - { - double temp; - string tempStr; - if (!hpwh.isNewSetpointPossible(setpointT_C, temp, tempStr)) - { - return; // Numbers don't aline for this type - } - hpwh.setSetpoint(setpointT_C); - } - - // change to SOC control; - hpwh.switchToSoCControls(.85, .05, minTUse_F, true, coldWater_F, HPWH::UNITS_F); - ASSERTTRUE(hpwh.isSoCControlled()); - - // Test if we're on and in band stay on - hpwh.setTankToTemperature(F_TO_C(tankTAt76SoC)); // .76 - hpwh.runOneStep(0, externalT_C, externalT_C, HPWH::DR_ALLOW); - ASSERTTRUE(compressorIsRunning(hpwh)); - - // Test we can change the target SoC and turn off - hpwh.setTargetSoCFraction(0.5); - hpwh.runOneStep(0, externalT_C, externalT_C, HPWH::DR_ALLOW); - ASSERTFALSE(compressorIsRunning(hpwh)); - - // Change back in the band and stay turned off - hpwh.setTargetSoCFraction(0.72); - hpwh.runOneStep(0, externalT_C, externalT_C, HPWH::DR_ALLOW); - ASSERTFALSE(compressorIsRunning(hpwh)); - - // Drop below the band and turn on - hpwh.setTargetSoCFraction(0.70); - hpwh.runOneStep(0, externalT_C, externalT_C, HPWH::DR_ALLOW); - ASSERTFALSE(compressorIsRunning(hpwh)); -} - -/*Test adding extra heat to a tank for one minute*/ -void testExtraHeat() -{ - HPWH hpwh; - getHPWHObject(hpwh, "StorageTank"); - - const double ambientT_C = 20.; - const double externalT_C = 20.; - const double inletVol2_L = 0.; - const double inletT2_C = 0.; - - double extraPower_W = 1000.; - std::vector nodePowerExtra_W = {extraPower_W}; - - // - hpwh.setUA(0.); - hpwh.setTankToTemperature(20.); - - double Q_init = hpwh.getTankHeatContent_kJ(); - hpwh.runOneStep( - 0, ambientT_C, externalT_C, HPWH::DR_LOC, inletVol2_L, inletT2_C, &nodePowerExtra_W); - double Q_final = hpwh.getTankHeatContent_kJ(); - - double dQ_actual_kJ = (Q_final - Q_init); - - double dQ_expected_kJ = extraPower_W * 60. / 1.e3; // 1 min - - ASSERTTRUE(cmpd(dQ_actual_kJ, dQ_expected_kJ)); -} diff --git a/test/testMaxSetpoint.cc b/test/testMaxSetpoint.cc deleted file mode 100644 index 18074c6c..00000000 --- a/test/testMaxSetpoint.cc +++ /dev/null @@ -1,304 +0,0 @@ - - -/*unit test for isTankSizeFixed() functionality - * - * - * - */ -#include "HPWH.hh" -#include "testUtilityFcts.cc" - -#include -#include - -using std::cout; -using std::string; - -void testMaxSetpointResistanceTank(); -void testScalableCompressor(); -void testJustR134ACompressor(); -void testJustR410ACompressor(); -void testJustQAHVCompressor(); -void testHybridModel(); -void testStorageTankSetpoint(); -void testSetpointFixed(); -void testResampling(); -void testSetTankTemps(); - -const double REMaxShouldBe = 100.; - -int main(int, char**) -{ - testMaxSetpointResistanceTank(); - testScalableCompressor(); - testJustR134ACompressor(); - testJustR410ACompressor(); - testJustQAHVCompressor(); - testHybridModel(); - testStorageTankSetpoint(); - testSetpointFixed(); - testResampling(); - testSetTankTemps(); - - // Made it through the gauntlet - return 0; -} - -void testMaxSetpointResistanceTank() -{ - HPWH hpwh; - double num; - string why; - hpwh.HPWHinit_resTank(); - - ASSERTFALSE(hpwh.isNewSetpointPossible(101., num, why)); // Can't go above boiling - ASSERTTRUE(hpwh.isNewSetpointPossible(99., num, why)); // Can go to near boiling - ASSERTTRUE(hpwh.isNewSetpointPossible(100., num, why)); // Can go to boiling - ASSERTTRUE(hpwh.isNewSetpointPossible(10., num, why)); // Can go low, albiet dumb - ASSERTTRUE(REMaxShouldBe == num); - - // Check this carries over into setting the setpoint - ASSERTTRUE(hpwh.setSetpoint(101.) == HPWH::HPWH_ABORT); // Can't go above boiling - ASSERTTRUE(hpwh.setSetpoint(99.) == 0) -} - -void testScalableCompressor() -{ - HPWH hpwh; - - string input = "TamScalable_SP"; // Just a compressor with R134A - double num; - string why; - - getHPWHObject(hpwh, input); - - ASSERTFALSE(hpwh.isNewSetpointPossible(101., num, why)); // Can't go above boiling - ASSERTTRUE(hpwh.isNewSetpointPossible(99., num, why)); // Can go to near boiling - ASSERTTRUE(hpwh.isNewSetpointPossible(60., num, why)); // Can go to normal - ASSERTTRUE(hpwh.isNewSetpointPossible(100, num, why)); // Can go to programed max - - // Check this carries over into setting the setpoint - ASSERTTRUE(hpwh.setSetpoint(101.) == HPWH::HPWH_ABORT); // Can't go above boiling - ASSERTTRUE(hpwh.setSetpoint(50.) == 0) -} - -void testJustR134ACompressor() -{ - HPWH hpwh; - - string input = "NyleC90A_SP"; // Just a compressor with R134A - double num; - string why; - - getHPWHObject(hpwh, input); - - ASSERTFALSE(hpwh.isNewSetpointPossible(101., num, why)); // Can't go above boiling - ASSERTFALSE(hpwh.isNewSetpointPossible(99., num, why)); // Can't go to near boiling - ASSERTTRUE(HPWH::MAXOUTLET_R134A == num); // Assert we're getting the right number - ASSERTTRUE(hpwh.isNewSetpointPossible(60., num, why)); // Can go to normal - ASSERTTRUE( - hpwh.isNewSetpointPossible(HPWH::MAXOUTLET_R134A, num, why)); // Can go to programed max - - // Check this carries over into setting the setpoint - ASSERTTRUE(hpwh.setSetpoint(101.) == HPWH::HPWH_ABORT); // Can't go above boiling - ASSERTTRUE(hpwh.setSetpoint(50.) == 0) -} - -void testJustR410ACompressor() -{ - HPWH hpwh; - string input = "ColmacCxV_5_SP"; // Just a compressor with R410A - double num; - string why; - - getHPWHObject(hpwh, input); - - ASSERTFALSE(hpwh.isNewSetpointPossible(101., num, why)); // Can't go above boiling - ASSERTFALSE(hpwh.isNewSetpointPossible(99., num, why)); // Can't go to near boiling - ASSERTTRUE(HPWH::MAXOUTLET_R410A == num); // Assert we're getting the right number - ASSERTTRUE(hpwh.isNewSetpointPossible(50., num, why)); // Can go to normal - ASSERTTRUE( - hpwh.isNewSetpointPossible(HPWH::MAXOUTLET_R410A, num, why)); // Can go to programed max - - // Check this carries over into setting the setpoint - ASSERTTRUE(hpwh.setSetpoint(101.) == HPWH::HPWH_ABORT); // Can't go above boiling - ASSERTTRUE(hpwh.setSetpoint(50.) == 0) -} - -void testJustQAHVCompressor() -{ - HPWH hpwh; - string input = "QAHV_N136TAU_HPB_SP"; - double num; - string why; - - getHPWHObject(hpwh, input); - - const double maxQAHVSetpoint = F_TO_C(176.1); - const double qAHVHotSideTemepratureOffset = dF_TO_dC(15.); - - // isNewSetpointPossible should be fine, we aren't changing the setpoint of the Sanden. - ASSERTFALSE(hpwh.isNewSetpointPossible(101., num, why)); // Can't go above boiling - ASSERTFALSE(hpwh.isNewSetpointPossible(99., num, why)); // Can't go to near boiling - - ASSERTTRUE(hpwh.isNewSetpointPossible(60., num, why)); // Can go to normal - - ASSERTFALSE(hpwh.isNewSetpointPossible(maxQAHVSetpoint, num, why)); - ASSERTTRUE( - hpwh.isNewSetpointPossible(maxQAHVSetpoint - qAHVHotSideTemepratureOffset, num, why)); - - // Check this carries over into setting the setpoint. - ASSERTTRUE(hpwh.setSetpoint(101) == HPWH::HPWH_ABORT); - ASSERTTRUE(hpwh.setSetpoint(maxQAHVSetpoint) == HPWH::HPWH_ABORT); - ASSERTTRUE(hpwh.setSetpoint(maxQAHVSetpoint - qAHVHotSideTemepratureOffset) == 0); -} - -void testHybridModel() -{ - HPWH hpwh; - string input = "AOSmithCAHP120"; // Hybrid unit with a compressor with R134A - double num; - string why; - - getHPWHObject(hpwh, input); - - ASSERTFALSE(hpwh.isNewSetpointPossible(101., num, why)); // Can't go above boiling - ASSERTTRUE(hpwh.isNewSetpointPossible(99., num, why)); // Can go to near boiling - ASSERTTRUE(hpwh.isNewSetpointPossible(100., num, why)); // Can go to boiling - ASSERTTRUE(hpwh.isNewSetpointPossible(10., num, why)); // Can go low, albiet dumb - ASSERTTRUE(REMaxShouldBe == num); // Max is boiling - - // Check this carries over into setting the setpoint - ASSERTTRUE(hpwh.setSetpoint(101.) == HPWH::HPWH_ABORT); // Can't go above boiling - ASSERTTRUE(hpwh.setSetpoint(99.) == 0) // Can go lower than boiling though -} - -void testStorageTankSetpoint() -{ - HPWH hpwh; - string input = "StorageTank"; // Hybrid unit with a compressor with R134A - double num; - string why; - - getHPWHObject(hpwh, input); - - // Storage tanks have free reign! - ASSERTTRUE(hpwh.isNewSetpointPossible(101., num, why)); // Can go above boiling! - ASSERTTRUE(hpwh.isNewSetpointPossible(99., num, why)); // Can go to near boiling! - ASSERTTRUE(hpwh.isNewSetpointPossible(10., num, why)); // Can go low, albiet dumb - - // Check this carries over into setting the setpoint - ASSERTTRUE(hpwh.setSetpoint(101.) == 0); // Can't go above boiling - ASSERTTRUE(hpwh.setSetpoint(99.) == 0) // Can go lower than boiling though -} - -void testSetpointFixed() -{ - HPWH hpwh; - string input = "Sanden80"; // Fixed setpoint model - double num, num1; - string why; - - getHPWHObject(hpwh, input); - - // Storage tanks have free reign! - ASSERTFALSE(hpwh.isNewSetpointPossible(101., num, why)); // Can't go above boiling! - ASSERTFALSE(hpwh.isNewSetpointPossible(99., num, why)); // Can't go to near boiling! - ASSERTFALSE(hpwh.isNewSetpointPossible(60., num, why)); // Can't go to normalish - ASSERTFALSE(hpwh.isNewSetpointPossible(10., num, why)); // Can't go low, albiet dumb - - ASSERTTRUE(num == hpwh.getSetpoint()); // Make sure it thinks the max is the setpoint - ASSERTTRUE(hpwh.isNewSetpointPossible( - num, num1, why)) // Check that the setpoint can be set to the setpoint. - - // Check this carries over into setting the setpoint - ASSERTTRUE(hpwh.setSetpoint(101.) == HPWH::HPWH_ABORT); // Can't go above boiling - ASSERTTRUE(hpwh.setSetpoint(99.) == HPWH::HPWH_ABORT) // Can go lower than boiling though - ASSERTTRUE(hpwh.setSetpoint(60.) == HPWH::HPWH_ABORT); // Can't go to normalish - ASSERTTRUE(hpwh.setSetpoint(10.) == HPWH::HPWH_ABORT); // Can't go low, albiet dumb -} - -void testResampling() -{ - - // test extensive resampling - std::vector values(10); - std::vector sampleValues {20., 40., 60., 40., 20.}; - ASSERTTRUE(resampleExtensive(values, sampleValues)); - - // Check some expected values. - ASSERTTRUE(relcmpd(values[1], 10.)); // - ASSERTTRUE(relcmpd(values[5], 30.)); // - - // test intensive resampling - ASSERTTRUE(resampleIntensive(values, sampleValues)); - - // Check some expected values. - ASSERTTRUE(relcmpd(values[1], 20.)); // - ASSERTTRUE(relcmpd(values[5], 60.)); // -} - -void testSetTankTemps() -{ - HPWH hpwh; - getHPWHObject(hpwh, "Rheem2020Prem50"); // 12-node model - - std::vector newTemps; - - // test 1 - std::vector setTemps {10., 60.}; - hpwh.setTankLayerTemperatures(setTemps); - hpwh.getTankTemps(newTemps); - - // Check some expected values. - ASSERTTRUE(relcmpd(newTemps[0], 10.0)); // - ASSERTTRUE(relcmpd(newTemps[11], 60.0)); // - - // test 2 - setTemps = {10., 20., 30., 40., 50., 60.}; - hpwh.setTankLayerTemperatures(setTemps); - hpwh.getTankTemps(newTemps); - - // Check some expected values. - ASSERTTRUE(relcmpd(newTemps[0], 10.)); // - ASSERTTRUE(relcmpd(newTemps[5], 30.)); // - ASSERTTRUE(relcmpd(newTemps[6], 40.)); // - ASSERTTRUE(relcmpd(newTemps[11], 60.)); // - - // test 3 - setTemps = { - 10., 15., 20., 25., 30., 35., 40., 45., 50., 55., 60., 65., 70., 75., 80., 85., 90.}; - hpwh.setTankLayerTemperatures(setTemps); - hpwh.getTankTemps(newTemps); - - // Check some expected values. - ASSERTTRUE(relcmpd(newTemps[2], 25.3, 0.1)); // - ASSERTTRUE(relcmpd(newTemps[8], 67.6, 0.1)); // - - // test 4 - std::size_t nSet = 24; - setTemps.resize(nSet); - double Ti = 20., Tf = 66.; - for (std::size_t i = 0; i < nSet; ++i) - setTemps[i] = Ti + (Tf - Ti) * i / (nSet - 1); - hpwh.setTankLayerTemperatures(setTemps); - hpwh.getTankTemps(newTemps); - - // Check some expected values. - ASSERTTRUE(relcmpd(newTemps[4], 37.)); // - ASSERTTRUE(relcmpd(newTemps[10], 61.)); // - - // test 5 - nSet = 12; - setTemps.resize(nSet); - Ti = 20.; - Tf = 64.; - for (std::size_t i = 0; i < nSet; ++i) - setTemps[i] = Ti + (Tf - Ti) * i / (nSet - 1); - hpwh.setTankLayerTemperatures(setTemps); - hpwh.getTankTemps(newTemps); - - // Check some expected values. - ASSERTTRUE(fabs(newTemps[3] - 32.) < 0.1); // - ASSERTTRUE(fabs(newTemps[11] - 64.) < 0.1); // -} diff --git a/test/testPerformanceMaps.cc b/test/testPerformanceMaps.cc deleted file mode 100644 index f88ced4a..00000000 --- a/test/testPerformanceMaps.cc +++ /dev/null @@ -1,682 +0,0 @@ -/* - unit test to check data input and performance maps are correct -*/ - -#include "HPWH.hh" -#include "testUtilityFcts.cc" - -#include -#include - -using std::cout; -using std::string; - -const double tInOffsetQAHV_dF = 10.; -const double tOutOffsetQAHV_dF = 15.; - -struct performancePointMP -{ - double tairF; - double tinF; - double outputBTUH; -}; - -double getCapacityMP_F_KW(HPWH& hpwh, performancePointMP& point) -{ - return hpwh.getCompressorCapacity( - point.tairF, point.tinF, point.tinF, HPWH::UNITS_KW, HPWH::UNITS_F); -} - -struct performancePointSP -{ - double tairF; - double toutF; - double tinF; - double outputBTUH; -}; - -double getCapacitySP_F_BTUHR(HPWH& hpwh, performancePointSP& point) -{ - return hpwh.getCompressorCapacity( - point.tairF, point.tinF, point.toutF, HPWH::UNITS_BTUperHr, HPWH::UNITS_F); -} - -double getCapacitySP_F_BTUHR(HPWH& hpwh, - performancePointSP& point, - double tInOffSet_dF, - double tOutOffSet_dF) -{ - return hpwh.getCompressorCapacity(point.tairF, - point.tinF - tInOffSet_dF, - point.toutF - tOutOffSet_dF, - HPWH::UNITS_BTUperHr, - HPWH::UNITS_F); -} - -void testCXA15MatchesDataMap() -{ - HPWH hpwh; - string input = "ColmacCxA_15_SP"; - double capacity_kW, capacity_BTUperHr; - // get preset model - getHPWHObject(hpwh, input); - - // test hot ////////////////////////// - double airTempF = 100.; - double waterTempF = 125.; - double setpointF = 150.; - double capacityData_kW = 52.779317; - - capacity_BTUperHr = hpwh.getCompressorCapacity( - airTempF, waterTempF, setpointF, HPWH::UNITS_BTUperHr, HPWH::UNITS_F); - capacity_kW = - hpwh.getCompressorCapacity(F_TO_C(airTempF), F_TO_C(waterTempF), F_TO_C(setpointF)); - - ASSERTTRUE(relcmpd(KWH_TO_BTU(capacityData_kW), capacity_BTUperHr)); - ASSERTTRUE(relcmpd(capacityData_kW, capacity_kW)); - - // test middle //////////////// - airTempF = 80.; - waterTempF = 40.; - setpointF = 150.; - capacityData_kW = 44.962957379; - - capacity_BTUperHr = hpwh.getCompressorCapacity( - airTempF, waterTempF, setpointF, HPWH::UNITS_BTUperHr, HPWH::UNITS_F); - capacity_kW = - hpwh.getCompressorCapacity(F_TO_C(airTempF), F_TO_C(waterTempF), F_TO_C(setpointF)); - - ASSERTTRUE(relcmpd(KWH_TO_BTU(capacityData_kW), capacity_BTUperHr)); - ASSERTTRUE(relcmpd(capacityData_kW, capacity_kW)); - - // test cold //////////////// - airTempF = 60.; - waterTempF = 40.; - setpointF = 125.; - capacityData_kW = 37.5978306881; - - capacity_BTUperHr = hpwh.getCompressorCapacity( - airTempF, waterTempF, setpointF, HPWH::UNITS_BTUperHr, HPWH::UNITS_F); - capacity_kW = - hpwh.getCompressorCapacity(F_TO_C(airTempF), F_TO_C(waterTempF), F_TO_C(setpointF)); - - ASSERTTRUE(relcmpd(KWH_TO_BTU(capacityData_kW), capacity_BTUperHr)); - ASSERTTRUE(relcmpd(capacityData_kW, capacity_kW)); -} - -void testCXA30MatchesDataMap() -{ - HPWH hpwh; - string input = "ColmacCxA_30_SP"; - double capacity_kW, capacity_BTUperHr; - // get preset model - getHPWHObject(hpwh, input); - - // test hot ////////////////////////// - double airTempF = 100.; - double waterTempF = 125.; - double setpointF = 150.; - double capacityData_kW = 105.12836804; - - capacity_BTUperHr = hpwh.getCompressorCapacity( - airTempF, waterTempF, setpointF, HPWH::UNITS_BTUperHr, HPWH::UNITS_F); - capacity_kW = - hpwh.getCompressorCapacity(F_TO_C(airTempF), F_TO_C(waterTempF), F_TO_C(setpointF)); - - ASSERTTRUE(relcmpd(KWH_TO_BTU(capacityData_kW), capacity_BTUperHr)); - ASSERTTRUE(relcmpd(capacityData_kW, capacity_kW)); - - // test middle //////////////// - airTempF = 80.; - waterTempF = 40.; - setpointF = 150.; - capacityData_kW = 89.186101453; - - capacity_BTUperHr = hpwh.getCompressorCapacity( - airTempF, waterTempF, setpointF, HPWH::UNITS_BTUperHr, HPWH::UNITS_F); - capacity_kW = - hpwh.getCompressorCapacity(F_TO_C(airTempF), F_TO_C(waterTempF), F_TO_C(setpointF)); - - ASSERTTRUE(relcmpd(KWH_TO_BTU(capacityData_kW), capacity_BTUperHr)); - ASSERTTRUE(relcmpd(capacityData_kW, capacity_kW)); - - // test cold //////////////// - airTempF = 60.; - waterTempF = 40.; - setpointF = 125.; - capacityData_kW = 74.2437689948; - - capacity_BTUperHr = hpwh.getCompressorCapacity( - airTempF, waterTempF, setpointF, HPWH::UNITS_BTUperHr, HPWH::UNITS_F); - capacity_kW = - hpwh.getCompressorCapacity(F_TO_C(airTempF), F_TO_C(waterTempF), F_TO_C(setpointF)); - - ASSERTTRUE(relcmpd(KWH_TO_BTU(capacityData_kW), capacity_BTUperHr)); - ASSERTTRUE(relcmpd(capacityData_kW, capacity_kW)); -} - -// Colmac MP perfmaps tests -void testCXV5MPMatchesDataMap() -{ - HPWH hpwh; - string input = "ColmacCxV_5_MP"; - performancePointMP checkPoint; - - // get preset model - getHPWHObject(hpwh, input); - - // test some points outside of defrost //////////////// - checkPoint = {10.0, 60.0, 8.7756391}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); - - checkPoint = {10.0, 102.0, 9.945545}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); - - checkPoint = {70.0, 74.0, 19.09682784}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); - - checkPoint = {70.0, 116.0, 18.97090763}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); - - checkPoint = {100.0, 116.0, 24.48703111}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); -} - -void testCXA10MPMatchesDataMap() -{ - HPWH hpwh; - string input = "ColmacCxA_10_MP"; - performancePointMP checkPoint; - - // get preset model - getHPWHObject(hpwh, input); - - // test some points outside of defrost //////////////// - checkPoint = {60.0, 66.0, 29.36581754}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); - - checkPoint = {60.0, 114.0, 27.7407144}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); - - checkPoint = {80.0, 66.0, 37.4860496}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); - - checkPoint = {80.0, 114.0, 35.03416199}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); - - checkPoint = {100.0, 66.0, 46.63144}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); - - checkPoint = {100.0, 114.0, 43.4308219}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); -} - -void testCXA15MPMatchesDataMap() -{ - HPWH hpwh; - string input = "ColmacCxA_15_MP"; - performancePointMP checkPoint; - - // get preset model - getHPWHObject(hpwh, input); - - // test some points outside of defrost //////////////// - checkPoint = {60.0, 66.0, 37.94515042}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); - - checkPoint = {60.0, 114.0, 35.2295393}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); - - checkPoint = {80.0, 66.0, 50.360549115}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); - - checkPoint = {80.0, 114.0, 43.528417017}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); - - checkPoint = {100.0, 66.0, 66.2675493}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); - - checkPoint = {100.0, 114.0, 55.941855}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); -} - -void testCXA20MPMatchesDataMap() -{ - HPWH hpwh; - string input = "ColmacCxA_20_MP"; - performancePointMP checkPoint; - - // get preset model - getHPWHObject(hpwh, input); - - // test some points outside of defrost //////////////// - checkPoint = {60.0, 66.0, 57.0994624}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); - - checkPoint = {60.0, 114.0, 53.554293}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); - - checkPoint = {80.0, 66.0, 73.11242842}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); - - checkPoint = {80.0, 114.0, 68.034677}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); - - checkPoint = {100.0, 66.0, 90.289474295}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); - - checkPoint = {100.0, 114.0, 84.69323}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); -} - -void testCXA25MPMatchesDataMap() -{ - HPWH hpwh; - string input = "ColmacCxA_25_MP"; - performancePointMP checkPoint; - - // get preset model - getHPWHObject(hpwh, input); - - // test some points outside of defrost //////////////// - checkPoint = {60.0, 66.0, 67.28116620}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); - - checkPoint = {60.0, 114.0, 63.5665037}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); - - checkPoint = {80.0, 66.0, 84.9221285742}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); - - checkPoint = {80.0, 114.0, 79.6237088}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); - - checkPoint = {100.0, 66.0, 103.43268186}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); - - checkPoint = {100.0, 114.0, 97.71458413}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); -} - -void testCXA30MPMatchesDataMap() -{ - HPWH hpwh; - string input = "ColmacCxA_30_MP"; - performancePointMP checkPoint; - - // get preset model - getHPWHObject(hpwh, input); - - // test some points outside of defrost //////////////// - checkPoint = {60.0, 66.0, 76.741462845}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); - - checkPoint = {60.0, 114.0, 73.66879620}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); - - checkPoint = {80.0, 66.0, 94.863116775}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); - - checkPoint = {80.0, 114.0, 90.998904269}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); - - checkPoint = {100.0, 66.0, 112.864628}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); - - checkPoint = {100.0, 114.0, 109.444451}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); -} - -void testRheemHPHD60() -{ - // MODELS_RHEEM_HPHD60HNU_201_MP - // MODELS_RHEEM_HPHD60VNU_201_MP - HPWH hpwh; - string input = "RheemHPHD60"; - performancePointMP checkPoint; - - // get preset model - getHPWHObject(hpwh, input); - - // test some points outside of defrost //////////////// - checkPoint = {66.6666666, 60.0, 16.785535996}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); - checkPoint = {66.6666666, 120.0, 16.76198953}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); - checkPoint = {88.3333333, 80.0, 20.8571194294}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); - checkPoint = {110.0, 100.0, 24.287512}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); -} - -void testRheemHPHD135() -{ - // MODELS_RHEEM_HPHD135HNU_483_MP - // MODELS_RHEEM_HPHD135VNU_483_MP - HPWH hpwh; - string input = "RheemHPHD135"; - performancePointMP checkPoint; - - // get preset model - getHPWHObject(hpwh, input); - - // test some points outside of defrost //////////////// - checkPoint = {66.6666666, 80.0, 38.560161199}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); - checkPoint = {66.6666666, 140.0, 34.70681846}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); - checkPoint = {88.3333333, 140.0, 42.40407101}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); - checkPoint = {110.0, 120.0, 54.3580927}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); -} - -void testNyleC60AMP() -{ - HPWH hpwh; - string input = "NyleC60A_MP"; - performancePointMP checkPoint; - - // get preset model - getHPWHObject(hpwh, input); - - // test some points outside of defrost //////////////// - checkPoint = {60.0, 60.0, 16.11}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); - checkPoint = {80.0, 60.0, 21.33}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); - checkPoint = {90.0, 130.0, 19.52}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); -} - -void testNyleC90AMP() -{ - HPWH hpwh; - string input = "NyleC90A_MP"; - performancePointMP checkPoint; - - // get preset model - getHPWHObject(hpwh, input); - - // test some points outside of defrost //////////////// - checkPoint = {60.0, 60.0, 28.19}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); - checkPoint = {80.0, 60.0, 37.69}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); - checkPoint = {90.0, 130.0, 36.27}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); -} - -void testNyleC125AMP() -{ - HPWH hpwh; - string input = "NyleC125A_MP"; - performancePointMP checkPoint; - - // get preset model - getHPWHObject(hpwh, input); - - // test some points outside of defrost //////////////// - checkPoint = {60.0, 60.0, 36.04}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); - checkPoint = {80.0, 60.0, 47.86}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); - checkPoint = {90.0, 130.0, 43.80}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); -} - -void testNyleC185AMP() -{ - HPWH hpwh; - string input = "NyleC185A_MP"; - performancePointMP checkPoint; - - // get preset model - getHPWHObject(hpwh, input); - - // test some points outside of defrost //////////////// - checkPoint = {60.0, 60.0, 55.00}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); - checkPoint = {80.0, 60.0, 74.65}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); - checkPoint = {90.0, 130.0, 67.52}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); -} - -void testNyleC250AMP() -{ - HPWH hpwh; - string input = "NyleC250A_MP"; - performancePointMP checkPoint; - - // get preset model - getHPWHObject(hpwh, input); - - // test some points outside of defrost //////////////// - checkPoint = {60.0, 60.0, 75.70}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); - checkPoint = {80.0, 60.0, 103.40}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); - checkPoint = {90.0, 130.0, 77.89}; - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint))); -} - -void testQAHVMatchesDataMap() -{ - HPWH hpwh; - string input = "QAHV_N136TAU_HPB_SP"; - performancePointSP checkPoint; // tairF, toutF, tinF, outputW - double outputBTUH; - getHPWHObject(hpwh, input); - - // test - checkPoint = {-13.0, 140.0, 41.0, 66529.49616}; - outputBTUH = getCapacitySP_F_BTUHR(hpwh, checkPoint, tInOffsetQAHV_dF, tOutOffsetQAHV_dF); - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, outputBTUH)); - // test - checkPoint = {-13.0, 176.0, 41.0, 65872.597448}; - ASSERTTRUE(getCapacitySP_F_BTUHR(hpwh, checkPoint) == - HPWH::HPWH_ABORT); // max setpoint without adjustment forces error - ASSERTTRUE( - relcmpd(checkPoint.outputBTUH, - getCapacitySP_F_BTUHR(hpwh, checkPoint, tInOffsetQAHV_dF, tOutOffsetQAHV_dF))); - // test - checkPoint = {-13.0, 176.0, 84.2, 55913.249232}; - ASSERTTRUE( - relcmpd(checkPoint.outputBTUH, - getCapacitySP_F_BTUHR(hpwh, checkPoint, tInOffsetQAHV_dF, tOutOffsetQAHV_dF))); - // test - checkPoint = {14.0, 176.0, 84.2, 92933.01932}; - ASSERTTRUE( - relcmpd(checkPoint.outputBTUH, - getCapacitySP_F_BTUHR(hpwh, checkPoint, tInOffsetQAHV_dF, tOutOffsetQAHV_dF))); - // test - checkPoint = {42.8, 140.0, 41.0, 136425.98804}; - ASSERTTRUE( - relcmpd(checkPoint.outputBTUH, - getCapacitySP_F_BTUHR(hpwh, checkPoint, tInOffsetQAHV_dF, tOutOffsetQAHV_dF))); - // test - checkPoint = {50.0, 140.0, 41.0, 136425.98804}; - ASSERTTRUE( - relcmpd(checkPoint.outputBTUH, - getCapacitySP_F_BTUHR(hpwh, checkPoint, tInOffsetQAHV_dF, tOutOffsetQAHV_dF))); - // test - checkPoint = {50.0, 176.0, 84.2, 136564.470884}; - ASSERTTRUE( - relcmpd(checkPoint.outputBTUH, - getCapacitySP_F_BTUHR(hpwh, checkPoint, tInOffsetQAHV_dF, tOutOffsetQAHV_dF))); - // test - checkPoint = {60.8, 158.0, 84.2, 136461.998288}; - ASSERTTRUE( - relcmpd(checkPoint.outputBTUH, - getCapacitySP_F_BTUHR(hpwh, checkPoint, tInOffsetQAHV_dF, tOutOffsetQAHV_dF))); - // test - checkPoint = {71.6, 158.0, 48.2, 136498.001712}; - ASSERTTRUE( - relcmpd(checkPoint.outputBTUH, - getCapacitySP_F_BTUHR(hpwh, checkPoint, tInOffsetQAHV_dF, tOutOffsetQAHV_dF))); - - // test constant with setpoint between 140 and 158 - checkPoint = {71.6, 149.0, 48.2, 136498.001712}; - ASSERTTRUE( - relcmpd(checkPoint.outputBTUH, - getCapacitySP_F_BTUHR(hpwh, checkPoint, tInOffsetQAHV_dF, tOutOffsetQAHV_dF))); - // test - checkPoint = {82.4, 176.0, 41.0, 136557.496756}; - ASSERTTRUE( - relcmpd(checkPoint.outputBTUH, - getCapacitySP_F_BTUHR(hpwh, checkPoint, tInOffsetQAHV_dF, tOutOffsetQAHV_dF))); - // test - checkPoint = {104.0, 140.0, 62.6, 136480}; - ASSERTTRUE( - relcmpd(checkPoint.outputBTUH, - getCapacitySP_F_BTUHR(hpwh, checkPoint, tInOffsetQAHV_dF, tOutOffsetQAHV_dF))); - // test - checkPoint = {104.0, 158.0, 62.6, 136480}; - ASSERTTRUE( - relcmpd(checkPoint.outputBTUH, - getCapacitySP_F_BTUHR(hpwh, checkPoint, tInOffsetQAHV_dF, tOutOffsetQAHV_dF))); - // test - checkPoint = {104.0, 176.0, 84.2, 136564.470884}; - ASSERTTRUE( - relcmpd(checkPoint.outputBTUH, - getCapacitySP_F_BTUHR(hpwh, checkPoint, tInOffsetQAHV_dF, tOutOffsetQAHV_dF))); -} - -// Also test QAHV constant extrpolation at high air temperatures AND linear extrapolation to hot -// water temperatures! -void testQAHVExtrapolates() -{ - HPWH hpwh; - string input = "QAHV_N136TAU_HPB_SP"; - performancePointSP checkPoint; // tairF, toutF, tinF, outputW - getHPWHObject(hpwh, input); - - // test linear along Tin - checkPoint = {-13.0, 140.0, 36.0, 66529.49616}; - ASSERTTRUE( - checkPoint.outputBTUH < - getCapacitySP_F_BTUHR( - hpwh, checkPoint, tInOffsetQAHV_dF, tOutOffsetQAHV_dF)); // Check output has increased - // test linear along Tin - checkPoint = {-13.0, 140.0, 100.0, 66529.49616}; - ASSERTTRUE( - checkPoint.outputBTUH > - getCapacitySP_F_BTUHR( - hpwh, checkPoint, tInOffsetQAHV_dF, tOutOffsetQAHV_dF)); // Check output has decreased - // test linear along Tin - checkPoint = {-13.0, 176.0, 36.0, 65872.597448}; - ASSERTTRUE( - checkPoint.outputBTUH < - getCapacitySP_F_BTUHR( - hpwh, checkPoint, tInOffsetQAHV_dF, tOutOffsetQAHV_dF)); // Check output has increased - // test linear along Tin - checkPoint = {-13.0, 176.0, 100.0, 55913.249232}; - ASSERTTRUE(checkPoint.outputBTUH > - getCapacitySP_F_BTUHR(hpwh, - checkPoint, - tInOffsetQAHV_dF, - tOutOffsetQAHV_dF)); // Check output has decreased at high Tin - // test linear along Tin - checkPoint = {10.4, 140.0, 111., 89000.085396}; - ASSERTTRUE(checkPoint.outputBTUH > - getCapacitySP_F_BTUHR(hpwh, - checkPoint, - tInOffsetQAHV_dF, - tOutOffsetQAHV_dF)); // Check output has decreased at high Tin - // test linear along Tin - checkPoint = {64.4, 158.0, 100, 136461.998288}; - ASSERTTRUE(checkPoint.outputBTUH > - getCapacitySP_F_BTUHR(hpwh, - checkPoint, - tInOffsetQAHV_dF, - tOutOffsetQAHV_dF)); // Check output has decreased at high Tin - // test linear along Tin - checkPoint = {86.0, 158.0, 100, 136461.998288}; - ASSERTTRUE(checkPoint.outputBTUH > - getCapacitySP_F_BTUHR(hpwh, - checkPoint, - tInOffsetQAHV_dF, - tOutOffsetQAHV_dF)); // Check output has decreased at high Tin - // test linear along Tin - checkPoint = {104.0, 176.0, 100., 136564.470884}; - ASSERTTRUE(checkPoint.outputBTUH > - getCapacitySP_F_BTUHR(hpwh, - checkPoint, - tInOffsetQAHV_dF, - tOutOffsetQAHV_dF)); // Check output has decreased at high Tin - - // test const along Tair - checkPoint = {110.0, 140.0, 62.6, 136480}; - ASSERTTRUE( - relcmpd(checkPoint.outputBTUH, - getCapacitySP_F_BTUHR(hpwh, checkPoint, tInOffsetQAHV_dF, tOutOffsetQAHV_dF))); - - // test const along Tair - checkPoint = {114.0, 176.0, 84.2, 136564.470884}; - ASSERTTRUE( - relcmpd(checkPoint.outputBTUH, - getCapacitySP_F_BTUHR(hpwh, checkPoint, tInOffsetQAHV_dF, tOutOffsetQAHV_dF))); - - checkPoint = {114.0, 200.0, 84.2, 136564.470884}; - double output = getCapacitySP_F_BTUHR(hpwh, checkPoint, tInOffsetQAHV_dF, tOutOffsetQAHV_dF); - ASSERTTRUE(output == HPWH::HPWH_ABORT); -} - -void testSanden() -{ - HPWH hpwh; - string input = "Sanden120"; - performancePointSP checkPoint; // tairF, toutF, tinF, outputW - double outputBTUH; - getHPWHObject(hpwh, input); - - // nominal - checkPoint = {60, 149.0, 41.0, 15059.59167}; - outputBTUH = hpwh.getCompressorCapacity( - checkPoint.tairF, checkPoint.tinF, checkPoint.toutF, HPWH::UNITS_BTUperHr, HPWH::UNITS_F); - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, outputBTUH)); - - // Cold outlet temperature - checkPoint = {60, 125.0, 41.0, 15059.59167}; - outputBTUH = hpwh.getCompressorCapacity( - checkPoint.tairF, checkPoint.tinF, checkPoint.toutF, HPWH::UNITS_BTUperHr, HPWH::UNITS_F); - ASSERTTRUE(relcmpd(checkPoint.outputBTUH, outputBTUH)); - - // tests fails when output high - checkPoint = {60, 200, 41.0, 15059.59167}; - outputBTUH = hpwh.getCompressorCapacity( - checkPoint.tairF, checkPoint.tinF, checkPoint.toutF, HPWH::UNITS_BTUperHr, HPWH::UNITS_F); - ASSERTTRUE(outputBTUH == HPWH::HPWH_ABORT); -} - -int main(int, char**) -{ - testSanden(); // check can still work with HPWH::getCapacity() as expected - - testQAHVMatchesDataMap(); // Test QAHV grid data input correctly - testQAHVExtrapolates(); // Test QAHV grid data extrapolate correctly - - // Tests that the correct capacity is returned for specific equipement that matches the data set - testCXA15MatchesDataMap(); - testCXA30MatchesDataMap(); - - testCXV5MPMatchesDataMap(); - testCXA10MPMatchesDataMap(); - testCXA15MPMatchesDataMap(); - testCXA20MPMatchesDataMap(); - testCXA25MPMatchesDataMap(); - testCXA30MPMatchesDataMap(); - - testRheemHPHD135(); - testRheemHPHD60(); - - testNyleC60AMP(); - testNyleC90AMP(); - testNyleC125AMP(); - testNyleC185AMP(); - testNyleC250AMP(); - - // Made it through the gauntlet - return 0; -} diff --git a/test/testResistanceFcts.cc b/test/testResistanceFcts.cc deleted file mode 100644 index 980a3c93..00000000 --- a/test/testResistanceFcts.cc +++ /dev/null @@ -1,273 +0,0 @@ - - -/*unit test for isTankSizeFixed() functionality - * - * - * - */ -#include "HPWH.hh" -#include "testUtilityFcts.cc" - -#include -#include - -using std::cout; -using std::string; - -void testSetResistanceCapacityErrorChecks() -{ - HPWH hpwhHP1, hpwhR; - string input = "ColmacCxA_30_SP"; - - // get preset model - getHPWHObject(hpwhHP1, input); - - ASSERTTRUE(hpwhHP1.setResistanceCapacity(100.) == HPWH::HPWH_ABORT); // Need's to be scalable - - input = "restankRealistic"; - // get preset model - getHPWHObject(hpwhR, input); - ASSERTTRUE(hpwhR.setResistanceCapacity(-100.) == HPWH::HPWH_ABORT); - ASSERTTRUE(hpwhR.setResistanceCapacity(100., 3) == HPWH::HPWH_ABORT); - ASSERTTRUE(hpwhR.setResistanceCapacity(100., 30000) == HPWH::HPWH_ABORT); - ASSERTTRUE(hpwhR.setResistanceCapacity(100., -3) == HPWH::HPWH_ABORT); - ASSERTTRUE(hpwhR.setResistanceCapacity(100., 0, HPWH::UNITS_F) == HPWH::HPWH_ABORT); -} - -void testGetSetResistanceErrors() -{ - HPWH hpwh; - double lowerElementPower_W = 1000; - double lowerElementPower = lowerElementPower_W / 1000; - hpwh.HPWHinit_resTank(100., 0.95, 0., lowerElementPower_W); - - double returnVal; - returnVal = hpwh.getResistanceCapacity(0, HPWH::UNITS_KW); // lower - ASSERTTRUE(relcmpd(returnVal, lowerElementPower)); - returnVal = hpwh.getResistanceCapacity(-1, HPWH::UNITS_KW); // both, - ASSERTTRUE(relcmpd(returnVal, lowerElementPower)); - returnVal = hpwh.getResistanceCapacity(1, HPWH::UNITS_KW); // higher doesn't exist - ASSERTTRUE(returnVal == HPWH::HPWH_ABORT); -} - -void testCommercialTankInitErrors() -{ - HPWH hpwh; - // init model - ASSERTTRUE(hpwh.HPWHinit_resTankGeneric(-800., 10., 100., 100.) == - HPWH::HPWH_ABORT); // negative volume - ASSERTTRUE(hpwh.HPWHinit_resTankGeneric(800., 10., -100., 100.) == - HPWH::HPWH_ABORT); // negative element - ASSERTTRUE(hpwh.HPWHinit_resTankGeneric(800., 10., 100., -100.) == - HPWH::HPWH_ABORT); // negative element - ASSERTTRUE(hpwh.HPWHinit_resTankGeneric(800., -10., 100., 100.) == - HPWH::HPWH_ABORT); // negative r value - ASSERTTRUE(hpwh.HPWHinit_resTankGeneric(800., 0., 100., 100.) == HPWH::HPWH_ABORT); // 0 r value - ASSERTTRUE(hpwh.HPWHinit_resTankGeneric(800., 10., 0., 0.) == - HPWH::HPWH_ABORT); // Check needs one element -} - -void testGetNumResistanceElements() -{ - HPWH hpwh; - - hpwh.HPWHinit_resTankGeneric(800., 10., 0., 1000.); - ASSERTTRUE(hpwh.getNumResistanceElements() == 1); // Check 1 elements - hpwh.HPWHinit_resTankGeneric(800., 10., 1000., 0.); - ASSERTTRUE(hpwh.getNumResistanceElements() == 1); // Check 1 elements - hpwh.HPWHinit_resTankGeneric(800., 10., 1000., 1000.); - ASSERTTRUE(hpwh.getNumResistanceElements() == 2); // Check 2 elements -} - -void testGetResistancePositionInRETank() -{ - HPWH hpwh; - - hpwh.HPWHinit_resTankGeneric(800., 10., 0., 1000.); - ASSERTTRUE(hpwh.getResistancePosition(0) == 0); // Check lower element is there - ASSERTTRUE(hpwh.getResistancePosition(1) == HPWH::HPWH_ABORT); // Check no element - ASSERTTRUE(hpwh.getResistancePosition(2) == HPWH::HPWH_ABORT); // Check no element - - hpwh.HPWHinit_resTankGeneric(800., 10., 1000., 0.); - ASSERTTRUE(hpwh.getResistancePosition(0) == 8); // Check upper element there - ASSERTTRUE(hpwh.getResistancePosition(1) == HPWH::HPWH_ABORT); // Check no elements - ASSERTTRUE(hpwh.getResistancePosition(2) == HPWH::HPWH_ABORT); // Check no elements - - hpwh.HPWHinit_resTankGeneric(800., 10., 1000., 1000.); - ASSERTTRUE(hpwh.getResistancePosition(0) == 8); // Check upper element there - ASSERTTRUE(hpwh.getResistancePosition(1) == 0); // Check lower element is there - ASSERTTRUE(hpwh.getResistancePosition(2) == HPWH::HPWH_ABORT); // Check 0 elements} -} - -void testGetResistancePositionInCompressorTank() -{ - HPWH hpwh; - - string input = "TamScalable_SP"; - // get preset model - getHPWHObject(hpwh, input); - - ASSERTTRUE(hpwh.getResistancePosition(0) == 9); // Check top elements - ASSERTTRUE(hpwh.getResistancePosition(1) == 0); // Check bottom elements - ASSERTTRUE(hpwh.getResistancePosition(2) == HPWH::HPWH_ABORT); // Check compressor isn't RE - ASSERTTRUE(hpwh.getResistancePosition(-1) == HPWH::HPWH_ABORT); // Check out of bounds - ASSERTTRUE(hpwh.getResistancePosition(1000) == HPWH::HPWH_ABORT); // Check out of bounds -} - -void testCommercialTankErrorsWithBottomElement() -{ - HPWH hpwh; - double elementPower_kW = 10.; // KW - // init model - hpwh.HPWHinit_resTankGeneric(800., 10., 0., elementPower_kW * 1000.); - - // Check only lowest setting works - double factor = 3.; - // set both, but really only one - ASSERTTRUE(hpwh.setResistanceCapacity(factor * elementPower_kW, -1, HPWH::UNITS_KW) == - 0); // Check sets - ASSERTTRUE(relcmpd(hpwh.getResistanceCapacity(-1, HPWH::UNITS_KW), - factor * elementPower_kW)); // Check gets just bottom with both - ASSERTTRUE(relcmpd(hpwh.getResistanceCapacity(0, HPWH::UNITS_KW), - factor * elementPower_kW)); // Check gets bottom with bottom - ASSERTTRUE(hpwh.getResistanceCapacity(1, HPWH::UNITS_KW) == - HPWH::HPWH_ABORT); // only have one element - - // set lowest - factor = 4.; - ASSERTTRUE(hpwh.setResistanceCapacity(factor * elementPower_kW, 0, HPWH::UNITS_KW) == - 0); // Set just bottom - ASSERTTRUE(relcmpd(hpwh.getResistanceCapacity(-1, HPWH::UNITS_KW), - factor * elementPower_kW)); // Check gets just bottom with both - ASSERTTRUE(relcmpd(hpwh.getResistanceCapacity(0, HPWH::UNITS_KW), - factor * elementPower_kW)); // Check gets bottom with bottom - ASSERTTRUE(hpwh.getResistanceCapacity(1, HPWH::UNITS_KW) == - HPWH::HPWH_ABORT); // only have one element - - ASSERTTRUE(hpwh.setResistanceCapacity(factor * elementPower_kW, 1, HPWH::UNITS_KW) == - HPWH::HPWH_ABORT); // set top returns error -} -void testCommercialTankErrorsWithTopElement() -{ - HPWH hpwh; - double elementPower_kW = 10.; // KW - // init model - hpwh.HPWHinit_resTankGeneric(800., 10., elementPower_kW * 1000., 0.); - - // Check only bottom setting works - double factor = 3.; - // set both, but only bottom really. - ASSERTTRUE(hpwh.setResistanceCapacity(factor * elementPower_kW, -1, HPWH::UNITS_KW) == - 0); // Check sets - ASSERTTRUE( - relcmpd(hpwh.getResistanceCapacity(-1, HPWH::UNITS_KW), - factor * elementPower_kW)); // Check gets just bottom which is now top with both - ASSERTTRUE(relcmpd(hpwh.getResistanceCapacity(0, HPWH::UNITS_KW), - factor * elementPower_kW)); // Check the lower and only element - ASSERTTRUE(hpwh.getResistanceCapacity(1, HPWH::UNITS_KW) == - HPWH::HPWH_ABORT); // error on non existant element - - // set top - factor = 4.; - ASSERTTRUE(hpwh.setResistanceCapacity(factor * elementPower_kW, 0, HPWH::UNITS_KW) == - 0); // only one element to set - ASSERTTRUE( - relcmpd(hpwh.getResistanceCapacity(0, HPWH::UNITS_KW), - factor * elementPower_kW)); // Check gets just bottom which is now top with both - ASSERTTRUE(hpwh.getResistanceCapacity(1, HPWH::UNITS_KW) == - HPWH::HPWH_ABORT); // error on non existant bottom - - // set bottom returns error - ASSERTTRUE(hpwh.setResistanceCapacity(factor * elementPower_kW, 2, HPWH::UNITS_KW) == - HPWH::HPWH_ABORT); -} - -struct InsulationPoint -{ - double volume_L; - double rValue_IP; - double expectedUA_SI; -}; - -#define R_TO_RSI(rvalue) rvalue * 0.176110 -#define INITGEN(point) \ - hpwh.HPWHinit_resTankGeneric(point.volume_L, \ - R_TO_RSI(point.rValue_IP), \ - elementPower_kW * 1000., \ - elementPower_kW * 1000.) -void testCommercialTankInit() -{ - HPWH hpwh; - double elementPower_kW = 10.; // KW - double UA; - const InsulationPoint testPoint800 = {800., 10., 10.500366}; - const InsulationPoint testPoint2 = {2., 6., 0.322364}; - const InsulationPoint testPoint50 = {50., 12., 1.37808}; - const InsulationPoint testPoint200 = {200., 16., 2.604420}; - const InsulationPoint testPoint200B = {200., 6., 6.94512163}; - const InsulationPoint testPoint2000 = {2000., 16., 12.0886496}; - const InsulationPoint testPoint20000 = {20000., 6., 149.628109}; - - // Check UA is as expected at 800 gal - INITGEN(testPoint800); - hpwh.getUA(UA); - ASSERTTRUE(relcmpd(UA, testPoint800.expectedUA_SI, 0.0001)); - // Check UA independent of elements - hpwh.HPWHinit_resTankGeneric( - testPoint800.volume_L, R_TO_RSI(testPoint800.rValue_IP), elementPower_kW, elementPower_kW); - hpwh.getUA(UA); - ASSERTTRUE(relcmpd(UA, testPoint800.expectedUA_SI, 0.0001)); - - // Check UA is as expected at 2 gal - INITGEN(testPoint2); - hpwh.getUA(UA); - ASSERTTRUE(relcmpd(UA, testPoint2.expectedUA_SI, 0.0001)); - - // Check UA is as expected at 50 gal - INITGEN(testPoint50); - hpwh.getUA(UA); - ASSERTTRUE(relcmpd(UA, testPoint50.expectedUA_SI, 0.0001)); - - // Check UA is as expected at 200 gal - INITGEN(testPoint200); - hpwh.getUA(UA); - ASSERTTRUE(relcmpd(UA, testPoint200.expectedUA_SI, 0.0001)); - - INITGEN(testPoint200B); - hpwh.getUA(UA); - ASSERTTRUE(relcmpd(UA, testPoint200B.expectedUA_SI, 0.0001)); - - // Check UA is as expected at 2000 gal - INITGEN(testPoint2000); - hpwh.getUA(UA); - ASSERTTRUE(relcmpd(UA, testPoint2000.expectedUA_SI, 0.0001)); - - // Check UA is as expected at 20000 gal - INITGEN(testPoint20000); - hpwh.getUA(UA); - ASSERTTRUE(relcmpd(UA, testPoint20000.expectedUA_SI, 0.0001)); -} -#undef INITGEN -#undef R_TO_RSI - -int main(int, char**) -{ - testSetResistanceCapacityErrorChecks(); // Check the resistance reset throws errors when - // expected. - - testGetSetResistanceErrors(); // Check can make ER residential tank with one lower element, and - // can't set/get upper - - testCommercialTankInitErrors(); // test it inits as expected - testGetNumResistanceElements(); // unit test on getNumResistanceElements() - testGetResistancePositionInRETank(); // unit test on getResistancePosition() for an RE tank - testGetResistancePositionInCompressorTank(); // unit test on getResistancePosition() for a - // compressor - - testCommercialTankErrorsWithBottomElement(); // - testCommercialTankErrorsWithTopElement(); - testCommercialTankInit(); // - - // Made it through the gauntlet - return 0; -} diff --git a/test/testScaleHPWH.cc b/test/testScaleHPWH.cc deleted file mode 100644 index 49d58eb6..00000000 --- a/test/testScaleHPWH.cc +++ /dev/null @@ -1,578 +0,0 @@ - - -/*unit test for isTankSizeFixed() functionality - * - * - * - */ -#include "HPWH.hh" -#include "testUtilityFcts.cc" - -#include -#include - -using std::cout; -using std::string; - -struct performance -{ - double input, output, cop; -}; - -void getCompressorPerformance( - HPWH& hpwh, performance& point, double waterTempC, double airTempC, double setpointC) -{ - if (hpwh.isCompressorMultipass()) - { // Multipass capacity looks at the average of the - // temperature of the lift - hpwh.setSetpoint((waterTempC + setpointC) / 2.); - } - else - { - hpwh.setSetpoint(waterTempC); - } - hpwh.resetTankToSetpoint(); // Force tank cold - hpwh.setSetpoint(setpointC); - - // Run the step - hpwh.runOneStep(waterTempC, // Inlet water temperature (C ) - 0., // Flow in gallons - airTempC, // Ambient Temp (C) - airTempC, // External Temp (C) - // HPWH::DR_TOO // DR Status (now an enum. Fixed for now as allow) - (HPWH::DR_TOO | HPWH::DR_LOR) // DR Status (now an enum. Fixed for now as allow) - ); - - // Check the heat in and out of the compressor - point.input = hpwh.getNthHeatSourceEnergyInput(hpwh.getCompressorIndex()); - point.output = hpwh.getNthHeatSourceEnergyOutput(hpwh.getCompressorIndex()); - point.cop = point.output / point.input; -} - -void scaleCapacityCOP(HPWH& hpwh, - double scaleInput, - double scaleCOP, - performance& point0, - performance& point1, - double waterTempC = F_TO_C(63), - double airTempC = F_TO_C(77), - double setpointC = F_TO_C(135)) -{ - // Get peformance unscalled - getCompressorPerformance(hpwh, point0, waterTempC, airTempC, setpointC); - - // Scale the compressor - int val = hpwh.setScaleHPWHCapacityCOP(scaleInput, scaleCOP); - ASSERTTRUE(val == 0); - - // Get the scaled performance - getCompressorPerformance(hpwh, point1, waterTempC, airTempC, setpointC); -} - -void testNoScaleOutOfBounds() -{ // Test that we can NOT scale the scalable model with scale <= 0 - HPWH hpwh; - - string input = "TamScalable_SP"; - - double num; - - // get preset model - getHPWHObject(hpwh, input); - - num = 0; - ASSERTTRUE(hpwh.setScaleHPWHCapacityCOP(num, 1.) == HPWH::HPWH_ABORT); - ASSERTTRUE(hpwh.setScaleHPWHCapacityCOP(1., num) == HPWH::HPWH_ABORT); - - num = -1; - ASSERTTRUE(hpwh.setScaleHPWHCapacityCOP(num, 1.) == HPWH::HPWH_ABORT); - ASSERTTRUE(hpwh.setScaleHPWHCapacityCOP(1., num) == HPWH::HPWH_ABORT); -} - -void testNoneScalable() -{ // Test a model that is not scalable - HPWH hpwh; - - string input = "AOSmithCAHP120"; - - // get preset model - getHPWHObject(hpwh, input); - - ASSERTTRUE(hpwh.setScaleHPWHCapacityCOP(1., 1.) == HPWH::HPWH_ABORT); -} - -void testScalableHPWHScales() -{ // Test the scalable hpwh can scale - HPWH hpwh; - - string input = "TamScalable_SP"; - - performance point0, point1; - double num, anotherNum; - - // get preset model - getHPWHObject(hpwh, input); - - num = 0.001; // Very low - scaleCapacityCOP(hpwh, num, 1., point0, point1); - ASSERTTRUE(cmpd(point0.input, point1.input / num)); - ASSERTTRUE(cmpd(point0.output, point1.output / num)); - ASSERTTRUE(cmpd(point0.cop, point1.cop)); - - scaleCapacityCOP(hpwh, 1., num, point0, point1); - ASSERTTRUE(cmpd(point0.input, point1.input)); - ASSERTTRUE(cmpd(point0.output, point1.output / num)); - ASSERTTRUE(cmpd(point0.cop, point1.cop / num)); - - scaleCapacityCOP(hpwh, num, num, point0, point1); - ASSERTTRUE(cmpd(point0.input, point1.input / num)); - ASSERTTRUE(cmpd(point0.output, point1.output / num / num)); - ASSERTTRUE(cmpd(point0.cop, point1.cop / num)); - - num = 0.2; // normal but bad low - scaleCapacityCOP(hpwh, num, 1., point0, point1); - ASSERTTRUE(cmpd(point0.input, point1.input / num)); - ASSERTTRUE(cmpd(point0.output, point1.output / num)); - ASSERTTRUE(cmpd(point0.cop, point1.cop)); - - scaleCapacityCOP(hpwh, 1., num, point0, point1); - ASSERTTRUE(cmpd(point0.input, point1.input)); - ASSERTTRUE(cmpd(point0.output, point1.output / num)); - ASSERTTRUE(cmpd(point0.cop, point1.cop / num)); - - scaleCapacityCOP(hpwh, num, num, point0, point1); - ASSERTTRUE(cmpd(point0.input, point1.input / num)); - ASSERTTRUE(cmpd(point0.output, point1.output / num / num)); - ASSERTTRUE(cmpd(point0.cop, point1.cop / num)); - - num = 3.; // normal but pretty high - scaleCapacityCOP(hpwh, num, 1., point0, point1); - ASSERTTRUE(cmpd(point0.input, point1.input / num)); - ASSERTTRUE(cmpd(point0.output, point1.output / num)); - ASSERTTRUE(cmpd(point0.cop, point1.cop)); - - scaleCapacityCOP(hpwh, 1., num, point0, point1); - ASSERTTRUE(cmpd(point0.input, point1.input)); - ASSERTTRUE(cmpd(point0.output, point1.output / num)); - ASSERTTRUE(cmpd(point0.cop, point1.cop / num)); - - scaleCapacityCOP(hpwh, num, num, point0, point1); - ASSERTTRUE(cmpd(point0.input, point1.input / num)); - ASSERTTRUE(cmpd(point0.output, point1.output / num / num)); - ASSERTTRUE(cmpd(point0.cop, point1.cop / num)); - - num = 1000; // really high - scaleCapacityCOP(hpwh, num, 1., point0, point1); - ASSERTTRUE(cmpd(point0.input, point1.input / num)); - ASSERTTRUE(cmpd(point0.output, point1.output / num)); - ASSERTTRUE(cmpd(point0.cop, point1.cop)); - - scaleCapacityCOP(hpwh, 1., num, point0, point1); - ASSERTTRUE(cmpd(point0.input, point1.input)); - ASSERTTRUE(cmpd(point0.output, point1.output / num)); - ASSERTTRUE(cmpd(point0.cop, point1.cop / num)); - - scaleCapacityCOP(hpwh, num, num, point0, point1); - ASSERTTRUE(cmpd(point0.input, point1.input / num)); - ASSERTTRUE(cmpd(point0.output, point1.output / num / num)); - ASSERTTRUE(cmpd(point0.cop, point1.cop / num)); - - num = 10; - anotherNum = 0.1; // weird high and low - scaleCapacityCOP(hpwh, num, anotherNum, point0, point1); - ASSERTTRUE(cmpd(point0.input, point1.input / num)); - ASSERTTRUE(cmpd(point0.output, point1.output / num / anotherNum)); - ASSERTTRUE(cmpd(point0.cop, point1.cop / anotherNum)); - - scaleCapacityCOP(hpwh, anotherNum, num, point0, point1); - ASSERTTRUE(cmpd(point0.input, point1.input / anotherNum)); - ASSERTTRUE(cmpd(point0.output, point1.output / num / anotherNum)); - ASSERTTRUE(cmpd(point0.cop, point1.cop / num)); - - num = 1.5; - anotherNum = 0.9; // real high and low - scaleCapacityCOP(hpwh, num, anotherNum, point0, point1); - ASSERTTRUE(cmpd(point0.input, point1.input / num)); - ASSERTTRUE(cmpd(point0.output, point1.output / num / anotherNum)); - ASSERTTRUE(cmpd(point0.cop, point1.cop / anotherNum)); - - scaleCapacityCOP(hpwh, anotherNum, num, point0, point1); - ASSERTTRUE(cmpd(point0.input, point1.input / anotherNum)); - ASSERTTRUE(cmpd(point0.output, point1.output / num / anotherNum)); - ASSERTTRUE(cmpd(point0.cop, point1.cop / num)); -} - -void testScalableMPHPWHScales() -{ // Test the scalable MP hpwh can scale - HPWH hpwh; - - string input = "Scalable_MP"; - - performance point0, point1; - double num, anotherNum; - - // get preset model - getHPWHObject(hpwh, input); - - num = 0.001; // Very low - scaleCapacityCOP(hpwh, num, 1., point0, point1); - ASSERTTRUE(cmpd(point0.input, point1.input / num)); - ASSERTTRUE(cmpd(point0.output, point1.output / num)); - ASSERTTRUE(cmpd(point0.cop, point1.cop)); - - scaleCapacityCOP(hpwh, 1., num, point0, point1); - ASSERTTRUE(cmpd(point0.input, point1.input)); - ASSERTTRUE(cmpd(point0.output, point1.output / num)); - ASSERTTRUE(cmpd(point0.cop, point1.cop / num)); - - scaleCapacityCOP(hpwh, num, num, point0, point1); - ASSERTTRUE(cmpd(point0.input, point1.input / num)); - ASSERTTRUE(cmpd(point0.output, point1.output / num / num)); - ASSERTTRUE(cmpd(point0.cop, point1.cop / num)); - - num = 0.2; // normal but bad low - scaleCapacityCOP(hpwh, num, 1., point0, point1); - ASSERTTRUE(cmpd(point0.input, point1.input / num)); - ASSERTTRUE(cmpd(point0.output, point1.output / num)); - ASSERTTRUE(cmpd(point0.cop, point1.cop)); - - scaleCapacityCOP(hpwh, 1., num, point0, point1); - ASSERTTRUE(cmpd(point0.input, point1.input)); - ASSERTTRUE(cmpd(point0.output, point1.output / num)); - ASSERTTRUE(cmpd(point0.cop, point1.cop / num)); - - scaleCapacityCOP(hpwh, num, num, point0, point1); - ASSERTTRUE(cmpd(point0.input, point1.input / num)); - ASSERTTRUE(cmpd(point0.output, point1.output / num / num)); - ASSERTTRUE(cmpd(point0.cop, point1.cop / num)); - - num = 3.; // normal but pretty high - scaleCapacityCOP(hpwh, num, 1., point0, point1); - ASSERTTRUE(cmpd(point0.input, point1.input / num)); - ASSERTTRUE(cmpd(point0.output, point1.output / num)); - ASSERTTRUE(cmpd(point0.cop, point1.cop)); - - scaleCapacityCOP(hpwh, 1., num, point0, point1); - ASSERTTRUE(cmpd(point0.input, point1.input)); - ASSERTTRUE(cmpd(point0.output, point1.output / num)); - ASSERTTRUE(cmpd(point0.cop, point1.cop / num)); - - scaleCapacityCOP(hpwh, num, num, point0, point1); - ASSERTTRUE(cmpd(point0.input, point1.input / num)); - ASSERTTRUE(cmpd(point0.output, point1.output / num / num)); - ASSERTTRUE(cmpd(point0.cop, point1.cop / num)); - - num = 1000; // really high - scaleCapacityCOP(hpwh, num, 1., point0, point1); - ASSERTTRUE(cmpd(point0.input, point1.input / num)); - ASSERTTRUE(cmpd(point0.output, point1.output / num)); - ASSERTTRUE(cmpd(point0.cop, point1.cop)); - - scaleCapacityCOP(hpwh, 1., num, point0, point1); - ASSERTTRUE(cmpd(point0.input, point1.input)); - ASSERTTRUE(cmpd(point0.output, point1.output / num)); - ASSERTTRUE(cmpd(point0.cop, point1.cop / num)); - - scaleCapacityCOP(hpwh, num, num, point0, point1); - ASSERTTRUE(cmpd(point0.input, point1.input / num)); - ASSERTTRUE(cmpd(point0.output, point1.output / num / num)); - ASSERTTRUE(cmpd(point0.cop, point1.cop / num)); - - num = 10; - anotherNum = 0.1; // weird high and low - scaleCapacityCOP(hpwh, num, anotherNum, point0, point1); - ASSERTTRUE(cmpd(point0.input, point1.input / num)); - ASSERTTRUE(cmpd(point0.output, point1.output / num / anotherNum)); - ASSERTTRUE(cmpd(point0.cop, point1.cop / anotherNum)); - - scaleCapacityCOP(hpwh, anotherNum, num, point0, point1); - ASSERTTRUE(cmpd(point0.input, point1.input / anotherNum)); - ASSERTTRUE(cmpd(point0.output, point1.output / num / anotherNum)); - ASSERTTRUE(cmpd(point0.cop, point1.cop / num)); - - num = 1.5; - anotherNum = 0.9; // real high and low - scaleCapacityCOP(hpwh, num, anotherNum, point0, point1); - ASSERTTRUE(cmpd(point0.input, point1.input / num)); - ASSERTTRUE(cmpd(point0.output, point1.output / num / anotherNum)); - ASSERTTRUE(cmpd(point0.cop, point1.cop / anotherNum)); - - scaleCapacityCOP(hpwh, anotherNum, num, point0, point1); - ASSERTTRUE(cmpd(point0.input, point1.input / anotherNum)); - ASSERTTRUE(cmpd(point0.output, point1.output / num / anotherNum)); - ASSERTTRUE(cmpd(point0.cop, point1.cop / num)); -} - -void testSPGetCompressorCapacity() -{ - HPWH hpwh; - - string input = "ColmacCxA_20_SP"; - - performance point0; - - double capacity_kWH, capacity_BTU; - double waterTempC = F_TO_C(63); - double airTempC = F_TO_C(77); - double setpointC = F_TO_C(135); - - // get preset model - getHPWHObject(hpwh, input); - - getCompressorPerformance(hpwh, point0, waterTempC, airTempC, setpointC); // gives kWH - capacity_kWH = hpwh.getCompressorCapacity(airTempC, waterTempC, setpointC) / - 60; // div 60 to kWh because I know above only runs 1 minute - - ASSERTTRUE(cmpd(point0.output, capacity_kWH)); - - // Test with IP units - capacity_BTU = hpwh.getCompressorCapacity(C_TO_F(airTempC), - C_TO_F(waterTempC), - C_TO_F(setpointC), - HPWH::UNITS_BTUperHr, - HPWH::UNITS_F) / - 60; // div 60 to BTU because I know above only runs 1 minute - ASSERTTRUE(relcmpd(KWH_TO_BTU(point0.output), - capacity_BTU)); // relative cmp since in btu's these will be large numbers -} - -void testMPGetCompressorCapacity() -{ - HPWH hpwh; - - string input = "ColmacCxA_20_MP"; - - performance point0; - - double capacity_kWH, capacity_BTU; - double waterTempC = F_TO_C(50); // 50 and 126 to make average 88 - double airTempC = F_TO_C(61.7); - double setpointC = F_TO_C(126); - - // get preset model - getHPWHObject(hpwh, input); - capacity_kWH = hpwh.getCompressorCapacity(airTempC, waterTempC, setpointC) / - 60.; // div 60 to kWh because I know above only runs 1 minute - getCompressorPerformance(hpwh, point0, waterTempC, airTempC, setpointC); // gives kWH - ASSERTTRUE(cmpd(point0.output, capacity_kWH)); - - // Test with IP units - capacity_BTU = hpwh.getCompressorCapacity(C_TO_F(airTempC), - C_TO_F(waterTempC), - C_TO_F(setpointC), - HPWH::UNITS_BTUperHr, - HPWH::UNITS_F) / - 60; // div 60 to BTU because I know above only runs 1 minute - ASSERTTRUE(relcmpd(KWH_TO_BTU(point0.output), - capacity_BTU, - 0.0001)); // relative cmp since in btu's these will be large numbers -} - -void testSetMPCompressorOutputCapacity() -{ - HPWH hpwh; - - string input = "Scalable_MP"; - - double newCapacity_kW, num; - double waterTempC = F_TO_C(44); - double airTempC = F_TO_C(98); - double setpointC = F_TO_C(150); - - // get preset model - getHPWHObject(hpwh, input); - - // Scale output to 1 kW - num = 1.; - hpwh.setCompressorOutputCapacity(num, airTempC, waterTempC, setpointC); - newCapacity_kW = hpwh.getCompressorCapacity(airTempC, waterTempC, setpointC); - ASSERTTRUE(cmpd(num, newCapacity_kW)); - - // Scale output to .01 kW - num = .01; - hpwh.setCompressorOutputCapacity(num, airTempC, waterTempC, setpointC); - newCapacity_kW = hpwh.getCompressorCapacity(airTempC, waterTempC, setpointC); - ASSERTTRUE(cmpd(num, newCapacity_kW)); - - // Scale output to 1000 kW - num = 1000.; - hpwh.setCompressorOutputCapacity(num, airTempC, waterTempC, setpointC); - newCapacity_kW = hpwh.getCompressorCapacity(airTempC, waterTempC, setpointC); - ASSERTTRUE(cmpd(num, newCapacity_kW)); - - // Check again with changed setpoint, for MP it should affect output capacity since it looks at - // the mean temperature for the cycle. - setpointC = F_TO_C(100); - newCapacity_kW = hpwh.getCompressorCapacity(airTempC, waterTempC, setpointC); - ASSERTFALSE(cmpd(num, newCapacity_kW)); -} - -void testSetCompressorOutputCapacity() -{ - HPWH hpwh; - - string input = "TamScalable_SP"; - - double newCapacity_kW, num; - double waterTempC = F_TO_C(44); - double airTempC = F_TO_C(98); - double setpointC = F_TO_C(145); - - // get preset model - getHPWHObject(hpwh, input); - - // Scale output to 1 kW - num = 1.; - hpwh.setCompressorOutputCapacity(num, airTempC, waterTempC, setpointC); - newCapacity_kW = hpwh.getCompressorCapacity(airTempC, waterTempC, setpointC); - ASSERTTRUE(cmpd(num, newCapacity_kW)); - - // Scale output to .01 kW - num = .01; - hpwh.setCompressorOutputCapacity(num, airTempC, waterTempC, setpointC); - newCapacity_kW = hpwh.getCompressorCapacity(airTempC, waterTempC, setpointC); - ASSERTTRUE(cmpd(num, newCapacity_kW)); - - // Scale output to 1000 kW - num = 1000.; - hpwh.setCompressorOutputCapacity(num, airTempC, waterTempC, setpointC); - newCapacity_kW = hpwh.getCompressorCapacity(airTempC, waterTempC, setpointC); - ASSERTTRUE(cmpd(num, newCapacity_kW)); - - // Scale output to 1000 kW but let's use do the calc in other units - num = KW_TO_BTUperHR(num); - hpwh.setCompressorOutputCapacity(num, - C_TO_F(airTempC), - C_TO_F(waterTempC), - C_TO_F(setpointC), - HPWH::UNITS_BTUperHr, - HPWH::UNITS_F); - double newCapacity_BTUperHr = hpwh.getCompressorCapacity(C_TO_F(airTempC), - C_TO_F(waterTempC), - C_TO_F(setpointC), - HPWH::UNITS_BTUperHr, - HPWH::UNITS_F); - ASSERTTRUE(relcmpd(num, newCapacity_BTUperHr)); -} - -void testChipsCaseWithIPUnits() -{ - HPWH hpwh; - - string input = "TamScalable_SP"; - - double waterTempF = 50; - double airTempF = 50; - double setpointF = 120; - double wh_heatingCap = 20000.; - - // get preset model - getHPWHObject(hpwh, input); - - // Scale output to 20000 btu/hr but let's use do the calc in other units - hpwh.setCompressorOutputCapacity( - wh_heatingCap, airTempF, waterTempF, setpointF, HPWH::UNITS_BTUperHr, HPWH::UNITS_F); - double newCapacity_BTUperHr = hpwh.getCompressorCapacity( - airTempF, waterTempF, setpointF, HPWH::UNITS_BTUperHr, HPWH::UNITS_F); - ASSERTTRUE(relcmpd(wh_heatingCap, newCapacity_BTUperHr)); -} - -void testScaleRestank() -{ - HPWH hpwh; - - string input = "restankRealistic"; - // get preset model - getHPWHObject(hpwh, input); - - // Scale COP for restank fails. - int val = hpwh.setScaleHPWHCapacityCOP(2., 2.); - ASSERTTRUE(val == HPWH::HPWH_ABORT); -} - -void testResistanceScales() -{ - HPWH hpwh; - - string input = "TamScalable_SP"; - double elementPower = 30.0; // KW - - // hpwh.HPWHinit_resTank(); - getHPWHObject(hpwh, input); - - double returnVal; - returnVal = hpwh.getResistanceCapacity(0, HPWH::UNITS_KW); - ASSERTTRUE(relcmpd(returnVal, elementPower)); - returnVal = hpwh.getResistanceCapacity(1, HPWH::UNITS_KW); - ASSERTTRUE(relcmpd(returnVal, elementPower)); - returnVal = hpwh.getResistanceCapacity(-1, HPWH::UNITS_KW); - ASSERTTRUE(relcmpd(returnVal, 2. * elementPower)); - - // check units convert - returnVal = hpwh.getResistanceCapacity(-1, HPWH::UNITS_BTUperHr); - ASSERTTRUE(relcmpd(returnVal, 2. * elementPower * 3412.14)); - - // Check setting bottom works - double factor = 2.0; - hpwh.setResistanceCapacity(factor * elementPower, 0); - returnVal = hpwh.getResistanceCapacity(0, HPWH::UNITS_KW); - ASSERTTRUE(relcmpd(returnVal, factor * elementPower)); - returnVal = hpwh.getResistanceCapacity(1, HPWH::UNITS_KW); - ASSERTTRUE(relcmpd(returnVal, elementPower)); - returnVal = hpwh.getResistanceCapacity(-1, HPWH::UNITS_KW); - ASSERTTRUE(relcmpd(returnVal, factor * elementPower + elementPower)); - - // Check setting both works - factor = 3.; - hpwh.setResistanceCapacity(factor * elementPower, -1); - returnVal = hpwh.getResistanceCapacity(0, HPWH::UNITS_KW); - ASSERTTRUE(relcmpd(returnVal, factor * elementPower)); - returnVal = hpwh.getResistanceCapacity(1, HPWH::UNITS_KW); - ASSERTTRUE(relcmpd(returnVal, factor * elementPower)); - returnVal = hpwh.getResistanceCapacity(-1, HPWH::UNITS_KW); - ASSERTTRUE(relcmpd(returnVal, 2. * factor * elementPower)); -} - -void testStorageTankErrors() -{ - HPWH hpwh; - string input = "StorageTank"; - // get preset model - getHPWHObject(hpwh, input); - - ASSERTTRUE(hpwh.setResistanceCapacity(1000.) == HPWH::HPWH_ABORT); - ASSERTTRUE(hpwh.setScaleHPWHCapacityCOP(1., 1.) == HPWH::HPWH_ABORT); -} - -int main(int, char**) -{ - - testSetMPCompressorOutputCapacity(); - - testScalableHPWHScales(); // Test the scalable model scales properly - - testNoScaleOutOfBounds(); // Test that models can't scale with invalid inputs - - testNoneScalable(); // Test that models can't scale that are non scalable presets - - testScaleRestank(); // Test the resistance tank can't scale the compressor - - testResistanceScales(); // Test the resistance tank scales the resistance elements - - testSPGetCompressorCapacity(); // Test we can get the capacity - - testSetCompressorOutputCapacity(); // Test we can set the capacity with a specific number - - testChipsCaseWithIPUnits(); // Debuging Chip's case - - testStorageTankErrors(); // Make sure we can't scale the storage tank. - - testScalableMPHPWHScales(); // Test for proper scaling in the MP scalable model - - testMPGetCompressorCapacity(); // Test MP capacity in and out correct. - - // testSetMPCompressorOutputCapacity(); // Tets MP capacity can be set correctly. - - // Made it through the gauntlet - return 0; -} diff --git a/test/testSizingFractions.cc b/test/testSizingFractions.cc deleted file mode 100644 index 2053922b..00000000 --- a/test/testSizingFractions.cc +++ /dev/null @@ -1,176 +0,0 @@ - - -/*unit test for isTankSizeFixed() functionality - * - * - * - */ -#include "HPWH.hh" -#include "testUtilityFcts.cc" - -#include -#include - -#define SIZE (double)HPWH::CONDENSITY_SIZE - -using std::cout; -using std::string; - -void testScalableSizingFract(); -void testSandenSizingFract(); -void testColmacSizingFract(); -void testHPTU50SizingFract(); -void test220eSizingFract(); -void testGESizingFract(); -void testResTankSizingFract(); -void testStoTankSizingFract(); -void testGetCompressorMinRuntime(); - -int main(int, char**) -{ - testScalableSizingFract(); - testSandenSizingFract(); - testColmacSizingFract(); - testHPTU50SizingFract(); - test220eSizingFract(); - testGESizingFract(); - testResTankSizingFract(); - testStoTankSizingFract(); - - // Made it through the gauntlet - return 0; -} - -void testScalableSizingFract() -{ - HPWH hpwh; - double AF, pU; - double AF_answer = 4. / SIZE; - - string input = "TamScalable_SP"; // Just a compressor with R134A - getHPWHObject(hpwh, input); // get preset model - - int val = hpwh.getSizingFractions(AF, pU); - ASSERTTRUE(val == 0); - ASSERTTRUE(cmpd(AF, AF_answer)); - ASSERTTRUE(cmpd(pU, 1 - 1. / SIZE)); -} - -void testSandenSizingFract() -{ - HPWH hpwh; - double AF, pU; - double AF_answer = 8. / SIZE; - - string input = "Sanden80"; // Just a compressor with R134A - getHPWHObject(hpwh, input); // get preset model - - int val = hpwh.getSizingFractions(AF, pU); - ASSERTTRUE(val == 0); - ASSERTTRUE(cmpd(AF, AF_answer)); - ASSERTTRUE(cmpd(pU, 1 - 1. / SIZE)); -} - -void testColmacSizingFract() -{ - HPWH hpwh; - double AF, pU; - double AF_answer = 4. / SIZE; - - string input = "ColmacCxV_5_SP"; // Just a compressor with R134A - getHPWHObject(hpwh, input); // get preset model - - int val = hpwh.getSizingFractions(AF, pU); - ASSERTTRUE(val == 0); - ASSERTTRUE(cmpd(AF, AF_answer)); - ASSERTTRUE(cmpd(pU, 1 - 1. / SIZE)); -} - -void testHPTU50SizingFract() -{ - HPWH hpwh; - double AF, pU; - double AF_answer = (1. + 2. + 3. + 4.) / 4. / SIZE; - - string input = "AOSmithHPTU50"; // Just a compressor with R134A - getHPWHObject(hpwh, input); // get preset model - - int val = hpwh.getSizingFractions(AF, pU); - ASSERTTRUE(val == 0); - ASSERTTRUE(cmpd(AF, AF_answer)); - ASSERTTRUE(cmpd(pU, 1.)); -} - -void testGESizingFract() -{ - HPWH hpwh; - double AF, pU; - double AF_answer = (1. + 2. + 3. + 4.) / 4. / SIZE; - - string input = "GE"; // Just a compressor with R134A - getHPWHObject(hpwh, input); // get preset model - - int val = hpwh.getSizingFractions(AF, pU); - ASSERTTRUE(val == 0); - ASSERTTRUE(cmpd(AF, AF_answer)); - ASSERTTRUE(cmpd(pU, 1.)); -} - -void test220eSizingFract() -{ - HPWH hpwh; - double AF, pU; - double AF_answer = (5. + 6.) / 2. / SIZE; - - string input = "Stiebel220e"; // Just a compressor with R134A - getHPWHObject(hpwh, input); // get preset model - - int val = hpwh.getSizingFractions(AF, pU); - ASSERTTRUE(val == 0); - ASSERTTRUE(cmpd(AF, AF_answer)); - ASSERTTRUE(cmpd(pU, 1 - 1. / SIZE)); -} - -void testResTankSizingFract() -{ - HPWH hpwh; - double AF, pU; - - string input = "restankRealistic"; // Just a compressor with R134A - getHPWHObject(hpwh, input); // get preset model - - int val = hpwh.getSizingFractions(AF, pU); - ASSERTTRUE(val == HPWH::HPWH_ABORT); -} - -void testStoTankSizingFract() -{ - HPWH hpwh; - double AF, pU; - - string input = "StorageTank"; // Just a compressor with R134A - getHPWHObject(hpwh, input); // get preset model - - int val = hpwh.getSizingFractions(AF, pU); - ASSERTTRUE(val == HPWH::HPWH_ABORT); -} - -void testGetCompressorMinRuntime() -{ - HPWH hpwh; - string input = "TamScalable_SP"; // Just a compressor with R134A - getHPWHObject(hpwh, input); // get preset model - - double expected_mins = 10.; - double expected_secs = expected_mins * 60.; - double expected_hrs = expected_mins / 60.; - - double mins = hpwh.getCompressorMinRuntime(); - ASSERTTRUE(mins == expected_mins); - - double secs = hpwh.getCompressorMinRuntime(HPWH::UNITS_SEC); - ASSERTTRUE(secs == expected_secs); - - double hrs = hpwh.getCompressorMinRuntime(HPWH::UNITS_HR); - ASSERTTRUE(hrs == expected_hrs); -} diff --git a/test/testStateOfChargeFcts.cc b/test/testStateOfChargeFcts.cc deleted file mode 100644 index a4a93892..00000000 --- a/test/testStateOfChargeFcts.cc +++ /dev/null @@ -1,80 +0,0 @@ -#include "HPWH.hh" -#include "testUtilityFcts.cc" - -#include -#include - -void testGetStateOfCharge(); -void testChargeBelowSetpoint(); - -int main() -{ - testGetStateOfCharge(); - testChargeBelowSetpoint(); -} - -void testGetStateOfCharge() -{ - HPWH hpwh; - string input = "Sanden80"; - getHPWHObject(hpwh, input); - double tMains_C = F_TO_C(55.); - double tMinUseful_C = F_TO_C(110.); - double chargeFraction; - - // Check for errors - chargeFraction = hpwh.calcSoCFraction(F_TO_C(125.), tMinUseful_C); - ASSERTTRUE(chargeFraction == HPWH::HPWH_ABORT); - chargeFraction = hpwh.calcSoCFraction(tMains_C, F_TO_C(155.)); - ASSERTTRUE(chargeFraction == HPWH::HPWH_ABORT); - chargeFraction = hpwh.calcSoCFraction(tMains_C, tMinUseful_C, F_TO_C(100.)); - ASSERTTRUE(chargeFraction == HPWH::HPWH_ABORT); - - // Check state of charge returns 1 at setpoint - chargeFraction = hpwh.calcSoCFraction(tMains_C, tMinUseful_C); - ASSERTTRUE(cmpd(chargeFraction, 1.)); - chargeFraction = hpwh.calcSoCFraction(tMains_C + 5., tMinUseful_C); - ASSERTTRUE(cmpd(chargeFraction, 1.)); - chargeFraction = hpwh.calcSoCFraction(tMains_C, tMinUseful_C + 5.); - ASSERTTRUE(cmpd(chargeFraction, 1.)); - - // Varying max temp - chargeFraction = hpwh.calcSoCFraction(tMains_C, tMinUseful_C, F_TO_C(110.)); - ASSERTTRUE(cmpd(chargeFraction, 1.70909)); - chargeFraction = hpwh.calcSoCFraction(tMains_C, tMinUseful_C, F_TO_C(120.)); - ASSERTTRUE(cmpd(chargeFraction, 1.4461)); - chargeFraction = hpwh.calcSoCFraction(tMains_C, tMinUseful_C, F_TO_C(135.)); - ASSERTTRUE(cmpd(chargeFraction, 1.175)); -} - -void testChargeBelowSetpoint() -{ - HPWH hpwh; - string input = "ColmacCxV_5_SP"; - getHPWHObject(hpwh, input); - double tMains_C = F_TO_C(60.); - double tMinUseful_C = F_TO_C(110.); - double chargeFraction; - - // Check state of charge returns 1 at setpoint - chargeFraction = hpwh.calcSoCFraction(tMains_C, tMinUseful_C); - ASSERTTRUE(cmpd(chargeFraction, 1.)); - - // Check state of charge returns 0 when tank below useful - hpwh.setTankToTemperature(F_TO_C(109.)); - chargeFraction = hpwh.calcSoCFraction(tMains_C, tMinUseful_C, F_TO_C(140.)); - ASSERTTRUE(cmpd(chargeFraction, 0.)); - - // Check some lower values with tank set at constant temperatures - hpwh.setTankToTemperature(F_TO_C(110.)); - chargeFraction = hpwh.calcSoCFraction(tMains_C, tMinUseful_C, F_TO_C(140.)); - ASSERTTRUE(cmpd(chargeFraction, 0.625)); - - hpwh.setTankToTemperature(F_TO_C(120.)); - chargeFraction = hpwh.calcSoCFraction(tMains_C, tMinUseful_C, F_TO_C(140.)); - ASSERTTRUE(cmpd(chargeFraction, 0.75)); - - hpwh.setTankToTemperature(F_TO_C(130.)); - chargeFraction = hpwh.calcSoCFraction(tMains_C, tMinUseful_C, F_TO_C(140.)); - ASSERTTRUE(cmpd(chargeFraction, 0.875)); -} diff --git a/test/testTankSizeFixed.cc b/test/testTankSizeFixed.cc deleted file mode 100644 index af286fcc..00000000 --- a/test/testTankSizeFixed.cc +++ /dev/null @@ -1,135 +0,0 @@ - - -/*unit test for isTankSizeFixed() functionality - * - * - * - */ -#include "HPWH.hh" -#include "testUtilityFcts.cc" - -#include -#include - -using std::cout; -using std::string; - -int testForceChangeTankSize(HPWH::MODELS model); -int testIsTankSizeFixed(HPWH::MODELS model); - -int main(int argc, char* argv[]) -{ - HPWH::MODELS presetModel; - - string input; // = "AOSmithCAHP120"; - - if (argc != 2) - { - cout << "Invalid input. This program takes One arguments: preset model specification (ie. " - "Sanden80). Recieved input: \n"; - for (int ii = 0; ii < argc; ii++) - { - cout << argv[ii] << " "; - } - exit(1); - } - else - { - input = argv[1]; - } - - // get model number - presetModel = mapStringToPreset(input); - - ASSERTTRUE(testIsTankSizeFixed(presetModel) == 0, "Tank size is not fixed"); - ASSERTTRUE(testForceChangeTankSize(presetModel) == 0, "Tank size was not forced to change"); - - // Made it through the gauntlet - return 0; -} - -int testIsTankSizeFixed(HPWH::MODELS model) -{ - HPWH hpwh; - - // set preset - if (hpwh.HPWHinit_presets(model) != 0) - return 1; - - double originalTankSize = hpwh.getTankSize(); - double newTankSize = originalTankSize + 100; - - // change the tank size - int result = hpwh.setTankSize(newTankSize); - - if (result != 0 && result != HPWH::HPWH_ABORT) - { - cout << "Error, setTankSize() returned an invalid result: " << result << "\n"; - return 1; - } - - if (hpwh.isTankSizeFixed()) - { // better not have change! - if (result == 0) - { - cout << "Error, setTankSize() returned 0 when should be HPWH_ABORT\n"; - return 1; - } - if (originalTankSize != hpwh.getTankSize()) - { - cout << "Error, the tank size has changed when isTankSizeFixed is true\n"; - return 1; - } - } - else - { // it better have changed - if (result != 0) - { - cout << "Error, setTankSize() returned HPWH_ABORT when it should be 0\n"; - return 1; - } - if (newTankSize != hpwh.getTankSize()) - { - cout << "Error, the tank size hasn't changed to the new tank size when it should have. " - "New Size: " - << newTankSize << ". Returned Value: " << hpwh.getTankSize() << "\n"; - return 1; - } - } - return 0; -} - -int testForceChangeTankSize(HPWH::MODELS model) -{ - HPWH hpwh; - - // set preset - if (hpwh.HPWHinit_presets(model) != 0) - return 1; - - double newTankSize = 133.312; // No way a tank has this size originally - - // change the tank size - int result = hpwh.setTankSize(newTankSize, HPWH::UNITS_GAL, true); - - if (result != 0 && result != HPWH::HPWH_ABORT) - { - cout << "Error, setTankSize() returned an invalid result: " << result << "\n"; - return 1; - } - - // it better have changed - if (result != 0) - { - cout << "Error, setTankSize() returned HPWH_ABORT when it should be 0\n"; - return 1; - } - if (newTankSize != hpwh.getTankSize(HPWH::UNITS_GAL)) - { - cout << "Error, the tank size hasn't changed to the new tank size when it should have. New " - "Size: " - << newTankSize << ". Returned Value: " << hpwh.getTankSize(HPWH::UNITS_GAL) << "\n"; - return 1; - } - return 0; -} diff --git a/test/testUtilityFcts.cc b/test/testUtilityFcts.cc deleted file mode 100644 index 94e2a76e..00000000 --- a/test/testUtilityFcts.cc +++ /dev/null @@ -1,423 +0,0 @@ -/*This is not a substitute for a proper HPWH Test Tool, it is merely a short program - * to aid in the testing of the new HPWH.cc as it is being written. - * - * -NDK - * - * Bring on the HPWH Test Tool!!! -MJL - * - * - * - */ -#include "HPWH.hh" -#include -#include - -using std::cout; -using std::string; - -#define F_TO_C(T) ((T - 32.0) * 5.0 / 9.0) -#define C_TO_F(T) (((9.0 / 5.0) * T) + 32.0) -#define dF_TO_dC(T) (T * 5.0 / 9.0) -#define GAL_TO_L(GAL) (GAL * 3.78541) -#define KW_TO_BTUperHR(KW) (KW * BTUperKWH) -#define KWH_TO_BTU(KW) (KW * BTUperKWH) - -#define ASSERTTRUE(input, ...) \ - if (!(input)) \ - { \ - cout << "Assertation failed at " << __FILE__ << ", line: " << __LINE__ << ".\n"; \ - exit(1); \ - } -#define ASSERTFALSE(input, ...) \ - if ((input)) \ - { \ - cout << "Assertation failed at " << __FILE__ << ", line: " << __LINE__ << ".\n"; \ - exit(1); \ - } - -// Compare doubles -bool cmpd(double A, double B, double epsilon = 0.0001) { return (fabs(A - B) < epsilon); } -// Relative Compare doubles -bool relcmpd(double A, double B, double epsilon = 0.00001) -{ - return fabs(A - B) < (epsilon * (fabs(A) < fabs(B) ? fabs(B) : fabs(A))); -} - -bool compressorIsRunning(HPWH& hpwh) -{ - return (bool)hpwh.isNthHeatSourceRunning(hpwh.getCompressorIndex()); -} - -HPWH::MODELS mapStringToPreset(string modelName) -{ - - HPWH::MODELS hpwhModel; - - if (modelName == "Voltex60" || modelName == "AOSmithPHPT60") - { - hpwhModel = HPWH::MODELS_AOSmithPHPT60; - } - else if (modelName == "Voltex80" || modelName == "AOSmith80") - { - hpwhModel = HPWH::MODELS_AOSmithPHPT80; - } - else if (modelName == "GEred" || modelName == "GE") - { - hpwhModel = HPWH::MODELS_GE2012; - } - else if (modelName == "SandenGAU" || modelName == "Sanden80" || modelName == "SandenGen3") - { - hpwhModel = HPWH::MODELS_Sanden80; - } - else if (modelName == "Sanden120") - { - hpwhModel = HPWH::MODELS_Sanden120; - } - else if (modelName == "SandenGES" || modelName == "Sanden40") - { - hpwhModel = HPWH::MODELS_Sanden40; - } - else if (modelName == "AOSmithHPTU50") - { - hpwhModel = HPWH::MODELS_AOSmithHPTU50; - } - else if (modelName == "AOSmithHPTU66") - { - hpwhModel = HPWH::MODELS_AOSmithHPTU66; - } - else if (modelName == "AOSmithHPTU80") - { - hpwhModel = HPWH::MODELS_AOSmithHPTU80; - } - else if (modelName == "AOSmithHPTS50") - { - hpwhModel = HPWH::MODELS_AOSmithHPTS50; - } - else if (modelName == "AOSmithHPTS66") - { - hpwhModel = HPWH::MODELS_AOSmithHPTS66; - } - else if (modelName == "AOSmithHPTS80") - { - hpwhModel = HPWH::MODELS_AOSmithHPTS80; - } - else if (modelName == "AOSmithHPTU80DR") - { - hpwhModel = HPWH::MODELS_AOSmithHPTU80_DR; - } - else if (modelName == "GE502014STDMode" || modelName == "GE2014STDMode") - { - hpwhModel = HPWH::MODELS_GE2014STDMode; - } - else if (modelName == "GE502014" || modelName == "GE2014") - { - hpwhModel = HPWH::MODELS_GE2014; - } - else if (modelName == "GE802014") - { - hpwhModel = HPWH::MODELS_GE2014_80DR; - } - else if (modelName == "RheemHB50") - { - hpwhModel = HPWH::MODELS_RheemHB50; - } - else if (modelName == "Stiebel220e" || modelName == "Stiebel220E") - { - hpwhModel = HPWH::MODELS_Stiebel220E; - } - else if (modelName == "Generic1") - { - hpwhModel = HPWH::MODELS_Generic1; - } - else if (modelName == "Generic2") - { - hpwhModel = HPWH::MODELS_Generic2; - } - else if (modelName == "Generic3") - { - hpwhModel = HPWH::MODELS_Generic3; - } - else if (modelName == "custom") - { - hpwhModel = HPWH::MODELS_CustomFile; - } - else if (modelName == "restankRealistic") - { - hpwhModel = HPWH::MODELS_restankRealistic; - } - else if (modelName == "StorageTank") - { - hpwhModel = HPWH::MODELS_StorageTank; - } - else if (modelName == "BWC2020_65") - { - hpwhModel = HPWH::MODELS_BWC2020_65; - } - // New Rheems - else if (modelName == "Rheem2020Prem40") - { - hpwhModel = HPWH::MODELS_Rheem2020Prem40; - } - else if (modelName == "Rheem2020Prem50") - { - hpwhModel = HPWH::MODELS_Rheem2020Prem50; - } - else if (modelName == "Rheem2020Prem65") - { - hpwhModel = HPWH::MODELS_Rheem2020Prem65; - } - else if (modelName == "Rheem2020Prem80") - { - hpwhModel = HPWH::MODELS_Rheem2020Prem80; - } - else if (modelName == "Rheem2020Build40") - { - hpwhModel = HPWH::MODELS_Rheem2020Build40; - } - else if (modelName == "Rheem2020Build50") - { - hpwhModel = HPWH::MODELS_Rheem2020Build50; - } - else if (modelName == "Rheem2020Build65") - { - hpwhModel = HPWH::MODELS_Rheem2020Build65; - } - else if (modelName == "Rheem2020Build80") - { - hpwhModel = HPWH::MODELS_Rheem2020Build80; - } - else if (modelName == "RheemPlugInDedicated40") - { - hpwhModel = HPWH::MODELS_RheemPlugInDedicated40; - } - else if (modelName == "RheemPlugInDedicated50") - { - hpwhModel = HPWH::MODELS_RheemPlugInDedicated50; - } - else if (modelName == "RheemPlugInShared40") - { - hpwhModel = HPWH::MODELS_RheemPlugInShared40; - } - else if (modelName == "RheemPlugInShared50") - { - hpwhModel = HPWH::MODELS_RheemPlugInShared50; - } - else if (modelName == "RheemPlugInShared65") - { - hpwhModel = HPWH::MODELS_RheemPlugInShared65; - } - else if (modelName == "RheemPlugInShared80") - { - hpwhModel = HPWH::MODELS_RheemPlugInShared80; - } - // Large HPWH's - else if (modelName == "AOSmithCAHP120") - { - hpwhModel = HPWH::MODELS_AOSmithCAHP120; - } - else if (modelName == "ColmacCxV_5_SP") - { - hpwhModel = HPWH::MODELS_ColmacCxV_5_SP; - } - else if (modelName == "ColmacCxA_10_SP") - { - hpwhModel = HPWH::MODELS_ColmacCxA_10_SP; - } - else if (modelName == "ColmacCxA_15_SP") - { - hpwhModel = HPWH::MODELS_ColmacCxA_15_SP; - } - else if (modelName == "ColmacCxA_20_SP") - { - hpwhModel = HPWH::MODELS_ColmacCxA_20_SP; - } - else if (modelName == "ColmacCxA_25_SP") - { - hpwhModel = HPWH::MODELS_ColmacCxA_25_SP; - } - else if (modelName == "ColmacCxA_30_SP") - { - hpwhModel = HPWH::MODELS_ColmacCxA_30_SP; - } - - else if (modelName == "ColmacCxV_5_MP") - { - hpwhModel = HPWH::MODELS_ColmacCxV_5_MP; - } - else if (modelName == "ColmacCxA_10_MP") - { - hpwhModel = HPWH::MODELS_ColmacCxA_10_MP; - } - else if (modelName == "ColmacCxA_15_MP") - { - hpwhModel = HPWH::MODELS_ColmacCxA_15_MP; - } - else if (modelName == "ColmacCxA_20_MP") - { - hpwhModel = HPWH::MODELS_ColmacCxA_20_MP; - } - else if (modelName == "ColmacCxA_25_MP") - { - hpwhModel = HPWH::MODELS_ColmacCxA_25_MP; - } - else if (modelName == "ColmacCxA_30_MP") - { - hpwhModel = HPWH::MODELS_ColmacCxA_30_MP; - } - - else if (modelName == "RheemHPHD60") - { - hpwhModel = HPWH::MODELS_RHEEM_HPHD60VNU_201_MP; - } - else if (modelName == "RheemHPHD135") - { - hpwhModel = HPWH::MODELS_RHEEM_HPHD135VNU_483_MP; - } - // Nyle Single pass models - else if (modelName == "NyleC25A_SP") - { - hpwhModel = HPWH::MODELS_NyleC25A_SP; - } - else if (modelName == "NyleC60A_SP") - { - hpwhModel = HPWH::MODELS_NyleC60A_SP; - } - else if (modelName == "NyleC90A_SP") - { - hpwhModel = HPWH::MODELS_NyleC90A_SP; - } - else if (modelName == "NyleC185A_SP") - { - hpwhModel = HPWH::MODELS_NyleC185A_SP; - } - else if (modelName == "NyleC250A_SP") - { - hpwhModel = HPWH::MODELS_NyleC250A_SP; - } - else if (modelName == "NyleC60A_C_SP") - { - hpwhModel = HPWH::MODELS_NyleC60A_C_SP; - } - else if (modelName == "NyleC90A_C_SP") - { - hpwhModel = HPWH::MODELS_NyleC90A_C_SP; - } - else if (modelName == "NyleC185A_C_SP") - { - hpwhModel = HPWH::MODELS_NyleC185A_C_SP; - } - else if (modelName == "NyleC250A_C_SP") - { - hpwhModel = HPWH::MODELS_NyleC250A_C_SP; - } - // Nyle MP models - else if (modelName == "NyleC60A_MP") - { - hpwhModel = HPWH::MODELS_NyleC60A_MP; - } - else if (modelName == "NyleC90A_MP") - { - hpwhModel = HPWH::MODELS_NyleC90A_MP; - } - else if (modelName == "NyleC125A_MP") - { - hpwhModel = HPWH::MODELS_NyleC125A_MP; - } - else if (modelName == "NyleC185A_MP") - { - hpwhModel = HPWH::MODELS_NyleC185A_MP; - } - else if (modelName == "NyleC250A_MP") - { - hpwhModel = HPWH::MODELS_NyleC250A_MP; - } - else if (modelName == "NyleC60A_C_MP") - { - hpwhModel = HPWH::MODELS_NyleC60A_C_MP; - } - else if (modelName == "NyleC90A_C_MP") - { - hpwhModel = HPWH::MODELS_NyleC90A_C_MP; - } - else if (modelName == "NyleC125A_C_MP") - { - hpwhModel = HPWH::MODELS_NyleC125A_C_MP; - } - else if (modelName == "NyleC185A_C_MP") - { - hpwhModel = HPWH::MODELS_NyleC185A_C_MP; - } - else if (modelName == "NyleC250A_C_MP") - { - hpwhModel = HPWH::MODELS_NyleC250A_C_MP; - } - else if (modelName == "QAHV_N136TAU_HPB_SP") - { - hpwhModel = HPWH::MODELS_MITSUBISHI_QAHV_N136TAU_HPB_SP; - } - // Stack in a couple scalable models - else if (modelName == "TamScalable_SP") - { - hpwhModel = HPWH::MODELS_TamScalable_SP; - } - else if (modelName == "TamScalable_SP_2X") - { - hpwhModel = HPWH::MODELS_TamScalable_SP; - } - else if (modelName == "TamScalable_SP_Half") - { - hpwhModel = HPWH::MODELS_TamScalable_SP; - } - else if (modelName == "Scalable_MP") - { - hpwhModel = HPWH::MODELS_Scalable_MP; - } - else if (modelName == "AWHSTier3Generic40") - { - hpwhModel = HPWH::MODELS_AWHSTier3Generic40; - } - else if (modelName == "AWHSTier3Generic50") - { - hpwhModel = HPWH::MODELS_AWHSTier3Generic50; - } - else if (modelName == "AWHSTier3Generic65") - { - hpwhModel = HPWH::MODELS_AWHSTier3Generic65; - } - else if (modelName == "AWHSTier3Generic80") - { - hpwhModel = HPWH::MODELS_AWHSTier3Generic80; - } - else if (modelName == "AquaThermAire") - { - hpwhModel = HPWH::MODELS_AquaThermAire; - } - else - { - hpwhModel = HPWH::MODELS_basicIntegrated; - cout << "Couldn't find model " << modelName << ". Exiting...\n"; - exit(1); - } - return hpwhModel; -} - -int getHPWHObject(HPWH& hpwh, string modelName) -{ - /**Sets up the preset HPWH object with modelName */ - int returnVal = 1; - HPWH::MODELS model = mapStringToPreset(modelName); - - returnVal = hpwh.HPWHinit_presets(model); - - if (modelName == "TamScalable_SP_2X") - { - hpwh.setScaleHPWHCapacityCOP(2., 1.); // Scale the compressor - hpwh.setResistanceCapacity(60.); // Reset resistance elements in kW - } - else if (modelName == "TamScalable_SP_Half") - { - hpwh.setScaleHPWHCapacityCOP(1 / 2., 1.); // Scale the compressor - hpwh.setResistanceCapacity(15.); // Reset resistance elements in kW - } - return returnVal; -} diff --git a/test/unit_tests/CMakeLists.txt b/test/unit_tests/CMakeLists.txt new file mode 100644 index 00000000..c08c4671 --- /dev/null +++ b/test/unit_tests/CMakeLists.txt @@ -0,0 +1,29 @@ +set(library_files + unit-test.hh + scaleTest.cpp + energyBalanceTest.cpp + fixedTankSizeTest.cpp + sizingFractionsTest.cpp + maxSetpointTest.cpp + heatingLogicsTest.cpp + stateOfChargeFncsTest.cpp + resistanceFncsTest.cpp + compressorFncsTest.cpp + performanceMapTest.cpp + unit-test-main.cpp + ) + +add_executable(${PROJECT_NAME}_tests ${library_files}) + +target_compile_features(${PROJECT_NAME}_tests PRIVATE cxx_std_17) + +target_include_directories(${PROJECT_NAME}_tests PRIVATE ${PROJECT_BINARY_DIR}/src "${PROJECT_SOURCE_DIR}/src") + +target_link_libraries(${PROJECT_NAME}_tests ${PROJECT_NAME} gtest gmock fmt) + +include(GoogleTest) + +gtest_discover_tests( + ${PROJECT_NAME}_tests + TEST_PREFIX ${PROJECT_NAME}: + ) diff --git a/test/unit_tests/compressorFncsTest.cpp b/test/unit_tests/compressorFncsTest.cpp new file mode 100644 index 00000000..72cbfbfb --- /dev/null +++ b/test/unit_tests/compressorFncsTest.cpp @@ -0,0 +1,63 @@ +/* Copyright (c) 2023 Big Ladder Software LLC. All rights reserved. + * See the LICENSE file for additional terms and conditions. */ + +// HPWHsim +#include "HPWH.hh" +#include "unit-test.hh" + +struct CompressorFncsTest : public testing::Test +{ + const int intAbort = HPWH::HPWH_ABORT; + const double dblAbort = static_cast(HPWH::HPWH_ABORT); + + struct ModelSpecs + { + std::string sModelName; + bool hasCompressor; + int coilConfig; // 1: Wrapped, 2: External + int isMultipass; + int isExternalMultipass; + double maxSetpointT_C; + double minT_F; + }; + + const std::vector modelSpecs = { + {"AOSmithHPTU50", true, 1, true, false, HPWH::MAXOUTLET_R134A, 42.}, + {"Stiebel220e", true, 1, true, false, HPWH::MAXOUTLET_R134A, 32.}, + {"AOSmithCAHP120", true, 1, true, false, HPWH::MAXOUTLET_R134A, 47.}, + {"Sanden80", true, 2, false, false, HPWH::MAXOUTLET_R744, -25.}, + {"ColmacCxV_5_SP", true, 2, false, false, HPWH::MAXOUTLET_R410A, -4.}, + {"ColmacCxA_20_SP", true, 2, false, false, HPWH::MAXOUTLET_R134A, 40.}, + {"TamScalable_SP", true, 2, false, false, HPWH::MAXOUTLET_R134A, 40.}, + {"restankRealistic", false, intAbort, intAbort, intAbort, dblAbort, dblAbort}, + {"StorageTank", false, intAbort, intAbort, intAbort, dblAbort, dblAbort}, + {"ColmacCxA_20_MP", true, 2, true, true, HPWH::MAXOUTLET_R134A, 40.}, + {"Scalable_MP", true, 2, true, true, HPWH::MAXOUTLET_R134A, 40.}, + {"NyleC90A_MP", true, 2, true, true, F_TO_C(160.), 40.}, + {"NyleC90A_C_MP", true, 2, true, true, F_TO_C(160.), 35.}, + {"QAHV_N136TAU_HPB_SP", true, 2, false, false, F_TO_C(176.1), -13.}}; +}; + +/* + * compressorSpecs tests + */ +TEST_F(CompressorFncsTest, compressorSpecs) +{ + for (auto& modelSpec : modelSpecs) + { + // get preset model + HPWH hpwh; + EXPECT_EQ(hpwh.initPreset(modelSpec.sModelName), 0) + << "Could not initialize model " << modelSpec.sModelName; + + EXPECT_EQ(hpwh.hasACompressor(), modelSpec.hasCompressor) << modelSpec.sModelName; + EXPECT_EQ(hpwh.getCompressorCoilConfig(), modelSpec.coilConfig) << modelSpec.sModelName; + EXPECT_EQ(hpwh.isCompressorMultipass(), modelSpec.isMultipass) << modelSpec.sModelName; + EXPECT_EQ(hpwh.isCompressorExternalMultipass(), modelSpec.isExternalMultipass) + << modelSpec.sModelName; + EXPECT_EQ(hpwh.getMaxCompressorSetpoint(), modelSpec.maxSetpointT_C) + << modelSpec.sModelName; + EXPECT_EQ(hpwh.getMinOperatingTemp(HPWH::UNITS_F), modelSpec.minT_F) + << modelSpec.sModelName; + } +} diff --git a/test/unit_tests/energyBalanceTest.cpp b/test/unit_tests/energyBalanceTest.cpp new file mode 100644 index 00000000..1d900574 --- /dev/null +++ b/test/unit_tests/energyBalanceTest.cpp @@ -0,0 +1,93 @@ +/* Copyright (c) 2023 Big Ladder Software LLC. All rights reserved. + * See the LICENSE file for additional terms and conditions. */ + +// standard +#include + +// HPWHsim +#include "HPWH.hh" +#include "unit-test.hh" + +/* + * energyBalance tests + */ +TEST(EnergyBalanceTest, energyBalance) +{ + const double Pi = 4. * atan(1.); + + /* no extra heat */ + { + // get preset model + HPWH hpwh; + const std::string sModelName = "AOSmithHPTS50"; + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model."; + + const double maxDrawVol_L = 1.; + const double ambientT_C = 20.; + const double externalT_C = 20.; + + // + hpwh.setTankToTemperature(20.); + hpwh.setInletT(5.); + + constexpr double testDuration_min = 60.; + bool result = true; + int i_min = 0; + do + { + double t_min = static_cast(i_min); + + double flowFac = sin(Pi * t_min / testDuration_min) - 0.5; + flowFac += fabs(flowFac); // semi-sinusoidal flow profile + double drawVol_L = flowFac * maxDrawVol_L; + + double prevHeatContent_kJ = hpwh.getTankHeatContent_kJ(); + EXPECT_EQ(hpwh.runOneStep(drawVol_L, ambientT_C, externalT_C, HPWH::DR_ALLOW), 0); + result &= hpwh.isEnergyBalanced(drawVol_L, prevHeatContent_kJ, 1.e-6); + + ++i_min; + } while (result && (i_min < testDuration_min)); + + EXPECT_TRUE(result) << "Energy balance failed for model " << sModelName; + } + + /* storage tank with extra heat (solar) */ + { + // get preset model + HPWH hpwh; + const std::string sModelName = "StorageTank"; + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model."; + + const double maxDrawVol_L = 1.; + const double ambientT_C = 20.; + const double externalT_C = 20.; + + // + std::vector nodePowerExtra_W = {1000.}; + hpwh.setTankToTemperature(20.); + hpwh.setInletT(5.); + + constexpr double testDuration_min = 60.; + bool result = true; + int i_min = 0; + do + { + double t_min = static_cast(i_min); + + double flowFac = sin(Pi * t_min / testDuration_min) - 0.5; + flowFac += fabs(flowFac); // semi-sinusoidal flow profile + double drawVol_L = flowFac * maxDrawVol_L; + + double prevHeatContent_kJ = hpwh.getTankHeatContent_kJ(); + EXPECT_EQ( + hpwh.runOneStep( + drawVol_L, ambientT_C, externalT_C, HPWH::DR_ALLOW, 0., 0., &nodePowerExtra_W), + 0); + result &= hpwh.isEnergyBalanced(drawVol_L, prevHeatContent_kJ, 1.e-6); + + ++i_min; + } while (result && (i_min < testDuration_min)); + + EXPECT_TRUE(result) << "Energy balance failed for model " << sModelName; + } +} diff --git a/test/unit_tests/fixedTankSizeTest.cpp b/test/unit_tests/fixedTankSizeTest.cpp new file mode 100644 index 00000000..891d1b4d --- /dev/null +++ b/test/unit_tests/fixedTankSizeTest.cpp @@ -0,0 +1,66 @@ +/* Copyright (c) 2023 Big Ladder Software LLC. All rights reserved. + * See the LICENSE file for additional terms and conditions. */ + +// standard +#include + +// HPWHsim +#include "HPWH.hh" +#include "unit-test.hh" + +struct FixedSizeTest : public testing::Test +{ + const std::vector sModelNames = {"AOSmithHPTS50", + "AOSmithPHPT60", + "AOSmithHPTU80", + "Sanden80", + "RheemHB50", + "Stiebel220e", + "GE502014", + "Rheem2020Prem40", + "Rheem2020Prem50", + "Rheem2020Build50"}; +}; + +/* + * tankSizeFixed tests + */ +TEST_F(FixedSizeTest, tankSizeFixed) +{ + constexpr double tol = 1.e-4; + + for (auto& sModelName : sModelNames) + { + // get preset model + HPWH hpwh; + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + // get the initial tank size + double intitialTankSize_gal = hpwh.getTankSize(HPWH::UNITS_GAL); + + // get the target tank size + double targetTankSize_gal = intitialTankSize_gal + 100.; + + // change the tank size + hpwh.setTankSize(targetTankSize_gal, HPWH::UNITS_GAL); + + // change tank size (unforced) + if (hpwh.isTankSizeFixed()) + { // tank size should not have changed + EXPECT_NEAR(intitialTankSize_gal, hpwh.getTankSize(HPWH::UNITS_GAL), tol) + << "The tank size has changed when it should not."; + } + else + { // tank size should have changed to target value + EXPECT_NEAR(targetTankSize_gal, hpwh.getTankSize(HPWH::UNITS_GAL), tol) + << "The tank size did not change to the target value."; + } + + // change tank size (forced) + hpwh.setTankSize(targetTankSize_gal, HPWH::UNITS_GAL, true); + + // tank size should have changed to target value + EXPECT_NEAR(targetTankSize_gal, hpwh.getTankSize(HPWH::UNITS_GAL), tol) + << "The tank size has not changed when forced."; + } +} diff --git a/test/unit_tests/heatingLogicsTest.cpp b/test/unit_tests/heatingLogicsTest.cpp new file mode 100644 index 00000000..26bf1c73 --- /dev/null +++ b/test/unit_tests/heatingLogicsTest.cpp @@ -0,0 +1,352 @@ +/* Copyright (c) 2023 Big Ladder Software LLC. All rights reserved. + * See the LICENSE file for additional terms and conditions. */ + +// standard +#include + +// HPWHsim +#include "HPWH.hh" +#include "unit-test.hh" + +struct HeatingLogicsTest : public testing::Test +{ + const std::vector sHighShutOffSP_modelNames = {"Sanden80", + "QAHV_N136TAU_HPB_SP", + "ColmacCxA_20_SP", + "ColmacCxV_5_SP", + "NyleC60A_SP", + "NyleC60A_C_SP", + "NyleC185A_C_SP", + "TamScalable_SP"}; + + const std::vector sNoHighShutOffMP_externalModelNames = {"Scalable_MP", + "ColmacCxA_20_MP", + "ColmacCxA_15_MP", + "ColmacCxV_5_MP", + "NyleC90A_MP", + "NyleC90A_C_MP", + "NyleC250A_MP", + "NyleC250A_C_MP"}; + + const std::vector sNoHighShutOffIntegratedModelNames = {"AOSmithHPTU80", + "Rheem2020Build80", + "Stiebel220e", + "AOSmithCAHP120", + "AWHSTier3Generic80", + "Generic1", + "RheemPlugInDedicated50", + "RheemPlugInShared65", + "restankRealistic", + "StorageTank"}; +}; + +/* + * highShutOffSP tests + */ +TEST_F(HeatingLogicsTest, highShutOffSP) +{ + for (auto& sModelName : sHighShutOffSP_modelNames) + { + // get preset model + HPWH hpwh; + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + { // testHasEnteringWaterShutOff + int index = hpwh.getCompressorIndex() == -1 ? 0 : hpwh.getCompressorIndex(); + EXPECT_TRUE(hpwh.hasEnteringWaterHighTempShutOff(index)); + } + + { // testSetEnteringWaterShuffOffOutOfBoundsIndex + EXPECT_EQ(hpwh.setEnteringWaterHighTempShutOff(10., false, -1), HPWH::HPWH_ABORT); + EXPECT_EQ(hpwh.setEnteringWaterHighTempShutOff(10., false, 15), HPWH::HPWH_ABORT); + } + + { // testSetEnteringWaterShuffOffDeadbandToSmall + double value = HPWH::MINSINGLEPASSLIFT - 1.; + EXPECT_EQ(hpwh.setEnteringWaterHighTempShutOff(value, false, hpwh.getCompressorIndex()), + HPWH::HPWH_ABORT); + + value = HPWH::MINSINGLEPASSLIFT; + EXPECT_EQ(hpwh.setEnteringWaterHighTempShutOff(value, false, hpwh.getCompressorIndex()), + 0); + + value = hpwh.getSetpoint() - (HPWH::MINSINGLEPASSLIFT - 1); + EXPECT_EQ(hpwh.setEnteringWaterHighTempShutOff(value, true, hpwh.getCompressorIndex()), + HPWH::HPWH_ABORT); + + value = hpwh.getSetpoint() - HPWH::MINSINGLEPASSLIFT; + EXPECT_EQ(hpwh.setEnteringWaterHighTempShutOff(value, true, hpwh.getCompressorIndex()), + 0); + } + + { // testSetEnteringWaterHighTempShutOffAbsolute + const double drawVolume_L = 0.; + const double externalT_C = 20.; + const double delta = 2.; + const double highT_C = 20.; + const bool doAbsolute = true; + + // make tank cold to force on + hpwh.setTankToTemperature(highT_C); + + // run a step and check we're heating + hpwh.runOneStep(highT_C, drawVolume_L, externalT_C, externalT_C, HPWH::DR_ALLOW); + EXPECT_EQ(hpwh.isCompressorRunning(), 1); + + // change entering water temp to below temp + EXPECT_EQ(hpwh.setEnteringWaterHighTempShutOff( + highT_C - delta, doAbsolute, hpwh.getCompressorIndex()), + 0); + + // run a step and check we're not heating. + hpwh.runOneStep(highT_C, drawVolume_L, externalT_C, externalT_C, HPWH::DR_ALLOW); + EXPECT_EQ(hpwh.isCompressorRunning(), 0); + + // and reverse it + EXPECT_EQ(hpwh.setEnteringWaterHighTempShutOff( + highT_C + delta, doAbsolute, hpwh.getCompressorIndex()), + 0); + hpwh.runOneStep(highT_C, drawVolume_L, externalT_C, externalT_C, HPWH::DR_ALLOW); + EXPECT_EQ(hpwh.isCompressorRunning(), 1); + } + + { // testSetEnteringWaterHighTempShutOffRelative + const double drawVolume_L = 0.; + const double externalT_C = 20.; + const double delta = 2.; + const double highT_C = 20.; + const bool doAbsolute = false; + + const double relativeHighT_C = hpwh.getSetpoint() - highT_C; + // make tank cold to force on + hpwh.setTankToTemperature(highT_C); + + // run a step and check we're heating + hpwh.runOneStep(highT_C, drawVolume_L, externalT_C, externalT_C, HPWH::DR_ALLOW); + EXPECT_EQ(hpwh.isCompressorRunning(), 1); + + // change entering water temp to below temp + EXPECT_EQ(hpwh.setEnteringWaterHighTempShutOff( + relativeHighT_C + delta, doAbsolute, hpwh.getCompressorIndex()), + 0); + + // run a step and check we're not heating. + hpwh.runOneStep(highT_C, drawVolume_L, externalT_C, externalT_C, HPWH::DR_ALLOW); + EXPECT_EQ(hpwh.isCompressorRunning(), 0); + + // and reverse it + EXPECT_EQ(hpwh.setEnteringWaterHighTempShutOff( + relativeHighT_C - delta, doAbsolute, hpwh.getCompressorIndex()), + 0); + hpwh.runOneStep(highT_C, drawVolume_L, externalT_C, externalT_C, HPWH::DR_ALLOW); + EXPECT_EQ(hpwh.isCompressorRunning(), 1); + } + } +} + +/* + * noHighShutOffMP_external tests + */ +TEST_F(HeatingLogicsTest, noShutOffMP_external) +{ + for (auto& sModelName : sNoHighShutOffMP_externalModelNames) + { + // get preset model + HPWH hpwh; + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + { // testDoesNotHaveEnteringWaterShutOff + int index = hpwh.getCompressorIndex() == -1 ? 0 : hpwh.getCompressorIndex(); + EXPECT_FALSE(hpwh.hasEnteringWaterHighTempShutOff(index)); + } + + { // testCanNotSetEnteringWaterShutOff + int index = hpwh.getCompressorIndex() == -1 ? 0 : hpwh.getCompressorIndex(); + EXPECT_EQ(hpwh.setEnteringWaterHighTempShutOff(10., false, index), HPWH::HPWH_ABORT); + } + } +} + +/* + * state-of-charge logics tests + */ +TEST_F(HeatingLogicsTest, stateOfChargeLogics) +{ + std::vector sCombinedModelNames = sHighShutOffSP_modelNames; + sCombinedModelNames.insert(sCombinedModelNames.end(), + sNoHighShutOffMP_externalModelNames.begin(), + sNoHighShutOffMP_externalModelNames.end()); + + const double externalT_C = 20.; + const double setpointT_C = F_TO_C(149.); + + for (auto& sModelName : sCombinedModelNames) + { + // get preset model + HPWH hpwh; + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + if (!hpwh.isSetpointFixed()) + { + double temp; + std::string tempStr; + if (!hpwh.isNewSetpointPossible(setpointT_C, temp, tempStr)) + { + continue; // Numbers don't align for this type + } + hpwh.setSetpoint(setpointT_C); + } + + { // testChangeToStateofChargeControlled + double value = HPWH::MINSINGLEPASSLIFT - 1.; + const double externalT_C = 20.; + const double setpointT_C = F_TO_C(149.); + + const bool originalHasHighTempShutOff = + hpwh.hasEnteringWaterHighTempShutOff(hpwh.getCompressorIndex()); + if (!hpwh.isSetpointFixed()) + { + double temp; + std::string tempStr; + if (!hpwh.isNewSetpointPossible(setpointT_C, temp, tempStr)) + { + continue; // Numbers don't align for this type + } + hpwh.setSetpoint(setpointT_C); + } + + // Just created so should be fasle + EXPECT_FALSE(hpwh.isSoCControlled()); + + // change to SOC control; + hpwh.switchToSoCControls(.76, .05, 99, true, 49, HPWH::UNITS_F); + EXPECT_TRUE(hpwh.isSoCControlled()); + + // check entering water high temp shut off controll unchanged + EXPECT_EQ(hpwh.hasEnteringWaterHighTempShutOff(hpwh.getCompressorIndex()), + originalHasHighTempShutOff); + + // Test we can change the SoC and run a step and check we're heating + if (hpwh.hasEnteringWaterHighTempShutOff(hpwh.getCompressorIndex())) + { + EXPECT_EQ( + hpwh.setEnteringWaterHighTempShutOff( + setpointT_C - HPWH::MINSINGLEPASSLIFT, true, hpwh.getCompressorIndex()), + 0); // Force to ignore this part. + } + EXPECT_EQ(hpwh.setTankToTemperature(F_TO_C(100.)), 0); // .51 + hpwh.runOneStep(0, externalT_C, externalT_C, HPWH::DR_ALLOW); + EXPECT_EQ(hpwh.isCompressorRunning(), 1); + + // Test if we're on and in band stay on + hpwh.setTankToTemperature(F_TO_C(125)); // .76 (current target) + hpwh.runOneStep(0, externalT_C, externalT_C, HPWH::DR_ALLOW); + EXPECT_EQ(hpwh.isCompressorRunning(), 1); + + // Test we can change the SoC and turn off + hpwh.setTankToTemperature(F_TO_C(133)); // .84 + hpwh.runOneStep(0, externalT_C, externalT_C, HPWH::DR_ALLOW); + EXPECT_EQ(hpwh.isCompressorRunning(), 0); + + // Test if off and in band stay off + hpwh.setTankToTemperature(F_TO_C(125)); // .76 (current target) + hpwh.runOneStep(0, externalT_C, externalT_C, HPWH::DR_ALLOW); + EXPECT_EQ(hpwh.isCompressorRunning(), 0); + } + + { // testSetStateOfCharge + const double tempsForSetSoC[5][3] = { + {49, 99, 125}, {65, 110, 129}, {32, 120, 121}, {32, 33, 121}, {80, 81, 132.5}}; + + for (auto i = 0; i < 5; ++i) + { + double coldWaterT_F = tempsForSetSoC[i][0]; + double minUseT_F = tempsForSetSoC[i][1]; + double tankAt76SoC_T_F = tempsForSetSoC[i][2]; + + // change to SOC control; + hpwh.switchToSoCControls(.85, .05, minUseT_F, true, coldWaterT_F, HPWH::UNITS_F); + EXPECT_TRUE(hpwh.isSoCControlled()); + + // Test if we're on and in band stay on + hpwh.setTankToTemperature(F_TO_C(tankAt76SoC_T_F)); // .76 + hpwh.runOneStep(0, externalT_C, externalT_C, HPWH::DR_ALLOW); + EXPECT_EQ(hpwh.isCompressorRunning(), 1); + + // Test we can change the target SoC and turn off + hpwh.setTargetSoCFraction(0.5); + hpwh.runOneStep(0, externalT_C, externalT_C, HPWH::DR_ALLOW); + EXPECT_EQ(hpwh.isCompressorRunning(), 0); + + // Change back in the band and stay turned off + hpwh.setTargetSoCFraction(0.72); + hpwh.runOneStep(0, externalT_C, externalT_C, HPWH::DR_ALLOW); + EXPECT_EQ(hpwh.isCompressorRunning(), 0); + + // Drop below the band and turn on + hpwh.setTargetSoCFraction(0.70); + hpwh.runOneStep(0, externalT_C, externalT_C, HPWH::DR_ALLOW); + EXPECT_EQ(hpwh.isCompressorRunning(), 0); + } + } + } +} + +/* + * noHighShutOffIntegrated tests + */ +TEST_F(HeatingLogicsTest, noHighShutOffIntegrated) +{ + for (auto& sModelName : sNoHighShutOffIntegratedModelNames) + { + // get preset model + HPWH hpwh; + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + int index = hpwh.getCompressorIndex() == -1 ? 0 : hpwh.getCompressorIndex(); + { // testDoesNotHaveEnteringWaterShutOff + EXPECT_FALSE(hpwh.hasEnteringWaterHighTempShutOff(index)); + } + + { // testCannotSetEnteringWaterShutOff + EXPECT_EQ(hpwh.setEnteringWaterHighTempShutOff(10., false, index), HPWH::HPWH_ABORT); + } + } +} + +/* + * extraHeat test + */ +TEST(ExtraHeatTest, extraHeat) +{ + constexpr double tol = 1.e-4; + + const std::string sModelName = "StorageTank"; + + // get preset model + HPWH hpwh; + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + const double ambientT_C = 20.; + const double externalT_C = 20.; + const double inletVol2_L = 0.; + const double inletT2_C = 0.; + + double extraPower_W = 1000.; + std::vector nodePowerExtra_W = {extraPower_W}; + + // Test adding extra heat to a tank for one minute + hpwh.setUA(0.); + hpwh.setTankToTemperature(20.); + + double Q_init = hpwh.getTankHeatContent_kJ(); + hpwh.runOneStep( + 0, ambientT_C, externalT_C, HPWH::DR_LOC, inletVol2_L, inletT2_C, &nodePowerExtra_W); + double Q_final = hpwh.getTankHeatContent_kJ(); + + double dQ_actual_kJ = (Q_final - Q_init); + + double dQ_expected_kJ = extraPower_W * 60. / 1.e3; // 1 min + + EXPECT_NEAR(dQ_actual_kJ, dQ_expected_kJ, tol); +} diff --git a/test/unit_tests/maxSetpointTest.cpp b/test/unit_tests/maxSetpointTest.cpp new file mode 100644 index 00000000..11907a44 --- /dev/null +++ b/test/unit_tests/maxSetpointTest.cpp @@ -0,0 +1,322 @@ +/* Copyright (c) 2023 Big Ladder Software LLC. All rights reserved. + * See the LICENSE file for additional terms and conditions. */ + +// HPWHsim +#include "HPWH.hh" +#include "unit-test.hh" + +const double expectedRE_maxT_C = 100.; + +/* + * resistanceTank tests + */ +TEST(MaxSetpointTest, resistanceTank) +{ + HPWH hpwh; + EXPECT_EQ(hpwh.initResistanceTank(), 0) << "Could not initialize resistance tank."; + + double num; + std::string why; + + EXPECT_FALSE(hpwh.isNewSetpointPossible(101., num, why)); // Can't go above boiling + EXPECT_TRUE(hpwh.isNewSetpointPossible(99., num, why)); // Can go to near boiling + EXPECT_TRUE(hpwh.isNewSetpointPossible(100., num, why)); // Can go to boiling + EXPECT_TRUE(hpwh.isNewSetpointPossible(10., num, why)); // Can go low, albiet dumb + EXPECT_EQ(expectedRE_maxT_C, num); + + // Check this carries over into setting the setpoint + EXPECT_EQ(hpwh.setSetpoint(101.), HPWH::HPWH_ABORT); // Can't go above boiling + EXPECT_EQ(hpwh.setSetpoint(99.), 0); +} + +/* + * scalableCompressor tests + */ +TEST(MaxSetpointTest, scalableCompressor) +{ + // get preset model + HPWH hpwh; + const std::string sModelName = "TamScalable_SP"; + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + double num; + std::string why; + + EXPECT_FALSE(hpwh.isNewSetpointPossible(101., num, why)); // Can't go above boiling + EXPECT_TRUE(hpwh.isNewSetpointPossible(99., num, why)); // Can go to near boiling + EXPECT_TRUE(hpwh.isNewSetpointPossible(60., num, why)); // Can go to normal + EXPECT_TRUE(hpwh.isNewSetpointPossible(100, num, why)); // Can go to programed max + + // Check this carries over into setting the setpoint + EXPECT_EQ(hpwh.setSetpoint(101.), HPWH::HPWH_ABORT); // Can't go above boiling + EXPECT_EQ(hpwh.setSetpoint(50.), 0); +} + +/* + * NyleC90A_SP tests + */ +TEST(MaxSetpointTest, NyleC90A_SP) +{ + // get preset model + HPWH hpwh; + const std::string sModelName = "NyleC90A_SP"; + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + double num; + std::string why; + + EXPECT_FALSE(hpwh.isNewSetpointPossible(101., num, why)); // Can't go above boiling + EXPECT_FALSE(hpwh.isNewSetpointPossible(99., num, why)); // Can't go to near boiling + EXPECT_EQ(HPWH::MAXOUTLET_R134A, num); // Assert we're getting the right number + EXPECT_TRUE(hpwh.isNewSetpointPossible(60., num, why)); // Can go to normal + EXPECT_TRUE( + hpwh.isNewSetpointPossible(HPWH::MAXOUTLET_R134A, num, why)); // Can go to programed max + + // Check this carries over into setting the setpoint + EXPECT_EQ(hpwh.setSetpoint(101.), HPWH::HPWH_ABORT); // Can't go above boiling + EXPECT_EQ(hpwh.setSetpoint(50.), 0); +} + +/* + * ColmacCxV_5_SP tests + */ +TEST(MaxSetpointTest, ColmacCxV_5_SP) +{ + // get preset model + HPWH hpwh; + const std::string sModelName = "ColmacCxV_5_SP"; + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + double num; + std::string why; + + EXPECT_FALSE(hpwh.isNewSetpointPossible(101., num, why)); // Can't go above boiling + EXPECT_FALSE(hpwh.isNewSetpointPossible(99., num, why)); // Can't go to near boiling + EXPECT_TRUE(HPWH::MAXOUTLET_R410A == num); // Assert we're getting the right number + EXPECT_TRUE(hpwh.isNewSetpointPossible(50., num, why)); // Can go to normal + EXPECT_TRUE( + hpwh.isNewSetpointPossible(HPWH::MAXOUTLET_R410A, num, why)); // Can go to programed max + + // Check this carries over into setting the setpoint + EXPECT_EQ(hpwh.setSetpoint(101.), HPWH::HPWH_ABORT); // Can't go above boiling + EXPECT_EQ(hpwh.setSetpoint(50.), 0); +} + +/* + * QAHV_N136TAU_HPB_SP tests + */ +TEST(MaxSetpointTest, QAHV_N136TAU_HPB_SP) +{ + // get preset model + HPWH hpwh; + const std::string sModelName = "QAHV_N136TAU_HPB_SP"; + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + double num; + std::string why; + + const double maxQAHVSetpoint = F_TO_C(176.1); + const double qAHVHotSideTemepratureOffset = dF_TO_dC(15.); + + // isNewSetpointPossible should be fine, we aren't changing the setpoint of the Sanden. + EXPECT_FALSE(hpwh.isNewSetpointPossible(101., num, why)); // Can't go above boiling + EXPECT_FALSE(hpwh.isNewSetpointPossible(99., num, why)); // Can't go to near boiling + + EXPECT_TRUE(hpwh.isNewSetpointPossible(60., num, why)); // Can go to normal + + EXPECT_FALSE(hpwh.isNewSetpointPossible(maxQAHVSetpoint, num, why)); + EXPECT_TRUE( + hpwh.isNewSetpointPossible(maxQAHVSetpoint - qAHVHotSideTemepratureOffset, num, why)); + + // Check this carries over into setting the setpoint. + EXPECT_EQ(hpwh.setSetpoint(101), HPWH::HPWH_ABORT); + EXPECT_EQ(hpwh.setSetpoint(maxQAHVSetpoint), HPWH::HPWH_ABORT); + EXPECT_EQ(hpwh.setSetpoint(maxQAHVSetpoint - qAHVHotSideTemepratureOffset), 0); +} + +/* + * AOSmithCAHP120 tests + */ +TEST(MaxSetpointTest, AOSmithCAHP120) +{ + // get preset model + HPWH hpwh; + const std::string sModelName = "AOSmithCAHP120"; // Hybrid unit with a compressor with R134A + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + double num; + std::string why; + + EXPECT_FALSE(hpwh.isNewSetpointPossible(101., num, why)); // Can't go above boiling + EXPECT_TRUE(hpwh.isNewSetpointPossible(99., num, why)); // Can go to near boiling + EXPECT_TRUE(hpwh.isNewSetpointPossible(100., num, why)); // Can go to boiling + EXPECT_TRUE(hpwh.isNewSetpointPossible(10., num, why)); // Can go low, albiet dumb + EXPECT_EQ(expectedRE_maxT_C, num); // Max is boiling + + // Check this carries over into setting the setpoint + EXPECT_EQ(hpwh.setSetpoint(101.), HPWH::HPWH_ABORT); // Can't go above boiling + EXPECT_EQ(hpwh.setSetpoint(99.), 0); // Can go lower than boiling though +} + +/* + * StorageTank tests + */ +TEST(MaxSetpointTest, StorageTank) +{ + // get preset model + HPWH hpwh; + const std::string sModelName = "StorageTank"; // Hybrid unit with a compressor with R134A + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + ; + + double num; + std::string why; + + // Storage tanks have free reign! + EXPECT_TRUE(hpwh.isNewSetpointPossible(101., num, why)); // Can go above boiling! + EXPECT_TRUE(hpwh.isNewSetpointPossible(99., num, why)); // Can go to near boiling! + EXPECT_TRUE(hpwh.isNewSetpointPossible(10., num, why)); // Can go low, albiet dumb + + // Check this carries over into setting the setpoint + EXPECT_EQ(hpwh.setSetpoint(101.), 0); // Can go above boiling + EXPECT_EQ(hpwh.setSetpoint(99.), 0); // Can go lower than boiling though +} + +/* + * Sanden80 tests + */ +TEST(MaxSetpointTest, Sanden80) +{ + // get preset model + HPWH hpwh; + const std::string sModelName = "Sanden80"; // Fixed setpoint model + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + double num, num1; + std::string why; + + // Storage tanks have free reign! + EXPECT_FALSE(hpwh.isNewSetpointPossible(101., num, why)); // Can't go above boiling! + EXPECT_FALSE(hpwh.isNewSetpointPossible(99., num, why)); // Can't go to near boiling! + EXPECT_FALSE(hpwh.isNewSetpointPossible(60., num, why)); // Can't go to normalish + EXPECT_FALSE(hpwh.isNewSetpointPossible(10., num, why)); // Can't go low, albiet dumb + + EXPECT_EQ(num, hpwh.getSetpoint()); // Make sure it thinks the max is the setpoint + EXPECT_TRUE(hpwh.isNewSetpointPossible( + num, num1, why)); // Check that the setpoint can be set to the setpoint. + + // Check this carries over into setting the setpoint + EXPECT_EQ(hpwh.setSetpoint(101.), HPWH::HPWH_ABORT); // Can't go above boiling + EXPECT_EQ(hpwh.setSetpoint(99.), HPWH::HPWH_ABORT); // Can go lower than boiling though + EXPECT_EQ(hpwh.setSetpoint(60.), HPWH::HPWH_ABORT); // Can't go to normalish + EXPECT_EQ(hpwh.setSetpoint(10.), HPWH::HPWH_ABORT); // Can't go low, albiet dumb +} + +/* + * resample tests + */ +TEST(UtilityTest, resample) +{ + // test extensive resampling + std::vector values(10); + std::vector sampleValues {20., 40., 60., 40., 20.}; + EXPECT_TRUE(resampleExtensive(values, sampleValues)); + + // Check some expected values. + EXPECT_NEAR_REL(values[1], 10.); // + EXPECT_NEAR_REL(values[5], 30.); // + + // test intensive resampling + EXPECT_TRUE(resampleIntensive(values, sampleValues)); + + // Check some expected values. + EXPECT_NEAR_REL(values[1], 20.); // + EXPECT_NEAR_REL(values[5], 60.); // +} + +/* + * setTemperatures tests + */ +TEST(UtilityTest, setTemperatures) +{ + // get preset model + HPWH hpwh; + const std::string sModelName = "Rheem2020Prem50"; // 12-node model + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + // test 1 + { + std::vector setT_C {10., 60.}; + hpwh.setTankLayerTemperatures(setT_C); + + std::vector newT_C; + hpwh.getTankTemps(newT_C); + + // Check some expected values. + EXPECT_NEAR_REL(newT_C[0], 10.); // + EXPECT_NEAR_REL(newT_C[11], 60.); // + } + + // test 2 + { + std::vector setT_C = {10., 20., 30., 40., 50., 60.}; + hpwh.setTankLayerTemperatures(setT_C); + + std::vector newT_C; + hpwh.getTankTemps(newT_C); + + // Check some expected values. + EXPECT_NEAR_REL(newT_C[0], 10.); // + EXPECT_NEAR_REL(newT_C[5], 30.); // + EXPECT_NEAR_REL(newT_C[6], 40.); // + EXPECT_NEAR_REL(newT_C[11], 60.); // + } + + // test 3 + { + std::vector setT_C = { + 10., 15., 20., 25., 30., 35., 40., 45., 50., 55., 60., 65., 70., 75., 80., 85., 90.}; + hpwh.setTankLayerTemperatures(setT_C); + + std::vector newT_C; + hpwh.getTankTemps(newT_C); + + // Check some expected values. + EXPECT_NEAR_REL(newT_C[2], 25.2941); // + EXPECT_NEAR_REL(newT_C[8], 67.6471); // + } + + // test 4 + { + const std::size_t nSet = 24; + std::vector setT_C(nSet); + double initialT_C = 20., finalT_C = 66.; + for (std::size_t i = 0; i < nSet; ++i) + setT_C[i] = initialT_C + (finalT_C - initialT_C) * i / static_cast(nSet - 1); + hpwh.setTankLayerTemperatures(setT_C); + + std::vector newT_C; + hpwh.getTankTemps(newT_C); + + // Check some expected values. + EXPECT_NEAR_REL(newT_C[4], 37.); // + EXPECT_NEAR_REL(newT_C[10], 61.); // + } + + // test 5 + { + const std::size_t nSet = 12; + std::vector setT_C(nSet); + double initialT_C = 20., finalT_C = 64.; + for (std::size_t i = 0; i < nSet; ++i) + setT_C[i] = initialT_C + (finalT_C - initialT_C) * i / static_cast(nSet - 1); + hpwh.setTankLayerTemperatures(setT_C); + + std::vector newT_C; + hpwh.getTankTemps(newT_C); + + // Check some expected values. + EXPECT_NEAR_REL(newT_C[3], 32.); // + EXPECT_NEAR_REL(newT_C[11], 64.); // + } +} diff --git a/test/unit_tests/performanceMapTest.cpp b/test/unit_tests/performanceMapTest.cpp new file mode 100644 index 00000000..4e329a38 --- /dev/null +++ b/test/unit_tests/performanceMapTest.cpp @@ -0,0 +1,701 @@ +/* Copyright (c) 2023 Big Ladder Software LLC. All rights reserved. + * See the LICENSE file for additional terms and conditions. */ + +// HPWHsim +#include "HPWH.hh" +#include "unit-test.hh" + +struct PerformanceMapTest : public testing::Test +{ + const double tInOffsetQAHV_dF = 10.; + const double tOutOffsetQAHV_dF = 15.; + + struct performancePointMP + { + double tairF; + double tinF; + double outputBTUH; + }; + + double getCapacityMP_F_KW(HPWH& hpwh, performancePointMP& point) + { + return hpwh.getCompressorCapacity( + point.tairF, point.tinF, point.tinF, HPWH::UNITS_KW, HPWH::UNITS_F); + } + + struct performancePointSP + { + double tairF; + double toutF; + double tinF; + double outputBTUH; + }; + + double getCapacitySP_F_BTUHR(HPWH& hpwh, performancePointSP& point) + { + return hpwh.getCompressorCapacity( + point.tairF, point.tinF, point.toutF, HPWH::UNITS_BTUperHr, HPWH::UNITS_F); + } + + double getCapacitySP_F_BTUHR(HPWH& hpwh, + performancePointSP& point, + double tInOffSet_dF, + double tOutOffSet_dF) + { + return hpwh.getCompressorCapacity(point.tairF, + point.tinF - tInOffSet_dF, + point.toutF - tOutOffSet_dF, + HPWH::UNITS_BTUperHr, + HPWH::UNITS_F); + } +}; + +/* + * ColmacCxA_15_SP tests + */ +TEST_F(PerformanceMapTest, ColmacCxA_15_SP) +{ + // get preset model + HPWH hpwh; + const std::string sModelName = "ColmacCxA_15_SP"; + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + double capacity_kW, capacity_BTUperHr; + + // test hot ////////////////////////// + double airTempF = 100.; + double waterTempF = 125.; + double setpointF = 150.; + double capacityData_kW = 52.779317; + + capacity_BTUperHr = hpwh.getCompressorCapacity( + airTempF, waterTempF, setpointF, HPWH::UNITS_BTUperHr, HPWH::UNITS_F); + capacity_kW = + hpwh.getCompressorCapacity(F_TO_C(airTempF), F_TO_C(waterTempF), F_TO_C(setpointF)); + + EXPECT_NEAR_REL(KWH_TO_BTU(capacityData_kW), capacity_BTUperHr); + EXPECT_NEAR_REL(capacityData_kW, capacity_kW); + + // test middle //////////////// + airTempF = 80.; + waterTempF = 40.; + setpointF = 150.; + capacityData_kW = 44.962957379; + + capacity_BTUperHr = hpwh.getCompressorCapacity( + airTempF, waterTempF, setpointF, HPWH::UNITS_BTUperHr, HPWH::UNITS_F); + capacity_kW = + hpwh.getCompressorCapacity(F_TO_C(airTempF), F_TO_C(waterTempF), F_TO_C(setpointF)); + + EXPECT_NEAR_REL(KWH_TO_BTU(capacityData_kW), capacity_BTUperHr); + EXPECT_NEAR_REL(capacityData_kW, capacity_kW); + + // test cold //////////////// + airTempF = 60.; + waterTempF = 40.; + setpointF = 125.; + capacityData_kW = 37.5978306881; + + capacity_BTUperHr = hpwh.getCompressorCapacity( + airTempF, waterTempF, setpointF, HPWH::UNITS_BTUperHr, HPWH::UNITS_F); + capacity_kW = + hpwh.getCompressorCapacity(F_TO_C(airTempF), F_TO_C(waterTempF), F_TO_C(setpointF)); + + EXPECT_NEAR_REL(KWH_TO_BTU(capacityData_kW), capacity_BTUperHr); + EXPECT_NEAR_REL(capacityData_kW, capacity_kW); +} + +/* + * ColmacCxA_30_SP tests + */ +TEST_F(PerformanceMapTest, ColmacCxA_30_SP) +{ + // get preset model + HPWH hpwh; + const std::string sModelName = "ColmacCxA_30_SP"; + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + double capacity_kW, capacity_BTUperHr; + + // test hot ////////////////////////// + double airTempF = 100.; + double waterTempF = 125.; + double setpointF = 150.; + double capacityData_kW = 105.12836804; + + capacity_BTUperHr = hpwh.getCompressorCapacity( + airTempF, waterTempF, setpointF, HPWH::UNITS_BTUperHr, HPWH::UNITS_F); + capacity_kW = + hpwh.getCompressorCapacity(F_TO_C(airTempF), F_TO_C(waterTempF), F_TO_C(setpointF)); + + EXPECT_NEAR_REL(KWH_TO_BTU(capacityData_kW), capacity_BTUperHr); + EXPECT_NEAR_REL(capacityData_kW, capacity_kW); + + // test middle //////////////// + airTempF = 80.; + waterTempF = 40.; + setpointF = 150.; + capacityData_kW = 89.186101453; + + capacity_BTUperHr = hpwh.getCompressorCapacity( + airTempF, waterTempF, setpointF, HPWH::UNITS_BTUperHr, HPWH::UNITS_F); + capacity_kW = + hpwh.getCompressorCapacity(F_TO_C(airTempF), F_TO_C(waterTempF), F_TO_C(setpointF)); + + EXPECT_NEAR_REL(KWH_TO_BTU(capacityData_kW), capacity_BTUperHr); + EXPECT_NEAR_REL(capacityData_kW, capacity_kW); + + // test cold //////////////// + airTempF = 60.; + waterTempF = 40.; + setpointF = 125.; + capacityData_kW = 74.2437689948; + + capacity_BTUperHr = hpwh.getCompressorCapacity( + airTempF, waterTempF, setpointF, HPWH::UNITS_BTUperHr, HPWH::UNITS_F); + capacity_kW = + hpwh.getCompressorCapacity(F_TO_C(airTempF), F_TO_C(waterTempF), F_TO_C(setpointF)); + + EXPECT_NEAR_REL(KWH_TO_BTU(capacityData_kW), capacity_BTUperHr); + EXPECT_NEAR_REL(capacityData_kW, capacity_kW); +} + +/* + * ColmacCxV_5_MP tests + */ +TEST_F(PerformanceMapTest, ColmacCxV_5_MP) +{ + // get preset model + HPWH hpwh; + const std::string sModelName = "ColmacCxV_5_MP"; + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + performancePointMP checkPoint; + + // test some points outside of defrost //////////////// + checkPoint = {10.0, 60.0, 8.7756391}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); + + checkPoint = {10.0, 102.0, 9.945545}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); + + checkPoint = {70.0, 74.0, 19.09682784}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); + + checkPoint = {70.0, 116.0, 18.97090763}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); + + checkPoint = {100.0, 116.0, 24.48703111}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); +} + +/* + * ColmacCxA_10_MP tests + */ +TEST_F(PerformanceMapTest, ColmacCxA_10_MP) +{ + // get preset model + HPWH hpwh; + const std::string sModelName = "ColmacCxA_10_MP"; + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + performancePointMP checkPoint; + + // test some points outside of defrost //////////////// + checkPoint = {60.0, 66.0, 29.36581754}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); + + checkPoint = {60.0, 114.0, 27.7407144}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); + + checkPoint = {80.0, 66.0, 37.4860496}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); + + checkPoint = {80.0, 114.0, 35.03416199}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); + + checkPoint = {100.0, 66.0, 46.63144}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); + + checkPoint = {100.0, 114.0, 43.4308219}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); +} + +/* + * ColmacCxA_15_MP tests + */ +TEST_F(PerformanceMapTest, ColmacCxA_15_MP) +{ + // get preset model + HPWH hpwh; + const std::string sModelName = "ColmacCxA_15_MP"; + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + performancePointMP checkPoint; + + // test some points outside of defrost //////////////// + checkPoint = {60.0, 66.0, 37.94515042}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); + + checkPoint = {60.0, 114.0, 35.2295393}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); + + checkPoint = {80.0, 66.0, 50.360549115}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); + + checkPoint = {80.0, 114.0, 43.528417017}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); + + checkPoint = {100.0, 66.0, 66.2675493}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); + + checkPoint = {100.0, 114.0, 55.941855}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); +} + +/* + * ColmacCxA_20_MP tests + */ +TEST_F(PerformanceMapTest, ColmacCxA_20_MP) +{ + // get preset model + HPWH hpwh; + const std::string sModelName = "ColmacCxA_20_MP"; + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + performancePointMP checkPoint; + + // test some points outside of defrost //////////////// + checkPoint = {60.0, 66.0, 57.0994624}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); + + checkPoint = {60.0, 114.0, 53.554293}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); + + checkPoint = {80.0, 66.0, 73.11242842}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); + + checkPoint = {80.0, 114.0, 68.034677}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); + + checkPoint = {100.0, 66.0, 90.289474295}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); + + checkPoint = {100.0, 114.0, 84.69323}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); +} + +/* + * ColmacCxA_25_MP tests + */ +TEST_F(PerformanceMapTest, ColmacCxA_25_MP) +{ + // get preset model + HPWH hpwh; + const std::string sModelName = "ColmacCxA_25_MP"; + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + performancePointMP checkPoint; + + // test some points outside of defrost //////////////// + checkPoint = {60.0, 66.0, 67.28116620}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); + + checkPoint = {60.0, 114.0, 63.5665037}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); + + checkPoint = {80.0, 66.0, 84.9221285742}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); + + checkPoint = {80.0, 114.0, 79.6237088}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); + + checkPoint = {100.0, 66.0, 103.43268186}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); + + checkPoint = {100.0, 114.0, 97.71458413}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); +} + +/* + * ColmacCxA_30_MP tests + */ +TEST_F(PerformanceMapTest, ColmacCxA_30_MP) +{ + // get preset model + HPWH hpwh; + const std::string sModelName = "ColmacCxA_30_MP"; + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + performancePointMP checkPoint; + + // test some points outside of defrost //////////////// + checkPoint = {60.0, 66.0, 76.741462845}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); + + checkPoint = {60.0, 114.0, 73.66879620}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); + + checkPoint = {80.0, 66.0, 94.863116775}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); + + checkPoint = {80.0, 114.0, 90.998904269}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); + + checkPoint = {100.0, 66.0, 112.864628}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); + + checkPoint = {100.0, 114.0, 109.444451}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); +} + +/* + * RheemHPHD60 tests + */ +TEST_F(PerformanceMapTest, RheemHPHD60) +{ + // MODELS_RHEEM_HPHD60HNU_201_MP + // MODELS_RHEEM_HPHD60VNU_201_MP + // get preset model + HPWH hpwh; + const std::string sModelName = "RheemHPHD60"; + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + performancePointMP checkPoint; + + // test some points outside of defrost //////////////// + checkPoint = {66.6666666, 60.0, 16.785535996}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); + checkPoint = {66.6666666, 120.0, 16.76198953}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); + checkPoint = {88.3333333, 80.0, 20.8571194294}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); + checkPoint = {110.0, 100.0, 24.287512}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); +} + +/* + * RheemHPHD135 tests + */ +TEST_F(PerformanceMapTest, RheemHPHD135) +{ + // MODELS_RHEEM_HPHD135HNU_483_MP + // MODELS_RHEEM_HPHD135VNU_483_MP + HPWH hpwh; + const std::string sModelName = "RheemHPHD135"; + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + performancePointMP checkPoint; + + // test some points outside of defrost //////////////// + checkPoint = {66.6666666, 80.0, 38.560161199}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); + checkPoint = {66.6666666, 140.0, 34.70681846}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); + checkPoint = {88.3333333, 140.0, 42.40407101}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); + checkPoint = {110.0, 120.0, 54.3580927}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); +} + +/* + * NyleC60A_MP tests + */ +TEST_F(PerformanceMapTest, NyleC60A_MP) +{ + HPWH hpwh; + const std::string sModelName = "NyleC60A_MP"; + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + performancePointMP checkPoint; + + // test some points outside of defrost //////////////// + checkPoint = {60.0, 60.0, 16.11}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); + checkPoint = {80.0, 60.0, 21.33}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); + checkPoint = {90.0, 130.0, 19.52}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); +} + +/* + * NyleC60A_MP tests + */ +TEST_F(PerformanceMapTest, NyleC90A_MP) +{ + HPWH hpwh; + const std::string sModelName = "NyleC90A_MP"; + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + performancePointMP checkPoint; + + // test some points outside of defrost //////////////// + checkPoint = {60.0, 60.0, 28.19}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); + checkPoint = {80.0, 60.0, 37.69}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); + checkPoint = {90.0, 130.0, 36.27}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); +} + +/* + * NyleC125A_MP tests + */ +TEST_F(PerformanceMapTest, NyleC125A_MP) +{ + HPWH hpwh; + const std::string sModelName = "NyleC125A_MP"; + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + performancePointMP checkPoint; + + // test some points outside of defrost //////////////// + checkPoint = {60.0, 60.0, 36.04}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); + checkPoint = {80.0, 60.0, 47.86}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); + checkPoint = {90.0, 130.0, 43.80}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); +} + +/* + * NyleC185A_MP tests + */ +TEST_F(PerformanceMapTest, NyleC185A_MP) +{ + HPWH hpwh; + const std::string sModelName = "NyleC185A_MP"; + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + performancePointMP checkPoint; + + // test some points outside of defrost //////////////// + checkPoint = {60.0, 60.0, 55.00}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); + checkPoint = {80.0, 60.0, 74.65}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); + checkPoint = {90.0, 130.0, 67.52}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); +} + +/* + * NyleC250A_MP tests + */ +TEST_F(PerformanceMapTest, NyleC250A_MP) +{ + HPWH hpwh; + const std::string sModelName = "NyleC250A_MP"; + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + performancePointMP checkPoint; + + // test some points outside of defrost //////////////// + checkPoint = {60.0, 60.0, 75.70}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); + checkPoint = {80.0, 60.0, 103.40}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); + checkPoint = {90.0, 130.0, 77.89}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, getCapacityMP_F_KW(hpwh, checkPoint)); +} + +/* + * QAHV_N136TAU_HPB_SP tests + */ +TEST_F(PerformanceMapTest, QAHV_N136TAU_HPB_SP) +{ + HPWH hpwh; + const std::string sModelName = "QAHV_N136TAU_HPB_SP"; + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + performancePointSP checkPoint; // tairF, toutF, tinF, outputW + double outputBTUH; + + // test + checkPoint = {-13.0, 140.0, 41.0, 66529.49616}; + outputBTUH = getCapacitySP_F_BTUHR(hpwh, checkPoint, tInOffsetQAHV_dF, tOutOffsetQAHV_dF); + EXPECT_NEAR_REL(checkPoint.outputBTUH, outputBTUH); + // test + checkPoint = {-13.0, 176.0, 41.0, 65872.597448}; + EXPECT_EQ(getCapacitySP_F_BTUHR(hpwh, checkPoint), + HPWH::HPWH_ABORT); // max setpoint without adjustment forces error + EXPECT_NEAR_REL(checkPoint.outputBTUH, + getCapacitySP_F_BTUHR(hpwh, checkPoint, tInOffsetQAHV_dF, tOutOffsetQAHV_dF)); + + // test + checkPoint = {-13.0, 176.0, 84.2, 55913.249232}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, + getCapacitySP_F_BTUHR(hpwh, checkPoint, tInOffsetQAHV_dF, tOutOffsetQAHV_dF)); + + // test + checkPoint = {14.0, 176.0, 84.2, 92933.01932}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, + getCapacitySP_F_BTUHR(hpwh, checkPoint, tInOffsetQAHV_dF, tOutOffsetQAHV_dF)); + + // test + checkPoint = {42.8, 140.0, 41.0, 136425.98804}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, + getCapacitySP_F_BTUHR(hpwh, checkPoint, tInOffsetQAHV_dF, tOutOffsetQAHV_dF)); + + // test + checkPoint = {50.0, 140.0, 41.0, 136425.98804}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, + getCapacitySP_F_BTUHR(hpwh, checkPoint, tInOffsetQAHV_dF, tOutOffsetQAHV_dF)); + + // test + checkPoint = {50.0, 176.0, 84.2, 136564.470884}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, + getCapacitySP_F_BTUHR(hpwh, checkPoint, tInOffsetQAHV_dF, tOutOffsetQAHV_dF)); + // test + checkPoint = {60.8, 158.0, 84.2, 136461.998288}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, + getCapacitySP_F_BTUHR(hpwh, checkPoint, tInOffsetQAHV_dF, tOutOffsetQAHV_dF)); + + // test + checkPoint = {71.6, 158.0, 48.2, 136498.001712}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, + getCapacitySP_F_BTUHR(hpwh, checkPoint, tInOffsetQAHV_dF, tOutOffsetQAHV_dF)); + + // test constant with setpoint between 140 and 158 + checkPoint = {71.6, 149.0, 48.2, 136498.001712}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, + getCapacitySP_F_BTUHR(hpwh, checkPoint, tInOffsetQAHV_dF, tOutOffsetQAHV_dF)); + + // test + checkPoint = {82.4, 176.0, 41.0, 136557.496756}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, + getCapacitySP_F_BTUHR(hpwh, checkPoint, tInOffsetQAHV_dF, tOutOffsetQAHV_dF)); + + // test + checkPoint = {104.0, 140.0, 62.6, 136480}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, + getCapacitySP_F_BTUHR(hpwh, checkPoint, tInOffsetQAHV_dF, tOutOffsetQAHV_dF)); + // test + checkPoint = {104.0, 158.0, 62.6, 136480}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, + getCapacitySP_F_BTUHR(hpwh, checkPoint, tInOffsetQAHV_dF, tOutOffsetQAHV_dF)); + // test + checkPoint = {104.0, 176.0, 84.2, 136564.470884}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, + getCapacitySP_F_BTUHR(hpwh, checkPoint, tInOffsetQAHV_dF, tOutOffsetQAHV_dF)); +} + +/* + * QAHV_N136TAU_HPB_SP_extrapolation tests + */ +TEST_F(PerformanceMapTest, QAHV_N136TAU_HPB_SP_extrapolation) +{ + // Also test QAHV constant extrpolation at high air temperatures AND linear extrapolation to hot + // water temperatures! + + HPWH hpwh; + const std::string sModelName = "QAHV_N136TAU_HPB_SP"; + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + performancePointSP checkPoint; // tairF, toutF, tinF, outputW + + // test linear along Tin + checkPoint = {-13.0, 140.0, 36.0, 66529.49616}; + EXPECT_TRUE( + checkPoint.outputBTUH < + getCapacitySP_F_BTUHR( + hpwh, checkPoint, tInOffsetQAHV_dF, tOutOffsetQAHV_dF)); // Check output has increased + + // test linear along Tin + checkPoint = {-13.0, 140.0, 100.0, 66529.49616}; + EXPECT_TRUE( + checkPoint.outputBTUH > + getCapacitySP_F_BTUHR( + hpwh, checkPoint, tInOffsetQAHV_dF, tOutOffsetQAHV_dF)); // Check output has decreased + + // test linear along Tin + checkPoint = {-13.0, 176.0, 36.0, 65872.597448}; + EXPECT_TRUE( + checkPoint.outputBTUH < + getCapacitySP_F_BTUHR( + hpwh, checkPoint, tInOffsetQAHV_dF, tOutOffsetQAHV_dF)); // Check output has increased + + // test linear along Tin + checkPoint = {-13.0, 176.0, 100.0, 55913.249232}; + EXPECT_TRUE(checkPoint.outputBTUH > + getCapacitySP_F_BTUHR(hpwh, + checkPoint, + tInOffsetQAHV_dF, + tOutOffsetQAHV_dF)); // Check output has decreased at high Tin + + // test linear along Tin + checkPoint = {10.4, 140.0, 111., 89000.085396}; + EXPECT_TRUE(checkPoint.outputBTUH > + getCapacitySP_F_BTUHR(hpwh, + checkPoint, + tInOffsetQAHV_dF, + tOutOffsetQAHV_dF)); // Check output has decreased at high Tin + + // test linear along Tin + checkPoint = {64.4, 158.0, 100, 136461.998288}; + EXPECT_TRUE(checkPoint.outputBTUH > + getCapacitySP_F_BTUHR(hpwh, + checkPoint, + tInOffsetQAHV_dF, + tOutOffsetQAHV_dF)); // Check output has decreased at high Tin + + // test linear along Tin + checkPoint = {86.0, 158.0, 100, 136461.998288}; + EXPECT_TRUE(checkPoint.outputBTUH > + getCapacitySP_F_BTUHR(hpwh, + checkPoint, + tInOffsetQAHV_dF, + tOutOffsetQAHV_dF)); // Check output has decreased at high Tin + + // test linear along Tin + checkPoint = {104.0, 176.0, 100., 136564.470884}; + EXPECT_TRUE(checkPoint.outputBTUH > + getCapacitySP_F_BTUHR(hpwh, + checkPoint, + tInOffsetQAHV_dF, + tOutOffsetQAHV_dF)); // Check output has decreased at high Tin + + // test const along Tair + checkPoint = {110.0, 140.0, 62.6, 136480}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, + getCapacitySP_F_BTUHR(hpwh, checkPoint, tInOffsetQAHV_dF, tOutOffsetQAHV_dF)); + + // test const along Tair + checkPoint = {114.0, 176.0, 84.2, 136564.470884}; + EXPECT_NEAR_REL(checkPoint.outputBTUH, + getCapacitySP_F_BTUHR(hpwh, checkPoint, tInOffsetQAHV_dF, tOutOffsetQAHV_dF)); + + checkPoint = {114.0, 200.0, 84.2, 136564.470884}; + EXPECT_EQ(getCapacitySP_F_BTUHR(hpwh, checkPoint, tInOffsetQAHV_dF, tOutOffsetQAHV_dF), + HPWH::HPWH_ABORT); +} + +/* + * Sanden120 tests + */ +TEST_F(PerformanceMapTest, Sanden120) +{ + HPWH hpwh; + const std::string sModelName = "Sanden120"; + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + performancePointSP checkPoint; // tairF, toutF, tinF, outputW + double outputBTUH; + + // nominal + checkPoint = {60, 149.0, 41.0, 15059.59167}; + outputBTUH = hpwh.getCompressorCapacity( + checkPoint.tairF, checkPoint.tinF, checkPoint.toutF, HPWH::UNITS_BTUperHr, HPWH::UNITS_F); + EXPECT_NEAR_REL(checkPoint.outputBTUH, outputBTUH); + + // Cold outlet temperature + checkPoint = {60, 125.0, 41.0, 15059.59167}; + outputBTUH = hpwh.getCompressorCapacity( + checkPoint.tairF, checkPoint.tinF, checkPoint.toutF, HPWH::UNITS_BTUperHr, HPWH::UNITS_F); + EXPECT_NEAR_REL(checkPoint.outputBTUH, outputBTUH); + + // tests fails when output high + checkPoint = {60, 200, 41.0, 15059.59167}; + outputBTUH = hpwh.getCompressorCapacity( + checkPoint.tairF, checkPoint.tinF, checkPoint.toutF, HPWH::UNITS_BTUperHr, HPWH::UNITS_F); + EXPECT_EQ(outputBTUH, HPWH::HPWH_ABORT); +} diff --git a/test/unit_tests/resistanceFncsTest.cpp b/test/unit_tests/resistanceFncsTest.cpp new file mode 100644 index 00000000..ae2c849c --- /dev/null +++ b/test/unit_tests/resistanceFncsTest.cpp @@ -0,0 +1,294 @@ +/* Copyright (c) 2023 Big Ladder Software LLC. All rights reserved. + * See the LICENSE file for additional terms and conditions. */ + +// HPWHsim +#include "HPWH.hh" +#include "unit-test.hh" + +/* + * setResistanceCapacityErrorChecks tests + */ +TEST(ResistanceFunctionsTest, setResistanceCapacityErrorChecks) +{ + { + // get preset model + HPWH hpwh; + const std::string sModelName = "ColmacCxA_30_SP"; + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + EXPECT_EQ(hpwh.setResistanceCapacity(100.), HPWH::HPWH_ABORT); // Need's to be scalable + } + + { + // get preset model + HPWH hpwh; + const std::string sModelName = "restankRealistic"; + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + EXPECT_EQ(hpwh.setResistanceCapacity(-100.), HPWH::HPWH_ABORT); + EXPECT_EQ(hpwh.setResistanceCapacity(100., 3), HPWH::HPWH_ABORT); + EXPECT_EQ(hpwh.setResistanceCapacity(100., 30000), HPWH::HPWH_ABORT); + EXPECT_EQ(hpwh.setResistanceCapacity(100., -3), HPWH::HPWH_ABORT); + EXPECT_EQ(hpwh.setResistanceCapacity(100., 0, HPWH::UNITS_F), HPWH::HPWH_ABORT); + } +} + +/* + * getSetResistanceErrors tests + */ +TEST(ResistanceFunctionsTest, getSetResistanceErrors) +{ + HPWH hpwh; + double lowerElementPower_W = 1000; + double lowerElementPower = lowerElementPower_W / 1000; + EXPECT_EQ(hpwh.initResistanceTank(100., 0.95, 0., lowerElementPower_W), 0) + << "Could not initialize resistance tank."; + + double returnVal; + + returnVal = hpwh.getResistanceCapacity(0, HPWH::UNITS_KW); // lower + EXPECT_NEAR_REL(returnVal, lowerElementPower); + + returnVal = hpwh.getResistanceCapacity(-1, HPWH::UNITS_KW); // both, + EXPECT_NEAR_REL(returnVal, lowerElementPower); + + returnVal = hpwh.getResistanceCapacity(1, HPWH::UNITS_KW); // higher doesn't exist + EXPECT_EQ(returnVal, HPWH::HPWH_ABORT); +} + +/* + * commercialTankInitErrors tests + */ +TEST(ResistanceFunctionsTest, commercialTankInitErrors) +{ + HPWH hpwh; + + // init model + EXPECT_EQ(hpwh.initResistanceTankGeneric(-800., 10., 100., 100.), + HPWH::HPWH_ABORT); // negative volume + EXPECT_EQ(hpwh.initResistanceTankGeneric(800., 10., -100., 100.), + HPWH::HPWH_ABORT); // negative element + EXPECT_EQ(hpwh.initResistanceTankGeneric(800., 10., 100., -100.), + HPWH::HPWH_ABORT); // negative element + EXPECT_EQ(hpwh.initResistanceTankGeneric(800., -10., 100., 100.), + HPWH::HPWH_ABORT); // negative r value + EXPECT_EQ(hpwh.initResistanceTankGeneric(800., 0., 100., 100.), HPWH::HPWH_ABORT); // 0 r value + EXPECT_EQ(hpwh.initResistanceTankGeneric(800., 10., 0., 0.), + HPWH::HPWH_ABORT); // Check needs one element +} + +/* + * getNumResistanceElements tests + */ +TEST(ResistanceFunctionsTest, getNumResistanceElements) +{ + HPWH hpwh; + + EXPECT_EQ(hpwh.initResistanceTankGeneric(800., 10., 0., 1000.), 0); + EXPECT_EQ(hpwh.getNumResistanceElements(), 1); // Check 1 elements + + EXPECT_EQ(hpwh.initResistanceTankGeneric(800., 10., 1000., 0.), 0); + EXPECT_EQ(hpwh.getNumResistanceElements(), 1); // Check 1 elements + + EXPECT_EQ(hpwh.initResistanceTankGeneric(800., 10., 1000., 1000.), 0); + EXPECT_EQ(hpwh.getNumResistanceElements(), 2); // Check 2 elements +} + +/* + * getResistancePositionInRE_tank tests + */ +TEST(ResistanceFunctionsTest, getResistancePositionInRE_tank) +{ + HPWH hpwh; + + EXPECT_EQ(hpwh.initResistanceTankGeneric(800., 10., 0., 1000.), 0); + EXPECT_EQ(hpwh.getResistancePosition(0), 0); // Check lower element is there + EXPECT_EQ(hpwh.getResistancePosition(1), HPWH::HPWH_ABORT); // Check no element + EXPECT_EQ(hpwh.getResistancePosition(2), HPWH::HPWH_ABORT); // Check no element + + EXPECT_EQ(hpwh.initResistanceTankGeneric(800., 10., 1000., 0.), 0); + EXPECT_EQ(hpwh.getResistancePosition(0), 8); // Check upper element there + EXPECT_EQ(hpwh.getResistancePosition(1), HPWH::HPWH_ABORT); // Check no elements + EXPECT_EQ(hpwh.getResistancePosition(2), HPWH::HPWH_ABORT); // Check no elements + + EXPECT_EQ(hpwh.initResistanceTankGeneric(800., 10., 1000., 1000.), 0); + EXPECT_EQ(hpwh.getResistancePosition(0), 8); // Check upper element there + EXPECT_EQ(hpwh.getResistancePosition(1), 0); // Check lower element is there + EXPECT_EQ(hpwh.getResistancePosition(2), HPWH::HPWH_ABORT); // Check 0 elements} +} + +/* + * getResistancePositionInCompressorTank test + */ +TEST(ResistanceFunctionsTest, getResistancePositionInCompressorTank) +{ + + // get preset model + HPWH hpwh; + const std::string sModelName = "TamScalable_SP"; + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + EXPECT_EQ(hpwh.getResistancePosition(0), 9); // Check top elements + EXPECT_EQ(hpwh.getResistancePosition(1), 0); // Check bottom elements + EXPECT_EQ(hpwh.getResistancePosition(2), HPWH::HPWH_ABORT); // Check compressor isn't RE + EXPECT_EQ(hpwh.getResistancePosition(-1), HPWH::HPWH_ABORT); // Check out of bounds + EXPECT_EQ(hpwh.getResistancePosition(1000), HPWH::HPWH_ABORT); // Check out of bounds +} + +/* + * commercialTankErrorsWithBottomElement test + */ +TEST(ResistanceFunctionsTest, commercialTankErrorsWithBottomElement) +{ + const double elementPower_kW = 10.; // kW + + // init model + HPWH hpwh; + EXPECT_EQ(hpwh.initResistanceTankGeneric(800., 10., 0., elementPower_kW * 1000.), 0) + << "Could not initialize generic resistance tank."; + + // Check only lowest setting works + double factor = 3.; + + // set both, but really only one + EXPECT_EQ(hpwh.setResistanceCapacity(factor * elementPower_kW, -1, HPWH::UNITS_KW), + 0); // Check sets + EXPECT_NEAR_REL(hpwh.getResistanceCapacity(-1, HPWH::UNITS_KW), + factor * elementPower_kW); // Check gets just bottom with both + EXPECT_NEAR_REL(hpwh.getResistanceCapacity(0, HPWH::UNITS_KW), + factor * elementPower_kW); // Check gets bottom with bottom + EXPECT_EQ(hpwh.getResistanceCapacity(1, HPWH::UNITS_KW), + HPWH::HPWH_ABORT); // only have one element + + // set lowest + factor = 4.; + EXPECT_EQ(hpwh.setResistanceCapacity(factor * elementPower_kW, 0, HPWH::UNITS_KW), + 0); // Set just bottom + EXPECT_NEAR_REL(hpwh.getResistanceCapacity(-1, HPWH::UNITS_KW), + factor * elementPower_kW); // Check gets just bottom with both + EXPECT_NEAR_REL(hpwh.getResistanceCapacity(0, HPWH::UNITS_KW), + factor * elementPower_kW); // Check gets bottom with bottom + EXPECT_EQ(hpwh.getResistanceCapacity(1, HPWH::UNITS_KW), + HPWH::HPWH_ABORT); // only have one element + + EXPECT_EQ(hpwh.setResistanceCapacity(factor * elementPower_kW, 1, HPWH::UNITS_KW), + HPWH::HPWH_ABORT); // set top returns error +} + +/* + * commercialTankErrorsWithTopElement tests + */ +TEST(ResistanceFunctionsTest, commercialTankErrorsWithTopElement) +{ + const double elementPower_kW = 10.; // KW + + // init model + HPWH hpwh; + EXPECT_EQ(hpwh.initResistanceTankGeneric(800., 10., elementPower_kW * 1000., 0.), 0) + << "Could not initialize resistance tank."; + + // Check only bottom setting works + double factor = 3.; + + // set both, but only bottom really. + EXPECT_EQ(hpwh.setResistanceCapacity(factor * elementPower_kW, -1, HPWH::UNITS_KW), + 0); // Check sets + EXPECT_NEAR_REL(hpwh.getResistanceCapacity(-1, HPWH::UNITS_KW), + factor * elementPower_kW); // Check gets just bottom which is now top with both + EXPECT_NEAR_REL(hpwh.getResistanceCapacity(0, HPWH::UNITS_KW), + factor * elementPower_kW); // Check the lower and only element + EXPECT_EQ(hpwh.getResistanceCapacity(1, HPWH::UNITS_KW), + HPWH::HPWH_ABORT); // error on non existant element + + // set top + factor = 4.; + EXPECT_EQ(hpwh.setResistanceCapacity(factor * elementPower_kW, 0, HPWH::UNITS_KW), + 0); // only one element to set + EXPECT_NEAR_REL(hpwh.getResistanceCapacity(0, HPWH::UNITS_KW), + factor * elementPower_kW); // Check gets just bottom which is now top with both + EXPECT_EQ(hpwh.getResistanceCapacity(1, HPWH::UNITS_KW), + HPWH::HPWH_ABORT); // error on non existant bottom + + // set bottom returns error + EXPECT_EQ(hpwh.setResistanceCapacity(factor * elementPower_kW, 2, HPWH::UNITS_KW), + HPWH::HPWH_ABORT); +} + +struct InsulationPoint +{ + double volume_L; + double r_ft2hFperBTU; // ft^2.degF/(BTU/h) + double expectedUA_SI; +}; + +#define FT2HFperBTU_TO_M2CperW(r_ft2hFperBTU) BTUm2C_per_kWhft2F* r_ft2hFperBTU / 1000. + +// #define R_TO_RSI(rvalue) rvalue * 0.176110 +#define TEST_INIT_RESISTANCE_TANK_GENERIC(point, elementPower_W) \ + EXPECT_EQ(hpwh.initResistanceTankGeneric(point.volume_L, \ + FT2HFperBTU_TO_M2CperW(point.r_ft2hFperBTU), \ + elementPower_W, \ + elementPower_W), \ + 0) \ + << "Could not initialize generic resistance tank."; + +/* + * commercialTankInit tests + */ +TEST(ResistanceFunctionsTest, commercialTankInit) +{ + const InsulationPoint testPoint800 = {800., 10., 10.500366}; + const InsulationPoint testPoint2 = {2., 6., 0.322364}; + const InsulationPoint testPoint50 = {50., 12., 1.37808}; + const InsulationPoint testPoint200 = {200., 16., 2.604420}; + const InsulationPoint testPoint200B = {200., 6., 6.94512163}; + const InsulationPoint testPoint2000 = {2000., 16., 12.0886496}; + const InsulationPoint testPoint20000 = {20000., 6., 149.628109}; + + const double elementPower_W = 1.e4; + double UA; + + HPWH hpwh; + + // Check UA is as expected at 800 gal + TEST_INIT_RESISTANCE_TANK_GENERIC(testPoint800, elementPower_W); + hpwh.getUA(UA); + EXPECT_NEAR_REL(UA, testPoint800.expectedUA_SI); + + // Check UA independent of elements + TEST_INIT_RESISTANCE_TANK_GENERIC(testPoint800, elementPower_W / 1000.); + hpwh.getUA(UA); + EXPECT_NEAR_REL(UA, testPoint800.expectedUA_SI); + + // Check UA is as expected at 2 gal + TEST_INIT_RESISTANCE_TANK_GENERIC(testPoint2, elementPower_W); + hpwh.getUA(UA); + EXPECT_NEAR_REL(UA, testPoint2.expectedUA_SI); + + // Check UA is as expected at 50 gal + TEST_INIT_RESISTANCE_TANK_GENERIC(testPoint50, elementPower_W); + hpwh.getUA(UA); + EXPECT_NEAR_REL(UA, testPoint50.expectedUA_SI); + + // Check UA is as expected at 200 gal + TEST_INIT_RESISTANCE_TANK_GENERIC(testPoint200, elementPower_W); + hpwh.getUA(UA); + EXPECT_NEAR_REL(UA, testPoint200.expectedUA_SI); + + TEST_INIT_RESISTANCE_TANK_GENERIC(testPoint200B, elementPower_W); + hpwh.getUA(UA); + EXPECT_NEAR_REL(UA, testPoint200B.expectedUA_SI); + + // Check UA is as expected at 2000 gal + TEST_INIT_RESISTANCE_TANK_GENERIC(testPoint2000, elementPower_W); + hpwh.getUA(UA); + EXPECT_NEAR_REL(UA, testPoint2000.expectedUA_SI); + + // Check UA is as expected at 20000 gal + TEST_INIT_RESISTANCE_TANK_GENERIC(testPoint20000, elementPower_W); + hpwh.getUA(UA); + EXPECT_NEAR_REL(UA, testPoint20000.expectedUA_SI); +} + +#undef TEST_INIT_RESISTANCE_TANK_GENERIC +#undef R_TO_RSI diff --git a/test/unit_tests/scaleTest.cpp b/test/unit_tests/scaleTest.cpp new file mode 100644 index 00000000..18a482db --- /dev/null +++ b/test/unit_tests/scaleTest.cpp @@ -0,0 +1,555 @@ +/* Copyright (c) 2023 Big Ladder Software LLC. All rights reserved. + * See the LICENSE file for additional terms and conditions. */ + +// HPWHsim +#include "HPWH.hh" +#include "unit-test.hh" + +constexpr double tol = 1.e-4; + +struct Performance +{ + double input, output, cop; +}; + +void getCompressorPerformance( + HPWH& hpwh, Performance& point, double waterTempC, double airTempC, double setpointC) +{ + if (hpwh.isCompressorMultipass() == 1) + { // Multipass capacity looks at the average of the + // temperature of the lift + hpwh.setSetpoint((waterTempC + setpointC) / 2.); + } + else + { + hpwh.setSetpoint(waterTempC); + } + hpwh.resetTankToSetpoint(); // Force tank cold + hpwh.setSetpoint(setpointC); + + // Run the step + hpwh.runOneStep(waterTempC, // Inlet water temperature (C ) + 0., // Flow in gallons + airTempC, // Ambient Temp (C) + airTempC, // External Temp (C) + // HPWH::DR_TOO // DR Status (now an enum. Fixed for now as allow) + (HPWH::DR_TOO | HPWH::DR_LOR) // DR Status (now an enum. Fixed for now as allow) + ); + + // Check the heat in and out of the compressor + point.input = hpwh.getNthHeatSourceEnergyInput(hpwh.getCompressorIndex()); + point.output = hpwh.getNthHeatSourceEnergyOutput(hpwh.getCompressorIndex()); + point.cop = point.output / point.input; +} + +bool scaleCapacityCOP(HPWH& hpwh, + double scaleInput, + double scaleCOP, + Performance& point0, + Performance& point1, + double waterTempC = F_TO_C(63), + double airTempC = F_TO_C(77), + double setpointC = F_TO_C(135)) +{ + // Get peformance unscaled + getCompressorPerformance(hpwh, point0, waterTempC, airTempC, setpointC); + + // Scale the compressor + int val = hpwh.setScaleCapacityCOP(scaleInput, scaleCOP); + if (val != 0) + { + return false; + } + + // Get the scaled performance + getCompressorPerformance(hpwh, point1, waterTempC, airTempC, setpointC); + return true; +} + +/* + * noScaleOutOfBounds tests + */ +TEST(ScaleTest, noScaleOutOfBounds) +{ // Test that we CANNOT scale the scalable model with scale <= 0 + + // get preset model + HPWH hpwh; + const std::string sModelName = "TamScalable_SP"; + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + double num = 0; + EXPECT_EQ(hpwh.setScaleCapacityCOP(num, 1.), HPWH::HPWH_ABORT); + EXPECT_EQ(hpwh.setScaleCapacityCOP(1., num), HPWH::HPWH_ABORT); + + num = -1; + EXPECT_EQ(hpwh.setScaleCapacityCOP(num, 1.), HPWH::HPWH_ABORT); + EXPECT_EQ(hpwh.setScaleCapacityCOP(1., num), HPWH::HPWH_ABORT); +} + +/* + * nonScalable tests + */ +TEST(ScaleTest, nonScalable) +{ // Test a model that is not scalable + + const std::string sModelName = "AOSmithCAHP120"; + + // get preset model + HPWH hpwh; + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + EXPECT_EQ(hpwh.setScaleCapacityCOP(1., 1.), HPWH::HPWH_ABORT); +} + +/* + * scalableScales tests + */ +TEST(ScaleTest, scalableScales) +{ // Test that scalable hpwh can scale + + // get preset model + HPWH hpwh; + const std::string sModelName = "TamScalable_SP"; + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + Performance point0, point1; + double num, anotherNum; + + num = 0.001; // Very low + EXPECT_TRUE(scaleCapacityCOP(hpwh, num, 1., point0, point1)); + EXPECT_NEAR(point0.input, point1.input / num, tol); + EXPECT_NEAR(point0.output, point1.output / num, tol); + EXPECT_NEAR(point0.cop, point1.cop, tol); + + EXPECT_TRUE(scaleCapacityCOP(hpwh, 1., num, point0, point1)); + EXPECT_NEAR(point0.input, point1.input, tol); + EXPECT_NEAR(point0.output, point1.output / num, tol); + EXPECT_NEAR(point0.cop, point1.cop / num, tol); + + EXPECT_TRUE(scaleCapacityCOP(hpwh, num, num, point0, point1)); + EXPECT_NEAR(point0.input, point1.input / num, tol); + EXPECT_NEAR(point0.output, point1.output / num / num, tol); + EXPECT_NEAR(point0.cop, point1.cop / num, tol); + + num = 0.2; // normal but bad low + EXPECT_TRUE(scaleCapacityCOP(hpwh, num, 1., point0, point1)); + EXPECT_NEAR(point0.input, point1.input / num, tol); + EXPECT_NEAR(point0.output, point1.output / num, tol); + EXPECT_NEAR(point0.cop, point1.cop, tol); + + EXPECT_TRUE(scaleCapacityCOP(hpwh, 1., num, point0, point1)); + EXPECT_NEAR(point0.input, point1.input, tol); + EXPECT_NEAR(point0.output, point1.output / num, tol); + EXPECT_NEAR(point0.cop, point1.cop / num, tol); + + EXPECT_TRUE(scaleCapacityCOP(hpwh, num, num, point0, point1)); + EXPECT_NEAR(point0.input, point1.input / num, tol); + EXPECT_NEAR(point0.output, point1.output / num / num, tol); + EXPECT_NEAR(point0.cop, point1.cop / num, tol); + + num = 3.; // normal but pretty high + EXPECT_TRUE(scaleCapacityCOP(hpwh, num, 1., point0, point1)); + EXPECT_NEAR(point0.input, point1.input / num, tol); + EXPECT_NEAR(point0.output, point1.output / num, tol); + EXPECT_NEAR(point0.cop, point1.cop, tol); + + EXPECT_TRUE(scaleCapacityCOP(hpwh, 1., num, point0, point1)); + EXPECT_NEAR(point0.input, point1.input, tol); + EXPECT_NEAR(point0.output, point1.output / num, tol); + EXPECT_NEAR(point0.cop, point1.cop / num, tol); + + EXPECT_TRUE(scaleCapacityCOP(hpwh, num, num, point0, point1)); + EXPECT_NEAR(point0.input, point1.input / num, tol); + EXPECT_NEAR(point0.output, point1.output / num / num, tol); + EXPECT_NEAR(point0.cop, point1.cop / num, tol); + + num = 1000; // really high + EXPECT_TRUE(scaleCapacityCOP(hpwh, num, 1., point0, point1)); + EXPECT_NEAR(point0.input, point1.input / num, tol); + EXPECT_NEAR(point0.output, point1.output / num, tol); + EXPECT_NEAR(point0.cop, point1.cop, tol); + + EXPECT_TRUE(scaleCapacityCOP(hpwh, 1., num, point0, point1)); + EXPECT_NEAR(point0.input, point1.input, tol); + EXPECT_NEAR(point0.output, point1.output / num, tol); + EXPECT_NEAR(point0.cop, point1.cop / num, tol); + + EXPECT_TRUE(scaleCapacityCOP(hpwh, num, num, point0, point1)); + EXPECT_NEAR(point0.input, point1.input / num, tol); + EXPECT_NEAR(point0.output, point1.output / num / num, tol); + EXPECT_NEAR(point0.cop, point1.cop / num, tol); + + num = 10; + anotherNum = 0.1; // weird high and low + EXPECT_TRUE(scaleCapacityCOP(hpwh, num, anotherNum, point0, point1)); + EXPECT_NEAR(point0.input, point1.input / num, tol); + EXPECT_NEAR(point0.output, point1.output / num / anotherNum, tol); + EXPECT_NEAR(point0.cop, point1.cop / anotherNum, tol); + + EXPECT_TRUE(scaleCapacityCOP(hpwh, anotherNum, num, point0, point1)); + EXPECT_NEAR(point0.input, point1.input / anotherNum, tol); + EXPECT_NEAR(point0.output, point1.output / num / anotherNum, tol); + EXPECT_NEAR(point0.cop, point1.cop / num, tol); + + num = 1.5; + anotherNum = 0.9; // real high and low + EXPECT_TRUE(scaleCapacityCOP(hpwh, num, anotherNum, point0, point1)); + EXPECT_NEAR(point0.input, point1.input / num, tol); + EXPECT_NEAR(point0.output, point1.output / num / anotherNum, tol); + EXPECT_NEAR(point0.cop, point1.cop / anotherNum, tol); + + EXPECT_TRUE(scaleCapacityCOP(hpwh, anotherNum, num, point0, point1)); + EXPECT_NEAR(point0.input, point1.input / anotherNum, tol); + EXPECT_NEAR(point0.output, point1.output / num / anotherNum, tol); + EXPECT_NEAR(point0.cop, point1.cop / num, tol); +} + +/* + * scalableMP_scales tests + */ +TEST(ScaleTest, scalableMP_scales) +{ // Test that scalable MP hpwh can scale + + // get preset model + HPWH hpwh; + const std::string sModelName = "Scalable_MP"; + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + Performance point0, point1; + double num, anotherNum; + + num = 0.001; // Very low + EXPECT_TRUE(scaleCapacityCOP(hpwh, num, 1., point0, point1)); + EXPECT_NEAR(point0.input, point1.input / num, tol); + EXPECT_NEAR(point0.output, point1.output / num, tol); + EXPECT_NEAR(point0.cop, point1.cop, tol); + + EXPECT_TRUE(scaleCapacityCOP(hpwh, 1., num, point0, point1)); + EXPECT_NEAR(point0.input, point1.input, tol); + EXPECT_NEAR(point0.output, point1.output / num, tol); + EXPECT_NEAR(point0.cop, point1.cop / num, tol); + + EXPECT_TRUE(scaleCapacityCOP(hpwh, num, num, point0, point1)); + EXPECT_NEAR(point0.input, point1.input / num, tol); + EXPECT_NEAR(point0.output, point1.output / num / num, tol); + EXPECT_NEAR(point0.cop, point1.cop / num, tol); + + num = 0.2; // normal but bad low + scaleCapacityCOP(hpwh, num, 1., point0, point1); + EXPECT_NEAR(point0.input, point1.input / num, tol); + EXPECT_NEAR(point0.output, point1.output / num, tol); + EXPECT_NEAR(point0.cop, point1.cop, tol); + + scaleCapacityCOP(hpwh, 1., num, point0, point1); + EXPECT_NEAR(point0.input, point1.input, tol); + EXPECT_NEAR(point0.output, point1.output / num, tol); + EXPECT_NEAR(point0.cop, point1.cop / num, tol); + + EXPECT_TRUE(scaleCapacityCOP(hpwh, num, num, point0, point1)); + EXPECT_NEAR(point0.input, point1.input / num, tol); + EXPECT_NEAR(point0.output, point1.output / num / num, tol); + EXPECT_NEAR(point0.cop, point1.cop / num, tol); + + num = 3.; // normal but pretty high + EXPECT_TRUE(scaleCapacityCOP(hpwh, num, 1., point0, point1)); + EXPECT_NEAR(point0.input, point1.input / num, tol); + EXPECT_NEAR(point0.output, point1.output / num, tol); + EXPECT_NEAR(point0.cop, point1.cop, tol); + + EXPECT_TRUE(scaleCapacityCOP(hpwh, 1., num, point0, point1)); + EXPECT_NEAR(point0.input, point1.input, tol); + EXPECT_NEAR(point0.output, point1.output / num, tol); + EXPECT_NEAR(point0.cop, point1.cop / num, tol); + + EXPECT_TRUE(scaleCapacityCOP(hpwh, num, num, point0, point1)); + EXPECT_NEAR(point0.input, point1.input / num, tol); + EXPECT_NEAR(point0.output, point1.output / num / num, tol); + EXPECT_NEAR(point0.cop, point1.cop / num, tol); + + num = 1000; // really high + EXPECT_TRUE(scaleCapacityCOP(hpwh, num, 1., point0, point1)); + EXPECT_NEAR(point0.input, point1.input / num, tol); + EXPECT_NEAR(point0.output, point1.output / num, tol); + EXPECT_NEAR(point0.cop, point1.cop, tol); + + EXPECT_TRUE(scaleCapacityCOP(hpwh, 1., num, point0, point1)); + EXPECT_NEAR(point0.input, point1.input, tol); + EXPECT_NEAR(point0.output, point1.output / num, tol); + EXPECT_NEAR(point0.cop, point1.cop / num, tol); + + EXPECT_TRUE(scaleCapacityCOP(hpwh, num, num, point0, point1)); + EXPECT_NEAR(point0.input, point1.input / num, tol); + EXPECT_NEAR(point0.output, point1.output / num / num, tol); + EXPECT_NEAR(point0.cop, point1.cop / num, tol); + + num = 10; + anotherNum = 0.1; // weird high and low + EXPECT_TRUE(scaleCapacityCOP(hpwh, num, anotherNum, point0, point1)); + EXPECT_NEAR(point0.input, point1.input / num, tol); + EXPECT_NEAR(point0.output, point1.output / num / anotherNum, tol); + EXPECT_NEAR(point0.cop, point1.cop / anotherNum, tol); + + EXPECT_TRUE(scaleCapacityCOP(hpwh, anotherNum, num, point0, point1)); + EXPECT_NEAR(point0.input, point1.input / anotherNum, tol); + EXPECT_NEAR(point0.output, point1.output / num / anotherNum, tol); + EXPECT_NEAR(point0.cop, point1.cop / num, tol); + + num = 1.5; + anotherNum = 0.9; // real high and low + EXPECT_TRUE(scaleCapacityCOP(hpwh, num, anotherNum, point0, point1)); + EXPECT_NEAR(point0.input, point1.input / num, tol); + EXPECT_NEAR(point0.input, point1.input / num, tol); + EXPECT_NEAR(point0.output, point1.output / num / anotherNum, tol); + EXPECT_NEAR(point0.cop, point1.cop / anotherNum, tol); + + EXPECT_TRUE(scaleCapacityCOP(hpwh, anotherNum, num, point0, point1)); + EXPECT_NEAR(point0.input, point1.input / anotherNum, tol); + EXPECT_NEAR(point0.output, point1.output / num / anotherNum, tol); + EXPECT_NEAR(point0.cop, point1.cop / num, tol); +} + +/* + * getCompressorSP_capacity tests + */ +TEST(ScaleTest, getCompressorSP_capacity) +{ + // get preset model + HPWH hpwh; + const std::string sModelName = "ColmacCxA_20_SP"; + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + Performance point0; + + double capacity_kWH, capacity_BTU; + double waterTempC = F_TO_C(63); + double airTempC = F_TO_C(77); + double setpointC = F_TO_C(135); + + getCompressorPerformance(hpwh, point0, waterTempC, airTempC, setpointC); // gives kWH + capacity_kWH = hpwh.getCompressorCapacity(airTempC, waterTempC, setpointC) / + 60; // div 60 to kWh because I know above only runs 1 minute + + EXPECT_NEAR(point0.output, capacity_kWH, tol); + + // Test with IP units + capacity_BTU = hpwh.getCompressorCapacity(C_TO_F(airTempC), + C_TO_F(waterTempC), + C_TO_F(setpointC), + HPWH::UNITS_BTUperHr, + HPWH::UNITS_F) / + 60; // div 60 to BTU because I know above only runs 1 minute + + EXPECT_NEAR_REL(KWH_TO_BTU(point0.output), + capacity_BTU); // relative cmp since in btu's these will be large numbers +} + +/* + * getCompressorMP_capacity tests + */ +TEST(ScaleTest, getCompressorMP_capacity) +{ + // get preset model + HPWH hpwh; + const std::string sModelName = "ColmacCxA_20_MP"; + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + Performance point0; + + const double waterTempC = F_TO_C(50); // 50 and 126 to make average 88 + const double airTempC = F_TO_C(61.7); + const double setpointC = F_TO_C(126); + + double capacity_kWH = hpwh.getCompressorCapacity(airTempC, waterTempC, setpointC) / + 60.; // div 60 to kWh because I know above only runs 1 minute + getCompressorPerformance(hpwh, point0, waterTempC, airTempC, setpointC); // gives kWH + EXPECT_NEAR(point0.output, capacity_kWH, tol); + + // Test with IP units + double capacity_BTU = hpwh.getCompressorCapacity(C_TO_F(airTempC), + C_TO_F(waterTempC), + C_TO_F(setpointC), + HPWH::UNITS_BTUperHr, + HPWH::UNITS_F) / + 60; // div 60 to BTU because I know above only runs 1 minute + + EXPECT_NEAR_REL(KWH_TO_BTU(point0.output), + capacity_BTU); // relative cmp since in btu's these will be large numbers +} + +/* + * getCompressorMP_outputCapacity tests + */ +TEST(ScaleTest, getCompressorMP_outputCapacity) +{ + // get preset model + HPWH hpwh; + const std::string sModelName = "Scalable_MP"; + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + double newCapacity_kW, num; + double waterTempC = F_TO_C(44); + double airTempC = F_TO_C(98); + double setpointC = F_TO_C(150); + + // Scale output to 1 kW + num = 1.; + hpwh.setCompressorOutputCapacity(num, airTempC, waterTempC, setpointC); + newCapacity_kW = hpwh.getCompressorCapacity(airTempC, waterTempC, setpointC); + EXPECT_NEAR(num, newCapacity_kW, tol); + + // Scale output to .01 kW + num = .01; + hpwh.setCompressorOutputCapacity(num, airTempC, waterTempC, setpointC); + newCapacity_kW = hpwh.getCompressorCapacity(airTempC, waterTempC, setpointC); + EXPECT_NEAR(num, newCapacity_kW, tol); + + // Scale output to 1000 kW + num = 1000.; + hpwh.setCompressorOutputCapacity(num, airTempC, waterTempC, setpointC); + newCapacity_kW = hpwh.getCompressorCapacity(airTempC, waterTempC, setpointC); + EXPECT_NEAR(num, newCapacity_kW, tol); + + // Check again with changed setpoint. For MP it should affect output capacity since it looks at + // the mean temperature for the cycle. + setpointC = F_TO_C(100); + newCapacity_kW = hpwh.getCompressorCapacity(airTempC, waterTempC, setpointC); + EXPECT_FAR(num, newCapacity_kW, tol); +} + +/* + * setCompressorSP_outputCapacity tests + */ +TEST(ScaleTest, setCompressorSP_outputCapacity) +{ + // get preset model + HPWH hpwh; + const std::string sModelName = "TamScalable_SP"; + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + double newCapacity_kW, num; + double waterTempC = F_TO_C(44); + double airTempC = F_TO_C(98); + double setpointC = F_TO_C(145); + + // Scale output to 1 kW + num = 1.; + hpwh.setCompressorOutputCapacity(num, airTempC, waterTempC, setpointC); + newCapacity_kW = hpwh.getCompressorCapacity(airTempC, waterTempC, setpointC); + EXPECT_NEAR(num, newCapacity_kW, tol); + + // Scale output to .01 kW + num = .01; + hpwh.setCompressorOutputCapacity(num, airTempC, waterTempC, setpointC); + newCapacity_kW = hpwh.getCompressorCapacity(airTempC, waterTempC, setpointC); + EXPECT_NEAR(num, newCapacity_kW, tol); + + // Scale output to 1000 kW + num = 1000.; + hpwh.setCompressorOutputCapacity(num, airTempC, waterTempC, setpointC); + newCapacity_kW = hpwh.getCompressorCapacity(airTempC, waterTempC, setpointC); + EXPECT_NEAR(num, newCapacity_kW, tol); + + // Scale output to 1000 kW but let's do the calc in other units + num = KW_TO_BTUperH(num); + hpwh.setCompressorOutputCapacity(num, + C_TO_F(airTempC), + C_TO_F(waterTempC), + C_TO_F(setpointC), + HPWH::UNITS_BTUperHr, + HPWH::UNITS_F); + double newCapacity_BTUperHr = hpwh.getCompressorCapacity(C_TO_F(airTempC), + C_TO_F(waterTempC), + C_TO_F(setpointC), + HPWH::UNITS_BTUperHr, + HPWH::UNITS_F); + EXPECT_NEAR_REL(num, newCapacity_BTUperHr); +} + +/* + * chipsCaseWithIP_units tests + */ +TEST(ScaleTest, chipsCaseWithIP_units) +{ + // get preset model + HPWH hpwh; + const std::string sModelName = "TamScalable_SP"; + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + const double waterT_F = 50; + const double airT_F = 50; + const double setpointT_F = 120; + const double wh_heatingCap = 20000.; + + // Scale output to 20000 btu/hr but let's use do the calc in other units + hpwh.setCompressorOutputCapacity( + wh_heatingCap, airT_F, waterT_F, setpointT_F, HPWH::UNITS_BTUperHr, HPWH::UNITS_F); + + double newCapacity_BTUperHr = hpwh.getCompressorCapacity( + airT_F, waterT_F, setpointT_F, HPWH::UNITS_BTUperHr, HPWH::UNITS_F); + + EXPECT_NEAR_REL(wh_heatingCap, newCapacity_BTUperHr); +} + +/* + * scaleRestank tests + */ +TEST(ScaleTest, scaleRestank) +{ + // get preset model + HPWH hpwh; + const std::string sModelName = "restankRealistic"; + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + // Scale COP for restank fails. + EXPECT_EQ(hpwh.setScaleCapacityCOP(2., 2.), HPWH::HPWH_ABORT); +} + +/* + * resistanceScales tests + */ +TEST(ScaleTest, resistanceScales) +{ + // get preset model + HPWH hpwh; + const std::string sModelName = "TamScalable_SP"; + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + double elementPower = 30.; // KW + + EXPECT_NEAR_REL(hpwh.getResistanceCapacity(0, HPWH::UNITS_KW), elementPower); + EXPECT_NEAR_REL(hpwh.getResistanceCapacity(1, HPWH::UNITS_KW), elementPower); + EXPECT_NEAR_REL(hpwh.getResistanceCapacity(-1, HPWH::UNITS_KW), 2. * elementPower); + + // check units convert + EXPECT_NEAR_REL(hpwh.getResistanceCapacity(-1, HPWH::UNITS_BTUperHr), + 2. * KW_TO_BTUperH(elementPower)); + + // Check setting bottom works + double factor = 2.; + hpwh.setResistanceCapacity(factor * elementPower, 0); + EXPECT_NEAR_REL(hpwh.getResistanceCapacity(0, HPWH::UNITS_KW), factor * elementPower); + EXPECT_NEAR_REL(hpwh.getResistanceCapacity(1, HPWH::UNITS_KW), elementPower); + EXPECT_NEAR_REL(hpwh.getResistanceCapacity(-1, HPWH::UNITS_KW), + factor * elementPower + elementPower); + + // Check setting both works + factor = 3.; + hpwh.setResistanceCapacity(factor * elementPower, -1); + EXPECT_NEAR_REL(hpwh.getResistanceCapacity(0, HPWH::UNITS_KW), factor * elementPower); + EXPECT_NEAR_REL(hpwh.getResistanceCapacity(1, HPWH::UNITS_KW), factor * elementPower); + EXPECT_NEAR_REL(hpwh.getResistanceCapacity(-1, HPWH::UNITS_KW), 2. * factor * elementPower); +} + +/* + * storageTankErrors tests + */ +TEST(ScaleTest, storageTankErrors) +{ + // get preset model + HPWH hpwh; + const std::string sModelName = "StorageTank"; + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + EXPECT_EQ(hpwh.setResistanceCapacity(1000.), HPWH::HPWH_ABORT); + EXPECT_EQ(hpwh.setScaleCapacityCOP(1., 1.), HPWH::HPWH_ABORT); +} diff --git a/test/unit_tests/sizingFractionsTest.cpp b/test/unit_tests/sizingFractionsTest.cpp new file mode 100644 index 00000000..8085cdc1 --- /dev/null +++ b/test/unit_tests/sizingFractionsTest.cpp @@ -0,0 +1,170 @@ +/* Copyright (c) 2023 Big Ladder Software LLC. All rights reserved. + * See the LICENSE file for additional terms and conditions. */ + +// HPWHsim +#include "HPWH.hh" +#include "unit-test.hh" + +constexpr double logicSize = static_cast(HPWH::LOGIC_SIZE); + +constexpr double tol = 1.e-4; + +/* + * TamScalable_SP_SizingFract tests + */ +TEST(SizingFractionsTest, TamScalable_SP_SizingFract) +{ + // get preset model + HPWH hpwh; + const std::string sModelName = "TamScalable_SP"; // Just a compressor with R134A + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + double aquaFrac, useableFrac; + const double aquaFrac_answer = 4. / logicSize; + + EXPECT_EQ(hpwh.getSizingFractions(aquaFrac, useableFrac), 0); + EXPECT_NEAR(aquaFrac, aquaFrac_answer, tol); + EXPECT_NEAR(useableFrac, 1. - 1. / logicSize, tol); +} + +/* + * Sanden80_SizingFract tests + */ +TEST(SizingFractionsTest, Sanden80_SizingFract) +{ + // get preset model + HPWH hpwh; + const std::string sModelName = "Sanden80"; + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + double aquaFrac, useableFrac; + const double aquaFrac_answer = 8. / logicSize; + + EXPECT_EQ(hpwh.getSizingFractions(aquaFrac, useableFrac), 0); + EXPECT_NEAR(aquaFrac, aquaFrac_answer, tol); + EXPECT_NEAR(useableFrac, 1. - 1. / logicSize, tol); +} + +/* + * ColmacCxV_5_SP_SizingFract tests + */ +TEST(SizingFractionsTest, ColmacCxV_5_SP_SizingFract) +{ + // get preset model + HPWH hpwh; + const std::string sModelName = "ColmacCxV_5_SP"; + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + double aquaFrac, useableFrac; + const double aquaFrac_answer = 4. / logicSize; + + EXPECT_EQ(hpwh.getSizingFractions(aquaFrac, useableFrac), 0); + EXPECT_NEAR(aquaFrac, aquaFrac_answer, tol); + EXPECT_NEAR(useableFrac, 1. - 1. / logicSize, tol); +} + +/* + * AOSmithHPTU50_SizingFract tests + */ +TEST(SizingFractionsTest, AOSmithHPTU50_SizingFract) +{ + // get preset model + HPWH hpwh; + const std::string sModelName = "AOSmithHPTU50"; + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + double aquaFrac, useableFrac; + const double aquaFrac_answer = (1. + 2. + 3. + 4.) / 4. / logicSize; + + EXPECT_EQ(hpwh.getSizingFractions(aquaFrac, useableFrac), 0); + EXPECT_NEAR(aquaFrac, aquaFrac_answer, tol); + EXPECT_NEAR(useableFrac, 1., tol); +} + +/* + * GE_SizingFract tests + */ +TEST(SizingFractionsTest, GE_SizingFract) +{ + // get preset model + HPWH hpwh; + const std::string sModelName = "GE"; + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + double aquaFrac, useableFrac; + const double aquaFrac_answer = (1. + 2. + 3. + 4.) / 4. / logicSize; + + EXPECT_EQ(hpwh.getSizingFractions(aquaFrac, useableFrac), 0); + EXPECT_NEAR(aquaFrac, aquaFrac_answer, tol); + EXPECT_NEAR(useableFrac, 1., tol); +} + +/* + * Stiebel220e_SizingFract tests + */ +TEST(SizingFractionsTest, Stiebel220e_SizingFract) +{ + // get preset model + HPWH hpwh; + const std::string sModelName = "Stiebel220e"; + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + double aquaFrac, useableFrac; + const double aquaFrac_answer = (5. + 6.) / 2. / logicSize; + + EXPECT_EQ(hpwh.getSizingFractions(aquaFrac, useableFrac), 0); + EXPECT_NEAR(aquaFrac, aquaFrac_answer, tol); + EXPECT_NEAR(useableFrac, 1. - 1. / logicSize, tol); +} + +/* + * resTankRealistic_SizingFract tests + */ +TEST(SizingFractionsTest, resTankRealistic_SizingFract) +{ + // get preset model + HPWH hpwh; + const std::string sModelName = "restankRealistic"; + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + double aquaFrac, useableFrac; + EXPECT_EQ(hpwh.getSizingFractions(aquaFrac, useableFrac), HPWH::HPWH_ABORT); +} + +/* + * storageTank_SizingFract tests + */ +TEST(SizingFractionsTest, storageTank_SizingFract) +{ + // get preset model + HPWH hpwh; + const std::string sModelName = "StorageTank"; + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + double aquaFrac, useableFrac; + EXPECT_EQ(hpwh.getSizingFractions(aquaFrac, useableFrac), HPWH::HPWH_ABORT); +} + +/* + * getCompressorMinRuntime tests + */ +TEST(SizingFractionsTest, getCompressorMinRuntime) +{ + // get preset model + HPWH hpwh; + const std::string sModelName = "TamScalable_SP"; // Just a compressor with R134A + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + double expectedRunTime_min = 10.; + double expectedRunTime_sec = expectedRunTime_min * 60.; + double expectedRunTime_hr = expectedRunTime_min / 60.; + + double runTime_min = hpwh.getCompressorMinRuntime(); + EXPECT_EQ(runTime_min, expectedRunTime_min); + + double runTime_sec = hpwh.getCompressorMinRuntime(HPWH::UNITS_SEC); + EXPECT_EQ(runTime_sec, expectedRunTime_sec); + + double runTime_hr = hpwh.getCompressorMinRuntime(HPWH::UNITS_HR); + EXPECT_EQ(runTime_hr, expectedRunTime_hr); +} diff --git a/test/unit_tests/stateOfChargeFncsTest.cpp b/test/unit_tests/stateOfChargeFncsTest.cpp new file mode 100644 index 00000000..07deae1c --- /dev/null +++ b/test/unit_tests/stateOfChargeFncsTest.cpp @@ -0,0 +1,90 @@ +/* Copyright (c) 2023 Big Ladder Software LLC. All rights reserved. + * See the LICENSE file for additional terms and conditions. */ + +// HPWHsim +#include "HPWH.hh" +#include "unit-test.hh" + +constexpr double tol = 1.e-4; + +/* + * getSoC tests + */ +TEST(StateOfChargeFunctionsTest, getSoC) +{ + // get preset model + HPWH hpwh; + const std::string sModelName = "Sanden80"; + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + const double mainsT_C = F_TO_C(55.); + const double minUsefulT_C = F_TO_C(110.); + double chargeFraction; + + // Check for errors + chargeFraction = hpwh.calcSoCFraction(F_TO_C(125.), minUsefulT_C); + EXPECT_EQ(chargeFraction, HPWH::HPWH_ABORT); + + chargeFraction = hpwh.calcSoCFraction(mainsT_C, F_TO_C(155.)); + EXPECT_EQ(chargeFraction, HPWH::HPWH_ABORT); + + chargeFraction = hpwh.calcSoCFraction(mainsT_C, minUsefulT_C, F_TO_C(100.)); + EXPECT_EQ(chargeFraction, HPWH::HPWH_ABORT); + + // Check state of charge returns 1 at setpoint + chargeFraction = hpwh.calcSoCFraction(mainsT_C, minUsefulT_C); + EXPECT_NEAR(chargeFraction, 1., tol); + + chargeFraction = hpwh.calcSoCFraction(mainsT_C + 5., minUsefulT_C); + EXPECT_NEAR(chargeFraction, 1., tol); + + chargeFraction = hpwh.calcSoCFraction(mainsT_C, minUsefulT_C + 5.); + EXPECT_NEAR(chargeFraction, 1., tol); + + // Varying max temp + chargeFraction = hpwh.calcSoCFraction(mainsT_C, minUsefulT_C, F_TO_C(110.)); + EXPECT_NEAR(chargeFraction, 1.70909, tol); + + chargeFraction = hpwh.calcSoCFraction(mainsT_C, minUsefulT_C, F_TO_C(120.)); + EXPECT_NEAR(chargeFraction, 1.4461, tol); + + chargeFraction = hpwh.calcSoCFraction(mainsT_C, minUsefulT_C, F_TO_C(135.)); + EXPECT_NEAR(chargeFraction, 1.175, tol); +} + +/* + * chargeBelowSetpoint tests + */ +TEST(StateOfChargeFunctionsTest, chargeBelowSetpoint) +{ + // get preset model + HPWH hpwh; + const std::string sModelName = "ColmacCxV_5_SP"; + EXPECT_EQ(hpwh.initPreset(sModelName), 0) << "Could not initialize model " << sModelName; + + const double mainsT_C = F_TO_C(60.); + double minUsefulT_C = F_TO_C(110.); + double chargeFraction; + + // Check state of charge returns 1 at setpoint + chargeFraction = hpwh.calcSoCFraction(mainsT_C, minUsefulT_C); + EXPECT_NEAR(chargeFraction, 1., tol); + + // Check state of charge returns 0 when tank below useful + hpwh.setTankToTemperature(F_TO_C(109.)); + chargeFraction = hpwh.calcSoCFraction(mainsT_C, minUsefulT_C, F_TO_C(140.)); + EXPECT_NEAR(chargeFraction, 0., tol); + + // Check some lower values with tank set at constant temperatures + hpwh.setTankToTemperature(F_TO_C(110.)); + chargeFraction = hpwh.calcSoCFraction(mainsT_C, minUsefulT_C, F_TO_C(140.)); + EXPECT_NEAR(chargeFraction, 0.625, tol); + + hpwh.setTankToTemperature(F_TO_C(120.)); + chargeFraction = hpwh.calcSoCFraction(mainsT_C, minUsefulT_C, F_TO_C(140.)); + EXPECT_NEAR(chargeFraction, 0.75, tol); + + hpwh.setTankToTemperature(F_TO_C(130.)); + chargeFraction = hpwh.calcSoCFraction(mainsT_C, minUsefulT_C, F_TO_C(140.)); + EXPECT_NEAR(chargeFraction, 0.875, tol); +} diff --git a/test/unit_tests/unit-test-main.cpp b/test/unit_tests/unit-test-main.cpp new file mode 100644 index 00000000..f11f8ffe --- /dev/null +++ b/test/unit_tests/unit-test-main.cpp @@ -0,0 +1,11 @@ +/* Copyright (c) 2023 Big Ladder Software LLC. All rights reserved. + * See the LICENSE file for additional terms and conditions. */ + +// Vendor +#include + +int main(int argc, char** argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/test/unit_tests/unit-test.hh b/test/unit_tests/unit-test.hh new file mode 100644 index 00000000..967bfade --- /dev/null +++ b/test/unit_tests/unit-test.hh @@ -0,0 +1,18 @@ +/* + * HPWHsim unit tests + */ + +#ifndef HPWH_UNIT_TEST_hh +#define HPWH_UNIT_TEST_hh + +// vendor +#include +#include + +#define EXPECT_NEAR_REL_TOL(A, B, eps) EXPECT_NEAR(A, B, eps*(abs(A) < abs(B) ? abs(B) : abs(A))) + +#define EXPECT_NEAR_REL(A, B) EXPECT_NEAR_REL_TOL(A, B, 1.e-4) + +#define EXPECT_FAR(A, B, eps) EXPECT_FALSE(abs(A - B) < eps) + +#endif diff --git a/vendor/CMakeLists.txt b/vendor/CMakeLists.txt index 2bf8b46d..22ae7341 100644 --- a/vendor/CMakeLists.txt +++ b/vendor/CMakeLists.txt @@ -1,8 +1,19 @@ - - include(initialize-submodules) initialize_submodules() if (NOT TARGET btwxt) add_subdirectory(btwxt) +endif () + +# googletest library +if (${PROJECT_NAME}_BUILD_TESTING AND NOT TARGET gtest) + + # Prevent GoogleTest from overriding our compiler/linker options + # when building with Visual Studio + set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) + set(BUILD_GTEST ON CACHE BOOL "" FORCE MARK) + set(BUILD_GMOCK ON CACHE BOOL "" FORCE) + set(INSTALL_GTEST OFF CACHE BOOL "" FORCE) + mark_as_advanced(BUILD_GTEST BUILD_GMOCK INSTALL_GTEST) + add_subdirectory("${btwxt_SOURCE_DIR}/vendor/googletest") endif () \ No newline at end of file