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