From ad3b72eda0505b1db6793225eb995780e02a5e93 Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Wed, 18 Dec 2024 13:51:29 +0100 Subject: [PATCH 1/6] #5314 - Add Tank Element Control Logic to WaterHeater:HeatPump(:PumpedCondenser) --- resources/model/OpenStudio.idd | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/resources/model/OpenStudio.idd b/resources/model/OpenStudio.idd index 3a6a323995..b77fdfa53d 100644 --- a/resources/model/OpenStudio.idd +++ b/resources/model/OpenStudio.idd @@ -31701,7 +31701,16 @@ OS:WaterHeater:HeatPump, \note A schedule value of 1 denotes inlet air is drawn only from outdoors. \note Schedule values between 0 and 1 denote a mixture of zone and outdoor air \note proportional to the schedule value. - A19; \field Control Sensor Location In Stratified Tank + A19, \field Tank Element Control Logic + \type choice + \key MutuallyExclusive + \key Simultaneous + \default Simultaneous + \note MutuallyExclusive means that once the tank heating element is active the + \note heat pump is shut down until setpoint is reached. + \note Simultaneous (default) means that both the tank heating element and + \note heat pump are used at the same time recover the tank temperature. + A20; \field Control Sensor Location In Stratified Tank \note Used to indicate height of control sensor if Tank Object Type is WaterHeater:Stratified \type choice \key Heater1 From 2da07d41b0d4d91a2dd050e18261e6c3bfd8775e Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Wed, 18 Dec 2024 13:51:43 +0100 Subject: [PATCH 2/6] Make it required-field --- resources/model/OpenStudio.idd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/model/OpenStudio.idd b/resources/model/OpenStudio.idd index b77fdfa53d..973dd6e91b 100644 --- a/resources/model/OpenStudio.idd +++ b/resources/model/OpenStudio.idd @@ -31705,7 +31705,7 @@ OS:WaterHeater:HeatPump, \type choice \key MutuallyExclusive \key Simultaneous - \default Simultaneous + \required-field \note MutuallyExclusive means that once the tank heating element is active the \note heat pump is shut down until setpoint is reached. \note Simultaneous (default) means that both the tank heating element and From 6d1edb3c07e72b46c4d4df352db77514c556fc85 Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Wed, 18 Dec 2024 14:21:21 +0100 Subject: [PATCH 3/6] #5314 - Add Tank Element Control Logic to model / FT for WaterHeaterHeatPump --- .../ForwardTranslateWaterHeaterHeatPump.cpp | 5 ++++ src/model/WaterHeaterHeatPump.cpp | 25 +++++++++++++++++++ src/model/WaterHeaterHeatPump.hpp | 6 +++++ src/model/WaterHeaterHeatPump_Impl.hpp | 4 +++ src/model/test/WaterHeaterHeatPump_GTest.cpp | 8 ++++++ 5 files changed, 48 insertions(+) diff --git a/src/energyplus/ForwardTranslator/ForwardTranslateWaterHeaterHeatPump.cpp b/src/energyplus/ForwardTranslator/ForwardTranslateWaterHeaterHeatPump.cpp index d99af2bf17..867f2d929a 100644 --- a/src/energyplus/ForwardTranslator/ForwardTranslateWaterHeaterHeatPump.cpp +++ b/src/energyplus/ForwardTranslator/ForwardTranslateWaterHeaterHeatPump.cpp @@ -141,6 +141,11 @@ namespace energyplus { idfObject.setString(WaterHeater_HeatPump_PumpedCondenserFields::ParasiticHeatRejectionLocation, value); } + { + auto value = modelObject.tankElementControlLogic(); + idfObject.setString(WaterHeater_HeatPump_PumpedCondenserFields::TankElementControlLogic, value); + } + { auto tank = modelObject.tank(); if (auto stratifiedTank = tank.optionalCast()) { diff --git a/src/model/WaterHeaterHeatPump.cpp b/src/model/WaterHeaterHeatPump.cpp index f6eeb8e31f..817185938a 100644 --- a/src/model/WaterHeaterHeatPump.cpp +++ b/src/model/WaterHeaterHeatPump.cpp @@ -229,6 +229,12 @@ namespace model { return value.get(); } + std::string WaterHeaterHeatPump_Impl::tankElementControlLogic() const { + boost::optional value = getString(OS_WaterHeater_HeatPumpFields::TankElementControlLogic, true); + OS_ASSERT(value); + return value.get(); + } + std::string WaterHeaterHeatPump_Impl::controlSensorLocationInStratifiedTank() const { boost::optional value = getString(OS_WaterHeater_HeatPumpFields::ControlSensorLocationInStratifiedTank, true); OS_ASSERT(value); @@ -393,6 +399,11 @@ namespace model { return result; } + bool WaterHeaterHeatPump_Impl::setTankElementControlLogic(const std::string& tankElementControlLogic) { + bool result = setString(OS_WaterHeater_HeatPumpFields::TankElementControlLogic, tankElementControlLogic); + return result; + } + bool WaterHeaterHeatPump_Impl::setControlSensorLocationInStratifiedTank(const std::string& controlSensorLocationInStratifiedTank) { bool result = setString(OS_WaterHeater_HeatPumpFields::ControlSensorLocationInStratifiedTank, controlSensorLocationInStratifiedTank); return result; @@ -565,6 +576,7 @@ namespace model { setOnCycleParasiticElectricLoad(0.0); setOffCycleParasiticElectricLoad(0.0); setParasiticHeatRejectionLocation("Outdoors"); + setTankElementControlLogic("Simultaneous"); setControlSensorLocationInStratifiedTank("Heater1"); } @@ -621,6 +633,7 @@ namespace model { setOnCycleParasiticElectricLoad(0.0); setOffCycleParasiticElectricLoad(0.0); setParasiticHeatRejectionLocation("Outdoors"); + setTankElementControlLogic("Simultaneous"); setControlSensorLocationInStratifiedTank("Heater1"); } @@ -649,6 +662,10 @@ namespace model { OS_WaterHeater_HeatPumpFields::ControlSensorLocationInStratifiedTank); } + std::vector WaterHeaterHeatPump::tankElementControlLogicValues() { + return getIddKeyNames(IddFactory::instance().getObject(iddObjectType()).get(), OS_WaterHeater_HeatPumpFields::TankElementControlLogic); + } + boost::optional WaterHeaterHeatPump::availabilitySchedule() const { return getImpl()->availabilitySchedule(); } @@ -737,6 +754,10 @@ namespace model { return getImpl()->inletAirMixerSchedule(); } + std::string WaterHeaterHeatPump::tankElementControlLogic() const { + return getImpl()->tankElementControlLogic(); + } + std::string WaterHeaterHeatPump::controlSensorLocationInStratifiedTank() const { return getImpl()->controlSensorLocationInStratifiedTank(); } @@ -855,6 +876,10 @@ namespace model { return getImpl()->setInletAirMixerSchedule(schedule); } + bool WaterHeaterHeatPump::setTankElementControlLogic(const std::string& tankElementControlLogic) { + return getImpl()->setTankElementControlLogic(tankElementControlLogic); + } + bool WaterHeaterHeatPump::setControlSensorLocationInStratifiedTank(const std::string& controlSensorLocationInStratifiedTank) { return getImpl()->setControlSensorLocationInStratifiedTank(controlSensorLocationInStratifiedTank); } diff --git a/src/model/WaterHeaterHeatPump.hpp b/src/model/WaterHeaterHeatPump.hpp index 5ae484fb1b..05520f7827 100644 --- a/src/model/WaterHeaterHeatPump.hpp +++ b/src/model/WaterHeaterHeatPump.hpp @@ -55,6 +55,8 @@ namespace model { static std::vector parasiticHeatRejectionLocationValues(); + static std::vector tankElementControlLogicValues(); + static std::vector controlSensorLocationInStratifiedTankValues(); /** @name Getters */ @@ -104,6 +106,8 @@ namespace model { Schedule inletAirMixerSchedule() const; + std::string tankElementControlLogic() const; + std::string controlSensorLocationInStratifiedTank() const; //@} @@ -166,6 +170,8 @@ namespace model { bool setInletAirMixerSchedule(Schedule& schedule); + bool setTankElementControlLogic(const std::string& tankElementControlLogic); + bool setControlSensorLocationInStratifiedTank(const std::string& controlSensorLocationInStratifiedTank); //@} diff --git a/src/model/WaterHeaterHeatPump_Impl.hpp b/src/model/WaterHeaterHeatPump_Impl.hpp index 089cda92e1..7f2edc2437 100644 --- a/src/model/WaterHeaterHeatPump_Impl.hpp +++ b/src/model/WaterHeaterHeatPump_Impl.hpp @@ -95,6 +95,8 @@ namespace model { Schedule inletAirMixerSchedule() const; + std::string tankElementControlLogic() const; + std::string controlSensorLocationInStratifiedTank() const; boost::optional autosizedCondenserWaterFlowRate() const; @@ -165,6 +167,8 @@ namespace model { bool setInletAirMixerSchedule(Schedule& schedule); + bool setTankElementControlLogic(const std::string& tankElementControlLogic); + bool setControlSensorLocationInStratifiedTank(const std::string& controlSensorLocationInStratifiedTank); //@} diff --git a/src/model/test/WaterHeaterHeatPump_GTest.cpp b/src/model/test/WaterHeaterHeatPump_GTest.cpp index d7da8d7f48..f1d848735c 100644 --- a/src/model/test/WaterHeaterHeatPump_GTest.cpp +++ b/src/model/test/WaterHeaterHeatPump_GTest.cpp @@ -254,6 +254,14 @@ TEST_F(ModelFixture, WaterHeaterHeatPump_GettersSetters) { EXPECT_EQ(obj, hpwh.inletAirMixerSchedule()); } + // Tank Element Control Logic: Required String + EXPECT_EQ("Simultaneous", hpwh.tankElementControlLogic()); + EXPECT_TRUE(hpwh.setTankElementControlLogic("MutuallyExclusive")); + EXPECT_EQ("MutuallyExclusive", hpwh.tankElementControlLogic()); + // Bad Value + EXPECT_FALSE(hpwh.setTankElementControlLogic("BADENUM")); + EXPECT_EQ("MutuallyExclusive", hpwh.tankElementControlLogic()); + // Control Sensor Location In Stratified Tank: Required String EXPECT_TRUE(hpwh.setControlSensorLocationInStratifiedTank("Heater1")); EXPECT_EQ("Heater1", hpwh.controlSensorLocationInStratifiedTank()); From f82ef7570395bb6baa6c626d9d88196dcc63a639 Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Wed, 18 Dec 2024 14:21:40 +0100 Subject: [PATCH 4/6] #5314 - Add VersionTranslation for Tank Element Control Logic to model / FT for WaterHeaterHeatPump --- src/osversion/VersionTranslator.cpp | 46 ++- src/osversion/VersionTranslator.hpp | 1 + .../3_9_1/test_vt_WaterHeaterHeatPump.osm | 380 ++++++++++++++++++ .../test/3_9_1/test_vt_WaterHeaterHeatPump.rb | 13 + .../test/VersionTranslator_GTest.cpp | 26 ++ 5 files changed, 465 insertions(+), 1 deletion(-) create mode 100644 src/osversion/test/3_9_1/test_vt_WaterHeaterHeatPump.osm create mode 100644 src/osversion/test/3_9_1/test_vt_WaterHeaterHeatPump.rb diff --git a/src/osversion/VersionTranslator.cpp b/src/osversion/VersionTranslator.cpp index 534c778af0..c449598bc4 100644 --- a/src/osversion/VersionTranslator.cpp +++ b/src/osversion/VersionTranslator.cpp @@ -145,7 +145,7 @@ namespace osversion { m_updateMethods[VersionString("3.7.0")] = &VersionTranslator::update_3_6_1_to_3_7_0; m_updateMethods[VersionString("3.8.0")] = &VersionTranslator::update_3_7_0_to_3_8_0; m_updateMethods[VersionString("3.9.0")] = &VersionTranslator::update_3_8_0_to_3_9_0; - m_updateMethods[VersionString("3.9.1")] = &VersionTranslator::defaultUpdate; + m_updateMethods[VersionString("3.9.1")] = &VersionTranslator::update_3_9_0_to_3_9_1; // m_updateMethods[VersionString("3.10.0")] = &VersionTranslator::defaultUpdate; // List of previous versions that may be updated to this one. @@ -9636,5 +9636,49 @@ namespace osversion { } // end update_3_8_0_to_3_9_0 + std::string VersionTranslator::update_3_9_0_to_3_9_1(const IdfFile& idf_3_9_0, const IddFileAndFactoryWrapper& idd_3_9_1) { + std::stringstream ss; + boost::optional value; + + ss << idf_3_9_0.header() << '\n' << '\n'; + IdfFile targetIdf(idd_3_9_1.iddFile()); + ss << targetIdf.versionObject().get(); + + for (const IdfObject& object : idf_3_9_0.objects()) { + auto iddname = object.iddObject().name(); + + if (iddname == "OS:WaterHeater:HeatPump") { + + // 1 Field has been inserted from 3.9.0 to 3.9.1: + // ---------------------------------------------- + // * Tank Element Control Logic * 25 + auto iddObject = idd_3_9_1.getObject(iddname); + IdfObject newObject(iddObject.get()); + + for (size_t i = 0; i < object.numFields(); ++i) { + if ((value = object.getString(i))) { + if (i < 25) { + newObject.setString(i, value.get()); + } else { + newObject.setString(i + 1, value.get()); + } + } + } + + newObject.setString(25, "Simultaneous"); + + ss << newObject; + m_refactored.emplace_back(std::move(object), std::move(newObject)); + + // No-op + } else { + ss << object; + } + } + + return ss.str(); + + } // end update_3_9_0_to_3_9_1 + } // namespace osversion } // namespace openstudio diff --git a/src/osversion/VersionTranslator.hpp b/src/osversion/VersionTranslator.hpp index 4600c2faa7..9ea4e977e4 100644 --- a/src/osversion/VersionTranslator.hpp +++ b/src/osversion/VersionTranslator.hpp @@ -237,6 +237,7 @@ namespace osversion { std::string update_3_6_1_to_3_7_0(const IdfFile& idf_3_6_1, const IddFileAndFactoryWrapper& idd_3_7_0); std::string update_3_7_0_to_3_8_0(const IdfFile& idf_3_7_0, const IddFileAndFactoryWrapper& idd_3_8_0); std::string update_3_8_0_to_3_9_0(const IdfFile& idf_3_8_0, const IddFileAndFactoryWrapper& idd_3_9_0); + std::string update_3_9_0_to_3_9_1(const IdfFile& idf_3_9_0, const IddFileAndFactoryWrapper& idd_3_9_1); IdfObject updateUrlField_0_7_1_to_0_7_2(const IdfObject& object, unsigned index); diff --git a/src/osversion/test/3_9_1/test_vt_WaterHeaterHeatPump.osm b/src/osversion/test/3_9_1/test_vt_WaterHeaterHeatPump.osm new file mode 100644 index 0000000000..a645294ee6 --- /dev/null +++ b/src/osversion/test/3_9_1/test_vt_WaterHeaterHeatPump.osm @@ -0,0 +1,380 @@ + +OS:Version, + {9fc26069-607c-49f9-a9f9-06c348919a6e}, !- Handle + 3.9.0; !- Version Identifier + +OS:WaterHeater:HeatPump, + {86c0fef7-5c22-4fac-9766-9c880b4dd43e}, !- Handle + Water Heater Heat Pump 1, !- Name + , !- Availability Schedule + {170bb840-b066-4bc0-ad04-79e4f616663c}, !- Compressor Setpoint Temperature Schedule + 5, !- Dead Band Temperature Difference {deltaC} + autosize, !- Condenser Water Flow Rate {m3/s} + autosize, !- Evaporator Air Flow Rate {m3/s} + Schedule, !- Inlet Air Configuration + , !- Air Inlet Node + , !- Air Outlet Node + , !- Outdoor Air Node + {9868d5f7-3b93-4786-b56f-567304422d2a}, !- Inlet Air Temperature Schedule + {7752e8ab-439d-4a4a-8e9e-4ebe2f47d34c}, !- Inlet Air Humidity Schedule + {80515266-3261-422f-8ea5-e42363a5ab5f}, !- Tank + {fcf0e2a4-67eb-49a0-8c8b-f8d44fc8e50a}, !- DX Coil + 10, !- Minimum Inlet Air Temperature for Compressor Operation {C} + 48.89, !- Maximum Inlet Air Temperature for Compressor Operation {C} + Schedule, !- Compressor Location + {4d0ad212-207e-4ad0-be44-dc85cde2f773}, !- Compressor Ambient Temperature Schedule + {427ec742-b5e4-4684-ab67-0efd2c2dfc62}, !- Fan + DrawThrough, !- Fan Placement + 0, !- On Cycle Parasitic Electric Load {W} + 0, !- Off Cycle Parasitic Electric Load {W} + Outdoors, !- Parasitic Heat Rejection Location + {d1edcd81-43ce-420e-a192-89dd610f1f05}, !- Inlet Air Mixer Schedule + Heater2; !- Control Sensor Location In Stratified Tank + +OS:Coil:WaterHeating:AirToWaterHeatPump, + {fcf0e2a4-67eb-49a0-8c8b-f8d44fc8e50a}, !- Handle + Coil Water Heating Air To Water Heat Pump 1, !- Name + 4000, !- Rated Heating Capacity {W} + 3.2, !- Rated COP {W/W} + 0.6956, !- Rated Sensible Heat Ratio + 29.44, !- Rated Evaporator Inlet Air Dry-Bulb Temperature {C} + 22.22, !- Rated Evaporator Inlet Air Wet-Bulb Temperature {C} + 55.72, !- Rated Condenser Inlet Water Temperature {C} + autosize, !- Rated Evaporator Air Flow Rate {m3/s} + autosize, !- Rated Condenser Water Flow Rate {m3/s} + No, !- Evaporator Fan Power Included in Rated COP + No, !- Condenser Pump Power Included in Rated COP + No, !- Condenser Pump Heat Included in Rated Heating Capacity and Rated COP + 150, !- Condenser Water Pump Power {W} + 0.1, !- Fraction of Condenser Pump Heat to Water + , !- Evaporator Air Inlet Node Name + , !- Evaporator Air Outlet Node Name + , !- Condenser Water Inlet Node + , !- Condenser Water Outlet Node + 100, !- Crankcase Heater Capacity {W} + , !- Crankcase Heater Capacity Function of Temperature Curve Name + 5, !- Maximum Ambient Temperature for Crankcase Heater Operation {C} + WetBulbTemperature, !- Evaporator Air Temperature Type for Curve Objects + {d4ed0d7e-d0ee-4604-b0ce-d02ac665ef3c}, !- Heating Capacity Function of Temperature Curve + {1d000c3a-a46f-4887-a5b7-4658e992eadb}, !- Heating Capacity Function of Air Flow Fraction Curve + {69123eb8-cc62-4508-b209-4621759c0f6f}, !- Heating Capacity Function of Water Flow Fraction Curve + {5982a871-e93a-4084-9222-beb018f55f51}, !- Heating COP Function of Temperature Curve + {3f07af59-c45c-4ccf-a498-3859c302ed70}, !- Heating COP Function of Air Flow Fraction Curve + {f6ceebd3-853b-4eb2-b98e-c9c17829ed96}, !- Heating COP Function of Water Flow Fraction Curve + {ee072dfe-f061-472d-a382-48531c0e839d}; !- Part Load Fraction Correlation Curve + +OS:Curve:Biquadratic, + {d4ed0d7e-d0ee-4604-b0ce-d02ac665ef3c}, !- Handle + Curve Biquadratic 1, !- Name + 0.369827, !- Coefficient1 Constant + 0.043341, !- Coefficient2 x + -0.00023, !- Coefficient3 x**2 + 0.000466, !- Coefficient4 y + 2.6e-05, !- Coefficient5 y**2 + -0.00027, !- Coefficient6 x*y + 0, !- Minimum Value of x + 40, !- Maximum Value of x + 20, !- Minimum Value of y + 90, !- Maximum Value of y + , !- Minimum Curve Output + , !- Maximum Curve Output + Temperature, !- Input Unit Type for X + Temperature, !- Input Unit Type for Y + Dimensionless; !- Output Unit Type + +OS:Curve:Quadratic, + {1d000c3a-a46f-4887-a5b7-4658e992eadb}, !- Handle + Curve Quadratic 1, !- Name + 1, !- Coefficient1 Constant + 0, !- Coefficient2 x + 0, !- Coefficient3 x**2 + 0, !- Minimum Value of x + 1; !- Maximum Value of x + +OS:Curve:Quadratic, + {69123eb8-cc62-4508-b209-4621759c0f6f}, !- Handle + Curve Quadratic 2, !- Name + 1, !- Coefficient1 Constant + 0, !- Coefficient2 x + 0, !- Coefficient3 x**2 + 0, !- Minimum Value of x + 1; !- Maximum Value of x + +OS:Curve:Biquadratic, + {5982a871-e93a-4084-9222-beb018f55f51}, !- Handle + Curve Biquadratic 2, !- Name + 1.19713, !- Coefficient1 Constant + 0.077849, !- Coefficient2 x + -1.6e-06, !- Coefficient3 x**2 + -0.02675, !- Coefficient4 y + 0.000296, !- Coefficient5 y**2 + -0.00112, !- Coefficient6 x*y + 0, !- Minimum Value of x + 40, !- Maximum Value of x + 20, !- Minimum Value of y + 90, !- Maximum Value of y + , !- Minimum Curve Output + , !- Maximum Curve Output + Temperature, !- Input Unit Type for X + Temperature, !- Input Unit Type for Y + Dimensionless; !- Output Unit Type + +OS:Curve:Quadratic, + {3f07af59-c45c-4ccf-a498-3859c302ed70}, !- Handle + Curve Quadratic 3, !- Name + 1, !- Coefficient1 Constant + 0, !- Coefficient2 x + 0, !- Coefficient3 x**2 + 0, !- Minimum Value of x + 1; !- Maximum Value of x + +OS:Curve:Quadratic, + {f6ceebd3-853b-4eb2-b98e-c9c17829ed96}, !- Handle + Curve Quadratic 4, !- Name + 1, !- Coefficient1 Constant + 0, !- Coefficient2 x + 0, !- Coefficient3 x**2 + 0, !- Minimum Value of x + 1; !- Maximum Value of x + +OS:Curve:Quadratic, + {ee072dfe-f061-472d-a382-48531c0e839d}, !- Handle + Curve Quadratic 5, !- Name + 0.75, !- Coefficient1 Constant + 0.25, !- Coefficient2 x + 0, !- Coefficient3 x**2 + 0, !- Minimum Value of x + 1; !- Maximum Value of x + +OS:WaterHeater:Mixed, + {80515266-3261-422f-8ea5-e42363a5ab5f}, !- Handle + Water Heater Mixed 1, !- Name + 0.3785, !- Tank Volume {m3} + {d165ff2b-a4bc-4dd2-a986-008cfd26096a}, !- Setpoint Temperature Schedule Name + 2, !- Deadband Temperature Difference {deltaC} + 82.22, !- Maximum Temperature Limit {C} + Cycle, !- Heater Control Type + 845000, !- Heater Maximum Capacity {W} + , !- Heater Minimum Capacity {W} + , !- Heater Ignition Minimum Flow Rate {m3/s} + , !- Heater Ignition Delay {s} + NaturalGas, !- Heater Fuel Type + 0.8, !- Heater Thermal Efficiency + , !- Part Load Factor Curve Name + 20, !- Off Cycle Parasitic Fuel Consumption Rate {W} + NaturalGas, !- Off Cycle Parasitic Fuel Type + 0.8, !- Off Cycle Parasitic Heat Fraction to Tank + , !- On Cycle Parasitic Fuel Consumption Rate {W} + NaturalGas, !- On Cycle Parasitic Fuel Type + , !- On Cycle Parasitic Heat Fraction to Tank + Schedule, !- Ambient Temperature Indicator + {2b6df6dd-c4c9-4ef2-a003-91e1cfb8e68a}, !- Ambient Temperature Schedule Name + , !- Ambient Temperature Thermal Zone Name + , !- Ambient Temperature Outdoor Air Node Name + 6, !- Off Cycle Loss Coefficient to Ambient Temperature {W/K} + , !- Off Cycle Loss Fraction to Thermal Zone + 6, !- On Cycle Loss Coefficient to Ambient Temperature {W/K} + , !- On Cycle Loss Fraction to Thermal Zone + , !- Peak Use Flow Rate {m3/s} + , !- Use Flow Rate Fraction Schedule Name + , !- Cold Water Supply Temperature Schedule Name + , !- Use Side Inlet Node Name + , !- Use Side Outlet Node Name + 1, !- Use Side Effectiveness + , !- Source Side Inlet Node Name + , !- Source Side Outlet Node Name + 1, !- Source Side Effectiveness + autosize, !- Use Side Design Flow Rate {m3/s} + autosize, !- Source Side Design Flow Rate {m3/s} + 1.5, !- Indirect Water Heating Recovery Time {hr} + IndirectHeatPrimarySetpoint, !- Source Side Flow Control Mode + , !- Indirect Alternate Setpoint Temperature Schedule Name + General; !- End-Use Subcategory + +OS:Schedule:Ruleset, + {2b6df6dd-c4c9-4ef2-a003-91e1cfb8e68a}, !- Handle + Schedule Ruleset 1, !- Name + {7618d9a8-9a72-4d93-8572-e246cc181e6d}, !- Schedule Type Limits Name + {32413f84-23b6-423c-8298-47885f192f55}; !- Default Day Schedule Name + +OS:Schedule:Day, + {32413f84-23b6-423c-8298-47885f192f55}, !- Handle + Schedule Day 1, !- Name + {7618d9a8-9a72-4d93-8572-e246cc181e6d}, !- Schedule Type Limits Name + , !- Interpolate to Timestep + 24, !- Hour 1 + 0, !- Minute 1 + 22; !- Value Until Time 1 + +OS:ScheduleTypeLimits, + {7618d9a8-9a72-4d93-8572-e246cc181e6d}, !- Handle + Temperature, !- Name + , !- Lower Limit Value + , !- Upper Limit Value + Continuous, !- Numeric Type + Temperature; !- Unit Type + +OS:Schedule:Ruleset, + {d165ff2b-a4bc-4dd2-a986-008cfd26096a}, !- Handle + Schedule Ruleset 2, !- Name + {7618d9a8-9a72-4d93-8572-e246cc181e6d}, !- Schedule Type Limits Name + {b7425088-0278-4f27-ac6b-2f33b3b751f6}; !- Default Day Schedule Name + +OS:Schedule:Day, + {b7425088-0278-4f27-ac6b-2f33b3b751f6}, !- Handle + Schedule Day 2, !- Name + {7618d9a8-9a72-4d93-8572-e246cc181e6d}, !- Schedule Type Limits Name + , !- Interpolate to Timestep + 24, !- Hour 1 + 0, !- Minute 1 + 60; !- Value Until Time 1 + +OS:WaterHeater:Sizing, + {c6e53721-60db-4fe5-86e4-a2fb4b6a4b05}, !- Handle + {80515266-3261-422f-8ea5-e42363a5ab5f}, !- WaterHeater Name + PeakDraw, !- Design Mode + 0.538503, !- Time Storage Can Meet Peak Draw {hr} + 0, !- Time for Tank Recovery {hr} + 1; !- Nominal Tank Volume for Autosizing Plant Connections {m3} + +OS:Fan:OnOff, + {427ec742-b5e4-4684-ab67-0efd2c2dfc62}, !- Handle + Fan On Off 1, !- Name + {ffe3c9b3-c46e-4801-851d-af35235b19d0}, !- Availability Schedule Name + 0.6, !- Fan Total Efficiency + 300, !- Pressure Rise {Pa} + autosize, !- Maximum Flow Rate {m3/s} + 0.8, !- Motor Efficiency + 1, !- Motor In Airstream Fraction + , !- Air Inlet Node Name + , !- Air Outlet Node Name + {e64c8d56-a78b-4adf-994a-49036b1b02dd}, !- Fan Power Ratio Function of Speed Ratio Curve Name + {d1e63cae-b8bb-4d63-997f-cf914bc1cc9d}, !- Fan Efficiency Ratio Function of Speed Ratio Curve Name + ; !- End-Use Subcategory + +OS:Schedule:Constant, + {ffe3c9b3-c46e-4801-851d-af35235b19d0}, !- Handle + Always On Discrete, !- Name + {c0caae58-b814-4f35-b1b2-d5c86b8d739d}, !- Schedule Type Limits Name + 1; !- Value + +OS:ScheduleTypeLimits, + {c0caae58-b814-4f35-b1b2-d5c86b8d739d}, !- Handle + OnOff, !- Name + 0, !- Lower Limit Value + 1, !- Upper Limit Value + Discrete, !- Numeric Type + Availability; !- Unit Type + +OS:Curve:Exponent, + {e64c8d56-a78b-4adf-994a-49036b1b02dd}, !- Handle + Fan On Off Power Curve, !- Name + 1, !- Coefficient1 Constant + 0, !- Coefficient2 Constant + 0, !- Coefficient3 Constant + 0, !- Minimum Value of x + 1, !- Maximum Value of x + , !- Minimum Curve Output + , !- Maximum Curve Output + , !- Input Unit Type for X + ; !- Output Unit Type + +OS:Curve:Cubic, + {d1e63cae-b8bb-4d63-997f-cf914bc1cc9d}, !- Handle + Fan On Off Efficiency Curve, !- Name + 1, !- Coefficient1 Constant + 0, !- Coefficient2 x + 0, !- Coefficient3 x**2 + 0, !- Coefficient4 x**3 + 0, !- Minimum Value of x + 1; !- Maximum Value of x + +OS:Schedule:Ruleset, + {170bb840-b066-4bc0-ad04-79e4f616663c}, !- Handle + Schedule Ruleset 3, !- Name + {7618d9a8-9a72-4d93-8572-e246cc181e6d}, !- Schedule Type Limits Name + {4f334873-4053-4c1d-9aaa-a84c9bd5d466}; !- Default Day Schedule Name + +OS:Schedule:Day, + {4f334873-4053-4c1d-9aaa-a84c9bd5d466}, !- Handle + Schedule Day 3, !- Name + {7618d9a8-9a72-4d93-8572-e246cc181e6d}, !- Schedule Type Limits Name + , !- Interpolate to Timestep + 24, !- Hour 1 + 0, !- Minute 1 + 60; !- Value Until Time 1 + +OS:Schedule:Ruleset, + {d1edcd81-43ce-420e-a192-89dd610f1f05}, !- Handle + HPWH Inlet Air Mixer Schedule, !- Name + {a9d7daaf-e76b-48a2-b017-3977bb48fcbe}, !- Schedule Type Limits Name + {6b875af1-5c3a-4f41-97bb-5f6074b1b800}; !- Default Day Schedule Name + +OS:Schedule:Day, + {6b875af1-5c3a-4f41-97bb-5f6074b1b800}, !- Handle + Schedule Day 4, !- Name + {a9d7daaf-e76b-48a2-b017-3977bb48fcbe}, !- Schedule Type Limits Name + , !- Interpolate to Timestep + 24, !- Hour 1 + 0, !- Minute 1 + 0.2; !- Value Until Time 1 + +OS:ScheduleTypeLimits, + {a9d7daaf-e76b-48a2-b017-3977bb48fcbe}, !- Handle + Fractional, !- Name + 0, !- Lower Limit Value + 1, !- Upper Limit Value + Continuous; !- Numeric Type + +OS:Schedule:Ruleset, + {9868d5f7-3b93-4786-b56f-567304422d2a}, !- Handle + Schedule Ruleset 5, !- Name + {7618d9a8-9a72-4d93-8572-e246cc181e6d}, !- Schedule Type Limits Name + {6e56ba9f-bcbc-4723-8fe9-4c09fa52513a}; !- Default Day Schedule Name + +OS:Schedule:Day, + {6e56ba9f-bcbc-4723-8fe9-4c09fa52513a}, !- Handle + Schedule Day 5, !- Name + {7618d9a8-9a72-4d93-8572-e246cc181e6d}, !- Schedule Type Limits Name + , !- Interpolate to Timestep + 24, !- Hour 1 + 0, !- Minute 1 + 19.7; !- Value Until Time 1 + +OS:Schedule:Ruleset, + {7752e8ab-439d-4a4a-8e9e-4ebe2f47d34c}, !- Handle + Schedule Ruleset 6, !- Name + {c3980eb2-a25c-4df1-9a0b-81c4934bb9bd}, !- Schedule Type Limits Name + {65947b68-f663-43f4-86ec-b6eb614ecf4c}; !- Default Day Schedule Name + +OS:Schedule:Day, + {65947b68-f663-43f4-86ec-b6eb614ecf4c}, !- Handle + Schedule Day 6, !- Name + {c3980eb2-a25c-4df1-9a0b-81c4934bb9bd}, !- Schedule Type Limits Name + , !- Interpolate to Timestep + 24, !- Hour 1 + 0, !- Minute 1 + 0.5; !- Value Until Time 1 + +OS:ScheduleTypeLimits, + {c3980eb2-a25c-4df1-9a0b-81c4934bb9bd}, !- Handle + Dimensionless, !- Name + 0, !- Lower Limit Value + , !- Upper Limit Value + Continuous; !- Numeric Type + +OS:Schedule:Ruleset, + {4d0ad212-207e-4ad0-be44-dc85cde2f773}, !- Handle + Schedule Ruleset 7, !- Name + {7618d9a8-9a72-4d93-8572-e246cc181e6d}, !- Schedule Type Limits Name + {43a1ced1-c811-4c6c-ae05-c864f5234b41}; !- Default Day Schedule Name + +OS:Schedule:Day, + {43a1ced1-c811-4c6c-ae05-c864f5234b41}, !- Handle + Schedule Day 7, !- Name + {7618d9a8-9a72-4d93-8572-e246cc181e6d}, !- Schedule Type Limits Name + , !- Interpolate to Timestep + 24, !- Hour 1 + 0, !- Minute 1 + 21; !- Value Until Time 1 + diff --git a/src/osversion/test/3_9_1/test_vt_WaterHeaterHeatPump.rb b/src/osversion/test/3_9_1/test_vt_WaterHeaterHeatPump.rb new file mode 100644 index 0000000000..23467677bd --- /dev/null +++ b/src/osversion/test/3_9_1/test_vt_WaterHeaterHeatPump.rb @@ -0,0 +1,13 @@ +#require '/usr/local/openstudio-3.9.0/Ruby/openstudio' + +include OpenStudio::Model + +m = Model.new + +hpwh = WaterHeaterHeatPump.new(m) +# Field before insertion +hpwh.inletAirMixerSchedule.setName("HPWH Inlet Air Mixer Schedule") +# Field after insertion, also last field +hpwh.setControlSensorLocationInStratifiedTank("Heater2") + +m.save('test_vt_WaterHeaterHeatPump.osm', true) diff --git a/src/osversion/test/VersionTranslator_GTest.cpp b/src/osversion/test/VersionTranslator_GTest.cpp index de25c25a3b..bf7acdd53d 100644 --- a/src/osversion/test/VersionTranslator_GTest.cpp +++ b/src/osversion/test/VersionTranslator_GTest.cpp @@ -4524,3 +4524,29 @@ TEST_F(OSVersionFixture, update_3_8_0_to_3_9_0_SizingZone) { EXPECT_EQ("Coincident", sizing_zone.getString(39).get()); // Sizing Option } + +TEST_F(OSVersionFixture, update_3_9_0_to_3_9_1_WaterHeaterHeatPump) { + openstudio::path path = resourcesPath() / toPath("osversion/3_9_1/test_vt_WaterHeaterHeatPump.osm"); + osversion::VersionTranslator vt; + boost::optional model = vt.loadModel(path); + ASSERT_TRUE(model) << "Failed to load " << path; + + openstudio::path outPath = resourcesPath() / toPath("osversion/3_9_1/test_vt_WaterHeaterHeatPump_updated.osm"); + model->save(outPath, true); + + std::vector hpwhs = model->getObjectsByType("OS:WaterHeater:HeatPump"); + ASSERT_EQ(1u, hpwhs.size()); + const auto& hpwh = hpwhs.front(); + + EXPECT_EQ("Water Heater Heat Pump 1", hpwh.getString(1).get()); // Name + + // Before insertion: Inlet Air Mixer Schedule + ASSERT_TRUE(hpwh.getTarget(24)); + EXPECT_EQ("HPWH Inlet Air Mixer Schedule", hpwh.getTarget(24)->nameString()); + + // New Field: Tank Element Control Logic + EXPECT_EQ("Simultaneous", hpwh.getString(25).get()); + + // After insertion and also last field: Control Sensor Location In Stratified Tank + EXPECT_EQ("Heater2", hpwh.getString(26).get()); +} From 4c2a2abcdbdf26536bb32f4270da7fd4463b25f3 Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Wed, 18 Dec 2024 14:22:14 +0100 Subject: [PATCH 5/6] Unrelated but leave a TODO: the default Tank Element Control Logic is NOT the E+ default for WaterHeaterHeatPumpWrappedCondenser --- src/model/WaterHeaterHeatPumpWrappedCondenser.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/model/WaterHeaterHeatPumpWrappedCondenser.cpp b/src/model/WaterHeaterHeatPumpWrappedCondenser.cpp index c287140ad2..8da4f2a26a 100644 --- a/src/model/WaterHeaterHeatPumpWrappedCondenser.cpp +++ b/src/model/WaterHeaterHeatPumpWrappedCondenser.cpp @@ -610,7 +610,7 @@ namespace model { setOnCycleParasiticElectricLoad(0.0); setOffCycleParasiticElectricLoad(0.0); setParasiticHeatRejectionLocation("Outdoors"); - setTankElementControlLogic("MutuallyExclusive"); + setTankElementControlLogic("MutuallyExclusive"); // TODO: The E+ default is Simultaneous! setControlSensor1HeightInStratifiedTank(1.262); setControlSensor1Weight(0.75); setControlSensor2HeightInStratifiedTank(0.464); @@ -640,7 +640,7 @@ namespace model { setOnCycleParasiticElectricLoad(0.0); setOffCycleParasiticElectricLoad(0.0); setParasiticHeatRejectionLocation("Outdoors"); - setTankElementControlLogic("MutuallyExclusive"); + setTankElementControlLogic("MutuallyExclusive"); // TODO: The E+ default is Simultaneous! setControlSensor1HeightInStratifiedTank(1.262); setControlSensor1Weight(0.75); setControlSensor2HeightInStratifiedTank(0.464); From 2e37401ff9e5886ad8ab55b3a84cecf2664ed4c4 Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Wed, 18 Dec 2024 16:53:47 +0100 Subject: [PATCH 6/6] adjust old VT test --- src/osversion/test/VersionTranslator_GTest.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/osversion/test/VersionTranslator_GTest.cpp b/src/osversion/test/VersionTranslator_GTest.cpp index bf7acdd53d..d946b751a6 100644 --- a/src/osversion/test/VersionTranslator_GTest.cpp +++ b/src/osversion/test/VersionTranslator_GTest.cpp @@ -1216,8 +1216,8 @@ TEST_F(OSVersionFixture, update_3_0_1_to_3_1_0_WaterHeaterHeatPump) { EXPECT_EQ("Outdoors", wh.getString(17, false, true).get()); // Last Field: Control Sensor Location In Stratified Tank - ASSERT_TRUE(wh.getString(25, false, true)); - EXPECT_EQ("Heater2", wh.getString(25, false, true).get()); + ASSERT_TRUE(wh.getString(26, false, true)); + EXPECT_EQ("Heater2", wh.getString(26, false, true).get()); } TEST_F(OSVersionFixture, update_3_0_1_to_3_1_0_ShadingControl_and_SubSurfaces) {