Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2025, The Board of Trustees of the University of Illinois,
2 : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
3 : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
4 : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
5 : // contributors. All rights reserved.
6 : //
7 : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
8 : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
9 : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
10 : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
11 : // derivative works, and perform publicly and display publicly, and to permit others to do so.
12 : //
13 : // Redistribution and use in source and binary forms, with or without modification, are permitted
14 : // provided that the following conditions are met:
15 : //
16 : // (1) Redistributions of source code must retain the above copyright notice, this list of
17 : // conditions and the following disclaimer.
18 : //
19 : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
20 : // conditions and the following disclaimer in the documentation and/or other materials
21 : // provided with the distribution.
22 : //
23 : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
24 : // the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
25 : // used to endorse or promote products derived from this software without specific prior
26 : // written permission.
27 : //
28 : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
29 : // without changes from the version obtained under this License, or (ii) Licensee makes a
30 : // reference solely to the software portion of its product, Licensee must refer to the
31 : // software as "EnergyPlus version X" software, where "X" is the version number Licensee
32 : // obtained under this License and may not use a different name for the software. Except as
33 : // specifically required in this Section (4), Licensee shall not use in a company name, a
34 : // product name, in advertising, publicity, or other promotional activities any name, trade
35 : // name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
36 : // similar designation, without the U.S. Department of Energy's prior written consent.
37 : //
38 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
39 : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
40 : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
41 : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43 : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
45 : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46 : // POSSIBILITY OF SUCH DAMAGE.
47 :
48 : // C++ Headers
49 : #include <cmath>
50 :
51 : // ObjexxFCL Headers
52 : #include <ObjexxFCL/Array.functions.hh>
53 :
54 : // EnergyPlus Headers
55 : #include <EnergyPlus/Autosizing/All_Simple_Sizing.hh>
56 : #include <EnergyPlus/Autosizing/HeatingAirFlowSizing.hh>
57 : #include <EnergyPlus/BranchNodeConnections.hh>
58 : #include <EnergyPlus/Data/EnergyPlusData.hh>
59 : #include <EnergyPlus/DataContaminantBalance.hh>
60 : #include <EnergyPlus/DataEnvironment.hh>
61 : #include <EnergyPlus/DataHVACGlobals.hh>
62 : #include <EnergyPlus/DataLoopNode.hh>
63 : #include <EnergyPlus/DataSizing.hh>
64 : #include <EnergyPlus/Fans.hh>
65 : #include <EnergyPlus/FaultsManager.hh>
66 : #include <EnergyPlus/FluidProperties.hh>
67 : #include <EnergyPlus/GeneralRoutines.hh>
68 : #include <EnergyPlus/GlobalNames.hh>
69 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
70 : #include <EnergyPlus/NodeInputManager.hh>
71 : #include <EnergyPlus/OutputProcessor.hh>
72 : #include <EnergyPlus/Plant/DataPlant.hh>
73 : #include <EnergyPlus/PlantUtilities.hh>
74 : #include <EnergyPlus/Psychrometrics.hh>
75 : #include <EnergyPlus/ReportCoilSelection.hh>
76 : #include <EnergyPlus/ScheduleManager.hh>
77 : #include <EnergyPlus/SteamCoils.hh>
78 : #include <EnergyPlus/UtilityRoutines.hh>
79 :
80 : namespace EnergyPlus {
81 :
82 : namespace SteamCoils {
83 :
84 : // Module containing the SteamCoil simulation routines
85 :
86 : // MODULE INFORMATION:
87 : // AUTHOR Rahul Chillar
88 : // DATE WRITTEN Jan 2005
89 : // MODIFIED na
90 : // RE-ENGINEERED na
91 :
92 : // PURPOSE OF THIS MODULE:
93 : // To encapsulate the data and algorithms required to
94 : // manage the SteamCoil System Component.
95 :
96 : using namespace DataLoopNode;
97 : using namespace Psychrometrics;
98 :
99 : using PlantUtilities::MyPlantSizingIndex;
100 : using PlantUtilities::ScanPlantLoopsForObject;
101 :
102 : constexpr std::array<std::string_view, static_cast<int>(CoilControlType::Num)> coilControlTypeNames = {"TEMPERATURESETPOINTCONTROL",
103 : "ZONELOADCONTROL"};
104 :
105 3 : void SimulateSteamCoilComponents(EnergyPlusData &state,
106 : std::string_view CompName,
107 : bool const FirstHVACIteration,
108 : int &CompIndex,
109 : ObjexxFCL::Optional<Real64 const> QCoilReq, // coil load to be met
110 : ObjexxFCL::Optional<Real64> QCoilActual, // coil load actually delivered returned to calling component
111 : ObjexxFCL::Optional<HVAC::FanOp const> fanOpMode,
112 : ObjexxFCL::Optional<Real64 const> PartLoadRatio)
113 : {
114 :
115 : // SUBROUTINE INFORMATION:
116 : // AUTHOR Rahul Chillar
117 : // DATE WRITTEN Jan 2005
118 : // MODIFIED na
119 : // RE-ENGINEERED na
120 :
121 : // PURPOSE OF THIS SUBROUTINE:
122 : // This subroutine manages SteamCoil component simulation.
123 :
124 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
125 : Real64 QCoilActualTemp; // coil load actually delivered returned to calling component
126 : int CoilNum; // The SteamCoil that you are currently loading input into
127 : HVAC::FanOp fanOp; // fan operating mode
128 : Real64 PartLoadFrac; // part-load fraction of heating coil
129 : Real64 QCoilReqLocal; // local required heating load optional
130 :
131 : // Obtains and Allocates SteamCoil related parameters from input file
132 3 : if (state.dataSteamCoils->GetSteamCoilsInputFlag) { // First time subroutine has been entered
133 0 : GetSteamCoilInput(state);
134 0 : state.dataSteamCoils->GetSteamCoilsInputFlag = false;
135 : }
136 :
137 : // Find the correct SteamCoilNumber with the Coil Name
138 3 : if (CompIndex == 0) {
139 0 : CoilNum = Util::FindItemInList(CompName, state.dataSteamCoils->SteamCoil);
140 0 : if (CoilNum == 0) {
141 0 : ShowFatalError(state, format("SimulateSteamCoilComponents: Coil not found={}", CompName));
142 : }
143 0 : CompIndex = CoilNum;
144 : } else {
145 3 : CoilNum = CompIndex;
146 3 : if (CoilNum > state.dataSteamCoils->NumSteamCoils || CoilNum < 1) {
147 0 : ShowFatalError(state,
148 0 : format("SimulateSteamCoilComponents: Invalid CompIndex passed={}, Number of Steam Coils={}, Coil name={}",
149 : CoilNum,
150 0 : state.dataSteamCoils->NumSteamCoils,
151 : CompName));
152 : }
153 3 : if (state.dataSteamCoils->CheckEquipName(CoilNum)) {
154 2 : if (CompName != state.dataSteamCoils->SteamCoil(CoilNum).Name) {
155 0 : ShowFatalError(
156 : state,
157 0 : format("SimulateSteamCoilComponents: Invalid CompIndex passed={}, Coil name={}, stored Coil Name for that index={}",
158 : CoilNum,
159 : CompName,
160 0 : state.dataSteamCoils->SteamCoil(CoilNum).Name));
161 : }
162 2 : state.dataSteamCoils->CheckEquipName(CoilNum) = false;
163 : }
164 : }
165 :
166 : // With the correct CoilNum Initialize
167 3 : InitSteamCoil(state, CoilNum, FirstHVACIteration); // Initialize all SteamCoil related parameters
168 :
169 3 : if (present(fanOpMode)) {
170 2 : fanOp = fanOpMode;
171 : } else {
172 1 : fanOp = HVAC::FanOp::Continuous;
173 : }
174 3 : if (present(PartLoadRatio)) {
175 2 : PartLoadFrac = PartLoadRatio;
176 : } else {
177 1 : PartLoadFrac = 1.0;
178 : }
179 3 : if (present(QCoilReq)) {
180 2 : QCoilReqLocal = QCoilReq;
181 : } else {
182 1 : QCoilReqLocal = 0.0;
183 : }
184 :
185 3 : CalcSteamAirCoil(
186 : state, CoilNum, QCoilReqLocal, QCoilActualTemp, fanOp, PartLoadFrac); // Autodesk:OPTIONAL QCoilReq used without PRESENT check
187 3 : if (present(QCoilActual)) {
188 2 : QCoilActual = QCoilActualTemp;
189 : }
190 :
191 : // Update the current SteamCoil to the outlet nodes
192 3 : UpdateSteamCoil(state, CoilNum);
193 :
194 : // Report the current SteamCoil
195 3 : ReportSteamCoil(state, CoilNum);
196 3 : }
197 :
198 : // Get Input Section of the Module
199 :
200 2 : void GetSteamCoilInput(EnergyPlusData &state)
201 : {
202 : // SUBROUTINE INFORMATION:
203 : // AUTHOR Rahul Chillar
204 : // DATE WRITTEN Jan 2005
205 : // MODIFIED na
206 : // RE-ENGINEERED na
207 :
208 : // PURPOSE OF THIS SUBROUTINE:
209 : // Obtains input data for coils and stores it in coil data structures
210 :
211 : // METHODOLOGY EMPLOYED:
212 : // Uses "Get" routines to read in data.
213 :
214 : // Using/Aliasing
215 : using BranchNodeConnections::TestCompSet;
216 : using GlobalNames::VerifyUniqueCoilName;
217 : using NodeInputManager::GetOnlySingleNode;
218 :
219 : // SUBROUTINE PARAMETER DEFINITIONS:
220 : static constexpr std::string_view RoutineName("GetSteamCoilInput: "); // include trailing blank space
221 : static constexpr std::string_view routineName = "GetSteamCoilInput";
222 :
223 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
224 : int CoilNum; // The SteamCoil that you are currently loading input into
225 : int NumStmHeat;
226 : int StmHeatNum;
227 : int NumAlphas;
228 : int NumNums;
229 : int IOStat;
230 2 : bool ErrorsFound(false); // If errors detected in input
231 2 : std::string CurrentModuleObject; // for ease in getting objects
232 2 : Array1D_string AlphArray; // Alpha input items for object
233 2 : Array1D_string cAlphaFields; // Alpha field names
234 2 : Array1D_string cNumericFields; // Numeric field names
235 2 : Array1D<Real64> NumArray; // Numeric input items for object
236 2 : Array1D_bool lAlphaBlanks; // Logical array, alpha field input BLANK = .TRUE.
237 2 : Array1D_bool lNumericBlanks; // Logical array, numeric field input BLANK = .TRUE.
238 2 : int TotalArgs(0); // Total number of alpha and numeric arguments (max) for a
239 : // certain object in the input file
240 :
241 2 : CurrentModuleObject = "Coil:Heating:Steam";
242 2 : NumStmHeat = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
243 2 : state.dataSteamCoils->NumSteamCoils = NumStmHeat;
244 2 : if (state.dataSteamCoils->NumSteamCoils > 0) {
245 2 : state.dataSteamCoils->SteamCoil.allocate(state.dataSteamCoils->NumSteamCoils);
246 2 : state.dataSteamCoils->CheckEquipName.dimension(state.dataSteamCoils->NumSteamCoils, true);
247 : }
248 :
249 2 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, TotalArgs, NumAlphas, NumNums);
250 2 : AlphArray.allocate(NumAlphas);
251 2 : cAlphaFields.allocate(NumAlphas);
252 2 : cNumericFields.allocate(NumNums);
253 2 : NumArray.dimension(NumNums, 0.0);
254 2 : lAlphaBlanks.dimension(NumAlphas, true);
255 2 : lNumericBlanks.dimension(NumNums, true);
256 :
257 : // Get the data for steam heating coils
258 4 : for (StmHeatNum = 1; StmHeatNum <= NumStmHeat; ++StmHeatNum) {
259 :
260 2 : CoilNum = StmHeatNum;
261 :
262 2 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
263 : CurrentModuleObject,
264 : StmHeatNum,
265 : AlphArray,
266 : NumAlphas,
267 : NumArray,
268 : NumNums,
269 : IOStat,
270 : lNumericBlanks,
271 : lAlphaBlanks,
272 : cAlphaFields,
273 : cNumericFields);
274 :
275 2 : ErrorObjectHeader eoh{routineName, CurrentModuleObject, AlphArray(1)};
276 2 : Util::IsNameEmpty(state, AlphArray(1), CurrentModuleObject, ErrorsFound);
277 :
278 : // ErrorsFound will be set to True if problem was found, left untouched otherwise
279 2 : VerifyUniqueCoilName(state, CurrentModuleObject, AlphArray(1), ErrorsFound, CurrentModuleObject + " Name");
280 :
281 2 : state.dataSteamCoils->SteamCoil(CoilNum).Name = AlphArray(1);
282 :
283 2 : if (lAlphaBlanks(2)) {
284 0 : state.dataSteamCoils->SteamCoil(CoilNum).availSched = Sched::GetScheduleAlwaysOn(state);
285 2 : } else if ((state.dataSteamCoils->SteamCoil(CoilNum).availSched = Sched::GetSchedule(state, AlphArray(2))) == nullptr) {
286 0 : ShowSevereItemNotFound(state, eoh, cAlphaFields(2), AlphArray(2));
287 0 : ErrorsFound = true;
288 : }
289 :
290 2 : state.dataSteamCoils->SteamCoil(CoilNum).SteamCoilTypeA = "Heating";
291 2 : state.dataSteamCoils->SteamCoil(CoilNum).CoilType = DataPlant::PlantEquipmentType::CoilSteamAirHeating;
292 2 : state.dataSteamCoils->SteamCoil(CoilNum).MaxSteamVolFlowRate = NumArray(1);
293 2 : state.dataSteamCoils->SteamCoil(CoilNum).DegOfSubcooling = NumArray(2);
294 2 : state.dataSteamCoils->SteamCoil(CoilNum).LoopSubcoolReturn = NumArray(3);
295 :
296 4 : state.dataSteamCoils->SteamCoil(CoilNum).SteamInletNodeNum = GetOnlySingleNode(state,
297 2 : AlphArray(3),
298 : ErrorsFound,
299 : DataLoopNode::ConnectionObjectType::CoilHeatingSteam,
300 2 : AlphArray(1),
301 : DataLoopNode::NodeFluidType::Steam,
302 : DataLoopNode::ConnectionType::Inlet,
303 : NodeInputManager::CompFluidStream::Secondary,
304 : ObjectIsNotParent);
305 4 : state.dataSteamCoils->SteamCoil(CoilNum).SteamOutletNodeNum = GetOnlySingleNode(state,
306 2 : AlphArray(4),
307 : ErrorsFound,
308 : DataLoopNode::ConnectionObjectType::CoilHeatingSteam,
309 2 : AlphArray(1),
310 : DataLoopNode::NodeFluidType::Steam,
311 : DataLoopNode::ConnectionType::Outlet,
312 : NodeInputManager::CompFluidStream::Secondary,
313 : ObjectIsNotParent);
314 4 : state.dataSteamCoils->SteamCoil(CoilNum).AirInletNodeNum = GetOnlySingleNode(state,
315 2 : AlphArray(5),
316 : ErrorsFound,
317 : DataLoopNode::ConnectionObjectType::CoilHeatingSteam,
318 2 : AlphArray(1),
319 : DataLoopNode::NodeFluidType::Air,
320 : DataLoopNode::ConnectionType::Inlet,
321 : NodeInputManager::CompFluidStream::Primary,
322 : ObjectIsNotParent);
323 4 : state.dataSteamCoils->SteamCoil(CoilNum).AirOutletNodeNum = GetOnlySingleNode(state,
324 2 : AlphArray(6),
325 : ErrorsFound,
326 : DataLoopNode::ConnectionObjectType::CoilHeatingSteam,
327 2 : AlphArray(1),
328 : DataLoopNode::NodeFluidType::Air,
329 : DataLoopNode::ConnectionType::Outlet,
330 : NodeInputManager::CompFluidStream::Primary,
331 : ObjectIsNotParent);
332 :
333 2 : std::string controlMode = Util::makeUPPER(AlphArray(7));
334 2 : state.dataSteamCoils->SteamCoil(CoilNum).TypeOfCoil = static_cast<CoilControlType>(getEnumValue(coilControlTypeNames, controlMode));
335 :
336 2 : switch (state.dataSteamCoils->SteamCoil(CoilNum).TypeOfCoil) {
337 0 : case CoilControlType::TemperatureSetPoint:
338 0 : state.dataSteamCoils->SteamCoil(CoilNum).TempSetPointNodeNum = GetOnlySingleNode(state,
339 0 : AlphArray(8),
340 : ErrorsFound,
341 : DataLoopNode::ConnectionObjectType::CoilHeatingSteam,
342 0 : AlphArray(1),
343 : DataLoopNode::NodeFluidType::Air,
344 : DataLoopNode::ConnectionType::Sensor,
345 : NodeInputManager::CompFluidStream::Primary,
346 : ObjectIsNotParent);
347 0 : if (state.dataSteamCoils->SteamCoil(CoilNum).TempSetPointNodeNum == 0) {
348 0 : ShowSevereError(state, format("{}{} not found for {} = {}", RoutineName, cAlphaFields(8), CurrentModuleObject, AlphArray(1)));
349 0 : ShowContinueError(state, "..required for Temperature Setpoint Controlled Coils.");
350 0 : ErrorsFound = true;
351 : }
352 0 : break;
353 2 : case CoilControlType::ZoneLoadControl:
354 2 : if (!lAlphaBlanks(8)) {
355 0 : ShowWarningError(state, format("{}ZoneLoad Controlled Coil, so {} not needed", RoutineName, cAlphaFields(8)));
356 0 : ShowContinueError(state, format("for {} = {}", CurrentModuleObject, AlphArray(1)));
357 0 : state.dataSteamCoils->SteamCoil(CoilNum).TempSetPointNodeNum = 0;
358 : }
359 2 : break;
360 0 : default:
361 0 : ShowSevereError(
362 : state,
363 0 : format("{}Invalid {} [{}] specified for {} = {}", RoutineName, cAlphaFields(7), AlphArray(7), CurrentModuleObject, AlphArray(1)));
364 0 : ErrorsFound = true;
365 : }
366 :
367 4 : TestCompSet(state, CurrentModuleObject, AlphArray(1), AlphArray(3), AlphArray(4), "Steam Nodes");
368 2 : TestCompSet(state, CurrentModuleObject, AlphArray(1), AlphArray(5), AlphArray(6), "Air Nodes");
369 :
370 2 : state.dataSteamCoils->SteamCoil(CoilNum).steam = Fluid::GetSteam(state);
371 2 : if (state.dataSteamCoils->SteamCoil(CoilNum).steam == nullptr && CoilNum == 1) {
372 0 : ShowSevereError(state, format("{}Steam Properties for {} not found.", RoutineName, AlphArray(1)));
373 0 : ShowContinueError(state, "Steam Fluid Properties should have been included in the input file.");
374 0 : ErrorsFound = true;
375 : }
376 2 : }
377 :
378 4 : for (CoilNum = 1; CoilNum <= NumStmHeat; ++CoilNum) {
379 :
380 : // Setup the Simple Heating Coil reporting variables
381 : // CurrentModuleObject = "Coil:Heating:Steam"
382 4 : SetupOutputVariable(state,
383 : "Heating Coil Heating Energy",
384 : Constant::Units::J,
385 2 : state.dataSteamCoils->SteamCoil(CoilNum).TotSteamHeatingCoilEnergy,
386 : OutputProcessor::TimeStepType::System,
387 : OutputProcessor::StoreType::Sum,
388 2 : state.dataSteamCoils->SteamCoil(CoilNum).Name,
389 : Constant::eResource::EnergyTransfer,
390 : OutputProcessor::Group::HVAC,
391 : OutputProcessor::EndUseCat::HeatingCoils);
392 4 : SetupOutputVariable(state,
393 : "Heating Coil Heating Rate",
394 : Constant::Units::W,
395 2 : state.dataSteamCoils->SteamCoil(CoilNum).TotSteamHeatingCoilRate,
396 : OutputProcessor::TimeStepType::System,
397 : OutputProcessor::StoreType::Average,
398 2 : state.dataSteamCoils->SteamCoil(CoilNum).Name);
399 4 : SetupOutputVariable(state,
400 : "Heating Coil Steam Mass Flow Rate",
401 : Constant::Units::kg_s,
402 2 : state.dataSteamCoils->SteamCoil(CoilNum).OutletSteamMassFlowRate,
403 : OutputProcessor::TimeStepType::System,
404 : OutputProcessor::StoreType::Average,
405 2 : state.dataSteamCoils->SteamCoil(CoilNum).Name);
406 4 : SetupOutputVariable(state,
407 : "Heating Coil Steam Inlet Temperature",
408 : Constant::Units::C,
409 2 : state.dataSteamCoils->SteamCoil(CoilNum).InletSteamTemp,
410 : OutputProcessor::TimeStepType::System,
411 : OutputProcessor::StoreType::Average,
412 2 : state.dataSteamCoils->SteamCoil(CoilNum).Name);
413 4 : SetupOutputVariable(state,
414 : "Heating Coil Steam Outlet Temperature",
415 : Constant::Units::C,
416 2 : state.dataSteamCoils->SteamCoil(CoilNum).OutletSteamTemp,
417 : OutputProcessor::TimeStepType::System,
418 : OutputProcessor::StoreType::Average,
419 2 : state.dataSteamCoils->SteamCoil(CoilNum).Name);
420 4 : SetupOutputVariable(state,
421 : "Heating Coil Steam Trap Loss Rate",
422 : Constant::Units::W,
423 2 : state.dataSteamCoils->SteamCoil(CoilNum).LoopLoss,
424 : OutputProcessor::TimeStepType::System,
425 : OutputProcessor::StoreType::Average,
426 2 : state.dataSteamCoils->SteamCoil(CoilNum).Name);
427 : }
428 :
429 2 : if (ErrorsFound) {
430 0 : ShowFatalError(state, format("{}Errors found in getting input.", RoutineName));
431 : }
432 :
433 2 : AlphArray.deallocate();
434 2 : cAlphaFields.deallocate();
435 2 : cNumericFields.deallocate();
436 2 : NumArray.deallocate();
437 2 : lAlphaBlanks.deallocate();
438 2 : lNumericBlanks.deallocate();
439 2 : }
440 :
441 : // End of Get Input subroutines for the HB Module
442 :
443 : // Beginning Initialization Section of the Module
444 :
445 3 : void InitSteamCoil(EnergyPlusData &state, int const CoilNum, bool const FirstHVACIteration)
446 : {
447 : // SUBROUTINE INFORMATION:
448 : // AUTHOR Rahul Chillar
449 : // DATE WRITTEN Jan 2005
450 : // MODIFIED na
451 : // RE-ENGINEERED na
452 :
453 : // PURPOSE OF THIS SUBROUTINE:
454 : // This subroutine is for initializations of the SteamCoil Components.
455 :
456 : // METHODOLOGY EMPLOYED:
457 : // Uses the status flags to trigger initializations.
458 :
459 : // REFERENCES:
460 : // na
461 :
462 : // Using/Aliasing
463 : using PlantUtilities::InitComponentNodes;
464 :
465 : // Locals
466 : // SUBROUTINE ARGUMENT DEFINITIONS:
467 :
468 : // SUBROUTINE PARAMETER DEFINITIONS:
469 : static constexpr std::string_view RoutineName("InitSteamCoil");
470 :
471 : // INTERFACE BLOCK SPECIFICATIONS
472 : // na
473 :
474 : // DERIVED TYPE DEFINITIONS
475 : // na
476 :
477 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
478 : int AirInletNode;
479 : int SteamInletNode;
480 : int ControlNode;
481 : int AirOutletNode;
482 : Real64 SteamDensity;
483 : Real64 StartEnthSteam;
484 : bool errFlag;
485 :
486 3 : if (state.dataSteamCoils->MyOneTimeFlag) {
487 : // initialize the environment and sizing flags
488 2 : state.dataSteamCoils->MyEnvrnFlag.dimension(state.dataSteamCoils->NumSteamCoils, true);
489 2 : state.dataSteamCoils->MySizeFlag.dimension(state.dataSteamCoils->NumSteamCoils, true);
490 2 : state.dataSteamCoils->CoilWarningOnceFlag.dimension(state.dataSteamCoils->NumSteamCoils, true);
491 2 : state.dataSteamCoils->MyPlantScanFlag.dimension(state.dataSteamCoils->NumSteamCoils, true);
492 2 : state.dataSteamCoils->MyOneTimeFlag = false;
493 : }
494 :
495 3 : if (state.dataSteamCoils->MyPlantScanFlag(CoilNum) && allocated(state.dataPlnt->PlantLoop)) {
496 2 : errFlag = false;
497 4 : ScanPlantLoopsForObject(state,
498 2 : state.dataSteamCoils->SteamCoil(CoilNum).Name,
499 2 : state.dataSteamCoils->SteamCoil(CoilNum).CoilType,
500 2 : state.dataSteamCoils->SteamCoil(CoilNum).plantLoc,
501 : errFlag,
502 : _,
503 : _,
504 : _,
505 : _,
506 : _);
507 2 : if (errFlag) {
508 0 : ShowFatalError(state, "InitSteamCoil: Program terminated for previous conditions.");
509 : }
510 2 : state.dataSteamCoils->MyPlantScanFlag(CoilNum) = false;
511 : }
512 :
513 3 : if (!state.dataGlobal->SysSizingCalc && state.dataSteamCoils->MySizeFlag(CoilNum)) {
514 : // for each coil, do the sizing once.
515 1 : SizeSteamCoil(state, CoilNum);
516 1 : state.dataSteamCoils->MySizeFlag(CoilNum) = false;
517 : }
518 :
519 : // Do the Begin Environment initializations
520 3 : if (state.dataGlobal->BeginEnvrnFlag && state.dataSteamCoils->MyEnvrnFlag(CoilNum)) {
521 : // Initialize all report variables to a known state at beginning of simulation
522 2 : state.dataSteamCoils->SteamCoil(CoilNum).TotSteamHeatingCoilEnergy = 0.0;
523 2 : state.dataSteamCoils->SteamCoil(CoilNum).TotSteamCoolingCoilEnergy = 0.0;
524 2 : state.dataSteamCoils->SteamCoil(CoilNum).SenSteamCoolingCoilEnergy = 0.0;
525 2 : state.dataSteamCoils->SteamCoil(CoilNum).TotSteamHeatingCoilRate = 0.0;
526 2 : state.dataSteamCoils->SteamCoil(CoilNum).TotSteamCoolingCoilRate = 0.0;
527 2 : state.dataSteamCoils->SteamCoil(CoilNum).SenSteamCoolingCoilRate = 0.0;
528 : // Initialize other module level variables
529 2 : state.dataSteamCoils->SteamCoil(CoilNum).InletAirMassFlowRate = 0.0;
530 2 : state.dataSteamCoils->SteamCoil(CoilNum).OutletAirMassFlowRate = 0.0;
531 2 : state.dataSteamCoils->SteamCoil(CoilNum).InletAirTemp = 0.0;
532 2 : state.dataSteamCoils->SteamCoil(CoilNum).OutletAirTemp = 0.0;
533 2 : state.dataSteamCoils->SteamCoil(CoilNum).InletAirHumRat = 0.0;
534 2 : state.dataSteamCoils->SteamCoil(CoilNum).OutletAirHumRat = 0.0;
535 2 : state.dataSteamCoils->SteamCoil(CoilNum).InletAirEnthalpy = 0.0;
536 2 : state.dataSteamCoils->SteamCoil(CoilNum).OutletAirEnthalpy = 0.0;
537 2 : state.dataSteamCoils->SteamCoil(CoilNum).TotSteamCoilLoad = 0.0;
538 2 : state.dataSteamCoils->SteamCoil(CoilNum).SenSteamCoilLoad = 0.0;
539 2 : state.dataSteamCoils->SteamCoil(CoilNum).LoopLoss = 0.0;
540 2 : state.dataSteamCoils->SteamCoil(CoilNum).LeavingRelHum = 0.0;
541 2 : state.dataSteamCoils->SteamCoil(CoilNum).DesiredOutletTemp = 0.0;
542 2 : state.dataSteamCoils->SteamCoil(CoilNum).DesiredOutletHumRat = 0.0;
543 2 : state.dataSteamCoils->SteamCoil(CoilNum).InletSteamTemp = 0.0;
544 2 : state.dataSteamCoils->SteamCoil(CoilNum).OutletSteamTemp = 0.0;
545 2 : state.dataSteamCoils->SteamCoil(CoilNum).InletSteamMassFlowRate = 0.0;
546 2 : state.dataSteamCoils->SteamCoil(CoilNum).OutletSteamMassFlowRate = 0.0;
547 2 : state.dataSteamCoils->SteamCoil(CoilNum).InletSteamEnthalpy = 0.0;
548 2 : state.dataSteamCoils->SteamCoil(CoilNum).OutletWaterEnthalpy = 0.0;
549 2 : state.dataSteamCoils->SteamCoil(CoilNum).InletSteamPress = 0.0;
550 2 : state.dataSteamCoils->SteamCoil(CoilNum).InletSteamQuality = 0.0;
551 2 : state.dataSteamCoils->SteamCoil(CoilNum).OutletSteamQuality = 0.0;
552 :
553 : // More Environment initializations
554 2 : AirInletNode = state.dataSteamCoils->SteamCoil(CoilNum).AirInletNodeNum;
555 2 : SteamInletNode = state.dataSteamCoils->SteamCoil(CoilNum).SteamInletNodeNum;
556 2 : ControlNode = state.dataSteamCoils->SteamCoil(CoilNum).TempSetPointNodeNum;
557 2 : AirOutletNode = state.dataSteamCoils->SteamCoil(CoilNum).AirOutletNodeNum;
558 :
559 2 : state.dataLoopNodes->Node(SteamInletNode).Temp = 100.0;
560 2 : state.dataLoopNodes->Node(SteamInletNode).Press = 101325.0;
561 2 : auto *steam = Fluid::GetSteam(state);
562 2 : SteamDensity = steam->getSatDensity(state, state.dataLoopNodes->Node(SteamInletNode).Temp, 1.0, RoutineName);
563 2 : StartEnthSteam = steam->getSatEnthalpy(state, state.dataLoopNodes->Node(SteamInletNode).Temp, 1.0, RoutineName);
564 2 : state.dataLoopNodes->Node(SteamInletNode).Enthalpy = StartEnthSteam;
565 2 : state.dataLoopNodes->Node(SteamInletNode).Quality = 1.0;
566 2 : state.dataLoopNodes->Node(SteamInletNode).HumRat = 0.0;
567 2 : state.dataSteamCoils->SteamCoil(CoilNum).MaxSteamMassFlowRate =
568 2 : SteamDensity * state.dataSteamCoils->SteamCoil(CoilNum).MaxSteamVolFlowRate;
569 : // Node(SteamInletNode)%MassFlowRate = SteamCoil(CoilNum)%MaxSteamMassFlowRate
570 : // Node(SteamInletNode)%MassFlowRateMinAvail = 0.0
571 : // Node(SteamInletNode)%MassFlowRateMaxAvail = SteamCoil(CoilNum)%MaxSteamMassFlowRate
572 6 : InitComponentNodes(state,
573 : 0.0,
574 2 : state.dataSteamCoils->SteamCoil(CoilNum).MaxSteamMassFlowRate,
575 2 : state.dataSteamCoils->SteamCoil(CoilNum).SteamInletNodeNum,
576 2 : state.dataSteamCoils->SteamCoil(CoilNum).SteamOutletNodeNum);
577 2 : state.dataSteamCoils->MyEnvrnFlag(CoilNum) = false;
578 : } // End If for the Begin Environment initializations
579 :
580 3 : if (!state.dataGlobal->BeginEnvrnFlag) {
581 0 : state.dataSteamCoils->MyEnvrnFlag(CoilNum) = true;
582 : }
583 :
584 : // Do the Begin Day initializations
585 : // NONE
586 :
587 : // Do the begin HVAC time step initializations
588 : // NONE
589 :
590 : // Do the following initializations (every time step): This should be the info from
591 : // the previous components outlets or the node data in this section.
592 :
593 3 : AirInletNode = state.dataSteamCoils->SteamCoil(CoilNum).AirInletNodeNum;
594 3 : SteamInletNode = state.dataSteamCoils->SteamCoil(CoilNum).SteamInletNodeNum;
595 3 : ControlNode = state.dataSteamCoils->SteamCoil(CoilNum).TempSetPointNodeNum;
596 3 : AirOutletNode = state.dataSteamCoils->SteamCoil(CoilNum).AirOutletNodeNum;
597 :
598 : // First set the conditions for the air into the coil model
599 :
600 : // If a temperature setpoint controlled coil must set the desired outlet temp everytime
601 3 : if (ControlNode == 0) {
602 3 : state.dataSteamCoils->SteamCoil(CoilNum).DesiredOutletTemp = 0.0;
603 0 : } else if (ControlNode == AirOutletNode) {
604 0 : state.dataSteamCoils->SteamCoil(CoilNum).DesiredOutletTemp = state.dataLoopNodes->Node(ControlNode).TempSetPoint;
605 : } else {
606 0 : state.dataSteamCoils->SteamCoil(CoilNum).DesiredOutletTemp =
607 0 : state.dataLoopNodes->Node(ControlNode).TempSetPoint -
608 0 : (state.dataLoopNodes->Node(ControlNode).Temp - state.dataLoopNodes->Node(AirOutletNode).Temp);
609 : }
610 :
611 3 : state.dataSteamCoils->SteamCoil(CoilNum).InletAirMassFlowRate = state.dataLoopNodes->Node(AirInletNode).MassFlowRate;
612 3 : state.dataSteamCoils->SteamCoil(CoilNum).InletAirTemp = state.dataLoopNodes->Node(AirInletNode).Temp;
613 3 : state.dataSteamCoils->SteamCoil(CoilNum).InletAirHumRat = state.dataLoopNodes->Node(AirInletNode).HumRat;
614 3 : state.dataSteamCoils->SteamCoil(CoilNum).InletAirEnthalpy = state.dataLoopNodes->Node(AirInletNode).Enthalpy;
615 3 : if (FirstHVACIteration) {
616 3 : state.dataSteamCoils->SteamCoil(CoilNum).InletSteamMassFlowRate = state.dataSteamCoils->SteamCoil(CoilNum).MaxSteamMassFlowRate;
617 : } else {
618 0 : state.dataSteamCoils->SteamCoil(CoilNum).InletSteamMassFlowRate = state.dataLoopNodes->Node(SteamInletNode).MassFlowRate;
619 : }
620 3 : state.dataSteamCoils->SteamCoil(CoilNum).InletSteamTemp = state.dataLoopNodes->Node(SteamInletNode).Temp;
621 3 : state.dataSteamCoils->SteamCoil(CoilNum).InletSteamEnthalpy = state.dataLoopNodes->Node(SteamInletNode).Enthalpy;
622 3 : state.dataSteamCoils->SteamCoil(CoilNum).InletSteamPress = state.dataLoopNodes->Node(SteamInletNode).Press;
623 3 : state.dataSteamCoils->SteamCoil(CoilNum).InletSteamQuality = state.dataLoopNodes->Node(SteamInletNode).Quality;
624 3 : state.dataSteamCoils->SteamCoil(CoilNum).TotSteamHeatingCoilRate = 0.0;
625 3 : state.dataSteamCoils->SteamCoil(CoilNum).TotSteamCoolingCoilRate = 0.0;
626 3 : state.dataSteamCoils->SteamCoil(CoilNum).SenSteamCoolingCoilRate = 0.0;
627 : // Node(SteamInletNode)%MassFlowRateMaxAvail = MIN(Node(SteamInletNode)%MassFlowRateMaxAvail,&
628 : // SteamCoil(CoilNum)%MaxSteamMassFlowRate)
629 3 : }
630 :
631 1 : void SizeSteamCoil(EnergyPlusData &state, int const CoilNum)
632 : {
633 : // SUBROUTINE INFORMATION:
634 : // AUTHOR Rahul Chillar
635 : // DATE WRITTEN Jan 2005
636 : // MODIFIED na
637 : // RE-ENGINEERED na
638 :
639 : // PURPOSE OF THIS SUBROUTINE:
640 : // This subroutine is for sizing Steam Coil Components for which flow rates have not been
641 : // specified in the input.
642 :
643 : // METHODOLOGY EMPLOYED:
644 : // Obtains flow rates from the zone or system sizing arrays and plant sizing data.
645 :
646 : // Using/Aliasing
647 : using namespace DataSizing;
648 : using PlantUtilities::RegisterPlantCompDesignFlow;
649 :
650 : // SUBROUTINE PARAMETER DEFINITIONS:
651 : static constexpr std::string_view RoutineName("SizeSteamCoil");
652 :
653 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
654 : int PltSizNum; // do loop index for plant sizing
655 : int PltSizSteamNum; // index of plant sizing object for 1st steam loop
656 : bool ErrorsFound; // If errors detected in input
657 : Real64 CoilInTemp;
658 : Real64 CoilOutTemp;
659 : Real64 CoilOutHumRat;
660 : Real64 CoilInHumRat;
661 : Real64 DesCoilLoad;
662 : Real64 DesMassFlow;
663 : Real64 DesVolFlow;
664 : Real64 MinFlowFrac;
665 : Real64 OutAirFrac;
666 1 : Real64 TempSteamIn(100.0);
667 : Real64 EnthSteamInDry;
668 : Real64 EnthSteamOutWet;
669 : Real64 LatentHeatSteam;
670 : Real64 SteamDensity;
671 : Real64 RhoAirStd; // density of air at standard conditions
672 : Real64 CpAirStd; // specific heat of air at std conditions
673 : Real64 CpWater; // specific heat of water (condensed steam)
674 :
675 1 : std::string CompName; // component name
676 1 : std::string CompType; // component type
677 1 : std::string SizingString; // input field sizing description (e.g., Nominal Capacity)
678 1 : bool bPRINT = false; // TRUE if sizing is reported to output (eio)
679 : Real64 TempSize; // autosized value
680 :
681 1 : ErrorsFound = false;
682 1 : PltSizSteamNum = 0;
683 1 : PltSizNum = 0;
684 1 : CoilInTemp = 0.0;
685 1 : CoilInHumRat = 0.0;
686 1 : CoilOutTemp = 0.0;
687 1 : DesCoilLoad = 0.0;
688 1 : MinFlowFrac = 0.0;
689 1 : DesMassFlow = 0.0;
690 1 : DesVolFlow = 0.0;
691 1 : CpWater = 0.0;
692 1 : RhoAirStd = PsyRhoAirFnPbTdbW(state, state.dataEnvrn->StdBaroPress, 20.0, 0.0);
693 1 : CpAirStd = PsyCpAirFnW(0.0);
694 1 : bool coilWasAutosized(false); // coil report
695 :
696 1 : auto &OASysEqSizing = state.dataSize->OASysEqSizing;
697 1 : auto &TermUnitSizing = state.dataSize->TermUnitSizing;
698 :
699 : // If this is a steam coil
700 : // Find the appropriate steam Plant Sizing object
701 1 : if (state.dataSteamCoils->SteamCoil(CoilNum).MaxSteamVolFlowRate == AutoSize) {
702 1 : coilWasAutosized = true; // coil report
703 1 : PltSizSteamNum = MyPlantSizingIndex(state,
704 : "steam heating coil",
705 1 : state.dataSteamCoils->SteamCoil(CoilNum).Name,
706 1 : state.dataSteamCoils->SteamCoil(CoilNum).SteamInletNodeNum,
707 1 : state.dataSteamCoils->SteamCoil(CoilNum).SteamOutletNodeNum,
708 : ErrorsFound);
709 : }
710 :
711 1 : if (PltSizSteamNum > 0) {
712 : // If this is a central air system heating coil
713 1 : if (state.dataSize->CurSysNum > 0) {
714 0 : auto &finalSysSizing = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum);
715 :
716 : // If the coil water volume flow rate needs autosizing, then do it
717 0 : if (state.dataSteamCoils->SteamCoil(CoilNum).MaxSteamVolFlowRate == AutoSize) {
718 0 : CheckSysSizing(state, "Coil:Heating:Steam", state.dataSteamCoils->SteamCoil(CoilNum).Name);
719 :
720 0 : if (state.dataSteamCoils->SteamCoil(CoilNum).DesiccantRegenerationCoil) {
721 :
722 0 : state.dataSize->DataDesicRegCoil = true;
723 0 : state.dataSize->DataDesicDehumNum = state.dataSteamCoils->SteamCoil(CoilNum).DesiccantDehumNum;
724 0 : CompType = state.dataSteamCoils->SteamCoil(CoilNum).SteamCoilType; // this is casting an int to a string
725 0 : CompName = state.dataSteamCoils->SteamCoil(CoilNum).Name;
726 0 : bPRINT = false;
727 0 : HeatingCoilDesAirInletTempSizer sizerHeatingDesInletTemp;
728 0 : bool ErrorsFound = false;
729 0 : sizerHeatingDesInletTemp.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
730 0 : state.dataSize->DataDesInletAirTemp = sizerHeatingDesInletTemp.size(state, DataSizing::AutoSize, ErrorsFound);
731 :
732 0 : HeatingCoilDesAirOutletTempSizer sizerHeatingDesOutletTemp;
733 0 : ErrorsFound = false;
734 0 : sizerHeatingDesOutletTemp.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
735 0 : state.dataSize->DataDesOutletAirTemp = sizerHeatingDesOutletTemp.size(state, DataSizing::AutoSize, ErrorsFound);
736 :
737 0 : if (state.dataSize->CurOASysNum > 0) {
738 0 : OASysEqSizing(state.dataSize->CurOASysNum).AirFlow = true;
739 0 : OASysEqSizing(state.dataSize->CurOASysNum).AirVolFlow = finalSysSizing.DesOutAirVolFlow;
740 : }
741 0 : TempSize = AutoSize; // reset back
742 0 : }
743 :
744 : // Set the duct flow rate
745 0 : switch (state.dataSize->CurDuctType) {
746 0 : case HVAC::AirDuctType::Main:
747 0 : DesVolFlow = finalSysSizing.SysAirMinFlowRat * finalSysSizing.DesMainVolFlow;
748 0 : break;
749 0 : case HVAC::AirDuctType::Cooling:
750 0 : DesVolFlow = finalSysSizing.SysAirMinFlowRat * finalSysSizing.DesCoolVolFlow;
751 0 : break;
752 0 : case HVAC::AirDuctType::Heating:
753 0 : DesVolFlow = finalSysSizing.DesHeatVolFlow;
754 0 : break;
755 0 : case HVAC::AirDuctType::Other:
756 0 : DesVolFlow = finalSysSizing.DesMainVolFlow;
757 0 : break;
758 0 : default:
759 0 : DesVolFlow = finalSysSizing.DesMainVolFlow;
760 : }
761 0 : if (state.dataSize->DataDesicRegCoil) {
762 0 : bPRINT = false;
763 0 : TempSize = AutoSize;
764 0 : bool errorsFound = false;
765 0 : HeatingAirFlowSizer sizingHeatingAirFlow;
766 0 : sizingHeatingAirFlow.overrideSizingString(SizingString);
767 : // sizingHeatingAirFlow.setHVACSizingIndexData(FanCoil(FanCoilNum).HVACSizingIndex);
768 0 : sizingHeatingAirFlow.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
769 0 : DesVolFlow = sizingHeatingAirFlow.size(state, TempSize, errorsFound);
770 0 : }
771 0 : DesMassFlow = RhoAirStd * DesVolFlow;
772 : // get the outside air fraction
773 0 : if (finalSysSizing.HeatOAOption == DataSizing::OAControl::MinOA) {
774 0 : if (DesVolFlow > 0.0) {
775 0 : OutAirFrac = finalSysSizing.DesOutAirVolFlow / DesVolFlow;
776 : } else {
777 0 : OutAirFrac = 1.0;
778 : }
779 0 : OutAirFrac = min(1.0, max(0.0, OutAirFrac));
780 : } else {
781 0 : OutAirFrac = 1.0;
782 : }
783 :
784 0 : if (state.dataSize->DataDesicRegCoil) {
785 0 : DesCoilLoad = CpAirStd * DesMassFlow * (state.dataSize->DataDesOutletAirTemp - state.dataSize->DataDesInletAirTemp);
786 : } else {
787 : // mixed air temp
788 0 : CoilInTemp = OutAirFrac * finalSysSizing.HeatOutTemp + (1.0 - OutAirFrac) * finalSysSizing.HeatRetTemp;
789 : // coil load
790 0 : DesCoilLoad = CpAirStd * DesMassFlow * (finalSysSizing.HeatSupTemp - CoilInTemp);
791 : }
792 : // AUTOSTEAMCOIL
793 0 : if (DesCoilLoad >= HVAC::SmallLoad) {
794 : // TempSteamIn=SteamCoil(CoilNum)%InletSteamTemp
795 : // TempSteamIn=PlantSizData(PltSizSteamNum)%ExitTemp
796 0 : TempSteamIn = 100.0; // Should be from the PlantSizing object (ExitTemp) instead of hardwired to 100?
797 : // RefrigIndex is set during GetInput for this module
798 0 : EnthSteamInDry = state.dataSteamCoils->SteamCoil(CoilNum).steam->getSatEnthalpy(state, TempSteamIn, 1.0, RoutineName);
799 0 : EnthSteamOutWet = state.dataSteamCoils->SteamCoil(CoilNum).steam->getSatEnthalpy(state, TempSteamIn, 0.0, RoutineName);
800 0 : LatentHeatSteam = EnthSteamInDry - EnthSteamOutWet;
801 0 : SteamDensity = state.dataSteamCoils->SteamCoil(CoilNum).steam->getSatDensity(state, TempSteamIn, 1.0, RoutineName);
802 : // SteamCoil(CoilNum)%MaxSteamVolFlowRate = DesCoilLoad/(SteamDensity * LatentHeatSteam)
803 : // CpWater = GetSpecificHeatGlycol('WATER', &
804 : // TempSteamIn, &
805 : // PlantLoop(SteamCoil(CoilNum)%LoopNum)%FluidIndex, &
806 : // 'SizeSteamCoil')
807 0 : CpWater = state.dataSteamCoils->SteamCoil(CoilNum).steam->getSatSpecificHeat(state, TempSteamIn, 0.0, RoutineName);
808 :
809 0 : state.dataSteamCoils->SteamCoil(CoilNum).MaxSteamVolFlowRate =
810 0 : DesCoilLoad / (SteamDensity * (LatentHeatSteam + state.dataSteamCoils->SteamCoil(CoilNum).DegOfSubcooling * CpWater));
811 : // PlantSizData(PltSizSteamNum)%DeltaT*CPHW(PlantSizData(PltSizSteamNum)%ExitTemp)))
812 : } else {
813 0 : state.dataSteamCoils->SteamCoil(CoilNum).MaxSteamVolFlowRate = 0.0;
814 0 : ShowWarningError(
815 0 : state, format("The design coil load is zero for COIL:Heating:Steam {}", state.dataSteamCoils->SteamCoil(CoilNum).Name));
816 : }
817 0 : BaseSizer::reportSizerOutput(state,
818 : "Coil:Heating:Steam",
819 0 : state.dataSteamCoils->SteamCoil(CoilNum).Name,
820 : "Maximum Steam Flow Rate [m3/s]",
821 0 : state.dataSteamCoils->SteamCoil(CoilNum).MaxSteamVolFlowRate);
822 : }
823 0 : state.dataSize->DataDesicRegCoil = false; // reset all globals to 0 to ensure correct sizing for other child components
824 : // Coil report, set fan info for airloopnum
825 :
826 0 : if (state.dataAirSystemsData->PrimaryAirSystems(state.dataSize->CurSysNum).supFanNum > 0) {
827 0 : state.dataRptCoilSelection->coilSelectionReportObj->setCoilSupplyFanInfo(
828 : state,
829 0 : state.dataSteamCoils->SteamCoil(CoilNum).Name,
830 : "Coil:Heating:Steam",
831 0 : state.dataFans->fans(state.dataAirSystemsData->PrimaryAirSystems(state.dataSize->CurSysNum).supFanNum)->Name,
832 0 : state.dataFans->fans(state.dataAirSystemsData->PrimaryAirSystems(state.dataSize->CurSysNum).supFanNum)->type,
833 0 : state.dataAirSystemsData->PrimaryAirSystems(state.dataSize->CurSysNum).supFanNum);
834 : }
835 :
836 : // if this is a zone coil
837 1 : } else if (state.dataSize->CurZoneEqNum > 0) {
838 1 : CheckZoneSizing(state, "Coil:Heating:Steam", state.dataSteamCoils->SteamCoil(CoilNum).Name);
839 : // autosize the coil steam volume flow rate if needed
840 1 : if (state.dataSteamCoils->SteamCoil(CoilNum).MaxSteamVolFlowRate == AutoSize) {
841 : // if coil is part of a terminal unit just use the terminal unit value
842 1 : if (state.dataSize->TermUnitSingDuct || state.dataSize->TermUnitPIU || state.dataSize->TermUnitIU) {
843 0 : if (state.dataSize->CurTermUnitSizingNum > 0) {
844 0 : state.dataSteamCoils->SteamCoil(CoilNum).MaxSteamVolFlowRate =
845 0 : TermUnitSizing(state.dataSize->CurTermUnitSizingNum).MaxSTVolFlow;
846 : } else {
847 0 : state.dataSteamCoils->SteamCoil(CoilNum).MaxSteamVolFlowRate = 0.0;
848 : }
849 : // if coil is part of a zonal unit, calc coil load to get hot Steam flow rate
850 0 : DesCoilLoad = TermUnitSizing(state.dataSize->CurTermUnitSizingNum).DesHeatingLoad; // coil report
851 0 : DesVolFlow = TermUnitSizing(state.dataSize->CurTermUnitSizingNum).AirVolFlow *
852 0 : TermUnitSizing(state.dataSize->CurTermUnitSizingNum).ReheatAirFlowMult; // coil report
853 : } else {
854 1 : CoilInTemp = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).DesHeatCoilInTemp;
855 1 : CoilOutTemp = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).HeatDesTemp;
856 1 : CoilOutHumRat = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).HeatDesHumRat;
857 1 : DesMassFlow = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).DesHeatMassFlow;
858 1 : DesVolFlow = DesMassFlow / RhoAirStd;
859 1 : DesCoilLoad = PsyCpAirFnW(CoilOutHumRat) * DesMassFlow * (CoilOutTemp - CoilInTemp);
860 1 : if (DesCoilLoad >= HVAC::SmallLoad) {
861 1 : TempSteamIn = 100.0;
862 : // RefrigIndex is set during GetInput for this module
863 1 : EnthSteamInDry = state.dataSteamCoils->SteamCoil(CoilNum).steam->getSatEnthalpy(state, TempSteamIn, 1.0, RoutineName);
864 1 : EnthSteamOutWet = state.dataSteamCoils->SteamCoil(CoilNum).steam->getSatEnthalpy(state, TempSteamIn, 0.0, RoutineName);
865 1 : LatentHeatSteam = EnthSteamInDry - EnthSteamOutWet;
866 1 : SteamDensity = state.dataSteamCoils->SteamCoil(CoilNum).steam->getSatDensity(state, TempSteamIn, 1.0, RoutineName);
867 : // SteamCoil(CoilNum)%MaxSteamVolFlowRate = DesCoilLoad/(SteamDensity * LatentHeatSteam)
868 : // CpWater = GetSpecificHeatGlycol('WATER', &
869 : // TempSteamIn, &
870 : // PlantLoop(SteamCoil(CoilNum)%LoopNum)%FluidIndex, &
871 : // 'SizeSteamCoil')
872 1 : CpWater = state.dataSteamCoils->SteamCoil(CoilNum).steam->getSatSpecificHeat(state, TempSteamIn, 0.0, RoutineName);
873 :
874 1 : state.dataSteamCoils->SteamCoil(CoilNum).MaxSteamVolFlowRate =
875 1 : DesCoilLoad / (SteamDensity * (LatentHeatSteam + state.dataSteamCoils->SteamCoil(CoilNum).DegOfSubcooling * CpWater));
876 : // PlantSizData(PltSizSteamNum)%DeltaT*CPHW(PlantSizData(PltSizSteamNum)%ExitTemp)))
877 : } else {
878 0 : state.dataSteamCoils->SteamCoil(CoilNum).MaxSteamVolFlowRate = 0.0;
879 : }
880 : }
881 : // issue warning if hw coil has zero flow
882 1 : if (state.dataSteamCoils->SteamCoil(CoilNum).MaxSteamVolFlowRate == 0.0) {
883 0 : ShowWarningError(
884 0 : state, format("The design coil load is zero for COIL:Heating:Steam {}", state.dataSteamCoils->SteamCoil(CoilNum).Name));
885 0 : ShowContinueError(state, "The autosize value for max Steam flow rate is zero");
886 : }
887 2 : BaseSizer::reportSizerOutput(state,
888 : "Coil:Heating:Steam",
889 1 : state.dataSteamCoils->SteamCoil(CoilNum).Name,
890 : "Maximum Steam Flow Rate [m3/s]",
891 1 : state.dataSteamCoils->SteamCoil(CoilNum).MaxSteamVolFlowRate);
892 : }
893 : } // end zone coil ELSE - IF
894 :
895 : } else {
896 : // if there is no heating Plant Sizing object and autosizng was requested, issue an error message
897 0 : if (state.dataSteamCoils->SteamCoil(CoilNum).MaxSteamVolFlowRate == AutoSize) {
898 0 : ShowSevereError(state, "Autosizing of Steam coil requires a heating loop Sizing:Plant object");
899 0 : ShowContinueError(state, format("Occurs in Steam coil object= {}", state.dataSteamCoils->SteamCoil(CoilNum).Name));
900 0 : ErrorsFound = true;
901 : }
902 : } // end of heating Plant Sizing existence IF - ELSE
903 :
904 : // save the design Steam volumetric flow rate for use by the Steam loop sizing algorithms
905 2 : RegisterPlantCompDesignFlow(
906 1 : state, state.dataSteamCoils->SteamCoil(CoilNum).SteamInletNodeNum, state.dataSteamCoils->SteamCoil(CoilNum).MaxSteamVolFlowRate);
907 :
908 4 : state.dataRptCoilSelection->coilSelectionReportObj->setCoilHeatingCapacity(state,
909 1 : state.dataSteamCoils->SteamCoil(CoilNum).Name,
910 : "Coil:Heating:Steam",
911 : DesCoilLoad,
912 : coilWasAutosized,
913 1 : state.dataSize->CurSysNum,
914 1 : state.dataSize->CurZoneEqNum,
915 1 : state.dataSize->CurOASysNum,
916 : 0.0,
917 : 1.0,
918 : -999.0,
919 : -999.0);
920 3 : state.dataRptCoilSelection->coilSelectionReportObj->setCoilWaterFlowNodeNums(state,
921 1 : state.dataSteamCoils->SteamCoil(CoilNum).Name,
922 : "Coil:Heating:Steam",
923 1 : state.dataSteamCoils->SteamCoil(CoilNum).MaxSteamVolFlowRate,
924 : coilWasAutosized,
925 1 : state.dataSteamCoils->SteamCoil(CoilNum).SteamInletNodeNum,
926 1 : state.dataSteamCoils->SteamCoil(CoilNum).SteamOutletNodeNum,
927 1 : state.dataSteamCoils->SteamCoil(CoilNum).plantLoc.loopNum);
928 3 : state.dataRptCoilSelection->coilSelectionReportObj->setCoilWaterHeaterCapacityNodeNums(
929 : state,
930 1 : state.dataSteamCoils->SteamCoil(CoilNum).Name,
931 : "Coil:Heating:Steam",
932 : DesCoilLoad,
933 : coilWasAutosized,
934 1 : state.dataSteamCoils->SteamCoil(CoilNum).SteamInletNodeNum,
935 1 : state.dataSteamCoils->SteamCoil(CoilNum).SteamOutletNodeNum,
936 1 : state.dataSteamCoils->SteamCoil(CoilNum).plantLoc.loopNum);
937 3 : state.dataRptCoilSelection->coilSelectionReportObj->setCoilEntWaterTemp(
938 1 : state, state.dataSteamCoils->SteamCoil(CoilNum).Name, "Coil:Heating:Steam", TempSteamIn); // coil report
939 3 : state.dataRptCoilSelection->coilSelectionReportObj->setCoilLvgWaterTemp(
940 : state,
941 1 : state.dataSteamCoils->SteamCoil(CoilNum).Name,
942 : "Coil:Heating:Steam",
943 1 : TempSteamIn - state.dataSteamCoils->SteamCoil(CoilNum).DegOfSubcooling); // coil report
944 3 : state.dataRptCoilSelection->coilSelectionReportObj->setCoilWaterDeltaT(
945 : state,
946 1 : state.dataSteamCoils->SteamCoil(CoilNum).Name,
947 : "Coil:Heating:Steam",
948 1 : state.dataSteamCoils->SteamCoil(CoilNum).DegOfSubcooling); // coil report
949 1 : state.dataSteamCoils->SteamCoil(CoilNum).DesCoilCapacity = DesCoilLoad;
950 1 : state.dataSteamCoils->SteamCoil(CoilNum).DesAirVolFlow = DesVolFlow;
951 1 : if (ErrorsFound) {
952 0 : ShowFatalError(state, "Preceding Steam coil sizing errors cause program termination");
953 : }
954 :
955 : // There is no standard rating for heating coils at this point, so fill with dummy flag values
956 3 : state.dataRptCoilSelection->coilSelectionReportObj->setRatedCoilConditions(state,
957 1 : state.dataSteamCoils->SteamCoil(CoilNum).Name,
958 : "Coil:Heating:Steam",
959 : -999.0,
960 : -999.0,
961 : -999.0,
962 : -999.0,
963 : -999.0,
964 : -999.0,
965 : -999.0,
966 : -999.0,
967 : -999.0,
968 : -999.0,
969 : -999.0,
970 : -999.0,
971 : -999.0);
972 1 : }
973 :
974 : // End Initialization Section of the Module
975 :
976 : // Begin Algorithm Section of the Module
977 :
978 3 : void CalcSteamAirCoil(EnergyPlusData &state,
979 : int const CoilNum,
980 : Real64 const QCoilRequested, // requested coil load
981 : Real64 &QCoilActual, // coil load actually delivered
982 : HVAC::FanOp const fanOp, // fan operating mode
983 : Real64 const PartLoadRatio // part-load ratio of heating coil
984 : )
985 : {
986 : // SUBROUTINE INFORMATION:
987 : // AUTHOR Rahul Chillar
988 : // DATE WRITTEN Jan 2005
989 : // MODIFIED Sep. 2012, B. Griffith, add calls to SetComponentFlowRate for plant interactions
990 : // Jul. 2016, R. Zhang, Applied the coil supply air temperature sensor offset fault model
991 : // RE-ENGINEERED na
992 :
993 : // PURPOSE OF THIS SUBROUTINE:
994 : // Simple Steam to air heat exchanger which,
995 : // serves as an interface for distributing heat from boiler to zones.
996 :
997 : // METHODOLOGY EMPLOYED:
998 : // Steam coils are different, All of steam condenses in heat exchanger
999 : // Steam traps allow only water to leave the coil,the degree of subcooling
1000 : // desired is input by the user, which is used to calculate water outlet temp.
1001 : // Heat exchange is = Latent Heat + Sensible heat,coil effectivness is 1.0
1002 :
1003 : using HVAC::TempControlTol;
1004 : using PlantUtilities::SetComponentFlowRate;
1005 :
1006 : static constexpr std::string_view RoutineName("CalcSteamAirCoil");
1007 : static constexpr std::string_view RoutineNameSizeSteamCoil("SizeSteamCoil");
1008 :
1009 3 : Real64 SteamMassFlowRate(0.0);
1010 3 : Real64 AirMassFlow(0.0); // [kg/sec]
1011 3 : Real64 TempAirIn(0.0); // [C]
1012 3 : Real64 TempAirOut(0.0); // [C]
1013 3 : Real64 Win(0.0);
1014 3 : Real64 TempSteamIn(0.0);
1015 3 : Real64 TempWaterOut(0.0);
1016 3 : Real64 CapacitanceAir(0.0);
1017 3 : Real64 HeatingCoilLoad(0.0);
1018 3 : Real64 CoilPress(0.0);
1019 3 : Real64 EnthSteamInDry(0.0);
1020 3 : Real64 EnthSteamOutWet(0.0);
1021 3 : Real64 LatentHeatSteam(0.0);
1022 3 : Real64 SubcoolDeltaTemp(0.0);
1023 3 : Real64 TempSetPoint(0.0);
1024 3 : Real64 QCoilReq(0.0);
1025 3 : Real64 QCoilCap(0.0);
1026 3 : Real64 QSteamCoilMaxHT(0.0);
1027 3 : Real64 TempWaterAtmPress(0.0);
1028 3 : Real64 TempLoopOutToPump(0.0);
1029 3 : Real64 EnergyLossToEnvironment(0.0);
1030 3 : Real64 EnthCoilOutlet(0.0);
1031 3 : Real64 EnthPumpInlet(0.0);
1032 3 : Real64 EnthAtAtmPress(0.0);
1033 3 : Real64 CpWater(0.0);
1034 :
1035 3 : QCoilReq = QCoilRequested;
1036 3 : TempAirIn = state.dataSteamCoils->SteamCoil(CoilNum).InletAirTemp;
1037 3 : Win = state.dataSteamCoils->SteamCoil(CoilNum).InletAirHumRat;
1038 3 : TempSteamIn = state.dataSteamCoils->SteamCoil(CoilNum).InletSteamTemp;
1039 3 : CoilPress = state.dataSteamCoils->SteamCoil(CoilNum).InletSteamPress;
1040 3 : SubcoolDeltaTemp = state.dataSteamCoils->SteamCoil(CoilNum).DegOfSubcooling;
1041 3 : TempSetPoint = state.dataSteamCoils->SteamCoil(CoilNum).DesiredOutletTemp;
1042 :
1043 : // If there is a fault of coil SAT Sensor
1044 3 : if (state.dataSteamCoils->SteamCoil(CoilNum).FaultyCoilSATFlag && (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing) &&
1045 0 : (!state.dataGlobal->KickOffSimulation)) {
1046 : // calculate the sensor offset using fault information
1047 0 : int FaultIndex = state.dataSteamCoils->SteamCoil(CoilNum).FaultyCoilSATIndex;
1048 0 : state.dataSteamCoils->SteamCoil(CoilNum).FaultyCoilSATOffset =
1049 0 : state.dataFaultsMgr->FaultsCoilSATSensor(FaultIndex).CalFaultOffsetAct(state);
1050 : // update the TempSetPoint
1051 0 : TempSetPoint -= state.dataSteamCoils->SteamCoil(CoilNum).FaultyCoilSATOffset;
1052 : }
1053 :
1054 : // adjust mass flow rates for cycling fan cycling coil operation
1055 3 : if (fanOp == HVAC::FanOp::Cycling) {
1056 0 : if (PartLoadRatio > 0.0) {
1057 0 : AirMassFlow = state.dataSteamCoils->SteamCoil(CoilNum).InletAirMassFlowRate / PartLoadRatio;
1058 0 : SteamMassFlowRate = min(state.dataSteamCoils->SteamCoil(CoilNum).InletSteamMassFlowRate / PartLoadRatio,
1059 0 : state.dataSteamCoils->SteamCoil(CoilNum).MaxSteamMassFlowRate);
1060 0 : QCoilReq /= PartLoadRatio;
1061 : } else {
1062 0 : AirMassFlow = 0.0;
1063 0 : SteamMassFlowRate = 0.0;
1064 : }
1065 : } else {
1066 3 : AirMassFlow = state.dataSteamCoils->SteamCoil(CoilNum).InletAirMassFlowRate;
1067 3 : SteamMassFlowRate = state.dataSteamCoils->SteamCoil(CoilNum).InletSteamMassFlowRate;
1068 : }
1069 :
1070 3 : if (AirMassFlow > 0.0) { // If the coil is operating
1071 2 : CapacitanceAir = PsyCpAirFnW(Win) * AirMassFlow;
1072 : } else {
1073 1 : CapacitanceAir = 0.0;
1074 : }
1075 :
1076 : // If the coil is operating there should be some heating capacitance
1077 : // across the coil, so do the simulation. If not set outlet to inlet and no load.
1078 : // Also the coil has to be scheduled to be available
1079 : // Control output to meet load QCoilReq. Load Controlled Coil.
1080 3 : switch (state.dataSteamCoils->SteamCoil(CoilNum).TypeOfCoil) {
1081 :
1082 3 : case CoilControlType::ZoneLoadControl:
1083 4 : if ((CapacitanceAir > 0.0) && ((state.dataSteamCoils->SteamCoil(CoilNum).InletSteamMassFlowRate) > 0.0) &&
1084 7 : (state.dataSteamCoils->SteamCoil(CoilNum).availSched->getCurrentVal() > 0.0 || state.dataSteamCoils->MySizeFlag(CoilNum)) &&
1085 : (QCoilReq > 0.0)) {
1086 :
1087 : // Steam heat exchangers would not have effectivness, since all of the steam is
1088 : // converted to water and only then the steam trap allows it to leave the heat
1089 : // exchanger, subsequently heat exchange is latent heat + subcooling.
1090 2 : EnthSteamInDry = state.dataSteamCoils->SteamCoil(CoilNum).steam->getSatEnthalpy(state, TempSteamIn, 1.0, RoutineName);
1091 2 : EnthSteamOutWet = state.dataSteamCoils->SteamCoil(CoilNum).steam->getSatEnthalpy(state, TempSteamIn, 0.0, RoutineName);
1092 :
1093 2 : LatentHeatSteam = EnthSteamInDry - EnthSteamOutWet;
1094 :
1095 : // CpWater = GetSpecificHeatGlycol('WATER', &
1096 : // TempSteamIn, &
1097 : // PlantLoop(SteamCoil(CoilNum)%LoopNum)%FluidIndex, &
1098 : // 'CalcSteamAirCoil')
1099 :
1100 2 : CpWater = state.dataSteamCoils->SteamCoil(CoilNum).steam->getSatSpecificHeat(state, TempSteamIn, 0.0, RoutineNameSizeSteamCoil);
1101 :
1102 : // Max Heat Transfer
1103 2 : QSteamCoilMaxHT = state.dataSteamCoils->SteamCoil(CoilNum).MaxSteamMassFlowRate * (LatentHeatSteam + SubcoolDeltaTemp * CpWater);
1104 2 : state.dataSteamCoils->SteamCoil(CoilNum).OperatingCapacity = QSteamCoilMaxHT;
1105 :
1106 : // Determine the Max coil capacity and check for the same.
1107 2 : if (QCoilReq > QSteamCoilMaxHT) {
1108 1 : QCoilCap = QSteamCoilMaxHT;
1109 : } else {
1110 1 : QCoilCap = QCoilReq;
1111 : }
1112 :
1113 : // Steam Mass Flow Rate Required
1114 2 : SteamMassFlowRate = QCoilCap / (LatentHeatSteam + SubcoolDeltaTemp * CpWater);
1115 :
1116 4 : SetComponentFlowRate(state,
1117 : SteamMassFlowRate,
1118 2 : state.dataSteamCoils->SteamCoil(CoilNum).SteamInletNodeNum,
1119 2 : state.dataSteamCoils->SteamCoil(CoilNum).SteamOutletNodeNum,
1120 2 : state.dataSteamCoils->SteamCoil(CoilNum).plantLoc);
1121 :
1122 : // recalculate if mass flow rate changed in previous call.
1123 2 : QCoilCap = SteamMassFlowRate * (LatentHeatSteam + SubcoolDeltaTemp * CpWater);
1124 :
1125 : // In practice Sensible & Superheated heat transfer is negligible compared to latent part.
1126 : // This is required for outlet water temperature, otherwise it will be saturation temperature.
1127 : // Steam Trap drains off all the Water formed.
1128 : // Here Degree of Subcooling is used to calculate hot water return temperature.
1129 :
1130 : // Calculating Water outlet temperature
1131 2 : TempWaterOut = TempSteamIn - SubcoolDeltaTemp;
1132 :
1133 : // Total Heat Transfer to air
1134 2 : HeatingCoilLoad = QCoilCap;
1135 :
1136 : // Temperature of air at outlet
1137 2 : TempAirOut = TempAirIn + QCoilCap / (AirMassFlow * PsyCpAirFnW(Win));
1138 :
1139 2 : state.dataSteamCoils->SteamCoil(CoilNum).OutletSteamMassFlowRate = SteamMassFlowRate;
1140 2 : state.dataSteamCoils->SteamCoil(CoilNum).InletSteamMassFlowRate = SteamMassFlowRate;
1141 :
1142 : //************************* Loop Losses *****************************
1143 : // Loop pressure return considerations included in steam coil since the pipes are
1144 : // perfect and do not account for losses.
1145 : // Return water is condensate at atmoshperic pressure
1146 : // Process is considered constant enthalpy expansion
1147 : // No quality function in EnergyPlus hence no option left apart from
1148 : // considering saturated state.
1149 : // StdBaroPress=101325
1150 :
1151 : TempWaterAtmPress =
1152 2 : state.dataSteamCoils->SteamCoil(CoilNum).steam->getSatTemperature(state, state.dataEnvrn->StdBaroPress, RoutineName);
1153 :
1154 : // Point 4 at atm - loop delta subcool during return journery back to pump
1155 2 : TempLoopOutToPump = TempWaterAtmPress - state.dataSteamCoils->SteamCoil(CoilNum).LoopSubcoolReturn;
1156 :
1157 : // Actual Steam Coil Outlet Enthalpy
1158 2 : EnthCoilOutlet =
1159 2 : state.dataSteamCoils->SteamCoil(CoilNum).steam->getSatEnthalpy(state, TempSteamIn, 0.0, RoutineName) - CpWater * SubcoolDeltaTemp;
1160 :
1161 : // Enthalpy at Point 4
1162 2 : EnthAtAtmPress = state.dataSteamCoils->SteamCoil(CoilNum).steam->getSatEnthalpy(state, TempWaterAtmPress, 0.0, RoutineName);
1163 :
1164 : // Reported value of coil outlet enthalpy at the node to match the node outlet temperature
1165 2 : CpWater = state.dataSteamCoils->SteamCoil(CoilNum).steam->getSatSpecificHeat(state, TempLoopOutToPump, 0.0, RoutineNameSizeSteamCoil);
1166 :
1167 2 : EnthPumpInlet = EnthAtAtmPress - CpWater * state.dataSteamCoils->SteamCoil(CoilNum).LoopSubcoolReturn;
1168 :
1169 2 : state.dataSteamCoils->SteamCoil(CoilNum).OutletWaterEnthalpy = EnthPumpInlet;
1170 :
1171 : // Point 3-Point 5,
1172 2 : EnergyLossToEnvironment = SteamMassFlowRate * (EnthCoilOutlet - EnthPumpInlet);
1173 :
1174 : // Loss to enviornment due to pressure drop
1175 2 : state.dataSteamCoils->SteamCoil(CoilNum).LoopLoss = EnergyLossToEnvironment;
1176 : //************************* Loop Losses *****************************
1177 : } else { // Coil is not running.
1178 :
1179 1 : TempAirOut = TempAirIn;
1180 1 : TempWaterOut = TempSteamIn;
1181 1 : HeatingCoilLoad = 0.0;
1182 1 : state.dataSteamCoils->SteamCoil(CoilNum).OutletWaterEnthalpy = state.dataSteamCoils->SteamCoil(CoilNum).InletSteamEnthalpy;
1183 1 : state.dataSteamCoils->SteamCoil(CoilNum).OutletSteamMassFlowRate = 0.0;
1184 1 : state.dataSteamCoils->SteamCoil(CoilNum).OutletSteamQuality = 0.0;
1185 1 : state.dataSteamCoils->SteamCoil(CoilNum).LoopLoss = 0.0;
1186 1 : TempLoopOutToPump = TempWaterOut;
1187 : }
1188 3 : break;
1189 0 : case CoilControlType::TemperatureSetPoint:
1190 : // Control coil output to meet a Setpoint Temperature.
1191 0 : if ((CapacitanceAir > 0.0) && ((state.dataSteamCoils->SteamCoil(CoilNum).InletSteamMassFlowRate) > 0.0) &&
1192 0 : (state.dataSteamCoils->SteamCoil(CoilNum).availSched->getCurrentVal() > 0.0 || state.dataSteamCoils->MySizeFlag(CoilNum)) &&
1193 0 : (std::abs(TempSetPoint - TempAirIn) > TempControlTol)) {
1194 :
1195 : // Steam heat exchangers would not have effectivness, since all of the steam is
1196 : // converted to water and only then the steam trap allows it to leave the heat
1197 : // exchanger, subsequently heat exchange is latent heat + subcooling.
1198 0 : EnthSteamInDry = state.dataSteamCoils->SteamCoil(CoilNum).steam->getSatEnthalpy(state, TempSteamIn, 1.0, RoutineName);
1199 0 : EnthSteamOutWet = state.dataSteamCoils->SteamCoil(CoilNum).steam->getSatEnthalpy(state, TempSteamIn, 0.0, RoutineName);
1200 0 : LatentHeatSteam = EnthSteamInDry - EnthSteamOutWet;
1201 :
1202 : // CpWater = GetSpecificHeatGlycol('WATER', &
1203 : // TempSteamIn, &
1204 : // PlantLoop(SteamCoil(CoilNum)%LoopNum)%FluidIndex, &
1205 : // 'CalcSteamAirCoil')
1206 0 : CpWater = state.dataSteamCoils->SteamCoil(CoilNum).steam->getSatSpecificHeat(state, TempSteamIn, 0.0, RoutineNameSizeSteamCoil);
1207 :
1208 : // Max Heat Transfer
1209 0 : QSteamCoilMaxHT = state.dataSteamCoils->SteamCoil(CoilNum).MaxSteamMassFlowRate * (LatentHeatSteam + SubcoolDeltaTemp * CpWater);
1210 :
1211 : // Coil Load in case of temperature setpoint
1212 0 : QCoilCap = CapacitanceAir * (TempSetPoint - TempAirIn);
1213 :
1214 : // Check to see if setpoint above enetering temperature. If not, set
1215 : // output to zero.
1216 0 : if (QCoilCap <= 0.0) {
1217 0 : QCoilCap = 0.0;
1218 0 : TempAirOut = TempAirIn;
1219 :
1220 : // Steam Mass Flow Rate Required
1221 0 : SteamMassFlowRate = 0.0;
1222 0 : SetComponentFlowRate(state,
1223 : SteamMassFlowRate,
1224 0 : state.dataSteamCoils->SteamCoil(CoilNum).SteamInletNodeNum,
1225 0 : state.dataSteamCoils->SteamCoil(CoilNum).SteamOutletNodeNum,
1226 0 : state.dataSteamCoils->SteamCoil(CoilNum).plantLoc);
1227 : // Inlet equal to outlet when not required to run.
1228 0 : TempWaterOut = TempSteamIn;
1229 :
1230 : // Total Heat Transfer to air
1231 0 : HeatingCoilLoad = QCoilCap;
1232 :
1233 : // The HeatingCoilLoad is the change in the enthalpy of the water
1234 0 : state.dataSteamCoils->SteamCoil(CoilNum).OutletWaterEnthalpy = state.dataSteamCoils->SteamCoil(CoilNum).InletSteamEnthalpy;
1235 :
1236 : // Outlet flow rate set to inlet
1237 0 : state.dataSteamCoils->SteamCoil(CoilNum).OutletSteamMassFlowRate = SteamMassFlowRate;
1238 0 : state.dataSteamCoils->SteamCoil(CoilNum).InletSteamMassFlowRate = SteamMassFlowRate;
1239 :
1240 0 : } else if (QCoilCap > QSteamCoilMaxHT) {
1241 : // Setting to Maximum Coil Capacity
1242 0 : QCoilCap = QSteamCoilMaxHT;
1243 :
1244 : // Temperature of air at outlet
1245 0 : TempAirOut = TempAirIn + QCoilCap / (AirMassFlow * PsyCpAirFnW(Win));
1246 :
1247 : // In practice Sensible & Superheated heat transfer is negligible compared to latent part.
1248 : // This is required for outlet water temperature, otherwise it will be saturation temperature.
1249 : // Steam Trap drains off all the Water formed.
1250 : // Here Degree of Subcooling is used to calculate hot water return temperature.
1251 :
1252 : // Calculating Water outlet temperature
1253 0 : TempWaterOut = TempSteamIn - SubcoolDeltaTemp;
1254 :
1255 : // Steam Mass Flow Rate Required
1256 0 : SteamMassFlowRate = QCoilCap / (LatentHeatSteam + SubcoolDeltaTemp * CpWater);
1257 0 : SetComponentFlowRate(state,
1258 : SteamMassFlowRate,
1259 0 : state.dataSteamCoils->SteamCoil(CoilNum).SteamInletNodeNum,
1260 0 : state.dataSteamCoils->SteamCoil(CoilNum).SteamOutletNodeNum,
1261 0 : state.dataSteamCoils->SteamCoil(CoilNum).plantLoc);
1262 :
1263 : // recalculate in case previous call changed mass flow rate
1264 0 : QCoilCap = SteamMassFlowRate * (LatentHeatSteam + SubcoolDeltaTemp * CpWater);
1265 0 : TempAirOut = TempAirIn + QCoilCap / (AirMassFlow * PsyCpAirFnW(Win));
1266 :
1267 : // Total Heat Transfer to air
1268 0 : HeatingCoilLoad = QCoilCap;
1269 :
1270 : // The HeatingCoilLoad is the change in the enthalpy of the water
1271 0 : state.dataSteamCoils->SteamCoil(CoilNum).OutletWaterEnthalpy =
1272 0 : state.dataSteamCoils->SteamCoil(CoilNum).InletSteamEnthalpy - HeatingCoilLoad / SteamMassFlowRate;
1273 0 : state.dataSteamCoils->SteamCoil(CoilNum).OutletSteamMassFlowRate = SteamMassFlowRate;
1274 0 : state.dataSteamCoils->SteamCoil(CoilNum).InletSteamMassFlowRate = SteamMassFlowRate;
1275 :
1276 : } else {
1277 : // Temp air out is temperature Setpoint
1278 0 : TempAirOut = TempSetPoint;
1279 :
1280 : // In practice Sensible & Superheated heat transfer is negligible compared to latent part.
1281 : // This is required for outlet water temperature, otherwise it will be saturation temperature.
1282 : // Steam Trap drains off all the Water formed.
1283 : // Here Degree of Subcooling is used to calculate hot water return temperature.
1284 :
1285 : // Calculating Water outlet temperature
1286 0 : TempWaterOut = TempSteamIn - SubcoolDeltaTemp;
1287 :
1288 : // Steam Mass Flow Rate Required
1289 0 : SteamMassFlowRate = QCoilCap / (LatentHeatSteam + SubcoolDeltaTemp * CpWater);
1290 0 : SetComponentFlowRate(state,
1291 : SteamMassFlowRate,
1292 0 : state.dataSteamCoils->SteamCoil(CoilNum).SteamInletNodeNum,
1293 0 : state.dataSteamCoils->SteamCoil(CoilNum).SteamOutletNodeNum,
1294 0 : state.dataSteamCoils->SteamCoil(CoilNum).plantLoc);
1295 :
1296 : // recalculate in case previous call changed mass flow rate
1297 0 : QCoilCap = SteamMassFlowRate * (LatentHeatSteam + SubcoolDeltaTemp * CpWater);
1298 0 : TempAirOut = TempAirIn + QCoilCap / (AirMassFlow * PsyCpAirFnW(Win));
1299 :
1300 : // Total Heat Transfer to air
1301 0 : HeatingCoilLoad = QCoilCap;
1302 :
1303 0 : state.dataSteamCoils->SteamCoil(CoilNum).OutletSteamMassFlowRate = SteamMassFlowRate;
1304 0 : state.dataSteamCoils->SteamCoil(CoilNum).InletSteamMassFlowRate = SteamMassFlowRate;
1305 :
1306 : //************************* Loop Losses *****************************
1307 : // Loop pressure return considerations included in steam coil since the pipes are
1308 : // perfect and do not account for losses.
1309 :
1310 : // Return water is condensate at atmoshperic pressure
1311 : // Process is considered constant enthalpy expansion
1312 : // No quality function in EnergyPlus hence no option left apart from
1313 : // considering saturated state.
1314 : // StdBaroPress=101325
1315 :
1316 : TempWaterAtmPress =
1317 0 : state.dataSteamCoils->SteamCoil(CoilNum).steam->getSatTemperature(state, state.dataEnvrn->StdBaroPress, RoutineName);
1318 :
1319 : // Point 4 at atm - loop delta subcool during return journery back to pump
1320 0 : TempLoopOutToPump = TempWaterAtmPress - state.dataSteamCoils->SteamCoil(CoilNum).LoopSubcoolReturn;
1321 :
1322 : // Actual Steam Coil Outlet Enthalpy
1323 0 : EnthCoilOutlet = state.dataSteamCoils->SteamCoil(CoilNum).steam->getSatEnthalpy(state, TempSteamIn, 0.0, RoutineName) -
1324 0 : CpWater * SubcoolDeltaTemp;
1325 :
1326 : // Enthalpy at Point 4
1327 0 : EnthAtAtmPress = state.dataSteamCoils->SteamCoil(CoilNum).steam->getSatEnthalpy(state, TempWaterAtmPress, 0.0, RoutineName);
1328 :
1329 : CpWater =
1330 0 : state.dataSteamCoils->SteamCoil(CoilNum).steam->getSatSpecificHeat(state, TempLoopOutToPump, 0.0, RoutineNameSizeSteamCoil);
1331 :
1332 : // Reported value of coil outlet enthalpy at the node to match the node outlet temperature
1333 0 : EnthPumpInlet = EnthAtAtmPress - CpWater * state.dataSteamCoils->SteamCoil(CoilNum).LoopSubcoolReturn;
1334 :
1335 0 : state.dataSteamCoils->SteamCoil(CoilNum).OutletWaterEnthalpy = EnthPumpInlet;
1336 :
1337 : // Point 3-Point 5,
1338 0 : EnergyLossToEnvironment = SteamMassFlowRate * (EnthCoilOutlet - EnthPumpInlet);
1339 :
1340 : // Loss to enviornment due to pressure drop
1341 0 : state.dataSteamCoils->SteamCoil(CoilNum).LoopLoss = EnergyLossToEnvironment;
1342 : //************************* Loop Losses *****************************
1343 : }
1344 :
1345 : } else { // If not running Conditions do not change across coil from inlet to outlet
1346 0 : SteamMassFlowRate = 0.0;
1347 0 : SetComponentFlowRate(state,
1348 : SteamMassFlowRate,
1349 0 : state.dataSteamCoils->SteamCoil(CoilNum).SteamInletNodeNum,
1350 0 : state.dataSteamCoils->SteamCoil(CoilNum).SteamOutletNodeNum,
1351 0 : state.dataSteamCoils->SteamCoil(CoilNum).plantLoc);
1352 0 : TempAirOut = TempAirIn;
1353 0 : TempWaterOut = TempSteamIn;
1354 0 : HeatingCoilLoad = 0.0;
1355 0 : state.dataSteamCoils->SteamCoil(CoilNum).OutletWaterEnthalpy = state.dataSteamCoils->SteamCoil(CoilNum).InletSteamEnthalpy;
1356 0 : state.dataSteamCoils->SteamCoil(CoilNum).OutletSteamMassFlowRate = 0.0;
1357 0 : state.dataSteamCoils->SteamCoil(CoilNum).OutletSteamQuality = 0.0;
1358 0 : state.dataSteamCoils->SteamCoil(CoilNum).LoopLoss = 0.0;
1359 0 : TempLoopOutToPump = TempWaterOut;
1360 : }
1361 0 : break;
1362 0 : default:
1363 0 : assert(false);
1364 : }
1365 :
1366 3 : if (fanOp == HVAC::FanOp::Cycling) {
1367 0 : HeatingCoilLoad *= PartLoadRatio;
1368 : }
1369 :
1370 : // Set the outlet conditions
1371 3 : state.dataSteamCoils->SteamCoil(CoilNum).TotSteamHeatingCoilRate = HeatingCoilLoad;
1372 3 : state.dataSteamCoils->SteamCoil(CoilNum).OutletAirTemp = TempAirOut;
1373 3 : state.dataSteamCoils->SteamCoil(CoilNum).OutletSteamTemp = TempLoopOutToPump;
1374 3 : state.dataSteamCoils->SteamCoil(CoilNum).OutletSteamQuality = 0.0;
1375 3 : QCoilActual = HeatingCoilLoad;
1376 :
1377 : // This SteamCoil does not change the moisture or Mass Flow across the component
1378 3 : state.dataSteamCoils->SteamCoil(CoilNum).OutletAirHumRat = state.dataSteamCoils->SteamCoil(CoilNum).InletAirHumRat;
1379 3 : state.dataSteamCoils->SteamCoil(CoilNum).OutletAirMassFlowRate = state.dataSteamCoils->SteamCoil(CoilNum).InletAirMassFlowRate;
1380 : // Set the outlet enthalpys for air and water
1381 3 : state.dataSteamCoils->SteamCoil(CoilNum).OutletAirEnthalpy =
1382 3 : PsyHFnTdbW(state.dataSteamCoils->SteamCoil(CoilNum).OutletAirTemp, state.dataSteamCoils->SteamCoil(CoilNum).OutletAirHumRat);
1383 3 : }
1384 :
1385 : // Beginning of Update subroutines for the SteamCoil Module
1386 :
1387 3 : void UpdateSteamCoil(EnergyPlusData &state, int const CoilNum)
1388 : {
1389 : // SUBROUTINE INFORMATION:
1390 : // AUTHOR Rahul Chillar
1391 : // DATE WRITTEN Jan 2005
1392 : // MODIFIED na
1393 : // RE-ENGINEERED na
1394 :
1395 : // PURPOSE OF THIS SUBROUTINE:
1396 : // This subroutine updates the coil outlet nodes.
1397 :
1398 : // METHODOLOGY EMPLOYED:
1399 : // Data is moved from the coil data structure to the coil outlet nodes.
1400 :
1401 : using PlantUtilities::SafeCopyPlantNode;
1402 :
1403 : int AirInletNode;
1404 : int SteamInletNode;
1405 : int AirOutletNode;
1406 : int SteamOutletNode;
1407 :
1408 3 : AirInletNode = state.dataSteamCoils->SteamCoil(CoilNum).AirInletNodeNum;
1409 3 : SteamInletNode = state.dataSteamCoils->SteamCoil(CoilNum).SteamInletNodeNum;
1410 3 : AirOutletNode = state.dataSteamCoils->SteamCoil(CoilNum).AirOutletNodeNum;
1411 3 : SteamOutletNode = state.dataSteamCoils->SteamCoil(CoilNum).SteamOutletNodeNum;
1412 :
1413 : // Set the outlet air nodes of the SteamCoil
1414 3 : state.dataLoopNodes->Node(AirOutletNode).MassFlowRate = state.dataSteamCoils->SteamCoil(CoilNum).OutletAirMassFlowRate;
1415 3 : state.dataLoopNodes->Node(AirOutletNode).Temp = state.dataSteamCoils->SteamCoil(CoilNum).OutletAirTemp;
1416 3 : state.dataLoopNodes->Node(AirOutletNode).HumRat = state.dataSteamCoils->SteamCoil(CoilNum).OutletAirHumRat;
1417 3 : state.dataLoopNodes->Node(AirOutletNode).Enthalpy = state.dataSteamCoils->SteamCoil(CoilNum).OutletAirEnthalpy;
1418 :
1419 3 : SafeCopyPlantNode(state, SteamInletNode, SteamOutletNode);
1420 :
1421 : // Set the outlet Steam nodes for the Coil
1422 : // Node(SteamOutletNode)%MassFlowRate = SteamCoil(CoilNum)%OutletSteamMassFlowRate
1423 3 : state.dataLoopNodes->Node(SteamOutletNode).Temp = state.dataSteamCoils->SteamCoil(CoilNum).OutletSteamTemp;
1424 3 : state.dataLoopNodes->Node(SteamOutletNode).Enthalpy = state.dataSteamCoils->SteamCoil(CoilNum).OutletWaterEnthalpy;
1425 3 : state.dataLoopNodes->Node(SteamOutletNode).Quality = state.dataSteamCoils->SteamCoil(CoilNum).OutletSteamQuality;
1426 : // Node(SteamInletNode)%MassFlowRate = SteamCoil(CoilNum)%OutletSteamMassFlowRate
1427 :
1428 : // Set the outlet nodes for properties that just pass through & not used
1429 3 : state.dataLoopNodes->Node(AirOutletNode).Quality = state.dataLoopNodes->Node(AirInletNode).Quality;
1430 3 : state.dataLoopNodes->Node(AirOutletNode).Press = state.dataLoopNodes->Node(AirInletNode).Press;
1431 3 : state.dataLoopNodes->Node(AirOutletNode).MassFlowRateMin = state.dataLoopNodes->Node(AirInletNode).MassFlowRateMin;
1432 3 : state.dataLoopNodes->Node(AirOutletNode).MassFlowRateMax = state.dataLoopNodes->Node(AirInletNode).MassFlowRateMax;
1433 3 : state.dataLoopNodes->Node(AirOutletNode).MassFlowRateMinAvail = state.dataLoopNodes->Node(AirInletNode).MassFlowRateMinAvail;
1434 3 : state.dataLoopNodes->Node(AirOutletNode).MassFlowRateMaxAvail = state.dataLoopNodes->Node(AirInletNode).MassFlowRateMaxAvail;
1435 :
1436 : // Set the outlet nodes for properties that just pass through & not used
1437 :
1438 : // Node(SteamOutletNode)%Press = Node(SteamInletNode)%Press
1439 : // Node(SteamOutletNode)%Press = StdBaroPress ! Water out at atm pressure
1440 : // Node(SteamOutletNode)%HumRat = Node(SteamInletNode)%HumRat
1441 : // Node(SteamOutletNode)%MassFlowRateMin = Node(SteamInletNode)%MassFlowRateMin
1442 : // Node(SteamOutletNode)%MassFlowRateMax = Node(SteamInletNode)%MassFlowRateMax
1443 : // Node(SteamOutletNode)%MassFlowRateMinAvail= Node(SteamInletNode)%MassFlowRateMinAvail
1444 : // Node(SteamOutletNode)%MassFlowRateMaxAvail= Node(SteamInletNode)%MassFlowRateMaxAvail
1445 :
1446 : // IF (SteamCoil(CoilNum)%InletSteamMassFlowRate.EQ.0.0) THEN
1447 : // Node(SteamInletNode)%MassFlowRate = 0.0
1448 : // Node(SteamInletNode)%MassFlowRateMinAvail = 0.0
1449 : // Node(SteamOutletNode)%MassFlowRateMinAvail= 0.0
1450 : // END IF
1451 :
1452 3 : if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
1453 0 : state.dataLoopNodes->Node(AirOutletNode).CO2 = state.dataLoopNodes->Node(AirInletNode).CO2;
1454 : }
1455 3 : if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
1456 0 : state.dataLoopNodes->Node(AirOutletNode).GenContam = state.dataLoopNodes->Node(AirInletNode).GenContam;
1457 : }
1458 3 : }
1459 :
1460 : // End of Update subroutines for the SteamCoil Module
1461 :
1462 : // Beginning of Reporting subroutines for the SteamCoil Module
1463 :
1464 3 : void ReportSteamCoil(EnergyPlusData &state, int const CoilNum)
1465 : {
1466 : // SUBROUTINE INFORMATION:
1467 : // AUTHOR Rahul Chillar
1468 : // DATE WRITTEN Jan 2005
1469 : // MODIFIED na
1470 : // RE-ENGINEERED na
1471 :
1472 : // PURPOSE OF THIS SUBROUTINE:
1473 : // This subroutine updates the report variable for the coils.
1474 :
1475 : // Report the SteamCoil energy from this component
1476 3 : state.dataSteamCoils->SteamCoil(CoilNum).TotSteamHeatingCoilEnergy =
1477 3 : state.dataSteamCoils->SteamCoil(CoilNum).TotSteamHeatingCoilRate * state.dataHVACGlobal->TimeStepSysSec;
1478 3 : }
1479 :
1480 : // End of Reporting subroutines for the SteamCoil Module
1481 :
1482 : // Utility subroutines for the SteamCoil Module
1483 :
1484 2 : int GetSteamCoilIndex(EnergyPlusData &state,
1485 : std::string_view CoilType, // must match coil types in this module
1486 : std::string const &CoilName, // must match coil names for the coil type
1487 : bool &ErrorsFound // set to true if problem
1488 : )
1489 : {
1490 :
1491 : // FUNCTION INFORMATION:
1492 : // AUTHOR R. Raustad
1493 : // DATE WRITTEN August 2007
1494 : // MODIFIED na
1495 : // RE-ENGINEERED na
1496 :
1497 : // PURPOSE OF THIS FUNCTION:
1498 : // This function looks up the index for the given coil and returns it. If
1499 : // incorrect coil type or name is given, ErrorsFound is returned as true and node number is returned
1500 : // as zero.
1501 :
1502 : // Return value
1503 : int IndexNum; // returned air inlet node number of matched coil
1504 :
1505 : // Obtains and Allocates SteamCoil related parameters from input file
1506 2 : if (state.dataSteamCoils->GetSteamCoilsInputFlag) { // First time subroutine has been entered
1507 2 : GetSteamCoilInput(state);
1508 2 : state.dataSteamCoils->GetSteamCoilsInputFlag = false;
1509 : }
1510 :
1511 2 : if (CoilType == "COIL:HEATING:STEAM") {
1512 2 : IndexNum = Util::FindItemInList(CoilName, state.dataSteamCoils->SteamCoil);
1513 : } else {
1514 0 : IndexNum = 0;
1515 : }
1516 :
1517 2 : if (IndexNum == 0) {
1518 0 : ShowSevereError(state, format(R"(GetSteamCoilIndex: Could not find CoilType="{}" with Name="{}")", CoilType, CoilName));
1519 0 : ErrorsFound = true;
1520 : }
1521 :
1522 2 : return IndexNum;
1523 : }
1524 :
1525 0 : int GetCompIndex(EnergyPlusData &state, std::string_view const coilName)
1526 : {
1527 0 : if (state.dataSteamCoils->GetSteamCoilsInputFlag) { // First time subroutine has been entered
1528 0 : GetSteamCoilInput(state);
1529 0 : state.dataSteamCoils->GetSteamCoilsInputFlag = false;
1530 : }
1531 :
1532 0 : int indexNum = Util::FindItemInList(coilName, state.dataSteamCoils->SteamCoil);
1533 :
1534 0 : if (indexNum == 0) { // may not find coil name
1535 0 : ShowSevereError(state, format("GetSteamCoilIndex: Could not find CoilType = Coil:Heating:Steam with Name = \"{}\"", coilName));
1536 : }
1537 :
1538 0 : return indexNum;
1539 : }
1540 :
1541 0 : void CheckSteamCoilSchedule(
1542 : EnergyPlusData &state, [[maybe_unused]] std::string const &CompType, std::string_view CompName, Real64 &Value, int &CompIndex)
1543 : {
1544 :
1545 : // SUBROUTINE INFORMATION:
1546 : // AUTHOR Linda Lawrie
1547 : // DATE WRITTEN March 2006
1548 : // MODIFIED na
1549 : // RE-ENGINEERED na
1550 :
1551 : // PURPOSE OF THIS SUBROUTINE:
1552 : // Gets the correct schedule value for this coil
1553 :
1554 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1555 : int CoilNum;
1556 :
1557 : // Obtains and Allocates SteamCoil related parameters from input file
1558 0 : if (state.dataSteamCoils->GetSteamCoilsInputFlag) { // First time subroutine has been entered
1559 0 : GetSteamCoilInput(state);
1560 0 : state.dataSteamCoils->GetSteamCoilsInputFlag = false;
1561 : }
1562 :
1563 : // Find the correct Coil number
1564 0 : if (CompIndex == 0) {
1565 0 : CoilNum = Util::FindItemInList(CompName, state.dataSteamCoils->SteamCoil);
1566 0 : if (CoilNum == 0) {
1567 0 : ShowFatalError(state, format("CheckSteamCoilSchedule: Coil not found={}", CompName));
1568 : }
1569 0 : CompIndex = CoilNum;
1570 0 : Value = state.dataSteamCoils->SteamCoil(CoilNum).availSched->getCurrentVal(); // not scheduled?
1571 : } else {
1572 0 : CoilNum = CompIndex;
1573 0 : if (CoilNum > state.dataSteamCoils->NumSteamCoils || CoilNum < 1) {
1574 0 : ShowFatalError(state,
1575 0 : format("SimulateSteamCoilComponents: Invalid CompIndex passed={}, Number of Steam Coils={}, Coil name={}",
1576 : CoilNum,
1577 0 : state.dataSteamCoils->NumSteamCoils,
1578 : CompName));
1579 : }
1580 0 : if (CompName != state.dataSteamCoils->SteamCoil(CoilNum).Name) {
1581 0 : ShowFatalError(state,
1582 0 : format("SimulateSteamCoilComponents: Invalid CompIndex passed={}, Coil name={}, stored Coil Name for that index={}",
1583 : CoilNum,
1584 : CompName,
1585 0 : state.dataSteamCoils->SteamCoil(CoilNum).Name));
1586 : }
1587 0 : Value = state.dataSteamCoils->SteamCoil(CoilNum).availSched->getCurrentVal(); // not scheduled?
1588 : }
1589 0 : }
1590 :
1591 0 : Real64 GetCoilMaxWaterFlowRate(EnergyPlusData &state,
1592 : std::string const &CoilType, // must match coil types in this module
1593 : std::string const &CoilName, // must match coil names for the coil type
1594 : bool &ErrorsFound // set to true if problem
1595 : )
1596 : {
1597 :
1598 : // FUNCTION INFORMATION:
1599 : // AUTHOR Linda Lawrie
1600 : // DATE WRITTEN November 2006
1601 : // MODIFIED na
1602 : // RE-ENGINEERED na
1603 :
1604 : // PURPOSE OF THIS FUNCTION:
1605 : // This function looks up the max water flow rate for the given coil and returns it. If
1606 : // incorrect coil type or name is given, ErrorsFound is returned as true and capacity is returned
1607 : // as negative.
1608 :
1609 : // Return value
1610 : Real64 MaxWaterFlowRate; // returned max water flow rate of matched coil
1611 :
1612 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
1613 : int WhichCoil;
1614 :
1615 : // Obtains and Allocates SteamCoil related parameters from input file
1616 0 : if (state.dataSteamCoils->GetSteamCoilsInputFlag) { // First time subroutine has been entered
1617 0 : GetSteamCoilInput(state);
1618 0 : state.dataSteamCoils->GetSteamCoilsInputFlag = false;
1619 : }
1620 :
1621 0 : if (Util::SameString(CoilType, "Coil:Heating:Steam")) {
1622 0 : WhichCoil = Util::FindItem(CoilName, state.dataSteamCoils->SteamCoil);
1623 0 : if (WhichCoil != 0) {
1624 : // coil does not specify MaxWaterFlowRate
1625 0 : MaxWaterFlowRate = 0.0;
1626 0 : ShowRecurringWarningErrorAtEnd(state, "Requested Max Water Flow Rate from COIL:Heating:Steam N/A", state.dataSteamCoils->ErrCount);
1627 : }
1628 : } else {
1629 0 : WhichCoil = 0;
1630 : }
1631 :
1632 0 : if (WhichCoil == 0) {
1633 0 : ShowSevereError(state, format("GetCoilMaxWaterFlowRate: Could not find CoilType=\"{}\" with Name=\"{}\"", CoilType, CoilName));
1634 0 : ErrorsFound = true;
1635 0 : MaxWaterFlowRate = -1000.0;
1636 : }
1637 :
1638 0 : return MaxWaterFlowRate;
1639 : }
1640 :
1641 3 : Real64 GetCoilMaxSteamFlowRate(EnergyPlusData &state,
1642 : int const CoilIndex, // must match coil types in this module
1643 : bool &ErrorsFound // set to true if problem
1644 : )
1645 : {
1646 :
1647 : // FUNCTION INFORMATION:
1648 : // AUTHOR R. Raustad
1649 : // DATE WRITTEN August 2007
1650 : // MODIFIED na
1651 : // RE-ENGINEERED na
1652 :
1653 : // PURPOSE OF THIS FUNCTION:
1654 : // This function looks up the max steam flow rate for the given coil and returns it. If
1655 : // incorrect coil type or name is given, ErrorsFound is returned as true and flow rate is returned
1656 : // as zero.
1657 :
1658 : // Return value
1659 : Real64 MaxSteamFlowRate; // returned max steam flow rate of matched coil
1660 :
1661 : // Obtains and Allocates SteamCoil related parameters from input file
1662 3 : if (state.dataSteamCoils->GetSteamCoilsInputFlag) { // First time subroutine has been entered
1663 0 : GetSteamCoilInput(state);
1664 0 : state.dataSteamCoils->GetSteamCoilsInputFlag = false;
1665 : }
1666 :
1667 3 : if (CoilIndex == 0) {
1668 0 : ShowSevereError(state, "GetCoilMaxSteamFlowRate: Could not find CoilType = \"Coil:Heating:Steam\"");
1669 0 : ErrorsFound = true;
1670 0 : MaxSteamFlowRate = 0.0;
1671 : } else {
1672 3 : MaxSteamFlowRate = state.dataSteamCoils->SteamCoil(CoilIndex).MaxSteamVolFlowRate;
1673 : }
1674 :
1675 3 : return MaxSteamFlowRate;
1676 : }
1677 :
1678 2 : int GetCoilAirInletNode(EnergyPlusData &state,
1679 : int const CoilIndex, // must match coil types in this module
1680 : std::string const &CoilName, // must match coil names for the coil type
1681 : bool &ErrorsFound // set to true if problem
1682 : )
1683 : {
1684 :
1685 : // FUNCTION INFORMATION:
1686 : // AUTHOR R. Raustad
1687 : // DATE WRITTEN July 2007
1688 : // MODIFIED na
1689 : // RE-ENGINEERED na
1690 :
1691 : // PURPOSE OF THIS FUNCTION:
1692 : // This function looks up the air inlet node number for the given coil and returns it. If
1693 : // incorrect coil type or name is given, ErrorsFound is returned as true and node number is returned
1694 : // as zero.
1695 :
1696 : // Return value
1697 : int NodeNumber; // returned air inlet node number of matched coil
1698 :
1699 : // Obtains and Allocates SteamCoil related parameters from input file
1700 2 : if (state.dataSteamCoils->GetSteamCoilsInputFlag) { // First time subroutine has been entered
1701 0 : GetSteamCoilInput(state);
1702 0 : state.dataSteamCoils->GetSteamCoilsInputFlag = false;
1703 : }
1704 :
1705 2 : if (CoilIndex == 0) {
1706 0 : ShowSevereError(state, format("GetCoilAirInletNode: Could not find CoilType = \"Coil:Heating:Steam\" with Name = {}", CoilName));
1707 0 : ErrorsFound = true;
1708 0 : NodeNumber = 0;
1709 : } else {
1710 2 : NodeNumber = state.dataSteamCoils->SteamCoil(CoilIndex).AirInletNodeNum;
1711 : }
1712 :
1713 2 : return NodeNumber;
1714 : }
1715 :
1716 2 : int GetCoilAirOutletNode(EnergyPlusData &state,
1717 : int const CoilIndex, // must match coil types in this module
1718 : std::string const &CoilName, // must match coil names for the coil type
1719 : bool &ErrorsFound // set to true if problem
1720 : )
1721 : {
1722 :
1723 : // FUNCTION INFORMATION:
1724 : // AUTHOR R. Raustad
1725 : // DATE WRITTEN July 2007
1726 : // MODIFIED na
1727 : // RE-ENGINEERED na
1728 :
1729 : // PURPOSE OF THIS FUNCTION:
1730 : // This function looks up the air outlet node number for the given coil and returns it. If
1731 : // incorrect coil type or name is given, ErrorsFound is returned as true and node number is returned
1732 : // as zero.
1733 :
1734 : // METHODOLOGY EMPLOYED:
1735 : // na
1736 :
1737 : // REFERENCES:
1738 : // na
1739 :
1740 : // USE STATEMENTS:
1741 : // na
1742 :
1743 : // Return value
1744 : int NodeNumber; // returned air inlet node number of matched coil
1745 :
1746 : // Obtains and Allocates SteamCoil related parameters from input file
1747 2 : if (state.dataSteamCoils->GetSteamCoilsInputFlag) { // First time subroutine has been entered
1748 0 : GetSteamCoilInput(state);
1749 0 : state.dataSteamCoils->GetSteamCoilsInputFlag = false;
1750 : }
1751 :
1752 2 : if (CoilIndex == 0) {
1753 0 : ShowSevereError(state, format("GetCoilAirOutletNode: Could not find CoilType = \"Coil:Heating:Steam\" with Name = {}", CoilName));
1754 0 : ErrorsFound = true;
1755 0 : NodeNumber = 0;
1756 : } else {
1757 2 : NodeNumber = state.dataSteamCoils->SteamCoil(CoilIndex).AirOutletNodeNum;
1758 : }
1759 :
1760 2 : return NodeNumber;
1761 : }
1762 :
1763 0 : int GetCoilAirOutletNode(EnergyPlusData &state,
1764 : std::string const &CoilType, // must match coil types in this module
1765 : std::string const &CoilName, // must match coil names for the coil type
1766 : [[maybe_unused]] bool &ErrorsFound // set to true if problem
1767 : )
1768 : {
1769 :
1770 : // FUNCTION INFORMATION:
1771 : // AUTHOR R. Raustad
1772 : // DATE WRITTEN July 2007
1773 : // MODIFIED na
1774 : // RE-ENGINEERED na
1775 :
1776 : // PURPOSE OF THIS FUNCTION:
1777 : // This function looks up the air outlet node number for the given coil and returns it. If
1778 : // incorrect coil type or name is given, ErrorsFound is returned as true and node number is returned
1779 : // as zero.
1780 :
1781 : // Return value
1782 : int NodeNumber; // returned air inlet node number of matched coil
1783 :
1784 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
1785 : int IndexNum; // returned air inlet node number of matched coil
1786 :
1787 : // Obtains and Allocates SteamCoil related parameters from input file
1788 0 : if (state.dataSteamCoils->GetSteamCoilsInputFlag) { // First time subroutine has been entered
1789 0 : GetSteamCoilInput(state);
1790 0 : state.dataSteamCoils->GetSteamCoilsInputFlag = false;
1791 : }
1792 :
1793 0 : if (Util::SameString(CoilType, "Coil:Heating:Steam")) {
1794 0 : IndexNum = Util::FindItem(CoilName, state.dataSteamCoils->SteamCoil);
1795 : } else {
1796 0 : IndexNum = 0;
1797 : }
1798 :
1799 0 : if (IndexNum == 0) {
1800 0 : NodeNumber = 0;
1801 : } else {
1802 0 : NodeNumber = state.dataSteamCoils->SteamCoil(IndexNum).AirOutletNodeNum;
1803 : }
1804 :
1805 0 : return NodeNumber;
1806 : }
1807 :
1808 1 : int GetCoilSteamInletNode(EnergyPlusData &state,
1809 : int const CoilIndex, // must match coil types in this module
1810 : std::string const &CoilName, // must match coil names for the coil type
1811 : bool &ErrorsFound // set to true if problem
1812 : )
1813 : {
1814 :
1815 : // FUNCTION INFORMATION:
1816 : // AUTHOR R. Raustad
1817 : // DATE WRITTEN July 2007
1818 : // MODIFIED na
1819 : // RE-ENGINEERED na
1820 :
1821 : // PURPOSE OF THIS FUNCTION:
1822 : // This function looks up the steam inlet node number for the given coil and returns it. If
1823 : // incorrect coil type or name is given, ErrorsFound is returned as true and node number is returned
1824 : // as zero.
1825 :
1826 : // Return value
1827 : int NodeNumber; // returned air inlet node number of matched coil
1828 :
1829 : // Obtains and Allocates SteamCoil related parameters from input file
1830 1 : if (state.dataSteamCoils->GetSteamCoilsInputFlag) { // First time subroutine has been entered
1831 0 : GetSteamCoilInput(state);
1832 0 : state.dataSteamCoils->GetSteamCoilsInputFlag = false;
1833 : }
1834 :
1835 1 : if (CoilIndex == 0) {
1836 0 : ShowSevereError(state, format("GetCoilSteamInletNode: Could not find CoilType = \"Coil:Heating:Steam\" with Name = {}", CoilName));
1837 0 : ErrorsFound = true;
1838 0 : NodeNumber = 0;
1839 : } else {
1840 1 : NodeNumber = state.dataSteamCoils->SteamCoil(CoilIndex).SteamInletNodeNum;
1841 : }
1842 :
1843 1 : return NodeNumber;
1844 : }
1845 :
1846 1 : int GetCoilSteamInletNode(EnergyPlusData &state,
1847 : std::string const &CoilType, // must match coil types in this module
1848 : std::string const &CoilName, // must match coil names for the coil type
1849 : bool &ErrorsFound // set to true if problem
1850 : )
1851 : {
1852 :
1853 : // FUNCTION INFORMATION:
1854 : // AUTHOR L. Lawrie (based on R. Raustad)
1855 : // DATE WRITTEN June 2008
1856 : // MODIFIED na
1857 : // RE-ENGINEERED na
1858 :
1859 : // PURPOSE OF THIS FUNCTION:
1860 : // This function looks up the steam inlet node number for the given coil and returns it. If
1861 : // incorrect coil type or name is given, ErrorsFound is returned as true and node number is returned
1862 : // as zero.
1863 :
1864 : // Return value
1865 : int NodeNumber; // returned air inlet node number of matched coil
1866 :
1867 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
1868 : int IndexNum; // returned air inlet node number of matched coil
1869 :
1870 : // Obtains and Allocates SteamCoil related parameters from input file
1871 1 : if (state.dataSteamCoils->GetSteamCoilsInputFlag) { // First time subroutine has been entered
1872 0 : GetSteamCoilInput(state);
1873 0 : state.dataSteamCoils->GetSteamCoilsInputFlag = false;
1874 : }
1875 :
1876 1 : if (Util::SameString(CoilType, "Coil:Heating:Steam")) {
1877 1 : IndexNum = Util::FindItem(CoilName, state.dataSteamCoils->SteamCoil);
1878 : } else {
1879 0 : IndexNum = 0;
1880 : }
1881 :
1882 1 : if (IndexNum == 0) {
1883 0 : ShowSevereError(state, format("GetCoilSteamInletNode: Could not find CoilType = \"Coil:Heating:Steam\" with Name = {}", CoilName));
1884 0 : ErrorsFound = true;
1885 0 : NodeNumber = 0;
1886 : } else {
1887 1 : NodeNumber = state.dataSteamCoils->SteamCoil(IndexNum).SteamInletNodeNum;
1888 : }
1889 :
1890 1 : return NodeNumber;
1891 : }
1892 :
1893 0 : int GetCoilSteamOutletNode(EnergyPlusData &state,
1894 : int const CoilIndex, // must match coil types in this module
1895 : std::string const &CoilName, // must match coil names for the coil type
1896 : bool &ErrorsFound // set to true if problem
1897 : )
1898 : {
1899 :
1900 : // FUNCTION INFORMATION:
1901 : // AUTHOR R. Raustad
1902 : // DATE WRITTEN July 2007
1903 : // MODIFIED na
1904 : // RE-ENGINEERED na
1905 :
1906 : // PURPOSE OF THIS FUNCTION:
1907 : // This function looks up the steam inlet node number for the given coil and returns it. If
1908 : // incorrect coil type or name is given, ErrorsFound is returned as true and node number is returned
1909 : // as zero.
1910 :
1911 : // Return value
1912 : int NodeNumber; // returned air inlet node number of matched coil
1913 :
1914 : // Obtains and Allocates SteamCoil related parameters from input file
1915 0 : if (state.dataSteamCoils->GetSteamCoilsInputFlag) { // First time subroutine has been entered
1916 0 : GetSteamCoilInput(state);
1917 0 : state.dataSteamCoils->GetSteamCoilsInputFlag = false;
1918 : }
1919 :
1920 0 : if (CoilIndex == 0) {
1921 0 : ShowSevereError(state, format("GetCoilSteamInletNode: Could not find CoilType = \"Coil:Heating:Steam\" with Name = {}", CoilName));
1922 0 : ErrorsFound = true;
1923 0 : NodeNumber = 0;
1924 : } else {
1925 0 : NodeNumber = state.dataSteamCoils->SteamCoil(CoilIndex).SteamOutletNodeNum;
1926 : }
1927 :
1928 0 : return NodeNumber;
1929 : }
1930 :
1931 1 : int GetCoilSteamOutletNode(EnergyPlusData &state,
1932 : std::string_view CoilType, // must match coil types in this module
1933 : std::string const &CoilName, // must match coil names for the coil type
1934 : bool &ErrorsFound // set to true if problem
1935 : )
1936 : {
1937 :
1938 : // FUNCTION INFORMATION:
1939 : // AUTHOR L. Lawrie (based on R. Raustad)
1940 : // DATE WRITTEN June 2008
1941 : // MODIFIED na
1942 : // RE-ENGINEERED na
1943 :
1944 : // PURPOSE OF THIS FUNCTION:
1945 : // This function looks up the steam inlet node number for the given coil and returns it. If
1946 : // incorrect coil type or name is given, ErrorsFound is returned as true and node number is returned
1947 : // as zero.
1948 :
1949 : // Return value
1950 : int NodeNumber; // returned air inlet node number of matched coil
1951 :
1952 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
1953 : int IndexNum; // returned air inlet node number of matched coil
1954 :
1955 : // Obtains and Allocates SteamCoil related parameters from input file
1956 1 : if (state.dataSteamCoils->GetSteamCoilsInputFlag) { // First time subroutine has been entered
1957 0 : GetSteamCoilInput(state);
1958 0 : state.dataSteamCoils->GetSteamCoilsInputFlag = false;
1959 : }
1960 :
1961 1 : if (Util::SameString(CoilType, "Coil:Heating:Steam")) {
1962 1 : IndexNum = Util::FindItem(CoilName, state.dataSteamCoils->SteamCoil);
1963 : } else {
1964 0 : IndexNum = 0;
1965 : }
1966 :
1967 1 : if (IndexNum == 0) {
1968 0 : ShowSevereError(state, format("GetCoilSteamInletNode: Could not find CoilType = \"Coil:Heating:Steam\" with Name = {}", CoilName));
1969 0 : ErrorsFound = true;
1970 0 : NodeNumber = 0;
1971 : } else {
1972 1 : NodeNumber = state.dataSteamCoils->SteamCoil(IndexNum).SteamOutletNodeNum;
1973 : }
1974 :
1975 1 : return NodeNumber;
1976 : }
1977 :
1978 0 : Real64 GetCoilCapacity(EnergyPlusData &state,
1979 : std::string const &CoilType, // must match coil types in this module
1980 : std::string const &CoilName, // must match coil names for the coil type
1981 : bool &ErrorsFound // set to true if problem
1982 : )
1983 : {
1984 :
1985 : // FUNCTION INFORMATION:
1986 : // AUTHOR R. Raustad
1987 : // DATE WRITTEN July 2007
1988 : // MODIFIED na
1989 : // RE-ENGINEERED na
1990 :
1991 : // PURPOSE OF THIS FUNCTION:
1992 : // This function looks up the steam coils operating capacity and returns it. If
1993 : // incorrect coil type or name is given, ErrorsFound is returned as true and node number is returned
1994 : // as zero.
1995 :
1996 : // Return value
1997 : Real64 Capacity; // returned operating capacity of matched coil (W)
1998 :
1999 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
2000 : int WhichCoil;
2001 :
2002 : // Obtains and Allocates SteamCoil related parameters from input file
2003 0 : if (state.dataSteamCoils->GetSteamCoilsInputFlag) { // First time subroutine has been entered
2004 0 : GetSteamCoilInput(state);
2005 0 : state.dataSteamCoils->GetSteamCoilsInputFlag = false;
2006 : }
2007 :
2008 0 : if (Util::SameString(CoilType, "Coil:Heating:Steam")) {
2009 0 : WhichCoil = Util::FindItem(CoilName, state.dataSteamCoils->SteamCoil);
2010 0 : if (WhichCoil != 0) {
2011 : // coil does not specify MaxWaterFlowRate
2012 0 : Capacity = state.dataSteamCoils->SteamCoil(WhichCoil).OperatingCapacity;
2013 : }
2014 : } else {
2015 0 : WhichCoil = 0;
2016 : }
2017 :
2018 0 : if (WhichCoil == 0) {
2019 0 : ShowSevereError(state, format("GetCoilSteamInletNode: Could not find CoilType=\"{}\" with Name=\"{}\"", CoilType, CoilName));
2020 0 : ErrorsFound = true;
2021 0 : Capacity = 0.0;
2022 : }
2023 :
2024 0 : return Capacity;
2025 : }
2026 :
2027 0 : CoilControlType GetTypeOfCoil(EnergyPlusData &state,
2028 : int const CoilIndex, // must match coil types in this module
2029 : std::string const &CoilName, // must match coil names for the coil type
2030 : bool &ErrorsFound // set to true if problem
2031 : )
2032 : {
2033 :
2034 : // FUNCTION INFORMATION:
2035 : // AUTHOR R. Raustad
2036 : // DATE WRITTEN July 2007
2037 : // MODIFIED na
2038 : // RE-ENGINEERED na
2039 :
2040 : // PURPOSE OF THIS FUNCTION:
2041 : // This function looks up the steam coils operating capacity and returns it. If
2042 : // incorrect coil type or name is given, ErrorsFound is returned as true and node number is returned
2043 : // as zero.
2044 :
2045 : // Obtains and Allocates SteamCoil related parameters from input file
2046 0 : if (state.dataSteamCoils->GetSteamCoilsInputFlag) { // First time subroutine has been entered
2047 0 : GetSteamCoilInput(state);
2048 0 : state.dataSteamCoils->GetSteamCoilsInputFlag = false;
2049 : }
2050 :
2051 0 : if (CoilIndex == 0) {
2052 0 : ShowSevereError(state, format("GetCoilSteamInletNode: Could not find CoilType = \"Coil:Heating:Steam\" with Name = {}", CoilName));
2053 0 : ErrorsFound = true;
2054 0 : return CoilControlType::Invalid;
2055 : } else {
2056 0 : return state.dataSteamCoils->SteamCoil(CoilIndex).TypeOfCoil;
2057 : }
2058 : }
2059 :
2060 0 : int GetSteamCoilControlNodeNum(EnergyPlusData &state,
2061 : std::string const &CoilType, // must match coil types in this module
2062 : std::string const &CoilName, // must match coil names for the coil type
2063 : bool &ErrorFlag // set to true if problem
2064 : )
2065 : {
2066 :
2067 : // FUNCTION INFORMATION:
2068 : // AUTHOR B. Nigusse, FSEC
2069 : // DATE WRITTEN January 2012
2070 : // MODIFIED na
2071 : // RE-ENGINEERED na
2072 :
2073 : // PURPOSE OF THIS FUNCTION:
2074 : // This function looks up the steam coils and returns the steam control node number. If
2075 : // incorrect coil type or name is given, ErrorsFound is returned as true and node number is returned
2076 : // as zero.
2077 :
2078 : // Return value
2079 : int NodeNumber; // returned node number of matched coil
2080 :
2081 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
2082 : int WhichCoil;
2083 :
2084 : // Obtains and Allocates SteamCoil related parameters from input file
2085 0 : if (state.dataSteamCoils->GetSteamCoilsInputFlag) { // First time subroutine has been entered
2086 0 : GetSteamCoilInput(state);
2087 0 : state.dataSteamCoils->GetSteamCoilsInputFlag = false;
2088 : }
2089 :
2090 0 : WhichCoil = 0;
2091 0 : NodeNumber = 0;
2092 0 : if (Util::SameString(CoilType, "Coil:Heating:Steam")) {
2093 0 : WhichCoil = Util::FindItem(CoilName, state.dataSteamCoils->SteamCoil);
2094 0 : if (WhichCoil != 0) {
2095 0 : NodeNumber = state.dataSteamCoils->SteamCoil(WhichCoil).TempSetPointNodeNum;
2096 : }
2097 : } else {
2098 0 : WhichCoil = 0;
2099 : }
2100 :
2101 0 : if (WhichCoil == 0) {
2102 0 : ShowSevereError(state, format("GetSteamCoilControlNodeNum: Could not find Coil, Type=\"{}\" Name=\"{}\"", CoilType, CoilName));
2103 0 : ErrorFlag = true;
2104 0 : NodeNumber = 0;
2105 : }
2106 :
2107 0 : return NodeNumber;
2108 : }
2109 :
2110 0 : int GetSteamCoilAvailScheduleIndex(EnergyPlusData &state,
2111 : std::string const &CoilType, // must match coil types in this module
2112 : std::string const &CoilName, // must match coil names for the coil type
2113 : bool &ErrorsFound // set to true if problem
2114 : )
2115 : {
2116 :
2117 : // FUNCTION INFORMATION:
2118 : // AUTHOR Chandan Sharma, FSEC
2119 : // DATE WRITTEN February 2013
2120 : // MODIFIED na
2121 : // RE-ENGINEERED na
2122 :
2123 : // PURPOSE OF THIS FUNCTION:
2124 : // This function looks up the given coil and returns the availability schedule index. If
2125 : // incorrect coil type or name is given, ErrorsFound is returned as true and index is returned
2126 : // as zero.
2127 :
2128 : // Return value
2129 : int AvailSchIndex; // returned availability schedule of matched coil
2130 :
2131 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
2132 : int WhichCoil;
2133 :
2134 : // Obtains and Allocates HeatingCoil related parameters from input file
2135 0 : if (state.dataSteamCoils->GetSteamCoilsInputFlag) { // First time subroutine has been entered
2136 0 : GetSteamCoilInput(state);
2137 0 : state.dataSteamCoils->GetSteamCoilsInputFlag = false;
2138 : }
2139 :
2140 0 : WhichCoil = 0;
2141 0 : AvailSchIndex = 0;
2142 :
2143 0 : if (Util::SameString(CoilType, "Coil:Heating:Steam")) {
2144 0 : WhichCoil = Util::FindItem(CoilName, state.dataSteamCoils->SteamCoil);
2145 0 : if (WhichCoil != 0) {
2146 0 : AvailSchIndex = state.dataSteamCoils->SteamCoil(WhichCoil).availSched->Num;
2147 : }
2148 : } else {
2149 0 : WhichCoil = 0;
2150 : }
2151 :
2152 0 : if (WhichCoil == 0) {
2153 0 : ShowSevereError(state, format("GetCoilAvailScheduleIndex: Could not find Coil, Type=\"{}\" Name=\"{}\"", CoilType, CoilName));
2154 0 : ErrorsFound = true;
2155 0 : AvailSchIndex = 0;
2156 : }
2157 :
2158 0 : return AvailSchIndex;
2159 : }
2160 :
2161 0 : void SetSteamCoilData(EnergyPlusData &state,
2162 : int const CoilNum, // Number of hot water heating Coil
2163 : bool &ErrorsFound, // Set to true if certain errors found
2164 : ObjexxFCL::Optional_bool DesiccantRegenerationCoil, // Flag that this coil is used as regeneration air heating coil
2165 : ObjexxFCL::Optional_int DesiccantDehumIndex // Index for the desiccant dehum system where this caoil is used
2166 : )
2167 : {
2168 :
2169 : // FUNCTION INFORMATION:
2170 : // AUTHOR Bereket Nigusse
2171 : // DATE WRITTEN February 2016
2172 : // MODIFIED na
2173 : // RE-ENGINEERED na
2174 :
2175 : // PURPOSE OF THIS FUNCTION:
2176 : // This function sets data to water Heating Coil using the coil index and arguments passed
2177 :
2178 0 : if (state.dataSteamCoils->GetSteamCoilsInputFlag) {
2179 0 : GetSteamCoilInput(state);
2180 0 : state.dataSteamCoils->GetSteamCoilsInputFlag = false;
2181 : }
2182 :
2183 0 : if (CoilNum <= 0 || CoilNum > state.dataSteamCoils->NumSteamCoils) {
2184 0 : ShowSevereError(state,
2185 0 : format("SetHeatingCoilData: called with heating coil Number out of range={} should be >0 and <{}",
2186 : CoilNum,
2187 0 : state.dataSteamCoils->NumSteamCoils));
2188 0 : ErrorsFound = true;
2189 0 : return;
2190 : }
2191 :
2192 0 : if (present(DesiccantRegenerationCoil)) {
2193 0 : state.dataSteamCoils->SteamCoil(CoilNum).DesiccantRegenerationCoil = DesiccantRegenerationCoil;
2194 : }
2195 :
2196 0 : if (present(DesiccantDehumIndex)) {
2197 0 : state.dataSteamCoils->SteamCoil(CoilNum).DesiccantDehumNum = DesiccantDehumIndex;
2198 : }
2199 : }
2200 : // End of Utility subroutines for the SteamCoil Module
2201 :
2202 : } // namespace SteamCoils
2203 :
2204 : } // namespace EnergyPlus
|