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) ShowFatalError(state, "ManageMundtModel: Errors in setting up Mundt Model. Preceding condition(s) cause termination.");
130 :
131 : // perform Mundt model calculations
132 0 : CalcDispVent1Node(state, ZoneNum);
133 : }
134 :
135 : // transfer data from air domain back to surface domain for the specified zone
136 0 : SetSurfHBDataForDispVent1Node(state, ZoneNum);
137 0 : }
138 :
139 : //*****************************************************************************************
140 :
141 0 : void InitDispVent1Node(EnergyPlusData &state)
142 : {
143 :
144 : // SUBROUTINE INFORMATION:
145 : // AUTHOR Chanvit Chantrasrisalai
146 : // DATE WRITTEN February 2004
147 : // MODIFIED na
148 : // RE-ENGINEERED na
149 :
150 : // PURPOSE OF THIS SUBROUTINE:
151 : // initialize Mundt-model variables
152 :
153 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
154 : int NodeNum; // index for air nodes
155 : int ZoneIndex; // index for zones
156 : int NumOfAirNodes; // total number of nodes in each zone
157 : int NumOfMundtZones; // number of zones using the Mundt model
158 : int MundtZoneIndex; // index for zones using the Mundt model
159 : int MaxNumOfSurfs; // maximum of number of surfaces
160 : int MaxNumOfFloorSurfs; // maximum of number of surfaces
161 : int MaxNumOfAirNodes; // maximum of number of air nodes
162 : int MaxNumOfRoomNodes; // maximum of number of nodes connected to walls
163 : int RoomNodesCount; // number of nodes connected to walls
164 : int FloorSurfCount; // number of nodes connected to walls
165 : int AirNodeBeginNum; // index number of the first air node for this zone
166 : int AirNodeNum; // index for air nodes
167 : bool AirNodeFoundFlag; // flag used for error check
168 : bool ErrorsFound; // true if errors found in init
169 :
170 : // allocate and initialize zone data
171 0 : state.dataMundtSimMgr->ZoneData.allocate(state.dataGlobal->NumOfZones);
172 0 : for (auto &e : state.dataMundtSimMgr->ZoneData) {
173 0 : e.NumOfSurfs = 0;
174 0 : e.MundtZoneIndex = 0;
175 : }
176 :
177 : // get zone data
178 0 : NumOfMundtZones = 0;
179 0 : MaxNumOfSurfs = 0;
180 0 : MaxNumOfFloorSurfs = 0;
181 0 : MaxNumOfAirNodes = 0;
182 0 : MaxNumOfRoomNodes = 0;
183 0 : ErrorsFound = false;
184 0 : for (ZoneIndex = 1; ZoneIndex <= state.dataGlobal->NumOfZones; ++ZoneIndex) {
185 0 : auto const &thisZone = state.dataHeatBal->Zone(ZoneIndex);
186 0 : if (state.dataRoomAir->AirModel(ZoneIndex).AirModel == RoomAir::RoomAirModel::DispVent1Node) {
187 : // find number of zones using the Mundt model
188 0 : ++NumOfMundtZones;
189 : // find maximum number of surfaces in zones using the Mundt model
190 0 : int NumOfSurfs = 0;
191 0 : for (int spaceNum : thisZone.spaceIndexes) {
192 0 : auto const &thisSpace = state.dataHeatBal->space(spaceNum);
193 0 : for (int surfNum = thisSpace.HTSurfaceFirst; surfNum <= thisSpace.HTSurfaceLast; ++surfNum) {
194 0 : state.dataMundtSimMgr->ZoneData(ZoneIndex).HBsurfaceIndexes.emplace_back(surfNum);
195 0 : ++NumOfSurfs;
196 : }
197 0 : MaxNumOfSurfs = max(MaxNumOfSurfs, NumOfSurfs);
198 : // find maximum number of air nodes in zones using the Mundt model
199 0 : NumOfAirNodes = state.dataRoomAir->TotNumOfZoneAirNodes(ZoneIndex);
200 0 : MaxNumOfAirNodes = max(MaxNumOfAirNodes, NumOfAirNodes);
201 : // assign zone data
202 0 : state.dataMundtSimMgr->ZoneData(ZoneIndex).NumOfSurfs = NumOfSurfs;
203 0 : state.dataMundtSimMgr->ZoneData(ZoneIndex).MundtZoneIndex = NumOfMundtZones;
204 : }
205 : }
206 : }
207 :
208 : // allocate and initialize surface and air-node data
209 0 : state.dataMundtSimMgr->ID1dSurf.allocate(MaxNumOfSurfs);
210 0 : state.dataMundtSimMgr->TheseSurfIDs.allocate(MaxNumOfSurfs);
211 0 : state.dataMundtSimMgr->MundtAirSurf.allocate(MaxNumOfSurfs, NumOfMundtZones);
212 0 : state.dataMundtSimMgr->LineNode.allocate(MaxNumOfAirNodes, NumOfMundtZones);
213 0 : for (int SurfNum = 1; SurfNum <= MaxNumOfSurfs; ++SurfNum)
214 0 : state.dataMundtSimMgr->ID1dSurf(SurfNum) = SurfNum;
215 0 : for (auto &e : state.dataMundtSimMgr->MundtAirSurf) {
216 0 : e.Area = 0.0;
217 0 : e.Temp = 25.0;
218 0 : e.Hc = 0.0;
219 0 : e.TMeanAir = 25.0;
220 : }
221 0 : for (auto &e : state.dataMundtSimMgr->LineNode) {
222 0 : e.AirNodeName.clear();
223 0 : e.ClassType = RoomAir::AirNodeType::Invalid;
224 0 : e.Height = 0.0;
225 0 : e.Temp = 25.0;
226 : }
227 :
228 : // get constant data (unchanged over time) for surfaces and air nodes
229 0 : for (MundtZoneIndex = 1; MundtZoneIndex <= NumOfMundtZones; ++MundtZoneIndex) {
230 0 : for (ZoneIndex = 1; ZoneIndex <= state.dataGlobal->NumOfZones; ++ZoneIndex) {
231 0 : auto &thisZone = state.dataHeatBal->Zone(ZoneIndex);
232 0 : if (state.dataMundtSimMgr->ZoneData(ZoneIndex).MundtZoneIndex == MundtZoneIndex) {
233 : // get surface data
234 0 : for (int surfNum = 1; surfNum <= state.dataMundtSimMgr->ZoneData(ZoneIndex).NumOfSurfs; ++surfNum) {
235 0 : state.dataMundtSimMgr->MundtAirSurf(surfNum, MundtZoneIndex).Area =
236 0 : state.dataSurface->Surface(state.dataMundtSimMgr->ZoneData(ZoneIndex).HBsurfaceIndexes(surfNum)).Area;
237 : }
238 :
239 : // get air node data
240 0 : RoomNodesCount = 0;
241 0 : FloorSurfCount = 0;
242 0 : for (NodeNum = 1; NodeNum <= state.dataRoomAir->TotNumOfZoneAirNodes(ZoneIndex); ++NodeNum) {
243 :
244 0 : state.dataMundtSimMgr->LineNode(NodeNum, MundtZoneIndex)
245 0 : .SurfMask.allocate(state.dataMundtSimMgr->ZoneData(ZoneIndex).NumOfSurfs);
246 :
247 0 : if (NodeNum == 1) {
248 0 : AirNodeBeginNum = NodeNum;
249 : }
250 :
251 : // error check for debugging
252 0 : if (AirNodeBeginNum > state.dataRoomAir->TotNumOfAirNodes) {
253 0 : ShowFatalError(state, "An array bound exceeded. Error in InitMundtModel subroutine of MundtSimMgr.");
254 : }
255 :
256 0 : AirNodeFoundFlag = false;
257 0 : for (AirNodeNum = AirNodeBeginNum; AirNodeNum <= state.dataRoomAir->TotNumOfAirNodes; ++AirNodeNum) {
258 0 : if (Util::SameString(state.dataRoomAir->AirNode(AirNodeNum).ZoneName, thisZone.Name)) {
259 0 : state.dataMundtSimMgr->LineNode(NodeNum, MundtZoneIndex).ClassType = state.dataRoomAir->AirNode(AirNodeNum).ClassType;
260 0 : state.dataMundtSimMgr->LineNode(NodeNum, MundtZoneIndex).AirNodeName = state.dataRoomAir->AirNode(AirNodeNum).Name;
261 0 : state.dataMundtSimMgr->LineNode(NodeNum, MundtZoneIndex).Height = state.dataRoomAir->AirNode(AirNodeNum).Height;
262 0 : state.dataMundtSimMgr->LineNode(NodeNum, MundtZoneIndex).SurfMask = state.dataRoomAir->AirNode(AirNodeNum).SurfMask;
263 0 : SetupOutputVariable(state,
264 : "Room Air Node Air Temperature",
265 : Constant::Units::C,
266 0 : state.dataMundtSimMgr->LineNode(NodeNum, MundtZoneIndex).Temp,
267 : OutputProcessor::TimeStepType::System,
268 : OutputProcessor::StoreType::Average,
269 0 : state.dataMundtSimMgr->LineNode(NodeNum, MundtZoneIndex).AirNodeName);
270 :
271 0 : AirNodeBeginNum = AirNodeNum + 1;
272 0 : AirNodeFoundFlag = true;
273 :
274 0 : break;
275 : }
276 : }
277 :
278 : // error check for debugging
279 0 : if (!AirNodeFoundFlag) {
280 0 : ShowSevereError(state, format("InitMundtModel: Air Node in Zone=\"{}\" is not found.", thisZone.Name));
281 0 : ErrorsFound = true;
282 0 : continue;
283 : }
284 :
285 : // count air nodes connected to walls in each zone
286 0 : if (state.dataMundtSimMgr->LineNode(NodeNum, MundtZoneIndex).ClassType == RoomAir::AirNodeType::Mundt) {
287 0 : ++RoomNodesCount;
288 : }
289 :
290 : // count floors in each zone
291 0 : if (state.dataMundtSimMgr->LineNode(NodeNum, MundtZoneIndex).ClassType == RoomAir::AirNodeType::Floor) {
292 0 : FloorSurfCount += count(state.dataMundtSimMgr->LineNode(NodeNum, MundtZoneIndex).SurfMask);
293 : }
294 : }
295 : // got data for this zone so exit the zone loop
296 0 : if (AirNodeFoundFlag) break;
297 : }
298 : }
299 :
300 0 : MaxNumOfRoomNodes = max(MaxNumOfRoomNodes, RoomNodesCount);
301 0 : MaxNumOfFloorSurfs = max(MaxNumOfFloorSurfs, FloorSurfCount);
302 : }
303 :
304 0 : if (ErrorsFound) ShowFatalError(state, "InitMundtModel: Preceding condition(s) cause termination.");
305 :
306 : // allocate arrays
307 0 : state.dataMundtSimMgr->RoomNodeIDs.allocate(MaxNumOfRoomNodes);
308 0 : state.dataMundtSimMgr->FloorSurfSetIDs.allocate(MaxNumOfFloorSurfs);
309 0 : state.dataMundtSimMgr->FloorSurf.allocate(MaxNumOfFloorSurfs);
310 0 : }
311 :
312 : //*****************************************************************************************
313 :
314 0 : void GetSurfHBDataForDispVent1Node(EnergyPlusData &state, int const ZoneNum) // index number for the specified zone
315 : {
316 :
317 : // SUBROUTINE INFORMATION:
318 : // AUTHOR Weixiu Kong
319 : // DATE WRITTEN April 2003
320 : // MODIFIED July 2003 (CC)
321 : // February 2004, fix allocate-deallocate problem (CC)
322 :
323 : // PURPOSE OF THIS SUBROUTINE:
324 : // map data from surface domain to air domain for each particular zone
325 :
326 : using Psychrometrics::PsyCpAirFnW;
327 : using Psychrometrics::PsyRhoAirFnPbTdbW;
328 : using Psychrometrics::PsyWFnTdpPb;
329 :
330 : Real64 CpAir; // specific heat
331 : Real64 SumSysMCp; // zone sum of air system MassFlowRate*Cp
332 : Real64 SumSysMCpT; // zone sum of air system MassFlowRate*Cp*T
333 : Real64 MassFlowRate; // mass flowrate
334 : Real64 NodeTemp; // node temperature
335 : int ZoneNode; // index number for specified zone node
336 : Real64 ZoneMassFlowRate; // zone mass flowrate
337 : int ZoneEquipConfigNum; // index number for zone equipment configuration
338 : Real64 ZoneMult; // total zone multiplier
339 : Real64 RetAirConvGain;
340 :
341 0 : auto const &Zone(state.dataHeatBal->Zone);
342 :
343 : // determine ZoneEquipConfigNum for this zone
344 0 : ZoneEquipConfigNum = ZoneNum;
345 : // check whether this zone is a controlled zone or not
346 0 : if (!Zone(ZoneNum).IsControlled) {
347 0 : ShowFatalError(state, format("Zones must be controlled for Mundt air model. No system serves zone {}", Zone(ZoneNum).Name));
348 0 : return;
349 : }
350 :
351 : // determine information required by Mundt model
352 0 : state.dataMundtSimMgr->ZoneHeight = Zone(ZoneNum).CeilingHeight;
353 0 : state.dataMundtSimMgr->ZoneFloorArea = Zone(ZoneNum).FloorArea;
354 0 : ZoneMult = Zone(ZoneNum).Multiplier * Zone(ZoneNum).ListMultiplier;
355 :
356 : // supply air flowrate is the same as zone air flowrate
357 0 : ZoneNode = Zone(ZoneNum).SystemZoneNodeNumber;
358 0 : state.dataMundtSimMgr->ZoneAirDensity =
359 0 : PsyRhoAirFnPbTdbW(state,
360 0 : state.dataEnvrn->OutBaroPress,
361 0 : state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).MAT,
362 0 : PsyWFnTdpPb(state, state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).MAT, state.dataEnvrn->OutBaroPress));
363 0 : ZoneMassFlowRate = state.dataLoopNodes->Node(ZoneNode).MassFlowRate;
364 0 : state.dataMundtSimMgr->SupplyAirVolumeRate = ZoneMassFlowRate / state.dataMundtSimMgr->ZoneAirDensity;
365 0 : auto &thisZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum);
366 0 : if (ZoneMassFlowRate <= 0.0001) {
367 : // system is off
368 0 : state.dataMundtSimMgr->QsysCoolTot = 0.0;
369 : } else {
370 : // determine supply air conditions
371 0 : SumSysMCp = 0.0;
372 0 : SumSysMCpT = 0.0;
373 0 : for (int NodeNum = 1; NodeNum <= state.dataZoneEquip->ZoneEquipConfig(ZoneEquipConfigNum).NumInletNodes; ++NodeNum) {
374 0 : NodeTemp = state.dataLoopNodes->Node(state.dataZoneEquip->ZoneEquipConfig(ZoneEquipConfigNum).InletNode(NodeNum)).Temp;
375 0 : MassFlowRate = state.dataLoopNodes->Node(state.dataZoneEquip->ZoneEquipConfig(ZoneEquipConfigNum).InletNode(NodeNum)).MassFlowRate;
376 0 : CpAir = PsyCpAirFnW(thisZoneHB.airHumRat);
377 0 : SumSysMCp += MassFlowRate * CpAir;
378 0 : SumSysMCpT += MassFlowRate * CpAir * NodeTemp;
379 : }
380 : // prevent dividing by zero due to zero supply air flow rate
381 0 : if (SumSysMCp <= 0.0) {
382 0 : state.dataMundtSimMgr->SupplyAirTemp =
383 0 : state.dataLoopNodes->Node(state.dataZoneEquip->ZoneEquipConfig(ZoneEquipConfigNum).InletNode(1)).Temp;
384 : } else {
385 : // a weighted average of the inlet temperatures
386 0 : state.dataMundtSimMgr->SupplyAirTemp = SumSysMCpT / SumSysMCp;
387 : }
388 : // determine cooling load
389 0 : CpAir = PsyCpAirFnW(thisZoneHB.airHumRat);
390 0 : state.dataMundtSimMgr->QsysCoolTot =
391 0 : -(SumSysMCpT - ZoneMassFlowRate * CpAir * state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).MAT);
392 : }
393 : // determine heat gains
394 0 : state.dataMundtSimMgr->ConvIntGain = InternalHeatGains::zoneSumAllInternalConvectionGains(state, ZoneNum);
395 0 : state.dataMundtSimMgr->ConvIntGain += state.dataHeatBalFanSys->SumConvHTRadSys(ZoneNum) + state.dataHeatBalFanSys->SumConvPool(ZoneNum) +
396 0 : thisZoneHB.SysDepZoneLoadsLagged + thisZoneHB.NonAirSystemResponse / ZoneMult;
397 :
398 : // Add heat to return air if zonal system (no return air) or cycling system (return air frequently very
399 : // low or zero)
400 0 : if (Zone(ZoneNum).NoHeatToReturnAir) {
401 0 : RetAirConvGain = InternalHeatGains::zoneSumAllReturnAirConvectionGains(state, ZoneNum, 0);
402 0 : state.dataMundtSimMgr->ConvIntGain += RetAirConvGain;
403 : }
404 :
405 0 : state.dataMundtSimMgr->QventCool =
406 0 : -thisZoneHB.MCPI * (Zone(ZoneNum).OutDryBulbTemp - state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).MAT);
407 :
408 : // get surface data
409 0 : for (int SurfNum = 1; SurfNum <= state.dataMundtSimMgr->ZoneData(ZoneNum).NumOfSurfs; ++SurfNum) {
410 0 : state.dataMundtSimMgr->MundtAirSurf(SurfNum, state.dataMundtSimMgr->MundtZoneNum).Temp =
411 0 : state.dataHeatBalSurf->SurfTempIn(state.dataMundtSimMgr->ZoneData(ZoneNum).HBsurfaceIndexes(SurfNum));
412 0 : state.dataMundtSimMgr->MundtAirSurf(SurfNum, state.dataMundtSimMgr->MundtZoneNum).Hc =
413 0 : state.dataHeatBalSurf->SurfHConvInt(state.dataMundtSimMgr->ZoneData(ZoneNum).HBsurfaceIndexes(SurfNum));
414 : }
415 : }
416 :
417 : //*****************************************************************************************
418 :
419 0 : void SetupDispVent1Node(EnergyPlusData &state,
420 : int const ZoneNum, // index number for the specified zone
421 : bool &ErrorsFound // true if problems setting up model
422 : )
423 : {
424 :
425 : // SUBROUTINE INFORMATION:
426 : // AUTHOR Brent Griffith
427 : // DATE WRITTEN Febraury 2002
428 : // RE-ENGINEERED June 2003, EnergyPlus Implementation (CC)
429 : // MODIFIED February 2004, fix allocate-deallocate problem (CC)
430 :
431 : // PURPOSE OF THIS SUBROUTINE:
432 : // Subroutine must be called once before main model calculation
433 : // need to pass some zone characteristics only once
434 : // initializes module level variables, collect info from Air Data Manager
435 :
436 : // METHODOLOGY EMPLOYED:
437 : // na
438 :
439 : // REFERENCES:
440 : // na
441 :
442 : // Locals
443 : // SUBROUTINE ARGUMENT DEFINITIONS:
444 :
445 : // SUBROUTINE PARAMETER DEFINITIONS:
446 : // na
447 :
448 : // INTERFACE BLOCK SPECIFICATIONS:
449 : // na
450 :
451 : // DERIVED TYPE DEFINITIONS:
452 : // na
453 :
454 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
455 : int NodeNum; // index for air nodes
456 :
457 : // set up air node ID
458 0 : state.dataMundtSimMgr->NumRoomNodes = 0;
459 0 : for (NodeNum = 1; NodeNum <= state.dataRoomAir->TotNumOfZoneAirNodes(ZoneNum); ++NodeNum) {
460 0 : switch (state.dataMundtSimMgr->LineNode(NodeNum, state.dataMundtSimMgr->MundtZoneNum).ClassType) {
461 0 : case RoomAir::AirNodeType::Inlet: { // inlet
462 0 : state.dataMundtSimMgr->SupplyNodeID = NodeNum;
463 0 : } break;
464 0 : case RoomAir::AirNodeType::Floor: { // floor
465 0 : state.dataMundtSimMgr->MundtFootAirID = NodeNum;
466 0 : } break;
467 0 : case RoomAir::AirNodeType::Control: { // thermostat
468 0 : state.dataMundtSimMgr->TstatNodeID = NodeNum;
469 0 : } break;
470 0 : case RoomAir::AirNodeType::Ceiling: { // ceiling
471 0 : state.dataMundtSimMgr->MundtCeilAirID = NodeNum;
472 0 : } break;
473 0 : case RoomAir::AirNodeType::Mundt: { // wall
474 0 : ++state.dataMundtSimMgr->NumRoomNodes;
475 0 : state.dataMundtSimMgr->RoomNodeIDs(state.dataMundtSimMgr->NumRoomNodes) = NodeNum;
476 0 : } break;
477 0 : case RoomAir::AirNodeType::Return: { // return
478 0 : state.dataMundtSimMgr->ReturnNodeID = NodeNum;
479 0 : } break;
480 0 : default: {
481 0 : ShowSevereError(state, "SetupMundtModel: Non-Standard Type of Air Node for Mundt Model");
482 0 : ErrorsFound = true;
483 0 : } break;
484 : }
485 : }
486 :
487 : // get number of floors in the zone and setup FloorSurfSetIDs
488 0 : if (state.dataMundtSimMgr->MundtFootAirID > 0) {
489 0 : state.dataMundtSimMgr->NumFloorSurfs =
490 0 : count(state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->MundtFootAirID, state.dataMundtSimMgr->MundtZoneNum).SurfMask);
491 0 : state.dataMundtSimMgr->FloorSurfSetIDs =
492 0 : pack(state.dataMundtSimMgr->ID1dSurf,
493 0 : state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->MundtFootAirID, state.dataMundtSimMgr->MundtZoneNum).SurfMask);
494 : // initialize floor surface data (a must since NumFloorSurfs is varied among zones)
495 0 : for (auto &e : state.dataMundtSimMgr->FloorSurf) {
496 0 : e.Temp = 25.0;
497 0 : e.Hc = 0.0;
498 0 : e.Area = 0.0;
499 : }
500 : // get floor surface data
501 0 : for (int SurfNum = 1; SurfNum <= state.dataMundtSimMgr->NumFloorSurfs; ++SurfNum) {
502 0 : state.dataMundtSimMgr->FloorSurf(SurfNum).Temp =
503 0 : state.dataMundtSimMgr->MundtAirSurf(state.dataMundtSimMgr->FloorSurfSetIDs(SurfNum), state.dataMundtSimMgr->MundtZoneNum).Temp;
504 0 : state.dataMundtSimMgr->FloorSurf(SurfNum).Hc =
505 0 : state.dataMundtSimMgr->MundtAirSurf(state.dataMundtSimMgr->FloorSurfSetIDs(SurfNum), state.dataMundtSimMgr->MundtZoneNum).Hc;
506 0 : state.dataMundtSimMgr->FloorSurf(SurfNum).Area =
507 0 : state.dataMundtSimMgr->MundtAirSurf(state.dataMundtSimMgr->FloorSurfSetIDs(SurfNum), state.dataMundtSimMgr->MundtZoneNum).Area;
508 : }
509 : } else {
510 0 : ShowSevereError(state, format("SetupMundtModel: Mundt model has no FloorAirNode, Zone={}", state.dataHeatBal->Zone(ZoneNum).Name));
511 0 : ErrorsFound = true;
512 : }
513 0 : }
514 :
515 : //*****************************************************************************************
516 :
517 0 : void CalcDispVent1Node(EnergyPlusData &state, int const ZoneNum) // index number for the specified zone
518 : {
519 :
520 : // SUBROUTINE INFORMATION:
521 : // AUTHOR Brent Griffith
522 : // DATE WRITTEN September 2001
523 : // RE-ENGINEERED July 2003, EnergyPlus Implementation (CC)
524 : // MODIFIED February 2004, fix allocate-deallocate problem (CC)
525 :
526 : // PURPOSE OF THIS SUBROUTINE:
527 : // Compute the simplified version of Mundt and store results in Air data Manager
528 : // argument passing is plentiful but are IN and nothing out.
529 : // these variables are scaler conditions at current HB day,timestep, and iteration
530 : // This subroutine is USE'ed by heat balance driver (top level module)
531 :
532 : // METHODOLOGY EMPLOYED:
533 : // apply Mundt's simple model for delta Temp head-foot and update values in Air data manager.
534 :
535 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
536 : Real64 TAirFoot; // air temperature at the floor
537 : Real64 TAirCeil; // air temperature at the ceiling
538 : Real64 TLeaving; // air temperature leaving zone (= return air temp)
539 : Real64 TControlPoint; // air temperature at thermostat
540 : Real64 Slope; // vertical air temperature gradient (slope) from Mundt equations
541 : Real64 QequipConvFloor; // convective gain at the floor due to internal heat sources
542 : Real64 QSensInfilFloor; // convective gain at the floor due to infiltration
543 : Real64 FloorSumHAT; // sum of hci*area*temp at the floor
544 : Real64 FloorSumHA; // sum of hci*area at the floor
545 : Real64 TThisNode; // dummy variable for air node temp
546 : int NodeNum; // index for air nodes
547 : int SurfNum; // index for surfaces
548 : int SurfCounted; // number of surfaces assciated with an air node
549 :
550 : // apply floor splits
551 0 : QequipConvFloor = state.dataRoomAir->ConvectiveFloorSplit(ZoneNum) * state.dataMundtSimMgr->ConvIntGain;
552 0 : QSensInfilFloor = -state.dataRoomAir->InfiltratFloorSplit(ZoneNum) * state.dataMundtSimMgr->QventCool;
553 :
554 : // Begin computations for Mundt model
555 :
556 : // do summations for floor surfaces of this zone
557 0 : FloorSumHAT = 0.0;
558 0 : FloorSumHA = 0.0;
559 0 : for (auto const &s : state.dataMundtSimMgr->FloorSurf) {
560 0 : FloorSumHAT += s.Area * s.Hc * s.Temp;
561 0 : FloorSumHA += s.Area * s.Hc;
562 : }
563 :
564 : // Eq 2.2 in ASHRAE RP 1222 Final report
565 0 : TAirFoot =
566 0 : ((state.dataMundtSimMgr->ZoneAirDensity * CpAir * state.dataMundtSimMgr->SupplyAirVolumeRate * state.dataMundtSimMgr->SupplyAirTemp) +
567 0 : (FloorSumHAT) + QequipConvFloor + QSensInfilFloor) /
568 0 : ((state.dataMundtSimMgr->ZoneAirDensity * CpAir * state.dataMundtSimMgr->SupplyAirVolumeRate) + (FloorSumHA));
569 :
570 : // prevent dividing by zero due to zero cooling load (or zero supply air flow rate)
571 0 : if (state.dataMundtSimMgr->QsysCoolTot <= 0.0) {
572 0 : TLeaving = state.dataMundtSimMgr->SupplyAirTemp;
573 : } else {
574 : // Eq 2.3 in ASHRAE RP 1222 Final report
575 0 : TLeaving =
576 0 : (state.dataMundtSimMgr->QsysCoolTot / (state.dataMundtSimMgr->ZoneAirDensity * CpAir * state.dataMundtSimMgr->SupplyAirVolumeRate)) +
577 0 : state.dataMundtSimMgr->SupplyAirTemp;
578 : }
579 :
580 : // Eq 2.4 in ASHRAE RP 1222 Final report
581 0 : Slope = (TLeaving - TAirFoot) /
582 0 : (state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->ReturnNodeID, state.dataMundtSimMgr->MundtZoneNum).Height -
583 0 : state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->MundtFootAirID, state.dataMundtSimMgr->MundtZoneNum).Height);
584 : // check slope
585 0 : if (Slope > MaxSlope) {
586 0 : Slope = MaxSlope;
587 0 : TAirFoot = TLeaving -
588 0 : (Slope * (state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->ReturnNodeID, state.dataMundtSimMgr->MundtZoneNum).Height -
589 0 : state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->MundtFootAirID, state.dataMundtSimMgr->MundtZoneNum).Height));
590 : }
591 0 : if (Slope < MinSlope) { // pretty much vertical
592 0 : Slope = MinSlope;
593 0 : TAirFoot = TLeaving;
594 : }
595 :
596 : // Eq 2.4 in ASHRAE RP 1222 Final report
597 0 : TAirCeil =
598 0 : TLeaving - (Slope * (state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->ReturnNodeID, state.dataMundtSimMgr->MundtZoneNum).Height -
599 0 : state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->MundtCeilAirID, state.dataMundtSimMgr->MundtZoneNum).Height));
600 :
601 0 : TControlPoint =
602 0 : TLeaving - (Slope * (state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->ReturnNodeID, state.dataMundtSimMgr->MundtZoneNum).Height -
603 0 : state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->TstatNodeID, state.dataMundtSimMgr->MundtZoneNum).Height));
604 :
605 : // determine air node temperatures in this zone
606 0 : SetNodeResult(state, state.dataMundtSimMgr->SupplyNodeID, state.dataMundtSimMgr->SupplyAirTemp);
607 0 : SetNodeResult(state, state.dataMundtSimMgr->ReturnNodeID, TLeaving);
608 0 : SetNodeResult(state, state.dataMundtSimMgr->MundtCeilAirID, TAirCeil);
609 0 : SetNodeResult(state, state.dataMundtSimMgr->MundtFootAirID, TAirFoot);
610 0 : SetNodeResult(state, state.dataMundtSimMgr->TstatNodeID, TControlPoint);
611 :
612 0 : for (SurfNum = 1; SurfNum <= state.dataMundtSimMgr->NumFloorSurfs; ++SurfNum) {
613 0 : SetSurfTmeanAir(state, state.dataMundtSimMgr->FloorSurfSetIDs(SurfNum), TAirFoot);
614 : }
615 :
616 0 : SurfCounted = count(state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->MundtCeilAirID, state.dataMundtSimMgr->MundtZoneNum).SurfMask);
617 0 : state.dataMundtSimMgr->TheseSurfIDs =
618 0 : pack(state.dataMundtSimMgr->ID1dSurf,
619 0 : state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->MundtCeilAirID, state.dataMundtSimMgr->MundtZoneNum).SurfMask);
620 0 : for (SurfNum = 1; SurfNum <= SurfCounted; ++SurfNum) {
621 0 : SetSurfTmeanAir(state, state.dataMundtSimMgr->TheseSurfIDs(SurfNum), TAirCeil);
622 : }
623 :
624 0 : for (NodeNum = 1; NodeNum <= state.dataMundtSimMgr->NumRoomNodes; ++NodeNum) {
625 0 : TThisNode =
626 : TLeaving -
627 0 : (Slope * (state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->ReturnNodeID, state.dataMundtSimMgr->MundtZoneNum).Height -
628 0 : state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->RoomNodeIDs(NodeNum), state.dataMundtSimMgr->MundtZoneNum).Height));
629 0 : SetNodeResult(state, state.dataMundtSimMgr->RoomNodeIDs(NodeNum), TThisNode);
630 0 : SurfCounted =
631 0 : count(state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->RoomNodeIDs(NodeNum), state.dataMundtSimMgr->MundtZoneNum).SurfMask);
632 0 : state.dataMundtSimMgr->TheseSurfIDs =
633 0 : pack(state.dataMundtSimMgr->ID1dSurf,
634 0 : state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->RoomNodeIDs(NodeNum), state.dataMundtSimMgr->MundtZoneNum).SurfMask);
635 0 : for (SurfNum = 1; SurfNum <= SurfCounted; ++SurfNum) {
636 0 : SetSurfTmeanAir(state, state.dataMundtSimMgr->TheseSurfIDs(SurfNum), TThisNode);
637 : }
638 : }
639 0 : }
640 :
641 : //*****************************************************************************************
642 :
643 0 : void SetNodeResult(EnergyPlusData &state,
644 : int const NodeID, // node ID
645 : Real64 const TempResult // temperature for the specified air node
646 : )
647 : {
648 :
649 : // SUBROUTINE INFORMATION:
650 : // AUTHOR Brent Griffith
651 : // DATE WRITTEN September 2002
652 : // RE-ENGINEERED April 2003, Weixiu Kong, EnergyPlus Implementation
653 : // MODIFIED February 2004, fix allocate-deallocate problem (CC)
654 :
655 : // PURPOSE OF THIS SUBROUTINE:
656 : // provide set routine for reporting results
657 : // to AirDataManager from air model
658 :
659 : // METHODOLOGY EMPLOYED:
660 : // na
661 :
662 : // REFERENCES:
663 : // na
664 :
665 : // USE STATEMENTS:
666 : // na
667 :
668 : // Locals
669 : // SUBROUTINE ARGUMENT DEFINITIONS:
670 :
671 : // SUBROUTINE PARAMETER DEFINITIONS:
672 : // na
673 :
674 : // INTERFACE BLOCK SPECIFICATIONS:
675 : // na
676 :
677 : // DERIVED TYPE DEFINITIONS:
678 : // na
679 :
680 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
681 : // na
682 :
683 0 : state.dataMundtSimMgr->LineNode(NodeID, state.dataMundtSimMgr->MundtZoneNum).Temp = TempResult;
684 0 : }
685 :
686 : //*****************************************************************************************
687 :
688 0 : void SetSurfTmeanAir(EnergyPlusData &state,
689 : int const SurfID, // surface ID
690 : Real64 const TeffAir // temperature of air node adjacent to the specified surface
691 : )
692 : {
693 :
694 : // SUBROUTINE INFORMATION:
695 : // AUTHOR Brent Griffith
696 : // DATE WRITTEN September 2002
697 : // RE-ENGINEERED April 2003, Wiexiu Kong, EnergyPlus Implementation
698 : // MODIFIED February 2004, fix allocate-deallocate problem (CC)
699 :
700 : // PURPOSE OF THIS SUBROUTINE:
701 : // provide set routine for air model prediction of
702 : // effective air for single surface
703 :
704 0 : state.dataMundtSimMgr->MundtAirSurf(SurfID, state.dataMundtSimMgr->MundtZoneNum).TMeanAir = TeffAir;
705 0 : }
706 :
707 : //*****************************************************************************************
708 :
709 0 : void SetSurfHBDataForDispVent1Node(EnergyPlusData &state, int const ZoneNum) // index number for the specified zone
710 : {
711 :
712 : // SUBROUTINE INFORMATION:
713 : // AUTHOR Chanvit Chantrasrisalai
714 : // DATE WRITTEN July 2003
715 : // MODIFIED February 2004, fix allocate-deallocate problem (CC)
716 : // RE-ENGINEERED na
717 :
718 : // PURPOSE OF THIS SUBROUTINE:
719 : // map data from air domain back to surface domain for each particular zone
720 :
721 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
722 : Real64 DeltaTemp; // dummy variable for temperature difference
723 :
724 : // get surface info
725 0 : int NumOfSurfs = state.dataMundtSimMgr->ZoneData(ZoneNum).NumOfSurfs;
726 :
727 0 : if ((state.dataMundtSimMgr->SupplyAirVolumeRate > 0.0001) &&
728 0 : (state.dataMundtSimMgr->QsysCoolTot > 0.0001)) { // Controlled zone when the system is on
729 :
730 0 : if (state.dataRoomAir->AirModel(ZoneNum).TempCoupleScheme == RoomAir::CouplingScheme::Direct) {
731 : // Use direct coupling scheme to report air temperatures back to surface/system domains
732 : // a) Bulk air temperatures -> TempEffBulkAir(SurfNum)
733 0 : for (int SurfNum = 1; SurfNum <= NumOfSurfs; ++SurfNum) {
734 0 : int hbSurfNum = state.dataMundtSimMgr->ZoneData(ZoneNum).HBsurfaceIndexes(SurfNum);
735 0 : state.dataHeatBal->SurfTempEffBulkAir(hbSurfNum) =
736 0 : state.dataMundtSimMgr->MundtAirSurf(SurfNum, state.dataMundtSimMgr->MundtZoneNum).TMeanAir;
737 : // set flag for reference air temperature
738 0 : state.dataSurface->SurfTAirRef(hbSurfNum) = DataSurfaces::RefAirTemp::AdjacentAirTemp;
739 0 : state.dataSurface->SurfTAirRefRpt(hbSurfNum) = DataSurfaces::SurfTAirRefReportVals[state.dataSurface->SurfTAirRef(hbSurfNum)];
740 : }
741 : // b) Average zone air temperature -> ZT(ZoneNum)
742 : // For Mundt model, average room air is the weighted value of floor and ceiling air temps
743 : // TRoomAverage = ( LineNode( MundtCeilAirID, MundtZoneNum ).Temp + LineNode( MundtFootAirID, MundtZoneNum ).Temp ) / 2;
744 : // ZT(ZoneNum) = TRoomAverage
745 : // c) Leaving-zone air temperature -> Node(ZoneNode)%Temp
746 0 : int ZoneNodeNum = state.dataHeatBal->Zone(ZoneNum).SystemZoneNodeNumber;
747 0 : state.dataLoopNodes->Node(ZoneNodeNum).Temp =
748 0 : state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->ReturnNodeID, state.dataMundtSimMgr->MundtZoneNum).Temp;
749 : // d) Thermostat air temperature -> TempTstatAir(ZoneNum)
750 0 : state.dataHeatBalFanSys->TempTstatAir(ZoneNum) =
751 0 : state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->TstatNodeID, state.dataMundtSimMgr->MundtZoneNum).Temp;
752 : } else {
753 : // Use indirect coupling scheme to report air temperatures back to surface/system domains
754 : // a) Bulk air temperatures -> TempEffBulkAir(SurfNum)
755 0 : for (int SurfNum = 1; SurfNum <= NumOfSurfs; ++SurfNum) {
756 0 : int hbSurfNum = state.dataMundtSimMgr->ZoneData(ZoneNum).HBsurfaceIndexes(SurfNum);
757 0 : DeltaTemp = state.dataMundtSimMgr->MundtAirSurf(SurfNum, state.dataMundtSimMgr->MundtZoneNum).TMeanAir -
758 0 : state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->TstatNodeID, state.dataMundtSimMgr->MundtZoneNum).Temp;
759 0 : state.dataHeatBal->SurfTempEffBulkAir(hbSurfNum) = state.dataHeatBalFanSys->zoneTstatSetpts(ZoneNum).setpt + DeltaTemp;
760 : // set flag for reference air temperature
761 0 : state.dataSurface->SurfTAirRef(hbSurfNum) = DataSurfaces::RefAirTemp::AdjacentAirTemp;
762 0 : state.dataSurface->SurfTAirRefRpt(hbSurfNum) = DataSurfaces::SurfTAirRefReportVals[state.dataSurface->SurfTAirRef(hbSurfNum)];
763 : }
764 : // b) Average zone air temperature -> ZT(ZoneNum)
765 : // For Mundt model, average room air is the weighted value of floor and ceiling air temps
766 : // TRoomAverage = ( LineNode( MundtCeilAirID, MundtZoneNum ).Temp + LineNode( MundtFootAirID, MundtZoneNum ).Temp ) / 2;
767 : // DeltaTemp = TRoomAverage - LineNode( TstatNodeID, MundtZoneNum ).Temp;
768 : // ZT(ZoneNum) = TempZoneThermostatSetPoint(ZoneNum) + DeltaTemp
769 : // c) Leaving-zone air temperature -> Node(ZoneNode)%Temp
770 0 : int ZoneNodeNum = state.dataHeatBal->Zone(ZoneNum).SystemZoneNodeNumber;
771 0 : DeltaTemp = state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->ReturnNodeID, state.dataMundtSimMgr->MundtZoneNum).Temp -
772 0 : state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->TstatNodeID, state.dataMundtSimMgr->MundtZoneNum).Temp;
773 0 : state.dataLoopNodes->Node(ZoneNodeNum).Temp = state.dataHeatBalFanSys->zoneTstatSetpts(ZoneNum).setpt + DeltaTemp;
774 : // d) Thermostat air temperature -> TempTstatAir(ZoneNum)
775 0 : state.dataHeatBalFanSys->TempTstatAir(ZoneNum) = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum)
776 0 : .ZT; // for indirect coupling, control air temp is equal to mean air temp?
777 : }
778 : // set flag to indicate that Mundt model is used for this zone at the present time
779 0 : state.dataRoomAir->AirModel(ZoneNum).SimAirModel = true;
780 : } else { // Controlled zone when the system is off --> Use the mixing model instead of the Mundt model
781 : // Bulk air temperatures -> TempEffBulkAir(SurfNum)
782 0 : for (int SurfNum = 1; SurfNum <= NumOfSurfs; ++SurfNum) {
783 0 : int hbSurfNum = state.dataMundtSimMgr->ZoneData(ZoneNum).HBsurfaceIndexes(SurfNum);
784 0 : state.dataHeatBal->SurfTempEffBulkAir(hbSurfNum) = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).MAT;
785 : // set flag for reference air temperature
786 0 : state.dataSurface->SurfTAirRef(hbSurfNum) = DataSurfaces::RefAirTemp::ZoneMeanAirTemp;
787 0 : state.dataSurface->SurfTAirRefRpt(hbSurfNum) = DataSurfaces::SurfTAirRefReportVals[state.dataSurface->SurfTAirRef(hbSurfNum)];
788 : }
789 : // set flag to indicate that Mundt model is NOT used for this zone at the present time
790 0 : state.dataRoomAir->AirModel(ZoneNum).SimAirModel = false;
791 : }
792 0 : }
793 :
794 : //*****************************************************************************************
795 :
796 : } // namespace RoomAir
797 :
798 : } // namespace EnergyPlus
|