diff --git a/src/energyplus/CMakeLists.txt b/src/energyplus/CMakeLists.txt index 5cfa5d7497c..306cb07c83f 100644 --- a/src/energyplus/CMakeLists.txt +++ b/src/energyplus/CMakeLists.txt @@ -856,6 +856,7 @@ set(${target_name}_test_src Test/ThermostatSetpointDualSetpoint_GTest.cpp Test/UnitarySystemPerformanceMultispeed_GTest.cpp Test/WindowPropertyFrameAndDivider_GTest.cpp + Test/WaterHeaterHeatPumpWrappedCondenser_GTest.cpp Test/WaterHeaterMixed_GTest.cpp Test/WaterHeaterSizing_GTest.cpp Test/WaterHeaterStratified_GTest.cpp diff --git a/src/energyplus/ForwardTranslator/ForwardTranslateWaterHeaterHeatPumpWrappedCondenser.cpp b/src/energyplus/ForwardTranslator/ForwardTranslateWaterHeaterHeatPumpWrappedCondenser.cpp index af2bf8b9da3..afea0fd33a6 100644 --- a/src/energyplus/ForwardTranslator/ForwardTranslateWaterHeaterHeatPumpWrappedCondenser.cpp +++ b/src/energyplus/ForwardTranslator/ForwardTranslateWaterHeaterHeatPumpWrappedCondenser.cpp @@ -108,8 +108,10 @@ namespace energyplus { } } - std::string airInletNodeName; - std::string airOutletNodeName; + // Logic is in model namespace for these two for EMS, cf #5547 + std::string airInletNodeName = modelObject.airInletNodeName(); + std::string airOutletNodeName = modelObject.airOutletNodeName(); + std::string outdoorAirNodeName; std::string exhaustAirNodeName; std::string inletAirZoneName; @@ -126,16 +128,12 @@ namespace energyplus { if (istringEqual(modelObject.fanPlacement(), "DrawThrough")) { idfObject.setString(WaterHeater_HeatPump_WrappedCondenserFields::FanPlacement, "DrawThrough"); + // Depending on inletAirConfiguration, what this returns will be different + // * "ZoneAirOnly" and "ZoneAndOutdoorAir" need to get nodes from the thermal zone + // * "OutdoorAirOnly" and "Schedule", it just constructs a node name. + // This is helpful if you need to control this via EMS if (istringEqual(inletAirConfiguration, "ZoneAirOnly")) { if (auto thermalZone = modelObject.thermalZone()) { - auto inletNode = modelObject.inletNode(); - OS_ASSERT(inletNode); - airInletNodeName = inletNode->name().get(); - - auto outletNode = modelObject.outletNode(); - OS_ASSERT(outletNode); - airOutletNodeName = outletNode->name().get(); - inletAirZoneName = thermalZone->name().get(); fanInletNodeName = modelObject.name().get() + " Evap Outlet - Fan Inlet"; fanOutletNodeName = airOutletNodeName; @@ -144,14 +142,6 @@ namespace energyplus { } } else if (istringEqual(inletAirConfiguration, "ZoneAndOutdoorAir")) { if (auto thermalZone = modelObject.thermalZone()) { - auto inletNode = modelObject.inletNode(); - OS_ASSERT(inletNode); - airInletNodeName = inletNode->name().get(); - - auto outletNode = modelObject.outletNode(); - OS_ASSERT(outletNode); - airOutletNodeName = outletNode->name().get(); - outdoorAirNodeName = modelObject.name().get() + " Outdoor Air"; exhaustAirNodeName = modelObject.name().get() + " Exhaust Air"; inletAirZoneName = thermalZone->name().get(); @@ -170,8 +160,6 @@ namespace energyplus { evapInletNodeName = outdoorAirNodeName; evapOutletNodeName = fanInletNodeName; } else if (istringEqual(inletAirConfiguration, "Schedule")) { - airInletNodeName = modelObject.name().get() + " Inlet"; - airOutletNodeName = modelObject.name().get() + " Outlet"; fanInletNodeName = modelObject.name().get() + " Evap Outlet - Fan Inlet"; fanOutletNodeName = airOutletNodeName; evapInletNodeName = airInletNodeName; @@ -183,14 +171,6 @@ namespace energyplus { if (istringEqual(inletAirConfiguration, "ZoneAirOnly")) { if (auto thermalZone = modelObject.thermalZone()) { - auto inletNode = modelObject.inletNode(); - OS_ASSERT(inletNode); - airInletNodeName = inletNode->name().get(); - - auto outletNode = modelObject.outletNode(); - OS_ASSERT(outletNode); - airOutletNodeName = outletNode->name().get(); - inletAirZoneName = thermalZone->name().get(); fanInletNodeName = airInletNodeName; fanOutletNodeName = modelObject.name().get() + " Fan Outlet - Evap Inlet"; @@ -199,14 +179,6 @@ namespace energyplus { } } else if (istringEqual(inletAirConfiguration, "ZoneAndOutdoorAir")) { if (auto thermalZone = modelObject.thermalZone()) { - auto inletNode = modelObject.inletNode(); - OS_ASSERT(inletNode); - airInletNodeName = inletNode->name().get(); - - auto outletNode = modelObject.outletNode(); - OS_ASSERT(outletNode); - airOutletNodeName = outletNode->name().get(); - outdoorAirNodeName = modelObject.name().get() + " Outdoor Air"; exhaustAirNodeName = modelObject.name().get() + " Exhaust Air"; inletAirZoneName = thermalZone->name().get(); @@ -225,8 +197,6 @@ namespace energyplus { evapInletNodeName = fanOutletNodeName; evapOutletNodeName = exhaustAirNodeName; } else if (istringEqual(inletAirConfiguration, "Schedule")) { - airInletNodeName = modelObject.name().get() + " Inlet"; - airOutletNodeName = modelObject.name().get() + " Outlet"; fanInletNodeName = airInletNodeName; fanOutletNodeName = modelObject.name().get() + " Fan Outlet - Evap Inlet"; evapInletNodeName = fanOutletNodeName; diff --git a/src/energyplus/Test/WaterHeaterHeatPumpWrappedCondenser_GTest.cpp b/src/energyplus/Test/WaterHeaterHeatPumpWrappedCondenser_GTest.cpp new file mode 100644 index 00000000000..48ea66d0d53 --- /dev/null +++ b/src/energyplus/Test/WaterHeaterHeatPumpWrappedCondenser_GTest.cpp @@ -0,0 +1,248 @@ +/*********************************************************************************************************************** +* OpenStudio(R), Copyright (c) Alliance for Sustainable Energy, LLC. +* See also https://openstudio.net/license +***********************************************************************************************************************/ + +#include +#include "EnergyPlusFixture.hpp" + +#include "../ForwardTranslator.hpp" + +#include "../../model/Model.hpp" +#include "../../model/CoilWaterHeatingAirToWaterHeatPumpWrapped.hpp" +#include "../../model/CoilWaterHeatingAirToWaterHeatPumpWrapped_Impl.hpp" +#include "../../model/WaterHeaterHeatPumpWrappedCondenser.hpp" +#include "../../model/ThermalZone.hpp" +#include "../../model/Space.hpp" +#include "../../model/ScheduleConstant.hpp" +#include "../../model/ScheduleConstant_Impl.hpp" +#include "../../model/WaterHeaterStratified.hpp" +#include "../../model/WaterHeaterStratified_Impl.hpp" +#include "../../model/FanOnOff.hpp" +#include "../../model/FanOnOff_Impl.hpp" +#include "../../model/PlantLoop.hpp" +#include "../../model/PlantLoop_Impl.hpp" +#include "../../model/Node.hpp" +#include "../../model/Node_Impl.hpp" + +#include +#include + +using namespace openstudio::energyplus; +using namespace openstudio::model; +using namespace openstudio; + +TEST_F(EnergyPlusFixture, ForwardTranslator_WaterHeaterHeatPumpWrappedCondenser_addToThermalZone) { + Model m; + + WaterHeaterStratified tank(m); + CoilWaterHeatingAirToWaterHeatPumpWrapped coil(m); + FanOnOff fan(m); + + WaterHeaterHeatPumpWrappedCondenser hpwh(m); + + hpwh.setName("My WaterHeaterHeatPumpWrappedCondenser"); + Schedule availabilitySchedule = m.alwaysOnDiscreteSchedule(); + EXPECT_TRUE(hpwh.setAvailabilitySchedule(availabilitySchedule)); + ScheduleConstant scheduleConstant1(m); + scheduleConstant1.setValue(0.1); + EXPECT_TRUE(hpwh.setCompressorSetpointTemperatureSchedule(scheduleConstant1)); + EXPECT_TRUE(hpwh.setDeadBandTemperatureDifference(1)); + EXPECT_TRUE(hpwh.setCondenserBottomLocation(2)); + EXPECT_TRUE(hpwh.setCondenserTopLocation(3)); + EXPECT_TRUE(hpwh.setEvaporatorAirFlowRate(4)); + EXPECT_TRUE(hpwh.setInletAirConfiguration("Schedule")); + ScheduleConstant scheduleConstant2(m); + scheduleConstant2.setValue(0.2); + EXPECT_TRUE(hpwh.setInletAirTemperatureSchedule(scheduleConstant2)); + ScheduleConstant scheduleConstant3(m); + scheduleConstant3.setValue(0.3); + EXPECT_TRUE(hpwh.setInletAirHumiditySchedule(scheduleConstant3)); + EXPECT_TRUE(hpwh.setTank(tank)); + EXPECT_TRUE(hpwh.setDXCoil(coil)); + EXPECT_TRUE(hpwh.setMinimumInletAirTemperatureforCompressorOperation(15)); + EXPECT_TRUE(hpwh.setMaximumInletAirTemperatureforCompressorOperation(30)); + EXPECT_TRUE(hpwh.setCompressorLocation("Outdoors")); + ScheduleConstant scheduleConstant4(m); + scheduleConstant4.setValue(0.4); + EXPECT_TRUE(hpwh.setCompressorAmbientTemperatureSchedule(scheduleConstant4)); + EXPECT_TRUE(hpwh.setFan(fan)); + EXPECT_TRUE(hpwh.setFanPlacement("DrawThrough")); + EXPECT_TRUE(hpwh.setOnCycleParasiticElectricLoad(40)); + EXPECT_TRUE(hpwh.setOffCycleParasiticElectricLoad(50)); + EXPECT_TRUE(hpwh.setParasiticHeatRejectionLocation("Zone")); + ScheduleConstant scheduleConstant5(m); + scheduleConstant5.setValue(0.5); + EXPECT_TRUE(hpwh.setInletAirMixerSchedule(scheduleConstant5)); + EXPECT_TRUE(hpwh.setTankElementControlLogic("Simultaneous")); + EXPECT_TRUE(hpwh.setControlSensor1HeightInStratifiedTank(60)); + EXPECT_TRUE(hpwh.setControlSensor1Weight(0.75)); + EXPECT_TRUE(hpwh.setControlSensor2HeightInStratifiedTank(70)); + + ThermalZone tz(m); + Space space(m); + space.setThermalZone(tz); + + EXPECT_TRUE(hpwh.addToThermalZone(tz)); + + PlantLoop plant_loop(m); + EXPECT_TRUE(plant_loop.addSupplyBranchForComponent(tank)); + + ForwardTranslator ft; + const Workspace w = ft.translateModel(m); + + EXPECT_EQ(1u, w.getObjectsByType(IddObjectType::WaterHeater_Stratified).size()); + const auto idfObjs = w.getObjectsByType(IddObjectType::WaterHeater_HeatPump_WrappedCondenser); + ASSERT_EQ(1u, idfObjs.size()); + const auto& idfObject = idfObjs.front(); + + EXPECT_EQ(hpwh.nameString(), idfObject.getString(WaterHeater_HeatPump_WrappedCondenserFields::Name).get()); + EXPECT_EQ(availabilitySchedule.nameString(), idfObject.getString(WaterHeater_HeatPump_WrappedCondenserFields::AvailabilityScheduleName).get()); + EXPECT_EQ(scheduleConstant1.nameString(), + idfObject.getString(WaterHeater_HeatPump_WrappedCondenserFields::CompressorSetpointTemperatureScheduleName).get()); + EXPECT_EQ(1, idfObject.getDouble(WaterHeater_HeatPump_WrappedCondenserFields::DeadBandTemperatureDifference).get()); + EXPECT_EQ(2, idfObject.getDouble(WaterHeater_HeatPump_WrappedCondenserFields::CondenserBottomLocation).get()); + EXPECT_EQ(3, idfObject.getDouble(WaterHeater_HeatPump_WrappedCondenserFields::CondenserTopLocation).get()); + EXPECT_EQ(4, idfObject.getDouble(WaterHeater_HeatPump_WrappedCondenserFields::EvaporatorAirFlowRate).get()); + EXPECT_EQ("ZoneAirOnly", idfObject.getString(WaterHeater_HeatPump_WrappedCondenserFields::InletAirConfiguration).get()); + ASSERT_TRUE(hpwh.inletNode()); + EXPECT_EQ(hpwh.inletNode()->nameString(), idfObject.getString(WaterHeater_HeatPump_WrappedCondenserFields::AirInletNodeName).get()); + ASSERT_TRUE(hpwh.outletNode()); + EXPECT_EQ(hpwh.outletNode()->nameString(), idfObject.getString(WaterHeater_HeatPump_WrappedCondenserFields::AirOutletNodeName).get()); + EXPECT_TRUE(idfObject.isEmpty(WaterHeater_HeatPump_WrappedCondenserFields::OutdoorAirNodeName)); + EXPECT_TRUE(idfObject.isEmpty(WaterHeater_HeatPump_WrappedCondenserFields::ExhaustAirNodeName)); + EXPECT_EQ(scheduleConstant2.nameString(), idfObject.getString(WaterHeater_HeatPump_WrappedCondenserFields::InletAirTemperatureScheduleName).get()); + EXPECT_EQ(scheduleConstant3.nameString(), idfObject.getString(WaterHeater_HeatPump_WrappedCondenserFields::InletAirHumidityScheduleName).get()); + EXPECT_EQ(tz.nameString(), idfObject.getString(WaterHeater_HeatPump_WrappedCondenserFields::InletAirZoneName).get()); + EXPECT_EQ("WaterHeater:Stratified", idfObject.getString(WaterHeater_HeatPump_WrappedCondenserFields::TankObjectType).get()); + EXPECT_EQ(tank.nameString(), idfObject.getString(WaterHeater_HeatPump_WrappedCondenserFields::TankName).get()); + ASSERT_TRUE(tank.supplyInletModelObject()); + EXPECT_EQ(tank.supplyInletModelObject()->nameString(), + idfObject.getString(WaterHeater_HeatPump_WrappedCondenserFields::TankUseSideInletNodeName).get()); + ASSERT_TRUE(tank.supplyOutletModelObject()); + EXPECT_EQ(tank.supplyOutletModelObject()->nameString(), + idfObject.getString(WaterHeater_HeatPump_WrappedCondenserFields::TankUseSideOutletNodeName).get()); + EXPECT_EQ("Coil:WaterHeating:AirToWaterHeatPump:Wrapped", idfObject.getString(WaterHeater_HeatPump_WrappedCondenserFields::DXCoilObjectType).get()); + EXPECT_EQ(coil.nameString(), idfObject.getString(WaterHeater_HeatPump_WrappedCondenserFields::DXCoilName).get()); + EXPECT_EQ(15, idfObject.getDouble(WaterHeater_HeatPump_WrappedCondenserFields::MinimumInletAirTemperatureforCompressorOperation).get()); + EXPECT_EQ(30, idfObject.getDouble(WaterHeater_HeatPump_WrappedCondenserFields::MaximumInletAirTemperatureforCompressorOperation).get()); + EXPECT_EQ("Zone", idfObject.getString(WaterHeater_HeatPump_WrappedCondenserFields::CompressorLocation).get()); + EXPECT_TRUE(idfObject.isEmpty(WaterHeater_HeatPump_WrappedCondenserFields::CompressorAmbientTemperatureScheduleName)); + EXPECT_EQ("Fan:OnOff", idfObject.getString(WaterHeater_HeatPump_WrappedCondenserFields::FanObjectType).get()); + EXPECT_EQ(fan.nameString(), idfObject.getString(WaterHeater_HeatPump_WrappedCondenserFields::FanName).get()); + EXPECT_EQ("DrawThrough", idfObject.getString(WaterHeater_HeatPump_WrappedCondenserFields::FanPlacement).get()); + EXPECT_EQ(40, idfObject.getDouble(WaterHeater_HeatPump_WrappedCondenserFields::OnCycleParasiticElectricLoad).get()); + EXPECT_EQ(50, idfObject.getDouble(WaterHeater_HeatPump_WrappedCondenserFields::OffCycleParasiticElectricLoad).get()); + EXPECT_EQ("Zone", idfObject.getString(WaterHeater_HeatPump_WrappedCondenserFields::ParasiticHeatRejectionLocation).get()); + EXPECT_TRUE(idfObject.isEmpty(WaterHeater_HeatPump_WrappedCondenserFields::InletAirMixerNodeName)); + EXPECT_TRUE(idfObject.isEmpty(WaterHeater_HeatPump_WrappedCondenserFields::OutletAirSplitterNodeName)); + EXPECT_EQ(scheduleConstant5.nameString(), idfObject.getString(WaterHeater_HeatPump_WrappedCondenserFields::InletAirMixerScheduleName).get()); + EXPECT_EQ("Simultaneous", idfObject.getString(WaterHeater_HeatPump_WrappedCondenserFields::TankElementControlLogic).get()); + EXPECT_EQ(60, idfObject.getDouble(WaterHeater_HeatPump_WrappedCondenserFields::ControlSensor1HeightInStratifiedTank).get()); + EXPECT_EQ(0.75, idfObject.getDouble(WaterHeater_HeatPump_WrappedCondenserFields::ControlSensor1Weight).get()); + EXPECT_EQ(70, idfObject.getDouble(WaterHeater_HeatPump_WrappedCondenserFields::ControlSensor2HeightInStratifiedTank).get()); +} + +TEST_F(EnergyPlusFixture, ForwardTranslator_WaterHeaterHeatPumpWrappedCondenser_Schedule) { + Model m; + + WaterHeaterStratified tank(m); + CoilWaterHeatingAirToWaterHeatPumpWrapped coil(m); + FanOnOff fan(m); + + WaterHeaterHeatPumpWrappedCondenser hpwh(m); + + hpwh.setName("My WaterHeaterHeatPumpWrappedCondenser"); + Schedule availabilitySchedule = m.alwaysOnDiscreteSchedule(); + EXPECT_TRUE(hpwh.setAvailabilitySchedule(availabilitySchedule)); + ScheduleConstant scheduleConstant1(m); + scheduleConstant1.setValue(0.1); + EXPECT_TRUE(hpwh.setCompressorSetpointTemperatureSchedule(scheduleConstant1)); + EXPECT_TRUE(hpwh.setDeadBandTemperatureDifference(1)); + EXPECT_TRUE(hpwh.setCondenserBottomLocation(2)); + EXPECT_TRUE(hpwh.setCondenserTopLocation(3)); + EXPECT_TRUE(hpwh.setEvaporatorAirFlowRate(4)); + EXPECT_TRUE(hpwh.setInletAirConfiguration("Schedule")); + ScheduleConstant scheduleConstant2(m); + scheduleConstant2.setValue(0.2); + EXPECT_TRUE(hpwh.setInletAirTemperatureSchedule(scheduleConstant2)); + ScheduleConstant scheduleConstant3(m); + scheduleConstant3.setValue(0.3); + EXPECT_TRUE(hpwh.setInletAirHumiditySchedule(scheduleConstant3)); + EXPECT_TRUE(hpwh.setTank(tank)); + EXPECT_TRUE(hpwh.setDXCoil(coil)); + EXPECT_TRUE(hpwh.setMinimumInletAirTemperatureforCompressorOperation(15)); + EXPECT_TRUE(hpwh.setMaximumInletAirTemperatureforCompressorOperation(30)); + EXPECT_TRUE(hpwh.setCompressorLocation("Schedule")); + ScheduleConstant scheduleConstant4(m); + scheduleConstant4.setValue(0.4); + EXPECT_TRUE(hpwh.setCompressorAmbientTemperatureSchedule(scheduleConstant4)); + EXPECT_TRUE(hpwh.setFan(fan)); + EXPECT_TRUE(hpwh.setFanPlacement("DrawThrough")); + EXPECT_TRUE(hpwh.setOnCycleParasiticElectricLoad(40)); + EXPECT_TRUE(hpwh.setOffCycleParasiticElectricLoad(50)); + EXPECT_TRUE(hpwh.setParasiticHeatRejectionLocation("Zone")); + ScheduleConstant scheduleConstant5(m); + scheduleConstant5.setValue(0.5); + EXPECT_TRUE(hpwh.setInletAirMixerSchedule(scheduleConstant5)); + EXPECT_TRUE(hpwh.setTankElementControlLogic("Simultaneous")); + EXPECT_TRUE(hpwh.setControlSensor1HeightInStratifiedTank(60)); + EXPECT_TRUE(hpwh.setControlSensor1Weight(0.75)); + EXPECT_TRUE(hpwh.setControlSensor2HeightInStratifiedTank(70)); + + PlantLoop plant_loop(m); + EXPECT_TRUE(plant_loop.addSupplyBranchForComponent(tank)); + + ForwardTranslator ft; + const Workspace w = ft.translateModel(m); + + EXPECT_EQ(1u, w.getObjectsByType(IddObjectType::WaterHeater_Stratified).size()); + const auto idfObjs = w.getObjectsByType(IddObjectType::WaterHeater_HeatPump_WrappedCondenser); + ASSERT_EQ(1u, idfObjs.size()); + const auto& idfObject = idfObjs.front(); + + EXPECT_EQ(hpwh.nameString(), idfObject.getString(WaterHeater_HeatPump_WrappedCondenserFields::Name).get()); + EXPECT_EQ(availabilitySchedule.nameString(), idfObject.getString(WaterHeater_HeatPump_WrappedCondenserFields::AvailabilityScheduleName).get()); + EXPECT_EQ(scheduleConstant1.nameString(), + idfObject.getString(WaterHeater_HeatPump_WrappedCondenserFields::CompressorSetpointTemperatureScheduleName).get()); + EXPECT_EQ(1, idfObject.getDouble(WaterHeater_HeatPump_WrappedCondenserFields::DeadBandTemperatureDifference).get()); + EXPECT_EQ(2, idfObject.getDouble(WaterHeater_HeatPump_WrappedCondenserFields::CondenserBottomLocation).get()); + EXPECT_EQ(3, idfObject.getDouble(WaterHeater_HeatPump_WrappedCondenserFields::CondenserTopLocation).get()); + EXPECT_EQ(4, idfObject.getDouble(WaterHeater_HeatPump_WrappedCondenserFields::EvaporatorAirFlowRate).get()); + EXPECT_EQ("Schedule", idfObject.getString(WaterHeater_HeatPump_WrappedCondenserFields::InletAirConfiguration).get()); + EXPECT_EQ(hpwh.nameString() + " Inlet", idfObject.getString(WaterHeater_HeatPump_WrappedCondenserFields::AirInletNodeName).get()); + EXPECT_EQ(hpwh.nameString() + " Outlet", idfObject.getString(WaterHeater_HeatPump_WrappedCondenserFields::AirOutletNodeName).get()); + EXPECT_TRUE(idfObject.isEmpty(WaterHeater_HeatPump_WrappedCondenserFields::OutdoorAirNodeName)); + EXPECT_TRUE(idfObject.isEmpty(WaterHeater_HeatPump_WrappedCondenserFields::ExhaustAirNodeName)); + EXPECT_EQ(scheduleConstant2.nameString(), idfObject.getString(WaterHeater_HeatPump_WrappedCondenserFields::InletAirTemperatureScheduleName).get()); + EXPECT_EQ(scheduleConstant3.nameString(), idfObject.getString(WaterHeater_HeatPump_WrappedCondenserFields::InletAirHumidityScheduleName).get()); + EXPECT_TRUE(idfObject.isEmpty(WaterHeater_HeatPump_WrappedCondenserFields::InletAirZoneName)); + EXPECT_EQ("WaterHeater:Stratified", idfObject.getString(WaterHeater_HeatPump_WrappedCondenserFields::TankObjectType).get()); + EXPECT_EQ(tank.nameString(), idfObject.getString(WaterHeater_HeatPump_WrappedCondenserFields::TankName).get()); + ASSERT_TRUE(tank.supplyInletModelObject()); + EXPECT_EQ(tank.supplyInletModelObject()->nameString(), + idfObject.getString(WaterHeater_HeatPump_WrappedCondenserFields::TankUseSideInletNodeName).get()); + ASSERT_TRUE(tank.supplyOutletModelObject()); + EXPECT_EQ(tank.supplyOutletModelObject()->nameString(), + idfObject.getString(WaterHeater_HeatPump_WrappedCondenserFields::TankUseSideOutletNodeName).get()); + EXPECT_EQ("Coil:WaterHeating:AirToWaterHeatPump:Wrapped", idfObject.getString(WaterHeater_HeatPump_WrappedCondenserFields::DXCoilObjectType).get()); + EXPECT_EQ(coil.nameString(), idfObject.getString(WaterHeater_HeatPump_WrappedCondenserFields::DXCoilName).get()); + EXPECT_EQ(15, idfObject.getDouble(WaterHeater_HeatPump_WrappedCondenserFields::MinimumInletAirTemperatureforCompressorOperation).get()); + EXPECT_EQ(30, idfObject.getDouble(WaterHeater_HeatPump_WrappedCondenserFields::MaximumInletAirTemperatureforCompressorOperation).get()); + EXPECT_EQ("Schedule", idfObject.getString(WaterHeater_HeatPump_WrappedCondenserFields::CompressorLocation).get()); + EXPECT_EQ(scheduleConstant4.nameString(), + idfObject.getString(WaterHeater_HeatPump_WrappedCondenserFields::CompressorAmbientTemperatureScheduleName).get()); + EXPECT_EQ("Fan:OnOff", idfObject.getString(WaterHeater_HeatPump_WrappedCondenserFields::FanObjectType).get()); + EXPECT_EQ(fan.nameString(), idfObject.getString(WaterHeater_HeatPump_WrappedCondenserFields::FanName).get()); + EXPECT_EQ("DrawThrough", idfObject.getString(WaterHeater_HeatPump_WrappedCondenserFields::FanPlacement).get()); + EXPECT_EQ(40, idfObject.getDouble(WaterHeater_HeatPump_WrappedCondenserFields::OnCycleParasiticElectricLoad).get()); + EXPECT_EQ(50, idfObject.getDouble(WaterHeater_HeatPump_WrappedCondenserFields::OffCycleParasiticElectricLoad).get()); + EXPECT_EQ("Zone", idfObject.getString(WaterHeater_HeatPump_WrappedCondenserFields::ParasiticHeatRejectionLocation).get()); + EXPECT_TRUE(idfObject.isEmpty(WaterHeater_HeatPump_WrappedCondenserFields::InletAirMixerNodeName)); + EXPECT_TRUE(idfObject.isEmpty(WaterHeater_HeatPump_WrappedCondenserFields::OutletAirSplitterNodeName)); + EXPECT_EQ(scheduleConstant5.nameString(), idfObject.getString(WaterHeater_HeatPump_WrappedCondenserFields::InletAirMixerScheduleName).get()); + EXPECT_EQ("Simultaneous", idfObject.getString(WaterHeater_HeatPump_WrappedCondenserFields::TankElementControlLogic).get()); + EXPECT_EQ(60, idfObject.getDouble(WaterHeater_HeatPump_WrappedCondenserFields::ControlSensor1HeightInStratifiedTank).get()); + EXPECT_EQ(0.75, idfObject.getDouble(WaterHeater_HeatPump_WrappedCondenserFields::ControlSensor1Weight).get()); + EXPECT_EQ(70, idfObject.getDouble(WaterHeater_HeatPump_WrappedCondenserFields::ControlSensor2HeightInStratifiedTank).get()); +} diff --git a/src/model/WaterHeaterHeatPumpWrappedCondenser.cpp b/src/model/WaterHeaterHeatPumpWrappedCondenser.cpp index 8da4f2a26a7..f0653bca824 100644 --- a/src/model/WaterHeaterHeatPumpWrappedCondenser.cpp +++ b/src/model/WaterHeaterHeatPumpWrappedCondenser.cpp @@ -14,6 +14,7 @@ #include "HVACComponent_Impl.hpp" #include "FanOnOff.hpp" #include "FanOnOff_Impl.hpp" +#include "Node.hpp" // #include "FanSystemModel.hpp" #include "WaterToWaterComponent.hpp" #include "WaterToWaterComponent_Impl.hpp" @@ -144,6 +145,52 @@ namespace model { return value.get(); } + std::string WaterHeaterHeatPumpWrappedCondenser_Impl::airInletNodeName() const { + auto inletAirConfiguration = this->inletAirConfiguration(); + + std::string airInletNodeName; + // Depending on inletAirConfiguration, what this returns will be different + // * "ZoneAirOnly" and "ZoneAndOutdoorAir" need to get nodes from the thermal zone + // * "OutdoorAirOnly" and "Schedule", it just constructs a node name. + // This is helpful if you need to control this via EMS + if (istringEqual(inletAirConfiguration, "ZoneAirOnly") || istringEqual(inletAirConfiguration, "ZoneAndOutdoorAir")) { + if (auto thermalZone = this->thermalZone()) { + auto inletNode = this->inletNode(); + OS_ASSERT(inletNode); + airInletNodeName = inletNode->nameString(); + } + } else if (istringEqual(inletAirConfiguration, "OutdoorAirOnly")) { + // Empty + } else if (istringEqual(inletAirConfiguration, "Schedule")) { + airInletNodeName = this->nameString() + " Inlet"; + } + + return airInletNodeName; + } + + std::string WaterHeaterHeatPumpWrappedCondenser_Impl::airOutletNodeName() const { + auto inletAirConfiguration = this->inletAirConfiguration(); + + std::string airOutletNodeName; + // Depending on inletAirConfiguration, what this returns will be different + // * "ZoneAirOnly" and "ZoneAndOutdoorAir" need to get nodes from the thermal zone + // * "OutdoorAirOnly" and "Schedule", it just constructs a node name. + // This is helpful if you need to control this via EMS + if (istringEqual(inletAirConfiguration, "ZoneAirOnly") || istringEqual(inletAirConfiguration, "ZoneAndOutdoorAir")) { + if (auto thermalZone = this->thermalZone()) { + auto outletNode = this->outletNode(); + OS_ASSERT(outletNode); + airOutletNodeName = outletNode->nameString(); + } + } else if (istringEqual(inletAirConfiguration, "OutdoorAirOnly")) { + // Empty + } else if (istringEqual(inletAirConfiguration, "Schedule")) { + airOutletNodeName = this->nameString() + " Outlet"; + } + + return airOutletNodeName; + } + boost::optional WaterHeaterHeatPumpWrappedCondenser_Impl::inletAirTemperatureSchedule() const { return getObject().getModelObjectTarget(OS_WaterHeater_HeatPump_WrappedCondenserFields::InletAirTemperatureScheduleName); } @@ -706,6 +753,14 @@ namespace model { return getImpl()->inletAirConfiguration(); } + std::string WaterHeaterHeatPumpWrappedCondenser::airInletNodeName() const { + return getImpl()->airInletNodeName(); + } + + std::string WaterHeaterHeatPumpWrappedCondenser::airOutletNodeName() const { + return getImpl()->airOutletNodeName(); + } + boost::optional WaterHeaterHeatPumpWrappedCondenser::inletAirTemperatureSchedule() const { return getImpl()->inletAirTemperatureSchedule(); } diff --git a/src/model/WaterHeaterHeatPumpWrappedCondenser.hpp b/src/model/WaterHeaterHeatPumpWrappedCondenser.hpp index ff068b56f82..0689c5fbc86 100644 --- a/src/model/WaterHeaterHeatPumpWrappedCondenser.hpp +++ b/src/model/WaterHeaterHeatPumpWrappedCondenser.hpp @@ -184,6 +184,14 @@ namespace model { /** @name Other */ //@{ + /** Convenience methods to return the name of the inlet/outlet nodes + * Depending on inletAirConfiguration, what this returns will be different + * - "ZoneAirOnly" and "ZoneAndOutdoorAir" need to get nodes from the thermal zone + * - "OutdoorAirOnly" and "Schedule", it just constructs a node name. + * This is helpful if you need to control this via EMS */ + std::string airInletNodeName() const; + std::string airOutletNodeName() const; + //@} protected: /// @cond diff --git a/src/model/WaterHeaterHeatPumpWrappedCondenser_Impl.hpp b/src/model/WaterHeaterHeatPumpWrappedCondenser_Impl.hpp index c57e8d468fd..13042939997 100644 --- a/src/model/WaterHeaterHeatPumpWrappedCondenser_Impl.hpp +++ b/src/model/WaterHeaterHeatPumpWrappedCondenser_Impl.hpp @@ -186,6 +186,9 @@ namespace model { bool addToThermalZone(ThermalZone& thermalZone) override; std::vector remove() override; + std::string airInletNodeName() const; + std::string airOutletNodeName() const; + //@} protected: private: diff --git a/src/model/test/WaterHeaterHeatPumpWrappedCondenser_GTest.cpp b/src/model/test/WaterHeaterHeatPumpWrappedCondenser_GTest.cpp index de203012a45..a9b133da6a9 100644 --- a/src/model/test/WaterHeaterHeatPumpWrappedCondenser_GTest.cpp +++ b/src/model/test/WaterHeaterHeatPumpWrappedCondenser_GTest.cpp @@ -85,6 +85,25 @@ TEST_F(ModelFixture, WaterHeaterHeatPumpWrappedCondenser_GettersSetters) { EXPECT_FALSE(hpwh.setInletAirConfiguration("BADENUM")); EXPECT_EQ("OutdoorAirOnly", hpwh.inletAirConfiguration()); + // Air Inlet Node Name: Required String + EXPECT_EQ("", hpwh.airInletNodeName()); + EXPECT_TRUE(hpwh.setInletAirConfiguration("ZoneAirOnly")); + EXPECT_EQ("", hpwh.airInletNodeName()); + EXPECT_TRUE(hpwh.setInletAirConfiguration("ZoneAndOutdoorAir")); + EXPECT_EQ("", hpwh.airInletNodeName()); + EXPECT_TRUE(hpwh.setInletAirConfiguration("Schedule")); + EXPECT_EQ(hpwh.nameString() + " Inlet", hpwh.airInletNodeName()); + + // Air Outlet Node Name: Required String + EXPECT_TRUE(hpwh.setInletAirConfiguration("OutdoorAirOnly")); + EXPECT_EQ("", hpwh.airOutletNodeName()); + EXPECT_TRUE(hpwh.setInletAirConfiguration("ZoneAirOnly")); + EXPECT_EQ("", hpwh.airOutletNodeName()); + EXPECT_TRUE(hpwh.setInletAirConfiguration("ZoneAndOutdoorAir")); + EXPECT_EQ("", hpwh.airOutletNodeName()); + EXPECT_TRUE(hpwh.setInletAirConfiguration("Schedule")); + EXPECT_EQ(hpwh.nameString() + " Outlet", hpwh.airOutletNodeName()); + // Inlet Air Temperature Schedule: Optional Object but set in Ctor { ScheduleConstant obj(m);