diff --git a/resources/energyplus/ProposedEnergy+.idd b/resources/energyplus/ProposedEnergy+.idd index 718ac1ef2a..e6ebb889e0 100644 --- a/resources/energyplus/ProposedEnergy+.idd +++ b/resources/energyplus/ProposedEnergy+.idd @@ -24646,7 +24646,7 @@ ZoneHVAC:WaterToAirHeatPump, \note Enter the type of performance specification object used to describe the multispeed coil or fan. A22; \field Design Specification Multispeed Object Name \type object-list - \object-list UnitarySystemPerformaceNames + \object-list UnitarySystemPerformanceNames \note The name of the performance specification object used to describe the multispeed coil or fan. ZoneHVAC:Dehumidifier:DX, @@ -25996,7 +25996,7 @@ ZoneHVAC:TerminalUnit:VariableRefrigerantFlow, \note Enter the type of performance specification object used to describe the multispeed coil or fan. A21; \field Design Specification Multispeed Object Name \type object-list - \object-list UnitarySystemPerformaceNames + \object-list UnitarySystemPerformanceNames \note The name of the performance specification object used to describe the multispeed coil or fan. \group Zone HVAC Radiative/Convective Units @@ -37684,7 +37684,7 @@ AirLoopHVAC:UnitarySystem, \note Enter the type of performance specification object used to describe the multispeed coil. A27; \field Design Specification Multispeed Object Name \type object-list - \object-list UnitarySystemPerformaceNames + \object-list UnitarySystemPerformanceNames \note The name of the performance specification object used to describe the multispeed coil. UnitarySystemPerformance:Multispeed, @@ -37694,7 +37694,7 @@ UnitarySystemPerformance:Multispeed, \extensible:2 - repeat last two fields, remembering to remove ; from "inner" fields. A1 , \field Name \required-field - \reference UnitarySystemPerformaceNames + \reference UnitarySystemPerformanceNames N1 , \field Number of Speeds for Heating \required-field \type integer diff --git a/resources/model/OpenStudio.idd b/resources/model/OpenStudio.idd index 150a093f1d..746890249a 100644 --- a/resources/model/OpenStudio.idd +++ b/resources/model/OpenStudio.idd @@ -29485,13 +29485,17 @@ OS:ZoneHVAC:TerminalUnit:VariableRefrigerantFlow, \units C \required-field \note Supplemental heater will not operate when outdoor temperature exceeds this value. - A15; \field Controlling Zone or Thermostat Location + A15, \field Controlling Zone or Thermostat Location \type object-list \object-list ThermalZoneNames \note Used only for AirloopHVAC equipment on a main branch and defines zone name where thermostat is located. \note Not required for zone equipment. Leave blank if terminal unit is used in AirLoopHVAC:OutdoorAirSystem:EquipmentList. \note Required when terminal unit is used on main AirloopHVAC branch and coils are not set point controlled. \note When terminal unit is used in air loop and is load controlled, this zone's thermostat will control operation. + A16; \field Design Specification Multispeed Object Name + \type object-list + \object-list UnitarySystemPerformaceNames + \note The name of the performance specification object used to describe the multispeed coil or fan. OS:ZoneHVAC:WaterToAirHeatPump, \min-fields 22 @@ -29628,10 +29632,14 @@ OS:ZoneHVAC:WaterToAirHeatPump, \note Constant results in 100% water flow regardless of compressor PLR \note Cycling results in water flow that matches compressor PLR \note ConstantOnDemand results in 100% water flow whenever the coil is on, but is 0% whenever the coil has no load - A26; \field Design Specification ZoneHVAC Sizing Object Name + A26, \field Design Specification ZoneHVAC Sizing Object Name \note Enter the name of a DesignSpecificationZoneHVACSizing object. \type object-list \object-list DesignSpecificationZoneHVACSizingName + A27; \field Design Specification Multispeed Object Name + \type object-list + \object-list UnitarySystemPerformaceNames + \note The name of the performance specification object used to describe the multispeed coil or fan. OS:ZoneHVAC:UnitHeater, \min-fields 10 diff --git a/src/energyplus/CMakeLists.txt b/src/energyplus/CMakeLists.txt index 9caeb1792d..dda4bfc2d3 100644 --- a/src/energyplus/CMakeLists.txt +++ b/src/energyplus/CMakeLists.txt @@ -822,6 +822,7 @@ set(${target_name}_test_src Test/ThermalStorageChilledWaterStratified_GTest.cpp Test/ThermalZone_GTest.cpp Test/ThermostatSetpointDualSetpoint_GTest.cpp + Test/UnitarySystemPerformanceMultispeed_GTest.cpp Test/WindowPropertyFrameAndDivider_GTest.cpp Test/WaterHeaterMixed_GTest.cpp Test/WaterHeaterSizing_GTest.cpp diff --git a/src/energyplus/ForwardTranslator/ForwardTranslateUnitarySystemPerformanceMultispeed.cpp b/src/energyplus/ForwardTranslator/ForwardTranslateUnitarySystemPerformanceMultispeed.cpp index 86da5f777f..ce28a924f0 100644 --- a/src/energyplus/ForwardTranslator/ForwardTranslateUnitarySystemPerformanceMultispeed.cpp +++ b/src/energyplus/ForwardTranslator/ForwardTranslateUnitarySystemPerformanceMultispeed.cpp @@ -9,6 +9,10 @@ #include "../../model/UnitarySystemPerformanceMultispeed_Impl.hpp" #include "../../model/AirLoopHVACUnitarySystem.hpp" #include "../../model/AirLoopHVACUnitarySystem_Impl.hpp" +#include "../../model/ZoneHVACTerminalUnitVariableRefrigerantFlow.hpp" +#include "../../model/ZoneHVACTerminalUnitVariableRefrigerantFlow_Impl.hpp" +#include "../../model/ZoneHVACWaterToAirHeatPump.hpp" +#include "../../model/ZoneHVACWaterToAirHeatPump_Impl.hpp" #include "../../model/CoilHeatingDXMultiSpeed.hpp" #include "../../model/CoilHeatingDXMultiSpeed_Impl.hpp" #include "../../model/CoilHeatingDXMultiSpeedStageData.hpp" @@ -19,10 +23,26 @@ #include "../../model/CoilHeatingGasMultiStage_Impl.hpp" #include "../../model/CoilHeatingGasMultiStageStageData.hpp" #include "../../model/CoilHeatingGasMultiStageStageData_Impl.hpp" +#include "../../model/CoilHeatingDXVariableSpeed.hpp" +#include "../../model/CoilHeatingDXVariableSpeed_Impl.hpp" +#include "../../model/CoilHeatingDXVariableSpeedSpeedData.hpp" +#include "../../model/CoilHeatingDXVariableSpeedSpeedData_Impl.hpp" +#include "../../model/CoilHeatingWaterToAirHeatPumpVariableSpeedEquationFit.hpp" +#include "../../model/CoilHeatingWaterToAirHeatPumpVariableSpeedEquationFit_Impl.hpp" +#include "../../model/CoilHeatingWaterToAirHeatPumpVariableSpeedEquationFitSpeedData.hpp" +#include "../../model/CoilHeatingWaterToAirHeatPumpVariableSpeedEquationFitSpeedData_Impl.hpp" #include "../../model/CoilCoolingDXMultiSpeed.hpp" #include "../../model/CoilCoolingDXMultiSpeed_Impl.hpp" #include "../../model/CoilCoolingDXMultiSpeedStageData.hpp" #include "../../model/CoilCoolingDXMultiSpeedStageData_Impl.hpp" +#include "../../model/CoilCoolingDXVariableSpeed.hpp" +#include "../../model/CoilCoolingDXVariableSpeed_Impl.hpp" +#include "../../model/CoilCoolingDXVariableSpeedSpeedData.hpp" +#include "../../model/CoilCoolingDXVariableSpeedSpeedData_Impl.hpp" +#include "../../model/CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit.hpp" +#include "../../model/CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl.hpp" +#include "../../model/CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFitSpeedData.hpp" +#include "../../model/CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFitSpeedData_Impl.hpp" #include #include "../../utilities/idd/IddEnums.hpp" #include "../../utilities/idf/IdfExtensibleGroup.hpp" @@ -34,23 +54,46 @@ namespace openstudio { namespace energyplus { boost::optional ForwardTranslator::translateUnitarySystemPerformanceMultispeed(UnitarySystemPerformanceMultispeed& modelObject) { - boost::optional s; - boost::optional d; // Name IdfObject sysPerf = createRegisterAndNameIdfObject(openstudio::IddObjectType::UnitarySystemPerformance_Multispeed, modelObject); - // Find the associated AirLoopHVACUnitarySystem + boost::optional heatingCoil; + boost::optional coolingCoil; + + // Find the associated AirLoopHVACUnitarySystem, ZoneHVACTerminalUnitVariableRefrigerantFlow, or ZoneHVACWaterToAirHeatPump std::vector unitarySystems = modelObject.getModelObjectSources(); - if (unitarySystems.size() != 1) { - LOG(Error, "OS:UnitarySystemPerformance:Multispeed should be referenced by one and only one OS:AirLoopHVAC:UnitarySystem, " - << modelObject.nameString() << " is referenced by " << unitarySystems.size() << ".") + std::vector tuVRFs = + modelObject.getModelObjectSources(); + std::vector hps = modelObject.getModelObjectSources(); + + if (((unitarySystems.size() + tuVRFs.size() + hps.size()) != 1)) { + LOG(Error, "OS:UnitarySystemPerformance:Multispeed should be referenced by one and only one OS:AirLoopHVAC:UnitarySystem or " + "OS:ZoneHVAC:TerminalUnit:VariableRefrigerantFlow or OS:ZoneHVAC:WaterToAirHeatPump, " + << modelObject.nameString() << " is referenced by " << unitarySystems.size() << " OS:AirLoopHVAC:UnitarySystem, " << tuVRFs.size() + << " OS:ZoneHVAC:TerminalUnit:VariableRefrigerantFlow, " << hps.size() << " OS:ZoneHVAC:WaterToAirHeatPump.") return boost::none; } - AirLoopHVACUnitarySystem& unitarySystem = unitarySystems[0]; + + if (unitarySystems.size() == 1) { + AirLoopHVACUnitarySystem& unitarySystem = unitarySystems[0]; + heatingCoil = unitarySystem.heatingCoil(); + coolingCoil = unitarySystem.coolingCoil(); + } + + if (tuVRFs.size() == 1) { + ZoneHVACTerminalUnitVariableRefrigerantFlow& tuVRF = tuVRFs[0]; + heatingCoil = tuVRF.heatingCoil(); + coolingCoil = tuVRF.coolingCoil(); + } + + if (hps.size() == 1) { + ZoneHVACWaterToAirHeatPump& hp = hps[0]; + heatingCoil = hp.heatingCoil().optionalCast(); + coolingCoil = hp.coolingCoil().optionalCast(); + } // Number of speeds for heating - boost::optional heatingCoil = unitarySystem.heatingCoil(); if (heatingCoil) { if (heatingCoil->iddObjectType() == openstudio::IddObjectType::OS_Coil_Heating_DX_MultiSpeed) { auto heatingCoilDXMultispeed = heatingCoil->cast(); @@ -58,7 +101,13 @@ namespace energyplus { } else if (heatingCoil->iddObjectType() == openstudio::IddObjectType::OS_Coil_Heating_Gas_MultiStage) { auto heatingCoilGasMultiStage = heatingCoil->cast(); sysPerf.setInt(UnitarySystemPerformance_MultispeedFields::NumberofSpeedsforHeating, heatingCoilGasMultiStage.stages().size()); - } else { + } else if (heatingCoil->iddObjectType() == openstudio::IddObjectType::OS_Coil_Heating_DX_VariableSpeed) { + auto heatingCoilDXVarspeed = heatingCoil->cast(); + sysPerf.setInt(UnitarySystemPerformance_MultispeedFields::NumberofSpeedsforHeating, heatingCoilDXVarspeed.speeds().size()); + } else if (heatingCoil->iddObjectType() == openstudio::IddObjectType::OS_Coil_Heating_WaterToAirHeatPump_VariableSpeedEquationFit) { + auto heatingCoilWaterToAirHeatingVar = heatingCoil->cast(); + sysPerf.setInt(UnitarySystemPerformance_MultispeedFields::NumberofSpeedsforHeating, heatingCoilWaterToAirHeatingVar.speeds().size()); + } else { // e.g., CoilHeatingWaterToAirHeatPumpEquationFit, CoilHeatingDXVariableRefrigerantFlow, CoilHeatingDXVariableRefrigerantFlowFluidTemperatureControl sysPerf.setInt(UnitarySystemPerformance_MultispeedFields::NumberofSpeedsforHeating, 1); } } else { @@ -66,12 +115,17 @@ namespace energyplus { } // Number of speeds for cooling - boost::optional coolingCoil = unitarySystem.coolingCoil(); if (coolingCoil) { if (coolingCoil->iddObjectType() == openstudio::IddObjectType::OS_Coil_Cooling_DX_MultiSpeed) { auto coolingCoilDXMultispeed = coolingCoil->cast(); sysPerf.setInt(UnitarySystemPerformance_MultispeedFields::NumberofSpeedsforCooling, coolingCoilDXMultispeed.stages().size()); - } else { + } else if (coolingCoil->iddObjectType() == openstudio::IddObjectType::OS_Coil_Cooling_DX_VariableSpeed) { + auto coolingCoilDXVarspeed = coolingCoil->cast(); + sysPerf.setInt(UnitarySystemPerformance_MultispeedFields::NumberofSpeedsforCooling, coolingCoilDXVarspeed.speeds().size()); + } else if (coolingCoil->iddObjectType() == openstudio::IddObjectType::OS_Coil_Cooling_WaterToAirHeatPump_VariableSpeedEquationFit) { + auto coolingCoilWaterToAirHeatingVar = coolingCoil->cast(); + sysPerf.setInt(UnitarySystemPerformance_MultispeedFields::NumberofSpeedsforCooling, coolingCoilWaterToAirHeatingVar.speeds().size()); + } else { // e.g., CoilCoolingWaterToAirHeatPumpEquationFit, CoilCoolingDXVariableRefrigerantFlow, CoilCoolingDXVariableRefrigerantFlowFluidTemperatureControl sysPerf.setInt(UnitarySystemPerformance_MultispeedFields::NumberofSpeedsforCooling, 1); } } else { diff --git a/src/energyplus/ForwardTranslator/ForwardTranslateZoneHVACTerminalUnitVariableRefrigerantFlow.cpp b/src/energyplus/ForwardTranslator/ForwardTranslateZoneHVACTerminalUnitVariableRefrigerantFlow.cpp index c02db7b817..e993ef8f2f 100644 --- a/src/energyplus/ForwardTranslator/ForwardTranslateZoneHVACTerminalUnitVariableRefrigerantFlow.cpp +++ b/src/energyplus/ForwardTranslator/ForwardTranslateZoneHVACTerminalUnitVariableRefrigerantFlow.cpp @@ -29,6 +29,8 @@ #include "../../model/CoilCoolingDXVariableRefrigerantFlow_Impl.hpp" #include "../../model/CoilHeatingDXVariableRefrigerantFlow.hpp" #include "../../model/CoilHeatingDXVariableRefrigerantFlow_Impl.hpp" +#include "../../model/UnitarySystemPerformanceMultispeed.hpp" +#include "../../model/UnitarySystemPerformanceMultispeed_Impl.hpp" #include "../../utilities/core/Logger.hpp" #include "../../utilities/core/Assert.hpp" #include "../../utilities/math/FloatCompare.hpp" @@ -432,6 +434,18 @@ namespace energyplus { } } + // Design Specification Multispeed Object Name + if (boost::optional designSpecificationMultispeedObject = modelObject.designSpecificationMultispeedObject()) { + boost::optional _unitarySystemPerformance = translateAndMapModelObject(designSpecificationMultispeedObject.get()); + + if (_unitarySystemPerformance && _unitarySystemPerformance->name()) { + idfObject.setString(ZoneHVAC_TerminalUnit_VariableRefrigerantFlowFields::DesignSpecificationMultispeedObjectType, + _unitarySystemPerformance->iddObject().name()); + idfObject.setString(ZoneHVAC_TerminalUnit_VariableRefrigerantFlowFields::DesignSpecificationMultispeedObjectName, + _unitarySystemPerformance->name().get()); + } + } + return idfObject; } diff --git a/src/energyplus/ForwardTranslator/ForwardTranslateZoneHVACWaterToAirHeatPump.cpp b/src/energyplus/ForwardTranslator/ForwardTranslateZoneHVACWaterToAirHeatPump.cpp index d7cd88f2ba..93e9f9e2c8 100644 --- a/src/energyplus/ForwardTranslator/ForwardTranslateZoneHVACWaterToAirHeatPump.cpp +++ b/src/energyplus/ForwardTranslator/ForwardTranslateZoneHVACWaterToAirHeatPump.cpp @@ -27,6 +27,8 @@ #include "../../model/CoilHeatingGas_Impl.hpp" #include "../../model/CoilHeatingWater.hpp" #include "../../model/CoilHeatingWater_Impl.hpp" +#include "../../model/UnitarySystemPerformanceMultispeed.hpp" +#include "../../model/UnitarySystemPerformanceMultispeed_Impl.hpp" #include #include #include @@ -355,6 +357,17 @@ namespace energyplus { // TODO: field 'Design Specification ZoneHVAC Sizing' isn't implemented since the object isn't wrapped in SDK + // Design Specification Multispeed Object Name + if (boost::optional designSpecificationMultispeedObject = modelObject.designSpecificationMultispeedObject()) { + boost::optional _unitarySystemPerformance = translateAndMapModelObject(designSpecificationMultispeedObject.get()); + + if (_unitarySystemPerformance && _unitarySystemPerformance->name()) { + idfObject.setString(ZoneHVAC_WaterToAirHeatPumpFields::DesignSpecificationMultispeedObjectType, + _unitarySystemPerformance->iddObject().name()); + idfObject.setString(ZoneHVAC_WaterToAirHeatPumpFields::DesignSpecificationMultispeedObjectName, _unitarySystemPerformance->name().get()); + } + } + return idfObject; } diff --git a/src/energyplus/Test/UnitarySystemPerformanceMultispeed_GTest.cpp b/src/energyplus/Test/UnitarySystemPerformanceMultispeed_GTest.cpp new file mode 100644 index 0000000000..f9f83b61d6 --- /dev/null +++ b/src/energyplus/Test/UnitarySystemPerformanceMultispeed_GTest.cpp @@ -0,0 +1,205 @@ +/*********************************************************************************************************************** +* 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/ThermalZone.hpp" +#include "../../model/Space.hpp" +#include "../../model/AirLoopHVAC.hpp" +#include "../../model/AirLoopHVACUnitarySystem.hpp" +#include "../../model/ZoneHVACWaterToAirHeatPump.hpp" +#include "../../model/ZoneHVACTerminalUnitVariableRefrigerantFlow.hpp" +#include "../../model/CoilCoolingDXVariableSpeed.hpp" +#include "../../model/CoilCoolingDXVariableSpeedSpeedData.hpp" +#include "../../model/CoilHeatingWaterToAirHeatPumpEquationFit.hpp" +#include "../../model/CoilCoolingWaterToAirHeatPumpEquationFit.hpp" +#include "../../model/CoilCoolingDXVariableRefrigerantFlow.hpp" +#include "../../model/CoilHeatingDXVariableRefrigerantFlow.hpp" +#include "../../model/FanOnOff.hpp" +#include "../../model/CoilHeatingElectric.hpp" +#include "../../model/ScheduleConstant.hpp" +#include "../../model/Node.hpp" +#include "../../model/UnitarySystemPerformanceMultispeed.hpp" + +#include +#include +#include +#include + +#include +#include "../../utilities/idf/IdfObject.hpp" +#include "../../utilities/idf/IdfObject_Impl.hpp" + +#include "../../utilities/idf/WorkspaceObject.hpp" +#include "../../utilities/idf/WorkspaceObject_Impl.hpp" + +using namespace openstudio::energyplus; +using namespace openstudio::model; +using namespace openstudio; + +TEST_F(EnergyPlusFixture, ForwardTranslator_UnitarySystemPerformanceMultispeed_AirLoopHVACUnitarySystem) { + Model m; + + CoilCoolingDXVariableSpeed coil(m); + CoilCoolingDXVariableSpeedSpeedData speed1(m); + EXPECT_TRUE(coil.addSpeed(speed1)); + CoilCoolingDXVariableSpeedSpeedData speed2(m); + EXPECT_TRUE(coil.addSpeed(speed2)); + + AirLoopHVACUnitarySystem unitary(m); + unitary.setCoolingCoil(coil); + + AirLoopHVAC airLoop(m); + Node supplyOutletNode = airLoop.supplyOutletNode(); + unitary.addToNode(supplyOutletNode); + + UnitarySystemPerformanceMultispeed perf(m); + perf.setName("US Perf Multispeed"); + EXPECT_TRUE(perf.addSupplyAirflowRatioField(1.0, 2.0)); + EXPECT_TRUE(unitary.setDesignSpecificationMultispeedObject(perf)); + + ForwardTranslator ft; + Workspace w = ft.translateModel(m); + + WorkspaceObjectVector idf_unitarys(w.getObjectsByType(IddObjectType::AirLoopHVAC_UnitarySystem)); + EXPECT_EQ(1, idf_unitarys.size()); + WorkspaceObject& idf_unitary = idf_unitarys.front(); + + EXPECT_EQ("UnitarySystemPerformance:Multispeed", + idf_unitary.getString(AirLoopHVAC_UnitarySystemFields::DesignSpecificationMultispeedObjectType).get()); + EXPECT_EQ("US Perf Multispeed", idf_unitary.getString(AirLoopHVAC_UnitarySystemFields::DesignSpecificationMultispeedObjectName).get()); + + WorkspaceObjectVector idf_perfs(w.getObjectsByType(IddObjectType::UnitarySystemPerformance_Multispeed)); + EXPECT_EQ(1, idf_perfs.size()); + WorkspaceObject& idf_perf = idf_perfs.front(); + + EXPECT_EQ(0, idf_perf.getInt(UnitarySystemPerformance_MultispeedFields::NumberofSpeedsforHeating).get()); + EXPECT_EQ(2, idf_perf.getInt(UnitarySystemPerformance_MultispeedFields::NumberofSpeedsforCooling).get()); + EXPECT_EQ("No", idf_perf.getString(UnitarySystemPerformance_MultispeedFields::SingleModeOperation).get()); + EXPECT_EQ(1.0, idf_perf.getDouble(UnitarySystemPerformance_MultispeedFields::NoLoadSupplyAirFlowRateRatio).get()); + + ASSERT_EQ(1u, idf_perf.numExtensibleGroups()); +} + +TEST_F(EnergyPlusFixture, ForwardTranslator_UnitarySystemPerformanceMultispeed_ZoneHVACWaterToAirHeatPump) { + Model m; + + Schedule sch = m.alwaysOnDiscreteSchedule(); + FanOnOff fan(m); + CoilHeatingWaterToAirHeatPumpEquationFit htg_coil(m); + CoilCoolingWaterToAirHeatPumpEquationFit clg_coil(m); + CoilHeatingElectric supp_htg_coil(m); + + ZoneHVACWaterToAirHeatPump hp(m, sch, fan, htg_coil, clg_coil, supp_htg_coil); + + UnitarySystemPerformanceMultispeed perf(m); + perf.setName("US Perf Multispeed"); + EXPECT_TRUE(perf.addSupplyAirflowRatioField(1.0, 2.0)); + EXPECT_TRUE(perf.addSupplyAirflowRatioField(3.0, 4.0)); + EXPECT_TRUE(hp.setDesignSpecificationMultispeedObject(perf)); + + ThermalZone z(m); + Space s(m); + s.setThermalZone(z); + EXPECT_TRUE(hp.addToThermalZone(z)); + + ForwardTranslator ft; + Workspace w = ft.translateModel(m); + + WorkspaceObjectVector idf_hps(w.getObjectsByType(IddObjectType::ZoneHVAC_WaterToAirHeatPump)); + EXPECT_EQ(1, idf_hps.size()); + WorkspaceObject& idf_hp = idf_hps.front(); + + EXPECT_EQ("UnitarySystemPerformance:Multispeed", + idf_hp.getString(ZoneHVAC_WaterToAirHeatPumpFields::DesignSpecificationMultispeedObjectType).get()); + EXPECT_EQ("US Perf Multispeed", idf_hp.getString(ZoneHVAC_WaterToAirHeatPumpFields::DesignSpecificationMultispeedObjectName).get()); + + WorkspaceObjectVector idf_perfs(w.getObjectsByType(IddObjectType::UnitarySystemPerformance_Multispeed)); + EXPECT_EQ(1, idf_perfs.size()); + WorkspaceObject& idf_perf = idf_perfs.front(); + + EXPECT_EQ(1, idf_perf.getInt(UnitarySystemPerformance_MultispeedFields::NumberofSpeedsforHeating).get()); + EXPECT_EQ(1, idf_perf.getInt(UnitarySystemPerformance_MultispeedFields::NumberofSpeedsforCooling).get()); + EXPECT_EQ("No", idf_perf.getString(UnitarySystemPerformance_MultispeedFields::SingleModeOperation).get()); + EXPECT_EQ(1.0, idf_perf.getDouble(UnitarySystemPerformance_MultispeedFields::NoLoadSupplyAirFlowRateRatio).get()); + + ASSERT_EQ(2u, idf_perf.numExtensibleGroups()); +} + +TEST_F(EnergyPlusFixture, ForwardTranslator_UnitarySystemPerformanceMultispeed_ZoneHVACTerminalUnitVariableRefrigerantFlow) { + Model m; + + FanOnOff fan(m); + CoilCoolingDXVariableRefrigerantFlow cc(m); + CoilHeatingDXVariableRefrigerantFlow hc(m); + + ZoneHVACTerminalUnitVariableRefrigerantFlow vrf(m, cc, hc, fan); + + UnitarySystemPerformanceMultispeed perf(m); + perf.setName("US Perf Multispeed"); + EXPECT_TRUE(perf.addSupplyAirflowRatioField(1.0, 2.0)); + EXPECT_TRUE(perf.addSupplyAirflowRatioField(3.0, 4.0)); + EXPECT_TRUE(perf.addSupplyAirflowRatioField(5.0, 6.0)); + EXPECT_TRUE(vrf.setDesignSpecificationMultispeedObject(perf)); + + ThermalZone z(m); + Space s(m); + s.setThermalZone(z); + EXPECT_TRUE(vrf.addToThermalZone(z)); + + ForwardTranslator ft; + Workspace w = ft.translateModel(m); + + WorkspaceObjectVector idf_vrfs(w.getObjectsByType(IddObjectType::ZoneHVAC_TerminalUnit_VariableRefrigerantFlow)); + EXPECT_EQ(1, idf_vrfs.size()); + WorkspaceObject& idf_vrf = idf_vrfs.front(); + + EXPECT_EQ("UnitarySystemPerformance:Multispeed", + idf_vrf.getString(ZoneHVAC_TerminalUnit_VariableRefrigerantFlowFields::DesignSpecificationMultispeedObjectType).get()); + EXPECT_EQ("US Perf Multispeed", + idf_vrf.getString(ZoneHVAC_TerminalUnit_VariableRefrigerantFlowFields::DesignSpecificationMultispeedObjectName).get()); + + WorkspaceObjectVector idf_perfs(w.getObjectsByType(IddObjectType::UnitarySystemPerformance_Multispeed)); + EXPECT_EQ(1, idf_perfs.size()); + WorkspaceObject& idf_perf = idf_perfs.front(); + + EXPECT_EQ(1, idf_perf.getInt(UnitarySystemPerformance_MultispeedFields::NumberofSpeedsforHeating).get()); + EXPECT_EQ(1, idf_perf.getInt(UnitarySystemPerformance_MultispeedFields::NumberofSpeedsforCooling).get()); + EXPECT_EQ("No", idf_perf.getString(UnitarySystemPerformance_MultispeedFields::SingleModeOperation).get()); + EXPECT_EQ(1.0, idf_perf.getDouble(UnitarySystemPerformance_MultispeedFields::NoLoadSupplyAirFlowRateRatio).get()); + + ASSERT_EQ(3u, idf_perf.numExtensibleGroups()); +} + +TEST_F(EnergyPlusFixture, ForwardTranslator_UnitarySystemPerformanceMultispeed_DoubleAssign) { + Model m; + + CoilCoolingDXVariableSpeed coil(m); + CoilCoolingDXVariableSpeedSpeedData speed(m); + EXPECT_TRUE(coil.addSpeed(speed)); + + AirLoopHVACUnitarySystem unitary(m); + unitary.setCoolingCoil(coil); + AirLoopHVACUnitarySystem unitary2(m); + unitary2.setCoolingCoil(coil); + + UnitarySystemPerformanceMultispeed perf(m); + EXPECT_TRUE(unitary.setDesignSpecificationMultispeedObject(perf)); + EXPECT_TRUE(unitary2.setDesignSpecificationMultispeedObject(perf)); + + AirLoopHVAC airLoop(m); + Node supplyOutletNode = airLoop.supplyOutletNode(); + unitary.addToNode(supplyOutletNode); + unitary2.addToNode(supplyOutletNode); + + ForwardTranslator ft; + Workspace w = ft.translateModel(m); + + EXPECT_EQ(1u, ft.errors().size()); +} diff --git a/src/model/ZoneHVACTerminalUnitVariableRefrigerantFlow.cpp b/src/model/ZoneHVACTerminalUnitVariableRefrigerantFlow.cpp index f06f67736e..1af6aa497f 100644 --- a/src/model/ZoneHVACTerminalUnitVariableRefrigerantFlow.cpp +++ b/src/model/ZoneHVACTerminalUnitVariableRefrigerantFlow.cpp @@ -38,6 +38,8 @@ #include "AirConditionerVariableRefrigerantFlowFluidTemperatureControl_Impl.hpp" #include "AirConditionerVariableRefrigerantFlowFluidTemperatureControlHR.hpp" #include "AirConditionerVariableRefrigerantFlowFluidTemperatureControlHR_Impl.hpp" +#include "UnitarySystemPerformanceMultispeed.hpp" +#include "UnitarySystemPerformanceMultispeed_Impl.hpp" #include @@ -581,6 +583,30 @@ namespace model { OS_ASSERT(result); } + boost::optional + ZoneHVACTerminalUnitVariableRefrigerantFlow_Impl::designSpecificationMultispeedObject() const { + return getObject().getModelObjectTarget( + OS_ZoneHVAC_TerminalUnit_VariableRefrigerantFlowFields::DesignSpecificationMultispeedObjectName); + } + + bool ZoneHVACTerminalUnitVariableRefrigerantFlow_Impl::setDesignSpecificationMultispeedObject( + const boost::optional& unitarySystemPerformace) { + bool result(false); + if (unitarySystemPerformace) { + result = setPointer(OS_ZoneHVAC_TerminalUnit_VariableRefrigerantFlowFields::DesignSpecificationMultispeedObjectName, + unitarySystemPerformace.get().handle()); + } else { + resetDesignSpecificationMultispeedObject(); + result = true; + } + return result; + } + + void ZoneHVACTerminalUnitVariableRefrigerantFlow_Impl::resetDesignSpecificationMultispeedObject() { + bool result = setString(OS_ZoneHVAC_TerminalUnit_VariableRefrigerantFlowFields::DesignSpecificationMultispeedObjectName, ""); + OS_ASSERT(result); + } + ModelObject ZoneHVACTerminalUnitVariableRefrigerantFlow_Impl::clone(Model model) const { ModelObject terminalClone = ZoneHVACComponent_Impl::clone(model); @@ -604,6 +630,11 @@ namespace model { terminalClone.getImpl()->setSupplementalHeatingCoil(coilClone); } + if (auto designSpec = designSpecificationMultispeedObject()) { + auto designSpecClone = designSpec->clone(model).cast(); + terminalClone.getImpl()->setDesignSpecificationMultispeedObject(designSpecClone); + } + // TODO Move this into base clase terminalClone.setString(OS_ZoneHVAC_TerminalUnit_VariableRefrigerantFlowFields::TerminalUnitAirInletNode, ""); terminalClone.setString(OS_ZoneHVAC_TerminalUnit_VariableRefrigerantFlowFields::TerminalUnitAirOutletNode, ""); @@ -630,6 +661,10 @@ namespace model { result.push_back(coil.get()); } + if (auto designSpec = designSpecificationMultispeedObject()) { + result.push_back(*designSpec); + } + return result; } @@ -1334,6 +1369,19 @@ namespace model { return getImpl()->setSupplyAirFanPlacement(supplyAirFanPlacement); } + boost::optional ZoneHVACTerminalUnitVariableRefrigerantFlow::designSpecificationMultispeedObject() const { + return getImpl()->designSpecificationMultispeedObject(); + } + + bool ZoneHVACTerminalUnitVariableRefrigerantFlow::setDesignSpecificationMultispeedObject( + const UnitarySystemPerformanceMultispeed& unitarySystemPerformace) { + return getImpl()->setDesignSpecificationMultispeedObject(unitarySystemPerformace); + } + + void ZoneHVACTerminalUnitVariableRefrigerantFlow::resetDesignSpecificationMultispeedObject() { + getImpl()->resetDesignSpecificationMultispeedObject(); + } + /// @cond ZoneHVACTerminalUnitVariableRefrigerantFlow::ZoneHVACTerminalUnitVariableRefrigerantFlow( std::shared_ptr impl) diff --git a/src/model/ZoneHVACTerminalUnitVariableRefrigerantFlow.hpp b/src/model/ZoneHVACTerminalUnitVariableRefrigerantFlow.hpp index c326d616d0..a3a976b9f2 100644 --- a/src/model/ZoneHVACTerminalUnitVariableRefrigerantFlow.hpp +++ b/src/model/ZoneHVACTerminalUnitVariableRefrigerantFlow.hpp @@ -20,6 +20,7 @@ namespace model { class CoilHeatingDXVariableRefrigerantFlowFluidTemperatureControl; class CoilCoolingDXVariableRefrigerantFlowFluidTemperatureControl; class ThermalZone; + class UnitarySystemPerformanceMultispeed; namespace detail { @@ -180,6 +181,10 @@ namespace model { bool setControllingZoneorThermostatLocation(const ThermalZone& thermalZone); void resetControllingZoneorThermostatLocation(); + boost::optional designSpecificationMultispeedObject() const; + bool setDesignSpecificationMultispeedObject(const UnitarySystemPerformanceMultispeed& unitarySystemPerformace); + void resetDesignSpecificationMultispeedObject(); + boost::optional autosizedSupplyAirFlowRateDuringCoolingOperation() const; boost::optional autosizedSupplyAirFlowRateWhenNoCoolingisNeeded() const; diff --git a/src/model/ZoneHVACTerminalUnitVariableRefrigerantFlow_Impl.hpp b/src/model/ZoneHVACTerminalUnitVariableRefrigerantFlow_Impl.hpp index 4536d69c86..93b44e1bd7 100644 --- a/src/model/ZoneHVACTerminalUnitVariableRefrigerantFlow_Impl.hpp +++ b/src/model/ZoneHVACTerminalUnitVariableRefrigerantFlow_Impl.hpp @@ -16,6 +16,7 @@ namespace model { class HVACComponent; class Schedule; class ThermalZone; + class UnitarySystemPerformanceMultispeed; namespace detail { @@ -141,6 +142,10 @@ namespace model { std::string supplyAirFanPlacement() const; bool setSupplyAirFanPlacement(const std::string& supplyAirFanPlacement); + boost::optional designSpecificationMultispeedObject() const; + bool setDesignSpecificationMultispeedObject(const boost::optional& unitarySystemPerformace); + void resetDesignSpecificationMultispeedObject(); + boost::optional autosizedSupplyAirFlowRateDuringCoolingOperation() const; boost::optional autosizedSupplyAirFlowRateWhenNoCoolingisNeeded() const; diff --git a/src/model/ZoneHVACWaterToAirHeatPump.cpp b/src/model/ZoneHVACWaterToAirHeatPump.cpp index 09776fbb19..587a00cb9b 100644 --- a/src/model/ZoneHVACWaterToAirHeatPump.cpp +++ b/src/model/ZoneHVACWaterToAirHeatPump.cpp @@ -27,6 +27,8 @@ #include "CoilHeatingWater_Impl.hpp" #include "Model.hpp" #include "Model_Impl.hpp" +#include "UnitarySystemPerformanceMultispeed.hpp" +#include "UnitarySystemPerformanceMultispeed_Impl.hpp" #include @@ -84,6 +86,10 @@ namespace model { wahpClone.setSupplementalHeatingCoil(supplementalHeatingCoilClone); + if (auto designSpec = designSpecificationMultispeedObject()) { + wahpClone.setDesignSpecificationMultispeedObject(designSpec->clone(model).cast()); + } + if (model == this->model()) { if (auto waterToAirComponent = t_coolingCoil.optionalCast()) { if (auto plant = waterToAirComponent->plantLoop()) { @@ -126,6 +132,9 @@ namespace model { plantLoop->removeDemandBranchWithComponent(t_supplementalHeatingCoil.get()); } } + if (auto designSpec = designSpecificationMultispeedObject()) { + designSpec->remove(); + } return ZoneHVACComponent_Impl::remove(); } @@ -175,6 +184,9 @@ namespace model { if (OptionalHVACComponent intermediate = optionalSupplementalHeatingCoil()) { result.push_back(*intermediate); } + if (auto designSpec = designSpecificationMultispeedObject()) { + result.push_back(*designSpec); + } return result; } @@ -351,6 +363,11 @@ namespace model { return getObject().getModelObjectTarget(OS_ZoneHVAC_WaterToAirHeatPumpFields::SupplyAirFanOperatingModeScheduleName); } + boost::optional ZoneHVACWaterToAirHeatPump_Impl::designSpecificationMultispeedObject() const { + return getObject().getModelObjectTarget( + OS_ZoneHVAC_WaterToAirHeatPumpFields::DesignSpecificationMultispeedObjectName); + } + bool ZoneHVACWaterToAirHeatPump_Impl::setAvailabilitySchedule(Schedule& schedule) { bool result = setSchedule(OS_ZoneHVAC_WaterToAirHeatPumpFields::AvailabilityScheduleName, "ZoneHVACWaterToAirHeatPump", "Availability", schedule); @@ -595,6 +612,23 @@ namespace model { OS_ASSERT(result); } + bool ZoneHVACWaterToAirHeatPump_Impl::setDesignSpecificationMultispeedObject( + const boost::optional& unitarySystemPerformace) { + bool result(false); + if (unitarySystemPerformace) { + result = setPointer(OS_ZoneHVAC_WaterToAirHeatPumpFields::DesignSpecificationMultispeedObjectName, unitarySystemPerformace.get().handle()); + } else { + resetDesignSpecificationMultispeedObject(); + result = true; + } + return result; + } + + void ZoneHVACWaterToAirHeatPump_Impl::resetDesignSpecificationMultispeedObject() { + bool result = setString(OS_ZoneHVAC_WaterToAirHeatPumpFields::DesignSpecificationMultispeedObjectName, ""); + OS_ASSERT(result); + } + boost::optional ZoneHVACWaterToAirHeatPump_Impl::optionalAvailabilitySchedule() const { return getObject().getModelObjectTarget(OS_ZoneHVAC_WaterToAirHeatPumpFields::AvailabilityScheduleName); } @@ -980,6 +1014,10 @@ namespace model { return getImpl()->supplyAirFanOperatingModeSchedule(); } + boost::optional ZoneHVACWaterToAirHeatPump::designSpecificationMultispeedObject() const { + return getImpl()->designSpecificationMultispeedObject(); + } + bool ZoneHVACWaterToAirHeatPump::setAvailabilitySchedule(Schedule& schedule) { return getImpl()->setAvailabilitySchedule(schedule); } @@ -1153,6 +1191,14 @@ namespace model { getImpl()->resetSupplyAirFanOperatingModeSchedule(); } + bool ZoneHVACWaterToAirHeatPump::setDesignSpecificationMultispeedObject(const UnitarySystemPerformanceMultispeed& unitarySystemPerformace) { + return getImpl()->setDesignSpecificationMultispeedObject(unitarySystemPerformace); + } + + void ZoneHVACWaterToAirHeatPump::resetDesignSpecificationMultispeedObject() { + getImpl()->resetDesignSpecificationMultispeedObject(); + } + /// @cond ZoneHVACWaterToAirHeatPump::ZoneHVACWaterToAirHeatPump(std::shared_ptr impl) : ZoneHVACComponent(std::move(impl)) {} diff --git a/src/model/ZoneHVACWaterToAirHeatPump.hpp b/src/model/ZoneHVACWaterToAirHeatPump.hpp index 33c18a9dfa..c6fefd5588 100644 --- a/src/model/ZoneHVACWaterToAirHeatPump.hpp +++ b/src/model/ZoneHVACWaterToAirHeatPump.hpp @@ -16,8 +16,8 @@ namespace openstudio { namespace model { class Schedule; - class HVACComponent; + class UnitarySystemPerformanceMultispeed; namespace detail { @@ -132,6 +132,8 @@ namespace model { // TODO: field 'Design Specification ZoneHVAC Sizing' isn't implemented since the object isn't wrapped in SDK + boost::optional designSpecificationMultispeedObject() const; + //@} /** @name Setters */ //@{ @@ -248,6 +250,10 @@ namespace model { void resetSupplyAirFanOperatingModeSchedule(); + bool setDesignSpecificationMultispeedObject(const UnitarySystemPerformanceMultispeed& unitarySystemPerformace); + + void resetDesignSpecificationMultispeedObject(); + //@} /** @name Other */ //@{ diff --git a/src/model/ZoneHVACWaterToAirHeatPump_Impl.hpp b/src/model/ZoneHVACWaterToAirHeatPump_Impl.hpp index 1ac835b2a4..779ffcbeb8 100644 --- a/src/model/ZoneHVACWaterToAirHeatPump_Impl.hpp +++ b/src/model/ZoneHVACWaterToAirHeatPump_Impl.hpp @@ -13,8 +13,8 @@ namespace openstudio { namespace model { class Schedule; - class HVACComponent; + class UnitarySystemPerformanceMultispeed; namespace detail { @@ -116,6 +116,8 @@ namespace model { boost::optional supplyAirFanOperatingModeSchedule() const; + boost::optional designSpecificationMultispeedObject() const; + boost::optional autosizedSupplyAirFlowRateDuringCoolingOperation() const; boost::optional autosizedSupplyAirFlowRateDuringHeatingOperation() const; @@ -226,6 +228,10 @@ namespace model { void resetSupplyAirFanOperatingModeSchedule(); + bool setDesignSpecificationMultispeedObject(const boost::optional& unitarySystemPerformace); + + void resetDesignSpecificationMultispeedObject(); + //@} /** @name Other */ //@{ diff --git a/src/model/test/UnitarySystemPerformanceMultispeed_GTest.cpp b/src/model/test/UnitarySystemPerformanceMultispeed_GTest.cpp index 01235da7f4..0697ba66c8 100644 --- a/src/model/test/UnitarySystemPerformanceMultispeed_GTest.cpp +++ b/src/model/test/UnitarySystemPerformanceMultispeed_GTest.cpp @@ -9,8 +9,25 @@ #include "../AirLoopHVACUnitarySystem.hpp" #include "../AirLoopHVACUnitarySystem_Impl.hpp" + +#include "../ZoneHVACWaterToAirHeatPump.hpp" +#include "../ZoneHVACWaterToAirHeatPump_Impl.hpp" +#include "../ZoneHVACTerminalUnitVariableRefrigerantFlow.hpp" +#include "../ZoneHVACTerminalUnitVariableRefrigerantFlow_Impl.hpp" #include "../UnitarySystemPerformanceMultispeed.hpp" #include "../UnitarySystemPerformanceMultispeed_Impl.hpp" +#include "../ScheduleConstant.hpp" +#include "../ScheduleConstant_Impl.hpp" +#include "../Schedule.hpp" +#include "../Schedule_Impl.hpp" +#include "../CoilCoolingWaterToAirHeatPumpEquationFit.hpp" +#include "../CoilCoolingWaterToAirHeatPumpEquationFit_Impl.hpp" +#include "../CoilHeatingWaterToAirHeatPumpEquationFit.hpp" +#include "../CoilHeatingWaterToAirHeatPumpEquationFit_Impl.hpp" +#include "../CoilHeatingElectric.hpp" +#include "../CoilHeatingElectric_Impl.hpp" +#include "../FanOnOff.hpp" +#include "../FanOnOff_Impl.hpp" using namespace openstudio; using namespace openstudio::model; @@ -98,12 +115,44 @@ TEST_F(ModelFixture, UnitarySystemPerformanceMultispeed_SupplyAirflowRatioField) TEST_F(ModelFixture, UnitarySystemPerformanceMultispeed_addToAirLoopHVACUnitarySystem) { Model m; - UnitarySystemPerformanceMultispeed perf = UnitarySystemPerformanceMultispeed(m); + UnitarySystemPerformanceMultispeed perf(m); AirLoopHVACUnitarySystem airloopsys = AirLoopHVACUnitarySystem(m); + ASSERT_FALSE(airloopsys.designSpecificationMultispeedObject()); EXPECT_TRUE(airloopsys.setDesignSpecificationMultispeedObject(perf)); ASSERT_TRUE(airloopsys.designSpecificationMultispeedObject()); EXPECT_EQ(airloopsys.designSpecificationMultispeedObject().get().handle(), perf.handle()); airloopsys.resetDesignSpecificationMultispeedObject(); ASSERT_FALSE(airloopsys.designSpecificationMultispeedObject()); } + +TEST_F(ModelFixture, UnitarySystemPerformanceMultispeed_addZoneHVACWaterToAirHeatPump) { + Model m; + UnitarySystemPerformanceMultispeed perf(m); + Schedule availabilitySched = m.alwaysOnDiscreteSchedule(); + FanOnOff supplyFan(m, availabilitySched); + CoilHeatingWaterToAirHeatPumpEquationFit coilHeatingWaterToAirHP(m); + CoilCoolingWaterToAirHeatPumpEquationFit coilCoolingWaterToAirHP(m); + CoilHeatingElectric supplementalHC(m, availabilitySched); + ZoneHVACWaterToAirHeatPump zonehvac(m, availabilitySched, supplyFan, coilHeatingWaterToAirHP, coilCoolingWaterToAirHP, supplementalHC); + + ASSERT_FALSE(zonehvac.designSpecificationMultispeedObject()); + EXPECT_TRUE(zonehvac.setDesignSpecificationMultispeedObject(perf)); + ASSERT_TRUE(zonehvac.designSpecificationMultispeedObject()); + EXPECT_EQ(zonehvac.designSpecificationMultispeedObject().get().handle(), perf.handle()); + zonehvac.resetDesignSpecificationMultispeedObject(); + ASSERT_FALSE(zonehvac.designSpecificationMultispeedObject()); +} + +TEST_F(ModelFixture, UnitarySystemPerformanceMultispeed_addZoneHVACTerminalUnitVariableRefrigerantFlow) { + Model m; + UnitarySystemPerformanceMultispeed perf(m); + ZoneHVACTerminalUnitVariableRefrigerantFlow zonehvac(m); + + ASSERT_FALSE(zonehvac.designSpecificationMultispeedObject()); + EXPECT_TRUE(zonehvac.setDesignSpecificationMultispeedObject(perf)); + ASSERT_TRUE(zonehvac.designSpecificationMultispeedObject()); + EXPECT_EQ(zonehvac.designSpecificationMultispeedObject().get().handle(), perf.handle()); + zonehvac.resetDesignSpecificationMultispeedObject(); + ASSERT_FALSE(zonehvac.designSpecificationMultispeedObject()); +}