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 0 : 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 0 : if (state.dataHWBaseboardRad->GetInputFlag) {
131 0 : GetHWBaseboardInput(state);
132 0 : state.dataHWBaseboardRad->GetInputFlag = false;
133 : }
134 :
135 0 : int const NumHWBaseboards = state.dataHWBaseboardRad->NumHWBaseboards;
136 :
137 : // Find the correct Baseboard Equipment
138 0 : if (CompIndex == 0) {
139 0 : BaseboardNum = Util::FindItemInList(EquipName, state.dataHWBaseboardRad->HWBaseboard, &HWBaseboardParams::Name);
140 0 : if (BaseboardNum == 0) {
141 0 : ShowFatalError(state, format("SimHWBaseboard: Unit not found={}", EquipName));
142 : }
143 0 : CompIndex = BaseboardNum;
144 : } else {
145 0 : BaseboardNum = CompIndex;
146 0 : 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 0 : if (state.dataHWBaseboardRad->CheckEquipName(BaseboardNum)) {
154 0 : 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 0 : state.dataHWBaseboardRad->CheckEquipName(BaseboardNum) = false;
162 : }
163 : }
164 :
165 0 : if (CompIndex > 0) {
166 0 : auto &HWBaseboard = state.dataHWBaseboardRad->HWBaseboard(BaseboardNum);
167 :
168 0 : HWBaseboardDesignData const &HWBaseboardDesignDataObject = state.dataHWBaseboardRad->HWBaseboardDesignObject(
169 : HWBaseboard.DesignObjectPtr); // Contains the data for variable flow hydronic systems
170 :
171 0 : InitHWBaseboard(state, BaseboardNum, ControlledZoneNum, FirstHVACIteration);
172 :
173 0 : 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 0 : if (FirstHVACIteration) {
178 0 : MaxWaterFlow = HWBaseboard.WaterMassFlowRateMax;
179 0 : MinWaterFlow = 0.0;
180 : } else {
181 0 : MaxWaterFlow = state.dataLoopNodes->Node(HWBaseboard.WaterInletNode).MassFlowRateMaxAvail;
182 0 : MinWaterFlow = state.dataLoopNodes->Node(HWBaseboard.WaterInletNode).MassFlowRateMinAvail;
183 : }
184 :
185 0 : switch (HWBaseboard.EquipType) {
186 0 : case DataPlant::PlantEquipmentType::Baseboard_Rad_Conv_Water: { // 'ZoneHVAC:Baseboard:RadiantConvective:Water'
187 0 : ControlCompOutput(state,
188 0 : HWBaseboard.Name,
189 : cCMO_BBRadiator_Water,
190 : BaseboardNum,
191 : FirstHVACIteration,
192 : QZnReq,
193 : HWBaseboard.WaterInletNode,
194 : MaxWaterFlow,
195 : MinWaterFlow,
196 0 : HWBaseboardDesignDataObject.Offset,
197 0 : HWBaseboard.ControlCompTypeNum,
198 0 : HWBaseboard.CompErrIndex,
199 : _,
200 : _,
201 : _,
202 : _,
203 : _,
204 0 : HWBaseboard.plantLoc);
205 0 : } 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 0 : PowerMet = HWBaseboard.TotPower;
214 :
215 0 : UpdateHWBaseboard(state, BaseboardNum);
216 :
217 0 : ReportHWBaseboard(state, BaseboardNum);
218 :
219 : } else {
220 0 : ShowFatalError(state, format("SimHWBaseboard: Unit not found={}", EquipName));
221 : }
222 0 : }
223 :
224 1 : 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 1 : Real64 constexpr MaxFraction(1.0);
242 1 : Real64 constexpr MinFraction(0.0);
243 1 : Real64 constexpr MaxWaterTempAvg(150.0); // Maximum limit of average water temperature in degree C
244 1 : Real64 constexpr MinWaterTempAvg(20.0); // Minimum limit of average water temperature in degree C
245 1 : Real64 constexpr HighWaterMassFlowRate(10.0); // Maximum limit of water mass flow rate in kg/s
246 1 : Real64 constexpr LowWaterMassFlowRate(0.00001); // Minimum limit of water mass flow rate in kg/s
247 1 : Real64 constexpr MaxWaterFlowRate(10.0); // Maximum limit of water volume flow rate in m3/s
248 1 : Real64 constexpr MinWaterFlowRate(0.00001); // Minimum limit of water volume flow rate in m3/s
249 1 : Real64 constexpr WaterMassFlowDefault(0.063); // Default water mass flow rate in kg/s
250 1 : int constexpr MinDistribSurfaces(1); // Minimum number of surfaces that a baseboard heater can radiate to
251 1 : int constexpr iHeatCAPMAlphaNum(2); // get input index to HW baseboard heating capacity sizing method
252 1 : int constexpr iHeatDesignCapacityNumericNum(3); // get input index to HW baseboard heating capacity
253 1 : int constexpr iHeatCapacityPerFloorAreaNumericNum(1); // get input index to HW baseboard heating capacity per floor area sizing
254 1 : 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 1 : bool ErrorsFound(false); // If errors detected in input
265 :
266 : // Update Nums in state and make local convenience copies
267 2 : int NumHWBaseboards = state.dataHWBaseboardRad->NumHWBaseboards =
268 1 : state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCMO_BBRadiator_Water);
269 2 : int NumHWBaseboardDesignObjs = state.dataHWBaseboardRad->NumHWBaseboardDesignObjs =
270 1 : state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCMO_BBRadiator_Water_Design);
271 :
272 : // Count total number of baseboard units
273 :
274 1 : state.dataHWBaseboardRad->HWBaseboard.allocate(NumHWBaseboards);
275 1 : state.dataHWBaseboardRad->HWBaseboardDesignObject.allocate(NumHWBaseboardDesignObjs);
276 1 : state.dataHWBaseboardRad->CheckEquipName.allocate(NumHWBaseboards);
277 1 : state.dataHWBaseboardRad->HWBaseboardNumericFields.allocate(NumHWBaseboards);
278 1 : Array1D_string HWBaseboardDesignNames;
279 1 : HWBaseboardDesignNames.allocate(NumHWBaseboardDesignObjs);
280 1 : state.dataHWBaseboardRad->CheckEquipName = true;
281 :
282 : // Get the data from the user input related to design data for baseboard heaters
283 2 : for (BaseboardDesignNum = 1; BaseboardDesignNum <= NumHWBaseboardDesignObjs; ++BaseboardDesignNum) {
284 1 : auto &thisHWBaseboardDesign = state.dataHWBaseboardRad->HWBaseboardDesignObject(BaseboardDesignNum);
285 :
286 2 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
287 : cCMO_BBRadiator_Water_Design,
288 : BaseboardDesignNum,
289 1 : state.dataIPShortCut->cAlphaArgs,
290 : NumAlphas,
291 1 : state.dataIPShortCut->rNumericArgs,
292 : NumNumbers,
293 : IOStat,
294 1 : state.dataIPShortCut->lNumericFieldBlanks,
295 1 : state.dataIPShortCut->lAlphaFieldBlanks,
296 1 : state.dataIPShortCut->cAlphaFieldNames,
297 1 : state.dataIPShortCut->cNumericFieldNames);
298 :
299 : // ErrorsFound will be set to True if problem was found, left untouched otherwise
300 1 : GlobalNames::VerifyUniqueBaseboardName(
301 2 : state, cCMO_BBRadiator_Water_Design, state.dataIPShortCut->cAlphaArgs(1), ErrorsFound, cCMO_BBRadiator_Water_Design + " Name");
302 :
303 1 : thisHWBaseboardDesign.designName = state.dataIPShortCut->cAlphaArgs(1); // Name of this baseboard design object
304 1 : HWBaseboardDesignNames(BaseboardDesignNum) = thisHWBaseboardDesign.designName;
305 :
306 : // Determine HW radiant baseboard heating design capacity sizing method
307 1 : thisHWBaseboardDesign.HeatingCapMethod = static_cast<DataSizing::DesignSizingType>(
308 1 : getEnumValue(DataSizing::DesignSizingTypeNamesUC, state.dataIPShortCut->cAlphaArgs(iHeatCAPMAlphaNum)));
309 1 : 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 1 : } 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 1 : thisHWBaseboardDesign.Offset = state.dataIPShortCut->rNumericArgs(3);
369 : // Set default convergence tolerance
370 1 : 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 1 : thisHWBaseboardDesign.FracRadiant = state.dataIPShortCut->rNumericArgs(4);
382 1 : 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 1 : 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 1 : thisHWBaseboardDesign.FracDistribPerson = state.dataIPShortCut->rNumericArgs(5);
404 1 : 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 1 : 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 2 : for (BaseboardNum = 1; BaseboardNum <= NumHWBaseboards; ++BaseboardNum) {
428 1 : auto &thisHWBaseboard = state.dataHWBaseboardRad->HWBaseboard(BaseboardNum);
429 1 : auto &HWBaseboardNumericFields = state.dataHWBaseboardRad->HWBaseboardNumericFields(BaseboardNum);
430 :
431 2 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
432 : cCMO_BBRadiator_Water,
433 : BaseboardNum,
434 1 : state.dataIPShortCut->cAlphaArgs,
435 : NumAlphas,
436 1 : state.dataIPShortCut->rNumericArgs,
437 : NumNumbers,
438 : IOStat,
439 1 : state.dataIPShortCut->lNumericFieldBlanks,
440 1 : state.dataIPShortCut->lAlphaFieldBlanks,
441 1 : state.dataIPShortCut->cAlphaFieldNames,
442 1 : state.dataIPShortCut->cNumericFieldNames);
443 :
444 1 : ErrorObjectHeader eoh{routineName, cCMO_BBRadiator_Water, state.dataIPShortCut->cAlphaArgs(1)};
445 :
446 1 : HWBaseboardNumericFields.FieldNames.allocate(NumNumbers);
447 1 : HWBaseboardNumericFields.FieldNames = state.dataIPShortCut->cNumericFieldNames;
448 :
449 : // ErrorsFound will be set to True if problem was found, left untouched otherwise
450 1 : GlobalNames::VerifyUniqueBaseboardName(
451 2 : state, cCMO_BBRadiator_Water, state.dataIPShortCut->cAlphaArgs(1), ErrorsFound, cCMO_BBRadiator_Water + " Name");
452 :
453 1 : thisHWBaseboard.Name = state.dataIPShortCut->cAlphaArgs(1); // Name of this baseboard
454 1 : thisHWBaseboard.EquipType = DataPlant::PlantEquipmentType::Baseboard_Rad_Conv_Water; //'ZoneHVAC:Baseboard:RadiantConvective:Water'
455 :
456 1 : thisHWBaseboard.designObjectName = state.dataIPShortCut->cAlphaArgs(2); // Name of the design object for this baseboard
457 1 : thisHWBaseboard.DesignObjectPtr = Util::FindItemInList(thisHWBaseboard.designObjectName, HWBaseboardDesignNames);
458 : HWBaseboardDesignData &HWBaseboardDesignDataObject =
459 1 : state.dataHWBaseboardRad->HWBaseboardDesignObject(thisHWBaseboard.DesignObjectPtr); // Contains the data for the design object
460 :
461 : // Get schedule
462 1 : if (state.dataIPShortCut->lAlphaFieldBlanks(3)) {
463 1 : thisHWBaseboard.availSched = Sched::GetScheduleAlwaysOn(state);
464 0 : } 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 1 : thisHWBaseboard.WaterInletNode = GetOnlySingleNode(state,
471 1 : state.dataIPShortCut->cAlphaArgs(4),
472 : ErrorsFound,
473 : DataLoopNode::ConnectionObjectType::ZoneHVACBaseboardRadiantConvectiveWater,
474 1 : 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 2 : thisHWBaseboard.WaterOutletNode = GetOnlySingleNode(state,
482 1 : state.dataIPShortCut->cAlphaArgs(5),
483 : ErrorsFound,
484 : DataLoopNode::ConnectionObjectType::ZoneHVACBaseboardRadiantConvectiveWater,
485 1 : state.dataIPShortCut->cAlphaArgs(1),
486 : DataLoopNode::NodeFluidType::Water,
487 : DataLoopNode::ConnectionType::Outlet,
488 : NodeInputManager::CompFluidStream::Primary,
489 : DataLoopNode::ObjectIsNotParent);
490 2 : BranchNodeConnections::TestCompSet(state,
491 : cCMO_BBRadiator_Water,
492 1 : state.dataIPShortCut->cAlphaArgs(1),
493 1 : state.dataIPShortCut->cAlphaArgs(4),
494 1 : state.dataIPShortCut->cAlphaArgs(5),
495 : "Hot Water Nodes");
496 :
497 1 : thisHWBaseboard.WaterTempAvg = state.dataIPShortCut->rNumericArgs(1);
498 1 : 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 1 : } 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 1 : thisHWBaseboard.WaterMassFlowRateStd = state.dataIPShortCut->rNumericArgs(2);
519 1 : if (thisHWBaseboard.WaterMassFlowRateStd < LowWaterMassFlowRate - 0.0001 ||
520 1 : 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 1 : thisHWBaseboard.HeatingCapMethod = static_cast<int>(HWBaseboardDesignDataObject.HeatingCapMethod);
533 1 : if (thisHWBaseboard.HeatingCapMethod == DataSizing::HeatingDesignCapacity) {
534 1 : if (!state.dataIPShortCut->lNumericFieldBlanks(iHeatDesignCapacityNumericNum)) {
535 1 : thisHWBaseboard.ScaledHeatingCapacity = state.dataIPShortCut->rNumericArgs(iHeatDesignCapacityNumericNum);
536 1 : 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 1 : thisHWBaseboard.WaterVolFlowRateMax = state.dataIPShortCut->rNumericArgs(4);
570 1 : 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 1 : } 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 1 : 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 1 : thisHWBaseboard.FracConvect = 1.0 - HWBaseboardDesignDataObject.FracRadiant;
601 : }
602 :
603 1 : 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 1 : 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 1 : thisHWBaseboard.SurfacePtr.allocate(thisHWBaseboard.TotSurfToDistrib);
621 1 : thisHWBaseboard.SurfacePtr = 0;
622 1 : thisHWBaseboard.FracDistribToSurf.allocate(thisHWBaseboard.TotSurfToDistrib);
623 1 : thisHWBaseboard.FracDistribToSurf = 0.0;
624 :
625 1 : thisHWBaseboard.ZonePtr =
626 1 : DataZoneEquipment::GetZoneEquipControlledZoneNum(state, DataZoneEquipment::ZoneEquipType::BaseboardWater, thisHWBaseboard.Name);
627 :
628 1 : Real64 AllFracsSummed = HWBaseboardDesignDataObject.FracDistribPerson;
629 2 : for (SurfNum = 1; SurfNum <= thisHWBaseboard.TotSurfToDistrib; ++SurfNum) {
630 2 : thisHWBaseboard.SurfacePtr(SurfNum) =
631 1 : HeatBalanceIntRadExchange::GetRadiantSystemSurface(state,
632 : cCMO_BBRadiator_Water,
633 1 : thisHWBaseboard.Name,
634 : thisHWBaseboard.ZonePtr,
635 1 : state.dataIPShortCut->cAlphaArgs(SurfNum + 5),
636 : ErrorsFound);
637 1 : thisHWBaseboard.FracDistribToSurf(SurfNum) = state.dataIPShortCut->rNumericArgs(SurfNum + 4);
638 1 : 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 1 : 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 1 : if (thisHWBaseboard.SurfacePtr(SurfNum) != 0) {
659 1 : state.dataSurface->surfIntConv(thisHWBaseboard.SurfacePtr(SurfNum)).getsRadiantHeat = true;
660 1 : state.dataSurface->allGetsRadiantHeatSurfaceList.emplace_back(thisHWBaseboard.SurfacePtr(SurfNum));
661 : }
662 :
663 1 : AllFracsSummed += thisHWBaseboard.FracDistribToSurf(SurfNum);
664 : } // Surfaces
665 :
666 1 : 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 1 : if ((AllFracsSummed < (MaxFraction - 0.01)) &&
675 0 : (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 1 : 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 2 : for (BaseboardNum = 1; BaseboardNum <= NumHWBaseboards; ++BaseboardNum) {
692 : // CurrentModuleObject='ZoneHVAC:Baseboard:RadiantConvective:Water'
693 1 : auto &thisHWBaseboard = state.dataHWBaseboardRad->HWBaseboard(BaseboardNum);
694 2 : SetupOutputVariable(state,
695 : "Baseboard Total Heating Rate",
696 : Constant::Units::W,
697 1 : thisHWBaseboard.TotPower,
698 : OutputProcessor::TimeStepType::System,
699 : OutputProcessor::StoreType::Average,
700 1 : thisHWBaseboard.Name);
701 :
702 2 : SetupOutputVariable(state,
703 : "Baseboard Convective Heating Rate",
704 : Constant::Units::W,
705 1 : thisHWBaseboard.ConvPower,
706 : OutputProcessor::TimeStepType::System,
707 : OutputProcessor::StoreType::Average,
708 1 : thisHWBaseboard.Name);
709 2 : SetupOutputVariable(state,
710 : "Baseboard Radiant Heating Rate",
711 : Constant::Units::W,
712 1 : thisHWBaseboard.RadPower,
713 : OutputProcessor::TimeStepType::System,
714 : OutputProcessor::StoreType::Average,
715 1 : thisHWBaseboard.Name);
716 2 : SetupOutputVariable(state,
717 : "Baseboard Total Heating Energy",
718 : Constant::Units::J,
719 1 : thisHWBaseboard.TotEnergy,
720 : OutputProcessor::TimeStepType::System,
721 : OutputProcessor::StoreType::Sum,
722 1 : thisHWBaseboard.Name,
723 : Constant::eResource::EnergyTransfer,
724 : OutputProcessor::Group::HVAC,
725 : OutputProcessor::EndUseCat::Baseboard);
726 :
727 2 : SetupOutputVariable(state,
728 : "Baseboard Convective Heating Energy",
729 : Constant::Units::J,
730 1 : thisHWBaseboard.ConvEnergy,
731 : OutputProcessor::TimeStepType::System,
732 : OutputProcessor::StoreType::Sum,
733 1 : thisHWBaseboard.Name);
734 2 : SetupOutputVariable(state,
735 : "Baseboard Radiant Heating Energy",
736 : Constant::Units::J,
737 1 : thisHWBaseboard.RadEnergy,
738 : OutputProcessor::TimeStepType::System,
739 : OutputProcessor::StoreType::Sum,
740 1 : thisHWBaseboard.Name);
741 2 : SetupOutputVariable(state,
742 : "Baseboard Hot Water Energy",
743 : Constant::Units::J,
744 1 : thisHWBaseboard.Energy,
745 : OutputProcessor::TimeStepType::System,
746 : OutputProcessor::StoreType::Sum,
747 1 : thisHWBaseboard.Name,
748 : Constant::eResource::PlantLoopHeatingDemand,
749 : OutputProcessor::Group::HVAC,
750 : OutputProcessor::EndUseCat::Baseboard);
751 2 : SetupOutputVariable(state,
752 : "Baseboard Hot Water Mass Flow Rate",
753 : Constant::Units::kg_s,
754 1 : thisHWBaseboard.WaterMassFlowRate,
755 : OutputProcessor::TimeStepType::System,
756 : OutputProcessor::StoreType::Average,
757 1 : thisHWBaseboard.Name);
758 2 : SetupOutputVariable(state,
759 : "Baseboard Air Mass Flow Rate",
760 : Constant::Units::kg_s,
761 1 : thisHWBaseboard.AirMassFlowRate,
762 : OutputProcessor::TimeStepType::System,
763 : OutputProcessor::StoreType::Average,
764 1 : thisHWBaseboard.Name);
765 2 : SetupOutputVariable(state,
766 : "Baseboard Air Inlet Temperature",
767 : Constant::Units::C,
768 1 : thisHWBaseboard.AirInletTemp,
769 : OutputProcessor::TimeStepType::System,
770 : OutputProcessor::StoreType::Average,
771 1 : thisHWBaseboard.Name);
772 2 : SetupOutputVariable(state,
773 : "Baseboard Air Outlet Temperature",
774 : Constant::Units::C,
775 1 : thisHWBaseboard.AirOutletTemp,
776 : OutputProcessor::TimeStepType::System,
777 : OutputProcessor::StoreType::Average,
778 1 : thisHWBaseboard.Name);
779 2 : SetupOutputVariable(state,
780 : "Baseboard Water Inlet Temperature",
781 : Constant::Units::C,
782 1 : thisHWBaseboard.WaterInletTemp,
783 : OutputProcessor::TimeStepType::System,
784 : OutputProcessor::StoreType::Average,
785 1 : thisHWBaseboard.Name);
786 2 : SetupOutputVariable(state,
787 : "Baseboard Water Outlet Temperature",
788 : Constant::Units::C,
789 1 : thisHWBaseboard.WaterOutletTemp,
790 : OutputProcessor::TimeStepType::System,
791 : OutputProcessor::StoreType::Average,
792 1 : thisHWBaseboard.Name);
793 : }
794 1 : }
795 :
796 0 : 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 0 : Real64 constexpr Constant(0.0062); // Constant of linear equation for air mass flow rate
823 0 : 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 0 : int NumHWBaseboards = state.dataHWBaseboardRad->NumHWBaseboards;
831 0 : auto &HWBaseboard = state.dataHWBaseboardRad->HWBaseboard(BaseboardNum);
832 :
833 : // Do the one time initializations
834 0 : if (state.dataHWBaseboardRad->MyOneTimeFlag) {
835 :
836 : // Initialize the environment and sizing flags
837 0 : state.dataHWBaseboardRad->MyEnvrnFlag.dimension(NumHWBaseboards, true);
838 0 : state.dataHWBaseboardRad->MySizeFlag.dimension(NumHWBaseboards, true);
839 0 : state.dataHWBaseboardRad->SetLoopIndexFlag.dimension(NumHWBaseboards, true);
840 0 : state.dataHWBaseboardRad->MyOneTimeFlag = false;
841 :
842 0 : 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 0 : hWBB.ZeroBBSourceSumHATsurf = 0.0;
846 0 : hWBB.QBBRadSource = 0.0;
847 0 : hWBB.QBBRadSrcAvg = 0.0;
848 0 : hWBB.LastQBBRadSrc = 0.0;
849 0 : hWBB.LastSysTimeElapsed = 0.0;
850 0 : hWBB.LastTimeStepSys = 0.0;
851 0 : hWBB.AirMassFlowRateStd = Constant + Coeff * hWBB.RatedCapacity;
852 : }
853 : }
854 :
855 0 : if (state.dataHWBaseboardRad->SetLoopIndexFlag(BaseboardNum)) {
856 0 : if (allocated(state.dataPlnt->PlantLoop)) {
857 0 : bool errFlag = false;
858 0 : PlantUtilities::ScanPlantLoopsForObject(state, HWBaseboard.Name, HWBaseboard.EquipType, HWBaseboard.plantLoc, errFlag, _, _, _, _, _);
859 0 : if (errFlag) {
860 0 : ShowFatalError(state, "InitHWBaseboard: Program terminated for previous conditions.");
861 : }
862 0 : state.dataHWBaseboardRad->SetLoopIndexFlag(BaseboardNum) = false;
863 : }
864 : }
865 :
866 0 : if (!state.dataGlobal->SysSizingCalc && state.dataHWBaseboardRad->MySizeFlag(BaseboardNum) &&
867 0 : !state.dataHWBaseboardRad->SetLoopIndexFlag(BaseboardNum)) {
868 : // For each coil, do the sizing once
869 0 : SizeHWBaseboard(state, BaseboardNum);
870 0 : state.dataHWBaseboardRad->MySizeFlag(BaseboardNum) = false;
871 : }
872 :
873 : // Do the Begin Environment initializations
874 0 : if (state.dataGlobal->BeginEnvrnFlag && state.dataHWBaseboardRad->MyEnvrnFlag(BaseboardNum)) {
875 : // Initialize
876 0 : WaterInletNode = HWBaseboard.WaterInletNode;
877 :
878 0 : rho = state.dataPlnt->PlantLoop(HWBaseboard.plantLoc.loopNum).glycol->getDensity(state, Constant::HWInitConvTemp, RoutineName);
879 :
880 0 : HWBaseboard.WaterMassFlowRateMax = rho * HWBaseboard.WaterVolFlowRateMax;
881 :
882 0 : PlantUtilities::InitComponentNodes(state, 0.0, HWBaseboard.WaterMassFlowRateMax, HWBaseboard.WaterInletNode, HWBaseboard.WaterOutletNode);
883 :
884 0 : state.dataLoopNodes->Node(WaterInletNode).Temp = 60.0;
885 :
886 0 : Cp = state.dataPlnt->PlantLoop(HWBaseboard.plantLoc.loopNum)
887 0 : .glycol->getSpecificHeat(state, state.dataLoopNodes->Node(WaterInletNode).Temp, RoutineName);
888 :
889 0 : state.dataLoopNodes->Node(WaterInletNode).Enthalpy = Cp * state.dataLoopNodes->Node(WaterInletNode).Temp;
890 0 : state.dataLoopNodes->Node(WaterInletNode).Quality = 0.0;
891 0 : state.dataLoopNodes->Node(WaterInletNode).Press = 0.0;
892 0 : state.dataLoopNodes->Node(WaterInletNode).HumRat = 0.0;
893 :
894 0 : HWBaseboard.ZeroBBSourceSumHATsurf = 0.0;
895 0 : HWBaseboard.QBBRadSource = 0.0;
896 0 : HWBaseboard.QBBRadSrcAvg = 0.0;
897 0 : HWBaseboard.LastQBBRadSrc = 0.0;
898 0 : HWBaseboard.LastSysTimeElapsed = 0.0;
899 0 : HWBaseboard.LastTimeStepSys = 0.0;
900 :
901 0 : state.dataHWBaseboardRad->MyEnvrnFlag(BaseboardNum) = false;
902 : }
903 :
904 0 : if (!state.dataGlobal->BeginEnvrnFlag) {
905 0 : state.dataHWBaseboardRad->MyEnvrnFlag(BaseboardNum) = true;
906 : }
907 :
908 0 : if (state.dataGlobal->BeginTimeStepFlag && FirstHVACIteration) {
909 0 : int ZoneNum = HWBaseboard.ZonePtr;
910 0 : HWBaseboard.ZeroBBSourceSumHATsurf = state.dataHeatBal->Zone(ZoneNum).sumHATsurf(state);
911 0 : HWBaseboard.QBBRadSrcAvg = 0.0;
912 0 : HWBaseboard.LastQBBRadSrc = 0.0;
913 0 : HWBaseboard.LastSysTimeElapsed = 0.0;
914 0 : HWBaseboard.LastTimeStepSys = 0.0;
915 : }
916 :
917 : // Do the every time step initializations
918 0 : WaterInletNode = HWBaseboard.WaterInletNode;
919 0 : int ZoneNode = state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).ZoneNode;
920 0 : HWBaseboard.WaterMassFlowRate = state.dataLoopNodes->Node(WaterInletNode).MassFlowRate;
921 0 : HWBaseboard.WaterInletTemp = state.dataLoopNodes->Node(WaterInletNode).Temp;
922 0 : HWBaseboard.WaterInletEnthalpy = state.dataLoopNodes->Node(WaterInletNode).Enthalpy;
923 0 : HWBaseboard.AirInletTemp = state.dataLoopNodes->Node(ZoneNode).Temp;
924 0 : HWBaseboard.AirInletHumRat = state.dataLoopNodes->Node(ZoneNode).HumRat;
925 :
926 0 : HWBaseboard.TotPower = 0.0;
927 0 : HWBaseboard.Power = 0.0;
928 0 : HWBaseboard.ConvPower = 0.0;
929 0 : HWBaseboard.RadPower = 0.0;
930 0 : HWBaseboard.TotEnergy = 0.0;
931 0 : HWBaseboard.Energy = 0.0;
932 0 : HWBaseboard.ConvEnergy = 0.0;
933 0 : HWBaseboard.RadEnergy = 0.0;
934 0 : }
935 :
936 0 : 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 0 : Real64 constexpr AirInletTempStd(18.0); // I=B=R rating document
954 0 : Real64 constexpr CPAirStd(1005.0); // Average specific heat of air at between 25C and 40C in J/kg-k
955 0 : Real64 constexpr Constant(0.0062); // Constant of linear equation for air mass flow rate
956 0 : 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 0 : int PltSizHeatNum = 0;
974 0 : Real64 DesCoilLoad = 0.0;
975 0 : bool ErrorsFound = false;
976 0 : Real64 WaterVolFlowRateMaxDes = 0.0;
977 0 : Real64 WaterVolFlowRateMaxUser = 0.0;
978 0 : Real64 RatedCapacityDes = 0.0;
979 0 : state.dataSize->DataScalableCapSizingON = false;
980 :
981 0 : auto &hWBaseboard = state.dataHWBaseboardRad->HWBaseboard(BaseboardNum);
982 0 : if (state.dataSize->CurZoneEqNum > 0) {
983 0 : auto &zoneEqSizing = state.dataSize->ZoneEqSizing(state.dataSize->CurZoneEqNum);
984 :
985 0 : std::string CompType = cCMO_BBRadiator_Water;
986 0 : std::string CompName = hWBaseboard.Name;
987 0 : state.dataSize->DataHeatSizeRatio = 1.0;
988 0 : state.dataSize->DataFracOfAutosizedHeatingCapacity = 1.0;
989 0 : state.dataSize->DataZoneNumber = hWBaseboard.ZonePtr;
990 0 : int SizingMethod = HVAC::HeatingCapacitySizing;
991 0 : int FieldNum = 3; // IDD numeric field number where input field description is found
992 0 : std::string SizingString = state.dataHWBaseboardRad->HWBaseboardNumericFields(BaseboardNum).FieldNames(FieldNum) + " [W]";
993 0 : int CapSizingMethod = hWBaseboard.HeatingCapMethod;
994 0 : zoneEqSizing.SizingMethod(SizingMethod) = CapSizingMethod;
995 0 : if (CapSizingMethod == DataSizing::HeatingDesignCapacity || CapSizingMethod == DataSizing::CapacityPerFloorArea ||
996 : CapSizingMethod == DataSizing::FractionOfAutosizedHeatingCapacity) {
997 0 : if (CapSizingMethod == DataSizing::HeatingDesignCapacity) {
998 0 : if (hWBaseboard.ScaledHeatingCapacity == DataSizing::AutoSize) {
999 0 : CheckZoneSizing(state, CompType, CompName);
1000 0 : zoneEqSizing.HeatingCapacity = true;
1001 0 : zoneEqSizing.DesHeatingLoad = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).NonAirSysDesHeatLoad;
1002 : }
1003 0 : 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 0 : bool PrintFlag = false;
1022 0 : bool errorsFound = false;
1023 0 : HeatingCapacitySizer sizerHeatingCapacity;
1024 0 : sizerHeatingCapacity.overrideSizingString(SizingString);
1025 0 : sizerHeatingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
1026 0 : TempSize = sizerHeatingCapacity.size(state, TempSize, errorsFound);
1027 0 : if (hWBaseboard.ScaledHeatingCapacity == DataSizing::AutoSize) {
1028 0 : hWBaseboard.RatedCapacity = DataSizing::AutoSize;
1029 : } else {
1030 0 : hWBaseboard.RatedCapacity = TempSize;
1031 : }
1032 0 : RatedCapacityDes = TempSize;
1033 0 : state.dataSize->DataScalableCapSizingON = false;
1034 0 : }
1035 0 : }
1036 :
1037 : // find the appropriate heating Plant Sizing object
1038 0 : PltSizHeatNum = state.dataPlnt->PlantLoop(hWBaseboard.plantLoc.loopNum).PlantSizNum;
1039 :
1040 0 : if (PltSizHeatNum > 0) {
1041 0 : if (state.dataSize->CurZoneEqNum > 0) {
1042 0 : bool FlowAutoSize = false;
1043 :
1044 0 : if (hWBaseboard.WaterVolFlowRateMax == DataSizing::AutoSize) {
1045 0 : FlowAutoSize = true;
1046 : }
1047 0 : 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 0 : CheckZoneSizing(state, cCMO_BBRadiator_Water, hWBaseboard.Name);
1057 0 : DesCoilLoad = RatedCapacityDes;
1058 0 : if (DesCoilLoad >= HVAC::SmallLoad) {
1059 0 : Cp = state.dataPlnt->PlantLoop(hWBaseboard.plantLoc.loopNum)
1060 0 : .glycol->getSpecificHeat(state, Constant::HWInitConvTemp, RoutineName);
1061 : rho =
1062 0 : state.dataPlnt->PlantLoop(hWBaseboard.plantLoc.loopNum).glycol->getDensity(state, Constant::HWInitConvTemp, RoutineName);
1063 0 : WaterVolFlowRateMaxDes = DesCoilLoad / (state.dataSize->PlantSizData(PltSizHeatNum).DeltaT * Cp * rho);
1064 : } else {
1065 0 : WaterVolFlowRateMaxDes = 0.0;
1066 : }
1067 :
1068 0 : if (FlowAutoSize) {
1069 0 : hWBaseboard.WaterVolFlowRateMax = WaterVolFlowRateMaxDes;
1070 0 : 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 0 : if (hWBaseboard.WaterTempAvg > 0.0 && hWBaseboard.WaterMassFlowRateStd > 0.0 && hWBaseboard.RatedCapacity > 0.0) {
1101 0 : DesCoilLoad = hWBaseboard.RatedCapacity;
1102 0 : WaterMassFlowRateStd = hWBaseboard.WaterMassFlowRateStd;
1103 0 : } else if (hWBaseboard.RatedCapacity == DataSizing::AutoSize || hWBaseboard.RatedCapacity == 0.0) {
1104 0 : DesCoilLoad = RatedCapacityDes;
1105 : rho =
1106 0 : state.dataPlnt->PlantLoop(hWBaseboard.plantLoc.loopNum).glycol->getDensity(state, Constant::HWInitConvTemp, RoutineNameFull);
1107 0 : WaterMassFlowRateStd = hWBaseboard.WaterVolFlowRateMax * rho;
1108 : }
1109 0 : 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 0 : AirMassFlowRate = Constant + Coeff * DesCoilLoad;
1114 : Cp =
1115 0 : state.dataPlnt->PlantLoop(hWBaseboard.plantLoc.loopNum).glycol->getSpecificHeat(state, hWBaseboard.WaterTempAvg, RoutineName);
1116 0 : WaterInletTempStd = (DesCoilLoad / (2.0 * WaterMassFlowRateStd * Cp)) + hWBaseboard.WaterTempAvg;
1117 0 : WaterOutletTempStd = std::abs((2.0 * hWBaseboard.WaterTempAvg) - WaterInletTempStd);
1118 0 : AirOutletTempStd = (DesCoilLoad / (AirMassFlowRate * CPAirStd)) + AirInletTempStd;
1119 0 : hWBaseboard.AirMassFlowRateStd = AirMassFlowRate;
1120 : // Check Ta,out < Tw,in
1121 0 : 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 0 : 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 0 : DeltaT1 = WaterInletTempStd - AirOutletTempStd;
1142 0 : DeltaT2 = WaterOutletTempStd - AirInletTempStd;
1143 0 : LMTD = (DeltaT1 - DeltaT2) / (std::log(DeltaT1 / DeltaT2));
1144 0 : hWBaseboard.UA = DesCoilLoad / LMTD;
1145 : } else {
1146 0 : hWBaseboard.UA = 0.0;
1147 : }
1148 : // Report an UA value
1149 0 : 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 0 : PlantUtilities::RegisterPlantCompDesignFlow(state, hWBaseboard.WaterInletNode, hWBaseboard.WaterVolFlowRateMax);
1204 :
1205 0 : if (ErrorsFound) {
1206 0 : ShowFatalError(state, "Preceding sizing errors cause program termination");
1207 : }
1208 0 : }
1209 :
1210 2 : 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 2 : 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 2 : auto &hWBaseboard = state.dataHWBaseboardRad->HWBaseboard(BaseboardNum);
1252 :
1253 2 : int const ZoneNum = hWBaseboard.ZonePtr;
1254 2 : Real64 QZnReq = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).RemainingOutputReqToHeatSP;
1255 2 : Real64 AirInletTemp = hWBaseboard.AirInletTemp;
1256 2 : Real64 WaterInletTemp = hWBaseboard.WaterInletTemp;
1257 2 : Real64 WaterMassFlowRate = state.dataLoopNodes->Node(hWBaseboard.WaterInletNode).MassFlowRate;
1258 :
1259 3 : if (QZnReq > HVAC::SmallLoad && !state.dataZoneEnergyDemand->CurDeadBandOrSetback(ZoneNum) && (hWBaseboard.availSched->getCurrentVal() > 0) &&
1260 1 : (WaterMassFlowRate > 0.0)) {
1261 :
1262 : HWBaseboardDesignData const &HWBaseboardDesignDataObject{
1263 1 : state.dataHWBaseboardRad->HWBaseboardDesignObject(hWBaseboard.DesignObjectPtr)}; // Contains the data for the design object
1264 :
1265 : // Calculate air mass flow rate
1266 1 : AirMassFlowRate = hWBaseboard.AirMassFlowRateStd * (WaterMassFlowRate / hWBaseboard.WaterMassFlowRateMax);
1267 1 : CapacitanceAir = Psychrometrics::PsyCpAirFnW(hWBaseboard.AirInletHumRat) * AirMassFlowRate;
1268 1 : Cp = state.dataPlnt->PlantLoop(hWBaseboard.plantLoc.loopNum).glycol->getSpecificHeat(state, WaterInletTemp, RoutineName);
1269 :
1270 1 : CapacitanceWater = Cp * WaterMassFlowRate;
1271 1 : CapacitanceMax = max(CapacitanceAir, CapacitanceWater);
1272 1 : CapacitanceMin = min(CapacitanceAir, CapacitanceWater);
1273 1 : CapacityRatio = CapacitanceMin / CapacitanceMax;
1274 1 : 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 1 : AA = -CapacityRatio * std::pow(NTU, 0.78);
1281 1 : if (AA < -20.0) {
1282 0 : BB = 0.0;
1283 : } else {
1284 1 : BB = std::exp(AA);
1285 : }
1286 1 : CC = (1.0 / CapacityRatio) * std::pow(NTU, 0.22) * (BB - 1.0);
1287 1 : if (CC < -20.0) {
1288 0 : Effectiveness = 1.0;
1289 : } else {
1290 1 : Effectiveness = 1.0 - std::exp(CC);
1291 : }
1292 :
1293 1 : AirOutletTemp = AirInletTemp + Effectiveness * CapacitanceMin * (WaterInletTemp - AirInletTemp) / CapacitanceAir;
1294 1 : WaterOutletTemp = WaterInletTemp - CapacitanceAir * (AirOutletTemp - AirInletTemp) / CapacitanceWater;
1295 1 : BBHeat = CapacitanceWater * (WaterInletTemp - WaterOutletTemp);
1296 1 : RadHeat = BBHeat * HWBaseboardDesignDataObject.FracRadiant;
1297 1 : hWBaseboard.QBBRadSource = RadHeat;
1298 :
1299 1 : if (HWBaseboardDesignDataObject.FracRadiant <= MinFrac) {
1300 1 : LoadMet = BBHeat;
1301 : } else {
1302 :
1303 : // Now, distribute the radiant energy of all systems to the appropriate surfaces, to people, and the air
1304 0 : DistributeBBRadGains(state);
1305 : // Now "simulate" the system by recalculating the heat balances
1306 0 : HeatBalanceSurfaceManager::CalcHeatBalanceOutsideSurf(state, ZoneNum);
1307 :
1308 0 : 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 0 : LoadMet = (state.dataHeatBal->Zone(ZoneNum).sumHATsurf(state) - hWBaseboard.ZeroBBSourceSumHATsurf) +
1320 0 : (BBHeat * hWBaseboard.FracConvect) + (RadHeat * HWBaseboardDesignDataObject.FracDistribPerson);
1321 : }
1322 1 : hWBaseboard.WaterOutletEnthalpy = hWBaseboard.WaterInletEnthalpy - BBHeat / WaterMassFlowRate;
1323 : } else {
1324 1 : CapacitanceWater = 0.0;
1325 1 : CapacitanceMax = 0.0;
1326 1 : CapacitanceMin = 0.0;
1327 1 : NTU = 0.0;
1328 1 : Effectiveness = 0.0;
1329 1 : AirOutletTemp = AirInletTemp;
1330 1 : WaterOutletTemp = WaterInletTemp;
1331 1 : BBHeat = 0.0;
1332 1 : LoadMet = 0.0;
1333 1 : RadHeat = 0.0;
1334 1 : WaterMassFlowRate = 0.0;
1335 1 : AirMassFlowRate = 0.0;
1336 1 : hWBaseboard.QBBRadSource = 0.0;
1337 1 : hWBaseboard.WaterOutletEnthalpy = hWBaseboard.WaterInletEnthalpy;
1338 1 : PlantUtilities::SetActuatedBranchFlowRate(state, WaterMassFlowRate, hWBaseboard.WaterInletNode, hWBaseboard.plantLoc, false);
1339 : }
1340 :
1341 2 : hWBaseboard.WaterOutletTemp = WaterOutletTemp;
1342 2 : hWBaseboard.AirOutletTemp = AirOutletTemp;
1343 2 : hWBaseboard.WaterMassFlowRate = WaterMassFlowRate;
1344 2 : hWBaseboard.AirMassFlowRate = AirMassFlowRate;
1345 2 : hWBaseboard.TotPower = LoadMet;
1346 2 : hWBaseboard.Power = BBHeat;
1347 2 : hWBaseboard.ConvPower = BBHeat - RadHeat;
1348 2 : hWBaseboard.RadPower = RadHeat;
1349 2 : }
1350 :
1351 0 : 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 0 : auto &thisHWBB = state.dataHWBaseboardRad->HWBaseboard(BaseboardNum);
1369 :
1370 0 : if (state.dataGlobal->BeginEnvrnFlag && state.dataHWBaseboardRad->MyEnvrnFlag2) {
1371 0 : state.dataHWBaseboardRad->Iter = 0;
1372 0 : state.dataHWBaseboardRad->MyEnvrnFlag2 = false;
1373 : }
1374 0 : if (!state.dataGlobal->BeginEnvrnFlag) {
1375 0 : state.dataHWBaseboardRad->MyEnvrnFlag2 = true;
1376 : }
1377 :
1378 : // First, update the running average if necessary...
1379 0 : if (thisHWBB.LastSysTimeElapsed == state.dataHVACGlobal->SysTimeElapsed) {
1380 0 : 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 0 : thisHWBB.QBBRadSrcAvg += thisHWBB.QBBRadSource * state.dataHVACGlobal->TimeStepSys / state.dataGlobal->TimeStepZone;
1384 :
1385 0 : thisHWBB.LastQBBRadSrc = thisHWBB.QBBRadSource;
1386 0 : thisHWBB.LastSysTimeElapsed = state.dataHVACGlobal->SysTimeElapsed;
1387 0 : thisHWBB.LastTimeStepSys = state.dataHVACGlobal->TimeStepSys;
1388 :
1389 0 : WaterInletNode = thisHWBB.WaterInletNode;
1390 0 : WaterOutletNode = thisHWBB.WaterOutletNode;
1391 :
1392 : // Set the outlet air nodes of the Baseboard
1393 : // Set the outlet water nodes for the Coil
1394 0 : PlantUtilities::SafeCopyPlantNode(state, WaterInletNode, WaterOutletNode);
1395 0 : state.dataLoopNodes->Node(WaterOutletNode).Temp = thisHWBB.WaterOutletTemp;
1396 0 : state.dataLoopNodes->Node(WaterOutletNode).Enthalpy = thisHWBB.WaterOutletEnthalpy;
1397 0 : }
1398 :
1399 249945 : 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 249945 : HWBaseboardSysOn = false;
1421 :
1422 : // If there are no baseboards in this input file, just RETURN
1423 249945 : if (state.dataHWBaseboardRad->NumHWBaseboards == 0) return;
1424 :
1425 : // If there are baseboards, then we have to check to see if this was running at all...
1426 0 : for (auto &thisHWBaseboard : state.dataHWBaseboardRad->HWBaseboard) {
1427 0 : thisHWBaseboard.QBBRadSource = thisHWBaseboard.QBBRadSrcAvg;
1428 0 : if (thisHWBaseboard.QBBRadSrcAvg != 0.0) HWBaseboardSysOn = true;
1429 : }
1430 :
1431 0 : DistributeBBRadGains(state); // QBBRadSource has been modified so we need to redistribute gains
1432 : }
1433 :
1434 0 : void DistributeBBRadGains(EnergyPlusData &state)
1435 : {
1436 :
1437 : // SUBROUTINE INFORMATION:
1438 : // AUTHOR Rick Strand
1439 : // DATE WRITTEN February 2001
1440 : // MODIFIED Aug. 2007 Daeho Kang (Modification only for baseboard)
1441 : // April 2010 Brent Griffith, max limit to protect surface temperature calcs
1442 :
1443 : // PURPOSE OF THIS SUBROUTINE:
1444 : // To distribute the gains from the hot water baseboard heater
1445 : // as specified in the user input file. This includes distribution
1446 : // of long wavelength radiant gains to surfaces and "people."
1447 :
1448 : // METHODOLOGY EMPLOYED:
1449 : // We must cycle through all of the radiant systems because each
1450 : // surface could feel the effect of more than one radiant system.
1451 : // Note that the energy radiated to people is assumed to affect them
1452 : // but them it is assumed to be convected to the air.
1453 :
1454 : // SUBROUTINE PARAMETER DEFINITIONS:
1455 0 : Real64 constexpr SmallestArea(0.001); // Smallest area in meters squared (to avoid a divide by zero)
1456 :
1457 : Real64 ThisSurfIntensity; // temporary for W/m2 term for rad on a surface
1458 :
1459 : // Initialize arrays
1460 0 : for (auto &thisHWBB : state.dataHWBaseboardRad->HWBaseboard) {
1461 0 : for (int radSurfNum = 1; radSurfNum <= thisHWBB.TotSurfToDistrib; ++radSurfNum) {
1462 0 : int surfNum = thisHWBB.SurfacePtr(radSurfNum);
1463 0 : state.dataHeatBalFanSys->surfQRadFromHVAC(surfNum).HWBaseboard = 0.0;
1464 : }
1465 : }
1466 0 : state.dataHeatBalFanSys->ZoneQHWBaseboardToPerson = 0.0;
1467 :
1468 0 : for (auto &thisHWBB : state.dataHWBaseboardRad->HWBaseboard) {
1469 : HWBaseboardDesignData const &HWBaseboardDesignDataObject =
1470 0 : state.dataHWBaseboardRad->HWBaseboardDesignObject(thisHWBB.DesignObjectPtr); // Contains the data for the design object
1471 0 : int ZoneNum = thisHWBB.ZonePtr;
1472 0 : if (ZoneNum <= 0) continue;
1473 0 : state.dataHeatBalFanSys->ZoneQHWBaseboardToPerson(ZoneNum) += thisHWBB.QBBRadSource * HWBaseboardDesignDataObject.FracDistribPerson;
1474 :
1475 0 : for (int RadSurfNum = 1; RadSurfNum <= thisHWBB.TotSurfToDistrib; ++RadSurfNum) {
1476 0 : int SurfNum = thisHWBB.SurfacePtr(RadSurfNum);
1477 0 : if (state.dataSurface->Surface(SurfNum).Area > SmallestArea) {
1478 0 : ThisSurfIntensity = (thisHWBB.QBBRadSource * thisHWBB.FracDistribToSurf(RadSurfNum) / state.dataSurface->Surface(SurfNum).Area);
1479 0 : state.dataHeatBalFanSys->surfQRadFromHVAC(SurfNum).HWBaseboard += ThisSurfIntensity;
1480 : // CR 8074, trap for excessive intensity (throws off surface balance )
1481 0 : if (ThisSurfIntensity > DataHeatBalFanSys::MaxRadHeatFlux) {
1482 0 : ShowSevereError(state, "DistributeBBRadGains: excessive thermal radiation heat flux intensity detected");
1483 0 : ShowContinueError(state, format("Surface = {}", state.dataSurface->Surface(SurfNum).Name));
1484 0 : ShowContinueError(state, format("Surface area = {:.3R} [m2]", state.dataSurface->Surface(SurfNum).Area));
1485 0 : ShowContinueError(state, format("Occurs in {} = {}", cCMO_BBRadiator_Water, thisHWBB.Name));
1486 0 : ShowContinueError(state, format("Radiation intensity = {:.2R} [W/m2]", ThisSurfIntensity));
1487 0 : ShowContinueError(state, format("Assign a larger surface area or more surfaces in {}", cCMO_BBRadiator_Water));
1488 0 : ShowFatalError(state, "DistributeBBRadGains: excessive thermal radiation heat flux intensity detected");
1489 : }
1490 : } else {
1491 0 : ShowSevereError(state, "DistributeBBRadGains: surface not large enough to receive thermal radiation heat flux");
1492 0 : ShowContinueError(state, format("Surface = {}", state.dataSurface->Surface(SurfNum).Name));
1493 0 : ShowContinueError(state, format("Surface area = {:.3R} [m2]", state.dataSurface->Surface(SurfNum).Area));
1494 0 : ShowContinueError(state, format("Occurs in {} = {}", cCMO_BBRadiator_Water, thisHWBB.Name));
1495 0 : ShowContinueError(state, format("Assign a larger surface area or more surfaces in {}", cCMO_BBRadiator_Water));
1496 0 : ShowFatalError(state, "DistributeBBRadGains: surface not large enough to receive thermal radiation heat flux");
1497 : }
1498 : }
1499 : }
1500 0 : }
1501 :
1502 0 : void ReportHWBaseboard(EnergyPlusData &state, int const BaseboardNum)
1503 : {
1504 :
1505 : // SUBROUTINE INFORMATION:
1506 : // AUTHOR Daeho Kang
1507 : // DATE WRITTEN Aug 2007
1508 :
1509 0 : auto &thisHWBB = state.dataHWBaseboardRad->HWBaseboard(BaseboardNum);
1510 0 : Real64 const timeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
1511 :
1512 0 : thisHWBB.TotEnergy = thisHWBB.TotPower * timeStepSysSec;
1513 0 : thisHWBB.Energy = thisHWBB.Power * timeStepSysSec;
1514 0 : thisHWBB.ConvEnergy = thisHWBB.ConvPower * timeStepSysSec;
1515 0 : thisHWBB.RadEnergy = thisHWBB.RadPower * timeStepSysSec;
1516 0 : }
1517 :
1518 0 : void UpdateHWBaseboardPlantConnection(EnergyPlusData &state,
1519 : int const BaseboardTypeNum, // type index
1520 : std::string const &BaseboardName, // component name
1521 : [[maybe_unused]] int const EquipFlowCtrl, // Flow control mode for the equipment
1522 : [[maybe_unused]] int const LoopNum, // Plant loop index for where called from
1523 : [[maybe_unused]] const DataPlant::LoopSideLocation LoopSide, // Plant loop side index for where called from
1524 : int &CompIndex, // Chiller number pointer
1525 : [[maybe_unused]] bool const FirstHVACIteration,
1526 : bool &InitLoopEquip // If not zero, calculate the max load for operating conditions
1527 : )
1528 : {
1529 :
1530 : // SUBROUTINE INFORMATION:
1531 : // AUTHOR Brent Griffith
1532 : // DATE WRITTEN Sept. 2010
1533 :
1534 : // PURPOSE OF THIS SUBROUTINE:
1535 : // update sim routine called from plant
1536 :
1537 : // METHODOLOGY EMPLOYED:
1538 : // check input, provide comp index, call utility routines
1539 :
1540 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1541 0 : int const NumHWBaseboards = state.dataHWBaseboardRad->NumHWBaseboards;
1542 : int BaseboardNum;
1543 :
1544 : // Find the correct baseboard
1545 0 : if (CompIndex == 0) {
1546 0 : BaseboardNum = Util::FindItemInList(BaseboardName, state.dataHWBaseboardRad->HWBaseboard, &HWBaseboardParams::Name);
1547 0 : if (BaseboardNum == 0) {
1548 0 : ShowFatalError(state, format("UpdateHWBaseboardPlantConnection: Specified baseboard not valid ={}", BaseboardName));
1549 : }
1550 0 : CompIndex = BaseboardNum;
1551 : } else {
1552 0 : BaseboardNum = CompIndex;
1553 0 : if (BaseboardNum > NumHWBaseboards || BaseboardNum < 1) {
1554 0 : ShowFatalError(
1555 : state,
1556 0 : format("UpdateHWBaseboardPlantConnection: Invalid CompIndex passed={}, Number of baseboards={}, Entered baseboard name={}",
1557 : BaseboardNum,
1558 : NumHWBaseboards,
1559 : BaseboardName));
1560 : }
1561 0 : if (state.dataGlobal->KickOffSimulation) {
1562 0 : if (BaseboardName != state.dataHWBaseboardRad->HWBaseboard(BaseboardNum).Name) {
1563 0 : ShowFatalError(state,
1564 0 : format("UpdateHWBaseboardPlantConnection: Invalid CompIndex passed={}, baseboard name={}, stored baseboard Name "
1565 : "for that index={}",
1566 : BaseboardNum,
1567 : BaseboardName,
1568 0 : state.dataHWBaseboardRad->HWBaseboard(BaseboardNum).Name));
1569 : }
1570 0 : if (BaseboardTypeNum != static_cast<int>(DataPlant::PlantEquipmentType::Baseboard_Rad_Conv_Water)) {
1571 0 : ShowFatalError(state,
1572 0 : format("UpdateHWBaseboardPlantConnection: Invalid CompIndex passed={}, baseboard name={}, stored baseboard Name "
1573 : "for that index={}",
1574 : BaseboardNum,
1575 : BaseboardName,
1576 0 : DataPlant::PlantEquipTypeNames[BaseboardTypeNum]));
1577 : }
1578 : }
1579 : }
1580 :
1581 0 : if (InitLoopEquip) {
1582 0 : return;
1583 : }
1584 :
1585 0 : auto &thisHWBaseboard = state.dataHWBaseboardRad->HWBaseboard(BaseboardNum);
1586 0 : PlantUtilities::PullCompInterconnectTrigger(state,
1587 0 : thisHWBaseboard.plantLoc,
1588 0 : thisHWBaseboard.BBLoadReSimIndex,
1589 0 : thisHWBaseboard.plantLoc,
1590 : DataPlant::CriteriaType::HeatTransferRate,
1591 : thisHWBaseboard.Power);
1592 :
1593 0 : PlantUtilities::PullCompInterconnectTrigger(state,
1594 0 : thisHWBaseboard.plantLoc,
1595 0 : thisHWBaseboard.BBMassFlowReSimIndex,
1596 0 : thisHWBaseboard.plantLoc,
1597 : DataPlant::CriteriaType::MassFlowRate,
1598 : thisHWBaseboard.WaterMassFlowRate);
1599 :
1600 0 : PlantUtilities::PullCompInterconnectTrigger(state,
1601 0 : thisHWBaseboard.plantLoc,
1602 0 : thisHWBaseboard.BBInletTempFlowReSimIndex,
1603 0 : thisHWBaseboard.plantLoc,
1604 : DataPlant::CriteriaType::Temperature,
1605 : thisHWBaseboard.WaterOutletTemp);
1606 : }
1607 :
1608 : //*****************************************************************************************
1609 :
1610 : } // namespace HWBaseboardRadiator
1611 :
1612 : } // namespace EnergyPlus
|