Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2023, 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/DataSizing.hh>
67 : #include <EnergyPlus/DataSurfaces.hh>
68 : #include <EnergyPlus/DataZoneEnergyDemands.hh>
69 : #include <EnergyPlus/DataZoneEquipment.hh>
70 : #include <EnergyPlus/FluidProperties.hh>
71 : #include <EnergyPlus/General.hh>
72 : #include <EnergyPlus/GeneralRoutines.hh>
73 : #include <EnergyPlus/GlobalNames.hh>
74 : #include <EnergyPlus/HWBaseboardRadiator.hh>
75 : #include <EnergyPlus/HeatBalanceIntRadExchange.hh>
76 : #include <EnergyPlus/HeatBalanceSurfaceManager.hh>
77 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
78 : #include <EnergyPlus/NodeInputManager.hh>
79 : #include <EnergyPlus/OutputProcessor.hh>
80 : #include <EnergyPlus/Plant/DataPlant.hh>
81 : #include <EnergyPlus/PlantUtilities.hh>
82 : #include <EnergyPlus/Psychrometrics.hh>
83 : #include <EnergyPlus/ScheduleManager.hh>
84 : #include <EnergyPlus/UtilityRoutines.hh>
85 :
86 : namespace EnergyPlus {
87 :
88 : namespace HWBaseboardRadiator {
89 :
90 : // Module -- (ref: Object: ZoneHVAC:Baseboard:RadiantConvective:Water)
91 :
92 : // Module containing the routines dealing with the hot water baseboard heaters
93 :
94 : // MODULE INFORMATION:
95 : // AUTHOR Daeho Kang
96 : // DATE WRITTEN Aug 2007
97 : // MODIFIED na
98 : // RE-ENGINEERED na
99 :
100 : // PURPOSE OF THIS MODULE:
101 : // The purpose of this module is to simulate hot water baseboard heaters.
102 :
103 : // METHODOLOGY EMPLOYED:
104 :
105 : // REFERENCES:
106 : // 1. I=B=R Ratings for Baseboards, Baseboard Radiation,
107 : // Finned Tube (Commercial) Radiation, and Indirect Fired Water Heaters, January 2007 Edition
108 : // 2. Incropera and DeWitt, Fundamentals of Heat and Mass Transfer, Chapter 11.3 and 11.4,
109 : // eq. 11.15, 11.17, and 11.33
110 :
111 : // OTHER NOTES:
112 : // na
113 :
114 : // USE STATEMENTS:
115 : // Use statements for data only modules
116 : // Using/Aliasing
117 : using DataHVACGlobals::SmallLoad;
118 : using FluidProperties::GetDensityGlycol;
119 : using FluidProperties::GetSpecificHeatGlycol;
120 : using Psychrometrics::PsyCpAirFnW;
121 : using Psychrometrics::PsyRhoAirFnPbTdbW;
122 :
123 771 : std::string const cCMO_BBRadiator_Water("ZoneHVAC:Baseboard:RadiantConvective:Water");
124 771 : std::string const cCMO_BBRadiator_Water_Design("ZoneHVAC:Baseboard:RadiantConvective:Water:Design");
125 :
126 89527 : void SimHWBaseboard(EnergyPlusData &state,
127 : std::string const &EquipName,
128 : int const ControlledZoneNum,
129 : bool const FirstHVACIteration,
130 : Real64 &PowerMet,
131 : int &CompIndex)
132 : {
133 :
134 : // SUBROUTINE INFORMATION:
135 : // AUTHOR Russ Taylor
136 : // DATE WRITTEN Nov 1997
137 :
138 : // PURPOSE OF THIS SUBROUTINE:
139 : // This subroutine simulates the Baseboard Radiators.
140 :
141 : // Using/Aliasing
142 : using ScheduleManager::GetCurrentScheduleValue;
143 :
144 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
145 : int BaseboardNum; // Index of unit in baseboard array
146 89527 : auto &GetInputFlag = state.dataHWBaseboardRad->GetInputFlag;
147 : Real64 QZnReq; // Zone load not yet satisfied
148 : Real64 MaxWaterFlow;
149 : Real64 MinWaterFlow;
150 :
151 89527 : if (GetInputFlag) {
152 7 : GetHWBaseboardInput(state);
153 7 : GetInputFlag = false;
154 : }
155 :
156 89527 : auto &HWBaseboard = state.dataHWBaseboardRad->HWBaseboard;
157 89527 : auto &NumHWBaseboards = state.dataHWBaseboardRad->NumHWBaseboards;
158 89527 : auto &CheckEquipName = state.dataHWBaseboardRad->CheckEquipName;
159 89527 : auto &HWBaseboardDesignObject = state.dataHWBaseboardRad->HWBaseboardDesignObject;
160 :
161 : // Find the correct Baseboard Equipment
162 89527 : if (CompIndex == 0) {
163 17 : BaseboardNum = UtilityRoutines::FindItemInList(EquipName, HWBaseboard, &HWBaseboardParams::EquipID);
164 17 : if (BaseboardNum == 0) {
165 0 : ShowFatalError(state, "SimHWBaseboard: Unit not found=" + EquipName);
166 : }
167 17 : CompIndex = BaseboardNum;
168 : } else {
169 89510 : BaseboardNum = CompIndex;
170 89510 : if (BaseboardNum > NumHWBaseboards || BaseboardNum < 1) {
171 0 : ShowFatalError(state,
172 0 : format("SimHWBaseboard: Invalid CompIndex passed={}, Number of Units={}, Entered Unit name={}",
173 : BaseboardNum,
174 : NumHWBaseboards,
175 0 : EquipName));
176 : }
177 89510 : if (CheckEquipName(BaseboardNum)) {
178 17 : if (EquipName != HWBaseboard(BaseboardNum).EquipID) {
179 0 : ShowFatalError(state,
180 0 : format("SimHWBaseboard: Invalid CompIndex passed={}, Unit name={}, stored Unit Name for that index={}",
181 : BaseboardNum,
182 : EquipName,
183 0 : HWBaseboard(BaseboardNum).EquipID));
184 : }
185 17 : CheckEquipName(BaseboardNum) = false;
186 : }
187 : }
188 :
189 89527 : if (CompIndex > 0) {
190 : HWBaseboardDesignData HWBaseboardDesignDataObject{
191 179054 : HWBaseboardDesignObject(HWBaseboard(BaseboardNum).DesignObjectPtr)}; // Contains the data for variable flow hydronic systems
192 :
193 89527 : InitHWBaseboard(state, BaseboardNum, ControlledZoneNum, FirstHVACIteration);
194 :
195 89527 : QZnReq = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ControlledZoneNum).RemainingOutputReqToHeatSP;
196 :
197 : // On the first HVAC iteration the system values are given to the controller, but after that
198 : // the demand limits are in place and there needs to be feedback to the Zone Equipment
199 89527 : if (FirstHVACIteration) {
200 42576 : MaxWaterFlow = HWBaseboard(BaseboardNum).WaterMassFlowRateMax;
201 42576 : MinWaterFlow = 0.0;
202 : } else {
203 46951 : MaxWaterFlow = state.dataLoopNodes->Node(HWBaseboard(BaseboardNum).WaterInletNode).MassFlowRateMaxAvail;
204 46951 : MinWaterFlow = state.dataLoopNodes->Node(HWBaseboard(BaseboardNum).WaterInletNode).MassFlowRateMinAvail;
205 : }
206 :
207 89527 : switch (HWBaseboard(BaseboardNum).EquipType) {
208 89527 : case DataPlant::PlantEquipmentType::Baseboard_Rad_Conv_Water: { // 'ZoneHVAC:Baseboard:RadiantConvective:Water'
209 537162 : ControlCompOutput(state,
210 89527 : HWBaseboard(BaseboardNum).EquipID,
211 : cCMO_BBRadiator_Water,
212 : BaseboardNum,
213 : FirstHVACIteration,
214 : QZnReq,
215 89527 : HWBaseboard(BaseboardNum).WaterInletNode,
216 : MaxWaterFlow,
217 : MinWaterFlow,
218 : HWBaseboardDesignDataObject.Offset,
219 89527 : HWBaseboard(BaseboardNum).ControlCompTypeNum,
220 89527 : HWBaseboard(BaseboardNum).CompErrIndex,
221 : _,
222 : _,
223 : _,
224 : _,
225 : _,
226 89527 : HWBaseboard(BaseboardNum).plantLoc);
227 89527 : } break;
228 0 : default: {
229 0 : ShowSevereError(state, "SimBaseboard: Errors in Baseboard=" + HWBaseboard(BaseboardNum).EquipID);
230 0 : ShowContinueError(state, format("Invalid or unimplemented equipment type={}", HWBaseboard(BaseboardNum).EquipType));
231 0 : ShowFatalError(state, "Preceding condition causes termination.");
232 0 : } break;
233 : }
234 :
235 89527 : PowerMet = HWBaseboard(BaseboardNum).TotPower;
236 :
237 89527 : UpdateHWBaseboard(state, BaseboardNum);
238 :
239 89527 : ReportHWBaseboard(state, BaseboardNum);
240 :
241 : } else {
242 0 : ShowFatalError(state, "SimHWBaseboard: Unit not found=" + EquipName);
243 : }
244 89527 : }
245 :
246 7 : void GetHWBaseboardInput(EnergyPlusData &state)
247 : {
248 :
249 : // SUBROUTINE INFORMATION:
250 : // AUTHOR Daeho Kang
251 : // DATE WRITTEN Aug 2007
252 : // MODIFIED na
253 : // RE-ENGINEERED na
254 :
255 : // PURPOSE OF THIS SUBROUTINE:
256 : // This subroutine gets the input for the baseboard units.
257 :
258 : // METHODOLOGY EMPLOYED:
259 : // Standard input processor calls.
260 :
261 : // Using/Aliasing
262 : using BranchNodeConnections::TestCompSet;
263 : using DataLoopNode::ObjectIsNotParent;
264 : using DataSizing::AutoSize;
265 : using DataSizing::CapacityPerFloorArea;
266 : using DataSizing::FractionOfAutosizedHeatingCapacity;
267 : using DataSizing::HeatingDesignCapacity;
268 : using GlobalNames::VerifyUniqueBaseboardName;
269 : using NodeInputManager::GetOnlySingleNode;
270 : using ScheduleManager::GetCurrentScheduleValue;
271 : using ScheduleManager::GetScheduleIndex;
272 :
273 : // SUBROUTINE PARAMETER DEFINITIONS:
274 : static constexpr std::string_view RoutineName("GetHWBaseboardInput:");
275 7 : Real64 constexpr MaxFraction(1.0);
276 7 : Real64 constexpr MinFraction(0.0);
277 7 : Real64 constexpr MaxWaterTempAvg(150.0); // Maximum limit of average water temperature in degree C
278 7 : Real64 constexpr MinWaterTempAvg(20.0); // Minimum limit of average water temperature in degree C
279 7 : Real64 constexpr HighWaterMassFlowRate(10.0); // Maximum limit of water mass flow rate in kg/s
280 7 : Real64 constexpr LowWaterMassFlowRate(0.00001); // Minimum limit of water mass flow rate in kg/s
281 7 : Real64 constexpr MaxWaterFlowRate(10.0); // Maximum limit of water volume flow rate in m3/s
282 7 : Real64 constexpr MinWaterFlowRate(0.00001); // Minimum limit of water volume flow rate in m3/s
283 7 : Real64 constexpr WaterMassFlowDefault(0.063); // Default water mass flow rate in kg/s
284 : // INTEGER, PARAMETER :: MaxDistribSurfaces = 20 ! Maximum number of surfaces that a baseboard heater can radiate to
285 7 : int constexpr MinDistribSurfaces(1); // Minimum number of surfaces that a baseboard heater can radiate to
286 7 : int constexpr iHeatCAPMAlphaNum(2); // get input index to HW baseboard heating capacity sizing method
287 7 : int constexpr iHeatDesignCapacityNumericNum(3); // get input index to HW baseboard heating capacity
288 7 : int constexpr iHeatCapacityPerFloorAreaNumericNum(1); // get input index to HW baseboard heating capacity per floor area sizing
289 7 : int constexpr iHeatFracOfAutosizedCapacityNumericNum(
290 : 2); // get input index to HW baseboard heating capacity sizing as fraction of autozized heating capacity
291 :
292 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
293 : Real64 AllFracsSummed; // Sum of the fractions radiant
294 : int BaseboardNum; // Baseboard number
295 : int BaseboardDesignNum;
296 : int NumAlphas; // Number of Alphas for each GetobjectItem call
297 : int NumNumbers; // Number of Numbers for each GetobjectItem call
298 : int SurfNum; // Surface number Do loop counter
299 : int IOStat;
300 7 : bool ErrorsFound(false); // If errors detected in input
301 :
302 7 : auto &NumHWBaseboards = state.dataHWBaseboardRad->NumHWBaseboards;
303 7 : auto &NumHWBaseboardDesignObjs = state.dataHWBaseboardRad->NumHWBaseboardDesignObjs;
304 7 : auto &HWBaseboard = state.dataHWBaseboardRad->HWBaseboard;
305 7 : auto &HWBaseboardDesignObject = state.dataHWBaseboardRad->HWBaseboardDesignObject;
306 7 : auto &CheckEquipName = state.dataHWBaseboardRad->CheckEquipName;
307 7 : auto &HWBaseboardNumericFields = state.dataHWBaseboardRad->HWBaseboardNumericFields;
308 7 : auto &HWBaseboardDesignNumericFields = state.dataHWBaseboardRad->HWBaseboardDesignNumericFields;
309 7 : auto &HWBaseboardDesignNames = state.dataHWBaseboardRad->HWBaseboardDesignNames;
310 :
311 7 : NumHWBaseboards = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCMO_BBRadiator_Water);
312 7 : NumHWBaseboardDesignObjs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCMO_BBRadiator_Water_Design);
313 :
314 : // Count total number of baseboard units
315 :
316 7 : HWBaseboard.allocate(NumHWBaseboards);
317 7 : HWBaseboardDesignObject.allocate(NumHWBaseboardDesignObjs);
318 7 : CheckEquipName.allocate(NumHWBaseboards);
319 7 : HWBaseboardNumericFields.allocate(NumHWBaseboards);
320 7 : HWBaseboardDesignNumericFields.allocate(NumHWBaseboardDesignObjs);
321 7 : HWBaseboardDesignNames.allocate(NumHWBaseboardDesignObjs);
322 7 : CheckEquipName = true;
323 :
324 : // Get the data from the user input related to design data for baseboard heaters
325 18 : for (BaseboardDesignNum = 1; BaseboardDesignNum <= NumHWBaseboardDesignObjs; ++BaseboardDesignNum) {
326 77 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
327 : cCMO_BBRadiator_Water_Design,
328 : BaseboardDesignNum,
329 11 : state.dataIPShortCut->cAlphaArgs,
330 : NumAlphas,
331 11 : state.dataIPShortCut->rNumericArgs,
332 : NumNumbers,
333 : IOStat,
334 11 : state.dataIPShortCut->lNumericFieldBlanks,
335 11 : state.dataIPShortCut->lAlphaFieldBlanks,
336 11 : state.dataIPShortCut->cAlphaFieldNames,
337 11 : state.dataIPShortCut->cNumericFieldNames);
338 :
339 11 : HWBaseboardDesignNumericFields(BaseboardDesignNum).FieldNames.allocate(NumNumbers);
340 11 : HWBaseboardDesignNumericFields(BaseboardDesignNum).FieldNames = "";
341 11 : HWBaseboardDesignNumericFields(BaseboardDesignNum).FieldNames = state.dataIPShortCut->cNumericFieldNames;
342 :
343 11 : UtilityRoutines::IsNameEmpty(state, state.dataIPShortCut->cAlphaArgs(1), state.dataIPShortCut->cCurrentModuleObject, ErrorsFound);
344 :
345 : // ErrorsFound will be set to True if problem was found, left untouched otherwise
346 11 : VerifyUniqueBaseboardName(
347 22 : state, cCMO_BBRadiator_Water_Design, state.dataIPShortCut->cAlphaArgs(1), ErrorsFound, cCMO_BBRadiator_Water_Design + " Name");
348 :
349 11 : HWBaseboardDesignObject(BaseboardDesignNum).designName = state.dataIPShortCut->cAlphaArgs(1); // Name of this baseboard design object
350 11 : HWBaseboardDesignNames(BaseboardDesignNum) = state.dataIPShortCut->cAlphaArgs(1);
351 :
352 : // Determine HW radiant baseboard heating design capacity sizing method
353 11 : if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(iHeatCAPMAlphaNum), "HeatingDesignCapacity")) {
354 11 : HWBaseboardDesignObject(BaseboardDesignNum).HeatingCapMethod = HeatingDesignCapacity;
355 0 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(iHeatCAPMAlphaNum), "CapacityPerFloorArea")) {
356 0 : HWBaseboardDesignObject(BaseboardDesignNum).HeatingCapMethod = CapacityPerFloorArea;
357 0 : if (!state.dataIPShortCut->lNumericFieldBlanks(iHeatCapacityPerFloorAreaNumericNum)) {
358 0 : HWBaseboardDesignObject(BaseboardDesignNum).ScaledHeatingCapacity =
359 0 : state.dataIPShortCut->rNumericArgs(iHeatCapacityPerFloorAreaNumericNum);
360 0 : if (HWBaseboardDesignObject(BaseboardDesignNum).ScaledHeatingCapacity <= 0.0) {
361 0 : ShowSevereError(state,
362 0 : state.dataIPShortCut->cCurrentModuleObject + " = " + HWBaseboardDesignObject(BaseboardDesignNum).designName);
363 0 : ShowContinueError(state,
364 0 : "Input for " + state.dataIPShortCut->cAlphaFieldNames(iHeatCAPMAlphaNum) + " = " +
365 0 : state.dataIPShortCut->cAlphaArgs(iHeatCAPMAlphaNum));
366 0 : ShowContinueError(state,
367 0 : format("Illegal {} = {:.7T}",
368 0 : state.dataIPShortCut->cNumericFieldNames(iHeatCapacityPerFloorAreaNumericNum),
369 0 : state.dataIPShortCut->rNumericArgs(iHeatCapacityPerFloorAreaNumericNum)));
370 0 : ErrorsFound = true;
371 0 : } else if (HWBaseboardDesignObject(BaseboardDesignNum).ScaledHeatingCapacity == AutoSize) {
372 0 : ShowSevereError(state,
373 0 : state.dataIPShortCut->cCurrentModuleObject + " = " + HWBaseboardDesignObject(BaseboardDesignNum).designName);
374 0 : ShowContinueError(state,
375 0 : "Input for " + state.dataIPShortCut->cAlphaFieldNames(iHeatCAPMAlphaNum) + " = " +
376 0 : state.dataIPShortCut->cAlphaArgs(iHeatCAPMAlphaNum));
377 0 : ShowContinueError(state,
378 0 : "Illegal " + state.dataIPShortCut->cNumericFieldNames(iHeatCapacityPerFloorAreaNumericNum) + " = Autosize");
379 0 : ErrorsFound = true;
380 : }
381 : } else {
382 0 : ShowSevereError(state,
383 0 : state.dataIPShortCut->cCurrentModuleObject + " = " + HWBaseboardDesignObject(BaseboardDesignNum).designName);
384 0 : ShowContinueError(state,
385 0 : "Input for " + state.dataIPShortCut->cAlphaFieldNames(iHeatCAPMAlphaNum) + " = " +
386 0 : state.dataIPShortCut->cAlphaArgs(iHeatCAPMAlphaNum));
387 0 : ShowContinueError(state,
388 0 : "Blank field not allowed for " + state.dataIPShortCut->cNumericFieldNames(iHeatCapacityPerFloorAreaNumericNum));
389 0 : ErrorsFound = true;
390 : }
391 0 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(iHeatCAPMAlphaNum), "FractionOfAutosizedHeatingCapacity")) {
392 0 : HWBaseboardDesignObject(BaseboardDesignNum).HeatingCapMethod = FractionOfAutosizedHeatingCapacity;
393 0 : if (!state.dataIPShortCut->lNumericFieldBlanks(iHeatFracOfAutosizedCapacityNumericNum)) {
394 0 : HWBaseboardDesignObject(BaseboardDesignNum).ScaledHeatingCapacity =
395 0 : state.dataIPShortCut->rNumericArgs(iHeatFracOfAutosizedCapacityNumericNum);
396 0 : if (HWBaseboardDesignObject(BaseboardDesignNum).ScaledHeatingCapacity < 0.0) {
397 0 : ShowSevereError(state,
398 0 : state.dataIPShortCut->cCurrentModuleObject + " = " + HWBaseboardDesignObject(BaseboardDesignNum).designName);
399 0 : ShowContinueError(state,
400 0 : format("Illegal {} = {:.7T}",
401 0 : state.dataIPShortCut->cNumericFieldNames(iHeatFracOfAutosizedCapacityNumericNum),
402 0 : state.dataIPShortCut->rNumericArgs(iHeatFracOfAutosizedCapacityNumericNum)));
403 0 : ErrorsFound = true;
404 : }
405 : } else {
406 0 : ShowSevereError(state,
407 0 : state.dataIPShortCut->cCurrentModuleObject + " = " + HWBaseboardDesignObject(BaseboardDesignNum).designName);
408 0 : ShowContinueError(state,
409 0 : "Input for " + state.dataIPShortCut->cAlphaFieldNames(iHeatCAPMAlphaNum) + " = " +
410 0 : state.dataIPShortCut->cAlphaArgs(iHeatCAPMAlphaNum));
411 0 : ShowContinueError(
412 0 : state, "Blank field not allowed for " + state.dataIPShortCut->cNumericFieldNames(iHeatFracOfAutosizedCapacityNumericNum));
413 0 : ErrorsFound = true;
414 : }
415 : }
416 :
417 11 : HWBaseboardDesignObject(BaseboardDesignNum).Offset = state.dataIPShortCut->rNumericArgs(3);
418 : // Set default convergence tolerance
419 11 : if (HWBaseboardDesignObject(BaseboardDesignNum).Offset <= 0.0) {
420 0 : ShowWarningError(state,
421 0 : std::string{RoutineName} + cCMO_BBRadiator_Water_Design + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", " +
422 0 : state.dataIPShortCut->cNumericFieldNames(3) + " was less than the allowable minimum.");
423 0 : ShowContinueError(state, format("...reset to a default value=[{:.2R}].", MaxFraction));
424 0 : HWBaseboardDesignObject(BaseboardDesignNum).Offset = 0.001;
425 : }
426 :
427 11 : HWBaseboardDesignObject(BaseboardDesignNum).FracRadiant = state.dataIPShortCut->rNumericArgs(4);
428 11 : if (HWBaseboardDesignObject(BaseboardDesignNum).FracRadiant < MinFraction) {
429 0 : ShowWarningError(state,
430 0 : std::string{RoutineName} + cCMO_BBRadiator_Water + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", " +
431 0 : state.dataIPShortCut->cNumericFieldNames(4) + " was lower than the allowable minimum.");
432 0 : ShowContinueError(state, format("...reset to minimum value=[{:.2R}].", MinFraction));
433 0 : HWBaseboardDesignObject(BaseboardDesignNum).FracRadiant = MinFraction;
434 : }
435 11 : if (HWBaseboardDesignObject(BaseboardDesignNum).FracRadiant > MaxFraction) {
436 0 : ShowWarningError(state,
437 0 : std::string{RoutineName} + cCMO_BBRadiator_Water + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", " +
438 0 : state.dataIPShortCut->cNumericFieldNames(4) + " was higher than the allowable maximum.");
439 0 : ShowContinueError(state, format("...reset to maximum value=[{:.2R}].", MaxFraction));
440 0 : HWBaseboardDesignObject(BaseboardDesignNum).FracRadiant = MaxFraction;
441 : }
442 :
443 11 : HWBaseboardDesignObject(BaseboardDesignNum).FracDistribPerson = state.dataIPShortCut->rNumericArgs(5);
444 11 : if (HWBaseboardDesignObject(BaseboardDesignNum).FracDistribPerson < MinFraction) {
445 0 : ShowWarningError(state,
446 0 : std::string{RoutineName} + cCMO_BBRadiator_Water + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", " +
447 0 : state.dataIPShortCut->cNumericFieldNames(5) + " was lower than the allowable minimum.");
448 0 : ShowContinueError(state, format("...reset to minimum value=[{:.3R}].", MinFraction));
449 0 : HWBaseboardDesignObject(BaseboardDesignNum).FracDistribPerson = MinFraction;
450 : }
451 11 : if (HWBaseboardDesignObject(BaseboardDesignNum).FracDistribPerson > MaxFraction) {
452 0 : ShowWarningError(state,
453 0 : std::string{RoutineName} + cCMO_BBRadiator_Water + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", " +
454 0 : state.dataIPShortCut->cNumericFieldNames(5) + " was higher than the allowable maximum.");
455 0 : ShowContinueError(state, format("...reset to maximum value=[{:.3R}].", MaxFraction));
456 0 : HWBaseboardDesignObject(BaseboardDesignNum).FracDistribPerson = MaxFraction;
457 : }
458 : }
459 :
460 : // Get the data from the user input related to baseboard heaters
461 24 : for (BaseboardNum = 1; BaseboardNum <= NumHWBaseboards; ++BaseboardNum) {
462 :
463 119 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
464 : cCMO_BBRadiator_Water,
465 : BaseboardNum,
466 17 : state.dataIPShortCut->cAlphaArgs,
467 : NumAlphas,
468 17 : state.dataIPShortCut->rNumericArgs,
469 : NumNumbers,
470 : IOStat,
471 17 : state.dataIPShortCut->lNumericFieldBlanks,
472 17 : state.dataIPShortCut->lAlphaFieldBlanks,
473 17 : state.dataIPShortCut->cAlphaFieldNames,
474 17 : state.dataIPShortCut->cNumericFieldNames);
475 :
476 17 : HWBaseboardNumericFields(BaseboardNum).FieldNames.allocate(NumNumbers);
477 17 : HWBaseboardNumericFields(BaseboardNum).FieldNames = "";
478 17 : HWBaseboardNumericFields(BaseboardNum).FieldNames = state.dataIPShortCut->cNumericFieldNames;
479 17 : UtilityRoutines::IsNameEmpty(state, state.dataIPShortCut->cAlphaArgs(1), state.dataIPShortCut->cCurrentModuleObject, ErrorsFound);
480 :
481 : // ErrorsFound will be set to True if problem was found, left untouched otherwise
482 17 : VerifyUniqueBaseboardName(
483 34 : state, cCMO_BBRadiator_Water, state.dataIPShortCut->cAlphaArgs(1), ErrorsFound, cCMO_BBRadiator_Water + " Name");
484 :
485 17 : HWBaseboard(BaseboardNum).EquipID = state.dataIPShortCut->cAlphaArgs(1); // Name of this baseboard
486 17 : HWBaseboard(BaseboardNum).EquipType =
487 : DataPlant::PlantEquipmentType::Baseboard_Rad_Conv_Water; //'ZoneHVAC:Baseboard:RadiantConvective:Water'
488 :
489 17 : HWBaseboard(BaseboardNum).designObjectName = state.dataIPShortCut->cAlphaArgs(2); // Name of the design object for this baseboard
490 17 : HWBaseboard(BaseboardNum).DesignObjectPtr =
491 17 : UtilityRoutines::FindItemInList(HWBaseboard(BaseboardNum).designObjectName, HWBaseboardDesignNames);
492 : HWBaseboardDesignData HWBaseboardDesignDataObject{
493 34 : HWBaseboardDesignObject(HWBaseboard(BaseboardNum).DesignObjectPtr)}; // Contains the data for the design object
494 :
495 : // Get schedule
496 17 : HWBaseboard(BaseboardNum).Schedule = state.dataIPShortCut->cAlphaArgs(3);
497 17 : if (state.dataIPShortCut->lAlphaFieldBlanks(3)) {
498 5 : HWBaseboard(BaseboardNum).SchedPtr = DataGlobalConstants::ScheduleAlwaysOn;
499 : } else {
500 12 : HWBaseboard(BaseboardNum).SchedPtr = GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(3));
501 12 : if (HWBaseboard(BaseboardNum).SchedPtr == 0) {
502 0 : ShowSevereError(state,
503 0 : std::string{RoutineName} + cCMO_BBRadiator_Water + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", " +
504 0 : state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + state.dataIPShortCut->cAlphaArgs(3) + "\" not found.");
505 0 : ErrorsFound = true;
506 : }
507 : }
508 :
509 : // Get inlet node number
510 17 : HWBaseboard(BaseboardNum).WaterInletNode = GetOnlySingleNode(state,
511 17 : state.dataIPShortCut->cAlphaArgs(4),
512 : ErrorsFound,
513 : DataLoopNode::ConnectionObjectType::ZoneHVACBaseboardRadiantConvectiveWater,
514 17 : state.dataIPShortCut->cAlphaArgs(1),
515 : DataLoopNode::NodeFluidType::Water,
516 : DataLoopNode::ConnectionType::Inlet,
517 : NodeInputManager::CompFluidStream::Primary,
518 17 : ObjectIsNotParent);
519 :
520 : // Get outlet node number
521 17 : HWBaseboard(BaseboardNum).WaterOutletNode = GetOnlySingleNode(state,
522 17 : state.dataIPShortCut->cAlphaArgs(5),
523 : ErrorsFound,
524 : DataLoopNode::ConnectionObjectType::ZoneHVACBaseboardRadiantConvectiveWater,
525 17 : state.dataIPShortCut->cAlphaArgs(1),
526 : DataLoopNode::NodeFluidType::Water,
527 : DataLoopNode::ConnectionType::Outlet,
528 : NodeInputManager::CompFluidStream::Primary,
529 17 : ObjectIsNotParent);
530 34 : TestCompSet(state,
531 : cCMO_BBRadiator_Water,
532 17 : state.dataIPShortCut->cAlphaArgs(1),
533 17 : state.dataIPShortCut->cAlphaArgs(4),
534 17 : state.dataIPShortCut->cAlphaArgs(5),
535 : "Hot Water Nodes");
536 :
537 17 : HWBaseboard(BaseboardNum).WaterTempAvg = state.dataIPShortCut->rNumericArgs(1);
538 17 : if (HWBaseboard(BaseboardNum).WaterTempAvg > MaxWaterTempAvg + 0.001) {
539 0 : ShowWarningError(state,
540 0 : std::string{RoutineName} + cCMO_BBRadiator_Water + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", " +
541 0 : state.dataIPShortCut->cNumericFieldNames(1) + " was higher than the allowable maximum.");
542 0 : ShowContinueError(state, format("...reset to maximum value=[{:.2R}].", MaxWaterTempAvg));
543 0 : HWBaseboard(BaseboardNum).WaterTempAvg = MaxWaterTempAvg;
544 17 : } else if (HWBaseboard(BaseboardNum).WaterTempAvg < MinWaterTempAvg - 0.001) {
545 0 : ShowWarningError(state,
546 0 : std::string{RoutineName} + cCMO_BBRadiator_Water + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", " +
547 0 : state.dataIPShortCut->cNumericFieldNames(1) + " was lower than the allowable minimum.");
548 0 : ShowContinueError(state, format("...reset to minimum value=[{:.2R}].", MinWaterTempAvg));
549 0 : HWBaseboard(BaseboardNum).WaterTempAvg = MinWaterTempAvg;
550 : }
551 :
552 17 : HWBaseboard(BaseboardNum).WaterMassFlowRateStd = state.dataIPShortCut->rNumericArgs(2);
553 34 : if (HWBaseboard(BaseboardNum).WaterMassFlowRateStd < LowWaterMassFlowRate - 0.0001 ||
554 17 : HWBaseboard(BaseboardNum).WaterMassFlowRateStd > HighWaterMassFlowRate + 0.0001) {
555 0 : ShowWarningError(state,
556 0 : std::string{RoutineName} + cCMO_BBRadiator_Water + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", " +
557 0 : state.dataIPShortCut->cNumericFieldNames(2) + " is an invalid Standard Water mass flow rate.");
558 0 : ShowContinueError(state, format("...reset to a default value=[{:.1R}].", WaterMassFlowDefault));
559 0 : HWBaseboard(BaseboardNum).WaterMassFlowRateStd = WaterMassFlowDefault;
560 : }
561 :
562 : // Determine HW radiant baseboard heating design capacity sizing method
563 17 : HWBaseboard(BaseboardNum).HeatingCapMethod = HWBaseboardDesignDataObject.HeatingCapMethod;
564 17 : if (HWBaseboard(BaseboardNum).HeatingCapMethod == HeatingDesignCapacity) {
565 17 : if (!state.dataIPShortCut->lNumericFieldBlanks(iHeatDesignCapacityNumericNum)) {
566 17 : HWBaseboard(BaseboardNum).ScaledHeatingCapacity = state.dataIPShortCut->rNumericArgs(iHeatDesignCapacityNumericNum);
567 17 : if (HWBaseboard(BaseboardNum).ScaledHeatingCapacity < 0.0 && HWBaseboard(BaseboardNum).ScaledHeatingCapacity != AutoSize) {
568 0 : ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + " = " + HWBaseboard(BaseboardNum).EquipID);
569 0 : ShowContinueError(state,
570 0 : format("Illegal {} = {:.7T}",
571 0 : state.dataIPShortCut->cNumericFieldNames(iHeatDesignCapacityNumericNum),
572 0 : state.dataIPShortCut->rNumericArgs(iHeatDesignCapacityNumericNum)));
573 0 : ErrorsFound = true;
574 : }
575 : } else {
576 0 : ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + " = " + HWBaseboard(BaseboardNum).EquipID);
577 0 : ShowContinueError(state,
578 0 : "Input for " + state.dataIPShortCut->cAlphaFieldNames(iHeatCAPMAlphaNum) + " = " +
579 0 : state.dataIPShortCut->cAlphaArgs(iHeatCAPMAlphaNum));
580 0 : ShowContinueError(state,
581 0 : "Blank field not allowed for " + state.dataIPShortCut->cNumericFieldNames(iHeatDesignCapacityNumericNum));
582 0 : ErrorsFound = true;
583 : }
584 0 : } else if (HWBaseboard(BaseboardNum).HeatingCapMethod == CapacityPerFloorArea) {
585 0 : HWBaseboard(BaseboardNum).ScaledHeatingCapacity = HWBaseboardDesignDataObject.ScaledHeatingCapacity;
586 :
587 0 : } else if (HWBaseboard(BaseboardNum).HeatingCapMethod == FractionOfAutosizedHeatingCapacity) {
588 0 : HWBaseboard(BaseboardNum).ScaledHeatingCapacity = HWBaseboardDesignDataObject.ScaledHeatingCapacity;
589 :
590 : } else {
591 0 : ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + " = " + HWBaseboard(BaseboardNum).EquipID);
592 0 : ShowContinueError(state,
593 0 : "Illegal " + state.dataIPShortCut->cAlphaFieldNames(iHeatCAPMAlphaNum) + " = " +
594 0 : state.dataIPShortCut->cAlphaArgs(iHeatCAPMAlphaNum));
595 0 : ErrorsFound = true;
596 : }
597 :
598 17 : HWBaseboard(BaseboardNum).WaterVolFlowRateMax = state.dataIPShortCut->rNumericArgs(4);
599 17 : if (std::abs(HWBaseboard(BaseboardNum).WaterVolFlowRateMax) <= MinWaterFlowRate) {
600 0 : ShowWarningError(state,
601 0 : std::string{RoutineName} + cCMO_BBRadiator_Water + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", " +
602 0 : state.dataIPShortCut->cNumericFieldNames(4) + " was less than the allowable minimum.");
603 0 : ShowContinueError(state, format("...reset to minimum value=[{:.2R}].", MinWaterFlowRate));
604 0 : HWBaseboard(BaseboardNum).WaterVolFlowRateMax = MinWaterFlowRate;
605 17 : } else if (HWBaseboard(BaseboardNum).WaterVolFlowRateMax > MaxWaterFlowRate) {
606 0 : ShowWarningError(state,
607 0 : std::string{RoutineName} + cCMO_BBRadiator_Water + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", " +
608 0 : state.dataIPShortCut->cNumericFieldNames(4) + " was higher than the allowable maximum.");
609 0 : ShowContinueError(state, format("...reset to maximum value=[{:.2R}].", MaxWaterFlowRate));
610 0 : HWBaseboard(BaseboardNum).WaterVolFlowRateMax = MaxWaterFlowRate;
611 : }
612 :
613 : // Remaining fraction is added to the zone as convective heat transfer
614 17 : AllFracsSummed = HWBaseboardDesignDataObject.FracDistribPerson;
615 17 : if (AllFracsSummed > MaxFraction) {
616 0 : ShowWarningError(state,
617 0 : std::string{RoutineName} + cCMO_BBRadiator_Water + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
618 : "\", Fraction Radiant was higher than the allowable maximum.");
619 0 : HWBaseboardDesignDataObject.FracRadiant = MaxFraction;
620 0 : HWBaseboard(BaseboardNum).FracConvect = 0.0;
621 : } else {
622 17 : HWBaseboard(BaseboardNum).FracConvect = 1.0 - AllFracsSummed;
623 : }
624 :
625 17 : HWBaseboard(BaseboardNum).TotSurfToDistrib = NumNumbers - 4;
626 : // IF (HWBaseboard(BaseboardNum)%TotSurfToDistrib > MaxDistribSurfaces) THEN
627 : // CALL ShowWarningError(state, RoutineName//cCMO_BBRadiator_Water//'="'//TRIM(state.dataIPShortCut->cAlphaArgs(1))// &
628 : // '", the number of surface/radiant fraction groups entered was higher than the allowable maximum.')
629 : // CALL ShowContinueError(state, '...only the maximum value=['//TRIM(RoundSigDigits(MaxDistribSurfaces))// &
630 : // '] will be processed.')
631 : // HWBaseboard(BaseboardNum)%TotSurfToDistrib = MaxDistribSurfaces
632 : // END IF
633 17 : if ((HWBaseboard(BaseboardNum).TotSurfToDistrib < MinDistribSurfaces) && (HWBaseboardDesignDataObject.FracRadiant > MinFraction)) {
634 0 : ShowSevereError(state,
635 0 : std::string{RoutineName} + cCMO_BBRadiator_Water + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
636 : "\", the number of surface/radiant fraction groups entered was less than the allowable minimum.");
637 0 : ShowContinueError(state, format("...the minimum that must be entered=[{}].", MinDistribSurfaces));
638 0 : ErrorsFound = true;
639 0 : HWBaseboard(BaseboardNum).TotSurfToDistrib = 0; // error
640 : }
641 :
642 17 : HWBaseboard(BaseboardNum).SurfaceName.allocate(HWBaseboard(BaseboardNum).TotSurfToDistrib);
643 17 : HWBaseboard(BaseboardNum).SurfaceName = "";
644 17 : HWBaseboard(BaseboardNum).SurfacePtr.allocate(HWBaseboard(BaseboardNum).TotSurfToDistrib);
645 17 : HWBaseboard(BaseboardNum).SurfacePtr = 0;
646 17 : HWBaseboard(BaseboardNum).FracDistribToSurf.allocate(HWBaseboard(BaseboardNum).TotSurfToDistrib);
647 17 : HWBaseboard(BaseboardNum).FracDistribToSurf = 0.0;
648 :
649 17 : HWBaseboard(BaseboardNum).ZonePtr =
650 17 : DataZoneEquipment::GetZoneEquipControlledZoneNum(state, DataZoneEquipment::ZoneEquip::BBWater, HWBaseboard(BaseboardNum).EquipID);
651 :
652 17 : AllFracsSummed = HWBaseboardDesignDataObject.FracDistribPerson;
653 53 : for (SurfNum = 1; SurfNum <= HWBaseboard(BaseboardNum).TotSurfToDistrib; ++SurfNum) {
654 36 : HWBaseboard(BaseboardNum).SurfaceName(SurfNum) = state.dataIPShortCut->cAlphaArgs(SurfNum + 5);
655 36 : HWBaseboard(BaseboardNum).SurfacePtr(SurfNum) =
656 72 : HeatBalanceIntRadExchange::GetRadiantSystemSurface(state,
657 : cCMO_BBRadiator_Water,
658 36 : HWBaseboard(BaseboardNum).EquipID,
659 36 : HWBaseboard(BaseboardNum).ZonePtr,
660 36 : HWBaseboard(BaseboardNum).SurfaceName(SurfNum),
661 : ErrorsFound);
662 36 : HWBaseboard(BaseboardNum).FracDistribToSurf(SurfNum) = state.dataIPShortCut->rNumericArgs(SurfNum + 4);
663 36 : if (HWBaseboard(BaseboardNum).FracDistribToSurf(SurfNum) > MaxFraction) {
664 0 : ShowWarningError(state,
665 0 : std::string{RoutineName} + cCMO_BBRadiator_Water + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", " +
666 0 : state.dataIPShortCut->cNumericFieldNames(SurfNum + 4) + "was greater than the allowable maximum.");
667 0 : ShowContinueError(state, format("...reset to maximum value=[{:.2R}].", MaxFraction));
668 0 : HWBaseboard(BaseboardNum).TotSurfToDistrib = MaxFraction;
669 : }
670 36 : if (HWBaseboard(BaseboardNum).FracDistribToSurf(SurfNum) < MinFraction) {
671 0 : ShowWarningError(state,
672 0 : std::string{RoutineName} + cCMO_BBRadiator_Water + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", " +
673 0 : state.dataIPShortCut->cNumericFieldNames(SurfNum + 4) + "was less than the allowable minimum.");
674 0 : ShowContinueError(state, format("...reset to maximum value=[{:.2R}].", MinFraction));
675 0 : HWBaseboard(BaseboardNum).TotSurfToDistrib = MinFraction;
676 : }
677 36 : if (HWBaseboard(BaseboardNum).SurfacePtr(SurfNum) != 0) {
678 36 : state.dataSurface->SurfIntConvSurfGetsRadiantHeat(HWBaseboard(BaseboardNum).SurfacePtr(SurfNum)) = true;
679 : }
680 :
681 36 : AllFracsSummed += HWBaseboard(BaseboardNum).FracDistribToSurf(SurfNum);
682 : } // Surfaces
683 :
684 17 : if (AllFracsSummed > (MaxFraction + 0.01)) {
685 0 : ShowSevereError(state,
686 0 : std::string{RoutineName} + cCMO_BBRadiator_Water + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
687 : "\", Summed radiant fractions for people + surface groups > 1.0");
688 0 : ErrorsFound = true;
689 : }
690 22 : if ((AllFracsSummed < (MaxFraction - 0.01)) &&
691 5 : (HWBaseboardDesignDataObject.FracRadiant >
692 : MinFraction)) { // User didn't distribute all of the | radiation warn that some will be lost
693 0 : ShowWarningError(state,
694 0 : std::string{RoutineName} + cCMO_BBRadiator_Water + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
695 : "\", Summed radiant fractions for people + surface groups < 1.0");
696 0 : ShowContinueError(state, "The rest of the radiant energy delivered by the baseboard heater will be lost");
697 : }
698 : }
699 :
700 7 : if (ErrorsFound) {
701 0 : ShowFatalError(state, std::string{RoutineName} + cCMO_BBRadiator_Water + "Errors found getting input. Program terminates.");
702 : }
703 :
704 : // Setup Report variables for the Coils
705 24 : for (BaseboardNum = 1; BaseboardNum <= NumHWBaseboards; ++BaseboardNum) {
706 : // CurrentModuleObject='ZoneHVAC:Baseboard:RadiantConvective:Water'
707 68 : SetupOutputVariable(state,
708 : "Baseboard Total Heating Rate",
709 : OutputProcessor::Unit::W,
710 17 : HWBaseboard(BaseboardNum).TotPower,
711 : OutputProcessor::SOVTimeStepType::System,
712 : OutputProcessor::SOVStoreType::Average,
713 34 : HWBaseboard(BaseboardNum).EquipID);
714 :
715 68 : SetupOutputVariable(state,
716 : "Baseboard Convective Heating Rate",
717 : OutputProcessor::Unit::W,
718 17 : HWBaseboard(BaseboardNum).ConvPower,
719 : OutputProcessor::SOVTimeStepType::System,
720 : OutputProcessor::SOVStoreType::Average,
721 34 : HWBaseboard(BaseboardNum).EquipID);
722 68 : SetupOutputVariable(state,
723 : "Baseboard Radiant Heating Rate",
724 : OutputProcessor::Unit::W,
725 17 : HWBaseboard(BaseboardNum).RadPower,
726 : OutputProcessor::SOVTimeStepType::System,
727 : OutputProcessor::SOVStoreType::Average,
728 34 : HWBaseboard(BaseboardNum).EquipID);
729 68 : SetupOutputVariable(state,
730 : "Baseboard Total Heating Energy",
731 : OutputProcessor::Unit::J,
732 17 : HWBaseboard(BaseboardNum).TotEnergy,
733 : OutputProcessor::SOVTimeStepType::System,
734 : OutputProcessor::SOVStoreType::Summed,
735 17 : HWBaseboard(BaseboardNum).EquipID,
736 : _,
737 : "ENERGYTRANSFER",
738 : "BASEBOARD",
739 : _,
740 17 : "System");
741 :
742 68 : SetupOutputVariable(state,
743 : "Baseboard Convective Heating Energy",
744 : OutputProcessor::Unit::J,
745 17 : HWBaseboard(BaseboardNum).ConvEnergy,
746 : OutputProcessor::SOVTimeStepType::System,
747 : OutputProcessor::SOVStoreType::Summed,
748 34 : HWBaseboard(BaseboardNum).EquipID);
749 68 : SetupOutputVariable(state,
750 : "Baseboard Radiant Heating Energy",
751 : OutputProcessor::Unit::J,
752 17 : HWBaseboard(BaseboardNum).RadEnergy,
753 : OutputProcessor::SOVTimeStepType::System,
754 : OutputProcessor::SOVStoreType::Summed,
755 34 : HWBaseboard(BaseboardNum).EquipID);
756 68 : SetupOutputVariable(state,
757 : "Baseboard Hot Water Energy",
758 : OutputProcessor::Unit::J,
759 17 : HWBaseboard(BaseboardNum).Energy,
760 : OutputProcessor::SOVTimeStepType::System,
761 : OutputProcessor::SOVStoreType::Summed,
762 17 : HWBaseboard(BaseboardNum).EquipID,
763 : _,
764 : "PLANTLOOPHEATINGDEMAND",
765 : "BASEBOARD",
766 : _,
767 17 : "System");
768 68 : SetupOutputVariable(state,
769 : "Baseboard Hot Water Mass Flow Rate",
770 : OutputProcessor::Unit::kg_s,
771 17 : HWBaseboard(BaseboardNum).WaterMassFlowRate,
772 : OutputProcessor::SOVTimeStepType::System,
773 : OutputProcessor::SOVStoreType::Average,
774 34 : HWBaseboard(BaseboardNum).EquipID);
775 68 : SetupOutputVariable(state,
776 : "Baseboard Air Mass Flow Rate",
777 : OutputProcessor::Unit::kg_s,
778 17 : HWBaseboard(BaseboardNum).AirMassFlowRate,
779 : OutputProcessor::SOVTimeStepType::System,
780 : OutputProcessor::SOVStoreType::Average,
781 34 : HWBaseboard(BaseboardNum).EquipID);
782 68 : SetupOutputVariable(state,
783 : "Baseboard Air Inlet Temperature",
784 : OutputProcessor::Unit::C,
785 17 : HWBaseboard(BaseboardNum).AirInletTemp,
786 : OutputProcessor::SOVTimeStepType::System,
787 : OutputProcessor::SOVStoreType::Average,
788 34 : HWBaseboard(BaseboardNum).EquipID);
789 68 : SetupOutputVariable(state,
790 : "Baseboard Air Outlet Temperature",
791 : OutputProcessor::Unit::C,
792 17 : HWBaseboard(BaseboardNum).AirOutletTemp,
793 : OutputProcessor::SOVTimeStepType::System,
794 : OutputProcessor::SOVStoreType::Average,
795 34 : HWBaseboard(BaseboardNum).EquipID);
796 68 : SetupOutputVariable(state,
797 : "Baseboard Water Inlet Temperature",
798 : OutputProcessor::Unit::C,
799 17 : HWBaseboard(BaseboardNum).WaterInletTemp,
800 : OutputProcessor::SOVTimeStepType::System,
801 : OutputProcessor::SOVStoreType::Average,
802 34 : HWBaseboard(BaseboardNum).EquipID);
803 68 : SetupOutputVariable(state,
804 : "Baseboard Water Outlet Temperature",
805 : OutputProcessor::Unit::C,
806 17 : HWBaseboard(BaseboardNum).WaterOutletTemp,
807 : OutputProcessor::SOVTimeStepType::System,
808 : OutputProcessor::SOVStoreType::Average,
809 34 : HWBaseboard(BaseboardNum).EquipID);
810 : }
811 7 : }
812 :
813 89527 : void InitHWBaseboard(EnergyPlusData &state, int const BaseboardNum, int const ControlledZoneNum, bool const FirstHVACIteration)
814 : {
815 :
816 : // SUBROUTINE INFORMATION:
817 : // AUTHOR Russ Taylor
818 : // Rick Strand
819 : // DATE WRITTEN Nov 1997
820 : // Feb 2001
821 : // MODIFIED Aug 2007 Daeho Kang (Add radiant component)
822 : // Sept 2010 Brent Griffith (plant interactions)
823 :
824 : // PURPOSE OF THIS SUBROUTINE:
825 : // This subroutine initializes the baseboard units, and determines the UA values during simulation.
826 :
827 : // METHODOLOGY EMPLOYED:
828 : // The initialization subrotines both in high temperature radiant radiator
829 : // and convective only baseboard radiator are combined and modified. In addition,
830 : // an UA value calculation by LMTD method is added.
831 : // The heater is assumed to be crossflow with both fluids unmixed.
832 :
833 : // REFERENCES:
834 : // 1. Incropera and DeWitt, Fundamentals of Heat and Mass Transfer
835 : // Chapter 11.3, p. 510, eq. 11.15 and 11.17
836 : // 2. I=B=R Ratings for Baseboards, Baseboard Radiation, Finned Tube (Commercial) Radiation,
837 : // and Indirect Fired Water Heaters, January 2007 Edition
838 :
839 : // Using/Aliasing
840 : using PlantUtilities::InitComponentNodes;
841 : using PlantUtilities::ScanPlantLoopsForObject;
842 :
843 89527 : Real64 constexpr Constant(0.0062); // Constant of linear equation for air mass flow rate
844 89527 : Real64 constexpr Coeff(0.0000275); // Correlation coefficient to capacity
845 : static constexpr std::string_view RoutineName("BaseboardRadiatorWater:InitHWBaseboard");
846 :
847 89527 : auto &MyOneTimeFlag = state.dataHWBaseboardRad->MyOneTimeFlag;
848 89527 : auto &MyEnvrnFlag = state.dataHWBaseboardRad->MyEnvrnFlag;
849 : int Loop;
850 : int WaterInletNode;
851 : Real64 RhoAirStdInit;
852 : Real64 rho; // local fluid density
853 : Real64 Cp; // local fluid specific heat
854 : bool errFlag;
855 :
856 89527 : auto &MySizeFlag = state.dataHWBaseboardRad->MySizeFlag;
857 89527 : auto &ZeroSourceSumHATsurf = state.dataHWBaseboardRad->ZeroSourceSumHATsurf;
858 89527 : auto &QBBRadSource = state.dataHWBaseboardRad->QBBRadSource;
859 89527 : auto &QBBRadSrcAvg = state.dataHWBaseboardRad->QBBRadSrcAvg;
860 89527 : auto &LastQBBRadSrc = state.dataHWBaseboardRad->LastQBBRadSrc;
861 89527 : auto &LastSysTimeElapsed = state.dataHWBaseboardRad->LastSysTimeElapsed;
862 89527 : auto &LastTimeStepSys = state.dataHWBaseboardRad->LastTimeStepSys;
863 89527 : auto &SetLoopIndexFlag = state.dataHWBaseboardRad->SetLoopIndexFlag;
864 89527 : auto &NumHWBaseboards = state.dataHWBaseboardRad->NumHWBaseboards;
865 89527 : auto &HWBaseboard = state.dataHWBaseboardRad->HWBaseboard;
866 :
867 : // Do the one time initializations
868 89527 : if (MyOneTimeFlag) {
869 :
870 : // Initialize the environment and sizing flags
871 7 : MyEnvrnFlag.allocate(NumHWBaseboards);
872 7 : MySizeFlag.allocate(NumHWBaseboards);
873 7 : ZeroSourceSumHATsurf.dimension(state.dataGlobal->NumOfZones, 0.0);
874 7 : QBBRadSource.dimension(NumHWBaseboards, 0.0);
875 7 : QBBRadSrcAvg.dimension(NumHWBaseboards, 0.0);
876 7 : LastQBBRadSrc.dimension(NumHWBaseboards, 0.0);
877 7 : LastSysTimeElapsed.dimension(NumHWBaseboards, 0.0);
878 7 : LastTimeStepSys.dimension(NumHWBaseboards, 0.0);
879 7 : SetLoopIndexFlag.allocate(NumHWBaseboards);
880 7 : MyEnvrnFlag = true;
881 7 : MySizeFlag = true;
882 7 : MyOneTimeFlag = false;
883 7 : SetLoopIndexFlag = true;
884 24 : for (Loop = 1; Loop <= NumHWBaseboards; ++Loop) {
885 : // Air mass flow rate is obtained from the following linear equation (reset if autosize is used)
886 : // m_dot = 0.0062 + 2.75e-05*q
887 17 : HWBaseboard(Loop).AirMassFlowRateStd = Constant + Coeff * HWBaseboard(Loop).RatedCapacity;
888 : }
889 : }
890 :
891 89527 : if (SetLoopIndexFlag(BaseboardNum)) {
892 17 : if (allocated(state.dataPlnt->PlantLoop)) {
893 17 : errFlag = false;
894 68 : ScanPlantLoopsForObject(state,
895 17 : HWBaseboard(BaseboardNum).EquipID,
896 17 : HWBaseboard(BaseboardNum).EquipType,
897 17 : HWBaseboard(BaseboardNum).plantLoc,
898 : errFlag,
899 : _,
900 : _,
901 : _,
902 : _,
903 : _);
904 17 : if (errFlag) {
905 0 : ShowFatalError(state, "InitHWBaseboard: Program terminated for previous conditions.");
906 : }
907 17 : SetLoopIndexFlag(BaseboardNum) = false;
908 : }
909 : }
910 :
911 89527 : if (!state.dataGlobal->SysSizingCalc && MySizeFlag(BaseboardNum) && !SetLoopIndexFlag(BaseboardNum)) {
912 : // For each coil, do the sizing once
913 17 : SizeHWBaseboard(state, BaseboardNum);
914 17 : MySizeFlag(BaseboardNum) = false;
915 : }
916 :
917 : // Do the Begin Environment initializations
918 89527 : if (state.dataGlobal->BeginEnvrnFlag && MyEnvrnFlag(BaseboardNum)) {
919 : // Initialize
920 102 : RhoAirStdInit = state.dataEnvrn->StdRhoAir;
921 102 : WaterInletNode = HWBaseboard(BaseboardNum).WaterInletNode;
922 :
923 204 : rho = GetDensityGlycol(state,
924 102 : state.dataPlnt->PlantLoop(HWBaseboard(BaseboardNum).plantLoc.loopNum).FluidName,
925 : DataGlobalConstants::HWInitConvTemp,
926 102 : state.dataPlnt->PlantLoop(HWBaseboard(BaseboardNum).plantLoc.loopNum).FluidIndex,
927 : RoutineName);
928 :
929 102 : HWBaseboard(BaseboardNum).WaterMassFlowRateMax = rho * HWBaseboard(BaseboardNum).WaterVolFlowRateMax;
930 :
931 306 : InitComponentNodes(state,
932 : 0.0,
933 102 : HWBaseboard(BaseboardNum).WaterMassFlowRateMax,
934 102 : HWBaseboard(BaseboardNum).WaterInletNode,
935 102 : HWBaseboard(BaseboardNum).WaterOutletNode);
936 :
937 102 : state.dataLoopNodes->Node(WaterInletNode).Temp = 60.0;
938 :
939 306 : Cp = GetSpecificHeatGlycol(state,
940 102 : state.dataPlnt->PlantLoop(HWBaseboard(BaseboardNum).plantLoc.loopNum).FluidName,
941 102 : state.dataLoopNodes->Node(WaterInletNode).Temp,
942 102 : state.dataPlnt->PlantLoop(HWBaseboard(BaseboardNum).plantLoc.loopNum).FluidIndex,
943 : RoutineName);
944 :
945 102 : state.dataLoopNodes->Node(WaterInletNode).Enthalpy = Cp * state.dataLoopNodes->Node(WaterInletNode).Temp;
946 102 : state.dataLoopNodes->Node(WaterInletNode).Quality = 0.0;
947 102 : state.dataLoopNodes->Node(WaterInletNode).Press = 0.0;
948 102 : state.dataLoopNodes->Node(WaterInletNode).HumRat = 0.0;
949 :
950 102 : ZeroSourceSumHATsurf = 0.0;
951 102 : QBBRadSource = 0.0;
952 102 : QBBRadSrcAvg = 0.0;
953 102 : LastQBBRadSrc = 0.0;
954 102 : LastSysTimeElapsed = 0.0;
955 102 : LastTimeStepSys = 0.0;
956 :
957 102 : MyEnvrnFlag(BaseboardNum) = false;
958 : }
959 :
960 89527 : if (!state.dataGlobal->BeginEnvrnFlag) {
961 88993 : MyEnvrnFlag(BaseboardNum) = true;
962 : }
963 :
964 89527 : if (state.dataGlobal->BeginTimeStepFlag && FirstHVACIteration) {
965 31094 : int ZoneNum = HWBaseboard(BaseboardNum).ZonePtr;
966 31094 : ZeroSourceSumHATsurf(ZoneNum) = state.dataHeatBal->Zone(ZoneNum).sumHATsurf(state);
967 31094 : QBBRadSrcAvg(BaseboardNum) = 0.0;
968 31094 : LastQBBRadSrc(BaseboardNum) = 0.0;
969 31094 : LastSysTimeElapsed(BaseboardNum) = 0.0;
970 31094 : LastTimeStepSys(BaseboardNum) = 0.0;
971 : }
972 :
973 : // Do the every time step initializations
974 89527 : WaterInletNode = HWBaseboard(BaseboardNum).WaterInletNode;
975 89527 : int ZoneNode = state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).ZoneNode;
976 89527 : HWBaseboard(BaseboardNum).WaterMassFlowRate = state.dataLoopNodes->Node(WaterInletNode).MassFlowRate;
977 89527 : HWBaseboard(BaseboardNum).WaterInletTemp = state.dataLoopNodes->Node(WaterInletNode).Temp;
978 89527 : HWBaseboard(BaseboardNum).WaterInletEnthalpy = state.dataLoopNodes->Node(WaterInletNode).Enthalpy;
979 89527 : HWBaseboard(BaseboardNum).AirInletTemp = state.dataLoopNodes->Node(ZoneNode).Temp;
980 89527 : HWBaseboard(BaseboardNum).AirInletHumRat = state.dataLoopNodes->Node(ZoneNode).HumRat;
981 :
982 89527 : HWBaseboard(BaseboardNum).TotPower = 0.0;
983 89527 : HWBaseboard(BaseboardNum).Power = 0.0;
984 89527 : HWBaseboard(BaseboardNum).ConvPower = 0.0;
985 89527 : HWBaseboard(BaseboardNum).RadPower = 0.0;
986 89527 : HWBaseboard(BaseboardNum).TotEnergy = 0.0;
987 89527 : HWBaseboard(BaseboardNum).Energy = 0.0;
988 89527 : HWBaseboard(BaseboardNum).ConvEnergy = 0.0;
989 89527 : HWBaseboard(BaseboardNum).RadEnergy = 0.0;
990 89527 : }
991 :
992 17 : void SizeHWBaseboard(EnergyPlusData &state, int const BaseboardNum)
993 : {
994 :
995 : // SUBROUTINE INFORMATION:
996 : // AUTHOR Fred Buhl
997 : // DATE WRITTEN February 2002
998 : // MODIFIED August 2009 Daeho Kang (Add UA autosizing by LMTD)
999 : // Aug 2013 Daeho Kang, add component sizing table entries
1000 : // July 2014, B.Nigusse, added scalable sizing
1001 : // RE-ENGINEERED na
1002 :
1003 : // PURPOSE OF THIS SUBROUTINE:
1004 : // This subroutine is for sizing hot water baseboard components
1005 :
1006 : // METHODOLOGY EMPLOYED:
1007 : // Obtains flow rates from the zone sizing arrays and plant sizing data.
1008 :
1009 : // REFERENCES:
1010 : // na
1011 :
1012 : // Using/Aliasing
1013 : using namespace DataSizing;
1014 : using DataHVACGlobals::HeatingCapacitySizing;
1015 :
1016 : using PlantUtilities::RegisterPlantCompDesignFlow;
1017 :
1018 : // Locals
1019 : // SUBROUTINE ARGUMENT DEFINITIONS:
1020 :
1021 : // SUBROUTINE PARAMETER DEFINITIONS:
1022 17 : Real64 constexpr AirInletTempStd(18.0); // I=B=R rating document
1023 17 : Real64 constexpr CPAirStd(1005.0); // Average specific heat of air at between 25C and 40C in J/kg-k
1024 17 : Real64 constexpr Constant(0.0062); // Constant of linear equation for air mass flow rate
1025 17 : Real64 constexpr Coeff(0.0000275); // Correlation coefficient to capacity
1026 : static constexpr std::string_view RoutineName("SizeHWBaseboard");
1027 : static constexpr std::string_view RoutineNameFull("BaseboardRadiatorWater:SizeHWBaseboard");
1028 :
1029 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1030 : int PltSizNum; // do loop index for plant sizing
1031 : int PltSizHeatNum; // index of plant sizing object for 1st heating loop
1032 : Real64 DesCoilLoad;
1033 : Real64 WaterInletTempStd;
1034 : Real64 WaterOutletTempStd;
1035 : Real64 AirOutletTempStd;
1036 : Real64 DeltaT1;
1037 : Real64 DeltaT2;
1038 : Real64 LMTD;
1039 : Real64 AirMassFlowRate;
1040 : Real64 WaterMassFlowRateStd;
1041 : Real64 rho; // local fluid density
1042 : Real64 Cp; // local fluid specific heat
1043 : bool ErrorsFound; // If errors detected in input
1044 : bool FlowAutoSize; // Indicator to autosize for maximum water vloume flow
1045 : bool CapAutoSize; // Indicator to autosize for capacity
1046 : Real64 WaterVolFlowRateMaxDes; // Design maximum water volume flow for reproting
1047 : Real64 WaterVolFlowRateMaxUser; // User hard-sized maximum water volume flow for reproting
1048 : Real64 RatedCapacityDes; // Design rated capacity for reproting
1049 :
1050 34 : std::string CompName; // component name
1051 34 : std::string CompType; // component type
1052 34 : std::string SizingString; // input field sizing description (e.g., Nominal Capacity)
1053 : Real64 TempSize; // autosized value of coil input field
1054 17 : int FieldNum = 1; // IDD numeric field number where input field description is found
1055 : int SizingMethod; // Integer representation of sizing method name (e.g., CoolingAirflowSizing, HeatingAirflowSizing, CoolingCapacitySizing,
1056 : // HeatingCapacitySizing, etc.)
1057 : bool PrintFlag; // TRUE when sizing information is reported in the eio file
1058 17 : int CapSizingMethod(0); // capacity sizing methods (HeatingDesignCapacity, CapacityPerFloorArea, FractionOfAutosizedCoolingCapacity, and
1059 : // FractionOfAutosizedHeatingCapacity )
1060 :
1061 17 : PltSizHeatNum = 0;
1062 17 : PltSizNum = 0;
1063 17 : DesCoilLoad = 0.0;
1064 17 : ErrorsFound = false;
1065 17 : FlowAutoSize = false;
1066 17 : CapAutoSize = false;
1067 17 : WaterVolFlowRateMaxDes = 0.0;
1068 17 : WaterVolFlowRateMaxUser = 0.0;
1069 17 : RatedCapacityDes = 0.0;
1070 17 : state.dataSize->DataScalableCapSizingON = false;
1071 :
1072 17 : auto &ZoneEqSizing(state.dataSize->ZoneEqSizing);
1073 17 : auto &HWBaseboard = state.dataHWBaseboardRad->HWBaseboard;
1074 17 : auto &HWBaseboardNumericFields = state.dataHWBaseboardRad->HWBaseboardNumericFields;
1075 :
1076 17 : if (state.dataSize->CurZoneEqNum > 0) {
1077 :
1078 17 : CompType = cCMO_BBRadiator_Water;
1079 17 : CompName = HWBaseboard(BaseboardNum).EquipID;
1080 17 : state.dataSize->DataHeatSizeRatio = 1.0;
1081 17 : state.dataSize->DataFracOfAutosizedHeatingCapacity = 1.0;
1082 17 : state.dataSize->DataZoneNumber = HWBaseboard(BaseboardNum).ZonePtr;
1083 17 : SizingMethod = HeatingCapacitySizing;
1084 17 : FieldNum = 3;
1085 17 : PrintFlag = false;
1086 17 : SizingString = HWBaseboardNumericFields(BaseboardNum).FieldNames(FieldNum) + " [W]";
1087 17 : CapSizingMethod = HWBaseboard(BaseboardNum).HeatingCapMethod;
1088 17 : ZoneEqSizing(state.dataSize->CurZoneEqNum).SizingMethod(SizingMethod) = CapSizingMethod;
1089 17 : if (CapSizingMethod == HeatingDesignCapacity || CapSizingMethod == CapacityPerFloorArea ||
1090 : CapSizingMethod == FractionOfAutosizedHeatingCapacity) {
1091 17 : if (CapSizingMethod == HeatingDesignCapacity) {
1092 17 : if (HWBaseboard(BaseboardNum).ScaledHeatingCapacity == AutoSize) {
1093 17 : CheckZoneSizing(state, CompType, CompName);
1094 17 : ZoneEqSizing(state.dataSize->CurZoneEqNum).HeatingCapacity = true;
1095 17 : ZoneEqSizing(state.dataSize->CurZoneEqNum).DesHeatingLoad =
1096 17 : state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).NonAirSysDesHeatLoad;
1097 : }
1098 17 : TempSize = HWBaseboard(BaseboardNum).ScaledHeatingCapacity;
1099 :
1100 0 : } else if (CapSizingMethod == CapacityPerFloorArea) {
1101 0 : ZoneEqSizing(state.dataSize->CurZoneEqNum).HeatingCapacity = true;
1102 0 : ZoneEqSizing(state.dataSize->CurZoneEqNum).DesHeatingLoad =
1103 0 : HWBaseboard(BaseboardNum).ScaledHeatingCapacity * state.dataHeatBal->Zone(state.dataSize->DataZoneNumber).FloorArea;
1104 0 : TempSize = ZoneEqSizing(state.dataSize->CurZoneEqNum).DesHeatingLoad;
1105 0 : state.dataSize->DataScalableCapSizingON = true;
1106 0 : } else if (CapSizingMethod == FractionOfAutosizedHeatingCapacity) {
1107 0 : CheckZoneSizing(state, CompType, CompName);
1108 0 : ZoneEqSizing(state.dataSize->CurZoneEqNum).HeatingCapacity = true;
1109 0 : state.dataSize->DataFracOfAutosizedHeatingCapacity = HWBaseboard(BaseboardNum).ScaledHeatingCapacity;
1110 0 : ZoneEqSizing(state.dataSize->CurZoneEqNum).DesHeatingLoad =
1111 0 : state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).NonAirSysDesHeatLoad;
1112 0 : TempSize = AutoSize;
1113 0 : state.dataSize->DataScalableCapSizingON = true;
1114 : } else {
1115 0 : TempSize = HWBaseboard(BaseboardNum).ScaledHeatingCapacity;
1116 : }
1117 17 : bool errorsFound = false;
1118 34 : HeatingCapacitySizer sizerHeatingCapacity;
1119 17 : sizerHeatingCapacity.overrideSizingString(SizingString);
1120 17 : sizerHeatingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
1121 17 : TempSize = sizerHeatingCapacity.size(state, TempSize, errorsFound);
1122 17 : if (HWBaseboard(BaseboardNum).ScaledHeatingCapacity == AutoSize) {
1123 17 : HWBaseboard(BaseboardNum).RatedCapacity = AutoSize;
1124 : } else {
1125 0 : HWBaseboard(BaseboardNum).RatedCapacity = TempSize;
1126 : }
1127 17 : RatedCapacityDes = TempSize;
1128 17 : state.dataSize->DataScalableCapSizingON = false;
1129 : }
1130 : }
1131 :
1132 : // find the appropriate heating Plant Sizing object
1133 17 : PltSizHeatNum = state.dataPlnt->PlantLoop(HWBaseboard(BaseboardNum).plantLoc.loopNum).PlantSizNum;
1134 :
1135 17 : if (PltSizHeatNum > 0) {
1136 17 : if (state.dataSize->CurZoneEqNum > 0) {
1137 :
1138 17 : if (HWBaseboard(BaseboardNum).WaterVolFlowRateMax == AutoSize) {
1139 17 : FlowAutoSize = true;
1140 : }
1141 17 : if (!FlowAutoSize && !state.dataSize->ZoneSizingRunDone) { // Simulation continue
1142 0 : if (HWBaseboard(BaseboardNum).WaterVolFlowRateMax > 0.0) {
1143 0 : BaseSizer::reportSizerOutput(state,
1144 : cCMO_BBRadiator_Water,
1145 0 : HWBaseboard(BaseboardNum).EquipID,
1146 : "User-Specified Maximum Water Flow Rate [m3/s]",
1147 0 : HWBaseboard(BaseboardNum).WaterVolFlowRateMax);
1148 : }
1149 : } else {
1150 17 : CheckZoneSizing(state, cCMO_BBRadiator_Water, HWBaseboard(BaseboardNum).EquipID);
1151 17 : DesCoilLoad = RatedCapacityDes;
1152 17 : if (DesCoilLoad >= SmallLoad) {
1153 34 : Cp = GetSpecificHeatGlycol(state,
1154 17 : state.dataPlnt->PlantLoop(HWBaseboard(BaseboardNum).plantLoc.loopNum).FluidName,
1155 : DataGlobalConstants::HWInitConvTemp,
1156 17 : state.dataPlnt->PlantLoop(HWBaseboard(BaseboardNum).plantLoc.loopNum).FluidIndex,
1157 : RoutineName);
1158 34 : rho = GetDensityGlycol(state,
1159 17 : state.dataPlnt->PlantLoop(HWBaseboard(BaseboardNum).plantLoc.loopNum).FluidName,
1160 : DataGlobalConstants::HWInitConvTemp,
1161 17 : state.dataPlnt->PlantLoop(HWBaseboard(BaseboardNum).plantLoc.loopNum).FluidIndex,
1162 : RoutineName);
1163 17 : WaterVolFlowRateMaxDes = DesCoilLoad / (state.dataSize->PlantSizData(PltSizHeatNum).DeltaT * Cp * rho);
1164 : } else {
1165 0 : WaterVolFlowRateMaxDes = 0.0;
1166 : }
1167 :
1168 17 : if (FlowAutoSize) {
1169 17 : HWBaseboard(BaseboardNum).WaterVolFlowRateMax = WaterVolFlowRateMaxDes;
1170 34 : BaseSizer::reportSizerOutput(state,
1171 : cCMO_BBRadiator_Water,
1172 17 : HWBaseboard(BaseboardNum).EquipID,
1173 : "Design Size Maximum Water Flow Rate [m3/s]",
1174 17 : WaterVolFlowRateMaxDes);
1175 : } else { // Hard-sized with sizing data
1176 0 : if (HWBaseboard(BaseboardNum).WaterVolFlowRateMax > 0.0 && WaterVolFlowRateMaxDes > 0.0) {
1177 0 : WaterVolFlowRateMaxUser = HWBaseboard(BaseboardNum).WaterVolFlowRateMax;
1178 0 : BaseSizer::reportSizerOutput(state,
1179 : cCMO_BBRadiator_Water,
1180 0 : HWBaseboard(BaseboardNum).EquipID,
1181 : "Design Size Maximum Water Flow Rate [m3/s]",
1182 : WaterVolFlowRateMaxDes,
1183 : "User-Specified Maximum Water Flow Rate [m3/s]",
1184 0 : WaterVolFlowRateMaxUser);
1185 0 : if (state.dataGlobal->DisplayExtraWarnings) {
1186 0 : if ((std::abs(WaterVolFlowRateMaxDes - WaterVolFlowRateMaxUser) / WaterVolFlowRateMaxUser) >
1187 0 : state.dataSize->AutoVsHardSizingThreshold) {
1188 0 : ShowMessage(
1189 : state,
1190 0 : "SizeHWBaseboard: Potential issue with equipment sizing for ZoneHVAC:Baseboard:RadiantConvective:Water=\"" +
1191 0 : HWBaseboard(BaseboardNum).EquipID + "\".");
1192 0 : ShowContinueError(state,
1193 0 : format("User-Specified Maximum Water Flow Rate of {:.5R} [m3/s]", WaterVolFlowRateMaxUser));
1194 0 : ShowContinueError(
1195 0 : state, format("differs from Design Size Maximum Water Flow Rate of {:.5R} [m3/s]", WaterVolFlowRateMaxDes));
1196 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
1197 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
1198 : }
1199 : }
1200 : }
1201 : }
1202 : }
1203 34 : if (HWBaseboard(BaseboardNum).WaterTempAvg > 0.0 && HWBaseboard(BaseboardNum).WaterMassFlowRateStd > 0.0 &&
1204 17 : HWBaseboard(BaseboardNum).RatedCapacity > 0.0) {
1205 0 : DesCoilLoad = HWBaseboard(BaseboardNum).RatedCapacity;
1206 0 : WaterMassFlowRateStd = HWBaseboard(BaseboardNum).WaterMassFlowRateStd;
1207 17 : } else if (HWBaseboard(BaseboardNum).RatedCapacity == AutoSize || HWBaseboard(BaseboardNum).RatedCapacity == 0.0) {
1208 17 : DesCoilLoad = RatedCapacityDes;
1209 34 : rho = GetDensityGlycol(state,
1210 17 : state.dataPlnt->PlantLoop(HWBaseboard(BaseboardNum).plantLoc.loopNum).FluidName,
1211 : DataGlobalConstants::HWInitConvTemp,
1212 17 : state.dataPlnt->PlantLoop(HWBaseboard(BaseboardNum).plantLoc.loopNum).FluidIndex,
1213 : RoutineNameFull);
1214 17 : WaterMassFlowRateStd = HWBaseboard(BaseboardNum).WaterVolFlowRateMax * rho;
1215 : }
1216 17 : if (DesCoilLoad >= SmallLoad) {
1217 : // Calculate UA value
1218 : // Air mass flow rate is obtained from the following linear equation
1219 : // m_dot = 0.0062 + 2.75e-05*q
1220 17 : AirMassFlowRate = Constant + Coeff * DesCoilLoad;
1221 51 : Cp = GetSpecificHeatGlycol(state,
1222 17 : state.dataPlnt->PlantLoop(HWBaseboard(BaseboardNum).plantLoc.loopNum).FluidName,
1223 17 : HWBaseboard(BaseboardNum).WaterTempAvg,
1224 17 : state.dataPlnt->PlantLoop(HWBaseboard(BaseboardNum).plantLoc.loopNum).FluidIndex,
1225 : RoutineName);
1226 17 : WaterInletTempStd = (DesCoilLoad / (2.0 * WaterMassFlowRateStd * Cp)) + HWBaseboard(BaseboardNum).WaterTempAvg;
1227 17 : WaterOutletTempStd = std::abs((2.0 * HWBaseboard(BaseboardNum).WaterTempAvg) - WaterInletTempStd);
1228 17 : AirOutletTempStd = (DesCoilLoad / (AirMassFlowRate * CPAirStd)) + AirInletTempStd;
1229 17 : HWBaseboard(BaseboardNum).AirMassFlowRateStd = AirMassFlowRate;
1230 : // Check Ta,out < Tw,in
1231 17 : if (AirOutletTempStd >= WaterInletTempStd) {
1232 0 : ShowSevereError(state,
1233 0 : "SizeHWBaseboard: ZoneHVAC:Baseboard:RadiantConvective:Water=\"" + HWBaseboard(BaseboardNum).EquipID + "\".");
1234 0 : ShowContinueError(state, "...Air Outlet temperature must be below the Water Inlet temperature");
1235 0 : ShowContinueError(
1236 : state,
1237 0 : format("...Air Outlet Temperature=[{:.2R}], Water Inlet Temperature=[{:.2R}].", AirOutletTempStd, WaterInletTempStd));
1238 0 : AirOutletTempStd = WaterInletTempStd - 0.01;
1239 0 : ShowContinueError(state, format("...Air Outlet Temperature set to [{:.2R}].", AirOutletTempStd));
1240 : }
1241 : // Check Tw,out < Ta,in
1242 17 : if (AirInletTempStd >= WaterOutletTempStd) {
1243 0 : ShowSevereError(state,
1244 0 : "SizeHWBaseboard: ZoneHVAC:Baseboard:RadiantConvective:Water=\"" + HWBaseboard(BaseboardNum).EquipID + "\".");
1245 0 : ShowContinueError(state, "...Water Outlet temperature must be below the Air Inlet temperature");
1246 0 : ShowContinueError(
1247 : state,
1248 0 : format("...Air Inlet Temperature=[{:.2R}], Water Outlet Temperature=[{:.2R}].", AirInletTempStd, WaterOutletTempStd));
1249 0 : WaterOutletTempStd = AirInletTempStd + 0.01;
1250 0 : ShowContinueError(state, format("...Water Outlet Temperature set to [{:.2R}].", WaterOutletTempStd));
1251 : }
1252 : // LMTD calculation
1253 17 : DeltaT1 = WaterInletTempStd - AirOutletTempStd;
1254 17 : DeltaT2 = WaterOutletTempStd - AirInletTempStd;
1255 17 : LMTD = (DeltaT1 - DeltaT2) / (std::log(DeltaT1 / DeltaT2));
1256 17 : HWBaseboard(BaseboardNum).UA = DesCoilLoad / LMTD;
1257 : } else {
1258 0 : HWBaseboard(BaseboardNum).UA = 0.0;
1259 : }
1260 : // Report an UA value
1261 51 : BaseSizer::reportSizerOutput(
1262 34 : state, cCMO_BBRadiator_Water, HWBaseboard(BaseboardNum).EquipID, "U-Factor times Area [W/C]", HWBaseboard(BaseboardNum).UA);
1263 : }
1264 : } else {
1265 : // if there is no heating Sizing:Plant object and autosizng was requested, issue an error message
1266 0 : if (HWBaseboard(BaseboardNum).WaterVolFlowRateMax == AutoSize || HWBaseboard(BaseboardNum).RatedCapacity == AutoSize ||
1267 0 : HWBaseboard(BaseboardNum).RatedCapacity == 0.0) {
1268 0 : ShowSevereError(state, "Autosizing of hot water baseboard requires a heating loop Sizing:Plant object");
1269 0 : ShowContinueError(state, "Occurs in Hot Water Baseboard Heater=" + HWBaseboard(BaseboardNum).EquipID);
1270 0 : ErrorsFound = true;
1271 : }
1272 : // calculate UA from rated capacities
1273 0 : HWBaseboard(BaseboardNum).RatedCapacity = RatedCapacityDes;
1274 0 : DesCoilLoad = RatedCapacityDes;
1275 :
1276 0 : if (DesCoilLoad >= SmallLoad) {
1277 0 : WaterMassFlowRateStd = HWBaseboard(BaseboardNum).WaterMassFlowRateStd;
1278 : // m_dot = 0.0062 + 2.75e-05*q
1279 0 : AirMassFlowRate = Constant + Coeff * DesCoilLoad;
1280 0 : Cp = GetSpecificHeatGlycol(state,
1281 0 : state.dataPlnt->PlantLoop(HWBaseboard(BaseboardNum).plantLoc.loopNum).FluidName,
1282 0 : HWBaseboard(BaseboardNum).WaterTempAvg,
1283 0 : state.dataPlnt->PlantLoop(HWBaseboard(BaseboardNum).plantLoc.loopNum).FluidIndex,
1284 : RoutineName);
1285 0 : WaterInletTempStd = (DesCoilLoad / (2.0 * WaterMassFlowRateStd * Cp)) + HWBaseboard(BaseboardNum).WaterTempAvg;
1286 0 : WaterOutletTempStd = std::abs((2.0 * HWBaseboard(BaseboardNum).WaterTempAvg) - WaterInletTempStd);
1287 0 : AirOutletTempStd = (DesCoilLoad / (AirMassFlowRate * CPAirStd)) + AirInletTempStd;
1288 0 : HWBaseboard(BaseboardNum).AirMassFlowRateStd = AirMassFlowRate;
1289 :
1290 : // Check Ta,out < Tw,in
1291 0 : if (AirOutletTempStd >= WaterInletTempStd) {
1292 0 : ShowSevereError(state,
1293 0 : "SizeHWBaseboard: ZoneHVAC:Baseboard:RadiantConvective:Water=\"" + HWBaseboard(BaseboardNum).EquipID + "\".");
1294 0 : ShowContinueError(state, "...Air Outlet temperature must be below the Water Inlet temperature");
1295 0 : ShowContinueError(
1296 0 : state, format("...Air Outlet Temperature=[{:.2R}], Water Inlet Temperature=[{:.2R}].", AirOutletTempStd, WaterInletTempStd));
1297 0 : AirOutletTempStd = WaterInletTempStd - 0.01;
1298 0 : ShowContinueError(state, format("...Air Outlet Temperature set to [{:.2R}].", AirOutletTempStd));
1299 : }
1300 : // Check Tw,out < Ta,in
1301 0 : if (AirInletTempStd >= WaterOutletTempStd) {
1302 0 : ShowSevereError(state,
1303 0 : "SizeHWBaseboard: ZoneHVAC:Baseboard:RadiantConvective:Water=\"" + HWBaseboard(BaseboardNum).EquipID + "\".");
1304 0 : ShowContinueError(state, "...Water Outlet temperature must be below the Air Inlet temperature");
1305 0 : ShowContinueError(
1306 0 : state, format("...Air Inlet Temperature=[{:.2R}], Water Outlet Temperature=[{:.2R}].", AirInletTempStd, WaterOutletTempStd));
1307 0 : WaterOutletTempStd = AirInletTempStd + 0.01;
1308 0 : ShowContinueError(state, format("...Water Outlet Temperature set to [{:.2R}].", WaterOutletTempStd));
1309 : }
1310 : // LMTD calculation
1311 0 : DeltaT1 = WaterInletTempStd - AirOutletTempStd;
1312 0 : DeltaT2 = WaterOutletTempStd - AirInletTempStd;
1313 0 : LMTD = (DeltaT1 - DeltaT2) / (std::log(DeltaT1 / DeltaT2));
1314 0 : HWBaseboard(BaseboardNum).UA = DesCoilLoad / LMTD;
1315 : } else {
1316 0 : HWBaseboard(BaseboardNum).UA = 0.0;
1317 : }
1318 : // Report an UA value
1319 0 : BaseSizer::reportSizerOutput(
1320 0 : state, cCMO_BBRadiator_Water, HWBaseboard(BaseboardNum).EquipID, "U-Factor times Area [W/C]", HWBaseboard(BaseboardNum).UA);
1321 : }
1322 : // save the design water flow rate for use by the water loop sizing algorithms
1323 17 : RegisterPlantCompDesignFlow(state, HWBaseboard(BaseboardNum).WaterInletNode, HWBaseboard(BaseboardNum).WaterVolFlowRateMax);
1324 :
1325 17 : if (ErrorsFound) {
1326 0 : ShowFatalError(state, "Preceding sizing errors cause program termination");
1327 : }
1328 17 : }
1329 :
1330 162274 : void CalcHWBaseboard(EnergyPlusData &state, int &BaseboardNum, Real64 &LoadMet)
1331 : {
1332 : // SUBROUTINE INFORMATION:
1333 : // AUTHOR Russ Taylor
1334 : // DATE WRITTEN Nov 1997
1335 : // MODIFIED May 2000 Fred Buhl
1336 : // Aug 2007 Daeho Kang (Add the calculation of radiant heat source)
1337 : // Sep 2011 LKL/BG - resimulate only zones needing it for Radiant systems
1338 : // RE-ENGINEERED na
1339 :
1340 : // PURPOSE OF THIS SUBROUTINE:
1341 : // This subroutine calculates both the convective and radiant heat transfer rate
1342 : // in a hot water baseboard heater. The heater is assumed to be crossflowwith
1343 : // both fluids unmixed. The air flow is buoyancy driven and a constant airflow
1344 : // and a constant airflow velocity of 0.5m/s is assumed.
1345 :
1346 : // METHODOLOGY EMPLOYED:
1347 : // na
1348 :
1349 : // REFERENCES:
1350 : // Incropera and DeWitt, Fundamentals of Heat and Mass Transfer
1351 : // Chapter 11.4, p. 523, eq. 11.33
1352 :
1353 : // Using/Aliasing
1354 : using namespace DataSizing;
1355 : using PlantUtilities::SetActuatedBranchFlowRate;
1356 : using ScheduleManager::GetCurrentScheduleValue;
1357 :
1358 : // Locals
1359 : // SUBROUTINE ARGUMENT DEFINITIONS:
1360 :
1361 : // SUBROUTINE PARAMETER DEFINITIONS:
1362 162274 : Real64 constexpr MinFrac(0.0005); // Minimum fraction that delivers radiant heats to surfaces
1363 : static constexpr std::string_view RoutineName("CalcHWBaseboard");
1364 :
1365 : // INTERFACE BLOCK SPECIFICATIONS
1366 : // na
1367 :
1368 : // DERIVED TYPE DEFINITIONS
1369 : // na
1370 :
1371 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1372 : int ZoneNum;
1373 : Real64 RadHeat;
1374 : Real64 BBHeat;
1375 : Real64 AirInletTemp;
1376 : Real64 AirOutletTemp;
1377 : Real64 WaterInletTemp;
1378 : Real64 WaterOutletTemp;
1379 : Real64 WaterMassFlowRate;
1380 : Real64 AirMassFlowRate;
1381 : Real64 CapacitanceAir;
1382 : Real64 CapacitanceWater;
1383 : Real64 CapacitanceMax;
1384 : Real64 CapacitanceMin;
1385 : Real64 CapacityRatio;
1386 : Real64 NTU;
1387 : Real64 Effectiveness;
1388 : Real64 AA;
1389 : Real64 BB;
1390 : Real64 CC;
1391 : Real64 QZnReq;
1392 : Real64 Cp;
1393 162274 : auto &HWBaseboard = state.dataHWBaseboardRad->HWBaseboard;
1394 162274 : auto &HWBaseboardDesignObject = state.dataHWBaseboardRad->HWBaseboardDesignObject;
1395 162274 : auto &QBBRadSource = state.dataHWBaseboardRad->QBBRadSource;
1396 162274 : auto &ZeroSourceSumHATsurf = state.dataHWBaseboardRad->ZeroSourceSumHATsurf;
1397 :
1398 162274 : ZoneNum = HWBaseboard(BaseboardNum).ZonePtr;
1399 162274 : QZnReq = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).RemainingOutputReqToHeatSP;
1400 162274 : AirInletTemp = HWBaseboard(BaseboardNum).AirInletTemp;
1401 162274 : AirOutletTemp = AirInletTemp;
1402 162274 : WaterInletTemp = HWBaseboard(BaseboardNum).WaterInletTemp;
1403 162274 : WaterOutletTemp = WaterInletTemp;
1404 162274 : WaterMassFlowRate = state.dataLoopNodes->Node(HWBaseboard(BaseboardNum).WaterInletNode).MassFlowRate;
1405 : HWBaseboardDesignData HWBaseboardDesignDataObject{
1406 324548 : HWBaseboardDesignObject(HWBaseboard(BaseboardNum).DesignObjectPtr)}; // Contains the data for the design object
1407 :
1408 313234 : if (QZnReq > SmallLoad && !state.dataZoneEnergyDemand->CurDeadBandOrSetback(ZoneNum) &&
1409 313234 : (GetCurrentScheduleValue(state, HWBaseboard(BaseboardNum).SchedPtr) > 0) && (WaterMassFlowRate > 0.0)) {
1410 : // Calculate air mass flow rate
1411 69252 : AirMassFlowRate = HWBaseboard(BaseboardNum).AirMassFlowRateStd * (WaterMassFlowRate / HWBaseboard(BaseboardNum).WaterMassFlowRateMax);
1412 69252 : CapacitanceAir = PsyCpAirFnW(HWBaseboard(BaseboardNum).AirInletHumRat) * AirMassFlowRate;
1413 138504 : Cp = GetSpecificHeatGlycol(state,
1414 69252 : state.dataPlnt->PlantLoop(HWBaseboard(BaseboardNum).plantLoc.loopNum).FluidName,
1415 : WaterInletTemp,
1416 69252 : state.dataPlnt->PlantLoop(HWBaseboard(BaseboardNum).plantLoc.loopNum).FluidIndex,
1417 : RoutineName);
1418 :
1419 69252 : CapacitanceWater = Cp * WaterMassFlowRate;
1420 69252 : CapacitanceMax = max(CapacitanceAir, CapacitanceWater);
1421 69252 : CapacitanceMin = min(CapacitanceAir, CapacitanceWater);
1422 69252 : CapacityRatio = CapacitanceMin / CapacitanceMax;
1423 69252 : NTU = HWBaseboard(BaseboardNum).UA / CapacitanceMin;
1424 :
1425 : // The effectiveness is given by the following formula:
1426 : // Effectiveness = 1. - EXP((1./CapacityRatio)*(NTU)**0.22*(EXP(-CapacityRatio*(NTU)**0.78)-1.))
1427 : // To prevent possible underflows (numbers smaller than the computer can handle) we must break
1428 : // the calculation up into steps and check the size of the exponential arguments.
1429 69252 : AA = -CapacityRatio * std::pow(NTU, 0.78);
1430 69252 : if (AA < -20.0) {
1431 66 : BB = 0.0;
1432 : } else {
1433 69186 : BB = std::exp(AA);
1434 : }
1435 69252 : CC = (1.0 / CapacityRatio) * std::pow(NTU, 0.22) * (BB - 1.0);
1436 69252 : if (CC < -20.0) {
1437 11 : Effectiveness = 1.0;
1438 : } else {
1439 69241 : Effectiveness = 1.0 - std::exp(CC);
1440 : }
1441 :
1442 69252 : AirOutletTemp = AirInletTemp + Effectiveness * CapacitanceMin * (WaterInletTemp - AirInletTemp) / CapacitanceAir;
1443 69252 : WaterOutletTemp = WaterInletTemp - CapacitanceAir * (AirOutletTemp - AirInletTemp) / CapacitanceWater;
1444 69252 : BBHeat = CapacitanceWater * (WaterInletTemp - WaterOutletTemp);
1445 69252 : RadHeat = BBHeat * HWBaseboardDesignDataObject.FracRadiant;
1446 69252 : QBBRadSource(BaseboardNum) = RadHeat;
1447 :
1448 69252 : if (HWBaseboardDesignDataObject.FracRadiant <= MinFrac) {
1449 31368 : LoadMet = BBHeat;
1450 : } else {
1451 :
1452 : // Now, distribute the radiant energy of all systems to the appropriate surfaces, to people, and the air
1453 37884 : DistributeBBRadGains(state);
1454 : // Now "simulate" the system by recalculating the heat balances
1455 37884 : HeatBalanceSurfaceManager::CalcHeatBalanceOutsideSurf(state, ZoneNum);
1456 :
1457 37884 : HeatBalanceSurfaceManager::CalcHeatBalanceInsideSurf(state, ZoneNum);
1458 :
1459 : // Here an assumption is made regarding radiant heat transfer to people.
1460 : // While the radiant heat transfer to people array will be used by the thermal comfort
1461 : // routines, the energy transfer to people would get lost from the perspective
1462 : // of the heat balance. So, to avoid this net loss of energy which clearly
1463 : // gets added to the zones, we must account for it somehow. This assumption
1464 : // that all energy radiated to people is converted to convective energy is
1465 : // not very precise, but at least it conserves energy. The system impact to heat balance
1466 : // should include this.
1467 113652 : LoadMet = (state.dataHeatBal->Zone(ZoneNum).sumHATsurf(state) - ZeroSourceSumHATsurf(ZoneNum)) +
1468 75768 : (BBHeat * HWBaseboard(BaseboardNum).FracConvect) + (RadHeat * HWBaseboardDesignDataObject.FracDistribPerson);
1469 : }
1470 69252 : HWBaseboard(BaseboardNum).WaterOutletEnthalpy = HWBaseboard(BaseboardNum).WaterInletEnthalpy - BBHeat / WaterMassFlowRate;
1471 : } else {
1472 93022 : CapacitanceWater = 0.0;
1473 93022 : CapacitanceMax = 0.0;
1474 93022 : CapacitanceMin = 0.0;
1475 93022 : NTU = 0.0;
1476 93022 : Effectiveness = 0.0;
1477 93022 : AirOutletTemp = AirInletTemp;
1478 93022 : WaterOutletTemp = WaterInletTemp;
1479 93022 : BBHeat = 0.0;
1480 93022 : LoadMet = 0.0;
1481 93022 : RadHeat = 0.0;
1482 93022 : WaterMassFlowRate = 0.0;
1483 93022 : AirMassFlowRate = 0.0;
1484 93022 : QBBRadSource(BaseboardNum) = 0.0;
1485 93022 : HWBaseboard(BaseboardNum).WaterOutletEnthalpy = HWBaseboard(BaseboardNum).WaterInletEnthalpy;
1486 93022 : SetActuatedBranchFlowRate(state, WaterMassFlowRate, HWBaseboard(BaseboardNum).WaterInletNode, HWBaseboard(BaseboardNum).plantLoc, false);
1487 : }
1488 :
1489 162274 : HWBaseboard(BaseboardNum).WaterOutletTemp = WaterOutletTemp;
1490 162274 : HWBaseboard(BaseboardNum).AirOutletTemp = AirOutletTemp;
1491 162274 : HWBaseboard(BaseboardNum).WaterMassFlowRate = WaterMassFlowRate;
1492 162274 : HWBaseboard(BaseboardNum).AirMassFlowRate = AirMassFlowRate;
1493 162274 : HWBaseboard(BaseboardNum).TotPower = LoadMet;
1494 162274 : HWBaseboard(BaseboardNum).Power = BBHeat;
1495 162274 : HWBaseboard(BaseboardNum).ConvPower = BBHeat - RadHeat;
1496 162274 : HWBaseboard(BaseboardNum).RadPower = RadHeat;
1497 162274 : }
1498 :
1499 89527 : void UpdateHWBaseboard(EnergyPlusData &state, int const BaseboardNum)
1500 : {
1501 :
1502 : // SUBROUTINE INFORMATION:
1503 : // AUTHOR Russ Taylor
1504 : // Rick Strand
1505 : // DATE WRITTEN Nov 1997
1506 : // February 2001
1507 : // MODIFIED Aug 2007 Daeho Kang (Add the update of radiant source)
1508 : // RE-ENGINEERED na
1509 :
1510 : // PURPOSE OF THIS SUBROUTINE:
1511 :
1512 : // METHODOLOGY EMPLOYED:
1513 : // The update subrotines both in high temperature radiant radiator
1514 : // and convective only baseboard radiator are combined and modified.
1515 :
1516 : // REFERENCES:
1517 : // na
1518 :
1519 : // Using/Aliasing
1520 : using PlantUtilities::SafeCopyPlantNode;
1521 :
1522 : // Locals
1523 : // SUBROUTINE ARGUMENT DEFINITIONS:
1524 :
1525 : // SUBROUTINE PARAMETER DEFINITIONS:
1526 : // na
1527 :
1528 : // INTERFACE BLOCK SPECIFICATIONS
1529 : // na
1530 :
1531 : // DERIVED TYPE DEFINITIONS
1532 : // na
1533 :
1534 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1535 : int WaterInletNode;
1536 : int WaterOutletNode;
1537 89527 : auto &Iter = state.dataHWBaseboardRad->Iter;
1538 89527 : auto &MyEnvrnFlag2 = state.dataHWBaseboardRad->MyEnvrnFlag2;
1539 89527 : auto &HWBaseboard = state.dataHWBaseboardRad->HWBaseboard;
1540 89527 : auto &LastSysTimeElapsed = state.dataHWBaseboardRad->LastSysTimeElapsed;
1541 89527 : auto &QBBRadSrcAvg = state.dataHWBaseboardRad->QBBRadSrcAvg;
1542 89527 : auto &LastQBBRadSrc = state.dataHWBaseboardRad->LastQBBRadSrc;
1543 89527 : auto &QBBRadSource = state.dataHWBaseboardRad->QBBRadSource;
1544 89527 : auto &LastTimeStepSys = state.dataHWBaseboardRad->LastTimeStepSys;
1545 :
1546 89527 : if (state.dataGlobal->BeginEnvrnFlag && MyEnvrnFlag2) {
1547 42 : Iter = 0;
1548 42 : MyEnvrnFlag2 = false;
1549 : }
1550 89527 : if (!state.dataGlobal->BeginEnvrnFlag) {
1551 88993 : MyEnvrnFlag2 = true;
1552 : }
1553 :
1554 : // First, update the running average if necessary...
1555 89527 : if (LastSysTimeElapsed(BaseboardNum) == state.dataHVACGlobal->SysTimeElapsed) {
1556 82993 : QBBRadSrcAvg(BaseboardNum) -= LastQBBRadSrc(BaseboardNum) * LastTimeStepSys(BaseboardNum) / state.dataGlobal->TimeStepZone;
1557 : }
1558 : // Update the running average and the "last" values with the current values of the appropriate variables
1559 89527 : QBBRadSrcAvg(BaseboardNum) += QBBRadSource(BaseboardNum) * state.dataHVACGlobal->TimeStepSys / state.dataGlobal->TimeStepZone;
1560 :
1561 89527 : LastQBBRadSrc(BaseboardNum) = QBBRadSource(BaseboardNum);
1562 89527 : LastSysTimeElapsed(BaseboardNum) = state.dataHVACGlobal->SysTimeElapsed;
1563 89527 : LastTimeStepSys(BaseboardNum) = state.dataHVACGlobal->TimeStepSys;
1564 :
1565 89527 : WaterInletNode = HWBaseboard(BaseboardNum).WaterInletNode;
1566 89527 : WaterOutletNode = HWBaseboard(BaseboardNum).WaterOutletNode;
1567 :
1568 : // Set the outlet air nodes of the Baseboard
1569 : // Set the outlet water nodes for the Coil
1570 89527 : SafeCopyPlantNode(state, WaterInletNode, WaterOutletNode);
1571 89527 : state.dataLoopNodes->Node(WaterOutletNode).Temp = HWBaseboard(BaseboardNum).WaterOutletTemp;
1572 89527 : state.dataLoopNodes->Node(WaterOutletNode).Enthalpy = HWBaseboard(BaseboardNum).WaterOutletEnthalpy;
1573 89527 : }
1574 :
1575 2568313 : void UpdateBBRadSourceValAvg(EnergyPlusData &state, bool &HWBaseboardSysOn) // .TRUE. if the radiant system has run this zone time step
1576 : {
1577 :
1578 : // SUBROUTINE INFORMATION:
1579 : // AUTHOR Rick Strand
1580 : // DATE WRITTEN February 2001
1581 : // MODIFIED Aug 2007 Daeho Kang (Modification only for baseboard)
1582 : // RE-ENGINEERED na
1583 :
1584 : // PURPOSE OF THIS SUBROUTINE:
1585 : // To transfer the average value of the heat source over the entire
1586 : // zone time step back to the heat balance routines so that the heat
1587 : // balance algorithms can simulate one last time with the average source
1588 : // to maintain some reasonable amount of continuity and energy balance
1589 : // in the temperature and flux histories.
1590 :
1591 : // METHODOLOGY EMPLOYED:
1592 : // All of the record keeping for the average term is done in the Update
1593 : // routine so the only other thing that this subroutine does is check to
1594 : // see if the system was even on. If any average term is non-zero, then
1595 : // one or more of the radiant systems was running.
1596 :
1597 : // REFERENCES:
1598 : // na
1599 :
1600 : // USE STATEMENTS:
1601 : // na
1602 :
1603 : // Locals
1604 : // SUBROUTINE ARGUMENT DEFINITIONS:
1605 :
1606 : // SUBROUTINE PARAMETER DEFINITIONS:
1607 : // na
1608 :
1609 : // INTERFACE BLOCK SPECIFICATIONS
1610 : // na
1611 :
1612 : // DERIVED TYPE DEFINITIONS
1613 : // na
1614 :
1615 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1616 : int BaseboardNum; // DO loop counter for surface index
1617 :
1618 2568313 : HWBaseboardSysOn = false;
1619 :
1620 : // If this was never allocated, then there are no radiant systems in this input file (just RETURN)
1621 2568313 : if (!allocated(state.dataHWBaseboardRad->QBBRadSrcAvg)) return;
1622 :
1623 : // If it was allocated, then we have to check to see if this was running at all...
1624 32544 : for (BaseboardNum = 1; BaseboardNum <= state.dataHWBaseboardRad->NumHWBaseboards; ++BaseboardNum) {
1625 25068 : if (state.dataHWBaseboardRad->QBBRadSrcAvg(BaseboardNum) != 0.0) {
1626 6048 : HWBaseboardSysOn = true;
1627 6048 : break; // DO loop
1628 : }
1629 : }
1630 :
1631 13524 : state.dataHWBaseboardRad->QBBRadSource = state.dataHWBaseboardRad->QBBRadSrcAvg;
1632 :
1633 13524 : DistributeBBRadGains(state); // QBBRadSource has been modified so we need to redistribute gains
1634 : }
1635 :
1636 51408 : void DistributeBBRadGains(EnergyPlusData &state)
1637 : {
1638 :
1639 : // SUBROUTINE INFORMATION:
1640 : // AUTHOR Rick Strand
1641 : // DATE WRITTEN February 2001
1642 : // MODIFIED Aug. 2007 Daeho Kang (Modification only for baseboard)
1643 : // April 2010 Brent Griffith, max limit to protect surface temperature calcs
1644 : // RE-ENGINEERED na
1645 :
1646 : // PURPOSE OF THIS SUBROUTINE:
1647 : // To distribute the gains from the hot water basebaord heater
1648 : // as specified in the user input file. This includes distribution
1649 : // of long wavelength radiant gains to surfaces and "people."
1650 :
1651 : // METHODOLOGY EMPLOYED:
1652 : // We must cycle through all of the radiant systems because each
1653 : // surface could feel the effect of more than one radiant system.
1654 : // Note that the energy radiated to people is assumed to affect them
1655 : // but them it is assumed to be convected to the air.
1656 :
1657 : // Using/Aliasing
1658 : using DataHeatBalFanSys::MaxRadHeatFlux;
1659 :
1660 : // SUBROUTINE PARAMETER DEFINITIONS:
1661 51408 : Real64 constexpr SmallestArea(0.001); // Smallest area in meters squared (to avoid a divide by zero)
1662 :
1663 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1664 : int RadSurfNum; // Counter for surfaces receiving radiation from radiant heater
1665 : int BaseboardNum; // Counter for the baseboard
1666 : int SurfNum; // Pointer to the Surface derived type
1667 : int ZoneNum; // Pointer to the Zone derived type
1668 : Real64 ThisSurfIntensity; // temporary for W/m2 term for rad on a surface
1669 :
1670 51408 : auto &NumHWBaseboards = state.dataHWBaseboardRad->NumHWBaseboards;
1671 51408 : auto &HWBaseboard = state.dataHWBaseboardRad->HWBaseboard;
1672 51408 : auto &HWBaseboardDesignObject = state.dataHWBaseboardRad->HWBaseboardDesignObject;
1673 51408 : auto &QBBRadSource = state.dataHWBaseboardRad->QBBRadSource;
1674 :
1675 : // Initialize arrays
1676 51408 : state.dataHeatBalFanSys->SurfQHWBaseboard = 0.0;
1677 51408 : state.dataHeatBalFanSys->ZoneQHWBaseboardToPerson = 0.0;
1678 :
1679 158292 : for (BaseboardNum = 1; BaseboardNum <= NumHWBaseboards; ++BaseboardNum) {
1680 :
1681 : HWBaseboardDesignData HWBaseboardDesignDataObject{
1682 213768 : HWBaseboardDesignObject(HWBaseboard(BaseboardNum).DesignObjectPtr)}; // Contains the data for the design object
1683 106884 : ZoneNum = HWBaseboard(BaseboardNum).ZonePtr;
1684 106884 : if (ZoneNum <= 0) continue;
1685 106884 : state.dataHeatBalFanSys->ZoneQHWBaseboardToPerson(ZoneNum) += QBBRadSource(BaseboardNum) * HWBaseboardDesignDataObject.FracDistribPerson;
1686 :
1687 407196 : for (RadSurfNum = 1; RadSurfNum <= HWBaseboard(BaseboardNum).TotSurfToDistrib; ++RadSurfNum) {
1688 300312 : SurfNum = HWBaseboard(BaseboardNum).SurfacePtr(RadSurfNum);
1689 300312 : if (state.dataSurface->Surface(SurfNum).Area > SmallestArea) {
1690 600624 : ThisSurfIntensity = (QBBRadSource(BaseboardNum) * HWBaseboard(BaseboardNum).FracDistribToSurf(RadSurfNum) /
1691 300312 : state.dataSurface->Surface(SurfNum).Area);
1692 300312 : state.dataHeatBalFanSys->SurfQHWBaseboard(SurfNum) += ThisSurfIntensity;
1693 300312 : state.dataHeatBalSurf->AnyRadiantSystems = true;
1694 : // CR 8074, trap for excessive intensity (throws off surface balance )
1695 300312 : if (ThisSurfIntensity > MaxRadHeatFlux) {
1696 0 : ShowSevereError(state, "DistributeBBRadGains: excessive thermal radiation heat flux intensity detected");
1697 0 : ShowContinueError(state, "Surface = " + state.dataSurface->Surface(SurfNum).Name);
1698 0 : ShowContinueError(state, format("Surface area = {:.3R} [m2]", state.dataSurface->Surface(SurfNum).Area));
1699 0 : ShowContinueError(state, "Occurs in " + cCMO_BBRadiator_Water + " = " + HWBaseboard(BaseboardNum).EquipID);
1700 0 : ShowContinueError(state, format("Radiation intensity = {:.2R} [W/m2]", ThisSurfIntensity));
1701 0 : ShowContinueError(state, "Assign a larger surface area or more surfaces in " + cCMO_BBRadiator_Water);
1702 0 : ShowFatalError(state, "DistributeBBRadGains: excessive thermal radiation heat flux intensity detected");
1703 : }
1704 : } else {
1705 0 : ShowSevereError(state, "DistributeBBRadGains: surface not large enough to receive thermal radiation heat flux");
1706 0 : ShowContinueError(state, "Surface = " + state.dataSurface->Surface(SurfNum).Name);
1707 0 : ShowContinueError(state, format("Surface area = {:.3R} [m2]", state.dataSurface->Surface(SurfNum).Area));
1708 0 : ShowContinueError(state, "Occurs in " + cCMO_BBRadiator_Water + " = " + HWBaseboard(BaseboardNum).EquipID);
1709 0 : ShowContinueError(state, "Assign a larger surface area or more surfaces in " + cCMO_BBRadiator_Water);
1710 0 : ShowFatalError(state, "DistributeBBRadGains: surface not large enough to receive thermal radiation heat flux");
1711 : }
1712 : }
1713 : }
1714 51408 : }
1715 :
1716 89527 : void ReportHWBaseboard(EnergyPlusData &state, int const BaseboardNum)
1717 : {
1718 :
1719 : // SUBROUTINE INFORMATION:
1720 : // AUTHOR Daeho Kang
1721 : // DATE WRITTEN Aug 2007
1722 : // MODIFIED na
1723 : // RE-ENGINEERED na
1724 89527 : auto &HWBaseboard = state.dataHWBaseboardRad->HWBaseboard;
1725 :
1726 89527 : HWBaseboard(BaseboardNum).TotEnergy = HWBaseboard(BaseboardNum).TotPower * state.dataHVACGlobal->TimeStepSys * DataGlobalConstants::SecInHour;
1727 89527 : HWBaseboard(BaseboardNum).Energy = HWBaseboard(BaseboardNum).Power * state.dataHVACGlobal->TimeStepSys * DataGlobalConstants::SecInHour;
1728 89527 : HWBaseboard(BaseboardNum).ConvEnergy =
1729 89527 : HWBaseboard(BaseboardNum).ConvPower * state.dataHVACGlobal->TimeStepSys * DataGlobalConstants::SecInHour;
1730 89527 : HWBaseboard(BaseboardNum).RadEnergy = HWBaseboard(BaseboardNum).RadPower * state.dataHVACGlobal->TimeStepSys * DataGlobalConstants::SecInHour;
1731 89527 : }
1732 :
1733 0 : void UpdateHWBaseboardPlantConnection(EnergyPlusData &state,
1734 : int const BaseboardTypeNum, // type index
1735 : std::string const &BaseboardName, // component name
1736 : [[maybe_unused]] int const EquipFlowCtrl, // Flow control mode for the equipment
1737 : [[maybe_unused]] int const LoopNum, // Plant loop index for where called from
1738 : [[maybe_unused]] const DataPlant::LoopSideLocation LoopSide, // Plant loop side index for where called from
1739 : int &CompIndex, // Chiller number pointer
1740 : [[maybe_unused]] bool const FirstHVACIteration,
1741 : bool &InitLoopEquip // If not zero, calculate the max load for operating conditions
1742 : )
1743 : {
1744 :
1745 : // SUBROUTINE INFORMATION:
1746 : // AUTHOR Brent Griffith
1747 : // DATE WRITTEN Sept. 2010
1748 : // MODIFIED na
1749 : // RE-ENGINEERED na
1750 :
1751 : // PURPOSE OF THIS SUBROUTINE:
1752 : // update sim routine called from plant
1753 :
1754 : // METHODOLOGY EMPLOYED:
1755 : // check input, provide comp index, call utility routines
1756 :
1757 : // Using/Aliasing
1758 : using DataPlant::PlantEquipTypeNames;
1759 :
1760 : using PlantUtilities::PullCompInterconnectTrigger;
1761 :
1762 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1763 0 : auto &HWBaseboard = state.dataHWBaseboardRad->HWBaseboard;
1764 0 : auto &NumHWBaseboards = state.dataHWBaseboardRad->NumHWBaseboards;
1765 :
1766 : int BaseboardNum;
1767 :
1768 : // Find the correct baseboard
1769 0 : if (CompIndex == 0) {
1770 0 : BaseboardNum = UtilityRoutines::FindItemInList(BaseboardName, HWBaseboard, &HWBaseboardParams::EquipID);
1771 0 : if (BaseboardNum == 0) {
1772 0 : ShowFatalError(state, "UpdateHWBaseboardPlantConnection: Specified baseboard not valid =" + BaseboardName);
1773 : }
1774 0 : CompIndex = BaseboardNum;
1775 : } else {
1776 0 : BaseboardNum = CompIndex;
1777 0 : if (BaseboardNum > NumHWBaseboards || BaseboardNum < 1) {
1778 0 : ShowFatalError(
1779 : state,
1780 0 : format("UpdateHWBaseboardPlantConnection: Invalid CompIndex passed={}, Number of baseboards={}, Entered baseboard name={}",
1781 : BaseboardNum,
1782 : NumHWBaseboards,
1783 0 : BaseboardName));
1784 : }
1785 0 : if (state.dataGlobal->KickOffSimulation) {
1786 0 : if (BaseboardName != HWBaseboard(BaseboardNum).EquipID) {
1787 0 : ShowFatalError(state,
1788 0 : format("UpdateHWBaseboardPlantConnection: Invalid CompIndex passed={}, baseboard name={}, stored baseboard Name "
1789 : "for that index={}",
1790 : BaseboardNum,
1791 : BaseboardName,
1792 0 : HWBaseboard(BaseboardNum).EquipID));
1793 : }
1794 0 : if (BaseboardTypeNum != static_cast<int>(DataPlant::PlantEquipmentType::Baseboard_Rad_Conv_Water)) {
1795 0 : ShowFatalError(state,
1796 0 : format("UpdateHWBaseboardPlantConnection: Invalid CompIndex passed={}, baseboard name={}, stored baseboard Name "
1797 : "for that index={}",
1798 : BaseboardNum,
1799 : BaseboardName,
1800 0 : PlantEquipTypeNames[BaseboardTypeNum]));
1801 : }
1802 : }
1803 : }
1804 :
1805 0 : if (InitLoopEquip) {
1806 0 : return;
1807 : }
1808 :
1809 0 : PullCompInterconnectTrigger(state,
1810 0 : HWBaseboard(BaseboardNum).plantLoc,
1811 0 : HWBaseboard(BaseboardNum).BBLoadReSimIndex,
1812 0 : HWBaseboard(BaseboardNum).plantLoc,
1813 : DataPlant::CriteriaType::HeatTransferRate,
1814 0 : HWBaseboard(BaseboardNum).Power);
1815 :
1816 0 : PullCompInterconnectTrigger(state,
1817 0 : HWBaseboard(BaseboardNum).plantLoc,
1818 0 : HWBaseboard(BaseboardNum).BBMassFlowReSimIndex,
1819 0 : HWBaseboard(BaseboardNum).plantLoc,
1820 : DataPlant::CriteriaType::MassFlowRate,
1821 0 : HWBaseboard(BaseboardNum).WaterMassFlowRate);
1822 :
1823 0 : PullCompInterconnectTrigger(state,
1824 0 : HWBaseboard(BaseboardNum).plantLoc,
1825 0 : HWBaseboard(BaseboardNum).BBInletTempFlowReSimIndex,
1826 0 : HWBaseboard(BaseboardNum).plantLoc,
1827 : DataPlant::CriteriaType::Temperature,
1828 0 : HWBaseboard(BaseboardNum).WaterOutletTemp);
1829 : }
1830 :
1831 : //*****************************************************************************************
1832 :
1833 : } // namespace HWBaseboardRadiator
1834 :
1835 2313 : } // namespace EnergyPlus
|