Skip to content

Commit

Permalink
Allow ZoneHVAC:WindowAirConditioner along AFN simulations.
Browse files Browse the repository at this point in the history
  • Loading branch information
lymereJ committed Jul 22, 2024
1 parent 15f6491 commit dd7dbee
Show file tree
Hide file tree
Showing 4 changed files with 183 additions and 0 deletions.
14 changes: 14 additions & 0 deletions src/EnergyPlus/AirflowNetwork/src/Solver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@
#include <EnergyPlus/ThermalComfort.hh>
#include <EnergyPlus/UtilityRoutines.hh>
#include <EnergyPlus/WaterThermalTanks.hh>
#include <EnergyPlus/WindowAC.hh>
#include <EnergyPlus/ZoneDehumidifier.hh>
#include <EnergyPlus/ZoneTempPredictorCorrector.hh>

Expand Down Expand Up @@ -10143,6 +10144,7 @@ namespace AirflowNetwork {
using SplitterComponent::GetSplitterNodeNumbers;
using SplitterComponent::GetSplitterOutletNumber;
using WaterThermalTanks::GetHeatPumpWaterHeaterNodeNumber;
using WindowAC::GetWindowACNodeNumber;
using ZoneDehumidifier::GetZoneDehumidifierNodeNumber;

// SUBROUTINE PARAMETER DEFINITIONS:
Expand All @@ -10161,6 +10163,7 @@ namespace AirflowNetwork {

bool HPWHFound(false); // Flag for HPWH identification
bool StandaloneERVFound(false); // Flag for Standalone ERV (ZoneHVAC:EnergyRecoveryVentilator) identification
bool WindowACFound(false); // Flag for Window AC (ZoneHVAC:WindowAirConditioner) identification

// Validate supply and return connections
NodeFound.dimension(m_state.dataLoopNodes->NumOfNodes, false);
Expand Down Expand Up @@ -10273,6 +10276,12 @@ namespace AirflowNetwork {
NodeFound(i) = true;
StandaloneERVFound = true;
}

// Skip Window AC with no OA
if (GetWindowACNodeNumber(m_state, i)) {
NodeFound(i) = true;
WindowACFound = true;
}
}

for (int zoneNum = 1; zoneNum <= m_state.dataGlobal->NumOfZones; ++zoneNum) {
Expand Down Expand Up @@ -10413,6 +10422,11 @@ namespace AirflowNetwork {
format(RoutineName) + "A ZoneHVAC:EnergyRecoveryVentilator is simulated along with an AirflowNetwork but is not "
"included in the AirflowNetwork.");
}
if (WindowACFound) {
ShowWarningError(m_state,
format(RoutineName) + "A ZoneHVAC:WindowAirConditioner is simulated along with an AirflowNetwork but is not "
"included in the AirflowNetwork.");
}
NodeFound.deallocate();

// Assign AirLoop Number to every node and linkage
Expand Down
30 changes: 30 additions & 0 deletions src/EnergyPlus/WindowAC.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1499,6 +1499,36 @@ namespace WindowAC {
} // WindAC(WindACNum)%DXCoilType_Num == CoilDX_CoolingHXAssisted && *
}

bool GetWindowACNodeNumber(EnergyPlusData &state, int const NodeNumber)
{
if (state.dataWindowAC->GetWindowACInputFlag) {
GetWindowAC(state);
state.dataWindowAC->GetWindowACInputFlag = false;
}

bool windowACOutdoorAir = false;

for (int windowACIndex = 1; windowACIndex <= state.dataWindowAC->NumWindAC; ++windowACIndex) {
auto &windowAC = state.dataWindowAC->WindAC(windowACIndex);
if (windowAC.OutAirVolFlow == 0) {
windowACOutdoorAir = true;
} else {
windowACOutdoorAir = false;
}
int FanInletNodeIndex = 0;
int FanOutletNodeIndex = 0;
FanInletNodeIndex = state.dataFans->fans(windowAC.FanIndex)->inletNodeNum;
FanOutletNodeIndex = state.dataFans->fans(windowAC.FanIndex)->outletNodeNum;

if (windowACOutdoorAir &&
(NodeNumber == windowAC.OutsideAirNode || NodeNumber == windowAC.MixedAirNode || NodeNumber == windowAC.AirReliefNode ||
NodeNumber == FanInletNodeIndex || NodeNumber == FanOutletNodeIndex || NodeNumber == windowAC.AirInNode)) {
return true;
}
}
return false;
}

int GetWindowACZoneInletAirNode(EnergyPlusData &state, int const WindACNum)
{

Expand Down
2 changes: 2 additions & 0 deletions src/EnergyPlus/WindowAC.hh
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,8 @@ namespace WindowAC {
bool &HXUnitOn // Used to control HX heat recovery as needed
);

bool GetWindowACNodeNumber(EnergyPlusData &state, int const WindACNum);

int GetWindowACZoneInletAirNode(EnergyPlusData &state, int const WindACNum);

int GetWindowACOutAirNode(EnergyPlusData &state, int const WindACNum);
Expand Down
137 changes: 137 additions & 0 deletions tst/EnergyPlus/unit/AirflowNetworkHVAC.unit.cc
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
#include <EnergyPlus/SurfaceGeometry.hh>
#include <EnergyPlus/UtilityRoutines.hh>
#include <EnergyPlus/WaterThermalTanks.hh>
#include <EnergyPlus/WindowAC.hh>
#include <EnergyPlus/ZoneAirLoopEquipmentManager.hh>
#include <EnergyPlus/ZoneEquipmentManager.hh>
#include <EnergyPlus/ZoneTempPredictorCorrector.hh>
Expand Down Expand Up @@ -19767,4 +19768,140 @@ TEST_F(EnergyPlusFixture, AirflowNetwork_ZoneOrderTest)
state->afn->AirflowNetworkNodeData(3).EPlusNodeNum = 0;
}

TEST_F(EnergyPlusFixture, AirflowNetwork_TestZoneEqpSupportZoneWindowAC)
{
// Create zone
state->dataGlobal->NumOfZones = 1;
state->dataHeatBal->Zone.allocate(1);
state->dataHeatBal->Zone(1).Name = "ZONE 1";

// Create surfaces
state->dataSurface->Surface.allocate(1);
state->dataSurface->Surface(1).Name = "ZN004:ROOF001";
state->dataSurface->Surface(1).Zone = 1;
state->dataSurface->Surface(1).ZoneName = "ZONE 1";
state->dataSurface->Surface(1).Azimuth = 0.0;
state->dataSurface->Surface(1).ExtBoundCond = 0;
state->dataSurface->Surface(1).HeatTransSurf = true;
state->dataSurface->Surface(1).Tilt = 180.0;
state->dataSurface->Surface(1).Sides = 4;
state->dataSurface->Surface(1).Name = "ZN004:ROOF002";
state->dataSurface->Surface(1).Zone = 1;
state->dataSurface->Surface(1).ZoneName = "ZONE 1";
state->dataSurface->Surface(1).Azimuth = 0.0;
state->dataSurface->Surface(1).ExtBoundCond = 0;
state->dataSurface->Surface(1).HeatTransSurf = true;
state->dataSurface->Surface(1).Tilt = 180.0;
state->dataSurface->Surface(1).Sides = 4;

state->dataSurface->Surface(1).OriginalClass = DataSurfaces::SurfaceClass::Window;

// Create air system
state->dataAirSystemsData->PrimaryAirSystems.allocate(1);
state->dataAirSystemsData->PrimaryAirSystems(1).NumBranches = 1;
state->dataAirSystemsData->PrimaryAirSystems(1).Branch.allocate(1);
state->dataAirSystemsData->PrimaryAirSystems(1).Branch(1).TotalComponents = 1;
state->dataAirSystemsData->PrimaryAirSystems(1).Branch(1).Comp.allocate(1);
state->dataAirSystemsData->PrimaryAirSystems(1).Branch(1).Comp(1).TypeOf = "Fan:ConstantVolume";

// Create air nodes
state->dataLoopNodes->NumOfNodes = 3;
state->dataLoopNodes->Node.allocate(3);
state->dataLoopNodes->Node(1).FluidType = DataLoopNode::NodeFluidType::Air;
state->dataLoopNodes->Node(2).FluidType = DataLoopNode::NodeFluidType::Air;
state->dataLoopNodes->Node(3).FluidType = DataLoopNode::NodeFluidType::Air;
state->dataLoopNodes->NodeID.allocate(3);
state->dataLoopNodes->NodeID(1) = "ZONE 1 AIR NODE";
bool errFlag{false};
BranchNodeConnections::RegisterNodeConnection(*state,
1,
"ZONE 1 AIR NODE",
DataLoopNode::ConnectionObjectType::FanOnOff,
"Object1",
DataLoopNode::ConnectionType::ZoneNode,
NodeInputManager::CompFluidStream::Primary,
false,
errFlag);
EXPECT_FALSE(errFlag);

// Connect zone to air node
state->dataZoneEquip->ZoneEquipConfig.allocate(1);
state->dataZoneEquip->ZoneEquipConfig(1).IsControlled = true;
state->dataZoneEquip->ZoneEquipConfig(1).ZoneName = "ZONE 1";
state->dataZoneEquip->ZoneEquipConfig(1).ZoneNode = 1;
state->dataZoneEquip->ZoneEquipConfig(1).NumInletNodes = 0;
state->dataZoneEquip->ZoneEquipConfig(1).NumReturnNodes = 0;
state->dataZoneEquip->ZoneEquipConfig(1).IsControlled = true;

// One AirflowNetwork:MultiZone:Zone object
state->afn->AirflowNetworkNumOfZones = 1;
state->afn->MultizoneZoneData.allocate(1);
state->afn->MultizoneZoneData(1).ZoneNum = 1;
state->afn->MultizoneZoneData(1).ZoneName = "ZONE 1";

// Assume only one AirflowNetwork:Distribution:Node object is set for the Zone Air Node
state->afn->AirflowNetworkNumOfNodes = 1;
state->afn->AirflowNetworkNodeData.allocate(1);
state->afn->AirflowNetworkNodeData(1).Name = "ZONE 1";
state->afn->AirflowNetworkNodeData(1).EPlusZoneNum = 1;

state->afn->SplitterNodeNumbers.allocate(2);
state->afn->SplitterNodeNumbers(1) = 0;
state->afn->SplitterNodeNumbers(2) = 0;

// Set flag to support zone equipment
state->afn->simulation_control.allow_unsupported_zone_equipment = true;

// Create Fans
Real64 supplyFlowRate = 0.005;
Real64 exhaustFlowRate = 0.005;

auto *fan1 = new Fans::FanComponent;
fan1->Name = "SupplyFan";

fan1->inletNodeNum = 2;
fan1->outletNodeNum = 3;
fan1->type = HVAC::FanType::OnOff;
fan1->maxAirFlowRate = supplyFlowRate;

state->dataFans->fans.push_back(fan1);
state->dataFans->fanMap.insert_or_assign(fan1->Name, state->dataFans->fans.size());

state->dataLoopNodes->NodeID(2) = "SupplyFanInletNode";
BranchNodeConnections::RegisterNodeConnection(*state,
2,
state->dataLoopNodes->NodeID(2),
DataLoopNode::ConnectionObjectType::FanOnOff,
state->dataFans->fans(1)->Name,
DataLoopNode::ConnectionType::Inlet,
NodeInputManager::CompFluidStream::Primary,
false,
errFlag);
state->dataLoopNodes->NodeID(3) = "SupplyFanOutletNode";
BranchNodeConnections::RegisterNodeConnection(*state,
3,
state->dataLoopNodes->NodeID(3),
DataLoopNode::ConnectionObjectType::FanOnOff,
state->dataFans->fans(1)->Name,
DataLoopNode::ConnectionType::Outlet,
NodeInputManager::CompFluidStream::Primary,
false,
errFlag);

// Create Window AC
state->dataWindowAC->WindAC.allocate(1);
state->dataWindowAC->GetWindowACInputFlag = false;
state->dataWindowAC->NumWindAC = 1;
state->dataWindowAC->WindAC(1).OutAirVolFlow = 0.0;
state->dataWindowAC->WindAC(1).FanName = state->dataFans->fans(1)->Name;
state->dataWindowAC->WindAC(1).FanIndex = 1;

// Check validation and expected warning
state->afn->validate_distribution();

EXPECT_TRUE(compare_err_stream(" ** Warning ** AirflowNetwork::Solver::validate_distribution: A ZoneHVAC:WindowAirConditioner is simulated "
"along with an AirflowNetwork but is not included in the AirflowNetwork.\n",
true));
}

} // namespace EnergyPlus

5 comments on commit dd7dbee

@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.

allow_windowac_afn (lymereJ) - x86_64-MacOS-10.18-clang-15.0.0: OK (3645 of 3645 tests passed, 0 test warnings)

Build Badge Test Badge

@nrel-bot
Copy link

Choose a reason for hiding this comment

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

allow_windowac_afn (lymereJ) - Win64-Windows-10-VisualStudio-16: OK (2853 of 2853 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.

allow_windowac_afn (lymereJ) - x86_64-Linux-Ubuntu-22.04-gcc-11.4: OK (3686 of 3686 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.

allow_windowac_afn (lymereJ) - x86_64-Linux-Ubuntu-22.04-gcc-11.4-UnitTestsCoverage-Debug: OK (2061 of 2061 tests passed, 0 test warnings)

Build Badge Test Badge Coverage Badge

@nrel-bot-2b
Copy link

Choose a reason for hiding this comment

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

allow_windowac_afn (lymereJ) - x86_64-Linux-Ubuntu-22.04-gcc-11.4-IntegrationCoverage-Debug: OK (795 of 795 tests passed, 0 test warnings)

Build Badge Test Badge Coverage Badge

Please sign in to comment.