Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2023, The Board of Trustees of the University of Illinois,
2 : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
3 : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
4 : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
5 : // contributors. All rights reserved.
6 : //
7 : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
8 : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
9 : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
10 : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
11 : // derivative works, and perform publicly and display publicly, and to permit others to do so.
12 : //
13 : // Redistribution and use in source and binary forms, with or without modification, are permitted
14 : // provided that the following conditions are met:
15 : //
16 : // (1) Redistributions of source code must retain the above copyright notice, this list of
17 : // conditions and the following disclaimer.
18 : //
19 : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
20 : // conditions and the following disclaimer in the documentation and/or other materials
21 : // provided with the distribution.
22 : //
23 : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
24 : // the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
25 : // used to endorse or promote products derived from this software without specific prior
26 : // written permission.
27 : //
28 : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
29 : // without changes from the version obtained under this License, or (ii) Licensee makes a
30 : // reference solely to the software portion of its product, Licensee must refer to the
31 : // software as "EnergyPlus version X" software, where "X" is the version number Licensee
32 : // obtained under this License and may not use a different name for the software. Except as
33 : // specifically required in this Section (4), Licensee shall not use in a company name, a
34 : // product name, in advertising, publicity, or other promotional activities any name, trade
35 : // name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
36 : // similar designation, without the U.S. Department of Energy's prior written consent.
37 : //
38 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
39 : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
40 : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
41 : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43 : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
45 : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46 : // POSSIBILITY OF SUCH DAMAGE.
47 :
48 : // C++ Headers
49 : #include <cmath>
50 :
51 : // ObjexxFCL Headers
52 : #include <ObjexxFCL/Array.functions.hh>
53 : #include <ObjexxFCL/Fmath.hh>
54 :
55 : // EnergyPlus Headers
56 : #include <EnergyPlus/Autosizing/All_Simple_Sizing.hh>
57 : #include <EnergyPlus/Autosizing/CoolingAirFlowSizing.hh>
58 : #include <EnergyPlus/Autosizing/CoolingCapacitySizing.hh>
59 : #include <EnergyPlus/Autosizing/CoolingWaterDesAirInletHumRatSizing.hh>
60 : #include <EnergyPlus/Autosizing/CoolingWaterDesAirInletTempSizing.hh>
61 : #include <EnergyPlus/Autosizing/CoolingWaterDesAirOutletHumRatSizing.hh>
62 : #include <EnergyPlus/Autosizing/CoolingWaterDesAirOutletTempSizing.hh>
63 : #include <EnergyPlus/Autosizing/CoolingWaterDesWaterInletTempSizing.hh>
64 : #include <EnergyPlus/Autosizing/CoolingWaterNumofTubesPerRowSizing.hh>
65 : #include <EnergyPlus/Autosizing/CoolingWaterflowSizing.hh>
66 : #include <EnergyPlus/Autosizing/HeatingAirFlowSizing.hh>
67 : #include <EnergyPlus/Autosizing/HeatingAirflowUASizing.hh>
68 : #include <EnergyPlus/Autosizing/HeatingCapacitySizing.hh>
69 : #include <EnergyPlus/Autosizing/HeatingWaterDesAirInletHumRatSizing.hh>
70 : #include <EnergyPlus/Autosizing/HeatingWaterDesAirInletTempSizing.hh>
71 : #include <EnergyPlus/Autosizing/HeatingWaterDesCoilLoadUsedForUASizing.hh>
72 : #include <EnergyPlus/Autosizing/HeatingWaterDesCoilWaterVolFlowUsedForUASizing.hh>
73 : #include <EnergyPlus/Autosizing/HeatingWaterflowSizing.hh>
74 : #include <EnergyPlus/Autosizing/WaterHeatingCapacitySizing.hh>
75 : #include <EnergyPlus/Autosizing/WaterHeatingCoilUASizing.hh>
76 : #include <EnergyPlus/BranchNodeConnections.hh>
77 : #include <EnergyPlus/Data/EnergyPlusData.hh>
78 : #include <EnergyPlus/DataBranchAirLoopPlant.hh>
79 : #include <EnergyPlus/DataContaminantBalance.hh>
80 : #include <EnergyPlus/DataEnvironment.hh>
81 : #include <EnergyPlus/DataHVACGlobals.hh>
82 : #include <EnergyPlus/DataIPShortCuts.hh>
83 : #include <EnergyPlus/DataLoopNode.hh>
84 : #include <EnergyPlus/DataSizing.hh>
85 : #include <EnergyPlus/DataWater.hh>
86 : #include <EnergyPlus/EMSManager.hh>
87 : #include <EnergyPlus/FaultsManager.hh>
88 : #include <EnergyPlus/FluidProperties.hh>
89 : #include <EnergyPlus/General.hh>
90 : #include <EnergyPlus/GeneralRoutines.hh>
91 : #include <EnergyPlus/GlobalNames.hh>
92 : #include <EnergyPlus/HVACControllers.hh>
93 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
94 : #include <EnergyPlus/NodeInputManager.hh>
95 : #include <EnergyPlus/OutputProcessor.hh>
96 : #include <EnergyPlus/OutputReportPredefined.hh>
97 : #include <EnergyPlus/Plant/DataPlant.hh>
98 : #include <EnergyPlus/PlantUtilities.hh>
99 : #include <EnergyPlus/Psychrometrics.hh>
100 : #include <EnergyPlus/ReportCoilSelection.hh>
101 : #include <EnergyPlus/ScheduleManager.hh>
102 : #include <EnergyPlus/SetPointManager.hh>
103 : #include <EnergyPlus/SimAirServingZones.hh>
104 : #include <EnergyPlus/UtilityRoutines.hh>
105 : #include <EnergyPlus/WaterCoils.hh>
106 : #include <EnergyPlus/WaterManager.hh>
107 :
108 : namespace EnergyPlus::WaterCoils {
109 : // Module containing the WaterCoil simulation routines
110 :
111 : // MODULE INFORMATION:
112 : // AUTHOR Richard J. Liesen
113 : // DATE WRITTEN April 1998
114 : // MODIFIED April 2004: Rahul Chillar
115 : // Feb. 2010, Brent Griffith, Plant Demand Side Update, general fluid properties
116 : // RE-ENGINEERED na
117 :
118 : // PURPOSE OF THIS MODULE:
119 : // To encapsulate the data and algorithms required to
120 : // manage the WaterCoil System Component
121 :
122 : using namespace DataLoopNode;
123 : using namespace DataHVACGlobals;
124 :
125 : using FluidProperties::GetDensityGlycol;
126 : using FluidProperties::GetSpecificHeatGlycol;
127 : using Psychrometrics::PsyCpAirFnW;
128 : using Psychrometrics::PsyHFnTdbRhPb;
129 : using Psychrometrics::PsyHFnTdbW;
130 : using Psychrometrics::PsyRhoAirFnPbTdbW;
131 : using Psychrometrics::PsyTdbFnHW;
132 : using Psychrometrics::PsyTdpFnWPb;
133 : using Psychrometrics::PsyTsatFnHPb;
134 : using Psychrometrics::PsyWFnTdbH;
135 : using Psychrometrics::PsyWFnTdbRhPb;
136 : using Psychrometrics::PsyWFnTdbTwbPb;
137 : using Psychrometrics::PsyWFnTdpPb;
138 : using namespace ScheduleManager;
139 :
140 137535475 : void SimulateWaterCoilComponents(EnergyPlusData &state,
141 : std::string_view CompName,
142 : bool const FirstHVACIteration,
143 : int &CompIndex,
144 : Optional<Real64> QActual,
145 : Optional_int_const FanOpMode,
146 : Optional<Real64 const> PartLoadRatio)
147 : {
148 :
149 : // SUBROUTINE INFORMATION:
150 : // AUTHOR Richard Liesen
151 : // DATE WRITTEN February 1998
152 : // MODIFIED na
153 : // RE-ENGINEERED na
154 :
155 : // PURPOSE OF THIS SUBROUTINE:
156 : // This subroutine manages WaterCoil component simulation.
157 :
158 : // Using/Aliasing
159 :
160 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
161 : int CoilNum; // The WaterCoil that you are currently loading input into
162 : int OpMode; // fan operating mode
163 : Real64 PartLoadFrac; // part-load fraction of heating coil
164 :
165 : // Obtains and Allocates WaterCoil related parameters from input file
166 137535475 : if (state.dataWaterCoils->GetWaterCoilsInputFlag) { // First time subroutine has been entered
167 0 : GetWaterCoilInput(state);
168 0 : state.dataWaterCoils->GetWaterCoilsInputFlag = false;
169 : }
170 :
171 : // Find the correct WaterCoilNumber with the Coil Name
172 137535475 : if (CompIndex == 0) {
173 767839 : CoilNum = UtilityRoutines::FindItemInList(CompName, state.dataWaterCoils->WaterCoil);
174 767839 : if (CoilNum == 0) {
175 0 : ShowFatalError(state, "SimulateWaterCoilComponents: Coil not found=" + std::string{CompName});
176 : }
177 767839 : CompIndex = CoilNum;
178 : } else {
179 136767636 : CoilNum = CompIndex;
180 136767636 : if (CoilNum > state.dataWaterCoils->NumWaterCoils || CoilNum < 1) {
181 0 : ShowFatalError(state,
182 0 : format("SimulateWaterCoilComponents: Invalid CompIndex passed={}, Number of Water Coils={}, Coil name={}",
183 : CoilNum,
184 0 : state.dataWaterCoils->NumWaterCoils,
185 0 : CompName));
186 : }
187 136767636 : if (state.dataWaterCoils->CheckEquipName(CoilNum)) {
188 3092 : if (CompName != state.dataWaterCoils->WaterCoil(CoilNum).Name) {
189 0 : ShowFatalError(state,
190 0 : format("SimulateWaterCoilComponents: Invalid CompIndex passed={}, Coil name={}, stored Coil Name for that index={}",
191 : CoilNum,
192 : CompName,
193 0 : state.dataWaterCoils->WaterCoil(CoilNum).Name));
194 : }
195 3092 : state.dataWaterCoils->CheckEquipName(CoilNum) = false;
196 : }
197 : }
198 :
199 : // With the correct CoilNum Initialize
200 137535475 : InitWaterCoil(state, CoilNum, FirstHVACIteration); // Initialize all WaterCoil related parameters
201 :
202 137535475 : if (present(FanOpMode)) {
203 5522026 : OpMode = FanOpMode;
204 : } else {
205 132013449 : OpMode = ContFanCycCoil;
206 : }
207 137535475 : if (present(PartLoadRatio)) {
208 4127696 : PartLoadFrac = PartLoadRatio;
209 : } else {
210 133407779 : PartLoadFrac = 1.0;
211 : }
212 :
213 : // Calculate the Correct WaterCoil Model with the current CoilNum
214 137535475 : if (state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterDetailedFlatCooling) {
215 3336941 : CalcDetailFlatFinCoolingCoil(state, CoilNum, state.dataWaterCoils->SimCalc, OpMode, PartLoadFrac);
216 3336941 : if (present(QActual)) QActual = state.dataWaterCoils->WaterCoil(CoilNum).SenWaterCoolingCoilRate;
217 134198534 : } else if (state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterCooling) {
218 22043969 : CoolingCoil(state, CoilNum, FirstHVACIteration, state.dataWaterCoils->SimCalc, OpMode, PartLoadFrac);
219 22043969 : if (present(QActual)) QActual = state.dataWaterCoils->WaterCoil(CoilNum).SenWaterCoolingCoilRate;
220 : }
221 :
222 137535475 : if (state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterSimpleHeating) {
223 112154565 : CalcSimpleHeatingCoil(state, CoilNum, OpMode, PartLoadFrac, state.dataWaterCoils->SimCalc);
224 112154565 : if (present(QActual)) QActual = state.dataWaterCoils->WaterCoil(CoilNum).TotWaterHeatingCoilRate;
225 : }
226 :
227 : // Update the current WaterCoil to the outlet nodes
228 137535475 : UpdateWaterCoil(state, CoilNum);
229 :
230 : // Report the current WaterCoil
231 137535475 : ReportWaterCoil(state, CoilNum);
232 137535475 : }
233 :
234 : // Get Input Section of the Module
235 : //******************************************************************************
236 :
237 325 : void GetWaterCoilInput(EnergyPlusData &state)
238 : {
239 :
240 : // SUBROUTINE INFORMATION:
241 : // AUTHOR Richard Liesen
242 : // DATE WRITTEN April 1998
243 : // MODIFIED April 2004: Rahul Chillar
244 : // November 2013: Tianzhen Hong for fouling coils
245 : // RE-ENGINEERED na
246 :
247 : // PURPOSE OF THIS SUBROUTINE:
248 : // Obtains input data for coils and stores it in coil data structures
249 :
250 : // METHODOLOGY EMPLOYED:
251 : // Uses "Get" routines to read in data.
252 :
253 : // Using/Aliasing
254 : using BranchNodeConnections::TestCompSet;
255 : using DataSizing::AutoSize;
256 : using GlobalNames::VerifyUniqueCoilName;
257 : using NodeInputManager::GetOnlySingleNode;
258 : using SetPointManager::NodeHasSPMCtrlVarType;
259 : using WaterManager::SetupTankSupplyComponent;
260 : using namespace FaultsManager;
261 :
262 : // SUBROUTINE PARAMETER DEFINITIONS:
263 : static constexpr std::string_view RoutineName("GetWaterCoilInput: "); // include trailing blank space
264 :
265 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
266 : int CoilNum; // The WaterCoil that you are currently loading input into
267 325 : int NumSimpHeat(0);
268 325 : int NumFlatFin(0);
269 325 : int NumCooling(0);
270 : int SimpHeatNum;
271 : int FlatFinNum;
272 : int CoolingNum;
273 : int NumAlphas;
274 : int NumNums;
275 : int IOStat;
276 650 : std::string CurrentModuleObject; // for ease in getting objects
277 650 : Array1D_string AlphArray; // Alpha input items for object
278 650 : Array1D_string cAlphaFields; // Alpha field names
279 650 : Array1D_string cNumericFields; // Numeric field names
280 650 : Array1D<Real64> NumArray; // Numeric input items for object
281 650 : Array1D_bool lAlphaBlanks; // Logical array, alpha field input BLANK = .TRUE.
282 650 : Array1D_bool lNumericBlanks; // Logical array, numeric field input BLANK = .TRUE.
283 325 : int MaxNums(0); // Maximum number of numeric input fields
284 325 : int MaxAlphas(0); // Maximum number of alpha input fields
285 325 : int TotalArgs(0); // Total number of alpha and numeric arguments (max) for a certain object in the input file
286 325 : bool ErrorsFound(false); // If errors detected in input
287 :
288 325 : NumSimpHeat = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Coil:Heating:Water");
289 325 : NumFlatFin = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Coil:Cooling:Water:DetailedGeometry");
290 325 : NumCooling = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Coil:Cooling:Water");
291 325 : state.dataWaterCoils->NumWaterCoils = NumSimpHeat + NumFlatFin + NumCooling;
292 :
293 325 : if (state.dataWaterCoils->NumWaterCoils > 0) {
294 314 : state.dataWaterCoils->WaterCoil.allocate(state.dataWaterCoils->NumWaterCoils);
295 314 : state.dataWaterCoils->WaterCoilNumericFields.allocate(state.dataWaterCoils->NumWaterCoils);
296 314 : state.dataWaterCoils->WaterTempCoolCoilErrs.dimension(state.dataWaterCoils->NumWaterCoils, 0);
297 314 : state.dataWaterCoils->PartWetCoolCoilErrs.dimension(state.dataWaterCoils->NumWaterCoils, 0);
298 314 : state.dataWaterCoils->CheckEquipName.dimension(state.dataWaterCoils->NumWaterCoils, true);
299 : }
300 :
301 325 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, "Coil:Heating:Water", TotalArgs, NumAlphas, NumNums);
302 325 : MaxNums = max(MaxNums, NumNums);
303 325 : MaxAlphas = max(MaxAlphas, NumAlphas);
304 325 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, "Coil:Cooling:Water:DetailedGeometry", TotalArgs, NumAlphas, NumNums);
305 325 : MaxNums = max(MaxNums, NumNums);
306 325 : MaxAlphas = max(MaxAlphas, NumAlphas);
307 325 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, "Coil:Cooling:Water", TotalArgs, NumAlphas, NumNums);
308 325 : MaxNums = max(MaxNums, NumNums);
309 325 : MaxAlphas = max(MaxAlphas, NumAlphas);
310 :
311 325 : AlphArray.allocate(MaxAlphas);
312 325 : cAlphaFields.allocate(MaxAlphas);
313 325 : cNumericFields.allocate(MaxNums);
314 325 : NumArray.dimension(MaxNums, 0.0);
315 325 : lAlphaBlanks.dimension(MaxAlphas, true);
316 325 : lNumericBlanks.dimension(MaxNums, true);
317 325 : auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
318 325 : CurrentModuleObject = "Coil:Heating:Water";
319 : // Get the data for simple heating coils
320 2879 : for (SimpHeatNum = 1; SimpHeatNum <= NumSimpHeat; ++SimpHeatNum) {
321 :
322 2554 : CoilNum = SimpHeatNum;
323 :
324 2554 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
325 : CurrentModuleObject,
326 : SimpHeatNum,
327 : AlphArray,
328 : NumAlphas,
329 : NumArray,
330 : NumNums,
331 : IOStat,
332 : lNumericBlanks,
333 : lAlphaBlanks,
334 : cAlphaFields,
335 : cNumericFields);
336 :
337 2554 : state.dataWaterCoils->WaterCoilNumericFields(CoilNum).FieldNames.allocate(MaxNums);
338 2554 : state.dataWaterCoils->WaterCoilNumericFields(CoilNum).FieldNames = "";
339 2554 : state.dataWaterCoils->WaterCoilNumericFields(CoilNum).FieldNames = cNumericFields;
340 2554 : UtilityRoutines::IsNameEmpty(state, AlphArray(1), cCurrentModuleObject, ErrorsFound);
341 :
342 : // ErrorsFound will be set to True if problem was found, left untouched otherwise
343 2554 : VerifyUniqueCoilName(state, CurrentModuleObject, AlphArray(1), ErrorsFound, CurrentModuleObject + " Name");
344 :
345 2554 : state.dataWaterCoils->WaterCoil(CoilNum).Name = AlphArray(1);
346 2554 : state.dataWaterCoils->WaterCoil(CoilNum).Schedule = AlphArray(2);
347 2554 : if (lAlphaBlanks(2)) {
348 49 : state.dataWaterCoils->WaterCoil(CoilNum).SchedPtr = DataGlobalConstants::ScheduleAlwaysOn;
349 : } else {
350 2505 : state.dataWaterCoils->WaterCoil(CoilNum).SchedPtr = GetScheduleIndex(state, AlphArray(2));
351 2505 : if (state.dataWaterCoils->WaterCoil(CoilNum).SchedPtr == 0) {
352 0 : ShowSevereError(state,
353 0 : CurrentModuleObject + ": invalid " + cAlphaFields(2) + " entered =" + AlphArray(2) + " for " + cAlphaFields(1) + '=' +
354 0 : AlphArray(1));
355 0 : ErrorsFound = true;
356 : }
357 : }
358 :
359 2554 : state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilTypeA = "Heating";
360 2554 : state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilType = DataPlant::PlantEquipmentType::CoilWaterCooling; // 'Heating'
361 2554 : state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilModelA = "SIMPLE";
362 2554 : state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilModel = CoilModel::HeatingSimple; // 'SIMPLE'
363 2554 : state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilType = DataPlant::PlantEquipmentType::CoilWaterSimpleHeating;
364 :
365 2554 : state.dataWaterCoils->WaterCoil(CoilNum).UACoil = NumArray(1);
366 2554 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilVariable = state.dataWaterCoils->WaterCoil(CoilNum).UACoil;
367 2554 : state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterVolFlowRate = NumArray(2);
368 2554 : state.dataWaterCoils->WaterCoil(CoilNum).WaterInletNodeNum = GetOnlySingleNode(state,
369 2554 : AlphArray(3),
370 : ErrorsFound,
371 : DataLoopNode::ConnectionObjectType::CoilHeatingWater,
372 2554 : AlphArray(1),
373 : DataLoopNode::NodeFluidType::Water,
374 : DataLoopNode::ConnectionType::Inlet,
375 : NodeInputManager::CompFluidStream::Secondary,
376 2554 : ObjectIsNotParent);
377 2554 : state.dataWaterCoils->WaterCoil(CoilNum).WaterOutletNodeNum = GetOnlySingleNode(state,
378 2554 : AlphArray(4),
379 : ErrorsFound,
380 : DataLoopNode::ConnectionObjectType::CoilHeatingWater,
381 2554 : AlphArray(1),
382 : DataLoopNode::NodeFluidType::Water,
383 : DataLoopNode::ConnectionType::Outlet,
384 : NodeInputManager::CompFluidStream::Secondary,
385 2554 : ObjectIsNotParent);
386 2554 : state.dataWaterCoils->WaterCoil(CoilNum).AirInletNodeNum = GetOnlySingleNode(state,
387 2554 : AlphArray(5),
388 : ErrorsFound,
389 : DataLoopNode::ConnectionObjectType::CoilHeatingWater,
390 2554 : AlphArray(1),
391 : DataLoopNode::NodeFluidType::Air,
392 : DataLoopNode::ConnectionType::Inlet,
393 : NodeInputManager::CompFluidStream::Primary,
394 2554 : ObjectIsNotParent);
395 2554 : state.dataWaterCoils->WaterCoil(CoilNum).AirOutletNodeNum = GetOnlySingleNode(state,
396 2554 : AlphArray(6),
397 : ErrorsFound,
398 : DataLoopNode::ConnectionObjectType::CoilHeatingWater,
399 2554 : AlphArray(1),
400 : DataLoopNode::NodeFluidType::Air,
401 : DataLoopNode::ConnectionType::Outlet,
402 : NodeInputManager::CompFluidStream::Primary,
403 2554 : ObjectIsNotParent);
404 :
405 2554 : if (AlphArray(7) == "NOMINALCAPACITY") { // not "UFACTORTIMESAREAANDDESIGNWATERFLOWRATE"
406 52 : state.dataWaterCoils->WaterCoil(CoilNum).CoilPerfInpMeth = state.dataWaterCoils->NomCap;
407 :
408 : } else {
409 : // will be caught by input processor
410 2502 : state.dataWaterCoils->WaterCoil(CoilNum).CoilPerfInpMeth = state.dataWaterCoils->UAandFlow;
411 : }
412 :
413 2554 : state.dataWaterCoils->WaterCoil(CoilNum).DesTotWaterCoilLoad = NumArray(3);
414 :
415 4802 : if (state.dataWaterCoils->WaterCoil(CoilNum).UACoil == AutoSize &&
416 2248 : state.dataWaterCoils->WaterCoil(CoilNum).CoilPerfInpMeth == state.dataWaterCoils->UAandFlow)
417 2200 : state.dataWaterCoils->WaterCoil(CoilNum).RequestingAutoSize = true;
418 2554 : if (state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterVolFlowRate == AutoSize)
419 2248 : state.dataWaterCoils->WaterCoil(CoilNum).RequestingAutoSize = true;
420 5065 : if (state.dataWaterCoils->WaterCoil(CoilNum).DesTotWaterCoilLoad == AutoSize &&
421 2511 : state.dataWaterCoils->WaterCoil(CoilNum).CoilPerfInpMeth == state.dataWaterCoils->NomCap)
422 9 : state.dataWaterCoils->WaterCoil(CoilNum).RequestingAutoSize = true;
423 :
424 2554 : state.dataWaterCoils->WaterCoil(CoilNum).DesInletWaterTemp = NumArray(4);
425 2554 : state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirTemp = NumArray(5);
426 2554 : state.dataWaterCoils->WaterCoil(CoilNum).DesOutletWaterTemp = NumArray(6);
427 2554 : state.dataWaterCoils->WaterCoil(CoilNum).DesOutletAirTemp = NumArray(7);
428 2554 : state.dataWaterCoils->WaterCoil(CoilNum).RatioAirSideToWaterSideConvect = NumArray(8);
429 2554 : if (!lNumericBlanks(9)) {
430 93 : state.dataWaterCoils->WaterCoil(CoilNum).DesignWaterDeltaTemp = NumArray(9);
431 93 : state.dataWaterCoils->WaterCoil(CoilNum).UseDesignWaterDeltaTemp = true;
432 : } else {
433 2461 : state.dataWaterCoils->WaterCoil(CoilNum).UseDesignWaterDeltaTemp = false;
434 : }
435 2554 : if (state.dataWaterCoils->WaterCoil(CoilNum).DesInletWaterTemp <= state.dataWaterCoils->WaterCoil(CoilNum).DesOutletWaterTemp) {
436 0 : ShowSevereError(state, "For " + CurrentModuleObject + ", " + AlphArray(1));
437 0 : ShowContinueError(state, " the " + cNumericFields(4) + " must be greater than the " + cNumericFields(6) + '.');
438 0 : ErrorsFound = true;
439 : }
440 2554 : if (state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirTemp >= state.dataWaterCoils->WaterCoil(CoilNum).DesOutletAirTemp) {
441 0 : ShowSevereError(state, "For " + CurrentModuleObject + ", " + AlphArray(1));
442 0 : ShowContinueError(state, " the " + cNumericFields(5) + " must be less than the " + cNumericFields(7) + '.');
443 0 : ErrorsFound = true;
444 : }
445 2554 : if (state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirTemp >= state.dataWaterCoils->WaterCoil(CoilNum).DesInletWaterTemp) {
446 0 : ShowSevereError(state, "For " + CurrentModuleObject + ", " + AlphArray(1));
447 0 : ShowContinueError(state, " the " + cNumericFields(5) + " must be less than the " + cNumericFields(4) + '.');
448 0 : ErrorsFound = true;
449 : }
450 :
451 2554 : TestCompSet(state, CurrentModuleObject, AlphArray(1), AlphArray(3), AlphArray(4), "Water Nodes");
452 2554 : TestCompSet(state, CurrentModuleObject, AlphArray(1), AlphArray(5), AlphArray(6), "Air Nodes");
453 :
454 : // Setup the Simple Heating Coil reporting variables
455 : // CurrentModuleObject = "Coil:Heating:Water"
456 10216 : SetupOutputVariable(state,
457 : "Heating Coil Heating Energy",
458 : OutputProcessor::Unit::J,
459 2554 : state.dataWaterCoils->WaterCoil(CoilNum).TotWaterHeatingCoilEnergy,
460 : OutputProcessor::SOVTimeStepType::System,
461 : OutputProcessor::SOVStoreType::Summed,
462 2554 : state.dataWaterCoils->WaterCoil(CoilNum).Name,
463 : _,
464 : "ENERGYTRANSFER",
465 : "HEATINGCOILS",
466 : _,
467 2554 : "System");
468 10216 : SetupOutputVariable(state,
469 : "Heating Coil Source Side Heat Transfer Energy",
470 : OutputProcessor::Unit::J,
471 2554 : state.dataWaterCoils->WaterCoil(CoilNum).TotWaterHeatingCoilEnergy,
472 : OutputProcessor::SOVTimeStepType::System,
473 : OutputProcessor::SOVStoreType::Summed,
474 2554 : state.dataWaterCoils->WaterCoil(CoilNum).Name,
475 : _,
476 : "PLANTLOOPHEATINGDEMAND",
477 : "HEATINGCOILS",
478 : _,
479 2554 : "System");
480 10216 : SetupOutputVariable(state,
481 : "Heating Coil Heating Rate",
482 : OutputProcessor::Unit::W,
483 2554 : state.dataWaterCoils->WaterCoil(CoilNum).TotWaterHeatingCoilRate,
484 : OutputProcessor::SOVTimeStepType::System,
485 : OutputProcessor::SOVStoreType::Average,
486 5108 : state.dataWaterCoils->WaterCoil(CoilNum).Name);
487 10216 : SetupOutputVariable(state,
488 : "Heating Coil U Factor Times Area Value",
489 : OutputProcessor::Unit::W_K,
490 2554 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilVariable,
491 : OutputProcessor::SOVTimeStepType::System,
492 : OutputProcessor::SOVStoreType::Average,
493 5108 : state.dataWaterCoils->WaterCoil(CoilNum).Name);
494 : }
495 :
496 325 : CurrentModuleObject = "Coil:Cooling:Water:DetailedGeometry";
497 : // Get the data for detailed cooling coils.
498 468 : for (FlatFinNum = 1; FlatFinNum <= NumFlatFin; ++FlatFinNum) {
499 :
500 143 : CoilNum = NumSimpHeat + FlatFinNum;
501 :
502 143 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
503 : CurrentModuleObject,
504 : FlatFinNum,
505 : AlphArray,
506 : NumAlphas,
507 : NumArray,
508 : NumNums,
509 : IOStat,
510 : lNumericBlanks,
511 : lAlphaBlanks,
512 : cAlphaFields,
513 : cNumericFields);
514 :
515 143 : state.dataWaterCoils->WaterCoilNumericFields(CoilNum).FieldNames.allocate(MaxNums);
516 143 : state.dataWaterCoils->WaterCoilNumericFields(CoilNum).FieldNames = "";
517 143 : state.dataWaterCoils->WaterCoilNumericFields(CoilNum).FieldNames = cNumericFields;
518 143 : UtilityRoutines::IsNameEmpty(state, AlphArray(1), cCurrentModuleObject, ErrorsFound);
519 :
520 : // ErrorsFound will be set to True if problem was found, left untouched otherwise
521 143 : VerifyUniqueCoilName(state, CurrentModuleObject, AlphArray(1), ErrorsFound, CurrentModuleObject + " Name");
522 :
523 143 : state.dataWaterCoils->WaterCoil(CoilNum).Name = AlphArray(1);
524 143 : state.dataWaterCoils->WaterCoil(CoilNum).Schedule = AlphArray(2);
525 143 : if (lAlphaBlanks(2)) {
526 0 : state.dataWaterCoils->WaterCoil(CoilNum).SchedPtr = DataGlobalConstants::ScheduleAlwaysOn;
527 : } else {
528 143 : state.dataWaterCoils->WaterCoil(CoilNum).SchedPtr = GetScheduleIndex(state, AlphArray(2));
529 143 : if (state.dataWaterCoils->WaterCoil(CoilNum).SchedPtr == 0) {
530 0 : ShowSevereError(state,
531 0 : CurrentModuleObject + ": invalid " + cAlphaFields(2) + " entered =" + AlphArray(2) + " for " + cAlphaFields(1) + '=' +
532 0 : AlphArray(1));
533 0 : ErrorsFound = true;
534 : }
535 : }
536 :
537 143 : state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilTypeA = "Cooling";
538 143 : state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilType = DataPlant::PlantEquipmentType::CoilWaterCooling; // 'Cooling'
539 143 : state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilModelA = "DETAILED FLAT FIN";
540 143 : state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilModel = CoilModel::CoolingDetailed; // 'DETAILED FLAT FIN'
541 143 : state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilType = DataPlant::PlantEquipmentType::CoilWaterDetailedFlatCooling;
542 :
543 143 : state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterVolFlowRate = NumArray(1);
544 143 : if (state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterVolFlowRate == AutoSize)
545 62 : state.dataWaterCoils->WaterCoil(CoilNum).RequestingAutoSize = true;
546 143 : state.dataWaterCoils->WaterCoil(CoilNum).TubeOutsideSurfArea = NumArray(2);
547 143 : if (state.dataWaterCoils->WaterCoil(CoilNum).TubeOutsideSurfArea == AutoSize)
548 62 : state.dataWaterCoils->WaterCoil(CoilNum).RequestingAutoSize = true;
549 143 : state.dataWaterCoils->WaterCoil(CoilNum).TotTubeInsideArea = NumArray(3);
550 143 : if (state.dataWaterCoils->WaterCoil(CoilNum).TotTubeInsideArea == AutoSize)
551 62 : state.dataWaterCoils->WaterCoil(CoilNum).RequestingAutoSize = true;
552 143 : state.dataWaterCoils->WaterCoil(CoilNum).FinSurfArea = NumArray(4);
553 143 : if (state.dataWaterCoils->WaterCoil(CoilNum).FinSurfArea == AutoSize) state.dataWaterCoils->WaterCoil(CoilNum).RequestingAutoSize = true;
554 143 : state.dataWaterCoils->WaterCoil(CoilNum).MinAirFlowArea = NumArray(5);
555 143 : if (state.dataWaterCoils->WaterCoil(CoilNum).MinAirFlowArea == AutoSize) state.dataWaterCoils->WaterCoil(CoilNum).RequestingAutoSize = true;
556 143 : state.dataWaterCoils->WaterCoil(CoilNum).CoilDepth = NumArray(6);
557 143 : if (state.dataWaterCoils->WaterCoil(CoilNum).CoilDepth == AutoSize) state.dataWaterCoils->WaterCoil(CoilNum).RequestingAutoSize = true;
558 143 : state.dataWaterCoils->WaterCoil(CoilNum).FinDiam = NumArray(7);
559 143 : if (state.dataWaterCoils->WaterCoil(CoilNum).FinDiam == AutoSize) state.dataWaterCoils->WaterCoil(CoilNum).RequestingAutoSize = true;
560 143 : state.dataWaterCoils->WaterCoil(CoilNum).FinThickness = NumArray(8);
561 143 : if (state.dataWaterCoils->WaterCoil(CoilNum).FinThickness <= 0.0) {
562 0 : ShowSevereError(state,
563 0 : CurrentModuleObject + ": " + cNumericFields(8) + " must be > 0.0, for " + cAlphaFields(1) + " = " +
564 0 : state.dataWaterCoils->WaterCoil(CoilNum).Name);
565 0 : ErrorsFound = true;
566 : }
567 143 : state.dataWaterCoils->WaterCoil(CoilNum).TubeInsideDiam = NumArray(9);
568 143 : state.dataWaterCoils->WaterCoil(CoilNum).TubeOutsideDiam = NumArray(10);
569 143 : state.dataWaterCoils->WaterCoil(CoilNum).TubeThermConductivity = NumArray(11);
570 143 : if (state.dataWaterCoils->WaterCoil(CoilNum).TubeThermConductivity <= 0.0) {
571 0 : ShowSevereError(state,
572 0 : CurrentModuleObject + ": " + cNumericFields(11) + " must be > 0.0, for " + cAlphaFields(1) + " = " +
573 0 : state.dataWaterCoils->WaterCoil(CoilNum).Name);
574 0 : ErrorsFound = true;
575 : }
576 143 : state.dataWaterCoils->WaterCoil(CoilNum).FinThermConductivity = NumArray(12);
577 143 : if (state.dataWaterCoils->WaterCoil(CoilNum).FinThermConductivity <= 0.0) {
578 0 : ShowSevereError(state,
579 0 : CurrentModuleObject + ": " + cNumericFields(12) + " must be > 0.0, for " + cAlphaFields(1) + " = " +
580 0 : state.dataWaterCoils->WaterCoil(CoilNum).Name);
581 0 : ErrorsFound = true;
582 : }
583 143 : state.dataWaterCoils->WaterCoil(CoilNum).FinSpacing = NumArray(13);
584 143 : state.dataWaterCoils->WaterCoil(CoilNum).TubeDepthSpacing = NumArray(14);
585 143 : state.dataWaterCoils->WaterCoil(CoilNum).NumOfTubeRows = NumArray(15);
586 143 : state.dataWaterCoils->WaterCoil(CoilNum).NumOfTubesPerRow = NumArray(16);
587 143 : if (state.dataWaterCoils->WaterCoil(CoilNum).NumOfTubesPerRow == AutoSize) state.dataWaterCoils->WaterCoil(CoilNum).RequestingAutoSize = true;
588 143 : if (!lNumericBlanks(17)) {
589 1 : state.dataWaterCoils->WaterCoil(CoilNum).DesignWaterDeltaTemp = NumArray(17);
590 1 : state.dataWaterCoils->WaterCoil(CoilNum).UseDesignWaterDeltaTemp = true;
591 : } else {
592 142 : state.dataWaterCoils->WaterCoil(CoilNum).UseDesignWaterDeltaTemp = false;
593 : }
594 143 : state.dataWaterCoils->WaterCoil(CoilNum).WaterInletNodeNum =
595 286 : GetOnlySingleNode(state,
596 143 : AlphArray(3),
597 : ErrorsFound,
598 : DataLoopNode::ConnectionObjectType::CoilCoolingWaterDetailedGeometry,
599 143 : AlphArray(1),
600 : DataLoopNode::NodeFluidType::Water,
601 : DataLoopNode::ConnectionType::Inlet,
602 : NodeInputManager::CompFluidStream::Secondary,
603 143 : ObjectIsNotParent);
604 143 : state.dataWaterCoils->WaterCoil(CoilNum).WaterOutletNodeNum =
605 286 : GetOnlySingleNode(state,
606 143 : AlphArray(4),
607 : ErrorsFound,
608 : DataLoopNode::ConnectionObjectType::CoilCoolingWaterDetailedGeometry,
609 143 : AlphArray(1),
610 : DataLoopNode::NodeFluidType::Water,
611 : DataLoopNode::ConnectionType::Outlet,
612 : NodeInputManager::CompFluidStream::Secondary,
613 143 : ObjectIsNotParent);
614 143 : state.dataWaterCoils->WaterCoil(CoilNum).AirInletNodeNum =
615 286 : GetOnlySingleNode(state,
616 143 : AlphArray(5),
617 : ErrorsFound,
618 : DataLoopNode::ConnectionObjectType::CoilCoolingWaterDetailedGeometry,
619 143 : AlphArray(1),
620 : DataLoopNode::NodeFluidType::Air,
621 : DataLoopNode::ConnectionType::Inlet,
622 : NodeInputManager::CompFluidStream::Primary,
623 143 : ObjectIsNotParent);
624 143 : state.dataWaterCoils->WaterCoil(CoilNum).AirOutletNodeNum =
625 286 : GetOnlySingleNode(state,
626 143 : AlphArray(6),
627 : ErrorsFound,
628 : DataLoopNode::ConnectionObjectType::CoilCoolingWaterDetailedGeometry,
629 143 : AlphArray(1),
630 : DataLoopNode::NodeFluidType::Air,
631 : DataLoopNode::ConnectionType::Outlet,
632 : NodeInputManager::CompFluidStream::Primary,
633 143 : ObjectIsNotParent);
634 :
635 : // A7 ; \field Name of Water Storage Tank for Condensate Collection
636 143 : state.dataWaterCoils->WaterCoil(CoilNum).CondensateCollectName = AlphArray(7);
637 143 : if (lAlphaBlanks(7)) {
638 143 : state.dataWaterCoils->WaterCoil(CoilNum).CondensateCollectMode = state.dataWaterCoils->CondensateDiscarded;
639 : } else {
640 0 : state.dataWaterCoils->WaterCoil(CoilNum).CondensateCollectMode = state.dataWaterCoils->CondensateToTank;
641 0 : SetupTankSupplyComponent(state,
642 0 : state.dataWaterCoils->WaterCoil(CoilNum).Name,
643 : CurrentModuleObject,
644 0 : state.dataWaterCoils->WaterCoil(CoilNum).CondensateCollectName,
645 : ErrorsFound,
646 0 : state.dataWaterCoils->WaterCoil(CoilNum).CondensateTankID,
647 0 : state.dataWaterCoils->WaterCoil(CoilNum).CondensateTankSupplyARRID);
648 : }
649 :
650 143 : TestCompSet(state, CurrentModuleObject, AlphArray(1), AlphArray(3), AlphArray(4), "Water Nodes");
651 143 : TestCompSet(state, CurrentModuleObject, AlphArray(1), AlphArray(5), AlphArray(6), "Air Nodes");
652 :
653 : // Setup Report variables for the Detailed Flat Fin Cooling Coils
654 : // CurrentModuleObject = "Coil:Cooling:Water:DetailedGeometry"
655 572 : SetupOutputVariable(state,
656 : "Cooling Coil Total Cooling Energy",
657 : OutputProcessor::Unit::J,
658 143 : state.dataWaterCoils->WaterCoil(CoilNum).TotWaterCoolingCoilEnergy,
659 : OutputProcessor::SOVTimeStepType::System,
660 : OutputProcessor::SOVStoreType::Summed,
661 143 : state.dataWaterCoils->WaterCoil(CoilNum).Name,
662 : _,
663 : "ENERGYTRANSFER",
664 : "COOLINGCOILS",
665 : _,
666 143 : "System");
667 572 : SetupOutputVariable(state,
668 : "Cooling Coil Source Side Heat Transfer Energy",
669 : OutputProcessor::Unit::J,
670 143 : state.dataWaterCoils->WaterCoil(CoilNum).TotWaterCoolingCoilEnergy,
671 : OutputProcessor::SOVTimeStepType::System,
672 : OutputProcessor::SOVStoreType::Summed,
673 143 : state.dataWaterCoils->WaterCoil(CoilNum).Name,
674 : _,
675 : "PLANTLOOPCOOLINGDEMAND",
676 : "COOLINGCOILS",
677 : _,
678 143 : "System");
679 572 : SetupOutputVariable(state,
680 : "Cooling Coil Sensible Cooling Energy",
681 : OutputProcessor::Unit::J,
682 143 : state.dataWaterCoils->WaterCoil(CoilNum).SenWaterCoolingCoilEnergy,
683 : OutputProcessor::SOVTimeStepType::System,
684 : OutputProcessor::SOVStoreType::Summed,
685 286 : state.dataWaterCoils->WaterCoil(CoilNum).Name);
686 572 : SetupOutputVariable(state,
687 : "Cooling Coil Total Cooling Rate",
688 : OutputProcessor::Unit::W,
689 143 : state.dataWaterCoils->WaterCoil(CoilNum).TotWaterCoolingCoilRate,
690 : OutputProcessor::SOVTimeStepType::System,
691 : OutputProcessor::SOVStoreType::Average,
692 286 : state.dataWaterCoils->WaterCoil(CoilNum).Name);
693 572 : SetupOutputVariable(state,
694 : "Cooling Coil Sensible Cooling Rate",
695 : OutputProcessor::Unit::W,
696 143 : state.dataWaterCoils->WaterCoil(CoilNum).SenWaterCoolingCoilRate,
697 : OutputProcessor::SOVTimeStepType::System,
698 : OutputProcessor::SOVStoreType::Average,
699 286 : state.dataWaterCoils->WaterCoil(CoilNum).Name);
700 :
701 143 : if (state.dataWaterCoils->WaterCoil(CoilNum).CondensateCollectMode == state.dataWaterCoils->CondensateToTank) {
702 :
703 0 : SetupOutputVariable(state,
704 : "Cooling Coil Condensate Volume Flow Rate",
705 : OutputProcessor::Unit::m3_s,
706 0 : state.dataWaterCoils->WaterCoil(CoilNum).CondensateVdot,
707 : OutputProcessor::SOVTimeStepType::System,
708 : OutputProcessor::SOVStoreType::Average,
709 0 : state.dataWaterCoils->WaterCoil(CoilNum).Name);
710 0 : SetupOutputVariable(state,
711 : "Cooling Coil Condensate Volume",
712 : OutputProcessor::Unit::m3,
713 0 : state.dataWaterCoils->WaterCoil(CoilNum).CondensateVol,
714 : OutputProcessor::SOVTimeStepType::System,
715 : OutputProcessor::SOVStoreType::Summed,
716 0 : state.dataWaterCoils->WaterCoil(CoilNum).Name,
717 : _,
718 : "OnSiteWater",
719 : "Condensate",
720 : _,
721 0 : "System");
722 : }
723 : }
724 :
725 325 : CurrentModuleObject = "Coil:Cooling:Water";
726 : // Get the data for Cooling coils.
727 728 : for (CoolingNum = 1; CoolingNum <= NumCooling; ++CoolingNum) {
728 :
729 403 : CoilNum = NumSimpHeat + NumFlatFin + CoolingNum;
730 :
731 403 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
732 : CurrentModuleObject,
733 : CoolingNum,
734 : AlphArray,
735 : NumAlphas,
736 : NumArray,
737 : NumNums,
738 : IOStat,
739 : lNumericBlanks,
740 : lAlphaBlanks,
741 : cAlphaFields,
742 : cNumericFields);
743 :
744 403 : state.dataWaterCoils->WaterCoilNumericFields(CoilNum).FieldNames.allocate(MaxNums);
745 403 : state.dataWaterCoils->WaterCoilNumericFields(CoilNum).FieldNames = "";
746 403 : state.dataWaterCoils->WaterCoilNumericFields(CoilNum).FieldNames = cNumericFields;
747 403 : UtilityRoutines::IsNameEmpty(state, AlphArray(1), cCurrentModuleObject, ErrorsFound);
748 :
749 : // ErrorsFound will be set to True if problem was found, left untouched otherwise
750 403 : VerifyUniqueCoilName(state, CurrentModuleObject, AlphArray(1), ErrorsFound, CurrentModuleObject + " Name");
751 :
752 403 : state.dataWaterCoils->WaterCoil(CoilNum).Name = AlphArray(1);
753 403 : state.dataWaterCoils->WaterCoil(CoilNum).Schedule = AlphArray(2);
754 403 : if (lAlphaBlanks(2)) {
755 24 : state.dataWaterCoils->WaterCoil(CoilNum).SchedPtr = DataGlobalConstants::ScheduleAlwaysOn;
756 : } else {
757 379 : state.dataWaterCoils->WaterCoil(CoilNum).SchedPtr = GetScheduleIndex(state, AlphArray(2));
758 379 : if (state.dataWaterCoils->WaterCoil(CoilNum).SchedPtr == 0) {
759 0 : ShowSevereError(state,
760 0 : CurrentModuleObject + ": invalid " + cAlphaFields(2) + " entered =" + AlphArray(2) + " for " + cAlphaFields(1) + '=' +
761 0 : AlphArray(1));
762 0 : ErrorsFound = true;
763 : }
764 : }
765 :
766 403 : state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilTypeA = "Cooling";
767 403 : state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilType = DataPlant::PlantEquipmentType::CoilWaterCooling; // 'Cooling'
768 403 : state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilModelA = "Cooling";
769 403 : state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilModel = CoilModel::CoolingSimple; // 'Cooling'
770 403 : state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilType = DataPlant::PlantEquipmentType::CoilWaterCooling;
771 :
772 403 : state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterVolFlowRate = NumArray(1); // Liquid mass flow rate at Design kg/s
773 403 : if (state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterVolFlowRate == AutoSize)
774 381 : state.dataWaterCoils->WaterCoil(CoilNum).RequestingAutoSize = true;
775 403 : state.dataWaterCoils->WaterCoil(CoilNum).DesAirVolFlowRate = NumArray(2); // Dry air mass flow rate at Design (kg/s)
776 403 : if (state.dataWaterCoils->WaterCoil(CoilNum).DesAirVolFlowRate == AutoSize)
777 381 : state.dataWaterCoils->WaterCoil(CoilNum).RequestingAutoSize = true;
778 403 : state.dataWaterCoils->WaterCoil(CoilNum).DesInletWaterTemp = NumArray(3); // Entering water temperature at Design C
779 403 : if (state.dataWaterCoils->WaterCoil(CoilNum).DesInletWaterTemp == AutoSize)
780 368 : state.dataWaterCoils->WaterCoil(CoilNum).RequestingAutoSize = true;
781 403 : state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirTemp = NumArray(4); // Entering air dry bulb temperature at Design(C)
782 403 : if (state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirTemp == AutoSize) state.dataWaterCoils->WaterCoil(CoilNum).RequestingAutoSize = true;
783 403 : state.dataWaterCoils->WaterCoil(CoilNum).DesOutletAirTemp = NumArray(5); // Leaving air dry bulb temperature at Design(C)
784 403 : if (state.dataWaterCoils->WaterCoil(CoilNum).DesOutletAirTemp == AutoSize) state.dataWaterCoils->WaterCoil(CoilNum).RequestingAutoSize = true;
785 403 : state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirHumRat = NumArray(6); // Entering air humidity ratio at Design
786 403 : if (state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirHumRat == AutoSize)
787 376 : state.dataWaterCoils->WaterCoil(CoilNum).RequestingAutoSize = true;
788 403 : state.dataWaterCoils->WaterCoil(CoilNum).DesOutletAirHumRat = NumArray(7); // Leaving air humidity ratio at Design
789 403 : if (state.dataWaterCoils->WaterCoil(CoilNum).DesOutletAirHumRat == AutoSize)
790 376 : state.dataWaterCoils->WaterCoil(CoilNum).RequestingAutoSize = true;
791 403 : if (!lNumericBlanks(8)) {
792 27 : state.dataWaterCoils->WaterCoil(CoilNum).DesignWaterDeltaTemp = NumArray(8);
793 27 : state.dataWaterCoils->WaterCoil(CoilNum).UseDesignWaterDeltaTemp = true;
794 : } else {
795 376 : state.dataWaterCoils->WaterCoil(CoilNum).UseDesignWaterDeltaTemp = false;
796 : }
797 :
798 403 : state.dataWaterCoils->WaterCoil(CoilNum).WaterInletNodeNum = GetOnlySingleNode(state,
799 403 : AlphArray(3),
800 : ErrorsFound,
801 : DataLoopNode::ConnectionObjectType::CoilCoolingWater,
802 403 : AlphArray(1),
803 : DataLoopNode::NodeFluidType::Water,
804 : DataLoopNode::ConnectionType::Inlet,
805 : NodeInputManager::CompFluidStream::Secondary,
806 403 : ObjectIsNotParent);
807 403 : state.dataWaterCoils->WaterCoil(CoilNum).WaterOutletNodeNum = GetOnlySingleNode(state,
808 403 : AlphArray(4),
809 : ErrorsFound,
810 : DataLoopNode::ConnectionObjectType::CoilCoolingWater,
811 403 : AlphArray(1),
812 : DataLoopNode::NodeFluidType::Water,
813 : DataLoopNode::ConnectionType::Outlet,
814 : NodeInputManager::CompFluidStream::Secondary,
815 403 : ObjectIsNotParent);
816 403 : state.dataWaterCoils->WaterCoil(CoilNum).AirInletNodeNum = GetOnlySingleNode(state,
817 403 : AlphArray(5),
818 : ErrorsFound,
819 : DataLoopNode::ConnectionObjectType::CoilCoolingWater,
820 403 : AlphArray(1),
821 : DataLoopNode::NodeFluidType::Air,
822 : DataLoopNode::ConnectionType::Inlet,
823 : NodeInputManager::CompFluidStream::Primary,
824 403 : ObjectIsNotParent);
825 403 : state.dataWaterCoils->WaterCoil(CoilNum).AirOutletNodeNum = GetOnlySingleNode(state,
826 403 : AlphArray(6),
827 : ErrorsFound,
828 : DataLoopNode::ConnectionObjectType::CoilCoolingWater,
829 403 : AlphArray(1),
830 : DataLoopNode::NodeFluidType::Air,
831 : DataLoopNode::ConnectionType::Outlet,
832 : NodeInputManager::CompFluidStream::Primary,
833 403 : ObjectIsNotParent);
834 :
835 : // The default is SimpleAnalysis = 2. and DetailedAnalysis =1
836 403 : if (AlphArray(7) == "DETAILEDANALYSIS") { // not "SIMPLEANALYSIS"
837 54 : state.dataWaterCoils->WaterCoil(CoilNum).CoolingCoilAnalysisMode = state.dataWaterCoils->DetailedAnalysis;
838 :
839 : } else {
840 349 : state.dataWaterCoils->WaterCoil(CoilNum).CoolingCoilAnalysisMode = state.dataWaterCoils->SimpleAnalysis;
841 : }
842 :
843 : // The default is CrossFlow = 2. and CounterFlow=1
844 403 : if (AlphArray(8) == "COUNTERFLOW") { // not "CROSSFLOW"
845 1 : state.dataWaterCoils->WaterCoil(CoilNum).HeatExchType = state.dataWaterCoils->CounterFlow;
846 :
847 : } else {
848 402 : state.dataWaterCoils->WaterCoil(CoilNum).HeatExchType = state.dataWaterCoils->CrossFlow;
849 : }
850 :
851 : // A9; \field Name of Water Storage Tank for Condensate Collection
852 403 : state.dataWaterCoils->WaterCoil(CoilNum).CondensateCollectName = AlphArray(9);
853 403 : if (lAlphaBlanks(9)) {
854 403 : state.dataWaterCoils->WaterCoil(CoilNum).CondensateCollectMode = state.dataWaterCoils->CondensateDiscarded;
855 : } else {
856 0 : state.dataWaterCoils->WaterCoil(CoilNum).CondensateCollectMode = state.dataWaterCoils->CondensateToTank;
857 0 : SetupTankSupplyComponent(state,
858 0 : state.dataWaterCoils->WaterCoil(CoilNum).Name,
859 : CurrentModuleObject,
860 0 : state.dataWaterCoils->WaterCoil(CoilNum).CondensateCollectName,
861 : ErrorsFound,
862 0 : state.dataWaterCoils->WaterCoil(CoilNum).CondensateTankID,
863 0 : state.dataWaterCoils->WaterCoil(CoilNum).CondensateTankSupplyARRID);
864 : }
865 :
866 403 : TestCompSet(state, CurrentModuleObject, AlphArray(1), AlphArray(3), AlphArray(4), "Water Nodes");
867 403 : TestCompSet(state, CurrentModuleObject, AlphArray(1), AlphArray(5), AlphArray(6), "Air Nodes");
868 :
869 : // Setup Report variables for the Design input Cooling Coils
870 : // CurrentModuleObject = "Coil:Cooling:Water"
871 1612 : SetupOutputVariable(state,
872 : "Cooling Coil Total Cooling Energy",
873 : OutputProcessor::Unit::J,
874 403 : state.dataWaterCoils->WaterCoil(CoilNum).TotWaterCoolingCoilEnergy,
875 : OutputProcessor::SOVTimeStepType::System,
876 : OutputProcessor::SOVStoreType::Summed,
877 403 : state.dataWaterCoils->WaterCoil(CoilNum).Name,
878 : _,
879 : "ENERGYTRANSFER",
880 : "COOLINGCOILS",
881 : _,
882 403 : "System");
883 1612 : SetupOutputVariable(state,
884 : "Cooling Coil Source Side Heat Transfer Energy",
885 : OutputProcessor::Unit::J,
886 403 : state.dataWaterCoils->WaterCoil(CoilNum).TotWaterCoolingCoilEnergy,
887 : OutputProcessor::SOVTimeStepType::System,
888 : OutputProcessor::SOVStoreType::Summed,
889 403 : state.dataWaterCoils->WaterCoil(CoilNum).Name,
890 : _,
891 : "PLANTLOOPCOOLINGDEMAND",
892 : "COOLINGCOILS",
893 : _,
894 403 : "System");
895 1612 : SetupOutputVariable(state,
896 : "Cooling Coil Sensible Cooling Energy",
897 : OutputProcessor::Unit::J,
898 403 : state.dataWaterCoils->WaterCoil(CoilNum).SenWaterCoolingCoilEnergy,
899 : OutputProcessor::SOVTimeStepType::System,
900 : OutputProcessor::SOVStoreType::Summed,
901 806 : state.dataWaterCoils->WaterCoil(CoilNum).Name);
902 1612 : SetupOutputVariable(state,
903 : "Cooling Coil Total Cooling Rate",
904 : OutputProcessor::Unit::W,
905 403 : state.dataWaterCoils->WaterCoil(CoilNum).TotWaterCoolingCoilRate,
906 : OutputProcessor::SOVTimeStepType::System,
907 : OutputProcessor::SOVStoreType::Average,
908 806 : state.dataWaterCoils->WaterCoil(CoilNum).Name);
909 1612 : SetupOutputVariable(state,
910 : "Cooling Coil Sensible Cooling Rate",
911 : OutputProcessor::Unit::W,
912 403 : state.dataWaterCoils->WaterCoil(CoilNum).SenWaterCoolingCoilRate,
913 : OutputProcessor::SOVTimeStepType::System,
914 : OutputProcessor::SOVStoreType::Average,
915 806 : state.dataWaterCoils->WaterCoil(CoilNum).Name);
916 1612 : SetupOutputVariable(state,
917 : "Cooling Coil Wetted Area Fraction",
918 : OutputProcessor::Unit::None,
919 403 : state.dataWaterCoils->WaterCoil(CoilNum).SurfAreaWetFraction,
920 : OutputProcessor::SOVTimeStepType::System,
921 : OutputProcessor::SOVStoreType::Average,
922 806 : state.dataWaterCoils->WaterCoil(CoilNum).Name);
923 :
924 403 : if (state.dataWaterCoils->WaterCoil(CoilNum).CondensateCollectMode == state.dataWaterCoils->CondensateToTank) {
925 :
926 0 : SetupOutputVariable(state,
927 : "Cooling Coil Condensate Volume Flow Rate",
928 : OutputProcessor::Unit::m3_s,
929 0 : state.dataWaterCoils->WaterCoil(CoilNum).CondensateVdot,
930 : OutputProcessor::SOVTimeStepType::System,
931 : OutputProcessor::SOVStoreType::Average,
932 0 : state.dataWaterCoils->WaterCoil(CoilNum).Name);
933 0 : SetupOutputVariable(state,
934 : "Cooling Coil Condensate Volume",
935 : OutputProcessor::Unit::m3,
936 0 : state.dataWaterCoils->WaterCoil(CoilNum).CondensateVol,
937 : OutputProcessor::SOVTimeStepType::System,
938 : OutputProcessor::SOVStoreType::Summed,
939 0 : state.dataWaterCoils->WaterCoil(CoilNum).Name,
940 : _,
941 : "OnSiteWater",
942 : "Condensate",
943 : _,
944 0 : "System");
945 : }
946 : }
947 :
948 325 : if (ErrorsFound) {
949 0 : ShowFatalError(state, std::string{RoutineName} + "Errors found in getting input.");
950 : }
951 :
952 325 : AlphArray.deallocate();
953 325 : cAlphaFields.deallocate();
954 325 : cNumericFields.deallocate();
955 325 : NumArray.deallocate();
956 325 : lAlphaBlanks.deallocate();
957 325 : lNumericBlanks.deallocate();
958 325 : }
959 :
960 137535475 : void InitWaterCoil(EnergyPlusData &state, int const CoilNum, bool const FirstHVACIteration)
961 : {
962 :
963 : // SUBROUTINE INFORMATION:
964 : // AUTHOR Richard J. Liesen
965 : // DATE WRITTEN February 1998
966 : // MODIFIED April 2004: Rahul Chillar
967 : // November 2013: XP, Tianzhen Hong to handle fouling coils
968 : // RE-ENGINEERED na
969 :
970 : // PURPOSE OF THIS SUBROUTINE:
971 : // This subroutine is for initializations of the WaterCoil Components.
972 :
973 : // METHODOLOGY EMPLOYED:
974 : // Uses the status flags to trigger initializations.
975 :
976 : // REFERENCES:
977 :
978 : // Using/Aliasing
979 : using General::Iterate;
980 :
981 : using General::SafeDivide;
982 : using General::SolveRoot;
983 : using namespace OutputReportPredefined;
984 : using PlantUtilities::InitComponentNodes;
985 : using PlantUtilities::RegisterPlantCompDesignFlow;
986 : using PlantUtilities::ScanPlantLoopsForObject;
987 : using namespace FaultsManager;
988 : using HVACControllers::GetControllerNameAndIndex;
989 : using SimAirServingZones::CheckWaterCoilIsOnAirLoop;
990 :
991 : // SUBROUTINE PARAMETER DEFINITIONS:
992 137535475 : constexpr Real64 SmallNo(1.e-9); // SmallNo number in place of zero
993 137535475 : constexpr int itmax(10);
994 137535475 : constexpr int MaxIte(500); // Maximum number of iterations
995 : static constexpr std::string_view RoutineName("InitWaterCoil");
996 :
997 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
998 : int tempCoilNum; // loop variable
999 : Real64 DesInletAirEnth; // Entering air enthalpy at rating (J/kg)
1000 : Real64 DesOutletAirEnth; // Leaving air enthalpy at rating(J/kg)
1001 : Real64 DesAirApparatusDewPtEnth; // Air enthalpy at apparatus dew point at rating(J/kg)
1002 : Real64 DesSatEnthAtWaterInTemp; // Saturated enthalpy at entering liquid temp(J/kg)
1003 : Real64 DesHumRatAtWaterInTemp; // Enthalpy at water inlet temp and entering air HumRat (J/kg)
1004 : Real64 CapacitanceAir; // Air-side capacity rate(W/C)
1005 : Real64 DesAirTempApparatusDewPt; // Temperature apparatus dew point at design capacity
1006 : Real64 DesAirHumRatApparatusDewPt; // Humidity Ratio at apparatus dew point at design capacity
1007 : Real64 DesBypassFactor; // ByPass Factor at design condition
1008 : Real64 SlopeTempVsHumRatio; // Ratio temperature difference to humidity difference
1009 : // between entering and leaving air states
1010 : Real64 TempApparatusDewPtEstimate; // Estimate of TAdp from SlopeTempVsHumRatio
1011 : Real64 Y1; // Previous values of dependent variable in ITERATE
1012 : Real64 X1; // Previous values of independent variable in ITERATE
1013 : Real64 error; // Deviation of dependent variable in iteration
1014 : int iter; // Iteration counter
1015 : int icvg; // Iteration convergence flag
1016 : Real64 ResultX; // Output variable from ITERATE function.
1017 : int Ipass; // loop index for App_Dewpoint_Loop
1018 : int AirInletNode;
1019 : int WaterInletNode;
1020 : int WaterOutletNode;
1021 : Real64 FinDiamVar;
1022 : Real64 TubeToFinDiamRatio;
1023 : Real64 CpAirStd; // specific heat of air at std conditions
1024 : int SolFla; // Flag of solver
1025 : Real64 UA0; // lower bound for UA
1026 : Real64 UA1; // upper bound for UA
1027 : Real64 UA;
1028 : Real64 DesUACoilExternalEnth; // enthalpy based UAExternal for wet coil surface {kg/s}
1029 : Real64 LogMeanEnthDiff; // long mean enthalpy difference {J/kg}
1030 : Real64 LogMeanTempDiff; // long mean temperature difference {C}
1031 : Real64 DesOutletWaterTemp;
1032 : Real64 DesSatEnthAtWaterOutTemp;
1033 : Real64 DesEnthAtWaterOutTempAirInHumRat;
1034 : Real64 DesEnthWaterOut;
1035 : Real64 Cp; // local fluid specific heat
1036 : Real64 rho; // local fluid density
1037 : bool errFlag;
1038 137535475 : Real64 EnthCorrFrac(0.0); // enthalpy correction factor
1039 137535475 : Real64 TempCorrFrac(0.0); // temperature correction factor
1040 :
1041 137535475 : auto &Node(state.dataLoopNodes->Node);
1042 :
1043 137535475 : if (state.dataWaterCoils->InitWaterCoilOneTimeFlag) {
1044 : // initialize the environment and sizing flags
1045 314 : state.dataWaterCoils->MyEnvrnFlag.allocate(state.dataWaterCoils->NumWaterCoils);
1046 314 : state.dataWaterCoils->MySizeFlag.allocate(state.dataWaterCoils->NumWaterCoils);
1047 314 : state.dataWaterCoils->CoilWarningOnceFlag.allocate(state.dataWaterCoils->NumWaterCoils);
1048 314 : state.dataWaterCoils->DesCpAir.allocate(state.dataWaterCoils->NumWaterCoils);
1049 314 : state.dataWaterCoils->MyUAAndFlowCalcFlag.allocate(state.dataWaterCoils->NumWaterCoils);
1050 314 : state.dataWaterCoils->MyCoilDesignFlag.allocate(state.dataWaterCoils->NumWaterCoils);
1051 314 : state.dataWaterCoils->MyCoilReportFlag.allocate(state.dataWaterCoils->NumWaterCoils);
1052 314 : state.dataWaterCoils->DesUARangeCheck.allocate(state.dataWaterCoils->NumWaterCoils);
1053 314 : state.dataWaterCoils->PlantLoopScanFlag.allocate(state.dataWaterCoils->NumWaterCoils);
1054 :
1055 314 : state.dataWaterCoils->DesCpAir = 0.0;
1056 314 : state.dataWaterCoils->DesUARangeCheck = 0.0;
1057 314 : state.dataWaterCoils->MyEnvrnFlag = true;
1058 314 : state.dataWaterCoils->MySizeFlag = true;
1059 314 : state.dataWaterCoils->CoilWarningOnceFlag = true;
1060 314 : state.dataWaterCoils->MyUAAndFlowCalcFlag = true;
1061 314 : state.dataWaterCoils->MyCoilDesignFlag = true;
1062 314 : state.dataWaterCoils->MyCoilReportFlag = true;
1063 314 : state.dataWaterCoils->InitWaterCoilOneTimeFlag = false;
1064 314 : state.dataWaterCoils->PlantLoopScanFlag = true;
1065 :
1066 3414 : for (tempCoilNum = 1; tempCoilNum <= state.dataWaterCoils->NumWaterCoils; ++tempCoilNum) {
1067 9300 : GetControllerNameAndIndex(state,
1068 3100 : state.dataWaterCoils->WaterCoil(tempCoilNum).WaterInletNodeNum,
1069 3100 : state.dataWaterCoils->WaterCoil(tempCoilNum).ControllerName,
1070 3100 : state.dataWaterCoils->WaterCoil(tempCoilNum).ControllerIndex,
1071 : errFlag);
1072 : }
1073 : }
1074 :
1075 137535475 : if (state.dataWaterCoils->WaterCoilControllerCheckOneTimeFlag && (state.dataHVACGlobal->GetAirPathDataDone)) {
1076 314 : bool ErrorsFound = false;
1077 314 : bool WaterCoilOnAirLoop = true;
1078 3414 : for (tempCoilNum = 1; tempCoilNum <= state.dataWaterCoils->NumWaterCoils; ++tempCoilNum) {
1079 3100 : if (state.dataWaterCoils->WaterCoil(tempCoilNum).ControllerIndex > 0) {
1080 822 : SimAirServingZones::CompType CoilTypeNum(SimAirServingZones::CompType::Invalid);
1081 1644 : std::string CompType;
1082 1644 : std::string CompName = state.dataWaterCoils->WaterCoil(tempCoilNum).Name;
1083 822 : if (state.dataWaterCoils->WaterCoil(tempCoilNum).WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterCooling) {
1084 293 : CoilTypeNum = SimAirServingZones::CompType::WaterCoil_Cooling;
1085 293 : CompType = cAllCoilTypes(DataHVACGlobals::Coil_CoolingWater);
1086 529 : } else if (state.dataWaterCoils->WaterCoil(tempCoilNum).WaterCoilType ==
1087 : DataPlant::PlantEquipmentType::CoilWaterDetailedFlatCooling) {
1088 143 : CoilTypeNum = SimAirServingZones::CompType::WaterCoil_DetailedCool;
1089 143 : CompType = cAllCoilTypes(DataHVACGlobals::Coil_CoolingWaterDetailed);
1090 386 : } else if (state.dataWaterCoils->WaterCoil(tempCoilNum).WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterSimpleHeating) {
1091 386 : CoilTypeNum = SimAirServingZones::CompType::WaterCoil_SimpleHeat;
1092 386 : CompType = cAllCoilTypes(DataHVACGlobals::Coil_HeatingWater);
1093 : }
1094 822 : WaterCoilOnAirLoop = true;
1095 822 : CheckWaterCoilIsOnAirLoop(state, CoilTypeNum, CompType, CompName, WaterCoilOnAirLoop);
1096 822 : if (!WaterCoilOnAirLoop) {
1097 0 : ShowContinueError(state,
1098 0 : "Controller:WaterCoil = " + state.dataWaterCoils->WaterCoil(tempCoilNum).ControllerName +
1099 : ". Invalid water controller entry.");
1100 0 : ErrorsFound = true;
1101 : }
1102 : }
1103 : }
1104 314 : state.dataWaterCoils->WaterCoilControllerCheckOneTimeFlag = false;
1105 314 : if (ErrorsFound) {
1106 0 : ShowFatalError(state, "Program terminated for previous condition.");
1107 : }
1108 : }
1109 :
1110 137535475 : if (state.dataWaterCoils->PlantLoopScanFlag(CoilNum) && allocated(state.dataPlnt->PlantLoop)) {
1111 3100 : errFlag = false;
1112 12400 : ScanPlantLoopsForObject(state,
1113 3100 : state.dataWaterCoils->WaterCoil(CoilNum).Name,
1114 3100 : state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilType,
1115 3100 : state.dataWaterCoils->WaterCoil(CoilNum).WaterPlantLoc,
1116 : errFlag,
1117 : _,
1118 : _,
1119 : _,
1120 : _,
1121 : _);
1122 3100 : if (errFlag) {
1123 0 : ShowFatalError(state, "InitWaterCoil: Program terminated for previous conditions.");
1124 : }
1125 3100 : state.dataWaterCoils->PlantLoopScanFlag(CoilNum) = false;
1126 : }
1127 137535475 : if (!state.dataGlobal->SysSizingCalc && state.dataWaterCoils->MySizeFlag(CoilNum)) {
1128 : // for each coil, do the sizing once.
1129 3100 : SizeWaterCoil(state, CoilNum);
1130 :
1131 3100 : state.dataWaterCoils->MySizeFlag(CoilNum) = false;
1132 : }
1133 :
1134 : // Do the Begin Environment initializations
1135 137535475 : if (state.dataGlobal->BeginEnvrnFlag && state.dataWaterCoils->MyEnvrnFlag(CoilNum)) {
1136 41464 : rho = GetDensityGlycol(state,
1137 20732 : state.dataPlnt->PlantLoop(state.dataWaterCoils->WaterCoil(CoilNum).WaterPlantLoc.loopNum).FluidName,
1138 : DataGlobalConstants::InitConvTemp,
1139 20732 : state.dataPlnt->PlantLoop(state.dataWaterCoils->WaterCoil(CoilNum).WaterPlantLoc.loopNum).FluidIndex,
1140 : RoutineName);
1141 : // Initialize all report variables to a known state at beginning of simulation
1142 20732 : state.dataWaterCoils->WaterCoil(CoilNum).TotWaterHeatingCoilEnergy = 0.0;
1143 20732 : state.dataWaterCoils->WaterCoil(CoilNum).TotWaterCoolingCoilEnergy = 0.0;
1144 20732 : state.dataWaterCoils->WaterCoil(CoilNum).SenWaterCoolingCoilEnergy = 0.0;
1145 20732 : state.dataWaterCoils->WaterCoil(CoilNum).TotWaterHeatingCoilRate = 0.0;
1146 20732 : state.dataWaterCoils->WaterCoil(CoilNum).TotWaterCoolingCoilRate = 0.0;
1147 20732 : state.dataWaterCoils->WaterCoil(CoilNum).SenWaterCoolingCoilRate = 0.0;
1148 :
1149 : // The rest of the one time initializations
1150 20732 : AirInletNode = state.dataWaterCoils->WaterCoil(CoilNum).AirInletNodeNum;
1151 20732 : WaterInletNode = state.dataWaterCoils->WaterCoil(CoilNum).WaterInletNodeNum;
1152 20732 : WaterOutletNode = state.dataWaterCoils->WaterCoil(CoilNum).WaterOutletNodeNum;
1153 :
1154 20732 : state.dataWaterCoils->DesCpAir(CoilNum) = PsyCpAirFnW(0.0);
1155 20732 : state.dataWaterCoils->DesUARangeCheck(CoilNum) = (-1568.6 * state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirHumRat + 20.157);
1156 :
1157 38767 : if ((state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterCooling) ||
1158 18035 : (state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterDetailedFlatCooling)) { // 'Cooling'
1159 3569 : Node(WaterInletNode).Temp = 5.0;
1160 :
1161 10707 : Cp = GetSpecificHeatGlycol(state,
1162 3569 : state.dataPlnt->PlantLoop(state.dataWaterCoils->WaterCoil(CoilNum).WaterPlantLoc.loopNum).FluidName,
1163 3569 : Node(WaterInletNode).Temp,
1164 3569 : state.dataPlnt->PlantLoop(state.dataWaterCoils->WaterCoil(CoilNum).WaterPlantLoc.loopNum).FluidIndex,
1165 : RoutineName);
1166 :
1167 3569 : Node(WaterInletNode).Enthalpy = Cp * Node(WaterInletNode).Temp;
1168 3569 : Node(WaterInletNode).Quality = 0.0;
1169 3569 : Node(WaterInletNode).Press = 0.0;
1170 3569 : Node(WaterInletNode).HumRat = 0.0;
1171 : }
1172 :
1173 20732 : if (state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterSimpleHeating) { // 'Heating'
1174 17163 : Node(WaterInletNode).Temp = 60.0;
1175 :
1176 51489 : Cp = GetSpecificHeatGlycol(state,
1177 17163 : state.dataPlnt->PlantLoop(state.dataWaterCoils->WaterCoil(CoilNum).WaterPlantLoc.loopNum).FluidName,
1178 17163 : Node(WaterInletNode).Temp,
1179 17163 : state.dataPlnt->PlantLoop(state.dataWaterCoils->WaterCoil(CoilNum).WaterPlantLoc.loopNum).FluidIndex,
1180 : RoutineName);
1181 :
1182 17163 : Node(WaterInletNode).Enthalpy = Cp * Node(WaterInletNode).Temp;
1183 17163 : Node(WaterInletNode).Quality = 0.0;
1184 17163 : Node(WaterInletNode).Press = 0.0;
1185 17163 : Node(WaterInletNode).HumRat = 0.0;
1186 17163 : state.dataWaterCoils->MyUAAndFlowCalcFlag(CoilNum) = false;
1187 : // fill values for variable UA
1188 17163 : CpAirStd = PsyCpAirFnW(0.0);
1189 17163 : state.dataWaterCoils->WaterCoil(CoilNum).DesAirMassFlowRate =
1190 17163 : state.dataEnvrn->StdRhoAir * state.dataWaterCoils->WaterCoil(CoilNum).DesAirVolFlowRate;
1191 17163 : state.dataWaterCoils->WaterCoil(CoilNum).LiquidSideNominalConvect =
1192 34326 : state.dataWaterCoils->WaterCoil(CoilNum).UACoil * (state.dataWaterCoils->WaterCoil(CoilNum).RatioAirSideToWaterSideConvect + 1) /
1193 17163 : state.dataWaterCoils->WaterCoil(CoilNum).RatioAirSideToWaterSideConvect;
1194 34326 : state.dataWaterCoils->WaterCoil(CoilNum).AirSideNominalConvect = state.dataWaterCoils->WaterCoil(CoilNum).RatioAirSideToWaterSideConvect *
1195 17163 : state.dataWaterCoils->WaterCoil(CoilNum).LiquidSideNominalConvect;
1196 : } else {
1197 3569 : state.dataWaterCoils->MyUAAndFlowCalcFlag(CoilNum) = false;
1198 : }
1199 :
1200 20732 : state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterMassFlowRate = rho * state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterVolFlowRate;
1201 :
1202 62196 : InitComponentNodes(state,
1203 : 0.0,
1204 20732 : state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterMassFlowRate,
1205 20732 : state.dataWaterCoils->WaterCoil(CoilNum).WaterInletNodeNum,
1206 20732 : state.dataWaterCoils->WaterCoil(CoilNum).WaterOutletNodeNum);
1207 :
1208 : // effective fin diameter for detailed flat fin coil
1209 20732 : if (state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilModel == CoilModel::CoolingDetailed) { // 'DETAILED FLAT FIN'
1210 872 : state.dataWaterCoils->WaterCoil(CoilNum).EffectiveFinDiam =
1211 1744 : std::sqrt(4.0 * state.dataWaterCoils->WaterCoil(CoilNum).FinDiam * state.dataWaterCoils->WaterCoil(CoilNum).CoilDepth /
1212 1744 : (DataGlobalConstants::Pi * state.dataWaterCoils->WaterCoil(CoilNum).NumOfTubeRows *
1213 872 : state.dataWaterCoils->WaterCoil(CoilNum).NumOfTubesPerRow));
1214 :
1215 : // calculate fixed geometric parameters of the coil:
1216 : // Total Area
1217 872 : state.dataWaterCoils->WaterCoil(CoilNum).TotCoilOutsideSurfArea =
1218 872 : state.dataWaterCoils->WaterCoil(CoilNum).TubeOutsideSurfArea + state.dataWaterCoils->WaterCoil(CoilNum).FinSurfArea;
1219 : // Effective Tube Inside Diameter - the model assumes that the coil
1220 : // can be simulated as a tube with an equivalent hydraulic diameter.
1221 2616 : state.dataWaterCoils->WaterCoil(CoilNum).CoilEffectiveInsideDiam = 4.0 * state.dataWaterCoils->WaterCoil(CoilNum).MinAirFlowArea *
1222 1744 : state.dataWaterCoils->WaterCoil(CoilNum).CoilDepth /
1223 872 : state.dataWaterCoils->WaterCoil(CoilNum).TotCoilOutsideSurfArea;
1224 : // Ratio of tube outside diameter to effective fin diameter should always
1225 : // be less than 1
1226 872 : TubeToFinDiamRatio = state.dataWaterCoils->WaterCoil(CoilNum).TubeOutsideDiam / state.dataWaterCoils->WaterCoil(CoilNum).EffectiveFinDiam;
1227 872 : if (TubeToFinDiamRatio > 1.0) {
1228 0 : ShowWarningError(state, format("InitWaterCoil: Detailed Flat Fin Coil, TubetoFinDiamRatio > 1.0, [{:.4R}]", TubeToFinDiamRatio));
1229 : // reset tube depth spacing and recalc dependent parameters
1230 0 : state.dataWaterCoils->WaterCoil(CoilNum).TubeDepthSpacing *= (pow_2(TubeToFinDiamRatio) + 0.1);
1231 0 : state.dataWaterCoils->WaterCoil(CoilNum).CoilDepth =
1232 0 : state.dataWaterCoils->WaterCoil(CoilNum).TubeDepthSpacing * state.dataWaterCoils->WaterCoil(CoilNum).NumOfTubeRows;
1233 0 : state.dataWaterCoils->WaterCoil(CoilNum).EffectiveFinDiam =
1234 0 : std::sqrt(4.0 * state.dataWaterCoils->WaterCoil(CoilNum).FinDiam * state.dataWaterCoils->WaterCoil(CoilNum).CoilDepth /
1235 0 : (DataGlobalConstants::Pi * state.dataWaterCoils->WaterCoil(CoilNum).NumOfTubeRows *
1236 0 : state.dataWaterCoils->WaterCoil(CoilNum).NumOfTubesPerRow));
1237 0 : state.dataWaterCoils->WaterCoil(CoilNum).CoilEffectiveInsideDiam = 4.0 * state.dataWaterCoils->WaterCoil(CoilNum).MinAirFlowArea *
1238 0 : state.dataWaterCoils->WaterCoil(CoilNum).CoilDepth /
1239 0 : state.dataWaterCoils->WaterCoil(CoilNum).TotCoilOutsideSurfArea;
1240 0 : TubeToFinDiamRatio =
1241 0 : state.dataWaterCoils->WaterCoil(CoilNum).TubeOutsideDiam / state.dataWaterCoils->WaterCoil(CoilNum).EffectiveFinDiam;
1242 0 : ShowContinueError(
1243 0 : state, format(" Resetting tube depth spacing to {:.4R} meters", state.dataWaterCoils->WaterCoil(CoilNum).TubeDepthSpacing));
1244 0 : ShowContinueError(state, format(" Resetting coil depth to {:.4R} meters", state.dataWaterCoils->WaterCoil(CoilNum).CoilDepth));
1245 : }
1246 :
1247 872 : CalcDryFinEffCoef(state, TubeToFinDiamRatio, state.dataWaterCoils->CoefSeries);
1248 :
1249 872 : state.dataWaterCoils->WaterCoil(CoilNum).DryFinEfficncyCoef = state.dataWaterCoils->CoefSeries;
1250 :
1251 872 : FinDiamVar = 0.5 * (state.dataWaterCoils->WaterCoil(CoilNum).EffectiveFinDiam - state.dataWaterCoils->WaterCoil(CoilNum).TubeOutsideDiam);
1252 :
1253 872 : state.dataWaterCoils->WaterCoil(CoilNum).GeometryCoef1 =
1254 872 : 0.159 *
1255 872 : std::pow(state.dataWaterCoils->WaterCoil(CoilNum).FinThickness / state.dataWaterCoils->WaterCoil(CoilNum).CoilEffectiveInsideDiam,
1256 872 : -0.065) *
1257 872 : std::pow(state.dataWaterCoils->WaterCoil(CoilNum).FinThickness / FinDiamVar, 0.141);
1258 872 : state.dataWaterCoils->WaterCoil(CoilNum).GeometryCoef2 =
1259 1744 : -0.323 * std::pow(state.dataWaterCoils->WaterCoil(CoilNum).FinSpacing / FinDiamVar, 0.049) *
1260 872 : std::pow(state.dataWaterCoils->WaterCoil(CoilNum).EffectiveFinDiam / state.dataWaterCoils->WaterCoil(CoilNum).TubeDepthSpacing,
1261 872 : 0.549) *
1262 872 : std::pow(state.dataWaterCoils->WaterCoil(CoilNum).FinThickness / state.dataWaterCoils->WaterCoil(CoilNum).FinSpacing, -0.028);
1263 :
1264 : // Set some initial values for simulation
1265 872 : state.dataWaterCoils->WaterCoil(CoilNum).SatEnthlCurveConstCoef = -10.57;
1266 872 : state.dataWaterCoils->WaterCoil(CoilNum).SatEnthlCurveSlope = 3.3867;
1267 872 : state.dataWaterCoils->WaterCoil(CoilNum).EnthVsTempCurveAppxSlope = 3.3867;
1268 872 : state.dataWaterCoils->WaterCoil(CoilNum).EnthVsTempCurveConst = -10.57;
1269 : // Set Saved Values to Zero
1270 872 : state.dataWaterCoils->WaterCoil(CoilNum).SurfAreaWetSaved = 0.0;
1271 872 : state.dataWaterCoils->WaterCoil(CoilNum).MeanWaterTempSaved = 0.0;
1272 872 : state.dataWaterCoils->WaterCoil(CoilNum).InWaterTempSaved = 0.0;
1273 872 : state.dataWaterCoils->WaterCoil(CoilNum).OutWaterTempSaved = 0.0;
1274 :
1275 : } // End the Detailed Flat Fin Coil Initialization
1276 :
1277 : // Calculation for Cooling Coil, The part between the '@@@' are design condition
1278 : // and are calculated only once to calculate standard values for UAs and other physical parameters of
1279 : // the cooling coil.
1280 : // Basic Idea for UA: Heat Transfer= UAenthalpybased*(Delta enthalpy), this is a necessity since the
1281 : // coil may be Wet or Dry or Partially Wet-Dry, so latent effects are accounted for in this model while
1282 : // calculating the UA. A fictitious specific heat is also defined to caculate the conventional UA.
1283 : // On the air side, enthalpy capacity rate is the air mass flow rate,while on water side it is
1284 : // enthalpy of saturated air at water temperature.
1285 : //@@@ DESIGN CONDITION BEGIN HERE @@@
1286 :
1287 : // Check for zero design cooling capacity as specified by coil design inputs
1288 59910 : if (state.dataWaterCoils->MyCoilDesignFlag(CoilNum) &&
1289 18857 : (state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilModel == CoilModel::CoolingSimple) &&
1290 21554 : (state.dataWaterCoils->WaterCoil(CoilNum).DesAirVolFlowRate > 0.0) &&
1291 411 : (state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterMassFlowRate > 0.0)) {
1292 :
1293 401 : DesInletAirEnth =
1294 401 : PsyHFnTdbW(state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirTemp, state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirHumRat);
1295 401 : DesOutletAirEnth =
1296 401 : PsyHFnTdbW(state.dataWaterCoils->WaterCoil(CoilNum).DesOutletAirTemp, state.dataWaterCoils->WaterCoil(CoilNum).DesOutletAirHumRat);
1297 401 : DesSatEnthAtWaterInTemp =
1298 1203 : PsyHFnTdbW(state.dataWaterCoils->WaterCoil(CoilNum).DesInletWaterTemp,
1299 802 : PsyWFnTdpPb(state, state.dataWaterCoils->WaterCoil(CoilNum).DesInletWaterTemp, state.dataEnvrn->StdBaroPress));
1300 : // check for dry coil
1301 401 : DesHumRatAtWaterInTemp =
1302 401 : PsyWFnTdbH(state, state.dataWaterCoils->WaterCoil(CoilNum).DesInletWaterTemp, DesSatEnthAtWaterInTemp, RoutineName);
1303 436 : if (DesHumRatAtWaterInTemp > state.dataWaterCoils->WaterCoil(CoilNum).DesOutletAirHumRat &&
1304 35 : state.dataWaterCoils->WaterCoil(CoilNum).DesOutletAirTemp > state.dataWaterCoils->WaterCoil(CoilNum).DesInletWaterTemp) {
1305 : // if the design outlet air humrat is lower than the saturated air humrat at the design inlet water temp
1306 : // and the design outlet air temperature is higher than the design inlet water temp (i.e, cooling possible),
1307 : // move the design outlet air saturated enthalpy down (i.e., to Twaterin, Wair,out) to allow the coil to size.
1308 35 : DesSatEnthAtWaterInTemp = PsyHFnTdbW(state.dataWaterCoils->WaterCoil(CoilNum).DesInletWaterTemp,
1309 35 : state.dataWaterCoils->WaterCoil(CoilNum).DesOutletAirHumRat) -
1310 : 0.0001;
1311 : }
1312 802 : if (DesOutletAirEnth >= DesInletAirEnth ||
1313 401 : state.dataWaterCoils->WaterCoil(CoilNum).DesInletWaterTemp >= state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirTemp) {
1314 0 : ShowWarningError(state,
1315 0 : "The design cooling capacity is zero for Coil:Cooling:Water " + state.dataWaterCoils->WaterCoil(CoilNum).Name);
1316 0 : ShowContinueError(state, " The maximum water flow rate for this coil will be set to zero and the coil will do no cooling.");
1317 0 : ShowContinueError(state,
1318 0 : format(" Check the following coil design inputs for problems: Tair,in = {:.4R}",
1319 0 : state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirTemp));
1320 0 : ShowContinueError(state,
1321 0 : format(" Wair,in = {:.6R}",
1322 0 : state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirHumRat));
1323 0 : ShowContinueError(state,
1324 0 : format(" Twater,in = {:.4R}",
1325 0 : state.dataWaterCoils->WaterCoil(CoilNum).DesInletWaterTemp));
1326 0 : ShowContinueError(state,
1327 0 : format(" Tair,out = {:.4R}",
1328 0 : state.dataWaterCoils->WaterCoil(CoilNum).DesOutletAirTemp));
1329 0 : ShowContinueError(state,
1330 0 : format(" Wair,out = {:.6R}",
1331 0 : state.dataWaterCoils->WaterCoil(CoilNum).DesOutletAirHumRat));
1332 0 : state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterVolFlowRate = 0.0;
1333 0 : state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterMassFlowRate = 0.0;
1334 : }
1335 : }
1336 :
1337 59910 : if (state.dataWaterCoils->MyCoilDesignFlag(CoilNum) &&
1338 18857 : (state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilModel == CoilModel::CoolingSimple) &&
1339 21554 : (state.dataWaterCoils->WaterCoil(CoilNum).DesAirVolFlowRate > 0.0) &&
1340 411 : (state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterMassFlowRate > 0.0)) { // 'Cooling'
1341 :
1342 401 : state.dataWaterCoils->MyCoilDesignFlag(CoilNum) = false;
1343 401 : state.dataWaterCoils->NoSatCurveIntersect = false;
1344 401 : state.dataWaterCoils->BelowInletWaterTemp = false;
1345 401 : state.dataWaterCoils->CBFTooLarge = false;
1346 401 : state.dataWaterCoils->NoExitCondReset = false;
1347 835 : for (Ipass = 1; Ipass <= 2; ++Ipass) {
1348 759 : if (Ipass == 2) {
1349 697 : if (!state.dataWaterCoils->NoSatCurveIntersect && !state.dataWaterCoils->BelowInletWaterTemp &&
1350 339 : !state.dataWaterCoils->CBFTooLarge) {
1351 282 : goto Inlet_Conditions_Loop_exit; // coil UA calcs OK
1352 : } else {
1353 228 : ShowWarningError(state,
1354 152 : "In calculating the design coil UA for Coil:Cooling:Water " + state.dataWaterCoils->WaterCoil(CoilNum).Name);
1355 76 : if (state.dataWaterCoils->NoSatCurveIntersect) {
1356 14 : ShowContinueError(state, "no apparatus dew-point can be found for the initial entering and leaving conditions;");
1357 : }
1358 76 : if (state.dataWaterCoils->BelowInletWaterTemp) {
1359 6 : ShowContinueError(state, "the apparatus dew-point is below the coil design inlet water temperature;");
1360 : }
1361 76 : if (state.dataWaterCoils->CBFTooLarge) {
1362 58 : ShowContinueError(state, "the coil bypass factor is unrealistically large;");
1363 : }
1364 76 : if (!state.dataWaterCoils->NoExitCondReset) {
1365 8 : ShowContinueError(state, "the coil outlet design conditions will be changed to correct the problem.");
1366 : }
1367 228 : ShowContinueError(
1368 : state,
1369 152 : format("The initial design conditions are: Tair,in = {:.4R}", state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirTemp));
1370 228 : ShowContinueError(state,
1371 228 : format(" Wair,in = {:.6R}",
1372 152 : state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirHumRat));
1373 228 : ShowContinueError(state,
1374 228 : format(" Twater,in = {:.4R}",
1375 152 : state.dataWaterCoils->WaterCoil(CoilNum).DesInletWaterTemp));
1376 228 : ShowContinueError(state,
1377 228 : format(" Tair,out = {:.4R}",
1378 152 : state.dataWaterCoils->WaterCoil(CoilNum).DesOutletAirTemp));
1379 228 : ShowContinueError(state,
1380 228 : format(" Wair,out = {:.6R}",
1381 152 : state.dataWaterCoils->WaterCoil(CoilNum).DesOutletAirHumRat));
1382 76 : if (!state.dataWaterCoils->NoExitCondReset) {
1383 8 : ShowContinueError(state, format("The revised design conditions are: Tair,out = {:.4R}", state.dataWaterCoils->TOutNew));
1384 8 : ShowContinueError(state, format(" Wair,out = {:.6R}", state.dataWaterCoils->WOutNew));
1385 8 : state.dataWaterCoils->WaterCoil(CoilNum).DesOutletAirHumRat = state.dataWaterCoils->WOutNew;
1386 8 : state.dataWaterCoils->WaterCoil(CoilNum).DesOutletAirTemp = state.dataWaterCoils->TOutNew;
1387 : // update outlet air conditions used for sizing
1388 16 : std::string CompType;
1389 8 : if (state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilModel == CoilModel::CoolingDetailed) {
1390 0 : CompType = cAllCoilTypes(Coil_CoolingWaterDetailed);
1391 : } else {
1392 8 : CompType = cAllCoilTypes(Coil_CoolingWater);
1393 : }
1394 24 : state.dataRptCoilSelection->coilSelectionReportObj->setCoilLvgAirTemp(
1395 16 : state, state.dataWaterCoils->WaterCoil(CoilNum).Name, CompType, state.dataWaterCoils->TOutNew);
1396 24 : state.dataRptCoilSelection->coilSelectionReportObj->setCoilLvgAirHumRat(
1397 16 : state, state.dataWaterCoils->WaterCoil(CoilNum).Name, CompType, state.dataWaterCoils->WOutNew);
1398 : // end update outlet air conditions used for sizing
1399 : }
1400 : }
1401 : }
1402 :
1403 : // Volume flow rate being converted to mass flow rate for water
1404 477 : state.dataWaterCoils->WaterCoil(CoilNum).DesAirMassFlowRate =
1405 477 : state.dataEnvrn->StdRhoAir * state.dataWaterCoils->WaterCoil(CoilNum).DesAirVolFlowRate;
1406 :
1407 : // Enthalpy of Air at Inlet design conditions
1408 477 : DesInletAirEnth =
1409 477 : PsyHFnTdbW(state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirTemp, state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirHumRat);
1410 :
1411 : // Enthalpy of Air at outlet at design conditions
1412 477 : DesOutletAirEnth = PsyHFnTdbW(state.dataWaterCoils->WaterCoil(CoilNum).DesOutletAirTemp,
1413 477 : state.dataWaterCoils->WaterCoil(CoilNum).DesOutletAirHumRat);
1414 :
1415 : // already calculated above and possibly reset if dry coil
1416 : // ! Enthalpy of Water at Inlet design conditions
1417 : // DesSatEnthAtWaterInTemp =PsyHFnTdbW(WaterCoil(CoilNum)%DesInletWaterTemp, &
1418 : // PsyWFnTdpPb(state, WaterCoil(CoilNum)%DesInletWaterTemp,StdBaroPress))
1419 :
1420 : // Total Coil Load from Inlet and Outlet Air States (which include fan heat as appropriate).
1421 477 : state.dataWaterCoils->WaterCoil(CoilNum).DesTotWaterCoilLoad =
1422 477 : state.dataWaterCoils->WaterCoil(CoilNum).DesAirMassFlowRate * (DesInletAirEnth - DesOutletAirEnth);
1423 :
1424 : // Enthalpy of Water at Intlet design conditions
1425 1431 : Cp = GetSpecificHeatGlycol(state,
1426 477 : state.dataPlnt->PlantLoop(state.dataWaterCoils->WaterCoil(CoilNum).WaterPlantLoc.loopNum).FluidName,
1427 477 : state.dataWaterCoils->WaterCoil(CoilNum).DesInletWaterTemp,
1428 477 : state.dataPlnt->PlantLoop(state.dataWaterCoils->WaterCoil(CoilNum).WaterPlantLoc.loopNum).FluidIndex,
1429 : RoutineName);
1430 :
1431 954 : DesOutletWaterTemp = state.dataWaterCoils->WaterCoil(CoilNum).DesInletWaterTemp +
1432 954 : state.dataWaterCoils->WaterCoil(CoilNum).DesTotWaterCoilLoad /
1433 477 : (state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterMassFlowRate * Cp);
1434 :
1435 477 : DesSatEnthAtWaterOutTemp = PsyHFnTdbW(DesOutletWaterTemp, PsyWFnTdpPb(state, DesOutletWaterTemp, state.dataEnvrn->StdBaroPress));
1436 477 : DesEnthAtWaterOutTempAirInHumRat = PsyHFnTdbW(DesOutletWaterTemp, state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirHumRat);
1437 477 : DesEnthWaterOut = min(DesSatEnthAtWaterOutTemp, DesEnthAtWaterOutTempAirInHumRat);
1438 :
1439 : // dry coil test
1440 911 : if (state.dataWaterCoils->WaterCoil(CoilNum).DesOutletAirHumRat < state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirHumRat &&
1441 434 : DesHumRatAtWaterInTemp < state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirHumRat) { // wet coil
1442 :
1443 : // Calculations for BYPASS FACTOR at design conditions
1444 : // Calculate "slope" of temperature vs. humidity ratio between entering and leaving states
1445 434 : SlopeTempVsHumRatio =
1446 434 : (state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirTemp - state.dataWaterCoils->WaterCoil(CoilNum).DesOutletAirTemp) /
1447 868 : max((state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirHumRat -
1448 434 : state.dataWaterCoils->WaterCoil(CoilNum).DesOutletAirHumRat),
1449 : SmallNo);
1450 :
1451 : // Initialize iteration parameters
1452 434 : DesAirTempApparatusDewPt =
1453 868 : PsyTdpFnWPb(state, state.dataWaterCoils->WaterCoil(CoilNum).DesOutletAirHumRat, state.dataEnvrn->OutBaroPress);
1454 :
1455 : // Iterating to calculate Apparatus Dew Point Temperature at Design Conditions
1456 2237 : for (iter = 1; iter <= itmax; ++iter) {
1457 :
1458 : // Calculate apparatus dewpoint and compare with predicted value
1459 : // using entering conditions and SlopeTempVsHumRatio
1460 2237 : DesAirHumRatApparatusDewPt = PsyWFnTdpPb(state, DesAirTempApparatusDewPt, state.dataEnvrn->OutBaroPress);
1461 :
1462 : // Initial Estimate for apparatus Dew Point Temperature
1463 2237 : TempApparatusDewPtEstimate =
1464 2237 : state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirTemp -
1465 2237 : SlopeTempVsHumRatio * (state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirHumRat - DesAirHumRatApparatusDewPt);
1466 :
1467 : // Iterating to calculate Apparatus Dew Point Temperature at Design Condition
1468 2237 : error = DesAirTempApparatusDewPt - TempApparatusDewPtEstimate;
1469 2237 : Iterate(ResultX, 0.01, DesAirTempApparatusDewPt, error, X1, Y1, iter, icvg);
1470 2237 : DesAirTempApparatusDewPt = ResultX;
1471 :
1472 : // If converged, exit loop
1473 2237 : if (icvg == 1) {
1474 408 : goto App_DewPoint_Loop1_exit;
1475 : }
1476 :
1477 : // If not converged due to low Humidity Ratio approximate value at outlet conditions
1478 1829 : if (iter == itmax) {
1479 26 : state.dataWaterCoils->NoSatCurveIntersect = true;
1480 26 : DesAirTempApparatusDewPt =
1481 52 : PsyTdpFnWPb(state, state.dataWaterCoils->WaterCoil(CoilNum).DesOutletAirHumRat, state.dataEnvrn->OutBaroPress);
1482 26 : DesAirHumRatApparatusDewPt = PsyWFnTdpPb(state, DesAirTempApparatusDewPt, state.dataEnvrn->OutBaroPress);
1483 26 : goto App_DewPoint_Loop1_exit;
1484 : }
1485 :
1486 : // End of Loop for Iteration
1487 : }
1488 0 : App_DewPoint_Loop1_exit:;
1489 :
1490 : // Air enthalpy at apparatus dew point at design conditions
1491 434 : DesAirApparatusDewPtEnth = PsyHFnTdbW(DesAirTempApparatusDewPt, DesAirHumRatApparatusDewPt);
1492 :
1493 : // Calculate bypass factor from enthalpies calculated above.
1494 434 : DesBypassFactor = (DesOutletAirEnth - DesAirApparatusDewPtEnth) / (DesInletAirEnth - DesAirApparatusDewPtEnth);
1495 :
1496 : // Check for bypass factor for unsuitable value. Note that bypass factor is never used in the coil calculation
1497 434 : if ((DesBypassFactor > 0.5) || (DesBypassFactor < 0.0)) {
1498 116 : state.dataWaterCoils->CBFTooLarge = true;
1499 116 : DesBypassFactor = 0.37;
1500 : }
1501 :
1502 434 : if (DesEnthWaterOut > DesInletAirEnth) {
1503 0 : ShowWarningError(state,
1504 0 : "In calculating the design coil UA for Coil:Cooling:Water " + state.dataWaterCoils->WaterCoil(CoilNum).Name);
1505 0 : ShowContinueError(state, "the outlet chilled water design enthalpy is greater than the inlet air design enthalpy.");
1506 0 : ShowContinueError(state,
1507 0 : format("To correct this condition the design chilled water flow rate will be increased from {:.5R}",
1508 0 : state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterVolFlowRate));
1509 0 : EnthCorrFrac = (DesEnthWaterOut - DesInletAirEnth) / (DesEnthWaterOut - DesSatEnthAtWaterInTemp);
1510 0 : state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterVolFlowRate *= (1.0 + 2.0 * EnthCorrFrac);
1511 0 : ShowContinueError(state, format("to {:.5R} m3/s", state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterVolFlowRate));
1512 0 : state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterMassFlowRate =
1513 0 : rho * state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterVolFlowRate;
1514 0 : DesOutletWaterTemp = state.dataWaterCoils->WaterCoil(CoilNum).DesInletWaterTemp +
1515 0 : state.dataWaterCoils->WaterCoil(CoilNum).DesTotWaterCoilLoad /
1516 0 : (state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterMassFlowRate * Cp);
1517 0 : DesSatEnthAtWaterOutTemp =
1518 0 : PsyHFnTdbW(DesOutletWaterTemp, PsyWFnTdpPb(state, DesOutletWaterTemp, state.dataEnvrn->StdBaroPress));
1519 0 : DesEnthAtWaterOutTempAirInHumRat = PsyHFnTdbW(DesOutletWaterTemp, state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirHumRat);
1520 0 : DesEnthWaterOut = min(DesSatEnthAtWaterOutTemp, DesEnthAtWaterOutTempAirInHumRat);
1521 : }
1522 :
1523 : // Determine air-side coefficient, UACoilExternal, assuming that the
1524 : // surface temperature is at the apparatus dewpoint temperature
1525 434 : if (DesAirApparatusDewPtEnth <= DesSatEnthAtWaterInTemp) state.dataWaterCoils->BelowInletWaterTemp = true;
1526 434 : if ((DesInletAirEnth - DesEnthWaterOut) > SmallNo && (DesOutletAirEnth - DesSatEnthAtWaterInTemp) > SmallNo) {
1527 868 : LogMeanEnthDiff = ((DesInletAirEnth - DesEnthWaterOut) - (DesOutletAirEnth - DesSatEnthAtWaterInTemp)) /
1528 434 : std::log((DesInletAirEnth - DesEnthWaterOut) / (DesOutletAirEnth - DesSatEnthAtWaterInTemp));
1529 : } else {
1530 0 : LogMeanEnthDiff = 2000.0; // UA will be 1/2 the design coil load
1531 : }
1532 434 : DesUACoilExternalEnth = state.dataWaterCoils->WaterCoil(CoilNum).DesTotWaterCoilLoad / LogMeanEnthDiff;
1533 434 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilExternal =
1534 434 : DesUACoilExternalEnth * PsyCpAirFnW(state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirHumRat);
1535 :
1536 720 : if (Ipass == 1 && (state.dataWaterCoils->NoSatCurveIntersect || state.dataWaterCoils->CBFTooLarge ||
1537 286 : state.dataWaterCoils->BelowInletWaterTemp)) {
1538 : // reset outlet conditions to 90% relative humidity at the same outlet enthalpy
1539 76 : state.dataWaterCoils->TOutNew = TdbFnHRhPb(state, DesOutletAirEnth, 0.9, state.dataEnvrn->StdBaroPress);
1540 76 : state.dataWaterCoils->WOutNew = PsyWFnTdbH(state, state.dataWaterCoils->TOutNew, DesOutletAirEnth);
1541 151 : if (state.dataWaterCoils->WOutNew >= state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirHumRat ||
1542 75 : state.dataWaterCoils->TOutNew > state.dataWaterCoils->WaterCoil(CoilNum).DesOutletAirTemp) {
1543 68 : state.dataWaterCoils->NoExitCondReset = true;
1544 : }
1545 76 : goto Inlet_Conditions_Loop_loop;
1546 : }
1547 :
1548 358 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilInternal = state.dataWaterCoils->WaterCoil(CoilNum).UACoilExternal * 3.30;
1549 : // Overall heat transfer coefficient
1550 716 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilTotal = 1.0 / (1.0 / state.dataWaterCoils->WaterCoil(CoilNum).UACoilExternal +
1551 358 : 1.0 / state.dataWaterCoils->WaterCoil(CoilNum).UACoilInternal);
1552 :
1553 : } else { // dry coil
1554 :
1555 43 : if (DesOutletWaterTemp > state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirTemp) {
1556 0 : ShowWarningError(state,
1557 0 : "In calculating the design coil UA for Coil:Cooling:Water " + state.dataWaterCoils->WaterCoil(CoilNum).Name);
1558 0 : ShowContinueError(state, "the outlet chilled water design temperature is greater than the inlet air design temperature.");
1559 0 : ShowContinueError(state,
1560 0 : format("To correct this condition the design chilled water flow rate will be increased from {:.5R}",
1561 0 : state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterVolFlowRate));
1562 0 : TempCorrFrac = (DesOutletWaterTemp - state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirTemp) /
1563 0 : (DesOutletWaterTemp - state.dataWaterCoils->WaterCoil(CoilNum).DesInletWaterTemp);
1564 0 : state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterVolFlowRate *= (1.0 + 2.0 * TempCorrFrac);
1565 0 : ShowContinueError(state, format("to {:.5R} m3/s", state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterVolFlowRate));
1566 0 : state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterMassFlowRate =
1567 0 : rho * state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterVolFlowRate;
1568 0 : DesOutletWaterTemp = state.dataWaterCoils->WaterCoil(CoilNum).DesInletWaterTemp +
1569 0 : state.dataWaterCoils->WaterCoil(CoilNum).DesTotWaterCoilLoad /
1570 0 : (state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterMassFlowRate * Cp);
1571 : }
1572 :
1573 86 : if ((state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirTemp - DesOutletWaterTemp) > SmallNo &&
1574 43 : (state.dataWaterCoils->WaterCoil(CoilNum).DesOutletAirTemp - state.dataWaterCoils->WaterCoil(CoilNum).DesInletWaterTemp) >
1575 : SmallNo) {
1576 129 : LogMeanTempDiff = ((state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirTemp - DesOutletWaterTemp) -
1577 86 : (state.dataWaterCoils->WaterCoil(CoilNum).DesOutletAirTemp -
1578 43 : state.dataWaterCoils->WaterCoil(CoilNum).DesInletWaterTemp)) /
1579 86 : std::log((state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirTemp - DesOutletWaterTemp) /
1580 86 : (state.dataWaterCoils->WaterCoil(CoilNum).DesOutletAirTemp -
1581 43 : state.dataWaterCoils->WaterCoil(CoilNum).DesInletWaterTemp));
1582 43 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilExternal =
1583 43 : state.dataWaterCoils->WaterCoil(CoilNum).DesTotWaterCoilLoad / LogMeanTempDiff;
1584 : } else {
1585 0 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilExternal =
1586 0 : state.dataWaterCoils->WaterCoil(CoilNum).DesTotWaterCoilLoad / 2.0; // make the UA large
1587 : }
1588 43 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilInternal = state.dataWaterCoils->WaterCoil(CoilNum).UACoilExternal * 3.30;
1589 : // Overall heat transfer coefficient
1590 86 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilTotal = 1.0 / (1.0 / state.dataWaterCoils->WaterCoil(CoilNum).UACoilExternal +
1591 43 : 1.0 / state.dataWaterCoils->WaterCoil(CoilNum).UACoilInternal);
1592 43 : goto Inlet_Conditions_Loop_exit;
1593 : }
1594 :
1595 434 : Inlet_Conditions_Loop_loop:;
1596 : }
1597 76 : Inlet_Conditions_Loop_exit:;
1598 :
1599 : // estimate the heat external transfer surface area using typical design over all U value
1600 401 : state.dataWaterCoils->WaterCoil(CoilNum).TotCoilOutsideSurfArea = EstimateHEXSurfaceArea(state, CoilNum);
1601 : // calculate internal and external "UA per external surface area"
1602 401 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilInternalPerUnitArea =
1603 401 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilInternal / state.dataWaterCoils->WaterCoil(CoilNum).TotCoilOutsideSurfArea;
1604 401 : state.dataWaterCoils->WaterCoil(CoilNum).UAWetExtPerUnitArea =
1605 401 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilExternal / state.dataWaterCoils->WaterCoil(CoilNum).TotCoilOutsideSurfArea;
1606 : // approximate the dry UA as 1.0 times wet UA
1607 401 : state.dataWaterCoils->WaterCoil(CoilNum).UADryExtPerUnitArea = state.dataWaterCoils->WaterCoil(CoilNum).UAWetExtPerUnitArea;
1608 :
1609 : // Now use SolveRoot to "invert" the cooling coil model to obtain the UA given the specified design inlet and outlet conditions
1610 : // Note that the UAs we have obtained so far are rough estimates that are the starting points for the the following iterative
1611 : // calulation of the actual UAs.
1612 401 : state.dataWaterCoils->WaterCoil(CoilNum).InletAirTemp = state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirTemp;
1613 401 : state.dataWaterCoils->WaterCoil(CoilNum).InletAirHumRat = state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirHumRat;
1614 401 : state.dataWaterCoils->WaterCoil(CoilNum).InletWaterTemp = state.dataWaterCoils->WaterCoil(CoilNum).DesInletWaterTemp;
1615 401 : state.dataWaterCoils->WaterCoil(CoilNum).InletWaterMassFlowRate = rho * state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterVolFlowRate;
1616 401 : state.dataWaterCoils->WaterCoil(CoilNum).InletAirMassFlowRate = state.dataWaterCoils->WaterCoil(CoilNum).DesAirMassFlowRate;
1617 : // set the lower and upper limits on the UA
1618 401 : UA0 = 0.1 * state.dataWaterCoils->WaterCoil(CoilNum).UACoilExternal;
1619 401 : UA1 = 10.0 * state.dataWaterCoils->WaterCoil(CoilNum).UACoilExternal;
1620 : // Invert the simple cooling coil model: given the design inlet conditions and the design load, find the design UA
1621 315320 : auto f = [&state, CoilNum](Real64 const UA) {
1622 : int FanOpMode;
1623 : Real64 PartLoadRatio;
1624 :
1625 7883 : FanOpMode = ContFanCycCoil;
1626 7883 : PartLoadRatio = 1.0;
1627 23649 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilExternal = UA;
1628 31532 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilInternal = state.dataWaterCoils->WaterCoil(CoilNum).UACoilExternal * 3.3;
1629 39415 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilTotal = 1.0 / (1.0 / state.dataWaterCoils->WaterCoil(CoilNum).UACoilExternal +
1630 15766 : 1.0 / state.dataWaterCoils->WaterCoil(CoilNum).UACoilInternal);
1631 23649 : state.dataWaterCoils->WaterCoil(CoilNum).TotCoilOutsideSurfArea = EstimateHEXSurfaceArea(state, CoilNum);
1632 15766 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilInternalPerUnitArea =
1633 31532 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilInternal / state.dataWaterCoils->WaterCoil(CoilNum).TotCoilOutsideSurfArea;
1634 15766 : state.dataWaterCoils->WaterCoil(CoilNum).UAWetExtPerUnitArea =
1635 31532 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilExternal / state.dataWaterCoils->WaterCoil(CoilNum).TotCoilOutsideSurfArea;
1636 31532 : state.dataWaterCoils->WaterCoil(CoilNum).UADryExtPerUnitArea = state.dataWaterCoils->WaterCoil(CoilNum).UAWetExtPerUnitArea;
1637 :
1638 15766 : CoolingCoil(state, CoilNum, true, state.dataWaterCoils->DesignCalc, FanOpMode, PartLoadRatio);
1639 :
1640 23649 : return (state.dataWaterCoils->WaterCoil(CoilNum).DesTotWaterCoilLoad -
1641 15766 : state.dataWaterCoils->WaterCoil(CoilNum).TotWaterCoolingCoilRate) /
1642 15766 : state.dataWaterCoils->WaterCoil(CoilNum).DesTotWaterCoilLoad;
1643 401 : };
1644 401 : General::SolveRoot(state, 0.001, MaxIte, SolFla, UA, f, UA0, UA1);
1645 : // if the numerical inversion failed, issue error messages.
1646 401 : if (SolFla == -1) {
1647 0 : ShowSevereError(state, "Calculation of cooling coil design UA failed for coil " + state.dataWaterCoils->WaterCoil(CoilNum).Name);
1648 0 : ShowContinueError(state, " Iteration limit exceeded in calculating coil UA");
1649 0 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilExternal = UA0 * 10.0;
1650 0 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilInternal = state.dataWaterCoils->WaterCoil(CoilNum).UACoilExternal * 3.3;
1651 0 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilTotal = 1.0 / (1.0 / state.dataWaterCoils->WaterCoil(CoilNum).UACoilExternal +
1652 0 : 1.0 / state.dataWaterCoils->WaterCoil(CoilNum).UACoilInternal);
1653 0 : state.dataWaterCoils->WaterCoil(CoilNum).TotCoilOutsideSurfArea = EstimateHEXSurfaceArea(state, CoilNum);
1654 0 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilInternalPerUnitArea =
1655 0 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilInternal / state.dataWaterCoils->WaterCoil(CoilNum).TotCoilOutsideSurfArea;
1656 0 : state.dataWaterCoils->WaterCoil(CoilNum).UAWetExtPerUnitArea =
1657 0 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilExternal / state.dataWaterCoils->WaterCoil(CoilNum).TotCoilOutsideSurfArea;
1658 0 : state.dataWaterCoils->WaterCoil(CoilNum).UADryExtPerUnitArea = state.dataWaterCoils->WaterCoil(CoilNum).UAWetExtPerUnitArea;
1659 0 : ShowContinueError(state, format(" Coil design UA set to {:.6R} [W/C]", state.dataWaterCoils->WaterCoil(CoilNum).UACoilTotal));
1660 401 : } else if (SolFla == -2) {
1661 11 : ShowSevereError(state, "Calculation of cooling coil design UA failed for coil " + state.dataWaterCoils->WaterCoil(CoilNum).Name);
1662 11 : ShowContinueError(state, " Bad starting values for UA");
1663 11 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilExternal = UA0 * 10.0;
1664 11 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilInternal = state.dataWaterCoils->WaterCoil(CoilNum).UACoilExternal * 3.3;
1665 22 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilTotal = 1.0 / (1.0 / state.dataWaterCoils->WaterCoil(CoilNum).UACoilExternal +
1666 11 : 1.0 / state.dataWaterCoils->WaterCoil(CoilNum).UACoilInternal);
1667 11 : state.dataWaterCoils->WaterCoil(CoilNum).TotCoilOutsideSurfArea = EstimateHEXSurfaceArea(state, CoilNum);
1668 11 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilInternalPerUnitArea =
1669 11 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilInternal / state.dataWaterCoils->WaterCoil(CoilNum).TotCoilOutsideSurfArea;
1670 11 : state.dataWaterCoils->WaterCoil(CoilNum).UAWetExtPerUnitArea =
1671 11 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilExternal / state.dataWaterCoils->WaterCoil(CoilNum).TotCoilOutsideSurfArea;
1672 11 : state.dataWaterCoils->WaterCoil(CoilNum).UADryExtPerUnitArea = state.dataWaterCoils->WaterCoil(CoilNum).UAWetExtPerUnitArea;
1673 11 : ShowContinueError(state, format(" Coil design UA set to {:.6R} [W/C]", state.dataWaterCoils->WaterCoil(CoilNum).UACoilTotal));
1674 : }
1675 :
1676 : // cooling coil surface area
1677 401 : state.dataWaterCoils->SurfaceArea = state.dataWaterCoils->WaterCoil(CoilNum).TotCoilOutsideSurfArea;
1678 :
1679 : // cooling coil overall UA value
1680 401 : state.dataWaterCoils->UATotal = state.dataWaterCoils->WaterCoil(CoilNum).UACoilTotal;
1681 :
1682 : // save the design internal and external UAs
1683 401 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilExternalDes = state.dataWaterCoils->WaterCoil(CoilNum).UACoilExternal;
1684 401 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilInternalDes = state.dataWaterCoils->WaterCoil(CoilNum).UACoilInternal;
1685 : }
1686 :
1687 : //@@@@ DESIGN CONDITION END HERE @@@@
1688 :
1689 : // Calculate rated Total, latent, sensible capacity, SHR, effectiveness
1690 20732 : if (state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterSimpleHeating) {
1691 17163 : state.dataWaterCoils->WaterCoil(CoilNum).InletAirTemp = 16.6;
1692 17163 : state.dataWaterCoils->WaterCoil(CoilNum).InletAirHumRat = PsyWFnTdbRhPb(state, 16.6, 0.5, state.dataEnvrn->StdBaroPress, RoutineName);
1693 17163 : state.dataWaterCoils->WaterCoil(CoilNum).InletWaterTemp = 82.2;
1694 : } else {
1695 3569 : state.dataWaterCoils->WaterCoil(CoilNum).InletAirTemp = 26.67;
1696 3569 : state.dataWaterCoils->WaterCoil(CoilNum).InletAirHumRat = PsyWFnTdbTwbPb(state, 26.67, 19.44, state.dataEnvrn->StdBaroPress, RoutineName);
1697 3569 : state.dataWaterCoils->WaterCoil(CoilNum).InletWaterTemp = 6.67;
1698 : }
1699 20732 : state.dataWaterCoils->WaterCoil(CoilNum).InletAirEnthalpy =
1700 20732 : PsyHFnTdbW(state.dataWaterCoils->WaterCoil(CoilNum).InletAirTemp, state.dataWaterCoils->WaterCoil(CoilNum).InletAirHumRat);
1701 20732 : state.dataWaterCoils->WaterCoil(CoilNum).InletWaterMassFlowRate = state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterMassFlowRate;
1702 20732 : state.dataWaterCoils->WaterCoil(CoilNum).InletAirMassFlowRate =
1703 20732 : state.dataEnvrn->StdRhoAir * state.dataWaterCoils->WaterCoil(CoilNum).DesAirVolFlowRate;
1704 20732 : CapacitanceAir =
1705 20732 : state.dataWaterCoils->WaterCoil(CoilNum).InletAirMassFlowRate * PsyCpAirFnW(state.dataWaterCoils->WaterCoil(CoilNum).InletAirHumRat);
1706 :
1707 62196 : Cp = GetSpecificHeatGlycol(state,
1708 20732 : state.dataPlnt->PlantLoop(state.dataWaterCoils->WaterCoil(CoilNum).WaterPlantLoc.loopNum).FluidName,
1709 20732 : state.dataWaterCoils->WaterCoil(CoilNum).InletWaterTemp,
1710 20732 : state.dataPlnt->PlantLoop(state.dataWaterCoils->WaterCoil(CoilNum).WaterPlantLoc.loopNum).FluidIndex,
1711 : RoutineName);
1712 :
1713 20732 : state.dataWaterCoils->CapacitanceWater = state.dataWaterCoils->WaterCoil(CoilNum).InletWaterMassFlowRate * Cp;
1714 20732 : state.dataWaterCoils->CMin = min(CapacitanceAir, state.dataWaterCoils->CapacitanceWater);
1715 20732 : if (state.dataWaterCoils->CMin > 0.0) {
1716 20461 : if (state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterCooling) {
1717 2687 : CoolingCoil(state, CoilNum, FirstHVACIteration, state.dataWaterCoils->DesignCalc, ContFanCycCoil, 1.0);
1718 2687 : state.dataWaterCoils->CoilEffectiveness =
1719 5374 : (state.dataWaterCoils->WaterCoil(CoilNum).InletAirTemp - state.dataWaterCoils->WaterCoil(CoilNum).OutletAirTemp) /
1720 5374 : (state.dataWaterCoils->WaterCoil(CoilNum).InletAirTemp - state.dataWaterCoils->WaterCoil(CoilNum).InletWaterTemp) *
1721 2687 : (CapacitanceAir / state.dataWaterCoils->CMin);
1722 5374 : state.dataWaterCoils->RatedLatentCapacity = state.dataWaterCoils->WaterCoil(CoilNum).TotWaterCoolingCoilRate -
1723 2687 : state.dataWaterCoils->WaterCoil(CoilNum).SenWaterCoolingCoilRate;
1724 5374 : state.dataWaterCoils->RatedSHR = state.dataWaterCoils->WaterCoil(CoilNum).SenWaterCoolingCoilRate /
1725 2687 : state.dataWaterCoils->WaterCoil(CoilNum).TotWaterCoolingCoilRate;
1726 17774 : } else if (state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterDetailedFlatCooling) {
1727 872 : CalcDetailFlatFinCoolingCoil(state, CoilNum, state.dataWaterCoils->DesignCalc, ContFanCycCoil, 1.0);
1728 872 : state.dataWaterCoils->CoilEffectiveness =
1729 1744 : (state.dataWaterCoils->WaterCoil(CoilNum).InletAirTemp - state.dataWaterCoils->WaterCoil(CoilNum).OutletAirTemp) /
1730 1744 : (state.dataWaterCoils->WaterCoil(CoilNum).InletAirTemp - state.dataWaterCoils->WaterCoil(CoilNum).InletWaterTemp) *
1731 872 : (CapacitanceAir / state.dataWaterCoils->CMin);
1732 1744 : state.dataWaterCoils->RatedLatentCapacity = state.dataWaterCoils->WaterCoil(CoilNum).TotWaterCoolingCoilRate -
1733 872 : state.dataWaterCoils->WaterCoil(CoilNum).SenWaterCoolingCoilRate;
1734 1744 : state.dataWaterCoils->RatedSHR = state.dataWaterCoils->WaterCoil(CoilNum).SenWaterCoolingCoilRate /
1735 872 : state.dataWaterCoils->WaterCoil(CoilNum).TotWaterCoolingCoilRate;
1736 16902 : } else if (state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterSimpleHeating) {
1737 16902 : CalcSimpleHeatingCoil(state, CoilNum, ContFanCycCoil, 1.0, state.dataWaterCoils->DesignCalc);
1738 16902 : state.dataWaterCoils->CoilEffectiveness =
1739 33804 : (state.dataWaterCoils->WaterCoil(CoilNum).OutletAirTemp - state.dataWaterCoils->WaterCoil(CoilNum).InletAirTemp) /
1740 33804 : (state.dataWaterCoils->WaterCoil(CoilNum).InletWaterTemp - state.dataWaterCoils->WaterCoil(CoilNum).InletAirTemp) *
1741 16902 : (CapacitanceAir / state.dataWaterCoils->CMin);
1742 : }
1743 : } else {
1744 271 : state.dataWaterCoils->CoilEffectiveness = 0.0;
1745 271 : state.dataWaterCoils->WaterCoil(CoilNum).TotWaterHeatingCoilRate = 0.0;
1746 271 : state.dataWaterCoils->WaterCoil(CoilNum).TotWaterCoolingCoilRate = 0.0;
1747 271 : state.dataWaterCoils->WaterCoil(CoilNum).SenWaterCoolingCoilRate = 0.0;
1748 271 : state.dataWaterCoils->RatedLatentCapacity = 0.0;
1749 271 : state.dataWaterCoils->RatedSHR = 0.0;
1750 : }
1751 20732 : state.dataWaterCoils->MyEnvrnFlag(CoilNum) = false;
1752 :
1753 : } // End If for the Begin Environment initializations
1754 :
1755 137535475 : if (!state.dataGlobal->BeginEnvrnFlag) {
1756 137191014 : state.dataWaterCoils->MyEnvrnFlag(CoilNum) = true;
1757 : }
1758 :
1759 137535475 : if (!state.dataGlobal->DoingSizing) {
1760 137533328 : if (state.dataWaterCoils->MyCoilReportFlag(CoilNum)) {
1761 : // create predefined report entries
1762 3100 : state.dataWaterCoils->MyCoilReportFlag(CoilNum) = false;
1763 3100 : switch (state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilType) {
1764 2554 : case DataPlant::PlantEquipmentType::CoilWaterSimpleHeating: {
1765 2554 : if (state.dataWaterCoils->RptCoilHeaderFlag(1)) {
1766 303 : print(state.files.eio, "{}", "! <Water Heating Coil Capacity Information>,Component Type,Name,Nominal Total Capacity {W}\n");
1767 303 : state.dataWaterCoils->RptCoilHeaderFlag(1) = false;
1768 : }
1769 5108 : PreDefTableEntry(
1770 5108 : state, state.dataOutRptPredefined->pdchHeatCoilType, state.dataWaterCoils->WaterCoil(CoilNum).Name, "Coil:Heating:Water");
1771 10216 : PreDefTableEntry(state,
1772 2554 : state.dataOutRptPredefined->pdchHeatCoilDesCap,
1773 2554 : state.dataWaterCoils->WaterCoil(CoilNum).Name,
1774 2554 : state.dataWaterCoils->WaterCoil(CoilNum).DesWaterHeatingCoilRate);
1775 10216 : PreDefTableEntry(state,
1776 2554 : state.dataOutRptPredefined->pdchHeatCoilNomCap,
1777 2554 : state.dataWaterCoils->WaterCoil(CoilNum).Name,
1778 2554 : state.dataWaterCoils->WaterCoil(CoilNum).TotWaterHeatingCoilRate);
1779 2554 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchHeatCoilNomEff, state.dataWaterCoils->WaterCoil(CoilNum).Name, "-");
1780 2554 : addFootNoteSubTable(
1781 : state,
1782 2554 : state.dataOutRptPredefined->pdstHeatCoil,
1783 2554 : "Nominal values are gross at rated conditions, i.e., the supply air fan heat and electric power NOT accounted for.");
1784 7662 : print(state.files.eio,
1785 : "{},{},{:.2R}\n",
1786 : "Water Heating Coil Capacity Information,Coil:Heating:Water",
1787 2554 : state.dataWaterCoils->WaterCoil(CoilNum).Name,
1788 5108 : state.dataWaterCoils->WaterCoil(CoilNum).TotWaterHeatingCoilRate);
1789 10216 : state.dataRptCoilSelection->coilSelectionReportObj->setCoilAirFlow(state,
1790 2554 : state.dataWaterCoils->WaterCoil(CoilNum).Name,
1791 : "Coil:Heating:Water",
1792 2554 : state.dataWaterCoils->WaterCoil(CoilNum).DesAirVolFlowRate,
1793 2554 : state.dataWaterCoils->WaterCoil(CoilNum).RequestingAutoSize);
1794 17878 : state.dataRptCoilSelection->coilSelectionReportObj->setCoilWaterHeaterCapacityNodeNums(
1795 : state,
1796 2554 : state.dataWaterCoils->WaterCoil(CoilNum).Name,
1797 : "Coil:Heating:Water",
1798 2554 : state.dataWaterCoils->WaterCoil(CoilNum).DesWaterHeatingCoilRate,
1799 2554 : state.dataWaterCoils->WaterCoil(CoilNum).RequestingAutoSize,
1800 2554 : state.dataWaterCoils->WaterCoil(CoilNum).WaterInletNodeNum,
1801 2554 : state.dataWaterCoils->WaterCoil(CoilNum).WaterOutletNodeNum,
1802 2554 : state.dataWaterCoils->WaterCoil(CoilNum).WaterPlantLoc.loopNum); // coil report
1803 2554 : break;
1804 : }
1805 143 : case DataPlant::PlantEquipmentType::CoilWaterDetailedFlatCooling: {
1806 143 : if (state.dataWaterCoils->RptCoilHeaderFlag(2)) {
1807 114 : print(state.files.eio,
1808 : "{}\n",
1809 : "! <Water Cooling Coil Capacity Information>,Component Type,Name,Nominal Total "
1810 : "Capacity {W},Nominal Sensible Capacity {W},Nominal Latent Capacity {W},Nominal "
1811 114 : "Sensible Heat Ratio");
1812 114 : state.dataWaterCoils->RptCoilHeaderFlag(2) = false;
1813 : }
1814 286 : state.dataWaterCoils->RatedLatentCapacity = state.dataWaterCoils->WaterCoil(CoilNum).TotWaterCoolingCoilRate -
1815 143 : state.dataWaterCoils->WaterCoil(CoilNum).SenWaterCoolingCoilRate;
1816 143 : state.dataWaterCoils->RatedSHR = SafeDivide(state.dataWaterCoils->WaterCoil(CoilNum).SenWaterCoolingCoilRate,
1817 143 : state.dataWaterCoils->WaterCoil(CoilNum).TotWaterCoolingCoilRate);
1818 286 : PreDefTableEntry(state,
1819 143 : state.dataOutRptPredefined->pdchCoolCoilType,
1820 143 : state.dataWaterCoils->WaterCoil(CoilNum).Name,
1821 143 : "Coil:Cooling:Water:DetailedGeometry");
1822 572 : PreDefTableEntry(state,
1823 143 : state.dataOutRptPredefined->pdchCoolCoilDesCap,
1824 143 : state.dataWaterCoils->WaterCoil(CoilNum).Name,
1825 143 : state.dataWaterCoils->WaterCoil(CoilNum).DesWaterCoolingCoilRate);
1826 572 : PreDefTableEntry(state,
1827 143 : state.dataOutRptPredefined->pdchCoolCoilTotCap,
1828 143 : state.dataWaterCoils->WaterCoil(CoilNum).Name,
1829 143 : state.dataWaterCoils->WaterCoil(CoilNum).TotWaterCoolingCoilRate);
1830 572 : PreDefTableEntry(state,
1831 143 : state.dataOutRptPredefined->pdchCoolCoilSensCap,
1832 143 : state.dataWaterCoils->WaterCoil(CoilNum).Name,
1833 143 : state.dataWaterCoils->WaterCoil(CoilNum).SenWaterCoolingCoilRate);
1834 572 : PreDefTableEntry(state,
1835 143 : state.dataOutRptPredefined->pdchCoolCoilLatCap,
1836 143 : state.dataWaterCoils->WaterCoil(CoilNum).Name,
1837 143 : state.dataWaterCoils->RatedLatentCapacity);
1838 572 : PreDefTableEntry(state,
1839 143 : state.dataOutRptPredefined->pdchCoolCoilSHR,
1840 143 : state.dataWaterCoils->WaterCoil(CoilNum).Name,
1841 143 : state.dataWaterCoils->RatedSHR);
1842 143 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchCoolCoilNomEff, state.dataWaterCoils->WaterCoil(CoilNum).Name, "-");
1843 143 : addFootNoteSubTable(
1844 : state,
1845 143 : state.dataOutRptPredefined->pdstCoolCoil,
1846 143 : "Nominal values are gross at rated conditions, i.e., the supply air fan heat and electric power NOT accounted for.");
1847 858 : print(state.files.eio,
1848 : "{},{},{:.2R},{:.2R},{:.2R},{:.2R}\n",
1849 : "Water Cooling Coil Capacity Information,Coil:Cooling:Water:DetailedGeometry",
1850 143 : state.dataWaterCoils->WaterCoil(CoilNum).Name,
1851 143 : state.dataWaterCoils->WaterCoil(CoilNum).TotWaterCoolingCoilRate,
1852 143 : state.dataWaterCoils->WaterCoil(CoilNum).SenWaterCoolingCoilRate,
1853 143 : state.dataWaterCoils->RatedLatentCapacity,
1854 286 : state.dataWaterCoils->RatedSHR);
1855 572 : state.dataRptCoilSelection->coilSelectionReportObj->setCoilAirFlow(
1856 : state,
1857 143 : state.dataWaterCoils->WaterCoil(CoilNum).Name,
1858 : "Coil:Cooling:Water:DetailedGeometry",
1859 143 : state.dataWaterCoils->WaterCoil(CoilNum).DesAirVolFlowRate,
1860 143 : state.dataWaterCoils->WaterCoil(CoilNum).RequestingAutoSize); // Coil Report
1861 1001 : state.dataRptCoilSelection->coilSelectionReportObj->setCoilWaterCoolingCapacity(
1862 : state,
1863 143 : state.dataWaterCoils->WaterCoil(CoilNum).Name,
1864 : "Coil:Cooling:Water:DetailedGeometry",
1865 143 : state.dataWaterCoils->WaterCoil(CoilNum).DesWaterCoolingCoilRate,
1866 143 : state.dataWaterCoils->WaterCoil(CoilNum).RequestingAutoSize,
1867 143 : state.dataWaterCoils->WaterCoil(CoilNum).WaterInletNodeNum,
1868 143 : state.dataWaterCoils->WaterCoil(CoilNum).WaterOutletNodeNum,
1869 143 : state.dataWaterCoils->WaterCoil(CoilNum).WaterPlantLoc.loopNum); // Coil Report
1870 143 : break;
1871 : }
1872 403 : case DataPlant::PlantEquipmentType::CoilWaterCooling: {
1873 403 : if (state.dataWaterCoils->RptCoilHeaderFlag(2)) {
1874 184 : print(state.files.eio,
1875 : "{}\n",
1876 : "! <Water Cooling Coil Capacity Information>,Component Type,Name,Nominal Total "
1877 : "Capacity {W},Nominal Sensible Capacity {W},Nominal Latent Capacity {W},Nominal "
1878 184 : "Sensible Heat Ratio, Nominal Coil UA Value {W/C}, Nominal Coil Surface Area {m2}");
1879 184 : state.dataWaterCoils->RptCoilHeaderFlag(2) = false;
1880 : }
1881 806 : state.dataWaterCoils->RatedLatentCapacity = state.dataWaterCoils->WaterCoil(CoilNum).TotWaterCoolingCoilRate -
1882 403 : state.dataWaterCoils->WaterCoil(CoilNum).SenWaterCoolingCoilRate;
1883 403 : state.dataWaterCoils->RatedSHR = SafeDivide(state.dataWaterCoils->WaterCoil(CoilNum).SenWaterCoolingCoilRate,
1884 403 : state.dataWaterCoils->WaterCoil(CoilNum).TotWaterCoolingCoilRate);
1885 806 : PreDefTableEntry(
1886 806 : state, state.dataOutRptPredefined->pdchCoolCoilType, state.dataWaterCoils->WaterCoil(CoilNum).Name, "Coil:Cooling:Water");
1887 1612 : PreDefTableEntry(state,
1888 403 : state.dataOutRptPredefined->pdchCoolCoilDesCap,
1889 403 : state.dataWaterCoils->WaterCoil(CoilNum).Name,
1890 403 : state.dataWaterCoils->WaterCoil(CoilNum).DesWaterCoolingCoilRate);
1891 1612 : PreDefTableEntry(state,
1892 403 : state.dataOutRptPredefined->pdchCoolCoilTotCap,
1893 403 : state.dataWaterCoils->WaterCoil(CoilNum).Name,
1894 403 : state.dataWaterCoils->WaterCoil(CoilNum).TotWaterCoolingCoilRate);
1895 1612 : PreDefTableEntry(state,
1896 403 : state.dataOutRptPredefined->pdchCoolCoilSensCap,
1897 403 : state.dataWaterCoils->WaterCoil(CoilNum).Name,
1898 403 : state.dataWaterCoils->WaterCoil(CoilNum).SenWaterCoolingCoilRate);
1899 1612 : PreDefTableEntry(state,
1900 403 : state.dataOutRptPredefined->pdchCoolCoilLatCap,
1901 403 : state.dataWaterCoils->WaterCoil(CoilNum).Name,
1902 403 : state.dataWaterCoils->RatedLatentCapacity);
1903 1612 : PreDefTableEntry(state,
1904 403 : state.dataOutRptPredefined->pdchCoolCoilSHR,
1905 403 : state.dataWaterCoils->WaterCoil(CoilNum).Name,
1906 403 : state.dataWaterCoils->RatedSHR);
1907 403 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchCoolCoilNomEff, state.dataWaterCoils->WaterCoil(CoilNum).Name, "-");
1908 1612 : PreDefTableEntry(state,
1909 403 : state.dataOutRptPredefined->pdchCoolCoilUATotal,
1910 403 : state.dataWaterCoils->WaterCoil(CoilNum).Name,
1911 403 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilTotal);
1912 1612 : PreDefTableEntry(state,
1913 403 : state.dataOutRptPredefined->pdchCoolCoilArea,
1914 403 : state.dataWaterCoils->WaterCoil(CoilNum).Name,
1915 403 : state.dataWaterCoils->WaterCoil(CoilNum).TotCoilOutsideSurfArea);
1916 403 : addFootNoteSubTable(
1917 : state,
1918 403 : state.dataOutRptPredefined->pdstCoolCoil,
1919 403 : "Nominal values are gross at rated conditions, i.e., the supply air fan heat and electric power NOT accounted for.");
1920 3224 : print(state.files.eio,
1921 : "{},{},{:.2R},{:.2R},{:.2R},{:.2R},{:.2R},{:.2R}\n",
1922 : "Water Cooling Coil Capacity Information,Coil:Cooling:Water",
1923 403 : state.dataWaterCoils->WaterCoil(CoilNum).Name,
1924 403 : state.dataWaterCoils->WaterCoil(CoilNum).TotWaterCoolingCoilRate,
1925 403 : state.dataWaterCoils->WaterCoil(CoilNum).SenWaterCoolingCoilRate,
1926 403 : state.dataWaterCoils->RatedLatentCapacity,
1927 403 : state.dataWaterCoils->RatedSHR,
1928 403 : state.dataWaterCoils->UATotal,
1929 806 : state.dataWaterCoils->SurfaceArea);
1930 1612 : state.dataRptCoilSelection->coilSelectionReportObj->setCoilAirFlow(
1931 : state,
1932 403 : state.dataWaterCoils->WaterCoil(CoilNum).Name,
1933 : "Coil:Cooling:Water",
1934 403 : state.dataWaterCoils->WaterCoil(CoilNum).DesAirVolFlowRate,
1935 403 : state.dataWaterCoils->WaterCoil(CoilNum).RequestingAutoSize); // Coil Report
1936 2821 : state.dataRptCoilSelection->coilSelectionReportObj->setCoilWaterCoolingCapacity(
1937 : state,
1938 403 : state.dataWaterCoils->WaterCoil(CoilNum).Name,
1939 : "Coil:Cooling:Water",
1940 403 : state.dataWaterCoils->WaterCoil(CoilNum).DesWaterCoolingCoilRate,
1941 403 : state.dataWaterCoils->WaterCoil(CoilNum).RequestingAutoSize,
1942 403 : state.dataWaterCoils->WaterCoil(CoilNum).WaterInletNodeNum,
1943 403 : state.dataWaterCoils->WaterCoil(CoilNum).WaterOutletNodeNum,
1944 403 : state.dataWaterCoils->WaterCoil(CoilNum).WaterPlantLoc.loopNum); // Coil Report
1945 403 : break;
1946 : }
1947 0 : default:
1948 0 : break;
1949 : }
1950 3100 : if (state.dataWaterCoils->WaterCoil(CoilNum).DesWaterCoolingCoilRate <= 0.0)
1951 2659 : state.dataWaterCoils->WaterCoil(CoilNum).DesWaterCoolingCoilRate = state.dataWaterCoils->WaterCoil(CoilNum).TotWaterCoolingCoilRate;
1952 3100 : if (state.dataWaterCoils->WaterCoil(CoilNum).DesWaterHeatingCoilRate <= 0.0)
1953 883 : state.dataWaterCoils->WaterCoil(CoilNum).DesWaterHeatingCoilRate = state.dataWaterCoils->WaterCoil(CoilNum).TotWaterHeatingCoilRate;
1954 :
1955 : // call coil model with everthing set at rating point
1956 3100 : state.dataWaterCoils->WaterCoil(CoilNum).InletAirMassFlowRate = state.dataWaterCoils->WaterCoil(CoilNum).DesAirMassFlowRate;
1957 3100 : state.dataWaterCoils->WaterCoil(CoilNum).InletAirTemp = state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirTemp;
1958 3100 : state.dataWaterCoils->WaterCoil(CoilNum).InletAirHumRat =
1959 3100 : state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirHumRat; // fixed in sizing routine
1960 6200 : state.dataWaterCoils->WaterCoil(CoilNum).InletAirEnthalpy = Psychrometrics::PsyHFnTdbW(
1961 6200 : state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirTemp, state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirHumRat);
1962 9300 : Real64 DesInletWetBulb = Psychrometrics::PsyTwbFnTdbWPb(state,
1963 3100 : state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirTemp,
1964 3100 : state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirHumRat,
1965 : DataEnvironment::StdPressureSeaLevel,
1966 6200 : "InitWaterCoils");
1967 3100 : state.dataWaterCoils->WaterCoil(CoilNum).InletWaterMassFlowRate = state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterMassFlowRate;
1968 3100 : state.dataWaterCoils->WaterCoil(CoilNum).InletWaterTemp = state.dataWaterCoils->WaterCoil(CoilNum).DesInletWaterTemp;
1969 12400 : Real64 cp = GetSpecificHeatGlycol(state,
1970 3100 : state.dataPlnt->PlantLoop(state.dataWaterCoils->WaterCoil(CoilNum).WaterPlantLoc.loopNum).FluidName,
1971 3100 : state.dataWaterCoils->WaterCoil(CoilNum).DesInletWaterTemp,
1972 3100 : state.dataPlnt->PlantLoop(state.dataWaterCoils->WaterCoil(CoilNum).WaterPlantLoc.loopNum).FluidIndex,
1973 6200 : "InitWaterCoil");
1974 3100 : state.dataWaterCoils->WaterCoil(CoilNum).InletWaterEnthalpy = cp * state.dataWaterCoils->WaterCoil(CoilNum).InletWaterTemp;
1975 :
1976 3100 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilVariable = state.dataWaterCoils->WaterCoil(CoilNum).UACoil;
1977 3100 : state.dataWaterCoils->WaterCoil(CoilNum).FaultyCoilFoulingFactor = 0.0;
1978 3100 : Real64 holdOutBaroPress = state.dataEnvrn->OutBaroPress;
1979 3100 : state.dataEnvrn->OutBaroPress = DataEnvironment::StdPressureSeaLevel; // assume rating is for sea level.
1980 3100 : CalcAdjustedCoilUA(state, CoilNum);
1981 :
1982 6200 : std::string coilTypeName(" ");
1983 : // calculate coil sim model at rating point, full load, continuous fan
1984 3100 : if (state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterDetailedFlatCooling) {
1985 143 : CalcDetailFlatFinCoolingCoil(state, CoilNum, state.dataWaterCoils->SimCalc, ContFanCycCoil, 1.0);
1986 143 : coilTypeName = "Coil:Cooling:Water:DetailedGeometry";
1987 2957 : } else if (state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterCooling) {
1988 403 : CoolingCoil(state, CoilNum, FirstHVACIteration, state.dataWaterCoils->SimCalc, ContFanCycCoil, 1.0);
1989 403 : coilTypeName = "Coil:Cooling:Water";
1990 2554 : } else if (state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterSimpleHeating) {
1991 2554 : CalcSimpleHeatingCoil(state, CoilNum, ContFanCycCoil, 1.0, state.dataWaterCoils->SimCalc);
1992 2554 : coilTypeName = "Coil:Heating:Water";
1993 : }
1994 :
1995 : // coil outlets
1996 3100 : Real64 RatedOutletWetBulb(0.0);
1997 6200 : RatedOutletWetBulb = Psychrometrics::PsyTwbFnTdbWPb(state,
1998 3100 : state.dataWaterCoils->WaterCoil(CoilNum).OutletAirTemp,
1999 3100 : state.dataWaterCoils->WaterCoil(CoilNum).OutletAirHumRat,
2000 : DataEnvironment::StdPressureSeaLevel,
2001 3100 : "InitWaterCoil");
2002 :
2003 : // call set routine in coil report
2004 6057 : if (state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterDetailedFlatCooling ||
2005 2957 : state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterCooling) {
2006 4914 : state.dataRptCoilSelection->coilSelectionReportObj->setRatedCoilConditions(
2007 : state,
2008 546 : state.dataWaterCoils->WaterCoil(CoilNum).Name,
2009 : coilTypeName,
2010 546 : state.dataWaterCoils->WaterCoil(CoilNum).TotWaterCoolingCoilRate, // this is the report variable
2011 546 : state.dataWaterCoils->WaterCoil(CoilNum).SenWaterCoolingCoilRate, // this is the report variable
2012 546 : state.dataWaterCoils->WaterCoil(CoilNum).InletAirMassFlowRate,
2013 546 : state.dataWaterCoils->WaterCoil(CoilNum).InletAirTemp,
2014 546 : state.dataWaterCoils->WaterCoil(CoilNum).InletAirHumRat,
2015 : DesInletWetBulb,
2016 546 : state.dataWaterCoils->WaterCoil(CoilNum).OutletAirTemp,
2017 546 : state.dataWaterCoils->WaterCoil(CoilNum).OutletAirHumRat,
2018 : RatedOutletWetBulb,
2019 : -999.0,
2020 : -999.0,
2021 : -999.0,
2022 : -999.0); // coil effectiveness
2023 2554 : } else if (state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterSimpleHeating) {
2024 22986 : state.dataRptCoilSelection->coilSelectionReportObj->setRatedCoilConditions(
2025 : state,
2026 2554 : state.dataWaterCoils->WaterCoil(CoilNum).Name,
2027 : coilTypeName,
2028 2554 : state.dataWaterCoils->WaterCoil(CoilNum).TotWaterHeatingCoilRate, // this is the report variable
2029 2554 : state.dataWaterCoils->WaterCoil(CoilNum).TotWaterHeatingCoilRate, // this is the report variable
2030 2554 : state.dataWaterCoils->WaterCoil(CoilNum).InletAirMassFlowRate,
2031 2554 : state.dataWaterCoils->WaterCoil(CoilNum).InletAirTemp,
2032 2554 : state.dataWaterCoils->WaterCoil(CoilNum).InletAirHumRat,
2033 : DesInletWetBulb,
2034 2554 : state.dataWaterCoils->WaterCoil(CoilNum).OutletAirTemp,
2035 2554 : state.dataWaterCoils->WaterCoil(CoilNum).OutletAirHumRat,
2036 : RatedOutletWetBulb,
2037 : -999.0,
2038 : -999.0,
2039 : -999.0,
2040 : -999.0); // coil effectiveness
2041 : }
2042 : // now replace the outdoor air conditions set above for one time rating point calc
2043 3100 : state.dataEnvrn->OutBaroPress = holdOutBaroPress;
2044 : }
2045 : }
2046 :
2047 : // Do the Begin Day initializations
2048 : // NONE
2049 :
2050 : // Do the begin HVAC time step initializations
2051 : // NONE
2052 :
2053 : // Do the following initializations (every time step): This should be the info from
2054 : // the previous components outlets or the node data in this section.
2055 : // First set the conditions for the air into the coil model
2056 137535475 : AirInletNode = state.dataWaterCoils->WaterCoil(CoilNum).AirInletNodeNum;
2057 137535475 : WaterInletNode = state.dataWaterCoils->WaterCoil(CoilNum).WaterInletNodeNum;
2058 137535475 : state.dataWaterCoils->WaterCoil(CoilNum).InletAirMassFlowRate = Node(AirInletNode).MassFlowRate;
2059 137535475 : state.dataWaterCoils->WaterCoil(CoilNum).InletAirTemp = Node(AirInletNode).Temp;
2060 137535475 : state.dataWaterCoils->WaterCoil(CoilNum).InletAirHumRat = Node(AirInletNode).HumRat;
2061 137535475 : state.dataWaterCoils->WaterCoil(CoilNum).InletAirEnthalpy = Node(AirInletNode).Enthalpy;
2062 :
2063 137535475 : state.dataWaterCoils->WaterCoil(CoilNum).InletWaterMassFlowRate = Node(WaterInletNode).MassFlowRate;
2064 137535475 : state.dataWaterCoils->WaterCoil(CoilNum).InletWaterTemp = Node(WaterInletNode).Temp;
2065 137535475 : state.dataWaterCoils->WaterCoil(CoilNum).InletWaterEnthalpy = Node(WaterInletNode).Enthalpy;
2066 :
2067 137535475 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilVariable = state.dataWaterCoils->WaterCoil(CoilNum).UACoil;
2068 :
2069 137535475 : CalcAdjustedCoilUA(state, CoilNum);
2070 :
2071 137535475 : state.dataWaterCoils->WaterCoil(CoilNum).TotWaterHeatingCoilRate = 0.0;
2072 137535475 : state.dataWaterCoils->WaterCoil(CoilNum).TotWaterCoolingCoilRate = 0.0;
2073 137535475 : state.dataWaterCoils->WaterCoil(CoilNum).SenWaterCoolingCoilRate = 0.0;
2074 137535475 : }
2075 :
2076 : // refactor coilUA adjustment into separate routine, for use with rating calc
2077 137538575 : void CalcAdjustedCoilUA(EnergyPlusData &state, int const CoilNum)
2078 : {
2079 : // Pull these precalc routines out of big init routine
2080 : // modify the coil UA based on model in Wetter 1999
2081 : Real64 x_a; // result of Eq.70 in Wetter 1999
2082 : Real64 x_w; // result of Eq.72 in Wetter 1999
2083 : Real64 AirConvectTerm; // result of Eq.71 in Wetter 1999
2084 : Real64 WaterConvectTerm; // result of Eq.73 in Wetter 1999
2085 : Real64 WaterConvSensitivity; // "s" in Wetter 1999, temperature sensitivity in water side convection
2086 :
2087 : // Coil:Heating:Water
2088 249695694 : if ((state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterSimpleHeating) &&
2089 112157119 : (!(state.dataWaterCoils->MyUAAndFlowCalcFlag(CoilNum)))) { // update Coil UA based on inlet mass flows and temps
2090 112155112 : x_a = 1.0 + 4.769E-3 * (state.dataWaterCoils->WaterCoil(CoilNum).InletAirTemp - state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirTemp);
2091 112155112 : if (state.dataWaterCoils->WaterCoil(CoilNum).DesAirMassFlowRate > 0.0) {
2092 111491444 : AirConvectTerm =
2093 111491444 : x_a *
2094 111491444 : std::pow(state.dataWaterCoils->WaterCoil(CoilNum).InletAirMassFlowRate / state.dataWaterCoils->WaterCoil(CoilNum).DesAirMassFlowRate,
2095 : 0.8) *
2096 111491444 : state.dataWaterCoils->WaterCoil(CoilNum).AirSideNominalConvect;
2097 : } else {
2098 663668 : AirConvectTerm = 0.0;
2099 : }
2100 112155112 : WaterConvSensitivity = 0.014 / (1.0 + 0.014 * state.dataWaterCoils->WaterCoil(CoilNum).DesInletWaterTemp);
2101 112155112 : x_w = 1.0 + WaterConvSensitivity *
2102 112155112 : (state.dataWaterCoils->WaterCoil(CoilNum).InletWaterTemp - state.dataWaterCoils->WaterCoil(CoilNum).DesInletWaterTemp);
2103 112155112 : if (state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterMassFlowRate > 0.0) {
2104 222062574 : WaterConvectTerm = x_w *
2105 222062574 : std::pow(state.dataWaterCoils->WaterCoil(CoilNum).InletWaterMassFlowRate /
2106 111031287 : state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterMassFlowRate,
2107 : 0.85) *
2108 111031287 : state.dataWaterCoils->WaterCoil(CoilNum).LiquidSideNominalConvect;
2109 : } else {
2110 1123825 : WaterConvectTerm = 0.0;
2111 : }
2112 112155112 : if ((AirConvectTerm > 0.0) && (WaterConvectTerm > 0.0)) {
2113 71051070 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilVariable = 1.0 / ((1.0 / WaterConvectTerm) + (1.0 / AirConvectTerm));
2114 : } else {
2115 : // use nominal UA since variable UA cannot be calculated
2116 41104042 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilVariable = state.dataWaterCoils->WaterCoil(CoilNum).UACoil;
2117 : }
2118 :
2119 : // calculate the Faulty Coil Fouling (thermal insulance) Factor using fault information
2120 224326315 : if (state.dataWaterCoils->WaterCoil(CoilNum).FaultyCoilFoulingFlag &&
2121 : // The fault shouldn't apply during sizing.
2122 112157730 : (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing) && (!state.dataGlobal->KickOffSimulation) &&
2123 : // This was preexisting
2124 1309 : !(state.dataWaterCoils->MyUAAndFlowCalcFlag(CoilNum))) {
2125 : // Store original value
2126 1309 : state.dataWaterCoils->WaterCoil(CoilNum).OriginalUACoilVariable = state.dataWaterCoils->WaterCoil(CoilNum).UACoilVariable;
2127 :
2128 1309 : int FaultIndex = state.dataWaterCoils->WaterCoil(CoilNum).FaultyCoilFoulingIndex;
2129 1309 : FaultsManager::FaultPropertiesFoulingCoil &fouling = state.dataFaultsMgr->FouledCoils(FaultIndex);
2130 1309 : Real64 FaultFrac = fouling.FaultFraction(state);
2131 :
2132 1309 : if (fouling.FoulingInputMethod == FaultsManager::FouledCoil::UARated) {
2133 : // 1/UA' = Frac * (1/UAFouled) + (1-Frac) / UA
2134 1309 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilVariable =
2135 1309 : 1 / (FaultFrac / (fouling.UAFouled) + (1 - FaultFrac) / state.dataWaterCoils->WaterCoil(CoilNum).UACoilVariable);
2136 : } else {
2137 : // R' = R + Rfoul
2138 : // Rfoul = r_air/A_air + r_water/A_water (FoulingFactor = thermal insulance [K/W, A] = Area [m2], r=fouling factor [m2.K/W]
2139 0 : Real64 FoulingFactor = FaultFrac * (fouling.Rfw / (fouling.Aratio * fouling.Aout) + fouling.Rfa / fouling.Aout);
2140 0 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilVariable =
2141 0 : 1.0 / ((1.0 / state.dataWaterCoils->WaterCoil(CoilNum).UACoilVariable) + FoulingFactor);
2142 : }
2143 :
2144 : // Do not allow improving coil performance
2145 1309 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilVariable =
2146 1309 : min(state.dataWaterCoils->WaterCoil(CoilNum).UACoilVariable, state.dataWaterCoils->WaterCoil(CoilNum).OriginalUACoilVariable);
2147 :
2148 : // Only for reporting purposes
2149 1309 : state.dataWaterCoils->WaterCoil(CoilNum).FaultyCoilFoulingFactor =
2150 2618 : (1.0 / state.dataWaterCoils->WaterCoil(CoilNum).UACoilVariable) -
2151 1309 : (1.0 / state.dataWaterCoils->WaterCoil(CoilNum).OriginalUACoilVariable);
2152 : } else {
2153 112153803 : state.dataWaterCoils->WaterCoil(CoilNum).FaultyCoilFoulingFactor = 0;
2154 : }
2155 : }
2156 :
2157 : // Coil:Cooling:Water
2158 : // update Coil UA based on inlet mass flows and temps
2159 159582947 : if (state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterCooling &&
2160 22044372 : (!state.dataWaterCoils->MyCoilDesignFlag(CoilNum))) {
2161 22034986 : if (state.dataWaterCoils->WaterCoil(CoilNum).DesAirMassFlowRate > 0.0) {
2162 22034986 : x_a = 1.0 + 4.769E-3 * (state.dataWaterCoils->WaterCoil(CoilNum).InletAirTemp - state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirTemp);
2163 22034986 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilExternal =
2164 22034986 : x_a *
2165 22034986 : std::pow(state.dataWaterCoils->WaterCoil(CoilNum).InletAirMassFlowRate / state.dataWaterCoils->WaterCoil(CoilNum).DesAirMassFlowRate,
2166 22034986 : 0.8) *
2167 22034986 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilExternalDes;
2168 : } else {
2169 0 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilExternal = state.dataWaterCoils->WaterCoil(CoilNum).UACoilExternalDes;
2170 : }
2171 :
2172 22034986 : if (state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterMassFlowRate > 0.0) {
2173 22034986 : WaterConvSensitivity = 0.014 / (1.0 + 0.014 * state.dataWaterCoils->WaterCoil(CoilNum).DesInletWaterTemp);
2174 22034986 : x_w = 1.0 + WaterConvSensitivity *
2175 22034986 : (state.dataWaterCoils->WaterCoil(CoilNum).InletWaterTemp - state.dataWaterCoils->WaterCoil(CoilNum).DesInletWaterTemp);
2176 44069972 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilInternal = x_w *
2177 44069972 : std::pow(state.dataWaterCoils->WaterCoil(CoilNum).InletWaterMassFlowRate /
2178 22034986 : state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterMassFlowRate,
2179 22034986 : 0.85) *
2180 22034986 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilInternalDes;
2181 : } else {
2182 0 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilInternal = state.dataWaterCoils->WaterCoil(CoilNum).UACoilInternalDes;
2183 : }
2184 :
2185 22034986 : if (!(state.dataWaterCoils->WaterCoil(CoilNum).UACoilInternal > 0.0 && state.dataWaterCoils->WaterCoil(CoilNum).UACoilExternal > 0.0)) {
2186 9621553 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilInternal = state.dataWaterCoils->WaterCoil(CoilNum).UACoilInternalDes;
2187 9621553 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilExternal = state.dataWaterCoils->WaterCoil(CoilNum).UACoilExternalDes;
2188 : }
2189 :
2190 : // If Fouling
2191 44086063 : if (state.dataWaterCoils->WaterCoil(CoilNum).FaultyCoilFoulingFlag &&
2192 : // The fault shouldn't apply during sizing.
2193 22037604 : (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing) && (!state.dataGlobal->KickOffSimulation) &&
2194 : // This was preexisting
2195 1309 : !(state.dataWaterCoils->MyUAAndFlowCalcFlag(CoilNum))) {
2196 : // Store original value
2197 : // This is really UACoilTotal technically, but I don't see the point of declaring another Real on the struct just for that
2198 1309 : state.dataWaterCoils->WaterCoil(CoilNum).OriginalUACoilVariable =
2199 1309 : 1.0 / (1.0 / state.dataWaterCoils->WaterCoil(CoilNum).UACoilExternal + 1.0 / state.dataWaterCoils->WaterCoil(CoilNum).UACoilInternal);
2200 :
2201 1309 : state.dataWaterCoils->WaterCoil(CoilNum).OriginalUACoilExternal = state.dataWaterCoils->WaterCoil(CoilNum).UACoilExternal;
2202 1309 : state.dataWaterCoils->WaterCoil(CoilNum).OriginalUACoilInternal = state.dataWaterCoils->WaterCoil(CoilNum).UACoilInternal;
2203 :
2204 1309 : int FaultIndex = state.dataWaterCoils->WaterCoil(CoilNum).FaultyCoilFoulingIndex;
2205 :
2206 1309 : FaultsManager::FaultPropertiesFoulingCoil &fouling = state.dataFaultsMgr->FouledCoils(FaultIndex);
2207 1309 : Real64 FaultFrac = fouling.FaultFraction(state);
2208 :
2209 1309 : if (fouling.FoulingInputMethod == FaultsManager::FouledCoil::FoulingFactor) {
2210 : // Adjust the External (air) UA and Internal (water) UA accordingly
2211 0 : Real64 Rfoul_air = FaultFrac * (fouling.Rfa / fouling.Aout);
2212 0 : Real64 Rfoul_water = FaultFrac * (fouling.Rfw / (fouling.Aratio * fouling.Aout));
2213 :
2214 0 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilInternal =
2215 0 : 1.0 / (1.0 / state.dataWaterCoils->WaterCoil(CoilNum).UACoilInternal + Rfoul_water);
2216 0 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilExternal =
2217 0 : 1.0 / (1.0 / state.dataWaterCoils->WaterCoil(CoilNum).UACoilExternal + Rfoul_air);
2218 : //
2219 : } else { // iFouledCoil_UARated
2220 : // FouledUARated is supposed to be the overall UA. So we need to split between Internal and External UAs
2221 :
2222 : // How should I split fouling between internal/external?
2223 : // We can actually use the current ratio before fouling...
2224 : // splitRatio = UACoilInternal/UACoilExternal
2225 : // UACoilInternal = UACoilExternal * splitRatio
2226 :
2227 : // UACoilTotal = 1 / (1 / UACoilExternal + 1 / UACoilInternal)
2228 : // UACoilTotal = 1 / (1 / UACoilExternal + 1 / (UACoilExernal * splitRatio))
2229 : // UACoilTotal = UACoilExternal / (1 + 1 / splitRatio) = UACoilExternal * splitRatio / (1 + splitRatio)
2230 : // UACoilExternal = UACoilTotal * (1 + splitRatio) / splitRatio
2231 : // UACoilInternal = UACoilTotal * (1 + splitRatio)
2232 :
2233 : // Adding in FaultFrac:
2234 : // UACoilExternal = FaultFrac * [UAFouled * (1+splitRatio) / splitRatio] + (1-FaultFrac) * UACoilExternal
2235 : // UACoilInternal = FaultFrac * [UAFouled * splitRatio] + (1-FaultFrac) * UACoilInternal
2236 :
2237 1309 : Real64 splitRatio = state.dataWaterCoils->WaterCoil(CoilNum).UACoilInternal / state.dataWaterCoils->WaterCoil(CoilNum).UACoilExternal;
2238 :
2239 1309 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilExternal =
2240 2618 : 1.0 / ((FaultFrac * splitRatio) / ((1 + splitRatio) * fouling.UAFouled) +
2241 1309 : (1 - FaultFrac) / state.dataWaterCoils->WaterCoil(CoilNum).UACoilExternal);
2242 :
2243 : // WaterCoil(CoilNum).UACoilInternal = 1.0 /
2244 : //( FaultFrac / ((1 + splitRatio) * fouling.UAFouled) +
2245 : //(1-FaultFrac) / WaterCoil(CoilNum).UACoilInternal);
2246 :
2247 1309 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilInternal = splitRatio * state.dataWaterCoils->WaterCoil(CoilNum).UACoilExternal;
2248 : }
2249 :
2250 : // Do not allow improving coil performance
2251 1309 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilExternal =
2252 1309 : min(state.dataWaterCoils->WaterCoil(CoilNum).UACoilExternal, state.dataWaterCoils->WaterCoil(CoilNum).OriginalUACoilExternal);
2253 1309 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilInternal =
2254 1309 : min(state.dataWaterCoils->WaterCoil(CoilNum).UACoilInternal, state.dataWaterCoils->WaterCoil(CoilNum).OriginalUACoilInternal);
2255 :
2256 : // Only for reporting purposes
2257 1309 : state.dataWaterCoils->WaterCoil(CoilNum).FaultyCoilFoulingFactor =
2258 2618 : (1.0 / state.dataWaterCoils->WaterCoil(CoilNum).UACoilExternal) -
2259 2618 : (1.0 / state.dataWaterCoils->WaterCoil(CoilNum).OriginalUACoilExternal) +
2260 2618 : (1.0 / state.dataWaterCoils->WaterCoil(CoilNum).UACoilInternal) -
2261 1309 : (1.0 / state.dataWaterCoils->WaterCoil(CoilNum).OriginalUACoilInternal);
2262 : } else {
2263 22033677 : state.dataWaterCoils->WaterCoil(CoilNum).FaultyCoilFoulingFactor = 0;
2264 : }
2265 :
2266 22034986 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilTotal =
2267 22034986 : 1.0 / (1.0 / state.dataWaterCoils->WaterCoil(CoilNum).UACoilExternal + 1.0 / state.dataWaterCoils->WaterCoil(CoilNum).UACoilInternal);
2268 :
2269 22034986 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilInternalPerUnitArea =
2270 22034986 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilInternal / state.dataWaterCoils->WaterCoil(CoilNum).TotCoilOutsideSurfArea;
2271 22034986 : state.dataWaterCoils->WaterCoil(CoilNum).UAWetExtPerUnitArea =
2272 22034986 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilExternal / state.dataWaterCoils->WaterCoil(CoilNum).TotCoilOutsideSurfArea;
2273 22034986 : state.dataWaterCoils->WaterCoil(CoilNum).UADryExtPerUnitArea = state.dataWaterCoils->WaterCoil(CoilNum).UAWetExtPerUnitArea;
2274 : }
2275 137538575 : }
2276 :
2277 3100 : void SizeWaterCoil(EnergyPlusData &state, int const CoilNum)
2278 : {
2279 :
2280 : // SUBROUTINE INFORMATION:
2281 : // AUTHOR Fred Buhl
2282 : // DATE WRITTEN November 2001
2283 : // MODIFIED August 2013 Daeho Kang, add component sizing table entries
2284 : // RE-ENGINEERED na
2285 :
2286 : // PURPOSE OF THIS SUBROUTINE:
2287 : // This subroutine is for sizing Water Coil Components for which flow rates and UAs have not been
2288 : // specified in the input.
2289 :
2290 : // METHODOLOGY EMPLOYED:
2291 : // Obtains flow rates from the zone or system sizing arrays and plant sizing data. UAs are
2292 : // calculated by numerically inverting the individual coil calculation routines.
2293 :
2294 : // Using/Aliasing
2295 : using namespace DataSizing;
2296 : using PlantUtilities::RegisterPlantCompDesignFlow;
2297 :
2298 : // SUBROUTINE PARAMETER DEFINITIONS:
2299 : static constexpr std::string_view RoutineName("SizeWaterCoil");
2300 :
2301 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
2302 : Real64 rho;
2303 3100 : int FieldNum = 2; // IDD numeric field number where input field description is found
2304 6200 : std::string CompType; // component type
2305 : int SizingType; // type of sizing to perform
2306 6200 : std::string SizingString; // input field sizing description (e.g., Nominal Capacity)
2307 3100 : bool bPRINT = true; // TRUE if sizing is reported to output (eio)
2308 : Real64 TempSize; // autosized value
2309 : Real64 DesCoilWaterInTempSaved; // coil water inlet temp used for error checking UA sizing
2310 3100 : Real64 DesCoilInletWaterTempUsed(0.0); // coil design inlet water temp for UA sizing only
2311 : Real64 Cp;
2312 3100 : bool NomCapUserInp = false; // flag for whether user has onput a nominal heating capacity
2313 :
2314 3100 : bool ErrorsFound = false;
2315 3100 : bool LoopErrorsFound = false;
2316 3100 : int PltSizCoolNum = 0;
2317 3100 : int PltSizHeatNum = 0;
2318 3100 : Real64 DesCoilAirFlow = 0.0;
2319 3100 : Real64 DesCoilExitTemp = 0.0;
2320 3100 : Real64 CpAirStd = PsyCpAirFnW(0.0);
2321 6200 : std::string CompName = state.dataWaterCoils->WaterCoil(CoilNum).Name;
2322 :
2323 3100 : auto &ZoneEqSizing(state.dataSize->ZoneEqSizing);
2324 3100 : auto &OASysEqSizing(state.dataSize->OASysEqSizing);
2325 :
2326 : // cooling coils
2327 8897 : if (((state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterCooling) ||
2328 3646 : (state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterDetailedFlatCooling)) &&
2329 546 : state.dataWaterCoils->WaterCoil(CoilNum).RequestingAutoSize) {
2330 : // find the appropriate Plant Sizing object
2331 1772 : PltSizCoolNum = PlantUtilities::MyPlantSizingIndex(state,
2332 : "chilled water coil",
2333 443 : state.dataWaterCoils->WaterCoil(CoilNum).Name,
2334 443 : state.dataWaterCoils->WaterCoil(CoilNum).WaterInletNodeNum,
2335 443 : state.dataWaterCoils->WaterCoil(CoilNum).WaterOutletNodeNum,
2336 : LoopErrorsFound);
2337 : }
2338 :
2339 5797 : if (((state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterCooling) ||
2340 2697 : (state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterDetailedFlatCooling))) { // 'Cooling'
2341 :
2342 546 : if (state.dataWaterCoils->WaterCoil(CoilNum).UseDesignWaterDeltaTemp) {
2343 28 : state.dataSize->DataWaterCoilSizCoolDeltaT = state.dataWaterCoils->WaterCoil(CoilNum).DesignWaterDeltaTemp;
2344 : } else {
2345 518 : if (PltSizCoolNum > 0) {
2346 415 : state.dataSize->DataWaterCoilSizCoolDeltaT = state.dataSize->PlantSizData(PltSizCoolNum).DeltaT;
2347 : }
2348 : }
2349 :
2350 546 : if (PltSizCoolNum > 0) {
2351 :
2352 443 : state.dataSize->DataPltSizCoolNum = PltSizCoolNum;
2353 443 : state.dataSize->DataWaterLoopNum = state.dataWaterCoils->WaterCoil(CoilNum).WaterPlantLoc.loopNum;
2354 :
2355 443 : if (state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilModel == CoilModel::CoolingDetailed) { // 'DETAILED FLAT FIN'
2356 62 : CompType = cAllCoilTypes(Coil_CoolingWaterDetailed); // Coil:Cooling:Water:DetailedGeometry
2357 : } else {
2358 381 : CompType = cAllCoilTypes(Coil_CoolingWater); // Coil:Cooling:Water
2359 : }
2360 :
2361 443 : bPRINT = false; // do not print this sizing request since the autosized value is needed and this input may not be autosized (we should
2362 : // print this!)
2363 443 : if (state.dataWaterCoils->WaterCoil(CoilNum).DesAirVolFlowRate == state.dataSize->DataFlowUsedForSizing) {
2364 84 : TempSize = state.dataWaterCoils->WaterCoil(CoilNum).DesAirVolFlowRate; // represents parent object has hard-sized airflow
2365 : } else {
2366 359 : TempSize = AutoSize; // get the autosized air volume flow rate for use in other calculations
2367 : }
2368 :
2369 443 : bool errorsFound = false;
2370 886 : CoolingAirFlowSizer sizingCoolingAirFlow;
2371 443 : CompName = state.dataWaterCoils->WaterCoil(CoilNum).Name;
2372 443 : sizingCoolingAirFlow.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
2373 443 : Real64 autoSizedValue = sizingCoolingAirFlow.size(state, TempSize, errorsFound);
2374 443 : state.dataWaterCoils->WaterCoil(CoilNum).InletAirMassFlowRate =
2375 443 : state.dataEnvrn->StdRhoAir * autoSizedValue; // inlet air mass flow rate is the autosized value
2376 :
2377 : // Check if the air volume flow rate is defined in parent HVAC equipment and set water coil design air volume flow rate accordingly
2378 443 : if (state.dataSize->CurZoneEqNum > 0) {
2379 173 : if (ZoneEqSizing(state.dataSize->CurZoneEqNum).DesignSizeFromParent &&
2380 81 : state.dataWaterCoils->WaterCoil(CoilNum).DesAirVolFlowRate == autoSizedValue) {
2381 80 : state.dataSize->DataAirFlowUsedForSizing = ZoneEqSizing(state.dataSize->CurZoneEqNum).AirVolFlow;
2382 80 : state.dataSize->DataFlowUsedForSizing = ZoneEqSizing(state.dataSize->CurZoneEqNum).AirVolFlow;
2383 80 : state.dataWaterCoils->WaterCoil(CoilNum).DesAirVolFlowRate = AutoSize; // represents water coil being autosized
2384 : } else {
2385 12 : state.dataSize->DataAirFlowUsedForSizing =
2386 : autoSizedValue; // many autosized inputs use the design (autosized) air volume flow rate, save this value
2387 12 : state.dataSize->DataFlowUsedForSizing = autoSizedValue;
2388 : }
2389 : } else {
2390 351 : state.dataSize->DataAirFlowUsedForSizing =
2391 : autoSizedValue; // many autosized inputs use the design (autosized) air volume flow rate, save this value
2392 351 : state.dataSize->DataFlowUsedForSizing = autoSizedValue;
2393 : }
2394 :
2395 443 : if (state.dataSize->CurSysNum > 0 && state.dataSize->CurOASysNum == 0) {
2396 323 : Real64 DesCoilExitHumRat(0.0); // fix coil sizing inconsistency
2397 323 : DataSizing::GetCoilDesFlowT(state, state.dataSize->CurSysNum, CpAirStd, DesCoilAirFlow, DesCoilExitTemp, DesCoilExitHumRat);
2398 323 : state.dataSize->DataAirFlowUsedForSizing = DesCoilAirFlow;
2399 323 : state.dataSize->DataFlowUsedForSizing = DesCoilAirFlow;
2400 323 : state.dataSize->DataDesOutletAirTemp = DesCoilExitTemp;
2401 323 : state.dataSize->DataDesOutletAirHumRat = DesCoilExitHumRat; // need to test for dry coil but inlet conditions not yet known
2402 : }
2403 :
2404 : // calculate pre-sizing data needed for specific functions (e.g., CoolingWaterDesAirInletTempSizing needs HRin and air flow)
2405 : // these will be calculated again after other parameters are known
2406 443 : if (state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilModel == CoilModel::CoolingDetailed) { // 'DETAILED FLAT FIN'
2407 62 : TempSize = AutoSize; // coil report
2408 : } else {
2409 381 : TempSize = state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirHumRat; // preserve input if entered
2410 : }
2411 886 : CoolingWaterDesAirInletHumRatSizer sizerCWDesInHumRat;
2412 443 : sizerCWDesInHumRat.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
2413 443 : state.dataSize->DataDesInletAirHumRat = sizerCWDesInHumRat.size(state, TempSize, ErrorsFound);
2414 :
2415 443 : TempSize = AutoSize;
2416 886 : CoolingCapacitySizer sizerCoolingCapacity;
2417 443 : sizerCoolingCapacity.overrideSizingString(SizingString);
2418 443 : sizerCoolingCapacity.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
2419 443 : state.dataSize->DataCapacityUsedForSizing = sizerCoolingCapacity.size(state, TempSize, ErrorsFound);
2420 443 : TempSize = state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterVolFlowRate;
2421 886 : CoolingWaterflowSizer sizerCWWaterflow;
2422 443 : sizerCWWaterflow.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
2423 443 : Real64 autoSizedCWFlow = sizerCWWaterflow.size(state, TempSize, ErrorsFound);
2424 : // Check if the water flow rate is defined in parent HVAC equipment and set water coil design water flow rate accordingly
2425 443 : if (state.dataSize->CurZoneEqNum > 0) {
2426 92 : if (ZoneEqSizing(state.dataSize->CurZoneEqNum).DesignSizeFromParent) {
2427 81 : state.dataSize->DataWaterFlowUsedForSizing = ZoneEqSizing(state.dataSize->CurZoneEqNum).MaxCWVolFlow;
2428 : } else {
2429 11 : state.dataSize->DataWaterFlowUsedForSizing = autoSizedCWFlow;
2430 : }
2431 : } else {
2432 351 : state.dataSize->DataWaterFlowUsedForSizing = autoSizedCWFlow;
2433 : }
2434 : // end pre-sizing data calculations
2435 :
2436 443 : if (state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilModel == CoilModel::CoolingDetailed) { // 'DETAILED FLAT FIN'
2437 62 : bPRINT = false; // do not print this sizing request since this coil does not have a design inlet air temp input field (we
2438 : // should print this!)
2439 62 : TempSize = AutoSize; // not an input for this model
2440 62 : SizingString.clear(); // doesn't matter
2441 : } else {
2442 381 : FieldNum = 4; // N4 , \field Design Inlet Air Temperature
2443 381 : bPRINT = true;
2444 381 : TempSize = state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirTemp; // preserve input if entered
2445 381 : SizingString = state.dataWaterCoils->WaterCoilNumericFields(CoilNum).FieldNames(FieldNum) + " [C]";
2446 : }
2447 :
2448 886 : CoolingWaterDesAirInletTempSizer sizerCWDesInletAirTemp;
2449 443 : sizerCWDesInletAirTemp.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
2450 443 : state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirTemp = sizerCWDesInletAirTemp.size(state, TempSize, ErrorsFound);
2451 443 : state.dataSize->DataDesInletAirTemp = state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirTemp;
2452 :
2453 443 : if (state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilModel == CoilModel::CoolingDetailed) { // 'DETAILED FLAT FIN'
2454 62 : bPRINT = false; // no field for detailed water coil, should print to eio anyway
2455 62 : TempSize = AutoSize; // coil report
2456 62 : SizingString.clear(); // doesn't matter
2457 : } else {
2458 381 : FieldNum = 3; // N3 , \field Design Inlet Water Temperature
2459 381 : bPRINT = true;
2460 381 : TempSize = state.dataWaterCoils->WaterCoil(CoilNum).DesInletWaterTemp; // preserve input if entered
2461 381 : SizingString = state.dataWaterCoils->WaterCoilNumericFields(CoilNum).FieldNames(FieldNum) + " [C]";
2462 : }
2463 886 : CoolingWaterDesWaterInletTempSizer sizerCWDesWaterInTemp;
2464 443 : sizerCWDesWaterInTemp.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
2465 443 : state.dataWaterCoils->WaterCoil(CoilNum).DesInletWaterTemp = sizerCWDesWaterInTemp.size(state, TempSize, ErrorsFound);
2466 :
2467 563 : if ((state.dataWaterCoils->WaterCoil(CoilNum).DesInletWaterTemp > state.dataSize->DataDesOutletAirTemp) &&
2468 120 : state.dataSize->DataDesOutletAirTemp > 0.0) {
2469 0 : ShowWarningError(state, "Invalid design inlet water temperature for " + std::string{CompType} + " = " + std::string{CompName});
2470 0 : ShowContinueError(state,
2471 0 : format("...design inlet water temperature = {:.3R} C", state.dataWaterCoils->WaterCoil(CoilNum).DesInletWaterTemp));
2472 0 : ShowContinueError(state, format("...design outlet air temperature = {:.3R} C", state.dataSize->DataDesOutletAirTemp));
2473 0 : ShowContinueError(state, "...design inlet water temperature should be less than the design outlet air temperature");
2474 0 : ShowContinueError(state, "...design inlet water temperature is set to the design outlet air temperature minus 5.0C");
2475 0 : state.dataWaterCoils->WaterCoil(CoilNum).DesInletWaterTemp = state.dataSize->DataDesOutletAirTemp - 5.0;
2476 : }
2477 :
2478 443 : if (state.dataSize->CurZoneEqNum > 0) { // zone equipment use air inlet humrat to calculate design outlet air temperature
2479 92 : if (state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilModel == CoilModel::CoolingDetailed) { // 'DETAILED FLAT FIN'
2480 0 : bPRINT = false; // no field for detailed water coil, should print to eio anyway
2481 0 : TempSize = AutoSize; // coil report
2482 : } else {
2483 92 : bPRINT = true;
2484 92 : TempSize = state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirHumRat; // preserve input if entered
2485 : }
2486 92 : sizerCWDesInHumRat.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
2487 92 : state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirHumRat = sizerCWDesInHumRat.size(state, TempSize, ErrorsFound);
2488 : }
2489 :
2490 443 : if (state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilModel == CoilModel::CoolingDetailed) { // 'DETAILED FLAT FIN'
2491 62 : bPRINT = false; // no field for detailed water coil, should print to eio anyway
2492 62 : TempSize = AutoSize; // coil report
2493 62 : SizingString.clear(); // doesn't matter
2494 : } else {
2495 381 : FieldNum = 5; // N5 , \field Design Outlet Air Temperature
2496 381 : bPRINT = true;
2497 381 : TempSize = state.dataWaterCoils->WaterCoil(CoilNum).DesOutletAirTemp; // preserve input if entered
2498 381 : SizingString = state.dataWaterCoils->WaterCoilNumericFields(CoilNum).FieldNames(FieldNum) + " [C]";
2499 : }
2500 :
2501 443 : state.dataSize->DataDesInletWaterTemp = state.dataWaterCoils->WaterCoil(CoilNum).DesInletWaterTemp; // used for warning messages
2502 886 : CoolingWaterDesAirOutletTempSizer sizerCWDesAirOutTemp;
2503 443 : sizerCWDesAirOutTemp.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
2504 443 : state.dataWaterCoils->WaterCoil(CoilNum).DesOutletAirTemp = sizerCWDesAirOutTemp.size(state, TempSize, ErrorsFound);
2505 443 : state.dataSize->DataDesOutletAirTemp = state.dataWaterCoils->WaterCoil(CoilNum).DesOutletAirTemp;
2506 :
2507 443 : if (state.dataSize->CurSysNum > 0) { // This call can be deleted at a future time and remove the if ( CurZoneEqNum > 0 ) check above. This
2508 : // will change the order of the eio file.
2509 351 : if (state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilModel == CoilModel::CoolingDetailed) { // 'DETAILED FLAT FIN'
2510 62 : bPRINT = false; // no field for detailed water coil, should print this to eio anyway
2511 62 : TempSize = AutoSize; // coil report
2512 : } else {
2513 289 : bPRINT = true;
2514 289 : TempSize = state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirHumRat;
2515 : }
2516 351 : sizerCWDesInHumRat.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
2517 351 : state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirHumRat = sizerCWDesInHumRat.size(state, TempSize, ErrorsFound);
2518 : }
2519 :
2520 443 : if (state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilModel == CoilModel::CoolingDetailed) { // 'DETAILED FLAT FIN'
2521 62 : bPRINT = false; // no field for detailed water coil, should print this to eio anyway
2522 62 : TempSize = AutoSize; // coil report
2523 : } else {
2524 381 : bPRINT = true;
2525 381 : TempSize = state.dataWaterCoils->WaterCoil(CoilNum).DesOutletAirHumRat; // preserve input if entered
2526 : }
2527 886 : CoolingWaterDesAirOutletHumRatSizer sizerCWDesOutHumRat;
2528 443 : sizerCWDesOutHumRat.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
2529 443 : state.dataWaterCoils->WaterCoil(CoilNum).DesOutletAirHumRat = sizerCWDesOutHumRat.size(state, TempSize, ErrorsFound);
2530 443 : state.dataSize->DataDesOutletAirHumRat = state.dataWaterCoils->WaterCoil(CoilNum).DesOutletAirHumRat;
2531 :
2532 443 : TempSize = AutoSize;
2533 443 : bPRINT = true;
2534 443 : if (state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterVolFlowRate != AutoSize) bPRINT = false;
2535 443 : if (state.dataSize->CurSysNum == 0) bPRINT = false;
2536 443 : SizingString = "Design Coil Load [W]"; // there is no input field for this value and this is not the rated capacity (we should
2537 : // always print this!)
2538 : // air inlet/outlet conditions should be known. Don't include fan heat in capacity calculation.
2539 443 : state.dataSize->DataDesAccountForFanHeat = false;
2540 886 : CoolingCapacitySizer sizerCoolingCapacity2;
2541 443 : sizerCoolingCapacity2.overrideSizingString(SizingString);
2542 443 : sizerCoolingCapacity2.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
2543 443 : state.dataWaterCoils->WaterCoil(CoilNum).DesWaterCoolingCoilRate = sizerCoolingCapacity2.size(state, TempSize, ErrorsFound);
2544 443 : state.dataWaterCoils->WaterCoil(CoilNum).InletAirMassFlowRate =
2545 443 : state.dataEnvrn->StdRhoAir * state.dataSize->DataFlowUsedForSizing; // inlet air mass flow rate is the autosized value
2546 443 : state.dataSize->DataCapacityUsedForSizing = state.dataWaterCoils->WaterCoil(CoilNum).DesWaterCoolingCoilRate;
2547 :
2548 : // Why isn't the water volume flow rate based on the user inputs for inlet/outlet air/water temps? Water volume flow rate is
2549 : // always based on autosized inputs.
2550 443 : bPRINT = true;
2551 443 : TempSize = state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterVolFlowRate;
2552 443 : sizerCWWaterflow.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
2553 443 : state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterVolFlowRate = sizerCWWaterflow.size(state, TempSize, ErrorsFound);
2554 443 : state.dataSize->DataWaterFlowUsedForSizing = state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterVolFlowRate;
2555 :
2556 443 : if (state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilModel == CoilModel::CoolingDetailed) { // 'DETAILED FLAT FIN'
2557 62 : bPRINT = false; // do not print this sizing request since this coil does not have a design air flow rate input field (we
2558 : // should print this!)
2559 : } else {
2560 381 : bPRINT = true;
2561 : }
2562 443 : TempSize = state.dataWaterCoils->WaterCoil(CoilNum).DesAirVolFlowRate;
2563 886 : CoolingAirFlowSizer sizingCoolingAirFlow2;
2564 886 : std::string stringOverride = "Design Air Flow Rate [m3/s]";
2565 443 : if (state.dataGlobal->isEpJSON) stringOverride = "design_air_flow_rate [m3/s]";
2566 443 : sizingCoolingAirFlow2.overrideSizingString(stringOverride);
2567 : // sizingCoolingAirFlow2.setHVACSizingIndexData(FanCoil(FanCoilNum).HVACSizingIndex);
2568 443 : sizingCoolingAirFlow2.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
2569 443 : state.dataWaterCoils->WaterCoil(CoilNum).DesAirVolFlowRate = sizingCoolingAirFlow2.size(state, TempSize, errorsFound);
2570 443 : state.dataWaterCoils->WaterCoil(CoilNum).DesAirMassFlowRate =
2571 443 : state.dataWaterCoils->WaterCoil(CoilNum).DesAirVolFlowRate * state.dataEnvrn->StdRhoAir;
2572 :
2573 443 : if (state.dataWaterCoils->WaterCoil(CoilNum).DesAirVolFlowRate <= 0.0) {
2574 0 : state.dataWaterCoils->WaterCoil(CoilNum).DesAirVolFlowRate = 0.0;
2575 0 : ShowWarningError(state, "The design air flow rate is zero for " + std::string{CompType} + " = " + std::string{CompName});
2576 0 : ShowContinueError(state, "The autosize value for max air volume flow rate is zero");
2577 : }
2578 :
2579 443 : if (state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilModel == CoilModel::CoolingDetailed) {
2580 :
2581 62 : FieldNum = 16; // N16, \field Number of Tubes per Row
2582 62 : bPRINT = true;
2583 62 : SizingString = state.dataWaterCoils->WaterCoilNumericFields(CoilNum).FieldNames(FieldNum);
2584 : // Auto size detailed cooling coil number of tubes per row = int( 13750.0 * WaterCoil( CoilNum ).MaxWaterVolFlowRate ) + 1
2585 62 : state.dataSize->DataFlowUsedForSizing = state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterVolFlowRate;
2586 62 : TempSize = float(state.dataWaterCoils->WaterCoil(CoilNum).NumOfTubesPerRow);
2587 124 : CoolingWaterNumofTubesPerRowSizer sizerCWNumofTubesPerRow;
2588 62 : sizerCWNumofTubesPerRow.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
2589 62 : state.dataWaterCoils->WaterCoil(CoilNum).NumOfTubesPerRow = sizerCWNumofTubesPerRow.size(state, TempSize, ErrorsFound);
2590 :
2591 : // Auto size water coil fin diameter = 0.335 * WaterCoil( CoilNum ).InletAirMassFlowRate
2592 62 : state.dataSize->DataConstantUsedForSizing = state.dataWaterCoils->WaterCoil(CoilNum).InletAirMassFlowRate;
2593 62 : state.dataSize->DataFractionUsedForSizing = 0.335;
2594 62 : TempSize = state.dataWaterCoils->WaterCoil(CoilNum).FinDiam;
2595 :
2596 124 : AutoCalculateSizer sizerFinDiameter;
2597 124 : std::string stringOverride = "Fin Diameter [m]";
2598 62 : if (state.dataGlobal->isEpJSON) stringOverride = "fin_diameter [m]";
2599 62 : sizerFinDiameter.overrideSizingString(stringOverride);
2600 62 : sizerFinDiameter.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
2601 62 : state.dataWaterCoils->WaterCoil(CoilNum).FinDiam = sizerFinDiameter.size(state, TempSize, ErrorsFound);
2602 :
2603 : // Auto size water coil minimum airflow area = 0.44 * WaterCoil( CoilNum ).InletAirMassFlowRate
2604 62 : state.dataSize->DataConstantUsedForSizing = state.dataWaterCoils->WaterCoil(CoilNum).InletAirMassFlowRate;
2605 62 : state.dataSize->DataFractionUsedForSizing = 0.44;
2606 62 : TempSize = state.dataWaterCoils->WaterCoil(CoilNum).MinAirFlowArea;
2607 :
2608 124 : AutoCalculateSizer sizerMinAirFlowArea;
2609 62 : stringOverride = "Minimum Airflow Area [m2]";
2610 62 : if (state.dataGlobal->isEpJSON) stringOverride = "minimum_airflow_area [m2]";
2611 62 : sizerMinAirFlowArea.overrideSizingString(stringOverride);
2612 62 : sizerMinAirFlowArea.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
2613 62 : state.dataWaterCoils->WaterCoil(CoilNum).MinAirFlowArea = sizerMinAirFlowArea.size(state, TempSize, ErrorsFound);
2614 :
2615 62 : if (state.dataWaterCoils->WaterCoil(CoilNum).MinAirFlowArea <= 0.0) {
2616 0 : ShowSevereError(state, "Coil:Cooling:Water:DetailedGeometry: \"" + state.dataWaterCoils->WaterCoil(CoilNum).Name + "\"");
2617 0 : ShowContinueError(state,
2618 0 : format("Coil Minimum Airflow Area must be greater than 0. Coil area = {:.6T}",
2619 0 : state.dataWaterCoils->WaterCoil(CoilNum).MinAirFlowArea));
2620 0 : ErrorsFound = true;
2621 : }
2622 :
2623 : // Auto size water coil finned surface area = 78.5 * WaterCoil( CoilNum ).InletAirMassFlowRate
2624 62 : state.dataSize->DataConstantUsedForSizing =
2625 62 : state.dataWaterCoils->WaterCoil(CoilNum)
2626 62 : .InletAirMassFlowRate; // actual autosized air mass flow rate, not calculated from user input
2627 62 : state.dataSize->DataFractionUsedForSizing = 78.5;
2628 62 : TempSize = state.dataWaterCoils->WaterCoil(CoilNum).FinSurfArea;
2629 :
2630 124 : AutoCalculateSizer sizerFinSurfaceArea;
2631 62 : stringOverride = "Fin Surface Area [m2]";
2632 62 : if (state.dataGlobal->isEpJSON) stringOverride = "fin_surface_area [m2]";
2633 62 : sizerFinSurfaceArea.overrideSizingString(stringOverride);
2634 62 : sizerFinSurfaceArea.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
2635 62 : state.dataWaterCoils->WaterCoil(CoilNum).FinSurfArea = sizerFinSurfaceArea.size(state, TempSize, ErrorsFound);
2636 :
2637 : // Auto size water coil total tube inside surface area = 4.4 * WaterCoil( CoilNum ).TubeInsideDiam * WaterCoil( CoilNum
2638 : // ).NumOfTubeRows * WaterCoil( CoilNum ).NumOfTubesPerRow
2639 186 : state.dataSize->DataConstantUsedForSizing = state.dataWaterCoils->WaterCoil(CoilNum).TubeInsideDiam *
2640 124 : state.dataWaterCoils->WaterCoil(CoilNum).NumOfTubeRows *
2641 62 : state.dataWaterCoils->WaterCoil(CoilNum).NumOfTubesPerRow;
2642 62 : state.dataSize->DataFractionUsedForSizing = 4.4;
2643 62 : TempSize = state.dataWaterCoils->WaterCoil(CoilNum).TotTubeInsideArea;
2644 :
2645 124 : AutoCalculateSizer sizerTubeInsideArea;
2646 62 : stringOverride = "Total Tube Inside Area [m2]";
2647 62 : if (state.dataGlobal->isEpJSON) stringOverride = "total_tube_inside_area [m2]";
2648 62 : sizerTubeInsideArea.overrideSizingString(stringOverride);
2649 62 : sizerTubeInsideArea.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
2650 62 : state.dataWaterCoils->WaterCoil(CoilNum).TotTubeInsideArea = sizerTubeInsideArea.size(state, TempSize, ErrorsFound);
2651 :
2652 : // Auto size water coil total tube outside surface area = 4.1 * WaterCoil( CoilNum ).TubeOutsideDiam * WaterCoil( CoilNum
2653 : // ).NumOfTubeRows * WaterCoil( CoilNum ).NumOfTubesPerRow
2654 186 : state.dataSize->DataConstantUsedForSizing = state.dataWaterCoils->WaterCoil(CoilNum).TubeOutsideDiam *
2655 124 : state.dataWaterCoils->WaterCoil(CoilNum).NumOfTubeRows *
2656 62 : state.dataWaterCoils->WaterCoil(CoilNum).NumOfTubesPerRow;
2657 62 : state.dataSize->DataFractionUsedForSizing = 4.1;
2658 62 : TempSize = state.dataWaterCoils->WaterCoil(CoilNum).TubeOutsideSurfArea;
2659 :
2660 124 : AutoCalculateSizer sizerTubeOutsideArea;
2661 62 : stringOverride = "Tube Outside Surface Area [m2]";
2662 62 : if (state.dataGlobal->isEpJSON) stringOverride = "tube_outside_surface_area [m2]";
2663 62 : sizerTubeOutsideArea.overrideSizingString(stringOverride);
2664 62 : sizerTubeOutsideArea.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
2665 62 : state.dataWaterCoils->WaterCoil(CoilNum).TubeOutsideSurfArea = sizerTubeOutsideArea.size(state, TempSize, ErrorsFound);
2666 :
2667 62 : if ((state.dataWaterCoils->WaterCoil(CoilNum).FinSurfArea + state.dataWaterCoils->WaterCoil(CoilNum).TubeOutsideSurfArea) <= 0.0) {
2668 0 : ShowSevereError(state, "Coil:Cooling:Water:DetailedGeometry: \"" + state.dataWaterCoils->WaterCoil(CoilNum).Name + "\"");
2669 0 : ShowContinueError(
2670 : state,
2671 0 : format(
2672 : "Coil Fin Surface Area plus Coil Tube Outside Surface Area must be greater than 0. Total surface area = {:.6T}",
2673 0 : (state.dataWaterCoils->WaterCoil(CoilNum).FinSurfArea + state.dataWaterCoils->WaterCoil(CoilNum).TubeOutsideSurfArea)));
2674 0 : ErrorsFound = true;
2675 : }
2676 :
2677 : // Auto size water coil coil depth = WaterCoil( CoilNum ).TubeDepthSpacing * WaterCoil( CoilNum ).NumOfTubeRows
2678 62 : state.dataSize->DataConstantUsedForSizing = state.dataWaterCoils->WaterCoil(CoilNum).TubeDepthSpacing;
2679 62 : state.dataSize->DataFractionUsedForSizing = state.dataWaterCoils->WaterCoil(CoilNum).NumOfTubeRows;
2680 62 : TempSize = state.dataWaterCoils->WaterCoil(CoilNum).CoilDepth;
2681 :
2682 124 : AutoCalculateSizer sizerCoilDepth;
2683 62 : stringOverride = "Coil Depth [m]";
2684 62 : if (state.dataGlobal->isEpJSON) stringOverride = "coil_depth [m]";
2685 62 : sizerCoilDepth.overrideSizingString(stringOverride);
2686 62 : sizerCoilDepth.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
2687 62 : state.dataWaterCoils->WaterCoil(CoilNum).CoilDepth = sizerCoilDepth.size(state, TempSize, ErrorsFound);
2688 : }
2689 443 : state.dataSize->DataPltSizCoolNum = 0; // reset all globals to 0 to ensure correct sizing for other child components
2690 443 : state.dataSize->DataWaterLoopNum = 0;
2691 443 : state.dataSize->DataConstantUsedForSizing = 0.0;
2692 443 : state.dataSize->DataFractionUsedForSizing = 0.0;
2693 443 : state.dataSize->DataAirFlowUsedForSizing = 0.0;
2694 443 : state.dataSize->DataFlowUsedForSizing = 0.0;
2695 443 : state.dataSize->DataWaterFlowUsedForSizing = 0.0;
2696 443 : state.dataSize->DataCapacityUsedForSizing = 0.0;
2697 443 : state.dataSize->DataDesInletAirTemp = 0.0;
2698 443 : state.dataSize->DataDesOutletAirTemp = 0.0;
2699 443 : state.dataSize->DataDesOutletAirHumRat = 0.0;
2700 443 : state.dataSize->DataDesInletAirHumRat = 0.0;
2701 443 : state.dataSize->DataDesInletWaterTemp = 0.0;
2702 443 : state.dataSize->DataWaterCoilSizCoolDeltaT = 0.0;
2703 443 : state.dataSize->DataDesAccountForFanHeat = true;
2704 : } else {
2705 : // If there is no cooling Plant Sizing object and autosizing was requested, issue fatal error message
2706 103 : if (state.dataWaterCoils->WaterCoil(CoilNum).RequestingAutoSize) {
2707 0 : ShowSevereError(state, "Autosizing of water coil requires a cooling loop Sizing:Plant object");
2708 0 : ShowContinueError(state, "Occurs in water coil object= " + state.dataWaterCoils->WaterCoil(CoilNum).Name);
2709 0 : ErrorsFound = true;
2710 : }
2711 : }
2712 : //} // end of cooling Plant Sizing existence IF - ELSE
2713 : } // end cooling coil IF
2714 :
2715 : // if this is a heating coil
2716 5654 : if (state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterSimpleHeating &&
2717 2554 : state.dataWaterCoils->WaterCoil(CoilNum).RequestingAutoSize) {
2718 : // find the appropriate heating Plant Sizing object
2719 8992 : PltSizHeatNum = PlantUtilities::MyPlantSizingIndex(state,
2720 : "hot water coil",
2721 2248 : state.dataWaterCoils->WaterCoil(CoilNum).Name,
2722 2248 : state.dataWaterCoils->WaterCoil(CoilNum).WaterInletNodeNum,
2723 2248 : state.dataWaterCoils->WaterCoil(CoilNum).WaterOutletNodeNum,
2724 : LoopErrorsFound);
2725 : }
2726 :
2727 3100 : if (state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterSimpleHeating) {
2728 :
2729 2554 : if (state.dataWaterCoils->WaterCoil(CoilNum).UseDesignWaterDeltaTemp) {
2730 : // use water design deltaT specified in the heating water coils
2731 93 : state.dataSize->DataWaterCoilSizHeatDeltaT = state.dataWaterCoils->WaterCoil(CoilNum).DesignWaterDeltaTemp;
2732 : } else {
2733 2461 : if (PltSizHeatNum > 0) {
2734 2155 : state.dataSize->DataWaterCoilSizHeatDeltaT = state.dataSize->PlantSizData(PltSizHeatNum).DeltaT;
2735 : }
2736 : }
2737 :
2738 2554 : if (PltSizHeatNum > 0) {
2739 :
2740 2248 : state.dataSize->DataPltSizHeatNum = PltSizHeatNum;
2741 2248 : state.dataSize->DataWaterLoopNum = state.dataWaterCoils->WaterCoil(CoilNum).WaterPlantLoc.loopNum;
2742 4496 : rho = GetDensityGlycol(state,
2743 2248 : state.dataPlnt->PlantLoop(state.dataWaterCoils->WaterCoil(CoilNum).WaterPlantLoc.loopNum).FluidName,
2744 : DataGlobalConstants::HWInitConvTemp,
2745 2248 : state.dataPlnt->PlantLoop(state.dataWaterCoils->WaterCoil(CoilNum).WaterPlantLoc.loopNum).FluidIndex,
2746 : RoutineName);
2747 4496 : Cp = GetSpecificHeatGlycol(state,
2748 2248 : state.dataPlnt->PlantLoop(state.dataSize->DataWaterLoopNum).FluidName,
2749 : DataGlobalConstants::HWInitConvTemp,
2750 2248 : state.dataPlnt->PlantLoop(state.dataSize->DataWaterLoopNum).FluidIndex,
2751 : RoutineName);
2752 2248 : if (state.dataWaterCoils->WaterCoil(CoilNum).DesTotWaterCoilLoad > 0.0) {
2753 35 : NomCapUserInp = true;
2754 2213 : } else if (state.dataSize->CurSysNum > 0 && state.dataSize->CurSysNum <= state.dataHVACGlobal->NumPrimaryAirSys) {
2755 370 : if (state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).HeatingCapMethod == CapacityPerFloorArea) {
2756 0 : NomCapUserInp = true;
2757 739 : } else if (state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).HeatingCapMethod == HeatingDesignCapacity &&
2758 369 : state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).HeatingTotalCapacity > 0.0) {
2759 0 : NomCapUserInp = true;
2760 : }
2761 : } else {
2762 1843 : NomCapUserInp = false;
2763 : }
2764 2248 : bPRINT = false; // do not print this sizing request
2765 2248 : TempSize = AutoSize; // get the autosized air volume flow rate for use in other calculations
2766 2248 : SizingString.clear(); // doesn't matter
2767 2248 : CompType = cAllCoilTypes(Coil_HeatingWater); // "Coil:Heating:Water"
2768 2248 : CompName = state.dataWaterCoils->WaterCoil(CoilNum).Name;
2769 2248 : if (state.dataWaterCoils->WaterCoil(CoilNum).DesiccantRegenerationCoil) {
2770 0 : state.dataSize->DataDesicRegCoil = true;
2771 0 : state.dataSize->DataDesicDehumNum = state.dataWaterCoils->WaterCoil(CoilNum).DesiccantDehumNum;
2772 0 : HeatingCoilDesAirInletTempSizer sizerHeatingDesInletTemp;
2773 0 : bool ErrorsFound = false;
2774 0 : sizerHeatingDesInletTemp.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
2775 0 : state.dataSize->DataDesInletAirTemp = sizerHeatingDesInletTemp.size(state, DataSizing::AutoSize, ErrorsFound);
2776 :
2777 0 : HeatingCoilDesAirOutletTempSizer sizerHeatingDesOutletTemp;
2778 0 : ErrorsFound = false;
2779 0 : sizerHeatingDesOutletTemp.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
2780 0 : state.dataSize->DataDesOutletAirTemp = sizerHeatingDesOutletTemp.size(state, DataSizing::AutoSize, ErrorsFound);
2781 :
2782 0 : if (state.dataSize->CurOASysNum > 0) {
2783 0 : OASysEqSizing(state.dataSize->CurOASysNum).AirFlow = true;
2784 0 : OASysEqSizing(state.dataSize->CurOASysNum).AirVolFlow =
2785 0 : state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).DesOutAirVolFlow;
2786 : }
2787 0 : TempSize = AutoSize; // reset back
2788 : }
2789 2248 : bool errorsFound = false;
2790 4496 : HeatingAirFlowSizer sizingHeatingAirFlow;
2791 2248 : sizingHeatingAirFlow.overrideSizingString(SizingString);
2792 : // sizingHeatingAirFlow.setHVACSizingIndexData(FanCoil(FanCoilNum).HVACSizingIndex);
2793 2248 : sizingHeatingAirFlow.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
2794 2248 : TempSize = sizingHeatingAirFlow.size(state, TempSize, errorsFound);
2795 : // reset the design air volume flow rate for air loop coils only
2796 2248 : if (state.dataSize->CurSysNum > 0) state.dataWaterCoils->WaterCoil(CoilNum).DesAirVolFlowRate = TempSize;
2797 2248 : state.dataWaterCoils->WaterCoil(CoilNum).InletAirMassFlowRate =
2798 2248 : state.dataEnvrn->StdRhoAir * TempSize; // inlet air mass flow rate is not the autosized value
2799 2248 : state.dataSize->DataAirFlowUsedForSizing = TempSize;
2800 2248 : state.dataSize->DataFlowUsedForSizing = TempSize; // many autosized inputs use the design (autosized) air flow rate, save this value
2801 :
2802 2248 : bPRINT = true;
2803 2248 : if (state.dataWaterCoils->WaterCoil(CoilNum).CoilPerfInpMeth == state.dataWaterCoils->NomCap && NomCapUserInp) {
2804 35 : TempSize = state.dataWaterCoils->WaterCoil(CoilNum).DesTotWaterCoilLoad;
2805 35 : state.dataSize->DataNomCapInpMeth = true;
2806 : } else {
2807 2213 : TempSize = AutoSize;
2808 : }
2809 2248 : if (state.dataSize->CurSysNum > 0) {
2810 371 : SizingType = HeatingCapacitySizing;
2811 371 : FieldNum = 3; // N3 , \field Rated Capacity
2812 371 : SizingString = state.dataWaterCoils->WaterCoilNumericFields(CoilNum).FieldNames(FieldNum) + " [W]";
2813 371 : bool errorsFound = false;
2814 742 : HeatingCapacitySizer sizerHeatingCapacity;
2815 371 : sizerHeatingCapacity.overrideSizingString(SizingString);
2816 371 : sizerHeatingCapacity.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
2817 371 : TempSize = sizerHeatingCapacity.size(state, TempSize, errorsFound);
2818 371 : state.dataWaterCoils->WaterCoil(CoilNum).DesWaterHeatingCoilRate = TempSize;
2819 371 : state.dataWaterCoils->WaterCoil(CoilNum).DesTotWaterCoilLoad = TempSize;
2820 371 : state.dataSize->DataCapacityUsedForSizing = state.dataWaterCoils->WaterCoil(CoilNum).DesWaterHeatingCoilRate;
2821 : } else {
2822 3754 : WaterHeatingCapacitySizer sizerWaterHeatingCapacity;
2823 1877 : bool ErrorsFound = false;
2824 1877 : sizerWaterHeatingCapacity.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
2825 1877 : state.dataWaterCoils->WaterCoil(CoilNum).DesWaterHeatingCoilRate = sizerWaterHeatingCapacity.size(state, TempSize, ErrorsFound);
2826 1877 : state.dataWaterCoils->WaterCoil(CoilNum).DesTotWaterCoilLoad = state.dataWaterCoils->WaterCoil(CoilNum).DesWaterHeatingCoilRate;
2827 1877 : state.dataSize->DataCapacityUsedForSizing = state.dataWaterCoils->WaterCoil(CoilNum).DesWaterHeatingCoilRate;
2828 : }
2829 :
2830 : // We now have the design load if it was autosized. For the case of CoilPerfInpMeth == NomCap, calculate the air flow rate
2831 : // specified by the NomCap inputs. This overrides all previous values
2832 2248 : if (state.dataWaterCoils->WaterCoil(CoilNum).CoilPerfInpMeth == state.dataWaterCoils->NomCap && NomCapUserInp) {
2833 35 : state.dataWaterCoils->WaterCoil(CoilNum).InletAirMassFlowRate =
2834 70 : state.dataWaterCoils->WaterCoil(CoilNum).DesTotWaterCoilLoad /
2835 35 : (CpAirStd *
2836 35 : (state.dataWaterCoils->WaterCoil(CoilNum).DesOutletAirTemp - state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirTemp));
2837 35 : state.dataWaterCoils->WaterCoil(CoilNum).DesAirVolFlowRate =
2838 35 : state.dataWaterCoils->WaterCoil(CoilNum).InletAirMassFlowRate / state.dataEnvrn->StdRhoAir;
2839 35 : state.dataSize->DataAirFlowUsedForSizing = state.dataWaterCoils->WaterCoil(CoilNum).DesAirVolFlowRate;
2840 35 : state.dataSize->DataFlowUsedForSizing = state.dataWaterCoils->WaterCoil(CoilNum).DesAirVolFlowRate;
2841 : }
2842 :
2843 2248 : TempSize = state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterVolFlowRate;
2844 :
2845 2248 : if (state.dataWaterCoils->WaterCoil(CoilNum).CoilPerfInpMeth == state.dataWaterCoils->NomCap && NomCapUserInp) {
2846 35 : if (state.dataWaterCoils->WaterCoil(CoilNum).DesTotWaterCoilLoad > SmallLoad) {
2847 35 : state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterVolFlowRate =
2848 70 : state.dataSize->DataCapacityUsedForSizing /
2849 70 : (Cp * rho *
2850 35 : (state.dataWaterCoils->WaterCoil(CoilNum).DesInletWaterTemp - state.dataWaterCoils->WaterCoil(CoilNum).DesOutletWaterTemp));
2851 : } else {
2852 0 : state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterVolFlowRate = 0.0;
2853 : }
2854 35 : state.dataSize->DataConstantUsedForSizing = state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterVolFlowRate;
2855 35 : state.dataSize->DataFractionUsedForSizing = 1.0;
2856 : }
2857 4496 : HeatingWaterflowSizer sizerHWWaterflow;
2858 2248 : sizerHWWaterflow.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
2859 2248 : Real64 sizedMaxWaterVolFlowRate = sizerHWWaterflow.size(state, TempSize, ErrorsFound);
2860 : // Check if the water flow rate is defined in parent HVAC equipment and set water coil design water flow rate accordingly
2861 2248 : if (state.dataSize->CurZoneEqNum > 0) {
2862 1877 : if (ZoneEqSizing(state.dataSize->CurZoneEqNum).DesignSizeFromParent) {
2863 80 : state.dataSize->DataWaterFlowUsedForSizing = ZoneEqSizing(state.dataSize->CurZoneEqNum).MaxHWVolFlow;
2864 80 : state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterVolFlowRate = ZoneEqSizing(state.dataSize->CurZoneEqNum).MaxHWVolFlow;
2865 : } else {
2866 1797 : state.dataSize->DataWaterFlowUsedForSizing = sizedMaxWaterVolFlowRate;
2867 1797 : state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterVolFlowRate = sizedMaxWaterVolFlowRate;
2868 : }
2869 : } else {
2870 371 : state.dataSize->DataWaterFlowUsedForSizing = sizedMaxWaterVolFlowRate;
2871 371 : state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterVolFlowRate = sizedMaxWaterVolFlowRate;
2872 : }
2873 2248 : state.dataSize->DataConstantUsedForSizing = 0.0; // reset these in case NomCapUserInp was true
2874 2248 : state.dataSize->DataFractionUsedForSizing = 0.0;
2875 2248 : if (state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterVolFlowRate <= 0.0) {
2876 : // MaxWaterVolFlowRateDes = 0.0;
2877 31 : ShowWarningError(state, "The design coil load is zero for Coil:Heating:Water " + state.dataWaterCoils->WaterCoil(CoilNum).Name);
2878 31 : ShowContinueError(state, "The autosize value for maximum water flow rate is zero");
2879 31 : ShowContinueError(state, "To change this, input a value for UA, change the heating design day, or raise the");
2880 31 : ShowContinueError(state, " system heating design supply air temperature. Also check to make sure the Preheat");
2881 31 : ShowContinueError(state, " Design Temperature is not the same as the Central Heating Design Supply Air Temperature. ");
2882 : }
2883 :
2884 : // initialize the water coil inlet conditions
2885 2248 : bPRINT = false; // no need to print to eio since we only need the values
2886 2248 : state.dataSize->DataFlowUsedForSizing = state.dataSize->DataAirFlowUsedForSizing;
2887 2248 : if (state.dataWaterCoils->WaterCoil(CoilNum).CoilPerfInpMeth == state.dataWaterCoils->NomCap && NomCapUserInp) {
2888 35 : state.dataWaterCoils->WaterCoil(CoilNum).InletAirTemp = state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirTemp;
2889 35 : state.dataWaterCoils->WaterCoil(CoilNum).InletAirHumRat =
2890 35 : PsyWFnTdbRhPb(state, state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirTemp, 0.5, state.dataEnvrn->StdBaroPress, RoutineName);
2891 35 : state.dataWaterCoils->WaterCoil(CoilNum).InletAirMassFlowRate =
2892 35 : state.dataSize->DataAirFlowUsedForSizing * state.dataEnvrn->StdRhoAir; // don't need this
2893 35 : state.dataSize->DataDesOutletAirTemp = state.dataWaterCoils->WaterCoil(CoilNum).DesOutletAirTemp; // for error messages
2894 35 : state.dataSize->DataDesOutletAirHumRat =
2895 35 : PsyWFnTdbRhPb(state, state.dataSize->DataDesOutletAirTemp, 0.5, state.dataEnvrn->StdBaroPress, RoutineName); // for error messages
2896 35 : state.dataWaterCoils->WaterCoil(CoilNum).InletWaterMassFlowRate = rho * state.dataSize->DataWaterFlowUsedForSizing;
2897 35 : state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterMassFlowRate = rho * state.dataSize->DataWaterFlowUsedForSizing;
2898 35 : state.dataWaterCoils->WaterCoil(CoilNum).InletWaterTemp = state.dataWaterCoils->WaterCoil(CoilNum).DesInletWaterTemp;
2899 2213 : } else if (state.dataWaterCoils->WaterCoil(CoilNum).DesiccantRegenerationCoil) {
2900 0 : state.dataWaterCoils->WaterCoil(CoilNum).InletAirTemp = state.dataSize->DataDesInletAirTemp;
2901 0 : HeatingCoilDesAirInletHumRatSizer sizerHeatingDesInletHumRat;
2902 0 : bool ErrorsFound = false;
2903 0 : sizerHeatingDesInletHumRat.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
2904 0 : state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirHumRat =
2905 0 : sizerHeatingDesInletHumRat.size(state, DataSizing::AutoSize, ErrorsFound);
2906 0 : state.dataWaterCoils->WaterCoil(CoilNum).InletAirHumRat = state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirHumRat;
2907 :
2908 0 : state.dataWaterCoils->WaterCoil(CoilNum).DesAirVolFlowRate = state.dataSize->DataAirFlowUsedForSizing; // coil report
2909 0 : state.dataWaterCoils->WaterCoil(CoilNum).InletAirMassFlowRate =
2910 0 : state.dataSize->DataAirFlowUsedForSizing * state.dataEnvrn->StdRhoAir; // this is stiil volume flow!
2911 : } else {
2912 4426 : HeatingWaterDesAirInletTempSizer sizerHWDesInletTemp;
2913 2213 : sizerHWDesInletTemp.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
2914 2213 : state.dataWaterCoils->WaterCoil(CoilNum).InletAirTemp = sizerHWDesInletTemp.size(state, DataSizing::AutoSize, ErrorsFound);
2915 :
2916 2213 : TempSize = AutoSize; // these data are initially 0, set to autosize to receive a result from Sizers
2917 4426 : HeatingWaterDesAirInletHumRatSizer sizerHWAirInletHumRat;
2918 2213 : sizerHWAirInletHumRat.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
2919 2213 : state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirHumRat = sizerHWAirInletHumRat.size(state, DataSizing::AutoSize, ErrorsFound);
2920 2213 : state.dataWaterCoils->WaterCoil(CoilNum).InletAirHumRat = state.dataWaterCoils->WaterCoil(CoilNum).DesInletAirHumRat;
2921 :
2922 4426 : HeatingAirflowUASizer sizerHWAirFlowUA;
2923 2213 : sizerHWAirFlowUA.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
2924 2213 : state.dataWaterCoils->WaterCoil(CoilNum).DesAirMassFlowRate = sizerHWAirFlowUA.size(state, DataSizing::AutoSize, ErrorsFound);
2925 2213 : state.dataWaterCoils->WaterCoil(CoilNum).InletAirMassFlowRate = state.dataWaterCoils->WaterCoil(CoilNum).DesAirMassFlowRate;
2926 : }
2927 :
2928 : // zone and air loop coils use different design coil load calculations, air loop coils use air side capacity,
2929 : // zone coils use water side capacity
2930 2248 : state.dataSize->DataDesInletAirTemp = state.dataWaterCoils->WaterCoil(CoilNum).InletAirTemp; // used in error mesages
2931 2248 : state.dataSize->DataDesInletAirHumRat = state.dataWaterCoils->WaterCoil(CoilNum).InletAirHumRat; // used in error mesages
2932 2248 : state.dataSize->DataFlowUsedForSizing = state.dataSize->DataAirFlowUsedForSizing * state.dataEnvrn->StdRhoAir; // used in error mesages
2933 2248 : state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterVolFlowRate = state.dataSize->DataWaterFlowUsedForSizing; // why is this here?
2934 2248 : if (!(state.dataWaterCoils->WaterCoil(CoilNum).CoilPerfInpMeth == state.dataWaterCoils->NomCap && NomCapUserInp)) {
2935 : // get the design coil load used to size UA
2936 4426 : HeatingWaterDesCoilLoadUsedForUASizer sizerHWDesCoilLoadForUA;
2937 2213 : sizerHWDesCoilLoadForUA.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
2938 2213 : state.dataSize->DataCapacityUsedForSizing = sizerHWDesCoilLoadForUA.size(state, DataSizing::AutoSize, ErrorsFound);
2939 : // get the water volume flow rate used to size UA
2940 4426 : HeatingWaterDesCoilWaterVolFlowUsedForUASizer sizerHWWaterVolFlowUA;
2941 2213 : sizerHWWaterVolFlowUA.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
2942 2213 : state.dataSize->DataWaterFlowUsedForSizing = sizerHWWaterVolFlowUA.size(state, DataSizing::AutoSize, ErrorsFound);
2943 2213 : state.dataWaterCoils->WaterCoil(CoilNum).InletWaterTemp = state.dataSize->PlantSizData(PltSizHeatNum).ExitTemp;
2944 2213 : state.dataWaterCoils->WaterCoil(CoilNum).InletWaterMassFlowRate = rho * state.dataSize->DataWaterFlowUsedForSizing;
2945 2213 : state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterMassFlowRate = rho * state.dataSize->DataWaterFlowUsedForSizing;
2946 2213 : state.dataWaterCoils->WaterCoil(CoilNum).DesWaterHeatingCoilRate = state.dataSize->DataCapacityUsedForSizing;
2947 : }
2948 : // calculate UA
2949 2248 : if (state.dataSize->CurSysNum > 0)
2950 371 : state.dataWaterCoils->WaterCoil(CoilNum).DesTotWaterCoilLoad = state.dataSize->DataCapacityUsedForSizing;
2951 2248 : FieldNum = 1; // N1 , \field U-Factor Times Area Value
2952 2248 : bPRINT = true; // report to eio the UA value
2953 2248 : SizingString = state.dataWaterCoils->WaterCoilNumericFields(CoilNum).FieldNames(FieldNum) + " [W/K]";
2954 2248 : state.dataSize->DataCoilNum = CoilNum;
2955 2248 : state.dataSize->DataFanOpMode = ContFanCycCoil;
2956 2248 : if (state.dataWaterCoils->WaterCoil(CoilNum).CoilPerfInpMeth == state.dataWaterCoils->NomCap && NomCapUserInp) {
2957 35 : TempSize = AutoSize;
2958 : } else {
2959 2213 : TempSize = state.dataWaterCoils->WaterCoil(CoilNum).UACoil;
2960 : }
2961 :
2962 2248 : state.dataSize->DataFlowUsedForSizing = state.dataWaterCoils->WaterCoil(CoilNum).InletAirMassFlowRate;
2963 2248 : DesCoilWaterInTempSaved = state.dataWaterCoils->WaterCoil(state.dataSize->DataCoilNum).InletWaterTemp;
2964 2248 : if (DesCoilWaterInTempSaved < DesCoilHWInletTempMin) {
2965 : // at low coil design water inlet temp, sizing has convergence issue hence slightly higher water inlet temperature
2966 : // is estimated in "EstimateCoilInletWaterTemp" and used for UA autosizing only
2967 0 : EstimateCoilInletWaterTemp(state,
2968 0 : state.dataSize->DataCoilNum,
2969 0 : state.dataSize->DataFanOpMode,
2970 : 1.0,
2971 0 : state.dataSize->DataCapacityUsedForSizing,
2972 : DesCoilInletWaterTempUsed);
2973 0 : state.dataWaterCoils->WaterCoil(state.dataSize->DataCoilNum).InletWaterTemp = DesCoilInletWaterTempUsed;
2974 : }
2975 : // must set DataCapacityUsedForSizing, DataWaterFlowUsedForSizing and DataFlowUsedForSizing to size UA. Any value of 0 will result
2976 : // in UA = 1.
2977 4496 : WaterHeatingCoilUASizer sizerHWCoilUA;
2978 2248 : sizerHWCoilUA.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
2979 2248 : state.dataWaterCoils->WaterCoil(CoilNum).UACoil = sizerHWCoilUA.size(state, TempSize, ErrorsFound);
2980 2248 : if (DesCoilWaterInTempSaved < DesCoilHWInletTempMin) {
2981 0 : ShowWarningError(state, "Autosizing of heating coil UA for Coil:Heating:Water \"" + std::string{CompName} + "\"");
2982 0 : ShowContinueError(state,
2983 0 : format(" Plant design loop exit temperature = {:.2T} C",
2984 0 : state.dataSize->PlantSizData(state.dataSize->DataPltSizHeatNum).ExitTemp));
2985 0 : ShowContinueError(state, " Plant design loop exit temperature is low for design load and leaving air temperature anticipated.");
2986 0 : ShowContinueError(state,
2987 0 : format(" Heating coil UA-value is sized using coil water inlet temperature = {:.2T} C", DesCoilInletWaterTempUsed));
2988 0 : state.dataWaterCoils->WaterCoil(state.dataSize->DataCoilNum).InletWaterTemp =
2989 : DesCoilWaterInTempSaved; // reset the Design Coil Inlet Water Temperature
2990 : }
2991 : // if coil UA did not size due to one of these variables being 0, must set UACoilVariable to avoid crash later on
2992 4465 : if (state.dataSize->DataCapacityUsedForSizing == 0.0 || state.dataSize->DataWaterFlowUsedForSizing == 0.0 ||
2993 2217 : state.dataSize->DataFlowUsedForSizing == 0.0) {
2994 31 : if (state.dataWaterCoils->WaterCoil(CoilNum).UACoilVariable == AutoSize) {
2995 31 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilVariable = state.dataWaterCoils->WaterCoil(CoilNum).UACoil;
2996 : }
2997 : }
2998 : // WaterCoil(CoilNum).UACoilVariable = WaterCoil(CoilNum).UACoil;
2999 2248 : state.dataWaterCoils->WaterCoil(CoilNum).DesWaterHeatingCoilRate = state.dataSize->DataCapacityUsedForSizing;
3000 2248 : state.dataWaterCoils->WaterCoil(state.dataSize->DataCoilNum).InletWaterTemp =
3001 : DesCoilWaterInTempSaved; // reset the Design Coil Inlet Water Temperature
3002 :
3003 2248 : state.dataSize->DataWaterLoopNum = 0; // reset all globals to 0 to ensure correct sizing for other child components
3004 2248 : state.dataSize->DataPltSizHeatNum = 0;
3005 2248 : state.dataSize->DataCoilNum = 0;
3006 2248 : state.dataSize->DataFanOpMode = 0;
3007 2248 : state.dataSize->DataCapacityUsedForSizing = 0.0;
3008 2248 : state.dataSize->DataWaterFlowUsedForSizing = 0.0;
3009 2248 : state.dataSize->DataDesInletAirTemp = 0.0;
3010 2248 : state.dataSize->DataDesInletAirHumRat = 0.0;
3011 2248 : state.dataSize->DataDesOutletAirTemp = 0.0;
3012 2248 : state.dataSize->DataDesOutletAirHumRat = 0.0;
3013 2248 : state.dataSize->DataAirFlowUsedForSizing = 0.0;
3014 2248 : state.dataSize->DataFlowUsedForSizing = 0.0;
3015 2248 : state.dataSize->DataDesicDehumNum = 0;
3016 2248 : state.dataSize->DataDesicRegCoil = false;
3017 2248 : state.dataSize->DataWaterCoilSizHeatDeltaT = 0.0;
3018 2248 : state.dataSize->DataNomCapInpMeth = false;
3019 :
3020 : } else {
3021 : // if there is no heating Plant Sizing object and autosizng was requested, issue an error message
3022 306 : if (state.dataWaterCoils->WaterCoil(CoilNum).RequestingAutoSize) {
3023 0 : ShowSevereError(state, "Autosizing of water coil requires a heating loop Sizing:Plant object");
3024 0 : ShowContinueError(state, "Occurs in water coil object= " + state.dataWaterCoils->WaterCoil(CoilNum).Name);
3025 0 : ErrorsFound = true;
3026 : }
3027 : }
3028 : //} // end of heating Plant Sizing existence IF - ELSE
3029 : } // end heating coil IF
3030 :
3031 : // save the design water volumetric flow rate for use by the water loop sizing algorithms
3032 3100 : if (state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterVolFlowRate > 0.0) {
3033 6134 : RegisterPlantCompDesignFlow(
3034 6134 : state, state.dataWaterCoils->WaterCoil(CoilNum).WaterInletNodeNum, state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterVolFlowRate);
3035 : }
3036 :
3037 3100 : if (ErrorsFound || state.dataSize->DataErrorsFound) {
3038 0 : ShowFatalError(state, "Preceding water coil sizing errors cause program termination");
3039 : }
3040 3100 : }
3041 :
3042 : // End Initialization Section of the Module
3043 : //******************************************************************************
3044 :
3045 : // Begin Algorithm Section of the Module
3046 : //******************************************************************************
3047 :
3048 112202558 : void CalcSimpleHeatingCoil(EnergyPlusData &state,
3049 : int const CoilNum, // index to heating coil
3050 : int const FanOpMode, // fan operating mode
3051 : Real64 const PartLoadRatio, // part-load ratio of heating coil
3052 : int const CalcMode // 1 = design calc; 2 = simulation calculation
3053 : )
3054 : {
3055 : // SUBROUTINE INFORMATION:
3056 : // AUTHOR Rich Liesen
3057 : // DATE WRITTEN
3058 : // MODIFIED Aug. 2007 - R. Raustad, added fan operating mode and part-load ratio to
3059 : // calculate the outlet conditions when fan and coil cycle.
3060 : // Air and water outlet temperature are full output with average
3061 : // air and water mass flow rate when fan and coil cycle.
3062 : // RE-ENGINEERED na
3063 :
3064 : // PURPOSE OF THIS SUBROUTINE:
3065 : // Simulates a simple NTU effectiveness model heating coil
3066 :
3067 : // METHODOLOGY EMPLOYED:
3068 : // (1) outlet conditions are calculated from the effectiveness and the inlet conditions.
3069 : // (2) Effectiveness is calculated from the NTU formula for a cross flow heat exchanger
3070 : // with both streams unmixed.
3071 : // Note: UA is input by user and is fixed.
3072 :
3073 : // REFERENCES:
3074 : // See for instance ASHRAE HVAC 2 Toolkit, page 4-4, formula (4-7)
3075 :
3076 : // Using/Aliasing
3077 :
3078 : // Locals
3079 : // SUBROUTINE ARGUMENT DEFINITIONS:
3080 :
3081 : // SUBROUTINE PARAMETER DEFINITIONS:
3082 : static constexpr std::string_view RoutineName("CalcSimpleHeatingCoil");
3083 :
3084 : // INTERFACE BLOCK SPECIFICATIONS
3085 : // na
3086 :
3087 : // DERIVED TYPE DEFINITIONS
3088 : // na
3089 :
3090 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
3091 : Real64 WaterMassFlowRate;
3092 : Real64 AirMassFlow; // [kg/sec]
3093 : Real64 TempAirIn; // [C]
3094 : Real64 TempAirOut; // [C]
3095 : Real64 Win;
3096 : Real64 TempWaterIn;
3097 : Real64 TempWaterOut;
3098 : Real64 UA;
3099 : Real64 CapacitanceAir;
3100 : Real64 CapacitanceWater;
3101 : Real64 CapacitanceMin;
3102 : Real64 CapacitanceMax;
3103 : Real64 HeatingCoilLoad;
3104 : Real64 NTU;
3105 : Real64 ETA;
3106 : Real64 A;
3107 : Real64 CapRatio;
3108 : Real64 E1;
3109 : Real64 E2;
3110 : Real64 Effec;
3111 : Real64 Cp;
3112 : int Control;
3113 :
3114 112202558 : UA = state.dataWaterCoils->WaterCoil(CoilNum).UACoilVariable;
3115 112202558 : TempAirIn = state.dataWaterCoils->WaterCoil(CoilNum).InletAirTemp;
3116 112202558 : Win = state.dataWaterCoils->WaterCoil(CoilNum).InletAirHumRat;
3117 112202558 : Control = state.dataWaterCoils->WaterCoil(CoilNum).Control;
3118 112202558 : TempWaterIn = state.dataWaterCoils->WaterCoil(CoilNum).InletWaterTemp;
3119 :
3120 : // adjust mass flow rates for cycling fan cycling coil operation
3121 112202558 : if (FanOpMode == CycFanCycCoil) {
3122 2155645 : if (PartLoadRatio > 0.0) {
3123 1581726 : AirMassFlow = state.dataWaterCoils->WaterCoil(CoilNum).InletAirMassFlowRate / PartLoadRatio;
3124 1581726 : WaterMassFlowRate = min(state.dataWaterCoils->WaterCoil(CoilNum).InletWaterMassFlowRate / PartLoadRatio,
3125 1581726 : state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterMassFlowRate);
3126 : } else {
3127 573919 : AirMassFlow = 0.0;
3128 573919 : WaterMassFlowRate = 0.0;
3129 : }
3130 : } else {
3131 110046913 : AirMassFlow = state.dataWaterCoils->WaterCoil(CoilNum).InletAirMassFlowRate;
3132 110046913 : WaterMassFlowRate = state.dataWaterCoils->WaterCoil(CoilNum).InletWaterMassFlowRate;
3133 : }
3134 :
3135 112202558 : if (WaterMassFlowRate > DataBranchAirLoopPlant::MassFlowTolerance) { // If the coil is operating
3136 71618883 : CapacitanceAir = PsyCpAirFnW(Win) * AirMassFlow;
3137 143237766 : Cp = GetSpecificHeatGlycol(state,
3138 71618883 : state.dataPlnt->PlantLoop(state.dataWaterCoils->WaterCoil(CoilNum).WaterPlantLoc.loopNum).FluidName,
3139 : TempWaterIn,
3140 71618883 : state.dataPlnt->PlantLoop(state.dataWaterCoils->WaterCoil(CoilNum).WaterPlantLoc.loopNum).FluidIndex,
3141 : RoutineName);
3142 71618883 : CapacitanceWater = Cp * WaterMassFlowRate;
3143 71618883 : CapacitanceMin = min(CapacitanceAir, CapacitanceWater);
3144 71618883 : CapacitanceMax = max(CapacitanceAir, CapacitanceWater);
3145 : } else {
3146 40583675 : CapacitanceAir = 0.0;
3147 40583675 : CapacitanceWater = 0.0;
3148 : }
3149 :
3150 : // If the coil is operating there should be some heating capacitance
3151 : // across the coil, so do the simulation. If not set outlet to inlet and no load.
3152 : // Also the coil has to be scheduled to be available
3153 255355948 : if (((CapacitanceAir > 0.0) && (CapacitanceWater > 0.0)) &&
3154 214770488 : (CalcMode == state.dataWaterCoils->DesignCalc || state.dataWaterCoils->MySizeFlag(CoilNum) ||
3155 143131008 : state.dataWaterCoils->MyUAAndFlowCalcFlag(CoilNum) ||
3156 71565504 : GetCurrentScheduleValue(state, state.dataWaterCoils->WaterCoil(CoilNum).SchedPtr) > 0.0)) {
3157 :
3158 71542447 : if (UA <= 0.0) {
3159 0 : ShowFatalError(state, "UA is zero for COIL:Heating:Water " + state.dataWaterCoils->WaterCoil(CoilNum).Name);
3160 : }
3161 71542447 : NTU = UA / CapacitanceMin;
3162 71542447 : ETA = std::pow(NTU, 0.22);
3163 71542447 : CapRatio = CapacitanceMin / CapacitanceMax;
3164 71542447 : A = CapRatio * NTU / ETA;
3165 :
3166 71542447 : if (A > 20.0) {
3167 0 : A = ETA * 1.0 / CapRatio;
3168 : } else {
3169 71542447 : E1 = std::exp(-A);
3170 71542447 : A = ETA * (1.0 - E1) / CapRatio;
3171 : }
3172 :
3173 71542447 : if (A > 20.0) {
3174 226535 : Effec = 1.0;
3175 : } else {
3176 71315912 : E2 = std::exp(-A);
3177 71315912 : Effec = 1.0 - E2;
3178 : }
3179 :
3180 71542447 : TempAirOut = TempAirIn + Effec * CapacitanceMin * (TempWaterIn - TempAirIn) / CapacitanceAir;
3181 71542447 : TempWaterOut = TempWaterIn - CapacitanceAir * (TempAirOut - TempAirIn) / CapacitanceWater;
3182 71542447 : HeatingCoilLoad = CapacitanceWater * (TempWaterIn - TempWaterOut);
3183 : // The HeatingCoilLoad is the change in the enthalpy of the water
3184 71542447 : state.dataWaterCoils->WaterCoil(CoilNum).OutletWaterEnthalpy =
3185 143084894 : state.dataWaterCoils->WaterCoil(CoilNum).InletWaterEnthalpy -
3186 71542447 : HeatingCoilLoad / state.dataWaterCoils->WaterCoil(CoilNum).InletWaterMassFlowRate;
3187 71542447 : state.dataWaterCoils->WaterCoil(CoilNum).OutletWaterMassFlowRate = state.dataWaterCoils->WaterCoil(CoilNum).InletWaterMassFlowRate;
3188 :
3189 : } else { // If not running Conditions do not change across coil from inlet to outlet
3190 :
3191 40660111 : TempAirOut = TempAirIn;
3192 40660111 : TempWaterOut = TempWaterIn;
3193 40660111 : HeatingCoilLoad = 0.0;
3194 40660111 : state.dataWaterCoils->WaterCoil(CoilNum).OutletWaterEnthalpy = state.dataWaterCoils->WaterCoil(CoilNum).InletWaterEnthalpy;
3195 40660111 : state.dataWaterCoils->WaterCoil(CoilNum).OutletWaterMassFlowRate = 0.0;
3196 : }
3197 :
3198 112202558 : if (FanOpMode == CycFanCycCoil) {
3199 2155645 : HeatingCoilLoad *= PartLoadRatio;
3200 : }
3201 :
3202 : // Set the outlet conditions
3203 112202558 : state.dataWaterCoils->WaterCoil(CoilNum).TotWaterHeatingCoilRate = HeatingCoilLoad;
3204 112202558 : state.dataWaterCoils->WaterCoil(CoilNum).OutletAirTemp = TempAirOut;
3205 112202558 : state.dataWaterCoils->WaterCoil(CoilNum).OutletWaterTemp = TempWaterOut;
3206 :
3207 : // This WaterCoil does not change the moisture or Mass Flow across the component
3208 112202558 : state.dataWaterCoils->WaterCoil(CoilNum).OutletAirHumRat = state.dataWaterCoils->WaterCoil(CoilNum).InletAirHumRat;
3209 112202558 : state.dataWaterCoils->WaterCoil(CoilNum).OutletAirMassFlowRate = state.dataWaterCoils->WaterCoil(CoilNum).InletAirMassFlowRate;
3210 : // Set the outlet enthalpys for air and water
3211 112202558 : state.dataWaterCoils->WaterCoil(CoilNum).OutletAirEnthalpy =
3212 112202558 : PsyHFnTdbW(state.dataWaterCoils->WaterCoil(CoilNum).OutletAirTemp, state.dataWaterCoils->WaterCoil(CoilNum).OutletAirHumRat);
3213 112202558 : }
3214 :
3215 3337956 : void CalcDetailFlatFinCoolingCoil(EnergyPlusData &state,
3216 : int const CoilNum,
3217 : int const CalcMode,
3218 : int const FanOpMode, // fan operating mode
3219 : Real64 const PartLoadRatio // part-load ratio of heating coil
3220 : )
3221 : {
3222 :
3223 : // SUBROUTINE INFORMATION:
3224 : // AUTHOR(S) Russell Taylor / Richard Liesen
3225 : // DATE WRITTEN Mar 1997
3226 : // MODIFIED Feb 2010, B. Nigusse, FSEC, corrected units inconsistency for tube and fins
3227 : // materials thermal conductivties. Now input values in the idf are in {W/(m.K)}
3228 : // RE-ENGINEERED Sept 1998
3229 :
3230 : // PURPOSE OF THIS SUBROUTINE:
3231 : // This subroutine simulates a chilled water cooling coil. Provided with
3232 : // the coil geometry and the flow (i.e. air and water) inlet conditions,
3233 : // it will calculate the flow outlet conditions and the total and latent
3234 : // heat extraction rates from the air. The coil model has some limitations
3235 : // as noted in the code.
3236 :
3237 : // METHODOLOGY EMPLOYED:
3238 : // successive substitution, solve coil as if all wet, then
3239 : // again if partly or entirely dry
3240 :
3241 : // REFERENCES:
3242 : // First found in Type 12 from MODSIM, but now
3243 : // programmed directly from Elmahdy, A.H. and Mitalas, G.P. "A
3244 : // Simple Model for Cooling and Dehumidifying Coils for Use in
3245 : // Calculating Energy Requirements for Buildings" _ASHRAE
3246 : // Transactions_ Vol. 83, Part 2, pp. 103-117 (1977).
3247 :
3248 : // OTHER NOTES:
3249 : // Routine was originally adapted for use in IBLAST by R.D. Taylor in l993.
3250 : // Subsequently rewritten and improved by J.C. Vanderzee in 1994
3251 : // Revised and further enhanced by R.D. Taylor in Jan 1996
3252 : // Re-engineered for EnergyPlus by Richard Liesen PhD in 1998
3253 :
3254 : // Using/Aliasing
3255 :
3256 : // Locals
3257 : // SUBROUTINE ARGUMENT DEFINITIONS:
3258 :
3259 : // SUBROUTINE PARAMETER DEFINITIONS:
3260 : static Real64 const exp_47(std::exp(-0.41718));
3261 : static Real64 const exp_35(std::exp(-0.3574));
3262 : static constexpr std::string_view RoutineName("CalcDetailFlatFinCoolingCoil");
3263 :
3264 3337956 : constexpr Real64 AirViscosity(1.846e-5); // Dynamic Viscosity of Air in kg/(m.s)
3265 3337956 : constexpr Real64 ConvK(1.0e-3); // Unit conversion factor
3266 3337956 : constexpr Real64 unity(1.0);
3267 3337956 : constexpr Real64 zero(0.0);
3268 3337956 : constexpr Real64 TubeFoulFactor(5.0e-2); // Inside tube fouling factor for water, in m2K/kW
3269 : // Changed from m2K/W to m2K/kW for consistency with the
3270 : // other parameters in "TubeFoulThermResis" calculation
3271 :
3272 : // INTERFACE BLOCK SPECIFICATIONS
3273 : // na
3274 :
3275 : // DERIVED TYPE DEFINITIONS
3276 : // na
3277 :
3278 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
3279 : int CoefPointer;
3280 : // INTEGER :: CoolCoilErrs = 0
3281 : int PartWetIterations;
3282 : int WaterTempConvgLoop;
3283 :
3284 : bool CoilPartWetConvg;
3285 : bool WaterTempConvg;
3286 :
3287 : Real64 AirEnthAtRsdInletWaterTemp;
3288 : Real64 AirExitEnthlAtCoilSurfTemp;
3289 : Real64 AirExitCoilSurfTemp;
3290 : Real64 AirReynoldsNo;
3291 : Real64 AirEnthAtWetDryIntrfcSurfTemp;
3292 : Real64 AirSideDrySurfFilmCoef;
3293 : Real64 AirSideWetSurfFilmCoef;
3294 : Real64 AirWetDryInterfcTemp;
3295 : Real64 CoilToAirThermResistDrySurf;
3296 : Real64 CoilToAirThermResistWetSurf;
3297 : Real64 DryAirSpecHeat;
3298 : Real64 DryCoilCoeff1;
3299 : Real64 DryCoilCoeff;
3300 : Real64 DryCoilEfficiency;
3301 : Real64 DryFinEfficncy;
3302 : Real64 DryCoilInThermResist;
3303 : Real64 DrySideEffectiveWaterTemp;
3304 : Real64 EnterAirDewPoint;
3305 : Real64 EnterAirHumRatDiff;
3306 : Real64 WetDryInterSurfTempErrorLast;
3307 : Real64 WetDryInterSurfTempError;
3308 : Real64 expon;
3309 : Real64 FilmCoefEqnFactor;
3310 : Real64 FilmCoefReynldsCorrelatnFact;
3311 : Real64 FinToTotSurfAreaRatio;
3312 : Real64 InCoilSurfTemp;
3313 : Real64 InsdToOutsdThermResistRatio;
3314 : Real64 InSurfTempSatAirEnthl;
3315 : Real64 K1;
3316 : Real64 MeanWaterTemp;
3317 : Real64 MoistAirSpecificHeat;
3318 : Real64 OutCoilSurfTemp;
3319 : Real64 OutSurfTempSatAirEnthl;
3320 : Real64 RaisedInletWaterTemp;
3321 : Real64 RsdInletWaterTempSatAirHumRat;
3322 : Real64 ScaledAirMassFlowRate;
3323 : Real64 ScaledCoilAirThermResistWetSurf;
3324 : Real64 ScaledWaterSpecHeat;
3325 : Real64 ScaledWaterToTubeThermResist;
3326 : Real64 SensToTotEnthDiffRatio;
3327 : Real64 SurfAreaWet;
3328 : Real64 TubeFoulThermResist;
3329 : Real64 TubeWaterVel;
3330 : Real64 UACoilAllWet;
3331 : Real64 UACoilPartWet;
3332 : Real64 UADryCoil;
3333 : Real64 WaterToTubeThermResist;
3334 : Real64 WetAreaChange;
3335 : Real64 WetAreaLast;
3336 : Real64 WetCoilCoeff;
3337 : Real64 WetCoilFinEfficncy;
3338 : Real64 WetDryInterfcAirEnthl;
3339 : Real64 WetDryInterfcSurfTemp;
3340 : Real64 WetDryInterfcWaterTemp;
3341 : Real64 WetFinEfficncy;
3342 : Real64 WetSideEffctvWaterTemp;
3343 : Real64 y;
3344 : Real64 TempAirIn;
3345 : Real64 TempAirOut;
3346 : Real64 InletAirHumRat;
3347 : Real64 OutletAirHumRat;
3348 : Real64 InletAirEnthalpy;
3349 : Real64 OutletAirEnthalpy;
3350 : Real64 WaterMassFlowRate;
3351 : Real64 AirMassFlow;
3352 : Real64 TempWaterIn;
3353 : Real64 TempWaterOut;
3354 : Real64 TotWaterCoilLoad;
3355 : Real64 SenWaterCoilLoad;
3356 : Real64 AirDensity;
3357 : Real64 AirVelocity;
3358 : Real64 denom;
3359 : Real64 rho;
3360 : Real64 Cp;
3361 :
3362 : // Set derived type variables to shorter local variables
3363 3337956 : TempAirIn = state.dataWaterCoils->WaterCoil(CoilNum).InletAirTemp;
3364 3337956 : InletAirHumRat = state.dataWaterCoils->WaterCoil(CoilNum).InletAirHumRat;
3365 3337956 : TempWaterIn = state.dataWaterCoils->WaterCoil(CoilNum).InletWaterTemp;
3366 :
3367 : // adjust mass flow rates for cycling fan cycling coil operation
3368 3337956 : if (FanOpMode == CycFanCycCoil) {
3369 0 : if (PartLoadRatio > 0.0) {
3370 0 : AirMassFlow = state.dataWaterCoils->WaterCoil(CoilNum).InletAirMassFlowRate / PartLoadRatio;
3371 0 : WaterMassFlowRate = min(state.dataWaterCoils->WaterCoil(CoilNum).InletWaterMassFlowRate / PartLoadRatio,
3372 0 : state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterMassFlowRate);
3373 : } else {
3374 0 : AirMassFlow = 0.0;
3375 0 : WaterMassFlowRate = 0.0;
3376 : }
3377 : } else {
3378 3337956 : AirMassFlow = state.dataWaterCoils->WaterCoil(CoilNum).InletAirMassFlowRate;
3379 3337956 : WaterMassFlowRate = state.dataWaterCoils->WaterCoil(CoilNum).InletWaterMassFlowRate;
3380 : }
3381 :
3382 3337956 : if (WaterMassFlowRate < state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterMassFlowRate * WaterCoils::MinWaterMassFlowFrac) {
3383 1633368 : WaterMassFlowRate = 0.0;
3384 : }
3385 3337956 : if (TempAirIn <= TempWaterIn) {
3386 269278 : WaterMassFlowRate = 0.0;
3387 : }
3388 3337956 : WetDryInterfcAirEnthl = 0.0;
3389 3337956 : OutletAirEnthalpy = 0.0;
3390 3337956 : InletAirEnthalpy = 0.0;
3391 :
3392 : // Warning and error messages for large flow rates for the given user input geometry
3393 3337956 : AirDensity = PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, TempAirIn, InletAirHumRat, RoutineName);
3394 3340614 : if (AirMassFlow > (5.0 * state.dataWaterCoils->WaterCoil(CoilNum).MinAirFlowArea / AirDensity) &&
3395 2658 : state.dataWaterCoils->CoilWarningOnceFlag(CoilNum)) {
3396 2 : ShowWarningError(state, "Coil:Cooling:Water:DetailedGeometry in Coil =" + state.dataWaterCoils->WaterCoil(CoilNum).Name);
3397 2 : ShowContinueError(state, "Air Flow Rate Velocity has greatly exceeded upper design guidelines of ~2.5 m/s");
3398 2 : ShowContinueError(state, format("Air Mass Flow Rate[kg/s]={:.6T}", AirMassFlow));
3399 : // [m/s] = [kg/s] / ([m2] * [kg/m3])
3400 2 : AirVelocity = AirMassFlow / (state.dataWaterCoils->WaterCoil(CoilNum).MinAirFlowArea * AirDensity);
3401 2 : ShowContinueError(state, format("Air Face Velocity[m/s]={:.6T}", AirVelocity));
3402 6 : ShowContinueError(state,
3403 4 : format("Approximate Mass Flow Rate limit for Face Area[kg/s]={:.6T}",
3404 4 : 2.5 * state.dataWaterCoils->WaterCoil(CoilNum).MinAirFlowArea * AirDensity));
3405 2 : ShowContinueError(state, "Coil:Cooling:Water:DetailedGeometry could be resized/autosized to handle capacity");
3406 2 : state.dataWaterCoils->CoilWarningOnceFlag(CoilNum) = false;
3407 3337954 : } else if (AirMassFlow > (44.7 * state.dataWaterCoils->WaterCoil(CoilNum).MinAirFlowArea * AirDensity)) {
3408 0 : ShowSevereError(state, "Coil:Cooling:Water:DetailedGeometry in Coil =" + state.dataWaterCoils->WaterCoil(CoilNum).Name);
3409 0 : ShowContinueError(state, "Air Flow Rate Velocity is > 100MPH (44.7m/s) and simulation cannot continue");
3410 0 : ShowContinueError(state, format("Air Mass Flow Rate[kg/s]={:.6T}", AirMassFlow));
3411 0 : AirVelocity = AirMassFlow / (state.dataWaterCoils->WaterCoil(CoilNum).MinAirFlowArea * AirDensity);
3412 0 : ShowContinueError(state, format("Air Face Velocity[m/s]={:.6T}", AirVelocity));
3413 0 : ShowContinueError(state,
3414 0 : format("Approximate Mass Flow Rate limit for Face Area[kg/s]={:.6T}",
3415 0 : 44.7 * state.dataWaterCoils->WaterCoil(CoilNum).MinAirFlowArea * AirDensity));
3416 0 : ShowFatalError(state, "Coil:Cooling:Water:DetailedGeometry needs to be resized/autosized to handle capacity");
3417 : }
3418 :
3419 : // If Coil is Scheduled ON then do the simulation
3420 10907974 : if (((GetCurrentScheduleValue(state, state.dataWaterCoils->WaterCoil(CoilNum).SchedPtr) > 0.0) && (WaterMassFlowRate > 0.0) &&
3421 6676941 : (AirMassFlow >= WaterCoils::MinAirMassFlow)) ||
3422 1720997 : (CalcMode == state.dataWaterCoils->DesignCalc)) {
3423 : // transfer inputs to simulation variables and calculate
3424 : // known thermodynamic functions
3425 : // All coil calcs are done in KJoules. Convert to KJ here and then convert
3426 : // back to Joules at the end of the Subroutine.
3427 1617457 : DryAirSpecHeat = PsyCpAirFnW(zero) * ConvK;
3428 1617457 : MoistAirSpecificHeat = PsyCpAirFnW(InletAirHumRat) * ConvK;
3429 1617457 : InletAirEnthalpy = state.dataWaterCoils->WaterCoil(CoilNum).InletAirEnthalpy * ConvK;
3430 :
3431 1617457 : EnterAirDewPoint = PsyTdpFnWPb(state, InletAirHumRat, state.dataEnvrn->OutBaroPress, RoutineName);
3432 : // Ratio of secondary (fin) to total (secondary plus primary) surface areas
3433 1617457 : FinToTotSurfAreaRatio =
3434 1617457 : state.dataWaterCoils->WaterCoil(CoilNum).FinSurfArea / state.dataWaterCoils->WaterCoil(CoilNum).TotCoilOutsideSurfArea;
3435 : // known water and air flow parameters:
3436 3234914 : rho = GetDensityGlycol(state,
3437 1617457 : state.dataPlnt->PlantLoop(state.dataWaterCoils->WaterCoil(CoilNum).WaterPlantLoc.loopNum).FluidName,
3438 : TempWaterIn,
3439 1617457 : state.dataPlnt->PlantLoop(state.dataWaterCoils->WaterCoil(CoilNum).WaterPlantLoc.loopNum).FluidIndex,
3440 : RoutineName);
3441 : // water flow velocity - assuming number of water circuits = NumOfTubesPerRow
3442 3234914 : TubeWaterVel = WaterMassFlowRate * 4.0 /
3443 3234914 : (state.dataWaterCoils->WaterCoil(CoilNum).NumOfTubesPerRow * rho * DataGlobalConstants::Pi *
3444 3234914 : state.dataWaterCoils->WaterCoil(CoilNum).TubeInsideDiam * state.dataWaterCoils->WaterCoil(CoilNum).TubeInsideDiam);
3445 : // air mass flow rate per unit area
3446 1617457 : ScaledAirMassFlowRate = (1.0 + InletAirHumRat) * AirMassFlow / state.dataWaterCoils->WaterCoil(CoilNum).MinAirFlowArea;
3447 : // air flow Reynold's Number
3448 1617457 : AirReynoldsNo = state.dataWaterCoils->WaterCoil(CoilNum).CoilEffectiveInsideDiam * ScaledAirMassFlowRate / AirViscosity;
3449 : // heat transfer coefficients and resistance components:
3450 : // inside (water)
3451 3234914 : WaterToTubeThermResist = std::pow(state.dataWaterCoils->WaterCoil(CoilNum).TubeInsideDiam, 0.2) /
3452 1617457 : (state.dataWaterCoils->WaterCoil(CoilNum).TotTubeInsideArea * 1.429 * std::pow(TubeWaterVel, 0.8));
3453 : // metal and fouling
3454 1617457 : TubeFoulThermResist =
3455 3234914 : (0.5 * (state.dataWaterCoils->WaterCoil(CoilNum).TubeOutsideDiam - state.dataWaterCoils->WaterCoil(CoilNum).TubeInsideDiam) /
3456 3234914 : (ConvK * state.dataWaterCoils->WaterCoil(CoilNum).TubeThermConductivity) +
3457 : TubeFoulFactor) /
3458 1617457 : state.dataWaterCoils->WaterCoil(CoilNum).TotTubeInsideArea;
3459 : // outside (wet and dry coil)
3460 1617457 : FilmCoefEqnFactor =
3461 1617457 : state.dataWaterCoils->WaterCoil(CoilNum).GeometryCoef1 * std::pow(AirReynoldsNo, state.dataWaterCoils->WaterCoil(CoilNum).GeometryCoef2);
3462 : // (1.23 is 1/Prandt(air)**(2/3))
3463 1617457 : AirSideDrySurfFilmCoef = 1.23 * FilmCoefEqnFactor * MoistAirSpecificHeat * ScaledAirMassFlowRate;
3464 1617457 : FilmCoefReynldsCorrelatnFact = 1.425 + AirReynoldsNo * (-0.51e-3 + AirReynoldsNo * 0.263e-6);
3465 : // NOTE: the equation for FilmCoefReynldsCorrelatnFact generates valid results over
3466 : // a limited range of Air Reynolds Numbers as indicated by
3467 : // deleted code below. Reynolds Numbers outside this range
3468 : // may result in inaccurate results or failure of the coil
3469 : // simulation to obtain a solution
3470 : // Deleted code by J.C. Vanderzee
3471 :
3472 1617457 : AirSideWetSurfFilmCoef = FilmCoefReynldsCorrelatnFact * AirSideDrySurfFilmCoef;
3473 : //-- need wet fin efficiency for outside
3474 1617457 : RaisedInletWaterTemp = TempWaterIn + 0.5;
3475 :
3476 : // By this statement the Inlet Air enthalpy will never be equal to AirEnthAtRsdInletWaterTemp
3477 1617457 : if ((RaisedInletWaterTemp - TempAirIn) < 0.000001) {
3478 1617287 : RaisedInletWaterTemp = TempWaterIn + 0.3;
3479 : }
3480 1617457 : if (TempAirIn < RaisedInletWaterTemp) {
3481 170 : RaisedInletWaterTemp = TempAirIn - 0.3;
3482 : }
3483 :
3484 1617457 : RsdInletWaterTempSatAirHumRat = PsyWFnTdbRhPb(state, RaisedInletWaterTemp, unity, state.dataEnvrn->OutBaroPress, RoutineName);
3485 1617457 : AirEnthAtRsdInletWaterTemp = PsyHFnTdbW(RaisedInletWaterTemp, RsdInletWaterTempSatAirHumRat) * ConvK;
3486 :
3487 1617457 : SensToTotEnthDiffRatio = DryAirSpecHeat * (TempAirIn - RaisedInletWaterTemp) / (InletAirEnthalpy - AirEnthAtRsdInletWaterTemp);
3488 :
3489 1617457 : EnterAirHumRatDiff = InletAirHumRat - RsdInletWaterTempSatAirHumRat;
3490 1617457 : DryFinEfficncy =
3491 1617457 : 0.5 * (state.dataWaterCoils->WaterCoil(CoilNum).EffectiveFinDiam - state.dataWaterCoils->WaterCoil(CoilNum).TubeOutsideDiam) *
3492 1617457 : std::sqrt(
3493 1617457 : 2.0 * AirSideWetSurfFilmCoef /
3494 1617457 : (ConvK * state.dataWaterCoils->WaterCoil(CoilNum).FinThermConductivity * state.dataWaterCoils->WaterCoil(CoilNum).FinThickness));
3495 1617457 : if (EnterAirHumRatDiff < 0) {
3496 : // note that this condition indicates dry coil
3497 63730 : EnterAirHumRatDiff = -EnterAirHumRatDiff;
3498 63730 : SensToTotEnthDiffRatio = std::abs(SensToTotEnthDiffRatio);
3499 : }
3500 :
3501 1617457 : if (EnterAirHumRatDiff > 1.0) {
3502 0 : EnterAirHumRatDiff = 1.0;
3503 1617457 : } else if (EnterAirHumRatDiff < 0.00001) {
3504 828 : EnterAirHumRatDiff = 0.00001;
3505 : }
3506 :
3507 1617457 : if (DryFinEfficncy > 1.0) {
3508 0 : DryFinEfficncy = 1.0;
3509 1617457 : } else if (DryFinEfficncy < 0.00001) {
3510 0 : DryFinEfficncy = 0.00001;
3511 : }
3512 :
3513 1617457 : if (TempAirIn > 48.0 / 1.8) {
3514 161103 : WetFinEfficncy =
3515 161103 : exp_47 * std::pow(SensToTotEnthDiffRatio, 0.09471) * std::pow(EnterAirHumRatDiff, 0.0108) * std::pow(DryFinEfficncy, -0.50303);
3516 : } else {
3517 1456354 : WetFinEfficncy =
3518 1456354 : exp_35 * std::pow(SensToTotEnthDiffRatio, 0.16081) * std::pow(EnterAirHumRatDiff, 0.01995) * std::pow(DryFinEfficncy, -0.52951);
3519 : }
3520 :
3521 1617457 : if (WetFinEfficncy > 1.0) WetFinEfficncy = 0.99;
3522 1617457 : if (WetFinEfficncy < 0.0) WetFinEfficncy = 0.001;
3523 : // wet coil fin efficiency
3524 :
3525 1617457 : WetCoilFinEfficncy = 1.0 + FinToTotSurfAreaRatio * (WetFinEfficncy - 1.0);
3526 : // wet coil outside thermal resistance = [1/UA] (wet coil)
3527 1617457 : CoilToAirThermResistWetSurf =
3528 1617457 : MoistAirSpecificHeat / (state.dataWaterCoils->WaterCoil(CoilNum).TotCoilOutsideSurfArea * AirSideWetSurfFilmCoef * WetCoilFinEfficncy);
3529 : //-- and dry fin efficiency
3530 1617457 : DryFinEfficncy =
3531 1617457 : 0.5 * (state.dataWaterCoils->WaterCoil(CoilNum).EffectiveFinDiam - state.dataWaterCoils->WaterCoil(CoilNum).TubeOutsideDiam) *
3532 1617457 : std::sqrt(
3533 1617457 : 2.0 * AirSideDrySurfFilmCoef /
3534 1617457 : (ConvK * state.dataWaterCoils->WaterCoil(CoilNum).FinThermConductivity * state.dataWaterCoils->WaterCoil(CoilNum).FinThickness));
3535 : // NOTE: The same caveats on the validity of the FilmCoefReynldsCorrelatnFact equation
3536 : // hold for the DryFinEfficncy equation. Values of DryFinEfficncy outside the
3537 : // specified range of validity are not guaranteed to
3538 : // produce results
3539 : // Deleted code by J.C. Vanderzee
3540 : // dry coil fin efficiency
3541 1617457 : DryCoilEfficiency = 0.0;
3542 : // Tuned Replaced by below to eliminate pow calls
3543 : // for ( CoefPointer = 1; CoefPointer <= 5; ++CoefPointer ) {
3544 : // DryCoilEfficiency += WaterCoil( CoilNum ).DryFinEfficncyCoef( CoefPointer ) * std::pow(
3545 : // DryFinEfficncy,
3546 : // CoefPointer
3547 : //-
3548 : // 1
3549 : //); } // CoefPointer
3550 1617457 : auto const &dry_fin_eff_coef(state.dataWaterCoils->WaterCoil(CoilNum).DryFinEfficncyCoef);
3551 1617457 : auto DryFinEfficncy_pow(1.0);
3552 9704742 : for (CoefPointer = 1; CoefPointer <= 5; ++CoefPointer) {
3553 8087285 : DryCoilEfficiency += dry_fin_eff_coef(CoefPointer) * DryFinEfficncy_pow;
3554 8087285 : DryFinEfficncy_pow *= DryFinEfficncy;
3555 : } // CoefPointer
3556 1617457 : DryCoilEfficiency = 1.0 + FinToTotSurfAreaRatio * (DryCoilEfficiency - 1.0);
3557 : // dry coil outside thermal resistance = [1/UA] (dry coil)
3558 1617457 : CoilToAirThermResistDrySurf =
3559 1617457 : 1.0 / (state.dataWaterCoils->WaterCoil(CoilNum).TotCoilOutsideSurfArea * AirSideDrySurfFilmCoef * DryCoilEfficiency);
3560 : // definitions made to simplify some of the expressions used below
3561 3234914 : Cp = GetSpecificHeatGlycol(state,
3562 1617457 : state.dataPlnt->PlantLoop(state.dataWaterCoils->WaterCoil(CoilNum).WaterPlantLoc.loopNum).FluidName,
3563 : TempWaterIn,
3564 1617457 : state.dataPlnt->PlantLoop(state.dataWaterCoils->WaterCoil(CoilNum).WaterPlantLoc.loopNum).FluidIndex,
3565 : RoutineName);
3566 1617457 : ScaledWaterSpecHeat = WaterMassFlowRate * Cp * ConvK / AirMassFlow;
3567 1617457 : DryCoilCoeff1 = 1.0 / (AirMassFlow * MoistAirSpecificHeat) - 1.0 / (WaterMassFlowRate * Cp * ConvK);
3568 : // perform initialisations for all wet solution
3569 1617457 : WetSideEffctvWaterTemp =
3570 1617457 : state.dataWaterCoils->WaterCoil(CoilNum).MeanWaterTempSaved + (TempWaterIn - state.dataWaterCoils->WaterCoil(CoilNum).InWaterTempSaved);
3571 1617457 : WaterTempConvgLoop = 0;
3572 1617457 : WaterTempConvg = false;
3573 : // Loop to solve coil as if all wet, converges on MeanWaterTemp eq WetSideEffctvWaterTemp
3574 : // if conv=.TRUE. at any time program exits loop and proceeds
3575 : // to part wet / part dry solution
3576 6630525 : while (WaterTempConvgLoop < 8 && !WaterTempConvg) {
3577 2506534 : ++WaterTempConvgLoop;
3578 2506534 : ScaledWaterToTubeThermResist = WaterToTubeThermResist / (1.0 + 0.0146 * WetSideEffctvWaterTemp);
3579 2506534 : ScaledCoilAirThermResistWetSurf = CoilToAirThermResistWetSurf / state.dataWaterCoils->WaterCoil(CoilNum).SatEnthlCurveSlope;
3580 5013068 : UACoilAllWet = 1.0 / (state.dataWaterCoils->WaterCoil(CoilNum).SatEnthlCurveSlope *
3581 2506534 : (TubeFoulThermResist + ScaledWaterToTubeThermResist + ScaledCoilAirThermResistWetSurf));
3582 : // prevents floating point error when taking exponential
3583 : // of a very large number
3584 2506534 : expon =
3585 2506534 : UACoilAllWet * (1.0 / AirMassFlow - state.dataWaterCoils->WaterCoil(CoilNum).SatEnthlCurveSlope / (WaterMassFlowRate * Cp * ConvK));
3586 2506534 : if (expon < 20.0) { // CR7189 changed from ABS(expon) < 20
3587 : // negative expon can happen, but lead to tiny WetCoilCoef that aren't a problem
3588 2506430 : WetCoilCoeff = std::exp(expon);
3589 : // following appears similar to eq. 320 in Eng Ref but neglects K1 term
3590 7519290 : TempWaterOut = ((1.0 - WetCoilCoeff) * (InletAirEnthalpy - state.dataWaterCoils->WaterCoil(CoilNum).SatEnthlCurveConstCoef) +
3591 2506430 : WetCoilCoeff * TempWaterIn * (state.dataWaterCoils->WaterCoil(CoilNum).SatEnthlCurveSlope - ScaledWaterSpecHeat)) /
3592 2506430 : (state.dataWaterCoils->WaterCoil(CoilNum).SatEnthlCurveSlope - WetCoilCoeff * ScaledWaterSpecHeat);
3593 : } else {
3594 : // following appears to be same as above with equation simplified to use only significant terms when WetCoilCoeff very large
3595 208 : TempWaterOut = ((InletAirEnthalpy - state.dataWaterCoils->WaterCoil(CoilNum).SatEnthlCurveConstCoef) -
3596 104 : TempWaterIn * (state.dataWaterCoils->WaterCoil(CoilNum).SatEnthlCurveSlope - ScaledWaterSpecHeat)) /
3597 : ScaledWaterSpecHeat;
3598 : }
3599 : // above is inverted form of WaterMassFlowRate*cpw*(TempWaterOut-TempWaterIn) = UA(LMHD)
3600 : // note simplification that hsat = WaterCoil(CoilNum)%SatEnthlCurveConstCoef + &
3601 : // WaterCoil(CoilNum)%SatEnthlCurveSlope*WetSideEffctvWaterTemp
3602 2506534 : MeanWaterTemp = 0.5 * (TempWaterIn + TempWaterOut);
3603 2506534 : OutletAirEnthalpy = InletAirEnthalpy - (TempWaterOut - TempWaterIn) * ScaledWaterSpecHeat;
3604 :
3605 2506534 : InsdToOutsdThermResistRatio = (TubeFoulThermResist + ScaledWaterToTubeThermResist) / ScaledCoilAirThermResistWetSurf;
3606 5013068 : InCoilSurfTemp = UACoilAllWet * ScaledCoilAirThermResistWetSurf *
3607 5013068 : (state.dataWaterCoils->WaterCoil(CoilNum).SatEnthlCurveSlope * TempWaterIn +
3608 2506534 : (OutletAirEnthalpy - state.dataWaterCoils->WaterCoil(CoilNum).SatEnthlCurveConstCoef) * InsdToOutsdThermResistRatio);
3609 5013068 : OutCoilSurfTemp = UACoilAllWet * ScaledCoilAirThermResistWetSurf *
3610 5013068 : (state.dataWaterCoils->WaterCoil(CoilNum).SatEnthlCurveSlope * TempWaterOut +
3611 2506534 : (InletAirEnthalpy - state.dataWaterCoils->WaterCoil(CoilNum).SatEnthlCurveConstCoef) * InsdToOutsdThermResistRatio);
3612 :
3613 2506534 : if (std::abs(MeanWaterTemp - WetSideEffctvWaterTemp) > 0.01) {
3614 889077 : WetSideEffctvWaterTemp = MeanWaterTemp;
3615 889077 : InSurfTempSatAirEnthl = PsyHFnTdbRhPb(state, InCoilSurfTemp, unity, state.dataEnvrn->OutBaroPress, RoutineName) * ConvK;
3616 889077 : OutSurfTempSatAirEnthl = PsyHFnTdbRhPb(state, OutCoilSurfTemp, unity, state.dataEnvrn->OutBaroPress, RoutineName) * ConvK;
3617 :
3618 889077 : state.dataWaterCoils->WaterCoil(CoilNum).SatEnthlCurveSlope =
3619 889077 : (OutSurfTempSatAirEnthl - InSurfTempSatAirEnthl) / (OutCoilSurfTemp - InCoilSurfTemp);
3620 889077 : state.dataWaterCoils->WaterCoil(CoilNum).SatEnthlCurveConstCoef =
3621 889077 : InSurfTempSatAirEnthl - state.dataWaterCoils->WaterCoil(CoilNum).SatEnthlCurveSlope * InCoilSurfTemp;
3622 : } else {
3623 1617457 : WaterTempConvg = true;
3624 : }
3625 : } // End of iteration loop to get MeanWaterTemp=WetSideEffctvWaterTemp
3626 : // if 8 CoolCoilErrs are reached without convergence and the
3627 : // predicted coil surface temperature at the outlet is less than
3628 : // the dew point coil is apparently all wet but a solution
3629 : // cannot be obtained
3630 1617457 : if (!WaterTempConvg && !state.dataGlobal->WarmupFlag && (OutCoilSurfTemp < EnterAirDewPoint)) {
3631 0 : ShowRecurringWarningErrorAtEnd(state,
3632 0 : state.dataWaterCoils->WaterCoil(CoilNum).Name +
3633 : " not converged (8 iterations) due to \"Wet Convergence\" conditions.",
3634 0 : state.dataWaterCoils->WaterTempCoolCoilErrs(CoilNum),
3635 0 : std::abs(MeanWaterTemp - WetSideEffctvWaterTemp),
3636 0 : std::abs(MeanWaterTemp - WetSideEffctvWaterTemp));
3637 : // CoolCoilErrs = CoolCoilErrs + 1
3638 : // IF (CoolCoilErrs .LE. MaxCoolCoilErrs) THEN
3639 : // CALL ShowWarningError(state, 'tp12c0: not converged in 8 CoolCoilErrs')
3640 : // END IF
3641 : }
3642 1617457 : state.dataWaterCoils->WaterCoil(CoilNum).MeanWaterTempSaved = MeanWaterTemp;
3643 : // now simulate wet dry coil - test outlet condition from all
3644 : // wet case to give an idea of the expected solution
3645 1617457 : PartWetIterations = 0;
3646 1617457 : WetDryInterSurfTempError = 0.0;
3647 1617457 : CoilPartWetConvg = false;
3648 : // Surface temp at coil water outlet (air inlet) is less than
3649 : // the dew point - Coil must be completely wet so no need to
3650 : // simulate wet/dry case
3651 1617457 : if (OutCoilSurfTemp < EnterAirDewPoint) {
3652 234586 : CoilPartWetConvg = true;
3653 234586 : state.dataWaterCoils->WaterCoil(CoilNum).SurfAreaWetFraction = 1.0;
3654 234586 : TotWaterCoilLoad = AirMassFlow * (InletAirEnthalpy - OutletAirEnthalpy);
3655 234586 : AirWetDryInterfcTemp = TempAirIn;
3656 234586 : WetDryInterfcAirEnthl = InletAirEnthalpy;
3657 : // Surface temperature at coil water inlet is greater than the
3658 : // dewpoint - coil cannot be all wet but may be all dry -
3659 : // initialise with all dry solution
3660 1382871 : } else if (InCoilSurfTemp > EnterAirDewPoint) {
3661 219512 : SurfAreaWet = 0.0;
3662 219512 : state.dataWaterCoils->WaterCoil(CoilNum).SurfAreaWetFraction = 0.0;
3663 219512 : WetDryInterfcWaterTemp = TempWaterIn;
3664 439024 : TempWaterOut = state.dataWaterCoils->WaterCoil(CoilNum).OutWaterTempSaved +
3665 219512 : (TempWaterIn - state.dataWaterCoils->WaterCoil(CoilNum).InWaterTempSaved);
3666 219512 : WetAreaLast = 0.05 * state.dataWaterCoils->WaterCoil(CoilNum).TotCoilOutsideSurfArea;
3667 : // General case - must be part-wet/part-dry - initialise
3668 : // accordingly with some non-zero wet area
3669 : } else {
3670 1163359 : if (state.dataWaterCoils->WaterCoil(CoilNum).SurfAreaWetSaved != 0.0) {
3671 1162506 : SurfAreaWet = state.dataWaterCoils->WaterCoil(CoilNum).SurfAreaWetSaved;
3672 : } else {
3673 1706 : SurfAreaWet = 0.8 * state.dataWaterCoils->WaterCoil(CoilNum).TotCoilOutsideSurfArea * (EnterAirDewPoint - InCoilSurfTemp) /
3674 853 : (OutCoilSurfTemp - InCoilSurfTemp);
3675 : }
3676 1163359 : WetDryInterfcWaterTemp = TempWaterIn + EnterAirDewPoint - InCoilSurfTemp;
3677 1163359 : WetAreaLast = 0.0;
3678 : }
3679 : // Loop to solve partly wet coil, converges on wet area and
3680 : // boundary temperature at dew point
3681 : // Dry coil is special case with zero wet area, converges on
3682 : // mean water temperature
3683 21371069 : while (PartWetIterations < 40 && !CoilPartWetConvg) {
3684 9876806 : ++PartWetIterations;
3685 : // effective water temp on dry side of coil
3686 9876806 : DrySideEffectiveWaterTemp = 0.5 * (TempWaterOut + WetDryInterfcWaterTemp);
3687 : // tube inside thermal resistance
3688 9876806 : DryCoilInThermResist = WaterToTubeThermResist / (1.0 + 0.0146 * DrySideEffectiveWaterTemp);
3689 : // overall UA, from water to air, of dry portion of coil
3690 :
3691 19753612 : UADryCoil = (state.dataWaterCoils->WaterCoil(CoilNum).TotCoilOutsideSurfArea - SurfAreaWet) /
3692 19753612 : (state.dataWaterCoils->WaterCoil(CoilNum).TotCoilOutsideSurfArea *
3693 9876806 : (TubeFoulThermResist + DryCoilInThermResist + CoilToAirThermResistDrySurf));
3694 :
3695 : // This is a numerical trap for a very small number in the EXP function that is approaching zero
3696 9876806 : if (UADryCoil * DryCoilCoeff1 < -60.0) {
3697 0 : DryCoilCoeff = 0.0;
3698 : } else {
3699 9876806 : DryCoilCoeff = std::exp(UADryCoil * DryCoilCoeff1);
3700 : }
3701 :
3702 19753612 : K1 = WaterMassFlowRate * Cp * ConvK * (DryCoilCoeff - 1.0) /
3703 9876806 : (WaterMassFlowRate * Cp * ConvK * DryCoilCoeff - AirMassFlow * MoistAirSpecificHeat);
3704 9876806 : if (SurfAreaWet != 0) {
3705 9391660 : state.dataWaterCoils->WaterCoil(CoilNum).SurfAreaWetFraction =
3706 9391660 : SurfAreaWet / state.dataWaterCoils->WaterCoil(CoilNum).TotCoilOutsideSurfArea;
3707 : // effective water temp on wet side of coil
3708 9391660 : WetSideEffctvWaterTemp = 0.5 * (TempWaterIn + WetDryInterfcWaterTemp);
3709 : // tube inside thermal resistance
3710 9391660 : ScaledWaterToTubeThermResist = WaterToTubeThermResist / (1.0 + 0.0146 * WetSideEffctvWaterTemp);
3711 9391660 : ScaledCoilAirThermResistWetSurf = CoilToAirThermResistWetSurf / state.dataWaterCoils->WaterCoil(CoilNum).EnthVsTempCurveAppxSlope;
3712 : // overall UA, from water to air, of wet portion of coil
3713 18783320 : UACoilAllWet = 1.0 / (state.dataWaterCoils->WaterCoil(CoilNum).EnthVsTempCurveAppxSlope *
3714 9391660 : (TubeFoulThermResist + ScaledWaterToTubeThermResist + ScaledCoilAirThermResistWetSurf));
3715 9391660 : UACoilPartWet = state.dataWaterCoils->WaterCoil(CoilNum).SurfAreaWetFraction * UACoilAllWet;
3716 9391660 : expon = UACoilPartWet *
3717 9391660 : (1.0 / AirMassFlow - state.dataWaterCoils->WaterCoil(CoilNum).EnthVsTempCurveAppxSlope / (WaterMassFlowRate * Cp * ConvK));
3718 : // prevents floating point error when taking exponential
3719 : // of a very large number
3720 9391660 : if (expon < 20.0) {
3721 9391660 : WetCoilCoeff = std::exp(expon);
3722 : // write(outputfiledebug,*) ' wcc=',wetcoilcoeff
3723 18783320 : denom = (state.dataWaterCoils->WaterCoil(CoilNum).EnthVsTempCurveAppxSlope - WetCoilCoeff * ScaledWaterSpecHeat -
3724 9391660 : (1.0 - WetCoilCoeff) * K1 * MoistAirSpecificHeat);
3725 : // write(outputfiledebug,*) ' denom=',denom
3726 : // WetDryInterfcWaterTemp = ((1.0 - WetCoilCoeff) * (InletAirEnthalpy - WaterCoil(CoilNum)%EnthVsTempCurveConst -
3727 : // K1
3728 : // * &
3729 : // MoistAirSpecificHeat * TempAirIn) + WetCoilCoeff * &
3730 : // TempWaterIn * (WaterCoil(CoilNum)%EnthVsTempCurveAppxSlope - &
3731 : // ScaledWaterSpecHeat)) / (WaterCoil(CoilNum)%EnthVsTempCurveAppxSlope - &
3732 : // WetCoilCoeff * ScaledWaterSpecHeat - (1.0 - WetCoilCoeff) * K1 * &
3733 : // MoistAirSpecificHeat)
3734 9391660 : WetDryInterfcWaterTemp =
3735 18783320 : ((1.0 - WetCoilCoeff) * (InletAirEnthalpy - state.dataWaterCoils->WaterCoil(CoilNum).EnthVsTempCurveConst -
3736 18783320 : K1 * MoistAirSpecificHeat * TempAirIn) +
3737 9391660 : WetCoilCoeff * TempWaterIn * (state.dataWaterCoils->WaterCoil(CoilNum).EnthVsTempCurveAppxSlope - ScaledWaterSpecHeat)) /
3738 : denom;
3739 : } else {
3740 : // approximation to equation for WetDryInterfcWaterTemp when WetCoilCoeff-->inf.
3741 0 : WetDryInterfcWaterTemp =
3742 0 : (TempWaterIn * (state.dataWaterCoils->WaterCoil(CoilNum).EnthVsTempCurveAppxSlope - ScaledWaterSpecHeat) -
3743 0 : (InletAirEnthalpy - state.dataWaterCoils->WaterCoil(CoilNum).EnthVsTempCurveConst - K1 * MoistAirSpecificHeat * TempAirIn)) /
3744 0 : (K1 * MoistAirSpecificHeat - ScaledWaterSpecHeat);
3745 : }
3746 : }
3747 : // air temperature at wet-dry interface
3748 9876806 : AirWetDryInterfcTemp = TempAirIn - (TempAirIn - WetDryInterfcWaterTemp) * K1;
3749 : // coil surface temperature at wet-dry interface
3750 29630418 : WetDryInterfcSurfTemp = WetDryInterfcWaterTemp + (AirWetDryInterfcTemp - WetDryInterfcWaterTemp) *
3751 19753612 : (TubeFoulThermResist + DryCoilInThermResist) /
3752 9876806 : (TubeFoulThermResist + DryCoilInThermResist + CoilToAirThermResistDrySurf);
3753 9876806 : if (SurfAreaWet != 0) {
3754 9391660 : WetDryInterfcAirEnthl = InletAirEnthalpy - MoistAirSpecificHeat * (TempAirIn - AirWetDryInterfcTemp);
3755 : // conservation of energy - wet portion of coil
3756 9391660 : OutletAirEnthalpy = WetDryInterfcAirEnthl - WaterMassFlowRate * Cp * ConvK * (WetDryInterfcWaterTemp - TempWaterIn) / AirMassFlow;
3757 : // ratio of inside to outside thermal resistance
3758 9391660 : InsdToOutsdThermResistRatio = (TubeFoulThermResist + ScaledWaterToTubeThermResist) / ScaledCoilAirThermResistWetSurf;
3759 : // coil surface temperature at water inlet (air outlet)
3760 18783320 : InCoilSurfTemp = UACoilAllWet * ScaledCoilAirThermResistWetSurf *
3761 18783320 : (state.dataWaterCoils->WaterCoil(CoilNum).EnthVsTempCurveAppxSlope * TempWaterIn +
3762 9391660 : (OutletAirEnthalpy - state.dataWaterCoils->WaterCoil(CoilNum).EnthVsTempCurveConst) * InsdToOutsdThermResistRatio);
3763 9391660 : WetDryInterSurfTempErrorLast = WetDryInterSurfTempError;
3764 : // in part-wet/part-dry solution EnterAirDewPoint=WetDryInterfcSurfTemp drives WetDryInterSurfTempError->0
3765 9391660 : WetDryInterSurfTempError = EnterAirDewPoint - WetDryInterfcSurfTemp;
3766 : } else {
3767 : // dry coil solution
3768 485146 : WetDryInterfcAirEnthl = 0.0;
3769 485146 : OutletAirEnthalpy = InletAirEnthalpy - MoistAirSpecificHeat * (TempAirIn - AirWetDryInterfcTemp);
3770 : }
3771 : // total cooling = change in air enthalpy across coil
3772 9876806 : TotWaterCoilLoad = AirMassFlow * (InletAirEnthalpy - OutletAirEnthalpy);
3773 : // conservation of energy on water stream gives water outlet
3774 : // temperature
3775 9876806 : TempWaterOut = WaterMassFlowRate * Cp * ConvK; // Temp for next calc
3776 9876806 : TempWaterOut = min(TempWaterIn + TotWaterCoilLoad / TempWaterOut, TempAirIn);
3777 : // update estimate of coil wet area
3778 :
3779 9876806 : if (SurfAreaWet == 0) {
3780 485146 : MeanWaterTemp = 0.5 * (TempWaterOut + WetDryInterfcWaterTemp);
3781 485146 : if (EnterAirDewPoint > WetDryInterfcSurfTemp) {
3782 92090 : SurfAreaWet = 0.5 * WetAreaLast;
3783 393056 : } else if (std::abs(MeanWaterTemp - DrySideEffectiveWaterTemp) <= 0.00002) {
3784 128742 : CoilPartWetConvg = true;
3785 : }
3786 10699197 : } else if (std::abs(WetDryInterSurfTempError) > 0.00002 ||
3787 1307537 : std::abs(SurfAreaWet - WetAreaLast) / state.dataWaterCoils->WaterCoil(CoilNum).TotCoilOutsideSurfArea > 0.00001) {
3788 8154040 : if (WetAreaLast == 0) {
3789 1163359 : WetAreaLast = SurfAreaWet;
3790 2326718 : SurfAreaWet += 0.4 * state.dataWaterCoils->WaterCoil(CoilNum).TotCoilOutsideSurfArea * WetDryInterSurfTempError /
3791 1163359 : (OutCoilSurfTemp - InCoilSurfTemp);
3792 6990681 : } else if (WetDryInterSurfTempError != WetDryInterSurfTempErrorLast) {
3793 6990681 : WetAreaChange = SurfAreaWet - WetAreaLast;
3794 6990681 : WetAreaLast = SurfAreaWet;
3795 6990681 : SurfAreaWet -= 0.8 * WetDryInterSurfTempError * WetAreaChange / (WetDryInterSurfTempError - WetDryInterSurfTempErrorLast);
3796 : }
3797 8154040 : if (SurfAreaWet >= state.dataWaterCoils->WaterCoil(CoilNum).TotCoilOutsideSurfArea) {
3798 80734 : SurfAreaWet = state.dataWaterCoils->WaterCoil(CoilNum).TotCoilOutsideSurfArea;
3799 80734 : MeanWaterTemp = 0.5 * (TempWaterIn + WetDryInterfcWaterTemp);
3800 140412 : if (WetAreaLast == state.dataWaterCoils->WaterCoil(CoilNum).TotCoilOutsideSurfArea &&
3801 59678 : std::abs(MeanWaterTemp - WetSideEffctvWaterTemp) <= 0.00002) {
3802 16509 : CoilPartWetConvg = true;
3803 : }
3804 : }
3805 8154040 : if (SurfAreaWet <= 0) {
3806 1320 : SurfAreaWet = 0.0;
3807 1320 : state.dataWaterCoils->WaterCoil(CoilNum).SurfAreaWetFraction = 0.0;
3808 1320 : WetDryInterfcWaterTemp = TempWaterIn;
3809 : }
3810 8154040 : InSurfTempSatAirEnthl = PsyHFnTdbRhPb(state, InCoilSurfTemp, unity, state.dataEnvrn->OutBaroPress, RoutineName) * ConvK;
3811 8154040 : if ((EnterAirDewPoint - InCoilSurfTemp) >= 0.0001) {
3812 8054607 : AirEnthAtWetDryIntrfcSurfTemp = PsyHFnTdbRhPb(state, EnterAirDewPoint, unity, state.dataEnvrn->OutBaroPress, RoutineName) * ConvK;
3813 8054607 : state.dataWaterCoils->WaterCoil(CoilNum).EnthVsTempCurveAppxSlope =
3814 8054607 : (AirEnthAtWetDryIntrfcSurfTemp - InSurfTempSatAirEnthl) / (EnterAirDewPoint - InCoilSurfTemp);
3815 : } else {
3816 99433 : AirEnthAtWetDryIntrfcSurfTemp =
3817 99433 : PsyHFnTdbRhPb(state, InCoilSurfTemp + 0.0001, unity, state.dataEnvrn->OutBaroPress, RoutineName) * ConvK;
3818 99433 : state.dataWaterCoils->WaterCoil(CoilNum).EnthVsTempCurveAppxSlope =
3819 99433 : (AirEnthAtWetDryIntrfcSurfTemp - InSurfTempSatAirEnthl) / 0.0001;
3820 : }
3821 8154040 : state.dataWaterCoils->WaterCoil(CoilNum).EnthVsTempCurveConst =
3822 8154040 : InSurfTempSatAirEnthl - state.dataWaterCoils->WaterCoil(CoilNum).EnthVsTempCurveAppxSlope * InCoilSurfTemp;
3823 : } else {
3824 1237620 : CoilPartWetConvg = true;
3825 : }
3826 : }
3827 : // error checking to see if convergence has been achieved
3828 1617457 : if (!CoilPartWetConvg && !state.dataGlobal->WarmupFlag) {
3829 0 : ShowRecurringWarningErrorAtEnd(state,
3830 0 : state.dataWaterCoils->WaterCoil(CoilNum).Name +
3831 : " not converged (40 iterations) due to \"Partial Wet Convergence\" conditions.",
3832 0 : state.dataWaterCoils->PartWetCoolCoilErrs(CoilNum));
3833 : // CoolCoilErrs = CoolCoilErrs + 1
3834 : // IF (CoolCoilErrs .LE. MaxCoolCoilErrs) THEN
3835 : // CALL ShowWarningError(state, 'tp12c0: not converged in 20 CoolCoilErrs')
3836 : // END IF
3837 : }
3838 1617457 : if (state.dataWaterCoils->WaterCoil(CoilNum).SurfAreaWetFraction > 0 && state.dataWaterCoils->WaterCoil(CoilNum).SurfAreaWetFraction < 1) {
3839 1237620 : state.dataWaterCoils->WaterCoil(CoilNum).SurfAreaWetSaved = SurfAreaWet;
3840 : }
3841 : // calculate TempAirOut, OutletAirHumRat, and SensCoolRate based on equations from
3842 : // TYPE12 and the ASHRAE toolkit
3843 1617457 : if (state.dataWaterCoils->WaterCoil(CoilNum).SurfAreaWetFraction == 0) {
3844 : // dry coil
3845 128742 : TempAirOut = TempAirIn - TotWaterCoilLoad / (AirMassFlow * MoistAirSpecificHeat);
3846 128742 : OutletAirHumRat = InletAirHumRat;
3847 128742 : SenWaterCoilLoad = TotWaterCoilLoad;
3848 : } else {
3849 : // coil effectiveness
3850 1488715 : expon = state.dataWaterCoils->WaterCoil(CoilNum).SurfAreaWetFraction / (CoilToAirThermResistWetSurf * AirMassFlow);
3851 1488715 : y = 0.0;
3852 1488715 : if (expon < 20.0) y = std::exp(-expon);
3853 1488715 : AirExitEnthlAtCoilSurfTemp = WetDryInterfcAirEnthl - (WetDryInterfcAirEnthl - OutletAirEnthalpy) / (1.0 - y);
3854 1488715 : AirExitCoilSurfTemp = AirExitEnthlAtCoilSurfTemp / ConvK; // TEmporary calc
3855 1488715 : AirExitCoilSurfTemp = PsyTsatFnHPb(state, AirExitCoilSurfTemp, state.dataEnvrn->OutBaroPress);
3856 : // Implementation of epsilon*NTU method
3857 1488715 : TempAirOut = AirExitCoilSurfTemp + (AirWetDryInterfcTemp - AirExitCoilSurfTemp) * y;
3858 1488715 : OutletAirHumRat = PsyWFnTdbH(state, TempAirOut, 1000.0 * OutletAirEnthalpy, RoutineName);
3859 1488715 : SenWaterCoilLoad = AirMassFlow * (PsyCpAirFnW(InletAirHumRat) * TempAirIn - PsyCpAirFnW(OutletAirHumRat) * TempAirOut) * ConvK;
3860 : }
3861 :
3862 1617457 : if (FanOpMode == CycFanCycCoil) {
3863 0 : TotWaterCoilLoad *= PartLoadRatio;
3864 0 : SenWaterCoilLoad *= PartLoadRatio;
3865 : }
3866 :
3867 : // Set the outlet conditions
3868 1617457 : state.dataWaterCoils->WaterCoil(CoilNum).TotWaterCoolingCoilRate = TotWaterCoilLoad * 1000.0;
3869 1617457 : state.dataWaterCoils->WaterCoil(CoilNum).SenWaterCoolingCoilRate = SenWaterCoilLoad * 1000.0;
3870 1617457 : state.dataWaterCoils->WaterCoil(CoilNum).OutletAirTemp = TempAirOut;
3871 1617457 : state.dataWaterCoils->WaterCoil(CoilNum).OutletWaterTemp = TempWaterOut;
3872 1617457 : state.dataWaterCoils->WaterCoil(CoilNum).OutletAirEnthalpy = OutletAirEnthalpy * 1000.0;
3873 1617457 : state.dataWaterCoils->WaterCoil(CoilNum).OutletAirHumRat = OutletAirHumRat;
3874 : // The CoolingCoilLoad is the change in the enthalpy of the water
3875 1617457 : state.dataWaterCoils->WaterCoil(CoilNum).OutletWaterEnthalpy =
3876 3234914 : state.dataWaterCoils->WaterCoil(CoilNum).InletWaterEnthalpy +
3877 1617457 : state.dataWaterCoils->WaterCoil(CoilNum).TotWaterCoolingCoilRate / state.dataWaterCoils->WaterCoil(CoilNum).InletWaterMassFlowRate;
3878 :
3879 : // This WaterCoil does not change the Mass Flow across the component
3880 1617457 : state.dataWaterCoils->WaterCoil(CoilNum).OutletAirMassFlowRate = state.dataWaterCoils->WaterCoil(CoilNum).InletAirMassFlowRate;
3881 1617457 : state.dataWaterCoils->WaterCoil(CoilNum).OutletWaterMassFlowRate = state.dataWaterCoils->WaterCoil(CoilNum).InletWaterMassFlowRate;
3882 : } else {
3883 : // If Coil is scheduled OFF then Outlet conditions are set to Inlet Conditions
3884 1720499 : state.dataWaterCoils->WaterCoil(CoilNum).TotWaterCoolingCoilRate = 0.0;
3885 1720499 : state.dataWaterCoils->WaterCoil(CoilNum).SenWaterCoolingCoilRate = 0.0;
3886 1720499 : TempAirOut = TempAirIn;
3887 1720499 : TempWaterOut = TempWaterIn;
3888 : // set the outlet conditions to the coil derived type
3889 1720499 : state.dataWaterCoils->WaterCoil(CoilNum).OutletAirTemp = TempAirOut;
3890 1720499 : state.dataWaterCoils->WaterCoil(CoilNum).OutletWaterTemp = TempWaterOut;
3891 1720499 : state.dataWaterCoils->WaterCoil(CoilNum).OutletAirEnthalpy = state.dataWaterCoils->WaterCoil(CoilNum).InletAirEnthalpy;
3892 1720499 : state.dataWaterCoils->WaterCoil(CoilNum).OutletAirHumRat = state.dataWaterCoils->WaterCoil(CoilNum).InletAirHumRat;
3893 : // The CoolingCoilLoad is the change in the enthalpy of the water
3894 1720499 : state.dataWaterCoils->WaterCoil(CoilNum).OutletWaterEnthalpy = state.dataWaterCoils->WaterCoil(CoilNum).InletWaterEnthalpy;
3895 :
3896 : // This WaterCoil does not change the Mass Flow across the component
3897 1720499 : state.dataWaterCoils->WaterCoil(CoilNum).OutletAirMassFlowRate = state.dataWaterCoils->WaterCoil(CoilNum).InletAirMassFlowRate;
3898 1720499 : state.dataWaterCoils->WaterCoil(CoilNum).OutletWaterMassFlowRate = 0.0;
3899 : }
3900 :
3901 : // Save some of the Values for next Time step
3902 3337956 : state.dataWaterCoils->WaterCoil(CoilNum).InWaterTempSaved = TempWaterIn;
3903 3337956 : state.dataWaterCoils->WaterCoil(CoilNum).OutWaterTempSaved = TempWaterOut;
3904 3337956 : }
3905 :
3906 22054942 : void CoolingCoil(EnergyPlusData &state,
3907 : int const CoilNum,
3908 : bool const FirstHVACIteration,
3909 : int const CalcMode,
3910 : int const FanOpMode, // fan operating mode
3911 : Real64 const PartLoadRatio // part-load ratio of heating coil
3912 : )
3913 : {
3914 :
3915 : // FUNCTION INFORMATION:
3916 : // AUTHOR Rahul Chillar
3917 : // DATE WRITTEN Mar 2004
3918 : // MODIFIED na
3919 : // RE-ENGINEERED na
3920 :
3921 : // PURPOSE OF THIS FUNCTION:
3922 : // The subroutine has the coil logic. Three types of Cooling Coils exist:
3923 : // They are 1.CoilDry , 2.CoilWet, 3. CoilPartDryPartWet. The logic for
3924 : // the three individual cases is in this subroutine.
3925 :
3926 : // METHODOLOGY EMPLOYED:
3927 : // Simulates a Coil Model from Design conditions and subsequently uses
3928 : // configuration values (example: UA)calculated from those design conditions
3929 : // to calculate new performance of coil from operating inputs.The values are
3930 : // calculated in the Subroutine InitWaterCoil
3931 :
3932 : // REFERENCES:
3933 : // ASHRAE Secondary HVAC Toolkit TRNSYS. 1990. A Transient System
3934 : // Simulation Program: Reference Manual. Solar Energy Laboratory, Univ. Wisconsin-
3935 : // Madison, pp. 4.6.8-1 - 4.6.8-12.
3936 : // Threlkeld, J.L. 1970. Thermal Environmental Engineering, 2nd Edition,
3937 : // Englewood Cliffs: Prentice-Hall,Inc. pp. 254-270.
3938 :
3939 : // Using/Aliasing
3940 : using General::SafeDivide;
3941 :
3942 : // Enforce explicit typing of all variables in this routine
3943 :
3944 : // Locals
3945 : // FUNCTION ARGUMENT DEFINITIONS:
3946 :
3947 : // FUNCTION PARAMETER DEFINITIONS:
3948 : // na
3949 :
3950 : // INTERFACE BLOCK SPECIFICATIONS
3951 : // na
3952 :
3953 : // DERIVED TYPE DEFINITIONS
3954 : // na
3955 :
3956 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
3957 : Real64 AirInletCoilSurfTemp; // Coil surface temperature at air entrance(C)
3958 : Real64 AirDewPointTemp; // Temperature dew point at operating condition
3959 : Real64 OutletAirTemp; // Outlet air temperature at operating condition
3960 : Real64 OutletAirHumRat; // Outlet air humidity ratio at operating condition
3961 : Real64 OutletWaterTemp; // Outlet water temperature at operating condtitons
3962 : Real64 TotWaterCoilLoad; // Total heat transfer rate(W)
3963 : Real64 SenWaterCoilLoad; // Sensible heat transfer rate
3964 : Real64 SurfAreaWetFraction; // Fraction of surface area wet
3965 : Real64 AirMassFlowRate; // Air mass flow rate for the calculation
3966 :
3967 22054942 : AirInletCoilSurfTemp = 0.0; // Coil surface temperature at air entrance(C)
3968 22054942 : AirDewPointTemp = 0.0; // Temperature dew point at operating condition
3969 22054942 : OutletAirTemp = 0.0; // Outlet air temperature at operating condition
3970 22054942 : OutletAirHumRat = 0.0; // Outlet air humidity ratio at operating condition
3971 22054942 : OutletWaterTemp = 0.0; // Outlet water temperature at operating condtitons
3972 22054942 : TotWaterCoilLoad = 0.0; // Total heat transfer rate(W)
3973 22054942 : SenWaterCoilLoad = 0.0; // Sensible heat transfer rate
3974 22054942 : SurfAreaWetFraction = 0.0; // Fraction of surface area wet
3975 :
3976 22054942 : if (FanOpMode == CycFanCycCoil && PartLoadRatio > 0.0) { // FB Start
3977 1349120 : AirMassFlowRate = state.dataWaterCoils->WaterCoil(CoilNum).InletAirMassFlowRate / PartLoadRatio;
3978 : } else {
3979 20705822 : AirMassFlowRate = state.dataWaterCoils->WaterCoil(CoilNum).InletAirMassFlowRate;
3980 : }
3981 :
3982 : // If Coil is Scheduled ON then do the simulation
3983 65079296 : if (((GetCurrentScheduleValue(state, state.dataWaterCoils->WaterCoil(CoilNum).SchedPtr) > 0.0) &&
3984 45347556 : (state.dataWaterCoils->WaterCoil(CoilNum).InletWaterMassFlowRate > 0.0) && (AirMassFlowRate >= WaterCoils::MinAirMassFlow) &&
3985 24370060 : (state.dataWaterCoils->WaterCoil(CoilNum).DesAirVolFlowRate > 0.0) &&
3986 44109884 : (state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterMassFlowRate > 0.0)) ||
3987 9869912 : (CalcMode == state.dataWaterCoils->DesignCalc)) {
3988 :
3989 : // Calculate Temperature Dew Point at operating conditions.
3990 12186409 : AirDewPointTemp = PsyTdpFnWPb(state, state.dataWaterCoils->WaterCoil(CoilNum).InletAirHumRat, state.dataEnvrn->OutBaroPress);
3991 :
3992 12186409 : if (state.dataWaterCoils->WaterCoil(CoilNum).CoolingCoilAnalysisMode == state.dataWaterCoils->DetailedAnalysis) {
3993 : // Coil is completely dry if AirDewPointTemp is less than InletWaterTemp,hence Call CoilCompletelyDry
3994 890386 : if (AirDewPointTemp <= state.dataWaterCoils->WaterCoil(CoilNum).InletWaterTemp) {
3995 :
3996 : // Calculate the leaving conditions and performance of dry coil
3997 4452 : CoilCompletelyDry(state,
3998 : CoilNum,
3999 1484 : state.dataWaterCoils->WaterCoil(CoilNum).InletWaterTemp,
4000 1484 : state.dataWaterCoils->WaterCoil(CoilNum).InletAirTemp,
4001 1484 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilTotal,
4002 : OutletWaterTemp,
4003 : OutletAirTemp,
4004 : OutletAirHumRat,
4005 : TotWaterCoilLoad,
4006 : FanOpMode,
4007 : PartLoadRatio);
4008 :
4009 1484 : SenWaterCoilLoad = TotWaterCoilLoad;
4010 1484 : SurfAreaWetFraction = 0.0;
4011 :
4012 : } else {
4013 : // Else If AirDewPointTemp is greater than InletWaterTemp then assume the
4014 : // external surface of coil is completely wet,hence Call CoilCompletelyWet
4015 : // Calculate the leaving conditions and performance of wet coil
4016 4444510 : CoilCompletelyWet(state,
4017 : CoilNum,
4018 888902 : state.dataWaterCoils->WaterCoil(CoilNum).InletWaterTemp,
4019 888902 : state.dataWaterCoils->WaterCoil(CoilNum).InletAirTemp,
4020 888902 : state.dataWaterCoils->WaterCoil(CoilNum).InletAirHumRat,
4021 888902 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilInternal,
4022 888902 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilExternal,
4023 : OutletWaterTemp,
4024 : OutletAirTemp,
4025 : OutletAirHumRat,
4026 : TotWaterCoilLoad,
4027 : SenWaterCoilLoad,
4028 : SurfAreaWetFraction,
4029 : AirInletCoilSurfTemp,
4030 : FanOpMode,
4031 : PartLoadRatio);
4032 :
4033 : // If AirDewPointTemp is less than temp of coil surface at entry of air
4034 888902 : if (AirDewPointTemp < AirInletCoilSurfTemp) {
4035 :
4036 : // Then coil is partially wet and dry hence call CoilPartWetPartDry
4037 : // Calculate the leaving conditions and performance of dry coil
4038 1412438 : CoilPartWetPartDry(state,
4039 : CoilNum,
4040 : FirstHVACIteration,
4041 706219 : state.dataWaterCoils->WaterCoil(CoilNum).InletWaterTemp,
4042 706219 : state.dataWaterCoils->WaterCoil(CoilNum).InletAirTemp,
4043 : AirDewPointTemp,
4044 : OutletWaterTemp,
4045 : OutletAirTemp,
4046 : OutletAirHumRat,
4047 : TotWaterCoilLoad,
4048 : SenWaterCoilLoad,
4049 : SurfAreaWetFraction,
4050 : FanOpMode,
4051 : PartLoadRatio);
4052 :
4053 : } // End if for part wet part dry coil
4054 : } // End if for dry coil
4055 :
4056 11296023 : } else if (state.dataWaterCoils->WaterCoil(CoilNum).CoolingCoilAnalysisMode == state.dataWaterCoils->SimpleAnalysis) {
4057 : // Coil is completely dry if AirDewPointTemp is less than InletWaterTemp,hence Call CoilCompletelyDry
4058 11296023 : if (AirDewPointTemp <= state.dataWaterCoils->WaterCoil(CoilNum).InletWaterTemp) {
4059 :
4060 : // Calculate the leaving conditions and performance of dry coil
4061 5001183 : CoilCompletelyDry(state,
4062 : CoilNum,
4063 1667061 : state.dataWaterCoils->WaterCoil(CoilNum).InletWaterTemp,
4064 1667061 : state.dataWaterCoils->WaterCoil(CoilNum).InletAirTemp,
4065 1667061 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilTotal,
4066 : OutletWaterTemp,
4067 : OutletAirTemp,
4068 : OutletAirHumRat,
4069 : TotWaterCoilLoad,
4070 : FanOpMode,
4071 : PartLoadRatio);
4072 :
4073 1667061 : SenWaterCoilLoad = TotWaterCoilLoad;
4074 1667061 : SurfAreaWetFraction = 0.0;
4075 :
4076 : } else {
4077 : // Else If AirDewPointTemp is greater than InletWaterTemp then assume the
4078 : // external surface of coil is completely wet,hence Call CoilCompletelyWet
4079 : // Calculate the leaving conditions and performance of wet coil
4080 48144810 : CoilCompletelyWet(state,
4081 : CoilNum,
4082 9628962 : state.dataWaterCoils->WaterCoil(CoilNum).InletWaterTemp,
4083 9628962 : state.dataWaterCoils->WaterCoil(CoilNum).InletAirTemp,
4084 9628962 : state.dataWaterCoils->WaterCoil(CoilNum).InletAirHumRat,
4085 9628962 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilInternal,
4086 9628962 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilExternal,
4087 : OutletWaterTemp,
4088 : OutletAirTemp,
4089 : OutletAirHumRat,
4090 : TotWaterCoilLoad,
4091 : SenWaterCoilLoad,
4092 : SurfAreaWetFraction,
4093 : AirInletCoilSurfTemp,
4094 : FanOpMode,
4095 : PartLoadRatio);
4096 :
4097 : } // End if for dry coil
4098 : }
4099 :
4100 : // Report outlet variables at nodes
4101 12186409 : state.dataWaterCoils->WaterCoil(CoilNum).OutletAirTemp = OutletAirTemp;
4102 12186409 : state.dataWaterCoils->WaterCoil(CoilNum).OutletAirHumRat = OutletAirHumRat;
4103 12186409 : state.dataWaterCoils->WaterCoil(CoilNum).OutletWaterTemp = OutletWaterTemp;
4104 : // Report output results if the coil was operating
4105 :
4106 12186409 : if (FanOpMode == CycFanCycCoil) {
4107 714002 : TotWaterCoilLoad *= PartLoadRatio;
4108 714002 : SenWaterCoilLoad *= PartLoadRatio;
4109 : }
4110 :
4111 12186409 : state.dataWaterCoils->WaterCoil(CoilNum).TotWaterCoolingCoilRate = TotWaterCoilLoad;
4112 12186409 : state.dataWaterCoils->WaterCoil(CoilNum).SenWaterCoolingCoilRate = SenWaterCoilLoad;
4113 12186409 : state.dataWaterCoils->WaterCoil(CoilNum).SurfAreaWetFraction = SurfAreaWetFraction;
4114 : // WaterCoil(CoilNum)%OutletWaterEnthalpy = WaterCoil(CoilNum)%InletWaterEnthalpy+ &
4115 : // WaterCoil(CoilNum)%TotWaterCoolingCoilRate/WaterCoil(CoilNum)%InletWaterMassFlowRate
4116 12186409 : state.dataWaterCoils->WaterCoil(CoilNum).OutletWaterEnthalpy =
4117 24372818 : state.dataWaterCoils->WaterCoil(CoilNum).InletWaterEnthalpy + SafeDivide(state.dataWaterCoils->WaterCoil(CoilNum).TotWaterCoolingCoilRate,
4118 12186409 : state.dataWaterCoils->WaterCoil(CoilNum).InletWaterMassFlowRate);
4119 :
4120 : } else {
4121 : // If both mass flow rates are zero, set outputs to inputs and return
4122 9868533 : state.dataWaterCoils->WaterCoil(CoilNum).OutletWaterTemp = state.dataWaterCoils->WaterCoil(CoilNum).InletWaterTemp;
4123 9868533 : state.dataWaterCoils->WaterCoil(CoilNum).OutletAirTemp = state.dataWaterCoils->WaterCoil(CoilNum).InletAirTemp;
4124 9868533 : state.dataWaterCoils->WaterCoil(CoilNum).OutletAirHumRat = state.dataWaterCoils->WaterCoil(CoilNum).InletAirHumRat;
4125 9868533 : state.dataWaterCoils->WaterCoil(CoilNum).OutletWaterEnthalpy = state.dataWaterCoils->WaterCoil(CoilNum).InletWaterEnthalpy;
4126 9868533 : state.dataWaterCoils->WaterCoil(CoilNum).TotWaterCoolingCoilEnergy = 0.0;
4127 9868533 : state.dataWaterCoils->WaterCoil(CoilNum).SenWaterCoolingCoilEnergy = 0.0;
4128 9868533 : state.dataWaterCoils->WaterCoil(CoilNum).SurfAreaWetFraction = 0.0;
4129 :
4130 : } // End of the Flow or No flow If block
4131 22054942 : state.dataWaterCoils->WaterCoil(CoilNum).OutletWaterMassFlowRate = state.dataWaterCoils->WaterCoil(CoilNum).InletWaterMassFlowRate;
4132 22054942 : state.dataWaterCoils->WaterCoil(CoilNum).OutletAirMassFlowRate = state.dataWaterCoils->WaterCoil(CoilNum).InletAirMassFlowRate;
4133 22054942 : state.dataWaterCoils->WaterCoil(CoilNum).OutletAirEnthalpy =
4134 22054942 : PsyHFnTdbW(state.dataWaterCoils->WaterCoil(CoilNum).OutletAirTemp, state.dataWaterCoils->WaterCoil(CoilNum).OutletAirHumRat);
4135 22054942 : }
4136 :
4137 : // End Algorithm Section of the Module
4138 :
4139 : // Coil Completely Dry Subroutine for Cooling Coil
4140 :
4141 17783792 : void CoilCompletelyDry(EnergyPlusData &state,
4142 : int const CoilNum,
4143 : Real64 const WaterTempIn, // Entering water temperature
4144 : Real64 const AirTempIn, // Entering air dry bulb temperature
4145 : Real64 const CoilUA, // Overall heat transfer coefficient
4146 : Real64 &OutletWaterTemp, // Leaving water temperature
4147 : Real64 &OutletAirTemp, // Leaving air dry bulb temperature
4148 : Real64 &OutletAirHumRat, // Leaving air humidity ratio
4149 : Real64 &Q, // Heat transfer rate
4150 : int const FanOpMode, // fan operating mode
4151 : Real64 const PartLoadRatio // part-load ratio of heating coil
4152 : )
4153 : {
4154 :
4155 : // FUNCTION INFORMATION:
4156 : // AUTHOR Rahul Chillar
4157 : // DATE WRITTEN March 2004
4158 : // MODIFIED na
4159 : // RE-ENGINEERED na
4160 :
4161 : // PURPOSE OF THIS FUNCTION:
4162 : // Calculate the performance of a sensible air-liquid heat exchanger. Calculated
4163 : // results include outlet air temperature and humidity, outlet water temperature,
4164 : // and heat transfer rate.
4165 :
4166 : // METHODOLOGY EMPLOYED:
4167 : // Models coil using effectiveness-NTU model.
4168 :
4169 : // REFERENCES:
4170 : // Kays, W.M. and A.L. London. 1964,Compact Heat Exchangers, 2nd Edition,
4171 : // New York: McGraw-Hill.
4172 :
4173 : // USE STATEMENTS:
4174 : // na
4175 :
4176 : // Enforce explicit typing of all variables in this routine
4177 :
4178 : // Locals
4179 : // FUNCTION ARGUMENT DEFINITIONS:
4180 :
4181 : // FUNCTION PARAMETER DEFINITIONS:
4182 : static constexpr std::string_view RoutineName("CoilCompletelyDry");
4183 :
4184 : // INTERFACE BLOCK SPECIFICATIONS
4185 : // na
4186 :
4187 : // DERIVED TYPE DEFINITIONS
4188 : // na
4189 :
4190 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
4191 : Real64 CapacitanceAir; // Air-side capacity rate(W/C)
4192 : Real64 CapacitanceWater; // Water-side capacity rate(W/C)
4193 : Real64 AirMassFlow;
4194 : Real64 WaterMassFlowRate;
4195 : Real64 Cp;
4196 :
4197 : // adjust mass flow rates for cycling fan cycling coil operation
4198 17783792 : if (FanOpMode == CycFanCycCoil) {
4199 2124185 : if (PartLoadRatio > 0.0) {
4200 2124185 : AirMassFlow = state.dataWaterCoils->WaterCoil(CoilNum).InletAirMassFlowRate / PartLoadRatio;
4201 2124185 : WaterMassFlowRate = min(state.dataWaterCoils->WaterCoil(CoilNum).InletWaterMassFlowRate / PartLoadRatio,
4202 2124185 : state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterMassFlowRate);
4203 : } else {
4204 0 : AirMassFlow = 0.0;
4205 0 : WaterMassFlowRate = 0.0;
4206 : }
4207 : } else {
4208 15659607 : AirMassFlow = state.dataWaterCoils->WaterCoil(CoilNum).InletAirMassFlowRate;
4209 15659607 : WaterMassFlowRate = state.dataWaterCoils->WaterCoil(CoilNum).InletWaterMassFlowRate;
4210 : }
4211 :
4212 : // Calculate air and water capacity rates
4213 17783792 : CapacitanceAir = AirMassFlow * PsyCpAirFnW(state.dataWaterCoils->WaterCoil(CoilNum).InletAirHumRat);
4214 : // Water Capacity Rate
4215 35567584 : Cp = GetSpecificHeatGlycol(state,
4216 17783792 : state.dataPlnt->PlantLoop(state.dataWaterCoils->WaterCoil(CoilNum).WaterPlantLoc.loopNum).FluidName,
4217 : WaterTempIn,
4218 17783792 : state.dataPlnt->PlantLoop(state.dataWaterCoils->WaterCoil(CoilNum).WaterPlantLoc.loopNum).FluidIndex,
4219 : RoutineName);
4220 :
4221 17783792 : CapacitanceWater = WaterMassFlowRate * Cp;
4222 :
4223 : // Determine the air and water outlet conditions
4224 17783792 : CoilOutletStreamCondition(state, CoilNum, CapacitanceWater, WaterTempIn, CapacitanceAir, AirTempIn, CoilUA, OutletWaterTemp, OutletAirTemp);
4225 :
4226 : // Calculate the total and sensible heat transfer rate both are equal in case of Dry Coil
4227 17783792 : Q = CapacitanceAir * (AirTempIn - OutletAirTemp);
4228 :
4229 : // Outlet humidity is equal to Inlet Humidity because its a dry coil
4230 17783792 : OutletAirHumRat = state.dataWaterCoils->WaterCoil(CoilNum).InletAirHumRat;
4231 17783792 : }
4232 :
4233 : // Coil Completely Wet Subroutine for Cooling Coil
4234 :
4235 26633111 : void CoilCompletelyWet(EnergyPlusData &state,
4236 : int const CoilNum, // Number of Coil
4237 : Real64 const WaterTempIn, // Water temperature IN to this function (C)
4238 : Real64 const AirTempIn, // Air dry bulb temperature IN to this function(C)
4239 : Real64 const AirHumRat, // Air Humidity Ratio IN to this funcation (C)
4240 : Real64 const UAInternalTotal, // Internal overall heat transfer coefficient(W/m2 C)
4241 : Real64 const UAExternalTotal, // External overall heat transfer coefficient(W/m2 C)
4242 : Real64 &OutletWaterTemp, // Leaving water temperature (C)
4243 : Real64 &OutletAirTemp, // Leaving air dry bulb temperature(C)
4244 : Real64 &OutletAirHumRat, // Leaving air humidity ratio
4245 : Real64 &TotWaterCoilLoad, // Total heat transfer rate(W)
4246 : Real64 &SenWaterCoilLoad, // Sensible heat transfer rate(W)
4247 : Real64 &SurfAreaWetFraction, // Fraction of surface area wet
4248 : Real64 &AirInletCoilSurfTemp, // Surface temperature at air entrance(C)
4249 : int const FanOpMode, // fan operating mode
4250 : Real64 const PartLoadRatio // part-load ratio of heating coil
4251 : )
4252 : {
4253 :
4254 : // FUNCTION INFORMATION:
4255 : // AUTHOR Rahul Chillar
4256 : // DATE WRITTEN Mar 2004
4257 : // MODIFIED na
4258 : // RE-ENGINEERED na
4259 :
4260 : // PURPOSE OF THIS FUNCTION:
4261 : // Calculate the performance of a cooling coil when the external fin surface is
4262 : // complete wet. Results include outlet air temperature and humidity,
4263 : // outlet water temperature, sensible and total cooling capacities, and the wet
4264 : // fraction of the air-side surface area.
4265 :
4266 : // METHODOLOGY EMPLOYED:
4267 : // Models coil as counterflow heat exchanger. Approximates saturated air enthalpy as
4268 : // a linear function of temperature
4269 : // TRNSYS. 1990. A Transient System Simulation Program: Reference Manual.
4270 : // Solar Energy Laboratory, Univ. Wisconsin Madison, pp. 4.6.8-1 - 4.6.8-12.
4271 : // Threlkeld, J.L. 1970. Thermal Environmental Engineering, 2nd Edition,
4272 : // Englewood Cliffs: Prentice-Hall,Inc. pp. 254-270.
4273 : // Coil Uses Enthalpy Based Heat Transfer Coefficents and converts them to
4274 : // convential UA values. Intermediate value of fictitious Cp is defined. This follow
4275 : // the same procedure followed in the Design Calculation of the Coil. See the node in
4276 : // the one time calculation for design condition.
4277 :
4278 : // REFERENCES:
4279 : // Elmahdy, A.H. and Mitalas, G.P. 1977."A Simple Model for Cooling and
4280 : // Dehumidifying Coils for Use In Calculating Energy Requirements for Buildings,"
4281 : // ASHRAE Transactions,Vol.83 Part 2, pp. 103-117.
4282 :
4283 : // USE STATEMENTS:
4284 :
4285 : // Enforce explicit typing of all variables in this routine
4286 :
4287 : // Locals
4288 : // FUNCTION ARGUMENT DEFINITIONS:
4289 :
4290 : // FUNCTION PARAMETER DEFINITIONS:
4291 : static constexpr std::string_view RoutineName("CoilCompletelyWet");
4292 :
4293 : // INTERFACE BLOCK SPECIFICATIONS
4294 : // na
4295 :
4296 : // DERIVED TYPE DEFINITIONS
4297 : // na
4298 :
4299 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
4300 : Real64 AirSideResist; // Air-side resistance to heat transfer(m2 C/W)
4301 : Real64 WaterSideResist; // Liquid-side resistance to heat transfer(m2 C/W)
4302 : Real64 EnteringAirDewPt; // Entering air dew point(C)
4303 : Real64 UACoilTotalEnth; // Overall enthalpy heat transfer coefficient(kg/s)
4304 : Real64 CapacityRateAirWet; // Air-side capacity rate(kg/s)
4305 : Real64 CapacityRateWaterWet; // Liquid-side capacity rate(kg/s)
4306 : Real64 ResistRatio; // Ratio of resistances
4307 : Real64 EnthAirOutlet; // Outlet air enthalpy
4308 : Real64 EnthSatAirInletWaterTemp; // Saturated enthalpy of air at entering water temperature(J/kg)
4309 : Real64 EnthSatAirOutletWaterTemp; // Saturated enthalpy of air at exit water temperature(J/kg)
4310 : Real64 EnthSatAirCoilSurfaceEntryTemp; // Saturated enthalpy of air at entering surface temperature(J/kg)
4311 : Real64 EnthSatAirCoilSurfaceExitTemp; // Saturated enthalpy of air at exit surface temperature(J/kg)
4312 : Real64 EnthAirInlet; // Enthalpy of air at inlet
4313 : Real64 IntermediateCpSat; // Coefficient for equation below(J/kg C)
4314 : // EnthSat1-EnthSat2 = IntermediateCpSat*(TSat1-TSat2)
4315 : // (all water and surface temperatures are
4316 : // related to saturated air enthalpies for
4317 : // wet surface heat transfer calculations)
4318 26633111 : Real64 constexpr SmallNo(1.e-9); // smallNo used in place of 0
4319 : Real64 AirMassFlow;
4320 : Real64 WaterMassFlowRate;
4321 : Real64 Cp;
4322 :
4323 26633111 : SurfAreaWetFraction = 1.0;
4324 26633111 : AirSideResist = 1.0 / max(UAExternalTotal, SmallNo);
4325 26633111 : WaterSideResist = 1.0 / max(UAInternalTotal, SmallNo);
4326 :
4327 : // adjust mass flow rates for cycling fan cycling coil operation
4328 26633111 : if (FanOpMode == CycFanCycCoil) {
4329 2481243 : if (PartLoadRatio > 0.0) {
4330 2481243 : AirMassFlow = state.dataWaterCoils->WaterCoil(CoilNum).InletAirMassFlowRate / PartLoadRatio;
4331 2481243 : WaterMassFlowRate = min(state.dataWaterCoils->WaterCoil(CoilNum).InletWaterMassFlowRate / PartLoadRatio,
4332 2481243 : state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterMassFlowRate);
4333 : } else {
4334 0 : AirMassFlow = 0.0;
4335 0 : WaterMassFlowRate = 0.0;
4336 : }
4337 : } else {
4338 24151868 : AirMassFlow = state.dataWaterCoils->WaterCoil(CoilNum).InletAirMassFlowRate;
4339 24151868 : WaterMassFlowRate = state.dataWaterCoils->WaterCoil(CoilNum).InletWaterMassFlowRate;
4340 : }
4341 :
4342 : // Calculate enthalpies of entering air and water
4343 :
4344 : // Enthalpy of air at inlet to the coil
4345 26633111 : EnthAirInlet = PsyHFnTdbW(AirTempIn, AirHumRat);
4346 :
4347 : // Saturation Enthalpy of Air at inlet water temperature
4348 26633111 : EnthSatAirInletWaterTemp = PsyHFnTdbW(WaterTempIn, PsyWFnTdpPb(state, WaterTempIn, state.dataEnvrn->OutBaroPress));
4349 :
4350 : // Estimate IntermediateCpSat using entering air dewpoint and water temperature
4351 26633111 : EnteringAirDewPt = PsyTdpFnWPb(state, AirHumRat, state.dataEnvrn->OutBaroPress);
4352 :
4353 : // An intermediate value of Specific heat . EnthSat1-EnthSat2 = IntermediateCpSat*(TSat1-TSat2)
4354 26633111 : IntermediateCpSat =
4355 53266222 : (PsyHFnTdbW(EnteringAirDewPt, PsyWFnTdpPb(state, EnteringAirDewPt, state.dataEnvrn->OutBaroPress)) - EnthSatAirInletWaterTemp) /
4356 26633111 : (EnteringAirDewPt - WaterTempIn);
4357 :
4358 : // Determine air and water enthalpy outlet conditions by modeling
4359 : // coil as counterflow enthalpy heat exchanger
4360 26633111 : UACoilTotalEnth = 1.0 / (IntermediateCpSat * WaterSideResist + AirSideResist * PsyCpAirFnW(0.0));
4361 26633111 : CapacityRateAirWet = AirMassFlow;
4362 53266222 : Cp = GetSpecificHeatGlycol(state,
4363 26633111 : state.dataPlnt->PlantLoop(state.dataWaterCoils->WaterCoil(CoilNum).WaterPlantLoc.loopNum).FluidName,
4364 : WaterTempIn,
4365 26633111 : state.dataPlnt->PlantLoop(state.dataWaterCoils->WaterCoil(CoilNum).WaterPlantLoc.loopNum).FluidIndex,
4366 : RoutineName);
4367 26633111 : CapacityRateWaterWet = WaterMassFlowRate * (Cp / IntermediateCpSat);
4368 26633111 : CoilOutletStreamCondition(state,
4369 : CoilNum,
4370 : CapacityRateAirWet,
4371 : EnthAirInlet,
4372 : CapacityRateWaterWet,
4373 : EnthSatAirInletWaterTemp,
4374 : UACoilTotalEnth,
4375 : EnthAirOutlet,
4376 : EnthSatAirOutletWaterTemp);
4377 :
4378 : // Calculate entering and leaving external surface conditions from
4379 : // air and water conditions and the ratio of resistances
4380 26633111 : ResistRatio = (WaterSideResist) / (WaterSideResist + PsyCpAirFnW(0.0) / IntermediateCpSat * AirSideResist);
4381 26633111 : EnthSatAirCoilSurfaceEntryTemp = EnthSatAirOutletWaterTemp + ResistRatio * (EnthAirInlet - EnthSatAirOutletWaterTemp);
4382 26633111 : EnthSatAirCoilSurfaceExitTemp = EnthSatAirInletWaterTemp + ResistRatio * (EnthAirOutlet - EnthSatAirInletWaterTemp);
4383 :
4384 : // Calculate Coil Surface Temperature at air entry to the coil
4385 26633111 : AirInletCoilSurfTemp = PsyTsatFnHPb(state, EnthSatAirCoilSurfaceEntryTemp, state.dataEnvrn->OutBaroPress);
4386 :
4387 : // Calculate outlet air temperature and humidity from enthalpies and surface conditions.
4388 26633111 : TotWaterCoilLoad = AirMassFlow * (EnthAirInlet - EnthAirOutlet);
4389 26633111 : OutletWaterTemp = WaterTempIn + TotWaterCoilLoad / max(WaterMassFlowRate, SmallNo) / Cp;
4390 :
4391 : // Calculates out put variable for the completely wet coil
4392 26633111 : WetCoilOutletCondition(state, CoilNum, AirTempIn, EnthAirInlet, EnthAirOutlet, UAExternalTotal, OutletAirTemp, OutletAirHumRat, SenWaterCoilLoad);
4393 26633111 : }
4394 :
4395 : // Coil Part Wet Part Dry Subroutine for Cooling Coil
4396 :
4397 706219 : void CoilPartWetPartDry(EnergyPlusData &state,
4398 : int const CoilNum, // Number of Coil
4399 : bool const FirstHVACIteration, // Saving Old values
4400 : Real64 const InletWaterTemp, // Entering liquid temperature(C)
4401 : Real64 const InletAirTemp, // Entering air dry bulb temperature(C)
4402 : Real64 const AirDewPointTemp, // Entering air dew point(C)
4403 : Real64 &OutletWaterTemp, // Leaving liquid temperature(C)
4404 : Real64 &OutletAirTemp, // Leaving air dry bulb temperature(C)
4405 : Real64 &OutletAirHumRat, // Leaving air humidity ratio
4406 : Real64 &TotWaterCoilLoad, // Total heat transfer rate (W)
4407 : Real64 &SenWaterCoilLoad, // Sensible heat transfer rate (W)
4408 : Real64 &SurfAreaWetFraction, // Fraction of surface area wet
4409 : int const FanOpMode, // fan operating mode
4410 : Real64 const PartLoadRatio // part-load ratio of heating coil
4411 : )
4412 : {
4413 :
4414 : // FUNCTION INFORMATION:
4415 : // AUTHOR Rahul Chillar
4416 : // DATE WRITTEN March 2004
4417 : // MODIFIED na
4418 : // RE-ENGINEERED na
4419 :
4420 : // PURPOSE OF THIS FUNCTION:
4421 : // Calculate the performance of a cooling coil when the external fin surface is
4422 : // part wet and part dry. Results include outlet air temperature and humidity,
4423 : // outlet liquid temperature, sensible and total cooling capacities, and the wet
4424 : // fraction of the air-side surface area.
4425 :
4426 : // METHODOLOGY EMPLOYED:
4427 : // Models coil using effectiveness NTU model
4428 :
4429 : // REFERENCES:
4430 : // Elmahdy, A.H. and Mitalas, G.P. 1977. "A Simple Model for Cooling and
4431 : // Dehumidifying Coils for Use In Calculating Energy Requirements for Buildings,"
4432 : // ASHRAE Transactions,Vol.83 Part 2, pp. 103-117.
4433 : // TRNSYS. 1990. A Transient System Simulation Program: Reference Manual.
4434 : // Solar Energy Laboratory, Univ. Wisconsin- Madison, pp. 4.6.8-1 - 4.6.8-12.
4435 : // Threlkeld, J.L. 1970. Thermal Environmental Engineering, 2nd Edition,
4436 : // Englewood Cliffs: Prentice-Hall,Inc. pp. 254-270.
4437 :
4438 : // Using/Aliasing
4439 : using General::Iterate;
4440 :
4441 : // Enforce explicit typing of all variables in this routine
4442 :
4443 : // Locals
4444 : // FUNCTION ARGUMENT DEFINITIONS:
4445 :
4446 : // FUNCTION PARAMETER DEFINITIONS:
4447 706219 : int constexpr itmax(60);
4448 706219 : Real64 constexpr smalltempdiff(1.0e-9);
4449 :
4450 : // INTERFACE BLOCK SPECIFICATIONS
4451 : // na
4452 :
4453 : // DERIVED TYPE DEFINITIONS
4454 : // na
4455 :
4456 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
4457 : Real64 DryCoilHeatTranfer; // Heat transfer rate for dry coil(W)
4458 : Real64 WetCoilTotalHeatTransfer; // Total heat transfer rate for wet coil(W)
4459 : Real64 WetCoilSensibleHeatTransfer; // Sensible heat transfer rate for wet coil(W)
4460 : Real64 SurfAreaWet; // Air-side area of wet coil(m2)
4461 : Real64 SurfAreaDry; // Air-side area of dry coil(m2)
4462 : Real64 DryCoilUA; // Overall heat transfer coefficient for dry coil(W/C)
4463 : Real64 WetDryInterfcWaterTemp; // Liquid temperature at wet/dry boundary(C)
4464 : Real64 WetDryInterfcAirTemp; // Air temperature at wet/dry boundary(C)
4465 : Real64 WetDryInterfcSurfTemp; // Surface temperature at wet/dry boundary(C)
4466 : Real64 EstimateWetDryInterfcWaterTemp; // Estimated liquid temperature at wet/dry boundary(C)
4467 : Real64 EstimateSurfAreaWetFraction; // Initial Estimate for Fraction of Surface Wet with condensation
4468 : Real64 WetPartUAInternal; // UA of Wet Coil Internal
4469 : Real64 WetPartUAExternal; // UA of Dry Coil External
4470 : Real64 WetDryInterfcHumRat; // Humidity Ratio at interface of the wet dry transition
4471 : Real64 X1T; // Variables used in the two iteration in this subroutine.
4472 : Real64 NewSurfAreaWetFrac; // Variables used in the two iteration in this subroutine.
4473 : Real64 ResultXT; // Variables used in the two iteration in this subroutine.
4474 : Real64 Y1T; // Variables used in the two iterations in this subroutine.
4475 : Real64 errorT; // Error in interation for First If loop
4476 : Real64 error; // Deviation of dependent variable in iteration
4477 : Real64 SurfAreaFracPrevious;
4478 : Real64 ErrorPrevious;
4479 : Real64 SurfAreaFracLast;
4480 : Real64 ErrorLast;
4481 : int iter; // Iteration counter
4482 : int icvg; // Iteration convergence flag
4483 : int icvgT; // Iteration Convergence Flag for First If loop
4484 : int itT; // Iteration Counter for First If Loop
4485 :
4486 : // Iterates on SurfAreaWetFraction to converge on surface temperature equal to
4487 : // entering air dewpoint at wet/dry boundary.
4488 :
4489 : // Preliminary estimates of coil performance to begin iteration
4490 706219 : OutletWaterTemp = InletAirTemp;
4491 706219 : DryCoilHeatTranfer = 0.0;
4492 706219 : WetCoilTotalHeatTransfer = 0.0;
4493 706219 : WetCoilSensibleHeatTransfer = 0.0;
4494 :
4495 706219 : if (FirstHVACIteration) {
4496 : // Estimate liquid temperature at boundary as entering air dew point
4497 313054 : WetDryInterfcWaterTemp = AirDewPointTemp;
4498 :
4499 : // Estimate fraction wet surface area based on liquid temperatures
4500 313054 : if (std::abs(OutletWaterTemp - InletWaterTemp) > smalltempdiff) {
4501 313054 : SurfAreaWetFraction = (WetDryInterfcWaterTemp - InletWaterTemp) / (OutletWaterTemp - InletWaterTemp);
4502 : } else {
4503 0 : SurfAreaWetFraction = 0.0;
4504 : }
4505 :
4506 : } else {
4507 393165 : SurfAreaWetFraction = state.dataWaterCoils->WaterCoil(CoilNum).SurfAreaWetFractionSaved;
4508 : }
4509 : // BEGIN LOOP to converge on SurfAreaWetFraction
4510 : // The method employed in this loop is as follows: The coil is partially wet and partially dry,
4511 : // we calculate the temperature of the coil at the interface, (the point at which the moisture begins
4512 : // to condense) temperature of the water at interface and air temp is dew point at that location.
4513 : // This is done by Iterating between the Completely Dry and Completely Wet Coil until the outlet
4514 : // water temperature of one coil equals the inlet water temperature of another.
4515 : // Using this value of interface temperature we now iterate to calculate Surface Fraction Wet, Iterate
4516 : // function perturbs the value of Surface Fraction Wet and based on this new value the entire loop is
4517 : // repeated to get a new interface water temperature and then surface fraction wet is again calculated.
4518 : // This process continues till the error between the Wet Dry Interface Temp and Air Dew Point becomes
4519 : // very negligible and in 95% of the cases its is a complete convergence to give the exact surface Wet
4520 : // fraction.
4521 706219 : NewSurfAreaWetFrac = SurfAreaWetFraction;
4522 706219 : error = 0.0;
4523 706219 : SurfAreaFracPrevious = SurfAreaWetFraction;
4524 706219 : ErrorPrevious = 0.0;
4525 706219 : SurfAreaFracLast = SurfAreaWetFraction;
4526 706219 : ErrorLast = 0.0;
4527 :
4528 4038163 : for (iter = 1; iter <= itmax; ++iter) {
4529 :
4530 : // Calculating Surface Area Wet and Surface Area Dry
4531 4038163 : SurfAreaWet = SurfAreaWetFraction * state.dataWaterCoils->WaterCoil(CoilNum).TotCoilOutsideSurfArea;
4532 4038163 : SurfAreaDry = state.dataWaterCoils->WaterCoil(CoilNum).TotCoilOutsideSurfArea - SurfAreaWet;
4533 :
4534 : // Calculating UA values for the Dry Part of the Coil
4535 8076326 : DryCoilUA = SurfAreaDry / (1.0 / state.dataWaterCoils->WaterCoil(CoilNum).UACoilInternalPerUnitArea +
4536 4038163 : 1.0 / state.dataWaterCoils->WaterCoil(CoilNum).UADryExtPerUnitArea);
4537 :
4538 : // Calculating UA Value for the Wet part of the Coil
4539 4038163 : WetPartUAExternal = state.dataWaterCoils->WaterCoil(CoilNum).UAWetExtPerUnitArea * SurfAreaWet;
4540 4038163 : WetPartUAInternal = state.dataWaterCoils->WaterCoil(CoilNum).UACoilInternalPerUnitArea * SurfAreaWet;
4541 :
4542 : // Calculating Water Temperature at Wet Dry Interface of the coil
4543 4038163 : WetDryInterfcWaterTemp = InletWaterTemp + SurfAreaWetFraction * (OutletWaterTemp - InletWaterTemp);
4544 :
4545 : // BEGIN LOOP to converge on liquid temperature at wet/dry boundary
4546 16115247 : for (itT = 1; itT <= itmax; ++itT) {
4547 :
4548 : // Calculate dry coil performance with estimated liquid temperature at the boundary.
4549 16115247 : CoilCompletelyDry(state,
4550 : CoilNum,
4551 : WetDryInterfcWaterTemp,
4552 : InletAirTemp,
4553 : DryCoilUA,
4554 : OutletWaterTemp,
4555 : WetDryInterfcAirTemp,
4556 : WetDryInterfcHumRat,
4557 : DryCoilHeatTranfer,
4558 : FanOpMode,
4559 : PartLoadRatio);
4560 :
4561 : // Calculate wet coil performance with calculated air temperature at the boundary.
4562 16115247 : CoilCompletelyWet(state,
4563 : CoilNum,
4564 : InletWaterTemp,
4565 : WetDryInterfcAirTemp,
4566 : WetDryInterfcHumRat,
4567 : WetPartUAInternal,
4568 : WetPartUAExternal,
4569 : EstimateWetDryInterfcWaterTemp,
4570 : OutletAirTemp,
4571 : OutletAirHumRat,
4572 : WetCoilTotalHeatTransfer,
4573 : WetCoilSensibleHeatTransfer,
4574 : EstimateSurfAreaWetFraction,
4575 : WetDryInterfcSurfTemp,
4576 : FanOpMode,
4577 : PartLoadRatio);
4578 :
4579 : // Iterating to calculate the actual wet dry interface water temperature.
4580 16115247 : errorT = EstimateWetDryInterfcWaterTemp - WetDryInterfcWaterTemp;
4581 16115247 : Iterate(ResultXT, 0.001, WetDryInterfcWaterTemp, errorT, X1T, Y1T, itT, icvgT);
4582 16115247 : WetDryInterfcWaterTemp = ResultXT;
4583 :
4584 : // IF convergence is achieved then exit the itT to itmax Do loop.
4585 16115247 : if (icvgT == 1) break;
4586 :
4587 : } // End Do for Liq Boundary temp Convergence
4588 :
4589 : // Wet Dry Interface temperature not converged after maximum specified iterations.
4590 : // Print error message, set return error flag
4591 4038163 : if ((itT > itmax) && (!state.dataGlobal->WarmupFlag)) {
4592 0 : ShowWarningError(state, "For Coil:Cooling:Water " + state.dataWaterCoils->WaterCoil(CoilNum).Name);
4593 0 : ShowContinueError(state, "CoilPartWetPartDry: Maximum iterations exceeded for Liq Temp, at Interface");
4594 : }
4595 :
4596 : // If Following condition prevails then surface is dry, calculate dry coil performance and return
4597 4038163 : if (SurfAreaWetFraction <= 0.0 && WetDryInterfcSurfTemp >= AirDewPointTemp) {
4598 :
4599 : // Calculating Value of Dry UA for the coil
4600 0 : DryCoilUA = state.dataWaterCoils->WaterCoil(CoilNum).TotCoilOutsideSurfArea /
4601 0 : (1.0 / state.dataWaterCoils->WaterCoil(CoilNum).UACoilInternalPerUnitArea +
4602 0 : 1.0 / state.dataWaterCoils->WaterCoil(CoilNum).UADryExtPerUnitArea);
4603 :
4604 : // Calling the Completely Dry Coil for outputs
4605 0 : CoilCompletelyDry(state,
4606 : CoilNum,
4607 : InletWaterTemp,
4608 : InletAirTemp,
4609 : DryCoilUA,
4610 : OutletWaterTemp,
4611 : OutletAirTemp,
4612 : OutletAirHumRat,
4613 : TotWaterCoilLoad,
4614 : FanOpMode,
4615 : PartLoadRatio);
4616 :
4617 : // Sensible load = Total load in a Completely Dry Coil
4618 0 : SenWaterCoilLoad = TotWaterCoilLoad;
4619 :
4620 : // All coil is Dry so fraction wet is ofcourse =0
4621 0 : SurfAreaWetFraction = 0.0;
4622 0 : return;
4623 : }
4624 :
4625 : // IF the coil is not Dry then iterate to calculate Fraction of surface area that is wet.
4626 4038163 : error = WetDryInterfcSurfTemp - AirDewPointTemp;
4627 4038163 : CoilAreaFracIter(
4628 : NewSurfAreaWetFrac, SurfAreaWetFraction, error, SurfAreaFracPrevious, ErrorPrevious, SurfAreaFracLast, ErrorLast, iter, icvg);
4629 4038163 : SurfAreaWetFraction = NewSurfAreaWetFrac;
4630 :
4631 : // If converged, leave iteration loop
4632 4038163 : if (icvg == 1) break;
4633 :
4634 : // Surface temperature not converged. Repeat calculations with new
4635 : // estimate of fraction wet surface area.
4636 3331944 : if (SurfAreaWetFraction > 1.0) SurfAreaWetFraction = 1.0;
4637 3331944 : if (SurfAreaWetFraction <= 0.0) SurfAreaWetFraction = 0.0098;
4638 :
4639 : } // End do for the overall iteration
4640 :
4641 : // Calculate sum of total and sensible heat transfer from dry and wet parts.
4642 706219 : TotWaterCoilLoad = DryCoilHeatTranfer + WetCoilTotalHeatTransfer;
4643 706219 : SenWaterCoilLoad = DryCoilHeatTranfer + WetCoilSensibleHeatTransfer;
4644 :
4645 : // Save last iterations values for this current time step
4646 706219 : state.dataWaterCoils->WaterCoil(CoilNum).SurfAreaWetFractionSaved = SurfAreaWetFraction;
4647 : }
4648 :
4649 : // Calculating coil UA for Cooling Coil
4650 :
4651 0 : Real64 CalcCoilUAbyEffectNTU(EnergyPlusData &state,
4652 : int const CoilNum,
4653 : Real64 const CapacityStream1, // Capacity rate of stream1.(W/C)
4654 : Real64 const EnergyInStreamOne, // Inlet state of stream1.(C)
4655 : Real64 const CapacityStream2, // Capacity rate of stream2.(W/C)
4656 : Real64 const EnergyInStreamTwo, // Inlet state of stream2.(C)
4657 : Real64 const DesTotalHeatTransfer // Heat transfer rate(W)
4658 : )
4659 : {
4660 :
4661 : // FUNCTION INFORMATION:
4662 : // AUTHOR Rahul Chillar
4663 : // DATE WRITTEN March 2004
4664 : // MODIFIED na
4665 : // RE-ENGINEERED na
4666 :
4667 : // PURPOSE OF THIS FUNCTION:
4668 : // Calculate the UA of a heat exchanger using the effectiveness-NTU relationships
4669 : // given the entering capacity rate and temperature of each flow stream, the
4670 : // heat transfer rate under these conditions and the heat exchanger configuration.
4671 :
4672 : // METHODOLOGY EMPLOYED:
4673 : // Models coil using effectiveness NTU model
4674 :
4675 : // REFERENCES:
4676 : // na
4677 :
4678 : // Using/Aliasing
4679 : using General::Iterate;
4680 :
4681 : // Enforce explicit typing of all variables in this routine
4682 :
4683 : // Return value
4684 : Real64 CalcCoilUAbyEffectNTU; // Overall heat transfer coefficient(W/C)
4685 :
4686 : // Locals
4687 : // FUNCTION ARGUMENT DEFINITIONS:
4688 :
4689 : // FUNCTION PARAMETER DEFINITIONS:
4690 0 : Real64 constexpr SmallNo(1.e-9);
4691 0 : int constexpr itmax(12);
4692 :
4693 : // INTERFACE BLOCK SPECIFICATIONS
4694 : // na
4695 :
4696 : // DERIVED TYPE DEFINITIONS
4697 : // na
4698 :
4699 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
4700 : Real64 MaxHeatTransfer; // Maximum heat transfer from inlet conditions (W)
4701 : Real64 EstimatedHeatTransfer; // Estimated heat transfer in iteration(W)
4702 : Real64 CoilUA; // Estimated heat transfer coefficient(W/C)
4703 : Real64 error; // Deviation of dependent variable in iteration
4704 : Real64 X1; // Previous values of independent variable in iteration
4705 : Real64 Y1;
4706 : Real64 ResultX;
4707 : Real64 EnergyOutStreamOne; // Intermediate Variable used
4708 : Real64 EnergyOutStreamTwo; // Intermediate variable used
4709 : Real64 DesTotalHeatTransferCheck; // Check value to keep design total heat transfer in range
4710 : int iter; // Iteration index
4711 : int icvg; // Iteration convergence flag
4712 :
4713 : // Check for Q out of range (effectiveness > 1)
4714 0 : MaxHeatTransfer = std::abs(min(CapacityStream1, CapacityStream2) * (EnergyInStreamOne - EnergyInStreamTwo));
4715 :
4716 : // Error Message
4717 0 : if ((std::abs(DesTotalHeatTransfer) - MaxHeatTransfer) / max(MaxHeatTransfer, SmallNo) > SmallNo) {
4718 0 : ShowWarningError(state, "For Coil:Cooling:Water " + state.dataWaterCoils->WaterCoil(CoilNum).Name);
4719 0 : ShowContinueError(state, "CalcCoilUAbyEffectNTU:Given Q impossible for given inlet states, proceeding with MaxHeat Transfer");
4720 0 : ShowContinueError(state, "Check the Sizing:System and Sizing:Zone cooling design supply air temperature and ");
4721 0 : ShowContinueError(state,
4722 : "the Sizing:Plant design Loop exit temperature. There must be sufficient difference between these two temperatures.");
4723 : }
4724 :
4725 : // Design Heat Transfer cannot exceed Max heat Transfer , setting it value such that effectiveness<1.0
4726 0 : if ((DesTotalHeatTransfer) > (MaxHeatTransfer)) {
4727 : // Pegging value so that effectiveness is less than 1.
4728 0 : DesTotalHeatTransferCheck = 0.9 * MaxHeatTransfer;
4729 :
4730 : // Estimate CalcCoilUAbyEffectNTU
4731 0 : CoilUA = std::abs(DesTotalHeatTransferCheck / (EnergyInStreamOne - EnergyInStreamTwo));
4732 :
4733 : } else {
4734 :
4735 : // Estimate CalcCoilUAbyEffectNTU
4736 0 : CoilUA = std::abs(DesTotalHeatTransfer / (EnergyInStreamOne - EnergyInStreamTwo));
4737 : }
4738 :
4739 : // BEGIN LOOP to iteratively calculate CalcCoilUAbyEffectNTU
4740 0 : for (iter = 1; iter <= itmax; ++iter) {
4741 :
4742 : // Calculate heat transfer rate for estimated CalcCoilUAbyEffectNTU
4743 0 : CoilOutletStreamCondition(
4744 : state, CoilNum, CapacityStream1, EnergyInStreamOne, CapacityStream2, EnergyInStreamTwo, CoilUA, EnergyOutStreamOne, EnergyOutStreamTwo);
4745 :
4746 : // Initial Guess for a value of heat transfer
4747 0 : EstimatedHeatTransfer = CapacityStream1 * (EnergyInStreamOne - EnergyOutStreamOne);
4748 :
4749 : // Calculate new estimate for CalcCoilUAbyEffectNTU by iteration
4750 0 : if (DesTotalHeatTransfer > MaxHeatTransfer) {
4751 0 : error = std::abs(EstimatedHeatTransfer) - std::abs(DesTotalHeatTransferCheck);
4752 : } else {
4753 0 : error = std::abs(EstimatedHeatTransfer) - std::abs(DesTotalHeatTransfer);
4754 : }
4755 0 : Iterate(ResultX, 0.01, CoilUA, error, X1, Y1, iter, icvg);
4756 0 : CoilUA = ResultX;
4757 : // If converged, leave loop
4758 0 : if (icvg == 1) break;
4759 : }
4760 :
4761 : // If not converged after itmax iterations, return error code
4762 0 : if ((iter > itmax) && (!state.dataGlobal->WarmupFlag)) {
4763 0 : ShowWarningError(state, "For Coil:Cooling:Water " + state.dataWaterCoils->WaterCoil(CoilNum).Name);
4764 0 : ShowContinueError(state, "CalcCoilUAbyEffectNTU: Maximum iterations exceeded:Coil UA calculation");
4765 0 : CalcCoilUAbyEffectNTU = 0.0; // Autodesk:Return Line added to set return value: Using non-converged CoilUA value may be preferred but
4766 : // that was not happening
4767 : } else {
4768 :
4769 : // Assign value to CalcCoilUAbyEffectNTU
4770 0 : CalcCoilUAbyEffectNTU = CoilUA;
4771 : }
4772 :
4773 0 : return CalcCoilUAbyEffectNTU;
4774 : }
4775 :
4776 : // Calculating coil outlet stream conditions and coil UA for Cooling Coil
4777 :
4778 44416903 : void CoilOutletStreamCondition(EnergyPlusData &state,
4779 : int const CoilNum,
4780 : Real64 const CapacityStream1, // Capacity rate of stream1(W/C)
4781 : Real64 const EnergyInStreamOne, // Inlet state of stream1 (C)
4782 : Real64 const CapacityStream2, // Capacity rate of stream2 (W/C)
4783 : Real64 const EnergyInStreamTwo, // Inlet state of stream2 (C)
4784 : Real64 const CoilUA, // Heat transfer rateW)
4785 : Real64 &EnergyOutStreamOne, // Outlet state of stream1 (C)
4786 : Real64 &EnergyOutStreamTwo // Outlet state of stream2 (C)
4787 : )
4788 : {
4789 :
4790 : // FUNCTION INFORMATION:
4791 : // AUTHOR Rahul Chillar
4792 : // DATE WRITTEN March 2004
4793 : // MODIFIED na
4794 : // RE-ENGINEERED na
4795 :
4796 : // PURPOSE OF THIS FUNCTION:
4797 : // Calculate the outlet states of a simple heat exchanger using the effectiveness-Ntu
4798 : // method of analysis.
4799 :
4800 : // METHODOLOGY EMPLOYED:
4801 : // na
4802 :
4803 : // REFERENCES:
4804 : // Kays, W.M. and A.L. London. 1964.Compact Heat Exchangers, 2nd Ed.McGraw-Hill:New York.
4805 :
4806 : // USE STATEMENTS:
4807 : // na
4808 :
4809 : // Enforce explicit typing of all variables in this routine
4810 :
4811 : // Locals
4812 : // FUNCTION ARGUMENT DEFINITIONS:
4813 :
4814 : // FUNCTION PARAMETER DEFINITIONS:
4815 44416903 : Real64 constexpr LargeNo(1.e10); // value used in place of infinity
4816 44416903 : Real64 constexpr SmallNo(1.e-15); // value used in place of zero
4817 :
4818 : // INTERFACE BLOCK SPECIFICATIONS
4819 : // na
4820 :
4821 : // DERIVED TYPE DEFINITIONS
4822 : // na
4823 :
4824 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
4825 : Real64 MinimumCapacityStream; // Minimum capacity rate of the streams(W/C)
4826 : Real64 MaximumCapacityStream; // Maximum capacity rate of the streams(W/C)
4827 : Real64 RatioStreamCapacity; // Ratio of minimum to maximum capacity rate
4828 : Real64 NTU; // Number of transfer units
4829 44416903 : Real64 effectiveness(0.0); // Heat exchanger effectiveness
4830 : Real64 MaxHeatTransfer; // Maximum heat transfer possible(W)
4831 : Real64 e; // Intermediate variables in effectiveness equation
4832 : Real64 eta;
4833 : Real64 b;
4834 : Real64 d;
4835 :
4836 : // NTU and MinimumCapacityStream/MaximumCapacityStream (RatioStreamCapacity) calculations
4837 44416903 : MinimumCapacityStream = min(CapacityStream1, CapacityStream2);
4838 44416903 : MaximumCapacityStream = max(CapacityStream1, CapacityStream2);
4839 :
4840 44416903 : if (std::abs(MaximumCapacityStream) <= 1.e-6) { // .EQ. 0.0d0) THEN
4841 0 : RatioStreamCapacity = 1.0;
4842 : } else {
4843 44416903 : RatioStreamCapacity = MinimumCapacityStream / MaximumCapacityStream;
4844 : }
4845 :
4846 44416903 : if (std::abs(MinimumCapacityStream) <= 1.e-6) { // .EQ. 0.0d0) THEN
4847 0 : NTU = LargeNo;
4848 : } else {
4849 44416903 : NTU = CoilUA / MinimumCapacityStream;
4850 : }
4851 :
4852 : // Calculate effectiveness for special limiting cases
4853 44416903 : if (NTU <= 0.0) {
4854 171699 : effectiveness = 0.0;
4855 :
4856 44245204 : } else if (RatioStreamCapacity < SmallNo) {
4857 : // MinimumCapacityStream/MaximumCapacityStream = 0 and effectiveness is independent of configuration
4858 : // 20 is the Limit Chosen for Exponential Function, beyond which there is float point error.
4859 0 : if (NTU > 20.0) {
4860 0 : effectiveness = 1.0;
4861 : } else {
4862 0 : effectiveness = 1.0 - std::exp(-NTU);
4863 : }
4864 : // Calculate effectiveness depending on heat exchanger configuration
4865 44245204 : } else if (state.dataWaterCoils->WaterCoil(CoilNum).HeatExchType == state.dataWaterCoils->CounterFlow) {
4866 :
4867 : // Counterflow Heat Exchanger Configuration
4868 12283 : if (std::abs(RatioStreamCapacity - 1.0) < SmallNo) {
4869 0 : effectiveness = NTU / (NTU + 1.0);
4870 : } else {
4871 12283 : if (NTU * (1.0 - RatioStreamCapacity) > 20.0) {
4872 0 : e = 0.0;
4873 : } else {
4874 12283 : e = std::exp(-NTU * (1.0 - RatioStreamCapacity));
4875 : }
4876 12283 : effectiveness = (1.0 - e) / (1.0 - RatioStreamCapacity * e);
4877 : }
4878 :
4879 44232921 : } else if (state.dataWaterCoils->WaterCoil(CoilNum).HeatExchType == state.dataWaterCoils->CrossFlow) {
4880 : // Cross flow, both streams unmixed
4881 44232921 : eta = std::pow(NTU, -0.22);
4882 44232921 : if ((NTU * RatioStreamCapacity * eta) > 20.0) {
4883 0 : b = 1.0 / (RatioStreamCapacity * eta);
4884 0 : if (b > 20.0) {
4885 0 : effectiveness = 1.0;
4886 : } else {
4887 0 : effectiveness = 1.0 - std::exp(-b);
4888 0 : if (effectiveness < 0.0) effectiveness = 0.0;
4889 : }
4890 : } else {
4891 44232921 : d = ((std::exp(-NTU * RatioStreamCapacity * eta) - 1.0) / (RatioStreamCapacity * eta));
4892 44232921 : if (d < -20.0 || d > 0.0) {
4893 15093 : effectiveness = 1.0;
4894 : } else {
4895 44217828 : effectiveness = 1.0 - std::exp((std::exp(-NTU * RatioStreamCapacity * eta) - 1.0) / (RatioStreamCapacity * eta));
4896 44217828 : if (effectiveness < 0.0) effectiveness = 0.0;
4897 : }
4898 : }
4899 : }
4900 :
4901 : // Determine leaving conditions for the two streams
4902 44416903 : MaxHeatTransfer = max(MinimumCapacityStream, SmallNo) * (EnergyInStreamOne - EnergyInStreamTwo);
4903 44416903 : EnergyOutStreamOne = EnergyInStreamOne - effectiveness * MaxHeatTransfer / max(CapacityStream1, SmallNo);
4904 44416903 : EnergyOutStreamTwo = EnergyInStreamTwo + effectiveness * MaxHeatTransfer / max(CapacityStream2, SmallNo);
4905 44416903 : }
4906 :
4907 : // Subroutine for caculating outlet condition if coil is wet , for Cooling Coil
4908 :
4909 26633111 : void WetCoilOutletCondition(EnergyPlusData &state,
4910 : int const CoilNum,
4911 : Real64 const AirTempIn, // Entering air dry bulb temperature(C)
4912 : Real64 const EnthAirInlet, // Entering air enthalpy(J/kg)
4913 : Real64 const EnthAirOutlet, // Leaving air enthalpy(J/kg)
4914 : Real64 const UACoilExternal, // Heat transfer coefficient for external surface (W/C)
4915 : Real64 &OutletAirTemp, // Leaving air dry bulb temperature(C)
4916 : Real64 &OutletAirHumRat, // Leaving air humidity ratio
4917 : Real64 &SenWaterCoilLoad // Sensible heat transfer rate(W)
4918 : )
4919 : {
4920 :
4921 : // FUNCTION INFORMATION:
4922 : // AUTHOR Rahul Chillar
4923 : // DATE WRITTEN Mar 2004
4924 : // MODIFIED na
4925 : // RE-ENGINEERED na
4926 :
4927 : // PURPOSE OF THIS FUNCTION:
4928 : // Calculate the leaving air temperature,the leaving air humidity ratio and the
4929 : // sensible cooling capacity of wet cooling coil.
4930 :
4931 : // METHODOLOGY EMPLOYED:
4932 : // Assumes condensate at uniform temperature.
4933 :
4934 : // REFERENCES:
4935 : // Elmahdy, A.H. and Mitalas, G.P. 1977."A Simple Model for Cooling and
4936 : // Dehumidifying Coils for Use In Calculating Energy Requirements for Buildings,"
4937 : // ASHRAE Transactions,Vol.83 Part 2, pp. 103-117.
4938 :
4939 : // USE STATEMENTS:
4940 :
4941 : // Enforce explicit typing of all variables in this routine
4942 :
4943 : // Locals
4944 : // FUNCTION ARGUMENT DEFINITIONS:
4945 :
4946 : // FUNCTION PARAMETER DEFINITIONS:
4947 26633111 : Real64 constexpr SmallNo(1.e-9); // SmallNo value used in place of zero
4948 :
4949 : // INTERFACE BLOCK SPECIFICATIONS
4950 : // na
4951 :
4952 : // DERIVED TYPE DEFINITIONS
4953 : // na
4954 :
4955 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
4956 : Real64 CapacitanceAir; // Air capacity rate(W/C)
4957 : Real64 NTU; // Number of heat transfer units
4958 : Real64 effectiveness; // Heat exchanger effectiveness
4959 : Real64 EnthAirCondensateTemp; // Saturated air enthalpy at temperature of condensate(J/kg)
4960 : Real64 TempCondensation; // Temperature of condensate(C)
4961 : Real64 TempAirDewPoint; // Temperature air dew point
4962 :
4963 : // Determine the temperature effectiveness, assuming the temperature
4964 : // of the condensate is constant (MinimumCapacityStream/MaximumCapacityStream = 0) and the specific heat
4965 : // of moist air is constant
4966 26633111 : CapacitanceAir =
4967 26633111 : state.dataWaterCoils->WaterCoil(CoilNum).InletAirMassFlowRate * PsyCpAirFnW(state.dataWaterCoils->WaterCoil(CoilNum).InletAirHumRat);
4968 :
4969 : // Calculating NTU from UA and Capacitance.
4970 : // del NTU = UACoilExternal/MAX(CapacitanceAir,SmallNo)
4971 : // del effectiveness = 1 - EXP(-MAX(0.0d0,NTU))
4972 : // Calculating NTU from UA and Capacitance.
4973 26633111 : if (UACoilExternal > 0.0) {
4974 26633111 : if (CapacitanceAir > 0.0) {
4975 26633111 : NTU = UACoilExternal / CapacitanceAir;
4976 : } else {
4977 0 : NTU = 0.0;
4978 : }
4979 26633111 : effectiveness = 1.0 - std::exp(-NTU);
4980 : } else {
4981 0 : effectiveness = 0.0;
4982 : }
4983 :
4984 : // Calculate coil surface enthalpy and temperature at the exit
4985 : // of the wet part of the coil using the effectiveness relation
4986 26633111 : effectiveness = max(effectiveness, SmallNo);
4987 26633111 : EnthAirCondensateTemp = EnthAirInlet - (EnthAirInlet - EnthAirOutlet) / effectiveness;
4988 :
4989 : // Calculate condensate temperature as the saturation temperature
4990 : // at given saturation enthalpy
4991 26633111 : TempCondensation = PsyTsatFnHPb(state, EnthAirCondensateTemp, state.dataEnvrn->OutBaroPress);
4992 :
4993 26633111 : TempAirDewPoint = PsyTdpFnWPb(state, state.dataWaterCoils->WaterCoil(CoilNum).InletAirHumRat, state.dataEnvrn->OutBaroPress);
4994 :
4995 26633111 : if ((TempAirDewPoint - TempCondensation) > 0.1) {
4996 :
4997 : // Calculate Outlet Air Temperature using effectivness
4998 23255988 : OutletAirTemp = AirTempIn - (AirTempIn - TempCondensation) * effectiveness;
4999 : // Calculate Outlet air humidity ratio from PsyWFnTdbH routine
5000 23255988 : OutletAirHumRat = PsyWFnTdbH(state, OutletAirTemp, EnthAirOutlet);
5001 :
5002 : } else {
5003 3377123 : OutletAirHumRat = state.dataWaterCoils->WaterCoil(CoilNum).InletAirHumRat;
5004 3377123 : OutletAirTemp = PsyTdbFnHW(EnthAirOutlet, OutletAirHumRat);
5005 : }
5006 :
5007 : // Calculate Sensible Coil Load
5008 26633111 : SenWaterCoilLoad = CapacitanceAir * (AirTempIn - OutletAirTemp);
5009 26633111 : }
5010 :
5011 : // Beginning of Update subroutines for the WaterCoil Module
5012 : // *****************************************************************************
5013 :
5014 137535475 : void UpdateWaterCoil(EnergyPlusData &state, int const CoilNum)
5015 : {
5016 : // SUBROUTINE INFORMATION:
5017 : // AUTHOR Richard Liesen
5018 : // DATE WRITTEN 1998
5019 : // MODIFIED April 2004: Rahul Chillar
5020 : // Feb 2010 B. Griffith, plant upgrades
5021 : // RE-ENGINEERED na
5022 :
5023 : // PURPOSE OF THIS SUBROUTINE:
5024 : // This subroutine updates the coil outlet nodes.
5025 :
5026 : // METHODOLOGY EMPLOYED:
5027 : // Data is moved from the coil data structure to the coil outlet nodes.
5028 :
5029 : // REFERENCES:
5030 : // na
5031 :
5032 : // Using/Aliasing
5033 : using PlantUtilities::SetComponentFlowRate;
5034 :
5035 : // Locals
5036 : // SUBROUTINE ARGUMENT DEFINITIONS:
5037 :
5038 : // SUBROUTINE PARAMETER DEFINITIONS:
5039 : // na
5040 :
5041 : // INTERFACE BLOCK SPECIFICATIONS
5042 : // na
5043 :
5044 : // DERIVED TYPE DEFINITIONS
5045 : // na
5046 :
5047 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
5048 : int AirInletNode;
5049 : int WaterInletNode;
5050 : int AirOutletNode;
5051 : int WaterOutletNode;
5052 :
5053 137535475 : AirInletNode = state.dataWaterCoils->WaterCoil(CoilNum).AirInletNodeNum;
5054 137535475 : WaterInletNode = state.dataWaterCoils->WaterCoil(CoilNum).WaterInletNodeNum;
5055 137535475 : AirOutletNode = state.dataWaterCoils->WaterCoil(CoilNum).AirOutletNodeNum;
5056 137535475 : WaterOutletNode = state.dataWaterCoils->WaterCoil(CoilNum).WaterOutletNodeNum;
5057 :
5058 : // Set the outlet air nodes of the WaterCoil
5059 137535475 : state.dataLoopNodes->Node(AirOutletNode).MassFlowRate = state.dataWaterCoils->WaterCoil(CoilNum).OutletAirMassFlowRate;
5060 137535475 : state.dataLoopNodes->Node(AirOutletNode).Temp = state.dataWaterCoils->WaterCoil(CoilNum).OutletAirTemp;
5061 137535475 : state.dataLoopNodes->Node(AirOutletNode).HumRat = state.dataWaterCoils->WaterCoil(CoilNum).OutletAirHumRat;
5062 137535475 : state.dataLoopNodes->Node(AirOutletNode).Enthalpy = state.dataWaterCoils->WaterCoil(CoilNum).OutletAirEnthalpy;
5063 :
5064 137535475 : state.dataLoopNodes->Node(WaterOutletNode).Temp = state.dataWaterCoils->WaterCoil(CoilNum).OutletWaterTemp;
5065 137535475 : state.dataLoopNodes->Node(WaterOutletNode).Enthalpy = state.dataWaterCoils->WaterCoil(CoilNum).OutletWaterEnthalpy;
5066 :
5067 : // Set the outlet nodes for properties that just pass through & not used
5068 137535475 : state.dataLoopNodes->Node(AirOutletNode).Quality = state.dataLoopNodes->Node(AirInletNode).Quality;
5069 137535475 : state.dataLoopNodes->Node(AirOutletNode).Press = state.dataLoopNodes->Node(AirInletNode).Press;
5070 137535475 : state.dataLoopNodes->Node(AirOutletNode).MassFlowRateMin = state.dataLoopNodes->Node(AirInletNode).MassFlowRateMin;
5071 137535475 : state.dataLoopNodes->Node(AirOutletNode).MassFlowRateMax = state.dataLoopNodes->Node(AirInletNode).MassFlowRateMax;
5072 137535475 : state.dataLoopNodes->Node(AirOutletNode).MassFlowRateMinAvail = state.dataLoopNodes->Node(AirInletNode).MassFlowRateMinAvail;
5073 137535475 : state.dataLoopNodes->Node(AirOutletNode).MassFlowRateMaxAvail = state.dataLoopNodes->Node(AirInletNode).MassFlowRateMaxAvail;
5074 137535475 : if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
5075 0 : state.dataLoopNodes->Node(AirOutletNode).CO2 = state.dataLoopNodes->Node(AirInletNode).CO2;
5076 : }
5077 137535475 : if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
5078 0 : state.dataLoopNodes->Node(AirOutletNode).GenContam = state.dataLoopNodes->Node(AirInletNode).GenContam;
5079 : }
5080 137535475 : }
5081 :
5082 : // End of Update subroutines for the WaterCoil Module
5083 : // *****************************************************************************
5084 :
5085 : // Beginning of Reporting subroutines for the WaterCoil Module
5086 : // *****************************************************************************
5087 :
5088 137535475 : void ReportWaterCoil(EnergyPlusData &state, int const CoilNum)
5089 : {
5090 :
5091 : // SUBROUTINE INFORMATION:
5092 : // AUTHOR Richard Liesen
5093 : // DATE WRITTEN 1998
5094 : // MODIFIED na
5095 : // RE-ENGINEERED na
5096 :
5097 : // PURPOSE OF THIS SUBROUTINE:
5098 : // This subroutine updates the report variable for the coils.
5099 :
5100 : // METHODOLOGY EMPLOYED:
5101 : // NA
5102 :
5103 : // REFERENCES:
5104 : // na
5105 :
5106 : // Using/Aliasing
5107 :
5108 : // Locals
5109 : // SUBROUTINE ARGUMENT DEFINITIONS:
5110 :
5111 : // SUBROUTINE PARAMETER DEFINITIONS:
5112 : static constexpr std::string_view RoutineName("ReportWaterCoil");
5113 :
5114 : // INTERFACE BLOCK SPECIFICATIONS
5115 : // na
5116 :
5117 : // DERIVED TYPE DEFINITIONS
5118 : // na
5119 :
5120 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
5121 : Real64 RhoWater;
5122 : Real64 Tavg;
5123 : Real64 SpecHumOut;
5124 : Real64 SpecHumIn;
5125 : Real64 ReportingConstant;
5126 :
5127 137535475 : if (state.dataWaterCoils->WaterCoil(CoilNum).reportCoilFinalSizes) {
5128 18944507 : if (!state.dataGlobal->WarmupFlag && !state.dataGlobal->DoingHVACSizingSimulations && !state.dataGlobal->DoingSizing) {
5129 6200 : std::string coilObjClassName;
5130 3100 : if (state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterSimpleHeating) {
5131 2554 : coilObjClassName = "Coil:Heating:Water";
5132 15324 : state.dataRptCoilSelection->coilSelectionReportObj->setCoilFinalSizes(
5133 : state,
5134 2554 : state.dataWaterCoils->WaterCoil(CoilNum).Name,
5135 : coilObjClassName,
5136 2554 : state.dataWaterCoils->WaterCoil(CoilNum).DesWaterHeatingCoilRate,
5137 2554 : state.dataWaterCoils->WaterCoil(CoilNum).DesWaterHeatingCoilRate,
5138 2554 : state.dataWaterCoils->WaterCoil(CoilNum).DesAirVolFlowRate,
5139 2554 : state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterVolFlowRate);
5140 2554 : state.dataWaterCoils->WaterCoil(CoilNum).reportCoilFinalSizes = false;
5141 546 : } else if (state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterDetailedFlatCooling) {
5142 143 : coilObjClassName = "Coil:Cooling:Water:DetailedGeometry";
5143 715 : state.dataRptCoilSelection->coilSelectionReportObj->setCoilFinalSizes(
5144 : state,
5145 143 : state.dataWaterCoils->WaterCoil(CoilNum).Name,
5146 : coilObjClassName,
5147 143 : state.dataWaterCoils->WaterCoil(CoilNum).DesWaterCoolingCoilRate,
5148 : -999.0,
5149 143 : state.dataWaterCoils->WaterCoil(CoilNum).DesAirVolFlowRate,
5150 143 : state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterVolFlowRate);
5151 143 : state.dataWaterCoils->WaterCoil(CoilNum).reportCoilFinalSizes = false;
5152 403 : } else if (state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterCooling) {
5153 403 : coilObjClassName = "Coil:Cooling:Water";
5154 2015 : state.dataRptCoilSelection->coilSelectionReportObj->setCoilFinalSizes(
5155 : state,
5156 403 : state.dataWaterCoils->WaterCoil(CoilNum).Name,
5157 : coilObjClassName,
5158 403 : state.dataWaterCoils->WaterCoil(CoilNum).DesWaterCoolingCoilRate,
5159 : -999.0,
5160 403 : state.dataWaterCoils->WaterCoil(CoilNum).DesAirVolFlowRate,
5161 403 : state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterVolFlowRate);
5162 403 : state.dataWaterCoils->WaterCoil(CoilNum).reportCoilFinalSizes = false;
5163 : }
5164 : }
5165 : }
5166 137535475 : ReportingConstant = state.dataHVACGlobal->TimeStepSys * DataGlobalConstants::SecInHour;
5167 : // report the WaterCoil energy from this component
5168 137535475 : state.dataWaterCoils->WaterCoil(CoilNum).TotWaterHeatingCoilEnergy =
5169 137535475 : state.dataWaterCoils->WaterCoil(CoilNum).TotWaterHeatingCoilRate * ReportingConstant;
5170 137535475 : state.dataWaterCoils->WaterCoil(CoilNum).TotWaterCoolingCoilEnergy =
5171 137535475 : state.dataWaterCoils->WaterCoil(CoilNum).TotWaterCoolingCoilRate * ReportingConstant;
5172 137535475 : state.dataWaterCoils->WaterCoil(CoilNum).SenWaterCoolingCoilEnergy =
5173 137535475 : state.dataWaterCoils->WaterCoil(CoilNum).SenWaterCoolingCoilRate * ReportingConstant;
5174 :
5175 : // report the WaterCoil water collection to water storage tank (if needed)
5176 :
5177 137535475 : if (state.dataWaterCoils->WaterCoil(CoilNum).CondensateCollectMode == state.dataWaterCoils->CondensateToTank) {
5178 : // calculate and report condensation rates (how much water extracted from the air stream)
5179 : // water volumetric flow of water in m3/s for water system interactions
5180 : // put here to catch all types of DX coils
5181 0 : Tavg = (state.dataWaterCoils->WaterCoil(CoilNum).InletAirTemp - state.dataWaterCoils->WaterCoil(CoilNum).OutletAirTemp) / 2.0;
5182 :
5183 0 : RhoWater = GetDensityGlycol(state,
5184 0 : state.dataPlnt->PlantLoop(state.dataWaterCoils->WaterCoil(CoilNum).WaterPlantLoc.loopNum).FluidName,
5185 : Tavg,
5186 0 : state.dataPlnt->PlantLoop(state.dataWaterCoils->WaterCoil(CoilNum).WaterPlantLoc.loopNum).FluidIndex,
5187 : RoutineName);
5188 : // CR9155 Remove specific humidity calculations
5189 0 : SpecHumIn = state.dataWaterCoils->WaterCoil(CoilNum).InletAirHumRat;
5190 0 : SpecHumOut = state.dataWaterCoils->WaterCoil(CoilNum).OutletAirHumRat;
5191 : // mdot * del HumRat / rho water
5192 0 : state.dataWaterCoils->WaterCoil(CoilNum).CondensateVdot =
5193 0 : max(0.0, (state.dataWaterCoils->WaterCoil(CoilNum).InletAirMassFlowRate * (SpecHumIn - SpecHumOut) / RhoWater));
5194 0 : state.dataWaterCoils->WaterCoil(CoilNum).CondensateVol = state.dataWaterCoils->WaterCoil(CoilNum).CondensateVdot * ReportingConstant;
5195 :
5196 0 : state.dataWaterData->WaterStorage(state.dataWaterCoils->WaterCoil(CoilNum).CondensateTankID)
5197 0 : .VdotAvailSupply(state.dataWaterCoils->WaterCoil(CoilNum).CondensateTankSupplyARRID) =
5198 0 : state.dataWaterCoils->WaterCoil(CoilNum).CondensateVdot;
5199 0 : state.dataWaterData->WaterStorage(state.dataWaterCoils->WaterCoil(CoilNum).CondensateTankID)
5200 0 : .TwaterSupply(state.dataWaterCoils->WaterCoil(CoilNum).CondensateTankSupplyARRID) =
5201 0 : state.dataWaterCoils->WaterCoil(CoilNum).OutletAirTemp;
5202 : }
5203 137535475 : }
5204 :
5205 : // End of Reporting subroutines for the WaterCoil Module
5206 : // *****************************************************************************
5207 :
5208 : // Beginning of Coil Utility subroutines for the Detailed Model
5209 : // *****************************************************************************
5210 :
5211 872 : void CalcDryFinEffCoef(EnergyPlusData &state, Real64 const OutTubeEffFinDiamRatio, Array1D<Real64> &PolynomCoef)
5212 : {
5213 : // SUBROUTINE INFORMATION:
5214 : // AUTHOR Unknown
5215 : // DATE WRITTEN Unknown
5216 : // DATE REWRITTEN April 1997 by Russell D. Taylor, Ph.D.
5217 : // MODIFIED
5218 : // RE-ENGINEERED
5219 :
5220 : // PURPOSE OF THIS SUBROUTINE:
5221 : // The following subroutines are used once per cooling coil
5222 : // simulation to obtain the coefficients of the dry fin
5223 : // efficiency equation. CalcDryFinEffCoef is the main calling
5224 : // routine which manages calls to the Bessel funtion and polynomial
5225 : // fit routines.
5226 :
5227 : // REFERENCES:
5228 : // First found in MODSIM.
5229 : // USE STATEMENTS:
5230 : // na
5231 :
5232 : // Argument array dimensioning
5233 :
5234 : // Locals
5235 : // SUBROUTINE ARGUMENT DEFINITIONS:
5236 :
5237 : // SUBROUTINE PARAMETER DEFINITIONS:
5238 : // na
5239 :
5240 : // INTERFACE BLOCK SPECIFICATIONS
5241 : // na
5242 :
5243 : // DERIVED TYPE DEFINITIONS
5244 : // na
5245 :
5246 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
5247 : Real64 FAI;
5248 : Real64 FED;
5249 : Real64 FEDnumerator;
5250 : int I;
5251 : int IE1;
5252 : int IE2;
5253 : int IE3;
5254 : int IE4;
5255 : int IE5;
5256 : int IE6;
5257 : Real64 R1;
5258 : Real64 R1I1;
5259 : Real64 R1K1;
5260 : Real64 R2;
5261 : Real64 R2I0;
5262 : Real64 R2I1;
5263 : Real64 R2K0;
5264 : Real64 R2K1;
5265 : Real64 RO;
5266 :
5267 872 : FAI = 0.02;
5268 53192 : for (I = 1; I <= WaterCoils::MaxOrderedPairs; ++I) {
5269 52320 : FAI += 0.035;
5270 52320 : R1 = FAI / (1.0 - OutTubeEffFinDiamRatio);
5271 52320 : R2 = R1 * OutTubeEffFinDiamRatio;
5272 52320 : RO = 2.0 * OutTubeEffFinDiamRatio / (FAI * (1.0 + OutTubeEffFinDiamRatio));
5273 52320 : CalcIBesselFunc(R1, 1, R1I1, IE1);
5274 52320 : CalcKBesselFunc(R2, 1, R2K1, IE2);
5275 52320 : CalcIBesselFunc(R2, 1, R2I1, IE3);
5276 52320 : CalcKBesselFunc(R1, 1, R1K1, IE4);
5277 52320 : CalcIBesselFunc(R2, 0, R2I0, IE5);
5278 52320 : CalcKBesselFunc(R2, 0, R2K0, IE6);
5279 52320 : FEDnumerator = RO * (R1I1 * R2K1 - R2I1 * R1K1);
5280 52320 : if (FEDnumerator != 0.0) {
5281 52320 : FED = FEDnumerator / (R2I0 * R1K1 + R1I1 * R2K0);
5282 : } else {
5283 0 : FED = 0.0;
5284 : }
5285 : // FED = RO * (R1I1 * R2K1 - R2I1 * R1K1) / (R2I0 * R1K1 + R1I1 * R2K0)
5286 52320 : state.dataWaterCoils->OrderedPair(I, 1) = FAI;
5287 52320 : state.dataWaterCoils->OrderedPair(I, 2) = FED;
5288 : }
5289 872 : CalcPolynomCoef(state, state.dataWaterCoils->OrderedPair, PolynomCoef);
5290 872 : }
5291 :
5292 156960 : void CalcIBesselFunc(Real64 const BessFuncArg, int const BessFuncOrd, Real64 &IBessFunc, int &ErrorCode)
5293 : {
5294 : // SUBROUTINE INFORMATION:
5295 : // AUTHOR Unknown
5296 : // DATE WRITTEN Unknown
5297 : // DATE REWRITTEN April 1997 by Russell D. Taylor, Ph.D.
5298 : // MODIFIED
5299 : // RE-ENGINEERED
5300 :
5301 : // PURPOSE OF THIS SUBROUTINE:
5302 : // To calculate the modified Bessel Function from order 0 to BessFuncOrd
5303 : // BessFuncArg ARGUMENT OF BESSEL FUNCTION
5304 : // BessFuncOrd ORDER OF BESSEL FUNCTION, GREATER THAN OR EQUAL TO ZERO
5305 : // IBessFunc RESULTANT VALUE OF I BESSEL FUNCTION
5306 : // ErrorCode RESULTANT ERROR CODE:
5307 : // ErrorCode = 0 NO ERROR
5308 : // ErrorCode = 1 BessFuncOrd .LT. 0
5309 : // ErrorCode = 2 BessFuncArg .LT. 0
5310 : // ErrorCode = 3 IBessFunc .LT. 10**(-30), IBessFunc IS SET TO 0
5311 : // ErrorCode = 4 BessFuncArg .GT. BessFuncOrd & BessFuncArg .GT. 90, IBessFunc IS SET TO 10**38
5312 :
5313 : // REFERENCES:
5314 : // First found in MODSIM.
5315 :
5316 : // USE STATEMENTS:
5317 : // na
5318 :
5319 : // Locals
5320 : // SUBROUTINE ARGUMENT DEFINITIONS:
5321 :
5322 : // SUBROUTINE PARAMETER DEFINITIONS:
5323 156960 : Real64 constexpr ErrorTol(1.0e-06);
5324 :
5325 : // INTERFACE BLOCK SPECIFICATIONS
5326 : // na
5327 :
5328 : // DERIVED TYPE DEFINITIONS
5329 : // na
5330 :
5331 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
5332 : int LoopCount;
5333 :
5334 : Real64 FI;
5335 : Real64 FK;
5336 : Real64 TERM;
5337 :
5338 156960 : ErrorCode = 0;
5339 156960 : IBessFunc = 1.0;
5340 156960 : if (BessFuncArg == 0.0 && BessFuncOrd == 0) return;
5341 :
5342 156960 : if (BessFuncOrd < 0) {
5343 0 : ErrorCode = 1;
5344 0 : return;
5345 156960 : } else if (BessFuncArg < 0.0) {
5346 0 : ErrorCode = 2;
5347 0 : return;
5348 156960 : } else if (BessFuncArg > 12.0 && BessFuncArg > BessFuncOrd) {
5349 0 : if (BessFuncArg > 90.0) {
5350 0 : ErrorCode = 4;
5351 0 : IBessFunc = 1.0e30;
5352 0 : return;
5353 : }
5354 0 : TERM = 1.0;
5355 0 : IBessFunc = 1.0;
5356 0 : for (LoopCount = 1; LoopCount <= 30; ++LoopCount) { // Start of 1st LoopCount Loop
5357 0 : if (std::abs(TERM) <= std::abs(ErrorTol * IBessFunc)) {
5358 0 : IBessFunc *= std::exp(BessFuncArg) / std::sqrt(2.0 * DataGlobalConstants::Pi * BessFuncArg);
5359 0 : return;
5360 : }
5361 0 : TERM *= 0.125 / BessFuncArg * (pow_2(2 * LoopCount - 1) - 4 * BessFuncOrd * BessFuncOrd) / double(LoopCount);
5362 0 : IBessFunc += TERM;
5363 : } // End of 1st LoopCount loop
5364 : }
5365 :
5366 156960 : TERM = 1.0;
5367 156960 : if (BessFuncOrd > 0) {
5368 209280 : for (LoopCount = 1; LoopCount <= BessFuncOrd; ++LoopCount) { // Start of 2nd LoopCount Loop
5369 104640 : FI = LoopCount;
5370 104640 : if (std::abs(TERM) < 1.0e-30 * FI / (BessFuncArg * 2.0)) {
5371 0 : ErrorCode = 3;
5372 0 : IBessFunc = 0.0;
5373 0 : return;
5374 : }
5375 104640 : TERM *= BessFuncArg / (2.0 * FI);
5376 : } // End of 2nd LoopCount loop
5377 : }
5378 :
5379 156960 : IBessFunc = TERM;
5380 970432 : for (LoopCount = 1; LoopCount <= 1000; ++LoopCount) { // Start of 3rd LoopCount Loop
5381 970432 : if (std::abs(TERM) <= std::abs(IBessFunc * ErrorTol)) return;
5382 813472 : FK = LoopCount * (BessFuncOrd + LoopCount);
5383 813472 : TERM *= pow_2(BessFuncArg) / (4.0 * FK);
5384 813472 : IBessFunc += TERM;
5385 : } // End of 3rd LoopCount loop
5386 : }
5387 :
5388 156960 : void CalcKBesselFunc(Real64 const BessFuncArg, int const BessFuncOrd, Real64 &KBessFunc, int &ErrorCode)
5389 : {
5390 : // SUBROUTINE INFORMATION:
5391 : // AUTHOR Unknown
5392 : // DATE WRITTEN Unknown
5393 : // DATE REWRITTEN April 1997 by Russell D. Taylor, Ph.D.
5394 : // MODIFIED
5395 : // RE-ENGINEERED
5396 :
5397 : // PURPOSE OF THIS SUBROUTINE:
5398 : // To calculate the K Bessel Function for a given argument and
5399 : // order
5400 : // BessFuncArg THE ARGUMENT OF THE K BESSEL FUNCTION DESIRED
5401 : // BessFuncOrd THE ORDER OF THE K BESSEL FUNCTION DESIRED
5402 : // KBessFunc THE RESULTANT K BESSEL FUNCTION
5403 : // ErrorCode RESULTANT ERROR CODE:
5404 : // ErrorCode=0 NO ERROR
5405 : // ErrorCode=1 BessFuncOrd IS NEGATIVE
5406 : // ErrorCode=2 BessFuncArg IS ZERO OR NEGATIVE
5407 : // ErrorCode=3 BessFuncArg .GT. 85, KBessFunc .LT. 10**-38; KBessFunc SET TO 0.
5408 : // ErrorCode=4 KBessFunc .GT. 10**38; KBessFunc SET TO 10**38
5409 : // NOTE: BessFuncOrd MUST BE GREATER THAN OR EQUAL TO ZERO
5410 : // METHOD:
5411 : // COMPUTES ZERO ORDER AND FIRST ORDER BESSEL FUNCTIONS USING
5412 : // SERIES APPROXIMATIONS AND THEN COMPUTES BessFuncOrd TH ORDER FUNCTION
5413 : // USING RECURRENCE RELATION.
5414 : // RECURRENCE RELATION AND POLYNOMIAL APPROXIMATION TECHNIQUE
5415 : // AS DESCRIBED BY A.J.M. HITCHCOCK, 'POLYNOMIAL APPROXIMATIONS
5416 : // TO BESSEL FUNCTIONS OF ORDER ZERO AND ONE AND TO RELATED
5417 : // FUNCTIONS,' M.T.A.C., V.11, 1957, PP. 86-88, AND G.BessFuncOrd. WATSON,
5418 : // 'A TREATISE ON THE THEORY OF BESSEL FUNCTIONS,' CAMBRIDGE
5419 : // UNIVERSITY PRESS, 1958, P.62
5420 :
5421 : // USE STATEMENTS:
5422 : // na
5423 :
5424 : // Locals
5425 : // SUBROUTINE ARGUMENT DEFINITIONS:
5426 :
5427 : // SUBROUTINE PARAMETER DEFINITIONS:
5428 156960 : Real64 constexpr GJMAX(1.0e+38);
5429 :
5430 : // INTERFACE BLOCK SPECIFICATIONS
5431 : // na
5432 :
5433 : // DERIVED TYPE DEFINITIONS
5434 : // na
5435 :
5436 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
5437 : int LoopCount;
5438 : bool StopLoop;
5439 :
5440 : Real64 FACT;
5441 : Real64 G0;
5442 : Real64 G1;
5443 : Real64 GJ;
5444 : Real64 HJ;
5445 156960 : Array1D<Real64> T(12);
5446 : Real64 X2J;
5447 :
5448 156960 : KBessFunc = 0.0;
5449 156960 : G0 = 0.0;
5450 156960 : GJ = 0.0;
5451 :
5452 156960 : if (BessFuncOrd < 0.0) {
5453 0 : ErrorCode = 1;
5454 0 : return;
5455 156960 : } else if (BessFuncArg <= 0.0) {
5456 0 : ErrorCode = 2;
5457 0 : return;
5458 156960 : } else if (BessFuncArg > 85.0) {
5459 0 : ErrorCode = 3;
5460 0 : KBessFunc = 0.0;
5461 0 : return;
5462 : }
5463 :
5464 156960 : ErrorCode = 0;
5465 :
5466 : // Use polynomial approximation if BessFuncArg > 1.
5467 :
5468 156960 : if (BessFuncArg > 1.0) {
5469 95694 : T(1) = 1.0 / BessFuncArg;
5470 1148328 : for (LoopCount = 2; LoopCount <= 12; ++LoopCount) {
5471 1052634 : T(LoopCount) = T(LoopCount - 1) / BessFuncArg;
5472 : } // End of LoopCount Loop
5473 95694 : if (BessFuncOrd != 1) {
5474 :
5475 : // Compute K0 using polynomial approximation
5476 :
5477 82587 : G0 = std::exp(-BessFuncArg) *
5478 55058 : (1.2533141 - 0.1566642 * T(1) + 0.08811128 * T(2) - 0.09139095 * T(3) + 0.1344596 * T(4) - 0.2299850 * T(5) + 0.3792410 * T(6) -
5479 55058 : 0.5247277 * T(7) + 0.5575368 * T(8) - 0.4262633 * T(9) + 0.2184518 * T(10) - 0.06680977 * T(11) + 0.009189383 * T(12)) *
5480 27529 : std::sqrt(1.0 / BessFuncArg);
5481 27529 : if (BessFuncOrd == 0) {
5482 27529 : KBessFunc = G0;
5483 27529 : return;
5484 : }
5485 : }
5486 :
5487 : // Compute K1 using polynomial approximation
5488 :
5489 204495 : G1 = std::exp(-BessFuncArg) *
5490 136330 : (1.2533141 + 0.4699927 * T(1) - 0.1468583 * T(2) + 0.1280427 * T(3) - 0.1736432 * T(4) + 0.2847618 * T(5) - 0.4594342 * T(6) +
5491 136330 : 0.6283381 * T(7) - 0.6632295 * T(8) + 0.5050239 * T(9) - 0.2581304 * T(10) + 0.07880001 * T(11) - 0.01082418 * T(12)) *
5492 68165 : std::sqrt(1.0 / BessFuncArg);
5493 68165 : if (BessFuncOrd == 1) {
5494 68165 : KBessFunc = G1;
5495 68165 : return;
5496 : }
5497 : } else {
5498 :
5499 : // Use series expansion if BessFuncArg <= 1.
5500 :
5501 61266 : if (BessFuncOrd != 1) {
5502 :
5503 : // Compute K0 using series expansion
5504 :
5505 24791 : G0 = -(0.5772157 + std::log(BessFuncArg / 2.0));
5506 24791 : X2J = 1.0;
5507 24791 : FACT = 1.0;
5508 24791 : HJ = 0.0;
5509 173537 : for (LoopCount = 1; LoopCount <= 6; ++LoopCount) {
5510 148746 : X2J *= pow_2(BessFuncArg) / 4.0;
5511 148746 : FACT *= pow_2(1.0 / double(LoopCount));
5512 148746 : HJ += 1.0 / double(LoopCount);
5513 148746 : G0 += X2J * FACT * (HJ - (0.5772157 + std::log(BessFuncArg / 2.0)));
5514 : } // End of LoopCount Loop
5515 24791 : if (BessFuncOrd == 0.0) {
5516 24791 : KBessFunc = G0;
5517 24791 : return;
5518 : }
5519 : }
5520 :
5521 : // Compute K1 using series expansion
5522 :
5523 36475 : X2J = BessFuncArg / 2.0;
5524 36475 : FACT = 1.0;
5525 36475 : HJ = 1.0;
5526 36475 : G1 = 1.0 / BessFuncArg + X2J * (0.5 + (0.5772157 + std::log(BessFuncArg / 2.0)) - HJ);
5527 291800 : for (LoopCount = 2; LoopCount <= 8; ++LoopCount) {
5528 255325 : X2J *= pow_2(BessFuncArg) / 4.0;
5529 255325 : FACT *= pow_2(1.0 / double(LoopCount));
5530 255325 : HJ += 1.0 / double(LoopCount);
5531 255325 : G1 += X2J * FACT * (0.5 + ((0.5772157 + std::log(BessFuncArg / 2.0)) - HJ) * double(LoopCount));
5532 : } // End of LoopCount Loop
5533 36475 : if (BessFuncOrd == 1) {
5534 36475 : KBessFunc = G1;
5535 36475 : return;
5536 : }
5537 : }
5538 :
5539 : // From K0 and K1 compute KN using recurrence relation
5540 :
5541 0 : LoopCount = 2;
5542 0 : StopLoop = false;
5543 0 : while (LoopCount <= BessFuncOrd && !StopLoop) {
5544 0 : GJ = 2.0 * (double(LoopCount) - 1.0) * G1 / BessFuncArg + G0;
5545 0 : if (GJ - GJMAX > 0.0) {
5546 0 : ErrorCode = 4;
5547 0 : GJ = GJMAX;
5548 0 : StopLoop = true;
5549 : } else {
5550 0 : G0 = G1;
5551 0 : G1 = GJ;
5552 0 : ++LoopCount;
5553 : }
5554 : } // End of LoopCount Loop
5555 0 : KBessFunc = GJ;
5556 : }
5557 :
5558 872 : void CalcPolynomCoef(EnergyPlusData &state, Array2<Real64> const &OrderedPair, Array1D<Real64> &PolynomCoef)
5559 : {
5560 : // SUBROUTINE INFORMATION:
5561 : // AUTHOR Unknown
5562 : // DATE WRITTEN Unknown
5563 : // DATE REWRITTEN April 1997 by Russell D. Taylor, Ph.D.
5564 : // MODIFIED
5565 : // RE-ENGINEERED
5566 :
5567 : // PURPOSE OF THIS SUBROUTINE:
5568 : // Fits polynomial of order from 1 to MaxPolynomOrder to the
5569 : // ordered pairs of data points X,Y
5570 :
5571 : // USE STATEMENTS:
5572 : // na
5573 :
5574 : // Locals
5575 : // SUBROUTINE ARGUMENT DEFINITIONS:
5576 :
5577 : // SUBROUTINE PARAMETER DEFINITIONS:
5578 : // na
5579 :
5580 : // INTERFACE BLOCK SPECIFICATIONS
5581 : // na
5582 :
5583 : // DERIVED TYPE DEFINITIONS
5584 : // na
5585 :
5586 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
5587 : bool Converged;
5588 : Real64 B;
5589 : int I;
5590 : int II;
5591 : int J;
5592 : int PolynomOrder;
5593 : int CurrentOrder;
5594 : int CurrentOrdPair;
5595 : Real64 S1;
5596 : Real64 S2;
5597 :
5598 872 : auto &OrdPairSum(state.dataWaterCoils->OrdPairSum);
5599 872 : auto &OrdPairSumMatrix(state.dataWaterCoils->OrdPairSumMatrix);
5600 :
5601 872 : OrdPairSum = 0.0;
5602 872 : OrdPairSum(1, 1) = WaterCoils::MaxOrderedPairs;
5603 872 : PolynomCoef = 0.0;
5604 53192 : for (CurrentOrdPair = 1; CurrentOrdPair <= WaterCoils::MaxOrderedPairs; ++CurrentOrdPair) {
5605 52320 : OrdPairSum(2, 1) += OrderedPair(CurrentOrdPair, 1);
5606 52320 : OrdPairSum(3, 1) += OrderedPair(CurrentOrdPair, 1) * OrderedPair(CurrentOrdPair, 1);
5607 52320 : OrdPairSum(1, 2) += OrderedPair(CurrentOrdPair, 2);
5608 52320 : OrdPairSum(2, 2) += OrderedPair(CurrentOrdPair, 1) * OrderedPair(CurrentOrdPair, 2);
5609 : }
5610 872 : PolynomOrder = 1;
5611 872 : Converged = false;
5612 7848 : while (!Converged) {
5613 15696 : for (CurrentOrder = 1; CurrentOrder <= PolynomOrder + 1; ++CurrentOrder) {
5614 59296 : for (J = 1; J <= PolynomOrder + 1; ++J) {
5615 47088 : OrdPairSumMatrix(J, CurrentOrder) = OrdPairSum(J - 1 + CurrentOrder, 1);
5616 : } // End of J loop
5617 12208 : OrdPairSumMatrix(PolynomOrder + 2, CurrentOrder) = OrdPairSum(CurrentOrder, 2);
5618 : } // End of CurrentOrder loop
5619 :
5620 15696 : for (CurrentOrder = 1; CurrentOrder <= PolynomOrder + 1; ++CurrentOrder) {
5621 12208 : OrdPairSumMatrix(CurrentOrder, PolynomOrder + 2) = -1.0;
5622 41856 : for (J = CurrentOrder + 1; J <= PolynomOrder + 2; ++J) {
5623 29648 : OrdPairSumMatrix(J, PolynomOrder + 2) = 0.0;
5624 : } // End of J loop
5625 :
5626 59296 : for (II = 2; II <= PolynomOrder + 2; ++II) {
5627 168296 : for (J = CurrentOrder + 1; J <= PolynomOrder + 2; ++J) {
5628 121208 : OrdPairSumMatrix(J, II) -= OrdPairSumMatrix(J, 1) * OrdPairSumMatrix(CurrentOrder, II) / OrdPairSumMatrix(CurrentOrder, 1);
5629 : } // End of J loop
5630 : } // End of II loop
5631 59296 : for (II = 1; II <= PolynomOrder + 1; ++II) {
5632 168296 : for (J = CurrentOrder + 1; J <= PolynomOrder + 2; ++J) {
5633 121208 : OrdPairSumMatrix(J, II) = OrdPairSumMatrix(J, II + 1);
5634 : } // End of J loop
5635 : } // End of II loop
5636 : } // End of CurrentOrder loop
5637 :
5638 3488 : S2 = 0.0;
5639 212768 : for (CurrentOrdPair = 1; CurrentOrdPair <= WaterCoils::MaxOrderedPairs; ++CurrentOrdPair) {
5640 209280 : S1 = OrdPairSumMatrix(PolynomOrder + 2, 1);
5641 209280 : auto const OrderedPair1C(OrderedPair(CurrentOrdPair, 1));
5642 209280 : auto OrderedPair1C_pow(1.0);
5643 732480 : for (CurrentOrder = 1; CurrentOrder <= PolynomOrder; ++CurrentOrder) {
5644 523200 : OrderedPair1C_pow *= OrderedPair1C;
5645 523200 : S1 += OrdPairSumMatrix(PolynomOrder + 2, CurrentOrder + 1) * OrderedPair1C_pow;
5646 : } // End of CurrentOrder loop
5647 209280 : S2 += (S1 - OrderedPair(CurrentOrdPair, 2)) * (S1 - OrderedPair(CurrentOrdPair, 2));
5648 : } // End of CurrentOrdPair loop
5649 3488 : B = WaterCoils::MaxOrderedPairs - (PolynomOrder + 1);
5650 3488 : if (S2 > 0.0001) S2 = std::sqrt(S2 / B);
5651 15696 : for (CurrentOrder = 1; CurrentOrder <= PolynomOrder + 1; ++CurrentOrder) {
5652 12208 : PolynomCoef(CurrentOrder) = OrdPairSumMatrix(PolynomOrder + 2, CurrentOrder);
5653 : } // End of CurrentOrder loop
5654 :
5655 3488 : if ((PolynomOrder - WaterCoils::MaxPolynomOrder < 0) && (S2 - WaterCoils::PolyConvgTol > 0.0)) {
5656 2616 : ++PolynomOrder;
5657 2616 : J = 2 * PolynomOrder;
5658 2616 : OrdPairSum(J, 1) = OrdPairSum(J + 1, 1) = 0.0;
5659 2616 : auto OrdPairSum2P = OrdPairSum(PolynomOrder + 1, 2) = 0.0;
5660 159576 : for (I = 1; I <= WaterCoils::MaxOrderedPairs; ++I) {
5661 156960 : auto const OrderedPair1I(OrderedPair(I, 1));
5662 156960 : auto OrderedPair_pow(std::pow(OrderedPair1I, J - 1));
5663 156960 : OrdPairSum(J, 1) += OrderedPair_pow;
5664 156960 : OrderedPair_pow *= OrderedPair1I;
5665 156960 : OrdPairSum(J + 1, 1) += OrderedPair_pow;
5666 156960 : OrdPairSum2P += OrderedPair(I, 2) * std::pow(OrderedPair1I, PolynomOrder);
5667 : }
5668 2616 : OrdPairSum(PolynomOrder + 1, 2) = OrdPairSum2P;
5669 : } else {
5670 872 : Converged = true;
5671 : }
5672 : }
5673 872 : }
5674 :
5675 : // Iterate Routine for Cooling Coil
5676 :
5677 4038163 : void CoilAreaFracIter(Real64 &NewSurfAreaWetFrac, // Out Value of variable
5678 : Real64 const SurfAreaFracCurrent, // Driver Value
5679 : Real64 const ErrorCurrent, // Objective Function
5680 : Real64 &SurfAreaFracPrevious, // First Previous value of Surf Area Fraction
5681 : Real64 &ErrorPrevious, // First Previous value of error
5682 : Real64 &SurfAreaFracLast, // Second Previous value of Surf Area Fraction
5683 : Real64 &ErrorLast, // Second Previous value of error
5684 : int const IterNum, // Number of Iterations
5685 : int &icvg // Iteration convergence flag
5686 : )
5687 : {
5688 : // FUNCTION INFORMATION:
5689 : // AUTHOR Rahul Chillar
5690 : // DATE WRITTEN June 2004
5691 : // MODIFIED na
5692 : // RE-ENGINEERED na
5693 :
5694 : // PURPOSE OF THIS FUNCTION:
5695 : // Iterately solves for the value of SurfAreaWetFraction for the Cooling Coil.
5696 :
5697 : // METHODOLOGY EMPLOYED:
5698 : // First function generates 2 sets of guess points by perturbation and subsequently
5699 : // by Linear Fit and using the generated points calculates coeffecients for Quadratic
5700 : // fit to predict the next value of surface area wet fraction.
5701 :
5702 : // REFERENCES:
5703 : // ME 423 Design of Thermal Systems Class Notes.UIUC. W.F.Stoecker
5704 :
5705 : // USE STATEMENTS:
5706 : // na
5707 :
5708 : // Enforce explicit typing of all variables in this routine
5709 :
5710 : // Locals
5711 : // FUNCTION ARGUMENT DEFINITIONS:
5712 :
5713 : // FUNCTION PARAMETER DEFINITIONS:
5714 4038163 : Real64 constexpr Tolerance(1.e-5); // Relative error tolerance
5715 4038163 : Real64 constexpr PerturbSurfAreaFrac(0.1); // Perturbation applied to Surf Fraction to initialize iteration
5716 4038163 : Real64 constexpr SmallNum(1.e-9); // Small Number
5717 :
5718 : // INTERFACE BLOCK SPECIFICATIONS
5719 : // na
5720 :
5721 : // DERIVED TYPE DEFINITIONS
5722 : // na
5723 :
5724 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
5725 : Real64 check; // Validity Check for moving to Quad Solution
5726 : Real64 QuadCoefThree; // Term under radical in quadratic solution
5727 : Real64 QuadCoefOne; // Term under radical in quadratic solution
5728 : Real64 QuadCoefTwo; // Term under radical in quadratic solution
5729 : Real64 Slope; // Slope for linear fit
5730 : Real64 SurfAreaFracOther; // Intermediate Value of Surf Area
5731 : int mode; // Linear/ perturbation option
5732 :
5733 : // Convergence Check by comparing previous and current value of surf area fraction
5734 4038163 : if ((std::abs(SurfAreaFracCurrent - SurfAreaFracPrevious) < Tolerance * max(std::abs(SurfAreaFracCurrent), SmallNum) && IterNum != 1) ||
5735 : ErrorCurrent == 0.0) {
5736 : // Setting value for surface area fraction for coil
5737 706219 : NewSurfAreaWetFrac = SurfAreaFracCurrent;
5738 706219 : icvg = 1; // Convergance Flag
5739 706219 : return;
5740 : }
5741 :
5742 : // If Icvg = 0 , it has not converged.By perturbation for getting second set of
5743 : // data (mode=1), Getting Third set of data by performing a linear fit(Mode=2).
5744 : // Now using the above 3 points generated by perturbation and Linear Fit to perform
5745 : // a quadratic fit.This will happen after second iteration only.
5746 3331944 : icvg = 0; // Convergance flag = false
5747 : // For First Iteration Start with perturbation, For second iteration start with linear fit
5748 : // from the previous two values
5749 3331944 : mode = IterNum;
5750 :
5751 3374290 : Label10:;
5752 3374290 : if (mode == 1) {
5753 :
5754 : // FirstGuess Set of Points provided by perturbation
5755 706220 : if (std::abs(SurfAreaFracCurrent) > SmallNum) {
5756 706220 : NewSurfAreaWetFrac = SurfAreaFracCurrent * (1.0 + PerturbSurfAreaFrac);
5757 : } else {
5758 0 : NewSurfAreaWetFrac = PerturbSurfAreaFrac;
5759 : }
5760 :
5761 : // Second set of values being calculated from the first set of values (incoming & perturb)
5762 2668070 : } else if (mode == 2) {
5763 :
5764 : // Calculating Slope for interpolating to the New Point (Simple Linear Extrapolation)
5765 748564 : Slope = (ErrorPrevious - ErrorCurrent) / (SurfAreaFracPrevious - SurfAreaFracCurrent);
5766 : // Error Check for value or Slope
5767 748564 : if (Slope == 0.0) {
5768 1 : mode = 1; // Go back to Perturbation
5769 1 : goto Label10;
5770 : }
5771 : // Guessing New Value for Surface Area Fraction
5772 748563 : NewSurfAreaWetFrac = SurfAreaFracCurrent - ErrorCurrent / Slope;
5773 : } else {
5774 :
5775 : // Check for Quadratic Fit possible here ,Previous value of surf area fraction
5776 : // equals current value then Try linear fit for another point.
5777 1919506 : if (SurfAreaFracCurrent == SurfAreaFracPrevious) {
5778 : // Assign Value of previous point to Last Variable for storing
5779 : // Go back and calculate new value for Previous.
5780 0 : SurfAreaFracPrevious = SurfAreaFracLast;
5781 0 : ErrorPrevious = ErrorLast;
5782 0 : mode = 2;
5783 0 : goto Label10;
5784 1919506 : } else if (SurfAreaFracCurrent == SurfAreaFracLast) {
5785 : // Calculate another value using Linear Fit.
5786 25980 : mode = 2;
5787 25980 : goto Label10;
5788 : }
5789 :
5790 : // Now We have enough previous points to calculate coefficients and
5791 : // perform a quadratic fit for new guess value of surface area fraction
5792 :
5793 : // Calculating First Coefficients for Quadratic Curve Fit
5794 5680578 : QuadCoefThree = ((ErrorLast - ErrorCurrent) / (SurfAreaFracLast - SurfAreaFracCurrent) -
5795 1893526 : (ErrorPrevious - ErrorCurrent) / (SurfAreaFracPrevious - SurfAreaFracCurrent)) /
5796 1893526 : (SurfAreaFracLast - SurfAreaFracPrevious);
5797 : // Calculating Second Coefficients for Quadratic Curve Fit
5798 3787052 : QuadCoefTwo = (ErrorPrevious - ErrorCurrent) / (SurfAreaFracPrevious - SurfAreaFracCurrent) -
5799 1893526 : (SurfAreaFracPrevious + SurfAreaFracCurrent) * QuadCoefThree;
5800 :
5801 : // Calculating Third Coefficients for Quadratic Curve Fit
5802 1893526 : QuadCoefOne = ErrorCurrent - (QuadCoefTwo + QuadCoefThree * SurfAreaFracCurrent) * SurfAreaFracCurrent;
5803 :
5804 : // Check for validity of coefficients , if not REAL(r64) ,Then fit is linear
5805 1893526 : if (std::abs(QuadCoefThree) < 1.E-10) {
5806 0 : mode = 2; // going to Linear mode, due to colinear points.
5807 0 : goto Label10;
5808 : }
5809 :
5810 : // If value of Quadratic coefficients not suitable enought due to round off errors
5811 : // to predict new point go to linear fit and acertain new values for the coefficients.
5812 1893526 : if (std::abs((QuadCoefOne + (QuadCoefTwo + QuadCoefThree * SurfAreaFracPrevious) * SurfAreaFracPrevious - ErrorPrevious) / ErrorPrevious) >
5813 : 1.E-4) {
5814 5 : mode = 2; // go to linear mode
5815 5 : goto Label10;
5816 : }
5817 :
5818 : // Validity Check for Imaginary roots, In this case go back to linear fit.
5819 1893521 : check = pow_2(QuadCoefTwo) - 4.0 * QuadCoefOne * QuadCoefThree;
5820 : // Imaginary Root Exist
5821 1893521 : if (check < 0) {
5822 16360 : mode = 2;
5823 16360 : goto Label10;
5824 1877161 : } else if (check > 0) {
5825 : // real unequal roots exist, Determine the roots nearest to most recent guess
5826 1877134 : NewSurfAreaWetFrac = (-QuadCoefTwo + std::sqrt(check)) / QuadCoefThree / 2.0;
5827 1877134 : SurfAreaFracOther = -NewSurfAreaWetFrac - QuadCoefTwo / QuadCoefThree;
5828 : // Assigning value to Surface Area Fraction with recent
5829 1877134 : if (std::abs(NewSurfAreaWetFrac - SurfAreaFracCurrent) > std::abs(SurfAreaFracOther - SurfAreaFracCurrent))
5830 3271 : NewSurfAreaWetFrac = SurfAreaFracOther;
5831 : } else {
5832 : // The roots are real, one solution exists.
5833 27 : NewSurfAreaWetFrac = -QuadCoefTwo / QuadCoefThree / 2;
5834 : }
5835 : }
5836 :
5837 3331944 : if (mode < 3) {
5838 : // No valid previous points to eliminate, since it just has 2 points.
5839 : // Loading previous values into last
5840 1454783 : SurfAreaFracLast = SurfAreaFracPrevious;
5841 1454783 : ErrorLast = ErrorPrevious;
5842 : // Loading Current Values into previous
5843 1454783 : SurfAreaFracPrevious = SurfAreaFracCurrent;
5844 1454783 : ErrorPrevious = ErrorCurrent;
5845 : } else {
5846 :
5847 : // Elimination the most distance previous point from the answer based on sign and
5848 : // magnitute of the error. Keeping Current Point
5849 1877161 : if (ErrorPrevious * ErrorCurrent > 0 && ErrorLast * ErrorCurrent > 0) {
5850 : // If sign are same , simply eliminate the one with biggest error value.
5851 471122 : if (std::abs(ErrorLast) > std::abs(ErrorPrevious)) {
5852 : // Eliminating Last Value
5853 96672 : SurfAreaFracLast = SurfAreaFracPrevious;
5854 96672 : ErrorLast = ErrorPrevious;
5855 : }
5856 : } else {
5857 : // If signs are different eliminate previous error with same sign as current error
5858 1641600 : if (ErrorLast * ErrorCurrent > 0) {
5859 : // Previous Loaded to Last
5860 511195 : SurfAreaFracLast = SurfAreaFracPrevious;
5861 511195 : ErrorLast = ErrorPrevious;
5862 : }
5863 : }
5864 : // Current Loaded into previous.
5865 1877161 : SurfAreaFracPrevious = SurfAreaFracCurrent;
5866 1877161 : ErrorPrevious = ErrorCurrent;
5867 : }
5868 : }
5869 :
5870 279206 : void CheckWaterCoilSchedule(EnergyPlusData &state, std::string_view CompName, Real64 &Value, int &CompIndex)
5871 : {
5872 :
5873 : // SUBROUTINE INFORMATION:
5874 : // AUTHOR Linda Lawrie
5875 : // DATE WRITTEN October 2005
5876 : // MODIFIED na
5877 : // RE-ENGINEERED na
5878 :
5879 : // PURPOSE OF THIS SUBROUTINE:
5880 : // <description>
5881 :
5882 : // Using/Aliasing
5883 :
5884 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
5885 : int CoilNum;
5886 :
5887 : // Obtains and Allocates WaterCoil related parameters from input file
5888 279206 : if (state.dataWaterCoils->GetWaterCoilsInputFlag) { // First time subroutine has been entered
5889 0 : GetWaterCoilInput(state);
5890 0 : state.dataWaterCoils->GetWaterCoilsInputFlag = false;
5891 : }
5892 :
5893 : // Find the correct Coil number
5894 279206 : if (CompIndex == 0) {
5895 8 : CoilNum = UtilityRoutines::FindItemInList(CompName, state.dataWaterCoils->WaterCoil);
5896 8 : if (CoilNum == 0) {
5897 0 : ShowFatalError(state, "CheckWaterCoilSchedule: Coil not found=" + std::string{CompName});
5898 : }
5899 8 : CompIndex = CoilNum;
5900 8 : Value = GetCurrentScheduleValue(state, state.dataWaterCoils->WaterCoil(CoilNum).SchedPtr); // not scheduled?
5901 : } else {
5902 279198 : CoilNum = CompIndex;
5903 279198 : if (CoilNum > state.dataWaterCoils->NumWaterCoils || CoilNum < 1) {
5904 0 : ShowFatalError(state,
5905 0 : format("CheckWaterCoilSchedule: Invalid CompIndex passed={}, Number of Heating Coils={}, Coil name={}",
5906 : CoilNum,
5907 0 : state.dataWaterCoils->NumWaterCoils,
5908 0 : CompName));
5909 : }
5910 279198 : if (CompName != state.dataWaterCoils->WaterCoil(CoilNum).Name) {
5911 0 : ShowFatalError(state,
5912 0 : format("CheckWaterCoilSchedule: Invalid CompIndex passed={}, Coil name={}, stored Coil Name for that index={}",
5913 : CoilNum,
5914 : CompName,
5915 0 : state.dataWaterCoils->WaterCoil(CoilNum).Name));
5916 : }
5917 279198 : Value = GetCurrentScheduleValue(state, state.dataWaterCoils->WaterCoil(CoilNum).SchedPtr); // not scheduled?
5918 : }
5919 279206 : }
5920 :
5921 137 : Real64 GetCoilMaxWaterFlowRate(EnergyPlusData &state,
5922 : std::string_view CoilType, // must match coil types in this module
5923 : std::string const &CoilName, // must match coil names for the coil type
5924 : bool &ErrorsFound // set to true if problem
5925 : )
5926 : {
5927 :
5928 : // FUNCTION INFORMATION:
5929 : // AUTHOR Linda Lawrie
5930 : // DATE WRITTEN November 2006
5931 : // MODIFIED na
5932 : // RE-ENGINEERED na
5933 :
5934 : // PURPOSE OF THIS FUNCTION:
5935 : // This function looks up the max water flow rate for the given coil and returns it. If
5936 : // incorrect coil type or name is given, ErrorsFound is returned as true and capacity is returned
5937 : // as negative.
5938 :
5939 : // Return value
5940 : Real64 MaxWaterFlowRate; // returned max water flow rate of matched coil
5941 :
5942 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
5943 : int WhichCoil;
5944 :
5945 : // Obtains and Allocates WaterCoil related parameters from input file
5946 137 : if (state.dataWaterCoils->GetWaterCoilsInputFlag) { // First time subroutine has been entered
5947 2 : GetWaterCoilInput(state);
5948 2 : state.dataWaterCoils->GetWaterCoilsInputFlag = false;
5949 : }
5950 :
5951 137 : WhichCoil = 0;
5952 330 : if (UtilityRoutines::SameString(CoilType, "Coil:Heating:Water") || UtilityRoutines::SameString(CoilType, "Coil:Cooling:Water:DetailedGeometry") ||
5953 193 : UtilityRoutines::SameString(CoilType, "Coil:Cooling:Water")) {
5954 137 : WhichCoil = UtilityRoutines::FindItem(CoilName, state.dataWaterCoils->WaterCoil);
5955 137 : if (WhichCoil != 0) {
5956 : // coil does not specify MaxWaterFlowRate
5957 137 : MaxWaterFlowRate = state.dataWaterCoils->WaterCoil(WhichCoil).MaxWaterVolFlowRate;
5958 : }
5959 : } else {
5960 0 : WhichCoil = 0;
5961 : }
5962 :
5963 137 : if (WhichCoil == 0) {
5964 0 : ShowSevereError(state, format("GetCoilMaxWaterFlowRate: Could not find Coil, Type=\"{}\" Name=\"{}\"", CoilType, CoilName));
5965 0 : ShowContinueError(state, "... Max Water Flow rate returned as -1000.");
5966 0 : ErrorsFound = true;
5967 0 : MaxWaterFlowRate = -1000.0;
5968 : }
5969 :
5970 137 : return MaxWaterFlowRate;
5971 : }
5972 :
5973 185 : int GetCoilInletNode(EnergyPlusData &state,
5974 : std::string_view CoilType, // must match coil types in this module
5975 : std::string const &CoilName, // must match coil names for the coil type
5976 : bool &ErrorsFound // set to true if problem
5977 : )
5978 : {
5979 :
5980 : // FUNCTION INFORMATION:
5981 : // AUTHOR R. Raustad
5982 : // DATE WRITTEN March 2007
5983 : // MODIFIED na
5984 : // RE-ENGINEERED na
5985 :
5986 : // PURPOSE OF THIS FUNCTION:
5987 : // This function looks up the given coil and returns the inlet node number. If
5988 : // incorrect coil type or name is given, ErrorsFound is returned as true and node number is returned
5989 : // as zero.
5990 :
5991 : // Return value
5992 : int NodeNumber; // returned node number of matched coil
5993 :
5994 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
5995 : int WhichCoil;
5996 :
5997 : // Obtains and Allocates DXCoils
5998 185 : if (state.dataWaterCoils->GetWaterCoilsInputFlag) {
5999 0 : GetWaterCoilInput(state);
6000 0 : state.dataWaterCoils->GetWaterCoilsInputFlag = false;
6001 : }
6002 :
6003 185 : NodeNumber = 0;
6004 185 : WhichCoil = 0;
6005 460 : if (UtilityRoutines::SameString(CoilType, "Coil:Heating:Water") || UtilityRoutines::SameString(CoilType, "Coil:Cooling:Water:DetailedGeometry") ||
6006 275 : UtilityRoutines::SameString(CoilType, "Coil:Cooling:Water")) {
6007 185 : WhichCoil = UtilityRoutines::FindItem(CoilName, state.dataWaterCoils->WaterCoil);
6008 185 : if (WhichCoil != 0) {
6009 185 : NodeNumber = state.dataWaterCoils->WaterCoil(WhichCoil).AirInletNodeNum;
6010 : }
6011 : } else {
6012 0 : WhichCoil = 0;
6013 : }
6014 :
6015 185 : if (WhichCoil == 0) {
6016 0 : ShowSevereError(state, format("GetCoilInletNode: Could not find Coil, Type=\"{}\" Name=\"{}\"", CoilType, CoilName));
6017 0 : ErrorsFound = true;
6018 0 : NodeNumber = 0;
6019 : }
6020 :
6021 185 : return NodeNumber;
6022 : }
6023 :
6024 191 : int GetCoilOutletNode(EnergyPlusData &state,
6025 : std::string_view CoilType, // must match coil types in this module
6026 : std::string const &CoilName, // must match coil names for the coil type
6027 : bool &ErrorsFound // set to true if problem
6028 : )
6029 : {
6030 :
6031 : // FUNCTION INFORMATION:
6032 : // AUTHOR R. Raustad
6033 : // DATE WRITTEN March 2007
6034 : // MODIFIED na
6035 : // RE-ENGINEERED na
6036 :
6037 : // PURPOSE OF THIS FUNCTION:
6038 : // This function looks up the given coil and returns the inlet node number. If
6039 : // incorrect coil type or name is given, ErrorsFound is returned as true and node number is returned
6040 : // as zero.
6041 :
6042 : // Return value
6043 : int NodeNumber; // returned node number of matched coil
6044 :
6045 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
6046 : int WhichCoil;
6047 :
6048 : // Obtains and Allocates DXCoils
6049 191 : if (state.dataWaterCoils->GetWaterCoilsInputFlag) {
6050 0 : GetWaterCoilInput(state);
6051 0 : state.dataWaterCoils->GetWaterCoilsInputFlag = false;
6052 : }
6053 :
6054 191 : WhichCoil = 0;
6055 191 : NodeNumber = 0;
6056 470 : if (UtilityRoutines::SameString(CoilType, "Coil:Heating:Water") || UtilityRoutines::SameString(CoilType, "Coil:Cooling:Water:DetailedGeometry") ||
6057 279 : UtilityRoutines::SameString(CoilType, "Coil:Cooling:Water")) {
6058 191 : WhichCoil = UtilityRoutines::FindItem(CoilName, state.dataWaterCoils->WaterCoil);
6059 191 : if (WhichCoil != 0) {
6060 191 : NodeNumber = state.dataWaterCoils->WaterCoil(WhichCoil).AirOutletNodeNum;
6061 : }
6062 : } else {
6063 0 : WhichCoil = 0;
6064 : }
6065 :
6066 191 : if (WhichCoil == 0) {
6067 0 : ShowSevereError(
6068 : state,
6069 0 : format("GetCoilOutletNode: Could not find Coil, Type=\"{}\" Name=\"{}\" when accessing coil outlet node number.", CoilType, CoilName));
6070 0 : ErrorsFound = true;
6071 0 : NodeNumber = 0;
6072 : }
6073 :
6074 191 : return NodeNumber;
6075 : }
6076 :
6077 5157 : int GetCoilWaterInletNode(EnergyPlusData &state,
6078 : std::string_view CoilType, // must match coil types in this module
6079 : std::string const &CoilName, // must match coil names for the coil type
6080 : bool &ErrorsFound // set to true if problem
6081 : )
6082 : {
6083 :
6084 : // FUNCTION INFORMATION:
6085 : // AUTHOR R. Raustad
6086 : // DATE WRITTEN July 2007
6087 : // MODIFIED na
6088 : // RE-ENGINEERED na
6089 :
6090 : // PURPOSE OF THIS FUNCTION:
6091 : // This function looks up the given coil and returns the inlet water control node number. If
6092 : // incorrect coil type or name is given, ErrorsFound is returned as true and node number is returned
6093 : // as zero.
6094 :
6095 : // Return value
6096 : int NodeNumber; // returned node number of matched coil
6097 :
6098 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
6099 : int WhichCoil;
6100 :
6101 : // Obtains and Allocates DXCoils
6102 5157 : if (state.dataWaterCoils->GetWaterCoilsInputFlag) {
6103 297 : GetWaterCoilInput(state);
6104 297 : state.dataWaterCoils->GetWaterCoilsInputFlag = false;
6105 : }
6106 :
6107 5157 : NodeNumber = 0;
6108 5157 : WhichCoil = 0;
6109 10812 : if (UtilityRoutines::SameString(CoilType, "Coil:Heating:Water") || UtilityRoutines::SameString(CoilType, "Coil:Cooling:Water:DetailedGeometry") ||
6110 5655 : UtilityRoutines::SameString(CoilType, "Coil:Cooling:Water")) {
6111 5157 : WhichCoil = UtilityRoutines::FindItem(CoilName, state.dataWaterCoils->WaterCoil);
6112 5157 : if (WhichCoil != 0) {
6113 5157 : NodeNumber = state.dataWaterCoils->WaterCoil(WhichCoil).WaterInletNodeNum;
6114 : }
6115 : } else {
6116 0 : WhichCoil = 0;
6117 : }
6118 :
6119 5157 : if (WhichCoil == 0) {
6120 0 : ShowSevereError(state, format("GetCoilWaterInletNode: Could not find Coil, Type=\"{}\" Name=\"{}\"", CoilType, CoilName));
6121 0 : ErrorsFound = true;
6122 0 : NodeNumber = 0;
6123 : }
6124 :
6125 5157 : return NodeNumber;
6126 : }
6127 :
6128 2024 : int GetCoilWaterOutletNode(EnergyPlusData &state,
6129 : std::string_view CoilType, // must match coil types in this module
6130 : std::string const &CoilName, // must match coil names for the coil type
6131 : bool &ErrorsFound // set to true if problem
6132 : )
6133 : {
6134 :
6135 : // FUNCTION INFORMATION:
6136 : // AUTHOR R. Raustad
6137 : // DATE WRITTEN July 2007
6138 : // MODIFIED na
6139 : // RE-ENGINEERED na
6140 :
6141 : // PURPOSE OF THIS FUNCTION:
6142 : // This function looks up the given coil and returns the outlet water node number. If
6143 : // incorrect coil type or name is given, ErrorsFound is returned as true and node number is returned
6144 : // as zero.
6145 :
6146 : // Return value
6147 : int NodeNumber; // returned node number of matched coil
6148 :
6149 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
6150 : int WhichCoil;
6151 :
6152 : // Obtains and Allocates DXCoils
6153 2024 : if (state.dataWaterCoils->GetWaterCoilsInputFlag) {
6154 0 : GetWaterCoilInput(state);
6155 0 : state.dataWaterCoils->GetWaterCoilsInputFlag = false;
6156 : }
6157 :
6158 2024 : NodeNumber = 0;
6159 2024 : WhichCoil = 0;
6160 4145 : if (UtilityRoutines::SameString(CoilType, "Coil:Heating:Water") || UtilityRoutines::SameString(CoilType, "Coil:Cooling:Water:DetailedGeometry") ||
6161 2121 : UtilityRoutines::SameString(CoilType, "Coil:Cooling:Water")) {
6162 2024 : WhichCoil = UtilityRoutines::FindItem(CoilName, state.dataWaterCoils->WaterCoil);
6163 2024 : if (WhichCoil != 0) {
6164 2024 : NodeNumber = state.dataWaterCoils->WaterCoil(WhichCoil).WaterOutletNodeNum;
6165 : }
6166 : } else {
6167 0 : WhichCoil = 0;
6168 : }
6169 :
6170 2024 : if (WhichCoil == 0) {
6171 0 : ShowSevereError(state, format("GetCoilWaterOutletNode: Could not find Coil, Type=\"{}\" Name=\"{}\"", CoilType, CoilName));
6172 0 : ErrorsFound = true;
6173 0 : NodeNumber = 0;
6174 : }
6175 :
6176 2024 : return NodeNumber;
6177 : }
6178 :
6179 2882 : void SetCoilDesFlow(EnergyPlusData &state,
6180 : std::string_view CoilType, // must match coil types in this module
6181 : std::string const &CoilName, // must match coil names for the coil type
6182 : Real64 const CoilDesFlow, // coil volumetric air flow rate [m3/s]
6183 : bool &ErrorsFound // set to true if problem
6184 : )
6185 : {
6186 :
6187 : // SUBROUTINE INFORMATION:
6188 : // AUTHOR Fred Buhl
6189 : // DATE WRITTEN May 2009
6190 : // MODIFIED na
6191 : // RE-ENGINEERED na
6192 :
6193 : // PURPOSE OF THIS SUBROUTINE:
6194 : // This routine is designed to set the design air volume flow rate in the
6195 : // water coil data structure. Some of the coil types do not have this datum as
6196 : // an input parameter and it is needed for calculating capacity for output reporting.
6197 :
6198 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
6199 : int WhichCoil; // index to coil
6200 :
6201 2882 : if (state.dataWaterCoils->GetWaterCoilsInputFlag) { // First time subroutine has been entered
6202 11 : GetWaterCoilInput(state);
6203 11 : state.dataWaterCoils->GetWaterCoilsInputFlag = false;
6204 : }
6205 :
6206 5948 : if (UtilityRoutines::SameString(CoilType, "Coil:Heating:Water") || UtilityRoutines::SameString(CoilType, "Coil:Cooling:Water:DetailedGeometry") ||
6207 3066 : UtilityRoutines::SameString(CoilType, "Coil:Cooling:Water")) {
6208 2792 : WhichCoil = UtilityRoutines::FindItem(CoilName, state.dataWaterCoils->WaterCoil);
6209 2792 : if (WhichCoil != 0) {
6210 2792 : if (state.dataWaterCoils->WaterCoil(WhichCoil).DesAirVolFlowRate <= 0.0) {
6211 2783 : state.dataWaterCoils->WaterCoil(WhichCoil).DesAirVolFlowRate = CoilDesFlow;
6212 : } else {
6213 : // WaterCoil(WhichCoil).DesAirVolFlowRate = CoilDesFlow;
6214 : }
6215 : } else {
6216 0 : ShowSevereError(state, format("GetCoilMaxWaterFlowRate: Could not find Coil, Type=\"{}\" Name=\"{}\"", CoilType, CoilName));
6217 0 : ErrorsFound = true;
6218 : }
6219 : }
6220 2882 : }
6221 :
6222 0 : Real64 GetWaterCoilDesAirFlow(EnergyPlusData &state,
6223 : std::string const &CoilType, // must match coil types in this module
6224 : std::string const &CoilName, // must match coil names for the coil type
6225 : bool &ErrorsFound // set to true if problem
6226 : )
6227 : {
6228 :
6229 : // SUBROUTINE INFORMATION:
6230 : // AUTHOR Fred Buhl
6231 : // DATE WRITTEN May 2009
6232 : // MODIFIED na
6233 : // RE-ENGINEERED na
6234 :
6235 : // PURPOSE OF THIS SUBROUTINE:
6236 : // This routine is designed to set the design air volume flow rate in the
6237 : // water coil data structure. Some of the coil types do not have this datum as
6238 : // an input parameter and it is needed for calculating capacity for output reporting.
6239 :
6240 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
6241 : int WhichCoil; // index to coil
6242 : Real64 CoilDesAirFlow;
6243 :
6244 0 : CoilDesAirFlow = 0.0;
6245 :
6246 0 : if (state.dataWaterCoils->GetWaterCoilsInputFlag) { // First time subroutine has been entered
6247 0 : GetWaterCoilInput(state);
6248 0 : state.dataWaterCoils->GetWaterCoilsInputFlag = false;
6249 : }
6250 :
6251 0 : if (UtilityRoutines::SameString(CoilType, "Coil:Cooling:Water")) {
6252 0 : WhichCoil = UtilityRoutines::FindItem(CoilName, state.dataWaterCoils->WaterCoil);
6253 0 : if (WhichCoil != 0) {
6254 0 : CoilDesAirFlow = state.dataWaterCoils->WaterCoil(WhichCoil).DesAirVolFlowRate;
6255 : } else {
6256 0 : ShowSevereError(state, "GetWaterCoilDesAirFlowRate: Could not find Coil, Type=\"" + CoilType + "\" Name=\"" + CoilName + "\"");
6257 0 : ErrorsFound = true;
6258 : }
6259 : } else {
6260 0 : ShowSevereError(state, "GetWaterCoilDesAirFlowRate: Funciton not valid for Coil, Type=\"" + CoilType + "\" Name=\"" + CoilName + "\"");
6261 0 : ErrorsFound = true;
6262 : }
6263 :
6264 0 : return CoilDesAirFlow;
6265 : }
6266 :
6267 822 : void CheckActuatorNode(EnergyPlusData &state,
6268 : int const ActuatorNodeNum, // input actuator node number
6269 : DataPlant::PlantEquipmentType &WaterCoilType, // Cooling or Heating or 0
6270 : bool &NodeNotFound // true if matching water inlet node not found
6271 : )
6272 : {
6273 :
6274 : // SUBROUTINE INFORMATION:
6275 : // AUTHOR Fred Buhl
6276 : // DATE WRITTEN January 2009
6277 : // MODIFIED na
6278 : // RE-ENGINEERED na
6279 :
6280 : // PURPOSE OF THIS FUNCTION:
6281 : // This subroutine checks that the input actuator node number is matched by
6282 : // the water inlet node number of some water coil
6283 :
6284 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
6285 : int WhichCoil;
6286 : int CoilNum;
6287 :
6288 : // Obtains and Allocates DXCoils
6289 822 : if (state.dataWaterCoils->GetWaterCoilsInputFlag) {
6290 0 : GetWaterCoilInput(state);
6291 0 : state.dataWaterCoils->GetWaterCoilsInputFlag = false;
6292 : }
6293 :
6294 822 : WhichCoil = 0;
6295 822 : WaterCoilType = DataPlant::PlantEquipmentType::Invalid;
6296 822 : NodeNotFound = true;
6297 25324 : for (CoilNum = 1; CoilNum <= state.dataWaterCoils->NumWaterCoils; ++CoilNum) {
6298 24502 : if (state.dataWaterCoils->WaterCoil(CoilNum).WaterInletNodeNum == ActuatorNodeNum) {
6299 822 : WhichCoil = CoilNum;
6300 822 : WaterCoilType = state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilType;
6301 822 : NodeNotFound = false;
6302 : }
6303 : }
6304 822 : }
6305 :
6306 822 : void CheckForSensorAndSetPointNode(EnergyPlusData &state,
6307 : int const SensorNodeNum, // controller sensor node number
6308 : HVACControllers::CtrlVarType const ControlledVar, // controlled variable type
6309 : bool &NodeNotFound // true if matching air outlet node not found
6310 : )
6311 : {
6312 :
6313 : // SUBROUTINE INFORMATION:
6314 : // AUTHOR Bereket Nigusse
6315 : // DATE WRITTEN March 2013
6316 : // MODIFIED na
6317 : // RE-ENGINEERED na
6318 :
6319 : // PURPOSE OF THIS SUBROUTINE:
6320 : // This subroutine checks that the sensor node number matches the air outlet node number
6321 : // of some water coils
6322 :
6323 : // Using/Aliasing
6324 : using EMSManager::CheckIfNodeSetPointManagedByEMS;
6325 : using SetPointManager::CtrlVarType;
6326 : using SetPointManager::NodeHasSPMCtrlVarType;
6327 :
6328 : // SUBROUTINE PARAMETER DEFINITIONS:
6329 : static constexpr std::string_view RoutineName("CheckForSensorAndSetpointNode: ");
6330 :
6331 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
6332 : int WhichCoil; // water coil index
6333 : int CoilNum; // counter
6334 1644 : std::string WaterCoilType; // water coil type
6335 : bool EMSSetPointErrorFlag; // flag true is EMS is used to set node setpoints
6336 :
6337 : // Obtains and Allocates DXCoils
6338 822 : if (state.dataWaterCoils->GetWaterCoilsInputFlag) {
6339 2 : GetWaterCoilInput(state);
6340 2 : state.dataWaterCoils->GetWaterCoilsInputFlag = false;
6341 : }
6342 :
6343 822 : WhichCoil = 0;
6344 822 : NodeNotFound = true;
6345 :
6346 21064 : for (CoilNum = 1; CoilNum <= state.dataWaterCoils->NumWaterCoils; ++CoilNum) {
6347 21064 : if (SensorNodeNum != state.dataWaterCoils->WaterCoil(CoilNum).AirOutletNodeNum) continue;
6348 822 : NodeNotFound = false;
6349 822 : WhichCoil = CoilNum;
6350 822 : break;
6351 : }
6352 : // now if the sensor node is on the water coil air outlet node then check that
6353 : // a setpoint is also specified on the water coil outlet node
6354 822 : if (!NodeNotFound) {
6355 822 : if (WhichCoil > 0) {
6356 822 : if (state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterDetailedFlatCooling) {
6357 143 : WaterCoilType = "Coil:Cooling:Water:DetailedGeometry";
6358 679 : } else if (state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterCooling) {
6359 293 : WaterCoilType = "Coil:Cooling:Water";
6360 386 : } else if (state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterSimpleHeating) {
6361 386 : WaterCoilType = "Coil:Heating:Water";
6362 : }
6363 822 : EMSSetPointErrorFlag = false;
6364 822 : switch (ControlledVar) {
6365 779 : case HVACControllers::CtrlVarType::Temperature: {
6366 779 : CheckIfNodeSetPointManagedByEMS(state, SensorNodeNum, EMSManager::SPControlType::TemperatureSetPoint, EMSSetPointErrorFlag);
6367 779 : state.dataLoopNodes->NodeSetpointCheck(SensorNodeNum).needsSetpointChecking = false;
6368 779 : if (EMSSetPointErrorFlag) {
6369 600 : if (!NodeHasSPMCtrlVarType(state, SensorNodeNum, CtrlVarType::Temp)) {
6370 0 : ShowWarningError(state,
6371 0 : std::string{RoutineName} + WaterCoilType + "=\"" + state.dataWaterCoils->WaterCoil(WhichCoil).Name + "\". ");
6372 0 : ShowContinueError(state, " ..Temperature setpoint not found on coil air outlet node.");
6373 0 : ShowContinueError(state,
6374 : " ..The setpoint may have been placed on a node downstream of the coil or on an airloop outlet node.");
6375 0 : ShowContinueError(state, " ..Specify the setpoint and the sensor on the coil air outlet node when possible.");
6376 : }
6377 : }
6378 779 : break;
6379 : }
6380 0 : case HVACControllers::CtrlVarType::HumidityRatio: {
6381 0 : CheckIfNodeSetPointManagedByEMS(state, SensorNodeNum, EMSManager::SPControlType::HumidityRatioMaxSetPoint, EMSSetPointErrorFlag);
6382 0 : state.dataLoopNodes->NodeSetpointCheck(SensorNodeNum).needsSetpointChecking = false;
6383 0 : if (EMSSetPointErrorFlag) {
6384 0 : if (!NodeHasSPMCtrlVarType(state, SensorNodeNum, CtrlVarType::MaxHumRat)) {
6385 0 : ShowWarningError(state,
6386 0 : std::string{RoutineName} + WaterCoilType + "=\"" + state.dataWaterCoils->WaterCoil(WhichCoil).Name + "\". ");
6387 0 : ShowContinueError(state, " ..Humidity ratio setpoint not found on coil air outlet node.");
6388 0 : ShowContinueError(state,
6389 : " ..The setpoint may have been placed on a node downstream of the coil or on an airloop outlet node.");
6390 0 : ShowContinueError(state, " ..Specify the setpoint and the sensor on the coil air outlet node when possible.");
6391 : }
6392 : }
6393 0 : break;
6394 : }
6395 43 : case HVACControllers::CtrlVarType::TemperatureAndHumidityRatio: {
6396 43 : CheckIfNodeSetPointManagedByEMS(state, SensorNodeNum, EMSManager::SPControlType::TemperatureSetPoint, EMSSetPointErrorFlag);
6397 43 : state.dataLoopNodes->NodeSetpointCheck(SensorNodeNum).needsSetpointChecking = false;
6398 43 : if (EMSSetPointErrorFlag) {
6399 28 : if (!NodeHasSPMCtrlVarType(state, SensorNodeNum, CtrlVarType::Temp)) {
6400 0 : ShowWarningError(state,
6401 0 : std::string{RoutineName} + WaterCoilType + "=\"" + state.dataWaterCoils->WaterCoil(WhichCoil).Name + "\". ");
6402 0 : ShowContinueError(state, " ..Temperature setpoint not found on coil air outlet node.");
6403 0 : ShowContinueError(state,
6404 : " ..The setpoint may have been placed on a node downstream of the coil or on an airloop outlet node.");
6405 0 : ShowContinueError(state, " ..Specify the setpoint and the sensor on the coil air outlet node when possible.");
6406 : }
6407 : }
6408 43 : EMSSetPointErrorFlag = false;
6409 43 : CheckIfNodeSetPointManagedByEMS(state, SensorNodeNum, EMSManager::SPControlType::HumidityRatioMaxSetPoint, EMSSetPointErrorFlag);
6410 43 : state.dataLoopNodes->NodeSetpointCheck(SensorNodeNum).needsSetpointChecking = false;
6411 43 : if (EMSSetPointErrorFlag) {
6412 28 : if (!NodeHasSPMCtrlVarType(state, SensorNodeNum, CtrlVarType::MaxHumRat)) {
6413 0 : ShowWarningError(state,
6414 0 : std::string{RoutineName} + WaterCoilType + "=\"" + state.dataWaterCoils->WaterCoil(WhichCoil).Name + "\". ");
6415 0 : ShowContinueError(state, " ..Humidity ratio setpoint not found on coil air outlet node.");
6416 0 : ShowContinueError(state,
6417 : " ..The setpoint may have been placed on a node downstream of the coil or on an airloop outlet node.");
6418 0 : ShowContinueError(state, " ..Specify the setpoint and the sensor on the coil air outlet node when possible.");
6419 : }
6420 : }
6421 43 : break;
6422 : }
6423 0 : default:
6424 0 : break;
6425 : }
6426 : }
6427 : }
6428 822 : }
6429 :
6430 76 : Real64 TdbFnHRhPb(EnergyPlusData &state,
6431 : Real64 const H, // specific enthalpy {J/kg}
6432 : Real64 const RH, // relative humidity value (0.0-1.0)
6433 : Real64 const PB // barometric pressure {Pascals}
6434 : )
6435 : {
6436 :
6437 : // FUNCTION INFORMATION:
6438 : // AUTHOR Fred Buhl
6439 : // DATE WRITTEN April 1, 2009
6440 : // MODIFIED na
6441 : // RE-ENGINEERED na
6442 :
6443 : // PURPOSE OF THIS FUNCTION:
6444 : // Given the specific enthalpy, relative humidity, and the
6445 : // barometric pressure, the function returns the dry bulb temperature.
6446 :
6447 : // METHODOLOGY EMPLOYED:
6448 : // Inverts PsyHFnTdbRhPb
6449 :
6450 : // REFERENCES:
6451 : // none
6452 :
6453 : // Using/Aliasing
6454 :
6455 : using General::SolveRoot;
6456 :
6457 : // Return value
6458 : Real64 T; // result=> humidity ratio
6459 :
6460 : // Locals
6461 : // FUNCTION ARGUMENT DEFINITIONS:
6462 :
6463 : // FUNCTION PARAMETER DEFINITIONS:
6464 76 : int constexpr MaxIte(500); // Maximum number of iterations
6465 76 : Real64 constexpr Acc(1.0); // Accuracy of result
6466 :
6467 : // INTERFACE BLOCK SPECIFICATIONS
6468 : // na
6469 :
6470 : // DERIVED TYPE DEFINITIONS
6471 : // na
6472 :
6473 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
6474 : int SolFla; // Flag of solver
6475 : Real64 T0; // lower bound for Tprov [C]
6476 : Real64 T1; // upper bound for Tprov [C]
6477 76 : Real64 Tprov(0.0); // provisional value of drybulb temperature [C]
6478 :
6479 76 : T0 = 1.0;
6480 76 : T1 = 50.0;
6481 :
6482 1752 : auto f = [&state, H, RH, PB](Real64 const Tprov) { return H - Psychrometrics::PsyHFnTdbRhPb(state, Tprov, RH, PB); };
6483 :
6484 76 : General::SolveRoot(state, Acc, MaxIte, SolFla, Tprov, f, T0, T1);
6485 : // if the numerical inversion failed, issue error messages.
6486 76 : if (SolFla == -1) {
6487 0 : ShowSevereError(state, "Calculation of drybulb temperature failed in TdbFnHRhPb(H,RH,PB)");
6488 0 : ShowContinueError(state, " Iteration limit exceeded");
6489 0 : ShowContinueError(state, format(" H=[{:.6R}], RH=[{:.4R}], PB=[{:.5R}].", H, RH, PB));
6490 76 : } else if (SolFla == -2) {
6491 0 : ShowSevereError(state, "Calculation of drybulb temperature failed in TdbFnHRhPb(H,RH,PB)");
6492 0 : ShowContinueError(state, " Bad starting values for Tdb");
6493 0 : ShowContinueError(state, format(" H=[{:.6R}], RH=[{:.4R}], PB=[{:.5R}].", H, RH, PB));
6494 : }
6495 76 : if (SolFla < 0) {
6496 0 : T = 0.0;
6497 : } else {
6498 76 : T = Tprov;
6499 : }
6500 :
6501 76 : return T;
6502 : }
6503 :
6504 8295 : Real64 EstimateHEXSurfaceArea(EnergyPlusData &state, int const CoilNum) // coil number, [-]
6505 : {
6506 :
6507 : // FUNCTION INFORMATION:
6508 : // AUTHOR Bereket A Nigusse, FSEC
6509 : // DATE WRITTEN July 2010
6510 : // MODIFIED
6511 : // RE-ENGINEERED
6512 :
6513 : // PURPOSE OF THIS FUNCTION:
6514 : // Splits the UA value of a simple coil:cooling:water heat exchanger model into
6515 : // "A" and U" values.
6516 :
6517 : // METHODOLOGY EMPLOYED:
6518 : // A typical design U overall heat transfer coefficient is used to split the "UA" into "A"
6519 : // and "U" values. Currently a constant U value calculated for a typical cooling coil is
6520 : // used. The assumptions used to calculate a typical U value are:
6521 : // (1) tube side water velocity of 2.0 [m/s]
6522 : // (2) inside to outside total surface area ratio (Ai/Ao) = 0.07 [-]
6523 : // (3) fins overall efficiency = 0.92 based on aluminum fin, 12 fins per inch, and
6524 : // fins area to total outside surafce area ratio of about 90%.
6525 : // (4) air side convection coefficient of 140.0 [W/m2C]. Assumes sensible convection
6526 : // of 58.0 [W/m2C] and 82.0 [W/m2C] sensible convection equivalent of the mass
6527 : // transfer coefficient converted using the approximate relation:
6528 : // hequivalent = hmasstransfer/CpAir.
6529 :
6530 : // REFERENCES:
6531 :
6532 : // USE STATEMENTS:
6533 :
6534 : // Return value
6535 :
6536 : // Locals
6537 : // SUBROUTINE ARGUMENT DEFINITIONS:
6538 :
6539 : // FUNCTION PARAMETER DEFINITIONS:
6540 8295 : constexpr Real64 OverallFinEfficiency(0.92); // Assumes aluminum fins, 12 fins per inch, fins
6541 : // area of about 90% of external surface area Ao.
6542 :
6543 8295 : constexpr Real64 AreaRatio(0.07); // Heat exchanger Inside to Outside surface area ratio
6544 : // design values range from (Ai/Ao) = 0.06 to 0.08
6545 :
6546 : // Constant value air side heat transfer coefficient is assumed. This coefficient has sensible
6547 : // (58.d0 [W/m2C]) and latent (82.d0 [W/m2C]) heat transfer coefficient components.
6548 8295 : constexpr Real64 hAirTubeOutside(58.0 + 82.0); // Air side heat transfer coefficient [W/m2C]
6549 :
6550 : // Tube side water convection heat transfer coefficient of the cooling coil is calculated for
6551 : // inside tube diameter of 0.0122m (~0.5 inch nominal diameter) and water velocity 2.0 m/s:
6552 : static Real64 const hWaterTubeInside(1429.0 * std::pow(2.0, 0.8) * std::pow(0.0122, -0.2)); // water (tube) side heat transfer coefficient [W/m2C]
6553 :
6554 : // Estimate the overall heat transfer coefficient, UOverallHeatTransferCoef in [W/(m2C)].
6555 : // Neglecting tube wall and fouling resistance, the overall U value can be estimated as:
6556 : // 1/UOverallHeatTransferCoef = 1/(hi*AreaRatio) + 1/(ho*OverallFinEfficiency)
6557 : static Real64 const UOverallHeatTransferCoef_inv(
6558 : 1.0 / (hWaterTubeInside * AreaRatio) +
6559 : 1.0 / (hAirTubeOutside * OverallFinEfficiency)); // Inverse of overall heat transfer coefficient for coil [W/m2C]
6560 :
6561 : // INTERFACE BLOCK SPECIFICATIONS
6562 : // na
6563 :
6564 : // DERIVED TYPE DEFINITIONS
6565 : // na
6566 :
6567 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
6568 :
6569 8295 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilTotal =
6570 8295 : 1.0 / (1.0 / state.dataWaterCoils->WaterCoil(CoilNum).UACoilExternal + 1.0 / state.dataWaterCoils->WaterCoil(CoilNum).UACoilInternal);
6571 :
6572 : // the heat exchanger surface area is calculated as follows:
6573 8295 : return state.dataWaterCoils->WaterCoil(CoilNum).UACoilTotal * UOverallHeatTransferCoef_inv; // Heat exchanger surface area [m2]
6574 : }
6575 :
6576 192 : int GetWaterCoilIndex(EnergyPlusData &state,
6577 : std::string_view CoilType, // must match coil types in this module
6578 : std::string const &CoilName, // must match coil names for the coil type
6579 : bool &ErrorsFound // set to true if problem
6580 : )
6581 : {
6582 :
6583 : // FUNCTION INFORMATION:
6584 : // AUTHOR B. Nigusse, FSEC
6585 : // DATE WRITTEN Feb 2012
6586 : // MODIFIED na
6587 : // RE-ENGINEERED na
6588 :
6589 : // PURPOSE OF THIS FUNCTION:
6590 : // This function looks up the index for the given coil and returns it. If incorrect coil
6591 : // type or name is given, ErrorsFound is returned as true and node number is returned
6592 : // as zero.
6593 :
6594 : // Return value
6595 : int IndexNum; // returned coil index if matched coil
6596 :
6597 : // Obtains and allocates WaterCoil related parameters from input file
6598 192 : if (state.dataWaterCoils->GetWaterCoilsInputFlag) {
6599 8 : GetWaterCoilInput(state);
6600 8 : state.dataWaterCoils->GetWaterCoilsInputFlag = false;
6601 : }
6602 :
6603 192 : IndexNum = 0;
6604 192 : if (CoilType == "COIL:HEATING:WATER") {
6605 98 : IndexNum = UtilityRoutines::FindItemInList(CoilName, state.dataWaterCoils->WaterCoil);
6606 94 : } else if (CoilType == "COIL:COOLING:WATER") {
6607 94 : IndexNum = UtilityRoutines::FindItemInList(CoilName, state.dataWaterCoils->WaterCoil);
6608 0 : } else if (CoilType == "COIL:COOLING:WATER:DETAILEDGEOMETRY") {
6609 0 : IndexNum = UtilityRoutines::FindItemInList(CoilName, state.dataWaterCoils->WaterCoil);
6610 : } else {
6611 0 : IndexNum = 0;
6612 : }
6613 :
6614 192 : if (IndexNum == 0) {
6615 0 : ShowSevereError(state, format("GetWaterCoilIndex: Could not find CoilType=\"{}\" with Name=\"{}\"", CoilType, CoilName));
6616 0 : ErrorsFound = true;
6617 : }
6618 :
6619 192 : return IndexNum;
6620 : }
6621 24 : int GetCompIndex(EnergyPlusData &state, CoilModel compType, std::string_view const coilName)
6622 : {
6623 : static constexpr std::array<std::string_view, (int)WaterCoils::CoilModel::Num> CoilModelNamesUC = {
6624 : "COIL:HEATING:WATER", "COIL:COOLING:WATER", "COIL:COOLING:WATER:DETAILED"};
6625 :
6626 24 : if (state.dataWaterCoils->GetWaterCoilsInputFlag) {
6627 5 : GetWaterCoilInput(state);
6628 5 : state.dataWaterCoils->GetWaterCoilsInputFlag = false;
6629 : }
6630 :
6631 24 : int index = UtilityRoutines::FindItemInList(coilName, state.dataWaterCoils->WaterCoil);
6632 :
6633 24 : if (index == 0) { // may not find coil name
6634 0 : ShowSevereError(state,
6635 0 : format("GetWaterCoilIndex: Could not find CoilType = \"{}\" with Name = \"{}\"", CoilModelNamesUC[(int)compType], coilName));
6636 : }
6637 24 : return index;
6638 : }
6639 :
6640 14 : Real64 GetWaterCoilCapacity(EnergyPlusData &state,
6641 : std::string const &CoilType, // must match coil types in this module
6642 : std::string const &CoilName, // must match coil names for the coil type
6643 : bool &ErrorsFound // set to true if problem
6644 : )
6645 : {
6646 :
6647 : // FUNCTION INFORMATION:
6648 : // AUTHOR R. Raustad, FSEC
6649 : // DATE WRITTEN Sep 2013
6650 : // MODIFIED na
6651 : // RE-ENGINEERED na
6652 :
6653 : // PURPOSE OF THIS FUNCTION:
6654 : // This function looks up the capacity for the given coil and returns it. If incorrect coil
6655 : // type or name is given, ErrorsFound is returned as true and capacity is returned
6656 : // as zero.
6657 :
6658 : // Return value
6659 : Real64 Capacity; // returned coil capacity if matched coil
6660 :
6661 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
6662 : int IndexNum; // index to water coil
6663 :
6664 : // Obtains and allocates WaterCoil related parameters from input file
6665 14 : if (state.dataWaterCoils->GetWaterCoilsInputFlag) {
6666 0 : GetWaterCoilInput(state);
6667 0 : state.dataWaterCoils->GetWaterCoilsInputFlag = false;
6668 : }
6669 :
6670 14 : Capacity = -1.0;
6671 :
6672 14 : if (CoilType == "COIL:HEATING:WATER") {
6673 9 : IndexNum = UtilityRoutines::FindItemInList(CoilName, state.dataWaterCoils->WaterCoil);
6674 9 : Capacity = state.dataWaterCoils->WaterCoil(IndexNum).DesWaterHeatingCoilRate;
6675 5 : } else if (CoilType == "COIL:COOLING:WATER") {
6676 5 : IndexNum = UtilityRoutines::FindItemInList(CoilName, state.dataWaterCoils->WaterCoil);
6677 5 : Capacity = state.dataWaterCoils->WaterCoil(IndexNum).DesWaterCoolingCoilRate;
6678 0 : } else if (CoilType == "COIL:COOLING:WATER:DETAILEDGEOMETRY") {
6679 0 : IndexNum = UtilityRoutines::FindItemInList(CoilName, state.dataWaterCoils->WaterCoil);
6680 0 : Capacity = state.dataWaterCoils->WaterCoil(IndexNum).DesWaterCoolingCoilRate;
6681 : } else {
6682 0 : IndexNum = 0;
6683 : }
6684 :
6685 14 : if (IndexNum == 0) {
6686 0 : ShowSevereError(state, "GetWaterCoilCapacity: Could not find CoilType=\"" + CoilType + "\" with Name=\"" + CoilName + "\"");
6687 0 : ErrorsFound = true;
6688 : }
6689 :
6690 14 : return Capacity;
6691 : }
6692 :
6693 0 : void UpdateWaterToAirCoilPlantConnection(EnergyPlusData &state,
6694 : DataPlant::PlantEquipmentType const CoilType,
6695 : std::string const &CoilName,
6696 : [[maybe_unused]] int const EquipFlowCtrl, // Flow control mode for the equipment
6697 : int const LoopNum, // Plant loop index for where called from
6698 : const DataPlant::LoopSideLocation LoopSide, // Plant loop side index for where called from
6699 : int &CompIndex, // Chiller number pointer
6700 : [[maybe_unused]] bool const FirstHVACIteration,
6701 : bool &InitLoopEquip // If not zero, calculate the max load for operating conditions
6702 : )
6703 : {
6704 :
6705 : // SUBROUTINE INFORMATION:
6706 : // AUTHOR B. Griffith
6707 : // DATE WRITTEN February 2010
6708 : // MODIFIED na
6709 : // RE-ENGINEERED na
6710 :
6711 : // PURPOSE OF THIS SUBROUTINE:
6712 : // update sim routine called from plant
6713 :
6714 : // Using/Aliasing
6715 : using DataPlant::PlantEquipTypeNames;
6716 :
6717 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
6718 :
6719 : int CoilNum;
6720 0 : bool DidAnythingChange(false); // set to true if conditions changed
6721 : int InletNodeNum;
6722 : int OutletNodeNum;
6723 :
6724 : // Find the correct water coil
6725 0 : if (CompIndex == 0) {
6726 0 : CoilNum = UtilityRoutines::FindItemInList(CoilName, state.dataWaterCoils->WaterCoil);
6727 0 : if (CoilNum == 0) {
6728 0 : ShowFatalError(state, "UpdateWaterToAirCoilPlantConnection: Specified Coil not one of Valid water coils=" + CoilName);
6729 : }
6730 0 : CompIndex = CoilNum;
6731 : } else {
6732 0 : CoilNum = CompIndex;
6733 0 : if (CoilNum > state.dataWaterCoils->NumWaterCoils || CoilNum < 1) {
6734 0 : ShowFatalError(state,
6735 0 : format("UpdateWaterToAirCoilPlantConnection: Invalid CompIndex passed={}, Number of Coils={}, Entered Coil name={}",
6736 : CoilNum,
6737 0 : state.dataWaterCoils->NumWaterCoils,
6738 0 : CoilName));
6739 : }
6740 0 : if (state.dataGlobal->KickOffSimulation) {
6741 0 : if (CoilName != state.dataWaterCoils->WaterCoil(CoilNum).Name) {
6742 0 : ShowFatalError(
6743 : state,
6744 0 : format("UpdateWaterToAirCoilPlantConnection: Invalid CompIndex passed={}, Coil name={}, stored Coil Name for that index={}",
6745 : CoilNum,
6746 : CoilName,
6747 0 : state.dataWaterCoils->WaterCoil(CoilNum).Name));
6748 : }
6749 0 : if (CoilType != state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilType) {
6750 0 : ShowFatalError(
6751 : state,
6752 0 : format("UpdateWaterToAirCoilPlantConnection: Invalid CompIndex passed={}, Coil name={}, stored Coil Name for that index={}",
6753 : CoilNum,
6754 : CoilName,
6755 0 : PlantEquipTypeNames[static_cast<int>(CoilType)]));
6756 : }
6757 : }
6758 : }
6759 :
6760 0 : if (InitLoopEquip) {
6761 0 : return;
6762 : }
6763 :
6764 0 : DidAnythingChange = false;
6765 :
6766 0 : InletNodeNum = state.dataWaterCoils->WaterCoil(CoilNum).WaterInletNodeNum;
6767 0 : OutletNodeNum = state.dataWaterCoils->WaterCoil(CoilNum).WaterOutletNodeNum;
6768 :
6769 0 : if (state.dataLoopNodes->Node(InletNodeNum).Temp != state.dataWaterCoils->WaterCoil(CoilNum).InletWaterTemp) DidAnythingChange = true;
6770 :
6771 0 : if (state.dataLoopNodes->Node(OutletNodeNum).Temp != state.dataWaterCoils->WaterCoil(CoilNum).OutletWaterTemp) DidAnythingChange = true;
6772 :
6773 0 : if (state.dataLoopNodes->Node(InletNodeNum).MassFlowRate != state.dataWaterCoils->WaterCoil(CoilNum).OutletWaterMassFlowRate) {
6774 0 : DidAnythingChange = true;
6775 0 : state.dataLoopNodes->Node(OutletNodeNum).MassFlowRate =
6776 0 : state.dataLoopNodes->Node(InletNodeNum).MassFlowRate; // make sure flows are consistent
6777 : }
6778 :
6779 0 : if (state.dataLoopNodes->Node(OutletNodeNum).MassFlowRate != state.dataWaterCoils->WaterCoil(CoilNum).OutletWaterMassFlowRate)
6780 0 : DidAnythingChange = true;
6781 :
6782 0 : if (DidAnythingChange) {
6783 : // set sim flag for this loop
6784 0 : state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSide).SimLoopSideNeeded = true;
6785 : // set sim flags for air side users of coils
6786 :
6787 0 : state.dataHVACGlobal->SimAirLoopsFlag = true;
6788 0 : state.dataHVACGlobal->SimZoneEquipmentFlag = true;
6789 : } else { // nothing changed so turn off sim flag
6790 0 : state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSide).SimLoopSideNeeded = false;
6791 : }
6792 : }
6793 :
6794 0 : int GetWaterCoilAvailScheduleIndex(EnergyPlusData &state,
6795 : std::string const &CoilType, // must match coil types in this module
6796 : std::string const &CoilName, // must match coil names for the coil type
6797 : bool &ErrorsFound // set to true if problem
6798 : )
6799 : {
6800 :
6801 : // FUNCTION INFORMATION:
6802 : // AUTHOR Chandan Sharma, FSEC
6803 : // DATE WRITTEN February 2013
6804 : // MODIFIED na
6805 : // RE-ENGINEERED na
6806 :
6807 : // PURPOSE OF THIS FUNCTION:
6808 : // This function looks up the given coil and returns the availability schedule index. If
6809 : // incorrect coil type or name is given, ErrorsFound is returned as true and index is returned
6810 : // as zero.
6811 :
6812 : // Return value
6813 : int AvailSchIndex; // returned availability schedule of matched coil
6814 :
6815 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
6816 : int WhichCoil;
6817 :
6818 : // Obtains and Allocates HeatingCoil related parameters from input file
6819 : // Obtains and Allocates DXCoils
6820 0 : if (state.dataWaterCoils->GetWaterCoilsInputFlag) {
6821 0 : GetWaterCoilInput(state);
6822 0 : state.dataWaterCoils->GetWaterCoilsInputFlag = false;
6823 : }
6824 :
6825 0 : WhichCoil = 0;
6826 0 : AvailSchIndex = 0;
6827 :
6828 0 : if (UtilityRoutines::SameString(CoilType, "Coil:Heating:Water") || UtilityRoutines::SameString(CoilType, "Coil:Cooling:Water") ||
6829 0 : UtilityRoutines::SameString(CoilType, "Coil:Cooling:Water:DetailedGeometry")) {
6830 0 : WhichCoil = UtilityRoutines::FindItem(CoilName, state.dataWaterCoils->WaterCoil);
6831 0 : if (WhichCoil != 0) {
6832 0 : AvailSchIndex = state.dataWaterCoils->WaterCoil(WhichCoil).SchedPtr;
6833 : }
6834 : } else {
6835 0 : WhichCoil = 0;
6836 : }
6837 :
6838 0 : if (WhichCoil == 0) {
6839 0 : ShowSevereError(state, "GetCoilAvailScheduleIndex: Could not find Coil, Type=\"" + CoilType + "\" Name=\"" + CoilName + "\"");
6840 0 : ErrorsFound = true;
6841 0 : AvailSchIndex = 0;
6842 : }
6843 :
6844 0 : return AvailSchIndex;
6845 : }
6846 :
6847 2 : void SetWaterCoilData(EnergyPlusData &state,
6848 : int const CoilNum, // Number of hot water heating Coil
6849 : bool &ErrorsFound, // Set to true if certain errors found
6850 : Optional_bool DesiccantRegenerationCoil, // Flag that this coil is used as regeneration air heating coil
6851 : Optional_int DesiccantDehumIndex, // Index for the desiccant dehum system where this caoil is used
6852 : Optional_bool heatRecoveryCoil) // true if water coil is connected to heat recovery loop
6853 : {
6854 :
6855 : // FUNCTION INFORMATION:
6856 : // AUTHOR Bereket Nigusse
6857 : // DATE WRITTEN February 2016
6858 : // MODIFIED na
6859 : // RE-ENGINEERED na
6860 :
6861 : // PURPOSE OF THIS FUNCTION:
6862 : // This function sets data to water Heating Coil using the coil index and arguments passed
6863 :
6864 : // Using/Aliasing
6865 :
6866 2 : if (state.dataWaterCoils->GetWaterCoilsInputFlag) {
6867 0 : GetWaterCoilInput(state);
6868 0 : state.dataWaterCoils->GetWaterCoilsInputFlag = false;
6869 : }
6870 :
6871 2 : if (CoilNum <= 0 || CoilNum > state.dataWaterCoils->NumWaterCoils) {
6872 0 : ShowSevereError(state,
6873 0 : format("SetHeatingCoilData: called with heating coil Number out of range={} should be >0 and <{}",
6874 : CoilNum,
6875 0 : state.dataWaterCoils->NumWaterCoils));
6876 0 : ErrorsFound = true;
6877 0 : return;
6878 : }
6879 :
6880 2 : if (present(DesiccantRegenerationCoil)) {
6881 0 : state.dataWaterCoils->WaterCoil(CoilNum).DesiccantRegenerationCoil = DesiccantRegenerationCoil;
6882 : }
6883 :
6884 2 : if (present(DesiccantDehumIndex)) {
6885 0 : state.dataWaterCoils->WaterCoil(CoilNum).DesiccantDehumNum = DesiccantDehumIndex;
6886 : }
6887 :
6888 2 : if (present(heatRecoveryCoil)) {
6889 2 : state.dataWaterCoils->WaterCoil(CoilNum).heatRecoveryCoil = heatRecoveryCoil;
6890 : }
6891 : }
6892 :
6893 0 : void EstimateCoilInletWaterTemp(EnergyPlusData &state,
6894 : int const CoilNum, // index to heating coil
6895 : int const FanOpMode, // fan operating mode
6896 : Real64 const PartLoadRatio, // part-load ratio of heating coil
6897 : Real64 const UAMax, // maximum UA-Value = design heating capacity
6898 : Real64 &DesCoilInletWaterTempUsed // estimated coil design inlet water temperature
6899 : )
6900 : {
6901 : // SUBROUTINE INFORMATION:
6902 :
6903 : // PURPOSE OF THIS SUBROUTINE:
6904 : // returns estimated coil inlet water temperature given UA value for assumed
6905 : // maximum effectiveness value for heating coil
6906 :
6907 : // METHODOLOGY EMPLOYED:
6908 : // applies energy balance around the water coil and estimates coil water inlet temperature
6909 : // assuming coil effectiveness of 0.8
6910 :
6911 : // REFERENCES:
6912 : // na
6913 :
6914 : // Using/Aliasing
6915 :
6916 : // Locals
6917 : // SUBROUTINE ARGUMENT DEFINITIONS:
6918 :
6919 : // SUBROUTINE PARAMETER DEFINITIONS:
6920 : static constexpr std::string_view RoutineName("EstimateCoilInletWaterTemp");
6921 0 : constexpr Real64 EffectivenessMaxAssumed(0.80);
6922 :
6923 : // INTERFACE BLOCK SPECIFICATIONS
6924 : // na
6925 :
6926 : // DERIVED TYPE DEFINITIONS
6927 : // na
6928 :
6929 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
6930 : Real64 WaterMassFlowRate;
6931 : Real64 AirMassFlow;
6932 : Real64 TempAirIn;
6933 : Real64 TempAirOut; // [C]
6934 : Real64 Win;
6935 : Real64 TempWaterIn;
6936 : Real64 UA;
6937 : Real64 CapacitanceAir;
6938 : Real64 CapacitanceWater;
6939 : Real64 CapacitanceMin;
6940 : Real64 CapacitanceMax;
6941 : Real64 NTU;
6942 : Real64 ETA;
6943 : Real64 A;
6944 : Real64 CapRatio;
6945 : Real64 E1;
6946 : Real64 E2;
6947 : Real64 Effec;
6948 : Real64 Cp;
6949 :
6950 0 : UA = UAMax;
6951 0 : DesCoilInletWaterTempUsed = DesCoilHWInletTempMin;
6952 0 : TempAirIn = state.dataWaterCoils->WaterCoil(CoilNum).InletAirTemp;
6953 0 : Win = state.dataWaterCoils->WaterCoil(CoilNum).InletAirHumRat;
6954 0 : TempWaterIn = state.dataWaterCoils->WaterCoil(CoilNum).InletWaterTemp;
6955 : // adjust mass flow rates for cycling fan cycling coil operation
6956 0 : if (FanOpMode == CycFanCycCoil) {
6957 0 : if (PartLoadRatio > 0.0) {
6958 0 : AirMassFlow = state.dataWaterCoils->WaterCoil(CoilNum).InletAirMassFlowRate / PartLoadRatio;
6959 0 : WaterMassFlowRate = min(state.dataWaterCoils->WaterCoil(CoilNum).InletWaterMassFlowRate / PartLoadRatio,
6960 0 : state.dataWaterCoils->WaterCoil(CoilNum).MaxWaterMassFlowRate);
6961 : } else {
6962 0 : AirMassFlow = 0.0;
6963 0 : WaterMassFlowRate = 0.0;
6964 0 : return;
6965 : }
6966 : } else {
6967 0 : AirMassFlow = state.dataWaterCoils->WaterCoil(CoilNum).InletAirMassFlowRate;
6968 0 : WaterMassFlowRate = state.dataWaterCoils->WaterCoil(CoilNum).InletWaterMassFlowRate;
6969 : }
6970 0 : if (WaterMassFlowRate > DataBranchAirLoopPlant::MassFlowTolerance) { // if the coil is operating
6971 0 : CapacitanceAir = PsyCpAirFnW(Win) * AirMassFlow;
6972 0 : Cp = GetSpecificHeatGlycol(state,
6973 0 : state.dataPlnt->PlantLoop(state.dataWaterCoils->WaterCoil(CoilNum).WaterPlantLoc.loopNum).FluidName,
6974 : TempWaterIn,
6975 0 : state.dataPlnt->PlantLoop(state.dataWaterCoils->WaterCoil(CoilNum).WaterPlantLoc.loopNum).FluidIndex,
6976 : RoutineName);
6977 0 : CapacitanceWater = Cp * WaterMassFlowRate;
6978 0 : CapacitanceMin = min(CapacitanceAir, CapacitanceWater);
6979 0 : CapacitanceMax = max(CapacitanceAir, CapacitanceWater);
6980 : } else {
6981 0 : CapacitanceAir = 0.0;
6982 0 : CapacitanceWater = 0.0;
6983 0 : return;
6984 : }
6985 : // calculate DesCoilInletWaterTempUsed
6986 0 : if (((CapacitanceAir > 0.0) && (CapacitanceWater > 0.0))) {
6987 :
6988 0 : if (UA <= 0.0) {
6989 0 : ShowWarningError(state, "UA is zero for COIL:Heating:Water " + state.dataWaterCoils->WaterCoil(CoilNum).Name);
6990 0 : return;
6991 : }
6992 0 : NTU = UA / CapacitanceMin;
6993 0 : ETA = std::pow(NTU, 0.22);
6994 0 : CapRatio = CapacitanceMin / CapacitanceMax;
6995 0 : A = CapRatio * NTU / ETA;
6996 :
6997 0 : if (A > 20.0) {
6998 0 : A = ETA * 1.0 / CapRatio;
6999 : } else {
7000 0 : E1 = std::exp(-A);
7001 0 : A = ETA * (1.0 - E1) / CapRatio;
7002 : }
7003 :
7004 0 : if (A > 20.0) {
7005 0 : Effec = 1.0;
7006 : } else {
7007 0 : E2 = std::exp(-A);
7008 0 : Effec = 1.0 - E2;
7009 : }
7010 0 : TempAirOut = TempAirIn + Effec * CapacitanceMin * (TempWaterIn - TempAirIn) / CapacitanceAir;
7011 : // this formulation assumes coil effectiveness of 0.80 to increase the estimated coil water inlet temperatures
7012 0 : DesCoilInletWaterTempUsed = CapacitanceAir * (TempAirOut - TempAirIn) / (CapacitanceMin * EffectivenessMaxAssumed) + TempAirIn;
7013 : // water coil should not be sized at coil water inlet temperature lower than 46.0C (for convergence problem in Regulafalsi)
7014 0 : DesCoilInletWaterTempUsed = max(DesCoilInletWaterTempUsed, DesCoilHWInletTempMin);
7015 : }
7016 : }
7017 :
7018 : // End of Coil Utility subroutines
7019 : // *****************************************************************************
7020 :
7021 2313 : } // namespace EnergyPlus::WaterCoils
|