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 34 : Util::setDesignObjectNameAndPointer(state,
457 17 : thisHWBaseboard.designObjectName,
458 17 : thisHWBaseboard.DesignObjectPtr,
459 17 : state.dataIPShortCut->cAlphaArgs(2),
460 : HWBaseboardDesignNames,
461 : cCMO_BBRadiator_Water,
462 17 : state.dataIPShortCut->cAlphaArgs(1),
463 : ErrorsFound);
464 17 : if (ErrorsFound) {
465 0 : break;
466 : }
467 : HWBaseboardDesignData &HWBaseboardDesignDataObject =
468 17 : state.dataHWBaseboardRad->HWBaseboardDesignObject(thisHWBaseboard.DesignObjectPtr); // Contains the data for the design object
469 :
470 : // Get schedule
471 17 : if (state.dataIPShortCut->lAlphaFieldBlanks(3)) {
472 5 : thisHWBaseboard.availSched = Sched::GetScheduleAlwaysOn(state);
473 12 : } else if ((thisHWBaseboard.availSched = Sched::GetSchedule(state, state.dataIPShortCut->cAlphaArgs(3))) == nullptr) {
474 0 : ShowSevereItemNotFound(state, eoh, state.dataIPShortCut->cAlphaFieldNames(3), state.dataIPShortCut->cAlphaArgs(3));
475 0 : ErrorsFound = true;
476 : }
477 :
478 : // Get inlet node number
479 17 : thisHWBaseboard.WaterInletNode = GetOnlySingleNode(state,
480 17 : state.dataIPShortCut->cAlphaArgs(4),
481 : ErrorsFound,
482 : DataLoopNode::ConnectionObjectType::ZoneHVACBaseboardRadiantConvectiveWater,
483 17 : state.dataIPShortCut->cAlphaArgs(1),
484 : DataLoopNode::NodeFluidType::Water,
485 : DataLoopNode::ConnectionType::Inlet,
486 : NodeInputManager::CompFluidStream::Primary,
487 : DataLoopNode::ObjectIsNotParent);
488 :
489 : // Get outlet node number
490 34 : thisHWBaseboard.WaterOutletNode = GetOnlySingleNode(state,
491 17 : state.dataIPShortCut->cAlphaArgs(5),
492 : ErrorsFound,
493 : DataLoopNode::ConnectionObjectType::ZoneHVACBaseboardRadiantConvectiveWater,
494 17 : state.dataIPShortCut->cAlphaArgs(1),
495 : DataLoopNode::NodeFluidType::Water,
496 : DataLoopNode::ConnectionType::Outlet,
497 : NodeInputManager::CompFluidStream::Primary,
498 : DataLoopNode::ObjectIsNotParent);
499 34 : BranchNodeConnections::TestCompSet(state,
500 : cCMO_BBRadiator_Water,
501 17 : state.dataIPShortCut->cAlphaArgs(1),
502 17 : state.dataIPShortCut->cAlphaArgs(4),
503 17 : state.dataIPShortCut->cAlphaArgs(5),
504 : "Hot Water Nodes");
505 :
506 17 : thisHWBaseboard.WaterTempAvg = state.dataIPShortCut->rNumericArgs(1);
507 17 : if (thisHWBaseboard.WaterTempAvg > MaxWaterTempAvg + 0.001) {
508 0 : ShowWarningError(state,
509 0 : format("{}{}=\"{}\", {} was higher than the allowable maximum.",
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 maximum value=[{:.2R}].", MaxWaterTempAvg));
515 0 : thisHWBaseboard.WaterTempAvg = MaxWaterTempAvg;
516 17 : } else if (thisHWBaseboard.WaterTempAvg < MinWaterTempAvg - 0.001) {
517 0 : ShowWarningError(state,
518 0 : format("{}{}=\"{}\", {} was lower than the allowable minimum.",
519 : RoutineName,
520 : cCMO_BBRadiator_Water,
521 0 : state.dataIPShortCut->cAlphaArgs(1),
522 0 : state.dataIPShortCut->cNumericFieldNames(1)));
523 0 : ShowContinueError(state, format("...reset to minimum value=[{:.2R}].", MinWaterTempAvg));
524 0 : thisHWBaseboard.WaterTempAvg = MinWaterTempAvg;
525 : }
526 :
527 17 : thisHWBaseboard.WaterMassFlowRateStd = state.dataIPShortCut->rNumericArgs(2);
528 17 : if (thisHWBaseboard.WaterMassFlowRateStd < LowWaterMassFlowRate - 0.0001 ||
529 17 : thisHWBaseboard.WaterMassFlowRateStd > HighWaterMassFlowRate + 0.0001) {
530 0 : ShowWarningError(state,
531 0 : format("{}{}=\"{}\", {} is an invalid Standard Water mass flow rate.",
532 : RoutineName,
533 : cCMO_BBRadiator_Water,
534 0 : state.dataIPShortCut->cAlphaArgs(1),
535 0 : state.dataIPShortCut->cNumericFieldNames(2)));
536 0 : ShowContinueError(state, format("...reset to a default value=[{:.1R}].", WaterMassFlowDefault));
537 0 : thisHWBaseboard.WaterMassFlowRateStd = WaterMassFlowDefault;
538 : }
539 :
540 : // Determine HW radiant baseboard heating design capacity sizing method
541 17 : thisHWBaseboard.HeatingCapMethod = static_cast<int>(HWBaseboardDesignDataObject.HeatingCapMethod);
542 17 : if (thisHWBaseboard.HeatingCapMethod == DataSizing::HeatingDesignCapacity) {
543 17 : if (!state.dataIPShortCut->lNumericFieldBlanks(iHeatDesignCapacityNumericNum)) {
544 17 : thisHWBaseboard.ScaledHeatingCapacity = state.dataIPShortCut->rNumericArgs(iHeatDesignCapacityNumericNum);
545 17 : if (thisHWBaseboard.ScaledHeatingCapacity < 0.0 && thisHWBaseboard.ScaledHeatingCapacity != DataSizing::AutoSize) {
546 0 : ShowSevereError(state, format("{} = {}", state.dataIPShortCut->cCurrentModuleObject, thisHWBaseboard.Name));
547 0 : ShowContinueError(state,
548 0 : format("Illegal {} = {:.7T}",
549 0 : state.dataIPShortCut->cNumericFieldNames(iHeatDesignCapacityNumericNum),
550 0 : state.dataIPShortCut->rNumericArgs(iHeatDesignCapacityNumericNum)));
551 0 : ErrorsFound = true;
552 : }
553 : } else {
554 0 : ShowSevereError(state, format("{} = {}", state.dataIPShortCut->cCurrentModuleObject, thisHWBaseboard.Name));
555 0 : ShowContinueError(state,
556 0 : format("Input for {} = {}",
557 0 : state.dataIPShortCut->cAlphaFieldNames(iHeatCAPMAlphaNum),
558 0 : state.dataIPShortCut->cAlphaArgs(iHeatCAPMAlphaNum)));
559 0 : ShowContinueError(
560 0 : state, format("Blank field not allowed for {}", state.dataIPShortCut->cNumericFieldNames(iHeatDesignCapacityNumericNum)));
561 0 : ErrorsFound = true;
562 : }
563 0 : } else if (thisHWBaseboard.HeatingCapMethod == DataSizing::CapacityPerFloorArea) {
564 0 : thisHWBaseboard.ScaledHeatingCapacity = HWBaseboardDesignDataObject.ScaledHeatingCapacity;
565 :
566 0 : } else if (thisHWBaseboard.HeatingCapMethod == DataSizing::FractionOfAutosizedHeatingCapacity) {
567 0 : thisHWBaseboard.ScaledHeatingCapacity = HWBaseboardDesignDataObject.ScaledHeatingCapacity;
568 :
569 : } else {
570 0 : ShowSevereError(state, format("{} = {}", state.dataIPShortCut->cCurrentModuleObject, thisHWBaseboard.Name));
571 0 : ShowContinueError(state,
572 0 : format("Illegal {} = {}",
573 0 : state.dataIPShortCut->cAlphaFieldNames(iHeatCAPMAlphaNum),
574 0 : state.dataIPShortCut->cAlphaArgs(iHeatCAPMAlphaNum)));
575 0 : ErrorsFound = true;
576 : }
577 :
578 17 : thisHWBaseboard.WaterVolFlowRateMax = state.dataIPShortCut->rNumericArgs(4);
579 17 : if (std::abs(thisHWBaseboard.WaterVolFlowRateMax) <= MinWaterFlowRate) {
580 0 : ShowWarningError(state,
581 0 : format("{}{}=\"{}\", {} was less than the allowable minimum.",
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 minimum value=[{:.2R}].", MinWaterFlowRate));
587 0 : thisHWBaseboard.WaterVolFlowRateMax = MinWaterFlowRate;
588 17 : } else if (thisHWBaseboard.WaterVolFlowRateMax > MaxWaterFlowRate) {
589 0 : ShowWarningError(state,
590 0 : format("{}{}=\"{}\", {} was higher than the allowable maximum.",
591 : RoutineName,
592 : cCMO_BBRadiator_Water,
593 0 : state.dataIPShortCut->cAlphaArgs(1),
594 0 : state.dataIPShortCut->cNumericFieldNames(4)));
595 0 : ShowContinueError(state, format("...reset to maximum value=[{:.2R}].", MaxWaterFlowRate));
596 0 : thisHWBaseboard.WaterVolFlowRateMax = MaxWaterFlowRate;
597 : }
598 :
599 : // Remaining fraction is added to the zone as convective heat transfer
600 17 : if (HWBaseboardDesignDataObject.FracRadiant > MaxFraction) {
601 0 : ShowWarningError(state,
602 0 : format("{}{}=\"{}\", Fraction Radiant was higher than the allowable maximum.",
603 : RoutineName,
604 : cCMO_BBRadiator_Water,
605 0 : state.dataIPShortCut->cAlphaArgs(1)));
606 0 : HWBaseboardDesignDataObject.FracRadiant = MaxFraction;
607 0 : thisHWBaseboard.FracConvect = 0.0;
608 : } else {
609 17 : thisHWBaseboard.FracConvect = 1.0 - HWBaseboardDesignDataObject.FracRadiant;
610 : }
611 :
612 17 : thisHWBaseboard.TotSurfToDistrib = NumNumbers - 4;
613 : // IF (thisHWBaseboard%TotSurfToDistrib > MaxDistribSurfaces) THEN
614 : // CALL ShowWarningError(state, RoutineName//cCMO_BBRadiator_Water//'="'//TRIM(state.dataIPShortCut->cAlphaArgs(1))// &
615 : // '", the number of surface/radiant fraction groups entered was higher than the allowable maximum.')
616 : // CALL ShowContinueError(state, '...only the maximum value=['//TRIM(RoundSigDigits(MaxDistribSurfaces))// &
617 : // '] will be processed.')
618 : // thisHWBaseboard%TotSurfToDistrib = MaxDistribSurfaces
619 : // END IF
620 17 : if ((thisHWBaseboard.TotSurfToDistrib < MinDistribSurfaces) && (HWBaseboardDesignDataObject.FracRadiant > MinFraction)) {
621 0 : ShowSevereError(state,
622 0 : std::string{RoutineName} + cCMO_BBRadiator_Water + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
623 : "\", the number of surface/radiant fraction groups entered was less than the allowable minimum.");
624 0 : ShowContinueError(state, format("...the minimum that must be entered=[{}].", MinDistribSurfaces));
625 0 : ErrorsFound = true;
626 0 : thisHWBaseboard.TotSurfToDistrib = 0; // error
627 : }
628 :
629 17 : thisHWBaseboard.SurfacePtr.allocate(thisHWBaseboard.TotSurfToDistrib);
630 17 : thisHWBaseboard.SurfacePtr = 0;
631 17 : thisHWBaseboard.FracDistribToSurf.allocate(thisHWBaseboard.TotSurfToDistrib);
632 17 : thisHWBaseboard.FracDistribToSurf = 0.0;
633 :
634 17 : thisHWBaseboard.ZonePtr =
635 17 : DataZoneEquipment::GetZoneEquipControlledZoneNum(state, DataZoneEquipment::ZoneEquipType::BaseboardWater, thisHWBaseboard.Name);
636 :
637 17 : Real64 AllFracsSummed = HWBaseboardDesignDataObject.FracDistribPerson;
638 53 : for (SurfNum = 1; SurfNum <= thisHWBaseboard.TotSurfToDistrib; ++SurfNum) {
639 72 : thisHWBaseboard.SurfacePtr(SurfNum) =
640 36 : HeatBalanceIntRadExchange::GetRadiantSystemSurface(state,
641 : cCMO_BBRadiator_Water,
642 36 : thisHWBaseboard.Name,
643 : thisHWBaseboard.ZonePtr,
644 36 : state.dataIPShortCut->cAlphaArgs(SurfNum + 5),
645 : ErrorsFound);
646 36 : thisHWBaseboard.FracDistribToSurf(SurfNum) = state.dataIPShortCut->rNumericArgs(SurfNum + 4);
647 36 : if (thisHWBaseboard.FracDistribToSurf(SurfNum) > MaxFraction) {
648 0 : ShowWarningError(state,
649 0 : format("{}{}=\"{}\", {}was greater than the allowable maximum.",
650 : RoutineName,
651 : cCMO_BBRadiator_Water,
652 0 : state.dataIPShortCut->cAlphaArgs(1),
653 0 : state.dataIPShortCut->cNumericFieldNames(SurfNum + 4)));
654 0 : ShowContinueError(state, format("...reset to maximum value=[{:.2R}].", MaxFraction));
655 0 : thisHWBaseboard.TotSurfToDistrib = MaxFraction;
656 : }
657 36 : if (thisHWBaseboard.FracDistribToSurf(SurfNum) < MinFraction) {
658 0 : ShowWarningError(state,
659 0 : format("{}{}=\"{}\", {}was less than the allowable minimum.",
660 : RoutineName,
661 : cCMO_BBRadiator_Water,
662 0 : state.dataIPShortCut->cAlphaArgs(1),
663 0 : state.dataIPShortCut->cNumericFieldNames(SurfNum + 4)));
664 0 : ShowContinueError(state, format("...reset to maximum value=[{:.2R}].", MinFraction));
665 0 : thisHWBaseboard.TotSurfToDistrib = MinFraction;
666 : }
667 36 : if (thisHWBaseboard.SurfacePtr(SurfNum) != 0) {
668 36 : state.dataSurface->surfIntConv(thisHWBaseboard.SurfacePtr(SurfNum)).getsRadiantHeat = true;
669 36 : state.dataSurface->allGetsRadiantHeatSurfaceList.emplace_back(thisHWBaseboard.SurfacePtr(SurfNum));
670 : }
671 :
672 36 : AllFracsSummed += thisHWBaseboard.FracDistribToSurf(SurfNum);
673 : } // Surfaces
674 :
675 17 : if (AllFracsSummed > (MaxFraction + 0.01)) {
676 0 : ShowSevereError(state,
677 0 : format("{}{}=\"{}\", Summed radiant fractions for people + surface groups > 1.0",
678 : RoutineName,
679 : cCMO_BBRadiator_Water,
680 0 : state.dataIPShortCut->cAlphaArgs(1)));
681 0 : ErrorsFound = true;
682 : }
683 17 : if ((AllFracsSummed < (MaxFraction - 0.01)) &&
684 5 : (HWBaseboardDesignDataObject.FracRadiant >
685 : MinFraction)) { // User didn't distribute all of the | radiation warn that some will be lost
686 0 : ShowWarningError(state,
687 0 : format("{}{}=\"{}\", Summed radiant fractions for people + surface groups < 1.0",
688 : RoutineName,
689 : cCMO_BBRadiator_Water,
690 0 : state.dataIPShortCut->cAlphaArgs(1)));
691 0 : ShowContinueError(state, "The rest of the radiant energy delivered by the baseboard heater will be lost");
692 : }
693 : }
694 :
695 7 : if (ErrorsFound) {
696 0 : ShowFatalError(state, format("{}{}Errors found getting input. Program terminates.", RoutineName, cCMO_BBRadiator_Water));
697 : }
698 :
699 : // Setup Report variables for the Coils
700 24 : for (BaseboardNum = 1; BaseboardNum <= NumHWBaseboards; ++BaseboardNum) {
701 : // CurrentModuleObject='ZoneHVAC:Baseboard:RadiantConvective:Water'
702 17 : auto &thisHWBaseboard = state.dataHWBaseboardRad->HWBaseboard(BaseboardNum);
703 34 : SetupOutputVariable(state,
704 : "Baseboard Total Heating Rate",
705 : Constant::Units::W,
706 17 : thisHWBaseboard.TotPower,
707 : OutputProcessor::TimeStepType::System,
708 : OutputProcessor::StoreType::Average,
709 17 : thisHWBaseboard.Name);
710 :
711 34 : SetupOutputVariable(state,
712 : "Baseboard Convective Heating Rate",
713 : Constant::Units::W,
714 17 : thisHWBaseboard.ConvPower,
715 : OutputProcessor::TimeStepType::System,
716 : OutputProcessor::StoreType::Average,
717 17 : thisHWBaseboard.Name);
718 34 : SetupOutputVariable(state,
719 : "Baseboard Radiant Heating Rate",
720 : Constant::Units::W,
721 17 : thisHWBaseboard.RadPower,
722 : OutputProcessor::TimeStepType::System,
723 : OutputProcessor::StoreType::Average,
724 17 : thisHWBaseboard.Name);
725 34 : SetupOutputVariable(state,
726 : "Baseboard Total Heating Energy",
727 : Constant::Units::J,
728 17 : thisHWBaseboard.TotEnergy,
729 : OutputProcessor::TimeStepType::System,
730 : OutputProcessor::StoreType::Sum,
731 17 : thisHWBaseboard.Name,
732 : Constant::eResource::EnergyTransfer,
733 : OutputProcessor::Group::HVAC,
734 : OutputProcessor::EndUseCat::Baseboard);
735 :
736 34 : SetupOutputVariable(state,
737 : "Baseboard Convective Heating Energy",
738 : Constant::Units::J,
739 17 : thisHWBaseboard.ConvEnergy,
740 : OutputProcessor::TimeStepType::System,
741 : OutputProcessor::StoreType::Sum,
742 17 : thisHWBaseboard.Name);
743 34 : SetupOutputVariable(state,
744 : "Baseboard Radiant Heating Energy",
745 : Constant::Units::J,
746 17 : thisHWBaseboard.RadEnergy,
747 : OutputProcessor::TimeStepType::System,
748 : OutputProcessor::StoreType::Sum,
749 17 : thisHWBaseboard.Name);
750 34 : SetupOutputVariable(state,
751 : "Baseboard Hot Water Energy",
752 : Constant::Units::J,
753 17 : thisHWBaseboard.Energy,
754 : OutputProcessor::TimeStepType::System,
755 : OutputProcessor::StoreType::Sum,
756 17 : thisHWBaseboard.Name,
757 : Constant::eResource::PlantLoopHeatingDemand,
758 : OutputProcessor::Group::HVAC,
759 : OutputProcessor::EndUseCat::Baseboard);
760 34 : SetupOutputVariable(state,
761 : "Baseboard Hot Water Mass Flow Rate",
762 : Constant::Units::kg_s,
763 17 : thisHWBaseboard.WaterMassFlowRate,
764 : OutputProcessor::TimeStepType::System,
765 : OutputProcessor::StoreType::Average,
766 17 : thisHWBaseboard.Name);
767 34 : SetupOutputVariable(state,
768 : "Baseboard Air Mass Flow Rate",
769 : Constant::Units::kg_s,
770 17 : thisHWBaseboard.AirMassFlowRate,
771 : OutputProcessor::TimeStepType::System,
772 : OutputProcessor::StoreType::Average,
773 17 : thisHWBaseboard.Name);
774 34 : SetupOutputVariable(state,
775 : "Baseboard Air Inlet Temperature",
776 : Constant::Units::C,
777 17 : thisHWBaseboard.AirInletTemp,
778 : OutputProcessor::TimeStepType::System,
779 : OutputProcessor::StoreType::Average,
780 17 : thisHWBaseboard.Name);
781 34 : SetupOutputVariable(state,
782 : "Baseboard Air Outlet Temperature",
783 : Constant::Units::C,
784 17 : thisHWBaseboard.AirOutletTemp,
785 : OutputProcessor::TimeStepType::System,
786 : OutputProcessor::StoreType::Average,
787 17 : thisHWBaseboard.Name);
788 34 : SetupOutputVariable(state,
789 : "Baseboard Water Inlet Temperature",
790 : Constant::Units::C,
791 17 : thisHWBaseboard.WaterInletTemp,
792 : OutputProcessor::TimeStepType::System,
793 : OutputProcessor::StoreType::Average,
794 17 : thisHWBaseboard.Name);
795 34 : SetupOutputVariable(state,
796 : "Baseboard Water Outlet Temperature",
797 : Constant::Units::C,
798 17 : thisHWBaseboard.WaterOutletTemp,
799 : OutputProcessor::TimeStepType::System,
800 : OutputProcessor::StoreType::Average,
801 17 : thisHWBaseboard.Name);
802 : }
803 7 : }
804 :
805 89083 : void InitHWBaseboard(EnergyPlusData &state, int const BaseboardNum, int const ControlledZoneNum, bool const FirstHVACIteration)
806 : {
807 :
808 : // SUBROUTINE INFORMATION:
809 : // AUTHOR Russ Taylor
810 : // Rick Strand
811 : // DATE WRITTEN Nov 1997
812 : // Feb 2001
813 : // MODIFIED Aug 2007 Daeho Kang (Add radiant component)
814 : // Sept 2010 Brent Griffith (plant interactions)
815 :
816 : // PURPOSE OF THIS SUBROUTINE:
817 : // This subroutine initializes the baseboard units, and determines the UA values during simulation.
818 :
819 : // METHODOLOGY EMPLOYED:
820 : // The initialization subroutines both in high temperature radiant radiator
821 : // and convective only baseboard radiator are combined and modified. In addition,
822 : // an UA value calculation by LMTD method is added.
823 : // The heater is assumed to be crossflow with both fluids unmixed.
824 :
825 : // REFERENCES:
826 : // 1. Incropera and DeWitt, Fundamentals of Heat and Mass Transfer
827 : // Chapter 11.3, p. 510, eq. 11.15 and 11.17
828 : // 2. I=B=R Ratings for Baseboards, Baseboard Radiation, Finned Tube (Commercial) Radiation,
829 : // and Indirect Fired Water Heaters, January 2007 Edition
830 :
831 89083 : Real64 constexpr Constant(0.0062); // Constant of linear equation for air mass flow rate
832 89083 : Real64 constexpr Coeff(0.0000275); // Correlation coefficient to capacity
833 : static constexpr std::string_view RoutineName("BaseboardRadiatorWater:InitHWBaseboard");
834 :
835 : int WaterInletNode;
836 : Real64 rho; // local fluid density
837 : Real64 Cp; // local fluid specific heat
838 :
839 89083 : int NumHWBaseboards = state.dataHWBaseboardRad->NumHWBaseboards;
840 89083 : auto &HWBaseboard = state.dataHWBaseboardRad->HWBaseboard(BaseboardNum);
841 :
842 : // Do the one time initializations
843 89083 : if (state.dataHWBaseboardRad->MyOneTimeFlag) {
844 :
845 : // Initialize the environment and sizing flags
846 7 : state.dataHWBaseboardRad->MyEnvrnFlag.dimension(NumHWBaseboards, true);
847 7 : state.dataHWBaseboardRad->MySizeFlag.dimension(NumHWBaseboards, true);
848 7 : state.dataHWBaseboardRad->SetLoopIndexFlag.dimension(NumHWBaseboards, true);
849 7 : state.dataHWBaseboardRad->MyOneTimeFlag = false;
850 :
851 24 : for (auto &hWBB : state.dataHWBaseboardRad->HWBaseboard) {
852 : // Air mass flow rate is obtained from the following linear equation (reset if autosize is used)
853 : // m_dot = 0.0062 + 2.75e-05*q
854 17 : hWBB.ZeroBBSourceSumHATsurf = 0.0;
855 17 : hWBB.QBBRadSource = 0.0;
856 17 : hWBB.QBBRadSrcAvg = 0.0;
857 17 : hWBB.LastQBBRadSrc = 0.0;
858 17 : hWBB.LastSysTimeElapsed = 0.0;
859 17 : hWBB.LastTimeStepSys = 0.0;
860 17 : hWBB.AirMassFlowRateStd = Constant + Coeff * hWBB.RatedCapacity;
861 : }
862 : }
863 :
864 89083 : if (state.dataHWBaseboardRad->SetLoopIndexFlag(BaseboardNum)) {
865 17 : if (allocated(state.dataPlnt->PlantLoop)) {
866 17 : bool errFlag = false;
867 17 : PlantUtilities::ScanPlantLoopsForObject(state, HWBaseboard.Name, HWBaseboard.EquipType, HWBaseboard.plantLoc, errFlag, _, _, _, _, _);
868 17 : if (errFlag) {
869 0 : ShowFatalError(state, "InitHWBaseboard: Program terminated for previous conditions.");
870 : }
871 17 : state.dataHWBaseboardRad->SetLoopIndexFlag(BaseboardNum) = false;
872 : }
873 : }
874 :
875 89100 : if (!state.dataGlobal->SysSizingCalc && state.dataHWBaseboardRad->MySizeFlag(BaseboardNum) &&
876 17 : !state.dataHWBaseboardRad->SetLoopIndexFlag(BaseboardNum)) {
877 : // For each coil, do the sizing once
878 17 : SizeHWBaseboard(state, BaseboardNum);
879 17 : state.dataHWBaseboardRad->MySizeFlag(BaseboardNum) = false;
880 : }
881 :
882 : // Do the Begin Environment initializations
883 89083 : if (state.dataGlobal->BeginEnvrnFlag && state.dataHWBaseboardRad->MyEnvrnFlag(BaseboardNum)) {
884 : // Initialize
885 102 : WaterInletNode = HWBaseboard.WaterInletNode;
886 :
887 102 : rho = state.dataPlnt->PlantLoop(HWBaseboard.plantLoc.loopNum).glycol->getDensity(state, Constant::HWInitConvTemp, RoutineName);
888 :
889 102 : HWBaseboard.WaterMassFlowRateMax = rho * HWBaseboard.WaterVolFlowRateMax;
890 :
891 102 : PlantUtilities::InitComponentNodes(state, 0.0, HWBaseboard.WaterMassFlowRateMax, HWBaseboard.WaterInletNode, HWBaseboard.WaterOutletNode);
892 :
893 102 : state.dataLoopNodes->Node(WaterInletNode).Temp = 60.0;
894 :
895 102 : Cp = state.dataPlnt->PlantLoop(HWBaseboard.plantLoc.loopNum)
896 102 : .glycol->getSpecificHeat(state, state.dataLoopNodes->Node(WaterInletNode).Temp, RoutineName);
897 :
898 102 : state.dataLoopNodes->Node(WaterInletNode).Enthalpy = Cp * state.dataLoopNodes->Node(WaterInletNode).Temp;
899 102 : state.dataLoopNodes->Node(WaterInletNode).Quality = 0.0;
900 102 : state.dataLoopNodes->Node(WaterInletNode).Press = 0.0;
901 102 : state.dataLoopNodes->Node(WaterInletNode).HumRat = 0.0;
902 :
903 102 : HWBaseboard.ZeroBBSourceSumHATsurf = 0.0;
904 102 : HWBaseboard.QBBRadSource = 0.0;
905 102 : HWBaseboard.QBBRadSrcAvg = 0.0;
906 102 : HWBaseboard.LastQBBRadSrc = 0.0;
907 102 : HWBaseboard.LastSysTimeElapsed = 0.0;
908 102 : HWBaseboard.LastTimeStepSys = 0.0;
909 :
910 102 : state.dataHWBaseboardRad->MyEnvrnFlag(BaseboardNum) = false;
911 : }
912 :
913 89083 : if (!state.dataGlobal->BeginEnvrnFlag) {
914 88549 : state.dataHWBaseboardRad->MyEnvrnFlag(BaseboardNum) = true;
915 : }
916 :
917 89083 : if (state.dataGlobal->BeginTimeStepFlag && FirstHVACIteration) {
918 31094 : int ZoneNum = HWBaseboard.ZonePtr;
919 31094 : HWBaseboard.ZeroBBSourceSumHATsurf = state.dataHeatBal->Zone(ZoneNum).sumHATsurf(state);
920 31094 : HWBaseboard.QBBRadSrcAvg = 0.0;
921 31094 : HWBaseboard.LastQBBRadSrc = 0.0;
922 31094 : HWBaseboard.LastSysTimeElapsed = 0.0;
923 31094 : HWBaseboard.LastTimeStepSys = 0.0;
924 : }
925 :
926 : // Do the every time step initializations
927 89083 : WaterInletNode = HWBaseboard.WaterInletNode;
928 89083 : int ZoneNode = state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).ZoneNode;
929 89083 : HWBaseboard.WaterMassFlowRate = state.dataLoopNodes->Node(WaterInletNode).MassFlowRate;
930 89083 : HWBaseboard.WaterInletTemp = state.dataLoopNodes->Node(WaterInletNode).Temp;
931 89083 : HWBaseboard.WaterInletEnthalpy = state.dataLoopNodes->Node(WaterInletNode).Enthalpy;
932 89083 : HWBaseboard.AirInletTemp = state.dataLoopNodes->Node(ZoneNode).Temp;
933 89083 : HWBaseboard.AirInletHumRat = state.dataLoopNodes->Node(ZoneNode).HumRat;
934 :
935 89083 : HWBaseboard.TotPower = 0.0;
936 89083 : HWBaseboard.Power = 0.0;
937 89083 : HWBaseboard.ConvPower = 0.0;
938 89083 : HWBaseboard.RadPower = 0.0;
939 89083 : HWBaseboard.TotEnergy = 0.0;
940 89083 : HWBaseboard.Energy = 0.0;
941 89083 : HWBaseboard.ConvEnergy = 0.0;
942 89083 : HWBaseboard.RadEnergy = 0.0;
943 89083 : }
944 :
945 17 : void SizeHWBaseboard(EnergyPlusData &state, int const BaseboardNum)
946 : {
947 :
948 : // SUBROUTINE INFORMATION:
949 : // AUTHOR Fred Buhl
950 : // DATE WRITTEN February 2002
951 : // MODIFIED August 2009 Daeho Kang (Add UA autosizing by LMTD)
952 : // Aug 2013 Daeho Kang, add component sizing table entries
953 : // July 2014, B.Nigusse, added scalable sizing
954 :
955 : // PURPOSE OF THIS SUBROUTINE:
956 : // This subroutine is for sizing hot water baseboard components
957 :
958 : // METHODOLOGY EMPLOYED:
959 : // Obtains flow rates from the zone sizing arrays and plant sizing data.
960 :
961 : // SUBROUTINE PARAMETER DEFINITIONS:
962 17 : Real64 constexpr AirInletTempStd(18.0); // I=B=R rating document
963 17 : Real64 constexpr CPAirStd(1005.0); // Average specific heat of air at between 25C and 40C in J/kg-k
964 17 : Real64 constexpr Constant(0.0062); // Constant of linear equation for air mass flow rate
965 17 : Real64 constexpr Coeff(0.0000275); // Correlation coefficient to capacity
966 : static constexpr std::string_view RoutineName("SizeHWBaseboard");
967 : static constexpr std::string_view RoutineNameFull("BaseboardRadiatorWater:SizeHWBaseboard");
968 :
969 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
970 : Real64 WaterInletTempStd;
971 : Real64 WaterOutletTempStd;
972 : Real64 AirOutletTempStd;
973 : Real64 DeltaT1;
974 : Real64 DeltaT2;
975 : Real64 LMTD;
976 : Real64 AirMassFlowRate;
977 : Real64 WaterMassFlowRateStd;
978 : Real64 rho; // local fluid density
979 : Real64 Cp; // local fluid specific heat
980 : Real64 TempSize; // autosized value of coil input field
981 :
982 17 : int PltSizHeatNum = 0;
983 17 : Real64 DesCoilLoad = 0.0;
984 17 : bool ErrorsFound = false;
985 17 : Real64 WaterVolFlowRateMaxDes = 0.0;
986 17 : Real64 WaterVolFlowRateMaxUser = 0.0;
987 17 : Real64 RatedCapacityDes = 0.0;
988 17 : state.dataSize->DataScalableCapSizingON = false;
989 :
990 17 : auto &hWBaseboard = state.dataHWBaseboardRad->HWBaseboard(BaseboardNum);
991 17 : if (state.dataSize->CurZoneEqNum > 0) {
992 17 : auto &zoneEqSizing = state.dataSize->ZoneEqSizing(state.dataSize->CurZoneEqNum);
993 :
994 17 : std::string CompType = cCMO_BBRadiator_Water;
995 17 : std::string CompName = hWBaseboard.Name;
996 17 : state.dataSize->DataHeatSizeRatio = 1.0;
997 17 : state.dataSize->DataFracOfAutosizedHeatingCapacity = 1.0;
998 17 : state.dataSize->DataZoneNumber = hWBaseboard.ZonePtr;
999 17 : int SizingMethod = HVAC::HeatingCapacitySizing;
1000 17 : int FieldNum = 3; // IDD numeric field number where input field description is found
1001 17 : std::string SizingString = state.dataHWBaseboardRad->HWBaseboardNumericFields(BaseboardNum).FieldNames(FieldNum) + " [W]";
1002 17 : int CapSizingMethod = hWBaseboard.HeatingCapMethod;
1003 17 : zoneEqSizing.SizingMethod(SizingMethod) = CapSizingMethod;
1004 17 : if (CapSizingMethod == DataSizing::HeatingDesignCapacity || CapSizingMethod == DataSizing::CapacityPerFloorArea ||
1005 : CapSizingMethod == DataSizing::FractionOfAutosizedHeatingCapacity) {
1006 17 : if (CapSizingMethod == DataSizing::HeatingDesignCapacity) {
1007 17 : if (hWBaseboard.ScaledHeatingCapacity == DataSizing::AutoSize) {
1008 17 : CheckZoneSizing(state, CompType, CompName);
1009 17 : zoneEqSizing.HeatingCapacity = true;
1010 17 : zoneEqSizing.DesHeatingLoad = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).NonAirSysDesHeatLoad;
1011 : }
1012 17 : TempSize = hWBaseboard.ScaledHeatingCapacity;
1013 :
1014 0 : } else if (CapSizingMethod == DataSizing::CapacityPerFloorArea) {
1015 0 : zoneEqSizing.HeatingCapacity = true;
1016 0 : zoneEqSizing.DesHeatingLoad =
1017 0 : hWBaseboard.ScaledHeatingCapacity * state.dataHeatBal->Zone(state.dataSize->DataZoneNumber).FloorArea;
1018 0 : TempSize = zoneEqSizing.DesHeatingLoad;
1019 0 : state.dataSize->DataScalableCapSizingON = true;
1020 0 : } else if (CapSizingMethod == DataSizing::FractionOfAutosizedHeatingCapacity) {
1021 0 : CheckZoneSizing(state, CompType, CompName);
1022 0 : zoneEqSizing.HeatingCapacity = true;
1023 0 : state.dataSize->DataFracOfAutosizedHeatingCapacity = hWBaseboard.ScaledHeatingCapacity;
1024 0 : zoneEqSizing.DesHeatingLoad = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).NonAirSysDesHeatLoad;
1025 0 : TempSize = DataSizing::AutoSize;
1026 0 : state.dataSize->DataScalableCapSizingON = true;
1027 : } else {
1028 0 : TempSize = hWBaseboard.ScaledHeatingCapacity;
1029 : }
1030 17 : bool PrintFlag = false;
1031 17 : bool errorsFound = false;
1032 17 : HeatingCapacitySizer sizerHeatingCapacity;
1033 17 : sizerHeatingCapacity.overrideSizingString(SizingString);
1034 17 : sizerHeatingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
1035 17 : TempSize = sizerHeatingCapacity.size(state, TempSize, errorsFound);
1036 17 : if (hWBaseboard.ScaledHeatingCapacity == DataSizing::AutoSize) {
1037 17 : hWBaseboard.RatedCapacity = DataSizing::AutoSize;
1038 : } else {
1039 0 : hWBaseboard.RatedCapacity = TempSize;
1040 : }
1041 17 : RatedCapacityDes = TempSize;
1042 17 : state.dataSize->DataScalableCapSizingON = false;
1043 17 : }
1044 17 : }
1045 :
1046 : // find the appropriate heating Plant Sizing object
1047 17 : PltSizHeatNum = state.dataPlnt->PlantLoop(hWBaseboard.plantLoc.loopNum).PlantSizNum;
1048 :
1049 17 : if (PltSizHeatNum > 0) {
1050 17 : if (state.dataSize->CurZoneEqNum > 0) {
1051 17 : bool FlowAutoSize = false;
1052 :
1053 17 : if (hWBaseboard.WaterVolFlowRateMax == DataSizing::AutoSize) {
1054 17 : FlowAutoSize = true;
1055 : }
1056 17 : if (!FlowAutoSize && !state.dataSize->ZoneSizingRunDone) { // Simulation continue
1057 0 : if (hWBaseboard.WaterVolFlowRateMax > 0.0) {
1058 0 : BaseSizer::reportSizerOutput(state,
1059 : cCMO_BBRadiator_Water,
1060 : hWBaseboard.Name,
1061 : "User-Specified Maximum Water Flow Rate [m3/s]",
1062 : hWBaseboard.WaterVolFlowRateMax);
1063 : }
1064 : } else {
1065 17 : CheckZoneSizing(state, cCMO_BBRadiator_Water, hWBaseboard.Name);
1066 17 : DesCoilLoad = RatedCapacityDes;
1067 17 : if (DesCoilLoad >= HVAC::SmallLoad) {
1068 17 : Cp = state.dataPlnt->PlantLoop(hWBaseboard.plantLoc.loopNum)
1069 17 : .glycol->getSpecificHeat(state, Constant::HWInitConvTemp, RoutineName);
1070 : rho =
1071 17 : state.dataPlnt->PlantLoop(hWBaseboard.plantLoc.loopNum).glycol->getDensity(state, Constant::HWInitConvTemp, RoutineName);
1072 17 : WaterVolFlowRateMaxDes = DesCoilLoad / (state.dataSize->PlantSizData(PltSizHeatNum).DeltaT * Cp * rho);
1073 : } else {
1074 0 : WaterVolFlowRateMaxDes = 0.0;
1075 : }
1076 :
1077 17 : if (FlowAutoSize) {
1078 17 : hWBaseboard.WaterVolFlowRateMax = WaterVolFlowRateMaxDes;
1079 17 : BaseSizer::reportSizerOutput(
1080 : state, cCMO_BBRadiator_Water, hWBaseboard.Name, "Design Size Maximum Water Flow Rate [m3/s]", WaterVolFlowRateMaxDes);
1081 : } else { // Hard-sized with sizing data
1082 0 : if (hWBaseboard.WaterVolFlowRateMax > 0.0 && WaterVolFlowRateMaxDes > 0.0) {
1083 0 : WaterVolFlowRateMaxUser = hWBaseboard.WaterVolFlowRateMax;
1084 0 : BaseSizer::reportSizerOutput(state,
1085 : cCMO_BBRadiator_Water,
1086 : hWBaseboard.Name,
1087 : "Design Size Maximum Water Flow Rate [m3/s]",
1088 : WaterVolFlowRateMaxDes,
1089 : "User-Specified Maximum Water Flow Rate [m3/s]",
1090 : WaterVolFlowRateMaxUser);
1091 0 : if (state.dataGlobal->DisplayExtraWarnings) {
1092 0 : if ((std::abs(WaterVolFlowRateMaxDes - WaterVolFlowRateMaxUser) / WaterVolFlowRateMaxUser) >
1093 0 : state.dataSize->AutoVsHardSizingThreshold) {
1094 0 : ShowMessage(state,
1095 0 : format("SizeHWBaseboard: Potential issue with equipment sizing for "
1096 : "ZoneHVAC:Baseboard:RadiantConvective:Water=\"{}\".",
1097 0 : hWBaseboard.Name));
1098 0 : ShowContinueError(state,
1099 0 : format("User-Specified Maximum Water Flow Rate of {:.5R} [m3/s]", WaterVolFlowRateMaxUser));
1100 0 : ShowContinueError(
1101 0 : state, format("differs from Design Size Maximum Water Flow Rate of {:.5R} [m3/s]", WaterVolFlowRateMaxDes));
1102 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
1103 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
1104 : }
1105 : }
1106 : }
1107 : }
1108 : }
1109 17 : if (hWBaseboard.WaterTempAvg > 0.0 && hWBaseboard.WaterMassFlowRateStd > 0.0 && hWBaseboard.RatedCapacity > 0.0) {
1110 0 : DesCoilLoad = hWBaseboard.RatedCapacity;
1111 0 : WaterMassFlowRateStd = hWBaseboard.WaterMassFlowRateStd;
1112 17 : } else if (hWBaseboard.RatedCapacity == DataSizing::AutoSize || hWBaseboard.RatedCapacity == 0.0) {
1113 17 : DesCoilLoad = RatedCapacityDes;
1114 : rho =
1115 17 : state.dataPlnt->PlantLoop(hWBaseboard.plantLoc.loopNum).glycol->getDensity(state, Constant::HWInitConvTemp, RoutineNameFull);
1116 17 : WaterMassFlowRateStd = hWBaseboard.WaterVolFlowRateMax * rho;
1117 : }
1118 17 : if (DesCoilLoad >= HVAC::SmallLoad) {
1119 : // Calculate UA value
1120 : // Air mass flow rate is obtained from the following linear equation
1121 : // m_dot = 0.0062 + 2.75e-05*q
1122 17 : AirMassFlowRate = Constant + Coeff * DesCoilLoad;
1123 : Cp =
1124 17 : state.dataPlnt->PlantLoop(hWBaseboard.plantLoc.loopNum).glycol->getSpecificHeat(state, hWBaseboard.WaterTempAvg, RoutineName);
1125 17 : WaterInletTempStd = (DesCoilLoad / (2.0 * WaterMassFlowRateStd * Cp)) + hWBaseboard.WaterTempAvg;
1126 17 : WaterOutletTempStd = std::abs((2.0 * hWBaseboard.WaterTempAvg) - WaterInletTempStd);
1127 17 : AirOutletTempStd = (DesCoilLoad / (AirMassFlowRate * CPAirStd)) + AirInletTempStd;
1128 17 : hWBaseboard.AirMassFlowRateStd = AirMassFlowRate;
1129 : // Check Ta,out < Tw,in
1130 17 : if (AirOutletTempStd >= WaterInletTempStd) {
1131 0 : ShowSevereError(state, format("SizeHWBaseboard: ZoneHVAC:Baseboard:RadiantConvective:Water=\"{}\".", hWBaseboard.Name));
1132 0 : ShowContinueError(state, "...Air Outlet temperature must be below the Water Inlet temperature");
1133 0 : ShowContinueError(
1134 : state,
1135 0 : format("...Air Outlet Temperature=[{:.2R}], Water Inlet Temperature=[{:.2R}].", AirOutletTempStd, WaterInletTempStd));
1136 0 : AirOutletTempStd = WaterInletTempStd - 0.01;
1137 0 : ShowContinueError(state, format("...Air Outlet Temperature set to [{:.2R}].", AirOutletTempStd));
1138 : }
1139 : // Check Tw,out < Ta,in
1140 17 : if (AirInletTempStd >= WaterOutletTempStd) {
1141 0 : ShowSevereError(state, format("SizeHWBaseboard: ZoneHVAC:Baseboard:RadiantConvective:Water=\"{}\".", hWBaseboard.Name));
1142 0 : ShowContinueError(state, "...Water Outlet temperature must be below the Air Inlet temperature");
1143 0 : ShowContinueError(
1144 : state,
1145 0 : format("...Air Inlet Temperature=[{:.2R}], Water Outlet Temperature=[{:.2R}].", AirInletTempStd, WaterOutletTempStd));
1146 0 : WaterOutletTempStd = AirInletTempStd + 0.01;
1147 0 : ShowContinueError(state, format("...Water Outlet Temperature set to [{:.2R}].", WaterOutletTempStd));
1148 : }
1149 : // LMTD calculation
1150 17 : DeltaT1 = WaterInletTempStd - AirOutletTempStd;
1151 17 : DeltaT2 = WaterOutletTempStd - AirInletTempStd;
1152 17 : LMTD = (DeltaT1 - DeltaT2) / (std::log(DeltaT1 / DeltaT2));
1153 17 : hWBaseboard.UA = DesCoilLoad / LMTD;
1154 : } else {
1155 0 : hWBaseboard.UA = 0.0;
1156 : }
1157 : // Report an UA value
1158 17 : BaseSizer::reportSizerOutput(state, cCMO_BBRadiator_Water, hWBaseboard.Name, "U-Factor times Area [W/C]", hWBaseboard.UA);
1159 : }
1160 : } else {
1161 : // if there is no heating Sizing:Plant object and autosizing was requested, issue an error message
1162 0 : if (hWBaseboard.WaterVolFlowRateMax == DataSizing::AutoSize || hWBaseboard.RatedCapacity == DataSizing::AutoSize ||
1163 0 : hWBaseboard.RatedCapacity == 0.0) {
1164 0 : ShowSevereError(state, "Autosizing of hot water baseboard requires a heating loop Sizing:Plant object");
1165 0 : ShowContinueError(state, format("Occurs in Hot Water Baseboard Heater={}", hWBaseboard.Name));
1166 0 : ErrorsFound = true;
1167 : }
1168 : // calculate UA from rated capacities
1169 0 : hWBaseboard.RatedCapacity = RatedCapacityDes;
1170 0 : DesCoilLoad = RatedCapacityDes;
1171 :
1172 0 : if (DesCoilLoad >= HVAC::SmallLoad) {
1173 0 : WaterMassFlowRateStd = hWBaseboard.WaterMassFlowRateStd;
1174 : // m_dot = 0.0062 + 2.75e-05*q
1175 0 : AirMassFlowRate = Constant + Coeff * DesCoilLoad;
1176 0 : Cp = state.dataPlnt->PlantLoop(hWBaseboard.plantLoc.loopNum).glycol->getSpecificHeat(state, hWBaseboard.WaterTempAvg, RoutineName);
1177 0 : WaterInletTempStd = (DesCoilLoad / (2.0 * WaterMassFlowRateStd * Cp)) + hWBaseboard.WaterTempAvg;
1178 0 : WaterOutletTempStd = std::abs((2.0 * hWBaseboard.WaterTempAvg) - WaterInletTempStd);
1179 0 : AirOutletTempStd = (DesCoilLoad / (AirMassFlowRate * CPAirStd)) + AirInletTempStd;
1180 0 : hWBaseboard.AirMassFlowRateStd = AirMassFlowRate;
1181 :
1182 : // Check Ta,out < Tw,in
1183 0 : if (AirOutletTempStd >= WaterInletTempStd) {
1184 0 : ShowSevereError(state, format("SizeHWBaseboard: ZoneHVAC:Baseboard:RadiantConvective:Water=\"{}\".", hWBaseboard.Name));
1185 0 : ShowContinueError(state, "...Air Outlet temperature must be below the Water Inlet temperature");
1186 0 : ShowContinueError(
1187 0 : state, format("...Air Outlet Temperature=[{:.2R}], Water Inlet Temperature=[{:.2R}].", AirOutletTempStd, WaterInletTempStd));
1188 0 : AirOutletTempStd = WaterInletTempStd - 0.01;
1189 0 : ShowContinueError(state, format("...Air Outlet Temperature set to [{:.2R}].", AirOutletTempStd));
1190 : }
1191 : // Check Tw,out < Ta,in
1192 0 : if (AirInletTempStd >= WaterOutletTempStd) {
1193 0 : ShowSevereError(state, format("SizeHWBaseboard: ZoneHVAC:Baseboard:RadiantConvective:Water=\"{}\".", hWBaseboard.Name));
1194 0 : ShowContinueError(state, "...Water Outlet temperature must be below the Air Inlet temperature");
1195 0 : ShowContinueError(
1196 0 : state, format("...Air Inlet Temperature=[{:.2R}], Water Outlet Temperature=[{:.2R}].", AirInletTempStd, WaterOutletTempStd));
1197 0 : WaterOutletTempStd = AirInletTempStd + 0.01;
1198 0 : ShowContinueError(state, format("...Water Outlet Temperature set to [{:.2R}].", WaterOutletTempStd));
1199 : }
1200 : // LMTD calculation
1201 0 : DeltaT1 = WaterInletTempStd - AirOutletTempStd;
1202 0 : DeltaT2 = WaterOutletTempStd - AirInletTempStd;
1203 0 : LMTD = (DeltaT1 - DeltaT2) / (std::log(DeltaT1 / DeltaT2));
1204 0 : hWBaseboard.UA = DesCoilLoad / LMTD;
1205 : } else {
1206 0 : hWBaseboard.UA = 0.0;
1207 : }
1208 : // Report an UA value
1209 0 : BaseSizer::reportSizerOutput(state, cCMO_BBRadiator_Water, hWBaseboard.Name, "U-Factor times Area [W/C]", hWBaseboard.UA);
1210 : }
1211 : // save the design water flow rate for use by the water loop sizing algorithms
1212 17 : PlantUtilities::RegisterPlantCompDesignFlow(state, hWBaseboard.WaterInletNode, hWBaseboard.WaterVolFlowRateMax);
1213 :
1214 17 : if (ErrorsFound) {
1215 0 : ShowFatalError(state, "Preceding sizing errors cause program termination");
1216 : }
1217 17 : }
1218 :
1219 159997 : void CalcHWBaseboard(EnergyPlusData &state, int &BaseboardNum, Real64 &LoadMet)
1220 : {
1221 : // SUBROUTINE INFORMATION:
1222 : // AUTHOR Russ Taylor
1223 : // DATE WRITTEN Nov 1997
1224 : // MODIFIED May 2000 Fred Buhl
1225 : // Aug 2007 Daeho Kang (Add the calculation of radiant heat source)
1226 : // Sep 2011 LKL/BG - resimulate only zones needing it for Radiant systems
1227 :
1228 : // PURPOSE OF THIS SUBROUTINE:
1229 : // This subroutine calculates both the convective and radiant heat transfer rate
1230 : // in a hot water baseboard heater. The heater is assumed to be crossflow with
1231 : // both fluids unmixed. The air flow is buoyancy driven and a constant airflow
1232 : // and a constant airflow velocity of 0.5m/s is assumed.
1233 :
1234 : // REFERENCES:
1235 : // Incropera and DeWitt, Fundamentals of Heat and Mass Transfer
1236 : // Chapter 11.4, p. 523, eq. 11.33
1237 :
1238 : // SUBROUTINE PARAMETER DEFINITIONS:
1239 159997 : Real64 constexpr MinFrac(0.0005); // Minimum fraction that delivers radiant heats to surfaces
1240 : static constexpr std::string_view RoutineName("CalcHWBaseboard");
1241 :
1242 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1243 : Real64 RadHeat;
1244 : Real64 BBHeat;
1245 : Real64 AirOutletTemp;
1246 : Real64 WaterOutletTemp;
1247 : Real64 AirMassFlowRate;
1248 : Real64 CapacitanceAir;
1249 : Real64 CapacitanceWater;
1250 : Real64 CapacitanceMax;
1251 : Real64 CapacitanceMin;
1252 : Real64 CapacityRatio;
1253 : Real64 NTU;
1254 : Real64 Effectiveness;
1255 : Real64 AA;
1256 : Real64 BB;
1257 : Real64 CC;
1258 : Real64 Cp;
1259 :
1260 159997 : auto &hWBaseboard = state.dataHWBaseboardRad->HWBaseboard(BaseboardNum);
1261 :
1262 159997 : int const ZoneNum = hWBaseboard.ZonePtr;
1263 159997 : Real64 QZnReq = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).RemainingOutputReqToHeatSP;
1264 159997 : Real64 AirInletTemp = hWBaseboard.AirInletTemp;
1265 159997 : Real64 WaterInletTemp = hWBaseboard.WaterInletTemp;
1266 159997 : Real64 WaterMassFlowRate = state.dataLoopNodes->Node(hWBaseboard.WaterInletNode).MassFlowRate;
1267 :
1268 234544 : if (QZnReq > HVAC::SmallLoad && !state.dataZoneEnergyDemand->CurDeadBandOrSetback(ZoneNum) && (hWBaseboard.availSched->getCurrentVal() > 0) &&
1269 74547 : (WaterMassFlowRate > 0.0)) {
1270 :
1271 : HWBaseboardDesignData const &HWBaseboardDesignDataObject{
1272 68613 : state.dataHWBaseboardRad->HWBaseboardDesignObject(hWBaseboard.DesignObjectPtr)}; // Contains the data for the design object
1273 :
1274 : // Calculate air mass flow rate
1275 68613 : AirMassFlowRate = hWBaseboard.AirMassFlowRateStd * (WaterMassFlowRate / hWBaseboard.WaterMassFlowRateMax);
1276 68613 : CapacitanceAir = Psychrometrics::PsyCpAirFnW(hWBaseboard.AirInletHumRat) * AirMassFlowRate;
1277 68613 : Cp = state.dataPlnt->PlantLoop(hWBaseboard.plantLoc.loopNum).glycol->getSpecificHeat(state, WaterInletTemp, RoutineName);
1278 :
1279 68613 : CapacitanceWater = Cp * WaterMassFlowRate;
1280 68613 : CapacitanceMax = max(CapacitanceAir, CapacitanceWater);
1281 68613 : CapacitanceMin = min(CapacitanceAir, CapacitanceWater);
1282 68613 : CapacityRatio = CapacitanceMin / CapacitanceMax;
1283 68613 : NTU = hWBaseboard.UA / CapacitanceMin;
1284 :
1285 : // The effectiveness is given by the following formula:
1286 : // Effectiveness = 1. - EXP((1./CapacityRatio)*(NTU)**0.22*(EXP(-CapacityRatio*(NTU)**0.78)-1.))
1287 : // To prevent possible underflows (numbers smaller than the computer can handle) we must break
1288 : // the calculation up into steps and check the size of the exponential arguments.
1289 68613 : AA = -CapacityRatio * std::pow(NTU, 0.78);
1290 68613 : if (AA < -20.0) {
1291 66 : BB = 0.0;
1292 : } else {
1293 68547 : BB = std::exp(AA);
1294 : }
1295 68613 : CC = (1.0 / CapacityRatio) * std::pow(NTU, 0.22) * (BB - 1.0);
1296 68613 : if (CC < -20.0) {
1297 11 : Effectiveness = 1.0;
1298 : } else {
1299 68602 : Effectiveness = 1.0 - std::exp(CC);
1300 : }
1301 :
1302 68613 : AirOutletTemp = AirInletTemp + Effectiveness * CapacitanceMin * (WaterInletTemp - AirInletTemp) / CapacitanceAir;
1303 68613 : WaterOutletTemp = WaterInletTemp - CapacitanceAir * (AirOutletTemp - AirInletTemp) / CapacitanceWater;
1304 68613 : BBHeat = CapacitanceWater * (WaterInletTemp - WaterOutletTemp);
1305 68613 : RadHeat = BBHeat * HWBaseboardDesignDataObject.FracRadiant;
1306 68613 : hWBaseboard.QBBRadSource = RadHeat;
1307 :
1308 68613 : if (HWBaseboardDesignDataObject.FracRadiant <= MinFrac) {
1309 31186 : LoadMet = BBHeat;
1310 : } else {
1311 :
1312 : // Now, distribute the radiant energy of all systems to the appropriate surfaces, to people, and the air
1313 37427 : DistributeBBRadGains(state);
1314 : // Now "simulate" the system by recalculating the heat balances
1315 37427 : HeatBalanceSurfaceManager::CalcHeatBalanceOutsideSurf(state, ZoneNum);
1316 :
1317 37427 : HeatBalanceSurfaceManager::CalcHeatBalanceInsideSurf(state, ZoneNum);
1318 :
1319 : // Here an assumption is made regarding radiant heat transfer to people.
1320 : // While the radiant heat transfer to people array will be used by the thermal comfort
1321 : // routines, the energy transfer to people would get lost from the perspective
1322 : // of the heat balance. So, to avoid this net loss of energy which clearly
1323 : // gets added to the zones, we must account for it somehow. This assumption
1324 : // that all energy radiated to people is converted to convective energy is
1325 : // not very precise, but at least it conserves energy. The system impact to heat balance
1326 : // should include this.
1327 :
1328 37427 : LoadMet = (state.dataHeatBal->Zone(ZoneNum).sumHATsurf(state) - hWBaseboard.ZeroBBSourceSumHATsurf) +
1329 37427 : (BBHeat * hWBaseboard.FracConvect) + (RadHeat * HWBaseboardDesignDataObject.FracDistribPerson);
1330 : }
1331 68613 : hWBaseboard.WaterOutletEnthalpy = hWBaseboard.WaterInletEnthalpy - BBHeat / WaterMassFlowRate;
1332 : } else {
1333 91384 : CapacitanceWater = 0.0;
1334 91384 : CapacitanceMax = 0.0;
1335 91384 : CapacitanceMin = 0.0;
1336 91384 : NTU = 0.0;
1337 91384 : Effectiveness = 0.0;
1338 91384 : AirOutletTemp = AirInletTemp;
1339 91384 : WaterOutletTemp = WaterInletTemp;
1340 91384 : BBHeat = 0.0;
1341 91384 : LoadMet = 0.0;
1342 91384 : RadHeat = 0.0;
1343 91384 : WaterMassFlowRate = 0.0;
1344 91384 : AirMassFlowRate = 0.0;
1345 91384 : hWBaseboard.QBBRadSource = 0.0;
1346 91384 : hWBaseboard.WaterOutletEnthalpy = hWBaseboard.WaterInletEnthalpy;
1347 91384 : PlantUtilities::SetActuatedBranchFlowRate(state, WaterMassFlowRate, hWBaseboard.WaterInletNode, hWBaseboard.plantLoc, false);
1348 : }
1349 :
1350 159997 : hWBaseboard.WaterOutletTemp = WaterOutletTemp;
1351 159997 : hWBaseboard.AirOutletTemp = AirOutletTemp;
1352 159997 : hWBaseboard.WaterMassFlowRate = WaterMassFlowRate;
1353 159997 : hWBaseboard.AirMassFlowRate = AirMassFlowRate;
1354 159997 : hWBaseboard.TotPower = LoadMet;
1355 159997 : hWBaseboard.Power = BBHeat;
1356 159997 : hWBaseboard.ConvPower = BBHeat - RadHeat;
1357 159997 : hWBaseboard.RadPower = RadHeat;
1358 159997 : }
1359 :
1360 89083 : void UpdateHWBaseboard(EnergyPlusData &state, int const BaseboardNum)
1361 : {
1362 :
1363 : // SUBROUTINE INFORMATION:
1364 : // AUTHOR Russ Taylor
1365 : // Rick Strand
1366 : // DATE WRITTEN Nov 1997
1367 : // February 2001
1368 : // MODIFIED Aug 2007 Daeho Kang (Add the update of radiant source)
1369 :
1370 : // METHODOLOGY EMPLOYED:
1371 : // The update subroutines both in high temperature radiant radiator
1372 : // and convective only baseboard radiator are combined and modified.
1373 :
1374 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1375 : int WaterInletNode;
1376 : int WaterOutletNode;
1377 89083 : auto &thisHWBB = state.dataHWBaseboardRad->HWBaseboard(BaseboardNum);
1378 :
1379 89083 : if (state.dataGlobal->BeginEnvrnFlag && state.dataHWBaseboardRad->MyEnvrnFlag2) {
1380 42 : state.dataHWBaseboardRad->Iter = 0;
1381 42 : state.dataHWBaseboardRad->MyEnvrnFlag2 = false;
1382 : }
1383 89083 : if (!state.dataGlobal->BeginEnvrnFlag) {
1384 88549 : state.dataHWBaseboardRad->MyEnvrnFlag2 = true;
1385 : }
1386 :
1387 : // First, update the running average if necessary...
1388 89083 : if (thisHWBB.LastSysTimeElapsed == state.dataHVACGlobal->SysTimeElapsed) {
1389 82573 : thisHWBB.QBBRadSrcAvg -= thisHWBB.LastQBBRadSrc * thisHWBB.LastTimeStepSys / state.dataGlobal->TimeStepZone;
1390 : }
1391 : // Update the running average and the "last" values with the current values of the appropriate variables
1392 89083 : thisHWBB.QBBRadSrcAvg += thisHWBB.QBBRadSource * state.dataHVACGlobal->TimeStepSys / state.dataGlobal->TimeStepZone;
1393 :
1394 89083 : thisHWBB.LastQBBRadSrc = thisHWBB.QBBRadSource;
1395 89083 : thisHWBB.LastSysTimeElapsed = state.dataHVACGlobal->SysTimeElapsed;
1396 89083 : thisHWBB.LastTimeStepSys = state.dataHVACGlobal->TimeStepSys;
1397 :
1398 89083 : WaterInletNode = thisHWBB.WaterInletNode;
1399 89083 : WaterOutletNode = thisHWBB.WaterOutletNode;
1400 :
1401 : // Set the outlet air nodes of the Baseboard
1402 : // Set the outlet water nodes for the Coil
1403 89083 : PlantUtilities::SafeCopyPlantNode(state, WaterInletNode, WaterOutletNode);
1404 89083 : state.dataLoopNodes->Node(WaterOutletNode).Temp = thisHWBB.WaterOutletTemp;
1405 89083 : state.dataLoopNodes->Node(WaterOutletNode).Enthalpy = thisHWBB.WaterOutletEnthalpy;
1406 89083 : }
1407 :
1408 2799877 : void UpdateBBRadSourceValAvg(EnergyPlusData &state, bool &HWBaseboardSysOn) // .TRUE. if the radiant system has run this zone time step
1409 : {
1410 :
1411 : // SUBROUTINE INFORMATION:
1412 : // AUTHOR Rick Strand
1413 : // DATE WRITTEN February 2001
1414 : // MODIFIED Aug 2007 Daeho Kang (Modification only for baseboard)
1415 :
1416 : // PURPOSE OF THIS SUBROUTINE:
1417 : // To transfer the average value of the heat source over the entire
1418 : // zone time step back to the heat balance routines so that the heat
1419 : // balance algorithms can simulate one last time with the average source
1420 : // to maintain some reasonable amount of continuity and energy balance
1421 : // in the temperature and flux histories.
1422 :
1423 : // METHODOLOGY EMPLOYED:
1424 : // All of the record keeping for the average term is done in the Update
1425 : // routine so the only other thing that this subroutine does is check to
1426 : // see if the system was even on. If any average term is non-zero, then
1427 : // one or more of the radiant systems was running.
1428 :
1429 2799877 : HWBaseboardSysOn = false;
1430 :
1431 : // If there are no baseboards in this input file, just RETURN
1432 2799877 : if (state.dataHWBaseboardRad->NumHWBaseboards == 0) {
1433 2786353 : return;
1434 : }
1435 :
1436 : // If there are baseboards, then we have to check to see if this was running at all...
1437 44640 : for (auto &thisHWBaseboard : state.dataHWBaseboardRad->HWBaseboard) {
1438 31116 : thisHWBaseboard.QBBRadSource = thisHWBaseboard.QBBRadSrcAvg;
1439 31116 : if (thisHWBaseboard.QBBRadSrcAvg != 0.0) {
1440 12096 : HWBaseboardSysOn = true;
1441 : }
1442 : }
1443 :
1444 13524 : DistributeBBRadGains(state); // QBBRadSource has been modified so we need to redistribute gains
1445 : }
1446 :
1447 50951 : void DistributeBBRadGains(EnergyPlusData &state)
1448 : {
1449 :
1450 : // SUBROUTINE INFORMATION:
1451 : // AUTHOR Rick Strand
1452 : // DATE WRITTEN February 2001
1453 : // MODIFIED Aug. 2007 Daeho Kang (Modification only for baseboard)
1454 : // April 2010 Brent Griffith, max limit to protect surface temperature calcs
1455 :
1456 : // PURPOSE OF THIS SUBROUTINE:
1457 : // To distribute the gains from the hot water baseboard heater
1458 : // as specified in the user input file. This includes distribution
1459 : // of long wavelength radiant gains to surfaces and "people."
1460 :
1461 : // METHODOLOGY EMPLOYED:
1462 : // We must cycle through all of the radiant systems because each
1463 : // surface could feel the effect of more than one radiant system.
1464 : // Note that the energy radiated to people is assumed to affect them
1465 : // but them it is assumed to be convected to the air.
1466 :
1467 : // SUBROUTINE PARAMETER DEFINITIONS:
1468 50951 : Real64 constexpr SmallestArea(0.001); // Smallest area in meters squared (to avoid a divide by zero)
1469 :
1470 : Real64 ThisSurfIntensity; // temporary for W/m2 term for rad on a surface
1471 :
1472 : // Initialize arrays
1473 156921 : for (auto &thisHWBB : state.dataHWBaseboardRad->HWBaseboard) {
1474 403540 : for (int radSurfNum = 1; radSurfNum <= thisHWBB.TotSurfToDistrib; ++radSurfNum) {
1475 297570 : int surfNum = thisHWBB.SurfacePtr(radSurfNum);
1476 297570 : state.dataHeatBalFanSys->surfQRadFromHVAC(surfNum).HWBaseboard = 0.0;
1477 : }
1478 : }
1479 50951 : state.dataHeatBalFanSys->ZoneQHWBaseboardToPerson = 0.0;
1480 :
1481 156921 : for (auto &thisHWBB : state.dataHWBaseboardRad->HWBaseboard) {
1482 : HWBaseboardDesignData const &HWBaseboardDesignDataObject =
1483 105970 : state.dataHWBaseboardRad->HWBaseboardDesignObject(thisHWBB.DesignObjectPtr); // Contains the data for the design object
1484 105970 : int ZoneNum = thisHWBB.ZonePtr;
1485 105970 : if (ZoneNum <= 0) {
1486 0 : continue;
1487 : }
1488 105970 : state.dataHeatBalFanSys->ZoneQHWBaseboardToPerson(ZoneNum) += thisHWBB.QBBRadSource * HWBaseboardDesignDataObject.FracDistribPerson;
1489 :
1490 403540 : for (int RadSurfNum = 1; RadSurfNum <= thisHWBB.TotSurfToDistrib; ++RadSurfNum) {
1491 297570 : int SurfNum = thisHWBB.SurfacePtr(RadSurfNum);
1492 297570 : if (state.dataSurface->Surface(SurfNum).Area > SmallestArea) {
1493 297570 : ThisSurfIntensity = (thisHWBB.QBBRadSource * thisHWBB.FracDistribToSurf(RadSurfNum) / state.dataSurface->Surface(SurfNum).Area);
1494 297570 : state.dataHeatBalFanSys->surfQRadFromHVAC(SurfNum).HWBaseboard += ThisSurfIntensity;
1495 : // CR 8074, trap for excessive intensity (throws off surface balance )
1496 297570 : if (ThisSurfIntensity > DataHeatBalFanSys::MaxRadHeatFlux) {
1497 0 : ShowSevereError(state, "DistributeBBRadGains: excessive thermal radiation heat flux intensity detected");
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("Radiation intensity = {:.2R} [W/m2]", ThisSurfIntensity));
1502 0 : ShowContinueError(state, format("Assign a larger surface area or more surfaces in {}", cCMO_BBRadiator_Water));
1503 0 : ShowFatalError(state, "DistributeBBRadGains: excessive thermal radiation heat flux intensity detected");
1504 : }
1505 : } else {
1506 0 : ShowSevereError(state, "DistributeBBRadGains: surface not large enough to receive thermal radiation heat flux");
1507 0 : ShowContinueError(state, format("Surface = {}", state.dataSurface->Surface(SurfNum).Name));
1508 0 : ShowContinueError(state, format("Surface area = {:.3R} [m2]", state.dataSurface->Surface(SurfNum).Area));
1509 0 : ShowContinueError(state, format("Occurs in {} = {}", cCMO_BBRadiator_Water, thisHWBB.Name));
1510 0 : ShowContinueError(state, format("Assign a larger surface area or more surfaces in {}", cCMO_BBRadiator_Water));
1511 0 : ShowFatalError(state, "DistributeBBRadGains: surface not large enough to receive thermal radiation heat flux");
1512 : }
1513 : }
1514 : }
1515 50951 : }
1516 :
1517 89083 : void ReportHWBaseboard(EnergyPlusData &state, int const BaseboardNum)
1518 : {
1519 :
1520 : // SUBROUTINE INFORMATION:
1521 : // AUTHOR Daeho Kang
1522 : // DATE WRITTEN Aug 2007
1523 :
1524 89083 : auto &thisHWBB = state.dataHWBaseboardRad->HWBaseboard(BaseboardNum);
1525 89083 : Real64 const timeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
1526 :
1527 89083 : thisHWBB.TotEnergy = thisHWBB.TotPower * timeStepSysSec;
1528 89083 : thisHWBB.Energy = thisHWBB.Power * timeStepSysSec;
1529 89083 : thisHWBB.ConvEnergy = thisHWBB.ConvPower * timeStepSysSec;
1530 89083 : thisHWBB.RadEnergy = thisHWBB.RadPower * timeStepSysSec;
1531 89083 : }
1532 :
1533 0 : void UpdateHWBaseboardPlantConnection(EnergyPlusData &state,
1534 : int const BaseboardTypeNum, // type index
1535 : std::string const &BaseboardName, // component name
1536 : [[maybe_unused]] int const EquipFlowCtrl, // Flow control mode for the equipment
1537 : [[maybe_unused]] int const LoopNum, // Plant loop index for where called from
1538 : [[maybe_unused]] const DataPlant::LoopSideLocation LoopSide, // Plant loop side index for where called from
1539 : int &CompIndex, // Chiller number pointer
1540 : [[maybe_unused]] bool const FirstHVACIteration,
1541 : bool &InitLoopEquip // If not zero, calculate the max load for operating conditions
1542 : )
1543 : {
1544 :
1545 : // SUBROUTINE INFORMATION:
1546 : // AUTHOR Brent Griffith
1547 : // DATE WRITTEN Sept. 2010
1548 :
1549 : // PURPOSE OF THIS SUBROUTINE:
1550 : // update sim routine called from plant
1551 :
1552 : // METHODOLOGY EMPLOYED:
1553 : // check input, provide comp index, call utility routines
1554 :
1555 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1556 0 : int const NumHWBaseboards = state.dataHWBaseboardRad->NumHWBaseboards;
1557 : int BaseboardNum;
1558 :
1559 : // Find the correct baseboard
1560 0 : if (CompIndex == 0) {
1561 0 : BaseboardNum = Util::FindItemInList(BaseboardName, state.dataHWBaseboardRad->HWBaseboard, &HWBaseboardParams::Name);
1562 0 : if (BaseboardNum == 0) {
1563 0 : ShowFatalError(state, format("UpdateHWBaseboardPlantConnection: Specified baseboard not valid ={}", BaseboardName));
1564 : }
1565 0 : CompIndex = BaseboardNum;
1566 : } else {
1567 0 : BaseboardNum = CompIndex;
1568 0 : if (BaseboardNum > NumHWBaseboards || BaseboardNum < 1) {
1569 0 : ShowFatalError(
1570 : state,
1571 0 : format("UpdateHWBaseboardPlantConnection: Invalid CompIndex passed={}, Number of baseboards={}, Entered baseboard name={}",
1572 : BaseboardNum,
1573 : NumHWBaseboards,
1574 : BaseboardName));
1575 : }
1576 0 : if (state.dataGlobal->KickOffSimulation) {
1577 0 : if (BaseboardName != state.dataHWBaseboardRad->HWBaseboard(BaseboardNum).Name) {
1578 0 : ShowFatalError(state,
1579 0 : format("UpdateHWBaseboardPlantConnection: Invalid CompIndex passed={}, baseboard name={}, stored baseboard Name "
1580 : "for that index={}",
1581 : BaseboardNum,
1582 : BaseboardName,
1583 0 : state.dataHWBaseboardRad->HWBaseboard(BaseboardNum).Name));
1584 : }
1585 0 : if (BaseboardTypeNum != static_cast<int>(DataPlant::PlantEquipmentType::Baseboard_Rad_Conv_Water)) {
1586 0 : ShowFatalError(state,
1587 0 : format("UpdateHWBaseboardPlantConnection: Invalid CompIndex passed={}, baseboard name={}, stored baseboard Name "
1588 : "for that index={}",
1589 : BaseboardNum,
1590 : BaseboardName,
1591 0 : DataPlant::PlantEquipTypeNames[BaseboardTypeNum]));
1592 : }
1593 : }
1594 : }
1595 :
1596 0 : if (InitLoopEquip) {
1597 0 : return;
1598 : }
1599 :
1600 0 : auto &thisHWBaseboard = state.dataHWBaseboardRad->HWBaseboard(BaseboardNum);
1601 0 : PlantUtilities::PullCompInterconnectTrigger(state,
1602 0 : thisHWBaseboard.plantLoc,
1603 0 : thisHWBaseboard.BBLoadReSimIndex,
1604 0 : thisHWBaseboard.plantLoc,
1605 : DataPlant::CriteriaType::HeatTransferRate,
1606 : thisHWBaseboard.Power);
1607 :
1608 0 : PlantUtilities::PullCompInterconnectTrigger(state,
1609 0 : thisHWBaseboard.plantLoc,
1610 0 : thisHWBaseboard.BBMassFlowReSimIndex,
1611 0 : thisHWBaseboard.plantLoc,
1612 : DataPlant::CriteriaType::MassFlowRate,
1613 : thisHWBaseboard.WaterMassFlowRate);
1614 :
1615 0 : PlantUtilities::PullCompInterconnectTrigger(state,
1616 0 : thisHWBaseboard.plantLoc,
1617 0 : thisHWBaseboard.BBInletTempFlowReSimIndex,
1618 0 : thisHWBaseboard.plantLoc,
1619 : DataPlant::CriteriaType::Temperature,
1620 : thisHWBaseboard.WaterOutletTemp);
1621 : }
1622 :
1623 : //*****************************************************************************************
1624 :
1625 : } // namespace HWBaseboardRadiator
1626 :
1627 : } // namespace EnergyPlus
|