Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2025, The Board of Trustees of the University of Illinois,
2 : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
3 : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
4 : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
5 : // contributors. All rights reserved.
6 : //
7 : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
8 : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
9 : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
10 : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
11 : // derivative works, and perform publicly and display publicly, and to permit others to do so.
12 : //
13 : // Redistribution and use in source and binary forms, with or without modification, are permitted
14 : // provided that the following conditions are met:
15 : //
16 : // (1) Redistributions of source code must retain the above copyright notice, this list of
17 : // conditions and the following disclaimer.
18 : //
19 : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
20 : // conditions and the following disclaimer in the documentation and/or other materials
21 : // provided with the distribution.
22 : //
23 : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
24 : // the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
25 : // used to endorse or promote products derived from this software without specific prior
26 : // written permission.
27 : //
28 : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
29 : // without changes from the version obtained under this License, or (ii) Licensee makes a
30 : // reference solely to the software portion of its product, Licensee must refer to the
31 : // software as "EnergyPlus version X" software, where "X" is the version number Licensee
32 : // obtained under this License and may not use a different name for the software. Except as
33 : // specifically required in this Section (4), Licensee shall not use in a company name, a
34 : // product name, in advertising, publicity, or other promotional activities any name, trade
35 : // name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
36 : // similar designation, without the U.S. Department of Energy's prior written consent.
37 : //
38 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
39 : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
40 : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
41 : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43 : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
45 : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46 : // POSSIBILITY OF SUCH DAMAGE.
47 :
48 : // C++ Headers
49 : #include <cmath>
50 :
51 : // ObjexxFCL Headers
52 : #include <ObjexxFCL/Array.functions.hh>
53 :
54 : // EnergyPlus Headers
55 : #include <EnergyPlus/Autosizing/CoolingAirFlowSizing.hh>
56 : #include <EnergyPlus/Autosizing/CoolingCapacitySizing.hh>
57 : #include <EnergyPlus/Autosizing/HeatingAirFlowSizing.hh>
58 : #include <EnergyPlus/Autosizing/HeatingCapacitySizing.hh>
59 : #include <EnergyPlus/Autosizing/SystemAirFlowSizing.hh>
60 : #include <EnergyPlus/BranchNodeConnections.hh>
61 : #include <EnergyPlus/Construction.hh>
62 : #include <EnergyPlus/Data/EnergyPlusData.hh>
63 : #include <EnergyPlus/DataAirSystems.hh>
64 : #include <EnergyPlus/DataEnvironment.hh>
65 : #include <EnergyPlus/DataHVACGlobals.hh>
66 : #include <EnergyPlus/DataHeatBalFanSys.hh>
67 : #include <EnergyPlus/DataHeatBalSurface.hh>
68 : #include <EnergyPlus/DataHeatBalance.hh>
69 : #include <EnergyPlus/DataIPShortCuts.hh>
70 : #include <EnergyPlus/DataLoopNode.hh>
71 : #include <EnergyPlus/DataSizing.hh>
72 : #include <EnergyPlus/DataSurfaceLists.hh>
73 : #include <EnergyPlus/DataSurfaces.hh>
74 : #include <EnergyPlus/DataZoneEquipment.hh>
75 : #include <EnergyPlus/Fans.hh>
76 : #include <EnergyPlus/FluidProperties.hh>
77 : #include <EnergyPlus/General.hh>
78 : #include <EnergyPlus/GeneralRoutines.hh>
79 : #include <EnergyPlus/HVACHXAssistedCoolingCoil.hh>
80 : #include <EnergyPlus/HeatBalanceSurfaceManager.hh>
81 : #include <EnergyPlus/HeatingCoils.hh>
82 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
83 : #include <EnergyPlus/NodeInputManager.hh>
84 : #include <EnergyPlus/OutAirNodeManager.hh>
85 : #include <EnergyPlus/OutputProcessor.hh>
86 : #include <EnergyPlus/PlantUtilities.hh>
87 : #include <EnergyPlus/Psychrometrics.hh>
88 : #include <EnergyPlus/ScheduleManager.hh>
89 : #include <EnergyPlus/SteamCoils.hh>
90 : #include <EnergyPlus/UtilityRoutines.hh>
91 : #include <EnergyPlus/VentilatedSlab.hh>
92 : #include <EnergyPlus/WaterCoils.hh>
93 : #include <EnergyPlus/ZoneTempPredictorCorrector.hh>
94 :
95 : namespace EnergyPlus {
96 :
97 : namespace VentilatedSlab {
98 :
99 : // Module containing the routines dealing with the Ventilated Slab
100 :
101 : // MODULE INFORMATION:
102 : // AUTHOR Young Tae Chae, Rick Strand
103 : // DATE WRITTEN June 2008
104 :
105 : // PURPOSE OF THIS MODULE:
106 : // Simulate Ventilated Slab Systems.
107 :
108 : // METHODOLOGY EMPLOYED:
109 : // Systems are modeled as a collection of components: radiant panel, outside air mixer,
110 : // fan, heating coil and/or cooling coil plus an integrated control
111 : // algorithm that adjusts the hot or cold water flow to meet the setpoint
112 : // condition. Outside air mixing is handled locally as either fixed percent
113 : // or as attempting to meet a prescribed mixed air temperature.
114 :
115 : // REFERENCES:
116 : // ASHRAE Systems and Equipment Handbook (SI), 1996. pp. 31.1-31.3
117 : // Fred Buhl's fan coil module (FanCoilUnits.cc)
118 :
119 : std::string const cMO_VentilatedSlab = "ZoneHVAC:VentilatedSlab";
120 :
121 : // int constexpr NotOperating = 0; // Parameter for use with OperatingMode variable, set for no heating/cooling
122 : int constexpr HeatingMode = 1; // Parameter for use with OperatingMode variable, set for heating
123 : int constexpr CoolingMode = 2; // Parameter for use with OperatingMode variable, set for cooling
124 :
125 0 : void SimVentilatedSlab(EnergyPlusData &state,
126 : std::string const &CompName, // name of the fan coil unit
127 : int const ZoneNum, // number of zone being served
128 : bool const FirstHVACIteration, // TRUE if 1st HVAC simulation of system timestep
129 : Real64 &PowerMet, // Sensible power supplied (W)
130 : Real64 &LatOutputProvided, // Latent add/removal supplied by window AC (kg/s), dehumid = negative
131 : int &CompIndex)
132 : {
133 :
134 : // SUBROUTINE INFORMATION:
135 : // AUTHOR Rick Strand
136 : // DATE WRITTEN May 2000
137 : // MODIFIED Don Shirey, Aug 2009 (LatOutputProvided)
138 : // RE-ENGINEERED Rick Strand and Young T. Chae for Ventilated Slab (June, 2008)
139 :
140 : // PURPOSE OF THIS SUBROUTINE:
141 : // This is the main driver subroutine for the Ventilated Slab simulation.
142 :
143 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
144 : int Item; // index of ventilated slab being simulated
145 :
146 0 : if (state.dataVentilatedSlab->GetInputFlag) {
147 0 : GetVentilatedSlabInput(state);
148 0 : state.dataVentilatedSlab->GetInputFlag = false;
149 : }
150 :
151 : // Find the correct VentilatedSlabInput
152 0 : if (CompIndex == 0) {
153 0 : Item = Util::FindItemInList(CompName, state.dataVentilatedSlab->VentSlab);
154 0 : if (Item == 0) {
155 0 : ShowFatalError(state, format("SimVentilatedSlab: system not found={}", CompName));
156 : }
157 0 : CompIndex = Item;
158 : } else {
159 0 : Item = CompIndex;
160 0 : if (Item > state.dataVentilatedSlab->NumOfVentSlabs || Item < 1) {
161 0 : ShowFatalError(state,
162 0 : format("SimVentilatedSlab: Invalid CompIndex passed={}, Number of Systems={}, Entered System name={}",
163 : Item,
164 0 : state.dataVentilatedSlab->NumOfVentSlabs,
165 : CompName));
166 : }
167 0 : if (state.dataVentilatedSlab->CheckEquipName(Item)) {
168 0 : if (CompName != state.dataVentilatedSlab->VentSlab(Item).Name) {
169 0 : ShowFatalError(state,
170 0 : format("SimVentilatedSlab: Invalid CompIndex passed={}, System name={}, stored System Name for that index={}",
171 : Item,
172 : CompName,
173 0 : state.dataVentilatedSlab->VentSlab(Item).Name));
174 : }
175 0 : state.dataVentilatedSlab->CheckEquipName(Item) = false;
176 : }
177 : }
178 :
179 0 : state.dataSize->ZoneEqVentedSlab = true;
180 :
181 0 : InitVentilatedSlab(state, Item, ZoneNum, FirstHVACIteration);
182 :
183 0 : CalcVentilatedSlab(state, Item, ZoneNum, FirstHVACIteration, PowerMet, LatOutputProvided);
184 :
185 0 : UpdateVentilatedSlab(state, Item, FirstHVACIteration);
186 :
187 0 : ReportVentilatedSlab(state, Item);
188 :
189 0 : state.dataSize->ZoneEqVentedSlab = false;
190 0 : }
191 :
192 1 : void GetVentilatedSlabInput(EnergyPlusData &state)
193 : {
194 :
195 : // SUBROUTINE INFORMATION:
196 : // AUTHOR Young Tae Chae, Rick Strand
197 : // DATE WRITTEN June 2008
198 : // MODIFIED July 2012, Chandan Sharma - FSEC: Added zone sys avail managers
199 :
200 : // PURPOSE OF THIS SUBROUTINE:
201 : // This subroutine obtains the input for ventilated slab and sets
202 : // up the appropriate derived type.
203 :
204 : // METHODOLOGY EMPLOYED:
205 : // Standard EnergyPlus methodology.
206 :
207 : // REFERENCES:
208 : // Fred Buhl's fan coil module (FanCoilUnits.cc)
209 : // Kwang Ho Lee's Unit Ventilator Module (UnitVentilator.cc)
210 : // Rick Strand's Low temperature Radiant system (RadiantSystemLowTemp.cc)
211 :
212 : static constexpr std::string_view routineName = "GetVentilatedSlabInput";
213 : // Using/Aliasing
214 1 : auto &GetWaterCoilMaxFlowRate(WaterCoils::GetCoilMaxWaterFlowRate);
215 1 : auto &GetSteamCoilMaxFlowRate(SteamCoils::GetCoilMaxWaterFlowRate);
216 1 : auto &GetHXAssistedCoilFlowRate(HVACHXAssistedCoolingCoil::GetCoilMaxWaterFlowRate);
217 :
218 : // SUBROUTINE PARAMETER DEFINITIONS:
219 1 : constexpr std::array<std::string_view, static_cast<int>(VentilatedSlabConfig::Num)> VentilatedSlabConfigNamesUC{
220 : "SLABONLY", "SLABANDZONE", "SERIESSLABS"};
221 :
222 1 : constexpr std::array<std::string_view, static_cast<int>(ControlType::Num)> ControlTypeNamesUC{
223 : "MEANAIRTEMPERATURE",
224 : "MEANRADIANTTEMPERATURE",
225 : "OPERATIVETEMPERATURE",
226 : "OUTDOORDRYBULBTEMPERATURE",
227 : "OUTDOORWETBULBTEMPERATURE",
228 : "SURFACETEMPERATURE",
229 : "ZONEAIRDEWPOINTTEMPERATURE",
230 : };
231 :
232 3 : static std::string const CurrentModuleObject("ZoneHVAC:VentilatedSlab");
233 :
234 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
235 1 : bool ErrorsFound(false); // Set to true if errors in input, fatal at end of routine
236 : int IOStatus; // Used in GetObjectItem
237 : bool IsNotOK; // TRUE if there was a problem with a list name
238 : int NumAlphas; // Number of Alphas for each GetObjectItem call
239 : int NumArgs; // Unused variable that is part of a subroutine call
240 : int NumNumbers; // Number of Numbers for each GetObjectItem call
241 : int Item; // Item to be "gotten"
242 : int BaseNum; // Temporary number for creating RadiantSystemTypes structure
243 : bool errFlag; // interim error flag
244 : int SurfNum; // DO loop counter for surfaces
245 : bool IsValid; // Set for outside air node check
246 1 : Array1D_string cAlphaArgs; // Alpha input items for object
247 1 : Array1D_string cAlphaFields; // Alpha field names
248 1 : Array1D_string cNumericFields; // Numeric field names
249 1 : Array1D<Real64> rNumericArgs; // Numeric input items for object
250 1 : Array1D_bool lAlphaBlanks; // Logical array, alpha field input BLANK = .TRUE.
251 1 : Array1D_bool lNumericBlanks; // Logical array, numeric field input BLANK = .TRUE.
252 : bool SteamMessageNeeded;
253 :
254 1 : constexpr std::array<std::string_view, static_cast<int>(OutsideAirControlType::Num)> OutsideAirControlTypeNamesUC{
255 : "VARIABLEPERCENT", "FIXEDTEMPERATURE", "FIXEDAMOUNT"};
256 1 : constexpr std::array<std::string_view, static_cast<int>(CoilType::Num)> CoilTypeNamesUC{"NONE", "HEATING", "COOLING", "HEATINGANDCOOLING"};
257 :
258 1 : constexpr std::array<std::string_view, static_cast<int>(HeatingCoilType::Num)> HeatingCoilTypeNamesUC{
259 : "COIL:HEATING:ELECTRIC", "COIL:HEATING:FUEL", "COIL:HEATING:WATER", "COIL:HEATING:STEAM"};
260 1 : constexpr std::array<std::string_view, static_cast<int>(CoolingCoilType::Num)> CoolingCoilTypeNamesUC{
261 : "COIL:COOLING:WATER", "COIL:COOLING:WATER:DETAILEDGEOMETRY", "COILSYSTEM:COOLING:WATER:HEATEXCHANGERASSISTED"};
262 :
263 : // Figure out how many Ventilated Slab Systems there are in the input file
264 :
265 1 : SteamMessageNeeded = true;
266 1 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, NumArgs, NumAlphas, NumNumbers);
267 1 : cAlphaArgs.allocate(NumAlphas);
268 1 : cAlphaFields.allocate(NumAlphas);
269 1 : cNumericFields.allocate(NumNumbers);
270 1 : rNumericArgs.dimension(NumNumbers, 0.0);
271 1 : lAlphaBlanks.dimension(NumAlphas, true);
272 1 : lNumericBlanks.dimension(NumNumbers, true);
273 :
274 : // make sure data is gotten for surface lists
275 1 : BaseNum = DataSurfaceLists::GetNumberOfSurfListVentSlab(state);
276 :
277 1 : state.dataVentilatedSlab->NumOfVentSlabs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
278 : // Allocate the local derived type and do one-time initializations for all parts of it
279 :
280 1 : state.dataVentilatedSlab->VentSlab.allocate(state.dataVentilatedSlab->NumOfVentSlabs);
281 1 : state.dataVentilatedSlab->CheckEquipName.dimension(state.dataVentilatedSlab->NumOfVentSlabs, true);
282 1 : state.dataVentilatedSlab->VentSlabNumericFields.allocate(state.dataVentilatedSlab->NumOfVentSlabs);
283 :
284 3 : for (Item = 1; Item <= state.dataVentilatedSlab->NumOfVentSlabs;
285 : ++Item) { // Begin looping over the entire ventilated slab systems found in the input file...
286 :
287 4 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
288 : CurrentModuleObject,
289 : Item,
290 2 : state.dataIPShortCut->cAlphaArgs,
291 : NumAlphas,
292 2 : state.dataIPShortCut->rNumericArgs,
293 : NumNumbers,
294 : IOStatus,
295 : lNumericBlanks,
296 : lAlphaBlanks,
297 : cAlphaFields,
298 : cNumericFields);
299 :
300 2 : ErrorObjectHeader eoh{routineName, CurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)};
301 :
302 2 : state.dataVentilatedSlab->VentSlabNumericFields(Item).FieldNames.allocate(NumNumbers);
303 2 : state.dataVentilatedSlab->VentSlabNumericFields(Item).FieldNames = cNumericFields;
304 2 : Util::IsNameEmpty(state, state.dataIPShortCut->cAlphaArgs(1), CurrentModuleObject, ErrorsFound);
305 2 : auto &ventSlab = state.dataVentilatedSlab->VentSlab(Item);
306 :
307 2 : ventSlab.Name = state.dataIPShortCut->cAlphaArgs(1);
308 2 : if (lAlphaBlanks(2)) {
309 0 : ventSlab.availSched = Sched::GetScheduleAlwaysOn(state);
310 2 : } else if ((ventSlab.availSched = Sched::GetSchedule(state, state.dataIPShortCut->cAlphaArgs(2))) == nullptr) {
311 0 : ShowSevereItemNotFound(state, eoh, cAlphaFields(2), state.dataIPShortCut->cAlphaArgs(2));
312 0 : ErrorsFound = true;
313 : }
314 :
315 2 : ventSlab.ZonePtr = Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(3), state.dataHeatBal->Zone);
316 2 : if (ventSlab.ZonePtr == 0) {
317 0 : if (lAlphaBlanks(3)) {
318 0 : ShowSevereError(
319 0 : state, format(R"({}="{}" invalid {} is required but input is blank.)", CurrentModuleObject, ventSlab.Name, cAlphaFields(3)));
320 : } else {
321 0 : ShowSevereError(state,
322 0 : format(R"({}="{}" invalid {}="{}" not found.)",
323 : CurrentModuleObject,
324 0 : ventSlab.Name,
325 : cAlphaFields(3),
326 0 : state.dataIPShortCut->cAlphaArgs(3)));
327 : }
328 0 : ErrorsFound = true;
329 : }
330 :
331 2 : ventSlab.SurfListName = state.dataIPShortCut->cAlphaArgs(4);
332 2 : int SurfListNum = 0;
333 : // IF (NumOfSlabLists > 0) SurfListNum = Util::FindItemInList(VentSlab(Item)%SurfListName, SlabList%Name, NumOfSlabLists)
334 2 : if (state.dataSurfLists->NumOfSurfListVentSlab > 0) {
335 2 : SurfListNum = Util::FindItemInList(ventSlab.SurfListName, state.dataSurfLists->SlabList);
336 : }
337 2 : if (SurfListNum > 0) { // Found a valid surface list
338 2 : ventSlab.NumOfSurfaces = state.dataSurfLists->SlabList(SurfListNum).NumOfSurfaces;
339 2 : ventSlab.ZName.allocate(ventSlab.NumOfSurfaces);
340 2 : ventSlab.ZPtr.allocate(ventSlab.NumOfSurfaces);
341 2 : ventSlab.SurfaceName.allocate(ventSlab.NumOfSurfaces);
342 2 : ventSlab.SurfacePtr.allocate(ventSlab.NumOfSurfaces);
343 2 : ventSlab.CDiameter.allocate(ventSlab.NumOfSurfaces);
344 2 : ventSlab.CLength.allocate(ventSlab.NumOfSurfaces);
345 2 : ventSlab.CNumbers.allocate(ventSlab.NumOfSurfaces);
346 2 : ventSlab.SlabIn.allocate(ventSlab.NumOfSurfaces);
347 2 : ventSlab.SlabOut.allocate(ventSlab.NumOfSurfaces);
348 :
349 2 : state.dataVentilatedSlab->MaxCloNumOfSurfaces = max(state.dataVentilatedSlab->MaxCloNumOfSurfaces, ventSlab.NumOfSurfaces);
350 7 : for (SurfNum = 1; SurfNum <= state.dataSurfLists->SlabList(SurfListNum).NumOfSurfaces; ++SurfNum) {
351 5 : ventSlab.ZName(SurfNum) = state.dataSurfLists->SlabList(SurfListNum).ZoneName(SurfNum);
352 5 : ventSlab.ZPtr(SurfNum) = state.dataSurfLists->SlabList(SurfListNum).ZonePtr(SurfNum);
353 5 : ventSlab.SurfaceName(SurfNum) = state.dataSurfLists->SlabList(SurfListNum).SurfName(SurfNum);
354 5 : ventSlab.SurfacePtr(SurfNum) = state.dataSurfLists->SlabList(SurfListNum).SurfPtr(SurfNum);
355 5 : ventSlab.CDiameter(SurfNum) = state.dataSurfLists->SlabList(SurfListNum).CoreDiameter(SurfNum);
356 5 : ventSlab.CLength(SurfNum) = state.dataSurfLists->SlabList(SurfListNum).CoreLength(SurfNum);
357 5 : ventSlab.CNumbers(SurfNum) = state.dataSurfLists->SlabList(SurfListNum).CoreNumbers(SurfNum);
358 5 : ventSlab.SlabIn(SurfNum) = state.dataSurfLists->SlabList(SurfListNum).SlabInNodeName(SurfNum);
359 5 : ventSlab.SlabOut(SurfNum) = state.dataSurfLists->SlabList(SurfListNum).SlabOutNodeName(SurfNum);
360 5 : if (ventSlab.SurfacePtr(SurfNum) != 0) {
361 5 : state.dataSurface->surfIntConv(ventSlab.SurfacePtr(SurfNum)).hasActiveInIt = true;
362 : }
363 : }
364 :
365 : } else { // User entered a single surface name rather than a surface list
366 0 : ventSlab.NumOfSurfaces = 1;
367 0 : ventSlab.SurfacePtr.allocate(ventSlab.NumOfSurfaces);
368 0 : ventSlab.SurfaceName.allocate(ventSlab.NumOfSurfaces);
369 0 : ventSlab.SurfaceFlowFrac.allocate(ventSlab.NumOfSurfaces);
370 0 : state.dataVentilatedSlab->MaxCloNumOfSurfaces = max(state.dataVentilatedSlab->MaxCloNumOfSurfaces, ventSlab.NumOfSurfaces);
371 0 : ventSlab.SurfaceName(1) = ventSlab.SurfListName;
372 0 : ventSlab.SurfacePtr(1) = Util::FindItemInList(ventSlab.SurfaceName(1), state.dataSurface->Surface);
373 0 : ventSlab.SurfaceFlowFrac(1) = 1.0;
374 : // Error checking for single surfaces
375 0 : if (ventSlab.SurfacePtr(1) == 0) {
376 0 : ShowSevereError(state,
377 0 : format(R"({}="{}" invalid {}="{}" not found.)",
378 : CurrentModuleObject,
379 0 : ventSlab.Name,
380 : cAlphaFields(4),
381 0 : state.dataIPShortCut->cAlphaArgs(4)));
382 0 : ErrorsFound = true;
383 0 : } else if (state.dataSurface->SurfIsRadSurfOrVentSlabOrPool(ventSlab.SurfacePtr(1))) {
384 0 : ShowSevereError(state, format("{}=\"{}\", invalid Surface", CurrentModuleObject, ventSlab.Name));
385 0 : ShowContinueError(state,
386 0 : format("{}=\"{}\" has been used in another radiant system or ventilated slab.",
387 : cAlphaFields(4),
388 0 : state.dataIPShortCut->cAlphaArgs(4)));
389 0 : ErrorsFound = true;
390 : }
391 0 : if (ventSlab.SurfacePtr(1) != 0) {
392 0 : state.dataSurface->surfIntConv(ventSlab.SurfacePtr(1)).hasActiveInIt = true;
393 0 : state.dataSurface->SurfIsRadSurfOrVentSlabOrPool(ventSlab.SurfacePtr(1)) = true;
394 : }
395 : }
396 :
397 : // Error checking for zones and construction information
398 :
399 2 : if (SurfListNum > 0) {
400 :
401 7 : for (SurfNum = 1; SurfNum <= ventSlab.NumOfSurfaces; ++SurfNum) {
402 :
403 5 : int const ConstrNum = state.dataSurface->Surface(ventSlab.SurfacePtr(SurfNum)).Construction;
404 5 : auto const &thisConstruct = state.dataConstruction->Construct(ConstrNum);
405 5 : if (ventSlab.SurfacePtr(SurfNum) == 0) {
406 0 : continue; // invalid surface -- detected earlier
407 : }
408 5 : if (ventSlab.ZPtr(SurfNum) == 0) {
409 0 : continue; // invalid zone -- detected earlier
410 : }
411 5 : if (state.dataSurface->Surface(ventSlab.SurfacePtr(SurfNum)).Construction == 0) {
412 0 : continue; // invalid construction, detected earlier
413 : }
414 5 : if (!thisConstruct.SourceSinkPresent) {
415 0 : ShowSevereError(state,
416 0 : format("{}=\"{}\" invalid surface=\"{}\".",
417 : CurrentModuleObject,
418 0 : ventSlab.Name,
419 0 : state.dataSurface->Surface(ventSlab.SurfacePtr(SurfNum)).Name));
420 0 : ShowContinueError(state,
421 0 : format("Surface Construction does not have a source/sink, Construction name= \"{}\".", thisConstruct.Name));
422 0 : ErrorsFound = true;
423 : }
424 : }
425 : } else {
426 0 : for (SurfNum = 1; SurfNum <= ventSlab.NumOfSurfaces; ++SurfNum) {
427 0 : int const ConstrNum = state.dataSurface->Surface(ventSlab.SurfacePtr(SurfNum)).Construction;
428 0 : auto const &thisConstruct = state.dataConstruction->Construct(ConstrNum);
429 0 : if (ventSlab.SurfacePtr(SurfNum) == 0) {
430 0 : continue; // invalid surface -- detected earlier
431 : }
432 0 : if (ventSlab.ZonePtr == 0) {
433 0 : continue; // invalid zone -- detected earlier
434 : }
435 0 : if (state.dataSurface->Surface(ventSlab.SurfacePtr(SurfNum)).Zone != ventSlab.ZonePtr) {
436 0 : ShowSevereError(state,
437 0 : format("{}=\"{}\" invalid surface=\"{}\".",
438 : CurrentModuleObject,
439 0 : ventSlab.Name,
440 0 : state.dataSurface->Surface(ventSlab.SurfacePtr(SurfNum)).Name));
441 0 : ShowContinueError(state,
442 0 : format("Surface in Zone={} {} in Zone={}",
443 0 : state.dataHeatBal->Zone(state.dataSurface->Surface(ventSlab.SurfacePtr(SurfNum)).Zone).Name,
444 : CurrentModuleObject,
445 0 : state.dataIPShortCut->cAlphaArgs(3)));
446 0 : ErrorsFound = true;
447 : }
448 0 : if (state.dataSurface->Surface(ventSlab.SurfacePtr(SurfNum)).Construction == 0) {
449 0 : continue; // invalid construction, detected earlier
450 : }
451 0 : if (!thisConstruct.SourceSinkPresent) {
452 0 : ShowSevereError(state,
453 0 : format("{}=\"{}\" invalid surface=\"{}\".",
454 : CurrentModuleObject,
455 0 : ventSlab.Name,
456 0 : state.dataSurface->Surface(ventSlab.SurfacePtr(SurfNum)).Name));
457 0 : ShowContinueError(state,
458 0 : format("Surface Construction does not have a source/sink, Construction name= \"{}\".", thisConstruct.Name));
459 0 : ErrorsFound = true;
460 : }
461 : }
462 : }
463 :
464 2 : ventSlab.MaxAirVolFlow = state.dataIPShortCut->rNumericArgs(1);
465 :
466 : // Outside air information:
467 2 : ventSlab.MinOutAirVolFlow = state.dataIPShortCut->rNumericArgs(2);
468 2 : ventSlab.OutAirVolFlow = state.dataIPShortCut->rNumericArgs(3);
469 :
470 2 : ventSlab.outsideAirControlType =
471 2 : static_cast<OutsideAirControlType>(getEnumValue(OutsideAirControlTypeNamesUC, Util::makeUPPER(state.dataIPShortCut->cAlphaArgs(5))));
472 :
473 2 : switch (ventSlab.outsideAirControlType) {
474 :
475 2 : case OutsideAirControlType::VariablePercent: {
476 2 : if (lAlphaBlanks(7)) {
477 0 : ShowSevereEmptyField(state, eoh, state.dataIPShortCut->cAlphaFieldNames(7));
478 0 : ErrorsFound = true;
479 2 : } else if ((ventSlab.maxOASched = Sched::GetSchedule(state, state.dataIPShortCut->cAlphaArgs(7))) == nullptr) {
480 0 : ShowSevereItemNotFound(state, eoh, cAlphaFields(7), state.dataIPShortCut->cAlphaArgs(7));
481 0 : ErrorsFound = true;
482 2 : } else if (!ventSlab.maxOASched->checkMinMaxVals(state, Clusive::In, 0.0, Clusive::In, 1.0)) {
483 0 : Sched::ShowSevereBadMinMax(state, eoh, cAlphaFields(7), state.dataIPShortCut->cAlphaArgs(7), Clusive::In, 0.0, Clusive::In, 1.0);
484 0 : ErrorsFound = true;
485 : }
486 2 : } break;
487 :
488 0 : case OutsideAirControlType::FixedOAControl: {
489 0 : if (lAlphaBlanks(7)) {
490 0 : ShowSevereEmptyField(state, eoh, state.dataIPShortCut->cAlphaFieldNames(7));
491 0 : ErrorsFound = true;
492 0 : } else if ((ventSlab.maxOASched = Sched::GetSchedule(state, state.dataIPShortCut->cAlphaArgs(7))) == nullptr) {
493 0 : ShowSevereItemNotFound(state, eoh, cAlphaFields(7), state.dataIPShortCut->cAlphaArgs(7));
494 0 : ErrorsFound = true;
495 0 : } else if (!ventSlab.maxOASched->checkMinVal(state, Clusive::In, 0.0)) {
496 0 : Sched::ShowSevereBadMin(state, eoh, cAlphaFields(7), state.dataIPShortCut->cAlphaArgs(7), Clusive::In, 0.0);
497 0 : ErrorsFound = true;
498 : }
499 0 : } break;
500 :
501 0 : case OutsideAirControlType::FixedTemperature: {
502 0 : if (lAlphaBlanks(7)) {
503 0 : ShowSevereEmptyField(state, eoh, cAlphaFields(7));
504 0 : ErrorsFound = true;
505 0 : } else if ((ventSlab.tempSched = Sched::GetSchedule(state, state.dataIPShortCut->cAlphaArgs(7))) == nullptr) {
506 0 : ShowSevereItemNotFound(state, eoh, cAlphaFields(7), state.dataIPShortCut->cAlphaArgs(7));
507 0 : ErrorsFound = true;
508 : }
509 0 : } break;
510 :
511 0 : default: {
512 0 : ShowSevereError(
513 : state,
514 0 : format(R"({}="{}" invalid {}="{}".)", CurrentModuleObject, ventSlab.Name, cAlphaFields(5), state.dataIPShortCut->cAlphaArgs(5)));
515 0 : } break;
516 : } // switch (outsideAirControlType)
517 :
518 2 : if (lAlphaBlanks(6)) {
519 2 : } else if ((ventSlab.minOASched = Sched::GetSchedule(state, state.dataIPShortCut->cAlphaArgs(6))) == nullptr) {
520 0 : ShowSevereItemNotFound(state, eoh, cAlphaFields(6), state.dataIPShortCut->cAlphaArgs(6));
521 0 : ErrorsFound = true;
522 : }
523 :
524 : // System Configuration:
525 2 : ventSlab.SysConfg = static_cast<VentilatedSlabConfig>(getEnumValue(VentilatedSlabConfigNamesUC, state.dataIPShortCut->cAlphaArgs(8)));
526 2 : if (ventSlab.SysConfg == VentilatedSlabConfig::Invalid) {
527 0 : ShowWarningInvalidKey(state, eoh, cAlphaFields(8), state.dataIPShortCut->cAlphaArgs(8), "Control reset to SLAB ONLY Configuration.");
528 0 : ventSlab.SysConfg = VentilatedSlabConfig::SlabOnly;
529 : }
530 :
531 : // Hollow Core information :
532 2 : ventSlab.CoreDiameter = state.dataIPShortCut->rNumericArgs(4);
533 2 : ventSlab.CoreLength = state.dataIPShortCut->rNumericArgs(5);
534 2 : ventSlab.CoreNumbers = state.dataIPShortCut->rNumericArgs(6);
535 :
536 2 : if (Util::SameString(state.dataIPShortCut->cAlphaArgs(8), "SurfaceListNames")) {
537 0 : if (!lNumericBlanks(4)) {
538 0 : ShowWarningError(state,
539 0 : format("{}=\"{}\" Core Diameter is not needed for the series slabs configuration- ignored.",
540 : CurrentModuleObject,
541 0 : ventSlab.Name));
542 0 : ShowContinueError(state, "...It has been assigned on SlabGroup.");
543 : }
544 : }
545 :
546 2 : if (Util::SameString(state.dataIPShortCut->cAlphaArgs(8), "SurfaceListNames")) {
547 0 : if (!lNumericBlanks(5)) {
548 0 : ShowWarningError(state,
549 0 : format("{}=\"{}\" Core Length is not needed for the series slabs configuration- ignored.",
550 : CurrentModuleObject,
551 0 : ventSlab.Name));
552 0 : ShowContinueError(state, "...It has been assigned on SlabGroup.");
553 : }
554 : }
555 :
556 2 : if (Util::SameString(state.dataIPShortCut->cAlphaArgs(8), "SurfaceListNames")) {
557 0 : if (!lNumericBlanks(6)) {
558 0 : ShowWarningError(state,
559 0 : format("{}=\"{}\" Core Numbers is not needed for the series slabs configuration- ignored.",
560 : CurrentModuleObject,
561 0 : ventSlab.Name));
562 0 : ShowContinueError(state, "...It has been assigned on SlabGroup.");
563 : }
564 : }
565 :
566 : // Process the temperature control type
567 2 : ventSlab.controlType = static_cast<ControlType>(getEnumValue(ControlTypeNamesUC, Util::makeUPPER(state.dataIPShortCut->cAlphaArgs(9))));
568 :
569 2 : if (ventSlab.controlType == ControlType::Invalid) {
570 0 : ShowSevereError(
571 : state,
572 0 : format(R"({}="{}" invalid {}="{}".)", CurrentModuleObject, ventSlab.Name, cAlphaFields(9), state.dataIPShortCut->cAlphaArgs(9)));
573 0 : ShowContinueError(state, "Control reset to ODB control.");
574 0 : ventSlab.controlType = ControlType::OutdoorDryBulbTemp;
575 : }
576 :
577 : // Heating User Input Data For Ventilated Slab Control :
578 :
579 : // High Air Temp :
580 2 : if (lAlphaBlanks(10)) {
581 2 : } else if ((ventSlab.hotAirHiTempSched = Sched::GetSchedule(state, state.dataIPShortCut->cAlphaArgs(10))) == nullptr) {
582 0 : ShowSevereItemNotFound(state, eoh, cAlphaFields(10), state.dataIPShortCut->cAlphaArgs(10));
583 0 : ErrorsFound = true;
584 : }
585 :
586 : // Low Air Temp :
587 2 : if (lAlphaBlanks(11)) {
588 2 : } else if ((ventSlab.hotAirLoTempSched = Sched::GetSchedule(state, state.dataIPShortCut->cAlphaArgs(11))) == nullptr) {
589 0 : ShowSevereItemNotFound(state, eoh, cAlphaFields(11), state.dataIPShortCut->cAlphaArgs(11));
590 0 : ErrorsFound = true;
591 : }
592 :
593 2 : if (lAlphaBlanks(12)) {
594 2 : } else if ((ventSlab.hotCtrlHiTempSched = Sched::GetSchedule(state, state.dataIPShortCut->cAlphaArgs(12))) == nullptr) {
595 0 : ShowSevereItemNotFound(state, eoh, cAlphaFields(12), state.dataIPShortCut->cAlphaArgs(12));
596 0 : ErrorsFound = true;
597 : }
598 :
599 2 : if (lAlphaBlanks(13)) {
600 2 : } else if ((ventSlab.hotCtrlLoTempSched = Sched::GetSchedule(state, state.dataIPShortCut->cAlphaArgs(13))) == nullptr) {
601 0 : ShowSevereItemNotFound(state, eoh, cAlphaFields(13), state.dataIPShortCut->cAlphaArgs(13));
602 0 : ErrorsFound = true;
603 : }
604 :
605 : // Cooling User Input Data For Ventilated Slab Control :
606 : // Cooling High Temp Sch.
607 2 : if (lAlphaBlanks(14)) {
608 2 : } else if ((ventSlab.coldAirHiTempSched = Sched::GetSchedule(state, state.dataIPShortCut->cAlphaArgs(14))) == nullptr) {
609 0 : ShowSevereItemNotFound(state, eoh, cAlphaFields(14), state.dataIPShortCut->cAlphaArgs(14));
610 0 : ErrorsFound = true;
611 : }
612 :
613 : // Cooling Low Temp Sch.
614 2 : if (lAlphaBlanks(15)) {
615 2 : } else if ((ventSlab.coldAirLoTempSched = Sched::GetSchedule(state, state.dataIPShortCut->cAlphaArgs(15))) == nullptr) {
616 0 : ShowSevereItemNotFound(state, eoh, cAlphaFields(15), state.dataIPShortCut->cAlphaArgs(15));
617 0 : ErrorsFound = true;
618 : }
619 :
620 : // Cooling Control High Sch.
621 2 : if (lAlphaBlanks(16)) {
622 2 : } else if ((ventSlab.coldCtrlHiTempSched = Sched::GetSchedule(state, state.dataIPShortCut->cAlphaArgs(16))) == nullptr) {
623 0 : ShowSevereItemNotFound(state, eoh, cAlphaFields(16), state.dataIPShortCut->cAlphaArgs(16));
624 0 : ErrorsFound = true;
625 : }
626 :
627 : // Cooling Control Low Sch.
628 2 : if (lAlphaBlanks(17)) {
629 2 : } else if ((ventSlab.coldCtrlLoTempSched = Sched::GetSchedule(state, state.dataIPShortCut->cAlphaArgs(17))) == nullptr) {
630 0 : ShowSevereItemNotFound(state, eoh, cAlphaFields(17), state.dataIPShortCut->cAlphaArgs(17));
631 0 : ErrorsFound = true;
632 : }
633 :
634 : // Main air nodes (except outside air node):
635 : // Refer the Unit Ventilator Air Node note
636 :
637 : // MJW CR7903 - Ventilated slab was not drawing properly in HVAC Diagram svg output
638 : // This object is structured differently from other zone equipment in that it functions
639 : // as both a parent and non-parent, and it has an implicit OA mixer. This makes it difficult
640 : // to register the nodes in a way that HVAC Diagram can understand and in a way that satisfies
641 : // node connection tests. Here's an explanation of the changes made for this CR:
642 : // In general, nodes associated with the ventilated slab system (the overall parent object)
643 : // are registered with "-SYSTEM" appended to the object type and object name
644 : // This same suffix is also added later when SetUpCompSets is called, for the same reason
645 : // In general, nodes associated with the implicit OA mixer object
646 : // are registered with "-OA MIXER" appended to the object type and object name
647 : // %ReturnAirNode is one inlet to the implicit oa mixer
648 : // For SlabOnly and SeriesSlab this node does nothing,
649 : // so DataLoopNode::NodeConnectionType::Internal,ObjectIsNotParent, -OA MIXER
650 : // For SlabandZone, this node extracts air from the zone,
651 : // so DataLoopNode::NodeConnectionType::Inlet,ObjectIsNotParent, -OA MIXER
652 : // For SlabandZone, this node is also used to associate the whole system with a pair of zone inlet/exhaust nodes,
653 : // so it is registered again as DataLoopNode::NodeConnectionType::Inlet,1,ObjectIsParent, -SYSTEM
654 : // %RadInNode is the ultimate air inlet to the slab or series of slabs
655 : // For all types of ventilated slab, this is DataLoopNode::NodeConnectionType::Inlet,ObjectIsNotParent
656 : // %OAMixerOutNode is the outlet from the implicit OA mixer
657 : // For all types of ventilated slab, this is DataLoopNode::NodeConnectionType::Outlet,ObjectIsNotParent
658 : // %FanOutletNode is the outlet from the explicit fan child object (redundant input, should mine from child)
659 : // For all types of ventilated slab, this is DataLoopNode::NodeConnectionType::Internal,ObjectIsParent
660 : // %ZoneAirInNode is applicable only to SlabandZone configuration. It is the node that flows into the zone,
661 : // and it is also the outlet from the ventilated slab section, so it must be registered twice
662 : // First for the overall system, DataLoopNode::NodeConnectionType::Outlet,ObjectIsParent, -SYSTEM
663 : // Second as the slab outlet, DataLoopNode::NodeConnectionType::Outlet,ObjectIsNotParent
664 : // %OutsideAirNode is the outdoor air inlet to the OA mixer
665 : // For all types of ventilated slab, this is DataLoopNode::NodeConnectionType::Inlet,ObjectIsNotParent, -OA MIXER
666 :
667 2 : if (ventSlab.SysConfg == VentilatedSlabConfig::SlabOnly) {
668 :
669 0 : ventSlab.ReturnAirNode = NodeInputManager::GetOnlySingleNode(state,
670 0 : state.dataIPShortCut->cAlphaArgs(18),
671 : ErrorsFound,
672 : DataLoopNode::ConnectionObjectType::ZoneHVACVentilatedSlab,
673 0 : ventSlab.Name + "-OA MIXER",
674 : DataLoopNode::NodeFluidType::Air,
675 : DataLoopNode::ConnectionType::Outlet,
676 : NodeInputManager::CompFluidStream::Primary,
677 : DataLoopNode::ObjectIsNotParent);
678 0 : ventSlab.ReturnAirNode = NodeInputManager::GetOnlySingleNode(state,
679 0 : state.dataIPShortCut->cAlphaArgs(18),
680 : ErrorsFound,
681 : DataLoopNode::ConnectionObjectType::ZoneHVACVentilatedSlab,
682 0 : ventSlab.Name,
683 : DataLoopNode::NodeFluidType::Air,
684 : DataLoopNode::ConnectionType::Inlet,
685 : NodeInputManager::CompFluidStream::Primary,
686 : DataLoopNode::ObjectIsParent);
687 0 : ventSlab.RadInNode = NodeInputManager::GetOnlySingleNode(state,
688 0 : state.dataIPShortCut->cAlphaArgs(19),
689 : ErrorsFound,
690 : DataLoopNode::ConnectionObjectType::ZoneHVACVentilatedSlab,
691 0 : ventSlab.Name,
692 : DataLoopNode::NodeFluidType::Air,
693 : DataLoopNode::ConnectionType::Inlet,
694 : NodeInputManager::CompFluidStream::Primary,
695 : DataLoopNode::ObjectIsNotParent);
696 :
697 0 : ventSlab.OAMixerOutNode = NodeInputManager::GetOnlySingleNode(state,
698 0 : state.dataIPShortCut->cAlphaArgs(23),
699 : ErrorsFound,
700 : DataLoopNode::ConnectionObjectType::ZoneHVACVentilatedSlab,
701 0 : ventSlab.Name + "-OA MIXER",
702 : DataLoopNode::NodeFluidType::Air,
703 : DataLoopNode::ConnectionType::Outlet,
704 : NodeInputManager::CompFluidStream::Primary,
705 : DataLoopNode::ObjectIsNotParent);
706 0 : ventSlab.FanOutletNode = NodeInputManager::GetOnlySingleNode(state,
707 0 : state.dataIPShortCut->cAlphaArgs(24),
708 : ErrorsFound,
709 : DataLoopNode::ConnectionObjectType::ZoneHVACVentilatedSlab,
710 0 : ventSlab.Name,
711 : DataLoopNode::NodeFluidType::Air,
712 : DataLoopNode::ConnectionType::Internal,
713 : NodeInputManager::CompFluidStream::Primary,
714 : DataLoopNode::ObjectIsParent);
715 :
716 2 : } else if (ventSlab.SysConfg == VentilatedSlabConfig::SeriesSlabs) {
717 :
718 2 : ventSlab.ReturnAirNode = NodeInputManager::GetOnlySingleNode(state,
719 2 : state.dataIPShortCut->cAlphaArgs(18),
720 : ErrorsFound,
721 : DataLoopNode::ConnectionObjectType::ZoneHVACVentilatedSlab,
722 4 : ventSlab.Name + "-OA MIXER",
723 : DataLoopNode::NodeFluidType::Air,
724 : DataLoopNode::ConnectionType::Outlet,
725 : NodeInputManager::CompFluidStream::Primary,
726 : DataLoopNode::ObjectIsNotParent);
727 2 : ventSlab.ReturnAirNode = NodeInputManager::GetOnlySingleNode(state,
728 2 : state.dataIPShortCut->cAlphaArgs(18),
729 : ErrorsFound,
730 : DataLoopNode::ConnectionObjectType::ZoneHVACVentilatedSlab,
731 2 : ventSlab.Name,
732 : DataLoopNode::NodeFluidType::Air,
733 : DataLoopNode::ConnectionType::Inlet,
734 : NodeInputManager::CompFluidStream::Primary,
735 : DataLoopNode::ObjectIsParent);
736 2 : ventSlab.RadInNode = NodeInputManager::GetOnlySingleNode(state,
737 2 : state.dataIPShortCut->cAlphaArgs(19),
738 : ErrorsFound,
739 : DataLoopNode::ConnectionObjectType::ZoneHVACVentilatedSlab,
740 2 : ventSlab.Name,
741 : DataLoopNode::NodeFluidType::Air,
742 : DataLoopNode::ConnectionType::Inlet,
743 : NodeInputManager::CompFluidStream::Primary,
744 : DataLoopNode::ObjectIsNotParent);
745 :
746 2 : ventSlab.OAMixerOutNode = NodeInputManager::GetOnlySingleNode(state,
747 2 : state.dataIPShortCut->cAlphaArgs(23),
748 : ErrorsFound,
749 : DataLoopNode::ConnectionObjectType::ZoneHVACVentilatedSlab,
750 4 : ventSlab.Name + "-OA MIXER",
751 : DataLoopNode::NodeFluidType::Air,
752 : DataLoopNode::ConnectionType::Outlet,
753 : NodeInputManager::CompFluidStream::Primary,
754 : DataLoopNode::ObjectIsNotParent);
755 4 : ventSlab.FanOutletNode = NodeInputManager::GetOnlySingleNode(state,
756 2 : state.dataIPShortCut->cAlphaArgs(24),
757 : ErrorsFound,
758 : DataLoopNode::ConnectionObjectType::ZoneHVACVentilatedSlab,
759 2 : ventSlab.Name,
760 : DataLoopNode::NodeFluidType::Air,
761 : DataLoopNode::ConnectionType::Internal,
762 : NodeInputManager::CompFluidStream::Primary,
763 : DataLoopNode::ObjectIsParent);
764 :
765 0 : } else if (ventSlab.SysConfg == VentilatedSlabConfig::SlabAndZone) {
766 :
767 0 : ventSlab.ReturnAirNode = NodeInputManager::GetOnlySingleNode(state,
768 0 : state.dataIPShortCut->cAlphaArgs(18),
769 : ErrorsFound,
770 : DataLoopNode::ConnectionObjectType::ZoneHVACVentilatedSlab,
771 0 : ventSlab.Name + "-SYSTEM",
772 : DataLoopNode::NodeFluidType::Air,
773 : DataLoopNode::ConnectionType::Inlet,
774 : NodeInputManager::CompFluidStream::Primary,
775 : DataLoopNode::ObjectIsParent);
776 0 : ventSlab.ReturnAirNode = NodeInputManager::GetOnlySingleNode(state,
777 0 : state.dataIPShortCut->cAlphaArgs(18),
778 : ErrorsFound,
779 : DataLoopNode::ConnectionObjectType::ZoneHVACVentilatedSlab,
780 0 : ventSlab.Name,
781 : DataLoopNode::NodeFluidType::Air,
782 : DataLoopNode::ConnectionType::Inlet,
783 : NodeInputManager::CompFluidStream::Primary,
784 : DataLoopNode::ObjectIsParent);
785 0 : ventSlab.ReturnAirNode = NodeInputManager::GetOnlySingleNode(state,
786 0 : state.dataIPShortCut->cAlphaArgs(18),
787 : ErrorsFound,
788 : DataLoopNode::ConnectionObjectType::ZoneHVACVentilatedSlab,
789 0 : ventSlab.Name + "-OA MIXER",
790 : DataLoopNode::NodeFluidType::Air,
791 : DataLoopNode::ConnectionType::Inlet,
792 : NodeInputManager::CompFluidStream::Primary,
793 : DataLoopNode::ObjectIsNotParent);
794 0 : ventSlab.RadInNode = NodeInputManager::GetOnlySingleNode(state,
795 0 : state.dataIPShortCut->cAlphaArgs(19),
796 : ErrorsFound,
797 : DataLoopNode::ConnectionObjectType::ZoneHVACVentilatedSlab,
798 0 : ventSlab.Name,
799 : DataLoopNode::NodeFluidType::Air,
800 : DataLoopNode::ConnectionType::Inlet,
801 : NodeInputManager::CompFluidStream::Primary,
802 : DataLoopNode::ObjectIsNotParent);
803 0 : ventSlab.OAMixerOutNode = NodeInputManager::GetOnlySingleNode(state,
804 0 : state.dataIPShortCut->cAlphaArgs(23),
805 : ErrorsFound,
806 : DataLoopNode::ConnectionObjectType::ZoneHVACVentilatedSlab,
807 0 : ventSlab.Name + "-OA MIXER",
808 : DataLoopNode::NodeFluidType::Air,
809 : DataLoopNode::ConnectionType::Outlet,
810 : NodeInputManager::CompFluidStream::Primary,
811 : DataLoopNode::ObjectIsNotParent);
812 0 : ventSlab.FanOutletNode = NodeInputManager::GetOnlySingleNode(state,
813 0 : state.dataIPShortCut->cAlphaArgs(24),
814 : ErrorsFound,
815 : DataLoopNode::ConnectionObjectType::ZoneHVACVentilatedSlab,
816 0 : ventSlab.Name,
817 : DataLoopNode::NodeFluidType::Air,
818 : DataLoopNode::ConnectionType::Internal,
819 : NodeInputManager::CompFluidStream::Primary,
820 : DataLoopNode::ObjectIsParent);
821 : }
822 :
823 2 : if (ventSlab.SysConfg == VentilatedSlabConfig::SlabOnly) {
824 0 : if (!lAlphaBlanks(20)) {
825 0 : ShowWarningError(state,
826 0 : format("{}=\"{}\" {}=\"{}\" not needed - ignored.",
827 : CurrentModuleObject,
828 0 : ventSlab.Name,
829 : cAlphaFields(20),
830 0 : state.dataIPShortCut->cAlphaArgs(20)));
831 0 : ShowContinueError(state, "It is used for \"SlabAndZone\" only");
832 : }
833 :
834 2 : } else if (ventSlab.SysConfg == VentilatedSlabConfig::SlabAndZone) {
835 0 : if (lAlphaBlanks(20)) {
836 0 : ShowSevereError(
837 0 : state, format("{}=\"{}\" invalid {} is blank and must be entered.", CurrentModuleObject, ventSlab.Name, cAlphaFields(20)));
838 0 : ErrorsFound = true;
839 : }
840 :
841 0 : ventSlab.ZoneAirInNode = NodeInputManager::GetOnlySingleNode(state,
842 0 : state.dataIPShortCut->cAlphaArgs(20),
843 : ErrorsFound,
844 : DataLoopNode::ConnectionObjectType::ZoneHVACVentilatedSlab,
845 0 : ventSlab.Name + "-SYSTEM",
846 : DataLoopNode::NodeFluidType::Air,
847 : DataLoopNode::ConnectionType::Outlet,
848 : NodeInputManager::CompFluidStream::Primary,
849 : DataLoopNode::ObjectIsParent);
850 :
851 0 : ventSlab.ZoneAirInNode = NodeInputManager::GetOnlySingleNode(state,
852 0 : state.dataIPShortCut->cAlphaArgs(20),
853 : ErrorsFound,
854 : DataLoopNode::ConnectionObjectType::ZoneHVACVentilatedSlab,
855 0 : ventSlab.Name,
856 : DataLoopNode::NodeFluidType::Air,
857 : DataLoopNode::ConnectionType::Outlet,
858 : NodeInputManager::CompFluidStream::Primary,
859 : DataLoopNode::ObjectIsNotParent);
860 : }
861 :
862 : // Set connection type to 'Inlet', because it now uses an OA node
863 2 : ventSlab.OutsideAirNode = NodeInputManager::GetOnlySingleNode(state,
864 2 : state.dataIPShortCut->cAlphaArgs(21),
865 : ErrorsFound,
866 : DataLoopNode::ConnectionObjectType::ZoneHVACVentilatedSlab,
867 4 : ventSlab.Name + "-OA MIXER",
868 : DataLoopNode::NodeFluidType::Air,
869 : DataLoopNode::ConnectionType::Inlet,
870 : NodeInputManager::CompFluidStream::Primary,
871 : DataLoopNode::ObjectIsNotParent);
872 :
873 2 : if (!lAlphaBlanks(21)) {
874 2 : OutAirNodeManager::CheckAndAddAirNodeNumber(state, ventSlab.OutsideAirNode, IsValid);
875 2 : if (!IsValid) {
876 0 : ShowWarningError(
877 : state,
878 0 : format("{}=\"{}\", Adding OutdoorAir:Node={}", CurrentModuleObject, ventSlab.Name, state.dataIPShortCut->cAlphaArgs(21)));
879 : }
880 : }
881 :
882 2 : ventSlab.AirReliefNode = NodeInputManager::GetOnlySingleNode(state,
883 2 : state.dataIPShortCut->cAlphaArgs(22),
884 : ErrorsFound,
885 : DataLoopNode::ConnectionObjectType::ZoneHVACVentilatedSlab,
886 4 : ventSlab.Name + "-OA MIXER",
887 : DataLoopNode::NodeFluidType::Air,
888 : DataLoopNode::ConnectionType::ReliefAir,
889 : NodeInputManager::CompFluidStream::Primary,
890 : DataLoopNode::ObjectIsNotParent);
891 :
892 : // Fan information:
893 2 : ventSlab.FanName = state.dataIPShortCut->cAlphaArgs(25);
894 :
895 2 : if ((ventSlab.Fan_Index = Fans::GetFanIndex(state, ventSlab.FanName)) == 0) {
896 0 : ShowSevereItemNotFound(state, eoh, state.dataIPShortCut->cAlphaFieldNames(25), state.dataIPShortCut->cAlphaArgs(25));
897 0 : ErrorsFound = true;
898 : } else {
899 2 : ventSlab.fanType = state.dataFans->fans(ventSlab.Fan_Index)->type;
900 2 : if (ventSlab.fanType != HVAC::FanType::Constant && ventSlab.fanType != HVAC::FanType::SystemModel) {
901 0 : ShowSevereCustom(state,
902 : eoh,
903 0 : format("Only fans of type Fan:ConstantVolume and Fan:SystemModel are supported. {} is of type {}",
904 0 : ventSlab.FanName,
905 0 : HVAC::fanTypeNames[(int)ventSlab.fanType]));
906 0 : ErrorsFound = true;
907 : }
908 : }
909 2 : if (ventSlab.outsideAirControlType == OutsideAirControlType::FixedOAControl) {
910 0 : ventSlab.OutAirVolFlow = ventSlab.MinOutAirVolFlow;
911 0 : ventSlab.maxOASched = ventSlab.minOASched;
912 : }
913 :
914 : // Add fan to component sets array
915 4 : BranchNodeConnections::SetUpCompSets(state,
916 : CurrentModuleObject,
917 : ventSlab.Name,
918 : "UNDEFINED",
919 2 : state.dataIPShortCut->cAlphaArgs(25),
920 2 : state.dataIPShortCut->cAlphaArgs(23),
921 2 : state.dataIPShortCut->cAlphaArgs(24));
922 :
923 : // Coil options assign
924 :
925 2 : ventSlab.coilOption = static_cast<CoilType>(getEnumValue(CoilTypeNamesUC, Util::makeUPPER(state.dataIPShortCut->cAlphaArgs(26))));
926 :
927 2 : if (ventSlab.coilOption == CoilType::Invalid) {
928 0 : ShowSevereError(
929 : state,
930 0 : format(
931 0 : R"({}="{}" invalid {}="{}".)", CurrentModuleObject, ventSlab.Name, cAlphaFields(26), state.dataIPShortCut->cAlphaArgs(26)));
932 0 : ErrorsFound = true;
933 : }
934 :
935 2 : if (ventSlab.coilOption == CoilType::Both || ventSlab.coilOption == CoilType::Heating) {
936 : // Heating coil information:
937 : // A27, \field Heating Coil Object Type
938 : // \type choice
939 : // \key Coil:Heating:Water
940 : // \key Coil:Heating:Electric
941 : // \key Coil:Heating:Fuel
942 : // \key Coil:Heating:Steam
943 : // A28, \field Heating Coil Name
944 : // \type object-list
945 : // \object-list HeatingCoilName
946 :
947 : // Heating coil information:
948 2 : if (!lAlphaBlanks(28)) {
949 2 : ventSlab.heatingCoilPresent = true;
950 2 : ventSlab.heatingCoilTypeCh = state.dataIPShortCut->cAlphaArgs(27);
951 2 : errFlag = false;
952 :
953 2 : ventSlab.hCoilType =
954 2 : static_cast<HeatingCoilType>(getEnumValue(HeatingCoilTypeNamesUC, Util::makeUPPER(state.dataIPShortCut->cAlphaArgs(27))));
955 :
956 2 : switch (ventSlab.hCoilType) {
957 :
958 1 : case HeatingCoilType::Water: {
959 1 : ventSlab.heatingCoilType = DataPlant::PlantEquipmentType::CoilWaterSimpleHeating;
960 1 : break;
961 : }
962 0 : case HeatingCoilType::Steam: {
963 0 : ventSlab.heatingCoilType = DataPlant::PlantEquipmentType::CoilSteamAirHeating;
964 0 : ventSlab.heatingCoil_fluid = Fluid::GetSteam(state);
965 0 : if (ventSlab.heatingCoil_fluid == nullptr) {
966 0 : ShowSevereError(state, format("{}=\"{}Steam Properties not found.", CurrentModuleObject, ventSlab.Name));
967 0 : if (SteamMessageNeeded) {
968 0 : ShowContinueError(state, "Steam Fluid Properties should have been included in the input file.");
969 : }
970 0 : ErrorsFound = true;
971 0 : SteamMessageNeeded = false;
972 : }
973 0 : break;
974 : }
975 1 : case HeatingCoilType::Electric:
976 : case HeatingCoilType::Gas:
977 1 : break;
978 0 : default: {
979 0 : ShowSevereError(state,
980 0 : format(R"({}="{}" invalid {}="{}".)",
981 : CurrentModuleObject,
982 0 : ventSlab.Name,
983 : cAlphaFields(27),
984 0 : state.dataIPShortCut->cAlphaArgs(27)));
985 0 : ErrorsFound = true;
986 0 : errFlag = true;
987 0 : break;
988 : }
989 : }
990 2 : if (!errFlag) {
991 2 : ventSlab.heatingCoilName = state.dataIPShortCut->cAlphaArgs(28);
992 2 : ValidateComponent(state, state.dataIPShortCut->cAlphaArgs(27), ventSlab.heatingCoilName, IsNotOK, CurrentModuleObject);
993 2 : if (IsNotOK) {
994 0 : ShowContinueError(state,
995 0 : format("{}=\"{}\" invalid {}=\"{}\".",
996 : CurrentModuleObject,
997 0 : ventSlab.Name,
998 : cAlphaFields(28),
999 0 : state.dataIPShortCut->cAlphaArgs(28)));
1000 0 : ShowContinueError(state, format("... not valid for {}=\"{}\".", cAlphaFields(27), state.dataIPShortCut->cAlphaArgs(27)));
1001 0 : ErrorsFound = true;
1002 : }
1003 : }
1004 :
1005 2 : ventSlab.MinVolHotWaterFlow = 0.0;
1006 2 : ventSlab.MinVolHotSteamFlow = 0.0;
1007 :
1008 : // The heating coil control node is necessary for a hot water coil, but not necessary for an
1009 : // electric or gas coil.
1010 2 : if (ventSlab.hCoilType == HeatingCoilType::Gas || ventSlab.hCoilType == HeatingCoilType::Electric) {
1011 1 : if (!lAlphaBlanks(29)) {
1012 0 : ShowWarningError(state,
1013 0 : format("{}=\"{}\" {}=\"{}\" not needed - ignored.",
1014 : CurrentModuleObject,
1015 0 : ventSlab.Name,
1016 : cAlphaFields(29),
1017 0 : state.dataIPShortCut->cAlphaArgs(29)));
1018 0 : ShowContinueError(state, "..It is used for hot water coils only.");
1019 : }
1020 : } else {
1021 1 : if (lAlphaBlanks(29)) {
1022 0 : ShowSevereError(
1023 : state,
1024 0 : format("{}=\"{}\" invalid {} is blank and must be entered.", CurrentModuleObject, ventSlab.Name, cAlphaFields(29)));
1025 0 : ErrorsFound = true;
1026 : }
1027 2 : ventSlab.HotControlNode = NodeInputManager::GetOnlySingleNode(state,
1028 1 : state.dataIPShortCut->cAlphaArgs(29),
1029 : ErrorsFound,
1030 : DataLoopNode::ConnectionObjectType::ZoneHVACVentilatedSlab,
1031 1 : ventSlab.Name,
1032 : DataLoopNode::NodeFluidType::Water,
1033 : DataLoopNode::ConnectionType::Actuator,
1034 : NodeInputManager::CompFluidStream::Primary,
1035 : DataLoopNode::ObjectIsParent);
1036 : }
1037 2 : ventSlab.HotControlOffset = 0.001;
1038 :
1039 2 : if (ventSlab.hCoilType == HeatingCoilType::Water) {
1040 1 : ventSlab.MaxVolHotWaterFlow = GetWaterCoilMaxFlowRate(state, "Coil:Heating:Water", ventSlab.heatingCoilName, ErrorsFound);
1041 1 : ventSlab.MaxVolHotSteamFlow = GetWaterCoilMaxFlowRate(state, "Coil:Heating:Water", ventSlab.heatingCoilName, ErrorsFound);
1042 1 : } else if (ventSlab.hCoilType == HeatingCoilType::Steam) {
1043 0 : ventSlab.MaxVolHotWaterFlow = GetSteamCoilMaxFlowRate(state, "Coil:Heating:Steam", ventSlab.heatingCoilName, ErrorsFound);
1044 0 : ventSlab.MaxVolHotSteamFlow = GetSteamCoilMaxFlowRate(state, "Coil:Heating:Steam", ventSlab.heatingCoilName, ErrorsFound);
1045 : }
1046 :
1047 : } else { // no heating coil
1048 0 : ShowSevereError(state, format("{}=\"{}\" missing heating coil.", CurrentModuleObject, ventSlab.Name));
1049 0 : ShowContinueError(state,
1050 0 : format("a heating coil is required for {}=\"{}\".", cAlphaFields(26), state.dataIPShortCut->cAlphaArgs(26)));
1051 0 : ErrorsFound = true;
1052 : }
1053 : }
1054 :
1055 2 : if (ventSlab.coilOption == CoilType::Both || ventSlab.coilOption == CoilType::Cooling) {
1056 : // Cooling coil information (if one is present):
1057 : // A30, \field Cooling Coil Object Type
1058 : // \type choice
1059 : // \key Coil:Cooling:Water
1060 : // \key Coil:Cooling:Water:DetailedGeometry
1061 : // \key CoilSystem:Cooling:Water:HeatExchangerAssisted
1062 : // A31, \field Cooling Coil Name
1063 : // \type object-list
1064 : // \object-list CoolingCoilsWater
1065 : // Cooling coil information (if one is present):
1066 2 : if (!lAlphaBlanks(31)) {
1067 2 : ventSlab.coolingCoilPresent = true;
1068 2 : ventSlab.coolingCoilTypeCh = state.dataIPShortCut->cAlphaArgs(30);
1069 2 : errFlag = false;
1070 :
1071 2 : ventSlab.cCoilType =
1072 2 : static_cast<CoolingCoilType>(getEnumValue(CoolingCoilTypeNamesUC, Util::makeUPPER(state.dataIPShortCut->cAlphaArgs(30))));
1073 2 : switch (ventSlab.cCoilType) {
1074 2 : case CoolingCoilType::WaterCooling: {
1075 2 : ventSlab.coolingCoilType = DataPlant::PlantEquipmentType::CoilWaterCooling;
1076 2 : ventSlab.coolingCoilPlantName = state.dataIPShortCut->cAlphaArgs(31);
1077 2 : break;
1078 : }
1079 0 : case CoolingCoilType::DetailedCooling: {
1080 0 : ventSlab.coolingCoilType = DataPlant::PlantEquipmentType::CoilWaterDetailedFlatCooling;
1081 0 : ventSlab.coolingCoilPlantName = state.dataIPShortCut->cAlphaArgs(31);
1082 0 : break;
1083 : }
1084 0 : case CoolingCoilType::HXAssisted: {
1085 0 : HVACHXAssistedCoolingCoil::GetHXCoilTypeAndName(state,
1086 0 : state.dataIPShortCut->cAlphaArgs(30),
1087 0 : state.dataIPShortCut->cAlphaArgs(31),
1088 : ErrorsFound,
1089 0 : ventSlab.coolingCoilPlantType,
1090 0 : ventSlab.coolingCoilPlantName);
1091 0 : if (Util::SameString(ventSlab.coolingCoilPlantType, "Coil:Cooling:Water")) {
1092 0 : ventSlab.coolingCoilType = DataPlant::PlantEquipmentType::CoilWaterCooling;
1093 0 : } else if (Util::SameString(ventSlab.coolingCoilPlantType, "Coil:Cooling:Water:DetailedGeometry")) {
1094 0 : ventSlab.coolingCoilType = DataPlant::PlantEquipmentType::CoilWaterDetailedFlatCooling;
1095 : } else {
1096 0 : ShowSevereError(state, format("GetVentilatedSlabInput: {}=\"{}\", invalid", CurrentModuleObject, ventSlab.Name));
1097 0 : ShowContinueError(state, format("For: {}=\"{}\".", cAlphaFields(30), state.dataIPShortCut->cAlphaArgs(30)));
1098 0 : ShowContinueError(state,
1099 0 : format("Invalid Coil Type={}, Name={}", ventSlab.coolingCoilPlantType, ventSlab.coolingCoilPlantName));
1100 0 : ShowContinueError(state, R"(must be "Coil:Cooling:Water" or "Coil:Cooling:Water:DetailedGeometry")");
1101 0 : ErrorsFound = true;
1102 : }
1103 0 : break;
1104 : }
1105 0 : default: {
1106 0 : ShowSevereError(state,
1107 0 : format(R"({}="{}" invalid {}="{}".)",
1108 : CurrentModuleObject,
1109 0 : ventSlab.Name,
1110 : cAlphaFields(29),
1111 0 : state.dataIPShortCut->cAlphaArgs(29)));
1112 0 : ErrorsFound = true;
1113 0 : errFlag = true;
1114 0 : break;
1115 : }
1116 : }
1117 :
1118 2 : if (!errFlag) {
1119 2 : ventSlab.coolingCoilName = state.dataIPShortCut->cAlphaArgs(31);
1120 2 : ValidateComponent(state, state.dataIPShortCut->cAlphaArgs(30), ventSlab.coolingCoilName, IsNotOK, "ZoneHVAC:VentilatedSlab ");
1121 2 : if (IsNotOK) {
1122 0 : ShowContinueError(state,
1123 0 : format("{}=\"{}\" invalid {}=\"{}\".",
1124 : CurrentModuleObject,
1125 0 : ventSlab.Name,
1126 : cAlphaFields(31),
1127 0 : state.dataIPShortCut->cAlphaArgs(31)));
1128 0 : ShowContinueError(state, format("... not valid for {}=\"{}\".", cAlphaFields(30), state.dataIPShortCut->cAlphaArgs(30)));
1129 0 : ErrorsFound = true;
1130 : }
1131 : }
1132 :
1133 2 : ventSlab.MinVolColdWaterFlow = 0.0;
1134 :
1135 2 : ventSlab.ColdControlNode = NodeInputManager::GetOnlySingleNode(state,
1136 2 : state.dataIPShortCut->cAlphaArgs(32),
1137 : ErrorsFound,
1138 : DataLoopNode::ConnectionObjectType::ZoneHVACVentilatedSlab,
1139 2 : ventSlab.Name,
1140 : DataLoopNode::NodeFluidType::Water,
1141 : DataLoopNode::ConnectionType::Actuator,
1142 : NodeInputManager::CompFluidStream::Primary,
1143 : DataLoopNode::ObjectIsParent);
1144 :
1145 2 : if (lAlphaBlanks(32)) {
1146 0 : ShowSevereError(
1147 : state,
1148 0 : format("{}=\"{}\" invalid {} is blank and must be entered.", CurrentModuleObject, ventSlab.Name, cAlphaFields(32)));
1149 0 : ErrorsFound = true;
1150 : }
1151 :
1152 2 : ventSlab.ColdControlOffset = 0.001;
1153 :
1154 2 : if (ventSlab.cCoilType == CoolingCoilType::WaterCooling) {
1155 2 : ventSlab.MaxVolColdWaterFlow = GetWaterCoilMaxFlowRate(state, "Coil:Cooling:Water", ventSlab.coolingCoilName, ErrorsFound);
1156 0 : } else if (ventSlab.cCoilType == CoolingCoilType::DetailedCooling) {
1157 0 : ventSlab.MaxVolColdWaterFlow =
1158 0 : GetWaterCoilMaxFlowRate(state, "Coil:Cooling:Water:DetailedGeometry", ventSlab.coolingCoilName, ErrorsFound);
1159 0 : } else if (ventSlab.cCoilType == CoolingCoilType::HXAssisted) {
1160 0 : ventSlab.MaxVolColdWaterFlow =
1161 0 : GetHXAssistedCoilFlowRate(state, "CoilSystem:Cooling:Water:HeatExchangerAssisted", ventSlab.coolingCoilName, ErrorsFound);
1162 : }
1163 :
1164 : } else { // No Cooling Coil
1165 0 : ShowSevereError(state, format("{}=\"{}\" missing cooling coil.", CurrentModuleObject, ventSlab.Name));
1166 0 : ShowContinueError(state,
1167 0 : format("a cooling coil is required for {}=\"{}\".", cAlphaFields(26), state.dataIPShortCut->cAlphaArgs(26)));
1168 0 : ErrorsFound = true;
1169 : }
1170 : }
1171 :
1172 2 : ventSlab.HVACSizingIndex = 0;
1173 2 : if (!lAlphaBlanks(34)) {
1174 0 : ventSlab.HVACSizingIndex = Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(34), state.dataSize->ZoneHVACSizing);
1175 0 : if (ventSlab.HVACSizingIndex == 0) {
1176 0 : ShowSevereError(state, format("{} = {} not found.", cAlphaFields(34), state.dataIPShortCut->cAlphaArgs(34)));
1177 0 : ShowContinueError(state, format("Occurs in {} = {}", cMO_VentilatedSlab, ventSlab.Name));
1178 0 : ErrorsFound = true;
1179 : }
1180 : }
1181 :
1182 2 : switch (ventSlab.coilOption) {
1183 2 : case CoilType::Both: { // 'HeatingAndCooling'
1184 : // Add cooling coil to component sets array when present
1185 4 : BranchNodeConnections::SetUpCompSets(state,
1186 : CurrentModuleObject,
1187 : ventSlab.Name,
1188 2 : state.dataIPShortCut->cAlphaArgs(30),
1189 2 : state.dataIPShortCut->cAlphaArgs(31),
1190 2 : state.dataIPShortCut->cAlphaArgs(24),
1191 : "UNDEFINED");
1192 :
1193 : // Add heating coil to component sets array when cooling coil present
1194 6 : BranchNodeConnections::SetUpCompSets(state,
1195 : CurrentModuleObject,
1196 : ventSlab.Name,
1197 2 : state.dataIPShortCut->cAlphaArgs(27),
1198 2 : state.dataIPShortCut->cAlphaArgs(28),
1199 : "UNDEFINED",
1200 2 : state.dataIPShortCut->cAlphaArgs(19));
1201 2 : break;
1202 : }
1203 0 : case CoilType::Heating: { // 'Heating'
1204 : // Add heating coil to component sets array when no cooling coil present
1205 0 : BranchNodeConnections::SetUpCompSets(state,
1206 : CurrentModuleObject,
1207 : ventSlab.Name,
1208 0 : state.dataIPShortCut->cAlphaArgs(27),
1209 0 : state.dataIPShortCut->cAlphaArgs(28),
1210 0 : state.dataIPShortCut->cAlphaArgs(24),
1211 0 : state.dataIPShortCut->cAlphaArgs(19));
1212 0 : break;
1213 : }
1214 0 : case CoilType::Cooling: { // 'Cooling'
1215 : // Add cooling coil to component sets array when no heating coil present
1216 0 : BranchNodeConnections::SetUpCompSets(state,
1217 : CurrentModuleObject,
1218 : ventSlab.Name,
1219 0 : state.dataIPShortCut->cAlphaArgs(30),
1220 0 : state.dataIPShortCut->cAlphaArgs(31),
1221 0 : state.dataIPShortCut->cAlphaArgs(24),
1222 0 : state.dataIPShortCut->cAlphaArgs(19));
1223 0 : break;
1224 : }
1225 0 : case CoilType::None:
1226 : default:
1227 0 : break;
1228 : }
1229 :
1230 : } // ...loop over all of the ventilated slab found in the input file
1231 :
1232 1 : cAlphaArgs.deallocate();
1233 1 : cAlphaFields.deallocate();
1234 1 : cNumericFields.deallocate();
1235 1 : rNumericArgs.deallocate();
1236 1 : lAlphaBlanks.deallocate();
1237 1 : lNumericBlanks.deallocate();
1238 :
1239 1 : if (ErrorsFound) {
1240 0 : ShowFatalError(state, format("{} errors occurred in input. Program terminates.", CurrentModuleObject));
1241 : }
1242 :
1243 : // Setup Report variables for the VENTILATED SLAB
1244 3 : for (Item = 1; Item <= state.dataVentilatedSlab->NumOfVentSlabs; ++Item) {
1245 2 : auto &ventSlab = state.dataVentilatedSlab->VentSlab(Item);
1246 4 : SetupOutputVariable(state,
1247 : "Zone Ventilated Slab Radiant Heating Rate",
1248 : Constant::Units::W,
1249 2 : ventSlab.RadHeatingPower,
1250 : OutputProcessor::TimeStepType::System,
1251 : OutputProcessor::StoreType::Average,
1252 2 : ventSlab.Name);
1253 4 : SetupOutputVariable(state,
1254 : "Zone Ventilated Slab Radiant Heating Energy",
1255 : Constant::Units::J,
1256 2 : ventSlab.RadHeatingEnergy,
1257 : OutputProcessor::TimeStepType::System,
1258 : OutputProcessor::StoreType::Sum,
1259 2 : ventSlab.Name);
1260 4 : SetupOutputVariable(state,
1261 : "Zone Ventilated Slab Radiant Cooling Rate",
1262 : Constant::Units::W,
1263 2 : ventSlab.RadCoolingPower,
1264 : OutputProcessor::TimeStepType::System,
1265 : OutputProcessor::StoreType::Average,
1266 2 : ventSlab.Name);
1267 4 : SetupOutputVariable(state,
1268 : "Zone Ventilated Slab Radiant Cooling Energy",
1269 : Constant::Units::J,
1270 2 : ventSlab.RadCoolingEnergy,
1271 : OutputProcessor::TimeStepType::System,
1272 : OutputProcessor::StoreType::Sum,
1273 2 : ventSlab.Name);
1274 4 : SetupOutputVariable(state,
1275 : "Zone Ventilated Slab Coil Heating Rate",
1276 : Constant::Units::W,
1277 2 : ventSlab.HeatCoilPower,
1278 : OutputProcessor::TimeStepType::System,
1279 : OutputProcessor::StoreType::Average,
1280 2 : ventSlab.Name);
1281 4 : SetupOutputVariable(state,
1282 : "Zone Ventilated Slab Coil Heating Energy",
1283 : Constant::Units::J,
1284 2 : ventSlab.HeatCoilEnergy,
1285 : OutputProcessor::TimeStepType::System,
1286 : OutputProcessor::StoreType::Sum,
1287 2 : ventSlab.Name);
1288 4 : SetupOutputVariable(state,
1289 : "Zone Ventilated Slab Coil Total Cooling Rate",
1290 : Constant::Units::W,
1291 2 : ventSlab.TotCoolCoilPower,
1292 : OutputProcessor::TimeStepType::System,
1293 : OutputProcessor::StoreType::Average,
1294 2 : ventSlab.Name);
1295 4 : SetupOutputVariable(state,
1296 : "Zone Ventilated Slab Coil Total Cooling Energy",
1297 : Constant::Units::J,
1298 2 : ventSlab.TotCoolCoilEnergy,
1299 : OutputProcessor::TimeStepType::System,
1300 : OutputProcessor::StoreType::Sum,
1301 2 : ventSlab.Name);
1302 4 : SetupOutputVariable(state,
1303 : "Zone Ventilated Slab Coil Sensible Cooling Rate",
1304 : Constant::Units::W,
1305 2 : ventSlab.SensCoolCoilPower,
1306 : OutputProcessor::TimeStepType::System,
1307 : OutputProcessor::StoreType::Average,
1308 2 : ventSlab.Name);
1309 4 : SetupOutputVariable(state,
1310 : "Zone Ventilated Slab Coil Sensible Cooling Energy",
1311 : Constant::Units::J,
1312 2 : ventSlab.SensCoolCoilEnergy,
1313 : OutputProcessor::TimeStepType::System,
1314 : OutputProcessor::StoreType::Sum,
1315 2 : ventSlab.Name);
1316 4 : SetupOutputVariable(state,
1317 : "Zone Ventilated Slab Coil Latent Cooling Rate",
1318 : Constant::Units::W,
1319 2 : ventSlab.LateCoolCoilPower,
1320 : OutputProcessor::TimeStepType::System,
1321 : OutputProcessor::StoreType::Average,
1322 2 : ventSlab.Name);
1323 4 : SetupOutputVariable(state,
1324 : "Zone Ventilated Slab Coil Latent Cooling Energy",
1325 : Constant::Units::J,
1326 2 : ventSlab.LateCoolCoilEnergy,
1327 : OutputProcessor::TimeStepType::System,
1328 : OutputProcessor::StoreType::Sum,
1329 2 : ventSlab.Name);
1330 4 : SetupOutputVariable(state,
1331 : "Zone Ventilated Slab Air Mass Flow Rate",
1332 : Constant::Units::kg_s,
1333 2 : ventSlab.AirMassFlowRate,
1334 : OutputProcessor::TimeStepType::System,
1335 : OutputProcessor::StoreType::Average,
1336 2 : ventSlab.Name);
1337 4 : SetupOutputVariable(state,
1338 : "Zone Ventilated Slab Fan Electricity Rate",
1339 : Constant::Units::W,
1340 2 : ventSlab.ElecFanPower,
1341 : OutputProcessor::TimeStepType::System,
1342 : OutputProcessor::StoreType::Average,
1343 2 : ventSlab.Name);
1344 : //! Note that the ventilated slab fan electric is NOT metered because this value is already metered through the fan component
1345 4 : SetupOutputVariable(state,
1346 : "Zone Ventilated Slab Fan Electricity Energy",
1347 : Constant::Units::J,
1348 2 : ventSlab.ElecFanEnergy,
1349 : OutputProcessor::TimeStepType::System,
1350 : OutputProcessor::StoreType::Sum,
1351 2 : ventSlab.Name);
1352 4 : SetupOutputVariable(state,
1353 : "Zone Ventilated Slab Inlet Air Temperature",
1354 : Constant::Units::C,
1355 2 : ventSlab.SlabInTemp,
1356 : OutputProcessor::TimeStepType::System,
1357 : OutputProcessor::StoreType::Average,
1358 2 : ventSlab.Name);
1359 4 : SetupOutputVariable(state,
1360 : "Zone Ventilated Slab Outlet Air Temperature",
1361 : Constant::Units::C,
1362 2 : ventSlab.SlabOutTemp,
1363 : OutputProcessor::TimeStepType::System,
1364 : OutputProcessor::StoreType::Average,
1365 2 : ventSlab.Name);
1366 4 : SetupOutputVariable(state,
1367 : "Zone Ventilated Slab Zone Inlet Air Temperature",
1368 : Constant::Units::C,
1369 2 : ventSlab.ZoneInletTemp,
1370 : OutputProcessor::TimeStepType::System,
1371 : OutputProcessor::StoreType::Average,
1372 2 : ventSlab.Name);
1373 4 : SetupOutputVariable(state,
1374 : "Zone Ventilated Slab Return Air Temperature",
1375 : Constant::Units::C,
1376 2 : ventSlab.ReturnAirTemp,
1377 : OutputProcessor::TimeStepType::System,
1378 : OutputProcessor::StoreType::Average,
1379 2 : ventSlab.Name);
1380 4 : SetupOutputVariable(state,
1381 : "Zone Ventilated Slab Fan Outlet Air Temperature",
1382 : Constant::Units::C,
1383 2 : ventSlab.FanOutletTemp,
1384 : OutputProcessor::TimeStepType::System,
1385 : OutputProcessor::StoreType::Average,
1386 2 : ventSlab.Name);
1387 2 : SetupOutputVariable(state,
1388 : "Zone Ventilated Slab Fan Availability Status",
1389 : Constant::Units::None,
1390 2 : (int &)ventSlab.availStatus,
1391 : OutputProcessor::TimeStepType::System,
1392 : OutputProcessor::StoreType::Average,
1393 2 : ventSlab.Name);
1394 : }
1395 1 : }
1396 :
1397 1 : void InitVentilatedSlab(EnergyPlusData &state,
1398 : int const Item, // index for the current ventilated slab
1399 : int const VentSlabZoneNum, // number of zone being served
1400 : bool const FirstHVACIteration // TRUE if 1st HVAC simulation of system timestep
1401 : )
1402 : {
1403 :
1404 : // SUBROUTINE INFORMATION:
1405 : // AUTHOR Young Tae Chae, Rick Strand
1406 : // DATE WRITTEN June 2008
1407 : // MODIFIED July 2012, Chandan Sharma - FSEC: Added zone sys avail managers
1408 :
1409 : // PURPOSE OF THIS SUBROUTINE:
1410 : // This subroutine initializes all of the data elements which are necessary
1411 : // to simulate a Ventilated Slab.
1412 :
1413 : // METHODOLOGY EMPLOYED:
1414 : // Uses the status flags to trigger initializations.
1415 :
1416 : // Using/Aliasing
1417 1 : auto &ventSlab = state.dataVentilatedSlab->VentSlab(Item);
1418 :
1419 : // SUBROUTINE PARAMETER DEFINITIONS:
1420 : static constexpr std::string_view RoutineName("InitVentilatedSlab");
1421 :
1422 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1423 : int AirRelNode; // relief air node number in Ventilated Slab loop
1424 : Real64 RhoAir; // air density at InNode
1425 : Real64 TempSteamIn;
1426 : Real64 SteamDensity;
1427 : Real64 rho;
1428 :
1429 : // Do the one time initializations
1430 :
1431 1 : if (state.dataVentilatedSlab->MyOneTimeFlag) {
1432 1 : state.dataVentilatedSlab->MyEnvrnFlag.allocate(state.dataVentilatedSlab->NumOfVentSlabs);
1433 1 : state.dataVentilatedSlab->MySizeFlag.allocate(state.dataVentilatedSlab->NumOfVentSlabs);
1434 1 : state.dataVentilatedSlab->MyPlantScanFlag.allocate(state.dataVentilatedSlab->NumOfVentSlabs);
1435 1 : state.dataVentilatedSlab->MyZoneEqFlag.allocate(state.dataVentilatedSlab->NumOfVentSlabs);
1436 :
1437 : // Initialize total areas for all radiant systems and dimension record keeping arrays
1438 3 : for (auto &thisVentSlab : state.dataVentilatedSlab->VentSlab) {
1439 2 : thisVentSlab.TotalSurfaceArea = 0.0;
1440 2 : int numRadSurfs = thisVentSlab.NumOfSurfaces;
1441 7 : for (int SurfNum = 1; SurfNum <= numRadSurfs; ++SurfNum) {
1442 5 : thisVentSlab.TotalSurfaceArea += state.dataSurface->Surface(thisVentSlab.SurfacePtr(SurfNum)).Area;
1443 : }
1444 2 : thisVentSlab.QRadSysSrcAvg.dimension(numRadSurfs, 0.0);
1445 2 : thisVentSlab.LastQRadSysSrc.dimension(numRadSurfs, 0.0);
1446 2 : thisVentSlab.LastSysTimeElapsed = 0.0;
1447 2 : thisVentSlab.LastTimeStepSys = 0.0;
1448 1 : }
1449 1 : state.dataVentilatedSlab->MyEnvrnFlag = true;
1450 1 : state.dataVentilatedSlab->MySizeFlag = true;
1451 1 : state.dataVentilatedSlab->MyPlantScanFlag = true;
1452 1 : state.dataVentilatedSlab->MyZoneEqFlag = true;
1453 1 : state.dataVentilatedSlab->MyOneTimeFlag = false;
1454 : }
1455 :
1456 1 : if (allocated(state.dataAvail->ZoneComp)) {
1457 0 : auto &availMgr = state.dataAvail->ZoneComp(DataZoneEquipment::ZoneEquipType::VentilatedSlab).ZoneCompAvailMgrs(Item);
1458 0 : if (state.dataVentilatedSlab->MyZoneEqFlag(Item)) { // initialize the name of each availability manager list and zone number
1459 0 : availMgr.AvailManagerListName = ventSlab.AvailManagerListName;
1460 0 : availMgr.ZoneNum = VentSlabZoneNum;
1461 0 : state.dataVentilatedSlab->MyZoneEqFlag(Item) = false;
1462 : }
1463 0 : ventSlab.availStatus = availMgr.availStatus;
1464 : }
1465 :
1466 1 : if (state.dataVentilatedSlab->MyPlantScanFlag(Item) && allocated(state.dataPlnt->PlantLoop)) {
1467 0 : if ((ventSlab.heatingCoilType == DataPlant::PlantEquipmentType::CoilWaterSimpleHeating) ||
1468 0 : (ventSlab.heatingCoilType == DataPlant::PlantEquipmentType::CoilSteamAirHeating)) {
1469 0 : bool errFlag = false;
1470 0 : PlantUtilities::ScanPlantLoopsForObject(
1471 0 : state, ventSlab.heatingCoilName, ventSlab.heatingCoilType, ventSlab.HWPlantLoc, errFlag, _, _, _, _, _);
1472 0 : if (errFlag) {
1473 0 : ShowContinueError(state, format("Reference Unit=\"{}\", type=ZoneHVAC:VentilatedSlab", ventSlab.Name));
1474 0 : ShowFatalError(state, "InitVentilatedSlab: Program terminated due to previous condition(s).");
1475 : }
1476 :
1477 0 : ventSlab.HotCoilOutNodeNum = DataPlant::CompData::getPlantComponent(state, ventSlab.HWPlantLoc).NodeNumOut;
1478 : }
1479 0 : if ((ventSlab.coolingCoilType == DataPlant::PlantEquipmentType::CoilWaterCooling) ||
1480 0 : (ventSlab.coolingCoilType == DataPlant::PlantEquipmentType::CoilWaterDetailedFlatCooling)) {
1481 0 : bool errFlag = false;
1482 0 : PlantUtilities::ScanPlantLoopsForObject(state, ventSlab.coolingCoilPlantName, ventSlab.coolingCoilType, ventSlab.CWPlantLoc, errFlag);
1483 0 : if (errFlag) {
1484 0 : ShowContinueError(state, format("Reference Unit=\"{}\", type=ZoneHVAC:VentilatedSlab", ventSlab.Name));
1485 0 : ShowFatalError(state, "InitVentilatedSlab: Program terminated due to previous condition(s).");
1486 : }
1487 0 : ventSlab.ColdCoilOutNodeNum = DataPlant::CompData::getPlantComponent(state, ventSlab.CWPlantLoc).NodeNumOut;
1488 0 : } else {
1489 0 : if (ventSlab.coolingCoilPresent) {
1490 0 : ShowFatalError(state, format("InitVentilatedSlab: Unit={}, invalid cooling coil type. Program terminated.", ventSlab.Name));
1491 : }
1492 : }
1493 0 : state.dataVentilatedSlab->MyPlantScanFlag(Item) = false;
1494 1 : } else if (state.dataVentilatedSlab->MyPlantScanFlag(Item) && !state.dataGlobal->AnyPlantInModel) {
1495 1 : state.dataVentilatedSlab->MyPlantScanFlag(Item) = false;
1496 : }
1497 :
1498 : // need to check all Ventilated Slab units to see if they are on Zone Equipment List or issue warning
1499 1 : if (!state.dataVentilatedSlab->ZoneEquipmentListChecked && state.dataZoneEquip->ZoneEquipInputsFilled) {
1500 1 : state.dataVentilatedSlab->ZoneEquipmentListChecked = true;
1501 3 : for (int RadNum = 1; RadNum <= state.dataVentilatedSlab->NumOfVentSlabs; ++RadNum) {
1502 2 : if (DataZoneEquipment::CheckZoneEquipmentList(state, cMO_VentilatedSlab, state.dataVentilatedSlab->VentSlab(RadNum).Name)) {
1503 2 : continue;
1504 : }
1505 0 : ShowSevereError(
1506 : state,
1507 0 : format("InitVentilatedSlab: Ventilated Slab Unit=[{},{}] is not on any ZoneHVAC:EquipmentList. It will not be simulated.",
1508 : cMO_VentilatedSlab,
1509 0 : state.dataVentilatedSlab->VentSlab(RadNum).Name));
1510 : }
1511 : }
1512 :
1513 1 : if (!state.dataGlobal->SysSizingCalc && state.dataVentilatedSlab->MySizeFlag(Item) && !state.dataVentilatedSlab->MyPlantScanFlag(Item)) {
1514 :
1515 1 : SizeVentilatedSlab(state, Item);
1516 :
1517 1 : state.dataVentilatedSlab->MySizeFlag(Item) = false;
1518 : }
1519 :
1520 1 : int InNode = ventSlab.ReturnAirNode;
1521 1 : int OutNode = ventSlab.RadInNode;
1522 1 : int OutsideAirNode = ventSlab.OutsideAirNode;
1523 :
1524 : // Do the one time initializations
1525 1 : if (state.dataGlobal->BeginEnvrnFlag && state.dataVentilatedSlab->MyEnvrnFlag(Item) && !state.dataVentilatedSlab->MyPlantScanFlag(Item)) {
1526 :
1527 : // Coil Part
1528 0 : RhoAir = state.dataEnvrn->StdRhoAir;
1529 :
1530 0 : if (state.dataVentilatedSlab->NumOfVentSlabs > 0) {
1531 0 : for (auto &e : state.dataVentilatedSlab->VentSlab) {
1532 0 : e.ZeroVentSlabSourceSumHATsurf = 0.0;
1533 0 : e.RadHeatingPower = 0.0;
1534 0 : e.RadHeatingEnergy = 0.0;
1535 0 : e.RadCoolingPower = 0.0;
1536 0 : e.RadCoolingEnergy = 0.0;
1537 0 : e.QRadSysSrcAvg = 0.0;
1538 0 : e.LastQRadSysSrc = 0.0;
1539 0 : e.LastSysTimeElapsed = 0.0;
1540 0 : e.LastTimeStepSys = 0.0;
1541 0 : }
1542 : }
1543 :
1544 : // set the initial Temperature of Return Air
1545 :
1546 : // set the mass flow rates from the input volume flow rates
1547 0 : ventSlab.MaxAirMassFlow = RhoAir * ventSlab.MaxAirVolFlow;
1548 0 : ventSlab.OutAirMassFlow = RhoAir * ventSlab.OutAirVolFlow;
1549 0 : ventSlab.MinOutAirMassFlow = RhoAir * ventSlab.MinOutAirVolFlow;
1550 0 : if (ventSlab.OutAirMassFlow > ventSlab.MaxAirMassFlow) {
1551 0 : ventSlab.OutAirMassFlow = ventSlab.MaxAirMassFlow;
1552 0 : ventSlab.MinOutAirMassFlow = ventSlab.OutAirMassFlow * (ventSlab.MinOutAirVolFlow / ventSlab.OutAirVolFlow);
1553 0 : ShowWarningError(state,
1554 0 : format("Outdoor air mass flow rate higher than unit flow rate, reset to unit flow rate for {}", ventSlab.Name));
1555 : }
1556 :
1557 : // set the node max and min mass flow rates
1558 0 : state.dataLoopNodes->Node(OutsideAirNode).MassFlowRateMax = ventSlab.OutAirMassFlow;
1559 0 : state.dataLoopNodes->Node(OutsideAirNode).MassFlowRateMin = 0.0;
1560 :
1561 0 : state.dataLoopNodes->Node(OutNode).MassFlowRateMax = ventSlab.MaxAirMassFlow;
1562 0 : state.dataLoopNodes->Node(OutNode).MassFlowRateMin = 0.0;
1563 :
1564 0 : state.dataLoopNodes->Node(InNode).MassFlowRateMax = ventSlab.MaxAirMassFlow;
1565 0 : state.dataLoopNodes->Node(InNode).MassFlowRateMin = 0.0;
1566 :
1567 0 : if (ventSlab.heatingCoilPresent) { // Only initialize these if a heating coil is actually present
1568 :
1569 0 : if (ventSlab.heatingCoilType == DataPlant::PlantEquipmentType::CoilWaterSimpleHeating &&
1570 0 : !state.dataVentilatedSlab->MyPlantScanFlag(Item)) {
1571 0 : rho = state.dataPlnt->PlantLoop(ventSlab.HWPlantLoc.loopNum).glycol->getDensity(state, Constant::HWInitConvTemp, RoutineName);
1572 :
1573 0 : ventSlab.MaxHotWaterFlow = rho * ventSlab.MaxVolHotWaterFlow;
1574 0 : ventSlab.MinHotWaterFlow = rho * ventSlab.MinVolHotWaterFlow;
1575 :
1576 0 : PlantUtilities::InitComponentNodes(
1577 : state, ventSlab.MinHotWaterFlow, ventSlab.MaxHotWaterFlow, ventSlab.HotControlNode, ventSlab.HotCoilOutNodeNum);
1578 : }
1579 0 : if (ventSlab.heatingCoilType == DataPlant::PlantEquipmentType::CoilSteamAirHeating &&
1580 0 : !state.dataVentilatedSlab->MyPlantScanFlag(Item)) {
1581 0 : TempSteamIn = 100.00;
1582 0 : SteamDensity = Fluid::GetSteam(state)->getSatDensity(state, TempSteamIn, 1.0, RoutineName);
1583 0 : ventSlab.MaxHotSteamFlow = SteamDensity * ventSlab.MaxVolHotSteamFlow;
1584 0 : ventSlab.MinHotSteamFlow = SteamDensity * ventSlab.MinVolHotSteamFlow;
1585 :
1586 0 : PlantUtilities::InitComponentNodes(
1587 : state, ventSlab.MinHotSteamFlow, ventSlab.MaxHotSteamFlow, ventSlab.HotControlNode, ventSlab.HotCoilOutNodeNum);
1588 : }
1589 : } //(VentSlab(Item)%HCoilPresent)
1590 :
1591 0 : if (ventSlab.coolingCoilPresent && !state.dataVentilatedSlab->MyPlantScanFlag(Item)) {
1592 : // Only initialize these if a cooling coil is actually present
1593 0 : if ((ventSlab.coolingCoilType == DataPlant::PlantEquipmentType::CoilWaterCooling) ||
1594 0 : (ventSlab.coolingCoilType == DataPlant::PlantEquipmentType::CoilWaterDetailedFlatCooling)) {
1595 0 : rho = state.dataPlnt->PlantLoop(ventSlab.CWPlantLoc.loopNum).glycol->getDensity(state, Constant::CWInitConvTemp, RoutineName);
1596 0 : ventSlab.MaxColdWaterFlow = rho * ventSlab.MaxVolColdWaterFlow;
1597 0 : ventSlab.MinColdWaterFlow = rho * ventSlab.MinVolColdWaterFlow;
1598 0 : PlantUtilities::InitComponentNodes(
1599 : state, ventSlab.MinColdWaterFlow, ventSlab.MaxColdWaterFlow, ventSlab.ColdControlNode, ventSlab.ColdCoilOutNodeNum);
1600 : }
1601 : }
1602 :
1603 0 : state.dataVentilatedSlab->MyEnvrnFlag(Item) = false;
1604 :
1605 : } // ...end start of environment inits
1606 :
1607 1 : if (!state.dataGlobal->BeginEnvrnFlag) {
1608 :
1609 1 : state.dataVentilatedSlab->MyEnvrnFlag(Item) = true;
1610 : }
1611 :
1612 : // These initializations are done every iteration...
1613 1 : AirRelNode = ventSlab.AirReliefNode;
1614 :
1615 : // First, set the flow conditions up so that there is flow through the ventilated
1616 : // slab system(this will be shut down if the system is not available or there
1617 : // is no load
1618 1 : state.dataLoopNodes->Node(InNode).MassFlowRate = ventSlab.MaxAirMassFlow;
1619 1 : state.dataLoopNodes->Node(InNode).MassFlowRateMaxAvail = ventSlab.MaxAirMassFlow;
1620 1 : state.dataLoopNodes->Node(InNode).MassFlowRateMinAvail = ventSlab.MaxAirMassFlow;
1621 1 : state.dataLoopNodes->Node(OutNode).MassFlowRate = ventSlab.MaxAirMassFlow;
1622 1 : state.dataLoopNodes->Node(OutNode).MassFlowRateMaxAvail = ventSlab.MaxAirMassFlow;
1623 1 : state.dataLoopNodes->Node(OutNode).MassFlowRateMinAvail = ventSlab.MaxAirMassFlow;
1624 1 : state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate = ventSlab.OutAirMassFlow;
1625 1 : state.dataLoopNodes->Node(OutsideAirNode).MassFlowRateMaxAvail = ventSlab.OutAirMassFlow;
1626 1 : state.dataLoopNodes->Node(OutsideAirNode).MassFlowRateMinAvail = ventSlab.OutAirMassFlow;
1627 1 : state.dataLoopNodes->Node(AirRelNode).MassFlowRate = ventSlab.OutAirMassFlow;
1628 1 : state.dataLoopNodes->Node(AirRelNode).MassFlowRateMaxAvail = ventSlab.OutAirMassFlow;
1629 1 : state.dataLoopNodes->Node(AirRelNode).MassFlowRateMinAvail = ventSlab.OutAirMassFlow;
1630 :
1631 : // Initialize the relief air (same as inlet conditions to the Ventilated Slab ..
1632 : // Note that mass flow rates will be taken care of later.
1633 1 : state.dataLoopNodes->Node(AirRelNode) = state.dataLoopNodes->Node(InNode);
1634 1 : state.dataVentilatedSlab->OAMassFlowRate = 0.0;
1635 :
1636 : // Just in case the system is off and conditions do not get sent through
1637 : // the system for some reason, set the outlet conditions equal to the inlet
1638 : // conditions of the ventilated slab mixer
1639 1 : state.dataLoopNodes->Node(OutNode).Temp = state.dataLoopNodes->Node(InNode).Temp;
1640 1 : state.dataLoopNodes->Node(OutNode).Press = state.dataLoopNodes->Node(InNode).Press;
1641 1 : state.dataLoopNodes->Node(OutNode).HumRat = state.dataLoopNodes->Node(InNode).HumRat;
1642 1 : state.dataLoopNodes->Node(OutNode).Enthalpy = state.dataLoopNodes->Node(InNode).Enthalpy;
1643 :
1644 : // These initializations only need to be done once at the start of the iterations...
1645 1 : if (state.dataGlobal->BeginTimeStepFlag && FirstHVACIteration) {
1646 : // Initialize the outside air conditions...
1647 0 : state.dataLoopNodes->Node(OutsideAirNode).Temp = state.dataLoopNodes->Node(OutsideAirNode).OutAirDryBulb;
1648 0 : state.dataLoopNodes->Node(OutsideAirNode).HumRat = state.dataEnvrn->OutHumRat;
1649 0 : state.dataLoopNodes->Node(OutsideAirNode).Press = state.dataEnvrn->OutBaroPress;
1650 :
1651 : // The first pass through in a particular time step
1652 0 : int ZoneNum = ventSlab.ZonePtr;
1653 0 : ventSlab.ZeroVentSlabSourceSumHATsurf =
1654 0 : state.dataHeatBal->Zone(ZoneNum).sumHATsurf(state); // Set this to figure what part of the load the radiant system meets
1655 0 : ventSlab.QRadSysSrcAvg = 0.0; // Initialize this variable to zero (radiant system defaults to off)
1656 0 : ventSlab.LastQRadSysSrc = 0.0; // At the start of a time step, reset to zero so average calculation can begin again
1657 0 : ventSlab.LastSysTimeElapsed = 0.0; // At the start of a time step, reset to zero so average calculation can begin again
1658 0 : ventSlab.LastTimeStepSys = 0.0; // At the start of a time step, reset to zero so average calculation can begin again
1659 : }
1660 1 : }
1661 :
1662 1 : void SizeVentilatedSlab(EnergyPlusData &state, int const Item)
1663 : {
1664 :
1665 : // SUBROUTINE INFORMATION:
1666 : // AUTHOR Young Tae Chae, Rick Strand
1667 : // DATE WRITTEN June 2008
1668 : // MODIFIED July 2013 Daeho Kang, add component sizing table entries
1669 : // July 2014, B. Nigusse, added scalable sizing
1670 :
1671 : // PURPOSE OF THIS SUBROUTINE:
1672 : // This subroutine is for sizing Ventilated Slab components for which flow rates have not been
1673 : // specified in the input.
1674 :
1675 : // METHODOLOGY EMPLOYED:
1676 : // Obtains flow rates from the zone sizing arrays and plant sizing data.
1677 :
1678 : // SUBROUTINE PARAMETER DEFINITIONS:
1679 : static constexpr std::string_view RoutineName("SizeVentilatedSlab");
1680 :
1681 1 : int CurZoneEqNum = state.dataSize->CurZoneEqNum;
1682 1 : auto &ventSlab = state.dataVentilatedSlab->VentSlab(Item);
1683 :
1684 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1685 : bool ErrorsFound;
1686 : Real64 DesCoilLoad;
1687 : Real64 TempSteamIn;
1688 : Real64 EnthSteamInDry;
1689 : Real64 EnthSteamOutWet;
1690 : Real64 LatentHeatSteam;
1691 : Real64 SteamDensity;
1692 1 : std::string CoolingCoilName;
1693 1 : std::string CoolingCoilType;
1694 : Real64 rho;
1695 : Real64 Cp;
1696 : Real64 MaxAirVolFlowDes; // Autosized maximum air flow for reporting
1697 : Real64 MaxAirVolFlowUser; // Hardsized maximum air flow for reporting
1698 : Real64 OutAirVolFlowDes; // Autosized outdoor air flow for reporting
1699 : Real64 OutAirVolFlowUser; // Hardsized outdoor air flow for reporting
1700 : Real64 MinOutAirVolFlowDes; // Autosized minimum outdoor air flow for reporting
1701 : Real64 MinOutAirVolFlowUser; // Hardsized minimum outdoor air flow for reporting
1702 : Real64 MaxVolHotWaterFlowDes; // Autosized maximum hot water flow for reporting
1703 : Real64 MaxVolHotWaterFlowUser; // Hardsized maximum hot water flow for reporting
1704 : Real64 MaxVolHotSteamFlowDes; // Autosized maximum hot steam flow for reporting
1705 : Real64 MaxVolHotSteamFlowUser; // Hardsized maximum hot steam flow for reporting
1706 : Real64 MaxVolColdWaterFlowDes; // Autosized maximum cold water flow for reporting
1707 : Real64 MaxVolColdWaterFlowUser; // Hardsized maximum cold water flow for reporting
1708 1 : std::string CompName; // component name
1709 1 : std::string CompType; // component type
1710 1 : std::string SizingString; // input field sizing description (e.g., Nominal Capacity)
1711 : Real64 TempSize; // autosized value of coil input field
1712 1 : int FieldNum = 2; // IDD numeric field number where input field description is found
1713 : int SizingMethod; // Integer representation of sizing method name (e.g., CoolingAirflowSizing, HeatingAirflowSizing, CoolingCapacitySizing,
1714 : // HeatingCapacitySizing, etc.)
1715 : bool PrintFlag; // TRUE when sizing information is reported in the eio file
1716 : int zoneHVACIndex; // index of zoneHVAC equipment sizing specification
1717 : Real64 CoolingAirVolFlowScalable; // cooling airvolume for rate determined using scalable sizing method
1718 : Real64 HeatingAirVolFlowScalable; // heating airvolume for rate determined using scalable sizing method
1719 : bool DoWaterCoilSizing; // if TRUE do water coil sizing calculation
1720 : Real64 WaterCoilSizDeltaT; // water coil deltaT for design water flow rate autosizing
1721 :
1722 1 : WaterCoilSizDeltaT = 0.0;
1723 1 : ErrorsFound = false;
1724 1 : MaxAirVolFlowDes = 0.0;
1725 1 : MaxAirVolFlowUser = 0.0;
1726 1 : OutAirVolFlowDes = 0.0;
1727 1 : OutAirVolFlowUser = 0.0;
1728 1 : MinOutAirVolFlowDes = 0.0;
1729 1 : MinOutAirVolFlowUser = 0.0;
1730 1 : MaxVolHotWaterFlowDes = 0.0;
1731 1 : MaxVolHotWaterFlowUser = 0.0;
1732 1 : MaxVolHotSteamFlowDes = 0.0;
1733 1 : MaxVolHotSteamFlowUser = 0.0;
1734 1 : MaxVolColdWaterFlowDes = 0.0;
1735 1 : MaxVolColdWaterFlowUser = 0.0;
1736 1 : CoolingAirVolFlowScalable = 0.0;
1737 1 : HeatingAirVolFlowScalable = 0.0;
1738 1 : state.dataSize->DataScalableSizingON = false;
1739 1 : state.dataSize->DataScalableCapSizingON = false;
1740 1 : CompType = cMO_VentilatedSlab;
1741 1 : CompName = ventSlab.Name;
1742 1 : state.dataSize->DataZoneNumber = ventSlab.ZonePtr;
1743 1 : state.dataSize->DataFanType = ventSlab.fanType;
1744 1 : state.dataSize->DataFanIndex = ventSlab.Fan_Index;
1745 : // ventilated slab unit is always blow thru
1746 1 : state.dataSize->DataFanPlacement = HVAC::FanPlace::BlowThru;
1747 :
1748 1 : if (ventSlab.HVACSizingIndex > 0) {
1749 0 : zoneHVACIndex = ventSlab.HVACSizingIndex;
1750 : // N1 , \field Maximum Supply Air Flow Rate
1751 0 : FieldNum = 1;
1752 0 : PrintFlag = true;
1753 0 : SizingString = state.dataVentilatedSlab->VentSlabNumericFields(Item).FieldNames(FieldNum) + " [m3/s]";
1754 0 : auto &zoneEqSizing = state.dataSize->ZoneEqSizing(CurZoneEqNum);
1755 0 : if (state.dataSize->ZoneHVACSizing(zoneHVACIndex).CoolingSAFMethod > 0) {
1756 0 : SizingMethod = HVAC::CoolingAirflowSizing;
1757 0 : int SAFMethod = state.dataSize->ZoneHVACSizing(zoneHVACIndex).CoolingSAFMethod;
1758 0 : zoneEqSizing.SizingMethod(SizingMethod) = SAFMethod;
1759 0 : if (SAFMethod == DataSizing::None || SAFMethod == DataSizing::SupplyAirFlowRate || SAFMethod == DataSizing::FlowPerFloorArea ||
1760 : SAFMethod == DataSizing::FractionOfAutosizedCoolingAirflow) {
1761 0 : if (SAFMethod == DataSizing::SupplyAirFlowRate) {
1762 0 : if (state.dataSize->ZoneHVACSizing(zoneHVACIndex).MaxCoolAirVolFlow > 0.0) {
1763 0 : zoneEqSizing.AirVolFlow = state.dataSize->ZoneHVACSizing(zoneHVACIndex).MaxCoolAirVolFlow;
1764 0 : zoneEqSizing.SystemAirFlow = true;
1765 : }
1766 0 : TempSize = state.dataSize->ZoneHVACSizing(zoneHVACIndex).MaxCoolAirVolFlow;
1767 0 : } else if (SAFMethod == DataSizing::FlowPerFloorArea) {
1768 0 : zoneEqSizing.SystemAirFlow = true;
1769 0 : zoneEqSizing.AirVolFlow = state.dataSize->ZoneHVACSizing(zoneHVACIndex).MaxCoolAirVolFlow *
1770 0 : state.dataHeatBal->Zone(state.dataSize->DataZoneNumber).FloorArea;
1771 0 : TempSize = zoneEqSizing.AirVolFlow;
1772 0 : state.dataSize->DataScalableSizingON = true;
1773 0 : } else if (SAFMethod == DataSizing::FractionOfAutosizedCoolingAirflow) {
1774 0 : state.dataSize->DataFracOfAutosizedCoolingAirflow = state.dataSize->ZoneHVACSizing(zoneHVACIndex).MaxCoolAirVolFlow;
1775 0 : TempSize = DataSizing::AutoSize;
1776 0 : state.dataSize->DataScalableSizingON = true;
1777 : } else {
1778 0 : TempSize = state.dataSize->ZoneHVACSizing(zoneHVACIndex).MaxCoolAirVolFlow;
1779 : }
1780 0 : CoolingAirFlowSizer sizingCoolingAirFlow;
1781 0 : std::string stringOverride = "Maximum Air Flow Rate [m3/s]";
1782 0 : if (state.dataGlobal->isEpJSON) {
1783 0 : stringOverride = "maximum_air_flow_rate [m3/s]";
1784 : }
1785 0 : sizingCoolingAirFlow.overrideSizingString(stringOverride);
1786 : // sizingCoolingAirFlow.setHVACSizingIndexData(FanCoil(FanCoilNum).HVACSizingIndex);
1787 0 : sizingCoolingAirFlow.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
1788 0 : CoolingAirVolFlowScalable = sizingCoolingAirFlow.size(state, TempSize, ErrorsFound);
1789 :
1790 0 : } else if (SAFMethod == DataSizing::FlowPerCoolingCapacity) {
1791 0 : TempSize = DataSizing::AutoSize;
1792 0 : PrintFlag = false;
1793 0 : state.dataSize->DataScalableSizingON = true;
1794 0 : state.dataSize->DataFlowUsedForSizing = state.dataSize->FinalZoneSizing(CurZoneEqNum).DesCoolVolFlow;
1795 0 : CoolingCapacitySizer sizerCoolingCapacity;
1796 0 : sizerCoolingCapacity.overrideSizingString(SizingString);
1797 0 : sizerCoolingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
1798 0 : state.dataSize->DataAutosizedCoolingCapacity = sizerCoolingCapacity.size(state, TempSize, ErrorsFound);
1799 0 : state.dataSize->DataFlowPerCoolingCapacity = state.dataSize->ZoneHVACSizing(zoneHVACIndex).MaxCoolAirVolFlow;
1800 0 : PrintFlag = true;
1801 0 : TempSize = DataSizing::AutoSize;
1802 0 : CoolingAirFlowSizer sizingCoolingAirFlow;
1803 0 : std::string stringOverride = "Maximum Air Flow Rate [m3/s]";
1804 0 : if (state.dataGlobal->isEpJSON) {
1805 0 : stringOverride = "maximum_air_flow_rate [m3/s]";
1806 : }
1807 0 : sizingCoolingAirFlow.overrideSizingString(stringOverride);
1808 : // sizingCoolingAirFlow.setHVACSizingIndexData(FanCoil(FanCoilNum).HVACSizingIndex);
1809 0 : sizingCoolingAirFlow.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
1810 0 : CoolingAirVolFlowScalable = sizingCoolingAirFlow.size(state, TempSize, ErrorsFound);
1811 0 : }
1812 : }
1813 0 : if (state.dataSize->ZoneHVACSizing(zoneHVACIndex).HeatingSAFMethod > 0) {
1814 0 : SizingMethod = HVAC::HeatingAirflowSizing;
1815 0 : int SAFMethod = state.dataSize->ZoneHVACSizing(zoneHVACIndex).HeatingSAFMethod;
1816 0 : zoneEqSizing.SizingMethod(SizingMethod) = SAFMethod;
1817 0 : if (SAFMethod == DataSizing::None || SAFMethod == DataSizing::SupplyAirFlowRate || SAFMethod == DataSizing::FlowPerFloorArea ||
1818 : SAFMethod == DataSizing::FractionOfAutosizedHeatingAirflow) {
1819 0 : if (SAFMethod == DataSizing::SupplyAirFlowRate) {
1820 0 : if (state.dataSize->ZoneHVACSizing(zoneHVACIndex).MaxHeatAirVolFlow > 0.0) {
1821 0 : zoneEqSizing.AirVolFlow = state.dataSize->ZoneHVACSizing(zoneHVACIndex).MaxHeatAirVolFlow;
1822 0 : zoneEqSizing.SystemAirFlow = true;
1823 : }
1824 0 : TempSize = state.dataSize->ZoneHVACSizing(zoneHVACIndex).MaxHeatAirVolFlow;
1825 0 : } else if (SAFMethod == DataSizing::FlowPerFloorArea) {
1826 0 : zoneEqSizing.SystemAirFlow = true;
1827 0 : zoneEqSizing.AirVolFlow = state.dataSize->ZoneHVACSizing(zoneHVACIndex).MaxHeatAirVolFlow *
1828 0 : state.dataHeatBal->Zone(state.dataSize->DataZoneNumber).FloorArea;
1829 0 : TempSize = zoneEqSizing.AirVolFlow;
1830 0 : state.dataSize->DataScalableSizingON = true;
1831 0 : } else if (SAFMethod == DataSizing::FractionOfAutosizedHeatingAirflow) {
1832 0 : state.dataSize->DataFracOfAutosizedHeatingAirflow = state.dataSize->ZoneHVACSizing(zoneHVACIndex).MaxHeatAirVolFlow;
1833 0 : TempSize = DataSizing::AutoSize;
1834 0 : state.dataSize->DataScalableSizingON = true;
1835 : } else {
1836 0 : TempSize = state.dataSize->ZoneHVACSizing(zoneHVACIndex).MaxHeatAirVolFlow;
1837 : }
1838 0 : HeatingAirFlowSizer sizingHeatingAirFlow;
1839 0 : sizingHeatingAirFlow.overrideSizingString(SizingString);
1840 : // sizingHeatingAirFlow.setHVACSizingIndexData(FanCoil(FanCoilNum).HVACSizingIndex);
1841 0 : sizingHeatingAirFlow.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
1842 0 : HeatingAirVolFlowScalable = sizingHeatingAirFlow.size(state, TempSize, ErrorsFound);
1843 0 : } else if (SAFMethod == DataSizing::FlowPerHeatingCapacity) {
1844 0 : TempSize = DataSizing::AutoSize;
1845 0 : PrintFlag = false;
1846 0 : state.dataSize->DataScalableSizingON = true;
1847 0 : state.dataSize->DataFlowUsedForSizing = state.dataSize->FinalZoneSizing(CurZoneEqNum).DesHeatVolFlow;
1848 0 : HeatingCapacitySizer sizerHeatingCapacity;
1849 0 : sizerHeatingCapacity.overrideSizingString(SizingString);
1850 0 : sizerHeatingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
1851 0 : state.dataSize->DataAutosizedHeatingCapacity = sizerHeatingCapacity.size(state, TempSize, ErrorsFound);
1852 0 : state.dataSize->DataFlowPerHeatingCapacity = state.dataSize->ZoneHVACSizing(zoneHVACIndex).MaxHeatAirVolFlow;
1853 0 : PrintFlag = true;
1854 0 : TempSize = DataSizing::AutoSize;
1855 0 : HeatingAirFlowSizer sizingHeatingAirFlow;
1856 0 : sizingHeatingAirFlow.overrideSizingString(SizingString);
1857 : // sizingHeatingAirFlow.setHVACSizingIndexData(FanCoil(FanCoilNum).HVACSizingIndex);
1858 0 : sizingHeatingAirFlow.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
1859 0 : HeatingAirVolFlowScalable = sizingHeatingAirFlow.size(state, TempSize, ErrorsFound);
1860 0 : }
1861 : }
1862 : // DataScalableSizingON = false;
1863 0 : ventSlab.MaxAirVolFlow = max(CoolingAirVolFlowScalable, HeatingAirVolFlowScalable);
1864 : } else {
1865 : // no scalble sizing method has been specified. Sizing proceeds using the method
1866 : // specified in the zoneHVAC object
1867 : // N1 , \field Maximum Supply Air Flow Rate
1868 1 : FieldNum = 1;
1869 1 : PrintFlag = true;
1870 1 : SizingString = state.dataVentilatedSlab->VentSlabNumericFields(Item).FieldNames(FieldNum) + " [m3/s]";
1871 1 : TempSize = ventSlab.MaxAirVolFlow;
1872 1 : SystemAirFlowSizer sizerSystemAirFlow;
1873 1 : sizerSystemAirFlow.overrideSizingString(SizingString);
1874 : // sizerSystemAirFlow.setHVACSizingIndexData(FanCoil(FanCoilNum).HVACSizingIndex);
1875 1 : sizerSystemAirFlow.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
1876 1 : ventSlab.MaxAirVolFlow = sizerSystemAirFlow.size(state, TempSize, ErrorsFound);
1877 1 : }
1878 :
1879 1 : bool IsAutoSize = false;
1880 1 : if (ventSlab.OutAirVolFlow == DataSizing::AutoSize) {
1881 0 : IsAutoSize = true;
1882 : }
1883 1 : if (CurZoneEqNum > 0) {
1884 1 : if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) {
1885 1 : if (ventSlab.OutAirVolFlow > 0.0) {
1886 1 : BaseSizer::reportSizerOutput(
1887 : state, cMO_VentilatedSlab, ventSlab.Name, "User-Specified Maximum Outdoor Air Flow Rate [m3/s]", ventSlab.OutAirVolFlow);
1888 : }
1889 : } else { // Autosize or hard-size with sizing run
1890 0 : CheckZoneSizing(state, cMO_VentilatedSlab, ventSlab.Name);
1891 0 : OutAirVolFlowDes = ventSlab.MaxAirVolFlow;
1892 0 : if (IsAutoSize) {
1893 0 : ventSlab.OutAirVolFlow = OutAirVolFlowDes;
1894 0 : BaseSizer::reportSizerOutput(
1895 : state, cMO_VentilatedSlab, ventSlab.Name, "Design Size Maximum Outdoor Air Flow Rate [m3/s]", OutAirVolFlowDes);
1896 : } else {
1897 0 : if (ventSlab.OutAirVolFlow > 0.0 && OutAirVolFlowDes > 0.0) {
1898 0 : OutAirVolFlowUser = ventSlab.OutAirVolFlow;
1899 0 : BaseSizer::reportSizerOutput(state,
1900 : cMO_VentilatedSlab,
1901 : ventSlab.Name,
1902 : "Design Size Maximum Outdoor Air Flow Rate [m3/s]",
1903 : OutAirVolFlowDes,
1904 : "User-Specified Maximum Outdoor Air Flow Rate [m3/s]",
1905 : OutAirVolFlowUser);
1906 0 : if (state.dataGlobal->DisplayExtraWarnings) {
1907 0 : if ((std::abs(OutAirVolFlowDes - OutAirVolFlowUser) / OutAirVolFlowUser) > state.dataSize->AutoVsHardSizingThreshold) {
1908 0 : ShowMessage(state,
1909 0 : format("SizeVentilatedSlab: Potential issue with equipment sizing for ZoneHVAC:VentilatedSlab = \"{}\".",
1910 0 : ventSlab.Name));
1911 0 : ShowContinueError(state, format("User-Specified Maximum Outdoor Air Flow Rate of {:.5R} [m3/s]", OutAirVolFlowUser));
1912 0 : ShowContinueError(
1913 0 : state, format("differs from Design Size Maximum Outdoor Air Flow Rate of {:.5R} [m3/s]", OutAirVolFlowDes));
1914 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
1915 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
1916 : }
1917 : }
1918 : }
1919 : }
1920 : }
1921 : }
1922 :
1923 1 : IsAutoSize = false;
1924 1 : if (ventSlab.MinOutAirVolFlow == DataSizing::AutoSize) {
1925 0 : IsAutoSize = true;
1926 : }
1927 1 : if (CurZoneEqNum > 0) {
1928 1 : if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) {
1929 1 : if (ventSlab.MinOutAirVolFlow > 0.0) {
1930 1 : BaseSizer::reportSizerOutput(
1931 : state, cMO_VentilatedSlab, ventSlab.Name, "User-Specified Minimum Outdoor Air Flow Rate [m3/s]", ventSlab.MinOutAirVolFlow);
1932 : }
1933 : } else {
1934 0 : CheckZoneSizing(state, cMO_VentilatedSlab, ventSlab.Name);
1935 0 : MinOutAirVolFlowDes = min(state.dataSize->FinalZoneSizing(CurZoneEqNum).MinOA, ventSlab.MaxAirVolFlow);
1936 0 : if (MinOutAirVolFlowDes < HVAC::SmallAirVolFlow) {
1937 0 : MinOutAirVolFlowDes = 0.0;
1938 : }
1939 0 : if (IsAutoSize) {
1940 0 : ventSlab.MinOutAirVolFlow = MinOutAirVolFlowDes;
1941 0 : BaseSizer::reportSizerOutput(
1942 : state, cMO_VentilatedSlab, ventSlab.Name, "Design Size Minimum Outdoor Air Flow Rate [m3/s]", MinOutAirVolFlowDes);
1943 : } else { // Hard-size with sizing data
1944 0 : if (ventSlab.MinOutAirVolFlow > 0.0 && MinOutAirVolFlowDes > 0.0) {
1945 0 : MinOutAirVolFlowUser = ventSlab.MinOutAirVolFlow;
1946 0 : BaseSizer::reportSizerOutput(state,
1947 : cMO_VentilatedSlab,
1948 : ventSlab.Name,
1949 : "Design Size Minimum Outdoor Air Flow Rate [m3/s]",
1950 : MinOutAirVolFlowDes,
1951 : "User-Specified Minimum Outdoor Air Flow Rate [m3/s]",
1952 : MinOutAirVolFlowUser);
1953 0 : if (state.dataGlobal->DisplayExtraWarnings) {
1954 0 : if ((std::abs(MinOutAirVolFlowDes - MinOutAirVolFlowUser) / MinOutAirVolFlowUser) >
1955 0 : state.dataSize->AutoVsHardSizingThreshold) {
1956 0 : ShowMessage(state,
1957 0 : format("SizeVentilatedSlab: Potential issue with equipment sizing for ZoneHVAC:VentilatedSlab = \"{}\".",
1958 0 : ventSlab.Name));
1959 0 : ShowContinueError(state,
1960 0 : format("User-Specified Minimum Outdoor Air Flow Rate of {:.5R} [m3/s]", MinOutAirVolFlowUser));
1961 0 : ShowContinueError(
1962 0 : state, format("differs from Design Size Minimum Outdoor Air Flow Rate of {:.5R} [m3/s]", MinOutAirVolFlowDes));
1963 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
1964 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
1965 : }
1966 : }
1967 : }
1968 : }
1969 : }
1970 : }
1971 :
1972 1 : IsAutoSize = false;
1973 1 : if (ventSlab.MaxVolHotWaterFlow == DataSizing::AutoSize) {
1974 0 : IsAutoSize = true;
1975 : }
1976 1 : if (ventSlab.hCoilType == HeatingCoilType::Water) {
1977 :
1978 1 : if (CurZoneEqNum > 0) {
1979 1 : if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) {
1980 1 : if (ventSlab.MaxVolHotWaterFlow > 0.0) {
1981 1 : BaseSizer::reportSizerOutput(
1982 : state, cMO_VentilatedSlab, ventSlab.Name, "User-Specified Maximum Hot Water Flow [m3/s]", ventSlab.MaxVolHotWaterFlow);
1983 : }
1984 : } else { // Autosize or hard-size with sizing run
1985 0 : CheckZoneSizing(state, cMO_VentilatedSlab, ventSlab.Name);
1986 :
1987 0 : int CoilWaterInletNode = WaterCoils::GetCoilWaterInletNode(state, "Coil:Heating:Water", ventSlab.heatingCoilName, ErrorsFound);
1988 0 : int CoilWaterOutletNode = WaterCoils::GetCoilWaterOutletNode(state, "Coil:Heating:Water", ventSlab.heatingCoilName, ErrorsFound);
1989 0 : if (IsAutoSize) {
1990 0 : int PltSizHeatNum = PlantUtilities::MyPlantSizingIndex(
1991 : state, "Coil:Heating:Water", ventSlab.heatingCoilName, CoilWaterInletNode, CoilWaterOutletNode, ErrorsFound);
1992 0 : int CoilNum = WaterCoils::GetWaterCoilIndex(state, "COIL:HEATING:WATER", ventSlab.heatingCoilName, ErrorsFound);
1993 0 : if (state.dataWaterCoils->WaterCoil(CoilNum).UseDesignWaterDeltaTemp) {
1994 0 : WaterCoilSizDeltaT = state.dataWaterCoils->WaterCoil(CoilNum).DesignWaterDeltaTemp;
1995 0 : DoWaterCoilSizing = true;
1996 : } else {
1997 0 : if (PltSizHeatNum > 0) {
1998 0 : WaterCoilSizDeltaT = state.dataSize->PlantSizData(PltSizHeatNum).DeltaT;
1999 0 : DoWaterCoilSizing = true;
2000 : } else {
2001 0 : DoWaterCoilSizing = false;
2002 : // If there is no heating Plant Sizing object and autosizing was requested, issue fatal error message
2003 0 : ShowSevereError(state, "Autosizing of water flow requires a heating loop Sizing:Plant object");
2004 0 : ShowContinueError(state, format("Occurs in {} Object={}", cMO_VentilatedSlab, ventSlab.Name));
2005 0 : ErrorsFound = true;
2006 : }
2007 : }
2008 0 : if (DoWaterCoilSizing) {
2009 0 : if (state.dataSize->FinalZoneSizing(CurZoneEqNum).DesHeatMassFlow >= HVAC::SmallAirVolFlow) {
2010 0 : auto &zoneEqSizing = state.dataSize->ZoneEqSizing(CurZoneEqNum);
2011 0 : SizingMethod = HVAC::HeatingCapacitySizing;
2012 0 : if (ventSlab.HVACSizingIndex > 0) {
2013 0 : zoneHVACIndex = ventSlab.HVACSizingIndex;
2014 0 : int CapSizingMethod = state.dataSize->ZoneHVACSizing(zoneHVACIndex).HeatingCapMethod;
2015 0 : zoneEqSizing.SizingMethod(SizingMethod) = CapSizingMethod;
2016 0 : if (CapSizingMethod == DataSizing::HeatingDesignCapacity || CapSizingMethod == DataSizing::CapacityPerFloorArea ||
2017 : CapSizingMethod == DataSizing::FractionOfAutosizedHeatingCapacity) {
2018 0 : if (CapSizingMethod == DataSizing::HeatingDesignCapacity) {
2019 0 : if (state.dataSize->ZoneHVACSizing(zoneHVACIndex).ScaledHeatingCapacity > 0.0) {
2020 0 : zoneEqSizing.HeatingCapacity = true;
2021 0 : zoneEqSizing.DesHeatingLoad = state.dataSize->ZoneHVACSizing(zoneHVACIndex).ScaledHeatingCapacity;
2022 : } else {
2023 0 : state.dataSize->DataFlowUsedForSizing = state.dataSize->FinalZoneSizing(CurZoneEqNum).DesHeatVolFlow;
2024 : }
2025 0 : TempSize = state.dataSize->ZoneHVACSizing(zoneHVACIndex).ScaledHeatingCapacity;
2026 0 : } else if (CapSizingMethod == DataSizing::CapacityPerFloorArea) {
2027 0 : zoneEqSizing.HeatingCapacity = true;
2028 0 : zoneEqSizing.DesHeatingLoad = state.dataSize->ZoneHVACSizing(zoneHVACIndex).ScaledHeatingCapacity *
2029 0 : state.dataHeatBal->Zone(state.dataSize->DataZoneNumber).FloorArea;
2030 0 : state.dataSize->DataScalableCapSizingON = true;
2031 0 : } else if (CapSizingMethod == DataSizing::FractionOfAutosizedHeatingCapacity) {
2032 0 : state.dataSize->DataFracOfAutosizedHeatingCapacity =
2033 0 : state.dataSize->ZoneHVACSizing(zoneHVACIndex).ScaledHeatingCapacity;
2034 0 : state.dataSize->DataFlowUsedForSizing = state.dataSize->FinalZoneSizing(CurZoneEqNum).DesHeatVolFlow;
2035 0 : TempSize = DataSizing::AutoSize;
2036 0 : state.dataSize->DataScalableCapSizingON = true;
2037 : }
2038 : }
2039 0 : SizingString = "";
2040 0 : PrintFlag = false;
2041 0 : HeatingCapacitySizer sizerHeatingCapacity;
2042 0 : sizerHeatingCapacity.overrideSizingString(SizingString);
2043 0 : sizerHeatingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
2044 0 : DesCoilLoad = sizerHeatingCapacity.size(state, TempSize, ErrorsFound);
2045 0 : state.dataSize->DataScalableCapSizingON = false;
2046 0 : } else {
2047 0 : SizingString = "";
2048 0 : PrintFlag = false;
2049 0 : TempSize = DataSizing::AutoSize;
2050 0 : HeatingCapacitySizer sizerHeatingCapacity;
2051 0 : sizerHeatingCapacity.overrideSizingString(SizingString);
2052 0 : sizerHeatingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
2053 0 : DesCoilLoad = sizerHeatingCapacity.size(state, TempSize, ErrorsFound);
2054 0 : }
2055 0 : rho = state.dataPlnt->PlantLoop(ventSlab.HWPlantLoc.loopNum)
2056 0 : .glycol->getDensity(state, Constant::HWInitConvTemp, RoutineName);
2057 0 : Cp = state.dataPlnt->PlantLoop(ventSlab.HWPlantLoc.loopNum)
2058 0 : .glycol->getSpecificHeat(state, Constant::HWInitConvTemp, RoutineName);
2059 0 : MaxVolHotWaterFlowDes = DesCoilLoad / (WaterCoilSizDeltaT * Cp * rho);
2060 : } else {
2061 0 : MaxVolHotWaterFlowDes = 0.0;
2062 : }
2063 : }
2064 0 : ventSlab.MaxVolHotWaterFlow = MaxVolHotWaterFlowDes;
2065 0 : BaseSizer::reportSizerOutput(
2066 : state, cMO_VentilatedSlab, ventSlab.Name, "Design Size Maximum Hot Water Flow [m3/s]", MaxVolHotWaterFlowDes);
2067 : } else { // Hard-size with sizing data
2068 0 : if (ventSlab.MaxVolHotWaterFlow > 0.0 && MaxVolHotWaterFlowDes > 0.0) {
2069 0 : MaxVolHotWaterFlowUser = ventSlab.MaxVolHotWaterFlow;
2070 0 : BaseSizer::reportSizerOutput(state,
2071 : cMO_VentilatedSlab,
2072 : ventSlab.Name,
2073 : "Design Size Maximum Hot Water Flow [m3/s]",
2074 : MaxVolHotWaterFlowDes,
2075 : "User-Specified Maximum Hot Water Flow [m3/s]",
2076 : MaxVolHotWaterFlowUser);
2077 0 : if (state.dataGlobal->DisplayExtraWarnings) {
2078 0 : if ((std::abs(MaxVolHotWaterFlowDes - MaxVolHotWaterFlowUser) / MaxVolHotWaterFlowUser) >
2079 0 : state.dataSize->AutoVsHardSizingThreshold) {
2080 0 : ShowMessage(
2081 : state,
2082 0 : format("SizeVentilatedSlab: Potential issue with equipment sizing for ZoneHVAC:VentilatedSlab = \"{}\".",
2083 0 : ventSlab.Name));
2084 0 : ShowContinueError(state,
2085 0 : format("User-Specified Maximum Hot Water Flow of {:.5R} [m3/s]", MaxVolHotWaterFlowUser));
2086 0 : ShowContinueError(
2087 0 : state, format("differs from Design Size Maximum Hot Water Flow of {:.5R} [m3/s]", MaxVolHotWaterFlowDes));
2088 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
2089 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
2090 : }
2091 : }
2092 : }
2093 : }
2094 : }
2095 : }
2096 : } else {
2097 0 : ventSlab.MaxVolHotWaterFlow = 0.0;
2098 : }
2099 :
2100 1 : IsAutoSize = false;
2101 1 : if (ventSlab.MaxVolHotSteamFlow == DataSizing::AutoSize) {
2102 0 : IsAutoSize = true;
2103 : }
2104 1 : if (ventSlab.hCoilType == HeatingCoilType::Steam) {
2105 :
2106 0 : if (CurZoneEqNum > 0) {
2107 0 : if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) {
2108 0 : if (ventSlab.MaxVolHotSteamFlow > 0.0) {
2109 0 : BaseSizer::reportSizerOutput(
2110 : state, cMO_VentilatedSlab, ventSlab.Name, "User-Specified Maximum Steam Flow [m3/s]", ventSlab.MaxVolHotSteamFlow);
2111 : }
2112 : } else { // Autosize or hard-size with sizing run
2113 0 : CheckZoneSizing(state, "ZoneHVAC:VentilatedSlab", ventSlab.Name);
2114 :
2115 0 : int CoilSteamInletNode = SteamCoils::GetCoilSteamInletNode(state, "Coil:Heating:Steam", ventSlab.heatingCoilName, ErrorsFound);
2116 0 : int CoilSteamOutletNode = SteamCoils::GetCoilSteamOutletNode(state, "Coil:Heating:Steam", ventSlab.heatingCoilName, ErrorsFound);
2117 0 : if (IsAutoSize) {
2118 0 : int PltSizHeatNum = PlantUtilities::MyPlantSizingIndex(
2119 : state, "Coil:Heating:Steam", ventSlab.heatingCoilName, CoilSteamInletNode, CoilSteamOutletNode, ErrorsFound);
2120 0 : if (PltSizHeatNum > 0) {
2121 0 : if (state.dataSize->FinalZoneSizing(CurZoneEqNum).DesHeatMassFlow >= HVAC::SmallAirVolFlow) {
2122 0 : SizingMethod = HVAC::HeatingCapacitySizing;
2123 0 : if (ventSlab.HVACSizingIndex > 0) {
2124 0 : auto &zoneEqSizing = state.dataSize->ZoneEqSizing(CurZoneEqNum);
2125 0 : zoneHVACIndex = ventSlab.HVACSizingIndex;
2126 0 : int CapSizingMethod = state.dataSize->ZoneHVACSizing(zoneHVACIndex).HeatingCapMethod;
2127 0 : zoneEqSizing.SizingMethod(SizingMethod) = CapSizingMethod;
2128 0 : if (CapSizingMethod == DataSizing::HeatingDesignCapacity || CapSizingMethod == DataSizing::CapacityPerFloorArea ||
2129 : CapSizingMethod == DataSizing::FractionOfAutosizedHeatingCapacity) {
2130 0 : if (CapSizingMethod == DataSizing::HeatingDesignCapacity) {
2131 0 : if (state.dataSize->ZoneHVACSizing(zoneHVACIndex).ScaledHeatingCapacity > 0.0) {
2132 0 : zoneEqSizing.HeatingCapacity = true;
2133 0 : zoneEqSizing.DesHeatingLoad = state.dataSize->ZoneHVACSizing(zoneHVACIndex).ScaledHeatingCapacity;
2134 : } else {
2135 0 : state.dataSize->DataFlowUsedForSizing = state.dataSize->FinalZoneSizing(CurZoneEqNum).DesHeatVolFlow;
2136 : }
2137 0 : TempSize = state.dataSize->ZoneHVACSizing(zoneHVACIndex).ScaledHeatingCapacity;
2138 0 : } else if (CapSizingMethod == DataSizing::CapacityPerFloorArea) {
2139 0 : zoneEqSizing.HeatingCapacity = true;
2140 0 : zoneEqSizing.DesHeatingLoad = state.dataSize->ZoneHVACSizing(zoneHVACIndex).ScaledHeatingCapacity *
2141 0 : state.dataHeatBal->Zone(state.dataSize->DataZoneNumber).FloorArea;
2142 0 : state.dataSize->DataScalableCapSizingON = true;
2143 0 : } else if (CapSizingMethod == DataSizing::FractionOfAutosizedHeatingCapacity) {
2144 0 : state.dataSize->DataFracOfAutosizedHeatingCapacity =
2145 0 : state.dataSize->ZoneHVACSizing(zoneHVACIndex).ScaledHeatingCapacity;
2146 0 : state.dataSize->DataFlowUsedForSizing = state.dataSize->FinalZoneSizing(CurZoneEqNum).DesHeatVolFlow;
2147 0 : TempSize = DataSizing::AutoSize;
2148 0 : state.dataSize->DataScalableCapSizingON = true;
2149 : }
2150 : }
2151 0 : SizingString = "";
2152 0 : PrintFlag = false;
2153 0 : HeatingCapacitySizer sizerHeatingCapacity;
2154 0 : sizerHeatingCapacity.overrideSizingString(SizingString);
2155 0 : sizerHeatingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
2156 0 : DesCoilLoad = sizerHeatingCapacity.size(state, TempSize, ErrorsFound);
2157 0 : state.dataSize->DataScalableCapSizingON = false;
2158 0 : } else {
2159 0 : SizingString = "";
2160 0 : PrintFlag = false;
2161 0 : TempSize = DataSizing::AutoSize;
2162 0 : HeatingCapacitySizer sizerHeatingCapacity;
2163 0 : sizerHeatingCapacity.overrideSizingString(SizingString);
2164 0 : sizerHeatingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
2165 0 : DesCoilLoad = sizerHeatingCapacity.size(state, TempSize, ErrorsFound);
2166 0 : }
2167 0 : TempSteamIn = 100.00;
2168 0 : auto *steam = Fluid::GetSteam(state);
2169 0 : EnthSteamInDry = steam->getSatEnthalpy(state, TempSteamIn, 1.0, RoutineName);
2170 0 : EnthSteamOutWet = steam->getSatEnthalpy(state, TempSteamIn, 0.0, RoutineName);
2171 0 : LatentHeatSteam = EnthSteamInDry - EnthSteamOutWet;
2172 0 : SteamDensity = steam->getSatDensity(state, TempSteamIn, 1.0, RoutineName);
2173 0 : int DummyWaterIndex = 1;
2174 :
2175 0 : auto *water = Fluid::GetWater(state);
2176 0 : Cp = water->getSpecificHeat(state, Constant::HWInitConvTemp, RoutineName);
2177 0 : rho = water->getDensity(state, Constant::HWInitConvTemp, RoutineName);
2178 0 : MaxVolHotSteamFlowDes =
2179 0 : DesCoilLoad / ((state.dataSize->PlantSizData(PltSizHeatNum).DeltaT * Cp * rho) + SteamDensity * LatentHeatSteam);
2180 : } else {
2181 0 : MaxVolHotSteamFlowDes = 0.0;
2182 : }
2183 : } else {
2184 0 : ShowSevereError(state, "Autosizing of Steam flow requires a heating loop Sizing:Plant object");
2185 0 : ShowContinueError(state, format("Occurs in ZoneHVAC:VentilatedSlab Object={}", ventSlab.Name));
2186 0 : ErrorsFound = true;
2187 : }
2188 0 : ventSlab.MaxVolHotSteamFlow = MaxVolHotSteamFlowDes;
2189 0 : BaseSizer::reportSizerOutput(
2190 : state, cMO_VentilatedSlab, ventSlab.Name, "Design Size Maximum Steam Flow [m3/s]", MaxVolHotSteamFlowDes);
2191 : } else {
2192 0 : if (ventSlab.MaxVolHotSteamFlow > 0.0 && MaxVolHotSteamFlowDes > 0.0) {
2193 0 : MaxVolHotSteamFlowUser = ventSlab.MaxVolHotSteamFlow;
2194 0 : BaseSizer::reportSizerOutput(state,
2195 : cMO_VentilatedSlab,
2196 : ventSlab.Name,
2197 : "Design Size Maximum Steam Flow [m3/s]",
2198 : MaxVolHotSteamFlowDes,
2199 : "User-Specified Maximum Steam Flow [m3/s]",
2200 : MaxVolHotSteamFlowUser);
2201 0 : if (state.dataGlobal->DisplayExtraWarnings) {
2202 0 : if ((std::abs(MaxVolHotSteamFlowDes - MaxVolHotSteamFlowUser) / MaxVolHotSteamFlowUser) >
2203 0 : state.dataSize->AutoVsHardSizingThreshold) {
2204 0 : ShowMessage(
2205 : state,
2206 0 : format("SizeVentilatedSlab: Potential issue with equipment sizing for ZoneHVAC:VentilatedSlab = \"{}\".",
2207 0 : ventSlab.Name));
2208 0 : ShowContinueError(state, format("User-Specified Maximum Steam Flow of {:.5R} [m3/s]", MaxVolHotSteamFlowUser));
2209 0 : ShowContinueError(state,
2210 0 : format("differs from Design Size Maximum Steam Flow of {:.5R} [m3/s]", MaxVolHotSteamFlowDes));
2211 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
2212 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
2213 : }
2214 : }
2215 : }
2216 : }
2217 : }
2218 : }
2219 : } else {
2220 1 : ventSlab.MaxVolHotSteamFlow = 0.0;
2221 : }
2222 :
2223 1 : IsAutoSize = false;
2224 1 : if (ventSlab.MaxVolColdWaterFlow == DataSizing::AutoSize) {
2225 0 : IsAutoSize = true;
2226 : }
2227 1 : if (CurZoneEqNum > 0) {
2228 1 : if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) {
2229 1 : if (ventSlab.MaxVolColdWaterFlow > 0.0) {
2230 1 : BaseSizer::reportSizerOutput(
2231 : state, cMO_VentilatedSlab, ventSlab.Name, "User-Specified Maximum Cold Water Flow [m3/s]", ventSlab.MaxVolColdWaterFlow);
2232 : }
2233 : } else {
2234 0 : CheckZoneSizing(state, cMO_VentilatedSlab, ventSlab.Name);
2235 0 : if (ventSlab.cCoilType == CoolingCoilType::HXAssisted) {
2236 : CoolingCoilName =
2237 0 : HVACHXAssistedCoolingCoil::GetHXDXCoilName(state, ventSlab.coolingCoilTypeCh, ventSlab.coolingCoilName, ErrorsFound);
2238 : CoolingCoilType =
2239 0 : HVACHXAssistedCoolingCoil::GetHXCoilType(state, ventSlab.coolingCoilTypeCh, ventSlab.coolingCoilName, ErrorsFound);
2240 : } else {
2241 0 : CoolingCoilName = ventSlab.coolingCoilName;
2242 0 : CoolingCoilType = ventSlab.coolingCoilTypeCh;
2243 : }
2244 0 : int CoilWaterInletNode = WaterCoils::GetCoilWaterInletNode(state, CoolingCoilType, CoolingCoilName, ErrorsFound);
2245 0 : int CoilWaterOutletNode = WaterCoils::GetCoilWaterOutletNode(state, CoolingCoilType, CoolingCoilName, ErrorsFound);
2246 0 : if (IsAutoSize) {
2247 0 : int PltSizCoolNum = PlantUtilities::MyPlantSizingIndex(
2248 : state, CoolingCoilType, CoolingCoilName, CoilWaterInletNode, CoilWaterOutletNode, ErrorsFound);
2249 0 : int CoilNum = WaterCoils::GetWaterCoilIndex(state, CoolingCoilType, CoolingCoilName, ErrorsFound);
2250 0 : if (state.dataWaterCoils->WaterCoil(CoilNum).UseDesignWaterDeltaTemp) {
2251 0 : WaterCoilSizDeltaT = state.dataWaterCoils->WaterCoil(CoilNum).DesignWaterDeltaTemp;
2252 0 : DoWaterCoilSizing = true;
2253 : } else {
2254 0 : if (PltSizCoolNum > 0) {
2255 0 : WaterCoilSizDeltaT = state.dataSize->PlantSizData(PltSizCoolNum).DeltaT;
2256 0 : DoWaterCoilSizing = true;
2257 : } else {
2258 0 : DoWaterCoilSizing = false;
2259 : // If there is no cooling Plant Sizing object and autosizing was requested, issue fatal error message
2260 0 : ShowSevereError(state, "Autosizing of water flow requires a cooling loop Sizing:Plant object");
2261 0 : ShowContinueError(state, format("Occurs in {} Object={}", cMO_VentilatedSlab, ventSlab.Name));
2262 0 : ErrorsFound = true;
2263 : }
2264 : }
2265 0 : if (DoWaterCoilSizing) {
2266 0 : if (state.dataSize->FinalZoneSizing(CurZoneEqNum).DesCoolMassFlow >= HVAC::SmallAirVolFlow) {
2267 0 : SizingMethod = HVAC::CoolingCapacitySizing;
2268 0 : if (ventSlab.HVACSizingIndex > 0) {
2269 0 : auto &zoneEqSizing = state.dataSize->ZoneEqSizing(CurZoneEqNum);
2270 0 : zoneHVACIndex = ventSlab.HVACSizingIndex;
2271 0 : int CapSizingMethod = state.dataSize->ZoneHVACSizing(zoneHVACIndex).CoolingCapMethod;
2272 0 : zoneEqSizing.SizingMethod(SizingMethod) = CapSizingMethod;
2273 0 : if (CapSizingMethod == DataSizing::CoolingDesignCapacity || CapSizingMethod == DataSizing::CapacityPerFloorArea ||
2274 : CapSizingMethod == DataSizing::FractionOfAutosizedCoolingCapacity) {
2275 0 : if (CapSizingMethod == DataSizing::CoolingDesignCapacity) {
2276 0 : if (state.dataSize->ZoneHVACSizing(zoneHVACIndex).ScaledCoolingCapacity > 0.0) {
2277 0 : zoneEqSizing.CoolingCapacity = true;
2278 0 : zoneEqSizing.DesCoolingLoad = state.dataSize->ZoneHVACSizing(zoneHVACIndex).ScaledCoolingCapacity;
2279 : } else {
2280 0 : state.dataSize->DataFlowUsedForSizing = state.dataSize->FinalZoneSizing(CurZoneEqNum).DesCoolVolFlow;
2281 : }
2282 0 : TempSize = state.dataSize->ZoneHVACSizing(zoneHVACIndex).ScaledCoolingCapacity;
2283 0 : } else if (CapSizingMethod == DataSizing::CapacityPerFloorArea) {
2284 0 : zoneEqSizing.CoolingCapacity = true;
2285 0 : zoneEqSizing.DesCoolingLoad = state.dataSize->ZoneHVACSizing(zoneHVACIndex).ScaledCoolingCapacity *
2286 0 : state.dataHeatBal->Zone(state.dataSize->DataZoneNumber).FloorArea;
2287 0 : state.dataSize->DataScalableCapSizingON = true;
2288 0 : } else if (CapSizingMethod == DataSizing::FractionOfAutosizedCoolingCapacity) {
2289 0 : state.dataSize->DataFracOfAutosizedHeatingCapacity =
2290 0 : state.dataSize->ZoneHVACSizing(zoneHVACIndex).ScaledCoolingCapacity;
2291 0 : state.dataSize->DataFlowUsedForSizing = state.dataSize->FinalZoneSizing(CurZoneEqNum).DesCoolVolFlow;
2292 0 : TempSize = DataSizing::AutoSize;
2293 0 : state.dataSize->DataScalableCapSizingON = true;
2294 : }
2295 : }
2296 0 : SizingString = "";
2297 0 : PrintFlag = false;
2298 0 : CoolingCapacitySizer sizerCoolingCapacity;
2299 0 : sizerCoolingCapacity.overrideSizingString(SizingString);
2300 0 : sizerCoolingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
2301 0 : DesCoilLoad = sizerCoolingCapacity.size(state, TempSize, ErrorsFound);
2302 0 : state.dataSize->DataScalableCapSizingON = false;
2303 0 : } else {
2304 0 : SizingString = "";
2305 0 : PrintFlag = false;
2306 0 : TempSize = DataSizing::AutoSize;
2307 0 : state.dataSize->DataFlowUsedForSizing = state.dataSize->FinalZoneSizing(CurZoneEqNum).DesCoolVolFlow;
2308 0 : CoolingCapacitySizer sizerCoolingCapacity;
2309 0 : sizerCoolingCapacity.overrideSizingString(SizingString);
2310 0 : sizerCoolingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
2311 0 : DesCoilLoad = sizerCoolingCapacity.size(state, TempSize, ErrorsFound);
2312 0 : }
2313 0 : rho = state.dataPlnt->PlantLoop(ventSlab.CWPlantLoc.loopNum).glycol->getDensity(state, 5., RoutineName);
2314 0 : Cp = state.dataPlnt->PlantLoop(ventSlab.CWPlantLoc.loopNum).glycol->getSpecificHeat(state, 5., RoutineName);
2315 0 : MaxVolColdWaterFlowDes = DesCoilLoad / (WaterCoilSizDeltaT * Cp * rho);
2316 : } else {
2317 0 : MaxVolColdWaterFlowDes = 0.0;
2318 : }
2319 : }
2320 0 : ventSlab.MaxVolColdWaterFlow = MaxVolColdWaterFlowDes;
2321 0 : BaseSizer::reportSizerOutput(
2322 : state, cMO_VentilatedSlab, ventSlab.Name, "Design Size Maximum Cold Water Flow [m3/s]", MaxVolColdWaterFlowDes);
2323 : } else {
2324 0 : if (ventSlab.MaxVolColdWaterFlow > 0.0 && MaxVolColdWaterFlowDes > 0.0) {
2325 0 : MaxVolColdWaterFlowUser = ventSlab.MaxVolColdWaterFlow;
2326 0 : BaseSizer::reportSizerOutput(state,
2327 : cMO_VentilatedSlab,
2328 : ventSlab.Name,
2329 : "Design Size Maximum Cold Water Flow [m3/s]",
2330 : MaxVolColdWaterFlowDes,
2331 : "User-Specified Maximum Cold Water Flow [m3/s]",
2332 : MaxVolColdWaterFlowUser);
2333 0 : if (state.dataGlobal->DisplayExtraWarnings) {
2334 0 : if ((std::abs(MaxVolColdWaterFlowDes - MaxVolColdWaterFlowUser) / MaxVolColdWaterFlowUser) >
2335 0 : state.dataSize->AutoVsHardSizingThreshold) {
2336 0 : ShowMessage(state,
2337 0 : format("SizeVentilatedSlab: Potential issue with equipment sizing for ZoneHVAC:VentilatedSlab = \"{}\".",
2338 0 : ventSlab.Name));
2339 0 : ShowContinueError(state, format("User-Specified Maximum Cold Water Flow of {:.5R} [m3/s]", MaxVolColdWaterFlowUser));
2340 0 : ShowContinueError(
2341 0 : state, format("differs from Design Size Maximum Cold Water Flow of {:.5R} [m3/s]", MaxVolColdWaterFlowDes));
2342 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
2343 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
2344 : }
2345 : }
2346 : }
2347 : }
2348 : }
2349 : }
2350 :
2351 1 : if (ventSlab.cCoilType == CoolingCoilType::HXAssisted) {
2352 0 : CoolingCoilName = HVACHXAssistedCoolingCoil::GetHXDXCoilName(state, ventSlab.coolingCoilTypeCh, ventSlab.coolingCoilName, ErrorsFound);
2353 0 : CoolingCoilType = HVACHXAssistedCoolingCoil::GetHXCoilType(state, ventSlab.coolingCoilTypeCh, ventSlab.coolingCoilName, ErrorsFound);
2354 : } else {
2355 1 : CoolingCoilName = ventSlab.coolingCoilName;
2356 1 : CoolingCoilType = ventSlab.coolingCoilTypeCh;
2357 : }
2358 1 : WaterCoils::SetCoilDesFlow(state, CoolingCoilType, CoolingCoilName, ventSlab.MaxAirVolFlow, ErrorsFound);
2359 1 : WaterCoils::SetCoilDesFlow(state, ventSlab.heatingCoilTypeCh, ventSlab.heatingCoilName, ventSlab.MaxAirVolFlow, ErrorsFound);
2360 :
2361 1 : if (CurZoneEqNum > 0) {
2362 1 : auto &zoneEqSizing = state.dataSize->ZoneEqSizing(CurZoneEqNum);
2363 1 : zoneEqSizing.MaxHWVolFlow = ventSlab.MaxVolHotWaterFlow;
2364 1 : zoneEqSizing.MaxCWVolFlow = ventSlab.MaxVolColdWaterFlow;
2365 : }
2366 :
2367 1 : if (ErrorsFound) {
2368 0 : ShowFatalError(state, "Preceding sizing errors cause program termination");
2369 : }
2370 1 : }
2371 :
2372 0 : void CalcVentilatedSlab(EnergyPlusData &state,
2373 : int &Item, // number of the current ventilated slab being simulated
2374 : int const ZoneNum, // number of zone being served
2375 : bool const FirstHVACIteration, // TRUE if 1st HVAC simulation of system timestep
2376 : Real64 &PowerMet, // power supplied (W)
2377 : Real64 &LatOutputProvided // latent capacity supplied (kg/s)
2378 : )
2379 : {
2380 :
2381 : // SUBROUTINE INFORMATION:
2382 : // AUTHOR Young Tae Chae, Rick Strand
2383 : // DATE WRITTEN June 2008
2384 : // MODIFIED Don Shirey, Aug 2009 (LatOutputProvided)
2385 : // July 2012, Chandan Sharma - FSEC: Added zone sys avail managers
2386 :
2387 : // PURPOSE OF THIS SUBROUTINE:
2388 : // This subroutine mainly controls the action of the Ventilated Slab
2389 : // (or more exactly, it controls the amount of outside air brought in)
2390 : // based on the user input for controls and the defined controls
2391 : // algorithms.
2392 :
2393 : // METHODOLOGY EMPLOYED:
2394 : // Ventilated slab is controlled based on user input and what is happening in the
2395 : // simulation. There are various cases to consider:
2396 : // 1. OFF: Unit is schedule off or there is no load on it. All flow
2397 : // rates are set to zero and the temperatures are set to zone conditions
2398 : // (except for the outside air inlet).
2399 : // 2. HEATING/VARIABLE PERCENT: The unit is on, there is a heating load,
2400 : // and variable percent control is specified. The outside air fraction
2401 : // is set to the minimum outside air fraction (schedule based) and the
2402 : // heating coil is activated.
2403 : // 3. HEATING/FIXED TEMPERATURE: The unit is on, there is a heating load,
2404 : // and fixed temperature control is specified. The outside air fraction
2405 : // is varied in an attempt to obtain a mixed air temperature equal to
2406 : // the user specified temperature (schedule based). The heating coil
2407 : // is activated, if necessary.
2408 : // 4. COOLING/NO COIL: The unit is on, there is a cooling load, and no
2409 : // coil is present or it has been scheduled off. Set the amount of
2410 : // outside air based on the control type. Simulate the "mixing box".
2411 : // 5. COOLING/WITH COIL: The unit is on, there is a cooling load, and
2412 : // a cooling coil is present and scheduled on. Tries to use outside
2413 : // air as best as possible and then calls a cooling coil
2414 : // Note: controls are strictly temperature based and do not factor
2415 : // humidity into the equation (not an enthalpy economy cycle but rather
2416 : // a simple return air economy cycle). In addition, temperature predictions
2417 : // are not strict energy balances here in the control routine though
2418 : // in the mixing routine an energy balance is preserved.
2419 :
2420 : // REFERENCES:
2421 : // ASHRAE Systems and Equipment Handbook (SI), 1996. page 31.3
2422 :
2423 : // Using/Aliasing
2424 0 : auto &ventSlab = state.dataVentilatedSlab->VentSlab(Item);
2425 :
2426 : // SUBROUTINE PARAMETER DEFINITIONS:
2427 0 : Real64 constexpr LowTempDiff(0.1); // Smallest allowed temperature difference for comparisons
2428 : // (below this value the temperatures are assumed equal)
2429 0 : Real64 constexpr LowOAFracDiff(0.01); // Smallest allowed outside air fraction difference for comparison
2430 : // (below this value the fractions are assumed equal)
2431 :
2432 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
2433 : Real64 QZnReq;
2434 : Real64 AirMassFlow; // air mass flow rate [kg/sec]
2435 : int AirRelNode; // outside air relief node
2436 : int ControlNode; // the hot water or cold water inlet node
2437 : int InletNode; // system air inlet node
2438 : int FanOutletNode; // system fan outlet node
2439 : int ZoneAirInNode; // zone supply air node
2440 : Real64 MaxOAFrac; // maximum possible outside air fraction
2441 : Real64 MaxWaterFlow; // maximum water flow for heating or cooling [kg/sec]
2442 : Real64 MinOAFrac; // minimum possible outside air fraction
2443 : Real64 MinWaterFlow; // minimum water flow for heating or cooling [kg/sec]
2444 : int OutletNode; // air outlet node
2445 : int OutsideAirNode; // outside air node
2446 : int MixoutNode; // oa mixer outlet node
2447 : int ReturnAirNode; // return air node
2448 : Real64 QUnitOut; // heating or sens. cooling provided by fan coil unit [watts]
2449 : Real64 LatentOutput; // Latent (moisture) add/removal rate, negative is dehumidification [kg/s]
2450 : Real64 Tdesired; // desired temperature after mixing inlet and outdoor air [degrees C]
2451 : Real64 Tinlet; // temperature of air coming into the ventilated slab [degrees C]
2452 : Real64 Toutdoor; // temperature of outdoor air being introduced into the ventilated slab [degrees C]
2453 : Real64 MaxSteamFlow;
2454 : Real64 MinSteamFlow;
2455 : Real64 RadInTemp; // "Desired" radiant system air inlet temperature [Celsius]**setpoint
2456 : Real64 SetPointTemp; // temperature that will be used to control the radiant system [Celsius]
2457 : Real64 SetPointTempHi; // Current high point in setpoint temperature range
2458 : Real64 SetPointTempLo; // Current low point in setpoint temperature range
2459 : Real64 AirTempHi; // Current high point in water temperature range
2460 : Real64 AirTempLo; // Current low point in water temperature range
2461 : Real64 AirTempHeatHi; // Current high point in water temperature range
2462 : Real64 AirTempCoolLo; // Current low point in water temperature range
2463 : Real64 CpFan; // Intermediate calculational variable for specific heat of air <<NOV9 Updated
2464 : Real64 ZoneRadNum; // number of zone being served *********************
2465 : int RadSurfNum; // DO loop counter for the surfaces that comprise a particular radiant system
2466 0 : static std::string const CurrentModuleObject("ZoneHVAC:VentilatedSlab");
2467 :
2468 0 : switch (ventSlab.coilOption) {
2469 0 : case CoilType::Both: {
2470 :
2471 0 : switch (ventSlab.hCoilType) {
2472 0 : case HeatingCoilType::Water: {
2473 0 : WaterCoils::CheckWaterCoilSchedule(state, ventSlab.heatingCoilName, ventSlab.heatingCoilSchedValue, ventSlab.heatingCoil_Index);
2474 0 : break;
2475 : }
2476 0 : case HeatingCoilType::Steam: {
2477 0 : SteamCoils::CheckSteamCoilSchedule(
2478 0 : state, "Coil:Heating:Steam", ventSlab.heatingCoilName, ventSlab.heatingCoilSchedValue, ventSlab.heatingCoil_Index);
2479 0 : break;
2480 : }
2481 0 : case HeatingCoilType::Electric: {
2482 0 : HeatingCoils::CheckHeatingCoilSchedule(
2483 0 : state, "Coil:Heating:Electric", ventSlab.heatingCoilName, ventSlab.heatingCoilSchedValue, ventSlab.heatingCoil_Index);
2484 0 : break;
2485 : }
2486 0 : case HeatingCoilType::Gas: {
2487 0 : HeatingCoils::CheckHeatingCoilSchedule(
2488 0 : state, "Coil:Heating:Fuel", ventSlab.heatingCoilName, ventSlab.heatingCoilSchedValue, ventSlab.heatingCoil_Index);
2489 0 : break;
2490 : }
2491 0 : default:
2492 0 : break;
2493 : }
2494 :
2495 0 : switch (ventSlab.cCoilType) {
2496 0 : case CoolingCoilType::WaterCooling:
2497 : case CoolingCoilType::DetailedCooling: {
2498 0 : WaterCoils::CheckWaterCoilSchedule(state, ventSlab.coolingCoilName, ventSlab.coolingCoilSchedValue, ventSlab.coolingCoil_Index);
2499 0 : break;
2500 : }
2501 0 : case CoolingCoilType::HXAssisted: {
2502 0 : HVACHXAssistedCoolingCoil::CheckHXAssistedCoolingCoilSchedule(state,
2503 : "CoilSystem:Cooling:Water:HeatExchangerAssisted",
2504 : ventSlab.coolingCoilName,
2505 0 : ventSlab.coolingCoilSchedValue,
2506 0 : ventSlab.coolingCoil_Index);
2507 0 : break;
2508 : }
2509 0 : default:
2510 0 : break;
2511 : }
2512 0 : break;
2513 : }
2514 0 : case CoilType::Heating: {
2515 :
2516 0 : switch (ventSlab.hCoilType) {
2517 0 : case HeatingCoilType::Water: {
2518 0 : WaterCoils::CheckWaterCoilSchedule(state, ventSlab.heatingCoilName, ventSlab.heatingCoilSchedValue, ventSlab.heatingCoil_Index);
2519 0 : break;
2520 : }
2521 0 : case HeatingCoilType::Steam: {
2522 0 : SteamCoils::CheckSteamCoilSchedule(
2523 0 : state, "Coil:Heating:Steam", ventSlab.heatingCoilName, ventSlab.heatingCoilSchedValue, ventSlab.heatingCoil_Index);
2524 0 : break;
2525 : }
2526 0 : case HeatingCoilType::Electric: {
2527 0 : HeatingCoils::CheckHeatingCoilSchedule(
2528 0 : state, "Coil:Heating:Electric", ventSlab.heatingCoilName, ventSlab.heatingCoilSchedValue, ventSlab.heatingCoil_Index);
2529 0 : break;
2530 : }
2531 0 : case HeatingCoilType::Gas: {
2532 0 : HeatingCoils::CheckHeatingCoilSchedule(
2533 0 : state, "Coil:Heating:Fuel", ventSlab.heatingCoilName, ventSlab.heatingCoilSchedValue, ventSlab.heatingCoil_Index);
2534 0 : break;
2535 : }
2536 0 : default:
2537 0 : break;
2538 : }
2539 0 : break;
2540 : }
2541 0 : case CoilType::Cooling: {
2542 :
2543 0 : switch (ventSlab.cCoilType) {
2544 0 : case CoolingCoilType::WaterCooling:
2545 : case CoolingCoilType::DetailedCooling: {
2546 0 : WaterCoils::CheckWaterCoilSchedule(state, ventSlab.coolingCoilName, ventSlab.coolingCoilSchedValue, ventSlab.coolingCoil_Index);
2547 0 : break;
2548 : }
2549 0 : case CoolingCoilType::HXAssisted: {
2550 0 : HVACHXAssistedCoolingCoil::CheckHXAssistedCoolingCoilSchedule(state,
2551 : "CoilSystem:Cooling:Water:HeatExchangerAssisted",
2552 : ventSlab.coolingCoilName,
2553 0 : ventSlab.coolingCoilSchedValue,
2554 0 : ventSlab.coolingCoil_Index);
2555 0 : break;
2556 : }
2557 0 : default:
2558 0 : break;
2559 : }
2560 : }
2561 : case CoilType::None:
2562 : default:
2563 0 : break;
2564 : }
2565 :
2566 : // initialize local variables
2567 0 : ControlNode = 0;
2568 0 : QUnitOut = 0.0;
2569 0 : LatentOutput = 0.0;
2570 0 : MaxWaterFlow = 0.0;
2571 0 : MinWaterFlow = 0.0;
2572 0 : AirMassFlow = 0.0;
2573 0 : InletNode = ventSlab.ReturnAirNode;
2574 0 : OutletNode = ventSlab.RadInNode;
2575 0 : FanOutletNode = ventSlab.FanOutletNode;
2576 0 : ZoneAirInNode = ventSlab.ZoneAirInNode;
2577 0 : OutsideAirNode = ventSlab.OutsideAirNode;
2578 0 : AirRelNode = ventSlab.AirReliefNode;
2579 0 : MixoutNode = ventSlab.OAMixerOutNode;
2580 0 : ReturnAirNode = ventSlab.ReturnAirNode;
2581 0 : ZoneRadNum = ventSlab.ZonePtr;
2582 0 : RadSurfNum = ventSlab.NumOfSurfaces;
2583 0 : Tinlet = state.dataLoopNodes->Node(InletNode).Temp;
2584 0 : Toutdoor = state.dataLoopNodes->Node(OutsideAirNode).Temp;
2585 0 : auto const &thisZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum);
2586 :
2587 : // Control Type Check
2588 0 : switch (ventSlab.controlType) {
2589 0 : case ControlType::MeanAirTemp: {
2590 0 : SetPointTemp = thisZoneHB.MAT;
2591 0 : break;
2592 : }
2593 0 : case ControlType::MeanRadTemp: {
2594 0 : SetPointTemp = thisZoneHB.MRT;
2595 0 : break;
2596 : }
2597 0 : case ControlType::OperativeTemp: {
2598 0 : SetPointTemp = 0.5 * (thisZoneHB.MAT + thisZoneHB.MRT);
2599 0 : break;
2600 : }
2601 0 : case ControlType::OutdoorDryBulbTemp: {
2602 0 : SetPointTemp = state.dataEnvrn->OutDryBulbTemp;
2603 0 : break;
2604 : }
2605 0 : case ControlType::OutdoorWetBulbTemp: {
2606 0 : SetPointTemp = state.dataEnvrn->OutWetBulbTemp;
2607 0 : break;
2608 : }
2609 0 : case ControlType::SurfaceTemp: {
2610 0 : SetPointTemp = state.dataHeatBalSurf->SurfInsideTempHist(1)(ventSlab.SurfacePtr(RadSurfNum));
2611 0 : break;
2612 : }
2613 0 : case ControlType::DewPointTemp: {
2614 0 : SetPointTemp = Psychrometrics::PsyTdpFnWPb(
2615 0 : state, state.dataZoneTempPredictorCorrector->zoneHeatBalance(ventSlab.ZonePtr).airHumRat, state.dataEnvrn->OutBaroPress);
2616 0 : break;
2617 : }
2618 0 : default: { // Should never get here
2619 0 : SetPointTemp = 0.0; // Suppress uninitialized warning
2620 0 : ShowSevereError(state, format("Illegal control type in low temperature radiant system: {}", ventSlab.Name));
2621 0 : ShowFatalError(state, "Preceding condition causes termination.");
2622 0 : } break;
2623 : } // switch (ctrlType)
2624 :
2625 : // Load Check
2626 :
2627 0 : AirTempHeatHi = ventSlab.hotCtrlHiTempSched->getCurrentVal();
2628 0 : AirTempCoolLo = ventSlab.coldCtrlLoTempSched->getCurrentVal();
2629 :
2630 0 : if (((SetPointTemp >= AirTempHeatHi) && (SetPointTemp <= AirTempCoolLo)) || (ventSlab.availSched->getCurrentVal() <= 0)) {
2631 :
2632 : // System is off or has no load upon it; set the flow rates to zero and then
2633 : // simulate the components with the no flow conditions
2634 0 : state.dataLoopNodes->Node(InletNode).MassFlowRate = 0.0;
2635 0 : state.dataLoopNodes->Node(InletNode).MassFlowRateMaxAvail = 0.0;
2636 0 : state.dataLoopNodes->Node(InletNode).MassFlowRateMinAvail = 0.0;
2637 0 : state.dataLoopNodes->Node(OutletNode).MassFlowRate = 0.0;
2638 0 : state.dataLoopNodes->Node(OutletNode).MassFlowRateMaxAvail = 0.0;
2639 0 : state.dataLoopNodes->Node(OutletNode).MassFlowRateMinAvail = 0.0;
2640 0 : state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate = 0.0;
2641 0 : state.dataLoopNodes->Node(OutsideAirNode).MassFlowRateMaxAvail = 0.0;
2642 0 : state.dataLoopNodes->Node(OutsideAirNode).MassFlowRateMinAvail = 0.0;
2643 0 : state.dataLoopNodes->Node(AirRelNode).MassFlowRate = 0.0;
2644 0 : state.dataLoopNodes->Node(AirRelNode).MassFlowRateMaxAvail = 0.0;
2645 0 : state.dataLoopNodes->Node(AirRelNode).MassFlowRateMinAvail = 0.0;
2646 0 : state.dataLoopNodes->Node(ReturnAirNode).MassFlowRate = 0.0;
2647 0 : state.dataLoopNodes->Node(ReturnAirNode).MassFlowRateMaxAvail = 0.0;
2648 0 : state.dataLoopNodes->Node(ReturnAirNode).MassFlowRateMinAvail = 0.0;
2649 0 : state.dataLoopNodes->Node(MixoutNode).MassFlowRate = 0.0;
2650 0 : state.dataLoopNodes->Node(MixoutNode).MassFlowRateMaxAvail = 0.0;
2651 0 : state.dataLoopNodes->Node(MixoutNode).MassFlowRateMinAvail = 0.0;
2652 0 : state.dataLoopNodes->Node(FanOutletNode).MassFlowRate = 0.0;
2653 0 : state.dataLoopNodes->Node(FanOutletNode).MassFlowRateMaxAvail = 0.0;
2654 0 : state.dataLoopNodes->Node(FanOutletNode).MassFlowRateMinAvail = 0.0;
2655 0 : AirMassFlow = 0.0;
2656 0 : state.dataVentilatedSlab->HCoilOn = false;
2657 :
2658 : // Node condition
2659 0 : state.dataLoopNodes->Node(InletNode).Temp = state.dataHeatBalSurf->SurfInsideTempHist(1)(ventSlab.SurfacePtr(1));
2660 0 : state.dataLoopNodes->Node(FanOutletNode).Temp = state.dataLoopNodes->Node(InletNode).Temp;
2661 0 : state.dataLoopNodes->Node(OutletNode).Temp = state.dataLoopNodes->Node(FanOutletNode).Temp;
2662 :
2663 : // Node condition
2664 0 : if (ventSlab.SysConfg == VentilatedSlabConfig::SeriesSlabs) {
2665 0 : bool ErrorsFound = false; // Set to true if errors in input, fatal at end of routine
2666 0 : for (RadSurfNum = 1; RadSurfNum <= ventSlab.NumOfSurfaces; ++RadSurfNum) {
2667 0 : std::string SlabName = ventSlab.SurfaceName(RadSurfNum);
2668 0 : std::string MSlabIn = ventSlab.SlabIn(RadSurfNum);
2669 0 : std::string MSlabOut = ventSlab.SlabOut(RadSurfNum);
2670 0 : ventSlab.MSlabInNode = NodeInputManager::GetOnlySingleNode(state,
2671 : MSlabIn,
2672 : ErrorsFound,
2673 : DataLoopNode::ConnectionObjectType::ZoneHVACVentilatedSlab,
2674 : SlabName,
2675 : DataLoopNode::NodeFluidType::Air,
2676 : DataLoopNode::ConnectionType::Internal,
2677 : NodeInputManager::CompFluidStream::Primary,
2678 : DataLoopNode::ObjectIsNotParent);
2679 0 : ventSlab.MSlabOutNode = NodeInputManager::GetOnlySingleNode(state,
2680 : MSlabOut,
2681 : ErrorsFound,
2682 : DataLoopNode::ConnectionObjectType::ZoneHVACVentilatedSlab,
2683 : SlabName,
2684 : DataLoopNode::NodeFluidType::Air,
2685 : DataLoopNode::ConnectionType::Internal,
2686 : NodeInputManager::CompFluidStream::Primary,
2687 : DataLoopNode::ObjectIsNotParent);
2688 0 : int MSlabInletNode = ventSlab.MSlabInNode;
2689 0 : int MSlabOutletNode = ventSlab.MSlabOutNode;
2690 :
2691 0 : state.dataLoopNodes->Node(MSlabInletNode).Temp = state.dataLoopNodes->Node(InletNode).Temp;
2692 0 : state.dataLoopNodes->Node(MSlabOutletNode).Temp = state.dataLoopNodes->Node(MSlabInletNode).Temp;
2693 0 : }
2694 : }
2695 :
2696 0 : CalcVentilatedSlabComps(state, Item, FirstHVACIteration, QUnitOut);
2697 :
2698 : } else { // System On
2699 :
2700 0 : if (SetPointTemp < AirTempHeatHi) { // HEATING MODE
2701 0 : state.dataVentilatedSlab->OperatingMode = HeatingMode;
2702 :
2703 : // Check the setpoint and temperature span
2704 0 : SetPointTempHi = ventSlab.hotCtrlHiTempSched->getCurrentVal();
2705 0 : SetPointTempLo = ventSlab.hotCtrlLoTempSched->getCurrentVal();
2706 0 : if (SetPointTempHi < SetPointTempLo) {
2707 0 : ShowSevereError(state, format("Heating setpoint temperature mismatch in{}", ventSlab.Name));
2708 0 : ShowContinueError(state, "High setpoint temperature is less than low setpoint temperature--check your schedule input");
2709 0 : ShowFatalError(state, "Preceding condition causes termination.");
2710 : }
2711 :
2712 0 : AirTempHi = ventSlab.hotAirHiTempSched->getCurrentVal();
2713 0 : AirTempLo = ventSlab.hotAirLoTempSched->getCurrentVal();
2714 :
2715 0 : if (AirTempHi < AirTempLo) {
2716 0 : ShowSevereError(state, format("Heating Air temperature mismatch in{}", ventSlab.Name));
2717 0 : ShowContinueError(state, "High Air temperature is less than low Air temperature--check your schedule input");
2718 0 : ShowFatalError(state, "Preceding condition causes termination.");
2719 : }
2720 :
2721 0 : if (SetPointTemp >= SetPointTempHi) {
2722 : // System is above high heating setpoint so we should be able to turn the system off
2723 0 : RadInTemp = AirTempLo;
2724 :
2725 0 : } else if (SetPointTemp <= SetPointTempLo) {
2726 : // System is running with its highest inlet temperature
2727 0 : RadInTemp = AirTempHi;
2728 : } else {
2729 : // Interpolate to obtain the current radiant system inlet temperature
2730 0 : RadInTemp = AirTempHi - (AirTempHi - AirTempLo) * (SetPointTemp - SetPointTempLo) / (SetPointTempHi - SetPointTempLo);
2731 : }
2732 :
2733 0 : state.dataLoopNodes->Node(ventSlab.RadInNode).Temp = RadInTemp;
2734 :
2735 0 : ControlNode = ventSlab.HotControlNode;
2736 0 : MaxWaterFlow = ventSlab.MaxHotWaterFlow;
2737 0 : MinWaterFlow = ventSlab.MinHotWaterFlow;
2738 0 : MaxSteamFlow = ventSlab.MaxHotSteamFlow;
2739 0 : MinSteamFlow = ventSlab.MinHotSteamFlow;
2740 :
2741 : // On the first HVAC iteration the system values are given to the controller, but after that
2742 : // the demand limits are in place and there needs to be feedback to the Zone Equipment
2743 :
2744 0 : if (!FirstHVACIteration && ventSlab.hCoilType == HeatingCoilType::Water) {
2745 0 : MaxWaterFlow = state.dataLoopNodes->Node(ControlNode).MassFlowRateMaxAvail;
2746 0 : MinWaterFlow = state.dataLoopNodes->Node(ControlNode).MassFlowRateMinAvail;
2747 : }
2748 :
2749 0 : if (!FirstHVACIteration && ventSlab.hCoilType == HeatingCoilType::Steam) {
2750 0 : MaxSteamFlow = state.dataLoopNodes->Node(ControlNode).MassFlowRateMaxAvail;
2751 0 : MinSteamFlow = state.dataLoopNodes->Node(ControlNode).MassFlowRateMinAvail;
2752 : }
2753 :
2754 0 : state.dataVentilatedSlab->HCoilOn = true;
2755 :
2756 0 : if (state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate > 0.0) {
2757 0 : MinOAFrac =
2758 0 : ventSlab.minOASched->getCurrentVal() * (ventSlab.MinOutAirMassFlow / state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate);
2759 : } else {
2760 0 : MinOAFrac = 0.0;
2761 : }
2762 :
2763 0 : MinOAFrac = min(1.0, max(0.0, MinOAFrac));
2764 :
2765 0 : if ((!ventSlab.heatingCoilPresent) || (ventSlab.heatingCoilSchedValue <= 0.0)) {
2766 : // In heating mode, but there is no coil to provide heating. This is handled
2767 : // differently than if there was a heating coil present. Fixed temperature
2768 : // will still try to vary the amount of outside air to meet the desired
2769 : // mixed air temperature, while variable percent will go to full ventilation
2770 : // when it is most advantageous.
2771 :
2772 : // If there are no coil, Slab In Node is assumed to be Fan Outlet Node
2773 :
2774 0 : OutletNode = FanOutletNode;
2775 :
2776 0 : switch (ventSlab.outsideAirControlType) {
2777 0 : case OutsideAirControlType::FixedOAControl: {
2778 : // In this control type, the outdoor air flow rate is fixed to the maximum value
2779 : // which is equal to the minimum value, regardless of all the other conditions.
2780 0 : state.dataVentilatedSlab->OAMassFlowRate = MinOAFrac * state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate;
2781 0 : break;
2782 : }
2783 0 : case OutsideAirControlType::VariablePercent: {
2784 : // This algorithm is probably a bit simplistic in that it just bounces
2785 : // back and forth between the maximum outside air and the minimum. In
2786 : // reality, a system *might* vary between the two based on the load in
2787 : // the zone. This simple flow control might cause some overcooling but
2788 : // chances are that if there is a cooling load and the zone temperature
2789 : // gets above the outside temperature that overcooling won't be significant.
2790 0 : Tinlet = state.dataLoopNodes->Node(InletNode).Temp;
2791 0 : Toutdoor = state.dataLoopNodes->Node(OutsideAirNode).Temp;
2792 :
2793 0 : if (Tinlet >= Toutdoor) {
2794 :
2795 0 : state.dataVentilatedSlab->OAMassFlowRate = MinOAFrac * state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate;
2796 :
2797 : } else { // Tinlet < Toutdoor
2798 0 : MaxOAFrac = ventSlab.maxOASched->getCurrentVal();
2799 0 : state.dataVentilatedSlab->OAMassFlowRate = MaxOAFrac * state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate;
2800 : }
2801 0 : break;
2802 : }
2803 0 : case OutsideAirControlType::FixedTemperature: {
2804 : // This is basically the same algorithm as for the heating case...
2805 0 : Tdesired = ventSlab.tempSched->getCurrentVal();
2806 0 : MaxOAFrac = 1.0;
2807 :
2808 0 : if (std::abs(Tinlet - Toutdoor) <= LowTempDiff) { // no difference in indoor and outdoor conditions-->set OA to minimum
2809 0 : state.dataVentilatedSlab->OAMassFlowRate = MinOAFrac * state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate;
2810 0 : } else if (std::abs(MaxOAFrac - MinOAFrac) <= LowOAFracDiff) { // no difference in outside air fractions
2811 0 : state.dataVentilatedSlab->OAMassFlowRate = MinOAFrac * state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate;
2812 0 : } else if (((Tdesired <= Tinlet) && (Tdesired >= Toutdoor)) || ((Tdesired >= Tinlet) && (Tdesired <= Toutdoor))) {
2813 : // Desired temperature is between the inlet and outdoor temperatures
2814 : // so vary the flow rate between no outside air and no recirculation air
2815 : // then applying the maximum and minimum limits the user has scheduled
2816 : // to make sure too much/little outside air is being introduced
2817 0 : state.dataVentilatedSlab->OAMassFlowRate =
2818 0 : ((Tdesired - Tinlet) / (Toutdoor - Tinlet)) * state.dataLoopNodes->Node(InletNode).MassFlowRate;
2819 0 : state.dataVentilatedSlab->OAMassFlowRate =
2820 0 : max(state.dataVentilatedSlab->OAMassFlowRate, (MinOAFrac * state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate));
2821 0 : state.dataVentilatedSlab->OAMassFlowRate =
2822 0 : min(state.dataVentilatedSlab->OAMassFlowRate, (MaxOAFrac * state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate));
2823 0 : } else if ((Tdesired < Tinlet) && (Tdesired < Toutdoor)) {
2824 : // Desired temperature is below both the inlet and outdoor temperatures
2825 : // so use whichever flow rate (max or min) that will get closer
2826 0 : if (Tinlet < Toutdoor) { // Tinlet closer to Tdesired so use minimum outside air
2827 0 : state.dataVentilatedSlab->OAMassFlowRate = MinOAFrac * state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate;
2828 : } else { // Toutdoor closer to Tdesired so use maximum outside air
2829 0 : state.dataVentilatedSlab->OAMassFlowRate = MaxOAFrac * state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate;
2830 : }
2831 0 : } else if ((Tdesired > Tinlet) && (Tdesired > Toutdoor)) {
2832 : // Desired temperature is above both the inlet and outdoor temperatures
2833 : // so use whichever flow rate (max or min) that will get closer
2834 0 : if (Tinlet > Toutdoor) { // Tinlet closer to Tdesired so use minimum outside air
2835 0 : state.dataVentilatedSlab->OAMassFlowRate = MinOAFrac * state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate;
2836 : } else { // Toutdoor closer to Tdesired so use maximum outside air
2837 0 : state.dataVentilatedSlab->OAMassFlowRate = MaxOAFrac * state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate;
2838 : }
2839 : } else {
2840 : // It should NEVER get to this point, but just in case...
2841 0 : ShowFatalError(state, format("Ventilated Slab simulation control: illogical condition for {}", ventSlab.Name));
2842 : }
2843 0 : break;
2844 : }
2845 0 : default:
2846 0 : break;
2847 : }
2848 :
2849 0 : CalcVentilatedSlabComps(state, Item, FirstHVACIteration, QUnitOut);
2850 :
2851 : } else { // Heating Coil present
2852 :
2853 0 : switch (ventSlab.outsideAirControlType) {
2854 0 : case OutsideAirControlType::FixedOAControl: {
2855 : // In this control type, the outdoor air flow rate is fixed to the maximum value
2856 : // which is equal to the minimum value, regardless of all the other conditions.
2857 0 : if (state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate > 0.0) {
2858 0 : MaxOAFrac = min(1.0, max(0.0, ventSlab.maxOASched->getCurrentVal()));
2859 : } else {
2860 0 : MaxOAFrac = 0.0;
2861 : }
2862 0 : state.dataVentilatedSlab->OAMassFlowRate = MaxOAFrac * state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate;
2863 0 : break;
2864 : }
2865 0 : case OutsideAirControlType::VariablePercent: {
2866 : // In heating mode, the ouside air for "variable percent" control
2867 : // is set to the minimum value
2868 :
2869 0 : state.dataVentilatedSlab->OAMassFlowRate = MinOAFrac * state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate;
2870 0 : break;
2871 : }
2872 0 : case OutsideAirControlType::FixedTemperature: {
2873 : // This is basically the same algorithm as for the heating case...
2874 0 : Tdesired = ventSlab.tempSched->getCurrentVal();
2875 0 : MaxOAFrac = 1.0;
2876 :
2877 0 : if (std::abs(Tinlet - Toutdoor) <= LowTempDiff) { // no difference in indoor and outdoor conditions-->set OA to minimum
2878 0 : state.dataVentilatedSlab->OAMassFlowRate = MinOAFrac * state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate;
2879 0 : } else if (std::abs(MaxOAFrac - MinOAFrac) <= LowOAFracDiff) { // no difference in outside air fractions
2880 0 : state.dataVentilatedSlab->OAMassFlowRate = MinOAFrac * state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate;
2881 0 : } else if (((Tdesired <= Tinlet) && (Tdesired >= Toutdoor)) || ((Tdesired >= Tinlet) && (Tdesired <= Toutdoor))) {
2882 : // Desired temperature is between the inlet and outdoor temperatures
2883 : // so vary the flow rate between no outside air and no recirculation air
2884 : // then applying the maximum and minimum limits the user has scheduled
2885 : // to make sure too much/little outside air is being introduced
2886 0 : state.dataVentilatedSlab->OAMassFlowRate =
2887 0 : ((Tdesired - Tinlet) / (Toutdoor - Tinlet)) * state.dataLoopNodes->Node(InletNode).MassFlowRate;
2888 0 : state.dataVentilatedSlab->OAMassFlowRate =
2889 0 : max(state.dataVentilatedSlab->OAMassFlowRate, (MinOAFrac * state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate));
2890 0 : state.dataVentilatedSlab->OAMassFlowRate =
2891 0 : min(state.dataVentilatedSlab->OAMassFlowRate, (MaxOAFrac * state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate));
2892 0 : } else if ((Tdesired < Tinlet) && (Tdesired < Toutdoor)) {
2893 : // Desired temperature is below both the inlet and outdoor temperatures
2894 : // so use whichever flow rate (max or min) that will get closer
2895 0 : if (Tinlet < Toutdoor) { // Tinlet closer to Tdesired so use minimum outside air
2896 0 : state.dataVentilatedSlab->OAMassFlowRate = MinOAFrac * state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate;
2897 : } else { // Toutdoor closer to Tdesired so use maximum outside air
2898 0 : state.dataVentilatedSlab->OAMassFlowRate = MaxOAFrac * state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate;
2899 : }
2900 0 : } else if ((Tdesired > Tinlet) && (Tdesired > Toutdoor)) {
2901 : // Desired temperature is above both the inlet and outdoor temperatures
2902 : // so use whichever flow rate (max or min) that will get closer
2903 0 : if (Tinlet > Toutdoor) { // Tinlet closer to Tdesired so use minimum outside air
2904 0 : state.dataVentilatedSlab->OAMassFlowRate = MinOAFrac * state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate;
2905 : } else { // Toutdoor closer to Tdesired so use maximum outside air
2906 0 : state.dataVentilatedSlab->OAMassFlowRate = MaxOAFrac * state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate;
2907 : }
2908 : } else {
2909 : // It should NEVER get to this point, but just in case...
2910 0 : ShowFatalError(state, format("Ventilated Slab simulation control: illogical condition for {}", ventSlab.Name));
2911 : }
2912 0 : break;
2913 : }
2914 0 : default:
2915 0 : break;
2916 : }
2917 :
2918 0 : SimVentSlabOAMixer(state, Item);
2919 :
2920 0 : state.dataFans->fans(ventSlab.Fan_Index)->simulate(state, FirstHVACIteration, _, _);
2921 :
2922 0 : CpFan = Psychrometrics::PsyCpAirFnW(state.dataLoopNodes->Node(FanOutletNode).HumRat);
2923 0 : QZnReq =
2924 0 : (state.dataLoopNodes->Node(OutletNode).MassFlowRate) * CpFan * (RadInTemp - state.dataLoopNodes->Node(FanOutletNode).Temp);
2925 :
2926 : // Setup the coil configuration
2927 0 : switch (ventSlab.hCoilType) {
2928 :
2929 0 : case HeatingCoilType::Water: {
2930 : // control water flow to obtain output matching QZnReq
2931 :
2932 0 : ControlCompOutput(state,
2933 0 : ventSlab.Name,
2934 : cMO_VentilatedSlab,
2935 : Item,
2936 : FirstHVACIteration,
2937 : QZnReq,
2938 : ControlNode,
2939 : MaxWaterFlow,
2940 : MinWaterFlow,
2941 : 0.001,
2942 0 : ventSlab.ControlCompTypeNum,
2943 0 : ventSlab.CompErrIndex,
2944 : _,
2945 : _,
2946 : _,
2947 : _,
2948 : _,
2949 0 : ventSlab.HWPlantLoc);
2950 0 : break;
2951 : }
2952 0 : case HeatingCoilType::Gas:
2953 : case HeatingCoilType::Electric:
2954 : case HeatingCoilType::Steam: {
2955 :
2956 0 : CalcVentilatedSlabComps(state, Item, FirstHVACIteration, QUnitOut);
2957 0 : break;
2958 : }
2959 0 : default:
2960 0 : break;
2961 : }
2962 :
2963 : } // Coil/no coil block
2964 :
2965 0 : } else if (SetPointTemp > AirTempCoolLo) { // Cooling Mode
2966 :
2967 0 : state.dataVentilatedSlab->OperatingMode = CoolingMode;
2968 0 : SetPointTempHi = ventSlab.coldCtrlHiTempSched->getCurrentVal();
2969 0 : SetPointTempLo = ventSlab.coldCtrlLoTempSched->getCurrentVal();
2970 0 : if (SetPointTempHi < SetPointTempLo) {
2971 0 : ShowSevereError(state, format("Cooling setpoint temperature mismatch in{}", ventSlab.Name));
2972 0 : ShowContinueError(state, "High setpoint temperature is less than low setpoint temperature--check your schedule input");
2973 0 : ShowFatalError(state, "Preceding condition causes termination.");
2974 : }
2975 :
2976 0 : AirTempHi = ventSlab.coldAirHiTempSched->getCurrentVal();
2977 0 : AirTempLo = ventSlab.coldAirLoTempSched->getCurrentVal();
2978 0 : if (AirTempHi < AirTempLo) {
2979 0 : ShowSevereError(state, format("Cooling Air temperature mismatch in{}", ventSlab.Name));
2980 0 : ShowContinueError(state, "High Air temperature is less than low Air temperature--check your schedule input");
2981 0 : ShowFatalError(state, "Preceding condition causes termination.");
2982 : }
2983 :
2984 0 : if (SetPointTemp <= SetPointTempLo) {
2985 : // System is below low cooling setpoint so we should be able to turn the system off
2986 0 : RadInTemp = AirTempHi;
2987 0 : } else if (SetPointTemp >= SetPointTempHi) {
2988 : // System is running with its lowest inlet temperature
2989 0 : RadInTemp = AirTempLo;
2990 : } else {
2991 : // Interpolate to obtain the current radiant system inlet temperature
2992 0 : RadInTemp = AirTempHi - (AirTempHi - AirTempLo) * (SetPointTemp - SetPointTempLo) / (SetPointTempHi - SetPointTempLo);
2993 : }
2994 :
2995 0 : ControlNode = ventSlab.ColdControlNode;
2996 0 : MaxWaterFlow = ventSlab.MaxColdWaterFlow;
2997 0 : MinWaterFlow = ventSlab.MinColdWaterFlow;
2998 :
2999 : // On the first HVAC iteration the system values are given to the controller, but after that
3000 : // the demand limits are in place and there needs to be feedback to the Zone Equipment
3001 0 : if ((!FirstHVACIteration) && (ControlNode > 0) && (ventSlab.coolingCoilPresent)) {
3002 0 : MaxWaterFlow = state.dataLoopNodes->Node(ControlNode).MassFlowRateMaxAvail;
3003 0 : MinWaterFlow = state.dataLoopNodes->Node(ControlNode).MassFlowRateMinAvail;
3004 : }
3005 0 : state.dataVentilatedSlab->HCoilOn = false;
3006 :
3007 0 : if (state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate > 0.0) {
3008 0 : MinOAFrac =
3009 0 : ventSlab.minOASched->getCurrentVal() * (ventSlab.MinOutAirMassFlow / state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate);
3010 : } else {
3011 0 : MinOAFrac = 0.0;
3012 : }
3013 0 : MinOAFrac = min(1.0, max(0.0, MinOAFrac));
3014 :
3015 0 : if ((!ventSlab.coolingCoilPresent) || (ventSlab.coolingCoilSchedValue <= 0.0)) {
3016 : // In cooling mode, but there is no coil to provide cooling. This is handled
3017 : // differently than if there was a cooling coil present. Fixed temperature
3018 : // will still try to vary the amount of outside air to meet the desired
3019 : // mixed air temperature, while variable percent will go to full ventilation
3020 : // when it is most advantageous.
3021 :
3022 : // If there are no coil, Slab In Node is assumed to be Fan Outlet Node
3023 0 : OutletNode = FanOutletNode;
3024 :
3025 0 : switch (ventSlab.outsideAirControlType) {
3026 :
3027 0 : case OutsideAirControlType::FixedOAControl: {
3028 : // In this control type, the outdoor air flow rate is fixed to the maximum value
3029 : // which is equal to the minimum value, regardless of all the other conditions.
3030 0 : if (state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate > 0.0) {
3031 0 : MaxOAFrac = min(1.0, max(0.0, ventSlab.maxOASched->getCurrentVal()));
3032 : } else {
3033 0 : MaxOAFrac = 0.0;
3034 : }
3035 0 : state.dataVentilatedSlab->OAMassFlowRate = MaxOAFrac * state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate;
3036 0 : break;
3037 : }
3038 0 : case OutsideAirControlType::VariablePercent: {
3039 : // This algorithm is probably a bit simplistic in that it just bounces
3040 : // back and forth between the maximum outside air and the minimum. In
3041 : // reality, a system *might* vary between the two based on the load in
3042 : // the zone. This simple flow control might cause some overcooling but
3043 : // chances are that if there is a cooling load and the zone temperature
3044 : // gets above the outside temperature that overcooling won't be significant.
3045 :
3046 0 : Tinlet = state.dataLoopNodes->Node(InletNode).Temp;
3047 0 : Toutdoor = state.dataLoopNodes->Node(OutsideAirNode).Temp;
3048 :
3049 0 : if (Tinlet <= Toutdoor) {
3050 :
3051 0 : state.dataVentilatedSlab->OAMassFlowRate = MinOAFrac * state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate;
3052 :
3053 : } else { // Tinlet > Toutdoor
3054 0 : MaxOAFrac = ventSlab.maxOASched->getCurrentVal();
3055 0 : state.dataVentilatedSlab->OAMassFlowRate = MaxOAFrac * state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate;
3056 : }
3057 0 : break;
3058 : }
3059 0 : case OutsideAirControlType::FixedTemperature: {
3060 : // This is basically the same algorithm as for the heating case...
3061 0 : Tdesired = ventSlab.tempSched->getCurrentVal();
3062 0 : MaxOAFrac = 1.0;
3063 :
3064 0 : if (std::abs(Tinlet - Toutdoor) <= LowTempDiff) { // no difference in indoor and outdoor conditions-->set OA to minimum
3065 0 : state.dataVentilatedSlab->OAMassFlowRate = MinOAFrac * state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate;
3066 0 : } else if (std::abs(MaxOAFrac - MinOAFrac) <= LowOAFracDiff) { // no difference in outside air fractions
3067 0 : state.dataVentilatedSlab->OAMassFlowRate = MinOAFrac * state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate;
3068 0 : } else if (((Tdesired <= Tinlet) && (Tdesired >= Toutdoor)) || ((Tdesired >= Tinlet) && (Tdesired <= Toutdoor))) {
3069 : // Desired temperature is between the inlet and outdoor temperatures
3070 : // so vary the flow rate between no outside air and no recirculation air
3071 : // then applying the maximum and minimum limits the user has scheduled
3072 : // to make sure too much/little outside air is being introduced
3073 0 : state.dataVentilatedSlab->OAMassFlowRate =
3074 0 : ((Tdesired - Tinlet) / (Toutdoor - Tinlet)) * state.dataLoopNodes->Node(InletNode).MassFlowRate;
3075 0 : state.dataVentilatedSlab->OAMassFlowRate =
3076 0 : max(state.dataVentilatedSlab->OAMassFlowRate, (MinOAFrac * state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate));
3077 0 : state.dataVentilatedSlab->OAMassFlowRate =
3078 0 : min(state.dataVentilatedSlab->OAMassFlowRate, (MaxOAFrac * state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate));
3079 0 : } else if ((Tdesired < Tinlet) && (Tdesired < Toutdoor)) {
3080 : // Desired temperature is below both the inlet and outdoor temperatures
3081 : // so use whichever flow rate (max or min) that will get closer
3082 0 : if (Tinlet < Toutdoor) { // Tinlet closer to Tdesired so use minimum outside air
3083 0 : state.dataVentilatedSlab->OAMassFlowRate = MinOAFrac * state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate;
3084 : } else { // Toutdoor closer to Tdesired so use maximum outside air
3085 0 : state.dataVentilatedSlab->OAMassFlowRate = MaxOAFrac * state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate;
3086 : }
3087 0 : } else if ((Tdesired > Tinlet) && (Tdesired > Toutdoor)) {
3088 : // Desired temperature is above both the inlet and outdoor temperatures
3089 : // so use whichever flow rate (max or min) that will get closer
3090 0 : if (Tinlet > Toutdoor) { // Tinlet closer to Tdesired so use minimum outside air
3091 0 : state.dataVentilatedSlab->OAMassFlowRate = MinOAFrac * state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate;
3092 : } else { // Toutdoor closer to Tdesired so use maximum outside air
3093 0 : state.dataVentilatedSlab->OAMassFlowRate = MaxOAFrac * state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate;
3094 : }
3095 : } else {
3096 : // It should NEVER get to this point, but just in case...
3097 0 : ShowFatalError(state, format("{} simulation control: illogical condition for {}", cMO_VentilatedSlab, ventSlab.Name));
3098 : }
3099 0 : break;
3100 : }
3101 0 : default:
3102 0 : break;
3103 : }
3104 :
3105 0 : CalcVentilatedSlabComps(state, Item, FirstHVACIteration, QUnitOut);
3106 :
3107 : } else {
3108 : // There is a cooling load and there is a cooling coil present (presumably).
3109 : // Variable percent will throttle outside air back to the minimum while
3110 : // fixed temperature will still try to vary the outside air amount to meet
3111 : // the desired mixed air temperature.
3112 :
3113 0 : switch (ventSlab.outsideAirControlType) {
3114 :
3115 0 : case OutsideAirControlType::FixedOAControl: {
3116 : // In this control type, the outdoor air flow rate is fixed to the maximum value
3117 : // which is equal to the minimum value, regardless of all the other conditions.
3118 0 : if (state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate > 0.0) {
3119 0 : MaxOAFrac = min(1.0, max(0.0, ventSlab.maxOASched->getCurrentVal()));
3120 : } else {
3121 0 : MaxOAFrac = 0.0;
3122 : }
3123 0 : state.dataVentilatedSlab->OAMassFlowRate = MaxOAFrac * state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate;
3124 0 : break;
3125 : }
3126 0 : case OutsideAirControlType::VariablePercent: {
3127 : // A cooling coil is present so let it try to do the cooling...
3128 0 : state.dataVentilatedSlab->OAMassFlowRate = MinOAFrac * state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate;
3129 0 : break;
3130 : }
3131 0 : case OutsideAirControlType::FixedTemperature: {
3132 : // This is basically the same algorithm as for the heating case...
3133 0 : Tdesired = ventSlab.tempSched->getCurrentVal();
3134 :
3135 0 : MaxOAFrac = 1.0;
3136 :
3137 0 : if (std::abs(Tinlet - Toutdoor) <= LowTempDiff) { // no difference in indoor and outdoor conditions-->set OA to minimum
3138 0 : state.dataVentilatedSlab->OAMassFlowRate = MinOAFrac * state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate;
3139 0 : } else if (std::abs(MaxOAFrac - MinOAFrac) <= LowOAFracDiff) { // no difference in outside air fractions
3140 0 : state.dataVentilatedSlab->OAMassFlowRate = MinOAFrac * state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate;
3141 0 : } else if (((Tdesired <= Tinlet) && (Tdesired >= Toutdoor)) || ((Tdesired >= Tinlet) && (Tdesired <= Toutdoor))) {
3142 : // Desired temperature is between the inlet and outdoor temperatures
3143 : // so vary the flow rate between no outside air and no recirculation air
3144 : // then applying the maximum and minimum limits the user has scheduled
3145 : // to make sure too much/little outside air is being introduced
3146 0 : state.dataVentilatedSlab->OAMassFlowRate =
3147 0 : ((Tdesired - Tinlet) / (Toutdoor - Tinlet)) * state.dataLoopNodes->Node(InletNode).MassFlowRate;
3148 0 : state.dataVentilatedSlab->OAMassFlowRate =
3149 0 : max(state.dataVentilatedSlab->OAMassFlowRate, (MinOAFrac * state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate));
3150 0 : state.dataVentilatedSlab->OAMassFlowRate =
3151 0 : min(state.dataVentilatedSlab->OAMassFlowRate, (MaxOAFrac * state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate));
3152 0 : } else if ((Tdesired < Tinlet) && (Tdesired < Toutdoor)) {
3153 : // Desired temperature is below both the inlet and outdoor temperatures
3154 : // so use whichever flow rate (max or min) that will get closer
3155 0 : if (Tinlet < Toutdoor) { // Tinlet closer to Tdesired so use minimum outside air
3156 0 : state.dataVentilatedSlab->OAMassFlowRate = MinOAFrac * state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate;
3157 : } else { // Toutdoor closer to Tdesired so use maximum outside air
3158 0 : state.dataVentilatedSlab->OAMassFlowRate = MaxOAFrac * state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate;
3159 : }
3160 0 : } else if ((Tdesired > Tinlet) && (Tdesired > Toutdoor)) {
3161 : // Desired temperature is above both the inlet and outdoor temperatures
3162 : // so use whichever flow rate (max or min) that will get closer
3163 0 : if (Tinlet > Toutdoor) { // Tinlet closer to Tdesired so use minimum outside air
3164 0 : state.dataVentilatedSlab->OAMassFlowRate = MinOAFrac * state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate;
3165 : } else { // Toutdoor closer to Tdesired so use maximum outside air
3166 0 : state.dataVentilatedSlab->OAMassFlowRate = MaxOAFrac * state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate;
3167 : }
3168 : } else {
3169 : // It should NEVER get to this point, but just in case...
3170 0 : ShowFatalError(state, format("{} simulation control: illogical condition for {}", cMO_VentilatedSlab, ventSlab.Name));
3171 : }
3172 0 : break;
3173 : }
3174 0 : default:
3175 0 : break;
3176 : }
3177 :
3178 : // control water flow to obtain output matching Low Setpoint Temperateure
3179 0 : state.dataVentilatedSlab->HCoilOn = false;
3180 :
3181 0 : SimVentSlabOAMixer(state, Item);
3182 0 : state.dataFans->fans(ventSlab.Fan_Index)->simulate(state, FirstHVACIteration, _, _);
3183 :
3184 0 : CpFan = Psychrometrics::PsyCpAirFnW(state.dataLoopNodes->Node(FanOutletNode).HumRat);
3185 0 : QZnReq =
3186 0 : (state.dataLoopNodes->Node(OutletNode).MassFlowRate) * CpFan * (RadInTemp - state.dataLoopNodes->Node(FanOutletNode).Temp);
3187 :
3188 0 : ControlCompOutput(state,
3189 0 : ventSlab.Name,
3190 : cMO_VentilatedSlab,
3191 : Item,
3192 : FirstHVACIteration,
3193 : QZnReq,
3194 : ControlNode,
3195 : MaxWaterFlow,
3196 : MinWaterFlow,
3197 : 0.001,
3198 0 : ventSlab.ControlCompTypeNum,
3199 0 : ventSlab.CompErrIndex,
3200 : _,
3201 : _,
3202 : _,
3203 : _,
3204 : _,
3205 0 : ventSlab.CWPlantLoc);
3206 : }
3207 :
3208 : } // ...end of HEATING/COOLING IF-THEN block
3209 :
3210 0 : CalcVentilatedSlabRadComps(state, Item, FirstHVACIteration);
3211 :
3212 : } // ...end of system ON/OFF IF-THEN block
3213 :
3214 : // Resimulate fans if AirMassFlow is zero and FanElecPower is > 0, indicating that load or condensation controls shut off the ventilated slab
3215 : // in CalcVentilatedSlabRadComps
3216 0 : AirMassFlow = state.dataLoopNodes->Node(OutletNode).MassFlowRate;
3217 0 : Real64 locFanElecPower = state.dataFans->fans(ventSlab.Fan_Index)->totalPower;
3218 :
3219 0 : if ((AirMassFlow <= 0.0) && (locFanElecPower > 0.0)) {
3220 0 : state.dataLoopNodes->Node(MixoutNode).MassFlowRate = 0.0;
3221 0 : state.dataLoopNodes->Node(MixoutNode).MassFlowRateMaxAvail = 0.0;
3222 0 : state.dataLoopNodes->Node(MixoutNode).MassFlowRateMinAvail = 0.0;
3223 0 : state.dataLoopNodes->Node(FanOutletNode).MassFlowRate = 0.0;
3224 0 : state.dataLoopNodes->Node(FanOutletNode).MassFlowRateMaxAvail = 0.0;
3225 0 : state.dataLoopNodes->Node(FanOutletNode).MassFlowRateMinAvail = 0.0;
3226 0 : state.dataFans->fans(ventSlab.Fan_Index)->simulate(state, FirstHVACIteration, _, _);
3227 : }
3228 :
3229 0 : CalcVentilatedSlabCoilOutput(state, Item, PowerMet, LatOutputProvided);
3230 0 : }
3231 :
3232 0 : void CalcVentilatedSlabComps(EnergyPlusData &state,
3233 : int const Item, // system index in ventilated slab array
3234 : bool const FirstHVACIteration, // flag for 1st HVAV iteration in the time step
3235 : Real64 &LoadMet // load met by the system (watts)
3236 : )
3237 : {
3238 :
3239 : // SUBROUTINE INFORMATION:
3240 : // AUTHOR Young Tae Chae, Rick Strand
3241 : // DATE WRITTEN June 2008
3242 : // MODIFIED July 2012, Chandan Sharma - FSEC: Added zone sys avail managers
3243 :
3244 : // PURPOSE OF THIS SUBROUTINE:
3245 : // This subroutine launches the individual component simulations.
3246 : // This is called either when the system is off to carry null conditions
3247 : // through the system or during control iterations to continue updating
3248 : // what is going on within the unit.
3249 :
3250 : // METHODOLOGY EMPLOYED:
3251 : // Simply calls the different components in order. Only slight wrinkles
3252 : // here are that the ventilated slab system has it's own outside air mixed and
3253 : // that a cooling coil must be present in order to call a cooling coil
3254 : // simulation. Other than that, the subroutine is very straightforward.
3255 :
3256 : // Using/Aliasing
3257 0 : auto &ventSlab = state.dataVentilatedSlab->VentSlab(Item);
3258 :
3259 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
3260 : Real64 AirMassFlow; // total mass flow through the system
3261 : Real64 CpAirZn; // specific heat of dry air at zone conditions (zone conditions same as system inlet)
3262 : int InletNode; // system air inlet node
3263 : int OutletNode; // system air outlet node
3264 : // unused0309 INTEGER :: HCoilOutAirNode
3265 : Real64 QCoilReq; // Heat addition required from an electric/gas heating coil
3266 : Real64 HCoilOutAirTemp;
3267 : Real64 HCoilInAirTemp;
3268 : // unused1208 REAL(r64) :: RadInTemp ! Set temperature for "Slab In Node"
3269 :
3270 0 : SimVentSlabOAMixer(state, Item);
3271 0 : state.dataFans->fans(ventSlab.Fan_Index)->simulate(state, FirstHVACIteration, _, _);
3272 :
3273 0 : if ((ventSlab.coolingCoilPresent) && (ventSlab.coolingCoilSchedValue >= 0.0)) {
3274 0 : if (ventSlab.cCoilType == CoolingCoilType::HXAssisted) {
3275 0 : HVACHXAssistedCoolingCoil::SimHXAssistedCoolingCoil(state,
3276 : ventSlab.coolingCoilName,
3277 : FirstHVACIteration,
3278 : HVAC::CompressorOp::On,
3279 : 0.0,
3280 0 : ventSlab.coolingCoil_Index,
3281 : HVAC::FanOp::Continuous);
3282 : } else {
3283 0 : WaterCoils::SimulateWaterCoilComponents(state, ventSlab.coolingCoilName, FirstHVACIteration, ventSlab.coolingCoil_Index);
3284 : }
3285 : }
3286 :
3287 0 : if ((ventSlab.heatingCoilPresent) && (ventSlab.heatingCoilSchedValue >= 0.0)) {
3288 :
3289 0 : switch (ventSlab.hCoilType) {
3290 :
3291 0 : case HeatingCoilType::Water: {
3292 :
3293 0 : WaterCoils::SimulateWaterCoilComponents(state, ventSlab.heatingCoilName, FirstHVACIteration, ventSlab.heatingCoil_Index);
3294 0 : break;
3295 : }
3296 0 : case HeatingCoilType::Steam: {
3297 :
3298 0 : if (!state.dataVentilatedSlab->HCoilOn) {
3299 0 : QCoilReq = 0.0;
3300 : } else {
3301 0 : int HCoilInAirNode = ventSlab.FanOutletNode;
3302 0 : CpAirZn = Psychrometrics::PsyCpAirFnW(state.dataLoopNodes->Node(HCoilInAirNode).HumRat);
3303 0 : QCoilReq =
3304 0 : state.dataLoopNodes->Node(HCoilInAirNode).MassFlowRate * CpAirZn * (state.dataLoopNodes->Node(ventSlab.RadInNode).Temp) -
3305 0 : (state.dataLoopNodes->Node(HCoilInAirNode).Temp);
3306 : }
3307 :
3308 0 : if (QCoilReq < 0.0) {
3309 0 : QCoilReq = 0.0; // a heating coil can only heat, not cool
3310 : }
3311 :
3312 0 : SteamCoils::SimulateSteamCoilComponents(state, ventSlab.heatingCoilName, FirstHVACIteration, ventSlab.heatingCoil_Index, QCoilReq);
3313 0 : break;
3314 : }
3315 0 : case HeatingCoilType::Electric:
3316 : case HeatingCoilType::Gas: {
3317 :
3318 0 : if (!state.dataVentilatedSlab->HCoilOn) {
3319 0 : QCoilReq = 0.0;
3320 : } else {
3321 0 : HCoilInAirTemp = state.dataLoopNodes->Node(ventSlab.FanOutletNode).Temp;
3322 0 : HCoilOutAirTemp = state.dataLoopNodes->Node(ventSlab.RadInNode).Temp;
3323 0 : CpAirZn = Psychrometrics::PsyCpAirFnW(state.dataLoopNodes->Node(ventSlab.RadInNode).HumRat);
3324 0 : QCoilReq = state.dataLoopNodes->Node(ventSlab.FanOutletNode).MassFlowRate * CpAirZn * (HCoilOutAirTemp - HCoilInAirTemp);
3325 : }
3326 :
3327 0 : if (QCoilReq < 0.0) {
3328 0 : QCoilReq = 0.0; // a heating coil can only heat, not cool
3329 : }
3330 :
3331 0 : HeatingCoils::SimulateHeatingCoilComponents(
3332 0 : state, ventSlab.heatingCoilName, FirstHVACIteration, QCoilReq, ventSlab.heatingCoil_Index);
3333 0 : break;
3334 : }
3335 0 : default:
3336 0 : break;
3337 : }
3338 : }
3339 :
3340 0 : InletNode = ventSlab.FanOutletNode;
3341 0 : OutletNode = ventSlab.RadInNode;
3342 0 : AirMassFlow = state.dataLoopNodes->Node(OutletNode).MassFlowRate;
3343 :
3344 0 : LoadMet = AirMassFlow * (Psychrometrics::PsyHFnTdbW(state.dataLoopNodes->Node(OutletNode).Temp, state.dataLoopNodes->Node(InletNode).HumRat) -
3345 0 : Psychrometrics::PsyHFnTdbW(state.dataLoopNodes->Node(InletNode).Temp, state.dataLoopNodes->Node(InletNode).HumRat));
3346 0 : }
3347 :
3348 3 : void CalcVentilatedSlabCoilOutput(EnergyPlusData &state,
3349 : int const Item, // system index in ventilated slab array
3350 : Real64 &PowerMet, // power supplied (W)
3351 : Real64 &LatOutputProvided // latent capacity supplied (kg/s)
3352 : )
3353 : {
3354 :
3355 : // SUBROUTINE INFORMATION:
3356 : // AUTHOR Young Tae Chae, Rick Strand
3357 : // DATE WRITTEN June 2008
3358 : // MODIFIED July 2012, Chandan Sharma - FSEC: Added zone sys avail managers
3359 : // RE-ENGINEERED July 2015, M.J. Witte, Refactored coil output calcs in to this new routine
3360 :
3361 : // PURPOSE OF THIS SUBROUTINE:
3362 : // This subroutine calculates the output from the coils
3363 :
3364 : // METHODOLOGY EMPLOYED:
3365 : // Calculates the sensible and total enthalpy change from the fan outlet node to the slab inlet node.
3366 :
3367 : // USING/ALIASING:
3368 3 : auto &ventSlab = state.dataVentilatedSlab->VentSlab(Item);
3369 :
3370 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
3371 : Real64 AirMassFlow; // total mass flow through the system
3372 : int FanOutletNode; // system fan outlet node
3373 : int OutletNode; // air outlet node
3374 : Real64 SpecHumOut; // Specific humidity ratio of outlet air (kg moisture / kg moist air)
3375 : Real64 SpecHumIn; // Specific humidity ratio of inlet air (kg moisture / kg moist air)
3376 : Real64 QTotUnitOut; // total unit output [watts]
3377 : Real64 QUnitOut; // heating or sens. cooling provided by fan coil unit [watts]
3378 :
3379 3 : OutletNode = ventSlab.RadInNode;
3380 3 : FanOutletNode = ventSlab.FanOutletNode;
3381 3 : AirMassFlow = state.dataLoopNodes->Node(OutletNode).MassFlowRate;
3382 :
3383 : // QTotUnitOut = AirMassFlow * ( Node( OutletNode ).Enthalpy - Node( FanOutletNode ).Enthalpy );
3384 3 : QTotUnitOut = AirMassFlow *
3385 3 : (Psychrometrics::PsyHFnTdbW(state.dataLoopNodes->Node(OutletNode).Temp, state.dataLoopNodes->Node(OutletNode).HumRat) -
3386 3 : Psychrometrics::PsyHFnTdbW(state.dataLoopNodes->Node(FanOutletNode).Temp, state.dataLoopNodes->Node(FanOutletNode).HumRat));
3387 3 : QUnitOut = AirMassFlow *
3388 3 : (Psychrometrics::PsyHFnTdbW(state.dataLoopNodes->Node(OutletNode).Temp, state.dataLoopNodes->Node(FanOutletNode).HumRat) -
3389 3 : Psychrometrics::PsyHFnTdbW(state.dataLoopNodes->Node(FanOutletNode).Temp, state.dataLoopNodes->Node(FanOutletNode).HumRat));
3390 : // Limit sensible <= total when cooling (which is negative, so use max)
3391 3 : QUnitOut = max(QUnitOut, QTotUnitOut);
3392 :
3393 : // Report variables...
3394 3 : ventSlab.HeatCoilPower = max(0.0, QUnitOut);
3395 3 : ventSlab.SensCoolCoilPower = std::abs(min(0.0, QUnitOut));
3396 3 : ventSlab.TotCoolCoilPower = std::abs(min(0.0, QTotUnitOut));
3397 3 : ventSlab.LateCoolCoilPower = ventSlab.TotCoolCoilPower - ventSlab.SensCoolCoilPower;
3398 3 : ventSlab.ElecFanPower = (ventSlab.Fan_Index == 0) ? 0.0 : state.dataFans->fans(ventSlab.Fan_Index)->totalPower;
3399 :
3400 3 : ventSlab.AirMassFlowRate = AirMassFlow;
3401 :
3402 3 : SpecHumOut = state.dataLoopNodes->Node(OutletNode).HumRat;
3403 3 : SpecHumIn = state.dataLoopNodes->Node(FanOutletNode).HumRat;
3404 3 : LatOutputProvided = AirMassFlow * (SpecHumOut - SpecHumIn); // Latent rate (kg/s), dehumid = negative
3405 3 : PowerMet = QUnitOut;
3406 3 : }
3407 :
3408 0 : void CalcVentilatedSlabRadComps(EnergyPlusData &state,
3409 : int const Item, // System index in ventilated slab array
3410 : [[maybe_unused]] bool const FirstHVACIteration // flag for 1st HVAV iteration in the time step !unused1208
3411 : )
3412 : {
3413 :
3414 : // SUBROUTINE INFORMATION:
3415 : // AUTHOR Young Tae Chae, Rick Strand
3416 : // DATE WRITTEN June 2008
3417 : // MODIFIED Sep 2011 LKL/BG - resimulate only zones needing it for Radiant systems
3418 :
3419 : // PURPOSE OF THIS SUBROUTINE:
3420 : // This subroutine launches the individual component simulations.
3421 : // This is called either when the system is off to carry null conditions
3422 : // through the system or during control iterations to continue updating
3423 : // what is going on within the system.
3424 :
3425 : // METHODOLOGY EMPLOYED:
3426 : // Simply calls the different components in order. Only slight wrinkles
3427 : // here are that the Ventilated Slab has it's own outside air mixed and
3428 : // that a cooling coil must be present in order to call a cooling coil
3429 : // simulation. Other than that, the subroutine is very straightforward.
3430 :
3431 : // Using/Aliasing
3432 0 : auto &ventSlab = state.dataVentilatedSlab->VentSlab(Item);
3433 :
3434 : // SUBROUTINE PARAMETER DEFINITIONS:
3435 0 : Real64 constexpr CondDeltaTemp(0.001); // How close the surface temperatures can get to the dewpoint temperature
3436 : // of a space before the radiant cooling system shuts off the flow.
3437 0 : Real64 constexpr ZeroSystemResp(0.1); // Response below which the system response is really zero
3438 0 : Real64 constexpr TempCheckLimit(0.1); // Maximum allowed temperature difference between outlet temperature calculations
3439 0 : static std::string const CurrentModuleObject("ZoneHVAC:VentilatedSlab");
3440 :
3441 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
3442 : Real64 CpAirZn; // Intermediate calculational variable for specific heat of air
3443 : Real64 DewPointTemp; // Dew-point temperature based on the zone air conditions
3444 : Real64 EpsMdotCpAirZn; // Epsilon (heat exchanger terminology) times water mass flow rate times water specific heat
3445 : Real64 Mdot; // Intermediate calculation variable for mass flow rate in a surface within the radiant system
3446 : int RadSurfNum; // DO loop counter for the surfaces that comprise a particular radiant system
3447 : // unused0309 INTEGER :: RadSurfNum4 ! DO loop counter for the surfaces that comprise a particular radiant system
3448 :
3449 : int SurfNum; // Index for radiant surface in Surface derived type
3450 : // unused0309 INTEGER :: RadSurfNumNum
3451 : Real64 TotalVentSlabRadPower; // Total heat source/sink to radiant system
3452 : Real64 AirOutletTempCheck; // Radiant system air outlet temperature (calculated from mixing all outlet streams together)
3453 : Real64 AirTempIn; // Temperature of the air entering the radiant system, in C
3454 : Real64 Ca; // Coefficients to relate the inlet air temperature to the heat source
3455 : Real64 Cb;
3456 : Real64 Cc;
3457 : Real64 Cd;
3458 : Real64 Ce;
3459 : Real64 Cf;
3460 : Real64 Cg;
3461 : Real64 Ch;
3462 : Real64 Ci;
3463 : Real64 Cj;
3464 : Real64 Ck;
3465 : Real64 Cl;
3466 : // For more info on Ca through Cl, refer Constant Flow Radiant System
3467 : // For Phase 3
3468 : Real64 CNumDS;
3469 : Real64 CLengDS;
3470 : Real64 CDiaDS;
3471 : Real64 FlowFrac;
3472 : Real64 MSlabAirInTemp;
3473 :
3474 0 : if (state.dataVentilatedSlab->FirstTimeFlag) {
3475 0 : state.dataVentilatedSlab->AirTempOut.allocate(state.dataVentilatedSlab->MaxCloNumOfSurfaces);
3476 0 : state.dataVentilatedSlab->FirstTimeFlag = false;
3477 : }
3478 :
3479 0 : int SlabInNode = ventSlab.RadInNode;
3480 0 : int FanOutletNode = ventSlab.FanOutletNode;
3481 0 : int OAInletNode = ventSlab.OutsideAirNode;
3482 0 : int MixoutNode = ventSlab.OAMixerOutNode;
3483 0 : int ReturnAirNode = ventSlab.ReturnAirNode;
3484 0 : int ZoneAirInNode = ventSlab.ZoneAirInNode;
3485 :
3486 : // Set the conditions on the air side inlet
3487 0 : int ZoneNum = ventSlab.ZonePtr;
3488 0 : Real64 ZoneMult = double(state.dataHeatBal->Zone(ZoneNum).Multiplier * state.dataHeatBal->Zone(ZoneNum).ListMultiplier);
3489 0 : Real64 AirMassFlow = state.dataLoopNodes->Node(ventSlab.RadInNode).MassFlowRate / ZoneMult;
3490 0 : auto &thisZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum);
3491 :
3492 0 : if (state.dataVentilatedSlab->OperatingMode == HeatingMode) {
3493 :
3494 0 : if ((!ventSlab.heatingCoilPresent) || (ventSlab.heatingCoilSchedValue <= 0.0)) {
3495 :
3496 0 : AirTempIn = state.dataLoopNodes->Node(FanOutletNode).Temp;
3497 0 : state.dataLoopNodes->Node(SlabInNode).Temp =
3498 0 : state.dataLoopNodes->Node(FanOutletNode).Temp; // If coil not available or running, then coil in and out temps same
3499 :
3500 : } else {
3501 :
3502 0 : AirTempIn = state.dataLoopNodes->Node(SlabInNode).Temp;
3503 : }
3504 : }
3505 :
3506 0 : if (state.dataVentilatedSlab->OperatingMode == CoolingMode) {
3507 :
3508 0 : if ((!ventSlab.coolingCoilPresent) || (ventSlab.coolingCoilSchedValue <= 0.0)) {
3509 :
3510 0 : AirTempIn = state.dataLoopNodes->Node(FanOutletNode).Temp;
3511 0 : state.dataLoopNodes->Node(SlabInNode).Temp =
3512 0 : state.dataLoopNodes->Node(FanOutletNode).Temp; // If coil not available or running, then coil in and out temps same
3513 :
3514 : } else {
3515 :
3516 0 : AirTempIn = state.dataLoopNodes->Node(SlabInNode).Temp;
3517 : }
3518 : }
3519 :
3520 0 : if (AirMassFlow <= 0.0) {
3521 : // No flow or below minimum allowed so there is no heat source/sink
3522 : // This is possible with a mismatch between system and plant operation
3523 : // or a slight mismatch between zone and system controls. This is not
3524 : // necessarily a "problem" so this exception is necessary in the code.
3525 :
3526 0 : for (RadSurfNum = 1; RadSurfNum <= ventSlab.NumOfSurfaces; ++RadSurfNum) {
3527 0 : SurfNum = ventSlab.SurfacePtr(RadSurfNum);
3528 0 : state.dataHeatBalFanSys->QRadSysSource(SurfNum) = 0.0;
3529 0 : if (state.dataSurface->Surface(SurfNum).ExtBoundCond > 0 && state.dataSurface->Surface(SurfNum).ExtBoundCond != SurfNum) {
3530 0 : state.dataHeatBalFanSys->QRadSysSource(state.dataSurface->Surface(SurfNum).ExtBoundCond) =
3531 : 0.0; // Also zero the other side of an interzone
3532 : }
3533 : }
3534 :
3535 0 : ventSlab.SlabOutTemp = ventSlab.SlabInTemp;
3536 :
3537 : // zero out node flows
3538 0 : state.dataLoopNodes->Node(SlabInNode).MassFlowRate = 0.0;
3539 0 : state.dataLoopNodes->Node(FanOutletNode).MassFlowRate = 0.0;
3540 0 : state.dataLoopNodes->Node(OAInletNode).MassFlowRate = 0.0;
3541 0 : state.dataLoopNodes->Node(MixoutNode).MassFlowRate = 0.0;
3542 0 : state.dataLoopNodes->Node(ReturnAirNode).MassFlowRate = 0.0;
3543 0 : state.dataLoopNodes->Node(FanOutletNode).Temp = state.dataLoopNodes->Node(SlabInNode).Temp;
3544 0 : AirMassFlow = 0.0;
3545 : }
3546 :
3547 0 : if (AirMassFlow > 0.0) {
3548 :
3549 0 : if ((ventSlab.SysConfg == VentilatedSlabConfig::SlabOnly) || (ventSlab.SysConfg == VentilatedSlabConfig::SlabAndZone)) {
3550 :
3551 0 : for (RadSurfNum = 1; RadSurfNum <= ventSlab.NumOfSurfaces; ++RadSurfNum) {
3552 0 : SurfNum = ventSlab.SurfacePtr(RadSurfNum);
3553 : // Determine the heat exchanger "effectiveness" term
3554 0 : EpsMdotCpAirZn = CalcVentSlabHXEffectTerm(state,
3555 : Item,
3556 : AirTempIn,
3557 : AirMassFlow,
3558 0 : ventSlab.SurfaceFlowFrac(RadSurfNum),
3559 : ventSlab.CoreLength,
3560 : ventSlab.CoreDiameter,
3561 : ventSlab.CoreNumbers);
3562 :
3563 : // Obtain the heat balance coefficients and calculate the intermediate coefficients
3564 : // linking the inlet air temperature to the heat source/sink to the radiant system.
3565 : // The coefficients are based on the Constant Flow Radiation System.
3566 :
3567 0 : int ConstrNum = state.dataSurface->Surface(SurfNum).Construction;
3568 0 : auto const &thisConstruct = state.dataConstruction->Construct(ConstrNum);
3569 :
3570 0 : Ca = state.dataHeatBalFanSys->RadSysTiHBConstCoef(SurfNum);
3571 0 : Cb = state.dataHeatBalFanSys->RadSysTiHBToutCoef(SurfNum);
3572 0 : Cc = state.dataHeatBalFanSys->RadSysTiHBQsrcCoef(SurfNum);
3573 :
3574 0 : Cd = state.dataHeatBalFanSys->RadSysToHBConstCoef(SurfNum);
3575 0 : Ce = state.dataHeatBalFanSys->RadSysToHBTinCoef(SurfNum);
3576 0 : Cf = state.dataHeatBalFanSys->RadSysToHBQsrcCoef(SurfNum);
3577 :
3578 0 : Cg = state.dataHeatBalFanSys->CTFTsrcConstPart(SurfNum);
3579 0 : Ch = double(thisConstruct.CTFTSourceQ[0]);
3580 0 : Ci = double(thisConstruct.CTFTSourceIn[0]);
3581 0 : Cj = double(thisConstruct.CTFTSourceOut[0]);
3582 :
3583 0 : Ck = Cg + ((Ci * (Ca + Cb * Cd) + Cj * (Cd + Ce * Ca)) / (1.0 - Ce * Cb));
3584 0 : Cl = Ch + ((Ci * (Cc + Cb * Cf) + Cj * (Cf + Ce * Cc)) / (1.0 - Ce * Cb));
3585 :
3586 0 : Mdot = AirMassFlow * ventSlab.SurfaceFlowFrac(RadSurfNum);
3587 0 : CpAirZn = Psychrometrics::PsyCpAirFnW(state.dataLoopNodes->Node(ventSlab.RadInNode).HumRat);
3588 :
3589 0 : state.dataHeatBalFanSys->QRadSysSource(SurfNum) = ventSlab.CoreNumbers * EpsMdotCpAirZn * (AirTempIn - Ck) /
3590 0 : (1.0 + (EpsMdotCpAirZn * Cl / state.dataSurface->Surface(SurfNum).Area));
3591 :
3592 0 : if (state.dataSurface->Surface(SurfNum).ExtBoundCond > 0 && state.dataSurface->Surface(SurfNum).ExtBoundCond != SurfNum) {
3593 0 : state.dataHeatBalFanSys->QRadSysSource(state.dataSurface->Surface(SurfNum).ExtBoundCond) =
3594 0 : state.dataHeatBalFanSys->QRadSysSource(SurfNum);
3595 : }
3596 : // Also set the other side of an interzone!
3597 0 : state.dataVentilatedSlab->AirTempOut(RadSurfNum) =
3598 0 : AirTempIn - (state.dataHeatBalFanSys->QRadSysSource(SurfNum) / (Mdot * CpAirZn));
3599 :
3600 : // "Temperature Comparison" Cut-off:
3601 : // Check to see whether or not the system should really be running. If
3602 : // QRadSysSource is negative when we are in heating mode or QRadSysSource
3603 : // is positive when we are in cooling mode, then the radiant system will
3604 : // be doing the opposite of its intention. In this case, the flow rate
3605 : // is set to zero to avoid heating in cooling mode or cooling in heating
3606 : // mode.
3607 :
3608 0 : if (((state.dataVentilatedSlab->OperatingMode == HeatingMode) && (state.dataHeatBalFanSys->QRadSysSource(SurfNum) <= 0.0)) ||
3609 0 : ((state.dataVentilatedSlab->OperatingMode == CoolingMode) && (state.dataHeatBalFanSys->QRadSysSource(SurfNum) >= 0.0))) {
3610 :
3611 : // IF (.not. WarmupFlag) THEN
3612 : // TempComparisonErrorCount = TempComparisonErrorCount + 1
3613 : // IF (TempComparisonErrorCount <= NumOfVentSlabs) THEN
3614 : // CALL ShowWarningError(state, 'Radaint Heat exchange is negative in Heating Mode or posive in Cooling Mode')
3615 : // CALL ShowContinueError(state, 'Flow to the following ventilated slab will be shut-off to avoid heating in cooling mode
3616 : // or cooling &
3617 : // in heating mode')
3618 : // CALL ShowContinueError(state, 'Ventilated Slab Name = '//TRIM(VentSlab(Item)%Name))
3619 : // CALL ShowContinueError(state, 'All node temperature are reseted at the ventilated slab surface temperature = '// &
3620 : // RoundSigDigits(TH(VentSlab(Item)%SurfacePtr(RadSurfNum),1,2),2))
3621 : // CALL ShowContinueErrorTimeStamp(state, ' ')
3622 : // ELSE
3623 : // CALL ShowRecurringWarningErrorAtEnd(state, 'Ventilated Slab ['//TRIM(VentSlab(Item)%Name)// &
3624 : // '] Temperature Comparison Error shut-off occurrence continues.', &
3625 : // VentSlab(Item)%CondErrCount)
3626 : // END IF
3627 : // END IF
3628 :
3629 0 : state.dataLoopNodes->Node(SlabInNode).MassFlowRate = 0.0;
3630 0 : state.dataLoopNodes->Node(FanOutletNode).MassFlowRate = 0.0;
3631 0 : state.dataLoopNodes->Node(OAInletNode).MassFlowRate = 0.0;
3632 0 : state.dataLoopNodes->Node(MixoutNode).MassFlowRate = 0.0;
3633 0 : state.dataLoopNodes->Node(ReturnAirNode).MassFlowRate = 0.0;
3634 0 : AirMassFlow = 0.0;
3635 :
3636 0 : for (int RadSurfNum2 = 1; RadSurfNum2 <= ventSlab.NumOfSurfaces; ++RadSurfNum2) {
3637 0 : int SurfNum2 = ventSlab.SurfacePtr(RadSurfNum2);
3638 0 : state.dataHeatBalFanSys->QRadSysSource(SurfNum2) = 0.0;
3639 0 : if (state.dataSurface->Surface(SurfNum2).ExtBoundCond > 0 &&
3640 0 : state.dataSurface->Surface(SurfNum2).ExtBoundCond != SurfNum2) {
3641 0 : state.dataHeatBalFanSys->QRadSysSource(state.dataSurface->Surface(SurfNum2).ExtBoundCond) =
3642 : 0.0; // Also zero the other side of an interzone
3643 : }
3644 :
3645 0 : if (ventSlab.SysConfg == VentilatedSlabConfig::SlabOnly) {
3646 : // state.dataLoopNodes->Node(Returnairnode)%Temp = MAT(Zonenum)
3647 0 : state.dataLoopNodes->Node(ReturnAirNode).Temp =
3648 0 : state.dataHeatBalSurf->SurfInsideTempHist(1)(ventSlab.SurfacePtr(RadSurfNum));
3649 0 : state.dataLoopNodes->Node(FanOutletNode).Temp = state.dataLoopNodes->Node(ReturnAirNode).Temp;
3650 0 : state.dataLoopNodes->Node(SlabInNode).Temp = state.dataLoopNodes->Node(FanOutletNode).Temp;
3651 0 : } else if (ventSlab.SysConfg == VentilatedSlabConfig::SlabAndZone) {
3652 0 : state.dataLoopNodes->Node(ReturnAirNode).Temp = thisZoneHB.MAT;
3653 0 : state.dataLoopNodes->Node(SlabInNode).Temp = state.dataLoopNodes->Node(ReturnAirNode).Temp;
3654 0 : state.dataLoopNodes->Node(FanOutletNode).Temp = state.dataLoopNodes->Node(SlabInNode).Temp;
3655 0 : state.dataLoopNodes->Node(ZoneAirInNode).Temp = state.dataLoopNodes->Node(SlabInNode).Temp;
3656 : }
3657 : }
3658 0 : break; // outer do loop
3659 : }
3660 :
3661 : // Condensation Cut-off:
3662 : // Check to see whether there are any surface temperatures within the radiant system that have
3663 : // dropped below the dew-point temperature. If so, we need to shut off this radiant system.
3664 : // A safety parameter is added (hardwired parameter) to avoid getting too close to condensation
3665 : // conditions.
3666 :
3667 0 : if (state.dataVentilatedSlab->OperatingMode == CoolingMode) {
3668 0 : DewPointTemp = Psychrometrics::PsyTdpFnWPb(state, thisZoneHB.airHumRat, state.dataEnvrn->OutBaroPress);
3669 0 : for (int RadSurfNum2 = 1; RadSurfNum2 <= ventSlab.NumOfSurfaces; ++RadSurfNum2) {
3670 0 : if (state.dataHeatBalSurf->SurfInsideTempHist(1)(ventSlab.SurfacePtr(RadSurfNum2)) < (DewPointTemp + CondDeltaTemp)) {
3671 : // Condensation warning--must shut off radiant system
3672 0 : state.dataLoopNodes->Node(SlabInNode).MassFlowRate = 0.0;
3673 0 : state.dataLoopNodes->Node(FanOutletNode).MassFlowRate = 0.0;
3674 0 : state.dataLoopNodes->Node(OAInletNode).MassFlowRate = 0.0;
3675 0 : state.dataLoopNodes->Node(MixoutNode).MassFlowRate = 0.0;
3676 0 : state.dataLoopNodes->Node(ReturnAirNode).MassFlowRate = 0.0;
3677 0 : state.dataLoopNodes->Node(FanOutletNode).Temp = state.dataLoopNodes->Node(SlabInNode).Temp;
3678 0 : AirMassFlow = 0.0;
3679 0 : for (int RadSurfNum3 = 1; RadSurfNum3 <= ventSlab.NumOfSurfaces; ++RadSurfNum3) {
3680 0 : int SurfNum2 = ventSlab.SurfacePtr(RadSurfNum3);
3681 0 : state.dataHeatBalFanSys->QRadSysSource(SurfNum2) = 0.0;
3682 0 : if (state.dataSurface->Surface(SurfNum2).ExtBoundCond > 0 &&
3683 0 : state.dataSurface->Surface(SurfNum2).ExtBoundCond != SurfNum2) {
3684 0 : state.dataHeatBalFanSys->QRadSysSource(state.dataSurface->Surface(SurfNum2).ExtBoundCond) =
3685 : 0.0; // Also zero the other side of an interzone
3686 : }
3687 : }
3688 : // Produce a warning message so that user knows the system was shut-off due to potential for condensation
3689 0 : if (!state.dataGlobal->WarmupFlag) {
3690 0 : ++state.dataVentilatedSlab->CondensationErrorCount;
3691 :
3692 0 : if (ventSlab.CondErrIndex == 0) {
3693 0 : ShowWarningMessage(state, format("{} [{}]", cMO_VentilatedSlab, ventSlab.Name));
3694 0 : ShowContinueError(
3695 : state,
3696 0 : format("Surface [{}] temperature below dew-point temperature--potential for condensation exists",
3697 0 : state.dataSurface->Surface(ventSlab.SurfacePtr(RadSurfNum2)).Name));
3698 0 : ShowContinueError(state, "Flow to the ventilated slab system will be shut-off to avoid condensation");
3699 0 : ShowContinueError(state,
3700 0 : format("Predicted radiant system surface temperature = {:.2R}",
3701 0 : state.dataHeatBalSurf->SurfInsideTempHist(1)(ventSlab.SurfacePtr(RadSurfNum2))));
3702 0 : ShowContinueError(
3703 0 : state, format("Zone dew-point temperature + safety factor delta= {:.2R}", DewPointTemp + CondDeltaTemp));
3704 0 : ShowContinueErrorTimeStamp(state, "");
3705 : }
3706 0 : if (state.dataVentilatedSlab->CondensationErrorCount == 1) {
3707 0 : ShowContinueError(
3708 0 : state, format("Note that there is a {:.4R} C safety built-in to the shut-off criteria", CondDeltaTemp));
3709 0 : ShowContinueError(state, "Note also that this affects all surfaces that are part of this system");
3710 : }
3711 0 : ShowRecurringWarningErrorAtEnd(state,
3712 0 : cMO_VentilatedSlab + " [" + ventSlab.Name +
3713 : "] condensation shut-off occurrence continues.",
3714 0 : ventSlab.CondErrIndex,
3715 : DewPointTemp,
3716 : DewPointTemp,
3717 : _,
3718 : "C",
3719 : "C");
3720 : }
3721 0 : break; // outer do loop
3722 : }
3723 : }
3724 : }
3725 : }
3726 :
3727 : // Total Radiant Power
3728 0 : AirOutletTempCheck = 0.0;
3729 0 : TotalVentSlabRadPower = 0.0;
3730 0 : for (RadSurfNum = 1; RadSurfNum <= ventSlab.NumOfSurfaces; ++RadSurfNum) {
3731 0 : SurfNum = ventSlab.SurfacePtr(RadSurfNum);
3732 0 : TotalVentSlabRadPower += state.dataHeatBalFanSys->QRadSysSource(SurfNum);
3733 0 : AirOutletTempCheck += (ventSlab.SurfaceFlowFrac(RadSurfNum) * state.dataVentilatedSlab->AirTempOut(RadSurfNum));
3734 : }
3735 0 : TotalVentSlabRadPower *= ZoneMult;
3736 :
3737 : // Return Air temp Check
3738 0 : if (ventSlab.SysConfg == VentilatedSlabConfig::SlabOnly) {
3739 0 : if (AirMassFlow > 0.0) {
3740 0 : CpAirZn = Psychrometrics::PsyCpAirFnW(state.dataLoopNodes->Node(ventSlab.RadInNode).HumRat);
3741 0 : state.dataLoopNodes->Node(ReturnAirNode).Temp =
3742 0 : state.dataLoopNodes->Node(SlabInNode).Temp - (TotalVentSlabRadPower / (AirMassFlow * CpAirZn));
3743 0 : if ((std::abs(state.dataLoopNodes->Node(ReturnAirNode).Temp - AirOutletTempCheck) > TempCheckLimit) &&
3744 0 : (std::abs(TotalVentSlabRadPower) > ZeroSystemResp)) {
3745 :
3746 0 : if (!state.dataGlobal->WarmupFlag) {
3747 0 : ++state.dataVentilatedSlab->EnergyImbalanceErrorCount;
3748 0 : if (ventSlab.EnrgyImbalErrIndex == 0) {
3749 0 : ShowWarningMessage(state, format("{} [{}]", cMO_VentilatedSlab, ventSlab.Name));
3750 0 : ShowContinueError(state, "Ventilated Slab (slab only type) air outlet temperature calculation mismatch.");
3751 0 : ShowContinueError(state,
3752 : "This should not happen as it indicates a potential energy imbalance in the calculations.");
3753 0 : ShowContinueError(state, "However, it could also result from improper input for the ventilated slab or");
3754 0 : ShowContinueError(state, "illogical control temperatures. Check your input for this ventilated slab and");
3755 0 : ShowContinueError(state, "also look at the internal data shown below.");
3756 0 : ShowContinueError(state,
3757 0 : format("Predicted return air temperature [C] from the overall energy balance = {:.4R}",
3758 0 : state.dataLoopNodes->Node(ReturnAirNode).Temp));
3759 0 : ShowContinueError(state,
3760 0 : format("Predicted return air temperature [C] from the slab section energy balances = {:.4R}",
3761 : AirOutletTempCheck));
3762 0 : ShowContinueError(state,
3763 0 : format("Total energy rate (power) [W] added to the slab = {:.4R}", TotalVentSlabRadPower));
3764 0 : ShowContinueErrorTimeStamp(state, "");
3765 : }
3766 0 : ShowRecurringWarningErrorAtEnd(state,
3767 0 : cMO_VentilatedSlab + " [" + ventSlab.Name +
3768 : "] temperature calculation mismatch occurrence continues.",
3769 0 : ventSlab.EnrgyImbalErrIndex);
3770 : }
3771 : }
3772 : } else {
3773 0 : state.dataLoopNodes->Node(ReturnAirNode).Temp = state.dataLoopNodes->Node(SlabInNode).Temp;
3774 : }
3775 : }
3776 :
3777 0 : if (ventSlab.SysConfg == VentilatedSlabConfig::SlabAndZone) {
3778 0 : if (AirMassFlow > 0.0) {
3779 0 : state.dataLoopNodes->Node(ZoneAirInNode).Temp =
3780 0 : state.dataLoopNodes->Node(SlabInNode).Temp - (TotalVentSlabRadPower / (AirMassFlow * CpAirZn));
3781 0 : if ((std::abs(state.dataLoopNodes->Node(ZoneAirInNode).Temp - AirOutletTempCheck) > TempCheckLimit) &&
3782 0 : (std::abs(TotalVentSlabRadPower) > ZeroSystemResp)) {
3783 :
3784 0 : if (!state.dataGlobal->WarmupFlag) {
3785 0 : ++state.dataVentilatedSlab->EnergyImbalanceErrorCount;
3786 0 : if (ventSlab.EnrgyImbalErrIndex == 0) {
3787 0 : ShowWarningMessage(state, format("{} [{}]", cMO_VentilatedSlab, ventSlab.Name));
3788 0 : ShowContinueError(state, "Ventilated Slab (slab only type) air outlet temperature calculation mismatch.");
3789 0 : ShowContinueError(state,
3790 : "This should not happen as it indicates a potential energy imbalance in the calculations.");
3791 0 : ShowContinueError(state, "However, it could also result from improper input for the ventilated slab or");
3792 0 : ShowContinueError(state, "illogical control temperatures. Check your input for this ventilated slab and");
3793 0 : ShowContinueError(state, "also look at the internal data shown below.");
3794 0 : ShowContinueError(state,
3795 0 : format("Predicted return air temperature [C] from the overall energy balance = {:.4R}",
3796 0 : state.dataLoopNodes->Node(ReturnAirNode).Temp));
3797 0 : ShowContinueError(state,
3798 0 : format("Predicted return air temperature [C] from the slab section energy balances = {:.4R}",
3799 : AirOutletTempCheck));
3800 0 : ShowContinueError(state,
3801 0 : format("Total energy rate (power) [W] added to the slab = {:.4R}", TotalVentSlabRadPower));
3802 0 : ShowContinueErrorTimeStamp(state, "");
3803 : }
3804 0 : ShowRecurringWarningErrorAtEnd(state,
3805 0 : cMO_VentilatedSlab + " [" + ventSlab.Name +
3806 : "] temperature calculation mismatch occurrence continues.",
3807 0 : ventSlab.EnrgyImbalErrIndex);
3808 : }
3809 : }
3810 : // IF ((.NOT. FirstHVACIteration) .AND. &
3811 : // (ABS(Node(ReturnAirNode)%Temp-MAT(Zonenum)) > VentSlabAirTempToler))THEN
3812 : // NeedtoIterate = .TRUE.
3813 : // END IF
3814 : // state.dataLoopNodes->Node(ReturnAirNode)%Temp = MAT(Zonenum)
3815 : } else {
3816 0 : state.dataLoopNodes->Node(ZoneAirInNode).Temp = state.dataLoopNodes->Node(SlabInNode).Temp;
3817 0 : state.dataLoopNodes->Node(ReturnAirNode).Temp = thisZoneHB.MAT;
3818 : }
3819 : }
3820 :
3821 : // Now that we have the source/sink term, we must redo the heat balances to obtain
3822 : // the new SumHATsurf value for the zone. Note that the difference between the new
3823 : // SumHATsurf and the value originally calculated by the heat balance with a zero
3824 : // source for all radiant systems in the zone is the load met by the system (approximately).
3825 0 : HeatBalanceSurfaceManager::CalcHeatBalanceOutsideSurf(state, ZoneNum);
3826 0 : HeatBalanceSurfaceManager::CalcHeatBalanceInsideSurf(state, ZoneNum);
3827 :
3828 : } // SYSCONFIG. SLABONLY&SLABANDZONE
3829 :
3830 0 : if (ventSlab.SysConfg == VentilatedSlabConfig::SeriesSlabs) {
3831 :
3832 0 : for (RadSurfNum = 1; RadSurfNum <= ventSlab.NumOfSurfaces; ++RadSurfNum) {
3833 :
3834 0 : CNumDS = ventSlab.CNumbers(RadSurfNum);
3835 0 : CLengDS = ventSlab.CLength(RadSurfNum); // for check
3836 0 : CDiaDS = ventSlab.CDiameter(RadSurfNum); // for check
3837 0 : FlowFrac = 1.0;
3838 :
3839 0 : SurfNum = ventSlab.SurfacePtr(RadSurfNum);
3840 :
3841 : // Determine the heat exchanger "effectiveness" term
3842 0 : EpsMdotCpAirZn = CalcVentSlabHXEffectTerm(state, Item, AirTempIn, AirMassFlow, FlowFrac, CLengDS, CDiaDS, CNumDS);
3843 :
3844 : // Obtain the heat balance coefficients and calculate the intermediate coefficients
3845 : // linking the inlet air temperature to the heat source/sink to the radiant system.
3846 : // The coefficients are based on the Constant Flow Radiation System.
3847 :
3848 0 : int ConstrNum = state.dataSurface->Surface(SurfNum).Construction;
3849 :
3850 0 : Ca = state.dataHeatBalFanSys->RadSysTiHBConstCoef(SurfNum);
3851 0 : Cb = state.dataHeatBalFanSys->RadSysTiHBToutCoef(SurfNum);
3852 0 : Cc = state.dataHeatBalFanSys->RadSysTiHBQsrcCoef(SurfNum);
3853 :
3854 0 : Cd = state.dataHeatBalFanSys->RadSysToHBConstCoef(SurfNum);
3855 0 : Ce = state.dataHeatBalFanSys->RadSysToHBTinCoef(SurfNum);
3856 0 : Cf = state.dataHeatBalFanSys->RadSysToHBQsrcCoef(SurfNum);
3857 :
3858 0 : Cg = state.dataHeatBalFanSys->CTFTsrcConstPart(SurfNum);
3859 0 : Ch = double(state.dataConstruction->Construct(ConstrNum).CTFTSourceQ[0]);
3860 0 : Ci = double(state.dataConstruction->Construct(ConstrNum).CTFTSourceIn[0]);
3861 0 : Cj = double(state.dataConstruction->Construct(ConstrNum).CTFTSourceOut[0]);
3862 :
3863 0 : Ck = Cg + ((Ci * (Ca + Cb * Cd) + Cj * (Cd + Ce * Ca)) / (1.0 - Ce * Cb));
3864 0 : Cl = Ch + ((Ci * (Cc + Cb * Cf) + Cj * (Cf + Ce * Cc)) / (1.0 - Ce * Cb));
3865 :
3866 0 : Mdot = AirMassFlow * FlowFrac;
3867 0 : CpAirZn = Psychrometrics::PsyCpAirFnW(state.dataLoopNodes->Node(ventSlab.RadInNode).HumRat);
3868 :
3869 0 : state.dataHeatBalFanSys->QRadSysSource(SurfNum) =
3870 0 : CNumDS * EpsMdotCpAirZn * (AirTempIn - Ck) / (1.0 + (EpsMdotCpAirZn * Cl / state.dataSurface->Surface(SurfNum).Area));
3871 :
3872 0 : if (state.dataSurface->Surface(SurfNum).ExtBoundCond > 0 && state.dataSurface->Surface(SurfNum).ExtBoundCond != SurfNum) {
3873 0 : state.dataHeatBalFanSys->QRadSysSource(state.dataSurface->Surface(SurfNum).ExtBoundCond) =
3874 0 : state.dataHeatBalFanSys->QRadSysSource(SurfNum);
3875 : }
3876 : // Also set the other side of an interzone!
3877 :
3878 0 : state.dataVentilatedSlab->AirTempOut(RadSurfNum) =
3879 0 : AirTempIn - (state.dataHeatBalFanSys->QRadSysSource(SurfNum) / (Mdot * CpAirZn));
3880 0 : AirTempIn = state.dataVentilatedSlab->AirTempOut(RadSurfNum);
3881 : // "Temperature Comparison" Cut-off:
3882 : // Check to see whether or not the system should really be running. If
3883 : // QRadSysSource is negative when we are in heating mode or QRadSysSource
3884 : // is positive when we are in cooling mode, then the radiant system will
3885 : // be doing the opposite of its intention. In this case, the flow rate
3886 : // is set to zero to avoid heating in cooling mode or cooling in heating
3887 : // mode.
3888 :
3889 0 : if (RadSurfNum == 1) {
3890 0 : if (((state.dataVentilatedSlab->OperatingMode == HeatingMode) && (state.dataHeatBalFanSys->QRadSysSource(SurfNum) <= 0.0)) ||
3891 0 : ((state.dataVentilatedSlab->OperatingMode == CoolingMode) && (state.dataHeatBalFanSys->QRadSysSource(SurfNum) >= 0.0))) {
3892 0 : state.dataLoopNodes->Node(SlabInNode).MassFlowRate = 0.0;
3893 0 : state.dataLoopNodes->Node(FanOutletNode).MassFlowRate = 0.0;
3894 0 : state.dataLoopNodes->Node(OAInletNode).MassFlowRate = 0.0;
3895 0 : state.dataLoopNodes->Node(MixoutNode).MassFlowRate = 0.0;
3896 0 : state.dataLoopNodes->Node(ReturnAirNode).MassFlowRate = 0.0;
3897 0 : AirMassFlow = 0.0;
3898 :
3899 0 : for (int RadSurfNum2 = 1; RadSurfNum2 <= ventSlab.NumOfSurfaces; ++RadSurfNum2) {
3900 0 : int SurfNum2 = ventSlab.SurfacePtr(RadSurfNum2);
3901 0 : state.dataHeatBalFanSys->QRadSysSource(SurfNum2) = 0.0;
3902 0 : if (state.dataSurface->Surface(SurfNum2).ExtBoundCond > 0 &&
3903 0 : state.dataSurface->Surface(SurfNum2).ExtBoundCond != SurfNum2) {
3904 0 : state.dataHeatBalFanSys->QRadSysSource(state.dataSurface->Surface(SurfNum2).ExtBoundCond) =
3905 : 0.0; // Also zero the other side of an interzone
3906 : }
3907 : }
3908 0 : state.dataLoopNodes->Node(ReturnAirNode).Temp = state.dataHeatBalSurf->SurfInsideTempHist(1)(ventSlab.SurfacePtr(1));
3909 0 : state.dataLoopNodes->Node(FanOutletNode).Temp = state.dataLoopNodes->Node(ReturnAirNode).Temp;
3910 0 : state.dataLoopNodes->Node(SlabInNode).Temp = state.dataLoopNodes->Node(FanOutletNode).Temp;
3911 : // Each Internal node is reseted at the surface temperature
3912 :
3913 0 : break; // outer do loop
3914 : }
3915 : }
3916 : // Condensation Cut-off:
3917 : // Check to see whether there are any surface temperatures within the radiant system that have
3918 : // dropped below the dew-point temperature. If so, we need to shut off this radiant system.
3919 : // A safety parameter is added (hardwired parameter) to avoid getting too close to condensation
3920 : // conditions.
3921 :
3922 0 : if (state.dataVentilatedSlab->OperatingMode == CoolingMode) {
3923 0 : DewPointTemp =
3924 0 : Psychrometrics::PsyTdpFnWPb(state,
3925 0 : state.dataZoneTempPredictorCorrector->zoneHeatBalance(ventSlab.ZPtr(RadSurfNum)).airHumRat,
3926 0 : state.dataEnvrn->OutBaroPress);
3927 0 : for (int RadSurfNum2 = 1; RadSurfNum2 <= ventSlab.NumOfSurfaces; ++RadSurfNum2) {
3928 0 : if (state.dataHeatBalSurf->SurfInsideTempHist(1)(ventSlab.SurfacePtr(RadSurfNum2)) < (DewPointTemp + CondDeltaTemp)) {
3929 : // Condensation warning--must shut off radiant system
3930 0 : state.dataLoopNodes->Node(SlabInNode).MassFlowRate = 0.0;
3931 0 : state.dataLoopNodes->Node(FanOutletNode).MassFlowRate = 0.0;
3932 0 : state.dataLoopNodes->Node(OAInletNode).MassFlowRate = 0.0;
3933 0 : state.dataLoopNodes->Node(MixoutNode).MassFlowRate = 0.0;
3934 0 : state.dataLoopNodes->Node(ReturnAirNode).MassFlowRate = 0.0;
3935 0 : state.dataLoopNodes->Node(FanOutletNode).Temp = state.dataLoopNodes->Node(SlabInNode).Temp;
3936 0 : AirMassFlow = 0.0;
3937 0 : for (int RadSurfNum3 = 1; RadSurfNum3 <= ventSlab.NumOfSurfaces; ++RadSurfNum3) {
3938 0 : int SurfNum2 = ventSlab.SurfacePtr(RadSurfNum3);
3939 0 : state.dataHeatBalFanSys->QRadSysSource(SurfNum2) = 0.0;
3940 0 : if (state.dataSurface->Surface(SurfNum2).ExtBoundCond > 0 &&
3941 0 : state.dataSurface->Surface(SurfNum2).ExtBoundCond != SurfNum2) {
3942 0 : state.dataHeatBalFanSys->QRadSysSource(state.dataSurface->Surface(SurfNum2).ExtBoundCond) =
3943 : 0.0; // Also zero the other side of an interzone
3944 : }
3945 : }
3946 : // Produce a warning message so that user knows the system was shut-off due to potential for condensation
3947 0 : if (!state.dataGlobal->WarmupFlag) {
3948 0 : ++state.dataVentilatedSlab->CondensationErrorCount;
3949 0 : if (ventSlab.CondErrIndex == 0) {
3950 0 : ShowWarningMessage(state, format("{} [{}]", cMO_VentilatedSlab, ventSlab.Name));
3951 0 : ShowContinueError(
3952 : state,
3953 0 : format("Surface [{}] temperature below dew-point temperature--potential for condensation exists",
3954 0 : state.dataSurface->Surface(ventSlab.SurfacePtr(RadSurfNum2)).Name));
3955 0 : ShowContinueError(state, "Flow to the ventilated slab system will be shut-off to avoid condensation");
3956 0 : ShowContinueError(state,
3957 0 : format("Predicted radiant system surface temperature = {:.2R}",
3958 0 : state.dataHeatBalSurf->SurfInsideTempHist(1)(ventSlab.SurfacePtr(RadSurfNum2))));
3959 0 : ShowContinueError(
3960 0 : state, format("Zone dew-point temperature + safety factor delta= {:.2R}", DewPointTemp + CondDeltaTemp));
3961 0 : ShowContinueErrorTimeStamp(state, "");
3962 : }
3963 0 : if (state.dataVentilatedSlab->CondensationErrorCount == 1) {
3964 0 : ShowContinueError(
3965 0 : state, format("Note that there is a {:.4R} C safety built-in to the shut-off criteria", CondDeltaTemp));
3966 0 : ShowContinueError(state, "Note also that this affects all surfaces that are part of this system");
3967 : }
3968 0 : ShowRecurringWarningErrorAtEnd(state,
3969 0 : cMO_VentilatedSlab + " [" + ventSlab.Name +
3970 : "] condensation shut-off occurrence continues.",
3971 0 : ventSlab.CondErrIndex,
3972 : DewPointTemp,
3973 : DewPointTemp,
3974 : _,
3975 : "C",
3976 : "C");
3977 : }
3978 0 : break; // outer do loop
3979 : }
3980 : }
3981 : }
3982 : }
3983 :
3984 : // Total Radiant Power
3985 0 : AirOutletTempCheck = 0.0;
3986 0 : TotalVentSlabRadPower = 0.0;
3987 0 : for (RadSurfNum = 1; RadSurfNum <= ventSlab.NumOfSurfaces; ++RadSurfNum) {
3988 0 : SurfNum = ventSlab.SurfacePtr(RadSurfNum);
3989 0 : TotalVentSlabRadPower += state.dataHeatBalFanSys->QRadSysSource(SurfNum);
3990 0 : AirOutletTempCheck = state.dataVentilatedSlab->AirTempOut(RadSurfNum);
3991 : }
3992 0 : TotalVentSlabRadPower *= ZoneMult;
3993 :
3994 : // Internal Node Temperature Check
3995 :
3996 0 : MSlabAirInTemp = state.dataLoopNodes->Node(SlabInNode).Temp;
3997 0 : bool ErrorsFound = false; // Set to true if errors in input, fatal at end of routine
3998 :
3999 0 : for (RadSurfNum = 1; RadSurfNum <= ventSlab.NumOfSurfaces; ++RadSurfNum) {
4000 0 : std::string SlabName = ventSlab.SurfaceName(RadSurfNum);
4001 0 : std::string MSlabIn = ventSlab.SlabIn(RadSurfNum);
4002 0 : std::string MSlabOut = ventSlab.SlabOut(RadSurfNum);
4003 0 : ventSlab.MSlabInNode = NodeInputManager::GetOnlySingleNode(state,
4004 : MSlabIn,
4005 : ErrorsFound,
4006 : DataLoopNode::ConnectionObjectType::ZoneHVACVentilatedSlab,
4007 : SlabName,
4008 : DataLoopNode::NodeFluidType::Air,
4009 : DataLoopNode::ConnectionType::Internal,
4010 : NodeInputManager::CompFluidStream::Primary,
4011 : DataLoopNode::ObjectIsNotParent);
4012 0 : ventSlab.MSlabOutNode = NodeInputManager::GetOnlySingleNode(state,
4013 : MSlabOut,
4014 : ErrorsFound,
4015 : DataLoopNode::ConnectionObjectType::ZoneHVACVentilatedSlab,
4016 : SlabName,
4017 : DataLoopNode::NodeFluidType::Air,
4018 : DataLoopNode::ConnectionType::Internal,
4019 : NodeInputManager::CompFluidStream::Primary,
4020 : DataLoopNode::ObjectIsNotParent);
4021 0 : int MSlabInletNode = ventSlab.MSlabInNode;
4022 0 : int MSlabOutletNode = ventSlab.MSlabOutNode;
4023 0 : SurfNum = ventSlab.SurfacePtr(RadSurfNum);
4024 :
4025 0 : if (AirMassFlow > 0.0) {
4026 :
4027 0 : CpAirZn = Psychrometrics::PsyCpAirFnW(state.dataLoopNodes->Node(ventSlab.RadInNode).HumRat);
4028 :
4029 0 : state.dataLoopNodes->Node(MSlabInletNode).Temp = MSlabAirInTemp;
4030 0 : state.dataLoopNodes->Node(MSlabOutletNode).Temp = state.dataLoopNodes->Node(MSlabInletNode).Temp -
4031 0 : (state.dataHeatBalFanSys->QRadSysSource(SurfNum) / (AirMassFlow * CpAirZn));
4032 0 : MSlabAirInTemp = state.dataLoopNodes->Node(MSlabOutletNode).Temp;
4033 : } else {
4034 0 : state.dataLoopNodes->Node(MSlabInletNode).Temp = state.dataLoopNodes->Node(ReturnAirNode).Temp;
4035 0 : state.dataLoopNodes->Node(MSlabOutletNode).Temp = state.dataLoopNodes->Node(MSlabInletNode).Temp;
4036 : }
4037 0 : }
4038 :
4039 : // Return Air temp Check
4040 0 : if (AirMassFlow > 0.0) {
4041 :
4042 0 : CpAirZn = Psychrometrics::PsyCpAirFnW(state.dataLoopNodes->Node(ventSlab.RadInNode).HumRat);
4043 0 : state.dataLoopNodes->Node(ReturnAirNode).Temp =
4044 0 : state.dataLoopNodes->Node(SlabInNode).Temp - (TotalVentSlabRadPower / (AirMassFlow * CpAirZn));
4045 :
4046 0 : if ((std::abs(state.dataLoopNodes->Node(ReturnAirNode).Temp - AirOutletTempCheck) > TempCheckLimit) &&
4047 0 : (std::abs(TotalVentSlabRadPower) > ZeroSystemResp)) { // Return air temperature check did not match calculated temp
4048 :
4049 0 : if (!state.dataGlobal->WarmupFlag) {
4050 0 : ++state.dataVentilatedSlab->EnergyImbalanceErrorCount;
4051 0 : if (ventSlab.EnrgyImbalErrIndex == 0) {
4052 0 : ShowWarningMessage(state, format("{} [{}]", cMO_VentilatedSlab, ventSlab.Name));
4053 0 : ShowContinueError(state, "Ventilated Slab (slab only type) air outlet temperature calculation mismatch.");
4054 0 : ShowContinueError(state, "This should not happen as it indicates a potential energy imbalance in the calculations.");
4055 0 : ShowContinueError(state, "However, it could also result from improper input for the ventilated slab or");
4056 0 : ShowContinueError(state, "illogical control temperatures. Check your input for this ventilated slab and");
4057 0 : ShowContinueError(state, "also look at the internal data shown below.");
4058 0 : ShowContinueError(state,
4059 0 : format("Predicted return air temperature [C] from the overall energy balance = {:.4R}",
4060 0 : state.dataLoopNodes->Node(ReturnAirNode).Temp));
4061 0 : ShowContinueError(state,
4062 0 : format("Predicted return air temperature [C] from the slab section energy balances = {:.4R}",
4063 : AirOutletTempCheck));
4064 0 : ShowContinueError(state, format("Total energy rate (power) [W] added to the slab = {:.4R}", TotalVentSlabRadPower));
4065 0 : ShowContinueErrorTimeStamp(state, "");
4066 : }
4067 0 : ShowRecurringWarningErrorAtEnd(state,
4068 0 : cMO_VentilatedSlab + " [" + ventSlab.Name +
4069 : "] temperature calculation mismatch occurrence continues.",
4070 0 : ventSlab.EnrgyImbalErrIndex);
4071 : }
4072 : }
4073 :
4074 : } else {
4075 0 : state.dataLoopNodes->Node(ReturnAirNode).Temp = state.dataLoopNodes->Node(SlabInNode).Temp;
4076 : }
4077 :
4078 : // Now that we have the source/sink term, we must redo the heat balances to obtain
4079 : // the new SumHATsurf value for the zone. Note that the difference between the new
4080 : // SumHATsurf and the value originally calculated by the heat balance with a zero
4081 : // source for all radiant systems in the zone is the load met by the system (approximately).
4082 :
4083 0 : HeatBalanceSurfaceManager::CalcHeatBalanceOutsideSurf(state);
4084 0 : HeatBalanceSurfaceManager::CalcHeatBalanceInsideSurf(state);
4085 :
4086 : } // SeriesSlabs
4087 :
4088 : } //(AirMassFlow > 0.0d0)
4089 0 : }
4090 :
4091 0 : void SimVentSlabOAMixer(EnergyPlusData &state, int const Item) // System index in Ventilated Slab array
4092 : {
4093 :
4094 : // SUBROUTINE INFORMATION:
4095 : // AUTHOR Rick Strand
4096 : // DATE WRITTEN May 2000
4097 :
4098 : // PURPOSE OF THIS SUBROUTINE:
4099 : // This responsibility of this subroutine is to set the air flow rates
4100 : // through the mixing box portion of the Ventilated Slab and then perform
4101 : // an energy balance to arrive at outlet conditions which then would
4102 : // serve as inlet conditions to the coils (or outlet conditions for
4103 : // the device). There is some question as to whether this needs to be
4104 : // called every time the coils and fan are called since how the fans and
4105 : // coil operate won't presumable change how the mixer operates. The
4106 : // method in which this routine is called is slightly cleaner though
4107 : // from a code readability standpoint though less efficient.
4108 :
4109 : // METHODOLOGY EMPLOYED:
4110 : // The OAMassFlowRate has already been calculated in the main control
4111 : // algorithm. Use this flow rate to establish all of the other flow
4112 : // rates and perform an energy balance on the mixing of the return and
4113 : // outdoor air streams.
4114 :
4115 : // Using/Aliasing
4116 0 : auto const &ventSlab = state.dataVentilatedSlab->VentSlab(Item);
4117 :
4118 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
4119 : Real64 OAFraction; // Outside air fraction of inlet air
4120 :
4121 0 : int AirRelNode = ventSlab.AirReliefNode; // relief air node number in ventilated slab loop
4122 0 : int InletNode = ventSlab.ReturnAirNode; // inlet node number for ventilated slab loop
4123 0 : int OAMixOutNode = ventSlab.OAMixerOutNode; // outside air mixer outlet node for ventilated slab loop
4124 0 : int OutsideAirNode = ventSlab.OutsideAirNode; // outside air node number in ventilated slab loop
4125 :
4126 : // "Resolve" the air flow rates...
4127 :
4128 0 : state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate = state.dataVentilatedSlab->OAMassFlowRate;
4129 0 : state.dataLoopNodes->Node(OutsideAirNode).MassFlowRateMinAvail = state.dataVentilatedSlab->OAMassFlowRate;
4130 0 : state.dataLoopNodes->Node(OutsideAirNode).MassFlowRateMaxAvail = state.dataVentilatedSlab->OAMassFlowRate;
4131 :
4132 0 : state.dataLoopNodes->Node(AirRelNode).MassFlowRate = state.dataVentilatedSlab->OAMassFlowRate;
4133 0 : state.dataLoopNodes->Node(AirRelNode).MassFlowRateMinAvail = state.dataVentilatedSlab->OAMassFlowRate;
4134 0 : state.dataLoopNodes->Node(AirRelNode).MassFlowRateMaxAvail = state.dataVentilatedSlab->OAMassFlowRate;
4135 :
4136 0 : state.dataLoopNodes->Node(OAMixOutNode).MassFlowRate = state.dataLoopNodes->Node(InletNode).MassFlowRate;
4137 0 : state.dataLoopNodes->Node(OAMixOutNode).MassFlowRateMinAvail = state.dataLoopNodes->Node(InletNode).MassFlowRate;
4138 0 : state.dataLoopNodes->Node(OAMixOutNode).MassFlowRateMaxAvail = state.dataLoopNodes->Node(InletNode).MassFlowRate;
4139 :
4140 : // "Inlet" conditions for InletNode and OutsideAirNode have already
4141 : // been set elsewhere so we just need to set the "outlet" conditions
4142 0 : state.dataLoopNodes->Node(AirRelNode).Temp = state.dataLoopNodes->Node(InletNode).Temp;
4143 0 : state.dataLoopNodes->Node(AirRelNode).Press = state.dataLoopNodes->Node(InletNode).Press;
4144 0 : state.dataLoopNodes->Node(AirRelNode).HumRat = state.dataLoopNodes->Node(InletNode).HumRat;
4145 0 : state.dataLoopNodes->Node(AirRelNode).Enthalpy = state.dataLoopNodes->Node(InletNode).Enthalpy;
4146 :
4147 0 : if (state.dataLoopNodes->Node(InletNode).MassFlowRate > 0.0) {
4148 :
4149 0 : OAFraction = state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate / state.dataLoopNodes->Node(InletNode).MassFlowRate;
4150 :
4151 : } else {
4152 0 : OAFraction = 0.0;
4153 : }
4154 :
4155 0 : state.dataLoopNodes->Node(InletNode).Enthalpy =
4156 0 : Psychrometrics::PsyHFnTdbW(state.dataLoopNodes->Node(InletNode).Temp, state.dataLoopNodes->Node(InletNode).HumRat);
4157 :
4158 : // Perform an energy and moisture mass balance on the mixing portion of the OA Mixer of the ventilated slab
4159 0 : state.dataLoopNodes->Node(OAMixOutNode).Enthalpy =
4160 0 : OAFraction * state.dataLoopNodes->Node(OutsideAirNode).Enthalpy + (1.0 - OAFraction) * state.dataLoopNodes->Node(InletNode).Enthalpy;
4161 0 : state.dataLoopNodes->Node(OAMixOutNode).HumRat =
4162 0 : OAFraction * state.dataLoopNodes->Node(OutsideAirNode).HumRat + (1.0 - OAFraction) * state.dataLoopNodes->Node(InletNode).HumRat;
4163 :
4164 : // Find the other key state points based on calculated conditions
4165 0 : state.dataLoopNodes->Node(OAMixOutNode).Temp =
4166 0 : Psychrometrics::PsyTdbFnHW(state.dataLoopNodes->Node(OAMixOutNode).Enthalpy, state.dataLoopNodes->Node(OAMixOutNode).HumRat);
4167 0 : state.dataLoopNodes->Node(OAMixOutNode).Press = state.dataLoopNodes->Node(InletNode).Press;
4168 0 : }
4169 :
4170 0 : void UpdateVentilatedSlab(EnergyPlusData &state,
4171 : int const Item, // Index for the ventilated slab under consideration within the derived types
4172 : [[maybe_unused]] bool const FirstHVACIteration // TRUE if 1st HVAC simulation of system timestep !unused1208
4173 : )
4174 : {
4175 :
4176 : // SUBROUTINE INFORMATION:
4177 : // AUTHOR Young Tae Chae, Rick Strand
4178 : // DATE WRITTEN November 2000
4179 :
4180 : // PURPOSE OF THIS SUBROUTINE:
4181 : // This subroutine does any updating that needs to be done for low
4182 : // temperature radiant heating and cooling systems. One of the most
4183 : // important functions of this routine is to update the average heat
4184 : // source/sink for a particular system over the various system time
4185 : // steps that make up the zone time step. For hydronic systems,
4186 : // this routine must also set the outlet water conditions.
4187 :
4188 : // METHODOLOGY EMPLOYED:
4189 : // For the source/sink average update, if the system time step elapsed
4190 : // is still what it used to be, then either we are still iterating or
4191 : // we had to go back and shorten the time step. As a result, we have
4192 : // to subtract out the previous value that we added. If the system
4193 : // time step elapsed is different, then we just need to add the new
4194 : // values to the running average.
4195 :
4196 : // Using/Aliasing
4197 0 : Real64 SysTimeElapsed = state.dataHVACGlobal->SysTimeElapsed;
4198 0 : Real64 TimeStepSys = state.dataHVACGlobal->TimeStepSys;
4199 0 : auto &ventSlab = state.dataVentilatedSlab->VentSlab(Item);
4200 :
4201 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
4202 : Real64 OAFraction; // Outside air fraction of inlet air
4203 :
4204 0 : int TotRadSurfaces = ventSlab.NumOfSurfaces;
4205 0 : int MixOutNode = ventSlab.OAMixerOutNode; // Node number for the water side outlet of the radiant system
4206 0 : int OANode = ventSlab.OutsideAirNode;
4207 0 : int AirOutletNode = ventSlab.RadInNode;
4208 0 : int FanOutNode = ventSlab.FanOutletNode;
4209 0 : Real64 AirMassFlow = state.dataLoopNodes->Node(AirOutletNode).MassFlowRate;
4210 0 : int ZoneInletNode = ventSlab.ZoneAirInNode; // Node number for the air side inlet of the ventilated slab
4211 0 : Real64 CpAppAir = Psychrometrics::PsyCpAirFnW(state.dataLoopNodes->Node(AirOutletNode).HumRat);
4212 0 : int AirInletNode = ventSlab.ReturnAirNode; // Node number for the air side inlet of the ventilated slab
4213 :
4214 0 : for (int RadSurfNum = 1; RadSurfNum <= TotRadSurfaces; ++RadSurfNum) {
4215 :
4216 0 : int SurfNum = ventSlab.SurfacePtr(RadSurfNum);
4217 :
4218 0 : if (ventSlab.LastSysTimeElapsed == SysTimeElapsed) {
4219 : // Still iterating or reducing system time step, so subtract old values which were not valid
4220 0 : ventSlab.QRadSysSrcAvg(RadSurfNum) -= ventSlab.LastQRadSysSrc(RadSurfNum) * ventSlab.LastTimeStepSys / state.dataGlobal->TimeStepZone;
4221 : }
4222 :
4223 : // Update the running average and the "last" values with the current values of the appropriate variables
4224 0 : ventSlab.QRadSysSrcAvg(RadSurfNum) += state.dataHeatBalFanSys->QRadSysSource(SurfNum) * TimeStepSys / state.dataGlobal->TimeStepZone;
4225 0 : ventSlab.LastQRadSysSrc(RadSurfNum) = state.dataHeatBalFanSys->QRadSysSource(SurfNum);
4226 : }
4227 0 : ventSlab.LastSysTimeElapsed = SysTimeElapsed;
4228 0 : ventSlab.LastTimeStepSys = TimeStepSys;
4229 :
4230 : // First sum up all of the heat sources/sinks associated with this system
4231 0 : Real64 TotalHeatSource = 0.0;
4232 0 : for (int RadSurfNum = 1; RadSurfNum <= ventSlab.NumOfSurfaces; ++RadSurfNum) {
4233 0 : int SurfNum = ventSlab.SurfacePtr(RadSurfNum);
4234 0 : TotalHeatSource += state.dataHeatBalFanSys->QRadSysSource(SurfNum);
4235 : }
4236 0 : int ZoneNum = ventSlab.ZonePtr;
4237 0 : int ZoneMult = double(state.dataHeatBal->Zone(ZoneNum).Multiplier * state.dataHeatBal->Zone(ZoneNum).ListMultiplier);
4238 0 : TotalHeatSource *= ZoneMult;
4239 :
4240 : // Update the heating side of things
4241 :
4242 0 : if ((CpAppAir > 0.0) && (AirMassFlow > 0.0)) {
4243 :
4244 0 : if ((ventSlab.SysConfg == VentilatedSlabConfig::SlabOnly) || (ventSlab.SysConfg == VentilatedSlabConfig::SeriesSlabs)) {
4245 0 : state.dataLoopNodes->Node(AirInletNode) = state.dataLoopNodes->Node(AirInletNode);
4246 0 : state.dataLoopNodes->Node(AirInletNode).Temp =
4247 0 : state.dataLoopNodes->Node(AirOutletNode).Temp - TotalHeatSource / AirMassFlow / CpAppAir;
4248 0 : state.dataLoopNodes->Node(AirInletNode).MassFlowRate = state.dataLoopNodes->Node(AirOutletNode).MassFlowRate;
4249 0 : state.dataLoopNodes->Node(AirInletNode).HumRat = state.dataLoopNodes->Node(AirOutletNode).HumRat;
4250 :
4251 0 : } else if (ventSlab.SysConfg == VentilatedSlabConfig::SlabAndZone) {
4252 0 : state.dataLoopNodes->Node(ZoneInletNode) = state.dataLoopNodes->Node(ZoneInletNode);
4253 0 : state.dataLoopNodes->Node(ZoneInletNode).Temp =
4254 0 : state.dataLoopNodes->Node(AirOutletNode).Temp - TotalHeatSource / AirMassFlow / CpAppAir;
4255 0 : state.dataLoopNodes->Node(ZoneInletNode).MassFlowRate = state.dataLoopNodes->Node(AirOutletNode).MassFlowRate;
4256 0 : state.dataLoopNodes->Node(ZoneInletNode).HumRat = state.dataLoopNodes->Node(AirOutletNode).HumRat;
4257 0 : state.dataLoopNodes->Node(ventSlab.ReturnAirNode).Temp = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).MAT;
4258 : }
4259 :
4260 : } else {
4261 0 : state.dataLoopNodes->Node(FanOutNode) = state.dataLoopNodes->Node(AirOutletNode);
4262 0 : if (ventSlab.SysConfg == VentilatedSlabConfig::SlabAndZone) {
4263 0 : state.dataLoopNodes->Node(ZoneInletNode) = state.dataLoopNodes->Node(AirInletNode);
4264 : }
4265 0 : for (int const surfNum : ventSlab.SurfacePtr) {
4266 0 : state.dataHeatBalFanSys->QRadSysSource(surfNum) = 0.0;
4267 : }
4268 : }
4269 :
4270 : // Resolve mixouttemp
4271 :
4272 0 : if (state.dataLoopNodes->Node(AirInletNode).MassFlowRate > 0.0) {
4273 :
4274 0 : OAFraction = state.dataLoopNodes->Node(OANode).MassFlowRate / state.dataLoopNodes->Node(AirInletNode).MassFlowRate;
4275 :
4276 : } else {
4277 0 : OAFraction = 0.0;
4278 : }
4279 :
4280 0 : if (OAFraction <= 0.0) {
4281 :
4282 0 : state.dataLoopNodes->Node(MixOutNode).HumRat = state.dataLoopNodes->Node(AirInletNode).HumRat;
4283 0 : state.dataLoopNodes->Node(MixOutNode).Temp = state.dataLoopNodes->Node(AirInletNode).Temp;
4284 :
4285 : } else {
4286 :
4287 0 : state.dataLoopNodes->Node(MixOutNode).Enthalpy =
4288 0 : OAFraction * state.dataLoopNodes->Node(OANode).Enthalpy + (1.0 - OAFraction) * state.dataLoopNodes->Node(AirInletNode).Enthalpy;
4289 0 : state.dataLoopNodes->Node(MixOutNode).HumRat =
4290 0 : OAFraction * state.dataLoopNodes->Node(OANode).HumRat + (1.0 - OAFraction) * state.dataLoopNodes->Node(AirInletNode).HumRat;
4291 :
4292 0 : state.dataLoopNodes->Node(MixOutNode).Temp =
4293 0 : Psychrometrics::PsyTdbFnHW(state.dataLoopNodes->Node(MixOutNode).Enthalpy, state.dataLoopNodes->Node(MixOutNode).HumRat);
4294 : }
4295 0 : }
4296 :
4297 0 : Real64 CalcVentSlabHXEffectTerm(EnergyPlusData &state,
4298 : int const Item, // Index number of radiant system under consideration
4299 : Real64 const Temperature, // Temperature of air entering the radiant system, in C
4300 : Real64 const AirMassFlow, // Mass flow rate of water in the radiant system, in kg/s
4301 : Real64 const FlowFraction, // Mass flow rate fraction for this surface in the radiant system
4302 : Real64 const CoreLength, // Length of tubing in the radiant system, in m
4303 : Real64 const CoreDiameter, // Inside diameter of the tubing in the radiant system, in m
4304 : Real64 const CoreNumbers)
4305 : {
4306 :
4307 : // SUBROUTINE INFORMATION:
4308 : // AUTHOR Rick Strand
4309 : // DATE WRITTEN December 2000
4310 : // MODIFIED June 2008 (air properties)
4311 :
4312 : // PURPOSE OF THIS SUBROUTINE:
4313 : // This subroutine calculates the radiant system "heat exchanger"
4314 : // effectiveness term. This is equal to the mass flow rate of water
4315 : // times the specific heat of water times the effectiveness of
4316 : // the heat exchanger (radiant system "coil").
4317 :
4318 : // METHODOLOGY EMPLOYED:
4319 : // Assumes that the only real heat transfer term that we have to
4320 : // deal with is the convection from the water to the tube. The
4321 : // other assumptions are that the tube inside surface temperature
4322 : // is equal to the "source location temperature" and that it is
4323 : // a CONSTANT throughout the radiant system. This is to make
4324 : // the problem more tractable and to fit with other system assumptions
4325 : // that were made elsewhere in the radiant system model.
4326 :
4327 : // REFERENCES:
4328 : // Property data for air shown below as parameters taken from
4329 : // Mills, Heat Transfer, Table A.7.
4330 : // Heat exchanger information also from Incropera and DeWitt.
4331 : // Code based loosely on code from IBLAST program (research version)
4332 :
4333 : // Using/Aliasing
4334 0 : auto &ventSlab = state.dataVentilatedSlab->VentSlab(Item);
4335 :
4336 : // Return value
4337 : Real64 CalcVentSlabHXEffectTerm;
4338 :
4339 0 : Real64 constexpr MaxLaminarRe(2300.0); // Maximum Reynolds number for laminar flow
4340 0 : int constexpr NumOfPropDivisions(13);
4341 0 : Real64 constexpr MaxExpPower(50.0); // Maximum power after which EXP argument would be zero for DP variables
4342 : static constexpr std::array<Real64, NumOfPropDivisions> Temps = {
4343 : 1.85, 6.85, 11.85, 16.85, 21.85, 26.85, 31.85, 36.85, 41.85, 46.85, 51.85, 56.85, 61.85}; // Temperature, in C
4344 : static constexpr std::array<Real64, NumOfPropDivisions> Mu = {0.0000088,
4345 : 0.0000176,
4346 : 0.00001781,
4347 : 0.00001802,
4348 : 0.000018225,
4349 : 0.00001843,
4350 : 0.00001865,
4351 : 0.00001887,
4352 : 0.00001908,
4353 : 0.00001929,
4354 : 0.0000195,
4355 : 0.00001971,
4356 : 0.00001992}; // Viscosity, in Ns/m2
4357 :
4358 : static constexpr std::array<Real64, NumOfPropDivisions> Conductivity = {
4359 : 0.01275, 0.0255, 0.0258, 0.0261, 0.0264, 0.0267, 0.02705, 0.0274, 0.02775, 0.0281, 0.0284, 0.0287, 0.01435}; // Conductivity, in W/mK
4360 : static constexpr std::array<Real64, NumOfPropDivisions> Pr = {
4361 : 0.69, 0.69, 0.69, 0.69, 0.69, 0.69, 0.69, 0.69, 0.69, 0.69, 0.69, 0.69, 0.69}; // Prandtl number (dimensionless)
4362 :
4363 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
4364 : int Index;
4365 : Real64 InterpFrac;
4366 : Real64 NuD;
4367 : Real64 ReD;
4368 : Real64 NTU;
4369 : Real64 CpAppAir;
4370 : Real64 Kactual;
4371 : Real64 MUactual;
4372 : Real64 PRactual;
4373 : Real64 SysAirMassFlow; // Specific heat of air
4374 :
4375 : // First find out where we are in the range of temperatures
4376 0 : Index = 0;
4377 0 : while (Index < NumOfPropDivisions) {
4378 0 : if (Temperature < Temps[Index]) {
4379 0 : break; // DO loop
4380 : }
4381 0 : ++Index;
4382 : }
4383 :
4384 : // Initialize thermal properties of Air
4385 0 : if (Index == 0) {
4386 0 : MUactual = Mu[Index];
4387 0 : Kactual = Conductivity[Index];
4388 0 : PRactual = Pr[Index];
4389 0 : } else if (Index > NumOfPropDivisions - 1) {
4390 0 : Index = NumOfPropDivisions - 1;
4391 0 : MUactual = Mu[Index];
4392 0 : Kactual = Conductivity[Index];
4393 0 : PRactual = Pr[Index];
4394 : } else {
4395 0 : InterpFrac = (Temperature - Temps[Index - 1]) / (Temps[Index] - Temps[Index - 1]);
4396 0 : MUactual = Mu[Index - 1] + InterpFrac * (Mu[Index] - Mu[Index - 1]);
4397 0 : Kactual = Conductivity[Index - 1] + InterpFrac * (Conductivity[Index] - Conductivity[Index - 1]);
4398 0 : PRactual = Pr[Index - 1] + InterpFrac * (Pr[Index] - Pr[Index - 1]);
4399 : }
4400 : // arguments are glycol name, temperature, and concentration
4401 0 : CpAppAir = Psychrometrics::PsyCpAirFnW(state.dataLoopNodes->Node(ventSlab.RadInNode).HumRat);
4402 0 : SysAirMassFlow = AirMassFlow / CoreNumbers;
4403 :
4404 : // Calculate the Reynold's number from RE=(4*Mdot)/(Pi*Mu*Diameter)
4405 0 : ReD = 4.0 * SysAirMassFlow * FlowFraction / (Constant::Pi * MUactual * CoreDiameter);
4406 :
4407 : // Calculate the Nusselt number based on what flow regime one is in
4408 0 : if (ReD >= MaxLaminarRe) { // Turbulent flow --> use Colburn equation
4409 :
4410 0 : NuD = 0.023 * std::pow(ReD, 0.8) * std::pow(PRactual, 1.0 / 3.0);
4411 :
4412 : } else { // Laminar flow --> use constant surface temperature relation
4413 :
4414 0 : NuD = 3.66;
4415 : }
4416 :
4417 : // Calculate the NTU parameter
4418 : // NTU = UA/[(Mdot*Cp)min]
4419 : // where: U = h (convection coefficient) and h = (k)(Nu)/D
4420 : // A = Pi*D*TubeLength
4421 0 : NTU = Constant::Pi * Kactual * NuD * CoreLength / (SysAirMassFlow * CpAppAir); // FlowFraction cancels out here
4422 :
4423 : // Calculate Epsilon*MassFlowRate*Cp
4424 0 : if (NTU > MaxExpPower) {
4425 0 : CalcVentSlabHXEffectTerm = FlowFraction * SysAirMassFlow * CpAppAir;
4426 : } else {
4427 0 : CalcVentSlabHXEffectTerm = (1.0 - std::exp(-NTU)) * FlowFraction * SysAirMassFlow * CpAppAir;
4428 : }
4429 :
4430 0 : return CalcVentSlabHXEffectTerm;
4431 : }
4432 :
4433 0 : void ReportVentilatedSlab(EnergyPlusData &state, int const Item) // Index for the ventilated slab under consideration within the derived types
4434 : {
4435 :
4436 : // SUBROUTINE INFORMATION:
4437 : // AUTHOR Rick Strand
4438 : // DATE WRITTEN November 2000
4439 :
4440 : // PURPOSE OF THIS SUBROUTINE:
4441 : // This subroutine simply produces output for the low temperature radiant system.
4442 :
4443 : // Using/Aliasing
4444 0 : Real64 TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
4445 0 : auto &ventSlab = state.dataVentilatedSlab->VentSlab(Item);
4446 :
4447 : // Slab Part
4448 0 : Real64 TotalVentSlabRadPower = 0.0; // Total source/sink power for the radiant system (sum of all surfaces of the system)
4449 :
4450 0 : for (int RadSurfNum = 1; RadSurfNum <= ventSlab.NumOfSurfaces; ++RadSurfNum) {
4451 0 : int SurfNum = ventSlab.SurfacePtr(RadSurfNum);
4452 0 : TotalVentSlabRadPower += state.dataHeatBalFanSys->QRadSysSource(SurfNum);
4453 : }
4454 0 : Real64 ZoneMult = double(state.dataHeatBal->Zone(ventSlab.ZonePtr).Multiplier * state.dataHeatBal->Zone(ventSlab.ZonePtr).ListMultiplier);
4455 0 : TotalVentSlabRadPower *= ZoneMult;
4456 0 : ventSlab.RadHeatingPower = 0.0;
4457 0 : ventSlab.RadCoolingPower = 0.0;
4458 :
4459 0 : if (TotalVentSlabRadPower >= 0.01) {
4460 :
4461 0 : ventSlab.RadHeatingPower = +TotalVentSlabRadPower;
4462 : } else {
4463 :
4464 0 : ventSlab.RadCoolingPower = -TotalVentSlabRadPower;
4465 : }
4466 :
4467 0 : ventSlab.RadHeatingEnergy = ventSlab.RadHeatingPower * TimeStepSysSec;
4468 0 : ventSlab.RadCoolingEnergy = ventSlab.RadCoolingPower * TimeStepSysSec;
4469 :
4470 : // Coil Part
4471 0 : ventSlab.HeatCoilEnergy = ventSlab.HeatCoilPower * TimeStepSysSec;
4472 0 : ventSlab.SensCoolCoilEnergy = ventSlab.SensCoolCoilPower * TimeStepSysSec;
4473 0 : ventSlab.LateCoolCoilEnergy = ventSlab.LateCoolCoilPower * TimeStepSysSec;
4474 0 : ventSlab.TotCoolCoilEnergy = ventSlab.TotCoolCoilPower * TimeStepSysSec;
4475 0 : ventSlab.ElecFanEnergy = ventSlab.ElecFanPower * TimeStepSysSec;
4476 :
4477 0 : if ((ventSlab.SysConfg == VentilatedSlabConfig::SlabOnly) || (ventSlab.SysConfg == VentilatedSlabConfig::SeriesSlabs)) {
4478 0 : ventSlab.SlabInTemp = state.dataLoopNodes->Node(ventSlab.RadInNode).Temp;
4479 0 : ventSlab.SlabOutTemp = state.dataLoopNodes->Node(ventSlab.ReturnAirNode).Temp;
4480 :
4481 0 : } else if (ventSlab.SysConfg == VentilatedSlabConfig::SlabAndZone) {
4482 0 : ventSlab.SlabInTemp = state.dataLoopNodes->Node(ventSlab.RadInNode).Temp;
4483 0 : ventSlab.ZoneInletTemp = state.dataLoopNodes->Node(ventSlab.ZoneAirInNode).Temp;
4484 0 : ventSlab.SlabOutTemp = state.dataLoopNodes->Node(ventSlab.ReturnAirNode).Temp;
4485 : }
4486 :
4487 0 : ventSlab.ReturnAirTemp = state.dataLoopNodes->Node(ventSlab.ReturnAirNode).Temp;
4488 0 : ventSlab.FanOutletTemp = state.dataLoopNodes->Node(ventSlab.FanOutletNode).Temp;
4489 :
4490 0 : if (ventSlab.FirstPass) { // reset sizing flags so other zone equipment can size normally
4491 0 : if (!state.dataGlobal->SysSizingCalc) {
4492 0 : DataSizing::resetHVACSizingGlobals(state, state.dataSize->CurZoneEqNum, 0, ventSlab.FirstPass);
4493 : }
4494 : }
4495 0 : }
4496 :
4497 1 : int getVentilatedSlabIndex(EnergyPlusData &state, std::string_view CompName)
4498 : {
4499 1 : if (state.dataVentilatedSlab->GetInputFlag) {
4500 0 : GetVentilatedSlabInput(state);
4501 0 : state.dataVentilatedSlab->GetInputFlag = false;
4502 : }
4503 :
4504 1 : for (int VentSlabNum = 1; VentSlabNum <= state.dataVentilatedSlab->NumOfVentSlabs; ++VentSlabNum) {
4505 1 : if (Util::SameString(state.dataVentilatedSlab->VentSlab(VentSlabNum).Name, CompName)) {
4506 1 : return VentSlabNum;
4507 : }
4508 : }
4509 :
4510 0 : return 0;
4511 : }
4512 : //*****************************************************************************************
4513 :
4514 : } // namespace VentilatedSlab
4515 :
4516 : } // namespace EnergyPlus
|