Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2023, 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 <cassert>
50 : #include <cmath>
51 :
52 : // ObjexxFCL Headers
53 : #include <ObjexxFCL/Array.functions.hh>
54 : #include <ObjexxFCL/Fmath.hh>
55 :
56 : // EnergyPlus Headers
57 : #include <EnergyPlus/Autosizing/CoolingCapacitySizing.hh>
58 : #include <EnergyPlus/Autosizing/HeatingCapacitySizing.hh>
59 : #include <EnergyPlus/BranchNodeConnections.hh>
60 : #include <EnergyPlus/Construction.hh>
61 : #include <EnergyPlus/Data/EnergyPlusData.hh>
62 : #include <EnergyPlus/DataBranchAirLoopPlant.hh>
63 : #include <EnergyPlus/DataEnvironment.hh>
64 : #include <EnergyPlus/DataHVACGlobals.hh>
65 : #include <EnergyPlus/DataHeatBalFanSys.hh>
66 : #include <EnergyPlus/DataHeatBalSurface.hh>
67 : #include <EnergyPlus/DataHeatBalance.hh>
68 : #include <EnergyPlus/DataLoopNode.hh>
69 : #include <EnergyPlus/DataSizing.hh>
70 : #include <EnergyPlus/DataSurfaceLists.hh>
71 : #include <EnergyPlus/DataSurfaces.hh>
72 : #include <EnergyPlus/DataZoneEquipment.hh>
73 : #include <EnergyPlus/EMSManager.hh>
74 : #include <EnergyPlus/FluidProperties.hh>
75 : #include <EnergyPlus/General.hh>
76 : #include <EnergyPlus/GeneralRoutines.hh>
77 : #include <EnergyPlus/GlobalNames.hh>
78 : #include <EnergyPlus/HeatBalanceSurfaceManager.hh>
79 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
80 : #include <EnergyPlus/LowTempRadiantSystem.hh>
81 : #include <EnergyPlus/NodeInputManager.hh>
82 : #include <EnergyPlus/OutputProcessor.hh>
83 : #include <EnergyPlus/Plant/Enums.hh>
84 : #include <EnergyPlus/PlantUtilities.hh>
85 : #include <EnergyPlus/Psychrometrics.hh>
86 : #include <EnergyPlus/ScheduleManager.hh>
87 : #include <EnergyPlus/UtilityRoutines.hh>
88 : #include <EnergyPlus/WeatherManager.hh>
89 : #include <EnergyPlus/ZoneTempPredictorCorrector.hh>
90 :
91 : namespace EnergyPlus {
92 :
93 : namespace LowTempRadiantSystem {
94 :
95 : // Module containing the routines dealing with the low temperature radiant systems
96 :
97 : // MODULE INFORMATION:
98 : // AUTHOR Rick Strand
99 : // DATE WRITTEN November 2000
100 : // MODIFIED Rick Strand March 2001 (additional controls, etc.)
101 : // Rick Strand July 2003 (added constant flow hydronic system)
102 : // B. Griffith Sept 2010, plant upgrades, generalize fluid properties
103 : // Rick Strand August 2011 (improved condensation handling)
104 :
105 : // PURPOSE OF THIS MODULE:
106 : // The purpose of this module is to simulate low temperature radiant systems.
107 : // It is the intention of this module to cover all types of low temperature
108 : // radiant systems: wall, ceiling, floor, heating, cooling, panels, etc.
109 :
110 : // METHODOLOGY EMPLOYED:
111 : // Based on work done in IBLAST, this model has been revised for the structure
112 : // of EnergyPlus. It is still based on the QTF formulation of heat transfer
113 : // through building elements with embedded heat sources/sinks. Note that due
114 : // to the fact that a radiant system is both a building heat transfer element
115 : // and a controllable system that some iteration between the system and the
116 : // surface heat balance routine is necessary.
117 : // REFERENCES:
118 : // IBLAST-QTF research program, completed in January 1995 (unreleased)
119 : // Strand, R.K. 1995. "Heat Source Transfer Functions and Their Application to
120 : // Low Temperature Radiant Heating Systems", Ph.D. dissertation, University
121 : // of Illinois at Urbana-Champaign, Department of Mechanical and Industrial
122 : // Engineering.
123 : // Seem, J.E. 1986. "Heat Transfer in Buildings", Ph.D. dissertation, University
124 : // of Wisconsin-Madison.
125 :
126 : // OTHER NOTES: This module contains three different types of radiant system
127 : // models: (a) variable flow hydronic heating/cooling radiant system;
128 : // (b) constant flow, variable controlled temperature heating/cooling radiant
129 : // system; (c) electric resistance heating radiant system. Systems (a) and
130 : // (b) are hydronic systems--one which varies hydronic flow as the key control
131 : // paramter (a) and one which varies the inlet hydronic temperature while
132 : // keeping the flow rate through the radiant system constant (b). In system
133 : // (b), the injection rate from the main water loop is varied to obtain the
134 : // proper inlet temperature.
135 :
136 : // USE STATEMENTS:
137 : // Use statements for data only modules
138 : // Using/Aliasing
139 : using DataHVACGlobals::SmallLoad;
140 : using Psychrometrics::PsyTdpFnWPb;
141 :
142 : // Data
143 : // MODULE PARAMETER DEFINITIONS:
144 : // System types:
145 : auto constexpr cHydronicSystem("ZoneHVAC:LowTemperatureRadiant:VariableFlow");
146 : auto constexpr cConstantFlowSystem("ZoneHVAC:LowTemperatureRadiant:ConstantFlow");
147 : auto constexpr OnePerSurf("OnePerSurface");
148 : auto constexpr CalcFromLength("CalculateFromCircuitLength");
149 :
150 : auto constexpr fluidNameWater("WATER");
151 :
152 : // DERIVED TYPE DEFINITIONS:
153 :
154 : // MODULE VARIABLE DECLARATIONS:
155 : // Standard, run-of-the-mill variables...
156 :
157 : // Object Data
158 :
159 684904 : void SimLowTempRadiantSystem(EnergyPlusData &state,
160 : std::string_view CompName, // name of the low temperature radiant system
161 : bool const FirstHVACIteration, // TRUE if 1st HVAC simulation of system timestep
162 : Real64 &LoadMet, // load met by the radiant system, in Watts
163 : int &CompIndex)
164 : {
165 :
166 : // SUBROUTINE INFORMATION:
167 : // AUTHOR Rick Strand
168 : // DATE WRITTEN November 2000
169 :
170 : // Using/Aliasing
171 :
172 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
173 : int RadSysNum; // Radiant system number/index in local derived types
174 : LowTempRadiantSystem::SystemType SystemType; // Type of radiant system: hydronic, constant flow, or electric
175 684904 : bool InitErrorFound(false);
176 :
177 684904 : if (state.dataLowTempRadSys->GetInputFlag) {
178 29 : GetLowTempRadiantSystem(state);
179 29 : state.dataLowTempRadSys->GetInputFlag = false;
180 : }
181 :
182 : // Find the correct Low Temp Radiant System
183 684904 : if (CompIndex == 0) {
184 82 : RadSysNum = UtilityRoutines::FindItemInList(CompName, state.dataLowTempRadSys->RadSysTypes);
185 82 : if (RadSysNum == 0) {
186 0 : ShowFatalError(state, "SimLowTempRadiantSystem: Unit not found=" + std::string{CompName});
187 : }
188 82 : CompIndex = RadSysNum;
189 82 : SystemType = state.dataLowTempRadSys->RadSysTypes(RadSysNum).SystemType;
190 82 : switch (SystemType) {
191 46 : case LowTempRadiantSystem::SystemType::HydronicSystem: {
192 46 : state.dataLowTempRadSys->RadSysTypes(RadSysNum).CompIndex =
193 46 : UtilityRoutines::FindItemInList(CompName, state.dataLowTempRadSys->HydrRadSys);
194 46 : } break;
195 27 : case LowTempRadiantSystem::SystemType::ConstantFlowSystem: {
196 27 : state.dataLowTempRadSys->RadSysTypes(RadSysNum).CompIndex =
197 27 : UtilityRoutines::FindItemInList(CompName, state.dataLowTempRadSys->CFloRadSys);
198 27 : } break;
199 9 : case LowTempRadiantSystem::SystemType::ElectricSystem: {
200 9 : state.dataLowTempRadSys->RadSysTypes(RadSysNum).CompIndex =
201 9 : UtilityRoutines::FindItemInList(CompName, state.dataLowTempRadSys->ElecRadSys);
202 9 : } break;
203 0 : default:
204 0 : break;
205 : }
206 : } else {
207 684822 : RadSysNum = CompIndex;
208 684822 : SystemType = state.dataLowTempRadSys->RadSysTypes(RadSysNum).SystemType;
209 684822 : if (RadSysNum > state.dataLowTempRadSys->TotalNumOfRadSystems || RadSysNum < 1) {
210 0 : ShowFatalError(state,
211 0 : format("SimLowTempRadiantSystem: Invalid CompIndex passed={}, Number of Units={}, Entered Unit name={}",
212 : RadSysNum,
213 0 : state.dataLowTempRadSys->TotalNumOfRadSystems,
214 0 : CompName));
215 : }
216 684822 : if (state.dataLowTempRadSys->CheckEquipName(RadSysNum)) {
217 82 : if (CompName != state.dataLowTempRadSys->RadSysTypes(RadSysNum).Name) {
218 0 : ShowFatalError(state,
219 0 : format("SimLowTempRadiantSystem: Invalid CompIndex passed={}, Unit name={}, stored Unit Name for that index={}",
220 : RadSysNum,
221 : CompName,
222 0 : state.dataLowTempRadSys->RadSysTypes(RadSysNum).Name));
223 : }
224 82 : state.dataLowTempRadSys->CheckEquipName(RadSysNum) = false;
225 : }
226 : }
227 :
228 684904 : InitLowTempRadiantSystem(state, FirstHVACIteration, state.dataLowTempRadSys->RadSysTypes(RadSysNum).CompIndex, SystemType, InitErrorFound);
229 684904 : if (InitErrorFound) {
230 0 : ShowFatalError(state,
231 : "InitLowTempRadiantSystem: Preceding error is not allowed to proceed with the simulation. Correct this input problem.");
232 : }
233 :
234 : // Simulate, update, and report based on the type of radiant system
235 : {
236 : RadiantSystemBaseData *baseSystem;
237 684904 : if (SystemType == LowTempRadiantSystem::SystemType::HydronicSystem) {
238 372334 : baseSystem = &state.dataLowTempRadSys->HydrRadSys(state.dataLowTempRadSys->RadSysTypes(RadSysNum).CompIndex);
239 312570 : } else if (SystemType == LowTempRadiantSystem::SystemType::ConstantFlowSystem) {
240 231699 : baseSystem = &state.dataLowTempRadSys->CFloRadSys(state.dataLowTempRadSys->RadSysTypes(RadSysNum).CompIndex);
241 80871 : } else if (SystemType == LowTempRadiantSystem::SystemType::ElectricSystem) {
242 80871 : baseSystem = &state.dataLowTempRadSys->ElecRadSys(state.dataLowTempRadSys->RadSysTypes(RadSysNum).CompIndex);
243 : } else {
244 0 : ShowFatalError(state, "SimLowTempRadiantSystem: Illegal system type for system " + std::string{CompName});
245 : }
246 :
247 684904 : if ((SystemType == LowTempRadiantSystem::SystemType::HydronicSystem) ||
248 80871 : (SystemType == LowTempRadiantSystem::SystemType::ConstantFlowSystem) ||
249 : (SystemType == LowTempRadiantSystem::SystemType::ElectricSystem)) {
250 684904 : baseSystem->calculateLowTemperatureRadiantSystem(state, LoadMet);
251 684904 : baseSystem->updateLowTemperatureRadiantSystemSurfaces(state);
252 684904 : baseSystem->updateLowTemperatureRadiantSystem(state); // Nothing to update for electric systems
253 684904 : baseSystem->reportLowTemperatureRadiantSystem(state);
254 : }
255 : }
256 684904 : }
257 :
258 29 : void GetLowTempRadiantSystem(EnergyPlusData &state)
259 : {
260 :
261 : // SUBROUTINE INFORMATION:
262 : // AUTHOR Rick Strand
263 : // DATE WRITTEN November 2000
264 : // MODIFIED August 2003 (added constant flow system, made input extensible)
265 :
266 : // PURPOSE OF THIS SUBROUTINE:
267 : // This subroutine reads the input for low temperature radiant systems
268 : // from the user input file. This will contain all of the information
269 : // needed to simulate a low temperature radiant system.
270 :
271 : // Using/Aliasing
272 : using BranchNodeConnections::TestCompSet;
273 : using DataSizing::AutoSize;
274 : using DataSizing::CapacityPerFloorArea;
275 : using DataSizing::CoolingDesignCapacity;
276 : using DataSizing::FractionOfAutosizedCoolingCapacity;
277 : using DataSizing::FractionOfAutosizedHeatingCapacity;
278 : using DataSizing::HeatingDesignCapacity;
279 : using FluidProperties::FindGlycol;
280 :
281 : using NodeInputManager::GetOnlySingleNode;
282 : using ScheduleManager::GetScheduleIndex;
283 : using namespace DataLoopNode;
284 : using namespace DataSurfaceLists;
285 :
286 : // SUBROUTINE PARAMETER DEFINITIONS:
287 29 : auto constexpr RoutineName("GetLowTempRadiantSystem: "); // include trailing blank space
288 29 : auto constexpr Off("Off");
289 29 : auto constexpr SimpleOff("SimpleOff");
290 29 : auto constexpr VariableOff("VariableOff");
291 29 : int constexpr iHeatCAPMAlphaNum(5); // get input index to Low Temperature Radiant system heating capacity sizing method
292 29 : int constexpr iHeatDesignCapacityNumericNum(1); // get input index to Low Temperature Radiant system electric heating capacity
293 29 : int constexpr iHeatCapacityPerFloorAreaNumericNum(
294 : 2); // get input index to Low Temperature Radiant system electric heating capacity per floor area sizing
295 29 : int constexpr iHeatFracOfAutosizedCapacityNumericNum(
296 : 3); // get input index to Low Temperature Radiant system electric heating capacity sizing as fraction of autozized heating capacity
297 :
298 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
299 58 : std::string CurrentModuleObject; // for ease in getting objects
300 58 : Array1D_string Alphas; // Alpha items for object
301 58 : Array1D_string cAlphaFields; // Alpha field names
302 58 : Array1D_string cNumericFields; // Numeric field names
303 58 : Array1D_bool AssignedAsRadiantSurface; // Set to true when a surface is part of a radiant system
304 : int CheckSurfNum; // Surface number to check to see if it has already been used by a radiant system
305 29 : bool ErrorsFound(false); // Set to true if errors in input, fatal at end of routine
306 : int GlycolIndex; // Index of 'Water' in glycol data structure
307 : int IOStatus; // Used in GetObjectItem
308 : int Item; // Item to be "gotten"
309 : int MaxAlphas; // Maximum number of alphas for these input keywords
310 : int MaxNumbers; // Maximum number of numbers for these input keywords
311 58 : Array1D<Real64> Numbers; // Numeric items for object
312 : int NumAlphas; // Number of Alphas for each GetObjectItem call
313 : int NumArgs; // Unused variable that is part of a subroutine call
314 : int NumNumbers; // Number of Numbers for each GetObjectItem call
315 : int SurfListNum; // Index within the SurfList derived type for a surface list name
316 : int SurfNum; // DO loop counter for surfaces
317 : int BaseNum; // Temporary number for creating RadiantSystemTypes structure
318 58 : Array1D_bool lAlphaBlanks; // Logical array, alpha field input BLANK = .TRUE.
319 58 : Array1D_bool lNumericBlanks; // Logical array, numeric field input BLANK = .TRUE.
320 :
321 29 : auto &Zone(state.dataHeatBal->Zone);
322 29 : auto &Surface(state.dataSurface->Surface);
323 :
324 58 : Array1D_string VarFlowRadDesignNames;
325 58 : Array1D_string CFlowRadDesignNames;
326 :
327 29 : MaxAlphas = 0;
328 29 : MaxNumbers = 0;
329 :
330 58 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(
331 29 : state, "ZoneHVAC:LowTemperatureRadiant:VariableFlow:Design", NumArgs, NumAlphas, NumNumbers);
332 29 : MaxAlphas = max(MaxAlphas, NumAlphas);
333 29 : MaxNumbers = max(MaxNumbers, NumNumbers);
334 :
335 58 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(
336 29 : state, "ZoneHVAC:LowTemperatureRadiant:ConstantFlow:Design", NumArgs, NumAlphas, NumNumbers);
337 29 : MaxAlphas = max(MaxAlphas, NumAlphas);
338 29 : MaxNumbers = max(MaxNumbers, NumNumbers);
339 :
340 58 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(
341 29 : state, "ZoneHVAC:LowTemperatureRadiant:VariableFlow", NumArgs, NumAlphas, NumNumbers);
342 29 : MaxAlphas = max(MaxAlphas, NumAlphas);
343 29 : MaxNumbers = max(MaxNumbers, NumNumbers);
344 :
345 58 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(
346 29 : state, "ZoneHVAC:LowTemperatureRadiant:ConstantFlow", NumArgs, NumAlphas, NumNumbers);
347 29 : MaxAlphas = max(MaxAlphas, NumAlphas);
348 29 : MaxNumbers = max(MaxNumbers, NumNumbers);
349 :
350 58 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(
351 29 : state, "ZoneHVAC:LowTemperatureRadiant:Electric", NumArgs, NumAlphas, NumNumbers);
352 29 : MaxAlphas = max(MaxAlphas, NumAlphas);
353 29 : MaxNumbers = max(MaxNumbers, NumNumbers);
354 :
355 29 : Alphas.allocate(MaxAlphas);
356 29 : Numbers.dimension(MaxNumbers, 0.0);
357 29 : cAlphaFields.allocate(MaxAlphas);
358 29 : cNumericFields.allocate(MaxNumbers);
359 29 : lAlphaBlanks.dimension(MaxAlphas, true);
360 29 : lNumericBlanks.dimension(MaxNumbers, true);
361 :
362 29 : state.dataLowTempRadSys->NumOfHydrLowTempRadSys =
363 58 : state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "ZoneHVAC:LowTemperatureRadiant:VariableFlow");
364 29 : state.dataLowTempRadSys->NumOfCFloLowTempRadSys =
365 58 : state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "ZoneHVAC:LowTemperatureRadiant:ConstantFlow");
366 29 : state.dataLowTempRadSys->NumOfElecLowTempRadSys =
367 58 : state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "ZoneHVAC:LowTemperatureRadiant:Electric");
368 :
369 29 : state.dataLowTempRadSys->NumOfHydrLowTempRadSysDes =
370 58 : state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "ZoneHVAC:LowTemperatureRadiant:VariableFlow:Design");
371 29 : state.dataLowTempRadSys->NumOfCFloLowTempRadSysDes =
372 58 : state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "ZoneHVAC:LowTemperatureRadiant:ConstantFlow:Design");
373 :
374 87 : state.dataLowTempRadSys->TotalNumOfRadSystems = state.dataLowTempRadSys->NumOfHydrLowTempRadSys +
375 58 : state.dataLowTempRadSys->NumOfElecLowTempRadSys +
376 29 : state.dataLowTempRadSys->NumOfCFloLowTempRadSys;
377 29 : state.dataLowTempRadSys->RadSysTypes.allocate(state.dataLowTempRadSys->TotalNumOfRadSystems);
378 29 : state.dataLowTempRadSys->LowTempRadUniqueNames.reserve(static_cast<unsigned>(state.dataLowTempRadSys->TotalNumOfRadSystems));
379 29 : state.dataLowTempRadSys->CheckEquipName.dimension(state.dataLowTempRadSys->TotalNumOfRadSystems, true);
380 :
381 29 : state.dataLowTempRadSys->HydrRadSys.allocate(state.dataLowTempRadSys->NumOfHydrLowTempRadSys);
382 29 : if (state.dataLowTempRadSys->NumOfHydrLowTempRadSys > 0) {
383 17 : GlycolIndex = FindGlycol(state, fluidNameWater);
384 63 : for (auto &e : state.dataLowTempRadSys->HydrRadSys)
385 46 : e.GlycolIndex = GlycolIndex;
386 17 : if (GlycolIndex == 0) {
387 0 : ShowSevereError(state, "Hydronic radiant systems: no water property data found in input");
388 0 : ErrorsFound = true;
389 : }
390 : } else {
391 12 : for (auto &e : state.dataLowTempRadSys->HydrRadSys)
392 0 : e.GlycolIndex = 0;
393 : }
394 :
395 29 : state.dataLowTempRadSys->CFloRadSys.allocate(state.dataLowTempRadSys->NumOfCFloLowTempRadSys);
396 29 : if (state.dataLowTempRadSys->NumOfCFloLowTempRadSys > 0) {
397 9 : GlycolIndex = FindGlycol(state, fluidNameWater);
398 36 : for (auto &e : state.dataLowTempRadSys->CFloRadSys)
399 27 : e.GlycolIndex = GlycolIndex;
400 9 : if (GlycolIndex == 0) {
401 0 : ShowSevereError(state, "Constant flow radiant systems: no water property data found in input");
402 0 : ErrorsFound = true;
403 : }
404 : } else {
405 20 : for (auto &e : state.dataLowTempRadSys->CFloRadSys)
406 0 : e.GlycolIndex = 0;
407 : }
408 :
409 29 : state.dataLowTempRadSys->ElecRadSys.allocate(state.dataLowTempRadSys->NumOfElecLowTempRadSys);
410 29 : state.dataLowTempRadSys->ElecRadSysNumericFields.allocate(state.dataLowTempRadSys->NumOfElecLowTempRadSys);
411 :
412 29 : state.dataLowTempRadSys->HydronicRadiantSysNumericFields.allocate(state.dataLowTempRadSys->NumOfHydrLowTempRadSys);
413 29 : state.dataLowTempRadSys->HydronicRadiantSysDesign.allocate(state.dataLowTempRadSys->NumOfHydrLowTempRadSysDes);
414 29 : VarFlowRadDesignNames.allocate(state.dataLowTempRadSys->NumOfHydrLowTempRadSysDes);
415 :
416 29 : state.dataLowTempRadSys->CflowRadiantSysDesign.allocate(state.dataLowTempRadSys->NumOfCFloLowTempRadSysDes);
417 29 : CFlowRadDesignNames.allocate(state.dataLowTempRadSys->NumOfCFloLowTempRadSysDes);
418 :
419 : // make sure data is gotten for surface lists
420 29 : GetNumberOfSurfaceLists(state);
421 :
422 : // Obtain all of the design data related to hydronic low temperature radiant systems...
423 29 : CurrentModuleObject = "ZoneHVAC:LowTemperatureRadiant:VariableFlow:Design";
424 60 : for (Item = 1; Item <= state.dataLowTempRadSys->NumOfHydrLowTempRadSysDes; ++Item) {
425 :
426 31 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
427 : CurrentModuleObject,
428 : Item,
429 : Alphas,
430 : NumAlphas,
431 : Numbers,
432 : NumNumbers,
433 : IOStatus,
434 : lNumericBlanks,
435 : lAlphaBlanks,
436 : cAlphaFields,
437 : cNumericFields);
438 :
439 31 : state.dataLowTempRadSys->HydronicRadiantSysDesign(Item).FieldNames.allocate(NumNumbers);
440 31 : state.dataLowTempRadSys->HydronicRadiantSysDesign(Item).FieldNames = "";
441 31 : state.dataLowTempRadSys->HydronicRadiantSysDesign(Item).FieldNames = cNumericFields;
442 62 : GlobalNames::VerifyUniqueInterObjectName(
443 62 : state, state.dataLowTempRadSys->LowTempRadUniqueNames, Alphas(1), CurrentModuleObject, cAlphaFields(1), ErrorsFound);
444 :
445 31 : auto &thisRadSysDesign(state.dataLowTempRadSys->HydronicRadiantSysDesign(Item));
446 :
447 : // General user input data
448 31 : thisRadSysDesign.designName = Alphas(1);
449 :
450 31 : thisRadSysDesign.FluidToSlabHeatTransfer = thisRadSysDesign.getFluidToSlabHeatTransferInput(state, Alphas(2));
451 :
452 31 : thisRadSysDesign.TubeDiameterInner = Numbers(1);
453 31 : thisRadSysDesign.TubeDiameterOuter = Numbers(2);
454 :
455 31 : thisRadSysDesign.VarFlowTubeConductivity = Numbers(3);
456 :
457 : // Process the temperature control type
458 62 : thisRadSysDesign.VarFlowControlType = thisRadSysDesign.processRadiantSystemControlInput(
459 31 : state, Alphas(3), cAlphaFields(3), LowTempRadiantSystem::SystemType::HydronicSystem);
460 :
461 : // Process the setpoint type
462 31 : thisRadSysDesign.VarFlowSetpointType = thisRadSysDesign.processRadiantSystemSetpointInput(state, Alphas(4), cAlphaFields(4));
463 :
464 : // Refactor everything below to Alphas as HCMethod, etc
465 :
466 : // Determine Low Temp Radiant heating design capacity sizing method
467 31 : thisRadSysDesign.DesignHeatingCapMethodInput = Alphas(5);
468 31 : if (UtilityRoutines::SameString(thisRadSysDesign.DesignHeatingCapMethodInput, "HeatingDesignCapacity")) {
469 29 : thisRadSysDesign.DesignHeatingCapMethod = HeatingDesignCapacity;
470 2 : } else if (UtilityRoutines::SameString(thisRadSysDesign.DesignHeatingCapMethodInput, "CapacityPerFloorArea")) {
471 1 : thisRadSysDesign.DesignHeatingCapMethod = CapacityPerFloorArea;
472 1 : if (!lNumericBlanks(4)) {
473 1 : thisRadSysDesign.DesignScaledHeatingCapacity = Numbers(4);
474 1 : if (thisRadSysDesign.DesignScaledHeatingCapacity <= 0.0) {
475 0 : ShowSevereError(state, CurrentModuleObject + " = " + thisRadSysDesign.designName);
476 0 : ShowContinueError(state, "Input for " + cAlphaFields(5) + " = " + thisRadSysDesign.DesignHeatingCapMethodInput);
477 0 : ShowContinueError(state, format("Illegal {} = {:.7T}", cNumericFields(4), Numbers(4)));
478 0 : ErrorsFound = true;
479 1 : } else if (thisRadSysDesign.DesignScaledHeatingCapacity == AutoSize) {
480 0 : ShowSevereError(state, CurrentModuleObject + " = " + thisRadSysDesign.designName);
481 0 : ShowContinueError(state, "Input for " + cAlphaFields(5) + " = " + thisRadSysDesign.DesignHeatingCapMethodInput);
482 0 : ShowContinueError(state, "Illegal " + cNumericFields(4) + " = Autosize");
483 0 : ErrorsFound = true;
484 : }
485 : } else {
486 0 : ShowSevereError(state, CurrentModuleObject + " = " + thisRadSysDesign.Name);
487 0 : ShowContinueError(state, "Input for " + cAlphaFields(5) + " = " + thisRadSysDesign.DesignHeatingCapMethodInput);
488 0 : ShowContinueError(state, "Blank field not allowed for " + cNumericFields(4));
489 0 : ErrorsFound = true;
490 : }
491 1 : } else if (UtilityRoutines::SameString(thisRadSysDesign.DesignHeatingCapMethodInput, "FractionOfAutosizedHeatingCapacity")) {
492 1 : thisRadSysDesign.DesignHeatingCapMethod = FractionOfAutosizedHeatingCapacity;
493 1 : if (!lNumericBlanks(5)) {
494 1 : thisRadSysDesign.DesignScaledHeatingCapacity = Numbers(5);
495 1 : if (thisRadSysDesign.DesignScaledHeatingCapacity < 0.0) {
496 0 : ShowSevereError(state, CurrentModuleObject + " = " + thisRadSysDesign.designName);
497 0 : ShowContinueError(state, format("Illegal {} = {:.7T}", cNumericFields(5), Numbers(5)));
498 0 : ErrorsFound = true;
499 : }
500 : } else {
501 0 : ShowSevereError(state, CurrentModuleObject + " = " + thisRadSysDesign.designName);
502 0 : ShowContinueError(state, "Input for " + cAlphaFields(5) + " = " + thisRadSysDesign.DesignHeatingCapMethodInput);
503 0 : ShowContinueError(state, "Blank field not allowed for " + cNumericFields(5));
504 0 : ErrorsFound = true;
505 : }
506 : } else {
507 0 : ShowSevereError(state, CurrentModuleObject + " = " + thisRadSysDesign.designName);
508 0 : ShowContinueError(state, "Illegal " + cAlphaFields(5) + " = " + thisRadSysDesign.DesignHeatingCapMethodInput);
509 0 : ErrorsFound = true;
510 : }
511 :
512 31 : thisRadSysDesign.HotThrottlRange = Numbers(6);
513 :
514 31 : thisRadSysDesign.HotSetptSched = Alphas(6);
515 31 : thisRadSysDesign.HotSetptSchedPtr = GetScheduleIndex(state, thisRadSysDesign.HotSetptSched);
516 31 : if ((thisRadSysDesign.HotSetptSchedPtr == 0) && (!lAlphaBlanks(6))) {
517 0 : ShowSevereError(state, cAlphaFields(6) + " not found: " + Alphas(6));
518 0 : ShowContinueError(state, "Occurs in " + CurrentModuleObject + " = " + Alphas(1));
519 0 : ErrorsFound = true;
520 : }
521 :
522 : // Determine Low Temp Radiant cooling design capacity sizing method
523 31 : thisRadSysDesign.DesignCoolingCapMethodInput = Alphas(7);
524 31 : if (UtilityRoutines::SameString(thisRadSysDesign.DesignCoolingCapMethodInput, "CoolingDesignCapacity")) {
525 29 : thisRadSysDesign.DesignCoolingCapMethod = CoolingDesignCapacity;
526 2 : } else if (UtilityRoutines::SameString(thisRadSysDesign.DesignCoolingCapMethodInput, "CapacityPerFloorArea")) {
527 1 : thisRadSysDesign.DesignCoolingCapMethod = CapacityPerFloorArea;
528 1 : if (!lNumericBlanks(7)) {
529 1 : thisRadSysDesign.DesignScaledCoolingCapacity = Numbers(7);
530 2 : std::string a = cNumericFields(4);
531 1 : if (thisRadSysDesign.DesignScaledCoolingCapacity <= 0.0) {
532 0 : ShowSevereError(state, CurrentModuleObject + " = " + thisRadSysDesign.designName);
533 0 : ShowContinueError(state, "Input for " + cAlphaFields(7) + " = " + thisRadSysDesign.DesignCoolingCapMethodInput);
534 0 : ShowContinueError(state, format("Illegal {} = {:.7T}", cNumericFields(7), thisRadSysDesign.DesignScaledCoolingCapacity));
535 0 : ErrorsFound = true;
536 1 : } else if (thisRadSysDesign.DesignScaledCoolingCapacity == AutoSize) {
537 0 : ShowSevereError(state, CurrentModuleObject + " = " + thisRadSysDesign.designName);
538 0 : ShowContinueError(state, "Input for " + cAlphaFields(7) + " = " + thisRadSysDesign.DesignCoolingCapMethodInput);
539 0 : ShowContinueError(state, "Illegal " + cNumericFields(7) + " = Autosize");
540 0 : ErrorsFound = true;
541 : }
542 : } else {
543 0 : ShowSevereError(state, CurrentModuleObject + " = " + thisRadSysDesign.designName);
544 0 : ShowContinueError(state, "Input for " + cAlphaFields(7) + " = " + thisRadSysDesign.DesignCoolingCapMethodInput);
545 0 : ShowContinueError(state, "Blank field not allowed for " + cNumericFields(7));
546 0 : ErrorsFound = true;
547 : }
548 1 : } else if (UtilityRoutines::SameString(thisRadSysDesign.DesignCoolingCapMethodInput, "FractionOfAutosizedCoolingCapacity")) {
549 1 : thisRadSysDesign.DesignCoolingCapMethod = FractionOfAutosizedCoolingCapacity;
550 1 : if (!lNumericBlanks(8)) {
551 1 : thisRadSysDesign.DesignScaledCoolingCapacity = Numbers(8);
552 1 : if (thisRadSysDesign.DesignScaledCoolingCapacity < 0.0) {
553 0 : ShowSevereError(state, CurrentModuleObject + " = " + thisRadSysDesign.designName);
554 0 : ShowContinueError(state, format("Illegal {} = {:.7T}", cNumericFields(8), Numbers(8)));
555 0 : ErrorsFound = true;
556 : }
557 : } else {
558 0 : ShowSevereError(state, CurrentModuleObject + " = " + thisRadSysDesign.designName);
559 0 : ShowContinueError(state, "Input for " + cAlphaFields(7) + " = " + thisRadSysDesign.DesignCoolingCapMethodInput);
560 0 : ShowContinueError(state, "Blank field not allowed for " + cNumericFields(8));
561 0 : ErrorsFound = true;
562 : }
563 : } else {
564 0 : ShowSevereError(state, CurrentModuleObject + " = " + thisRadSysDesign.designName);
565 0 : ShowContinueError(state, "Illegal " + cAlphaFields(7) + " = " + thisRadSysDesign.DesignCoolingCapMethodInput);
566 0 : ErrorsFound = true;
567 : }
568 :
569 31 : thisRadSysDesign.ColdThrottlRange = Numbers(9);
570 :
571 31 : thisRadSysDesign.ColdSetptSched = Alphas(8);
572 31 : thisRadSysDesign.ColdSetptSchedPtr = GetScheduleIndex(state, Alphas(8));
573 31 : if ((thisRadSysDesign.ColdSetptSchedPtr == 0) && (!lAlphaBlanks(8))) {
574 0 : ShowSevereError(state, cAlphaFields(8) + " not found: " + Alphas(8));
575 0 : ShowContinueError(state, "Occurs in " + CurrentModuleObject + " = " + Alphas(1));
576 0 : ErrorsFound = true;
577 : }
578 :
579 31 : if (UtilityRoutines::SameString(Alphas(9), Off)) {
580 10 : thisRadSysDesign.CondCtrlType = CondContrlType::CondCtrlNone;
581 21 : } else if (UtilityRoutines::SameString(Alphas(9), SimpleOff)) {
582 19 : thisRadSysDesign.CondCtrlType = CondContrlType::CondCtrlSimpleOff;
583 2 : } else if (UtilityRoutines::SameString(Alphas(9), VariableOff)) {
584 2 : thisRadSysDesign.CondCtrlType = CondContrlType::CondCtrlVariedOff;
585 : } else {
586 0 : thisRadSysDesign.CondCtrlType = CondContrlType::CondCtrlSimpleOff;
587 : }
588 :
589 31 : thisRadSysDesign.CondDewPtDeltaT = Numbers(10);
590 :
591 31 : thisRadSysDesign.schedNameChangeoverDelay = Alphas(10);
592 31 : if (!lAlphaBlanks(10)) {
593 3 : thisRadSysDesign.schedPtrChangeoverDelay = GetScheduleIndex(state, thisRadSysDesign.schedNameChangeoverDelay);
594 3 : if (thisRadSysDesign.schedPtrChangeoverDelay == 0) {
595 0 : ShowWarningError(state, cAlphaFields(10) + " not found for " + thisRadSysDesign.schedNameChangeoverDelay);
596 0 : ShowContinueError(state, "This occurs for " + cAlphaFields(1) + " = " + Alphas(1));
597 0 : ShowContinueError(state, "As a result, no changeover delay will be used for this radiant system.");
598 : }
599 : }
600 :
601 31 : VarFlowRadDesignNames(Item) = Alphas(1);
602 : }
603 :
604 : // Obtain all of the user data related to hydronic low temperature radiant systems...
605 29 : BaseNum = 0;
606 29 : CurrentModuleObject = "ZoneHVAC:LowTemperatureRadiant:VariableFlow";
607 75 : for (Item = 1; Item <= state.dataLowTempRadSys->NumOfHydrLowTempRadSys; ++Item) {
608 :
609 46 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
610 : CurrentModuleObject,
611 : Item,
612 : Alphas,
613 : NumAlphas,
614 : Numbers,
615 : NumNumbers,
616 : IOStatus,
617 : lNumericBlanks,
618 : lAlphaBlanks,
619 : cAlphaFields,
620 : cNumericFields);
621 :
622 46 : state.dataLowTempRadSys->HydronicRadiantSysNumericFields(Item).FieldNames.allocate(NumNumbers);
623 46 : state.dataLowTempRadSys->HydronicRadiantSysNumericFields(Item).FieldNames = "";
624 46 : state.dataLowTempRadSys->HydronicRadiantSysNumericFields(Item).FieldNames = cNumericFields;
625 92 : GlobalNames::VerifyUniqueInterObjectName(
626 92 : state, state.dataLowTempRadSys->LowTempRadUniqueNames, Alphas(1), CurrentModuleObject, cAlphaFields(1), ErrorsFound);
627 :
628 46 : ++BaseNum;
629 46 : state.dataLowTempRadSys->RadSysTypes(BaseNum).Name = Alphas(1);
630 46 : state.dataLowTempRadSys->RadSysTypes(BaseNum).SystemType = LowTempRadiantSystem::SystemType::HydronicSystem;
631 :
632 46 : auto &thisRadSys(state.dataLowTempRadSys->HydrRadSys(Item));
633 :
634 : // General user input data
635 46 : thisRadSys.Name = Alphas(1);
636 :
637 46 : thisRadSys.designObjectName = Alphas(2);
638 46 : thisRadSys.DesignObjectPtr = UtilityRoutines::FindItemInList(thisRadSys.designObjectName, VarFlowRadDesignNames);
639 46 : VarFlowRadDesignData variableFlowDesignDataObject{state.dataLowTempRadSys->HydronicRadiantSysDesign(
640 92 : thisRadSys.DesignObjectPtr)}; // Contains the data for variable flow hydronic systems
641 :
642 46 : thisRadSys.SchedName = Alphas(3);
643 46 : if (lAlphaBlanks(3)) {
644 0 : thisRadSys.SchedPtr = DataGlobalConstants::ScheduleAlwaysOn;
645 : } else {
646 46 : thisRadSys.SchedPtr = GetScheduleIndex(state, Alphas(3));
647 46 : if (thisRadSys.SchedPtr == 0) {
648 0 : ShowSevereError(state, cAlphaFields(2) + " not found for " + Alphas(1));
649 0 : ShowContinueError(state, "Missing " + cAlphaFields(3) + " is " + Alphas(3));
650 0 : ErrorsFound = true;
651 : }
652 : }
653 :
654 46 : thisRadSys.ZoneName = Alphas(4);
655 46 : thisRadSys.ZonePtr = UtilityRoutines::FindItemInList(Alphas(4), Zone);
656 46 : if (thisRadSys.ZonePtr == 0) {
657 0 : ShowSevereError(state, format("{}Invalid {} = {}", RoutineName, cAlphaFields(3), Alphas(4)));
658 0 : ShowContinueError(state, "Occurs in " + CurrentModuleObject + " = " + Alphas(1));
659 0 : ErrorsFound = true;
660 : }
661 :
662 46 : thisRadSys.SurfListName = Alphas(5);
663 46 : SurfListNum = 0;
664 46 : if (state.dataSurfLists->NumOfSurfaceLists > 0)
665 4 : SurfListNum = UtilityRoutines::FindItemInList(thisRadSys.SurfListName, state.dataSurfLists->SurfList);
666 46 : if (SurfListNum > 0) { // Found a valid surface list
667 3 : thisRadSys.NumOfSurfaces = state.dataSurfLists->SurfList(SurfListNum).NumOfSurfaces;
668 3 : thisRadSys.SurfacePtr.allocate(thisRadSys.NumOfSurfaces);
669 3 : thisRadSys.SurfaceName.allocate(thisRadSys.NumOfSurfaces);
670 3 : thisRadSys.SurfaceFrac.allocate(thisRadSys.NumOfSurfaces);
671 3 : thisRadSys.NumCircuits.allocate(thisRadSys.NumOfSurfaces);
672 18 : for (SurfNum = 1; SurfNum <= state.dataSurfLists->SurfList(SurfListNum).NumOfSurfaces; ++SurfNum) {
673 15 : thisRadSys.SurfacePtr(SurfNum) = state.dataSurfLists->SurfList(SurfListNum).SurfPtr(SurfNum);
674 15 : thisRadSys.SurfaceName(SurfNum) = state.dataSurfLists->SurfList(SurfListNum).SurfName(SurfNum);
675 15 : thisRadSys.SurfaceFrac(SurfNum) = state.dataSurfLists->SurfList(SurfListNum).SurfFlowFrac(SurfNum);
676 15 : if (thisRadSys.SurfacePtr(SurfNum) > 0) {
677 15 : state.dataSurface->SurfIntConvSurfHasActiveInIt(thisRadSys.SurfacePtr(SurfNum)) = true;
678 : }
679 : }
680 : } else { // User entered a single surface name rather than a surface list
681 43 : thisRadSys.NumOfSurfaces = 1;
682 43 : thisRadSys.SurfacePtr.allocate(thisRadSys.NumOfSurfaces);
683 43 : thisRadSys.SurfaceName.allocate(thisRadSys.NumOfSurfaces);
684 43 : thisRadSys.SurfaceFrac.allocate(thisRadSys.NumOfSurfaces);
685 43 : thisRadSys.NumCircuits.allocate(thisRadSys.NumOfSurfaces);
686 43 : thisRadSys.SurfaceName(1) = thisRadSys.SurfListName;
687 43 : thisRadSys.SurfacePtr(1) = UtilityRoutines::FindItemInList(thisRadSys.SurfaceName(1), Surface);
688 43 : thisRadSys.SurfaceFrac(1) = 1.0;
689 43 : thisRadSys.NumCircuits(1) = 0.0;
690 : // Error checking for single surfaces
691 43 : if (thisRadSys.SurfacePtr(1) == 0) {
692 0 : ShowSevereError(state, format("{}Invalid {} = {}", RoutineName, cAlphaFields(5), Alphas(5)));
693 0 : ShowContinueError(state, "Occurs in " + CurrentModuleObject + " = " + Alphas(1));
694 0 : ErrorsFound = true;
695 43 : } else if (state.dataSurface->SurfIsRadSurfOrVentSlabOrPool(thisRadSys.SurfacePtr(1))) {
696 0 : ShowSevereError(state, std::string{RoutineName} + CurrentModuleObject + "=\"" + Alphas(1) + "\", Invalid Surface");
697 0 : ShowContinueError(state, cAlphaFields(5) + "=\"" + Alphas(5) + "\" has been used in another radiant system or ventilated slab.");
698 0 : ErrorsFound = true;
699 : }
700 43 : if (thisRadSys.SurfacePtr(1) != 0) {
701 43 : state.dataSurface->SurfIntConvSurfHasActiveInIt(thisRadSys.SurfacePtr(1)) = true;
702 43 : state.dataSurface->SurfIntConvSurfHasActiveInIt(thisRadSys.SurfacePtr(1)) = true;
703 : }
704 : }
705 :
706 : // Error checking for zones and construction information
707 46 : thisRadSys.errorCheckZonesAndConstructions(state, ErrorsFound);
708 :
709 46 : thisRadSys.TubeLength = Numbers(1);
710 :
711 : // Determine Low Temp Radiant heating design capacity sizing method
712 46 : if (variableFlowDesignDataObject.DesignHeatingCapMethod == HeatingDesignCapacity) {
713 44 : thisRadSys.HeatingCapMethod = HeatingDesignCapacity;
714 44 : if (!lNumericBlanks(2)) {
715 44 : thisRadSys.ScaledHeatingCapacity = Numbers(2);
716 44 : if (thisRadSys.ScaledHeatingCapacity < 0.0 && thisRadSys.ScaledHeatingCapacity != AutoSize) {
717 0 : ShowSevereError(state, CurrentModuleObject + " = " + thisRadSys.Name);
718 0 : ShowContinueError(state, format("Illegal {} = {:.7T}", cNumericFields(2), Numbers(2)));
719 0 : ErrorsFound = true;
720 : }
721 : } else {
722 0 : if ((!lAlphaBlanks(6)) || (!lAlphaBlanks(7))) {
723 0 : ShowSevereError(state, CurrentModuleObject + " = " + thisRadSys.Name);
724 0 : ShowContinueError(state, "Input for Heating Design Capacity Method = HeatingDesignCapacity");
725 0 : ShowContinueError(state, "Blank field not allowed for " + cNumericFields(2));
726 0 : ErrorsFound = true;
727 : }
728 : }
729 2 : } else if (variableFlowDesignDataObject.DesignHeatingCapMethod == CapacityPerFloorArea) {
730 1 : thisRadSys.HeatingCapMethod = CapacityPerFloorArea;
731 1 : thisRadSys.ScaledHeatingCapacity = variableFlowDesignDataObject.DesignScaledHeatingCapacity;
732 1 : } else if (variableFlowDesignDataObject.DesignHeatingCapMethod == FractionOfAutosizedHeatingCapacity) {
733 1 : thisRadSys.HeatingCapMethod = FractionOfAutosizedHeatingCapacity;
734 1 : thisRadSys.ScaledHeatingCapacity = variableFlowDesignDataObject.DesignScaledHeatingCapacity;
735 : }
736 :
737 : // Heating user input data
738 46 : thisRadSys.WaterVolFlowMaxHeat = Numbers(3);
739 :
740 46 : thisRadSys.HotWaterInNode = GetOnlySingleNode(state,
741 46 : Alphas(6),
742 : ErrorsFound,
743 : DataLoopNode::ConnectionObjectType::ZoneHVACLowTemperatureRadiantVariableFlow,
744 46 : Alphas(1),
745 : DataLoopNode::NodeFluidType::Water,
746 : DataLoopNode::ConnectionType::Inlet,
747 : NodeInputManager::CompFluidStream::Primary,
748 46 : ObjectIsNotParent);
749 :
750 46 : thisRadSys.HotWaterOutNode = GetOnlySingleNode(state,
751 46 : Alphas(7),
752 : ErrorsFound,
753 : DataLoopNode::ConnectionObjectType::ZoneHVACLowTemperatureRadiantVariableFlow,
754 46 : Alphas(1),
755 : DataLoopNode::NodeFluidType::Water,
756 : DataLoopNode::ConnectionType::Outlet,
757 : NodeInputManager::CompFluidStream::Primary,
758 46 : ObjectIsNotParent);
759 :
760 46 : if ((!lAlphaBlanks(6)) || (!lAlphaBlanks(7))) {
761 46 : TestCompSet(state, CurrentModuleObject, Alphas(1), Alphas(6), Alphas(7), "Hot Water Nodes");
762 : }
763 52 : if ((thisRadSys.WaterVolFlowMaxHeat == AutoSize) &&
764 18 : (lAlphaBlanks(6) || lAlphaBlanks(7) || (thisRadSys.HotWaterInNode <= 0) || (thisRadSys.HotWaterOutNode <= 0) ||
765 6 : (variableFlowDesignDataObject.HotSetptSchedPtr == 0))) {
766 0 : ShowSevereError(state, "Hydronic radiant systems may not be autosized without specification of nodes or schedules.");
767 0 : ShowContinueError(state, "Occurs in " + CurrentModuleObject + " (heating input) = " + Alphas(1));
768 0 : ErrorsFound = true;
769 : }
770 :
771 : // Determine Low Temp Radiant cooling design capacity sizing method
772 46 : if (variableFlowDesignDataObject.DesignCoolingCapMethod == CoolingDesignCapacity) {
773 44 : thisRadSys.CoolingCapMethod = CoolingDesignCapacity;
774 44 : if (!lNumericBlanks(4)) {
775 44 : thisRadSys.ScaledCoolingCapacity = Numbers(4);
776 44 : if (thisRadSys.ScaledCoolingCapacity < 0.0 && thisRadSys.ScaledCoolingCapacity != AutoSize) {
777 0 : ShowSevereError(state, CurrentModuleObject + " = " + thisRadSys.Name);
778 0 : ShowContinueError(state, format("Illegal {} = {:.7T}", cNumericFields(4), Numbers(4)));
779 0 : ErrorsFound = true;
780 : }
781 : } else {
782 0 : if ((!lAlphaBlanks(8)) || (!lAlphaBlanks(9))) {
783 0 : ShowSevereError(state, CurrentModuleObject + " = " + thisRadSys.Name);
784 0 : ShowContinueError(state, "Input for Cooling Design Capacity Method = CoolingDesignCapacity");
785 0 : ShowContinueError(state, "Blank field not allowed for " + cNumericFields(4));
786 0 : ErrorsFound = true;
787 : }
788 : }
789 2 : } else if (variableFlowDesignDataObject.DesignCoolingCapMethod == CapacityPerFloorArea) {
790 1 : thisRadSys.CoolingCapMethod = CapacityPerFloorArea;
791 1 : thisRadSys.ScaledCoolingCapacity = variableFlowDesignDataObject.DesignScaledCoolingCapacity;
792 1 : } else if (variableFlowDesignDataObject.DesignCoolingCapMethod == FractionOfAutosizedCoolingCapacity) {
793 1 : thisRadSys.CoolingCapMethod = FractionOfAutosizedCoolingCapacity;
794 1 : thisRadSys.ScaledCoolingCapacity = variableFlowDesignDataObject.DesignScaledCoolingCapacity;
795 : }
796 :
797 : // Cooling user input data
798 46 : thisRadSys.WaterVolFlowMaxCool = Numbers(5);
799 :
800 46 : thisRadSys.ColdWaterInNode = GetOnlySingleNode(state,
801 46 : Alphas(8),
802 : ErrorsFound,
803 : DataLoopNode::ConnectionObjectType::ZoneHVACLowTemperatureRadiantVariableFlow,
804 46 : Alphas(1),
805 : DataLoopNode::NodeFluidType::Water,
806 : DataLoopNode::ConnectionType::Inlet,
807 : NodeInputManager::CompFluidStream::Secondary,
808 46 : ObjectIsNotParent);
809 :
810 46 : thisRadSys.ColdWaterOutNode = GetOnlySingleNode(state,
811 46 : Alphas(9),
812 : ErrorsFound,
813 : DataLoopNode::ConnectionObjectType::ZoneHVACLowTemperatureRadiantVariableFlow,
814 46 : Alphas(1),
815 : DataLoopNode::NodeFluidType::Water,
816 : DataLoopNode::ConnectionType::Outlet,
817 : NodeInputManager::CompFluidStream::Secondary,
818 46 : ObjectIsNotParent);
819 :
820 46 : if ((!lAlphaBlanks(8)) || (!lAlphaBlanks(9))) {
821 43 : TestCompSet(state, CurrentModuleObject, Alphas(1), Alphas(8), Alphas(9), "Chilled Water Nodes");
822 : }
823 :
824 46 : if (UtilityRoutines::SameString(Alphas(10), OnePerSurf)) {
825 46 : thisRadSys.NumCircCalcMethod = CircuitCalc::OneCircuit;
826 0 : } else if (UtilityRoutines::SameString(Alphas(10), CalcFromLength)) {
827 0 : thisRadSys.NumCircCalcMethod = CircuitCalc::CalculateFromLength;
828 : } else {
829 0 : thisRadSys.NumCircCalcMethod = CircuitCalc::OneCircuit;
830 : }
831 :
832 46 : thisRadSys.schedPtrChangeoverDelay = variableFlowDesignDataObject.schedPtrChangeoverDelay;
833 :
834 46 : thisRadSys.CircLength = Numbers(6);
835 :
836 52 : if ((thisRadSys.WaterVolFlowMaxCool == AutoSize) &&
837 18 : (variableFlowDesignDataObject.DesignCoolingCapMethod == 0 || lAlphaBlanks(8) || lAlphaBlanks(9) ||
838 12 : (thisRadSys.ColdWaterInNode <= 0) || (thisRadSys.ColdWaterOutNode <= 0) || (variableFlowDesignDataObject.ColdSetptSchedPtr == 0))) {
839 0 : ShowSevereError(state, "Hydronic radiant systems may not be autosized without specification of nodes or schedules");
840 0 : ShowContinueError(state, "Occurs in " + CurrentModuleObject + " (cooling input) =" + Alphas(1));
841 0 : ErrorsFound = true;
842 : }
843 : }
844 :
845 : // Obtain all of the design data related to Constant flow low temperature radiant systems...
846 29 : CurrentModuleObject = "ZoneHVAC:LowTemperatureRadiant:ConstantFlow:Design";
847 52 : for (Item = 1; Item <= state.dataLowTempRadSys->NumOfCFloLowTempRadSysDes; ++Item) {
848 :
849 23 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
850 : CurrentModuleObject,
851 : Item,
852 : Alphas,
853 : NumAlphas,
854 : Numbers,
855 : NumNumbers,
856 : IOStatus,
857 : lNumericBlanks,
858 : lAlphaBlanks,
859 : cAlphaFields,
860 : cNumericFields);
861 :
862 23 : state.dataLowTempRadSys->CflowRadiantSysDesign(Item).FieldNames.allocate(NumNumbers);
863 23 : state.dataLowTempRadSys->CflowRadiantSysDesign(Item).FieldNames = "";
864 23 : state.dataLowTempRadSys->CflowRadiantSysDesign(Item).FieldNames = cNumericFields;
865 46 : GlobalNames::VerifyUniqueInterObjectName(
866 46 : state, state.dataLowTempRadSys->LowTempRadUniqueNames, Alphas(1), CurrentModuleObject, cAlphaFields(1), ErrorsFound);
867 :
868 23 : auto &thisRadSysDesign(state.dataLowTempRadSys->CflowRadiantSysDesign(Item));
869 :
870 : // General user input data
871 23 : thisRadSysDesign.designName = Alphas(1);
872 :
873 23 : thisRadSysDesign.FluidToSlabHeatTransfer = thisRadSysDesign.getFluidToSlabHeatTransferInput(state, Alphas(2));
874 :
875 23 : thisRadSysDesign.TubeDiameterInner = Numbers(1);
876 23 : thisRadSysDesign.TubeDiameterOuter = Numbers(2);
877 23 : thisRadSysDesign.ConstFlowTubeConductivity = Numbers(3);
878 :
879 : // Process the temperature control type
880 46 : thisRadSysDesign.ConstFlowControlType = thisRadSysDesign.processRadiantSystemControlInput(
881 23 : state, Alphas(3), cAlphaFields(3), LowTempRadiantSystem::SystemType::ConstantFlowSystem);
882 23 : thisRadSysDesign.runningMeanOutdoorAirTemperatureWeightingFactor = Numbers(4);
883 23 : thisRadSysDesign.MotorEffic = Numbers(5);
884 23 : thisRadSysDesign.FracMotorLossToFluid = Numbers(6);
885 :
886 23 : if (UtilityRoutines::SameString(Alphas(4), Off)) {
887 16 : thisRadSysDesign.CondCtrlType = CondContrlType::CondCtrlNone;
888 7 : } else if (UtilityRoutines::SameString(Alphas(4), SimpleOff)) {
889 5 : thisRadSysDesign.CondCtrlType = CondContrlType::CondCtrlSimpleOff;
890 2 : } else if (UtilityRoutines::SameString(Alphas(4), VariableOff)) {
891 2 : thisRadSysDesign.CondCtrlType = CondContrlType::CondCtrlVariedOff;
892 : } else {
893 0 : thisRadSysDesign.CondCtrlType = CondContrlType::CondCtrlSimpleOff;
894 : }
895 23 : thisRadSysDesign.CondDewPtDeltaT = Numbers(7);
896 :
897 23 : thisRadSysDesign.schedNameChangeoverDelay = Alphas(5);
898 23 : if (!lAlphaBlanks(5)) {
899 3 : thisRadSysDesign.schedPtrChangeoverDelay = GetScheduleIndex(state, thisRadSysDesign.schedNameChangeoverDelay);
900 3 : if (thisRadSysDesign.schedPtrChangeoverDelay == 0) {
901 0 : ShowWarningError(state, cAlphaFields(5) + " not found for " + thisRadSysDesign.schedNameChangeoverDelay);
902 0 : ShowContinueError(state, "This occurs for " + cAlphaFields(1) + " = " + Alphas(1));
903 0 : ShowContinueError(state, "As a result, no changeover delay will be used for this radiant system.");
904 : }
905 : }
906 23 : CFlowRadDesignNames(Item) = Alphas(1);
907 : }
908 :
909 : // Obtain all of the user data related to constant flow (hydronic) low temperature radiant systems...
910 29 : CurrentModuleObject = "ZoneHVAC:LowTemperatureRadiant:ConstantFlow";
911 56 : for (Item = 1; Item <= state.dataLowTempRadSys->NumOfCFloLowTempRadSys; ++Item) {
912 :
913 27 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
914 : CurrentModuleObject,
915 : Item,
916 : Alphas,
917 : NumAlphas,
918 : Numbers,
919 : NumNumbers,
920 : IOStatus,
921 : lNumericBlanks,
922 : lAlphaBlanks,
923 : cAlphaFields,
924 : cNumericFields);
925 54 : GlobalNames::VerifyUniqueInterObjectName(
926 54 : state, state.dataLowTempRadSys->LowTempRadUniqueNames, Alphas(1), CurrentModuleObject, cAlphaFields(1), ErrorsFound);
927 27 : ++BaseNum;
928 27 : state.dataLowTempRadSys->RadSysTypes(BaseNum).Name = Alphas(1);
929 27 : state.dataLowTempRadSys->RadSysTypes(BaseNum).SystemType = LowTempRadiantSystem::SystemType::ConstantFlowSystem;
930 :
931 : // General user input data
932 27 : auto &thisCFloSys(state.dataLowTempRadSys->CFloRadSys(Item));
933 :
934 27 : thisCFloSys.Name = Alphas(1);
935 27 : thisCFloSys.designObjectName = Alphas(2);
936 27 : thisCFloSys.DesignObjectPtr = UtilityRoutines::FindItemInList(thisCFloSys.designObjectName, CFlowRadDesignNames);
937 : ConstantFlowRadDesignData ConstantFlowRadDesignDataObject{
938 54 : state.dataLowTempRadSys->CflowRadiantSysDesign(thisCFloSys.DesignObjectPtr)}; // Contains the data for variable flow hydronic systems
939 :
940 27 : thisCFloSys.SchedName = Alphas(3);
941 27 : if (lAlphaBlanks(3)) {
942 0 : thisCFloSys.SchedPtr = DataGlobalConstants::ScheduleAlwaysOn;
943 : } else {
944 27 : thisCFloSys.SchedPtr = GetScheduleIndex(state, Alphas(3));
945 27 : if (thisCFloSys.SchedPtr == 0) {
946 0 : ShowSevereError(state, cAlphaFields(3) + " not found for " + Alphas(1));
947 0 : ShowContinueError(state, "Missing " + cAlphaFields(3) + " is " + Alphas(3));
948 0 : ErrorsFound = true;
949 : }
950 : }
951 :
952 27 : thisCFloSys.ZoneName = Alphas(4);
953 27 : thisCFloSys.ZonePtr = UtilityRoutines::FindItemInList(Alphas(4), Zone);
954 27 : if (thisCFloSys.ZonePtr == 0) {
955 0 : ShowSevereError(state, format("{}Invalid {} = {}", RoutineName, cAlphaFields(4), Alphas(4)));
956 0 : ShowContinueError(state, "Occurs in " + CurrentModuleObject + " = " + Alphas(1));
957 0 : ErrorsFound = true;
958 : }
959 :
960 27 : thisCFloSys.SurfListName = Alphas(5);
961 27 : SurfListNum = 0;
962 27 : if (state.dataSurfLists->NumOfSurfaceLists > 0)
963 0 : SurfListNum = UtilityRoutines::FindItemInList(thisCFloSys.SurfListName, state.dataSurfLists->SurfList);
964 27 : if (SurfListNum > 0) { // Found a valid surface list
965 0 : thisCFloSys.NumOfSurfaces = state.dataSurfLists->SurfList(SurfListNum).NumOfSurfaces;
966 0 : thisCFloSys.SurfacePtr.allocate(thisCFloSys.NumOfSurfaces);
967 0 : thisCFloSys.SurfaceName.allocate(thisCFloSys.NumOfSurfaces);
968 0 : thisCFloSys.SurfaceFrac.allocate(thisCFloSys.NumOfSurfaces);
969 0 : thisCFloSys.NumCircuits.allocate(thisCFloSys.NumOfSurfaces);
970 0 : state.dataLowTempRadSys->MaxCloNumOfSurfaces = max(state.dataLowTempRadSys->MaxCloNumOfSurfaces, thisCFloSys.NumOfSurfaces);
971 0 : for (SurfNum = 1; SurfNum <= state.dataSurfLists->SurfList(SurfListNum).NumOfSurfaces; ++SurfNum) {
972 0 : thisCFloSys.SurfacePtr(SurfNum) = state.dataSurfLists->SurfList(SurfListNum).SurfPtr(SurfNum);
973 0 : thisCFloSys.SurfaceName(SurfNum) = state.dataSurfLists->SurfList(SurfListNum).SurfName(SurfNum);
974 0 : thisCFloSys.SurfaceFrac(SurfNum) = state.dataSurfLists->SurfList(SurfListNum).SurfFlowFrac(SurfNum);
975 0 : thisCFloSys.NumCircuits(SurfNum) = 0.0;
976 0 : if (thisCFloSys.SurfacePtr(SurfNum) != 0) {
977 0 : state.dataSurface->SurfIntConvSurfHasActiveInIt(thisCFloSys.SurfacePtr(SurfNum)) = true;
978 : }
979 : }
980 : } else { // User entered a single surface name rather than a surface list
981 27 : thisCFloSys.NumOfSurfaces = 1;
982 27 : thisCFloSys.SurfacePtr.allocate(thisCFloSys.NumOfSurfaces);
983 27 : thisCFloSys.SurfaceName.allocate(thisCFloSys.NumOfSurfaces);
984 27 : thisCFloSys.SurfaceFrac.allocate(thisCFloSys.NumOfSurfaces);
985 27 : thisCFloSys.NumCircuits.allocate(thisCFloSys.NumOfSurfaces);
986 27 : state.dataLowTempRadSys->MaxCloNumOfSurfaces = max(state.dataLowTempRadSys->MaxCloNumOfSurfaces, thisCFloSys.NumOfSurfaces);
987 27 : thisCFloSys.SurfaceName(1) = thisCFloSys.SurfListName;
988 27 : thisCFloSys.SurfacePtr(1) = UtilityRoutines::FindItemInList(thisCFloSys.SurfaceName(1), Surface);
989 27 : thisCFloSys.SurfaceFrac(1) = 1.0;
990 27 : thisCFloSys.NumCircuits(1) = 0.0;
991 : // Error checking for single surfaces
992 27 : if (thisCFloSys.SurfacePtr(1) == 0) {
993 0 : ShowSevereError(state, format("{}Invalid {} = {}", RoutineName, cAlphaFields(4), Alphas(4)));
994 0 : ShowContinueError(state, "Occurs in " + CurrentModuleObject + " = " + Alphas(1));
995 0 : ErrorsFound = true;
996 27 : } else if (state.dataSurface->SurfIsRadSurfOrVentSlabOrPool(thisCFloSys.SurfacePtr(1))) {
997 0 : ShowSevereError(state, std::string{RoutineName} + CurrentModuleObject + "=\"" + Alphas(1) + "\", Invalid Surface");
998 0 : ShowContinueError(state, cAlphaFields(5) + "=\"" + Alphas(5) + "\" has been used in another radiant system or ventilated slab.");
999 0 : ErrorsFound = true;
1000 : }
1001 27 : if (thisCFloSys.SurfacePtr(1) != 0) {
1002 27 : state.dataSurface->SurfIntConvSurfHasActiveInIt(thisCFloSys.SurfacePtr(1)) = true;
1003 27 : state.dataSurface->SurfIsRadSurfOrVentSlabOrPool(thisCFloSys.SurfacePtr(1)) = true;
1004 : }
1005 : }
1006 :
1007 : // Error checking for zones and construction information
1008 27 : thisCFloSys.errorCheckZonesAndConstructions(state, ErrorsFound);
1009 :
1010 27 : thisCFloSys.TubeLength = Numbers(1);
1011 :
1012 : // Process pump input for constant flow (hydronic) radiant system
1013 27 : thisCFloSys.WaterVolFlowMax = Numbers(2);
1014 27 : thisCFloSys.VolFlowSched = Alphas(6);
1015 27 : thisCFloSys.VolFlowSchedPtr = GetScheduleIndex(state, thisCFloSys.VolFlowSched);
1016 27 : if ((thisCFloSys.VolFlowSchedPtr == 0) && (!lAlphaBlanks(6))) {
1017 0 : ShowSevereError(state, cAlphaFields(6) + " not found: " + Alphas(6));
1018 0 : ShowContinueError(state, "Occurs in " + CurrentModuleObject + " = " + Alphas(1));
1019 0 : ErrorsFound = true;
1020 : }
1021 27 : thisCFloSys.NomPumpHead = Numbers(3);
1022 27 : thisCFloSys.NomPowerUse = Numbers(4);
1023 :
1024 : // Heating user input data
1025 27 : thisCFloSys.HotWaterInNode = GetOnlySingleNode(state,
1026 27 : Alphas(7),
1027 : ErrorsFound,
1028 : DataLoopNode::ConnectionObjectType::ZoneHVACLowTemperatureRadiantConstantFlow,
1029 27 : Alphas(1),
1030 : DataLoopNode::NodeFluidType::Water,
1031 : DataLoopNode::ConnectionType::Inlet,
1032 : NodeInputManager::CompFluidStream::Primary,
1033 27 : ObjectIsNotParent);
1034 :
1035 27 : thisCFloSys.HotWaterOutNode = GetOnlySingleNode(state,
1036 27 : Alphas(8),
1037 : ErrorsFound,
1038 : DataLoopNode::ConnectionObjectType::ZoneHVACLowTemperatureRadiantConstantFlow,
1039 27 : Alphas(1),
1040 : DataLoopNode::NodeFluidType::Water,
1041 : DataLoopNode::ConnectionType::Outlet,
1042 : NodeInputManager::CompFluidStream::Primary,
1043 27 : ObjectIsNotParent);
1044 :
1045 27 : if ((!lAlphaBlanks(7)) || (!lAlphaBlanks(8))) {
1046 27 : TestCompSet(state, CurrentModuleObject, Alphas(1), Alphas(7), Alphas(8), "Hot Water Nodes");
1047 : }
1048 :
1049 27 : thisCFloSys.HotWaterHiTempSched = Alphas(9);
1050 27 : thisCFloSys.HotWaterHiTempSchedPtr = GetScheduleIndex(state, Alphas(9));
1051 27 : if ((thisCFloSys.HotWaterHiTempSchedPtr == 0) && (!lAlphaBlanks(9))) {
1052 0 : ShowSevereError(state, cAlphaFields(9) + " not found: " + Alphas(9));
1053 0 : ShowContinueError(state, "Occurs in " + CurrentModuleObject + " = " + Alphas(1));
1054 0 : ErrorsFound = true;
1055 : }
1056 :
1057 27 : thisCFloSys.HotWaterLoTempSched = Alphas(10);
1058 27 : thisCFloSys.HotWaterLoTempSchedPtr = GetScheduleIndex(state, Alphas(10));
1059 27 : if ((thisCFloSys.HotWaterLoTempSchedPtr == 0) && (!lAlphaBlanks(10))) {
1060 0 : ShowSevereError(state, cAlphaFields(10) + " not found: " + Alphas(10));
1061 0 : ShowContinueError(state, "Occurs in " + CurrentModuleObject + " = " + Alphas(1));
1062 0 : ErrorsFound = true;
1063 : }
1064 :
1065 27 : thisCFloSys.HotCtrlHiTempSched = Alphas(11);
1066 27 : thisCFloSys.HotCtrlHiTempSchedPtr = GetScheduleIndex(state, Alphas(11));
1067 27 : if ((thisCFloSys.HotCtrlHiTempSchedPtr == 0) && (!lAlphaBlanks(11))) {
1068 0 : ShowSevereError(state, cAlphaFields(11) + " not found: " + Alphas(11));
1069 0 : ShowContinueError(state, "Occurs in " + CurrentModuleObject + " = " + Alphas(1));
1070 0 : ErrorsFound = true;
1071 : }
1072 :
1073 27 : thisCFloSys.HotCtrlLoTempSched = Alphas(12);
1074 27 : thisCFloSys.HotCtrlLoTempSchedPtr = GetScheduleIndex(state, Alphas(12));
1075 27 : if ((thisCFloSys.HotCtrlLoTempSchedPtr == 0) && (!lAlphaBlanks(12))) {
1076 0 : ShowSevereError(state, cAlphaFields(12) + " not found: " + Alphas(12));
1077 0 : ShowContinueError(state, "Occurs in " + CurrentModuleObject + " = " + Alphas(1));
1078 0 : ErrorsFound = true;
1079 : }
1080 :
1081 : // Cooling user input data
1082 27 : thisCFloSys.ColdWaterInNode = GetOnlySingleNode(state,
1083 27 : Alphas(13),
1084 : ErrorsFound,
1085 : DataLoopNode::ConnectionObjectType::ZoneHVACLowTemperatureRadiantConstantFlow,
1086 27 : Alphas(1),
1087 : DataLoopNode::NodeFluidType::Water,
1088 : DataLoopNode::ConnectionType::Inlet,
1089 : NodeInputManager::CompFluidStream::Secondary,
1090 27 : ObjectIsNotParent);
1091 :
1092 27 : thisCFloSys.ColdWaterOutNode = GetOnlySingleNode(state,
1093 27 : Alphas(14),
1094 : ErrorsFound,
1095 : DataLoopNode::ConnectionObjectType::ZoneHVACLowTemperatureRadiantConstantFlow,
1096 27 : Alphas(1),
1097 : DataLoopNode::NodeFluidType::Water,
1098 : DataLoopNode::ConnectionType::Outlet,
1099 : NodeInputManager::CompFluidStream::Secondary,
1100 27 : ObjectIsNotParent);
1101 :
1102 27 : if ((!lAlphaBlanks(13)) || (!lAlphaBlanks(14))) {
1103 24 : TestCompSet(state, CurrentModuleObject, Alphas(1), Alphas(13), Alphas(14), "Chilled Water Nodes");
1104 : }
1105 :
1106 27 : thisCFloSys.ColdWaterHiTempSched = Alphas(15);
1107 27 : thisCFloSys.ColdWaterHiTempSchedPtr = GetScheduleIndex(state, Alphas(15));
1108 27 : if ((thisCFloSys.ColdWaterHiTempSchedPtr == 0) && (!lAlphaBlanks(15))) {
1109 0 : ShowSevereError(state, cAlphaFields(15) + " not found: " + Alphas(15));
1110 0 : ShowContinueError(state, "Occurs in " + CurrentModuleObject + " = " + Alphas(1));
1111 0 : ErrorsFound = true;
1112 : }
1113 :
1114 27 : thisCFloSys.ColdWaterLoTempSched = Alphas(16);
1115 27 : thisCFloSys.ColdWaterLoTempSchedPtr = GetScheduleIndex(state, Alphas(16));
1116 27 : if ((thisCFloSys.ColdWaterLoTempSchedPtr == 0) && (!lAlphaBlanks(16))) {
1117 0 : ShowSevereError(state, cAlphaFields(16) + " not found: " + Alphas(16));
1118 0 : ShowContinueError(state, "Occurs in " + CurrentModuleObject + " = " + Alphas(1));
1119 0 : ErrorsFound = true;
1120 : }
1121 :
1122 27 : thisCFloSys.ColdCtrlHiTempSched = Alphas(17);
1123 27 : thisCFloSys.ColdCtrlHiTempSchedPtr = GetScheduleIndex(state, Alphas(17));
1124 27 : if ((thisCFloSys.ColdCtrlHiTempSchedPtr == 0) && (!lAlphaBlanks(17))) {
1125 0 : ShowSevereError(state, cAlphaFields(17) + " not found: " + Alphas(17));
1126 0 : ShowContinueError(state, "Occurs in " + CurrentModuleObject + " = " + Alphas(1));
1127 0 : ErrorsFound = true;
1128 : }
1129 :
1130 27 : thisCFloSys.ColdCtrlLoTempSched = Alphas(18);
1131 27 : thisCFloSys.ColdCtrlLoTempSchedPtr = GetScheduleIndex(state, Alphas(18));
1132 27 : if ((thisCFloSys.ColdCtrlLoTempSchedPtr == 0) && (!lAlphaBlanks(18))) {
1133 0 : ShowSevereError(state, cAlphaFields(19) + " not found: " + Alphas(18));
1134 0 : ShowContinueError(state, "Occurs in " + CurrentModuleObject + " = " + Alphas(1));
1135 0 : ErrorsFound = true;
1136 : }
1137 :
1138 27 : if (UtilityRoutines::SameString(Alphas(19), OnePerSurf)) {
1139 27 : thisCFloSys.NumCircCalcMethod = CircuitCalc::OneCircuit;
1140 0 : } else if (UtilityRoutines::SameString(Alphas(19), CalcFromLength)) {
1141 0 : thisCFloSys.NumCircCalcMethod = CircuitCalc::CalculateFromLength;
1142 : } else {
1143 0 : thisCFloSys.NumCircCalcMethod = CircuitCalc::OneCircuit;
1144 : }
1145 :
1146 27 : thisCFloSys.schedPtrChangeoverDelay = ConstantFlowRadDesignDataObject.schedPtrChangeoverDelay;
1147 :
1148 27 : thisCFloSys.CircLength = Numbers(5);
1149 : }
1150 :
1151 : // Obtain all of the user data related to electric low temperature radiant systems...
1152 29 : CurrentModuleObject = "ZoneHVAC:LowTemperatureRadiant:Electric";
1153 :
1154 38 : for (Item = 1; Item <= state.dataLowTempRadSys->NumOfElecLowTempRadSys; ++Item) {
1155 :
1156 9 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
1157 : CurrentModuleObject,
1158 : Item,
1159 : Alphas,
1160 : NumAlphas,
1161 : Numbers,
1162 : NumNumbers,
1163 : IOStatus,
1164 : lNumericBlanks,
1165 : lAlphaBlanks,
1166 : cAlphaFields,
1167 : cNumericFields);
1168 :
1169 9 : state.dataLowTempRadSys->ElecRadSysNumericFields(Item).FieldNames.allocate(NumNumbers);
1170 9 : state.dataLowTempRadSys->ElecRadSysNumericFields(Item).FieldNames = "";
1171 9 : state.dataLowTempRadSys->ElecRadSysNumericFields(Item).FieldNames = cNumericFields;
1172 :
1173 18 : GlobalNames::VerifyUniqueInterObjectName(
1174 18 : state, state.dataLowTempRadSys->LowTempRadUniqueNames, Alphas(1), CurrentModuleObject, cAlphaFields(1), ErrorsFound);
1175 9 : ++BaseNum;
1176 9 : state.dataLowTempRadSys->RadSysTypes(BaseNum).Name = Alphas(1);
1177 9 : state.dataLowTempRadSys->RadSysTypes(BaseNum).SystemType = LowTempRadiantSystem::SystemType::ElectricSystem;
1178 :
1179 : // General user input data
1180 9 : auto &thisElecSys(state.dataLowTempRadSys->ElecRadSys(Item));
1181 :
1182 9 : thisElecSys.Name = Alphas(1);
1183 :
1184 9 : thisElecSys.SchedName = Alphas(2);
1185 9 : if (lAlphaBlanks(2)) {
1186 0 : thisElecSys.SchedPtr = DataGlobalConstants::ScheduleAlwaysOn;
1187 : } else {
1188 9 : thisElecSys.SchedPtr = GetScheduleIndex(state, Alphas(2));
1189 9 : if (thisElecSys.SchedPtr == 0) {
1190 0 : ShowSevereError(state, cAlphaFields(2) + " not found for" + Alphas(1));
1191 0 : ShowContinueError(state, "Incorrect " + cAlphaFields(2) + " = " + Alphas(2));
1192 0 : ErrorsFound = true;
1193 : }
1194 : }
1195 :
1196 9 : thisElecSys.ZoneName = Alphas(3);
1197 9 : thisElecSys.ZonePtr = UtilityRoutines::FindItemInList(Alphas(3), Zone);
1198 9 : if (thisElecSys.ZonePtr == 0) {
1199 0 : ShowSevereError(state, format("{}Invalid {} = {}", RoutineName, cAlphaFields(3), Alphas(3)));
1200 0 : ShowContinueError(state, "Occurs in " + CurrentModuleObject + " = " + Alphas(1));
1201 0 : ErrorsFound = true;
1202 : }
1203 :
1204 9 : thisElecSys.SurfListName = Alphas(4);
1205 9 : SurfListNum = 0;
1206 9 : if (state.dataSurfLists->NumOfSurfaceLists > 0)
1207 0 : SurfListNum = UtilityRoutines::FindItemInList(thisElecSys.SurfListName, state.dataSurfLists->SurfList);
1208 9 : if (SurfListNum > 0) { // Found a valid surface list
1209 0 : thisElecSys.NumOfSurfaces = state.dataSurfLists->SurfList(SurfListNum).NumOfSurfaces;
1210 0 : thisElecSys.SurfacePtr.allocate(thisElecSys.NumOfSurfaces);
1211 0 : thisElecSys.SurfaceName.allocate(thisElecSys.NumOfSurfaces);
1212 0 : thisElecSys.SurfaceFrac.allocate(thisElecSys.NumOfSurfaces);
1213 0 : for (SurfNum = 1; SurfNum <= state.dataSurfLists->SurfList(SurfListNum).NumOfSurfaces; ++SurfNum) {
1214 0 : thisElecSys.SurfacePtr(SurfNum) = state.dataSurfLists->SurfList(SurfListNum).SurfPtr(SurfNum);
1215 0 : thisElecSys.SurfaceName(SurfNum) = state.dataSurfLists->SurfList(SurfListNum).SurfName(SurfNum);
1216 0 : thisElecSys.SurfaceFrac(SurfNum) = state.dataSurfLists->SurfList(SurfListNum).SurfFlowFrac(SurfNum);
1217 : }
1218 : } else { // User entered a single surface name rather than a surface list
1219 9 : thisElecSys.NumOfSurfaces = 1;
1220 9 : thisElecSys.SurfacePtr.allocate(thisElecSys.NumOfSurfaces);
1221 9 : thisElecSys.SurfaceName.allocate(thisElecSys.NumOfSurfaces);
1222 9 : thisElecSys.SurfaceFrac.allocate(thisElecSys.NumOfSurfaces);
1223 9 : thisElecSys.SurfaceName(1) = thisElecSys.SurfListName;
1224 9 : thisElecSys.SurfacePtr(1) = UtilityRoutines::FindItemInList(thisElecSys.SurfaceName(1), Surface);
1225 9 : thisElecSys.SurfaceFrac(1) = 1.0;
1226 : // Error checking for single surfaces
1227 9 : if (thisElecSys.SurfacePtr(1) == 0) {
1228 0 : ShowSevereError(state, format("{}Invalid {} = {}", RoutineName, cAlphaFields(4), Alphas(4)));
1229 0 : ShowContinueError(state, "Occurs in " + CurrentModuleObject + " = " + Alphas(1));
1230 0 : ErrorsFound = true;
1231 9 : } else if (state.dataSurface->SurfIsRadSurfOrVentSlabOrPool(thisElecSys.SurfacePtr(1))) {
1232 0 : ShowSevereError(state, std::string{RoutineName} + CurrentModuleObject + "=\"" + Alphas(1) + "\", Invalid Surface");
1233 0 : ShowContinueError(state, cAlphaFields(4) + "=\"" + Alphas(4) + "\" has been used in another radiant system or ventilated slab.");
1234 0 : ErrorsFound = true;
1235 : }
1236 9 : if (thisElecSys.SurfacePtr(1) != 0) {
1237 9 : state.dataSurface->SurfIsRadSurfOrVentSlabOrPool(state.dataLowTempRadSys->ElecRadSys(Item).SurfacePtr(1)) = true;
1238 : }
1239 : }
1240 :
1241 : // Error checking for zones and construction information
1242 9 : thisElecSys.errorCheckZonesAndConstructions(state, ErrorsFound);
1243 :
1244 : // Heating user input data
1245 : // Determine Low Temp Radiant heating design capacity sizing method
1246 9 : if (UtilityRoutines::SameString(Alphas(iHeatCAPMAlphaNum), "HeatingDesignCapacity")) {
1247 5 : thisElecSys.HeatingCapMethod = HeatingDesignCapacity;
1248 5 : if (!lNumericBlanks(iHeatDesignCapacityNumericNum)) {
1249 5 : thisElecSys.ScaledHeatingCapacity = Numbers(iHeatDesignCapacityNumericNum);
1250 5 : thisElecSys.MaxElecPower = thisElecSys.ScaledHeatingCapacity;
1251 5 : if (thisElecSys.ScaledHeatingCapacity < 0.0 && thisElecSys.ScaledHeatingCapacity != AutoSize) {
1252 0 : ShowSevereError(state, CurrentModuleObject + " = " + thisElecSys.Name);
1253 0 : ShowContinueError(
1254 : state,
1255 0 : format("Illegal {} = {:.7T}", cNumericFields(iHeatDesignCapacityNumericNum), Numbers(iHeatDesignCapacityNumericNum)));
1256 0 : ErrorsFound = true;
1257 : }
1258 : } else {
1259 0 : ShowSevereError(state, CurrentModuleObject + " = " + thisElecSys.Name);
1260 0 : ShowContinueError(state, "Input for " + cAlphaFields(iHeatCAPMAlphaNum) + " = " + Alphas(iHeatCAPMAlphaNum));
1261 0 : ShowContinueError(state, "Blank field not allowed for " + cNumericFields(iHeatDesignCapacityNumericNum));
1262 0 : ErrorsFound = true;
1263 : }
1264 4 : } else if (UtilityRoutines::SameString(Alphas(iHeatCAPMAlphaNum), "CapacityPerFloorArea")) {
1265 2 : thisElecSys.HeatingCapMethod = CapacityPerFloorArea;
1266 2 : if (!lNumericBlanks(iHeatCapacityPerFloorAreaNumericNum)) {
1267 2 : thisElecSys.ScaledHeatingCapacity = Numbers(iHeatCapacityPerFloorAreaNumericNum);
1268 2 : thisElecSys.MaxElecPower = thisElecSys.ScaledHeatingCapacity;
1269 2 : if (thisElecSys.ScaledHeatingCapacity <= 0.0) {
1270 0 : ShowSevereError(state, CurrentModuleObject + " = " + thisElecSys.Name);
1271 0 : ShowContinueError(state, "Input for " + cAlphaFields(iHeatCAPMAlphaNum) + " = " + Alphas(iHeatCAPMAlphaNum));
1272 0 : ShowContinueError(state,
1273 0 : format("Illegal {} = {:.7T}",
1274 : cNumericFields(iHeatCapacityPerFloorAreaNumericNum),
1275 0 : Numbers(iHeatCapacityPerFloorAreaNumericNum)));
1276 0 : ErrorsFound = true;
1277 2 : } else if (thisElecSys.ScaledHeatingCapacity == AutoSize) {
1278 0 : ShowSevereError(state, CurrentModuleObject + " = " + thisElecSys.Name);
1279 0 : ShowContinueError(state, "Input for " + cAlphaFields(iHeatCAPMAlphaNum) + " = " + Alphas(iHeatCAPMAlphaNum));
1280 0 : ShowContinueError(state, "Illegal " + cNumericFields(iHeatCapacityPerFloorAreaNumericNum) + " = Autosize");
1281 0 : ErrorsFound = true;
1282 : }
1283 : } else {
1284 0 : ShowSevereError(state, CurrentModuleObject + " = " + thisElecSys.Name);
1285 0 : ShowContinueError(state, "Input for " + cAlphaFields(iHeatCAPMAlphaNum) + " = " + Alphas(iHeatCAPMAlphaNum));
1286 0 : ShowContinueError(state, "Blank field not allowed for " + cNumericFields(iHeatCapacityPerFloorAreaNumericNum));
1287 0 : ErrorsFound = true;
1288 : }
1289 2 : } else if (UtilityRoutines::SameString(Alphas(iHeatCAPMAlphaNum), "FractionOfAutosizedHeatingCapacity")) {
1290 2 : thisElecSys.HeatingCapMethod = FractionOfAutosizedHeatingCapacity;
1291 2 : if (!lNumericBlanks(iHeatFracOfAutosizedCapacityNumericNum)) {
1292 2 : thisElecSys.ScaledHeatingCapacity = Numbers(iHeatFracOfAutosizedCapacityNumericNum);
1293 2 : thisElecSys.MaxElecPower = thisElecSys.ScaledHeatingCapacity;
1294 2 : if (thisElecSys.ScaledHeatingCapacity < 0.0) {
1295 0 : ShowSevereError(state, CurrentModuleObject + " = " + thisElecSys.Name);
1296 0 : ShowContinueError(state,
1297 0 : format("Illegal {} = {:.7T}",
1298 : cNumericFields(iHeatFracOfAutosizedCapacityNumericNum),
1299 0 : Numbers(iHeatFracOfAutosizedCapacityNumericNum)));
1300 0 : ErrorsFound = true;
1301 : }
1302 : } else {
1303 0 : ShowSevereError(state, CurrentModuleObject + " = " + thisElecSys.Name);
1304 0 : ShowContinueError(state, "Input for " + cAlphaFields(iHeatCAPMAlphaNum) + " = " + Alphas(iHeatCAPMAlphaNum));
1305 0 : ShowContinueError(state, "Blank field not allowed for " + cNumericFields(iHeatFracOfAutosizedCapacityNumericNum));
1306 0 : ErrorsFound = true;
1307 : }
1308 : } else {
1309 0 : ShowSevereError(state, CurrentModuleObject + " = " + thisElecSys.Name);
1310 0 : ShowContinueError(state, "Illegal " + cAlphaFields(iHeatCAPMAlphaNum) + " = " + Alphas(iHeatCAPMAlphaNum));
1311 0 : ErrorsFound = true;
1312 : }
1313 :
1314 : // Process the temperature control type
1315 9 : thisElecSys.controlType =
1316 9 : thisElecSys.processRadiantSystemControlInput(state, Alphas(6), cAlphaFields(6), LowTempRadiantSystem::SystemType::ElectricSystem);
1317 :
1318 : // Process the setpoint type
1319 9 : thisElecSys.SetpointType = thisElecSys.processRadiantSystemSetpointInput(state, Alphas(7), cAlphaFields(7));
1320 :
1321 9 : thisElecSys.ThrottlRange = Numbers(4);
1322 :
1323 9 : thisElecSys.SetptSched = Alphas(8);
1324 9 : thisElecSys.SetptSchedPtr = GetScheduleIndex(state, Alphas(8));
1325 9 : if (thisElecSys.SetptSchedPtr == 0) {
1326 0 : if (lAlphaBlanks(8)) {
1327 0 : ShowSevereError(state, cAlphaFields(8) + " must be input, missing for " + Alphas(1));
1328 : } else {
1329 0 : ShowSevereError(state, cAlphaFields(8) + " not found for " + Alphas(8));
1330 0 : ShowContinueError(state, "Incorrect " + cAlphaFields(8) + " = " + Alphas(8));
1331 : }
1332 0 : ErrorsFound = true;
1333 : }
1334 : }
1335 :
1336 : // Check to see if any surface is included in more than one radiant system. This is not allowed
1337 : // and thus indicative that there is an error in the input file. This is to make sure that two
1338 : // different radiant systems are competing for the same surface. Allowing this to happen would
1339 : // result in lost energy somewhere and the situation really is not physically possible anyway.
1340 29 : AssignedAsRadiantSurface.dimension(state.dataSurface->TotSurfaces, false);
1341 :
1342 75 : for (Item = 1; Item <= state.dataLowTempRadSys->NumOfHydrLowTempRadSys; ++Item) {
1343 104 : for (SurfNum = 1; SurfNum <= state.dataLowTempRadSys->HydrRadSys(Item).NumOfSurfaces; ++SurfNum) {
1344 58 : CheckSurfNum = state.dataLowTempRadSys->HydrRadSys(Item).SurfacePtr(SurfNum);
1345 58 : if (CheckSurfNum == 0) continue;
1346 58 : if (AssignedAsRadiantSurface(CheckSurfNum)) {
1347 0 : ShowSevereError(state,
1348 0 : "Surface " + Surface(CheckSurfNum).Name + " is referenced by more than one radiant system--this is not allowed");
1349 0 : ErrorsFound = true;
1350 : } else {
1351 58 : AssignedAsRadiantSurface(CheckSurfNum) = true;
1352 : }
1353 : // Also check the other side of interzone partitions
1354 58 : if ((Surface(CheckSurfNum).ExtBoundCond > 0) && (Surface(CheckSurfNum).ExtBoundCond != CheckSurfNum)) {
1355 1 : if (AssignedAsRadiantSurface(Surface(CheckSurfNum).ExtBoundCond)) {
1356 0 : ShowSevereError(state,
1357 0 : "Interzone surface " + Surface(Surface(CheckSurfNum).ExtBoundCond).Name +
1358 : " is referenced by more than one radiant system--this is not allowed");
1359 0 : ErrorsFound = true;
1360 : } else {
1361 1 : AssignedAsRadiantSurface(Surface(CheckSurfNum).ExtBoundCond) = true;
1362 : }
1363 : }
1364 : }
1365 : }
1366 :
1367 56 : for (Item = 1; Item <= state.dataLowTempRadSys->NumOfCFloLowTempRadSys; ++Item) {
1368 54 : for (SurfNum = 1; SurfNum <= state.dataLowTempRadSys->CFloRadSys(Item).NumOfSurfaces; ++SurfNum) {
1369 27 : CheckSurfNum = state.dataLowTempRadSys->CFloRadSys(Item).SurfacePtr(SurfNum);
1370 27 : if (CheckSurfNum == 0) continue;
1371 27 : if (AssignedAsRadiantSurface(CheckSurfNum)) {
1372 0 : ShowSevereError(state,
1373 0 : "Surface " + Surface(CheckSurfNum).Name + " is referenced by more than one radiant system--this is not allowed");
1374 0 : ErrorsFound = true;
1375 : } else {
1376 27 : AssignedAsRadiantSurface(CheckSurfNum) = true;
1377 : }
1378 : // Also check the other side of interzone partitions
1379 27 : if ((Surface(CheckSurfNum).ExtBoundCond > 0) && (Surface(CheckSurfNum).ExtBoundCond != CheckSurfNum)) {
1380 0 : if (AssignedAsRadiantSurface(Surface(CheckSurfNum).ExtBoundCond)) {
1381 0 : ShowSevereError(state,
1382 0 : "Interzone surface " + Surface(Surface(CheckSurfNum).ExtBoundCond).Name +
1383 : " is referenced by more than one radiant system--this is not allowed");
1384 0 : ErrorsFound = true;
1385 : } else {
1386 0 : AssignedAsRadiantSurface(Surface(CheckSurfNum).ExtBoundCond) = true;
1387 : }
1388 : }
1389 : }
1390 : }
1391 :
1392 38 : for (Item = 1; Item <= state.dataLowTempRadSys->NumOfElecLowTempRadSys; ++Item) {
1393 18 : for (SurfNum = 1; SurfNum <= state.dataLowTempRadSys->ElecRadSys(Item).NumOfSurfaces; ++SurfNum) {
1394 9 : CheckSurfNum = state.dataLowTempRadSys->ElecRadSys(Item).SurfacePtr(SurfNum);
1395 9 : if (CheckSurfNum == 0) continue;
1396 9 : if (AssignedAsRadiantSurface(CheckSurfNum)) {
1397 0 : ShowSevereError(state,
1398 0 : "Surface " + Surface(CheckSurfNum).Name + " is referenced by more than one radiant system--this is not allowed");
1399 0 : ErrorsFound = true;
1400 : } else {
1401 9 : AssignedAsRadiantSurface(CheckSurfNum) = true;
1402 : }
1403 : // Also check the other side of interzone partitions
1404 9 : if ((Surface(CheckSurfNum).ExtBoundCond > 0) && (Surface(CheckSurfNum).ExtBoundCond != CheckSurfNum)) {
1405 0 : if (AssignedAsRadiantSurface(Surface(CheckSurfNum).ExtBoundCond)) {
1406 0 : ShowSevereError(state,
1407 0 : "Interzone surface " + Surface(Surface(CheckSurfNum).ExtBoundCond).Name +
1408 : " is referenced by more than one radiant system--this is not allowed");
1409 0 : ErrorsFound = true;
1410 : } else {
1411 0 : AssignedAsRadiantSurface(Surface(CheckSurfNum).ExtBoundCond) = true;
1412 : }
1413 : }
1414 : }
1415 : }
1416 :
1417 29 : AssignedAsRadiantSurface.deallocate();
1418 29 : Alphas.deallocate();
1419 29 : Numbers.deallocate();
1420 29 : cAlphaFields.deallocate();
1421 29 : cNumericFields.deallocate();
1422 29 : lAlphaBlanks.deallocate();
1423 29 : lNumericBlanks.deallocate();
1424 :
1425 29 : if (ErrorsFound) {
1426 0 : ShowFatalError(state, format("{}Errors found in input. Preceding conditions cause termination.", RoutineName));
1427 : }
1428 :
1429 : // Set up the output variables for low temperature radiant systems
1430 : // ZoneHVAC:LowTemperatureRadiant:VariableFlow (HydrRadSys)
1431 75 : for (Item = 1; Item <= state.dataLowTempRadSys->NumOfHydrLowTempRadSys; ++Item) {
1432 :
1433 46 : auto &thisHydrSys(state.dataLowTempRadSys->HydrRadSys(Item));
1434 :
1435 92 : SetupOutputVariable(state,
1436 : "Zone Radiant HVAC Heating Rate",
1437 : OutputProcessor::Unit::W,
1438 : thisHydrSys.HeatPower,
1439 : OutputProcessor::SOVTimeStepType::System,
1440 : OutputProcessor::SOVStoreType::Average,
1441 46 : thisHydrSys.Name);
1442 92 : SetupOutputVariable(state,
1443 : "Zone Radiant HVAC Heating Energy",
1444 : OutputProcessor::Unit::J,
1445 : thisHydrSys.HeatEnergy,
1446 : OutputProcessor::SOVTimeStepType::System,
1447 : OutputProcessor::SOVStoreType::Summed,
1448 : thisHydrSys.Name,
1449 : _,
1450 : "ENERGYTRANSFER",
1451 : "HEATINGCOILS",
1452 : _,
1453 46 : "System");
1454 92 : SetupOutputVariable(state,
1455 : "Zone Radiant HVAC Heating Fluid Energy",
1456 : OutputProcessor::Unit::J,
1457 : thisHydrSys.HeatEnergy,
1458 : OutputProcessor::SOVTimeStepType::System,
1459 : OutputProcessor::SOVStoreType::Summed,
1460 : thisHydrSys.Name,
1461 : _,
1462 : "PLANTLOOPHEATINGDEMAND",
1463 : "HEATINGCOILS",
1464 : _,
1465 46 : "System");
1466 92 : SetupOutputVariable(state,
1467 : "Zone Radiant HVAC Cooling Rate",
1468 : OutputProcessor::Unit::W,
1469 : thisHydrSys.CoolPower,
1470 : OutputProcessor::SOVTimeStepType::System,
1471 : OutputProcessor::SOVStoreType::Average,
1472 46 : thisHydrSys.Name);
1473 :
1474 92 : SetupOutputVariable(state,
1475 : "Zone Radiant HVAC Cooling Energy",
1476 : OutputProcessor::Unit::J,
1477 : thisHydrSys.CoolEnergy,
1478 : OutputProcessor::SOVTimeStepType::System,
1479 : OutputProcessor::SOVStoreType::Summed,
1480 : thisHydrSys.Name,
1481 : _,
1482 : "ENERGYTRANSFER",
1483 : "COOLINGCOILS",
1484 : _,
1485 46 : "System");
1486 92 : SetupOutputVariable(state,
1487 : "Zone Radiant HVAC Cooling Fluid Energy",
1488 : OutputProcessor::Unit::J,
1489 : thisHydrSys.CoolEnergy,
1490 : OutputProcessor::SOVTimeStepType::System,
1491 : OutputProcessor::SOVStoreType::Summed,
1492 : thisHydrSys.Name,
1493 : _,
1494 : "PLANTLOOPCOOLINGDEMAND",
1495 : "COOLINGCOILS",
1496 : _,
1497 46 : "System");
1498 92 : SetupOutputVariable(state,
1499 : "Zone Radiant HVAC Mass Flow Rate",
1500 : OutputProcessor::Unit::kg_s,
1501 : thisHydrSys.WaterMassFlowRate,
1502 : OutputProcessor::SOVTimeStepType::System,
1503 : OutputProcessor::SOVStoreType::Average,
1504 46 : thisHydrSys.Name);
1505 92 : SetupOutputVariable(state,
1506 : "Zone Radiant HVAC Inlet Temperature",
1507 : OutputProcessor::Unit::C,
1508 : thisHydrSys.WaterInletTemp,
1509 : OutputProcessor::SOVTimeStepType::System,
1510 : OutputProcessor::SOVStoreType::Average,
1511 46 : thisHydrSys.Name);
1512 92 : SetupOutputVariable(state,
1513 : "Zone Radiant HVAC Outlet Temperature",
1514 : OutputProcessor::Unit::C,
1515 : thisHydrSys.WaterOutletTemp,
1516 : OutputProcessor::SOVTimeStepType::System,
1517 : OutputProcessor::SOVStoreType::Average,
1518 46 : thisHydrSys.Name);
1519 92 : SetupOutputVariable(state,
1520 : "Zone Radiant HVAC Moisture Condensation Time",
1521 : OutputProcessor::Unit::s,
1522 : thisHydrSys.CondCausedTimeOff,
1523 : OutputProcessor::SOVTimeStepType::System,
1524 : OutputProcessor::SOVStoreType::Summed,
1525 46 : thisHydrSys.Name);
1526 92 : SetupOutputVariable(state,
1527 : "Zone Radiant HVAC Operation Mode",
1528 : OutputProcessor::Unit::None,
1529 : thisHydrSys.OperatingMode,
1530 : OutputProcessor::SOVTimeStepType::System,
1531 : OutputProcessor::SOVStoreType::Average,
1532 46 : thisHydrSys.Name);
1533 46 : if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
1534 0 : SetupEMSInternalVariable(state,
1535 : "Hydronic Low Temp Radiant Design Water Volume Flow Rate for Heating",
1536 : thisHydrSys.Name,
1537 : "[m3/s]",
1538 0 : thisHydrSys.WaterVolFlowMaxHeat);
1539 0 : SetupEMSInternalVariable(state,
1540 : "Hydronic Low Temp Radiant Design Water Volume Flow Rate for Cooling",
1541 : thisHydrSys.Name,
1542 : "[m3/s]",
1543 0 : thisHydrSys.WaterVolFlowMaxCool);
1544 0 : SetupEMSActuator(state,
1545 : "Hydronic Low Temp Radiant",
1546 : thisHydrSys.Name,
1547 : "Water Mass Flow Rate",
1548 : "[kg/s]",
1549 : thisHydrSys.EMSOverrideOnWaterMdot,
1550 0 : thisHydrSys.EMSWaterMdotOverrideValue);
1551 : }
1552 : }
1553 :
1554 : // Set up the output variables for low temperature radiant systems
1555 : // ZoneHVAC:LowTemperatureRadiant:ConstantFlow (CFloRadSys)
1556 56 : for (Item = 1; Item <= state.dataLowTempRadSys->NumOfCFloLowTempRadSys; ++Item) {
1557 :
1558 27 : auto &thisCFloSys(state.dataLowTempRadSys->CFloRadSys(Item));
1559 :
1560 54 : SetupOutputVariable(state,
1561 : "Zone Radiant HVAC Heating Rate",
1562 : OutputProcessor::Unit::W,
1563 : thisCFloSys.HeatPower,
1564 : OutputProcessor::SOVTimeStepType::System,
1565 : OutputProcessor::SOVStoreType::Average,
1566 27 : thisCFloSys.Name);
1567 54 : SetupOutputVariable(state,
1568 : "Zone Radiant HVAC Heating Energy",
1569 : OutputProcessor::Unit::J,
1570 : thisCFloSys.HeatEnergy,
1571 : OutputProcessor::SOVTimeStepType::System,
1572 : OutputProcessor::SOVStoreType::Summed,
1573 : thisCFloSys.Name,
1574 : _,
1575 : "ENERGYTRANSFER",
1576 : "HEATINGCOILS",
1577 : _,
1578 27 : "System");
1579 54 : SetupOutputVariable(state,
1580 : "Zone Radiant HVAC Heating Fluid Heat Transfer Energy",
1581 : OutputProcessor::Unit::J,
1582 : thisCFloSys.HeatEnergy,
1583 : OutputProcessor::SOVTimeStepType::System,
1584 : OutputProcessor::SOVStoreType::Summed,
1585 : thisCFloSys.Name,
1586 : _,
1587 : "PLANTLOOPHEATINGDEMAND",
1588 : "HEATINGCOILS",
1589 : _,
1590 27 : "System");
1591 54 : SetupOutputVariable(state,
1592 : "Zone Radiant HVAC Cooling Rate",
1593 : OutputProcessor::Unit::W,
1594 : thisCFloSys.CoolPower,
1595 : OutputProcessor::SOVTimeStepType::System,
1596 : OutputProcessor::SOVStoreType::Average,
1597 27 : thisCFloSys.Name);
1598 54 : SetupOutputVariable(state,
1599 : "Zone Radiant HVAC Cooling Energy",
1600 : OutputProcessor::Unit::J,
1601 : thisCFloSys.CoolEnergy,
1602 : OutputProcessor::SOVTimeStepType::System,
1603 : OutputProcessor::SOVStoreType::Summed,
1604 : thisCFloSys.Name,
1605 : _,
1606 : "ENERGYTRANSFER",
1607 : "COOLINGCOILS",
1608 : _,
1609 27 : "System");
1610 54 : SetupOutputVariable(state,
1611 : "Zone Radiant HVAC Cooling Fluid Heat Transfer Energy",
1612 : OutputProcessor::Unit::J,
1613 : thisCFloSys.CoolEnergy,
1614 : OutputProcessor::SOVTimeStepType::System,
1615 : OutputProcessor::SOVStoreType::Summed,
1616 : thisCFloSys.Name,
1617 : _,
1618 : "PLANTLOOPCOOLINGDEMAND",
1619 : "COOLINGCOILS",
1620 : _,
1621 27 : "System");
1622 54 : SetupOutputVariable(state,
1623 : "Zone Radiant HVAC Mass Flow Rate",
1624 : OutputProcessor::Unit::kg_s,
1625 : thisCFloSys.WaterMassFlowRate,
1626 : OutputProcessor::SOVTimeStepType::System,
1627 : OutputProcessor::SOVStoreType::Average,
1628 27 : thisCFloSys.Name);
1629 54 : SetupOutputVariable(state,
1630 : "Zone Radiant HVAC Injection Mass Flow Rate",
1631 : OutputProcessor::Unit::kg_s,
1632 : thisCFloSys.WaterInjectionRate,
1633 : OutputProcessor::SOVTimeStepType::System,
1634 : OutputProcessor::SOVStoreType::Average,
1635 27 : thisCFloSys.Name);
1636 54 : SetupOutputVariable(state,
1637 : "Zone Radiant HVAC Recirculation Mass Flow Rate",
1638 : OutputProcessor::Unit::kg_s,
1639 : thisCFloSys.WaterRecircRate,
1640 : OutputProcessor::SOVTimeStepType::System,
1641 : OutputProcessor::SOVStoreType::Average,
1642 27 : thisCFloSys.Name);
1643 54 : SetupOutputVariable(state,
1644 : "Zone Radiant HVAC Inlet Temperature",
1645 : OutputProcessor::Unit::C,
1646 : thisCFloSys.WaterInletTemp,
1647 : OutputProcessor::SOVTimeStepType::System,
1648 : OutputProcessor::SOVStoreType::Average,
1649 27 : thisCFloSys.Name);
1650 54 : SetupOutputVariable(state,
1651 : "Zone Radiant HVAC Outlet Temperature",
1652 : OutputProcessor::Unit::C,
1653 : thisCFloSys.WaterOutletTemp,
1654 : OutputProcessor::SOVTimeStepType::System,
1655 : OutputProcessor::SOVStoreType::Average,
1656 27 : thisCFloSys.Name);
1657 54 : SetupOutputVariable(state,
1658 : "Zone Radiant HVAC Pump Inlet Temperature",
1659 : OutputProcessor::Unit::C,
1660 : thisCFloSys.PumpInletTemp,
1661 : OutputProcessor::SOVTimeStepType::System,
1662 : OutputProcessor::SOVStoreType::Average,
1663 27 : thisCFloSys.Name);
1664 54 : SetupOutputVariable(state,
1665 : "Zone Radiant HVAC Pump Electricity Rate",
1666 : OutputProcessor::Unit::W,
1667 : thisCFloSys.PumpPower,
1668 : OutputProcessor::SOVTimeStepType::System,
1669 : OutputProcessor::SOVStoreType::Average,
1670 27 : thisCFloSys.Name);
1671 54 : SetupOutputVariable(state,
1672 : "Zone Radiant HVAC Pump Electricity Energy",
1673 : OutputProcessor::Unit::J,
1674 : thisCFloSys.PumpEnergy,
1675 : OutputProcessor::SOVTimeStepType::System,
1676 : OutputProcessor::SOVStoreType::Summed,
1677 : thisCFloSys.Name,
1678 : _,
1679 : "Electricity",
1680 : "Pumps",
1681 : _,
1682 27 : "Plant");
1683 54 : SetupOutputVariable(state,
1684 : "Zone Radiant HVAC Pump Mass Flow Rate",
1685 : OutputProcessor::Unit::kg_s,
1686 : thisCFloSys.PumpMassFlowRate,
1687 : OutputProcessor::SOVTimeStepType::System,
1688 : OutputProcessor::SOVStoreType::Average,
1689 27 : thisCFloSys.Name);
1690 54 : SetupOutputVariable(state,
1691 : "Zone Radiant HVAC Pump Fluid Heat Gain Rate",
1692 : OutputProcessor::Unit::W,
1693 : thisCFloSys.PumpHeattoFluid,
1694 : OutputProcessor::SOVTimeStepType::System,
1695 : OutputProcessor::SOVStoreType::Average,
1696 27 : thisCFloSys.Name);
1697 54 : SetupOutputVariable(state,
1698 : "Zone Radiant HVAC Pump Fluid Heat Gain Energy",
1699 : OutputProcessor::Unit::J,
1700 : thisCFloSys.PumpHeattoFluidEnergy,
1701 : OutputProcessor::SOVTimeStepType::System,
1702 : OutputProcessor::SOVStoreType::Summed,
1703 27 : thisCFloSys.Name);
1704 54 : SetupOutputVariable(state,
1705 : "Zone Radiant HVAC Moisture Condensation Time",
1706 : OutputProcessor::Unit::s,
1707 : thisCFloSys.CondCausedTimeOff,
1708 : OutputProcessor::SOVTimeStepType::System,
1709 : OutputProcessor::SOVStoreType::Summed,
1710 27 : thisCFloSys.Name);
1711 54 : SetupOutputVariable(state,
1712 : "Zone Radiant HVAC Operation Mode",
1713 : OutputProcessor::Unit::None,
1714 : thisCFloSys.OperatingMode,
1715 : OutputProcessor::SOVTimeStepType::System,
1716 : OutputProcessor::SOVStoreType::Average,
1717 27 : thisCFloSys.Name);
1718 27 : if (state.dataLowTempRadSys->anyRadiantSystemUsingRunningMeanAverage) {
1719 6 : SetupOutputVariable(state,
1720 : "Zone Radiant HVAC Running Mean Outdoor Dry-Bulb Temperature",
1721 : OutputProcessor::Unit::C,
1722 : thisCFloSys.todayRunningMeanOutdoorDryBulbTemperature,
1723 : OutputProcessor::SOVTimeStepType::System,
1724 : OutputProcessor::SOVStoreType::Average,
1725 3 : thisCFloSys.Name);
1726 6 : SetupOutputVariable(state,
1727 : "Zone Radiant HVAC Previous Day Running Mean Outdoor Dry-Bulb Temperature",
1728 : OutputProcessor::Unit::C,
1729 : thisCFloSys.yesterdayRunningMeanOutdoorDryBulbTemperature,
1730 : OutputProcessor::SOVTimeStepType::System,
1731 : OutputProcessor::SOVStoreType::Average,
1732 3 : thisCFloSys.Name);
1733 6 : SetupOutputVariable(state,
1734 : "Zone Radiant HVAC Previous Day Average Outdoor Dry-Bulb Temperature",
1735 : OutputProcessor::Unit::C,
1736 : thisCFloSys.yesterdayAverageOutdoorDryBulbTemperature,
1737 : OutputProcessor::SOVTimeStepType::System,
1738 : OutputProcessor::SOVStoreType::Average,
1739 3 : thisCFloSys.Name);
1740 : }
1741 27 : if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
1742 0 : SetupEMSInternalVariable(
1743 0 : state, "Constant Flow Low Temp Radiant Design Water Mass Flow Rate", thisCFloSys.Name, "[m3/s]", thisCFloSys.WaterVolFlowMax);
1744 0 : SetupEMSActuator(state,
1745 : "Constant Flow Low Temp Radiant",
1746 : thisCFloSys.Name,
1747 : "Water Mass Flow Rate",
1748 : "[kg/s]",
1749 : thisCFloSys.EMSOverrideOnWaterMdot,
1750 0 : thisCFloSys.EMSWaterMdotOverrideValue);
1751 : }
1752 : }
1753 :
1754 38 : for (Item = 1; Item <= state.dataLowTempRadSys->NumOfElecLowTempRadSys; ++Item) {
1755 : // Set up the output variables for low temperature radiant systems
1756 : // ZoneHVAC:LowTemperatureRadiant:Electric (ElecRadSys)
1757 :
1758 9 : auto &thisElecSys(state.dataLowTempRadSys->ElecRadSys(Item));
1759 :
1760 18 : SetupOutputVariable(state,
1761 : "Zone Radiant HVAC Electricity Rate",
1762 : OutputProcessor::Unit::W,
1763 : thisElecSys.ElecPower,
1764 : OutputProcessor::SOVTimeStepType::System,
1765 : OutputProcessor::SOVStoreType::Average,
1766 9 : thisElecSys.Name);
1767 18 : SetupOutputVariable(state,
1768 : "Zone Radiant HVAC Electricity Energy",
1769 : OutputProcessor::Unit::J,
1770 : thisElecSys.ElecEnergy,
1771 : OutputProcessor::SOVTimeStepType::System,
1772 : OutputProcessor::SOVStoreType::Summed,
1773 : thisElecSys.Name,
1774 : _,
1775 : "ELECTRICITY",
1776 : "Heating",
1777 : _,
1778 9 : "System");
1779 18 : SetupOutputVariable(state,
1780 : "Zone Radiant HVAC Heating Rate",
1781 : OutputProcessor::Unit::W,
1782 : thisElecSys.HeatPower,
1783 : OutputProcessor::SOVTimeStepType::System,
1784 : OutputProcessor::SOVStoreType::Average,
1785 9 : thisElecSys.Name);
1786 18 : SetupOutputVariable(state,
1787 : "Zone Radiant HVAC Heating Energy",
1788 : OutputProcessor::Unit::J,
1789 : thisElecSys.HeatEnergy,
1790 : OutputProcessor::SOVTimeStepType::System,
1791 : OutputProcessor::SOVStoreType::Summed,
1792 : thisElecSys.Name,
1793 : _,
1794 : "ENERGYTRANSFER",
1795 : "HEATINGCOILS",
1796 : _,
1797 9 : "System");
1798 : }
1799 29 : }
1800 :
1801 54 : FluidToSlabHeatTransferTypes HydronicSystemBaseData::getFluidToSlabHeatTransferInput(EnergyPlusData &state, std::string const &userInput)
1802 : {
1803 54 : if (UtilityRoutines::SameString(userInput, "ConvectionOnly")) {
1804 48 : return FluidToSlabHeatTransferTypes::ConvectionOnly;
1805 6 : } else if (UtilityRoutines::SameString(userInput, "ISOStandard")) {
1806 6 : return FluidToSlabHeatTransferTypes::ISOStandard;
1807 : } else {
1808 0 : ShowWarningError(state, "Invalid Fluid to Slab Heat Transfer Model Input = " + userInput);
1809 0 : ShowContinueError(state, "Occurs in Low Temperature Radiant System = " + this->Name);
1810 0 : ShowContinueError(state, "Heat transfer model reset to convection only for this Low Temperature Radiant System.");
1811 0 : return FluidToSlabHeatTransferTypes::ConvectionOnly;
1812 : }
1813 : }
1814 :
1815 63 : LowTempRadiantControlTypes RadiantSystemBaseData::processRadiantSystemControlInput(EnergyPlusData &state,
1816 : std::string const &controlInput,
1817 : std::string const &controlInputField,
1818 : LowTempRadiantSystem::SystemType const typeOfRadiantSystem)
1819 : {
1820 63 : if (UtilityRoutines::SameString(controlInput, "MeanAirTemperature")) {
1821 41 : return LowTempRadiantControlTypes::MATControl;
1822 22 : } else if (UtilityRoutines::SameString(controlInput, "MeanRadiantTemperature")) {
1823 4 : return LowTempRadiantControlTypes::MRTControl;
1824 18 : } else if (UtilityRoutines::SameString(controlInput, "OperativeTemperature")) {
1825 4 : return LowTempRadiantControlTypes::OperativeControl;
1826 14 : } else if (UtilityRoutines::SameString(controlInput, "OutdoorDryBulbTemperature")) {
1827 3 : return LowTempRadiantControlTypes::ODBControl;
1828 11 : } else if (UtilityRoutines::SameString(controlInput, "OutdoorWetBulbTemperature")) {
1829 2 : return LowTempRadiantControlTypes::OWBControl;
1830 9 : } else if (UtilityRoutines::SameString(controlInput, "SurfaceFaceTemperature")) {
1831 3 : return LowTempRadiantControlTypes::SurfFaceTempControl;
1832 6 : } else if (UtilityRoutines::SameString(controlInput, "SurfaceInteriorTemperature")) {
1833 3 : return LowTempRadiantControlTypes::SurfIntTempControl;
1834 3 : } else if (UtilityRoutines::SameString(controlInput, "RunningMeanOutdoorDryBulbTemperature") &&
1835 : typeOfRadiantSystem == LowTempRadiantSystem::SystemType::ConstantFlowSystem) {
1836 3 : state.dataLowTempRadSys->anyRadiantSystemUsingRunningMeanAverage = true;
1837 3 : return LowTempRadiantControlTypes::RunningMeanODBControl;
1838 : } else {
1839 0 : ShowWarningError(state, "Invalid " + controlInputField + " = " + controlInput);
1840 0 : ShowContinueError(state, "Occurs in Low Temperature Radiant System = " + this->Name);
1841 0 : ShowContinueError(state, "Control reset to MAT control for this Low Temperature Radiant System.");
1842 0 : return LowTempRadiantControlTypes::MATControl;
1843 : }
1844 : }
1845 :
1846 40 : LowTempRadiantSetpointTypes RadiantSystemBaseData::processRadiantSystemSetpointInput(EnergyPlusData &state,
1847 : std::string const &controlInput,
1848 : std::string const &controlInputField)
1849 : {
1850 40 : if (UtilityRoutines::SameString(controlInput, "HalfFlowPower")) {
1851 33 : return LowTempRadiantSetpointTypes::HalfFlowPower;
1852 7 : } else if (UtilityRoutines::SameString(controlInput, "ZeroFlowPower")) {
1853 7 : return LowTempRadiantSetpointTypes::ZeroFlowPower;
1854 : } else {
1855 0 : ShowWarningError(state, "Invalid " + controlInputField + " = " + controlInput);
1856 0 : ShowContinueError(state, "Occurs in Low Temperature Radiant System = " + this->Name);
1857 0 : ShowContinueError(state, "Setpoint type reset to HalfFlowPower for this Low Temperature Radiant System.");
1858 0 : return LowTempRadiantSetpointTypes::HalfFlowPower;
1859 : }
1860 : }
1861 :
1862 82 : void RadiantSystemBaseData::errorCheckZonesAndConstructions(EnergyPlusData &state, bool &errorsFound)
1863 : {
1864 82 : auto &Zone(state.dataHeatBal->Zone);
1865 82 : auto &Surface(state.dataSurface->Surface);
1866 :
1867 82 : Real64 zoneMultipliers = 0.0;
1868 82 : Real64 zoneMultipliersSurface = 0.0;
1869 82 : Real64 zoneMultiplersTolerance = 0.001;
1870 176 : for (int SurfNum = 1; SurfNum <= this->NumOfSurfaces; ++SurfNum) {
1871 :
1872 94 : if (this->SurfacePtr(SurfNum) == 0) continue; // invalid surface -- detected earlier
1873 :
1874 94 : if (state.dataGlobal->DisplayExtraWarnings) {
1875 : // check zone numbers--ok if they are not the same
1876 : // group warning issued earlier, show detailed warning here
1877 0 : if (Surface(this->SurfacePtr(SurfNum)).Zone != this->ZonePtr) {
1878 0 : ShowWarningError(state,
1879 : "A surface referenced in a Low Temperature Radiant System is not in same zone as the radiant system itself");
1880 0 : ShowContinueError(state, "Surface = " + Surface(this->SurfacePtr(SurfNum)).Name);
1881 0 : ShowContinueError(state,
1882 0 : "Surface in Zone = " + Zone(Surface(this->SurfacePtr(SurfNum)).Zone).Name +
1883 0 : ". Radiant System in Zone = " + this->ZoneName);
1884 0 : ShowContinueError(state, "Occurs in Low Temperature Radiant System = " + this->Name);
1885 0 : ShowContinueError(state, "If this is intentionally a radiant system with surfaces in more than one thermal zone,");
1886 0 : ShowContinueError(state, "then ignore this warning message. Otherwise, check the surfaces in this radiant system.");
1887 : }
1888 : }
1889 :
1890 : // check zone multipliers--these must be the same
1891 94 : if (SurfNum == 1) zoneMultipliers = double(Zone(this->ZonePtr).Multiplier) * double(Zone(this->ZonePtr).ListMultiplier);
1892 188 : zoneMultipliersSurface = double(Zone(Surface(this->SurfacePtr(SurfNum)).Zone).Multiplier) *
1893 94 : double(Zone(Surface(this->SurfacePtr(SurfNum)).Zone).ListMultiplier);
1894 94 : if (std::abs(zoneMultipliers - zoneMultipliersSurface) > zoneMultiplersTolerance) {
1895 0 : ShowSevereError(state, "The zone multipliers are not the same for all surfaces contained in this radiant system");
1896 0 : ShowContinueError(state, "This is not allowed and must be fixed for the simulation to run.");
1897 0 : ShowContinueError(state, "Occurs in Low Temperature Radiant System = " + this->Name);
1898 0 : errorsFound = true;
1899 : }
1900 :
1901 : // make sure that this construction is defined with a source/sink--this must be the case or it can't serve as a radiant system surface
1902 94 : if (!state.dataConstruction->Construct(Surface(this->SurfacePtr(SurfNum)).Construction).SourceSinkPresent) {
1903 0 : ShowSevereError(state, "Construction referenced in Radiant System Surface does not have a source/sink present");
1904 0 : ShowContinueError(state,
1905 0 : "Surface name= " + Surface(this->SurfacePtr(SurfNum)).Name + " Construction name = " +
1906 0 : state.dataConstruction->Construct(Surface(this->SurfacePtr(SurfNum)).Construction).Name);
1907 0 : ShowContinueError(state, "Construction needs to be referenced by a \"ConstructionProperty:InternalHeatSource\" object.");
1908 0 : errorsFound = true;
1909 : }
1910 : }
1911 82 : }
1912 :
1913 684904 : void InitLowTempRadiantSystem(EnergyPlusData &state,
1914 : bool const FirstHVACIteration, // TRUE if 1st HVAC simulation of system timestep
1915 : int const RadSysNum, // Index for the low temperature radiant system under consideration within the derived types
1916 : LowTempRadiantSystem::SystemType const SystemType, // Type of radiant system: hydronic, constant flow, or electric
1917 : bool &InitErrorsFound)
1918 : {
1919 :
1920 : // SUBROUTINE INFORMATION:
1921 : // AUTHOR Rick Strand
1922 : // DATE WRITTEN November 2000
1923 :
1924 : // Using/Aliasing
1925 :
1926 : using DataSizing::AutoSize;
1927 : using DataZoneEquipment::CheckZoneEquipmentList;
1928 : using FluidProperties::GetDensityGlycol;
1929 :
1930 : using PlantUtilities::InitComponentNodes;
1931 : using PlantUtilities::ScanPlantLoopsForObject;
1932 : using PlantUtilities::SetComponentFlowRate;
1933 : using ScheduleManager::GetCurrentScheduleValue;
1934 :
1935 : // SUBROUTINE PARAMETER DEFINITIONS:
1936 684904 : Real64 constexpr ZeroTol(0.0000001); // Smallest non-zero value allowed
1937 684904 : auto constexpr RoutineName("InitLowTempRadiantSystem");
1938 :
1939 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1940 : Real64 CurrentFlowSchedule; // Schedule value for flow fraction in a constant flow radiant system
1941 : int RadNum; // Number of the radiant system (DO loop counter)
1942 : int RadSurfNum; // Number of the radiant system surface (DO loop counter)
1943 : int SurfNum; // Intermediate variable for keeping track of the surface number
1944 : Real64 TotalEffic; // Intermediate calculation variable for total pump efficiency
1945 : int ZoneNum; // Intermediate variable for keeping track of the zone number
1946 : int Loop;
1947 : Real64 mdot; // local fluid mass flow rate
1948 : Real64 rho; // local fluid density
1949 : bool errFlag;
1950 :
1951 684904 : InitErrorsFound = false;
1952 :
1953 684904 : auto &Surface(state.dataSurface->Surface);
1954 :
1955 684904 : if (state.dataLowTempRadSys->MyOneTimeFlag) {
1956 29 : state.dataLowTempRadSys->MyEnvrnFlagHydr.allocate(state.dataLowTempRadSys->NumOfHydrLowTempRadSys);
1957 29 : state.dataLowTempRadSys->MyEnvrnFlagCFlo.allocate(state.dataLowTempRadSys->NumOfCFloLowTempRadSys);
1958 29 : state.dataLowTempRadSys->MyEnvrnFlagElec.allocate(state.dataLowTempRadSys->NumOfElecLowTempRadSys);
1959 29 : state.dataLowTempRadSys->MyPlantScanFlagHydr.allocate(state.dataLowTempRadSys->NumOfHydrLowTempRadSys);
1960 29 : state.dataLowTempRadSys->MyPlantScanFlagCFlo.allocate(state.dataLowTempRadSys->NumOfCFloLowTempRadSys);
1961 29 : state.dataLowTempRadSys->MyPlantScanFlagHydr = true;
1962 29 : state.dataLowTempRadSys->MyPlantScanFlagCFlo = true;
1963 29 : state.dataLowTempRadSys->MyEnvrnFlagHydr = true;
1964 29 : state.dataLowTempRadSys->MyEnvrnFlagCFlo = true;
1965 29 : state.dataLowTempRadSys->MyEnvrnFlagElec = true;
1966 29 : state.dataLowTempRadSys->MyOneTimeFlag = false;
1967 : }
1968 :
1969 684904 : if (state.dataLowTempRadSys->FirstTimeInit) {
1970 :
1971 29 : state.dataLowTempRadSys->ZeroSourceSumHATsurf.dimension(state.dataGlobal->NumOfZones, 0.0);
1972 29 : state.dataLowTempRadSys->QRadSysSrcAvg.dimension(state.dataSurface->TotSurfaces, 0.0);
1973 29 : state.dataLowTempRadSys->LastQRadSysSrc.dimension(state.dataSurface->TotSurfaces, 0.0);
1974 29 : state.dataLowTempRadSys->LastSysTimeElapsed.dimension(state.dataSurface->TotSurfaces, 0.0);
1975 29 : state.dataLowTempRadSys->LastTimeStepSys.dimension(state.dataSurface->TotSurfaces, 0.0);
1976 29 : state.dataLowTempRadSys->MySizeFlagHydr.allocate(state.dataLowTempRadSys->NumOfHydrLowTempRadSys);
1977 29 : state.dataLowTempRadSys->MySizeFlagCFlo.allocate(state.dataLowTempRadSys->NumOfCFloLowTempRadSys);
1978 29 : state.dataLowTempRadSys->MySizeFlagElec.allocate(state.dataLowTempRadSys->NumOfElecLowTempRadSys);
1979 29 : state.dataLowTempRadSys->MySizeFlagHydr = true;
1980 29 : state.dataLowTempRadSys->MySizeFlagCFlo = true;
1981 29 : state.dataLowTempRadSys->MySizeFlagElec = true;
1982 :
1983 : // Initialize total areas for all radiant systems
1984 75 : for (RadNum = 1; RadNum <= state.dataLowTempRadSys->NumOfHydrLowTempRadSys; ++RadNum) {
1985 46 : state.dataLowTempRadSys->HydrRadSys(RadNum).TotalSurfaceArea = 0.0;
1986 104 : for (SurfNum = 1; SurfNum <= state.dataLowTempRadSys->HydrRadSys(RadNum).NumOfSurfaces; ++SurfNum) {
1987 58 : state.dataLowTempRadSys->HydrRadSys(RadNum).TotalSurfaceArea +=
1988 58 : Surface(state.dataLowTempRadSys->HydrRadSys(RadNum).SurfacePtr(SurfNum)).Area;
1989 : }
1990 : }
1991 56 : for (RadNum = 1; RadNum <= state.dataLowTempRadSys->NumOfCFloLowTempRadSys; ++RadNum) {
1992 27 : state.dataLowTempRadSys->CFloRadSys(RadNum).TotalSurfaceArea = 0.0;
1993 54 : for (SurfNum = 1; SurfNum <= state.dataLowTempRadSys->CFloRadSys(RadNum).NumOfSurfaces; ++SurfNum) {
1994 27 : state.dataLowTempRadSys->CFloRadSys(RadNum).TotalSurfaceArea +=
1995 27 : Surface(state.dataLowTempRadSys->CFloRadSys(RadNum).SurfacePtr(SurfNum)).Area;
1996 : }
1997 : }
1998 38 : for (RadNum = 1; RadNum <= state.dataLowTempRadSys->NumOfElecLowTempRadSys; ++RadNum) {
1999 9 : state.dataLowTempRadSys->ElecRadSys(RadNum).TotalSurfaceArea = 0.0;
2000 18 : for (SurfNum = 1; SurfNum <= state.dataLowTempRadSys->ElecRadSys(RadNum).NumOfSurfaces; ++SurfNum) {
2001 9 : state.dataLowTempRadSys->ElecRadSys(RadNum).TotalSurfaceArea +=
2002 9 : Surface(state.dataLowTempRadSys->ElecRadSys(RadNum).SurfacePtr(SurfNum)).Area;
2003 : }
2004 : }
2005 :
2006 29 : Real64 MotorEffic(0.0);
2007 29 : if (SystemType == LowTempRadiantSystem::SystemType::ConstantFlowSystem) {
2008 9 : ConstantFlowRadDesignData constantFlowDesignDataObject{state.dataLowTempRadSys->CflowRadiantSysDesign(
2009 18 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).DesignObjectPtr)}; // Contains the data for constant flow hydronic systems
2010 9 : MotorEffic = constantFlowDesignDataObject.MotorEffic;
2011 : }
2012 :
2013 : // Check pump parameters for constant flow hydronic radiant systems
2014 56 : for (RadNum = 1; RadNum <= state.dataLowTempRadSys->NumOfCFloLowTempRadSys; ++RadNum) {
2015 : // Calculate the efficiency for each pump: The calculation
2016 : // is based on the PMPSIM code in the ASHRAE Secondary Toolkit
2017 27 : Real64 PEC = state.dataLowTempRadSys->CFloRadSys(RadNum).PumpEffic;
2018 54 : if ((state.dataLowTempRadSys->CFloRadSys(RadNum).NomPowerUse > ZeroTol) && (MotorEffic > ZeroTol) &&
2019 27 : (state.dataLowTempRadSys->CFloRadSys(RadNum).WaterVolFlowMax != AutoSize)) {
2020 78 : TotalEffic = state.dataLowTempRadSys->CFloRadSys(RadNum).WaterVolFlowMax *
2021 52 : state.dataLowTempRadSys->CFloRadSys(RadNum).NomPumpHead / state.dataLowTempRadSys->CFloRadSys(RadNum).NomPowerUse;
2022 26 : state.dataLowTempRadSys->CFloRadSys(RadNum).PumpEffic = TotalEffic / MotorEffic;
2023 26 : PEC = state.dataLowTempRadSys->CFloRadSys(RadNum).PumpEffic;
2024 26 : auto constexpr fmt = "Check input. Calc Pump Efficiency={:.5R}% {}, for pump in radiant system {}";
2025 26 : Real64 pumpEfficiency = state.dataLowTempRadSys->CFloRadSys(RadNum).PumpEffic * 100.0;
2026 26 : PEC = state.dataLowTempRadSys->CFloRadSys(RadNum).PumpEffic;
2027 26 : if (state.dataLowTempRadSys->CFloRadSys(RadNum).PumpEffic < 0.50) {
2028 9 : ShowWarningError(state,
2029 6 : format(fmt, pumpEfficiency, "which is less than 50%", state.dataLowTempRadSys->CFloRadSys(RadNum).Name));
2030 23 : } else if ((state.dataLowTempRadSys->CFloRadSys(RadNum).PumpEffic > 0.95) &&
2031 0 : (state.dataLowTempRadSys->CFloRadSys(RadNum).PumpEffic <= 1.0)) {
2032 0 : ShowWarningError(state, format(fmt, pumpEfficiency, "is approaching 100%", state.dataLowTempRadSys->CFloRadSys(RadNum).Name));
2033 23 : } else if (state.dataLowTempRadSys->CFloRadSys(RadNum).PumpEffic > 1.0) {
2034 0 : ShowSevereError(state,
2035 0 : format(fmt, pumpEfficiency, "which is bigger than 100%", state.dataLowTempRadSys->CFloRadSys(RadNum).Name));
2036 0 : InitErrorsFound = true;
2037 : }
2038 : } else {
2039 1 : if (state.dataLowTempRadSys->CFloRadSys(RadNum).WaterVolFlowMax !=
2040 : AutoSize) { // Autosize is not an error but it does not need to check pump efficiency here
2041 0 : ShowSevereError(state,
2042 0 : "Check input. Pump nominal power and motor efficiency cannot be 0, for pump=" +
2043 0 : state.dataLowTempRadSys->CFloRadSys(RadNum).Name);
2044 0 : InitErrorsFound = true;
2045 : }
2046 : }
2047 : }
2048 :
2049 29 : state.dataLowTempRadSys->FirstTimeInit = false;
2050 : }
2051 :
2052 684904 : if (SystemType == LowTempRadiantSystem::SystemType::HydronicSystem) {
2053 372334 : if (state.dataLowTempRadSys->MyPlantScanFlagHydr(RadSysNum) && allocated(state.dataPlnt->PlantLoop)) {
2054 46 : errFlag = false;
2055 46 : if (state.dataLowTempRadSys->HydrRadSys(RadSysNum).HotWaterInNode > 0) {
2056 184 : ScanPlantLoopsForObject(state,
2057 46 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).Name,
2058 : DataPlant::PlantEquipmentType::LowTempRadiant_VarFlow,
2059 46 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).HWPlantLoc,
2060 : errFlag,
2061 : _,
2062 : _,
2063 : _,
2064 46 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).HotWaterInNode,
2065 : _);
2066 46 : if (errFlag) {
2067 0 : ShowFatalError(state, "InitLowTempRadiantSystem: Program terminated due to previous condition(s).");
2068 : }
2069 : }
2070 46 : if (state.dataLowTempRadSys->HydrRadSys(RadSysNum).ColdWaterInNode > 0) {
2071 172 : ScanPlantLoopsForObject(state,
2072 43 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).Name,
2073 : DataPlant::PlantEquipmentType::LowTempRadiant_VarFlow,
2074 43 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).CWPlantLoc,
2075 : errFlag,
2076 : _,
2077 : _,
2078 : _,
2079 43 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).ColdWaterInNode,
2080 : _);
2081 43 : if (errFlag) {
2082 0 : ShowFatalError(state, "InitLowTempRadiantSystem: Program terminated due to previous condition(s).");
2083 : }
2084 : }
2085 46 : state.dataLowTempRadSys->MyPlantScanFlagHydr(RadSysNum) = false;
2086 372288 : } else if (state.dataLowTempRadSys->MyPlantScanFlagHydr(RadSysNum) && !state.dataGlobal->AnyPlantInModel) {
2087 0 : state.dataLowTempRadSys->MyPlantScanFlagHydr(RadSysNum) = false;
2088 : }
2089 : }
2090 :
2091 684904 : if (SystemType == LowTempRadiantSystem::SystemType::ConstantFlowSystem) {
2092 231699 : if (state.dataLowTempRadSys->MyPlantScanFlagCFlo(RadSysNum) && allocated(state.dataPlnt->PlantLoop)) {
2093 27 : errFlag = false;
2094 27 : if (state.dataLowTempRadSys->CFloRadSys(RadSysNum).HotWaterInNode > 0) {
2095 108 : ScanPlantLoopsForObject(state,
2096 27 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).Name,
2097 : DataPlant::PlantEquipmentType::LowTempRadiant_ConstFlow,
2098 27 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).HWPlantLoc,
2099 : errFlag,
2100 : _,
2101 : _,
2102 : _,
2103 27 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).HotWaterInNode,
2104 : _);
2105 27 : if (errFlag) {
2106 0 : ShowFatalError(state, "InitLowTempRadiantSystem: Program terminated due to previous condition(s).");
2107 : }
2108 : }
2109 27 : if (state.dataLowTempRadSys->CFloRadSys(RadSysNum).ColdWaterInNode > 0) {
2110 96 : ScanPlantLoopsForObject(state,
2111 24 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).Name,
2112 : DataPlant::PlantEquipmentType::LowTempRadiant_ConstFlow,
2113 24 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).CWPlantLoc,
2114 : errFlag,
2115 : _,
2116 : _,
2117 : _,
2118 24 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).ColdWaterInNode,
2119 : _);
2120 24 : if (errFlag) {
2121 0 : ShowFatalError(state, "InitLowTempRadiantSystem: Program terminated due to previous condition(s).");
2122 : }
2123 : }
2124 27 : state.dataLowTempRadSys->MyPlantScanFlagCFlo(RadSysNum) = false;
2125 231672 : } else if (state.dataLowTempRadSys->MyPlantScanFlagCFlo(RadSysNum) && !state.dataGlobal->AnyPlantInModel) {
2126 0 : state.dataLowTempRadSys->MyPlantScanFlagCFlo(RadSysNum) = false;
2127 : }
2128 : }
2129 :
2130 : // need to check all units to see if they are on Zone Equipment List or issue warning
2131 684904 : if (!state.dataLowTempRadSys->ZoneEquipmentListChecked && state.dataZoneEquip->ZoneEquipInputsFilled) {
2132 29 : state.dataLowTempRadSys->ZoneEquipmentListChecked = true;
2133 111 : for (Loop = 1; Loop <= state.dataLowTempRadSys->TotalNumOfRadSystems; ++Loop) {
2134 82 : switch (state.dataLowTempRadSys->RadSysTypes(Loop).SystemType) {
2135 46 : case LowTempRadiantSystem::SystemType::HydronicSystem: {
2136 46 : if (CheckZoneEquipmentList(state, "ZoneHVAC:LowTemperatureRadiant:VariableFlow", state.dataLowTempRadSys->RadSysTypes(Loop).Name))
2137 46 : continue;
2138 0 : ShowSevereError(state,
2139 0 : "InitLowTempRadiantSystem: Unit=[ZoneHVAC:LowTemperatureRadiant:VariableFlow," +
2140 0 : state.dataLowTempRadSys->RadSysTypes(Loop).Name +
2141 : "] is not on any ZoneHVAC:EquipmentList. It will not be simulated.");
2142 0 : } break;
2143 27 : case LowTempRadiantSystem::SystemType::ConstantFlowSystem: {
2144 27 : if (CheckZoneEquipmentList(state, "ZoneHVAC:LowTemperatureRadiant:ConstantFlow", state.dataLowTempRadSys->RadSysTypes(Loop).Name))
2145 27 : continue;
2146 0 : ShowSevereError(state,
2147 0 : "InitLowTempRadiantSystem: Unit=[ZoneHVAC:LowTemperatureRadiant:ConstantFlow," +
2148 0 : state.dataLowTempRadSys->RadSysTypes(Loop).Name +
2149 : "] is not on any ZoneHVAC:EquipmentList. It will not be simulated.");
2150 0 : } break;
2151 9 : case LowTempRadiantSystem::SystemType::ElectricSystem: {
2152 9 : if (CheckZoneEquipmentList(state, "ZoneHVAC:LowTemperatureRadiant:Electric", state.dataLowTempRadSys->RadSysTypes(Loop).Name))
2153 9 : continue;
2154 0 : ShowSevereError(state,
2155 0 : "InitLowTempRadiantSystem: Unit=[ZoneHVAC:LowTemperatureRadiant:Electric," +
2156 0 : state.dataLowTempRadSys->RadSysTypes(Loop).Name +
2157 : "] is not on any ZoneHVAC:EquipmentList. It will not be simulated.");
2158 0 : } break;
2159 0 : default: { // Illegal system, but checked earlier
2160 0 : } break;
2161 : }
2162 : }
2163 : }
2164 :
2165 684904 : if (!state.dataGlobal->SysSizingCalc && (SystemType == LowTempRadiantSystem::SystemType::HydronicSystem)) {
2166 372288 : if (state.dataLowTempRadSys->MySizeFlagHydr(RadSysNum) && !state.dataLowTempRadSys->MyPlantScanFlagHydr(RadSysNum)) {
2167 : // for each radiant system do the sizing once.
2168 46 : SizeLowTempRadiantSystem(state, RadSysNum, SystemType);
2169 46 : state.dataLowTempRadSys->MySizeFlagHydr(RadSysNum) = false;
2170 :
2171 46 : int ColdSetptSchedPtr(0), HotSetptSchedPtr(0);
2172 46 : if (SystemType == LowTempRadiantSystem::SystemType::HydronicSystem) {
2173 46 : VarFlowRadDesignData variableFlowDesignDataObject{state.dataLowTempRadSys->HydronicRadiantSysDesign(
2174 92 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).DesignObjectPtr)}; // Contains the data for variable flow hydronic systems;
2175 46 : ColdSetptSchedPtr = variableFlowDesignDataObject.ColdSetptSchedPtr;
2176 46 : HotSetptSchedPtr = variableFlowDesignDataObject.HotSetptSchedPtr;
2177 : }
2178 :
2179 : // Can this system actually do cooling?
2180 135 : if ((state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterVolFlowMaxCool > 0.0) &&
2181 86 : (state.dataLowTempRadSys->HydrRadSys(RadSysNum).ColdWaterInNode > 0) &&
2182 132 : (state.dataLowTempRadSys->HydrRadSys(RadSysNum).ColdWaterOutNode > 0) && ColdSetptSchedPtr > 0) {
2183 43 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).CoolingSystem = true;
2184 : }
2185 :
2186 : // Can this system actually do heating?
2187 138 : if ((state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterVolFlowMaxHeat > 0.0) &&
2188 92 : (state.dataLowTempRadSys->HydrRadSys(RadSysNum).HotWaterInNode > 0) &&
2189 138 : (state.dataLowTempRadSys->HydrRadSys(RadSysNum).HotWaterOutNode > 0) && (HotSetptSchedPtr > 0)) {
2190 46 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).HeatingSystem = true;
2191 : }
2192 :
2193 : // set design mass flow rates
2194 46 : if (state.dataLowTempRadSys->HydrRadSys(RadSysNum).HotWaterInNode > 0) {
2195 92 : rho = GetDensityGlycol(state,
2196 46 : state.dataPlnt->PlantLoop(state.dataLowTempRadSys->HydrRadSys(RadSysNum).HWPlantLoc.loopNum).FluidName,
2197 : DataGlobalConstants::HWInitConvTemp,
2198 46 : state.dataPlnt->PlantLoop(state.dataLowTempRadSys->HydrRadSys(RadSysNum).HWPlantLoc.loopNum).FluidIndex,
2199 46 : RoutineName);
2200 46 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterFlowMaxHeat =
2201 46 : rho * state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterVolFlowMaxHeat;
2202 138 : InitComponentNodes(state,
2203 : 0.0,
2204 46 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterFlowMaxHeat,
2205 46 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).HotWaterInNode,
2206 46 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).HotWaterOutNode);
2207 : }
2208 46 : if (state.dataLowTempRadSys->HydrRadSys(RadSysNum).ColdWaterInNode > 0) {
2209 86 : rho = GetDensityGlycol(state,
2210 43 : state.dataPlnt->PlantLoop(state.dataLowTempRadSys->HydrRadSys(RadSysNum).CWPlantLoc.loopNum).FluidName,
2211 : DataGlobalConstants::CWInitConvTemp,
2212 43 : state.dataPlnt->PlantLoop(state.dataLowTempRadSys->HydrRadSys(RadSysNum).CWPlantLoc.loopNum).FluidIndex,
2213 43 : RoutineName);
2214 43 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterFlowMaxCool =
2215 43 : rho * state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterVolFlowMaxCool;
2216 129 : InitComponentNodes(state,
2217 : 0.0,
2218 43 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterFlowMaxCool,
2219 43 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).ColdWaterInNode,
2220 43 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).ColdWaterOutNode);
2221 : }
2222 : }
2223 : }
2224 :
2225 684904 : if (!state.dataGlobal->SysSizingCalc && (SystemType == LowTempRadiantSystem::SystemType::ConstantFlowSystem)) {
2226 231696 : if (state.dataLowTempRadSys->MySizeFlagCFlo(RadSysNum) && !state.dataLowTempRadSys->MyPlantScanFlagCFlo(RadSysNum)) {
2227 : // for each radiant system do the sizing once.
2228 27 : SizeLowTempRadiantSystem(state, RadSysNum, SystemType);
2229 :
2230 : // set design mass flow rates
2231 27 : if (state.dataLowTempRadSys->CFloRadSys(RadSysNum).HotWaterInNode > 0) {
2232 54 : rho = GetDensityGlycol(state,
2233 27 : state.dataPlnt->PlantLoop(state.dataLowTempRadSys->CFloRadSys(RadSysNum).HWPlantLoc.loopNum).FluidName,
2234 : DataGlobalConstants::HWInitConvTemp,
2235 27 : state.dataPlnt->PlantLoop(state.dataLowTempRadSys->CFloRadSys(RadSysNum).HWPlantLoc.loopNum).FluidIndex,
2236 27 : RoutineName);
2237 27 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).HotDesignWaterMassFlowRate =
2238 27 : rho * state.dataLowTempRadSys->CFloRadSys(RadSysNum).WaterVolFlowMax;
2239 81 : InitComponentNodes(state,
2240 : 0.0,
2241 27 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).HotDesignWaterMassFlowRate,
2242 27 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).HotWaterInNode,
2243 27 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).HotWaterOutNode);
2244 : }
2245 27 : if (state.dataLowTempRadSys->CFloRadSys(RadSysNum).ColdWaterInNode > 0) {
2246 48 : rho = GetDensityGlycol(state,
2247 24 : state.dataPlnt->PlantLoop(state.dataLowTempRadSys->CFloRadSys(RadSysNum).CWPlantLoc.loopNum).FluidName,
2248 : DataGlobalConstants::CWInitConvTemp,
2249 24 : state.dataPlnt->PlantLoop(state.dataLowTempRadSys->CFloRadSys(RadSysNum).CWPlantLoc.loopNum).FluidIndex,
2250 24 : RoutineName);
2251 24 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).ColdDesignWaterMassFlowRate =
2252 24 : rho * state.dataLowTempRadSys->CFloRadSys(RadSysNum).WaterVolFlowMax;
2253 72 : InitComponentNodes(state,
2254 : 0.0,
2255 24 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).ColdDesignWaterMassFlowRate,
2256 24 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).ColdWaterInNode,
2257 24 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).ColdWaterOutNode);
2258 : }
2259 27 : state.dataLowTempRadSys->MySizeFlagCFlo(RadSysNum) = false;
2260 : }
2261 : }
2262 :
2263 684904 : if (!state.dataGlobal->SysSizingCalc && (SystemType == LowTempRadiantSystem::SystemType::ElectricSystem)) {
2264 80865 : if (state.dataLowTempRadSys->MySizeFlagElec(RadSysNum)) {
2265 : // for each radiant system do the sizing once.
2266 9 : SizeLowTempRadiantSystem(state, RadSysNum, SystemType);
2267 9 : state.dataLowTempRadSys->MySizeFlagElec(RadSysNum) = false;
2268 : }
2269 : }
2270 :
2271 684904 : if (state.dataGlobal->BeginEnvrnFlag && state.dataLowTempRadSys->MyEnvrnFlagGeneral) {
2272 160 : state.dataLowTempRadSys->ZeroSourceSumHATsurf = 0.0;
2273 160 : state.dataLowTempRadSys->QRadSysSrcAvg = 0.0;
2274 160 : state.dataLowTempRadSys->LastQRadSysSrc = 0.0;
2275 160 : state.dataLowTempRadSys->LastSysTimeElapsed = 0.0;
2276 160 : state.dataLowTempRadSys->LastTimeStepSys = 0.0;
2277 160 : state.dataLowTempRadSys->MyEnvrnFlagGeneral = false;
2278 : }
2279 684904 : if (!state.dataGlobal->BeginEnvrnFlag) state.dataLowTempRadSys->MyEnvrnFlagGeneral = true;
2280 :
2281 : // If we are at the beginning of a new environment OR the warmup period is done and the simulation is starting,
2282 : // then the various changeover variables need to be reset so that we are starting from scratch.
2283 1370002 : if ((state.dataGlobal->BeginEnvrnFlag && FirstHVACIteration) ||
2284 790897 : (!state.dataGlobal->WarmupFlag && state.dataGlobal->BeginDayFlag && FirstHVACIteration && state.dataGlobal->DayOfSim == 1)) {
2285 : // Reset values related to changeover
2286 1798 : if (SystemType == LowTempRadiantSystem::SystemType::HydronicSystem) {
2287 1000 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).lastOperatingMode = NotOperating;
2288 1000 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).lastDayOfSim = 0;
2289 1000 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).lastHourOfDay = 0;
2290 1000 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).lastTimeStep = 0;
2291 : }
2292 1798 : if (SystemType == LowTempRadiantSystem::SystemType::ConstantFlowSystem) {
2293 648 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).lastOperatingMode = NotOperating;
2294 648 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).lastDayOfSim = 0;
2295 648 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).lastHourOfDay = 0;
2296 648 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).lastTimeStep = 0;
2297 : }
2298 : }
2299 :
2300 684904 : if (SystemType == LowTempRadiantSystem::SystemType::HydronicSystem) {
2301 372334 : if (state.dataGlobal->BeginEnvrnFlag && state.dataLowTempRadSys->MyEnvrnFlagHydr(RadSysNum)) {
2302 242 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).HeatPower = 0.0;
2303 242 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).HeatEnergy = 0.0;
2304 242 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).CoolPower = 0.0;
2305 242 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).CoolEnergy = 0.0;
2306 242 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterInletTemp = 0.0;
2307 242 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterOutletTemp = 0.0;
2308 242 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterMassFlowRate = 0.0;
2309 :
2310 242 : if (!state.dataLowTempRadSys->MyPlantScanFlagHydr(RadSysNum)) {
2311 242 : if (state.dataLowTempRadSys->HydrRadSys(RadSysNum).HotWaterInNode > 0) {
2312 726 : InitComponentNodes(state,
2313 : 0.0,
2314 242 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterFlowMaxHeat,
2315 242 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).HotWaterInNode,
2316 242 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).HotWaterOutNode);
2317 : }
2318 242 : if (state.dataLowTempRadSys->HydrRadSys(RadSysNum).ColdWaterInNode > 0) {
2319 681 : InitComponentNodes(state,
2320 : 0.0,
2321 227 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterFlowMaxCool,
2322 227 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).ColdWaterInNode,
2323 227 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).ColdWaterOutNode);
2324 : }
2325 : }
2326 242 : state.dataLowTempRadSys->MyEnvrnFlagHydr(RadSysNum) = false;
2327 : }
2328 : } // NumOfHydrLowTempRadSys > 0
2329 684904 : if (!state.dataGlobal->BeginEnvrnFlag && SystemType == LowTempRadiantSystem::SystemType::HydronicSystem)
2330 370766 : state.dataLowTempRadSys->MyEnvrnFlagHydr(RadSysNum) = true;
2331 :
2332 684904 : if (SystemType == LowTempRadiantSystem::SystemType::ConstantFlowSystem) {
2333 231699 : if (state.dataGlobal->BeginEnvrnFlag && state.dataLowTempRadSys->MyEnvrnFlagCFlo(RadSysNum)) {
2334 168 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).WaterInletTemp = 0.0;
2335 168 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).WaterOutletTemp = 0.0;
2336 168 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).PumpInletTemp = 0.0;
2337 168 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).WaterMassFlowRate = 0.0;
2338 168 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).WaterInjectionRate = 0.0;
2339 168 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).WaterRecircRate = 0.0;
2340 168 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).HeatPower = 0.0;
2341 168 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).HeatEnergy = 0.0;
2342 168 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).CoolPower = 0.0;
2343 168 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).CoolEnergy = 0.0;
2344 168 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).PumpPower = 0.0;
2345 168 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).PumpMassFlowRate = 0.0;
2346 168 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).PumpHeattoFluid = 0.0;
2347 :
2348 168 : if (!state.dataLowTempRadSys->MyPlantScanFlagCFlo(RadSysNum)) {
2349 168 : if (state.dataLowTempRadSys->CFloRadSys(RadSysNum).HotWaterInNode > 0) {
2350 504 : InitComponentNodes(state,
2351 : 0.0,
2352 168 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).HotDesignWaterMassFlowRate,
2353 168 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).HotWaterInNode,
2354 168 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).HotWaterOutNode);
2355 : }
2356 168 : if (state.dataLowTempRadSys->CFloRadSys(RadSysNum).ColdWaterInNode > 0) {
2357 459 : InitComponentNodes(state,
2358 : 0.0,
2359 153 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).ColdDesignWaterMassFlowRate,
2360 153 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).ColdWaterInNode,
2361 153 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).ColdWaterOutNode);
2362 : }
2363 : }
2364 168 : state.dataLowTempRadSys->MyEnvrnFlagCFlo(RadSysNum) = false;
2365 : }
2366 :
2367 231699 : if (state.dataLowTempRadSys->anyRadiantSystemUsingRunningMeanAverage) {
2368 27132 : if (state.dataGlobal->BeginDayFlag && state.dataLowTempRadSys->CFloRadSys(RadSysNum).setRunningMeanValuesAtBeginningOfDay) {
2369 78 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).calculateRunningMeanAverageTemperature(state, RadSysNum);
2370 78 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).setRunningMeanValuesAtBeginningOfDay = false; // only set these once per system
2371 27054 : } else if (!state.dataGlobal->BeginDayFlag && !state.dataLowTempRadSys->CFloRadSys(RadSysNum).setRunningMeanValuesAtBeginningOfDay) {
2372 78 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).setRunningMeanValuesAtBeginningOfDay =
2373 : true; // reset so that the next time BeginDayFlag is true this can get set
2374 : }
2375 : }
2376 :
2377 : } // NumOfCFloLowTempRadSys > 0
2378 684904 : if (!state.dataGlobal->BeginEnvrnFlag && SystemType == LowTempRadiantSystem::SystemType::ConstantFlowSystem)
2379 230733 : state.dataLowTempRadSys->MyEnvrnFlagCFlo(RadSysNum) = true;
2380 :
2381 684904 : if (SystemType == LowTempRadiantSystem::SystemType::ElectricSystem) {
2382 80871 : if (state.dataGlobal->BeginEnvrnFlag && state.dataLowTempRadSys->MyEnvrnFlagElec(RadSysNum)) {
2383 45 : state.dataLowTempRadSys->ElecRadSys(RadSysNum).HeatPower = 0.0;
2384 45 : state.dataLowTempRadSys->ElecRadSys(RadSysNum).HeatEnergy = 0.0;
2385 45 : state.dataLowTempRadSys->ElecRadSys(RadSysNum).ElecPower = 0.0;
2386 45 : state.dataLowTempRadSys->ElecRadSys(RadSysNum).ElecEnergy = 0.0;
2387 : }
2388 80871 : state.dataLowTempRadSys->MyEnvrnFlagElec(RadSysNum) = false;
2389 : }
2390 684904 : if (!state.dataGlobal->BeginEnvrnFlag && SystemType == LowTempRadiantSystem::SystemType::ElectricSystem)
2391 80652 : state.dataLowTempRadSys->MyEnvrnFlagElec(RadSysNum) = true;
2392 :
2393 684904 : if (SystemType == LowTempRadiantSystem::SystemType::ConstantFlowSystem) {
2394 :
2395 : // Can this system actually do heating?
2396 695096 : if ((state.dataLowTempRadSys->CFloRadSys(RadSysNum).WaterVolFlowMax > 0.0) &&
2397 463396 : (state.dataLowTempRadSys->CFloRadSys(RadSysNum).HotWaterInNode > 0) &&
2398 463396 : (state.dataLowTempRadSys->CFloRadSys(RadSysNum).HotWaterOutNode > 0) &&
2399 463396 : (state.dataLowTempRadSys->CFloRadSys(RadSysNum).HotWaterHiTempSchedPtr > 0) &&
2400 463396 : (state.dataLowTempRadSys->CFloRadSys(RadSysNum).HotWaterLoTempSchedPtr > 0) &&
2401 695095 : (state.dataLowTempRadSys->CFloRadSys(RadSysNum).HotCtrlHiTempSchedPtr > 0) &&
2402 231698 : (state.dataLowTempRadSys->CFloRadSys(RadSysNum).HotCtrlLoTempSchedPtr > 0)) {
2403 231698 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).HeatingSystem = true;
2404 : }
2405 :
2406 : // Can this system actually do cooling?
2407 695096 : if ((state.dataLowTempRadSys->CFloRadSys(RadSysNum).WaterVolFlowMax > 0.0) &&
2408 449551 : (state.dataLowTempRadSys->CFloRadSys(RadSysNum).ColdWaterInNode > 0) &&
2409 435706 : (state.dataLowTempRadSys->CFloRadSys(RadSysNum).ColdWaterOutNode > 0) &&
2410 435706 : (state.dataLowTempRadSys->CFloRadSys(RadSysNum).ColdWaterHiTempSchedPtr > 0) &&
2411 435706 : (state.dataLowTempRadSys->CFloRadSys(RadSysNum).ColdWaterLoTempSchedPtr > 0) &&
2412 667405 : (state.dataLowTempRadSys->CFloRadSys(RadSysNum).ColdCtrlHiTempSchedPtr > 0) &&
2413 217853 : (state.dataLowTempRadSys->CFloRadSys(RadSysNum).ColdCtrlLoTempSchedPtr > 0)) {
2414 217853 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).CoolingSystem = true;
2415 : }
2416 : }
2417 :
2418 684904 : if (state.dataGlobal->BeginTimeStepFlag && FirstHVACIteration) { // This is the first pass through in a particular time step
2419 :
2420 256040 : switch (SystemType) {
2421 140501 : case LowTempRadiantSystem::SystemType::HydronicSystem: {
2422 140501 : ZoneNum = state.dataLowTempRadSys->HydrRadSys(RadSysNum).ZonePtr;
2423 140501 : state.dataLowTempRadSys->ZeroSourceSumHATsurf(ZoneNum) =
2424 140501 : state.dataHeatBal->Zone(ZoneNum).sumHATsurf(state); // Set this to figure what part of the load the radiant system meets
2425 298570 : for (RadSurfNum = 1; RadSurfNum <= state.dataLowTempRadSys->HydrRadSys(RadSysNum).NumOfSurfaces; ++RadSurfNum) {
2426 158069 : SurfNum = state.dataLowTempRadSys->HydrRadSys(RadSysNum).SurfacePtr(RadSurfNum);
2427 158069 : state.dataLowTempRadSys->QRadSysSrcAvg(SurfNum) = 0.0; // Initialize this variable to zero (radiant system defaults to off)
2428 158069 : state.dataLowTempRadSys->LastQRadSysSrc(SurfNum) =
2429 : 0.0; // At the start of a time step, reset to zero so average calculation can begin again
2430 158069 : state.dataLowTempRadSys->LastSysTimeElapsed(SurfNum) =
2431 : 0.0; // At the start of a time step, reset to zero so average calculation can begin again
2432 158069 : state.dataLowTempRadSys->LastTimeStepSys(SurfNum) =
2433 : 0.0; // At the start of a time step, reset to zero so average calculation can begin again
2434 : }
2435 140501 : } break;
2436 83211 : case LowTempRadiantSystem::SystemType::ConstantFlowSystem: {
2437 83211 : ZoneNum = state.dataLowTempRadSys->CFloRadSys(RadSysNum).ZonePtr;
2438 83211 : state.dataLowTempRadSys->ZeroSourceSumHATsurf(ZoneNum) =
2439 83211 : state.dataHeatBal->Zone(ZoneNum).sumHATsurf(state); // Set this to figure what part of the load the radiant system meets
2440 166422 : for (RadSurfNum = 1; RadSurfNum <= state.dataLowTempRadSys->CFloRadSys(RadSysNum).NumOfSurfaces; ++RadSurfNum) {
2441 83211 : SurfNum = state.dataLowTempRadSys->CFloRadSys(RadSysNum).SurfacePtr(RadSurfNum);
2442 83211 : state.dataLowTempRadSys->QRadSysSrcAvg(SurfNum) = 0.0; // Initialize this variable to zero (radiant system defaults to off)
2443 83211 : state.dataLowTempRadSys->LastQRadSysSrc(SurfNum) =
2444 : 0.0; // At the start of a time step, reset to zero so average calculation can begin again
2445 83211 : state.dataLowTempRadSys->LastSysTimeElapsed(SurfNum) =
2446 : 0.0; // At the start of a time step, reset to zero so average calculation can begin again
2447 83211 : state.dataLowTempRadSys->LastTimeStepSys(SurfNum) =
2448 : 0.0; // At the start of a time step, reset to zero so average calculation can begin again
2449 : }
2450 83211 : } break;
2451 32328 : case LowTempRadiantSystem::SystemType::ElectricSystem: {
2452 32328 : ZoneNum = state.dataLowTempRadSys->ElecRadSys(RadSysNum).ZonePtr;
2453 32328 : state.dataLowTempRadSys->ZeroSourceSumHATsurf(ZoneNum) =
2454 32328 : state.dataHeatBal->Zone(ZoneNum).sumHATsurf(state); // Set this to figure what part of the load the radiant system meets
2455 64656 : for (RadSurfNum = 1; RadSurfNum <= state.dataLowTempRadSys->ElecRadSys(RadSysNum).NumOfSurfaces; ++RadSurfNum) {
2456 32328 : SurfNum = state.dataLowTempRadSys->ElecRadSys(RadSysNum).SurfacePtr(RadSurfNum);
2457 32328 : state.dataLowTempRadSys->QRadSysSrcAvg(SurfNum) = 0.0; // Initialize this variable to zero (radiant system defaults to off)
2458 32328 : state.dataLowTempRadSys->LastQRadSysSrc(SurfNum) =
2459 : 0.0; // At the start of a time step, reset to zero so average calculation can begin again
2460 32328 : state.dataLowTempRadSys->LastSysTimeElapsed(SurfNum) =
2461 : 0.0; // At the start of a time step, reset to zero so average calculation can begin again
2462 32328 : state.dataLowTempRadSys->LastTimeStepSys(SurfNum) =
2463 : 0.0; // At the start of a time step, reset to zero so average calculation can begin again
2464 : }
2465 32328 : } break;
2466 0 : default: {
2467 0 : ShowSevereError(state, "Radiant system entered without specification of type: electric, constant flow, or hydronic?");
2468 0 : ShowContinueError(state, "Occurs in Radiant System=" + state.dataLowTempRadSys->HydrRadSys(RadSysNum).Name);
2469 0 : ShowFatalError(state, "Preceding condition causes termination.");
2470 0 : } break;
2471 : }
2472 :
2473 : } // ...for first pass through in a particular time step.
2474 :
2475 684904 : switch (SystemType) {
2476 372334 : case LowTempRadiantSystem::SystemType::HydronicSystem: {
2477 :
2478 : // Initialize the appropriate node data
2479 372334 : if (state.dataLowTempRadSys->HydrRadSys(RadSysNum).HeatingSystem) {
2480 372288 : mdot = 0.0;
2481 1116864 : SetComponentFlowRate(state,
2482 : mdot,
2483 372288 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).HotWaterInNode,
2484 372288 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).HotWaterOutNode,
2485 372288 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).HWPlantLoc);
2486 : }
2487 372334 : if (state.dataLowTempRadSys->HydrRadSys(RadSysNum).CoolingSystem) {
2488 357489 : mdot = 0.0;
2489 1072467 : SetComponentFlowRate(state,
2490 : mdot,
2491 357489 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).ColdWaterInNode,
2492 357489 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).ColdWaterOutNode,
2493 357489 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).CWPlantLoc);
2494 : }
2495 372334 : if (state.dataLowTempRadSys->HydrRadSys(RadSysNum).OperatingMode != NotOperating && FirstHVACIteration)
2496 126775 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).updateOperatingModeHistory(state);
2497 :
2498 372334 : } break;
2499 231699 : case LowTempRadiantSystem::SystemType::ConstantFlowSystem: {
2500 231699 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).WaterMassFlowRate = 0.0;
2501 : // Initialize the appropriate node data
2502 231699 : if (state.dataLowTempRadSys->CFloRadSys(RadSysNum).HeatingSystem) {
2503 231698 : if (state.dataLowTempRadSys->CFloRadSys(RadSysNum).VolFlowSchedPtr > 0) {
2504 0 : CurrentFlowSchedule = GetCurrentScheduleValue(state, state.dataLowTempRadSys->CFloRadSys(RadSysNum).VolFlowSchedPtr);
2505 : } else {
2506 231698 : CurrentFlowSchedule = 1.0; // Allow user to avoid putting in a schedule (defaults to constant flow at all times)
2507 : }
2508 231698 : if (CurrentFlowSchedule > 1.0) CurrentFlowSchedule = 1.0; // Do not allow more flow than design maximum
2509 231698 : if (CurrentFlowSchedule < 0.0) CurrentFlowSchedule = 0.0; // Do not allow negative flow
2510 :
2511 231698 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).HotWaterMassFlowRate =
2512 231698 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).HotDesignWaterMassFlowRate * CurrentFlowSchedule;
2513 :
2514 231698 : if (state.dataLowTempRadSys->CFloRadSys(RadSysNum).EMSOverrideOnWaterMdot)
2515 0 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).HotWaterMassFlowRate =
2516 0 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).EMSWaterMdotOverrideValue;
2517 :
2518 231698 : if (state.dataLowTempRadSys->CFloRadSys(RadSysNum).HotWaterInNode > 0)
2519 926792 : SetComponentFlowRate(state,
2520 231698 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).HotWaterMassFlowRate,
2521 231698 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).HotWaterInNode,
2522 231698 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).HotWaterOutNode,
2523 231698 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).HWPlantLoc);
2524 : }
2525 231699 : if (state.dataLowTempRadSys->CFloRadSys(RadSysNum).CoolingSystem) {
2526 217853 : if (state.dataLowTempRadSys->CFloRadSys(RadSysNum).VolFlowSchedPtr > 0) {
2527 0 : CurrentFlowSchedule = GetCurrentScheduleValue(state, state.dataLowTempRadSys->CFloRadSys(RadSysNum).VolFlowSchedPtr);
2528 : } else {
2529 217853 : CurrentFlowSchedule = 1.0; // Allow user to avoid putting in a schedule (defaults to constant flow at all times)
2530 : }
2531 217853 : if (CurrentFlowSchedule > 1.0) CurrentFlowSchedule = 1.0; // Do not allow more flow than design maximum
2532 217853 : if (CurrentFlowSchedule < 0.0) CurrentFlowSchedule = 0.0; // Do not allow negative flow
2533 217853 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).ChWaterMassFlowRate =
2534 217853 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).ColdDesignWaterMassFlowRate * CurrentFlowSchedule;
2535 :
2536 217853 : if (state.dataLowTempRadSys->CFloRadSys(RadSysNum).EMSOverrideOnWaterMdot)
2537 0 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).ChWaterMassFlowRate =
2538 0 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).EMSWaterMdotOverrideValue;
2539 :
2540 217853 : if (state.dataLowTempRadSys->CFloRadSys(RadSysNum).ColdWaterInNode > 0)
2541 871412 : SetComponentFlowRate(state,
2542 217853 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).ChWaterMassFlowRate,
2543 217853 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).ColdWaterInNode,
2544 217853 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).ColdWaterOutNode,
2545 217853 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).CWPlantLoc);
2546 : }
2547 231699 : if (state.dataLowTempRadSys->CFloRadSys(RadSysNum).OperatingMode != NotOperating && FirstHVACIteration)
2548 85395 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).updateOperatingModeHistory(state);
2549 :
2550 231699 : } break;
2551 80871 : case LowTempRadiantSystem::SystemType::ElectricSystem: {
2552 80871 : state.dataLowTempRadSys->ElecRadSys(RadSysNum).OperatingMode = NotOperating;
2553 80871 : } break;
2554 0 : default:
2555 0 : break;
2556 : }
2557 684904 : }
2558 :
2559 212170 : void HydronicSystemBaseData::updateOperatingModeHistory(EnergyPlusData &state)
2560 : {
2561 : // Since this is only called when the operating mode is something other than "not operating",
2562 : // the status from the previous system time step is what it did in the last or previous time step.
2563 : // So, we can update the last status of the system using this information before reseting things
2564 : // to "not operating".
2565 212170 : this->lastOperatingMode = this->OperatingMode;
2566 :
2567 212170 : if (state.dataGlobal->BeginDayFlag) {
2568 : // The begin day flag is set which mean this is the first time step of the day.
2569 : // This also means that the previous time step was the last time step of yesterday.
2570 : // So, the day should be the previous day, the hour should bethe last hour of the
2571 : // day, and the time step should be the last time step.
2572 1352 : this->lastDayOfSim = state.dataGlobal->DayOfSim - 1;
2573 1352 : this->lastHourOfDay = int(DataGlobalConstants::HoursInDay);
2574 1352 : this->lastTimeStep = state.dataGlobal->NumOfTimeStepInHour;
2575 210818 : } else if (state.dataGlobal->BeginHourFlag) {
2576 : // It's not the beginning of the day but it is the beginning of an hour other than
2577 : // the first hour. This means that the previous time step was the previous hour of
2578 : // today in the last time step. So, the day should be the current day, the hour should
2579 : // be the previous hour, and the time step should be the last time step.
2580 37004 : this->lastDayOfSim = state.dataGlobal->DayOfSim;
2581 37004 : this->lastHourOfDay = state.dataGlobal->HourOfDay - 1;
2582 37004 : this->lastTimeStep = state.dataGlobal->NumOfTimeStepInHour;
2583 173814 : } else if (state.dataGlobal->BeginTimeStepFlag) {
2584 : // It's neither the beginning of the day nor the beginning of an hour but it is the start
2585 : // of a time step other than the first time step in the hour. So, the day should be the
2586 : // current day, the hour should be the current hour, and the time step should be the
2587 : // previous time step.
2588 142597 : this->lastDayOfSim = state.dataGlobal->DayOfSim;
2589 142597 : this->lastHourOfDay = state.dataGlobal->HourOfDay;
2590 142597 : this->lastTimeStep = state.dataGlobal->TimeStep - 1;
2591 : } else {
2592 : // It's not the beginning of the day, hour, or time step so the "last" value is simply the
2593 : // same as the current value. Note that these parameters only track down to the zone time
2594 : // step level and will make decisions based on that.
2595 31217 : this->lastDayOfSim = state.dataGlobal->DayOfSim;
2596 31217 : this->lastHourOfDay = state.dataGlobal->HourOfDay;
2597 31217 : this->lastTimeStep = state.dataGlobal->TimeStep;
2598 : }
2599 :
2600 : // Now go ahead and reset the operating mode (this will be set to something else if the system is running)
2601 212170 : this->OperatingMode = NotOperating;
2602 212170 : }
2603 :
2604 588544 : void HydronicSystemBaseData::setOperatingModeBasedOnChangeoverDelay(EnergyPlusData &state)
2605 : {
2606 588544 : if (this->lastOperatingMode == NotOperating)
2607 20451 : return; // this should only happen at the beginning of a simulation (at the start of warmup and the actual simulation)
2608 : // so let things proceed with whatever the system wants to do
2609 :
2610 568093 : if (this->OperatingMode == NotOperating) return; // always let it turn off
2611 :
2612 489615 : if (this->OperatingMode == this->lastOperatingMode) return; // always let it continue to operating in the same mode
2613 :
2614 8685 : if (this->schedPtrChangeoverDelay == 0) return; // user not requesting any delays (no schedule entered) so let it do whatever is requested
2615 :
2616 7426 : Real64 currentChangeoverDelay = ScheduleManager::GetCurrentScheduleValue(state, this->schedPtrChangeoverDelay);
2617 7426 : if (currentChangeoverDelay <= 0.0) return; // delay is zero so let it do whatever it requested
2618 :
2619 : // At this point, the radiant system is trying to switch modes from the previous time step, the user is requesting a delay in the changeover,
2620 : // and the requested delay is greater than zero. Calculate what the current time is in hours from the start of the simulation
2621 7426 : Real64 timeCurrent = 24.0 * float(state.dataGlobal->DayOfSim - 1) + float(state.dataGlobal->HourOfDay - 1) +
2622 7426 : float(state.dataGlobal->TimeStep - 1) / float(state.dataGlobal->NumOfTimeStepInHour);
2623 7426 : Real64 timeLast = 24.0 * float(this->lastDayOfSim - 1) + float(this->lastHourOfDay - 1) +
2624 7426 : float(this->lastTimeStep - 1) / float(state.dataGlobal->NumOfTimeStepInHour);
2625 7426 : Real64 actualTimeDifference = timeCurrent - timeLast;
2626 :
2627 : // If the time difference is not longer than the user delay, then the system should not switch modes and needs to be turned off.
2628 7426 : if (actualTimeDifference <= currentChangeoverDelay) this->OperatingMode = NotOperating;
2629 :
2630 : // Note: if the time difference is greater than the user delay request, then go ahead and keep the operating mode needed (don't do anything).
2631 : }
2632 :
2633 82 : void SizeLowTempRadiantSystem(EnergyPlusData &state,
2634 : int const RadSysNum, // Index for the low temperature radiant system under consideration within the derived types
2635 : LowTempRadiantSystem::SystemType const SystemType // Type of radiant system: hydronic, constant flow, or electric
2636 : )
2637 : {
2638 :
2639 : // SUBROUTINE INFORMATION:
2640 : // AUTHOR Fred Buhl
2641 : // DATE WRITTEN February 2002
2642 : // MODIFIED August 2013 Daeho Kang, add component sizing table entries
2643 : // August 2014 Bereket Nigusse, added scalable sizing
2644 : // March 2014 Daeho Kang, add constant flow system autosizing
2645 :
2646 : // PURPOSE OF THIS SUBROUTINE:
2647 : // This subroutine is for sizing low temperature radiant components for which flow rates
2648 : // and tube length or max electric power have not been specified in the input
2649 :
2650 : // METHODOLOGY EMPLOYED:
2651 : // Obtains flow rates from the zone sizing arrays and plant sizing data. Maximum electric
2652 : // power is set to the design heat load. Tube length is calculated by rule-of-thumb from
2653 : // the surface area.
2654 :
2655 : // Using/Aliasing
2656 : using namespace DataSizing;
2657 : using DataHVACGlobals::AutoCalculateSizing;
2658 : using DataHVACGlobals::CoolingCapacitySizing;
2659 : using DataHVACGlobals::HeatingCapacitySizing;
2660 : using FluidProperties::GetDensityGlycol;
2661 : using FluidProperties::GetSpecificHeatGlycol;
2662 :
2663 : using PlantUtilities::MyPlantSizingIndex;
2664 : using PlantUtilities::RegisterPlantCompDesignFlow;
2665 :
2666 : // SUBROUTINE PARAMETER DEFINITIONS:
2667 82 : auto constexpr RoutineName("SizeLowTempRadiantSystem");
2668 :
2669 : enum class OperatingMode
2670 : {
2671 : Invalid = -1,
2672 : OFF,
2673 : ClgHtg,
2674 : ClgOnly,
2675 : HtgOnly,
2676 : Num
2677 : };
2678 :
2679 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
2680 82 : int PltSizHeatNum(0); // index of plant sizing object for 1st heating loop
2681 82 : int PltSizCoolNum(0); // index of plant sizing object for 1st cooling loop
2682 : int SurfNum; // surface index in radiant system data structure
2683 82 : bool ErrorsFound(false); // If errors detected in input
2684 : Real64 rho;
2685 : Real64 Cp;
2686 82 : bool IsAutoSize(false); // Indicator to autosize
2687 82 : Real64 WaterVolFlowMaxHeatDes(0.0); // Design hot water flow for reproting
2688 82 : Real64 WaterVolFlowMaxHeatUser(0.0); // User hard-sized hot water flow for
2689 82 : Real64 WaterVolFlowMaxCoolDes(0.0); // Design chilled water flow for reproting
2690 82 : Real64 WaterVolFlowMaxCoolUser(0.0); // User hard-sized chilled water flow for reproting
2691 82 : Real64 TubeLengthDes(0.0); // Design tube length for reproting
2692 82 : Real64 TubeLengthUser(0.0); // User hard-sized tube length for reproting
2693 164 : std::string CompName; // component name
2694 164 : std::string CompType; // component type
2695 164 : std::string SizingString; // input field sizing description (e.g., Nominal Capacity)
2696 : Real64 TempSize; // autosized value of coil input field
2697 82 : int FieldNum = 1; // IDD numeric field number where input field description is found
2698 : int SizingMethod; // Integer representation of sizing method name (e.g. CoolingCapacitySizing, HeatingCapacitySizing)
2699 : bool PrintFlag; // TRUE when sizing information is reported in the eio file
2700 82 : int CapSizingMethod(0); // capacity sizing methods (HeatingDesignCapacity, CapacityPerFloorArea, FractionOfAutosizedCoolingCapacity, and
2701 : // FractionOfAutosizedHeatingCapacity )
2702 : Real64 DesCoilLoad; // design autosized or user specified capacity
2703 82 : OperatingMode OpMode(OperatingMode::ClgHtg); // System operating mode
2704 : int HeatNode; // Hot water inlet node to determine system operating mode
2705 : int CoolNode; // Chilled water inlet node to determine system operating mode
2706 : Real64 WaterVolFlowMaxDes; // Design water volume flow rate for reproting
2707 : Real64 WaterVolFlowMaxUser; // User hard-sized water volume flow rate for reproting
2708 :
2709 82 : auto &ZoneEqSizing(state.dataSize->ZoneEqSizing);
2710 :
2711 82 : DesCoilLoad = 0.0;
2712 82 : state.dataSize->DataScalableCapSizingON = false;
2713 82 : state.dataSize->DataFracOfAutosizedHeatingCapacity = 1.0;
2714 :
2715 82 : auto &Zone(state.dataHeatBal->Zone);
2716 :
2717 82 : if (SystemType == LowTempRadiantSystem::SystemType::ElectricSystem) {
2718 :
2719 9 : if (state.dataLowTempRadSys->ElecRadSys(RadSysNum).MaxElecPower == AutoSize) {
2720 2 : IsAutoSize = true;
2721 : }
2722 :
2723 9 : if (state.dataSize->CurZoneEqNum > 0) {
2724 :
2725 9 : CompType = "ZoneHVAC:LowTemperatureRadiant:Electric";
2726 9 : CompName = state.dataLowTempRadSys->ElecRadSys(RadSysNum).Name;
2727 9 : SizingMethod = HeatingCapacitySizing;
2728 9 : FieldNum = 1;
2729 9 : PrintFlag = true;
2730 9 : SizingString = state.dataLowTempRadSys->ElecRadSysNumericFields(RadSysNum).FieldNames(FieldNum) + " [W]";
2731 9 : CapSizingMethod = state.dataLowTempRadSys->ElecRadSys(RadSysNum).HeatingCapMethod;
2732 9 : ZoneEqSizing(state.dataSize->CurZoneEqNum).SizingMethod(SizingMethod) = CapSizingMethod;
2733 :
2734 9 : if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) { // simulation continue
2735 3 : if (CapSizingMethod == HeatingDesignCapacity && state.dataLowTempRadSys->ElecRadSys(RadSysNum).ScaledHeatingCapacity > 0.0) {
2736 3 : TempSize = state.dataLowTempRadSys->ElecRadSys(RadSysNum).ScaledHeatingCapacity;
2737 3 : bool errorsFound = false;
2738 6 : HeatingCapacitySizer sizerHeatingCapacity;
2739 3 : sizerHeatingCapacity.overrideSizingString(SizingString);
2740 3 : sizerHeatingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
2741 3 : DesCoilLoad = sizerHeatingCapacity.size(state, TempSize, errorsFound);
2742 0 : } else if (CapSizingMethod == CapacityPerFloorArea) {
2743 0 : state.dataSize->DataScalableCapSizingON = true;
2744 0 : TempSize = state.dataLowTempRadSys->ElecRadSys(RadSysNum).ScaledHeatingCapacity *
2745 0 : Zone(state.dataLowTempRadSys->ElecRadSys(RadSysNum).ZonePtr).FloorArea;
2746 0 : bool errorsFound = false;
2747 0 : HeatingCapacitySizer sizerHeatingCapacity;
2748 0 : sizerHeatingCapacity.overrideSizingString(SizingString);
2749 0 : sizerHeatingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
2750 0 : DesCoilLoad = sizerHeatingCapacity.size(state, TempSize, errorsFound);
2751 0 : state.dataSize->DataScalableCapSizingON = false;
2752 0 : state.dataLowTempRadSys->ElecRadSys(RadSysNum).MaxElecPower = TempSize;
2753 0 : } else if (CapSizingMethod == FractionOfAutosizedHeatingCapacity) {
2754 0 : ShowSevereError(state,
2755 0 : format("{}: auto-sizing cannot be done for {} = {}\".",
2756 : RoutineName,
2757 : CompType,
2758 0 : state.dataLowTempRadSys->ElecRadSys(RadSysNum).Name));
2759 0 : ShowContinueError(state,
2760 : "The \"SimulationControl\" object must have the field \"Do Zone Sizing Calculation\" set to Yes when the "
2761 : "Heating Design Capacity Method = \"FractionOfAutosizedHeatingCapacity\".");
2762 0 : ErrorsFound = true;
2763 : }
2764 : } else {
2765 6 : if (CapSizingMethod == HeatingDesignCapacity || CapSizingMethod == CapacityPerFloorArea ||
2766 : CapSizingMethod == FractionOfAutosizedHeatingCapacity) {
2767 6 : if (CapSizingMethod == HeatingDesignCapacity) {
2768 2 : if (state.dataSize->ZoneSizingRunDone) {
2769 2 : CheckZoneSizing(state, CompType, CompName);
2770 2 : SizingMethod = AutoCalculateSizing;
2771 2 : state.dataSize->DataConstantUsedForSizing =
2772 2 : state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).NonAirSysDesHeatLoad;
2773 2 : state.dataSize->DataFractionUsedForSizing = 1.0;
2774 : }
2775 2 : if (state.dataLowTempRadSys->ElecRadSys(RadSysNum).ScaledHeatingCapacity == AutoSize) {
2776 2 : TempSize = AutoSize;
2777 : } else {
2778 0 : TempSize = state.dataLowTempRadSys->ElecRadSys(RadSysNum).ScaledHeatingCapacity;
2779 : }
2780 4 : } else if (CapSizingMethod == CapacityPerFloorArea) {
2781 2 : if (state.dataSize->ZoneSizingRunDone) {
2782 2 : CheckZoneSizing(state, CompType, CompName);
2783 2 : ZoneEqSizing(state.dataSize->CurZoneEqNum).HeatingCapacity = true;
2784 2 : ZoneEqSizing(state.dataSize->CurZoneEqNum).DesHeatingLoad =
2785 2 : state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).NonAirSysDesHeatLoad;
2786 : }
2787 4 : TempSize = state.dataLowTempRadSys->ElecRadSys(RadSysNum).ScaledHeatingCapacity *
2788 2 : Zone(state.dataLowTempRadSys->ElecRadSys(RadSysNum).ZonePtr).FloorArea;
2789 2 : state.dataSize->DataScalableCapSizingON = true;
2790 :
2791 2 : } else if (CapSizingMethod == FractionOfAutosizedHeatingCapacity) {
2792 2 : CheckZoneSizing(state, CompType, CompName);
2793 2 : ZoneEqSizing(state.dataSize->CurZoneEqNum).HeatingCapacity = true;
2794 2 : ZoneEqSizing(state.dataSize->CurZoneEqNum).DesHeatingLoad =
2795 2 : state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).NonAirSysDesHeatLoad;
2796 4 : TempSize = ZoneEqSizing(state.dataSize->CurZoneEqNum).DesHeatingLoad *
2797 2 : state.dataLowTempRadSys->ElecRadSys(RadSysNum).ScaledHeatingCapacity;
2798 2 : state.dataSize->DataScalableCapSizingON = true;
2799 : } else {
2800 0 : TempSize = state.dataLowTempRadSys->ElecRadSys(RadSysNum).ScaledHeatingCapacity;
2801 : }
2802 12 : HeatingCapacitySizer sizerHeatingCapacity;
2803 6 : sizerHeatingCapacity.overrideSizingString(SizingString);
2804 6 : sizerHeatingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
2805 6 : state.dataLowTempRadSys->ElecRadSys(RadSysNum).MaxElecPower = sizerHeatingCapacity.size(state, TempSize, ErrorsFound);
2806 6 : state.dataSize->DataConstantUsedForSizing = 0.0;
2807 6 : state.dataSize->DataFractionUsedForSizing = 0.0;
2808 6 : state.dataSize->DataScalableCapSizingON = false;
2809 : }
2810 : }
2811 : }
2812 : }
2813 :
2814 82 : if (SystemType == LowTempRadiantSystem::SystemType::HydronicSystem) {
2815 :
2816 46 : CompType = "ZoneHVAC:LowTemperatureRadiant:VariableFlow";
2817 46 : CompName = state.dataLowTempRadSys->HydrRadSys(RadSysNum).Name;
2818 :
2819 46 : IsAutoSize = false;
2820 46 : if (state.dataLowTempRadSys->HydrRadSys(RadSysNum).ScaledHeatingCapacity == AutoSize) {
2821 44 : IsAutoSize = true;
2822 : }
2823 :
2824 46 : if (state.dataSize->CurZoneEqNum > 0) {
2825 :
2826 46 : SizingMethod = HeatingCapacitySizing;
2827 46 : FieldNum = 2;
2828 46 : PrintFlag = true;
2829 46 : SizingString = state.dataLowTempRadSys->HydronicRadiantSysNumericFields(RadSysNum).FieldNames(FieldNum) + " [W]";
2830 46 : CapSizingMethod = state.dataLowTempRadSys->HydrRadSys(RadSysNum).HeatingCapMethod;
2831 46 : ZoneEqSizing(state.dataSize->CurZoneEqNum).SizingMethod(SizingMethod) = CapSizingMethod;
2832 :
2833 46 : if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) { // simulation continue
2834 0 : if (CapSizingMethod == HeatingDesignCapacity && state.dataLowTempRadSys->HydrRadSys(RadSysNum).ScaledHeatingCapacity > 0.0) {
2835 0 : TempSize = state.dataLowTempRadSys->HydrRadSys(RadSysNum).ScaledHeatingCapacity;
2836 0 : bool errorsFound = false;
2837 0 : HeatingCapacitySizer sizerHeatingCapacity;
2838 0 : sizerHeatingCapacity.overrideSizingString(SizingString);
2839 0 : sizerHeatingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
2840 0 : DesCoilLoad = sizerHeatingCapacity.size(state, TempSize, errorsFound);
2841 0 : } else if (CapSizingMethod == CapacityPerFloorArea) {
2842 0 : state.dataSize->DataScalableCapSizingON = true;
2843 0 : TempSize = state.dataLowTempRadSys->HydrRadSys(RadSysNum).ScaledHeatingCapacity *
2844 0 : Zone(state.dataLowTempRadSys->HydrRadSys(RadSysNum).ZonePtr).FloorArea;
2845 0 : HeatingCapacitySizer sizerHeatingCapacity;
2846 0 : sizerHeatingCapacity.overrideSizingString(SizingString);
2847 0 : sizerHeatingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
2848 0 : DesCoilLoad = sizerHeatingCapacity.size(state, TempSize, ErrorsFound);
2849 0 : state.dataSize->DataScalableCapSizingON = false;
2850 0 : } else if (CapSizingMethod == FractionOfAutosizedHeatingCapacity) {
2851 0 : if (state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterVolFlowMaxHeat == AutoSize) {
2852 0 : ShowSevereError(state,
2853 0 : format("{}: auto-sizing cannot be done for {} = {}\".",
2854 : RoutineName,
2855 : CompType,
2856 0 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).Name));
2857 0 : ShowContinueError(state,
2858 : "The \"SimulationControl\" object must have the field \"Do Zone Sizing Calculation\" set to Yes when "
2859 : "the Heating Design Capacity Method = \"FractionOfAutosizedHeatingCapacity\".");
2860 0 : ErrorsFound = true;
2861 : }
2862 : }
2863 : } else { // Autosize or hard-size with sizing run
2864 46 : if (CapSizingMethod == HeatingDesignCapacity || CapSizingMethod == CapacityPerFloorArea ||
2865 : CapSizingMethod == FractionOfAutosizedHeatingCapacity) {
2866 46 : if (CapSizingMethod == HeatingDesignCapacity) {
2867 44 : if (state.dataSize->ZoneSizingRunDone) {
2868 44 : CheckZoneSizing(state, CompType, CompName);
2869 44 : SizingMethod = AutoCalculateSizing;
2870 44 : state.dataSize->DataConstantUsedForSizing =
2871 44 : state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).NonAirSysDesHeatLoad;
2872 44 : state.dataSize->DataFractionUsedForSizing = 1.0;
2873 : }
2874 44 : if (state.dataLowTempRadSys->HydrRadSys(RadSysNum).ScaledHeatingCapacity == AutoSize) {
2875 44 : TempSize = AutoSize;
2876 : } else {
2877 0 : TempSize = state.dataLowTempRadSys->HydrRadSys(RadSysNum).ScaledHeatingCapacity;
2878 : }
2879 2 : } else if (CapSizingMethod == CapacityPerFloorArea) {
2880 1 : if (state.dataSize->ZoneSizingRunDone) {
2881 1 : CheckZoneSizing(state, CompType, CompName);
2882 1 : ZoneEqSizing(state.dataSize->CurZoneEqNum).HeatingCapacity = true;
2883 1 : ZoneEqSizing(state.dataSize->CurZoneEqNum).DesHeatingLoad =
2884 1 : state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).NonAirSysDesHeatLoad;
2885 : }
2886 2 : TempSize = state.dataLowTempRadSys->HydrRadSys(RadSysNum).ScaledHeatingCapacity *
2887 1 : Zone(state.dataLowTempRadSys->HydrRadSys(RadSysNum).ZonePtr).FloorArea;
2888 1 : state.dataSize->DataScalableCapSizingON = true;
2889 1 : } else if (CapSizingMethod == FractionOfAutosizedHeatingCapacity) {
2890 1 : CheckZoneSizing(state, CompType, CompName);
2891 1 : ZoneEqSizing(state.dataSize->CurZoneEqNum).HeatingCapacity = true;
2892 1 : ZoneEqSizing(state.dataSize->CurZoneEqNum).DesHeatingLoad =
2893 1 : state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).NonAirSysDesHeatLoad;
2894 2 : TempSize = ZoneEqSizing(state.dataSize->CurZoneEqNum).DesHeatingLoad *
2895 1 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).ScaledHeatingCapacity;
2896 1 : state.dataSize->DataScalableCapSizingON = true;
2897 : } else {
2898 0 : TempSize = state.dataLowTempRadSys->HydrRadSys(RadSysNum).ScaledHeatingCapacity;
2899 : }
2900 92 : HeatingCapacitySizer sizerHeatingCapacity;
2901 46 : sizerHeatingCapacity.overrideSizingString(SizingString);
2902 46 : sizerHeatingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
2903 46 : DesCoilLoad = sizerHeatingCapacity.size(state, TempSize, ErrorsFound);
2904 46 : state.dataSize->DataConstantUsedForSizing = 0.0;
2905 46 : state.dataSize->DataFractionUsedForSizing = 0.0;
2906 92 : state.dataSize->DataScalableCapSizingON = false;
2907 : } else {
2908 0 : DesCoilLoad = 0.0;
2909 : }
2910 : }
2911 : // finally heating capacity is saved in this variable
2912 46 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).ScaledHeatingCapacity = DesCoilLoad;
2913 : }
2914 :
2915 46 : IsAutoSize = false;
2916 46 : if (state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterVolFlowMaxHeat == AutoSize) {
2917 6 : IsAutoSize = true;
2918 : }
2919 :
2920 46 : if (state.dataSize->CurZoneEqNum > 0) {
2921 46 : if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) { // simulation continue
2922 0 : if (state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterVolFlowMaxHeat > 0.0) {
2923 0 : BaseSizer::reportSizerOutput(state,
2924 : CompType,
2925 0 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).Name,
2926 : "User-Specified Maximum Hot Water Flow [m3/s]",
2927 0 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterVolFlowMaxHeat);
2928 : }
2929 : } else { // Autosize or hard-size with sizing run
2930 92 : if (state.dataLowTempRadSys->HydrRadSys(RadSysNum).HotWaterInNode > 0 &&
2931 46 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).HotWaterOutNode > 0) {
2932 184 : PltSizHeatNum = MyPlantSizingIndex(state,
2933 : CompType,
2934 46 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).Name,
2935 46 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).HotWaterInNode,
2936 46 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).HotWaterOutNode,
2937 : ErrorsFound);
2938 46 : if (PltSizHeatNum > 0) {
2939 46 : if (DesCoilLoad >= SmallLoad) {
2940 86 : rho = GetDensityGlycol(
2941 : state,
2942 43 : state.dataPlnt->PlantLoop(state.dataLowTempRadSys->HydrRadSys(RadSysNum).HWPlantLoc.loopNum).FluidName,
2943 : DataGlobalConstants::HWInitConvTemp,
2944 43 : state.dataPlnt->PlantLoop(state.dataLowTempRadSys->HydrRadSys(RadSysNum).HWPlantLoc.loopNum).FluidIndex,
2945 43 : RoutineName);
2946 86 : Cp = GetSpecificHeatGlycol(
2947 : state,
2948 43 : state.dataPlnt->PlantLoop(state.dataLowTempRadSys->HydrRadSys(RadSysNum).HWPlantLoc.loopNum).FluidName,
2949 : DataGlobalConstants::HWInitConvTemp,
2950 43 : state.dataPlnt->PlantLoop(state.dataLowTempRadSys->HydrRadSys(RadSysNum).HWPlantLoc.loopNum).FluidIndex,
2951 43 : RoutineName);
2952 43 : WaterVolFlowMaxHeatDes = DesCoilLoad / (state.dataSize->PlantSizData(PltSizHeatNum).DeltaT * Cp * rho);
2953 : } else {
2954 3 : WaterVolFlowMaxHeatDes = 0.0;
2955 : }
2956 : } else {
2957 0 : ShowSevereError(state, "Autosizing of water flow requires a heating loop Sizing:Plant object");
2958 0 : ShowContinueError(state,
2959 0 : "Occurs in ZoneHVAC:LowTemperatureRadiant:VariableFlow Object=" +
2960 0 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).Name);
2961 0 : ErrorsFound = true;
2962 : }
2963 : }
2964 :
2965 46 : if (IsAutoSize) {
2966 6 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterVolFlowMaxHeat = WaterVolFlowMaxHeatDes;
2967 12 : BaseSizer::reportSizerOutput(state,
2968 : CompType,
2969 6 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).Name,
2970 : "Design Size Maximum Hot Water Flow [m3/s]",
2971 6 : WaterVolFlowMaxHeatDes);
2972 : } else { // hard-size with sizing data
2973 40 : if (state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterVolFlowMaxHeat > 0.0 && WaterVolFlowMaxHeatDes > 0.0) {
2974 37 : WaterVolFlowMaxHeatUser = state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterVolFlowMaxHeat;
2975 74 : BaseSizer::reportSizerOutput(state,
2976 : CompType,
2977 37 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).Name,
2978 : "Design Size Maximum Hot Water Flow [m3/s]",
2979 : WaterVolFlowMaxHeatDes,
2980 : "User-Specified Maximum Hot Water Flow [m3/s]",
2981 37 : WaterVolFlowMaxHeatUser);
2982 37 : if (state.dataGlobal->DisplayExtraWarnings) {
2983 0 : if ((std::abs(WaterVolFlowMaxHeatDes - WaterVolFlowMaxHeatUser) / WaterVolFlowMaxHeatUser) >
2984 0 : state.dataSize->AutoVsHardSizingThreshold) {
2985 0 : ShowMessage(state,
2986 : "SizeLowTempRadiantSystem: Potential issue with equipment sizing for "
2987 0 : "ZoneHVAC:LowTemperatureRadiant:VariableFlow = \"" +
2988 0 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).Name + "\".");
2989 0 : ShowContinueError(state,
2990 0 : format("User-Specified Maximum Hot Water Flow of {:.5R} [m3/s]", WaterVolFlowMaxHeatUser));
2991 0 : ShowContinueError(
2992 0 : state, format("differs from Design Size Maximum Hot Water Flow of {:.5R} [m3/s]", WaterVolFlowMaxHeatDes));
2993 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
2994 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
2995 : }
2996 : }
2997 : }
2998 : }
2999 : }
3000 : }
3001 :
3002 46 : IsAutoSize = false;
3003 46 : if (state.dataLowTempRadSys->HydrRadSys(RadSysNum).ScaledCoolingCapacity == AutoSize) {
3004 44 : IsAutoSize = true;
3005 : }
3006 :
3007 46 : if (state.dataSize->CurZoneEqNum > 0) {
3008 :
3009 46 : SizingMethod = CoolingCapacitySizing;
3010 46 : FieldNum = 4;
3011 46 : PrintFlag = true;
3012 46 : SizingString = state.dataLowTempRadSys->HydronicRadiantSysNumericFields(RadSysNum).FieldNames(FieldNum) + " [W]";
3013 46 : CapSizingMethod = state.dataLowTempRadSys->HydrRadSys(RadSysNum).CoolingCapMethod;
3014 46 : ZoneEqSizing(state.dataSize->CurZoneEqNum).SizingMethod(SizingMethod) = CapSizingMethod;
3015 :
3016 46 : if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) { // simulation continue
3017 0 : if (CapSizingMethod == CoolingDesignCapacity && state.dataLowTempRadSys->HydrRadSys(RadSysNum).ScaledCoolingCapacity > 0.0) {
3018 0 : TempSize = state.dataLowTempRadSys->HydrRadSys(RadSysNum).ScaledCoolingCapacity;
3019 0 : CoolingCapacitySizer sizerCoolingCapacity;
3020 0 : sizerCoolingCapacity.overrideSizingString(SizingString);
3021 0 : sizerCoolingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
3022 0 : DesCoilLoad = sizerCoolingCapacity.size(state, TempSize, ErrorsFound);
3023 0 : } else if (CapSizingMethod == CapacityPerFloorArea) {
3024 0 : state.dataSize->DataScalableCapSizingON = true;
3025 0 : TempSize = state.dataLowTempRadSys->HydrRadSys(RadSysNum).ScaledCoolingCapacity *
3026 0 : Zone(state.dataLowTempRadSys->HydrRadSys(RadSysNum).ZonePtr).FloorArea;
3027 0 : CoolingCapacitySizer sizerCoolingCapacity;
3028 0 : sizerCoolingCapacity.overrideSizingString(SizingString);
3029 0 : sizerCoolingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
3030 0 : DesCoilLoad = sizerCoolingCapacity.size(state, TempSize, ErrorsFound);
3031 0 : state.dataSize->DataScalableCapSizingON = false;
3032 0 : } else if (CapSizingMethod == FractionOfAutosizedCoolingCapacity) {
3033 0 : if (state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterVolFlowMaxCool == AutoSize) {
3034 0 : ShowSevereError(state,
3035 0 : format("{}: auto-sizing cannot be done for {} = {}\".",
3036 : RoutineName,
3037 : CompType,
3038 0 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).Name));
3039 0 : ShowContinueError(state,
3040 : "The \"SimulationControl\" object must have the field \"Do Zone Sizing Calculation\" set to Yes when "
3041 : "the Cooling Design Capacity Method = \"FractionOfAutosizedCoolingCapacity\".");
3042 0 : ErrorsFound = true;
3043 : }
3044 : }
3045 : } else { // Autosize or hard-size with sizing run
3046 46 : if (CapSizingMethod == CoolingDesignCapacity || CapSizingMethod == CapacityPerFloorArea ||
3047 : CapSizingMethod == FractionOfAutosizedCoolingCapacity) {
3048 46 : if (CapSizingMethod == CoolingDesignCapacity) {
3049 44 : if (state.dataSize->ZoneSizingRunDone) {
3050 44 : CheckZoneSizing(state, CompType, CompName);
3051 44 : SizingMethod = AutoCalculateSizing;
3052 44 : state.dataSize->DataConstantUsedForSizing =
3053 44 : state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).NonAirSysDesCoolLoad;
3054 44 : state.dataSize->DataFractionUsedForSizing = 1.0;
3055 : }
3056 44 : if (state.dataLowTempRadSys->HydrRadSys(RadSysNum).ScaledCoolingCapacity == AutoSize) {
3057 44 : TempSize = AutoSize;
3058 : } else {
3059 0 : TempSize = state.dataLowTempRadSys->HydrRadSys(RadSysNum).ScaledCoolingCapacity;
3060 : }
3061 2 : } else if (CapSizingMethod == CapacityPerFloorArea) {
3062 1 : if (state.dataSize->ZoneSizingRunDone) {
3063 1 : CheckZoneSizing(state, CompType, CompName);
3064 1 : ZoneEqSizing(state.dataSize->CurZoneEqNum).CoolingCapacity = true;
3065 1 : ZoneEqSizing(state.dataSize->CurZoneEqNum).DesCoolingLoad =
3066 1 : state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).NonAirSysDesCoolLoad;
3067 : }
3068 2 : TempSize = state.dataLowTempRadSys->HydrRadSys(RadSysNum).ScaledCoolingCapacity *
3069 1 : Zone(state.dataLowTempRadSys->HydrRadSys(RadSysNum).ZonePtr).FloorArea;
3070 1 : state.dataSize->DataScalableCapSizingON = true;
3071 1 : } else if (CapSizingMethod == FractionOfAutosizedCoolingCapacity) {
3072 1 : CheckZoneSizing(state, CompType, CompName);
3073 1 : ZoneEqSizing(state.dataSize->CurZoneEqNum).CoolingCapacity = true;
3074 1 : ZoneEqSizing(state.dataSize->CurZoneEqNum).DesCoolingLoad =
3075 1 : state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).NonAirSysDesCoolLoad;
3076 2 : TempSize = ZoneEqSizing(state.dataSize->CurZoneEqNum).DesCoolingLoad *
3077 1 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).ScaledCoolingCapacity;
3078 1 : state.dataSize->DataScalableCapSizingON = true;
3079 :
3080 : } else {
3081 0 : TempSize = state.dataLowTempRadSys->HydrRadSys(RadSysNum).ScaledCoolingCapacity;
3082 : }
3083 92 : CoolingCapacitySizer sizerCoolingCapacity;
3084 46 : sizerCoolingCapacity.overrideSizingString(SizingString);
3085 46 : sizerCoolingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
3086 46 : DesCoilLoad = sizerCoolingCapacity.size(state, TempSize, ErrorsFound);
3087 46 : state.dataSize->DataConstantUsedForSizing = 0.0;
3088 46 : state.dataSize->DataFractionUsedForSizing = 0.0;
3089 92 : state.dataSize->DataScalableCapSizingON = false;
3090 : } else {
3091 0 : DesCoilLoad = 0.0;
3092 : }
3093 : }
3094 : // finally cooling capacity is saved in this variable
3095 46 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).ScaledCoolingCapacity = DesCoilLoad;
3096 : }
3097 :
3098 46 : IsAutoSize = false;
3099 46 : if (state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterVolFlowMaxCool == AutoSize) {
3100 6 : IsAutoSize = true;
3101 : }
3102 46 : if (state.dataSize->CurZoneEqNum > 0) {
3103 46 : if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) { // simulation continue
3104 0 : if (state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterVolFlowMaxCool > 0.0) {
3105 0 : BaseSizer::reportSizerOutput(state,
3106 : CompType,
3107 0 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).Name,
3108 : "User-Specified Maximum Cold Water Flow [m3/s]",
3109 0 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterVolFlowMaxCool);
3110 : }
3111 : } else { // Autosize or hard-size with sizing run
3112 89 : if (state.dataLowTempRadSys->HydrRadSys(RadSysNum).ColdWaterInNode > 0 &&
3113 43 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).ColdWaterOutNode > 0) {
3114 172 : PltSizCoolNum = MyPlantSizingIndex(state,
3115 : CompType,
3116 43 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).Name,
3117 43 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).ColdWaterInNode,
3118 43 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).ColdWaterOutNode,
3119 : ErrorsFound);
3120 43 : if (PltSizCoolNum > 0) {
3121 43 : if (DesCoilLoad >= SmallLoad) {
3122 80 : rho = GetDensityGlycol(
3123 : state,
3124 40 : state.dataPlnt->PlantLoop(state.dataLowTempRadSys->HydrRadSys(RadSysNum).CWPlantLoc.loopNum).FluidName,
3125 : DataGlobalConstants::CWInitConvTemp,
3126 40 : state.dataPlnt->PlantLoop(state.dataLowTempRadSys->HydrRadSys(RadSysNum).CWPlantLoc.loopNum).FluidIndex,
3127 40 : RoutineName);
3128 80 : Cp = GetSpecificHeatGlycol(
3129 : state,
3130 40 : state.dataPlnt->PlantLoop(state.dataLowTempRadSys->HydrRadSys(RadSysNum).CWPlantLoc.loopNum).FluidName,
3131 : DataGlobalConstants::CWInitConvTemp,
3132 40 : state.dataPlnt->PlantLoop(state.dataLowTempRadSys->HydrRadSys(RadSysNum).CWPlantLoc.loopNum).FluidIndex,
3133 40 : RoutineName);
3134 40 : WaterVolFlowMaxCoolDes = DesCoilLoad / (state.dataSize->PlantSizData(PltSizCoolNum).DeltaT * Cp * rho);
3135 : } else {
3136 3 : WaterVolFlowMaxCoolDes = 0.0;
3137 : }
3138 : } else {
3139 0 : ShowSevereError(state, "Autosizing of water flow requires a cooling loop Sizing:Plant object");
3140 0 : ShowContinueError(state,
3141 0 : "Occurs in ZoneHVAC:LowTemperatureRadiant:VariableFlow Object=" +
3142 0 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).Name);
3143 0 : ErrorsFound = true;
3144 : }
3145 : }
3146 :
3147 46 : if (IsAutoSize) {
3148 6 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterVolFlowMaxCool = WaterVolFlowMaxCoolDes;
3149 12 : BaseSizer::reportSizerOutput(state,
3150 : CompType,
3151 6 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).Name,
3152 : "Design Size Maximum Cold Water Flow [m3/s]",
3153 6 : WaterVolFlowMaxCoolDes);
3154 : } else { // hard-size with sizing data
3155 40 : if (state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterVolFlowMaxCool > 0.0 && WaterVolFlowMaxCoolDes > 0.0) {
3156 34 : WaterVolFlowMaxCoolUser = state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterVolFlowMaxCool;
3157 68 : BaseSizer::reportSizerOutput(state,
3158 : CompType,
3159 34 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).Name,
3160 : "Design Size Maximum Cold Water Flow [m3/s]",
3161 : WaterVolFlowMaxCoolDes,
3162 : "User-Specified Maximum Cold Water Flow [m3/s]",
3163 34 : WaterVolFlowMaxCoolUser);
3164 34 : if (state.dataGlobal->DisplayExtraWarnings) {
3165 0 : if ((std::abs(WaterVolFlowMaxCoolDes - WaterVolFlowMaxCoolUser) / WaterVolFlowMaxCoolUser) >
3166 0 : state.dataSize->AutoVsHardSizingThreshold) {
3167 0 : ShowMessage(state,
3168 : "SizeLowTempRadiantSystem: Potential issue with equipment sizing for "
3169 0 : "ZoneHVAC:LowTemperatureRadiant:VariableFlow = \"" +
3170 0 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).Name + "\".");
3171 0 : ShowContinueError(state,
3172 0 : format("User-Specified Maximum Cool Water Flow of {:.5R} [m3/s]", WaterVolFlowMaxCoolUser));
3173 0 : ShowContinueError(
3174 0 : state, format("differs from Design Size Maximum Cool Water Flow of {:.5R} [m3/s]", WaterVolFlowMaxCoolDes));
3175 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
3176 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
3177 : }
3178 : }
3179 : }
3180 : }
3181 : }
3182 : }
3183 :
3184 46 : IsAutoSize = false;
3185 46 : if (state.dataLowTempRadSys->HydrRadSys(RadSysNum).TubeLength == AutoSize) {
3186 6 : IsAutoSize = true;
3187 : }
3188 46 : if (state.dataSize->CurZoneEqNum > 0) {
3189 46 : if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) { // simulation continue
3190 0 : if (state.dataLowTempRadSys->HydrRadSys(RadSysNum).TubeLength > 0.0) {
3191 0 : BaseSizer::reportSizerOutput(state,
3192 : CompType,
3193 0 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).Name,
3194 : "User-Specified Hydronic Tubing Length [m]",
3195 0 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).TubeLength);
3196 : }
3197 : } else { // Autosize or hard-size with sizing run
3198 : // CheckZoneSizing is not required here because the tube length calculation is not dependent on zone sizing calculation results
3199 46 : TubeLengthDes = state.dataLowTempRadSys->HydrRadSys(RadSysNum).sizeRadiantSystemTubeLength(state);
3200 46 : if (IsAutoSize) {
3201 6 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).TubeLength = TubeLengthDes;
3202 12 : BaseSizer::reportSizerOutput(state,
3203 : CompType,
3204 6 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).Name,
3205 : "Design Size Hydronic Tubing Length [m]",
3206 6 : TubeLengthDes);
3207 : } else { // hard-size with sizing data
3208 40 : if (state.dataLowTempRadSys->HydrRadSys(RadSysNum).TubeLength > 0.0 && TubeLengthDes > 0.0) {
3209 40 : TubeLengthUser = state.dataLowTempRadSys->HydrRadSys(RadSysNum).TubeLength;
3210 80 : BaseSizer::reportSizerOutput(state,
3211 : CompType,
3212 40 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).Name,
3213 : "Design Size Hydronic Tubing Length [m]",
3214 : TubeLengthDes,
3215 : "User-Specified Hydronic Tubing Length [m]",
3216 40 : TubeLengthUser);
3217 40 : if (state.dataGlobal->DisplayExtraWarnings) {
3218 0 : if ((std::abs(TubeLengthDes - TubeLengthUser) / TubeLengthUser) > state.dataSize->AutoVsHardSizingThreshold) {
3219 0 : ShowMessage(state,
3220 : "SizeLowTempRadiantSystem: Potential issue with equipment sizing for "
3221 0 : "ZoneHVAC:LowTemperatureRadiant:VariableFlow = \"" +
3222 0 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).Name + "\".");
3223 0 : ShowContinueError(state, format("User-Specified Hydronic Tubing Length of {:.5R} [m]", TubeLengthUser));
3224 0 : ShowContinueError(state, format("differs from Design Size Hydronic Tubing Length of {:.5R} [m]", TubeLengthDes));
3225 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
3226 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
3227 : }
3228 : }
3229 : }
3230 : }
3231 : }
3232 : }
3233 :
3234 104 : for (SurfNum = 1; SurfNum <= state.dataLowTempRadSys->HydrRadSys(RadSysNum).NumOfSurfaces; ++SurfNum) {
3235 58 : if (state.dataLowTempRadSys->HydrRadSys(RadSysNum).NumCircCalcMethod == CircuitCalc::CalculateFromLength) {
3236 0 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).NumCircuits(SurfNum) =
3237 0 : (state.dataLowTempRadSys->HydrRadSys(RadSysNum).SurfaceFrac(SurfNum) *
3238 0 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).TubeLength) /
3239 0 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).CircLength;
3240 0 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).NumCircuits(SurfNum) =
3241 0 : max(state.dataLowTempRadSys->HydrRadSys(RadSysNum).NumCircuits(SurfNum), 1.0);
3242 : } else {
3243 58 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).NumCircuits(SurfNum) = 1.0;
3244 : }
3245 : }
3246 :
3247 92 : RegisterPlantCompDesignFlow(state,
3248 46 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).HotWaterInNode,
3249 46 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterVolFlowMaxHeat);
3250 92 : RegisterPlantCompDesignFlow(state,
3251 46 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).ColdWaterInNode,
3252 46 : state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterVolFlowMaxCool);
3253 : }
3254 :
3255 82 : if (SystemType == LowTempRadiantSystem::SystemType::ConstantFlowSystem) {
3256 :
3257 27 : CompType = "ZoneHVAC:LowTemperatureRadiant:ConstantFlow";
3258 27 : CompName = state.dataLowTempRadSys->CFloRadSys(RadSysNum).Name;
3259 :
3260 : // Check which operating system it is
3261 27 : HeatNode = state.dataLowTempRadSys->CFloRadSys(RadSysNum).HotWaterInNode;
3262 27 : CoolNode = state.dataLowTempRadSys->CFloRadSys(RadSysNum).ColdWaterInNode;
3263 27 : if (HeatNode > 0 && CoolNode > 0) {
3264 24 : OpMode = OperatingMode::ClgHtg;
3265 3 : } else if (HeatNode > 0 && CoolNode <= 0) {
3266 3 : OpMode = OperatingMode::HtgOnly;
3267 0 : } else if (CoolNode > 0 && HeatNode <= 0) {
3268 0 : OpMode = OperatingMode::ClgOnly;
3269 : } else {
3270 0 : OpMode = OperatingMode::OFF; // It shouldn't happen here
3271 : }
3272 :
3273 27 : if (state.dataLowTempRadSys->CFloRadSys(RadSysNum).WaterVolFlowMax == AutoSize) {
3274 1 : IsAutoSize = true;
3275 : }
3276 :
3277 27 : if (state.dataSize->CurZoneEqNum > 0) {
3278 27 : if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) { // simulation continue
3279 24 : if (state.dataLowTempRadSys->CFloRadSys(RadSysNum).WaterVolFlowMax > 0.0) {
3280 72 : BaseSizer::reportSizerOutput(state,
3281 : CompType,
3282 24 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).Name,
3283 : "User-Specified Maximum Water Flow [m3/s]",
3284 48 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).WaterVolFlowMax);
3285 : }
3286 : } else { // Autosize or hard-size with sizing run
3287 3 : CheckZoneSizing(state, CompType, state.dataLowTempRadSys->CFloRadSys(RadSysNum).Name);
3288 : // Estimate hot water and chilled water flows
3289 : // Index only if it provides heating to avoid severe error
3290 3 : if (OpMode == OperatingMode::ClgHtg || OpMode == OperatingMode::HtgOnly) {
3291 12 : PltSizHeatNum = MyPlantSizingIndex(state,
3292 : CompType,
3293 3 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).Name,
3294 3 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).HotWaterInNode,
3295 3 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).HotWaterOutNode,
3296 : ErrorsFound);
3297 : }
3298 3 : if (PltSizHeatNum > 0) {
3299 3 : if (state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).NonAirSysDesHeatLoad >= SmallLoad) {
3300 6 : rho = GetDensityGlycol(
3301 : state,
3302 3 : state.dataPlnt->PlantLoop(state.dataLowTempRadSys->CFloRadSys(RadSysNum).HWPlantLoc.loopNum).FluidName,
3303 : DataGlobalConstants::HWInitConvTemp,
3304 3 : state.dataPlnt->PlantLoop(state.dataLowTempRadSys->CFloRadSys(RadSysNum).HWPlantLoc.loopNum).FluidIndex,
3305 3 : "SizeLowTempRadiantSystem");
3306 6 : Cp = GetSpecificHeatGlycol(
3307 : state,
3308 3 : state.dataPlnt->PlantLoop(state.dataLowTempRadSys->CFloRadSys(RadSysNum).HWPlantLoc.loopNum).FluidName,
3309 : DataGlobalConstants::HWInitConvTemp,
3310 3 : state.dataPlnt->PlantLoop(state.dataLowTempRadSys->CFloRadSys(RadSysNum).HWPlantLoc.loopNum).FluidIndex,
3311 3 : "SizeLowTempRadiantSystem");
3312 6 : WaterVolFlowMaxHeatDes = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).NonAirSysDesHeatLoad /
3313 3 : (state.dataSize->PlantSizData(PltSizHeatNum).DeltaT * Cp * rho);
3314 : } else {
3315 0 : WaterVolFlowMaxHeatDes = 0.0;
3316 : }
3317 : } else {
3318 0 : if (OpMode == OperatingMode::ClgHtg || OpMode == OperatingMode::HtgOnly) {
3319 0 : ShowSevereError(state, "Autosizing of water flow requires a heating loop Sizing:Plant object");
3320 0 : ShowContinueError(state,
3321 0 : "Occurs in ZoneHVAC:LowTemperatureRadiant:ConstantFlow Object=" +
3322 0 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).Name);
3323 0 : ErrorsFound = true;
3324 : }
3325 : }
3326 :
3327 : // Index only if it provides cooling system to avoid severe error
3328 3 : if (OpMode == OperatingMode::ClgHtg || OpMode == OperatingMode::ClgOnly) {
3329 12 : PltSizCoolNum = MyPlantSizingIndex(state,
3330 : CompType,
3331 3 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).Name,
3332 3 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).ColdWaterInNode,
3333 3 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).ColdWaterOutNode,
3334 : ErrorsFound);
3335 : }
3336 3 : if (PltSizCoolNum > 0) {
3337 3 : if (state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).NonAirSysDesCoolLoad >= SmallLoad) {
3338 6 : rho = GetDensityGlycol(
3339 : state,
3340 3 : state.dataPlnt->PlantLoop(state.dataLowTempRadSys->CFloRadSys(RadSysNum).CWPlantLoc.loopNum).FluidName,
3341 : DataGlobalConstants::CWInitConvTemp,
3342 3 : state.dataPlnt->PlantLoop(state.dataLowTempRadSys->CFloRadSys(RadSysNum).CWPlantLoc.loopNum).FluidIndex,
3343 3 : "SizeLowTempRadiantSystem");
3344 6 : Cp = GetSpecificHeatGlycol(
3345 : state,
3346 3 : state.dataPlnt->PlantLoop(state.dataLowTempRadSys->CFloRadSys(RadSysNum).CWPlantLoc.loopNum).FluidName,
3347 : DataGlobalConstants::CWInitConvTemp,
3348 3 : state.dataPlnt->PlantLoop(state.dataLowTempRadSys->CFloRadSys(RadSysNum).CWPlantLoc.loopNum).FluidIndex,
3349 3 : "SizeLowTempRadiantSystem");
3350 6 : WaterVolFlowMaxCoolDes = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).NonAirSysDesCoolLoad /
3351 3 : (state.dataSize->PlantSizData(PltSizCoolNum).DeltaT * Cp * rho);
3352 : } else {
3353 0 : WaterVolFlowMaxCoolDes = 0.0;
3354 : }
3355 : } else {
3356 0 : if (OpMode == OperatingMode::ClgHtg || OpMode == OperatingMode::ClgOnly) {
3357 0 : ShowSevereError(state, "Autosizing of water flow requires a cooling loop Sizing:Plant object");
3358 0 : ShowContinueError(state,
3359 0 : "Occurs in ZoneHVAC:LowTemperatureRadiant:ConstantFlow Object=" +
3360 0 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).Name);
3361 0 : ErrorsFound = true;
3362 : }
3363 : }
3364 :
3365 : // Determine maximum water flow rate depending upon system type
3366 3 : if (OpMode == OperatingMode::ClgHtg) {
3367 3 : WaterVolFlowMaxDes = std::max(WaterVolFlowMaxHeatDes, WaterVolFlowMaxCoolDes);
3368 0 : } else if (OpMode == OperatingMode::ClgOnly) {
3369 0 : WaterVolFlowMaxDes = WaterVolFlowMaxCoolDes;
3370 0 : } else if (OpMode == OperatingMode::HtgOnly) {
3371 0 : WaterVolFlowMaxDes = WaterVolFlowMaxHeatDes;
3372 : } else {
3373 0 : WaterVolFlowMaxDes = 0.0;
3374 : }
3375 :
3376 3 : if (IsAutoSize) {
3377 1 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).WaterVolFlowMax = WaterVolFlowMaxDes;
3378 2 : BaseSizer::reportSizerOutput(state,
3379 : CompType,
3380 1 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).Name,
3381 : "Design Size Maximum Water Flow [m3/s]",
3382 1 : WaterVolFlowMaxDes);
3383 : } else { // hard-size with sizing data
3384 2 : if (state.dataLowTempRadSys->CFloRadSys(RadSysNum).WaterVolFlowMax > 0.0 && WaterVolFlowMaxDes > 0.0) {
3385 2 : WaterVolFlowMaxUser = state.dataLowTempRadSys->CFloRadSys(RadSysNum).WaterVolFlowMax;
3386 4 : BaseSizer::reportSizerOutput(state,
3387 : CompType,
3388 2 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).Name,
3389 : "Design Size Maximum Water Flow [m3/s]",
3390 : WaterVolFlowMaxDes,
3391 : "User-Specified Maximum Water Flow [m3/s]",
3392 2 : WaterVolFlowMaxUser);
3393 2 : if (state.dataGlobal->DisplayExtraWarnings) {
3394 0 : if ((std::abs(WaterVolFlowMaxDes - WaterVolFlowMaxUser) / WaterVolFlowMaxUser) >
3395 0 : state.dataSize->AutoVsHardSizingThreshold) {
3396 0 : ShowMessage(state,
3397 : "SizeLowTempRadiantSystem: Potential issue with equipment sizing for "
3398 0 : "ZoneHVAC:LowTemperatureRadiant:ConstantFlow = \" " +
3399 0 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).Name + "\".");
3400 0 : ShowContinueError(state, format("User-Specified Maximum Water Flow of {:.5R} [m3/s]", WaterVolFlowMaxUser));
3401 0 : ShowContinueError(state,
3402 0 : format("differs from Design Size Maximum Water Flow of {:.5R} [m3/s]", WaterVolFlowMaxDes));
3403 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
3404 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
3405 : }
3406 : }
3407 : }
3408 : }
3409 : }
3410 : }
3411 :
3412 27 : IsAutoSize = false;
3413 27 : if (state.dataLowTempRadSys->CFloRadSys(RadSysNum).TubeLength == AutoSize) {
3414 1 : IsAutoSize = true;
3415 : }
3416 :
3417 27 : if (state.dataSize->CurZoneEqNum > 0) {
3418 27 : if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) { // simulation continue
3419 24 : if (state.dataLowTempRadSys->CFloRadSys(RadSysNum).TubeLength > 0.0) {
3420 96 : BaseSizer::reportSizerOutput(state,
3421 : "ZoneHVAC:LowTemperatureRadiant:ConstantFlow",
3422 24 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).Name,
3423 : "User-Specified Hydronic Tubing Length [m]",
3424 72 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).TubeLength);
3425 : }
3426 : } else { // Autosize or hard-size with sizing run
3427 : // CheckZoneSizing is not required here because the tube length calculation is not dependent on zone sizing calculation results
3428 3 : TubeLengthDes = state.dataLowTempRadSys->CFloRadSys(RadSysNum).sizeRadiantSystemTubeLength(state);
3429 3 : if (IsAutoSize) {
3430 1 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).TubeLength = TubeLengthDes;
3431 3 : BaseSizer::reportSizerOutput(state,
3432 : "ZoneHVAC:LowTemperatureRadiant:ConstantFlow",
3433 1 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).Name,
3434 : "Design Size Hydronic Tubing Length [m]",
3435 2 : TubeLengthDes);
3436 : } else { // hard-size with sizing data
3437 2 : if (state.dataLowTempRadSys->CFloRadSys(RadSysNum).TubeLength > 0.0 && TubeLengthDes > 0.0) {
3438 2 : TubeLengthUser = state.dataLowTempRadSys->CFloRadSys(RadSysNum).TubeLength;
3439 6 : BaseSizer::reportSizerOutput(state,
3440 : "ZoneHVAC:LowTemperatureRadiant:ConstantFlow",
3441 2 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).Name,
3442 : "Design Size Hydronic Tubing Length [m]",
3443 : TubeLengthDes,
3444 : "User-Specified Hydronic Tubing Length [m]",
3445 4 : TubeLengthUser);
3446 2 : if (state.dataGlobal->DisplayExtraWarnings) {
3447 0 : if ((std::abs(TubeLengthDes - TubeLengthUser) / TubeLengthUser) > state.dataSize->AutoVsHardSizingThreshold) {
3448 0 : ShowMessage(state,
3449 : "SizeLowTempRadiantSystem: Potential issue with equipment sizing for "
3450 0 : "ZoneHVAC:LowTemperatureRadiant:ConstantFlow = \" " +
3451 0 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).Name + "\".");
3452 0 : ShowContinueError(state, format("User-Specified Hydronic Tubing Length of {:.5R} [m]", TubeLengthUser));
3453 0 : ShowContinueError(state, format("differs from Design Size Hydronic Tubing Length of {:.5R} [m]", TubeLengthDes));
3454 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
3455 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
3456 : }
3457 : }
3458 : }
3459 : }
3460 : }
3461 : }
3462 :
3463 54 : for (SurfNum = 1; SurfNum <= state.dataLowTempRadSys->CFloRadSys(RadSysNum).NumOfSurfaces; ++SurfNum) {
3464 27 : if (state.dataLowTempRadSys->CFloRadSys(RadSysNum).NumCircCalcMethod == CircuitCalc::CalculateFromLength) {
3465 0 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).NumCircuits(SurfNum) =
3466 0 : (state.dataLowTempRadSys->CFloRadSys(RadSysNum).SurfaceFrac(SurfNum) *
3467 0 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).TubeLength) /
3468 0 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).CircLength;
3469 0 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).NumCircuits(SurfNum) =
3470 0 : max(state.dataLowTempRadSys->CFloRadSys(RadSysNum).NumCircuits(SurfNum), 1.0);
3471 : } else {
3472 27 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).NumCircuits(SurfNum) = 1.0;
3473 : }
3474 : }
3475 27 : if (state.dataLowTempRadSys->CFloRadSys(RadSysNum).HotWaterInNode > 0) {
3476 54 : RegisterPlantCompDesignFlow(state,
3477 27 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).HotWaterInNode,
3478 27 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).WaterVolFlowMax);
3479 : }
3480 27 : if (state.dataLowTempRadSys->CFloRadSys(RadSysNum).ColdWaterInNode > 0) {
3481 48 : RegisterPlantCompDesignFlow(state,
3482 24 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).ColdWaterInNode,
3483 24 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).WaterVolFlowMax);
3484 : }
3485 : }
3486 :
3487 82 : if (ErrorsFound) {
3488 0 : ShowFatalError(state, "Preceding sizing errors cause program termination");
3489 : }
3490 82 : }
3491 :
3492 49 : Real64 HydronicSystemBaseData::sizeRadiantSystemTubeLength(EnergyPlusData &state)
3493 : {
3494 :
3495 : // SUBROUTINE INFORMATION:
3496 : // AUTHOR Rick Strand
3497 : // DATE WRITTEN August 2017
3498 :
3499 : // PURPOSE OF THIS SUBROUTINE:
3500 : // This subroutine figures out the tube length based on the spacing of tubes.
3501 : // For single surface systems, this is fairly easy as there is only one spacing
3502 : // to deal with. For multi-surface systems, more work is necessary because each
3503 : // surface could use a different spacing.
3504 :
3505 : // Return value
3506 : Real64 sizeRadiantSystemTubeLength;
3507 :
3508 49 : Real64 tubeLength(0.0); // temporary holding place for the function calculation
3509 :
3510 110 : for (int surfNum = 1; surfNum <= this->NumOfSurfaces; ++surfNum) {
3511 61 : auto &thisHydrSysSurf(state.dataSurface->Surface(this->SurfacePtr(surfNum)));
3512 61 : auto &thisHydrSpacing(state.dataConstruction->Construct(thisHydrSysSurf.Construction).ThicknessPerpend);
3513 61 : if ((thisHydrSpacing > 0.005) && (thisHydrSpacing < 0.5)) { // limit allowable spacing to between 1cm and 1m
3514 61 : tubeLength += thisHydrSysSurf.Area / (2.0 * thisHydrSpacing);
3515 : } else { // if not in allowable limit, default back to 0.15m (15cm or 6 inches)
3516 0 : tubeLength += thisHydrSysSurf.Area / 0.15;
3517 : }
3518 : }
3519 :
3520 49 : sizeRadiantSystemTubeLength = tubeLength;
3521 49 : return sizeRadiantSystemTubeLength;
3522 : }
3523 :
3524 372334 : void VariableFlowRadiantSystemData::calculateLowTemperatureRadiantSystem(EnergyPlusData &state,
3525 : Real64 &LoadMet) // load met by the radiant system, in Watts
3526 : {
3527 :
3528 : // SUBROUTINE INFORMATION:
3529 : // AUTHOR Rick Strand
3530 : // DATE WRITTEN November 2000
3531 :
3532 : // PURPOSE OF THIS SUBROUTINE:
3533 : // This subroutine does all of the stuff that is necessary to simulate
3534 : // a low temperature hydronic radiant heating/cooling system. Calls are
3535 : // made to appropriate subroutines either in this module or outside of it.
3536 :
3537 : // METHODOLOGY EMPLOYED:
3538 : // Follows the methods used by many other pieces of zone equipment.
3539 : // Much like a water coil, a hydronic system will use the ControlCompOutput
3540 : // routine to determine what fraction of capacity the unit should be
3541 : // functioning at by controlling the flow rate of water to the element.
3542 :
3543 : // REFERENCES:
3544 : // Other EnergyPlus modules
3545 : // IBLAST-QTF research program, completed in January 1995 (unreleased)
3546 : // Strand, R.K. 1995. "Heat Source Transfer Functions and Their Application to
3547 : // Low Temperature Radiant Heating Systems", Ph.D. dissertation, University
3548 : // of Illinois at Urbana-Champaign, Department of Mechanical and Industrial
3549 : // Engineering.
3550 : // Seem, J.E. 1986. "Heat Transfer in Buildings", Ph.D. dissertation, University
3551 : // of Wisconsin-Madison.
3552 :
3553 : // Using/Aliasing
3554 : using DataHeatBalance::ZoneData;
3555 : using DataHVACGlobals::SmallLoad;
3556 : using PlantUtilities::SetComponentFlowRate;
3557 : using ScheduleManager::GetCurrentScheduleValue;
3558 :
3559 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
3560 : Real64 ActWaterFlow; // actual water flow for heating or cooling [kg/sec]
3561 : int ControlNode; // the hot water or cold water inlet node
3562 : Real64 ControlTemp; // temperature of whatever is controlling the radiant system
3563 : Real64 MassFlowFrac; // fraction of the maximum water flow rate as determined by the control algorithm
3564 : Real64 MaxWaterFlow; // maximum water flow for heating or cooling [kg/sec]
3565 : Real64 OffTempCool; // temperature at which the flow rate throttles back to zero for cooling
3566 : Real64 OffTempHeat; // temperature at which the flow rate throttles back to zero for heating
3567 : int SurfNum; // Surface number in the Surface derived type for a radiant system surface
3568 : int SurfNum2; // Surface number in the Surface derived type for a radiant system surface
3569 : int ZoneNum; // number of zone being served
3570 : Real64 mdot; // local temporary for fluid mass flow rate
3571 : bool SysRunning; // True when system is running
3572 :
3573 : VarFlowRadDesignData variableFlowDesignDataObject{
3574 744668 : state.dataLowTempRadSys->HydronicRadiantSysDesign(this->DesignObjectPtr)}; // Contains the data for variable flow hydronic systems
3575 :
3576 372334 : auto &Surface(state.dataSurface->Surface);
3577 :
3578 372334 : ControlNode = 0;
3579 372334 : MaxWaterFlow = 0.0;
3580 372334 : ActWaterFlow = 0.0;
3581 372334 : ZoneNum = this->ZonePtr;
3582 372334 : this->OperatingMode = NotOperating;
3583 372334 : SysRunning = true;
3584 :
3585 372334 : if (GetCurrentScheduleValue(state, this->SchedPtr) <= 0) {
3586 :
3587 : // Unit is off or has no load upon it; set the flow rates to zero and then
3588 : // simulate the components with the no flow conditions
3589 15534 : for (SurfNum = 1; SurfNum <= this->NumOfSurfaces; ++SurfNum) {
3590 7767 : SurfNum2 = this->SurfacePtr(SurfNum);
3591 7767 : state.dataHeatBalFanSys->QRadSysSource(SurfNum2) = 0.0;
3592 7767 : if (Surface(SurfNum2).ExtBoundCond > 0 && Surface(SurfNum2).ExtBoundCond != SurfNum2)
3593 0 : state.dataHeatBalFanSys->QRadSysSource(Surface(SurfNum2).ExtBoundCond) = 0.0; // Also zero the other side of an interzone
3594 : }
3595 7767 : if (this->HeatingSystem) {
3596 7764 : mdot = 0.0;
3597 7764 : SetComponentFlowRate(state, mdot, this->HotWaterInNode, this->HotWaterOutNode, this->HWPlantLoc);
3598 : }
3599 7767 : if (this->CoolingSystem) {
3600 0 : mdot = 0.0;
3601 0 : SetComponentFlowRate(state, mdot, this->ColdWaterInNode, this->ColdWaterOutNode, this->CWPlantLoc);
3602 : }
3603 : } else { // Unit might be on-->this section is intended to control the water mass flow rate being
3604 : // sent to the radiant system
3605 :
3606 364567 : ControlTemp = this->setRadiantSystemControlTemperature(state, variableFlowDesignDataObject.VarFlowControlType);
3607 :
3608 364567 : if (variableFlowDesignDataObject.HotSetptSchedPtr > 0) {
3609 : // OffTempHeat = this->setOffTemperatureLowTemperatureRadiantSystem(state, this->HotSetptSchedPtr,
3610 : // this->HotThrottlRange);
3611 : Real64 a;
3612 364567 : a = variableFlowDesignDataObject.HotThrottlRange;
3613 364567 : OffTempHeat = this->setOffTemperatureLowTemperatureRadiantSystem(state,
3614 : variableFlowDesignDataObject.HotSetptSchedPtr,
3615 : variableFlowDesignDataObject.HotThrottlRange,
3616 : variableFlowDesignDataObject.VarFlowSetpointType);
3617 : } else { // This system is not capable of heating, set OffTempHeat to something really low
3618 0 : OffTempHeat = state.dataLowTempRadSys->LowTempHeating;
3619 : }
3620 364567 : if (variableFlowDesignDataObject.ColdSetptSchedPtr > 0) {
3621 715064 : OffTempCool = this->setOffTemperatureLowTemperatureRadiantSystem(state,
3622 : variableFlowDesignDataObject.ColdSetptSchedPtr,
3623 357532 : -variableFlowDesignDataObject.ColdThrottlRange,
3624 : variableFlowDesignDataObject.VarFlowSetpointType);
3625 : } else { // This system is not capable of cooling, set OffTempCool to something really high
3626 7035 : OffTempCool = state.dataLowTempRadSys->HighTempCooling;
3627 : }
3628 :
3629 : // Check for an illogical condition where a user enters controls that could
3630 : // potentially be heating or cooling at a particular control temperature
3631 364567 : if (OffTempHeat > OffTempCool) {
3632 0 : MassFlowFrac = 0.0;
3633 0 : ShowSevereError(state, "Overlapping heating and cooling control temps in radiant system: " + this->Name);
3634 0 : ShowFatalError(state, "Preceding condition causes termination.");
3635 :
3636 : } else { // Temperatures for heating and cooling do not overlap--calculate the mass flow fraction
3637 :
3638 364567 : if (ControlTemp < OffTempHeat && this->HeatingSystem) { // Heating mode
3639 155912 : this->OperatingMode = HeatingMode;
3640 208655 : } else if (ControlTemp > OffTempCool && this->CoolingSystem) { // Cooling mode
3641 142687 : this->OperatingMode = CoolingMode;
3642 : }
3643 :
3644 364567 : this->setOperatingModeBasedOnChangeoverDelay(state);
3645 :
3646 364567 : if (this->OperatingMode == HeatingMode) {
3647 152746 : ControlNode = this->HotWaterInNode;
3648 152746 : MaxWaterFlow = this->WaterFlowMaxHeat;
3649 152746 : MassFlowFrac = this->calculateOperationalFraction(OffTempHeat, ControlTemp, variableFlowDesignDataObject.HotThrottlRange);
3650 211821 : } else if (this->OperatingMode == CoolingMode) {
3651 142021 : ControlNode = this->ColdWaterInNode;
3652 142021 : MaxWaterFlow = this->WaterFlowMaxCool;
3653 142021 : MassFlowFrac = this->calculateOperationalFraction(OffTempCool, ControlTemp, variableFlowDesignDataObject.ColdThrottlRange);
3654 : } else {
3655 69800 : MassFlowFrac = 0.0;
3656 : }
3657 : }
3658 :
3659 : // Calculate and limit the water flow rate
3660 364567 : ActWaterFlow = MassFlowFrac * MaxWaterFlow;
3661 364567 : if (ActWaterFlow < DataBranchAirLoopPlant::MassFlowTolerance) ActWaterFlow = 0.0;
3662 364567 : if (this->EMSOverrideOnWaterMdot) ActWaterFlow = this->EMSWaterMdotOverrideValue;
3663 :
3664 364567 : if (this->OperatingMode == HeatingMode) {
3665 152746 : if (this->HeatingSystem) {
3666 152746 : SetComponentFlowRate(state, ActWaterFlow, this->HotWaterInNode, this->HotWaterOutNode, this->HWPlantLoc);
3667 : } else { // not heating system
3668 0 : SysRunning = false;
3669 : }
3670 211821 : } else if (this->OperatingMode == CoolingMode) {
3671 142021 : if (this->CoolingSystem) {
3672 142021 : SetComponentFlowRate(state, ActWaterFlow, this->ColdWaterInNode, this->ColdWaterOutNode, this->CWPlantLoc);
3673 : } else { // not cooling system
3674 0 : SysRunning = false;
3675 : }
3676 : }
3677 :
3678 : // Now simulate the system...
3679 364567 : if (((this->OperatingMode == HeatingMode) || (this->OperatingMode == CoolingMode)) && SysRunning)
3680 294767 : this->calculateLowTemperatureRadiantSystemComponents(state, LoadMet, SystemType::HydronicSystem);
3681 : }
3682 372334 : }
3683 :
3684 294767 : void VariableFlowRadiantSystemData::calculateLowTemperatureRadiantSystemComponents(
3685 : EnergyPlusData &state,
3686 : Real64 &LoadMet,
3687 : LowTempRadiantSystem::SystemType const typeOfRadiantSystem) // Load met by the low temperature radiant system, in Watts
3688 : {
3689 :
3690 : // SUBROUTINE INFORMATION:
3691 : // AUTHOR Rick Strand
3692 : // DATE WRITTEN November 2000
3693 : // MODIFIED Sep 2011 LKL/BG - resimulate only zones needing it for Radiant systems
3694 :
3695 : // PURPOSE OF THIS SUBROUTINE:
3696 : // This subroutine solves the radiant system based on how much water is (and
3697 : // the conditions of the water) supplied to the radiant system.
3698 :
3699 : // METHODOLOGY EMPLOYED:
3700 : // Use heat exchanger formulas to obtain the heat source/sink for the radiant
3701 : // system based on the inlet conditions and flow rate of water. Once that is
3702 : // determined, recalculate the surface heat balances to reflect this heat
3703 : // addition/subtraction. The load met by the system is determined by the
3704 : // difference between the convection from all surfaces in the zone when
3705 : // there was no radiant system output and with a source/sink added.
3706 :
3707 : // REFERENCES:
3708 : // IBLAST-QTF research program, completed in January 1995 (unreleased)
3709 : // Strand, R.K. 1995. "Heat Source Transfer Functions and Their Application to
3710 : // Low Temperature Radiant Heating Systems", Ph.D. dissertation, University
3711 : // of Illinois at Urbana-Champaign, Department of Mechanical and Industrial
3712 : // Engineering.
3713 :
3714 294767 : auto &Zone(state.dataHeatBal->Zone);
3715 :
3716 : // Using/Aliasing
3717 : using PlantUtilities::SetComponentFlowRate;
3718 :
3719 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
3720 : int CondSurfNum; // Surface number (in radiant array) of
3721 : int ConstrNum; // Index for construction number in Construct derived type
3722 : Real64 DewPointTemp; // Dew-point temperature based on the zone air conditions
3723 : Real64 EpsMdotCp; // Epsilon (heat exchanger terminology) times water mass flow rate times water specific heat
3724 : Real64 FullWaterMassFlow; // Original water mass flow rate before reducing the flow for condensation concerns
3725 : Real64 LowestRadSurfTemp; // Lowest surface temperature of a radiant system (when condensation is a concern)
3726 : Real64 PredictedCondTemp; // Temperature at which condensation is predicted (includes user parameter)
3727 : int RadSurfNum; // DO loop counter for the surfaces that comprise a particular radiant system
3728 : int RadSurfNum2; // DO loop counter for the surfaces that comprise a particular radiant system
3729 : int RadSurfNum3; // DO loop counter for the surfaces that comprise a particular radiant system
3730 : Real64 ReductionFrac; // Fraction that the flow should be reduced to avoid condensation
3731 : int SurfNum; // Index for radiant surface in Surface derived type
3732 : int SurfNum2; // Index for radiant surface in Surface derived type
3733 : Real64 SysWaterMassFlow; // System level water mass flow rate (includes effect of zone multiplier)
3734 : Real64 WaterMassFlow; // Water mass flow rate in the radiant system, kg/s
3735 : int WaterNodeIn; // Node number of the water entering the radiant system
3736 : Real64 WaterTempIn; // Temperature of the water entering the radiant system, in C
3737 : Real64 ZeroFlowSurfTemp; // Temperature of radiant surface when flow is zero
3738 : int ZoneNum; // Zone pointer for this radiant system
3739 :
3740 : VarFlowRadDesignData variableFlowDesignDataObject{
3741 589534 : state.dataLowTempRadSys->HydronicRadiantSysDesign(this->DesignObjectPtr)}; // Contains the data for variable flow hydronic systems
3742 :
3743 294767 : auto &Surface(state.dataSurface->Surface);
3744 :
3745 : Real64 Ca; // Coefficients to relate the inlet water temperature to the heat source
3746 : Real64 Cb;
3747 : Real64 Cc;
3748 : Real64 Cd;
3749 : Real64 Ce;
3750 : Real64 Cf;
3751 : Real64 Cg;
3752 : Real64 Ch;
3753 : Real64 Ci;
3754 : Real64 Cj;
3755 : Real64 Ck;
3756 : Real64 Cl;
3757 : // For more info on Ca through Cl, see comments below
3758 :
3759 : // First, apply heat exchanger logic to find the heat source/sink to the system.
3760 : // This involves finding out the heat transfer characteristics of the hydronic
3761 : // loop and then applying the equations derived on pp. 113-118 of the dissertation.
3762 :
3763 : // Set the conditions on the water side inlet
3764 294767 : switch (this->OperatingMode) {
3765 152746 : case HeatingMode: {
3766 152746 : WaterNodeIn = this->HotWaterInNode;
3767 152746 : } break;
3768 142021 : case CoolingMode: {
3769 142021 : WaterNodeIn = this->ColdWaterInNode;
3770 142021 : } break;
3771 0 : default: {
3772 0 : WaterNodeIn = 0; // Suppress uninitialized warning
3773 0 : ShowSevereError(state, "Illegal low temperature radiant system operating mode");
3774 0 : ShowContinueError(state, "Occurs in Radiant System=" + this->Name);
3775 0 : ShowFatalError(state, "Preceding condition causes termination.");
3776 0 : } break;
3777 : }
3778 294767 : ZoneNum = this->ZonePtr;
3779 294767 : SysWaterMassFlow = state.dataLoopNodes->Node(WaterNodeIn).MassFlowRate;
3780 294767 : WaterMassFlow = state.dataLoopNodes->Node(WaterNodeIn).MassFlowRate / double(Zone(ZoneNum).Multiplier * Zone(ZoneNum).ListMultiplier);
3781 294767 : WaterTempIn = state.dataLoopNodes->Node(WaterNodeIn).Temp;
3782 :
3783 294767 : if (WaterMassFlow <= 0.0) {
3784 : // No flow or below minimum allowed so there is no heat source/sink
3785 : // This is possible with a mismatch between system and plant operation
3786 : // or a slight mismatch between zone and system controls. This is not
3787 : // necessarily a "problem" so this exception is necessary in the code.
3788 72 : for (RadSurfNum = 1; RadSurfNum <= this->NumOfSurfaces; ++RadSurfNum) {
3789 36 : SurfNum = this->SurfacePtr(RadSurfNum);
3790 36 : state.dataHeatBalFanSys->QRadSysSource(SurfNum) = 0.0;
3791 36 : if (Surface(SurfNum).ExtBoundCond > 0 && Surface(SurfNum).ExtBoundCond != SurfNum)
3792 0 : state.dataHeatBalFanSys->QRadSysSource(Surface(SurfNum).ExtBoundCond) = 0.0; // Also zero the other side of an interzone
3793 : }
3794 :
3795 : } else {
3796 :
3797 615434 : for (RadSurfNum = 1; RadSurfNum <= this->NumOfSurfaces; ++RadSurfNum) {
3798 :
3799 320703 : SurfNum = this->SurfacePtr(RadSurfNum);
3800 : // Determine the heat exchanger "effectiveness" term
3801 :
3802 962109 : EpsMdotCp = calculateHXEffectivenessTerm(state,
3803 : SurfNum,
3804 : WaterTempIn,
3805 : WaterMassFlow,
3806 320703 : this->SurfaceFrac(RadSurfNum),
3807 320703 : this->NumCircuits(RadSurfNum),
3808 : this->DesignObjectPtr,
3809 : typeOfRadiantSystem);
3810 :
3811 : // Obtain the heat balance coefficients and calculate the intermediate coefficients
3812 : // linking the inlet water temperature to the heat source/sink to the radiant system.
3813 : // The coefficients are based on the following development...
3814 : // The heat balance equations at the outside and inside surfaces are of the form:
3815 : // Tinside = Ca + Cb*Toutside + Cc*q"
3816 : // Toutside = Cd + Ce*Tinside + Cf*q"
3817 : // Tsource = Cg + Ch*q" + Ci*Tinside + Cj*Toutside
3818 : // where:
3819 : // Tinside is the temperature at the inside surface
3820 : // Toutside is the temperature at the outside surface
3821 : // Tsource is the temperature within the radiant system at the location of the source/sink
3822 : // Ca is all of the other terms in the inside heat balance (solar, LW exchange, conduction history terms, etc.)
3823 : // Cb is the current cross CTF term
3824 : // Cc is the QTF inside term for the current heat source/sink
3825 : // Cd is all of the other terms in the outside heat balance (solar, LW exchange, conduction history terms, etc.)
3826 : // Ce is the current cross CTF term (should be equal to Cb)
3827 : // Cf is the QTF outside term for the current heat source/sink
3828 : // Cg is the summation of all temperature and source history terms at the source/sink location
3829 : // Ch is the QTF term at the source/sink location for the current heat source/sink
3830 : // Ci is the CTF inside term for the current inside surface temperature
3831 : // Cj is the CTF outside term for the current outside surface temperature
3832 : // Note that it is necessary to not use "slow conduction" assumptions because the
3833 : // source/sink has an impact on BOTH the inside and outside surface heat balances.
3834 : // Hence the more general formulation.
3835 : // The first two T equations above can be solved to remove the other surface temperature.
3836 : // This results in the following equations:
3837 : // Tinside = Ca + Cb*(Cd + Ce*Tinside + Cf*q") + Cc*q" or...
3838 : // Tinside = (Ca + Cb*Cd + (Cc+Cb*Cf)*q") / (1 - Ce*Cb)
3839 : // Toutside = Cd + Ce*(Ca + Cb*Toutside + Cc*q") + Cf*q" or...
3840 : // Toutside = (Cd + Ce*Ca + (Cf+Ce*Cc)*q") / (1 - Ce*Cb)
3841 : // Substituting the new equations for Tinside and Toutside as a function of C and q"
3842 : // into the equation for Tsource...
3843 : // Tsource = Cg + Ch*q" + Ci*((Ca + Cb*Cd + (Cc+Cb*Cf)*q") / (1 - Ce*Cb)) &
3844 : // + Cj*((Cd + Ce*Ca + (Cf+Ce*Cc)*q") / (1 - Ce*Cb))
3845 : // Or rearranging this to get Tsource as a function of q", we get...
3846 : // Tsource = Cg + ((Ci*(Ca + Cb*Cd) + Cj*(Cd + Ce*Ca))/(1-Ce*Cb)) &
3847 : // +(Ch + ((Ci*(Cc + Cb*Cf) + Cj*(Cf + Ce*Cc))/(1-Ce*Cb)))*q"
3848 : // Or in a slightly simpler form...
3849 : // Tsource = Ck + Cl*q"
3850 : // where:
3851 : // Ck = Cg + ((Ci*(Ca + Cb*Cd) + Cj*(Cd + Ce*Ca))/(1-Ce*Cb))
3852 : // Cl = Ch + ((Ci*(Cc + Cb*Cf) + Cj*(Cf + Ce*Cc))/(1-Ce*Cb))
3853 : // Note also that from heat exchanger "algebra", we have:
3854 : // q = epsilon*qmax and qmax = Mdot*Cp*(Twaterin-Tsource)
3855 : // So...
3856 : // q" = q/Area = (epsilon*Mdot*Cp/Area)*(Twaterin-Tsource)
3857 : // Or rearranging this equation:
3858 : // Tsource = -(q"*A/(epsilon*Mdot*Cp)) + Twaterin
3859 : // Setting this equation equal to the other equation for Tsource a couple lines up
3860 : // and rearranging to solve for q"...
3861 : // q" = (Twaterin - Ck) / (Cl + (A/(epsilon*Mdot*Cp))
3862 : // or
3863 : // q = (Twaterin - Ck) / ((Cl/A) + (1/epsilon*Mdot*Cp))
3864 : // or
3865 : // q = epsilon*Mdot*Cp*(Twaterin - Ck) / (1+(epsilon*Mdot*Cp*Cl/A))
3866 : // which is the desired result, that is the heat source or sink to the radiant
3867 : // system as a function of the water inlet temperature (flow rate is also in there
3868 : // as well as all of the heat balance terms "hidden" in Ck and Cl).
3869 320703 : ConstrNum = Surface(SurfNum).Construction;
3870 :
3871 320703 : if (Surface(SurfNum).HeatTransferAlgorithm == DataSurfaces::HeatTransferModel::CTF) {
3872 :
3873 206403 : Ca = state.dataHeatBalFanSys->RadSysTiHBConstCoef(SurfNum);
3874 206403 : Cb = state.dataHeatBalFanSys->RadSysTiHBToutCoef(SurfNum);
3875 206403 : Cc = state.dataHeatBalFanSys->RadSysTiHBQsrcCoef(SurfNum);
3876 :
3877 206403 : Cd = state.dataHeatBalFanSys->RadSysToHBConstCoef(SurfNum);
3878 206403 : Ce = state.dataHeatBalFanSys->RadSysToHBTinCoef(SurfNum);
3879 206403 : Cf = state.dataHeatBalFanSys->RadSysToHBQsrcCoef(SurfNum);
3880 :
3881 206403 : Cg = state.dataHeatBalFanSys->CTFTsrcConstPart(SurfNum);
3882 206403 : Ch = state.dataConstruction->Construct(ConstrNum).CTFTSourceQ(0);
3883 206403 : Ci = state.dataConstruction->Construct(ConstrNum).CTFTSourceIn(0);
3884 206403 : Cj = state.dataConstruction->Construct(ConstrNum).CTFTSourceOut(0);
3885 :
3886 206403 : Ck = Cg + ((Ci * (Ca + Cb * Cd) + Cj * (Cd + Ce * Ca)) / (1.0 - Ce * Cb));
3887 206403 : Cl = Ch + ((Ci * (Cc + Cb * Cf) + Cj * (Cf + Ce * Cc)) / (1.0 - Ce * Cb));
3888 :
3889 206403 : state.dataHeatBalFanSys->QRadSysSource(SurfNum) =
3890 206403 : EpsMdotCp * (WaterTempIn - Ck) / (1.0 + (EpsMdotCp * Cl / Surface(SurfNum).Area));
3891 :
3892 114300 : } else if (Surface(SurfNum).HeatTransferAlgorithm == DataSurfaces::HeatTransferModel::CondFD) {
3893 :
3894 114300 : state.dataHeatBalFanSys->QRadSysSource(SurfNum) = EpsMdotCp * (WaterTempIn - state.dataHeatBalFanSys->TCondFDSourceNode(SurfNum));
3895 : }
3896 :
3897 320703 : if (Surface(SurfNum).ExtBoundCond > 0 && Surface(SurfNum).ExtBoundCond != SurfNum)
3898 4886 : state.dataHeatBalFanSys->QRadSysSource(Surface(SurfNum).ExtBoundCond) =
3899 4886 : state.dataHeatBalFanSys->QRadSysSource(SurfNum); // Also set the other side of an interzone
3900 : }
3901 :
3902 : // "Temperature Comparison" Cut-off:
3903 603563 : for (RadSurfNum = 1; RadSurfNum <= this->NumOfSurfaces; ++RadSurfNum) {
3904 : // Check to see whether or not the system should really be running. If
3905 : // QRadSysSource is negative when we are in heating mode or QRadSysSource
3906 : // is positive when we are in cooling mode, then the radiant system will
3907 : // be doing the opposite of its intention. In this case, the flow rate
3908 : // is set to zero to avoid heating in cooling mode or cooling in heating
3909 : // mode.
3910 320703 : SurfNum = this->SurfacePtr(RadSurfNum);
3911 :
3912 653277 : if (((this->OperatingMode == HeatingMode) && (state.dataHeatBalFanSys->QRadSysSource(SurfNum) <= 0.0)) ||
3913 471236 : ((this->OperatingMode == CoolingMode) && (state.dataHeatBalFanSys->QRadSysSource(SurfNum) >= 0.0))) {
3914 11871 : WaterMassFlow = 0.0;
3915 11871 : if (this->OperatingMode == HeatingMode) {
3916 0 : SetComponentFlowRate(state, WaterMassFlow, this->HotWaterInNode, this->HotWaterOutNode, this->HWPlantLoc);
3917 :
3918 11871 : } else if (this->OperatingMode == CoolingMode) {
3919 11871 : SetComponentFlowRate(state, WaterMassFlow, this->ColdWaterInNode, this->ColdWaterOutNode, this->CWPlantLoc);
3920 : }
3921 11871 : this->WaterMassFlowRate = WaterMassFlow;
3922 11871 : this->OperatingMode = NotOperating;
3923 :
3924 23742 : for (RadSurfNum2 = 1; RadSurfNum2 <= this->NumOfSurfaces; ++RadSurfNum2) {
3925 11871 : SurfNum2 = this->SurfacePtr(RadSurfNum2);
3926 11871 : state.dataHeatBalFanSys->QRadSysSource(SurfNum2) = 0.0;
3927 11871 : if (Surface(SurfNum2).ExtBoundCond > 0 && Surface(SurfNum2).ExtBoundCond != SurfNum2)
3928 0 : state.dataHeatBalFanSys->QRadSysSource(Surface(SurfNum2).ExtBoundCond) = 0.0; // Also zero the other side of an interzone
3929 : }
3930 11871 : break; // outer do loop
3931 : }
3932 : }
3933 :
3934 : // Condensation Cut-off:
3935 : // Check to see whether there are any surface temperatures within the radiant system that have
3936 : // dropped below the dew-point temperature. If so, we need to shut off this radiant system.
3937 : // A safety parameter is added (hardwired parameter) to avoid getting too close to condensation
3938 : // conditions.
3939 294731 : this->CondCausedShutDown = false;
3940 294731 : DewPointTemp =
3941 589462 : PsyTdpFnWPb(state, state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).ZoneAirHumRat, state.dataEnvrn->OutBaroPress);
3942 :
3943 371666 : if ((this->OperatingMode == CoolingMode) && (variableFlowDesignDataObject.CondCtrlType == CondContrlType::CondCtrlSimpleOff)) {
3944 :
3945 155637 : for (RadSurfNum2 = 1; RadSurfNum2 <= this->NumOfSurfaces; ++RadSurfNum2) {
3946 167250 : if (state.dataHeatBalSurf->SurfInsideTempHist(1)(this->SurfacePtr(RadSurfNum2)) <
3947 83625 : (DewPointTemp + variableFlowDesignDataObject.CondDewPtDeltaT)) {
3948 : // Condensation warning--must shut off radiant system
3949 4923 : this->CondCausedShutDown = true;
3950 4923 : WaterMassFlow = 0.0;
3951 4923 : this->OperatingMode = NotOperating;
3952 4923 : SetComponentFlowRate(state, WaterMassFlow, this->ColdWaterInNode, this->ColdWaterOutNode, this->CWPlantLoc);
3953 4923 : this->WaterMassFlowRate = WaterMassFlow;
3954 9846 : for (RadSurfNum3 = 1; RadSurfNum3 <= this->NumOfSurfaces; ++RadSurfNum3) {
3955 4923 : SurfNum2 = this->SurfacePtr(RadSurfNum3);
3956 4923 : state.dataHeatBalFanSys->QRadSysSource(SurfNum2) = 0.0;
3957 4923 : if (Surface(SurfNum2).ExtBoundCond > 0 && Surface(SurfNum2).ExtBoundCond != SurfNum2)
3958 0 : state.dataHeatBalFanSys->QRadSysSource(Surface(SurfNum2).ExtBoundCond) =
3959 : 0.0; // Also zero the other side of an interzone
3960 : }
3961 : // Produce a warning message so that user knows the system was shut-off due to potential for condensation
3962 4923 : if (!state.dataGlobal->WarmupFlag) {
3963 737 : if (this->CondErrIndex == 0) { // allow errors up to number of radiant systems
3964 10 : ShowWarningMessage(state, format("{} [{}]", cHydronicSystem, this->Name));
3965 30 : ShowContinueError(state,
3966 20 : "Surface [" + Surface(this->SurfacePtr(RadSurfNum2)).Name +
3967 : "] temperature below dew-point temperature--potential for condensation exists");
3968 10 : ShowContinueError(state, "Flow to the radiant system will be shut-off to avoid condensation");
3969 30 : ShowContinueError(state,
3970 40 : format("Predicted radiant system surface temperature = {:.2R}",
3971 30 : state.dataHeatBalSurf->SurfInsideTempHist(1)(this->SurfacePtr(RadSurfNum2))));
3972 30 : ShowContinueError(state,
3973 20 : format("Zone dew-point temperature + safety delta T= {:.2R}",
3974 20 : DewPointTemp + variableFlowDesignDataObject.CondDewPtDeltaT));
3975 10 : ShowContinueErrorTimeStamp(state, "");
3976 30 : ShowContinueError(state,
3977 20 : format("Note that a {:.4R} C safety was chosen in the input for the shut-off criteria",
3978 10 : variableFlowDesignDataObject.CondDewPtDeltaT));
3979 10 : ShowContinueError(state, "Note also that this affects all surfaces that are part of this radiant system");
3980 : }
3981 2211 : ShowRecurringWarningErrorAtEnd(state,
3982 1474 : format("{} [{}] condensation shut-off occurrence continues.", cHydronicSystem, this->Name),
3983 : this->CondErrIndex,
3984 : DewPointTemp,
3985 : DewPointTemp,
3986 : _,
3987 : "C",
3988 : "C");
3989 : }
3990 4923 : break; // outer do loop
3991 : }
3992 : }
3993 :
3994 262461 : } else if ((this->OperatingMode == CoolingMode) && (variableFlowDesignDataObject.CondCtrlType == CondContrlType::CondCtrlNone)) {
3995 :
3996 91182 : for (RadSurfNum2 = 1; RadSurfNum2 <= this->NumOfSurfaces; ++RadSurfNum2) {
3997 46517 : if (state.dataHeatBalSurf->SurfInsideTempHist(1)(this->SurfacePtr(RadSurfNum2)) < DewPointTemp) {
3998 : // Condensation occurring but user does not want to shut radiant system off ever
3999 19176 : this->CondCausedShutDown = true;
4000 : }
4001 : }
4002 :
4003 173131 : } else if ((this->OperatingMode == CoolingMode) && (variableFlowDesignDataObject.CondCtrlType == CondContrlType::CondCtrlVariedOff)) {
4004 :
4005 8520 : LowestRadSurfTemp = 999.9;
4006 8520 : CondSurfNum = 0;
4007 17040 : for (RadSurfNum2 = 1; RadSurfNum2 <= this->NumOfSurfaces; ++RadSurfNum2) {
4008 17040 : if (state.dataHeatBalSurf->SurfInsideTempHist(1)(this->SurfacePtr(RadSurfNum2)) <
4009 8520 : (DewPointTemp + variableFlowDesignDataObject.CondDewPtDeltaT)) {
4010 4098 : if (state.dataHeatBalSurf->SurfInsideTempHist(1)(this->SurfacePtr(RadSurfNum2)) < LowestRadSurfTemp) {
4011 4098 : LowestRadSurfTemp = state.dataHeatBalSurf->SurfInsideTempHist(1)(this->SurfacePtr(RadSurfNum2));
4012 4098 : CondSurfNum = RadSurfNum2;
4013 : }
4014 : }
4015 : }
4016 :
4017 8520 : if (CondSurfNum > 0) { // Condensation predicted so let's deal with it
4018 : // Process here is: turn everything off and see what the resulting surface temperature is for
4019 : // the surface that was causing the lowest temperature. Then, interpolate to find the flow that
4020 : // would still allow the system to operate without producing condensation. Rerun the heat balance
4021 : // and recheck for condensation. If condensation still exists, shut everything down. This avoids
4022 : // excessive iteration and still makes an attempt to vary the flow rate.
4023 : // First, shut everything off...
4024 4098 : FullWaterMassFlow = WaterMassFlow;
4025 4098 : WaterMassFlow = 0.0;
4026 4098 : SetComponentFlowRate(state, WaterMassFlow, this->ColdWaterInNode, this->ColdWaterOutNode, this->CWPlantLoc);
4027 4098 : this->WaterMassFlowRate = WaterMassFlow;
4028 8196 : for (RadSurfNum3 = 1; RadSurfNum3 <= this->NumOfSurfaces; ++RadSurfNum3) {
4029 4098 : SurfNum2 = this->SurfacePtr(RadSurfNum3);
4030 4098 : state.dataHeatBalFanSys->QRadSysSource(SurfNum2) = 0.0;
4031 4098 : if (Surface(SurfNum2).ExtBoundCond > 0 && Surface(SurfNum2).ExtBoundCond != SurfNum2)
4032 0 : state.dataHeatBalFanSys->QRadSysSource(Surface(SurfNum2).ExtBoundCond) = 0.0; // Also zero the other side of an interzone
4033 : }
4034 : // Redo the heat balances since we have changed the heat source (set it to zero)
4035 4098 : HeatBalanceSurfaceManager::CalcHeatBalanceOutsideSurf(state, ZoneNum);
4036 4098 : HeatBalanceSurfaceManager::CalcHeatBalanceInsideSurf(state, ZoneNum);
4037 : // Now check all of the surface temperatures. If any potentially have condensation, leave the system off.
4038 8196 : for (RadSurfNum2 = 1; RadSurfNum2 <= this->NumOfSurfaces; ++RadSurfNum2) {
4039 8196 : if (state.dataHeatBalSurf->SurfInsideTempHist(1)(this->SurfacePtr(RadSurfNum2)) <
4040 4098 : (DewPointTemp + variableFlowDesignDataObject.CondDewPtDeltaT)) {
4041 0 : this->CondCausedShutDown = true;
4042 : }
4043 : }
4044 : // If the system does not need to be shut down, then let's see if we can vary the flow based
4045 : // on the lowest temperature surface from before. This will use interpolation to try a new
4046 : // flow rate.
4047 4098 : if (!this->CondCausedShutDown) {
4048 4098 : PredictedCondTemp = DewPointTemp + variableFlowDesignDataObject.CondDewPtDeltaT;
4049 4098 : ZeroFlowSurfTemp = state.dataHeatBalSurf->SurfInsideTempHist(1)(this->SurfacePtr(CondSurfNum));
4050 4098 : ReductionFrac = (ZeroFlowSurfTemp - PredictedCondTemp) / std::abs(ZeroFlowSurfTemp - LowestRadSurfTemp);
4051 4098 : if (ReductionFrac < 0.0) ReductionFrac = 0.0; // Shouldn't happen as the above check should have screened this out
4052 4098 : if (ReductionFrac > 1.0) ReductionFrac = 1.0; // Shouldn't happen either because condensation doesn't exist then
4053 4098 : WaterMassFlow = ReductionFrac * FullWaterMassFlow;
4054 4098 : SysWaterMassFlow = double(Zone(ZoneNum).Multiplier * Zone(ZoneNum).ListMultiplier) * WaterMassFlow;
4055 : // Got a new reduced flow rate that should work...reset loop variable and resimulate the system
4056 4098 : SetComponentFlowRate(state, SysWaterMassFlow, this->ColdWaterInNode, this->ColdWaterOutNode, this->CWPlantLoc);
4057 4098 : this->WaterMassFlowRate = SysWaterMassFlow;
4058 :
4059 : // Go through all of the surfaces again with the new flow rate...
4060 8196 : for (RadSurfNum3 = 1; RadSurfNum3 <= this->NumOfSurfaces; ++RadSurfNum3) {
4061 4098 : SurfNum = this->SurfacePtr(RadSurfNum3);
4062 : // Determine the heat exchanger "effectiveness" term
4063 :
4064 12294 : EpsMdotCp = calculateHXEffectivenessTerm(state,
4065 : SurfNum,
4066 : WaterTempIn,
4067 : WaterMassFlow,
4068 4098 : this->SurfaceFrac(RadSurfNum3),
4069 4098 : this->NumCircuits(RadSurfNum3),
4070 : this->DesignObjectPtr,
4071 : typeOfRadiantSystem);
4072 :
4073 4098 : if (Surface(SurfNum).HeatTransferAlgorithm == DataSurfaces::HeatTransferModel::CTF) {
4074 : // For documentation on coefficients, see code earlier in this subroutine
4075 4098 : Ca = state.dataHeatBalFanSys->RadSysTiHBConstCoef(SurfNum);
4076 4098 : Cb = state.dataHeatBalFanSys->RadSysTiHBToutCoef(SurfNum);
4077 4098 : Cc = state.dataHeatBalFanSys->RadSysTiHBQsrcCoef(SurfNum);
4078 4098 : Cd = state.dataHeatBalFanSys->RadSysToHBConstCoef(SurfNum);
4079 4098 : Ce = state.dataHeatBalFanSys->RadSysToHBTinCoef(SurfNum);
4080 4098 : Cf = state.dataHeatBalFanSys->RadSysToHBQsrcCoef(SurfNum);
4081 4098 : Cg = state.dataHeatBalFanSys->CTFTsrcConstPart(SurfNum);
4082 4098 : Ch = state.dataConstruction->Construct(ConstrNum).CTFTSourceQ(0);
4083 4098 : Ci = state.dataConstruction->Construct(ConstrNum).CTFTSourceIn(0);
4084 4098 : Cj = state.dataConstruction->Construct(ConstrNum).CTFTSourceOut(0);
4085 4098 : Ck = Cg + ((Ci * (Ca + Cb * Cd) + Cj * (Cd + Ce * Ca)) / (1.0 - Ce * Cb));
4086 4098 : Cl = Ch + ((Ci * (Cc + Cb * Cf) + Cj * (Cf + Ce * Cc)) / (1.0 - Ce * Cb));
4087 4098 : state.dataHeatBalFanSys->QRadSysSource(SurfNum) =
4088 4098 : EpsMdotCp * (WaterTempIn - Ck) / (1.0 + (EpsMdotCp * Cl / Surface(SurfNum).Area));
4089 0 : } else if (Surface(SurfNum).HeatTransferAlgorithm == DataSurfaces::HeatTransferModel::CondFD) {
4090 0 : state.dataHeatBalFanSys->QRadSysSource(SurfNum) =
4091 0 : EpsMdotCp * (WaterTempIn - state.dataHeatBalFanSys->TCondFDSourceNode(SurfNum));
4092 : }
4093 4098 : if (Surface(SurfNum).ExtBoundCond > 0 && Surface(SurfNum).ExtBoundCond != SurfNum)
4094 0 : state.dataHeatBalFanSys->QRadSysSource(Surface(SurfNum).ExtBoundCond) =
4095 0 : state.dataHeatBalFanSys->QRadSysSource(SurfNum); // Also set the other side of an interzone
4096 : }
4097 :
4098 : // Redo the heat balances since we have changed the heat source
4099 4098 : HeatBalanceSurfaceManager::CalcHeatBalanceOutsideSurf(state, ZoneNum);
4100 4098 : HeatBalanceSurfaceManager::CalcHeatBalanceInsideSurf(state, ZoneNum);
4101 :
4102 : // Check for condensation one more time. If no condensation, we are done. If there is
4103 : // condensation, shut things down and be done.
4104 8196 : for (RadSurfNum2 = 1; RadSurfNum2 <= this->NumOfSurfaces; ++RadSurfNum2) {
4105 4098 : if (this->CondCausedShutDown) break;
4106 4098 : if (state.dataHeatBalSurf->SurfInsideTempHist(1)(this->SurfacePtr(RadSurfNum2)) < (PredictedCondTemp)) {
4107 : // Condensation still present--must shut off radiant system
4108 3954 : this->CondCausedShutDown = true;
4109 3954 : WaterMassFlow = 0.0;
4110 3954 : this->OperatingMode = NotOperating;
4111 3954 : RadSurfNum = RadSurfNum2;
4112 3954 : SetComponentFlowRate(state, WaterMassFlow, this->ColdWaterInNode, this->ColdWaterOutNode, this->CWPlantLoc);
4113 3954 : this->WaterMassFlowRate = WaterMassFlow;
4114 7908 : for (RadSurfNum3 = 1; RadSurfNum3 <= this->NumOfSurfaces; ++RadSurfNum3) {
4115 3954 : SurfNum2 = this->SurfacePtr(RadSurfNum3);
4116 3954 : state.dataHeatBalFanSys->QRadSysSource(SurfNum2) = 0.0;
4117 3954 : if (Surface(SurfNum2).ExtBoundCond > 0 && Surface(SurfNum2).ExtBoundCond != SurfNum2)
4118 0 : state.dataHeatBalFanSys->QRadSysSource(Surface(SurfNum2).ExtBoundCond) =
4119 : 0.0; // Also zero the other side of an interzone
4120 : }
4121 : }
4122 : }
4123 : }
4124 :
4125 4098 : if (this->CondCausedShutDown) {
4126 : // Produce a warning message so that user knows the system was shut-off due to potential for condensation
4127 3954 : if (!state.dataGlobal->WarmupFlag) {
4128 583 : if (this->CondErrIndex == 0) { // allow errors up to number of radiant systems
4129 2 : ShowWarningMessage(state, format("{} [{}]", cHydronicSystem, this->Name));
4130 6 : ShowContinueError(state,
4131 4 : "Surface [" + Surface(this->SurfacePtr(CondSurfNum)).Name +
4132 : "] temperature below dew-point temperature--potential for condensation exists");
4133 2 : ShowContinueError(state, "Flow to the radiant system will be shut-off to avoid condensation");
4134 6 : ShowContinueError(state,
4135 8 : format("Predicted radiant system surface temperature = {:.2R}",
4136 6 : state.dataHeatBalSurf->SurfInsideTempHist(1)(this->SurfacePtr(CondSurfNum))));
4137 6 : ShowContinueError(state,
4138 4 : format("Zone dew-point temperature + safety delta T= {:.2R}",
4139 4 : DewPointTemp + variableFlowDesignDataObject.CondDewPtDeltaT));
4140 2 : ShowContinueErrorTimeStamp(state, "");
4141 6 : ShowContinueError(state,
4142 4 : format("Note that a {:.4R} C safety was chosen in the input for the shut-off criteria",
4143 2 : variableFlowDesignDataObject.CondDewPtDeltaT));
4144 2 : ShowContinueError(state, "Note also that this affects all surfaces that are part of this radiant system");
4145 : }
4146 1749 : ShowRecurringWarningErrorAtEnd(state,
4147 1166 : format("{} [{}] condensation shut-off occurrence continues.", cHydronicSystem, this->Name),
4148 : this->CondErrIndex,
4149 : DewPointTemp,
4150 : DewPointTemp,
4151 : _,
4152 : "C",
4153 : "C");
4154 : }
4155 : }
4156 : } // Condensation Predicted in Variable Shut-Off Control Type
4157 : } // In cooling mode and one of the condensation control types
4158 : } // There was a non-zero flow
4159 :
4160 : // Now that we have the source/sink term, we must redo the heat balances to obtain
4161 : // the new SumHATsurf value for the zone. Note that the difference between the new
4162 : // SumHATsurf and the value originally calculated by the heat balance with a zero
4163 : // source for all radiant systems in the zone is the load met by the system (approximately).
4164 294767 : HeatBalanceSurfaceManager::CalcHeatBalanceOutsideSurf(state, ZoneNum);
4165 294767 : HeatBalanceSurfaceManager::CalcHeatBalanceInsideSurf(state, ZoneNum);
4166 :
4167 294767 : LoadMet = state.dataHeatBal->Zone(ZoneNum).sumHATsurf(state) - state.dataLowTempRadSys->ZeroSourceSumHATsurf(ZoneNum);
4168 294767 : }
4169 :
4170 231699 : void ConstantFlowRadiantSystemData::calculateLowTemperatureRadiantSystem(EnergyPlusData &state,
4171 : Real64 &LoadMet) // load met by the radiant system, in Watts
4172 : {
4173 :
4174 : // SUBROUTINE INFORMATION:
4175 : // AUTHOR Rick Strand
4176 : // DATE WRITTEN August 2003
4177 :
4178 : // PURPOSE OF THIS SUBROUTINE:
4179 : // This subroutine does all of the stuff that is necessary to simulate
4180 : // a constant flow low temperature hydronic radiant heating/cooling system.
4181 : // Calls are made to appropriate subroutines either in this module or
4182 : // outside of it.
4183 :
4184 : // METHODOLOGY EMPLOYED:
4185 : // Similar in many aspects to the hydronic (variable flow) radiant system
4186 : // except that flow rate through the radiant system is constant (based on
4187 : // the user schedule) and the inlet temperature is varied by injecting
4188 : // more or less fluid from the main loop to achieve the desired inlet
4189 : // temperature.
4190 :
4191 : // REFERENCES:
4192 : // Other EnergyPlus modules
4193 : // IBLAST-QTF research program, completed in January 1995 (unreleased)
4194 : // Strand, R.K. 1995. "Heat Source Transfer Functions and Their Application to
4195 : // Low Temperature Radiant Heating Systems", Ph.D. dissertation, University
4196 : // of Illinois at Urbana-Champaign, Department of Mechanical and Industrial
4197 : // Engineering.
4198 : // Seem, J.E. 1986. "Heat Transfer in Buildings", Ph.D. dissertation, University
4199 : // of Wisconsin-Madison.
4200 :
4201 : // Using/Aliasing
4202 : using DataHeatBalance::ZoneData;
4203 : using DataHVACGlobals::SmallLoad;
4204 : using FluidProperties::GetSpecificHeatGlycol;
4205 : using PlantUtilities::SetComponentFlowRate;
4206 : using ScheduleManager::GetCurrentScheduleValue;
4207 :
4208 : // SUBROUTINE PARAMETER DEFINITIONS:
4209 231699 : Real64 constexpr LowCpFluidValue(100.0); // lowest allowed Cp fluid value (to avoid dividing by zero) [J/kg-K]
4210 231699 : auto constexpr RoutineName("CalcLowTempCFloRadiantSystem");
4211 :
4212 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
4213 : Real64 CpFluid; // Specific heat of the fluid in the radiant system
4214 : Real64 InjectFlowRate; // Calculated injection flow rate that will meet the inlet temperature requirement
4215 : bool Iteration; // FALSE when a normal solution, TRUE when it is a solution where we must also find the inlet temp
4216 : int LoopInNode; // Node on the loop that is the inlet to the constant flow radiant system
4217 : Real64 OffTempCool; // temperature at which the cooling shuts down
4218 : Real64 OffTempHeat; // temperature at which the heating shuts down
4219 : Real64 PumpPartLoadRat; // Pump part load ratio (based on user schedule, or 1.0 for no schedule)
4220 : Real64 PumpTempRise; // Temperature rise of the fluid as it passes through the pump
4221 : Real64 RadInTemp; // "Desired" radiant system water inlet temperature [Celsius]
4222 : Real64 SetPointTemp; // temperature that will be used to control the radiant system [Celsius]
4223 : Real64 SetPointTempHi; // Current high point in setpoint temperature range
4224 : Real64 SetPointTempLo; // Current low point in setpoint temperature range
4225 : Real64 ShaftPower; // Amount of power expended at the pump shaft
4226 : int SurfNum; // Surface number in the Surface derived type for a radiant system surface
4227 : int SurfNum2; // Surface number in the Surface derived type for a radiant system surface
4228 : bool SysRunning; // TRUE when the system is running
4229 : Real64 SysWaterInTemp; // Fluid temperature supplied from the loop
4230 : Real64 WaterTempHi; // Current high point in water temperature range
4231 : Real64 WaterTempLo; // Current low point in water temperature range
4232 : int ZoneNum; // number of zone being served
4233 : Real64 mdot; // local temporary for water mass flow rate kg/s
4234 :
4235 : ConstantFlowRadDesignData ConstantFlowDesignDataObject{
4236 463398 : state.dataLowTempRadSys->CflowRadiantSysDesign(this->DesignObjectPtr)}; // Contains the data for variable flow hydronic systems
4237 231699 : auto &Surface(state.dataSurface->Surface);
4238 231699 : auto &Node(state.dataLoopNodes->Node);
4239 :
4240 : // initialize local variables
4241 231699 : ZoneNum = this->ZonePtr;
4242 231699 : SysRunning = true; // default to running and turn off only if not running
4243 231699 : state.dataLowTempRadSys->VarOffCond = false;
4244 :
4245 231699 : if (GetCurrentScheduleValue(state, this->SchedPtr) <= 0) SysRunning = false;
4246 :
4247 231699 : if (SysRunning) { // Unit is probably on-->this section is intended to control the water
4248 : // mass flow rate being sent to the radiant system
4249 :
4250 : // Set the current setpoint temperature (same procedure for either heating or cooling)
4251 :
4252 223977 : SetPointTemp = this->setRadiantSystemControlTemperature(state, ConstantFlowDesignDataObject.ConstFlowControlType);
4253 :
4254 : // Avoid problems when there is no heating or cooling control because the system only cools or heats
4255 223977 : if (this->HotCtrlHiTempSchedPtr > 0) {
4256 223977 : OffTempHeat = GetCurrentScheduleValue(state, this->HotCtrlHiTempSchedPtr);
4257 : } else {
4258 0 : OffTempHeat = state.dataLowTempRadSys->LowTempHeating;
4259 : }
4260 223977 : if (this->ColdCtrlLoTempSchedPtr > 0) {
4261 217854 : OffTempCool = GetCurrentScheduleValue(state, this->ColdCtrlLoTempSchedPtr);
4262 : } else {
4263 6123 : OffTempCool = state.dataLowTempRadSys->HighTempCooling;
4264 : }
4265 :
4266 223977 : if (SetPointTemp < OffTempHeat && this->HeatingSystem) { // Heating mode
4267 73132 : this->OperatingMode = HeatingMode;
4268 150845 : } else if (SetPointTemp > OffTempCool && this->CoolingSystem) { // Cooling mode
4269 123205 : this->OperatingMode = CoolingMode;
4270 : }
4271 :
4272 223977 : this->setOperatingModeBasedOnChangeoverDelay(state);
4273 :
4274 : // Now actually decide what to do based on the setpoint temperature in relation to the control temperatures
4275 223977 : if (this->OperatingMode == HeatingMode) { // HEATING MODE
4276 :
4277 70320 : this->WaterMassFlowRate = this->HotWaterMassFlowRate;
4278 :
4279 70320 : if (!this->HeatingSystem) {
4280 :
4281 0 : SysRunning = false; // Can't heat unless it's a heating system
4282 :
4283 : } else { // It is a heating system so set all of the values for controls
4284 :
4285 70320 : SetPointTempHi = GetCurrentScheduleValue(state, this->HotCtrlHiTempSchedPtr);
4286 70320 : SetPointTempLo = GetCurrentScheduleValue(state, this->HotCtrlLoTempSchedPtr);
4287 70320 : if (SetPointTempHi < SetPointTempLo) {
4288 0 : ShowSevereError(state, "Heating setpoint temperature mismatch in" + this->Name);
4289 0 : ShowContinueError(state, "High setpoint temperature is less than low setpoint temperature--check your schedule input");
4290 0 : ShowFatalError(state, "Preceding condition causes termination.");
4291 : }
4292 :
4293 70320 : WaterTempHi = GetCurrentScheduleValue(state, this->HotWaterHiTempSchedPtr);
4294 70320 : WaterTempLo = GetCurrentScheduleValue(state, this->HotWaterLoTempSchedPtr);
4295 70320 : if (WaterTempHi < WaterTempLo) {
4296 0 : ShowSevereError(state, "Heating water temperature mismatch in" + this->Name);
4297 0 : ShowContinueError(state, "High water temperature is less than low water temperature--check your schedule input");
4298 0 : ShowFatalError(state, "Preceding condition causes termination.");
4299 : }
4300 :
4301 70320 : if (SetPointTemp >= SetPointTempHi) {
4302 : // System is above high heating setpoint so we should be able to turn the system off
4303 136 : RadInTemp = WaterTempLo;
4304 136 : SysRunning = false;
4305 70184 : } else if (SetPointTemp <= SetPointTempLo) {
4306 : // System is running with its highest inlet temperature
4307 12843 : RadInTemp = WaterTempHi;
4308 : } else {
4309 : // Interpolate to obtain the current radiant system inlet temperature
4310 57341 : RadInTemp = WaterTempHi - (WaterTempHi - WaterTempLo) * (SetPointTemp - SetPointTempLo) / (SetPointTempHi - SetPointTempLo);
4311 : }
4312 : }
4313 :
4314 153657 : } else if (this->OperatingMode == CoolingMode) { // COOLING MODE
4315 :
4316 123190 : this->WaterMassFlowRate = this->ChWaterMassFlowRate;
4317 :
4318 123190 : if (!this->CoolingSystem) {
4319 :
4320 0 : SysRunning = false; // Can't cool unless it's a cooling system
4321 :
4322 : } else { // It is a cooling system so set all of the values for controls
4323 :
4324 123190 : SetPointTempHi = GetCurrentScheduleValue(state, this->ColdCtrlHiTempSchedPtr);
4325 123190 : SetPointTempLo = GetCurrentScheduleValue(state, this->ColdCtrlLoTempSchedPtr);
4326 123190 : if (SetPointTempHi < SetPointTempLo) {
4327 0 : ShowSevereError(state, "Cooling setpoint temperature mismatch in" + this->Name);
4328 0 : ShowContinueError(state, "High setpoint temperature is less than low setpoint temperature--check your schedule input");
4329 0 : ShowFatalError(state, "Preceding condition causes termination.");
4330 : }
4331 :
4332 123190 : WaterTempHi = GetCurrentScheduleValue(state, this->ColdWaterHiTempSchedPtr);
4333 123190 : WaterTempLo = GetCurrentScheduleValue(state, this->ColdWaterLoTempSchedPtr);
4334 123190 : if (WaterTempHi < WaterTempLo) {
4335 0 : ShowSevereError(state, "Cooling water temperature mismatch in" + this->Name);
4336 0 : ShowContinueError(state, "High water temperature is less than low water temperature--check your schedule input");
4337 0 : ShowFatalError(state, "Preceding condition causes termination.");
4338 : }
4339 :
4340 123190 : if (SetPointTemp <= SetPointTempLo) {
4341 : // System is below low cooling setpoint so we should be able to turn the system off
4342 631 : RadInTemp = WaterTempHi;
4343 631 : SysRunning = false;
4344 122559 : } else if (SetPointTemp >= SetPointTempHi) {
4345 : // System is running with its lowest inlet temperature
4346 60821 : RadInTemp = WaterTempLo;
4347 : } else {
4348 : // Interpolate to obtain the current radiant system inlet temperature
4349 61738 : RadInTemp = WaterTempHi - (WaterTempHi - WaterTempLo) * (SetPointTemp - SetPointTempLo) / (SetPointTempHi - SetPointTempLo);
4350 : }
4351 : }
4352 :
4353 : } else { // System is not running because the setpoint temperature is in the "deadband"
4354 :
4355 30467 : RadInTemp = SetPointTemp;
4356 30467 : SysRunning = false;
4357 : }
4358 : }
4359 :
4360 231699 : if (SysRunning) {
4361 192743 : CpFluid = GetSpecificHeatGlycol(state, fluidNameWater, RadInTemp, this->GlycolIndex, RoutineName);
4362 : }
4363 :
4364 231699 : if ((!SysRunning) || (CpFluid < LowCpFluidValue)) {
4365 : // Unit is off or has no load upon it OR CpFluid value is "zero" so
4366 : // set the flow rates to zero and then simulate the components with
4367 : // the no flow conditions
4368 38956 : this->OperatingMode = NotOperating;
4369 38956 : this->WaterMassFlowRate = 0.0;
4370 38956 : this->WaterInjectionRate = 0.0;
4371 38956 : this->WaterRecircRate = 0.0;
4372 38956 : this->HeatPower = 0.0;
4373 38956 : this->CoolPower = 0.0;
4374 38956 : this->PumpPower = 0.0;
4375 38956 : this->PumpMassFlowRate = 0.0;
4376 38956 : this->PumpHeattoFluid = 0.0;
4377 :
4378 77912 : for (SurfNum = 1; SurfNum <= this->NumOfSurfaces; ++SurfNum) {
4379 38956 : SurfNum2 = this->SurfacePtr(SurfNum);
4380 38956 : state.dataHeatBalFanSys->QRadSysSource(SurfNum2) = 0.0;
4381 38956 : if (Surface(SurfNum2).ExtBoundCond > 0 && Surface(SurfNum2).ExtBoundCond != SurfNum2)
4382 0 : state.dataHeatBalFanSys->QRadSysSource(Surface(SurfNum2).ExtBoundCond) = 0.0; // Also zero the other side of an interzone
4383 : }
4384 :
4385 : // turn off flow requests made during init because it is not actually running
4386 38956 : if (this->CWPlantLoc.loopNum > 0) {
4387 31234 : mdot = 0.0;
4388 31234 : SetComponentFlowRate(state, mdot, this->ColdWaterInNode, this->ColdWaterOutNode, this->CWPlantLoc);
4389 : }
4390 77912 : if (this->HWPlantLoc.loopNum > 0) {
4391 38956 : mdot = 0.0;
4392 38956 : SetComponentFlowRate(state, mdot, this->HotWaterInNode, this->HotWaterOutNode, this->HWPlantLoc);
4393 : }
4394 : } else { // (SysRunning) so simulate the system...
4395 :
4396 : // Determine pump flow rate and pump heat addition
4397 192743 : this->PumpMassFlowRate = this->WaterMassFlowRate; // Set in InitLowTempRadiantSystem
4398 192743 : if (this->VolFlowSchedPtr > 0) {
4399 0 : PumpPartLoadRat = GetCurrentScheduleValue(state, this->VolFlowSchedPtr);
4400 : } else {
4401 192743 : PumpPartLoadRat = 1.0;
4402 : }
4403 192743 : this->PumpPower = PumpPartLoadRat * this->NomPowerUse;
4404 192743 : ShaftPower = this->PumpPower * ConstantFlowDesignDataObject.MotorEffic;
4405 : // This adds the pump heat based on User input for the pump (same as in Pump module)
4406 : // We assume that all of the heat ends up in the fluid eventually since this is a closed loop.
4407 192743 : this->PumpHeattoFluid = ShaftPower + ((this->PumpPower - ShaftPower) * ConstantFlowDesignDataObject.FracMotorLossToFluid);
4408 192743 : if (this->PumpMassFlowRate > 0.0) {
4409 192677 : PumpTempRise = this->PumpHeattoFluid / (this->PumpMassFlowRate * CpFluid);
4410 : } else {
4411 66 : PumpTempRise = 0.0;
4412 : }
4413 :
4414 192743 : state.dataLowTempRadSys->LoopReqTemp =
4415 192743 : RadInTemp - PumpTempRise; // Temperature required at the inlet of the pump to meet the temperature request
4416 :
4417 192743 : if (this->OperatingMode == HeatingMode) {
4418 :
4419 : // in heating mode so shut down cold water flow request
4420 70184 : if (this->CWPlantLoc.loopNum > 0) {
4421 64061 : mdot = 0.0;
4422 64061 : SetComponentFlowRate(state, mdot, this->ColdWaterInNode, this->ColdWaterOutNode, this->CWPlantLoc);
4423 : }
4424 70184 : LoopInNode = this->HotWaterInNode;
4425 70184 : SysWaterInTemp = Node(LoopInNode).Temp;
4426 70184 : Iteration = false;
4427 :
4428 70184 : if ((SysWaterInTemp >= state.dataLowTempRadSys->LoopReqTemp) && (Node(LoopInNode).MassFlowRateMaxAvail >= this->WaterMassFlowRate)) {
4429 : // Case 1: Adequate temperature and flow
4430 : // Best condition--loop inlet temperature greater than requested and we have enough flow.
4431 : // So, proceed assuming the RadInTemp requested by the controls and then figure out the
4432 : // mixing after the outlet radiant temperature is calculated.
4433 70184 : this->WaterInletTemp = RadInTemp;
4434 70184 : this->calculateLowTemperatureRadiantSystemComponents(state, LoopInNode, Iteration, LoadMet, SystemType::ConstantFlowSystem);
4435 :
4436 : // We now have inlet and outlet temperatures--we still need to set the flow rates
4437 70184 : if ((SysWaterInTemp - this->WaterOutletTemp) != 0.0) { // protect divide by zero
4438 70184 : this->WaterInjectionRate =
4439 140368 : (this->WaterMassFlowRate * (this->WaterInletTemp - this->WaterOutletTemp) / (SysWaterInTemp - this->WaterOutletTemp)) -
4440 70184 : (this->PumpHeattoFluid / (CpFluid * (SysWaterInTemp - this->WaterOutletTemp)));
4441 : } else {
4442 0 : this->WaterInjectionRate = this->WaterMassFlowRate;
4443 : }
4444 70184 : this->WaterRecircRate = this->WaterMassFlowRate - this->WaterInjectionRate;
4445 :
4446 0 : } else if ((SysWaterInTemp < state.dataLowTempRadSys->LoopReqTemp) &&
4447 0 : (Node(LoopInNode).MassFlowRateMaxAvail >= this->WaterMassFlowRate)) {
4448 : // Case 2: Adequate flow but temperature too low
4449 : // Only thing to do is to reset the inlet temperature and assume that the loop will supply
4450 : // the entire flow to the component (no recirculation but potentially some bypass for the
4451 : // overall loop). There is no way we can meet the control temperature so don't even try.
4452 0 : this->WaterInletTemp = SysWaterInTemp + PumpTempRise;
4453 0 : this->calculateLowTemperatureRadiantSystemComponents(state, LoopInNode, Iteration, LoadMet, SystemType::ConstantFlowSystem);
4454 :
4455 : // We now have inlet and outlet temperatures--we still need to set the flow rates
4456 0 : if ((SysWaterInTemp - this->WaterOutletTemp) != 0.0) { // protect divide by zero
4457 0 : this->WaterInjectionRate =
4458 0 : (this->WaterMassFlowRate * (this->WaterInletTemp - this->WaterOutletTemp) / (SysWaterInTemp - this->WaterOutletTemp)) -
4459 0 : (this->PumpHeattoFluid / (CpFluid * (SysWaterInTemp - this->WaterOutletTemp)));
4460 : } else {
4461 0 : this->WaterInjectionRate = this->WaterMassFlowRate;
4462 : }
4463 0 : if (this->WaterInjectionRate > this->WaterMassFlowRate) this->WaterInjectionRate = this->WaterMassFlowRate;
4464 0 : this->WaterRecircRate = 0.0; // by definition
4465 :
4466 0 : } else if ((SysWaterInTemp >= state.dataLowTempRadSys->LoopReqTemp) &&
4467 0 : (Node(LoopInNode).MassFlowRateMaxAvail < this->WaterMassFlowRate)) {
4468 : // Case 3: Adequate temperature but loop flow is less than component flow
4469 : // This case might work out, but there is no guarantee that there is enough loop flow to
4470 : // mix with the recirculation flow and still provide a high enough temperature. First
4471 : // step is to try the inlet temperature and flow rate as in Case 1. If we can obtain
4472 : // the proper temperature inlet to the radiant system, then we are done. If not, we
4473 : // have to repeat the solution for an unknown inlet temperature and a known recirculation
4474 : // rate.
4475 0 : this->WaterInletTemp = RadInTemp;
4476 0 : this->calculateLowTemperatureRadiantSystemComponents(state, LoopInNode, Iteration, LoadMet, SystemType::ConstantFlowSystem);
4477 :
4478 : // Now see if we can really get that desired into temperature (RadInTemp) by solving
4479 : // for the flow that is injected from the loop. A heat balance for the mixer that relates
4480 : // the important quantities is:
4481 : // Mdotradsys*Cp*Tradsysin = Mdotloop*Cp*Tloop + (Mdotradsys-Mdotloop)*Cp*Tradsysout + PumpHeat
4482 : // or rearranging to get the injection flow (Mdotloop):
4483 : // Mdotloop = Mdotcomp*(Tradsysin-Tradsysout)/(Tloop-Tradsysout) - PumpHeat/(Cp*(Tloop-Tradsysout))
4484 : // If Mdotloop from this equation is greater that the loop flow rate (Node%MassFlowRate),
4485 : // then we cannot meet the inlet temperature and we have to "iterate" through the
4486 : // alternate solution.
4487 0 : if ((SysWaterInTemp - this->WaterOutletTemp) != 0.0) { // protect divide by zero
4488 0 : InjectFlowRate =
4489 0 : (this->WaterMassFlowRate * (this->WaterInletTemp - this->WaterOutletTemp) / (SysWaterInTemp - this->WaterOutletTemp)) -
4490 0 : (this->PumpHeattoFluid / (CpFluid * (SysWaterInTemp - this->WaterOutletTemp)));
4491 : } else {
4492 0 : InjectFlowRate = this->WaterMassFlowRate;
4493 : }
4494 0 : if (InjectFlowRate > Node(LoopInNode).MassFlowRateMaxAvail) {
4495 : // We didn't have enough flow from the loop to meet our inlet temperature request.
4496 : // So, set the injection rate to the loop flow and calculate the recirculation flow.
4497 : // Then, resimulate the radiant system using these values (it will obtain the actual
4498 : // inlet temperature that results from this).
4499 0 : this->WaterInjectionRate = Node(LoopInNode).MassFlowRateMaxAvail;
4500 0 : this->WaterRecircRate = this->WaterMassFlowRate - this->WaterInjectionRate;
4501 0 : this->WaterInletTemp = SysWaterInTemp + PumpTempRise;
4502 0 : Iteration = true;
4503 0 : this->calculateLowTemperatureRadiantSystemComponents(state, LoopInNode, Iteration, LoadMet, SystemType::ConstantFlowSystem);
4504 : } else {
4505 0 : this->WaterInjectionRate = InjectFlowRate;
4506 0 : this->WaterRecircRate = this->WaterMassFlowRate - this->WaterInjectionRate;
4507 : }
4508 :
4509 0 : } else if ((SysWaterInTemp < state.dataLowTempRadSys->LoopReqTemp) &&
4510 0 : (Node(LoopInNode).MassFlowRateMaxAvail < this->WaterMassFlowRate)) {
4511 : // Case 4: Temperature too low and loop flow is less than component flow
4512 : // Worst condition--can't meet the temperature request at all. Only thing to do is to
4513 : // set the loop flow and recirculation rate (known) and solve for the inlet temperature
4514 : // using the "iteration" solution scheme from "Case 3B" above
4515 0 : this->WaterInjectionRate = Node(LoopInNode).MassFlowRateMaxAvail;
4516 0 : this->WaterRecircRate = this->WaterMassFlowRate - this->WaterInjectionRate;
4517 0 : this->WaterInletTemp = SysWaterInTemp + PumpTempRise;
4518 0 : Iteration = true;
4519 0 : this->calculateLowTemperatureRadiantSystemComponents(state, LoopInNode, Iteration, LoadMet, SystemType::ConstantFlowSystem);
4520 : }
4521 :
4522 122559 : } else if (this->OperatingMode == CoolingMode) {
4523 :
4524 : // in cooling mode so shut down heating water flow request
4525 122559 : if (this->HWPlantLoc.loopNum > 0) {
4526 122559 : mdot = 0.0;
4527 122559 : SetComponentFlowRate(state, mdot, this->HotWaterInNode, this->HotWaterOutNode, this->HWPlantLoc);
4528 : }
4529 122559 : LoopInNode = this->ColdWaterInNode;
4530 122559 : SysWaterInTemp = Node(LoopInNode).Temp;
4531 122559 : state.dataLowTempRadSys->CFloCondIterNum = 1;
4532 634111 : while ((state.dataLowTempRadSys->CFloCondIterNum <= 1) ||
4533 250447 : ((state.dataLowTempRadSys->CFloCondIterNum <= 2) &&
4534 138963 : (ConstantFlowDesignDataObject.CondCtrlType == CondContrlType::CondCtrlVariedOff) && (state.dataLowTempRadSys->VarOffCond))) {
4535 127888 : Iteration = false;
4536 :
4537 219633 : if ((SysWaterInTemp <= state.dataLowTempRadSys->LoopReqTemp) &&
4538 91745 : (Node(LoopInNode).MassFlowRateMaxAvail >= this->WaterMassFlowRate)) {
4539 : // Case 1: Adequate temperature and flow
4540 : // Best condition--loop inlet temperature lower than requested and we have enough flow.
4541 : // So, proceed assuming the RadInTemp requested by the controls and then figure out the
4542 : // mixing after the outlet radiant temperature is calculated.
4543 :
4544 : // This condition can also happen when state.dataLowTempRadSys->LoopReqTemp has been reset to dewpoint for condensation
4545 : // control
4546 91745 : if (!state.dataLowTempRadSys->VarOffCond) {
4547 86416 : this->WaterInletTemp = RadInTemp;
4548 : } else {
4549 5329 : this->WaterInletTemp = state.dataLowTempRadSys->LoopReqTemp;
4550 : }
4551 91745 : this->calculateLowTemperatureRadiantSystemComponents(state, LoopInNode, Iteration, LoadMet, SystemType::ConstantFlowSystem);
4552 :
4553 : // We now have inlet and outlet temperatures--we still need to set the flow rates
4554 91745 : if ((SysWaterInTemp - this->WaterOutletTemp) != 0.0) { // protect div by zero
4555 275229 : this->WaterInjectionRate = (this->WaterMassFlowRate * (this->WaterInletTemp - this->WaterOutletTemp) /
4556 183486 : (SysWaterInTemp - this->WaterOutletTemp)) -
4557 91743 : (this->PumpHeattoFluid / (CpFluid * (SysWaterInTemp - this->WaterOutletTemp)));
4558 : } else {
4559 2 : this->WaterInjectionRate = this->WaterMassFlowRate;
4560 : }
4561 91745 : this->WaterRecircRate = this->WaterMassFlowRate - this->WaterInjectionRate;
4562 :
4563 72286 : } else if ((SysWaterInTemp > state.dataLowTempRadSys->LoopReqTemp) &&
4564 36143 : (Node(LoopInNode).MassFlowRateMaxAvail >= this->WaterMassFlowRate)) {
4565 : // Case 2: Adequate flow but temperature too high
4566 : // Only thing to do is to reset the inlet temperature and assume that the loop will supply
4567 : // the entire flow to the component (no recirculation but potentially some bypass for the
4568 : // overall loop). There is no way we can meet the control temperature so don't even try.
4569 36143 : this->WaterInletTemp = SysWaterInTemp + PumpTempRise;
4570 36143 : this->calculateLowTemperatureRadiantSystemComponents(state, LoopInNode, Iteration, LoadMet, SystemType::ConstantFlowSystem);
4571 :
4572 : // We now have inlet and outlet temperatures--we still need to set the flow rates
4573 36143 : if ((SysWaterInTemp - this->WaterOutletTemp) != 0.0) { // protect div by zero
4574 108420 : this->WaterInjectionRate = (this->WaterMassFlowRate * (this->WaterInletTemp - this->WaterOutletTemp) /
4575 72280 : (SysWaterInTemp - this->WaterOutletTemp)) -
4576 36140 : (this->PumpHeattoFluid / (CpFluid * (SysWaterInTemp - this->WaterOutletTemp)));
4577 : } else { // no temp change present, set injection rate to full flow
4578 3 : this->WaterInjectionRate = this->WaterMassFlowRate;
4579 : }
4580 36143 : if (this->WaterInjectionRate > this->WaterMassFlowRate) this->WaterInjectionRate = this->WaterMassFlowRate;
4581 36143 : this->WaterRecircRate = 0.0; // by definition
4582 :
4583 0 : } else if ((SysWaterInTemp <= state.dataLowTempRadSys->LoopReqTemp) &&
4584 0 : (Node(LoopInNode).MassFlowRateMaxAvail < this->WaterMassFlowRate)) {
4585 : // Case 3: Adequate temperature but loop flow is less than component flow
4586 : // This case might work out, but there is no guarantee that there is enough loop flow to
4587 : // mix with the recirculation flow and still provide a high enough temperature. First
4588 : // step is to try the inlet temperature and flow rate as in Case 1. If we can obtain
4589 : // the proper temperature inlet to the radiant system, then we are done. If not, we
4590 : // have to repeat the solution for an unknown inlet temperature and a known recirculation
4591 : // rate.
4592 : // This condition might happen when state.dataLowTempRadSys->LoopReqTemp has been reset to dewpoint for condensation control
4593 0 : if (!state.dataLowTempRadSys->VarOffCond) {
4594 0 : this->WaterInletTemp = RadInTemp;
4595 : } else {
4596 0 : this->WaterInletTemp = state.dataLowTempRadSys->LoopReqTemp;
4597 : }
4598 0 : this->calculateLowTemperatureRadiantSystemComponents(state, LoopInNode, Iteration, LoadMet, SystemType::ConstantFlowSystem);
4599 :
4600 : // Now see if we can really get that desired into temperature (RadInTemp) by solving
4601 : // for the flow that is injected from the loop. A heat balance for the mixer that relates
4602 : // the important quantities is:
4603 : // Mdotradsys*Cp*Tradsysin = Mdotloop*Cp*Tloop + (Mdotradsys-Mdotloop)*Cp*Tradsysout + PumpHeat
4604 : // or rearranging to get the injection flow (Mdotloop):
4605 : // Mdotloop = Mdotcomp*(Tradsysin-Tradsysout)/(Tloop-Tradsysout) - PumpHeat/(Cp*(Tloop-Tradsysout))
4606 : // If Mdotloop from this equation is greater that the loop flow rate (Node%MassFlowRate),
4607 : // then we cannot meet the inlet temperature and we have to "iterate" through the
4608 : // alternate solution.
4609 0 : if ((SysWaterInTemp - this->WaterOutletTemp) != 0.0) { // protect div by zero
4610 0 : InjectFlowRate = (this->WaterMassFlowRate * (this->WaterInletTemp - this->WaterOutletTemp) /
4611 0 : (SysWaterInTemp - this->WaterOutletTemp)) -
4612 0 : (this->PumpHeattoFluid / (CpFluid * (SysWaterInTemp - this->WaterOutletTemp)));
4613 : } else {
4614 0 : InjectFlowRate = this->WaterMassFlowRate;
4615 : }
4616 0 : if (InjectFlowRate > Node(LoopInNode).MassFlowRateMaxAvail) {
4617 : // We didn't have enough flow from the loop to meet our inlet temperature request.
4618 : // So, set the injection rate to the loop flow and calculate the recirculation flow.
4619 : // Then, resimulate the radiant system using these values (it will obtain the actual
4620 : // inlet temperature that results from this).
4621 0 : this->WaterInjectionRate = Node(LoopInNode).MassFlowRateMaxAvail;
4622 0 : this->WaterRecircRate = this->WaterMassFlowRate - this->WaterInjectionRate;
4623 0 : this->WaterInletTemp = SysWaterInTemp + PumpTempRise;
4624 0 : Iteration = true;
4625 0 : this->calculateLowTemperatureRadiantSystemComponents(
4626 : state, LoopInNode, Iteration, LoadMet, SystemType::ConstantFlowSystem);
4627 : } else {
4628 0 : this->WaterInjectionRate = InjectFlowRate;
4629 0 : this->WaterRecircRate = this->WaterMassFlowRate - this->WaterInjectionRate;
4630 : }
4631 :
4632 0 : } else if ((SysWaterInTemp > state.dataLowTempRadSys->LoopReqTemp) &&
4633 0 : (Node(LoopInNode).MassFlowRateMaxAvail < this->WaterMassFlowRate)) {
4634 : // Case 4: Temperature too low and loop flow is less than component flow
4635 : // Worst condition--can't meet the temperature request at all. Only thing to do is to
4636 : // set the loop flow and recirculation rate (known) and solve for the inlet temperature
4637 : // using the "iteration" solution scheme from "Case 3B" above
4638 0 : this->WaterInjectionRate = Node(LoopInNode).MassFlowRateMaxAvail;
4639 0 : this->WaterRecircRate = this->WaterMassFlowRate - this->WaterInjectionRate;
4640 0 : this->WaterInletTemp = SysWaterInTemp + PumpTempRise;
4641 0 : Iteration = true;
4642 0 : this->calculateLowTemperatureRadiantSystemComponents(state, LoopInNode, Iteration, LoadMet, SystemType::ConstantFlowSystem);
4643 : }
4644 :
4645 127888 : ++state.dataLowTempRadSys->CFloCondIterNum;
4646 : }
4647 :
4648 : } // Operating mode (heating or cooling)
4649 :
4650 : // Case when system has been shut down because of condensation issues or other limitations:
4651 192743 : if (this->WaterMassFlowRate < DataBranchAirLoopPlant::MassFlowTolerance) {
4652 11130 : this->WaterMassFlowRate = 0.0;
4653 11130 : this->WaterInjectionRate = 0.0;
4654 11130 : this->WaterRecircRate = 0.0;
4655 11130 : this->PumpMassFlowRate = 0.0;
4656 11130 : this->OperatingMode = NotOperating;
4657 : }
4658 :
4659 : // There are some cases when the pump heat is actually enough to provide all the heating that the system needs.
4660 : // In this case, the water injection flow rate will come back as a slightly negative number. Reset it to zero
4661 : // and just recirculate all the flow through the local loop.
4662 192743 : if (this->WaterInjectionRate < 0.0) {
4663 40 : this->WaterInjectionRate = 0.0;
4664 40 : this->WaterRecircRate = this->WaterMassFlowRate;
4665 : }
4666 :
4667 : // Error check, just in case
4668 192743 : if (this->WaterRecircRate < 0.0) {
4669 0 : ShowWarningError(state, "Flow mismatch in radiant system--result will be an energy imbalance--should not get this error");
4670 0 : ShowContinueErrorTimeStamp(state, format("WaterRecircRate={:.2T}, in Radiant System={},", this->WaterRecircRate, this->Name));
4671 0 : this->WaterRecircRate = 0.0;
4672 0 : this->WaterInjectionRate = this->WaterMassFlowRate;
4673 : }
4674 :
4675 : } // System running mode (yes or no)
4676 231699 : }
4677 :
4678 198072 : void ConstantFlowRadiantSystemData::calculateLowTemperatureRadiantSystemComponents(
4679 : EnergyPlusData &state,
4680 : int const MainLoopNodeIn, // Node number on main loop of the inlet node to the radiant system
4681 : bool const Iteration, // FALSE for the regular solution, TRUE when we had to loop back
4682 : Real64 &LoadMet, // Load met by the low temperature radiant system, in Watts
4683 : LowTempRadiantSystem::SystemType const typeOfRadiantSystem)
4684 : {
4685 :
4686 : // SUBROUTINE INFORMATION:
4687 : // AUTHOR Rick Strand
4688 : // DATE WRITTEN August 2003
4689 : // MODIFIED Sep 2011 LKL/BG - resimulate only zones needing it for Radiant systems
4690 :
4691 : // PURPOSE OF THIS SUBROUTINE:
4692 : // This subroutine solves the radiant system based on how much water is (and
4693 : // the conditions of the water) supplied to the radiant system. The purpose
4694 : // of this subroutine is similar to CalcLowTempHydrRadSysComps except that
4695 : // it solves this for a constant flow hydronic radiant system.
4696 :
4697 : // METHODOLOGY EMPLOYED:
4698 : // Use heat exchanger formulas to obtain the heat source/sink for the radiant
4699 : // system based on the inlet conditions and flow rate of water. Once that is
4700 : // determined, recalculate the surface heat balances to reflect this heat
4701 : // addition/subtraction. The load met by the system is determined by the
4702 : // difference between the convection from all surfaces in the zone when
4703 : // there was no radiant system output and with a source/sink added.
4704 :
4705 : // REFERENCES:
4706 : // IBLAST-QTF research program, completed in January 1995 (unreleased)
4707 : // Strand, R.K. 1995. "Heat Source Transfer Functions and Their Application to
4708 : // Low Temperature Radiant Heating Systems", Ph.D. dissertation, University
4709 : // of Illinois at Urbana-Champaign, Department of Mechanical and Industrial
4710 : // Engineering.
4711 :
4712 198072 : auto &Zone(state.dataHeatBal->Zone);
4713 :
4714 : // Using/Aliasing
4715 : using FluidProperties::GetSpecificHeatGlycol;
4716 : using PlantUtilities::SetComponentFlowRate;
4717 :
4718 : // SUBROUTINE PARAMETER DEFINITIONS:
4719 198072 : Real64 constexpr TempCheckLimit(0.1); // Maximum allowed temperature difference between outlet temperature calculations
4720 198072 : Real64 constexpr ZeroSystemResp(0.1); // Response below which the system response is really zero
4721 198072 : auto constexpr RoutineName("CalcLowTempCFloRadSysComps");
4722 :
4723 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
4724 : int ConstrNum; // Index for construction number in Construct derived type
4725 : Real64 Cp; // Intermediate calculational variable for specific heat of water
4726 : Real64 DewPointTemp; // Dew-point temperature based on the zone air conditions
4727 : Real64 EpsMdotCp; // Epsilon (heat exchanger terminology) times water mass flow rate times water specific heat
4728 : Real64 LoopTerm; // Intermeidate calculation variable for determining the water inlet temperature
4729 : Real64 Mdot; // Intermediate calculation variable for mass flow rate in a surface within the radiant system
4730 : int RadSurfNum; // DO loop counter for the surfaces that comprise a particular radiant system
4731 : int RadSurfNum2; // DO loop counter for the surfaces that comprise a particular radiant system
4732 : int RadSurfNum3; // DO loop counter for the surfaces that comprise a particular radiant system
4733 : Real64 RecircTerm; // Intermeidate calculation variable for determining the water inlet temperature
4734 : Real64 SumFlowFracCkCm; // Summation of surface flow fraction, Ck, and Cm product for each surface in the system
4735 : Real64 SumFlowFracOneMinusCm; // Summation of surface flow fraction times (1-Cm) for each surface in the radiant system
4736 : int SurfNum; // Index for radiant surface in Surface derived type
4737 : int SurfNum2; // Index for radiant surface in Surface derived type
4738 : Real64 TotalRadSysPower; // Total heat source/sink to radiant system
4739 : Real64 TwiCoeff; // Intermeidate calculation variable for determining the water inlet temperature
4740 : Real64 WaterMassFlow; // Water mass flow rate in the radiant system, kg/s
4741 : int WaterNodeIn; // Node number of the water entering the radiant system
4742 : Real64 WaterOutletTempCheck; // Radiant system water outlet temperature (calculated from mixing all outlet streams together)
4743 : Real64 WaterTempIn; // Temperature of the water entering the radiant system, in C
4744 : int ZoneNum; // number of zone being served
4745 : Real64 ZoneMult; // Zone multiplier for this system
4746 :
4747 : ConstantFlowRadDesignData ConstantFlowDesignDataObject{
4748 396144 : state.dataLowTempRadSys->CflowRadiantSysDesign(this->DesignObjectPtr)}; // Contains the data for variable flow hydronic systems
4749 198072 : auto &Surface(state.dataSurface->Surface);
4750 :
4751 : Real64 Ca; // Coefficients to relate the inlet water temperature to the heat source
4752 : Real64 Cb;
4753 : Real64 Cc;
4754 : Real64 Cd;
4755 : Real64 Ce;
4756 : Real64 Cf;
4757 : Real64 Cg;
4758 : Real64 Ch;
4759 : Real64 Ci;
4760 : Real64 Cj;
4761 : Real64 Ck;
4762 : Real64 Cl;
4763 : // For more info on Ca through Cl, see comments below
4764 :
4765 : // First, apply heat exchanger logic to find the heat source/sink to the system.
4766 : // This involves finding out the heat transfer characteristics of the hydronic
4767 : // loop and then applying the equations derived on pp. 113-118 of the dissertation.
4768 198072 : if (state.dataLowTempRadSys->FirstTimeFlag) {
4769 9 : state.dataLowTempRadSys->Ckj.allocate(state.dataLowTempRadSys->MaxCloNumOfSurfaces);
4770 9 : state.dataLowTempRadSys->Cmj.allocate(state.dataLowTempRadSys->MaxCloNumOfSurfaces);
4771 9 : state.dataLowTempRadSys->WaterTempOut.allocate(state.dataLowTempRadSys->MaxCloNumOfSurfaces);
4772 9 : state.dataLowTempRadSys->FirstTimeFlag = false;
4773 : }
4774 :
4775 198072 : state.dataLowTempRadSys->Ckj = 0.0;
4776 198072 : state.dataLowTempRadSys->Cmj = 0.0;
4777 198072 : state.dataLowTempRadSys->WaterTempOut = this->WaterInletTemp;
4778 :
4779 : // Set the conditions on the water side inlet
4780 198072 : switch (this->OperatingMode) {
4781 70184 : case HeatingMode: {
4782 70184 : WaterNodeIn = this->HotWaterInNode;
4783 70184 : } break;
4784 127888 : case CoolingMode: {
4785 127888 : WaterNodeIn = this->ColdWaterInNode;
4786 127888 : } break;
4787 0 : default: {
4788 0 : ShowSevereError(state, "Illegal low temperature radiant system operating mode");
4789 0 : ShowContinueError(state, "Occurs in Radiant System=" + this->Name);
4790 0 : ShowFatalError(state, "Preceding condition causes termination.");
4791 0 : } break;
4792 : }
4793 198072 : ZoneNum = this->ZonePtr;
4794 198072 : ZoneMult = double(Zone(ZoneNum).Multiplier * Zone(ZoneNum).ListMultiplier);
4795 198072 : WaterMassFlow = this->WaterMassFlowRate / ZoneMult;
4796 198072 : WaterTempIn = this->WaterInletTemp;
4797 :
4798 198072 : if (WaterMassFlow <= 0.0) {
4799 : // No flow or below minimum allowed so there is no heat source/sink
4800 : // This is possible with a mismatch between system and plant operation
4801 : // or a slight mismatch between zone and system controls. This is not
4802 : // necessarily a "problem" so this exception is necessary in the code.
4803 132 : for (RadSurfNum = 1; RadSurfNum <= this->NumOfSurfaces; ++RadSurfNum) {
4804 66 : SurfNum = this->SurfacePtr(RadSurfNum);
4805 66 : state.dataHeatBalFanSys->QRadSysSource(SurfNum) = 0.0;
4806 66 : if (Surface(SurfNum).ExtBoundCond > 0 && Surface(SurfNum).ExtBoundCond != SurfNum)
4807 0 : state.dataHeatBalFanSys->QRadSysSource(Surface(SurfNum).ExtBoundCond) = 0.0; // Also zero the other side of an interzone
4808 : }
4809 :
4810 66 : this->WaterOutletTemp = this->WaterInletTemp;
4811 :
4812 : } else {
4813 :
4814 396012 : for (RadSurfNum = 1; RadSurfNum <= this->NumOfSurfaces; ++RadSurfNum) {
4815 198006 : SurfNum = this->SurfacePtr(RadSurfNum);
4816 : // Determine the heat exchanger "effectiveness" term
4817 :
4818 594018 : EpsMdotCp = calculateHXEffectivenessTerm(state,
4819 : SurfNum,
4820 : WaterTempIn,
4821 : WaterMassFlow,
4822 198006 : this->SurfaceFrac(RadSurfNum),
4823 198006 : this->NumCircuits(RadSurfNum),
4824 : this->DesignObjectPtr,
4825 : typeOfRadiantSystem);
4826 :
4827 : // Obtain the heat balance coefficients and calculate the intermediate coefficients
4828 : // linking the inlet water temperature to the heat source/sink to the radiant system.
4829 : // The coefficients are based on the following development...
4830 : // The heat balance equations at the outside and inside surfaces are of the form:
4831 : // Tinside = Ca + Cb*Toutside + Cc*q"
4832 : // Toutside = Cd + Ce*Tinside + Cf*q"
4833 : // Tsource = Cg + Ch*q" + Ci*Tinside + Cj*Toutside
4834 : // where:
4835 : // Tinside is the temperature at the inside surface
4836 : // Toutside is the temperature at the outside surface
4837 : // Tsource is the temperature within the radiant system at the location of the source/sink
4838 : // Ca is all of the other terms in the inside heat balance (solar, LW exchange, conduction history terms, etc.)
4839 : // Cb is the current cross CTF term
4840 : // Cc is the QTF inside term for the current heat source/sink
4841 : // Cd is all of the other terms in the outside heat balance (solar, LW exchange, conduction history terms, etc.)
4842 : // Ce is the current cross CTF term (should be equal to Cb)
4843 : // Cf is the QTF outside term for the current heat source/sink
4844 : // Cg is the summation of all temperature and source history terms at the source/sink location
4845 : // Ch is the QTF term at the source/sink location for the current heat source/sink
4846 : // Ci is the CTF inside term for the current inside surface temperature
4847 : // Cj is the CTF outside term for the current outside surface temperature
4848 : // Note that it is necessary to not use "slow conduction" assumptions because the
4849 : // source/sink has an impact on BOTH the inside and outside surface heat balances.
4850 : // Hence the more general formulation.
4851 : // The first two T equations above can be solved to remove the other surface temperature.
4852 : // This results in the following equations:
4853 : // Tinside = Ca + Cb*(Cd + Ce*Tinside + Cf*q") + Cc*q" or...
4854 : // Tinside = (Ca + Cb*Cd + (Cc+Cb*Cf)*q") / (1 - Ce*Cb)
4855 : // Toutside = Cd + Ce*(Ca + Cb*Toutside + Cc*q") + Cf*q" or...
4856 : // Toutside = (Cd + Ce*Ca + (Cf+Ce*Cc)*q") / (1 - Ce*Cb)
4857 : // Substituting the new equations for Tinside and Toutside as a function of C and q"
4858 : // into the equation for Tsource...
4859 : // Tsource = Cg + Ch*q" + Ci*((Ca + Cb*Cd + (Cc+Cb*Cf)*q") / (1 - Ce*Cb)) &
4860 : // + Cj*((Cd + Ce*Ca + (Cf+Ce*Cc)*q") / (1 - Ce*Cb))
4861 : // Or rearranging this to get Tsource as a function of q", we get...
4862 : // Tsource = Cg + ((Ci*(Ca + Cb*Cd) + Cj*(Cd + Ce*Ca))/(1-Ce*Cb)) &
4863 : // +(Ch + ((Ci*(Cc + Cb*Cf) + Cj*(Cf + Ce*Cc))/(1-Ce*Cb)))*q"
4864 : // Or in a slightly simpler form...
4865 : // Tsource = Ck + Cl*q"
4866 : // where:
4867 : // Ck = Cg + ((Ci*(Ca + Cb*Cd) + Cj*(Cd + Ce*Ca))/(1-Ce*Cb))
4868 : // Cl = Ch + ((Ci*(Cc + Cb*Cf) + Cj*(Cf + Ce*Cc))/(1-Ce*Cb))
4869 : // Note also that from heat exchanger "algebra", we have:
4870 : // q = epsilon*qmax and qmax = Mdot*Cp*(Twaterin-Tsource)
4871 : // So...
4872 : // q" = q/Area = (epsilon*Mdot*Cp/Area)*(Twaterin-Tsource)
4873 : // Or rearranging this equation:
4874 : // Tsource = -(q"*A/(epsilon*Mdot*Cp)) + Twaterin
4875 : // Setting this equation equal to the other equation for Tsource a couple lines up
4876 : // and rearranging to solve for q"...
4877 : // q" = (Twaterin - Ck) / (Cl + (A/(epsilon*Mdot*Cp))
4878 : // or
4879 : // q = (Twaterin - Ck) / ((Cl/A) + (1/epsilon*Mdot*Cp))
4880 : // or
4881 : // q = epsilon*Mdot*Cp*(Twaterin - Ck) / (1+(epsilon*Mdot*Cp*Cl/A))
4882 : // which is the desired result, that is the heat source or sink to the radiant
4883 : // system as a function of the water inlet temperature (flow rate is also in there
4884 : // as well as all of the heat balance terms "hidden" in Ck and Cl).
4885 :
4886 198006 : ConstrNum = Surface(SurfNum).Construction;
4887 :
4888 198006 : Ca = state.dataHeatBalFanSys->RadSysTiHBConstCoef(SurfNum);
4889 198006 : Cb = state.dataHeatBalFanSys->RadSysTiHBToutCoef(SurfNum);
4890 198006 : Cc = state.dataHeatBalFanSys->RadSysTiHBQsrcCoef(SurfNum);
4891 :
4892 198006 : Cd = state.dataHeatBalFanSys->RadSysToHBConstCoef(SurfNum);
4893 198006 : Ce = state.dataHeatBalFanSys->RadSysToHBTinCoef(SurfNum);
4894 198006 : Cf = state.dataHeatBalFanSys->RadSysToHBQsrcCoef(SurfNum);
4895 :
4896 198006 : Cg = state.dataHeatBalFanSys->CTFTsrcConstPart(SurfNum);
4897 198006 : Ch = state.dataConstruction->Construct(ConstrNum).CTFTSourceQ(0);
4898 198006 : Ci = state.dataConstruction->Construct(ConstrNum).CTFTSourceIn(0);
4899 198006 : Cj = state.dataConstruction->Construct(ConstrNum).CTFTSourceOut(0);
4900 :
4901 198006 : Ck = Cg + ((Ci * (Ca + Cb * Cd) + Cj * (Cd + Ce * Ca)) / (1.0 - Ce * Cb));
4902 198006 : Cl = Ch + ((Ci * (Cc + Cb * Cf) + Cj * (Cf + Ce * Cc)) / (1.0 - Ce * Cb));
4903 :
4904 198006 : Mdot = WaterMassFlow * this->SurfaceFrac(RadSurfNum);
4905 198006 : Cp = GetSpecificHeatGlycol(state, fluidNameWater, WaterTempIn, this->GlycolIndex, RoutineName);
4906 :
4907 198006 : if (!Iteration) {
4908 :
4909 198006 : if (Surface(SurfNum).HeatTransferAlgorithm == DataSurfaces::HeatTransferModel::CTF)
4910 160926 : state.dataHeatBalFanSys->QRadSysSource(SurfNum) =
4911 160926 : EpsMdotCp * (WaterTempIn - Ck) / (1.0 + (EpsMdotCp * Cl / Surface(SurfNum).Area));
4912 :
4913 198006 : if (Surface(SurfNum).HeatTransferAlgorithm == DataSurfaces::HeatTransferModel::CondFD)
4914 37080 : state.dataHeatBalFanSys->QRadSysSource(SurfNum) =
4915 37080 : EpsMdotCp * (WaterTempIn - state.dataHeatBalFanSys->TCondFDSourceNode(SurfNum));
4916 :
4917 198006 : if (Surface(SurfNum).ExtBoundCond > 0 && Surface(SurfNum).ExtBoundCond != SurfNum)
4918 0 : state.dataHeatBalFanSys->QRadSysSource(Surface(SurfNum).ExtBoundCond) =
4919 0 : state.dataHeatBalFanSys->QRadSysSource(SurfNum); // Also set the other side of an interzone
4920 198006 : state.dataLowTempRadSys->WaterTempOut(RadSurfNum) = WaterTempIn - (state.dataHeatBalFanSys->QRadSysSource(SurfNum) / (Mdot * Cp));
4921 : } else { // (Iteration)
4922 : // In this case, we did not know the inlet temperature directly and have
4923 : // to figure it out as part of the solution. Thus, we have to do a little
4924 : // more algebra.
4925 : // The last equation in the previous block was:
4926 : // q = epsilon*Mdot*Cp*(Twaterin - Ck) / (1+(epsilon*Mdot*Cp*Cl/A))
4927 : // which combines with:
4928 : // q = Mdot*Cp*(Twaterin - Twaterout,j)
4929 : // so that:
4930 : // (Twaterin - Twaterout.j) = epsilon*(Twaterin - Ck) / (1+(epsilon*Mdot*Cp*Cl/A))
4931 : // Let:
4932 : // Cm = epsilonj / (1+(epsilonj*Mdot,j*Cp*Cl,j/A))
4933 : // for each surface in the radiant system. This results in:
4934 : // (Twaterin - Twaterout,j) = Cm,j*(Twaterin - Ck,j)
4935 : // Or:
4936 : // Twaterout,j = (1 - Cm,j)*Twaterin + Cm,j*Ck,j
4937 : // This holds for each surface that is part of the radiant system (j). To get the
4938 : // overall outlet temperature, we have to do a mixing calculation after all of the
4939 : // surfaces have been simulated:
4940 : // Twaterout = SUM(Fractionj*Twaterout,j)
4941 : // We also have to solve an energy balance at the mixing valve and add in pump heat.
4942 : // The energy balance at the mixing valve relates the loop inlet temperature (Tloopin)
4943 : // and the overall outlet temperature (Twaterout):
4944 : // Tpumpin = (Mdotloop/Mdotradsys)*Tloopin + (Mdotrecirc/Mdotradsys)*Twaterout
4945 : // This can then be related to the inlet water temperature to the radiant system
4946 : // after pump heat has been taken into account:
4947 : // Twaterin = (Mdotloop/Mdotradsys)*Tloopin + (Mdotrecirc/Mdotradsys)*Twaterout + PumpHeat/(Mdotradsys*Cp)
4948 : // Pluggin in the definition of Twaterout (sum equation above) and then the definition
4949 : // of each individual Twaterout,j equation (which is solely a function of Twaterin
4950 : // and coefficients), we can obtain an equation for Twaterin that consists of all
4951 : // known quantities. This requires us to calculate Ck,j and Cm,j for all the radiant
4952 : // surfaces in the system first and then coming up with a calculation for Twaterin.
4953 : // After than, individual Twaterout,j can be calculated along with QRadSysSource.
4954 0 : state.dataLowTempRadSys->Ckj(RadSurfNum) = Ck;
4955 0 : state.dataLowTempRadSys->Cmj(RadSurfNum) = (EpsMdotCp / (Mdot * Cp)) / (1.0 + (EpsMdotCp * Cl / Surface(SurfNum).Area));
4956 :
4957 0 : if (RadSurfNum == this->NumOfSurfaces) { // Last one so we can now do the other calculations
4958 : // Equation for Twaterin is:
4959 : // Twaterin = (LoopTerm + RecircTerm)/(TwiCoeff)
4960 : // where:
4961 : // LoopTerm = (Mdotloop/Mdotradsys)*Tloopin + PumpHeat/(Mdotradsys*Cp)
4962 : // RecircTerm = (Mdotrecirc/Mdotradsys)*SUM(FlowFracj*Ck,j*Cm,j)
4963 : // TwiCoeff = 1 - (Mdotrecirc/Mdotradsys)*SUM(FlowFracj*(1 - Cm,j))
4964 0 : SumFlowFracCkCm = 0.0;
4965 0 : SumFlowFracOneMinusCm = 0.0;
4966 0 : for (RadSurfNum2 = 1; RadSurfNum2 <= this->NumOfSurfaces; ++RadSurfNum2) {
4967 0 : SumFlowFracCkCm += (this->SurfaceFrac(RadSurfNum2) * state.dataLowTempRadSys->Ckj(RadSurfNum) *
4968 0 : state.dataLowTempRadSys->Cmj(RadSurfNum2));
4969 0 : SumFlowFracOneMinusCm += (this->SurfaceFrac(RadSurfNum2) * (1.0 - state.dataLowTempRadSys->Cmj(RadSurfNum2)));
4970 : }
4971 :
4972 0 : LoopTerm = (this->WaterInjectionRate / this->WaterMassFlowRate) * state.dataLoopNodes->Node(MainLoopNodeIn).Temp +
4973 0 : (this->PumpHeattoFluid / (this->WaterMassFlowRate * Cp));
4974 :
4975 0 : RecircTerm = (this->WaterRecircRate / this->WaterMassFlowRate) * SumFlowFracCkCm;
4976 :
4977 0 : TwiCoeff = 1.0 - (this->WaterRecircRate / this->WaterMassFlowRate) * SumFlowFracOneMinusCm;
4978 :
4979 0 : WaterTempIn = (LoopTerm + RecircTerm) / (TwiCoeff);
4980 :
4981 0 : this->WaterInletTemp = WaterTempIn;
4982 :
4983 0 : for (RadSurfNum2 = 1; RadSurfNum2 <= this->NumOfSurfaces; ++RadSurfNum2) {
4984 0 : state.dataLowTempRadSys->WaterTempOut(RadSurfNum2) =
4985 0 : WaterTempIn * (1.0 - state.dataLowTempRadSys->Cmj(RadSurfNum2)) +
4986 0 : (state.dataLowTempRadSys->Ckj(RadSurfNum2) * state.dataLowTempRadSys->Cmj(RadSurfNum2));
4987 0 : Mdot = WaterMassFlow * this->SurfaceFrac(RadSurfNum2);
4988 0 : SurfNum = this->SurfacePtr(RadSurfNum2);
4989 0 : state.dataHeatBalFanSys->QRadSysSource(SurfNum) =
4990 0 : Mdot * Cp * (WaterTempIn - state.dataLowTempRadSys->WaterTempOut(RadSurfNum2));
4991 0 : if (Surface(SurfNum).ExtBoundCond > 0 && Surface(SurfNum).ExtBoundCond != SurfNum)
4992 0 : state.dataHeatBalFanSys->QRadSysSource(Surface(SurfNum).ExtBoundCond) =
4993 0 : state.dataHeatBalFanSys->QRadSysSource(SurfNum); // Also set the other side of an interzone
4994 : }
4995 : }
4996 : }
4997 : }
4998 :
4999 395549 : for (RadSurfNum = 1; RadSurfNum <= this->NumOfSurfaces; ++RadSurfNum) {
5000 198006 : SurfNum = this->SurfacePtr(RadSurfNum);
5001 : // "Temperature Comparison" Cut-off:
5002 : // Check to see whether or not the system should really be running. If
5003 : // QRadSysSource is negative when we are in heating mode or QRadSysSource
5004 : // is positive when we are in cooling mode, then the radiant system will
5005 : // be doing the opposite of its intention. In this case, the flow rate
5006 : // is set to zero to avoid heating in cooling mode or cooling in heating
5007 : // mode.
5008 396012 : if (((this->OperatingMode == HeatingMode) && (state.dataHeatBalFanSys->QRadSysSource(SurfNum) <= 0.0)) ||
5009 325399 : ((this->OperatingMode == CoolingMode) && (state.dataHeatBalFanSys->QRadSysSource(SurfNum) >= 0.0))) {
5010 463 : WaterMassFlow = 0.0;
5011 463 : if (this->OperatingMode == HeatingMode) {
5012 463 : SetComponentFlowRate(state, WaterMassFlow, this->HotWaterInNode, this->HotWaterOutNode, this->HWPlantLoc);
5013 0 : } else if (this->OperatingMode == CoolingMode) {
5014 0 : SetComponentFlowRate(state, WaterMassFlow, this->ColdWaterInNode, this->ColdWaterOutNode, this->CWPlantLoc);
5015 : }
5016 463 : this->WaterMassFlowRate = WaterMassFlow;
5017 463 : this->OperatingMode = NotOperating;
5018 926 : for (RadSurfNum2 = 1; RadSurfNum2 <= this->NumOfSurfaces; ++RadSurfNum2) {
5019 463 : SurfNum2 = this->SurfacePtr(RadSurfNum2);
5020 463 : state.dataHeatBalFanSys->QRadSysSource(SurfNum2) = 0.0;
5021 463 : if (Surface(SurfNum2).ExtBoundCond > 0 && Surface(SurfNum2).ExtBoundCond != SurfNum2)
5022 0 : state.dataHeatBalFanSys->QRadSysSource(Surface(SurfNum2).ExtBoundCond) = 0.0; // Also zero the other side of an interzone
5023 : }
5024 463 : break; // outer do loop
5025 : }
5026 : }
5027 : // Condensation Cut-off:
5028 : // Check to see whether there are any surface temperatures within the radiant system that have
5029 : // dropped below the dew-point temperature. If so, we need to shut off this radiant system.
5030 : // A safety parameter is added (hardwired parameter) to avoid getting too close to condensation
5031 : // conditions.
5032 198006 : this->CondCausedShutDown = false;
5033 198006 : DewPointTemp =
5034 396012 : PsyTdpFnWPb(state, state.dataZoneTempPredictorCorrector->zoneHeatBalance(this->ZonePtr).ZoneAirHumRat, state.dataEnvrn->OutBaroPress);
5035 :
5036 224918 : if ((this->OperatingMode == CoolingMode) && (ConstantFlowDesignDataObject.CondCtrlType == CondContrlType::CondCtrlSimpleOff)) {
5037 :
5038 48529 : for (RadSurfNum2 = 1; RadSurfNum2 <= this->NumOfSurfaces; ++RadSurfNum2) {
5039 53824 : if (state.dataHeatBalSurf->SurfInsideTempHist(1)(this->SurfacePtr(RadSurfNum2)) <
5040 26912 : (DewPointTemp + ConstantFlowDesignDataObject.CondDewPtDeltaT)) {
5041 : // Condensation warning--must shut off radiant system
5042 5295 : this->CondCausedShutDown = true;
5043 5295 : WaterMassFlow = 0.0;
5044 5295 : this->OperatingMode = NotOperating;
5045 5295 : SetComponentFlowRate(state, WaterMassFlow, this->ColdWaterInNode, this->ColdWaterOutNode, this->CWPlantLoc);
5046 5295 : this->WaterMassFlowRate = WaterMassFlow;
5047 10590 : for (RadSurfNum3 = 1; RadSurfNum3 <= this->NumOfSurfaces; ++RadSurfNum3) {
5048 5295 : SurfNum2 = this->SurfacePtr(RadSurfNum3);
5049 5295 : state.dataHeatBalFanSys->QRadSysSource(SurfNum2) = 0.0;
5050 5295 : if (Surface(SurfNum2).ExtBoundCond > 0 && Surface(SurfNum2).ExtBoundCond != SurfNum2)
5051 0 : state.dataHeatBalFanSys->QRadSysSource(Surface(SurfNum2).ExtBoundCond) =
5052 : 0.0; // Also zero the other side of an interzone
5053 : }
5054 : // Produce a warning message so that user knows the system was shut-off due to potential for condensation
5055 5295 : if (!state.dataGlobal->WarmupFlag) {
5056 614 : if (this->CondErrIndex == 0) { // allow errors up to number of radiant systems
5057 2 : ShowWarningMessage(state, format("{} [{}]", cConstantFlowSystem, this->Name));
5058 6 : ShowContinueError(state,
5059 4 : "Surface [" + Surface(this->SurfacePtr(RadSurfNum2)).Name +
5060 : "] temperature below dew-point temperature--potential for condensation exists");
5061 2 : ShowContinueError(state, "Flow to the radiant system will be shut-off to avoid condensation");
5062 6 : ShowContinueError(state,
5063 8 : format("Predicted radiant system surface temperature = {:.2R}",
5064 6 : state.dataHeatBalSurf->SurfInsideTempHist(1)(this->SurfacePtr(RadSurfNum2))));
5065 6 : ShowContinueError(state,
5066 4 : format("Zone dew-point temperature + safety delta T= {:.2R}",
5067 4 : DewPointTemp + ConstantFlowDesignDataObject.CondDewPtDeltaT));
5068 2 : ShowContinueErrorTimeStamp(state, "");
5069 6 : ShowContinueError(state,
5070 4 : format("Note that a {:.4R} C safety was chosen in the input for the shut-off criteria",
5071 2 : ConstantFlowDesignDataObject.CondDewPtDeltaT));
5072 2 : ShowContinueError(state, "Note also that this affects all surfaces that are part of this radiant system");
5073 : }
5074 1842 : ShowRecurringWarningErrorAtEnd(
5075 : state,
5076 1228 : format("{} [{}] condensation shut-off occurrence continues.", cConstantFlowSystem, this->Name),
5077 : this->CondErrIndex,
5078 : DewPointTemp,
5079 : DewPointTemp,
5080 : _,
5081 : "C",
5082 : "C");
5083 : }
5084 5295 : break; // outer do loop
5085 : }
5086 : }
5087 :
5088 250307 : } else if ((this->OperatingMode == CoolingMode) && (ConstantFlowDesignDataObject.CondCtrlType == CondContrlType::CondCtrlNone)) {
5089 :
5090 158426 : for (RadSurfNum2 = 1; RadSurfNum2 <= this->NumOfSurfaces; ++RadSurfNum2) {
5091 79213 : if (state.dataHeatBalSurf->SurfInsideTempHist(1)(this->SurfacePtr(RadSurfNum2)) < DewPointTemp) {
5092 : // Condensation occurring but user does not want to shut radiant system off ever
5093 39223 : this->CondCausedShutDown = true;
5094 : }
5095 : }
5096 :
5097 91881 : } else if ((this->OperatingMode == CoolingMode) && (ConstantFlowDesignDataObject.CondCtrlType == CondContrlType::CondCtrlVariedOff)) {
5098 :
5099 38156 : for (RadSurfNum2 = 1; RadSurfNum2 <= this->NumOfSurfaces; ++RadSurfNum2) {
5100 43462 : if (state.dataHeatBalSurf->SurfInsideTempHist(1)(this->SurfacePtr(RadSurfNum2)) <
5101 21731 : (DewPointTemp + ConstantFlowDesignDataObject.CondDewPtDeltaT)) {
5102 10635 : state.dataLowTempRadSys->VarOffCond = true;
5103 10635 : if (state.dataLowTempRadSys->CFloCondIterNum >= 2) {
5104 : // We have already iterated once so now we must shut off radiant system
5105 5306 : this->CondCausedShutDown = true;
5106 5306 : WaterMassFlow = 0.0;
5107 5306 : this->OperatingMode = NotOperating;
5108 5306 : SetComponentFlowRate(state, WaterMassFlow, this->ColdWaterInNode, this->ColdWaterOutNode, this->CWPlantLoc);
5109 5306 : this->WaterMassFlowRate = WaterMassFlow;
5110 10612 : for (RadSurfNum3 = 1; RadSurfNum3 <= this->NumOfSurfaces; ++RadSurfNum3) {
5111 5306 : SurfNum2 = this->SurfacePtr(RadSurfNum3);
5112 5306 : state.dataHeatBalFanSys->QRadSysSource(SurfNum2) = 0.0;
5113 5306 : if (Surface(SurfNum2).ExtBoundCond > 0 && Surface(SurfNum2).ExtBoundCond != SurfNum2)
5114 0 : state.dataHeatBalFanSys->QRadSysSource(Surface(SurfNum2).ExtBoundCond) =
5115 : 0.0; // Also zero the other side of an interzone
5116 : }
5117 : // Produce a warning message so that user knows the system was shut-off due to potential for condensation
5118 5306 : if (!state.dataGlobal->WarmupFlag) {
5119 616 : if (this->CondErrIndex == 0) { // allow errors up to number of radiant systems
5120 2 : ShowWarningMessage(state, format("{} [{}]", cConstantFlowSystem, this->Name));
5121 6 : ShowContinueError(state,
5122 4 : "Surface [" + Surface(this->SurfacePtr(RadSurfNum2)).Name +
5123 : "] temperature below dew-point temperature--potential for condensation exists");
5124 2 : ShowContinueError(state, "Flow to the radiant system will be shut-off to avoid condensation");
5125 6 : ShowContinueError(state,
5126 8 : format("Predicted radiant system surface temperature = {:.2R}",
5127 6 : state.dataHeatBalSurf->SurfInsideTempHist(1)(this->SurfacePtr(RadSurfNum2))));
5128 6 : ShowContinueError(state,
5129 4 : format("Zone dew-point temperature + safety delta T= {:.2R}",
5130 4 : DewPointTemp + ConstantFlowDesignDataObject.CondDewPtDeltaT));
5131 2 : ShowContinueErrorTimeStamp(state, "");
5132 6 : ShowContinueError(state,
5133 4 : format("Note that a {:.4R} C safety was chosen in the input for the shut-off criteria",
5134 2 : ConstantFlowDesignDataObject.CondDewPtDeltaT));
5135 2 : ShowContinueError(state, "Note also that this affects all surfaces that are part of this radiant system");
5136 : }
5137 1848 : ShowRecurringWarningErrorAtEnd(
5138 : state,
5139 1232 : format("{} [{}] condensation shut-off occurrence continues.", cConstantFlowSystem, this->Name),
5140 : this->CondErrIndex,
5141 : DewPointTemp,
5142 : DewPointTemp,
5143 : _,
5144 : "C",
5145 : "C");
5146 : }
5147 5306 : break; // outer do loop
5148 : } else { // (First iteration--reset loop required temperature and try again to avoid condensation)
5149 5329 : state.dataLowTempRadSys->LoopReqTemp = DewPointTemp + ConstantFlowDesignDataObject.CondDewPtDeltaT;
5150 : }
5151 : }
5152 : }
5153 : }
5154 :
5155 : // Determine radiant system outlet temperature (two ways to calculate--use as a check)
5156 198006 : WaterOutletTempCheck = 0.0;
5157 198006 : TotalRadSysPower = 0.0;
5158 396012 : for (RadSurfNum = 1; RadSurfNum <= this->NumOfSurfaces; ++RadSurfNum) {
5159 198006 : SurfNum = this->SurfacePtr(RadSurfNum);
5160 198006 : TotalRadSysPower += state.dataHeatBalFanSys->QRadSysSource(SurfNum);
5161 198006 : WaterOutletTempCheck += (this->SurfaceFrac(RadSurfNum) * state.dataLowTempRadSys->WaterTempOut(RadSurfNum));
5162 : }
5163 198006 : TotalRadSysPower *= ZoneMult;
5164 :
5165 198006 : if (this->WaterMassFlowRate > 0.0) {
5166 186942 : Cp = GetSpecificHeatGlycol(state, fluidNameWater, WaterTempIn, this->GlycolIndex, RoutineName);
5167 186942 : this->WaterOutletTemp = this->WaterInletTemp - (TotalRadSysPower / (this->WaterMassFlowRate * Cp));
5168 186942 : if ((std::abs(this->WaterOutletTemp - WaterOutletTempCheck) > TempCheckLimit) && (std::abs(TotalRadSysPower) > ZeroSystemResp)) {
5169 : // If the total system power is zero, that means we have shut down and the temperatures won't match because of that
5170 0 : ShowWarningError(state, "Radiant system water outlet temperature calculation mismatch--this should not happen");
5171 : }
5172 : } else {
5173 11064 : this->WaterOutletTemp = this->WaterInletTemp;
5174 : }
5175 : }
5176 :
5177 : // Now that we have the source/sink term(s), we must redo the heat balances to obtain
5178 : // the new SumHATsurf value for the zone. Note that the difference between the new
5179 : // SumHATsurf and the value originally calculated by the heat balance with a zero
5180 : // source for all radiant systems in the zone is the load met by the system (approximately).
5181 198072 : HeatBalanceSurfaceManager::CalcHeatBalanceOutsideSurf(state, ZoneNum);
5182 198072 : HeatBalanceSurfaceManager::CalcHeatBalanceInsideSurf(state, ZoneNum);
5183 :
5184 198072 : LoadMet = state.dataHeatBal->Zone(this->ZonePtr).sumHATsurf(state) - state.dataLowTempRadSys->ZeroSourceSumHATsurf(this->ZonePtr);
5185 198072 : }
5186 : // TODO Write unit tests for baseboard
5187 78 : void ConstantFlowRadiantSystemData::calculateRunningMeanAverageTemperature(EnergyPlusData &state, int RadSysNum)
5188 : {
5189 : // This routine grabs the current weather data since it is currently available at this point in the simulation. Note, however,
5190 : // that the formula that calculates the running mean average (dry-bulb) temperature uses the values from "yesterday". So, today's
5191 : // values are calculated and then shifted at the beginning of the next day to the tomorrow variables. It is these tomorrow variables
5192 : // that are then used in the formula. So, that is why some of the assignments are done in the order that they are in below.
5193 :
5194 78 : ConstantFlowRadDesignData constantFlowDesignDataObject{state.dataLowTempRadSys->CflowRadiantSysDesign(
5195 156 : state.dataLowTempRadSys->CFloRadSys(RadSysNum).DesignObjectPtr)}; // Contains the data for constant flow hydronic systems
5196 :
5197 78 : if (state.dataGlobal->DayOfSim == 1 && state.dataGlobal->WarmupFlag) {
5198 : // there is no "history" here--assume everything that came before was the same (this applies to design days also--weather is always the
5199 : // same
5200 24 : this->todayAverageOutdoorDryBulbTemperature = this->calculateCurrentDailyAverageODB(state);
5201 24 : this->yesterdayAverageOutdoorDryBulbTemperature = this->todayAverageOutdoorDryBulbTemperature;
5202 24 : this->todayRunningMeanOutdoorDryBulbTemperature = this->todayAverageOutdoorDryBulbTemperature;
5203 24 : this->yesterdayRunningMeanOutdoorDryBulbTemperature = this->todayAverageOutdoorDryBulbTemperature;
5204 54 : } else if (!state.dataGlobal->WarmupFlag && state.dataGlobal->NumOfDayInEnvrn > 1) {
5205 : // This is an environment with more than one day (non-design day) so...
5206 : // First update yesterday's information using what was previously calculated for "today"
5207 0 : this->yesterdayAverageOutdoorDryBulbTemperature = this->todayAverageOutdoorDryBulbTemperature;
5208 0 : this->yesterdayRunningMeanOutdoorDryBulbTemperature = this->todayRunningMeanOutdoorDryBulbTemperature;
5209 : // Now update the running mean and average outdoor air temperatures
5210 0 : this->todayRunningMeanOutdoorDryBulbTemperature =
5211 0 : (1.0 - constantFlowDesignDataObject.runningMeanOutdoorAirTemperatureWeightingFactor) *
5212 0 : this->yesterdayAverageOutdoorDryBulbTemperature +
5213 0 : constantFlowDesignDataObject.runningMeanOutdoorAirTemperatureWeightingFactor * this->yesterdayRunningMeanOutdoorDryBulbTemperature;
5214 0 : this->todayAverageOutdoorDryBulbTemperature = this->calculateCurrentDailyAverageODB(state);
5215 : }
5216 78 : }
5217 :
5218 24 : Real64 ConstantFlowRadiantSystemData::calculateCurrentDailyAverageODB(EnergyPlusData &state)
5219 : {
5220 24 : Real64 sum = 0.0;
5221 600 : for (int hourNumber = 1; hourNumber <= DataGlobalConstants::HoursInDay; ++hourNumber) {
5222 4032 : for (int timeStepNumber = 1; timeStepNumber <= state.dataGlobal->NumOfTimeStepInHour; ++timeStepNumber) {
5223 3456 : sum += state.dataWeatherManager->TodayOutDryBulbTemp(timeStepNumber, hourNumber);
5224 : }
5225 : }
5226 24 : return sum / double(DataGlobalConstants::HoursInDay * state.dataGlobal->NumOfTimeStepInHour);
5227 : }
5228 :
5229 80871 : void ElectricRadiantSystemData::calculateLowTemperatureRadiantSystem(EnergyPlusData &state,
5230 : Real64 &LoadMet) // load met by the radiant system, in Watts
5231 : {
5232 :
5233 : // SUBROUTINE INFORMATION:
5234 : // AUTHOR Rick Strand
5235 : // DATE WRITTEN November 2000
5236 : // MODIFIED Sep 2011 LKL/BG - resimulate only zones needing it for Radiant systems
5237 :
5238 : // PURPOSE OF THIS SUBROUTINE:
5239 : // This subroutine does all of the stuff that is necessary to simulate
5240 : // a low temperature electric radiant heating system. Calls are made to
5241 : // appropriate subroutines either in this module or outside of it.
5242 :
5243 : // METHODOLOGY EMPLOYED:
5244 : // Follows the methods used by many other pieces of zone equipment except
5245 : // that we are controlling the electrical input to the building element's
5246 : // resistance heating wires. Note that cooling is not allowed for such
5247 : // a system.
5248 :
5249 : // REFERENCES:
5250 : // Other EnergyPlus modules
5251 : // IBLAST-QTF research program, completed in January 1995 (unreleased)
5252 : // Strand, R.K. 1995. "Heat Source Transfer Functions and Their Application to
5253 : // Low Temperature Radiant Heating Systems", Ph.D. dissertation, University
5254 : // of Illinois at Urbana-Champaign, Department of Mechanical and Industrial
5255 : // Engineering.
5256 : // Seem, J.E. 1986. "Heat Transfer in Buildings", Ph.D. dissertation, University
5257 : // of Wisconsin-Madison.
5258 :
5259 : // Using/Aliasing
5260 : using DataHeatBalance::ZoneData;
5261 : using DataHVACGlobals::SmallLoad;
5262 : using ScheduleManager::GetCurrentScheduleValue;
5263 :
5264 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
5265 : Real64 ControlTemp; // Temperature of the parameter that is controlling the radiant system
5266 : Real64 HeatFrac; // fraction of maximum electrical heat input to radiant system [dimensionless]
5267 : Real64 OffTemp; // Temperature above which the radiant system should be completely off [C]
5268 : int RadSurfNum; // number of surface that is the radiant system
5269 : int SurfNum; // intermediate variable for surface number in Surface derived type
5270 : int ZoneNum; // number of zone being served
5271 :
5272 : // initialize local variables
5273 80871 : ZoneNum = this->ZonePtr;
5274 80871 : HeatFrac = 0.0;
5275 80871 : auto &Surface(state.dataSurface->Surface);
5276 :
5277 80871 : if (GetCurrentScheduleValue(state, this->SchedPtr) <= 0.0) {
5278 :
5279 : // Unit is off; set the heat source terms to zero
5280 84720 : for (RadSurfNum = 1; RadSurfNum <= this->NumOfSurfaces; ++RadSurfNum) {
5281 42360 : SurfNum = this->SurfacePtr(RadSurfNum);
5282 42360 : state.dataHeatBalFanSys->QRadSysSource(SurfNum) = 0.0;
5283 42360 : if (Surface(SurfNum).ExtBoundCond > 0 && Surface(SurfNum).ExtBoundCond != SurfNum)
5284 0 : state.dataHeatBalFanSys->QRadSysSource(Surface(SurfNum).ExtBoundCond) = 0.0; // Also zero the other side of an interzone
5285 : }
5286 :
5287 : } else { // Unit might be on-->this section is intended to determine whether the controls say
5288 : // that the unit should be on or not
5289 :
5290 : // Determine the current setpoint temperature and the temperature at which the unit should be completely off
5291 38511 : OffTemp = this->setOffTemperatureLowTemperatureRadiantSystem(state, this->SetptSchedPtr, this->ThrottlRange, this->SetpointType);
5292 :
5293 : // Determine the control temperature--what the setpoint/offtemp is being compared to for unit operation
5294 :
5295 38511 : ControlTemp = this->setRadiantSystemControlTemperature(state, controlType);
5296 :
5297 38511 : if (ControlTemp < OffTemp) { // HEATING MODE
5298 :
5299 29745 : this->OperatingMode = HeatingMode;
5300 :
5301 29745 : HeatFrac = this->calculateOperationalFraction(OffTemp, ControlTemp, this->ThrottlRange);
5302 :
5303 : // Set the heat source for the low temperature electric radiant system
5304 59490 : for (RadSurfNum = 1; RadSurfNum <= this->NumOfSurfaces; ++RadSurfNum) {
5305 29745 : SurfNum = this->SurfacePtr(RadSurfNum);
5306 29745 : state.dataHeatBalFanSys->QRadSysSource(SurfNum) = HeatFrac * this->MaxElecPower * this->SurfaceFrac(RadSurfNum);
5307 29745 : if (Surface(SurfNum).ExtBoundCond > 0 && Surface(SurfNum).ExtBoundCond != SurfNum)
5308 0 : state.dataHeatBalFanSys->QRadSysSource(Surface(SurfNum).ExtBoundCond) =
5309 0 : state.dataHeatBalFanSys->QRadSysSource(SurfNum); // Also set the other side of an interzone
5310 : }
5311 :
5312 : // Now "simulate" the system by recalculating the heat balances
5313 29745 : HeatBalanceSurfaceManager::CalcHeatBalanceOutsideSurf(state, ZoneNum);
5314 29745 : HeatBalanceSurfaceManager::CalcHeatBalanceInsideSurf(state, ZoneNum);
5315 :
5316 29745 : LoadMet = state.dataHeatBal->Zone(ZoneNum).sumHATsurf(state) - state.dataLowTempRadSys->ZeroSourceSumHATsurf(ZoneNum);
5317 :
5318 : } else { // OFF or COOLING MODE (not allowed for an electric low temperature radiant system), turn it off
5319 :
5320 17532 : for (RadSurfNum = 1; RadSurfNum <= this->NumOfSurfaces; ++RadSurfNum) {
5321 8766 : SurfNum = this->SurfacePtr(RadSurfNum);
5322 8766 : state.dataHeatBalFanSys->QRadSysSource(SurfNum) = 0.0;
5323 8766 : if (Surface(SurfNum).ExtBoundCond > 0 && Surface(SurfNum).ExtBoundCond != SurfNum)
5324 0 : state.dataHeatBalFanSys->QRadSysSource(Surface(SurfNum).ExtBoundCond) = 0.0; // Also zero the other side of an interzone
5325 : }
5326 : }
5327 : }
5328 80871 : }
5329 :
5330 684904 : void RadiantSystemBaseData::updateLowTemperatureRadiantSystemSurfaces(EnergyPlusData &state)
5331 : {
5332 :
5333 : // The purpose of this routine is to update the average heat source/sink for a particular system over the various system time
5334 : // steps that make up the zone time step. For hydronic systems, this routine must also set the outlet water conditions.
5335 : // For the source/sink average update, if the system time step elapsed is still what it used to be, then either we are still
5336 : // iterating orwe had to go back and shorten the time step. As a result, we have to subtract out the previous value that we
5337 : // added. If the system time step elapsed is different, then we just need to add the new values to the running average.
5338 :
5339 : // Using/Aliasing
5340 684904 : auto &SysTimeElapsed = state.dataHVACGlobal->SysTimeElapsed;
5341 684904 : auto &TimeStepSys = state.dataHVACGlobal->TimeStepSys;
5342 :
5343 : // SUBROUTINE PARAMETER DEFINITIONS:
5344 :
5345 1410242 : for (int radSurfNum = 1; radSurfNum <= this->NumOfSurfaces; ++radSurfNum) {
5346 :
5347 725338 : int surfNum = this->SurfacePtr(radSurfNum);
5348 :
5349 725338 : if (state.dataLowTempRadSys->LastSysTimeElapsed(surfNum) == SysTimeElapsed) {
5350 : // Still iterating or reducing system time step, so subtract old values which were
5351 : // not valid
5352 1989183 : state.dataLowTempRadSys->QRadSysSrcAvg(surfNum) -= state.dataLowTempRadSys->LastQRadSysSrc(surfNum) *
5353 1326122 : state.dataLowTempRadSys->LastTimeStepSys(surfNum) / state.dataGlobal->TimeStepZone;
5354 : }
5355 :
5356 : // Update the running average and the "last" values with the current values of the appropriate variables
5357 725338 : state.dataLowTempRadSys->QRadSysSrcAvg(surfNum) +=
5358 725338 : state.dataHeatBalFanSys->QRadSysSource(surfNum) * TimeStepSys / state.dataGlobal->TimeStepZone;
5359 :
5360 725338 : state.dataLowTempRadSys->LastQRadSysSrc(surfNum) = state.dataHeatBalFanSys->QRadSysSource(surfNum);
5361 725338 : state.dataLowTempRadSys->LastSysTimeElapsed(surfNum) = SysTimeElapsed;
5362 725338 : state.dataLowTempRadSys->LastTimeStepSys(surfNum) = TimeStepSys;
5363 : }
5364 684904 : }
5365 :
5366 372334 : void VariableFlowRadiantSystemData::updateLowTemperatureRadiantSystem(EnergyPlusData &state)
5367 : {
5368 :
5369 : // Using/Aliasing
5370 : using FluidProperties::GetSpecificHeatGlycol;
5371 : using PlantUtilities::SafeCopyPlantNode;
5372 : using PlantUtilities::SetComponentFlowRate;
5373 :
5374 : // SUBROUTINE PARAMETER DEFINITIONS:
5375 372334 : auto constexpr RoutineName("UpdateVariableFlowSystem");
5376 :
5377 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
5378 : Real64 cpWater; // Specific heat of water
5379 : int waterInletNode; // Node number for the water side inlet of the radiant system
5380 : Real64 waterMassFlow; // Flow rate of water in the radiant system
5381 : int waterOutletNode; // Node number for the water side outlet of the radiant system
5382 :
5383 372334 : auto &Zone(state.dataHeatBal->Zone);
5384 372334 : auto &Node(state.dataLoopNodes->Node);
5385 :
5386 : // For a hydronic system, calculate the water side outlet conditions and set the
5387 : // appropriate conditions on the correct HVAC node.
5388 :
5389 : // First sum up all of the heat sources/sinks associated with this system
5390 372334 : Real64 TotalHeatSource(0.0); // Total heat source or sink for a particular radiant system (sum of all surface source/sinks)
5391 785102 : for (int radSurfNum = 1; radSurfNum <= this->NumOfSurfaces; ++radSurfNum) {
5392 412768 : TotalHeatSource += state.dataHeatBalFanSys->QRadSysSource(this->SurfacePtr(radSurfNum));
5393 : }
5394 372334 : TotalHeatSource *= double(Zone(this->ZonePtr).Multiplier * Zone(this->ZonePtr).ListMultiplier);
5395 :
5396 : // Update the heating side of things
5397 372334 : if (this->HeatingSystem) {
5398 :
5399 372288 : waterInletNode = this->HotWaterInNode;
5400 372288 : waterOutletNode = this->HotWaterOutNode;
5401 372288 : waterMassFlow = Node(waterInletNode).MassFlowRate;
5402 :
5403 1116864 : cpWater = GetSpecificHeatGlycol(state,
5404 372288 : state.dataPlnt->PlantLoop(this->HWPlantLoc.loopNum).FluidName,
5405 372288 : Node(waterInletNode).Temp,
5406 372288 : state.dataPlnt->PlantLoop(this->HWPlantLoc.loopNum).FluidIndex,
5407 372288 : RoutineName);
5408 :
5409 372288 : if (this->OperatingMode == HeatingMode) {
5410 152746 : if ((cpWater > 0.0) && (waterMassFlow > 0.0)) {
5411 152740 : SafeCopyPlantNode(state, waterInletNode, waterOutletNode);
5412 152740 : Node(waterOutletNode).Temp = Node(waterInletNode).Temp - TotalHeatSource / waterMassFlow / cpWater;
5413 : } else {
5414 6 : SafeCopyPlantNode(state, waterInletNode, waterOutletNode);
5415 : }
5416 :
5417 : } else { // CoolingMode or not on
5418 219542 : SafeCopyPlantNode(state, waterInletNode, waterOutletNode);
5419 : }
5420 :
5421 372288 : this->checkForOutOfRangeTemperatureResult(state, Node(waterOutletNode).Temp, Node(waterInletNode).Temp);
5422 : }
5423 :
5424 372334 : if (this->CoolingSystem) {
5425 :
5426 357489 : waterInletNode = this->ColdWaterInNode;
5427 357489 : waterOutletNode = this->ColdWaterOutNode;
5428 357489 : waterMassFlow = Node(waterInletNode).MassFlowRate;
5429 :
5430 1072467 : cpWater = GetSpecificHeatGlycol(state,
5431 357489 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidName,
5432 357489 : Node(waterInletNode).Temp,
5433 357489 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidIndex,
5434 357489 : RoutineName);
5435 :
5436 357489 : if (this->OperatingMode == CoolingMode) {
5437 121273 : if ((cpWater > 0.0) && (waterMassFlow > 0.0)) {
5438 121243 : SafeCopyPlantNode(state, waterInletNode, waterOutletNode);
5439 121243 : Node(waterOutletNode).Temp = Node(waterInletNode).Temp - TotalHeatSource / waterMassFlow / cpWater;
5440 : } else {
5441 30 : SafeCopyPlantNode(state, waterInletNode, waterOutletNode);
5442 : }
5443 :
5444 : } else { // HeatingMode or not on
5445 236216 : SafeCopyPlantNode(state, waterInletNode, waterOutletNode);
5446 : }
5447 :
5448 357489 : this->checkForOutOfRangeTemperatureResult(state, Node(waterOutletNode).Temp, Node(waterInletNode).Temp);
5449 : }
5450 372334 : }
5451 :
5452 231699 : void ConstantFlowRadiantSystemData::updateLowTemperatureRadiantSystem(EnergyPlusData &state)
5453 : {
5454 :
5455 : // Using/Aliasing
5456 : using FluidProperties::GetSpecificHeatGlycol;
5457 : using PlantUtilities::SafeCopyPlantNode;
5458 : using PlantUtilities::SetComponentFlowRate;
5459 :
5460 : Real64 bypassMassFlow; // Local bypass for a constant flow radiant system (could have recirculation and/or bypass)
5461 : int waterInletNode; // Node number for the water side inlet of the radiant system
5462 : int waterOutletNode; // Node number for the water side outlet of the radiant system
5463 :
5464 : // For a constant flow system, calculate the water side outlet conditions
5465 : // and set the appropriate conditions on the correct HVAC node. This may
5466 : // require mixing if the main system does not provide all of the flow that
5467 : // the local radiant system circulates.
5468 :
5469 : // Update the heating side of things
5470 231699 : if (this->HeatingSystem) {
5471 :
5472 231698 : waterInletNode = this->HotWaterInNode;
5473 231698 : waterOutletNode = this->HotWaterOutNode;
5474 231698 : SafeCopyPlantNode(state, waterInletNode, waterOutletNode);
5475 :
5476 231698 : if (this->OperatingMode == HeatingMode) {
5477 :
5478 : // Leave the inlet and outlet flow alone (if high enough) and perform a bypass if more flow than needed
5479 69687 : if (state.dataLoopNodes->Node(waterInletNode).MassFlowRate <= this->WaterInjectionRate) {
5480 : // Note that the water injection rate has already been restricted to the maximum available flow
5481 0 : state.dataLoopNodes->Node(waterOutletNode).Temp = this->WaterOutletTemp;
5482 : } else {
5483 : // Loop is providing more flow than needed so perform a local bypass and
5484 : // mix the flows to obtain the proper outlet temperature. In this case,
5485 : // the mass flow rates on the loop are left alone and the outlet temperature
5486 : // is calculated from a simple steady-steady, steady-flow energy balance.
5487 69687 : bypassMassFlow = state.dataLoopNodes->Node(waterInletNode).MassFlowRate - this->WaterInjectionRate;
5488 69687 : state.dataLoopNodes->Node(waterOutletNode).Temp =
5489 139374 : ((bypassMassFlow * state.dataLoopNodes->Node(waterInletNode).Temp) + (this->WaterInjectionRate * this->WaterOutletTemp)) /
5490 69687 : (state.dataLoopNodes->Node(waterOutletNode).MassFlowRate);
5491 : }
5492 : }
5493 695094 : this->checkForOutOfRangeTemperatureResult(
5494 463396 : state, state.dataLoopNodes->Node(waterOutletNode).Temp, state.dataLoopNodes->Node(waterInletNode).Temp);
5495 : }
5496 :
5497 231699 : if (this->CoolingSystem) {
5498 :
5499 217853 : waterInletNode = this->ColdWaterInNode;
5500 217853 : waterOutletNode = this->ColdWaterOutNode;
5501 217853 : SafeCopyPlantNode(state, waterInletNode, waterOutletNode);
5502 :
5503 217853 : if (this->OperatingMode == CoolingMode) {
5504 :
5505 111926 : if (state.dataLoopNodes->Node(waterInletNode).MassFlowRate <= this->WaterInjectionRate) {
5506 : // Note that the water injection rate has already been restricted to the maximum available flow
5507 :
5508 20929 : state.dataLoopNodes->Node(waterOutletNode).Temp = this->WaterOutletTemp;
5509 : } else {
5510 : // Loop is providing more flow than needed so perform a local bypass and
5511 : // mix the flows to obtain the proper outlet temperature. In this case,
5512 : // the mass flow rates on the loop are left alone and the outlet temperature
5513 : // is calculated from a simple steady-steady, steady-flow energy balance.
5514 90997 : bypassMassFlow = state.dataLoopNodes->Node(waterInletNode).MassFlowRate - this->WaterInjectionRate;
5515 90997 : state.dataLoopNodes->Node(waterOutletNode).Temp =
5516 181994 : ((bypassMassFlow * state.dataLoopNodes->Node(waterInletNode).Temp) + (this->WaterInjectionRate * this->WaterOutletTemp)) /
5517 90997 : (state.dataLoopNodes->Node(waterOutletNode).MassFlowRate);
5518 : }
5519 :
5520 335778 : this->checkForOutOfRangeTemperatureResult(
5521 223852 : state, state.dataLoopNodes->Node(waterOutletNode).Temp, state.dataLoopNodes->Node(waterInletNode).Temp);
5522 : }
5523 : }
5524 231699 : }
5525 :
5526 80871 : void ElectricRadiantSystemData::updateLowTemperatureRadiantSystem([[maybe_unused]] EnergyPlusData &state)
5527 : { // Dummy routine: no updates are needed for electric radiant systems
5528 80871 : }
5529 :
5530 1073401 : void HydronicSystemBaseData::checkForOutOfRangeTemperatureResult(EnergyPlusData &state, Real64 const outletTemp, Real64 const inletTemp)
5531 : {
5532 :
5533 : // SUBROUTINE INFORMATION:
5534 : // AUTHOR B. Griffith
5535 : // DATE WRITTEN March 2013
5536 :
5537 : // PURPOSE OF THIS SUBROUTINE:
5538 : // check for crazy, out of range temperature results for fluid leaving radiant system
5539 :
5540 : // Using/Aliasing
5541 :
5542 1073401 : Real64 constexpr upperRangeLimit(500.0); // high error trigger limit for when model is not working
5543 1073401 : Real64 constexpr lowerRangeLimit(-300.0); // Low error trigger limit for when model is not working
5544 :
5545 1073401 : if (outletTemp < lowerRangeLimit) {
5546 0 : state.dataLowTempRadSys->warnTooLow = true;
5547 : }
5548 :
5549 1073401 : if (outletTemp > upperRangeLimit) {
5550 0 : state.dataLowTempRadSys->warnTooHigh = true;
5551 : }
5552 :
5553 1073401 : if (state.dataLowTempRadSys->warnTooLow || state.dataLowTempRadSys->warnTooHigh) {
5554 0 : if (state.dataLowTempRadSys->warnTooLow) {
5555 0 : if (this->OutRangeLoErrorCount == 0) {
5556 0 : ShowSevereMessage(state, "UpdateLowTempRadiantSystem: model result for fluid outlet temperature is not physical.");
5557 0 : ShowContinueError(state, "Occurs for radiant system name = " + this->Name);
5558 0 : ShowContinueError(state, format("Calculated radiant system outlet temperature = {:.3R} [C]", outletTemp));
5559 0 : ShowContinueError(state, format("Radiant system inlet temperature = {:.3R} [C]", inletTemp));
5560 0 : ShowContinueError(
5561 : state, "A possible cause is that the materials used in the internal source construction are not compatible with the model.");
5562 : }
5563 0 : ShowRecurringSevereErrorAtEnd(
5564 : state,
5565 0 : "UpdateLowTempRadiantSystem: Detected low out of range outlet temperature result for radiant system name =" + this->Name,
5566 : this->OutRangeLoErrorCount,
5567 : outletTemp,
5568 : outletTemp);
5569 : }
5570 :
5571 0 : if (state.dataLowTempRadSys->warnTooHigh) {
5572 0 : if (this->OutRangeHiErrorCount == 0) {
5573 0 : ShowSevereMessage(state, "UpdateLowTempRadiantSystem: model result for fluid outlet temperature is not physical.");
5574 0 : ShowContinueError(state, "Occurs for radiant system name = " + this->Name);
5575 0 : ShowContinueError(state, format("Calculated radiant system outlet temperature = {:.3R} [C]", outletTemp));
5576 0 : ShowContinueError(state, format("Radiant system inlet temperature = {:.3R} [C]", inletTemp));
5577 0 : ShowContinueError(
5578 : state, "A possible cause is that the materials used in the internal source construction are not compatible with the model.");
5579 : }
5580 0 : ShowRecurringSevereErrorAtEnd(
5581 : state,
5582 0 : "UpdateLowTempRadiantSystem: Detected high out of range outlet temperature result radiant system name =" + this->Name,
5583 : this->OutRangeHiErrorCount,
5584 : outletTemp,
5585 : outletTemp);
5586 : }
5587 : }
5588 1073401 : }
5589 :
5590 627055 : Real64 RadiantSystemBaseData::setRadiantSystemControlTemperature(EnergyPlusData &state, LowTempRadiantControlTypes TempControlType)
5591 : {
5592 627055 : auto &thisZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(this->ZonePtr);
5593 627055 : switch (TempControlType) {
5594 486284 : case LowTempRadiantControlTypes::MATControl:
5595 486284 : return thisZoneHB.MAT;
5596 25325 : case LowTempRadiantControlTypes::MRTControl:
5597 25325 : return state.dataHeatBal->ZoneMRT(this->ZonePtr);
5598 25313 : case LowTempRadiantControlTypes::OperativeControl:
5599 25313 : return 0.5 * (thisZoneHB.MAT + state.dataHeatBal->ZoneMRT(this->ZonePtr));
5600 16682 : case LowTempRadiantControlTypes::ODBControl:
5601 16682 : return state.dataHeatBal->Zone(this->ZonePtr).OutDryBulbTemp;
5602 14483 : case LowTempRadiantControlTypes::OWBControl:
5603 14483 : return state.dataHeatBal->Zone(this->ZonePtr).OutWetBulbTemp;
5604 15918 : case LowTempRadiantControlTypes::SurfFaceTempControl:
5605 15918 : return state.dataHeatBalSurf->SurfTempIn(this->SurfacePtr(1)); // Grabs the inside face temperature of the first surface in the list
5606 15918 : case LowTempRadiantControlTypes::SurfIntTempControl:
5607 15918 : return state.dataHeatBalSurf->SurfTempUserLoc(
5608 15918 : this->SurfacePtr(1)); // Grabs the temperature inside the slab at the location specified by the user
5609 27132 : case LowTempRadiantControlTypes::RunningMeanODBControl:
5610 27132 : return this->todayRunningMeanOutdoorDryBulbTemperature;
5611 0 : default:
5612 0 : ShowSevereError(state, "Illegal control type in low temperature radiant system or it's design object: " + this->Name);
5613 0 : ShowFatalError(state, "Preceding condition causes termination.");
5614 0 : return 0.0; // hush the compiler
5615 : }
5616 : }
5617 :
5618 : Real64
5619 324512 : RadiantSystemBaseData::calculateOperationalFraction(Real64 const offTemperature, Real64 const controlTemperature, Real64 const throttlingRange)
5620 : {
5621 324512 : Real64 temperatureDifference = std::abs(offTemperature - controlTemperature);
5622 324512 : if (temperatureDifference <= 0.0) {
5623 0 : return 0.0; // No temperature difference--turn things off (set to zero); technically shouldn't happen
5624 324512 : } else if (throttlingRange < 0.001) {
5625 8496 : return 1.0; // Throttling range is essentially zero and there is a temperature difference--turn it full on
5626 : } else {
5627 : // Temperature difference is non-zero and less than the throttling range--calculate the operation fraction, but limit to a maximum of 1.0
5628 316016 : return min(temperatureDifference / throttlingRange, 1.0);
5629 : }
5630 : }
5631 :
5632 760610 : Real64 RadiantSystemBaseData::setOffTemperatureLowTemperatureRadiantSystem(EnergyPlusData &state,
5633 : const int scheduleIndex,
5634 : const Real64 throttlingRange,
5635 : LowTempRadiantSetpointTypes SetpointControlType)
5636 : {
5637 760610 : Real64 scheduleValue = ScheduleManager::GetCurrentScheduleValue(state, scheduleIndex);
5638 760610 : switch (SetpointControlType) {
5639 712816 : case LowTempRadiantSetpointTypes::HalfFlowPower:
5640 712816 : return scheduleValue + 0.5 * throttlingRange;
5641 47794 : case LowTempRadiantSetpointTypes::ZeroFlowPower:
5642 47794 : return scheduleValue;
5643 0 : default:
5644 0 : ShowSevereError(state, "Illegal setpoint type in low temperature radiant system: " + this->Name);
5645 0 : ShowFatalError(state, "Preceding condition causes termination.");
5646 0 : return scheduleValue + 0.5 * throttlingRange; // hush the compiler
5647 : }
5648 : }
5649 :
5650 : Real64
5651 522807 : HydronicSystemBaseData::calculateHXEffectivenessTerm(EnergyPlusData &state,
5652 : int const SurfNum, // Surface number for this particular part of the radiant system
5653 : Real64 const Temperature, // Temperature of water entering the radiant system, in C
5654 : Real64 const WaterMassFlow, // Mass flow rate of water in the radiant system, in kg/s
5655 : Real64 const FlowFraction, // Mass flow rate fraction for this surface in the radiant system
5656 : Real64 const NumCircs, // Number of fluid circuits in this surface
5657 : int const DesignObjPtr, // Design Object Pointer
5658 : LowTempRadiantSystem::SystemType const typeOfRadiantSystem)
5659 : {
5660 :
5661 : // SUBROUTINE INFORMATION:
5662 : // AUTHOR Rick Strand
5663 : // DATE WRITTEN December 2000
5664 :
5665 : // PURPOSE OF THIS SUBROUTINE:
5666 : // This subroutine calculates the radiant system "heat exchanger"
5667 : // effectiveness term. This is equal to the mass flow rate of water
5668 : // times the specific heat of water times the effectiveness of
5669 : // the heat exchanger (radiant system "coil").
5670 :
5671 : // METHODOLOGY EMPLOYED:
5672 : // Assumes that the only real heat transfer term that we have to
5673 : // deal with is the convection from the water to the tube. The
5674 : // other assumptions are that the tube inside surface temperature
5675 : // is equal to the "source location temperature" and that it is
5676 : // a CONSTANT throughout the radiant system. This is to make
5677 : // the problem more tractable and to fit with other system assumptions
5678 : // that were made elsewhere in the radiant system model.
5679 :
5680 : // REFERENCES:
5681 : // Property data for water shown below as parameters taken from
5682 : // Incropera and DeWitt, Introduction to Heat Transfer, Table A.6.
5683 : // Heat exchanger information also from Incropera and DeWitt.
5684 : // Code based loosely on code from IBLAST program (research version)
5685 :
5686 : // Using/Aliasing
5687 : using FluidProperties::GetSpecificHeatGlycol;
5688 :
5689 : // Return value
5690 : Real64 calculateHXEffectivenessTerm;
5691 :
5692 : // SUBROUTINE PARAMETER DEFINITIONS:
5693 522807 : Real64 constexpr MaxLaminarRe(2300.0); // Maximum Reynolds number for laminar flow
5694 522807 : int constexpr NumOfPropDivisions(13);
5695 522807 : Real64 constexpr MaxExpPower(50.0); // Maximum power after which EXP argument would be zero for DP variables
5696 : Array1D<Real64> Temps(NumOfPropDivisions,
5697 1045614 : {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
5698 : Array1D<Real64> Mu(NumOfPropDivisions,
5699 : {0.001652,
5700 : 0.001422,
5701 : 0.001225,
5702 : 0.00108,
5703 : 0.000959,
5704 : 0.000855,
5705 : 0.000769,
5706 : 0.000695,
5707 : 0.000631,
5708 : 0.000577,
5709 : 0.000528,
5710 : 0.000489,
5711 1045614 : 0.000453}); // Viscosity, in Ns/m2
5712 : Array1D<Real64> Conductivity(
5713 1045614 : NumOfPropDivisions, {0.574, 0.582, 0.590, 0.598, 0.606, 0.613, 0.620, 0.628, 0.634, 0.640, 0.645, 0.650, 0.656}); // Conductivity, in W/mK
5714 : Array1D<Real64> Pr(NumOfPropDivisions,
5715 1045614 : {12.22, 10.26, 8.81, 7.56, 6.62, 5.83, 5.20, 4.62, 4.16, 3.77, 3.42, 3.15, 2.88}); // Prandtl number (dimensionless)
5716 522807 : auto constexpr RoutineName("calculateHXEffectivenessTerm");
5717 :
5718 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
5719 : int Index;
5720 : Real64 InterpFrac;
5721 : Real64 NuD;
5722 : Real64 ReD;
5723 : Real64 NTU;
5724 522807 : Real64 CpWater(0.0);
5725 : Real64 Kactual;
5726 : Real64 MUactual;
5727 : Real64 PRactual;
5728 : Real64 Eff; // HX effectiveness
5729 :
5730 522807 : FluidToSlabHeatTransferTypes FluidToSlabHeatTransfer(FluidToSlabHeatTransferTypes::ConvectionOnly);
5731 522807 : Real64 TubeDiameterInner(0.0); // inside tube diameter for embedded tubing (meters)
5732 522807 : Real64 TubeDiameterOuter(0.0); // outside tube diameter for embedded tubing (meters)
5733 :
5734 522807 : if (typeOfRadiantSystem == LowTempRadiantSystem::SystemType::HydronicSystem) {
5735 : VarFlowRadDesignData variableFlowDesignDataObject{
5736 649602 : state.dataLowTempRadSys->HydronicRadiantSysDesign(DesignObjPtr)}; // Contains the data for variable flow hydronic systems
5737 324801 : FluidToSlabHeatTransfer = variableFlowDesignDataObject.FluidToSlabHeatTransfer;
5738 324801 : TubeDiameterInner = variableFlowDesignDataObject.TubeDiameterInner;
5739 324801 : TubeDiameterOuter = variableFlowDesignDataObject.TubeDiameterOuter;
5740 : }
5741 522807 : if (typeOfRadiantSystem == LowTempRadiantSystem::SystemType::ConstantFlowSystem) {
5742 : ConstantFlowRadDesignData constantFlowDesignDataObject{
5743 396012 : state.dataLowTempRadSys->CflowRadiantSysDesign(DesignObjPtr)}; // Contains the data for constant flow hydronic systems
5744 198006 : FluidToSlabHeatTransfer = constantFlowDesignDataObject.FluidToSlabHeatTransfer;
5745 198006 : TubeDiameterInner = constantFlowDesignDataObject.TubeDiameterInner;
5746 198006 : TubeDiameterOuter = constantFlowDesignDataObject.TubeDiameterOuter;
5747 : }
5748 :
5749 : // First find out where we are in the range of temperatures
5750 522807 : Index = 1;
5751 6900171 : while (Index <= NumOfPropDivisions) {
5752 3711489 : if (Temperature < Temps(Index)) break; // DO loop
5753 3188682 : ++Index;
5754 : }
5755 :
5756 : // Initialize thermal properties of water
5757 522807 : if (Index == 1) {
5758 0 : MUactual = Mu(Index);
5759 0 : Kactual = Conductivity(Index);
5760 0 : PRactual = Pr(Index);
5761 522807 : } else if (Index > NumOfPropDivisions) {
5762 0 : Index = NumOfPropDivisions;
5763 0 : MUactual = Mu(Index);
5764 0 : Kactual = Conductivity(Index);
5765 0 : PRactual = Pr(Index);
5766 : } else {
5767 522807 : InterpFrac = (Temperature - Temps(Index - 1)) / (Temps(Index) - Temps(Index - 1));
5768 522807 : MUactual = Mu(Index - 1) + InterpFrac * (Mu(Index) - Mu(Index - 1));
5769 522807 : Kactual = Conductivity(Index - 1) + InterpFrac * (Conductivity(Index) - Conductivity(Index - 1));
5770 522807 : PRactual = Pr(Index - 1) + InterpFrac * (Pr(Index) - Pr(Index - 1));
5771 : }
5772 : // arguments are glycol name, temperature, and concentration
5773 522807 : switch (this->OperatingMode) {
5774 240320 : case HeatingMode: {
5775 480640 : CpWater = GetSpecificHeatGlycol(state,
5776 240320 : state.dataPlnt->PlantLoop(this->HWPlantLoc.loopNum).FluidName,
5777 : Temperature,
5778 240320 : state.dataPlnt->PlantLoop(this->HWPlantLoc.loopNum).FluidIndex,
5779 240320 : RoutineName);
5780 240320 : } break;
5781 282487 : case CoolingMode: {
5782 564974 : CpWater = GetSpecificHeatGlycol(state,
5783 282487 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidName,
5784 : Temperature,
5785 282487 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidIndex,
5786 282487 : RoutineName);
5787 282487 : } break;
5788 0 : default: {
5789 0 : assert(false);
5790 : } break;
5791 : }
5792 :
5793 : // Calculate NTU based on the heat transfer model
5794 :
5795 522807 : if (FluidToSlabHeatTransfer == FluidToSlabHeatTransferTypes::ISOStandard) {
5796 :
5797 53162 : Real64 U = this->calculateUFromISOStandard(state, SurfNum, WaterMassFlow * FlowFraction, typeOfRadiantSystem, DesignObjPtr);
5798 :
5799 : // Calculate the NTU parameter
5800 : // NTU = UA/[(Mdot*Cp)min]
5801 : // where: U = h (convection coefficient) and h = (k)(Nu)/D
5802 : // A = DataGlobalConstants::Pi()*D*TubeLength
5803 53162 : NTU = U * DataGlobalConstants::Pi * TubeDiameterOuter * this->TubeLength / (WaterMassFlow * CpWater); // FlowFraction cancels out here
5804 : } else { // (this->FluidToSlabHeatTransfer == FluidToSlabHeatTransferTypes::ConvectionOnly)
5805 :
5806 : // Calculate the Reynold's number from RE=(4*Mdot)/(Pi*Mu*Diameter)
5807 469645 : ReD = 4.0 * WaterMassFlow * FlowFraction / (DataGlobalConstants::Pi * MUactual * TubeDiameterInner * NumCircs);
5808 :
5809 : // Calculate the Nusselt number based on what flow regime one is in
5810 469645 : if (ReD >= MaxLaminarRe) { // Turbulent flow --> use Colburn equation
5811 :
5812 445935 : NuD = 0.023 * std::pow(ReD, 0.8) * std::pow(PRactual, 1.0 / 3.0);
5813 :
5814 : } else { // Laminar flow --> use constant surface temperature relation
5815 :
5816 23710 : NuD = 3.66;
5817 : }
5818 :
5819 : // Calculate the NTU parameter
5820 : // NTU = UA/[(Mdot*Cp)min]
5821 : // where: U = h (convection coefficient) and h = (k)(Nu)/D
5822 : // A = Pi*D*TubeLength
5823 469645 : NTU = DataGlobalConstants::Pi * Kactual * NuD * this->TubeLength / (WaterMassFlow * CpWater); // FlowFraction cancels out here
5824 : }
5825 :
5826 : // Calculate Epsilon*MassFlowRate*Cp
5827 522807 : if (NTU > MaxExpPower) {
5828 426916 : Eff = 1.0;
5829 426916 : calculateHXEffectivenessTerm = FlowFraction * WaterMassFlow * CpWater;
5830 : } else {
5831 95891 : Eff = 1.0 - std::exp(-NTU);
5832 95891 : calculateHXEffectivenessTerm = Eff * FlowFraction * WaterMassFlow * CpWater;
5833 : }
5834 :
5835 1045614 : return calculateHXEffectivenessTerm;
5836 : }
5837 :
5838 53162 : Real64 HydronicSystemBaseData::calculateUFromISOStandard(EnergyPlusData &state,
5839 : int const SurfNum,
5840 : Real64 const WaterMassFlow,
5841 : SystemType typeOfRadiantSystem,
5842 : int const DesignObjPtr // Design Object Pointer
5843 : )
5844 : {
5845 : // Calculates the U-value for a pipe embedded in a radiant system using the information
5846 : // from ISO Standard 11855, Part 2 (2012): "Building environment design — Design, dimensioning,
5847 : // installation and control of embedded radiant heating and cooling systems — Part 2:
5848 : // Determination of the design heating and cooling capacity." This looks exclusively at the heat transfer
5849 : // between the fluid and the inner side of the pipe and heat conduction through the pipe. The remainder
5850 : // of the ISO calculation relates to the slab itself which is modeled using transient heat conduction here
5851 : // in EnergyPlus.
5852 :
5853 : // Return value
5854 : Real64 calculateUFromISOStandard;
5855 :
5856 53162 : int constructionNumber = state.dataSurface->Surface(SurfNum).Construction;
5857 :
5858 53162 : Real64 TubeDiameterOuter(0.0);
5859 53162 : Real64 TubeDiameterInner(0.0);
5860 53162 : Real64 TubeConductivity(0.0);
5861 :
5862 53162 : if (typeOfRadiantSystem == LowTempRadiantSystem::SystemType::HydronicSystem) {
5863 : VarFlowRadDesignData variableFlowDesignDataObject{
5864 46090 : state.dataLowTempRadSys->HydronicRadiantSysDesign(DesignObjPtr)}; // Contains the data for variable flow hydronic systems
5865 23045 : TubeDiameterOuter = variableFlowDesignDataObject.TubeDiameterOuter;
5866 23045 : TubeDiameterInner = variableFlowDesignDataObject.TubeDiameterInner;
5867 23045 : TubeConductivity = variableFlowDesignDataObject.VarFlowTubeConductivity;
5868 : }
5869 53162 : if (typeOfRadiantSystem == LowTempRadiantSystem::SystemType::ConstantFlowSystem) {
5870 : ConstantFlowRadDesignData constantFlowDesignDataObject{
5871 60234 : state.dataLowTempRadSys->CflowRadiantSysDesign(DesignObjPtr)}; // Contains the data for constant flow hydronic systems
5872 30117 : TubeDiameterOuter = constantFlowDesignDataObject.TubeDiameterOuter;
5873 30117 : TubeDiameterInner = constantFlowDesignDataObject.TubeDiameterInner;
5874 30117 : TubeConductivity = constantFlowDesignDataObject.ConstFlowTubeConductivity;
5875 : }
5876 :
5877 : // Fluid resistance to heat transfer, assumes turbulent flow (Equation B5, p. 38 of ISO Standard 11855-2)
5878 53162 : Real64 distanceBetweenPipes = 2.0 * state.dataConstruction->Construct(constructionNumber).ThicknessPerpend;
5879 53162 : Real64 ratioDiameterToMassFlowLength = TubeDiameterInner / WaterMassFlow / this->TubeLength;
5880 53162 : Real64 rFluid = 0.125 / DataGlobalConstants::Pi * std::pow(distanceBetweenPipes, 0.13) * std::pow(ratioDiameterToMassFlowLength, 0.87);
5881 :
5882 : // Resistance to heat transfer (conduction through the piping material, Equation B6, p. 38 of ISO Standard 11855-2)
5883 53162 : Real64 rTube = 0.5 * distanceBetweenPipes * std::log(TubeDiameterOuter / TubeDiameterInner) / DataGlobalConstants::Pi / TubeConductivity;
5884 :
5885 53162 : calculateUFromISOStandard = 1.0 / (rFluid + rTube);
5886 :
5887 53162 : return calculateUFromISOStandard;
5888 : }
5889 :
5890 2568313 : void UpdateRadSysSourceValAvg(EnergyPlusData &state,
5891 : bool &LowTempRadSysOn) // .TRUE. if the radiant system has run this zone time step
5892 : {
5893 :
5894 : // SUBROUTINE INFORMATION:
5895 : // AUTHOR Rick Strand
5896 : // DATE WRITTEN November 2000
5897 :
5898 : // PURPOSE OF THIS SUBROUTINE:
5899 : // To transfer the average value of the heat source/sink over the entire
5900 : // zone time step back to the heat balance routines so that the heat
5901 : // balance algorithms can simulate one last time with the average source
5902 : // to maintain some reasonable amount of continuity and energy balance
5903 : // in the temperature and flux histories.
5904 :
5905 : // METHODOLOGY EMPLOYED:
5906 : // All of the record keeping for the average term is done in the Update
5907 : // routine so the only other thing that this subroutine does is check to
5908 : // see if the system was even on. If any average term is non-zero, then
5909 : // one or more of the radiant systems was running.
5910 :
5911 : // SUBROUTINE PARAMETER DEFINITIONS:
5912 2568313 : Real64 constexpr CloseEnough(0.01); // Some arbitrarily small value to avoid zeros and numbers that are almost the same
5913 :
5914 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
5915 : int SurfNum; // DO loop counter for surface index
5916 :
5917 2568313 : LowTempRadSysOn = false;
5918 :
5919 : // If this was never allocated, then there are no radiant systems in this input file (just RETURN)
5920 2568313 : if (!allocated(state.dataLowTempRadSys->QRadSysSrcAvg)) return;
5921 :
5922 : // If it was allocated, then we have to check to see if this was running at all...
5923 863195 : for (SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
5924 842592 : if (state.dataLowTempRadSys->QRadSysSrcAvg(SurfNum) != 0.0) {
5925 67477 : LowTempRadSysOn = true;
5926 67477 : break; // DO loop
5927 : }
5928 : }
5929 :
5930 88080 : state.dataHeatBalFanSys->QRadSysSource = state.dataLowTempRadSys->QRadSysSrcAvg;
5931 88080 : auto &Surface(state.dataSurface->Surface);
5932 :
5933 : // For interzone surfaces, QRadSysSrcAvg was only updated for the "active" side. The active side
5934 : // would have a non-zero value at this point. If the numbers differ, then we have to manually update.
5935 1939113 : for (SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
5936 1851033 : if (Surface(SurfNum).ExtBoundCond > 0 && Surface(SurfNum).ExtBoundCond != SurfNum) {
5937 1542834 : if (std::abs(state.dataHeatBalFanSys->QRadSysSource(SurfNum) -
5938 1028556 : state.dataHeatBalFanSys->QRadSysSource(Surface(SurfNum).ExtBoundCond)) > CloseEnough) { // numbers differ
5939 2610 : if (std::abs(state.dataHeatBalFanSys->QRadSysSource(SurfNum)) >
5940 1305 : std::abs(state.dataHeatBalFanSys->QRadSysSource(Surface(SurfNum).ExtBoundCond))) {
5941 1305 : state.dataHeatBalFanSys->QRadSysSource(Surface(SurfNum).ExtBoundCond) = state.dataHeatBalFanSys->QRadSysSource(SurfNum);
5942 : } else {
5943 0 : state.dataHeatBalFanSys->QRadSysSource(SurfNum) = state.dataHeatBalFanSys->QRadSysSource(Surface(SurfNum).ExtBoundCond);
5944 : }
5945 : }
5946 : }
5947 : }
5948 : }
5949 :
5950 372334 : void VariableFlowRadiantSystemData::reportLowTemperatureRadiantSystem([[maybe_unused]] EnergyPlusData &state)
5951 : {
5952 :
5953 372334 : auto &Zone(state.dataHeatBal->Zone);
5954 :
5955 : // Using/Aliasing
5956 372334 : auto &TimeStepSys = state.dataHVACGlobal->TimeStepSys;
5957 :
5958 372334 : Real64 totalRadSysPower(0.0); // Total source/sink power for the radiant system (sum of all surfaces of the system)
5959 :
5960 785102 : for (int radSurfNum = 1; radSurfNum <= this->NumOfSurfaces; ++radSurfNum) {
5961 412768 : totalRadSysPower += state.dataHeatBalFanSys->QRadSysSource(this->SurfacePtr(radSurfNum));
5962 : }
5963 :
5964 372334 : totalRadSysPower *= double(Zone(this->ZonePtr).Multiplier * Zone(this->ZonePtr).ListMultiplier);
5965 :
5966 372334 : this->HeatPower = 0.0;
5967 372334 : this->CoolPower = 0.0;
5968 :
5969 372334 : if (this->OperatingMode == HeatingMode) {
5970 152746 : this->WaterInletTemp = state.dataLoopNodes->Node(this->HotWaterInNode).Temp;
5971 152746 : this->WaterOutletTemp = state.dataLoopNodes->Node(this->HotWaterOutNode).Temp;
5972 152746 : this->WaterMassFlowRate = state.dataLoopNodes->Node(this->HotWaterInNode).MassFlowRate;
5973 152746 : this->HeatPower = totalRadSysPower;
5974 :
5975 219588 : } else if (this->OperatingMode == CoolingMode) {
5976 121273 : this->WaterInletTemp = state.dataLoopNodes->Node(this->ColdWaterInNode).Temp;
5977 121273 : this->WaterOutletTemp = state.dataLoopNodes->Node(this->ColdWaterOutNode).Temp;
5978 121273 : this->WaterMassFlowRate = state.dataLoopNodes->Node(this->ColdWaterInNode).MassFlowRate;
5979 121273 : this->CoolPower = -totalRadSysPower;
5980 :
5981 : } else { // Not Operating: Leave temperatures at previous values
5982 98315 : this->WaterMassFlowRate = 0.0;
5983 98315 : this->WaterOutletTemp = this->WaterInletTemp;
5984 : }
5985 :
5986 372334 : this->HeatEnergy = this->HeatPower * TimeStepSys * DataGlobalConstants::SecInHour;
5987 372334 : this->CoolEnergy = this->CoolPower * TimeStepSys * DataGlobalConstants::SecInHour;
5988 :
5989 372334 : if (this->CondCausedShutDown) {
5990 32259 : this->CondCausedTimeOff = TimeStepSys * DataGlobalConstants::SecInHour;
5991 : } else {
5992 340075 : this->CondCausedTimeOff = 0.0;
5993 : }
5994 372334 : }
5995 :
5996 231699 : void ConstantFlowRadiantSystemData::reportLowTemperatureRadiantSystem(EnergyPlusData &state)
5997 : {
5998 :
5999 231699 : auto &Zone(state.dataHeatBal->Zone);
6000 :
6001 : // Using/Aliasing
6002 231699 : auto &TimeStepSys = state.dataHVACGlobal->TimeStepSys;
6003 : using FluidProperties::GetSpecificHeatGlycol;
6004 :
6005 231699 : auto constexpr routineName("ReportConstantFlowSystem");
6006 : Real64 cpFluid; // Specific heat of the fluid in the radiant system
6007 231699 : Real64 totalRadSysPower(0.0); // Total source/sink power for the radiant system (sum of all surfaces of the system)
6008 :
6009 463398 : for (int radSurfNum = 1; radSurfNum <= this->NumOfSurfaces; ++radSurfNum) {
6010 231699 : totalRadSysPower += state.dataHeatBalFanSys->QRadSysSource(this->SurfacePtr(radSurfNum));
6011 : }
6012 :
6013 231699 : totalRadSysPower *= double(Zone(this->ZonePtr).Multiplier * Zone(this->ZonePtr).ListMultiplier);
6014 :
6015 231699 : this->HeatPower = 0.0;
6016 231699 : this->CoolPower = 0.0;
6017 :
6018 : // Note that temperatures have already been set as part of the simulation
6019 : // step. So, they do not need to be calculated here except for the pump
6020 : // inlet temperature which was not calculated elsewhere. If the system is
6021 : // not operating, leave the temperatures with their previous values but
6022 : // zero out the flow and power quantities (should have already been done
6023 : // in another routine, but just in case...).
6024 :
6025 231699 : if (this->OperatingMode == HeatingMode) {
6026 209061 : cpFluid = GetSpecificHeatGlycol(state,
6027 69687 : state.dataPlnt->PlantLoop(this->HWPlantLoc.loopNum).FluidName,
6028 69687 : state.dataLoopNodes->Node(this->HotWaterInNode).Temp,
6029 69687 : state.dataPlnt->PlantLoop(this->HWPlantLoc.loopNum).FluidIndex,
6030 69687 : routineName);
6031 :
6032 69687 : this->HeatPower = totalRadSysPower;
6033 69687 : if (this->PumpMassFlowRate > 0.0) {
6034 69687 : this->PumpInletTemp = this->WaterInletTemp - (this->PumpHeattoFluid / (this->PumpMassFlowRate * cpFluid));
6035 : } else {
6036 0 : this->PumpInletTemp = this->WaterInletTemp;
6037 : }
6038 :
6039 162012 : } else if (this->OperatingMode == CoolingMode) {
6040 335778 : cpFluid = GetSpecificHeatGlycol(state,
6041 111926 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidName,
6042 111926 : state.dataLoopNodes->Node(this->ColdWaterInNode).Temp,
6043 111926 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidIndex,
6044 111926 : routineName);
6045 :
6046 111926 : this->CoolPower = -totalRadSysPower;
6047 111926 : this->PumpInletTemp = this->WaterInletTemp - (this->PumpHeattoFluid / (this->PumpMassFlowRate * cpFluid));
6048 :
6049 : } else { // Not Operating
6050 50086 : this->WaterOutletTemp = this->WaterInletTemp;
6051 50086 : this->PumpInletTemp = this->WaterInletTemp;
6052 50086 : this->WaterMassFlowRate = 0.0;
6053 50086 : this->WaterInjectionRate = 0.0;
6054 50086 : this->WaterRecircRate = 0.0;
6055 50086 : this->HeatPower = 0.0;
6056 50086 : this->CoolPower = 0.0;
6057 50086 : this->PumpPower = 0.0;
6058 50086 : this->PumpMassFlowRate = 0.0;
6059 50086 : this->PumpHeattoFluid = 0.0;
6060 : }
6061 :
6062 231699 : this->HeatEnergy = this->HeatPower * TimeStepSys * DataGlobalConstants::SecInHour;
6063 231699 : this->CoolEnergy = this->CoolPower * TimeStepSys * DataGlobalConstants::SecInHour;
6064 231699 : this->PumpEnergy = this->PumpPower * TimeStepSys * DataGlobalConstants::SecInHour;
6065 231699 : this->PumpHeattoFluidEnergy = this->PumpHeattoFluid * TimeStepSys * DataGlobalConstants::SecInHour;
6066 :
6067 231699 : if (this->CondCausedShutDown) {
6068 56561 : this->CondCausedTimeOff = TimeStepSys * DataGlobalConstants::SecInHour;
6069 : } else {
6070 175138 : this->CondCausedTimeOff = 0.0;
6071 : }
6072 231699 : }
6073 :
6074 80871 : void ElectricRadiantSystemData::reportLowTemperatureRadiantSystem([[maybe_unused]] EnergyPlusData &state)
6075 : {
6076 :
6077 80871 : auto &Zone(state.dataHeatBal->Zone);
6078 :
6079 : // Using/Aliasing
6080 80871 : auto &TimeStepSys = state.dataHVACGlobal->TimeStepSys;
6081 :
6082 80871 : Real64 totalRadSysPower(0.0); // Total source/sink power for the radiant system (sum of all surfaces of the system)
6083 :
6084 161742 : for (int radSurfNum = 1; radSurfNum <= this->NumOfSurfaces; ++radSurfNum) {
6085 80871 : totalRadSysPower += state.dataHeatBalFanSys->QRadSysSource(this->SurfacePtr(radSurfNum));
6086 : }
6087 :
6088 80871 : totalRadSysPower *= double(Zone(this->ZonePtr).Multiplier * Zone(this->ZonePtr).ListMultiplier);
6089 :
6090 80871 : this->ElecPower = totalRadSysPower;
6091 80871 : this->ElecEnergy = this->ElecPower * TimeStepSys * DataGlobalConstants::SecInHour;
6092 80871 : this->HeatPower = this->ElecPower;
6093 80871 : this->HeatEnergy = this->ElecEnergy;
6094 80871 : }
6095 :
6096 : } // namespace LowTempRadiantSystem
6097 :
6098 2313 : } // namespace EnergyPlus
|