Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2025, The Board of Trustees of the University of Illinois,
2 : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
3 : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
4 : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
5 : // contributors. All rights reserved.
6 : //
7 : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
8 : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
9 : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
10 : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
11 : // derivative works, and perform publicly and display publicly, and to permit others to do so.
12 : //
13 : // Redistribution and use in source and binary forms, with or without modification, are permitted
14 : // provided that the following conditions are met:
15 : //
16 : // (1) Redistributions of source code must retain the above copyright notice, this list of
17 : // conditions and the following disclaimer.
18 : //
19 : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
20 : // conditions and the following disclaimer in the documentation and/or other materials
21 : // provided with the distribution.
22 : //
23 : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
24 : // the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
25 : // used to endorse or promote products derived from this software without specific prior
26 : // written permission.
27 : //
28 : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
29 : // without changes from the version obtained under this License, or (ii) Licensee makes a
30 : // reference solely to the software portion of its product, Licensee must refer to the
31 : // software as "EnergyPlus version X" software, where "X" is the version number Licensee
32 : // obtained under this License and may not use a different name for the software. Except as
33 : // specifically required in this Section (4), Licensee shall not use in a company name, a
34 : // product name, in advertising, publicity, or other promotional activities any name, trade
35 : // name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
36 : // similar designation, without the U.S. Department of Energy's prior written consent.
37 : //
38 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
39 : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
40 : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
41 : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43 : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
45 : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46 : // POSSIBILITY OF SUCH DAMAGE.
47 :
48 : // C++ Headers
49 : #include <cmath>
50 :
51 : // ObjexxFCL Headers
52 : #include <ObjexxFCL/Array.functions.hh>
53 : #include <ObjexxFCL/Fmath.hh>
54 :
55 : // EnergyPlus Headers
56 : #include <EnergyPlus/Autosizing/All_Simple_Sizing.hh>
57 : #include <EnergyPlus/Autosizing/HeatingCapacitySizing.hh>
58 : #include <EnergyPlus/BranchNodeConnections.hh>
59 : #include <EnergyPlus/Coils/CoilCoolingDX.hh>
60 : #include <EnergyPlus/CurveManager.hh>
61 : #include <EnergyPlus/DXCoils.hh>
62 : #include <EnergyPlus/Data/EnergyPlusData.hh>
63 : #include <EnergyPlus/DataContaminantBalance.hh>
64 : #include <EnergyPlus/DataEnvironment.hh>
65 : #include <EnergyPlus/DataGlobalConstants.hh>
66 : #include <EnergyPlus/DataHVACGlobals.hh>
67 : #include <EnergyPlus/DataHeatBalance.hh>
68 : #include <EnergyPlus/DataLoopNode.hh>
69 : #include <EnergyPlus/DataSizing.hh>
70 : #include <EnergyPlus/EMSManager.hh>
71 : #include <EnergyPlus/FaultsManager.hh>
72 : #include <EnergyPlus/General.hh>
73 : #include <EnergyPlus/GlobalNames.hh>
74 : #include <EnergyPlus/HeatingCoils.hh>
75 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
76 : #include <EnergyPlus/NodeInputManager.hh>
77 : #include <EnergyPlus/OutputProcessor.hh>
78 : #include <EnergyPlus/OutputReportPredefined.hh>
79 : #include <EnergyPlus/Psychrometrics.hh>
80 : #include <EnergyPlus/RefrigeratedCase.hh>
81 : #include <EnergyPlus/ScheduleManager.hh>
82 : #include <EnergyPlus/UtilityRoutines.hh>
83 : #include <EnergyPlus/VariableSpeedCoils.hh>
84 :
85 : namespace EnergyPlus { // NOLINT(modernize-concat-nested-namespaces) // TODO: Take out this lint when we want to apply formatting for nested
86 : // namespacing
87 :
88 : namespace HeatingCoils {
89 : // Module containing the HeatingCoil simulation routines other than the Water coils
90 :
91 : // MODULE INFORMATION:
92 : // AUTHOR Richard J. Liesen
93 : // DATE WRITTEN May 2000
94 : // MODIFIED Therese Stovall June 2008 to add references to refrigeration condensers
95 :
96 : // PURPOSE OF THIS MODULE:
97 : // To encapsulate the data and algorithms required to
98 : // manage the HeatingCoil System Component
99 :
100 122270909 : void SimulateHeatingCoilComponents(EnergyPlusData &state,
101 : std::string_view CompName,
102 : bool const FirstHVACIteration,
103 : ObjexxFCL::Optional<Real64 const> QCoilReq, // coil load to be met
104 : ObjexxFCL::Optional_int CompIndex,
105 : ObjexxFCL::Optional<Real64> QCoilActual, // coil load actually delivered returned to calling component
106 : ObjexxFCL::Optional_bool_const SuppHeat, // True if current heating coil is a supplemental heating coil
107 : ObjexxFCL::Optional<HVAC::FanOp const> fanOpMode, // fan operating mode, FanOp::Cycling or FanOp::Continuous
108 : ObjexxFCL::Optional<Real64 const> PartLoadRatio, // part-load ratio of heating coil
109 : ObjexxFCL::Optional_int StageNum,
110 : ObjexxFCL::Optional<Real64 const> SpeedRatio // Speed ratio of MultiStage heating coil
111 : )
112 : {
113 :
114 : // SUBROUTINE INFORMATION:
115 : // AUTHOR Richard Liesen
116 : // DATE WRITTEN May 2000
117 :
118 : // PURPOSE OF THIS SUBROUTINE:
119 : // This subroutine manages HeatingCoil component simulation.
120 :
121 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
122 122270909 : int CoilNum(0); // The HeatingCoil that you are currently loading input into
123 : Real64 QCoilActual2; // coil load actually delivered returned from specific coil
124 : HVAC::FanOp fanOp; // fan operating mode
125 : Real64 PartLoadFrac; // part-load fraction of heating coil
126 : Real64 QCoilRequired; // local variable for optional argument
127 :
128 : // Obtains and Allocates HeatingCoil related parameters from input file
129 122270909 : if (state.dataHeatingCoils->GetCoilsInputFlag) { // First time subroutine has been entered
130 61 : GetHeatingCoilInput(state);
131 61 : state.dataHeatingCoils->GetCoilsInputFlag = false;
132 : }
133 :
134 : // Find the correct HeatingCoilNumber with the Coil Name
135 122270909 : if (present(CompIndex)) {
136 122270909 : if (CompIndex == 0) {
137 4689327 : CoilNum = Util::FindItemInList(CompName, state.dataHeatingCoils->HeatingCoil);
138 4689327 : if (CoilNum == 0) {
139 0 : ShowFatalError(state, format("SimulateHeatingCoilComponents: Coil not found={}", CompName));
140 : }
141 : // CompIndex=CoilNum
142 : } else {
143 117581582 : CoilNum = CompIndex;
144 117581582 : if (CoilNum > state.dataHeatingCoils->NumHeatingCoils || CoilNum < 1) {
145 0 : ShowFatalError(state,
146 0 : format("SimulateHeatingCoilComponents: Invalid CompIndex passed={}, Number of Heating Coils={}, Coil name={}",
147 : CoilNum,
148 0 : state.dataHeatingCoils->NumHeatingCoils,
149 : CompName));
150 : }
151 117581582 : if (state.dataHeatingCoils->CheckEquipName(CoilNum)) {
152 1225 : if (!CompName.empty() && CompName != state.dataHeatingCoils->HeatingCoil(CoilNum).Name) {
153 0 : ShowFatalError(
154 : state,
155 0 : format("SimulateHeatingCoilComponents: Invalid CompIndex passed={}, Coil name={}, stored Coil Name for that index={}",
156 : CoilNum,
157 : CompName,
158 0 : state.dataHeatingCoils->HeatingCoil(CoilNum).Name));
159 : }
160 1225 : state.dataHeatingCoils->CheckEquipName(CoilNum) = false;
161 : }
162 : }
163 : } else {
164 0 : ShowSevereError(state, "SimulateHeatingCoilComponents: CompIndex argument not used.");
165 0 : ShowContinueError(state, format("..CompName = {}", CompName));
166 0 : ShowFatalError(state, "Preceding conditions cause termination.");
167 : }
168 :
169 122270909 : if (present(SuppHeat)) {
170 112483462 : state.dataHeatingCoils->CoilIsSuppHeater = SuppHeat;
171 : } else {
172 9787447 : state.dataHeatingCoils->CoilIsSuppHeater = false;
173 : }
174 :
175 122270909 : if (present(fanOpMode)) {
176 113192350 : fanOp = fanOpMode;
177 : } else {
178 9078559 : fanOp = HVAC::FanOp::Continuous;
179 : }
180 :
181 122270909 : if (present(PartLoadRatio)) {
182 43928747 : PartLoadFrac = PartLoadRatio;
183 : } else {
184 78342162 : PartLoadFrac = 1.0;
185 : }
186 :
187 122270909 : if (present(QCoilReq)) {
188 118299355 : QCoilRequired = QCoilReq;
189 : } else {
190 3971554 : QCoilRequired = DataLoopNode::SensedLoadFlagValue;
191 : }
192 :
193 : // With the correct CoilNum Initialize
194 122270909 : InitHeatingCoil(state, CoilNum, FirstHVACIteration, QCoilRequired); // Initialize all HeatingCoil related parameters
195 :
196 : // Calculate the Correct HeatingCoil Model with the current CoilNum
197 122270909 : switch (state.dataHeatingCoils->HeatingCoil(CoilNum).HCoilType_Num) {
198 34314023 : case HVAC::Coil_HeatingElectric: {
199 34314023 : CalcElectricHeatingCoil(state, CoilNum, QCoilRequired, QCoilActual2, fanOp, PartLoadFrac);
200 34314023 : } break;
201 1063066 : case HVAC::Coil_HeatingElectric_MultiStage: {
202 1063066 : CalcMultiStageElectricHeatingCoil(
203 : state,
204 : CoilNum,
205 : SpeedRatio,
206 : PartLoadRatio,
207 : StageNum,
208 : fanOp,
209 : QCoilActual2,
210 1063066 : state.dataHeatingCoils->CoilIsSuppHeater); // Autodesk:OPTIONAL SpeedRatio, PartLoadRatio, StageNum used without PRESENT check
211 1063066 : } break;
212 86405587 : case HVAC::Coil_HeatingGasOrOtherFuel: {
213 86405587 : CalcFuelHeatingCoil(state, CoilNum, QCoilRequired, QCoilActual2, fanOp, PartLoadFrac);
214 86405587 : } break;
215 382010 : case HVAC::Coil_HeatingGas_MultiStage: {
216 382010 : CalcMultiStageGasHeatingCoil(state,
217 : CoilNum,
218 : SpeedRatio,
219 : PartLoadRatio,
220 : StageNum,
221 : fanOp); // Autodesk:OPTIONAL SpeedRatio, PartLoadRatio, StageNum used without PRESENT check
222 382010 : } break;
223 106223 : case HVAC::Coil_HeatingDesuperheater: {
224 106223 : CalcDesuperheaterHeatingCoil(state, CoilNum, QCoilRequired, QCoilActual2);
225 106223 : } break;
226 0 : default:
227 0 : QCoilActual2 = 0.0;
228 0 : break;
229 : }
230 :
231 : // Update the current HeatingCoil to the outlet nodes
232 122270909 : UpdateHeatingCoil(state, CoilNum);
233 :
234 : // Report the current HeatingCoil
235 122270909 : ReportHeatingCoil(state, CoilNum, state.dataHeatingCoils->CoilIsSuppHeater);
236 :
237 122270909 : if (present(QCoilActual)) {
238 72732462 : QCoilActual = QCoilActual2;
239 : }
240 122270909 : }
241 :
242 292 : void GetHeatingCoilInput(EnergyPlusData &state)
243 : {
244 :
245 : // SUBROUTINE INFORMATION:
246 : // AUTHOR Richard Liesen
247 : // DATE WRITTEN May 2000
248 :
249 : // PURPOSE OF THIS SUBROUTINE:
250 : // Obtains input data for coils and stores it in coil data structures
251 :
252 : // METHODOLOGY EMPLOYED:
253 : // Uses "Get" routines to read in data.
254 :
255 : // SUBROUTINE PARAMETER DEFINITIONS:
256 : static constexpr std::string_view RoutineName = "GetHeatingCoilInput: "; // include trailing blank space
257 : static constexpr std::string_view routineName = "GetHeatingCoilInput";
258 :
259 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
260 292 : std::string CurrentModuleObject; // for ease in getting objects
261 292 : Array1D_string Alphas; // Alpha input items for object
262 292 : Array1D_string cAlphaFields; // Alpha field names
263 292 : Array1D_string cNumericFields; // Numeric field names
264 292 : Array1D<Real64> Numbers; // Numeric input items for object
265 292 : Array1D_bool lAlphaBlanks; // Logical array, alpha field input BLANK = .TRUE.
266 292 : Array1D_bool lNumericBlanks; // Logical array, numeric field input BLANK = .TRUE.
267 : int NumAlphas;
268 : int NumNums;
269 : int IOStat;
270 : int StageNum;
271 : bool DXCoilErrFlag; // Used in GetDXCoil mining functions
272 : bool errFlag;
273 :
274 292 : state.dataHeatingCoils->NumElecCoil = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Coil:Heating:Electric");
275 584 : state.dataHeatingCoils->NumElecCoilMultiStage =
276 292 : state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Coil:Heating:Electric:MultiStage");
277 292 : state.dataHeatingCoils->NumFuelCoil = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Coil:Heating:Fuel");
278 584 : state.dataHeatingCoils->NumGasCoilMultiStage =
279 292 : state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Coil:Heating:Gas:MultiStage");
280 584 : state.dataHeatingCoils->NumDesuperheaterCoil =
281 292 : state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Coil:Heating:Desuperheater");
282 292 : state.dataHeatingCoils->NumHeatingCoils = state.dataHeatingCoils->NumElecCoil + state.dataHeatingCoils->NumElecCoilMultiStage +
283 292 : state.dataHeatingCoils->NumFuelCoil + state.dataHeatingCoils->NumGasCoilMultiStage +
284 292 : state.dataHeatingCoils->NumDesuperheaterCoil;
285 292 : if (state.dataHeatingCoils->NumHeatingCoils > 0) {
286 292 : state.dataHeatingCoils->HeatingCoil.allocate(state.dataHeatingCoils->NumHeatingCoils);
287 292 : state.dataHeatingCoils->HeatingCoilNumericFields.allocate(state.dataHeatingCoils->NumHeatingCoils);
288 292 : state.dataHeatingCoils->ValidSourceType.dimension(state.dataHeatingCoils->NumHeatingCoils, false);
289 292 : state.dataHeatingCoils->CheckEquipName.dimension(state.dataHeatingCoils->NumHeatingCoils, true);
290 : }
291 :
292 584 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(
293 292 : state, "Coil:Heating:Electric", state.dataHeatingCoils->TotalArgs, NumAlphas, NumNums);
294 292 : state.dataHeatingCoils->MaxNums = max(state.dataHeatingCoils->MaxNums, NumNums);
295 292 : state.dataHeatingCoils->MaxAlphas = max(state.dataHeatingCoils->MaxAlphas, NumAlphas);
296 584 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(
297 292 : state, "Coil:Heating:Electric:MultiStage", state.dataHeatingCoils->TotalArgs, NumAlphas, NumNums);
298 292 : state.dataHeatingCoils->MaxNums = max(state.dataHeatingCoils->MaxNums, NumNums);
299 292 : state.dataHeatingCoils->MaxAlphas = max(state.dataHeatingCoils->MaxAlphas, NumAlphas);
300 584 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(
301 292 : state, "Coil:Heating:Fuel", state.dataHeatingCoils->TotalArgs, NumAlphas, NumNums);
302 292 : state.dataHeatingCoils->MaxNums = max(state.dataHeatingCoils->MaxNums, NumNums);
303 292 : state.dataHeatingCoils->MaxAlphas = max(state.dataHeatingCoils->MaxAlphas, NumAlphas);
304 584 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(
305 292 : state, "Coil:Heating:Gas:MultiStage", state.dataHeatingCoils->TotalArgs, NumAlphas, NumNums);
306 292 : state.dataHeatingCoils->MaxNums = max(state.dataHeatingCoils->MaxNums, NumNums);
307 292 : state.dataHeatingCoils->MaxAlphas = max(state.dataHeatingCoils->MaxAlphas, NumAlphas);
308 584 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(
309 292 : state, "Coil:Heating:Desuperheater", state.dataHeatingCoils->TotalArgs, NumAlphas, NumNums);
310 292 : state.dataHeatingCoils->MaxNums = max(state.dataHeatingCoils->MaxNums, NumNums);
311 292 : state.dataHeatingCoils->MaxAlphas = max(state.dataHeatingCoils->MaxAlphas, NumAlphas);
312 :
313 292 : Alphas.allocate(state.dataHeatingCoils->MaxAlphas);
314 292 : cAlphaFields.allocate(state.dataHeatingCoils->MaxAlphas);
315 292 : cNumericFields.allocate(state.dataHeatingCoils->MaxNums);
316 292 : Numbers.dimension(state.dataHeatingCoils->MaxNums, 0.0);
317 292 : lAlphaBlanks.dimension(state.dataHeatingCoils->MaxAlphas, true);
318 292 : lNumericBlanks.dimension(state.dataHeatingCoils->MaxNums, true);
319 :
320 : // Get the data for electric heating coils
321 957 : for (int ElecCoilNum = 1; ElecCoilNum <= state.dataHeatingCoils->NumElecCoil; ++ElecCoilNum) {
322 :
323 665 : auto &heatingCoil = state.dataHeatingCoils->HeatingCoil(ElecCoilNum);
324 665 : auto &heatingCoilNumericFields = state.dataHeatingCoils->HeatingCoilNumericFields(ElecCoilNum);
325 :
326 665 : CurrentModuleObject = "Coil:Heating:Electric";
327 665 : heatingCoil.FuelType = Constant::eFuel::Electricity;
328 :
329 665 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
330 : CurrentModuleObject,
331 : ElecCoilNum,
332 : Alphas,
333 : NumAlphas,
334 : Numbers,
335 : NumNums,
336 : IOStat,
337 : lNumericBlanks,
338 : lAlphaBlanks,
339 : cAlphaFields,
340 : cNumericFields);
341 :
342 665 : ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
343 665 : heatingCoilNumericFields.FieldNames.allocate(state.dataHeatingCoils->MaxNums);
344 665 : heatingCoilNumericFields.FieldNames = cNumericFields;
345 :
346 : // InputErrorsFound will be set to True if problem was found, left untouched otherwise
347 665 : GlobalNames::VerifyUniqueCoilName(
348 665 : state, CurrentModuleObject, Alphas(1), state.dataHeatingCoils->InputErrorsFound, CurrentModuleObject + " Name");
349 :
350 665 : heatingCoil.Name = Alphas(1);
351 665 : if (lAlphaBlanks(2)) {
352 65 : heatingCoil.availSched = Sched::GetScheduleAlwaysOn(state);
353 600 : } else if ((heatingCoil.availSched = Sched::GetSchedule(state, Alphas(2))) == nullptr) {
354 0 : ShowSevereItemNotFound(state, eoh, cAlphaFields(2), Alphas(2));
355 0 : state.dataHeatingCoils->InputErrorsFound = true;
356 : }
357 :
358 665 : heatingCoil.HeatingCoilType = "Heating";
359 665 : heatingCoil.HeatingCoilModel = "Electric";
360 665 : heatingCoil.HCoilType_Num = HVAC::Coil_HeatingElectric;
361 :
362 665 : heatingCoil.Efficiency = Numbers(1);
363 665 : heatingCoil.NominalCapacity = Numbers(2);
364 665 : errFlag = false;
365 665 : heatingCoil.AirInletNodeNum = GetOnlySingleNode(state,
366 665 : Alphas(3),
367 : errFlag,
368 : DataLoopNode::ConnectionObjectType::CoilHeatingElectric,
369 665 : Alphas(1),
370 : DataLoopNode::NodeFluidType::Air,
371 : DataLoopNode::ConnectionType::Inlet,
372 : NodeInputManager::CompFluidStream::Primary,
373 : DataLoopNode::ObjectIsNotParent);
374 665 : state.dataHeatingCoils->InputErrorsFound = errFlag || state.dataHeatingCoils->InputErrorsFound;
375 665 : errFlag = false;
376 665 : heatingCoil.AirOutletNodeNum = GetOnlySingleNode(state,
377 665 : Alphas(4),
378 : errFlag,
379 : DataLoopNode::ConnectionObjectType::CoilHeatingElectric,
380 665 : Alphas(1),
381 : DataLoopNode::NodeFluidType::Air,
382 : DataLoopNode::ConnectionType::Outlet,
383 : NodeInputManager::CompFluidStream::Primary,
384 : DataLoopNode::ObjectIsNotParent);
385 665 : state.dataHeatingCoils->InputErrorsFound = errFlag || state.dataHeatingCoils->InputErrorsFound;
386 :
387 665 : BranchNodeConnections::TestCompSet(state, CurrentModuleObject, Alphas(1), Alphas(3), Alphas(4), "Air Nodes");
388 :
389 665 : errFlag = false;
390 665 : heatingCoil.TempSetPointNodeNum = GetOnlySingleNode(state,
391 665 : Alphas(5),
392 : errFlag,
393 : DataLoopNode::ConnectionObjectType::CoilHeatingElectric,
394 665 : Alphas(1),
395 : DataLoopNode::NodeFluidType::Air,
396 : DataLoopNode::ConnectionType::Sensor,
397 : NodeInputManager::CompFluidStream::Primary,
398 : DataLoopNode::ObjectIsNotParent);
399 665 : state.dataHeatingCoils->InputErrorsFound = errFlag || state.dataHeatingCoils->InputErrorsFound;
400 :
401 : // Setup Report variables for the Electric Coils
402 : // CurrentModuleObject = "Coil:Heating:Electric"
403 1330 : SetupOutputVariable(state,
404 : "Heating Coil Heating Energy",
405 : Constant::Units::J,
406 665 : heatingCoil.HeatingCoilLoad,
407 : OutputProcessor::TimeStepType::System,
408 : OutputProcessor::StoreType::Sum,
409 665 : heatingCoil.Name,
410 : Constant::eResource::EnergyTransfer,
411 : OutputProcessor::Group::HVAC,
412 : OutputProcessor::EndUseCat::HeatingCoils);
413 1330 : SetupOutputVariable(state,
414 : "Heating Coil Heating Rate",
415 : Constant::Units::W,
416 665 : heatingCoil.HeatingCoilRate,
417 : OutputProcessor::TimeStepType::System,
418 : OutputProcessor::StoreType::Average,
419 665 : heatingCoil.Name);
420 1330 : SetupOutputVariable(state,
421 : "Heating Coil Electricity Energy",
422 : Constant::Units::J,
423 665 : heatingCoil.ElecUseLoad,
424 : OutputProcessor::TimeStepType::System,
425 : OutputProcessor::StoreType::Sum,
426 665 : heatingCoil.Name,
427 : Constant::eResource::Electricity,
428 : OutputProcessor::Group::HVAC,
429 : OutputProcessor::EndUseCat::Heating);
430 1330 : SetupOutputVariable(state,
431 : "Heating Coil Electricity Rate",
432 : Constant::Units::W,
433 665 : heatingCoil.ElecUseRate,
434 : OutputProcessor::TimeStepType::System,
435 : OutputProcessor::StoreType::Average,
436 665 : heatingCoil.Name);
437 : }
438 :
439 : // Get the data for electric heating coils
440 297 : for (int ElecCoilNum = 1; ElecCoilNum <= state.dataHeatingCoils->NumElecCoilMultiStage; ++ElecCoilNum) {
441 :
442 5 : int CoilNum = state.dataHeatingCoils->NumElecCoil + ElecCoilNum;
443 5 : auto &heatingCoil = state.dataHeatingCoils->HeatingCoil(CoilNum);
444 5 : auto &heatingCoilNumericFields = state.dataHeatingCoils->HeatingCoilNumericFields(CoilNum);
445 :
446 5 : CurrentModuleObject = "Coil:Heating:Electric:MultiStage";
447 5 : heatingCoil.FuelType = Constant::eFuel::Electricity;
448 :
449 5 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
450 : CurrentModuleObject,
451 : ElecCoilNum,
452 : Alphas,
453 : NumAlphas,
454 : Numbers,
455 : NumNums,
456 : IOStat,
457 : lNumericBlanks,
458 : lAlphaBlanks,
459 : cAlphaFields,
460 : cNumericFields);
461 :
462 5 : ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
463 5 : heatingCoilNumericFields.FieldNames.allocate(state.dataHeatingCoils->MaxNums);
464 5 : heatingCoilNumericFields.FieldNames = cNumericFields;
465 :
466 : // InputErrorsFound will be set to True if problem was found, left untouched otherwise
467 5 : GlobalNames::VerifyUniqueCoilName(
468 5 : state, CurrentModuleObject, Alphas(1), state.dataHeatingCoils->InputErrorsFound, CurrentModuleObject + " Name");
469 5 : heatingCoil.Name = Alphas(1);
470 5 : if (lAlphaBlanks(2)) {
471 0 : heatingCoil.availSched = Sched::GetScheduleAlwaysOn(state);
472 5 : } else if ((heatingCoil.availSched = Sched::GetSchedule(state, Alphas(2))) == nullptr) {
473 0 : ShowSevereItemNotFound(state, eoh, cAlphaFields(2), Alphas(2));
474 0 : state.dataHeatingCoils->InputErrorsFound = true;
475 : }
476 :
477 5 : heatingCoil.HeatingCoilType = "Heating";
478 5 : heatingCoil.HeatingCoilModel = "Electric:MultiStage";
479 5 : heatingCoil.HCoilType_Num = HVAC::Coil_HeatingElectric_MultiStage;
480 :
481 5 : heatingCoil.NumOfStages = static_cast<int>(Numbers(1));
482 :
483 5 : heatingCoil.MSEfficiency.allocate(heatingCoil.NumOfStages);
484 5 : heatingCoil.MSNominalCapacity.allocate(heatingCoil.NumOfStages);
485 :
486 16 : for (StageNum = 1; StageNum <= heatingCoil.NumOfStages; ++StageNum) {
487 :
488 11 : heatingCoil.MSEfficiency(StageNum) = Numbers(StageNum * 2);
489 11 : heatingCoil.MSNominalCapacity(StageNum) = Numbers(StageNum * 2 + 1);
490 : }
491 :
492 5 : errFlag = false;
493 5 : heatingCoil.AirInletNodeNum = GetOnlySingleNode(state,
494 5 : Alphas(3),
495 : errFlag,
496 : DataLoopNode::ConnectionObjectType::CoilHeatingElectricMultiStage,
497 5 : Alphas(1),
498 : DataLoopNode::NodeFluidType::Air,
499 : DataLoopNode::ConnectionType::Inlet,
500 : NodeInputManager::CompFluidStream::Primary,
501 : DataLoopNode::ObjectIsNotParent);
502 5 : state.dataHeatingCoils->InputErrorsFound = errFlag || state.dataHeatingCoils->InputErrorsFound;
503 5 : errFlag = false;
504 5 : heatingCoil.AirOutletNodeNum = GetOnlySingleNode(state,
505 5 : Alphas(4),
506 : errFlag,
507 : DataLoopNode::ConnectionObjectType::CoilHeatingElectricMultiStage,
508 5 : Alphas(1),
509 : DataLoopNode::NodeFluidType::Air,
510 : DataLoopNode::ConnectionType::Outlet,
511 : NodeInputManager::CompFluidStream::Primary,
512 : DataLoopNode::ObjectIsNotParent);
513 5 : state.dataHeatingCoils->InputErrorsFound = errFlag || state.dataHeatingCoils->InputErrorsFound;
514 :
515 5 : BranchNodeConnections::TestCompSet(state, CurrentModuleObject, Alphas(1), Alphas(3), Alphas(4), "Air Nodes");
516 :
517 5 : errFlag = false;
518 5 : heatingCoil.TempSetPointNodeNum = GetOnlySingleNode(state,
519 5 : Alphas(5),
520 : errFlag,
521 : DataLoopNode::ConnectionObjectType::CoilHeatingElectricMultiStage,
522 5 : Alphas(1),
523 : DataLoopNode::NodeFluidType::Air,
524 : DataLoopNode::ConnectionType::Sensor,
525 : NodeInputManager::CompFluidStream::Primary,
526 : DataLoopNode::ObjectIsNotParent);
527 5 : state.dataHeatingCoils->InputErrorsFound = errFlag || state.dataHeatingCoils->InputErrorsFound;
528 :
529 : // Setup Report variables for the Electric Coils
530 : // CurrentModuleObject = "Coil:Heating:Electric:MultiStage"
531 10 : SetupOutputVariable(state,
532 : "Heating Coil Heating Energy",
533 : Constant::Units::J,
534 5 : heatingCoil.HeatingCoilLoad,
535 : OutputProcessor::TimeStepType::System,
536 : OutputProcessor::StoreType::Sum,
537 5 : heatingCoil.Name,
538 : Constant::eResource::EnergyTransfer,
539 : OutputProcessor::Group::HVAC,
540 : OutputProcessor::EndUseCat::HeatingCoils);
541 10 : SetupOutputVariable(state,
542 : "Heating Coil Heating Rate",
543 : Constant::Units::W,
544 5 : heatingCoil.HeatingCoilRate,
545 : OutputProcessor::TimeStepType::System,
546 : OutputProcessor::StoreType::Average,
547 5 : heatingCoil.Name);
548 10 : SetupOutputVariable(state,
549 : "Heating Coil Electricity Energy",
550 : Constant::Units::J,
551 5 : heatingCoil.ElecUseLoad,
552 : OutputProcessor::TimeStepType::System,
553 : OutputProcessor::StoreType::Sum,
554 5 : heatingCoil.Name,
555 : Constant::eResource::Electricity,
556 : OutputProcessor::Group::HVAC,
557 : OutputProcessor::EndUseCat::Heating);
558 10 : SetupOutputVariable(state,
559 : "Heating Coil Electricity Rate",
560 : Constant::Units::W,
561 5 : heatingCoil.ElecUseRate,
562 : OutputProcessor::TimeStepType::System,
563 : OutputProcessor::StoreType::Average,
564 5 : heatingCoil.Name);
565 : }
566 :
567 : // Get the data for for fuel heating coils
568 1196 : for (int FuelCoilNum = 1; FuelCoilNum <= state.dataHeatingCoils->NumFuelCoil; ++FuelCoilNum) {
569 :
570 904 : int CoilNum = state.dataHeatingCoils->NumElecCoil + state.dataHeatingCoils->NumElecCoilMultiStage + FuelCoilNum;
571 904 : auto &heatingCoil = state.dataHeatingCoils->HeatingCoil(CoilNum);
572 904 : auto &heatingCoilNumericFields = state.dataHeatingCoils->HeatingCoilNumericFields(CoilNum);
573 :
574 904 : CurrentModuleObject = "Coil:Heating:Fuel";
575 :
576 904 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
577 : CurrentModuleObject,
578 : FuelCoilNum,
579 : Alphas,
580 : NumAlphas,
581 : Numbers,
582 : NumNums,
583 : IOStat,
584 : lNumericBlanks,
585 : lAlphaBlanks,
586 : cAlphaFields,
587 : cNumericFields);
588 :
589 904 : ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
590 904 : heatingCoilNumericFields.FieldNames.allocate(state.dataHeatingCoils->MaxNums);
591 904 : heatingCoilNumericFields.FieldNames = cNumericFields;
592 :
593 : // InputErrorsFound will be set to True if problem was found, left untouched otherwise
594 904 : GlobalNames::VerifyUniqueCoilName(
595 904 : state, CurrentModuleObject, Alphas(1), state.dataHeatingCoils->InputErrorsFound, CurrentModuleObject + " Name");
596 904 : heatingCoil.Name = Alphas(1);
597 904 : if (lAlphaBlanks(2)) {
598 85 : heatingCoil.availSched = Sched::GetScheduleAlwaysOn(state);
599 819 : } else if ((heatingCoil.availSched = Sched::GetSchedule(state, Alphas(2))) == nullptr) {
600 0 : ShowSevereItemNotFound(state, eoh, cAlphaFields(2), Alphas(2));
601 0 : state.dataHeatingCoils->InputErrorsFound = true;
602 : }
603 :
604 904 : heatingCoil.HeatingCoilType = "Heating";
605 904 : heatingCoil.HeatingCoilModel = "Fuel";
606 904 : heatingCoil.HCoilType_Num = HVAC::Coil_HeatingGasOrOtherFuel;
607 :
608 904 : heatingCoil.FuelType = static_cast<Constant::eFuel>(getEnumValue(Constant::eFuelNamesUC, Alphas(3)));
609 904 : if (!(heatingCoil.FuelType == Constant::eFuel::NaturalGas || heatingCoil.FuelType == Constant::eFuel::Propane ||
610 1 : heatingCoil.FuelType == Constant::eFuel::Diesel || heatingCoil.FuelType == Constant::eFuel::Gasoline ||
611 1 : heatingCoil.FuelType == Constant::eFuel::FuelOilNo1 || heatingCoil.FuelType == Constant::eFuel::FuelOilNo2 ||
612 0 : heatingCoil.FuelType == Constant::eFuel::OtherFuel1 || heatingCoil.FuelType == Constant::eFuel::OtherFuel2 ||
613 0 : heatingCoil.FuelType == Constant::eFuel::Coal)) {
614 0 : ShowSevereError(state,
615 0 : format("{}{}: Invalid {} entered ={} for {}={}",
616 : RoutineName,
617 : CurrentModuleObject,
618 : cAlphaFields(3),
619 : Alphas(3),
620 : cAlphaFields(1),
621 : Alphas(1)));
622 0 : state.dataHeatingCoils->InputErrorsFound = true;
623 : }
624 904 : std::string const sFuelType(Constant::eFuelNames[static_cast<int>(heatingCoil.FuelType)]);
625 :
626 904 : heatingCoil.Efficiency = Numbers(1);
627 904 : heatingCoil.NominalCapacity = Numbers(2);
628 904 : errFlag = false;
629 904 : heatingCoil.AirInletNodeNum = GetOnlySingleNode(state,
630 904 : Alphas(4),
631 : errFlag,
632 : DataLoopNode::ConnectionObjectType::CoilHeatingFuel,
633 904 : Alphas(1),
634 : DataLoopNode::NodeFluidType::Air,
635 : DataLoopNode::ConnectionType::Inlet,
636 : NodeInputManager::CompFluidStream::Primary,
637 : DataLoopNode::ObjectIsNotParent);
638 904 : state.dataHeatingCoils->InputErrorsFound = errFlag || state.dataHeatingCoils->InputErrorsFound;
639 904 : errFlag = false;
640 904 : heatingCoil.AirOutletNodeNum = GetOnlySingleNode(state,
641 904 : Alphas(5),
642 : errFlag,
643 : DataLoopNode::ConnectionObjectType::CoilHeatingFuel,
644 904 : Alphas(1),
645 : DataLoopNode::NodeFluidType::Air,
646 : DataLoopNode::ConnectionType::Outlet,
647 : NodeInputManager::CompFluidStream::Primary,
648 : DataLoopNode::ObjectIsNotParent);
649 904 : state.dataHeatingCoils->InputErrorsFound = errFlag || state.dataHeatingCoils->InputErrorsFound;
650 :
651 904 : BranchNodeConnections::TestCompSet(state, CurrentModuleObject, Alphas(1), Alphas(4), Alphas(5), "Air Nodes");
652 :
653 904 : errFlag = false;
654 904 : heatingCoil.TempSetPointNodeNum = GetOnlySingleNode(state,
655 904 : Alphas(6),
656 : errFlag,
657 : DataLoopNode::ConnectionObjectType::CoilHeatingFuel,
658 904 : Alphas(1),
659 : DataLoopNode::NodeFluidType::Air,
660 : DataLoopNode::ConnectionType::Sensor,
661 : NodeInputManager::CompFluidStream::Primary,
662 : DataLoopNode::ObjectIsNotParent);
663 904 : state.dataHeatingCoils->InputErrorsFound = errFlag || state.dataHeatingCoils->InputErrorsFound;
664 :
665 : // parasitic electric load associated with the fuel heating coil
666 904 : heatingCoil.ParasiticElecLoad = Numbers(3);
667 :
668 904 : heatingCoil.PLFCurveIndex = Curve::GetCurveIndex(state, Alphas(7)); // convert curve name to number
669 :
670 : // parasitic fuel load associated with the gas heating coil (standing pilot light)
671 904 : heatingCoil.ParasiticFuelCapacity = Numbers(4);
672 :
673 : // Setup Report variables for the Fuel Coils
674 : // CurrentModuleObject = "Coil:Heating:OtherFuel"
675 :
676 1808 : SetupOutputVariable(state,
677 : "Heating Coil Heating Energy",
678 : Constant::Units::J,
679 904 : heatingCoil.HeatingCoilLoad,
680 : OutputProcessor::TimeStepType::System,
681 : OutputProcessor::StoreType::Sum,
682 904 : heatingCoil.Name,
683 : Constant::eResource::EnergyTransfer,
684 : OutputProcessor::Group::HVAC,
685 : OutputProcessor::EndUseCat::HeatingCoils);
686 1808 : SetupOutputVariable(state,
687 : "Heating Coil Heating Rate",
688 : Constant::Units::W,
689 904 : heatingCoil.HeatingCoilRate,
690 : OutputProcessor::TimeStepType::System,
691 : OutputProcessor::StoreType::Average,
692 904 : heatingCoil.Name);
693 2712 : SetupOutputVariable(state,
694 1808 : format("Heating Coil {} Energy", sFuelType),
695 : Constant::Units::J,
696 904 : heatingCoil.FuelUseLoad,
697 : OutputProcessor::TimeStepType::System,
698 : OutputProcessor::StoreType::Sum,
699 904 : heatingCoil.Name,
700 904 : Constant::eFuel2eResource[(int)heatingCoil.FuelType],
701 : OutputProcessor::Group::HVAC,
702 : OutputProcessor::EndUseCat::Heating);
703 2712 : SetupOutputVariable(state,
704 1808 : format("Heating Coil {} Rate", sFuelType),
705 : Constant::Units::W,
706 904 : heatingCoil.FuelUseRate,
707 : OutputProcessor::TimeStepType::System,
708 : OutputProcessor::StoreType::Average,
709 904 : heatingCoil.Name);
710 1808 : SetupOutputVariable(state,
711 : "Heating Coil Electricity Energy",
712 : Constant::Units::J,
713 904 : heatingCoil.ElecUseLoad,
714 : OutputProcessor::TimeStepType::System,
715 : OutputProcessor::StoreType::Sum,
716 904 : heatingCoil.Name,
717 : Constant::eResource::Electricity,
718 : OutputProcessor::Group::HVAC,
719 : OutputProcessor::EndUseCat::Heating);
720 1808 : SetupOutputVariable(state,
721 : "Heating Coil Electricity Rate",
722 : Constant::Units::W,
723 904 : heatingCoil.ElecUseRate,
724 : OutputProcessor::TimeStepType::System,
725 : OutputProcessor::StoreType::Average,
726 904 : heatingCoil.Name);
727 1808 : SetupOutputVariable(state,
728 : "Heating Coil Runtime Fraction",
729 : Constant::Units::None,
730 904 : heatingCoil.RTF,
731 : OutputProcessor::TimeStepType::System,
732 : OutputProcessor::StoreType::Average,
733 904 : heatingCoil.Name);
734 2712 : SetupOutputVariable(state,
735 1808 : "Heating Coil Ancillary " + sFuelType + " Rate",
736 : Constant::Units::W,
737 904 : heatingCoil.ParasiticFuelRate,
738 : OutputProcessor::TimeStepType::System,
739 : OutputProcessor::StoreType::Average,
740 904 : heatingCoil.Name);
741 2712 : SetupOutputVariable(state,
742 1808 : "Heating Coil Ancillary " + sFuelType + " Energy",
743 : Constant::Units::J,
744 904 : heatingCoil.ParasiticFuelConsumption,
745 : OutputProcessor::TimeStepType::System,
746 : OutputProcessor::StoreType::Sum,
747 904 : heatingCoil.Name,
748 904 : Constant::eFuel2eResource[(int)heatingCoil.FuelType],
749 : OutputProcessor::Group::HVAC,
750 : OutputProcessor::EndUseCat::Heating);
751 904 : }
752 :
753 : // Get the data for for gas multistage heating coils
754 293 : for (int FuelCoilNum = 1; FuelCoilNum <= state.dataHeatingCoils->NumGasCoilMultiStage; ++FuelCoilNum) {
755 :
756 1 : int CoilNum = state.dataHeatingCoils->NumElecCoil + state.dataHeatingCoils->NumElecCoilMultiStage + state.dataHeatingCoils->NumFuelCoil +
757 1 : FuelCoilNum;
758 1 : auto &heatingCoil = state.dataHeatingCoils->HeatingCoil(CoilNum);
759 1 : auto &heatingCoilNumericFields = state.dataHeatingCoils->HeatingCoilNumericFields(CoilNum);
760 1 : CurrentModuleObject = "Coil:Heating:Gas:MultiStage";
761 1 : heatingCoil.FuelType = Constant::eFuel::NaturalGas;
762 :
763 1 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
764 : CurrentModuleObject,
765 : FuelCoilNum,
766 : Alphas,
767 : NumAlphas,
768 : Numbers,
769 : NumNums,
770 : IOStat,
771 : lNumericBlanks,
772 : lAlphaBlanks,
773 : cAlphaFields,
774 : cNumericFields);
775 :
776 1 : ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
777 :
778 1 : heatingCoilNumericFields.FieldNames.allocate(state.dataHeatingCoils->MaxNums);
779 1 : heatingCoilNumericFields.FieldNames = cNumericFields;
780 :
781 : // InputErrorsFound will be set to True if problem was found, left untouched otherwise
782 1 : GlobalNames::VerifyUniqueCoilName(
783 1 : state, CurrentModuleObject, Alphas(1), state.dataHeatingCoils->InputErrorsFound, CurrentModuleObject + " Name");
784 1 : heatingCoil.Name = Alphas(1);
785 :
786 1 : if (lAlphaBlanks(2)) {
787 0 : heatingCoil.availSched = Sched::GetScheduleAlwaysOn(state);
788 1 : } else if ((heatingCoil.availSched = Sched::GetSchedule(state, Alphas(2))) == nullptr) {
789 0 : ShowSevereItemNotFound(state, eoh, cAlphaFields(2), Alphas(2));
790 0 : state.dataHeatingCoils->InputErrorsFound = true;
791 : }
792 :
793 1 : heatingCoil.HeatingCoilType = "Heating";
794 1 : heatingCoil.HeatingCoilModel = "Gas:MultiStage";
795 1 : heatingCoil.HCoilType_Num = HVAC::Coil_HeatingGas_MultiStage;
796 :
797 1 : heatingCoil.ParasiticFuelCapacity = Numbers(1);
798 :
799 1 : heatingCoil.NumOfStages = static_cast<int>(Numbers(2));
800 :
801 1 : heatingCoil.MSEfficiency.allocate(heatingCoil.NumOfStages);
802 1 : heatingCoil.MSNominalCapacity.allocate(heatingCoil.NumOfStages);
803 1 : heatingCoil.MSParasiticElecLoad.allocate(heatingCoil.NumOfStages);
804 :
805 2 : for (StageNum = 1; StageNum <= heatingCoil.NumOfStages; ++StageNum) {
806 :
807 1 : heatingCoil.MSEfficiency(StageNum) = Numbers(StageNum * 3);
808 1 : heatingCoil.MSNominalCapacity(StageNum) = Numbers(StageNum * 3 + 1);
809 1 : heatingCoil.MSParasiticElecLoad(StageNum) = Numbers(StageNum * 3 + 2);
810 : }
811 :
812 1 : errFlag = false;
813 1 : heatingCoil.AirInletNodeNum = GetOnlySingleNode(state,
814 1 : Alphas(3),
815 : errFlag,
816 : DataLoopNode::ConnectionObjectType::CoilHeatingGasMultiStage,
817 1 : Alphas(1),
818 : DataLoopNode::NodeFluidType::Air,
819 : DataLoopNode::ConnectionType::Inlet,
820 : NodeInputManager::CompFluidStream::Primary,
821 : DataLoopNode::ObjectIsNotParent);
822 1 : state.dataHeatingCoils->InputErrorsFound = errFlag || state.dataHeatingCoils->InputErrorsFound;
823 1 : errFlag = false;
824 1 : heatingCoil.AirOutletNodeNum = GetOnlySingleNode(state,
825 1 : Alphas(4),
826 : errFlag,
827 : DataLoopNode::ConnectionObjectType::CoilHeatingGasMultiStage,
828 1 : Alphas(1),
829 : DataLoopNode::NodeFluidType::Air,
830 : DataLoopNode::ConnectionType::Outlet,
831 : NodeInputManager::CompFluidStream::Primary,
832 : DataLoopNode::ObjectIsNotParent);
833 1 : state.dataHeatingCoils->InputErrorsFound = errFlag || state.dataHeatingCoils->InputErrorsFound;
834 :
835 1 : BranchNodeConnections::TestCompSet(state, CurrentModuleObject, Alphas(1), Alphas(3), Alphas(4), "Air Nodes");
836 :
837 1 : errFlag = false;
838 1 : heatingCoil.TempSetPointNodeNum = GetOnlySingleNode(state,
839 1 : Alphas(5),
840 : errFlag,
841 : DataLoopNode::ConnectionObjectType::CoilHeatingGasMultiStage,
842 1 : Alphas(1),
843 : DataLoopNode::NodeFluidType::Air,
844 : DataLoopNode::ConnectionType::Sensor,
845 : NodeInputManager::CompFluidStream::Primary,
846 : DataLoopNode::ObjectIsNotParent);
847 1 : state.dataHeatingCoils->InputErrorsFound = errFlag || state.dataHeatingCoils->InputErrorsFound;
848 :
849 : // parasitic electric load associated with the gas heating coil
850 1 : heatingCoil.ParasiticElecLoad = Numbers(10);
851 :
852 1 : heatingCoil.PLFCurveIndex = Curve::GetCurveIndex(state, Alphas(6)); // convert curve name to number
853 :
854 : // parasitic gas load associated with the gas heating coil (standing pilot light)
855 :
856 : // Setup Report variables for the Gas Coils
857 : // CurrentModuleObject = "Coil:Heating:Gas:MultiStage"
858 2 : SetupOutputVariable(state,
859 : "Heating Coil Heating Energy",
860 : Constant::Units::J,
861 1 : heatingCoil.HeatingCoilLoad,
862 : OutputProcessor::TimeStepType::System,
863 : OutputProcessor::StoreType::Sum,
864 1 : heatingCoil.Name,
865 : Constant::eResource::EnergyTransfer,
866 : OutputProcessor::Group::HVAC,
867 : OutputProcessor::EndUseCat::HeatingCoils);
868 2 : SetupOutputVariable(state,
869 : "Heating Coil Heating Rate",
870 : Constant::Units::W,
871 1 : heatingCoil.HeatingCoilRate,
872 : OutputProcessor::TimeStepType::System,
873 : OutputProcessor::StoreType::Average,
874 1 : heatingCoil.Name);
875 2 : SetupOutputVariable(state,
876 : "Heating Coil NaturalGas Energy",
877 : Constant::Units::J,
878 1 : heatingCoil.FuelUseLoad,
879 : OutputProcessor::TimeStepType::System,
880 : OutputProcessor::StoreType::Sum,
881 1 : heatingCoil.Name,
882 : Constant::eResource::NaturalGas,
883 : OutputProcessor::Group::HVAC,
884 : OutputProcessor::EndUseCat::Heating);
885 2 : SetupOutputVariable(state,
886 : "Heating Coil NaturalGas Rate",
887 : Constant::Units::W,
888 1 : heatingCoil.FuelUseRate,
889 : OutputProcessor::TimeStepType::System,
890 : OutputProcessor::StoreType::Average,
891 1 : heatingCoil.Name);
892 2 : SetupOutputVariable(state,
893 : "Heating Coil Electricity Energy",
894 : Constant::Units::J,
895 1 : heatingCoil.ElecUseLoad,
896 : OutputProcessor::TimeStepType::System,
897 : OutputProcessor::StoreType::Sum,
898 1 : heatingCoil.Name,
899 : Constant::eResource::Electricity,
900 : OutputProcessor::Group::HVAC,
901 : OutputProcessor::EndUseCat::Heating);
902 2 : SetupOutputVariable(state,
903 : "Heating Coil Electricity Rate",
904 : Constant::Units::W,
905 1 : heatingCoil.ElecUseRate,
906 : OutputProcessor::TimeStepType::System,
907 : OutputProcessor::StoreType::Average,
908 1 : heatingCoil.Name);
909 2 : SetupOutputVariable(state,
910 : "Heating Coil Runtime Fraction",
911 : Constant::Units::None,
912 1 : heatingCoil.RTF,
913 : OutputProcessor::TimeStepType::System,
914 : OutputProcessor::StoreType::Average,
915 1 : heatingCoil.Name);
916 2 : SetupOutputVariable(state,
917 : "Heating Coil Ancillary NaturalGas Rate",
918 : Constant::Units::W,
919 1 : heatingCoil.ParasiticFuelRate,
920 : OutputProcessor::TimeStepType::System,
921 : OutputProcessor::StoreType::Average,
922 1 : heatingCoil.Name);
923 2 : SetupOutputVariable(state,
924 : "Heating Coil Ancillary NaturalGas Energy",
925 : Constant::Units::J,
926 1 : heatingCoil.ParasiticFuelConsumption,
927 : OutputProcessor::TimeStepType::System,
928 : OutputProcessor::StoreType::Sum,
929 1 : heatingCoil.Name,
930 : Constant::eResource::NaturalGas,
931 : OutputProcessor::Group::HVAC,
932 : OutputProcessor::EndUseCat::Heating);
933 : }
934 :
935 : // Get the data for for desuperheater heating coils
936 295 : for (int DesuperheaterCoilNum = 1; DesuperheaterCoilNum <= state.dataHeatingCoils->NumDesuperheaterCoil; ++DesuperheaterCoilNum) {
937 :
938 3 : int CoilNum = state.dataHeatingCoils->NumElecCoil + state.dataHeatingCoils->NumElecCoilMultiStage + state.dataHeatingCoils->NumFuelCoil +
939 3 : state.dataHeatingCoils->NumGasCoilMultiStage + DesuperheaterCoilNum;
940 3 : auto &heatingCoil = state.dataHeatingCoils->HeatingCoil(CoilNum);
941 3 : auto &heatingCoilNumericFields = state.dataHeatingCoils->HeatingCoilNumericFields(CoilNum);
942 3 : CurrentModuleObject = "Coil:Heating:Desuperheater";
943 3 : heatingCoil.FuelType = Constant::eFuel::Electricity;
944 :
945 3 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
946 : CurrentModuleObject,
947 : DesuperheaterCoilNum,
948 : Alphas,
949 : NumAlphas,
950 : Numbers,
951 : NumNums,
952 : IOStat,
953 : lNumericBlanks,
954 : lAlphaBlanks,
955 : cAlphaFields,
956 : cNumericFields);
957 :
958 3 : ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
959 3 : heatingCoilNumericFields.FieldNames.allocate(state.dataHeatingCoils->MaxNums);
960 3 : heatingCoilNumericFields.FieldNames = cNumericFields;
961 :
962 : // InputErrorsFound will be set to True if problem was found, left untouched otherwise
963 3 : GlobalNames::VerifyUniqueCoilName(
964 3 : state, CurrentModuleObject, Alphas(1), state.dataHeatingCoils->InputErrorsFound, CurrentModuleObject + " Name");
965 3 : heatingCoil.Name = Alphas(1);
966 3 : if (lAlphaBlanks(2)) {
967 0 : heatingCoil.availSched = Sched::GetScheduleAlwaysOn(state);
968 3 : } else if ((heatingCoil.availSched = Sched::GetSchedule(state, Alphas(2))) == nullptr) {
969 0 : ShowSevereItemNotFound(state, eoh, cAlphaFields(2), Alphas(2));
970 0 : state.dataHeatingCoils->InputErrorsFound = true;
971 3 : } else if (!heatingCoil.availSched->checkMinMaxVals(state, Clusive::In, 0.0, Clusive::In, 1.0)) {
972 0 : Sched::ShowSevereBadMinMax(state, eoh, cAlphaFields(2), Alphas(2), Clusive::In, 0.0, Clusive::In, 1.0);
973 0 : state.dataHeatingCoils->InputErrorsFound = true;
974 : }
975 :
976 3 : heatingCoil.HeatingCoilType = "Heating";
977 3 : heatingCoil.HeatingCoilModel = "Desuperheater";
978 3 : heatingCoil.HCoilType_Num = HVAC::Coil_HeatingDesuperheater;
979 :
980 : // HeatingCoil(CoilNum)%Efficiency = Numbers(1)
981 : //(Numbers(1)) error limits checked and defaults applied on efficiency after
982 : // identifying souce type.
983 :
984 3 : errFlag = false;
985 3 : heatingCoil.AirInletNodeNum = GetOnlySingleNode(state,
986 3 : Alphas(3),
987 : errFlag,
988 : DataLoopNode::ConnectionObjectType::CoilHeatingDesuperheater,
989 3 : Alphas(1),
990 : DataLoopNode::NodeFluidType::Air,
991 : DataLoopNode::ConnectionType::Inlet,
992 : NodeInputManager::CompFluidStream::Primary,
993 : DataLoopNode::ObjectIsNotParent);
994 3 : state.dataHeatingCoils->InputErrorsFound = errFlag || state.dataHeatingCoils->InputErrorsFound;
995 3 : errFlag = false;
996 3 : heatingCoil.AirOutletNodeNum = GetOnlySingleNode(state,
997 3 : Alphas(4),
998 : errFlag,
999 : DataLoopNode::ConnectionObjectType::CoilHeatingDesuperheater,
1000 3 : Alphas(1),
1001 : DataLoopNode::NodeFluidType::Air,
1002 : DataLoopNode::ConnectionType::Outlet,
1003 : NodeInputManager::CompFluidStream::Primary,
1004 : DataLoopNode::ObjectIsNotParent);
1005 3 : state.dataHeatingCoils->InputErrorsFound = errFlag || state.dataHeatingCoils->InputErrorsFound;
1006 :
1007 3 : BranchNodeConnections::TestCompSet(state, CurrentModuleObject, Alphas(1), Alphas(3), Alphas(4), "Air Nodes");
1008 :
1009 5 : if ((Util::SameString(Alphas(5), "Refrigeration:Condenser:AirCooled")) ||
1010 5 : (Util::SameString(Alphas(5), "Refrigeration:Condenser:EvaporativeCooled")) ||
1011 5 : (Util::SameString(Alphas(5), "Refrigeration:Condenser:WaterCooled"))) {
1012 1 : if (lNumericBlanks(1)) {
1013 0 : heatingCoil.Efficiency = 0.8;
1014 : } else {
1015 1 : heatingCoil.Efficiency = Numbers(1);
1016 1 : if (Numbers(1) < 0.0 || Numbers(1) > 0.9) {
1017 0 : ShowSevereError(
1018 : state,
1019 0 : format("{}, \"{}\" heat reclaim recovery efficiency must be >= 0 and <=0.9", CurrentModuleObject, heatingCoil.Name));
1020 0 : state.dataHeatingCoils->InputErrorsFound = true;
1021 : }
1022 : }
1023 : } else {
1024 2 : if (lNumericBlanks(1)) {
1025 0 : heatingCoil.Efficiency = 0.25;
1026 : } else {
1027 2 : heatingCoil.Efficiency = Numbers(1);
1028 2 : if (Numbers(1) < 0.0 || Numbers(1) > 0.3) {
1029 0 : ShowSevereError(
1030 : state,
1031 0 : format("{}, \"{}\" heat reclaim recovery efficiency must be >= 0 and <=0.3", CurrentModuleObject, heatingCoil.Name));
1032 0 : state.dataHeatingCoils->InputErrorsFound = true;
1033 : }
1034 : }
1035 : }
1036 :
1037 : // Find the DX equipment index associated with the desuperheater heating coil.
1038 : // The CoilNum may not be found here when zone heating equip. exists. Check again in InitHeatingCoil.
1039 : // (when zone equipment heating coils are included in the input, the air loop DX equipment has not yet been read in)
1040 3 : if (Util::SameString(Alphas(5), "Refrigeration:CompressorRack")) {
1041 1 : heatingCoil.ReclaimHeatingSource = HeatObjTypes::COMPRESSORRACK_REFRIGERATEDCASE;
1042 2 : RefrigeratedCase::GetRefrigeratedRackIndex(
1043 1 : state, Alphas(6), heatingCoil.ReclaimHeatingSourceIndexNum, DataHeatBalance::RefrigSystemType::Rack, DXCoilErrFlag, Alphas(5));
1044 1 : if (heatingCoil.ReclaimHeatingSourceIndexNum > 0) {
1045 1 : if (allocated(state.dataHeatBal->HeatReclaimRefrigeratedRack)) {
1046 : DataHeatBalance::HeatReclaimDataBase &HeatReclaim =
1047 1 : state.dataHeatBal->HeatReclaimRefrigeratedRack(heatingCoil.ReclaimHeatingSourceIndexNum);
1048 1 : if (!allocated(HeatReclaim.HVACDesuperheaterReclaimedHeat)) {
1049 1 : HeatReclaim.HVACDesuperheaterReclaimedHeat.allocate(state.dataHeatingCoils->NumDesuperheaterCoil);
1050 1 : std::fill(HeatReclaim.HVACDesuperheaterReclaimedHeat.begin(), HeatReclaim.HVACDesuperheaterReclaimedHeat.end(), 0.0);
1051 : }
1052 1 : HeatReclaim.ReclaimEfficiencyTotal += heatingCoil.Efficiency;
1053 1 : if (HeatReclaim.ReclaimEfficiencyTotal > 0.3) {
1054 0 : ShowSevereError(
1055 : state,
1056 0 : format("{}, \"{}\" sum of heat reclaim recovery efficiencies from the same source coil: \"{} \" cannot be over 0.3",
1057 : HVAC::cAllCoilTypes(heatingCoil.HCoilType_Num),
1058 0 : heatingCoil.Name,
1059 0 : heatingCoil.ReclaimHeatingCoilName));
1060 : }
1061 1 : state.dataHeatingCoils->ValidSourceType(CoilNum) = true;
1062 : }
1063 : }
1064 3 : } else if ((Util::SameString(Alphas(5), "Refrigeration:Condenser:AirCooled")) ||
1065 3 : (Util::SameString(Alphas(5), "Refrigeration:Condenser:EvaporativeCooled")) ||
1066 3 : (Util::SameString(Alphas(5), "Refrigeration:Condenser:WaterCooled"))) {
1067 1 : heatingCoil.ReclaimHeatingSource = HeatObjTypes::CONDENSER_REFRIGERATION;
1068 2 : RefrigeratedCase::GetRefrigeratedRackIndex(state,
1069 1 : Alphas(6),
1070 1 : heatingCoil.ReclaimHeatingSourceIndexNum,
1071 : DataHeatBalance::RefrigSystemType::Detailed,
1072 : DXCoilErrFlag,
1073 1 : Alphas(5));
1074 1 : if (heatingCoil.ReclaimHeatingSourceIndexNum > 0) {
1075 1 : if (allocated(state.dataHeatBal->HeatReclaimRefrigCondenser)) {
1076 : DataHeatBalance::HeatReclaimDataBase &HeatReclaim =
1077 1 : state.dataHeatBal->HeatReclaimRefrigCondenser(heatingCoil.ReclaimHeatingSourceIndexNum);
1078 1 : if (!allocated(HeatReclaim.HVACDesuperheaterReclaimedHeat)) {
1079 1 : HeatReclaim.HVACDesuperheaterReclaimedHeat.allocate(state.dataHeatingCoils->NumDesuperheaterCoil);
1080 1 : std::fill(HeatReclaim.HVACDesuperheaterReclaimedHeat.begin(), HeatReclaim.HVACDesuperheaterReclaimedHeat.end(), 0.0);
1081 : }
1082 1 : HeatReclaim.ReclaimEfficiencyTotal += heatingCoil.Efficiency;
1083 1 : if (HeatReclaim.ReclaimEfficiencyTotal > 0.9) {
1084 0 : ShowSevereError(
1085 : state,
1086 0 : format("{}, \"{}\" sum of heat reclaim recovery efficiencies from the same source coil: \"{} \" cannot be over 0.9",
1087 : HVAC::cAllCoilTypes(heatingCoil.HCoilType_Num),
1088 0 : heatingCoil.Name,
1089 0 : heatingCoil.ReclaimHeatingCoilName));
1090 : }
1091 1 : state.dataHeatingCoils->ValidSourceType(CoilNum) = true;
1092 : }
1093 : }
1094 1 : } else if (Util::SameString(Alphas(5), "Coil:Cooling:DX:SingleSpeed")) {
1095 0 : heatingCoil.ReclaimHeatingSource = HeatObjTypes::COIL_DX_COOLING;
1096 0 : DXCoils::GetDXCoilIndex(state, Alphas(6), heatingCoil.ReclaimHeatingSourceIndexNum, DXCoilErrFlag, Alphas(5));
1097 0 : if (heatingCoil.ReclaimHeatingSourceIndexNum > 0) {
1098 0 : if (allocated(state.dataHeatBal->HeatReclaimDXCoil)) {
1099 : DataHeatBalance::HeatReclaimDataBase &HeatReclaim =
1100 0 : state.dataHeatBal->HeatReclaimDXCoil(heatingCoil.ReclaimHeatingSourceIndexNum);
1101 0 : if (!allocated(HeatReclaim.HVACDesuperheaterReclaimedHeat)) {
1102 0 : HeatReclaim.HVACDesuperheaterReclaimedHeat.allocate(state.dataHeatingCoils->NumDesuperheaterCoil);
1103 0 : std::fill(HeatReclaim.HVACDesuperheaterReclaimedHeat.begin(), HeatReclaim.HVACDesuperheaterReclaimedHeat.end(), 0.0);
1104 : }
1105 0 : HeatReclaim.ReclaimEfficiencyTotal += heatingCoil.Efficiency;
1106 0 : if (HeatReclaim.ReclaimEfficiencyTotal > 0.3) {
1107 0 : ShowSevereError(
1108 : state,
1109 0 : format("{}, \"{}\" sum of heat reclaim recovery efficiencies from the same source coil: \"{} \" cannot be over 0.3",
1110 : HVAC::cAllCoilTypes(heatingCoil.HCoilType_Num),
1111 0 : heatingCoil.Name,
1112 0 : heatingCoil.ReclaimHeatingCoilName));
1113 : }
1114 0 : state.dataHeatingCoils->ValidSourceType(CoilNum) = true;
1115 : }
1116 : }
1117 0 : if (heatingCoil.ReclaimHeatingSourceIndexNum > 0) {
1118 0 : state.dataHeatingCoils->ValidSourceType(CoilNum) = true;
1119 : }
1120 1 : } else if (Util::SameString(Alphas(5), "Coil:Cooling:DX:VariableSpeed")) {
1121 0 : heatingCoil.ReclaimHeatingSource = HeatObjTypes::COIL_DX_VARIABLE_COOLING;
1122 0 : heatingCoil.ReclaimHeatingSourceIndexNum = VariableSpeedCoils::GetCoilIndexVariableSpeed(state, Alphas(5), Alphas(6), DXCoilErrFlag);
1123 0 : if (heatingCoil.ReclaimHeatingSourceIndexNum > 0) {
1124 0 : if (allocated(state.dataHeatBal->HeatReclaimVS_Coil)) {
1125 : DataHeatBalance::HeatReclaimDataBase &HeatReclaim =
1126 0 : state.dataHeatBal->HeatReclaimVS_Coil(heatingCoil.ReclaimHeatingSourceIndexNum);
1127 0 : if (!allocated(HeatReclaim.HVACDesuperheaterReclaimedHeat)) {
1128 0 : HeatReclaim.HVACDesuperheaterReclaimedHeat.allocate(state.dataHeatingCoils->NumDesuperheaterCoil);
1129 0 : std::fill(HeatReclaim.HVACDesuperheaterReclaimedHeat.begin(), HeatReclaim.HVACDesuperheaterReclaimedHeat.end(), 0.0);
1130 : }
1131 0 : HeatReclaim.ReclaimEfficiencyTotal += heatingCoil.Efficiency;
1132 0 : if (HeatReclaim.ReclaimEfficiencyTotal > 0.3) {
1133 0 : ShowSevereError(
1134 : state,
1135 0 : format("{}, \"{}\" sum of heat reclaim recovery efficiencies from the same source coil: \"{} \" cannot be over 0.3",
1136 : HVAC::cAllCoilTypes(heatingCoil.HCoilType_Num),
1137 0 : heatingCoil.Name,
1138 0 : heatingCoil.ReclaimHeatingCoilName));
1139 : }
1140 0 : state.dataHeatingCoils->ValidSourceType(CoilNum) = true;
1141 : }
1142 : }
1143 1 : } else if (Util::SameString(Alphas(5), "Coil:Cooling:DX:TwoSpeed")) {
1144 0 : heatingCoil.ReclaimHeatingSource = HeatObjTypes::COIL_DX_MULTISPEED;
1145 0 : DXCoils::GetDXCoilIndex(state, Alphas(6), heatingCoil.ReclaimHeatingSourceIndexNum, DXCoilErrFlag, Alphas(5));
1146 0 : if (heatingCoil.ReclaimHeatingSourceIndexNum > 0) {
1147 0 : if (allocated(state.dataHeatBal->HeatReclaimDXCoil)) {
1148 : DataHeatBalance::HeatReclaimDataBase &HeatReclaim =
1149 0 : state.dataHeatBal->HeatReclaimDXCoil(heatingCoil.ReclaimHeatingSourceIndexNum);
1150 0 : if (!allocated(HeatReclaim.HVACDesuperheaterReclaimedHeat)) {
1151 0 : HeatReclaim.HVACDesuperheaterReclaimedHeat.allocate(state.dataHeatingCoils->NumDesuperheaterCoil);
1152 0 : std::fill(HeatReclaim.HVACDesuperheaterReclaimedHeat.begin(), HeatReclaim.HVACDesuperheaterReclaimedHeat.end(), 0.0);
1153 : }
1154 0 : HeatReclaim.ReclaimEfficiencyTotal += heatingCoil.Efficiency;
1155 0 : if (HeatReclaim.ReclaimEfficiencyTotal > 0.3) {
1156 0 : ShowSevereError(
1157 : state,
1158 0 : format("{}, \"{}\" sum of heat reclaim recovery efficiencies from the same source coil: \"{} \" cannot be over 0.3",
1159 : HVAC::cAllCoilTypes(heatingCoil.HCoilType_Num),
1160 0 : heatingCoil.Name,
1161 0 : heatingCoil.ReclaimHeatingCoilName));
1162 : }
1163 0 : state.dataHeatingCoils->ValidSourceType(CoilNum) = true;
1164 : }
1165 : }
1166 1 : } else if (Util::SameString(Alphas(5), "Coil:Cooling:DX:TwoStageWithHumidityControlMode")) {
1167 0 : heatingCoil.ReclaimHeatingSource = HeatObjTypes::COIL_DX_MULTIMODE;
1168 0 : DXCoils::GetDXCoilIndex(state, Alphas(6), heatingCoil.ReclaimHeatingSourceIndexNum, DXCoilErrFlag, Alphas(5));
1169 0 : if (heatingCoil.ReclaimHeatingSourceIndexNum > 0) {
1170 0 : if (allocated(state.dataHeatBal->HeatReclaimDXCoil)) {
1171 : DataHeatBalance::HeatReclaimDataBase &HeatReclaim =
1172 0 : state.dataHeatBal->HeatReclaimDXCoil(heatingCoil.ReclaimHeatingSourceIndexNum);
1173 0 : if (!allocated(HeatReclaim.HVACDesuperheaterReclaimedHeat)) {
1174 0 : HeatReclaim.HVACDesuperheaterReclaimedHeat.allocate(state.dataHeatingCoils->NumDesuperheaterCoil);
1175 0 : std::fill(HeatReclaim.HVACDesuperheaterReclaimedHeat.begin(), HeatReclaim.HVACDesuperheaterReclaimedHeat.end(), 0.0);
1176 : }
1177 0 : HeatReclaim.ReclaimEfficiencyTotal += heatingCoil.Efficiency;
1178 0 : if (HeatReclaim.ReclaimEfficiencyTotal > 0.3) {
1179 0 : ShowSevereError(
1180 : state,
1181 0 : format(R"({}, "{}" sum of heat reclaim recovery efficiencies from the same source coil: "{} " cannot be over 0.3)",
1182 : HVAC::cAllCoilTypes(heatingCoil.HCoilType_Num),
1183 0 : heatingCoil.Name,
1184 0 : heatingCoil.ReclaimHeatingCoilName));
1185 : }
1186 0 : state.dataHeatingCoils->ValidSourceType(CoilNum) = true;
1187 : }
1188 : }
1189 1 : } else if (Util::SameString(Alphas(5), "Coil:Cooling:DX")) {
1190 1 : heatingCoil.ReclaimHeatingSource = HeatObjTypes::COIL_COOLING_DX_NEW;
1191 1 : heatingCoil.ReclaimHeatingSourceIndexNum = CoilCoolingDX::factory(state, Alphas(6));
1192 1 : if (heatingCoil.ReclaimHeatingSourceIndexNum < 0) {
1193 0 : ShowSevereError(
1194 0 : state, format("{}={}, could not find desuperheater coil {}={}", CurrentModuleObject, heatingCoil.Name, Alphas(5), Alphas(6)));
1195 0 : state.dataHeatingCoils->InputErrorsFound = true;
1196 : }
1197 : DataHeatBalance::HeatReclaimDataBase &HeatReclaim =
1198 1 : state.dataCoilCoolingDX->coilCoolingDXs[heatingCoil.ReclaimHeatingSourceIndexNum].reclaimHeat;
1199 1 : if (!allocated(HeatReclaim.HVACDesuperheaterReclaimedHeat)) {
1200 1 : HeatReclaim.HVACDesuperheaterReclaimedHeat.allocate(state.dataHeatingCoils->NumDesuperheaterCoil);
1201 1 : std::fill(HeatReclaim.HVACDesuperheaterReclaimedHeat.begin(), HeatReclaim.HVACDesuperheaterReclaimedHeat.end(), 0.0);
1202 : }
1203 1 : HeatReclaim.ReclaimEfficiencyTotal += heatingCoil.Efficiency;
1204 1 : if (HeatReclaim.ReclaimEfficiencyTotal > 0.3) {
1205 0 : ShowSevereError(
1206 : state,
1207 0 : format("{}, \"{}\" sum of heat reclaim recovery efficiencies from the same source coil: \"{}\" cannot be over 0.3",
1208 : HVAC::cAllCoilTypes(heatingCoil.HCoilType_Num),
1209 0 : heatingCoil.Name,
1210 0 : heatingCoil.ReclaimHeatingCoilName));
1211 : }
1212 1 : state.dataHeatingCoils->ValidSourceType(CoilNum) = true;
1213 : } else {
1214 0 : ShowSevereError(
1215 : state,
1216 0 : format("{}, \"{}\" valid desuperheater heat source object type not found: {}", CurrentModuleObject, heatingCoil.Name, Alphas(5)));
1217 0 : ShowContinueError(state, "Valid desuperheater heat source objects are:");
1218 0 : ShowContinueError(state,
1219 : "Refrigeration:CompressorRack, Coil:Cooling:DX:SingleSpeed, Refrigeration:Condenser:AirCooled, "
1220 : "Refrigeration:Condenser:EvaporativeCooled, Refrigeration:Condenser:WaterCooled,Coil:Cooling:DX:TwoSpeed, and "
1221 : "Coil:Cooling:DX:TwoStageWithHumidityControlMode");
1222 0 : state.dataHeatingCoils->InputErrorsFound = true;
1223 : }
1224 :
1225 3 : heatingCoil.ReclaimHeatingCoilName = Alphas(6);
1226 :
1227 3 : errFlag = false;
1228 3 : heatingCoil.TempSetPointNodeNum = GetOnlySingleNode(state,
1229 3 : Alphas(7),
1230 : errFlag,
1231 : DataLoopNode::ConnectionObjectType::CoilHeatingDesuperheater,
1232 3 : Alphas(1),
1233 : DataLoopNode::NodeFluidType::Air,
1234 : DataLoopNode::ConnectionType::Sensor,
1235 : NodeInputManager::CompFluidStream::Primary,
1236 : DataLoopNode::ObjectIsNotParent);
1237 3 : state.dataHeatingCoils->InputErrorsFound = errFlag || state.dataHeatingCoils->InputErrorsFound;
1238 :
1239 : // parasitic electric load associated with the desuperheater heating coil
1240 3 : heatingCoil.ParasiticElecLoad = Numbers(2);
1241 :
1242 3 : if (Numbers(2) < 0.0) {
1243 0 : ShowSevereError(state, format("{}, \"{}\" parasitic electric load must be >= 0", CurrentModuleObject, heatingCoil.Name));
1244 0 : state.dataHeatingCoils->InputErrorsFound = true;
1245 : }
1246 :
1247 : // Setup Report variables for the Desuperheater Heating Coils
1248 : // CurrentModuleObject = "Coil:Heating:Desuperheater"
1249 6 : SetupOutputVariable(state,
1250 : "Heating Coil Heating Energy",
1251 : Constant::Units::J,
1252 3 : heatingCoil.HeatingCoilLoad,
1253 : OutputProcessor::TimeStepType::System,
1254 : OutputProcessor::StoreType::Sum,
1255 3 : heatingCoil.Name,
1256 : Constant::eResource::EnergyTransfer,
1257 : OutputProcessor::Group::HVAC,
1258 : OutputProcessor::EndUseCat::HeatingCoils);
1259 6 : SetupOutputVariable(state,
1260 : "Heating Coil Heating Rate",
1261 : Constant::Units::W,
1262 3 : heatingCoil.HeatingCoilRate,
1263 : OutputProcessor::TimeStepType::System,
1264 : OutputProcessor::StoreType::Average,
1265 3 : heatingCoil.Name);
1266 6 : SetupOutputVariable(state,
1267 : "Heating Coil Electricity Energy",
1268 : Constant::Units::J,
1269 3 : heatingCoil.ElecUseLoad,
1270 : OutputProcessor::TimeStepType::System,
1271 : OutputProcessor::StoreType::Sum,
1272 3 : heatingCoil.Name,
1273 : Constant::eResource::Electricity,
1274 : OutputProcessor::Group::HVAC,
1275 : OutputProcessor::EndUseCat::Heating);
1276 6 : SetupOutputVariable(state,
1277 : "Heating Coil Electricity Rate",
1278 : Constant::Units::W,
1279 3 : heatingCoil.ElecUseRate,
1280 : OutputProcessor::TimeStepType::System,
1281 : OutputProcessor::StoreType::Average,
1282 3 : heatingCoil.Name);
1283 6 : SetupOutputVariable(state,
1284 : "Heating Coil Runtime Fraction",
1285 : Constant::Units::None,
1286 3 : heatingCoil.RTF,
1287 : OutputProcessor::TimeStepType::System,
1288 : OutputProcessor::StoreType::Average,
1289 3 : heatingCoil.Name);
1290 : }
1291 :
1292 292 : if (state.dataHeatingCoils->InputErrorsFound) {
1293 0 : ShowFatalError(state, format("{}Errors found in input. Program terminates.", RoutineName));
1294 : }
1295 :
1296 292 : Alphas.deallocate();
1297 292 : cAlphaFields.deallocate();
1298 292 : cNumericFields.deallocate();
1299 292 : Numbers.deallocate();
1300 292 : lAlphaBlanks.deallocate();
1301 292 : lNumericBlanks.deallocate();
1302 292 : }
1303 :
1304 122270909 : void InitHeatingCoil(EnergyPlusData &state, int const CoilNum, bool const FirstHVACIteration, Real64 const QCoilRequired)
1305 : {
1306 :
1307 : // SUBROUTINE INFORMATION:
1308 : // AUTHOR Richard J. Liesen
1309 : // DATE WRITTEN May 2000
1310 : // MODIFIED B. Griffith, May 2009 added EMS setpoint check
1311 :
1312 : // PURPOSE OF THIS SUBROUTINE:
1313 : // This subroutine is for initializations of the HeatingCoil Components.
1314 :
1315 : // METHODOLOGY EMPLOYED:
1316 : // Uses the status flags to trigger initializations.
1317 :
1318 122270909 : auto &heatingCoil = state.dataHeatingCoils->HeatingCoil(CoilNum);
1319 :
1320 122270909 : if (state.dataHeatingCoils->MyOneTimeFlag) {
1321 : // initialize the environment and sizing flags
1322 292 : Real64 numHeatingCoils = state.dataHeatingCoils->NumHeatingCoils;
1323 292 : state.dataHeatingCoils->MyEnvrnFlag.allocate(numHeatingCoils);
1324 292 : state.dataHeatingCoils->MySizeFlag.allocate(numHeatingCoils);
1325 292 : state.dataHeatingCoils->ShowSingleWarning.allocate(numHeatingCoils);
1326 292 : state.dataHeatingCoils->MySPTestFlag.allocate(numHeatingCoils);
1327 292 : state.dataHeatingCoils->MyEnvrnFlag = true;
1328 292 : state.dataHeatingCoils->MySizeFlag = true;
1329 292 : state.dataHeatingCoils->ShowSingleWarning = true;
1330 292 : state.dataHeatingCoils->MyOneTimeFlag = false;
1331 292 : state.dataHeatingCoils->MySPTestFlag = true;
1332 : }
1333 :
1334 122270909 : if (!state.dataGlobal->SysSizingCalc && state.dataHeatingCoils->MySizeFlag(CoilNum)) {
1335 : // for each coil, do the sizing once.
1336 1578 : SizeHeatingCoil(state, CoilNum);
1337 :
1338 1578 : state.dataHeatingCoils->MySizeFlag(CoilNum) = false;
1339 : }
1340 :
1341 : // Do the following initializations (every time step): This should be the info from
1342 : // the previous components outlets or the node data in this section.
1343 : // First set the conditions for the air into the coil model
1344 122270909 : int AirOutletNodeNum = heatingCoil.AirOutletNodeNum;
1345 122270909 : int ControlNodeNum = heatingCoil.TempSetPointNodeNum;
1346 122270909 : auto const &airInletNode = state.dataLoopNodes->Node(heatingCoil.AirInletNodeNum);
1347 122270909 : auto const &airOutletNode = state.dataLoopNodes->Node(AirOutletNodeNum);
1348 122270909 : heatingCoil.InletAirMassFlowRate = airInletNode.MassFlowRate;
1349 122270909 : heatingCoil.InletAirTemp = airInletNode.Temp;
1350 122270909 : heatingCoil.InletAirHumRat = airInletNode.HumRat;
1351 122270909 : heatingCoil.InletAirEnthalpy = airInletNode.Enthalpy;
1352 :
1353 : // Set the reporting variables to zero at each timestep.
1354 122270909 : heatingCoil.HeatingCoilLoad = 0.0;
1355 122270909 : heatingCoil.FuelUseLoad = 0.0;
1356 122270909 : heatingCoil.ElecUseLoad = 0.0;
1357 122270909 : heatingCoil.RTF = 0.0;
1358 :
1359 : // If a temperature setpoint controlled coil must set the desired outlet temp everytime
1360 122270909 : if (ControlNodeNum == 0) {
1361 118935302 : heatingCoil.DesiredOutletTemp = 0.0;
1362 : } else {
1363 3335607 : auto const &controlNode = state.dataLoopNodes->Node(ControlNodeNum);
1364 3335607 : heatingCoil.DesiredOutletTemp =
1365 3335607 : controlNode.TempSetPoint - ((ControlNodeNum == AirOutletNodeNum) ? 0 : (controlNode.Temp - airOutletNode.Temp));
1366 : }
1367 :
1368 3980133 : if (QCoilRequired == DataLoopNode::SensedLoadFlagValue && state.dataHeatingCoils->MySPTestFlag(CoilNum) &&
1369 126251042 : heatingCoil.HCoilType_Num != HVAC::Coil_HeatingElectric_MultiStage && heatingCoil.HCoilType_Num != HVAC::Coil_HeatingGas_MultiStage) {
1370 :
1371 : // If the coil is temperature controlled (QCoilReq == -999.0), both a control node and setpoint are required.
1372 1379 : if (!state.dataGlobal->SysSizingCalc && state.dataHVACGlobal->DoSetPointTest) {
1373 : // 3 possibilities here:
1374 : // 1) TempSetPointNodeNum .GT. 0 and TempSetPoint /= SensedNodeFlagValue, this is correct
1375 : // 2) TempSetPointNodeNum .EQ. 0, this is not correct, control node is required
1376 : // 3) TempSetPointNodeNum .GT. 0 and TempSetPoint == SensedNodeFlagValue, this is not correct, missing temperature setpoint
1377 : // test 2) here (fatal message)
1378 283 : if (ControlNodeNum == 0) {
1379 0 : ShowSevereError(state, format("{} \"{}\"", HVAC::cAllCoilTypes(heatingCoil.HCoilType_Num), heatingCoil.Name));
1380 0 : ShowContinueError(state, "... Missing control node for heating coil.");
1381 0 : ShowContinueError(state, "... enter a control node name in the coil temperature setpoint node field for this heating coil.");
1382 0 : ShowContinueError(state, "... use a Setpoint Manager to establish a setpoint at the coil temperature setpoint node.");
1383 0 : state.dataHeatingCoils->HeatingCoilFatalError = true;
1384 : // test 3) here (fatal message)
1385 : } else { // IF(ControlNode .GT. 0)THEN
1386 283 : auto const &controlNode = state.dataLoopNodes->Node(ControlNodeNum);
1387 283 : if (controlNode.TempSetPoint == DataLoopNode::SensedNodeFlagValue) {
1388 0 : if (!state.dataGlobal->AnyEnergyManagementSystemInModel) {
1389 0 : ShowSevereError(state, format("{} \"{}\"", HVAC::cAllCoilTypes(heatingCoil.HCoilType_Num), heatingCoil.Name));
1390 0 : ShowContinueError(state, "... Missing temperature setpoint for heating coil.");
1391 0 : ShowContinueError(state, "... use a Setpoint Manager to establish a setpoint at the coil temperature setpoint node.");
1392 0 : state.dataHeatingCoils->HeatingCoilFatalError = true;
1393 : } else {
1394 0 : EMSManager::CheckIfNodeSetPointManagedByEMS(
1395 0 : state, ControlNodeNum, HVAC::CtrlVarType::Temp, state.dataHeatingCoils->HeatingCoilFatalError);
1396 0 : if (state.dataHeatingCoils->HeatingCoilFatalError) {
1397 0 : ShowSevereError(state, format("{} \"{}\"", HVAC::cAllCoilTypes(heatingCoil.HCoilType_Num), heatingCoil.Name));
1398 0 : ShowContinueError(state, "... Missing temperature setpoint for heating coil.");
1399 0 : ShowContinueError(state, "... use a Setpoint Manager to establish a setpoint at the coil temperature setpoint node.");
1400 0 : ShowContinueError(state, "... or use an EMS Actuator to establish a setpoint at the coil temperature setpoint node.");
1401 : }
1402 : }
1403 : }
1404 : }
1405 283 : state.dataHeatingCoils->MySPTestFlag(CoilNum) = false;
1406 : }
1407 122269530 : } else if (state.dataHeatingCoils->MySPTestFlag(CoilNum)) {
1408 : // If QCoilReq /= SensedLoadFlagValue, the coil is load controlled and does not require a control node
1409 : // 4 possibilities here:
1410 : // 1) TempSetPointNodeNum .EQ. 0 and TempSetPoint == SensedNodeFlagValue, this is correct
1411 : // 2) TempSetPointNodeNum .EQ. 0 and TempSetPoint /= SensedNodeFlagValue, this may be correct,
1412 : // (if no control node specified and SP on heating coil outlet do not show warning, other SP managers may be using SP)
1413 : // 3) TempSetPointNodeNum .GT. 0 and TempSetPoint == SensedNodeFlagValue, control node not required if load based control
1414 : // 4) TempSetPointNodeNum .GT. 0 and TempSetPoint /= SensedNodeFlagValue, control node not required if load based control
1415 : // test 3) and 4) here (warning only)
1416 1295 : if (ControlNodeNum > 0) {
1417 1 : ShowWarningError(state, format("{} \"{}\"", HVAC::cAllCoilTypes(heatingCoil.HCoilType_Num), heatingCoil.Name));
1418 2 : ShowContinueError(state, " The \"Temperature Setpoint Node Name\" input is not required for this heating coil.");
1419 3 : ShowContinueError(state, " Leaving the input field \"Temperature Setpoint Node Name\" blank will eliminate this warning.");
1420 : }
1421 1295 : state.dataHeatingCoils->MySPTestFlag(CoilNum) = false;
1422 : }
1423 :
1424 : // delay fatal error until all coils are called
1425 122270909 : if (!FirstHVACIteration && state.dataHeatingCoils->HeatingCoilFatalError) {
1426 0 : ShowFatalError(state, "... errors found in heating coil input.");
1427 : }
1428 :
1429 : // Find the heating source index for the desuperheater heating coil if not already found. This occurs when zone heating
1430 : // equip. exists. (when zone equipment heating coils are included in the input, the air loop DX equipment has not yet been read)
1431 : // Issue a single warning if the coil is not found and continue the simulation
1432 122270909 : if (!state.dataHeatingCoils->ValidSourceType(CoilNum) && (heatingCoil.HCoilType_Num == HVAC::Coil_HeatingDesuperheater) &&
1433 0 : state.dataHeatingCoils->ShowSingleWarning(CoilNum)) {
1434 0 : ++state.dataHeatingCoils->ValidSourceTypeCounter;
1435 0 : switch (heatingCoil.ReclaimHeatingSource) {
1436 0 : case HeatObjTypes::COMPRESSORRACK_REFRIGERATEDCASE: {
1437 0 : for (int RackNum = 1; RackNum <= state.dataRefrigCase->NumRefrigeratedRacks; ++RackNum) {
1438 0 : if (!Util::SameString(state.dataHeatBal->HeatReclaimRefrigeratedRack(RackNum).Name, heatingCoil.ReclaimHeatingCoilName)) {
1439 0 : continue;
1440 : }
1441 0 : heatingCoil.ReclaimHeatingSourceIndexNum = RackNum;
1442 0 : if (allocated(state.dataHeatBal->HeatReclaimRefrigeratedRack)) {
1443 : DataHeatBalance::HeatReclaimDataBase &HeatReclaim =
1444 0 : state.dataHeatBal->HeatReclaimRefrigeratedRack(heatingCoil.ReclaimHeatingSourceIndexNum);
1445 0 : if (!allocated(HeatReclaim.HVACDesuperheaterReclaimedHeat)) {
1446 0 : HeatReclaim.HVACDesuperheaterReclaimedHeat.allocate(state.dataHeatingCoils->NumDesuperheaterCoil);
1447 0 : std::fill(HeatReclaim.HVACDesuperheaterReclaimedHeat.begin(), HeatReclaim.HVACDesuperheaterReclaimedHeat.end(), 0.0);
1448 0 : HeatReclaim.ReclaimEfficiencyTotal += heatingCoil.Efficiency;
1449 0 : if (HeatReclaim.ReclaimEfficiencyTotal > 0.3) {
1450 0 : ShowSevereError(
1451 : state,
1452 0 : format(R"({}, "{}" sum of heat reclaim recovery efficiencies from the same source coil: "{}" cannot be over 0.3)",
1453 : HVAC::cAllCoilTypes(heatingCoil.HCoilType_Num),
1454 0 : heatingCoil.Name,
1455 0 : heatingCoil.ReclaimHeatingCoilName));
1456 : }
1457 : }
1458 0 : state.dataHeatingCoils->ValidSourceType(CoilNum) = true;
1459 : }
1460 0 : break;
1461 : }
1462 0 : } break;
1463 0 : case HeatObjTypes::CONDENSER_REFRIGERATION: {
1464 0 : for (int CondNum = 1; CondNum <= state.dataRefrigCase->NumRefrigCondensers; ++CondNum) {
1465 0 : if (!Util::SameString(state.dataHeatBal->HeatReclaimRefrigCondenser(CondNum).Name, heatingCoil.ReclaimHeatingCoilName)) {
1466 0 : continue;
1467 : }
1468 0 : heatingCoil.ReclaimHeatingSourceIndexNum = CondNum;
1469 0 : if (allocated(state.dataHeatBal->HeatReclaimRefrigCondenser)) {
1470 : DataHeatBalance::HeatReclaimDataBase &HeatReclaim =
1471 0 : state.dataHeatBal->HeatReclaimRefrigCondenser(heatingCoil.ReclaimHeatingSourceIndexNum);
1472 0 : if (!allocated(HeatReclaim.HVACDesuperheaterReclaimedHeat)) {
1473 0 : HeatReclaim.HVACDesuperheaterReclaimedHeat.allocate(state.dataHeatingCoils->NumDesuperheaterCoil);
1474 0 : std::fill(HeatReclaim.HVACDesuperheaterReclaimedHeat.begin(), HeatReclaim.HVACDesuperheaterReclaimedHeat.end(), 0.0);
1475 0 : HeatReclaim.ReclaimEfficiencyTotal += heatingCoil.Efficiency;
1476 0 : if (HeatReclaim.ReclaimEfficiencyTotal > 0.9) {
1477 0 : ShowSevereError(
1478 : state,
1479 0 : format(R"({}, "{}" sum of heat reclaim recovery efficiencies from the same source coil: "{}" cannot be over 0.9)",
1480 : HVAC::cAllCoilTypes(heatingCoil.HCoilType_Num),
1481 0 : heatingCoil.Name,
1482 0 : heatingCoil.ReclaimHeatingCoilName));
1483 : }
1484 : }
1485 0 : state.dataHeatingCoils->ValidSourceType(CoilNum) = true;
1486 : }
1487 0 : break;
1488 : }
1489 0 : } break;
1490 0 : case HeatObjTypes::COIL_DX_COOLING:
1491 : case HeatObjTypes::COIL_DX_MULTISPEED:
1492 : case HeatObjTypes::COIL_DX_MULTIMODE: {
1493 0 : for (int DXCoilNum = 1; DXCoilNum <= state.dataDXCoils->NumDXCoils; ++DXCoilNum) {
1494 0 : if (!Util::SameString(state.dataHeatBal->HeatReclaimDXCoil(DXCoilNum).Name, heatingCoil.ReclaimHeatingCoilName)) {
1495 0 : continue;
1496 : }
1497 0 : heatingCoil.ReclaimHeatingSourceIndexNum = DXCoilNum;
1498 0 : if (allocated(state.dataHeatBal->HeatReclaimDXCoil)) {
1499 : DataHeatBalance::HeatReclaimDataBase &HeatReclaim =
1500 0 : state.dataHeatBal->HeatReclaimDXCoil(heatingCoil.ReclaimHeatingSourceIndexNum);
1501 0 : if (!allocated(HeatReclaim.HVACDesuperheaterReclaimedHeat)) {
1502 0 : HeatReclaim.HVACDesuperheaterReclaimedHeat.allocate(state.dataHeatingCoils->NumDesuperheaterCoil);
1503 0 : std::fill(HeatReclaim.HVACDesuperheaterReclaimedHeat.begin(), HeatReclaim.HVACDesuperheaterReclaimedHeat.end(), 0.0);
1504 0 : HeatReclaim.ReclaimEfficiencyTotal += heatingCoil.Efficiency;
1505 0 : if (HeatReclaim.ReclaimEfficiencyTotal > 0.3) {
1506 0 : ShowSevereError(
1507 : state,
1508 0 : format(R"({}, "{}" sum of heat reclaim recovery efficiencies from the same source coil: "{}" cannot be over 0.3)",
1509 : HVAC::cAllCoilTypes(heatingCoil.HCoilType_Num),
1510 0 : heatingCoil.Name,
1511 0 : heatingCoil.ReclaimHeatingCoilName));
1512 : }
1513 : }
1514 0 : state.dataHeatingCoils->ValidSourceType(CoilNum) = true;
1515 : }
1516 0 : break;
1517 : }
1518 0 : } break;
1519 0 : case HeatObjTypes::COIL_DX_VARIABLE_COOLING: {
1520 0 : for (int DXCoilNum = 1; DXCoilNum <= state.dataVariableSpeedCoils->NumVarSpeedCoils; ++DXCoilNum) {
1521 0 : if (!Util::SameString(state.dataHeatBal->HeatReclaimVS_Coil(DXCoilNum).Name, heatingCoil.ReclaimHeatingCoilName)) {
1522 0 : continue;
1523 : }
1524 0 : heatingCoil.ReclaimHeatingSourceIndexNum = DXCoilNum;
1525 0 : if (allocated(state.dataHeatBal->HeatReclaimVS_Coil)) {
1526 : DataHeatBalance::HeatReclaimDataBase &HeatReclaim =
1527 0 : state.dataHeatBal->HeatReclaimVS_Coil(heatingCoil.ReclaimHeatingSourceIndexNum);
1528 0 : if (!allocated(HeatReclaim.HVACDesuperheaterReclaimedHeat)) {
1529 0 : HeatReclaim.HVACDesuperheaterReclaimedHeat.allocate(state.dataHeatingCoils->NumDesuperheaterCoil);
1530 0 : std::fill(HeatReclaim.HVACDesuperheaterReclaimedHeat.begin(), HeatReclaim.HVACDesuperheaterReclaimedHeat.end(), 0.0);
1531 0 : HeatReclaim.ReclaimEfficiencyTotal += heatingCoil.Efficiency;
1532 0 : if (HeatReclaim.ReclaimEfficiencyTotal > 0.3) {
1533 0 : ShowSevereError(
1534 : state,
1535 0 : format(R"({}, "{}" sum of heat reclaim recovery efficiencies from the same source coil: "{}" cannot be over 0.3)",
1536 : HVAC::cAllCoilTypes(heatingCoil.HCoilType_Num),
1537 0 : heatingCoil.Name,
1538 0 : heatingCoil.ReclaimHeatingCoilName));
1539 : }
1540 : }
1541 0 : state.dataHeatingCoils->ValidSourceType(CoilNum) = true;
1542 : }
1543 0 : break;
1544 : }
1545 : case HeatObjTypes::COIL_COOLING_DX_NEW:
1546 : DataHeatBalance::HeatReclaimDataBase &HeatReclaim =
1547 0 : state.dataCoilCoolingDX->coilCoolingDXs[heatingCoil.ReclaimHeatingSourceIndexNum].reclaimHeat;
1548 0 : if (!allocated(HeatReclaim.HVACDesuperheaterReclaimedHeat)) {
1549 0 : HeatReclaim.HVACDesuperheaterReclaimedHeat.allocate(state.dataHeatingCoils->NumDesuperheaterCoil);
1550 0 : std::fill(HeatReclaim.HVACDesuperheaterReclaimedHeat.begin(), HeatReclaim.HVACDesuperheaterReclaimedHeat.end(), 0.0);
1551 0 : HeatReclaim.ReclaimEfficiencyTotal += heatingCoil.Efficiency;
1552 0 : if (HeatReclaim.ReclaimEfficiencyTotal > 0.3) {
1553 0 : ShowSevereError(
1554 : state,
1555 0 : format("{}, \"{}\" sum of heat reclaim recovery efficiencies from the same source coil: \"{}\" cannot be over 0.3",
1556 : HVAC::cAllCoilTypes(heatingCoil.HCoilType_Num),
1557 0 : heatingCoil.Name,
1558 0 : heatingCoil.ReclaimHeatingCoilName));
1559 : }
1560 : }
1561 0 : state.dataHeatingCoils->ValidSourceType(CoilNum) = true;
1562 0 : break;
1563 : } break;
1564 0 : default:
1565 0 : break;
1566 : }
1567 0 : if ((state.dataHeatingCoils->ValidSourceTypeCounter > state.dataHeatingCoils->NumDesuperheaterCoil * 2) &&
1568 0 : state.dataHeatingCoils->ShowSingleWarning(CoilNum) && !state.dataHeatingCoils->ValidSourceType(CoilNum)) {
1569 0 : ShowWarningError(state,
1570 0 : format("Coil:Heating:Desuperheater, \"{}\" desuperheater heat source object name not found: {}",
1571 0 : heatingCoil.Name,
1572 0 : heatingCoil.ReclaimHeatingCoilName));
1573 0 : ShowContinueError(state, " Desuperheater heating coil is not modeled and simulation continues.");
1574 0 : state.dataHeatingCoils->ShowSingleWarning(CoilNum) = false;
1575 : }
1576 : }
1577 122270909 : }
1578 :
1579 1578 : void SizeHeatingCoil(EnergyPlusData &state, int const CoilNum)
1580 : {
1581 :
1582 : // SUBROUTINE INFORMATION:
1583 : // AUTHOR Fred Buhl
1584 : // DATE WRITTEN January 2002
1585 : // MODIFIED August 2013 Daeho Kang, add component sizing table entries
1586 : // RE-ENGINEERED Mar 2014 FSEC, moved calculations to common routine in BaseSizer
1587 :
1588 : // PURPOSE OF THIS SUBROUTINE:
1589 : // This subroutine is for sizing Heating Coil Components for which nominal capcities have not been
1590 : // specified in the input.
1591 :
1592 : // METHODOLOGY EMPLOYED:
1593 : // Obtains heating capacities from the zone or system sizing arrays or parent object as necessary.
1594 : // heating coil or other routine sets up any required data variables (e.g., DataCoilIsSuppHeater, TermUnitPIU, etc.),
1595 : // sizing variable (e.g., HeatingCoil( CoilNum ).NominalCapacity in this routine since it can be multi-staged and new routine
1596 : // currently only handles single values) and associated string representing that sizing variable.
1597 : // Sizer functions handles the actual sizing and reporting.
1598 :
1599 : // SUBROUTINE PARAMETER DEFINITIONS:
1600 : static constexpr std::string_view RoutineName("SizeHeatingCoil: "); // include trailing blank space
1601 :
1602 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1603 1578 : std::string CompName; // component name
1604 1578 : std::string CompType; // component type
1605 1578 : std::string SizingString; // input field sizing description (e.g., Nominal Capacity)
1606 1578 : bool bPRINT = true; // TRUE if sizing is reported to output (eio)
1607 : Real64 NominalCapacityDes; // Autosized nominal capacity for reporting
1608 : Real64 NominalCapacityUser; // Hardsized nominal capacity for reporting
1609 : Real64 TempCap; // autosized capacity of heating coil [W]
1610 1578 : int FieldNum = 2; // IDD numeric field number where input field description is found
1611 1578 : int NumCoilsSized = 0; // counter used to deallocate temporary string array after all coils have been sized
1612 :
1613 1578 : auto &heatingCoil = state.dataHeatingCoils->HeatingCoil(CoilNum);
1614 :
1615 1578 : if (heatingCoil.HCoilType_Num == HVAC::Coil_HeatingElectric_MultiStage) {
1616 5 : FieldNum = 1 + (heatingCoil.NumOfStages * 2);
1617 5 : TempCap = heatingCoil.MSNominalCapacity(heatingCoil.NumOfStages);
1618 1573 : } else if (heatingCoil.HCoilType_Num == HVAC::Coil_HeatingGas_MultiStage) {
1619 1 : FieldNum = 1 + (heatingCoil.NumOfStages * 3);
1620 1 : TempCap = heatingCoil.MSNominalCapacity(heatingCoil.NumOfStages);
1621 1572 : } else if (heatingCoil.HCoilType_Num == HVAC::Coil_HeatingDesuperheater) {
1622 3 : return; // no autosizable inputs for desupterheater
1623 : } else {
1624 1569 : FieldNum = 2;
1625 1569 : TempCap = heatingCoil.NominalCapacity;
1626 : }
1627 1575 : SizingString = state.dataHeatingCoils->HeatingCoilNumericFields(CoilNum).FieldNames(FieldNum) + " [W]";
1628 1575 : CompType = "Coil:" + heatingCoil.HeatingCoilType + ':' + heatingCoil.HeatingCoilModel;
1629 1575 : CompName = heatingCoil.Name;
1630 1575 : state.dataSize->DataCoilIsSuppHeater = state.dataHeatingCoils->CoilIsSuppHeater; // set global instead of using optional argument
1631 1575 : state.dataSize->DataCoolCoilCap =
1632 : 0.0; // global only used for heat pump heating coils, non-HP heating coils are sized with other global variables
1633 :
1634 1575 : if (TempCap == DataSizing::AutoSize) {
1635 1302 : if (heatingCoil.DesiccantRegenerationCoil) {
1636 0 : state.dataSize->DataDesicRegCoil = true;
1637 0 : bPRINT = false;
1638 0 : state.dataSize->DataDesicDehumNum = heatingCoil.DesiccantDehumNum;
1639 0 : HeatingCoilDesAirInletTempSizer sizerHeatingDesInletTemp;
1640 0 : bool ErrorsFound = false;
1641 0 : sizerHeatingDesInletTemp.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
1642 0 : state.dataSize->DataDesInletAirTemp = sizerHeatingDesInletTemp.size(state, DataSizing::AutoSize, ErrorsFound);
1643 :
1644 0 : HeatingCoilDesAirOutletTempSizer sizerHeatingDesOutletTemp;
1645 0 : ErrorsFound = false;
1646 0 : sizerHeatingDesOutletTemp.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
1647 0 : state.dataSize->DataDesOutletAirTemp = sizerHeatingDesOutletTemp.size(state, DataSizing::AutoSize, ErrorsFound);
1648 :
1649 0 : if (state.dataSize->CurOASysNum > 0) {
1650 0 : auto &OASysEqSizing(state.dataSize->OASysEqSizing(state.dataSize->CurOASysNum));
1651 0 : OASysEqSizing.AirFlow = true;
1652 0 : OASysEqSizing.AirVolFlow = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).DesOutAirVolFlow;
1653 : }
1654 0 : state.dataSize->DataDesicDehumNum = 0;
1655 0 : bPRINT = true;
1656 0 : }
1657 : }
1658 1575 : bool errorsFound = false;
1659 1575 : HeatingCapacitySizer sizerHeatingCapacity;
1660 1575 : sizerHeatingCapacity.overrideSizingString(SizingString);
1661 1575 : sizerHeatingCapacity.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
1662 1575 : TempCap = sizerHeatingCapacity.size(state, TempCap, errorsFound);
1663 1575 : state.dataSize->DataCoilIsSuppHeater = false; // reset global to false so other heating coils are not affected
1664 1575 : state.dataSize->DataDesicRegCoil = false; // reset global to false so other heating coils are not affected
1665 1575 : state.dataSize->DataDesInletAirTemp = 0.0; // reset global data to zero so other heating coils are not
1666 1575 : state.dataSize->DataDesOutletAirTemp = 0.0; // reset global data to zero so other heating coils are not affected
1667 :
1668 1575 : if (heatingCoil.HCoilType_Num == HVAC::Coil_HeatingElectric_MultiStage || heatingCoil.HCoilType_Num == HVAC::Coil_HeatingGas_MultiStage) {
1669 6 : heatingCoil.MSNominalCapacity(heatingCoil.NumOfStages) = TempCap;
1670 6 : bool IsAutoSize = false;
1671 : int NumOfStages; // total number of stages of multi-stage heating coil
1672 6 : if (any_eq(heatingCoil.MSNominalCapacity, DataSizing::AutoSize)) {
1673 4 : IsAutoSize = true;
1674 : }
1675 6 : if (IsAutoSize) {
1676 4 : NumOfStages = heatingCoil.NumOfStages;
1677 10 : for (int StageNum = NumOfStages - 1; StageNum >= 1; --StageNum) {
1678 6 : bool ThisStageAutoSize = false;
1679 6 : FieldNum = 1 + StageNum * ((heatingCoil.HCoilType_Num == HVAC::Coil_HeatingElectric_MultiStage) ? 2 : 3);
1680 6 : SizingString = state.dataHeatingCoils->HeatingCoilNumericFields(CoilNum).FieldNames(FieldNum) + " [W]";
1681 6 : if (heatingCoil.MSNominalCapacity(StageNum) == DataSizing::AutoSize) {
1682 6 : ThisStageAutoSize = true;
1683 : }
1684 6 : NominalCapacityDes = TempCap * StageNum / NumOfStages;
1685 6 : if (ThisStageAutoSize) {
1686 6 : heatingCoil.MSNominalCapacity(StageNum) = NominalCapacityDes;
1687 6 : BaseSizer::reportSizerOutput(state, CompType, CompName, "Design Size " + SizingString, NominalCapacityDes);
1688 : } else {
1689 0 : if (heatingCoil.MSNominalCapacity(StageNum) > 0.0 && NominalCapacityDes > 0.0) {
1690 0 : NominalCapacityUser = TempCap * StageNum / NumOfStages; // HeatingCoil( CoilNum ).MSNominalCapacity( StageNum );
1691 0 : BaseSizer::reportSizerOutput(state,
1692 : CompType,
1693 : CompName,
1694 0 : "Design Size " + SizingString,
1695 : NominalCapacityDes,
1696 0 : "User-Specified " + SizingString,
1697 : NominalCapacityUser);
1698 0 : if (state.dataGlobal->DisplayExtraWarnings) {
1699 0 : if ((std::abs(NominalCapacityDes - NominalCapacityUser) / NominalCapacityUser) >
1700 0 : state.dataSize->AutoVsHardSizingThreshold) {
1701 0 : ShowMessage(state,
1702 0 : format("SizeHeatingCoil: Potential issue with equipment sizing for {}, {}", CompType, CompName));
1703 0 : ShowContinueError(state, format("User-Specified Nominal Capacity of {:.2R} [W]", NominalCapacityUser));
1704 0 : ShowContinueError(state, format("differs from Design Size Nominal Capacity of {:.2R} [W]", NominalCapacityDes));
1705 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
1706 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
1707 : }
1708 : }
1709 : }
1710 : }
1711 : }
1712 : } else { // No autosize
1713 2 : NumOfStages = heatingCoil.NumOfStages;
1714 2 : for (int StageNum = NumOfStages - 1; StageNum >= 1; --StageNum) {
1715 0 : if (heatingCoil.MSNominalCapacity(StageNum) > 0.0) {
1716 0 : BaseSizer::reportSizerOutput(
1717 0 : state, CompType, CompName, "User-Specified " + SizingString, heatingCoil.MSNominalCapacity(StageNum));
1718 : }
1719 : }
1720 : }
1721 : // Ensure capacity at lower Stage must be lower or equal to the capacity at higher Stage.
1722 12 : for (int StageNum = 1; StageNum <= heatingCoil.NumOfStages - 1; ++StageNum) {
1723 6 : if (heatingCoil.MSNominalCapacity(StageNum) > heatingCoil.MSNominalCapacity(StageNum + 1)) {
1724 0 : ShowSevereError(state,
1725 0 : format("SizeHeatingCoil: {} {}, Stage {} Nominal Capacity ({:.2R} W) must be less than or equal to Stage {} "
1726 : "Nominal Capacity ({:.2R} W).",
1727 0 : heatingCoil.HeatingCoilType,
1728 0 : heatingCoil.Name,
1729 : StageNum,
1730 : heatingCoil.MSNominalCapacity(StageNum),
1731 0 : StageNum + 1,
1732 : heatingCoil.MSNominalCapacity(StageNum + 1)));
1733 0 : ShowFatalError(state, "Preceding conditions cause termination.");
1734 : }
1735 : }
1736 6 : } else { // not a multi-speed coil
1737 1569 : heatingCoil.NominalCapacity = TempCap;
1738 : }
1739 :
1740 1575 : if (++NumCoilsSized == state.dataHeatingCoils->NumHeatingCoils) {
1741 92 : state.dataHeatingCoils->HeatingCoilNumericFields.deallocate(); // remove temporary array for field names at end of sizing
1742 : }
1743 :
1744 : // create predefined report entries
1745 1575 : switch (heatingCoil.HCoilType_Num) {
1746 665 : case HVAC::Coil_HeatingElectric: {
1747 665 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchHeatCoilType, heatingCoil.Name, "Coil:Heating:Electric");
1748 1330 : OutputReportPredefined::PreDefTableEntry(
1749 665 : state, state.dataOutRptPredefined->pdchHeatCoilNomCap, heatingCoil.Name, heatingCoil.NominalCapacity);
1750 665 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchHeatCoilNomEff, heatingCoil.Name, heatingCoil.Efficiency);
1751 665 : } break;
1752 5 : case HVAC::Coil_HeatingElectric_MultiStage: {
1753 10 : OutputReportPredefined::PreDefTableEntry(
1754 5 : state, state.dataOutRptPredefined->pdchHeatCoilType, heatingCoil.Name, "Coil:Heating:Electric:MultiStage");
1755 10 : OutputReportPredefined::PreDefTableEntry(
1756 5 : state, state.dataOutRptPredefined->pdchHeatCoilNomCap, heatingCoil.Name, heatingCoil.MSNominalCapacity(heatingCoil.NumOfStages));
1757 10 : OutputReportPredefined::PreDefTableEntry(
1758 5 : state, state.dataOutRptPredefined->pdchHeatCoilNomEff, heatingCoil.Name, heatingCoil.MSEfficiency(heatingCoil.NumOfStages));
1759 5 : } break;
1760 904 : case HVAC::Coil_HeatingGasOrOtherFuel: {
1761 904 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchHeatCoilType, heatingCoil.Name, "Coil:Heating:Fuel");
1762 1808 : OutputReportPredefined::PreDefTableEntry(
1763 904 : state, state.dataOutRptPredefined->pdchHeatCoilNomCap, heatingCoil.Name, heatingCoil.NominalCapacity);
1764 904 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchHeatCoilNomEff, heatingCoil.Name, heatingCoil.Efficiency);
1765 904 : } break;
1766 1 : case HVAC::Coil_HeatingGas_MultiStage: {
1767 2 : OutputReportPredefined::PreDefTableEntry(
1768 1 : state, state.dataOutRptPredefined->pdchHeatCoilType, heatingCoil.Name, "Coil:Heating:Gas:MultiStage");
1769 2 : OutputReportPredefined::PreDefTableEntry(
1770 1 : state, state.dataOutRptPredefined->pdchHeatCoilNomCap, heatingCoil.Name, heatingCoil.MSNominalCapacity(heatingCoil.NumOfStages));
1771 2 : OutputReportPredefined::PreDefTableEntry(
1772 1 : state, state.dataOutRptPredefined->pdchHeatCoilNomEff, heatingCoil.Name, heatingCoil.MSEfficiency(heatingCoil.NumOfStages));
1773 1 : } break;
1774 0 : case HVAC::Coil_HeatingDesuperheater: {
1775 0 : OutputReportPredefined::PreDefTableEntry(
1776 0 : state, state.dataOutRptPredefined->pdchHeatCoilType, heatingCoil.Name, "Coil:Heating:Desuperheater");
1777 0 : OutputReportPredefined::PreDefTableEntry(
1778 0 : state, state.dataOutRptPredefined->pdchHeatCoilNomCap, heatingCoil.Name, heatingCoil.NominalCapacity);
1779 0 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchHeatCoilNomEff, heatingCoil.Name, heatingCoil.Efficiency);
1780 0 : } break;
1781 0 : default:
1782 0 : break;
1783 : }
1784 :
1785 : // std 229 heating coils existing table adding new variables:
1786 : // pdchHeatCoilUsedAsSupHeat is now reported at coil selection report
1787 : // pdchHeatCoilAirloopName is now reported at coil selection report
1788 : // std 229 Coil Connections New table: now all reported at coil selection report
1789 1584 : }
1790 :
1791 34314023 : void CalcElectricHeatingCoil(EnergyPlusData &state,
1792 : int const CoilNum, // index to heating coil
1793 : Real64 &QCoilReq,
1794 : Real64 &QCoilActual, // coil load actually delivered (W)
1795 : HVAC::FanOp const fanOp, // fan operating mode
1796 : Real64 const PartLoadRatio // part-load ratio of heating coil
1797 : )
1798 : {
1799 : // SUBROUTINE INFORMATION:
1800 : // AUTHOR Rich Liesen
1801 : // DATE WRITTEN May 2000
1802 : // MODIFIED Jul. 2016, R. Zhang, Applied the coil supply air temperature sensor offset
1803 :
1804 : // PURPOSE OF THIS SUBROUTINE:
1805 : // Simulates a simple Electric heating coil with an efficiency
1806 :
1807 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1808 : Real64 AirMassFlow; // [kg/sec]
1809 : Real64 TempAirOut; // [C]
1810 : Real64 HeatingCoilLoad;
1811 : Real64 QCoilCap;
1812 :
1813 34314023 : auto &heatingCoil = state.dataHeatingCoils->HeatingCoil(CoilNum);
1814 :
1815 34314023 : Real64 Effic = heatingCoil.Efficiency;
1816 34314023 : Real64 TempAirIn = heatingCoil.InletAirTemp;
1817 34314023 : Real64 Win = heatingCoil.InletAirHumRat;
1818 34314023 : Real64 TempSetPoint = heatingCoil.DesiredOutletTemp;
1819 :
1820 : // If there is a fault of coil SAT Sensor
1821 34314023 : if (heatingCoil.FaultyCoilSATFlag && (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing) &&
1822 0 : (!state.dataGlobal->KickOffSimulation)) {
1823 : // calculate the sensor offset using fault information
1824 0 : int FaultIndex = heatingCoil.FaultyCoilSATIndex;
1825 0 : heatingCoil.FaultyCoilSATOffset = state.dataFaultsMgr->FaultsCoilSATSensor(FaultIndex).CalFaultOffsetAct(state);
1826 : // update the TempSetPoint
1827 0 : TempSetPoint -= heatingCoil.FaultyCoilSATOffset;
1828 : }
1829 :
1830 : // adjust mass flow rates for cycling fan cycling coil operation
1831 34314023 : if (fanOp == HVAC::FanOp::Cycling) {
1832 17969507 : if (PartLoadRatio > 0.0) {
1833 11353254 : AirMassFlow = heatingCoil.InletAirMassFlowRate / PartLoadRatio;
1834 11353254 : QCoilReq /= PartLoadRatio;
1835 : } else {
1836 6616253 : AirMassFlow = 0.0;
1837 : }
1838 : } else {
1839 16344516 : AirMassFlow = heatingCoil.InletAirMassFlowRate;
1840 : }
1841 :
1842 34314023 : Real64 CapacitanceAir = Psychrometrics::PsyCpAirFnW(Win) * AirMassFlow;
1843 :
1844 : // If the coil is operating there should be some heating capacitance
1845 : // across the coil, so do the simulation. If not set outlet to inlet and no load.
1846 : // Also the coil has to be scheduled to be available.
1847 :
1848 : // Control output to meet load QCoilReq (QCoilReq is passed in if load controlled, otherwise QCoilReq=-999)
1849 34314023 : if ((AirMassFlow > 0.0 && heatingCoil.NominalCapacity > 0.0) && (heatingCoil.availSched->getCurrentVal() > 0.0) && (QCoilReq > 0.0)) {
1850 :
1851 : // check to see if the Required heating capacity is greater than the user specified capacity.
1852 5076564 : if (QCoilReq > heatingCoil.NominalCapacity) {
1853 272609 : QCoilCap = heatingCoil.NominalCapacity;
1854 : } else {
1855 4803955 : QCoilCap = QCoilReq;
1856 : }
1857 :
1858 5076564 : TempAirOut = TempAirIn + QCoilCap / CapacitanceAir;
1859 5076564 : HeatingCoilLoad = QCoilCap;
1860 :
1861 : // The HeatingCoilLoad is the change in the enthalpy of the Heating
1862 5076564 : heatingCoil.ElecUseLoad = HeatingCoilLoad / Effic;
1863 :
1864 : // Control coil output to meet a setpoint temperature.
1865 19112348 : } else if ((AirMassFlow > 0.0 && heatingCoil.NominalCapacity > 0.0) && (heatingCoil.availSched->getCurrentVal() > 0.0) &&
1866 48349807 : (QCoilReq == DataLoopNode::SensedLoadFlagValue) && (std::abs(TempSetPoint - TempAirIn) > HVAC::TempControlTol)) {
1867 :
1868 294290 : QCoilCap = CapacitanceAir * (TempSetPoint - TempAirIn);
1869 : // check to see if setpoint above enetering temperature. If not, set
1870 : // output to zero.
1871 294290 : if (QCoilCap <= 0.0) {
1872 33926 : QCoilCap = 0.0;
1873 33926 : TempAirOut = TempAirIn;
1874 : // check to see if the Required heating capacity is greater than the user
1875 : // specified capacity.
1876 260364 : } else if (QCoilCap > heatingCoil.NominalCapacity) {
1877 70000 : QCoilCap = heatingCoil.NominalCapacity;
1878 70000 : TempAirOut = TempAirIn + QCoilCap / CapacitanceAir;
1879 : } else {
1880 190364 : TempAirOut = TempSetPoint;
1881 : }
1882 :
1883 294290 : HeatingCoilLoad = QCoilCap;
1884 :
1885 : // The HeatingCoilLoad is the change in the enthalpy of the Heating
1886 294290 : heatingCoil.ElecUseLoad = HeatingCoilLoad / Effic;
1887 :
1888 : } else { // If not running Conditions do not change across coil from inlet to outlet
1889 :
1890 28943169 : TempAirOut = TempAirIn;
1891 28943169 : HeatingCoilLoad = 0.0;
1892 28943169 : heatingCoil.ElecUseLoad = 0.0;
1893 : }
1894 :
1895 34314023 : if (fanOp == HVAC::FanOp::Cycling) {
1896 17969507 : heatingCoil.ElecUseLoad *= PartLoadRatio;
1897 17969507 : HeatingCoilLoad *= PartLoadRatio;
1898 : }
1899 :
1900 34314023 : heatingCoil.HeatingCoilLoad = HeatingCoilLoad;
1901 :
1902 : // Set the outlet conditions
1903 34314023 : heatingCoil.OutletAirTemp = TempAirOut;
1904 :
1905 : // This HeatingCoil does not change the moisture or Mass Flow across the component
1906 34314023 : heatingCoil.OutletAirHumRat = heatingCoil.InletAirHumRat;
1907 34314023 : heatingCoil.OutletAirMassFlowRate = heatingCoil.InletAirMassFlowRate;
1908 : // Set the outlet enthalpys for air and Heating
1909 34314023 : heatingCoil.OutletAirEnthalpy = Psychrometrics::PsyHFnTdbW(heatingCoil.OutletAirTemp, heatingCoil.OutletAirHumRat);
1910 :
1911 34314023 : QCoilActual = HeatingCoilLoad;
1912 34314023 : if (std::abs(heatingCoil.NominalCapacity) < 1.e-8) {
1913 96033 : if (heatingCoil.AirLoopNum > 0) {
1914 0 : state.dataAirLoop->AirLoopAFNInfo(heatingCoil.AirLoopNum).AFNLoopHeatingCoilMaxRTF =
1915 0 : max(state.dataAirLoop->AirLoopAFNInfo(heatingCoil.AirLoopNum).AFNLoopHeatingCoilMaxRTF, 0.0);
1916 : }
1917 : } else {
1918 34217990 : if (heatingCoil.AirLoopNum > 0) {
1919 681678 : state.dataAirLoop->AirLoopAFNInfo(heatingCoil.AirLoopNum).AFNLoopHeatingCoilMaxRTF =
1920 681678 : max(state.dataAirLoop->AirLoopAFNInfo(heatingCoil.AirLoopNum).AFNLoopHeatingCoilMaxRTF,
1921 681678 : HeatingCoilLoad / heatingCoil.NominalCapacity);
1922 : }
1923 : }
1924 :
1925 : // set outlet node temp so parent objects can call calc directly without have to simulate entire model
1926 34314023 : state.dataLoopNodes->Node(heatingCoil.AirOutletNodeNum).Temp = heatingCoil.OutletAirTemp;
1927 34314023 : }
1928 :
1929 1083499 : void CalcMultiStageElectricHeatingCoil(EnergyPlusData &state,
1930 : int const CoilNum, // the number of the electric heating coil to be simulated
1931 : Real64 const SpeedRatio, // SpeedRatio varies between 1.0 (maximum speed) and 0.0 (minimum speed)
1932 : Real64 const CycRatio, // cycling part load ratio
1933 : int const StageNum, // Stage number
1934 : HVAC::FanOp const fanOp, // Fan operation mode
1935 : Real64 &QCoilActual, // coil load actually delivered (W)
1936 : bool const SuppHeat)
1937 : {
1938 :
1939 : // SUBROUTINE INFORMATION:
1940 : // AUTHOR Chandan Sharma, FSEC
1941 : // DATE WRITTEN January 2013
1942 :
1943 : // PURPOSE OF THIS SUBROUTINE:
1944 : // Calculates the air-side performance and electrical energy use of multistage electric heating coil.
1945 :
1946 : // METHODOLOGY EMPLOYED:
1947 : // Uses the same methodology as the single stage electric heating unit model (SUBROUTINE CalcelectricHeatingCoil).
1948 : // In addition it assumes that the unit performance is obtained by interpolating between
1949 : // the performance at high stage and that at low stage. If the output needed is below
1950 : // that produced at low stage, the coil cycles between off and low stage.
1951 :
1952 : // SUBROUTINE PARAMETER DEFINITIONS:
1953 : static constexpr std::string_view RoutineName = "CalcMultiStageElectricHeatingCoil";
1954 : static constexpr std::string_view RoutineNameAverageLoad = "CalcMultiStageElectricHeatingCoil:Averageload";
1955 : static constexpr std::string_view RoutineNameFullLoad = "CalcMultiStageElectricHeatingCoil:fullload";
1956 :
1957 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1958 : Real64 OutletAirEnthalpy; // outlet air enthalpy [J/kg]
1959 : Real64 OutletAirHumRat; // outlet air humidity ratio [kg/kg]
1960 : Real64 TotCapHS; // total capacity at high stage [W]
1961 : Real64 TotCapLS; // total capacity at low stage [W]
1962 : Real64 TotCap; // total capacity at current stage [W]
1963 : Real64 EffHS; // total capacity at high stage [W]
1964 : Real64 EffLS; // total capacity at low stage [W]
1965 : int StageNumHS; // High stage number
1966 : int StageNumLS; // Low stage number
1967 : Real64 FullLoadOutAirEnth; // Outlet full load enthalpy
1968 : Real64 FullLoadOutAirHumRat; // Outlet humidity ratio at full load
1969 : Real64 FullLoadOutAirTemp; // Outlet temperature at full load
1970 : Real64 FullLoadOutAirRH; // Outler relative humidity at full load
1971 : Real64 OutletAirTemp; // Supply ari temperature
1972 : Real64 LSElecHeatingPower; // Full load power at low stage
1973 : Real64 HSElecHeatingPower; // Full load power at high stage
1974 : Real64 PartLoadRat; // part load ratio
1975 :
1976 1083499 : auto &heatingCoil = state.dataHeatingCoils->HeatingCoil(CoilNum);
1977 1083499 : if (StageNum > 1) {
1978 209263 : StageNumLS = StageNum - 1;
1979 209263 : StageNumHS = StageNum;
1980 209263 : if (StageNum > heatingCoil.NumOfStages) {
1981 61842 : StageNumLS = heatingCoil.NumOfStages - 1;
1982 61842 : StageNumHS = heatingCoil.NumOfStages;
1983 : }
1984 : } else {
1985 874236 : StageNumLS = 1;
1986 874236 : StageNumHS = 1;
1987 : }
1988 :
1989 1083499 : Real64 AirMassFlow = heatingCoil.InletAirMassFlowRate;
1990 1083499 : Real64 InletAirDryBulbTemp = heatingCoil.InletAirTemp;
1991 1083499 : Real64 InletAirEnthalpy = heatingCoil.InletAirEnthalpy;
1992 1083499 : Real64 InletAirHumRat = heatingCoil.InletAirHumRat;
1993 :
1994 1083499 : Real64 OutdoorPressure = state.dataEnvrn->OutBaroPress;
1995 :
1996 1083499 : if ((AirMassFlow > 0.0) && (heatingCoil.availSched->getCurrentVal() > 0.0) && ((CycRatio > 0.0) || (SpeedRatio > 0.0))) {
1997 :
1998 281141 : if (StageNum > 1) {
1999 :
2000 147421 : TotCapLS = heatingCoil.MSNominalCapacity(StageNumLS);
2001 147421 : TotCapHS = heatingCoil.MSNominalCapacity(StageNumHS);
2002 :
2003 147421 : EffLS = heatingCoil.MSEfficiency(StageNumLS);
2004 147421 : EffHS = heatingCoil.MSEfficiency(StageNumHS);
2005 :
2006 : // Get full load output and power
2007 147421 : LSElecHeatingPower = TotCapLS / EffLS;
2008 147421 : HSElecHeatingPower = TotCapHS / EffHS;
2009 147421 : OutletAirHumRat = InletAirHumRat;
2010 :
2011 : // if cycling fan, send coil part-load fraction to on/off fan via HVACDataGlobals
2012 : // IF (FanOpMode .EQ. FanOp::Cycling) OnOffFanPartLoadFraction = 1.0d0
2013 :
2014 : // Power calculation
2015 147421 : heatingCoil.ElecUseLoad = SpeedRatio * HSElecHeatingPower + (1.0 - SpeedRatio) * LSElecHeatingPower;
2016 :
2017 147421 : heatingCoil.HeatingCoilLoad = TotCapHS * SpeedRatio + TotCapLS * (1.0 - SpeedRatio);
2018 :
2019 147421 : OutletAirEnthalpy = InletAirEnthalpy + heatingCoil.HeatingCoilLoad / heatingCoil.InletAirMassFlowRate;
2020 147421 : OutletAirTemp = Psychrometrics::PsyTdbFnHW(OutletAirEnthalpy, OutletAirHumRat);
2021 147421 : FullLoadOutAirRH = Psychrometrics::PsyRhFnTdbWPb(state, OutletAirTemp, OutletAirHumRat, OutdoorPressure, RoutineNameAverageLoad);
2022 :
2023 147421 : if (FullLoadOutAirRH > 1.0) { // Limit to saturated conditions at FullLoadOutAirEnth
2024 0 : OutletAirTemp = Psychrometrics::PsyTsatFnHPb(state, OutletAirEnthalpy, OutdoorPressure, RoutineName);
2025 0 : OutletAirHumRat = Psychrometrics::PsyWFnTdbH(state, OutletAirTemp, OutletAirEnthalpy, RoutineName);
2026 : }
2027 :
2028 147421 : heatingCoil.OutletAirTemp = OutletAirTemp;
2029 147421 : heatingCoil.OutletAirHumRat = OutletAirHumRat;
2030 147421 : heatingCoil.OutletAirEnthalpy = OutletAirEnthalpy;
2031 147421 : heatingCoil.OutletAirMassFlowRate = heatingCoil.InletAirMassFlowRate;
2032 :
2033 : // Stage 1
2034 133720 : } else if (CycRatio > 0.0) {
2035 :
2036 106216 : PartLoadRat = min(1.0, CycRatio);
2037 :
2038 : // for cycling fan, reset mass flow to full on rate
2039 106216 : if (fanOp == HVAC::FanOp::Cycling) {
2040 37168 : AirMassFlow /= PartLoadRat;
2041 69048 : } else if (fanOp == HVAC::FanOp::Continuous) {
2042 69048 : if (!SuppHeat) {
2043 66803 : AirMassFlow = state.dataHVACGlobal->MSHPMassFlowRateLow;
2044 : }
2045 : }
2046 :
2047 106216 : TotCap = heatingCoil.MSNominalCapacity(StageNumLS);
2048 :
2049 : // Calculate full load outlet conditions
2050 106216 : FullLoadOutAirEnth = InletAirEnthalpy + TotCap / AirMassFlow;
2051 106216 : FullLoadOutAirHumRat = InletAirHumRat;
2052 106216 : FullLoadOutAirTemp = Psychrometrics::PsyTdbFnHW(FullLoadOutAirEnth, FullLoadOutAirHumRat);
2053 : FullLoadOutAirRH =
2054 106216 : Psychrometrics::PsyRhFnTdbWPb(state, FullLoadOutAirTemp, FullLoadOutAirHumRat, OutdoorPressure, RoutineNameFullLoad);
2055 :
2056 106216 : if (FullLoadOutAirRH > 1.0) { // Limit to saturated conditions at FullLoadOutAirEnth
2057 0 : FullLoadOutAirTemp = Psychrometrics::PsyTsatFnHPb(state, FullLoadOutAirEnth, OutdoorPressure, RoutineName);
2058 : // Eventually inlet air conditions will be used in electric Coil, these lines are commented out and marked with this comment
2059 : // line FullLoadOutAirTemp = PsyTsatFnHPb(FullLoadOutAirEnth,InletAirPressure)
2060 0 : FullLoadOutAirHumRat = Psychrometrics::PsyWFnTdbH(state, FullLoadOutAirTemp, FullLoadOutAirEnth, RoutineName);
2061 : }
2062 :
2063 : // Set outlet conditions from the full load calculation
2064 106216 : if (fanOp == HVAC::FanOp::Cycling) {
2065 37168 : OutletAirEnthalpy = FullLoadOutAirEnth;
2066 37168 : OutletAirHumRat = FullLoadOutAirHumRat;
2067 37168 : OutletAirTemp = FullLoadOutAirTemp;
2068 : } else {
2069 69048 : OutletAirEnthalpy = PartLoadRat * FullLoadOutAirEnth + (1.0 - PartLoadRat) * InletAirEnthalpy;
2070 69048 : OutletAirHumRat = PartLoadRat * FullLoadOutAirHumRat + (1.0 - PartLoadRat) * InletAirHumRat;
2071 69048 : OutletAirTemp = PartLoadRat * FullLoadOutAirTemp + (1.0 - PartLoadRat) * InletAirDryBulbTemp;
2072 : }
2073 :
2074 106216 : EffLS = heatingCoil.MSEfficiency(StageNumLS);
2075 :
2076 : // HeatingCoil(CoilNum)%HeatingCoilLoad = TotCap
2077 : // This would require a CR to change
2078 106216 : heatingCoil.HeatingCoilLoad = TotCap * PartLoadRat;
2079 :
2080 106216 : heatingCoil.ElecUseLoad = heatingCoil.HeatingCoilLoad / EffLS;
2081 :
2082 106216 : heatingCoil.OutletAirTemp = OutletAirTemp;
2083 106216 : heatingCoil.OutletAirHumRat = OutletAirHumRat;
2084 106216 : heatingCoil.OutletAirEnthalpy = OutletAirEnthalpy;
2085 106216 : heatingCoil.OutletAirMassFlowRate = heatingCoil.InletAirMassFlowRate;
2086 : // this would require a CR to correct (i.e., calculate outputs when coil is off)
2087 : // ELSE
2088 : // ! electric coil is off; just pass through conditions
2089 : // HeatingCoil(CoilNum)%OutletAirEnthalpy = HeatingCoil(CoilNum)%InletAirEnthalpy
2090 : // HeatingCoil(CoilNum)%OutletAirHumRat = HeatingCoil(CoilNum)%InletAirHumRat
2091 : // HeatingCoil(CoilNum)%OutletAirTemp = HeatingCoil(CoilNum)%InletAirTemp
2092 : // HeatingCoil(CoilNum)%OutletAirMassFlowRate = HeatingCoil(CoilNum)%InletAirMassFlowRate
2093 : // HeatingCoil(CoilNum)%ElecUseLoad = 0.0
2094 : // HeatingCoil(CoilNum)%HeatingCoilLoad = 0.0
2095 : // ElecHeatingCoilPower = 0.0
2096 : }
2097 :
2098 : } else {
2099 :
2100 : // electric coil is off; just pass through conditions
2101 802358 : heatingCoil.OutletAirEnthalpy = heatingCoil.InletAirEnthalpy;
2102 802358 : heatingCoil.OutletAirHumRat = heatingCoil.InletAirHumRat;
2103 802358 : heatingCoil.OutletAirTemp = heatingCoil.InletAirTemp;
2104 802358 : heatingCoil.OutletAirMassFlowRate = heatingCoil.InletAirMassFlowRate;
2105 :
2106 : // some of these are reset in Init, can be removed to speed up code
2107 802358 : heatingCoil.ElecUseLoad = 0.0;
2108 802358 : heatingCoil.HeatingCoilLoad = 0.0;
2109 :
2110 : } // end of on/off if - else
2111 :
2112 : // set outlet node temp so parent objects can call calc directly without have to simulate entire model
2113 1083499 : state.dataLoopNodes->Node(heatingCoil.AirOutletNodeNum).Temp = heatingCoil.OutletAirTemp;
2114 :
2115 1083499 : QCoilActual = heatingCoil.HeatingCoilLoad;
2116 1083499 : }
2117 :
2118 86405587 : void CalcFuelHeatingCoil(EnergyPlusData &state,
2119 : int const CoilNum, // index to heating coil
2120 : Real64 const QCoilReq,
2121 : Real64 &QCoilActual, // coil load actually delivered (W)
2122 : HVAC::FanOp const fanOp, // fan operating mode
2123 : [[maybe_unused]] Real64 const PartLoadRatio // part-load ratio of heating coil
2124 : )
2125 : {
2126 : // SUBROUTINE INFORMATION:
2127 : // AUTHOR Rich Liesen
2128 : // DATE WRITTEN May 2000
2129 : // MODIFIED Jul. 2016, R. Zhang, Applied the coil supply air temperature sensor offset
2130 :
2131 : // PURPOSE OF THIS SUBROUTINE:
2132 : // Simulates a simple Gas heating coil with a burner efficiency
2133 :
2134 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
2135 : Real64 TempAirOut; // [C]
2136 : Real64 HeatingCoilLoad;
2137 : Real64 QCoilCap;
2138 : Real64 PartLoadRat;
2139 : Real64 PLF;
2140 :
2141 86405587 : auto &heatingCoil = state.dataHeatingCoils->HeatingCoil(CoilNum);
2142 :
2143 86405587 : Real64 Effic = heatingCoil.Efficiency;
2144 86405587 : Real64 TempAirIn = heatingCoil.InletAirTemp;
2145 86405587 : Real64 Win = heatingCoil.InletAirHumRat;
2146 86405587 : Real64 TempSetPoint = heatingCoil.DesiredOutletTemp;
2147 86405587 : Real64 AirMassFlow = heatingCoil.InletAirMassFlowRate;
2148 :
2149 86405587 : Real64 CapacitanceAir = Psychrometrics::PsyCpAirFnW(Win) * AirMassFlow;
2150 :
2151 : // If there is a fault of coil SAT Sensor
2152 86405587 : if (heatingCoil.FaultyCoilSATFlag && (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing) &&
2153 0 : (!state.dataGlobal->KickOffSimulation)) {
2154 : // calculate the sensor offset using fault information
2155 0 : int FaultIndex = heatingCoil.FaultyCoilSATIndex;
2156 0 : heatingCoil.FaultyCoilSATOffset = state.dataFaultsMgr->FaultsCoilSATSensor(FaultIndex).CalFaultOffsetAct(state);
2157 : // update the TempSetPoint
2158 0 : TempSetPoint -= heatingCoil.FaultyCoilSATOffset;
2159 : }
2160 :
2161 : // If the coil is operating there should be some heating capacitance
2162 : // across the coil, so do the simulation. If not set outlet to inlet and no load.
2163 : // Also the coil has to be scheduled to be available.
2164 :
2165 : // Control output to meet load QCoilReq (QCoilReq is passed in if load controlled, otherwise QCoilReq=-999)
2166 86405587 : if ((AirMassFlow > 0.0 && heatingCoil.NominalCapacity > 0.0) && (heatingCoil.availSched->getCurrentVal() > 0.0) && (QCoilReq > 0.0)) {
2167 :
2168 : // check to see if the Required heating capacity is greater than the user specified capacity.
2169 8431337 : if (QCoilReq > heatingCoil.NominalCapacity) {
2170 109612 : QCoilCap = heatingCoil.NominalCapacity;
2171 : } else {
2172 8321725 : QCoilCap = QCoilReq;
2173 : }
2174 :
2175 8431337 : TempAirOut = TempAirIn + QCoilCap / CapacitanceAir;
2176 8431337 : HeatingCoilLoad = QCoilCap;
2177 :
2178 8431337 : PartLoadRat = HeatingCoilLoad / heatingCoil.NominalCapacity;
2179 :
2180 : // The HeatingCoilLoad is the change in the enthalpy of the Heating
2181 8431337 : heatingCoil.FuelUseLoad = HeatingCoilLoad / Effic;
2182 8431337 : heatingCoil.ElecUseLoad = heatingCoil.ParasiticElecLoad * PartLoadRat;
2183 8431337 : heatingCoil.ParasiticFuelRate = heatingCoil.ParasiticFuelCapacity * (1.0 - PartLoadRat);
2184 :
2185 : // Control coil output to meet a setpoint temperature.
2186 69589454 : } else if ((AirMassFlow > 0.0 && heatingCoil.NominalCapacity > 0.0) && (heatingCoil.availSched->getCurrentVal() > 0.0) &&
2187 147563704 : (QCoilReq == DataLoopNode::SensedLoadFlagValue) && (std::abs(TempSetPoint - TempAirIn) > HVAC::TempControlTol)) {
2188 :
2189 1062571 : QCoilCap = CapacitanceAir * (TempSetPoint - TempAirIn);
2190 : // check to see if setpoint above entering temperature. If not, set
2191 : // output to zero.
2192 1062571 : if (QCoilCap <= 0.0) {
2193 201498 : QCoilCap = 0.0;
2194 201498 : TempAirOut = TempAirIn;
2195 : // check to see if the Required heating capacity is greater than the user
2196 : // specified capacity.
2197 861073 : } else if (QCoilCap > heatingCoil.NominalCapacity) {
2198 198008 : QCoilCap = heatingCoil.NominalCapacity;
2199 198008 : TempAirOut = TempAirIn + QCoilCap / CapacitanceAir;
2200 : } else {
2201 663065 : TempAirOut = TempSetPoint;
2202 : }
2203 :
2204 1062571 : HeatingCoilLoad = QCoilCap;
2205 :
2206 1062571 : PartLoadRat = HeatingCoilLoad / heatingCoil.NominalCapacity;
2207 :
2208 : // The HeatingCoilLoad is the change in the enthalpy of the Heating
2209 1062571 : heatingCoil.FuelUseLoad = HeatingCoilLoad / Effic;
2210 1062571 : heatingCoil.ElecUseLoad = heatingCoil.ParasiticElecLoad * PartLoadRat;
2211 1062571 : heatingCoil.ParasiticFuelRate = heatingCoil.ParasiticFuelCapacity * (1.0 - PartLoadRat);
2212 :
2213 : } else { // If not running Conditions do not change across coil from inlet to outlet
2214 :
2215 76911679 : TempAirOut = TempAirIn;
2216 76911679 : HeatingCoilLoad = 0.0;
2217 76911679 : PartLoadRat = 0.0;
2218 76911679 : heatingCoil.FuelUseLoad = 0.0;
2219 76911679 : heatingCoil.ElecUseLoad = 0.0;
2220 76911679 : heatingCoil.ParasiticFuelRate = heatingCoil.ParasiticFuelCapacity;
2221 : }
2222 :
2223 86405587 : heatingCoil.RTF = PartLoadRat;
2224 :
2225 : // If the PLF curve is defined the gas usage needs to be modified
2226 86405587 : if (heatingCoil.PLFCurveIndex > 0) {
2227 8976130 : if (PartLoadRat == 0) {
2228 6205796 : heatingCoil.FuelUseLoad = 0.0;
2229 : } else {
2230 2770334 : PLF = Curve::CurveValue(state, heatingCoil.PLFCurveIndex, PartLoadRat);
2231 2770334 : if (PLF < 0.7) {
2232 0 : if (heatingCoil.PLFErrorCount < 1) {
2233 0 : ++heatingCoil.PLFErrorCount;
2234 0 : ShowWarningError(state,
2235 0 : format("CalcFuelHeatingCoil: {}=\"{}\", PLF curve values",
2236 : HVAC::cAllCoilTypes(heatingCoil.HCoilType_Num),
2237 0 : heatingCoil.Name));
2238 0 : ShowContinueError(state, format("The PLF curve value = {:.5T} for part-load ratio = {:.5T}", PLF, PartLoadRat));
2239 0 : ShowContinueError(state, "PLF curve values must be >= 0.7. PLF has been reset to 0.7 and the simulation continues...");
2240 0 : ShowContinueError(state, "Check the IO reference manual for PLF curve guidance [Coil:Heating:Fuel].");
2241 : } else {
2242 0 : ShowRecurringWarningErrorAtEnd(
2243 0 : state, heatingCoil.Name + ", Heating coil PLF curve < 0.7 warning continues... ", heatingCoil.PLFErrorIndex, PLF, PLF);
2244 : }
2245 0 : PLF = 0.7;
2246 : }
2247 : // Modify the Gas Coil Consumption and parasitic loads based on PLF curve
2248 2770334 : heatingCoil.RTF = PartLoadRat / PLF;
2249 2770334 : if (heatingCoil.RTF > 1.0 && std::abs(heatingCoil.RTF - 1.0) > 0.001) {
2250 0 : if (heatingCoil.RTFErrorCount < 1) {
2251 0 : ++heatingCoil.RTFErrorCount;
2252 0 : ShowWarningError(state,
2253 0 : format("CalcFuelHeatingCoil: {}=\"{}\", runtime fraction",
2254 : HVAC::cAllCoilTypes(heatingCoil.HCoilType_Num),
2255 0 : heatingCoil.Name));
2256 0 : ShowContinueError(state, format("The runtime fraction exceeded 1.0. [{:.4T}].", heatingCoil.RTF));
2257 0 : ShowContinueError(state, "Runtime fraction is set to 1.0 and the simulation continues...");
2258 0 : ShowContinueError(state, "Check the IO reference manual for PLF curve guidance [Coil:Heating:Fuel].");
2259 : } else {
2260 0 : ShowRecurringWarningErrorAtEnd(state,
2261 0 : format("{}, Heating coil runtime fraction > 1.0 warning continues... ", heatingCoil.Name),
2262 0 : heatingCoil.RTFErrorIndex,
2263 0 : heatingCoil.RTF,
2264 0 : heatingCoil.RTF);
2265 : }
2266 0 : heatingCoil.RTF = 1.0; // Reset coil runtime fraction to 1.0
2267 2770334 : } else if (heatingCoil.RTF > 1.0) {
2268 0 : heatingCoil.RTF = 1.0; // Reset coil runtime fraction to 1.0
2269 : }
2270 2770334 : heatingCoil.ElecUseLoad = heatingCoil.ParasiticElecLoad * heatingCoil.RTF;
2271 2770334 : heatingCoil.FuelUseLoad = heatingCoil.NominalCapacity / Effic * heatingCoil.RTF;
2272 2770334 : heatingCoil.ParasiticFuelRate = heatingCoil.ParasiticFuelCapacity * (1.0 - heatingCoil.RTF);
2273 : // Fan power will also be modified by the heating coil's part load fraction
2274 : // OnOffFanPartLoadFraction passed to fan via DataHVACGlobals (cycling fan only)
2275 2770334 : if (fanOp == HVAC::FanOp::Cycling) {
2276 168443 : state.dataHVACGlobal->OnOffFanPartLoadFraction = PLF;
2277 : }
2278 : }
2279 : }
2280 :
2281 : // Set the outlet conditions
2282 86405587 : heatingCoil.HeatingCoilLoad = HeatingCoilLoad;
2283 86405587 : heatingCoil.OutletAirTemp = TempAirOut;
2284 :
2285 : // This HeatingCoil does not change the moisture or Mass Flow across the component
2286 86405587 : heatingCoil.OutletAirHumRat = heatingCoil.InletAirHumRat;
2287 86405587 : heatingCoil.OutletAirMassFlowRate = heatingCoil.InletAirMassFlowRate;
2288 : // Set the outlet enthalpys for air and Heating
2289 86405587 : heatingCoil.OutletAirEnthalpy = Psychrometrics::PsyHFnTdbW(heatingCoil.OutletAirTemp, heatingCoil.OutletAirHumRat);
2290 :
2291 86405587 : QCoilActual = HeatingCoilLoad;
2292 86405587 : if (heatingCoil.AirLoopNum > 0) {
2293 1063996 : state.dataAirLoop->AirLoopAFNInfo(heatingCoil.AirLoopNum).AFNLoopHeatingCoilMaxRTF =
2294 1063996 : max(state.dataAirLoop->AirLoopAFNInfo(heatingCoil.AirLoopNum).AFNLoopHeatingCoilMaxRTF, heatingCoil.RTF);
2295 : }
2296 86405587 : state.dataHVACGlobal->ElecHeatingCoilPower = heatingCoil.ElecUseLoad;
2297 :
2298 : // set outlet node temp so parent objects can call calc directly without have to simulate entire model
2299 86405587 : state.dataLoopNodes->Node(heatingCoil.AirOutletNodeNum).Temp = heatingCoil.OutletAirTemp;
2300 86405587 : }
2301 :
2302 382010 : void CalcMultiStageGasHeatingCoil(EnergyPlusData &state,
2303 : int const CoilNum, // the number of the Gas heating coil to be simulated
2304 : Real64 const SpeedRatio, // SpeedRatio varies between 1.0 (maximum speed) and 0.0 (minimum speed)
2305 : Real64 const CycRatio, // cycling part load ratio
2306 : int const StageNum, // Speed number
2307 : HVAC::FanOp const fanOp // Fan operation mode
2308 : )
2309 : {
2310 :
2311 : // SUBROUTINE INFORMATION:
2312 : // AUTHOR Chandan Sharma, FSEC
2313 : // DATE WRITTEN January 2013
2314 :
2315 : // PURPOSE OF THIS SUBROUTINE:
2316 : // Calculates the air-side performance and energy use of a multi stage gas heating coil.
2317 :
2318 : // METHODOLOGY EMPLOYED:
2319 : // Uses the same methodology as the single speed Gas heating unit model (SUBROUTINE CalcFuelHeatingCoil).
2320 : // In addition it assumes that the unit performance is obtained by interpolating between
2321 : // the performance at high stage and that at low stage. If the output needed is below
2322 : // that produced at low stage, the coil cycles between off and low stage.
2323 :
2324 382010 : Real64 const MSHPMassFlowRateHigh = state.dataHVACGlobal->MSHPMassFlowRateHigh;
2325 382010 : Real64 const MSHPMassFlowRateLow = state.dataHVACGlobal->MSHPMassFlowRateLow;
2326 :
2327 : // SUBROUTINE PARAMETER DEFINITIONS:
2328 : static constexpr std::string_view RoutineName("CalcMultiStageGasHeatingCoil");
2329 : static constexpr std::string_view RoutineNameAverageLoad("CalcMultiStageGasHeatingCoil:Averageload");
2330 : static constexpr std::string_view RoutineNameFullLoad("CalcMultiStageGasHeatingCoil:fullload");
2331 :
2332 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
2333 : Real64 OutletAirEnthalpy; // outlet air enthalpy [J/kg]
2334 : Real64 OutletAirHumRat; // outlet air humidity ratio [kg/kg]
2335 : Real64 TotCapHS; // total capacity at high stage [W]
2336 : Real64 TotCapLS; // total capacity at low stage [W]
2337 : Real64 TotCap; // total capacity at current stage [W]
2338 : Real64 EffHS; // efficiency at high stage
2339 382010 : Real64 EffLS(0.0); // efficiency at low stage
2340 : Real64 EffAvg; // average efficiency
2341 : int StageNumHS; // High stage number
2342 : int StageNumLS; // Low stage number
2343 : Real64 FullLoadOutAirEnth; // Outlet full load enthalpy
2344 : Real64 FullLoadOutAirHumRat; // Outlet humidity ratio at full load
2345 : Real64 FullLoadOutAirTemp; // Outlet temperature at full load
2346 : Real64 FullLoadOutAirRH; // Outler relative humidity at full load
2347 : Real64 OutletAirTemp; // Supply ari temperature
2348 : Real64 LSFullLoadOutAirEnth; // Outlet full load enthalpy at low stage
2349 : Real64 HSFullLoadOutAirEnth; // Outlet full load enthalpy at high stage
2350 : Real64 LSGasHeatingPower; // Full load power at low stage
2351 : Real64 HSGasHeatingPower; // Full load power at high stage
2352 382010 : Real64 PartLoadRat(0.0); // part load ratio
2353 : Real64 PLF; // part load factor used to calculate RTF
2354 :
2355 382010 : auto &heatingCoil = state.dataHeatingCoils->HeatingCoil(CoilNum);
2356 :
2357 382010 : if (StageNum > 1) {
2358 61842 : StageNumLS = StageNum - 1;
2359 61842 : StageNumHS = StageNum;
2360 61842 : if (StageNum > heatingCoil.NumOfStages) {
2361 61842 : StageNumLS = heatingCoil.NumOfStages - 1;
2362 61842 : StageNumHS = heatingCoil.NumOfStages;
2363 : }
2364 : } else {
2365 320168 : StageNumLS = 1;
2366 320168 : StageNumHS = 1;
2367 : }
2368 :
2369 382010 : Real64 AirMassFlow = heatingCoil.InletAirMassFlowRate;
2370 382010 : Real64 InletAirEnthalpy = heatingCoil.InletAirEnthalpy;
2371 382010 : Real64 InletAirHumRat = heatingCoil.InletAirHumRat;
2372 382010 : Real64 OutdoorPressure = state.dataEnvrn->OutBaroPress;
2373 :
2374 382010 : if ((AirMassFlow > 0.0) && (heatingCoil.availSched->getCurrentVal() > 0.0) && ((CycRatio > 0.0) || (SpeedRatio > 0.0))) {
2375 :
2376 200668 : if (StageNum > 1) {
2377 :
2378 0 : TotCapLS = heatingCoil.MSNominalCapacity(StageNumLS);
2379 0 : TotCapHS = heatingCoil.MSNominalCapacity(StageNumHS);
2380 :
2381 0 : EffLS = heatingCoil.MSEfficiency(StageNumLS);
2382 0 : EffHS = heatingCoil.MSEfficiency(StageNumHS);
2383 :
2384 0 : PartLoadRat = min(1.0, SpeedRatio);
2385 0 : heatingCoil.RTF = 1.0;
2386 :
2387 : // Get full load output and power
2388 0 : LSFullLoadOutAirEnth = InletAirEnthalpy + TotCapLS / MSHPMassFlowRateLow;
2389 0 : HSFullLoadOutAirEnth = InletAirEnthalpy + TotCapHS / MSHPMassFlowRateHigh;
2390 0 : LSGasHeatingPower = TotCapLS / EffLS;
2391 0 : HSGasHeatingPower = TotCapHS / EffHS;
2392 0 : OutletAirHumRat = InletAirHumRat;
2393 :
2394 : // if cycling fan, send coil part-load fraction to on/off fan via HVACDataGlobals
2395 : // IF (FanOpMode .EQ. FanOp::Cycling) OnOffFanPartLoadFraction = 1.0d0
2396 :
2397 : // Power calculation. If PartLoadRat (SpeedRatio) = 0, operate at LS the whole time step
2398 0 : heatingCoil.ElecUseLoad =
2399 0 : PartLoadRat * heatingCoil.MSParasiticElecLoad(StageNumHS) + (1.0 - PartLoadRat) * heatingCoil.MSParasiticElecLoad(StageNumLS);
2400 :
2401 0 : state.dataHVACGlobal->ElecHeatingCoilPower = heatingCoil.ElecUseLoad;
2402 0 : heatingCoil.HeatingCoilLoad = MSHPMassFlowRateHigh * (HSFullLoadOutAirEnth - InletAirEnthalpy) * PartLoadRat +
2403 0 : MSHPMassFlowRateLow * (LSFullLoadOutAirEnth - InletAirEnthalpy) * (1.0 - PartLoadRat);
2404 0 : EffAvg = (EffHS * PartLoadRat) + (EffLS * (1.0 - PartLoadRat));
2405 0 : heatingCoil.FuelUseLoad = heatingCoil.HeatingCoilLoad / EffAvg;
2406 0 : heatingCoil.ParasiticFuelRate = 0.0;
2407 :
2408 0 : OutletAirEnthalpy = InletAirEnthalpy + heatingCoil.HeatingCoilLoad / heatingCoil.InletAirMassFlowRate;
2409 0 : OutletAirTemp = Psychrometrics::PsyTdbFnHW(OutletAirEnthalpy, OutletAirHumRat);
2410 0 : FullLoadOutAirRH = Psychrometrics::PsyRhFnTdbWPb(state, OutletAirTemp, OutletAirHumRat, OutdoorPressure, RoutineNameAverageLoad);
2411 :
2412 0 : if (FullLoadOutAirRH > 1.0) { // Limit to saturated conditions at FullLoadOutAirEnth
2413 0 : OutletAirTemp = Psychrometrics::PsyTsatFnHPb(state, OutletAirEnthalpy, OutdoorPressure, RoutineName);
2414 0 : OutletAirHumRat = Psychrometrics::PsyWFnTdbH(state, OutletAirTemp, OutletAirEnthalpy, RoutineName);
2415 : }
2416 :
2417 0 : heatingCoil.OutletAirTemp = OutletAirTemp;
2418 0 : heatingCoil.OutletAirHumRat = OutletAirHumRat;
2419 0 : heatingCoil.OutletAirEnthalpy = OutletAirEnthalpy;
2420 0 : heatingCoil.OutletAirMassFlowRate = heatingCoil.InletAirMassFlowRate;
2421 :
2422 : // Stage 1
2423 200668 : } else if (CycRatio > 0.0) {
2424 :
2425 : // for cycling fan, reset mass flow to full on rate
2426 200668 : if (fanOp == HVAC::FanOp::Cycling) {
2427 28116 : AirMassFlow /= CycRatio;
2428 172552 : } else if (fanOp == HVAC::FanOp::Continuous) {
2429 172552 : AirMassFlow = MSHPMassFlowRateLow;
2430 : }
2431 :
2432 200668 : TotCap = heatingCoil.MSNominalCapacity(StageNumLS);
2433 :
2434 200668 : PartLoadRat = min(1.0, CycRatio);
2435 200668 : heatingCoil.RTF = PartLoadRat;
2436 :
2437 : // Calculate full load outlet conditions
2438 200668 : FullLoadOutAirEnth = InletAirEnthalpy + TotCap / AirMassFlow;
2439 200668 : FullLoadOutAirHumRat = InletAirHumRat;
2440 200668 : FullLoadOutAirTemp = Psychrometrics::PsyTdbFnHW(FullLoadOutAirEnth, FullLoadOutAirHumRat);
2441 : FullLoadOutAirRH =
2442 200668 : Psychrometrics::PsyRhFnTdbWPb(state, FullLoadOutAirTemp, FullLoadOutAirHumRat, OutdoorPressure, RoutineNameFullLoad);
2443 :
2444 200668 : if (FullLoadOutAirRH > 1.0) { // Limit to saturated conditions at FullLoadOutAirEnth
2445 0 : FullLoadOutAirTemp = Psychrometrics::PsyTsatFnHPb(state, FullLoadOutAirEnth, OutdoorPressure, RoutineName);
2446 : // Eventually inlet air conditions will be used in Gas Coil, these lines are commented out and marked with this comment line
2447 : // FullLoadOutAirTemp = PsyTsatFnHPb(FullLoadOutAirEnth,InletAirPressure)
2448 0 : FullLoadOutAirHumRat = Psychrometrics::PsyWFnTdbH(state, FullLoadOutAirTemp, FullLoadOutAirEnth, RoutineName);
2449 : }
2450 :
2451 : // Set outlet conditions from the full load calculation
2452 200668 : if (fanOp == HVAC::FanOp::Cycling) {
2453 28116 : OutletAirEnthalpy = FullLoadOutAirEnth;
2454 28116 : OutletAirHumRat = FullLoadOutAirHumRat;
2455 28116 : OutletAirTemp = FullLoadOutAirTemp;
2456 : } else {
2457 172552 : OutletAirEnthalpy =
2458 172552 : PartLoadRat * AirMassFlow / heatingCoil.InletAirMassFlowRate * (FullLoadOutAirEnth - InletAirEnthalpy) + InletAirEnthalpy;
2459 172552 : OutletAirHumRat =
2460 172552 : PartLoadRat * AirMassFlow / heatingCoil.InletAirMassFlowRate * (FullLoadOutAirHumRat - InletAirHumRat) + InletAirHumRat;
2461 172552 : OutletAirTemp = Psychrometrics::PsyTdbFnHW(OutletAirEnthalpy, OutletAirHumRat);
2462 : }
2463 :
2464 200668 : EffLS = heatingCoil.MSEfficiency(StageNumLS);
2465 :
2466 200668 : heatingCoil.HeatingCoilLoad = TotCap * PartLoadRat;
2467 :
2468 200668 : heatingCoil.FuelUseLoad = heatingCoil.HeatingCoilLoad / EffLS;
2469 : // parasitics are calculated when the coil is off (1-PLR)
2470 200668 : heatingCoil.ElecUseLoad = heatingCoil.MSParasiticElecLoad(StageNumLS) * (1.0 - PartLoadRat);
2471 200668 : heatingCoil.ParasiticFuelRate = heatingCoil.ParasiticFuelCapacity * (1.0 - PartLoadRat);
2472 200668 : state.dataHVACGlobal->ElecHeatingCoilPower = heatingCoil.ElecUseLoad;
2473 :
2474 200668 : heatingCoil.OutletAirTemp = OutletAirTemp;
2475 200668 : heatingCoil.OutletAirHumRat = OutletAirHumRat;
2476 200668 : heatingCoil.OutletAirEnthalpy = OutletAirEnthalpy;
2477 200668 : heatingCoil.OutletAirMassFlowRate = heatingCoil.InletAirMassFlowRate;
2478 : }
2479 :
2480 : // This requires a CR to correct (i.e., calculate outputs when coil is off)
2481 : } else {
2482 :
2483 : // Gas coil is off; just pass through conditions
2484 181342 : heatingCoil.OutletAirEnthalpy = heatingCoil.InletAirEnthalpy;
2485 181342 : heatingCoil.OutletAirHumRat = heatingCoil.InletAirHumRat;
2486 181342 : heatingCoil.OutletAirTemp = heatingCoil.InletAirTemp;
2487 181342 : heatingCoil.OutletAirMassFlowRate = heatingCoil.InletAirMassFlowRate;
2488 :
2489 : // some of these are reset in Init, can be removed to speed up code
2490 181342 : heatingCoil.ElecUseLoad = 0.0;
2491 181342 : heatingCoil.HeatingCoilLoad = 0.0;
2492 181342 : heatingCoil.FuelUseLoad = 0.0;
2493 181342 : heatingCoil.ParasiticFuelRate = heatingCoil.ParasiticFuelCapacity;
2494 181342 : state.dataHVACGlobal->ElecHeatingCoilPower = 0.0;
2495 181342 : PartLoadRat = 0.0;
2496 :
2497 : } // end of on/off if - else
2498 :
2499 : // If the PLF curve is defined the gas usage needs to be modified.
2500 : // The PLF curve is only used when the coil cycles.
2501 382010 : if (heatingCoil.PLFCurveIndex > 0) {
2502 0 : if (PartLoadRat > 0.0 && StageNum < 2) {
2503 0 : PLF = Curve::CurveValue(state, heatingCoil.PLFCurveIndex, PartLoadRat);
2504 0 : if (PLF < 0.7) {
2505 0 : if (heatingCoil.PLFErrorCount < 1) {
2506 0 : ++heatingCoil.PLFErrorCount;
2507 0 : ShowWarningError(state,
2508 0 : format("CalcFuelHeatingCoil: {}=\"{}\", PLF curve values",
2509 : HVAC::cAllCoilTypes(heatingCoil.HCoilType_Num),
2510 0 : heatingCoil.Name));
2511 0 : ShowContinueError(state, format("The PLF curve value = {:.5T} for part-load ratio = {:.5T}", PLF, PartLoadRat));
2512 0 : ShowContinueError(state, "PLF curve values must be >= 0.7. PLF has been reset to 0.7 and the simulation continues...");
2513 0 : ShowContinueError(state, "Check the IO reference manual for PLF curve guidance [Coil:Heating:Fuel].");
2514 : } else {
2515 0 : ShowRecurringWarningErrorAtEnd(state,
2516 0 : format("{}, Heating coil PLF curve < 0.7 warning continues... ", heatingCoil.Name),
2517 0 : heatingCoil.PLFErrorIndex,
2518 : PLF,
2519 : PLF);
2520 : }
2521 0 : PLF = 0.7;
2522 : }
2523 : // Modify the Gas Coil Consumption and parasitic loads based on PLF curve
2524 0 : heatingCoil.RTF = PartLoadRat / PLF;
2525 0 : if (heatingCoil.RTF > 1.0 && std::abs(heatingCoil.RTF - 1.0) > 0.001) {
2526 0 : if (heatingCoil.RTFErrorCount < 1) {
2527 0 : ++heatingCoil.RTFErrorCount;
2528 0 : ShowWarningError(state,
2529 0 : format("CalcFuelHeatingCoil: {}=\"{}\", runtime fraction",
2530 : HVAC::cAllCoilTypes(heatingCoil.HCoilType_Num),
2531 0 : heatingCoil.Name));
2532 0 : ShowContinueError(state, format("The runtime fraction exceeded 1.0. [{:.4T}].", heatingCoil.RTF));
2533 0 : ShowContinueError(state, "Runtime fraction is set to 1.0 and the simulation continues...");
2534 0 : ShowContinueError(state, "Check the IO reference manual for PLF curve guidance [Coil:Heating:Fuel].");
2535 : } else {
2536 0 : ShowRecurringWarningErrorAtEnd(state,
2537 0 : format("{}, Heating coil runtime fraction > 1.0 warning continues... ", heatingCoil.Name),
2538 0 : heatingCoil.RTFErrorIndex,
2539 0 : heatingCoil.RTF,
2540 0 : heatingCoil.RTF);
2541 : }
2542 0 : heatingCoil.RTF = 1.0; // Reset coil runtime fraction to 1.0
2543 0 : } else if (heatingCoil.RTF > 1.0) {
2544 0 : heatingCoil.RTF = 1.0; // Reset coil runtime fraction to 1.0
2545 : }
2546 0 : heatingCoil.ElecUseLoad = heatingCoil.MSParasiticElecLoad(StageNum) * heatingCoil.RTF;
2547 0 : heatingCoil.FuelUseLoad = (heatingCoil.MSNominalCapacity(StageNum) / EffLS) * heatingCoil.RTF;
2548 0 : heatingCoil.ParasiticFuelRate = heatingCoil.ParasiticFuelCapacity * (1.0 - heatingCoil.RTF);
2549 : // Fan power will also be modified by the heating coil's part load fraction
2550 : // OnOffFanPartLoadFraction passed to fan via DataHVACGlobals (cycling fan only)
2551 0 : if (fanOp == HVAC::FanOp::Cycling) {
2552 0 : state.dataHVACGlobal->OnOffFanPartLoadFraction = PLF;
2553 : }
2554 : }
2555 : }
2556 :
2557 : // set outlet node temp so parent objects can call calc directly without have to simulate entire model
2558 382010 : state.dataLoopNodes->Node(heatingCoil.AirOutletNodeNum).Temp = heatingCoil.OutletAirTemp;
2559 382010 : }
2560 :
2561 106223 : void CalcDesuperheaterHeatingCoil(EnergyPlusData &state,
2562 : int const CoilNum, // index to desuperheater heating coil
2563 : Real64 const QCoilReq, // load requested by the simulation for load based control [W]
2564 : Real64 &QCoilActual // coil load actually delivered
2565 : )
2566 : {
2567 : // SUBROUTINE INFORMATION:
2568 : // AUTHOR Richard Raustad
2569 : // DATE WRITTEN January 2005
2570 : // MODIFIED Jul. 2016, R. Zhang, Applied the coil supply air temperature sensor offset
2571 :
2572 : // PURPOSE OF THIS SUBROUTINE:
2573 : // Simulates a simple desuperheater heating coil with a heat reclaim efficiency
2574 : // (eff = ratio of condenser waste heat reclaimed to total condenser waste heat rejected)
2575 :
2576 : // METHODOLOGY EMPLOYED:
2577 : // The available capacity of the desuperheater heating coil is determined by the
2578 : // amount of heat rejected at the heating source condenser multiplied by the
2579 : // desuperheater heat reclaim efficiency. This capacity is either applied towards
2580 : // a requested load (load based control) or applied to the air stream to meet a
2581 : // heating setpoint (temperature based control). This subroutine is similar to
2582 : // the electric or gas heating coil except that the NominalCapacity is variable
2583 : // and based on the runtime fraction and heat rejection of the heat source object.
2584 :
2585 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
2586 : Real64 AvailTemp; // Lowest temperature available from desuperheater (~T condensing)[C]
2587 : Real64 TempAirOut; // temperature of the air leaving the desuperheater heating coil [C]
2588 : Real64 HeatingCoilLoad; // actual load delivered by the desuperheater heating coil [W]
2589 : Real64 QCoilCap; // available capacity of the desuperheater heating coil [W]
2590 : int SourceID; // waste heat source id number
2591 :
2592 106223 : auto &heatingCoil = state.dataHeatingCoils->HeatingCoil(CoilNum);
2593 :
2594 106223 : Real64 Effic = heatingCoil.Efficiency;
2595 106223 : Real64 AirMassFlow = heatingCoil.InletAirMassFlowRate;
2596 106223 : Real64 TempAirIn = heatingCoil.InletAirTemp;
2597 106223 : Real64 Win = heatingCoil.InletAirHumRat;
2598 106223 : Real64 CapacitanceAir = Psychrometrics::PsyCpAirFnW(Win) * AirMassFlow;
2599 106223 : Real64 TempSetPoint = heatingCoil.DesiredOutletTemp;
2600 :
2601 : // If there is a fault of coil SAT Sensor
2602 106223 : if (heatingCoil.FaultyCoilSATFlag && (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing) &&
2603 0 : (!state.dataGlobal->KickOffSimulation)) {
2604 : // calculate the sensor offset using fault information
2605 0 : int FaultIndex = heatingCoil.FaultyCoilSATIndex;
2606 0 : heatingCoil.FaultyCoilSATOffset = state.dataFaultsMgr->FaultsCoilSATSensor(FaultIndex).CalFaultOffsetAct(state);
2607 : // update the TempSetPoint
2608 0 : TempSetPoint -= heatingCoil.FaultyCoilSATOffset;
2609 : }
2610 :
2611 : // Access the appropriate structure to find the available heating capacity of the desuperheater heating coil
2612 : // The nominal capacity of the desuperheater heating coil varies based on the amount of heat rejected by the source
2613 : // Stovall 2011, add comparison to available temperature of heat reclaim source
2614 106223 : if (state.dataHeatingCoils->ValidSourceType(CoilNum)) {
2615 106223 : SourceID = heatingCoil.ReclaimHeatingSourceIndexNum;
2616 106223 : switch (heatingCoil.ReclaimHeatingSource) {
2617 48924 : case HeatObjTypes::COMPRESSORRACK_REFRIGERATEDCASE:
2618 : // Added last term to available energy equations to avoid double counting reclaimed energy
2619 : // because refrigeration systems are solved outside the hvac time step iterations
2620 48924 : heatingCoil.RTF = 1.0;
2621 48924 : heatingCoil.NominalCapacity = state.dataHeatBal->HeatReclaimRefrigeratedRack(SourceID).AvailCapacity * Effic -
2622 48924 : state.dataHeatBal->HeatReclaimRefrigeratedRack(SourceID).WaterHeatingDesuperheaterReclaimedHeatTotal;
2623 48924 : break;
2624 48866 : case HeatObjTypes::CONDENSER_REFRIGERATION:
2625 48866 : AvailTemp = state.dataHeatBal->HeatReclaimRefrigCondenser(SourceID).AvailTemperature;
2626 48866 : heatingCoil.RTF = 1.0;
2627 48866 : if (AvailTemp <= TempAirIn) {
2628 194 : heatingCoil.NominalCapacity = 0.0;
2629 1552 : ShowRecurringWarningErrorAtEnd(
2630 : state,
2631 388 : format("Coil:Heating:Desuperheater {} - Waste heat source temperature was too low to be useful.", heatingCoil.Name),
2632 194 : heatingCoil.InsuffTemperatureWarn);
2633 : } else {
2634 48672 : heatingCoil.NominalCapacity = state.dataHeatBal->HeatReclaimRefrigCondenser(SourceID).AvailCapacity * Effic -
2635 48672 : state.dataHeatBal->HeatReclaimRefrigCondenser(SourceID).WaterHeatingDesuperheaterReclaimedHeatTotal;
2636 : }
2637 48866 : break;
2638 0 : case HeatObjTypes::COIL_DX_COOLING:
2639 : case HeatObjTypes::COIL_DX_MULTISPEED:
2640 : case HeatObjTypes::COIL_DX_MULTIMODE:
2641 0 : heatingCoil.RTF = state.dataDXCoils->DXCoil(SourceID).CoolingCoilRuntimeFraction;
2642 0 : heatingCoil.NominalCapacity = state.dataHeatBal->HeatReclaimDXCoil(SourceID).AvailCapacity * Effic -
2643 0 : state.dataHeatBal->HeatReclaimDXCoil(SourceID).WaterHeatingDesuperheaterReclaimedHeatTotal;
2644 0 : break;
2645 0 : case HeatObjTypes::COIL_DX_VARIABLE_COOLING:
2646 : // condenser heat rejection
2647 0 : heatingCoil.RTF = state.dataVariableSpeedCoils->VarSpeedCoil(SourceID).RunFrac;
2648 0 : heatingCoil.NominalCapacity = state.dataHeatBal->HeatReclaimVS_Coil(SourceID).AvailCapacity * Effic -
2649 0 : state.dataHeatBal->HeatReclaimVS_Coil(SourceID).WaterHeatingDesuperheaterReclaimedHeatTotal;
2650 0 : break;
2651 8433 : case HeatObjTypes::COIL_COOLING_DX_NEW:
2652 : // get RTF and NominalCapacity from Coil:CoolingDX
2653 : {
2654 8433 : auto const &thisCoolingCoil = state.dataCoilCoolingDX->coilCoolingDXs[SourceID];
2655 8433 : heatingCoil.RTF = thisCoolingCoil.runTimeFraction;
2656 8433 : heatingCoil.NominalCapacity =
2657 8433 : thisCoolingCoil.reclaimHeat.AvailCapacity * Effic - thisCoolingCoil.reclaimHeat.WaterHeatingDesuperheaterReclaimedHeatTotal;
2658 : }
2659 8433 : break;
2660 0 : default:
2661 0 : assert(false);
2662 : }
2663 :
2664 : } else {
2665 0 : heatingCoil.NominalCapacity = 0.0;
2666 : }
2667 :
2668 : // Control output to meet load (QCoilReq)
2669 106223 : if ((AirMassFlow > 0.0) && (heatingCoil.availSched->getCurrentVal() > 0.0) && (QCoilReq > 0.0)) {
2670 :
2671 : // check to see if the Required heating capacity is greater than the available heating capacity.
2672 2416 : if (QCoilReq > heatingCoil.NominalCapacity) {
2673 2336 : QCoilCap = heatingCoil.NominalCapacity;
2674 : } else {
2675 80 : QCoilCap = QCoilReq;
2676 : }
2677 :
2678 : // report the runtime fraction of the desuperheater heating coil
2679 2416 : if (heatingCoil.NominalCapacity > 0.0) {
2680 2404 : heatingCoil.RTF *= (QCoilCap / heatingCoil.NominalCapacity);
2681 2404 : TempAirOut = TempAirIn + QCoilCap / CapacitanceAir;
2682 2404 : HeatingCoilLoad = QCoilCap;
2683 : } else {
2684 12 : heatingCoil.RTF = 0.0;
2685 12 : TempAirOut = TempAirIn;
2686 12 : HeatingCoilLoad = 0.0;
2687 : }
2688 :
2689 : // Control coil output to meet a setpoint temperature.
2690 103801 : } else if ((AirMassFlow > 0.0 && heatingCoil.NominalCapacity > 0.0) && (heatingCoil.availSched->getCurrentVal() > 0.0) &&
2691 207608 : (QCoilReq == DataLoopNode::SensedLoadFlagValue) && (std::abs(TempSetPoint - TempAirIn) > HVAC::TempControlTol)) {
2692 :
2693 0 : QCoilCap = CapacitanceAir * (TempSetPoint - TempAirIn);
2694 : // check to see if setpoint is above entering air temperature. If not, set output to zero.
2695 0 : if (QCoilCap <= 0.0) {
2696 0 : QCoilCap = 0.0;
2697 0 : TempAirOut = TempAirIn;
2698 : // check to see if the required heating capacity is greater than the available capacity.
2699 0 : } else if (QCoilCap > heatingCoil.NominalCapacity) {
2700 0 : QCoilCap = heatingCoil.NominalCapacity;
2701 0 : TempAirOut = TempAirIn + QCoilCap / CapacitanceAir;
2702 : } else {
2703 0 : TempAirOut = TempSetPoint;
2704 : }
2705 :
2706 0 : HeatingCoilLoad = QCoilCap;
2707 : // report the runtime fraction of the desuperheater heating coil
2708 0 : heatingCoil.RTF *= (QCoilCap / heatingCoil.NominalCapacity);
2709 :
2710 : } else { // If not running, conditions do not change across heating coil from inlet to outlet
2711 :
2712 103807 : TempAirOut = TempAirIn;
2713 103807 : HeatingCoilLoad = 0.0;
2714 103807 : heatingCoil.ElecUseLoad = 0.0;
2715 103807 : heatingCoil.RTF = 0.0;
2716 : }
2717 :
2718 : // Set the outlet conditions
2719 106223 : heatingCoil.HeatingCoilLoad = HeatingCoilLoad;
2720 106223 : heatingCoil.OutletAirTemp = TempAirOut;
2721 :
2722 : // This HeatingCoil does not change the moisture or Mass Flow across the component
2723 106223 : heatingCoil.OutletAirHumRat = heatingCoil.InletAirHumRat;
2724 106223 : heatingCoil.OutletAirMassFlowRate = heatingCoil.InletAirMassFlowRate;
2725 : // Set the outlet enthalpy
2726 106223 : heatingCoil.OutletAirEnthalpy = Psychrometrics::PsyHFnTdbW(heatingCoil.OutletAirTemp, heatingCoil.OutletAirHumRat);
2727 :
2728 106223 : heatingCoil.ElecUseLoad = heatingCoil.ParasiticElecLoad * heatingCoil.RTF;
2729 106223 : QCoilActual = HeatingCoilLoad;
2730 :
2731 : // Update remaining waste heat (just in case multiple users of waste heat use same source)
2732 106223 : if (state.dataHeatingCoils->ValidSourceType(CoilNum)) {
2733 106223 : SourceID = heatingCoil.ReclaimHeatingSourceIndexNum;
2734 : // Refrigerated cases are simulated at the zone time step, do not decrement available capacity
2735 : // (the heat reclaim available capacity will not get reinitialized as the air loop iterates)
2736 106223 : int DesuperheaterNum = CoilNum - state.dataHeatingCoils->NumElecCoil - state.dataHeatingCoils->NumElecCoilMultiStage -
2737 106223 : state.dataHeatingCoils->NumFuelCoil - state.dataHeatingCoils->NumGasCoilMultiStage;
2738 106223 : switch (heatingCoil.ReclaimHeatingSource) {
2739 48924 : case HeatObjTypes::COMPRESSORRACK_REFRIGERATEDCASE: {
2740 48924 : state.dataHeatBal->HeatReclaimRefrigeratedRack(SourceID).HVACDesuperheaterReclaimedHeat(DesuperheaterNum) = HeatingCoilLoad;
2741 48924 : state.dataHeatBal->HeatReclaimRefrigeratedRack(SourceID).HVACDesuperheaterReclaimedHeatTotal = 0.0;
2742 97848 : for (auto const &num : state.dataHeatBal->HeatReclaimRefrigeratedRack(SourceID).HVACDesuperheaterReclaimedHeat) {
2743 48924 : state.dataHeatBal->HeatReclaimRefrigeratedRack(SourceID).HVACDesuperheaterReclaimedHeatTotal += num;
2744 : }
2745 48924 : } break;
2746 48866 : case HeatObjTypes::CONDENSER_REFRIGERATION: {
2747 48866 : state.dataHeatBal->HeatReclaimRefrigCondenser(SourceID).HVACDesuperheaterReclaimedHeat(DesuperheaterNum) = HeatingCoilLoad;
2748 48866 : state.dataHeatBal->HeatReclaimRefrigCondenser(SourceID).HVACDesuperheaterReclaimedHeatTotal = 0.0;
2749 97732 : for (auto const &num : state.dataHeatBal->HeatReclaimRefrigCondenser(SourceID).HVACDesuperheaterReclaimedHeat) {
2750 48866 : state.dataHeatBal->HeatReclaimRefrigCondenser(SourceID).HVACDesuperheaterReclaimedHeatTotal += num;
2751 : }
2752 48866 : } break;
2753 0 : case HeatObjTypes::COIL_DX_COOLING:
2754 : case HeatObjTypes::COIL_DX_MULTISPEED:
2755 : case HeatObjTypes::COIL_DX_MULTIMODE: {
2756 0 : state.dataHeatBal->HeatReclaimDXCoil(SourceID).HVACDesuperheaterReclaimedHeat(DesuperheaterNum) = HeatingCoilLoad;
2757 0 : state.dataHeatBal->HeatReclaimDXCoil(SourceID).HVACDesuperheaterReclaimedHeatTotal = 0.0;
2758 0 : for (auto const &num : state.dataHeatBal->HeatReclaimDXCoil(SourceID).HVACDesuperheaterReclaimedHeat) {
2759 0 : state.dataHeatBal->HeatReclaimDXCoil(SourceID).HVACDesuperheaterReclaimedHeatTotal += num;
2760 : }
2761 0 : } break;
2762 0 : case HeatObjTypes::COIL_DX_VARIABLE_COOLING: {
2763 0 : state.dataHeatBal->HeatReclaimVS_Coil(SourceID).HVACDesuperheaterReclaimedHeat(DesuperheaterNum) = HeatingCoilLoad;
2764 0 : state.dataHeatBal->HeatReclaimVS_Coil(SourceID).HVACDesuperheaterReclaimedHeatTotal = 0.0;
2765 0 : for (auto const &num : state.dataHeatBal->HeatReclaimVS_Coil(SourceID).HVACDesuperheaterReclaimedHeat) {
2766 0 : state.dataHeatBal->HeatReclaimVS_Coil(SourceID).HVACDesuperheaterReclaimedHeatTotal += num;
2767 : }
2768 0 : } break;
2769 8433 : default:
2770 8433 : break;
2771 : }
2772 : }
2773 106223 : }
2774 :
2775 122270909 : void UpdateHeatingCoil(EnergyPlusData &state, int const CoilNum)
2776 : {
2777 : // SUBROUTINE INFORMATION:
2778 : // AUTHOR Richard Liesen
2779 : // DATE WRITTEN May 2000
2780 :
2781 : // PURPOSE OF THIS SUBROUTINE:
2782 : // This subroutine updates the coil outlet nodes.
2783 :
2784 : // METHODOLOGY EMPLOYED:
2785 : // Data is moved from the coil data structure to the coil outlet nodes.
2786 :
2787 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
2788 122270909 : auto const &heatingCoil = state.dataHeatingCoils->HeatingCoil(CoilNum);
2789 122270909 : auto const &airInletNode = state.dataLoopNodes->Node(heatingCoil.AirInletNodeNum);
2790 122270909 : auto &airOuletNode = state.dataLoopNodes->Node(heatingCoil.AirOutletNodeNum);
2791 :
2792 : // Set the outlet air nodes of the HeatingCoil
2793 122270909 : airOuletNode.MassFlowRate = heatingCoil.OutletAirMassFlowRate;
2794 122270909 : airOuletNode.Temp = heatingCoil.OutletAirTemp;
2795 122270909 : airOuletNode.HumRat = heatingCoil.OutletAirHumRat;
2796 122270909 : airOuletNode.Enthalpy = heatingCoil.OutletAirEnthalpy;
2797 :
2798 : // Set the outlet nodes for properties that just pass through & not used
2799 122270909 : airOuletNode.Quality = airInletNode.Quality;
2800 122270909 : airOuletNode.Press = airInletNode.Press;
2801 122270909 : airOuletNode.MassFlowRateMin = airInletNode.MassFlowRateMin;
2802 122270909 : airOuletNode.MassFlowRateMax = airInletNode.MassFlowRateMax;
2803 122270909 : airOuletNode.MassFlowRateMinAvail = airInletNode.MassFlowRateMinAvail;
2804 122270909 : airOuletNode.MassFlowRateMaxAvail = airInletNode.MassFlowRateMaxAvail;
2805 :
2806 122270909 : if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
2807 723462 : airOuletNode.CO2 = airInletNode.CO2;
2808 : }
2809 :
2810 122270909 : if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
2811 208042 : airOuletNode.GenContam = airInletNode.GenContam;
2812 : }
2813 122270909 : }
2814 :
2815 122270909 : void ReportHeatingCoil(EnergyPlusData &state, int const CoilNum, bool const coilIsSuppHeater)
2816 : {
2817 :
2818 : // SUBROUTINE INFORMATION:
2819 : // AUTHOR Richard Liesen
2820 : // DATE WRITTEN May 2000
2821 :
2822 : // PURPOSE OF THIS SUBROUTINE:
2823 : // This subroutine updates the report variable for the coils.
2824 :
2825 : // Using/Aliasing
2826 122270909 : Real64 TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
2827 122270909 : auto &heatingCoil = state.dataHeatingCoils->HeatingCoil(CoilNum);
2828 :
2829 : // report the HeatingCoil energy from this component
2830 122270909 : heatingCoil.HeatingCoilRate = heatingCoil.HeatingCoilLoad;
2831 122270909 : heatingCoil.HeatingCoilLoad *= TimeStepSysSec;
2832 :
2833 122270909 : heatingCoil.FuelUseRate = heatingCoil.FuelUseLoad;
2834 122270909 : heatingCoil.ElecUseRate = heatingCoil.ElecUseLoad;
2835 122270909 : if (coilIsSuppHeater) {
2836 43325422 : state.dataHVACGlobal->SuppHeatingCoilPower = heatingCoil.ElecUseLoad;
2837 : } else {
2838 78945487 : state.dataHVACGlobal->ElecHeatingCoilPower = heatingCoil.ElecUseLoad;
2839 : }
2840 122270909 : heatingCoil.FuelUseLoad *= TimeStepSysSec;
2841 122270909 : heatingCoil.ElecUseLoad *= TimeStepSysSec;
2842 :
2843 122270909 : heatingCoil.ParasiticFuelConsumption = heatingCoil.ParasiticFuelRate * TimeStepSysSec;
2844 :
2845 122270909 : std::string coilObjClassName;
2846 122270909 : switch (heatingCoil.HCoilType_Num) {
2847 34314023 : case HVAC::Coil_HeatingElectric: {
2848 34314023 : coilObjClassName = "Coil:Heating:Electric";
2849 34314023 : } break;
2850 1063066 : case HVAC::Coil_HeatingElectric_MultiStage: {
2851 1063066 : coilObjClassName = "Coil:Heating:Electric:MultiStage";
2852 1063066 : } break;
2853 86405587 : case HVAC::Coil_HeatingGasOrOtherFuel: {
2854 86405587 : coilObjClassName = "Coil:Heating:Fuel";
2855 86405587 : } break;
2856 382010 : case HVAC::Coil_HeatingGas_MultiStage: {
2857 382010 : coilObjClassName = "Coil:Heating:Gas:MultiStage";
2858 382010 : } break;
2859 106223 : case HVAC::Coil_HeatingDesuperheater: {
2860 106223 : coilObjClassName = "Coil:Heating:Desuperheater";
2861 106223 : } break;
2862 0 : default:
2863 0 : break;
2864 : }
2865 122270909 : if (heatingCoil.reportCoilFinalSizes) {
2866 20466368 : if (!state.dataGlobal->WarmupFlag && !state.dataGlobal->DoingHVACSizingSimulations && !state.dataGlobal->DoingSizing) {
2867 1573 : state.dataRptCoilSelection->coilSelectionReportObj->setCoilFinalSizes(
2868 1573 : state, heatingCoil.Name, coilObjClassName, heatingCoil.NominalCapacity, heatingCoil.NominalCapacity, -999.0, -999.0);
2869 1573 : heatingCoil.reportCoilFinalSizes = false;
2870 : }
2871 : }
2872 122270909 : }
2873 :
2874 : // End of Reporting subroutines for the HeatingCoil Module
2875 :
2876 983 : void GetCoilIndex(EnergyPlusData &state, std::string const &HeatingCoilName, int &HeatingCoilIndex, bool &ErrorsFound)
2877 : {
2878 :
2879 : // SUBROUTINE INFORMATION:
2880 : // AUTHOR Richard Raustad
2881 : // DATE WRITTEN March 2005
2882 :
2883 : // PURPOSE OF THIS SUBROUTINE:
2884 : // This subroutine sets an index for a given DX Coil -- issues error message if that
2885 : // DX Coil is not a legal DX Coil.
2886 :
2887 : // Obtains and Allocates HeatingCoil related parameters from input file
2888 983 : if (state.dataHeatingCoils->GetCoilsInputFlag) { // First time subroutine has been entered
2889 58 : GetHeatingCoilInput(state);
2890 58 : state.dataHeatingCoils->GetCoilsInputFlag = false;
2891 : }
2892 :
2893 983 : HeatingCoilIndex = Util::FindItem(HeatingCoilName, state.dataHeatingCoils->HeatingCoil);
2894 983 : if (HeatingCoilIndex == 0) {
2895 0 : ShowSevereError(state, format("GetCoilIndex: Heating coil not found={}", HeatingCoilName));
2896 0 : ErrorsFound = true;
2897 : }
2898 983 : }
2899 :
2900 98941 : void CheckHeatingCoilSchedule(EnergyPlusData &state,
2901 : std::string const &CompType, // unused1208
2902 : std::string_view CompName,
2903 : Real64 &Value,
2904 : int &CompIndex)
2905 : {
2906 :
2907 : // SUBROUTINE INFORMATION:
2908 : // AUTHOR Linda Lawrie
2909 : // DATE WRITTEN October 2005
2910 :
2911 : // PURPOSE OF THIS SUBROUTINE:
2912 : // This routine provides a method for outside routines to check if
2913 : // the heating coil is scheduled to be on.
2914 :
2915 : // Obtains and Allocates HeatingCoil related parameters from input file
2916 98941 : if (state.dataHeatingCoils->GetCoilsInputFlag) { // First time subroutine has been entered
2917 6 : GetHeatingCoilInput(state);
2918 6 : state.dataHeatingCoils->GetCoilsInputFlag = false;
2919 : }
2920 :
2921 : // Find the correct Coil number
2922 98941 : if (CompIndex == 0) {
2923 11 : int CoilNum = Util::FindItem(CompName, state.dataHeatingCoils->HeatingCoil);
2924 11 : if (CoilNum == 0) {
2925 0 : ShowFatalError(state, format("CheckHeatingCoilSchedule: Coil not found=\"{}\".", CompName));
2926 : }
2927 11 : if (!Util::SameString(CompType, HVAC::cAllCoilTypes(state.dataHeatingCoils->HeatingCoil(CoilNum).HCoilType_Num))) {
2928 0 : ShowSevereError(state, format("CheckHeatingCoilSchedule: Coil=\"{}\"", CompName));
2929 0 : ShowContinueError(state,
2930 0 : format("...expected type=\"{}\", actual type=\"{}\".",
2931 : CompType,
2932 0 : HVAC::cAllCoilTypes(state.dataHeatingCoils->HeatingCoil(CoilNum).HCoilType_Num)));
2933 0 : ShowFatalError(state, "Program terminates due to preceding conditions.");
2934 : }
2935 11 : CompIndex = CoilNum;
2936 11 : Value = state.dataHeatingCoils->HeatingCoil(CoilNum).availSched->getCurrentVal(); // not scheduled?
2937 : } else {
2938 98930 : int CoilNum = CompIndex;
2939 98930 : if (CoilNum > state.dataHeatingCoils->NumHeatingCoils || CoilNum < 1) {
2940 0 : ShowFatalError(state,
2941 0 : format("CheckHeatingCoilSchedule: Invalid CompIndex passed={}, Number of Heating Coils={}, Coil name={}",
2942 : CoilNum,
2943 0 : state.dataHeatingCoils->NumHeatingCoils,
2944 : CompName));
2945 : }
2946 98930 : if (CompName != state.dataHeatingCoils->HeatingCoil(CoilNum).Name) {
2947 0 : ShowSevereError(state,
2948 0 : format("CheckHeatingCoilSchedule: Invalid CompIndex passed={}, Coil name={}, stored Coil Name for that index={}",
2949 : CoilNum,
2950 : CompName,
2951 0 : state.dataHeatingCoils->HeatingCoil(CoilNum).Name));
2952 0 : ShowContinueError(state,
2953 0 : format("...expected type=\"{}\", actual type=\"{}\".",
2954 : CompType,
2955 0 : HVAC::cAllCoilTypes(state.dataHeatingCoils->HeatingCoil(CoilNum).HCoilType_Num)));
2956 0 : ShowFatalError(state, "Program terminates due to preceding conditions.");
2957 : }
2958 98930 : Value = state.dataHeatingCoils->HeatingCoil(CoilNum).availSched->getCurrentVal(); // not scheduled?
2959 : }
2960 98941 : }
2961 :
2962 399 : Real64 GetCoilCapacity(EnergyPlusData &state,
2963 : std::string const &CoilType, // must match coil types in this module
2964 : std::string const &CoilName, // must match coil names for the coil type
2965 : bool &ErrorsFound // set to true if problem
2966 : )
2967 : {
2968 :
2969 : // FUNCTION INFORMATION:
2970 : // AUTHOR Linda Lawrie
2971 : // DATE WRITTEN February 2006
2972 :
2973 : // PURPOSE OF THIS FUNCTION:
2974 : // This function looks up the coil capacity for the given coil and returns it. If
2975 : // incorrect coil type or name is given, ErrorsFound is returned as true and capacity is returned
2976 : // as negative.
2977 :
2978 : // Return value
2979 : Real64 CoilCapacity; // returned capacity of matched coil
2980 :
2981 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
2982 : int WhichCoil;
2983 :
2984 : // Obtains and Allocates HeatingCoil related parameters from input file
2985 399 : if (state.dataHeatingCoils->GetCoilsInputFlag) { // First time subroutine has been entered
2986 0 : GetHeatingCoilInput(state);
2987 0 : state.dataHeatingCoils->GetCoilsInputFlag = false;
2988 : }
2989 :
2990 399 : int FoundType = Util::FindItem(CoilType, HVAC::cAllCoilTypes, HVAC::NumAllCoilTypes);
2991 399 : if (FoundType == HVAC::Coil_HeatingElectric || FoundType == HVAC::Coil_HeatingGasOrOtherFuel ||
2992 : FoundType == HVAC::Coil_HeatingDesuperheater) {
2993 399 : WhichCoil = Util::FindItem(CoilName, state.dataHeatingCoils->HeatingCoil);
2994 399 : if (WhichCoil != 0) {
2995 399 : CoilCapacity = state.dataHeatingCoils->HeatingCoil(WhichCoil).NominalCapacity;
2996 : }
2997 0 : } else if (FoundType == HVAC::Coil_HeatingElectric_MultiStage || FoundType == HVAC::Coil_HeatingGas_MultiStage) {
2998 0 : WhichCoil = Util::FindItem(CoilName, state.dataHeatingCoils->HeatingCoil);
2999 0 : if (WhichCoil != 0) {
3000 0 : CoilCapacity =
3001 0 : state.dataHeatingCoils->HeatingCoil(WhichCoil).MSNominalCapacity(state.dataHeatingCoils->HeatingCoil(WhichCoil).NumOfStages);
3002 : }
3003 : } else {
3004 0 : WhichCoil = 0;
3005 : }
3006 :
3007 399 : if (WhichCoil == 0) { // Autodesk:Return Reworked block to assure CoilCapacity is set before return
3008 0 : if (FoundType == 0) {
3009 0 : ShowSevereError(state, format("GetCoilCapacity: Could not find Coil, Type=\"{}\" Name=\"{}\"", CoilType, CoilName));
3010 0 : } else if (FoundType > 0) {
3011 0 : ShowSevereError(state, format("GetCoilCapacity: Invalid coil type for capacity, Type=\"{}\" Name=\"{}\"", CoilType, CoilName));
3012 0 : ShowContinueError(state,
3013 0 : format("...only {}, {} or {} are valid in this context.",
3014 : HVAC::cAllCoilTypes(HVAC::Coil_HeatingElectric),
3015 : HVAC::cAllCoilTypes(HVAC::Coil_HeatingGasOrOtherFuel),
3016 : HVAC::cAllCoilTypes(HVAC::Coil_HeatingDesuperheater)));
3017 : }
3018 0 : ShowContinueError(state, "... returning Coil Capacity as -1000.");
3019 0 : ErrorsFound = true;
3020 0 : CoilCapacity = -1000.0;
3021 : }
3022 :
3023 399 : return CoilCapacity;
3024 : }
3025 :
3026 0 : Sched::Schedule *GetCoilAvailSched(EnergyPlusData &state,
3027 : std::string const &CoilType, // must match coil types in this module
3028 : std::string const &CoilName, // must match coil names for the coil type
3029 : bool &ErrorsFound // set to true if problem
3030 : )
3031 : {
3032 :
3033 : // FUNCTION INFORMATION:
3034 : // AUTHOR Richard Raustad, FSEC
3035 : // DATE WRITTEN February 2013
3036 :
3037 : // PURPOSE OF THIS FUNCTION:
3038 : // This function looks up the given coil and returns the availability schedule index. If
3039 : // incorrect coil type or name is given, ErrorsFound is returned as true and index is returned
3040 : // as zero.
3041 :
3042 : // Obtains and Allocates HeatingCoil related parameters from input file
3043 0 : if (state.dataHeatingCoils->GetCoilsInputFlag) { // First time subroutine has been entered
3044 0 : GetHeatingCoilInput(state);
3045 0 : state.dataHeatingCoils->GetCoilsInputFlag = false;
3046 : }
3047 :
3048 0 : int WhichCoil = 0;
3049 0 : int FoundType = Util::FindItem(CoilType, HVAC::cAllCoilTypes, HVAC::NumAllCoilTypes);
3050 0 : if (FoundType == HVAC::Coil_HeatingElectric || FoundType == HVAC::Coil_HeatingElectric_MultiStage ||
3051 0 : FoundType == HVAC::Coil_HeatingGasOrOtherFuel || FoundType == HVAC::Coil_HeatingGas_MultiStage ||
3052 : FoundType == HVAC::Coil_HeatingDesuperheater) {
3053 0 : WhichCoil = Util::FindItem(CoilName, state.dataHeatingCoils->HeatingCoil);
3054 0 : if (WhichCoil != 0) {
3055 0 : return state.dataHeatingCoils->HeatingCoil(WhichCoil).availSched;
3056 : }
3057 : } else {
3058 0 : WhichCoil = 0;
3059 : }
3060 :
3061 0 : if (WhichCoil == 0) {
3062 0 : ShowSevereError(state, format("GetCoilAvailScheduleIndex: Could not find Coil, Type=\"{}\" Name=\"{}\"", CoilType, CoilName));
3063 0 : ErrorsFound = true;
3064 : }
3065 :
3066 0 : return nullptr;
3067 : }
3068 :
3069 411 : int GetCoilInletNode(EnergyPlusData &state,
3070 : std::string_view CoilType, // must match coil types in this module
3071 : std::string const &CoilName, // must match coil names for the coil type
3072 : bool &ErrorsFound // set to true if problem
3073 : )
3074 : {
3075 :
3076 : // FUNCTION INFORMATION:
3077 : // AUTHOR Linda Lawrie
3078 : // DATE WRITTEN February 2006
3079 :
3080 : // PURPOSE OF THIS FUNCTION:
3081 : // This function looks up the given coil and returns the inlet node number. If
3082 : // incorrect coil type or name is given, ErrorsFound is returned as true and node number is returned
3083 : // as zero.
3084 :
3085 : // Obtains and Allocates HeatingCoil related parameters from input file
3086 411 : if (state.dataHeatingCoils->GetCoilsInputFlag) { // First time subroutine has been entered
3087 0 : GetHeatingCoilInput(state);
3088 0 : state.dataHeatingCoils->GetCoilsInputFlag = false;
3089 : }
3090 :
3091 411 : int WhichCoil = 0;
3092 411 : int NodeNumber = 0;
3093 411 : int FoundType = Util::FindItem(CoilType, HVAC::cAllCoilTypes, HVAC::NumAllCoilTypes);
3094 411 : if (FoundType == HVAC::Coil_HeatingElectric || FoundType == HVAC::Coil_HeatingElectric_MultiStage ||
3095 3 : FoundType == HVAC::Coil_HeatingGasOrOtherFuel || FoundType == HVAC::Coil_HeatingGas_MultiStage ||
3096 : FoundType == HVAC::Coil_HeatingDesuperheater) {
3097 411 : WhichCoil = Util::FindItem(CoilName, state.dataHeatingCoils->HeatingCoil);
3098 411 : if (WhichCoil != 0) {
3099 411 : NodeNumber = state.dataHeatingCoils->HeatingCoil(WhichCoil).AirInletNodeNum;
3100 : }
3101 : } else {
3102 0 : WhichCoil = 0;
3103 : }
3104 :
3105 411 : if (WhichCoil == 0) {
3106 0 : ShowSevereError(state, format("GetCoilInletNode: Could not find Coil, Type=\"{}\" Name=\"{}\"", CoilType, CoilName));
3107 0 : ErrorsFound = true;
3108 0 : NodeNumber = 0;
3109 : }
3110 :
3111 411 : return NodeNumber;
3112 : }
3113 :
3114 411 : int GetCoilOutletNode(EnergyPlusData &state,
3115 : std::string_view CoilType, // must match coil types in this module
3116 : std::string const &CoilName, // must match coil names for the coil type
3117 : bool &ErrorsFound // set to true if problem
3118 : )
3119 : {
3120 :
3121 : // FUNCTION INFORMATION:
3122 : // AUTHOR Richard Raustad
3123 : // DATE WRITTEN August 2006
3124 :
3125 : // PURPOSE OF THIS FUNCTION:
3126 : // This function looks up the given coil and returns the outlet node number. If
3127 : // incorrect coil type or name is given, ErrorsFound is returned as true and node number is returned
3128 : // as zero.
3129 :
3130 : // Obtains and Allocates HeatingCoil related parameters from input file
3131 411 : if (state.dataHeatingCoils->GetCoilsInputFlag) { // First time subroutine has been entered
3132 0 : GetHeatingCoilInput(state);
3133 0 : state.dataHeatingCoils->GetCoilsInputFlag = false;
3134 : }
3135 :
3136 411 : int WhichCoil = 0;
3137 411 : int NodeNumber = 0;
3138 411 : int FoundType = Util::FindItem(CoilType, HVAC::cAllCoilTypes, HVAC::NumAllCoilTypes);
3139 411 : if (FoundType == HVAC::Coil_HeatingElectric || FoundType == HVAC::Coil_HeatingElectric_MultiStage ||
3140 3 : FoundType == HVAC::Coil_HeatingGasOrOtherFuel || FoundType == HVAC::Coil_HeatingGas_MultiStage ||
3141 : FoundType == HVAC::Coil_HeatingDesuperheater) {
3142 411 : WhichCoil = Util::FindItem(CoilName, state.dataHeatingCoils->HeatingCoil);
3143 411 : if (WhichCoil != 0) {
3144 411 : NodeNumber = state.dataHeatingCoils->HeatingCoil(WhichCoil).AirOutletNodeNum;
3145 : }
3146 : } else {
3147 0 : WhichCoil = 0;
3148 : }
3149 :
3150 411 : if (WhichCoil == 0) {
3151 0 : ShowSevereError(state, format("GetCoilOutletNode: Could not find Coil, Type=\"{}\" Name=\"{}\"", CoilType, CoilName));
3152 0 : ErrorsFound = true;
3153 0 : NodeNumber = 0;
3154 : }
3155 :
3156 411 : return NodeNumber;
3157 : }
3158 :
3159 2 : int GetHeatReclaimSourceIndex(EnergyPlusData &state,
3160 : std::string const &CoilType, // must match coil types in this module
3161 : std::string const &CoilName, // must match coil names for the coil type
3162 : bool &ErrorsFound // set to true if problem
3163 : )
3164 : {
3165 :
3166 : // FUNCTION INFORMATION:
3167 : // AUTHOR Richard Raustad
3168 : // DATE WRITTEN June 2007
3169 :
3170 : // PURPOSE OF THIS FUNCTION:
3171 : // This function looks up the given coil and returns the heating coil index number if it is a desuperheating coil.
3172 : // If incorrect coil type or name is given, ErrorsFound is returned as true and index number is returned
3173 : // as zero.
3174 :
3175 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
3176 : bool GetCoilErrFlag;
3177 : int NumCoil;
3178 2 : int CoilNum(0);
3179 :
3180 : // Obtains and Allocates HeatingCoil related parameters from input file
3181 2 : if (state.dataHeatingCoils->GetCoilsInputFlag) { // First time subroutine has been entered
3182 0 : GetHeatingCoilInput(state);
3183 0 : state.dataHeatingCoils->GetCoilsInputFlag = false;
3184 : }
3185 :
3186 2 : int CoilFound = 0;
3187 :
3188 : // note should eventually get rid of this string comparison
3189 3 : if (Util::SameString(CoilType, "COIL:COOLING:DX:SINGLESPEED") || Util::SameString(CoilType, "COIL:COOLING:DX:TWOSPEED") ||
3190 3 : Util::SameString(CoilType, "COIL:COOLING:DX:TWOSTAGEWITHHUMIDITYCONTROLMODE")) {
3191 1 : bool SuppressWarning = true;
3192 1 : DXCoils::GetDXCoilIndex(state, CoilName, CoilNum, GetCoilErrFlag, CoilType, SuppressWarning);
3193 9 : for (NumCoil = 1; NumCoil <= state.dataHeatingCoils->NumHeatingCoils; ++NumCoil) {
3194 8 : if (state.dataHeatingCoils->HeatingCoil(NumCoil).ReclaimHeatingSource != HeatObjTypes::COIL_DX_COOLING &&
3195 8 : state.dataHeatingCoils->HeatingCoil(NumCoil).ReclaimHeatingSource != HeatObjTypes::COIL_DX_MULTISPEED &&
3196 24 : state.dataHeatingCoils->HeatingCoil(NumCoil).ReclaimHeatingSource != HeatObjTypes::COIL_DX_MULTIMODE &&
3197 8 : state.dataHeatingCoils->HeatingCoil(NumCoil).ReclaimHeatingCoilName != CoilName) {
3198 8 : continue;
3199 : }
3200 0 : CoilFound = CoilNum;
3201 0 : break;
3202 : }
3203 1 : } else if (Util::SameString(CoilType, "COIL:COOLING:DX:VARIABLESPEED")) {
3204 1 : CoilNum = VariableSpeedCoils::GetCoilIndexVariableSpeed(state, CoilType, CoilName, GetCoilErrFlag);
3205 9 : for (NumCoil = 1; NumCoil <= state.dataHeatingCoils->NumHeatingCoils; ++NumCoil) {
3206 16 : if (state.dataHeatingCoils->HeatingCoil(NumCoil).ReclaimHeatingSource != HeatObjTypes::COIL_DX_VARIABLE_COOLING &&
3207 8 : state.dataHeatingCoils->HeatingCoil(NumCoil).ReclaimHeatingCoilName != CoilName) {
3208 8 : continue;
3209 : }
3210 0 : CoilFound = CoilNum;
3211 0 : break;
3212 : }
3213 : }
3214 :
3215 2 : if (CoilNum == 0) {
3216 0 : ErrorsFound = true;
3217 : }
3218 :
3219 2 : return CoilFound;
3220 : }
3221 :
3222 4 : int GetCoilControlNodeNum(EnergyPlusData &state,
3223 : std::string const &CoilType, // must match coil types in this module
3224 : std::string const &CoilName, // must match coil names for the coil type
3225 : bool &ErrorsFound // set to true if problem
3226 : )
3227 : {
3228 :
3229 : // FUNCTION INFORMATION:
3230 : // AUTHOR Richard Raustad
3231 : // DATE WRITTEN June 2007
3232 :
3233 : // PURPOSE OF THIS FUNCTION:
3234 : // This function looks up the given coil and returns the control node number. If
3235 : // incorrect coil type or name is given, ErrorsFound is returned as true and node number is returned
3236 : // as zero.
3237 :
3238 : // Obtains and Allocates HeatingCoil related parameters from input file
3239 4 : if (state.dataHeatingCoils->GetCoilsInputFlag) { // First time subroutine has been entered
3240 0 : GetHeatingCoilInput(state);
3241 0 : state.dataHeatingCoils->GetCoilsInputFlag = false;
3242 : }
3243 :
3244 4 : int FoundType = Util::FindItem(CoilType, HVAC::cAllCoilTypes, HVAC::NumAllCoilTypes);
3245 4 : if (FoundType == HVAC::Coil_HeatingElectric || FoundType == HVAC::Coil_HeatingElectric_MultiStage ||
3246 0 : FoundType == HVAC::Coil_HeatingGasOrOtherFuel || FoundType == HVAC::Coil_HeatingGas_MultiStage ||
3247 : FoundType == HVAC::Coil_HeatingDesuperheater) {
3248 4 : int WhichCoil = Util::FindItem(CoilName, state.dataHeatingCoils->HeatingCoil);
3249 4 : if (WhichCoil != 0) {
3250 4 : return state.dataHeatingCoils->HeatingCoil(WhichCoil).TempSetPointNodeNum;
3251 : }
3252 : }
3253 :
3254 0 : ShowSevereError(state, format("GetCoilControlNodeNum: Could not find Coil, Type=\"{}\" Name=\"{}\"", CoilType, CoilName));
3255 0 : ErrorsFound = true;
3256 0 : return 0;
3257 : }
3258 :
3259 834 : int GetHeatingCoilTypeNum(EnergyPlusData &state,
3260 : std::string const &CoilType, // must match coil types in this module
3261 : std::string const &CoilName, // must match coil names for the coil type
3262 : bool &ErrorsFound // set to true if problem
3263 : )
3264 : {
3265 :
3266 : // FUNCTION INFORMATION:
3267 : // AUTHOR Richard Raustad
3268 : // DATE WRITTEN August 2008
3269 :
3270 : // PURPOSE OF THIS FUNCTION:
3271 : // This function looks up the given coil and returns the type number. If
3272 : // incorrect coil type or name is given, ErrorsFound is returned as true and type number is returned
3273 : // as zero.
3274 :
3275 : // Obtains and Allocates HeatingCoil related parameters from input file
3276 834 : if (state.dataHeatingCoils->GetCoilsInputFlag) { // First time subroutine has been entered
3277 158 : GetHeatingCoilInput(state);
3278 158 : state.dataHeatingCoils->GetCoilsInputFlag = false;
3279 : }
3280 :
3281 834 : int FoundType = Util::FindItem(CoilType, HVAC::cAllCoilTypes, HVAC::NumAllCoilTypes);
3282 834 : if (FoundType == HVAC::Coil_HeatingElectric || FoundType == HVAC::Coil_HeatingElectric_MultiStage ||
3283 3 : FoundType == HVAC::Coil_HeatingGasOrOtherFuel || FoundType == HVAC::Coil_HeatingGas_MultiStage ||
3284 : FoundType == HVAC::Coil_HeatingDesuperheater) {
3285 834 : int WhichCoil = Util::FindItem(CoilName, state.dataHeatingCoils->HeatingCoil);
3286 834 : if (WhichCoil != 0) {
3287 834 : return state.dataHeatingCoils->HeatingCoil(WhichCoil).HCoilType_Num;
3288 : }
3289 : }
3290 :
3291 0 : ShowSevereError(state, format("GetHeatingCoilTypeNum: Could not find Coil, Type=\"{}\" Name=\"{}\"", CoilType, CoilName));
3292 0 : ErrorsFound = true;
3293 0 : return 0;
3294 : }
3295 :
3296 243 : int GetHeatingCoilIndex(EnergyPlusData &state,
3297 : std::string const &CoilType, // must match coil types in this module
3298 : std::string const &CoilName, // must match coil names for the coil type
3299 : bool &ErrorsFound // set to true if problem
3300 : )
3301 : {
3302 :
3303 : // FUNCTION INFORMATION:
3304 : // AUTHOR Linda Lawrie
3305 : // DATE WRITTEN February 2011
3306 :
3307 : // PURPOSE OF THIS FUNCTION:
3308 : // This function looks up the given coil and returns the index into the structure. If
3309 : // incorrect coil type or name is given, ErrorsFound is returned as true and index is returned
3310 : // as zero.
3311 :
3312 : // Obtains and Allocates HeatingCoil related parameters from input file
3313 243 : if (state.dataHeatingCoils->GetCoilsInputFlag) { // First time subroutine has been entered
3314 9 : GetHeatingCoilInput(state);
3315 9 : state.dataHeatingCoils->GetCoilsInputFlag = false;
3316 : }
3317 :
3318 243 : int WhichCoil = 0;
3319 243 : int FoundType = Util::FindItem(CoilType, HVAC::cAllCoilTypes, HVAC::NumAllCoilTypes);
3320 243 : if (FoundType == HVAC::Coil_HeatingElectric || FoundType == HVAC::Coil_HeatingElectric_MultiStage ||
3321 1 : FoundType == HVAC::Coil_HeatingGasOrOtherFuel || FoundType == HVAC::Coil_HeatingGas_MultiStage ||
3322 : FoundType == HVAC::Coil_HeatingDesuperheater) {
3323 243 : WhichCoil = Util::FindItem(CoilName, state.dataHeatingCoils->HeatingCoil);
3324 : }
3325 :
3326 243 : if (WhichCoil == 0) {
3327 0 : ShowSevereError(state, format("GetHeatingCoilIndex: Could not find Coil, Type=\"{}\" Name=\"{}\"", CoilType, CoilName));
3328 0 : ErrorsFound = true;
3329 : }
3330 :
3331 243 : return WhichCoil;
3332 : }
3333 :
3334 181 : int GetHeatingCoilPLFCurveIndex(EnergyPlusData &state,
3335 : std::string const &CoilType, // must match coil types in this module
3336 : std::string const &CoilName, // must match coil names for the coil type
3337 : bool &ErrorsFound // set to true if problem
3338 : )
3339 : {
3340 :
3341 : // FUNCTION INFORMATION:
3342 : // AUTHOR Richard Raustad
3343 : // DATE WRITTEN December 2008
3344 :
3345 : // PURPOSE OF THIS FUNCTION:
3346 : // This function looks up the given coil and returns the PLF curve index. If
3347 : // incorrect coil name is given for gas or electric heating coils, ErrorsFound
3348 : // is returned as true and curve index is returned as zero.
3349 : // If not a gas or electric heating coil, ErrorsFound is unchanged and index is 0.
3350 :
3351 : // Obtains and Allocates HeatingCoil related parameters from input file
3352 181 : if (state.dataHeatingCoils->GetCoilsInputFlag) { // First time subroutine has been entered
3353 0 : GetHeatingCoilInput(state);
3354 0 : state.dataHeatingCoils->GetCoilsInputFlag = false;
3355 : }
3356 :
3357 181 : int FoundType = Util::FindItem(CoilType, HVAC::cAllCoilTypes, HVAC::NumAllCoilTypes);
3358 181 : if (FoundType == HVAC::Coil_HeatingElectric || FoundType == HVAC::Coil_HeatingElectric_MultiStage ||
3359 0 : FoundType == HVAC::Coil_HeatingGasOrOtherFuel || FoundType == HVAC::Coil_HeatingGas_MultiStage ||
3360 : FoundType == HVAC::Coil_HeatingDesuperheater) {
3361 181 : int WhichCoil = Util::FindItem(CoilName, state.dataHeatingCoils->HeatingCoil);
3362 181 : if (WhichCoil != 0) {
3363 181 : return state.dataHeatingCoils->HeatingCoil(WhichCoil).PLFCurveIndex;
3364 : } else {
3365 0 : ShowSevereError(state, format("GetHeatingCoilPLFCurveIndex: Could not find Coil, Type=\"{}\" Name=\"{}\"", CoilType, CoilName));
3366 0 : ErrorsFound = true;
3367 0 : return 0;
3368 : }
3369 : } else {
3370 0 : return 0;
3371 : }
3372 : }
3373 :
3374 2 : int GetHeatingCoilNumberOfStages(EnergyPlusData &state,
3375 : std::string const &CoilType, // must match coil types in this module
3376 : std::string const &CoilName, // must match coil names for the coil type
3377 : bool &ErrorsFound // set to true if problem
3378 : )
3379 : {
3380 :
3381 : // FUNCTION INFORMATION:
3382 : // AUTHOR Chandan Sharma
3383 : // DATE WRITTEN February 2013
3384 :
3385 : // PURPOSE OF THIS FUNCTION:
3386 : // This function looks up the given coil and returns the number of speeds for multistage coils.
3387 : // If incorrect coil type or name is given, ErrorsFound is returned as true.
3388 :
3389 : // Obtains and Allocates HeatingCoils
3390 2 : if (state.dataHeatingCoils->GetCoilsInputFlag) { // First time subroutine has been entered
3391 0 : GetHeatingCoilInput(state);
3392 0 : state.dataHeatingCoils->GetCoilsInputFlag = false;
3393 : }
3394 :
3395 2 : int WhichCoil = Util::FindItemInList(CoilName, state.dataHeatingCoils->HeatingCoil);
3396 2 : if (WhichCoil != 0) {
3397 2 : return state.dataHeatingCoils->HeatingCoil(WhichCoil).NumOfStages;
3398 : } else {
3399 0 : ShowSevereError(state, format("GetHeatingCoilNumberOfSpeeds: Invalid Heating Coil Type=\"{}\" Name=\"{}\"", CoilType, CoilName));
3400 0 : ErrorsFound = true;
3401 0 : return 0;
3402 : }
3403 : }
3404 :
3405 4 : void SetHeatingCoilData(EnergyPlusData &state,
3406 : int const CoilNum, // Number of electric or gas heating Coil
3407 : bool &ErrorsFound, // Set to true if certain errors found
3408 : ObjexxFCL::Optional_bool DesiccantRegenerationCoil, // Flag that this coil is used as regeneration air heating coil
3409 : ObjexxFCL::Optional_int DesiccantDehumIndex // Index for the desiccant dehum system where this coil is used
3410 : )
3411 : {
3412 :
3413 : // FUNCTION INFORMATION:
3414 : // AUTHOR Bereket Nigusse
3415 : // DATE WRITTEN February 2016
3416 :
3417 : // PURPOSE OF THIS FUNCTION:
3418 : // This function sets data to Heating Coil using the coil index and arguments passed
3419 :
3420 4 : auto &heatingCoil = state.dataHeatingCoils->HeatingCoil(CoilNum);
3421 4 : if (state.dataHeatingCoils->GetCoilsInputFlag) {
3422 0 : GetHeatingCoilInput(state);
3423 0 : state.dataHeatingCoils->GetCoilsInputFlag = false;
3424 : }
3425 :
3426 4 : if (CoilNum <= 0 || CoilNum > state.dataHeatingCoils->NumHeatingCoils) {
3427 0 : ShowSevereError(state,
3428 0 : format("SetHeatingCoilData: called with heating coil Number out of range={} should be >0 and <{}",
3429 : CoilNum,
3430 0 : state.dataHeatingCoils->NumHeatingCoils));
3431 0 : ErrorsFound = true;
3432 0 : return;
3433 : }
3434 :
3435 4 : if (present(DesiccantRegenerationCoil)) {
3436 4 : heatingCoil.DesiccantRegenerationCoil = DesiccantRegenerationCoil;
3437 : }
3438 :
3439 4 : if (present(DesiccantDehumIndex)) {
3440 4 : heatingCoil.DesiccantDehumNum = DesiccantDehumIndex;
3441 : }
3442 : }
3443 :
3444 25 : void SetHeatingCoilAirLoopNumber(EnergyPlusData &state, std::string const &HeatingCoilName, int AirLoopNum, bool &ErrorsFound)
3445 : {
3446 : // SUBROUTINE INFORMATION:
3447 : // AUTHOR L.Gu
3448 : // DATE WRITTEN March 2018
3449 :
3450 : // PURPOSE OF THIS SUBROUTINE:
3451 : // This subroutine sets an AirLoopNum for a given heating Coil
3452 :
3453 : int HeatingCoilIndex;
3454 :
3455 25 : if (state.dataHeatingCoils->GetCoilsInputFlag) { // First time subroutine has been entered
3456 0 : GetHeatingCoilInput(state);
3457 0 : state.dataHeatingCoils->GetCoilsInputFlag = false;
3458 : }
3459 :
3460 25 : HeatingCoilIndex = Util::FindItem(HeatingCoilName, state.dataHeatingCoils->HeatingCoil);
3461 25 : if (HeatingCoilIndex == 0) {
3462 0 : ShowSevereError(state, format("GetCoilIndex: Heating coil not found={}", HeatingCoilName));
3463 0 : ErrorsFound = true;
3464 : } else {
3465 25 : state.dataHeatingCoils->HeatingCoil(HeatingCoilIndex).AirLoopNum = AirLoopNum;
3466 : }
3467 25 : }
3468 : } // namespace HeatingCoils
3469 :
3470 : } // namespace EnergyPlus
|