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