-
Notifications
You must be signed in to change notification settings - Fork 398
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
Better humidity control for chilled water coils and for AirloopHVAC:UnitarySystem #7215
Changes from 4 commits
cb6f108
3adf350
865c9f0
53543cb
7683df8
6c08857
119c5bc
9451557
d136c4c
56330bd
ee06f4e
0bd833d
3f5a7e2
4471a4e
c029acf
7fda469
7883673
040fa15
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4441,7 +4441,7 @@ namespace ReportSizingManager { | |
int PeakLoadType; | ||
int DDAtTotPeak; | ||
int TimeStepAtTotPeak; | ||
int TimeStepAtPeak; | ||
int TimeStepAtPeak(0); | ||
Real64 ZoneCoolLoadSum(0); // sum of zone cooling loads at the peak [W] | ||
Real64 AvgZoneTemp(0); // average zone temperature [C] | ||
Real64 AvgSupTemp; // average supply temperature for bypass control [C] | ||
|
@@ -4451,23 +4451,28 @@ namespace ReportSizingManager { | |
CoolCapCtrl = SysSizInput(SysNum).CoolCapControl; | ||
PeakLoadType = SysSizInput(SysNum).CoolingPeakLoadType; | ||
DDAtSensPeak = SysSizPeakDDNum(SysNum).SensCoolPeakDD; | ||
TimeStepAtSensPeak = SysSizPeakDDNum(SysNum).TimeStepAtSensCoolPk(DDAtSensPeak); | ||
DDAtFlowPeak = SysSizPeakDDNum(SysNum).CoolFlowPeakDD; | ||
TimeStepAtFlowPeak = SysSizPeakDDNum(SysNum).TimeStepAtCoolFlowPk(DDAtFlowPeak); | ||
DDAtTotPeak = SysSizPeakDDNum(SysNum).TotCoolPeakDD; | ||
TimeStepAtTotPeak = SysSizPeakDDNum(SysNum).TimeStepAtTotCoolPk(DDAtTotPeak); | ||
if (DDAtSensPeak > 0) { | ||
TimeStepAtSensPeak = SysSizPeakDDNum(SysNum).TimeStepAtSensCoolPk(DDAtSensPeak); | ||
DDAtFlowPeak = SysSizPeakDDNum(SysNum).CoolFlowPeakDD; | ||
TimeStepAtFlowPeak = SysSizPeakDDNum(SysNum).TimeStepAtCoolFlowPk(DDAtFlowPeak); | ||
DDAtTotPeak = SysSizPeakDDNum(SysNum).TotCoolPeakDD; | ||
TimeStepAtTotPeak = SysSizPeakDDNum(SysNum).TimeStepAtTotCoolPk(DDAtTotPeak); | ||
|
||
if (PeakLoadType == TotalCoolingLoad) { | ||
TimeStepAtPeak = TimeStepAtTotPeak; | ||
} else { | ||
TimeStepAtPeak = TimeStepAtSensPeak; | ||
if (PeakLoadType == TotalCoolingLoad) { | ||
TimeStepAtPeak = TimeStepAtTotPeak; | ||
} else { | ||
TimeStepAtPeak = TimeStepAtSensPeak; | ||
} | ||
} | ||
if (CoolCapCtrl == VAV) { | ||
DesExitTemp = FinalSysSizing(SysNum).CoolSupTemp; | ||
DesFlow = FinalSysSizing(SysNum).MassFlowAtCoolPeak / StdRhoAir; | ||
} else if (CoolCapCtrl == OnOff) { | ||
DesExitTemp = FinalSysSizing(SysNum).CoolSupTemp; | ||
DesFlow = DataAirFlowUsedForSizing; | ||
} else if (TimeStepAtPeak == 0) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. TimeStepAtPeak can't be 0 if VAV or OnOff fan control is used? If so then this line won't get hit. This IF test should be first in list? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, I see. You put this IF test before those that use TimeStepAtPeak. |
||
ShowFatalError("GetCoilDesFlow: AirLoopHVAC=" + SysSizInput(SysNum).AirPriLoopName + | ||
" Central Cooling Capacity Control Method requires zone thermostats to calculate timestep loads."); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can still have a no design load condition (and therefore a 0 for time step at peak) even though a Tstat is used. Remember when zone return temp at heating peak was 0 and TU coils weren't sizing correctly? It's the combination of Tstat temp (i.e., zone temp during sizing) and supply air temp that yields a non-zero zone mass flow rate. Isn't there another way to know if a Tstat is used? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You're right, even with a tstat, there could be zero peak. So, should these methods throw a warning if there's no peak day/time and revert to one of the other methods? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe change the warning text to say exactly what has happened (inside the else if's below) and revert to sizing with CoolSupTemp and MassFlowAtCoolPeak? |
||
} else if (CoolCapCtrl == VT) { | ||
if (FinalSysSizing(SysNum).CoolingPeakLoadType == SensibleCoolingLoad) { | ||
ZoneCoolLoadSum = CalcSysSizing(SysNum).SumZoneCoolLoadSeq(TimeStepAtPeak); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2864,6 +2864,9 @@ namespace SimAirServingZones { | |
// E.g., actuator inlet water flow | ||
for (int AirLoopControlNum = 1; AirLoopControlNum <= PrimaryAirSystem(AirLoopNum).NumControllers; ++AirLoopControlNum) { | ||
|
||
// For temperature and humidity control reset humidity control override | ||
HVACControllers::ControllerProps(PrimaryAirSystem(AirLoopNum).ControllerIndex(AirLoopControlNum)).HumRatCtrlOverride = false; | ||
|
||
// BypassOAController is true here since we do not want to simulate the controller if it has already been simulated in the OA system | ||
// ControllerConvergedFlag is returned true here for water coils in OA system | ||
ManageControllers(PrimaryAirSystem(AirLoopNum).ControllerName(AirLoopControlNum), | ||
|
@@ -2960,6 +2963,31 @@ namespace SimAirServingZones { | |
// not converge | ||
ControllerConvergedFlag = PrimaryAirSystem(AirLoopNum).ControlConverged(AirLoopControlNum); | ||
IsUpToDateFlag = true; | ||
} else { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This will require multiple more iterations of the air loop components. Wouldn't it be better to use the lesser of T and TdpFw as the temperature set point up at line 1283 - 1289 of HVACControllers? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can try that on a separate branch, but I think it will over-dehumidify. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Or use T and TdpFw as a trigger to choose which set point to use, temperature or humidity ratio. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, don't need to try that. The humidity ratio setpoint is 0.011388 which is roughly Tdp=15.9C. There are many hours where the coil can meet the humidity ratio setpoint with a leaving temperature of 16-17C, and there are many hours where the leaving air is saturated. That's why this needs to switch gears and can't just use Tdp. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, how can Tdp come out lower than supply air T? If a dry coil then yes, but a wet coil? Not your problem at this point. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 'cause the water temp is well below Tdp, and some of the air bypasses the coil, so the resulting mix can be drier than saturation. |
||
{ | ||
auto &thisController(HVACControllers::ControllerProps(PrimaryAirSystem(AirLoopNum).ControllerIndex(AirLoopControlNum))); | ||
if (thisController.ControlVar == HVACControllers::iTemperatureAndHumidityRatio) { | ||
// For temperature and humidity control, after temperature control is converged, check if humidity setpoint is met | ||
if (!thisController.HumRatCtrlOverride) { | ||
if (Node(thisController.SensedNode).HumRat > (Node(thisController.SensedNode).HumRatMax + thisController.Offset)) { | ||
// Turn on humdity control and restart controller | ||
ControllerConvergedFlag = false; | ||
thisController.HumRatCtrlOverride = true; | ||
IsUpToDateFlag = false; | ||
ManageControllers(PrimaryAirSystem(AirLoopNum).ControllerName(AirLoopControlNum), | ||
PrimaryAirSystem(AirLoopNum).ControllerIndex(AirLoopControlNum), | ||
FirstHVACIteration, | ||
AirLoopNum, | ||
iControllerOpWarmRestart, | ||
ControllerConvergedFlag, | ||
IsUpToDateFlag, | ||
BypassOAController, | ||
AllowWarmRestartFlag); | ||
SimAirLoopComponents(AirLoopNum, FirstHVACIteration); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
} // End of the Convergence Iteration | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10406,7 +10406,7 @@ namespace UnitarySystems { | |
// and if coolReheat, check hum rat as well | ||
if (((NoLoadTempOut - DesOutTemp) < Acc) && ((NoLoadHumRatOut - DesOutHumRat) < HumRatAcc)) { | ||
PartLoadFrac = 0.0; | ||
} else if (SensibleLoad) { // need to turn on compressor to see if load is met | ||
} else { // need to turn on compressor to see if load is met | ||
PartLoadFrac = 1.0; | ||
CompOn = 1; | ||
m_WSHPRuntimeFrac = 1.0; | ||
|
@@ -10571,7 +10571,9 @@ namespace UnitarySystems { | |
(this->m_TESOpMode == PackagedThermalStorageCoil::OffMode || | ||
this->m_TESOpMode == PackagedThermalStorageCoil::ChargeOnlyMode)) { | ||
PartLoadFrac = 0.0; | ||
} else { | ||
} else if (!SensibleLoad) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Highlights an issue with all coils types when no sensible load exists and a latent load does. Logic at top of function could skip sensible PLR calcs and go directly to latent calcs. Sensible calcs are inside of if(SensibleLoad || LatentLoad) block. |
||
PartLoadFrac = 0.0; | ||
} else if (SensibleLoad) { | ||
|
||
Par[9] = double(AirLoopNum); | ||
Par[10] = 0.0; | ||
|
@@ -10866,6 +10868,7 @@ namespace UnitarySystems { | |
FullOutput = DataLoopNode::Node(InletNode).MassFlowRate * | ||
(Psychrometrics::PsyHFnTdbW(DataLoopNode::Node(OutletNode).Temp, DataLoopNode::Node(OutletNode).HumRat) - | ||
Psychrometrics::PsyHFnTdbW(DataLoopNode::Node(InletNode).Temp, DataLoopNode::Node(OutletNode).HumRat)); | ||
FullLoadHumRatOut = DataLoopNode::Node(OutletNode).HumRat; | ||
|
||
// Check to see if the system can meet the load with the compressor off | ||
// If NoOutput is lower than (more cooling than required) or very near the ReqOutput, do not run the compressor | ||
|
@@ -10906,6 +10909,7 @@ namespace UnitarySystems { | |
FullOutput = DataLoopNode::Node(InletNode).MassFlowRate * | ||
(Psychrometrics::PsyHFnTdbW(DataLoopNode::Node(OutletNode).Temp, DataLoopNode::Node(InletNode).HumRat) - | ||
Psychrometrics::PsyHFnTdbW(DataLoopNode::Node(InletNode).Temp, DataLoopNode::Node(InletNode).HumRat)); | ||
FullLoadHumRatOut = DataLoopNode::Node(OutletNode).HumRat; | ||
|
||
// Since we are cooling, we expect FullOutput to be < 0 and FullOutput < NoCoolOutput | ||
// Check that this is the case; IF not set PartLoadFrac = 0.0 (off) and return | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be nice to be able to trigger a tighter tolerance only when HumRatCtrlOverride = true.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried that first but it didn't work. There's some initial setup step that I couldn't find that includes the offset.