Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Zone Air Terminal VAV Damper Position variable is always zero for VAV Rheat with VS Fan air terminal #7696

Merged
merged 7 commits into from
Jan 22, 2020
Merged
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
16 changes: 16 additions & 0 deletions src/EnergyPlus/SingleDuct.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4463,6 +4463,7 @@ namespace SingleDuct {
Par(7) = double(FanOp);
Par(8) = QTotLoad;
SolveRoot(UnitFlowToler, 50, SolFlag, FracDelivered, VAVVSHCFanOnResidual, 0.0, 1.0, Par);
MassFlow = Node(SysInletNode).MassFlowRate;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Set MassFlow variable to current inlet node mass flow rate to avoid uninitialized variable warning. MassFlow local variable is now used to calculate damper position further down in this function.

if (SolFlag == -1) {
if (Sys(SysNum).IterationLimit == 0) {
ShowWarningError("Heating coil control failed in VS VAV terminal unit " + Sys(SysNum).SysName);
Expand Down Expand Up @@ -4493,6 +4494,21 @@ namespace SingleDuct {
FanOp = 0;
CalcVAVVS(SysNum, FirstHVACIteration, ZoneNodeNum, HCType, 0.0, 0.0, FanType, MassFlow, FanOp, QDelivered);
}

// Move mass flow rates to the damper outlet node
SysOutlet(SysNum).AirMassFlowRate = MassFlow;
SysOutlet(SysNum).AirMassFlowRateMaxAvail = SysInlet(SysNum).AirMassFlowRateMaxAvail;
SysOutlet(SysNum).AirMassFlowRateMinAvail = SysInlet(SysNum).AirMassFlowRateMinAvail;

// calculate VAV damper Position.
if (Sys(SysNum).AirMassFlowRateMax == 0.0) {
Sys(SysNum).DamperPosition = 0.0;
} else {
Sys(SysNum).DamperPosition = MassFlow / Sys(SysNum).AirMassFlowRateMax;
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

calculate the vav damper position for reporting purpose

Copy link
Member

Choose a reason for hiding this comment

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

👍 I see the unit test below exercises this calculation.

// update the air terminal outlet node data
UpdateSys(SysNum);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Allows to propagate the node information such as CO2 and contaminant.

Copy link
Member

Choose a reason for hiding this comment

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

Surprising this doesn't throw any more diffs, but no worries.


}

void SimConstVol(int const SysNum, bool const FirstHVACIteration, int const ZoneNum, int const ZoneNodeNum)
Expand Down
177 changes: 177 additions & 0 deletions tst/EnergyPlus/unit/AirTerminalSingleDuct.unit.cc
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
#include <EnergyPlus/DataLoopNode.hh>
#include <EnergyPlus/DataZoneEnergyDemands.hh>
#include <EnergyPlus/DataZoneEquipment.hh>
#include <EnergyPlus/General.hh>
#include <EnergyPlus/HVACSingleDuctInduc.hh>
#include <EnergyPlus/HeatBalanceManager.hh>
#include <EnergyPlus/MixedAir.hh>
Expand Down Expand Up @@ -682,4 +683,180 @@ TEST_F(EnergyPlusFixture, AirTerminalSingleDuctVAVReheat_NormalActionTest)
EXPECT_EQ(1.0, Sys(SysNum).AirMassFlowRateMax);
}

TEST_F(EnergyPlusFixture, SingleDuctVAVReheatVSFan_DamperPositionTest)
{
std::string const idf_objects = delimited_string({
" Zone,",
" Thermal Zone; !- Name",

" ZoneHVAC:EquipmentConnections,",
" Thermal Zone, !- Zone Name",
" Thermal Zone Equipment, !- Zone Conditioning Equipment List Name",
" Zone 1 In Node, !- Zone Air Inlet Node or NodeList Name",
" , !- Zone Air Exhaust Node or NodeList Name",
" Zone 1 Air Node, !- Zone Air Node Name",
" Zone 1 Return Node; !- Zone Return Air Node Name",

" ZoneHVAC:EquipmentList,",
" Thermal Zone Equipment, !- Name",
" SequentialLoad, !- Load Distribution Scheme",
" ZoneHVAC:AirDistributionUnit, !- Zone Equipment 1 Object Type",
" ADU VAV Rht VS Fan, !- Zone Equipment 1 Name",
" 1, !- Zone Equipment 1 Cooling Sequence",
" 1; !- Zone Equipment 1 Heating or No-Load Sequence",

" ZoneHVAC:AirDistributionUnit,",
" ADU VAV Rht VS Fan, !- Name",
" Zone 1 In Node, !- Air Distribution Unit Outlet Node Name",
" AirTerminal:SingleDuct:VAV:Reheat:VariableSpeedFan, !- Air Terminal Object Type",
" VAV Rht VS Fan AirTerm; !- Air Terminal Name",

" AirTerminal:SingleDuct:VAV:Reheat:VariableSpeedFan,",
" VAV Rht VS Fan AirTerm, !- Name",
" , !- Availability Schedule Name",
" 1.0, !- Maximum Cooling Air Flow Rate {m3/s}",
" 0.5, !- Maximum Heating Air Flow Rate {m3/s}",
" 0.05, !- Zone Minimum Air Flow Fraction",
" Zone 1 ATU In Node, !- Air Inlet Node Name",
" Zone 1 In Node, !- Air Outlet Node Name",
" Fan:SystemModel, !- Fan Object Type",
" Zone 1 VS Fan, !- Fan Name",
" Coil:Heating:Electric, !- Heating Coil Object Type",
" Zone 1 Reheat Coil, !- Heating Coil Name",
" autosize, !- Maximum Hot Water or Steam Flow Rate {m3/s}",
" 0.0, !- Minimum Hot Water or Steam Flow Rate {m3/s}",
" 0.001; !- Heating Convergence Tolerance",

" Coil:Heating:Electric,",
" Zone 1 Reheat Coil, !- Name",
" , !- Availability Schedule Name",
" 1.0, !- Efficiency",
" autosize, !- Nominal Capacity {W}",
" Reheat Air Inlet Node, !- Air Inlet Node Name",
" Zone 1 In Node; !- Air Outlet Node Name",

" Fan:SystemModel,",
" Zone 1 VS Fan, !- Name",
" , !- Availability Schedule Name",
" Zone 1 ATU In Node, !- Air Inlet Node Name",
" Reheat Air Inlet Node, !- Air Outlet Node Name",
" 1.0, !- Design Maximum Air Flow Rate {m3/s}",
" Continuous, !- Speed Control Method",
" 0.0, !- Electric Power Minimum Flow Rate Fraction",
" 125.0, !- Design Pressure Rise {Pa}",
" 0.9, !- Motor Efficiency",
" 1.0, !- Motor In Air Stream Fraction",
" AUTOSIZE, !- Design Electric Power Consumption {W}",
" TotalEfficiencyAndPressure, !- Design Power Sizing Method",
" , !- Electric Power Per Unit Flow Rate {W/(m3/s)}",
" , !- Electric Power Per Unit Flow Rate Per Unit Pressure {W/((m3/s)-Pa)}",
" 0.7, !- Fan Total Efficiency",
" VAV Fan Curve, !- Electric Power Function of Flow Fraction Curve Name",
" , !- Night Ventilation Mode Pressure Rise {Pa}",
" , !- Night Ventilation Mode Flow Fraction",
" , !- Motor Loss Zone Name",
" , !- Motor Loss Radiative Fraction",
" ATU Fan Energy; !- End-Use Subcategory",

" Curve:Quartic,",
" VAV Fan Curve, !- Name",
" 0.00153028, !- Coefficient1 Constant",
" 0.00520806, !- Coefficient2 x",
" 1.1086242, !- Coefficient3 x**2",
" -.11635563, !- Coefficient4 x**3",
" 0.0, !- Coefficient5 x**4",
" 0.0, !- Minimum Value of x",
" 1.0, !- Maximum Value of x",
" 0.0, !- Minimum Curve Output",
" 1.0, !- Maximum Curve Output",
" Dimensionless, !- Input Unit Type for X",
" Dimensionless; !- Output Unit Type",
});

ASSERT_TRUE(process_idf(idf_objects));
// setup variables for VAV Reheat VS Fan
int SysNum = 1;
int ZoneNum = 1;
int ZoneNodeNum = 1;
int InletNodeNum = 5;
bool ErrorsFound = false;
bool FirstHVACIteration = true;

DataGlobals::NumOfTimeStepInHour = 1;
DataGlobals::MinutesPerTimeStep = 60;
ScheduleManager::ProcessScheduleInput();
ScheduleManager::ScheduleInputProcessed = true;
DataEnvironment::Month = 1;
DataEnvironment::DayOfMonth = 21;
DataGlobals::HourOfDay = 1;
DataGlobals::TimeStep = 1;
DataEnvironment::DSTIndicator = 0;
DataEnvironment::DayOfWeek = 2;
DataEnvironment::HolidayIndex = 0;
DataEnvironment::DayOfYear_Schedule = General::OrdinalDay(DataEnvironment::Month, DataEnvironment::DayOfMonth, 1);
DataEnvironment::StdRhoAir = Psychrometrics::PsyRhoAirFnPbTdbW(101325.0, 20.0, 0.0);
ScheduleManager::UpdateScheduleValues();
DataZoneEnergyDemands::ZoneSysEnergyDemand.allocate(1);
DataHeatBalFanSys::TempControlType.allocate(1);
DataHeatBalFanSys::TempControlType(1) = DataHVACGlobals::DualSetPointWithDeadBand;
HeatBalanceManager::GetZoneData(ErrorsFound);
ASSERT_FALSE(ErrorsFound);
DataZoneEquipment::GetZoneEquipmentData1();
ZoneAirLoopEquipmentManager::GetZoneAirLoopEquipment();
SingleDuct::GetSysInput();
EXPECT_TRUE(compare_err_stream(""));

auto &thisAirTerminal = SingleDuct::Sys(SysNum);
auto &thisAirTerminalOutlet = SingleDuct::SysOutlet(SysNum);

// check VAV reheat VS Fan air terminal inputs
EXPECT_EQ("AirTerminal:SingleDuct:VAV:Reheat:VariableSpeedFan", thisAirTerminal.SysType);
EXPECT_EQ("VAV RHT VS FAN AIRTERM", thisAirTerminal.SysName);
EXPECT_EQ("COIL:HEATING:ELECTRIC", thisAirTerminal.ReheatComp);
EXPECT_EQ("ZONE 1 REHEAT COIL", thisAirTerminal.ReheatName);
EXPECT_EQ("FAN:SYSTEMMODEL", thisAirTerminal.FanType);
EXPECT_EQ("ZONE 1 VS FAN", thisAirTerminal.FanName);
EXPECT_EQ(thisAirTerminal.ZoneMinAirFrac, 0.05);
EXPECT_EQ(thisAirTerminal.MaxAirVolFlowRate, 1.0);
// test 1: 0.05 fraction damper position
Real64 SysMinMassFlowRes = 1.0 * DataEnvironment::StdRhoAir * 0.05;
Real64 SysMaxMassFlowRes = 1.0 * DataEnvironment::StdRhoAir;
DataZoneEnergyDemands::ZoneSysEnergyDemand(1).RemainingOutputRequired = 0.0;
DataLoopNode::Node(InletNodeNum).MassFlowRate = SysMaxMassFlowRes;
DataLoopNode::Node(InletNodeNum).MassFlowRateMaxAvail = SysMaxMassFlowRes;
CurDeadBandOrSetback.allocate(1);
CurDeadBandOrSetback(1) = false;
DataGlobals::BeginEnvrnFlag = true;
FirstHVACIteration = true;
SingleDuct::InitSys(SysNum, FirstHVACIteration);
DataGlobals::BeginEnvrnFlag = false;
FirstHVACIteration = false;
SingleDuct::InitSys(SysNum, FirstHVACIteration);
SingleDuct::SimVAVVS(SysNum, FirstHVACIteration, ZoneNum, ZoneNodeNum);
// check inputs and calculated values for zone air fraction 0.05
EXPECT_EQ(0.05,thisAirTerminal.ZoneMinAirFrac); // user input
EXPECT_EQ(0.05, thisAirTerminal.DamperPosition);
EXPECT_EQ(SysMinMassFlowRes, thisAirTerminal.AirMassFlowRateMax * thisAirTerminal.ZoneMinAirFrac);
EXPECT_EQ(SysMinMassFlowRes, thisAirTerminalOutlet.AirMassFlowRate);

// test 2: 0.10 fraction damper position
thisAirTerminal.ZoneMinAirFrac = 0.10; // modified user input
SysMinMassFlowRes = 1.0 * DataEnvironment::StdRhoAir * 0.10;
DataZoneEnergyDemands::ZoneSysEnergyDemand(1).RemainingOutputRequired = 0.0;
DataLoopNode::Node(InletNodeNum).MassFlowRate = SysMaxMassFlowRes;
DataLoopNode::Node(InletNodeNum).MassFlowRateMaxAvail = SysMaxMassFlowRes;
DataGlobals::BeginEnvrnFlag = true;
FirstHVACIteration = true;
SingleDuct::InitSys(SysNum, FirstHVACIteration);
DataGlobals::BeginEnvrnFlag = false;
FirstHVACIteration = false;
SingleDuct::InitSys(SysNum, FirstHVACIteration);
SingleDuct::SimVAVVS(SysNum, FirstHVACIteration, ZoneNum, ZoneNodeNum);
// check inputs and calculated values for zone air fraction 0.10
EXPECT_EQ(0.10, thisAirTerminal.ZoneMinAirFrac);
EXPECT_EQ(0.10, thisAirTerminal.DamperPosition);
EXPECT_EQ(SysMinMassFlowRes, thisAirTerminal.AirMassFlowRateMax * thisAirTerminal.ZoneMinAirFrac);
EXPECT_EQ(SysMinMassFlowRes, thisAirTerminalOutlet.AirMassFlowRate);
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The unit test checks user inputs and the damper position at the min flow rate. prior to the fix, the thisAirTerminal.DamperPosition variable was always zero.

Copy link
Member

Choose a reason for hiding this comment

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

👍 Great unit test.

} // namespace EnergyPlus