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