Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -174,13 +174,17 @@ namespace energyplus {

boost::optional<Node> inletNode(const PlantLoop& plantLoop, const HVACComponent& component) {
auto comps = plantLoop.supplyComponents(plantLoop.supplyInletNode(), component);
OS_ASSERT(comps.size() >= 2u);
if (comps.size() < 2u) {
return boost::none;
}
return (comps.end() - 2u)->optionalCast<Node>();
}

boost::optional<Node> outletNode(const PlantLoop& plantLoop, const HVACComponent& component) {
auto comps = plantLoop.supplyComponents(component, plantLoop.supplyOutletNode());
OS_ASSERT(comps.size() >= 2u);
if (comps.size() < 2u) {
return boost::none;
}
return comps[1].optionalCast<Node>();
}

Expand Down Expand Up @@ -437,7 +441,9 @@ namespace energyplus {
for (const auto& comp : subsetCastVector<HVACComponent>(plantLoop.supplyComponents())) {
if (!comp.optionalCast<Node>()) {
if (_isSetpointComponent(plantLoop, comp)) {
result.push_back(operationSchemeComponent(comp));
// Keep comp as-is (not operationSchemeComponent(comp)): inletNode/outletNode/flowrate
// below need the component that's actually on the supply branch.
result.push_back(comp);
}
}
}
Expand Down Expand Up @@ -543,16 +549,21 @@ namespace energyplus {
}

for (auto& setpointComponent : t_setpointComponents) {
// translationComponent may be a containing component (eg: HeatPumpAirToWater), used only
// for translation/naming below; setpointComponent stays the one on the supply branch for
// the inletNode/outletNode/flowrate/componentType lookups.
auto translationComponent = operationSchemeComponent(setpointComponent);

// TODO: @kbenne, Find the right way to deal with this
// For now, "dirty" (?) fix for Generator:MicroTurbine

boost::optional<IdfObject> _idfObject;

if (boost::optional<GeneratorMicroTurbineHeatRecovery> mchpHR = setpointComponent.optionalCast<GeneratorMicroTurbineHeatRecovery>()) {
if (boost::optional<GeneratorMicroTurbineHeatRecovery> mchpHR = translationComponent.optionalCast<GeneratorMicroTurbineHeatRecovery>()) {
GeneratorMicroTurbine mchp = mchpHR->generatorMicroTurbine();
_idfObject = translateAndMapModelObject(mchp);
} else {
_idfObject = translateAndMapModelObject(setpointComponent);
_idfObject = translateAndMapModelObject(translationComponent);
}

OS_ASSERT(_idfObject);
Expand Down
49 changes: 49 additions & 0 deletions src/energyplus/Test/PlantEquipmentOperationSchemes_GTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@
#include "../../model/GroundHeatExchangerHorizontalTrench.hpp"
#include "../../model/GroundHeatExchangerVertical.hpp"
#include "../../model/HeatExchangerFluidToFluid.hpp"
#include "../../model/HeatPumpAirToWater.hpp"
#include "../../model/HeatPumpAirToWaterHeating.hpp"
#include "../../model/HeatPumpAirToWaterFuelFiredHeating.hpp"
#include "../../model/HeatPumpAirToWaterFuelFiredCooling.hpp"
#include "../../model/HeatPumpWaterToWaterEquationFitCooling.hpp"
Expand Down Expand Up @@ -522,6 +524,53 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_PlantEquipmentOperationSchemes_Both_
EXPECT_EQ("Dual", w_eg.getString(PlantEquipmentOperation_ComponentSetpointExtensibleFields::OperationType).get());
}

TEST_F(EnergyPlusFixture, ForwardTranslator_PlantEquipmentOperationSchemes_HeatPumpAirToWaterHeating_ComponentSetpoint) {
// Test for #5665 - segfault when a SetpointManager is on the outlet node of a
// HeatPumpAirToWaterHeating, since it isn't itself on the plant loop (its containing
// HeatPumpAirToWater is translated/named instead, but node lookups need the actual component)

Model m;

HeatPumpAirToWater awhp(m);
HeatPumpAirToWaterHeating awhp_hc(m);
ASSERT_TRUE(awhp.setHeatingOperationMode(awhp_hc));

PlantLoop hwLoop(m);
ASSERT_TRUE(hwLoop.addSupplyBranchForComponent(awhp_hc));

ScheduleConstant sch(m);
SetpointManagerScheduled spm(m, sch);
ASSERT_TRUE(awhp_hc.outletModelObject());
Node outletNode = awhp_hc.outletModelObject()->cast<Node>();
ASSERT_TRUE(spm.addToNode(outletNode));

ForwardTranslator ft;
Workspace w = ft.translateModel(m);

boost::optional<WorkspaceObject> _wo = w.getObjectByTypeAndName(IddObjectType::PlantLoop, hwLoop.name().get());
ASSERT_TRUE(_wo.is_initialized());
WorkspaceObject idf_loop = _wo.get();
WorkspaceObject idf_plant_op = idf_loop.getTarget(PlantLoopFields::PlantEquipmentOperationSchemeName).get();

// HeatPumpAirToWaterHeating is Heating type, so it also lands on the default HeatingLoad scheme
// in addition to the ComponentSetpoint one created because of the SetpointManager
ASSERT_EQ(2u, idf_plant_op.extensibleGroups().size());
auto w_eg = idf_plant_op.extensibleGroups()[1].cast<WorkspaceExtensibleGroup>();
ASSERT_EQ("PlantEquipmentOperation:ComponentSetpoint",
w_eg.getString(PlantEquipmentOperationSchemesExtensibleFields::ControlSchemeObjectType).get());

_wo = w_eg.getTarget(PlantEquipmentOperationSchemesExtensibleFields::ControlSchemeName);
ASSERT_TRUE(_wo.is_initialized());
WorkspaceObject idf_op_scheme = _wo.get();

ASSERT_EQ(1u, idf_op_scheme.extensibleGroups().size());
w_eg = idf_op_scheme.extensibleGroups()[0].cast<WorkspaceExtensibleGroup>();
EXPECT_EQ("HeatPump:AirToWater", w_eg.getString(PlantEquipmentOperation_ComponentSetpointExtensibleFields::EquipmentObjectType).get());
EXPECT_EQ(awhp.nameString(), w_eg.getString(PlantEquipmentOperation_ComponentSetpointExtensibleFields::EquipmentName).get());
EXPECT_TRUE(w_eg.getString(PlantEquipmentOperation_ComponentSetpointExtensibleFields::DemandCalculationNodeName));
EXPECT_TRUE(w_eg.getString(PlantEquipmentOperation_ComponentSetpointExtensibleFields::SetpointNodeName));
}

TEST_F(EnergyPlusFixture, ForwardTranslator_PlantEquipmentOperationSchemes_HeatPumpPlantLoopEIR) {
Model m;

Expand Down