Skip to content
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
19 changes: 19 additions & 0 deletions src/EnergyPlus/HVACVariableRefrigerantFlow.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12660,6 +12660,25 @@ void VRFTerminalUnitEquipment::CalcVRF_FluidTCtrl(EnergyPlusData &state,
// now calculate the the mixer outlet air conditions (and the secondary air inlet flow rate). The mixer outlet flow rate has already
// been set above (it is the "inlet" node flow rate)
SimATMixer(state, this->ATMixerName, FirstHVACIteration, this->ATMixerIndex);
// inlet side ATMixer can change the VRF TU inlet condition and therefore the operating air flow rate
if (this->fanOp == HVAC::FanOp::Cycling && PartLoadRatio > 0) {
if (this->HeatingCoilPresent && state.dataHVACVarRefFlow->MaxHeatingCapacity(VRFCond) < Constant::MaxCap) {
// Only fix heating only mode for now
state.dataHVACVarRefFlow->CompOnMassFlow = CalVRFTUAirFlowRate_FluidTCtrl(
state, VRFTUNum, PartLoadRatio, FirstHVACIteration, state.dataHVACVarRefFlow->MaxHeatingCapacity(VRFCond));
} else {
state.dataHVACVarRefFlow->CompOnMassFlow = CalVRFTUAirFlowRate_FluidTCtrl(state, VRFTUNum, PartLoadRatio, FirstHVACIteration, _);
}
if (std::abs(state.dataHVACVarRefFlow->CompOnMassFlow - AirMassFlow) > HVAC::SmallMassFlow) {
SetAverageAirFlow(state, VRFTUNum, PartLoadRatio, OnOffAirFlowRatio);
AirMassFlow = state.dataLoopNodes->Node(VRFTUInletNodeNum).MassFlowRate;
// set the primary air inlet mass flow rate
state.dataLoopNodes->Node(this->ATMixerPriNode).MassFlowRate =
min(state.dataLoopNodes->Node(this->ATMixerPriNode).MassFlowRateMaxAvail,
state.dataLoopNodes->Node(VRFTUInletNodeNum).MassFlowRate);
SimATMixer(state, this->ATMixerName, FirstHVACIteration, this->ATMixerIndex);
}
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

A unit test failure showed that the changes to CalcATMixer could lead to incorrect CompOnMassFlow calculation since the outlet of the inlet side ATMixer is the inlet to the VRF TU and that node condition affects the operating air mass flow rate. This code calculates a new CompOnMassFlow when an inlet side ATMixer exists.

}
} else {
state.dataHVACVarRefFlow->ATMixOutNode2 = 0;
Expand Down
63 changes: 23 additions & 40 deletions src/EnergyPlus/SingleDuct.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5347,57 +5347,40 @@ void CalcATMixer(EnergyPlusData &state, int const SysNum)
// PURPOSE OF THIS SUBROUTINE
// Calculate the mixed air flow and conditions in the air terminal mixer

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Update CalcATMixer according to changes in #11004. This change causes diffs and this branch was created to isolate those diffs associated with the refactor of this function.

// Using/Aliasing
using Psychrometrics::PsyTdbFnHW;

state.dataSingleDuct->PriEnthalpyCATM = state.dataLoopNodes->Node(state.dataSingleDuct->SysATMixer(SysNum).PriInNode).Enthalpy;
state.dataSingleDuct->PriHumRatCATM = state.dataLoopNodes->Node(state.dataSingleDuct->SysATMixer(SysNum).PriInNode).HumRat;
state.dataSingleDuct->PriTempCATM = state.dataLoopNodes->Node(state.dataSingleDuct->SysATMixer(SysNum).PriInNode).Temp;
state.dataSingleDuct->PriMassFlowRateCATM = state.dataLoopNodes->Node(state.dataSingleDuct->SysATMixer(SysNum).PriInNode).MassFlowRate;
auto &atMixer = state.dataSingleDuct->SysATMixer(SysNum);
auto &priInNode = state.dataLoopNodes->Node(atMixer.PriInNode);
auto &secInNode = state.dataLoopNodes->Node(atMixer.SecInNode);
auto &mixedAirOutNode = state.dataLoopNodes->Node(atMixer.MixedAirOutNode);

state.dataSingleDuct->SecAirMassFlowRateCATM = state.dataLoopNodes->Node(state.dataSingleDuct->SysATMixer(SysNum).SecInNode).MassFlowRate;
state.dataSingleDuct->SecAirEnthalpyCATM = state.dataLoopNodes->Node(state.dataSingleDuct->SysATMixer(SysNum).SecInNode).Enthalpy;
state.dataSingleDuct->SecAirHumRatCATM = state.dataLoopNodes->Node(state.dataSingleDuct->SysATMixer(SysNum).SecInNode).HumRat;
state.dataSingleDuct->SecAirTempCATM = state.dataLoopNodes->Node(state.dataSingleDuct->SysATMixer(SysNum).SecInNode).Temp;
Real64 MixedAirMassFlowRate =
(atMixer.type == HVAC::MixerType::SupplySide) ? secInNode.MassFlowRate + priInNode.MassFlowRate : mixedAirOutNode.MassFlowRate;

if (state.dataSingleDuct->SysATMixer(SysNum).type == HVAC::MixerType::SupplySide) {
state.dataSingleDuct->MixedAirMassFlowRateCATM = state.dataSingleDuct->SecAirMassFlowRateCATM + state.dataSingleDuct->PriMassFlowRateCATM;
} else {
if (atMixer.type == HVAC::MixerType::InletSide) {
// for inlet side mixer, the mixed air flow has been set, but we don't know the secondary flow
state.dataSingleDuct->MixedAirMassFlowRateCATM =
state.dataLoopNodes->Node(state.dataSingleDuct->SysATMixer(SysNum).MixedAirOutNode).MassFlowRate;
state.dataSingleDuct->SecAirMassFlowRateCATM =
max(state.dataSingleDuct->MixedAirMassFlowRateCATM - state.dataSingleDuct->PriMassFlowRateCATM, 0.0);
state.dataLoopNodes->Node(state.dataSingleDuct->SysATMixer(SysNum).SecInNode).MassFlowRate = state.dataSingleDuct->SecAirMassFlowRateCATM;
if (std::abs(state.dataSingleDuct->PriMassFlowRateCATM + state.dataSingleDuct->SecAirMassFlowRateCATM -
state.dataSingleDuct->MixedAirMassFlowRateCATM) > SmallMassFlow) {
ShowSevereError(
state,
format("CalcATMixer: Invalid mass flow rates in AirTerminal:SingleDuct:Mixer={}", state.dataSingleDuct->SysATMixer(SysNum).Name));
secInNode.MassFlowRate = max(MixedAirMassFlowRate - priInNode.MassFlowRate, 0.0);
if (std::abs(priInNode.MassFlowRate + secInNode.MassFlowRate - MixedAirMassFlowRate) > SmallMassFlow) {
ShowSevereError(state, format("CalcATMixer: Invalid mass flow rates in AirTerminal:SingleDuct:Mixer={}", atMixer.Name));
ShowContinueErrorTimeStamp(state,
format("Primary mass flow rate={:.6R}Secondary mass flow rate={:.6R}Mixed mass flow rate={:.6R}",
state.dataSingleDuct->PriMassFlowRateCATM,
state.dataSingleDuct->SecAirMassFlowRateCATM,
state.dataSingleDuct->MixedAirMassFlowRateCATM));
priInNode.MassFlowRate,
secInNode.MassFlowRate,
MixedAirMassFlowRate));
ShowFatalError(state, "Simulation terminates.");
}
}
// now calculate the mixed (outlet) conditions
if (state.dataSingleDuct->MixedAirMassFlowRateCATM > 0.0) {
state.dataSingleDuct->MixedAirEnthalpyCATM = (state.dataSingleDuct->SecAirMassFlowRateCATM * state.dataSingleDuct->SecAirEnthalpyCATM +
state.dataSingleDuct->PriMassFlowRateCATM * state.dataSingleDuct->PriEnthalpyCATM) /
state.dataSingleDuct->MixedAirMassFlowRateCATM;
state.dataSingleDuct->MixedAirHumRatCATM = (state.dataSingleDuct->SecAirMassFlowRateCATM * state.dataSingleDuct->SecAirHumRatCATM +
state.dataSingleDuct->PriMassFlowRateCATM * state.dataSingleDuct->PriHumRatCATM) /
state.dataSingleDuct->MixedAirMassFlowRateCATM;
if ((atMixer.MixedAirMassFlowRate = MixedAirMassFlowRate) > 0.0) {
Real64 MixedAirEnthalpy = (secInNode.MassFlowRate * secInNode.Enthalpy + priInNode.MassFlowRate * priInNode.Enthalpy) / MixedAirMassFlowRate;
Real64 MixedAirHumRat = (secInNode.MassFlowRate * secInNode.HumRat + priInNode.MassFlowRate * priInNode.HumRat) / MixedAirMassFlowRate;
// Mixed air temperature is calculated from the mixed air enthalpy and humidity ratio.
state.dataSingleDuct->MixedAirTempCATM = PsyTdbFnHW(state.dataSingleDuct->MixedAirEnthalpyCATM, state.dataSingleDuct->MixedAirHumRatCATM);
atMixer.MixedAirTemp = Psychrometrics::PsyTdbFnHW(MixedAirEnthalpy, MixedAirHumRat);
atMixer.MixedAirEnthalpy = MixedAirEnthalpy;
atMixer.MixedAirHumRat = MixedAirHumRat;
} else {
atMixer.MixedAirEnthalpy = priInNode.Enthalpy;
atMixer.MixedAirHumRat = priInNode.HumRat;
atMixer.MixedAirTemp = priInNode.Temp;
}

state.dataSingleDuct->SysATMixer(SysNum).MixedAirMassFlowRate = state.dataSingleDuct->MixedAirMassFlowRateCATM;
state.dataSingleDuct->SysATMixer(SysNum).MixedAirEnthalpy = state.dataSingleDuct->MixedAirEnthalpyCATM;
state.dataSingleDuct->SysATMixer(SysNum).MixedAirHumRat = state.dataSingleDuct->MixedAirHumRatCATM;
state.dataSingleDuct->SysATMixer(SysNum).MixedAirTemp = state.dataSingleDuct->MixedAirTempCATM;
}

void UpdateATMixer(EnergyPlusData &state, int const SysNum)
Expand Down
14 changes: 0 additions & 14 deletions src/EnergyPlus/SingleDuct.hh
Original file line number Diff line number Diff line change
Expand Up @@ -403,20 +403,6 @@ struct SingleDuctData : BaseGlobalStruct
Real64 ZoneTempSCV = 0.0; // Zone temperature [C]
Real64 QMax2SCV = 0.0;
int SysNumSATM = 0;
Real64 PriMassFlowRateCATM = 0.0;
Real64 PriEnthalpyCATM = 0.0;
Real64 PriHumRatCATM = 0.0;
Real64 PriTempCATM = 0.0;

Real64 SecAirMassFlowRateCATM = 0.0;
Real64 SecAirEnthalpyCATM = 0.0;
Real64 SecAirHumRatCATM = 0.0;
Real64 SecAirTempCATM = 0.0;

Real64 MixedAirMassFlowRateCATM = 0.0;
Real64 MixedAirEnthalpyCATM = 0.0;
Real64 MixedAirHumRatCATM = 0.0;
Real64 MixedAirTempCATM = 0.0;
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Eliminate state variables used only in function CalcATMixer.

Copy link
Member

Choose a reason for hiding this comment

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

This is very very very nice. Thanks.


Real64 ZoneTempSDAT = 0.0; // zone air temperature [C]
Real64 MaxHeatTempSDAT = 0.0; // maximum supply air temperature [C]
Expand Down
3 changes: 2 additions & 1 deletion tst/EnergyPlus/unit/AirTerminalSingleDuctMixer.unit.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3314,7 +3314,7 @@ TEST_F(EnergyPlusFixture, AirTerminalSingleDuctMixer_SimVRF_ATMSupplySide)
// check the terminal air mixer outlet air mass flow rate
ATMixerOutletMassFlowRate = SecondaryAirMassFlowRate + PrimaryAirMassFlowRate;
ASSERT_EQ(ATMixerOutletMassFlowRate, state->dataSingleDuct->SysATMixer(1).MixedAirMassFlowRate);
// check the cooling output delivered is within 2.0 Watt of zone cooling load
// check the cooling output delivered is within 4.0 Watt of zone cooling load
ASSERT_NEAR(QZnReq, QUnitOutVRFTU, 4.0);
}

Expand Down Expand Up @@ -5094,6 +5094,7 @@ TEST_F(EnergyPlusFixture, AirTerminalSingleDuctMixer_SimVRFfluidCntrl_ATMInletSi
ASSERT_EQ(HVACInletMassFlowRate, state->dataSingleDuct->SysATMixer(1).MixedAirMassFlowRate);
// check the cooling output delivered is within 5.0 Watt of zone cooling load
ASSERT_NEAR(QZnReq, QUnitOutVRFTU, 5.0);
EXPECT_NEAR(0.965, state->dataDXCoils->DXCoil(1).PartLoadRatio, 0.001);
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This unit test highlighted the fact that the inlet side ATMixer can affect the operating air mass flow rate of the VRF_FluidTCtrl model.

}

TEST_F(EnergyPlusFixture, AirTerminalSingleDuctMixer_SimVRFfluidCntrl_ATMSupplySide)
Expand Down
Loading