Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2025, The Board of Trustees of the University of Illinois,
2 : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
3 : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
4 : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
5 : // contributors. All rights reserved.
6 : //
7 : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
8 : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
9 : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
10 : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
11 : // derivative works, and perform publicly and display publicly, and to permit others to do so.
12 : //
13 : // Redistribution and use in source and binary forms, with or without modification, are permitted
14 : // provided that the following conditions are met:
15 : //
16 : // (1) Redistributions of source code must retain the above copyright notice, this list of
17 : // conditions and the following disclaimer.
18 : //
19 : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
20 : // conditions and the following disclaimer in the documentation and/or other materials
21 : // provided with the distribution.
22 : //
23 : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
24 : // the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
25 : // used to endorse or promote products derived from this software without specific prior
26 : // written permission.
27 : //
28 : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
29 : // without changes from the version obtained under this License, or (ii) Licensee makes a
30 : // reference solely to the software portion of its product, Licensee must refer to the
31 : // software as "EnergyPlus version X" software, where "X" is the version number Licensee
32 : // obtained under this License and may not use a different name for the software. Except as
33 : // specifically required in this Section (4), Licensee shall not use in a company name, a
34 : // product name, in advertising, publicity, or other promotional activities any name, trade
35 : // name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
36 : // similar designation, without the U.S. Department of Energy's prior written consent.
37 : //
38 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
39 : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
40 : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
41 : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43 : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
45 : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46 : // POSSIBILITY OF SUCH DAMAGE.
47 :
48 : // C++ Headers
49 : #include <cmath>
50 :
51 : // ObjexxFCL Headers
52 : #include <ObjexxFCL/Array.functions.hh>
53 : #include <ObjexxFCL/Fmath.hh>
54 :
55 : // EnergyPlus Headers
56 : #include <EnergyPlus/Autosizing/HeatingCapacitySizing.hh>
57 : #include <EnergyPlus/BranchNodeConnections.hh>
58 : #include <EnergyPlus/Data/EnergyPlusData.hh>
59 : #include <EnergyPlus/DataEnvironment.hh>
60 : #include <EnergyPlus/DataHVACGlobals.hh>
61 : #include <EnergyPlus/DataHeatBalFanSys.hh>
62 : #include <EnergyPlus/DataHeatBalSurface.hh>
63 : #include <EnergyPlus/DataHeatBalance.hh>
64 : #include <EnergyPlus/DataIPShortCuts.hh>
65 : #include <EnergyPlus/DataLoopNode.hh>
66 : #include <EnergyPlus/DataSurfaces.hh>
67 : #include <EnergyPlus/DataZoneEnergyDemands.hh>
68 : #include <EnergyPlus/DataZoneEquipment.hh>
69 : #include <EnergyPlus/FluidProperties.hh>
70 : #include <EnergyPlus/General.hh>
71 : #include <EnergyPlus/GeneralRoutines.hh>
72 : #include <EnergyPlus/GlobalNames.hh>
73 : #include <EnergyPlus/HWBaseboardRadiator.hh>
74 : #include <EnergyPlus/HeatBalanceIntRadExchange.hh>
75 : #include <EnergyPlus/HeatBalanceSurfaceManager.hh>
76 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
77 : #include <EnergyPlus/NodeInputManager.hh>
78 : #include <EnergyPlus/OutputProcessor.hh>
79 : #include <EnergyPlus/Plant/DataPlant.hh>
80 : #include <EnergyPlus/PlantUtilities.hh>
81 : #include <EnergyPlus/Psychrometrics.hh>
82 : #include <EnergyPlus/ScheduleManager.hh>
83 : #include <EnergyPlus/UtilityRoutines.hh>
84 :
85 : namespace EnergyPlus {
86 :
87 : namespace HWBaseboardRadiator {
88 :
89 : // Module -- (ref: Object: ZoneHVAC:Baseboard:RadiantConvective:Water)
90 :
91 : // Module containing the routines dealing with the hot water baseboard heaters
92 :
93 : // MODULE INFORMATION:
94 : // AUTHOR Daeho Kang
95 : // DATE WRITTEN Aug 2007
96 :
97 : // PURPOSE OF THIS MODULE:
98 : // The purpose of this module is to simulate hot water baseboard heaters.
99 :
100 : // REFERENCES:
101 : // 1. I=B=R Ratings for Baseboards, Baseboard Radiation,
102 : // Finned Tube (Commercial) Radiation, and Indirect Fired Water Heaters, January 2007 Edition
103 : // 2. Incropera and DeWitt, Fundamentals of Heat and Mass Transfer, Chapter 11.3 and 11.4,
104 : // eq. 11.15, 11.17, and 11.33
105 :
106 : std::string const cCMO_BBRadiator_Water("ZoneHVAC:Baseboard:RadiantConvective:Water");
107 : std::string const cCMO_BBRadiator_Water_Design("ZoneHVAC:Baseboard:RadiantConvective:Water:Design");
108 :
109 89083 : void SimHWBaseboard(EnergyPlusData &state,
110 : std::string const &EquipName,
111 : int const ControlledZoneNum,
112 : bool const FirstHVACIteration,
113 : Real64 &PowerMet,
114 : int &CompIndex)
115 : {
116 :
117 : // SUBROUTINE INFORMATION:
118 : // AUTHOR Russ Taylor
119 : // DATE WRITTEN Nov 1997
120 :
121 : // PURPOSE OF THIS SUBROUTINE:
122 : // This subroutine simulates the Baseboard Radiators.
123 :
124 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
125 : int BaseboardNum; // Index of unit in baseboard array
126 : Real64 QZnReq; // Zone load not yet satisfied
127 : Real64 MaxWaterFlow;
128 : Real64 MinWaterFlow;
129 :
130 89083 : if (state.dataHWBaseboardRad->GetInputFlag) {
131 7 : GetHWBaseboardInput(state);
132 7 : state.dataHWBaseboardRad->GetInputFlag = false;
133 : }
134 :
135 89083 : int const NumHWBaseboards = state.dataHWBaseboardRad->NumHWBaseboards;
136 :
137 : // Find the correct Baseboard Equipment
138 89083 : if (CompIndex == 0) {
139 17 : BaseboardNum = Util::FindItemInList(EquipName, state.dataHWBaseboardRad->HWBaseboard, &HWBaseboardParams::Name);
140 17 : if (BaseboardNum == 0) {
141 0 : ShowFatalError(state, format("SimHWBaseboard: Unit not found={}", EquipName));
142 : }
143 17 : CompIndex = BaseboardNum;
144 : } else {
145 89066 : BaseboardNum = CompIndex;
146 89066 : if (BaseboardNum > NumHWBaseboards || BaseboardNum < 1) {
147 0 : ShowFatalError(state,
148 0 : format("SimHWBaseboard: Invalid CompIndex passed={}, Number of Units={}, Entered Unit name={}",
149 : BaseboardNum,
150 : NumHWBaseboards,
151 : EquipName));
152 : }
153 89066 : if (state.dataHWBaseboardRad->CheckEquipName(BaseboardNum)) {
154 17 : if (EquipName != state.dataHWBaseboardRad->HWBaseboard(BaseboardNum).Name) {
155 0 : ShowFatalError(state,
156 0 : format("SimHWBaseboard: Invalid CompIndex passed={}, Unit name={}, stored Unit Name for that index={}",
157 : BaseboardNum,
158 : EquipName,
159 0 : state.dataHWBaseboardRad->HWBaseboard(BaseboardNum).Name));
160 : }
161 17 : state.dataHWBaseboardRad->CheckEquipName(BaseboardNum) = false;
162 : }
163 : }
164 :
165 89083 : if (CompIndex > 0) {
166 89083 : auto &HWBaseboard = state.dataHWBaseboardRad->HWBaseboard(BaseboardNum);
167 :
168 89083 : HWBaseboardDesignData const &HWBaseboardDesignDataObject = state.dataHWBaseboardRad->HWBaseboardDesignObject(
169 : HWBaseboard.DesignObjectPtr); // Contains the data for variable flow hydronic systems
170 :
171 89083 : InitHWBaseboard(state, BaseboardNum, ControlledZoneNum, FirstHVACIteration);
172 :
173 89083 : QZnReq = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ControlledZoneNum).RemainingOutputReqToHeatSP;
174 :
175 : // On the first HVAC iteration the system values are given to the controller, but after that
176 : // the demand limits are in place and there needs to be feedback to the Zone Equipment
177 89083 : if (FirstHVACIteration) {
178 42552 : MaxWaterFlow = HWBaseboard.WaterMassFlowRateMax;
179 42552 : MinWaterFlow = 0.0;
180 : } else {
181 46531 : MaxWaterFlow = state.dataLoopNodes->Node(HWBaseboard.WaterInletNode).MassFlowRateMaxAvail;
182 46531 : MinWaterFlow = state.dataLoopNodes->Node(HWBaseboard.WaterInletNode).MassFlowRateMinAvail;
183 : }
184 :
185 89083 : switch (HWBaseboard.EquipType) {
186 89083 : case DataPlant::PlantEquipmentType::Baseboard_Rad_Conv_Water: { // 'ZoneHVAC:Baseboard:RadiantConvective:Water'
187 267249 : ControlCompOutput(state,
188 89083 : HWBaseboard.Name,
189 : cCMO_BBRadiator_Water,
190 : BaseboardNum,
191 : FirstHVACIteration,
192 : QZnReq,
193 : HWBaseboard.WaterInletNode,
194 : MaxWaterFlow,
195 : MinWaterFlow,
196 89083 : HWBaseboardDesignDataObject.Offset,
197 89083 : HWBaseboard.ControlCompTypeNum,
198 89083 : HWBaseboard.CompErrIndex,
199 : _,
200 : _,
201 : _,
202 : _,
203 : _,
204 89083 : HWBaseboard.plantLoc);
205 89083 : } break;
206 0 : default: {
207 0 : ShowSevereError(state, format("SimBaseboard: Errors in Baseboard={}", HWBaseboard.Name));
208 0 : ShowContinueError(state, format("Invalid or unimplemented equipment type={}", HWBaseboard.EquipType));
209 0 : ShowFatalError(state, "Preceding condition causes termination.");
210 0 : } break;
211 : }
212 :
213 89083 : PowerMet = HWBaseboard.TotPower;
214 :
215 89083 : UpdateHWBaseboard(state, BaseboardNum);
216 :
217 89083 : ReportHWBaseboard(state, BaseboardNum);
218 :
219 : } else {
220 0 : ShowFatalError(state, format("SimHWBaseboard: Unit not found={}", EquipName));
221 : }
222 89083 : }
223 :
224 7 : void GetHWBaseboardInput(EnergyPlusData &state)
225 : {
226 :
227 : // SUBROUTINE INFORMATION:
228 : // AUTHOR Daeho Kang
229 : // DATE WRITTEN Aug 2007
230 :
231 : // PURPOSE OF THIS SUBROUTINE:
232 : // This subroutine gets the input for the baseboard units.
233 :
234 : // METHODOLOGY EMPLOYED:
235 : // Standard input processor calls.
236 :
237 : // SUBROUTINE PARAMETER DEFINITIONS:
238 : static constexpr std::string_view RoutineName("GetHWBaseboardInput:");
239 : static constexpr std::string_view routineName = "GetHWBaseboardInput";
240 :
241 7 : Real64 constexpr MaxFraction(1.0);
242 7 : Real64 constexpr MinFraction(0.0);
243 7 : Real64 constexpr MaxWaterTempAvg(150.0); // Maximum limit of average water temperature in degree C
244 7 : Real64 constexpr MinWaterTempAvg(20.0); // Minimum limit of average water temperature in degree C
245 7 : Real64 constexpr HighWaterMassFlowRate(10.0); // Maximum limit of water mass flow rate in kg/s
246 7 : Real64 constexpr LowWaterMassFlowRate(0.00001); // Minimum limit of water mass flow rate in kg/s
247 7 : Real64 constexpr MaxWaterFlowRate(10.0); // Maximum limit of water volume flow rate in m3/s
248 7 : Real64 constexpr MinWaterFlowRate(0.00001); // Minimum limit of water volume flow rate in m3/s
249 7 : Real64 constexpr WaterMassFlowDefault(0.063); // Default water mass flow rate in kg/s
250 7 : int constexpr MinDistribSurfaces(1); // Minimum number of surfaces that a baseboard heater can radiate to
251 7 : int constexpr iHeatCAPMAlphaNum(2); // get input index to HW baseboard heating capacity sizing method
252 7 : int constexpr iHeatDesignCapacityNumericNum(3); // get input index to HW baseboard heating capacity
253 7 : int constexpr iHeatCapacityPerFloorAreaNumericNum(1); // get input index to HW baseboard heating capacity per floor area sizing
254 7 : int constexpr iHeatFracOfAutosizedCapacityNumericNum(
255 : 2); // get input index to HW baseboard heating capacity sizing as fraction of autosized heating capacity
256 :
257 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
258 : int BaseboardNum; // Baseboard number
259 : int BaseboardDesignNum;
260 : int NumAlphas; // Number of Alphas for each GetobjectItem call
261 : int NumNumbers; // Number of Numbers for each GetobjectItem call
262 : int SurfNum; // Surface number Do loop counter
263 : int IOStat;
264 7 : bool ErrorsFound(false); // If errors detected in input
265 :
266 : // Update Nums in state and make local convenience copies
267 14 : int NumHWBaseboards = state.dataHWBaseboardRad->NumHWBaseboards =
268 7 : state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCMO_BBRadiator_Water);
269 14 : int NumHWBaseboardDesignObjs = state.dataHWBaseboardRad->NumHWBaseboardDesignObjs =
270 7 : state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCMO_BBRadiator_Water_Design);
271 :
272 : // Count total number of baseboard units
273 :
274 7 : state.dataHWBaseboardRad->HWBaseboard.allocate(NumHWBaseboards);
275 7 : state.dataHWBaseboardRad->HWBaseboardDesignObject.allocate(NumHWBaseboardDesignObjs);
276 7 : state.dataHWBaseboardRad->CheckEquipName.allocate(NumHWBaseboards);
277 7 : state.dataHWBaseboardRad->HWBaseboardNumericFields.allocate(NumHWBaseboards);
278 7 : Array1D_string HWBaseboardDesignNames;
279 7 : HWBaseboardDesignNames.allocate(NumHWBaseboardDesignObjs);
280 7 : state.dataHWBaseboardRad->CheckEquipName = true;
281 :
282 : // Get the data from the user input related to design data for baseboard heaters
283 18 : for (BaseboardDesignNum = 1; BaseboardDesignNum <= NumHWBaseboardDesignObjs; ++BaseboardDesignNum) {
284 11 : auto &thisHWBaseboardDesign = state.dataHWBaseboardRad->HWBaseboardDesignObject(BaseboardDesignNum);
285 :
286 22 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
287 : cCMO_BBRadiator_Water_Design,
288 : BaseboardDesignNum,
289 11 : state.dataIPShortCut->cAlphaArgs,
290 : NumAlphas,
291 11 : state.dataIPShortCut->rNumericArgs,
292 : NumNumbers,
293 : IOStat,
294 11 : state.dataIPShortCut->lNumericFieldBlanks,
295 11 : state.dataIPShortCut->lAlphaFieldBlanks,
296 11 : state.dataIPShortCut->cAlphaFieldNames,
297 11 : state.dataIPShortCut->cNumericFieldNames);
298 :
299 : // ErrorsFound will be set to True if problem was found, left untouched otherwise
300 11 : GlobalNames::VerifyUniqueBaseboardName(
301 22 : state, cCMO_BBRadiator_Water_Design, state.dataIPShortCut->cAlphaArgs(1), ErrorsFound, cCMO_BBRadiator_Water_Design + " Name");
302 :
303 11 : thisHWBaseboardDesign.designName = state.dataIPShortCut->cAlphaArgs(1); // Name of this baseboard design object
304 11 : HWBaseboardDesignNames(BaseboardDesignNum) = thisHWBaseboardDesign.designName;
305 :
306 : // Determine HW radiant baseboard heating design capacity sizing method
307 11 : thisHWBaseboardDesign.HeatingCapMethod = static_cast<DataSizing::DesignSizingType>(
308 11 : getEnumValue(DataSizing::DesignSizingTypeNamesUC, state.dataIPShortCut->cAlphaArgs(iHeatCAPMAlphaNum)));
309 11 : if (thisHWBaseboardDesign.HeatingCapMethod == DataSizing::DesignSizingType::CapacityPerFloorArea) {
310 0 : if (!state.dataIPShortCut->lNumericFieldBlanks(iHeatCapacityPerFloorAreaNumericNum)) {
311 0 : thisHWBaseboardDesign.ScaledHeatingCapacity = state.dataIPShortCut->rNumericArgs(iHeatCapacityPerFloorAreaNumericNum);
312 0 : if (thisHWBaseboardDesign.ScaledHeatingCapacity <= 0.0) {
313 0 : ShowSevereError(state, format("{} = {}", state.dataIPShortCut->cCurrentModuleObject, thisHWBaseboardDesign.designName));
314 0 : ShowContinueError(state,
315 0 : format("Input for {} = {}",
316 0 : state.dataIPShortCut->cAlphaFieldNames(iHeatCAPMAlphaNum),
317 0 : state.dataIPShortCut->cAlphaArgs(iHeatCAPMAlphaNum)));
318 0 : ShowContinueError(state,
319 0 : format("Illegal {} = {:.7T}",
320 0 : state.dataIPShortCut->cNumericFieldNames(iHeatCapacityPerFloorAreaNumericNum),
321 0 : state.dataIPShortCut->rNumericArgs(iHeatCapacityPerFloorAreaNumericNum)));
322 0 : ErrorsFound = true;
323 0 : } else if (thisHWBaseboardDesign.ScaledHeatingCapacity == DataSizing::AutoSize) {
324 0 : ShowSevereError(state, format("{} = {}", state.dataIPShortCut->cCurrentModuleObject, thisHWBaseboardDesign.designName));
325 0 : ShowContinueError(state,
326 0 : format("Input for {} = {}",
327 0 : state.dataIPShortCut->cAlphaFieldNames(iHeatCAPMAlphaNum),
328 0 : state.dataIPShortCut->cAlphaArgs(iHeatCAPMAlphaNum)));
329 0 : ShowContinueError(
330 0 : state, format("Illegal {} = Autosize", state.dataIPShortCut->cNumericFieldNames(iHeatCapacityPerFloorAreaNumericNum)));
331 0 : ErrorsFound = true;
332 : }
333 : } else {
334 0 : ShowSevereError(state, format("{} = {}", state.dataIPShortCut->cCurrentModuleObject, thisHWBaseboardDesign.designName));
335 0 : ShowContinueError(state,
336 0 : format("Input for {} = {}",
337 0 : state.dataIPShortCut->cAlphaFieldNames(iHeatCAPMAlphaNum),
338 0 : state.dataIPShortCut->cAlphaArgs(iHeatCAPMAlphaNum)));
339 0 : ShowContinueError(
340 : state,
341 0 : format("Blank field not allowed for {}", state.dataIPShortCut->cNumericFieldNames(iHeatCapacityPerFloorAreaNumericNum)));
342 0 : ErrorsFound = true;
343 : }
344 11 : } else if (thisHWBaseboardDesign.HeatingCapMethod == DataSizing::DesignSizingType::FractionOfAutosizedHeatingCapacity) {
345 0 : if (!state.dataIPShortCut->lNumericFieldBlanks(iHeatFracOfAutosizedCapacityNumericNum)) {
346 0 : thisHWBaseboardDesign.ScaledHeatingCapacity = state.dataIPShortCut->rNumericArgs(iHeatFracOfAutosizedCapacityNumericNum);
347 0 : if (thisHWBaseboardDesign.ScaledHeatingCapacity < 0.0) {
348 0 : ShowSevereError(state, format("{} = {}", state.dataIPShortCut->cCurrentModuleObject, thisHWBaseboardDesign.designName));
349 0 : ShowContinueError(state,
350 0 : format("Illegal {} = {:.7T}",
351 0 : state.dataIPShortCut->cNumericFieldNames(iHeatFracOfAutosizedCapacityNumericNum),
352 0 : state.dataIPShortCut->rNumericArgs(iHeatFracOfAutosizedCapacityNumericNum)));
353 0 : ErrorsFound = true;
354 : }
355 : } else {
356 0 : ShowSevereError(state, format("{} = {}", state.dataIPShortCut->cCurrentModuleObject, thisHWBaseboardDesign.designName));
357 0 : ShowContinueError(state,
358 0 : format("Input for {} = {}",
359 0 : state.dataIPShortCut->cAlphaFieldNames(iHeatCAPMAlphaNum),
360 0 : state.dataIPShortCut->cAlphaArgs(iHeatCAPMAlphaNum)));
361 0 : ShowContinueError(
362 : state,
363 0 : format("Blank field not allowed for {}", state.dataIPShortCut->cNumericFieldNames(iHeatFracOfAutosizedCapacityNumericNum)));
364 0 : ErrorsFound = true;
365 : }
366 : }
367 :
368 11 : thisHWBaseboardDesign.Offset = state.dataIPShortCut->rNumericArgs(3);
369 : // Set default convergence tolerance
370 11 : if (thisHWBaseboardDesign.Offset <= 0.0) {
371 0 : ShowWarningError(state,
372 0 : format("{}{}=\"{}\", {} was less than the allowable minimum.",
373 : RoutineName,
374 : cCMO_BBRadiator_Water_Design,
375 0 : thisHWBaseboardDesign.designName,
376 0 : state.dataIPShortCut->cNumericFieldNames(3)));
377 0 : ShowContinueError(state, format("...reset to a default value=[{:.2R}].", MaxFraction));
378 0 : thisHWBaseboardDesign.Offset = 0.001;
379 : }
380 :
381 11 : thisHWBaseboardDesign.FracRadiant = state.dataIPShortCut->rNumericArgs(4);
382 11 : if (thisHWBaseboardDesign.FracRadiant < MinFraction) {
383 0 : ShowWarningError(state,
384 0 : format("{}{}=\"{}\", {} was lower than the allowable minimum.",
385 : RoutineName,
386 : cCMO_BBRadiator_Water,
387 0 : thisHWBaseboardDesign.designName,
388 0 : state.dataIPShortCut->cNumericFieldNames(4)));
389 0 : ShowContinueError(state, format("...reset to minimum value=[{:.2R}].", MinFraction));
390 0 : thisHWBaseboardDesign.FracRadiant = MinFraction;
391 : }
392 11 : if (thisHWBaseboardDesign.FracRadiant > MaxFraction) {
393 0 : ShowWarningError(state,
394 0 : format("{}{}=\"{}\", {} was higher than the allowable maximum.",
395 : RoutineName,
396 : cCMO_BBRadiator_Water,
397 0 : thisHWBaseboardDesign.designName,
398 0 : state.dataIPShortCut->cNumericFieldNames(4)));
399 0 : ShowContinueError(state, format("...reset to maximum value=[{:.2R}].", MaxFraction));
400 0 : thisHWBaseboardDesign.FracRadiant = MaxFraction;
401 : }
402 :
403 11 : thisHWBaseboardDesign.FracDistribPerson = state.dataIPShortCut->rNumericArgs(5);
404 11 : if (thisHWBaseboardDesign.FracDistribPerson < MinFraction) {
405 0 : ShowWarningError(state,
406 0 : format("{}{}=\"{}\", {} was lower than the allowable minimum.",
407 : RoutineName,
408 : cCMO_BBRadiator_Water,
409 0 : thisHWBaseboardDesign.designName,
410 0 : state.dataIPShortCut->cNumericFieldNames(5)));
411 0 : ShowContinueError(state, format("...reset to minimum value=[{:.3R}].", MinFraction));
412 0 : thisHWBaseboardDesign.FracDistribPerson = MinFraction;
413 : }
414 11 : if (thisHWBaseboardDesign.FracDistribPerson > MaxFraction) {
415 0 : ShowWarningError(state,
416 0 : format("{}{}=\"{}\", {} was higher than the allowable maximum.",
417 : RoutineName,
418 : cCMO_BBRadiator_Water,
419 0 : thisHWBaseboardDesign.designName,
420 0 : state.dataIPShortCut->cNumericFieldNames(5)));
421 0 : ShowContinueError(state, format("...reset to maximum value=[{:.3R}].", MaxFraction));
422 0 : thisHWBaseboardDesign.FracDistribPerson = MaxFraction;
423 : }
424 : }
425 :
426 : // Get the data from the user input related to baseboard heaters
427 24 : for (BaseboardNum = 1; BaseboardNum <= NumHWBaseboards; ++BaseboardNum) {
428 17 : auto &thisHWBaseboard = state.dataHWBaseboardRad->HWBaseboard(BaseboardNum);
429 17 : auto &HWBaseboardNumericFields = state.dataHWBaseboardRad->HWBaseboardNumericFields(BaseboardNum);
430 :
431 34 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
432 : cCMO_BBRadiator_Water,
433 : BaseboardNum,
434 17 : state.dataIPShortCut->cAlphaArgs,
435 : NumAlphas,
436 17 : state.dataIPShortCut->rNumericArgs,
437 : NumNumbers,
438 : IOStat,
439 17 : state.dataIPShortCut->lNumericFieldBlanks,
440 17 : state.dataIPShortCut->lAlphaFieldBlanks,
441 17 : state.dataIPShortCut->cAlphaFieldNames,
442 17 : state.dataIPShortCut->cNumericFieldNames);
443 :
444 17 : ErrorObjectHeader eoh{routineName, cCMO_BBRadiator_Water, state.dataIPShortCut->cAlphaArgs(1)};
445 :
446 17 : HWBaseboardNumericFields.FieldNames.allocate(NumNumbers);
447 17 : HWBaseboardNumericFields.FieldNames = state.dataIPShortCut->cNumericFieldNames;
448 :
449 : // ErrorsFound will be set to True if problem was found, left untouched otherwise
450 17 : GlobalNames::VerifyUniqueBaseboardName(
451 34 : state, cCMO_BBRadiator_Water, state.dataIPShortCut->cAlphaArgs(1), ErrorsFound, cCMO_BBRadiator_Water + " Name");
452 :
453 17 : thisHWBaseboard.Name = state.dataIPShortCut->cAlphaArgs(1); // Name of this baseboard
454 17 : thisHWBaseboard.EquipType = DataPlant::PlantEquipmentType::Baseboard_Rad_Conv_Water; //'ZoneHVAC:Baseboard:RadiantConvective:Water'
455 :
456 17 : thisHWBaseboard.designObjectName = state.dataIPShortCut->cAlphaArgs(2); // Name of the design object for this baseboard
457 17 : thisHWBaseboard.DesignObjectPtr = Util::FindItemInList(thisHWBaseboard.designObjectName, HWBaseboardDesignNames);
458 : HWBaseboardDesignData &HWBaseboardDesignDataObject =
459 17 : state.dataHWBaseboardRad->HWBaseboardDesignObject(thisHWBaseboard.DesignObjectPtr); // Contains the data for the design object
460 :
461 : // Get schedule
462 17 : if (state.dataIPShortCut->lAlphaFieldBlanks(3)) {
463 5 : thisHWBaseboard.availSched = Sched::GetScheduleAlwaysOn(state);
464 12 : } else if ((thisHWBaseboard.availSched = Sched::GetSchedule(state, state.dataIPShortCut->cAlphaArgs(3))) == nullptr) {
465 0 : ShowSevereItemNotFound(state, eoh, state.dataIPShortCut->cAlphaFieldNames(3), state.dataIPShortCut->cAlphaArgs(3));
466 0 : ErrorsFound = true;
467 : }
468 :
469 : // Get inlet node number
470 17 : thisHWBaseboard.WaterInletNode = GetOnlySingleNode(state,
471 17 : state.dataIPShortCut->cAlphaArgs(4),
472 : ErrorsFound,
473 : DataLoopNode::ConnectionObjectType::ZoneHVACBaseboardRadiantConvectiveWater,
474 17 : state.dataIPShortCut->cAlphaArgs(1),
475 : DataLoopNode::NodeFluidType::Water,
476 : DataLoopNode::ConnectionType::Inlet,
477 : NodeInputManager::CompFluidStream::Primary,
478 : DataLoopNode::ObjectIsNotParent);
479 :
480 : // Get outlet node number
481 34 : thisHWBaseboard.WaterOutletNode = GetOnlySingleNode(state,
482 17 : state.dataIPShortCut->cAlphaArgs(5),
483 : ErrorsFound,
484 : DataLoopNode::ConnectionObjectType::ZoneHVACBaseboardRadiantConvectiveWater,
485 17 : state.dataIPShortCut->cAlphaArgs(1),
486 : DataLoopNode::NodeFluidType::Water,
487 : DataLoopNode::ConnectionType::Outlet,
488 : NodeInputManager::CompFluidStream::Primary,
489 : DataLoopNode::ObjectIsNotParent);
490 34 : BranchNodeConnections::TestCompSet(state,
491 : cCMO_BBRadiator_Water,
492 17 : state.dataIPShortCut->cAlphaArgs(1),
493 17 : state.dataIPShortCut->cAlphaArgs(4),
494 17 : state.dataIPShortCut->cAlphaArgs(5),
495 : "Hot Water Nodes");
496 :
497 17 : thisHWBaseboard.WaterTempAvg = state.dataIPShortCut->rNumericArgs(1);
498 17 : if (thisHWBaseboard.WaterTempAvg > MaxWaterTempAvg + 0.001) {
499 0 : ShowWarningError(state,
500 0 : format("{}{}=\"{}\", {} was higher than the allowable maximum.",
501 : RoutineName,
502 : cCMO_BBRadiator_Water,
503 0 : state.dataIPShortCut->cAlphaArgs(1),
504 0 : state.dataIPShortCut->cNumericFieldNames(1)));
505 0 : ShowContinueError(state, format("...reset to maximum value=[{:.2R}].", MaxWaterTempAvg));
506 0 : thisHWBaseboard.WaterTempAvg = MaxWaterTempAvg;
507 17 : } else if (thisHWBaseboard.WaterTempAvg < MinWaterTempAvg - 0.001) {
508 0 : ShowWarningError(state,
509 0 : format("{}{}=\"{}\", {} was lower than the allowable minimum.",
510 : RoutineName,
511 : cCMO_BBRadiator_Water,
512 0 : state.dataIPShortCut->cAlphaArgs(1),
513 0 : state.dataIPShortCut->cNumericFieldNames(1)));
514 0 : ShowContinueError(state, format("...reset to minimum value=[{:.2R}].", MinWaterTempAvg));
515 0 : thisHWBaseboard.WaterTempAvg = MinWaterTempAvg;
516 : }
517 :
518 17 : thisHWBaseboard.WaterMassFlowRateStd = state.dataIPShortCut->rNumericArgs(2);
519 17 : if (thisHWBaseboard.WaterMassFlowRateStd < LowWaterMassFlowRate - 0.0001 ||
520 17 : thisHWBaseboard.WaterMassFlowRateStd > HighWaterMassFlowRate + 0.0001) {
521 0 : ShowWarningError(state,
522 0 : format("{}{}=\"{}\", {} is an invalid Standard Water mass flow rate.",
523 : RoutineName,
524 : cCMO_BBRadiator_Water,
525 0 : state.dataIPShortCut->cAlphaArgs(1),
526 0 : state.dataIPShortCut->cNumericFieldNames(2)));
527 0 : ShowContinueError(state, format("...reset to a default value=[{:.1R}].", WaterMassFlowDefault));
528 0 : thisHWBaseboard.WaterMassFlowRateStd = WaterMassFlowDefault;
529 : }
530 :
531 : // Determine HW radiant baseboard heating design capacity sizing method
532 17 : thisHWBaseboard.HeatingCapMethod = static_cast<int>(HWBaseboardDesignDataObject.HeatingCapMethod);
533 17 : if (thisHWBaseboard.HeatingCapMethod == DataSizing::HeatingDesignCapacity) {
534 17 : if (!state.dataIPShortCut->lNumericFieldBlanks(iHeatDesignCapacityNumericNum)) {
535 17 : thisHWBaseboard.ScaledHeatingCapacity = state.dataIPShortCut->rNumericArgs(iHeatDesignCapacityNumericNum);
536 17 : if (thisHWBaseboard.ScaledHeatingCapacity < 0.0 && thisHWBaseboard.ScaledHeatingCapacity != DataSizing::AutoSize) {
537 0 : ShowSevereError(state, format("{} = {}", state.dataIPShortCut->cCurrentModuleObject, thisHWBaseboard.Name));
538 0 : ShowContinueError(state,
539 0 : format("Illegal {} = {:.7T}",
540 0 : state.dataIPShortCut->cNumericFieldNames(iHeatDesignCapacityNumericNum),
541 0 : state.dataIPShortCut->rNumericArgs(iHeatDesignCapacityNumericNum)));
542 0 : ErrorsFound = true;
543 : }
544 : } else {
545 0 : ShowSevereError(state, format("{} = {}", state.dataIPShortCut->cCurrentModuleObject, thisHWBaseboard.Name));
546 0 : ShowContinueError(state,
547 0 : format("Input for {} = {}",
548 0 : state.dataIPShortCut->cAlphaFieldNames(iHeatCAPMAlphaNum),
549 0 : state.dataIPShortCut->cAlphaArgs(iHeatCAPMAlphaNum)));
550 0 : ShowContinueError(
551 0 : state, format("Blank field not allowed for {}", state.dataIPShortCut->cNumericFieldNames(iHeatDesignCapacityNumericNum)));
552 0 : ErrorsFound = true;
553 : }
554 0 : } else if (thisHWBaseboard.HeatingCapMethod == DataSizing::CapacityPerFloorArea) {
555 0 : thisHWBaseboard.ScaledHeatingCapacity = HWBaseboardDesignDataObject.ScaledHeatingCapacity;
556 :
557 0 : } else if (thisHWBaseboard.HeatingCapMethod == DataSizing::FractionOfAutosizedHeatingCapacity) {
558 0 : thisHWBaseboard.ScaledHeatingCapacity = HWBaseboardDesignDataObject.ScaledHeatingCapacity;
559 :
560 : } else {
561 0 : ShowSevereError(state, format("{} = {}", state.dataIPShortCut->cCurrentModuleObject, thisHWBaseboard.Name));
562 0 : ShowContinueError(state,
563 0 : format("Illegal {} = {}",
564 0 : state.dataIPShortCut->cAlphaFieldNames(iHeatCAPMAlphaNum),
565 0 : state.dataIPShortCut->cAlphaArgs(iHeatCAPMAlphaNum)));
566 0 : ErrorsFound = true;
567 : }
568 :
569 17 : thisHWBaseboard.WaterVolFlowRateMax = state.dataIPShortCut->rNumericArgs(4);
570 17 : if (std::abs(thisHWBaseboard.WaterVolFlowRateMax) <= MinWaterFlowRate) {
571 0 : ShowWarningError(state,
572 0 : format("{}{}=\"{}\", {} was less than the allowable minimum.",
573 : RoutineName,
574 : cCMO_BBRadiator_Water,
575 0 : state.dataIPShortCut->cAlphaArgs(1),
576 0 : state.dataIPShortCut->cNumericFieldNames(4)));
577 0 : ShowContinueError(state, format("...reset to minimum value=[{:.2R}].", MinWaterFlowRate));
578 0 : thisHWBaseboard.WaterVolFlowRateMax = MinWaterFlowRate;
579 17 : } else if (thisHWBaseboard.WaterVolFlowRateMax > MaxWaterFlowRate) {
580 0 : ShowWarningError(state,
581 0 : format("{}{}=\"{}\", {} was higher than the allowable maximum.",
582 : RoutineName,
583 : cCMO_BBRadiator_Water,
584 0 : state.dataIPShortCut->cAlphaArgs(1),
585 0 : state.dataIPShortCut->cNumericFieldNames(4)));
586 0 : ShowContinueError(state, format("...reset to maximum value=[{:.2R}].", MaxWaterFlowRate));
587 0 : thisHWBaseboard.WaterVolFlowRateMax = MaxWaterFlowRate;
588 : }
589 :
590 : // Remaining fraction is added to the zone as convective heat transfer
591 17 : if (HWBaseboardDesignDataObject.FracRadiant > MaxFraction) {
592 0 : ShowWarningError(state,
593 0 : format("{}{}=\"{}\", Fraction Radiant was higher than the allowable maximum.",
594 : RoutineName,
595 : cCMO_BBRadiator_Water,
596 0 : state.dataIPShortCut->cAlphaArgs(1)));
597 0 : HWBaseboardDesignDataObject.FracRadiant = MaxFraction;
598 0 : thisHWBaseboard.FracConvect = 0.0;
599 : } else {
600 17 : thisHWBaseboard.FracConvect = 1.0 - HWBaseboardDesignDataObject.FracRadiant;
601 : }
602 :
603 17 : thisHWBaseboard.TotSurfToDistrib = NumNumbers - 4;
604 : // IF (thisHWBaseboard%TotSurfToDistrib > MaxDistribSurfaces) THEN
605 : // CALL ShowWarningError(state, RoutineName//cCMO_BBRadiator_Water//'="'//TRIM(state.dataIPShortCut->cAlphaArgs(1))// &
606 : // '", the number of surface/radiant fraction groups entered was higher than the allowable maximum.')
607 : // CALL ShowContinueError(state, '...only the maximum value=['//TRIM(RoundSigDigits(MaxDistribSurfaces))// &
608 : // '] will be processed.')
609 : // thisHWBaseboard%TotSurfToDistrib = MaxDistribSurfaces
610 : // END IF
611 17 : if ((thisHWBaseboard.TotSurfToDistrib < MinDistribSurfaces) && (HWBaseboardDesignDataObject.FracRadiant > MinFraction)) {
612 0 : ShowSevereError(state,
613 0 : std::string{RoutineName} + cCMO_BBRadiator_Water + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
614 : "\", the number of surface/radiant fraction groups entered was less than the allowable minimum.");
615 0 : ShowContinueError(state, format("...the minimum that must be entered=[{}].", MinDistribSurfaces));
616 0 : ErrorsFound = true;
617 0 : thisHWBaseboard.TotSurfToDistrib = 0; // error
618 : }
619 :
620 17 : thisHWBaseboard.SurfacePtr.allocate(thisHWBaseboard.TotSurfToDistrib);
621 17 : thisHWBaseboard.SurfacePtr = 0;
622 17 : thisHWBaseboard.FracDistribToSurf.allocate(thisHWBaseboard.TotSurfToDistrib);
623 17 : thisHWBaseboard.FracDistribToSurf = 0.0;
624 :
625 17 : thisHWBaseboard.ZonePtr =
626 17 : DataZoneEquipment::GetZoneEquipControlledZoneNum(state, DataZoneEquipment::ZoneEquipType::BaseboardWater, thisHWBaseboard.Name);
627 :
628 17 : Real64 AllFracsSummed = HWBaseboardDesignDataObject.FracDistribPerson;
629 53 : for (SurfNum = 1; SurfNum <= thisHWBaseboard.TotSurfToDistrib; ++SurfNum) {
630 72 : thisHWBaseboard.SurfacePtr(SurfNum) =
631 36 : HeatBalanceIntRadExchange::GetRadiantSystemSurface(state,
632 : cCMO_BBRadiator_Water,
633 36 : thisHWBaseboard.Name,
634 : thisHWBaseboard.ZonePtr,
635 36 : state.dataIPShortCut->cAlphaArgs(SurfNum + 5),
636 : ErrorsFound);
637 36 : thisHWBaseboard.FracDistribToSurf(SurfNum) = state.dataIPShortCut->rNumericArgs(SurfNum + 4);
638 36 : if (thisHWBaseboard.FracDistribToSurf(SurfNum) > MaxFraction) {
639 0 : ShowWarningError(state,
640 0 : format("{}{}=\"{}\", {}was greater than the allowable maximum.",
641 : RoutineName,
642 : cCMO_BBRadiator_Water,
643 0 : state.dataIPShortCut->cAlphaArgs(1),
644 0 : state.dataIPShortCut->cNumericFieldNames(SurfNum + 4)));
645 0 : ShowContinueError(state, format("...reset to maximum value=[{:.2R}].", MaxFraction));
646 0 : thisHWBaseboard.TotSurfToDistrib = MaxFraction;
647 : }
648 36 : if (thisHWBaseboard.FracDistribToSurf(SurfNum) < MinFraction) {
649 0 : ShowWarningError(state,
650 0 : format("{}{}=\"{}\", {}was less than the allowable minimum.",
651 : RoutineName,
652 : cCMO_BBRadiator_Water,
653 0 : state.dataIPShortCut->cAlphaArgs(1),
654 0 : state.dataIPShortCut->cNumericFieldNames(SurfNum + 4)));
655 0 : ShowContinueError(state, format("...reset to maximum value=[{:.2R}].", MinFraction));
656 0 : thisHWBaseboard.TotSurfToDistrib = MinFraction;
657 : }
658 36 : if (thisHWBaseboard.SurfacePtr(SurfNum) != 0) {
659 36 : state.dataSurface->surfIntConv(thisHWBaseboard.SurfacePtr(SurfNum)).getsRadiantHeat = true;
660 36 : state.dataSurface->allGetsRadiantHeatSurfaceList.emplace_back(thisHWBaseboard.SurfacePtr(SurfNum));
661 : }
662 :
663 36 : AllFracsSummed += thisHWBaseboard.FracDistribToSurf(SurfNum);
664 : } // Surfaces
665 :
666 17 : if (AllFracsSummed > (MaxFraction + 0.01)) {
667 0 : ShowSevereError(state,
668 0 : format("{}{}=\"{}\", Summed radiant fractions for people + surface groups > 1.0",
669 : RoutineName,
670 : cCMO_BBRadiator_Water,
671 0 : state.dataIPShortCut->cAlphaArgs(1)));
672 0 : ErrorsFound = true;
673 : }
674 17 : if ((AllFracsSummed < (MaxFraction - 0.01)) &&
675 5 : (HWBaseboardDesignDataObject.FracRadiant >
676 : MinFraction)) { // User didn't distribute all of the | radiation warn that some will be lost
677 0 : ShowWarningError(state,
678 0 : format("{}{}=\"{}\", Summed radiant fractions for people + surface groups < 1.0",
679 : RoutineName,
680 : cCMO_BBRadiator_Water,
681 0 : state.dataIPShortCut->cAlphaArgs(1)));
682 0 : ShowContinueError(state, "The rest of the radiant energy delivered by the baseboard heater will be lost");
683 : }
684 : }
685 :
686 7 : if (ErrorsFound) {
687 0 : ShowFatalError(state, format("{}{}Errors found getting input. Program terminates.", RoutineName, cCMO_BBRadiator_Water));
688 : }
689 :
690 : // Setup Report variables for the Coils
691 24 : for (BaseboardNum = 1; BaseboardNum <= NumHWBaseboards; ++BaseboardNum) {
692 : // CurrentModuleObject='ZoneHVAC:Baseboard:RadiantConvective:Water'
693 17 : auto &thisHWBaseboard = state.dataHWBaseboardRad->HWBaseboard(BaseboardNum);
694 34 : SetupOutputVariable(state,
695 : "Baseboard Total Heating Rate",
696 : Constant::Units::W,
697 17 : thisHWBaseboard.TotPower,
698 : OutputProcessor::TimeStepType::System,
699 : OutputProcessor::StoreType::Average,
700 17 : thisHWBaseboard.Name);
701 :
702 34 : SetupOutputVariable(state,
703 : "Baseboard Convective Heating Rate",
704 : Constant::Units::W,
705 17 : thisHWBaseboard.ConvPower,
706 : OutputProcessor::TimeStepType::System,
707 : OutputProcessor::StoreType::Average,
708 17 : thisHWBaseboard.Name);
709 34 : SetupOutputVariable(state,
710 : "Baseboard Radiant Heating Rate",
711 : Constant::Units::W,
712 17 : thisHWBaseboard.RadPower,
713 : OutputProcessor::TimeStepType::System,
714 : OutputProcessor::StoreType::Average,
715 17 : thisHWBaseboard.Name);
716 34 : SetupOutputVariable(state,
717 : "Baseboard Total Heating Energy",
718 : Constant::Units::J,
719 17 : thisHWBaseboard.TotEnergy,
720 : OutputProcessor::TimeStepType::System,
721 : OutputProcessor::StoreType::Sum,
722 17 : thisHWBaseboard.Name,
723 : Constant::eResource::EnergyTransfer,
724 : OutputProcessor::Group::HVAC,
725 : OutputProcessor::EndUseCat::Baseboard);
726 :
727 34 : SetupOutputVariable(state,
728 : "Baseboard Convective Heating Energy",
729 : Constant::Units::J,
730 17 : thisHWBaseboard.ConvEnergy,
731 : OutputProcessor::TimeStepType::System,
732 : OutputProcessor::StoreType::Sum,
733 17 : thisHWBaseboard.Name);
734 34 : SetupOutputVariable(state,
735 : "Baseboard Radiant Heating Energy",
736 : Constant::Units::J,
737 17 : thisHWBaseboard.RadEnergy,
738 : OutputProcessor::TimeStepType::System,
739 : OutputProcessor::StoreType::Sum,
740 17 : thisHWBaseboard.Name);
741 34 : SetupOutputVariable(state,
742 : "Baseboard Hot Water Energy",
743 : Constant::Units::J,
744 17 : thisHWBaseboard.Energy,
745 : OutputProcessor::TimeStepType::System,
746 : OutputProcessor::StoreType::Sum,
747 17 : thisHWBaseboard.Name,
748 : Constant::eResource::PlantLoopHeatingDemand,
749 : OutputProcessor::Group::HVAC,
750 : OutputProcessor::EndUseCat::Baseboard);
751 34 : SetupOutputVariable(state,
752 : "Baseboard Hot Water Mass Flow Rate",
753 : Constant::Units::kg_s,
754 17 : thisHWBaseboard.WaterMassFlowRate,
755 : OutputProcessor::TimeStepType::System,
756 : OutputProcessor::StoreType::Average,
757 17 : thisHWBaseboard.Name);
758 34 : SetupOutputVariable(state,
759 : "Baseboard Air Mass Flow Rate",
760 : Constant::Units::kg_s,
761 17 : thisHWBaseboard.AirMassFlowRate,
762 : OutputProcessor::TimeStepType::System,
763 : OutputProcessor::StoreType::Average,
764 17 : thisHWBaseboard.Name);
765 34 : SetupOutputVariable(state,
766 : "Baseboard Air Inlet Temperature",
767 : Constant::Units::C,
768 17 : thisHWBaseboard.AirInletTemp,
769 : OutputProcessor::TimeStepType::System,
770 : OutputProcessor::StoreType::Average,
771 17 : thisHWBaseboard.Name);
772 34 : SetupOutputVariable(state,
773 : "Baseboard Air Outlet Temperature",
774 : Constant::Units::C,
775 17 : thisHWBaseboard.AirOutletTemp,
776 : OutputProcessor::TimeStepType::System,
777 : OutputProcessor::StoreType::Average,
778 17 : thisHWBaseboard.Name);
779 34 : SetupOutputVariable(state,
780 : "Baseboard Water Inlet Temperature",
781 : Constant::Units::C,
782 17 : thisHWBaseboard.WaterInletTemp,
783 : OutputProcessor::TimeStepType::System,
784 : OutputProcessor::StoreType::Average,
785 17 : thisHWBaseboard.Name);
786 34 : SetupOutputVariable(state,
787 : "Baseboard Water Outlet Temperature",
788 : Constant::Units::C,
789 17 : thisHWBaseboard.WaterOutletTemp,
790 : OutputProcessor::TimeStepType::System,
791 : OutputProcessor::StoreType::Average,
792 17 : thisHWBaseboard.Name);
793 : }
794 7 : }
795 :
796 89083 : void InitHWBaseboard(EnergyPlusData &state, int const BaseboardNum, int const ControlledZoneNum, bool const FirstHVACIteration)
797 : {
798 :
799 : // SUBROUTINE INFORMATION:
800 : // AUTHOR Russ Taylor
801 : // Rick Strand
802 : // DATE WRITTEN Nov 1997
803 : // Feb 2001
804 : // MODIFIED Aug 2007 Daeho Kang (Add radiant component)
805 : // Sept 2010 Brent Griffith (plant interactions)
806 :
807 : // PURPOSE OF THIS SUBROUTINE:
808 : // This subroutine initializes the baseboard units, and determines the UA values during simulation.
809 :
810 : // METHODOLOGY EMPLOYED:
811 : // The initialization subroutines both in high temperature radiant radiator
812 : // and convective only baseboard radiator are combined and modified. In addition,
813 : // an UA value calculation by LMTD method is added.
814 : // The heater is assumed to be crossflow with both fluids unmixed.
815 :
816 : // REFERENCES:
817 : // 1. Incropera and DeWitt, Fundamentals of Heat and Mass Transfer
818 : // Chapter 11.3, p. 510, eq. 11.15 and 11.17
819 : // 2. I=B=R Ratings for Baseboards, Baseboard Radiation, Finned Tube (Commercial) Radiation,
820 : // and Indirect Fired Water Heaters, January 2007 Edition
821 :
822 89083 : Real64 constexpr Constant(0.0062); // Constant of linear equation for air mass flow rate
823 89083 : Real64 constexpr Coeff(0.0000275); // Correlation coefficient to capacity
824 : static constexpr std::string_view RoutineName("BaseboardRadiatorWater:InitHWBaseboard");
825 :
826 : int WaterInletNode;
827 : Real64 rho; // local fluid density
828 : Real64 Cp; // local fluid specific heat
829 :
830 89083 : int NumHWBaseboards = state.dataHWBaseboardRad->NumHWBaseboards;
831 89083 : auto &HWBaseboard = state.dataHWBaseboardRad->HWBaseboard(BaseboardNum);
832 :
833 : // Do the one time initializations
834 89083 : if (state.dataHWBaseboardRad->MyOneTimeFlag) {
835 :
836 : // Initialize the environment and sizing flags
837 7 : state.dataHWBaseboardRad->MyEnvrnFlag.dimension(NumHWBaseboards, true);
838 7 : state.dataHWBaseboardRad->MySizeFlag.dimension(NumHWBaseboards, true);
839 7 : state.dataHWBaseboardRad->SetLoopIndexFlag.dimension(NumHWBaseboards, true);
840 7 : state.dataHWBaseboardRad->MyOneTimeFlag = false;
841 :
842 24 : for (auto &hWBB : state.dataHWBaseboardRad->HWBaseboard) {
843 : // Air mass flow rate is obtained from the following linear equation (reset if autosize is used)
844 : // m_dot = 0.0062 + 2.75e-05*q
845 17 : hWBB.ZeroBBSourceSumHATsurf = 0.0;
846 17 : hWBB.QBBRadSource = 0.0;
847 17 : hWBB.QBBRadSrcAvg = 0.0;
848 17 : hWBB.LastQBBRadSrc = 0.0;
849 17 : hWBB.LastSysTimeElapsed = 0.0;
850 17 : hWBB.LastTimeStepSys = 0.0;
851 17 : hWBB.AirMassFlowRateStd = Constant + Coeff * hWBB.RatedCapacity;
852 : }
853 : }
854 :
855 89083 : if (state.dataHWBaseboardRad->SetLoopIndexFlag(BaseboardNum)) {
856 17 : if (allocated(state.dataPlnt->PlantLoop)) {
857 17 : bool errFlag = false;
858 17 : PlantUtilities::ScanPlantLoopsForObject(state, HWBaseboard.Name, HWBaseboard.EquipType, HWBaseboard.plantLoc, errFlag, _, _, _, _, _);
859 17 : if (errFlag) {
860 0 : ShowFatalError(state, "InitHWBaseboard: Program terminated for previous conditions.");
861 : }
862 17 : state.dataHWBaseboardRad->SetLoopIndexFlag(BaseboardNum) = false;
863 : }
864 : }
865 :
866 89100 : if (!state.dataGlobal->SysSizingCalc && state.dataHWBaseboardRad->MySizeFlag(BaseboardNum) &&
867 17 : !state.dataHWBaseboardRad->SetLoopIndexFlag(BaseboardNum)) {
868 : // For each coil, do the sizing once
869 17 : SizeHWBaseboard(state, BaseboardNum);
870 17 : state.dataHWBaseboardRad->MySizeFlag(BaseboardNum) = false;
871 : }
872 :
873 : // Do the Begin Environment initializations
874 89083 : if (state.dataGlobal->BeginEnvrnFlag && state.dataHWBaseboardRad->MyEnvrnFlag(BaseboardNum)) {
875 : // Initialize
876 102 : WaterInletNode = HWBaseboard.WaterInletNode;
877 :
878 102 : rho = state.dataPlnt->PlantLoop(HWBaseboard.plantLoc.loopNum).glycol->getDensity(state, Constant::HWInitConvTemp, RoutineName);
879 :
880 102 : HWBaseboard.WaterMassFlowRateMax = rho * HWBaseboard.WaterVolFlowRateMax;
881 :
882 102 : PlantUtilities::InitComponentNodes(state, 0.0, HWBaseboard.WaterMassFlowRateMax, HWBaseboard.WaterInletNode, HWBaseboard.WaterOutletNode);
883 :
884 102 : state.dataLoopNodes->Node(WaterInletNode).Temp = 60.0;
885 :
886 102 : Cp = state.dataPlnt->PlantLoop(HWBaseboard.plantLoc.loopNum)
887 102 : .glycol->getSpecificHeat(state, state.dataLoopNodes->Node(WaterInletNode).Temp, RoutineName);
888 :
889 102 : state.dataLoopNodes->Node(WaterInletNode).Enthalpy = Cp * state.dataLoopNodes->Node(WaterInletNode).Temp;
890 102 : state.dataLoopNodes->Node(WaterInletNode).Quality = 0.0;
891 102 : state.dataLoopNodes->Node(WaterInletNode).Press = 0.0;
892 102 : state.dataLoopNodes->Node(WaterInletNode).HumRat = 0.0;
893 :
894 102 : HWBaseboard.ZeroBBSourceSumHATsurf = 0.0;
895 102 : HWBaseboard.QBBRadSource = 0.0;
896 102 : HWBaseboard.QBBRadSrcAvg = 0.0;
897 102 : HWBaseboard.LastQBBRadSrc = 0.0;
898 102 : HWBaseboard.LastSysTimeElapsed = 0.0;
899 102 : HWBaseboard.LastTimeStepSys = 0.0;
900 :
901 102 : state.dataHWBaseboardRad->MyEnvrnFlag(BaseboardNum) = false;
902 : }
903 :
904 89083 : if (!state.dataGlobal->BeginEnvrnFlag) {
905 88549 : state.dataHWBaseboardRad->MyEnvrnFlag(BaseboardNum) = true;
906 : }
907 :
908 89083 : if (state.dataGlobal->BeginTimeStepFlag && FirstHVACIteration) {
909 31094 : int ZoneNum = HWBaseboard.ZonePtr;
910 31094 : HWBaseboard.ZeroBBSourceSumHATsurf = state.dataHeatBal->Zone(ZoneNum).sumHATsurf(state);
911 31094 : HWBaseboard.QBBRadSrcAvg = 0.0;
912 31094 : HWBaseboard.LastQBBRadSrc = 0.0;
913 31094 : HWBaseboard.LastSysTimeElapsed = 0.0;
914 31094 : HWBaseboard.LastTimeStepSys = 0.0;
915 : }
916 :
917 : // Do the every time step initializations
918 89083 : WaterInletNode = HWBaseboard.WaterInletNode;
919 89083 : int ZoneNode = state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).ZoneNode;
920 89083 : HWBaseboard.WaterMassFlowRate = state.dataLoopNodes->Node(WaterInletNode).MassFlowRate;
921 89083 : HWBaseboard.WaterInletTemp = state.dataLoopNodes->Node(WaterInletNode).Temp;
922 89083 : HWBaseboard.WaterInletEnthalpy = state.dataLoopNodes->Node(WaterInletNode).Enthalpy;
923 89083 : HWBaseboard.AirInletTemp = state.dataLoopNodes->Node(ZoneNode).Temp;
924 89083 : HWBaseboard.AirInletHumRat = state.dataLoopNodes->Node(ZoneNode).HumRat;
925 :
926 89083 : HWBaseboard.TotPower = 0.0;
927 89083 : HWBaseboard.Power = 0.0;
928 89083 : HWBaseboard.ConvPower = 0.0;
929 89083 : HWBaseboard.RadPower = 0.0;
930 89083 : HWBaseboard.TotEnergy = 0.0;
931 89083 : HWBaseboard.Energy = 0.0;
932 89083 : HWBaseboard.ConvEnergy = 0.0;
933 89083 : HWBaseboard.RadEnergy = 0.0;
934 89083 : }
935 :
936 17 : void SizeHWBaseboard(EnergyPlusData &state, int const BaseboardNum)
937 : {
938 :
939 : // SUBROUTINE INFORMATION:
940 : // AUTHOR Fred Buhl
941 : // DATE WRITTEN February 2002
942 : // MODIFIED August 2009 Daeho Kang (Add UA autosizing by LMTD)
943 : // Aug 2013 Daeho Kang, add component sizing table entries
944 : // July 2014, B.Nigusse, added scalable sizing
945 :
946 : // PURPOSE OF THIS SUBROUTINE:
947 : // This subroutine is for sizing hot water baseboard components
948 :
949 : // METHODOLOGY EMPLOYED:
950 : // Obtains flow rates from the zone sizing arrays and plant sizing data.
951 :
952 : // SUBROUTINE PARAMETER DEFINITIONS:
953 17 : Real64 constexpr AirInletTempStd(18.0); // I=B=R rating document
954 17 : Real64 constexpr CPAirStd(1005.0); // Average specific heat of air at between 25C and 40C in J/kg-k
955 17 : Real64 constexpr Constant(0.0062); // Constant of linear equation for air mass flow rate
956 17 : Real64 constexpr Coeff(0.0000275); // Correlation coefficient to capacity
957 : static constexpr std::string_view RoutineName("SizeHWBaseboard");
958 : static constexpr std::string_view RoutineNameFull("BaseboardRadiatorWater:SizeHWBaseboard");
959 :
960 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
961 : Real64 WaterInletTempStd;
962 : Real64 WaterOutletTempStd;
963 : Real64 AirOutletTempStd;
964 : Real64 DeltaT1;
965 : Real64 DeltaT2;
966 : Real64 LMTD;
967 : Real64 AirMassFlowRate;
968 : Real64 WaterMassFlowRateStd;
969 : Real64 rho; // local fluid density
970 : Real64 Cp; // local fluid specific heat
971 : Real64 TempSize; // autosized value of coil input field
972 :
973 17 : int PltSizHeatNum = 0;
974 17 : Real64 DesCoilLoad = 0.0;
975 17 : bool ErrorsFound = false;
976 17 : Real64 WaterVolFlowRateMaxDes = 0.0;
977 17 : Real64 WaterVolFlowRateMaxUser = 0.0;
978 17 : Real64 RatedCapacityDes = 0.0;
979 17 : state.dataSize->DataScalableCapSizingON = false;
980 :
981 17 : auto &hWBaseboard = state.dataHWBaseboardRad->HWBaseboard(BaseboardNum);
982 17 : if (state.dataSize->CurZoneEqNum > 0) {
983 17 : auto &zoneEqSizing = state.dataSize->ZoneEqSizing(state.dataSize->CurZoneEqNum);
984 :
985 17 : std::string CompType = cCMO_BBRadiator_Water;
986 17 : std::string CompName = hWBaseboard.Name;
987 17 : state.dataSize->DataHeatSizeRatio = 1.0;
988 17 : state.dataSize->DataFracOfAutosizedHeatingCapacity = 1.0;
989 17 : state.dataSize->DataZoneNumber = hWBaseboard.ZonePtr;
990 17 : int SizingMethod = HVAC::HeatingCapacitySizing;
991 17 : int FieldNum = 3; // IDD numeric field number where input field description is found
992 17 : std::string SizingString = state.dataHWBaseboardRad->HWBaseboardNumericFields(BaseboardNum).FieldNames(FieldNum) + " [W]";
993 17 : int CapSizingMethod = hWBaseboard.HeatingCapMethod;
994 17 : zoneEqSizing.SizingMethod(SizingMethod) = CapSizingMethod;
995 17 : if (CapSizingMethod == DataSizing::HeatingDesignCapacity || CapSizingMethod == DataSizing::CapacityPerFloorArea ||
996 : CapSizingMethod == DataSizing::FractionOfAutosizedHeatingCapacity) {
997 17 : if (CapSizingMethod == DataSizing::HeatingDesignCapacity) {
998 17 : if (hWBaseboard.ScaledHeatingCapacity == DataSizing::AutoSize) {
999 17 : CheckZoneSizing(state, CompType, CompName);
1000 17 : zoneEqSizing.HeatingCapacity = true;
1001 17 : zoneEqSizing.DesHeatingLoad = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).NonAirSysDesHeatLoad;
1002 : }
1003 17 : TempSize = hWBaseboard.ScaledHeatingCapacity;
1004 :
1005 0 : } else if (CapSizingMethod == DataSizing::CapacityPerFloorArea) {
1006 0 : zoneEqSizing.HeatingCapacity = true;
1007 0 : zoneEqSizing.DesHeatingLoad =
1008 0 : hWBaseboard.ScaledHeatingCapacity * state.dataHeatBal->Zone(state.dataSize->DataZoneNumber).FloorArea;
1009 0 : TempSize = zoneEqSizing.DesHeatingLoad;
1010 0 : state.dataSize->DataScalableCapSizingON = true;
1011 0 : } else if (CapSizingMethod == DataSizing::FractionOfAutosizedHeatingCapacity) {
1012 0 : CheckZoneSizing(state, CompType, CompName);
1013 0 : zoneEqSizing.HeatingCapacity = true;
1014 0 : state.dataSize->DataFracOfAutosizedHeatingCapacity = hWBaseboard.ScaledHeatingCapacity;
1015 0 : zoneEqSizing.DesHeatingLoad = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).NonAirSysDesHeatLoad;
1016 0 : TempSize = DataSizing::AutoSize;
1017 0 : state.dataSize->DataScalableCapSizingON = true;
1018 : } else {
1019 0 : TempSize = hWBaseboard.ScaledHeatingCapacity;
1020 : }
1021 17 : bool PrintFlag = false;
1022 17 : bool errorsFound = false;
1023 17 : HeatingCapacitySizer sizerHeatingCapacity;
1024 17 : sizerHeatingCapacity.overrideSizingString(SizingString);
1025 17 : sizerHeatingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
1026 17 : TempSize = sizerHeatingCapacity.size(state, TempSize, errorsFound);
1027 17 : if (hWBaseboard.ScaledHeatingCapacity == DataSizing::AutoSize) {
1028 17 : hWBaseboard.RatedCapacity = DataSizing::AutoSize;
1029 : } else {
1030 0 : hWBaseboard.RatedCapacity = TempSize;
1031 : }
1032 17 : RatedCapacityDes = TempSize;
1033 17 : state.dataSize->DataScalableCapSizingON = false;
1034 17 : }
1035 17 : }
1036 :
1037 : // find the appropriate heating Plant Sizing object
1038 17 : PltSizHeatNum = state.dataPlnt->PlantLoop(hWBaseboard.plantLoc.loopNum).PlantSizNum;
1039 :
1040 17 : if (PltSizHeatNum > 0) {
1041 17 : if (state.dataSize->CurZoneEqNum > 0) {
1042 17 : bool FlowAutoSize = false;
1043 :
1044 17 : if (hWBaseboard.WaterVolFlowRateMax == DataSizing::AutoSize) {
1045 17 : FlowAutoSize = true;
1046 : }
1047 17 : if (!FlowAutoSize && !state.dataSize->ZoneSizingRunDone) { // Simulation continue
1048 0 : if (hWBaseboard.WaterVolFlowRateMax > 0.0) {
1049 0 : BaseSizer::reportSizerOutput(state,
1050 : cCMO_BBRadiator_Water,
1051 : hWBaseboard.Name,
1052 : "User-Specified Maximum Water Flow Rate [m3/s]",
1053 : hWBaseboard.WaterVolFlowRateMax);
1054 : }
1055 : } else {
1056 17 : CheckZoneSizing(state, cCMO_BBRadiator_Water, hWBaseboard.Name);
1057 17 : DesCoilLoad = RatedCapacityDes;
1058 17 : if (DesCoilLoad >= HVAC::SmallLoad) {
1059 17 : Cp = state.dataPlnt->PlantLoop(hWBaseboard.plantLoc.loopNum)
1060 17 : .glycol->getSpecificHeat(state, Constant::HWInitConvTemp, RoutineName);
1061 : rho =
1062 17 : state.dataPlnt->PlantLoop(hWBaseboard.plantLoc.loopNum).glycol->getDensity(state, Constant::HWInitConvTemp, RoutineName);
1063 17 : WaterVolFlowRateMaxDes = DesCoilLoad / (state.dataSize->PlantSizData(PltSizHeatNum).DeltaT * Cp * rho);
1064 : } else {
1065 0 : WaterVolFlowRateMaxDes = 0.0;
1066 : }
1067 :
1068 17 : if (FlowAutoSize) {
1069 17 : hWBaseboard.WaterVolFlowRateMax = WaterVolFlowRateMaxDes;
1070 17 : BaseSizer::reportSizerOutput(
1071 : state, cCMO_BBRadiator_Water, hWBaseboard.Name, "Design Size Maximum Water Flow Rate [m3/s]", WaterVolFlowRateMaxDes);
1072 : } else { // Hard-sized with sizing data
1073 0 : if (hWBaseboard.WaterVolFlowRateMax > 0.0 && WaterVolFlowRateMaxDes > 0.0) {
1074 0 : WaterVolFlowRateMaxUser = hWBaseboard.WaterVolFlowRateMax;
1075 0 : BaseSizer::reportSizerOutput(state,
1076 : cCMO_BBRadiator_Water,
1077 : hWBaseboard.Name,
1078 : "Design Size Maximum Water Flow Rate [m3/s]",
1079 : WaterVolFlowRateMaxDes,
1080 : "User-Specified Maximum Water Flow Rate [m3/s]",
1081 : WaterVolFlowRateMaxUser);
1082 0 : if (state.dataGlobal->DisplayExtraWarnings) {
1083 0 : if ((std::abs(WaterVolFlowRateMaxDes - WaterVolFlowRateMaxUser) / WaterVolFlowRateMaxUser) >
1084 0 : state.dataSize->AutoVsHardSizingThreshold) {
1085 0 : ShowMessage(state,
1086 0 : format("SizeHWBaseboard: Potential issue with equipment sizing for "
1087 : "ZoneHVAC:Baseboard:RadiantConvective:Water=\"{}\".",
1088 0 : hWBaseboard.Name));
1089 0 : ShowContinueError(state,
1090 0 : format("User-Specified Maximum Water Flow Rate of {:.5R} [m3/s]", WaterVolFlowRateMaxUser));
1091 0 : ShowContinueError(
1092 0 : state, format("differs from Design Size Maximum Water Flow Rate of {:.5R} [m3/s]", WaterVolFlowRateMaxDes));
1093 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
1094 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
1095 : }
1096 : }
1097 : }
1098 : }
1099 : }
1100 17 : if (hWBaseboard.WaterTempAvg > 0.0 && hWBaseboard.WaterMassFlowRateStd > 0.0 && hWBaseboard.RatedCapacity > 0.0) {
1101 0 : DesCoilLoad = hWBaseboard.RatedCapacity;
1102 0 : WaterMassFlowRateStd = hWBaseboard.WaterMassFlowRateStd;
1103 17 : } else if (hWBaseboard.RatedCapacity == DataSizing::AutoSize || hWBaseboard.RatedCapacity == 0.0) {
1104 17 : DesCoilLoad = RatedCapacityDes;
1105 : rho =
1106 17 : state.dataPlnt->PlantLoop(hWBaseboard.plantLoc.loopNum).glycol->getDensity(state, Constant::HWInitConvTemp, RoutineNameFull);
1107 17 : WaterMassFlowRateStd = hWBaseboard.WaterVolFlowRateMax * rho;
1108 : }
1109 17 : if (DesCoilLoad >= HVAC::SmallLoad) {
1110 : // Calculate UA value
1111 : // Air mass flow rate is obtained from the following linear equation
1112 : // m_dot = 0.0062 + 2.75e-05*q
1113 17 : AirMassFlowRate = Constant + Coeff * DesCoilLoad;
1114 : Cp =
1115 17 : state.dataPlnt->PlantLoop(hWBaseboard.plantLoc.loopNum).glycol->getSpecificHeat(state, hWBaseboard.WaterTempAvg, RoutineName);
1116 17 : WaterInletTempStd = (DesCoilLoad / (2.0 * WaterMassFlowRateStd * Cp)) + hWBaseboard.WaterTempAvg;
1117 17 : WaterOutletTempStd = std::abs((2.0 * hWBaseboard.WaterTempAvg) - WaterInletTempStd);
1118 17 : AirOutletTempStd = (DesCoilLoad / (AirMassFlowRate * CPAirStd)) + AirInletTempStd;
1119 17 : hWBaseboard.AirMassFlowRateStd = AirMassFlowRate;
1120 : // Check Ta,out < Tw,in
1121 17 : if (AirOutletTempStd >= WaterInletTempStd) {
1122 0 : ShowSevereError(state, format("SizeHWBaseboard: ZoneHVAC:Baseboard:RadiantConvective:Water=\"{}\".", hWBaseboard.Name));
1123 0 : ShowContinueError(state, "...Air Outlet temperature must be below the Water Inlet temperature");
1124 0 : ShowContinueError(
1125 : state,
1126 0 : format("...Air Outlet Temperature=[{:.2R}], Water Inlet Temperature=[{:.2R}].", AirOutletTempStd, WaterInletTempStd));
1127 0 : AirOutletTempStd = WaterInletTempStd - 0.01;
1128 0 : ShowContinueError(state, format("...Air Outlet Temperature set to [{:.2R}].", AirOutletTempStd));
1129 : }
1130 : // Check Tw,out < Ta,in
1131 17 : if (AirInletTempStd >= WaterOutletTempStd) {
1132 0 : ShowSevereError(state, format("SizeHWBaseboard: ZoneHVAC:Baseboard:RadiantConvective:Water=\"{}\".", hWBaseboard.Name));
1133 0 : ShowContinueError(state, "...Water Outlet temperature must be below the Air Inlet temperature");
1134 0 : ShowContinueError(
1135 : state,
1136 0 : format("...Air Inlet Temperature=[{:.2R}], Water Outlet Temperature=[{:.2R}].", AirInletTempStd, WaterOutletTempStd));
1137 0 : WaterOutletTempStd = AirInletTempStd + 0.01;
1138 0 : ShowContinueError(state, format("...Water Outlet Temperature set to [{:.2R}].", WaterOutletTempStd));
1139 : }
1140 : // LMTD calculation
1141 17 : DeltaT1 = WaterInletTempStd - AirOutletTempStd;
1142 17 : DeltaT2 = WaterOutletTempStd - AirInletTempStd;
1143 17 : LMTD = (DeltaT1 - DeltaT2) / (std::log(DeltaT1 / DeltaT2));
1144 17 : hWBaseboard.UA = DesCoilLoad / LMTD;
1145 : } else {
1146 0 : hWBaseboard.UA = 0.0;
1147 : }
1148 : // Report an UA value
1149 17 : BaseSizer::reportSizerOutput(state, cCMO_BBRadiator_Water, hWBaseboard.Name, "U-Factor times Area [W/C]", hWBaseboard.UA);
1150 : }
1151 : } else {
1152 : // if there is no heating Sizing:Plant object and autosizing was requested, issue an error message
1153 0 : if (hWBaseboard.WaterVolFlowRateMax == DataSizing::AutoSize || hWBaseboard.RatedCapacity == DataSizing::AutoSize ||
1154 0 : hWBaseboard.RatedCapacity == 0.0) {
1155 0 : ShowSevereError(state, "Autosizing of hot water baseboard requires a heating loop Sizing:Plant object");
1156 0 : ShowContinueError(state, format("Occurs in Hot Water Baseboard Heater={}", hWBaseboard.Name));
1157 0 : ErrorsFound = true;
1158 : }
1159 : // calculate UA from rated capacities
1160 0 : hWBaseboard.RatedCapacity = RatedCapacityDes;
1161 0 : DesCoilLoad = RatedCapacityDes;
1162 :
1163 0 : if (DesCoilLoad >= HVAC::SmallLoad) {
1164 0 : WaterMassFlowRateStd = hWBaseboard.WaterMassFlowRateStd;
1165 : // m_dot = 0.0062 + 2.75e-05*q
1166 0 : AirMassFlowRate = Constant + Coeff * DesCoilLoad;
1167 0 : Cp = state.dataPlnt->PlantLoop(hWBaseboard.plantLoc.loopNum).glycol->getSpecificHeat(state, hWBaseboard.WaterTempAvg, RoutineName);
1168 0 : WaterInletTempStd = (DesCoilLoad / (2.0 * WaterMassFlowRateStd * Cp)) + hWBaseboard.WaterTempAvg;
1169 0 : WaterOutletTempStd = std::abs((2.0 * hWBaseboard.WaterTempAvg) - WaterInletTempStd);
1170 0 : AirOutletTempStd = (DesCoilLoad / (AirMassFlowRate * CPAirStd)) + AirInletTempStd;
1171 0 : hWBaseboard.AirMassFlowRateStd = AirMassFlowRate;
1172 :
1173 : // Check Ta,out < Tw,in
1174 0 : if (AirOutletTempStd >= WaterInletTempStd) {
1175 0 : ShowSevereError(state, format("SizeHWBaseboard: ZoneHVAC:Baseboard:RadiantConvective:Water=\"{}\".", hWBaseboard.Name));
1176 0 : ShowContinueError(state, "...Air Outlet temperature must be below the Water Inlet temperature");
1177 0 : ShowContinueError(
1178 0 : state, format("...Air Outlet Temperature=[{:.2R}], Water Inlet Temperature=[{:.2R}].", AirOutletTempStd, WaterInletTempStd));
1179 0 : AirOutletTempStd = WaterInletTempStd - 0.01;
1180 0 : ShowContinueError(state, format("...Air Outlet Temperature set to [{:.2R}].", AirOutletTempStd));
1181 : }
1182 : // Check Tw,out < Ta,in
1183 0 : if (AirInletTempStd >= WaterOutletTempStd) {
1184 0 : ShowSevereError(state, format("SizeHWBaseboard: ZoneHVAC:Baseboard:RadiantConvective:Water=\"{}\".", hWBaseboard.Name));
1185 0 : ShowContinueError(state, "...Water Outlet temperature must be below the Air Inlet temperature");
1186 0 : ShowContinueError(
1187 0 : state, format("...Air Inlet Temperature=[{:.2R}], Water Outlet Temperature=[{:.2R}].", AirInletTempStd, WaterOutletTempStd));
1188 0 : WaterOutletTempStd = AirInletTempStd + 0.01;
1189 0 : ShowContinueError(state, format("...Water Outlet Temperature set to [{:.2R}].", WaterOutletTempStd));
1190 : }
1191 : // LMTD calculation
1192 0 : DeltaT1 = WaterInletTempStd - AirOutletTempStd;
1193 0 : DeltaT2 = WaterOutletTempStd - AirInletTempStd;
1194 0 : LMTD = (DeltaT1 - DeltaT2) / (std::log(DeltaT1 / DeltaT2));
1195 0 : hWBaseboard.UA = DesCoilLoad / LMTD;
1196 : } else {
1197 0 : hWBaseboard.UA = 0.0;
1198 : }
1199 : // Report an UA value
1200 0 : BaseSizer::reportSizerOutput(state, cCMO_BBRadiator_Water, hWBaseboard.Name, "U-Factor times Area [W/C]", hWBaseboard.UA);
1201 : }
1202 : // save the design water flow rate for use by the water loop sizing algorithms
1203 17 : PlantUtilities::RegisterPlantCompDesignFlow(state, hWBaseboard.WaterInletNode, hWBaseboard.WaterVolFlowRateMax);
1204 :
1205 17 : if (ErrorsFound) {
1206 0 : ShowFatalError(state, "Preceding sizing errors cause program termination");
1207 : }
1208 17 : }
1209 :
1210 159997 : void CalcHWBaseboard(EnergyPlusData &state, int &BaseboardNum, Real64 &LoadMet)
1211 : {
1212 : // SUBROUTINE INFORMATION:
1213 : // AUTHOR Russ Taylor
1214 : // DATE WRITTEN Nov 1997
1215 : // MODIFIED May 2000 Fred Buhl
1216 : // Aug 2007 Daeho Kang (Add the calculation of radiant heat source)
1217 : // Sep 2011 LKL/BG - resimulate only zones needing it for Radiant systems
1218 :
1219 : // PURPOSE OF THIS SUBROUTINE:
1220 : // This subroutine calculates both the convective and radiant heat transfer rate
1221 : // in a hot water baseboard heater. The heater is assumed to be crossflow with
1222 : // both fluids unmixed. The air flow is buoyancy driven and a constant airflow
1223 : // and a constant airflow velocity of 0.5m/s is assumed.
1224 :
1225 : // REFERENCES:
1226 : // Incropera and DeWitt, Fundamentals of Heat and Mass Transfer
1227 : // Chapter 11.4, p. 523, eq. 11.33
1228 :
1229 : // SUBROUTINE PARAMETER DEFINITIONS:
1230 159997 : Real64 constexpr MinFrac(0.0005); // Minimum fraction that delivers radiant heats to surfaces
1231 : static constexpr std::string_view RoutineName("CalcHWBaseboard");
1232 :
1233 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1234 : Real64 RadHeat;
1235 : Real64 BBHeat;
1236 : Real64 AirOutletTemp;
1237 : Real64 WaterOutletTemp;
1238 : Real64 AirMassFlowRate;
1239 : Real64 CapacitanceAir;
1240 : Real64 CapacitanceWater;
1241 : Real64 CapacitanceMax;
1242 : Real64 CapacitanceMin;
1243 : Real64 CapacityRatio;
1244 : Real64 NTU;
1245 : Real64 Effectiveness;
1246 : Real64 AA;
1247 : Real64 BB;
1248 : Real64 CC;
1249 : Real64 Cp;
1250 :
1251 159997 : auto &hWBaseboard = state.dataHWBaseboardRad->HWBaseboard(BaseboardNum);
1252 :
1253 159997 : int const ZoneNum = hWBaseboard.ZonePtr;
1254 159997 : Real64 QZnReq = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).RemainingOutputReqToHeatSP;
1255 159997 : Real64 AirInletTemp = hWBaseboard.AirInletTemp;
1256 159997 : Real64 WaterInletTemp = hWBaseboard.WaterInletTemp;
1257 159997 : Real64 WaterMassFlowRate = state.dataLoopNodes->Node(hWBaseboard.WaterInletNode).MassFlowRate;
1258 :
1259 234544 : if (QZnReq > HVAC::SmallLoad && !state.dataZoneEnergyDemand->CurDeadBandOrSetback(ZoneNum) && (hWBaseboard.availSched->getCurrentVal() > 0) &&
1260 74547 : (WaterMassFlowRate > 0.0)) {
1261 :
1262 : HWBaseboardDesignData const &HWBaseboardDesignDataObject{
1263 68613 : state.dataHWBaseboardRad->HWBaseboardDesignObject(hWBaseboard.DesignObjectPtr)}; // Contains the data for the design object
1264 :
1265 : // Calculate air mass flow rate
1266 68613 : AirMassFlowRate = hWBaseboard.AirMassFlowRateStd * (WaterMassFlowRate / hWBaseboard.WaterMassFlowRateMax);
1267 68613 : CapacitanceAir = Psychrometrics::PsyCpAirFnW(hWBaseboard.AirInletHumRat) * AirMassFlowRate;
1268 68613 : Cp = state.dataPlnt->PlantLoop(hWBaseboard.plantLoc.loopNum).glycol->getSpecificHeat(state, WaterInletTemp, RoutineName);
1269 :
1270 68613 : CapacitanceWater = Cp * WaterMassFlowRate;
1271 68613 : CapacitanceMax = max(CapacitanceAir, CapacitanceWater);
1272 68613 : CapacitanceMin = min(CapacitanceAir, CapacitanceWater);
1273 68613 : CapacityRatio = CapacitanceMin / CapacitanceMax;
1274 68613 : NTU = hWBaseboard.UA / CapacitanceMin;
1275 :
1276 : // The effectiveness is given by the following formula:
1277 : // Effectiveness = 1. - EXP((1./CapacityRatio)*(NTU)**0.22*(EXP(-CapacityRatio*(NTU)**0.78)-1.))
1278 : // To prevent possible underflows (numbers smaller than the computer can handle) we must break
1279 : // the calculation up into steps and check the size of the exponential arguments.
1280 68613 : AA = -CapacityRatio * std::pow(NTU, 0.78);
1281 68613 : if (AA < -20.0) {
1282 66 : BB = 0.0;
1283 : } else {
1284 68547 : BB = std::exp(AA);
1285 : }
1286 68613 : CC = (1.0 / CapacityRatio) * std::pow(NTU, 0.22) * (BB - 1.0);
1287 68613 : if (CC < -20.0) {
1288 11 : Effectiveness = 1.0;
1289 : } else {
1290 68602 : Effectiveness = 1.0 - std::exp(CC);
1291 : }
1292 :
1293 68613 : AirOutletTemp = AirInletTemp + Effectiveness * CapacitanceMin * (WaterInletTemp - AirInletTemp) / CapacitanceAir;
1294 68613 : WaterOutletTemp = WaterInletTemp - CapacitanceAir * (AirOutletTemp - AirInletTemp) / CapacitanceWater;
1295 68613 : BBHeat = CapacitanceWater * (WaterInletTemp - WaterOutletTemp);
1296 68613 : RadHeat = BBHeat * HWBaseboardDesignDataObject.FracRadiant;
1297 68613 : hWBaseboard.QBBRadSource = RadHeat;
1298 :
1299 68613 : if (HWBaseboardDesignDataObject.FracRadiant <= MinFrac) {
1300 31186 : LoadMet = BBHeat;
1301 : } else {
1302 :
1303 : // Now, distribute the radiant energy of all systems to the appropriate surfaces, to people, and the air
1304 37427 : DistributeBBRadGains(state);
1305 : // Now "simulate" the system by recalculating the heat balances
1306 37427 : HeatBalanceSurfaceManager::CalcHeatBalanceOutsideSurf(state, ZoneNum);
1307 :
1308 37427 : HeatBalanceSurfaceManager::CalcHeatBalanceInsideSurf(state, ZoneNum);
1309 :
1310 : // Here an assumption is made regarding radiant heat transfer to people.
1311 : // While the radiant heat transfer to people array will be used by the thermal comfort
1312 : // routines, the energy transfer to people would get lost from the perspective
1313 : // of the heat balance. So, to avoid this net loss of energy which clearly
1314 : // gets added to the zones, we must account for it somehow. This assumption
1315 : // that all energy radiated to people is converted to convective energy is
1316 : // not very precise, but at least it conserves energy. The system impact to heat balance
1317 : // should include this.
1318 :
1319 37427 : LoadMet = (state.dataHeatBal->Zone(ZoneNum).sumHATsurf(state) - hWBaseboard.ZeroBBSourceSumHATsurf) +
1320 37427 : (BBHeat * hWBaseboard.FracConvect) + (RadHeat * HWBaseboardDesignDataObject.FracDistribPerson);
1321 : }
1322 68613 : hWBaseboard.WaterOutletEnthalpy = hWBaseboard.WaterInletEnthalpy - BBHeat / WaterMassFlowRate;
1323 : } else {
1324 91384 : CapacitanceWater = 0.0;
1325 91384 : CapacitanceMax = 0.0;
1326 91384 : CapacitanceMin = 0.0;
1327 91384 : NTU = 0.0;
1328 91384 : Effectiveness = 0.0;
1329 91384 : AirOutletTemp = AirInletTemp;
1330 91384 : WaterOutletTemp = WaterInletTemp;
1331 91384 : BBHeat = 0.0;
1332 91384 : LoadMet = 0.0;
1333 91384 : RadHeat = 0.0;
1334 91384 : WaterMassFlowRate = 0.0;
1335 91384 : AirMassFlowRate = 0.0;
1336 91384 : hWBaseboard.QBBRadSource = 0.0;
1337 91384 : hWBaseboard.WaterOutletEnthalpy = hWBaseboard.WaterInletEnthalpy;
1338 91384 : PlantUtilities::SetActuatedBranchFlowRate(state, WaterMassFlowRate, hWBaseboard.WaterInletNode, hWBaseboard.plantLoc, false);
1339 : }
1340 :
1341 159997 : hWBaseboard.WaterOutletTemp = WaterOutletTemp;
1342 159997 : hWBaseboard.AirOutletTemp = AirOutletTemp;
1343 159997 : hWBaseboard.WaterMassFlowRate = WaterMassFlowRate;
1344 159997 : hWBaseboard.AirMassFlowRate = AirMassFlowRate;
1345 159997 : hWBaseboard.TotPower = LoadMet;
1346 159997 : hWBaseboard.Power = BBHeat;
1347 159997 : hWBaseboard.ConvPower = BBHeat - RadHeat;
1348 159997 : hWBaseboard.RadPower = RadHeat;
1349 159997 : }
1350 :
1351 89083 : void UpdateHWBaseboard(EnergyPlusData &state, int const BaseboardNum)
1352 : {
1353 :
1354 : // SUBROUTINE INFORMATION:
1355 : // AUTHOR Russ Taylor
1356 : // Rick Strand
1357 : // DATE WRITTEN Nov 1997
1358 : // February 2001
1359 : // MODIFIED Aug 2007 Daeho Kang (Add the update of radiant source)
1360 :
1361 : // METHODOLOGY EMPLOYED:
1362 : // The update subroutines both in high temperature radiant radiator
1363 : // and convective only baseboard radiator are combined and modified.
1364 :
1365 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1366 : int WaterInletNode;
1367 : int WaterOutletNode;
1368 89083 : auto &thisHWBB = state.dataHWBaseboardRad->HWBaseboard(BaseboardNum);
1369 :
1370 89083 : if (state.dataGlobal->BeginEnvrnFlag && state.dataHWBaseboardRad->MyEnvrnFlag2) {
1371 42 : state.dataHWBaseboardRad->Iter = 0;
1372 42 : state.dataHWBaseboardRad->MyEnvrnFlag2 = false;
1373 : }
1374 89083 : if (!state.dataGlobal->BeginEnvrnFlag) {
1375 88549 : state.dataHWBaseboardRad->MyEnvrnFlag2 = true;
1376 : }
1377 :
1378 : // First, update the running average if necessary...
1379 89083 : if (thisHWBB.LastSysTimeElapsed == state.dataHVACGlobal->SysTimeElapsed) {
1380 82573 : thisHWBB.QBBRadSrcAvg -= thisHWBB.LastQBBRadSrc * thisHWBB.LastTimeStepSys / state.dataGlobal->TimeStepZone;
1381 : }
1382 : // Update the running average and the "last" values with the current values of the appropriate variables
1383 89083 : thisHWBB.QBBRadSrcAvg += thisHWBB.QBBRadSource * state.dataHVACGlobal->TimeStepSys / state.dataGlobal->TimeStepZone;
1384 :
1385 89083 : thisHWBB.LastQBBRadSrc = thisHWBB.QBBRadSource;
1386 89083 : thisHWBB.LastSysTimeElapsed = state.dataHVACGlobal->SysTimeElapsed;
1387 89083 : thisHWBB.LastTimeStepSys = state.dataHVACGlobal->TimeStepSys;
1388 :
1389 89083 : WaterInletNode = thisHWBB.WaterInletNode;
1390 89083 : WaterOutletNode = thisHWBB.WaterOutletNode;
1391 :
1392 : // Set the outlet air nodes of the Baseboard
1393 : // Set the outlet water nodes for the Coil
1394 89083 : PlantUtilities::SafeCopyPlantNode(state, WaterInletNode, WaterOutletNode);
1395 89083 : state.dataLoopNodes->Node(WaterOutletNode).Temp = thisHWBB.WaterOutletTemp;
1396 89083 : state.dataLoopNodes->Node(WaterOutletNode).Enthalpy = thisHWBB.WaterOutletEnthalpy;
1397 89083 : }
1398 :
1399 2828212 : void UpdateBBRadSourceValAvg(EnergyPlusData &state, bool &HWBaseboardSysOn) // .TRUE. if the radiant system has run this zone time step
1400 : {
1401 :
1402 : // SUBROUTINE INFORMATION:
1403 : // AUTHOR Rick Strand
1404 : // DATE WRITTEN February 2001
1405 : // MODIFIED Aug 2007 Daeho Kang (Modification only for baseboard)
1406 :
1407 : // PURPOSE OF THIS SUBROUTINE:
1408 : // To transfer the average value of the heat source over the entire
1409 : // zone time step back to the heat balance routines so that the heat
1410 : // balance algorithms can simulate one last time with the average source
1411 : // to maintain some reasonable amount of continuity and energy balance
1412 : // in the temperature and flux histories.
1413 :
1414 : // METHODOLOGY EMPLOYED:
1415 : // All of the record keeping for the average term is done in the Update
1416 : // routine so the only other thing that this subroutine does is check to
1417 : // see if the system was even on. If any average term is non-zero, then
1418 : // one or more of the radiant systems was running.
1419 :
1420 2828212 : HWBaseboardSysOn = false;
1421 :
1422 : // If there are no baseboards in this input file, just RETURN
1423 2828212 : if (state.dataHWBaseboardRad->NumHWBaseboards == 0) {
1424 2814688 : return;
1425 : }
1426 :
1427 : // If there are baseboards, then we have to check to see if this was running at all...
1428 44640 : for (auto &thisHWBaseboard : state.dataHWBaseboardRad->HWBaseboard) {
1429 31116 : thisHWBaseboard.QBBRadSource = thisHWBaseboard.QBBRadSrcAvg;
1430 31116 : if (thisHWBaseboard.QBBRadSrcAvg != 0.0) {
1431 12096 : HWBaseboardSysOn = true;
1432 : }
1433 : }
1434 :
1435 13524 : DistributeBBRadGains(state); // QBBRadSource has been modified so we need to redistribute gains
1436 : }
1437 :
1438 50951 : void DistributeBBRadGains(EnergyPlusData &state)
1439 : {
1440 :
1441 : // SUBROUTINE INFORMATION:
1442 : // AUTHOR Rick Strand
1443 : // DATE WRITTEN February 2001
1444 : // MODIFIED Aug. 2007 Daeho Kang (Modification only for baseboard)
1445 : // April 2010 Brent Griffith, max limit to protect surface temperature calcs
1446 :
1447 : // PURPOSE OF THIS SUBROUTINE:
1448 : // To distribute the gains from the hot water baseboard heater
1449 : // as specified in the user input file. This includes distribution
1450 : // of long wavelength radiant gains to surfaces and "people."
1451 :
1452 : // METHODOLOGY EMPLOYED:
1453 : // We must cycle through all of the radiant systems because each
1454 : // surface could feel the effect of more than one radiant system.
1455 : // Note that the energy radiated to people is assumed to affect them
1456 : // but them it is assumed to be convected to the air.
1457 :
1458 : // SUBROUTINE PARAMETER DEFINITIONS:
1459 50951 : Real64 constexpr SmallestArea(0.001); // Smallest area in meters squared (to avoid a divide by zero)
1460 :
1461 : Real64 ThisSurfIntensity; // temporary for W/m2 term for rad on a surface
1462 :
1463 : // Initialize arrays
1464 156921 : for (auto &thisHWBB : state.dataHWBaseboardRad->HWBaseboard) {
1465 403540 : for (int radSurfNum = 1; radSurfNum <= thisHWBB.TotSurfToDistrib; ++radSurfNum) {
1466 297570 : int surfNum = thisHWBB.SurfacePtr(radSurfNum);
1467 297570 : state.dataHeatBalFanSys->surfQRadFromHVAC(surfNum).HWBaseboard = 0.0;
1468 : }
1469 : }
1470 50951 : state.dataHeatBalFanSys->ZoneQHWBaseboardToPerson = 0.0;
1471 :
1472 156921 : for (auto &thisHWBB : state.dataHWBaseboardRad->HWBaseboard) {
1473 : HWBaseboardDesignData const &HWBaseboardDesignDataObject =
1474 105970 : state.dataHWBaseboardRad->HWBaseboardDesignObject(thisHWBB.DesignObjectPtr); // Contains the data for the design object
1475 105970 : int ZoneNum = thisHWBB.ZonePtr;
1476 105970 : if (ZoneNum <= 0) {
1477 0 : continue;
1478 : }
1479 105970 : state.dataHeatBalFanSys->ZoneQHWBaseboardToPerson(ZoneNum) += thisHWBB.QBBRadSource * HWBaseboardDesignDataObject.FracDistribPerson;
1480 :
1481 403540 : for (int RadSurfNum = 1; RadSurfNum <= thisHWBB.TotSurfToDistrib; ++RadSurfNum) {
1482 297570 : int SurfNum = thisHWBB.SurfacePtr(RadSurfNum);
1483 297570 : if (state.dataSurface->Surface(SurfNum).Area > SmallestArea) {
1484 297570 : ThisSurfIntensity = (thisHWBB.QBBRadSource * thisHWBB.FracDistribToSurf(RadSurfNum) / state.dataSurface->Surface(SurfNum).Area);
1485 297570 : state.dataHeatBalFanSys->surfQRadFromHVAC(SurfNum).HWBaseboard += ThisSurfIntensity;
1486 : // CR 8074, trap for excessive intensity (throws off surface balance )
1487 297570 : if (ThisSurfIntensity > DataHeatBalFanSys::MaxRadHeatFlux) {
1488 0 : ShowSevereError(state, "DistributeBBRadGains: excessive thermal radiation heat flux intensity detected");
1489 0 : ShowContinueError(state, format("Surface = {}", state.dataSurface->Surface(SurfNum).Name));
1490 0 : ShowContinueError(state, format("Surface area = {:.3R} [m2]", state.dataSurface->Surface(SurfNum).Area));
1491 0 : ShowContinueError(state, format("Occurs in {} = {}", cCMO_BBRadiator_Water, thisHWBB.Name));
1492 0 : ShowContinueError(state, format("Radiation intensity = {:.2R} [W/m2]", ThisSurfIntensity));
1493 0 : ShowContinueError(state, format("Assign a larger surface area or more surfaces in {}", cCMO_BBRadiator_Water));
1494 0 : ShowFatalError(state, "DistributeBBRadGains: excessive thermal radiation heat flux intensity detected");
1495 : }
1496 : } else {
1497 0 : ShowSevereError(state, "DistributeBBRadGains: surface not large enough to receive thermal radiation heat flux");
1498 0 : ShowContinueError(state, format("Surface = {}", state.dataSurface->Surface(SurfNum).Name));
1499 0 : ShowContinueError(state, format("Surface area = {:.3R} [m2]", state.dataSurface->Surface(SurfNum).Area));
1500 0 : ShowContinueError(state, format("Occurs in {} = {}", cCMO_BBRadiator_Water, thisHWBB.Name));
1501 0 : ShowContinueError(state, format("Assign a larger surface area or more surfaces in {}", cCMO_BBRadiator_Water));
1502 0 : ShowFatalError(state, "DistributeBBRadGains: surface not large enough to receive thermal radiation heat flux");
1503 : }
1504 : }
1505 : }
1506 50951 : }
1507 :
1508 89083 : void ReportHWBaseboard(EnergyPlusData &state, int const BaseboardNum)
1509 : {
1510 :
1511 : // SUBROUTINE INFORMATION:
1512 : // AUTHOR Daeho Kang
1513 : // DATE WRITTEN Aug 2007
1514 :
1515 89083 : auto &thisHWBB = state.dataHWBaseboardRad->HWBaseboard(BaseboardNum);
1516 89083 : Real64 const timeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
1517 :
1518 89083 : thisHWBB.TotEnergy = thisHWBB.TotPower * timeStepSysSec;
1519 89083 : thisHWBB.Energy = thisHWBB.Power * timeStepSysSec;
1520 89083 : thisHWBB.ConvEnergy = thisHWBB.ConvPower * timeStepSysSec;
1521 89083 : thisHWBB.RadEnergy = thisHWBB.RadPower * timeStepSysSec;
1522 89083 : }
1523 :
1524 0 : void UpdateHWBaseboardPlantConnection(EnergyPlusData &state,
1525 : int const BaseboardTypeNum, // type index
1526 : std::string const &BaseboardName, // component name
1527 : [[maybe_unused]] int const EquipFlowCtrl, // Flow control mode for the equipment
1528 : [[maybe_unused]] int const LoopNum, // Plant loop index for where called from
1529 : [[maybe_unused]] const DataPlant::LoopSideLocation LoopSide, // Plant loop side index for where called from
1530 : int &CompIndex, // Chiller number pointer
1531 : [[maybe_unused]] bool const FirstHVACIteration,
1532 : bool &InitLoopEquip // If not zero, calculate the max load for operating conditions
1533 : )
1534 : {
1535 :
1536 : // SUBROUTINE INFORMATION:
1537 : // AUTHOR Brent Griffith
1538 : // DATE WRITTEN Sept. 2010
1539 :
1540 : // PURPOSE OF THIS SUBROUTINE:
1541 : // update sim routine called from plant
1542 :
1543 : // METHODOLOGY EMPLOYED:
1544 : // check input, provide comp index, call utility routines
1545 :
1546 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1547 0 : int const NumHWBaseboards = state.dataHWBaseboardRad->NumHWBaseboards;
1548 : int BaseboardNum;
1549 :
1550 : // Find the correct baseboard
1551 0 : if (CompIndex == 0) {
1552 0 : BaseboardNum = Util::FindItemInList(BaseboardName, state.dataHWBaseboardRad->HWBaseboard, &HWBaseboardParams::Name);
1553 0 : if (BaseboardNum == 0) {
1554 0 : ShowFatalError(state, format("UpdateHWBaseboardPlantConnection: Specified baseboard not valid ={}", BaseboardName));
1555 : }
1556 0 : CompIndex = BaseboardNum;
1557 : } else {
1558 0 : BaseboardNum = CompIndex;
1559 0 : if (BaseboardNum > NumHWBaseboards || BaseboardNum < 1) {
1560 0 : ShowFatalError(
1561 : state,
1562 0 : format("UpdateHWBaseboardPlantConnection: Invalid CompIndex passed={}, Number of baseboards={}, Entered baseboard name={}",
1563 : BaseboardNum,
1564 : NumHWBaseboards,
1565 : BaseboardName));
1566 : }
1567 0 : if (state.dataGlobal->KickOffSimulation) {
1568 0 : if (BaseboardName != state.dataHWBaseboardRad->HWBaseboard(BaseboardNum).Name) {
1569 0 : ShowFatalError(state,
1570 0 : format("UpdateHWBaseboardPlantConnection: Invalid CompIndex passed={}, baseboard name={}, stored baseboard Name "
1571 : "for that index={}",
1572 : BaseboardNum,
1573 : BaseboardName,
1574 0 : state.dataHWBaseboardRad->HWBaseboard(BaseboardNum).Name));
1575 : }
1576 0 : if (BaseboardTypeNum != static_cast<int>(DataPlant::PlantEquipmentType::Baseboard_Rad_Conv_Water)) {
1577 0 : ShowFatalError(state,
1578 0 : format("UpdateHWBaseboardPlantConnection: Invalid CompIndex passed={}, baseboard name={}, stored baseboard Name "
1579 : "for that index={}",
1580 : BaseboardNum,
1581 : BaseboardName,
1582 0 : DataPlant::PlantEquipTypeNames[BaseboardTypeNum]));
1583 : }
1584 : }
1585 : }
1586 :
1587 0 : if (InitLoopEquip) {
1588 0 : return;
1589 : }
1590 :
1591 0 : auto &thisHWBaseboard = state.dataHWBaseboardRad->HWBaseboard(BaseboardNum);
1592 0 : PlantUtilities::PullCompInterconnectTrigger(state,
1593 0 : thisHWBaseboard.plantLoc,
1594 0 : thisHWBaseboard.BBLoadReSimIndex,
1595 0 : thisHWBaseboard.plantLoc,
1596 : DataPlant::CriteriaType::HeatTransferRate,
1597 : thisHWBaseboard.Power);
1598 :
1599 0 : PlantUtilities::PullCompInterconnectTrigger(state,
1600 0 : thisHWBaseboard.plantLoc,
1601 0 : thisHWBaseboard.BBMassFlowReSimIndex,
1602 0 : thisHWBaseboard.plantLoc,
1603 : DataPlant::CriteriaType::MassFlowRate,
1604 : thisHWBaseboard.WaterMassFlowRate);
1605 :
1606 0 : PlantUtilities::PullCompInterconnectTrigger(state,
1607 0 : thisHWBaseboard.plantLoc,
1608 0 : thisHWBaseboard.BBInletTempFlowReSimIndex,
1609 0 : thisHWBaseboard.plantLoc,
1610 : DataPlant::CriteriaType::Temperature,
1611 : thisHWBaseboard.WaterOutletTemp);
1612 : }
1613 :
1614 : //*****************************************************************************************
1615 :
1616 : } // namespace HWBaseboardRadiator
1617 :
1618 : } // namespace EnergyPlus
|