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