Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2025, The Board of Trustees of the University of Illinois,
2 : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
3 : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
4 : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
5 : // contributors. All rights reserved.
6 : //
7 : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
8 : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
9 : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
10 : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
11 : // derivative works, and perform publicly and display publicly, and to permit others to do so.
12 : //
13 : // Redistribution and use in source and binary forms, with or without modification, are permitted
14 : // provided that the following conditions are met:
15 : //
16 : // (1) Redistributions of source code must retain the above copyright notice, this list of
17 : // conditions and the following disclaimer.
18 : //
19 : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
20 : // conditions and the following disclaimer in the documentation and/or other materials
21 : // provided with the distribution.
22 : //
23 : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
24 : // the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
25 : // used to endorse or promote products derived from this software without specific prior
26 : // written permission.
27 : //
28 : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
29 : // without changes from the version obtained under this License, or (ii) Licensee makes a
30 : // reference solely to the software portion of its product, Licensee must refer to the
31 : // software as "EnergyPlus version X" software, where "X" is the version number Licensee
32 : // obtained under this License and may not use a different name for the software. Except as
33 : // specifically required in this Section (4), Licensee shall not use in a company name, a
34 : // product name, in advertising, publicity, or other promotional activities any name, trade
35 : // name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
36 : // similar designation, without the U.S. Department of Energy's prior written consent.
37 : //
38 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
39 : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
40 : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
41 : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43 : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
45 : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46 : // POSSIBILITY OF SUCH DAMAGE.
47 :
48 : // C++ Headers
49 :
50 : // EnergyPlus Headers
51 : #include <EnergyPlus/Autosizing/HeatingCapacitySizing.hh>
52 : #include <EnergyPlus/BaseboardElectric.hh>
53 : #include <EnergyPlus/Data/EnergyPlusData.hh>
54 : #include <EnergyPlus/DataHVACGlobals.hh>
55 : #include <EnergyPlus/DataHeatBalance.hh>
56 : #include <EnergyPlus/DataIPShortCuts.hh>
57 : #include <EnergyPlus/DataLoopNode.hh>
58 : #include <EnergyPlus/DataSizing.hh>
59 : #include <EnergyPlus/DataZoneEnergyDemands.hh>
60 : #include <EnergyPlus/DataZoneEquipment.hh>
61 : #include <EnergyPlus/GeneralRoutines.hh>
62 : #include <EnergyPlus/GlobalNames.hh>
63 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
64 : #include <EnergyPlus/OutputProcessor.hh>
65 : #include <EnergyPlus/Psychrometrics.hh>
66 : #include <EnergyPlus/ScheduleManager.hh>
67 : #include <EnergyPlus/UtilityRoutines.hh>
68 :
69 : namespace EnergyPlus {
70 :
71 : namespace BaseboardElectric {
72 : // Module containing the routines dealing with the BASEBOARD Electric HEATER
73 : // component(s).
74 :
75 : // MODULE INFORMATION: Richard Liesen
76 : // DATE WRITTEN Nov 2001
77 : // RE-ENGINEERED na
78 :
79 : // MODULE PARAMETER DEFINITIONS
80 : constexpr std::string_view cCMO_BBRadiator_Electric = "ZoneHVAC:Baseboard:Convective:Electric";
81 : constexpr Real64 SimpConvAirFlowSpeed(0.5); // m/s
82 :
83 1 : void SimElectricBaseboard(EnergyPlusData &state, std::string const &EquipName, int const ControlledZoneNum, Real64 &PowerMet, int &CompIndex)
84 : {
85 :
86 : // SUBROUTINE INFORMATION:
87 : // AUTHOR Richard Liesen
88 : // DATE WRITTEN Nov 2001
89 : // MODIFIED na
90 : // RE-ENGINEERED na
91 :
92 : // PURPOSE OF THIS SUBROUTINE:
93 : // This subroutine simulates the Electric Baseboard units.
94 :
95 : int BaseboardNum; // index of unit in baseboard array
96 : Real64 QZnReq; // zone load not yet satisfied
97 :
98 1 : if (state.dataBaseboardElectric->getInputFlag) {
99 1 : GetBaseboardInput(state);
100 1 : state.dataBaseboardElectric->getInputFlag = false;
101 : }
102 :
103 1 : auto &baseboard = state.dataBaseboardElectric;
104 :
105 : // Find the correct Baseboard Equipment
106 1 : if (CompIndex == 0) {
107 1 : BaseboardNum = Util::FindItemInList(EquipName, baseboard->baseboards, &BaseboardParams::EquipName);
108 1 : if (BaseboardNum == 0) {
109 0 : ShowFatalError(state, format("SimElectricBaseboard: Unit not found={}", EquipName));
110 : }
111 1 : CompIndex = BaseboardNum;
112 : } else {
113 0 : BaseboardNum = CompIndex;
114 0 : int numBaseboards = (int)baseboard->baseboards.size();
115 0 : if (BaseboardNum > numBaseboards || BaseboardNum < 1) {
116 0 : ShowFatalError(state,
117 0 : format("SimElectricBaseboard: Invalid CompIndex passed={}, Number of Units={}, Entered Unit name={}",
118 : BaseboardNum,
119 : numBaseboards,
120 : EquipName));
121 : }
122 0 : if (baseboard->baseboards(BaseboardNum).CheckEquipName) {
123 0 : if (EquipName != baseboard->baseboards(BaseboardNum).EquipName) {
124 0 : ShowFatalError(state,
125 0 : format("SimElectricBaseboard: Invalid CompIndex passed={}, Unit name={}, stored Unit Name for that index={}",
126 : BaseboardNum,
127 : EquipName,
128 0 : baseboard->baseboards(BaseboardNum).EquipName));
129 : }
130 0 : baseboard->baseboards(BaseboardNum).CheckEquipName = false;
131 : }
132 : }
133 :
134 1 : InitBaseboard(state, BaseboardNum, ControlledZoneNum);
135 :
136 1 : QZnReq = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ControlledZoneNum).RemainingOutputReqToHeatSP;
137 :
138 : // Simulate baseboard
139 1 : SimElectricConvective(state, BaseboardNum, QZnReq);
140 :
141 1 : PowerMet = baseboard->baseboards(BaseboardNum).Power;
142 :
143 1 : baseboard->baseboards(BaseboardNum).Energy = baseboard->baseboards(BaseboardNum).Power * state.dataHVACGlobal->TimeStepSysSec;
144 1 : baseboard->baseboards(BaseboardNum).ElecUseLoad = baseboard->baseboards(BaseboardNum).ElecUseRate * state.dataHVACGlobal->TimeStepSysSec;
145 1 : }
146 :
147 8 : void GetBaseboardInput(EnergyPlusData &state)
148 : {
149 :
150 : // SUBROUTINE INFORMATION:
151 : // AUTHOR Richard Liesen
152 : // DATE WRITTEN Nov 2001
153 : // MODIFIED na
154 : // RE-ENGINEERED na
155 :
156 : // PURPOSE OF THIS SUBROUTINE:
157 : // This subroutine gets the input for the Baseboard units.
158 :
159 : // METHODOLOGY EMPLOYED:
160 : // Standard input processor calls.
161 :
162 : // Using/Aliasing
163 : using DataSizing::AutoSize;
164 : using DataSizing::CapacityPerFloorArea;
165 : using DataSizing::FractionOfAutosizedHeatingCapacity;
166 : using DataSizing::HeatingDesignCapacity;
167 : using GlobalNames::VerifyUniqueBaseboardName;
168 :
169 : // SUBROUTINE PARAMETER DEFINITIONS:
170 : static constexpr std::string_view RoutineName("GetBaseboardInput: "); // include trailing blank space
171 : static constexpr std::string_view routineName = "GetBaseboardInput";
172 8 : int constexpr iHeatCAPMAlphaNum(3); // get input index to baseboard heating capacity sizing method
173 8 : int constexpr iHeatDesignCapacityNumericNum(1); // get input index to baseboard heating capacity
174 8 : int constexpr iHeatCapacityPerFloorAreaNumericNum(2); // get input index to baseboard heating capacity per floor area sizing
175 8 : int constexpr iHeatFracOfAutosizedCapacityNumericNum(
176 : 3); // get input index to baseboard heating capacity sizing as fraction of autosized heating capacity
177 :
178 8 : auto &s_ipsc = state.dataIPShortCut;
179 :
180 8 : auto &baseboard = state.dataBaseboardElectric;
181 8 : std::string_view cCurrentModuleObject = cCMO_BBRadiator_Electric;
182 :
183 8 : int NumConvElecBaseboards = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
184 :
185 8 : baseboard->baseboards.allocate(NumConvElecBaseboards);
186 :
187 8 : if (NumConvElecBaseboards > 0) { // Get the data for cooling schemes
188 8 : bool ErrorsFound(false); // If errors detected in input
189 8 : int NumAlphas = 0;
190 8 : int NumNums = 0;
191 8 : int IOStat = 0;
192 8 : int BaseboardNum = 0;
193 16 : for (int ConvElecBBNum = 1; ConvElecBBNum <= NumConvElecBaseboards; ++ConvElecBBNum) {
194 :
195 16 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
196 : cCurrentModuleObject,
197 : ConvElecBBNum,
198 8 : s_ipsc->cAlphaArgs,
199 : NumAlphas,
200 8 : s_ipsc->rNumericArgs,
201 : NumNums,
202 : IOStat,
203 8 : s_ipsc->lNumericFieldBlanks,
204 8 : s_ipsc->lAlphaFieldBlanks,
205 8 : s_ipsc->cAlphaFieldNames,
206 8 : s_ipsc->cNumericFieldNames);
207 :
208 8 : baseboard->baseboards(ConvElecBBNum).FieldNames.allocate(NumNums);
209 8 : baseboard->baseboards(ConvElecBBNum).FieldNames = "";
210 8 : baseboard->baseboards(ConvElecBBNum).FieldNames = s_ipsc->cNumericFieldNames;
211 :
212 8 : ErrorObjectHeader eoh{routineName, cCurrentModuleObject, s_ipsc->cAlphaArgs(1)};
213 :
214 : // ErrorsFound will be set to True if problem was found, left untouched otherwise
215 8 : VerifyUniqueBaseboardName(state, cCurrentModuleObject, s_ipsc->cAlphaArgs(1), ErrorsFound, format("{} Name", cCurrentModuleObject));
216 :
217 8 : ++BaseboardNum;
218 8 : auto &thisBaseboard = baseboard->baseboards(BaseboardNum);
219 8 : thisBaseboard.EquipName = s_ipsc->cAlphaArgs(1); // name of this baseboard
220 8 : thisBaseboard.EquipType = Util::makeUPPER(cCurrentModuleObject); // the type of baseboard-rename change
221 8 : thisBaseboard.Schedule = s_ipsc->cAlphaArgs(2);
222 8 : if (s_ipsc->lAlphaFieldBlanks(2)) {
223 8 : thisBaseboard.availSched = Sched::GetScheduleAlwaysOn(state);
224 0 : } else if ((thisBaseboard.availSched = Sched::GetSchedule(state, s_ipsc->cAlphaArgs(2))) == nullptr) {
225 0 : ShowSevereItemNotFound(state, eoh, s_ipsc->cAlphaFieldNames(2), s_ipsc->cAlphaArgs(2));
226 0 : ErrorsFound = true;
227 : }
228 : // get inlet node number
229 8 : thisBaseboard.BaseboardEfficiency = s_ipsc->rNumericArgs(4);
230 :
231 : // Determine baseboard electric heating design capacity sizing method
232 8 : if (Util::SameString(s_ipsc->cAlphaArgs(iHeatCAPMAlphaNum), "HeatingDesignCapacity")) {
233 8 : thisBaseboard.HeatingCapMethod = HeatingDesignCapacity;
234 8 : if (!s_ipsc->lNumericFieldBlanks(iHeatDesignCapacityNumericNum)) {
235 8 : thisBaseboard.ScaledHeatingCapacity = s_ipsc->rNumericArgs(iHeatDesignCapacityNumericNum);
236 8 : if (thisBaseboard.ScaledHeatingCapacity < 0.0 && thisBaseboard.ScaledHeatingCapacity != AutoSize) {
237 0 : ShowSevereError(state, format("{} = {}", cCurrentModuleObject, thisBaseboard.EquipName));
238 0 : ShowContinueError(state,
239 0 : format("Illegal {} = {:.7T}",
240 0 : s_ipsc->cNumericFieldNames(iHeatDesignCapacityNumericNum),
241 0 : s_ipsc->rNumericArgs(iHeatDesignCapacityNumericNum)));
242 0 : ErrorsFound = true;
243 : }
244 : } else {
245 0 : ShowSevereError(state, format("{} = {}", cCurrentModuleObject, thisBaseboard.EquipName));
246 0 : ShowContinueError(
247 0 : state, format("Input for {} = {}", s_ipsc->cAlphaFieldNames(iHeatCAPMAlphaNum), s_ipsc->cAlphaArgs(iHeatCAPMAlphaNum)));
248 0 : ShowContinueError(state, format("Blank field not allowed for {}", s_ipsc->cNumericFieldNames(iHeatDesignCapacityNumericNum)));
249 0 : ErrorsFound = true;
250 : }
251 0 : } else if (Util::SameString(s_ipsc->cAlphaArgs(iHeatCAPMAlphaNum), "CapacityPerFloorArea")) {
252 0 : thisBaseboard.HeatingCapMethod = CapacityPerFloorArea;
253 0 : if (!s_ipsc->lNumericFieldBlanks(iHeatCapacityPerFloorAreaNumericNum)) {
254 0 : thisBaseboard.ScaledHeatingCapacity = s_ipsc->rNumericArgs(iHeatCapacityPerFloorAreaNumericNum);
255 0 : if (thisBaseboard.ScaledHeatingCapacity <= 0.0) {
256 0 : ShowSevereError(state, format("{} = {}", cCurrentModuleObject, thisBaseboard.EquipName));
257 0 : ShowContinueError(
258 : state,
259 0 : format("Input for {} = {}", s_ipsc->cAlphaFieldNames(iHeatCAPMAlphaNum), s_ipsc->cAlphaArgs(iHeatCAPMAlphaNum)));
260 0 : ShowContinueError(state,
261 0 : format("Illegal {} = {:.7T}",
262 0 : s_ipsc->cNumericFieldNames(iHeatCapacityPerFloorAreaNumericNum),
263 0 : s_ipsc->rNumericArgs(iHeatCapacityPerFloorAreaNumericNum)));
264 0 : ErrorsFound = true;
265 0 : } else if (thisBaseboard.ScaledHeatingCapacity == AutoSize) {
266 0 : ShowSevereError(state, format("{} = {}", cCurrentModuleObject, thisBaseboard.EquipName));
267 0 : ShowContinueError(
268 : state,
269 0 : format("Input for {} = {}", s_ipsc->cAlphaFieldNames(iHeatCAPMAlphaNum), s_ipsc->cAlphaArgs(iHeatCAPMAlphaNum)));
270 0 : ShowContinueError(state,
271 0 : format("Illegal {} = AutoSize", s_ipsc->cNumericFieldNames(iHeatCapacityPerFloorAreaNumericNum)));
272 0 : ErrorsFound = true;
273 : }
274 : } else {
275 0 : ShowSevereError(state, format("{} = {}", cCurrentModuleObject, thisBaseboard.EquipName));
276 0 : ShowContinueError(
277 0 : state, format("Input for {} = {}", s_ipsc->cAlphaFieldNames(iHeatCAPMAlphaNum), s_ipsc->cAlphaArgs(iHeatCAPMAlphaNum)));
278 0 : ShowContinueError(state,
279 0 : format("Blank field not allowed for {}", s_ipsc->cNumericFieldNames(iHeatCapacityPerFloorAreaNumericNum)));
280 0 : ErrorsFound = true;
281 : }
282 0 : } else if (Util::SameString(s_ipsc->cAlphaArgs(iHeatCAPMAlphaNum), "FractionOfAutosizedHeatingCapacity")) {
283 0 : thisBaseboard.HeatingCapMethod = FractionOfAutosizedHeatingCapacity;
284 0 : if (!s_ipsc->lNumericFieldBlanks(iHeatFracOfAutosizedCapacityNumericNum)) {
285 0 : thisBaseboard.ScaledHeatingCapacity = s_ipsc->rNumericArgs(iHeatFracOfAutosizedCapacityNumericNum);
286 0 : if (thisBaseboard.ScaledHeatingCapacity < 0.0) {
287 0 : ShowSevereError(state, format("{} = {}", cCurrentModuleObject, thisBaseboard.EquipName));
288 0 : ShowContinueError(state,
289 0 : format("Illegal {} = {:.7T}",
290 0 : s_ipsc->cNumericFieldNames(iHeatFracOfAutosizedCapacityNumericNum),
291 0 : s_ipsc->rNumericArgs(iHeatFracOfAutosizedCapacityNumericNum)));
292 0 : ErrorsFound = true;
293 : }
294 : } else {
295 0 : ShowSevereError(state, format("{} = {}", cCurrentModuleObject, thisBaseboard.EquipName));
296 0 : ShowContinueError(
297 0 : state, format("Input for {} = {}", s_ipsc->cAlphaFieldNames(iHeatCAPMAlphaNum), s_ipsc->cAlphaArgs(iHeatCAPMAlphaNum)));
298 0 : ShowContinueError(
299 0 : state, format("Blank field not allowed for {}", s_ipsc->cNumericFieldNames(iHeatFracOfAutosizedCapacityNumericNum)));
300 0 : ErrorsFound = true;
301 : }
302 : } else {
303 0 : ShowSevereError(state, format("{} = {}", cCurrentModuleObject, thisBaseboard.EquipName));
304 0 : ShowContinueError(state,
305 0 : format("Illegal {} = {}", s_ipsc->cAlphaFieldNames(iHeatCAPMAlphaNum), s_ipsc->cAlphaArgs(iHeatCAPMAlphaNum)));
306 0 : ErrorsFound = true;
307 : }
308 :
309 8 : thisBaseboard.ZonePtr = DataZoneEquipment::GetZoneEquipControlledZoneNum(
310 8 : state, DataZoneEquipment::ZoneEquipType::BaseboardConvectiveElectric, thisBaseboard.EquipName);
311 : }
312 :
313 8 : if (ErrorsFound) {
314 0 : ShowFatalError(state, format("{} Errors found in getting input. Preceding condition(s) cause termination.", RoutineName));
315 : }
316 : }
317 :
318 16 : for (int BaseboardNum = 1; BaseboardNum <= NumConvElecBaseboards; ++BaseboardNum) {
319 :
320 : // Setup Report variables for the Electric Baseboards
321 : // CurrentModuleObject='ZoneHVAC:Baseboard:Convective:Electric'
322 :
323 8 : auto &thisBaseboard = baseboard->baseboards(BaseboardNum);
324 16 : SetupOutputVariable(state,
325 : "Baseboard Total Heating Energy",
326 : Constant::Units::J,
327 8 : thisBaseboard.Energy,
328 : OutputProcessor::TimeStepType::System,
329 : OutputProcessor::StoreType::Sum,
330 8 : thisBaseboard.EquipName,
331 : Constant::eResource::EnergyTransfer,
332 : OutputProcessor::Group::HVAC,
333 : OutputProcessor::EndUseCat::Baseboard);
334 :
335 16 : SetupOutputVariable(state,
336 : "Baseboard Total Heating Rate",
337 : Constant::Units::W,
338 8 : thisBaseboard.Power,
339 : OutputProcessor::TimeStepType::System,
340 : OutputProcessor::StoreType::Average,
341 8 : thisBaseboard.EquipName);
342 :
343 16 : SetupOutputVariable(state,
344 : "Baseboard Electricity Energy",
345 : Constant::Units::J,
346 8 : thisBaseboard.ElecUseLoad,
347 : OutputProcessor::TimeStepType::System,
348 : OutputProcessor::StoreType::Sum,
349 8 : thisBaseboard.EquipName,
350 : Constant::eResource::Electricity,
351 : OutputProcessor::Group::HVAC,
352 : OutputProcessor::EndUseCat::Heating);
353 :
354 16 : SetupOutputVariable(state,
355 : "Baseboard Electricity Rate",
356 : Constant::Units::W,
357 8 : thisBaseboard.ElecUseRate,
358 : OutputProcessor::TimeStepType::System,
359 : OutputProcessor::StoreType::Average,
360 8 : thisBaseboard.EquipName);
361 : }
362 8 : }
363 :
364 1 : void InitBaseboard(EnergyPlusData &state, int const BaseboardNum, int const ControlledZoneNum)
365 : {
366 :
367 : // SUBROUTINE INFORMATION:
368 : // AUTHOR Richard Liesen
369 : // DATE WRITTEN Nov 2001
370 :
371 : // PURPOSE OF THIS SUBROUTINE:
372 : // This subroutine initializes the Baseboard units during simulation.
373 :
374 1 : auto &baseboard = state.dataBaseboardElectric;
375 :
376 1 : if (!state.dataGlobal->SysSizingCalc && baseboard->baseboards(BaseboardNum).MySizeFlag) {
377 : // for each coil, do the sizing once.
378 1 : SizeElectricBaseboard(state, BaseboardNum);
379 1 : baseboard->baseboards(BaseboardNum).MySizeFlag = false;
380 : }
381 :
382 : // Set the reporting variables to zero at each timestep.
383 1 : baseboard->baseboards(BaseboardNum).Energy = 0.0;
384 1 : baseboard->baseboards(BaseboardNum).Power = 0.0;
385 1 : baseboard->baseboards(BaseboardNum).ElecUseLoad = 0.0;
386 1 : baseboard->baseboards(BaseboardNum).ElecUseRate = 0.0;
387 :
388 : // Do the every time step initializations
389 1 : int ZoneNode = state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).ZoneNode;
390 1 : baseboard->baseboards(BaseboardNum).AirInletTemp = state.dataLoopNodes->Node(ZoneNode).Temp;
391 1 : baseboard->baseboards(BaseboardNum).AirInletHumRat = state.dataLoopNodes->Node(ZoneNode).HumRat;
392 1 : }
393 :
394 1 : void SizeElectricBaseboard(EnergyPlusData &state, int const BaseboardNum)
395 : {
396 :
397 : // SUBROUTINE INFORMATION:
398 : // AUTHOR Fred Buhl
399 : // DATE WRITTEN February 2002
400 : // MODIFIED August 2013 Daeho Kang, add component sizing table entries
401 : // July 2014, B. Nigusse, added scalable sizing
402 :
403 : // PURPOSE OF THIS SUBROUTINE:
404 : // This subroutine is for sizing electric baseboard components for which nominal capacities have not been
405 : // specified in the input.
406 :
407 : // METHODOLOGY EMPLOYED:
408 : // Obtains flow rates from the zone sizing arrays and plant sizing data. UAs are
409 : // calculated by numerically inverting the baseboard calculation routine.
410 :
411 : // SUBROUTINE PARAMETER DEFINITIONS:
412 : static constexpr std::string_view RoutineName("SizeElectricBaseboard");
413 :
414 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
415 : Real64 TempSize; // autosized value of coil input field
416 1 : state.dataSize->DataScalableCapSizingON = false;
417 :
418 1 : if (state.dataSize->CurZoneEqNum > 0) {
419 0 : auto &ZoneEqSizing = state.dataSize->ZoneEqSizing(state.dataSize->CurZoneEqNum);
420 0 : auto &baseboard = state.dataBaseboardElectric->baseboards(BaseboardNum);
421 :
422 0 : std::string_view const CompType = baseboard.EquipType;
423 0 : std::string_view const CompName = baseboard.EquipName;
424 0 : state.dataSize->DataFracOfAutosizedHeatingCapacity = 1.0;
425 0 : state.dataSize->DataZoneNumber = baseboard.ZonePtr;
426 0 : int SizingMethod = HVAC::HeatingCapacitySizing;
427 0 : int FieldNum = 1;
428 0 : std::string const SizingString = format("{} [W]", baseboard.FieldNames(FieldNum));
429 0 : int CapSizingMethod = baseboard.HeatingCapMethod;
430 0 : ZoneEqSizing.SizingMethod(SizingMethod) = CapSizingMethod;
431 0 : if (CapSizingMethod == DataSizing::HeatingDesignCapacity || CapSizingMethod == DataSizing::CapacityPerFloorArea ||
432 : CapSizingMethod == DataSizing::FractionOfAutosizedHeatingCapacity) {
433 0 : if (CapSizingMethod == DataSizing::HeatingDesignCapacity) {
434 0 : if (baseboard.ScaledHeatingCapacity == DataSizing::AutoSize) {
435 0 : CheckZoneSizing(state, CompType, CompName);
436 0 : ZoneEqSizing.HeatingCapacity = true;
437 0 : ZoneEqSizing.DesHeatingLoad = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).NonAirSysDesHeatLoad;
438 : }
439 0 : TempSize = baseboard.ScaledHeatingCapacity;
440 0 : } else if (CapSizingMethod == DataSizing::CapacityPerFloorArea) {
441 0 : ZoneEqSizing.HeatingCapacity = true;
442 0 : ZoneEqSizing.DesHeatingLoad = baseboard.ScaledHeatingCapacity * state.dataHeatBal->Zone(state.dataSize->DataZoneNumber).FloorArea;
443 0 : TempSize = ZoneEqSizing.DesHeatingLoad;
444 0 : state.dataSize->DataScalableCapSizingON = true;
445 0 : } else if (CapSizingMethod == DataSizing::FractionOfAutosizedHeatingCapacity) {
446 0 : CheckZoneSizing(state, CompType, CompName);
447 0 : ZoneEqSizing.HeatingCapacity = true;
448 0 : state.dataSize->DataFracOfAutosizedHeatingCapacity = baseboard.ScaledHeatingCapacity;
449 0 : ZoneEqSizing.DesHeatingLoad = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).NonAirSysDesHeatLoad;
450 0 : TempSize = DataSizing::AutoSize;
451 0 : state.dataSize->DataScalableCapSizingON = true;
452 : } else {
453 0 : TempSize = baseboard.ScaledHeatingCapacity;
454 : }
455 0 : bool PrintFlag = true; // TRUE when sizing information is reported in the eio file
456 0 : bool errorsFound = false;
457 0 : HeatingCapacitySizer sizerHeatingCapacity;
458 0 : sizerHeatingCapacity.overrideSizingString(SizingString);
459 0 : sizerHeatingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
460 0 : baseboard.NominalCapacity = sizerHeatingCapacity.size(state, TempSize, errorsFound);
461 0 : state.dataSize->DataScalableCapSizingON = false;
462 0 : }
463 0 : }
464 1 : }
465 :
466 1 : void SimElectricConvective(EnergyPlusData &state, int const BaseboardNum, Real64 const LoadMet)
467 : {
468 : // SUBROUTINE INFORMATION:
469 : // AUTHOR Richard Liesen
470 : // DATE WRITTEN Nov 2001
471 :
472 : // PURPOSE OF THIS SUBROUTINE: This subroutine calculates the heat exchange rate
473 : // in a pure Electricconvective baseboard heater.
474 :
475 : // METHODOLOGY EMPLOYED:
476 : // Currently this is primarily modified from HW Convective baseboard which has connections to
477 : // a water loop and was necessary to calculate temps, flow rates and other things. This
478 : // model might be made more sophisticated and might use some of those data structures in the future
479 : // so they are left in place even though this model does not utilize them.
480 :
481 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
482 : Real64 AirOutletTemp;
483 : Real64 QBBCap;
484 :
485 1 : auto &baseboard = state.dataBaseboardElectric->baseboards(BaseboardNum);
486 :
487 1 : Real64 AirInletTemp = baseboard.AirInletTemp;
488 1 : Real64 CpAir = Psychrometrics::PsyCpAirFnW(baseboard.AirInletHumRat);
489 1 : Real64 AirMassFlowRate = SimpConvAirFlowSpeed;
490 1 : Real64 CapacitanceAir = CpAir * AirMassFlowRate;
491 : // currently only the efficiency is used to calculate the electric consumption. There could be some
492 : // thermal loss that could be accounted for with this efficiency input.
493 1 : Real64 Effic = baseboard.BaseboardEfficiency;
494 :
495 1 : if (baseboard.availSched->getCurrentVal() > 0.0 && LoadMet >= HVAC::SmallLoad) {
496 :
497 : // if the load exceeds the capacity than the capacity is set to the BB limit.
498 1 : if (LoadMet > baseboard.NominalCapacity) {
499 1 : QBBCap = baseboard.NominalCapacity;
500 : } else {
501 0 : QBBCap = LoadMet;
502 : }
503 :
504 : // this could be utilized somehow or even reported so the data structures are left in place
505 1 : AirOutletTemp = AirInletTemp + QBBCap / CapacitanceAir;
506 :
507 : // The Baseboard electric Load is calculated using the efficiency
508 1 : baseboard.ElecUseRate = QBBCap / Effic;
509 :
510 : } else {
511 : // if there is an off condition the BB does nothing.
512 0 : AirOutletTemp = AirInletTemp;
513 0 : QBBCap = 0.0;
514 0 : baseboard.ElecUseRate = 0.0;
515 : }
516 :
517 1 : baseboard.AirOutletTemp = AirOutletTemp;
518 1 : baseboard.Power = QBBCap;
519 1 : }
520 :
521 : } // namespace BaseboardElectric
522 :
523 : } // namespace EnergyPlus
|