From 0fbc85734a9fd02907f318964e488b767b0aeae1 Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Fri, 31 Jan 2025 15:03:43 -0700 Subject: [PATCH 01/58] Separate coil cooling water ft into without unitary and coil system. --- src/energyplus/ForwardTranslator.cpp | 6 +- src/energyplus/ForwardTranslator.hpp | 2 + .../ForwardTranslateCoilCoolingWater.cpp | 56 ++++++++++++++++++- 3 files changed, 62 insertions(+), 2 deletions(-) diff --git a/src/energyplus/ForwardTranslator.cpp b/src/energyplus/ForwardTranslator.cpp index ec486ebb357..545473b0b87 100644 --- a/src/energyplus/ForwardTranslator.cpp +++ b/src/energyplus/ForwardTranslator.cpp @@ -1072,7 +1072,11 @@ namespace energyplus { } case openstudio::IddObjectType::OS_Coil_Cooling_Water: { auto coil = modelObject.cast(); - retVal = translateCoilCoolingWater(coil); + if (isHVACComponentWithinUnitary(coil)) { + retVal = translateCoilCoolingWaterWithoutUnitary(coil); + } else { + retVal = translateCoilCoolingWater(coil); + } break; } case openstudio::IddObjectType::OS_Coil_Cooling_Water_Panel_Radiant: { diff --git a/src/energyplus/ForwardTranslator.hpp b/src/energyplus/ForwardTranslator.hpp index f007e984484..a02a1737a2c 100644 --- a/src/energyplus/ForwardTranslator.hpp +++ b/src/energyplus/ForwardTranslator.hpp @@ -800,6 +800,8 @@ namespace energyplus { boost::optional translateCoilCoolingWater(model::CoilCoolingWater& modelObject); + boost::optional translateCoilCoolingWaterWithoutUnitary(model::CoilCoolingWater& modelObject); + boost::optional translateCoilCoolingWaterToAirHeatPumpEquationFit(model::CoilCoolingWaterToAirHeatPumpEquationFit& modelObject); boost::optional diff --git a/src/energyplus/ForwardTranslator/ForwardTranslateCoilCoolingWater.cpp b/src/energyplus/ForwardTranslator/ForwardTranslateCoilCoolingWater.cpp index 8968638ad86..105797b6c54 100644 --- a/src/energyplus/ForwardTranslator/ForwardTranslateCoilCoolingWater.cpp +++ b/src/energyplus/ForwardTranslator/ForwardTranslateCoilCoolingWater.cpp @@ -13,6 +13,7 @@ #include "../../model/CoilCoolingWater_Impl.hpp" #include "../../utilities/core/Logger.hpp" #include "../../utilities/core/Assert.hpp" +#include #include #include "../../utilities/idd/IddEnums.hpp" #include @@ -26,7 +27,7 @@ namespace openstudio { namespace energyplus { - boost::optional ForwardTranslator::translateCoilCoolingWater(CoilCoolingWater& modelObject) { + boost::optional ForwardTranslator::translateCoilCoolingWaterWithoutUnitary(model::CoilCoolingWater& modelObject) { boost::optional s; boost::optional value; @@ -150,6 +151,59 @@ namespace energyplus { return boost::optional(idfObject); } + boost::optional ForwardTranslator::translateCoilCoolingWater(CoilCoolingWater& modelObject) { + boost::optional s; + boost::optional value; + + IdfObject coilSystemCoolingWaterIdf(IddObjectType::CoilSystem_Cooling_Water); + + m_idfObjects.push_back(coilSystemCoolingWaterIdf); + + boost::optional oIdfObject = translateCoilCoolingWaterWithoutUnitary(modelObject); + + if (!oIdfObject) { + return boost::none; + } + + IdfObject idfObject = oIdfObject.get(); + + OptionalString s; + + s = modelObject.name(); + if (s) { + coilSystemCoolingWaterIdf.setString(CoilSystem_Cooling_WaterFields::CoolingCoilObjectType, idfObject.iddObject().name()); + + coilSystemCoolingWaterIdf.setString(CoilSystem_Cooling_WaterFields::CoolingCoilName, *s); + + coilSystemCoolingWaterIdf.setName(*s + " CoilSystem"); + } + + Schedule sched = modelObject.availabilitySchedule(); + translateAndMapModelObject(sched); + + coilSystemCoolingWaterIdf.setString(CoilSystem_Cooling_WaterFields::AvailabilityScheduleName, sched.name().get()); + + OptionalModelObject omo = modelObject.inletModelObject(); + if (omo) { + translateAndMapModelObject(*omo); + s = omo->name(); + if (s) { + coilSystemCoolingWaterIdf.setString(CoilSystem_Cooling_WaterFields::AirInletNodeName, *s); + } + } + + omo = modelObject.outletModelObject(); + if (omo) { + translateAndMapModelObject(*omo); + s = omo->name(); + if (s) { + coilSystemCoolingWaterIdf.setString(CoilSystem_Cooling_WaterFields::AirOutletNodeName, *s); + } + } + + return coilSystemCoolingWaterIdf; + } + //((Name)(Name)) //((AvailabilityScheduleName)(Availability Schedule Name)) From 22abca8b217a34096d3bd9a073b4f6363eedf0a1 Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Fri, 31 Jan 2025 15:03:55 -0700 Subject: [PATCH 02/58] Stub ft test for coil cooling water. --- src/energyplus/CMakeLists.txt | 1 + .../Test/CoilCoolingWater_GTest.cpp | 59 +++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 src/energyplus/Test/CoilCoolingWater_GTest.cpp diff --git a/src/energyplus/CMakeLists.txt b/src/energyplus/CMakeLists.txt index e7d407a525e..76b2a72d163 100644 --- a/src/energyplus/CMakeLists.txt +++ b/src/energyplus/CMakeLists.txt @@ -704,6 +704,7 @@ set(${target_name}_test_src Test/CoilCoolingDXTwoSpeed_GTest.cpp Test/CoilCoolingDXTwoStageWithHumidityControlMode_GTest.cpp Test/CoilCoolingDXVariableSpeed_GTest.cpp + Test/CoilCoolingWater_GTest.cpp Test/CoilCoolingWaterToAirHeatPumpEquationFit_GTest.cpp Test/CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_GTest.cpp Test/CoilHeatingDXMultiSpeed_GTest.cpp diff --git a/src/energyplus/Test/CoilCoolingWater_GTest.cpp b/src/energyplus/Test/CoilCoolingWater_GTest.cpp new file mode 100644 index 00000000000..d92c1f20ddb --- /dev/null +++ b/src/energyplus/Test/CoilCoolingWater_GTest.cpp @@ -0,0 +1,59 @@ +/*********************************************************************************************************************** +* 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/CoilCoolingWater.hpp" +#include "../../model/CoilCoolingWater_Impl.hpp" + +#include "../../model/AirLoopHVAC.hpp" +#include "../../model/AirLoopHVACUnitarySystem.hpp" +#include "../../model/Node.hpp" + +#include "../../utilities/idf/IdfObject.hpp" +#include "../../utilities/idf/IdfObject_Impl.hpp" +#include "../../utilities/idf/WorkspaceObject.hpp" +#include "../../utilities/idf/WorkspaceObject_Impl.hpp" +#include "../../utilities/idf/IdfExtensibleGroup.hpp" +#include "../../utilities/idf/WorkspaceExtensibleGroup.hpp" + +#include +#include +#include +#include +#include +#include +#include + +using namespace openstudio::energyplus; +using namespace openstudio::model; +using namespace openstudio; + +TEST_F(EnergyPlusFixture, ForwardTranslator_CoilCoolingWater_Unitary) { + Model m; + CoilCoolingWater coil(m); + + ForwardTranslator ft; + Workspace w = ft.translateModel(m); + + // No CoilSystem:Cooling:DX wrapper needed, it's inside a unitary + EXPECT_EQ(0, w.getObjectsByType(IddObjectType::CoilSystem_Cooling_Water).size()); +} + +TEST_F(EnergyPlusFixture, ForwardTranslator_CoilCoolingWater_AirLoopHVAC) { + + ForwardTranslator ft; + + Model m; + CoilCoolingWater coil(m); + + Workspace w = ft.translateModel(m); + + EXPECT_EQ(1, w.getObjectsByType(IddObjectType::CoilSystem_Cooling_Water).size()); +} From 9c21359d9dbb42cec9d61cc5da52aad2b83ef4b0 Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Fri, 31 Jan 2025 15:19:03 -0700 Subject: [PATCH 03/58] Few typos in new ft method. --- .../ForwardTranslator/ForwardTranslateCoilCoolingWater.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/energyplus/ForwardTranslator/ForwardTranslateCoilCoolingWater.cpp b/src/energyplus/ForwardTranslator/ForwardTranslateCoilCoolingWater.cpp index 105797b6c54..22a7314c3ab 100644 --- a/src/energyplus/ForwardTranslator/ForwardTranslateCoilCoolingWater.cpp +++ b/src/energyplus/ForwardTranslator/ForwardTranslateCoilCoolingWater.cpp @@ -152,9 +152,6 @@ namespace energyplus { } boost::optional ForwardTranslator::translateCoilCoolingWater(CoilCoolingWater& modelObject) { - boost::optional s; - boost::optional value; - IdfObject coilSystemCoolingWaterIdf(IddObjectType::CoilSystem_Cooling_Water); m_idfObjects.push_back(coilSystemCoolingWaterIdf); @@ -183,7 +180,7 @@ namespace energyplus { coilSystemCoolingWaterIdf.setString(CoilSystem_Cooling_WaterFields::AvailabilityScheduleName, sched.name().get()); - OptionalModelObject omo = modelObject.inletModelObject(); + OptionalModelObject omo = modelObject.airInletModelObject(); if (omo) { translateAndMapModelObject(*omo); s = omo->name(); @@ -192,7 +189,7 @@ namespace energyplus { } } - omo = modelObject.outletModelObject(); + omo = modelObject.airOutletModelObject(); if (omo) { translateAndMapModelObject(*omo); s = omo->name(); From f29ca2e4f664d6880b3f4e580124e05cf577723e Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Mon, 3 Feb 2025 10:39:17 -0700 Subject: [PATCH 04/58] Expand new ft test. --- .../Test/CoilCoolingWater_GTest.cpp | 114 +++++++++++++++++- 1 file changed, 111 insertions(+), 3 deletions(-) diff --git a/src/energyplus/Test/CoilCoolingWater_GTest.cpp b/src/energyplus/Test/CoilCoolingWater_GTest.cpp index d92c1f20ddb..f1261e04daf 100644 --- a/src/energyplus/Test/CoilCoolingWater_GTest.cpp +++ b/src/energyplus/Test/CoilCoolingWater_GTest.cpp @@ -38,22 +38,130 @@ using namespace openstudio; TEST_F(EnergyPlusFixture, ForwardTranslator_CoilCoolingWater_Unitary) { Model m; CoilCoolingWater coil(m); + coil.setName("My CoilCoolingWater"); + + // put it inside a Unitary, and put Unitary on an AirLoopHVAC so it gets translated + AirLoopHVACUnitarySystem unitary(m); + unitary.setCoolingCoil(coil); + AirLoopHVAC airLoop(m); + Node supplyOutletNode = airLoop.supplyOutletNode(); + unitary.addToNode(supplyOutletNode); + ASSERT_TRUE(unitary.inletNode()); + EXPECT_TRUE(unitary.inletNode()->setName("Coil Air Inlet Node")); + ASSERT_TRUE(unitary.outletNode()); + EXPECT_TRUE(unitary.outletNode()->setName("Coil Air Outlet Node")); + + // They must be connected to a PlantLoop too + PlantLoop chw_p(m); + chw_p.addDemandBranchForComponent(coil); + coil.waterInletModelObject()->setName("Coil Water Inlet Node"); + coil.waterOutletModelObject()->setName("Coil Water Outlet Node"); ForwardTranslator ft; Workspace w = ft.translateModel(m); + WorkspaceObjectVector idfUnitarys(w.getObjectsByType(IddObjectType::AirLoopHVAC_UnitarySystem)); + ASSERT_EQ(1u, idfUnitarys.size()); + WorkspaceObject idfUnitary(idfUnitarys[0]); + + WorkspaceObjectVector idfCoils(w.getObjectsByType(IddObjectType::Coil_Cooling_Water)); + ASSERT_EQ(1u, idfCoils.size()); + WorkspaceObject idfCoil(idfCoils[0]); + // No CoilSystem:Cooling:DX wrapper needed, it's inside a unitary EXPECT_EQ(0, w.getObjectsByType(IddObjectType::CoilSystem_Cooling_Water).size()); -} -TEST_F(EnergyPlusFixture, ForwardTranslator_CoilCoolingWater_AirLoopHVAC) { + // Check that the Unitary ends up with the CoilCoolingWater + EXPECT_EQ("Coil:Cooling:Water", idfUnitary.getString(AirLoopHVAC_UnitarySystemFields::CoolingCoilObjectType).get()); + EXPECT_EQ(idfCoil.nameString(), idfUnitary.getString(AirLoopHVAC_UnitarySystemFields::CoolingCoilName).get()); - ForwardTranslator ft; + // Since the Unitary only has a Cooling Coil (no fan, not HC / Suppl HC), the nodes should match + EXPECT_EQ(idfUnitary.getString(AirLoopHVAC_UnitarySystemFields::AirInletNodeName).get(), + idfCoil.getString(Coil_Cooling_WaterFields::AirInletNodeName).get()); + + EXPECT_EQ(idfUnitary.getString(AirLoopHVAC_UnitarySystemFields::AirOutletNodeName).get(), + idfCoil.getString(Coil_Cooling_WaterFields::AirOutletNodeName).get()); + + EXPECT_EQ("My CoilCoolingWater", idfCoil.getString(Coil_Cooling_WaterFields::Name).get()); + EXPECT_EQ("", idfCoil.getString(Coil_Cooling_WaterFields::AvailabilityScheduleName).get()); + EXPECT_EQ(0.6, idfCoil.getDouble(Coil_Cooling_WaterFields::DesignWaterFlowRate).get()); + EXPECT_EQ(0.6, idfCoil.getDouble(Coil_Cooling_WaterFields::DesignAirFlowRate).get()); + EXPECT_EQ(0.6, idfCoil.getDouble(Coil_Cooling_WaterFields::DesignInletWaterTemperature).get()); + EXPECT_EQ(0.6, idfCoil.getDouble(Coil_Cooling_WaterFields::DesignInletAirTemperature).get()); + EXPECT_EQ(0.6, idfCoil.getDouble(Coil_Cooling_WaterFields::DesignInletAirHumidityRatio).get()); + EXPECT_EQ(0.6, idfCoil.getDouble(Coil_Cooling_WaterFields::DesignOutletAirHumidityRatio).get()); + EXPECT_EQ("Coil Water Inlet Node", idfCoil.getString(Coil_Cooling_WaterFields::WaterInletNodeName).get()); + EXPECT_EQ("Coil Water Outlet Node", idfCoil.getString(Coil_Cooling_WaterFields::WaterOutletNodeName).get()); + EXPECT_EQ("Coil Air Inlet Node", idfCoil.getString(Coil_Cooling_WaterFields::AirInletNodeName).get()); + EXPECT_EQ("Coil Air Outlet Node", idfCoil.getString(Coil_Cooling_WaterFields::AirOutletNodeName).get()); + EXPECT_EQ("", idfCoil.getString(Coil_Cooling_WaterFields::TypeofAnalysis).get()); + EXPECT_EQ("", idfCoil.getString(Coil_Cooling_WaterFields::HeatExchangerConfiguration).get()); + EXPECT_EQ("", idfCoil.getString(Coil_Cooling_WaterFields::CondensateCollectionWaterStorageTankName).get()); + EXPECT_EQ(0.9, idfCoil.getDouble(Coil_Cooling_WaterFields::DesignWaterTemperatureDifference).get()); +} +TEST_F(EnergyPlusFixture, ForwardTranslator_CoilCoolingWater_AirLoopHVAC) { Model m; CoilCoolingWater coil(m); + // put it on an AirLoopHVAC + AirLoopHVAC airLoop(m); + Node supplyOutletNode = airLoop.supplyOutletNode(); + EXPECT_TRUE(coil.addToNode(supplyOutletNode)); + + // They must be connected to a PlantLoop too + PlantLoop chw_p(m); + chw_p.addDemandBranchForComponent(coil); + + ForwardTranslator ft; Workspace w = ft.translateModel(m); + WorkspaceObjectVector idfCoils(w.getObjectsByType(IddObjectType::Coil_Cooling_Water)); + ASSERT_EQ(1u, idfCoils.size()); + WorkspaceObject idfCoil(idfCoils[0]); + + EXPECT_EQ(idfCoil.getString(Coil_Cooling_WaterFields::WaterInletNodeName).get(), coil.waterInletModelObject().get().nameString()); + EXPECT_EQ(idfCoil.getString(Coil_Cooling_WaterFields::WaterOutletNodeName).get(), coil.waterOutletModelObject().get().nameString()); + EXPECT_EQ(idfCoil.getString(Coil_Cooling_WaterFields::AirInletNodeName).get(), coil.airInletModelObject().get().nameString()); + EXPECT_EQ(idfCoil.getString(Coil_Cooling_WaterFields::AirOutletNodeName).get(), coil.airOutletModelObject().get().nameString()); + + EXPECT_EQ(1, w.getObjectsByType(IddObjectType::CoilSystem_Cooling_Water).size()); + + // Go from AirLoopHVAC to BranchList to Branch + WorkspaceObjectVector idf_airloops = w.getObjectsByType(IddObjectType::AirLoopHVAC); + ASSERT_EQ(1u, idf_airloops.size()); + + WorkspaceObject& idf_airLoopHVAC = idf_airloops.front(); + WorkspaceObject idf_brlist = idf_airLoopHVAC.getTarget(AirLoopHVACFields::BranchListName).get(); + + // Should have one branch only + ASSERT_EQ(1u, idf_brlist.extensibleGroups().size()); + auto w_eg = idf_brlist.extensibleGroups()[0].cast(); + WorkspaceObject idf_branch = w_eg.getTarget(BranchListExtensibleFields::BranchName).get(); + + // There should be only one equipment on the branch + ASSERT_EQ(1u, idf_branch.extensibleGroups().size()); + auto w_eg2 = idf_branch.extensibleGroups()[0].cast(); + + EXPECT_EQ(w_eg2.getString(BranchExtensibleFields::ComponentInletNodeName).get(), coil.inletModelObject().get().nameString()); + EXPECT_EQ(w_eg2.getString(BranchExtensibleFields::ComponentOutletNodeName).get(), coil.outletModelObject().get().nameString()); + + EXPECT_EQ("CoilSystem:Cooling:Water", w_eg2.getString(BranchExtensibleFields::ComponentObjectType).get()); + auto idf_coilSystem = w_eg2.getTarget(BranchExtensibleFields::ComponentName).get(); + // CoilSystem:Cooling:Water wrapper needed, it's not inside a unitary EXPECT_EQ(1, w.getObjectsByType(IddObjectType::CoilSystem_Cooling_Water).size()); + + EXPECT_EQ(coil.airInletModelObject().get().nameString(), idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::AirInletNodeName).get()); + EXPECT_EQ(coil.airOutletModelObject().get().nameString(), idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::AirOutletNodeName).get()); + EXPECT_EQ("Always On Discrete", idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::AvailabilityScheduleName).get()); + EXPECT_EQ("Coil:Cooling:Water", idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::CoolingCoilObjectType).get()); + EXPECT_EQ(coil.nameString(), idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::CoolingCoilName).get()); + EXPECT_EQ(idfCoil, idf_coilSystem.getTarget(CoilSystem_Cooling_WaterFields::CoolingCoilName).get()); + EXPECT_EQ("", idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::DehumidificationControlType).get()); + EXPECT_EQ("", idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::RunonSensibleLoad).get()); + EXPECT_EQ("", idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::RunonLatentLoad).get()); + EXPECT_EQ("", idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::MinimumAirToWaterTemperatureOffset).get()); + EXPECT_EQ("", idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::EconomizerLockout).get()); + EXPECT_EQ("", idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::MinimumWaterLoopTemperatureForHeatRecovery).get()); + EXPECT_EQ("", idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::CompanionCoilUsedForHeatRecovery).get()); } From beff05992673ff09e95533fac24a41cd5a8a051b Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Mon, 3 Feb 2025 10:55:48 -0700 Subject: [PATCH 05/58] Typo. --- src/energyplus/Test/CoilCoolingWater_GTest.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/energyplus/Test/CoilCoolingWater_GTest.cpp b/src/energyplus/Test/CoilCoolingWater_GTest.cpp index f1261e04daf..2114142dda9 100644 --- a/src/energyplus/Test/CoilCoolingWater_GTest.cpp +++ b/src/energyplus/Test/CoilCoolingWater_GTest.cpp @@ -143,8 +143,8 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilCoolingWater_AirLoopHVAC) { ASSERT_EQ(1u, idf_branch.extensibleGroups().size()); auto w_eg2 = idf_branch.extensibleGroups()[0].cast(); - EXPECT_EQ(w_eg2.getString(BranchExtensibleFields::ComponentInletNodeName).get(), coil.inletModelObject().get().nameString()); - EXPECT_EQ(w_eg2.getString(BranchExtensibleFields::ComponentOutletNodeName).get(), coil.outletModelObject().get().nameString()); + EXPECT_EQ(w_eg2.getString(BranchExtensibleFields::ComponentInletNodeName).get(), coil.airInletModelObject().get().nameString()); + EXPECT_EQ(w_eg2.getString(BranchExtensibleFields::ComponentOutletNodeName).get(), coil.airOutletModelObject().get().nameString()); EXPECT_EQ("CoilSystem:Cooling:Water", w_eg2.getString(BranchExtensibleFields::ComponentObjectType).get()); auto idf_coilSystem = w_eg2.getTarget(BranchExtensibleFields::ComponentName).get(); From 43e81656141a86786b7320d526c5d0ca267aef2b Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Mon, 3 Feb 2025 12:28:19 -0700 Subject: [PATCH 06/58] Fix ft test. --- .../Test/CoilCoolingWater_GTest.cpp | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/energyplus/Test/CoilCoolingWater_GTest.cpp b/src/energyplus/Test/CoilCoolingWater_GTest.cpp index 2114142dda9..aec1e5f6b51 100644 --- a/src/energyplus/Test/CoilCoolingWater_GTest.cpp +++ b/src/energyplus/Test/CoilCoolingWater_GTest.cpp @@ -83,21 +83,21 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilCoolingWater_Unitary) { idfCoil.getString(Coil_Cooling_WaterFields::AirOutletNodeName).get()); EXPECT_EQ("My CoilCoolingWater", idfCoil.getString(Coil_Cooling_WaterFields::Name).get()); - EXPECT_EQ("", idfCoil.getString(Coil_Cooling_WaterFields::AvailabilityScheduleName).get()); - EXPECT_EQ(0.6, idfCoil.getDouble(Coil_Cooling_WaterFields::DesignWaterFlowRate).get()); - EXPECT_EQ(0.6, idfCoil.getDouble(Coil_Cooling_WaterFields::DesignAirFlowRate).get()); - EXPECT_EQ(0.6, idfCoil.getDouble(Coil_Cooling_WaterFields::DesignInletWaterTemperature).get()); - EXPECT_EQ(0.6, idfCoil.getDouble(Coil_Cooling_WaterFields::DesignInletAirTemperature).get()); - EXPECT_EQ(0.6, idfCoil.getDouble(Coil_Cooling_WaterFields::DesignInletAirHumidityRatio).get()); - EXPECT_EQ(0.6, idfCoil.getDouble(Coil_Cooling_WaterFields::DesignOutletAirHumidityRatio).get()); + EXPECT_EQ("Always On Discrete", idfCoil.getString(Coil_Cooling_WaterFields::AvailabilityScheduleName).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignWaterFlowRate).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignAirFlowRate).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignInletWaterTemperature).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignInletAirTemperature).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignInletAirHumidityRatio).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignOutletAirHumidityRatio).get()); EXPECT_EQ("Coil Water Inlet Node", idfCoil.getString(Coil_Cooling_WaterFields::WaterInletNodeName).get()); EXPECT_EQ("Coil Water Outlet Node", idfCoil.getString(Coil_Cooling_WaterFields::WaterOutletNodeName).get()); EXPECT_EQ("Coil Air Inlet Node", idfCoil.getString(Coil_Cooling_WaterFields::AirInletNodeName).get()); EXPECT_EQ("Coil Air Outlet Node", idfCoil.getString(Coil_Cooling_WaterFields::AirOutletNodeName).get()); - EXPECT_EQ("", idfCoil.getString(Coil_Cooling_WaterFields::TypeofAnalysis).get()); - EXPECT_EQ("", idfCoil.getString(Coil_Cooling_WaterFields::HeatExchangerConfiguration).get()); - EXPECT_EQ("", idfCoil.getString(Coil_Cooling_WaterFields::CondensateCollectionWaterStorageTankName).get()); - EXPECT_EQ(0.9, idfCoil.getDouble(Coil_Cooling_WaterFields::DesignWaterTemperatureDifference).get()); + EXPECT_EQ("SimpleAnalysis", idfCoil.getString(Coil_Cooling_WaterFields::TypeofAnalysis).get()); + EXPECT_EQ("CrossFlow", idfCoil.getString(Coil_Cooling_WaterFields::HeatExchangerConfiguration).get()); + EXPECT_TRUE(idfCoil.isEmpty(Coil_Cooling_WaterFields::CondensateCollectionWaterStorageTankName)); + EXPECT_TRUE(idfCoil.isEmpty(Coil_Cooling_WaterFields::DesignWaterTemperatureDifference)); } TEST_F(EnergyPlusFixture, ForwardTranslator_CoilCoolingWater_AirLoopHVAC) { @@ -157,11 +157,11 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilCoolingWater_AirLoopHVAC) { EXPECT_EQ("Coil:Cooling:Water", idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::CoolingCoilObjectType).get()); EXPECT_EQ(coil.nameString(), idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::CoolingCoilName).get()); EXPECT_EQ(idfCoil, idf_coilSystem.getTarget(CoilSystem_Cooling_WaterFields::CoolingCoilName).get()); - EXPECT_EQ("", idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::DehumidificationControlType).get()); - EXPECT_EQ("", idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::RunonSensibleLoad).get()); - EXPECT_EQ("", idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::RunonLatentLoad).get()); - EXPECT_EQ("", idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::MinimumAirToWaterTemperatureOffset).get()); - EXPECT_EQ("", idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::EconomizerLockout).get()); - EXPECT_EQ("", idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::MinimumWaterLoopTemperatureForHeatRecovery).get()); - EXPECT_EQ("", idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::CompanionCoilUsedForHeatRecovery).get()); + EXPECT_TRUE(idf_coilSystem.isEmpty(CoilSystem_Cooling_WaterFields::DehumidificationControlType)); + EXPECT_TRUE(idf_coilSystem.isEmpty(CoilSystem_Cooling_WaterFields::RunonSensibleLoad)); + EXPECT_TRUE(idf_coilSystem.isEmpty(CoilSystem_Cooling_WaterFields::RunonLatentLoad)); + EXPECT_TRUE(idf_coilSystem.isEmpty(CoilSystem_Cooling_WaterFields::MinimumAirToWaterTemperatureOffset)); + EXPECT_TRUE(idf_coilSystem.isEmpty(CoilSystem_Cooling_WaterFields::EconomizerLockout)); + EXPECT_TRUE(idf_coilSystem.isEmpty(CoilSystem_Cooling_WaterFields::MinimumWaterLoopTemperatureForHeatRecovery)); + EXPECT_TRUE(idf_coilSystem.isEmpty(CoilSystem_Cooling_WaterFields::CompanionCoilUsedForHeatRecovery)); } From 68870dcda1bd9858a4a79328330c7701ad4b9454 Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Mon, 3 Feb 2025 12:53:22 -0700 Subject: [PATCH 07/58] Separate coilsystem cooling water hx assisted ft into without unitary and coil system. --- src/energyplus/CMakeLists.txt | 1 + src/energyplus/ForwardTranslator.cpp | 8 +- .../ForwardTranslateCoilCoolingWater.cpp | 3 - ...ystemCoolingWaterHeatExchangerAssisted.cpp | 52 +++++- ...oolingWaterHeatExchangerAssisted_GTest.cpp | 156 ++++++++++++++++++ 5 files changed, 214 insertions(+), 6 deletions(-) create mode 100644 src/energyplus/Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp diff --git a/src/energyplus/CMakeLists.txt b/src/energyplus/CMakeLists.txt index 76b2a72d163..13ad14151e3 100644 --- a/src/energyplus/CMakeLists.txt +++ b/src/energyplus/CMakeLists.txt @@ -715,6 +715,7 @@ set(${target_name}_test_src Test/CoilHeatingGasMultiStage_GTest.cpp Test/CoilHeatingWaterToAirHeatPumpEquationFit_GTest.cpp Test/CoilHeatingWaterToAirHeatPumpVariableSpeedEquationFit_GTest.cpp + Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest Test/CoilSystemIntegratedHeatPumpAirSource_GTest.cpp Test/CoilUserDefined_GTest.cpp Test/CoilWaterHeatingAirToWaterHeatPump_GTest.cpp diff --git a/src/energyplus/ForwardTranslator.cpp b/src/energyplus/ForwardTranslator.cpp index 545473b0b87..51fe38cd396 100644 --- a/src/energyplus/ForwardTranslator.cpp +++ b/src/energyplus/ForwardTranslator.cpp @@ -1212,8 +1212,12 @@ namespace energyplus { break; } case openstudio::IddObjectType::OS_CoilSystem_Cooling_Water_HeatExchangerAssisted: { - auto mo = modelObject.cast(); - retVal = translateCoilSystemCoolingWaterHeatExchangerAssisted(mo); + auto coil = modelObject.cast(); + if (isHVACComponentWithinUnitary(coil)) { + retVal = translateCoilSystemCoolingWaterHeatExchangerAssistedWithoutUnitary(coil); + } else { + retVal = translateCoilSystemCoolingWaterHeatExchangerAssisted(coil); + } break; } case openstudio::IddObjectType::OS_CoilSystem_Cooling_DX_HeatExchangerAssisted: { diff --git a/src/energyplus/ForwardTranslator/ForwardTranslateCoilCoolingWater.cpp b/src/energyplus/ForwardTranslator/ForwardTranslateCoilCoolingWater.cpp index 22a7314c3ab..744fd357b13 100644 --- a/src/energyplus/ForwardTranslator/ForwardTranslateCoilCoolingWater.cpp +++ b/src/energyplus/ForwardTranslator/ForwardTranslateCoilCoolingWater.cpp @@ -201,9 +201,6 @@ namespace energyplus { return coilSystemCoolingWaterIdf; } - //((Name)(Name)) - //((AvailabilityScheduleName)(Availability Schedule Name)) - } // namespace energyplus } // namespace openstudio diff --git a/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWaterHeatExchangerAssisted.cpp b/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWaterHeatExchangerAssisted.cpp index 3cd67ee19a2..32a7f3e0dea 100644 --- a/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWaterHeatExchangerAssisted.cpp +++ b/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWaterHeatExchangerAssisted.cpp @@ -42,7 +42,7 @@ namespace openstudio { namespace energyplus { boost::optional - ForwardTranslator::translateCoilSystemCoolingWaterHeatExchangerAssisted(CoilSystemCoolingWaterHeatExchangerAssisted& modelObject) { + ForwardTranslator::translateCoilSystemCoolingWaterHeatExchangerAssistedWithoutUnitary(CoilSystemCoolingWaterHeatExchangerAssisted& modelObject) { IdfObject idfObject = createRegisterAndNameIdfObject(openstudio::IddObjectType::CoilSystem_Cooling_Water_HeatExchangerAssisted, modelObject); @@ -157,5 +157,55 @@ namespace energyplus { return idfObject; } + boost::optional ForwardTranslator::translateCoilSystemCoolingWaterHeatExchangerAssisted(CoilCoolingWater& modelObject) { + IdfObject coilSystemCoolingWaterIdf(IddObjectType::CoilSystem_Cooling_Water); + + m_idfObjects.push_back(coilSystemCoolingWaterIdf); + + boost::optional oIdfObject = translateCoilSystemCoolingWaterHeatExchangerAssistedWithoutUnitary(modelObject); + + if (!oIdfObject) { + return boost::none; + } + + IdfObject idfObject = oIdfObject.get(); + + OptionalString s; + + s = modelObject.name(); + if (s) { + coilSystemCoolingWaterIdf.setString(CoilSystem_Cooling_WaterFields::CoolingCoilObjectType, idfObject.iddObject().name()); + + coilSystemCoolingWaterIdf.setString(CoilSystem_Cooling_WaterFields::CoolingCoilName, *s); + + coilSystemCoolingWaterIdf.setName(*s + " CoilSystem"); + } + + Schedule sched = modelObject.availabilitySchedule(); + translateAndMapModelObject(sched); + + coilSystemCoolingWaterIdf.setString(CoilSystem_Cooling_WaterFields::AvailabilityScheduleName, sched.name().get()); + + OptionalModelObject omo = modelObject.airInletModelObject(); + if (omo) { + translateAndMapModelObject(*omo); + s = omo->name(); + if (s) { + coilSystemCoolingWaterIdf.setString(CoilSystem_Cooling_WaterFields::AirInletNodeName, *s); + } + } + + omo = modelObject.airOutletModelObject(); + if (omo) { + translateAndMapModelObject(*omo); + s = omo->name(); + if (s) { + coilSystemCoolingWaterIdf.setString(CoilSystem_Cooling_WaterFields::AirOutletNodeName, *s); + } + } + + return coilSystemCoolingWaterIdf; + } + } // namespace energyplus } // namespace openstudio diff --git a/src/energyplus/Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp b/src/energyplus/Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp new file mode 100644 index 00000000000..645eefe875d --- /dev/null +++ b/src/energyplus/Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp @@ -0,0 +1,156 @@ +/*********************************************************************************************************************** +* 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/CoilSystemCoolingWaterHeatExchangerAssisted.hpp" +#include "../../model/CoilSystemCoolingWaterHeatExchangerAssisted_Impl.hpp" + +#include "../../model/AirLoopHVAC.hpp" +#include "../../model/AirLoopHVACUnitarySystem.hpp" +#include "../../model/Node.hpp" + +#include "../../utilities/idf/IdfObject.hpp" +#include "../../utilities/idf/IdfObject_Impl.hpp" +#include "../../utilities/idf/WorkspaceObject.hpp" +#include "../../utilities/idf/WorkspaceObject_Impl.hpp" +#include "../../utilities/idf/IdfExtensibleGroup.hpp" +#include "../../utilities/idf/WorkspaceExtensibleGroup.hpp" + +#include +#include +#include +#include +#include +#include +#include + +using namespace openstudio::energyplus; +using namespace openstudio::model; +using namespace openstudio; + +TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWaterHeatExchangerAssisted_Unitary) { + Model m; + CoilSystemCoolingWaterHeatExchangerAssisted coil(m); + coil.setName("My CoilSystemCoolingWaterHeatExchangerAssisted"); + + // put it inside a Unitary, and put Unitary on an AirLoopHVAC so it gets translated + AirLoopHVACUnitarySystem unitary(m); + unitary.setCoolingCoil(coil); + AirLoopHVAC airLoop(m); + Node supplyOutletNode = airLoop.supplyOutletNode(); + unitary.addToNode(supplyOutletNode); + ASSERT_TRUE(unitary.inletNode()); + EXPECT_TRUE(unitary.inletNode()->setName("Coil Air Inlet Node")); + ASSERT_TRUE(unitary.outletNode()); + EXPECT_TRUE(unitary.outletNode()->setName("Coil Air Outlet Node")); + + // They must be connected to a PlantLoop too + PlantLoop chw_p(m); + chw_p.addDemandBranchForComponent(coil); + coil.waterInletModelObject()->setName("Coil Water Inlet Node"); + coil.waterOutletModelObject()->setName("Coil Water Outlet Node"); + + ForwardTranslator ft; + Workspace w = ft.translateModel(m); + + WorkspaceObjectVector idfUnitarys(w.getObjectsByType(IddObjectType::AirLoopHVAC_UnitarySystem)); + ASSERT_EQ(1u, idfUnitarys.size()); + WorkspaceObject idfUnitary(idfUnitarys[0]); + + WorkspaceObjectVector idfCoils(w.getObjectsByType(IddObjectType::CoilSystem_Cooling_Water_HeatExchangerAssisted)); + ASSERT_EQ(1u, idfCoils.size()); + WorkspaceObject idfCoil(idfCoils[0]); + + // No CoilSystem:Cooling:DX wrapper needed, it's inside a unitary + EXPECT_EQ(0, w.getObjectsByType(IddObjectType::CoilSystem_Cooling_Water).size()); + + // Check that the Unitary ends up with the CoilSystemCoolingWaterHeatExchangerAssisted + EXPECT_EQ("CoilSystem:Cooling:Water:HeatExchangerAssisted", idfUnitary.getString(AirLoopHVAC_UnitarySystemFields::CoolingCoilObjectType).get()); + EXPECT_EQ(idfCoil.nameString(), idfUnitary.getString(AirLoopHVAC_UnitarySystemFields::CoolingCoilName).get()); + + // Since the Unitary only has a Cooling Coil (no fan, not HC / Suppl HC), the nodes should match + EXPECT_EQ(idfUnitary.getString(AirLoopHVAC_UnitarySystemFields::AirInletNodeName).get(), + idfCoil.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::AirInletNodeName).get()); + + EXPECT_EQ(idfUnitary.getString(AirLoopHVAC_UnitarySystemFields::AirOutletNodeName).get(), + idfCoil.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::AirOutletNodeName).get()); + + EXPECT_EQ("My CoilSystemCoolingWaterHeatExchangerAssisted", idfCoil.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::Name).get()); + EXPECT_EQ("HeatExchanger:AirToAir:SensibleAndLatent", idfCoil.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::HeatExchangerObjectType).get()); + EXPECT_EQ(coil.heatExchanger().nameString(), idfCoil.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::HeatExchangerName).get()); + EXPECT_EQ("Coil:Cooling:Water", idfCoil.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::CoolingCoilObjectType).get()); + EXPECT_EQ(coil.coolingCoil().nameString(), idfCoil.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::CoolingCoilName).get()); +} + +TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWaterHeatExchangerAssisted_AirLoopHVAC) { + Model m; + CoilSystemCoolingWaterHeatExchangerAssisted coil(m); + + // put it on an AirLoopHVAC + AirLoopHVAC airLoop(m); + Node supplyOutletNode = airLoop.supplyOutletNode(); + EXPECT_TRUE(coil.addToNode(supplyOutletNode)); + + // They must be connected to a PlantLoop too + PlantLoop chw_p(m); + chw_p.addDemandBranchForComponent(coil); + + ForwardTranslator ft; + Workspace w = ft.translateModel(m); + + WorkspaceObjectVector idfCoils(w.getObjectsByType(IddObjectType::Coil_Cooling_Water)); + ASSERT_EQ(1u, idfCoils.size()); + WorkspaceObject idfCoil(idfCoils[0]); + + EXPECT_EQ(idfCoil.getString(Coil_Cooling_WaterFields::WaterInletNodeName).get(), coil.waterInletModelObject().get().nameString()); + EXPECT_EQ(idfCoil.getString(Coil_Cooling_WaterFields::WaterOutletNodeName).get(), coil.waterOutletModelObject().get().nameString()); + EXPECT_EQ(idfCoil.getString(Coil_Cooling_WaterFields::AirInletNodeName).get(), coil.airInletModelObject().get().nameString()); + EXPECT_EQ(idfCoil.getString(Coil_Cooling_WaterFields::AirOutletNodeName).get(), coil.airOutletModelObject().get().nameString()); + + EXPECT_EQ(1, w.getObjectsByType(IddObjectType::CoilSystem_Cooling_Water).size()); + + // Go from AirLoopHVAC to BranchList to Branch + WorkspaceObjectVector idf_airloops = w.getObjectsByType(IddObjectType::AirLoopHVAC); + ASSERT_EQ(1u, idf_airloops.size()); + + WorkspaceObject& idf_airLoopHVAC = idf_airloops.front(); + WorkspaceObject idf_brlist = idf_airLoopHVAC.getTarget(AirLoopHVACFields::BranchListName).get(); + + // Should have one branch only + ASSERT_EQ(1u, idf_brlist.extensibleGroups().size()); + auto w_eg = idf_brlist.extensibleGroups()[0].cast(); + WorkspaceObject idf_branch = w_eg.getTarget(BranchListExtensibleFields::BranchName).get(); + + // There should be only one equipment on the branch + ASSERT_EQ(1u, idf_branch.extensibleGroups().size()); + auto w_eg2 = idf_branch.extensibleGroups()[0].cast(); + + EXPECT_EQ(w_eg2.getString(BranchExtensibleFields::ComponentInletNodeName).get(), coil.airInletModelObject().get().nameString()); + EXPECT_EQ(w_eg2.getString(BranchExtensibleFields::ComponentOutletNodeName).get(), coil.airOutletModelObject().get().nameString()); + + EXPECT_EQ("CoilSystem:Cooling:Water", w_eg2.getString(BranchExtensibleFields::ComponentObjectType).get()); + auto idf_coilSystem = w_eg2.getTarget(BranchExtensibleFields::ComponentName).get(); + // CoilSystem:Cooling:Water wrapper needed, it's not inside a unitary + EXPECT_EQ(1, w.getObjectsByType(IddObjectType::CoilSystem_Cooling_Water).size()); + + EXPECT_EQ(coil.airInletModelObject().get().nameString(), idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::AirInletNodeName).get()); + EXPECT_EQ(coil.airOutletModelObject().get().nameString(), idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::AirOutletNodeName).get()); + EXPECT_EQ("Always On Discrete", idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::AvailabilityScheduleName).get()); + EXPECT_EQ("CoilSystem:Cooling:Water:HeatExchangerAssisted", idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::CoolingCoilObjectType).get()); + EXPECT_EQ(coil.nameString(), idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::CoolingCoilName).get()); + EXPECT_EQ(idfCoil, idf_coilSystem.getTarget(CoilSystem_Cooling_WaterFields::CoolingCoilName).get()); + EXPECT_TRUE(idf_coilSystem.isEmpty(CoilSystem_Cooling_WaterFields::DehumidificationControlType)); + EXPECT_TRUE(idf_coilSystem.isEmpty(CoilSystem_Cooling_WaterFields::RunonSensibleLoad)); + EXPECT_TRUE(idf_coilSystem.isEmpty(CoilSystem_Cooling_WaterFields::RunonLatentLoad)); + EXPECT_TRUE(idf_coilSystem.isEmpty(CoilSystem_Cooling_WaterFields::MinimumAirToWaterTemperatureOffset)); + EXPECT_TRUE(idf_coilSystem.isEmpty(CoilSystem_Cooling_WaterFields::EconomizerLockout)); + EXPECT_TRUE(idf_coilSystem.isEmpty(CoilSystem_Cooling_WaterFields::MinimumWaterLoopTemperatureForHeatRecovery)); + EXPECT_TRUE(idf_coilSystem.isEmpty(CoilSystem_Cooling_WaterFields::CompanionCoilUsedForHeatRecovery)); +} From 8dfc486bc881bbb7fe5ede1cc821dc5f20aa5930 Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Mon, 3 Feb 2025 12:53:37 -0700 Subject: [PATCH 08/58] Formatting. --- .../Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/energyplus/Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp b/src/energyplus/Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp index 645eefe875d..eaf8ee7d2e7 100644 --- a/src/energyplus/Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp +++ b/src/energyplus/Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp @@ -83,7 +83,8 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWaterHeatExchangerA idfCoil.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::AirOutletNodeName).get()); EXPECT_EQ("My CoilSystemCoolingWaterHeatExchangerAssisted", idfCoil.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::Name).get()); - EXPECT_EQ("HeatExchanger:AirToAir:SensibleAndLatent", idfCoil.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::HeatExchangerObjectType).get()); + EXPECT_EQ("HeatExchanger:AirToAir:SensibleAndLatent", + idfCoil.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::HeatExchangerObjectType).get()); EXPECT_EQ(coil.heatExchanger().nameString(), idfCoil.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::HeatExchangerName).get()); EXPECT_EQ("Coil:Cooling:Water", idfCoil.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::CoolingCoilObjectType).get()); EXPECT_EQ(coil.coolingCoil().nameString(), idfCoil.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::CoolingCoilName).get()); From b3235b74a679290ffb87905cf39ff69281ad3b81 Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Mon, 3 Feb 2025 12:57:15 -0700 Subject: [PATCH 09/58] Typo in cmakelists. --- src/energyplus/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/energyplus/CMakeLists.txt b/src/energyplus/CMakeLists.txt index 13ad14151e3..9b79fdb55b4 100644 --- a/src/energyplus/CMakeLists.txt +++ b/src/energyplus/CMakeLists.txt @@ -715,7 +715,7 @@ set(${target_name}_test_src Test/CoilHeatingGasMultiStage_GTest.cpp Test/CoilHeatingWaterToAirHeatPumpEquationFit_GTest.cpp Test/CoilHeatingWaterToAirHeatPumpVariableSpeedEquationFit_GTest.cpp - Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest + Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp Test/CoilSystemIntegratedHeatPumpAirSource_GTest.cpp Test/CoilUserDefined_GTest.cpp Test/CoilWaterHeatingAirToWaterHeatPump_GTest.cpp From 7ba073331c68c49a0e004df7648c60b016f3c4ad Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Mon, 3 Feb 2025 13:52:49 -0700 Subject: [PATCH 10/58] Few typos in new ft. --- src/energyplus/ForwardTranslator.hpp | 3 +++ ...anslateCoilSystemCoolingWaterHeatExchangerAssisted.cpp | 8 +++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/energyplus/ForwardTranslator.hpp b/src/energyplus/ForwardTranslator.hpp index a02a1737a2c..631071d97b8 100644 --- a/src/energyplus/ForwardTranslator.hpp +++ b/src/energyplus/ForwardTranslator.hpp @@ -845,6 +845,9 @@ namespace energyplus { boost::optional translateCoilSystemCoolingWaterHeatExchangerAssisted(model::CoilSystemCoolingWaterHeatExchangerAssisted& modelObject); + boost::optional + translateCoilSystemCoolingWaterHeatExchangerAssistedWithoutUnitary(model::CoilSystemCoolingWaterHeatExchangerAssisted& modelObject); + boost::optional translateCoilSystemIntegratedHeatPumpAirSource(model::CoilSystemIntegratedHeatPumpAirSource& modelObject); boost::optional translateCoilUserDefined(model::CoilUserDefined& modelObject); diff --git a/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWaterHeatExchangerAssisted.cpp b/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWaterHeatExchangerAssisted.cpp index 32a7f3e0dea..c26171176ff 100644 --- a/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWaterHeatExchangerAssisted.cpp +++ b/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWaterHeatExchangerAssisted.cpp @@ -27,6 +27,7 @@ #include "../../model/Model.hpp" #include "../../utilities/core/Assert.hpp" +#include #include #include #include @@ -41,8 +42,8 @@ namespace openstudio { namespace energyplus { - boost::optional - ForwardTranslator::translateCoilSystemCoolingWaterHeatExchangerAssistedWithoutUnitary(CoilSystemCoolingWaterHeatExchangerAssisted& modelObject) { + boost::optional ForwardTranslator::translateCoilSystemCoolingWaterHeatExchangerAssistedWithoutUnitary( + model::CoilSystemCoolingWaterHeatExchangerAssisted& modelObject) { IdfObject idfObject = createRegisterAndNameIdfObject(openstudio::IddObjectType::CoilSystem_Cooling_Water_HeatExchangerAssisted, modelObject); @@ -157,7 +158,8 @@ namespace energyplus { return idfObject; } - boost::optional ForwardTranslator::translateCoilSystemCoolingWaterHeatExchangerAssisted(CoilCoolingWater& modelObject) { + boost::optional + ForwardTranslator::translateCoilSystemCoolingWaterHeatExchangerAssisted(CoilSystemCoolingWaterHeatExchangerAssisted& modelObject) { IdfObject coilSystemCoolingWaterIdf(IddObjectType::CoilSystem_Cooling_Water); m_idfObjects.push_back(coilSystemCoolingWaterIdf); From 2a7b8c3aaef3d2fa568a4268c829384a718578cf Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Mon, 3 Feb 2025 14:05:19 -0700 Subject: [PATCH 11/58] Update new ft. --- ...nslateCoilSystemCoolingWaterHeatExchangerAssisted.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWaterHeatExchangerAssisted.cpp b/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWaterHeatExchangerAssisted.cpp index c26171176ff..0197e59eb19 100644 --- a/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWaterHeatExchangerAssisted.cpp +++ b/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWaterHeatExchangerAssisted.cpp @@ -183,12 +183,7 @@ namespace energyplus { coilSystemCoolingWaterIdf.setName(*s + " CoilSystem"); } - Schedule sched = modelObject.availabilitySchedule(); - translateAndMapModelObject(sched); - - coilSystemCoolingWaterIdf.setString(CoilSystem_Cooling_WaterFields::AvailabilityScheduleName, sched.name().get()); - - OptionalModelObject omo = modelObject.airInletModelObject(); + OptionalModelObject omo = modelObject.inletModelObject(); if (omo) { translateAndMapModelObject(*omo); s = omo->name(); @@ -197,7 +192,7 @@ namespace energyplus { } } - omo = modelObject.airOutletModelObject(); + omo = modelObject.outletModelObject(); if (omo) { translateAndMapModelObject(*omo); s = omo->name(); From d974d090736477ae5d7e3cf5b2ac610ada742d0f Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Mon, 3 Feb 2025 14:16:45 -0700 Subject: [PATCH 12/58] Another typo in ft. --- .../Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/energyplus/Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp b/src/energyplus/Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp index eaf8ee7d2e7..1719d478456 100644 --- a/src/energyplus/Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp +++ b/src/energyplus/Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp @@ -23,7 +23,7 @@ #include "../../utilities/idf/IdfExtensibleGroup.hpp" #include "../../utilities/idf/WorkspaceExtensibleGroup.hpp" -#include +#include #include #include #include From 45254a6db59ed9e80297283f15faedb6a9c0413d Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Tue, 4 Feb 2025 11:45:47 -0700 Subject: [PATCH 13/58] Special case for coilsystem ft on plant loop branch. --- .../ForwardTranslatePlantLoop.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/energyplus/ForwardTranslator/ForwardTranslatePlantLoop.cpp b/src/energyplus/ForwardTranslator/ForwardTranslatePlantLoop.cpp index a3dc363a531..86be1a75318 100644 --- a/src/energyplus/ForwardTranslator/ForwardTranslatePlantLoop.cpp +++ b/src/energyplus/ForwardTranslator/ForwardTranslatePlantLoop.cpp @@ -76,6 +76,8 @@ #include "../../model/CoilCoolingCooledBeam_Impl.hpp" #include "../../model/CoilCoolingFourPipeBeam.hpp" #include "../../model/CoilCoolingFourPipeBeam_Impl.hpp" +#include "../../model/CoilCoolingWater.hpp" +#include "../../model/CoilCoolingWater_Impl.hpp" #include "../../model/CoilHeatingFourPipeBeam.hpp" #include "../../model/CoilHeatingFourPipeBeam_Impl.hpp" #include "../../model/StraightComponent.hpp" @@ -116,6 +118,7 @@ #include #include #include +#include #include "../../utilities/core/Assert.hpp" using namespace openstudio::model; @@ -300,6 +303,17 @@ namespace energyplus { if (loop.optionalCast()) { inletNode = waterToAirComponent->waterInletModelObject()->optionalCast(); outletNode = waterToAirComponent->waterOutletModelObject()->optionalCast(); + // Special case for Coil:Cooling:Water. + if (boost::optional ccw = modelObject.optionalCast()) { + boost::optional idfCoil = this->translateAndMapModelObject(*ccw); + if (idfCoil) { + if (idfCoil->iddObject().type() == IddObjectType::CoilSystem_Cooling_Water) { + //Get the name and idd type of the coil cooling water inside the coil system + objectName = idfCoil->getString(CoilSystem_Cooling_WaterFields::CoolingCoilName).get(); + iddType = idfCoil->getString(CoilSystem_Cooling_WaterFields::CoolingCoilObjectType).get(); + } + } + } } else { inletNode = waterToAirComponent->airInletModelObject()->optionalCast(); outletNode = waterToAirComponent->airOutletModelObject()->optionalCast(); From 8d6f69c62bf838a83f31411fee9a43177e25eafc Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Tue, 4 Feb 2025 11:45:55 -0700 Subject: [PATCH 14/58] Fix and update ft tests. --- .../Test/CoilCoolingWater_GTest.cpp | 2 +- ...oolingWaterHeatExchangerAssisted_GTest.cpp | 38 ++++++++++--------- 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/src/energyplus/Test/CoilCoolingWater_GTest.cpp b/src/energyplus/Test/CoilCoolingWater_GTest.cpp index aec1e5f6b51..52e440931b4 100644 --- a/src/energyplus/Test/CoilCoolingWater_GTest.cpp +++ b/src/energyplus/Test/CoilCoolingWater_GTest.cpp @@ -68,7 +68,7 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilCoolingWater_Unitary) { ASSERT_EQ(1u, idfCoils.size()); WorkspaceObject idfCoil(idfCoils[0]); - // No CoilSystem:Cooling:DX wrapper needed, it's inside a unitary + // No CoilSystem:Cooling:Water wrapper needed, it's inside a unitary EXPECT_EQ(0, w.getObjectsByType(IddObjectType::CoilSystem_Cooling_Water).size()); // Check that the Unitary ends up with the CoilCoolingWater diff --git a/src/energyplus/Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp b/src/energyplus/Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp index 1719d478456..7b43b17c568 100644 --- a/src/energyplus/Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp +++ b/src/energyplus/Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp @@ -11,6 +11,10 @@ #include "../../model/Model.hpp" #include "../../model/CoilSystemCoolingWaterHeatExchangerAssisted.hpp" #include "../../model/CoilSystemCoolingWaterHeatExchangerAssisted_Impl.hpp" +#include "../../model/CoilCoolingWater.hpp" +#include "../../model/CoilCoolingWater_Impl.hpp" +#include "../../model/HeatExchangerAirToAirSensibleAndLatent.hpp" +#include "../../model/HeatExchangerAirToAirSensibleAndLatent_Impl.hpp" #include "../../model/AirLoopHVAC.hpp" #include "../../model/AirLoopHVACUnitarySystem.hpp" @@ -25,6 +29,7 @@ #include #include +#include #include #include #include @@ -53,9 +58,7 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWaterHeatExchangerA // They must be connected to a PlantLoop too PlantLoop chw_p(m); - chw_p.addDemandBranchForComponent(coil); - coil.waterInletModelObject()->setName("Coil Water Inlet Node"); - coil.waterOutletModelObject()->setName("Coil Water Outlet Node"); + chw_p.addDemandBranchForComponent(coil.coolingCoil()); ForwardTranslator ft; Workspace w = ft.translateModel(m); @@ -68,7 +71,11 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWaterHeatExchangerA ASSERT_EQ(1u, idfCoils.size()); WorkspaceObject idfCoil(idfCoils[0]); - // No CoilSystem:Cooling:DX wrapper needed, it's inside a unitary + WorkspaceObjectVector idfHXs(w.getObjectsByType(IddObjectType::HeatExchanger_AirToAir_SensibleAndLatent)); + ASSERT_EQ(1u, idfHXs.size()); + WorkspaceObject idfHX(idfHXs[0]); + + // No CoilSystem:Cooling:Water wrapper needed, it's inside a unitary EXPECT_EQ(0, w.getObjectsByType(IddObjectType::CoilSystem_Cooling_Water).size()); // Check that the Unitary ends up with the CoilSystemCoolingWaterHeatExchangerAssisted @@ -77,10 +84,10 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWaterHeatExchangerA // Since the Unitary only has a Cooling Coil (no fan, not HC / Suppl HC), the nodes should match EXPECT_EQ(idfUnitary.getString(AirLoopHVAC_UnitarySystemFields::AirInletNodeName).get(), - idfCoil.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::AirInletNodeName).get()); + idfHX.getString(HeatExchanger_AirToAir_SensibleAndLatentFields::SupplyAirInletNodeName).get()); EXPECT_EQ(idfUnitary.getString(AirLoopHVAC_UnitarySystemFields::AirOutletNodeName).get(), - idfCoil.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::AirOutletNodeName).get()); + idfHX.getString(HeatExchanger_AirToAir_SensibleAndLatentFields::ExhaustAirOutletNodeName).get()); EXPECT_EQ("My CoilSystemCoolingWaterHeatExchangerAssisted", idfCoil.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::Name).get()); EXPECT_EQ("HeatExchanger:AirToAir:SensibleAndLatent", @@ -101,20 +108,15 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWaterHeatExchangerA // They must be connected to a PlantLoop too PlantLoop chw_p(m); - chw_p.addDemandBranchForComponent(coil); + chw_p.addDemandBranchForComponent(coil.coolingCoil()); ForwardTranslator ft; Workspace w = ft.translateModel(m); - WorkspaceObjectVector idfCoils(w.getObjectsByType(IddObjectType::Coil_Cooling_Water)); + WorkspaceObjectVector idfCoils(w.getObjectsByType(IddObjectType::CoilSystem_Cooling_Water_HeatExchangerAssisted)); ASSERT_EQ(1u, idfCoils.size()); WorkspaceObject idfCoil(idfCoils[0]); - EXPECT_EQ(idfCoil.getString(Coil_Cooling_WaterFields::WaterInletNodeName).get(), coil.waterInletModelObject().get().nameString()); - EXPECT_EQ(idfCoil.getString(Coil_Cooling_WaterFields::WaterOutletNodeName).get(), coil.waterOutletModelObject().get().nameString()); - EXPECT_EQ(idfCoil.getString(Coil_Cooling_WaterFields::AirInletNodeName).get(), coil.airInletModelObject().get().nameString()); - EXPECT_EQ(idfCoil.getString(Coil_Cooling_WaterFields::AirOutletNodeName).get(), coil.airOutletModelObject().get().nameString()); - EXPECT_EQ(1, w.getObjectsByType(IddObjectType::CoilSystem_Cooling_Water).size()); // Go from AirLoopHVAC to BranchList to Branch @@ -133,17 +135,17 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWaterHeatExchangerA ASSERT_EQ(1u, idf_branch.extensibleGroups().size()); auto w_eg2 = idf_branch.extensibleGroups()[0].cast(); - EXPECT_EQ(w_eg2.getString(BranchExtensibleFields::ComponentInletNodeName).get(), coil.airInletModelObject().get().nameString()); - EXPECT_EQ(w_eg2.getString(BranchExtensibleFields::ComponentOutletNodeName).get(), coil.airOutletModelObject().get().nameString()); + EXPECT_EQ(w_eg2.getString(BranchExtensibleFields::ComponentInletNodeName).get(), coil.inletModelObject().get().nameString()); + EXPECT_EQ(w_eg2.getString(BranchExtensibleFields::ComponentOutletNodeName).get(), coil.outletModelObject().get().nameString()); EXPECT_EQ("CoilSystem:Cooling:Water", w_eg2.getString(BranchExtensibleFields::ComponentObjectType).get()); auto idf_coilSystem = w_eg2.getTarget(BranchExtensibleFields::ComponentName).get(); // CoilSystem:Cooling:Water wrapper needed, it's not inside a unitary EXPECT_EQ(1, w.getObjectsByType(IddObjectType::CoilSystem_Cooling_Water).size()); - EXPECT_EQ(coil.airInletModelObject().get().nameString(), idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::AirInletNodeName).get()); - EXPECT_EQ(coil.airOutletModelObject().get().nameString(), idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::AirOutletNodeName).get()); - EXPECT_EQ("Always On Discrete", idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::AvailabilityScheduleName).get()); + EXPECT_EQ(coil.inletModelObject().get().nameString(), idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::AirInletNodeName).get()); + EXPECT_EQ(coil.outletModelObject().get().nameString(), idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::AirOutletNodeName).get()); + EXPECT_TRUE(idf_coilSystem.isEmpty(CoilSystem_Cooling_WaterFields::AvailabilityScheduleName)); EXPECT_EQ("CoilSystem:Cooling:Water:HeatExchangerAssisted", idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::CoolingCoilObjectType).get()); EXPECT_EQ(coil.nameString(), idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::CoolingCoilName).get()); EXPECT_EQ(idfCoil, idf_coilSystem.getTarget(CoilSystem_Cooling_WaterFields::CoolingCoilName).get()); From a6e0711287750b12ed1c6556519ef8a44d6016e8 Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Fri, 31 Jan 2025 15:03:43 -0700 Subject: [PATCH 15/58] Separate coil cooling water ft into without unitary and coil system. --- src/energyplus/ForwardTranslator.cpp | 6 +- src/energyplus/ForwardTranslator.hpp | 2 + .../ForwardTranslateCoilCoolingWater.cpp | 56 ++++++++++++++++++- 3 files changed, 62 insertions(+), 2 deletions(-) diff --git a/src/energyplus/ForwardTranslator.cpp b/src/energyplus/ForwardTranslator.cpp index 8eaef4ae050..c9d8e628ed4 100644 --- a/src/energyplus/ForwardTranslator.cpp +++ b/src/energyplus/ForwardTranslator.cpp @@ -1072,7 +1072,11 @@ namespace energyplus { } case openstudio::IddObjectType::OS_Coil_Cooling_Water: { auto coil = modelObject.cast(); - retVal = translateCoilCoolingWater(coil); + if (isHVACComponentWithinUnitary(coil)) { + retVal = translateCoilCoolingWaterWithoutUnitary(coil); + } else { + retVal = translateCoilCoolingWater(coil); + } break; } case openstudio::IddObjectType::OS_Coil_Cooling_Water_Panel_Radiant: { diff --git a/src/energyplus/ForwardTranslator.hpp b/src/energyplus/ForwardTranslator.hpp index e2699e9f9ae..a77586f1af1 100644 --- a/src/energyplus/ForwardTranslator.hpp +++ b/src/energyplus/ForwardTranslator.hpp @@ -801,6 +801,8 @@ namespace energyplus { boost::optional translateCoilCoolingWater(model::CoilCoolingWater& modelObject); + boost::optional translateCoilCoolingWaterWithoutUnitary(model::CoilCoolingWater& modelObject); + boost::optional translateCoilCoolingWaterToAirHeatPumpEquationFit(model::CoilCoolingWaterToAirHeatPumpEquationFit& modelObject); boost::optional diff --git a/src/energyplus/ForwardTranslator/ForwardTranslateCoilCoolingWater.cpp b/src/energyplus/ForwardTranslator/ForwardTranslateCoilCoolingWater.cpp index 8968638ad86..105797b6c54 100644 --- a/src/energyplus/ForwardTranslator/ForwardTranslateCoilCoolingWater.cpp +++ b/src/energyplus/ForwardTranslator/ForwardTranslateCoilCoolingWater.cpp @@ -13,6 +13,7 @@ #include "../../model/CoilCoolingWater_Impl.hpp" #include "../../utilities/core/Logger.hpp" #include "../../utilities/core/Assert.hpp" +#include #include #include "../../utilities/idd/IddEnums.hpp" #include @@ -26,7 +27,7 @@ namespace openstudio { namespace energyplus { - boost::optional ForwardTranslator::translateCoilCoolingWater(CoilCoolingWater& modelObject) { + boost::optional ForwardTranslator::translateCoilCoolingWaterWithoutUnitary(model::CoilCoolingWater& modelObject) { boost::optional s; boost::optional value; @@ -150,6 +151,59 @@ namespace energyplus { return boost::optional(idfObject); } + boost::optional ForwardTranslator::translateCoilCoolingWater(CoilCoolingWater& modelObject) { + boost::optional s; + boost::optional value; + + IdfObject coilSystemCoolingWaterIdf(IddObjectType::CoilSystem_Cooling_Water); + + m_idfObjects.push_back(coilSystemCoolingWaterIdf); + + boost::optional oIdfObject = translateCoilCoolingWaterWithoutUnitary(modelObject); + + if (!oIdfObject) { + return boost::none; + } + + IdfObject idfObject = oIdfObject.get(); + + OptionalString s; + + s = modelObject.name(); + if (s) { + coilSystemCoolingWaterIdf.setString(CoilSystem_Cooling_WaterFields::CoolingCoilObjectType, idfObject.iddObject().name()); + + coilSystemCoolingWaterIdf.setString(CoilSystem_Cooling_WaterFields::CoolingCoilName, *s); + + coilSystemCoolingWaterIdf.setName(*s + " CoilSystem"); + } + + Schedule sched = modelObject.availabilitySchedule(); + translateAndMapModelObject(sched); + + coilSystemCoolingWaterIdf.setString(CoilSystem_Cooling_WaterFields::AvailabilityScheduleName, sched.name().get()); + + OptionalModelObject omo = modelObject.inletModelObject(); + if (omo) { + translateAndMapModelObject(*omo); + s = omo->name(); + if (s) { + coilSystemCoolingWaterIdf.setString(CoilSystem_Cooling_WaterFields::AirInletNodeName, *s); + } + } + + omo = modelObject.outletModelObject(); + if (omo) { + translateAndMapModelObject(*omo); + s = omo->name(); + if (s) { + coilSystemCoolingWaterIdf.setString(CoilSystem_Cooling_WaterFields::AirOutletNodeName, *s); + } + } + + return coilSystemCoolingWaterIdf; + } + //((Name)(Name)) //((AvailabilityScheduleName)(Availability Schedule Name)) From d63b3f1825d4ff1aeeaeb15fc6f82518f3d5e0a1 Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Fri, 31 Jan 2025 15:03:55 -0700 Subject: [PATCH 16/58] Stub ft test for coil cooling water. --- src/energyplus/CMakeLists.txt | 1 + .../Test/CoilCoolingWater_GTest.cpp | 59 +++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 src/energyplus/Test/CoilCoolingWater_GTest.cpp diff --git a/src/energyplus/CMakeLists.txt b/src/energyplus/CMakeLists.txt index fd1d301ed63..86c813f9da3 100644 --- a/src/energyplus/CMakeLists.txt +++ b/src/energyplus/CMakeLists.txt @@ -706,6 +706,7 @@ set(${target_name}_test_src Test/CoilCoolingDXTwoSpeed_GTest.cpp Test/CoilCoolingDXTwoStageWithHumidityControlMode_GTest.cpp Test/CoilCoolingDXVariableSpeed_GTest.cpp + Test/CoilCoolingWater_GTest.cpp Test/CoilCoolingWaterToAirHeatPumpEquationFit_GTest.cpp Test/CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_GTest.cpp Test/CoilHeatingDXMultiSpeed_GTest.cpp diff --git a/src/energyplus/Test/CoilCoolingWater_GTest.cpp b/src/energyplus/Test/CoilCoolingWater_GTest.cpp new file mode 100644 index 00000000000..d92c1f20ddb --- /dev/null +++ b/src/energyplus/Test/CoilCoolingWater_GTest.cpp @@ -0,0 +1,59 @@ +/*********************************************************************************************************************** +* 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/CoilCoolingWater.hpp" +#include "../../model/CoilCoolingWater_Impl.hpp" + +#include "../../model/AirLoopHVAC.hpp" +#include "../../model/AirLoopHVACUnitarySystem.hpp" +#include "../../model/Node.hpp" + +#include "../../utilities/idf/IdfObject.hpp" +#include "../../utilities/idf/IdfObject_Impl.hpp" +#include "../../utilities/idf/WorkspaceObject.hpp" +#include "../../utilities/idf/WorkspaceObject_Impl.hpp" +#include "../../utilities/idf/IdfExtensibleGroup.hpp" +#include "../../utilities/idf/WorkspaceExtensibleGroup.hpp" + +#include +#include +#include +#include +#include +#include +#include + +using namespace openstudio::energyplus; +using namespace openstudio::model; +using namespace openstudio; + +TEST_F(EnergyPlusFixture, ForwardTranslator_CoilCoolingWater_Unitary) { + Model m; + CoilCoolingWater coil(m); + + ForwardTranslator ft; + Workspace w = ft.translateModel(m); + + // No CoilSystem:Cooling:DX wrapper needed, it's inside a unitary + EXPECT_EQ(0, w.getObjectsByType(IddObjectType::CoilSystem_Cooling_Water).size()); +} + +TEST_F(EnergyPlusFixture, ForwardTranslator_CoilCoolingWater_AirLoopHVAC) { + + ForwardTranslator ft; + + Model m; + CoilCoolingWater coil(m); + + Workspace w = ft.translateModel(m); + + EXPECT_EQ(1, w.getObjectsByType(IddObjectType::CoilSystem_Cooling_Water).size()); +} From 5b02c726f5095d9dd40a42bd6de0714fe61ea98b Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Fri, 31 Jan 2025 15:19:03 -0700 Subject: [PATCH 17/58] Few typos in new ft method. --- .../ForwardTranslator/ForwardTranslateCoilCoolingWater.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/energyplus/ForwardTranslator/ForwardTranslateCoilCoolingWater.cpp b/src/energyplus/ForwardTranslator/ForwardTranslateCoilCoolingWater.cpp index 105797b6c54..22a7314c3ab 100644 --- a/src/energyplus/ForwardTranslator/ForwardTranslateCoilCoolingWater.cpp +++ b/src/energyplus/ForwardTranslator/ForwardTranslateCoilCoolingWater.cpp @@ -152,9 +152,6 @@ namespace energyplus { } boost::optional ForwardTranslator::translateCoilCoolingWater(CoilCoolingWater& modelObject) { - boost::optional s; - boost::optional value; - IdfObject coilSystemCoolingWaterIdf(IddObjectType::CoilSystem_Cooling_Water); m_idfObjects.push_back(coilSystemCoolingWaterIdf); @@ -183,7 +180,7 @@ namespace energyplus { coilSystemCoolingWaterIdf.setString(CoilSystem_Cooling_WaterFields::AvailabilityScheduleName, sched.name().get()); - OptionalModelObject omo = modelObject.inletModelObject(); + OptionalModelObject omo = modelObject.airInletModelObject(); if (omo) { translateAndMapModelObject(*omo); s = omo->name(); @@ -192,7 +189,7 @@ namespace energyplus { } } - omo = modelObject.outletModelObject(); + omo = modelObject.airOutletModelObject(); if (omo) { translateAndMapModelObject(*omo); s = omo->name(); From f2a8287ad6184c8c6786ca39a5dc1bad3def2a26 Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Mon, 3 Feb 2025 10:39:17 -0700 Subject: [PATCH 18/58] Expand new ft test. --- .../Test/CoilCoolingWater_GTest.cpp | 114 +++++++++++++++++- 1 file changed, 111 insertions(+), 3 deletions(-) diff --git a/src/energyplus/Test/CoilCoolingWater_GTest.cpp b/src/energyplus/Test/CoilCoolingWater_GTest.cpp index d92c1f20ddb..f1261e04daf 100644 --- a/src/energyplus/Test/CoilCoolingWater_GTest.cpp +++ b/src/energyplus/Test/CoilCoolingWater_GTest.cpp @@ -38,22 +38,130 @@ using namespace openstudio; TEST_F(EnergyPlusFixture, ForwardTranslator_CoilCoolingWater_Unitary) { Model m; CoilCoolingWater coil(m); + coil.setName("My CoilCoolingWater"); + + // put it inside a Unitary, and put Unitary on an AirLoopHVAC so it gets translated + AirLoopHVACUnitarySystem unitary(m); + unitary.setCoolingCoil(coil); + AirLoopHVAC airLoop(m); + Node supplyOutletNode = airLoop.supplyOutletNode(); + unitary.addToNode(supplyOutletNode); + ASSERT_TRUE(unitary.inletNode()); + EXPECT_TRUE(unitary.inletNode()->setName("Coil Air Inlet Node")); + ASSERT_TRUE(unitary.outletNode()); + EXPECT_TRUE(unitary.outletNode()->setName("Coil Air Outlet Node")); + + // They must be connected to a PlantLoop too + PlantLoop chw_p(m); + chw_p.addDemandBranchForComponent(coil); + coil.waterInletModelObject()->setName("Coil Water Inlet Node"); + coil.waterOutletModelObject()->setName("Coil Water Outlet Node"); ForwardTranslator ft; Workspace w = ft.translateModel(m); + WorkspaceObjectVector idfUnitarys(w.getObjectsByType(IddObjectType::AirLoopHVAC_UnitarySystem)); + ASSERT_EQ(1u, idfUnitarys.size()); + WorkspaceObject idfUnitary(idfUnitarys[0]); + + WorkspaceObjectVector idfCoils(w.getObjectsByType(IddObjectType::Coil_Cooling_Water)); + ASSERT_EQ(1u, idfCoils.size()); + WorkspaceObject idfCoil(idfCoils[0]); + // No CoilSystem:Cooling:DX wrapper needed, it's inside a unitary EXPECT_EQ(0, w.getObjectsByType(IddObjectType::CoilSystem_Cooling_Water).size()); -} -TEST_F(EnergyPlusFixture, ForwardTranslator_CoilCoolingWater_AirLoopHVAC) { + // Check that the Unitary ends up with the CoilCoolingWater + EXPECT_EQ("Coil:Cooling:Water", idfUnitary.getString(AirLoopHVAC_UnitarySystemFields::CoolingCoilObjectType).get()); + EXPECT_EQ(idfCoil.nameString(), idfUnitary.getString(AirLoopHVAC_UnitarySystemFields::CoolingCoilName).get()); - ForwardTranslator ft; + // Since the Unitary only has a Cooling Coil (no fan, not HC / Suppl HC), the nodes should match + EXPECT_EQ(idfUnitary.getString(AirLoopHVAC_UnitarySystemFields::AirInletNodeName).get(), + idfCoil.getString(Coil_Cooling_WaterFields::AirInletNodeName).get()); + + EXPECT_EQ(idfUnitary.getString(AirLoopHVAC_UnitarySystemFields::AirOutletNodeName).get(), + idfCoil.getString(Coil_Cooling_WaterFields::AirOutletNodeName).get()); + + EXPECT_EQ("My CoilCoolingWater", idfCoil.getString(Coil_Cooling_WaterFields::Name).get()); + EXPECT_EQ("", idfCoil.getString(Coil_Cooling_WaterFields::AvailabilityScheduleName).get()); + EXPECT_EQ(0.6, idfCoil.getDouble(Coil_Cooling_WaterFields::DesignWaterFlowRate).get()); + EXPECT_EQ(0.6, idfCoil.getDouble(Coil_Cooling_WaterFields::DesignAirFlowRate).get()); + EXPECT_EQ(0.6, idfCoil.getDouble(Coil_Cooling_WaterFields::DesignInletWaterTemperature).get()); + EXPECT_EQ(0.6, idfCoil.getDouble(Coil_Cooling_WaterFields::DesignInletAirTemperature).get()); + EXPECT_EQ(0.6, idfCoil.getDouble(Coil_Cooling_WaterFields::DesignInletAirHumidityRatio).get()); + EXPECT_EQ(0.6, idfCoil.getDouble(Coil_Cooling_WaterFields::DesignOutletAirHumidityRatio).get()); + EXPECT_EQ("Coil Water Inlet Node", idfCoil.getString(Coil_Cooling_WaterFields::WaterInletNodeName).get()); + EXPECT_EQ("Coil Water Outlet Node", idfCoil.getString(Coil_Cooling_WaterFields::WaterOutletNodeName).get()); + EXPECT_EQ("Coil Air Inlet Node", idfCoil.getString(Coil_Cooling_WaterFields::AirInletNodeName).get()); + EXPECT_EQ("Coil Air Outlet Node", idfCoil.getString(Coil_Cooling_WaterFields::AirOutletNodeName).get()); + EXPECT_EQ("", idfCoil.getString(Coil_Cooling_WaterFields::TypeofAnalysis).get()); + EXPECT_EQ("", idfCoil.getString(Coil_Cooling_WaterFields::HeatExchangerConfiguration).get()); + EXPECT_EQ("", idfCoil.getString(Coil_Cooling_WaterFields::CondensateCollectionWaterStorageTankName).get()); + EXPECT_EQ(0.9, idfCoil.getDouble(Coil_Cooling_WaterFields::DesignWaterTemperatureDifference).get()); +} +TEST_F(EnergyPlusFixture, ForwardTranslator_CoilCoolingWater_AirLoopHVAC) { Model m; CoilCoolingWater coil(m); + // put it on an AirLoopHVAC + AirLoopHVAC airLoop(m); + Node supplyOutletNode = airLoop.supplyOutletNode(); + EXPECT_TRUE(coil.addToNode(supplyOutletNode)); + + // They must be connected to a PlantLoop too + PlantLoop chw_p(m); + chw_p.addDemandBranchForComponent(coil); + + ForwardTranslator ft; Workspace w = ft.translateModel(m); + WorkspaceObjectVector idfCoils(w.getObjectsByType(IddObjectType::Coil_Cooling_Water)); + ASSERT_EQ(1u, idfCoils.size()); + WorkspaceObject idfCoil(idfCoils[0]); + + EXPECT_EQ(idfCoil.getString(Coil_Cooling_WaterFields::WaterInletNodeName).get(), coil.waterInletModelObject().get().nameString()); + EXPECT_EQ(idfCoil.getString(Coil_Cooling_WaterFields::WaterOutletNodeName).get(), coil.waterOutletModelObject().get().nameString()); + EXPECT_EQ(idfCoil.getString(Coil_Cooling_WaterFields::AirInletNodeName).get(), coil.airInletModelObject().get().nameString()); + EXPECT_EQ(idfCoil.getString(Coil_Cooling_WaterFields::AirOutletNodeName).get(), coil.airOutletModelObject().get().nameString()); + + EXPECT_EQ(1, w.getObjectsByType(IddObjectType::CoilSystem_Cooling_Water).size()); + + // Go from AirLoopHVAC to BranchList to Branch + WorkspaceObjectVector idf_airloops = w.getObjectsByType(IddObjectType::AirLoopHVAC); + ASSERT_EQ(1u, idf_airloops.size()); + + WorkspaceObject& idf_airLoopHVAC = idf_airloops.front(); + WorkspaceObject idf_brlist = idf_airLoopHVAC.getTarget(AirLoopHVACFields::BranchListName).get(); + + // Should have one branch only + ASSERT_EQ(1u, idf_brlist.extensibleGroups().size()); + auto w_eg = idf_brlist.extensibleGroups()[0].cast(); + WorkspaceObject idf_branch = w_eg.getTarget(BranchListExtensibleFields::BranchName).get(); + + // There should be only one equipment on the branch + ASSERT_EQ(1u, idf_branch.extensibleGroups().size()); + auto w_eg2 = idf_branch.extensibleGroups()[0].cast(); + + EXPECT_EQ(w_eg2.getString(BranchExtensibleFields::ComponentInletNodeName).get(), coil.inletModelObject().get().nameString()); + EXPECT_EQ(w_eg2.getString(BranchExtensibleFields::ComponentOutletNodeName).get(), coil.outletModelObject().get().nameString()); + + EXPECT_EQ("CoilSystem:Cooling:Water", w_eg2.getString(BranchExtensibleFields::ComponentObjectType).get()); + auto idf_coilSystem = w_eg2.getTarget(BranchExtensibleFields::ComponentName).get(); + // CoilSystem:Cooling:Water wrapper needed, it's not inside a unitary EXPECT_EQ(1, w.getObjectsByType(IddObjectType::CoilSystem_Cooling_Water).size()); + + EXPECT_EQ(coil.airInletModelObject().get().nameString(), idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::AirInletNodeName).get()); + EXPECT_EQ(coil.airOutletModelObject().get().nameString(), idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::AirOutletNodeName).get()); + EXPECT_EQ("Always On Discrete", idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::AvailabilityScheduleName).get()); + EXPECT_EQ("Coil:Cooling:Water", idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::CoolingCoilObjectType).get()); + EXPECT_EQ(coil.nameString(), idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::CoolingCoilName).get()); + EXPECT_EQ(idfCoil, idf_coilSystem.getTarget(CoilSystem_Cooling_WaterFields::CoolingCoilName).get()); + EXPECT_EQ("", idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::DehumidificationControlType).get()); + EXPECT_EQ("", idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::RunonSensibleLoad).get()); + EXPECT_EQ("", idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::RunonLatentLoad).get()); + EXPECT_EQ("", idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::MinimumAirToWaterTemperatureOffset).get()); + EXPECT_EQ("", idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::EconomizerLockout).get()); + EXPECT_EQ("", idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::MinimumWaterLoopTemperatureForHeatRecovery).get()); + EXPECT_EQ("", idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::CompanionCoilUsedForHeatRecovery).get()); } From 25ab778728b0471a6dee2c8d45618dbb4e5d549f Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Mon, 3 Feb 2025 10:55:48 -0700 Subject: [PATCH 19/58] Typo. --- src/energyplus/Test/CoilCoolingWater_GTest.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/energyplus/Test/CoilCoolingWater_GTest.cpp b/src/energyplus/Test/CoilCoolingWater_GTest.cpp index f1261e04daf..2114142dda9 100644 --- a/src/energyplus/Test/CoilCoolingWater_GTest.cpp +++ b/src/energyplus/Test/CoilCoolingWater_GTest.cpp @@ -143,8 +143,8 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilCoolingWater_AirLoopHVAC) { ASSERT_EQ(1u, idf_branch.extensibleGroups().size()); auto w_eg2 = idf_branch.extensibleGroups()[0].cast(); - EXPECT_EQ(w_eg2.getString(BranchExtensibleFields::ComponentInletNodeName).get(), coil.inletModelObject().get().nameString()); - EXPECT_EQ(w_eg2.getString(BranchExtensibleFields::ComponentOutletNodeName).get(), coil.outletModelObject().get().nameString()); + EXPECT_EQ(w_eg2.getString(BranchExtensibleFields::ComponentInletNodeName).get(), coil.airInletModelObject().get().nameString()); + EXPECT_EQ(w_eg2.getString(BranchExtensibleFields::ComponentOutletNodeName).get(), coil.airOutletModelObject().get().nameString()); EXPECT_EQ("CoilSystem:Cooling:Water", w_eg2.getString(BranchExtensibleFields::ComponentObjectType).get()); auto idf_coilSystem = w_eg2.getTarget(BranchExtensibleFields::ComponentName).get(); From c8248d64891ee7ae0a368b0fda4406d151e64fb1 Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Mon, 3 Feb 2025 12:28:19 -0700 Subject: [PATCH 20/58] Fix ft test. --- .../Test/CoilCoolingWater_GTest.cpp | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/energyplus/Test/CoilCoolingWater_GTest.cpp b/src/energyplus/Test/CoilCoolingWater_GTest.cpp index 2114142dda9..aec1e5f6b51 100644 --- a/src/energyplus/Test/CoilCoolingWater_GTest.cpp +++ b/src/energyplus/Test/CoilCoolingWater_GTest.cpp @@ -83,21 +83,21 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilCoolingWater_Unitary) { idfCoil.getString(Coil_Cooling_WaterFields::AirOutletNodeName).get()); EXPECT_EQ("My CoilCoolingWater", idfCoil.getString(Coil_Cooling_WaterFields::Name).get()); - EXPECT_EQ("", idfCoil.getString(Coil_Cooling_WaterFields::AvailabilityScheduleName).get()); - EXPECT_EQ(0.6, idfCoil.getDouble(Coil_Cooling_WaterFields::DesignWaterFlowRate).get()); - EXPECT_EQ(0.6, idfCoil.getDouble(Coil_Cooling_WaterFields::DesignAirFlowRate).get()); - EXPECT_EQ(0.6, idfCoil.getDouble(Coil_Cooling_WaterFields::DesignInletWaterTemperature).get()); - EXPECT_EQ(0.6, idfCoil.getDouble(Coil_Cooling_WaterFields::DesignInletAirTemperature).get()); - EXPECT_EQ(0.6, idfCoil.getDouble(Coil_Cooling_WaterFields::DesignInletAirHumidityRatio).get()); - EXPECT_EQ(0.6, idfCoil.getDouble(Coil_Cooling_WaterFields::DesignOutletAirHumidityRatio).get()); + EXPECT_EQ("Always On Discrete", idfCoil.getString(Coil_Cooling_WaterFields::AvailabilityScheduleName).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignWaterFlowRate).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignAirFlowRate).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignInletWaterTemperature).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignInletAirTemperature).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignInletAirHumidityRatio).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignOutletAirHumidityRatio).get()); EXPECT_EQ("Coil Water Inlet Node", idfCoil.getString(Coil_Cooling_WaterFields::WaterInletNodeName).get()); EXPECT_EQ("Coil Water Outlet Node", idfCoil.getString(Coil_Cooling_WaterFields::WaterOutletNodeName).get()); EXPECT_EQ("Coil Air Inlet Node", idfCoil.getString(Coil_Cooling_WaterFields::AirInletNodeName).get()); EXPECT_EQ("Coil Air Outlet Node", idfCoil.getString(Coil_Cooling_WaterFields::AirOutletNodeName).get()); - EXPECT_EQ("", idfCoil.getString(Coil_Cooling_WaterFields::TypeofAnalysis).get()); - EXPECT_EQ("", idfCoil.getString(Coil_Cooling_WaterFields::HeatExchangerConfiguration).get()); - EXPECT_EQ("", idfCoil.getString(Coil_Cooling_WaterFields::CondensateCollectionWaterStorageTankName).get()); - EXPECT_EQ(0.9, idfCoil.getDouble(Coil_Cooling_WaterFields::DesignWaterTemperatureDifference).get()); + EXPECT_EQ("SimpleAnalysis", idfCoil.getString(Coil_Cooling_WaterFields::TypeofAnalysis).get()); + EXPECT_EQ("CrossFlow", idfCoil.getString(Coil_Cooling_WaterFields::HeatExchangerConfiguration).get()); + EXPECT_TRUE(idfCoil.isEmpty(Coil_Cooling_WaterFields::CondensateCollectionWaterStorageTankName)); + EXPECT_TRUE(idfCoil.isEmpty(Coil_Cooling_WaterFields::DesignWaterTemperatureDifference)); } TEST_F(EnergyPlusFixture, ForwardTranslator_CoilCoolingWater_AirLoopHVAC) { @@ -157,11 +157,11 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilCoolingWater_AirLoopHVAC) { EXPECT_EQ("Coil:Cooling:Water", idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::CoolingCoilObjectType).get()); EXPECT_EQ(coil.nameString(), idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::CoolingCoilName).get()); EXPECT_EQ(idfCoil, idf_coilSystem.getTarget(CoilSystem_Cooling_WaterFields::CoolingCoilName).get()); - EXPECT_EQ("", idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::DehumidificationControlType).get()); - EXPECT_EQ("", idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::RunonSensibleLoad).get()); - EXPECT_EQ("", idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::RunonLatentLoad).get()); - EXPECT_EQ("", idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::MinimumAirToWaterTemperatureOffset).get()); - EXPECT_EQ("", idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::EconomizerLockout).get()); - EXPECT_EQ("", idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::MinimumWaterLoopTemperatureForHeatRecovery).get()); - EXPECT_EQ("", idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::CompanionCoilUsedForHeatRecovery).get()); + EXPECT_TRUE(idf_coilSystem.isEmpty(CoilSystem_Cooling_WaterFields::DehumidificationControlType)); + EXPECT_TRUE(idf_coilSystem.isEmpty(CoilSystem_Cooling_WaterFields::RunonSensibleLoad)); + EXPECT_TRUE(idf_coilSystem.isEmpty(CoilSystem_Cooling_WaterFields::RunonLatentLoad)); + EXPECT_TRUE(idf_coilSystem.isEmpty(CoilSystem_Cooling_WaterFields::MinimumAirToWaterTemperatureOffset)); + EXPECT_TRUE(idf_coilSystem.isEmpty(CoilSystem_Cooling_WaterFields::EconomizerLockout)); + EXPECT_TRUE(idf_coilSystem.isEmpty(CoilSystem_Cooling_WaterFields::MinimumWaterLoopTemperatureForHeatRecovery)); + EXPECT_TRUE(idf_coilSystem.isEmpty(CoilSystem_Cooling_WaterFields::CompanionCoilUsedForHeatRecovery)); } From 6d65d776bb8351780ea45e964448244dedf1a9f2 Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Mon, 3 Feb 2025 12:53:22 -0700 Subject: [PATCH 21/58] Separate coilsystem cooling water hx assisted ft into without unitary and coil system. --- src/energyplus/CMakeLists.txt | 1 + src/energyplus/ForwardTranslator.cpp | 8 +- .../ForwardTranslateCoilCoolingWater.cpp | 3 - ...ystemCoolingWaterHeatExchangerAssisted.cpp | 52 +++++- ...oolingWaterHeatExchangerAssisted_GTest.cpp | 156 ++++++++++++++++++ 5 files changed, 214 insertions(+), 6 deletions(-) create mode 100644 src/energyplus/Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp diff --git a/src/energyplus/CMakeLists.txt b/src/energyplus/CMakeLists.txt index 86c813f9da3..f9eb021abb8 100644 --- a/src/energyplus/CMakeLists.txt +++ b/src/energyplus/CMakeLists.txt @@ -717,6 +717,7 @@ set(${target_name}_test_src Test/CoilHeatingGasMultiStage_GTest.cpp Test/CoilHeatingWaterToAirHeatPumpEquationFit_GTest.cpp Test/CoilHeatingWaterToAirHeatPumpVariableSpeedEquationFit_GTest.cpp + Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest Test/CoilSystemIntegratedHeatPumpAirSource_GTest.cpp Test/CoilUserDefined_GTest.cpp Test/CoilWaterHeatingAirToWaterHeatPump_GTest.cpp diff --git a/src/energyplus/ForwardTranslator.cpp b/src/energyplus/ForwardTranslator.cpp index c9d8e628ed4..a2642334663 100644 --- a/src/energyplus/ForwardTranslator.cpp +++ b/src/energyplus/ForwardTranslator.cpp @@ -1212,8 +1212,12 @@ namespace energyplus { break; } case openstudio::IddObjectType::OS_CoilSystem_Cooling_Water_HeatExchangerAssisted: { - auto mo = modelObject.cast(); - retVal = translateCoilSystemCoolingWaterHeatExchangerAssisted(mo); + auto coil = modelObject.cast(); + if (isHVACComponentWithinUnitary(coil)) { + retVal = translateCoilSystemCoolingWaterHeatExchangerAssistedWithoutUnitary(coil); + } else { + retVal = translateCoilSystemCoolingWaterHeatExchangerAssisted(coil); + } break; } case openstudio::IddObjectType::OS_CoilSystem_Cooling_DX_HeatExchangerAssisted: { diff --git a/src/energyplus/ForwardTranslator/ForwardTranslateCoilCoolingWater.cpp b/src/energyplus/ForwardTranslator/ForwardTranslateCoilCoolingWater.cpp index 22a7314c3ab..744fd357b13 100644 --- a/src/energyplus/ForwardTranslator/ForwardTranslateCoilCoolingWater.cpp +++ b/src/energyplus/ForwardTranslator/ForwardTranslateCoilCoolingWater.cpp @@ -201,9 +201,6 @@ namespace energyplus { return coilSystemCoolingWaterIdf; } - //((Name)(Name)) - //((AvailabilityScheduleName)(Availability Schedule Name)) - } // namespace energyplus } // namespace openstudio diff --git a/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWaterHeatExchangerAssisted.cpp b/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWaterHeatExchangerAssisted.cpp index 3cd67ee19a2..32a7f3e0dea 100644 --- a/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWaterHeatExchangerAssisted.cpp +++ b/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWaterHeatExchangerAssisted.cpp @@ -42,7 +42,7 @@ namespace openstudio { namespace energyplus { boost::optional - ForwardTranslator::translateCoilSystemCoolingWaterHeatExchangerAssisted(CoilSystemCoolingWaterHeatExchangerAssisted& modelObject) { + ForwardTranslator::translateCoilSystemCoolingWaterHeatExchangerAssistedWithoutUnitary(CoilSystemCoolingWaterHeatExchangerAssisted& modelObject) { IdfObject idfObject = createRegisterAndNameIdfObject(openstudio::IddObjectType::CoilSystem_Cooling_Water_HeatExchangerAssisted, modelObject); @@ -157,5 +157,55 @@ namespace energyplus { return idfObject; } + boost::optional ForwardTranslator::translateCoilSystemCoolingWaterHeatExchangerAssisted(CoilCoolingWater& modelObject) { + IdfObject coilSystemCoolingWaterIdf(IddObjectType::CoilSystem_Cooling_Water); + + m_idfObjects.push_back(coilSystemCoolingWaterIdf); + + boost::optional oIdfObject = translateCoilSystemCoolingWaterHeatExchangerAssistedWithoutUnitary(modelObject); + + if (!oIdfObject) { + return boost::none; + } + + IdfObject idfObject = oIdfObject.get(); + + OptionalString s; + + s = modelObject.name(); + if (s) { + coilSystemCoolingWaterIdf.setString(CoilSystem_Cooling_WaterFields::CoolingCoilObjectType, idfObject.iddObject().name()); + + coilSystemCoolingWaterIdf.setString(CoilSystem_Cooling_WaterFields::CoolingCoilName, *s); + + coilSystemCoolingWaterIdf.setName(*s + " CoilSystem"); + } + + Schedule sched = modelObject.availabilitySchedule(); + translateAndMapModelObject(sched); + + coilSystemCoolingWaterIdf.setString(CoilSystem_Cooling_WaterFields::AvailabilityScheduleName, sched.name().get()); + + OptionalModelObject omo = modelObject.airInletModelObject(); + if (omo) { + translateAndMapModelObject(*omo); + s = omo->name(); + if (s) { + coilSystemCoolingWaterIdf.setString(CoilSystem_Cooling_WaterFields::AirInletNodeName, *s); + } + } + + omo = modelObject.airOutletModelObject(); + if (omo) { + translateAndMapModelObject(*omo); + s = omo->name(); + if (s) { + coilSystemCoolingWaterIdf.setString(CoilSystem_Cooling_WaterFields::AirOutletNodeName, *s); + } + } + + return coilSystemCoolingWaterIdf; + } + } // namespace energyplus } // namespace openstudio diff --git a/src/energyplus/Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp b/src/energyplus/Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp new file mode 100644 index 00000000000..645eefe875d --- /dev/null +++ b/src/energyplus/Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp @@ -0,0 +1,156 @@ +/*********************************************************************************************************************** +* 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/CoilSystemCoolingWaterHeatExchangerAssisted.hpp" +#include "../../model/CoilSystemCoolingWaterHeatExchangerAssisted_Impl.hpp" + +#include "../../model/AirLoopHVAC.hpp" +#include "../../model/AirLoopHVACUnitarySystem.hpp" +#include "../../model/Node.hpp" + +#include "../../utilities/idf/IdfObject.hpp" +#include "../../utilities/idf/IdfObject_Impl.hpp" +#include "../../utilities/idf/WorkspaceObject.hpp" +#include "../../utilities/idf/WorkspaceObject_Impl.hpp" +#include "../../utilities/idf/IdfExtensibleGroup.hpp" +#include "../../utilities/idf/WorkspaceExtensibleGroup.hpp" + +#include +#include +#include +#include +#include +#include +#include + +using namespace openstudio::energyplus; +using namespace openstudio::model; +using namespace openstudio; + +TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWaterHeatExchangerAssisted_Unitary) { + Model m; + CoilSystemCoolingWaterHeatExchangerAssisted coil(m); + coil.setName("My CoilSystemCoolingWaterHeatExchangerAssisted"); + + // put it inside a Unitary, and put Unitary on an AirLoopHVAC so it gets translated + AirLoopHVACUnitarySystem unitary(m); + unitary.setCoolingCoil(coil); + AirLoopHVAC airLoop(m); + Node supplyOutletNode = airLoop.supplyOutletNode(); + unitary.addToNode(supplyOutletNode); + ASSERT_TRUE(unitary.inletNode()); + EXPECT_TRUE(unitary.inletNode()->setName("Coil Air Inlet Node")); + ASSERT_TRUE(unitary.outletNode()); + EXPECT_TRUE(unitary.outletNode()->setName("Coil Air Outlet Node")); + + // They must be connected to a PlantLoop too + PlantLoop chw_p(m); + chw_p.addDemandBranchForComponent(coil); + coil.waterInletModelObject()->setName("Coil Water Inlet Node"); + coil.waterOutletModelObject()->setName("Coil Water Outlet Node"); + + ForwardTranslator ft; + Workspace w = ft.translateModel(m); + + WorkspaceObjectVector idfUnitarys(w.getObjectsByType(IddObjectType::AirLoopHVAC_UnitarySystem)); + ASSERT_EQ(1u, idfUnitarys.size()); + WorkspaceObject idfUnitary(idfUnitarys[0]); + + WorkspaceObjectVector idfCoils(w.getObjectsByType(IddObjectType::CoilSystem_Cooling_Water_HeatExchangerAssisted)); + ASSERT_EQ(1u, idfCoils.size()); + WorkspaceObject idfCoil(idfCoils[0]); + + // No CoilSystem:Cooling:DX wrapper needed, it's inside a unitary + EXPECT_EQ(0, w.getObjectsByType(IddObjectType::CoilSystem_Cooling_Water).size()); + + // Check that the Unitary ends up with the CoilSystemCoolingWaterHeatExchangerAssisted + EXPECT_EQ("CoilSystem:Cooling:Water:HeatExchangerAssisted", idfUnitary.getString(AirLoopHVAC_UnitarySystemFields::CoolingCoilObjectType).get()); + EXPECT_EQ(idfCoil.nameString(), idfUnitary.getString(AirLoopHVAC_UnitarySystemFields::CoolingCoilName).get()); + + // Since the Unitary only has a Cooling Coil (no fan, not HC / Suppl HC), the nodes should match + EXPECT_EQ(idfUnitary.getString(AirLoopHVAC_UnitarySystemFields::AirInletNodeName).get(), + idfCoil.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::AirInletNodeName).get()); + + EXPECT_EQ(idfUnitary.getString(AirLoopHVAC_UnitarySystemFields::AirOutletNodeName).get(), + idfCoil.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::AirOutletNodeName).get()); + + EXPECT_EQ("My CoilSystemCoolingWaterHeatExchangerAssisted", idfCoil.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::Name).get()); + EXPECT_EQ("HeatExchanger:AirToAir:SensibleAndLatent", idfCoil.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::HeatExchangerObjectType).get()); + EXPECT_EQ(coil.heatExchanger().nameString(), idfCoil.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::HeatExchangerName).get()); + EXPECT_EQ("Coil:Cooling:Water", idfCoil.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::CoolingCoilObjectType).get()); + EXPECT_EQ(coil.coolingCoil().nameString(), idfCoil.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::CoolingCoilName).get()); +} + +TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWaterHeatExchangerAssisted_AirLoopHVAC) { + Model m; + CoilSystemCoolingWaterHeatExchangerAssisted coil(m); + + // put it on an AirLoopHVAC + AirLoopHVAC airLoop(m); + Node supplyOutletNode = airLoop.supplyOutletNode(); + EXPECT_TRUE(coil.addToNode(supplyOutletNode)); + + // They must be connected to a PlantLoop too + PlantLoop chw_p(m); + chw_p.addDemandBranchForComponent(coil); + + ForwardTranslator ft; + Workspace w = ft.translateModel(m); + + WorkspaceObjectVector idfCoils(w.getObjectsByType(IddObjectType::Coil_Cooling_Water)); + ASSERT_EQ(1u, idfCoils.size()); + WorkspaceObject idfCoil(idfCoils[0]); + + EXPECT_EQ(idfCoil.getString(Coil_Cooling_WaterFields::WaterInletNodeName).get(), coil.waterInletModelObject().get().nameString()); + EXPECT_EQ(idfCoil.getString(Coil_Cooling_WaterFields::WaterOutletNodeName).get(), coil.waterOutletModelObject().get().nameString()); + EXPECT_EQ(idfCoil.getString(Coil_Cooling_WaterFields::AirInletNodeName).get(), coil.airInletModelObject().get().nameString()); + EXPECT_EQ(idfCoil.getString(Coil_Cooling_WaterFields::AirOutletNodeName).get(), coil.airOutletModelObject().get().nameString()); + + EXPECT_EQ(1, w.getObjectsByType(IddObjectType::CoilSystem_Cooling_Water).size()); + + // Go from AirLoopHVAC to BranchList to Branch + WorkspaceObjectVector idf_airloops = w.getObjectsByType(IddObjectType::AirLoopHVAC); + ASSERT_EQ(1u, idf_airloops.size()); + + WorkspaceObject& idf_airLoopHVAC = idf_airloops.front(); + WorkspaceObject idf_brlist = idf_airLoopHVAC.getTarget(AirLoopHVACFields::BranchListName).get(); + + // Should have one branch only + ASSERT_EQ(1u, idf_brlist.extensibleGroups().size()); + auto w_eg = idf_brlist.extensibleGroups()[0].cast(); + WorkspaceObject idf_branch = w_eg.getTarget(BranchListExtensibleFields::BranchName).get(); + + // There should be only one equipment on the branch + ASSERT_EQ(1u, idf_branch.extensibleGroups().size()); + auto w_eg2 = idf_branch.extensibleGroups()[0].cast(); + + EXPECT_EQ(w_eg2.getString(BranchExtensibleFields::ComponentInletNodeName).get(), coil.airInletModelObject().get().nameString()); + EXPECT_EQ(w_eg2.getString(BranchExtensibleFields::ComponentOutletNodeName).get(), coil.airOutletModelObject().get().nameString()); + + EXPECT_EQ("CoilSystem:Cooling:Water", w_eg2.getString(BranchExtensibleFields::ComponentObjectType).get()); + auto idf_coilSystem = w_eg2.getTarget(BranchExtensibleFields::ComponentName).get(); + // CoilSystem:Cooling:Water wrapper needed, it's not inside a unitary + EXPECT_EQ(1, w.getObjectsByType(IddObjectType::CoilSystem_Cooling_Water).size()); + + EXPECT_EQ(coil.airInletModelObject().get().nameString(), idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::AirInletNodeName).get()); + EXPECT_EQ(coil.airOutletModelObject().get().nameString(), idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::AirOutletNodeName).get()); + EXPECT_EQ("Always On Discrete", idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::AvailabilityScheduleName).get()); + EXPECT_EQ("CoilSystem:Cooling:Water:HeatExchangerAssisted", idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::CoolingCoilObjectType).get()); + EXPECT_EQ(coil.nameString(), idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::CoolingCoilName).get()); + EXPECT_EQ(idfCoil, idf_coilSystem.getTarget(CoilSystem_Cooling_WaterFields::CoolingCoilName).get()); + EXPECT_TRUE(idf_coilSystem.isEmpty(CoilSystem_Cooling_WaterFields::DehumidificationControlType)); + EXPECT_TRUE(idf_coilSystem.isEmpty(CoilSystem_Cooling_WaterFields::RunonSensibleLoad)); + EXPECT_TRUE(idf_coilSystem.isEmpty(CoilSystem_Cooling_WaterFields::RunonLatentLoad)); + EXPECT_TRUE(idf_coilSystem.isEmpty(CoilSystem_Cooling_WaterFields::MinimumAirToWaterTemperatureOffset)); + EXPECT_TRUE(idf_coilSystem.isEmpty(CoilSystem_Cooling_WaterFields::EconomizerLockout)); + EXPECT_TRUE(idf_coilSystem.isEmpty(CoilSystem_Cooling_WaterFields::MinimumWaterLoopTemperatureForHeatRecovery)); + EXPECT_TRUE(idf_coilSystem.isEmpty(CoilSystem_Cooling_WaterFields::CompanionCoilUsedForHeatRecovery)); +} From 63303d3a0a6246e8e7ee30b825573811f417fba2 Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Mon, 3 Feb 2025 12:53:37 -0700 Subject: [PATCH 22/58] Formatting. --- .../Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/energyplus/Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp b/src/energyplus/Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp index 645eefe875d..eaf8ee7d2e7 100644 --- a/src/energyplus/Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp +++ b/src/energyplus/Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp @@ -83,7 +83,8 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWaterHeatExchangerA idfCoil.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::AirOutletNodeName).get()); EXPECT_EQ("My CoilSystemCoolingWaterHeatExchangerAssisted", idfCoil.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::Name).get()); - EXPECT_EQ("HeatExchanger:AirToAir:SensibleAndLatent", idfCoil.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::HeatExchangerObjectType).get()); + EXPECT_EQ("HeatExchanger:AirToAir:SensibleAndLatent", + idfCoil.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::HeatExchangerObjectType).get()); EXPECT_EQ(coil.heatExchanger().nameString(), idfCoil.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::HeatExchangerName).get()); EXPECT_EQ("Coil:Cooling:Water", idfCoil.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::CoolingCoilObjectType).get()); EXPECT_EQ(coil.coolingCoil().nameString(), idfCoil.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::CoolingCoilName).get()); From 74b017a8f96990dfcf332fa3042b145107ce3feb Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Mon, 3 Feb 2025 12:57:15 -0700 Subject: [PATCH 23/58] Typo in cmakelists. --- src/energyplus/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/energyplus/CMakeLists.txt b/src/energyplus/CMakeLists.txt index f9eb021abb8..48f956fd4c0 100644 --- a/src/energyplus/CMakeLists.txt +++ b/src/energyplus/CMakeLists.txt @@ -717,7 +717,7 @@ set(${target_name}_test_src Test/CoilHeatingGasMultiStage_GTest.cpp Test/CoilHeatingWaterToAirHeatPumpEquationFit_GTest.cpp Test/CoilHeatingWaterToAirHeatPumpVariableSpeedEquationFit_GTest.cpp - Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest + Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp Test/CoilSystemIntegratedHeatPumpAirSource_GTest.cpp Test/CoilUserDefined_GTest.cpp Test/CoilWaterHeatingAirToWaterHeatPump_GTest.cpp From 46da7e46f8e098a33675b48439e12b5894f9e848 Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Mon, 3 Feb 2025 13:52:49 -0700 Subject: [PATCH 24/58] Few typos in new ft. --- src/energyplus/ForwardTranslator.hpp | 3 +++ ...anslateCoilSystemCoolingWaterHeatExchangerAssisted.cpp | 8 +++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/energyplus/ForwardTranslator.hpp b/src/energyplus/ForwardTranslator.hpp index a77586f1af1..c22eb2e5fae 100644 --- a/src/energyplus/ForwardTranslator.hpp +++ b/src/energyplus/ForwardTranslator.hpp @@ -846,6 +846,9 @@ namespace energyplus { boost::optional translateCoilSystemCoolingWaterHeatExchangerAssisted(model::CoilSystemCoolingWaterHeatExchangerAssisted& modelObject); + boost::optional + translateCoilSystemCoolingWaterHeatExchangerAssistedWithoutUnitary(model::CoilSystemCoolingWaterHeatExchangerAssisted& modelObject); + boost::optional translateCoilSystemIntegratedHeatPumpAirSource(model::CoilSystemIntegratedHeatPumpAirSource& modelObject); boost::optional translateCoilUserDefined(model::CoilUserDefined& modelObject); diff --git a/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWaterHeatExchangerAssisted.cpp b/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWaterHeatExchangerAssisted.cpp index 32a7f3e0dea..c26171176ff 100644 --- a/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWaterHeatExchangerAssisted.cpp +++ b/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWaterHeatExchangerAssisted.cpp @@ -27,6 +27,7 @@ #include "../../model/Model.hpp" #include "../../utilities/core/Assert.hpp" +#include #include #include #include @@ -41,8 +42,8 @@ namespace openstudio { namespace energyplus { - boost::optional - ForwardTranslator::translateCoilSystemCoolingWaterHeatExchangerAssistedWithoutUnitary(CoilSystemCoolingWaterHeatExchangerAssisted& modelObject) { + boost::optional ForwardTranslator::translateCoilSystemCoolingWaterHeatExchangerAssistedWithoutUnitary( + model::CoilSystemCoolingWaterHeatExchangerAssisted& modelObject) { IdfObject idfObject = createRegisterAndNameIdfObject(openstudio::IddObjectType::CoilSystem_Cooling_Water_HeatExchangerAssisted, modelObject); @@ -157,7 +158,8 @@ namespace energyplus { return idfObject; } - boost::optional ForwardTranslator::translateCoilSystemCoolingWaterHeatExchangerAssisted(CoilCoolingWater& modelObject) { + boost::optional + ForwardTranslator::translateCoilSystemCoolingWaterHeatExchangerAssisted(CoilSystemCoolingWaterHeatExchangerAssisted& modelObject) { IdfObject coilSystemCoolingWaterIdf(IddObjectType::CoilSystem_Cooling_Water); m_idfObjects.push_back(coilSystemCoolingWaterIdf); From 451c46601ba25d97787c402b5d0f249e9704fbf1 Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Mon, 3 Feb 2025 14:05:19 -0700 Subject: [PATCH 25/58] Update new ft. --- ...nslateCoilSystemCoolingWaterHeatExchangerAssisted.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWaterHeatExchangerAssisted.cpp b/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWaterHeatExchangerAssisted.cpp index c26171176ff..0197e59eb19 100644 --- a/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWaterHeatExchangerAssisted.cpp +++ b/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWaterHeatExchangerAssisted.cpp @@ -183,12 +183,7 @@ namespace energyplus { coilSystemCoolingWaterIdf.setName(*s + " CoilSystem"); } - Schedule sched = modelObject.availabilitySchedule(); - translateAndMapModelObject(sched); - - coilSystemCoolingWaterIdf.setString(CoilSystem_Cooling_WaterFields::AvailabilityScheduleName, sched.name().get()); - - OptionalModelObject omo = modelObject.airInletModelObject(); + OptionalModelObject omo = modelObject.inletModelObject(); if (omo) { translateAndMapModelObject(*omo); s = omo->name(); @@ -197,7 +192,7 @@ namespace energyplus { } } - omo = modelObject.airOutletModelObject(); + omo = modelObject.outletModelObject(); if (omo) { translateAndMapModelObject(*omo); s = omo->name(); From 9aa1aa3b4e4af877603d664fafd824407fdfae12 Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Mon, 3 Feb 2025 14:16:45 -0700 Subject: [PATCH 26/58] Another typo in ft. --- .../Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/energyplus/Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp b/src/energyplus/Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp index eaf8ee7d2e7..1719d478456 100644 --- a/src/energyplus/Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp +++ b/src/energyplus/Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp @@ -23,7 +23,7 @@ #include "../../utilities/idf/IdfExtensibleGroup.hpp" #include "../../utilities/idf/WorkspaceExtensibleGroup.hpp" -#include +#include #include #include #include From 62a9ef5e3dfe4458e5b90ffe153c54865654bbfb Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Tue, 4 Feb 2025 11:45:47 -0700 Subject: [PATCH 27/58] Special case for coilsystem ft on plant loop branch. --- .../ForwardTranslatePlantLoop.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/energyplus/ForwardTranslator/ForwardTranslatePlantLoop.cpp b/src/energyplus/ForwardTranslator/ForwardTranslatePlantLoop.cpp index a3dc363a531..86be1a75318 100644 --- a/src/energyplus/ForwardTranslator/ForwardTranslatePlantLoop.cpp +++ b/src/energyplus/ForwardTranslator/ForwardTranslatePlantLoop.cpp @@ -76,6 +76,8 @@ #include "../../model/CoilCoolingCooledBeam_Impl.hpp" #include "../../model/CoilCoolingFourPipeBeam.hpp" #include "../../model/CoilCoolingFourPipeBeam_Impl.hpp" +#include "../../model/CoilCoolingWater.hpp" +#include "../../model/CoilCoolingWater_Impl.hpp" #include "../../model/CoilHeatingFourPipeBeam.hpp" #include "../../model/CoilHeatingFourPipeBeam_Impl.hpp" #include "../../model/StraightComponent.hpp" @@ -116,6 +118,7 @@ #include #include #include +#include #include "../../utilities/core/Assert.hpp" using namespace openstudio::model; @@ -300,6 +303,17 @@ namespace energyplus { if (loop.optionalCast()) { inletNode = waterToAirComponent->waterInletModelObject()->optionalCast(); outletNode = waterToAirComponent->waterOutletModelObject()->optionalCast(); + // Special case for Coil:Cooling:Water. + if (boost::optional ccw = modelObject.optionalCast()) { + boost::optional idfCoil = this->translateAndMapModelObject(*ccw); + if (idfCoil) { + if (idfCoil->iddObject().type() == IddObjectType::CoilSystem_Cooling_Water) { + //Get the name and idd type of the coil cooling water inside the coil system + objectName = idfCoil->getString(CoilSystem_Cooling_WaterFields::CoolingCoilName).get(); + iddType = idfCoil->getString(CoilSystem_Cooling_WaterFields::CoolingCoilObjectType).get(); + } + } + } } else { inletNode = waterToAirComponent->airInletModelObject()->optionalCast(); outletNode = waterToAirComponent->airOutletModelObject()->optionalCast(); From a7399734d24cf2da2fd93cb12d7ee1b5cb3d2ef7 Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Tue, 4 Feb 2025 11:45:55 -0700 Subject: [PATCH 28/58] Fix and update ft tests. --- .../Test/CoilCoolingWater_GTest.cpp | 2 +- ...oolingWaterHeatExchangerAssisted_GTest.cpp | 38 ++++++++++--------- 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/src/energyplus/Test/CoilCoolingWater_GTest.cpp b/src/energyplus/Test/CoilCoolingWater_GTest.cpp index aec1e5f6b51..52e440931b4 100644 --- a/src/energyplus/Test/CoilCoolingWater_GTest.cpp +++ b/src/energyplus/Test/CoilCoolingWater_GTest.cpp @@ -68,7 +68,7 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilCoolingWater_Unitary) { ASSERT_EQ(1u, idfCoils.size()); WorkspaceObject idfCoil(idfCoils[0]); - // No CoilSystem:Cooling:DX wrapper needed, it's inside a unitary + // No CoilSystem:Cooling:Water wrapper needed, it's inside a unitary EXPECT_EQ(0, w.getObjectsByType(IddObjectType::CoilSystem_Cooling_Water).size()); // Check that the Unitary ends up with the CoilCoolingWater diff --git a/src/energyplus/Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp b/src/energyplus/Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp index 1719d478456..7b43b17c568 100644 --- a/src/energyplus/Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp +++ b/src/energyplus/Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp @@ -11,6 +11,10 @@ #include "../../model/Model.hpp" #include "../../model/CoilSystemCoolingWaterHeatExchangerAssisted.hpp" #include "../../model/CoilSystemCoolingWaterHeatExchangerAssisted_Impl.hpp" +#include "../../model/CoilCoolingWater.hpp" +#include "../../model/CoilCoolingWater_Impl.hpp" +#include "../../model/HeatExchangerAirToAirSensibleAndLatent.hpp" +#include "../../model/HeatExchangerAirToAirSensibleAndLatent_Impl.hpp" #include "../../model/AirLoopHVAC.hpp" #include "../../model/AirLoopHVACUnitarySystem.hpp" @@ -25,6 +29,7 @@ #include #include +#include #include #include #include @@ -53,9 +58,7 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWaterHeatExchangerA // They must be connected to a PlantLoop too PlantLoop chw_p(m); - chw_p.addDemandBranchForComponent(coil); - coil.waterInletModelObject()->setName("Coil Water Inlet Node"); - coil.waterOutletModelObject()->setName("Coil Water Outlet Node"); + chw_p.addDemandBranchForComponent(coil.coolingCoil()); ForwardTranslator ft; Workspace w = ft.translateModel(m); @@ -68,7 +71,11 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWaterHeatExchangerA ASSERT_EQ(1u, idfCoils.size()); WorkspaceObject idfCoil(idfCoils[0]); - // No CoilSystem:Cooling:DX wrapper needed, it's inside a unitary + WorkspaceObjectVector idfHXs(w.getObjectsByType(IddObjectType::HeatExchanger_AirToAir_SensibleAndLatent)); + ASSERT_EQ(1u, idfHXs.size()); + WorkspaceObject idfHX(idfHXs[0]); + + // No CoilSystem:Cooling:Water wrapper needed, it's inside a unitary EXPECT_EQ(0, w.getObjectsByType(IddObjectType::CoilSystem_Cooling_Water).size()); // Check that the Unitary ends up with the CoilSystemCoolingWaterHeatExchangerAssisted @@ -77,10 +84,10 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWaterHeatExchangerA // Since the Unitary only has a Cooling Coil (no fan, not HC / Suppl HC), the nodes should match EXPECT_EQ(idfUnitary.getString(AirLoopHVAC_UnitarySystemFields::AirInletNodeName).get(), - idfCoil.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::AirInletNodeName).get()); + idfHX.getString(HeatExchanger_AirToAir_SensibleAndLatentFields::SupplyAirInletNodeName).get()); EXPECT_EQ(idfUnitary.getString(AirLoopHVAC_UnitarySystemFields::AirOutletNodeName).get(), - idfCoil.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::AirOutletNodeName).get()); + idfHX.getString(HeatExchanger_AirToAir_SensibleAndLatentFields::ExhaustAirOutletNodeName).get()); EXPECT_EQ("My CoilSystemCoolingWaterHeatExchangerAssisted", idfCoil.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::Name).get()); EXPECT_EQ("HeatExchanger:AirToAir:SensibleAndLatent", @@ -101,20 +108,15 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWaterHeatExchangerA // They must be connected to a PlantLoop too PlantLoop chw_p(m); - chw_p.addDemandBranchForComponent(coil); + chw_p.addDemandBranchForComponent(coil.coolingCoil()); ForwardTranslator ft; Workspace w = ft.translateModel(m); - WorkspaceObjectVector idfCoils(w.getObjectsByType(IddObjectType::Coil_Cooling_Water)); + WorkspaceObjectVector idfCoils(w.getObjectsByType(IddObjectType::CoilSystem_Cooling_Water_HeatExchangerAssisted)); ASSERT_EQ(1u, idfCoils.size()); WorkspaceObject idfCoil(idfCoils[0]); - EXPECT_EQ(idfCoil.getString(Coil_Cooling_WaterFields::WaterInletNodeName).get(), coil.waterInletModelObject().get().nameString()); - EXPECT_EQ(idfCoil.getString(Coil_Cooling_WaterFields::WaterOutletNodeName).get(), coil.waterOutletModelObject().get().nameString()); - EXPECT_EQ(idfCoil.getString(Coil_Cooling_WaterFields::AirInletNodeName).get(), coil.airInletModelObject().get().nameString()); - EXPECT_EQ(idfCoil.getString(Coil_Cooling_WaterFields::AirOutletNodeName).get(), coil.airOutletModelObject().get().nameString()); - EXPECT_EQ(1, w.getObjectsByType(IddObjectType::CoilSystem_Cooling_Water).size()); // Go from AirLoopHVAC to BranchList to Branch @@ -133,17 +135,17 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWaterHeatExchangerA ASSERT_EQ(1u, idf_branch.extensibleGroups().size()); auto w_eg2 = idf_branch.extensibleGroups()[0].cast(); - EXPECT_EQ(w_eg2.getString(BranchExtensibleFields::ComponentInletNodeName).get(), coil.airInletModelObject().get().nameString()); - EXPECT_EQ(w_eg2.getString(BranchExtensibleFields::ComponentOutletNodeName).get(), coil.airOutletModelObject().get().nameString()); + EXPECT_EQ(w_eg2.getString(BranchExtensibleFields::ComponentInletNodeName).get(), coil.inletModelObject().get().nameString()); + EXPECT_EQ(w_eg2.getString(BranchExtensibleFields::ComponentOutletNodeName).get(), coil.outletModelObject().get().nameString()); EXPECT_EQ("CoilSystem:Cooling:Water", w_eg2.getString(BranchExtensibleFields::ComponentObjectType).get()); auto idf_coilSystem = w_eg2.getTarget(BranchExtensibleFields::ComponentName).get(); // CoilSystem:Cooling:Water wrapper needed, it's not inside a unitary EXPECT_EQ(1, w.getObjectsByType(IddObjectType::CoilSystem_Cooling_Water).size()); - EXPECT_EQ(coil.airInletModelObject().get().nameString(), idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::AirInletNodeName).get()); - EXPECT_EQ(coil.airOutletModelObject().get().nameString(), idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::AirOutletNodeName).get()); - EXPECT_EQ("Always On Discrete", idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::AvailabilityScheduleName).get()); + EXPECT_EQ(coil.inletModelObject().get().nameString(), idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::AirInletNodeName).get()); + EXPECT_EQ(coil.outletModelObject().get().nameString(), idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::AirOutletNodeName).get()); + EXPECT_TRUE(idf_coilSystem.isEmpty(CoilSystem_Cooling_WaterFields::AvailabilityScheduleName)); EXPECT_EQ("CoilSystem:Cooling:Water:HeatExchangerAssisted", idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::CoolingCoilObjectType).get()); EXPECT_EQ(coil.nameString(), idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::CoolingCoilName).get()); EXPECT_EQ(idfCoil, idf_coilSystem.getTarget(CoilSystem_Cooling_WaterFields::CoolingCoilName).get()); From 82f9c0fc00f2ea071b3e49dcd7398188190abd13 Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Tue, 18 Mar 2025 09:52:48 -0700 Subject: [PATCH 29/58] Check for ControllerWaterCoil in ft tests. --- src/energyplus/Test/CoilCoolingWater_GTest.cpp | 7 +++++++ .../CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/src/energyplus/Test/CoilCoolingWater_GTest.cpp b/src/energyplus/Test/CoilCoolingWater_GTest.cpp index 52e440931b4..453f0822e8a 100644 --- a/src/energyplus/Test/CoilCoolingWater_GTest.cpp +++ b/src/energyplus/Test/CoilCoolingWater_GTest.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include using namespace openstudio::energyplus; @@ -98,6 +99,9 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilCoolingWater_Unitary) { EXPECT_EQ("CrossFlow", idfCoil.getString(Coil_Cooling_WaterFields::HeatExchangerConfiguration).get()); EXPECT_TRUE(idfCoil.isEmpty(Coil_Cooling_WaterFields::CondensateCollectionWaterStorageTankName)); EXPECT_TRUE(idfCoil.isEmpty(Coil_Cooling_WaterFields::DesignWaterTemperatureDifference)); + + // Check Controller:WaterCoil created by coil.addToNode + EXPECT_EQ(0, w.getObjectsByType(IddObjectType::Controller_WaterCoil).size()); } TEST_F(EnergyPlusFixture, ForwardTranslator_CoilCoolingWater_AirLoopHVAC) { @@ -164,4 +168,7 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilCoolingWater_AirLoopHVAC) { EXPECT_TRUE(idf_coilSystem.isEmpty(CoilSystem_Cooling_WaterFields::EconomizerLockout)); EXPECT_TRUE(idf_coilSystem.isEmpty(CoilSystem_Cooling_WaterFields::MinimumWaterLoopTemperatureForHeatRecovery)); EXPECT_TRUE(idf_coilSystem.isEmpty(CoilSystem_Cooling_WaterFields::CompanionCoilUsedForHeatRecovery)); + + // Check Controller:WaterCoil created by coil.addToNode + EXPECT_EQ(1, w.getObjectsByType(IddObjectType::Controller_WaterCoil).size()); } diff --git a/src/energyplus/Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp b/src/energyplus/Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp index 7b43b17c568..a54ff0812b8 100644 --- a/src/energyplus/Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp +++ b/src/energyplus/Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include using namespace openstudio::energyplus; @@ -95,6 +96,9 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWaterHeatExchangerA EXPECT_EQ(coil.heatExchanger().nameString(), idfCoil.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::HeatExchangerName).get()); EXPECT_EQ("Coil:Cooling:Water", idfCoil.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::CoolingCoilObjectType).get()); EXPECT_EQ(coil.coolingCoil().nameString(), idfCoil.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::CoolingCoilName).get()); + + // Check Controller:WaterCoil created by coil.addToNode + EXPECT_EQ(0, w.getObjectsByType(IddObjectType::Controller_WaterCoil).size()); } TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWaterHeatExchangerAssisted_AirLoopHVAC) { @@ -156,4 +160,7 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWaterHeatExchangerA EXPECT_TRUE(idf_coilSystem.isEmpty(CoilSystem_Cooling_WaterFields::EconomizerLockout)); EXPECT_TRUE(idf_coilSystem.isEmpty(CoilSystem_Cooling_WaterFields::MinimumWaterLoopTemperatureForHeatRecovery)); EXPECT_TRUE(idf_coilSystem.isEmpty(CoilSystem_Cooling_WaterFields::CompanionCoilUsedForHeatRecovery)); + + // Check Controller:WaterCoil created by coil.addToNode + EXPECT_EQ(1, w.getObjectsByType(IddObjectType::Controller_WaterCoil).size()); } From 16c916c6c8283b513a511382c59d455c36360a1f Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Tue, 18 Mar 2025 11:13:27 -0700 Subject: [PATCH 30/58] Clean up and update test. --- .../CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp | 8 +++++++- src/model/CoilCoolingWater.cpp | 4 ---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/energyplus/Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp b/src/energyplus/Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp index a54ff0812b8..6ed8a796fdc 100644 --- a/src/energyplus/Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp +++ b/src/energyplus/Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp @@ -98,7 +98,13 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWaterHeatExchangerA EXPECT_EQ(coil.coolingCoil().nameString(), idfCoil.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::CoolingCoilName).get()); // Check Controller:WaterCoil created by coil.addToNode - EXPECT_EQ(0, w.getObjectsByType(IddObjectType::Controller_WaterCoil).size()); + EXPECT_EQ(1, w.getObjectsByType(IddObjectType::Controller_WaterCoil).size()); // why is this 1? + + WorkspaceObjectVector idfControllers(w.getObjectsByType(IddObjectType::Controller_WaterCoil)); + ASSERT_EQ(1u, idfControllers.size()); + WorkspaceObject idfController(idfControllers[0]); + + EXPECT_EQ("", idfController.getString(Controller_WaterCoilFields::Name).get()); } TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWaterHeatExchangerAssisted_AirLoopHVAC) { diff --git a/src/model/CoilCoolingWater.cpp b/src/model/CoilCoolingWater.cpp index e7d9d0af19f..4b5d5292cb8 100644 --- a/src/model/CoilCoolingWater.cpp +++ b/src/model/CoilCoolingWater.cpp @@ -134,7 +134,6 @@ namespace model { bool CoilCoolingWater_Impl::setDesignAirFlowRate(double value) { return setDouble(openstudio::OS_Coil_Cooling_WaterFields::DesignAirFlowRate, value); - ; } bool CoilCoolingWater_Impl::isDesignAirFlowRateAutosized() { @@ -156,7 +155,6 @@ namespace model { bool CoilCoolingWater_Impl::setDesignInletWaterTemperature(double value) { return setDouble(openstudio::OS_Coil_Cooling_WaterFields::DesignInletWaterTemperature, value); - ; } bool CoilCoolingWater_Impl::isDesignInletWaterTemperatureAutosized() { @@ -266,7 +264,6 @@ namespace model { bool CoilCoolingWater_Impl::setTypeOfAnalysis(const std::string& value) { return setString(openstudio::OS_Coil_Cooling_WaterFields::TypeofAnalysis, value); - ; } std::string CoilCoolingWater_Impl::heatExchangerConfiguration() { @@ -275,7 +272,6 @@ namespace model { bool CoilCoolingWater_Impl::setHeatExchangerConfiguration(const std::string& value) { return setString(openstudio::OS_Coil_Cooling_WaterFields::HeatExchangerConfiguration, value); - ; } bool CoilCoolingWater_Impl::addToNode(Node& node) { From ded5355ff30c0672449750bc5e7f628470d8d66b Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Wed, 19 Mar 2025 11:22:23 -0700 Subject: [PATCH 31/58] Add CoilSystemCoolingWater to idd. --- resources/model/OpenStudio.idd | 98 ++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/resources/model/OpenStudio.idd b/resources/model/OpenStudio.idd index 332f335af70..363b72b9d2d 100644 --- a/resources/model/OpenStudio.idd +++ b/resources/model/OpenStudio.idd @@ -18981,6 +18981,104 @@ OS:Coil:Cooling:DX:TwoSpeed, \type object-list \object-list ScheduleNames +OS:CoilSystem:Cooling:Water, + \memo Virtual container component that consists of a water cooling coil + \memo and its associated controls. This control object supports the + \memo available water coil types and may be placed directly on an + \memo air loop branch or in an outdoor air equipment list. + \min-fields 12 + A1, \field Handle + \type handle + \required-field + A2, \field Name + \required-field + \reference ConnectionObject + A3, \field Air Inlet Node Name + \type object-list + \required-field + \object-list ConnectionNames + A4, \field Air Outlet Node Name + \type object-list + \required-field + \object-list ConnectionNames + A5, \field Availability Schedule Name + \note Availability schedule name for this system. Schedule value > 0 + \note means the system is available. + \note If this field is blank, the system is always available. + \type object-list + \object-list ScheduleNames + \required-field + A6, \field Cooling Coil + \required-field + \type object-list + \object-list CoolingCoilsWater + A7, \field Dehumidification Control Type + \type choice + \key None + \key Multimode + \key CoolReheat + \required-field + \note None = meet sensible load only. Valid with all cooling coil types. When a heat + \note exchanger assisted cooling coil is used, the heat exchanger is locked on at all times. + \note Multimode = activate water coil and meet sensible load. If no sensible load exists, + \note and Run on Latent Load = Yes, and a latent load exists, the coil will operate to meet + \note the latent load. If the latent load cannot be met the heat exchanger will be activated. + \note Valid only with cooling coil type CoilSystem:Cooling:Water:HeatExchangerAssisted. + \note CoolReheat = cool beyond the dry-bulb setpoint as required to meet the humidity setpoint. + \note Valid with all cooling coil types. When a heat exchanger assisted cooling coil is used, + \note the heat exchanger is locked on at all times. + \note For all dehumidification controls, the max humidity setpoint on the Sensor Node is used. + \note SetpointManager:SingleZone:Humidity:Maximum, + \note SetpointManager:MultiZone:Humidity:Maximum, or + \note SetpointManager:MultiZone:MaximumHumidity:Average, and + \note SetpointManager:OutdoorAirPretreat (optional) objects. + A8, \field Run on Sensible Load + \type choice + \key Yes + \key No + \required-field + \note If Yes, unit will run if there is a sensible load. + \note If No, unit will not run if there is only a sensible load. + \note Dehumidification controls will be active if specified. + A9, \field Run on Latent Load + \type choice + \key Yes + \key No + \required-field + \note If Yes, unit will run if there is a latent load. + \note even if there is no sensible load. + \note If No, unit will not run if there is only a latent load. + \note Dehumidification controls will be active if specified. + N1, \field Minimum Air To Water Temperature Offset + \note Coil will turn on as required when inlet air temperature is above + \note water temperature by amount of offset. To model a waterside + \note economizer connect to condenser loop and increase offset as desired. + \type real + \units deltaC + \minimum 0.0 + \required-field + A10, \field Economizer Lockout + \type choice + \key Yes + \key No + \required-field + \note Yes means that the heat exchanger will be locked out (off) + N2, \field Minimum Water Loop Temperature For Heat Recovery + \note Only used for heat recovery loops. + \note Loop will turn off below this temperature. + \type real + \units C + \required-field + A11; \field Companion Coil Used For Heat Recovery + \note Only used for heat recovery loops. + \note Entering a coil name indicates a heat recovery loop is specified. + \note Coil listed is connected in series with this objects coil on demand side + \note branch of a plant loop. A dedicated plant loop with no supply side + \note equipment, other than a pump, is currently required. + \note Only Coil:Cooling:Water coil type is currently allowed for heat recovery loops. + \type object-list + \object-list CoolingCoilsWater + OS:CoilSystem:Cooling:Water:HeatExchangerAssisted, \memo Virtual component consisting of a chilled-water cooling coil and an air-to-air heat \memo exchanger. The air-to-air heat exchanger precools the air entering the cooling coil From 6591034ffd70858d43c47d64b48ea1f85a52c28d Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Wed, 19 Mar 2025 11:22:41 -0700 Subject: [PATCH 32/58] First add of CoilSystemCoolingWater src files. --- ...ForwardTranslateCoilSystemCoolingWater.cpp | 120 ++++++ .../Test/CoilSystemCoolingWater_GTest.cpp | 84 ++++ src/model/CoilSystemCoolingWater.cpp | 371 ++++++++++++++++++ src/model/CoilSystemCoolingWater.hpp | 142 +++++++ src/model/CoilSystemCoolingWater_Impl.hpp | 141 +++++++ src/model/ScheduleTypeRegistry.cpp | 1 + .../test/CoilSystemCoolingWater_GTest.cpp | 106 +++++ 7 files changed, 965 insertions(+) create mode 100644 src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWater.cpp create mode 100644 src/energyplus/Test/CoilSystemCoolingWater_GTest.cpp create mode 100644 src/model/CoilSystemCoolingWater.cpp create mode 100644 src/model/CoilSystemCoolingWater.hpp create mode 100644 src/model/CoilSystemCoolingWater_Impl.hpp create mode 100644 src/model/test/CoilSystemCoolingWater_GTest.cpp diff --git a/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWater.cpp b/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWater.cpp new file mode 100644 index 00000000000..539b1be0276 --- /dev/null +++ b/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWater.cpp @@ -0,0 +1,120 @@ +/*********************************************************************************************************************** +* OpenStudio(R), Copyright (c) Alliance for Sustainable Energy, LLC. +* See also https://openstudio.net/license +***********************************************************************************************************************/ + +#include "../ForwardTranslator.hpp" +#include "../../model/Model.hpp" + +#include "../../model/CoilSystemCoolingWater.hpp" + +// TODO: Check the following class names against object getters and setters. +#include "../../model/Node.hpp" +#include "../../model/Node_Impl.hpp" + +#include "../../model/Schedule.hpp" +#include "../../model/Schedule_Impl.hpp" + +#include "../../model/CoolingCoilsWater.hpp" +#include "../../model/CoolingCoilsWater_Impl.hpp" + +#include +#include + +using namespace openstudio::model; + +namespace openstudio { + +namespace energyplus { + + boost::optional ForwardTranslator::translateCoilSystemCoolingWater(model::CoilSystemCoolingWater& modelObject) { + + // Instantiate an IdfObject of the class to store the values + IdfObject idfObject = createRegisterAndNameIdfObject(openstudio::IddObjectType::CoilSystem_Cooling_Water, modelObject); + // If it doesn't have a name, or if you aren't sure you are going to want to return it + // IdfObject idfObject(openstudio::IddObjectType::CoilSystem_Cooling_Water); + // m_idfObjects.push_back(idfObject); + + // TODO: Note JM 2018-10-17 + // You are responsible for implementing any additional logic based on choice fields, etc. + // The ForwardTranslator generator script is meant to facilitate your work, not get you 100% of the way + + // TODO: If you keep createRegisterAndNameIdfObject above, you don't need this. + // But in some cases, you'll want to handle failure without pushing to the map + // Name + idfObject.setName(modelObject.nameString()); + + // Air Inlet Node Name: Required Node + Node airInletNodeName = modelObject.airInletNodeName(); + if (boost::optional wo_ = translateAndMapModelObject(airInletNodeName)) { + idfObject.setString(CoilSystem_Cooling_WaterFields::AirInletNodeName, wo_->nameString()); + } + + // Air Outlet Node Name: Required Node + Node airOutletNodeName = modelObject.airOutletNodeName(); + if (boost::optional wo_ = translateAndMapModelObject(airOutletNodeName)) { + idfObject.setString(CoilSystem_Cooling_WaterFields::AirOutletNodeName, wo_->nameString()); + } + + // Availability Schedule Name: Optional Object + if (boost::optional availabilitySchedule_ = modelObject.availabilitySchedule()) { + if (boost::optional wo_ = translateAndMapModelObject(availabilitySchedule_.get())) { + idfObject.setString(CoilSystem_Cooling_WaterFields::AvailabilityScheduleName, wo_->nameString()); + } + } + + // Cooling Coil Object Type: Required String + const std::string coolingCoilObjectType = modelObject.coolingCoilObjectType(); + idfObject.setString(CoilSystem_Cooling_WaterFields::CoolingCoilObjectType, coolingCoilObjectType); + + // Cooling Coil Name: Required Object + CoolingCoilsWater coolingCoil = modelObject.coolingCoil(); + if (boost::optional wo_ = translateAndMapModelObject(coolingCoil)) { + idfObject.setString(CoilSystem_Cooling_WaterFields::CoolingCoilName, wo_->nameString()); + } + + // Dehumidification Control Type: Optional String + const std::string dehumidificationControlType = modelObject.dehumidificationControlType(); + idfObject.setString(CoilSystem_Cooling_WaterFields::DehumidificationControlType, dehumidificationControlType); + + // Run on Sensible Load: Optional Boolean + if (modelObject.runonSensibleLoad()) { + idfObject.setString(CoilSystem_Cooling_WaterFields::RunonSensibleLoad, "Yes"); + } else { + idfObject.setString(CoilSystem_Cooling_WaterFields::RunonSensibleLoad, "No"); + } + + // Run on Latent Load: Optional Boolean + if (modelObject.runonLatentLoad()) { + idfObject.setString(CoilSystem_Cooling_WaterFields::RunonLatentLoad, "Yes"); + } else { + idfObject.setString(CoilSystem_Cooling_WaterFields::RunonLatentLoad, "No"); + } + + // Minimum Air To Water Temperature Offset: Optional Double + const double minimumAirToWaterTemperatureOffset = modelObject.minimumAirToWaterTemperatureOffset(); + idfObject.setDouble(CoilSystem_Cooling_WaterFields::MinimumAirToWaterTemperatureOffset, minimumAirToWaterTemperatureOffset); + + // Economizer Lockout: Optional Boolean + if (modelObject.economizerLockout()) { + idfObject.setString(CoilSystem_Cooling_WaterFields::EconomizerLockout, "Yes"); + } else { + idfObject.setString(CoilSystem_Cooling_WaterFields::EconomizerLockout, "No"); + } + + // Minimum Water Loop Temperature For Heat Recovery: Optional Double + const double minimumWaterLoopTemperatureForHeatRecovery = modelObject.minimumWaterLoopTemperatureForHeatRecovery(); + idfObject.setDouble(CoilSystem_Cooling_WaterFields::MinimumWaterLoopTemperatureForHeatRecovery, minimumWaterLoopTemperatureForHeatRecovery); + + // Companion Coil Used For Heat Recovery: Optional Object + if (boost::optional companionCoilUsedForHeatRecovery_ = modelObject.companionCoilUsedForHeatRecovery()) { + if (boost::optional wo_ = translateAndMapModelObject(companionCoilUsedForHeatRecovery_.get())) { + idfObject.setString(CoilSystem_Cooling_WaterFields::CompanionCoilUsedForHeatRecovery, wo_->nameString()); + } + } + + return idfObject; + } // End of translate function + +} // end namespace energyplus +} // end namespace openstudio diff --git a/src/energyplus/Test/CoilSystemCoolingWater_GTest.cpp b/src/energyplus/Test/CoilSystemCoolingWater_GTest.cpp new file mode 100644 index 00000000000..9d609276e58 --- /dev/null +++ b/src/energyplus/Test/CoilSystemCoolingWater_GTest.cpp @@ -0,0 +1,84 @@ +/*********************************************************************************************************************** +* OpenStudio(R), Copyright (c) Alliance for Sustainable Energy, LLC. +* See also https://openstudio.net/license +***********************************************************************************************************************/ + +#include +#include "EnergyPlusFixture.hpp" + +#include "../ForwardTranslator.hpp" +#include "../ReverseTranslator.hpp" + +#include "../../model/CoilSystemCoolingWater.hpp" +#include "../../model/CoilSystemCoolingWater_Impl.hpp" +// TODO: Check the following class names against object getters and setters. +#include "../../model/Schedule.hpp" +#include "../../model/Schedule_Impl.hpp" +#include "../../model/CoolingCoilsWater.hpp" +#include "../../model/CoolingCoilsWater_Impl.hpp" +#include "../../model/CoolingCoilsWater.hpp" +#include "../../model/CoolingCoilsWater_Impl.hpp" + +#include "../../utilities/idf/Workspace.hpp" +#include "../../utilities/idf/IdfObject.hpp" +#include "../../utilities/idf/WorkspaceObject.hpp" + +// E+ FieldEnums +#include +#include +#include + +using namespace openstudio::energyplus; +using namespace openstudio::model; +using namespace openstudio; + +TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWater) { + + ForwardTranslator ft; + + Model m; + // TODO: Check regular Ctor arguments + CoilSystemCoolingWater coilSystemCoolingWater(m); + // TODO: Or if a UniqueModelObject (and make sure _Impl is included) + // CoilSystemCoolingWater coilSystemCoolingWater = m.getUniqueModelObject(); + + coilSystemCoolingWater.setName("My CoilSystemCoolingWater"); + Node airInletNodeName(m); + EXPECT_TRUE(coilSystemCoolingWater.setAirInletNodeName(airInletNodeName)); + Node airOutletNodeName(m); + EXPECT_TRUE(coilSystemCoolingWater.setAirOutletNodeName(airOutletNodeName)); + boost::optional availabilitySchedule(m); + EXPECT_TRUE(coilSystemCoolingWater.setAvailabilitySchedule(availabilitySchedule)); + EXPECT_TRUE(coilSystemCoolingWater.setCoolingCoilObjectType("Coil:Cooling:Water")); + CoolingCoilsWater coolingCoil(m); + EXPECT_TRUE(coilSystemCoolingWater.setCoolingCoil(coolingCoil)); + EXPECT_TRUE(coilSystemCoolingWater.setDehumidificationControlType("None")); + EXPECT_TRUE(coilSystemCoolingWater.setRunonSensibleLoad(false)); // Opposite from IDD default + EXPECT_TRUE(coilSystemCoolingWater.setRunonLatentLoad(true)); // Opposite from IDD default + EXPECT_TRUE(coilSystemCoolingWater.setMinimumAirToWaterTemperatureOffset(1.0)); + EXPECT_TRUE(coilSystemCoolingWater.setEconomizerLockout(false)); // Opposite from IDD default + EXPECT_TRUE(coilSystemCoolingWater.setMinimumWaterLoopTemperatureForHeatRecovery(1.2)); + boost::optional companionCoilUsedForHeatRecovery(m); + EXPECT_TRUE(coilSystemCoolingWater.setCompanionCoilUsedForHeatRecovery(companionCoilUsedForHeatRecovery)); + + // TODO: you're responsible for creating all other objects needed so this object actually gets ForwardTranslated + + const Workspace w = ft.translateModel(m); + const auto idfObjs = w.getObjectsByType(IddObjectType::CoilSystem_Cooling_Water); + ASSERT_EQ(1u, idfObjs.size()); + + const auto& idfObject = idfObjs.front(); + EXPECT_EQ(airInletNodeName.nameString(), idfObject.getString(CoilSystem_Cooling_WaterFields::AirInletNodeName).get()); + EXPECT_EQ(airOutletNodeName.nameString(), idfObject.getString(CoilSystem_Cooling_WaterFields::AirOutletNodeName).get()); + EXPECT_EQ(availabilitySchedule.nameString(), idfObject.getString(CoilSystem_Cooling_WaterFields::AvailabilityScheduleName).get()); + EXPECT_EQ("Coil:Cooling:Water", idfObject.getString(CoilSystem_Cooling_WaterFields::CoolingCoilObjectType).get()); + EXPECT_EQ(coolingCoil.nameString(), idfObject.getString(CoilSystem_Cooling_WaterFields::CoolingCoilName).get()); + EXPECT_EQ("None", idfObject.getString(CoilSystem_Cooling_WaterFields::DehumidificationControlType).get()); + EXPECT_EQ("No", idfObject.getString(CoilSystem_Cooling_WaterFields::RunonSensibleLoad).get()); + EXPECT_EQ("Yes", idfObject.getString(CoilSystem_Cooling_WaterFields::RunonLatentLoad).get()); + EXPECT_EQ(1.0, idfObject.getDouble(CoilSystem_Cooling_WaterFields::MinimumAirToWaterTemperatureOffset).get()); + EXPECT_EQ("No", idfObject.getString(CoilSystem_Cooling_WaterFields::EconomizerLockout).get()); + EXPECT_EQ(1.2, idfObject.getDouble(CoilSystem_Cooling_WaterFields::MinimumWaterLoopTemperatureForHeatRecovery).get()); + EXPECT_EQ(companionCoilUsedForHeatRecovery.nameString(), + idfObject.getString(CoilSystem_Cooling_WaterFields::CompanionCoilUsedForHeatRecovery).get()); +} diff --git a/src/model/CoilSystemCoolingWater.cpp b/src/model/CoilSystemCoolingWater.cpp new file mode 100644 index 00000000000..b39a98385a2 --- /dev/null +++ b/src/model/CoilSystemCoolingWater.cpp @@ -0,0 +1,371 @@ +/*********************************************************************************************************************** +* OpenStudio(R), Copyright (c) Alliance for Sustainable Energy, LLC. +* See also https://openstudio.net/license +***********************************************************************************************************************/ + +#include "CoilSystemCoolingWater.hpp" +#include "CoilSystemCoolingWater_Impl.hpp" + +// TODO: Check the following class names against object getters and setters. +#include "Connection.hpp" +#include "Connection_Impl.hpp" +#include "Schedule.hpp" +#include "Schedule_Impl.hpp" +#include "CoolingCoilsWater.hpp" +#include "CoolingCoilsWater_Impl.hpp" +#include "ScheduleTypeLimits.hpp" +#include "ScheduleTypeRegistry.hpp" + +#include "../utilities/core/Assert.hpp" +#include "../utilities/data/DataEnums.hpp" + +#include +#include +#include + +namespace openstudio { +namespace model { + + namespace detail { + + CoilSystemCoolingWater_Impl::CoilSystemCoolingWater_Impl(const IdfObject& idfObject, Model_Impl* model, bool keepHandle) + : StraightComponent_Impl(idfObject, model, keepHandle) { + OS_ASSERT(idfObject.iddObject().type() == CoilSystemCoolingWater::iddObjectType()); + } + + CoilSystemCoolingWater_Impl::CoilSystemCoolingWater_Impl(const openstudio::detail::WorkspaceObject_Impl& other, Model_Impl* model, + bool keepHandle) + : StraightComponent_Impl(other, model, keepHandle) { + OS_ASSERT(other.iddObject().type() == CoilSystemCoolingWater::iddObjectType()); + } + + CoilSystemCoolingWater_Impl::CoilSystemCoolingWater_Impl(const CoilSystemCoolingWater_Impl& other, Model_Impl* model, bool keepHandle) + : StraightComponent_Impl(other, model, keepHandle) {} + + const std::vector& CoilSystemCoolingWater_Impl::outputVariableNames() const { + static std::vector result; + if (result.empty()) { + } + return result; + } + + IddObjectType CoilSystemCoolingWater_Impl::iddObjectType() const { + return CoilSystemCoolingWater::iddObjectType(); + } + + std::vector CoilSystemCoolingWater_Impl::getScheduleTypeKeys(const Schedule& schedule) const { + // TODO: Check schedule display names. + std::vector result; + const UnsignedVector fieldIndices = getSourceIndices(schedule.handle()); + if (std::find(fieldIndices.cbegin(), fieldIndices.cend(), OS_CoilSystem_Cooling_WaterFields::AvailabilityScheduleName) != fieldIndices.cend()) { + result.emplace_back("CoilSystemCoolingWater", "Availability"); + } + return result; + } + + ComponentType CoilSystemCoolingWater_Impl::componentType() const { + // TODO + return ComponentType::None; + } + + std::vector CoilSystemCoolingWater_Impl::coolingFuelTypes() const { + // TODO + return {}; + } + + std::vector CoilSystemCoolingWater_Impl::heatingFuelTypes() const { + // TODO + return {}; + } + + std::vector CoilSystemCoolingWater_Impl::appGHeatingFuelTypes() const { + + // TODO + return {}; + } + + Connection CoilSystemCoolingWater_Impl::airInletNode() const { + boost::optional value = optionalAirInletNode(); + if (!value) { + LOG_AND_THROW(briefDescription() << " does not have an Air Inlet Node attached."); + } + return value.get(); + } + + Connection CoilSystemCoolingWater_Impl::airOutletNode() const { + boost::optional value = optionalAirOutletNode(); + if (!value) { + LOG_AND_THROW(briefDescription() << " does not have an Air Outlet Node attached."); + } + return value.get(); + } + + Schedule CoilSystemCoolingWater_Impl::availabilitySchedule() const { + boost::optional value = optionalAvailabilitySchedule(); + if (!value) { + LOG_AND_THROW(briefDescription() << " does not have an Availability Schedule attached."); + } + return value.get(); + } + + CoolingCoilsWater CoilSystemCoolingWater_Impl::coolingCoil() const { + boost::optional value = optionalCoolingCoil(); + if (!value) { + LOG_AND_THROW(briefDescription() << " does not have an Cooling Coil attached."); + } + return value.get(); + } + + std::string CoilSystemCoolingWater_Impl::dehumidificationControlType() const { + boost::optional value = getString(OS_CoilSystem_Cooling_WaterFields::DehumidificationControlType, true); + OS_ASSERT(value); + return value.get(); + } + + bool CoilSystemCoolingWater_Impl::runonSensibleLoad() const { + return getBooleanFieldValue(OS_CoilSystem_Cooling_WaterFields::RunonSensibleLoad); + } + + bool CoilSystemCoolingWater_Impl::runonLatentLoad() const { + return getBooleanFieldValue(OS_CoilSystem_Cooling_WaterFields::RunonLatentLoad); + } + + double CoilSystemCoolingWater_Impl::minimumAirToWaterTemperatureOffset() const { + boost::optional value = getDouble(OS_CoilSystem_Cooling_WaterFields::MinimumAirToWaterTemperatureOffset, true); + OS_ASSERT(value); + return value.get(); + } + + bool CoilSystemCoolingWater_Impl::economizerLockout() const { + return getBooleanFieldValue(OS_CoilSystem_Cooling_WaterFields::EconomizerLockout); + } + + double CoilSystemCoolingWater_Impl::minimumWaterLoopTemperatureForHeatRecovery() const { + boost::optional value = getDouble(OS_CoilSystem_Cooling_WaterFields::MinimumWaterLoopTemperatureForHeatRecovery, true); + OS_ASSERT(value); + return value.get(); + } + + boost::optional CoilSystemCoolingWater_Impl::companionCoilUsedForHeatRecovery() const { + return getObject().getModelObjectTarget(OS_CoilSystem_Cooling_WaterFields::CompanionCoilUsedForHeatRecovery); + } + + bool CoilSystemCoolingWater_Impl::setAirInletNode(const Connection& connection) { + const bool result = setPointer(OS_CoilSystem_Cooling_WaterFields::AirInletNodeName, connection.handle()); + return result; + } + + bool CoilSystemCoolingWater_Impl::setAirOutletNode(const Connection& connection) { + const bool result = setPointer(OS_CoilSystem_Cooling_WaterFields::AirOutletNodeName, connection.handle()); + return result; + } + + bool CoilSystemCoolingWater_Impl::setAvailabilitySchedule(Schedule& schedule) { + const bool result = + setSchedule(OS_CoilSystem_Cooling_WaterFields::AvailabilityScheduleName, "CoilSystemCoolingWater", "Availability", schedule); + return result; + } + + bool CoilSystemCoolingWater_Impl::setCoolingCoil(const CoolingCoilsWater& coolingCoilsWater) { + const bool result = setPointer(OS_CoilSystem_Cooling_WaterFields::CoolingCoil, coolingCoilsWater.handle()); + return result; + } + + bool CoilSystemCoolingWater_Impl::setDehumidificationControlType(const std::string& dehumidificationControlType) { + const bool result = setString(OS_CoilSystem_Cooling_WaterFields::DehumidificationControlType, dehumidificationControlType); + return result; + } + + bool CoilSystemCoolingWater_Impl::setRunonSensibleLoad(bool runonSensibleLoad) { + const bool result = setBooleanFieldValue(OS_CoilSystem_Cooling_WaterFields::RunonSensibleLoad, runonSensibleLoad); + OS_ASSERT(result); + return result; + } + + bool CoilSystemCoolingWater_Impl::setRunonLatentLoad(bool runonLatentLoad) { + const bool result = setBooleanFieldValue(OS_CoilSystem_Cooling_WaterFields::RunonLatentLoad, runonLatentLoad); + OS_ASSERT(result); + return result; + } + + bool CoilSystemCoolingWater_Impl::setMinimumAirToWaterTemperatureOffset(double minimumAirToWaterTemperatureOffset) { + const bool result = setDouble(OS_CoilSystem_Cooling_WaterFields::MinimumAirToWaterTemperatureOffset, minimumAirToWaterTemperatureOffset); + return result; + } + + bool CoilSystemCoolingWater_Impl::setEconomizerLockout(bool economizerLockout) { + const bool result = setBooleanFieldValue(OS_CoilSystem_Cooling_WaterFields::EconomizerLockout, economizerLockout); + OS_ASSERT(result); + return result; + } + + bool CoilSystemCoolingWater_Impl::setMinimumWaterLoopTemperatureForHeatRecovery(double minimumWaterLoopTemperatureForHeatRecovery) { + const bool result = + setDouble(OS_CoilSystem_Cooling_WaterFields::MinimumWaterLoopTemperatureForHeatRecovery, minimumWaterLoopTemperatureForHeatRecovery); + OS_ASSERT(result); + return result; + } + + bool CoilSystemCoolingWater_Impl::setCompanionCoilUsedForHeatRecovery(const CoolingCoilsWater& coolingCoilsWater) { + const bool result = setPointer(OS_CoilSystem_Cooling_WaterFields::CompanionCoilUsedForHeatRecovery, coolingCoilsWater.handle()); + return result; + } + + void CoilSystemCoolingWater_Impl::resetCompanionCoilUsedForHeatRecovery() { + const bool result = setString(OS_CoilSystem_Cooling_WaterFields::CompanionCoilUsedForHeatRecovery, ""); + OS_ASSERT(result); + } + + boost::optional CoilSystemCoolingWater_Impl::optionalAirInletNode() const { + return getObject().getModelObjectTarget(OS_CoilSystem_Cooling_WaterFields::AirInletNodeName); + } + + boost::optional CoilSystemCoolingWater_Impl::optionalAirOutletNode() const { + return getObject().getModelObjectTarget(OS_CoilSystem_Cooling_WaterFields::AirOutletNodeName); + } + + boost::optional CoilSystemCoolingWater_Impl::optionalAvailabilitySchedule() const { + return getObject().getModelObjectTarget(OS_CoilSystem_Cooling_WaterFields::AvailabilityScheduleName); + } + + boost::optional CoilSystemCoolingWater_Impl::optionalCoolingCoil() const { + return getObject().getModelObjectTarget(OS_CoilSystem_Cooling_WaterFields::CoolingCoil); + } + + } // namespace detail + + CoilSystemCoolingWater::CoilSystemCoolingWater(const Model& model) : StraightComponent(CoilSystemCoolingWater::iddObjectType(), model) { + OS_ASSERT(getImpl()); + + // TODO: consider adding (overloaded or not) explicit ctors taking required objects as argument + + // TODO: Appropriately handle the following required object-list fields. + // OS_CoilSystem_Cooling_WaterFields::AirInletNodeName + // OS_CoilSystem_Cooling_WaterFields::AirOutletNodeName + // OS_CoilSystem_Cooling_WaterFields::AvailabilityScheduleName + // OS_CoilSystem_Cooling_WaterFields::CoolingCoil + bool ok = true; + // ok = setAirInletNode(); + OS_ASSERT(ok); + // ok = setAirOutletNode(); + OS_ASSERT(ok); + // ok = setAvailabilitySchedule(); + OS_ASSERT(ok); + // ok = setCoolingCoil(); + OS_ASSERT(ok); + // ok = setDehumidificationControlType(); + OS_ASSERT(ok); + // setRunonSensibleLoad(); + // setRunonLatentLoad(); + // ok = setMinimumAirToWaterTemperatureOffset(); + OS_ASSERT(ok); + // setEconomizerLockout(); + // setMinimumWaterLoopTemperatureForHeatRecovery(); + } + + IddObjectType CoilSystemCoolingWater::iddObjectType() { + return {IddObjectType::OS_CoilSystem_Cooling_Water}; + } + + std::vector CoilSystemCoolingWater::dehumidificationControlTypeValues() { + return getIddKeyNames(IddFactory::instance().getObject(iddObjectType()).get(), OS_CoilSystem_Cooling_WaterFields::DehumidificationControlType); + } + + Connection CoilSystemCoolingWater::airInletNode() const { + return getImpl()->airInletNode(); + } + + Connection CoilSystemCoolingWater::airOutletNode() const { + return getImpl()->airOutletNode(); + } + + Schedule CoilSystemCoolingWater::availabilitySchedule() const { + return getImpl()->availabilitySchedule(); + } + + CoolingCoilsWater CoilSystemCoolingWater::coolingCoil() const { + return getImpl()->coolingCoil(); + } + + std::string CoilSystemCoolingWater::dehumidificationControlType() const { + return getImpl()->dehumidificationControlType(); + } + + bool CoilSystemCoolingWater::runonSensibleLoad() const { + return getImpl()->runonSensibleLoad(); + } + + bool CoilSystemCoolingWater::runonLatentLoad() const { + return getImpl()->runonLatentLoad(); + } + + double CoilSystemCoolingWater::minimumAirToWaterTemperatureOffset() const { + return getImpl()->minimumAirToWaterTemperatureOffset(); + } + + bool CoilSystemCoolingWater::economizerLockout() const { + return getImpl()->economizerLockout(); + } + + double CoilSystemCoolingWater::minimumWaterLoopTemperatureForHeatRecovery() const { + return getImpl()->minimumWaterLoopTemperatureForHeatRecovery(); + } + + boost::optional CoilSystemCoolingWater::companionCoilUsedForHeatRecovery() const { + return getImpl()->companionCoilUsedForHeatRecovery(); + } + + bool CoilSystemCoolingWater::setAirInletNode(const Connection& connection) { + return getImpl()->setAirInletNode(connection); + } + + bool CoilSystemCoolingWater::setAirOutletNode(const Connection& connection) { + return getImpl()->setAirOutletNode(connection); + } + + bool CoilSystemCoolingWater::setAvailabilitySchedule(Schedule& schedule) { + return getImpl()->setAvailabilitySchedule(schedule); + } + + bool CoilSystemCoolingWater::setCoolingCoil(const CoolingCoilsWater& coolingCoilsWater) { + return getImpl()->setCoolingCoil(coolingCoilsWater); + } + + bool CoilSystemCoolingWater::setDehumidificationControlType(const std::string& dehumidificationControlType) { + return getImpl()->setDehumidificationControlType(dehumidificationControlType); + } + + bool CoilSystemCoolingWater::setRunonSensibleLoad(bool runonSensibleLoad) { + return getImpl()->setRunonSensibleLoad(runonSensibleLoad); + } + + bool CoilSystemCoolingWater::setRunonLatentLoad(bool runonLatentLoad) { + return getImpl()->setRunonLatentLoad(runonLatentLoad); + } + + bool CoilSystemCoolingWater::setMinimumAirToWaterTemperatureOffset(double minimumAirToWaterTemperatureOffset) { + return getImpl()->setMinimumAirToWaterTemperatureOffset(minimumAirToWaterTemperatureOffset); + } + + bool CoilSystemCoolingWater::setEconomizerLockout(bool economizerLockout) { + return getImpl()->setEconomizerLockout(economizerLockout); + } + + bool CoilSystemCoolingWater::setMinimumWaterLoopTemperatureForHeatRecovery(double minimumWaterLoopTemperatureForHeatRecovery) { + return getImpl()->setMinimumWaterLoopTemperatureForHeatRecovery(minimumWaterLoopTemperatureForHeatRecovery); + } + + bool CoilSystemCoolingWater::setCompanionCoilUsedForHeatRecovery(const CoolingCoilsWater& coolingCoilsWater) { + return getImpl()->setCompanionCoilUsedForHeatRecovery(coolingCoilsWater); + } + + void CoilSystemCoolingWater::resetCompanionCoilUsedForHeatRecovery() { + getImpl()->resetCompanionCoilUsedForHeatRecovery(); + } + + /// @cond + CoilSystemCoolingWater::CoilSystemCoolingWater(std::shared_ptr impl) : StraightComponent(std::move(impl)) {} + /// @endcond + +} // namespace model +} // namespace openstudio diff --git a/src/model/CoilSystemCoolingWater.hpp b/src/model/CoilSystemCoolingWater.hpp new file mode 100644 index 00000000000..f6cb9750e5e --- /dev/null +++ b/src/model/CoilSystemCoolingWater.hpp @@ -0,0 +1,142 @@ +/*********************************************************************************************************************** +* OpenStudio(R), Copyright (c) Alliance for Sustainable Energy, LLC. +* See also https://openstudio.net/license +***********************************************************************************************************************/ + +#ifndef MODEL_COILSYSTEMCOOLINGWATER_HPP +#define MODEL_COILSYSTEMCOOLINGWATER_HPP + +#include +#include "StraightComponent.hpp" + +namespace openstudio { + +namespace model { + + // TODO: Check the following class names against object getters and setters. + class Connection; + class Schedule; + class CoolingCoilsWater; + + namespace detail { + + class CoilSystemCoolingWater_Impl; + + } // namespace detail + + /** CoilSystemCoolingWater is a StraightComponent that wraps the OpenStudio IDD object 'OS:CoilSystem:Cooling:Water'. */ + class MODEL_API CoilSystemCoolingWater : public StraightComponent + { + public: + /** @name Constructors and Destructors */ + //@{ + + explicit CoilSystemCoolingWater(const Model& model); + + virtual ~CoilSystemCoolingWater() = default; + // Default the copy and move operators because the virtual dtor is explicit + CoilSystemCoolingWater(const CoilSystemCoolingWater& other) = default; + CoilSystemCoolingWater(CoilSystemCoolingWater&& other) = default; + CoilSystemCoolingWater& operator=(const CoilSystemCoolingWater&) = default; + CoilSystemCoolingWater& operator=(CoilSystemCoolingWater&&) = default; + + //@} + + static IddObjectType iddObjectType(); + + static std::vector dehumidificationControlTypeValues(); + + /** @name Getters */ + //@{ + + // TODO: Check return type. From object lists, some candidates are: Connection. + Connection airInletNode() const; + + // TODO: Check return type. From object lists, some candidates are: Connection. + Connection airOutletNode() const; + + // TODO: Check return type. From object lists, some candidates are: Schedule. + Schedule availabilitySchedule() const; + + // TODO: Check return type. From object lists, some candidates are: CoolingCoilsWater. + CoolingCoilsWater coolingCoil() const; + + std::string dehumidificationControlType() const; + + bool runonSensibleLoad() const; + + bool runonLatentLoad() const; + + double minimumAirToWaterTemperatureOffset() const; + + bool economizerLockout() const; + + double minimumWaterLoopTemperatureForHeatRecovery() const; + + // TODO: Check return type. From object lists, some candidates are: CoolingCoilsWater. + boost::optional companionCoilUsedForHeatRecovery() const; + + //@} + /** @name Setters */ + //@{ + + // TODO: Check argument type. From object lists, some candidates are: Connection. + bool setAirInletNode(const Connection& connection); + + // TODO: Check argument type. From object lists, some candidates are: Connection. + bool setAirOutletNode(const Connection& connection); + + // TODO: Check argument type. From object lists, some candidates are: Schedule. + // Note Schedules are passed by reference, not const reference. + bool setAvailabilitySchedule(Schedule& schedule); + + // TODO: Check argument type. From object lists, some candidates are: CoolingCoilsWater. + bool setCoolingCoil(const CoolingCoilsWater& coolingCoilsWater); + + bool setDehumidificationControlType(const std::string& dehumidificationControlType); + + bool setRunonSensibleLoad(bool runonSensibleLoad); + + bool setRunonLatentLoad(bool runonLatentLoad); + + bool setMinimumAirToWaterTemperatureOffset(double minimumAirToWaterTemperatureOffset); + + bool setEconomizerLockout(bool economizerLockout); + + bool setMinimumWaterLoopTemperatureForHeatRecovery(double minimumWaterLoopTemperatureForHeatRecovery); + + // TODO: Check argument type. From object lists, some candidates are: CoolingCoilsWater. + bool setCompanionCoilUsedForHeatRecovery(const CoolingCoilsWater& coolingCoilsWater); + + void resetCompanionCoilUsedForHeatRecovery(); + + //@} + /** @name Other */ + //@{ + + //@} + protected: + /// @cond + using ImplType = detail::CoilSystemCoolingWater_Impl; + + explicit CoilSystemCoolingWater(std::shared_ptr impl); + + friend class detail::CoilSystemCoolingWater_Impl; + friend class Model; + friend class IdfObject; + friend class openstudio::detail::IdfObject_Impl; + /// @endcond + private: + REGISTER_LOGGER("openstudio.model.CoilSystemCoolingWater"); + }; + + /** \relates CoilSystemCoolingWater*/ + using OptionalCoilSystemCoolingWater = boost::optional; + + /** \relates CoilSystemCoolingWater*/ + using CoilSystemCoolingWaterVector = std::vector; + +} // namespace model +} // namespace openstudio + +#endif // MODEL_COILSYSTEMCOOLINGWATER_HPP diff --git a/src/model/CoilSystemCoolingWater_Impl.hpp b/src/model/CoilSystemCoolingWater_Impl.hpp new file mode 100644 index 00000000000..82018f2f9ce --- /dev/null +++ b/src/model/CoilSystemCoolingWater_Impl.hpp @@ -0,0 +1,141 @@ +/*********************************************************************************************************************** +* OpenStudio(R), Copyright (c) Alliance for Sustainable Energy, LLC. +* See also https://openstudio.net/license +***********************************************************************************************************************/ + +#ifndef MODEL_COILSYSTEMCOOLINGWATER_IMPL_HPP +#define MODEL_COILSYSTEMCOOLINGWATER_IMPL_HPP + +#include +#include "StraightComponent_Impl.hpp" + +namespace openstudio { +namespace model { + + // TODO: Check the following class names against object getters and setters. + class Connection; + class Schedule; + class CoolingCoilsWater; + + namespace detail { + + /** CoilSystemCoolingWater_Impl is a StraightComponent_Impl that is the implementation class for CoilSystemCoolingWater.*/ + class MODEL_API CoilSystemCoolingWater_Impl : public StraightComponent_Impl + { + public: + /** @name Constructors and Destructors */ + //@{ + + CoilSystemCoolingWater_Impl(const IdfObject& idfObject, Model_Impl* model, bool keepHandle); + + CoilSystemCoolingWater_Impl(const openstudio::detail::WorkspaceObject_Impl& other, Model_Impl* model, bool keepHandle); + + CoilSystemCoolingWater_Impl(const CoilSystemCoolingWater_Impl& other, Model_Impl* model, bool keepHandle); + + virtual ~CoilSystemCoolingWater_Impl() = default; + + //@} + /** @name Virtual Methods */ + //@{ + + virtual const std::vector& outputVariableNames() const override; + + virtual IddObjectType iddObjectType() const override; + + virtual std::vector getScheduleTypeKeys(const Schedule& schedule) const override; + + virtual ComponentType componentType() const override; + virtual std::vector coolingFuelTypes() const override; + virtual std::vector heatingFuelTypes() const override; + virtual std::vector appGHeatingFuelTypes() const override; + + //@} + /** @name Getters */ + //@{ + + // TODO: Check return type. From object lists, some candidates are: Connection. + Connection airInletNode() const; + + // TODO: Check return type. From object lists, some candidates are: Connection. + Connection airOutletNode() const; + + // TODO: Check return type. From object lists, some candidates are: Schedule. + Schedule availabilitySchedule() const; + + // TODO: Check return type. From object lists, some candidates are: CoolingCoilsWater. + CoolingCoilsWater coolingCoil() const; + + std::string dehumidificationControlType() const; + + bool runonSensibleLoad() const; + + bool runonLatentLoad() const; + + double minimumAirToWaterTemperatureOffset() const; + + bool economizerLockout() const; + + double minimumWaterLoopTemperatureForHeatRecovery() const; + + // TODO: Check return type. From object lists, some candidates are: CoolingCoilsWater. + boost::optional companionCoilUsedForHeatRecovery() const; + + //@} + /** @name Setters */ + //@{ + + // TODO: Check argument type. From object lists, some candidates are: Connection. + bool setAirInletNode(const Connection& connection); + + // TODO: Check argument type. From object lists, some candidates are: Connection. + bool setAirOutletNode(const Connection& connection); + + // TODO: Check argument type. From object lists, some candidates are: Schedule. + // Note Schedules are passed by reference, not const reference. + bool setAvailabilitySchedule(Schedule& schedule); + + // TODO: Check argument type. From object lists, some candidates are: CoolingCoilsWater. + bool setCoolingCoil(const CoolingCoilsWater& coolingCoilsWater); + + bool setDehumidificationControlType(const std::string& dehumidificationControlType); + + bool setRunonSensibleLoad(bool runonSensibleLoad); + + bool setRunonLatentLoad(bool runonLatentLoad); + + bool setMinimumAirToWaterTemperatureOffset(double minimumAirToWaterTemperatureOffset); + + bool setEconomizerLockout(bool economizerLockout); + + bool setMinimumWaterLoopTemperatureForHeatRecovery(double minimumWaterLoopTemperatureForHeatRecovery); + + // TODO: Check argument type. From object lists, some candidates are: CoolingCoilsWater. + bool setCompanionCoilUsedForHeatRecovery(const CoolingCoilsWater& coolingCoilsWater); + + void resetCompanionCoilUsedForHeatRecovery(); + + //@} + /** @name Other */ + //@{ + + //@} + protected: + private: + REGISTER_LOGGER("openstudio.model.CoilSystemCoolingWater"); + + // TODO: Check the return types of these methods. + // Optional getters for use by methods like children() so can remove() if the constructor fails. + // There are other ways for the public versions of these getters to fail--perhaps all required + // objects should be returned as boost::optionals + boost::optional optionalAirInletNode() const; + boost::optional optionalAirOutletNode() const; + boost::optional optionalAvailabilitySchedule() const; + boost::optional optionalCoolingCoil() const; + }; + + } // namespace detail + +} // namespace model +} // namespace openstudio + +#endif // MODEL_COILSYSTEMCOOLINGWATER_IMPL_HPP diff --git a/src/model/ScheduleTypeRegistry.cpp b/src/model/ScheduleTypeRegistry.cpp index 123b45cfa31..fd2ac0ce654 100644 --- a/src/model/ScheduleTypeRegistry.cpp +++ b/src/model/ScheduleTypeRegistry.cpp @@ -224,6 +224,7 @@ namespace model { OptionalDouble()}, {"CoilHeatingWater", "Availability", "availabilitySchedule", false, "Availability", 0.0, 1.0}, {"CoilHeatingWaterBaseboard", "Availability", "availabilitySchedule", false, "Availability", 0.0, 1.0}, + {"CoilSystemCoolingWater", "Availability", "availabilitySchedule", false, "Availability", 0.0, 1.0}, {"CoilWaterHeatingDesuperheater", "Availability", "availabilitySchedule", false, "Availability", 0.0, 1.0}, {"CoilWaterHeatingDesuperheater", "Setpoint Temperature", "setpointTemperatureSchedule", true, "Temperature", OptionalDouble(), OptionalDouble()}, diff --git a/src/model/test/CoilSystemCoolingWater_GTest.cpp b/src/model/test/CoilSystemCoolingWater_GTest.cpp new file mode 100644 index 00000000000..e5bac6717cb --- /dev/null +++ b/src/model/test/CoilSystemCoolingWater_GTest.cpp @@ -0,0 +1,106 @@ +/*********************************************************************************************************************** +* OpenStudio(R), Copyright (c) Alliance for Sustainable Energy, LLC. +* See also https://openstudio.net/license +***********************************************************************************************************************/ + +#include "ModelFixture.hpp" + +#include "../CoilSystemCoolingWater.hpp" +#include "../CoilSystemCoolingWater_Impl.hpp" + +// TODO: Check the following class names against object getters and setters. +#include "../Connection.hpp" +#include "../Connection_Impl.hpp" + +#include "../Schedule.hpp" +#include "../Schedule_Impl.hpp" + +#include "../CoolingCoilsWater.hpp" +#include "../CoolingCoilsWater_Impl.hpp" + +using namespace openstudio; +using namespace openstudio::model; + +TEST_F(ModelFixture, CoilSystemCoolingWater_GettersSetters) { + Model m; + // TODO: Check regular Ctor arguments + CoilSystemCoolingWater coilSystemCoolingWater(m); + // TODO: Or if a UniqueModelObject (and make sure _Impl is included) + // CoilSystemCoolingWater coilSystemCoolingWater = m.getUniqueModelObject(); + + coilSystemCoolingWater.setName("My CoilSystemCoolingWater"); + + // Air Inlet Node Name: Required Object + Connection airInletNode(m); + EXPECT_TRUE(coilSystemCoolingWater.setAirInletNode(airInletNode)); + EXPECT_EQ(airInletNode, coilSystemCoolingWater.airInletNode()); + + // Air Outlet Node Name: Required Object + Connection airOutletNode(m); + EXPECT_TRUE(coilSystemCoolingWater.setAirOutletNode(airOutletNode)); + EXPECT_EQ(airOutletNode, coilSystemCoolingWater.airOutletNode()); + + // Availability Schedule Name: Required Object + Schedule availabilitySchedule(m); + EXPECT_TRUE(coilSystemCoolingWater.setAvailabilitySchedule(availabilitySchedule)); + EXPECT_EQ(availabilitySchedule, coilSystemCoolingWater.availabilitySchedule()); + + // Cooling Coil: Required Object + CoolingCoilsWater coolingCoil(m); + EXPECT_TRUE(coilSystemCoolingWater.setCoolingCoil(coolingCoil)); + EXPECT_EQ(coolingCoil, coilSystemCoolingWater.coolingCoil()); + + // Dehumidification Control Type: Required String + EXPECT_TRUE(coilSystemCoolingWater.setDehumidificationControlType("None")); + EXPECT_EQ("None", coilSystemCoolingWater.dehumidificationControlType()); + // Bad Value + EXPECT_FALSE(coilSystemCoolingWater.setDehumidificationControlType("BADENUM")); + EXPECT_EQ("None", coilSystemCoolingWater.dehumidificationControlType()); + + // Run on Sensible Load: Required Boolean + EXPECT_TRUE(coilSystemCoolingWater.setRunonSensibleLoad(true)); + EXPECT_TRUE(coilSystemCoolingWater.runonSensibleLoad()); + EXPECT_TRUE(coilSystemCoolingWater.setRunonSensibleLoad(false)); + EXPECT_FALSE(coilSystemCoolingWater.runonSensibleLoad()); + + // Run on Latent Load: Required Boolean + EXPECT_TRUE(coilSystemCoolingWater.setRunonLatentLoad(true)); + EXPECT_TRUE(coilSystemCoolingWater.runonLatentLoad()); + EXPECT_TRUE(coilSystemCoolingWater.setRunonLatentLoad(false)); + EXPECT_FALSE(coilSystemCoolingWater.runonLatentLoad()); + + // Minimum Air To Water Temperature Offset: Required Double + EXPECT_TRUE(coilSystemCoolingWater.setMinimumAirToWaterTemperatureOffset(1.0)); + EXPECT_EQ(1.0, coilSystemCoolingWater.minimumAirToWaterTemperatureOffset()); + // Bad Value + EXPECT_FALSE(coilSystemCoolingWater.setMinimumAirToWaterTemperatureOffset(-10.0)); + EXPECT_EQ(1.0, coilSystemCoolingWater.minimumAirToWaterTemperatureOffset()); + + // Economizer Lockout: Required Boolean + EXPECT_TRUE(coilSystemCoolingWater.setEconomizerLockout(true)); + EXPECT_TRUE(coilSystemCoolingWater.economizerLockout()); + EXPECT_TRUE(coilSystemCoolingWater.setEconomizerLockout(false)); + EXPECT_FALSE(coilSystemCoolingWater.economizerLockout()); + + // Minimum Water Loop Temperature For Heat Recovery: Required Double + EXPECT_TRUE(coilSystemCoolingWater.setMinimumWaterLoopTemperatureForHeatRecovery(1.2)); + EXPECT_EQ(1.2, coilSystemCoolingWater.minimumWaterLoopTemperatureForHeatRecovery()); + + // Companion Coil Used For Heat Recovery: Optional Object + boost::optional companionCoilUsedForHeatRecovery(m); + EXPECT_TRUE(coilSystemCoolingWater.setCompanionCoilUsedForHeatRecovery(companionCoilUsedForHeatRecovery)); + ASSERT_TRUE(coilSystemCoolingWater.companionCoilUsedForHeatRecovery()); + EXPECT_EQ(companionCoilUsedForHeatRecovery, coilSystemCoolingWater.companionCoilUsedForHeatRecovery().get()); +} +TEST_F(ModelFixture, CoilSystemCoolingWater_HeatCoolFuelTypes) { + Model m; + // TODO: Check regular Ctor arguments + CoilSystemCoolingWater coilSystemCoolingWater(m); + // TODO: Or if a UniqueModelObject (and make sure _Impl is included) + // CoilSystemCoolingWater coilSystemCoolingWater = m.getUniqueModelObject(); + + EXPECT_EQ(ComponentType(ComponentType::Both), coilSystemCoolingWater.componentType()); + testFuelTypeEquality({FuelType::Electricity}, coilSystemCoolingWater.coolingFuelTypes()); + testFuelTypeEquality({FuelType::Electricity, FuelType::Propane}, coilSystemCoolingWater.heatingFuelTypes()); + testAppGFuelTypeEquality({AppGFuelType::Fuel, AppGFuelType::HeatPump}, coilSystemCoolingWater.appGHeatingFuelTypes()); +} From 21bebc80bf4f2c3785f7545aef9c746fef5201e3 Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Wed, 19 Mar 2025 11:47:50 -0700 Subject: [PATCH 33/58] Update other src files. --- src/energyplus/CMakeLists.txt | 2 + src/energyplus/ForwardTranslator.cpp | 19 +++---- src/energyplus/ForwardTranslator.hpp | 8 ++- .../ForwardTranslateCoilCoolingWater.cpp | 54 ++----------------- ...ystemCoolingWaterHeatExchangerAssisted.cpp | 51 +----------------- .../ForwardTranslatePlantLoop.cpp | 14 ----- src/model/CMakeLists.txt | 4 ++ src/model/ConcreteModelObjects.hpp | 2 + src/model/Model.cpp | 2 + src/model/ModelStraightComponent.i | 2 + 10 files changed, 28 insertions(+), 130 deletions(-) diff --git a/src/energyplus/CMakeLists.txt b/src/energyplus/CMakeLists.txt index b880d9af349..a23df24d945 100644 --- a/src/energyplus/CMakeLists.txt +++ b/src/energyplus/CMakeLists.txt @@ -98,6 +98,7 @@ set(${target_name}_src ForwardTranslator/ForwardTranslateCoilHeatingWaterToAirHeatPumpVariableSpeedEquationFit.cpp ForwardTranslator/ForwardTranslateCoilPerformanceDXCooling.cpp ForwardTranslator/ForwardTranslateCoilSystemCoolingDXHeatExchangerAssisted.cpp + ForwardTranslator/ForwardTranslateCoilSystemCoolingWater.cpp ForwardTranslator/ForwardTranslateCoilSystemCoolingWaterHeatExchangerAssisted.cpp ForwardTranslator/ForwardTranslateCoilSystemIntegratedHeatPumpAirSource.cpp ForwardTranslator/ForwardTranslateCoilUserDefined.cpp @@ -721,6 +722,7 @@ set(${target_name}_test_src Test/CoilHeatingGasMultiStage_GTest.cpp Test/CoilHeatingWaterToAirHeatPumpEquationFit_GTest.cpp Test/CoilHeatingWaterToAirHeatPumpVariableSpeedEquationFit_GTest.cpp + Test/CoilSystemCoolingWater_GTest.cpp Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp Test/CoilSystemIntegratedHeatPumpAirSource_GTest.cpp Test/CoilUserDefined_GTest.cpp diff --git a/src/energyplus/ForwardTranslator.cpp b/src/energyplus/ForwardTranslator.cpp index 71652e18ec2..4f4db90c98f 100644 --- a/src/energyplus/ForwardTranslator.cpp +++ b/src/energyplus/ForwardTranslator.cpp @@ -1072,11 +1072,7 @@ namespace energyplus { } case openstudio::IddObjectType::OS_Coil_Cooling_Water: { auto coil = modelObject.cast(); - if (isHVACComponentWithinUnitary(coil)) { - retVal = translateCoilCoolingWaterWithoutUnitary(coil); - } else { - retVal = translateCoilCoolingWater(coil); - } + retVal = translateCoilCoolingWater(coil); break; } case openstudio::IddObjectType::OS_Coil_Cooling_Water_Panel_Radiant: { @@ -1211,13 +1207,14 @@ namespace energyplus { retVal = translateCoilPerformanceDXCooling(mo); break; } + case openstudio::IddObjectType::OS_CoilSystem_Cooling_Water: { + auto mo = modelObject.cast(); + retVal = translateCoilSystemCoolingWater(mo); + break; + } case openstudio::IddObjectType::OS_CoilSystem_Cooling_Water_HeatExchangerAssisted: { - auto coil = modelObject.cast(); - if (isHVACComponentWithinUnitary(coil)) { - retVal = translateCoilSystemCoolingWaterHeatExchangerAssistedWithoutUnitary(coil); - } else { - retVal = translateCoilSystemCoolingWaterHeatExchangerAssisted(coil); - } + auto mo = modelObject.cast(); + retVal = translateCoilSystemCoolingWaterHeatExchangerAssisted(mo); break; } case openstudio::IddObjectType::OS_CoilSystem_Cooling_DX_HeatExchangerAssisted: { diff --git a/src/energyplus/ForwardTranslator.hpp b/src/energyplus/ForwardTranslator.hpp index 1db498c2f65..7b83e9b8d7e 100644 --- a/src/energyplus/ForwardTranslator.hpp +++ b/src/energyplus/ForwardTranslator.hpp @@ -134,6 +134,7 @@ namespace model { class CoilHeatingWaterToAirHeatPumpVariableSpeedEquationFit; class CoilPerformanceDXCooling; class CoilSystemCoolingDXHeatExchangerAssisted; + class CoilSystemCoolingWater; class CoilSystemCoolingWaterHeatExchangerAssisted; class CoilSystemIntegratedHeatPumpAirSource; class CoilUserDefined; @@ -803,8 +804,6 @@ namespace energyplus { boost::optional translateCoilCoolingWater(model::CoilCoolingWater& modelObject); - boost::optional translateCoilCoolingWaterWithoutUnitary(model::CoilCoolingWater& modelObject); - boost::optional translateCoilCoolingWaterToAirHeatPumpEquationFit(model::CoilCoolingWaterToAirHeatPumpEquationFit& modelObject); boost::optional @@ -846,10 +845,9 @@ namespace energyplus { boost::optional translateCoilSystemCoolingDXHeatExchangerAssisted(model::CoilSystemCoolingDXHeatExchangerAssisted& modelObject); - boost::optional translateCoilSystemCoolingWaterHeatExchangerAssisted(model::CoilSystemCoolingWaterHeatExchangerAssisted& modelObject); + boost::optional translateCoilSystemCoolingWater(model::CoilSystemCoolingWater& modelObject); - boost::optional - translateCoilSystemCoolingWaterHeatExchangerAssistedWithoutUnitary(model::CoilSystemCoolingWaterHeatExchangerAssisted& modelObject); + boost::optional translateCoilSystemCoolingWaterHeatExchangerAssisted(model::CoilSystemCoolingWaterHeatExchangerAssisted& modelObject); boost::optional translateCoilSystemIntegratedHeatPumpAirSource(model::CoilSystemIntegratedHeatPumpAirSource& modelObject); diff --git a/src/energyplus/ForwardTranslator/ForwardTranslateCoilCoolingWater.cpp b/src/energyplus/ForwardTranslator/ForwardTranslateCoilCoolingWater.cpp index 744fd357b13..8968638ad86 100644 --- a/src/energyplus/ForwardTranslator/ForwardTranslateCoilCoolingWater.cpp +++ b/src/energyplus/ForwardTranslator/ForwardTranslateCoilCoolingWater.cpp @@ -13,7 +13,6 @@ #include "../../model/CoilCoolingWater_Impl.hpp" #include "../../utilities/core/Logger.hpp" #include "../../utilities/core/Assert.hpp" -#include #include #include "../../utilities/idd/IddEnums.hpp" #include @@ -27,7 +26,7 @@ namespace openstudio { namespace energyplus { - boost::optional ForwardTranslator::translateCoilCoolingWaterWithoutUnitary(model::CoilCoolingWater& modelObject) { + boost::optional ForwardTranslator::translateCoilCoolingWater(CoilCoolingWater& modelObject) { boost::optional s; boost::optional value; @@ -151,55 +150,8 @@ namespace energyplus { return boost::optional(idfObject); } - boost::optional ForwardTranslator::translateCoilCoolingWater(CoilCoolingWater& modelObject) { - IdfObject coilSystemCoolingWaterIdf(IddObjectType::CoilSystem_Cooling_Water); - - m_idfObjects.push_back(coilSystemCoolingWaterIdf); - - boost::optional oIdfObject = translateCoilCoolingWaterWithoutUnitary(modelObject); - - if (!oIdfObject) { - return boost::none; - } - - IdfObject idfObject = oIdfObject.get(); - - OptionalString s; - - s = modelObject.name(); - if (s) { - coilSystemCoolingWaterIdf.setString(CoilSystem_Cooling_WaterFields::CoolingCoilObjectType, idfObject.iddObject().name()); - - coilSystemCoolingWaterIdf.setString(CoilSystem_Cooling_WaterFields::CoolingCoilName, *s); - - coilSystemCoolingWaterIdf.setName(*s + " CoilSystem"); - } - - Schedule sched = modelObject.availabilitySchedule(); - translateAndMapModelObject(sched); - - coilSystemCoolingWaterIdf.setString(CoilSystem_Cooling_WaterFields::AvailabilityScheduleName, sched.name().get()); - - OptionalModelObject omo = modelObject.airInletModelObject(); - if (omo) { - translateAndMapModelObject(*omo); - s = omo->name(); - if (s) { - coilSystemCoolingWaterIdf.setString(CoilSystem_Cooling_WaterFields::AirInletNodeName, *s); - } - } - - omo = modelObject.airOutletModelObject(); - if (omo) { - translateAndMapModelObject(*omo); - s = omo->name(); - if (s) { - coilSystemCoolingWaterIdf.setString(CoilSystem_Cooling_WaterFields::AirOutletNodeName, *s); - } - } - - return coilSystemCoolingWaterIdf; - } + //((Name)(Name)) + //((AvailabilityScheduleName)(Availability Schedule Name)) } // namespace energyplus diff --git a/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWaterHeatExchangerAssisted.cpp b/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWaterHeatExchangerAssisted.cpp index 0197e59eb19..3cd67ee19a2 100644 --- a/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWaterHeatExchangerAssisted.cpp +++ b/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWaterHeatExchangerAssisted.cpp @@ -27,7 +27,6 @@ #include "../../model/Model.hpp" #include "../../utilities/core/Assert.hpp" -#include #include #include #include @@ -42,8 +41,8 @@ namespace openstudio { namespace energyplus { - boost::optional ForwardTranslator::translateCoilSystemCoolingWaterHeatExchangerAssistedWithoutUnitary( - model::CoilSystemCoolingWaterHeatExchangerAssisted& modelObject) { + boost::optional + ForwardTranslator::translateCoilSystemCoolingWaterHeatExchangerAssisted(CoilSystemCoolingWaterHeatExchangerAssisted& modelObject) { IdfObject idfObject = createRegisterAndNameIdfObject(openstudio::IddObjectType::CoilSystem_Cooling_Water_HeatExchangerAssisted, modelObject); @@ -158,51 +157,5 @@ namespace energyplus { return idfObject; } - boost::optional - ForwardTranslator::translateCoilSystemCoolingWaterHeatExchangerAssisted(CoilSystemCoolingWaterHeatExchangerAssisted& modelObject) { - IdfObject coilSystemCoolingWaterIdf(IddObjectType::CoilSystem_Cooling_Water); - - m_idfObjects.push_back(coilSystemCoolingWaterIdf); - - boost::optional oIdfObject = translateCoilSystemCoolingWaterHeatExchangerAssistedWithoutUnitary(modelObject); - - if (!oIdfObject) { - return boost::none; - } - - IdfObject idfObject = oIdfObject.get(); - - OptionalString s; - - s = modelObject.name(); - if (s) { - coilSystemCoolingWaterIdf.setString(CoilSystem_Cooling_WaterFields::CoolingCoilObjectType, idfObject.iddObject().name()); - - coilSystemCoolingWaterIdf.setString(CoilSystem_Cooling_WaterFields::CoolingCoilName, *s); - - coilSystemCoolingWaterIdf.setName(*s + " CoilSystem"); - } - - OptionalModelObject omo = modelObject.inletModelObject(); - if (omo) { - translateAndMapModelObject(*omo); - s = omo->name(); - if (s) { - coilSystemCoolingWaterIdf.setString(CoilSystem_Cooling_WaterFields::AirInletNodeName, *s); - } - } - - omo = modelObject.outletModelObject(); - if (omo) { - translateAndMapModelObject(*omo); - s = omo->name(); - if (s) { - coilSystemCoolingWaterIdf.setString(CoilSystem_Cooling_WaterFields::AirOutletNodeName, *s); - } - } - - return coilSystemCoolingWaterIdf; - } - } // namespace energyplus } // namespace openstudio diff --git a/src/energyplus/ForwardTranslator/ForwardTranslatePlantLoop.cpp b/src/energyplus/ForwardTranslator/ForwardTranslatePlantLoop.cpp index 86be1a75318..a3dc363a531 100644 --- a/src/energyplus/ForwardTranslator/ForwardTranslatePlantLoop.cpp +++ b/src/energyplus/ForwardTranslator/ForwardTranslatePlantLoop.cpp @@ -76,8 +76,6 @@ #include "../../model/CoilCoolingCooledBeam_Impl.hpp" #include "../../model/CoilCoolingFourPipeBeam.hpp" #include "../../model/CoilCoolingFourPipeBeam_Impl.hpp" -#include "../../model/CoilCoolingWater.hpp" -#include "../../model/CoilCoolingWater_Impl.hpp" #include "../../model/CoilHeatingFourPipeBeam.hpp" #include "../../model/CoilHeatingFourPipeBeam_Impl.hpp" #include "../../model/StraightComponent.hpp" @@ -118,7 +116,6 @@ #include #include #include -#include #include "../../utilities/core/Assert.hpp" using namespace openstudio::model; @@ -303,17 +300,6 @@ namespace energyplus { if (loop.optionalCast()) { inletNode = waterToAirComponent->waterInletModelObject()->optionalCast(); outletNode = waterToAirComponent->waterOutletModelObject()->optionalCast(); - // Special case for Coil:Cooling:Water. - if (boost::optional ccw = modelObject.optionalCast()) { - boost::optional idfCoil = this->translateAndMapModelObject(*ccw); - if (idfCoil) { - if (idfCoil->iddObject().type() == IddObjectType::CoilSystem_Cooling_Water) { - //Get the name and idd type of the coil cooling water inside the coil system - objectName = idfCoil->getString(CoilSystem_Cooling_WaterFields::CoolingCoilName).get(); - iddType = idfCoil->getString(CoilSystem_Cooling_WaterFields::CoolingCoilObjectType).get(); - } - } - } } else { inletNode = waterToAirComponent->airInletModelObject()->optionalCast(); outletNode = waterToAirComponent->airOutletModelObject()->optionalCast(); diff --git a/src/model/CMakeLists.txt b/src/model/CMakeLists.txt index e11982d4107..0cd8abff911 100644 --- a/src/model/CMakeLists.txt +++ b/src/model/CMakeLists.txt @@ -443,6 +443,9 @@ set(${target_name}_src CoilPerformanceDXCooling.hpp CoilPerformanceDXCooling_Impl.hpp CoilPerformanceDXCooling.cpp + CoilSystemCoolingWater.hpp + CoilSystemCoolingWater_Impl.hpp + CoilSystemCoolingWater.cpp CoilSystemCoolingWaterHeatExchangerAssisted.hpp CoilSystemCoolingWaterHeatExchangerAssisted_Impl.hpp CoilSystemCoolingWaterHeatExchangerAssisted.cpp @@ -2014,6 +2017,7 @@ set(${target_name}_test_src test/CoilHeatingWaterBaseboardRadiant_GTest.cpp test/CoilPerformanceDXCooling_GTest.cpp test/CoilSystemCoolingDXHeatExchangerAssisted_GTest.cpp + test/CoilSystemCoolingWater_GTest.cpp test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp test/CoilSystemIntegratedHeatPumpAirSource_GTest.cpp test/CoilUserDefined_GTest.cpp diff --git a/src/model/ConcreteModelObjects.hpp b/src/model/ConcreteModelObjects.hpp index df0cba1e357..57e043e49b2 100644 --- a/src/model/ConcreteModelObjects.hpp +++ b/src/model/ConcreteModelObjects.hpp @@ -135,6 +135,7 @@ #include "CoilHeatingWaterBaseboard.hpp" #include "CoilHeatingWaterBaseboardRadiant.hpp" #include "CoilPerformanceDXCooling.hpp" +#include "CoilSystemCoolingWater.hpp" #include "CoilSystemCoolingWaterHeatExchangerAssisted.hpp" #include "CoilSystemCoolingDXHeatExchangerAssisted.hpp" #include "CoilSystemIntegratedHeatPumpAirSource.hpp" @@ -693,6 +694,7 @@ #include "CoilHeatingWaterBaseboard_Impl.hpp" #include "CoilHeatingWaterBaseboardRadiant_Impl.hpp" #include "CoilPerformanceDXCooling_Impl.hpp" +#include "CoilSystemCoolingWater_Impl.hpp" #include "CoilSystemCoolingWaterHeatExchangerAssisted_Impl.hpp" #include "CoilSystemCoolingDXHeatExchangerAssisted_Impl.hpp" #include "CoilSystemIntegratedHeatPumpAirSource_Impl.hpp" diff --git a/src/model/Model.cpp b/src/model/Model.cpp index 7d43bf68abc..657761bf567 100644 --- a/src/model/Model.cpp +++ b/src/model/Model.cpp @@ -4034,6 +4034,7 @@ namespace model { REGISTER_CONSTRUCTOR(CoilHeatingWaterBaseboard); REGISTER_CONSTRUCTOR(CoilHeatingWaterBaseboardRadiant); REGISTER_CONSTRUCTOR(CoilPerformanceDXCooling); + REGISTER_CONSTRUCTOR(CoilSystemCoolingWater); REGISTER_CONSTRUCTOR(CoilSystemCoolingWaterHeatExchangerAssisted); REGISTER_CONSTRUCTOR(CoilSystemCoolingDXHeatExchangerAssisted); REGISTER_CONSTRUCTOR(CoilSystemIntegratedHeatPumpAirSource); @@ -4612,6 +4613,7 @@ namespace model { REGISTER_COPYCONSTRUCTORS(CoilHeatingWaterBaseboard); REGISTER_COPYCONSTRUCTORS(CoilHeatingWaterBaseboardRadiant); REGISTER_COPYCONSTRUCTORS(CoilPerformanceDXCooling); + REGISTER_COPYCONSTRUCTORS(CoilSystemCoolingWater); REGISTER_COPYCONSTRUCTORS(CoilSystemCoolingWaterHeatExchangerAssisted); REGISTER_COPYCONSTRUCTORS(CoilSystemCoolingDXHeatExchangerAssisted); REGISTER_COPYCONSTRUCTORS(CoilSystemIntegratedHeatPumpAirSource); diff --git a/src/model/ModelStraightComponent.i b/src/model/ModelStraightComponent.i index 3c835cceadf..c7c77775645 100644 --- a/src/model/ModelStraightComponent.i +++ b/src/model/ModelStraightComponent.i @@ -141,6 +141,7 @@ MODELOBJECT_TEMPLATES(CoilHeatingLowTempRadiantVarFlow); MODELOBJECT_TEMPLATES(CoilHeatingWaterBaseboard); MODELOBJECT_TEMPLATES(CoilHeatingWaterBaseboardRadiant); MODELOBJECT_TEMPLATES(CoilSystemCoolingDXHeatExchangerAssisted); +MODELOBJECT_TEMPLATES(CoilSystemCoolingWater); MODELOBJECT_TEMPLATES(CoilSystemCoolingWaterHeatExchangerAssisted); MODELOBJECT_TEMPLATES(CoilSystemIntegratedHeatPumpAirSource); MODELOBJECT_TEMPLATES(CoilWaterHeatingDesuperheater); @@ -229,6 +230,7 @@ SWIG_MODELOBJECT(CoilHeatingLowTempRadiantVarFlow,1); SWIG_MODELOBJECT(CoilHeatingWaterBaseboard,1); SWIG_MODELOBJECT(CoilHeatingWaterBaseboardRadiant,1); SWIG_MODELOBJECT(CoilSystemCoolingDXHeatExchangerAssisted,1); +SWIG_MODELOBJECT(CoilSystemCoolingWater,1); SWIG_MODELOBJECT(CoilSystemCoolingWaterHeatExchangerAssisted,1); SWIG_MODELOBJECT(CoilSystemIntegratedHeatPumpAirSource,1); SWIG_MODELOBJECT(CoilWaterHeatingDesuperheater,1); From 0fb2a2e8aae06869e1fd9c0bdc5daeba685994e4 Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Thu, 20 Mar 2025 13:52:36 -0700 Subject: [PATCH 34/58] Revise model and ft files. --- .../ForwardTranslateAirLoopHVAC.cpp | 9 + ...ForwardTranslateCoilSystemCoolingWater.cpp | 131 +++++--- src/model/CoilSystemCoolingWater.cpp | 279 ++++++++++++------ src/model/CoilSystemCoolingWater.hpp | 33 +-- src/model/CoilSystemCoolingWater_Impl.hpp | 59 ++-- 5 files changed, 313 insertions(+), 198 deletions(-) diff --git a/src/energyplus/ForwardTranslator/ForwardTranslateAirLoopHVAC.cpp b/src/energyplus/ForwardTranslator/ForwardTranslateAirLoopHVAC.cpp index d30a7f4925e..f43861de00f 100644 --- a/src/energyplus/ForwardTranslator/ForwardTranslateAirLoopHVAC.cpp +++ b/src/energyplus/ForwardTranslator/ForwardTranslateAirLoopHVAC.cpp @@ -18,6 +18,8 @@ #include "../../model/SizingSystem_Impl.hpp" #include "../../model/CoilCoolingWater.hpp" #include "../../model/CoilCoolingWater_Impl.hpp" +#include "../../model/CoilSystemCoolingWater.hpp" +#include "../../model/CoilSystemCoolingWater_Impl.hpp" #include "../../model/CoilSystemCoolingWaterHeatExchangerAssisted.hpp" #include "../../model/CoilSystemCoolingWaterHeatExchangerAssisted_Impl.hpp" #include "../../model/CoilHeatingWater.hpp" @@ -275,6 +277,13 @@ namespace energyplus { controller = supplyComponent.cast().controllerWaterCoil(); break; } + case openstudio::IddObjectType::OS_CoilSystem_Cooling_Water: { + auto coolingCoil = supplyComponent.cast().coolingCoil(); + if (auto coilCoolingWater = coolingCoil.optionalCast()) { + controller = coilCoolingWater->controllerWaterCoil(); + } + break; + } case openstudio::IddObjectType::OS_CoilSystem_Cooling_Water_HeatExchangerAssisted: { auto coolingCoil = supplyComponent.cast().coolingCoil(); if (auto coilCoolingWater = coolingCoil.optionalCast()) { diff --git a/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWater.cpp b/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWater.cpp index 539b1be0276..2143ea1a1b1 100644 --- a/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWater.cpp +++ b/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWater.cpp @@ -5,18 +5,26 @@ #include "../ForwardTranslator.hpp" #include "../../model/Model.hpp" - #include "../../model/CoilSystemCoolingWater.hpp" - -// TODO: Check the following class names against object getters and setters. +#include "../../model/CoilSystemCoolingWater_Impl.hpp" #include "../../model/Node.hpp" #include "../../model/Node_Impl.hpp" - #include "../../model/Schedule.hpp" #include "../../model/Schedule_Impl.hpp" - -#include "../../model/CoolingCoilsWater.hpp" -#include "../../model/CoolingCoilsWater_Impl.hpp" +#include "../../model/CoilCoolingWater.hpp" +#include "../../model/CoilCoolingWater_Impl.hpp" +#include "../../model/ControllerWaterCoil.hpp" +#include "../../model/ControllerWaterCoil_Impl.hpp" + +#include "../../model/AirLoopHVAC.hpp" +#include "../../model/FanVariableVolume.hpp" +#include "../../model/FanVariableVolume_Impl.hpp" +#include "../../model/FanConstantVolume.hpp" +#include "../../model/FanConstantVolume_Impl.hpp" +#include "../../model/FanOnOff.hpp" +#include "../../model/FanOnOff_Impl.hpp" +#include "../../model/FanSystemModel.hpp" +#include "../../model/FanSystemModel_Impl.hpp" #include #include @@ -29,31 +37,82 @@ namespace energyplus { boost::optional ForwardTranslator::translateCoilSystemCoolingWater(model::CoilSystemCoolingWater& modelObject) { - // Instantiate an IdfObject of the class to store the values IdfObject idfObject = createRegisterAndNameIdfObject(openstudio::IddObjectType::CoilSystem_Cooling_Water, modelObject); - // If it doesn't have a name, or if you aren't sure you are going to want to return it - // IdfObject idfObject(openstudio::IddObjectType::CoilSystem_Cooling_Water); - // m_idfObjects.push_back(idfObject); - - // TODO: Note JM 2018-10-17 - // You are responsible for implementing any additional logic based on choice fields, etc. - // The ForwardTranslator generator script is meant to facilitate your work, not get you 100% of the way - - // TODO: If you keep createRegisterAndNameIdfObject above, you don't need this. - // But in some cases, you'll want to handle failure without pushing to the map - // Name - idfObject.setName(modelObject.nameString()); - - // Air Inlet Node Name: Required Node - Node airInletNodeName = modelObject.airInletNodeName(); - if (boost::optional wo_ = translateAndMapModelObject(airInletNodeName)) { - idfObject.setString(CoilSystem_Cooling_WaterFields::AirInletNodeName, wo_->nameString()); - } - // Air Outlet Node Name: Required Node - Node airOutletNodeName = modelObject.airOutletNodeName(); - if (boost::optional wo_ = translateAndMapModelObject(airOutletNodeName)) { - idfObject.setString(CoilSystem_Cooling_WaterFields::AirOutletNodeName, wo_->nameString()); + std::string airInletNodeName = modelObject.nameString() + " Cooling Inlet Node"; + std::string airOutletNodeName = modelObject.nameString() + " Cooling Outlet Node"; + + // CoolingCoilObjectType + // CoolingCoilName + { + auto coolingCoil = modelObject.coolingCoil(); + if (auto idf = translateAndMapModelObject(coolingCoil)) { + idfObject.setString(CoilSystem_Cooling_WaterFields::CoolingCoilObjectType, idf->iddObject().name()); + idfObject.setString(CoilSystem_Cooling_WaterFields::CoolingCoilName, idf->nameString()); + if (idf->iddObject().type() == IddObjectType::Coil_Cooling_Water) { + idf->setString(Coil_Cooling_WaterFields::AirInletNodeName, airInletNodeName); + idf->setString(Coil_Cooling_WaterFields::AirOutletNodeName, airOutletNodeName); + // Add IddObjectType::Coil_Cooling_Water_DetailedGeometry if implemented + } else { + // Shouldn't happen, accepts only Coil:Cooling:Water or Coil:Cooling:Water:DetailedGeometry + // Shouldn't happen, accepts only Coil:Cooling:DX:SingleSpeed or Coil:Cooling:DX:VariableSpeed + LOG(Fatal, modelObject.briefDescription() + << " appears to have a cooling coil that shouldn't have been accepted: " << coolingCoil.briefDescription()); + OS_ASSERT(false); + } + } + if (auto coilCoolingWater = coolingCoil.optionalCast()) { + if (auto controller = coilCoolingWater->controllerWaterCoil()) { + if (auto idf = translateAndMapModelObject(controller.get())) { + idf->setString(Controller_WaterCoilFields::SensorNodeName, airOutletNodeName); + } + } + } + + // Need a SPM:MixedAir on the Coil:Cooling:Water outlet node (that we **created** just above in IDF directly, so it won't get picked up by the + // ForwardTranslateAirLoopHVAC method) + if (boost::optional airLoop_ = modelObject.airLoopHVAC()) { + std::vector fans; + std::vector supplyComponents = airLoop_->supplyComponents(); + + for (auto it = supplyComponents.begin(); it != supplyComponents.end(); ++it) { + if (auto fan_ = it->optionalCast()) { + fans.insert(fans.begin(), std::move(*fan_)); + } else if (auto fan_ = it->optionalCast()) { + fans.insert(fans.begin(), std::move(*fan_)); + } else if (auto fan_ = it->optionalCast()) { + fans.insert(fans.begin(), std::move(*fan_)); + } else if (auto fan_ = it->optionalCast()) { + fans.insert(fans.begin(), std::move(*fan_)); + } + } + + if (!fans.empty()) { + // Fan closest to the supply outlet node + StraightComponent fan = fans.front(); + OptionalNode inletNode = fan.inletModelObject()->optionalCast(); + OptionalNode outletNode = fan.outletModelObject()->optionalCast(); + + // No reason this wouldn't be ok at this point really... + // TODO: change to OS_ASSERT? + if (inletNode && outletNode) { + + IdfObject idf_spm(IddObjectType::SetpointManager_MixedAir); + idf_spm.setString(SetpointManager_MixedAirFields::Name, airOutletNodeName + " OS Default SPM"); + idf_spm.setString(SetpointManager_MixedAirFields::ControlVariable, "Temperature"); + + Node supplyOutletNode = airLoop_->supplyOutletNode(); + idf_spm.setString(SetpointManager_MixedAirFields::ReferenceSetpointNodeName, supplyOutletNode.nameString()); + + idf_spm.setString(SetpointManager_MixedAirFields::FanInletNodeName, inletNode->nameString()); + idf_spm.setString(SetpointManager_MixedAirFields::FanOutletNodeName, outletNode->nameString()); + + idf_spm.setString(SetpointManager_MixedAirFields::SetpointNodeorNodeListName, airOutletNodeName); + + m_idfObjects.push_back(idf_spm); + } + } + } } // Availability Schedule Name: Optional Object @@ -63,16 +122,6 @@ namespace energyplus { } } - // Cooling Coil Object Type: Required String - const std::string coolingCoilObjectType = modelObject.coolingCoilObjectType(); - idfObject.setString(CoilSystem_Cooling_WaterFields::CoolingCoilObjectType, coolingCoilObjectType); - - // Cooling Coil Name: Required Object - CoolingCoilsWater coolingCoil = modelObject.coolingCoil(); - if (boost::optional wo_ = translateAndMapModelObject(coolingCoil)) { - idfObject.setString(CoilSystem_Cooling_WaterFields::CoolingCoilName, wo_->nameString()); - } - // Dehumidification Control Type: Optional String const std::string dehumidificationControlType = modelObject.dehumidificationControlType(); idfObject.setString(CoilSystem_Cooling_WaterFields::DehumidificationControlType, dehumidificationControlType); @@ -107,7 +156,7 @@ namespace energyplus { idfObject.setDouble(CoilSystem_Cooling_WaterFields::MinimumWaterLoopTemperatureForHeatRecovery, minimumWaterLoopTemperatureForHeatRecovery); // Companion Coil Used For Heat Recovery: Optional Object - if (boost::optional companionCoilUsedForHeatRecovery_ = modelObject.companionCoilUsedForHeatRecovery()) { + if (boost::optional companionCoilUsedForHeatRecovery_ = modelObject.companionCoilUsedForHeatRecovery()) { if (boost::optional wo_ = translateAndMapModelObject(companionCoilUsedForHeatRecovery_.get())) { idfObject.setString(CoilSystem_Cooling_WaterFields::CompanionCoilUsedForHeatRecovery, wo_->nameString()); } diff --git a/src/model/CoilSystemCoolingWater.cpp b/src/model/CoilSystemCoolingWater.cpp index b39a98385a2..3b7d7fc9842 100644 --- a/src/model/CoilSystemCoolingWater.cpp +++ b/src/model/CoilSystemCoolingWater.cpp @@ -6,15 +6,14 @@ #include "CoilSystemCoolingWater.hpp" #include "CoilSystemCoolingWater_Impl.hpp" -// TODO: Check the following class names against object getters and setters. -#include "Connection.hpp" -#include "Connection_Impl.hpp" #include "Schedule.hpp" #include "Schedule_Impl.hpp" -#include "CoolingCoilsWater.hpp" -#include "CoolingCoilsWater_Impl.hpp" -#include "ScheduleTypeLimits.hpp" -#include "ScheduleTypeRegistry.hpp" +#include "WaterToAirComponent.hpp" +#include "WaterToAirComponent_Impl.hpp" +#include "Model.hpp" +#include "Model_Impl.hpp" +#include "Node.hpp" +#include "Node_Impl.hpp" #include "../utilities/core/Assert.hpp" #include "../utilities/data/DataEnums.hpp" @@ -54,7 +53,6 @@ namespace model { } std::vector CoilSystemCoolingWater_Impl::getScheduleTypeKeys(const Schedule& schedule) const { - // TODO: Check schedule display names. std::vector result; const UnsignedVector fieldIndices = getSourceIndices(schedule.handle()); if (std::find(fieldIndices.cbegin(), fieldIndices.cend(), OS_CoilSystem_Cooling_WaterFields::AvailabilityScheduleName) != fieldIndices.cend()) { @@ -63,41 +61,139 @@ namespace model { return result; } - ComponentType CoilSystemCoolingWater_Impl::componentType() const { - // TODO - return ComponentType::None; + unsigned CoilSystemCoolingWater_Impl::inletPort() const { + return OS_CoilSystem_Cooling_WaterFields::AirInletNodeName; } - std::vector CoilSystemCoolingWater_Impl::coolingFuelTypes() const { - // TODO - return {}; + unsigned CoilSystemCoolingWater_Impl::outletPort() const { + return OS_CoilSystem_Cooling_WaterFields::AirOutletNodeName; } - std::vector CoilSystemCoolingWater_Impl::heatingFuelTypes() const { - // TODO - return {}; + std::vector CoilSystemCoolingWater_Impl::children() const { + std::vector result; + if (OptionalWaterToAirComponent intermediate = optionalCoolingCoil()) { + result.push_back(*intermediate); + } + if (OptionalWaterToAirComponent intermediate = optionalCompanionCoilUsedForHeatRecovery()) { + result.push_back(*intermediate); + } + + return result; } - std::vector CoilSystemCoolingWater_Impl::appGHeatingFuelTypes() const { + ModelObject CoilSystemCoolingWater_Impl::clone(Model model) const { + auto coilSystemClone = StraightComponent_Impl::clone(model).cast(); - // TODO - return {}; + if (OptionalWaterToAirComponent intermediate = optionalCoolingCoil()) { + coilSystemClone.setSupplyAirFan(intermediate->clone(model).cast()); + } + if (OptionalWaterToAirComponent intermediate = optionalCompanionCoilUsedForHeatRecovery()) { + coilSystemClone.setSupplyAirFan(intermediate->clone(model).cast()); + } + + return std::move(coilSystemClone); + } + + bool CoilSystemCoolingWater_Impl::addToNode(Node& node) { + bool result = false; + + if (boost::optional airLoop = node.airLoopHVAC()) { + if (!airLoop->demandComponent(node.handle())) { + result = StraightComponent_Impl::addToNode(node); + if (result) { + auto t_coolingCoil = coolingCoil(); + if (auto waterInletModelObject = t_coolingCoil.waterInletModelObject()) { + + // TODO: why aren't we setting the water coil in this case? @kbenne thoughts please + if (auto coilCoolingWater = t_coolingCoil.optionalCast()) { + if (auto oldController = coilCoolingWater->controllerWaterCoil()) { + oldController->remove(); + } + } + + auto t_model = model(); + ControllerWaterCoil controller(t_model); + + auto coilWaterInletNode = waterInletModelObject->optionalCast(); + OS_ASSERT(coilWaterInletNode); + controller.setActuatorNode(coilWaterInletNode.get()); + // sensor node will be established in translator since that node does not yet exist + + controller.setAction("Reverse"); + } + } + } + } else if (boost::optional oas = node.airLoopHVACOutdoorAirSystem()) { + if (oas->airLoopHVACDedicatedOutdoorAirSystem()) { + return StraightComponent_Impl::addToNode(node); + } + } + + return result; } - Connection CoilSystemCoolingWater_Impl::airInletNode() const { - boost::optional value = optionalAirInletNode(); - if (!value) { - LOG_AND_THROW(briefDescription() << " does not have an Air Inlet Node attached."); + boost::optional CoilSystemCoolingWater_Impl::containingHVACComponent() const { + // AirLoopHVACUnitarySystem + std::vector airLoopHVACUnitarySystems = this->model().getConcreteModelObjects(); + + for (const auto& airLoopHVACUnitarySystem : airLoopHVACUnitarySystems) { + if (boost::optional coolingCoil = airLoopHVACUnitarySystem.coolingCoil()) { + if (coolingCoil->handle() == this->handle()) { + return airLoopHVACUnitarySystem; + } + } } - return value.get(); + + return boost::none; } - Connection CoilSystemCoolingWater_Impl::airOutletNode() const { - boost::optional value = optionalAirOutletNode(); - if (!value) { - LOG_AND_THROW(briefDescription() << " does not have an Air Outlet Node attached."); + boost::optional CoilSystemCoolingWater_Impl::containingZoneHVACComponent() const { + + // ZoneHVACFourPipeFanCoil + std::vector zoneHVACFourPipeFanCoils; + + zoneHVACFourPipeFanCoils = this->model().getConcreteModelObjects(); + + for (const auto& zoneHVACFourPipeFanCoil : zoneHVACFourPipeFanCoils) { + if (boost::optional coil = zoneHVACFourPipeFanCoil.coolingCoil()) { + if (coil->handle() == this->handle()) { + return zoneHVACFourPipeFanCoil; + } + } } - return value.get(); + + // ZoneHVACUnitVentilator + std::vector zoneHVACUnitVentilators; + + zoneHVACUnitVentilators = this->model().getConcreteModelObjects(); + + for (const auto& zoneHVACUnitVentilator : zoneHVACUnitVentilators) { + if (boost::optional coil = zoneHVACUnitVentilator.coolingCoil()) { + if (coil->handle() == this->handle()) { + return zoneHVACUnitVentilator; + } + } + } + + // ZoneHVAC:WindowAirConditioner not wrapped + + return boost::none; + } + + ComponentType CoilSystemCoolingWater_Impl::componentType() const { + return ComponentType::Cooling; + } + + std::vector CoilSystemCoolingWater_Impl::coolingFuelTypes() const { + return coolingCoil().coolingFuelTypes(); + } + + std::vector CoilSystemCoolingWater_Impl::heatingFuelTypes() const { + return {}; + } + + std::vector CoilSystemCoolingWater_Impl::appGHeatingFuelTypes() const { + return {}; } Schedule CoilSystemCoolingWater_Impl::availabilitySchedule() const { @@ -108,8 +204,8 @@ namespace model { return value.get(); } - CoolingCoilsWater CoilSystemCoolingWater_Impl::coolingCoil() const { - boost::optional value = optionalCoolingCoil(); + WaterToAirComponent CoilSystemCoolingWater_Impl::coolingCoil() const { + boost::optional value = optionalCoolingCoil(); if (!value) { LOG_AND_THROW(briefDescription() << " does not have an Cooling Coil attached."); } @@ -146,18 +242,8 @@ namespace model { return value.get(); } - boost::optional CoilSystemCoolingWater_Impl::companionCoilUsedForHeatRecovery() const { - return getObject().getModelObjectTarget(OS_CoilSystem_Cooling_WaterFields::CompanionCoilUsedForHeatRecovery); - } - - bool CoilSystemCoolingWater_Impl::setAirInletNode(const Connection& connection) { - const bool result = setPointer(OS_CoilSystem_Cooling_WaterFields::AirInletNodeName, connection.handle()); - return result; - } - - bool CoilSystemCoolingWater_Impl::setAirOutletNode(const Connection& connection) { - const bool result = setPointer(OS_CoilSystem_Cooling_WaterFields::AirOutletNodeName, connection.handle()); - return result; + boost::optional CoilSystemCoolingWater_Impl::companionCoilUsedForHeatRecovery() const { + return optionalCompanionCoilUsedForHeatRecovery(); } bool CoilSystemCoolingWater_Impl::setAvailabilitySchedule(Schedule& schedule) { @@ -166,8 +252,8 @@ namespace model { return result; } - bool CoilSystemCoolingWater_Impl::setCoolingCoil(const CoolingCoilsWater& coolingCoilsWater) { - const bool result = setPointer(OS_CoilSystem_Cooling_WaterFields::CoolingCoil, coolingCoilsWater.handle()); + bool CoilSystemCoolingWater_Impl::setCoolingCoil(const WaterToAirComponent& coolingCoil) { + const bool result = setPointer(OS_CoilSystem_Cooling_WaterFields::CoolingCoil, coolingCoil.handle()); return result; } @@ -206,8 +292,8 @@ namespace model { return result; } - bool CoilSystemCoolingWater_Impl::setCompanionCoilUsedForHeatRecovery(const CoolingCoilsWater& coolingCoilsWater) { - const bool result = setPointer(OS_CoilSystem_Cooling_WaterFields::CompanionCoilUsedForHeatRecovery, coolingCoilsWater.handle()); + bool CoilSystemCoolingWater_Impl::setCompanionCoilUsedForHeatRecovery(const WaterToAirComponent& companionCoilUsedForHeatRecovery) { + const bool result = setPointer(OS_CoilSystem_Cooling_WaterFields::CompanionCoilUsedForHeatRecovery, companionCoilUsedForHeatRecovery.handle()); return result; } @@ -216,20 +302,16 @@ namespace model { OS_ASSERT(result); } - boost::optional CoilSystemCoolingWater_Impl::optionalAirInletNode() const { - return getObject().getModelObjectTarget(OS_CoilSystem_Cooling_WaterFields::AirInletNodeName); - } - - boost::optional CoilSystemCoolingWater_Impl::optionalAirOutletNode() const { - return getObject().getModelObjectTarget(OS_CoilSystem_Cooling_WaterFields::AirOutletNodeName); - } - boost::optional CoilSystemCoolingWater_Impl::optionalAvailabilitySchedule() const { return getObject().getModelObjectTarget(OS_CoilSystem_Cooling_WaterFields::AvailabilityScheduleName); } - boost::optional CoilSystemCoolingWater_Impl::optionalCoolingCoil() const { - return getObject().getModelObjectTarget(OS_CoilSystem_Cooling_WaterFields::CoolingCoil); + boost::optional CoilSystemCoolingWater_Impl::optionalCoolingCoil() const { + return getObject().getModelObjectTarget(OS_CoilSystem_Cooling_WaterFields::CoolingCoil); + } + + boost::optional CoilSystemCoolingWater_Impl::optionalCompanionCoilUsedForHeatRecovery() const { + return getObject().getModelObjectTarget(OS_CoilSystem_Cooling_WaterFields::CompanionCoilUsedForHeatRecovery); } } // namespace detail @@ -237,30 +319,51 @@ namespace model { CoilSystemCoolingWater::CoilSystemCoolingWater(const Model& model) : StraightComponent(CoilSystemCoolingWater::iddObjectType(), model) { OS_ASSERT(getImpl()); - // TODO: consider adding (overloaded or not) explicit ctors taking required objects as argument + bool ok = true; + auto alwaysOn = model.alwaysOnDiscreteSchedule(); + ok = setAvailabilitySchedule(alwaysOn); + OS_ASSERT(ok); + + CoilCoolingWater coolingCoil(model); + ok = setCoolingCoil(coolingCoil); + OS_ASSERT(ok); + ok = setDehumidificationControlType("None"); + OS_ASSERT(ok); + ok = setRunonSensibleLoad(true); + OS_ASSERT(ok); + ok = setRunonLatentLoad(false); + OS_ASSERT(ok); + ok = setMinimumAirToWaterTemperatureOffset(0.0); + OS_ASSERT(ok); + ok = setEconomizerLockout(true); + OS_ASSERT(ok); + ok = setMinimumWaterLoopTemperatureForHeatRecovery(0.0); + OS_ASSERT(ok); + } + + CoilSystemCoolingWater::CoilSystemCoolingWater(const Model& model, const WaterToAirComponent& coolingCoil) + : StraightComponent(CoilSystemCoolingWater::iddObjectType(), model) { + OS_ASSERT(getImpl()); - // TODO: Appropriately handle the following required object-list fields. - // OS_CoilSystem_Cooling_WaterFields::AirInletNodeName - // OS_CoilSystem_Cooling_WaterFields::AirOutletNodeName - // OS_CoilSystem_Cooling_WaterFields::AvailabilityScheduleName - // OS_CoilSystem_Cooling_WaterFields::CoolingCoil bool ok = true; - // ok = setAirInletNode(); + auto alwaysOn = model.alwaysOnDiscreteSchedule(); + ok = setAvailabilitySchedule(alwaysOn); + OS_ASSERT(ok); + + ok = setCoolingCoil(coolingCoil); + OS_ASSERT(ok); + ok = setDehumidificationControlType("None"); OS_ASSERT(ok); - // ok = setAirOutletNode(); + ok = setRunonSensibleLoad(true); OS_ASSERT(ok); - // ok = setAvailabilitySchedule(); + ok = setRunonLatentLoad(false); OS_ASSERT(ok); - // ok = setCoolingCoil(); + ok = setMinimumAirToWaterTemperatureOffset(0.0); OS_ASSERT(ok); - // ok = setDehumidificationControlType(); + ok = setEconomizerLockout(true); OS_ASSERT(ok); - // setRunonSensibleLoad(); - // setRunonLatentLoad(); - // ok = setMinimumAirToWaterTemperatureOffset(); + ok = setMinimumWaterLoopTemperatureForHeatRecovery(0.0); OS_ASSERT(ok); - // setEconomizerLockout(); - // setMinimumWaterLoopTemperatureForHeatRecovery(); } IddObjectType CoilSystemCoolingWater::iddObjectType() { @@ -271,19 +374,11 @@ namespace model { return getIddKeyNames(IddFactory::instance().getObject(iddObjectType()).get(), OS_CoilSystem_Cooling_WaterFields::DehumidificationControlType); } - Connection CoilSystemCoolingWater::airInletNode() const { - return getImpl()->airInletNode(); - } - - Connection CoilSystemCoolingWater::airOutletNode() const { - return getImpl()->airOutletNode(); - } - Schedule CoilSystemCoolingWater::availabilitySchedule() const { return getImpl()->availabilitySchedule(); } - CoolingCoilsWater CoilSystemCoolingWater::coolingCoil() const { + WaterToAirComponent CoilSystemCoolingWater::coolingCoil() const { return getImpl()->coolingCoil(); } @@ -311,24 +406,16 @@ namespace model { return getImpl()->minimumWaterLoopTemperatureForHeatRecovery(); } - boost::optional CoilSystemCoolingWater::companionCoilUsedForHeatRecovery() const { + boost::optional CoilSystemCoolingWater::companionCoilUsedForHeatRecovery() const { return getImpl()->companionCoilUsedForHeatRecovery(); } - bool CoilSystemCoolingWater::setAirInletNode(const Connection& connection) { - return getImpl()->setAirInletNode(connection); - } - - bool CoilSystemCoolingWater::setAirOutletNode(const Connection& connection) { - return getImpl()->setAirOutletNode(connection); - } - bool CoilSystemCoolingWater::setAvailabilitySchedule(Schedule& schedule) { return getImpl()->setAvailabilitySchedule(schedule); } - bool CoilSystemCoolingWater::setCoolingCoil(const CoolingCoilsWater& coolingCoilsWater) { - return getImpl()->setCoolingCoil(coolingCoilsWater); + bool CoilSystemCoolingWater::setCoolingCoil(const WaterToAirComponent& coolingCoil) { + return getImpl()->setCoolingCoil(coolingCoil); } bool CoilSystemCoolingWater::setDehumidificationControlType(const std::string& dehumidificationControlType) { @@ -355,8 +442,8 @@ namespace model { return getImpl()->setMinimumWaterLoopTemperatureForHeatRecovery(minimumWaterLoopTemperatureForHeatRecovery); } - bool CoilSystemCoolingWater::setCompanionCoilUsedForHeatRecovery(const CoolingCoilsWater& coolingCoilsWater) { - return getImpl()->setCompanionCoilUsedForHeatRecovery(coolingCoilsWater); + bool CoilSystemCoolingWater::setCompanionCoilUsedForHeatRecovery(const WaterToAirComponent& companionCoilUsedForHeatRecovery) { + return getImpl()->setCompanionCoilUsedForHeatRecovery(companionCoilUsedForHeatRecovery); } void CoilSystemCoolingWater::resetCompanionCoilUsedForHeatRecovery() { diff --git a/src/model/CoilSystemCoolingWater.hpp b/src/model/CoilSystemCoolingWater.hpp index f6cb9750e5e..e22211ecbd1 100644 --- a/src/model/CoilSystemCoolingWater.hpp +++ b/src/model/CoilSystemCoolingWater.hpp @@ -13,10 +13,8 @@ namespace openstudio { namespace model { - // TODO: Check the following class names against object getters and setters. - class Connection; class Schedule; - class CoolingCoilsWater; + class WaterToAirComponent; namespace detail { @@ -33,6 +31,8 @@ namespace model { explicit CoilSystemCoolingWater(const Model& model); + explicit CoilSystemCoolingWater(const Model& model, const WaterToAirComponent& coolingCoil); + virtual ~CoilSystemCoolingWater() = default; // Default the copy and move operators because the virtual dtor is explicit CoilSystemCoolingWater(const CoilSystemCoolingWater& other) = default; @@ -49,17 +49,9 @@ namespace model { /** @name Getters */ //@{ - // TODO: Check return type. From object lists, some candidates are: Connection. - Connection airInletNode() const; - - // TODO: Check return type. From object lists, some candidates are: Connection. - Connection airOutletNode() const; - - // TODO: Check return type. From object lists, some candidates are: Schedule. Schedule availabilitySchedule() const; - // TODO: Check return type. From object lists, some candidates are: CoolingCoilsWater. - CoolingCoilsWater coolingCoil() const; + WaterToAirComponent coolingCoil() const; std::string dehumidificationControlType() const; @@ -73,25 +65,15 @@ namespace model { double minimumWaterLoopTemperatureForHeatRecovery() const; - // TODO: Check return type. From object lists, some candidates are: CoolingCoilsWater. - boost::optional companionCoilUsedForHeatRecovery() const; + boost::optional companionCoilUsedForHeatRecovery() const; //@} /** @name Setters */ //@{ - // TODO: Check argument type. From object lists, some candidates are: Connection. - bool setAirInletNode(const Connection& connection); - - // TODO: Check argument type. From object lists, some candidates are: Connection. - bool setAirOutletNode(const Connection& connection); - - // TODO: Check argument type. From object lists, some candidates are: Schedule. - // Note Schedules are passed by reference, not const reference. bool setAvailabilitySchedule(Schedule& schedule); - // TODO: Check argument type. From object lists, some candidates are: CoolingCoilsWater. - bool setCoolingCoil(const CoolingCoilsWater& coolingCoilsWater); + bool setCoolingCoil(const WaterToAirComponent& coolingCoil); bool setDehumidificationControlType(const std::string& dehumidificationControlType); @@ -105,8 +87,7 @@ namespace model { bool setMinimumWaterLoopTemperatureForHeatRecovery(double minimumWaterLoopTemperatureForHeatRecovery); - // TODO: Check argument type. From object lists, some candidates are: CoolingCoilsWater. - bool setCompanionCoilUsedForHeatRecovery(const CoolingCoilsWater& coolingCoilsWater); + bool setCompanionCoilUsedForHeatRecovery(const WaterToAirComponent& companionCoilUsedForHeatRecovery); void resetCompanionCoilUsedForHeatRecovery(); diff --git a/src/model/CoilSystemCoolingWater_Impl.hpp b/src/model/CoilSystemCoolingWater_Impl.hpp index 82018f2f9ce..f5572588d14 100644 --- a/src/model/CoilSystemCoolingWater_Impl.hpp +++ b/src/model/CoilSystemCoolingWater_Impl.hpp @@ -12,10 +12,8 @@ namespace openstudio { namespace model { - // TODO: Check the following class names against object getters and setters. - class Connection; class Schedule; - class CoolingCoilsWater; + class WaterToAirComponent; namespace detail { @@ -44,6 +42,23 @@ namespace model { virtual std::vector getScheduleTypeKeys(const Schedule& schedule) const override; + virtual unsigned inletPort() const override; + + virtual unsigned outletPort() const override; + + // will return the coolingCoil and companionCoilUsedForHeatRecovery + virtual std::vector children() const override; + + // Will also clone the coolingCoil and companionCoilUsedForHeatRecovery + virtual ModelObject clone(Model model) const override; + + // This function will connect the underlying Coil:Cooling:Water object + virtual bool addToNode(Node& node) override; + + virtual boost::optional containingHVACComponent() const override; + + virtual boost::optional containingZoneHVACComponent() const override; + virtual ComponentType componentType() const override; virtual std::vector coolingFuelTypes() const override; virtual std::vector heatingFuelTypes() const override; @@ -53,17 +68,7 @@ namespace model { /** @name Getters */ //@{ - // TODO: Check return type. From object lists, some candidates are: Connection. - Connection airInletNode() const; - - // TODO: Check return type. From object lists, some candidates are: Connection. - Connection airOutletNode() const; - - // TODO: Check return type. From object lists, some candidates are: Schedule. - Schedule availabilitySchedule() const; - - // TODO: Check return type. From object lists, some candidates are: CoolingCoilsWater. - CoolingCoilsWater coolingCoil() const; + WaterToAirComponent coolingCoil() const; std::string dehumidificationControlType() const; @@ -77,25 +82,15 @@ namespace model { double minimumWaterLoopTemperatureForHeatRecovery() const; - // TODO: Check return type. From object lists, some candidates are: CoolingCoilsWater. - boost::optional companionCoilUsedForHeatRecovery() const; + boost::optional companionCoilUsedForHeatRecovery() const; //@} /** @name Setters */ //@{ - // TODO: Check argument type. From object lists, some candidates are: Connection. - bool setAirInletNode(const Connection& connection); - - // TODO: Check argument type. From object lists, some candidates are: Connection. - bool setAirOutletNode(const Connection& connection); - - // TODO: Check argument type. From object lists, some candidates are: Schedule. - // Note Schedules are passed by reference, not const reference. bool setAvailabilitySchedule(Schedule& schedule); - // TODO: Check argument type. From object lists, some candidates are: CoolingCoilsWater. - bool setCoolingCoil(const CoolingCoilsWater& coolingCoilsWater); + bool setCoolingCoil(const WaterToAirComponent& coolingCoil); bool setDehumidificationControlType(const std::string& dehumidificationControlType); @@ -109,8 +104,7 @@ namespace model { bool setMinimumWaterLoopTemperatureForHeatRecovery(double minimumWaterLoopTemperatureForHeatRecovery); - // TODO: Check argument type. From object lists, some candidates are: CoolingCoilsWater. - bool setCompanionCoilUsedForHeatRecovery(const CoolingCoilsWater& coolingCoilsWater); + bool setCompanionCoilUsedForHeatRecovery(const WaterToAirComponent& companionCoilUsedForHeatRecovery); void resetCompanionCoilUsedForHeatRecovery(); @@ -123,14 +117,9 @@ namespace model { private: REGISTER_LOGGER("openstudio.model.CoilSystemCoolingWater"); - // TODO: Check the return types of these methods. - // Optional getters for use by methods like children() so can remove() if the constructor fails. - // There are other ways for the public versions of these getters to fail--perhaps all required - // objects should be returned as boost::optionals - boost::optional optionalAirInletNode() const; - boost::optional optionalAirOutletNode() const; boost::optional optionalAvailabilitySchedule() const; - boost::optional optionalCoolingCoil() const; + boost::optional optionalCoolingCoil() const; + boost::optional optionalCompanionCoilUsedForHeatRecovery() const; }; } // namespace detail From 20b38f2f646203b2d8b7e2243496cfe7436e3994 Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Thu, 20 Mar 2025 16:38:06 -0700 Subject: [PATCH 35/58] Update model and ft tests. --- .../Test/CoilSystemCoolingWater_GTest.cpp | 50 +++++++++-------- src/model/CoilSystemCoolingWater.cpp | 22 +++++++- ...oolingWaterHeatExchangerAssisted_GTest.cpp | 1 - .../test/CoilSystemCoolingWater_GTest.cpp | 53 ++++++++----------- 4 files changed, 70 insertions(+), 56 deletions(-) diff --git a/src/energyplus/Test/CoilSystemCoolingWater_GTest.cpp b/src/energyplus/Test/CoilSystemCoolingWater_GTest.cpp index 9d609276e58..9418e790d80 100644 --- a/src/energyplus/Test/CoilSystemCoolingWater_GTest.cpp +++ b/src/energyplus/Test/CoilSystemCoolingWater_GTest.cpp @@ -7,17 +7,17 @@ #include "EnergyPlusFixture.hpp" #include "../ForwardTranslator.hpp" -#include "../ReverseTranslator.hpp" #include "../../model/CoilSystemCoolingWater.hpp" #include "../../model/CoilSystemCoolingWater_Impl.hpp" -// TODO: Check the following class names against object getters and setters. #include "../../model/Schedule.hpp" #include "../../model/Schedule_Impl.hpp" -#include "../../model/CoolingCoilsWater.hpp" -#include "../../model/CoolingCoilsWater_Impl.hpp" -#include "../../model/CoolingCoilsWater.hpp" -#include "../../model/CoolingCoilsWater_Impl.hpp" +#include "../../model/CoilCoolingWater.hpp" +#include "../../model/CoilCoolingWater_Impl.hpp" + +#include "../../model/AirLoopHVAC.hpp" +#include "../../model/AirLoopHVACUnitarySystem.hpp" +#include "../../model/Node.hpp" #include "../../utilities/idf/Workspace.hpp" #include "../../utilities/idf/IdfObject.hpp" @@ -37,43 +37,47 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWater) { ForwardTranslator ft; Model m; - // TODO: Check regular Ctor arguments + CoilSystemCoolingWater coilSystemCoolingWater(m); - // TODO: Or if a UniqueModelObject (and make sure _Impl is included) - // CoilSystemCoolingWater coilSystemCoolingWater = m.getUniqueModelObject(); coilSystemCoolingWater.setName("My CoilSystemCoolingWater"); - Node airInletNodeName(m); - EXPECT_TRUE(coilSystemCoolingWater.setAirInletNodeName(airInletNodeName)); - Node airOutletNodeName(m); - EXPECT_TRUE(coilSystemCoolingWater.setAirOutletNodeName(airOutletNodeName)); - boost::optional availabilitySchedule(m); + Schedule availabilitySchedule = m.alwaysOnDiscreteSchedule(); EXPECT_TRUE(coilSystemCoolingWater.setAvailabilitySchedule(availabilitySchedule)); - EXPECT_TRUE(coilSystemCoolingWater.setCoolingCoilObjectType("Coil:Cooling:Water")); - CoolingCoilsWater coolingCoil(m); - EXPECT_TRUE(coilSystemCoolingWater.setCoolingCoil(coolingCoil)); - EXPECT_TRUE(coilSystemCoolingWater.setDehumidificationControlType("None")); + EXPECT_TRUE(coilSystemCoolingWater.setDehumidificationControlType("CoolReheat")); EXPECT_TRUE(coilSystemCoolingWater.setRunonSensibleLoad(false)); // Opposite from IDD default EXPECT_TRUE(coilSystemCoolingWater.setRunonLatentLoad(true)); // Opposite from IDD default EXPECT_TRUE(coilSystemCoolingWater.setMinimumAirToWaterTemperatureOffset(1.0)); EXPECT_TRUE(coilSystemCoolingWater.setEconomizerLockout(false)); // Opposite from IDD default EXPECT_TRUE(coilSystemCoolingWater.setMinimumWaterLoopTemperatureForHeatRecovery(1.2)); - boost::optional companionCoilUsedForHeatRecovery(m); + CoilCoolingWater companionCoilUsedForHeatRecovery(m); EXPECT_TRUE(coilSystemCoolingWater.setCompanionCoilUsedForHeatRecovery(companionCoilUsedForHeatRecovery)); - // TODO: you're responsible for creating all other objects needed so this object actually gets ForwardTranslated + // put it inside a Unitary, and put Unitary on an AirLoopHVAC so it gets translated + AirLoopHVACUnitarySystem unitary(m); + unitary.setCoolingCoil(coilSystemCoolingWater); + AirLoopHVAC airLoop(m); + Node supplyOutletNode = airLoop.supplyOutletNode(); + unitary.addToNode(supplyOutletNode); + ASSERT_TRUE(unitary.inletNode()); + EXPECT_TRUE(unitary.inletNode()->setName("Coil Air Inlet Node")); + ASSERT_TRUE(unitary.outletNode()); + EXPECT_TRUE(unitary.outletNode()->setName("Coil Air Outlet Node")); + + // They must be connected to a PlantLoop too + PlantLoop chw_p(m); + chw_p.addDemandBranchForComponent(coilSystemCoolingWater.coolingCoil()); const Workspace w = ft.translateModel(m); const auto idfObjs = w.getObjectsByType(IddObjectType::CoilSystem_Cooling_Water); ASSERT_EQ(1u, idfObjs.size()); const auto& idfObject = idfObjs.front(); - EXPECT_EQ(airInletNodeName.nameString(), idfObject.getString(CoilSystem_Cooling_WaterFields::AirInletNodeName).get()); - EXPECT_EQ(airOutletNodeName.nameString(), idfObject.getString(CoilSystem_Cooling_WaterFields::AirOutletNodeName).get()); + EXPECT_EQ(coil.inletModelObject().get().nameString(), idfObject.getString(CoilSystem_Cooling_WaterFields::AirInletNodeName).get()); + EXPECT_EQ(coil.outletModelObject().get().nameString(), idfObject.getString(CoilSystem_Cooling_WaterFields::AirOutletNodeName).get()); EXPECT_EQ(availabilitySchedule.nameString(), idfObject.getString(CoilSystem_Cooling_WaterFields::AvailabilityScheduleName).get()); EXPECT_EQ("Coil:Cooling:Water", idfObject.getString(CoilSystem_Cooling_WaterFields::CoolingCoilObjectType).get()); EXPECT_EQ(coolingCoil.nameString(), idfObject.getString(CoilSystem_Cooling_WaterFields::CoolingCoilName).get()); - EXPECT_EQ("None", idfObject.getString(CoilSystem_Cooling_WaterFields::DehumidificationControlType).get()); + EXPECT_EQ("CoolReheat", idfObject.getString(CoilSystem_Cooling_WaterFields::DehumidificationControlType).get()); EXPECT_EQ("No", idfObject.getString(CoilSystem_Cooling_WaterFields::RunonSensibleLoad).get()); EXPECT_EQ("Yes", idfObject.getString(CoilSystem_Cooling_WaterFields::RunonLatentLoad).get()); EXPECT_EQ(1.0, idfObject.getDouble(CoilSystem_Cooling_WaterFields::MinimumAirToWaterTemperatureOffset).get()); diff --git a/src/model/CoilSystemCoolingWater.cpp b/src/model/CoilSystemCoolingWater.cpp index 3b7d7fc9842..08f88641544 100644 --- a/src/model/CoilSystemCoolingWater.cpp +++ b/src/model/CoilSystemCoolingWater.cpp @@ -10,10 +10,28 @@ #include "Schedule_Impl.hpp" #include "WaterToAirComponent.hpp" #include "WaterToAirComponent_Impl.hpp" +#include "CoilCoolingWater.hpp" +#include "CoilCoolingWater_Impl.hpp" #include "Model.hpp" #include "Model_Impl.hpp" #include "Node.hpp" #include "Node_Impl.hpp" +#include "AirLoopHVAC.hpp" +#include "AirLoopHVAC_Impl.hpp" +#include "ControllerWaterCoil.hpp" +#include "ControllerWaterCoil_Impl.hpp" + +#include "AirLoopHVACUnitarySystem.hpp" +#include "AirLoopHVACUnitarySystem_Impl.hpp" +#include "ZoneHVACFourPipeFanCoil.hpp" +#include "ZoneHVACFourPipeFanCoil_Impl.hpp" +#include "ZoneHVACUnitVentilator.hpp" +#include "ZoneHVACUnitVentilator_Impl.hpp" + +#include "AirLoopHVACOutdoorAirSystem.hpp" +#include "AirLoopHVACOutdoorAirSystem_Impl.hpp" +#include "AirLoopHVACDedicatedOutdoorAirSystem.hpp" +#include "AirLoopHVACDedicatedOutdoorAirSystem_Impl.hpp" #include "../utilities/core/Assert.hpp" #include "../utilities/data/DataEnums.hpp" @@ -85,10 +103,10 @@ namespace model { auto coilSystemClone = StraightComponent_Impl::clone(model).cast(); if (OptionalWaterToAirComponent intermediate = optionalCoolingCoil()) { - coilSystemClone.setSupplyAirFan(intermediate->clone(model).cast()); + coilSystemClone.setCoolingCoil(intermediate->clone(model).cast()); } if (OptionalWaterToAirComponent intermediate = optionalCompanionCoilUsedForHeatRecovery()) { - coilSystemClone.setSupplyAirFan(intermediate->clone(model).cast()); + coilSystemClone.setCompanionCoilUsedForHeatRecovery(intermediate->clone(model).cast()); } return std::move(coilSystemClone); diff --git a/src/model/test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp b/src/model/test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp index acd6840f8c9..914fe9cfa3a 100644 --- a/src/model/test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp +++ b/src/model/test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp @@ -21,7 +21,6 @@ #include "../ZoneHVACFourPipeFanCoil.hpp" #include "../FanConstantVolume.hpp" #include "../CoilHeatingWater.hpp" -#include "../CoilCoolingWater.hpp" #include "../Schedule.hpp" using namespace openstudio; diff --git a/src/model/test/CoilSystemCoolingWater_GTest.cpp b/src/model/test/CoilSystemCoolingWater_GTest.cpp index e5bac6717cb..573f7db6fa0 100644 --- a/src/model/test/CoilSystemCoolingWater_GTest.cpp +++ b/src/model/test/CoilSystemCoolingWater_GTest.cpp @@ -7,46 +7,28 @@ #include "../CoilSystemCoolingWater.hpp" #include "../CoilSystemCoolingWater_Impl.hpp" - -// TODO: Check the following class names against object getters and setters. -#include "../Connection.hpp" -#include "../Connection_Impl.hpp" - #include "../Schedule.hpp" #include "../Schedule_Impl.hpp" - -#include "../CoolingCoilsWater.hpp" -#include "../CoolingCoilsWater_Impl.hpp" +#include "../CoilCoolingWater.hpp" +#include "../CoilCoolingWater_Impl.hpp" using namespace openstudio; using namespace openstudio::model; TEST_F(ModelFixture, CoilSystemCoolingWater_GettersSetters) { Model m; - // TODO: Check regular Ctor arguments + CoilSystemCoolingWater coilSystemCoolingWater(m); - // TODO: Or if a UniqueModelObject (and make sure _Impl is included) - // CoilSystemCoolingWater coilSystemCoolingWater = m.getUniqueModelObject(); coilSystemCoolingWater.setName("My CoilSystemCoolingWater"); - // Air Inlet Node Name: Required Object - Connection airInletNode(m); - EXPECT_TRUE(coilSystemCoolingWater.setAirInletNode(airInletNode)); - EXPECT_EQ(airInletNode, coilSystemCoolingWater.airInletNode()); - - // Air Outlet Node Name: Required Object - Connection airOutletNode(m); - EXPECT_TRUE(coilSystemCoolingWater.setAirOutletNode(airOutletNode)); - EXPECT_EQ(airOutletNode, coilSystemCoolingWater.airOutletNode()); - // Availability Schedule Name: Required Object - Schedule availabilitySchedule(m); + Schedule availabilitySchedule = m.alwaysOnDiscreteSchedule(); EXPECT_TRUE(coilSystemCoolingWater.setAvailabilitySchedule(availabilitySchedule)); EXPECT_EQ(availabilitySchedule, coilSystemCoolingWater.availabilitySchedule()); // Cooling Coil: Required Object - CoolingCoilsWater coolingCoil(m); + CoilCoolingWater coolingCoil(m); EXPECT_TRUE(coilSystemCoolingWater.setCoolingCoil(coolingCoil)); EXPECT_EQ(coolingCoil, coilSystemCoolingWater.coolingCoil()); @@ -87,20 +69,31 @@ TEST_F(ModelFixture, CoilSystemCoolingWater_GettersSetters) { EXPECT_EQ(1.2, coilSystemCoolingWater.minimumWaterLoopTemperatureForHeatRecovery()); // Companion Coil Used For Heat Recovery: Optional Object - boost::optional companionCoilUsedForHeatRecovery(m); + boost::optional companionCoilUsedForHeatRecovery(m); EXPECT_TRUE(coilSystemCoolingWater.setCompanionCoilUsedForHeatRecovery(companionCoilUsedForHeatRecovery)); ASSERT_TRUE(coilSystemCoolingWater.companionCoilUsedForHeatRecovery()); EXPECT_EQ(companionCoilUsedForHeatRecovery, coilSystemCoolingWater.companionCoilUsedForHeatRecovery().get()); } + TEST_F(ModelFixture, CoilSystemCoolingWater_HeatCoolFuelTypes) { Model m; - // TODO: Check regular Ctor arguments + CoilSystemCoolingWater coilSystemCoolingWater(m); - // TODO: Or if a UniqueModelObject (and make sure _Impl is included) - // CoilSystemCoolingWater coilSystemCoolingWater = m.getUniqueModelObject(); - EXPECT_EQ(ComponentType(ComponentType::Both), coilSystemCoolingWater.componentType()); + EXPECT_EQ(ComponentType(ComponentType::Cooling), coilSystemCoolingWater.componentType()); testFuelTypeEquality({FuelType::Electricity}, coilSystemCoolingWater.coolingFuelTypes()); - testFuelTypeEquality({FuelType::Electricity, FuelType::Propane}, coilSystemCoolingWater.heatingFuelTypes()); - testAppGFuelTypeEquality({AppGFuelType::Fuel, AppGFuelType::HeatPump}, coilSystemCoolingWater.appGHeatingFuelTypes()); + testFuelTypeEquality({}, coilSystemCoolingWater.heatingFuelTypes()); + testAppGFuelTypeEquality({}, coilSystemCoolingWater.appGHeatingFuelTypes()); +} + +TEST_F(ModelFixture, CoilSystemCoolingWater_clone) { + +} + +TEST_F(ModelFixture, CoilSystemCoolingWater_remove) { + +} + +TEST_F(ModelFixture, CoilSystemCoolingWater_addToNode) { + } From 9906df15b6dbaefef4c06cd76c936cd0f1aec647 Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Fri, 21 Mar 2025 11:51:46 -0700 Subject: [PATCH 36/58] Update model, ft, and stub tests. --- ...ForwardTranslateCoilSystemCoolingWater.cpp | 34 ++- .../Test/CoilCoolingWater_GTest.cpp | 46 ++- ...oolingWaterHeatExchangerAssisted_GTest.cpp | 271 ++++++++++++----- .../Test/CoilSystemCoolingWater_GTest.cpp | 279 ++++++++++++++++-- src/model/CoilCoolingWater.cpp | 12 + src/model/CoilSystemCoolingWater.cpp | 8 +- src/model/CoilSystemCoolingWater_Impl.hpp | 2 + src/model/ControllerWaterCoil.hpp | 2 + .../test/CoilSystemCoolingWater_GTest.cpp | 16 +- 9 files changed, 530 insertions(+), 140 deletions(-) diff --git a/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWater.cpp b/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWater.cpp index 2143ea1a1b1..47f58465373 100644 --- a/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWater.cpp +++ b/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWater.cpp @@ -27,6 +27,9 @@ #include "../../model/FanSystemModel_Impl.hpp" #include +#include +#include +#include #include using namespace openstudio::model; @@ -39,8 +42,24 @@ namespace energyplus { IdfObject idfObject = createRegisterAndNameIdfObject(openstudio::IddObjectType::CoilSystem_Cooling_Water, modelObject); - std::string airInletNodeName = modelObject.nameString() + " Cooling Inlet Node"; - std::string airOutletNodeName = modelObject.nameString() + " Cooling Outlet Node"; + std::string airInletNodeName; + // InletNodeName + if (auto mo = modelObject.inletModelObject()) { + if (auto node = mo->optionalCast()) { + airInletNodeName = node->nameString(); + } + } + + std::string airOutletNodeName; + // OutletNodeName + if (auto mo = modelObject.outletModelObject()) { + if (auto node = mo->optionalCast()) { + airOutletNodeName = node->nameString(); + } + } + + idfObject.setString(CoilSystem_Cooling_WaterFields::AirInletNodeName, airInletNodeName); + idfObject.setString(CoilSystem_Cooling_WaterFields::AirOutletNodeName, airOutletNodeName); // CoolingCoilObjectType // CoolingCoilName @@ -159,6 +178,17 @@ namespace energyplus { if (boost::optional companionCoilUsedForHeatRecovery_ = modelObject.companionCoilUsedForHeatRecovery()) { if (boost::optional wo_ = translateAndMapModelObject(companionCoilUsedForHeatRecovery_.get())) { idfObject.setString(CoilSystem_Cooling_WaterFields::CompanionCoilUsedForHeatRecovery, wo_->nameString()); + if (wo_->iddObject().type() == IddObjectType::Coil_Cooling_Water) { + wo_->setString(Coil_Cooling_WaterFields::AirInletNodeName, ""); // FIXME + wo_->setString(Coil_Cooling_WaterFields::AirOutletNodeName, ""); // FIXME + // Add IddObjectType::Coil_Cooling_Water_DetailedGeometry if implemented + } else { + // Shouldn't happen, accepts only Coil:Cooling:Water or Coil:Cooling:Water:DetailedGeometry + // Shouldn't happen, accepts only Coil:Cooling:DX:SingleSpeed or Coil:Cooling:DX:VariableSpeed + LOG(Fatal, modelObject.briefDescription() << " appears to have a companion coil used for heat recovery that shouldn't have been accepted: " + << companionCoilUsedForHeatRecovery_.get().briefDescription()); + OS_ASSERT(false); + } } } diff --git a/src/energyplus/Test/CoilCoolingWater_GTest.cpp b/src/energyplus/Test/CoilCoolingWater_GTest.cpp index 453f0822e8a..e4c570555ce 100644 --- a/src/energyplus/Test/CoilCoolingWater_GTest.cpp +++ b/src/energyplus/Test/CoilCoolingWater_GTest.cpp @@ -24,7 +24,6 @@ #include "../../utilities/idf/WorkspaceExtensibleGroup.hpp" #include -#include #include #include #include @@ -69,9 +68,6 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilCoolingWater_Unitary) { ASSERT_EQ(1u, idfCoils.size()); WorkspaceObject idfCoil(idfCoils[0]); - // No CoilSystem:Cooling:Water wrapper needed, it's inside a unitary - EXPECT_EQ(0, w.getObjectsByType(IddObjectType::CoilSystem_Cooling_Water).size()); - // Check that the Unitary ends up with the CoilCoolingWater EXPECT_EQ("Coil:Cooling:Water", idfUnitary.getString(AirLoopHVAC_UnitarySystemFields::CoolingCoilObjectType).get()); EXPECT_EQ(idfCoil.nameString(), idfUnitary.getString(AirLoopHVAC_UnitarySystemFields::CoolingCoilName).get()); @@ -124,13 +120,6 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilCoolingWater_AirLoopHVAC) { ASSERT_EQ(1u, idfCoils.size()); WorkspaceObject idfCoil(idfCoils[0]); - EXPECT_EQ(idfCoil.getString(Coil_Cooling_WaterFields::WaterInletNodeName).get(), coil.waterInletModelObject().get().nameString()); - EXPECT_EQ(idfCoil.getString(Coil_Cooling_WaterFields::WaterOutletNodeName).get(), coil.waterOutletModelObject().get().nameString()); - EXPECT_EQ(idfCoil.getString(Coil_Cooling_WaterFields::AirInletNodeName).get(), coil.airInletModelObject().get().nameString()); - EXPECT_EQ(idfCoil.getString(Coil_Cooling_WaterFields::AirOutletNodeName).get(), coil.airOutletModelObject().get().nameString()); - - EXPECT_EQ(1, w.getObjectsByType(IddObjectType::CoilSystem_Cooling_Water).size()); - // Go from AirLoopHVAC to BranchList to Branch WorkspaceObjectVector idf_airloops = w.getObjectsByType(IddObjectType::AirLoopHVAC); ASSERT_EQ(1u, idf_airloops.size()); @@ -149,25 +138,24 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilCoolingWater_AirLoopHVAC) { EXPECT_EQ(w_eg2.getString(BranchExtensibleFields::ComponentInletNodeName).get(), coil.airInletModelObject().get().nameString()); EXPECT_EQ(w_eg2.getString(BranchExtensibleFields::ComponentOutletNodeName).get(), coil.airOutletModelObject().get().nameString()); + EXPECT_EQ("Coil:Cooling:Water", w_eg2.getString(BranchExtensibleFields::ComponentObjectType).get()); - EXPECT_EQ("CoilSystem:Cooling:Water", w_eg2.getString(BranchExtensibleFields::ComponentObjectType).get()); - auto idf_coilSystem = w_eg2.getTarget(BranchExtensibleFields::ComponentName).get(); - // CoilSystem:Cooling:Water wrapper needed, it's not inside a unitary - EXPECT_EQ(1, w.getObjectsByType(IddObjectType::CoilSystem_Cooling_Water).size()); - - EXPECT_EQ(coil.airInletModelObject().get().nameString(), idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::AirInletNodeName).get()); - EXPECT_EQ(coil.airOutletModelObject().get().nameString(), idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::AirOutletNodeName).get()); - EXPECT_EQ("Always On Discrete", idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::AvailabilityScheduleName).get()); - EXPECT_EQ("Coil:Cooling:Water", idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::CoolingCoilObjectType).get()); - EXPECT_EQ(coil.nameString(), idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::CoolingCoilName).get()); - EXPECT_EQ(idfCoil, idf_coilSystem.getTarget(CoilSystem_Cooling_WaterFields::CoolingCoilName).get()); - EXPECT_TRUE(idf_coilSystem.isEmpty(CoilSystem_Cooling_WaterFields::DehumidificationControlType)); - EXPECT_TRUE(idf_coilSystem.isEmpty(CoilSystem_Cooling_WaterFields::RunonSensibleLoad)); - EXPECT_TRUE(idf_coilSystem.isEmpty(CoilSystem_Cooling_WaterFields::RunonLatentLoad)); - EXPECT_TRUE(idf_coilSystem.isEmpty(CoilSystem_Cooling_WaterFields::MinimumAirToWaterTemperatureOffset)); - EXPECT_TRUE(idf_coilSystem.isEmpty(CoilSystem_Cooling_WaterFields::EconomizerLockout)); - EXPECT_TRUE(idf_coilSystem.isEmpty(CoilSystem_Cooling_WaterFields::MinimumWaterLoopTemperatureForHeatRecovery)); - EXPECT_TRUE(idf_coilSystem.isEmpty(CoilSystem_Cooling_WaterFields::CompanionCoilUsedForHeatRecovery)); + EXPECT_EQ(coil.nameString(), idfCoil.getString(Coil_Cooling_WaterFields::Name).get()); + EXPECT_EQ("Always On Discrete", idfCoil.getString(Coil_Cooling_WaterFields::AvailabilityScheduleName).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignWaterFlowRate).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignAirFlowRate).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignInletWaterTemperature).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignInletAirTemperature).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignInletAirHumidityRatio).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignOutletAirHumidityRatio).get()); + EXPECT_EQ(coil.waterInletModelObject().get().nameString(), idfCoil.getString(Coil_Cooling_WaterFields::WaterInletNodeName).get()); + EXPECT_EQ(coil.waterOutletModelObject().get().nameString(), idfCoil.getString(Coil_Cooling_WaterFields::WaterOutletNodeName).get()); + EXPECT_EQ(coil.airInletModelObject().get().nameString(), idfCoil.getString(Coil_Cooling_WaterFields::AirInletNodeName).get()); + EXPECT_EQ(coil.airOutletModelObject().get().nameString(), idfCoil.getString(Coil_Cooling_WaterFields::AirOutletNodeName).get()); + EXPECT_EQ("SimpleAnalysis", idfCoil.getString(Coil_Cooling_WaterFields::TypeofAnalysis).get()); + EXPECT_EQ("CrossFlow", idfCoil.getString(Coil_Cooling_WaterFields::HeatExchangerConfiguration).get()); + EXPECT_TRUE(idfCoil.isEmpty(Coil_Cooling_WaterFields::CondensateCollectionWaterStorageTankName)); + EXPECT_TRUE(idfCoil.isEmpty(Coil_Cooling_WaterFields::DesignWaterTemperatureDifference)); // Check Controller:WaterCoil created by coil.addToNode EXPECT_EQ(1, w.getObjectsByType(IddObjectType::Controller_WaterCoil).size()); diff --git a/src/energyplus/Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp b/src/energyplus/Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp index 6ed8a796fdc..423dc1f09c8 100644 --- a/src/energyplus/Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp +++ b/src/energyplus/Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp @@ -28,7 +28,7 @@ #include "../../utilities/idf/WorkspaceExtensibleGroup.hpp" #include -#include +#include #include #include #include @@ -68,20 +68,24 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWaterHeatExchangerA ASSERT_EQ(1u, idfUnitarys.size()); WorkspaceObject idfUnitary(idfUnitarys[0]); - WorkspaceObjectVector idfCoils(w.getObjectsByType(IddObjectType::CoilSystem_Cooling_Water_HeatExchangerAssisted)); - ASSERT_EQ(1u, idfCoils.size()); - WorkspaceObject idfCoil(idfCoils[0]); + WorkspaceObjectVector idfCoilSystems(w.getObjectsByType(IddObjectType::CoilSystem_Cooling_Water_HeatExchangerAssisted)); + ASSERT_EQ(1u, idfCoilSystems.size()); + WorkspaceObject idfCoilSystem(idfCoilSystems[0]); WorkspaceObjectVector idfHXs(w.getObjectsByType(IddObjectType::HeatExchanger_AirToAir_SensibleAndLatent)); ASSERT_EQ(1u, idfHXs.size()); WorkspaceObject idfHX(idfHXs[0]); + WorkspaceObjectVector idfCoils(w.getObjectsByType(IddObjectType::Coil_Cooling_Water)); + ASSERT_EQ(1u, idfCoils.size()); + WorkspaceObject idfCoil(idfCoils[0]); + // No CoilSystem:Cooling:Water wrapper needed, it's inside a unitary EXPECT_EQ(0, w.getObjectsByType(IddObjectType::CoilSystem_Cooling_Water).size()); // Check that the Unitary ends up with the CoilSystemCoolingWaterHeatExchangerAssisted EXPECT_EQ("CoilSystem:Cooling:Water:HeatExchangerAssisted", idfUnitary.getString(AirLoopHVAC_UnitarySystemFields::CoolingCoilObjectType).get()); - EXPECT_EQ(idfCoil.nameString(), idfUnitary.getString(AirLoopHVAC_UnitarySystemFields::CoolingCoilName).get()); + EXPECT_EQ(idfCoilSystem.nameString(), idfUnitary.getString(AirLoopHVAC_UnitarySystemFields::CoolingCoilName).get()); // Since the Unitary only has a Cooling Coil (no fan, not HC / Suppl HC), the nodes should match EXPECT_EQ(idfUnitary.getString(AirLoopHVAC_UnitarySystemFields::AirInletNodeName).get(), @@ -90,83 +94,196 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWaterHeatExchangerA EXPECT_EQ(idfUnitary.getString(AirLoopHVAC_UnitarySystemFields::AirOutletNodeName).get(), idfHX.getString(HeatExchanger_AirToAir_SensibleAndLatentFields::ExhaustAirOutletNodeName).get()); - EXPECT_EQ("My CoilSystemCoolingWaterHeatExchangerAssisted", idfCoil.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::Name).get()); + EXPECT_EQ("My CoilSystemCoolingWaterHeatExchangerAssisted", + idfCoilSystem.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::Name).get()); EXPECT_EQ("HeatExchanger:AirToAir:SensibleAndLatent", - idfCoil.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::HeatExchangerObjectType).get()); - EXPECT_EQ(coil.heatExchanger().nameString(), idfCoil.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::HeatExchangerName).get()); - EXPECT_EQ("Coil:Cooling:Water", idfCoil.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::CoolingCoilObjectType).get()); - EXPECT_EQ(coil.coolingCoil().nameString(), idfCoil.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::CoolingCoilName).get()); + idfCoilSystem.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::HeatExchangerObjectType).get()); + EXPECT_EQ(coil.heatExchanger().nameString(), + idfCoilSystem.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::HeatExchangerName).get()); + EXPECT_EQ("Coil:Cooling:Water", idfCoilSystem.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::CoolingCoilObjectType).get()); + EXPECT_EQ(coil.coolingCoil().nameString(), idfCoilSystem.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::CoolingCoilName).get()); // Check Controller:WaterCoil created by coil.addToNode - EXPECT_EQ(1, w.getObjectsByType(IddObjectType::Controller_WaterCoil).size()); // why is this 1? - - WorkspaceObjectVector idfControllers(w.getObjectsByType(IddObjectType::Controller_WaterCoil)); - ASSERT_EQ(1u, idfControllers.size()); - WorkspaceObject idfController(idfControllers[0]); + EXPECT_EQ(1, w.getObjectsByType(IddObjectType::Controller_WaterCoil).size()); - EXPECT_EQ("", idfController.getString(Controller_WaterCoilFields::Name).get()); + EXPECT_EQ(coil.coolingCoil().nameString(), idfCoil.getString(Coil_Cooling_WaterFields::Name).get()); + EXPECT_EQ("Always On Discrete", idfCoil.getString(Coil_Cooling_WaterFields::AvailabilityScheduleName).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignWaterFlowRate).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignAirFlowRate).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignInletWaterTemperature).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignInletAirTemperature).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignInletAirHumidityRatio).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignOutletAirHumidityRatio).get()); + EXPECT_EQ(coil.coolingCoil().waterInletModelObject().get().nameString(), idfCoil.getString(Coil_Cooling_WaterFields::WaterInletNodeName).get()); + EXPECT_EQ(coil.coolingCoil().waterOutletModelObject().get().nameString(), idfCoil.getString(Coil_Cooling_WaterFields::WaterOutletNodeName).get()); + EXPECT_EQ(idfHX.getString(HeatExchanger_AirToAir_SensibleAndLatentFields::SupplyAirOutletNodeName).get(), + idfCoil.getString(Coil_Cooling_WaterFields::AirInletNodeName).get()); + EXPECT_EQ(idfHX.getString(HeatExchanger_AirToAir_SensibleAndLatentFields::ExhaustAirInletNodeName).get(), + idfCoil.getString(Coil_Cooling_WaterFields::AirOutletNodeName).get()); + EXPECT_EQ("SimpleAnalysis", idfCoil.getString(Coil_Cooling_WaterFields::TypeofAnalysis).get()); + EXPECT_EQ("CrossFlow", idfCoil.getString(Coil_Cooling_WaterFields::HeatExchangerConfiguration).get()); + EXPECT_TRUE(idfCoil.isEmpty(Coil_Cooling_WaterFields::CondensateCollectionWaterStorageTankName)); + EXPECT_TRUE(idfCoil.isEmpty(Coil_Cooling_WaterFields::DesignWaterTemperatureDifference)); } TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWaterHeatExchangerAssisted_AirLoopHVAC) { - Model m; - CoilSystemCoolingWaterHeatExchangerAssisted coil(m); - - // put it on an AirLoopHVAC - AirLoopHVAC airLoop(m); - Node supplyOutletNode = airLoop.supplyOutletNode(); - EXPECT_TRUE(coil.addToNode(supplyOutletNode)); - - // They must be connected to a PlantLoop too - PlantLoop chw_p(m); - chw_p.addDemandBranchForComponent(coil.coolingCoil()); - - ForwardTranslator ft; - Workspace w = ft.translateModel(m); - - WorkspaceObjectVector idfCoils(w.getObjectsByType(IddObjectType::CoilSystem_Cooling_Water_HeatExchangerAssisted)); - ASSERT_EQ(1u, idfCoils.size()); - WorkspaceObject idfCoil(idfCoils[0]); - - EXPECT_EQ(1, w.getObjectsByType(IddObjectType::CoilSystem_Cooling_Water).size()); - - // Go from AirLoopHVAC to BranchList to Branch - WorkspaceObjectVector idf_airloops = w.getObjectsByType(IddObjectType::AirLoopHVAC); - ASSERT_EQ(1u, idf_airloops.size()); - - WorkspaceObject& idf_airLoopHVAC = idf_airloops.front(); - WorkspaceObject idf_brlist = idf_airLoopHVAC.getTarget(AirLoopHVACFields::BranchListName).get(); - - // Should have one branch only - ASSERT_EQ(1u, idf_brlist.extensibleGroups().size()); - auto w_eg = idf_brlist.extensibleGroups()[0].cast(); - WorkspaceObject idf_branch = w_eg.getTarget(BranchListExtensibleFields::BranchName).get(); - - // There should be only one equipment on the branch - ASSERT_EQ(1u, idf_branch.extensibleGroups().size()); - auto w_eg2 = idf_branch.extensibleGroups()[0].cast(); - - EXPECT_EQ(w_eg2.getString(BranchExtensibleFields::ComponentInletNodeName).get(), coil.inletModelObject().get().nameString()); - EXPECT_EQ(w_eg2.getString(BranchExtensibleFields::ComponentOutletNodeName).get(), coil.outletModelObject().get().nameString()); - - EXPECT_EQ("CoilSystem:Cooling:Water", w_eg2.getString(BranchExtensibleFields::ComponentObjectType).get()); - auto idf_coilSystem = w_eg2.getTarget(BranchExtensibleFields::ComponentName).get(); - // CoilSystem:Cooling:Water wrapper needed, it's not inside a unitary - EXPECT_EQ(1, w.getObjectsByType(IddObjectType::CoilSystem_Cooling_Water).size()); - - EXPECT_EQ(coil.inletModelObject().get().nameString(), idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::AirInletNodeName).get()); - EXPECT_EQ(coil.outletModelObject().get().nameString(), idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::AirOutletNodeName).get()); - EXPECT_TRUE(idf_coilSystem.isEmpty(CoilSystem_Cooling_WaterFields::AvailabilityScheduleName)); - EXPECT_EQ("CoilSystem:Cooling:Water:HeatExchangerAssisted", idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::CoolingCoilObjectType).get()); - EXPECT_EQ(coil.nameString(), idf_coilSystem.getString(CoilSystem_Cooling_WaterFields::CoolingCoilName).get()); - EXPECT_EQ(idfCoil, idf_coilSystem.getTarget(CoilSystem_Cooling_WaterFields::CoolingCoilName).get()); - EXPECT_TRUE(idf_coilSystem.isEmpty(CoilSystem_Cooling_WaterFields::DehumidificationControlType)); - EXPECT_TRUE(idf_coilSystem.isEmpty(CoilSystem_Cooling_WaterFields::RunonSensibleLoad)); - EXPECT_TRUE(idf_coilSystem.isEmpty(CoilSystem_Cooling_WaterFields::RunonLatentLoad)); - EXPECT_TRUE(idf_coilSystem.isEmpty(CoilSystem_Cooling_WaterFields::MinimumAirToWaterTemperatureOffset)); - EXPECT_TRUE(idf_coilSystem.isEmpty(CoilSystem_Cooling_WaterFields::EconomizerLockout)); - EXPECT_TRUE(idf_coilSystem.isEmpty(CoilSystem_Cooling_WaterFields::MinimumWaterLoopTemperatureForHeatRecovery)); - EXPECT_TRUE(idf_coilSystem.isEmpty(CoilSystem_Cooling_WaterFields::CompanionCoilUsedForHeatRecovery)); - - // Check Controller:WaterCoil created by coil.addToNode - EXPECT_EQ(1, w.getObjectsByType(IddObjectType::Controller_WaterCoil).size()); + // connect coil system to air loop, and then connect coil to plant + { + Model m; + CoilSystemCoolingWaterHeatExchangerAssisted coil(m); + + // put it on an AirLoopHVAC + AirLoopHVAC airLoop(m); + Node supplyOutletNode = airLoop.supplyOutletNode(); + EXPECT_TRUE(coil.addToNode(supplyOutletNode)); + + // They must be connected to a PlantLoop too + PlantLoop chw_p(m); + chw_p.addDemandBranchForComponent(coil.coolingCoil()); + + ForwardTranslator ft; + Workspace w = ft.translateModel(m); + + WorkspaceObjectVector idfCoilSystems(w.getObjectsByType(IddObjectType::CoilSystem_Cooling_Water_HeatExchangerAssisted)); + ASSERT_EQ(1u, idfCoilSystems.size()); + WorkspaceObject idfCoilSystem(idfCoilSystems[0]); + + WorkspaceObjectVector idfCoils(w.getObjectsByType(IddObjectType::Coil_Cooling_Water)); + ASSERT_EQ(1u, idfCoils.size()); + WorkspaceObject idfCoil(idfCoils[0]); + + WorkspaceObjectVector idfHXs(w.getObjectsByType(IddObjectType::HeatExchanger_AirToAir_SensibleAndLatent)); + ASSERT_EQ(1u, idfHXs.size()); + WorkspaceObject idfHX(idfHXs[0]); + + // Go from AirLoopHVAC to BranchList to Branch + WorkspaceObjectVector idf_airloops = w.getObjectsByType(IddObjectType::AirLoopHVAC); + ASSERT_EQ(1u, idf_airloops.size()); + + WorkspaceObject& idf_airLoopHVAC = idf_airloops.front(); + WorkspaceObject idf_brlist = idf_airLoopHVAC.getTarget(AirLoopHVACFields::BranchListName).get(); + + // Should have one branch only + ASSERT_EQ(1u, idf_brlist.extensibleGroups().size()); + auto w_eg = idf_brlist.extensibleGroups()[0].cast(); + WorkspaceObject idf_branch = w_eg.getTarget(BranchListExtensibleFields::BranchName).get(); + + // There should be only one equipment on the branch + ASSERT_EQ(1u, idf_branch.extensibleGroups().size()); + auto w_eg2 = idf_branch.extensibleGroups()[0].cast(); + + EXPECT_EQ(w_eg2.getString(BranchExtensibleFields::ComponentInletNodeName).get(), coil.inletModelObject().get().nameString()); + EXPECT_EQ(w_eg2.getString(BranchExtensibleFields::ComponentOutletNodeName).get(), coil.outletModelObject().get().nameString()); + EXPECT_EQ("CoilSystem:Cooling:Water:HeatExchangerAssisted", w_eg2.getString(BranchExtensibleFields::ComponentObjectType).get()); + + EXPECT_EQ(coil.nameString(), idfCoilSystem.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::Name).get()); + EXPECT_EQ("HeatExchanger:AirToAir:SensibleAndLatent", + idfCoilSystem.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::HeatExchangerObjectType).get()); + EXPECT_EQ(coil.heatExchanger().nameString(), + idfCoilSystem.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::HeatExchangerName).get()); + EXPECT_EQ("Coil:Cooling:Water", idfCoilSystem.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::CoolingCoilObjectType).get()); + EXPECT_EQ(coil.coolingCoil().nameString(), idfCoilSystem.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::CoolingCoilName).get()); + + // Check Controller:WaterCoil created by coil.addToNode + EXPECT_EQ(1, w.getObjectsByType(IddObjectType::Controller_WaterCoil).size()); + + EXPECT_EQ(coil.coolingCoil().nameString(), idfCoil.getString(Coil_Cooling_WaterFields::Name).get()); + EXPECT_EQ("Always On Discrete", idfCoil.getString(Coil_Cooling_WaterFields::AvailabilityScheduleName).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignWaterFlowRate).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignAirFlowRate).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignInletWaterTemperature).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignInletAirTemperature).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignInletAirHumidityRatio).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignOutletAirHumidityRatio).get()); + EXPECT_EQ(coil.coolingCoil().waterInletModelObject().get().nameString(), idfCoil.getString(Coil_Cooling_WaterFields::WaterInletNodeName).get()); + EXPECT_EQ(coil.coolingCoil().waterOutletModelObject().get().nameString(), idfCoil.getString(Coil_Cooling_WaterFields::WaterOutletNodeName).get()); + EXPECT_EQ(idfHX.getString(HeatExchanger_AirToAir_SensibleAndLatentFields::SupplyAirOutletNodeName).get(), + idfCoil.getString(Coil_Cooling_WaterFields::AirInletNodeName).get()); + EXPECT_EQ(idfHX.getString(HeatExchanger_AirToAir_SensibleAndLatentFields::ExhaustAirInletNodeName).get(), + idfCoil.getString(Coil_Cooling_WaterFields::AirOutletNodeName).get()); + EXPECT_EQ("SimpleAnalysis", idfCoil.getString(Coil_Cooling_WaterFields::TypeofAnalysis).get()); + EXPECT_EQ("CrossFlow", idfCoil.getString(Coil_Cooling_WaterFields::HeatExchangerConfiguration).get()); + EXPECT_TRUE(idfCoil.isEmpty(Coil_Cooling_WaterFields::CondensateCollectionWaterStorageTankName)); + EXPECT_TRUE(idfCoil.isEmpty(Coil_Cooling_WaterFields::DesignWaterTemperatureDifference)); + } + + // Test for #4895: connect coil to plant, and then connect coil system to air loop + { + Model m; + CoilSystemCoolingWaterHeatExchangerAssisted coil(m); + + // They must be connected to a PlantLoop too + PlantLoop chw_p(m); + chw_p.addDemandBranchForComponent(coil.coolingCoil()); + + // put it on an AirLoopHVAC + AirLoopHVAC airLoop(m); + Node supplyOutletNode = airLoop.supplyOutletNode(); + EXPECT_TRUE(coil.addToNode(supplyOutletNode)); + + ForwardTranslator ft; + Workspace w = ft.translateModel(m); + + WorkspaceObjectVector idfCoilSystems(w.getObjectsByType(IddObjectType::CoilSystem_Cooling_Water_HeatExchangerAssisted)); + ASSERT_EQ(1u, idfCoilSystems.size()); + WorkspaceObject idfCoilSystem(idfCoilSystems[0]); + + WorkspaceObjectVector idfCoils(w.getObjectsByType(IddObjectType::Coil_Cooling_Water)); + ASSERT_EQ(1u, idfCoils.size()); + WorkspaceObject idfCoil(idfCoils[0]); + + WorkspaceObjectVector idfHXs(w.getObjectsByType(IddObjectType::HeatExchanger_AirToAir_SensibleAndLatent)); + ASSERT_EQ(1u, idfHXs.size()); + WorkspaceObject idfHX(idfHXs[0]); + + // Go from AirLoopHVAC to BranchList to Branch + WorkspaceObjectVector idf_airloops = w.getObjectsByType(IddObjectType::AirLoopHVAC); + ASSERT_EQ(1u, idf_airloops.size()); + + WorkspaceObject& idf_airLoopHVAC = idf_airloops.front(); + WorkspaceObject idf_brlist = idf_airLoopHVAC.getTarget(AirLoopHVACFields::BranchListName).get(); + + // Should have one branch only + ASSERT_EQ(1u, idf_brlist.extensibleGroups().size()); + auto w_eg = idf_brlist.extensibleGroups()[0].cast(); + WorkspaceObject idf_branch = w_eg.getTarget(BranchListExtensibleFields::BranchName).get(); + + // There should be only one equipment on the branch + ASSERT_EQ(1u, idf_branch.extensibleGroups().size()); + auto w_eg2 = idf_branch.extensibleGroups()[0].cast(); + + EXPECT_EQ(w_eg2.getString(BranchExtensibleFields::ComponentInletNodeName).get(), coil.inletModelObject().get().nameString()); + EXPECT_EQ(w_eg2.getString(BranchExtensibleFields::ComponentOutletNodeName).get(), coil.outletModelObject().get().nameString()); + EXPECT_EQ("CoilSystem:Cooling:Water:HeatExchangerAssisted", w_eg2.getString(BranchExtensibleFields::ComponentObjectType).get()); + + EXPECT_EQ(coil.nameString(), idfCoilSystem.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::Name).get()); + EXPECT_EQ("HeatExchanger:AirToAir:SensibleAndLatent", + idfCoilSystem.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::HeatExchangerObjectType).get()); + EXPECT_EQ(coil.heatExchanger().nameString(), + idfCoilSystem.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::HeatExchangerName).get()); + EXPECT_EQ("Coil:Cooling:Water", idfCoilSystem.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::CoolingCoilObjectType).get()); + EXPECT_EQ(coil.coolingCoil().nameString(), idfCoilSystem.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::CoolingCoilName).get()); + + // Check Controller:WaterCoil created by coil.addToNode + EXPECT_EQ(1, w.getObjectsByType(IddObjectType::Controller_WaterCoil).size()); + + EXPECT_EQ(coil.coolingCoil().nameString(), idfCoil.getString(Coil_Cooling_WaterFields::Name).get()); + EXPECT_EQ("Always On Discrete", idfCoil.getString(Coil_Cooling_WaterFields::AvailabilityScheduleName).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignWaterFlowRate).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignAirFlowRate).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignInletWaterTemperature).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignInletAirTemperature).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignInletAirHumidityRatio).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignOutletAirHumidityRatio).get()); + EXPECT_EQ(coil.coolingCoil().waterInletModelObject().get().nameString(), idfCoil.getString(Coil_Cooling_WaterFields::WaterInletNodeName).get()); + EXPECT_EQ(coil.coolingCoil().waterOutletModelObject().get().nameString(), idfCoil.getString(Coil_Cooling_WaterFields::WaterOutletNodeName).get()); + EXPECT_EQ(idfHX.getString(HeatExchanger_AirToAir_SensibleAndLatentFields::SupplyAirOutletNodeName).get(), + idfCoil.getString(Coil_Cooling_WaterFields::AirInletNodeName).get()); + EXPECT_EQ(idfHX.getString(HeatExchanger_AirToAir_SensibleAndLatentFields::ExhaustAirInletNodeName).get(), + idfCoil.getString(Coil_Cooling_WaterFields::AirOutletNodeName).get()); + EXPECT_EQ("SimpleAnalysis", idfCoil.getString(Coil_Cooling_WaterFields::TypeofAnalysis).get()); + EXPECT_EQ("CrossFlow", idfCoil.getString(Coil_Cooling_WaterFields::HeatExchangerConfiguration).get()); + EXPECT_TRUE(idfCoil.isEmpty(Coil_Cooling_WaterFields::CondensateCollectionWaterStorageTankName)); + EXPECT_TRUE(idfCoil.isEmpty(Coil_Cooling_WaterFields::DesignWaterTemperatureDifference)); + } } diff --git a/src/energyplus/Test/CoilSystemCoolingWater_GTest.cpp b/src/energyplus/Test/CoilSystemCoolingWater_GTest.cpp index 9418e790d80..cddf73b1b46 100644 --- a/src/energyplus/Test/CoilSystemCoolingWater_GTest.cpp +++ b/src/energyplus/Test/CoilSystemCoolingWater_GTest.cpp @@ -22,17 +22,25 @@ #include "../../utilities/idf/Workspace.hpp" #include "../../utilities/idf/IdfObject.hpp" #include "../../utilities/idf/WorkspaceObject.hpp" +#include "../../utilities/idf/IdfExtensibleGroup.hpp" +#include "../../utilities/idf/WorkspaceExtensibleGroup.hpp" // E+ FieldEnums #include #include #include +#include +#include +#include +#include +#include +#include using namespace openstudio::energyplus; using namespace openstudio::model; using namespace openstudio; -TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWater) { +TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWater_Unitary) { ForwardTranslator ft; @@ -68,21 +76,258 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWater) { chw_p.addDemandBranchForComponent(coilSystemCoolingWater.coolingCoil()); const Workspace w = ft.translateModel(m); - const auto idfObjs = w.getObjectsByType(IddObjectType::CoilSystem_Cooling_Water); - ASSERT_EQ(1u, idfObjs.size()); - - const auto& idfObject = idfObjs.front(); - EXPECT_EQ(coil.inletModelObject().get().nameString(), idfObject.getString(CoilSystem_Cooling_WaterFields::AirInletNodeName).get()); - EXPECT_EQ(coil.outletModelObject().get().nameString(), idfObject.getString(CoilSystem_Cooling_WaterFields::AirOutletNodeName).get()); - EXPECT_EQ(availabilitySchedule.nameString(), idfObject.getString(CoilSystem_Cooling_WaterFields::AvailabilityScheduleName).get()); - EXPECT_EQ("Coil:Cooling:Water", idfObject.getString(CoilSystem_Cooling_WaterFields::CoolingCoilObjectType).get()); - EXPECT_EQ(coolingCoil.nameString(), idfObject.getString(CoilSystem_Cooling_WaterFields::CoolingCoilName).get()); - EXPECT_EQ("CoolReheat", idfObject.getString(CoilSystem_Cooling_WaterFields::DehumidificationControlType).get()); - EXPECT_EQ("No", idfObject.getString(CoilSystem_Cooling_WaterFields::RunonSensibleLoad).get()); - EXPECT_EQ("Yes", idfObject.getString(CoilSystem_Cooling_WaterFields::RunonLatentLoad).get()); - EXPECT_EQ(1.0, idfObject.getDouble(CoilSystem_Cooling_WaterFields::MinimumAirToWaterTemperatureOffset).get()); - EXPECT_EQ("No", idfObject.getString(CoilSystem_Cooling_WaterFields::EconomizerLockout).get()); - EXPECT_EQ(1.2, idfObject.getDouble(CoilSystem_Cooling_WaterFields::MinimumWaterLoopTemperatureForHeatRecovery).get()); + + const auto idfUnitarys = w.getObjectsByType(IddObjectType::AirLoopHVAC_UnitarySystem); + ASSERT_EQ(1u, idfUnitarys.size()); + const auto& idfUnitary = idfUnitarys.front(); + + const auto idfCoilSystems = w.getObjectsByType(IddObjectType::CoilSystem_Cooling_Water); + ASSERT_EQ(1u, idfCoilSystems.size()); // FIXME: should unitary here be allowed? if so, we need to update those FT files? + const auto& idfCoilSystem = idfCoilSystems.front(); + + WorkspaceObjectVector idfCoils(w.getObjectsByType(IddObjectType::Coil_Cooling_Water)); + ASSERT_EQ(1u, idfCoils.size()); + WorkspaceObject idfCoil(idfCoils[0]); + + // Check that the Unitary ends up with the CoilSystemCoolingWater + EXPECT_EQ("CoilSystem:Cooling:Water", idfUnitary.getString(AirLoopHVAC_UnitarySystemFields::CoolingCoilObjectType).get()); + EXPECT_EQ(idfCoilSystem.nameString(), idfUnitary.getString(AirLoopHVAC_UnitarySystemFields::CoolingCoilName).get()); + + EXPECT_EQ(coilSystemCoolingWater.inletModelObject().get().nameString(), + idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::AirInletNodeName).get()); + EXPECT_EQ(coilSystemCoolingWater.outletModelObject().get().nameString(), + idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::AirOutletNodeName).get()); + EXPECT_EQ(availabilitySchedule.nameString(), idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::AvailabilityScheduleName).get()); + EXPECT_EQ("Coil:Cooling:Water", idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::CoolingCoilObjectType).get()); + EXPECT_EQ(coilSystemCoolingWater.coolingCoil().nameString(), idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::CoolingCoilName).get()); + EXPECT_EQ("CoolReheat", idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::DehumidificationControlType).get()); + EXPECT_EQ("No", idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::RunonSensibleLoad).get()); + EXPECT_EQ("Yes", idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::RunonLatentLoad).get()); + EXPECT_EQ(1.0, idfCoilSystem.getDouble(CoilSystem_Cooling_WaterFields::MinimumAirToWaterTemperatureOffset).get()); + EXPECT_EQ("No", idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::EconomizerLockout).get()); + EXPECT_EQ(1.2, idfCoilSystem.getDouble(CoilSystem_Cooling_WaterFields::MinimumWaterLoopTemperatureForHeatRecovery).get()); EXPECT_EQ(companionCoilUsedForHeatRecovery.nameString(), - idfObject.getString(CoilSystem_Cooling_WaterFields::CompanionCoilUsedForHeatRecovery).get()); + idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::CompanionCoilUsedForHeatRecovery).get()); + + EXPECT_EQ(0, w.getObjectsByType(IddObjectType::Controller_WaterCoil).size()); + + EXPECT_EQ(coilSystemCoolingWater.coolingCoil().nameString(), idfCoil.getString(Coil_Cooling_WaterFields::Name).get()); + EXPECT_EQ("Always On Discrete", idfCoil.getString(Coil_Cooling_WaterFields::AvailabilityScheduleName).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignWaterFlowRate).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignAirFlowRate).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignInletWaterTemperature).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignInletAirTemperature).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignInletAirHumidityRatio).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignOutletAirHumidityRatio).get()); + EXPECT_EQ(coilSystemCoolingWater.coolingCoil().waterInletModelObject().get().nameString(), + idfCoil.getString(Coil_Cooling_WaterFields::WaterInletNodeName).get()); + EXPECT_EQ(coilSystemCoolingWater.coolingCoil().waterOutletModelObject().get().nameString(), + idfCoil.getString(Coil_Cooling_WaterFields::WaterOutletNodeName).get()); + EXPECT_EQ(idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::AirInletNodeName).get(), + idfCoil.getString(Coil_Cooling_WaterFields::AirInletNodeName).get()); + EXPECT_EQ(idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::AirOutletNodeName).get(), + idfCoil.getString(Coil_Cooling_WaterFields::AirOutletNodeName).get()); + EXPECT_EQ("SimpleAnalysis", idfCoil.getString(Coil_Cooling_WaterFields::TypeofAnalysis).get()); + EXPECT_EQ("CrossFlow", idfCoil.getString(Coil_Cooling_WaterFields::HeatExchangerConfiguration).get()); + EXPECT_TRUE(idfCoil.isEmpty(Coil_Cooling_WaterFields::CondensateCollectionWaterStorageTankName)); + EXPECT_TRUE(idfCoil.isEmpty(Coil_Cooling_WaterFields::DesignWaterTemperatureDifference)); +} + +TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWater_AirLoopHVAC) { + // without companion + { + ForwardTranslator ft; + + Model m; + + CoilSystemCoolingWater coilSystemCoolingWater(m); + + coilSystemCoolingWater.setName("My CoilSystemCoolingWater"); + Schedule availabilitySchedule = m.alwaysOnDiscreteSchedule(); + EXPECT_TRUE(coilSystemCoolingWater.setAvailabilitySchedule(availabilitySchedule)); + EXPECT_TRUE(coilSystemCoolingWater.setDehumidificationControlType("CoolReheat")); + EXPECT_TRUE(coilSystemCoolingWater.setRunonSensibleLoad(false)); // Opposite from IDD default + EXPECT_TRUE(coilSystemCoolingWater.setRunonLatentLoad(true)); // Opposite from IDD default + EXPECT_TRUE(coilSystemCoolingWater.setMinimumAirToWaterTemperatureOffset(1.0)); + EXPECT_TRUE(coilSystemCoolingWater.setEconomizerLockout(false)); // Opposite from IDD default + EXPECT_TRUE(coilSystemCoolingWater.setMinimumWaterLoopTemperatureForHeatRecovery(1.2)); + + // put it inside a Unitary, and put Unitary on an AirLoopHVAC so it gets translated + AirLoopHVAC airLoop(m); + Node supplyOutletNode = airLoop.supplyOutletNode(); + EXPECT_TRUE(coilSystemCoolingWater.addToNode(supplyOutletNode)); + + // They must be connected to a PlantLoop too + PlantLoop chw_p(m); + chw_p.addDemandBranchForComponent(coilSystemCoolingWater.coolingCoil()); + + const Workspace w = ft.translateModel(m); + + const auto idfCoilSystems = w.getObjectsByType(IddObjectType::CoilSystem_Cooling_Water); + ASSERT_EQ(1u, idfCoilSystems.size()); + const auto& idfCoilSystem = idfCoilSystems.front(); + + WorkspaceObjectVector idfCoils(w.getObjectsByType(IddObjectType::Coil_Cooling_Water)); + ASSERT_EQ(1u, idfCoils.size()); + WorkspaceObject idfCoil(idfCoils[0]); + + // Go from AirLoopHVAC to BranchList to Branch + WorkspaceObjectVector idf_airloops = w.getObjectsByType(IddObjectType::AirLoopHVAC); + ASSERT_EQ(1u, idf_airloops.size()); + + WorkspaceObject& idf_airLoopHVAC = idf_airloops.front(); + WorkspaceObject idf_brlist = idf_airLoopHVAC.getTarget(AirLoopHVACFields::BranchListName).get(); + + // Should have one branch only + ASSERT_EQ(1u, idf_brlist.extensibleGroups().size()); + auto w_eg = idf_brlist.extensibleGroups()[0].cast(); + WorkspaceObject idf_branch = w_eg.getTarget(BranchListExtensibleFields::BranchName).get(); + + // There should be only one equipment on the branch + ASSERT_EQ(1u, idf_branch.extensibleGroups().size()); + auto w_eg2 = idf_branch.extensibleGroups()[0].cast(); + + EXPECT_EQ(w_eg2.getString(BranchExtensibleFields::ComponentInletNodeName).get(), coilSystemCoolingWater.inletModelObject().get().nameString()); + EXPECT_EQ(w_eg2.getString(BranchExtensibleFields::ComponentOutletNodeName).get(), coilSystemCoolingWater.outletModelObject().get().nameString()); + EXPECT_EQ("CoilSystem:Cooling:Water", w_eg2.getString(BranchExtensibleFields::ComponentObjectType).get()); + + EXPECT_EQ(coilSystemCoolingWater.inletModelObject().get().nameString(), + idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::AirInletNodeName).get()); + EXPECT_EQ(coilSystemCoolingWater.outletModelObject().get().nameString(), + idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::AirOutletNodeName).get()); + EXPECT_EQ(availabilitySchedule.nameString(), idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::AvailabilityScheduleName).get()); + EXPECT_EQ("Coil:Cooling:Water", idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::CoolingCoilObjectType).get()); + EXPECT_EQ(coilSystemCoolingWater.coolingCoil().nameString(), idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::CoolingCoilName).get()); + EXPECT_EQ("CoolReheat", idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::DehumidificationControlType).get()); + EXPECT_EQ("No", idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::RunonSensibleLoad).get()); + EXPECT_EQ("Yes", idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::RunonLatentLoad).get()); + EXPECT_EQ(1.0, idfCoilSystem.getDouble(CoilSystem_Cooling_WaterFields::MinimumAirToWaterTemperatureOffset).get()); + EXPECT_EQ("No", idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::EconomizerLockout).get()); + EXPECT_EQ(1.2, idfCoilSystem.getDouble(CoilSystem_Cooling_WaterFields::MinimumWaterLoopTemperatureForHeatRecovery).get()); + EXPECT_TRUE(idfCoilSystem.isEmpty(CoilSystem_Cooling_WaterFields::CompanionCoilUsedForHeatRecovery)); + + EXPECT_EQ(0, w.getObjectsByType(IddObjectType::Controller_WaterCoil) + .size()); // FIXME: what's creating this if i have it commented out in the addToNode method? + + EXPECT_EQ(coilSystemCoolingWater.coolingCoil().nameString(), idfCoil.getString(Coil_Cooling_WaterFields::Name).get()); + EXPECT_EQ("Always On Discrete", idfCoil.getString(Coil_Cooling_WaterFields::AvailabilityScheduleName).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignWaterFlowRate).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignAirFlowRate).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignInletWaterTemperature).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignInletAirTemperature).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignInletAirHumidityRatio).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignOutletAirHumidityRatio).get()); + EXPECT_EQ(coilSystemCoolingWater.coolingCoil().waterInletModelObject().get().nameString(), + idfCoil.getString(Coil_Cooling_WaterFields::WaterInletNodeName).get()); + EXPECT_EQ(coilSystemCoolingWater.coolingCoil().waterOutletModelObject().get().nameString(), + idfCoil.getString(Coil_Cooling_WaterFields::WaterOutletNodeName).get()); + EXPECT_EQ(idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::AirInletNodeName).get(), + idfCoil.getString(Coil_Cooling_WaterFields::AirInletNodeName).get()); + EXPECT_EQ(idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::AirOutletNodeName).get(), + idfCoil.getString(Coil_Cooling_WaterFields::AirOutletNodeName).get()); + EXPECT_EQ("SimpleAnalysis", idfCoil.getString(Coil_Cooling_WaterFields::TypeofAnalysis).get()); + EXPECT_EQ("CrossFlow", idfCoil.getString(Coil_Cooling_WaterFields::HeatExchangerConfiguration).get()); + EXPECT_TRUE(idfCoil.isEmpty(Coil_Cooling_WaterFields::CondensateCollectionWaterStorageTankName)); + EXPECT_TRUE(idfCoil.isEmpty(Coil_Cooling_WaterFields::DesignWaterTemperatureDifference)); + } + + // with companion + { + ForwardTranslator ft; + + Model m; + + CoilSystemCoolingWater coilSystemCoolingWater(m); + + coilSystemCoolingWater.setName("My CoilSystemCoolingWater"); + Schedule availabilitySchedule = m.alwaysOnDiscreteSchedule(); + EXPECT_TRUE(coilSystemCoolingWater.setAvailabilitySchedule(availabilitySchedule)); + EXPECT_TRUE(coilSystemCoolingWater.setDehumidificationControlType("CoolReheat")); + EXPECT_TRUE(coilSystemCoolingWater.setRunonSensibleLoad(false)); // Opposite from IDD default + EXPECT_TRUE(coilSystemCoolingWater.setRunonLatentLoad(true)); // Opposite from IDD default + EXPECT_TRUE(coilSystemCoolingWater.setMinimumAirToWaterTemperatureOffset(1.0)); + EXPECT_TRUE(coilSystemCoolingWater.setEconomizerLockout(false)); // Opposite from IDD default + EXPECT_TRUE(coilSystemCoolingWater.setMinimumWaterLoopTemperatureForHeatRecovery(1.2)); + CoilCoolingWater companionCoilUsedForHeatRecovery(m); + EXPECT_TRUE(coilSystemCoolingWater.setCompanionCoilUsedForHeatRecovery(companionCoilUsedForHeatRecovery)); + + // put it inside a Unitary, and put Unitary on an AirLoopHVAC so it gets translated + AirLoopHVAC airLoop(m); + Node supplyOutletNode = airLoop.supplyOutletNode(); + EXPECT_TRUE(coilSystemCoolingWater.addToNode(supplyOutletNode)); + + // They must be connected to a PlantLoop too + PlantLoop chw_p(m); + chw_p.addDemandBranchForComponent(coilSystemCoolingWater.coolingCoil()); + + const Workspace w = ft.translateModel(m); + + const auto idfCoilSystems = w.getObjectsByType(IddObjectType::CoilSystem_Cooling_Water); + ASSERT_EQ(1u, idfCoilSystems.size()); + const auto& idfCoilSystem = idfCoilSystems.front(); + + WorkspaceObjectVector idfCoils(w.getObjectsByType(IddObjectType::Coil_Cooling_Water)); + ASSERT_EQ(2u, idfCoils.size()); + WorkspaceObject idfCoil(idfCoils[0]); // FIXME: get these some other way + + // Go from AirLoopHVAC to BranchList to Branch + WorkspaceObjectVector idf_airloops = w.getObjectsByType(IddObjectType::AirLoopHVAC); + ASSERT_EQ(1u, idf_airloops.size()); + + WorkspaceObject& idf_airLoopHVAC = idf_airloops.front(); + WorkspaceObject idf_brlist = idf_airLoopHVAC.getTarget(AirLoopHVACFields::BranchListName).get(); + + // Should have one branch only + ASSERT_EQ(1u, idf_brlist.extensibleGroups().size()); + auto w_eg = idf_brlist.extensibleGroups()[0].cast(); + WorkspaceObject idf_branch = w_eg.getTarget(BranchListExtensibleFields::BranchName).get(); + + // There should be only one equipment on the branch + ASSERT_EQ(1u, idf_branch.extensibleGroups().size()); + auto w_eg2 = idf_branch.extensibleGroups()[0].cast(); + + EXPECT_EQ(w_eg2.getString(BranchExtensibleFields::ComponentInletNodeName).get(), coilSystemCoolingWater.inletModelObject().get().nameString()); + EXPECT_EQ(w_eg2.getString(BranchExtensibleFields::ComponentOutletNodeName).get(), coilSystemCoolingWater.outletModelObject().get().nameString()); + EXPECT_EQ("CoilSystem:Cooling:Water", w_eg2.getString(BranchExtensibleFields::ComponentObjectType).get()); + + EXPECT_EQ(coilSystemCoolingWater.inletModelObject().get().nameString(), + idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::AirInletNodeName).get()); + EXPECT_EQ(coilSystemCoolingWater.outletModelObject().get().nameString(), + idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::AirOutletNodeName).get()); + EXPECT_EQ(availabilitySchedule.nameString(), idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::AvailabilityScheduleName).get()); + EXPECT_EQ("Coil:Cooling:Water", idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::CoolingCoilObjectType).get()); + EXPECT_EQ(coilSystemCoolingWater.coolingCoil().nameString(), idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::CoolingCoilName).get()); + EXPECT_EQ("CoolReheat", idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::DehumidificationControlType).get()); + EXPECT_EQ("No", idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::RunonSensibleLoad).get()); + EXPECT_EQ("Yes", idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::RunonLatentLoad).get()); + EXPECT_EQ(1.0, idfCoilSystem.getDouble(CoilSystem_Cooling_WaterFields::MinimumAirToWaterTemperatureOffset).get()); + EXPECT_EQ("No", idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::EconomizerLockout).get()); + EXPECT_EQ(1.2, idfCoilSystem.getDouble(CoilSystem_Cooling_WaterFields::MinimumWaterLoopTemperatureForHeatRecovery).get()); + EXPECT_EQ(companionCoilUsedForHeatRecovery.nameString(), + idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::CompanionCoilUsedForHeatRecovery).get()); + + EXPECT_EQ(0, w.getObjectsByType(IddObjectType::Controller_WaterCoil) + .size()); // FIXME: what's creating this if i have it commented out in the addToNode method? + + EXPECT_EQ(coilSystemCoolingWater.coolingCoil().nameString(), idfCoil.getString(Coil_Cooling_WaterFields::Name).get()); + EXPECT_EQ("Always On Discrete", idfCoil.getString(Coil_Cooling_WaterFields::AvailabilityScheduleName).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignWaterFlowRate).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignAirFlowRate).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignInletWaterTemperature).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignInletAirTemperature).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignInletAirHumidityRatio).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignOutletAirHumidityRatio).get()); + EXPECT_EQ(coilSystemCoolingWater.coolingCoil().waterInletModelObject().get().nameString(), + idfCoil.getString(Coil_Cooling_WaterFields::WaterInletNodeName).get()); + EXPECT_EQ(coilSystemCoolingWater.coolingCoil().waterOutletModelObject().get().nameString(), + idfCoil.getString(Coil_Cooling_WaterFields::WaterOutletNodeName).get()); + EXPECT_EQ(idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::AirInletNodeName).get(), + idfCoil.getString(Coil_Cooling_WaterFields::AirInletNodeName).get()); + EXPECT_EQ(idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::AirOutletNodeName).get(), + idfCoil.getString(Coil_Cooling_WaterFields::AirOutletNodeName).get()); + EXPECT_EQ("SimpleAnalysis", idfCoil.getString(Coil_Cooling_WaterFields::TypeofAnalysis).get()); + EXPECT_EQ("CrossFlow", idfCoil.getString(Coil_Cooling_WaterFields::HeatExchangerConfiguration).get()); + EXPECT_TRUE(idfCoil.isEmpty(Coil_Cooling_WaterFields::CondensateCollectionWaterStorageTankName)); + EXPECT_TRUE(idfCoil.isEmpty(Coil_Cooling_WaterFields::DesignWaterTemperatureDifference)); + } } diff --git a/src/model/CoilCoolingWater.cpp b/src/model/CoilCoolingWater.cpp index 4b5d5292cb8..23dfb8e47d9 100644 --- a/src/model/CoilCoolingWater.cpp +++ b/src/model/CoilCoolingWater.cpp @@ -7,6 +7,8 @@ #include "CoilCoolingWater_Impl.hpp" #include "ControllerWaterCoil.hpp" #include "ControllerWaterCoil_Impl.hpp" +#include "CoilSystemCoolingWater.hpp" +#include "CoilSystemCoolingWater_Impl.hpp" #include "CoilSystemCoolingWaterHeatExchangerAssisted.hpp" #include "CoilSystemCoolingWaterHeatExchangerAssisted_Impl.hpp" #include "Node.hpp" @@ -374,6 +376,16 @@ namespace model { } } + // CoilSystemCoolingWater + { + auto coilSystems = model().getConcreteModelObjects(); + for (const auto& coilSystem : coilSystems) { + if (coilSystem.coolingCoil().handle() == handle()) { + return coilSystem; + } + } + } + // CoilSystemCoolingWaterHeatExchangerAssisted { auto coilSystems = model().getConcreteModelObjects(); diff --git a/src/model/CoilSystemCoolingWater.cpp b/src/model/CoilSystemCoolingWater.cpp index 08f88641544..4b565cf881e 100644 --- a/src/model/CoilSystemCoolingWater.cpp +++ b/src/model/CoilSystemCoolingWater.cpp @@ -103,10 +103,10 @@ namespace model { auto coilSystemClone = StraightComponent_Impl::clone(model).cast(); if (OptionalWaterToAirComponent intermediate = optionalCoolingCoil()) { - coilSystemClone.setCoolingCoil(intermediate->clone(model).cast()); + coilSystemClone.setCoolingCoil(intermediate->clone(model).cast()); } if (OptionalWaterToAirComponent intermediate = optionalCompanionCoilUsedForHeatRecovery()) { - coilSystemClone.setCompanionCoilUsedForHeatRecovery(intermediate->clone(model).cast()); + coilSystemClone.setCompanionCoilUsedForHeatRecovery(intermediate->clone(model).cast()); } return std::move(coilSystemClone); @@ -129,7 +129,7 @@ namespace model { } } - auto t_model = model(); + /* auto t_model = model(); ControllerWaterCoil controller(t_model); auto coilWaterInletNode = waterInletModelObject->optionalCast(); @@ -137,7 +137,7 @@ namespace model { controller.setActuatorNode(coilWaterInletNode.get()); // sensor node will be established in translator since that node does not yet exist - controller.setAction("Reverse"); + controller.setAction("Reverse"); */ } } } diff --git a/src/model/CoilSystemCoolingWater_Impl.hpp b/src/model/CoilSystemCoolingWater_Impl.hpp index f5572588d14..860dd9dc5f2 100644 --- a/src/model/CoilSystemCoolingWater_Impl.hpp +++ b/src/model/CoilSystemCoolingWater_Impl.hpp @@ -68,6 +68,8 @@ namespace model { /** @name Getters */ //@{ + Schedule availabilitySchedule() const; + WaterToAirComponent coolingCoil() const; std::string dehumidificationControlType() const; diff --git a/src/model/ControllerWaterCoil.hpp b/src/model/ControllerWaterCoil.hpp index b1e99d71d6f..bab927a4393 100644 --- a/src/model/ControllerWaterCoil.hpp +++ b/src/model/ControllerWaterCoil.hpp @@ -20,6 +20,7 @@ namespace model { class ControllerWaterCoil_Impl; class CoilCoolingWater_Impl; class CoilHeatingWater_Impl; + class CoilSystemCoolingWater_Impl; class CoilSystemCoolingWaterHeatExchangerAssisted_Impl; } // namespace detail @@ -141,6 +142,7 @@ namespace model { // Classes that need to instantiate it friend class openstudio::model::detail::CoilCoolingWater_Impl; friend class openstudio::model::detail::CoilHeatingWater_Impl; + friend class openstudio::model::detail::CoilSystemCoolingWater_Impl; friend class openstudio::model::detail::CoilSystemCoolingWaterHeatExchangerAssisted_Impl; explicit ControllerWaterCoil(const Model& model); diff --git a/src/model/test/CoilSystemCoolingWater_GTest.cpp b/src/model/test/CoilSystemCoolingWater_GTest.cpp index 573f7db6fa0..554b06722a3 100644 --- a/src/model/test/CoilSystemCoolingWater_GTest.cpp +++ b/src/model/test/CoilSystemCoolingWater_GTest.cpp @@ -69,7 +69,7 @@ TEST_F(ModelFixture, CoilSystemCoolingWater_GettersSetters) { EXPECT_EQ(1.2, coilSystemCoolingWater.minimumWaterLoopTemperatureForHeatRecovery()); // Companion Coil Used For Heat Recovery: Optional Object - boost::optional companionCoilUsedForHeatRecovery(m); + CoilCoolingWater companionCoilUsedForHeatRecovery(m); EXPECT_TRUE(coilSystemCoolingWater.setCompanionCoilUsedForHeatRecovery(companionCoilUsedForHeatRecovery)); ASSERT_TRUE(coilSystemCoolingWater.companionCoilUsedForHeatRecovery()); EXPECT_EQ(companionCoilUsedForHeatRecovery, coilSystemCoolingWater.companionCoilUsedForHeatRecovery().get()); @@ -81,19 +81,13 @@ TEST_F(ModelFixture, CoilSystemCoolingWater_HeatCoolFuelTypes) { CoilSystemCoolingWater coilSystemCoolingWater(m); EXPECT_EQ(ComponentType(ComponentType::Cooling), coilSystemCoolingWater.componentType()); - testFuelTypeEquality({FuelType::Electricity}, coilSystemCoolingWater.coolingFuelTypes()); + testFuelTypeEquality({}, coilSystemCoolingWater.coolingFuelTypes()); testFuelTypeEquality({}, coilSystemCoolingWater.heatingFuelTypes()); testAppGFuelTypeEquality({}, coilSystemCoolingWater.appGHeatingFuelTypes()); } -TEST_F(ModelFixture, CoilSystemCoolingWater_clone) { - -} +TEST_F(ModelFixture, CoilSystemCoolingWater_clone) {} -TEST_F(ModelFixture, CoilSystemCoolingWater_remove) { - -} +TEST_F(ModelFixture, CoilSystemCoolingWater_remove) {} -TEST_F(ModelFixture, CoilSystemCoolingWater_addToNode) { - -} +TEST_F(ModelFixture, CoilSystemCoolingWater_addToNode) {} From 2944388f85cdb308c3daeb112de497dd8564b765 Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Fri, 21 Mar 2025 16:44:16 -0700 Subject: [PATCH 37/58] Progress toward node connections and tests passing. --- ...ForwardTranslateCoilSystemCoolingWater.cpp | 7 +- ...oolingWaterHeatExchangerAssisted_GTest.cpp | 18 +- .../Test/CoilSystemCoolingWater_GTest.cpp | 154 +++++++++--------- src/model/CoilCoolingWater.cpp | 23 ++- src/model/CoilSystemCoolingWater.cpp | 24 +-- ...ystemCoolingWaterHeatExchangerAssisted.cpp | 24 +-- .../test/CoilSystemCoolingWater_GTest.cpp | 75 ++++++++- 7 files changed, 188 insertions(+), 137 deletions(-) diff --git a/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWater.cpp b/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWater.cpp index 47f58465373..9d0f7ec0180 100644 --- a/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWater.cpp +++ b/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWater.cpp @@ -25,6 +25,8 @@ #include "../../model/FanOnOff_Impl.hpp" #include "../../model/FanSystemModel.hpp" #include "../../model/FanSystemModel_Impl.hpp" +#include "../../model/AirLoopHVACOutdoorAirSystem.hpp" +#include "../../model/AirLoopHVACOutdoorAirSystem_Impl.hpp" #include #include @@ -179,8 +181,9 @@ namespace energyplus { if (boost::optional wo_ = translateAndMapModelObject(companionCoilUsedForHeatRecovery_.get())) { idfObject.setString(CoilSystem_Cooling_WaterFields::CompanionCoilUsedForHeatRecovery, wo_->nameString()); if (wo_->iddObject().type() == IddObjectType::Coil_Cooling_Water) { - wo_->setString(Coil_Cooling_WaterFields::AirInletNodeName, ""); // FIXME - wo_->setString(Coil_Cooling_WaterFields::AirOutletNodeName, ""); // FIXME + wo_->setString(Coil_Cooling_WaterFields::AirInletNodeName, + modelObject.airLoopHVACOutdoorAirSystem()->reliefAirModelObject()->nameString()); // FIXME + wo_->setString(Coil_Cooling_WaterFields::AirOutletNodeName, airOutletNodeName); // FIXME // Add IddObjectType::Coil_Cooling_Water_DetailedGeometry if implemented } else { // Shouldn't happen, accepts only Coil:Cooling:Water or Coil:Cooling:Water:DetailedGeometry diff --git a/src/energyplus/Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp b/src/energyplus/Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp index 423dc1f09c8..e51ee3dd306 100644 --- a/src/energyplus/Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp +++ b/src/energyplus/Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp @@ -131,15 +131,18 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWaterHeatExchangerA { Model m; CoilSystemCoolingWaterHeatExchangerAssisted coil(m); + EXPECT_FALSE(coil.coolingCoil().waterInletModelObject()); // put it on an AirLoopHVAC AirLoopHVAC airLoop(m); Node supplyOutletNode = airLoop.supplyOutletNode(); EXPECT_TRUE(coil.addToNode(supplyOutletNode)); + EXPECT_FALSE(coil.coolingCoil().waterInletModelObject()); // They must be connected to a PlantLoop too PlantLoop chw_p(m); chw_p.addDemandBranchForComponent(coil.coolingCoil()); + EXPECT_TRUE(coil.coolingCoil().waterInletModelObject()); ForwardTranslator ft; Workspace w = ft.translateModel(m); @@ -184,9 +187,6 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWaterHeatExchangerA EXPECT_EQ("Coil:Cooling:Water", idfCoilSystem.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::CoolingCoilObjectType).get()); EXPECT_EQ(coil.coolingCoil().nameString(), idfCoilSystem.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::CoolingCoilName).get()); - // Check Controller:WaterCoil created by coil.addToNode - EXPECT_EQ(1, w.getObjectsByType(IddObjectType::Controller_WaterCoil).size()); - EXPECT_EQ(coil.coolingCoil().nameString(), idfCoil.getString(Coil_Cooling_WaterFields::Name).get()); EXPECT_EQ("Always On Discrete", idfCoil.getString(Coil_Cooling_WaterFields::AvailabilityScheduleName).get()); EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignWaterFlowRate).get()); @@ -205,21 +205,27 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWaterHeatExchangerA EXPECT_EQ("CrossFlow", idfCoil.getString(Coil_Cooling_WaterFields::HeatExchangerConfiguration).get()); EXPECT_TRUE(idfCoil.isEmpty(Coil_Cooling_WaterFields::CondensateCollectionWaterStorageTankName)); EXPECT_TRUE(idfCoil.isEmpty(Coil_Cooling_WaterFields::DesignWaterTemperatureDifference)); + + // Check Controller:WaterCoil created by coil.addToNode + EXPECT_EQ(1, w.getObjectsByType(IddObjectType::Controller_WaterCoil).size()); } // Test for #4895: connect coil to plant, and then connect coil system to air loop { Model m; CoilSystemCoolingWaterHeatExchangerAssisted coil(m); + EXPECT_FALSE(coil.coolingCoil().waterInletModelObject()); // They must be connected to a PlantLoop too PlantLoop chw_p(m); chw_p.addDemandBranchForComponent(coil.coolingCoil()); + EXPECT_TRUE(coil.coolingCoil().waterInletModelObject()); // put it on an AirLoopHVAC AirLoopHVAC airLoop(m); Node supplyOutletNode = airLoop.supplyOutletNode(); EXPECT_TRUE(coil.addToNode(supplyOutletNode)); + EXPECT_TRUE(coil.coolingCoil().waterInletModelObject()); ForwardTranslator ft; Workspace w = ft.translateModel(m); @@ -264,9 +270,6 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWaterHeatExchangerA EXPECT_EQ("Coil:Cooling:Water", idfCoilSystem.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::CoolingCoilObjectType).get()); EXPECT_EQ(coil.coolingCoil().nameString(), idfCoilSystem.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::CoolingCoilName).get()); - // Check Controller:WaterCoil created by coil.addToNode - EXPECT_EQ(1, w.getObjectsByType(IddObjectType::Controller_WaterCoil).size()); - EXPECT_EQ(coil.coolingCoil().nameString(), idfCoil.getString(Coil_Cooling_WaterFields::Name).get()); EXPECT_EQ("Always On Discrete", idfCoil.getString(Coil_Cooling_WaterFields::AvailabilityScheduleName).get()); EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignWaterFlowRate).get()); @@ -285,5 +288,8 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWaterHeatExchangerA EXPECT_EQ("CrossFlow", idfCoil.getString(Coil_Cooling_WaterFields::HeatExchangerConfiguration).get()); EXPECT_TRUE(idfCoil.isEmpty(Coil_Cooling_WaterFields::CondensateCollectionWaterStorageTankName)); EXPECT_TRUE(idfCoil.isEmpty(Coil_Cooling_WaterFields::DesignWaterTemperatureDifference)); + + // Check Controller:WaterCoil created by coil.addToNode + EXPECT_EQ(1, w.getObjectsByType(IddObjectType::Controller_WaterCoil).size()); } } diff --git a/src/energyplus/Test/CoilSystemCoolingWater_GTest.cpp b/src/energyplus/Test/CoilSystemCoolingWater_GTest.cpp index cddf73b1b46..c480036bc5d 100644 --- a/src/energyplus/Test/CoilSystemCoolingWater_GTest.cpp +++ b/src/energyplus/Test/CoilSystemCoolingWater_GTest.cpp @@ -18,6 +18,13 @@ #include "../../model/AirLoopHVAC.hpp" #include "../../model/AirLoopHVACUnitarySystem.hpp" #include "../../model/Node.hpp" +#include "../../model/Node_Impl.hpp" +#include "../../model/AirLoopHVACOutdoorAirSystem.hpp" +#include "../../model/AirLoopHVACOutdoorAirSystem_Impl.hpp" +#include "../../model/ControllerOutdoorAir.hpp" +#include "../../model/ControllerOutdoorAir_Impl.hpp" +#include "../../model/PipeAdiabatic.hpp" +#include "../../model/PipeAdiabatic_Impl.hpp" #include "../../utilities/idf/Workspace.hpp" #include "../../utilities/idf/IdfObject.hpp" @@ -35,6 +42,7 @@ #include #include #include +#include using namespace openstudio::energyplus; using namespace openstudio::model; @@ -60,9 +68,9 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWater_Unitary) { CoilCoolingWater companionCoilUsedForHeatRecovery(m); EXPECT_TRUE(coilSystemCoolingWater.setCompanionCoilUsedForHeatRecovery(companionCoilUsedForHeatRecovery)); - // put it inside a Unitary, and put Unitary on an AirLoopHVAC so it gets translated + // put it inside a Unitary, and put Unitary on an AirLoopHVAC AirLoopHVACUnitarySystem unitary(m); - unitary.setCoolingCoil(coilSystemCoolingWater); + EXPECT_FALSE(unitary.setCoolingCoil(coilSystemCoolingWater)); AirLoopHVAC airLoop(m); Node supplyOutletNode = airLoop.supplyOutletNode(); unitary.addToNode(supplyOutletNode); @@ -82,55 +90,7 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWater_Unitary) { const auto& idfUnitary = idfUnitarys.front(); const auto idfCoilSystems = w.getObjectsByType(IddObjectType::CoilSystem_Cooling_Water); - ASSERT_EQ(1u, idfCoilSystems.size()); // FIXME: should unitary here be allowed? if so, we need to update those FT files? - const auto& idfCoilSystem = idfCoilSystems.front(); - - WorkspaceObjectVector idfCoils(w.getObjectsByType(IddObjectType::Coil_Cooling_Water)); - ASSERT_EQ(1u, idfCoils.size()); - WorkspaceObject idfCoil(idfCoils[0]); - - // Check that the Unitary ends up with the CoilSystemCoolingWater - EXPECT_EQ("CoilSystem:Cooling:Water", idfUnitary.getString(AirLoopHVAC_UnitarySystemFields::CoolingCoilObjectType).get()); - EXPECT_EQ(idfCoilSystem.nameString(), idfUnitary.getString(AirLoopHVAC_UnitarySystemFields::CoolingCoilName).get()); - - EXPECT_EQ(coilSystemCoolingWater.inletModelObject().get().nameString(), - idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::AirInletNodeName).get()); - EXPECT_EQ(coilSystemCoolingWater.outletModelObject().get().nameString(), - idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::AirOutletNodeName).get()); - EXPECT_EQ(availabilitySchedule.nameString(), idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::AvailabilityScheduleName).get()); - EXPECT_EQ("Coil:Cooling:Water", idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::CoolingCoilObjectType).get()); - EXPECT_EQ(coilSystemCoolingWater.coolingCoil().nameString(), idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::CoolingCoilName).get()); - EXPECT_EQ("CoolReheat", idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::DehumidificationControlType).get()); - EXPECT_EQ("No", idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::RunonSensibleLoad).get()); - EXPECT_EQ("Yes", idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::RunonLatentLoad).get()); - EXPECT_EQ(1.0, idfCoilSystem.getDouble(CoilSystem_Cooling_WaterFields::MinimumAirToWaterTemperatureOffset).get()); - EXPECT_EQ("No", idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::EconomizerLockout).get()); - EXPECT_EQ(1.2, idfCoilSystem.getDouble(CoilSystem_Cooling_WaterFields::MinimumWaterLoopTemperatureForHeatRecovery).get()); - EXPECT_EQ(companionCoilUsedForHeatRecovery.nameString(), - idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::CompanionCoilUsedForHeatRecovery).get()); - - EXPECT_EQ(0, w.getObjectsByType(IddObjectType::Controller_WaterCoil).size()); - - EXPECT_EQ(coilSystemCoolingWater.coolingCoil().nameString(), idfCoil.getString(Coil_Cooling_WaterFields::Name).get()); - EXPECT_EQ("Always On Discrete", idfCoil.getString(Coil_Cooling_WaterFields::AvailabilityScheduleName).get()); - EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignWaterFlowRate).get()); - EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignAirFlowRate).get()); - EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignInletWaterTemperature).get()); - EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignInletAirTemperature).get()); - EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignInletAirHumidityRatio).get()); - EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignOutletAirHumidityRatio).get()); - EXPECT_EQ(coilSystemCoolingWater.coolingCoil().waterInletModelObject().get().nameString(), - idfCoil.getString(Coil_Cooling_WaterFields::WaterInletNodeName).get()); - EXPECT_EQ(coilSystemCoolingWater.coolingCoil().waterOutletModelObject().get().nameString(), - idfCoil.getString(Coil_Cooling_WaterFields::WaterOutletNodeName).get()); - EXPECT_EQ(idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::AirInletNodeName).get(), - idfCoil.getString(Coil_Cooling_WaterFields::AirInletNodeName).get()); - EXPECT_EQ(idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::AirOutletNodeName).get(), - idfCoil.getString(Coil_Cooling_WaterFields::AirOutletNodeName).get()); - EXPECT_EQ("SimpleAnalysis", idfCoil.getString(Coil_Cooling_WaterFields::TypeofAnalysis).get()); - EXPECT_EQ("CrossFlow", idfCoil.getString(Coil_Cooling_WaterFields::HeatExchangerConfiguration).get()); - EXPECT_TRUE(idfCoil.isEmpty(Coil_Cooling_WaterFields::CondensateCollectionWaterStorageTankName)); - EXPECT_TRUE(idfCoil.isEmpty(Coil_Cooling_WaterFields::DesignWaterTemperatureDifference)); + ASSERT_EQ(0u, idfCoilSystems.size()); } TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWater_AirLoopHVAC) { @@ -206,9 +166,6 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWater_AirLoopHVAC) EXPECT_EQ(1.2, idfCoilSystem.getDouble(CoilSystem_Cooling_WaterFields::MinimumWaterLoopTemperatureForHeatRecovery).get()); EXPECT_TRUE(idfCoilSystem.isEmpty(CoilSystem_Cooling_WaterFields::CompanionCoilUsedForHeatRecovery)); - EXPECT_EQ(0, w.getObjectsByType(IddObjectType::Controller_WaterCoil) - .size()); // FIXME: what's creating this if i have it commented out in the addToNode method? - EXPECT_EQ(coilSystemCoolingWater.coolingCoil().nameString(), idfCoil.getString(Coil_Cooling_WaterFields::Name).get()); EXPECT_EQ("Always On Discrete", idfCoil.getString(Coil_Cooling_WaterFields::AvailabilityScheduleName).get()); EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignWaterFlowRate).get()); @@ -229,6 +186,9 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWater_AirLoopHVAC) EXPECT_EQ("CrossFlow", idfCoil.getString(Coil_Cooling_WaterFields::HeatExchangerConfiguration).get()); EXPECT_TRUE(idfCoil.isEmpty(Coil_Cooling_WaterFields::CondensateCollectionWaterStorageTankName)); EXPECT_TRUE(idfCoil.isEmpty(Coil_Cooling_WaterFields::DesignWaterTemperatureDifference)); + + // FIXME: what's creating this if i have it commented out in the addToNode method? + EXPECT_EQ(0, w.getObjectsByType(IddObjectType::Controller_WaterCoil).size()); } // with companion @@ -254,11 +214,22 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWater_AirLoopHVAC) // put it inside a Unitary, and put Unitary on an AirLoopHVAC so it gets translated AirLoopHVAC airLoop(m); Node supplyOutletNode = airLoop.supplyOutletNode(); - EXPECT_TRUE(coilSystemCoolingWater.addToNode(supplyOutletNode)); + ControllerOutdoorAir controller1(m); + AirLoopHVACOutdoorAirSystem oaSystem(m, controller1); + EXPECT_TRUE(oaSystem.addToNode(supplyOutletNode)); + Node oaNode = oaSystem.outboardOANode().get(); + EXPECT_TRUE(coilSystemCoolingWater.addToNode(oaNode)); + Node reliefNode = oaSystem.reliefAirModelObject()->cast(); + EXPECT_TRUE(companionCoilUsedForHeatRecovery.addToNode(reliefNode)); // They must be connected to a PlantLoop too PlantLoop chw_p(m); chw_p.addDemandBranchForComponent(coilSystemCoolingWater.coolingCoil()); + PipeAdiabatic pipe(m); + Node coolingOutlet = coilSystemCoolingWater.coolingCoil().waterOutletModelObject()->cast(); + EXPECT_TRUE(pipe.addToNode(coolingOutlet)); + Node pipeOutlet = pipe.outletModelObject()->cast(); + EXPECT_TRUE(companionCoilUsedForHeatRecovery.addToNode(pipeOutlet)); const Workspace w = ft.translateModel(m); @@ -268,7 +239,10 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWater_AirLoopHVAC) WorkspaceObjectVector idfCoils(w.getObjectsByType(IddObjectType::Coil_Cooling_Water)); ASSERT_EQ(2u, idfCoils.size()); - WorkspaceObject idfCoil(idfCoils[0]); // FIXME: get these some other way + + WorkspaceObjectVector idfControllers(w.getObjectsByType(IddObjectType::Controller_OutdoorAir)); + ASSERT_EQ(1u, idfControllers.size()); + const auto& idfController = idfControllers.front(); // Go from AirLoopHVAC to BranchList to Branch WorkspaceObjectVector idf_airloops = w.getObjectsByType(IddObjectType::AirLoopHVAC); @@ -286,9 +260,9 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWater_AirLoopHVAC) ASSERT_EQ(1u, idf_branch.extensibleGroups().size()); auto w_eg2 = idf_branch.extensibleGroups()[0].cast(); - EXPECT_EQ(w_eg2.getString(BranchExtensibleFields::ComponentInletNodeName).get(), coilSystemCoolingWater.inletModelObject().get().nameString()); - EXPECT_EQ(w_eg2.getString(BranchExtensibleFields::ComponentOutletNodeName).get(), coilSystemCoolingWater.outletModelObject().get().nameString()); - EXPECT_EQ("CoilSystem:Cooling:Water", w_eg2.getString(BranchExtensibleFields::ComponentObjectType).get()); + /* EXPECT_EQ(w_eg2.getString(BranchExtensibleFields::ComponentInletNodeName).get(), coilSystemCoolingWater.inletModelObject().get().nameString()); + EXPECT_EQ(w_eg2.getString(BranchExtensibleFields::ComponentOutletNodeName).get(), coilSystemCoolingWater.outletModelObject().get().nameString()); */ + EXPECT_EQ("AirLoopHVAC:OutdoorAirSystem", w_eg2.getString(BranchExtensibleFields::ComponentObjectType).get()); EXPECT_EQ(coilSystemCoolingWater.inletModelObject().get().nameString(), idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::AirInletNodeName).get()); @@ -306,28 +280,52 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWater_AirLoopHVAC) EXPECT_EQ(companionCoilUsedForHeatRecovery.nameString(), idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::CompanionCoilUsedForHeatRecovery).get()); - EXPECT_EQ(0, w.getObjectsByType(IddObjectType::Controller_WaterCoil) - .size()); // FIXME: what's creating this if i have it commented out in the addToNode method? - - EXPECT_EQ(coilSystemCoolingWater.coolingCoil().nameString(), idfCoil.getString(Coil_Cooling_WaterFields::Name).get()); - EXPECT_EQ("Always On Discrete", idfCoil.getString(Coil_Cooling_WaterFields::AvailabilityScheduleName).get()); - EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignWaterFlowRate).get()); - EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignAirFlowRate).get()); - EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignInletWaterTemperature).get()); - EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignInletAirTemperature).get()); - EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignInletAirHumidityRatio).get()); - EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignOutletAirHumidityRatio).get()); + WorkspaceObject idf_coolingCoil = idfCoilSystem.getTarget(CoilSystem_Cooling_WaterFields::CoolingCoilName).get(); + WorkspaceObject idf_companionCoil = idfCoilSystem.getTarget(CoilSystem_Cooling_WaterFields::CompanionCoilUsedForHeatRecovery).get(); + + EXPECT_EQ(coilSystemCoolingWater.coolingCoil().nameString(), idf_coolingCoil.getString(Coil_Cooling_WaterFields::Name).get()); + EXPECT_EQ("Always On Discrete", idf_coolingCoil.getString(Coil_Cooling_WaterFields::AvailabilityScheduleName).get()); + EXPECT_EQ("Autosize", idf_coolingCoil.getString(Coil_Cooling_WaterFields::DesignWaterFlowRate).get()); + EXPECT_EQ("Autosize", idf_coolingCoil.getString(Coil_Cooling_WaterFields::DesignAirFlowRate).get()); + EXPECT_EQ("Autosize", idf_coolingCoil.getString(Coil_Cooling_WaterFields::DesignInletWaterTemperature).get()); + EXPECT_EQ("Autosize", idf_coolingCoil.getString(Coil_Cooling_WaterFields::DesignInletAirTemperature).get()); + EXPECT_EQ("Autosize", idf_coolingCoil.getString(Coil_Cooling_WaterFields::DesignInletAirHumidityRatio).get()); + EXPECT_EQ("Autosize", idf_coolingCoil.getString(Coil_Cooling_WaterFields::DesignOutletAirHumidityRatio).get()); EXPECT_EQ(coilSystemCoolingWater.coolingCoil().waterInletModelObject().get().nameString(), - idfCoil.getString(Coil_Cooling_WaterFields::WaterInletNodeName).get()); + idf_coolingCoil.getString(Coil_Cooling_WaterFields::WaterInletNodeName).get()); EXPECT_EQ(coilSystemCoolingWater.coolingCoil().waterOutletModelObject().get().nameString(), - idfCoil.getString(Coil_Cooling_WaterFields::WaterOutletNodeName).get()); + idf_coolingCoil.getString(Coil_Cooling_WaterFields::WaterOutletNodeName).get()); EXPECT_EQ(idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::AirInletNodeName).get(), - idfCoil.getString(Coil_Cooling_WaterFields::AirInletNodeName).get()); + idf_coolingCoil.getString(Coil_Cooling_WaterFields::AirInletNodeName).get()); EXPECT_EQ(idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::AirOutletNodeName).get(), - idfCoil.getString(Coil_Cooling_WaterFields::AirOutletNodeName).get()); - EXPECT_EQ("SimpleAnalysis", idfCoil.getString(Coil_Cooling_WaterFields::TypeofAnalysis).get()); - EXPECT_EQ("CrossFlow", idfCoil.getString(Coil_Cooling_WaterFields::HeatExchangerConfiguration).get()); - EXPECT_TRUE(idfCoil.isEmpty(Coil_Cooling_WaterFields::CondensateCollectionWaterStorageTankName)); - EXPECT_TRUE(idfCoil.isEmpty(Coil_Cooling_WaterFields::DesignWaterTemperatureDifference)); + idf_coolingCoil.getString(Coil_Cooling_WaterFields::AirOutletNodeName).get()); + EXPECT_EQ("SimpleAnalysis", idf_coolingCoil.getString(Coil_Cooling_WaterFields::TypeofAnalysis).get()); + EXPECT_EQ("CrossFlow", idf_coolingCoil.getString(Coil_Cooling_WaterFields::HeatExchangerConfiguration).get()); + EXPECT_TRUE(idf_coolingCoil.isEmpty(Coil_Cooling_WaterFields::CondensateCollectionWaterStorageTankName)); + EXPECT_TRUE(idf_coolingCoil.isEmpty(Coil_Cooling_WaterFields::DesignWaterTemperatureDifference)); + + EXPECT_EQ(coilSystemCoolingWater.companionCoilUsedForHeatRecovery().get().nameString(), + idf_companionCoil.getString(Coil_Cooling_WaterFields::Name).get()); + EXPECT_EQ("Always On Discrete", idf_companionCoil.getString(Coil_Cooling_WaterFields::AvailabilityScheduleName).get()); + EXPECT_EQ("Autosize", idf_companionCoil.getString(Coil_Cooling_WaterFields::DesignWaterFlowRate).get()); + EXPECT_EQ("Autosize", idf_companionCoil.getString(Coil_Cooling_WaterFields::DesignAirFlowRate).get()); + EXPECT_EQ("Autosize", idf_companionCoil.getString(Coil_Cooling_WaterFields::DesignInletWaterTemperature).get()); + EXPECT_EQ("Autosize", idf_companionCoil.getString(Coil_Cooling_WaterFields::DesignInletAirTemperature).get()); + EXPECT_EQ("Autosize", idf_companionCoil.getString(Coil_Cooling_WaterFields::DesignInletAirHumidityRatio).get()); + EXPECT_EQ("Autosize", idf_companionCoil.getString(Coil_Cooling_WaterFields::DesignOutletAirHumidityRatio).get()); + EXPECT_EQ(coilSystemCoolingWater.companionCoilUsedForHeatRecovery().get().waterInletModelObject().get().nameString(), + idf_companionCoil.getString(Coil_Cooling_WaterFields::WaterInletNodeName).get()); + EXPECT_EQ(coilSystemCoolingWater.companionCoilUsedForHeatRecovery().get().waterOutletModelObject().get().nameString(), + idf_companionCoil.getString(Coil_Cooling_WaterFields::WaterOutletNodeName).get()); + EXPECT_EQ(idfController.getString(Controller_OutdoorAirFields::ReliefAirOutletNodeName).get(), + idf_companionCoil.getString(Coil_Cooling_WaterFields::AirInletNodeName).get()); + EXPECT_EQ("", idf_companionCoil.getString(Coil_Cooling_WaterFields::AirOutletNodeName).get()); // FIXME + EXPECT_EQ("SimpleAnalysis", idf_companionCoil.getString(Coil_Cooling_WaterFields::TypeofAnalysis).get()); + EXPECT_EQ("CrossFlow", idf_companionCoil.getString(Coil_Cooling_WaterFields::HeatExchangerConfiguration).get()); + EXPECT_TRUE(idf_companionCoil.isEmpty(Coil_Cooling_WaterFields::CondensateCollectionWaterStorageTankName)); + EXPECT_TRUE(idf_companionCoil.isEmpty(Coil_Cooling_WaterFields::DesignWaterTemperatureDifference)); + + // FIXME: what's creating this if i have it commented out in the addToNode method? + EXPECT_EQ(0, w.getObjectsByType(IddObjectType::Controller_WaterCoil).size()); } } diff --git a/src/model/CoilCoolingWater.cpp b/src/model/CoilCoolingWater.cpp index 23dfb8e47d9..14ca07d6095 100644 --- a/src/model/CoilCoolingWater.cpp +++ b/src/model/CoilCoolingWater.cpp @@ -286,6 +286,12 @@ namespace model { LOG(Warn, this->briefDescription() << " cannot be connected directly to an AirLoopHVAC when it's part of a parent CoilSystemCoolingWaterHeatExchangerAssisted. " "Please call CoilSystemCoolingWaterHeatExchangerAssisted::addToNode instead"); + + /* } else if (t_airLoop && t_containingHVACComponent && t_containingHVACComponent->optionalCast()) { + LOG(Warn, this->briefDescription() + << " cannot be connected directly to an AirLoopHVAC when it's part of a parent CoilSystemCoolingWater. " + "Please call CoilSystemCoolingWater::addToNode instead"); */ + } else { success = WaterToAirComponent_Impl::addToNode(node); @@ -300,10 +306,14 @@ namespace model { << " has an existing ControllerWaterCoil with action set to something else than 'Reverse'. Make sure this is what you want"); } } else { - Model t_model = model(); - ControllerWaterCoil controller(t_model); - controller.getImpl()->setWaterCoil(getObject()); - controller.setAction("Reverse"); + if (t_containingHVACComponent && t_containingHVACComponent->optionalCast()) { + // no-op + } else { + Model t_model = model(); + ControllerWaterCoil controller(t_model); + controller.getImpl()->setWaterCoil(getObject()); + controller.setAction("Reverse"); + } } } } @@ -383,6 +393,11 @@ namespace model { if (coilSystem.coolingCoil().handle() == handle()) { return coilSystem; } + if (boost::optional companionCoilUsedForHeatRecovery = coilSystem.companionCoilUsedForHeatRecovery()) { + if (companionCoilUsedForHeatRecovery->handle() == this->handle()) { + return coilSystem; + } + } } } diff --git a/src/model/CoilSystemCoolingWater.cpp b/src/model/CoilSystemCoolingWater.cpp index 4b565cf881e..f96f622abe2 100644 --- a/src/model/CoilSystemCoolingWater.cpp +++ b/src/model/CoilSystemCoolingWater.cpp @@ -117,29 +117,7 @@ namespace model { if (boost::optional airLoop = node.airLoopHVAC()) { if (!airLoop->demandComponent(node.handle())) { - result = StraightComponent_Impl::addToNode(node); - if (result) { - auto t_coolingCoil = coolingCoil(); - if (auto waterInletModelObject = t_coolingCoil.waterInletModelObject()) { - - // TODO: why aren't we setting the water coil in this case? @kbenne thoughts please - if (auto coilCoolingWater = t_coolingCoil.optionalCast()) { - if (auto oldController = coilCoolingWater->controllerWaterCoil()) { - oldController->remove(); - } - } - - /* auto t_model = model(); - ControllerWaterCoil controller(t_model); - - auto coilWaterInletNode = waterInletModelObject->optionalCast(); - OS_ASSERT(coilWaterInletNode); - controller.setActuatorNode(coilWaterInletNode.get()); - // sensor node will be established in translator since that node does not yet exist - - controller.setAction("Reverse"); */ - } - } + return StraightComponent_Impl::addToNode(node); } } else if (boost::optional oas = node.airLoopHVACOutdoorAirSystem()) { if (oas->airLoopHVACDedicatedOutdoorAirSystem()) { diff --git a/src/model/CoilSystemCoolingWaterHeatExchangerAssisted.cpp b/src/model/CoilSystemCoolingWaterHeatExchangerAssisted.cpp index 9b634fce884..fae50a76358 100644 --- a/src/model/CoilSystemCoolingWaterHeatExchangerAssisted.cpp +++ b/src/model/CoilSystemCoolingWaterHeatExchangerAssisted.cpp @@ -190,29 +190,7 @@ namespace model { if (boost::optional airLoop = node.airLoopHVAC()) { if (!airLoop->demandComponent(node.handle())) { - result = StraightComponent_Impl::addToNode(node); - if (result) { - auto t_coolingCoil = coolingCoil(); - if (auto waterInletModelObject = t_coolingCoil.waterInletModelObject()) { - - // TODO: why aren't we setting the water coil in this case? @kbenne thoughts please - if (auto coilCoolingWater = t_coolingCoil.optionalCast()) { - if (auto oldController = coilCoolingWater->controllerWaterCoil()) { - oldController->remove(); - } - } - - auto t_model = model(); - ControllerWaterCoil controller(t_model); - - auto coilWaterInletNode = waterInletModelObject->optionalCast(); - OS_ASSERT(coilWaterInletNode); - controller.setActuatorNode(coilWaterInletNode.get()); - // sensor node will be established in translator since that node does not yet exist - - controller.setAction("Reverse"); - } - } + return StraightComponent_Impl::addToNode(node); } } else if (boost::optional oas = node.airLoopHVACOutdoorAirSystem()) { if (oas->airLoopHVACDedicatedOutdoorAirSystem()) { diff --git a/src/model/test/CoilSystemCoolingWater_GTest.cpp b/src/model/test/CoilSystemCoolingWater_GTest.cpp index 554b06722a3..7c1aa4b661a 100644 --- a/src/model/test/CoilSystemCoolingWater_GTest.cpp +++ b/src/model/test/CoilSystemCoolingWater_GTest.cpp @@ -11,6 +11,9 @@ #include "../Schedule_Impl.hpp" #include "../CoilCoolingWater.hpp" #include "../CoilCoolingWater_Impl.hpp" +#include "../AirLoopHVAC.hpp" +#include "../PlantLoop.hpp" +#include "../Node.hpp" using namespace openstudio; using namespace openstudio::model; @@ -90,4 +93,74 @@ TEST_F(ModelFixture, CoilSystemCoolingWater_clone) {} TEST_F(ModelFixture, CoilSystemCoolingWater_remove) {} -TEST_F(ModelFixture, CoilSystemCoolingWater_addToNode) {} +TEST_F(ModelFixture, CoilSystemCoolingWater_addToNode) { + // Water Size Economizer Model + { + Model m; + CoilSystemCoolingWater coilSystem(m); + + AirLoopHVAC a(m); + Node n = a.supplyOutletNode(); + + auto cc = coilSystem.coolingCoil().cast(); + + EXPECT_EQ(2u, a.supplyComponents().size()); + + EXPECT_TRUE(cc.addToNode(n)); + EXPECT_EQ(3u, a.supplyComponents().size()); + + EXPECT_TRUE(coilSystem.addToNode(n)); + EXPECT_EQ(5u, a.supplyComponents().size()); + + { + auto containingHVACComponent = cc.containingHVACComponent(); + ASSERT_TRUE(containingHVACComponent); + EXPECT_EQ(containingHVACComponent->handle(), coilSystem.handle()); + } + + // BUT, we need to be able to connect the water side of the Coil... + PlantLoop p(m); + EXPECT_TRUE(p.addDemandBranchForComponent(cc)); + } + + // Wrap Around Water Coil Heat Recovery Mode + { + Model m; + CoilSystemCoolingWater coilSystem(m); + CoilCoolingWater companionCoil(m); + coilSystem.setCompanionCoilUsedForHeatRecovery(companionCoil); + + AirLoopHVAC a(m); + Node n = a.supplyOutletNode(); + + auto cc = coilSystem.coolingCoil().cast(); + auto hr = coilSystem.companionCoilUsedForHeatRecovery().get().cast(); + + EXPECT_EQ(2u, a.supplyComponents().size()); + + EXPECT_TRUE(cc.addToNode(n)); + EXPECT_EQ(3u, a.supplyComponents().size()); + + EXPECT_TRUE(hr.addToNode(n)); + EXPECT_EQ(5u, a.supplyComponents().size()); + + EXPECT_TRUE(coilSystem.addToNode(n)); + EXPECT_EQ(7u, a.supplyComponents().size()); + + { + auto containingHVACComponent = cc.containingHVACComponent(); + ASSERT_TRUE(containingHVACComponent); + EXPECT_EQ(containingHVACComponent->handle(), coilSystem.handle()); + } + + { + auto containingHVACComponent = hr.containingHVACComponent(); + ASSERT_TRUE(containingHVACComponent); + EXPECT_EQ(containingHVACComponent->handle(), coilSystem.handle()); + } + + // BUT, we need to be able to connect the water side of the Coil... + PlantLoop p(m); + EXPECT_TRUE(p.addDemandBranchForComponent(cc)); + } +} From 0b4d0f1eb8c7b6d5e547cc99018ce2083b01bae1 Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Fri, 21 Mar 2025 16:56:36 -0700 Subject: [PATCH 38/58] Cleanup. --- src/energyplus/Test/CoilSystemCoolingWater_GTest.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/energyplus/Test/CoilSystemCoolingWater_GTest.cpp b/src/energyplus/Test/CoilSystemCoolingWater_GTest.cpp index c480036bc5d..fc9d4103bc2 100644 --- a/src/energyplus/Test/CoilSystemCoolingWater_GTest.cpp +++ b/src/energyplus/Test/CoilSystemCoolingWater_GTest.cpp @@ -87,7 +87,6 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWater_Unitary) { const auto idfUnitarys = w.getObjectsByType(IddObjectType::AirLoopHVAC_UnitarySystem); ASSERT_EQ(1u, idfUnitarys.size()); - const auto& idfUnitary = idfUnitarys.front(); const auto idfCoilSystems = w.getObjectsByType(IddObjectType::CoilSystem_Cooling_Water); ASSERT_EQ(0u, idfCoilSystems.size()); From c5e4d4f652bdd1765ee1f06bfa1261277a964c28 Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Thu, 27 Mar 2025 16:05:57 -0700 Subject: [PATCH 39/58] Update plant eq op schemes ft for special case of coilsystemcoolingwater demand component. --- ...ranslatePlantEquipmentOperationSchemes.cpp | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/energyplus/ForwardTranslator/ForwardTranslatePlantEquipmentOperationSchemes.cpp b/src/energyplus/ForwardTranslator/ForwardTranslatePlantEquipmentOperationSchemes.cpp index 2ae937c92c1..64e7c034962 100644 --- a/src/energyplus/ForwardTranslator/ForwardTranslatePlantEquipmentOperationSchemes.cpp +++ b/src/energyplus/ForwardTranslator/ForwardTranslatePlantEquipmentOperationSchemes.cpp @@ -91,6 +91,10 @@ #include "../../model/HeatPumpPlantLoopEIRHeating_Impl.hpp" #include "../../model/HeatPumpPlantLoopEIRCooling.hpp" #include "../../model/HeatPumpPlantLoopEIRCooling_Impl.hpp" +#include "../../model/CoilCoolingWater.hpp" +#include "../../model/CoilCoolingWater_Impl.hpp" +#include "../../model/CoilSystemCoolingWater.hpp" +#include "../../model/CoilSystemCoolingWater_Impl.hpp" #include "../../utilities/idf/IdfExtensibleGroup.hpp" #include "../../utilities/idf/Workspace.hpp" #include "../../utilities/idf/WorkspaceObjectOrder.hpp" @@ -470,6 +474,18 @@ namespace energyplus { } } + // Special case for CoilSystemCoolingWater (Wrap Around Water Coil Heat Recovery Mode) + for (const auto& comp : subsetCastVector(plantLoop.demandComponents())) { + if (comp.iddObject().type().value() == openstudio::IddObjectType::OS_Coil_Cooling_Water) { + auto coil = comp.cast(); + if (auto containingHVACComponent = coil.containingHVACComponent()) { + if (auto coilSystemCoolingWater = containingHVACComponent->optionalCast()) { + result.push_back(operationSchemeComponent(*coilSystemCoolingWater)); + } + } + } + } + return result; } @@ -679,7 +695,9 @@ namespace energyplus { eg.setString(PlantEquipmentOperationSchemesExtensibleFields::ControlSchemeScheduleName, _alwaysOn->nameString()); for (auto& uncontrolledComponent : t_uncontrolledComponents) { - if (auto idfObject_ = translateAndMapModelObject(uncontrolledComponent)) { + if (uncontrolledComponent.optionalCast()) { + // no-op + } else if (auto idfObject_ = translateAndMapModelObject(uncontrolledComponent)) { IdfExtensibleGroup eg = plantEquipmentList.pushExtensibleGroup(); eg.setString(PlantEquipmentListExtensibleFields::EquipmentObjectType, idfObject_->iddObject().name()); eg.setString(PlantEquipmentListExtensibleFields::EquipmentName, idfObject_->nameString()); From 105478e23be62e83a73f7b0e8e4a42de4f7c7fa9 Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Thu, 27 Mar 2025 16:06:17 -0700 Subject: [PATCH 40/58] Update companion coil air outlet node name and test. --- .../ForwardTranslateCoilSystemCoolingWater.cpp | 5 ++--- src/energyplus/Test/CoilSystemCoolingWater_GTest.cpp | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWater.cpp b/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWater.cpp index 9d0f7ec0180..b2ec41fadf8 100644 --- a/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWater.cpp +++ b/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWater.cpp @@ -181,9 +181,8 @@ namespace energyplus { if (boost::optional wo_ = translateAndMapModelObject(companionCoilUsedForHeatRecovery_.get())) { idfObject.setString(CoilSystem_Cooling_WaterFields::CompanionCoilUsedForHeatRecovery, wo_->nameString()); if (wo_->iddObject().type() == IddObjectType::Coil_Cooling_Water) { - wo_->setString(Coil_Cooling_WaterFields::AirInletNodeName, - modelObject.airLoopHVACOutdoorAirSystem()->reliefAirModelObject()->nameString()); // FIXME - wo_->setString(Coil_Cooling_WaterFields::AirOutletNodeName, airOutletNodeName); // FIXME + wo_->setString(Coil_Cooling_WaterFields::AirInletNodeName, modelObject.airLoopHVACOutdoorAirSystem()->reliefAirModelObject()->nameString()); + wo_->setString(Coil_Cooling_WaterFields::AirOutletNodeName, wo_->nameString() + " Exhaust Outlet Node"); // FIXME // Add IddObjectType::Coil_Cooling_Water_DetailedGeometry if implemented } else { // Shouldn't happen, accepts only Coil:Cooling:Water or Coil:Cooling:Water:DetailedGeometry diff --git a/src/energyplus/Test/CoilSystemCoolingWater_GTest.cpp b/src/energyplus/Test/CoilSystemCoolingWater_GTest.cpp index fc9d4103bc2..745e7de391b 100644 --- a/src/energyplus/Test/CoilSystemCoolingWater_GTest.cpp +++ b/src/energyplus/Test/CoilSystemCoolingWater_GTest.cpp @@ -111,7 +111,6 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWater_AirLoopHVAC) EXPECT_TRUE(coilSystemCoolingWater.setEconomizerLockout(false)); // Opposite from IDD default EXPECT_TRUE(coilSystemCoolingWater.setMinimumWaterLoopTemperatureForHeatRecovery(1.2)); - // put it inside a Unitary, and put Unitary on an AirLoopHVAC so it gets translated AirLoopHVAC airLoop(m); Node supplyOutletNode = airLoop.supplyOutletNode(); EXPECT_TRUE(coilSystemCoolingWater.addToNode(supplyOutletNode)); @@ -210,7 +209,6 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWater_AirLoopHVAC) CoilCoolingWater companionCoilUsedForHeatRecovery(m); EXPECT_TRUE(coilSystemCoolingWater.setCompanionCoilUsedForHeatRecovery(companionCoilUsedForHeatRecovery)); - // put it inside a Unitary, and put Unitary on an AirLoopHVAC so it gets translated AirLoopHVAC airLoop(m); Node supplyOutletNode = airLoop.supplyOutletNode(); ControllerOutdoorAir controller1(m); @@ -318,7 +316,8 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWater_AirLoopHVAC) idf_companionCoil.getString(Coil_Cooling_WaterFields::WaterOutletNodeName).get()); EXPECT_EQ(idfController.getString(Controller_OutdoorAirFields::ReliefAirOutletNodeName).get(), idf_companionCoil.getString(Coil_Cooling_WaterFields::AirInletNodeName).get()); - EXPECT_EQ("", idf_companionCoil.getString(Coil_Cooling_WaterFields::AirOutletNodeName).get()); // FIXME + EXPECT_EQ(coilSystemCoolingWater.companionCoilUsedForHeatRecovery().get().nameString() + " Exhaust Outlet Node", + idf_companionCoil.getString(Coil_Cooling_WaterFields::AirOutletNodeName).get()); // FIXME EXPECT_EQ("SimpleAnalysis", idf_companionCoil.getString(Coil_Cooling_WaterFields::TypeofAnalysis).get()); EXPECT_EQ("CrossFlow", idf_companionCoil.getString(Coil_Cooling_WaterFields::HeatExchangerConfiguration).get()); EXPECT_TRUE(idf_companionCoil.isEmpty(Coil_Cooling_WaterFields::CondensateCollectionWaterStorageTankName)); From 39d8693494ea4a397c8ad4cedb413c78d4a375e2 Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Tue, 1 Apr 2025 15:34:06 -0700 Subject: [PATCH 41/58] Some cleanup. --- ...CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp | 9 +++------ src/energyplus/Test/CoilSystemCoolingWater_GTest.cpp | 2 -- src/model/CoilSystemCoolingWater.cpp | 2 -- .../CoilSystemCoolingWaterHeatExchangerAssisted.cpp | 2 -- 4 files changed, 3 insertions(+), 12 deletions(-) diff --git a/src/energyplus/Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp b/src/energyplus/Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp index e51ee3dd306..99c93a0d770 100644 --- a/src/energyplus/Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp +++ b/src/energyplus/Test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp @@ -80,9 +80,6 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWaterHeatExchangerA ASSERT_EQ(1u, idfCoils.size()); WorkspaceObject idfCoil(idfCoils[0]); - // No CoilSystem:Cooling:Water wrapper needed, it's inside a unitary - EXPECT_EQ(0, w.getObjectsByType(IddObjectType::CoilSystem_Cooling_Water).size()); - // Check that the Unitary ends up with the CoilSystemCoolingWaterHeatExchangerAssisted EXPECT_EQ("CoilSystem:Cooling:Water:HeatExchangerAssisted", idfUnitary.getString(AirLoopHVAC_UnitarySystemFields::CoolingCoilObjectType).get()); EXPECT_EQ(idfCoilSystem.nameString(), idfUnitary.getString(AirLoopHVAC_UnitarySystemFields::CoolingCoilName).get()); @@ -103,9 +100,6 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWaterHeatExchangerA EXPECT_EQ("Coil:Cooling:Water", idfCoilSystem.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::CoolingCoilObjectType).get()); EXPECT_EQ(coil.coolingCoil().nameString(), idfCoilSystem.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::CoolingCoilName).get()); - // Check Controller:WaterCoil created by coil.addToNode - EXPECT_EQ(1, w.getObjectsByType(IddObjectType::Controller_WaterCoil).size()); - EXPECT_EQ(coil.coolingCoil().nameString(), idfCoil.getString(Coil_Cooling_WaterFields::Name).get()); EXPECT_EQ("Always On Discrete", idfCoil.getString(Coil_Cooling_WaterFields::AvailabilityScheduleName).get()); EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignWaterFlowRate).get()); @@ -124,6 +118,9 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWaterHeatExchangerA EXPECT_EQ("CrossFlow", idfCoil.getString(Coil_Cooling_WaterFields::HeatExchangerConfiguration).get()); EXPECT_TRUE(idfCoil.isEmpty(Coil_Cooling_WaterFields::CondensateCollectionWaterStorageTankName)); EXPECT_TRUE(idfCoil.isEmpty(Coil_Cooling_WaterFields::DesignWaterTemperatureDifference)); + + // Check Controller:WaterCoil created by coil.addToNode + EXPECT_EQ(1, w.getObjectsByType(IddObjectType::Controller_WaterCoil).size()); } TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWaterHeatExchangerAssisted_AirLoopHVAC) { diff --git a/src/energyplus/Test/CoilSystemCoolingWater_GTest.cpp b/src/energyplus/Test/CoilSystemCoolingWater_GTest.cpp index 745e7de391b..85b1838cb40 100644 --- a/src/energyplus/Test/CoilSystemCoolingWater_GTest.cpp +++ b/src/energyplus/Test/CoilSystemCoolingWater_GTest.cpp @@ -185,7 +185,6 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWater_AirLoopHVAC) EXPECT_TRUE(idfCoil.isEmpty(Coil_Cooling_WaterFields::CondensateCollectionWaterStorageTankName)); EXPECT_TRUE(idfCoil.isEmpty(Coil_Cooling_WaterFields::DesignWaterTemperatureDifference)); - // FIXME: what's creating this if i have it commented out in the addToNode method? EXPECT_EQ(0, w.getObjectsByType(IddObjectType::Controller_WaterCoil).size()); } @@ -323,7 +322,6 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWater_AirLoopHVAC) EXPECT_TRUE(idf_companionCoil.isEmpty(Coil_Cooling_WaterFields::CondensateCollectionWaterStorageTankName)); EXPECT_TRUE(idf_companionCoil.isEmpty(Coil_Cooling_WaterFields::DesignWaterTemperatureDifference)); - // FIXME: what's creating this if i have it commented out in the addToNode method? EXPECT_EQ(0, w.getObjectsByType(IddObjectType::Controller_WaterCoil).size()); } } diff --git a/src/model/CoilSystemCoolingWater.cpp b/src/model/CoilSystemCoolingWater.cpp index f96f622abe2..2b200413ff2 100644 --- a/src/model/CoilSystemCoolingWater.cpp +++ b/src/model/CoilSystemCoolingWater.cpp @@ -18,8 +18,6 @@ #include "Node_Impl.hpp" #include "AirLoopHVAC.hpp" #include "AirLoopHVAC_Impl.hpp" -#include "ControllerWaterCoil.hpp" -#include "ControllerWaterCoil_Impl.hpp" #include "AirLoopHVACUnitarySystem.hpp" #include "AirLoopHVACUnitarySystem_Impl.hpp" diff --git a/src/model/CoilSystemCoolingWaterHeatExchangerAssisted.cpp b/src/model/CoilSystemCoolingWaterHeatExchangerAssisted.cpp index fae50a76358..ddfcb530900 100644 --- a/src/model/CoilSystemCoolingWaterHeatExchangerAssisted.cpp +++ b/src/model/CoilSystemCoolingWaterHeatExchangerAssisted.cpp @@ -7,8 +7,6 @@ #include "CoilSystemCoolingWaterHeatExchangerAssisted_Impl.hpp" #include "AirToAirComponent.hpp" #include "AirToAirComponent_Impl.hpp" -#include "ControllerWaterCoil.hpp" -#include "ControllerWaterCoil_Impl.hpp" #include "WaterToAirComponent.hpp" #include "WaterToAirComponent_Impl.hpp" #include "CoilCoolingWater.hpp" From 041adbd8ea0e52c83e21a9136d50c4b9be86b62d Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Mon, 5 May 2025 11:44:15 +0200 Subject: [PATCH 42/58] Make the coolingCoil/companion return a HVACComponent + restrict the companion to CoilCoolingWater per IDD/IO ref CoilSystem:Cooling:Water:HeatExchangerAssisted isn't WaterToAirComponent --- ...ForwardTranslateCoilSystemCoolingWater.cpp | 2 +- src/model/CoilCoolingWater.cpp | 2 +- src/model/CoilSystemCoolingWater.cpp | 55 +++++++++++-------- src/model/CoilSystemCoolingWater.hpp | 14 +++-- src/model/CoilSystemCoolingWater_Impl.hpp | 14 ++--- 5 files changed, 48 insertions(+), 39 deletions(-) diff --git a/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWater.cpp b/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWater.cpp index b2ec41fadf8..84d0ca4dfb1 100644 --- a/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWater.cpp +++ b/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWater.cpp @@ -177,7 +177,7 @@ namespace energyplus { idfObject.setDouble(CoilSystem_Cooling_WaterFields::MinimumWaterLoopTemperatureForHeatRecovery, minimumWaterLoopTemperatureForHeatRecovery); // Companion Coil Used For Heat Recovery: Optional Object - if (boost::optional companionCoilUsedForHeatRecovery_ = modelObject.companionCoilUsedForHeatRecovery()) { + if (boost::optional companionCoilUsedForHeatRecovery_ = modelObject.companionCoilUsedForHeatRecovery()) { if (boost::optional wo_ = translateAndMapModelObject(companionCoilUsedForHeatRecovery_.get())) { idfObject.setString(CoilSystem_Cooling_WaterFields::CompanionCoilUsedForHeatRecovery, wo_->nameString()); if (wo_->iddObject().type() == IddObjectType::Coil_Cooling_Water) { diff --git a/src/model/CoilCoolingWater.cpp b/src/model/CoilCoolingWater.cpp index afe42feb17f..8576570f2f8 100644 --- a/src/model/CoilCoolingWater.cpp +++ b/src/model/CoilCoolingWater.cpp @@ -389,7 +389,7 @@ namespace model { if (coilSystem.coolingCoil().handle() == handle()) { return coilSystem; } - if (boost::optional companionCoilUsedForHeatRecovery = coilSystem.companionCoilUsedForHeatRecovery()) { + if (boost::optional companionCoilUsedForHeatRecovery = coilSystem.companionCoilUsedForHeatRecovery()) { if (companionCoilUsedForHeatRecovery->handle() == this->handle()) { return coilSystem; } diff --git a/src/model/CoilSystemCoolingWater.cpp b/src/model/CoilSystemCoolingWater.cpp index 2b200413ff2..359aef8b051 100644 --- a/src/model/CoilSystemCoolingWater.cpp +++ b/src/model/CoilSystemCoolingWater.cpp @@ -8,8 +8,8 @@ #include "Schedule.hpp" #include "Schedule_Impl.hpp" -#include "WaterToAirComponent.hpp" -#include "WaterToAirComponent_Impl.hpp" +#include "HVACComponent.hpp" +#include "HVACComponent_Impl.hpp" #include "CoilCoolingWater.hpp" #include "CoilCoolingWater_Impl.hpp" #include "Model.hpp" @@ -87,10 +87,10 @@ namespace model { std::vector CoilSystemCoolingWater_Impl::children() const { std::vector result; - if (OptionalWaterToAirComponent intermediate = optionalCoolingCoil()) { + if (OptionalHVACComponent intermediate = optionalCoolingCoil()) { result.push_back(*intermediate); } - if (OptionalWaterToAirComponent intermediate = optionalCompanionCoilUsedForHeatRecovery()) { + if (OptionalHVACComponent intermediate = optionalCompanionCoilUsedForHeatRecovery()) { result.push_back(*intermediate); } @@ -100,11 +100,11 @@ namespace model { ModelObject CoilSystemCoolingWater_Impl::clone(Model model) const { auto coilSystemClone = StraightComponent_Impl::clone(model).cast(); - if (OptionalWaterToAirComponent intermediate = optionalCoolingCoil()) { - coilSystemClone.setCoolingCoil(intermediate->clone(model).cast()); + if (OptionalHVACComponent intermediate = optionalCoolingCoil()) { + coilSystemClone.setCoolingCoil(intermediate->clone(model).cast()); } - if (OptionalWaterToAirComponent intermediate = optionalCompanionCoilUsedForHeatRecovery()) { - coilSystemClone.setCompanionCoilUsedForHeatRecovery(intermediate->clone(model).cast()); + if (OptionalHVACComponent intermediate = optionalCompanionCoilUsedForHeatRecovery()) { + coilSystemClone.setCompanionCoilUsedForHeatRecovery(intermediate->clone(model).cast()); } return std::move(coilSystemClone); @@ -198,8 +198,8 @@ namespace model { return value.get(); } - WaterToAirComponent CoilSystemCoolingWater_Impl::coolingCoil() const { - boost::optional value = optionalCoolingCoil(); + HVACComponent CoilSystemCoolingWater_Impl::coolingCoil() const { + boost::optional value = optionalCoolingCoil(); if (!value) { LOG_AND_THROW(briefDescription() << " does not have an Cooling Coil attached."); } @@ -236,7 +236,7 @@ namespace model { return value.get(); } - boost::optional CoilSystemCoolingWater_Impl::companionCoilUsedForHeatRecovery() const { + boost::optional CoilSystemCoolingWater_Impl::companionCoilUsedForHeatRecovery() const { return optionalCompanionCoilUsedForHeatRecovery(); } @@ -246,7 +246,7 @@ namespace model { return result; } - bool CoilSystemCoolingWater_Impl::setCoolingCoil(const WaterToAirComponent& coolingCoil) { + bool CoilSystemCoolingWater_Impl::setCoolingCoil(const HVACComponent& coolingCoil) { const bool result = setPointer(OS_CoilSystem_Cooling_WaterFields::CoolingCoil, coolingCoil.handle()); return result; } @@ -286,9 +286,16 @@ namespace model { return result; } - bool CoilSystemCoolingWater_Impl::setCompanionCoilUsedForHeatRecovery(const WaterToAirComponent& companionCoilUsedForHeatRecovery) { - const bool result = setPointer(OS_CoilSystem_Cooling_WaterFields::CompanionCoilUsedForHeatRecovery, companionCoilUsedForHeatRecovery.handle()); - return result; + bool CoilSystemCoolingWater_Impl::setCompanionCoilUsedForHeatRecovery(const HVACComponent& companionCoilUsedForHeatRecovery) { + if (companionCoilUsedForHeatRecovery.iddObjectType() == IddObjectType::OS_Coil_Cooling_Water) { + const bool result = + setPointer(OS_CoilSystem_Cooling_WaterFields::CompanionCoilUsedForHeatRecovery, companionCoilUsedForHeatRecovery.handle()); + return result; + } else { + LOG(Warn, "Invalid Companion Coil Used For Heat Recovery Type (expected CoilCoolingWater, not '" + << companionCoilUsedForHeatRecovery.iddObjectType().valueName() << "') for " << briefDescription()); + return false; + } } void CoilSystemCoolingWater_Impl::resetCompanionCoilUsedForHeatRecovery() { @@ -300,12 +307,12 @@ namespace model { return getObject().getModelObjectTarget(OS_CoilSystem_Cooling_WaterFields::AvailabilityScheduleName); } - boost::optional CoilSystemCoolingWater_Impl::optionalCoolingCoil() const { - return getObject().getModelObjectTarget(OS_CoilSystem_Cooling_WaterFields::CoolingCoil); + boost::optional CoilSystemCoolingWater_Impl::optionalCoolingCoil() const { + return getObject().getModelObjectTarget(OS_CoilSystem_Cooling_WaterFields::CoolingCoil); } - boost::optional CoilSystemCoolingWater_Impl::optionalCompanionCoilUsedForHeatRecovery() const { - return getObject().getModelObjectTarget(OS_CoilSystem_Cooling_WaterFields::CompanionCoilUsedForHeatRecovery); + boost::optional CoilSystemCoolingWater_Impl::optionalCompanionCoilUsedForHeatRecovery() const { + return getObject().getModelObjectTarget(OS_CoilSystem_Cooling_WaterFields::CompanionCoilUsedForHeatRecovery); } } // namespace detail @@ -335,7 +342,7 @@ namespace model { OS_ASSERT(ok); } - CoilSystemCoolingWater::CoilSystemCoolingWater(const Model& model, const WaterToAirComponent& coolingCoil) + CoilSystemCoolingWater::CoilSystemCoolingWater(const Model& model, const HVACComponent& coolingCoil) : StraightComponent(CoilSystemCoolingWater::iddObjectType(), model) { OS_ASSERT(getImpl()); @@ -372,7 +379,7 @@ namespace model { return getImpl()->availabilitySchedule(); } - WaterToAirComponent CoilSystemCoolingWater::coolingCoil() const { + HVACComponent CoilSystemCoolingWater::coolingCoil() const { return getImpl()->coolingCoil(); } @@ -400,7 +407,7 @@ namespace model { return getImpl()->minimumWaterLoopTemperatureForHeatRecovery(); } - boost::optional CoilSystemCoolingWater::companionCoilUsedForHeatRecovery() const { + boost::optional CoilSystemCoolingWater::companionCoilUsedForHeatRecovery() const { return getImpl()->companionCoilUsedForHeatRecovery(); } @@ -408,7 +415,7 @@ namespace model { return getImpl()->setAvailabilitySchedule(schedule); } - bool CoilSystemCoolingWater::setCoolingCoil(const WaterToAirComponent& coolingCoil) { + bool CoilSystemCoolingWater::setCoolingCoil(const HVACComponent& coolingCoil) { return getImpl()->setCoolingCoil(coolingCoil); } @@ -436,7 +443,7 @@ namespace model { return getImpl()->setMinimumWaterLoopTemperatureForHeatRecovery(minimumWaterLoopTemperatureForHeatRecovery); } - bool CoilSystemCoolingWater::setCompanionCoilUsedForHeatRecovery(const WaterToAirComponent& companionCoilUsedForHeatRecovery) { + bool CoilSystemCoolingWater::setCompanionCoilUsedForHeatRecovery(const HVACComponent& companionCoilUsedForHeatRecovery) { return getImpl()->setCompanionCoilUsedForHeatRecovery(companionCoilUsedForHeatRecovery); } diff --git a/src/model/CoilSystemCoolingWater.hpp b/src/model/CoilSystemCoolingWater.hpp index e22211ecbd1..2d2b29ce9df 100644 --- a/src/model/CoilSystemCoolingWater.hpp +++ b/src/model/CoilSystemCoolingWater.hpp @@ -14,7 +14,7 @@ namespace openstudio { namespace model { class Schedule; - class WaterToAirComponent; + class HVACComponent; namespace detail { @@ -31,7 +31,7 @@ namespace model { explicit CoilSystemCoolingWater(const Model& model); - explicit CoilSystemCoolingWater(const Model& model, const WaterToAirComponent& coolingCoil); + explicit CoilSystemCoolingWater(const Model& model, const HVACComponent& coolingCoil); virtual ~CoilSystemCoolingWater() = default; // Default the copy and move operators because the virtual dtor is explicit @@ -51,7 +51,7 @@ namespace model { Schedule availabilitySchedule() const; - WaterToAirComponent coolingCoil() const; + HVACComponent coolingCoil() const; std::string dehumidificationControlType() const; @@ -65,7 +65,7 @@ namespace model { double minimumWaterLoopTemperatureForHeatRecovery() const; - boost::optional companionCoilUsedForHeatRecovery() const; + boost::optional companionCoilUsedForHeatRecovery() const; //@} /** @name Setters */ @@ -73,7 +73,8 @@ namespace model { bool setAvailabilitySchedule(Schedule& schedule); - bool setCoolingCoil(const WaterToAirComponent& coolingCoil); + // CoilCoolingWater or CoilSystemCoolingWaterHeatExchangerAssisted + bool setCoolingCoil(const HVACComponent& coolingCoil); bool setDehumidificationControlType(const std::string& dehumidificationControlType); @@ -87,7 +88,8 @@ namespace model { bool setMinimumWaterLoopTemperatureForHeatRecovery(double minimumWaterLoopTemperatureForHeatRecovery); - bool setCompanionCoilUsedForHeatRecovery(const WaterToAirComponent& companionCoilUsedForHeatRecovery); + // Only CoilCoolingWater is supported by E+ as a companion coil right now + bool setCompanionCoilUsedForHeatRecovery(const HVACComponent& companionCoilUsedForHeatRecovery); void resetCompanionCoilUsedForHeatRecovery(); diff --git a/src/model/CoilSystemCoolingWater_Impl.hpp b/src/model/CoilSystemCoolingWater_Impl.hpp index 860dd9dc5f2..5b583051ddb 100644 --- a/src/model/CoilSystemCoolingWater_Impl.hpp +++ b/src/model/CoilSystemCoolingWater_Impl.hpp @@ -13,7 +13,7 @@ namespace openstudio { namespace model { class Schedule; - class WaterToAirComponent; + class HVACComponent; namespace detail { @@ -70,7 +70,7 @@ namespace model { Schedule availabilitySchedule() const; - WaterToAirComponent coolingCoil() const; + HVACComponent coolingCoil() const; std::string dehumidificationControlType() const; @@ -84,7 +84,7 @@ namespace model { double minimumWaterLoopTemperatureForHeatRecovery() const; - boost::optional companionCoilUsedForHeatRecovery() const; + boost::optional companionCoilUsedForHeatRecovery() const; //@} /** @name Setters */ @@ -92,7 +92,7 @@ namespace model { bool setAvailabilitySchedule(Schedule& schedule); - bool setCoolingCoil(const WaterToAirComponent& coolingCoil); + bool setCoolingCoil(const HVACComponent& coolingCoil); bool setDehumidificationControlType(const std::string& dehumidificationControlType); @@ -106,7 +106,7 @@ namespace model { bool setMinimumWaterLoopTemperatureForHeatRecovery(double minimumWaterLoopTemperatureForHeatRecovery); - bool setCompanionCoilUsedForHeatRecovery(const WaterToAirComponent& companionCoilUsedForHeatRecovery); + bool setCompanionCoilUsedForHeatRecovery(const HVACComponent& companionCoilUsedForHeatRecovery); void resetCompanionCoilUsedForHeatRecovery(); @@ -120,8 +120,8 @@ namespace model { REGISTER_LOGGER("openstudio.model.CoilSystemCoolingWater"); boost::optional optionalAvailabilitySchedule() const; - boost::optional optionalCoolingCoil() const; - boost::optional optionalCompanionCoilUsedForHeatRecovery() const; + boost::optional optionalCoolingCoil() const; + boost::optional optionalCompanionCoilUsedForHeatRecovery() const; }; } // namespace detail From 310a14f7df9ccc215ea5e0a67a649c8924aab86f Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Mon, 5 May 2025 11:45:02 +0200 Subject: [PATCH 43/58] Improve model gtests --- .../test/CoilSystemCoolingWater_GTest.cpp | 90 ++++++++++++++++--- 1 file changed, 76 insertions(+), 14 deletions(-) diff --git a/src/model/test/CoilSystemCoolingWater_GTest.cpp b/src/model/test/CoilSystemCoolingWater_GTest.cpp index 7c1aa4b661a..c1b3241c63c 100644 --- a/src/model/test/CoilSystemCoolingWater_GTest.cpp +++ b/src/model/test/CoilSystemCoolingWater_GTest.cpp @@ -7,13 +7,18 @@ #include "../CoilSystemCoolingWater.hpp" #include "../CoilSystemCoolingWater_Impl.hpp" -#include "../Schedule.hpp" -#include "../Schedule_Impl.hpp" + #include "../CoilCoolingWater.hpp" #include "../CoilCoolingWater_Impl.hpp" +#include "../CoilSystemCoolingWaterHeatExchangerAssisted.hpp" +#include "../CoilSystemCoolingWaterHeatExchangerAssisted_Impl.hpp" #include "../AirLoopHVAC.hpp" -#include "../PlantLoop.hpp" +#include "../ChillerElectricEIR.hpp" #include "../Node.hpp" +#include "../PlantLoop.hpp" +#include "../Schedule.hpp" +#include "../ScheduleConstant.hpp" +#include "../ScheduleTypeLimits.hpp" using namespace openstudio; using namespace openstudio::model; @@ -26,35 +31,70 @@ TEST_F(ModelFixture, CoilSystemCoolingWater_GettersSetters) { coilSystemCoolingWater.setName("My CoilSystemCoolingWater"); // Availability Schedule Name: Required Object + // Ctor default Schedule availabilitySchedule = m.alwaysOnDiscreteSchedule(); - EXPECT_TRUE(coilSystemCoolingWater.setAvailabilitySchedule(availabilitySchedule)); EXPECT_EQ(availabilitySchedule, coilSystemCoolingWater.availabilitySchedule()); + // set + ScheduleConstant availSch(m); + EXPECT_TRUE(coilSystemCoolingWater.setAvailabilitySchedule(availSch)); + EXPECT_EQ(availSch, coilSystemCoolingWater.availabilitySchedule()); + // The Schedule Type Registry should have done it's thing and assigned a scheduleTypeLimits + ASSERT_TRUE(availSch.scheduleTypeLimits()); + { + auto sch_type_lim = availSch.scheduleTypeLimits().get(); + EXPECT_EQ("OnOff", sch_type_lim.nameString()); + ASSERT_TRUE(sch_type_lim.lowerLimitValue()); + EXPECT_EQ(0.0, sch_type_lim.lowerLimitValue().get()); + ASSERT_TRUE(sch_type_lim.upperLimitValue()); + EXPECT_EQ(1.0, sch_type_lim.upperLimitValue().get()); + ASSERT_TRUE(sch_type_lim.numericType()); + EXPECT_EQ("Discrete", sch_type_lim.numericType().get()); + EXPECT_EQ("Availability", sch_type_lim.unitType()); + } // Cooling Coil: Required Object + // Ctor instantiates a CoilCoolingWater + EXPECT_TRUE(coilSystemCoolingWater.coolingCoil().optionalCast()); CoilCoolingWater coolingCoil(m); EXPECT_TRUE(coilSystemCoolingWater.setCoolingCoil(coolingCoil)); EXPECT_EQ(coolingCoil, coilSystemCoolingWater.coolingCoil()); + CoilSystemCoolingWaterHeatExchangerAssisted coilSystemCoolingWaterHeatExchangerAssisted(m); + EXPECT_TRUE(coilSystemCoolingWater.setCoolingCoil(coilSystemCoolingWaterHeatExchangerAssisted)); + EXPECT_EQ(coilSystemCoolingWaterHeatExchangerAssisted, coilSystemCoolingWater.coolingCoil()); + // Dehumidification Control Type: Required String - EXPECT_TRUE(coilSystemCoolingWater.setDehumidificationControlType("None")); + // Ctor default EXPECT_EQ("None", coilSystemCoolingWater.dehumidificationControlType()); + // set + EXPECT_TRUE(coilSystemCoolingWater.setDehumidificationControlType("CoolReheat")); + EXPECT_EQ("CoolReheat", coilSystemCoolingWater.dehumidificationControlType()); // Bad Value EXPECT_FALSE(coilSystemCoolingWater.setDehumidificationControlType("BADENUM")); - EXPECT_EQ("None", coilSystemCoolingWater.dehumidificationControlType()); + EXPECT_EQ("CoolReheat", coilSystemCoolingWater.dehumidificationControlType()); // Run on Sensible Load: Required Boolean - EXPECT_TRUE(coilSystemCoolingWater.setRunonSensibleLoad(true)); + // Ctor default EXPECT_TRUE(coilSystemCoolingWater.runonSensibleLoad()); + // set EXPECT_TRUE(coilSystemCoolingWater.setRunonSensibleLoad(false)); EXPECT_FALSE(coilSystemCoolingWater.runonSensibleLoad()); + EXPECT_TRUE(coilSystemCoolingWater.setRunonSensibleLoad(true)); + EXPECT_TRUE(coilSystemCoolingWater.runonSensibleLoad()); // Run on Latent Load: Required Boolean + // Ctor default + EXPECT_FALSE(coilSystemCoolingWater.runonLatentLoad()); + // set EXPECT_TRUE(coilSystemCoolingWater.setRunonLatentLoad(true)); EXPECT_TRUE(coilSystemCoolingWater.runonLatentLoad()); EXPECT_TRUE(coilSystemCoolingWater.setRunonLatentLoad(false)); EXPECT_FALSE(coilSystemCoolingWater.runonLatentLoad()); // Minimum Air To Water Temperature Offset: Required Double + // Ctor default + EXPECT_EQ(0.0, coilSystemCoolingWater.minimumAirToWaterTemperatureOffset()); + // set EXPECT_TRUE(coilSystemCoolingWater.setMinimumAirToWaterTemperatureOffset(1.0)); EXPECT_EQ(1.0, coilSystemCoolingWater.minimumAirToWaterTemperatureOffset()); // Bad Value @@ -62,31 +102,53 @@ TEST_F(ModelFixture, CoilSystemCoolingWater_GettersSetters) { EXPECT_EQ(1.0, coilSystemCoolingWater.minimumAirToWaterTemperatureOffset()); // Economizer Lockout: Required Boolean - EXPECT_TRUE(coilSystemCoolingWater.setEconomizerLockout(true)); + // Ctor default EXPECT_TRUE(coilSystemCoolingWater.economizerLockout()); + // set EXPECT_TRUE(coilSystemCoolingWater.setEconomizerLockout(false)); EXPECT_FALSE(coilSystemCoolingWater.economizerLockout()); + EXPECT_TRUE(coilSystemCoolingWater.setEconomizerLockout(true)); + EXPECT_TRUE(coilSystemCoolingWater.economizerLockout()); // Minimum Water Loop Temperature For Heat Recovery: Required Double + // Ctor default + EXPECT_EQ(0.0, coilSystemCoolingWater.minimumWaterLoopTemperatureForHeatRecovery()); + // set EXPECT_TRUE(coilSystemCoolingWater.setMinimumWaterLoopTemperatureForHeatRecovery(1.2)); EXPECT_EQ(1.2, coilSystemCoolingWater.minimumWaterLoopTemperatureForHeatRecovery()); // Companion Coil Used For Heat Recovery: Optional Object + // The only type allowed is CoilCoolingWater CoilCoolingWater companionCoilUsedForHeatRecovery(m); EXPECT_TRUE(coilSystemCoolingWater.setCompanionCoilUsedForHeatRecovery(companionCoilUsedForHeatRecovery)); ASSERT_TRUE(coilSystemCoolingWater.companionCoilUsedForHeatRecovery()); EXPECT_EQ(companionCoilUsedForHeatRecovery, coilSystemCoolingWater.companionCoilUsedForHeatRecovery().get()); + + CoilSystemCoolingWaterHeatExchangerAssisted wrongCompanionCoil(m); + EXPECT_FALSE(coilSystemCoolingWater.setCompanionCoilUsedForHeatRecovery(wrongCompanionCoil)); + ASSERT_TRUE(coilSystemCoolingWater.companionCoilUsedForHeatRecovery()); + EXPECT_EQ(companionCoilUsedForHeatRecovery, coilSystemCoolingWater.companionCoilUsedForHeatRecovery().get()); } TEST_F(ModelFixture, CoilSystemCoolingWater_HeatCoolFuelTypes) { Model m; - CoilSystemCoolingWater coilSystemCoolingWater(m); - - EXPECT_EQ(ComponentType(ComponentType::Cooling), coilSystemCoolingWater.componentType()); - testFuelTypeEquality({}, coilSystemCoolingWater.coolingFuelTypes()); - testFuelTypeEquality({}, coilSystemCoolingWater.heatingFuelTypes()); - testAppGFuelTypeEquality({}, coilSystemCoolingWater.appGHeatingFuelTypes()); + CoilSystemCoolingWater coilSystem(m); + auto cc = coilSystem.coolingCoil().cast(); + + EXPECT_EQ(ComponentType(ComponentType::Cooling), coilSystem.componentType()); + testFuelTypeEquality({}, coilSystem.coolingFuelTypes()); + testFuelTypeEquality({}, coilSystem.heatingFuelTypes()); + testAppGFuelTypeEquality({}, coilSystem.appGHeatingFuelTypes()); + + PlantLoop p(m); + ChillerElectricEIR ch(m); + EXPECT_TRUE(p.addSupplyBranchForComponent(ch)); + EXPECT_TRUE(p.addDemandBranchForComponent(cc)); + EXPECT_EQ(ComponentType(ComponentType::Cooling), coilSystem.componentType()); + testFuelTypeEquality({FuelType::Electricity}, coilSystem.coolingFuelTypes()); + testFuelTypeEquality({}, coilSystem.heatingFuelTypes()); + testAppGFuelTypeEquality({}, coilSystem.appGHeatingFuelTypes()); } TEST_F(ModelFixture, CoilSystemCoolingWater_clone) {} From d0cc34b698dc71fdbffeeb0ed9bbdebc9774a257 Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Mon, 5 May 2025 11:57:50 +0200 Subject: [PATCH 44/58] Test Explicit Ctor, including wrong cooling coil type + fixup explicit ctor to remove() and LOG_AND_THROW --- src/model/CoilSystemCoolingWater.cpp | 7 +++-- .../test/CoilSystemCoolingWater_GTest.cpp | 31 +++++++++++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/model/CoilSystemCoolingWater.cpp b/src/model/CoilSystemCoolingWater.cpp index 359aef8b051..de9d9174233 100644 --- a/src/model/CoilSystemCoolingWater.cpp +++ b/src/model/CoilSystemCoolingWater.cpp @@ -347,12 +347,15 @@ namespace model { OS_ASSERT(getImpl()); bool ok = true; + ok = setCoolingCoil(coolingCoil); + if (!ok) { + remove(); + LOG_AND_THROW("Unable to set " << briefDescription() << "'s Cooling Coil " << coolingCoil.briefDescription() << "."); + } auto alwaysOn = model.alwaysOnDiscreteSchedule(); ok = setAvailabilitySchedule(alwaysOn); OS_ASSERT(ok); - ok = setCoolingCoil(coolingCoil); - OS_ASSERT(ok); ok = setDehumidificationControlType("None"); OS_ASSERT(ok); ok = setRunonSensibleLoad(true); diff --git a/src/model/test/CoilSystemCoolingWater_GTest.cpp b/src/model/test/CoilSystemCoolingWater_GTest.cpp index c1b3241c63c..08cd8677b2d 100644 --- a/src/model/test/CoilSystemCoolingWater_GTest.cpp +++ b/src/model/test/CoilSystemCoolingWater_GTest.cpp @@ -12,8 +12,11 @@ #include "../CoilCoolingWater_Impl.hpp" #include "../CoilSystemCoolingWaterHeatExchangerAssisted.hpp" #include "../CoilSystemCoolingWaterHeatExchangerAssisted_Impl.hpp" + #include "../AirLoopHVAC.hpp" #include "../ChillerElectricEIR.hpp" +#include "../CoilCoolingDXSingleSpeed.hpp" +#include "../CoilCoolingDXSingleSpeed_Impl.hpp" #include "../Node.hpp" #include "../PlantLoop.hpp" #include "../Schedule.hpp" @@ -130,6 +133,34 @@ TEST_F(ModelFixture, CoilSystemCoolingWater_GettersSetters) { EXPECT_EQ(companionCoilUsedForHeatRecovery, coilSystemCoolingWater.companionCoilUsedForHeatRecovery().get()); } +TEST_F(ModelFixture, CoilSystemCoolingWater_ExplicitCtor) { + { + Model m; + CoilCoolingWater coolingCoil(m); + CoilSystemCoolingWater coilSystem(m, coolingCoil); + EXPECT_EQ(coolingCoil, coilSystem.coolingCoil()); + EXPECT_EQ(1, m.getConcreteModelObjects().size()); + EXPECT_EQ(1, m.getConcreteModelObjects().size()); + } + + { + Model m; + CoilSystemCoolingWaterHeatExchangerAssisted coolingCoil(m); + CoilSystemCoolingWater coilSystem(m, coolingCoil); + EXPECT_EQ(coolingCoil, coilSystem.coolingCoil()); + EXPECT_EQ(1, m.getConcreteModelObjects().size()); + EXPECT_EQ(1, m.getConcreteModelObjects().size()); + } + + { + Model m; + CoilCoolingDXSingleSpeed coolingCoil(m); + EXPECT_ANY_THROW(CoilSystemCoolingWater coilSystem(m, coolingCoil)); + EXPECT_EQ(0, m.getConcreteModelObjects().size()); + EXPECT_EQ(1, m.getConcreteModelObjects().size()); + } +} + TEST_F(ModelFixture, CoilSystemCoolingWater_HeatCoolFuelTypes) { Model m; From ba57cdab084f70b5b5e1b133b18ee39e310506df Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Mon, 5 May 2025 14:50:20 +0200 Subject: [PATCH 45/58] Remove useless optionalCompanionCoilUsedForHeatRecovery --- src/model/CoilSystemCoolingWater.cpp | 10 +++------- src/model/CoilSystemCoolingWater_Impl.hpp | 1 - 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/src/model/CoilSystemCoolingWater.cpp b/src/model/CoilSystemCoolingWater.cpp index de9d9174233..c993c17ee3b 100644 --- a/src/model/CoilSystemCoolingWater.cpp +++ b/src/model/CoilSystemCoolingWater.cpp @@ -90,7 +90,7 @@ namespace model { if (OptionalHVACComponent intermediate = optionalCoolingCoil()) { result.push_back(*intermediate); } - if (OptionalHVACComponent intermediate = optionalCompanionCoilUsedForHeatRecovery()) { + if (OptionalHVACComponent intermediate = companionCoilUsedForHeatRecovery()) { result.push_back(*intermediate); } @@ -103,7 +103,7 @@ namespace model { if (OptionalHVACComponent intermediate = optionalCoolingCoil()) { coilSystemClone.setCoolingCoil(intermediate->clone(model).cast()); } - if (OptionalHVACComponent intermediate = optionalCompanionCoilUsedForHeatRecovery()) { + if (OptionalHVACComponent intermediate = companionCoilUsedForHeatRecovery()) { coilSystemClone.setCompanionCoilUsedForHeatRecovery(intermediate->clone(model).cast()); } @@ -237,7 +237,7 @@ namespace model { } boost::optional CoilSystemCoolingWater_Impl::companionCoilUsedForHeatRecovery() const { - return optionalCompanionCoilUsedForHeatRecovery(); + return getObject().getModelObjectTarget(OS_CoilSystem_Cooling_WaterFields::CompanionCoilUsedForHeatRecovery); } bool CoilSystemCoolingWater_Impl::setAvailabilitySchedule(Schedule& schedule) { @@ -311,10 +311,6 @@ namespace model { return getObject().getModelObjectTarget(OS_CoilSystem_Cooling_WaterFields::CoolingCoil); } - boost::optional CoilSystemCoolingWater_Impl::optionalCompanionCoilUsedForHeatRecovery() const { - return getObject().getModelObjectTarget(OS_CoilSystem_Cooling_WaterFields::CompanionCoilUsedForHeatRecovery); - } - } // namespace detail CoilSystemCoolingWater::CoilSystemCoolingWater(const Model& model) : StraightComponent(CoilSystemCoolingWater::iddObjectType(), model) { diff --git a/src/model/CoilSystemCoolingWater_Impl.hpp b/src/model/CoilSystemCoolingWater_Impl.hpp index 5b583051ddb..9d558cc1536 100644 --- a/src/model/CoilSystemCoolingWater_Impl.hpp +++ b/src/model/CoilSystemCoolingWater_Impl.hpp @@ -121,7 +121,6 @@ namespace model { boost::optional optionalAvailabilitySchedule() const; boost::optional optionalCoolingCoil() const; - boost::optional optionalCompanionCoilUsedForHeatRecovery() const; }; } // namespace detail From 4f3e2d4111a21f58243a7c7ebf13c4055ce205a6 Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Mon, 5 May 2025 15:17:51 +0200 Subject: [PATCH 46/58] CoilSystemCoolingWaterHXAssisted:containingHVACComponent picks up CoilSystemCoolingWater --- .../CoilSystemCoolingWaterHeatExchangerAssisted.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/model/CoilSystemCoolingWaterHeatExchangerAssisted.cpp b/src/model/CoilSystemCoolingWaterHeatExchangerAssisted.cpp index ddfcb530900..f3ff98c8cce 100644 --- a/src/model/CoilSystemCoolingWaterHeatExchangerAssisted.cpp +++ b/src/model/CoilSystemCoolingWaterHeatExchangerAssisted.cpp @@ -11,6 +11,8 @@ #include "WaterToAirComponent_Impl.hpp" #include "CoilCoolingWater.hpp" #include "CoilCoolingWater_Impl.hpp" +#include "CoilSystemCoolingWater.hpp" +#include "CoilSystemCoolingWater_Impl.hpp" #include "Model.hpp" #include "Model_Impl.hpp" #include "Node.hpp" @@ -105,6 +107,17 @@ namespace model { } } + // CoilSystemCoolingWater + for (const auto& coilSystem : this->model().getConcreteModelObjects()) { + if (coilSystem.coolingCoil().handle() == this->handle()) { + return coilSystem; + } else if (boost::optional companionCoil_ = coilSystem.companionCoilUsedForHeatRecovery()) { + if (companionCoil_->handle() == this->handle()) { + return coilSystem; + } + } + } + return boost::none; } From 63acda6fe25e3f698503c21335a7a75c7d5c75a9 Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Mon, 5 May 2025 15:18:52 +0200 Subject: [PATCH 47/58] Extend testing to ensure that remove works in particular --- ...oolingWaterHeatExchangerAssisted_GTest.cpp | 28 ++- .../test/CoilSystemCoolingWater_GTest.cpp | 164 +++++++++++++++++- 2 files changed, 177 insertions(+), 15 deletions(-) diff --git a/src/model/test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp b/src/model/test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp index 914fe9cfa3a..78bf7460a02 100644 --- a/src/model/test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp +++ b/src/model/test/CoilSystemCoolingWaterHeatExchangerAssisted_GTest.cpp @@ -98,11 +98,16 @@ TEST_F(ModelFixture, CoilSystemCoolingWaterHeatExchangerAssisted_clone) { auto hx = coilSystem.heatExchanger().cast(); AirLoopHVAC a(m); + EXPECT_EQ(2, a.supplyComponents().size()); // o --- o Node n = a.supplyOutletNode(); EXPECT_TRUE(coilSystem.addToNode(n)); + EXPECT_EQ(3, a.supplyComponents().size()); // o --- oa_sys --- o PlantLoop p(m); + EXPECT_EQ(5, p.demandComponents().size()); // o --- Splitter --- o --- Mixer --- o + EXPECT_TRUE(p.addDemandBranchForComponent(cc)); + EXPECT_EQ(7, p.demandComponents().size()); // o --- Splitter --- o --- coolingCoil --- Mixer --- o EXPECT_EQ(1u, m.getConcreteModelObjects().size()); EXPECT_EQ(1u, m.getConcreteModelObjects().size()); @@ -118,7 +123,7 @@ TEST_F(ModelFixture, CoilSystemCoolingWaterHeatExchangerAssisted_clone) { //EXPECT_EQ(coilSystem.plantLoop()->handle(), p.handle()); //EXPECT_TRUE(hx.airLoopHVAC()); - auto coilSystem2 = coilSystem.clone(m).cast(); + auto coilSystemClone = coilSystem.clone(m).cast(); EXPECT_EQ(2u, m.getConcreteModelObjects().size()); EXPECT_EQ(2u, m.getConcreteModelObjects().size()); @@ -128,12 +133,23 @@ TEST_F(ModelFixture, CoilSystemCoolingWaterHeatExchangerAssisted_clone) { EXPECT_TRUE(coilSystem.inletModelObject()); EXPECT_TRUE(coilSystem.outletModelObject()); - EXPECT_FALSE(coilSystem2.airLoopHVAC()); - EXPECT_FALSE(coilSystem2.inletModelObject()); - EXPECT_FALSE(coilSystem2.outletModelObject()); + EXPECT_FALSE(coilSystemClone.airLoopHVAC()); + EXPECT_FALSE(coilSystemClone.inletModelObject()); + EXPECT_FALSE(coilSystemClone.outletModelObject()); + + EXPECT_NE(coilSystemClone.coolingCoil().handle(), cc.handle()); + EXPECT_NE(coilSystemClone.heatExchanger().handle(), hx.handle()); + + coilSystemClone.remove(); + EXPECT_EQ(1, m.getConcreteModelObjects().size()); + EXPECT_EQ(1, m.getConcreteModelObjects().size()); + + coilSystem.remove(); + EXPECT_EQ(0, m.getConcreteModelObjects().size()); + EXPECT_EQ(0, m.getConcreteModelObjects().size()); - EXPECT_NE(coilSystem2.coolingCoil().handle(), cc.handle()); - EXPECT_NE(coilSystem2.heatExchanger().handle(), hx.handle()); + EXPECT_EQ(2, a.supplyComponents().size()); // o --- o + EXPECT_EQ(5, p.demandComponents().size()); // o --- Splitter --- o --- Mixer --- o } TEST_F(ModelFixture, CoilSystemCoolingWaterHeatExchangerAssisted_containingComponent) { diff --git a/src/model/test/CoilSystemCoolingWater_GTest.cpp b/src/model/test/CoilSystemCoolingWater_GTest.cpp index 08cd8677b2d..964dfa57a8b 100644 --- a/src/model/test/CoilSystemCoolingWater_GTest.cpp +++ b/src/model/test/CoilSystemCoolingWater_GTest.cpp @@ -14,10 +14,14 @@ #include "../CoilSystemCoolingWaterHeatExchangerAssisted_Impl.hpp" #include "../AirLoopHVAC.hpp" +#include "../AirLoopHVACOutdoorAirSystem.hpp" #include "../ChillerElectricEIR.hpp" #include "../CoilCoolingDXSingleSpeed.hpp" #include "../CoilCoolingDXSingleSpeed_Impl.hpp" +#include "../ControllerWaterCoil.hpp" +#include "../ControllerWaterCoil_Impl.hpp" #include "../Node.hpp" +#include "../Node_Impl.hpp" #include "../PlantLoop.hpp" #include "../Schedule.hpp" #include "../ScheduleConstant.hpp" @@ -182,9 +186,151 @@ TEST_F(ModelFixture, CoilSystemCoolingWater_HeatCoolFuelTypes) { testAppGFuelTypeEquality({}, coilSystem.appGHeatingFuelTypes()); } -TEST_F(ModelFixture, CoilSystemCoolingWater_clone) {} +TEST_F(ModelFixture, CoilSystemCoolingWater_clone_remove) { -TEST_F(ModelFixture, CoilSystemCoolingWater_remove) {} + Model m; + + // Wrap Around Water Coil Heat Recovery Mode + // CoilSystem has: + // - Primary Cooling Coil: a CoilSystemCoolingWaterHeatExchangerAssisted + // - This HXAssisted has a CoilCoolingWater as its coolingCoil + // - Companion Coil: a CoilCoolingWater + // + // CoilSystem is connected to an AirLoopHVACOutdoorAirSystem on the OA Intake + // Companion Coil is connected to OA Relief + // Both coils are connected to a PlantLoop in series on the demand side + + CoilSystemCoolingWaterHeatExchangerAssisted coilSystemHXAssisted(m); + auto coolingCoil = coilSystemHXAssisted.coolingCoil().cast(); + coolingCoil.setName("Primary Cooling Coil inside HXAssisted"); + CoilSystemCoolingWater coilSystem(m, coilSystemHXAssisted); + + CoilCoolingWater companionCoil(m); + companionCoil.setName("Companion Coil"); + EXPECT_TRUE(coilSystem.setCompanionCoilUsedForHeatRecovery(companionCoil)); + + // Air side connections + AirLoopHVAC a(m); + AirLoopHVACOutdoorAirSystem oa_sys(m); + EXPECT_EQ(2, a.supplyComponents().size()); // o --- o + EXPECT_EQ(1, oa_sys.oaComponents().size()); // o + EXPECT_EQ(1, oa_sys.reliefComponents().size()); // o + { + Node n = a.supplyOutletNode(); + EXPECT_TRUE(oa_sys.addToNode(n)); + } + EXPECT_EQ(3, a.supplyComponents().size()); // o --- oa_sys --- o + EXPECT_EQ(1, oa_sys.oaComponents().size()); // o + EXPECT_EQ(1, oa_sys.reliefComponents().size()); // o + { + Node n = oa_sys.outboardOANode().get(); + EXPECT_TRUE(coilSystem.addToNode(n)); + } + EXPECT_EQ(3, a.supplyComponents().size()); // o --- oa_sys --- o + EXPECT_EQ(3, oa_sys.oaComponents().size()); // o --- coilSystem --- o + EXPECT_EQ(1, oa_sys.reliefComponents().size()); // o + { + Node n = oa_sys.outboardReliefNode().get(); + EXPECT_TRUE(companionCoil.addToNode(n)); + } + EXPECT_EQ(3, a.supplyComponents().size()); // o --- oa_sys --- o + EXPECT_EQ(3, oa_sys.oaComponents().size()); // o --- coilSystem --- o + EXPECT_EQ(3, oa_sys.reliefComponents().size()); // o --- companionCoil --- o + + // Plant Side connections: in series + PlantLoop p(m); + EXPECT_EQ(5, p.demandComponents().size()); // o --- Splitter --- o --- Mixer --- o + + EXPECT_TRUE(p.addDemandBranchForComponent(coolingCoil)); + EXPECT_EQ(7, p.demandComponents().size()); // o --- Splitter --- o --- coolingCoil --- Mixer --- o + + { + Node n = coolingCoil.waterOutletModelObject()->cast(); + EXPECT_TRUE(companionCoil.addToNode(n)); + } + EXPECT_EQ(9, p.demandComponents().size()); // o --- Splitter --- o --- coolingCoil --- o --- HR Coil --- o --- Mixer --- o + + EXPECT_EQ(1, m.getConcreteModelObjects().size()); + EXPECT_EQ(1, m.getConcreteModelObjects().size()); + EXPECT_EQ(2, m.getConcreteModelObjects().size()); + + ASSERT_TRUE(coilSystem.airLoopHVAC()); + EXPECT_EQ(coilSystem.airLoopHVAC()->handle(), a.handle()); + + EXPECT_TRUE(coolingCoil.plantLoop()); + EXPECT_TRUE(companionCoil.plantLoop()); + + EXPECT_FALSE(coolingCoil.controllerWaterCoil()); + EXPECT_FALSE(companionCoil.controllerWaterCoil()); + EXPECT_EQ(0, m.getConcreteModelObjects().size()); + + auto coilSystemClone = coilSystem.clone(m).cast(); + + EXPECT_EQ(2, m.getConcreteModelObjects().size()); + EXPECT_EQ(2, m.getConcreteModelObjects().size()); + EXPECT_EQ(4, m.getConcreteModelObjects().size()); + EXPECT_EQ(0, m.getConcreteModelObjects().size()); + + EXPECT_TRUE(coilSystem.airLoopHVAC()); + EXPECT_TRUE(coilSystem.inletModelObject()); + EXPECT_TRUE(coilSystem.outletModelObject()); + + EXPECT_FALSE(coilSystemClone.airLoopHVAC()); + EXPECT_FALSE(coilSystemClone.inletModelObject()); + EXPECT_FALSE(coilSystemClone.outletModelObject()); + + EXPECT_TRUE(coilSystemClone.coolingCoil().optionalCast()); + EXPECT_NE(coilSystemHXAssisted.handle(), coilSystemClone.coolingCoil().handle()); + + ASSERT_TRUE(coilSystemClone.companionCoilUsedForHeatRecovery()); + EXPECT_TRUE(coilSystemClone.companionCoilUsedForHeatRecovery()->optionalCast()); + EXPECT_NE(companionCoil.handle(), coilSystemClone.companionCoilUsedForHeatRecovery()->handle()); + + // Clone into another Model + { + Model m2; + auto coilSystemClone = coilSystem.clone(m2).cast(); + + EXPECT_EQ(1, m2.getConcreteModelObjects().size()); + EXPECT_EQ(1, m2.getConcreteModelObjects().size()); + EXPECT_EQ(2, m2.getConcreteModelObjects().size()); + EXPECT_EQ(0, m2.getConcreteModelObjects().size()); + + EXPECT_FALSE(coilSystemClone.airLoopHVAC()); + EXPECT_FALSE(coilSystemClone.inletModelObject()); + EXPECT_FALSE(coilSystemClone.outletModelObject()); + + EXPECT_TRUE(coilSystemClone.coolingCoil().optionalCast()); + EXPECT_NE(coilSystemHXAssisted.handle(), coilSystemClone.coolingCoil().handle()); + + ASSERT_TRUE(coilSystemClone.companionCoilUsedForHeatRecovery()); + EXPECT_TRUE(coilSystemClone.companionCoilUsedForHeatRecovery()->optionalCast()); + EXPECT_NE(companionCoil.handle(), coilSystemClone.companionCoilUsedForHeatRecovery()->handle()); + + // Remove + coilSystemClone.remove(); + EXPECT_EQ(0, m2.getConcreteModelObjects().size()); + EXPECT_EQ(0, m2.getConcreteModelObjects().size()); + EXPECT_EQ(0, m2.getConcreteModelObjects().size()); + } + + coilSystemClone.remove(); + EXPECT_EQ(1, m.getConcreteModelObjects().size()); + EXPECT_EQ(1, m.getConcreteModelObjects().size()); + EXPECT_EQ(2, m.getConcreteModelObjects().size()); + EXPECT_EQ(0, m.getConcreteModelObjects().size()); + + coilSystem.remove(); + EXPECT_EQ(0, m.getConcreteModelObjects().size()); + EXPECT_EQ(0, m.getConcreteModelObjects().size()); + EXPECT_EQ(0, m.getConcreteModelObjects().size()); + EXPECT_EQ(0, m.getConcreteModelObjects().size()); + + EXPECT_EQ(3, a.supplyComponents().size()); // o --- oa_sys --- o + EXPECT_EQ(1, oa_sys.oaComponents().size()); // o + EXPECT_EQ(1, oa_sys.reliefComponents().size()); // o + EXPECT_EQ(5, p.demandComponents().size()); // o --- Splitter --- o --- Mixer --- o +} TEST_F(ModelFixture, CoilSystemCoolingWater_addToNode) { // Water Size Economizer Model @@ -199,11 +345,11 @@ TEST_F(ModelFixture, CoilSystemCoolingWater_addToNode) { EXPECT_EQ(2u, a.supplyComponents().size()); - EXPECT_TRUE(cc.addToNode(n)); - EXPECT_EQ(3u, a.supplyComponents().size()); + EXPECT_FALSE(cc.addToNode(n)); + EXPECT_EQ(2u, a.supplyComponents().size()); EXPECT_TRUE(coilSystem.addToNode(n)); - EXPECT_EQ(5u, a.supplyComponents().size()); + EXPECT_EQ(3u, a.supplyComponents().size()); { auto containingHVACComponent = cc.containingHVACComponent(); @@ -231,14 +377,14 @@ TEST_F(ModelFixture, CoilSystemCoolingWater_addToNode) { EXPECT_EQ(2u, a.supplyComponents().size()); - EXPECT_TRUE(cc.addToNode(n)); - EXPECT_EQ(3u, a.supplyComponents().size()); + EXPECT_FALSE(cc.addToNode(n)); + EXPECT_EQ(2, a.supplyComponents().size()); EXPECT_TRUE(hr.addToNode(n)); - EXPECT_EQ(5u, a.supplyComponents().size()); + EXPECT_EQ(3, a.supplyComponents().size()); EXPECT_TRUE(coilSystem.addToNode(n)); - EXPECT_EQ(7u, a.supplyComponents().size()); + EXPECT_EQ(5, a.supplyComponents().size()); { auto containingHVACComponent = cc.containingHVACComponent(); From b264a564dc3fabf86b538ee874daf5511530634d Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Mon, 5 May 2025 15:28:32 +0200 Subject: [PATCH 48/58] Override remove() for CoilSystemCoolingWaterXX objects: need to disconnect the water side for the children coils --- src/model/CoilSystemCoolingWater.cpp | 25 +++++++++++++++++++ ...ystemCoolingWaterHeatExchangerAssisted.cpp | 19 +++++++++++--- ...CoolingWaterHeatExchangerAssisted_Impl.hpp | 5 +++- src/model/CoilSystemCoolingWater_Impl.hpp | 5 +++- 4 files changed, 48 insertions(+), 6 deletions(-) diff --git a/src/model/CoilSystemCoolingWater.cpp b/src/model/CoilSystemCoolingWater.cpp index c993c17ee3b..ced7f236681 100644 --- a/src/model/CoilSystemCoolingWater.cpp +++ b/src/model/CoilSystemCoolingWater.cpp @@ -12,6 +12,8 @@ #include "HVACComponent_Impl.hpp" #include "CoilCoolingWater.hpp" #include "CoilCoolingWater_Impl.hpp" +#include "CoilSystemCoolingWaterHeatExchangerAssisted.hpp" +#include "CoilSystemCoolingWaterHeatExchangerAssisted_Impl.hpp" #include "Model.hpp" #include "Model_Impl.hpp" #include "Node.hpp" @@ -97,6 +99,29 @@ namespace model { return result; } + std::vector CoilSystemCoolingWater_Impl::remove() { + std::vector result; + + if (auto c_ = optionalCoolingCoil()) { // This is false when the explicit ctor throws + if (boost::optional cc_ = c_->optionalCast()) { + cc_->removeFromPlantLoop(); + } else if (auto cc_ = c_->optionalCast()) { + cc_->coolingCoil().removeFromPlantLoop(); + } else { + OS_ASSERT(false); + } + } + if (auto companionCoil_ = companionCoilUsedForHeatRecovery()) { + if (auto cc_ = companionCoil_->optionalCast()) { + cc_->removeFromPlantLoop(); + } else { + OS_ASSERT(false); + } + } + + return StraightComponent_Impl::remove(); + } + ModelObject CoilSystemCoolingWater_Impl::clone(Model model) const { auto coilSystemClone = StraightComponent_Impl::clone(model).cast(); diff --git a/src/model/CoilSystemCoolingWaterHeatExchangerAssisted.cpp b/src/model/CoilSystemCoolingWaterHeatExchangerAssisted.cpp index f3ff98c8cce..4c47c420be9 100644 --- a/src/model/CoilSystemCoolingWaterHeatExchangerAssisted.cpp +++ b/src/model/CoilSystemCoolingWaterHeatExchangerAssisted.cpp @@ -73,8 +73,12 @@ namespace model { std::vector CoilSystemCoolingWaterHeatExchangerAssisted_Impl::children() const { std::vector result; - result.push_back(coolingCoil()); - result.push_back(heatExchanger()); + if (auto intermediate = optionalCoolingCoil()) { + result.push_back(*intermediate); + } + if (auto intermediate = optionalHeatExchanger()) { + result.push_back(*intermediate); + } return result; } @@ -95,6 +99,14 @@ namespace model { return std::move(newCoilSystem); } + std::vector CoilSystemCoolingWaterHeatExchangerAssisted_Impl::remove() { + if (auto cc_ = optionalCoolingCoil()) { + cc_->removeFromPlantLoop(); + } + + return StraightComponent_Impl::remove(); + } + boost::optional CoilSystemCoolingWaterHeatExchangerAssisted_Impl::containingHVACComponent() const { // AirLoopHVACUnitarySystem std::vector airLoopHVACUnitarySystems = this->model().getConcreteModelObjects(); @@ -248,13 +260,12 @@ namespace model { bool ok = setHeatExchanger(heatExchanger); if (!ok) { + remove(); LOG_AND_THROW("Unable to set " << briefDescription() << "'s Heat Exchanger " << heatExchanger.briefDescription() << "."); } CoilCoolingWater coolingCoil(model); setCoolingCoil(coolingCoil); - - setHeatExchanger(heatExchanger); } IddObjectType CoilSystemCoolingWaterHeatExchangerAssisted::iddObjectType() { diff --git a/src/model/CoilSystemCoolingWaterHeatExchangerAssisted_Impl.hpp b/src/model/CoilSystemCoolingWaterHeatExchangerAssisted_Impl.hpp index 85bb4ef471c..375e842e9ed 100644 --- a/src/model/CoilSystemCoolingWaterHeatExchangerAssisted_Impl.hpp +++ b/src/model/CoilSystemCoolingWaterHeatExchangerAssisted_Impl.hpp @@ -51,9 +51,12 @@ namespace model { // Will also clone the coolingCoil and heatExchanger virtual ModelObject clone(Model model) const override; - // This function will connect the underlying Coil:Cooling:Water object + // This function will connect the air side only, for water side, use the coils directly virtual bool addToNode(Node& node) override; + // Need to disconnect the Water side of the coil(s) before removing + virtual std::vector remove() override; + virtual boost::optional containingHVACComponent() const override; virtual boost::optional containingZoneHVACComponent() const override; diff --git a/src/model/CoilSystemCoolingWater_Impl.hpp b/src/model/CoilSystemCoolingWater_Impl.hpp index 9d558cc1536..8793eba87ef 100644 --- a/src/model/CoilSystemCoolingWater_Impl.hpp +++ b/src/model/CoilSystemCoolingWater_Impl.hpp @@ -52,9 +52,12 @@ namespace model { // Will also clone the coolingCoil and companionCoilUsedForHeatRecovery virtual ModelObject clone(Model model) const override; - // This function will connect the underlying Coil:Cooling:Water object + // This function will connect the air side only, for water side, use the coils directly virtual bool addToNode(Node& node) override; + // Need to disconnect the Water side of the coil(s) before removing + virtual std::vector remove() override; + virtual boost::optional containingHVACComponent() const override; virtual boost::optional containingZoneHVACComponent() const override; From 53780c84a27e83c84839b5efa242fba76b5b4ddb Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Mon, 5 May 2025 15:29:38 +0200 Subject: [PATCH 49/58] Fixup the creation of the ControllerWaterCoil and disallow connection of the primary cooling cooling of a CoilSystemCoolingWater to an AirLoopHVAC Ensures coils that are part of a cooling system are not directly connected to an air loop, preventing potential errors. Also manages the creation and removal of ControllerWaterCoil objects based on the coil's parent system and presence within a ZoneHVACComponent. --- src/model/CoilCoolingWater.cpp | 80 +++++++++++++++++++++------------- 1 file changed, 50 insertions(+), 30 deletions(-) diff --git a/src/model/CoilCoolingWater.cpp b/src/model/CoilCoolingWater.cpp index 8576570f2f8..4be5cc9b666 100644 --- a/src/model/CoilCoolingWater.cpp +++ b/src/model/CoilCoolingWater.cpp @@ -273,48 +273,68 @@ namespace model { } bool CoilCoolingWater_Impl::addToNode(Node& node) { - bool success(false); + bool success = false; auto t_containingHVACComponent = containingHVACComponent(); auto t_airLoop = node.airLoopHVAC(); - if (t_airLoop && t_containingHVACComponent && t_containingHVACComponent->optionalCast()) { - LOG(Warn, this->briefDescription() - << " cannot be connected directly to an AirLoopHVAC when it's part of a parent CoilSystemCoolingWaterHeatExchangerAssisted. " - "Please call CoilSystemCoolingWaterHeatExchangerAssisted::addToNode instead"); - - /* } else if (t_airLoop && t_containingHVACComponent && t_containingHVACComponent->optionalCast()) { - LOG(Warn, this->briefDescription() - << " cannot be connected directly to an AirLoopHVAC when it's part of a parent CoilSystemCoolingWater. " - "Please call CoilSystemCoolingWater::addToNode instead"); */ + // Reject adding coils parent of a Parent System + if (t_airLoop && t_containingHVACComponent) { + if (t_containingHVACComponent->optionalCast()) { + LOG(Warn, this->briefDescription() + << " cannot be connected directly to an AirLoopHVAC when it's part of a parent CoilSystemCoolingWaterHeatExchangerAssisted. " + "Please call CoilSystemCoolingWaterHeatExchangerAssisted::addToNode instead"); + return false; + } - } else { + if (t_containingHVACComponent->optionalCast() + && t_containingHVACComponent->cast().coolingCoil().handle() == this->handle()) { + LOG(Warn, this->briefDescription() + << " cannot be connected directly to an AirLoopHVAC when it's the primary cooling coil of a parent CoilSystemCoolingWater. " + "Please call CoilSystemCoolingWater::addToNode instead"); + return false; + } + } - success = WaterToAirComponent_Impl::addToNode(node); - auto t_containingZoneHVACComponent = containingZoneHVACComponent(); + success = WaterToAirComponent_Impl::addToNode(node); + if (!success) { + return false; + } + // We only add the controller if we are not part of a containing ZoneHVACComponent, and we have a PlantLoop assigned + if (containingZoneHVACComponent() || !waterInletModelObject()) { + // We're done + return true; + } - if (success && (!t_containingZoneHVACComponent)) { - if (auto t_waterInletModelObject = waterInletModelObject()) { - if (auto oldController = controllerWaterCoil()) { - if (!openstudio::istringEqual(oldController->action().get(), "Reverse")) { - LOG(Warn, - briefDescription() - << " has an existing ControllerWaterCoil with action set to something else than 'Reverse'. Make sure this is what you want"); - } - } else { - if (t_containingHVACComponent && t_containingHVACComponent->optionalCast()) { - // no-op - } else { - Model t_model = model(); - ControllerWaterCoil controller(t_model); - controller.getImpl()->setWaterCoil(getObject()); - controller.setAction("Reverse"); - } + // We don't need a controller if we are part of a CoilSystemCoolingWater (directly, or indirectly via a + // CoilSystemCoolingWaterHeatExchangerAssisted) + bool needAController = true; + if (t_containingHVACComponent) { + if (t_containingHVACComponent->optionalCast()) { + needAController = false; + } else if (auto hxAssisted_ = t_containingHVACComponent->optionalCast()) { + if (auto parent_ = hxAssisted_->containingHVACComponent()) { + if (parent_->optionalCast()) { + needAController = false; } } } } + if (auto oldController_ = controllerWaterCoil()) { + if (!needAController) { + oldController_->remove(); + } else if (!openstudio::istringEqual(oldController_->action().get(), "Reverse")) { + LOG(Warn, briefDescription() + << " has an existing ControllerWaterCoil with action set to something else than 'Reverse'. Make sure this is what you want"); + } + } else if (needAController) { + Model t_model = model(); + ControllerWaterCoil controller(t_model); + controller.getImpl()->setWaterCoil(getObject()); + controller.setAction("Reverse"); + } + return success; } From 14c735774b8a534f1125c08ea5dfe9f99c63bff1 Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Mon, 5 May 2025 15:30:10 +0200 Subject: [PATCH 50/58] I have no reason to believe that CoilSystemCoolingWater would be allowed anywhere in a ZoneHVAC/HVACComponent --- src/model/CoilSystemCoolingWater.cpp | 40 ---------------------------- 1 file changed, 40 deletions(-) diff --git a/src/model/CoilSystemCoolingWater.cpp b/src/model/CoilSystemCoolingWater.cpp index ced7f236681..ad77a88ba47 100644 --- a/src/model/CoilSystemCoolingWater.cpp +++ b/src/model/CoilSystemCoolingWater.cpp @@ -152,50 +152,10 @@ namespace model { } boost::optional CoilSystemCoolingWater_Impl::containingHVACComponent() const { - // AirLoopHVACUnitarySystem - std::vector airLoopHVACUnitarySystems = this->model().getConcreteModelObjects(); - - for (const auto& airLoopHVACUnitarySystem : airLoopHVACUnitarySystems) { - if (boost::optional coolingCoil = airLoopHVACUnitarySystem.coolingCoil()) { - if (coolingCoil->handle() == this->handle()) { - return airLoopHVACUnitarySystem; - } - } - } - return boost::none; } boost::optional CoilSystemCoolingWater_Impl::containingZoneHVACComponent() const { - - // ZoneHVACFourPipeFanCoil - std::vector zoneHVACFourPipeFanCoils; - - zoneHVACFourPipeFanCoils = this->model().getConcreteModelObjects(); - - for (const auto& zoneHVACFourPipeFanCoil : zoneHVACFourPipeFanCoils) { - if (boost::optional coil = zoneHVACFourPipeFanCoil.coolingCoil()) { - if (coil->handle() == this->handle()) { - return zoneHVACFourPipeFanCoil; - } - } - } - - // ZoneHVACUnitVentilator - std::vector zoneHVACUnitVentilators; - - zoneHVACUnitVentilators = this->model().getConcreteModelObjects(); - - for (const auto& zoneHVACUnitVentilator : zoneHVACUnitVentilators) { - if (boost::optional coil = zoneHVACUnitVentilator.coolingCoil()) { - if (coil->handle() == this->handle()) { - return zoneHVACUnitVentilator; - } - } - } - - // ZoneHVAC:WindowAirConditioner not wrapped - return boost::none; } From 95c4727cac8ac93da17c99f6d71ec48892194aa0 Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Mon, 5 May 2025 15:48:26 +0200 Subject: [PATCH 51/58] Adjust FT test after changing return type, and remove the Unitary test (not supported AFAIK) --- .../Test/CoilSystemCoolingWater_GTest.cpp | 444 ++++++++---------- 1 file changed, 198 insertions(+), 246 deletions(-) diff --git a/src/energyplus/Test/CoilSystemCoolingWater_GTest.cpp b/src/energyplus/Test/CoilSystemCoolingWater_GTest.cpp index 85b1838cb40..2e0ce8ae009 100644 --- a/src/energyplus/Test/CoilSystemCoolingWater_GTest.cpp +++ b/src/energyplus/Test/CoilSystemCoolingWater_GTest.cpp @@ -14,6 +14,8 @@ #include "../../model/Schedule_Impl.hpp" #include "../../model/CoilCoolingWater.hpp" #include "../../model/CoilCoolingWater_Impl.hpp" +#include "../../model/CoilSystemCoolingWaterHeatExchangerAssisted.hpp" +#include "../../model/CoilSystemCoolingWaterHeatExchangerAssisted_Impl.hpp" #include "../../model/AirLoopHVAC.hpp" #include "../../model/AirLoopHVACUnitarySystem.hpp" @@ -48,13 +50,106 @@ using namespace openstudio::energyplus; using namespace openstudio::model; using namespace openstudio; -TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWater_Unitary) { +TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWater_WithoutCompanion) { + ForwardTranslator ft; + + Model m; + + CoilSystemCoolingWater coilSystemCoolingWater(m); + auto cc = coilSystemCoolingWater.coolingCoil().cast(); + + coilSystemCoolingWater.setName("My CoilSystemCoolingWater"); + Schedule availabilitySchedule = m.alwaysOnDiscreteSchedule(); + EXPECT_TRUE(coilSystemCoolingWater.setAvailabilitySchedule(availabilitySchedule)); + EXPECT_TRUE(coilSystemCoolingWater.setDehumidificationControlType("CoolReheat")); + EXPECT_TRUE(coilSystemCoolingWater.setRunonSensibleLoad(false)); // Opposite from IDD default + EXPECT_TRUE(coilSystemCoolingWater.setRunonLatentLoad(true)); // Opposite from IDD default + EXPECT_TRUE(coilSystemCoolingWater.setMinimumAirToWaterTemperatureOffset(1.0)); + EXPECT_TRUE(coilSystemCoolingWater.setEconomizerLockout(false)); // Opposite from IDD default + EXPECT_TRUE(coilSystemCoolingWater.setMinimumWaterLoopTemperatureForHeatRecovery(1.2)); + + AirLoopHVAC airLoop(m); + Node supplyOutletNode = airLoop.supplyOutletNode(); + EXPECT_TRUE(coilSystemCoolingWater.addToNode(supplyOutletNode)); + + // They must be connected to a PlantLoop too + PlantLoop chw_p(m); + chw_p.addDemandBranchForComponent(cc); + + const Workspace w = ft.translateModel(m); + + const auto idfCoilSystems = w.getObjectsByType(IddObjectType::CoilSystem_Cooling_Water); + ASSERT_EQ(1u, idfCoilSystems.size()); + const auto& idfCoilSystem = idfCoilSystems.front(); + + WorkspaceObjectVector idfCoils(w.getObjectsByType(IddObjectType::Coil_Cooling_Water)); + ASSERT_EQ(1u, idfCoils.size()); + WorkspaceObject idfCoil(idfCoils[0]); + + // Go from AirLoopHVAC to BranchList to Branch + WorkspaceObjectVector idf_airloops = w.getObjectsByType(IddObjectType::AirLoopHVAC); + ASSERT_EQ(1u, idf_airloops.size()); + + WorkspaceObject& idf_airLoopHVAC = idf_airloops.front(); + WorkspaceObject idf_brlist = idf_airLoopHVAC.getTarget(AirLoopHVACFields::BranchListName).get(); + + // Should have one branch only + ASSERT_EQ(1u, idf_brlist.extensibleGroups().size()); + auto w_eg = idf_brlist.extensibleGroups()[0].cast(); + WorkspaceObject idf_branch = w_eg.getTarget(BranchListExtensibleFields::BranchName).get(); + + // There should be only one equipment on the branch + ASSERT_EQ(1u, idf_branch.extensibleGroups().size()); + auto w_eg2 = idf_branch.extensibleGroups()[0].cast(); + + EXPECT_EQ(w_eg2.getString(BranchExtensibleFields::ComponentInletNodeName).get(), coilSystemCoolingWater.inletModelObject().get().nameString()); + EXPECT_EQ(w_eg2.getString(BranchExtensibleFields::ComponentOutletNodeName).get(), coilSystemCoolingWater.outletModelObject().get().nameString()); + EXPECT_EQ("CoilSystem:Cooling:Water", w_eg2.getString(BranchExtensibleFields::ComponentObjectType).get()); + + EXPECT_EQ(coilSystemCoolingWater.inletModelObject().get().nameString(), + idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::AirInletNodeName).get()); + EXPECT_EQ(coilSystemCoolingWater.outletModelObject().get().nameString(), + idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::AirOutletNodeName).get()); + EXPECT_EQ(availabilitySchedule.nameString(), idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::AvailabilityScheduleName).get()); + EXPECT_EQ("Coil:Cooling:Water", idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::CoolingCoilObjectType).get()); + EXPECT_EQ(coilSystemCoolingWater.coolingCoil().nameString(), idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::CoolingCoilName).get()); + EXPECT_EQ("CoolReheat", idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::DehumidificationControlType).get()); + EXPECT_EQ("No", idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::RunonSensibleLoad).get()); + EXPECT_EQ("Yes", idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::RunonLatentLoad).get()); + EXPECT_EQ(1.0, idfCoilSystem.getDouble(CoilSystem_Cooling_WaterFields::MinimumAirToWaterTemperatureOffset).get()); + EXPECT_EQ("No", idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::EconomizerLockout).get()); + EXPECT_EQ(1.2, idfCoilSystem.getDouble(CoilSystem_Cooling_WaterFields::MinimumWaterLoopTemperatureForHeatRecovery).get()); + EXPECT_TRUE(idfCoilSystem.isEmpty(CoilSystem_Cooling_WaterFields::CompanionCoilUsedForHeatRecovery)); + + EXPECT_EQ(coilSystemCoolingWater.coolingCoil().nameString(), idfCoil.getString(Coil_Cooling_WaterFields::Name).get()); + EXPECT_EQ("Always On Discrete", idfCoil.getString(Coil_Cooling_WaterFields::AvailabilityScheduleName).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignWaterFlowRate).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignAirFlowRate).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignInletWaterTemperature).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignInletAirTemperature).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignInletAirHumidityRatio).get()); + EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignOutletAirHumidityRatio).get()); + EXPECT_EQ(cc.waterInletModelObject().get().nameString(), idfCoil.getString(Coil_Cooling_WaterFields::WaterInletNodeName).get()); + EXPECT_EQ(cc.waterOutletModelObject().get().nameString(), idfCoil.getString(Coil_Cooling_WaterFields::WaterOutletNodeName).get()); + EXPECT_EQ(idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::AirInletNodeName).get(), + idfCoil.getString(Coil_Cooling_WaterFields::AirInletNodeName).get()); + EXPECT_EQ(idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::AirOutletNodeName).get(), + idfCoil.getString(Coil_Cooling_WaterFields::AirOutletNodeName).get()); + EXPECT_EQ("SimpleAnalysis", idfCoil.getString(Coil_Cooling_WaterFields::TypeofAnalysis).get()); + EXPECT_EQ("CrossFlow", idfCoil.getString(Coil_Cooling_WaterFields::HeatExchangerConfiguration).get()); + EXPECT_TRUE(idfCoil.isEmpty(Coil_Cooling_WaterFields::CondensateCollectionWaterStorageTankName)); + EXPECT_TRUE(idfCoil.isEmpty(Coil_Cooling_WaterFields::DesignWaterTemperatureDifference)); + + EXPECT_EQ(0, w.getObjectsByType(IddObjectType::Controller_WaterCoil).size()); +} +TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWater_WithCompanion) { ForwardTranslator ft; Model m; CoilSystemCoolingWater coilSystemCoolingWater(m); + auto cc = coilSystemCoolingWater.coolingCoil().cast(); coilSystemCoolingWater.setName("My CoilSystemCoolingWater"); Schedule availabilitySchedule = m.alwaysOnDiscreteSchedule(); @@ -68,260 +163,117 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWater_Unitary) { CoilCoolingWater companionCoilUsedForHeatRecovery(m); EXPECT_TRUE(coilSystemCoolingWater.setCompanionCoilUsedForHeatRecovery(companionCoilUsedForHeatRecovery)); - // put it inside a Unitary, and put Unitary on an AirLoopHVAC - AirLoopHVACUnitarySystem unitary(m); - EXPECT_FALSE(unitary.setCoolingCoil(coilSystemCoolingWater)); AirLoopHVAC airLoop(m); Node supplyOutletNode = airLoop.supplyOutletNode(); - unitary.addToNode(supplyOutletNode); - ASSERT_TRUE(unitary.inletNode()); - EXPECT_TRUE(unitary.inletNode()->setName("Coil Air Inlet Node")); - ASSERT_TRUE(unitary.outletNode()); - EXPECT_TRUE(unitary.outletNode()->setName("Coil Air Outlet Node")); + ControllerOutdoorAir controller1(m); + AirLoopHVACOutdoorAirSystem oaSystem(m, controller1); + EXPECT_TRUE(oaSystem.addToNode(supplyOutletNode)); + Node oaNode = oaSystem.outboardOANode().get(); + EXPECT_TRUE(coilSystemCoolingWater.addToNode(oaNode)); + Node reliefNode = oaSystem.reliefAirModelObject()->cast(); + EXPECT_TRUE(companionCoilUsedForHeatRecovery.addToNode(reliefNode)); // They must be connected to a PlantLoop too PlantLoop chw_p(m); - chw_p.addDemandBranchForComponent(coilSystemCoolingWater.coolingCoil()); + chw_p.addDemandBranchForComponent(cc); + PipeAdiabatic pipe(m); + Node coolingOutlet = cc.waterOutletModelObject()->cast(); + EXPECT_TRUE(pipe.addToNode(coolingOutlet)); + Node pipeOutlet = pipe.outletModelObject()->cast(); + EXPECT_TRUE(companionCoilUsedForHeatRecovery.addToNode(pipeOutlet)); const Workspace w = ft.translateModel(m); - const auto idfUnitarys = w.getObjectsByType(IddObjectType::AirLoopHVAC_UnitarySystem); - ASSERT_EQ(1u, idfUnitarys.size()); - const auto idfCoilSystems = w.getObjectsByType(IddObjectType::CoilSystem_Cooling_Water); - ASSERT_EQ(0u, idfCoilSystems.size()); -} + ASSERT_EQ(1u, idfCoilSystems.size()); + const auto& idfCoilSystem = idfCoilSystems.front(); + + WorkspaceObjectVector idfCoils(w.getObjectsByType(IddObjectType::Coil_Cooling_Water)); + ASSERT_EQ(2u, idfCoils.size()); + + WorkspaceObjectVector idfControllers(w.getObjectsByType(IddObjectType::Controller_OutdoorAir)); + ASSERT_EQ(1u, idfControllers.size()); + const auto& idfController = idfControllers.front(); + + // Go from AirLoopHVAC to BranchList to Branch + WorkspaceObjectVector idf_airloops = w.getObjectsByType(IddObjectType::AirLoopHVAC); + ASSERT_EQ(1u, idf_airloops.size()); + + WorkspaceObject& idf_airLoopHVAC = idf_airloops.front(); + WorkspaceObject idf_brlist = idf_airLoopHVAC.getTarget(AirLoopHVACFields::BranchListName).get(); + + // Should have one branch only + ASSERT_EQ(1u, idf_brlist.extensibleGroups().size()); + auto w_eg = idf_brlist.extensibleGroups()[0].cast(); + WorkspaceObject idf_branch = w_eg.getTarget(BranchListExtensibleFields::BranchName).get(); + + // There should be only one equipment on the branch + ASSERT_EQ(1u, idf_branch.extensibleGroups().size()); + auto w_eg2 = idf_branch.extensibleGroups()[0].cast(); -TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWater_AirLoopHVAC) { - // without companion - { - ForwardTranslator ft; - - Model m; - - CoilSystemCoolingWater coilSystemCoolingWater(m); - - coilSystemCoolingWater.setName("My CoilSystemCoolingWater"); - Schedule availabilitySchedule = m.alwaysOnDiscreteSchedule(); - EXPECT_TRUE(coilSystemCoolingWater.setAvailabilitySchedule(availabilitySchedule)); - EXPECT_TRUE(coilSystemCoolingWater.setDehumidificationControlType("CoolReheat")); - EXPECT_TRUE(coilSystemCoolingWater.setRunonSensibleLoad(false)); // Opposite from IDD default - EXPECT_TRUE(coilSystemCoolingWater.setRunonLatentLoad(true)); // Opposite from IDD default - EXPECT_TRUE(coilSystemCoolingWater.setMinimumAirToWaterTemperatureOffset(1.0)); - EXPECT_TRUE(coilSystemCoolingWater.setEconomizerLockout(false)); // Opposite from IDD default - EXPECT_TRUE(coilSystemCoolingWater.setMinimumWaterLoopTemperatureForHeatRecovery(1.2)); - - AirLoopHVAC airLoop(m); - Node supplyOutletNode = airLoop.supplyOutletNode(); - EXPECT_TRUE(coilSystemCoolingWater.addToNode(supplyOutletNode)); - - // They must be connected to a PlantLoop too - PlantLoop chw_p(m); - chw_p.addDemandBranchForComponent(coilSystemCoolingWater.coolingCoil()); - - const Workspace w = ft.translateModel(m); - - const auto idfCoilSystems = w.getObjectsByType(IddObjectType::CoilSystem_Cooling_Water); - ASSERT_EQ(1u, idfCoilSystems.size()); - const auto& idfCoilSystem = idfCoilSystems.front(); - - WorkspaceObjectVector idfCoils(w.getObjectsByType(IddObjectType::Coil_Cooling_Water)); - ASSERT_EQ(1u, idfCoils.size()); - WorkspaceObject idfCoil(idfCoils[0]); - - // Go from AirLoopHVAC to BranchList to Branch - WorkspaceObjectVector idf_airloops = w.getObjectsByType(IddObjectType::AirLoopHVAC); - ASSERT_EQ(1u, idf_airloops.size()); - - WorkspaceObject& idf_airLoopHVAC = idf_airloops.front(); - WorkspaceObject idf_brlist = idf_airLoopHVAC.getTarget(AirLoopHVACFields::BranchListName).get(); - - // Should have one branch only - ASSERT_EQ(1u, idf_brlist.extensibleGroups().size()); - auto w_eg = idf_brlist.extensibleGroups()[0].cast(); - WorkspaceObject idf_branch = w_eg.getTarget(BranchListExtensibleFields::BranchName).get(); - - // There should be only one equipment on the branch - ASSERT_EQ(1u, idf_branch.extensibleGroups().size()); - auto w_eg2 = idf_branch.extensibleGroups()[0].cast(); - - EXPECT_EQ(w_eg2.getString(BranchExtensibleFields::ComponentInletNodeName).get(), coilSystemCoolingWater.inletModelObject().get().nameString()); - EXPECT_EQ(w_eg2.getString(BranchExtensibleFields::ComponentOutletNodeName).get(), coilSystemCoolingWater.outletModelObject().get().nameString()); - EXPECT_EQ("CoilSystem:Cooling:Water", w_eg2.getString(BranchExtensibleFields::ComponentObjectType).get()); - - EXPECT_EQ(coilSystemCoolingWater.inletModelObject().get().nameString(), - idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::AirInletNodeName).get()); - EXPECT_EQ(coilSystemCoolingWater.outletModelObject().get().nameString(), - idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::AirOutletNodeName).get()); - EXPECT_EQ(availabilitySchedule.nameString(), idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::AvailabilityScheduleName).get()); - EXPECT_EQ("Coil:Cooling:Water", idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::CoolingCoilObjectType).get()); - EXPECT_EQ(coilSystemCoolingWater.coolingCoil().nameString(), idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::CoolingCoilName).get()); - EXPECT_EQ("CoolReheat", idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::DehumidificationControlType).get()); - EXPECT_EQ("No", idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::RunonSensibleLoad).get()); - EXPECT_EQ("Yes", idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::RunonLatentLoad).get()); - EXPECT_EQ(1.0, idfCoilSystem.getDouble(CoilSystem_Cooling_WaterFields::MinimumAirToWaterTemperatureOffset).get()); - EXPECT_EQ("No", idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::EconomizerLockout).get()); - EXPECT_EQ(1.2, idfCoilSystem.getDouble(CoilSystem_Cooling_WaterFields::MinimumWaterLoopTemperatureForHeatRecovery).get()); - EXPECT_TRUE(idfCoilSystem.isEmpty(CoilSystem_Cooling_WaterFields::CompanionCoilUsedForHeatRecovery)); - - EXPECT_EQ(coilSystemCoolingWater.coolingCoil().nameString(), idfCoil.getString(Coil_Cooling_WaterFields::Name).get()); - EXPECT_EQ("Always On Discrete", idfCoil.getString(Coil_Cooling_WaterFields::AvailabilityScheduleName).get()); - EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignWaterFlowRate).get()); - EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignAirFlowRate).get()); - EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignInletWaterTemperature).get()); - EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignInletAirTemperature).get()); - EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignInletAirHumidityRatio).get()); - EXPECT_EQ("Autosize", idfCoil.getString(Coil_Cooling_WaterFields::DesignOutletAirHumidityRatio).get()); - EXPECT_EQ(coilSystemCoolingWater.coolingCoil().waterInletModelObject().get().nameString(), - idfCoil.getString(Coil_Cooling_WaterFields::WaterInletNodeName).get()); - EXPECT_EQ(coilSystemCoolingWater.coolingCoil().waterOutletModelObject().get().nameString(), - idfCoil.getString(Coil_Cooling_WaterFields::WaterOutletNodeName).get()); - EXPECT_EQ(idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::AirInletNodeName).get(), - idfCoil.getString(Coil_Cooling_WaterFields::AirInletNodeName).get()); - EXPECT_EQ(idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::AirOutletNodeName).get(), - idfCoil.getString(Coil_Cooling_WaterFields::AirOutletNodeName).get()); - EXPECT_EQ("SimpleAnalysis", idfCoil.getString(Coil_Cooling_WaterFields::TypeofAnalysis).get()); - EXPECT_EQ("CrossFlow", idfCoil.getString(Coil_Cooling_WaterFields::HeatExchangerConfiguration).get()); - EXPECT_TRUE(idfCoil.isEmpty(Coil_Cooling_WaterFields::CondensateCollectionWaterStorageTankName)); - EXPECT_TRUE(idfCoil.isEmpty(Coil_Cooling_WaterFields::DesignWaterTemperatureDifference)); - - EXPECT_EQ(0, w.getObjectsByType(IddObjectType::Controller_WaterCoil).size()); - } - - // with companion - { - ForwardTranslator ft; - - Model m; - - CoilSystemCoolingWater coilSystemCoolingWater(m); - - coilSystemCoolingWater.setName("My CoilSystemCoolingWater"); - Schedule availabilitySchedule = m.alwaysOnDiscreteSchedule(); - EXPECT_TRUE(coilSystemCoolingWater.setAvailabilitySchedule(availabilitySchedule)); - EXPECT_TRUE(coilSystemCoolingWater.setDehumidificationControlType("CoolReheat")); - EXPECT_TRUE(coilSystemCoolingWater.setRunonSensibleLoad(false)); // Opposite from IDD default - EXPECT_TRUE(coilSystemCoolingWater.setRunonLatentLoad(true)); // Opposite from IDD default - EXPECT_TRUE(coilSystemCoolingWater.setMinimumAirToWaterTemperatureOffset(1.0)); - EXPECT_TRUE(coilSystemCoolingWater.setEconomizerLockout(false)); // Opposite from IDD default - EXPECT_TRUE(coilSystemCoolingWater.setMinimumWaterLoopTemperatureForHeatRecovery(1.2)); - CoilCoolingWater companionCoilUsedForHeatRecovery(m); - EXPECT_TRUE(coilSystemCoolingWater.setCompanionCoilUsedForHeatRecovery(companionCoilUsedForHeatRecovery)); - - AirLoopHVAC airLoop(m); - Node supplyOutletNode = airLoop.supplyOutletNode(); - ControllerOutdoorAir controller1(m); - AirLoopHVACOutdoorAirSystem oaSystem(m, controller1); - EXPECT_TRUE(oaSystem.addToNode(supplyOutletNode)); - Node oaNode = oaSystem.outboardOANode().get(); - EXPECT_TRUE(coilSystemCoolingWater.addToNode(oaNode)); - Node reliefNode = oaSystem.reliefAirModelObject()->cast(); - EXPECT_TRUE(companionCoilUsedForHeatRecovery.addToNode(reliefNode)); - - // They must be connected to a PlantLoop too - PlantLoop chw_p(m); - chw_p.addDemandBranchForComponent(coilSystemCoolingWater.coolingCoil()); - PipeAdiabatic pipe(m); - Node coolingOutlet = coilSystemCoolingWater.coolingCoil().waterOutletModelObject()->cast(); - EXPECT_TRUE(pipe.addToNode(coolingOutlet)); - Node pipeOutlet = pipe.outletModelObject()->cast(); - EXPECT_TRUE(companionCoilUsedForHeatRecovery.addToNode(pipeOutlet)); - - const Workspace w = ft.translateModel(m); - - const auto idfCoilSystems = w.getObjectsByType(IddObjectType::CoilSystem_Cooling_Water); - ASSERT_EQ(1u, idfCoilSystems.size()); - const auto& idfCoilSystem = idfCoilSystems.front(); - - WorkspaceObjectVector idfCoils(w.getObjectsByType(IddObjectType::Coil_Cooling_Water)); - ASSERT_EQ(2u, idfCoils.size()); - - WorkspaceObjectVector idfControllers(w.getObjectsByType(IddObjectType::Controller_OutdoorAir)); - ASSERT_EQ(1u, idfControllers.size()); - const auto& idfController = idfControllers.front(); - - // Go from AirLoopHVAC to BranchList to Branch - WorkspaceObjectVector idf_airloops = w.getObjectsByType(IddObjectType::AirLoopHVAC); - ASSERT_EQ(1u, idf_airloops.size()); - - WorkspaceObject& idf_airLoopHVAC = idf_airloops.front(); - WorkspaceObject idf_brlist = idf_airLoopHVAC.getTarget(AirLoopHVACFields::BranchListName).get(); - - // Should have one branch only - ASSERT_EQ(1u, idf_brlist.extensibleGroups().size()); - auto w_eg = idf_brlist.extensibleGroups()[0].cast(); - WorkspaceObject idf_branch = w_eg.getTarget(BranchListExtensibleFields::BranchName).get(); - - // There should be only one equipment on the branch - ASSERT_EQ(1u, idf_branch.extensibleGroups().size()); - auto w_eg2 = idf_branch.extensibleGroups()[0].cast(); - - /* EXPECT_EQ(w_eg2.getString(BranchExtensibleFields::ComponentInletNodeName).get(), coilSystemCoolingWater.inletModelObject().get().nameString()); + /* EXPECT_EQ(w_eg2.getString(BranchExtensibleFields::ComponentInletNodeName).get(), coilSystemCoolingWater.inletModelObject().get().nameString()); EXPECT_EQ(w_eg2.getString(BranchExtensibleFields::ComponentOutletNodeName).get(), coilSystemCoolingWater.outletModelObject().get().nameString()); */ - EXPECT_EQ("AirLoopHVAC:OutdoorAirSystem", w_eg2.getString(BranchExtensibleFields::ComponentObjectType).get()); - - EXPECT_EQ(coilSystemCoolingWater.inletModelObject().get().nameString(), - idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::AirInletNodeName).get()); - EXPECT_EQ(coilSystemCoolingWater.outletModelObject().get().nameString(), - idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::AirOutletNodeName).get()); - EXPECT_EQ(availabilitySchedule.nameString(), idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::AvailabilityScheduleName).get()); - EXPECT_EQ("Coil:Cooling:Water", idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::CoolingCoilObjectType).get()); - EXPECT_EQ(coilSystemCoolingWater.coolingCoil().nameString(), idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::CoolingCoilName).get()); - EXPECT_EQ("CoolReheat", idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::DehumidificationControlType).get()); - EXPECT_EQ("No", idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::RunonSensibleLoad).get()); - EXPECT_EQ("Yes", idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::RunonLatentLoad).get()); - EXPECT_EQ(1.0, idfCoilSystem.getDouble(CoilSystem_Cooling_WaterFields::MinimumAirToWaterTemperatureOffset).get()); - EXPECT_EQ("No", idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::EconomizerLockout).get()); - EXPECT_EQ(1.2, idfCoilSystem.getDouble(CoilSystem_Cooling_WaterFields::MinimumWaterLoopTemperatureForHeatRecovery).get()); - EXPECT_EQ(companionCoilUsedForHeatRecovery.nameString(), - idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::CompanionCoilUsedForHeatRecovery).get()); - - WorkspaceObject idf_coolingCoil = idfCoilSystem.getTarget(CoilSystem_Cooling_WaterFields::CoolingCoilName).get(); - WorkspaceObject idf_companionCoil = idfCoilSystem.getTarget(CoilSystem_Cooling_WaterFields::CompanionCoilUsedForHeatRecovery).get(); - - EXPECT_EQ(coilSystemCoolingWater.coolingCoil().nameString(), idf_coolingCoil.getString(Coil_Cooling_WaterFields::Name).get()); - EXPECT_EQ("Always On Discrete", idf_coolingCoil.getString(Coil_Cooling_WaterFields::AvailabilityScheduleName).get()); - EXPECT_EQ("Autosize", idf_coolingCoil.getString(Coil_Cooling_WaterFields::DesignWaterFlowRate).get()); - EXPECT_EQ("Autosize", idf_coolingCoil.getString(Coil_Cooling_WaterFields::DesignAirFlowRate).get()); - EXPECT_EQ("Autosize", idf_coolingCoil.getString(Coil_Cooling_WaterFields::DesignInletWaterTemperature).get()); - EXPECT_EQ("Autosize", idf_coolingCoil.getString(Coil_Cooling_WaterFields::DesignInletAirTemperature).get()); - EXPECT_EQ("Autosize", idf_coolingCoil.getString(Coil_Cooling_WaterFields::DesignInletAirHumidityRatio).get()); - EXPECT_EQ("Autosize", idf_coolingCoil.getString(Coil_Cooling_WaterFields::DesignOutletAirHumidityRatio).get()); - EXPECT_EQ(coilSystemCoolingWater.coolingCoil().waterInletModelObject().get().nameString(), - idf_coolingCoil.getString(Coil_Cooling_WaterFields::WaterInletNodeName).get()); - EXPECT_EQ(coilSystemCoolingWater.coolingCoil().waterOutletModelObject().get().nameString(), - idf_coolingCoil.getString(Coil_Cooling_WaterFields::WaterOutletNodeName).get()); - EXPECT_EQ(idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::AirInletNodeName).get(), - idf_coolingCoil.getString(Coil_Cooling_WaterFields::AirInletNodeName).get()); - EXPECT_EQ(idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::AirOutletNodeName).get(), - idf_coolingCoil.getString(Coil_Cooling_WaterFields::AirOutletNodeName).get()); - EXPECT_EQ("SimpleAnalysis", idf_coolingCoil.getString(Coil_Cooling_WaterFields::TypeofAnalysis).get()); - EXPECT_EQ("CrossFlow", idf_coolingCoil.getString(Coil_Cooling_WaterFields::HeatExchangerConfiguration).get()); - EXPECT_TRUE(idf_coolingCoil.isEmpty(Coil_Cooling_WaterFields::CondensateCollectionWaterStorageTankName)); - EXPECT_TRUE(idf_coolingCoil.isEmpty(Coil_Cooling_WaterFields::DesignWaterTemperatureDifference)); - - EXPECT_EQ(coilSystemCoolingWater.companionCoilUsedForHeatRecovery().get().nameString(), - idf_companionCoil.getString(Coil_Cooling_WaterFields::Name).get()); - EXPECT_EQ("Always On Discrete", idf_companionCoil.getString(Coil_Cooling_WaterFields::AvailabilityScheduleName).get()); - EXPECT_EQ("Autosize", idf_companionCoil.getString(Coil_Cooling_WaterFields::DesignWaterFlowRate).get()); - EXPECT_EQ("Autosize", idf_companionCoil.getString(Coil_Cooling_WaterFields::DesignAirFlowRate).get()); - EXPECT_EQ("Autosize", idf_companionCoil.getString(Coil_Cooling_WaterFields::DesignInletWaterTemperature).get()); - EXPECT_EQ("Autosize", idf_companionCoil.getString(Coil_Cooling_WaterFields::DesignInletAirTemperature).get()); - EXPECT_EQ("Autosize", idf_companionCoil.getString(Coil_Cooling_WaterFields::DesignInletAirHumidityRatio).get()); - EXPECT_EQ("Autosize", idf_companionCoil.getString(Coil_Cooling_WaterFields::DesignOutletAirHumidityRatio).get()); - EXPECT_EQ(coilSystemCoolingWater.companionCoilUsedForHeatRecovery().get().waterInletModelObject().get().nameString(), - idf_companionCoil.getString(Coil_Cooling_WaterFields::WaterInletNodeName).get()); - EXPECT_EQ(coilSystemCoolingWater.companionCoilUsedForHeatRecovery().get().waterOutletModelObject().get().nameString(), - idf_companionCoil.getString(Coil_Cooling_WaterFields::WaterOutletNodeName).get()); - EXPECT_EQ(idfController.getString(Controller_OutdoorAirFields::ReliefAirOutletNodeName).get(), - idf_companionCoil.getString(Coil_Cooling_WaterFields::AirInletNodeName).get()); - EXPECT_EQ(coilSystemCoolingWater.companionCoilUsedForHeatRecovery().get().nameString() + " Exhaust Outlet Node", - idf_companionCoil.getString(Coil_Cooling_WaterFields::AirOutletNodeName).get()); // FIXME - EXPECT_EQ("SimpleAnalysis", idf_companionCoil.getString(Coil_Cooling_WaterFields::TypeofAnalysis).get()); - EXPECT_EQ("CrossFlow", idf_companionCoil.getString(Coil_Cooling_WaterFields::HeatExchangerConfiguration).get()); - EXPECT_TRUE(idf_companionCoil.isEmpty(Coil_Cooling_WaterFields::CondensateCollectionWaterStorageTankName)); - EXPECT_TRUE(idf_companionCoil.isEmpty(Coil_Cooling_WaterFields::DesignWaterTemperatureDifference)); - - EXPECT_EQ(0, w.getObjectsByType(IddObjectType::Controller_WaterCoil).size()); - } + EXPECT_EQ("AirLoopHVAC:OutdoorAirSystem", w_eg2.getString(BranchExtensibleFields::ComponentObjectType).get()); + + EXPECT_EQ(coilSystemCoolingWater.inletModelObject().get().nameString(), + idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::AirInletNodeName).get()); + EXPECT_EQ(coilSystemCoolingWater.outletModelObject().get().nameString(), + idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::AirOutletNodeName).get()); + EXPECT_EQ(availabilitySchedule.nameString(), idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::AvailabilityScheduleName).get()); + EXPECT_EQ("Coil:Cooling:Water", idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::CoolingCoilObjectType).get()); + EXPECT_EQ(coilSystemCoolingWater.coolingCoil().nameString(), idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::CoolingCoilName).get()); + EXPECT_EQ("CoolReheat", idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::DehumidificationControlType).get()); + EXPECT_EQ("No", idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::RunonSensibleLoad).get()); + EXPECT_EQ("Yes", idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::RunonLatentLoad).get()); + EXPECT_EQ(1.0, idfCoilSystem.getDouble(CoilSystem_Cooling_WaterFields::MinimumAirToWaterTemperatureOffset).get()); + EXPECT_EQ("No", idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::EconomizerLockout).get()); + EXPECT_EQ(1.2, idfCoilSystem.getDouble(CoilSystem_Cooling_WaterFields::MinimumWaterLoopTemperatureForHeatRecovery).get()); + EXPECT_EQ(companionCoilUsedForHeatRecovery.nameString(), + idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::CompanionCoilUsedForHeatRecovery).get()); + + WorkspaceObject idf_coolingCoil = idfCoilSystem.getTarget(CoilSystem_Cooling_WaterFields::CoolingCoilName).get(); + WorkspaceObject idf_companionCoil = idfCoilSystem.getTarget(CoilSystem_Cooling_WaterFields::CompanionCoilUsedForHeatRecovery).get(); + + EXPECT_EQ(coilSystemCoolingWater.coolingCoil().nameString(), idf_coolingCoil.getString(Coil_Cooling_WaterFields::Name).get()); + EXPECT_EQ("Always On Discrete", idf_coolingCoil.getString(Coil_Cooling_WaterFields::AvailabilityScheduleName).get()); + EXPECT_EQ("Autosize", idf_coolingCoil.getString(Coil_Cooling_WaterFields::DesignWaterFlowRate).get()); + EXPECT_EQ("Autosize", idf_coolingCoil.getString(Coil_Cooling_WaterFields::DesignAirFlowRate).get()); + EXPECT_EQ("Autosize", idf_coolingCoil.getString(Coil_Cooling_WaterFields::DesignInletWaterTemperature).get()); + EXPECT_EQ("Autosize", idf_coolingCoil.getString(Coil_Cooling_WaterFields::DesignInletAirTemperature).get()); + EXPECT_EQ("Autosize", idf_coolingCoil.getString(Coil_Cooling_WaterFields::DesignInletAirHumidityRatio).get()); + EXPECT_EQ("Autosize", idf_coolingCoil.getString(Coil_Cooling_WaterFields::DesignOutletAirHumidityRatio).get()); + EXPECT_EQ(cc.waterInletModelObject().get().nameString(), idf_coolingCoil.getString(Coil_Cooling_WaterFields::WaterInletNodeName).get()); + EXPECT_EQ(cc.waterOutletModelObject().get().nameString(), idf_coolingCoil.getString(Coil_Cooling_WaterFields::WaterOutletNodeName).get()); + EXPECT_EQ(idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::AirInletNodeName).get(), + idf_coolingCoil.getString(Coil_Cooling_WaterFields::AirInletNodeName).get()); + EXPECT_EQ(idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::AirOutletNodeName).get(), + idf_coolingCoil.getString(Coil_Cooling_WaterFields::AirOutletNodeName).get()); + EXPECT_EQ("SimpleAnalysis", idf_coolingCoil.getString(Coil_Cooling_WaterFields::TypeofAnalysis).get()); + EXPECT_EQ("CrossFlow", idf_coolingCoil.getString(Coil_Cooling_WaterFields::HeatExchangerConfiguration).get()); + EXPECT_TRUE(idf_coolingCoil.isEmpty(Coil_Cooling_WaterFields::CondensateCollectionWaterStorageTankName)); + EXPECT_TRUE(idf_coolingCoil.isEmpty(Coil_Cooling_WaterFields::DesignWaterTemperatureDifference)); + + EXPECT_EQ(coilSystemCoolingWater.companionCoilUsedForHeatRecovery().get().nameString(), + idf_companionCoil.getString(Coil_Cooling_WaterFields::Name).get()); + EXPECT_EQ("Always On Discrete", idf_companionCoil.getString(Coil_Cooling_WaterFields::AvailabilityScheduleName).get()); + EXPECT_EQ("Autosize", idf_companionCoil.getString(Coil_Cooling_WaterFields::DesignWaterFlowRate).get()); + EXPECT_EQ("Autosize", idf_companionCoil.getString(Coil_Cooling_WaterFields::DesignAirFlowRate).get()); + EXPECT_EQ("Autosize", idf_companionCoil.getString(Coil_Cooling_WaterFields::DesignInletWaterTemperature).get()); + EXPECT_EQ("Autosize", idf_companionCoil.getString(Coil_Cooling_WaterFields::DesignInletAirTemperature).get()); + EXPECT_EQ("Autosize", idf_companionCoil.getString(Coil_Cooling_WaterFields::DesignInletAirHumidityRatio).get()); + EXPECT_EQ("Autosize", idf_companionCoil.getString(Coil_Cooling_WaterFields::DesignOutletAirHumidityRatio).get()); + EXPECT_EQ(companionCoilUsedForHeatRecovery.waterInletModelObject().get().nameString(), + idf_companionCoil.getString(Coil_Cooling_WaterFields::WaterInletNodeName).get()); + EXPECT_EQ(companionCoilUsedForHeatRecovery.waterOutletModelObject().get().nameString(), + idf_companionCoil.getString(Coil_Cooling_WaterFields::WaterOutletNodeName).get()); + EXPECT_EQ(idfController.getString(Controller_OutdoorAirFields::ReliefAirOutletNodeName).get(), + idf_companionCoil.getString(Coil_Cooling_WaterFields::AirInletNodeName).get()); + EXPECT_EQ(coilSystemCoolingWater.companionCoilUsedForHeatRecovery().get().nameString() + " Exhaust Outlet Node", + idf_companionCoil.getString(Coil_Cooling_WaterFields::AirOutletNodeName).get()); // FIXME + EXPECT_EQ("SimpleAnalysis", idf_companionCoil.getString(Coil_Cooling_WaterFields::TypeofAnalysis).get()); + EXPECT_EQ("CrossFlow", idf_companionCoil.getString(Coil_Cooling_WaterFields::HeatExchangerConfiguration).get()); + EXPECT_TRUE(idf_companionCoil.isEmpty(Coil_Cooling_WaterFields::CondensateCollectionWaterStorageTankName)); + EXPECT_TRUE(idf_companionCoil.isEmpty(Coil_Cooling_WaterFields::DesignWaterTemperatureDifference)); + + EXPECT_EQ(0, w.getObjectsByType(IddObjectType::Controller_WaterCoil).size()); } From 3d6d14531ac661797387a9b657a9961e3879241a Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Mon, 5 May 2025 15:52:52 +0200 Subject: [PATCH 52/58] Remove unneeded bit in ForwardTranslateAirLoopHVAC --- .../ForwardTranslator/ForwardTranslateAirLoopHVAC.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/energyplus/ForwardTranslator/ForwardTranslateAirLoopHVAC.cpp b/src/energyplus/ForwardTranslator/ForwardTranslateAirLoopHVAC.cpp index f43861de00f..e40d2ebf483 100644 --- a/src/energyplus/ForwardTranslator/ForwardTranslateAirLoopHVAC.cpp +++ b/src/energyplus/ForwardTranslator/ForwardTranslateAirLoopHVAC.cpp @@ -277,13 +277,6 @@ namespace energyplus { controller = supplyComponent.cast().controllerWaterCoil(); break; } - case openstudio::IddObjectType::OS_CoilSystem_Cooling_Water: { - auto coolingCoil = supplyComponent.cast().coolingCoil(); - if (auto coilCoolingWater = coolingCoil.optionalCast()) { - controller = coilCoolingWater->controllerWaterCoil(); - } - break; - } case openstudio::IddObjectType::OS_CoilSystem_Cooling_Water_HeatExchangerAssisted: { auto coolingCoil = supplyComponent.cast().coolingCoil(); if (auto coilCoolingWater = coolingCoil.optionalCast()) { @@ -291,6 +284,10 @@ namespace energyplus { } break; } + // case openstudio::IddObjectType::OS_CoilSystem_Cooling_Water: { + // // No-op: this has its own controller + // break; + // } default: { break; } From 868633ab378788f7205c73dda7d0432d5c593841 Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Mon, 5 May 2025 16:20:47 +0200 Subject: [PATCH 53/58] Add a private assignEnergyPlusIDDDefaults method to avoid repeating code (and getting them out of sync) in both ctors --- src/model/CoilSystemCoolingWater.cpp | 36 +++++++++++----------------- src/model/CoilSystemCoolingWater.hpp | 2 ++ 2 files changed, 16 insertions(+), 22 deletions(-) diff --git a/src/model/CoilSystemCoolingWater.cpp b/src/model/CoilSystemCoolingWater.cpp index ad77a88ba47..6b85a453e67 100644 --- a/src/model/CoilSystemCoolingWater.cpp +++ b/src/model/CoilSystemCoolingWater.cpp @@ -298,17 +298,12 @@ namespace model { } // namespace detail - CoilSystemCoolingWater::CoilSystemCoolingWater(const Model& model) : StraightComponent(CoilSystemCoolingWater::iddObjectType(), model) { - OS_ASSERT(getImpl()); - + void CoilSystemCoolingWater::assignEnergyPlusIDDDefaults() { bool ok = true; - auto alwaysOn = model.alwaysOnDiscreteSchedule(); + auto alwaysOn = model().alwaysOnDiscreteSchedule(); ok = setAvailabilitySchedule(alwaysOn); OS_ASSERT(ok); - CoilCoolingWater coolingCoil(model); - ok = setCoolingCoil(coolingCoil); - OS_ASSERT(ok); ok = setDehumidificationControlType("None"); OS_ASSERT(ok); ok = setRunonSensibleLoad(true); @@ -323,6 +318,17 @@ namespace model { OS_ASSERT(ok); } + CoilSystemCoolingWater::CoilSystemCoolingWater(const Model& model) : StraightComponent(CoilSystemCoolingWater::iddObjectType(), model) { + OS_ASSERT(getImpl()); + + CoilCoolingWater coolingCoil(model); + coolingCoil.setName(name().get() + " Cooling Coil"); + bool ok = setCoolingCoil(coolingCoil); + OS_ASSERT(ok); + + assignEnergyPlusIDDDefaults(); + } + CoilSystemCoolingWater::CoilSystemCoolingWater(const Model& model, const HVACComponent& coolingCoil) : StraightComponent(CoilSystemCoolingWater::iddObjectType(), model) { OS_ASSERT(getImpl()); @@ -333,22 +339,8 @@ namespace model { remove(); LOG_AND_THROW("Unable to set " << briefDescription() << "'s Cooling Coil " << coolingCoil.briefDescription() << "."); } - auto alwaysOn = model.alwaysOnDiscreteSchedule(); - ok = setAvailabilitySchedule(alwaysOn); - OS_ASSERT(ok); - ok = setDehumidificationControlType("None"); - OS_ASSERT(ok); - ok = setRunonSensibleLoad(true); - OS_ASSERT(ok); - ok = setRunonLatentLoad(false); - OS_ASSERT(ok); - ok = setMinimumAirToWaterTemperatureOffset(0.0); - OS_ASSERT(ok); - ok = setEconomizerLockout(true); - OS_ASSERT(ok); - ok = setMinimumWaterLoopTemperatureForHeatRecovery(0.0); - OS_ASSERT(ok); + assignEnergyPlusIDDDefaults(); } IddObjectType CoilSystemCoolingWater::iddObjectType() { diff --git a/src/model/CoilSystemCoolingWater.hpp b/src/model/CoilSystemCoolingWater.hpp index 2d2b29ce9df..dcc2cebd742 100644 --- a/src/model/CoilSystemCoolingWater.hpp +++ b/src/model/CoilSystemCoolingWater.hpp @@ -111,6 +111,8 @@ namespace model { /// @endcond private: REGISTER_LOGGER("openstudio.model.CoilSystemCoolingWater"); + + void assignEnergyPlusIDDDefaults(); }; /** \relates CoilSystemCoolingWater*/ From 64dd179bf65f886581920ecce1facd139a5778fc Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Mon, 5 May 2025 18:04:40 +0200 Subject: [PATCH 54/58] Adjust FT Test: name the nodes and co, and test the relief node that has a FIXME (it fails) /home/julien/Software/Others/OpenStudio/src/energyplus/Test/CoilSystemCoolingWater_GTest.cpp:297: Failure Expected equality of these values: "Relief Node" idf_companionCoil.getString(Coil_Cooling_WaterFields::AirOutletNodeName).get() Which is: "CompanionCoilUsedForHeatRecovery Exhaust Outlet Node" --- .../Test/CoilSystemCoolingWater_GTest.cpp | 32 +++++++++++++++++-- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/src/energyplus/Test/CoilSystemCoolingWater_GTest.cpp b/src/energyplus/Test/CoilSystemCoolingWater_GTest.cpp index 2e0ce8ae009..d66716170aa 100644 --- a/src/energyplus/Test/CoilSystemCoolingWater_GTest.cpp +++ b/src/energyplus/Test/CoilSystemCoolingWater_GTest.cpp @@ -161,6 +161,7 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWater_WithCompanion EXPECT_TRUE(coilSystemCoolingWater.setEconomizerLockout(false)); // Opposite from IDD default EXPECT_TRUE(coilSystemCoolingWater.setMinimumWaterLoopTemperatureForHeatRecovery(1.2)); CoilCoolingWater companionCoilUsedForHeatRecovery(m); + companionCoilUsedForHeatRecovery.setName("CompanionCoilUsedForHeatRecovery"); EXPECT_TRUE(coilSystemCoolingWater.setCompanionCoilUsedForHeatRecovery(companionCoilUsedForHeatRecovery)); AirLoopHVAC airLoop(m); @@ -170,9 +171,17 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWater_WithCompanion EXPECT_TRUE(oaSystem.addToNode(supplyOutletNode)); Node oaNode = oaSystem.outboardOANode().get(); EXPECT_TRUE(coilSystemCoolingWater.addToNode(oaNode)); - Node reliefNode = oaSystem.reliefAirModelObject()->cast(); + Node reliefNode = oaSystem.outboardReliefNode().get(); EXPECT_TRUE(companionCoilUsedForHeatRecovery.addToNode(reliefNode)); + oaNode.setName("Outdoor Air Inlet Node"); + reliefNode.setName("Relief Node"); + oaSystem.reliefAirModelObject()->setName("Return to OA System Node"); + oaSystem.outdoorAirModelObject()->setName("OA System Outlet to Mixed Node"); + airLoop.mixedAirNode()->setName("Mixed Air Node"); + airLoop.supplyInletNode().setName("Supply Inlet Node"); + airLoop.supplyOutletNode().setName("Supply Outlet Node"); + // They must be connected to a PlantLoop too PlantLoop chw_p(m); chw_p.addDemandBranchForComponent(cc); @@ -182,6 +191,11 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWater_WithCompanion Node pipeOutlet = pipe.outletModelObject()->cast(); EXPECT_TRUE(companionCoilUsedForHeatRecovery.addToNode(pipeOutlet)); + cc.waterInletModelObject()->setName("Cooling Coil Water Inlet Node"); + cc.waterOutletModelObject()->setName("Cooling Coil Water Outlet to Pipe Inlet Node"); + pipe.outletModelObject()->setName("Pipe Outlet to Companion Coil Water Inlet Node"); + companionCoilUsedForHeatRecovery.waterOutletModelObject()->setName("Companion Coil Water Outlet Node"); + const Workspace w = ft.translateModel(m); const auto idfCoilSystems = w.getObjectsByType(IddObjectType::CoilSystem_Cooling_Water); @@ -242,12 +256,19 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWater_WithCompanion EXPECT_EQ("Autosize", idf_coolingCoil.getString(Coil_Cooling_WaterFields::DesignInletAirTemperature).get()); EXPECT_EQ("Autosize", idf_coolingCoil.getString(Coil_Cooling_WaterFields::DesignInletAirHumidityRatio).get()); EXPECT_EQ("Autosize", idf_coolingCoil.getString(Coil_Cooling_WaterFields::DesignOutletAirHumidityRatio).get()); + EXPECT_EQ(cc.waterInletModelObject().get().nameString(), idf_coolingCoil.getString(Coil_Cooling_WaterFields::WaterInletNodeName).get()); + EXPECT_EQ("Cooling Coil Water Inlet Node", idf_coolingCoil.getString(Coil_Cooling_WaterFields::WaterInletNodeName).get()); EXPECT_EQ(cc.waterOutletModelObject().get().nameString(), idf_coolingCoil.getString(Coil_Cooling_WaterFields::WaterOutletNodeName).get()); + EXPECT_EQ("Cooling Coil Water Outlet to Pipe Inlet Node", idf_coolingCoil.getString(Coil_Cooling_WaterFields::WaterOutletNodeName).get()); EXPECT_EQ(idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::AirInletNodeName).get(), idf_coolingCoil.getString(Coil_Cooling_WaterFields::AirInletNodeName).get()); + + EXPECT_EQ("Outdoor Air Inlet Node", idf_coolingCoil.getString(Coil_Cooling_WaterFields::AirInletNodeName).get()); EXPECT_EQ(idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::AirOutletNodeName).get(), idf_coolingCoil.getString(Coil_Cooling_WaterFields::AirOutletNodeName).get()); + EXPECT_EQ("OA System Outlet to Mixed Node", idf_coolingCoil.getString(Coil_Cooling_WaterFields::AirOutletNodeName).get()); + EXPECT_EQ("SimpleAnalysis", idf_coolingCoil.getString(Coil_Cooling_WaterFields::TypeofAnalysis).get()); EXPECT_EQ("CrossFlow", idf_coolingCoil.getString(Coil_Cooling_WaterFields::HeatExchangerConfiguration).get()); EXPECT_TRUE(idf_coolingCoil.isEmpty(Coil_Cooling_WaterFields::CondensateCollectionWaterStorageTankName)); @@ -262,14 +283,19 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWater_WithCompanion EXPECT_EQ("Autosize", idf_companionCoil.getString(Coil_Cooling_WaterFields::DesignInletAirTemperature).get()); EXPECT_EQ("Autosize", idf_companionCoil.getString(Coil_Cooling_WaterFields::DesignInletAirHumidityRatio).get()); EXPECT_EQ("Autosize", idf_companionCoil.getString(Coil_Cooling_WaterFields::DesignOutletAirHumidityRatio).get()); + EXPECT_EQ(companionCoilUsedForHeatRecovery.waterInletModelObject().get().nameString(), idf_companionCoil.getString(Coil_Cooling_WaterFields::WaterInletNodeName).get()); + EXPECT_EQ("Companion Coil Water Outlet Node", idf_companionCoil.getString(Coil_Cooling_WaterFields::WaterOutletNodeName).get()); EXPECT_EQ(companionCoilUsedForHeatRecovery.waterOutletModelObject().get().nameString(), idf_companionCoil.getString(Coil_Cooling_WaterFields::WaterOutletNodeName).get()); + EXPECT_EQ("Pipe Outlet to Companion Coil Water Inlet Node", idf_companionCoil.getString(Coil_Cooling_WaterFields::WaterInletNodeName).get()); + EXPECT_EQ(idfController.getString(Controller_OutdoorAirFields::ReliefAirOutletNodeName).get(), idf_companionCoil.getString(Coil_Cooling_WaterFields::AirInletNodeName).get()); - EXPECT_EQ(coilSystemCoolingWater.companionCoilUsedForHeatRecovery().get().nameString() + " Exhaust Outlet Node", - idf_companionCoil.getString(Coil_Cooling_WaterFields::AirOutletNodeName).get()); // FIXME + EXPECT_EQ("Return to OA System Node", idf_companionCoil.getString(Coil_Cooling_WaterFields::AirInletNodeName).get()); + EXPECT_EQ("Relief Node", idf_companionCoil.getString(Coil_Cooling_WaterFields::AirOutletNodeName).get()); + EXPECT_EQ("SimpleAnalysis", idf_companionCoil.getString(Coil_Cooling_WaterFields::TypeofAnalysis).get()); EXPECT_EQ("CrossFlow", idf_companionCoil.getString(Coil_Cooling_WaterFields::HeatExchangerConfiguration).get()); EXPECT_TRUE(idf_companionCoil.isEmpty(Coil_Cooling_WaterFields::CondensateCollectionWaterStorageTankName)); From 51a0ae3b0402ec144c643b9255a672e84a464dfb Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Mon, 5 May 2025 18:07:07 +0200 Subject: [PATCH 55/58] Fixup the FIXME --- ...ForwardTranslateCoilSystemCoolingWater.cpp | 51 ++++++++----------- 1 file changed, 22 insertions(+), 29 deletions(-) diff --git a/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWater.cpp b/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWater.cpp index 84d0ca4dfb1..669feab5f06 100644 --- a/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWater.cpp +++ b/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWater.cpp @@ -75,35 +75,27 @@ namespace energyplus { idf->setString(Coil_Cooling_WaterFields::AirOutletNodeName, airOutletNodeName); // Add IddObjectType::Coil_Cooling_Water_DetailedGeometry if implemented } else { - // Shouldn't happen, accepts only Coil:Cooling:Water or Coil:Cooling:Water:DetailedGeometry - // Shouldn't happen, accepts only Coil:Cooling:DX:SingleSpeed or Coil:Cooling:DX:VariableSpeed - LOG(Fatal, modelObject.briefDescription() - << " appears to have a cooling coil that shouldn't have been accepted: " << coolingCoil.briefDescription()); - OS_ASSERT(false); - } - } - if (auto coilCoolingWater = coolingCoil.optionalCast()) { - if (auto controller = coilCoolingWater->controllerWaterCoil()) { - if (auto idf = translateAndMapModelObject(controller.get())) { - idf->setString(Controller_WaterCoilFields::SensorNodeName, airOutletNodeName); - } + // Shouldn't happen, accepts only Coil:Cooling:Water CoilSystem:Cooling:Water:HeatExchangerAssisted (or Coil:Cooling:Water:DetailedGeometry, not wrapped) + LOG_AND_THROW(modelObject.briefDescription() + << " appears to have a cooling coil that shouldn't have been accepted: " << coolingCoil.briefDescription()); } } - // Need a SPM:MixedAir on the Coil:Cooling:Water outlet node (that we **created** just above in IDF directly, so it won't get picked up by the + // TODO: is that true?! + // Need a SPM:MixedAir on the outlet node (that we **created** just above in IDF directly, so it won't get picked up by the // ForwardTranslateAirLoopHVAC method) if (boost::optional airLoop_ = modelObject.airLoopHVAC()) { std::vector fans; std::vector supplyComponents = airLoop_->supplyComponents(); - for (auto it = supplyComponents.begin(); it != supplyComponents.end(); ++it) { - if (auto fan_ = it->optionalCast()) { + for (auto& supplyComponent : supplyComponents) { + if (auto fan_ = supplyComponent.optionalCast()) { fans.insert(fans.begin(), std::move(*fan_)); - } else if (auto fan_ = it->optionalCast()) { + } else if (auto fan_ = supplyComponent.optionalCast()) { fans.insert(fans.begin(), std::move(*fan_)); - } else if (auto fan_ = it->optionalCast()) { + } else if (auto fan_ = supplyComponent.optionalCast()) { fans.insert(fans.begin(), std::move(*fan_)); - } else if (auto fan_ = it->optionalCast()) { + } else if (auto fan_ = supplyComponent.optionalCast()) { fans.insert(fans.begin(), std::move(*fan_)); } } @@ -178,19 +170,20 @@ namespace energyplus { // Companion Coil Used For Heat Recovery: Optional Object if (boost::optional companionCoilUsedForHeatRecovery_ = modelObject.companionCoilUsedForHeatRecovery()) { - if (boost::optional wo_ = translateAndMapModelObject(companionCoilUsedForHeatRecovery_.get())) { - idfObject.setString(CoilSystem_Cooling_WaterFields::CompanionCoilUsedForHeatRecovery, wo_->nameString()); - if (wo_->iddObject().type() == IddObjectType::Coil_Cooling_Water) { - wo_->setString(Coil_Cooling_WaterFields::AirInletNodeName, modelObject.airLoopHVACOutdoorAirSystem()->reliefAirModelObject()->nameString()); - wo_->setString(Coil_Cooling_WaterFields::AirOutletNodeName, wo_->nameString() + " Exhaust Outlet Node"); // FIXME - // Add IddObjectType::Coil_Cooling_Water_DetailedGeometry if implemented + if (auto comp_ = companionCoilUsedForHeatRecovery_->optionalCast()) { + if (comp_->airInletModelObject()) { + if (boost::optional idf_ = translateAndMapModelObject(companionCoilUsedForHeatRecovery_.get())) { + idfObject.setString(CoilSystem_Cooling_WaterFields::CompanionCoilUsedForHeatRecovery, idf_->nameString()); + } } else { - // Shouldn't happen, accepts only Coil:Cooling:Water or Coil:Cooling:Water:DetailedGeometry - // Shouldn't happen, accepts only Coil:Cooling:DX:SingleSpeed or Coil:Cooling:DX:VariableSpeed - LOG(Fatal, modelObject.briefDescription() << " appears to have a companion coil used for heat recovery that shouldn't have been accepted: " - << companionCoilUsedForHeatRecovery_.get().briefDescription()); - OS_ASSERT(false); + LOG(Warn, modelObject.briefDescription() + << " has a companion coil used for heat recovery that is not connected to an AirLoopHVAC / AirLoopHVACOutdoorAirSystem" + << " and will not be translated:" << comp_->briefDescription()); } + } else { + // Shouldn't happen, accepts only Coil:Cooling:Water + LOG_AND_THROW(modelObject.briefDescription() << " appears to have a companion coil used for heat recovery that shouldn't have been accepted: " + << companionCoilUsedForHeatRecovery_.get().briefDescription()); } } From 61ea54de103372086c2c78804a252875ac6c1241 Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Mon, 5 May 2025 18:35:11 +0200 Subject: [PATCH 56/58] Add a FT Gtest for a Case with a CoilSystemWaterHXAssisted inside a CoilSystemWater --- .../Test/CoilSystemCoolingWater_GTest.cpp | 199 +++++++++++++++++- 1 file changed, 198 insertions(+), 1 deletion(-) diff --git a/src/energyplus/Test/CoilSystemCoolingWater_GTest.cpp b/src/energyplus/Test/CoilSystemCoolingWater_GTest.cpp index d66716170aa..3746e2f41f7 100644 --- a/src/energyplus/Test/CoilSystemCoolingWater_GTest.cpp +++ b/src/energyplus/Test/CoilSystemCoolingWater_GTest.cpp @@ -12,11 +12,13 @@ #include "../../model/CoilSystemCoolingWater_Impl.hpp" #include "../../model/Schedule.hpp" #include "../../model/Schedule_Impl.hpp" +#include "../../model/ScheduleConstant.hpp" #include "../../model/CoilCoolingWater.hpp" #include "../../model/CoilCoolingWater_Impl.hpp" #include "../../model/CoilSystemCoolingWaterHeatExchangerAssisted.hpp" #include "../../model/CoilSystemCoolingWaterHeatExchangerAssisted_Impl.hpp" - +#include "../../model/HeatExchangerAirToAirSensibleAndLatent.hpp" +#include "../../model/HeatExchangerAirToAirSensibleAndLatent_Impl.hpp" #include "../../model/AirLoopHVAC.hpp" #include "../../model/AirLoopHVACUnitarySystem.hpp" #include "../../model/Node.hpp" @@ -39,6 +41,8 @@ #include #include #include +#include +#include #include #include #include @@ -303,3 +307,196 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWater_WithCompanion EXPECT_EQ(0, w.getObjectsByType(IddObjectType::Controller_WaterCoil).size()); } + +TEST_F(EnergyPlusFixture, ForwardTranslator_CoilSystemCoolingWater_HXAssisted) { + ForwardTranslator ft; + + Model m; + + CoilSystemCoolingWaterHeatExchangerAssisted coilSystemHXAssisted(m); + coilSystemHXAssisted.setName("HX Assisted"); + auto cc = coilSystemHXAssisted.coolingCoil().cast(); + auto hx = coilSystemHXAssisted.heatExchanger().cast(); + cc.setName("Primary Cooling Coil inside HXAssisted"); + hx.setName("HX AirToAir"); + CoilSystemCoolingWater coilSystemCoolingWater(m, coilSystemHXAssisted); + coilSystemCoolingWater.setName("My CoilSystemCoolingWater"); + + ScheduleConstant availabilitySchedule(m); + availabilitySchedule.setName("availabilitySchedule"); + EXPECT_TRUE(coilSystemCoolingWater.setAvailabilitySchedule(availabilitySchedule)); + EXPECT_TRUE(coilSystemCoolingWater.setDehumidificationControlType("CoolReheat")); + EXPECT_TRUE(coilSystemCoolingWater.setRunonSensibleLoad(false)); // Opposite from IDD default + EXPECT_TRUE(coilSystemCoolingWater.setRunonLatentLoad(true)); // Opposite from IDD default + EXPECT_TRUE(coilSystemCoolingWater.setMinimumAirToWaterTemperatureOffset(1.0)); + EXPECT_TRUE(coilSystemCoolingWater.setEconomizerLockout(false)); // Opposite from IDD default + EXPECT_TRUE(coilSystemCoolingWater.setMinimumWaterLoopTemperatureForHeatRecovery(1.2)); + CoilCoolingWater companionCoilUsedForHeatRecovery(m); + companionCoilUsedForHeatRecovery.setName("CompanionCoilUsedForHeatRecovery"); + EXPECT_TRUE(coilSystemCoolingWater.setCompanionCoilUsedForHeatRecovery(companionCoilUsedForHeatRecovery)); + + AirLoopHVAC airLoop(m); + Node supplyOutletNode = airLoop.supplyOutletNode(); + ControllerOutdoorAir controller1(m); + AirLoopHVACOutdoorAirSystem oaSystem(m, controller1); + EXPECT_TRUE(oaSystem.addToNode(supplyOutletNode)); + Node oaNode = oaSystem.outboardOANode().get(); + EXPECT_TRUE(coilSystemCoolingWater.addToNode(oaNode)); + Node reliefNode = oaSystem.outboardReliefNode().get(); + EXPECT_TRUE(companionCoilUsedForHeatRecovery.addToNode(reliefNode)); + + oaNode.setName("Outdoor Air Inlet Node"); + reliefNode.setName("Relief Node"); + oaSystem.reliefAirModelObject()->setName("Return to OA System Node"); + oaSystem.outdoorAirModelObject()->setName("OA System Outlet to Mixed Node"); + airLoop.mixedAirNode()->setName("Mixed Air Node"); + airLoop.supplyInletNode().setName("Supply Inlet Node"); + airLoop.supplyOutletNode().setName("Supply Outlet Node"); + + // They must be connected to a PlantLoop too + PlantLoop chw_p(m); + chw_p.addDemandBranchForComponent(cc); + PipeAdiabatic pipe(m); + Node coolingOutlet = cc.waterOutletModelObject()->cast(); + EXPECT_TRUE(pipe.addToNode(coolingOutlet)); + Node pipeOutlet = pipe.outletModelObject()->cast(); + EXPECT_TRUE(companionCoilUsedForHeatRecovery.addToNode(pipeOutlet)); + + cc.waterInletModelObject()->setName("Cooling Coil Water Inlet Node"); + cc.waterOutletModelObject()->setName("Cooling Coil Water Outlet to Pipe Inlet Node"); + pipe.outletModelObject()->setName("Pipe Outlet to Companion Coil Water Inlet Node"); + companionCoilUsedForHeatRecovery.waterOutletModelObject()->setName("Companion Coil Water Outlet Node"); + + const Workspace w = ft.translateModel(m); + + const auto idfCoilSystems = w.getObjectsByType(IddObjectType::CoilSystem_Cooling_Water); + ASSERT_EQ(1u, idfCoilSystems.size()); + const auto& idfCoilSystem = idfCoilSystems.front(); + + WorkspaceObjectVector idfCoils(w.getObjectsByType(IddObjectType::Coil_Cooling_Water)); + ASSERT_EQ(2u, idfCoils.size()); + + WorkspaceObjectVector idfControllers(w.getObjectsByType(IddObjectType::Controller_OutdoorAir)); + ASSERT_EQ(1u, idfControllers.size()); + const auto& idfController = idfControllers.front(); + + // Go from AirLoopHVAC to BranchList to Branch + WorkspaceObjectVector idf_airloops = w.getObjectsByType(IddObjectType::AirLoopHVAC); + ASSERT_EQ(1u, idf_airloops.size()); + + WorkspaceObject& idf_airLoopHVAC = idf_airloops.front(); + WorkspaceObject idf_brlist = idf_airLoopHVAC.getTarget(AirLoopHVACFields::BranchListName).get(); + + // Should have one branch only + ASSERT_EQ(1u, idf_brlist.extensibleGroups().size()); + auto w_eg = idf_brlist.extensibleGroups()[0].cast(); + WorkspaceObject idf_branch = w_eg.getTarget(BranchListExtensibleFields::BranchName).get(); + + // There should be only one equipment on the branch + ASSERT_EQ(1u, idf_branch.extensibleGroups().size()); + auto w_eg2 = idf_branch.extensibleGroups()[0].cast(); + + /* EXPECT_EQ(w_eg2.getString(BranchExtensibleFields::ComponentInletNodeName).get(), coilSystemCoolingWater.inletModelObject().get().nameString()); + EXPECT_EQ(w_eg2.getString(BranchExtensibleFields::ComponentOutletNodeName).get(), coilSystemCoolingWater.outletModelObject().get().nameString()); */ + EXPECT_EQ("AirLoopHVAC:OutdoorAirSystem", w_eg2.getString(BranchExtensibleFields::ComponentObjectType).get()); + + EXPECT_EQ(coilSystemCoolingWater.inletModelObject().get().nameString(), + idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::AirInletNodeName).get()); + EXPECT_EQ(coilSystemCoolingWater.outletModelObject().get().nameString(), + idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::AirOutletNodeName).get()); + EXPECT_EQ(availabilitySchedule.nameString(), idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::AvailabilityScheduleName).get()); + EXPECT_EQ("CoilSystem:Cooling:Water:HeatExchangerAssisted", idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::CoolingCoilObjectType).get()); + EXPECT_EQ(coilSystemCoolingWater.coolingCoil().nameString(), idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::CoolingCoilName).get()); + EXPECT_EQ("CoolReheat", idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::DehumidificationControlType).get()); + EXPECT_EQ("No", idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::RunonSensibleLoad).get()); + EXPECT_EQ("Yes", idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::RunonLatentLoad).get()); + EXPECT_EQ(1.0, idfCoilSystem.getDouble(CoilSystem_Cooling_WaterFields::MinimumAirToWaterTemperatureOffset).get()); + EXPECT_EQ("No", idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::EconomizerLockout).get()); + EXPECT_EQ(1.2, idfCoilSystem.getDouble(CoilSystem_Cooling_WaterFields::MinimumWaterLoopTemperatureForHeatRecovery).get()); + EXPECT_EQ(companionCoilUsedForHeatRecovery.nameString(), + idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::CompanionCoilUsedForHeatRecovery).get()); + + WorkspaceObject idf_hxAssisted = idfCoilSystem.getTarget(CoilSystem_Cooling_WaterFields::CoolingCoilName).get(); + EXPECT_EQ("HeatExchanger:AirToAir:SensibleAndLatent", + idf_hxAssisted.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::HeatExchangerObjectType).get()); + EXPECT_EQ("HX AirToAir", idf_hxAssisted.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::HeatExchangerName).get()); + EXPECT_EQ("Coil:Cooling:Water", idf_hxAssisted.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::CoolingCoilObjectType).get()); + EXPECT_EQ("Primary Cooling Coil inside HXAssisted", + idf_hxAssisted.getString(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::CoolingCoilName).get()); + + // This fails for some reason? + // auto idf_hx = idf_hxAssisted.getTarget(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::HeatExchangerName).get(); + ASSERT_EQ(1, w.getObjectsByType(IddObjectType::HeatExchanger_AirToAir_SensibleAndLatent).size()); + auto idf_hx = w.getObjectsByType(IddObjectType::HeatExchanger_AirToAir_SensibleAndLatent).front(); + + EXPECT_EQ(hx.nameString(), idf_hx.getString(HeatExchanger_AirToAir_SensibleAndLatentFields::Name).get()); + EXPECT_EQ(idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::AirInletNodeName).get(), + idf_hx.getString(HeatExchanger_AirToAir_SensibleAndLatentFields::SupplyAirInletNodeName).get()); + EXPECT_EQ("Outdoor Air Inlet Node", idf_hx.getString(HeatExchanger_AirToAir_SensibleAndLatentFields::SupplyAirInletNodeName).get()); + + EXPECT_EQ(idfCoilSystem.getString(CoilSystem_Cooling_WaterFields::AirOutletNodeName).get(), + idf_hx.getString(HeatExchanger_AirToAir_SensibleAndLatentFields::ExhaustAirOutletNodeName).get()); + EXPECT_EQ("OA System Outlet to Mixed Node", idf_hx.getString(HeatExchanger_AirToAir_SensibleAndLatentFields::ExhaustAirOutletNodeName).get()); + + EXPECT_EQ("HX Assisted HX Supply Air Outlet - Cooling Inlet Node", + idf_hx.getString(HeatExchanger_AirToAir_SensibleAndLatentFields::SupplyAirOutletNodeName).get()); + EXPECT_EQ("HX Assisted HX Exhaust Air Inlet - Cooling Outlet Node", + idf_hx.getString(HeatExchanger_AirToAir_SensibleAndLatentFields::ExhaustAirInletNodeName).get()); + + WorkspaceObject idf_coolingCoil = idf_hxAssisted.getTarget(CoilSystem_Cooling_Water_HeatExchangerAssistedFields::CoolingCoilName).get(); + WorkspaceObject idf_companionCoil = idfCoilSystem.getTarget(CoilSystem_Cooling_WaterFields::CompanionCoilUsedForHeatRecovery).get(); + + EXPECT_EQ("Primary Cooling Coil inside HXAssisted", idf_coolingCoil.getString(Coil_Cooling_WaterFields::Name).get()); + EXPECT_EQ("Always On Discrete", idf_coolingCoil.getString(Coil_Cooling_WaterFields::AvailabilityScheduleName).get()); + EXPECT_EQ("Autosize", idf_coolingCoil.getString(Coil_Cooling_WaterFields::DesignWaterFlowRate).get()); + EXPECT_EQ("Autosize", idf_coolingCoil.getString(Coil_Cooling_WaterFields::DesignAirFlowRate).get()); + EXPECT_EQ("Autosize", idf_coolingCoil.getString(Coil_Cooling_WaterFields::DesignInletWaterTemperature).get()); + EXPECT_EQ("Autosize", idf_coolingCoil.getString(Coil_Cooling_WaterFields::DesignInletAirTemperature).get()); + EXPECT_EQ("Autosize", idf_coolingCoil.getString(Coil_Cooling_WaterFields::DesignInletAirHumidityRatio).get()); + EXPECT_EQ("Autosize", idf_coolingCoil.getString(Coil_Cooling_WaterFields::DesignOutletAirHumidityRatio).get()); + + EXPECT_EQ(cc.waterInletModelObject().get().nameString(), idf_coolingCoil.getString(Coil_Cooling_WaterFields::WaterInletNodeName).get()); + EXPECT_EQ("Cooling Coil Water Inlet Node", idf_coolingCoil.getString(Coil_Cooling_WaterFields::WaterInletNodeName).get()); + EXPECT_EQ(cc.waterOutletModelObject().get().nameString(), idf_coolingCoil.getString(Coil_Cooling_WaterFields::WaterOutletNodeName).get()); + EXPECT_EQ("Cooling Coil Water Outlet to Pipe Inlet Node", idf_coolingCoil.getString(Coil_Cooling_WaterFields::WaterOutletNodeName).get()); + EXPECT_EQ(idf_hx.getString(HeatExchanger_AirToAir_SensibleAndLatentFields::SupplyAirOutletNodeName).get(), + idf_coolingCoil.getString(Coil_Cooling_WaterFields::AirInletNodeName).get()); + EXPECT_EQ("HX Assisted HX Supply Air Outlet - Cooling Inlet Node", idf_coolingCoil.getString(Coil_Cooling_WaterFields::AirInletNodeName).get()); + EXPECT_EQ(idf_hx.getString(HeatExchanger_AirToAir_SensibleAndLatentFields::ExhaustAirInletNodeName).get(), + idf_coolingCoil.getString(Coil_Cooling_WaterFields::AirOutletNodeName).get()); + EXPECT_EQ("HX Assisted HX Exhaust Air Inlet - Cooling Outlet Node", idf_coolingCoil.getString(Coil_Cooling_WaterFields::AirOutletNodeName).get()); + + EXPECT_EQ("SimpleAnalysis", idf_coolingCoil.getString(Coil_Cooling_WaterFields::TypeofAnalysis).get()); + EXPECT_EQ("CrossFlow", idf_coolingCoil.getString(Coil_Cooling_WaterFields::HeatExchangerConfiguration).get()); + EXPECT_TRUE(idf_coolingCoil.isEmpty(Coil_Cooling_WaterFields::CondensateCollectionWaterStorageTankName)); + EXPECT_TRUE(idf_coolingCoil.isEmpty(Coil_Cooling_WaterFields::DesignWaterTemperatureDifference)); + + EXPECT_EQ(coilSystemCoolingWater.companionCoilUsedForHeatRecovery().get().nameString(), + idf_companionCoil.getString(Coil_Cooling_WaterFields::Name).get()); + EXPECT_EQ("Always On Discrete", idf_companionCoil.getString(Coil_Cooling_WaterFields::AvailabilityScheduleName).get()); + EXPECT_EQ("Autosize", idf_companionCoil.getString(Coil_Cooling_WaterFields::DesignWaterFlowRate).get()); + EXPECT_EQ("Autosize", idf_companionCoil.getString(Coil_Cooling_WaterFields::DesignAirFlowRate).get()); + EXPECT_EQ("Autosize", idf_companionCoil.getString(Coil_Cooling_WaterFields::DesignInletWaterTemperature).get()); + EXPECT_EQ("Autosize", idf_companionCoil.getString(Coil_Cooling_WaterFields::DesignInletAirTemperature).get()); + EXPECT_EQ("Autosize", idf_companionCoil.getString(Coil_Cooling_WaterFields::DesignInletAirHumidityRatio).get()); + EXPECT_EQ("Autosize", idf_companionCoil.getString(Coil_Cooling_WaterFields::DesignOutletAirHumidityRatio).get()); + + EXPECT_EQ(companionCoilUsedForHeatRecovery.waterInletModelObject().get().nameString(), + idf_companionCoil.getString(Coil_Cooling_WaterFields::WaterInletNodeName).get()); + EXPECT_EQ("Companion Coil Water Outlet Node", idf_companionCoil.getString(Coil_Cooling_WaterFields::WaterOutletNodeName).get()); + EXPECT_EQ(companionCoilUsedForHeatRecovery.waterOutletModelObject().get().nameString(), + idf_companionCoil.getString(Coil_Cooling_WaterFields::WaterOutletNodeName).get()); + EXPECT_EQ("Pipe Outlet to Companion Coil Water Inlet Node", idf_companionCoil.getString(Coil_Cooling_WaterFields::WaterInletNodeName).get()); + + EXPECT_EQ(idfController.getString(Controller_OutdoorAirFields::ReliefAirOutletNodeName).get(), + idf_companionCoil.getString(Coil_Cooling_WaterFields::AirInletNodeName).get()); + EXPECT_EQ("Return to OA System Node", idf_companionCoil.getString(Coil_Cooling_WaterFields::AirInletNodeName).get()); + EXPECT_EQ("Relief Node", idf_companionCoil.getString(Coil_Cooling_WaterFields::AirOutletNodeName).get()); + + EXPECT_EQ("SimpleAnalysis", idf_companionCoil.getString(Coil_Cooling_WaterFields::TypeofAnalysis).get()); + EXPECT_EQ("CrossFlow", idf_companionCoil.getString(Coil_Cooling_WaterFields::HeatExchangerConfiguration).get()); + EXPECT_TRUE(idf_companionCoil.isEmpty(Coil_Cooling_WaterFields::CondensateCollectionWaterStorageTankName)); + EXPECT_TRUE(idf_companionCoil.isEmpty(Coil_Cooling_WaterFields::DesignWaterTemperatureDifference)); + + EXPECT_EQ(0, w.getObjectsByType(IddObjectType::Controller_WaterCoil).size()); +} From e1705d9fc1f6126da4df9868e89f6a3ed1d90f84 Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Mon, 5 May 2025 18:35:32 +0200 Subject: [PATCH 57/58] Fixup FT to handle CoilSystemWaterHXAssisted inside CoilSystemWater --- ...ForwardTranslateCoilSystemCoolingWater.cpp | 4 +++ ...ystemCoolingWaterHeatExchangerAssisted.cpp | 28 ++++++++++++++----- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWater.cpp b/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWater.cpp index 669feab5f06..f167f8bc181 100644 --- a/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWater.cpp +++ b/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWater.cpp @@ -74,6 +74,10 @@ namespace energyplus { idf->setString(Coil_Cooling_WaterFields::AirInletNodeName, airInletNodeName); idf->setString(Coil_Cooling_WaterFields::AirOutletNodeName, airOutletNodeName); // Add IddObjectType::Coil_Cooling_Water_DetailedGeometry if implemented + } else if (idf->iddObject().type() == IddObjectType::CoilSystem_Cooling_Water_HeatExchangerAssisted) { + // The logic is built in the translateCoilSystemCoolingWaterHeatExchangerAssisted method + // Essentially it's the same as getting the HX (CoilSystem_Cooling_Water_HeatExchangerAssistedFields::HeatExchangerName) + // and setting HeatExchanger_AirToAir_SensibleAndLatentFields::SupplyAirInletNodeName & ExhaustAirOutletNodeName } else { // Shouldn't happen, accepts only Coil:Cooling:Water CoilSystem:Cooling:Water:HeatExchangerAssisted (or Coil:Cooling:Water:DetailedGeometry, not wrapped) LOG_AND_THROW(modelObject.briefDescription() diff --git a/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWaterHeatExchangerAssisted.cpp b/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWaterHeatExchangerAssisted.cpp index 3cd67ee19a2..e54247683b6 100644 --- a/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWaterHeatExchangerAssisted.cpp +++ b/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWaterHeatExchangerAssisted.cpp @@ -14,6 +14,8 @@ #include "../../model/CoilCoolingWater_Impl.hpp" #include "../../model/ControllerWaterCoil.hpp" #include "../../model/ControllerWaterCoil_Impl.hpp" +#include "../../model/CoilSystemCoolingWater.hpp" +#include "../../model/CoilSystemCoolingWater_Impl.hpp" #include "../../model/AirLoopHVAC.hpp" #include "../../model/FanVariableVolume.hpp" @@ -47,18 +49,30 @@ namespace energyplus { IdfObject idfObject = createRegisterAndNameIdfObject(openstudio::IddObjectType::CoilSystem_Cooling_Water_HeatExchangerAssisted, modelObject); std::string hxSupplyAirInletNodeName; + std::string hxExhaustAirOutletNodeName; // InletNodeName if (auto mo = modelObject.inletModelObject()) { if (auto node = mo->optionalCast()) { hxSupplyAirInletNodeName = node->nameString(); } - } - - std::string hxExhaustAirOutletNodeName; - // OutletNodeName - if (auto mo = modelObject.outletModelObject()) { - if (auto node = mo->optionalCast()) { - hxExhaustAirOutletNodeName = node->nameString(); + // OutletNodeName + if (auto mo = modelObject.outletModelObject()) { + if (auto node = mo->optionalCast()) { + hxExhaustAirOutletNodeName = node->nameString(); + } + } + } else if (auto comp_ = modelObject.containingHVACComponent()) { + if (auto coilSystem_ = comp_->optionalCast()) { + if (auto mo = coilSystem_->inletModelObject()) { + if (auto node = mo->optionalCast()) { + hxSupplyAirInletNodeName = node->nameString(); + } + } + if (auto mo = coilSystem_->outletModelObject()) { + if (auto node = mo->optionalCast()) { + hxExhaustAirOutletNodeName = node->nameString(); + } + } } } From be13f9f3fe3061efb9f63920ef10b79213b1f374 Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Mon, 5 May 2025 22:15:18 +0200 Subject: [PATCH 58/58] Remove copy pasted bit that tries to add a SPM:MixedAir: it's not needed (and OS-resources test show E+ issuing a warning) --- ...ForwardTranslateCoilSystemCoolingWater.cpp | 46 ------------------- 1 file changed, 46 deletions(-) diff --git a/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWater.cpp b/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWater.cpp index f167f8bc181..48d64844462 100644 --- a/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWater.cpp +++ b/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingWater.cpp @@ -84,52 +84,6 @@ namespace energyplus { << " appears to have a cooling coil that shouldn't have been accepted: " << coolingCoil.briefDescription()); } } - - // TODO: is that true?! - // Need a SPM:MixedAir on the outlet node (that we **created** just above in IDF directly, so it won't get picked up by the - // ForwardTranslateAirLoopHVAC method) - if (boost::optional airLoop_ = modelObject.airLoopHVAC()) { - std::vector fans; - std::vector supplyComponents = airLoop_->supplyComponents(); - - for (auto& supplyComponent : supplyComponents) { - if (auto fan_ = supplyComponent.optionalCast()) { - fans.insert(fans.begin(), std::move(*fan_)); - } else if (auto fan_ = supplyComponent.optionalCast()) { - fans.insert(fans.begin(), std::move(*fan_)); - } else if (auto fan_ = supplyComponent.optionalCast()) { - fans.insert(fans.begin(), std::move(*fan_)); - } else if (auto fan_ = supplyComponent.optionalCast()) { - fans.insert(fans.begin(), std::move(*fan_)); - } - } - - if (!fans.empty()) { - // Fan closest to the supply outlet node - StraightComponent fan = fans.front(); - OptionalNode inletNode = fan.inletModelObject()->optionalCast(); - OptionalNode outletNode = fan.outletModelObject()->optionalCast(); - - // No reason this wouldn't be ok at this point really... - // TODO: change to OS_ASSERT? - if (inletNode && outletNode) { - - IdfObject idf_spm(IddObjectType::SetpointManager_MixedAir); - idf_spm.setString(SetpointManager_MixedAirFields::Name, airOutletNodeName + " OS Default SPM"); - idf_spm.setString(SetpointManager_MixedAirFields::ControlVariable, "Temperature"); - - Node supplyOutletNode = airLoop_->supplyOutletNode(); - idf_spm.setString(SetpointManager_MixedAirFields::ReferenceSetpointNodeName, supplyOutletNode.nameString()); - - idf_spm.setString(SetpointManager_MixedAirFields::FanInletNodeName, inletNode->nameString()); - idf_spm.setString(SetpointManager_MixedAirFields::FanOutletNodeName, outletNode->nameString()); - - idf_spm.setString(SetpointManager_MixedAirFields::SetpointNodeorNodeListName, airOutletNodeName); - - m_idfObjects.push_back(idf_spm); - } - } - } } // Availability Schedule Name: Optional Object