Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2025, The Board of Trustees of the University of Illinois,
2 : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
3 : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
4 : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
5 : // contributors. All rights reserved.
6 : //
7 : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
8 : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
9 : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
10 : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
11 : // derivative works, and perform publicly and display publicly, and to permit others to do so.
12 : //
13 : // Redistribution and use in source and binary forms, with or without modification, are permitted
14 : // provided that the following conditions are met:
15 : //
16 : // (1) Redistributions of source code must retain the above copyright notice, this list of
17 : // conditions and the following disclaimer.
18 : //
19 : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
20 : // conditions and the following disclaimer in the documentation and/or other materials
21 : // provided with the distribution.
22 : //
23 : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
24 : // the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
25 : // used to endorse or promote products derived from this software without specific prior
26 : // written permission.
27 : //
28 : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
29 : // without changes from the version obtained under this License, or (ii) Licensee makes a
30 : // reference solely to the software portion of its product, Licensee must refer to the
31 : // software as "EnergyPlus version X" software, where "X" is the version number Licensee
32 : // obtained under this License and may not use a different name for the software. Except as
33 : // specifically required in this Section (4), Licensee shall not use in a company name, a
34 : // product name, in advertising, publicity, or other promotional activities any name, trade
35 : // name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
36 : // similar designation, without the U.S. Department of Energy's prior written consent.
37 : //
38 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
39 : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
40 : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
41 : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43 : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
45 : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46 : // POSSIBILITY OF SUCH DAMAGE.
47 :
48 : // ObjexxFCL Headers
49 : #include <ObjexxFCL/Array.functions.hh>
50 : #include <ObjexxFCL/Fmath.hh>
51 :
52 : // EnergyPlus Headers
53 : #include <EnergyPlus/Data/EnergyPlusData.hh>
54 : #include <EnergyPlus/DataEnvironment.hh>
55 : #include <EnergyPlus/DataHeatBalFanSys.hh>
56 : #include <EnergyPlus/DataHeatBalSurface.hh>
57 : #include <EnergyPlus/DataHeatBalance.hh>
58 : #include <EnergyPlus/DataLoopNode.hh>
59 : #include <EnergyPlus/DataRoomAirModel.hh>
60 : #include <EnergyPlus/DataSurfaces.hh>
61 : #include <EnergyPlus/DataZoneEquipment.hh>
62 : #include <EnergyPlus/InternalHeatGains.hh>
63 : #include <EnergyPlus/MundtSimMgr.hh>
64 : #include <EnergyPlus/OutputProcessor.hh>
65 : #include <EnergyPlus/Psychrometrics.hh>
66 : #include <EnergyPlus/UtilityRoutines.hh>
67 : #include <EnergyPlus/ZoneTempPredictorCorrector.hh>
68 :
69 : namespace EnergyPlus {
70 :
71 : namespace RoomAir {
72 :
73 : // MODULE INFORMATION:
74 : // AUTHOR Brent Griffith
75 : // DATE WRITTEN February 2002
76 : // RE-ENGINEERED June 2003, EnergyPlus Implementation (CC)
77 : // MODIFIED February 2004, fix allocate-deallocate problem (CC)
78 :
79 : // PURPOSE OF THIS MODULE:
80 : // This module is the main module for running the
81 : // nodal air Mundt model...
82 :
83 : // METHODOLOGY EMPLOYED:
84 : // This module contains all subroutines required by the mundt model.
85 : // The following modules from AirToolkit included in this module are:
86 : // 1) MundtSimMgr Module,
87 : // 2) MundtInputMgr Module, and
88 : // 3) DataMundt Module,
89 :
90 : // REFERENCES:
91 : // AirToolkit source code
92 :
93 : // OTHER NOTES:
94 : // na
95 :
96 : // Data
97 : // MODULE PARAMETER DEFINITIONS:
98 : Real64 constexpr CpAir = 1005.0; // Specific heat of air
99 : Real64 constexpr MinSlope = 0.001; // Bound on result from Mundt model
100 : Real64 constexpr MaxSlope = 5.0; // Bound on result from Mundt Model
101 :
102 0 : void ManageDispVent1Node(EnergyPlusData &state, int const ZoneNum) // index number for the specified zone
103 : {
104 :
105 : // SUBROUTINE INFORMATION:
106 : // AUTHOR Chanvit Chantrasrisalai
107 : // DATE WRITTEN July 2003
108 : // MODIFIED February 2004, fix allocate-deallocate problem (CC)
109 : // RE-ENGINEERED na
110 :
111 : // initialize Mundt model data
112 0 : if (state.dataHeatBal->MundtFirstTimeFlag) {
113 0 : InitDispVent1Node(state);
114 0 : state.dataHeatBal->MundtFirstTimeFlag = false;
115 : }
116 :
117 : // identify the current zone index for zones using Mundt model
118 0 : state.dataMundtSimMgr->MundtZoneNum = state.dataMundtSimMgr->ZoneData(ZoneNum).MundtZoneIndex;
119 :
120 : // transfer data from surface domain to air domain for the specified zone
121 0 : GetSurfHBDataForDispVent1Node(state, ZoneNum);
122 :
123 : // use the Mundt model only for cooling case
124 0 : if ((state.dataMundtSimMgr->SupplyAirVolumeRate > 0.0001) && (state.dataMundtSimMgr->QsysCoolTot > 0.0001)) {
125 :
126 : // setup Mundt model
127 0 : bool ErrorsFound = false;
128 0 : SetupDispVent1Node(state, ZoneNum, ErrorsFound);
129 0 : if (ErrorsFound) {
130 0 : ShowFatalError(state, "ManageMundtModel: Errors in setting up Mundt Model. Preceding condition(s) cause termination.");
131 : }
132 :
133 : // perform Mundt model calculations
134 0 : CalcDispVent1Node(state, ZoneNum);
135 : }
136 :
137 : // transfer data from air domain back to surface domain for the specified zone
138 0 : SetSurfHBDataForDispVent1Node(state, ZoneNum);
139 0 : }
140 :
141 : //*****************************************************************************************
142 :
143 0 : void InitDispVent1Node(EnergyPlusData &state)
144 : {
145 :
146 : // SUBROUTINE INFORMATION:
147 : // AUTHOR Chanvit Chantrasrisalai
148 : // DATE WRITTEN February 2004
149 : // MODIFIED na
150 : // RE-ENGINEERED na
151 :
152 : // PURPOSE OF THIS SUBROUTINE:
153 : // initialize Mundt-model variables
154 :
155 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
156 : int NodeNum; // index for air nodes
157 : int ZoneIndex; // index for zones
158 : int NumOfAirNodes; // total number of nodes in each zone
159 : int NumOfMundtZones; // number of zones using the Mundt model
160 : int MundtZoneIndex; // index for zones using the Mundt model
161 : int MaxNumOfSurfs; // maximum of number of surfaces
162 : int MaxNumOfFloorSurfs; // maximum of number of surfaces
163 : int MaxNumOfAirNodes; // maximum of number of air nodes
164 : int MaxNumOfRoomNodes; // maximum of number of nodes connected to walls
165 : int RoomNodesCount; // number of nodes connected to walls
166 : int FloorSurfCount; // number of nodes connected to walls
167 : int AirNodeBeginNum; // index number of the first air node for this zone
168 : int AirNodeNum; // index for air nodes
169 : bool AirNodeFoundFlag; // flag used for error check
170 : bool ErrorsFound; // true if errors found in init
171 :
172 : // allocate and initialize zone data
173 0 : state.dataMundtSimMgr->ZoneData.allocate(state.dataGlobal->NumOfZones);
174 0 : for (auto &e : state.dataMundtSimMgr->ZoneData) {
175 0 : e.NumOfSurfs = 0;
176 0 : e.MundtZoneIndex = 0;
177 : }
178 :
179 : // get zone data
180 0 : NumOfMundtZones = 0;
181 0 : MaxNumOfSurfs = 0;
182 0 : MaxNumOfFloorSurfs = 0;
183 0 : MaxNumOfAirNodes = 0;
184 0 : MaxNumOfRoomNodes = 0;
185 0 : ErrorsFound = false;
186 0 : for (ZoneIndex = 1; ZoneIndex <= state.dataGlobal->NumOfZones; ++ZoneIndex) {
187 0 : auto const &thisZone = state.dataHeatBal->Zone(ZoneIndex);
188 0 : if (state.dataRoomAir->AirModel(ZoneIndex).AirModel == RoomAir::RoomAirModel::DispVent1Node) {
189 : // find number of zones using the Mundt model
190 0 : ++NumOfMundtZones;
191 : // find maximum number of surfaces in zones using the Mundt model
192 0 : int NumOfSurfs = 0;
193 0 : for (int spaceNum : thisZone.spaceIndexes) {
194 0 : auto const &thisSpace = state.dataHeatBal->space(spaceNum);
195 0 : for (int surfNum = thisSpace.HTSurfaceFirst; surfNum <= thisSpace.HTSurfaceLast; ++surfNum) {
196 0 : state.dataMundtSimMgr->ZoneData(ZoneIndex).HBsurfaceIndexes.emplace_back(surfNum);
197 0 : ++NumOfSurfs;
198 : }
199 0 : MaxNumOfSurfs = max(MaxNumOfSurfs, NumOfSurfs);
200 : // find maximum number of air nodes in zones using the Mundt model
201 0 : NumOfAirNodes = state.dataRoomAir->TotNumOfZoneAirNodes(ZoneIndex);
202 0 : MaxNumOfAirNodes = max(MaxNumOfAirNodes, NumOfAirNodes);
203 : // assign zone data
204 0 : state.dataMundtSimMgr->ZoneData(ZoneIndex).NumOfSurfs = NumOfSurfs;
205 0 : state.dataMundtSimMgr->ZoneData(ZoneIndex).MundtZoneIndex = NumOfMundtZones;
206 0 : }
207 : }
208 : }
209 :
210 : // allocate and initialize surface and air-node data
211 0 : state.dataMundtSimMgr->ID1dSurf.allocate(MaxNumOfSurfs);
212 0 : state.dataMundtSimMgr->TheseSurfIDs.allocate(MaxNumOfSurfs);
213 0 : state.dataMundtSimMgr->MundtAirSurf.allocate(MaxNumOfSurfs, NumOfMundtZones);
214 0 : state.dataMundtSimMgr->LineNode.allocate(MaxNumOfAirNodes, NumOfMundtZones);
215 0 : for (int SurfNum = 1; SurfNum <= MaxNumOfSurfs; ++SurfNum) {
216 0 : state.dataMundtSimMgr->ID1dSurf(SurfNum) = SurfNum;
217 : }
218 0 : for (auto &e : state.dataMundtSimMgr->MundtAirSurf) {
219 0 : e.Area = 0.0;
220 0 : e.Temp = 25.0;
221 0 : e.Hc = 0.0;
222 0 : e.TMeanAir = 25.0;
223 : }
224 0 : for (auto &e : state.dataMundtSimMgr->LineNode) {
225 0 : e.AirNodeName.clear();
226 0 : e.ClassType = RoomAir::AirNodeType::Invalid;
227 0 : e.Height = 0.0;
228 0 : e.Temp = 25.0;
229 : }
230 :
231 : // get constant data (unchanged over time) for surfaces and air nodes
232 0 : for (MundtZoneIndex = 1; MundtZoneIndex <= NumOfMundtZones; ++MundtZoneIndex) {
233 0 : for (ZoneIndex = 1; ZoneIndex <= state.dataGlobal->NumOfZones; ++ZoneIndex) {
234 0 : auto &thisZone = state.dataHeatBal->Zone(ZoneIndex);
235 0 : if (state.dataMundtSimMgr->ZoneData(ZoneIndex).MundtZoneIndex == MundtZoneIndex) {
236 : // get surface data
237 0 : for (int surfNum = 1; surfNum <= state.dataMundtSimMgr->ZoneData(ZoneIndex).NumOfSurfs; ++surfNum) {
238 0 : state.dataMundtSimMgr->MundtAirSurf(surfNum, MundtZoneIndex).Area =
239 0 : state.dataSurface->Surface(state.dataMundtSimMgr->ZoneData(ZoneIndex).HBsurfaceIndexes(surfNum)).Area;
240 : }
241 :
242 : // get air node data
243 0 : RoomNodesCount = 0;
244 0 : FloorSurfCount = 0;
245 0 : for (NodeNum = 1; NodeNum <= state.dataRoomAir->TotNumOfZoneAirNodes(ZoneIndex); ++NodeNum) {
246 :
247 0 : state.dataMundtSimMgr->LineNode(NodeNum, MundtZoneIndex)
248 0 : .SurfMask.allocate(state.dataMundtSimMgr->ZoneData(ZoneIndex).NumOfSurfs);
249 :
250 0 : if (NodeNum == 1) {
251 0 : AirNodeBeginNum = NodeNum;
252 : }
253 :
254 : // error check for debugging
255 0 : if (AirNodeBeginNum > state.dataRoomAir->TotNumOfAirNodes) {
256 0 : ShowFatalError(state, "An array bound exceeded. Error in InitMundtModel subroutine of MundtSimMgr.");
257 : }
258 :
259 0 : AirNodeFoundFlag = false;
260 0 : for (AirNodeNum = AirNodeBeginNum; AirNodeNum <= state.dataRoomAir->TotNumOfAirNodes; ++AirNodeNum) {
261 0 : if (Util::SameString(state.dataRoomAir->AirNode(AirNodeNum).ZoneName, thisZone.Name)) {
262 0 : state.dataMundtSimMgr->LineNode(NodeNum, MundtZoneIndex).ClassType = state.dataRoomAir->AirNode(AirNodeNum).ClassType;
263 0 : state.dataMundtSimMgr->LineNode(NodeNum, MundtZoneIndex).AirNodeName = state.dataRoomAir->AirNode(AirNodeNum).Name;
264 0 : state.dataMundtSimMgr->LineNode(NodeNum, MundtZoneIndex).Height = state.dataRoomAir->AirNode(AirNodeNum).Height;
265 0 : state.dataMundtSimMgr->LineNode(NodeNum, MundtZoneIndex).SurfMask = state.dataRoomAir->AirNode(AirNodeNum).SurfMask;
266 0 : SetupOutputVariable(state,
267 : "Room Air Node Air Temperature",
268 : Constant::Units::C,
269 0 : state.dataMundtSimMgr->LineNode(NodeNum, MundtZoneIndex).Temp,
270 : OutputProcessor::TimeStepType::System,
271 : OutputProcessor::StoreType::Average,
272 0 : state.dataMundtSimMgr->LineNode(NodeNum, MundtZoneIndex).AirNodeName);
273 :
274 0 : AirNodeBeginNum = AirNodeNum + 1;
275 0 : AirNodeFoundFlag = true;
276 :
277 0 : break;
278 : }
279 : }
280 :
281 : // error check for debugging
282 0 : if (!AirNodeFoundFlag) {
283 0 : ShowSevereError(state, format("InitMundtModel: Air Node in Zone=\"{}\" is not found.", thisZone.Name));
284 0 : ErrorsFound = true;
285 0 : continue;
286 : }
287 :
288 : // count air nodes connected to walls in each zone
289 0 : if (state.dataMundtSimMgr->LineNode(NodeNum, MundtZoneIndex).ClassType == RoomAir::AirNodeType::Mundt) {
290 0 : ++RoomNodesCount;
291 : }
292 :
293 : // count floors in each zone
294 0 : if (state.dataMundtSimMgr->LineNode(NodeNum, MundtZoneIndex).ClassType == RoomAir::AirNodeType::Floor) {
295 0 : FloorSurfCount += count(state.dataMundtSimMgr->LineNode(NodeNum, MundtZoneIndex).SurfMask);
296 : }
297 : }
298 : // got data for this zone so exit the zone loop
299 0 : if (AirNodeFoundFlag) {
300 0 : break;
301 : }
302 : }
303 : }
304 :
305 0 : MaxNumOfRoomNodes = max(MaxNumOfRoomNodes, RoomNodesCount);
306 0 : MaxNumOfFloorSurfs = max(MaxNumOfFloorSurfs, FloorSurfCount);
307 : }
308 :
309 0 : if (ErrorsFound) {
310 0 : ShowFatalError(state, "InitMundtModel: Preceding condition(s) cause termination.");
311 : }
312 :
313 : // allocate arrays
314 0 : state.dataMundtSimMgr->RoomNodeIDs.allocate(MaxNumOfRoomNodes);
315 0 : state.dataMundtSimMgr->FloorSurfSetIDs.allocate(MaxNumOfFloorSurfs);
316 0 : state.dataMundtSimMgr->FloorSurf.allocate(MaxNumOfFloorSurfs);
317 0 : }
318 :
319 : //*****************************************************************************************
320 :
321 0 : void GetSurfHBDataForDispVent1Node(EnergyPlusData &state, int const ZoneNum) // index number for the specified zone
322 : {
323 :
324 : // SUBROUTINE INFORMATION:
325 : // AUTHOR Weixiu Kong
326 : // DATE WRITTEN April 2003
327 : // MODIFIED July 2003 (CC)
328 : // February 2004, fix allocate-deallocate problem (CC)
329 :
330 : // PURPOSE OF THIS SUBROUTINE:
331 : // map data from surface domain to air domain for each particular zone
332 :
333 : using Psychrometrics::PsyCpAirFnW;
334 : using Psychrometrics::PsyRhoAirFnPbTdbW;
335 : using Psychrometrics::PsyWFnTdpPb;
336 :
337 : Real64 CpAir; // specific heat
338 : Real64 SumSysMCp; // zone sum of air system MassFlowRate*Cp
339 : Real64 SumSysMCpT; // zone sum of air system MassFlowRate*Cp*T
340 : Real64 MassFlowRate; // mass flowrate
341 : Real64 NodeTemp; // node temperature
342 : int ZoneNode; // index number for specified zone node
343 : Real64 ZoneMassFlowRate; // zone mass flowrate
344 : int ZoneEquipConfigNum; // index number for zone equipment configuration
345 : Real64 ZoneMult; // total zone multiplier
346 : Real64 RetAirConvGain;
347 :
348 0 : auto const &Zone(state.dataHeatBal->Zone);
349 :
350 : // determine ZoneEquipConfigNum for this zone
351 0 : ZoneEquipConfigNum = ZoneNum;
352 : // check whether this zone is a controlled zone or not
353 0 : if (!Zone(ZoneNum).IsControlled) {
354 0 : ShowFatalError(state, format("Zones must be controlled for Mundt air model. No system serves zone {}", Zone(ZoneNum).Name));
355 0 : return;
356 : }
357 :
358 : // determine information required by Mundt model
359 0 : state.dataMundtSimMgr->ZoneHeight = Zone(ZoneNum).CeilingHeight;
360 0 : state.dataMundtSimMgr->ZoneFloorArea = Zone(ZoneNum).FloorArea;
361 0 : ZoneMult = Zone(ZoneNum).Multiplier * Zone(ZoneNum).ListMultiplier;
362 :
363 : // supply air flowrate is the same as zone air flowrate
364 0 : ZoneNode = Zone(ZoneNum).SystemZoneNodeNumber;
365 0 : state.dataMundtSimMgr->ZoneAirDensity =
366 0 : PsyRhoAirFnPbTdbW(state,
367 0 : state.dataEnvrn->OutBaroPress,
368 0 : state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).MAT,
369 0 : PsyWFnTdpPb(state, state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).MAT, state.dataEnvrn->OutBaroPress));
370 0 : ZoneMassFlowRate = state.dataLoopNodes->Node(ZoneNode).MassFlowRate;
371 0 : state.dataMundtSimMgr->SupplyAirVolumeRate = ZoneMassFlowRate / state.dataMundtSimMgr->ZoneAirDensity;
372 0 : auto &thisZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum);
373 0 : if (ZoneMassFlowRate <= 0.0001) {
374 : // system is off
375 0 : state.dataMundtSimMgr->QsysCoolTot = 0.0;
376 : } else {
377 : // determine supply air conditions
378 0 : SumSysMCp = 0.0;
379 0 : SumSysMCpT = 0.0;
380 0 : for (int NodeNum = 1; NodeNum <= state.dataZoneEquip->ZoneEquipConfig(ZoneEquipConfigNum).NumInletNodes; ++NodeNum) {
381 0 : NodeTemp = state.dataLoopNodes->Node(state.dataZoneEquip->ZoneEquipConfig(ZoneEquipConfigNum).InletNode(NodeNum)).Temp;
382 0 : MassFlowRate = state.dataLoopNodes->Node(state.dataZoneEquip->ZoneEquipConfig(ZoneEquipConfigNum).InletNode(NodeNum)).MassFlowRate;
383 0 : CpAir = PsyCpAirFnW(thisZoneHB.airHumRat);
384 0 : SumSysMCp += MassFlowRate * CpAir;
385 0 : SumSysMCpT += MassFlowRate * CpAir * NodeTemp;
386 : }
387 : // prevent dividing by zero due to zero supply air flow rate
388 0 : if (SumSysMCp <= 0.0) {
389 0 : state.dataMundtSimMgr->SupplyAirTemp =
390 0 : state.dataLoopNodes->Node(state.dataZoneEquip->ZoneEquipConfig(ZoneEquipConfigNum).InletNode(1)).Temp;
391 : } else {
392 : // a weighted average of the inlet temperatures
393 0 : state.dataMundtSimMgr->SupplyAirTemp = SumSysMCpT / SumSysMCp;
394 : }
395 : // determine cooling load
396 0 : CpAir = PsyCpAirFnW(thisZoneHB.airHumRat);
397 0 : state.dataMundtSimMgr->QsysCoolTot =
398 0 : -(SumSysMCpT - ZoneMassFlowRate * CpAir * state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).MAT);
399 : }
400 : // determine heat gains
401 0 : state.dataMundtSimMgr->ConvIntGain = InternalHeatGains::zoneSumAllInternalConvectionGains(state, ZoneNum);
402 0 : state.dataMundtSimMgr->ConvIntGain += state.dataHeatBalFanSys->SumConvHTRadSys(ZoneNum) + state.dataHeatBalFanSys->SumConvPool(ZoneNum) +
403 0 : thisZoneHB.SysDepZoneLoadsLagged + thisZoneHB.NonAirSystemResponse / ZoneMult;
404 :
405 : // Add heat to return air if zonal system (no return air) or cycling system (return air frequently very
406 : // low or zero)
407 0 : if (Zone(ZoneNum).NoHeatToReturnAir) {
408 0 : RetAirConvGain = InternalHeatGains::zoneSumAllReturnAirConvectionGains(state, ZoneNum, 0);
409 0 : state.dataMundtSimMgr->ConvIntGain += RetAirConvGain;
410 : }
411 :
412 0 : state.dataMundtSimMgr->QventCool =
413 0 : -thisZoneHB.MCPI * (Zone(ZoneNum).OutDryBulbTemp - state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).MAT);
414 :
415 : // get surface data
416 0 : for (int SurfNum = 1; SurfNum <= state.dataMundtSimMgr->ZoneData(ZoneNum).NumOfSurfs; ++SurfNum) {
417 0 : state.dataMundtSimMgr->MundtAirSurf(SurfNum, state.dataMundtSimMgr->MundtZoneNum).Temp =
418 0 : state.dataHeatBalSurf->SurfTempIn(state.dataMundtSimMgr->ZoneData(ZoneNum).HBsurfaceIndexes(SurfNum));
419 0 : state.dataMundtSimMgr->MundtAirSurf(SurfNum, state.dataMundtSimMgr->MundtZoneNum).Hc =
420 0 : state.dataHeatBalSurf->SurfHConvInt(state.dataMundtSimMgr->ZoneData(ZoneNum).HBsurfaceIndexes(SurfNum));
421 : }
422 : }
423 :
424 : //*****************************************************************************************
425 :
426 0 : void SetupDispVent1Node(EnergyPlusData &state,
427 : int const ZoneNum, // index number for the specified zone
428 : bool &ErrorsFound // true if problems setting up model
429 : )
430 : {
431 :
432 : // SUBROUTINE INFORMATION:
433 : // AUTHOR Brent Griffith
434 : // DATE WRITTEN Febraury 2002
435 : // RE-ENGINEERED June 2003, EnergyPlus Implementation (CC)
436 : // MODIFIED February 2004, fix allocate-deallocate problem (CC)
437 :
438 : // PURPOSE OF THIS SUBROUTINE:
439 : // Subroutine must be called once before main model calculation
440 : // need to pass some zone characteristics only once
441 : // initializes module level variables, collect info from Air Data Manager
442 :
443 : // METHODOLOGY EMPLOYED:
444 : // na
445 :
446 : // REFERENCES:
447 : // na
448 :
449 : // Locals
450 : // SUBROUTINE ARGUMENT DEFINITIONS:
451 :
452 : // SUBROUTINE PARAMETER DEFINITIONS:
453 : // na
454 :
455 : // INTERFACE BLOCK SPECIFICATIONS:
456 : // na
457 :
458 : // DERIVED TYPE DEFINITIONS:
459 : // na
460 :
461 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
462 : int NodeNum; // index for air nodes
463 :
464 : // set up air node ID
465 0 : state.dataMundtSimMgr->NumRoomNodes = 0;
466 0 : for (NodeNum = 1; NodeNum <= state.dataRoomAir->TotNumOfZoneAirNodes(ZoneNum); ++NodeNum) {
467 0 : switch (state.dataMundtSimMgr->LineNode(NodeNum, state.dataMundtSimMgr->MundtZoneNum).ClassType) {
468 0 : case RoomAir::AirNodeType::Inlet: { // inlet
469 0 : state.dataMundtSimMgr->SupplyNodeID = NodeNum;
470 0 : } break;
471 0 : case RoomAir::AirNodeType::Floor: { // floor
472 0 : state.dataMundtSimMgr->MundtFootAirID = NodeNum;
473 0 : } break;
474 0 : case RoomAir::AirNodeType::Control: { // thermostat
475 0 : state.dataMundtSimMgr->TstatNodeID = NodeNum;
476 0 : } break;
477 0 : case RoomAir::AirNodeType::Ceiling: { // ceiling
478 0 : state.dataMundtSimMgr->MundtCeilAirID = NodeNum;
479 0 : } break;
480 0 : case RoomAir::AirNodeType::Mundt: { // wall
481 0 : ++state.dataMundtSimMgr->NumRoomNodes;
482 0 : state.dataMundtSimMgr->RoomNodeIDs(state.dataMundtSimMgr->NumRoomNodes) = NodeNum;
483 0 : } break;
484 0 : case RoomAir::AirNodeType::Return: { // return
485 0 : state.dataMundtSimMgr->ReturnNodeID = NodeNum;
486 0 : } break;
487 0 : default: {
488 0 : ShowSevereError(state, "SetupMundtModel: Non-Standard Type of Air Node for Mundt Model");
489 0 : ErrorsFound = true;
490 0 : } break;
491 : }
492 : }
493 :
494 : // get number of floors in the zone and setup FloorSurfSetIDs
495 0 : if (state.dataMundtSimMgr->MundtFootAirID > 0) {
496 0 : state.dataMundtSimMgr->NumFloorSurfs =
497 0 : count(state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->MundtFootAirID, state.dataMundtSimMgr->MundtZoneNum).SurfMask);
498 0 : state.dataMundtSimMgr->FloorSurfSetIDs =
499 0 : pack(state.dataMundtSimMgr->ID1dSurf,
500 0 : state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->MundtFootAirID, state.dataMundtSimMgr->MundtZoneNum).SurfMask);
501 : // initialize floor surface data (a must since NumFloorSurfs is varied among zones)
502 0 : for (auto &e : state.dataMundtSimMgr->FloorSurf) {
503 0 : e.Temp = 25.0;
504 0 : e.Hc = 0.0;
505 0 : e.Area = 0.0;
506 : }
507 : // get floor surface data
508 0 : for (int SurfNum = 1; SurfNum <= state.dataMundtSimMgr->NumFloorSurfs; ++SurfNum) {
509 0 : state.dataMundtSimMgr->FloorSurf(SurfNum).Temp =
510 0 : state.dataMundtSimMgr->MundtAirSurf(state.dataMundtSimMgr->FloorSurfSetIDs(SurfNum), state.dataMundtSimMgr->MundtZoneNum).Temp;
511 0 : state.dataMundtSimMgr->FloorSurf(SurfNum).Hc =
512 0 : state.dataMundtSimMgr->MundtAirSurf(state.dataMundtSimMgr->FloorSurfSetIDs(SurfNum), state.dataMundtSimMgr->MundtZoneNum).Hc;
513 0 : state.dataMundtSimMgr->FloorSurf(SurfNum).Area =
514 0 : state.dataMundtSimMgr->MundtAirSurf(state.dataMundtSimMgr->FloorSurfSetIDs(SurfNum), state.dataMundtSimMgr->MundtZoneNum).Area;
515 : }
516 : } else {
517 0 : ShowSevereError(state, format("SetupMundtModel: Mundt model has no FloorAirNode, Zone={}", state.dataHeatBal->Zone(ZoneNum).Name));
518 0 : ErrorsFound = true;
519 : }
520 0 : }
521 :
522 : //*****************************************************************************************
523 :
524 0 : void CalcDispVent1Node(EnergyPlusData &state, int const ZoneNum) // index number for the specified zone
525 : {
526 :
527 : // SUBROUTINE INFORMATION:
528 : // AUTHOR Brent Griffith
529 : // DATE WRITTEN September 2001
530 : // RE-ENGINEERED July 2003, EnergyPlus Implementation (CC)
531 : // MODIFIED February 2004, fix allocate-deallocate problem (CC)
532 :
533 : // PURPOSE OF THIS SUBROUTINE:
534 : // Compute the simplified version of Mundt and store results in Air data Manager
535 : // argument passing is plentiful but are IN and nothing out.
536 : // these variables are scaler conditions at current HB day,timestep, and iteration
537 : // This subroutine is USE'ed by heat balance driver (top level module)
538 :
539 : // METHODOLOGY EMPLOYED:
540 : // apply Mundt's simple model for delta Temp head-foot and update values in Air data manager.
541 :
542 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
543 : Real64 TAirFoot; // air temperature at the floor
544 : Real64 TAirCeil; // air temperature at the ceiling
545 : Real64 TLeaving; // air temperature leaving zone (= return air temp)
546 : Real64 TControlPoint; // air temperature at thermostat
547 : Real64 Slope; // vertical air temperature gradient (slope) from Mundt equations
548 : Real64 QequipConvFloor; // convective gain at the floor due to internal heat sources
549 : Real64 QSensInfilFloor; // convective gain at the floor due to infiltration
550 : Real64 FloorSumHAT; // sum of hci*area*temp at the floor
551 : Real64 FloorSumHA; // sum of hci*area at the floor
552 : Real64 TThisNode; // dummy variable for air node temp
553 : int NodeNum; // index for air nodes
554 : int SurfNum; // index for surfaces
555 : int SurfCounted; // number of surfaces assciated with an air node
556 :
557 : // apply floor splits
558 0 : QequipConvFloor = state.dataRoomAir->ConvectiveFloorSplit(ZoneNum) * state.dataMundtSimMgr->ConvIntGain;
559 0 : QSensInfilFloor = -state.dataRoomAir->InfiltratFloorSplit(ZoneNum) * state.dataMundtSimMgr->QventCool;
560 :
561 : // Begin computations for Mundt model
562 :
563 : // do summations for floor surfaces of this zone
564 0 : FloorSumHAT = 0.0;
565 0 : FloorSumHA = 0.0;
566 0 : for (auto const &s : state.dataMundtSimMgr->FloorSurf) {
567 0 : FloorSumHAT += s.Area * s.Hc * s.Temp;
568 0 : FloorSumHA += s.Area * s.Hc;
569 : }
570 :
571 : // Eq 2.2 in ASHRAE RP 1222 Final report
572 0 : TAirFoot =
573 0 : ((state.dataMundtSimMgr->ZoneAirDensity * CpAir * state.dataMundtSimMgr->SupplyAirVolumeRate * state.dataMundtSimMgr->SupplyAirTemp) +
574 0 : (FloorSumHAT) + QequipConvFloor + QSensInfilFloor) /
575 0 : ((state.dataMundtSimMgr->ZoneAirDensity * CpAir * state.dataMundtSimMgr->SupplyAirVolumeRate) + (FloorSumHA));
576 :
577 : // prevent dividing by zero due to zero cooling load (or zero supply air flow rate)
578 0 : if (state.dataMundtSimMgr->QsysCoolTot <= 0.0) {
579 0 : TLeaving = state.dataMundtSimMgr->SupplyAirTemp;
580 : } else {
581 : // Eq 2.3 in ASHRAE RP 1222 Final report
582 0 : TLeaving =
583 0 : (state.dataMundtSimMgr->QsysCoolTot / (state.dataMundtSimMgr->ZoneAirDensity * CpAir * state.dataMundtSimMgr->SupplyAirVolumeRate)) +
584 0 : state.dataMundtSimMgr->SupplyAirTemp;
585 : }
586 :
587 : // Eq 2.4 in ASHRAE RP 1222 Final report
588 0 : Slope = (TLeaving - TAirFoot) /
589 0 : (state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->ReturnNodeID, state.dataMundtSimMgr->MundtZoneNum).Height -
590 0 : state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->MundtFootAirID, state.dataMundtSimMgr->MundtZoneNum).Height);
591 : // check slope
592 0 : if (Slope > MaxSlope) {
593 0 : Slope = MaxSlope;
594 0 : TAirFoot = TLeaving -
595 0 : (Slope * (state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->ReturnNodeID, state.dataMundtSimMgr->MundtZoneNum).Height -
596 0 : state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->MundtFootAirID, state.dataMundtSimMgr->MundtZoneNum).Height));
597 : }
598 0 : if (Slope < MinSlope) { // pretty much vertical
599 0 : Slope = MinSlope;
600 0 : TAirFoot = TLeaving;
601 : }
602 :
603 : // Eq 2.4 in ASHRAE RP 1222 Final report
604 0 : TAirCeil =
605 0 : TLeaving - (Slope * (state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->ReturnNodeID, state.dataMundtSimMgr->MundtZoneNum).Height -
606 0 : state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->MundtCeilAirID, state.dataMundtSimMgr->MundtZoneNum).Height));
607 :
608 0 : TControlPoint =
609 0 : TLeaving - (Slope * (state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->ReturnNodeID, state.dataMundtSimMgr->MundtZoneNum).Height -
610 0 : state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->TstatNodeID, state.dataMundtSimMgr->MundtZoneNum).Height));
611 :
612 : // determine air node temperatures in this zone
613 0 : SetNodeResult(state, state.dataMundtSimMgr->SupplyNodeID, state.dataMundtSimMgr->SupplyAirTemp);
614 0 : SetNodeResult(state, state.dataMundtSimMgr->ReturnNodeID, TLeaving);
615 0 : SetNodeResult(state, state.dataMundtSimMgr->MundtCeilAirID, TAirCeil);
616 0 : SetNodeResult(state, state.dataMundtSimMgr->MundtFootAirID, TAirFoot);
617 0 : SetNodeResult(state, state.dataMundtSimMgr->TstatNodeID, TControlPoint);
618 :
619 0 : for (SurfNum = 1; SurfNum <= state.dataMundtSimMgr->NumFloorSurfs; ++SurfNum) {
620 0 : SetSurfTmeanAir(state, state.dataMundtSimMgr->FloorSurfSetIDs(SurfNum), TAirFoot);
621 : }
622 :
623 0 : SurfCounted = count(state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->MundtCeilAirID, state.dataMundtSimMgr->MundtZoneNum).SurfMask);
624 0 : state.dataMundtSimMgr->TheseSurfIDs =
625 0 : pack(state.dataMundtSimMgr->ID1dSurf,
626 0 : state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->MundtCeilAirID, state.dataMundtSimMgr->MundtZoneNum).SurfMask);
627 0 : for (SurfNum = 1; SurfNum <= SurfCounted; ++SurfNum) {
628 0 : SetSurfTmeanAir(state, state.dataMundtSimMgr->TheseSurfIDs(SurfNum), TAirCeil);
629 : }
630 :
631 0 : for (NodeNum = 1; NodeNum <= state.dataMundtSimMgr->NumRoomNodes; ++NodeNum) {
632 0 : TThisNode =
633 : TLeaving -
634 0 : (Slope * (state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->ReturnNodeID, state.dataMundtSimMgr->MundtZoneNum).Height -
635 0 : state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->RoomNodeIDs(NodeNum), state.dataMundtSimMgr->MundtZoneNum).Height));
636 0 : SetNodeResult(state, state.dataMundtSimMgr->RoomNodeIDs(NodeNum), TThisNode);
637 0 : SurfCounted =
638 0 : count(state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->RoomNodeIDs(NodeNum), state.dataMundtSimMgr->MundtZoneNum).SurfMask);
639 0 : state.dataMundtSimMgr->TheseSurfIDs =
640 0 : pack(state.dataMundtSimMgr->ID1dSurf,
641 0 : state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->RoomNodeIDs(NodeNum), state.dataMundtSimMgr->MundtZoneNum).SurfMask);
642 0 : for (SurfNum = 1; SurfNum <= SurfCounted; ++SurfNum) {
643 0 : SetSurfTmeanAir(state, state.dataMundtSimMgr->TheseSurfIDs(SurfNum), TThisNode);
644 : }
645 : }
646 0 : }
647 :
648 : //*****************************************************************************************
649 :
650 0 : void SetNodeResult(EnergyPlusData &state,
651 : int const NodeID, // node ID
652 : Real64 const TempResult // temperature for the specified air node
653 : )
654 : {
655 :
656 : // SUBROUTINE INFORMATION:
657 : // AUTHOR Brent Griffith
658 : // DATE WRITTEN September 2002
659 : // RE-ENGINEERED April 2003, Weixiu Kong, EnergyPlus Implementation
660 : // MODIFIED February 2004, fix allocate-deallocate problem (CC)
661 :
662 : // PURPOSE OF THIS SUBROUTINE:
663 : // provide set routine for reporting results
664 : // to AirDataManager from air model
665 :
666 : // METHODOLOGY EMPLOYED:
667 : // na
668 :
669 : // REFERENCES:
670 : // na
671 :
672 : // USE STATEMENTS:
673 : // na
674 :
675 : // Locals
676 : // SUBROUTINE ARGUMENT DEFINITIONS:
677 :
678 : // SUBROUTINE PARAMETER DEFINITIONS:
679 : // na
680 :
681 : // INTERFACE BLOCK SPECIFICATIONS:
682 : // na
683 :
684 : // DERIVED TYPE DEFINITIONS:
685 : // na
686 :
687 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
688 : // na
689 :
690 0 : state.dataMundtSimMgr->LineNode(NodeID, state.dataMundtSimMgr->MundtZoneNum).Temp = TempResult;
691 0 : }
692 :
693 : //*****************************************************************************************
694 :
695 0 : void SetSurfTmeanAir(EnergyPlusData &state,
696 : int const SurfID, // surface ID
697 : Real64 const TeffAir // temperature of air node adjacent to the specified surface
698 : )
699 : {
700 :
701 : // SUBROUTINE INFORMATION:
702 : // AUTHOR Brent Griffith
703 : // DATE WRITTEN September 2002
704 : // RE-ENGINEERED April 2003, Wiexiu Kong, EnergyPlus Implementation
705 : // MODIFIED February 2004, fix allocate-deallocate problem (CC)
706 :
707 : // PURPOSE OF THIS SUBROUTINE:
708 : // provide set routine for air model prediction of
709 : // effective air for single surface
710 :
711 0 : state.dataMundtSimMgr->MundtAirSurf(SurfID, state.dataMundtSimMgr->MundtZoneNum).TMeanAir = TeffAir;
712 0 : }
713 :
714 : //*****************************************************************************************
715 :
716 0 : void SetSurfHBDataForDispVent1Node(EnergyPlusData &state, int const ZoneNum) // index number for the specified zone
717 : {
718 :
719 : // SUBROUTINE INFORMATION:
720 : // AUTHOR Chanvit Chantrasrisalai
721 : // DATE WRITTEN July 2003
722 : // MODIFIED February 2004, fix allocate-deallocate problem (CC)
723 : // RE-ENGINEERED na
724 :
725 : // PURPOSE OF THIS SUBROUTINE:
726 : // map data from air domain back to surface domain for each particular zone
727 :
728 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
729 : Real64 DeltaTemp; // dummy variable for temperature difference
730 :
731 : // get surface info
732 0 : int NumOfSurfs = state.dataMundtSimMgr->ZoneData(ZoneNum).NumOfSurfs;
733 :
734 0 : if ((state.dataMundtSimMgr->SupplyAirVolumeRate > 0.0001) &&
735 0 : (state.dataMundtSimMgr->QsysCoolTot > 0.0001)) { // Controlled zone when the system is on
736 :
737 0 : if (state.dataRoomAir->AirModel(ZoneNum).TempCoupleScheme == RoomAir::CouplingScheme::Direct) {
738 : // Use direct coupling scheme to report air temperatures back to surface/system domains
739 : // a) Bulk air temperatures -> TempEffBulkAir(SurfNum)
740 0 : for (int SurfNum = 1; SurfNum <= NumOfSurfs; ++SurfNum) {
741 0 : int hbSurfNum = state.dataMundtSimMgr->ZoneData(ZoneNum).HBsurfaceIndexes(SurfNum);
742 0 : state.dataHeatBal->SurfTempEffBulkAir(hbSurfNum) =
743 0 : state.dataMundtSimMgr->MundtAirSurf(SurfNum, state.dataMundtSimMgr->MundtZoneNum).TMeanAir;
744 : // set flag for reference air temperature
745 0 : state.dataSurface->SurfTAirRef(hbSurfNum) = DataSurfaces::RefAirTemp::AdjacentAirTemp;
746 0 : state.dataSurface->SurfTAirRefRpt(hbSurfNum) = DataSurfaces::SurfTAirRefReportVals[state.dataSurface->SurfTAirRef(hbSurfNum)];
747 : }
748 : // b) Average zone air temperature -> ZT(ZoneNum)
749 : // For Mundt model, average room air is the weighted value of floor and ceiling air temps
750 : // TRoomAverage = ( LineNode( MundtCeilAirID, MundtZoneNum ).Temp + LineNode( MundtFootAirID, MundtZoneNum ).Temp ) / 2;
751 : // ZT(ZoneNum) = TRoomAverage
752 : // c) Leaving-zone air temperature -> Node(ZoneNode)%Temp
753 0 : int ZoneNodeNum = state.dataHeatBal->Zone(ZoneNum).SystemZoneNodeNumber;
754 0 : state.dataLoopNodes->Node(ZoneNodeNum).Temp =
755 0 : state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->ReturnNodeID, state.dataMundtSimMgr->MundtZoneNum).Temp;
756 : // d) Thermostat air temperature -> TempTstatAir(ZoneNum)
757 0 : state.dataHeatBalFanSys->TempTstatAir(ZoneNum) =
758 0 : state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->TstatNodeID, state.dataMundtSimMgr->MundtZoneNum).Temp;
759 : } else {
760 : // Use indirect coupling scheme to report air temperatures back to surface/system domains
761 : // a) Bulk air temperatures -> TempEffBulkAir(SurfNum)
762 0 : for (int SurfNum = 1; SurfNum <= NumOfSurfs; ++SurfNum) {
763 0 : int hbSurfNum = state.dataMundtSimMgr->ZoneData(ZoneNum).HBsurfaceIndexes(SurfNum);
764 0 : DeltaTemp = state.dataMundtSimMgr->MundtAirSurf(SurfNum, state.dataMundtSimMgr->MundtZoneNum).TMeanAir -
765 0 : state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->TstatNodeID, state.dataMundtSimMgr->MundtZoneNum).Temp;
766 0 : state.dataHeatBal->SurfTempEffBulkAir(hbSurfNum) = state.dataHeatBalFanSys->zoneTstatSetpts(ZoneNum).setpt + DeltaTemp;
767 : // set flag for reference air temperature
768 0 : state.dataSurface->SurfTAirRef(hbSurfNum) = DataSurfaces::RefAirTemp::AdjacentAirTemp;
769 0 : state.dataSurface->SurfTAirRefRpt(hbSurfNum) = DataSurfaces::SurfTAirRefReportVals[state.dataSurface->SurfTAirRef(hbSurfNum)];
770 : }
771 : // b) Average zone air temperature -> ZT(ZoneNum)
772 : // For Mundt model, average room air is the weighted value of floor and ceiling air temps
773 : // TRoomAverage = ( LineNode( MundtCeilAirID, MundtZoneNum ).Temp + LineNode( MundtFootAirID, MundtZoneNum ).Temp ) / 2;
774 : // DeltaTemp = TRoomAverage - LineNode( TstatNodeID, MundtZoneNum ).Temp;
775 : // ZT(ZoneNum) = TempZoneThermostatSetPoint(ZoneNum) + DeltaTemp
776 : // c) Leaving-zone air temperature -> Node(ZoneNode)%Temp
777 0 : int ZoneNodeNum = state.dataHeatBal->Zone(ZoneNum).SystemZoneNodeNumber;
778 0 : DeltaTemp = state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->ReturnNodeID, state.dataMundtSimMgr->MundtZoneNum).Temp -
779 0 : state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->TstatNodeID, state.dataMundtSimMgr->MundtZoneNum).Temp;
780 0 : state.dataLoopNodes->Node(ZoneNodeNum).Temp = state.dataHeatBalFanSys->zoneTstatSetpts(ZoneNum).setpt + DeltaTemp;
781 : // d) Thermostat air temperature -> TempTstatAir(ZoneNum)
782 0 : state.dataHeatBalFanSys->TempTstatAir(ZoneNum) = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum)
783 0 : .ZT; // for indirect coupling, control air temp is equal to mean air temp?
784 : }
785 : // set flag to indicate that Mundt model is used for this zone at the present time
786 0 : state.dataRoomAir->AirModel(ZoneNum).SimAirModel = true;
787 : } else { // Controlled zone when the system is off --> Use the mixing model instead of the Mundt model
788 : // Bulk air temperatures -> TempEffBulkAir(SurfNum)
789 0 : for (int SurfNum = 1; SurfNum <= NumOfSurfs; ++SurfNum) {
790 0 : int hbSurfNum = state.dataMundtSimMgr->ZoneData(ZoneNum).HBsurfaceIndexes(SurfNum);
791 0 : state.dataHeatBal->SurfTempEffBulkAir(hbSurfNum) = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).MAT;
792 : // set flag for reference air temperature
793 0 : state.dataSurface->SurfTAirRef(hbSurfNum) = DataSurfaces::RefAirTemp::ZoneMeanAirTemp;
794 0 : state.dataSurface->SurfTAirRefRpt(hbSurfNum) = DataSurfaces::SurfTAirRefReportVals[state.dataSurface->SurfTAirRef(hbSurfNum)];
795 : }
796 : // set flag to indicate that Mundt model is NOT used for this zone at the present time
797 0 : state.dataRoomAir->AirModel(ZoneNum).SimAirModel = false;
798 : }
799 0 : }
800 :
801 : //*****************************************************************************************
802 :
803 : } // namespace RoomAir
804 :
805 : } // namespace EnergyPlus
|