Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2025, The Board of Trustees of the University of Illinois,
2 : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
3 : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
4 : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
5 : // contributors. All rights reserved.
6 : //
7 : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
8 : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
9 : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
10 : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
11 : // derivative works, and perform publicly and display publicly, and to permit others to do so.
12 : //
13 : // Redistribution and use in source and binary forms, with or without modification, are permitted
14 : // provided that the following conditions are met:
15 : //
16 : // (1) Redistributions of source code must retain the above copyright notice, this list of
17 : // conditions and the following disclaimer.
18 : //
19 : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
20 : // conditions and the following disclaimer in the documentation and/or other materials
21 : // provided with the distribution.
22 : //
23 : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
24 : // the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
25 : // used to endorse or promote products derived from this software without specific prior
26 : // written permission.
27 : //
28 : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
29 : // without changes from the version obtained under this License, or (ii) Licensee makes a
30 : // reference solely to the software portion of its product, Licensee must refer to the
31 : // software as "EnergyPlus version X" software, where "X" is the version number Licensee
32 : // obtained under this License and may not use a different name for the software. Except as
33 : // specifically required in this Section (4), Licensee shall not use in a company name, a
34 : // product name, in advertising, publicity, or other promotional activities any name, trade
35 : // name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
36 : // similar designation, without the U.S. Department of Energy's prior written consent.
37 : //
38 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
39 : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
40 : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
41 : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43 : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
45 : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46 : // POSSIBILITY OF SUCH DAMAGE.
47 :
48 : #include <EnergyPlus/Autosizing/CoolingCapacitySizing.hh>
49 : #include <EnergyPlus/CurveManager.hh>
50 : #include <EnergyPlus/Data/EnergyPlusData.hh>
51 : #include <EnergyPlus/DataEnvironment.hh>
52 : #include <EnergyPlus/DataHVACGlobals.hh>
53 : #include <EnergyPlus/Fans.hh>
54 : #include <EnergyPlus/General.hh>
55 : #include <EnergyPlus/GeneralRoutines.hh>
56 : #include <EnergyPlus/Psychrometrics.hh>
57 : #include <EnergyPlus/SimAirServingZones.hh>
58 : #include <EnergyPlus/VariableSpeedCoils.hh>
59 : #include <EnergyPlus/WeatherManager.hh>
60 :
61 : namespace EnergyPlus {
62 :
63 392 : Real64 CoolingCapacitySizer::size(EnergyPlusData &state, Real64 _originalValue, bool &errorsFound)
64 : {
65 392 : if (!this->checkInitialized(state, errorsFound)) {
66 1 : return 0.0;
67 : }
68 391 : this->preSize(state, _originalValue);
69 391 : Real64 DesVolFlow = 0.0;
70 391 : Real64 CoilInTemp = -999.0;
71 391 : Real64 CoilInHumRat = -999.0;
72 391 : Real64 CoilOutTemp = -999.0;
73 391 : Real64 CoilOutHumRat = -999.0;
74 391 : Real64 FanCoolLoad = 0.0;
75 391 : Real64 TotCapTempModFac = 1.0;
76 391 : Real64 DXFlowPerCapMinRatio = 1.0;
77 391 : Real64 DXFlowPerCapMaxRatio = 1.0;
78 :
79 391 : if (this->dataEMSOverrideON) {
80 0 : this->autoSizedValue = this->dataEMSOverride;
81 391 : } else if (this->dataConstantUsedForSizing >= 0 && this->dataFractionUsedForSizing > 0) {
82 : // back and forth if dataConstantUsedForSizing should be > or >= 0 to make this work for AutoCalculate
83 28 : this->autoSizedValue = this->dataConstantUsedForSizing * this->dataFractionUsedForSizing;
84 : } else {
85 363 : if (this->curZoneEqNum > 0) {
86 180 : if (!this->wasAutoSized && !this->sizingDesRunThisZone) {
87 38 : this->autoSizedValue = _originalValue;
88 142 : } else if (this->zoneEqSizing(this->curZoneEqNum).DesignSizeFromParent) {
89 17 : this->autoSizedValue = this->zoneEqSizing(this->curZoneEqNum).DesCoolingLoad;
90 : } else {
91 125 : if (this->zoneEqSizing(this->curZoneEqNum).CoolingCapacity) { // Parent object calculated capacity
92 53 : this->autoSizedValue = this->zoneEqSizing(this->curZoneEqNum).DesCoolingLoad;
93 53 : DesVolFlow = this->dataFlowUsedForSizing;
94 53 : CoilInTemp = state.dataSize->DataCoilSizingAirInTemp;
95 53 : CoilInHumRat = state.dataSize->DataCoilSizingAirInHumRat;
96 53 : CoilOutTemp = state.dataSize->DataCoilSizingAirOutTemp;
97 53 : CoilOutHumRat = state.dataSize->DataCoilSizingAirOutHumRat;
98 53 : FanCoolLoad = state.dataSize->DataCoilSizingFanCoolLoad;
99 53 : TotCapTempModFac = state.dataSize->DataCoilSizingCapFT;
100 : } else {
101 137 : if (Util::SameString(this->compType, "COIL:COOLING:WATER") ||
102 137 : Util::SameString(this->compType, "COIL:COOLING:WATER:DETAILEDGEOMETRY") ||
103 137 : Util::SameString(this->compType, "ZONEHVAC:IDEALLOADSAIRSYSTEM")) {
104 14 : if (this->termUnitIU && (this->curTermUnitSizingNum > 0)) {
105 2 : this->autoSizedValue = this->termUnitSizing(this->curTermUnitSizingNum).DesCoolingLoad;
106 12 : } else if (this->zoneEqFanCoil) {
107 1 : this->autoSizedValue = this->zoneEqSizing(this->curZoneEqNum).DesCoolingLoad;
108 : } else {
109 11 : CoilInTemp = this->finalZoneSizing(this->curZoneEqNum).DesCoolCoilInTemp;
110 11 : CoilInHumRat = this->finalZoneSizing(this->curZoneEqNum).DesCoolCoilInHumRat;
111 11 : CoilOutTemp = min(CoilInTemp, this->finalZoneSizing(this->curZoneEqNum).CoolDesTemp);
112 11 : CoilOutHumRat = min(CoilInHumRat, this->finalZoneSizing(this->curZoneEqNum).CoolDesHumRat);
113 11 : this->autoSizedValue =
114 11 : this->finalZoneSizing(this->curZoneEqNum).DesCoolMassFlow *
115 11 : (Psychrometrics::PsyHFnTdbW(CoilInTemp, CoilInHumRat) - Psychrometrics::PsyHFnTdbW(CoilOutTemp, CoilOutHumRat));
116 11 : DesVolFlow = this->finalZoneSizing(this->curZoneEqNum).DesCoolMassFlow / state.dataEnvrn->StdRhoAir;
117 : // add fan heat to coil load
118 11 : FanCoolLoad += this->calcFanDesHeatGain(DesVolFlow);
119 11 : this->autoSizedValue += FanCoolLoad;
120 : }
121 : } else {
122 58 : DesVolFlow = this->dataFlowUsedForSizing;
123 58 : if (DesVolFlow >= HVAC::SmallAirVolFlow) {
124 : // each of these IFs now seem the same and can be condensed to just CoilInTemp = set() and CoilInHumRat = set()
125 57 : if (state.dataSize->ZoneEqDXCoil) {
126 : // ATMixer has priority over Equipment OA vol flow
127 17 : if (this->zoneEqSizing(this->curZoneEqNum).ATMixerVolFlow > 0.0) { // NEW ATMixer coil sizing method
128 3 : Real64 DesMassFlow = DesVolFlow * state.dataEnvrn->StdRhoAir;
129 3 : CoilInTemp = setCoolCoilInletTempForZoneEqSizing(
130 3 : setOAFracForZoneEqSizing(state, DesMassFlow, zoneEqSizing(this->curZoneEqNum)),
131 3 : zoneEqSizing(this->curZoneEqNum),
132 3 : finalZoneSizing(this->curZoneEqNum));
133 3 : CoilInHumRat = setCoolCoilInletHumRatForZoneEqSizing(
134 3 : setOAFracForZoneEqSizing(state, DesMassFlow, zoneEqSizing(this->curZoneEqNum)),
135 3 : zoneEqSizing(this->curZoneEqNum),
136 3 : finalZoneSizing(this->curZoneEqNum));
137 14 : } else if (this->zoneEqSizing(this->curZoneEqNum).OAVolFlow > 0.0) {
138 6 : CoilInTemp = this->finalZoneSizing(this->curZoneEqNum).DesCoolCoilInTemp;
139 6 : CoilInHumRat = this->finalZoneSizing(this->curZoneEqNum).DesCoolCoilInHumRat;
140 : } else {
141 8 : CoilInTemp = this->finalZoneSizing(this->curZoneEqNum)
142 8 : .ZoneRetTempAtCoolPeak; // Question whether zone equipment should use return temp for sizing
143 8 : CoilInHumRat = this->finalZoneSizing(this->curZoneEqNum).ZoneHumRatAtCoolPeak;
144 : }
145 40 : } else if (this->zoneEqFanCoil) {
146 : // use fan coil flow (i.e., set by parent) or flow used during sizing?
147 8 : Real64 DesMassFlow = this->finalZoneSizing(this->curZoneEqNum).DesCoolMassFlow;
148 8 : CoilInTemp = setCoolCoilInletTempForZoneEqSizing(
149 8 : setOAFracForZoneEqSizing(state, DesMassFlow, zoneEqSizing(this->curZoneEqNum)),
150 8 : zoneEqSizing(this->curZoneEqNum),
151 8 : finalZoneSizing(this->curZoneEqNum));
152 8 : CoilInHumRat = setCoolCoilInletHumRatForZoneEqSizing(
153 8 : setOAFracForZoneEqSizing(state, DesMassFlow, zoneEqSizing(this->curZoneEqNum)),
154 8 : zoneEqSizing(this->curZoneEqNum),
155 8 : finalZoneSizing(this->curZoneEqNum));
156 : } else {
157 32 : CoilInTemp = this->finalZoneSizing(this->curZoneEqNum).DesCoolCoilInTemp;
158 32 : CoilInHumRat = this->finalZoneSizing(this->curZoneEqNum).DesCoolCoilInHumRat;
159 : }
160 57 : CoilOutTemp = min(CoilInTemp, this->finalZoneSizing(this->curZoneEqNum).CoolDesTemp);
161 57 : CoilOutHumRat = min(CoilInHumRat, this->finalZoneSizing(this->curZoneEqNum).CoolDesHumRat);
162 57 : int TimeStepNumAtMax = this->finalZoneSizing(this->curZoneEqNum).TimeStepNumAtCoolMax;
163 57 : int DDNum = this->finalZoneSizing(this->curZoneEqNum).CoolDDNum;
164 57 : Real64 OutTemp = 0.0;
165 57 : if (DDNum > 0 && TimeStepNumAtMax > 0) {
166 36 : OutTemp = state.dataSize->DesDayWeath(DDNum).Temp(TimeStepNumAtMax);
167 : }
168 57 : if (this->dataCoolCoilType == HVAC::Coil_CoolingWaterToAirHPVSEquationFit) {
169 1 : OutTemp = VariableSpeedCoils::GetVSCoilRatedSourceTemp(state, this->dataCoolCoilIndex);
170 : }
171 57 : Real64 CoilInEnth = Psychrometrics::PsyHFnTdbW(CoilInTemp, CoilInHumRat);
172 57 : Real64 CoilOutEnth = Psychrometrics::PsyHFnTdbW(CoilOutTemp, CoilOutHumRat);
173 57 : Real64 PeakCoilLoad = max(0.0, (state.dataEnvrn->StdRhoAir * DesVolFlow * (CoilInEnth - CoilOutEnth)));
174 : // add fan heat to coil load
175 57 : FanCoolLoad += this->calcFanDesHeatGain(DesVolFlow);
176 57 : PeakCoilLoad += FanCoolLoad;
177 57 : Real64 CpAir = Psychrometrics::PsyCpAirFnW(CoilInHumRat);
178 : // adjust coil inlet/outlet temp with fan temperature rise
179 57 : if (this->dataDesAccountForFanHeat) {
180 57 : if (state.dataSize->DataFanPlacement == HVAC::FanPlace::BlowThru) {
181 21 : CoilInTemp += FanCoolLoad / (CpAir * state.dataEnvrn->StdRhoAir * DesVolFlow);
182 36 : } else if (state.dataSize->DataFanPlacement == HVAC::FanPlace::DrawThru) {
183 16 : CoilOutTemp -= FanCoolLoad / (CpAir * state.dataEnvrn->StdRhoAir * DesVolFlow);
184 : }
185 : }
186 : Real64 CoilInWetBulb =
187 57 : Psychrometrics::PsyTwbFnTdbWPb(state, CoilInTemp, CoilInHumRat, state.dataEnvrn->StdBaroPress, this->callingRoutine);
188 57 : if (this->dataTotCapCurveIndex > 0) {
189 26 : switch (state.dataCurveManager->curves(this->dataTotCapCurveIndex)->numDims) {
190 6 : case 1:
191 6 : TotCapTempModFac = Curve::CurveValue(state, this->dataTotCapCurveIndex, CoilInWetBulb);
192 6 : break;
193 20 : case 2:
194 : default: // this default allows the simulation to continue, but will issue a warning, should be removed eventually
195 20 : TotCapTempModFac = Curve::CurveValue(state, this->dataTotCapCurveIndex, CoilInWetBulb, OutTemp);
196 20 : break;
197 : }
198 31 : } else if (this->dataTotCapCurveValue > 0) {
199 1 : TotCapTempModFac = this->dataTotCapCurveValue;
200 : } else {
201 30 : TotCapTempModFac = 1.0;
202 : }
203 57 : if (TotCapTempModFac > 0.0) {
204 57 : this->autoSizedValue = PeakCoilLoad / TotCapTempModFac;
205 : } else {
206 0 : this->autoSizedValue = PeakCoilLoad;
207 : }
208 : // save these conditions to use when this->zoneEqSizing(this->curZoneEqNum).CoolingCapacity = true
209 57 : state.dataSize->DataCoilSizingAirInTemp = CoilInTemp;
210 57 : state.dataSize->DataCoilSizingAirInHumRat = CoilInHumRat;
211 57 : state.dataSize->DataCoilSizingAirOutTemp = CoilOutTemp;
212 57 : state.dataSize->DataCoilSizingAirOutHumRat = CoilOutHumRat;
213 57 : state.dataSize->DataCoilSizingFanCoolLoad = FanCoolLoad;
214 57 : state.dataSize->DataCoilSizingCapFT = TotCapTempModFac;
215 : } else {
216 1 : this->autoSizedValue = 0.0;
217 1 : CoilOutTemp = -999.0;
218 : }
219 : }
220 : }
221 125 : this->autoSizedValue = this->autoSizedValue * this->dataFracOfAutosizedCoolingCapacity;
222 125 : this->dataDesAccountForFanHeat = true; // reset for next water coil
223 125 : if (state.dataGlobal->DisplayExtraWarnings && this->autoSizedValue <= 0.0) {
224 0 : ShowWarningMessage(state,
225 0 : this->callingRoutine + ": Potential issue with equipment sizing for " + this->compType + ' ' + this->compName);
226 0 : ShowContinueError(state, format("...Rated Total Cooling Capacity = {:.2T} [W]", this->autoSizedValue));
227 0 : if (this->zoneEqSizing(this->curZoneEqNum).CoolingCapacity) {
228 0 : ShowContinueError(state,
229 0 : format("...Capacity passed by parent object to size child component = {:.2T} [W]", this->autoSizedValue));
230 : } else {
231 0 : if (Util::SameString(this->compType, "COIL:COOLING:WATER") ||
232 0 : Util::SameString(this->compType, "COIL:COOLING:WATER:DETAILEDGEOMETRY") ||
233 0 : Util::SameString(this->compType, "ZONEHVAC:IDEALLOADSAIRSYSTEM")) {
234 0 : if (this->termUnitIU || this->zoneEqFanCoil) {
235 0 : ShowContinueError(
236 0 : state, format("...Capacity passed by parent object to size child component = {:.2T} [W]", this->autoSizedValue));
237 : } else {
238 0 : ShowContinueError(state, format("...Air flow rate used for sizing = {:.5T} [m3/s]", DesVolFlow));
239 0 : ShowContinueError(state, format("...Coil inlet air temperature used for sizing = {:.2T} [C]", CoilInTemp));
240 0 : ShowContinueError(state, format("...Coil outlet air temperature used for sizing = {:.2T} [C]", CoilOutTemp));
241 : }
242 : } else {
243 0 : if (CoilOutTemp > -999.0) {
244 0 : ShowContinueError(state, format("...Air flow rate used for sizing = {:.5T} [m3/s]", DesVolFlow));
245 0 : ShowContinueError(state, format("...Coil inlet air temperature used for sizing = {:.2T} [C]", CoilInTemp));
246 0 : ShowContinueError(state, format("...Coil outlet air temperature used for sizing = {:.2T} [C]", CoilOutTemp));
247 : } else {
248 0 : ShowContinueError(state, "...Capacity used to size child component set to 0 [W]");
249 : }
250 : }
251 : }
252 : }
253 : }
254 183 : } else if (this->curSysNum > 0) {
255 138 : if (!this->wasAutoSized && !this->sizingDesRunThisAirSys) {
256 26 : this->autoSizedValue = _originalValue;
257 : } else {
258 112 : Real64 OutAirFrac = 0.0;
259 112 : this->dataFracOfAutosizedCoolingCapacity = 1.0;
260 112 : if (this->oaSysFlag) {
261 1 : this->autoSizedValue = this->oaSysEqSizing(this->curOASysNum).DesCoolingLoad;
262 1 : DesVolFlow = this->dataFlowUsedForSizing;
263 111 : } else if (this->airLoopSysFlag) {
264 6 : this->autoSizedValue = this->unitarySysEqSizing(this->curSysNum).DesCoolingLoad;
265 6 : DesVolFlow = this->dataFlowUsedForSizing;
266 6 : CoilInTemp = state.dataSize->DataCoilSizingAirInTemp;
267 6 : CoilInHumRat = state.dataSize->DataCoilSizingAirInHumRat;
268 6 : CoilOutTemp = state.dataSize->DataCoilSizingAirOutTemp;
269 6 : CoilOutHumRat = state.dataSize->DataCoilSizingAirOutHumRat;
270 6 : FanCoolLoad = state.dataSize->DataCoilSizingFanCoolLoad;
271 6 : TotCapTempModFac = state.dataSize->DataCoilSizingCapFT;
272 6 : if (state.dataRptCoilSelection->coilSelectionReportObj->isCompTypeCoil(this->compType)) {
273 5 : state.dataRptCoilSelection->coilSelectionReportObj->setCoilEntAirHumRat(state, this->compName, this->compType, CoilInHumRat);
274 5 : state.dataRptCoilSelection->coilSelectionReportObj->setCoilEntAirTemp(
275 5 : state, this->compName, this->compType, CoilInTemp, this->curSysNum, this->curZoneEqNum);
276 5 : state.dataRptCoilSelection->coilSelectionReportObj->setCoilLvgAirTemp(state, this->compName, this->compType, CoilOutTemp);
277 5 : state.dataRptCoilSelection->coilSelectionReportObj->setCoilLvgAirHumRat(state, this->compName, this->compType, CoilOutHumRat);
278 : }
279 105 : } else if (this->curOASysNum > 0 && this->outsideAirSys(this->curOASysNum).AirLoopDOASNum > -1) {
280 9 : auto &thisAirloopDOAS = this->airloopDOAS[this->outsideAirSys(this->curOASysNum).AirLoopDOASNum];
281 9 : DesVolFlow = thisAirloopDOAS.SizingMassFlow / state.dataEnvrn->StdRhoAir;
282 9 : CoilInTemp = thisAirloopDOAS.SizingCoolOATemp;
283 9 : CoilOutTemp = thisAirloopDOAS.PrecoolTemp;
284 9 : if (thisAirloopDOAS.m_FanIndex > 0) {
285 : // This should work for all fan types
286 9 : state.dataFans->fans(thisAirloopDOAS.m_FanIndex)
287 9 : ->getInputsForDesignHeatGain(state,
288 9 : this->deltaP,
289 9 : this->motEff,
290 9 : this->totEff,
291 9 : this->motInAirFrac,
292 9 : this->fanShaftPow,
293 9 : this->motInPower,
294 9 : this->fanCompModel);
295 :
296 9 : if (thisAirloopDOAS.m_FanTypeNum == SimAirServingZones::CompType::Fan_ComponentModel) {
297 0 : FanCoolLoad = this->fanShaftPow + (this->motInPower - this->fanShaftPow) * this->motInAirFrac;
298 9 : } else if (thisAirloopDOAS.m_FanTypeNum == SimAirServingZones::CompType::Fan_System_Object) {
299 9 : Real64 const fanPowerTot = (DesVolFlow * this->deltaP) / this->totEff;
300 9 : FanCoolLoad = this->motEff * fanPowerTot + (fanPowerTot - this->motEff * fanPowerTot) * this->motInAirFrac;
301 : }
302 9 : this->dataFanType = state.dataFans->fans(thisAirloopDOAS.m_FanIndex)->type;
303 9 : this->dataFanIndex = thisAirloopDOAS.m_FanIndex;
304 9 : Real64 const CpAir = Psychrometrics::PsyCpAirFnW(state.dataLoopNodes->Node(thisAirloopDOAS.m_FanInletNodeNum).HumRat);
305 9 : Real64 const DeltaT = FanCoolLoad / (thisAirloopDOAS.SizingMassFlow * CpAir);
306 9 : if (thisAirloopDOAS.FanBeforeCoolingCoilFlag) {
307 8 : CoilInTemp += DeltaT;
308 : } else {
309 1 : CoilOutTemp -= DeltaT;
310 1 : CoilOutTemp =
311 1 : max(CoilOutTemp, Psychrometrics::PsyTdpFnWPb(state, thisAirloopDOAS.PrecoolHumRat, state.dataEnvrn->StdBaroPress));
312 : }
313 : }
314 9 : CoilInHumRat = thisAirloopDOAS.SizingCoolOAHumRat;
315 9 : CoilOutHumRat = thisAirloopDOAS.PrecoolHumRat;
316 9 : this->autoSizedValue =
317 9 : DesVolFlow * state.dataEnvrn->StdRhoAir *
318 9 : (Psychrometrics::PsyHFnTdbW(CoilInTemp, CoilInHumRat) - Psychrometrics::PsyHFnTdbW(CoilOutTemp, CoilOutHumRat));
319 : } else {
320 96 : CheckSysSizing(state, this->compType, this->compName);
321 96 : auto const &thisFinalSysSizing = this->finalSysSizing(this->curSysNum);
322 96 : DesVolFlow = this->dataFlowUsedForSizing;
323 96 : Real64 NominalCapacityDes = 0.0;
324 96 : if (thisFinalSysSizing.CoolingCapMethod == DataSizing::FractionOfAutosizedCoolingCapacity) {
325 2 : this->dataFracOfAutosizedCoolingCapacity = thisFinalSysSizing.FractionOfAutosizedCoolingCapacity;
326 : }
327 96 : if (thisFinalSysSizing.CoolingCapMethod == DataSizing::CapacityPerFloorArea) {
328 1 : NominalCapacityDes = thisFinalSysSizing.CoolingTotalCapacity;
329 1 : this->autoSizedValue = NominalCapacityDes;
330 95 : } else if (thisFinalSysSizing.CoolingCapMethod == DataSizing::CoolingDesignCapacity &&
331 47 : thisFinalSysSizing.CoolingTotalCapacity > 0.0) {
332 1 : NominalCapacityDes = thisFinalSysSizing.CoolingTotalCapacity;
333 1 : this->autoSizedValue = NominalCapacityDes;
334 94 : } else if (DesVolFlow >= HVAC::SmallAirVolFlow) {
335 93 : if (DesVolFlow > 0.0) {
336 93 : OutAirFrac = thisFinalSysSizing.DesOutAirVolFlow / DesVolFlow;
337 : } else {
338 0 : OutAirFrac = 1.0;
339 : }
340 93 : OutAirFrac = min(1.0, max(0.0, OutAirFrac));
341 93 : if (this->curOASysNum > 0) { // coil is in the OA stream
342 0 : CoilInTemp = thisFinalSysSizing.OutTempAtCoolPeak;
343 0 : CoilInHumRat = thisFinalSysSizing.OutHumRatAtCoolPeak;
344 0 : CoilOutTemp = thisFinalSysSizing.PrecoolTemp;
345 0 : CoilOutHumRat = thisFinalSysSizing.PrecoolHumRat;
346 : } else { // coil is on the main air loop
347 93 : if (this->dataAirFlowUsedForSizing > 0.0) {
348 26 : DesVolFlow = this->dataAirFlowUsedForSizing;
349 : }
350 93 : if (this->dataDesOutletAirTemp > 0.0) {
351 22 : CoilOutTemp = this->dataDesOutletAirTemp;
352 : } else {
353 71 : CoilOutTemp = thisFinalSysSizing.CoolSupTemp;
354 : }
355 93 : if (this->dataDesOutletAirHumRat > 0.0) {
356 14 : CoilOutHumRat = this->dataDesOutletAirHumRat;
357 : } else {
358 79 : CoilOutHumRat = thisFinalSysSizing.CoolSupHumRat;
359 : }
360 :
361 93 : if (this->primaryAirSystem(this->curSysNum).NumOACoolCoils == 0) { // there is no precooling of the OA stream
362 90 : CoilInTemp = thisFinalSysSizing.MixTempAtCoolPeak;
363 90 : CoilInHumRat = thisFinalSysSizing.MixHumRatAtCoolPeak;
364 : } else { // there is precooling of OA stream
365 3 : if (DesVolFlow > 0.0) {
366 3 : OutAirFrac = thisFinalSysSizing.DesOutAirVolFlow / DesVolFlow;
367 : } else {
368 0 : OutAirFrac = 1.0;
369 : }
370 3 : OutAirFrac = min(1.0, max(0.0, OutAirFrac));
371 3 : CoilInTemp = OutAirFrac * thisFinalSysSizing.PrecoolTemp + (1.0 - OutAirFrac) * thisFinalSysSizing.RetTempAtCoolPeak;
372 3 : CoilInHumRat =
373 3 : OutAirFrac * thisFinalSysSizing.PrecoolHumRat + (1.0 - OutAirFrac) * thisFinalSysSizing.RetHumRatAtCoolPeak;
374 : }
375 93 : if (this->dataDesInletAirTemp > 0.0) CoilInTemp = this->dataDesInletAirTemp;
376 93 : if (this->dataDesInletAirHumRat > 0.0) CoilInHumRat = this->dataDesInletAirHumRat;
377 : }
378 93 : Real64 OutTemp = thisFinalSysSizing.OutTempAtCoolPeak;
379 93 : if (this->dataCoolCoilType == HVAC::Coil_CoolingWaterToAirHPVSEquationFit) {
380 1 : OutTemp = VariableSpeedCoils::GetVSCoilRatedSourceTemp(state, this->dataCoolCoilIndex);
381 : }
382 93 : CoilOutTemp = min(CoilInTemp, CoilOutTemp);
383 93 : CoilOutHumRat = min(CoilInHumRat, CoilOutHumRat);
384 93 : Real64 CoilInEnth = Psychrometrics::PsyHFnTdbW(CoilInTemp, CoilInHumRat);
385 : Real64 CoilInWetBulb =
386 93 : Psychrometrics::PsyTwbFnTdbWPb(state, CoilInTemp, CoilInHumRat, state.dataEnvrn->StdBaroPress, this->callingRoutine);
387 93 : Real64 CoilOutEnth = Psychrometrics::PsyHFnTdbW(CoilOutTemp, CoilOutHumRat);
388 93 : if (this->curOASysNum > 0) { // coil is in the OA stream
389 : // need to find fan type in OA system
390 : } else {
391 93 : if (this->primaryAirSystem(this->curSysNum).supFanType != HVAC::FanType::Invalid)
392 58 : FanCoolLoad = this->calcFanDesHeatGain(DesVolFlow);
393 93 : if (this->primaryAirSystem(this->curSysNum).retFanType != HVAC::FanType::Invalid)
394 0 : FanCoolLoad += (1.0 - OutAirFrac) * this->calcFanDesHeatGain(DesVolFlow);
395 93 : this->primaryAirSystem(this->curSysNum).FanDesCoolLoad = FanCoolLoad;
396 : }
397 93 : Real64 PeakCoilLoad = max(0.0, (state.dataEnvrn->StdRhoAir * DesVolFlow * (CoilInEnth - CoilOutEnth)));
398 93 : Real64 CpAir = Psychrometrics::PsyCpAirFnW(CoilInHumRat);
399 : // adjust coil inlet/outlet temp with fan temperature rise
400 93 : if (this->dataDesAccountForFanHeat) {
401 82 : PeakCoilLoad = max(0.0, (state.dataEnvrn->StdRhoAir * DesVolFlow * (CoilInEnth - CoilOutEnth) + FanCoolLoad));
402 82 : if (this->primaryAirSystem(this->curSysNum).supFanPlace == HVAC::FanPlace::BlowThru) {
403 5 : CoilInTemp += FanCoolLoad / (CpAir * state.dataEnvrn->StdRhoAir * DesVolFlow);
404 : // include change in inlet condition in TotCapTempModFac
405 10 : CoilInWetBulb = Psychrometrics::PsyTwbFnTdbWPb(
406 5 : state, CoilInTemp, CoilInHumRat, state.dataEnvrn->StdBaroPress, this->callingRoutine);
407 77 : } else if (this->primaryAirSystem(this->curSysNum).supFanPlace == HVAC::FanPlace::DrawThru) {
408 42 : CoilOutTemp -= FanCoolLoad / (CpAir * state.dataEnvrn->StdRhoAir * DesVolFlow);
409 : }
410 : }
411 93 : if (this->dataTotCapCurveIndex > 0) {
412 40 : switch (state.dataCurveManager->curves(this->dataTotCapCurveIndex)->numDims) {
413 1 : case 1:
414 1 : TotCapTempModFac = Curve::CurveValue(state, this->dataTotCapCurveIndex, CoilInWetBulb);
415 1 : break;
416 39 : case 2:
417 : default: // this default allows the simulation to continue, but will issue a warning, should be removed eventually
418 39 : TotCapTempModFac = Curve::CurveValue(state, this->dataTotCapCurveIndex, CoilInWetBulb, OutTemp);
419 39 : break;
420 : }
421 : } else {
422 53 : TotCapTempModFac = 1.0;
423 : }
424 93 : if (TotCapTempModFac > 0.0) {
425 93 : NominalCapacityDes = PeakCoilLoad / TotCapTempModFac;
426 : } else {
427 0 : NominalCapacityDes = PeakCoilLoad;
428 : }
429 93 : state.dataSize->DataCoilSizingAirInTemp = CoilInTemp;
430 93 : state.dataSize->DataCoilSizingAirInHumRat = CoilInHumRat;
431 93 : state.dataSize->DataCoilSizingAirOutTemp = CoilOutTemp;
432 93 : state.dataSize->DataCoilSizingAirOutHumRat = CoilOutHumRat;
433 93 : state.dataSize->DataCoilSizingFanCoolLoad = FanCoolLoad;
434 93 : state.dataSize->DataCoilSizingCapFT = TotCapTempModFac;
435 : } else {
436 1 : NominalCapacityDes = 0.0;
437 : }
438 96 : this->autoSizedValue =
439 96 : NominalCapacityDes * this->dataFracOfAutosizedCoolingCapacity; // Fixed Moved up 1 line inside block per Richard Raustad
440 : } // IF(OASysFlag) THEN or ELSE IF(AirLoopSysFlag) THEN
441 112 : this->dataDesAccountForFanHeat = true; // reset for next water coil
442 112 : if (state.dataGlobal->DisplayExtraWarnings && this->autoSizedValue <= 0.0) {
443 0 : ShowWarningMessage(state,
444 0 : this->callingRoutine + ": Potential issue with equipment sizing for " + this->compType + ' ' + this->compName);
445 0 : ShowContinueError(state, format("...Rated Total Cooling Capacity = {:.2T} [W]", this->autoSizedValue));
446 0 : if (this->oaSysFlag || this->airLoopSysFlag ||
447 0 : this->finalSysSizing(this->curSysNum).CoolingCapMethod == DataSizing::CapacityPerFloorArea ||
448 0 : (this->finalSysSizing(this->curSysNum).CoolingCapMethod == DataSizing::CoolingDesignCapacity &&
449 0 : this->finalSysSizing(this->curSysNum).CoolingTotalCapacity)) {
450 0 : ShowContinueError(state,
451 0 : format("...Capacity passed by parent object to size child component = {:.2T} [W]", this->autoSizedValue));
452 : } else {
453 0 : ShowContinueError(state, format("...Air flow rate used for sizing = {:.5T} [m3/s]", DesVolFlow));
454 0 : ShowContinueError(state, format("...Outdoor air fraction used for sizing = {:.2T}", OutAirFrac));
455 0 : ShowContinueError(state, format("...Coil inlet air temperature used for sizing = {:.2T} [C]", CoilInTemp));
456 0 : ShowContinueError(state, format("...Coil outlet air temperature used for sizing = {:.2T} [C]", CoilOutTemp));
457 : }
458 : }
459 : }
460 45 : } else if (this->dataNonZoneNonAirloopValue > 0) {
461 6 : this->autoSizedValue = this->dataNonZoneNonAirloopValue;
462 39 : } else if (!this->wasAutoSized) {
463 39 : this->autoSizedValue = this->originalValue;
464 : } else {
465 0 : std::string msg = this->callingRoutine + ' ' + this->compType + ' ' + this->compName + ", Developer Error: Component sizing incomplete.";
466 0 : ShowSevereError(state, msg);
467 0 : this->addErrorMessage(msg);
468 0 : msg = format("SizingString = {}, SizingResult = {:.1T}", this->sizingString, this->autoSizedValue);
469 0 : ShowContinueError(state, msg);
470 0 : this->addErrorMessage(msg);
471 0 : errorsFound = true;
472 0 : }
473 : }
474 391 : if (this->dataDXCoolsLowSpeedsAutozize) {
475 26 : this->autoSizedValue *= this->dataFractionUsedForSizing;
476 : }
477 391 : if (!this->hardSizeNoDesignRun || this->dataScalableSizingON || this->dataScalableCapSizingON) {
478 341 : if (this->wasAutoSized) {
479 : // Note: the VolFlowPerRatedTotCap check is not applicable for VRF-FluidTCtrl coil model, which implements variable flow fans and
480 : // determines capacity using physical calculations instead of emperical curves
481 259 : bool FlagCheckVolFlowPerRatedTotCap = true;
482 513 : if (Util::SameString(this->compType, "Coil:Cooling:DX:VariableRefrigerantFlow:FluidTemperatureControl") ||
483 513 : Util::SameString(this->compType, "Coil:Heating:DX:VariableRefrigerantFlow:FluidTemperatureControl"))
484 5 : FlagCheckVolFlowPerRatedTotCap = false;
485 :
486 259 : if (this->dataIsDXCoil && FlagCheckVolFlowPerRatedTotCap) {
487 93 : Real64 RatedVolFlowPerRatedTotCap = 0.0;
488 93 : if (this->autoSizedValue > 0.0) {
489 93 : RatedVolFlowPerRatedTotCap = DesVolFlow / this->autoSizedValue;
490 : }
491 93 : if (RatedVolFlowPerRatedTotCap < HVAC::MinRatedVolFlowPerRatedTotCap[(int)state.dataHVACGlobal->DXCT]) {
492 37 : if (!this->dataEMSOverride && state.dataGlobal->DisplayExtraWarnings && this->printWarningFlag) {
493 9 : ShowWarningError(state, this->callingRoutine + ' ' + this->compType + ' ' + this->compName);
494 18 : ShowContinueError(
495 18 : state, "..." + this->sizingString + " will be limited by the minimum rated volume flow per rated total capacity ratio.");
496 9 : ShowContinueError(state, format("...DX coil volume flow rate (m3/s ) = {:.6T}", DesVolFlow));
497 9 : ShowContinueError(state, format("...Requested capacity (W ) = {:.3T}", this->autoSizedValue));
498 9 : ShowContinueError(state, format("...Requested flow/capacity ratio (m3/s/W ) = {:.3T}", RatedVolFlowPerRatedTotCap));
499 18 : ShowContinueError(state,
500 18 : format("...Minimum flow/capacity ratio (m3/s/W ) = {:.3T}",
501 9 : HVAC::MinRatedVolFlowPerRatedTotCap[(int)state.dataHVACGlobal->DXCT]));
502 : }
503 :
504 37 : DXFlowPerCapMinRatio = (DesVolFlow / HVAC::MinRatedVolFlowPerRatedTotCap[(int)state.dataHVACGlobal->DXCT]) /
505 37 : this->autoSizedValue; // set DX Coil Capacity Increase Ratio from Too Low Flow/Capacity Ratio
506 37 : this->autoSizedValue = DesVolFlow / HVAC::MinRatedVolFlowPerRatedTotCap[(int)state.dataHVACGlobal->DXCT];
507 :
508 37 : if (!this->dataEMSOverride && state.dataGlobal->DisplayExtraWarnings && this->printWarningFlag) {
509 9 : ShowContinueError(state, format("...Adjusted capacity ( W ) = {:.3T}", this->autoSizedValue));
510 : }
511 56 : } else if (RatedVolFlowPerRatedTotCap > HVAC::MaxRatedVolFlowPerRatedTotCap[(int)state.dataHVACGlobal->DXCT]) {
512 7 : if (!this->dataEMSOverride && state.dataGlobal->DisplayExtraWarnings && this->printWarningFlag) {
513 1 : ShowWarningError(state, this->callingRoutine + ' ' + this->compType + ' ' + this->compName);
514 2 : ShowContinueError(
515 2 : state, "..." + this->sizingString + " will be limited by the maximum rated volume flow per rated total capacity ratio.");
516 1 : ShowContinueError(state, format("...DX coil volume flow rate ( m3/s ) = {:.6T}", DesVolFlow));
517 1 : ShowContinueError(state, format("...Requested capacity ( W ) = {:.3T}", this->autoSizedValue));
518 1 : ShowContinueError(state, format("...Requested flow/capacity ratio ( m3/s/W ) = {:.3T}", RatedVolFlowPerRatedTotCap));
519 2 : ShowContinueError(state,
520 2 : format("...Maximum flow/capacity ratio ( m3/s/W ) = {:.3T}",
521 1 : HVAC::MaxRatedVolFlowPerRatedTotCap[(int)state.dataHVACGlobal->DXCT]));
522 : }
523 :
524 7 : DXFlowPerCapMaxRatio = DesVolFlow / HVAC::MaxRatedVolFlowPerRatedTotCap[(int)state.dataHVACGlobal->DXCT] /
525 7 : this->autoSizedValue; // set DX Coil Capacity Decrease Ratio from Too High Flow/Capacity Ratio
526 7 : this->autoSizedValue = DesVolFlow / HVAC::MaxRatedVolFlowPerRatedTotCap[(int)state.dataHVACGlobal->DXCT];
527 :
528 7 : if (!this->dataEMSOverride && state.dataGlobal->DisplayExtraWarnings && this->printWarningFlag) {
529 1 : ShowContinueError(state, format("...Adjusted capacity ( W ) = {:.3T}", this->autoSizedValue));
530 : }
531 : }
532 : }
533 : }
534 : }
535 :
536 : // override sizing string
537 391 : if (this->overrideSizeString) {
538 27 : if (this->isEpJSON) this->sizingString = "cooling_design_capacity [W]";
539 : }
540 391 : if (this->dataScalableCapSizingON) {
541 5 : int const SELECT_CASE_var(this->zoneEqSizing(this->curZoneEqNum).SizingMethod(HVAC::CoolingCapacitySizing));
542 5 : if (SELECT_CASE_var == DataSizing::CapacityPerFloorArea) {
543 2 : this->sizingStringScalable = "(scaled by capacity / area) ";
544 3 : } else if (SELECT_CASE_var == DataSizing::FractionOfAutosizedHeatingCapacity ||
545 : SELECT_CASE_var == DataSizing::FractionOfAutosizedCoolingCapacity) {
546 3 : this->sizingStringScalable = "(scaled by fractional multiplier) ";
547 : }
548 : }
549 :
550 391 : this->selectSizerOutput(state, errorsFound);
551 :
552 391 : if (this->isCoilReportObject && this->curSysNum <= state.dataHVACGlobal->NumPrimaryAirSys) {
553 182 : if (CoilInTemp > -999.0) { // set inlet air properties used during capacity sizing if available, allow for negative winter temps
554 86 : state.dataRptCoilSelection->coilSelectionReportObj->setCoilEntAirTemp(
555 86 : state, this->compName, this->compType, CoilInTemp, this->curSysNum, this->curZoneEqNum);
556 86 : state.dataRptCoilSelection->coilSelectionReportObj->setCoilEntAirHumRat(state, this->compName, this->compType, CoilInHumRat);
557 : }
558 182 : if (CoilOutTemp > -999.0) { // set outlet air properties used during capacity sizing if available
559 86 : state.dataRptCoilSelection->coilSelectionReportObj->setCoilLvgAirTemp(state, this->compName, this->compType, CoilOutTemp);
560 86 : state.dataRptCoilSelection->coilSelectionReportObj->setCoilLvgAirHumRat(state, this->compName, this->compType, CoilOutHumRat);
561 : }
562 182 : state.dataRptCoilSelection->coilSelectionReportObj->setCoilCoolingCapacity(state,
563 182 : this->compName,
564 182 : this->compType,
565 : this->autoSizedValue,
566 182 : this->wasAutoSized,
567 : this->curSysNum,
568 : this->curZoneEqNum,
569 : this->curOASysNum,
570 : FanCoolLoad,
571 : TotCapTempModFac,
572 : DXFlowPerCapMinRatio,
573 : DXFlowPerCapMaxRatio);
574 : }
575 391 : return this->autoSizedValue;
576 : }
577 :
578 0 : void CoolingCapacitySizer::clearState()
579 : {
580 0 : BaseSizerWithScalableInputs::clearState();
581 0 : }
582 :
583 : } // namespace EnergyPlus
|