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