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 : // C++ Headers
49 : #include <cmath>
50 :
51 : // ObjexxFCL Headers
52 : #include <ObjexxFCL/Array1D.hh>
53 : #include <ObjexxFCL/member.functions.hh>
54 :
55 : // EnergyPlus Headers
56 : #include <EnergyPlus/Autosizing/Base.hh>
57 : #include <EnergyPlus/ConvectionCoefficients.hh>
58 : #include <EnergyPlus/Data/EnergyPlusData.hh>
59 : #include <EnergyPlus/DataEnvironment.hh>
60 : #include <EnergyPlus/DataHVACGlobals.hh>
61 : #include <EnergyPlus/DataHeatBalFanSys.hh>
62 : #include <EnergyPlus/DataHeatBalSurface.hh>
63 : #include <EnergyPlus/DataHeatBalance.hh>
64 : #include <EnergyPlus/DataLoopNode.hh>
65 : #include <EnergyPlus/DataRoomAirModel.hh>
66 : #include <EnergyPlus/DataSizing.hh>
67 : #include <EnergyPlus/DataSurfaces.hh>
68 : #include <EnergyPlus/DataZoneEquipment.hh>
69 : #include <EnergyPlus/General.hh>
70 : #include <EnergyPlus/InternalHeatGains.hh>
71 : #include <EnergyPlus/Psychrometrics.hh>
72 : #include <EnergyPlus/UFADManager.hh>
73 : #include <EnergyPlus/UtilityRoutines.hh>
74 : #include <EnergyPlus/ZoneTempPredictorCorrector.hh>
75 :
76 : namespace EnergyPlus {
77 :
78 : namespace RoomAir {
79 :
80 : // Module containing the routines dealing with the UnderFloor Air
81 : // Distribution zone model
82 :
83 : // MODULE INFORMATION:
84 : // AUTHOR Fred Buhl
85 : // DATE WRITTEN August 2005
86 :
87 : // PURPOSE OF THIS MODULE:
88 : // Encapsulate the routines that do the simulation of the UCSD UFAD non-uniform
89 : // zone models
90 :
91 : // METHODOLOGY EMPLOYED:
92 : // 2-node zone model with the node heights varying as a function of internal loads
93 : // and supply air flow (and other factors)
94 :
95 : // REFERENCES:
96 : // See the EnergyPlus Engineering Reference and the PhD thesis of Anna Liu, UC San Diego
97 :
98 : // OTHER NOTES:
99 : // na
100 :
101 : // Using/Aliasing
102 : using namespace DataLoopNode;
103 : using namespace DataEnvironment;
104 : using namespace DataHeatBalance;
105 : using namespace DataHeatBalSurface;
106 : using namespace DataSurfaces;
107 : using Convect::CalcDetailedHcInForDVModel;
108 :
109 0 : void ManageUFAD(EnergyPlusData &state,
110 : int const ZoneNum, // index number for the specified zone
111 : RoomAirModel const ZoneModelType // type of zone model; UCSDUFI = 6
112 : )
113 : {
114 :
115 : // SUBROUTINE INFORMATION:
116 : // AUTHOR Fred Buhl
117 : // DATE WRITTEN August, 2005
118 : // MODIFIED na
119 : // RE-ENGINEERED na
120 :
121 : // PURPOSE OF THIS SUBROUTINE:
122 : // Manages the simulation of the 2-node nonuniform zone models for underfloor air
123 : // distribution systems (UFAD). Called from RoomAirManager, ManageAirModel
124 :
125 : // METHODOLOGY EMPLOYED:
126 : // uses Init and Calc routines in the standard EPlus manner to manage the calculation
127 : // Note that much of the initialization is done in RoomAirManager, SharedDVCVUFDataInit
128 :
129 : // Using/Aliasing
130 : using namespace DataLoopNode;
131 : using namespace DataEnvironment;
132 : using namespace DataHeatBalance;
133 : using namespace DataHeatBalSurface;
134 : using namespace DataSurfaces;
135 : using Convect::CalcDetailedHcInForDVModel;
136 :
137 : // input was obtained in RoomAirManager, GetUFADIntZoneData
138 :
139 0 : InitUFAD(state, ZoneNum, ZoneModelType); // initialize some module variables
140 :
141 0 : switch (ZoneModelType) {
142 0 : case RoomAirModel::UFADInt: { // UCSD UFAD interior zone model
143 : // simulate room airflow using the UCSDUFI model
144 0 : CalcUFADInt(state, ZoneNum);
145 0 : } break;
146 0 : case RoomAirModel::UFADExt: { // UCSD UFAD exterior zone model
147 : // simulate room airflow using the UCSDUFE model
148 0 : CalcUFADExt(state, ZoneNum);
149 0 : } break;
150 0 : default:
151 0 : break;
152 : }
153 0 : }
154 :
155 0 : void InitUFAD(EnergyPlusData &state,
156 : int const ZoneNum,
157 : RoomAirModel const ZoneModelType // type of zone model; UCSDUFI = 6
158 : )
159 : {
160 :
161 : // SUBROUTINE INFORMATION:
162 : // AUTHOR Fred Buhl
163 : // DATE WRITTEN August 2005
164 :
165 : // PURPOSE OF THIS SUBROUTINE:
166 : // initialize arrays & variables used by the UCSD UFAD zone models
167 :
168 : // METHODOLOGY EMPLOYED:
169 : // Note that much of the initialization is done in RoomAirManager, SharedDVCVUFDataInit
170 :
171 0 : Real64 NumShadesDown(0.0);
172 :
173 : // Do the one time initializations
174 0 : if (state.dataUFADManager->MyOneTimeFlag) {
175 0 : state.dataUFADManager->HeightFloorSubzoneTop = 0.2;
176 0 : state.dataUFADManager->ThickOccupiedSubzoneMin = 0.2;
177 0 : state.dataUFADManager->HeightIntMassDefault = 2.0;
178 0 : state.dataUFADManager->MyOneTimeFlag = false;
179 0 : state.dataUFADManager->MySizeFlag.dimension(state.dataGlobal->NumOfZones, true);
180 : }
181 :
182 0 : if (state.dataUFADManager->MySizeFlag(ZoneNum)) {
183 0 : SizeUFAD(state, ZoneNum, ZoneModelType);
184 0 : state.dataUFADManager->MySizeFlag(ZoneNum) = false;
185 : }
186 :
187 : // initialize these variables every timestep
188 :
189 0 : state.dataUFADManager->HeightIntMass = state.dataUFADManager->HeightIntMassDefault;
190 0 : state.dataRoomAir->ZoneUFADGamma(ZoneNum) = 0.0;
191 0 : state.dataRoomAir->ZoneUFADPowInPlumes(ZoneNum) = 0.0;
192 0 : NumShadesDown = 0.0;
193 0 : for (int Ctd = state.dataRoomAir->PosZ_Window(ZoneNum).beg; Ctd <= state.dataRoomAir->PosZ_Window(ZoneNum).end; ++Ctd) {
194 0 : int SurfNum = state.dataRoomAir->APos_Window(Ctd);
195 0 : if (SurfNum == 0) {
196 0 : continue;
197 : }
198 0 : auto const &surf = state.dataSurface->Surface(SurfNum);
199 0 : if (surf.ExtBoundCond == ExternalEnvironment || surf.ExtBoundCond == OtherSideCoefNoCalcExt ||
200 0 : surf.ExtBoundCond == OtherSideCoefCalcExt || surf.ExtBoundCond == OtherSideCondModeledExt) {
201 0 : if (ANY_INTERIOR_SHADE_BLIND(state.dataSurface->SurfWinShadingFlag(SurfNum))) {
202 0 : ++NumShadesDown;
203 : }
204 : }
205 : }
206 0 : if (ZoneModelType == RoomAirModel::UFADExt) {
207 0 : auto &zoneUE = state.dataRoomAir->ZoneUFAD(state.dataRoomAir->ZoneUFADPtr(ZoneNum));
208 0 : zoneUE.ShadeDown = (zoneUE.NumExtWin > 1.0) && (NumShadesDown / zoneUE.NumExtWin >= 0.5);
209 : }
210 0 : }
211 :
212 0 : void SizeUFAD(EnergyPlusData &state,
213 : int const ZoneNum,
214 : RoomAirModel const model // type of zone model; UCSDUFI = 6
215 : )
216 : {
217 :
218 : // SUBROUTINE INFORMATION:
219 : // AUTHOR Fred Buhl
220 : // DATE WRITTEN August 2005
221 :
222 : // PURPOSE OF THIS SUBROUTINE:
223 : // set some smart defaults for UFAD systems
224 :
225 : // METHODOLOGY EMPLOYED:
226 : // use data from Center for Built Environment
227 :
228 : using DataSizing::AutoSize;
229 :
230 : // This is for both UFADInt and UFADExt
231 0 : auto &zoneU = state.dataRoomAir->ZoneUFAD(state.dataRoomAir->ZoneUFADPtr(ZoneNum));
232 :
233 : std::string_view cCMO = (model == RoomAirModel::UFADExt) ? "RoomAirSettings:UnderFloorAirDistributionExterior"
234 0 : : "RoomAirSettings:UnderFloorAirDistributionInterior";
235 :
236 0 : Real64 NumberOfOccupants = 0.0;
237 0 : for (auto const &people : state.dataHeatBal->People) {
238 0 : if (people.ZonePtr == ZoneNum) {
239 0 : NumberOfOccupants += people.NumberOfPeople;
240 : }
241 0 : }
242 :
243 0 : if (model == RoomAirModel::UFADExt) {
244 : // calculate total window width in zone
245 0 : for (int Ctd = state.dataRoomAir->PosZ_Window(ZoneNum).beg; Ctd <= state.dataRoomAir->PosZ_Window(ZoneNum).end; ++Ctd) {
246 0 : int SurfNum = state.dataRoomAir->APos_Window(Ctd);
247 0 : if (SurfNum == 0) {
248 0 : continue;
249 : }
250 0 : auto &surf = state.dataSurface->Surface(SurfNum);
251 0 : if (surf.ExtBoundCond == ExternalEnvironment || surf.ExtBoundCond == OtherSideCoefNoCalcExt ||
252 0 : surf.ExtBoundCond == OtherSideCoefCalcExt || surf.ExtBoundCond == OtherSideCondModeledExt) {
253 0 : zoneU.WinWidth += surf.Width;
254 0 : ++zoneU.NumExtWin;
255 : }
256 : }
257 0 : if (zoneU.WinWidth <= 0.0) {
258 0 : ShowWarningError(
259 : state,
260 0 : format("For RoomAirSettings:UnderFloorAirDistributionExterior for Zone {} there are no exterior windows.", zoneU.ZoneName));
261 0 : ShowContinueError(state, " The zone will be treated as a UFAD interior zone");
262 : }
263 : } // if (model == RoomAirModel::UFADExt)
264 :
265 0 : if (zoneU.DiffArea == AutoSize) {
266 0 : constexpr std::array<Real64, (int)Diffuser::Num> diffArea = {0.0075, 0.035, 0.0060, 0.03, 0.0075};
267 0 : zoneU.DiffArea = diffArea[(int)zoneU.DiffuserType];
268 : // 4 ft x 4 inches; 75 cfm per linear foot; area is .025 m2/m
269 :
270 0 : BaseSizer::reportSizerOutput(state, cCMO, zoneU.ZoneName, "Design effective area of diffuser", zoneU.DiffArea);
271 : }
272 0 : if (zoneU.DiffAngle == AutoSize) {
273 0 : constexpr std::array<Real64, (int)Diffuser::Num> diffAngle = {28.0, 45.0, 73.0, 15.0, 28.0};
274 0 : zoneU.DiffAngle = diffAngle[(int)zoneU.DiffuserType];
275 :
276 0 : BaseSizer::reportSizerOutput(state, cCMO, zoneU.ZoneName, "Angle between diffuser slots and the vertical", zoneU.DiffAngle);
277 : }
278 0 : if (zoneU.TransHeight == AutoSize) {
279 0 : zoneU.CalcTransHeight = true;
280 0 : zoneU.TransHeight = 0.0;
281 : } else {
282 0 : zoneU.CalcTransHeight = false;
283 : }
284 :
285 0 : if (zoneU.DiffuserType != Diffuser::Custom &&
286 0 : (zoneU.A_Kc != Constant::AutoCalculate || zoneU.B_Kc != Constant::AutoCalculate || zoneU.C_Kc != Constant::AutoCalculate ||
287 0 : zoneU.D_Kc != Constant::AutoCalculate || zoneU.E_Kc != Constant::AutoCalculate)) {
288 0 : ShowWarningError(state,
289 0 : format("For {} for Zone {}, input for Coefficients A - E will be "
290 : "ignored when Floor Diffuser Type = {}.",
291 : cCMO,
292 0 : zoneU.ZoneName,
293 0 : diffuserNamesUC[(int)zoneU.DiffuserType]));
294 0 : ShowContinueError(state, " To input these Coefficients, use Floor Diffuser Type = Custom.");
295 : }
296 :
297 0 : if (zoneU.DiffuserType == Diffuser::Swirl) {
298 0 : zoneU.A_Kc = 0.0;
299 0 : zoneU.B_Kc = 0.0;
300 0 : zoneU.C_Kc = 0.6531;
301 0 : zoneU.D_Kc = 0.0069;
302 0 : zoneU.E_Kc = -0.00004;
303 0 : } else if (zoneU.DiffuserType == Diffuser::VarArea) {
304 0 : zoneU.A_Kc = 0.0;
305 0 : zoneU.B_Kc = 0.0;
306 0 : zoneU.C_Kc = (model == RoomAirModel::UFADExt) ? 0.83 : 0.88;
307 0 : zoneU.D_Kc = 0.0;
308 0 : zoneU.E_Kc = 0.0;
309 0 : } else if (zoneU.DiffuserType == Diffuser::DisplVent) {
310 0 : zoneU.A_Kc = 0.0;
311 0 : zoneU.B_Kc = 0.0;
312 0 : zoneU.C_Kc = 0.67;
313 0 : zoneU.D_Kc = 0.0;
314 0 : zoneU.E_Kc = 0.0;
315 0 : } else if (zoneU.DiffuserType == Diffuser::LinBarGrille) {
316 0 : zoneU.A_Kc = 0.0;
317 0 : zoneU.B_Kc = 0.0;
318 0 : zoneU.C_Kc = (model == RoomAirModel::UFADExt) ? 0.8214 : 0.8;
319 0 : zoneU.D_Kc = (model == RoomAirModel::UFADExt) ? -0.0263 : 0.0;
320 0 : zoneU.E_Kc = (model == RoomAirModel::UFADExt) ? 0.0014 : 0.0;
321 0 : } else if (zoneU.A_Kc == Constant::AutoCalculate || zoneU.B_Kc == Constant::AutoCalculate || zoneU.C_Kc == Constant::AutoCalculate ||
322 0 : zoneU.D_Kc == Constant::AutoCalculate || zoneU.E_Kc == Constant::AutoCalculate) {
323 0 : ShowFatalError(state,
324 0 : format("For {} for Zone {}, input for Coefficients A - E must be "
325 : "specified when Floor Diffuser Type = Custom.",
326 : cCMO,
327 0 : zoneU.ZoneName));
328 : }
329 :
330 0 : if (zoneU.PowerPerPlume == Constant::AutoCalculate) {
331 :
332 0 : zoneU.PowerPerPlume = sumUFADConvGainPerPlume(state, ZoneNum, NumberOfOccupants);
333 :
334 0 : BaseSizer::reportSizerOutput(state, cCMO, zoneU.ZoneName, "Power per plume [W]", zoneU.PowerPerPlume);
335 :
336 0 : if (zoneU.DiffusersPerZone == AutoSize) {
337 0 : zoneU.DiffusersPerZone = (NumberOfOccupants > 0.0) ? NumberOfOccupants : 1.0;
338 0 : BaseSizer::reportSizerOutput(state, cCMO, zoneU.ZoneName, "Number of diffusers per zone", zoneU.DiffusersPerZone);
339 : }
340 : }
341 :
342 0 : if (zoneU.DiffusersPerZone == AutoSize) {
343 0 : zoneU.DiffusersPerZone = (NumberOfOccupants > 0.0) ? NumberOfOccupants : 1.0;
344 :
345 0 : BaseSizer::reportSizerOutput(state, cCMO, zoneU.ZoneName, "Number of diffusers per zone", zoneU.DiffusersPerZone);
346 : }
347 0 : }
348 :
349 8 : Real64 sumUFADConvGainPerPlume(EnergyPlusData const &state, int const zoneNum, Real64 const numOccupants)
350 : {
351 8 : Real64 zoneElecConv(0.0); // zone elec equip design convective gain [W]
352 48 : for (auto const &zoneElectric : state.dataHeatBal->ZoneElectric) {
353 40 : if (zoneElectric.ZonePtr == zoneNum) {
354 5 : zoneElecConv += zoneElectric.DesignLevel * zoneElectric.FractionConvected;
355 : }
356 8 : }
357 :
358 8 : Real64 zoneGasConv(0.0); // zone gas equip design convective gain [W]
359 48 : for (auto const &zoneGas : state.dataHeatBal->ZoneGas) {
360 40 : if (zoneGas.ZonePtr == zoneNum) {
361 5 : zoneGasConv += zoneGas.DesignLevel * zoneGas.FractionConvected;
362 : }
363 8 : }
364 :
365 8 : Real64 zoneOthEqConv(0.0); // zone other equip design convective gain [W]
366 48 : for (auto const &zoneOtherEq : state.dataHeatBal->ZoneOtherEq) {
367 40 : if (zoneOtherEq.ZonePtr == zoneNum) {
368 5 : zoneOthEqConv += zoneOtherEq.DesignLevel * zoneOtherEq.FractionConvected;
369 : }
370 8 : }
371 :
372 8 : Real64 zoneHWEqConv(0.0); // zone hot water equip design convective gain [W]
373 48 : for (auto const &zoneHWEq : state.dataHeatBal->ZoneHWEq) {
374 40 : if (zoneHWEq.ZonePtr == zoneNum) {
375 5 : zoneHWEqConv += zoneHWEq.DesignLevel * zoneHWEq.FractionConvected;
376 : }
377 8 : }
378 :
379 8 : Real64 zoneSteamEqConv(0.0); // zone steam equip design convective gain [W]
380 48 : for (auto const &zoneSteamEq : state.dataHeatBal->ZoneSteamEq) {
381 40 : if (zoneSteamEq.ZonePtr == zoneNum) {
382 5 : zoneSteamEqConv += zoneSteamEq.DesignLevel * zoneSteamEq.FractionConvected;
383 : }
384 8 : }
385 :
386 8 : Real64 numPlumes = (numOccupants > 0.0) ? numOccupants : 1.0;
387 :
388 8 : return (numOccupants * 73.0 + zoneElecConv + zoneGasConv + zoneOthEqConv + zoneHWEqConv + zoneSteamEqConv) / numPlumes;
389 : }
390 :
391 0 : void HcUFAD(EnergyPlusData &state, int const ZoneNum, Real64 const FractionHeight, UFADConvCoef &ufadCC)
392 : {
393 :
394 : // SUBROUTINE INFORMATION:
395 : // AUTHOR G. Carrilho da Graca
396 : // DATE WRITTEN February 2004
397 :
398 : // PURPOSE OF THIS SUBROUTINE:
399 : // Main subroutine for convection calculation in the UCSD Displacement Ventilation model.
400 : // It calls CalcDetailedHcInForDVModel for convection coefficient
401 : // initial calculations and averages the final result comparing the position of the surface with
402 : // the interface subzone height.
403 :
404 : // Using/Aliasing
405 : using namespace DataEnvironment;
406 : using namespace DataHeatBalance;
407 :
408 : // Is the air flow model for this zone set to UCSDDV Displacement Ventilation?
409 0 : if (!state.dataRoomAir->IsZoneUFAD(ZoneNum)) {
410 0 : return;
411 : }
412 :
413 0 : ufadCC.HAT_MX = 0.0; // HAT_MX Convection Coefficient times Area times Temperature for the upper subzone
414 0 : ufadCC.HAT_MXWin = 0.0; // HAT_MX Convection Coefficient times Area times Temperature for the upper subzone (windows only)
415 0 : ufadCC.HA_MX = 0.0; // HA_MX Convection Coefficient times Area for the upper subzone
416 0 : ufadCC.HA_MXWin = 0.0; // HA_MX Convection Coefficient times Area for the upper subzone (windows only)
417 0 : ufadCC.HAT_OC = 0.0; // HAT_OC Convection Coefficient times Area times Temperature for the lower subzone
418 0 : ufadCC.HAT_OCWin = 0.0; // HAT_OC Convection Coefficient times Area times Temperature for the lower subzone (windows only)
419 0 : ufadCC.HA_OC = 0.0; // HA_OC Convection Coefficient times Area for the lower subzone
420 0 : ufadCC.HA_OCWin = 0.0; // HA_OC Convection Coefficient times Area for the lower subzone (windows only)
421 0 : ufadCC.HAT_FLOOR = 0.0; // HAT_FLOOR Convection Coefficient times Area times Temperature for the floor(?) subzone
422 0 : ufadCC.HA_FLOOR = 0.0; // HA_FLOOR Convection Coefficient times Area for the floor(?) subzone
423 :
424 0 : Real64 zoneCeilingHeight1 = state.dataRoomAir->ZoneCeilingHeight1(ZoneNum);
425 0 : Real64 zoneCeilingHeight2 = state.dataRoomAir->ZoneCeilingHeight2(ZoneNum);
426 :
427 0 : Real64 LayH = FractionHeight * (zoneCeilingHeight2 - zoneCeilingHeight1); // Height of the Occupied/Mixed subzone interface
428 :
429 : // WALL Hc, HA and HAT calculation
430 0 : for (int Ctd = state.dataRoomAir->PosZ_Wall(ZoneNum).beg; Ctd <= state.dataRoomAir->PosZ_Wall(ZoneNum).end; ++Ctd) {
431 0 : int SurfNum = state.dataRoomAir->APos_Wall(Ctd);
432 0 : if (SurfNum == 0) {
433 0 : continue;
434 : }
435 :
436 0 : auto &surf = state.dataSurface->Surface(SurfNum);
437 0 : state.dataSurface->SurfTAirRef(SurfNum) = DataSurfaces::RefAirTemp::AdjacentAirTemp;
438 0 : state.dataSurface->SurfTAirRefRpt(SurfNum) = DataSurfaces::SurfTAirRefReportVals[state.dataSurface->SurfTAirRef(SurfNum)];
439 0 : Real64 ZSupSurf = maxval(surf.Vertex, &Vector::z) - zoneCeilingHeight1; // highest height for this surface
440 0 : Real64 ZInfSurf = minval(surf.Vertex, &Vector::z) - zoneCeilingHeight1; // lowest height for this surface
441 :
442 : // The Wall surface is in the upper subzone
443 0 : if (ZInfSurf > LayH) {
444 0 : state.dataHeatBal->SurfTempEffBulkAir(SurfNum) = state.dataRoomAir->ZTMX(ZoneNum);
445 0 : CalcDetailedHcInForDVModel(state, SurfNum, state.dataHeatBalSurf->SurfTempIn, state.dataRoomAir->UFADHcIn);
446 0 : state.dataRoomAir->HWall(Ctd) = state.dataRoomAir->UFADHcIn(SurfNum);
447 0 : ufadCC.HAT_MX += surf.Area * state.dataHeatBalSurf->SurfTempIn(SurfNum) * state.dataRoomAir->HWall(Ctd);
448 0 : ufadCC.HA_MX += surf.Area * state.dataRoomAir->HWall(Ctd);
449 : }
450 :
451 : // The Wall surface is in the lower subzone
452 0 : if (ZSupSurf < LayH) {
453 0 : state.dataHeatBal->SurfTempEffBulkAir(SurfNum) = state.dataRoomAir->ZTOC(ZoneNum);
454 0 : CalcDetailedHcInForDVModel(state, SurfNum, state.dataHeatBalSurf->SurfTempIn, state.dataRoomAir->UFADHcIn);
455 0 : state.dataRoomAir->HWall(Ctd) = state.dataRoomAir->UFADHcIn(SurfNum);
456 0 : ufadCC.HAT_OC += surf.Area * state.dataHeatBalSurf->SurfTempIn(SurfNum) * state.dataRoomAir->HWall(Ctd);
457 0 : ufadCC.HA_OC += surf.Area * state.dataRoomAir->HWall(Ctd);
458 : }
459 :
460 0 : if (std::abs(ZInfSurf - ZSupSurf) < 1.e-10) {
461 0 : ShowSevereError(state, "RoomAirModelUFAD:HcUCSDUF: Surface values will cause divide by zero.");
462 0 : ShowContinueError(state, format("Zone=\"{}\", Surface=\"{}\".", state.dataHeatBal->Zone(surf.Zone).Name, surf.Name));
463 0 : ShowContinueError(state, format("ZInfSurf=[{:.4R}], LayH=[{:.4R}].", ZInfSurf, LayH));
464 0 : ShowContinueError(state, format("ZSupSurf=[{:.4R}], LayH=[{:.4R}].", ZSupSurf, LayH));
465 0 : ShowFatalError(state, "...Previous condition causes termination.");
466 : }
467 :
468 : // The Wall surface is partially in upper and partially in lower subzone
469 0 : if (ZInfSurf <= LayH && ZSupSurf >= LayH) {
470 0 : state.dataHeatBal->SurfTempEffBulkAir(SurfNum) = state.dataRoomAir->ZTMX(ZoneNum);
471 0 : CalcDetailedHcInForDVModel(state, SurfNum, state.dataHeatBalSurf->SurfTempIn, state.dataRoomAir->UFADHcIn);
472 0 : Real64 HLU = state.dataRoomAir->UFADHcIn(SurfNum); // Convection coefficient for the upper area of surface
473 0 : state.dataHeatBal->SurfTempEffBulkAir(SurfNum) = state.dataRoomAir->ZTOC(ZoneNum);
474 0 : CalcDetailedHcInForDVModel(state, SurfNum, state.dataHeatBalSurf->SurfTempIn, state.dataRoomAir->UFADHcIn);
475 0 : Real64 HLD = state.dataRoomAir->UFADHcIn(SurfNum); // Convection coefficient for the lower area of surface
476 0 : Real64 TmedDV = ((ZSupSurf - LayH) * state.dataRoomAir->ZTMX(ZoneNum) + (LayH - ZInfSurf) * state.dataRoomAir->ZTOC(ZoneNum)) /
477 0 : (ZSupSurf - ZInfSurf); // Average temperature for DV
478 0 : state.dataRoomAir->HWall(Ctd) = ((LayH - ZInfSurf) * HLD + (ZSupSurf - LayH) * HLU) / (ZSupSurf - ZInfSurf);
479 0 : ufadCC.HAT_MX += surf.Area * (ZSupSurf - LayH) / (ZSupSurf - ZInfSurf) * state.dataHeatBalSurf->SurfTempIn(SurfNum) * HLU;
480 0 : ufadCC.HA_MX += surf.Area * (ZSupSurf - LayH) / (ZSupSurf - ZInfSurf) * HLU;
481 0 : ufadCC.HAT_OC += surf.Area * (LayH - ZInfSurf) / (ZSupSurf - ZInfSurf) * state.dataHeatBalSurf->SurfTempIn(SurfNum) * HLD;
482 0 : ufadCC.HA_OC += surf.Area * (LayH - ZInfSurf) / (ZSupSurf - ZInfSurf) * HLD;
483 0 : state.dataHeatBal->SurfTempEffBulkAir(SurfNum) = TmedDV;
484 : }
485 :
486 0 : state.dataRoomAir->UFADHcIn(SurfNum) = state.dataRoomAir->HWall(Ctd);
487 :
488 : } // END WALL
489 :
490 : // WINDOW Hc, HA and HAT CALCULATION
491 0 : for (int Ctd = state.dataRoomAir->PosZ_Window(ZoneNum).beg; Ctd <= state.dataRoomAir->PosZ_Window(ZoneNum).end; ++Ctd) {
492 0 : int SurfNum = state.dataRoomAir->APos_Window(Ctd);
493 0 : if (SurfNum == 0) {
494 0 : continue;
495 : }
496 :
497 0 : auto &surf = state.dataSurface->Surface(SurfNum);
498 0 : state.dataSurface->SurfTAirRef(SurfNum) = DataSurfaces::RefAirTemp::AdjacentAirTemp;
499 0 : state.dataSurface->SurfTAirRefRpt(SurfNum) = DataSurfaces::SurfTAirRefReportVals[state.dataSurface->SurfTAirRef(SurfNum)];
500 :
501 0 : if (surf.Tilt > 10.0 && surf.Tilt < 170.0) { // Window Wall
502 0 : Real64 ZSupSurf = maxval(surf.Vertex, &Vector::z) - zoneCeilingHeight1;
503 0 : Real64 ZInfSurf = minval(surf.Vertex, &Vector::z) - zoneCeilingHeight1;
504 :
505 0 : if (ZInfSurf > LayH) {
506 0 : state.dataHeatBal->SurfTempEffBulkAir(SurfNum) = state.dataRoomAir->ZTMX(ZoneNum);
507 0 : CalcDetailedHcInForDVModel(state, SurfNum, state.dataHeatBalSurf->SurfTempIn, state.dataRoomAir->UFADHcIn);
508 0 : state.dataRoomAir->HWindow(Ctd) = state.dataRoomAir->UFADHcIn(SurfNum);
509 0 : ufadCC.HAT_MX += surf.Area * state.dataHeatBalSurf->SurfTempIn(SurfNum) * state.dataRoomAir->HWindow(Ctd);
510 0 : ufadCC.HA_MX += surf.Area * state.dataRoomAir->HWindow(Ctd);
511 0 : ufadCC.HAT_MXWin += surf.Area * state.dataHeatBalSurf->SurfTempIn(SurfNum) * state.dataRoomAir->HWindow(Ctd);
512 0 : ufadCC.HA_MXWin += surf.Area * state.dataRoomAir->HWindow(Ctd);
513 : }
514 :
515 0 : if (ZSupSurf < LayH) {
516 0 : state.dataHeatBal->SurfTempEffBulkAir(SurfNum) = state.dataRoomAir->ZTOC(ZoneNum);
517 0 : CalcDetailedHcInForDVModel(state, SurfNum, state.dataHeatBalSurf->SurfTempIn, state.dataRoomAir->UFADHcIn);
518 0 : state.dataRoomAir->HWindow(Ctd) = state.dataRoomAir->UFADHcIn(SurfNum);
519 0 : ufadCC.HAT_OC += surf.Area * state.dataHeatBalSurf->SurfTempIn(SurfNum) * state.dataRoomAir->HWindow(Ctd);
520 0 : ufadCC.HA_OC += surf.Area * state.dataRoomAir->HWindow(Ctd);
521 0 : ufadCC.HAT_OCWin += surf.Area * state.dataHeatBalSurf->SurfTempIn(SurfNum) * state.dataRoomAir->HWindow(Ctd);
522 0 : ufadCC.HA_OCWin += surf.Area * state.dataRoomAir->HWindow(Ctd);
523 : }
524 :
525 0 : if (ZInfSurf <= LayH && ZSupSurf >= LayH) {
526 0 : state.dataHeatBal->SurfTempEffBulkAir(SurfNum) = state.dataRoomAir->ZTMX(ZoneNum);
527 0 : CalcDetailedHcInForDVModel(state, SurfNum, state.dataHeatBalSurf->SurfTempIn, state.dataRoomAir->UFADHcIn);
528 0 : Real64 HLU = state.dataRoomAir->UFADHcIn(SurfNum); // Convection coefficient for the upper area of surface
529 0 : state.dataHeatBal->SurfTempEffBulkAir(SurfNum) = state.dataRoomAir->ZTOC(ZoneNum);
530 0 : CalcDetailedHcInForDVModel(state, SurfNum, state.dataHeatBalSurf->SurfTempIn, state.dataRoomAir->UFADHcIn);
531 0 : Real64 HLD = state.dataRoomAir->UFADHcIn(SurfNum); // Convection coefficient for the lower area of surface
532 0 : Real64 TmedDV = ((ZSupSurf - LayH) * state.dataRoomAir->ZTMX(ZoneNum) + (LayH - ZInfSurf) * state.dataRoomAir->ZTOC(ZoneNum)) /
533 0 : (ZSupSurf - ZInfSurf); // Average temperature
534 :
535 0 : state.dataRoomAir->HWindow(Ctd) = ((LayH - ZInfSurf) * HLD + (ZSupSurf - LayH) * HLU) / (ZSupSurf - ZInfSurf);
536 0 : ufadCC.HAT_MX += surf.Area * (ZSupSurf - LayH) / (ZSupSurf - ZInfSurf) * state.dataHeatBalSurf->SurfTempIn(SurfNum) * HLU;
537 0 : ufadCC.HA_MX += surf.Area * (ZSupSurf - LayH) / (ZSupSurf - ZInfSurf) * HLU;
538 0 : ufadCC.HAT_MXWin += surf.Area * (ZSupSurf - LayH) / (ZSupSurf - ZInfSurf) * state.dataHeatBalSurf->SurfTempIn(SurfNum) * HLU;
539 0 : ufadCC.HA_MXWin += surf.Area * (ZSupSurf - LayH) / (ZSupSurf - ZInfSurf) * HLU;
540 0 : ufadCC.HAT_OC += surf.Area * (LayH - ZInfSurf) / (ZSupSurf - ZInfSurf) * state.dataHeatBalSurf->SurfTempIn(SurfNum) * HLD;
541 0 : ufadCC.HA_OC += surf.Area * (LayH - ZInfSurf) / (ZSupSurf - ZInfSurf) * HLD;
542 0 : ufadCC.HAT_OCWin += surf.Area * (LayH - ZInfSurf) / (ZSupSurf - ZInfSurf) * state.dataHeatBalSurf->SurfTempIn(SurfNum) * HLD;
543 0 : ufadCC.HA_OCWin += surf.Area * (LayH - ZInfSurf) / (ZSupSurf - ZInfSurf) * HLD;
544 0 : state.dataHeatBal->SurfTempEffBulkAir(SurfNum) = TmedDV;
545 : }
546 : }
547 :
548 0 : if (surf.Tilt <= 10.0) { // Window Ceiling
549 0 : state.dataHeatBal->SurfTempEffBulkAir(SurfNum) = state.dataRoomAir->ZTMX(ZoneNum);
550 0 : CalcDetailedHcInForDVModel(state, SurfNum, state.dataHeatBalSurf->SurfTempIn, state.dataRoomAir->UFADHcIn);
551 0 : state.dataRoomAir->HWindow(Ctd) = state.dataRoomAir->UFADHcIn(SurfNum);
552 0 : ufadCC.HAT_MX += surf.Area * state.dataHeatBalSurf->SurfTempIn(SurfNum) * state.dataRoomAir->HWindow(Ctd);
553 0 : ufadCC.HA_MX += surf.Area * state.dataRoomAir->HWindow(Ctd);
554 0 : } else if (surf.Tilt >= 170.0) { // Window Floor
555 0 : state.dataHeatBal->SurfTempEffBulkAir(SurfNum) = state.dataRoomAir->ZTOC(ZoneNum);
556 0 : CalcDetailedHcInForDVModel(state, SurfNum, state.dataHeatBalSurf->SurfTempIn, state.dataRoomAir->UFADHcIn);
557 0 : state.dataRoomAir->HWindow(Ctd) = state.dataRoomAir->UFADHcIn(SurfNum);
558 0 : ufadCC.HAT_OC += surf.Area * state.dataHeatBalSurf->SurfTempIn(SurfNum) * state.dataRoomAir->HWindow(Ctd);
559 0 : ufadCC.HA_OC += surf.Area * state.dataRoomAir->HWindow(Ctd);
560 : }
561 :
562 0 : state.dataRoomAir->UFADHcIn(SurfNum) = state.dataRoomAir->HWindow(Ctd);
563 :
564 : } // END WINDOW
565 :
566 : // DOOR Hc, HA and HAT CALCULATION
567 0 : for (int Ctd = state.dataRoomAir->PosZ_Door(ZoneNum).beg; Ctd <= state.dataRoomAir->PosZ_Door(ZoneNum).end; ++Ctd) { // DOOR
568 0 : int SurfNum = state.dataRoomAir->APos_Door(Ctd);
569 0 : if (SurfNum == 0) {
570 0 : continue;
571 : }
572 0 : auto &surf = state.dataSurface->Surface(SurfNum);
573 0 : state.dataSurface->SurfTAirRef(SurfNum) = DataSurfaces::RefAirTemp::AdjacentAirTemp;
574 0 : state.dataSurface->SurfTAirRefRpt(SurfNum) = DataSurfaces::SurfTAirRefReportVals[state.dataSurface->SurfTAirRef(SurfNum)];
575 :
576 0 : Real64 ZSupSurf = maxval(surf.Vertex, &Vector::z) - zoneCeilingHeight1;
577 0 : Real64 ZInfSurf = minval(surf.Vertex, &Vector::z) - zoneCeilingHeight1;
578 :
579 0 : if (ZInfSurf > LayH) {
580 0 : state.dataHeatBal->SurfTempEffBulkAir(SurfNum) = state.dataRoomAir->ZTMX(ZoneNum);
581 0 : CalcDetailedHcInForDVModel(state, SurfNum, state.dataHeatBalSurf->SurfTempIn, state.dataRoomAir->UFADHcIn);
582 0 : state.dataRoomAir->HDoor(Ctd) = state.dataRoomAir->UFADHcIn(SurfNum);
583 0 : ufadCC.HAT_MX += surf.Area * state.dataHeatBalSurf->SurfTempIn(SurfNum) * state.dataRoomAir->HDoor(Ctd);
584 0 : ufadCC.HA_MX += surf.Area * state.dataRoomAir->HDoor(Ctd);
585 : }
586 :
587 0 : if (ZSupSurf < LayH) {
588 0 : state.dataHeatBal->SurfTempEffBulkAir(SurfNum) = state.dataRoomAir->ZTOC(ZoneNum);
589 0 : CalcDetailedHcInForDVModel(state, SurfNum, state.dataHeatBalSurf->SurfTempIn, state.dataRoomAir->UFADHcIn);
590 0 : state.dataRoomAir->HDoor(Ctd) = state.dataRoomAir->UFADHcIn(SurfNum);
591 0 : ufadCC.HAT_OC += surf.Area * state.dataHeatBalSurf->SurfTempIn(SurfNum) * state.dataRoomAir->HDoor(Ctd);
592 0 : ufadCC.HA_OC += surf.Area * state.dataRoomAir->HDoor(Ctd);
593 : }
594 :
595 0 : if (ZInfSurf <= LayH && ZSupSurf >= LayH) {
596 0 : state.dataHeatBal->SurfTempEffBulkAir(SurfNum) = state.dataRoomAir->ZTMX(ZoneNum);
597 0 : CalcDetailedHcInForDVModel(state, SurfNum, state.dataHeatBalSurf->SurfTempIn, state.dataRoomAir->UFADHcIn);
598 0 : Real64 HLU = state.dataRoomAir->UFADHcIn(SurfNum); // Convection coefficient for the upper area of surface
599 0 : state.dataHeatBal->SurfTempEffBulkAir(SurfNum) = state.dataRoomAir->ZTOC(ZoneNum);
600 0 : CalcDetailedHcInForDVModel(state, SurfNum, state.dataHeatBalSurf->SurfTempIn, state.dataRoomAir->UFADHcIn);
601 0 : Real64 HLD = state.dataRoomAir->UFADHcIn(SurfNum); // Convection coefficient for the lower area of surface
602 0 : Real64 TmedDV = ((ZSupSurf - LayH) * state.dataRoomAir->ZTMX(ZoneNum) + (LayH - ZInfSurf) * state.dataRoomAir->ZTOC(ZoneNum)) /
603 0 : (ZSupSurf - ZInfSurf); // Average temperature
604 0 : state.dataRoomAir->HDoor(Ctd) = ((LayH - ZInfSurf) * HLD + (ZSupSurf - LayH) * HLU) / (ZSupSurf - ZInfSurf);
605 0 : ufadCC.HAT_MX += surf.Area * (ZSupSurf - LayH) / (ZSupSurf - ZInfSurf) * state.dataHeatBalSurf->SurfTempIn(SurfNum) * HLU;
606 0 : ufadCC.HA_MX += surf.Area * (ZSupSurf - LayH) / (ZSupSurf - ZInfSurf) * HLU;
607 0 : ufadCC.HAT_OC += surf.Area * (LayH - ZInfSurf) / (ZSupSurf - ZInfSurf) * state.dataHeatBalSurf->SurfTempIn(SurfNum) * HLD;
608 0 : ufadCC.HA_OC += surf.Area * (LayH - ZInfSurf) / (ZSupSurf - ZInfSurf) * HLD;
609 0 : state.dataHeatBal->SurfTempEffBulkAir(SurfNum) = TmedDV;
610 : }
611 :
612 0 : state.dataRoomAir->UFADHcIn(SurfNum) = state.dataRoomAir->HDoor(Ctd);
613 :
614 : } // END DOOR
615 :
616 : // INTERNAL Hc, HA and HAT CALCULATION
617 0 : state.dataUFADManager->HeightIntMass = min(state.dataUFADManager->HeightIntMassDefault, (zoneCeilingHeight2 - zoneCeilingHeight1));
618 0 : for (int Ctd = state.dataRoomAir->PosZ_Internal(ZoneNum).beg; Ctd <= state.dataRoomAir->PosZ_Internal(ZoneNum).end; ++Ctd) {
619 0 : int SurfNum = state.dataRoomAir->APos_Internal(Ctd);
620 0 : if (SurfNum == 0) {
621 0 : continue;
622 : }
623 :
624 0 : auto const &surf = state.dataSurface->Surface(SurfNum);
625 0 : state.dataSurface->SurfTAirRef(SurfNum) = DataSurfaces::RefAirTemp::AdjacentAirTemp;
626 0 : state.dataSurface->SurfTAirRefRpt(SurfNum) = DataSurfaces::SurfTAirRefReportVals[state.dataSurface->SurfTAirRef(SurfNum)];
627 0 : Real64 ZSupSurf = state.dataUFADManager->HeightIntMass;
628 0 : Real64 ZInfSurf = 0.0;
629 :
630 0 : if (ZSupSurf < LayH) {
631 0 : state.dataHeatBal->SurfTempEffBulkAir(SurfNum) = state.dataRoomAir->ZTOC(ZoneNum);
632 0 : CalcDetailedHcInForDVModel(state, SurfNum, state.dataHeatBalSurf->SurfTempIn, state.dataRoomAir->UFADHcIn);
633 0 : state.dataRoomAir->HInternal(Ctd) = state.dataRoomAir->UFADHcIn(SurfNum);
634 0 : ufadCC.HAT_OC += surf.Area * state.dataHeatBalSurf->SurfTempIn(SurfNum) * state.dataRoomAir->HInternal(Ctd);
635 0 : ufadCC.HA_OC += surf.Area * state.dataRoomAir->HInternal(Ctd);
636 : }
637 :
638 0 : if (ZInfSurf <= LayH && ZSupSurf >= LayH) {
639 0 : state.dataHeatBal->SurfTempEffBulkAir(SurfNum) = state.dataRoomAir->ZTMX(ZoneNum);
640 0 : CalcDetailedHcInForDVModel(state, SurfNum, state.dataHeatBalSurf->SurfTempIn, state.dataRoomAir->UFADHcIn);
641 0 : Real64 HLU = state.dataRoomAir->UFADHcIn(SurfNum); // Convection coefficient for the upper area of surface
642 0 : state.dataHeatBal->SurfTempEffBulkAir(SurfNum) = state.dataRoomAir->ZTOC(ZoneNum);
643 0 : CalcDetailedHcInForDVModel(state, SurfNum, state.dataHeatBalSurf->SurfTempIn, state.dataRoomAir->UFADHcIn);
644 0 : Real64 HLD = state.dataRoomAir->UFADHcIn(SurfNum); // Convection coefficient for the lower area of surface
645 0 : Real64 TmedDV = ((ZSupSurf - LayH) * state.dataRoomAir->ZTMX(ZoneNum) + (LayH - ZInfSurf) * state.dataRoomAir->ZTOC(ZoneNum)) /
646 0 : (ZSupSurf - ZInfSurf); // Average temperature
647 0 : state.dataRoomAir->HInternal(Ctd) = ((LayH - ZInfSurf) * HLD + (ZSupSurf - LayH) * HLU) / (ZSupSurf - ZInfSurf);
648 0 : ufadCC.HAT_MX += surf.Area * (ZSupSurf - LayH) / (ZSupSurf - ZInfSurf) * state.dataHeatBalSurf->SurfTempIn(SurfNum) * HLU;
649 0 : ufadCC.HA_MX += surf.Area * (ZSupSurf - LayH) / (ZSupSurf - ZInfSurf) * HLU;
650 0 : ufadCC.HAT_OC += surf.Area * (LayH - ZInfSurf) / (ZSupSurf - ZInfSurf) * state.dataHeatBalSurf->SurfTempIn(SurfNum) * HLD;
651 0 : ufadCC.HA_OC += surf.Area * (LayH - ZInfSurf) / (ZSupSurf - ZInfSurf) * HLD;
652 0 : state.dataHeatBal->SurfTempEffBulkAir(SurfNum) = TmedDV;
653 : }
654 :
655 0 : state.dataRoomAir->UFADHcIn(SurfNum) = state.dataRoomAir->HInternal(Ctd);
656 : } // END INTERNAL
657 :
658 : // CEILING Hc, HA and HAT CALCULATION
659 0 : for (int Ctd = state.dataRoomAir->PosZ_Ceiling(ZoneNum).beg; Ctd <= state.dataRoomAir->PosZ_Ceiling(ZoneNum).end; ++Ctd) {
660 0 : int SurfNum = state.dataRoomAir->APos_Ceiling(Ctd);
661 0 : if (SurfNum == 0) {
662 0 : continue;
663 : }
664 0 : auto const &surf = state.dataSurface->Surface(SurfNum);
665 :
666 0 : state.dataSurface->SurfTAirRef(SurfNum) = DataSurfaces::RefAirTemp::AdjacentAirTemp;
667 0 : state.dataSurface->SurfTAirRefRpt(SurfNum) = DataSurfaces::SurfTAirRefReportVals[state.dataSurface->SurfTAirRef(SurfNum)];
668 0 : state.dataHeatBal->SurfTempEffBulkAir(SurfNum) = state.dataRoomAir->ZTMX(ZoneNum);
669 0 : CalcDetailedHcInForDVModel(state, SurfNum, state.dataHeatBalSurf->SurfTempIn, state.dataRoomAir->UFADHcIn);
670 0 : state.dataRoomAir->HCeiling(Ctd) = state.dataRoomAir->UFADHcIn(SurfNum);
671 0 : ufadCC.HAT_MX += surf.Area * state.dataHeatBalSurf->SurfTempIn(SurfNum) * state.dataRoomAir->HCeiling(Ctd);
672 0 : ufadCC.HA_MX += surf.Area * state.dataRoomAir->HCeiling(Ctd);
673 0 : state.dataRoomAir->UFADHcIn(SurfNum) = state.dataRoomAir->HCeiling(Ctd);
674 : } // END CEILING
675 :
676 : // FLOOR Hc, HA and HAT CALCULATION
677 0 : for (int Ctd = state.dataRoomAir->PosZ_Floor(ZoneNum).beg; Ctd <= state.dataRoomAir->PosZ_Floor(ZoneNum).end; ++Ctd) {
678 0 : int SurfNum = state.dataRoomAir->APos_Floor(Ctd);
679 0 : if (SurfNum == 0) {
680 0 : continue;
681 : }
682 0 : auto const &surf = state.dataSurface->Surface(SurfNum);
683 :
684 0 : state.dataSurface->SurfTAirRef(SurfNum) = DataSurfaces::RefAirTemp::AdjacentAirTemp;
685 0 : state.dataSurface->SurfTAirRefRpt(SurfNum) = DataSurfaces::SurfTAirRefReportVals[state.dataSurface->SurfTAirRef(SurfNum)];
686 0 : state.dataHeatBal->SurfTempEffBulkAir(SurfNum) = state.dataRoomAir->ZTFloor(ZoneNum);
687 0 : CalcDetailedHcInForDVModel(state, SurfNum, state.dataHeatBalSurf->SurfTempIn, state.dataRoomAir->UFADHcIn);
688 0 : state.dataRoomAir->HFloor(Ctd) = state.dataRoomAir->UFADHcIn(SurfNum);
689 0 : ufadCC.HAT_OC += surf.Area * state.dataHeatBalSurf->SurfTempIn(SurfNum) * state.dataRoomAir->HFloor(Ctd);
690 0 : ufadCC.HA_OC += surf.Area * state.dataRoomAir->HFloor(Ctd);
691 0 : state.dataHeatBal->SurfTempEffBulkAir(SurfNum) = state.dataRoomAir->ZTFloor(ZoneNum);
692 0 : state.dataRoomAir->UFADHcIn(SurfNum) = state.dataRoomAir->HFloor(Ctd);
693 : } // END FLOOR
694 : }
695 :
696 : static constexpr std::array<DataHeatBalance::IntGainType, 51> IntGainTypesOccupied = {
697 : DataHeatBalance::IntGainType::People,
698 : DataHeatBalance::IntGainType::WaterHeaterMixed,
699 : DataHeatBalance::IntGainType::WaterHeaterStratified,
700 : DataHeatBalance::IntGainType::ThermalStorageChilledWaterMixed,
701 : DataHeatBalance::IntGainType::ThermalStorageChilledWaterStratified,
702 : DataHeatBalance::IntGainType::ElectricEquipment,
703 : DataHeatBalance::IntGainType::ElectricEquipmentITEAirCooled,
704 : DataHeatBalance::IntGainType::GasEquipment,
705 : DataHeatBalance::IntGainType::HotWaterEquipment,
706 : DataHeatBalance::IntGainType::SteamEquipment,
707 : DataHeatBalance::IntGainType::OtherEquipment,
708 : DataHeatBalance::IntGainType::IndoorGreen,
709 : DataHeatBalance::IntGainType::ZoneBaseboardOutdoorTemperatureControlled,
710 : DataHeatBalance::IntGainType::GeneratorFuelCell,
711 : DataHeatBalance::IntGainType::WaterUseEquipment,
712 : DataHeatBalance::IntGainType::GeneratorMicroCHP,
713 : DataHeatBalance::IntGainType::ElectricLoadCenterTransformer,
714 : DataHeatBalance::IntGainType::ElectricLoadCenterInverterSimple,
715 : DataHeatBalance::IntGainType::ElectricLoadCenterInverterFunctionOfPower,
716 : DataHeatBalance::IntGainType::ElectricLoadCenterInverterLookUpTable,
717 : DataHeatBalance::IntGainType::ElectricLoadCenterStorageBattery,
718 : DataHeatBalance::IntGainType::ElectricLoadCenterStorageLiIonNmcBattery,
719 : DataHeatBalance::IntGainType::ElectricLoadCenterStorageSimple,
720 : DataHeatBalance::IntGainType::PipeIndoor,
721 : DataHeatBalance::IntGainType::RefrigerationCase,
722 : DataHeatBalance::IntGainType::RefrigerationCompressorRack,
723 : DataHeatBalance::IntGainType::RefrigerationSystemAirCooledCondenser,
724 : DataHeatBalance::IntGainType::RefrigerationSystemSuctionPipe,
725 : DataHeatBalance::IntGainType::RefrigerationSecondaryReceiver,
726 : DataHeatBalance::IntGainType::RefrigerationSecondaryPipe,
727 : DataHeatBalance::IntGainType::RefrigerationWalkIn,
728 : DataHeatBalance::IntGainType::RefrigerationTransSysAirCooledGasCooler,
729 : DataHeatBalance::IntGainType::RefrigerationTransSysSuctionPipeMT,
730 : DataHeatBalance::IntGainType::RefrigerationTransSysSuctionPipeLT,
731 : DataHeatBalance::IntGainType::Pump_VarSpeed,
732 : DataHeatBalance::IntGainType::Pump_ConSpeed,
733 : DataHeatBalance::IntGainType::Pump_Cond,
734 : DataHeatBalance::IntGainType::PumpBank_VarSpeed,
735 : DataHeatBalance::IntGainType::PumpBank_ConSpeed,
736 : DataHeatBalance::IntGainType::PlantComponentUserDefined,
737 : DataHeatBalance::IntGainType::CoilUserDefined,
738 : DataHeatBalance::IntGainType::ZoneHVACForcedAirUserDefined,
739 : DataHeatBalance::IntGainType::AirTerminalUserDefined,
740 : DataHeatBalance::IntGainType::PackagedTESCoilTank,
741 : DataHeatBalance::IntGainType::SecCoolingDXCoilSingleSpeed,
742 : DataHeatBalance::IntGainType::SecHeatingDXCoilSingleSpeed,
743 : DataHeatBalance::IntGainType::SecCoolingDXCoilTwoSpeed,
744 : DataHeatBalance::IntGainType::SecCoolingDXCoilMultiSpeed,
745 : DataHeatBalance::IntGainType::SecHeatingDXCoilMultiSpeed,
746 : DataHeatBalance::IntGainType::ElectricLoadCenterConverter,
747 : DataHeatBalance::IntGainType::FanSystemModel};
748 :
749 : static constexpr std::array<DataHeatBalance::IntGainType, 2> IntGainTypesUpSubzone = {DataHeatBalance::IntGainType::DaylightingDeviceTubular,
750 : DataHeatBalance::IntGainType::Lights};
751 :
752 : // Explicitly list internal gains not applicable for UFAD
753 : // Explicitly list internal gains not applicable for Displacement Vent
754 : static constexpr std::array<DataHeatBalance::IntGainType, 2> ExcludedIntGainTypes = {
755 : DataHeatBalance::IntGainType::ZoneContaminantSourceAndSinkCarbonDioxide,
756 : DataHeatBalance::IntGainType::ZoneContaminantSourceAndSinkGenericContam};
757 :
758 0 : void CalcUFADInt(EnergyPlusData &state, int const ZoneNum) // index number for the specified zone
759 : {
760 :
761 : // SUBROUTINE INFORMATION:
762 : // AUTHOR Fred Buhl
763 : // DATE WRITTEN August 2005
764 : // MODIFIED Brent Griffith June 2008 for new interpolation and time history
765 : // RE-ENGINEERED na
766 :
767 : // PURPOSE OF THIS SUBROUTINE:
768 : // Using the UCSD UFAD interior zone model, this subroutine calculates the occupied subzone height,
769 : // surface heat transfer coefficients, the occupied subzone temperature, and the upper subzone temperature.
770 :
771 : // METHODOLOGY EMPLOYED:
772 : // The zone is divided into 2 subzones with a variable transition height.
773 :
774 : // REFERENCES:
775 : // The model is described in the EnergyPlus Engineering Reference in Anna Liu's UCSD PhD thesis.
776 :
777 : // Using/Aliasing
778 : using Psychrometrics::PsyCpAirFnW;
779 : using Psychrometrics::PsyRhoAirFnPbTdbW;
780 0 : Real64 TimeStepSys = state.dataHVACGlobal->TimeStepSys;
781 0 : Real64 TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
782 :
783 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
784 :
785 : Real64 HeightFrac; // Fractional height of transition between occupied and upper subzones
786 : Real64 Gamma; // dimensionless height parameter; higher gamma means interface height will be
787 : // higher, smaller gamma means interface height will be lower.
788 : Real64 ZTAveraged;
789 :
790 : // Exact solution or Euler method
791 0 : if (state.dataHeatBal->ZoneAirSolutionAlgo != DataHeatBalance::SolutionAlgo::ThirdOrder) {
792 0 : if (state.dataHVACGlobal->ShortenTimeStepSysRoomAir && TimeStepSys < state.dataGlobal->TimeStepZone) {
793 0 : if (state.dataHVACGlobal->PreviousTimeStep < state.dataGlobal->TimeStepZone) {
794 0 : state.dataRoomAir->Zone1OC(ZoneNum) = state.dataRoomAir->ZoneM2OC(ZoneNum);
795 0 : state.dataRoomAir->Zone1MX(ZoneNum) = state.dataRoomAir->ZoneM2MX(ZoneNum);
796 : } else {
797 0 : state.dataRoomAir->Zone1OC(ZoneNum) = state.dataRoomAir->ZoneMXOC(ZoneNum);
798 0 : state.dataRoomAir->Zone1MX(ZoneNum) = state.dataRoomAir->ZoneMXMX(ZoneNum);
799 : }
800 : } else {
801 0 : state.dataRoomAir->Zone1OC(ZoneNum) = state.dataRoomAir->ZTOC(ZoneNum);
802 0 : state.dataRoomAir->Zone1MX(ZoneNum) = state.dataRoomAir->ZTMX(ZoneNum);
803 : }
804 : }
805 :
806 0 : auto &thisZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum);
807 0 : bool MIXFLAG = false;
808 0 : state.dataRoomAir->UFADHcIn = state.dataHeatBalSurf->SurfHConvInt;
809 0 : Real64 SumSysMCp = 0.0; // Sum of system mass flow rate * specific heat for this zone [W/K]
810 0 : Real64 SumSysMCpT = 0.0; // Sum of system mass flow rate * specific heat * temperature for this zone [W]
811 0 : Real64 TSupK = 0.0; // supply temperature [K]
812 0 : Real64 SumSysM = 0.0; // Sum of systems mass flow rate [kg/s]
813 0 : Real64 TotSysFlow = 0.0; // [m3/s]
814 0 : int ZoneMult = state.dataHeatBal->Zone(ZoneNum).Multiplier * state.dataHeatBal->Zone(ZoneNum).ListMultiplier;
815 0 : Real64 CeilingHeight = state.dataRoomAir->ZoneCeilingHeight2(ZoneNum) - state.dataRoomAir->ZoneCeilingHeight1(ZoneNum);
816 :
817 0 : auto &zoneU = state.dataRoomAir->ZoneUFAD(state.dataRoomAir->ZoneUFADPtr(ZoneNum));
818 0 : Real64 HeightThermostat = zoneU.ThermostatHeight; // height of the thermostat above the floor [m]
819 0 : Real64 HeightComfort = zoneU.ComfortHeight; // height at which comfort temperature is calculated
820 0 : Real64 TempDiffCritRep = zoneU.TempTrigger; // Minimum temperature difference between upper and occupied subzones for reporting
821 0 : Real64 DiffArea = zoneU.DiffArea; // diffuser effective area [m2]
822 0 : Real64 ThrowAngle = Constant::DegToRad * zoneU.DiffAngle; // diffuser slot angle relative to vertical [radians]
823 0 : Real64 SourceHeight = 0.0; // height of plume sources above the floor [m]
824 0 : Real64 NumDiffusers = zoneU.DiffusersPerZone;
825 0 : Real64 PowerPerPlume = zoneU.PowerPerPlume;
826 : // gains from occupants, task lighting, elec equip, gas equip, other equip, hot water equip, steam equip,
827 : // baseboards (nonthermostatic), water heater skin loss
828 0 : Real64 ConvGainsOccSubzone = InternalHeatGains::SumInternalConvectionGainsByTypes(state, ZoneNum, IntGainTypesOccupied);
829 :
830 : // Add heat to return air if zonal system (no return air) or cycling system (return air frequently very
831 : // low or zero)
832 0 : if (state.dataHeatBal->Zone(ZoneNum).NoHeatToReturnAir) {
833 0 : ConvGainsOccSubzone += InternalHeatGains::SumReturnAirConvectionGainsByTypes(state, ZoneNum, IntGainTypesOccupied);
834 : }
835 :
836 : // Add convection from pool cover to occupied region
837 0 : ConvGainsOccSubzone += state.dataHeatBalFanSys->SumConvPool(ZoneNum);
838 :
839 : // gains from lights (ceiling), tubular daylighting devices, high temp radiant heaters
840 :
841 0 : Real64 ConvGainsUpSubzone = InternalHeatGains::SumInternalConvectionGainsByTypes(state, ZoneNum, IntGainTypesUpSubzone);
842 0 : ConvGainsUpSubzone += state.dataHeatBalFanSys->SumConvHTRadSys(ZoneNum);
843 0 : if (state.dataHeatBal->Zone(ZoneNum).NoHeatToReturnAir) {
844 0 : ConvGainsUpSubzone += InternalHeatGains::SumReturnAirConvectionGainsByTypes(state, ZoneNum, IntGainTypesUpSubzone);
845 : }
846 :
847 : // Make sure all types of internal gains have been gathered
848 0 : assert((int)(size(IntGainTypesOccupied) + size(IntGainTypesUpSubzone) + size(ExcludedIntGainTypes)) ==
849 : (int)DataHeatBalance::IntGainType::Num);
850 :
851 0 : Real64 ConvGains = ConvGainsOccSubzone + ConvGainsUpSubzone + thisZoneHB.SysDepZoneLoadsLagged;
852 0 : Real64 ZoneEquipConfigNum = zoneU.ZoneEquipPtr;
853 0 : if (ZoneEquipConfigNum > 0) {
854 0 : auto const &zoneEquipConfig = state.dataZoneEquip->ZoneEquipConfig(ZoneEquipConfigNum);
855 0 : for (int InNodeIndex = 1; InNodeIndex <= zoneEquipConfig.NumInletNodes; ++InNodeIndex) {
856 0 : Real64 NodeTemp = state.dataLoopNodes->Node(zoneEquipConfig.InletNode(InNodeIndex)).Temp;
857 0 : Real64 MassFlowRate = state.dataLoopNodes->Node(zoneEquipConfig.InletNode(InNodeIndex)).MassFlowRate;
858 0 : Real64 CpAir = PsyCpAirFnW(thisZoneHB.airHumRat);
859 0 : SumSysMCp += MassFlowRate * CpAir;
860 0 : SumSysMCpT += MassFlowRate * CpAir * NodeTemp;
861 0 : TotSysFlow += MassFlowRate / PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, NodeTemp, thisZoneHB.airHumRat);
862 0 : TSupK += MassFlowRate * NodeTemp;
863 0 : SumSysM += MassFlowRate;
864 : }
865 0 : if (TotSysFlow > 0.0) {
866 0 : TSupK = TSupK / SumSysM + Constant::Kelvin;
867 : } else {
868 0 : TSupK = 0.0;
869 : }
870 : }
871 : // mass flow rate * specific heat for this zone for infiltration, ventilation, mixing [W/K]
872 0 : Real64 SumMCp = thisZoneHB.MCPI + thisZoneHB.MCPV + thisZoneHB.MCPM + thisZoneHB.MCPE + thisZoneHB.MCPC + thisZoneHB.MDotCPOA;
873 : // mass flow rate * specific heat* temp for this zone for infiltration, ventilation, mixing [W]
874 0 : Real64 SumMCpT = thisZoneHB.MCPTI + thisZoneHB.MCPTV + thisZoneHB.MCPTM + thisZoneHB.MCPTE + thisZoneHB.MCPTC +
875 0 : thisZoneHB.MDotCPOA * state.dataHeatBal->Zone(ZoneNum).OutDryBulbTemp;
876 0 : Real64 MCp_Total = SumMCp + SumSysMCp; // total mass flow rate * specific heat for this zone [W/K]
877 0 : Real64 MCpT_Total = SumMCpT + SumSysMCpT; // total mass flow rate * specific heat* temp for this zone [W]
878 : // For the York MIT diffusers (variable area) the area varies with the flow rate. Assume 400 ft/min velocity
879 : // at the diffuser, and a design flow rate of 150 cfm (.0708 m3/s). Then the design area for each diffuser is
880 : // 150 ft3/min / 400 ft/min = .375 ft2 = .035 m2. This is adjusted each time step by
881 : // (TotSysFlow/(NumDiffusers*.0708))*.035
882 0 : if (zoneU.DiffuserType == Diffuser::VarArea) {
883 0 : DiffArea = 0.035 * TotSysFlow / (0.0708 * NumDiffusers);
884 : }
885 : // initial estimate of convective transfer from surfaces; assume HeightFrac is 0.5.
886 0 : UFADConvCoef ufadCC;
887 0 : HcUFAD(state, ZoneNum, 0.5, ufadCC);
888 0 : Real64 PowerInPlumes = ConvGains + ufadCC.HAT_OC - ufadCC.HA_OC * state.dataRoomAir->ZTOC(ZoneNum) + ufadCC.HAT_MX -
889 0 : ufadCC.HA_MX * state.dataRoomAir->ZTMX(ZoneNum);
890 :
891 0 : Real64 NumberOfPlumes = (PowerPerPlume > 0.0 && PowerInPlumes > 0.0) ? (PowerInPlumes / PowerPerPlume) : 1.0;
892 0 : Real64 NumDiffusersPerPlume = (PowerPerPlume > 0.0 && PowerInPlumes > 0.0) ? (NumDiffusers / NumberOfPlumes) : 1.0;
893 :
894 0 : if ((PowerInPlumes <= 0.0) || (TotSysFlow == 0.0) || (TSupK - Constant::Kelvin) > thisZoneHB.MAT) {
895 : // The system will mix
896 0 : HeightFrac = 0.0;
897 : } else {
898 0 : Gamma = std::pow(TotSysFlow * std::cos(ThrowAngle), 1.5) /
899 0 : (NumberOfPlumes * std::pow(NumDiffusersPerPlume * DiffArea, 1.25) * std::sqrt(0.0281 * 0.001 * PowerInPlumes));
900 0 : if (zoneU.CalcTransHeight) {
901 0 : HeightFrac = (std::sqrt(NumDiffusersPerPlume * DiffArea) * (7.43 * std::log(Gamma) - 1.35) + 0.5 * SourceHeight) / CeilingHeight;
902 : } else {
903 0 : HeightFrac = zoneU.TransHeight / CeilingHeight;
904 : }
905 0 : HeightFrac = max(0.0, min(1.0, HeightFrac));
906 0 : for (int Ctd = 1; Ctd <= 4; ++Ctd) {
907 0 : HcUFAD(state, ZoneNum, HeightFrac, ufadCC);
908 0 : PowerInPlumes = ConvGains + ufadCC.HAT_OC - ufadCC.HA_OC * state.dataRoomAir->ZTOC(ZoneNum) + ufadCC.HAT_MX -
909 0 : ufadCC.HA_MX * state.dataRoomAir->ZTMX(ZoneNum);
910 0 : if (PowerPerPlume > 0.0 && PowerInPlumes > 0.0) {
911 0 : NumberOfPlumes = PowerInPlumes / PowerPerPlume;
912 0 : NumDiffusersPerPlume = NumDiffusers / NumberOfPlumes;
913 : } else {
914 0 : NumberOfPlumes = 1.0;
915 0 : NumDiffusersPerPlume = 1.0;
916 : }
917 0 : if (PowerInPlumes <= 0.0) {
918 0 : break;
919 : }
920 0 : Gamma = std::pow(TotSysFlow * std::cos(ThrowAngle), 1.5) /
921 0 : (NumberOfPlumes * std::pow(NumDiffusersPerPlume * DiffArea, 1.25) * std::sqrt(0.0281 * 0.001 * PowerInPlumes));
922 0 : if (zoneU.CalcTransHeight) {
923 0 : HeightFrac = (std::sqrt(NumDiffusersPerPlume * DiffArea) * (7.43 * std::log(Gamma) - 1.35) + 0.5 * SourceHeight) / CeilingHeight;
924 : } else {
925 0 : HeightFrac = zoneU.TransHeight / CeilingHeight;
926 : }
927 0 : HeightFrac = max(0.0, min(1.0, HeightFrac));
928 0 : state.dataRoomAir->HeightTransition(ZoneNum) = HeightFrac * CeilingHeight;
929 0 : Real64 GainsFrac = zoneU.A_Kc * std::pow(Gamma, zoneU.B_Kc) + zoneU.C_Kc + zoneU.D_Kc * Gamma + zoneU.E_Kc * pow_2(Gamma);
930 0 : GainsFrac = max(0.6, min(GainsFrac, 1.0));
931 0 : state.dataRoomAir->AIRRATOC(ZoneNum) =
932 0 : state.dataHeatBal->Zone(ZoneNum).Volume *
933 0 : (state.dataRoomAir->HeightTransition(ZoneNum) - min(state.dataRoomAir->HeightTransition(ZoneNum), 0.2)) / CeilingHeight *
934 0 : state.dataHeatBal->Zone(ZoneNum).ZoneVolCapMultpSens *
935 0 : PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, state.dataRoomAir->MATOC(ZoneNum), thisZoneHB.airHumRat) *
936 0 : PsyCpAirFnW(thisZoneHB.airHumRat) / TimeStepSysSec;
937 0 : state.dataRoomAir->AIRRATMX(ZoneNum) =
938 0 : state.dataHeatBal->Zone(ZoneNum).Volume * (CeilingHeight - state.dataRoomAir->HeightTransition(ZoneNum)) / CeilingHeight *
939 0 : state.dataHeatBal->Zone(ZoneNum).ZoneVolCapMultpSens *
940 0 : PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, state.dataRoomAir->MATMX(ZoneNum), thisZoneHB.airHumRat) *
941 0 : PsyCpAirFnW(thisZoneHB.airHumRat) / TimeStepSysSec;
942 :
943 0 : if (state.dataHVACGlobal->UseZoneTimeStepHistory) {
944 0 : state.dataRoomAir->ZTMOC(ZoneNum)[2] = state.dataRoomAir->XMATOC(ZoneNum)[2];
945 0 : state.dataRoomAir->ZTMOC(ZoneNum)[1] = state.dataRoomAir->XMATOC(ZoneNum)[1];
946 0 : state.dataRoomAir->ZTMOC(ZoneNum)[0] = state.dataRoomAir->XMATOC(ZoneNum)[0];
947 :
948 0 : state.dataRoomAir->ZTMMX(ZoneNum)[2] = state.dataRoomAir->XMATMX(ZoneNum)[2];
949 0 : state.dataRoomAir->ZTMMX(ZoneNum)[1] = state.dataRoomAir->XMATMX(ZoneNum)[1];
950 0 : state.dataRoomAir->ZTMMX(ZoneNum)[0] = state.dataRoomAir->XMATMX(ZoneNum)[0];
951 :
952 : } else {
953 0 : state.dataRoomAir->ZTMOC(ZoneNum)[2] = state.dataRoomAir->DSXMATOC(ZoneNum)[2];
954 0 : state.dataRoomAir->ZTMOC(ZoneNum)[1] = state.dataRoomAir->DSXMATOC(ZoneNum)[1];
955 0 : state.dataRoomAir->ZTMOC(ZoneNum)[0] = state.dataRoomAir->DSXMATOC(ZoneNum)[0];
956 :
957 0 : state.dataRoomAir->ZTMMX(ZoneNum)[2] = state.dataRoomAir->DSXMATMX(ZoneNum)[2];
958 0 : state.dataRoomAir->ZTMMX(ZoneNum)[1] = state.dataRoomAir->DSXMATMX(ZoneNum)[1];
959 0 : state.dataRoomAir->ZTMMX(ZoneNum)[0] = state.dataRoomAir->DSXMATMX(ZoneNum)[0];
960 : }
961 :
962 0 : Real64 AirCap = state.dataRoomAir->AIRRATOC(ZoneNum);
963 0 : Real64 TempHistTerm = AirCap * (3.0 * state.dataRoomAir->ZTMOC(ZoneNum)[0] - (3.0 / 2.0) * state.dataRoomAir->ZTMOC(ZoneNum)[1] +
964 0 : (1.0 / 3.0) * state.dataRoomAir->ZTMOC(ZoneNum)[2]);
965 : // Formerly CoefSumha, coef in zone temp equation with dimensions of h*A
966 0 : Real64 TempDepCoef = GainsFrac * ufadCC.HA_OC + MCp_Total;
967 0 : Real64 TempIndCoef = GainsFrac * (ConvGains + ufadCC.HAT_OC + ufadCC.HAT_MX - ufadCC.HA_MX * state.dataRoomAir->ZTMX(ZoneNum)) +
968 0 : MCpT_Total + thisZoneHB.NonAirSystemResponse / ZoneMult;
969 0 : switch (state.dataHeatBal->ZoneAirSolutionAlgo) {
970 0 : case DataHeatBalance::SolutionAlgo::ThirdOrder: {
971 0 : state.dataRoomAir->ZTOC(ZoneNum) =
972 0 : (TempHistTerm + GainsFrac * (ConvGains + ufadCC.HAT_OC + ufadCC.HAT_MX - ufadCC.HA_MX * state.dataRoomAir->ZTMX(ZoneNum)) +
973 0 : MCpT_Total + thisZoneHB.NonAirSystemResponse / ZoneMult) /
974 0 : ((11.0 / 6.0) * AirCap + GainsFrac * ufadCC.HA_OC + MCp_Total);
975 0 : } break;
976 0 : case DataHeatBalance::SolutionAlgo::AnalyticalSolution: {
977 0 : if (TempDepCoef == 0.0) { // B=0
978 0 : state.dataRoomAir->ZTOC(ZoneNum) = state.dataRoomAir->Zone1OC(ZoneNum) + TempIndCoef / AirCap;
979 : } else {
980 0 : state.dataRoomAir->ZTOC(ZoneNum) =
981 0 : (state.dataRoomAir->Zone1OC(ZoneNum) - TempIndCoef / TempDepCoef) * std::exp(min(700.0, -TempDepCoef / AirCap)) +
982 0 : TempIndCoef / TempDepCoef;
983 : }
984 0 : } break;
985 0 : case DataHeatBalance::SolutionAlgo::EulerMethod: {
986 0 : state.dataRoomAir->ZTOC(ZoneNum) = (AirCap * state.dataRoomAir->Zone1OC(ZoneNum) + TempIndCoef) / (AirCap + TempDepCoef);
987 0 : } break;
988 0 : default:
989 0 : break;
990 : }
991 0 : AirCap = state.dataRoomAir->AIRRATMX(ZoneNum);
992 0 : TempHistTerm = AirCap * (3.0 * state.dataRoomAir->ZTMMX(ZoneNum)[0] - (3.0 / 2.0) * state.dataRoomAir->ZTMMX(ZoneNum)[1] +
993 0 : (1.0 / 3.0) * state.dataRoomAir->ZTMMX(ZoneNum)[2]);
994 0 : TempDepCoef = (1.0 - GainsFrac) * ufadCC.HA_MX + MCp_Total;
995 0 : TempIndCoef = (1.0 - GainsFrac) * (ConvGains + ufadCC.HAT_OC + ufadCC.HAT_MX - ufadCC.HA_OC * state.dataRoomAir->ZTOC(ZoneNum)) +
996 0 : state.dataRoomAir->ZTOC(ZoneNum) * MCp_Total;
997 0 : switch (state.dataHeatBal->ZoneAirSolutionAlgo) {
998 0 : case DataHeatBalance::SolutionAlgo::ThirdOrder: {
999 0 : state.dataRoomAir->ZTMX(ZoneNum) =
1000 0 : (TempHistTerm +
1001 0 : (1.0 - GainsFrac) * (ConvGains + ufadCC.HAT_OC + ufadCC.HAT_MX - ufadCC.HA_OC * state.dataRoomAir->ZTOC(ZoneNum)) +
1002 0 : state.dataRoomAir->ZTOC(ZoneNum) * MCp_Total) /
1003 0 : ((11.0 / 6.0) * AirCap + (1.0 - GainsFrac) * ufadCC.HA_MX + MCp_Total);
1004 0 : } break;
1005 0 : case DataHeatBalance::SolutionAlgo::AnalyticalSolution: {
1006 0 : if (TempDepCoef == 0.0) { // B=0
1007 0 : state.dataRoomAir->ZTMX(ZoneNum) = state.dataRoomAir->Zone1MX(ZoneNum) + TempIndCoef / AirCap;
1008 : } else {
1009 0 : state.dataRoomAir->ZTMX(ZoneNum) =
1010 0 : (state.dataRoomAir->Zone1MX(ZoneNum) - TempIndCoef / TempDepCoef) * std::exp(min(700.0, -TempDepCoef / AirCap)) +
1011 0 : TempIndCoef / TempDepCoef;
1012 : }
1013 0 : } break;
1014 0 : case DataHeatBalance::SolutionAlgo::EulerMethod: {
1015 0 : state.dataRoomAir->ZTMX(ZoneNum) = (AirCap * state.dataRoomAir->Zone1MX(ZoneNum) + TempIndCoef) / (AirCap + TempDepCoef);
1016 0 : } break;
1017 0 : default:
1018 0 : break;
1019 : }
1020 0 : state.dataRoomAir->ZTFloor(ZoneNum) = state.dataRoomAir->ZTOC(ZoneNum);
1021 : }
1022 0 : if (PowerInPlumes <= 0.0) {
1023 0 : HeightFrac = 0.0;
1024 0 : state.dataRoomAir->AirModel(ZoneNum).SimAirModel = false;
1025 0 : state.dataRoomAir->ZoneUFADGamma(ZoneNum) = 0.0;
1026 0 : state.dataRoomAir->ZoneUFADPowInPlumes(ZoneNum) = 0.0;
1027 : } else {
1028 0 : state.dataRoomAir->AirModel(ZoneNum).SimAirModel = true;
1029 0 : state.dataRoomAir->ZoneUFADGamma(ZoneNum) = Gamma;
1030 0 : state.dataRoomAir->ZoneUFADPowInPlumes(ZoneNum) = PowerInPlumes;
1031 : }
1032 : }
1033 :
1034 : //=============================== M I X E D Calculation ==============================================
1035 0 : if (state.dataRoomAir->ZTMX(ZoneNum) < state.dataRoomAir->ZTOC(ZoneNum) || MCp_Total <= 0.0 ||
1036 0 : HeightFrac * CeilingHeight < state.dataUFADManager->ThickOccupiedSubzoneMin) {
1037 0 : MIXFLAG = true;
1038 0 : HeightFrac = 0.0;
1039 0 : state.dataRoomAir->AvgTempGrad(ZoneNum) = 0.0;
1040 0 : state.dataRoomAir->MaxTempGrad(ZoneNum) = 0.0;
1041 0 : state.dataRoomAir->AirModel(ZoneNum).SimAirModel = false;
1042 0 : Real64 AirCap = thisZoneHB.AirPowerCap;
1043 0 : Real64 TempHistTerm = AirCap * (3.0 * thisZoneHB.ZTM[0] - (3.0 / 2.0) * thisZoneHB.ZTM[1] + (1.0 / 3.0) * thisZoneHB.ZTM[2]);
1044 :
1045 0 : for (int Ctd = 1; Ctd <= 3; ++Ctd) {
1046 0 : Real64 TempDepCoef = ufadCC.HA_MX + ufadCC.HA_OC + MCp_Total;
1047 0 : Real64 const thisZoneT1 = thisZoneHB.T1;
1048 : // Formerly CoefSumhat, coef in zone temp equation with dimensions of h*A(T1
1049 0 : Real64 TempIndCoef = ConvGains + ufadCC.HAT_MX + ufadCC.HAT_OC + MCpT_Total;
1050 0 : switch (state.dataHeatBal->ZoneAirSolutionAlgo) {
1051 0 : case DataHeatBalance::SolutionAlgo::ThirdOrder: {
1052 0 : ZTAveraged = (TempHistTerm + ConvGains + ufadCC.HAT_MX + ufadCC.HAT_OC + MCpT_Total) /
1053 0 : ((11.0 / 6.0) * AirCap + ufadCC.HA_MX + ufadCC.HA_OC + MCp_Total);
1054 0 : } break;
1055 0 : case DataHeatBalance::SolutionAlgo::AnalyticalSolution: {
1056 0 : if (TempDepCoef == 0.0) { // B=0
1057 0 : ZTAveraged = thisZoneT1 + TempIndCoef / AirCap;
1058 : } else {
1059 0 : ZTAveraged =
1060 0 : (thisZoneT1 - TempIndCoef / TempDepCoef) * std::exp(min(700.0, -TempDepCoef / AirCap)) + TempIndCoef / TempDepCoef;
1061 : }
1062 0 : } break;
1063 0 : case DataHeatBalance::SolutionAlgo::EulerMethod: {
1064 0 : ZTAveraged = (AirCap * thisZoneT1 + TempIndCoef) / (AirCap + TempDepCoef);
1065 0 : } break;
1066 0 : default:
1067 0 : break;
1068 : }
1069 0 : state.dataRoomAir->ZTOC(ZoneNum) = ZTAveraged;
1070 0 : state.dataRoomAir->ZTMX(ZoneNum) = ZTAveraged;
1071 0 : state.dataRoomAir->ZTFloor(ZoneNum) = ZTAveraged;
1072 0 : HcUFAD(state, ZoneNum, HeightFrac, ufadCC);
1073 0 : TempDepCoef = ufadCC.HA_MX + ufadCC.HA_OC + MCp_Total;
1074 0 : TempIndCoef = ConvGains + ufadCC.HAT_MX + ufadCC.HAT_OC + MCpT_Total;
1075 0 : switch (state.dataHeatBal->ZoneAirSolutionAlgo) {
1076 0 : case DataHeatBalance::SolutionAlgo::ThirdOrder: {
1077 0 : ZTAveraged = (TempHistTerm + ConvGains + ufadCC.HAT_MX + ufadCC.HAT_OC + MCpT_Total) /
1078 0 : ((11.0 / 6.0) * AirCap + ufadCC.HA_MX + ufadCC.HA_OC + MCp_Total);
1079 0 : } break;
1080 0 : case DataHeatBalance::SolutionAlgo::AnalyticalSolution: {
1081 0 : if (TempDepCoef == 0.0) { // B=0
1082 0 : ZTAveraged = thisZoneT1 + TempIndCoef / AirCap;
1083 : } else {
1084 0 : ZTAveraged =
1085 0 : (thisZoneT1 - TempIndCoef / TempDepCoef) * std::exp(min(700.0, -TempDepCoef / AirCap)) + TempIndCoef / TempDepCoef;
1086 : }
1087 0 : } break;
1088 0 : case DataHeatBalance::SolutionAlgo::EulerMethod: {
1089 0 : ZTAveraged = (AirCap * thisZoneT1 + TempIndCoef) / (AirCap + TempDepCoef);
1090 0 : } break;
1091 0 : default:
1092 0 : break;
1093 : }
1094 0 : state.dataRoomAir->ZTOC(ZoneNum) = ZTAveraged;
1095 0 : state.dataRoomAir->ZTMX(ZoneNum) = ZTAveraged;
1096 0 : state.dataRoomAir->ZTFloor(ZoneNum) = ZTAveraged;
1097 : }
1098 : }
1099 : //=========================================================================================
1100 :
1101 : // Comfort temperature and temperature at the thermostat/temperature control sensor
1102 :
1103 0 : state.dataRoomAir->HeightTransition(ZoneNum) = HeightFrac * CeilingHeight;
1104 0 : Real64 HeightUpSubzoneAve = (CeilingHeight + state.dataRoomAir->HeightTransition(ZoneNum)) / 2.0;
1105 0 : Real64 HeightOccupiedSubzoneAve = state.dataRoomAir->HeightTransition(ZoneNum) / 2.0;
1106 : // Comfort temperature
1107 :
1108 0 : if (MIXFLAG) {
1109 0 : state.dataRoomAir->TCMF(ZoneNum) = ZTAveraged;
1110 : } else {
1111 0 : if (HeightComfort < HeightOccupiedSubzoneAve) {
1112 0 : state.dataRoomAir->TCMF(ZoneNum) = state.dataRoomAir->ZTOC(ZoneNum);
1113 0 : } else if (HeightComfort >= HeightOccupiedSubzoneAve && HeightComfort < HeightUpSubzoneAve) {
1114 0 : state.dataRoomAir->TCMF(ZoneNum) = (state.dataRoomAir->ZTOC(ZoneNum) * (HeightUpSubzoneAve - HeightComfort) +
1115 0 : state.dataRoomAir->ZTMX(ZoneNum) * (HeightComfort - HeightOccupiedSubzoneAve)) /
1116 0 : (HeightUpSubzoneAve - HeightOccupiedSubzoneAve);
1117 0 : } else if (HeightComfort >= HeightUpSubzoneAve && HeightComfort <= CeilingHeight) {
1118 0 : state.dataRoomAir->TCMF(ZoneNum) = state.dataRoomAir->ZTMX(ZoneNum);
1119 : } else {
1120 0 : ShowFatalError(state,
1121 0 : format("UFAD comfort height is above ceiling or below floor in Zone: {}", state.dataHeatBal->Zone(ZoneNum).Name));
1122 : }
1123 : }
1124 :
1125 : // Temperature at the thermostat/temperature control sensor
1126 :
1127 0 : if (MIXFLAG) {
1128 0 : state.dataHeatBalFanSys->TempTstatAir(ZoneNum) = ZTAveraged;
1129 : } else {
1130 0 : if (HeightThermostat < HeightOccupiedSubzoneAve) {
1131 0 : state.dataHeatBalFanSys->TempTstatAir(ZoneNum) = state.dataRoomAir->ZTOC(ZoneNum);
1132 0 : } else if (HeightThermostat >= HeightOccupiedSubzoneAve && HeightThermostat < HeightUpSubzoneAve) {
1133 0 : state.dataHeatBalFanSys->TempTstatAir(ZoneNum) = (state.dataRoomAir->ZTOC(ZoneNum) * (HeightUpSubzoneAve - HeightThermostat) +
1134 0 : state.dataRoomAir->ZTMX(ZoneNum) * (HeightThermostat - HeightOccupiedSubzoneAve)) /
1135 0 : (HeightUpSubzoneAve - HeightOccupiedSubzoneAve);
1136 0 : } else if (HeightThermostat >= HeightUpSubzoneAve && HeightThermostat <= CeilingHeight) {
1137 0 : state.dataHeatBalFanSys->TempTstatAir(ZoneNum) = state.dataRoomAir->ZTMX(ZoneNum);
1138 : } else {
1139 0 : ShowFatalError(state,
1140 0 : format("Underfloor air distribution thermostat height is above ceiling or below floor in Zone: {}",
1141 0 : state.dataHeatBal->Zone(ZoneNum).Name));
1142 : }
1143 : }
1144 :
1145 : // Temperature gradients
1146 0 : if ((HeightUpSubzoneAve - HeightOccupiedSubzoneAve) > 0.1) {
1147 0 : state.dataRoomAir->AvgTempGrad(ZoneNum) =
1148 0 : (state.dataRoomAir->ZTMX(ZoneNum) - state.dataRoomAir->ZTOC(ZoneNum)) / (HeightUpSubzoneAve - HeightOccupiedSubzoneAve);
1149 : } else {
1150 0 : state.dataRoomAir->AvgTempGrad(ZoneNum) = 0.0;
1151 : }
1152 :
1153 0 : if (MIXFLAG) {
1154 0 : state.dataRoomAir->ZoneUFADMixedFlag(ZoneNum) = 1;
1155 0 : state.dataRoomAir->AirModel(ZoneNum).SimAirModel = false;
1156 : } else {
1157 0 : state.dataRoomAir->ZoneUFADMixedFlag(ZoneNum) = 0;
1158 0 : state.dataRoomAir->AirModel(ZoneNum).SimAirModel = true;
1159 : }
1160 :
1161 0 : if (ZoneEquipConfigNum > 0) {
1162 0 : int ZoneNodeNum = state.dataHeatBal->Zone(ZoneNum).SystemZoneNodeNumber;
1163 0 : state.dataLoopNodes->Node(ZoneNodeNum).Temp = state.dataRoomAir->ZTMX(ZoneNum);
1164 : }
1165 :
1166 0 : if (MIXFLAG) {
1167 0 : state.dataRoomAir->Phi(ZoneNum) = 1.0;
1168 : } else {
1169 0 : state.dataRoomAir->Phi(ZoneNum) =
1170 0 : (state.dataRoomAir->ZTOC(ZoneNum) - (TSupK - Constant::Kelvin)) / (state.dataRoomAir->ZTMX(ZoneNum) - (TSupK - Constant::Kelvin));
1171 : }
1172 :
1173 : // Mixed for reporting purposes
1174 0 : if ((MIXFLAG) || ((state.dataRoomAir->ZTMX(ZoneNum) - state.dataRoomAir->ZTOC(ZoneNum)) < TempDiffCritRep)) {
1175 0 : state.dataRoomAir->ZoneUFADMixedFlagRep(ZoneNum) = 1.0;
1176 0 : state.dataRoomAir->HeightTransition(ZoneNum) = 0.0;
1177 0 : state.dataRoomAir->AvgTempGrad(ZoneNum) = 0.0;
1178 : } else {
1179 0 : state.dataRoomAir->ZoneUFADMixedFlagRep(ZoneNum) = 0.0;
1180 : }
1181 0 : }
1182 :
1183 0 : void CalcUFADExt(EnergyPlusData &state, int const ZoneNum) // index number for the specified zone
1184 : {
1185 : // SUBROUTINE INFORMATION:
1186 : // AUTHOR Fred Buhl
1187 : // DATE WRITTEN January 2006
1188 : // MODIFIED Brent Griffith June 2008 for new interpolation and time history
1189 : // RE-ENGINEERED na
1190 :
1191 : // PURPOSE OF THIS SUBROUTINE:
1192 : // Using the UCSD UFAD exterior zone model, this subroutine calculates the occupied subzone height,
1193 : // surface heat transfer coefficients, the occupied subzone temperature, and the upper subzone temperature.
1194 :
1195 : // METHODOLOGY EMPLOYED:
1196 : // The zone is divided into 2 subzones with a variable transition height.
1197 :
1198 : // REFERENCES:
1199 : // The model is described in the EnergyPlus Engineering Reference in Anna Liu's UCSD PhD thesis.
1200 :
1201 : // Using/Aliasing
1202 : using Psychrometrics::PsyCpAirFnW;
1203 : using Psychrometrics::PsyRhoAirFnPbTdbW;
1204 0 : Real64 TimeStepSys = state.dataHVACGlobal->TimeStepSys;
1205 0 : Real64 TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
1206 : using InternalHeatGains::SumInternalConvectionGainsByTypes;
1207 : using InternalHeatGains::SumReturnAirConvectionGainsByTypes;
1208 :
1209 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1210 :
1211 : Real64 PowerInPlumesPerMeter; // Power in Plumes per meter of window length [W/m]
1212 : Real64 ZTAveraged;
1213 :
1214 : // Exact solution or Euler method
1215 0 : if (state.dataHeatBal->ZoneAirSolutionAlgo != DataHeatBalance::SolutionAlgo::ThirdOrder) {
1216 0 : if (state.dataHVACGlobal->ShortenTimeStepSysRoomAir && TimeStepSys < state.dataGlobal->TimeStepZone) {
1217 0 : if (state.dataHVACGlobal->PreviousTimeStep < state.dataGlobal->TimeStepZone) {
1218 0 : state.dataRoomAir->Zone1OC(ZoneNum) = state.dataRoomAir->ZoneM2OC(ZoneNum);
1219 0 : state.dataRoomAir->Zone1MX(ZoneNum) = state.dataRoomAir->ZoneM2MX(ZoneNum);
1220 : } else {
1221 0 : state.dataRoomAir->Zone1OC(ZoneNum) = state.dataRoomAir->ZoneMXOC(ZoneNum);
1222 0 : state.dataRoomAir->Zone1MX(ZoneNum) = state.dataRoomAir->ZoneMXMX(ZoneNum);
1223 : }
1224 : } else {
1225 0 : state.dataRoomAir->Zone1OC(ZoneNum) = state.dataRoomAir->ZTOC(ZoneNum);
1226 0 : state.dataRoomAir->Zone1MX(ZoneNum) = state.dataRoomAir->ZTMX(ZoneNum);
1227 : }
1228 : }
1229 :
1230 0 : auto &thisZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum);
1231 0 : Real64 HeightFrac = 0.0; // Fractional height of transition between occupied and upper subzones
1232 0 : bool MIXFLAG = false;
1233 0 : state.dataRoomAir->UFADHcIn = state.dataHeatBalSurf->SurfHConvInt;
1234 0 : Real64 SumSysMCp = 0.0; // Sum of system mass flow rate * specific heat for this zone [W/K]
1235 0 : Real64 SumSysMCpT = 0.0; // Sum of system mass flow rate * specific heat * temperature for this zone [W]
1236 0 : Real64 TotSysFlow = 0.0; // [m3/s]
1237 0 : Real64 TSupK = 0.0; // supply temperature [K]
1238 0 : Real64 SumSysM = 0.0; // Sum of systems mass flow rate [kg/s]
1239 0 : Real64 PowerInPlumes = 0.0; // [W]
1240 0 : Real64 Gamma = 0.0; // dimensionless height parameter; higher gamma means interface height will be
1241 : // higher, smaller gamma means interface height will be lower.
1242 0 : int ZoneMult = state.dataHeatBal->Zone(ZoneNum).Multiplier * state.dataHeatBal->Zone(ZoneNum).ListMultiplier;
1243 0 : Real64 CeilingHeight = state.dataRoomAir->ZoneCeilingHeight2(ZoneNum) - state.dataRoomAir->ZoneCeilingHeight1(ZoneNum);
1244 :
1245 0 : auto &zoneU = state.dataRoomAir->ZoneUFAD(state.dataRoomAir->ZoneUFADPtr(ZoneNum));
1246 0 : Real64 HeightThermostat = zoneU.ThermostatHeight; // height of the thermostat above the floor [m]
1247 0 : Real64 HeightComfort = zoneU.ComfortHeight; // height at which comfort temperature is calculated
1248 0 : Real64 TempDiffCritRep = zoneU.TempTrigger; // Minimum temperature difference between upper and occupied subzones for reporting
1249 0 : Real64 DiffArea = zoneU.DiffArea; // diffuser effective area [m2]
1250 0 : Real64 ThrowAngle = Constant::DegToRad * zoneU.DiffAngle; // diffuser slot angle relative to vertical [radians]
1251 0 : Real64 SourceHeight = zoneU.HeatSrcHeight; // height of plume sources above the floor [m]
1252 0 : Real64 NumDiffusers = zoneU.DiffusersPerZone;
1253 0 : Real64 PowerPerPlume = zoneU.PowerPerPlume;
1254 : // gains from occupants, task lighting, elec equip, gas equip, other equip, hot water equip, steam equip,
1255 : // baseboards (nonthermostatic), water heater skin loss
1256 0 : Real64 ConvGainsOccSubzone = SumInternalConvectionGainsByTypes(state, ZoneNum, IntGainTypesOccupied);
1257 :
1258 : // Add heat to return air if zonal system (no return air) or cycling system (return air frequently very
1259 : // low or zero)
1260 0 : if (state.dataHeatBal->Zone(ZoneNum).NoHeatToReturnAir) {
1261 0 : ConvGainsOccSubzone += SumReturnAirConvectionGainsByTypes(state, ZoneNum, IntGainTypesOccupied);
1262 : }
1263 :
1264 : // Add convection from pool cover to occupied region
1265 0 : ConvGainsOccSubzone += state.dataHeatBalFanSys->SumConvPool(ZoneNum);
1266 :
1267 : // gains from lights (ceiling), tubular daylighting devices, high temp radiant heaters
1268 : Real64 ConvGainsUpSubzone =
1269 0 : SumInternalConvectionGainsByTypes(state, ZoneNum, IntGainTypesUpSubzone); // convective heat gains into the upper subzone [W]
1270 0 : ConvGainsUpSubzone += state.dataHeatBalFanSys->SumConvHTRadSys(ZoneNum);
1271 0 : if (state.dataHeatBal->Zone(ZoneNum).NoHeatToReturnAir) {
1272 0 : ConvGainsUpSubzone += SumReturnAirConvectionGainsByTypes(state, ZoneNum, IntGainTypesUpSubzone);
1273 : }
1274 0 : Real64 ConvGains =
1275 0 : ConvGainsOccSubzone + ConvGainsUpSubzone + thisZoneHB.SysDepZoneLoadsLagged; // total zone convective gains (excluding surfaces) [W]
1276 0 : int ZoneEquipConfigNum = zoneU.ZoneEquipPtr;
1277 0 : if (ZoneEquipConfigNum > 0) {
1278 0 : auto const &zoneEquipConfig = state.dataZoneEquip->ZoneEquipConfig(ZoneEquipConfigNum);
1279 0 : for (int InNodeIndex = 1; InNodeIndex <= zoneEquipConfig.NumInletNodes; ++InNodeIndex) {
1280 0 : Real64 NodeTemp = state.dataLoopNodes->Node(zoneEquipConfig.InletNode(InNodeIndex)).Temp;
1281 0 : Real64 MassFlowRate = state.dataLoopNodes->Node(zoneEquipConfig.InletNode(InNodeIndex)).MassFlowRate;
1282 0 : Real64 CpAir = PsyCpAirFnW(thisZoneHB.airHumRat);
1283 0 : SumSysMCp += MassFlowRate * CpAir;
1284 0 : SumSysMCpT += MassFlowRate * CpAir * NodeTemp;
1285 0 : TotSysFlow += MassFlowRate / PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, NodeTemp, thisZoneHB.airHumRat);
1286 0 : TSupK += MassFlowRate * NodeTemp;
1287 0 : SumSysM += MassFlowRate;
1288 : }
1289 0 : if (TotSysFlow > 0.0) {
1290 0 : TSupK = TSupK / SumSysM + Constant::Kelvin;
1291 : } else {
1292 0 : TSupK = 0.0;
1293 : }
1294 : }
1295 :
1296 : // mass flow rate * specific heat for this zone for infiltration, ventilation, mixing [W/K]
1297 0 : Real64 SumMCp = thisZoneHB.MCPI + thisZoneHB.MCPV + thisZoneHB.MCPM + thisZoneHB.MDotCPOA;
1298 : // mass flow rate * specific heat* temp for this zone for infiltration, ventilation, mixing [W]
1299 : Real64 SumMCpT =
1300 0 : thisZoneHB.MCPTI + thisZoneHB.MCPTV + thisZoneHB.MCPTM + thisZoneHB.MDotCPOA * state.dataHeatBal->Zone(ZoneNum).OutDryBulbTemp;
1301 :
1302 0 : Real64 MCp_Total = SumMCp + SumSysMCp; // total mass flow rate * specific heat for this zone [W/K]
1303 0 : Real64 MCpT_Total = SumMCpT + SumSysMCpT; // total mass flow rate * specific heat* temp for this zone [W]
1304 :
1305 : // For the York MIT diffusers (variable area) the area varies with the flow rate. Assume 400 ft/min velocity
1306 : // at the diffuser, and a design flow rate of 150 cfm (.0708 m3/s). Then the design area for each diffuser is
1307 : // 150 ft3/min / 400 ft/min = .375 ft2 = .035 m2. This is adjusted each time step by
1308 : // (TotSysFlow/(NumDiffusers*.0708))*.035
1309 0 : if (zoneU.DiffuserType == Diffuser::VarArea) {
1310 0 : DiffArea = 0.035 * TotSysFlow / (0.0708 * NumDiffusers);
1311 : }
1312 : // initial estimate of convective transfer from surfaces; assume HeightFrac is 0.5.
1313 0 : UFADConvCoef ufadCC;
1314 0 : HcUFAD(state, ZoneNum, 0.5, ufadCC);
1315 0 : Real64 ConvGainsWindows = ufadCC.HAT_MXWin + ufadCC.HAT_OCWin - // ZoneEquipConfig index for this UFAD zone
1316 0 : ufadCC.HA_MXWin * state.dataRoomAir->ZTMX(ZoneNum) - ufadCC.HA_OCWin * state.dataRoomAir->ZTOC(ZoneNum);
1317 0 : PowerInPlumes = ConvGains + ufadCC.HAT_OC - ufadCC.HA_OC * state.dataRoomAir->ZTOC(ZoneNum) + ufadCC.HAT_MX -
1318 0 : ufadCC.HA_MX * state.dataRoomAir->ZTMX(ZoneNum);
1319 : // NumberOfPlumes = PowerInPlumes / PowerPerPlume
1320 0 : Real64 NumberOfPlumes = (PowerPerPlume > 0.0 && PowerInPlumes > 0.0) ? (PowerInPlumes / PowerPerPlume) : 1.0;
1321 0 : Real64 NumDiffusersPerPlume = (PowerPerPlume > 0.0 && PowerInPlumes > 0.0) ? (NumDiffusers / NumberOfPlumes) : 1.0;
1322 :
1323 0 : if ((PowerInPlumes <= 0.0) || (TotSysFlow == 0.0) || (TSupK - Constant::Kelvin) > thisZoneHB.MAT) {
1324 : // The system will mix
1325 0 : HeightFrac = 0.0;
1326 : } else {
1327 0 : if (PowerInPlumes > 0.0) {
1328 0 : if (zoneU.WinWidth > 0.0) { // exterior zone formula
1329 0 : PowerInPlumesPerMeter = PowerInPlumes / zoneU.WinWidth;
1330 0 : Gamma =
1331 0 : (TotSysFlow * std::cos(ThrowAngle)) / (NumDiffusers * DiffArea * std::pow(0.0281 * 0.001 * PowerInPlumesPerMeter, 0.333333));
1332 : } else { // interior zone formula
1333 0 : Gamma = std::pow(TotSysFlow * std::cos(ThrowAngle), 1.5) /
1334 0 : (NumberOfPlumes * std::pow(NumDiffusersPerPlume * DiffArea, 1.25) * std::sqrt(0.0281 * 0.001 * PowerInPlumes));
1335 : }
1336 : } else {
1337 0 : Gamma = 1000.0;
1338 : }
1339 0 : if (zoneU.CalcTransHeight) {
1340 0 : if (zoneU.WinWidth > 0.0) { // use exterior zone formula
1341 0 : HeightFrac = (std::sqrt(DiffArea) * (11.03 * std::log(Gamma) - 10.73) + 0.5 * SourceHeight) / CeilingHeight;
1342 : } else { // use interior zone formula
1343 0 : HeightFrac = (std::sqrt(NumDiffusersPerPlume * DiffArea) * (7.43 * std::log(Gamma) - 1.35) + 0.5 * SourceHeight) / CeilingHeight;
1344 : }
1345 : } else {
1346 0 : HeightFrac = zoneU.TransHeight / CeilingHeight;
1347 : }
1348 0 : HeightFrac = max(0.0, min(1.0, HeightFrac));
1349 0 : Real64 GainsFrac = zoneU.A_Kc * std::pow(Gamma, zoneU.B_Kc) + zoneU.C_Kc + zoneU.D_Kc * Gamma + zoneU.E_Kc * pow_2(Gamma);
1350 0 : GainsFrac = max(0.7, min(GainsFrac, 1.0));
1351 0 : if (zoneU.ShadeDown) {
1352 0 : GainsFrac -= 0.2;
1353 : }
1354 0 : state.dataRoomAir->ZoneUFADPowInPlumes(ZoneNum) = PowerInPlumes;
1355 0 : for (int Ctd = 1; Ctd <= 4; ++Ctd) {
1356 0 : HcUFAD(state, ZoneNum, HeightFrac, ufadCC);
1357 0 : ConvGainsWindows = ufadCC.HAT_MXWin + ufadCC.HAT_OCWin - ufadCC.HA_MXWin * state.dataRoomAir->ZTMX(ZoneNum) -
1358 0 : ufadCC.HA_OCWin * state.dataRoomAir->ZTOC(ZoneNum);
1359 0 : ConvGainsWindows = max(ConvGainsWindows, 0.0);
1360 0 : PowerInPlumes = ConvGains + ufadCC.HAT_OC - ufadCC.HA_OC * state.dataRoomAir->ZTOC(ZoneNum) + ufadCC.HAT_MX -
1361 0 : ufadCC.HA_MX * state.dataRoomAir->ZTMX(ZoneNum);
1362 : // NumberOfPlumes = PowerInPlumes / PowerPerPlume
1363 0 : NumberOfPlumes = 1.0;
1364 0 : if (PowerInPlumes <= 0.0) {
1365 0 : break;
1366 : }
1367 0 : if (zoneU.WinWidth > 0.0) { // use exterior zone formula
1368 0 : PowerInPlumesPerMeter = PowerInPlumes / zoneU.WinWidth;
1369 0 : Gamma =
1370 0 : (TotSysFlow * std::cos(ThrowAngle)) / (NumDiffusers * DiffArea * std::pow(0.0281 * 0.001 * PowerInPlumesPerMeter, 0.333333));
1371 : } else { // use interior zone formula
1372 0 : Gamma = std::pow(TotSysFlow * std::cos(ThrowAngle), 1.5) /
1373 0 : (NumberOfPlumes * std::pow(NumDiffusersPerPlume * DiffArea, 1.25) * std::sqrt(0.0281 * 0.001 * PowerInPlumes));
1374 : }
1375 0 : if (zoneU.CalcTransHeight) {
1376 0 : if (zoneU.WinWidth > 0.0) { // exterior zone formula
1377 0 : HeightFrac = (std::sqrt(DiffArea) * (11.03 * std::log(Gamma) - 10.73) + 0.5 * SourceHeight) / CeilingHeight;
1378 : } else { // interior zone formula
1379 0 : HeightFrac =
1380 0 : (std::sqrt(NumDiffusersPerPlume * DiffArea) * (7.43 * std::log(Gamma) - 1.35) + 0.5 * SourceHeight) / CeilingHeight;
1381 : }
1382 : } else {
1383 0 : HeightFrac = zoneU.TransHeight / CeilingHeight;
1384 : }
1385 0 : HeightFrac = min(1.0, HeightFrac);
1386 0 : state.dataRoomAir->HeightTransition(ZoneNum) = HeightFrac * CeilingHeight;
1387 0 : Real64 GainsFrac = zoneU.A_Kc * std::pow(Gamma, zoneU.B_Kc) + zoneU.C_Kc + zoneU.D_Kc * Gamma + zoneU.E_Kc * pow_2(Gamma);
1388 0 : GainsFrac = max(0.7, min(GainsFrac, 1.0));
1389 0 : if (zoneU.ShadeDown) {
1390 0 : GainsFrac -= 0.2;
1391 : }
1392 0 : state.dataRoomAir->AIRRATOC(ZoneNum) =
1393 0 : state.dataHeatBal->Zone(ZoneNum).Volume *
1394 0 : (state.dataRoomAir->HeightTransition(ZoneNum) - min(state.dataRoomAir->HeightTransition(ZoneNum), 0.2)) / CeilingHeight *
1395 0 : state.dataHeatBal->Zone(ZoneNum).ZoneVolCapMultpSens *
1396 0 : PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, state.dataRoomAir->MATOC(ZoneNum), thisZoneHB.airHumRat) *
1397 0 : PsyCpAirFnW(thisZoneHB.airHumRat) / TimeStepSysSec;
1398 0 : state.dataRoomAir->AIRRATMX(ZoneNum) =
1399 0 : state.dataHeatBal->Zone(ZoneNum).Volume * (CeilingHeight - state.dataRoomAir->HeightTransition(ZoneNum)) / CeilingHeight *
1400 0 : state.dataHeatBal->Zone(ZoneNum).ZoneVolCapMultpSens *
1401 0 : PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, state.dataRoomAir->MATMX(ZoneNum), thisZoneHB.airHumRat) *
1402 0 : PsyCpAirFnW(thisZoneHB.airHumRat) / TimeStepSysSec;
1403 :
1404 0 : if (state.dataHVACGlobal->UseZoneTimeStepHistory) {
1405 0 : state.dataRoomAir->ZTMOC(ZoneNum)[2] = state.dataRoomAir->XMATOC(ZoneNum)[2];
1406 0 : state.dataRoomAir->ZTMOC(ZoneNum)[1] = state.dataRoomAir->XMATOC(ZoneNum)[1];
1407 0 : state.dataRoomAir->ZTMOC(ZoneNum)[0] = state.dataRoomAir->XMATOC(ZoneNum)[0];
1408 :
1409 0 : state.dataRoomAir->ZTMMX(ZoneNum)[2] = state.dataRoomAir->XMATMX(ZoneNum)[2];
1410 0 : state.dataRoomAir->ZTMMX(ZoneNum)[1] = state.dataRoomAir->XMATMX(ZoneNum)[1];
1411 0 : state.dataRoomAir->ZTMMX(ZoneNum)[0] = state.dataRoomAir->XMATMX(ZoneNum)[0];
1412 :
1413 : } else {
1414 0 : state.dataRoomAir->ZTMOC(ZoneNum)[2] = state.dataRoomAir->DSXMATOC(ZoneNum)[2];
1415 0 : state.dataRoomAir->ZTMOC(ZoneNum)[1] = state.dataRoomAir->DSXMATOC(ZoneNum)[1];
1416 0 : state.dataRoomAir->ZTMOC(ZoneNum)[0] = state.dataRoomAir->DSXMATOC(ZoneNum)[0];
1417 :
1418 0 : state.dataRoomAir->ZTMMX(ZoneNum)[2] = state.dataRoomAir->DSXMATMX(ZoneNum)[2];
1419 0 : state.dataRoomAir->ZTMMX(ZoneNum)[1] = state.dataRoomAir->DSXMATMX(ZoneNum)[1];
1420 0 : state.dataRoomAir->ZTMMX(ZoneNum)[0] = state.dataRoomAir->DSXMATMX(ZoneNum)[0];
1421 : }
1422 :
1423 0 : Real64 AirCap = state.dataRoomAir->AIRRATOC(ZoneNum);
1424 0 : Real64 TempHistTerm = AirCap * (3.0 * state.dataRoomAir->ZTMOC(ZoneNum)[0] - (3.0 / 2.0) * state.dataRoomAir->ZTMOC(ZoneNum)[1] +
1425 0 : (1.0 / 3.0) * state.dataRoomAir->ZTMOC(ZoneNum)[2]);
1426 0 : Real64 TempDepCoef = GainsFrac * ufadCC.HA_OC + MCp_Total;
1427 0 : Real64 TempIndCoef = GainsFrac * (ConvGains + ufadCC.HAT_OC + ufadCC.HAT_MX - ufadCC.HA_MX * state.dataRoomAir->ZTMX(ZoneNum)) +
1428 0 : MCpT_Total + thisZoneHB.NonAirSystemResponse / ZoneMult;
1429 0 : switch (state.dataHeatBal->ZoneAirSolutionAlgo) {
1430 0 : case DataHeatBalance::SolutionAlgo::ThirdOrder: {
1431 0 : state.dataRoomAir->ZTOC(ZoneNum) =
1432 0 : (TempHistTerm + GainsFrac * (ConvGains + ufadCC.HAT_OC + ufadCC.HAT_MX - ufadCC.HA_MX * state.dataRoomAir->ZTMX(ZoneNum)) +
1433 0 : MCpT_Total + thisZoneHB.NonAirSystemResponse / ZoneMult) /
1434 0 : ((11.0 / 6.0) * AirCap + GainsFrac * ufadCC.HA_OC + MCp_Total);
1435 0 : } break;
1436 0 : case DataHeatBalance::SolutionAlgo::AnalyticalSolution: {
1437 0 : if (TempDepCoef == 0.0) { // B=0
1438 0 : state.dataRoomAir->ZTOC(ZoneNum) = state.dataRoomAir->Zone1OC(ZoneNum) + TempIndCoef / AirCap;
1439 : } else {
1440 0 : state.dataRoomAir->ZTOC(ZoneNum) =
1441 0 : (state.dataRoomAir->Zone1OC(ZoneNum) - TempIndCoef / TempDepCoef) * std::exp(min(700.0, -TempDepCoef / AirCap)) +
1442 0 : TempIndCoef / TempDepCoef;
1443 : }
1444 0 : } break;
1445 0 : case DataHeatBalance::SolutionAlgo::EulerMethod: {
1446 0 : state.dataRoomAir->ZTOC(ZoneNum) = (AirCap * state.dataRoomAir->Zone1OC(ZoneNum) + TempIndCoef) / (AirCap + TempDepCoef);
1447 0 : } break;
1448 0 : default:
1449 0 : break;
1450 : }
1451 0 : AirCap = state.dataRoomAir->AIRRATMX(ZoneNum);
1452 0 : TempHistTerm = AirCap * (3.0 * state.dataRoomAir->ZTMMX(ZoneNum)[0] - (3.0 / 2.0) * state.dataRoomAir->ZTMMX(ZoneNum)[1] +
1453 0 : (1.0 / 3.0) * state.dataRoomAir->ZTMMX(ZoneNum)[2]);
1454 0 : TempDepCoef = (1.0 - GainsFrac) * ufadCC.HA_MX + MCp_Total;
1455 0 : TempIndCoef = (1.0 - GainsFrac) * (ConvGains + ufadCC.HAT_OC + ufadCC.HAT_MX - ufadCC.HA_OC * state.dataRoomAir->ZTOC(ZoneNum)) +
1456 0 : state.dataRoomAir->ZTOC(ZoneNum) * MCp_Total;
1457 0 : switch (state.dataHeatBal->ZoneAirSolutionAlgo) {
1458 0 : case DataHeatBalance::SolutionAlgo::ThirdOrder: {
1459 0 : state.dataRoomAir->ZTMX(ZoneNum) =
1460 0 : (TempHistTerm +
1461 0 : (1.0 - GainsFrac) * (ConvGains + ufadCC.HAT_OC + ufadCC.HAT_MX - ufadCC.HA_OC * state.dataRoomAir->ZTOC(ZoneNum)) +
1462 0 : state.dataRoomAir->ZTOC(ZoneNum) * MCp_Total) /
1463 0 : ((11.0 / 6.0) * AirCap + (1.0 - GainsFrac) * ufadCC.HA_MX + MCp_Total);
1464 0 : } break;
1465 0 : case DataHeatBalance::SolutionAlgo::AnalyticalSolution: {
1466 0 : if (TempDepCoef == 0.0) { // B=0
1467 0 : state.dataRoomAir->ZTMX(ZoneNum) = state.dataRoomAir->Zone1MX(ZoneNum) + TempIndCoef / AirCap;
1468 : } else {
1469 0 : state.dataRoomAir->ZTMX(ZoneNum) =
1470 0 : (state.dataRoomAir->Zone1MX(ZoneNum) - TempIndCoef / TempDepCoef) * std::exp(min(700.0, -TempDepCoef / AirCap)) +
1471 0 : TempIndCoef / TempDepCoef;
1472 : }
1473 0 : } break;
1474 0 : case DataHeatBalance::SolutionAlgo::EulerMethod: {
1475 0 : state.dataRoomAir->ZTMX(ZoneNum) = (AirCap * state.dataRoomAir->Zone1MX(ZoneNum) + TempIndCoef) / (AirCap + TempDepCoef);
1476 0 : } break;
1477 0 : default:
1478 0 : break;
1479 : }
1480 0 : state.dataRoomAir->ZTFloor(ZoneNum) = state.dataRoomAir->ZTOC(ZoneNum);
1481 : }
1482 0 : if (PowerInPlumes <= 0.0) {
1483 0 : HeightFrac = 0.0;
1484 0 : state.dataRoomAir->AirModel(ZoneNum).SimAirModel = false;
1485 0 : state.dataRoomAir->ZoneUFADGamma(ZoneNum) = 0.0;
1486 0 : state.dataRoomAir->ZoneUFADPowInPlumes(ZoneNum) = 0.0;
1487 0 : state.dataRoomAir->ZoneUFADPowInPlumesfromWindows(ZoneNum) = 0.0;
1488 : } else {
1489 0 : state.dataRoomAir->AirModel(ZoneNum).SimAirModel = true;
1490 0 : state.dataRoomAir->ZoneUFADGamma(ZoneNum) = Gamma;
1491 0 : state.dataRoomAir->ZoneUFADPowInPlumes(ZoneNum) = PowerInPlumes;
1492 0 : state.dataRoomAir->ZoneUFADPowInPlumesfromWindows(ZoneNum) = ConvGainsWindows;
1493 : }
1494 : }
1495 :
1496 : //=============================== M I X E D Calculation ==============================================
1497 0 : if (state.dataRoomAir->ZTMX(ZoneNum) < state.dataRoomAir->ZTOC(ZoneNum) || MCp_Total <= 0.0 ||
1498 0 : HeightFrac * CeilingHeight < state.dataUFADManager->ThickOccupiedSubzoneMin) {
1499 0 : MIXFLAG = true;
1500 0 : HeightFrac = 0.0;
1501 0 : Real64 const thisZoneT1 = thisZoneHB.T1;
1502 :
1503 0 : state.dataRoomAir->AvgTempGrad(ZoneNum) = 0.0;
1504 0 : state.dataRoomAir->MaxTempGrad(ZoneNum) = 0.0;
1505 0 : state.dataRoomAir->AirModel(ZoneNum).SimAirModel = false;
1506 0 : Real64 AirCap = thisZoneHB.AirPowerCap;
1507 0 : Real64 TempHistTerm = AirCap * (3.0 * thisZoneHB.ZTM[0] - (3.0 / 2.0) * thisZoneHB.ZTM[1] + (1.0 / 3.0) * thisZoneHB.ZTM[2]);
1508 :
1509 0 : for (int Ctd = 1; Ctd <= 3; ++Ctd) {
1510 0 : Real64 TempDepCoef = ufadCC.HA_MX + ufadCC.HA_OC + MCp_Total;
1511 0 : Real64 TempIndCoef = ConvGains + ufadCC.HAT_MX + ufadCC.HAT_OC + MCpT_Total;
1512 0 : switch (state.dataHeatBal->ZoneAirSolutionAlgo) {
1513 0 : case DataHeatBalance::SolutionAlgo::ThirdOrder: {
1514 0 : ZTAveraged = (TempHistTerm + ConvGains + ufadCC.HAT_MX + ufadCC.HAT_OC + MCpT_Total) /
1515 0 : ((11.0 / 6.0) * AirCap + ufadCC.HA_MX + ufadCC.HA_OC + MCp_Total);
1516 0 : } break;
1517 0 : case DataHeatBalance::SolutionAlgo::AnalyticalSolution: {
1518 0 : if (TempDepCoef == 0.0) { // B=0
1519 0 : ZTAveraged = thisZoneT1 + TempIndCoef / AirCap;
1520 : } else {
1521 0 : ZTAveraged =
1522 0 : (thisZoneT1 - TempIndCoef / TempDepCoef) * std::exp(min(700.0, -TempDepCoef / AirCap)) + TempIndCoef / TempDepCoef;
1523 : }
1524 0 : } break;
1525 0 : case DataHeatBalance::SolutionAlgo::EulerMethod: {
1526 0 : ZTAveraged = (AirCap * thisZoneT1 + TempIndCoef) / (AirCap + TempDepCoef);
1527 0 : } break;
1528 0 : default:
1529 0 : break;
1530 : }
1531 0 : state.dataRoomAir->ZTOC(ZoneNum) = ZTAveraged;
1532 0 : state.dataRoomAir->ZTMX(ZoneNum) = ZTAveraged;
1533 0 : state.dataRoomAir->ZTFloor(ZoneNum) = ZTAveraged;
1534 0 : HcUFAD(state, ZoneNum, HeightFrac, ufadCC);
1535 0 : TempDepCoef = ufadCC.HA_MX + ufadCC.HA_OC + MCp_Total;
1536 0 : TempIndCoef = ConvGains + ufadCC.HAT_MX + ufadCC.HAT_OC + MCpT_Total;
1537 0 : switch (state.dataHeatBal->ZoneAirSolutionAlgo) {
1538 0 : case DataHeatBalance::SolutionAlgo::ThirdOrder: {
1539 0 : ZTAveraged = (TempHistTerm + ConvGains + ufadCC.HAT_MX + ufadCC.HAT_OC + MCpT_Total) /
1540 0 : ((11.0 / 6.0) * AirCap + ufadCC.HA_MX + ufadCC.HA_OC + MCp_Total);
1541 0 : } break;
1542 0 : case DataHeatBalance::SolutionAlgo::AnalyticalSolution: {
1543 0 : if (TempDepCoef == 0.0) { // B=0
1544 0 : ZTAveraged = thisZoneT1 + TempIndCoef / AirCap;
1545 : } else {
1546 0 : ZTAveraged =
1547 0 : (thisZoneT1 - TempIndCoef / TempDepCoef) * std::exp(min(700.0, -TempDepCoef / AirCap)) + TempIndCoef / TempDepCoef;
1548 : }
1549 0 : } break;
1550 0 : case DataHeatBalance::SolutionAlgo::EulerMethod: {
1551 0 : ZTAveraged = (AirCap * thisZoneT1 + TempIndCoef) / (AirCap + TempDepCoef);
1552 0 : } break;
1553 0 : default:
1554 0 : break;
1555 : }
1556 0 : state.dataRoomAir->ZTOC(ZoneNum) = ZTAveraged;
1557 0 : state.dataRoomAir->ZTMX(ZoneNum) = ZTAveraged;
1558 0 : state.dataRoomAir->ZTFloor(ZoneNum) = ZTAveraged;
1559 : }
1560 : }
1561 : //=========================================================================================
1562 :
1563 : // Comfort temperature and temperature at the thermostat/temperature control sensor
1564 :
1565 0 : Real64 HeightUpSubzoneAve = (CeilingHeight + state.dataRoomAir->HeightTransition(ZoneNum)) / 2.0;
1566 0 : Real64 HeightOccupiedSubzoneAve = state.dataRoomAir->HeightTransition(ZoneNum) / 2.0;
1567 : // Comfort temperature
1568 :
1569 0 : if (MIXFLAG) {
1570 0 : state.dataRoomAir->TCMF(ZoneNum) = ZTAveraged;
1571 : } else {
1572 0 : if (HeightComfort < HeightOccupiedSubzoneAve) {
1573 0 : state.dataRoomAir->TCMF(ZoneNum) = state.dataRoomAir->ZTOC(ZoneNum);
1574 0 : } else if (HeightComfort >= HeightOccupiedSubzoneAve && HeightComfort < HeightUpSubzoneAve) {
1575 0 : state.dataRoomAir->TCMF(ZoneNum) = (state.dataRoomAir->ZTOC(ZoneNum) * (HeightUpSubzoneAve - HeightComfort) +
1576 0 : state.dataRoomAir->ZTMX(ZoneNum) * (HeightComfort - HeightOccupiedSubzoneAve)) /
1577 0 : (HeightUpSubzoneAve - HeightOccupiedSubzoneAve);
1578 0 : } else if (HeightComfort >= HeightUpSubzoneAve && HeightComfort <= CeilingHeight) {
1579 0 : state.dataRoomAir->TCMF(ZoneNum) = state.dataRoomAir->ZTMX(ZoneNum);
1580 : } else {
1581 0 : ShowFatalError(state,
1582 0 : format("UFAD comfort height is above ceiling or below floor in Zone: {}", state.dataHeatBal->Zone(ZoneNum).Name));
1583 : }
1584 : }
1585 :
1586 : // Temperature at the thermostat/temperature control sensor
1587 :
1588 0 : if (MIXFLAG) {
1589 0 : state.dataHeatBalFanSys->TempTstatAir(ZoneNum) = ZTAveraged;
1590 : } else {
1591 0 : if (HeightThermostat < HeightOccupiedSubzoneAve) {
1592 0 : state.dataHeatBalFanSys->TempTstatAir(ZoneNum) = state.dataRoomAir->ZTOC(ZoneNum);
1593 0 : } else if (HeightThermostat >= HeightOccupiedSubzoneAve && HeightThermostat < HeightUpSubzoneAve) {
1594 0 : state.dataHeatBalFanSys->TempTstatAir(ZoneNum) = (state.dataRoomAir->ZTOC(ZoneNum) * (HeightUpSubzoneAve - HeightThermostat) +
1595 0 : state.dataRoomAir->ZTMX(ZoneNum) * (HeightThermostat - HeightOccupiedSubzoneAve)) /
1596 0 : (HeightUpSubzoneAve - HeightOccupiedSubzoneAve);
1597 0 : } else if (HeightThermostat >= HeightUpSubzoneAve && HeightThermostat <= CeilingHeight) {
1598 0 : state.dataHeatBalFanSys->TempTstatAir(ZoneNum) = state.dataRoomAir->ZTMX(ZoneNum);
1599 : } else {
1600 0 : ShowFatalError(state,
1601 0 : format("Underfloor air distribution thermostat height is above ceiling or below floor in Zone: {}",
1602 0 : state.dataHeatBal->Zone(ZoneNum).Name));
1603 : }
1604 : }
1605 :
1606 : // Temperature gradients
1607 0 : if ((HeightUpSubzoneAve - HeightOccupiedSubzoneAve) > 0.1) {
1608 0 : state.dataRoomAir->AvgTempGrad(ZoneNum) =
1609 0 : (state.dataRoomAir->ZTMX(ZoneNum) - state.dataRoomAir->ZTOC(ZoneNum)) / (HeightUpSubzoneAve - HeightOccupiedSubzoneAve);
1610 : } else {
1611 0 : state.dataRoomAir->AvgTempGrad(ZoneNum) = 0.0;
1612 : }
1613 :
1614 0 : if (MIXFLAG) {
1615 0 : state.dataRoomAir->ZoneUFADMixedFlag(ZoneNum) = 1;
1616 0 : state.dataRoomAir->AirModel(ZoneNum).SimAirModel = false;
1617 : } else {
1618 0 : state.dataRoomAir->ZoneUFADMixedFlag(ZoneNum) = 0;
1619 0 : state.dataRoomAir->AirModel(ZoneNum).SimAirModel = true;
1620 : }
1621 :
1622 0 : if (ZoneEquipConfigNum > 0) {
1623 0 : int ZoneNodeNum = state.dataHeatBal->Zone(ZoneNum).SystemZoneNodeNumber;
1624 0 : state.dataLoopNodes->Node(ZoneNodeNum).Temp = state.dataRoomAir->ZTMX(ZoneNum);
1625 : }
1626 :
1627 0 : if (MIXFLAG) {
1628 0 : state.dataRoomAir->Phi(ZoneNum) = 1.0;
1629 : } else {
1630 0 : state.dataRoomAir->Phi(ZoneNum) =
1631 0 : (state.dataRoomAir->ZTOC(ZoneNum) - (TSupK - Constant::Kelvin)) / (state.dataRoomAir->ZTMX(ZoneNum) - (TSupK - Constant::Kelvin));
1632 : }
1633 :
1634 : // Mixed for reporting purposes
1635 0 : if ((MIXFLAG) || ((state.dataRoomAir->ZTMX(ZoneNum) - state.dataRoomAir->ZTOC(ZoneNum)) < TempDiffCritRep)) {
1636 0 : state.dataRoomAir->ZoneUFADMixedFlagRep(ZoneNum) = 1.0;
1637 0 : state.dataRoomAir->HeightTransition(ZoneNum) = 0.0;
1638 0 : state.dataRoomAir->AvgTempGrad(ZoneNum) = 0.0;
1639 : } else {
1640 0 : state.dataRoomAir->ZoneUFADMixedFlagRep(ZoneNum) = 0.0;
1641 : }
1642 0 : }
1643 :
1644 : } // namespace RoomAir
1645 : } // namespace EnergyPlus
|