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