Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2025, The Board of Trustees of the University of Illinois,
2 : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
3 : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
4 : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
5 : // contributors. All rights reserved.
6 : //
7 : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
8 : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
9 : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
10 : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
11 : // derivative works, and perform publicly and display publicly, and to permit others to do so.
12 : //
13 : // Redistribution and use in source and binary forms, with or without modification, are permitted
14 : // provided that the following conditions are met:
15 : //
16 : // (1) Redistributions of source code must retain the above copyright notice, this list of
17 : // conditions and the following disclaimer.
18 : //
19 : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
20 : // conditions and the following disclaimer in the documentation and/or other materials
21 : // provided with the distribution.
22 : //
23 : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
24 : // the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
25 : // used to endorse or promote products derived from this software without specific prior
26 : // written permission.
27 : //
28 : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
29 : // without changes from the version obtained under this License, or (ii) Licensee makes a
30 : // reference solely to the software portion of its product, Licensee must refer to the
31 : // software as "EnergyPlus version X" software, where "X" is the version number Licensee
32 : // obtained under this License and may not use a different name for the software. Except as
33 : // specifically required in this Section (4), Licensee shall not use in a company name, a
34 : // product name, in advertising, publicity, or other promotional activities any name, trade
35 : // name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
36 : // similar designation, without the U.S. Department of Energy's prior written consent.
37 : //
38 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
39 : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
40 : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
41 : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43 : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
45 : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46 : // POSSIBILITY OF SUCH DAMAGE.
47 :
48 : // C++ Headers
49 : #include <cassert>
50 : #include <cmath>
51 :
52 : // ObjexxFCL Headers
53 : #include <ObjexxFCL/Array.functions.hh>
54 :
55 : // EnergyPlus Headers
56 : #include <EnergyPlus/Autosizing/HeatingCapacitySizing.hh>
57 : #include <EnergyPlus/Data/EnergyPlusData.hh>
58 : #include <EnergyPlus/DataGlobalConstants.hh>
59 : #include <EnergyPlus/DataHVACGlobals.hh>
60 : #include <EnergyPlus/DataHeatBalFanSys.hh>
61 : #include <EnergyPlus/DataHeatBalSurface.hh>
62 : #include <EnergyPlus/DataHeatBalance.hh>
63 : #include <EnergyPlus/DataIPShortCuts.hh>
64 : #include <EnergyPlus/DataSurfaces.hh>
65 : #include <EnergyPlus/DataViewFactorInformation.hh>
66 : #include <EnergyPlus/DataZoneEquipment.hh>
67 : #include <EnergyPlus/General.hh>
68 : #include <EnergyPlus/GeneralRoutines.hh>
69 : #include <EnergyPlus/HeatBalanceIntRadExchange.hh>
70 : #include <EnergyPlus/HeatBalanceSurfaceManager.hh>
71 : #include <EnergyPlus/HighTempRadiantSystem.hh>
72 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
73 : #include <EnergyPlus/OutputProcessor.hh>
74 : #include <EnergyPlus/ScheduleManager.hh>
75 : #include <EnergyPlus/UtilityRoutines.hh>
76 : #include <EnergyPlus/ZoneTempPredictorCorrector.hh>
77 :
78 : namespace EnergyPlus {
79 :
80 : namespace HighTempRadiantSystem {
81 :
82 : // Module containing the routines dealing with the high temperature radiant systems
83 :
84 : // MODULE INFORMATION:
85 : // AUTHOR Rick Strand
86 : // DATE WRITTEN February 2001
87 :
88 : // PURPOSE OF THIS MODULE:
89 : // The purpose of this module is to simulate high temperature radiant systems.
90 : // It is the intention of this module to cover all types of high temperature
91 : // radiant systems (gas and electric)
92 :
93 : // METHODOLOGY EMPLOYED:
94 : // Based on work done in BLAST, the EnergyPlus low temperature radiant system
95 : // model, this model has similar inherent challenges that are similar to the
96 : // low temperature radiant system. Because it is a system that directly
97 : // effects the surface heat balances, it must be a part of both the heat
98 : // balance routines and linked in with the HVAC system.
99 : // REFERENCES:
100 : // Building Systems Laboratory, BLAST User's Guide/Reference.
101 : // Maloney, Dan. 1987. "Development of a radiant heater model and the
102 : // incorporation of thermal comfort considerations into the BLAST
103 : // energy analysis program", M.S. thesis, University of Illinois at
104 : // Urbana-Champaign (Dept. of Mechanical and Industrial Engineering).
105 :
106 : // MODULE PARAMETER DEFINITIONS:
107 : constexpr std::array<std::string_view, static_cast<int>(RadControlType::Num)> radControlTypeNamesUC = {"MEANAIRTEMPERATURE",
108 : "MEANRADIANTTEMPERATURE",
109 : "OPERATIVETEMPERATURE",
110 : "MEANAIRTEMPERATURESETPOINT",
111 : "MEANRADIANTTEMPERATURESETPOINT",
112 : "OPERATIVETEMPERATURESETPOINT"};
113 :
114 0 : void SimHighTempRadiantSystem(EnergyPlusData &state,
115 : std::string_view CompName, // name of the low temperature radiant system
116 : bool const FirstHVACIteration, // TRUE if 1st HVAC simulation of system timestep
117 : Real64 &LoadMet, // load met by the radiant system, in Watts
118 : int &CompIndex)
119 : {
120 :
121 : // SUBROUTINE INFORMATION:
122 : // AUTHOR Rick Strand
123 : // DATE WRITTEN February 2001
124 :
125 : // PURPOSE OF THIS SUBROUTINE:
126 : // This subroutine is the "manager" for the high temperature radiant
127 : // system model. It is called from the outside and controls the
128 : // actions and subroutine calls to lower levels as appropriate.
129 :
130 : // METHODOLOGY EMPLOYED:
131 : // Standard EnergyPlus manager subroutine layout
132 :
133 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
134 : int RadSysNum; // Radiant system number/index in local derived types
135 :
136 0 : if (state.dataHighTempRadSys->GetInputFlag) {
137 0 : bool ErrorsFoundInGet = false;
138 0 : GetHighTempRadiantSystem(state, ErrorsFoundInGet);
139 0 : if (ErrorsFoundInGet) {
140 0 : ShowFatalError(state, "GetHighTempRadiantSystem: Errors found in input. Preceding condition(s) cause termination.");
141 : }
142 0 : state.dataHighTempRadSys->GetInputFlag = false;
143 : }
144 :
145 : // Find the correct ZoneHVAC:HighTemperatureRadiant
146 0 : if (CompIndex == 0) {
147 0 : RadSysNum = Util::FindItemInList(CompName, state.dataHighTempRadSys->HighTempRadSys);
148 0 : if (RadSysNum == 0) {
149 0 : ShowFatalError(state, format("SimHighTempRadiantSystem: Unit not found={}", CompName));
150 : }
151 0 : CompIndex = RadSysNum;
152 : } else {
153 0 : RadSysNum = CompIndex;
154 0 : if (RadSysNum > state.dataHighTempRadSys->NumOfHighTempRadSys || RadSysNum < 1) {
155 0 : ShowFatalError(state,
156 0 : format("SimHighTempRadiantSystem: Invalid CompIndex passed={}, Number of Units={}, Entered Unit name={}",
157 : RadSysNum,
158 0 : state.dataHighTempRadSys->NumOfHighTempRadSys,
159 : CompName));
160 : }
161 0 : if (state.dataHighTempRadSys->CheckEquipName(RadSysNum)) {
162 0 : if (CompName != state.dataHighTempRadSys->HighTempRadSys(RadSysNum).Name) {
163 0 : ShowFatalError(state,
164 0 : format("SimHighTempRadiantSystem: Invalid CompIndex passed={}, Unit name={}, stored Unit Name for that index={}",
165 : RadSysNum,
166 : CompName,
167 0 : state.dataHighTempRadSys->HighTempRadSys(RadSysNum).Name));
168 : }
169 0 : state.dataHighTempRadSys->CheckEquipName(RadSysNum) = false;
170 : }
171 : }
172 :
173 0 : InitHighTempRadiantSystem(state, FirstHVACIteration, RadSysNum);
174 :
175 0 : switch (state.dataHighTempRadSys->HighTempRadSys(RadSysNum).ControlType) {
176 0 : case RadControlType::MATControl:
177 : case RadControlType::MRTControl:
178 : case RadControlType::OperativeControl: {
179 0 : CalcHighTempRadiantSystem(state, RadSysNum);
180 0 : } break;
181 0 : case RadControlType::MATSPControl:
182 : case RadControlType::MRTSPControl:
183 : case RadControlType::OperativeSPControl: {
184 0 : CalcHighTempRadiantSystemSP(state, FirstHVACIteration, RadSysNum);
185 0 : } break;
186 0 : default:
187 0 : break;
188 : }
189 :
190 0 : UpdateHighTempRadiantSystem(state, RadSysNum, LoadMet);
191 :
192 0 : ReportHighTempRadiantSystem(state, RadSysNum);
193 0 : }
194 :
195 1 : void GetHighTempRadiantSystem(EnergyPlusData &state, bool &ErrorsFound // TRUE if errors are found on processing the input
196 : )
197 : {
198 :
199 : // SUBROUTINE INFORMATION:
200 : // AUTHOR Rick Strand
201 : // DATE WRITTEN February 2001
202 :
203 : // PURPOSE OF THIS SUBROUTINE:
204 : // This subroutine reads the input for high temperature radiant systems
205 : // from the user input file. This will contain all of the information
206 : // needed to simulate a high temperature radiant system.
207 :
208 : // METHODOLOGY EMPLOYED:
209 : // Standard EnergyPlus methodology.
210 : static constexpr std::string_view routineName = "GetHighTempRadiantSystem";
211 :
212 : // SUBROUTINE PARAMETER DEFINITIONS:
213 1 : Real64 constexpr MaxCombustionEffic = 1.0; // Limit the combustion efficiency to perfection
214 1 : Real64 constexpr MaxFraction = 1.0; // Limit the highest allowed fraction for heat transfer parts
215 1 : Real64 constexpr MinCombustionEffic = 0.01; // Limit the minimum combustion efficiency
216 1 : Real64 constexpr MinFraction = 0.0; // Limit the lowest allowed fraction for heat transfer parts
217 1 : Real64 constexpr MinThrottlingRange = 0.5; // Smallest throttling range allowed in degrees Celsius
218 1 : int constexpr iHeatCAPMAlphaNum = 4; // get input index to High Temperature Radiant system heating capacity sizing method
219 1 : int constexpr iHeatDesignCapacityNumericNum = 1; // get input index to High Temperature Radiant system heating capacity
220 1 : int constexpr iHeatCapacityPerFloorAreaNumericNum = 2; // index to High Temperature Radiant system heating capacity per floor area sizing
221 1 : int constexpr iHeatFracOfAutosizedCapacityNumericNum = 3; // index to system capacity sizing as fraction of autosized heating capacity
222 :
223 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
224 : Real64 FracOfRadPotentiallyLost; // Difference between unity and AllFracsSummed for error reporting
225 : int IOStatus; // Used in GetObjectItem
226 : int NumAlphas; // Number of Alphas for each GetObjectItem call
227 : int NumNumbers; // Number of Numbers for each GetObjectItem call
228 :
229 : // Initializations and allocations
230 2 : state.dataHighTempRadSys->NumOfHighTempRadSys =
231 1 : state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "ZoneHVAC:HighTemperatureRadiant");
232 :
233 1 : state.dataHighTempRadSys->HighTempRadSys.allocate(state.dataHighTempRadSys->NumOfHighTempRadSys);
234 1 : state.dataHighTempRadSys->CheckEquipName.allocate(state.dataHighTempRadSys->NumOfHighTempRadSys);
235 1 : state.dataHighTempRadSys->HighTempRadSysNumericFields.allocate(state.dataHighTempRadSys->NumOfHighTempRadSys);
236 1 : state.dataHighTempRadSys->CheckEquipName = true;
237 :
238 : // extensible object, do not need max args because using IPShortCuts
239 1 : auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
240 1 : cCurrentModuleObject = "ZoneHVAC:HighTemperatureRadiant";
241 : // Obtain all of the user data related to high temperature radiant systems...
242 2 : for (int Item = 1; Item <= state.dataHighTempRadSys->NumOfHighTempRadSys; ++Item) {
243 1 : auto &highTempRadSys = state.dataHighTempRadSys->HighTempRadSys(Item);
244 :
245 2 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
246 : cCurrentModuleObject,
247 : Item,
248 1 : state.dataIPShortCut->cAlphaArgs,
249 : NumAlphas,
250 1 : state.dataIPShortCut->rNumericArgs,
251 : NumNumbers,
252 : IOStatus,
253 1 : state.dataIPShortCut->lNumericFieldBlanks,
254 1 : state.dataIPShortCut->lAlphaFieldBlanks,
255 1 : state.dataIPShortCut->cAlphaFieldNames,
256 1 : state.dataIPShortCut->cNumericFieldNames);
257 :
258 1 : ErrorObjectHeader eoh{routineName, cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)};
259 :
260 1 : state.dataHighTempRadSys->HighTempRadSysNumericFields(Item).FieldNames.allocate(NumNumbers);
261 1 : state.dataHighTempRadSys->HighTempRadSysNumericFields(Item).FieldNames = "";
262 1 : state.dataHighTempRadSys->HighTempRadSysNumericFields(Item).FieldNames = state.dataIPShortCut->cNumericFieldNames;
263 : // General user input data
264 1 : highTempRadSys.Name = state.dataIPShortCut->cAlphaArgs(1);
265 :
266 1 : if (state.dataIPShortCut->lAlphaFieldBlanks(2)) {
267 1 : highTempRadSys.availSched = Sched::GetScheduleAlwaysOn(state);
268 0 : } else if ((highTempRadSys.availSched = Sched::GetSchedule(state, state.dataIPShortCut->cAlphaArgs(2))) == nullptr) {
269 0 : ShowSevereItemNotFound(state, eoh, state.dataIPShortCut->cAlphaFieldNames(2), state.dataIPShortCut->cAlphaArgs(2));
270 0 : ErrorsFound = true;
271 : }
272 :
273 1 : highTempRadSys.ZonePtr = Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(3), state.dataHeatBal->Zone);
274 1 : if (highTempRadSys.ZonePtr == 0) {
275 0 : ShowSevereError(state, format("Invalid {} = {}", state.dataIPShortCut->cAlphaFieldNames(3), state.dataIPShortCut->cAlphaArgs(3)));
276 0 : ShowContinueError(state, format("Occurs for {} = {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
277 0 : ErrorsFound = true;
278 : }
279 :
280 : // state.dataHighTempRadSys->HighTempRadSys( Item ).MaxPowerCapac = state.dataIPShortCut->rNumericArgs( 1 );
281 :
282 : // Determine High Temp Radiant heating design capacity sizing method
283 1 : highTempRadSys.HeatingCapMethod = static_cast<DataSizing::DesignSizingType>(
284 1 : getEnumValue(DataSizing::DesignSizingTypeNamesUC, state.dataIPShortCut->cAlphaArgs(iHeatCAPMAlphaNum)));
285 1 : if (highTempRadSys.HeatingCapMethod == DataSizing::DesignSizingType::HeatingDesignCapacity) {
286 1 : if (!state.dataIPShortCut->lNumericFieldBlanks(iHeatDesignCapacityNumericNum)) {
287 1 : highTempRadSys.ScaledHeatingCapacity = state.dataIPShortCut->rNumericArgs(iHeatDesignCapacityNumericNum);
288 1 : if (highTempRadSys.ScaledHeatingCapacity < 0.0 && highTempRadSys.ScaledHeatingCapacity != DataSizing::AutoSize) {
289 0 : ShowSevereError(state, format("{} = {}", cCurrentModuleObject, highTempRadSys.Name));
290 0 : ShowContinueError(state,
291 0 : format("Illegal {} = {:.7T}",
292 0 : state.dataIPShortCut->cNumericFieldNames(iHeatDesignCapacityNumericNum),
293 0 : state.dataIPShortCut->rNumericArgs(iHeatDesignCapacityNumericNum)));
294 0 : ErrorsFound = true;
295 : }
296 : } else {
297 0 : ShowSevereError(state, format("{} = {}", cCurrentModuleObject, highTempRadSys.Name));
298 0 : ShowContinueError(state,
299 0 : format("Input for {} = {}",
300 0 : state.dataIPShortCut->cAlphaFieldNames(iHeatCAPMAlphaNum),
301 0 : state.dataIPShortCut->cAlphaArgs(iHeatCAPMAlphaNum)));
302 0 : ShowContinueError(
303 0 : state, format("Blank field not allowed for {}", state.dataIPShortCut->cNumericFieldNames(iHeatDesignCapacityNumericNum)));
304 0 : ErrorsFound = true;
305 : }
306 0 : } else if (highTempRadSys.HeatingCapMethod == DataSizing::DesignSizingType::CapacityPerFloorArea) {
307 0 : if (!state.dataIPShortCut->lNumericFieldBlanks(iHeatCapacityPerFloorAreaNumericNum)) {
308 0 : highTempRadSys.ScaledHeatingCapacity = state.dataIPShortCut->rNumericArgs(iHeatCapacityPerFloorAreaNumericNum);
309 0 : if (highTempRadSys.ScaledHeatingCapacity <= 0.0) {
310 0 : ShowSevereError(state, format("{} = {}", cCurrentModuleObject, highTempRadSys.Name));
311 0 : ShowContinueError(state,
312 0 : format("Input for {} = {}",
313 0 : state.dataIPShortCut->cAlphaFieldNames(iHeatCAPMAlphaNum),
314 0 : state.dataIPShortCut->cAlphaArgs(iHeatCAPMAlphaNum)));
315 0 : ShowContinueError(state,
316 0 : format("Illegal {} = {:.7T}",
317 0 : state.dataIPShortCut->cNumericFieldNames(iHeatCapacityPerFloorAreaNumericNum),
318 0 : state.dataIPShortCut->rNumericArgs(iHeatCapacityPerFloorAreaNumericNum)));
319 0 : ErrorsFound = true;
320 0 : } else if (highTempRadSys.ScaledHeatingCapacity == DataSizing::AutoSize) {
321 0 : ShowSevereError(state, format("{} = {}", cCurrentModuleObject, highTempRadSys.Name));
322 0 : ShowContinueError(state,
323 0 : format("Input for {} = {}",
324 0 : state.dataIPShortCut->cAlphaFieldNames(iHeatCAPMAlphaNum),
325 0 : state.dataIPShortCut->cAlphaArgs(iHeatCAPMAlphaNum)));
326 0 : ShowContinueError(
327 0 : state, format("Illegal {} = Autosize", state.dataIPShortCut->cNumericFieldNames(iHeatCapacityPerFloorAreaNumericNum)));
328 0 : ErrorsFound = true;
329 : }
330 : } else {
331 0 : ShowSevereError(state, format("{} = {}", cCurrentModuleObject, highTempRadSys.Name));
332 0 : ShowContinueError(state,
333 0 : format("Input for {} = {}",
334 0 : state.dataIPShortCut->cAlphaFieldNames(iHeatCAPMAlphaNum),
335 0 : state.dataIPShortCut->cAlphaArgs(iHeatCAPMAlphaNum)));
336 0 : ShowContinueError(
337 : state,
338 0 : format("Blank field not allowed for {}", state.dataIPShortCut->cNumericFieldNames(iHeatCapacityPerFloorAreaNumericNum)));
339 0 : ErrorsFound = true;
340 : }
341 0 : } else if (highTempRadSys.HeatingCapMethod == DataSizing::DesignSizingType::FractionOfAutosizedHeatingCapacity) {
342 0 : if (!state.dataIPShortCut->lNumericFieldBlanks(iHeatFracOfAutosizedCapacityNumericNum)) {
343 0 : highTempRadSys.ScaledHeatingCapacity = state.dataIPShortCut->rNumericArgs(iHeatFracOfAutosizedCapacityNumericNum);
344 0 : if (highTempRadSys.ScaledHeatingCapacity < 0.0) {
345 0 : ShowSevereError(state, format("{} = {}", cCurrentModuleObject, highTempRadSys.Name));
346 0 : ShowContinueError(state,
347 0 : format("Illegal {} = {:.7T}",
348 0 : state.dataIPShortCut->cNumericFieldNames(iHeatFracOfAutosizedCapacityNumericNum),
349 0 : state.dataIPShortCut->rNumericArgs(iHeatFracOfAutosizedCapacityNumericNum)));
350 0 : ErrorsFound = true;
351 : }
352 : } else {
353 0 : ShowSevereError(state, format("{} = {}", cCurrentModuleObject, highTempRadSys.Name));
354 0 : ShowContinueError(state,
355 0 : format("Input for {} = {}",
356 0 : state.dataIPShortCut->cAlphaFieldNames(iHeatCAPMAlphaNum),
357 0 : state.dataIPShortCut->cAlphaArgs(iHeatCAPMAlphaNum)));
358 0 : ShowContinueError(
359 : state,
360 0 : format("Blank field not allowed for {}", state.dataIPShortCut->cNumericFieldNames(iHeatFracOfAutosizedCapacityNumericNum)));
361 0 : ErrorsFound = true;
362 : }
363 : }
364 :
365 1 : highTempRadSys.HeaterType =
366 1 : static_cast<Constant::eResource>(getEnumValue(Constant::eResourceNamesUC, state.dataIPShortCut->cAlphaArgs(5)));
367 :
368 1 : if (highTempRadSys.HeaterType == Constant::eResource::NaturalGas) {
369 0 : highTempRadSys.CombustionEffic = state.dataIPShortCut->rNumericArgs(4);
370 : // Limit the combustion efficiency to between zero and one...
371 0 : if (highTempRadSys.CombustionEffic < MinCombustionEffic) {
372 0 : highTempRadSys.CombustionEffic = MinCombustionEffic;
373 0 : ShowWarningError(
374 : state,
375 0 : format("{} was less than the allowable minimum, reset to minimum value.", state.dataIPShortCut->cNumericFieldNames(4)));
376 0 : ShowContinueError(state, format("Occurs for {} = {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
377 : }
378 0 : if (highTempRadSys.CombustionEffic > MaxCombustionEffic) {
379 0 : highTempRadSys.CombustionEffic = MaxCombustionEffic;
380 0 : ShowWarningError(
381 : state,
382 0 : format("{} was greater than the allowable maximum, reset to maximum value.", state.dataIPShortCut->cNumericFieldNames(4)));
383 0 : ShowContinueError(state, format("Occurs for {} = {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
384 : }
385 : } else {
386 1 : highTempRadSys.CombustionEffic = MaxCombustionEffic; // No inefficiency in the heater
387 : }
388 :
389 1 : highTempRadSys.FracRadiant = state.dataIPShortCut->rNumericArgs(5);
390 1 : if (highTempRadSys.FracRadiant < MinFraction) {
391 0 : highTempRadSys.FracRadiant = MinFraction;
392 0 : ShowWarningError(
393 0 : state, format("{} was less than the allowable minimum, reset to minimum value.", state.dataIPShortCut->cNumericFieldNames(5)));
394 0 : ShowContinueError(state, format("Occurs for {} = {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
395 : }
396 1 : if (highTempRadSys.FracRadiant > MaxFraction) {
397 0 : highTempRadSys.FracRadiant = MaxFraction;
398 0 : ShowWarningError(
399 0 : state, format("{} was greater than the allowable maximum, reset to maximum value.", state.dataIPShortCut->cNumericFieldNames(5)));
400 0 : ShowContinueError(state, format("Occurs for {} = {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
401 : }
402 :
403 1 : highTempRadSys.FracLatent = state.dataIPShortCut->rNumericArgs(6);
404 1 : if (highTempRadSys.FracLatent < MinFraction) {
405 0 : highTempRadSys.FracLatent = MinFraction;
406 0 : ShowWarningError(
407 0 : state, format("{} was less than the allowable minimum, reset to minimum value.", state.dataIPShortCut->cNumericFieldNames(6)));
408 0 : ShowContinueError(state, format("Occurs for {} = {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
409 : }
410 1 : if (highTempRadSys.FracLatent > MaxFraction) {
411 0 : highTempRadSys.FracLatent = MaxFraction;
412 0 : ShowWarningError(
413 0 : state, format("{} was greater than the allowable maximum, reset to maximum value.", state.dataIPShortCut->cNumericFieldNames(6)));
414 0 : ShowContinueError(state, format("Occurs for {} = {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
415 : }
416 :
417 1 : highTempRadSys.FracLost = state.dataIPShortCut->rNumericArgs(7);
418 1 : if (highTempRadSys.FracLost < MinFraction) {
419 0 : highTempRadSys.FracLost = MinFraction;
420 0 : ShowWarningError(
421 0 : state, format("{} was less than the allowable minimum, reset to minimum value.", state.dataIPShortCut->cNumericFieldNames(7)));
422 0 : ShowContinueError(state, format("Occurs for {} = {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
423 : }
424 1 : if (highTempRadSys.FracLost > MaxFraction) {
425 0 : highTempRadSys.FracLost = MaxFraction;
426 0 : ShowWarningError(
427 0 : state, format("{} was greater than the allowable maximum, reset to maximum value.", state.dataIPShortCut->cNumericFieldNames(7)));
428 0 : ShowContinueError(state, format("Occurs for {} = {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
429 : }
430 :
431 : // Based on the input for fractions radiant, latent, and lost, determine the fraction convective (remaining fraction)
432 1 : Real64 AllFracsSummed = highTempRadSys.FracRadiant + highTempRadSys.FracLatent + highTempRadSys.FracLost;
433 1 : if (AllFracsSummed > MaxFraction) {
434 0 : ShowSevereError(state,
435 0 : format("Fractions radiant, latent, and lost sum up to greater than 1 for{}", state.dataIPShortCut->cAlphaArgs(1)));
436 0 : ShowContinueError(state, format("Occurs for {} = {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
437 0 : ErrorsFound = true;
438 0 : highTempRadSys.FracConvect = 0.0;
439 : } else {
440 1 : highTempRadSys.FracConvect = 1.0 - AllFracsSummed;
441 : }
442 :
443 : // Process the temperature control type
444 1 : if (state.dataIPShortCut->lAlphaFieldBlanks(6)) {
445 0 : ShowWarningEmptyField(state, eoh, state.dataIPShortCut->cAlphaFieldNames(6), "OperativeTemperature");
446 0 : highTempRadSys.ControlType = RadControlType::OperativeControl;
447 1 : } else if ((highTempRadSys.ControlType = static_cast<RadControlType>(
448 1 : getEnumValue(radControlTypeNamesUC, state.dataIPShortCut->cAlphaArgs(6)))) == RadControlType::Invalid) {
449 0 : ShowSevereInvalidKey(state, eoh, state.dataIPShortCut->cAlphaFieldNames(6), state.dataIPShortCut->cAlphaArgs(6));
450 0 : ErrorsFound = true;
451 : }
452 :
453 1 : highTempRadSys.ThrottlRange = state.dataIPShortCut->rNumericArgs(8);
454 1 : if (highTempRadSys.ThrottlRange < MinThrottlingRange) {
455 0 : highTempRadSys.ThrottlRange = 1.0;
456 0 : ShowWarningError(state, format("{} is below the minimum allowed.", state.dataIPShortCut->cNumericFieldNames(8)));
457 0 : ShowContinueError(state, format("Occurs for {} = {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
458 0 : ShowContinueError(state, "Thus, the throttling range value has been reset to 1.0");
459 : }
460 :
461 1 : if (state.dataIPShortCut->lAlphaFieldBlanks(7)) {
462 0 : ShowSevereEmptyField(state,
463 : eoh,
464 0 : state.dataIPShortCut->cAlphaFieldNames(7),
465 0 : state.dataIPShortCut->cAlphaFieldNames(6),
466 0 : state.dataIPShortCut->cAlphaArgs(6));
467 0 : ErrorsFound = true;
468 1 : } else if ((highTempRadSys.setptSched = Sched::GetSchedule(state, state.dataIPShortCut->cAlphaArgs(7))) == nullptr) {
469 1 : ShowSevereItemNotFound(state, eoh, state.dataIPShortCut->cAlphaFieldNames(7), state.dataIPShortCut->cAlphaArgs(7));
470 1 : ErrorsFound = true;
471 : }
472 :
473 1 : highTempRadSys.FracDistribPerson = state.dataIPShortCut->rNumericArgs(9);
474 1 : if (highTempRadSys.FracDistribPerson < MinFraction) {
475 0 : highTempRadSys.FracDistribPerson = MinFraction;
476 0 : ShowWarningError(
477 0 : state, format("{} was less than the allowable minimum, reset to minimum value.", state.dataIPShortCut->cNumericFieldNames(9)));
478 0 : ShowContinueError(state, format("Occurs for {} = {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
479 : }
480 1 : if (highTempRadSys.FracDistribPerson > MaxFraction) {
481 0 : highTempRadSys.FracDistribPerson = MaxFraction;
482 0 : ShowWarningError(
483 0 : state, format("{} was greater than the allowable maximum, reset to maximum value.", state.dataIPShortCut->cNumericFieldNames(9)));
484 0 : ShowContinueError(state, format("Occurs for {} = {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
485 : }
486 :
487 1 : highTempRadSys.TotSurfToDistrib = NumNumbers - 9;
488 : // IF (highTempRadSys%TotSurfToDistrib > MaxDistribSurfaces) THEN
489 : // CALL ShowSevereError(state, 'Trying to distribute radiant energy to too many surfaces for heater
490 : // '//TRIM(state.dataIPShortCut->cAlphaArgs(1))) CALL ShowContinueError(state, 'Occurs for '//TRIM(cCurrentModuleObject)//' =
491 : // '//TRIM(state.dataIPShortCut->cAlphaArgs(1))) ErrorsFound=.TRUE.
492 : // END IF
493 1 : highTempRadSys.SurfaceName.allocate(highTempRadSys.TotSurfToDistrib);
494 1 : highTempRadSys.SurfacePtr.allocate(highTempRadSys.TotSurfToDistrib);
495 1 : highTempRadSys.FracDistribToSurf.allocate(highTempRadSys.TotSurfToDistrib);
496 :
497 1 : AllFracsSummed = highTempRadSys.FracDistribPerson;
498 2 : for (int SurfNum = 1; SurfNum <= highTempRadSys.TotSurfToDistrib; ++SurfNum) {
499 1 : highTempRadSys.SurfaceName(SurfNum) = state.dataIPShortCut->cAlphaArgs(SurfNum + 7);
500 1 : highTempRadSys.SurfacePtr(SurfNum) = HeatBalanceIntRadExchange::GetRadiantSystemSurface(
501 1 : state, cCurrentModuleObject, highTempRadSys.Name, highTempRadSys.ZonePtr, highTempRadSys.SurfaceName(SurfNum), ErrorsFound);
502 1 : highTempRadSys.FracDistribToSurf(SurfNum) = state.dataIPShortCut->rNumericArgs(SurfNum + 9);
503 : // Error trap for fractions that are out of range
504 1 : if (highTempRadSys.FracDistribToSurf(SurfNum) < MinFraction) {
505 0 : highTempRadSys.FracDistribToSurf(SurfNum) = MinFraction;
506 0 : ShowWarningError(state,
507 0 : format("{} was less than the allowable minimum, reset to minimum value.",
508 0 : state.dataIPShortCut->cNumericFieldNames(SurfNum + 9)));
509 0 : ShowContinueError(state, format("Occurs for {} = {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
510 : }
511 1 : if (highTempRadSys.FracDistribToSurf(SurfNum) > MaxFraction) {
512 0 : highTempRadSys.FracDistribToSurf(SurfNum) = MaxFraction;
513 0 : ShowWarningError(state,
514 0 : format("{} was greater than the allowable maximum, reset to maximum value.",
515 0 : state.dataIPShortCut->cNumericFieldNames(SurfNum + 9)));
516 0 : ShowContinueError(state, format("Occurs for {} = {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
517 : }
518 :
519 1 : if (highTempRadSys.SurfacePtr(SurfNum) != 0) {
520 1 : state.dataSurface->surfIntConv(highTempRadSys.SurfacePtr(SurfNum)).getsRadiantHeat = true;
521 1 : state.dataSurface->allGetsRadiantHeatSurfaceList.emplace_back(highTempRadSys.SurfacePtr(SurfNum));
522 : }
523 :
524 1 : AllFracsSummed += highTempRadSys.FracDistribToSurf(SurfNum);
525 :
526 : } // ...end of DO loop through surfaces that the heater radiates to.
527 :
528 : // Error trap if the fractions add up to greater than 1.0
529 1 : if (AllFracsSummed > (MaxFraction + 0.01)) {
530 0 : ShowSevereError(
531 : state,
532 0 : format("Fraction of radiation distributed to surfaces sums up to greater than 1 for {}", state.dataIPShortCut->cAlphaArgs(1)));
533 0 : ShowContinueError(state, format("Occurs for {} = {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
534 0 : ErrorsFound = true;
535 : }
536 1 : if (AllFracsSummed < (MaxFraction - 0.01)) { // User didn't distribute all of the radiation warn that some will be lost
537 1 : Real64 TotalFracToSurfs = AllFracsSummed - highTempRadSys.FracDistribPerson;
538 1 : FracOfRadPotentiallyLost = 1.0 - AllFracsSummed;
539 2 : ShowSevereError(state,
540 2 : format("Fraction of radiation distributed to surfaces and people sums up to less than 1 for {}",
541 1 : state.dataIPShortCut->cAlphaArgs(1)));
542 2 : ShowContinueError(state, "This would result in some of the radiant energy delivered by the high temp radiant heater being lost.");
543 1 : ShowContinueError(state, format("The sum of all radiation fractions to surfaces = {:.5T}", TotalFracToSurfs));
544 1 : ShowContinueError(state, format("The radiant fraction to people = {:.5T}", highTempRadSys.FracDistribPerson));
545 1 : ShowContinueError(state, format("So, all radiant fractions including surfaces and people = {:.5T}", AllFracsSummed));
546 2 : ShowContinueError(state,
547 2 : format("This means that the fraction of radiant energy that would be lost from the high temperature radiant heater "
548 : "would be = {:.5T}",
549 : FracOfRadPotentiallyLost));
550 2 : ShowContinueError(state,
551 2 : format("Please check and correct this so that all radiant energy is accounted for in {} = {}",
552 : cCurrentModuleObject,
553 1 : state.dataIPShortCut->cAlphaArgs(1)));
554 1 : ErrorsFound = true;
555 : }
556 :
557 : } // ...end of DO loop through all of the high temperature radiant heaters
558 :
559 : // Set up the output variables for high temperature radiant heaters
560 : // cCurrentModuleObject = "ZoneHVAC:HighTemperatureRadiant"
561 2 : for (int Item = 1; Item <= state.dataHighTempRadSys->NumOfHighTempRadSys; ++Item) {
562 1 : auto &highTempRadSys = state.dataHighTempRadSys->HighTempRadSys(Item);
563 2 : SetupOutputVariable(state,
564 : "Zone Radiant HVAC Heating Rate",
565 : Constant::Units::W,
566 1 : highTempRadSys.HeatPower,
567 : OutputProcessor::TimeStepType::System,
568 : OutputProcessor::StoreType::Average,
569 1 : highTempRadSys.Name);
570 2 : SetupOutputVariable(state,
571 : "Zone Radiant HVAC Heating Energy",
572 : Constant::Units::J,
573 1 : highTempRadSys.HeatEnergy,
574 : OutputProcessor::TimeStepType::System,
575 : OutputProcessor::StoreType::Sum,
576 1 : highTempRadSys.Name,
577 : Constant::eResource::EnergyTransfer,
578 : OutputProcessor::Group::HVAC,
579 : OutputProcessor::EndUseCat::HeatingCoils);
580 1 : if (highTempRadSys.HeaterType == Constant::eResource::NaturalGas) {
581 0 : SetupOutputVariable(state,
582 : "Zone Radiant HVAC NaturalGas Rate",
583 : Constant::Units::W,
584 0 : highTempRadSys.GasPower,
585 : OutputProcessor::TimeStepType::System,
586 : OutputProcessor::StoreType::Average,
587 0 : highTempRadSys.Name);
588 0 : SetupOutputVariable(state,
589 : "Zone Radiant HVAC NaturalGas Energy",
590 : Constant::Units::J,
591 0 : highTempRadSys.GasEnergy,
592 : OutputProcessor::TimeStepType::System,
593 : OutputProcessor::StoreType::Sum,
594 0 : highTempRadSys.Name,
595 : Constant::eResource::NaturalGas,
596 : OutputProcessor::Group::HVAC,
597 : OutputProcessor::EndUseCat::Heating);
598 1 : } else if (highTempRadSys.HeaterType == Constant::eResource::Electricity) {
599 2 : SetupOutputVariable(state,
600 : "Zone Radiant HVAC Electricity Rate",
601 : Constant::Units::W,
602 1 : highTempRadSys.ElecPower,
603 : OutputProcessor::TimeStepType::System,
604 : OutputProcessor::StoreType::Average,
605 1 : highTempRadSys.Name);
606 2 : SetupOutputVariable(state,
607 : "Zone Radiant HVAC Electricity Energy",
608 : Constant::Units::J,
609 1 : highTempRadSys.ElecEnergy,
610 : OutputProcessor::TimeStepType::System,
611 : OutputProcessor::StoreType::Sum,
612 1 : highTempRadSys.Name,
613 : Constant::eResource::Electricity,
614 : OutputProcessor::Group::HVAC,
615 : OutputProcessor::EndUseCat::Heating);
616 : }
617 : }
618 1 : }
619 :
620 0 : void InitHighTempRadiantSystem(EnergyPlusData &state,
621 : bool const FirstHVACIteration, // TRUE if 1st HVAC simulation of system timestep
622 : int const RadSysNum // Index for the low temperature radiant system under consideration within the derived types
623 : )
624 : {
625 :
626 : // SUBROUTINE INFORMATION:
627 : // AUTHOR Rick Strand
628 : // DATE WRITTEN February 2001
629 :
630 : // PURPOSE OF THIS SUBROUTINE:
631 : // This subroutine initializes variables relating to high temperature
632 : // radiant heating systems.
633 :
634 : // METHODOLOGY EMPLOYED:
635 : // Simply initializes whatever needs initializing.
636 :
637 : // Using/Aliasing
638 : using DataZoneEquipment::CheckZoneEquipmentList;
639 :
640 0 : if (state.dataHighTempRadSys->firstTime) {
641 0 : state.dataHighTempRadSys->MySizeFlag.dimension(state.dataHighTempRadSys->NumOfHighTempRadSys, true);
642 0 : state.dataHighTempRadSys->firstTime = false;
643 : }
644 :
645 : // need to check all units to see if they are on Zone Equipment List or issue warning
646 0 : if (!state.dataHighTempRadSys->ZoneEquipmentListChecked && state.dataZoneEquip->ZoneEquipInputsFilled) {
647 0 : state.dataHighTempRadSys->ZoneEquipmentListChecked = true;
648 0 : for (auto &thisHTRSys : state.dataHighTempRadSys->HighTempRadSys) {
649 0 : if (CheckZoneEquipmentList(state, "ZoneHVAC:HighTemperatureRadiant", thisHTRSys.Name)) {
650 0 : continue;
651 : }
652 0 : ShowSevereError(state,
653 0 : format("InitHighTempRadiantSystem: Unit=[ZoneHVAC:HighTemperatureRadiant,{}] is not on any ZoneHVAC:EquipmentList. "
654 : "It will not be simulated.",
655 0 : thisHTRSys.Name));
656 : }
657 : }
658 :
659 0 : if (!state.dataGlobal->SysSizingCalc && state.dataHighTempRadSys->MySizeFlag(RadSysNum)) {
660 : // for each radiant system do the sizing once.
661 0 : SizeHighTempRadiantSystem(state, RadSysNum);
662 0 : state.dataHighTempRadSys->MySizeFlag(RadSysNum) = false;
663 : }
664 :
665 0 : if (state.dataGlobal->BeginEnvrnFlag && state.dataHighTempRadSys->MyEnvrnFlag) {
666 0 : for (auto &thisHTR : state.dataHighTempRadSys->HighTempRadSys) {
667 0 : thisHTR.ZeroHTRSourceSumHATsurf = 0.0;
668 0 : thisHTR.QHTRRadSource = 0.0;
669 0 : thisHTR.QHTRRadSrcAvg = 0.0;
670 0 : thisHTR.LastQHTRRadSrc = 0.0;
671 0 : thisHTR.LastSysTimeElapsed = 0.0;
672 0 : thisHTR.LastTimeStepSys = 0.0;
673 : }
674 0 : state.dataHighTempRadSys->MyEnvrnFlag = false;
675 : }
676 0 : if (!state.dataGlobal->BeginEnvrnFlag) {
677 0 : state.dataHighTempRadSys->MyEnvrnFlag = true;
678 : }
679 :
680 0 : if (state.dataGlobal->BeginTimeStepFlag && FirstHVACIteration) { // This is the first pass through in a particular time step
681 0 : auto &thisHTR = state.dataHighTempRadSys->HighTempRadSys(RadSysNum);
682 0 : thisHTR.ZeroHTRSourceSumHATsurf =
683 0 : state.dataHeatBal->Zone(thisHTR.ZonePtr).sumHATsurf(state); // Set this to figure out what part of the load the radiant system meets
684 0 : thisHTR.QHTRRadSource = 0.0; // Initialize this variable to zero (radiant system defaults to off)
685 0 : thisHTR.QHTRRadSrcAvg = 0.0; // Initialize this variable to zero (radiant system defaults to off)
686 0 : thisHTR.LastQHTRRadSrc = 0.0; // At the beginning of a time step, reset to zero so average calculation can start again
687 0 : thisHTR.LastSysTimeElapsed = 0.0; // At the beginning of a time step, reset to zero so average calculation can start again
688 0 : thisHTR.LastTimeStepSys = 0.0; // At the beginning of a time step, reset to zero so average calculation can start again
689 : }
690 0 : }
691 :
692 1 : void SizeHighTempRadiantSystem(EnergyPlusData &state, int const RadSysNum)
693 : {
694 :
695 : // SUBROUTINE INFORMATION:
696 : // AUTHOR Fred Buhl
697 : // DATE WRITTEN February 2002
698 : // MODIFIED August 2013 Daeho Kang, add component sizing table entries
699 : // July 2014, B. Nigusse, added scalable sizing
700 :
701 : // PURPOSE OF THIS SUBROUTINE:
702 : // This subroutine is for sizing high temperature radiant components for which max power input has not been
703 : // specified in the input.
704 :
705 : // METHODOLOGY EMPLOYED:
706 : // Obtains design heating load from the zone sizing arrays
707 :
708 : // Using/Aliasing
709 1 : auto &thisHTR = state.dataHighTempRadSys->HighTempRadSys(RadSysNum);
710 :
711 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS
712 : Real64 TempSize; // autosized value of coil input field
713 1 : state.dataSize->DataScalableCapSizingON = false;
714 :
715 1 : int const curZoneEqNum = state.dataSize->CurZoneEqNum;
716 :
717 1 : if (curZoneEqNum > 0) {
718 1 : auto &zoneEqSizing = state.dataSize->ZoneEqSizing(curZoneEqNum);
719 :
720 1 : state.dataSize->DataFracOfAutosizedHeatingCapacity = 1.0;
721 1 : state.dataSize->DataZoneNumber = thisHTR.ZonePtr;
722 : // Integer representation of sizing method name (e.g., CoolingAirflowSizing, HeatingCapacitySizing, etc.)
723 1 : int SizingMethod = HVAC::HeatingCapacitySizing;
724 1 : int FieldNum = 1;
725 1 : std::string const SizingString = format("{} [W]", state.dataHighTempRadSys->HighTempRadSysNumericFields(RadSysNum).FieldNames(FieldNum));
726 : // capacity sizing methods (HeatingDesignCapacity, CapacityPerFloorArea, FractionOfAutosizedCoolingCapacity, and
727 : // FractionOfAutosizedHeatingCapacity )
728 1 : int CapSizingMethod = static_cast<int>(thisHTR.HeatingCapMethod);
729 1 : zoneEqSizing.SizingMethod(SizingMethod) = CapSizingMethod;
730 1 : if (CapSizingMethod == DataSizing::HeatingDesignCapacity || CapSizingMethod == DataSizing::CapacityPerFloorArea ||
731 : CapSizingMethod == DataSizing::FractionOfAutosizedHeatingCapacity) {
732 1 : std::string_view const CompType = "ZoneHVAC:HighTemperatureRadiant";
733 1 : std::string_view const CompName = thisHTR.Name;
734 :
735 1 : if (CapSizingMethod == DataSizing::HeatingDesignCapacity) {
736 0 : if (thisHTR.ScaledHeatingCapacity == DataSizing::AutoSize) {
737 0 : CheckZoneSizing(state, CompType, CompName);
738 0 : zoneEqSizing.DesHeatingLoad =
739 0 : state.dataSize->FinalZoneSizing(curZoneEqNum).NonAirSysDesHeatLoad / (thisHTR.FracRadiant + thisHTR.FracConvect);
740 : } else {
741 0 : zoneEqSizing.DesHeatingLoad = thisHTR.ScaledHeatingCapacity;
742 : }
743 0 : zoneEqSizing.HeatingCapacity = true;
744 0 : TempSize = zoneEqSizing.DesHeatingLoad;
745 1 : } else if (CapSizingMethod == DataSizing::CapacityPerFloorArea) {
746 1 : zoneEqSizing.HeatingCapacity = true;
747 1 : zoneEqSizing.DesHeatingLoad = thisHTR.ScaledHeatingCapacity * state.dataHeatBal->Zone(state.dataSize->DataZoneNumber).FloorArea;
748 1 : TempSize = zoneEqSizing.DesHeatingLoad;
749 1 : state.dataSize->DataScalableCapSizingON = true;
750 0 : } else if (CapSizingMethod == DataSizing::FractionOfAutosizedHeatingCapacity) {
751 0 : CheckZoneSizing(state, CompType, CompName);
752 0 : zoneEqSizing.HeatingCapacity = true;
753 0 : state.dataSize->DataFracOfAutosizedHeatingCapacity = thisHTR.ScaledHeatingCapacity;
754 0 : zoneEqSizing.DesHeatingLoad =
755 0 : state.dataSize->FinalZoneSizing(curZoneEqNum).NonAirSysDesHeatLoad / (thisHTR.FracRadiant + thisHTR.FracConvect);
756 0 : TempSize = DataSizing::AutoSize;
757 0 : state.dataSize->DataScalableCapSizingON = true;
758 : } else {
759 0 : TempSize = thisHTR.ScaledHeatingCapacity;
760 : }
761 1 : bool PrintFlag = true;
762 1 : bool errorsFound = false;
763 1 : constexpr std::string_view RoutineName = "SizeHighTempRadiantSystem";
764 1 : HeatingCapacitySizer sizerHeatingCapacity;
765 1 : sizerHeatingCapacity.overrideSizingString(SizingString);
766 1 : sizerHeatingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
767 1 : thisHTR.MaxPowerCapac = sizerHeatingCapacity.size(state, TempSize, errorsFound);
768 1 : state.dataSize->DataScalableCapSizingON = false;
769 1 : }
770 1 : }
771 1 : }
772 :
773 0 : void CalcHighTempRadiantSystem(EnergyPlusData &state, int const RadSysNum) // name of the low temperature radiant system
774 : {
775 :
776 : // SUBROUTINE INFORMATION:
777 : // AUTHOR Rick Strand
778 : // DATE WRITTEN February 2001
779 :
780 : // PURPOSE OF THIS SUBROUTINE:
781 : // This subroutine does all of the stuff that is necessary to simulate
782 : // a high temperature radiant heating system.
783 :
784 : // METHODOLOGY EMPLOYED:
785 : // Follows the methods used by many other pieces of zone equipment except
786 : // that we are controlling the input to the heater element. Note that
787 : // cooling is not allowed for such a system. Controls are very basic at
788 : // this point using just a linear interpolation between being off at
789 : // one end of the throttling range, fully on at the other end, and varying
790 : // linearly in between.
791 :
792 : // REFERENCES:
793 : // Other EnergyPlus modules
794 : // Building Systems Laboratory, BLAST User's Guide/Reference.
795 : // Fanger, P.O. "Analysis and Applications in Environmental Engineering",
796 : // Danish Technical Press, 1970.
797 : // Maloney, Dan. 1987. "Development of a radiant heater model and the
798 : // incorporation of thermal comfort considerations into the BLAST
799 : // energy analysis program", M.S. thesis, University of Illinois at
800 : // Urbana-Champaign (Dept. of Mechanical and Industrial Engineering).
801 :
802 : // Using/Aliasing
803 0 : auto &thisHTR = state.dataHighTempRadSys->HighTempRadSys(RadSysNum);
804 :
805 : // initialize local variables
806 0 : int ZoneNum = thisHTR.ZonePtr;
807 0 : Real64 HeatFrac = 0.0; // fraction of maximum energy input to radiant system [dimensionless]
808 :
809 0 : if (thisHTR.availSched->getCurrentVal() <= 0) {
810 :
811 : // Unit is off or has no load upon it; set the flow rates to zero and then
812 : // simulate the components with the no flow conditions
813 0 : thisHTR.QHTRRadSource = 0.0;
814 :
815 : } else { // Unit might be on-->this section is intended to control the output of the
816 : // high temperature radiant heater (temperature controlled)
817 :
818 : // Determine the current setpoint temperature and the temperature at which the unit should be completely off
819 0 : Real64 SetPtTemp = thisHTR.setptSched->getCurrentVal();
820 0 : Real64 OffTemp = SetPtTemp + 0.5 * thisHTR.ThrottlRange;
821 0 : auto const &thisZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum);
822 0 : Real64 OpTemp = (thisZoneHB.MAT + thisZoneHB.MRT) / 2.0; // Approximate the "operative" temperature
823 :
824 : // Determine the fraction of maximum power to the unit (limiting the fraction range from zero to unity)
825 0 : switch (thisHTR.ControlType) {
826 0 : case RadControlType::MATControl: {
827 0 : HeatFrac = (OffTemp - thisZoneHB.MAT) / thisHTR.ThrottlRange;
828 0 : } break;
829 0 : case RadControlType::MRTControl: {
830 0 : HeatFrac = (OffTemp - thisZoneHB.MRT) / thisHTR.ThrottlRange;
831 0 : } break;
832 0 : case RadControlType::OperativeControl: {
833 0 : OpTemp = 0.5 * (thisZoneHB.MAT + thisZoneHB.MRT);
834 0 : HeatFrac = (OffTemp - OpTemp) / thisHTR.ThrottlRange;
835 0 : } break;
836 0 : default:
837 0 : break;
838 : }
839 0 : if (HeatFrac < 0.0) {
840 0 : HeatFrac = 0.0;
841 : }
842 0 : if (HeatFrac > 1.0) {
843 0 : HeatFrac = 1.0;
844 : }
845 :
846 : // Set the heat source for the high temperature electric radiant system
847 0 : thisHTR.QHTRRadSource = HeatFrac * thisHTR.MaxPowerCapac;
848 : }
849 0 : }
850 :
851 0 : void CalcHighTempRadiantSystemSP(
852 : EnergyPlusData &state,
853 : [[maybe_unused]] bool const FirstHVACIteration, // true if this is the first HVAC iteration at this system time step !unused1208
854 : int const RadSysNum // name of the low temperature radiant system
855 : )
856 : {
857 :
858 : // SUBROUTINE INFORMATION:
859 : // AUTHOR Rick Strand
860 : // DATE WRITTEN February 2008
861 : // MODIFIED Sep 2011 LKL/BG - resimulate only zones needing it for Radiant systems
862 :
863 : // PURPOSE OF THIS SUBROUTINE:
864 : // This subroutine does all of the stuff that is necessary to simulate
865 : // a high temperature radiant heating system using setpoint temperature control.
866 :
867 : // METHODOLOGY EMPLOYED:
868 : // Follows the methods used by many other pieces of zone equipment except
869 : // that we are controlling the input to the heater element. Note that
870 : // cooling is not allowed for such a system. Controls are very basic and
871 : // use an iterative approach to get close to what we need.
872 :
873 : // REFERENCES:
874 : // Other EnergyPlus modules
875 : // Building Systems Laboratory, BLAST User's Guide/Reference.
876 : // Fanger, P.O. "Analysis and Applications in Environmental Engineering",
877 : // Danish Technical Press, 1970.
878 : // Maloney, Dan. 1987. "Development of a radiant heater model and the
879 : // incorporation of thermal comfort considerations into the BLAST
880 : // energy analysis program", M.S. thesis, University of Illinois at
881 : // Urbana-Champaign (Dept. of Mechanical and Industrial Engineering).
882 :
883 : // Using/Aliasing
884 0 : auto &thisHTR = state.dataHighTempRadSys->HighTempRadSys(RadSysNum);
885 :
886 : // SUBROUTINE PARAMETER DEFINITIONS:
887 0 : float const TempConvToler(0.1f); // Temperature controller tries to converge to within 0.1C
888 0 : int constexpr MaxIterations(10); // Maximum number of iterations to achieve temperature control
889 : // (10 interval halvings achieves control to 0.1% of capacity)
890 : // These two parameters are intended to achieve reasonable control
891 : // without excessive run times.
892 :
893 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
894 0 : Real64 ZoneTemp(0.0); // zone temperature (MAT, MRT, or Operative Temperature, depending on control type) [C]
895 :
896 : // initialize local variables
897 0 : int ZoneNum = thisHTR.ZonePtr;
898 0 : thisHTR.QHTRRadSource = 0.0;
899 :
900 0 : if (thisHTR.availSched->getCurrentVal() > 0) {
901 :
902 : // Unit is scheduled on-->this section is intended to control the output of the
903 : // high temperature radiant heater (temperature controlled)
904 :
905 : // Determine the current setpoint temperature and the temperature at which the unit should be completely off
906 0 : Real64 SetPtTemp = thisHTR.setptSched->getCurrentVal();
907 :
908 : // Now, distribute the radiant energy of all systems to the appropriate
909 : // surfaces, to people, and the air; determine the latent portion
910 0 : DistributeHTRadGains(state);
911 :
912 : // Now "simulate" the system by recalculating the heat balances
913 0 : HeatBalanceSurfaceManager::CalcHeatBalanceOutsideSurf(state, ZoneNum);
914 0 : HeatBalanceSurfaceManager::CalcHeatBalanceInsideSurf(state, ZoneNum);
915 :
916 : // First determine whether or not the unit should be on
917 : // Determine the proper temperature on which to control
918 0 : auto const &thisZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum);
919 0 : switch (thisHTR.ControlType) {
920 0 : case RadControlType::MATSPControl: {
921 0 : ZoneTemp = thisZoneHB.MAT;
922 0 : } break;
923 0 : case RadControlType::MRTSPControl: {
924 0 : ZoneTemp = thisZoneHB.MRT;
925 0 : } break;
926 0 : case RadControlType::OperativeSPControl: {
927 0 : ZoneTemp = 0.5 * (thisZoneHB.MAT + thisZoneHB.MRT);
928 0 : } break;
929 0 : default: {
930 0 : assert(false);
931 : } break;
932 : }
933 :
934 0 : if (ZoneTemp < (SetPtTemp - TempConvToler)) {
935 :
936 : // Use simple interval halving to find the best operating fraction to achieve proper temperature control
937 0 : int IterNum = 0;
938 0 : bool ConvergFlag = false;
939 : float HeatFrac; // fraction of maximum energy input to radiant system [dimensionless]
940 0 : float HeatFracMax = 1.0;
941 0 : float HeatFracMin = 0.0;
942 :
943 0 : while ((IterNum <= MaxIterations) && (!ConvergFlag)) {
944 :
945 : // In the first iteration (IterNum=0), try full capacity and see if that is the best solution
946 0 : if (IterNum == 0) {
947 0 : HeatFrac = 1.0;
948 : } else {
949 0 : HeatFrac = (HeatFracMin + HeatFracMax) / 2.0;
950 : }
951 :
952 : // Set the heat source for the high temperature radiant system
953 0 : thisHTR.QHTRRadSource = HeatFrac * thisHTR.MaxPowerCapac;
954 :
955 : // Now, distribute the radiant energy of all systems to the appropriate
956 : // surfaces, to people, and the air; determine the latent portion
957 0 : DistributeHTRadGains(state);
958 :
959 : // Now "simulate" the system by recalculating the heat balances
960 0 : HeatBalanceSurfaceManager::CalcHeatBalanceOutsideSurf(state, ZoneNum);
961 0 : HeatBalanceSurfaceManager::CalcHeatBalanceInsideSurf(state, ZoneNum);
962 :
963 : // Redetermine the current value of the controlling temperature
964 0 : auto const &thisZoneHBMod = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum);
965 0 : switch (thisHTR.ControlType) {
966 0 : case RadControlType::MATControl: {
967 0 : ZoneTemp = thisZoneHBMod.MAT;
968 0 : } break;
969 0 : case RadControlType::MRTControl: {
970 0 : ZoneTemp = thisZoneHBMod.MRT;
971 0 : } break;
972 0 : case RadControlType::OperativeControl: {
973 0 : ZoneTemp = 0.5 * (thisZoneHBMod.MAT + thisZoneHBMod.MRT);
974 0 : } break;
975 0 : default:
976 0 : break;
977 : }
978 :
979 0 : if ((std::abs(ZoneTemp - SetPtTemp)) <= TempConvToler) {
980 : // The radiant heater has controlled the zone temperature to the appropriate level--stop iterating
981 0 : ConvergFlag = true;
982 0 : } else if (ZoneTemp < SetPtTemp) {
983 : // The zone temperature is too low--try increasing the radiant heater output
984 0 : if (IterNum == 0) {
985 : // Heater already at capacity--this is the best that we can do
986 0 : ConvergFlag = true;
987 : } else {
988 0 : HeatFracMin = HeatFrac;
989 : }
990 : } else { // (ZoneTemp > SetPtTemp)
991 : // The zone temperature is too high--try decreasing the radiant heater output
992 0 : if (IterNum > 0) {
993 0 : HeatFracMax = HeatFrac;
994 : }
995 : }
996 :
997 0 : ++IterNum;
998 : }
999 : }
1000 : }
1001 0 : }
1002 :
1003 0 : void UpdateHighTempRadiantSystem(EnergyPlusData &state,
1004 : int const RadSysNum, // Index for the low temperature radiant system under consideration within the derived types
1005 : Real64 &LoadMet // load met by the radiant system, in Watts
1006 : )
1007 : {
1008 :
1009 : // SUBROUTINE INFORMATION:
1010 : // AUTHOR Rick Strand
1011 : // DATE WRITTEN February 2001
1012 :
1013 : // PURPOSE OF THIS SUBROUTINE:
1014 : // This subroutine does any updating that needs to be done for high
1015 : // temperature radiant heating systems. This routine has two functions.
1016 : // First, it needs to keep track of the average high temperature
1017 : // radiant source. The method for doing this is similar to low
1018 : // temperature systems except that heat input is kept locally on
1019 : // a system basis rather than a surface basis. This is because a high
1020 : // temperature system affects many surfaces while a low temperature
1021 : // system directly affects only one surface. This leads to the second
1022 : // function of this subroutine which is to account for the affect of
1023 : // all high temperature radiant systems on each surface. This
1024 : // distribution must be "redone" every time to be sure that we have
1025 : // properly accounted for all of the systems.
1026 :
1027 : // METHODOLOGY EMPLOYED:
1028 : // For the source average update, if the system time step elapsed is
1029 : // still what it used to be, then either we are still iterating or we
1030 : // had to go back and shorten the time step. As a result, we have to
1031 : // subtract out the previous value that we added. If the system time
1032 : // step elapsed is different, then we just need to add the new values
1033 : // to the running average.
1034 :
1035 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1036 : int ZoneNum; // Zone index number for the current radiant system
1037 0 : Real64 SysTimeElapsed = state.dataHVACGlobal->SysTimeElapsed;
1038 0 : Real64 TimeStepSys = state.dataHVACGlobal->TimeStepSys;
1039 0 : auto &thisHTR = state.dataHighTempRadSys->HighTempRadSys(RadSysNum);
1040 :
1041 : // First, update the running average if necessary...
1042 0 : if (thisHTR.LastSysTimeElapsed == SysTimeElapsed) {
1043 : // Still iterating or reducing system time step, so subtract old values which were
1044 : // not valid
1045 0 : thisHTR.QHTRRadSrcAvg -= thisHTR.LastQHTRRadSrc * thisHTR.LastTimeStepSys / state.dataGlobal->TimeStepZone;
1046 : }
1047 :
1048 : // Update the running average and the "last" values with the current values of the appropriate variables
1049 0 : thisHTR.QHTRRadSrcAvg += thisHTR.QHTRRadSource * TimeStepSys / state.dataGlobal->TimeStepZone;
1050 :
1051 0 : thisHTR.LastQHTRRadSrc = thisHTR.QHTRRadSource;
1052 0 : thisHTR.LastSysTimeElapsed = SysTimeElapsed;
1053 0 : thisHTR.LastTimeStepSys = TimeStepSys;
1054 :
1055 0 : switch (thisHTR.ControlType) {
1056 0 : case RadControlType::MATControl:
1057 : case RadControlType::MRTControl:
1058 : case RadControlType::OperativeControl: {
1059 : // Only need to do this for the non-SP controls (SP has already done this enough)
1060 : // Now, distribute the radiant energy of all systems to the appropriate
1061 : // surfaces, to people, and the air; determine the latent portion
1062 0 : DistributeHTRadGains(state);
1063 :
1064 : // Now "simulate" the system by recalculating the heat balances
1065 0 : ZoneNum = thisHTR.ZonePtr;
1066 0 : HeatBalanceSurfaceManager::CalcHeatBalanceOutsideSurf(state, ZoneNum);
1067 0 : HeatBalanceSurfaceManager::CalcHeatBalanceInsideSurf(state, ZoneNum);
1068 0 : } break;
1069 0 : default:
1070 0 : break;
1071 : }
1072 :
1073 0 : if (thisHTR.QHTRRadSource <= 0.0) {
1074 0 : LoadMet = 0.0; // System wasn't running so it can't meet a load
1075 : } else {
1076 0 : ZoneNum = thisHTR.ZonePtr;
1077 0 : LoadMet = (state.dataHeatBal->Zone(ZoneNum).sumHATsurf(state) - thisHTR.ZeroHTRSourceSumHATsurf) +
1078 0 : state.dataHeatBalFanSys->SumConvHTRadSys(ZoneNum);
1079 : }
1080 0 : }
1081 :
1082 249945 : void UpdateHTRadSourceValAvg(EnergyPlusData &state, bool &HighTempRadSysOn) // .TRUE. if the radiant system has run this zone time step
1083 : {
1084 :
1085 : // SUBROUTINE INFORMATION:
1086 : // AUTHOR Rick Strand
1087 : // DATE WRITTEN February 2001
1088 :
1089 : // PURPOSE OF THIS SUBROUTINE:
1090 : // To transfer the average value of the heat source over the entire
1091 : // zone time step back to the heat balance routines so that the heat
1092 : // balance algorithms can simulate one last time with the average source
1093 : // to maintain some reasonable amount of continuity and energy balance
1094 : // in the temperature and flux histories.
1095 :
1096 : // METHODOLOGY EMPLOYED:
1097 : // All of the record keeping for the average term is done in the Update
1098 : // routine so the only other thing that this subroutine does is check to
1099 : // see if the system was even on. If any average term is non-zero, then
1100 : // one or more of the radiant systems was running.
1101 :
1102 249945 : HighTempRadSysOn = false;
1103 :
1104 : // If this was never allocated, then there are no radiant systems in this input file (just RETURN)
1105 249945 : if (state.dataHighTempRadSys->NumOfHighTempRadSys == 0) {
1106 249945 : return;
1107 : }
1108 :
1109 : // If it was allocated, then we have to check to see if this was running at all...
1110 0 : for (auto &thisHTR : state.dataHighTempRadSys->HighTempRadSys) {
1111 0 : thisHTR.QHTRRadSource = thisHTR.QHTRRadSrcAvg;
1112 0 : if (thisHTR.QHTRRadSrcAvg != 0.0) {
1113 0 : HighTempRadSysOn = true;
1114 : }
1115 : }
1116 :
1117 0 : DistributeHTRadGains(
1118 : state); // state.dataHighTempRadSys->HighTempRadSys(RadSysNum).QHTRRadSource has been modified so we need to redistribute gains
1119 : }
1120 :
1121 0 : void DistributeHTRadGains(EnergyPlusData &state)
1122 : {
1123 :
1124 : // SUBROUTINE INFORMATION:
1125 : // AUTHOR Rick Strand
1126 : // DATE WRITTEN February 2001
1127 : // MODIFIED April 2010 Brent Griffith, max limit to protect surface temperature calcs
1128 :
1129 : // PURPOSE OF THIS SUBROUTINE:
1130 : // To distribute the gains from the high temperature radiant heater
1131 : // as specified in the user input file. This includes distribution
1132 : // of long wavelength radiant gains to surfaces and "people" as well
1133 : // as latent, lost, and convective portions of the total gain.
1134 :
1135 : // METHODOLOGY EMPLOYED:
1136 : // We must cycle through all of the radiant systems because each
1137 : // surface could feel the effect of more than one radiant system.
1138 : // Note that the energy radiated to people is assumed to affect them
1139 : // but them it is assumed to be convected to the air. This is why
1140 : // the convective portion shown below has two parts to it.
1141 :
1142 : // SUBROUTINE PARAMETER DEFINITIONS:
1143 0 : Real64 constexpr SmallestArea = 0.001; // Smallest area in meters squared (to avoid a divide by zero)
1144 :
1145 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1146 : Real64 ThisSurfIntensity; // temporary for W/m2 term for rad on a surface
1147 :
1148 : // Using/Aliasing
1149 0 : auto &dataHBFS = state.dataHeatBalFanSys;
1150 :
1151 : // Initialize arrays
1152 0 : dataHBFS->SumConvHTRadSys = 0.0;
1153 0 : dataHBFS->SumLatentHTRadSys = 0.0;
1154 0 : for (auto &thisHTR : state.dataHighTempRadSys->HighTempRadSys) {
1155 0 : for (int radSurfNum = 1; radSurfNum <= thisHTR.TotSurfToDistrib; ++radSurfNum) {
1156 0 : int surfNum = thisHTR.SurfacePtr(radSurfNum);
1157 0 : state.dataHeatBalFanSys->surfQRadFromHVAC(surfNum).HTRadSys = 0.0;
1158 : }
1159 : }
1160 0 : dataHBFS->ZoneQHTRadSysToPerson = 0.0;
1161 :
1162 0 : for (auto &thisHTR : state.dataHighTempRadSys->HighTempRadSys) {
1163 0 : int ZoneNum = thisHTR.ZonePtr;
1164 :
1165 0 : dataHBFS->ZoneQHTRadSysToPerson(ZoneNum) = thisHTR.QHTRRadSource * thisHTR.FracRadiant * thisHTR.FracDistribPerson;
1166 0 : dataHBFS->SumConvHTRadSys(ZoneNum) += thisHTR.QHTRRadSource * thisHTR.FracConvect;
1167 0 : dataHBFS->SumLatentHTRadSys(ZoneNum) += thisHTR.QHTRRadSource * thisHTR.FracLatent;
1168 :
1169 0 : for (int RadSurfNum = 1; RadSurfNum <= thisHTR.TotSurfToDistrib; ++RadSurfNum) {
1170 0 : int SurfNum = thisHTR.SurfacePtr(RadSurfNum);
1171 0 : if (state.dataSurface->Surface(SurfNum).Area > SmallestArea) {
1172 0 : ThisSurfIntensity = (thisHTR.QHTRRadSource * thisHTR.FracRadiant * thisHTR.FracDistribToSurf(RadSurfNum) /
1173 0 : state.dataSurface->Surface(SurfNum).Area);
1174 0 : state.dataHeatBalFanSys->surfQRadFromHVAC(SurfNum).HTRadSys += ThisSurfIntensity;
1175 :
1176 0 : if (ThisSurfIntensity > DataHeatBalFanSys::MaxRadHeatFlux) { // CR 8074, trap excessive intensity (throws off surface balance )
1177 0 : ShowSevereError(state, "DistributeHTRadGains: excessive thermal radiation heat flux intensity detected");
1178 0 : ShowContinueError(state, format("Surface = {}", state.dataSurface->Surface(SurfNum).Name));
1179 0 : ShowContinueError(state, format("Surface area = {:.3R} [m2]", state.dataSurface->Surface(SurfNum).Area));
1180 0 : ShowContinueError(state, format("Occurs in ZoneHVAC:HighTemperatureRadiant = {}", thisHTR.Name));
1181 0 : ShowContinueError(state, format("Radiation intensity = {:.2R} [W/m2]", ThisSurfIntensity));
1182 0 : ShowContinueError(state, "Assign a larger surface area or more surfaces in ZoneHVAC:HighTemperatureRadiant");
1183 0 : ShowFatalError(state, "DistributeHTRadGains: excessive thermal radiation heat flux intensity detected");
1184 : }
1185 : } else { // small surface
1186 0 : ShowSevereError(state, "DistributeHTRadGains: surface not large enough to receive thermal radiation heat flux");
1187 0 : ShowContinueError(state, format("Surface = {}", state.dataSurface->Surface(SurfNum).Name));
1188 0 : ShowContinueError(state, format("Surface area = {:.3R} [m2]", state.dataSurface->Surface(SurfNum).Area));
1189 0 : ShowContinueError(state, format("Occurs in ZoneHVAC:HighTemperatureRadiant = {}", thisHTR.Name));
1190 0 : ShowContinueError(state, "Assign a larger surface area or more surfaces in ZoneHVAC:HighTemperatureRadiant");
1191 0 : ShowFatalError(state, "DistributeHTRadGains: surface not large enough to receive thermal radiation heat flux");
1192 : }
1193 : }
1194 : }
1195 :
1196 : // Here an assumption is made regarding radiant heat transfer to people.
1197 : // While the ZoneQHTRadSysToPerson array will be used by the thermal comfort
1198 : // routines, the energy transfer to people would get lost from the perspective
1199 : // of the heat balance. So, to avoid this net loss of energy which clearly
1200 : // gets added to the zones, we must account for it somehow. This assumption
1201 : // that all energy radiated to people is converted to convective energy is
1202 : // not very precise, but at least it conserves energy.
1203 0 : for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
1204 0 : dataHBFS->SumConvHTRadSys(ZoneNum) += dataHBFS->ZoneQHTRadSysToPerson(ZoneNum);
1205 : }
1206 0 : }
1207 :
1208 0 : void ReportHighTempRadiantSystem(EnergyPlusData &state,
1209 : int const RadSysNum) // Index for the low temperature radiant system under consideration within the derived types
1210 : {
1211 :
1212 : // SUBROUTINE INFORMATION:
1213 : // AUTHOR Rick Strand
1214 : // DATE WRITTEN February 2001
1215 :
1216 : // PURPOSE OF THIS SUBROUTINE:
1217 : // This subroutine simply produces output for the high temperature radiant system.
1218 :
1219 : // Using/Aliasing
1220 0 : Real64 TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
1221 0 : auto &thisHTR = state.dataHighTempRadSys->HighTempRadSys(RadSysNum);
1222 :
1223 0 : if (thisHTR.HeaterType == Constant::eResource::NaturalGas) {
1224 0 : thisHTR.GasPower = thisHTR.QHTRRadSource / thisHTR.CombustionEffic;
1225 0 : thisHTR.GasEnergy = thisHTR.GasPower * TimeStepSysSec;
1226 0 : thisHTR.ElecPower = 0.0;
1227 0 : thisHTR.ElecEnergy = 0.0;
1228 0 : } else if (thisHTR.HeaterType == Constant::eResource::Electricity) {
1229 0 : thisHTR.GasPower = 0.0;
1230 0 : thisHTR.GasEnergy = 0.0;
1231 0 : thisHTR.ElecPower = thisHTR.QHTRRadSource;
1232 0 : thisHTR.ElecEnergy = thisHTR.ElecPower * TimeStepSysSec;
1233 : } else {
1234 0 : ShowWarningError(state, "Someone forgot to add a high temperature radiant heater type to the reporting subroutine");
1235 : }
1236 0 : thisHTR.HeatPower = thisHTR.QHTRRadSource;
1237 0 : thisHTR.HeatEnergy = thisHTR.HeatPower * TimeStepSysSec;
1238 0 : }
1239 :
1240 : } // namespace HighTempRadiantSystem
1241 :
1242 : } // namespace EnergyPlus
|