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