Skip to content

Commit

Permalink
Merge branch 'develop' into cooling-tower-fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
joseph-robertson committed Feb 28, 2022
2 parents e8d3391 + 1aef8bf commit c1cdade
Show file tree
Hide file tree
Showing 24 changed files with 41,110 additions and 261 deletions.
1 change: 1 addition & 0 deletions resources/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,7 @@ SET(gbxml_resources_src
gbxml/3951_Geometry_bug.xml
gbxml/3997_WindowScaling_bug.xml
gbxml/TestSchedules.xml
gbxml/gbXMLStandard_Single_Family_Residential_2016.xml
gbxml/TropicBird_BEM_4_2018.xml
gbxml/TropicBird.xml
)
Expand Down
39,017 changes: 39,017 additions & 0 deletions resources/gbxml/gbXMLStandard_Single_Family_Residential_2016.xml

Large diffs are not rendered by default.

20 changes: 20 additions & 0 deletions src/energyplus/ForwardTranslator/ForwardTranslatePlantLoop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,26 @@ namespace energyplus {
} else if (isSupplyBranch) {
inletNode = waterToWaterComponent->supplyInletModelObject()->optionalCast<Node>();
outletNode = waterToWaterComponent->supplyOutletModelObject()->optionalCast<Node>();

// WaterHeater:Mixed with Source Side nodes on supply branch
if (auto water_heater_mixed = modelObject.optionalCast<WaterHeaterMixed>()) {
if (boost::optional<PlantLoop> sourceSidePlantLoop = water_heater_mixed->sourceSidePlantLoop()) {
if (loop.handle() == sourceSidePlantLoop->handle()) {
inletNode = waterToWaterComponent->demandInletModelObject()->optionalCast<Node>();
outletNode = waterToWaterComponent->demandOutletModelObject()->optionalCast<Node>();
}
}
}

// WaterHeater:Stratified with Source Side nodes on supply branch
if (auto water_heater_stratified = modelObject.optionalCast<WaterHeaterStratified>()) {
if (boost::optional<PlantLoop> sourceSidePlantLoop = water_heater_stratified->sourceSidePlantLoop()) {
if (loop.handle() == sourceSidePlantLoop->handle()) {
inletNode = waterToWaterComponent->demandInletModelObject()->optionalCast<Node>();
outletNode = waterToWaterComponent->demandOutletModelObject()->optionalCast<Node>();
}
}
}
} else {
if (auto tertiaryInletModelObject = waterToWaterComponent->tertiaryInletModelObject()) {
if (auto tertiaryInletNode = tertiaryInletModelObject->optionalCast<Node>()) {
Expand Down
137 changes: 137 additions & 0 deletions src/energyplus/Test/WaterHeaterMixed_GTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,23 @@

#include "../../model/PlantLoop.hpp"
#include "../../model/PlantLoop_Impl.hpp"
#include "../../model/PipeAdiabatic.hpp"
#include "../../model/PipeAdiabatic_Impl.hpp"
#include "../../model/Node.hpp"
#include "../../model/Node_Impl.hpp"

#include "../../utilities/idf/IdfFile.hpp"
#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"

#include <utilities/idd/WaterHeater_Mixed_FieldEnums.hxx>
#include <utilities/idd/PlantLoop_FieldEnums.hxx>
#include <utilities/idd/PlantEquipmentList_FieldEnums.hxx>
#include <utilities/idd/PlantEquipmentOperationSchemes_FieldEnums.hxx>
#include <utilities/idd/PlantEquipmentOperation_HeatingLoad_FieldEnums.hxx>
#include <utilities/idd/IddEnums.hxx>

using namespace openstudio::energyplus;
Expand Down Expand Up @@ -110,3 +119,131 @@ TEST_F(EnergyPlusFixture, ForwardTranslatorWaterHeaterMixed_Condition) {
EXPECT_EQ(1u, w.getObjectsByType(IddObjectType::WaterHeater_Mixed).size());
}
}

TEST_F(EnergyPlusFixture, ForwardTranslatorWaterHeaterMixed_PlantLoopConnections) {
ForwardTranslator ft;
Model m;

WaterHeaterMixed wh(m);

PlantLoop useSidePlantLoop(m);

EXPECT_TRUE(useSidePlantLoop.addSupplyBranchForComponent(wh));
std::string useSideOutletNodeName;
{
Workspace w = ft.translateModel(m);

EXPECT_EQ(1, w.getObjectsByType(IddObjectType::PlantLoop).size());

std::vector<WorkspaceObject> idfWHMixeds(w.getObjectsByType(IddObjectType::WaterHeater_Mixed));
ASSERT_EQ(1, idfWHMixeds.size());
WorkspaceObject idfWHMixed(idfWHMixeds[0]);

EXPECT_FALSE(idfWHMixed.isEmpty(WaterHeater_MixedFields::UseSideInletNodeName));
ASSERT_FALSE(idfWHMixed.isEmpty(WaterHeater_MixedFields::UseSideOutletNodeName));
useSideOutletNodeName = idfWHMixed.getString(WaterHeater_MixedFields::UseSideOutletNodeName, false).get();
EXPECT_NE("", useSideOutletNodeName);

EXPECT_TRUE(idfWHMixed.isEmpty(WaterHeater_MixedFields::SourceSideInletNodeName));
EXPECT_TRUE(idfWHMixed.isEmpty(WaterHeater_MixedFields::SourceSideOutletNodeName));

EXPECT_EQ("", idfWHMixed.getString(WaterHeater_MixedFields::SourceSideInletNodeName, false).get());
EXPECT_EQ("", idfWHMixed.getString(WaterHeater_MixedFields::SourceSideOutletNodeName, false).get());

// Check PlantEquipmentOperationScheme for Use Side
{
auto _wo = w.getObjectByTypeAndName(IddObjectType::PlantLoop, useSidePlantLoop.nameString());
ASSERT_TRUE(_wo.is_initialized());
WorkspaceObject idf_coolingPlant = _wo.get();
WorkspaceObject idf_plant_op = idf_coolingPlant.getTarget(PlantLoopFields::PlantEquipmentOperationSchemeName).get();

// Should have created a Heating Load one only
ASSERT_EQ(1, idf_plant_op.extensibleGroups().size());
auto w_eg = idf_plant_op.extensibleGroups()[0].cast<WorkspaceExtensibleGroup>();
ASSERT_EQ("PlantEquipmentOperation:HeatingLoad", w_eg.getString(PlantEquipmentOperationSchemesExtensibleFields::ControlSchemeObjectType).get());

// Get the Operation Scheme
_wo = w_eg.getTarget(PlantEquipmentOperationSchemesExtensibleFields::ControlSchemeName);
ASSERT_TRUE(_wo.is_initialized());
WorkspaceObject idf_op_scheme = _wo.get();

// Get the Plant Equipment List of this HeatingLoad scheme
// There should only be one Load Range
ASSERT_EQ(1, idf_op_scheme.extensibleGroups().size());
// Load range 1
w_eg = idf_op_scheme.extensibleGroups()[0].cast<WorkspaceExtensibleGroup>();
_wo = w_eg.getTarget(PlantEquipmentOperation_HeatingLoadExtensibleFields::RangeEquipmentListName);
ASSERT_TRUE(_wo.is_initialized());
WorkspaceObject idf_peq_list = _wo.get();

// Should have one equipment on it: WaterHeater
ASSERT_EQ(1, idf_peq_list.extensibleGroups().size());
IdfExtensibleGroup idf_eg(idf_peq_list.extensibleGroups()[0]);

ASSERT_EQ(wh.nameString(), idf_eg.getString(PlantEquipmentListExtensibleFields::EquipmentName).get());
}
}

// Now add connect it on a supply side Source plant
PlantLoop sourceSidePlantLoop(m);
EXPECT_TRUE(sourceSidePlantLoop.addSupplyBranchForComponent(wh));

ASSERT_TRUE(wh.supplyInletModelObject());
ASSERT_TRUE(wh.supplyOutletModelObject());
ASSERT_TRUE(wh.demandInletModelObject());
ASSERT_TRUE(wh.demandOutletModelObject());

{
Workspace w = ft.translateModel(m);

EXPECT_EQ(2, w.getObjectsByType(IddObjectType::PlantLoop).size());

std::vector<WorkspaceObject> idfWHMixeds(w.getObjectsByType(IddObjectType::WaterHeater_Mixed));
ASSERT_EQ(1, idfWHMixeds.size());
WorkspaceObject idfWHMixed(idfWHMixeds[0]);

EXPECT_FALSE(idfWHMixed.isEmpty(WaterHeater_MixedFields::UseSideInletNodeName));
EXPECT_FALSE(idfWHMixed.isEmpty(WaterHeater_MixedFields::UseSideOutletNodeName));
EXPECT_FALSE(idfWHMixed.isEmpty(WaterHeater_MixedFields::SourceSideInletNodeName));
EXPECT_FALSE(idfWHMixed.isEmpty(WaterHeater_MixedFields::SourceSideOutletNodeName));

EXPECT_EQ(wh.supplyInletModelObject()->nameString(), idfWHMixed.getString(WaterHeater_MixedFields::UseSideInletNodeName, false).get());
EXPECT_EQ(wh.supplyOutletModelObject()->nameString(), idfWHMixed.getString(WaterHeater_MixedFields::UseSideOutletNodeName, false).get());
EXPECT_EQ(useSideOutletNodeName, idfWHMixed.getString(WaterHeater_MixedFields::UseSideOutletNodeName, false).get()); // doesn't change
EXPECT_EQ(wh.demandInletModelObject()->nameString(), idfWHMixed.getString(WaterHeater_MixedFields::SourceSideInletNodeName, false).get());
EXPECT_EQ(wh.demandOutletModelObject()->nameString(), idfWHMixed.getString(WaterHeater_MixedFields::SourceSideOutletNodeName, false).get());

// Check PlantEquipmentOperationScheme for Use Side AND Source side
for (const auto& plant : {useSidePlantLoop, sourceSidePlantLoop}) {
auto _wo = w.getObjectByTypeAndName(IddObjectType::PlantLoop, plant.nameString());
ASSERT_TRUE(_wo.is_initialized());
WorkspaceObject idf_coolingPlant = _wo.get();
WorkspaceObject idf_plant_op = idf_coolingPlant.getTarget(PlantLoopFields::PlantEquipmentOperationSchemeName).get();

// Should have created a Heating Load one only
ASSERT_EQ(1, idf_plant_op.extensibleGroups().size());
auto w_eg = idf_plant_op.extensibleGroups()[0].cast<WorkspaceExtensibleGroup>();
ASSERT_EQ("PlantEquipmentOperation:HeatingLoad", w_eg.getString(PlantEquipmentOperationSchemesExtensibleFields::ControlSchemeObjectType).get());

// Get the Operation Scheme
_wo = w_eg.getTarget(PlantEquipmentOperationSchemesExtensibleFields::ControlSchemeName);
ASSERT_TRUE(_wo.is_initialized());
WorkspaceObject idf_op_scheme = _wo.get();

// Get the Plant Equipment List of this HeatingLoad scheme
// There should only be one Load Range
ASSERT_EQ(1, idf_op_scheme.extensibleGroups().size());
// Load range 1
w_eg = idf_op_scheme.extensibleGroups()[0].cast<WorkspaceExtensibleGroup>();
_wo = w_eg.getTarget(PlantEquipmentOperation_HeatingLoadExtensibleFields::RangeEquipmentListName);
ASSERT_TRUE(_wo.is_initialized());
WorkspaceObject idf_peq_list = _wo.get();

// Should have one equipment on it: WaterHeater
ASSERT_EQ(1, idf_peq_list.extensibleGroups().size());
IdfExtensibleGroup idf_eg(idf_peq_list.extensibleGroups()[0]);

ASSERT_EQ(wh.nameString(), idf_eg.getString(PlantEquipmentListExtensibleFields::EquipmentName).get());
}
}
}
140 changes: 140 additions & 0 deletions src/energyplus/Test/WaterHeaterStratified_GTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,23 @@

#include "../../model/PlantLoop.hpp"
#include "../../model/PlantLoop_Impl.hpp"
#include "../../model/PipeAdiabatic.hpp"
#include "../../model/PipeAdiabatic_Impl.hpp"
#include "../../model/Node.hpp"
#include "../../model/Node_Impl.hpp"

#include "../../utilities/idf/IdfFile.hpp"
#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"

#include <utilities/idd/WaterHeater_Stratified_FieldEnums.hxx>
#include <utilities/idd/PlantLoop_FieldEnums.hxx>
#include <utilities/idd/PlantEquipmentList_FieldEnums.hxx>
#include <utilities/idd/PlantEquipmentOperationSchemes_FieldEnums.hxx>
#include <utilities/idd/PlantEquipmentOperation_HeatingLoad_FieldEnums.hxx>
#include <utilities/idd/IddEnums.hxx>

using namespace openstudio::energyplus;
Expand Down Expand Up @@ -110,3 +119,134 @@ TEST_F(EnergyPlusFixture, ForwardTranslatorWaterHeaterStratified_Condition) {
EXPECT_EQ(1u, w.getObjectsByType(IddObjectType::WaterHeater_Stratified).size());
}
}

TEST_F(EnergyPlusFixture, ForwardTranslatorWaterHeaterStratified_PlantLoopConnections) {
ForwardTranslator ft;
Model m;

WaterHeaterStratified wh(m);

PlantLoop useSidePlantLoop(m);

EXPECT_TRUE(useSidePlantLoop.addSupplyBranchForComponent(wh));
std::string useSideOutletNodeName;
{
Workspace w = ft.translateModel(m);

EXPECT_EQ(1, w.getObjectsByType(IddObjectType::PlantLoop).size());

std::vector<WorkspaceObject> idfWHStratifieds(w.getObjectsByType(IddObjectType::WaterHeater_Stratified));
ASSERT_EQ(1, idfWHStratifieds.size());
WorkspaceObject idfWHStratified(idfWHStratifieds[0]);

EXPECT_FALSE(idfWHStratified.isEmpty(WaterHeater_StratifiedFields::UseSideInletNodeName));
ASSERT_FALSE(idfWHStratified.isEmpty(WaterHeater_StratifiedFields::UseSideOutletNodeName));
useSideOutletNodeName = idfWHStratified.getString(WaterHeater_StratifiedFields::UseSideOutletNodeName, false).get();
EXPECT_NE("", useSideOutletNodeName);

EXPECT_TRUE(idfWHStratified.isEmpty(WaterHeater_StratifiedFields::SourceSideInletNodeName));
EXPECT_TRUE(idfWHStratified.isEmpty(WaterHeater_StratifiedFields::SourceSideOutletNodeName));

EXPECT_EQ("", idfWHStratified.getString(WaterHeater_StratifiedFields::SourceSideInletNodeName, false).get());
EXPECT_EQ("", idfWHStratified.getString(WaterHeater_StratifiedFields::SourceSideOutletNodeName, false).get());

// Check PlantEquipmentOperationScheme for Use Side
{
auto _wo = w.getObjectByTypeAndName(IddObjectType::PlantLoop, useSidePlantLoop.nameString());
ASSERT_TRUE(_wo.is_initialized());
WorkspaceObject idf_coolingPlant = _wo.get();
WorkspaceObject idf_plant_op = idf_coolingPlant.getTarget(PlantLoopFields::PlantEquipmentOperationSchemeName).get();

// Should have created a Heating Load one only
ASSERT_EQ(1, idf_plant_op.extensibleGroups().size());
auto w_eg = idf_plant_op.extensibleGroups()[0].cast<WorkspaceExtensibleGroup>();
ASSERT_EQ("PlantEquipmentOperation:HeatingLoad", w_eg.getString(PlantEquipmentOperationSchemesExtensibleFields::ControlSchemeObjectType).get());

// Get the Operation Scheme
_wo = w_eg.getTarget(PlantEquipmentOperationSchemesExtensibleFields::ControlSchemeName);
ASSERT_TRUE(_wo.is_initialized());
WorkspaceObject idf_op_scheme = _wo.get();

// Get the Plant Equipment List of this HeatingLoad scheme
// There should only be one Load Range
ASSERT_EQ(1, idf_op_scheme.extensibleGroups().size());
// Load range 1
w_eg = idf_op_scheme.extensibleGroups()[0].cast<WorkspaceExtensibleGroup>();
_wo = w_eg.getTarget(PlantEquipmentOperation_HeatingLoadExtensibleFields::RangeEquipmentListName);
ASSERT_TRUE(_wo.is_initialized());
WorkspaceObject idf_peq_list = _wo.get();

// Should have one equipment on it: WaterHeater
ASSERT_EQ(1, idf_peq_list.extensibleGroups().size());
IdfExtensibleGroup idf_eg(idf_peq_list.extensibleGroups()[0]);

ASSERT_EQ(wh.nameString(), idf_eg.getString(PlantEquipmentListExtensibleFields::EquipmentName).get());
}
}

// Now add connect it on a supply side Source plant
PlantLoop sourceSidePlantLoop(m);
EXPECT_TRUE(sourceSidePlantLoop.addSupplyBranchForComponent(wh));

ASSERT_TRUE(wh.supplyInletModelObject());
ASSERT_TRUE(wh.supplyOutletModelObject());
ASSERT_TRUE(wh.demandInletModelObject());
ASSERT_TRUE(wh.demandOutletModelObject());

{
Workspace w = ft.translateModel(m);

EXPECT_EQ(2, w.getObjectsByType(IddObjectType::PlantLoop).size());

std::vector<WorkspaceObject> idfWHStratifieds(w.getObjectsByType(IddObjectType::WaterHeater_Stratified));
ASSERT_EQ(1, idfWHStratifieds.size());
WorkspaceObject idfWHStratified(idfWHStratifieds[0]);

EXPECT_FALSE(idfWHStratified.isEmpty(WaterHeater_StratifiedFields::UseSideInletNodeName));
EXPECT_FALSE(idfWHStratified.isEmpty(WaterHeater_StratifiedFields::UseSideOutletNodeName));
EXPECT_FALSE(idfWHStratified.isEmpty(WaterHeater_StratifiedFields::SourceSideInletNodeName));
EXPECT_FALSE(idfWHStratified.isEmpty(WaterHeater_StratifiedFields::SourceSideOutletNodeName));

EXPECT_EQ(wh.supplyInletModelObject()->nameString(), idfWHStratified.getString(WaterHeater_StratifiedFields::UseSideInletNodeName, false).get());
EXPECT_EQ(wh.supplyOutletModelObject()->nameString(),
idfWHStratified.getString(WaterHeater_StratifiedFields::UseSideOutletNodeName, false).get());
EXPECT_EQ(useSideOutletNodeName, idfWHStratified.getString(WaterHeater_StratifiedFields::UseSideOutletNodeName, false).get()); // doesn't change
EXPECT_EQ(wh.demandInletModelObject()->nameString(),
idfWHStratified.getString(WaterHeater_StratifiedFields::SourceSideInletNodeName, false).get());
EXPECT_EQ(wh.demandOutletModelObject()->nameString(),
idfWHStratified.getString(WaterHeater_StratifiedFields::SourceSideOutletNodeName, false).get());

// Check PlantEquipmentOperationScheme for Use Side AND Source side
for (const auto& plant : {useSidePlantLoop, sourceSidePlantLoop}) {
auto _wo = w.getObjectByTypeAndName(IddObjectType::PlantLoop, plant.nameString());
ASSERT_TRUE(_wo.is_initialized());
WorkspaceObject idf_coolingPlant = _wo.get();
WorkspaceObject idf_plant_op = idf_coolingPlant.getTarget(PlantLoopFields::PlantEquipmentOperationSchemeName).get();

// Should have created a Heating Load one only
ASSERT_EQ(1, idf_plant_op.extensibleGroups().size());
auto w_eg = idf_plant_op.extensibleGroups()[0].cast<WorkspaceExtensibleGroup>();
ASSERT_EQ("PlantEquipmentOperation:HeatingLoad", w_eg.getString(PlantEquipmentOperationSchemesExtensibleFields::ControlSchemeObjectType).get());

// Get the Operation Scheme
_wo = w_eg.getTarget(PlantEquipmentOperationSchemesExtensibleFields::ControlSchemeName);
ASSERT_TRUE(_wo.is_initialized());
WorkspaceObject idf_op_scheme = _wo.get();

// Get the Plant Equipment List of this HeatingLoad scheme
// There should only be one Load Range
ASSERT_EQ(1, idf_op_scheme.extensibleGroups().size());
// Load range 1
w_eg = idf_op_scheme.extensibleGroups()[0].cast<WorkspaceExtensibleGroup>();
_wo = w_eg.getTarget(PlantEquipmentOperation_HeatingLoadExtensibleFields::RangeEquipmentListName);
ASSERT_TRUE(_wo.is_initialized());
WorkspaceObject idf_peq_list = _wo.get();

// Should have one equipment on it: WaterHeater
ASSERT_EQ(1, idf_peq_list.extensibleGroups().size());
IdfExtensibleGroup idf_eg(idf_peq_list.extensibleGroups()[0]);

ASSERT_EQ(wh.nameString(), idf_eg.getString(PlantEquipmentListExtensibleFields::EquipmentName).get());
}
}
}
Loading

0 comments on commit c1cdade

Please # to comment.