Skip to content

Commit

Permalink
Merge pull request #10199 from NREL/defect9740
Browse files Browse the repository at this point in the history
HeatPump:PlantLoop:EIR:* objects using the same inlet/outlet source node is incorrect 9740
  • Loading branch information
Myoldmopar authored Sep 20, 2023
2 parents f9f43d8 + 5f813c9 commit 1c467df
Show file tree
Hide file tree
Showing 2 changed files with 199 additions and 3 deletions.
11 changes: 8 additions & 3 deletions src/EnergyPlus/PlantLoopHeatPumpEIR.cc
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
#include <EnergyPlus/General.hh>
#include <EnergyPlus/InputProcessing/InputProcessor.hh>
#include <EnergyPlus/NodeInputManager.hh>
#include <EnergyPlus/OutAirNodeManager.hh>
#include <EnergyPlus/OutputProcessor.hh>
#include <EnergyPlus/OutputReportPredefined.hh>
#include <EnergyPlus/Plant/DataPlant.hh>
Expand Down Expand Up @@ -1272,7 +1273,6 @@ void EIRPlantLoopHeatPump::processInputForEIRPLHP(EnergyPlusData &state)
std::string condenserType = UtilityRoutines::makeUPPER(fields.at("condenser_type").get<std::string>());
std::string sourceSideInletNodeName = UtilityRoutines::makeUPPER(fields.at("source_side_inlet_node_name").get<std::string>());
std::string sourceSideOutletNodeName = UtilityRoutines::makeUPPER(fields.at("source_side_outlet_node_name").get<std::string>());

thisPLHP.companionCoilName = UtilityRoutines::makeUPPER(
state.dataInputProcessing->inputProcessor->getAlphaFieldValue(fields, schemaProps, "companion_heat_pump_name"));

Expand Down Expand Up @@ -1469,8 +1469,13 @@ void EIRPlantLoopHeatPump::processInputForEIRPLHP(EnergyPlusData &state)
} else if (condenserType == "AIRSOURCE") {
thisPLHP.airSource = true;
condenserNodeType = DataLoopNode::NodeFluidType::Air;
condenserNodeConnectionType_Inlet = DataLoopNode::ConnectionType::OutsideAir;
condenserNodeConnectionType_Outlet = DataLoopNode::ConnectionType::OutsideAir;
condenserNodeConnectionType_Inlet = DataLoopNode::ConnectionType::Inlet;
condenserNodeConnectionType_Outlet = DataLoopNode::ConnectionType::Outlet;
if (sourceSideInletNodeName == sourceSideOutletNodeName) {
ShowSevereError(state, format("PlantLoopHeatPump {} has the same inlet and outlet node.", thisObjectName));
ShowContinueError(state, format("Node Name: {}", sourceSideInletNodeName));
errorsFound = true;
}
} else {
// Again, this should be protected by the input processor
ShowErrorMessage(
Expand Down
191 changes: 191 additions & 0 deletions tst/EnergyPlus/unit/PlantLoopHeatPumpEIR.unit.cc
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,12 @@

// EnergyPlus Headers
#include "Fixtures/EnergyPlusFixture.hh"
#include <EnergyPlus/BranchNodeConnections.hh>
#include <EnergyPlus/Data/EnergyPlusData.hh>
#include <EnergyPlus/DataErrorTracking.hh>
#include <EnergyPlus/DataHVACGlobals.hh>
#include <EnergyPlus/DataSizing.hh>
#include <EnergyPlus/OutAirNodeManager.hh>
#include <EnergyPlus/OutputProcessor.hh>
#include <EnergyPlus/Plant/DataPlant.hh>
#include <EnergyPlus/PlantLoopHeatPumpEIR.hh>
Expand Down Expand Up @@ -400,6 +402,195 @@ TEST_F(EnergyPlusFixture, CatchErrorsOnBadCurves)
EXPECT_THROW(EIRPlantLoopHeatPump::factory(*state, DataPlant::PlantEquipmentType::HeatPumpEIRCooling, "HP COOLING SIDE"), std::runtime_error);
}

TEST_F(EnergyPlusFixture, processInputForEIRPLHP_TestAirSourceDuplicateNodes)
{
std::string const idf_objects = delimited_string({"HeatPump:PlantLoop:EIR:Cooling,",
" hp cooling side,",
" node 1,",
" node 2,",
" AirSource,",
" node 3,",
" node 3,",
" ,",
" 0.001,",
" 0.001,",
" 1000,",
" 3.14,",
" ,",
" dummyCurve,",
" dummyCurve,",
" dummyCurve;",
"Curve:Linear,",
" dummyCurve,",
" 1,",
" 0,",
" 1,",
" 1;"});
ASSERT_TRUE(process_idf(idf_objects));

// set up the plant loops
// first the load side
state->dataPlnt->TotNumLoops = 2;
state->dataPlnt->PlantLoop.allocate(2);

state->dataPlnt->PlantLoop(1).LoopSide(DataPlant::LoopSideLocation::Supply).TotalBranches = 1;
state->dataPlnt->PlantLoop(1).LoopSide(DataPlant::LoopSideLocation::Supply).Branch.allocate(1);
state->dataPlnt->PlantLoop(1).LoopSide(DataPlant::LoopSideLocation::Supply).Branch(1).TotalComponents = 1;
state->dataPlnt->PlantLoop(1).LoopSide(DataPlant::LoopSideLocation::Supply).Branch(1).Comp.allocate(1);
auto &PLHPPlantLoadSideComp = state->dataPlnt->PlantLoop(1).LoopSide(DataPlant::LoopSideLocation::Supply).Branch(1).Comp(1);
PLHPPlantLoadSideComp.Type = DataPlant::PlantEquipmentType::HeatPumpEIRCooling;
// then the source side

state->dataPlnt->PlantLoop(2).LoopSide(DataPlant::LoopSideLocation::Demand).TotalBranches = 1;
state->dataPlnt->PlantLoop(2).LoopSide(DataPlant::LoopSideLocation::Demand).Branch.allocate(1);
state->dataPlnt->PlantLoop(2).LoopSide(DataPlant::LoopSideLocation::Demand).Branch(1).TotalComponents = 1;
state->dataPlnt->PlantLoop(2).LoopSide(DataPlant::LoopSideLocation::Demand).Branch(1).Comp.allocate(1);
auto &PLHPPlantLoadSourceComp = state->dataPlnt->PlantLoop(2).LoopSide(DataPlant::LoopSideLocation::Demand).Branch(1).Comp(1);
PLHPPlantLoadSourceComp.Type = DataPlant::PlantEquipmentType::HeatPumpEIRCooling;

// the init call expects a "from" calling point
PlantLocation myLocation = PlantLocation(1, DataPlant::LoopSideLocation::Supply, 1, 1);

// call the factory with a valid name to trigger reading inputs
// expects fatal error due to same node names
EXPECT_THROW(EIRPlantLoopHeatPump::factory(*state, DataPlant::PlantEquipmentType::HeatPumpEIRCooling, "HP COOLING SIDE");, std::runtime_error);
// expect error related to same node names
std::string error_msg = delimited_string({
" ** Severe ** PlantLoopHeatPump hp cooling side has the same inlet and outlet node.",
" ** ~~~ ** Node Name: NODE 3",
" ** Fatal ** Previous EIR PLHP errors cause program termination",
" ...Summary of Errors that led to program termination:",
" ..... Reference severe error count=1",
" ..... Last severe error=PlantLoopHeatPump hp cooling side has the same inlet and outlet node.",
});
EXPECT_TRUE(compare_err_stream(error_msg));
}

TEST_F(EnergyPlusFixture, processInputForEIRPLHP_TestAirSourceOANode)
{
std::string const idf_objects = delimited_string({"HeatPump:PlantLoop:EIR:Cooling,",
" hp cooling side,",
" node 1,",
" node 2,",
" AirSource,",
" node 3,",
" node 4,",
" ,",
" Autosize,",
" Autosize,",
" Autosize,",
" 1.0,",
" 1,",
" dummyCurve,",
" dummyCurve,",
" dummyCurve;",
"Curve:Linear,",
" dummyCurve,",
" 1,",
" 0,",
" 1,",
" 1;",
"OutdoorAir:NodeList,",
" node 3;"});
ASSERT_TRUE(process_idf(idf_objects));

// set up the plant loops
// first the load side
state->dataPlnt->TotNumLoops = 2;
state->dataPlnt->PlantLoop.allocate(2);

state->dataPlnt->PlantLoop(1).LoopSide(DataPlant::LoopSideLocation::Supply).TotalBranches = 1;
state->dataPlnt->PlantLoop(1).LoopSide(DataPlant::LoopSideLocation::Supply).Branch.allocate(1);
state->dataPlnt->PlantLoop(1).LoopSide(DataPlant::LoopSideLocation::Supply).Branch(1).TotalComponents = 1;
state->dataPlnt->PlantLoop(1).LoopSide(DataPlant::LoopSideLocation::Supply).Branch(1).Comp.allocate(1);
auto &PLHPPlantLoadSideComp = state->dataPlnt->PlantLoop(1).LoopSide(DataPlant::LoopSideLocation::Supply).Branch(1).Comp(1);
PLHPPlantLoadSideComp.Type = DataPlant::PlantEquipmentType::HeatPumpEIRCooling;
// then the source side

state->dataPlnt->PlantLoop(2).LoopSide(DataPlant::LoopSideLocation::Demand).TotalBranches = 1;
state->dataPlnt->PlantLoop(2).LoopSide(DataPlant::LoopSideLocation::Demand).Branch.allocate(1);
state->dataPlnt->PlantLoop(2).LoopSide(DataPlant::LoopSideLocation::Demand).Branch(1).TotalComponents = 1;
state->dataPlnt->PlantLoop(2).LoopSide(DataPlant::LoopSideLocation::Demand).Branch(1).Comp.allocate(1);
auto &PLHPPlantLoadSourceComp = state->dataPlnt->PlantLoop(2).LoopSide(DataPlant::LoopSideLocation::Demand).Branch(1).Comp(1);
PLHPPlantLoadSourceComp.Type = DataPlant::PlantEquipmentType::HeatPumpEIRCooling;

// the init call expects a "from" calling point
PlantLocation myLocation = PlantLocation(1, DataPlant::LoopSideLocation::Supply, 1, 1);
// setup the outdoor air nodes
OutAirNodeManager::SetOutAirNodes(*state);
// call the factory with a valid name to trigger reading inputs
// expects fatal error due to same node names
EIRPlantLoopHeatPump::factory(*state, DataPlant::PlantEquipmentType::HeatPumpEIRCooling, "HP COOLING SIDE");
EXPECT_TRUE(compare_err_stream(""));
}

TEST_F(EnergyPlusFixture, processInputForEIRPLHP_TestAirSourceNoOANode)
{
std::string const idf_objects = delimited_string({"HeatPump:PlantLoop:EIR:Cooling,",
" hp cooling side,",
" node 1,",
" node 2,",
" AirSource,",
" node 3,",
" node 4,",
" ,",
" Autosize,",
" Autosize,",
" Autosize,",
" 1.0,",
" 1,",
" dummyCurve,",
" dummyCurve,",
" dummyCurve;",
"Curve:Linear,",
" dummyCurve,",
" 1,",
" 0,",
" 1,",
" 1;"});
ASSERT_TRUE(process_idf(idf_objects));

// set up the plant loops
// first the load side
state->dataPlnt->TotNumLoops = 2;
state->dataPlnt->PlantLoop.allocate(2);

state->dataPlnt->PlantLoop(1).LoopSide(DataPlant::LoopSideLocation::Supply).TotalBranches = 1;
state->dataPlnt->PlantLoop(1).LoopSide(DataPlant::LoopSideLocation::Supply).Branch.allocate(1);
state->dataPlnt->PlantLoop(1).LoopSide(DataPlant::LoopSideLocation::Supply).Branch(1).TotalComponents = 1;
state->dataPlnt->PlantLoop(1).LoopSide(DataPlant::LoopSideLocation::Supply).Branch(1).Comp.allocate(1);
auto &PLHPPlantLoadSideComp = state->dataPlnt->PlantLoop(1).LoopSide(DataPlant::LoopSideLocation::Supply).Branch(1).Comp(1);
PLHPPlantLoadSideComp.Type = DataPlant::PlantEquipmentType::HeatPumpEIRCooling;
// then the source side

state->dataPlnt->PlantLoop(2).LoopSide(DataPlant::LoopSideLocation::Demand).TotalBranches = 1;
state->dataPlnt->PlantLoop(2).LoopSide(DataPlant::LoopSideLocation::Demand).Branch.allocate(1);
state->dataPlnt->PlantLoop(2).LoopSide(DataPlant::LoopSideLocation::Demand).Branch(1).TotalComponents = 1;
state->dataPlnt->PlantLoop(2).LoopSide(DataPlant::LoopSideLocation::Demand).Branch(1).Comp.allocate(1);
auto &PLHPPlantLoadSourceComp = state->dataPlnt->PlantLoop(2).LoopSide(DataPlant::LoopSideLocation::Demand).Branch(1).Comp(1);
PLHPPlantLoadSourceComp.Type = DataPlant::PlantEquipmentType::HeatPumpEIRCooling;

// the init call expects a "from" calling point
PlantLocation myLocation = PlantLocation(1, DataPlant::LoopSideLocation::Supply, 1, 1);

// call the factory with a valid name to trigger reading inputs
// expects fatal error due to same node names
EIRPlantLoopHeatPump::factory(*state, DataPlant::PlantEquipmentType::HeatPumpEIRCooling, "HP COOLING SIDE");
bool ErrFound = false;
BranchNodeConnections::CheckNodeConnections(*state, ErrFound);
// expect error related to OA node not being an OutdoorAirNode
std::string error_msg = delimited_string({
" ** Severe ** Node Connection Error, Node=\"NODE 1\", Inlet node did not find an appropriate matching \"outlet\" node.",
" ** ~~~ ** If this is an outdoor air inlet node, it must be listed in an OutdoorAir:Node or OutdoorAir:NodeList object.",
" ** ~~~ ** Reference Object=HeatPump:PlantLoop:EIR:Cooling, Name=HP COOLING SIDE",
" ** Severe ** Node Connection Error, Node=\"NODE 3\", Inlet node did not find an appropriate matching \"outlet\" node.",
" ** ~~~ ** If this is an outdoor air inlet node, it must be listed in an OutdoorAir:Node or OutdoorAir:NodeList object.",
" ** ~~~ ** Reference Object=HeatPump:PlantLoop:EIR:Cooling, Name=HP COOLING SIDE",

});
EXPECT_TRUE(compare_err_stream(error_msg));
}

TEST_F(EnergyPlusFixture, Initialization)
{
std::string const idf_objects = delimited_string({"HeatPump:PlantLoop:EIR:Cooling,",
Expand Down

5 comments on commit 1c467df

@nrel-bot
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

develop (Myoldmopar) - Win64-Windows-10-VisualStudio-16: Build Failed

Failures:\n

API Test Summary

  • Failed: 10
  • notrun: 5

ConvertInputFormat Test Summary

  • Failed: 4
  • notrun: 1

integration Test Summary

  • Passed: 2
  • Failed: 786

Build Badge Test Badge

@nrel-bot-2c
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

develop (Myoldmopar) - x86_64-Linux-Ubuntu-22.04-gcc-11.4: OK (2769 of 2769 tests passed, 0 test warnings)

Build Badge Test Badge

@nrel-bot-3
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

develop (Myoldmopar) - x86_64-MacOS-10.17-clang-14.0.0: OK (2748 of 2748 tests passed, 0 test warnings)

Build Badge Test Badge

@nrel-bot-2c
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

develop (Myoldmopar) - x86_64-Linux-Ubuntu-22.04-gcc-11.4-UnitTestsCoverage-Debug: OK (1961 of 1961 tests passed, 0 test warnings)

Build Badge Test Badge Coverage Badge

@nrel-bot-2c
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

develop (Myoldmopar) - x86_64-Linux-Ubuntu-22.04-gcc-11.4-IntegrationCoverage-Debug: OK (789 of 789 tests passed, 0 test warnings)

Build Badge Test Badge Coverage Badge

Please sign in to comment.