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