diff --git a/resources/model/OpenStudio.idd b/resources/model/OpenStudio.idd index b657e0e26b..395aa4da1a 100644 --- a/resources/model/OpenStudio.idd +++ b/resources/model/OpenStudio.idd @@ -10218,28 +10218,6 @@ OS:AirLoopHVAC, \required-field \object-list ConnectionObject -OS:AirLoopHVAC:ControllerList, - \memo List controllers in order of control sequence - \extensible:2 - \min-fields 4 - A1, \field Handle - \type handle - \required-field - A2, \field Name - \type alpha - \required-field - \reference ControllerLists - A3, \field Controller Object Type - \type choice - \required-field - \begin-extensible - \key Controller:WaterCoil - \key Controller:OutdoorAir - A4; \field Controller Name - \type object-list - \required-field - \object-list AirLoopControllers - OS:AirLoopHVAC:OutdoorAirSystem, \min-fields 4 A1, \field Handle diff --git a/src/energyplus/ForwardTranslator.cpp b/src/energyplus/ForwardTranslator.cpp index 5c25712b85..87e53a3c33 100644 --- a/src/energyplus/ForwardTranslator.cpp +++ b/src/energyplus/ForwardTranslator.cpp @@ -3127,7 +3127,6 @@ namespace energyplus { result.push_back(IddObjectType::OS_Exterior_WaterEquipment); result.push_back(IddObjectType::OS_AirLoopHVAC); - result.push_back(IddObjectType::OS_AirLoopHVAC_ControllerList); // Translated by AirLoopHVAC // result.push_back(IddObjectType::OS_AirLoopHVAC_OutdoorAirSystem); diff --git a/src/energyplus/ForwardTranslator/ForwardTranslateAirLoopHVACOutdoorAirSystem.cpp b/src/energyplus/ForwardTranslator/ForwardTranslateAirLoopHVACOutdoorAirSystem.cpp index a0aa99a031..556335fb07 100644 --- a/src/energyplus/ForwardTranslator/ForwardTranslateAirLoopHVACOutdoorAirSystem.cpp +++ b/src/energyplus/ForwardTranslator/ForwardTranslateAirLoopHVACOutdoorAirSystem.cpp @@ -84,23 +84,6 @@ namespace energyplus { idfObject.setString(openstudio::AirLoopHVAC_OutdoorAirSystemFields::Name, name); // Controller List - IdfObject _controllerList(IddObjectType::AirLoopHVAC_ControllerList); - _controllerList.setName(name + " Controller List"); - _controllerList.clearExtensibleGroups(); - m_idfObjects.push_back(_controllerList); - idfObject.setString(openstudio::AirLoopHVAC_OutdoorAirSystemFields::ControllerListName, _controllerList.name().get()); - - ControllerOutdoorAir controllerOutdoorAir = modelObject.getControllerOutdoorAir(); - - if (!modelObject.airLoopHVACDedicatedOutdoorAirSystem()) { - boost::optional _controllerOutdoorAir = translateAndMapModelObject(controllerOutdoorAir); - OS_ASSERT(_controllerOutdoorAir); - - IdfExtensibleGroup eg = _controllerList.pushExtensibleGroup(); - eg.setString(AirLoopHVAC_ControllerListExtensibleFields::ControllerObjectType, _controllerOutdoorAir->iddObject().name()); - eg.setString(AirLoopHVAC_ControllerListExtensibleFields::ControllerName, _controllerOutdoorAir->name().get()); - } - std::vector controllers; auto components = modelObject.components(); for (const auto& component : components) { @@ -117,12 +100,34 @@ namespace energyplus { } } - for (auto& controller : controllers) { - auto _controller = translateAndMapModelObject(controller); - if (_controller) { + // If it's not empty: then we have work to do. + // If it's empty, there's at least the controller Outdoor Air UNLESS it's on a AirLoopHVACDOAS in which case do nothing + if (!controllers.empty() || !modelObject.airLoopHVACDedicatedOutdoorAirSystem()) { + + IdfObject _controllerList(IddObjectType::AirLoopHVAC_ControllerList); + _controllerList.setName(name + " Controller List"); + _controllerList.clearExtensibleGroups(); + m_idfObjects.push_back(_controllerList); + idfObject.setString(openstudio::AirLoopHVAC_OutdoorAirSystemFields::ControllerListName, _controllerList.name().get()); + + ControllerOutdoorAir controllerOutdoorAir = modelObject.getControllerOutdoorAir(); + + if (!modelObject.airLoopHVACDedicatedOutdoorAirSystem()) { + boost::optional _controllerOutdoorAir = translateAndMapModelObject(controllerOutdoorAir); + OS_ASSERT(_controllerOutdoorAir); + IdfExtensibleGroup eg = _controllerList.pushExtensibleGroup(); - eg.setString(AirLoopHVAC_ControllerListExtensibleFields::ControllerObjectType, _controller->iddObject().name()); - eg.setString(AirLoopHVAC_ControllerListExtensibleFields::ControllerName, _controller->name().get()); + eg.setString(AirLoopHVAC_ControllerListExtensibleFields::ControllerObjectType, _controllerOutdoorAir->iddObject().name()); + eg.setString(AirLoopHVAC_ControllerListExtensibleFields::ControllerName, _controllerOutdoorAir->name().get()); + } + + for (auto& controller : controllers) { + auto _controller = translateAndMapModelObject(controller); + if (_controller) { + IdfExtensibleGroup eg = _controllerList.pushExtensibleGroup(); + eg.setString(AirLoopHVAC_ControllerListExtensibleFields::ControllerObjectType, _controller->iddObject().name()); + eg.setString(AirLoopHVAC_ControllerListExtensibleFields::ControllerName, _controller->name().get()); + } } } diff --git a/src/energyplus/Test/AirLoopHVACDedicatedOutdoorAirSystem_GTest.cpp b/src/energyplus/Test/AirLoopHVACDedicatedOutdoorAirSystem_GTest.cpp index 5b6e353f88..f67117a00c 100644 --- a/src/energyplus/Test/AirLoopHVACDedicatedOutdoorAirSystem_GTest.cpp +++ b/src/energyplus/Test/AirLoopHVACDedicatedOutdoorAirSystem_GTest.cpp @@ -53,6 +53,8 @@ #include "../../model/CoilCoolingWater.hpp" #include "../../model/CoilCoolingWater_Impl.hpp" +#include "../../utilities/idf/IdfObject.hpp" +#include "../../utilities/idf/WorkspaceObject.hpp" #include "../../utilities/idf/IdfExtensibleGroup.hpp" #include "../../utilities/idf/WorkspaceExtensibleGroup.hpp" @@ -160,6 +162,60 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_AirLoopHVACDedicatedOutdoorAirSystem w_egSplitter.getString(AirLoopHVAC_SplitterExtensibleFields::OutletNodeName, false).get()); } +TEST_F(EnergyPlusFixture, ForwardTranslator_AirLoopHVACDedicatedOutdoorAirSystem_ControllerList) { + + // Test for #4265 - Do not translate empty AirLoopHVAC:ControllerList for AirLoopHVAC:DedicatedOutdoorAirSystem to avoid E+ Severe errors + ForwardTranslator ft; + + Model m; + + ControllerOutdoorAir controllerOutdoorAir(m); + AirLoopHVACOutdoorAirSystem oaSystem(m, controllerOutdoorAir); + oaSystem.setName("Outdoor Air System 1"); + AirLoopHVACDedicatedOutdoorAirSystem doas(oaSystem); + + // There's only the AirLoopHVACOutdoorAirSystem, but no components on it -> do not translate the ControllerList + { + Workspace w = ft.translateModel(m); + EXPECT_EQ(0, w.getObjectsByType(IddObjectType::AirLoopHVAC_ControllerList).size()); + + WorkspaceObjectVector idfDOASs(w.getObjectsByType(IddObjectType::AirLoopHVAC_DedicatedOutdoorAirSystem)); + ASSERT_EQ(1, idfDOASs.size()); + WorkspaceObject idfDOAS(idfDOASs[0]); + + auto _idfOASystem = idfDOAS.getTarget(AirLoopHVAC_DedicatedOutdoorAirSystemFields::AirLoopHVAC_OutdoorAirSystemName); + ASSERT_TRUE(_idfOASystem); + EXPECT_FALSE(_idfOASystem->getTarget(AirLoopHVAC_OutdoorAirSystemFields::ControllerListName)); + } + + CoilCoolingWater coil(m); + EXPECT_EQ(2, oaSystem.components().size()); + EXPECT_TRUE(coil.addToNode(oaSystem.outboardOANode().get())); + EXPECT_EQ(4, oaSystem.components().size()); + PlantLoop p(m); + EXPECT_TRUE(p.addDemandBranchForComponent(coil)); + + // There's the Controller:WaterCoil, so do translate it + { + Workspace w = ft.translateModel(m); + EXPECT_EQ(1, w.getObjectsByType(IddObjectType::AirLoopHVAC_ControllerList).size()); + + WorkspaceObjectVector idfDOASs(w.getObjectsByType(IddObjectType::AirLoopHVAC_DedicatedOutdoorAirSystem)); + ASSERT_EQ(1, idfDOASs.size()); + WorkspaceObject idfDOAS(idfDOASs[0]); + + auto _idfOASystem = idfDOAS.getTarget(AirLoopHVAC_DedicatedOutdoorAirSystemFields::AirLoopHVAC_OutdoorAirSystemName); + ASSERT_TRUE(_idfOASystem); + auto _idfControllerList = _idfOASystem->getTarget(AirLoopHVAC_OutdoorAirSystemFields::ControllerListName); + ASSERT_TRUE(_idfControllerList); + + ASSERT_EQ(1, _idfControllerList->numExtensibleGroups()); + WorkspaceExtensibleGroup w_eg = _idfControllerList->extensibleGroups()[0].cast(); + EXPECT_EQ("Controller:WaterCoil", w_eg.getString(AirLoopHVAC_ControllerListExtensibleFields::ControllerObjectType).get()); + EXPECT_TRUE(w_eg.getString(AirLoopHVAC_ControllerListExtensibleFields::ControllerName)); + } +} + /* TEST_F(EnergyPlusFixture, ReverseTranslator_AirLoopHVACDedicatedOutdoorAirSystem) { openstudio::Workspace workspace(openstudio::StrictnessLevel::None, openstudio::IddFileType::EnergyPlus); diff --git a/src/model/AirLoopHVAC.cpp b/src/model/AirLoopHVAC.cpp index 0b18c3c04d..c1f324f81f 100644 --- a/src/model/AirLoopHVAC.cpp +++ b/src/model/AirLoopHVAC.cpp @@ -110,7 +110,6 @@ #include #include #include -#include #include #include #include "../utilities/core/Compare.hpp" diff --git a/src/model/AirLoopHVACOutdoorAirSystem.cpp b/src/model/AirLoopHVACOutdoorAirSystem.cpp index a4a9b6a60f..b5831d6044 100644 --- a/src/model/AirLoopHVACOutdoorAirSystem.cpp +++ b/src/model/AirLoopHVACOutdoorAirSystem.cpp @@ -51,7 +51,6 @@ #include "../utilities/idf/IdfExtensibleGroup.hpp" #include #include -#include #include #include #include